@cjhyy/code-shell-core 0.6.0-rc.8 → 0.7.0-beta.1

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.
Files changed (177) hide show
  1. package/THIRD_PARTY_NOTICES.md +206 -0
  2. package/dist/automation/scheduler.d.ts +13 -7
  3. package/dist/automation/scheduler.js +116 -37
  4. package/dist/capability-control/service.d.ts +2 -0
  5. package/dist/capability-control/service.js +4 -2
  6. package/dist/cc-orchestrator/agent-adapter.d.ts +2 -0
  7. package/dist/cc-orchestrator/agent-adapter.js +7 -1
  8. package/dist/cc-orchestrator/codex-session-history.js +1 -1
  9. package/dist/cc-orchestrator/cwd-normalize.d.ts +2 -0
  10. package/dist/cc-orchestrator/cwd-normalize.js +19 -0
  11. package/dist/cc-orchestrator/external-agent-bindings.d.ts +27 -0
  12. package/dist/cc-orchestrator/external-agent-bindings.js +150 -0
  13. package/dist/cc-orchestrator/external-agent-driver.d.ts +1 -0
  14. package/dist/cc-orchestrator/external-agent-driver.js +102 -51
  15. package/dist/cc-orchestrator/external-agent-session-store.d.ts +23 -0
  16. package/dist/cc-orchestrator/external-agent-session-store.js +146 -0
  17. package/dist/cc-orchestrator/session-history.js +2 -2
  18. package/dist/cli/agent-server-stdio.js +9 -2
  19. package/dist/context/compaction.d.ts +38 -1
  20. package/dist/context/compaction.js +138 -0
  21. package/dist/context/manager.d.ts +34 -2
  22. package/dist/context/manager.js +254 -58
  23. package/dist/context/token-counter.js +13 -0
  24. package/dist/credentials/access.d.ts +56 -0
  25. package/dist/credentials/access.js +183 -0
  26. package/dist/credentials/index.d.ts +1 -0
  27. package/dist/credentials/index.js +1 -0
  28. package/dist/credentials/inject-credential-tool.d.ts +3 -1
  29. package/dist/credentials/inject-credential-tool.js +30 -11
  30. package/dist/credentials/types.d.ts +2 -2
  31. package/dist/credentials/use-credential-tool.d.ts +9 -1
  32. package/dist/credentials/use-credential-tool.js +58 -45
  33. package/dist/engine/engine.d.ts +38 -12
  34. package/dist/engine/engine.js +477 -163
  35. package/dist/engine/image-policy.d.ts +6 -0
  36. package/dist/engine/image-policy.js +17 -6
  37. package/dist/engine/input-attachments.d.ts +13 -0
  38. package/dist/engine/input-attachments.js +255 -0
  39. package/dist/engine/model-facade.d.ts +5 -2
  40. package/dist/engine/model-facade.js +6 -16
  41. package/dist/engine/parse-task.d.ts +10 -0
  42. package/dist/engine/parse-task.js +5 -0
  43. package/dist/engine/query.js +2 -0
  44. package/dist/engine/session-usage.d.ts +12 -0
  45. package/dist/engine/session-usage.js +56 -0
  46. package/dist/engine/steer-queue.d.ts +2 -1
  47. package/dist/engine/steer-queue.js +2 -2
  48. package/dist/engine/streaming-tool-queue.d.ts +11 -7
  49. package/dist/engine/streaming-tool-queue.js +11 -7
  50. package/dist/engine/turn-loop.d.ts +34 -2
  51. package/dist/engine/turn-loop.js +269 -52
  52. package/dist/engine/types.d.ts +8 -0
  53. package/dist/git/worktree/crud.d.ts +69 -0
  54. package/dist/git/worktree/crud.js +206 -0
  55. package/dist/git/worktree/diff.d.ts +14 -0
  56. package/dist/git/worktree/diff.js +82 -0
  57. package/dist/git/worktree/git-exec.d.ts +7 -0
  58. package/dist/git/worktree/git-exec.js +51 -0
  59. package/dist/git/worktree/index.d.ts +5 -0
  60. package/dist/git/worktree/index.js +5 -0
  61. package/dist/git/worktree/query.d.ts +42 -0
  62. package/dist/git/worktree/query.js +121 -0
  63. package/dist/git/worktree/slug.d.ts +11 -0
  64. package/dist/git/worktree/slug.js +58 -0
  65. package/dist/git/worktree.d.ts +1 -84
  66. package/dist/git/worktree.js +5 -230
  67. package/dist/index.d.ts +31 -28
  68. package/dist/index.js +27 -25
  69. package/dist/logging/logger.js +6 -6
  70. package/dist/logging/sanitize-messages.d.ts +10 -2
  71. package/dist/logging/sanitize-messages.js +21 -6
  72. package/dist/plugins/installer/checkUpdate.d.ts +4 -1
  73. package/dist/plugins/installer/checkUpdate.js +4 -2
  74. package/dist/plugins/installer/install.js +2 -0
  75. package/dist/plugins/installer/installFromSource.js +9 -1
  76. package/dist/plugins/installer/parseSource.d.ts +4 -1
  77. package/dist/plugins/installer/parseSource.js +28 -10
  78. package/dist/plugins/installer/sourcePath.d.ts +9 -0
  79. package/dist/plugins/installer/sourcePath.js +50 -0
  80. package/dist/plugins/installer/update.d.ts +4 -1
  81. package/dist/plugins/installer/update.js +5 -3
  82. package/dist/plugins/parseMarketplaceInput.d.ts +4 -1
  83. package/dist/plugins/parseMarketplaceInput.js +4 -3
  84. package/dist/plugins/pluginInstaller.js +24 -22
  85. package/dist/preset/index.d.ts +1 -0
  86. package/dist/preset/index.js +16 -9
  87. package/dist/prompt/sections/base.md +1 -1
  88. package/dist/protocol/chat-session-manager.d.ts +2 -0
  89. package/dist/protocol/chat-session-manager.js +38 -2
  90. package/dist/protocol/chat-session.d.ts +5 -0
  91. package/dist/protocol/chat-session.js +2 -0
  92. package/dist/protocol/client.d.ts +13 -5
  93. package/dist/protocol/client.js +26 -3
  94. package/dist/protocol/server.d.ts +43 -12
  95. package/dist/protocol/server.js +326 -104
  96. package/dist/protocol/types.d.ts +51 -0
  97. package/dist/protocol/types.js +6 -0
  98. package/dist/run/FileRunStore.js +10 -1
  99. package/dist/run/Heartbeat.js +12 -0
  100. package/dist/run/RunApprovalBackend.d.ts +3 -0
  101. package/dist/run/RunApprovalBackend.js +41 -6
  102. package/dist/run/RunLock.js +2 -0
  103. package/dist/run/RunManager.d.ts +2 -0
  104. package/dist/run/RunManager.js +64 -24
  105. package/dist/run/ids.d.ts +2 -0
  106. package/dist/run/ids.js +23 -0
  107. package/dist/runtime/background-shell.d.ts +1 -0
  108. package/dist/runtime/background-shell.js +23 -13
  109. package/dist/runtime/safe-spawn.js +74 -11
  110. package/dist/runtime/spawn-common.js +10 -0
  111. package/dist/services/auto-dream.d.ts +15 -4
  112. package/dist/services/auto-dream.js +20 -20
  113. package/dist/services/dream-consolidation.d.ts +2 -3
  114. package/dist/services/dream-consolidation.js +65 -15
  115. package/dist/services/extract-memories.d.ts +14 -5
  116. package/dist/services/extract-memories.js +20 -3
  117. package/dist/services/global-dream-promotion.d.ts +23 -0
  118. package/dist/services/global-dream-promotion.js +112 -0
  119. package/dist/services/memory-orchestrator.js +347 -34
  120. package/dist/session/memory.d.ts +61 -18
  121. package/dist/session/memory.js +342 -79
  122. package/dist/session/session-manager.d.ts +35 -1
  123. package/dist/session/session-manager.js +197 -4
  124. package/dist/session/transcript.d.ts +5 -1
  125. package/dist/session/transcript.js +38 -5
  126. package/dist/settings/manager.d.ts +1 -0
  127. package/dist/settings/manager.js +87 -37
  128. package/dist/settings/schema-export.d.ts +2 -3
  129. package/dist/settings/schema-export.js +2 -3
  130. package/dist/settings/schema.d.ts +21 -0
  131. package/dist/settings/schema.js +12 -0
  132. package/dist/skills/scanner.d.ts +3 -2
  133. package/dist/skills/scanner.js +12 -9
  134. package/dist/tool-system/builtin/background-jobs.d.ts +10 -1
  135. package/dist/tool-system/builtin/background-jobs.js +12 -1
  136. package/dist/tool-system/builtin/background-work.d.ts +17 -18
  137. package/dist/tool-system/builtin/background-work.js +51 -5
  138. package/dist/tool-system/builtin/config.d.ts +2 -1
  139. package/dist/tool-system/builtin/config.js +16 -11
  140. package/dist/tool-system/builtin/drive-claude-code.d.ts +16 -2
  141. package/dist/tool-system/builtin/drive-claude-code.js +301 -47
  142. package/dist/tool-system/builtin/edit.js +5 -2
  143. package/dist/tool-system/builtin/generate-video.d.ts +1 -0
  144. package/dist/tool-system/builtin/generate-video.js +13 -4
  145. package/dist/tool-system/builtin/index.d.ts +8 -3
  146. package/dist/tool-system/builtin/index.js +37 -21
  147. package/dist/tool-system/builtin/lsp.d.ts +2 -1
  148. package/dist/tool-system/builtin/lsp.js +6 -3
  149. package/dist/tool-system/builtin/memory.js +40 -8
  150. package/dist/tool-system/builtin/notebook-edit.js +5 -2
  151. package/dist/tool-system/builtin/powershell.d.ts +5 -2
  152. package/dist/tool-system/builtin/powershell.js +11 -7
  153. package/dist/tool-system/builtin/read.js +118 -6
  154. package/dist/tool-system/builtin/view-image.d.ts +2 -2
  155. package/dist/tool-system/builtin/view-image.js +109 -19
  156. package/dist/tool-system/builtin/worktree.d.ts +4 -4
  157. package/dist/tool-system/builtin/worktree.js +297 -74
  158. package/dist/tool-system/builtin/write.js +5 -3
  159. package/dist/tool-system/context.d.ts +23 -1
  160. package/dist/tool-system/executor.d.ts +1 -5
  161. package/dist/tool-system/executor.js +94 -115
  162. package/dist/tool-system/mcp-manager.d.ts +18 -5
  163. package/dist/tool-system/mcp-manager.js +157 -74
  164. package/dist/tool-system/mcp-stdio-diagnostics.d.ts +9 -0
  165. package/dist/tool-system/mcp-stdio-diagnostics.js +93 -0
  166. package/dist/tool-system/path-policy.d.ts +2 -0
  167. package/dist/tool-system/path-policy.js +41 -12
  168. package/dist/tool-system/permission.d.ts +28 -7
  169. package/dist/tool-system/permission.js +130 -49
  170. package/dist/tool-system/registry.js +11 -4
  171. package/dist/tool-system/tool-result-redaction.d.ts +7 -0
  172. package/dist/tool-system/tool-result-redaction.js +48 -0
  173. package/dist/tool-system/workspace-bridge.d.ts +11 -0
  174. package/dist/tool-system/workspace-bridge.js +1 -0
  175. package/dist/types.d.ts +86 -5
  176. package/dist/utils/toolDisplay.js +1 -1
  177. package/package.json +4 -3
