Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
327b80d
feat: integrate cs-agent for refactoring
vemv Aug 31, 2026
bd6f48e
refactor: rename ACE to CodeScene Refactoring Agent
vemv Sep 1, 2026
430fff1
fix: handle open-settings message in ACE acknowledgement panel
vemv Sep 1, 2026
cb4d860
fix: spawn refactoring agent with git repository root as cwd
vemv Sep 1, 2026
d66ae43
fix: add Amazon Bedrock provider config for refactoring agent
vemv Sep 2, 2026
2f304f8
fix: handle whole_file change type in agent output
vemv Sep 2, 2026
ef0c4d2
chore: remove debug log statements
vemv Sep 2, 2026
d300b63
feat: forward agent stdout to CWF progress widget
vemv Sep 3, 2026
c6ff0c2
chore: gitignore bin/cs-agent
vemv Sep 3, 2026
ad85010
chore: add updatecwf target for local CWF development
vemv Sep 3, 2026
82eda8b
chore: rename refactoring-agent directory to cs-agent
vemv Sep 3, 2026
8d195b4
chore: fix local builds with local CWF
vemv Sep 3, 2026
9549438
refactor: reduce complexity in AgentRefactoringService
vemv Sep 3, 2026
3fe8b66
fix: clean up test-git-repo-integration dir reliably
vemv Sep 3, 2026
afdfa5a
test: update agent output fixtures to use enum values
vemv Sep 3, 2026
de24fe3
chore: expand CLAUDE.md
vemv Sep 3, 2026
1eb2495
feat: use temp directory for agent JSON I/O files
vemv Sep 4, 2026
a996c35
test: verify agent reads input from io_json_dir
vemv Sep 4, 2026
1c178d9
feat: add settings UI for agent model selection
vemv Sep 4, 2026
19b1903
chore: expand CLAUDE.md
vemv Sep 4, 2026
b98a9af
feat: add providerOptions setting for agent configuration
vemv Sep 4, 2026
016b6bd
feat: expand Anthropic models
vemv Sep 8, 2026
53f7b26
feat: add Test connectivity button in settings
vemv Sep 8, 2026
e4850f4
fix: pass workspace folder as cwd in connectivity test
vemv Sep 8, 2026
9f54dd0
chore: expand CLAUDE.md
vemv Sep 8, 2026
b04faa4
fix: prevent connectivity test from hanging indefinitely
vemv Sep 8, 2026
1f76830
feat: add OpenAI, Anthropic, and Google provider auth options
vemv Sep 8, 2026
00e40f1
feat: add tracking config to cs-agent environment
vemv Sep 8, 2026
66e410e
refactor: separate provider credentials from bedrock config
vemv Sep 8, 2026
9c03255
refactor: simplify conditional in buildProviderCredentials
vemv Sep 8, 2026
0d8e5d2
fix: infer agent model from provider credentials
vemv Sep 8, 2026
a1729a2
fix: infer model from provider keys even with default agentModel
vemv Sep 8, 2026
83bc122
fix: treat content-identical refactorings as failures
vemv Sep 8, 2026
88f0e00
chore: build CWF from local ../cs-webview when available (#359)
martinsafsten-codescene Sep 29, 2026
b6979dd
Merge branch 'main' into agentic-ace-v2
martinsafsten-codescene Oct 29, 2026
978e728
feat(refactoring): gate ACE on sign-in, drop preflight, fetch IDE token
martinsafsten-codescene Oct 29, 2026
8f7852a
feat(auth): fetch the agent token over cs-ide/auth-token JSON-RPC
martinsafsten-codescene Oct 29, 2026
c7b8882
fix(refactoring): apply agent replacements despite line-ending and tr…
martinsafsten-codescene Oct 29, 2026
58a1e0e
feat(refactoring): ask to save unsaved changes before running the agent
martinsafsten-codescene Oct 29, 2026
7764129
refactor(devtools-api): drop the unused cs-ide/refactor request
martinsafsten-codescene Oct 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ test-git-repo-diff-utils/
test-cs-diagnostics/
coverage/
.cs-prod-build
bin/cs-agent
bench-results/
3 changes: 3 additions & 0 deletions .vscodeignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ cs-*
!cs-cwf/
!cs-cwf/**

## Include the agent binary
!bin/

## Misc dotfiles
.mocharc.json
Makefile
Expand Down
8 changes: 8 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,12 @@ Validate your work using `make lint`. Satifying all linter faults is mandatory -

If you find an issue at any stage, you must fix it immediately, regardless of whether you think it's pre-existing.

This project is a VS Code extension. You might need to study the VS Code accordingly. It might be cloned at `../vscode`.
This project uses CWF for rendering views, and can typically be found at `../cs-webview`.
This project uses cs-agent for performing refactorings, and can typically be found at `../cs-agent`.
This project uses the CodeScene CLI for performing various code analysis tasks, and can typically be found at `../codescene/cli`.
This project used in the past ACE where cs-agent is now used, and can typically be found at `../automated-refactoring`.

When querying external projects, please use subagents.

Commit messages follow Conventional Commits. Keep the subject line (`type: imperative summary`) to at most 100 characters and do not end it with a period. Put the why in the body after a blank line, wrapped near 80 columns. The commit-msg hook rejects messages that fail commitlint. `make lint` checks every commit from `main` to `HEAD`.
30 changes: 29 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: build package tsc clean lint watch test pretest test-release updatecwf benchmark benchmark-isolated
.PHONY: build package package-darwin-arm64 package-darwin-x64 package-linux-arm64 package-linux-x64 package-win32-x64 package-all tsc clean lint watch test pretest test-release updatecwf benchmark benchmark-isolated

.DEFAULT_GOAL := build

Expand All @@ -14,6 +14,34 @@ package: lint pretest
npx @vscode/vsce@4.0.0 package; \
git checkout .vscodeignore; \

package-darwin-arm64: lint pretest
npm i
cd ~/cs-agent/agent && $(MAKE) build-all
mkdir -p ./bin
cp ~/cs-agent/agent/target/aarch64-apple-darwin/release/cs-agent ./bin/cs-agent
node ./scripts/package-platform.js darwin arm64

package-darwin-x64: lint pretest
npm i
cd ~/cs-agent/agent && $(MAKE) build-all
mkdir -p ./bin
cp ~/cs-agent/agent/target/x86_64-apple-darwin/release/cs-agent ./bin/cs-agent
node ./scripts/package-platform.js darwin x64

package-linux-arm64: lint pretest
npm i
node ./scripts/package-platform.js linux arm64

package-linux-x64: lint pretest
npm i
node ./scripts/package-platform.js linux x64

package-win32-x64: lint pretest
npm i
node ./scripts/package-platform.js win32 x64

package-all: package-darwin-arm64 package-darwin-x64 package-linux-arm64 package-linux-x64 package-win32-x64

tsc:
npx tsc --noEmit

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ Location: `Code Health Monitor` > `Extension Settings`
| **Enable Review Code Lenses** | Boolean | true | Enables/Disables showing Code Health Score and Code Smells in the active documents |
| **Enable Auto Refactor** | Boolean | false | Enables/Disables ACE, CodeScenes automatic refactoring tool |
| **Server URL** | String | - | CodeScene server for browser sign-in. Empty uses `CS_ONPREM_URL`, then CodeScene Cloud. Used when Experimental: Sign In is on. |
| **Auth Token** | String | - | Personal access token — fallback for WSL, remote and headless environments. Browser sign-in is recommended. Also used for Automatic Refactoring in ACE. |
| **Auth Token** | String | - | Personal access token — an alternative to signing in, for WSL, remote and headless environments. Also used for refactoring. Browser sign-in is recommended. |
| **Experimental: Sign In** | Boolean | false | Sign in to CodeScene in the browser (experimental). Requires a CodeScene IDE server with sign-in support. |
| **Enable Telemetry** | Boolean | true | Enable/Disable collecting anonymized telemetry for tracking usage and feature engagement. |

Expand Down
87 changes: 85 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@
"command": "codescene.copyDeviceId",
"title": "CodeScene: copy Device ID"
},
{
"command": "codescene.testConnectivity",
"title": "CodeScene: test provider connectivity"
},
{
"command": "codescene.browserSignIn",
"title": "CodeScene: Sign in"
Expand Down Expand Up @@ -140,6 +144,10 @@
"command": "codescene.startAutomaticAnalysis",
"when": "!config.codescene.enableAutomaticAnalysis"
},
{
"command": "codescene.testConnectivity",
"when": "codescene.aceUsable"
},
{
"command": "codescene.browserSignIn",
"when": "codescene.signInActive"
Expand Down Expand Up @@ -172,9 +180,84 @@
"codescene.enableAutoRefactor": {
"type": "boolean",
"default": true,
"description": "Enable CodeScene ACE",
"description": "Enable CodeScene Refactoring Agent",
"order": 15
},
"codescene.agentModel": {
"type": "string",
"default": "amazon-bedrock/eu.anthropic.claude-sonnet-4-6",
"enum": [
"amazon-bedrock/eu.anthropic.claude-sonnet-4-6",
"amazon-bedrock/eu.anthropic.claude-opus-5",
"amazon-bedrock/eu.anthropic.claude-opus-4-8",
"amazon-bedrock/eu.anthropic.claude-sonnet-4-5-20250929-v1:0",
"amazon-bedrock/eu.anthropic.claude-haiku-4-5-20251001-v1:0",
"amazon-bedrock/us.anthropic.claude-opus-5",
"amazon-bedrock/us.anthropic.claude-sonnet-4-6",
"anthropic/claude-sonnet-4-0",
"anthropic/claude-opus-4",
"anthropic/claude-haiku-3-5-sonnet",
"openai/gpt-4o",
"openai/gpt-4-turbo",
"openai/o3",
"google/gemini-2.5-pro",
"google/gemini-2.5-flash"
],
"enumDescriptions": [
"Claude Sonnet 4.6 via Amazon Bedrock (EU)",
"Claude Opus 5 via Amazon Bedrock (EU) - Most advanced",
"Claude Opus 4.8 via Amazon Bedrock (EU) - Optimized for coding",
"Claude Sonnet 4.5 via Amazon Bedrock (EU) - Optimized for agents",
"Claude Haiku 4.5 via Amazon Bedrock (EU) - Fast and lightweight",
"Claude Opus 5 via Amazon Bedrock (US) - Most advanced",
"Claude Sonnet 4.6 via Amazon Bedrock (US)",
"Claude Sonnet 4.0 via Anthropic API",
"Claude Opus 4 via Anthropic API",
"Claude Haiku 3.5 via Anthropic API - Fast and lightweight",
"GPT-4o via OpenAI API",
"GPT-4 Turbo via OpenAI API",
"o3 via OpenAI API - Advanced reasoning",
"Gemini 2.5 Pro via Google API",
"Gemini 2.5 Flash via Google API - Fast and efficient"
],
"description": "Model to use for the Refactoring Agent.",
"order": 16
},
"codescene.agentModelOverride": {
"type": "string",
"default": "",
"description": "Custom model identifier. If set, overrides the dropdown selection above.",
"order": 17
},
"codescene.providerOptions": {
"type": "object",
"properties": {
"amazon-bedrock:profile": {
"type": "string",
"description": "AWS profile name for Amazon Bedrock"
},
"amazon-bedrock:region": {
"type": "string",
"description": "AWS region for Amazon Bedrock"
},
"anthropic:api-key": {
"type": "string",
"description": "API key for Anthropic"
},
"openai:api-key": {
"type": "string",
"description": "API key for OpenAI"
},
"google:api-key": {
"type": "string",
"description": "API key for Google (Gemini)"
}
},
"additionalProperties": false,
"default": {},
"markdownDescription": "Provider-specific options for the Refactoring Agent. Use this to authenticate into your preferred model.\n\n**[Test connectivity](command:codescene.testConnectivity)**",
"order": 18
},
"codescene.serverUrl": {
"type": "string",
"default": "",
Expand All @@ -184,7 +267,7 @@
"codescene.authToken": {
"type": "string",
"default": "",
"description": "Personal access token — fallback for WSL, remote and headless environments. Browser sign-in is recommended.",
"description": "Personal access token — an alternative to signing in, for WSL, remote and headless environments. Also used for refactoring. Browser sign-in is recommended.",
"order": 19.5
},
"codescene.experimental.signIn": {
Expand Down
2 changes: 1 addition & 1 deletion scripts/cli-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* - TypeScript source files (via artifact-info.ts) that import from this file
*/

const requiredDevtoolsVersion = 'eff2f1fd6e7d928b0abd2f59f2243c63cefdf885';
const requiredDevtoolsVersion = '4a1fe05787f040c67f8a9da547108c87082e6ec5';

const nativeOsNames = { darwin: 'macos', linux: 'linux', win32: 'windows' };
const nativeArchNames = { x64: 'amd64', arm64: 'aarch64' };
Expand Down
4 changes: 2 additions & 2 deletions src/auth/ace-credential.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { MissingAuthTokenError } from '../missing-auth-token-error';

export interface AceAuthState {
active: boolean;
status: Pick<AuthStatus, 'ace-credential'> | null;
status: Pick<AuthStatus, 'state'> | null;
}

function nonBlank(value: string | undefined): string | undefined {
Expand All @@ -16,7 +16,7 @@ export function resolveAceToken(settingToken: string | undefined, legacyToken: s
}

export function isAceAvailable(token: string | undefined, auth: AceAuthState): boolean {
return token !== undefined || (auth.active && auth.status?.['ace-credential'] === true);
return token !== undefined || (auth.active && auth.status?.state === 'signed-in');
}

export function refactorToken(token: string | undefined, auth: AceAuthState): string | undefined {
Expand Down
9 changes: 9 additions & 0 deletions src/auth/auth-token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export interface AuthTokenResponse {
'credential-source': 'env-token' | 'setting-token' | 'oauth';
'access-token': string;
}

export function tokenFromResponse(response: Partial<AuthTokenResponse> | null | undefined): string | undefined {
const token = response?.['access-token']?.trim();
return token ? token : undefined;
}
1 change: 1 addition & 0 deletions src/centralized-webview-framework/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export interface AceContextViewProps extends AuthField {
error?: string;
isStale: boolean;
loading: boolean;
progressMessage?: string;
};
}

Expand Down
9 changes: 7 additions & 2 deletions src/code-health-monitor/codelens.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import vscode, { Uri } from 'vscode';
import { ACE_ENABLED } from '../build-flags';
import { onDidChangeConfiguration, reviewCodeLensesEnabled } from '../configuration';
import { aceUsable } from '../devtools-api';
import { issueToDocsParams } from '../documentation/commands';
import { reviewDocumentSelector } from '../language-support';
import { DeltaFunctionInfo } from './delta-function-info';
Expand All @@ -18,6 +19,10 @@ export function register(context: vscode.ExtensionContext) {
);
}

function canOfferRefactoring(functionInfo: DeltaFunctionInfo): boolean {
return ACE_ENABLED && aceUsable() && functionInfo.isRefactoringSupported;
}

export class CodeHealthMonitorCodeLens implements vscode.CodeLensProvider<vscode.CodeLens> {
private changeCodeLensesEmitter = new vscode.EventEmitter<void>();
onDidChangeCodeLenses = this.changeCodeLensesEmitter.event;
Expand Down Expand Up @@ -55,7 +60,7 @@ export class CodeHealthMonitorCodeLens implements vscode.CodeLensProvider<vscode
const functionStartLine = functionInfo.range.start.with({ character: 0 });

const requestAceLens = new vscode.CodeLens(new vscode.Range(functionStartLine, functionStartLine), {
title: '$(sparkle) CodeScene ACE',
title: '$(sparkle) CodeScene Agent',
command: 'codescene.requestAndPresentRefactoring',
arguments: [functionInfo.parent.document, 'codelens (code-health-monitor)', functionInfo.fnToRefactor],
});
Expand All @@ -65,7 +70,7 @@ export class CodeHealthMonitorCodeLens implements vscode.CodeLensProvider<vscode
arguments: [functionInfo.parent.document.uri],
});

