diff --git a/src/agent-cli-provider/adapters/opencode.ts b/src/agent-cli-provider/adapters/opencode.ts index 804bafd0..ffc5e35f 100644 --- a/src/agent-cli-provider/adapters/opencode.ts +++ b/src/agent-cli-provider/adapters/opencode.ts @@ -85,6 +85,7 @@ function detectCliFeatures(helpText?: string | null): OpencodeCliFeatures { supportsModel: unknown ? true : /--model\b/.test(help), supportsVariant: unknown ? true : /--variant\b/.test(help), supportsCwd: unknown ? false : /--cwd\b/.test(help), + supportsDir: unknown ? false : /--dir\b/.test(help), supportsAutoApprove: false, unknown, }; @@ -109,6 +110,8 @@ function addOpencodeOptionalArgs(args: string[], options: BuildProviderCommandOp if (options.cwd && features.supportsCwd) { args.push('--cwd', options.cwd); + } else if (options.cwd && features.supportsDir) { + args.push('--dir', options.cwd); } } diff --git a/src/agent-cli-provider/types.ts b/src/agent-cli-provider/types.ts index ef2ca433..2f08eaf2 100644 --- a/src/agent-cli-provider/types.ts +++ b/src/agent-cli-provider/types.ts @@ -77,6 +77,7 @@ export interface OpencodeCliFeatures extends BaseCliFeatures { readonly supportsModel: boolean; readonly supportsVariant: boolean; readonly supportsCwd: boolean; + readonly supportsDir: boolean; readonly supportsAutoApprove: false; } @@ -97,6 +98,7 @@ export interface CliFeatureOverrides { readonly supportsJson?: boolean; readonly supportsOutputSchema?: boolean; readonly supportsCwd?: boolean; + readonly supportsDir?: boolean; readonly supportsConfigOverride?: boolean; readonly supportsSkipGitRepoCheck?: boolean; readonly supportsVariant?: boolean; diff --git a/tests/provider-cli-builder.test.js b/tests/provider-cli-builder.test.js index b01ed216..4c02c174 100644 --- a/tests/provider-cli-builder.test.js +++ b/tests/provider-cli-builder.test.js @@ -226,6 +226,83 @@ describe('Opencode provider helper builder', function () { assert.ok(result.args.includes('--variant')); assert.ok(result.args.includes('high')); }); + + describe('worktree isolation via --dir flag', function () { + it('passes --dir when supportsDir is true', function () { + const result = buildCommand('opencode', 'test prompt', { + cwd: '/worktrees/spinning-cosmos-71', + cliFeatures: { supportsDir: true, supportsCwd: false }, + }); + + assert.ok(result.args.includes('--dir'), 'expected --dir flag in args'); + assert.ok( + result.args.includes('/worktrees/spinning-cosmos-71'), + 'expected worktree path in args' + ); + assert.ok(!result.args.includes('--cwd'), '--cwd must not be used when supportsDir is true'); + }); + + it('falls back to --cwd when supportsCwd is true and supportsDir is false', function () { + const result = buildCommand('opencode', 'test prompt', { + cwd: '/worktrees/spinning-cosmos-71', + cliFeatures: { supportsDir: false, supportsCwd: true }, + }); + + assert.ok(result.args.includes('--cwd'), 'expected --cwd flag in args'); + assert.ok(!result.args.includes('--dir'), '--dir must not be used when supportsDir is false'); + }); + + it('sets commandSpec.cwd even when neither --dir nor --cwd flag is supported', function () { + const result = buildCommand('opencode', 'test prompt', { + cwd: '/worktrees/spinning-cosmos-71', + cliFeatures: { supportsDir: false, supportsCwd: false }, + }); + + assert.strictEqual( + result.cwd, + '/worktrees/spinning-cosmos-71', + 'commandSpec.cwd must be set so the process spawns in the worktree' + ); + assert.ok(!result.args.includes('--dir')); + assert.ok(!result.args.includes('--cwd')); + }); + + it('detects supportsDir from help text containing --dir', function () { + const { opencodeAdapter } = require('../lib/agent-cli-provider/adapters/opencode'); + const features = opencodeAdapter.detectCliFeatures( + 'Usage: opencode run [options]\n --dir Working directory\n --model Model to use\n' + ); + + assert.strictEqual( + features.supportsDir, + true, + 'supportsDir must be true when --dir appears in help text' + ); + assert.strictEqual( + features.supportsCwd, + false, + 'supportsCwd must be false when --cwd is absent from help text' + ); + }); + + it('detects supportsDir as false from help text without --dir', function () { + const { opencodeAdapter } = require('../lib/agent-cli-provider/adapters/opencode'); + const features = opencodeAdapter.detectCliFeatures( + 'Usage: opencode run [options]\n --cwd Working directory\n' + ); + + assert.strictEqual( + features.supportsDir, + false, + 'supportsDir must be false when --dir is absent from help text' + ); + assert.strictEqual( + features.supportsCwd, + true, + 'supportsCwd must be true when --cwd appears in help text' + ); + }); + }); }); describe('Claude provider helper builder', function () {