@@ -2,6 +2,7 @@
2
2
  * Settings schema with Zod validation.
3
3
  */
4
4
  import { z } from "zod";
5
+ import { DEFAULT_WORKTREE_BRANCH_PREFIX, isValidWorktreeBranchPrefix, normalizeWorktreeBranchPrefix, } from "../git/worktree/slug.js";
5
6
  /**
6
7
  * Tri-state project capability overlay. Lives in PROJECT settings only and
7
8
  * layers over the global baseline (disabledSkills / disabledPlugins /
@@ -30,6 +31,12 @@ export const CapabilityOverridesSchema = z
30
31
  pluginHooks: z.record(CapabilityOverrideSchema).optional(),
31
32
  })
32
33
  .optional();
34
+ const WorktreeBranchPrefixSchema = z
35
+ .string()
36
+ .trim()
37
+ .min(1)
38
+ .refine(isValidWorktreeBranchPrefix, "Invalid git branch prefix")
39
+ .transform((value) => normalizeWorktreeBranchPrefix(value));
33
40
  export const SettingsSchema = z
34
41
  .object({
35
42
  agent: z
@@ -214,6 +221,11 @@ export const SettingsSchema = z
214
221
  maxHistory: z.number().default(100),
215
222
  })
216
223
  .default({}),
224
+ worktree: z
225
+ .object({
226
+ branchPrefix: WorktreeBranchPrefixSchema.default(DEFAULT_WORKTREE_BRANCH_PREFIX),
227
+ })
228
+ .default({}),
217
229
  // The record key IS the server name at runtime (MCPManager.connectAll
218
230
  // uses Object.entries keys; desktop's persist strips the `name` field and
219
231
  // keys by it via stripNameFromServer). So `name` here is optional and
@@ -1,6 +1,7 @@
1
1
  /**
2
- * Skill scanner — discovers <base>/<name>/SKILL.md files from project + user
3
- * directories AND from installed plugins. Mirrors Claude Code's
2
+ * Skill scanner — discovers <base>/<name>/SKILL.md files from project
3
+ * `.code-shell/skills`, project `.agents/skills`, user `.code-shell/skills`,
4
+ * and installed plugins. Mirrors Claude Code's
4
5
  * `loadSkillsFromSkillsDir` (skills/loadSkillsDir.ts:407) plus plugin
5
6
  * integration (utils/plugins/pluginLoader.ts).
6
7
  */
