@cjhyy/code-shell-core 0.6.0-rc.9 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/THIRD_PARTY_NOTICES.md +206 -0
- package/dist/automation/scheduler.d.ts +13 -7
- package/dist/automation/scheduler.js +116 -37
- package/dist/capability-control/service.d.ts +2 -0
- package/dist/capability-control/service.js +4 -2
- package/dist/cc-orchestrator/agent-adapter.d.ts +4 -0
- package/dist/cc-orchestrator/agent-adapter.js +11 -1
- package/dist/cc-orchestrator/codex-session-history.d.ts +14 -1
- package/dist/cc-orchestrator/codex-session-history.js +65 -5
- package/dist/cc-orchestrator/cwd-normalize.d.ts +2 -0
- package/dist/cc-orchestrator/cwd-normalize.js +19 -0
- package/dist/cc-orchestrator/external-agent-bindings.d.ts +27 -0
- package/dist/cc-orchestrator/external-agent-bindings.js +150 -0
- package/dist/cc-orchestrator/external-agent-changes.js +22 -5
- package/dist/cc-orchestrator/external-agent-driver.d.ts +1 -0
- package/dist/cc-orchestrator/external-agent-driver.js +265 -50
- package/dist/cc-orchestrator/external-agent-session-store.d.ts +23 -0
- package/dist/cc-orchestrator/external-agent-session-store.js +146 -0
- package/dist/cc-orchestrator/session-history.d.ts +35 -0
- package/dist/cc-orchestrator/session-history.js +98 -15
- package/dist/cli/agent-server-stdio.js +9 -2
- package/dist/context/compaction.d.ts +8 -1
- package/dist/context/compaction.js +49 -4
- package/dist/context/manager.d.ts +16 -2
- package/dist/context/manager.js +103 -19
- package/dist/credentials/access.d.ts +57 -0
- package/dist/credentials/access.js +185 -0
- package/dist/credentials/index.d.ts +3 -1
- package/dist/credentials/index.js +2 -0
- package/dist/credentials/inject-credential-tool.d.ts +3 -1
- package/dist/credentials/inject-credential-tool.js +30 -11
- package/dist/credentials/oauth.d.ts +20 -0
- package/dist/credentials/oauth.js +114 -0
- package/dist/credentials/store.d.ts +1 -0
- package/dist/credentials/store.js +3 -1
- package/dist/credentials/types.d.ts +49 -3
- package/dist/credentials/use-credential-tool.d.ts +9 -1
- package/dist/credentials/use-credential-tool.js +58 -45
- package/dist/engine/engine.d.ts +23 -3
- package/dist/engine/engine.js +380 -255
- package/dist/engine/goal.d.ts +17 -0
- package/dist/engine/goal.js +16 -6
- package/dist/engine/image-policy.d.ts +6 -0
- package/dist/engine/image-policy.js +17 -6
- package/dist/engine/input-attachments.d.ts +13 -0
- package/dist/engine/input-attachments.js +398 -0
- package/dist/engine/model-facade.d.ts +5 -2
- package/dist/engine/model-facade.js +4 -4
- package/dist/engine/parse-task.d.ts +10 -0
- package/dist/engine/parse-task.js +5 -0
- package/dist/engine/run-image-input.d.ts +22 -0
- package/dist/engine/run-image-input.js +195 -0
- package/dist/engine/steer-queue.d.ts +3 -1
- package/dist/engine/steer-queue.js +10 -2
- package/dist/engine/streaming-tool-queue.d.ts +11 -7
- package/dist/engine/streaming-tool-queue.js +11 -7
- package/dist/engine/turn-loop.d.ts +37 -2
- package/dist/engine/turn-loop.js +228 -43
- package/dist/engine/types.d.ts +8 -0
- package/dist/git/worktree/crud.d.ts +69 -0
- package/dist/git/worktree/crud.js +206 -0
- package/dist/git/worktree/diff.d.ts +14 -0
- package/dist/git/worktree/diff.js +82 -0
- package/dist/git/worktree/git-exec.d.ts +7 -0
- package/dist/git/worktree/git-exec.js +51 -0
- package/dist/git/worktree/index.d.ts +5 -0
- package/dist/git/worktree/index.js +5 -0
- package/dist/git/worktree/query.d.ts +42 -0
- package/dist/git/worktree/query.js +121 -0
- package/dist/git/worktree/slug.d.ts +11 -0
- package/dist/git/worktree/slug.js +58 -0
- package/dist/git/worktree.d.ts +1 -84
- package/dist/git/worktree.js +5 -230
- package/dist/hooks/goal-stop-hook.d.ts +33 -1
- package/dist/hooks/goal-stop-hook.js +202 -34
- package/dist/index.d.ts +31 -28
- package/dist/index.js +27 -25
- package/dist/logging/logger.js +6 -6
- package/dist/logging/sanitize-messages.d.ts +10 -2
- package/dist/logging/sanitize-messages.js +21 -6
- package/dist/plugins/installer/checkUpdate.d.ts +4 -1
- package/dist/plugins/installer/checkUpdate.js +4 -2
- package/dist/plugins/installer/install.js +2 -0
- package/dist/plugins/installer/installFromSource.js +9 -1
- package/dist/plugins/installer/parseSource.d.ts +4 -1
- package/dist/plugins/installer/parseSource.js +28 -10
- package/dist/plugins/installer/sourcePath.d.ts +9 -0
- package/dist/plugins/installer/sourcePath.js +50 -0
- package/dist/plugins/installer/update.d.ts +4 -1
- package/dist/plugins/installer/update.js +5 -3
- package/dist/plugins/parseMarketplaceInput.d.ts +4 -1
- package/dist/plugins/parseMarketplaceInput.js +4 -3
- package/dist/plugins/pluginInstaller.js +24 -22
- package/dist/preset/index.d.ts +1 -0
- package/dist/preset/index.js +30 -13
- package/dist/prompt/sections/base.md +1 -1
- package/dist/protocol/chat-session-manager.d.ts +2 -0
- package/dist/protocol/chat-session-manager.js +38 -2
- package/dist/protocol/chat-session.d.ts +3 -0
- package/dist/protocol/chat-session.js +1 -0
- package/dist/protocol/client.d.ts +9 -4
- package/dist/protocol/client.js +18 -1
- package/dist/protocol/server.d.ts +30 -0
- package/dist/protocol/server.js +247 -47
- package/dist/protocol/types.d.ts +49 -0
- package/dist/protocol/types.js +6 -0
- package/dist/run/FileRunStore.js +10 -1
- package/dist/run/Heartbeat.js +12 -0
- package/dist/run/RunApprovalBackend.d.ts +3 -0
- package/dist/run/RunApprovalBackend.js +41 -6
- package/dist/run/RunLock.js +2 -0
- package/dist/run/RunManager.d.ts +2 -0
- package/dist/run/RunManager.js +64 -24
- package/dist/run/ids.d.ts +2 -0
- package/dist/run/ids.js +23 -0
- package/dist/runtime/background-shell.d.ts +1 -0
- package/dist/runtime/background-shell.js +23 -13
- package/dist/runtime/spawn-common.js +10 -0
- package/dist/services/auto-dream.d.ts +15 -4
- package/dist/services/auto-dream.js +20 -20
- package/dist/services/dream-consolidation.d.ts +2 -3
- package/dist/services/dream-consolidation.js +65 -15
- package/dist/services/extract-memories.d.ts +14 -5
- package/dist/services/extract-memories.js +20 -3
- package/dist/services/global-dream-promotion.d.ts +23 -0
- package/dist/services/global-dream-promotion.js +112 -0
- package/dist/services/memory-orchestrator.js +347 -34
- package/dist/session/memory.d.ts +61 -18
- package/dist/session/memory.js +342 -79
- package/dist/session/session-manager.d.ts +35 -1
- package/dist/session/session-manager.js +224 -4
- package/dist/session/transcript.d.ts +1 -1
- package/dist/session/transcript.js +17 -5
- package/dist/settings/manager.d.ts +1 -0
- package/dist/settings/manager.js +87 -37
- package/dist/settings/schema-export.d.ts +2 -3
- package/dist/settings/schema-export.js +2 -3
- package/dist/settings/schema.d.ts +21 -0
- package/dist/settings/schema.js +12 -0
- package/dist/skills/scanner.d.ts +3 -2
- package/dist/skills/scanner.js +12 -9
- package/dist/tool-system/builtin/agent-notifications.d.ts +11 -4
- package/dist/tool-system/builtin/agent-notifications.js +19 -7
- package/dist/tool-system/builtin/background-jobs.d.ts +35 -6
- package/dist/tool-system/builtin/background-jobs.js +116 -7
- package/dist/tool-system/builtin/background-work.d.ts +17 -18
- package/dist/tool-system/builtin/background-work.js +51 -5
- package/dist/tool-system/builtin/config.d.ts +2 -1
- package/dist/tool-system/builtin/config.js +16 -11
- package/dist/tool-system/builtin/cron-list.definition.d.ts +3 -0
- package/dist/tool-system/builtin/cron-list.definition.js +6 -0
- package/dist/tool-system/builtin/cron.d.ts +1 -2
- package/dist/tool-system/builtin/cron.js +9 -7
- package/dist/tool-system/builtin/drive-claude-code.d.ts +23 -2
- package/dist/tool-system/builtin/drive-claude-code.js +589 -48
- package/dist/tool-system/builtin/edit.js +5 -2
- package/dist/tool-system/builtin/generate-video.d.ts +1 -0
- package/dist/tool-system/builtin/generate-video.js +13 -4
- package/dist/tool-system/builtin/index.d.ts +8 -3
- package/dist/tool-system/builtin/index.js +50 -22
- package/dist/tool-system/builtin/lsp.d.ts +2 -1
- package/dist/tool-system/builtin/lsp.js +6 -3
- package/dist/tool-system/builtin/memory.js +40 -8
- package/dist/tool-system/builtin/notebook-edit.js +5 -2
- package/dist/tool-system/builtin/powershell.d.ts +5 -2
- package/dist/tool-system/builtin/powershell.js +11 -7
- package/dist/tool-system/builtin/read.js +118 -6
- package/dist/tool-system/builtin/sleep.d.ts +1 -2
- package/dist/tool-system/builtin/sleep.definition.d.ts +8 -0
- package/dist/tool-system/builtin/sleep.definition.js +28 -0
- package/dist/tool-system/builtin/sleep.js +1 -22
- package/dist/tool-system/builtin/view-image.d.ts +2 -2
- package/dist/tool-system/builtin/view-image.js +109 -19
- package/dist/tool-system/builtin/worktree.d.ts +4 -4
- package/dist/tool-system/builtin/worktree.js +297 -74
- package/dist/tool-system/builtin/write.js +5 -3
- package/dist/tool-system/context.d.ts +41 -1
- package/dist/tool-system/executor.d.ts +1 -5
- package/dist/tool-system/executor.js +94 -115
- package/dist/tool-system/mcp-manager.d.ts +31 -6
- package/dist/tool-system/mcp-manager.js +193 -78
- package/dist/tool-system/path-policy.d.ts +2 -0
- package/dist/tool-system/path-policy.js +41 -12
- package/dist/tool-system/permission.d.ts +28 -7
- package/dist/tool-system/permission.js +130 -49
- package/dist/tool-system/registry.js +11 -4
- package/dist/tool-system/tool-result-redaction.d.ts +7 -0
- package/dist/tool-system/tool-result-redaction.js +48 -0
- package/dist/tool-system/workspace-bridge.d.ts +11 -0
- package/dist/tool-system/workspace-bridge.js +1 -0
- package/dist/types.d.ts +78 -11
- package/dist/utils/toolDisplay.js +1 -1
- package/package.json +4 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readdirSync, readFileSync, statSync, existsSync, openSync, readSync, closeSync } from "node:fs";
|
|
1
|
+
import { readdirSync, readFileSync, statSync, existsSync, openSync, readSync, closeSync, } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
/**
|
|
@@ -22,7 +22,7 @@ import { homedir } from "node:os";
|
|
|
22
22
|
*/
|
|
23
23
|
export function readCodexRecentHistory(cwd, threadId, limit, codexHome = join(homedir(), ".codex")) {
|
|
24
24
|
const empty = { messages: [], hasMore: false, totalCount: 0 };
|
|
25
|
-
const file =
|
|
25
|
+
const file = findCodexRolloutFile(codexHome, cwd, threadId);
|
|
26
26
|
if (!file)
|
|
27
27
|
return empty;
|
|
28
28
|
let raw;
|
|
@@ -32,6 +32,11 @@ export function readCodexRecentHistory(cwd, threadId, limit, codexHome = join(ho
|
|
|
32
32
|
catch {
|
|
33
33
|
return empty;
|
|
34
34
|
}
|
|
35
|
+
return parseCodexRecentHistory(raw, limit);
|
|
36
|
+
}
|
|
37
|
+
/** Parse a bounded/raw Codex rollout snapshot. Shared with the desktop tail
|
|
38
|
+
* follower so its initial history and EOF cursor are atomic. */
|
|
39
|
+
export function parseCodexRecentHistory(raw, limit) {
|
|
35
40
|
const all = [];
|
|
36
41
|
for (const line of raw.split("\n")) {
|
|
37
42
|
if (!line.trim())
|
|
@@ -52,10 +57,14 @@ export function readCodexRecentHistory(cwd, threadId, limit, codexHome = join(ho
|
|
|
52
57
|
const t = textOf(p.content).trim();
|
|
53
58
|
if (!t || t.startsWith("<environment_context>"))
|
|
54
59
|
continue;
|
|
55
|
-
all.push({ role: p.role, text: t
|
|
60
|
+
all.push({ role: p.role, text: t });
|
|
56
61
|
}
|
|
57
62
|
else if (p.type === "function_call" || p.type === "custom_tool_call") {
|
|
58
|
-
const tool = {
|
|
63
|
+
const tool = {
|
|
64
|
+
name: typeof p.name === "string" ? p.name : "tool",
|
|
65
|
+
summary: summaryOf(p),
|
|
66
|
+
args: argsOf(p),
|
|
67
|
+
};
|
|
59
68
|
const last = all[all.length - 1];
|
|
60
69
|
// Attach the tool to the preceding assistant turn; otherwise start one.
|
|
61
70
|
if (last && last.role === "assistant") {
|
|
@@ -70,6 +79,57 @@ export function readCodexRecentHistory(cwd, threadId, limit, codexHome = join(ho
|
|
|
70
79
|
const start = Math.max(0, all.length - lim);
|
|
71
80
|
return { messages: all.slice(start), hasMore: start > 0, totalCount: all.length };
|
|
72
81
|
}
|
|
82
|
+
/** Parse one newly-appended Codex rollout JSONL line. `response_item` is the
|
|
83
|
+
* authoritative rendered stream; parallel `event_msg.agent_message` records
|
|
84
|
+
* are deliberately ignored to avoid duplicate assistant bubbles. */
|
|
85
|
+
export function parseCodexTranscriptLine(line) {
|
|
86
|
+
let d;
|
|
87
|
+
try {
|
|
88
|
+
d = JSON.parse(line);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return [];
|
|
92
|
+
}
|
|
93
|
+
if (d?.type === "event_msg" && d.payload?.type === "task_complete") {
|
|
94
|
+
return [{ type: "turn_end", reason: "completed" }];
|
|
95
|
+
}
|
|
96
|
+
if (d?.type !== "response_item" || !d.payload)
|
|
97
|
+
return [];
|
|
98
|
+
const p = d.payload;
|
|
99
|
+
if (p.type === "message" && (p.role === "user" || p.role === "assistant")) {
|
|
100
|
+
const text = textOf(p.content).trim();
|
|
101
|
+
if (!text || text.startsWith("<environment_context>"))
|
|
102
|
+
return [];
|
|
103
|
+
return [{ type: p.role === "user" ? "user" : "assistant", text }];
|
|
104
|
+
}
|
|
105
|
+
if (p.type === "function_call" || p.type === "custom_tool_call") {
|
|
106
|
+
return [
|
|
107
|
+
{
|
|
108
|
+
type: "tool",
|
|
109
|
+
id: typeof p.call_id === "string" ? p.call_id : undefined,
|
|
110
|
+
name: typeof p.name === "string" ? p.name : "tool",
|
|
111
|
+
summary: summaryOf(p),
|
|
112
|
+
args: argsOf(p),
|
|
113
|
+
},
|
|
114
|
+
];
|
|
115
|
+
}
|
|
116
|
+
if (p.type === "function_call_output" || p.type === "custom_tool_call_output") {
|
|
117
|
+
const result = typeof p.output === "string"
|
|
118
|
+
? p.output
|
|
119
|
+
: typeof p.content === "string"
|
|
120
|
+
? p.content
|
|
121
|
+
: JSON.stringify(p.output ?? p.content ?? "");
|
|
122
|
+
return [
|
|
123
|
+
{
|
|
124
|
+
type: "tool_result",
|
|
125
|
+
id: typeof p.call_id === "string" ? p.call_id : undefined,
|
|
126
|
+
result: result.slice(0, 4000),
|
|
127
|
+
isError: Boolean(p.is_error),
|
|
128
|
+
},
|
|
129
|
+
];
|
|
130
|
+
}
|
|
131
|
+
return [];
|
|
132
|
+
}
|
|
73
133
|
/** Join the text of codex content parts (`input_text`/`output_text`). */
|
|
74
134
|
function textOf(content) {
|
|
75
135
|
if (typeof content === "string")
|
|
@@ -121,7 +181,7 @@ function argsOf(payload) {
|
|
|
121
181
|
return undefined;
|
|
122
182
|
}
|
|
123
183
|
/** Find the rollout file whose `session_meta` matches both `threadId` and `cwd`. */
|
|
124
|
-
function
|
|
184
|
+
export function findCodexRolloutFile(codexHome, cwd, threadId) {
|
|
125
185
|
const root = join(codexHome, "sessions");
|
|
126
186
|
if (!existsSync(root))
|
|
127
187
|
return undefined;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { realpathSync, statSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
export function normalizeCwdPath(cwd) {
|
|
4
|
+
const resolved = resolve(cwd);
|
|
5
|
+
try {
|
|
6
|
+
return realpathSync(resolved);
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
return resolved;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export function isExistingDirectory(cwd) {
|
|
13
|
+
try {
|
|
14
|
+
return statSync(cwd).isDirectory();
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type ExternalAgentCli = "claude" | "codex";
|
|
2
|
+
export interface ExternalAgentRunBinding {
|
|
3
|
+
cli: ExternalAgentCli;
|
|
4
|
+
externalSessionId: string;
|
|
5
|
+
codeShellSessionId: string;
|
|
6
|
+
cwd: string;
|
|
7
|
+
worktreePath?: string;
|
|
8
|
+
worktreeBranch?: string;
|
|
9
|
+
createdAt: number;
|
|
10
|
+
lastUsedAt: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function externalAgentBindingsPath(home?: string): string;
|
|
13
|
+
export declare class ExternalAgentBindingStore {
|
|
14
|
+
private readonly filePath?;
|
|
15
|
+
constructor(filePath?: string | undefined);
|
|
16
|
+
get(externalSessionId: string): ExternalAgentRunBinding | undefined;
|
|
17
|
+
upsert(next: Omit<ExternalAgentRunBinding, "createdAt" | "lastUsedAt">): ExternalAgentRunBinding;
|
|
18
|
+
private read;
|
|
19
|
+
private write;
|
|
20
|
+
private file;
|
|
21
|
+
}
|
|
22
|
+
export declare function detectExternalAgentWorktree(cwd: string): {
|
|
23
|
+
worktreePath?: string;
|
|
24
|
+
worktreeBranch?: string;
|
|
25
|
+
};
|
|
26
|
+
export declare function externalAgentResumeCwdError(binding: ExternalAgentRunBinding): string | undefined;
|
|
27
|
+
export declare const externalAgentBindingStore: ExternalAgentBindingStore;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join, resolve } from "node:path";
|
|
3
|
+
import { execFileSync } from "node:child_process";
|
|
4
|
+
import { codeShellHome, SessionManager } from "../session/session-manager.js";
|
|
5
|
+
export function externalAgentBindingsPath(home = codeShellHome()) {
|
|
6
|
+
return join(home, "external-agents", "bindings.json");
|
|
7
|
+
}
|
|
8
|
+
export class ExternalAgentBindingStore {
|
|
9
|
+
filePath;
|
|
10
|
+
constructor(filePath) {
|
|
11
|
+
this.filePath = filePath;
|
|
12
|
+
}
|
|
13
|
+
get(externalSessionId) {
|
|
14
|
+
return this.read({ failOnCorrupt: true }).bindings[externalSessionId];
|
|
15
|
+
}
|
|
16
|
+
upsert(next) {
|
|
17
|
+
const data = this.read({ failOnCorrupt: false });
|
|
18
|
+
const existing = data.bindings[next.externalSessionId];
|
|
19
|
+
const now = Date.now();
|
|
20
|
+
const binding = {
|
|
21
|
+
...next,
|
|
22
|
+
codeShellSessionId: next.codeShellSessionId || existing?.codeShellSessionId || "",
|
|
23
|
+
createdAt: existing?.createdAt ?? now,
|
|
24
|
+
lastUsedAt: now,
|
|
25
|
+
};
|
|
26
|
+
data.bindings[next.externalSessionId] = binding;
|
|
27
|
+
this.write(data);
|
|
28
|
+
return binding;
|
|
29
|
+
}
|
|
30
|
+
read(opts) {
|
|
31
|
+
const file = this.file();
|
|
32
|
+
if (!existsSync(file))
|
|
33
|
+
return { bindings: {} };
|
|
34
|
+
try {
|
|
35
|
+
const parsed = JSON.parse(readFileSync(file, "utf-8"));
|
|
36
|
+
if (parsed && typeof parsed.bindings === "object" && parsed.bindings) {
|
|
37
|
+
return { bindings: parsed.bindings };
|
|
38
|
+
}
|
|
39
|
+
if (opts.failOnCorrupt) {
|
|
40
|
+
throw new Error(`external agent bindings file is corrupt: expected object with bindings`);
|
|
41
|
+
}
|
|
42
|
+
return { bindings: {} };
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
if (opts.failOnCorrupt) {
|
|
46
|
+
throw new Error(`external agent bindings file is corrupt or unreadable: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
|
|
47
|
+
}
|
|
48
|
+
return { bindings: {} };
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
write(data) {
|
|
52
|
+
const file = this.file();
|
|
53
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
54
|
+
const tmp = `${file}.${process.pid}.${Date.now()}.tmp`;
|
|
55
|
+
writeFileSync(tmp, JSON.stringify(data, null, 2), "utf-8");
|
|
56
|
+
renameSync(tmp, file);
|
|
57
|
+
}
|
|
58
|
+
file() {
|
|
59
|
+
return this.filePath ?? externalAgentBindingsPath();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export function detectExternalAgentWorktree(cwd) {
|
|
63
|
+
if (!existsSync(cwd))
|
|
64
|
+
return {};
|
|
65
|
+
try {
|
|
66
|
+
const root = git(cwd, ["rev-parse", "--show-toplevel"]);
|
|
67
|
+
const branch = git(root, ["branch", "--show-current"]);
|
|
68
|
+
const entries = parseWorktreeList(git(root, ["worktree", "list", "--porcelain"]));
|
|
69
|
+
const current = entries.find((entry) => resolve(entry.path) === resolve(root));
|
|
70
|
+
const main = entries[0];
|
|
71
|
+
if (!current || !branch || !main || resolve(current.path) === resolve(main.path))
|
|
72
|
+
return {};
|
|
73
|
+
return { worktreePath: root, worktreeBranch: branch };
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return {};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export function externalAgentResumeCwdError(binding) {
|
|
80
|
+
if (existsSync(binding.cwd))
|
|
81
|
+
return undefined;
|
|
82
|
+
const branch = binding.worktreeBranch;
|
|
83
|
+
if (branch && branchExistsForBinding(binding)) {
|
|
84
|
+
return (`Error: external ${binding.cli} session ${binding.externalSessionId} is bound to cwd ` +
|
|
85
|
+
`${binding.cwd}, but that directory no longer exists. Worktree branch ${branch} still ` +
|
|
86
|
+
`exists; recreate the worktree at ${binding.worktreePath ?? binding.cwd} before resuming.`);
|
|
87
|
+
}
|
|
88
|
+
return (`Error: external ${binding.cli} session ${binding.externalSessionId} is bound to cwd ` +
|
|
89
|
+
`${binding.cwd}, but the workspace deleted${branch ? ` and branch ${branch} is gone` : ""}. ` +
|
|
90
|
+
`Start a new external session.`);
|
|
91
|
+
}
|
|
92
|
+
function branchExistsForBinding(binding) {
|
|
93
|
+
if (!binding.worktreeBranch)
|
|
94
|
+
return false;
|
|
95
|
+
for (const cwd of candidateGitCwds(binding)) {
|
|
96
|
+
if (!cwd || !existsSync(cwd))
|
|
97
|
+
continue;
|
|
98
|
+
try {
|
|
99
|
+
const out = git(cwd, ["branch", "--list", binding.worktreeBranch]);
|
|
100
|
+
if (out.length > 0)
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// Try the next candidate.
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
function candidateGitCwds(binding) {
|
|
110
|
+
const candidates = new Set();
|
|
111
|
+
if (existsSync(binding.cwd))
|
|
112
|
+
candidates.add(binding.cwd);
|
|
113
|
+
if (binding.codeShellSessionId) {
|
|
114
|
+
const sessionCwd = new SessionManager().readCwd(binding.codeShellSessionId);
|
|
115
|
+
if (sessionCwd)
|
|
116
|
+
candidates.add(sessionCwd);
|
|
117
|
+
}
|
|
118
|
+
candidates.add(process.cwd());
|
|
119
|
+
candidates.add(dirname(binding.cwd));
|
|
120
|
+
candidates.add(dirname(dirname(binding.cwd)));
|
|
121
|
+
return [...candidates];
|
|
122
|
+
}
|
|
123
|
+
function parseWorktreeList(raw) {
|
|
124
|
+
if (!raw.trim())
|
|
125
|
+
return [];
|
|
126
|
+
const entries = [];
|
|
127
|
+
let current = { path: "", branch: "" };
|
|
128
|
+
for (const line of raw.split("\n")) {
|
|
129
|
+
if (line.startsWith("worktree ")) {
|
|
130
|
+
if (current.path)
|
|
131
|
+
entries.push(current);
|
|
132
|
+
current = { path: line.slice(9), branch: "" };
|
|
133
|
+
}
|
|
134
|
+
else if (line.startsWith("branch ")) {
|
|
135
|
+
current.branch = line.slice(7).replace("refs/heads/", "");
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (current.path)
|
|
139
|
+
entries.push(current);
|
|
140
|
+
return entries;
|
|
141
|
+
}
|
|
142
|
+
function git(cwd, args) {
|
|
143
|
+
return execFileSync("git", args, {
|
|
144
|
+
cwd,
|
|
145
|
+
encoding: "utf-8",
|
|
146
|
+
timeout: 10000,
|
|
147
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
148
|
+
}).trim();
|
|
149
|
+
}
|
|
150
|
+
export const externalAgentBindingStore = new ExternalAgentBindingStore();
|
|
@@ -2,6 +2,7 @@ import { readFileSync, existsSync, readdirSync, statSync, openSync, readSync, cl
|
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { encodeCwd } from "./session-discovery.js";
|
|
5
|
+
import { logger } from "../logging/logger.js";
|
|
5
6
|
/**
|
|
6
7
|
* #6 — attribute file changes made by a background external agent (DriveAgent
|
|
7
8
|
* running `claude` / `codex`). Those Edit/Write calls land in the external CLI's
|
|
@@ -143,11 +144,27 @@ export function readCodexChangedFiles(cwd, threadId, codexHome = join(homedir(),
|
|
|
143
144
|
/** Dispatch by CLI. Unknown cli → []. Never throws. */
|
|
144
145
|
export function readExternalChangedFiles(cli, cwd, sessionId) {
|
|
145
146
|
try {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
147
|
+
const files = cli === "codex"
|
|
148
|
+
? readCodexChangedFiles(cwd, sessionId)
|
|
149
|
+
: readClaudeChangedFiles(cwd, sessionId);
|
|
150
|
+
logger.debug("changed_files.external.extracted", {
|
|
151
|
+
cat: "changed_files",
|
|
152
|
+
cli,
|
|
153
|
+
cwd,
|
|
154
|
+
externalSessionId: sessionId,
|
|
155
|
+
size: files.length,
|
|
156
|
+
files,
|
|
157
|
+
});
|
|
158
|
+
return files;
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
logger.debug("changed_files.external.extract_failed", {
|
|
162
|
+
cat: "changed_files",
|
|
163
|
+
cli,
|
|
164
|
+
cwd,
|
|
165
|
+
externalSessionId: sessionId,
|
|
166
|
+
error: err instanceof Error ? err.message : String(err),
|
|
167
|
+
});
|
|
151
168
|
return [];
|
|
152
169
|
}
|
|
153
170
|
}
|
|
@@ -11,6 +11,7 @@ export declare function runWithLines(adapter: AgentAdapter, lines: string[], exi
|
|
|
11
11
|
export interface DriverRunOpts extends Omit<BuildArgsOpts, "permissionMode"> {
|
|
12
12
|
permissionMode?: PermissionMode;
|
|
13
13
|
}
|
|
14
|
+
export declare function detectCodexImageInput(command: string, cwd: string, signal?: AbortSignal): Promise<boolean>;
|
|
14
15
|
/** Spawn ONE headless agent run, collect stream-json to exit, return result.
|
|
15
16
|
* No time concept — a single turn. Honors AbortSignal (kills the child). */
|
|
16
17
|
export declare function runAgentOnce(adapter: AgentAdapter, opts: DriverRunOpts & {
|