fix(plugin-kimicode): plumb workspacePath into AgentLaunchConfig
The kimicode plugin's --work-dir was passing projectConfig.path, which breaks worktree-mode workspaces. In worktree mode, projectConfig.path is the original repo root while session.workspacePath is the per-session checkout — they differ. Either kimi would write to the project root (breaking worktree isolation) or md5(projectConfig.path) would diverge from md5(session.workspacePath), so getActivityState/getSessionInfo would never find this session's bucket. Fix: - Add optional `workspacePath` field to AgentLaunchConfig. - Plumb it through all 3 launch call sites in session-manager.ts. - kimicode getLaunchCommand uses config.workspacePath, falling back to config.projectConfig.path when undefined. - Tests for the divergent-paths case. Public-interface change: AgentLaunchConfig grows one optional field. Invariants preserved: - Agent.getLaunchCommand signature unchanged — still takes one AgentLaunchConfig. - Existing plugins (claude-code, aider, codex, opencode) compile and run unchanged; the new field is optional and they ignore it. - Clone-mode workspaces (where workspacePath === projectConfig.path) produce the same launch command as before. - Fallback to projectConfig.path keeps callers that don't pass the new field working — no flag day required.
This commit is contained in:
parent
bc6f1cf70d
commit
9fcc1d9ed5
|
|
@ -1290,6 +1290,7 @@ export function createSessionManager(deps: SessionManagerDeps): OpenCodeSessionM
|
|||
...(reusedOpenCodeSessionId ? { opencodeSessionId: reusedOpenCodeSessionId } : {}),
|
||||
},
|
||||
},
|
||||
workspacePath,
|
||||
issueId: spawnConfig.issueId,
|
||||
prompt: composedPrompt,
|
||||
permissions: selection.permissions,
|
||||
|
|
@ -1641,6 +1642,7 @@ export function createSessionManager(deps: SessionManagerDeps): OpenCodeSessionM
|
|||
...(reusableOpenCodeSessionId ? { opencodeSessionId: reusableOpenCodeSessionId } : {}),
|
||||
},
|
||||
},
|
||||
workspacePath,
|
||||
permissions: "permissionless" as const,
|
||||
model: selection.model,
|
||||
systemPromptFile,
|
||||
|
|
@ -2764,6 +2766,7 @@ export function createSessionManager(deps: SessionManagerDeps): OpenCodeSessionM
|
|||
const agentLaunchConfig = {
|
||||
sessionId,
|
||||
projectConfig: projectConfigForLaunch,
|
||||
workspacePath,
|
||||
issueId: session.issueId ?? undefined,
|
||||
permissions: selection.role === "orchestrator" ? "permissionless" : selection.permissions,
|
||||
model: selection.model,
|
||||
|
|
|
|||
|
|
@ -541,6 +541,15 @@ export interface Agent {
|
|||
export interface AgentLaunchConfig {
|
||||
sessionId: SessionId;
|
||||
projectConfig: ProjectConfig;
|
||||
/**
|
||||
* Per-session workspace path. Differs from `projectConfig.path` when the
|
||||
* workspace plugin (e.g. worktree mode) creates an isolated checkout per
|
||||
* session. Plugins that need the agent's actual cwd — for cwd-derived
|
||||
* lookups, --work-dir flags, file-based discovery — must use this when
|
||||
* present. Falls back to `projectConfig.path` when undefined (clone-mode
|
||||
* workspaces, or plugins not yet plumbing it through).
|
||||
*/
|
||||
workspacePath?: string;
|
||||
issueId?: string;
|
||||
prompt?: string;
|
||||
permissions?: AgentPermissionInput;
|
||||
|
|
|
|||
|
|
@ -309,6 +309,25 @@ describe("getLaunchCommand", () => {
|
|||
"kimi --work-dir '/workspace/repo' --yolo --model 'kimi-k2' --agent 'default' --agent-file '/tmp/sp.md' --prompt 'Go'",
|
||||
);
|
||||
});
|
||||
|
||||
// Worktree-mode parity: when AO runs in worktree workspace mode,
|
||||
// workspacePath (per-session checkout) differs from projectConfig.path
|
||||
// (the original repo root). --work-dir must take the workspacePath so
|
||||
// kimi's md5(cwd) bucket matches the one session-discovery scans.
|
||||
it("--work-dir prefers workspacePath over projectConfig.path", () => {
|
||||
const cmd = agent.getLaunchCommand(
|
||||
makeLaunchConfig({
|
||||
workspacePath: "/worktrees/sess-1",
|
||||
}),
|
||||
);
|
||||
expect(cmd).toContain("--work-dir '/worktrees/sess-1'");
|
||||
expect(cmd).not.toContain("/workspace/repo");
|
||||
});
|
||||
|
||||
it("--work-dir falls back to projectConfig.path when workspacePath is undefined", () => {
|
||||
const cmd = agent.getLaunchCommand(makeLaunchConfig({ workspacePath: undefined }));
|
||||
expect(cmd).toContain("--work-dir '/workspace/repo'");
|
||||
});
|
||||
});
|
||||
|
||||
// =============================================================================
|
||||
|
|
|
|||
|
|
@ -500,10 +500,19 @@ function createKimicodeAgent(): Agent {
|
|||
const parts: string[] = ["kimi"];
|
||||
|
||||
// Explicit --work-dir prevents shell-rc / tmux-hook cwd drift from
|
||||
// making our md5(cwd) hash diverge from kimi's. projectConfig.path
|
||||
// is the project root — the canonical workspace directory.
|
||||
if (config.projectConfig.path) {
|
||||
parts.push("--work-dir", shellEscape(config.projectConfig.path));
|
||||
// making our md5(cwd) hash diverge from kimi's.
|
||||
//
|
||||
// Prefer config.workspacePath (per-session worktree) over
|
||||
// projectConfig.path (the original repo root). When the workspace
|
||||
// plugin is "worktree", these differ — passing projectConfig.path
|
||||
// would either (a) make kimi write to the project root, breaking
|
||||
// worktree isolation, or (b) cause md5(cwd) to diverge from
|
||||
// session.workspacePath, so getActivityState/getSessionInfo never
|
||||
// find this session's bucket. Falls back to projectConfig.path
|
||||
// for clone-mode workspaces or older callers that don't plumb it.
|
||||
const workDir = config.workspacePath ?? config.projectConfig.path;
|
||||
if (workDir) {
|
||||
parts.push("--work-dir", shellEscape(workDir));
|
||||
}
|
||||
|
||||
appendApprovalFlags(parts, config.permissions);
|
||||
|
|
|
|||
Loading…
Reference in New Issue