@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.
Files changed (193) 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 +4 -0
  7. package/dist/cc-orchestrator/agent-adapter.js +11 -1
  8. package/dist/cc-orchestrator/codex-session-history.d.ts +14 -1
  9. package/dist/cc-orchestrator/codex-session-history.js +65 -5
  10. package/dist/cc-orchestrator/cwd-normalize.d.ts +2 -0
  11. package/dist/cc-orchestrator/cwd-normalize.js +19 -0
  12. package/dist/cc-orchestrator/external-agent-bindings.d.ts +27 -0
  13. package/dist/cc-orchestrator/external-agent-bindings.js +150 -0
  14. package/dist/cc-orchestrator/external-agent-changes.js +22 -5
  15. package/dist/cc-orchestrator/external-agent-driver.d.ts +1 -0
  16. package/dist/cc-orchestrator/external-agent-driver.js +265 -50
  17. package/dist/cc-orchestrator/external-agent-session-store.d.ts +23 -0
  18. package/dist/cc-orchestrator/external-agent-session-store.js +146 -0
  19. package/dist/cc-orchestrator/session-history.d.ts +35 -0
  20. package/dist/cc-orchestrator/session-history.js +98 -15
  21. package/dist/cli/agent-server-stdio.js +9 -2
  22. package/dist/context/compaction.d.ts +8 -1
  23. package/dist/context/compaction.js +49 -4
  24. package/dist/context/manager.d.ts +16 -2
  25. package/dist/context/manager.js +103 -19
  26. package/dist/credentials/access.d.ts +57 -0
  27. package/dist/credentials/access.js +185 -0
  28. package/dist/credentials/index.d.ts +3 -1
  29. package/dist/credentials/index.js +2 -0
  30. package/dist/credentials/inject-credential-tool.d.ts +3 -1
  31. package/dist/credentials/inject-credential-tool.js +30 -11
  32. package/dist/credentials/oauth.d.ts +20 -0
  33. package/dist/credentials/oauth.js +114 -0
  34. package/dist/credentials/store.d.ts +1 -0
  35. package/dist/credentials/store.js +3 -1
  36. package/dist/credentials/types.d.ts +49 -3
  37. package/dist/credentials/use-credential-tool.d.ts +9 -1
  38. package/dist/credentials/use-credential-tool.js +58 -45
  39. package/dist/engine/engine.d.ts +23 -3
  40. package/dist/engine/engine.js +380 -255
  41. package/dist/engine/goal.d.ts +17 -0
  42. package/dist/engine/goal.js +16 -6
  43. package/dist/engine/image-policy.d.ts +6 -0
  44. package/dist/engine/image-policy.js +17 -6
  45. package/dist/engine/input-attachments.d.ts +13 -0
  46. package/dist/engine/input-attachments.js +398 -0
  47. package/dist/engine/model-facade.d.ts +5 -2
  48. package/dist/engine/model-facade.js +4 -4
  49. package/dist/engine/parse-task.d.ts +10 -0
  50. package/dist/engine/parse-task.js +5 -0
  51. package/dist/engine/run-image-input.d.ts +22 -0
  52. package/dist/engine/run-image-input.js +195 -0
  53. package/dist/engine/steer-queue.d.ts +3 -1
  54. package/dist/engine/steer-queue.js +10 -2
  55. package/dist/engine/streaming-tool-queue.d.ts +11 -7
  56. package/dist/engine/streaming-tool-queue.js +11 -7
  57. package/dist/engine/turn-loop.d.ts +37 -2
  58. package/dist/engine/turn-loop.js +228 -43
  59. package/dist/engine/types.d.ts +8 -0
  60. package/dist/git/worktree/crud.d.ts +69 -0
  61. package/dist/git/worktree/crud.js +206 -0
  62. package/dist/git/worktree/diff.d.ts +14 -0
  63. package/dist/git/worktree/diff.js +82 -0
  64. package/dist/git/worktree/git-exec.d.ts +7 -0
  65. package/dist/git/worktree/git-exec.js +51 -0
  66. package/dist/git/worktree/index.d.ts +5 -0
  67. package/dist/git/worktree/index.js +5 -0
  68. package/dist/git/worktree/query.d.ts +42 -0
  69. package/dist/git/worktree/query.js +121 -0
  70. package/dist/git/worktree/slug.d.ts +11 -0
  71. package/dist/git/worktree/slug.js +58 -0
  72. package/dist/git/worktree.d.ts +1 -84
  73. package/dist/git/worktree.js +5 -230
  74. package/dist/hooks/goal-stop-hook.d.ts +33 -1
  75. package/dist/hooks/goal-stop-hook.js +202 -34
  76. package/dist/index.d.ts +31 -28
  77. package/dist/index.js +27 -25
  78. package/dist/logging/logger.js +6 -6
  79. package/dist/logging/sanitize-messages.d.ts +10 -2
  80. package/dist/logging/sanitize-messages.js +21 -6
  81. package/dist/plugins/installer/checkUpdate.d.ts +4 -1
  82. package/dist/plugins/installer/checkUpdate.js +4 -2
  83. package/dist/plugins/installer/install.js +2 -0
  84. package/dist/plugins/installer/installFromSource.js +9 -1
  85. package/dist/plugins/installer/parseSource.d.ts +4 -1
  86. package/dist/plugins/installer/parseSource.js +28 -10
  87. package/dist/plugins/installer/sourcePath.d.ts +9 -0
  88. package/dist/plugins/installer/sourcePath.js +50 -0
  89. package/dist/plugins/installer/update.d.ts +4 -1
  90. package/dist/plugins/installer/update.js +5 -3
  91. package/dist/plugins/parseMarketplaceInput.d.ts +4 -1
  92. package/dist/plugins/parseMarketplaceInput.js +4 -3
  93. package/dist/plugins/pluginInstaller.js +24 -22
  94. package/dist/preset/index.d.ts +1 -0
  95. package/dist/preset/index.js +30 -13
  96. package/dist/prompt/sections/base.md +1 -1
  97. package/dist/protocol/chat-session-manager.d.ts +2 -0
  98. package/dist/protocol/chat-session-manager.js +38 -2
  99. package/dist/protocol/chat-session.d.ts +3 -0
  100. package/dist/protocol/chat-session.js +1 -0
  101. package/dist/protocol/client.d.ts +9 -4
  102. package/dist/protocol/client.js +18 -1
  103. package/dist/protocol/server.d.ts +30 -0
  104. package/dist/protocol/server.js +247 -47
  105. package/dist/protocol/types.d.ts +49 -0
  106. package/dist/protocol/types.js +6 -0
  107. package/dist/run/FileRunStore.js +10 -1
  108. package/dist/run/Heartbeat.js +12 -0
  109. package/dist/run/RunApprovalBackend.d.ts +3 -0
  110. package/dist/run/RunApprovalBackend.js +41 -6
  111. package/dist/run/RunLock.js +2 -0
  112. package/dist/run/RunManager.d.ts +2 -0
  113. package/dist/run/RunManager.js +64 -24
  114. package/dist/run/ids.d.ts +2 -0
  115. package/dist/run/ids.js +23 -0
  116. package/dist/runtime/background-shell.d.ts +1 -0
  117. package/dist/runtime/background-shell.js +23 -13
  118. package/dist/runtime/spawn-common.js +10 -0
  119. package/dist/services/auto-dream.d.ts +15 -4
  120. package/dist/services/auto-dream.js +20 -20
  121. package/dist/services/dream-consolidation.d.ts +2 -3
  122. package/dist/services/dream-consolidation.js +65 -15
  123. package/dist/services/extract-memories.d.ts +14 -5
  124. package/dist/services/extract-memories.js +20 -3
  125. package/dist/services/global-dream-promotion.d.ts +23 -0
  126. package/dist/services/global-dream-promotion.js +112 -0
  127. package/dist/services/memory-orchestrator.js +347 -34
  128. package/dist/session/memory.d.ts +61 -18
  129. package/dist/session/memory.js +342 -79
  130. package/dist/session/session-manager.d.ts +35 -1
  131. package/dist/session/session-manager.js +224 -4
  132. package/dist/session/transcript.d.ts +1 -1
  133. package/dist/session/transcript.js +17 -5
  134. package/dist/settings/manager.d.ts +1 -0
  135. package/dist/settings/manager.js +87 -37
  136. package/dist/settings/schema-export.d.ts +2 -3
  137. package/dist/settings/schema-export.js +2 -3
  138. package/dist/settings/schema.d.ts +21 -0
  139. package/dist/settings/schema.js +12 -0
  140. package/dist/skills/scanner.d.ts +3 -2
  141. package/dist/skills/scanner.js +12 -9
  142. package/dist/tool-system/builtin/agent-notifications.d.ts +11 -4
  143. package/dist/tool-system/builtin/agent-notifications.js +19 -7
  144. package/dist/tool-system/builtin/background-jobs.d.ts +35 -6
  145. package/dist/tool-system/builtin/background-jobs.js +116 -7
  146. package/dist/tool-system/builtin/background-work.d.ts +17 -18
  147. package/dist/tool-system/builtin/background-work.js +51 -5
  148. package/dist/tool-system/builtin/config.d.ts +2 -1
  149. package/dist/tool-system/builtin/config.js +16 -11
  150. package/dist/tool-system/builtin/cron-list.definition.d.ts +3 -0
  151. package/dist/tool-system/builtin/cron-list.definition.js +6 -0
  152. package/dist/tool-system/builtin/cron.d.ts +1 -2
  153. package/dist/tool-system/builtin/cron.js +9 -7
  154. package/dist/tool-system/builtin/drive-claude-code.d.ts +23 -2
  155. package/dist/tool-system/builtin/drive-claude-code.js +589 -48
  156. package/dist/tool-system/builtin/edit.js +5 -2
  157. package/dist/tool-system/builtin/generate-video.d.ts +1 -0
  158. package/dist/tool-system/builtin/generate-video.js +13 -4
  159. package/dist/tool-system/builtin/index.d.ts +8 -3
  160. package/dist/tool-system/builtin/index.js +50 -22
  161. package/dist/tool-system/builtin/lsp.d.ts +2 -1
  162. package/dist/tool-system/builtin/lsp.js +6 -3
  163. package/dist/tool-system/builtin/memory.js +40 -8
  164. package/dist/tool-system/builtin/notebook-edit.js +5 -2
  165. package/dist/tool-system/builtin/powershell.d.ts +5 -2
  166. package/dist/tool-system/builtin/powershell.js +11 -7
  167. package/dist/tool-system/builtin/read.js +118 -6
  168. package/dist/tool-system/builtin/sleep.d.ts +1 -2
  169. package/dist/tool-system/builtin/sleep.definition.d.ts +8 -0
  170. package/dist/tool-system/builtin/sleep.definition.js +28 -0
  171. package/dist/tool-system/builtin/sleep.js +1 -22
  172. package/dist/tool-system/builtin/view-image.d.ts +2 -2
  173. package/dist/tool-system/builtin/view-image.js +109 -19
  174. package/dist/tool-system/builtin/worktree.d.ts +4 -4
  175. package/dist/tool-system/builtin/worktree.js +297 -74
  176. package/dist/tool-system/builtin/write.js +5 -3
  177. package/dist/tool-system/context.d.ts +41 -1
  178. package/dist/tool-system/executor.d.ts +1 -5
  179. package/dist/tool-system/executor.js +94 -115
  180. package/dist/tool-system/mcp-manager.d.ts +31 -6
  181. package/dist/tool-system/mcp-manager.js +193 -78
  182. package/dist/tool-system/path-policy.d.ts +2 -0
  183. package/dist/tool-system/path-policy.js +41 -12
  184. package/dist/tool-system/permission.d.ts +28 -7
  185. package/dist/tool-system/permission.js +130 -49
  186. package/dist/tool-system/registry.js +11 -4
  187. package/dist/tool-system/tool-result-redaction.d.ts +7 -0
  188. package/dist/tool-system/tool-result-redaction.js +48 -0
  189. package/dist/tool-system/workspace-bridge.d.ts +11 -0
  190. package/dist/tool-system/workspace-bridge.js +1 -0
  191. package/dist/types.d.ts +78 -11
  192. package/dist/utils/toolDisplay.js +1 -1
  193. package/package.json +4 -3
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import { readFile, writeFile } from "node:fs/promises";
5
5
  import { existsSync } from "node:fs";