if (ACE_ENABLED && functionInfo.fnToRefactor) {
if (canOfferRefactoring(functionInfo)) {
codeLenses.push(requestAceLens, dismissAceLens);
}
let order = 1;
Expand Down
2 changes: 1 addition & 1 deletion src/code-health-monitor/home/cwf-message-handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ function handleOpenDocs(homeView: HomeView, payload: OpenDocsMessage['payload'])
/**
* Open settings in editor
*/
function handleOpenSettings() {
export function handleOpenSettings() {
Telemetry.logUsage('control-center/open-settings');
vscode.commands.executeCommand('workbench.action.openWorkspaceSettings', getExtensionSettingsFilter()).then(
() => {},
Expand Down
3 changes: 1 addition & 2 deletions src/code-health-monitor/home/home-view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,8 @@ export class HomeView implements WebviewViewProvider, Disposable {

// Detect changes to the delta result, updates the list and lastly converts the data to CWF webview format
private updateFileDeltaData(event: DeltaAnalysisEvent) {
const { document, result, updateMonitor, enrichment } = event;
const { document, result, updateMonitor } = event;
if (!updateMonitor) return;
if (enrichment && !this.fileIssueMap.has(document.uri.fsPath)) return;

const evtData = (fileWithIssues: FileWithIssues) => {
const { nIssues, scoreChange } = fileWithIssues;
Expand Down
4 changes: 3 additions & 1 deletion src/codescene-tab/webview/ace/ace-data-mapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ interface CwfAceData {
isStale: boolean;
error?: string;
loading: boolean;
progressMessage?: string;
}

export function getAceData(data: CwfAceData): AceContextViewProps {
const { request, result, isStale, error, loading } = data;
const { request, result, isStale, error, loading, progressMessage } = data;

return {
view: 'ace',
Expand All @@ -40,6 +41,7 @@ export function getAceData(data: CwfAceData): AceContextViewProps {
isStale,
loading,
error,
progressMessage,
},
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ export function getAutoRefactorConfig(): AutoRefactorConfig {
return { disabled: true, activated: false, visible: false };
}

const hasToken = aceAvailable();
const authenticated = aceAvailable();
const acknowledged = CsExtensionState.acknowledgedAceUsage === true;
const activated = !(!acknowledged && hasToken);
const activated = !(!acknowledged && authenticated);

return {
disabled: !hasToken,
disabled: !authenticated,
activated,
visible: CsExtensionState.stateProperties.features.ace.state === 'enabled',
visible: authenticated && CsExtensionState.stateProperties.features.ace.state === 'enabled',
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { highlightCode } from '../../../../refactoring/utils';
import Telemetry from '../../../../telemetry';
import { reportError, showDocAtPosition } from '../../../../utils';
import { commonResourceRoots } from '../../../../webview-utils';
import { handleOpenSettings } from '../../../../code-health-monitor/home/cwf-message-handlers';
import { CsExtensionState } from '../../../../cs-extension-state';
import { getAceAcknowledgeData } from './ace-acknowledgement-mapper';

Expand Down Expand Up @@ -37,7 +38,7 @@ export class CodeSceneCWFAceAcknowledgementTabPanel implements Disposable {
constructor() {
this.webViewPanel = vscode.window.createWebviewPanel(
CodeSceneCWFAceAcknowledgementTabPanel.viewType,
'CodeScene ACE - AI-Powered Refactoring',
'CodeScene Refactoring Agent - AI-Powered Refactoring',
{ viewColumn: ViewColumn.Beside, preserveFocus: true },
{
enableScripts: true,
Expand Down Expand Up @@ -71,7 +72,7 @@ export class CodeSceneCWFAceAcknowledgementTabPanel implements Disposable {
if (!this.state) return;
await this.handleMessage(this.state.request, message);
} catch (e) {
reportError({ context: 'An error occurred in the CodeScene ACE Acknowledgement panel', e });
reportError({ context: 'An error occurred in the CodeScene Agent Acknowledgement panel', e });
}
}

Expand All @@ -82,6 +83,7 @@ export class CodeSceneCWFAceAcknowledgementTabPanel implements Disposable {
await showDocAtPosition(request.document, request.fnToRefactor.vscodeRange.start);
void highlightCode(request, false);
},
'open-settings': handleOpenSettings,
acknowledged: async () => {
const document = this.state?.request.document;
const fnToRefactor = this.state?.request.fnToRefactor;
Expand Down
Loading
Loading