@@ -1,6 +1,7 @@
1
1
  /**
2
- * Skill scanner — discovers <base>/<name>/SKILL.md files from project + user
3
- * directories AND from installed plugins. Mirrors Claude Code's
2
+ * Skill scanner — discovers <base>/<name>/SKILL.md files from project
3
+ * `.code-shell/skills`, project `.agents/skills`, user `.code-shell/skills`,
4
+ * and installed plugins. Mirrors Claude Code's
4
5
  * `loadSkillsFromSkillsDir` (skills/loadSkillsDir.ts:407) plus plugin
5
6
  * integration (utils/plugins/pluginLoader.ts).
6
7
  */
@@ -20,6 +21,7 @@ function userHome() {
20
21
  function bases(cwd) {
21
22
  return [
22
23
  { dir: join(cwd, ".code-shell", "skills"), source: "project" },
24
+ { dir: join(cwd, ".agents", "skills"), source: "project" },
23
25
  { dir: join(userHome(), ".code-shell", "skills"), source: "user" },
24
26
  ];
25
27
  }
@@ -158,13 +160,14 @@ function installedPluginsMtime() {
158
160
  }
159
161
  }
160
162
  /**
161
- * mtime of each local skills base dir (project + user). A directory's mtime
162
- * changes when a child entry is added/removed, so installing a new skill into
163
- * `<cwd>/.code-shell/skills` or `~/.code-shell/skills` busts the cache on the
164
- * next scan — the just-installed skill becomes visible to the running session
165
- * without a restart. (Editing an existing skill's *contents* does not bump the
166
- * dir mtime; install paths additionally call invalidateSkillCache() to cover
167
- * that, so this is the passive half of a two-part guard.)
163
+ * mtime of each local skills base dir (project .code-shell/.agents + user). A
164
+ * directory's mtime changes when a child entry is added/removed, so installing
165
+ * a new skill into `<cwd>/.code-shell/skills`, `<cwd>/.agents/skills`, or
166
+ * `~/.code-shell/skills` busts the cache on the next scan — the just-installed
167
+ * skill becomes visible to the running session without a restart. (Editing an
168
+ * existing skill's *contents* does not bump the dir mtime; install paths
169
+ * additionally call invalidateSkillCache() to cover that, so this is the
170
+ * passive half of a two-part guard.)
168
171
  */