6
+ import { isAbsolute, resolve } from "node:path";
6
7
  import { fileCache } from "./file-cache.js";
7
8
  import { detectEol, toLf, applyEol } from "./eol.js";
8
9
  export const editToolDef = {
@@ -32,11 +33,11 @@ export const editToolDef = {
32
33
  },
33
34
  };
34
35
  export async function editTool(args, ctx) {
35
- const filePath = args.file_path;
36
+ const rawPath = args.file_path;
36
37
  const oldString = args.old_string;
37
38
  const newString = args.new_string;
38
39
  const replaceAll = args.replace_all ?? false;
39
- if (!filePath)
40
+ if (!rawPath)
40
41
  return "Error: file_path is required";
41
42
  if (oldString === undefined)
42
43
  return "Error: old_string is required";
@@ -44,6 +45,8 @@ export async function editTool(args, ctx) {
44
45
  return "Error: new_string is required";
45
46
  if (oldString === newString)
46
47
  return "Error: old_string and new_string must be different";
48
+ const cwd = ctx?.cwd ?? process.cwd();
49
+ const filePath = isAbsolute(rawPath) ? rawPath : resolve(cwd, rawPath);
47
50
  if (!existsSync(filePath))
48
51
  return `Error: File not found: ${filePath}`;
49
52
  try {
@@ -18,6 +18,7 @@ import type { ToolDefinition } from "../../types.js";
18
18
  import type { ToolContext } from "../context.js";
19
19
  import { type VideoProvider, type VideoProviderCreds } from "./video-providers.js";
20
20
  import { type ImageUploader, type UploaderCreds } from "./image-uploader.js";
21
+ export declare function __resolveLocalImageInputForTests(pathOrUrl: string, cwd: string): string;
21
22
  /**
22
23
  * Normalize image inputs (URLs or local paths) into public URLs the provider
23
24
  * can consume. `images[]` wins over the single `image`. Local paths are
@@ -15,17 +15,22 @@
15
15
  * "no video provider configured" message) rather than half-working.
16
16
  */
17
17
  import { writeFile, mkdir } from "node:fs/promises";
18
- import { join } from "node:path";
18
+ import { isAbsolute, join, resolve } from "node:path";
19
19
  import { SettingsManager } from "../../settings/manager.js";
20
20
  import { notificationQueue } from "./agent-notifications.js";
21
21
  import { backgroundJobRegistry } from "./background-jobs.js";
22
22
  import { logger } from "../../logging/logger.js";
23
23
  import { getVideoProvider, DEFAULT_VIDEO_MODEL, } from "./video-providers.js";
24
- import { getImageUploader } from "./image-uploader.js";
24
+ import { getImageUploader, isHttpUrl } from "./image-uploader.js";
25
25
  import { effectiveApiKey } from "./generate-image.js";
26
26
  import { getMergedCatalog, findCatalogEntry } from "../../model-catalog/index.js";
27
27
  import { genInstancesFromConnections } from "../../model-catalog/gen-connections.js";
28
28
  const MAX_IMAGES = 9;
29
+ export function __resolveLocalImageInputForTests(pathOrUrl, cwd) {
30
+ if (isHttpUrl(pathOrUrl))
31
+ return pathOrUrl;
32
+ return isAbsolute(pathOrUrl) ? pathOrUrl : resolve(cwd, pathOrUrl);
33
+ }
29
34
  /**
30
35
  * Normalize image inputs (URLs or local paths) into public URLs the provider
31
36
  * can consume. `images[]` wins over the single `image`. Local paths are
@@ -230,9 +235,13 @@ export async function generateVideoTool(args, ctx) {
230
235
  const sessionId = ctx?.sessionId;
231
236
  const preferKind = typeof args.provider === "string" && args.provider ? args.provider : undefined;
232
237
  const overrideModel = typeof args.model === "string" && args.model ? args.model : undefined;
233
- const image = typeof args.image === "string" && args.image ? args.image : undefined;
238
+ const image = typeof args.image === "string" && args.image
239
+ ? __resolveLocalImageInputForTests(args.image, cwd)
240
+ : undefined;
234
241
  const imagesArg = Array.isArray(args.images)
235
- ? args.images.filter((x) => typeof x === "string")
242
+ ? args.images
243
+ .filter((x) => typeof x === "string")
244
+ .map((x) => __resolveLocalImageInputForTests(x, cwd))
236
245
  : undefined;
237
246
  // videos pass through verbatim to fal's video_urls (no upload) — http(s) only.
238
247
  const videosArg = Array.isArray(args.videos)
@@ -19,13 +19,18 @@ import type { ToolVisibilityContext } from "../context.js";
19
19
  * registry 会把它放进 ToolResult.contentBlocks。可选的 `result` 字段是给
20
20
  * transcript / 摘要用的纯文本镜像。沙箱执行类工具(Bash 等)可返回
21
21
  * `{ result, sandbox }`,registry 把 sandbox 透传到 ToolResult.sandbox 供 UI 显示。
22
+ * 敏感结果可返回 `{ result, sensitive, displayResult, transcriptResult }`;
23
+ * `result` 仅供当前模型轮使用,显示/持久化路径必须使用占位字段。
22
24
  */
23
25
  export type BuiltinToolResult = string | {
24
26
  contentBlocks: import("../../types.js").ContentBlock[];
25
27
  result?: string;
26
28
  } | {
27
29
  result: string;
28
- sandbox: import("../../types.js").ToolResult["sandbox"];
30
+ sandbox?: import("../../types.js").ToolResult["sandbox"];
31
+ sensitive?: boolean;
32
+ displayResult?: string;
33
+ transcriptResult?: string;
29
34
  };
30
35
  export type BuiltinToolFn = (args: Record<string, unknown>, ctx?: import("../context.js").ToolContext) => Promise<BuiltinToolResult>;
31
36
  export type BuiltinToolGuard = (ctx: ToolVisibilityContext) => boolean;
@@ -41,5 +46,5 @@ export declare const BUILTIN_TOOLS: BuiltinTool[];
41
46
  * Keyed by the tool's `name` (must match the toolDef name).
42
47
  */
43
48
  export declare const BUILTIN_TOOL_GUARDS: Map<string, BuiltinToolGuard>;
44
- /** UseCredential is available when the cwd's CredentialStore has ≥1 credential. */
45
- export declare function isUseCredentialAvailable(cwd: string): boolean;
49
+ /** UseCredential is available when the cwd's credential metadata has ≥1 entry. */
50
+ export declare function isUseCredentialAvailable(cwd: string, settingsScope?: import("../../settings/manager.js").SettingsScope): boolean;
@@ -3,9 +3,9 @@
3
3
  */
4
4
  import { readToolDef, readTool } from "./read.js";
5
5
  import { writeToolDef, writeTool } from "./write.js";
6
- import { generateImageToolDef, generateImageTool, isGenerateImageAvailable } from "./generate-image.js";
6
+ import { generateImageToolDef, generateImageTool, isGenerateImageAvailable, } from "./generate-image.js";
7
7
  import { editModelCatalogToolDef, editModelCatalogTool } from "./edit-model-catalog.js";
8
- import { generateVideoToolDef, generateVideoTool, isGenerateVideoAvailable } from "./generate-video.js";
8
+ import { generateVideoToolDef, generateVideoTool, isGenerateVideoAvailable, } from "./generate-video.js";
9
9
  import { viewImageToolDef, viewImageTool } from "./view-image.js";
10
10
  import { editToolDef, editTool } from "./edit.js";
11
11
  import { applyPatchToolDef, applyPatchTool } from "./apply-patch/index.js";
@@ -16,19 +16,21 @@ import { webSearchToolDef, webSearchTool, isWebSearchAvailable } from "./web-sea
16
16
  import { webFetchToolDef, webFetchTool } from "./web-fetch.js";
17
17
  import { askUserToolDef, askUserTool } from "./ask-user.js";
18
18
  import { agentToolDef, agentTool, agentStatusToolDef, agentStatusTool, agentCancelToolDef, agentCancelTool, agentSendInputToolDef, agentSendInputTool, } from "./agent.js";
19
- import { enterPlanModeToolDef, enterPlanModeTool, exitPlanModeToolDef, exitPlanModeTool } from "./plan.js";
19
+ import { enterPlanModeToolDef, enterPlanModeTool, exitPlanModeToolDef, exitPlanModeTool, } from "./plan.js";
20
20
  import { toolSearchToolDef, toolSearchTool } from "./tool-search.js";
21
21
  import { todoWriteToolDef, todoWriteTool } from "./task.js";
22
- import { enterWorktreeToolDef, enterWorktreeTool, exitWorktreeToolDef, exitWorktreeTool } from "./worktree.js";
23
- import { sleepToolDef, sleepTool } from "./sleep.js";
22
+ import { enterWorktreeToolDef, enterWorktreeTool, exitWorktreeToolDef, exitWorktreeTool, switchSessionWorkspaceToolDef, switchSessionWorkspaceTool, } from "./worktree.js";
23
+ import { sleepToolDef } from "./sleep.definition.js";
24
+ import { sleepTool } from "./sleep.js";
24
25
  import { configToolDef, configTool } from "./config.js";
25
26
  import { notebookEditToolDef, notebookEditTool } from "./notebook-edit.js";
26
27
  import { lspToolDef, lspTool } from "./lsp.js";
27
- import { cronCreateToolDef, cronCreateTool, cronDeleteToolDef, cronDeleteTool, cronListToolDef, cronListTool } from "./cron.js";
28
- import { driveClaudeCodeToolDef, driveClaudeCodeTool, driveAgentToolDef, driveAgentTool } from "./drive-claude-code.js";
28
+ import { cronCreateToolDef, cronCreateTool, cronDeleteToolDef, cronDeleteTool, cronListTool, } from "./cron.js";
29
+ import { cronListToolDef } from "./cron-list.definition.js";
30
+ import { driveClaudeCodeToolDef, driveClaudeCodeTool, driveAgentToolDef, driveAgentTool, driveAgentJobsToolDef, driveAgentJobsTool, DRIVE_AGENT_TOOL_TIMEOUT_MS, } from "./drive-claude-code.js";
29
31
  import { checkQuotaToolDef, checkQuotaTool } from "./check-quota.js";
30
32
  import { skillToolDef, skillTool } from "./skill.js";
31
- import { mcpToolDef, mcpToolExecute, listMcpResourcesToolDef, listMcpResourcesTool, readMcpResourceToolDef, readMcpResourceTool } from "./mcp-tools.js";
33
+ import { mcpToolDef, mcpToolExecute, listMcpResourcesToolDef, listMcpResourcesTool, readMcpResourceToolDef, readMcpResourceTool, } from "./mcp-tools.js";
32
34
  import { replToolDef, replTool } from "./repl.js";
33
35
  import { briefToolDef, briefTool } from "./brief.js";
34
36
  import { powershellToolDef, powershellTool } from "./powershell.js";
@@ -39,9 +41,9 @@ import { cancelGoalToolDef, cancelGoalTool } from "./cancel-goal.js";
39
41
  import { addMarketplaceToolDef, addMarketplaceTool } from "./add-marketplace.js";
40
42
  import { bashOutputToolDef, bashOutputTool, killShellToolDef, killShellTool, listShellsToolDef, listShellsTool, } from "./background-shell-tools.js";
41
43
  import { browserObserveToolDef, browserObserveTool, browserActToolDef, browserActTool, browserNavigateToolDef, browserNavigateTool, } from "./browser-tools.js";
42
- import { useCredentialToolDef, useCredentialTool } from "../../credentials/use-credential-tool.js";
44
+ import { useCredentialToolDef, useCredentialBuiltinTool, } from "../../credentials/use-credential-tool.js";
43
45
  import { injectCredentialToolDef, injectCredentialTool, isInjectCredentialAvailable, } from "../../credentials/inject-credential-tool.js";
44
- import { CredentialStore } from "../../credentials/store.js";
46
+ import { credentialAccessScope, getCredentialAccess } from "../../credentials/access.js";
45
47
  export const BUILTIN_TOOLS = [
46
48
  {
47
49
  definition: {
@@ -69,7 +71,7 @@ export const BUILTIN_TOOLS = [
69
71
  definition: {
70
72
  ...editModelCatalogToolDef,
71
73
  source: "builtin",
72
- permissionDefault: "ask", // writes user config confirm before each write
74
+ permissionDefault: "ask", // UI hint; default classifier fallback confirms writes.
73
75
  isReadOnly: false,
74
76
  isConcurrencySafe: false, // serializes writes to the single catalog file
75
77
  },
@@ -344,6 +346,16 @@ export const BUILTIN_TOOLS = [
344
346
  },
345
347
  execute: exitWorktreeTool,
346
348
  },
349
+ {
350
+ definition: {
351
+ ...switchSessionWorkspaceToolDef,
352
+ source: "builtin",
353
+ permissionDefault: "ask",
354
+ isReadOnly: false,
355
+ isConcurrencySafe: false,
356
+ },
357
+ execute: switchSessionWorkspaceTool,
358
+ },
347
359
  // ─── Phase 5: Utility Tools ────────────────────────────────────
348
360
  {
349
361
  definition: {
@@ -433,9 +445,21 @@ export const BUILTIN_TOOLS = [
433
445
  permissionDefault: "ask",
434
446
  isReadOnly: false,
435
447
  isConcurrencySafe: false,
448
+ timeoutMs: DRIVE_AGENT_TOOL_TIMEOUT_MS,
449
+ pathPolicy: [{ kind: "arg", arg: "attachmentPaths", operation: "read" }],
436
450
  },
437
451
  execute: driveAgentTool,
438
452
  },
453
+ {
454
+ definition: {
455
+ ...driveAgentJobsToolDef,
456
+ source: "builtin",
457
+ permissionDefault: "allow",
458
+ isReadOnly: false,
459
+ isConcurrencySafe: false,
460
+ },
461
+ execute: driveAgentJobsTool,
462
+ },
439
463
  // Back-compat alias: DriveClaudeCode = DriveAgent pinned to cli:claude. Kept
440
464
  // registered so old prompts/memories that name DriveClaudeCode still resolve.
441
465
  {
@@ -445,6 +469,8 @@ export const BUILTIN_TOOLS = [
445
469
  permissionDefault: "ask",
446
470
  isReadOnly: false,
447
471
  isConcurrencySafe: false,
472
+ timeoutMs: DRIVE_AGENT_TOOL_TIMEOUT_MS,
473
+ pathPolicy: [{ kind: "arg", arg: "attachmentPaths", operation: "read" }],
448
474
  },
449
475
  execute: driveClaudeCodeTool,
450
476
  },
@@ -638,7 +664,7 @@ export const BUILTIN_TOOLS = [
638
664
  },
639
665
  // Browser automation — 3 semantic tools driving the in-app webview via the
640
666
  // BrowserBridge (CDP). All serial on one webview (isConcurrencySafe:false).
641
- // browser_observe is read-only. browser_act is permissionDefault "allow"; its
667
+ // browser_observe is read-only. browser_act declares a UI hint of allow; its
642
668
  // sensitive actions (click/type/select) are escalated to "ask" by a preset
643
669
  // PermissionRule keyed on argsPattern { action } (see preset/index.ts §4.6) —
644
670
  // so one tool carries per-action gating. Sensitive-action + domain-whitelist
@@ -659,7 +685,7 @@ export const BUILTIN_TOOLS = [
659
685
  definition: {
660
686
  ...browserActToolDef,
661
687
  source: "builtin",
662
- permissionDefault: "allow", // per-action gating via preset rule (argsPattern.action)
688
+ permissionDefault: "allow", // UI hint; per-action execution gating is the preset rule.
663
689
  isReadOnly: false,
664
690
  isConcurrencySafe: false,
665
691
  timeoutMs: 30_000, // the wait action internally bounds; give RPC headroom
@@ -677,8 +703,8 @@ export const BUILTIN_TOOLS = [
677
703
  execute: browserNavigateTool,
678
704
  },
679
705
  // ─── Credentials: AI 取用已存凭证(token/link/cookie) ──────────
680
- // permissionDefault:"allow" —— 取用审批由工具内部的 CredentialUseGate 负责
681
- // (默认问/本会话记住/全自动),不走工具级权限层,避免双重弹窗。
706
+ // permissionDefault:"allow" 是展示/声明 hint;取用审批由工具内部的
707
+ // CredentialUseGate 负责(默认问/本会话记住/全自动),避免双重弹窗。
682
708
  // 读取凭证库本身不写文件(cookie 物化成临时 cookies.txt 是用完即弃的副产物)。
683
709
  {
684
710
  definition: {
@@ -688,10 +714,10 @@ export const BUILTIN_TOOLS = [
688
714
  isReadOnly: true,
689
715
  isConcurrencySafe: true,
690
716
  },
691
- execute: useCredentialTool,
717
+ execute: useCredentialBuiltinTool,
692
718
  },
693
719
  // InjectCredential:把 cookie 凭证注入内置浏览器(恢复登录态)。审批由工具内部
694
- // CredentialUseGate 负责(逐条 autoInjectByAI),故 permissionDefault:"allow"。
720
+ // CredentialUseGate 负责(逐条 autoInjectByAI),permissionDefault:"allow" 仅作展示 hint
695
721
  // 改浏览器登录态有副作用 → 非 read-only。
696
722
  {
697
723
  definition: {
@@ -718,15 +744,17 @@ export const BUILTIN_TOOL_GUARDS = new Map([
718
744
  // of the tool list (and the context) for the common no-credentials case,
719
745
  // matching the spec's "quiet when empty" intent (true ToolSearch-deferral for
720
746
  // builtins isn't wired in the engine).
721
- [useCredentialToolDef.name, (ctx) => isUseCredentialAvailable(ctx.cwd)],
747
+ [useCredentialToolDef.name, (ctx) => isUseCredentialAvailable(ctx.cwd, ctx.settingsScope)],
722
748
  // InjectCredential hidden until ≥1 cookie credential exists (browser injection
723
749
  // is cookie-only). Also degrades at call time if no browser bridge is wired.
724
- [injectCredentialToolDef.name, (ctx) => isInjectCredentialAvailable(ctx.cwd)],
750
+ [injectCredentialToolDef.name, (ctx) => isInjectCredentialAvailable(ctx.cwd, ctx.settingsScope)],
751
+ [completeGoalToolDef.name, (ctx) => ctx.hasGoal === true],
752
+ [cancelGoalToolDef.name, (ctx) => ctx.hasGoal === true],
725
753
  ]);
726
- /** UseCredential is available when the cwd's CredentialStore has ≥1 credential. */
727
- export function isUseCredentialAvailable(cwd) {
754
+ /** UseCredential is available when the cwd's credential metadata has ≥1 entry. */
755
+ export function isUseCredentialAvailable(cwd, settingsScope) {
728
756
  try {
729
- return new CredentialStore(cwd).listMasked().length > 0;
757
+ return getCredentialAccess().listMasked(cwd, credentialAccessScope(settingsScope)).length > 0;
730
758
  }
731
759
  catch {
732
760
  return false;
@@ -2,5 +2,6 @@
2
2
  * LSPTool — language server protocol operations for code intelligence.
3
3
  */
4
4
  import type { ToolDefinition } from "../../types.js";
5
+ import type { ToolContext } from "../context.js";
5
6
  export declare const lspToolDef: ToolDefinition;
6
- export declare function lspTool(args: Record<string, unknown>): Promise<string>;
7
+ export declare function lspTool(args: Record<string, unknown>, ctx?: ToolContext): Promise<string>;
@@ -4,6 +4,7 @@
4
4
  import { getLSPManager } from "../../lsp/manager.js";
5
5
  import { detectLSPServer } from "../../lsp/servers.js";
6
6
  import { pathToFileURL } from "node:url";
7
+ import { isAbsolute, resolve } from "node:path";
7
8
  export const lspToolDef = {
8
9
  name: "LSP",
9
10
  description: "Use Language Server Protocol for code intelligence operations. " +
@@ -33,13 +34,15 @@ export const lspToolDef = {
33
34
  required: ["action", "file_path"],
34
35
  },
35
36
  };
36
- export async function lspTool(args) {
37
+ export async function lspTool(args, ctx) {
37
38
  const action = args.action;
38
- const filePath = args.file_path;
39
+ const rawPath = args.file_path;
39
40
  const line = args.line ?? 0;
40
41
  const character = args.character ?? 0;
41
- if (!filePath)
42
+ if (!rawPath)
42
43
  return "Error: file_path is required";
44
+ const cwd = ctx?.cwd ?? process.cwd();
45
+ const filePath = isAbsolute(rawPath) ? rawPath : resolve(cwd, rawPath);
43
46
  const manager = getLSPManager();
44
47
  if (!manager)
45
48
  return "Error: LSP is not initialized. Language servers are not available.";
@@ -17,9 +17,10 @@
17
17
  import { MemoryManager } from "../../session/memory.js";
18
18
  const VALID_SCOPES = ["user", "dream"];
19
19
  const VALID_TYPES = ["user", "feedback", "project", "reference"];
20
+ const VALID_ORIGINS = ["auto", "manual", "dream"];
20
21
  function parseScope(raw) {
21
22
  if (typeof raw !== "string")
22
- return "Error: scope is required (\"user\" or \"dream\")";
23
+ return 'Error: scope is required ("user" or "dream")';
23
24
  if (!VALID_SCOPES.includes(raw)) {
24
25
  return `Error: scope must be "user" or "dream", got "${raw}"`;
25
26
  }
@@ -30,6 +31,11 @@ function parseScope(raw) {
30
31
  function parseLocation(raw) {
31
32
  return raw === "global" ? "global" : "project";
32
33
  }
34
+ function parseOrigin(raw) {
35
+ return typeof raw === "string" && VALID_ORIGINS.includes(raw)
36
+ ? raw
37
+ : undefined;
38
+ }
33
39
  function mmFor(ctx, scope, location = "project") {
34
40
  // location=global → omit projectDir so the manager points at the global store.
35
41
  return new MemoryManager({
@@ -46,7 +52,7 @@ const LOCATION_SCHEMA = {
46
52
  export const memoryListToolDef = {
47
53
  name: "MemoryList",
48
54
  description: "List persistent memory entries from one scope. " +
49
- "Returns each entry's name, type, and short description (not the full content — use MemoryRead for that). " +
55
+ "Returns each entry's id, origin, counts, name, type, and short description (not the full content — use MemoryRead for that). " +
50
56
  "Use this before MemorySave/MemoryDelete to find the exact name to target. " +
51
57
  'Scopes: "user" (entries the user owns; you need permission to modify) or "dream" (auto-consolidation workspace; you may freely modify).',
52
58
  inputSchema: {
@@ -73,7 +79,9 @@ export async function memoryListTool(args, ctx) {
73
79
  if (entries.length === 0)
74
80
  return `(no memories in scope "${scope}")`;
75
81
  return entries
76
- .map((e) => `- [${e.type}] ${e.name} ${e.description}`)
82
+ .map((e) => `- [${e.type}] ${e.name} ` +
83
+ `(id:${e.id ?? "(none)"}, origin:${e.origin ?? "manual"}, use:${e.useCount ?? 0}, updates:${e.updateCount ?? 0}) — ` +
84
+ e.description)
77
85
  .join("\n");
78
86
  }
79
87
  catch (err) {
@@ -127,15 +135,24 @@ export async function memoryReadTool(args, ctx) {
127
135
  if (cb) {
128
136
  // scope here is always "user"|"dream" (validated above); pending is
129
137
  // never tool-readable, so the narrower event type is correct.
130
- void cb({ type: "memory_recalled", name: entry.name, scope: scope, location });
138
+ void cb({
139
+ type: "memory_recalled",
140
+ name: entry.name,
141
+ scope: scope,
142
+ location,
143
+ });
131
144
  }
132
145
  }
133
146
  catch {
134
147
  // ignore — the read result below is what matters
135
148
  }
136
149
  return (`name: ${entry.name}\n` +
150
+ `id: ${entry.id ?? ""}\n` +
137
151
  `description: ${entry.description}\n` +
138
152
  `type: ${entry.type}\n` +
153
+ `origin: ${entry.origin ?? "manual"}\n` +
154
+ `useCount: ${entry.useCount ?? 0}\n` +
155
+ `updateCount: ${entry.updateCount ?? 0}\n` +
139
156
  `\n${entry.content}`);
140
157
  }
141
158
  catch (err) {
@@ -145,7 +162,7 @@ export async function memoryReadTool(args, ctx) {
145
162
  // ─── MemorySave ────────────────────────────────────────────────────────────
146
163
  export const memorySaveToolDef = {
147
164
  name: "MemorySave",
148
- description: "Create or overwrite a memory entry. Same name overwrite. " +
165
+ description: "Create or update a memory entry. Before saving, scan the injected memory index and/or call MemoryList; for the same durable topic, update the existing entry by id instead of creating date-stamped variants. " +
149
166
  'Saving to scope "user" requires user permission (you will see a confirmation prompt). ' +
150
167
  'Saving to scope "dream" is automatic — it is your auto-consolidation workspace. ' +
151
168
  "Pick `type` carefully: " +
@@ -154,7 +171,7 @@ export const memorySaveToolDef = {
154
171
  "project (non-obvious facts about ongoing work), " +
155
172
  "reference (pointers to external resources). " +
156
173
  "Pick `location`: global (a lesson/preference true in ANY project) vs project (this repo only). " +
157
- "If a memory in the injected index is now stale or wrong, overwrite it (same name) or MemoryDelete it — keep the store correct rather than letting contradictions pile up. " +
174
+ "If a memory in the injected index is now stale or wrong, update it by id or MemoryDelete it — keep the store correct rather than letting contradictions pile up. " +
158
175
  "The `description` is a one-line summary shown in the index; the `content` is the full body.",
159
176
  inputSchema: {
160
177
  type: "object",
@@ -165,9 +182,13 @@ export const memorySaveToolDef = {
165
182
  description: "Which scope to save to",
166
183
  },
167
184
  location: LOCATION_SCHEMA,
185
+ id: {
186
+ type: "string",
187
+ description: "Stable id from MemoryList/MemoryRead when updating an existing memory. Omit only for genuinely new topics.",
188
+ },
168
189
  name: {
169
190
  type: "string",
170
- description: "Short kebab-case identifier (also becomes the filename slug)",
191
+ description: "Short stable topic identifier; avoid dates, versions, or batch suffixes",
171
192
  },
172
193
  description: {
173
194
  type: "string",
@@ -192,11 +213,14 @@ export async function memorySaveTool(args, ctx) {
192
213
  return scope;
193
214
  }
194
215
  const name = args.name;
216
+ const id = args.id;
195
217
  const description = args.description;
196
218
  const type = args.type;
197
219
  const content = args.content;
198
220
  if (typeof name !== "string" || !name)
199
221
  return "Error: name is required";
222
+ if (id !== undefined && typeof id !== "string")
223
+ return "Error: id must be a string";
200
224
  if (typeof description !== "string")
201
225
  return "Error: description is required";
202
226
  if (typeof content !== "string")
@@ -207,12 +231,20 @@ export async function memorySaveTool(args, ctx) {
207
231
  try {
208
232
  const location = parseLocation(args.location);
209
233
  const mm = mmFor(ctx, scope, location);
234
+ const dreamLoop = ctx?.__dreamLoop === true;
235
+ const forcedOrigin = dreamLoop
236
+ ? "dream"
237
+ : scope === "user"
238
+ ? "manual"
239
+ : (parseOrigin(args.origin) ?? "manual");
210
240
  const fileName = mm.save({
241
+ id,
211
242
  name,
212
243
  description,
213
244
  type: type,
214
245
  content,
215
- });
246
+ origin: forcedOrigin,
247
+ }, { forceOrigin: forcedOrigin });
216
248
  return `Saved memory "${name}" → ${location}/${scope}/${fileName}`;
217
249
  }
218
250
  catch (err) {
@@ -2,6 +2,7 @@
2
2
  * NotebookEditTool — read and edit Jupyter notebook (.ipynb) cells.
3
3
  */
4
4
  import { readFileSync, writeFileSync, existsSync } from "node:fs";
5
+ import { isAbsolute, resolve } from "node:path";
5
6
  export const notebookEditToolDef = {
6
7
  name: "NotebookEdit",
7
8
  description: "Edit a Jupyter notebook (.ipynb) file. Supports actions: " +
@@ -37,10 +38,12 @@ export const notebookEditToolDef = {
37
38
  },
38
39
  };
39
40
  export async function notebookEditTool(args, ctx) {
40
- const filePath = args.file_path;
41
+ const rawPath = args.file_path;
41
42
  const action = args.action;
42
- if (!filePath)
43
+ if (!rawPath)
43
44
  return "Error: file_path is required";
45
+ const cwd = ctx?.cwd ?? process.cwd();
46
+ const filePath = isAbsolute(rawPath) ? rawPath : resolve(cwd, rawPath);
44
47
  if (!filePath.endsWith(".ipynb"))
45
48
  return "Error: file must be a .ipynb file";
46
49
  if (action === "read") {
@@ -5,7 +5,10 @@
5
5
  * centralized in {@link safeSpawn}; this file only carries the pwsh /
6
6
  * powershell.exe selection + the PowerShell-specific output formatting.
7
7
  */
8
- import type { ToolDefinition } from "../../types.js";
8
+ import type { ToolDefinition, ToolResult } from "../../types.js";
9
9
  import type { ToolContext } from "../context.js";
10
10
  export declare const powershellToolDef: ToolDefinition;
11
- export declare function powershellTool(args: Record<string, unknown>, ctx?: ToolContext): Promise<string>;
11
+ export declare function powershellTool(args: Record<string, unknown>, ctx?: ToolContext): Promise<string | {
12
+ result: string;
13
+ sandbox: ToolResult["sandbox"];
14
+ }>;
@@ -28,6 +28,10 @@ export const powershellToolDef = {
28
28
  },
29
29
  };
30
30
  const PS_MAX_BUFFER = 5 * 1024 * 1024;
31
+ const POWERSHELL_SANDBOX_MARK = { backend: "off" };
32
+ function markPowerShellResult(result) {
33
+ return { result, sandbox: POWERSHELL_SANDBOX_MARK };
34
+ }
31
35
  export async function powershellTool(args, ctx) {
32
36
  const command = args.command;
33
37
  // `??` only catches null/undefined — a non-positive timeout (0/-5) would slip
@@ -35,7 +39,7 @@ export async function powershellTool(args, ctx) {
35
39
  const rawTimeout = args.timeout;
36
40
  const timeout = typeof rawTimeout === "number" && rawTimeout > 0 ? rawTimeout : 120_000;
37
41
  if (!command.trim()) {
38
- return "Error: command is required.";
42
+ return markPowerShellResult("Error: command is required.");
39
43
  }
40
44
  // Determine PowerShell executable.
41
45
  const psCmd = process.platform === "win32" ? "powershell.exe" : "pwsh";
@@ -52,19 +56,19 @@ export async function powershellTool(args, ctx) {
52
56
  signal: ctx?.signal,
53
57
  });
54
58
  if (result.aborted) {
55
- return wasAbortedBeforeStart
59
+ return markPowerShellResult(wasAbortedBeforeStart
56
60
  ? "PowerShell aborted before starting."
57
- : "PowerShell aborted by signal.";
61
+ : "PowerShell aborted by signal.");
58
62
  }
59
63
  if (result.timedOut) {
60
- return `PowerShell timed out after ${timeout}ms`;
64
+ return markPowerShellResult(`PowerShell timed out after ${timeout}ms`);
61
65
  }
62
66
  if (result.spawnFailed) {
63
- return `PowerShell spawn error: ${result.error ?? "unknown error"}`;
67
+ return markPowerShellResult(`PowerShell spawn error: ${result.error ?? "unknown error"}`);
64
68
  }
65
69
  if (result.exitCode !== 0) {
66
70
  const out = [result.stdout.trim(), result.stderr.trim()].filter(Boolean).join("\n");
67
- return `PowerShell error:\n${out || `exit code ${result.exitCode}`}`;
71
+ return markPowerShellResult(`PowerShell error:\n${out || `exit code ${result.exitCode}`}`);
68
72
  }
69
- return result.stdout.trim() || "(no output)";
73
+ return markPowerShellResult(result.stdout.trim() || "(no output)");
70
74
  }