169
172
  function skillsDirsMtime(cwd) {
170
173
  return bases(cwd)
@@ -40,6 +40,8 @@ export interface BackgroundJobEntry {
40
40
  ccSessionId?: string;
41
41
  /** Files the external agent changed (parsed from its transcript, #6). */
42
42
  changedFiles?: string[];
43
+ /** Working directory for jobs that operate on the filesystem, e.g. DriveAgent. */
44
+ cwd?: string;
43
45
  }
44
46
  /** Outcome passed to finish() to record how a job ended. */
45
47
  export interface BackgroundJobOutcome {
@@ -48,11 +50,14 @@ export interface BackgroundJobOutcome {
48
50
  ccSessionId?: string;
49
51
  changedFiles?: string[];
50
52
  }
53
+ export interface BackgroundJobStartOptions {
54
+ cwd?: string;
55
+ }
51
56
  declare class BackgroundJobRegistry {
52
57
  private jobs;
53
58
  private listeners;
54
59
  /** Register a running job. Invalid sessionId is ignored (cannot be waited on). */
55
- start(jobId: string, sessionId: string, description?: string): void;
60
+ start(jobId: string, sessionId: string, description?: string, options?: BackgroundJobStartOptions): void;
56
61
  /** Mark a job terminal (retained, not deleted). Unknown id is a no-op (no
57
62
  * notify) so a double-finish or a finish after reset stays quiet. */
58
63
  finish(jobId: string, outcome?: BackgroundJobOutcome): void;
@@ -60,8 +65,12 @@ declare class BackgroundJobRegistry {
60
65
  hasRunningForSession(sessionId: string): boolean;
61
66
  /** Running jobs spawned by `sessionId`. Feeds the goal judge's task list. */
62
67
  listRunningForSession(sessionId: string): BackgroundJobEntry[];
68
+ /** Running jobs, across all sessions, that are operating in the same cwd. */
69
+ listRunningByCwd(cwd: string): BackgroundJobEntry[];
63
70
  /** All jobs (running + retained terminal) for `sessionId`. Feeds the panel. */
64
71
  listForSession(sessionId: string): BackgroundJobEntry[];
72
+ /** All jobs (running + retained terminal) across sessions. Feeds all-scope UI. */
73
+ list(): BackgroundJobEntry[];
65
74
  /** Drop every job of a session — called when the session is deleted/closed. */
66
75
  dropForSession(sessionId: string): void;
67
76
  subscribe: (cb: Listener) => (() => void);
@@ -20,6 +20,7 @@
20
20
  * loops run in the main engine process, so start/finish and the engine's wait
21
21
  * loop observe the same instance.
22
22
  */
23
+ import { normalizeCwdPath } from "../../cc-orchestrator/cwd-normalize.js";
23
24
  function isValidSessionId(sid) {
24
25
  return typeof sid === "string" && sid.length > 0;
25
26
  }
@@ -30,7 +31,7 @@ class BackgroundJobRegistry {
30
31
  jobs = new Map(); // jobId -> entry (insertion-ordered)
31
32
  listeners = new Set();
32
33
  /** Register a running job. Invalid sessionId is ignored (cannot be waited on). */
33
- start(jobId, sessionId, description = "") {
34
+ start(jobId, sessionId, description = "", options) {
34
35
  if (!isValidSessionId(sessionId))
35
36
  return;
36
37
  this.jobs.set(jobId, {
@@ -39,6 +40,7 @@ class BackgroundJobRegistry {
39
40
  description,
40
41
  status: "running",
41
42
  startedAt: Date.now(),
43
+ ...(options?.cwd ? { cwd: normalizeCwdPath(options.cwd) } : {}),
42
44
  });
43
45
  this.notify();
44
46
  }
@@ -71,10 +73,19 @@ class BackgroundJobRegistry {
71
73
  listRunningForSession(sessionId) {
72
74
  return [...this.jobs.values()].filter((e) => e.sessionId === sessionId && e.status === "running");
73
75
  }
76
+ /** Running jobs, across all sessions, that are operating in the same cwd. */
77
+ listRunningByCwd(cwd) {
78
+ const normalized = normalizeCwdPath(cwd);
79
+ return [...this.jobs.values()].filter((e) => e.status === "running" && e.cwd === normalized);
80
+ }
74
81
  /** All jobs (running + retained terminal) for `sessionId`. Feeds the panel. */
75
82
  listForSession(sessionId) {
76
83
  return [...this.jobs.values()].filter((e) => e.sessionId === sessionId);
77
84
  }
85
+ /** All jobs (running + retained terminal) across sessions. Feeds all-scope UI. */
86
+ list() {
87
+ return [...this.jobs.values()];
88
+ }
78
89
  /** Drop every job of a session — called when the session is deleted/closed. */
79
90
  dropForSession(sessionId) {
80
91
  let removed = false;
@@ -1,16 +1,3 @@
1
- /**
2
- * Unified view over the THREE kinds of async background work — background
3
- * sub-agents (asyncAgentRegistry), background jobs / video polls
4
- * (backgroundJobRegistry), and background shells (backgroundShellManager).
5
- *
6
- * Used by the goal-stop-hook to show the judge LLM what's still running, so it
7
- * can tell "the goal is done except for a finite task that will wake me" (a
8
- * download / video render → allow stop, wait for the wakeup) from "a long-lived
9
- * service that the goal doesn't depend on" (a dev server → judge the goal
10
- * normally). Replacing the old mechanical `hasRunningForSession` short-circuit:
11
- * a boolean can't distinguish a finite download from a never-ending dev server,
12
- * but the judge — given each task's kind + command — can.
13
- */
14
1
  import { type AsyncAgentStatus } from "./agent-registry.js";
15
2
  import { type BackgroundJobStatus } from "./background-jobs.js";
16
3
  import { type BgShell } from "../../runtime/background-shell.js";
@@ -30,12 +17,21 @@ export interface BackgroundWorkItem {
30
17
  /** List every still-running background work item spawned by `sessionId`. */
31
18
  export declare function listRunningBackgroundWork(sessionId: string): BackgroundWorkItem[];
32
19
  /** One background-work row for the desktop panel, discriminated by `kind`. */
33
- export type BackgroundWorkEntry = {
20
+ export interface BackgroundWorkSourceSession {
21
+ sessionId: string;
22
+ shortId: string;
23
+ title?: string;
24
+ current: boolean;
25
+ }
26
+ type WithSource<T> = T & {
27
+ sourceSession: BackgroundWorkSourceSession;
28
+ };
29
+ export type BackgroundWorkEntry = WithSource<{
34
30
  kind: "shell";
35
31
  /** Full shell snapshot — the panel already renders this shape (output/kill
36
32
  * still go through the dedicated agent/backgroundShells RPC by shellId). */
37
33
  shell: BgShell;
38
- } | {
34
+ }> | WithSource<{
39
35
  kind: "subagent";
40
36
  agentId: string;
41
37
  name?: string;
@@ -44,7 +40,7 @@ export type BackgroundWorkEntry = {
44
40
  status: AsyncAgentStatus;
45
41
  startedAt: number;
46
42
  finishedAt?: number;
47
- } | {
43
+ }> | WithSource<{
48
44
  kind: "job";
49
45
  jobId: string;
50
46
  description: string;
@@ -55,7 +51,7 @@ export type BackgroundWorkEntry = {
55
51
  finalText?: string;
56
52
  /** Files an external agent (DriveAgent) changed, parsed from its transcript. */
57
53
  changedFiles?: string[];
58
- };
54
+ }>;
59
55
  /**
60
56
  * Every background-work item spawned by `sessionId`, with per-kind detail, for
61
57
  * the desktop panel. Includes finished sub-agents that are still within their
@@ -64,4 +60,7 @@ export type BackgroundWorkEntry = {
64
60
  * keep them. Jobs are only ever present while running (the registry drops them
65
61
  * on finish).
66
62
  */
67
- export declare function listBackgroundWorkForUI(sessionId: string): BackgroundWorkEntry[];
63
+ export declare function listBackgroundWorkForUI(sessionId: string, opts?: {
64
+ scope?: "session" | "all";
65
+ }): BackgroundWorkEntry[];
66
+ export {};
@@ -11,9 +11,12 @@
11
11
  * a boolean can't distinguish a finite download from a never-ending dev server,
12
12
  * but the judge — given each task's kind + command — can.
13
13
  */
14
+ import { readFileSync, statSync } from "node:fs";
15
+ import { join } from "node:path";
14
16
  import { asyncAgentRegistry } from "./agent-registry.js";
15
17
  import { backgroundJobRegistry } from "./background-jobs.js";
16
18
  import { backgroundShellManager } from "../../runtime/background-shell.js";
19
+ import { codeShellHome } from "../../session/session-manager.js";
17
20
  /** List every still-running background work item spawned by `sessionId`. */
18
21
  export function listRunningBackgroundWork(sessionId) {
19
22
  const items = [];
@@ -39,6 +42,38 @@ export function listRunningBackgroundWork(sessionId) {
39
42
  }
40
43
  return items;
41
44
  }
45
+ const sessionTitleCache = new Map();
46
+ function shortSessionId(sessionId) {
47
+ return sessionId.length <= 10 ? sessionId : sessionId.slice(0, 10);
48
+ }
49
+ function readSessionTitle(sessionId) {
50
+ try {
51
+ const statePath = join(codeShellHome(), "sessions", sessionId, "state.json");
52
+ const st = statSync(statePath);
53
+ const cached = sessionTitleCache.get(sessionId);
54
+ if (cached && cached.mtimeMs === st.mtimeMs)
55
+ return cached.title;
56
+ const raw = JSON.parse(readFileSync(statePath, "utf8"));
57
+ const title = typeof raw.title === "string" && raw.title.trim()
58
+ ? raw.title.trim()
59
+ : typeof raw.summary === "string" && raw.summary.trim()
60
+ ? raw.summary.trim()
61
+ : undefined;
62
+ sessionTitleCache.set(sessionId, { mtimeMs: st.mtimeMs, title });
63
+ return title;
64
+ }
65
+ catch {
66
+ return undefined;
67
+ }
68
+ }
69
+ function sourceSession(currentSessionId, ownerSessionId) {
70
+ return {
71
+ sessionId: ownerSessionId,
72
+ shortId: shortSessionId(ownerSessionId),
73
+ title: readSessionTitle(ownerSessionId),
74
+ current: ownerSessionId === currentSessionId,
75
+ };
76
+ }
42
77
  /**
43
78
  * Every background-work item spawned by `sessionId`, with per-kind detail, for
44
79
  * the desktop panel. Includes finished sub-agents that are still within their
@@ -47,18 +82,24 @@ export function listRunningBackgroundWork(sessionId) {
47
82
  * keep them. Jobs are only ever present while running (the registry drops them
48
83
  * on finish).
49
84
  */
50
- export function listBackgroundWorkForUI(sessionId) {
85
+ export function listBackgroundWorkForUI(sessionId, opts = {}) {
51
86
  const entries = [];
52
- for (const s of backgroundShellManager.listForSession(sessionId)) {
53
- entries.push({ kind: "shell", shell: s });
87
+ const scope = opts.scope ?? "session";
88
+ const shells = scope === "all"
89
+ ? backgroundShellManager.list()
90
+ : backgroundShellManager.listForSession(sessionId);
91
+ for (const s of shells) {
92
+ entries.push({ kind: "shell", shell: s, sourceSession: sourceSession(sessionId, s.sessionId) });
54
93
  }
55
94
  const now = Date.now();
56
- for (const a of asyncAgentRegistry.listForSession(sessionId)) {
95
+ const agents = scope === "all" ? asyncAgentRegistry.list() : asyncAgentRegistry.listForSession(sessionId);
96
+ for (const a of agents) {
57
97
  // Keep running agents, plus finished ones still inside their fade window so
58
98
  // a completion is briefly visible. (finishedFadeAt = finishedAt + 30s.)
59
99
  const fresh = a.status === "running" || (a.finishedFadeAt != null && a.finishedFadeAt > now);
60
100
  if (!fresh)
61
101
  continue;
102
+ const ownerSessionId = a.sessionId ?? sessionId;
62
103
  entries.push({
63
104
  kind: "subagent",
64
105
  agentId: a.agentId,
@@ -68,9 +109,13 @@ export function listBackgroundWorkForUI(sessionId) {
68
109
  status: a.status,
69
110
  startedAt: a.startedAt,
70
111
  finishedAt: a.finishedAt,
112
+ sourceSession: sourceSession(sessionId, ownerSessionId),
71
113
  });
72
114
  }
73
- for (const j of backgroundJobRegistry.listForSession(sessionId)) {
115
+ const jobs = scope === "all"
116
+ ? backgroundJobRegistry.list()
117
+ : backgroundJobRegistry.listForSession(sessionId);
118
+ for (const j of jobs) {
74
119
  entries.push({
75
120
  kind: "job",
76
121
  jobId: j.jobId,
@@ -80,6 +125,7 @@ export function listBackgroundWorkForUI(sessionId) {
80
125
  ...(j.finishedAt != null ? { finishedAt: j.finishedAt } : {}),
81
126
  ...(j.finalText != null ? { finalText: j.finalText } : {}),
82
127
  ...(j.changedFiles && j.changedFiles.length ? { changedFiles: j.changedFiles } : {}),
128
+ sourceSession: sourceSession(sessionId, j.sessionId),
83
129
  });
84
130
  }
85
131
  return entries;
@@ -2,5 +2,6 @@
2
2
  * ConfigTool — read or update project settings.
3
3
  */
4
4
  import type { ToolDefinition } from "../../types.js";
5
+ import type { ToolContext } from "../context.js";
5
6
  export declare const configToolDef: ToolDefinition;
6
- export declare function configTool(args: Record<string, unknown>): Promise<string>;
7
+ export declare function configTool(args: Record<string, unknown>, ctx?: ToolContext): Promise<string>;
@@ -3,6 +3,8 @@
3
3
  */
4
4
  import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
5
5
  import { join } from "node:path";
6
+ import { setDottedSetting } from "../../settings/manager.js";
7
+ import { enforcePathPolicyWithApproval } from "../path-policy.js";
6
8
  export const configToolDef = {
7
9
  name: "Config",
8
10
  description: "Read or update the project's .code-shell/settings.json configuration. " +
@@ -26,11 +28,14 @@ export const configToolDef = {
26
28
  required: ["action"],
27
29
  },
28
30
  };
29
- export async function configTool(args) {
31
+ export async function configTool(args, ctx) {
30
32
  const action = args.action;
31
- const cwd = args.__cwd ?? process.cwd();
33
+ const cwd = ctx?.cwd ?? process.cwd();
32
34
  const configPath = join(cwd, ".code-shell", "settings.json");
33
35
  if (action === "read") {
36
+ const blocked = await enforcePathPolicyWithApproval(configPath, "read", ctx);
37
+ if (blocked)
38
+ return blocked;
34
39
  if (!existsSync(configPath)) {
35
40
  return "No project settings found. Use /init to create one.";
36
41
  }
@@ -38,6 +43,9 @@ export async function configTool(args) {
38
43
  return content;
39
44
  }
40
45
  if (action === "write") {
46
+ const blocked = await enforcePathPolicyWithApproval(configPath, "write", ctx);
47
+ if (blocked)
48
+ return blocked;
41
49
  const key = args.key;
42
50
  const value = args.value;
43
51
  if (!key)
@@ -49,16 +57,13 @@ export async function configTool(args) {
49
57
  if (existsSync(configPath)) {
50
58
  settings = JSON.parse(readFileSync(configPath, "utf-8"));
51
59
  }
52
- // Set nested key
53
- const parts = key.split(".");
54
- let obj = settings;
55
- for (let i = 0; i < parts.length - 1; i++) {
56
- if (typeof obj[parts[i]] !== "object" || obj[parts[i]] === null) {
57
- obj[parts[i]] = {};
58
- }
59
- obj = obj[parts[i]];
60
+ try {
61
+ setDottedSetting(settings, key, value);
62
+ }
63
+ catch (error) {
64
+ const message = error instanceof Error ? error.message : String(error);
65
+ return `Error: ${message}`;
60
66
  }
61
- obj[parts[parts.length - 1]] = value;
62
67
  // Never resurrect a deleted project root: a recursive mkdir of
63
68
  // <cwd>/.code-shell would recreate `cwd` itself as an empty shell when the
64
69
  // directory has been deleted (e.g. a stale session pointing at a removed
@@ -1,7 +1,10 @@
1
1
  import type { ToolDefinition } from "../../types.js";
2
2
  import type { AgentRunResult } from "../../cc-orchestrator/external-agent-driver.js";
3
3
  import type { ToolContext } from "../context.js";
4
+ import { type ExternalAgentSessionBinding, type ExternalAgentSessionRecord } from "../../cc-orchestrator/external-agent-session-store.js";
4
5
  export type DriveCli = "claude" | "codex";
6
+ export declare const DRIVE_AGENT_FOREGROUND_HANDOFF_MS = 110000;
7
+ export declare const DRIVE_AGENT_TOOL_TIMEOUT_MS = 1800000;
5
8
  export declare const driveAgentToolDef: ToolDefinition;
6
9
  type PermMode = "default" | "acceptEdits" | "bypassPermissions";
7
10
  type Runner = (opts: {
@@ -10,10 +13,20 @@ type Runner = (opts: {
10
13
  resumeSessionId?: string;
11
14
  cwd: string;
12
15
  permissionMode?: PermMode;
16
+ signal?: AbortSignal;
17
+ imagePaths?: string[];
13
18
  }) => Promise<AgentRunResult>;
19
+ type SessionStore = {
20
+ get(cli: DriveCli, sessionId: string): ExternalAgentSessionBinding | undefined;
21
+ record(binding: ExternalAgentSessionRecord): void;
22
+ };
23
+ export interface DriveAgentToolOptions {
24
+ foregroundHandoffMs?: number;
25
+ sessionStore?: SessionStore;
26
+ }
14
27
  /** Factory so tests can inject a fake runner. `fixedCli` (back-compat) forces a
15
28
  * cli and hides the `cli` arg — that's how DriveClaudeCode stays a thin alias. */
16
- export declare function makeDriveAgentTool(runner?: Runner, fixedCli?: DriveCli): (args: Record<string, unknown>, ctx?: ToolContext) => Promise<string>;
29
+ export declare function makeDriveAgentTool(runner?: Runner, fixedCli?: DriveCli, options?: DriveAgentToolOptions): (args: Record<string, unknown>, ctx?: ToolContext) => Promise<string>;
17
30
  export declare const driveAgentTool: (args: Record<string, unknown>, ctx?: ToolContext) => Promise<string>;
18
31
  export declare const driveClaudeCodeToolDef: ToolDefinition;
19
32
  /** Back-compat factory: a DriveAgent pinned to cli:"claude" with the `cli` arg
@@ -24,7 +37,8 @@ type LegacyRunner = (opts: {
24
37
  resumeSessionId?: string;
25
38
  cwd: string;
26
39
  permissionMode?: PermMode;
40
+ signal?: AbortSignal;
27
41
  }) => Promise<AgentRunResult>;
28
- export declare function makeDriveClaudeCodeTool(runner?: LegacyRunner): (args: Record<string, unknown>, ctx?: ToolContext) => Promise<string>;
42
+ export declare function makeDriveClaudeCodeTool(runner?: LegacyRunner, options?: DriveAgentToolOptions): (args: Record<string, unknown>, ctx?: ToolContext) => Promise<string>;
29
43
  export declare const driveClaudeCodeTool: (args: Record<string, unknown>, ctx?: ToolContext) => Promise<string>;
30
44
  export {};