@cjhyy/code-shell-core 0.5.0-rc.0 → 0.5.0-rc.2

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 (283) hide show
  1. package/dist/agent/agent-definition-registry.d.ts +29 -0
  2. package/dist/agent/agent-definition-registry.js +74 -0
  3. package/dist/agent/agent-definition.d.ts +37 -0
  4. package/dist/agent/agent-definition.js +59 -0
  5. package/dist/arena/arena.js +11 -12
  6. package/dist/arena/context/context-tools.js +2 -4
  7. package/dist/arena/context/within-root.d.ts +7 -0
  8. package/dist/arena/context/within-root.js +15 -0
  9. package/dist/arena/iterate/phases/argue.js +8 -2
  10. package/dist/arena/iterate/phases/revise.js +1 -1
  11. package/dist/arena/iterate/phases/tournament.js +3 -3
  12. package/dist/arena/phases/adjudication.js +1 -4
  13. package/dist/arena/phases/build-consensus.js +1 -4
  14. package/dist/arena/phases/cross-review.js +2 -8
  15. package/dist/arena/phases/debate-rounds.js +1 -4
  16. package/dist/arena/phases/participant-research.js +1 -4
  17. package/dist/arena/phases/planning-detail-expansion.js +8 -10
  18. package/dist/arena/planner.js +0 -1
  19. package/dist/arena/providers/docs.d.ts +1 -0
  20. package/dist/arena/providers/docs.js +5 -2
  21. package/dist/arena/providers/repo.d.ts +1 -0
  22. package/dist/arena/providers/repo.js +5 -2
  23. package/dist/arena/strategies/utils.js +36 -3
  24. package/dist/arena/transitions.d.ts +7 -2
  25. package/dist/arena/transitions.js +9 -4
  26. package/dist/arena/types.d.ts +8 -2
  27. package/dist/automation/cron-expr.d.ts +31 -0
  28. package/dist/automation/cron-expr.js +151 -0
  29. package/dist/automation/index.d.ts +41 -0
  30. package/dist/automation/index.js +39 -0
  31. package/dist/automation/runner.d.ts +67 -0
  32. package/dist/automation/runner.js +56 -0
  33. package/dist/automation/scheduler.d.ts +156 -0
  34. package/dist/automation/scheduler.js +546 -0
  35. package/dist/automation/store.d.ts +39 -0
  36. package/dist/automation/store.js +119 -0
  37. package/dist/automation/write-policy.d.ts +34 -0
  38. package/dist/automation/write-policy.js +113 -0
  39. package/dist/automation/write-run.d.ts +51 -0
  40. package/dist/automation/write-run.js +38 -0
  41. package/dist/capability-control/index.d.ts +5 -0
  42. package/dist/capability-control/index.js +3 -0
  43. package/dist/capability-control/overlay.d.ts +49 -0
  44. package/dist/capability-control/overlay.js +89 -0
  45. package/dist/capability-control/project.d.ts +65 -0
  46. package/dist/capability-control/project.js +147 -0
  47. package/dist/capability-control/service.d.ts +70 -0
  48. package/dist/capability-control/service.js +147 -0
  49. package/dist/capability-control/types.d.ts +62 -0
  50. package/dist/capability-control/types.js +17 -0
  51. package/dist/cli/agent-server-stdio.d.ts +12 -1
  52. package/dist/cli/agent-server-stdio.js +118 -18
  53. package/dist/cli/agent-server-tcp.d.ts +20 -0
  54. package/dist/cli/agent-server-tcp.js +120 -0
  55. package/dist/cli/graceful-shutdown.d.ts +27 -0
  56. package/dist/cli/graceful-shutdown.js +30 -0
  57. package/dist/context/compaction.js +23 -15
  58. package/dist/context/manager.d.ts +0 -20
  59. package/dist/context/manager.js +0 -37
  60. package/dist/cron/cron-runtime.d.ts +2 -0
  61. package/dist/cron/cron-runtime.js +2 -0
  62. package/dist/cron/cron-store.d.ts +2 -0
  63. package/dist/cron/cron-store.js +2 -0
  64. package/dist/cron/scheduler.d.ts +5 -32
  65. package/dist/cron/scheduler.js +5 -113
  66. package/dist/data/openrouter-sync.js +1 -1
  67. package/dist/engine/engine.d.ts +256 -16
  68. package/dist/engine/engine.js +856 -200
  69. package/dist/engine/goal.d.ts +42 -0
  70. package/dist/engine/goal.js +52 -0
  71. package/dist/engine/image-compression.d.ts +81 -0
  72. package/dist/engine/image-compression.js +186 -0
  73. package/dist/engine/image-policy.d.ts +152 -0
  74. package/dist/engine/image-policy.js +165 -0
  75. package/dist/engine/reactive-threshold.d.ts +13 -0
  76. package/dist/engine/reactive-threshold.js +17 -0
  77. package/dist/engine/runtime.js +7 -0
  78. package/dist/engine/session-title.d.ts +13 -0
  79. package/dist/engine/session-title.js +34 -0
  80. package/dist/engine/turn-loop.d.ts +29 -8
  81. package/dist/engine/turn-loop.js +498 -316
  82. package/dist/git/parse-log.d.ts +13 -0
  83. package/dist/git/parse-log.js +21 -0
  84. package/dist/git/utils.d.ts +8 -6
  85. package/dist/git/utils.js +57 -26
  86. package/dist/git/worktree.js +33 -18
  87. package/dist/hooks/events.d.ts +23 -1
  88. package/dist/hooks/goal-stop-hook.d.ts +30 -0
  89. package/dist/hooks/goal-stop-hook.js +102 -0
  90. package/dist/hooks/hook-output.d.ts +33 -0
  91. package/dist/hooks/hook-output.js +79 -0
  92. package/dist/hooks/registry.d.ts +7 -0
  93. package/dist/hooks/registry.js +38 -1
  94. package/dist/hooks/shell-runner.d.ts +2 -0
  95. package/dist/hooks/shell-runner.js +43 -2
  96. package/dist/index.d.ts +32 -7
  97. package/dist/index.js +30 -3
  98. package/dist/llm/capabilities/reasoning-control.d.ts +24 -0
  99. package/dist/llm/capabilities/reasoning-control.js +38 -0
  100. package/dist/llm/capabilities/rules.js +33 -3
  101. package/dist/llm/capabilities/types.d.ts +22 -2
  102. package/dist/llm/clamp-max-tokens.d.ts +11 -0
  103. package/dist/llm/clamp-max-tokens.js +17 -0
  104. package/dist/llm/client-base.d.ts +41 -4
  105. package/dist/llm/client-base.js +67 -13
  106. package/dist/llm/client-factory.d.ts +3 -3
  107. package/dist/llm/client-factory.js +2 -2
  108. package/dist/llm/model-pool.d.ts +15 -11
  109. package/dist/llm/model-pool.js +23 -20
  110. package/dist/llm/provider-catalog.d.ts +2 -2
  111. package/dist/llm/providers/anthropic.d.ts +32 -2
  112. package/dist/llm/providers/anthropic.js +147 -8
  113. package/dist/llm/providers/openai.d.ts +11 -2
  114. package/dist/llm/providers/openai.js +253 -52
  115. package/dist/llm/reasoning-setting.d.ts +51 -0
  116. package/dist/llm/reasoning-setting.js +32 -0
  117. package/dist/llm/stop-reason.d.ts +13 -0
  118. package/dist/llm/stop-reason.js +21 -0
  119. package/dist/llm/strip-vision.d.ts +32 -0
  120. package/dist/llm/strip-vision.js +94 -0
  121. package/dist/llm/types.d.ts +5 -6
  122. package/dist/logging/logger.js +18 -4
  123. package/dist/logging/sanitize-messages.d.ts +10 -0
  124. package/dist/logging/sanitize-messages.js +90 -0
  125. package/dist/lsp/client.js +28 -8
  126. package/dist/lsp/manager.js +2 -1
  127. package/dist/lsp/root-path.d.ts +9 -0
  128. package/dist/lsp/root-path.js +12 -0
  129. package/dist/onboarding.js +18 -11
  130. package/dist/plugins/gitOps.d.ts +34 -0
  131. package/dist/plugins/gitOps.js +59 -3
  132. package/dist/plugins/installer/codex/convertAgents.d.ts +7 -0
  133. package/dist/plugins/installer/codex/convertAgents.js +55 -0
  134. package/dist/plugins/installer/codex/convertMcp.d.ts +8 -0
  135. package/dist/plugins/installer/codex/convertMcp.js +45 -0
  136. package/dist/plugins/installer/codex/convertSkills.d.ts +12 -0
  137. package/dist/plugins/installer/codex/convertSkills.js +33 -0
  138. package/dist/plugins/installer/detectFormat.d.ts +2 -0
  139. package/dist/plugins/installer/detectFormat.js +6 -0
  140. package/dist/plugins/installer/install.d.ts +7 -0
  141. package/dist/plugins/installer/install.js +99 -0
  142. package/dist/plugins/installer/installFromSource.d.ts +13 -0
  143. package/dist/plugins/installer/installFromSource.js +45 -0
  144. package/dist/plugins/installer/list.d.ts +9 -0
  145. package/dist/plugins/installer/list.js +30 -0
  146. package/dist/plugins/installer/loadPluginAgents.d.ts +3 -0
  147. package/dist/plugins/installer/loadPluginAgents.js +23 -0
  148. package/dist/plugins/installer/loadPluginMcp.d.ts +7 -0
  149. package/dist/plugins/installer/loadPluginMcp.js +74 -0
  150. package/dist/plugins/installer/parseSource.d.ts +20 -0
  151. package/dist/plugins/installer/parseSource.js +74 -0
  152. package/dist/plugins/installer/paths.d.ts +5 -0
  153. package/dist/plugins/installer/paths.js +25 -0
  154. package/dist/plugins/installer/types.d.ts +49 -0
  155. package/dist/plugins/installer/types.js +27 -0
  156. package/dist/plugins/installer/uninstall.d.ts +2 -0
  157. package/dist/plugins/installer/uninstall.js +14 -0
  158. package/dist/plugins/installer/update.d.ts +14 -0
  159. package/dist/plugins/installer/update.js +65 -0
  160. package/dist/plugins/loadPluginHooks.d.ts +8 -1
  161. package/dist/plugins/loadPluginHooks.js +11 -1
  162. package/dist/plugins/marketplaceManager.d.ts +8 -1
  163. package/dist/plugins/marketplaceManager.js +38 -4
  164. package/dist/plugins/pluginCommandHook.js +34 -0
  165. package/dist/plugins/pluginInstaller.d.ts +21 -0
  166. package/dist/plugins/pluginInstaller.js +128 -29
  167. package/dist/plugins/schemas.js +40 -6
  168. package/dist/plugins/types.d.ts +4 -0
  169. package/dist/preset/index.js +16 -0
  170. package/dist/prompt/composer.d.ts +10 -0
  171. package/dist/prompt/composer.js +29 -4
  172. package/dist/prompt/sections/orchestration.md +8 -0
  173. package/dist/protocol/chat-session-manager.d.ts +8 -1
  174. package/dist/protocol/chat-session-manager.js +10 -0
  175. package/dist/protocol/chat-session.d.ts +17 -0
  176. package/dist/protocol/chat-session.js +28 -0
  177. package/dist/protocol/redact.d.ts +50 -0
  178. package/dist/protocol/redact.js +71 -0
  179. package/dist/protocol/server.d.ts +41 -2
  180. package/dist/protocol/server.js +231 -33
  181. package/dist/protocol/tcp-transport.d.ts +45 -0
  182. package/dist/protocol/tcp-transport.js +74 -0
  183. package/dist/protocol/types.d.ts +23 -0
  184. package/dist/protocol/types.js +6 -0
  185. package/dist/remote/bridge.d.ts +11 -2
  186. package/dist/remote/bridge.js +61 -33
  187. package/dist/run/ArtifactTracker.js +5 -4
  188. package/dist/run/EngineRunner.d.ts +27 -1
  189. package/dist/run/EngineRunner.js +46 -8
  190. package/dist/run/FileRunStore.js +32 -8
  191. package/dist/run/RunLock.d.ts +28 -2
  192. package/dist/run/RunLock.js +49 -7
  193. package/dist/run/RunManager.js +51 -3
  194. package/dist/run/RunQueue.d.ts +1 -0
  195. package/dist/run/RunQueue.js +8 -2
  196. package/dist/run/factory.d.ts +7 -0
  197. package/dist/run/factory.js +1 -0
  198. package/dist/run/index.d.ts +2 -2
  199. package/dist/run/index.js +1 -1
  200. package/dist/run/redirect-target.d.ts +7 -0
  201. package/dist/run/redirect-target.js +13 -0
  202. package/dist/run/types.js +1 -1
  203. package/dist/services/browser-open.d.ts +13 -0
  204. package/dist/services/browser-open.js +16 -0
  205. package/dist/services/dream-consolidation.d.ts +57 -0
  206. package/dist/services/dream-consolidation.js +151 -0
  207. package/dist/services/memory-orchestrator.js +18 -0
  208. package/dist/services/notifier.d.ts +8 -0
  209. package/dist/services/notifier.js +39 -25
  210. package/dist/services/oauth.js +5 -7
  211. package/dist/services/session-memory-sort.d.ts +8 -0
  212. package/dist/services/session-memory-sort.js +9 -0
  213. package/dist/services/session-memory.js +8 -9
  214. package/dist/session/file-history.js +10 -3
  215. package/dist/session/session-manager.d.ts +23 -1
  216. package/dist/session/session-manager.js +73 -2
  217. package/dist/settings/disk-defaults.d.ts +35 -0
  218. package/dist/settings/disk-defaults.js +24 -0
  219. package/dist/settings/manager.d.ts +45 -1
  220. package/dist/settings/manager.js +121 -17
  221. package/dist/settings/manager.test.d.ts +1 -0
  222. package/dist/settings/manager.test.js +73 -0
  223. package/dist/settings/personalization.d.ts +19 -0
  224. package/dist/settings/personalization.js +7 -0
  225. package/dist/settings/schema.d.ts +1163 -126
  226. package/dist/settings/schema.js +126 -10
  227. package/dist/skills/scanner.d.ts +13 -6
  228. package/dist/skills/scanner.js +23 -4
  229. package/dist/tool-system/builtin/add-marketplace.d.ts +12 -0
  230. package/dist/tool-system/builtin/add-marketplace.js +76 -0
  231. package/dist/tool-system/builtin/agent-registry.d.ts +15 -0
  232. package/dist/tool-system/builtin/agent-registry.js +14 -4
  233. package/dist/tool-system/builtin/agent.d.ts +55 -0
  234. package/dist/tool-system/builtin/agent.js +165 -17
  235. package/dist/tool-system/builtin/apply-patch/index.js +22 -3
  236. package/dist/tool-system/builtin/arena.js +6 -7
  237. package/dist/tool-system/builtin/complete-goal.d.ts +25 -0
  238. package/dist/tool-system/builtin/complete-goal.js +45 -0
  239. package/dist/tool-system/builtin/cron.js +53 -9
  240. package/dist/tool-system/builtin/edit.d.ts +2 -1
  241. package/dist/tool-system/builtin/edit.js +6 -1
  242. package/dist/tool-system/builtin/generate-image.d.ts +25 -0
  243. package/dist/tool-system/builtin/generate-image.js +146 -0
  244. package/dist/tool-system/builtin/glob.js +7 -0
  245. package/dist/tool-system/builtin/grep.js +6 -0
  246. package/dist/tool-system/builtin/index.d.ts +18 -1
  247. package/dist/tool-system/builtin/index.js +62 -1
  248. package/dist/tool-system/builtin/notebook-edit.d.ts +2 -1
  249. package/dist/tool-system/builtin/notebook-edit.js +8 -1
  250. package/dist/tool-system/builtin/read.d.ts +2 -1
  251. package/dist/tool-system/builtin/read.js +9 -1
  252. package/dist/tool-system/builtin/skill.js +23 -5
  253. package/dist/tool-system/builtin/sleep.js +9 -3
  254. package/dist/tool-system/builtin/task.js +4 -1
  255. package/dist/tool-system/builtin/update-automation-memory.d.ts +24 -0
  256. package/dist/tool-system/builtin/update-automation-memory.js +60 -0
  257. package/dist/tool-system/builtin/view-image.d.ts +18 -0
  258. package/dist/tool-system/builtin/view-image.js +96 -0
  259. package/dist/tool-system/builtin/web-search.d.ts +4 -1
  260. package/dist/tool-system/builtin/web-search.js +36 -3
  261. package/dist/tool-system/builtin/write.d.ts +2 -1
  262. package/dist/tool-system/builtin/write.js +7 -1
  263. package/dist/tool-system/context.d.ts +43 -0
  264. package/dist/tool-system/executor.d.ts +0 -1
  265. package/dist/tool-system/executor.js +34 -40
  266. package/dist/tool-system/investigation-guard.d.ts +4 -1
  267. package/dist/tool-system/investigation-guard.js +19 -3
  268. package/dist/tool-system/mcp-manager.d.ts +36 -12
  269. package/dist/tool-system/mcp-manager.js +173 -10
  270. package/dist/tool-system/path-policy.d.ts +94 -0
  271. package/dist/tool-system/path-policy.js +279 -0
  272. package/dist/tool-system/permission.js +43 -50
  273. package/dist/tool-system/plan-mode-allowlist.d.ts +21 -0
  274. package/dist/tool-system/plan-mode-allowlist.js +43 -0
  275. package/dist/tool-system/registry.js +12 -1
  276. package/dist/tool-system/validation.d.ts +10 -0
  277. package/dist/tool-system/validation.js +16 -3
  278. package/dist/types.d.ts +90 -15
  279. package/dist/utils/format.js +4 -2
  280. package/dist/utils/lockfile.js +9 -2
  281. package/dist/utils/theme.d.ts +6 -0
  282. package/dist/utils/theme.js +4 -2
  283. package/package.json +2 -1
@@ -2,6 +2,27 @@
2
2
  * Settings schema with Zod validation.
3
3
  */
4
4
  import { z } from "zod";
5
+ import { ReasoningSettingSchema } from "../llm/reasoning-setting.js";
6
+ /**
7
+ * Tri-state project capability overlay. Lives in PROJECT settings only and
8
+ * layers over the global baseline (disabledSkills / disabledPlugins /
9
+ * mcpServers.<name>.enabled / disabledAgents). NOT a second denylist:
10
+ * - "on" → force enabled (even if globally disabled)
11
+ * - "off" → force disabled (even if globally enabled)
12
+ * - "inherit" → take the global baseline. We don't persist "inherit"; an
13
+ * absent key means inherit. See the project-scoped
14
+ * capabilities design (spec §4).
15
+ */
16
+ export const CapabilityOverrideSchema = z.enum(["inherit", "on", "off"]);
17
+ export const CapabilityOverridesSchema = z
18
+ .object({
19
+ skills: z.record(CapabilityOverrideSchema).optional(),
20
+ plugins: z.record(CapabilityOverrideSchema).optional(),
21
+ agents: z.record(CapabilityOverrideSchema).optional(),
22
+ mcp: z.record(CapabilityOverrideSchema).optional(),
23
+ builtin: z.record(CapabilityOverrideSchema).optional(),
24
+ })
25
+ .optional();
5
26
  export const SettingsSchema = z
6
27
  .object({
7
28
  agent: z
@@ -12,6 +33,14 @@ export const SettingsSchema = z
12
33
  disabledBuiltinTools: z.array(z.string()).default([]),
13
34
  customSystemPrompt: z.string().optional(),
14
35
  appendSystemPrompt: z.string().optional(),
36
+ responseLanguage: z.string().optional(),
37
+ userProfile: z.string().optional(),
38
+ instructions: z
39
+ .object({
40
+ compatClaude: z.boolean().default(true),
41
+ compatCodex: z.boolean().default(true),
42
+ })
43
+ .optional(),
15
44
  })
16
45
  .default({}),
17
46
  /**
@@ -22,6 +51,15 @@ export const SettingsSchema = z
22
51
  * both — appendOnboardingResult does this in one shot.
23
52
  */
24
53
  activeKey: z.string().optional(),
54
+ /**
55
+ * Auxiliary-task model — points at a models[].key. Background, non-user-
56
+ * facing LLM calls (memory extraction, the auto-dream loop) use this model
57
+ * instead of the active one, so per-turn book-keeping doesn't burn the
58
+ * expensive primary model. Pick something fast/cheap (e.g. a Haiku or
59
+ * DeepSeek key). When unset, those calls fall back to the active model
60
+ * (legacy behavior). An invalid/missing key also falls back to active.
61
+ */
62
+ auxModelKey: z.string().optional(),
25
63
  /**
26
64
  * Toggle background auto-update. When true (default), code-shell checks
27
65
  * npm for newer versions and — if the npm global prefix is writable —
@@ -62,12 +100,11 @@ export const SettingsSchema = z
62
100
  protocol: z.enum(["openai-compat", "anthropic-style"]).optional(),
63
101
  modelsPath: z.string().optional(),
64
102
  /**
65
- * DeepSeek V4 thinking-mode default for this provider. "enabled"
66
- * matches endpoint default; "disabled" makes V4 calls run in
67
- * non-thinking mode (faster, cheaper). Ignored by every provider
68
- * other than DeepSeek V4. Per-call overrides still win.
103
+ * Default reasoning/thinking setting for this provider's models.
104
+ * Rich shape: {mode:"off"|"on"} | {mode:"effort",effort} |
105
+ * {mode:"budget",budgetTokens}. Per-model `reasoning` wins.
69
106
  */
70
- thinking: z.enum(["enabled", "disabled"]).optional(),
107
+ reasoning: ReasoningSettingSchema.optional(),
71
108
  }))
72
109
  .default([]),
73
110
  models: z
@@ -90,12 +127,12 @@ export const SettingsSchema = z
90
127
  baseUrl: z.string().optional(),
91
128
  apiKey: z.string().optional(),
92
129
  /**
93
- * Per-model thinking override. Wins over the provider-level
94
- * setting (settings.providers[].thinking). Use this when
95
- * different models under the same provider need different
96
- * defaults — e.g. DeepSeek V4 Pro off (faster) but V4 Flash on.
130
+ * Per-model reasoning override. Wins over the provider-level
131
+ * `reasoning` setting (settings.providers[].reasoning). Use this
132
+ * when different models under the same provider need different
133
+ * defaults — e.g. one model off (faster) and another on.
97
134
  */
98
- thinking: z.enum(["enabled", "disabled"]).optional(),
135
+ reasoning: ReasoningSettingSchema.optional(),
99
136
  })
100
137
  .transform((m) => {
101
138
  // Normalize: prefer `protocol`; fall back to legacy `provider`.
@@ -146,6 +183,9 @@ export const SettingsSchema = z
146
183
  url: z.string().optional(),
147
184
  transport: z.enum(["stdio", "sse", "streamable-http", "inprocess"]).optional(),
148
185
  headers: z.record(z.string()).optional(),
186
+ // Codex-style on/off switch. Absent or true → connected; only
187
+ // literal false disables. Filtered in MCPManager.connectAll.
188
+ enabled: z.boolean().optional(),
149
189
  }))
150
190
  .default({}),
151
191
  /**
@@ -155,6 +195,27 @@ export const SettingsSchema = z
155
195
  * tool both see the filtered set — see scanSkills(opts).
156
196
  */
157
197
  disabledSkills: z.array(z.string()).default([]),
198
+ /**
199
+ * Plugin-level total switch: every skill whose namespaced name
200
+ * starts with `${pluginName}:` is filtered. Coarser knob than
201
+ * disabledSkills; both are honored simultaneously. Bare plugin
202
+ * names (no colon suffix). See scanSkills(opts.disabledPlugins).
203
+ */
204
+ disabledPlugins: z.array(z.string()).default([]),
205
+ /**
206
+ * Sub-agent role names (the `name` in .code-shell/agents/*.md) to
207
+ * hide from the registry. A disabled role is filtered out at load
208
+ * so it never appears in registry.list()/get() — the Agent tool's
209
+ * agent_type list won't show it and the LLM can't pick it. Mirrors
210
+ * disabledSkills / disabledPlugins.
211
+ */
212
+ disabledAgents: z.array(z.string()).default([]),
213
+ /**
214
+ * Project-scoped tri-state capability overlay. Only meaningful in
215
+ * ${cwd}/.code-shell/settings.json; layered over the global baseline at
216
+ * capability-assembly time. Optional — absence === everything inherits.
217
+ */
218
+ capabilityOverrides: CapabilityOverridesSchema,
158
219
  instructions: z
159
220
  .object({
160
221
  fileName: z.string().default("CODESHELL.md"),
@@ -197,6 +258,15 @@ export const SettingsSchema = z
197
258
  .record(z.enum(["serper", "tavily", "searxng"]), z.object({
198
259
  apiKey: z.string().optional(),
199
260
  baseUrl: z.string().optional(),
261
+ lastProbe: z
262
+ .object({
263
+ status: z.enum(["ok", "error", "unconfigured"]),
264
+ sampleTitles: z.array(z.string()).optional(),
265
+ errorMessage: z.string().optional(),
266
+ errorDetail: z.string().optional(),
267
+ lastProbedAt: z.string(),
268
+ })
269
+ .optional(),
200
270
  }))
201
271
  .optional(),
202
272
  })
@@ -206,6 +276,24 @@ export const SettingsSchema = z
206
276
  format: z.enum(["text", "json", "jsonl", "stream-json"]).default("text"),
207
277
  })
208
278
  .default({}),
279
+ /**
280
+ * Image attachment handling. Sub-fields:
281
+ * - detail: OpenAI-style fidelity hint applied to every user-
282
+ * attached image. "low" = 85 tokens/image fixed (cheap
283
+ * thumbnail), "high" = ~768 px tiles (default), "original" =
284
+ * keep client-side dimensions (most expensive). Anthropic
285
+ * ignores this field today; that's fine — it just gets
286
+ * dropped on the Claude path.
287
+ * - mcpImageTokenBudget: per-turn cap on token cost of images
288
+ * returned by MCP tools. Codex doesn't enforce this; CC uses
289
+ * 25 000. Set to 0 to disable.
290
+ */
291
+ images: z
292
+ .object({
293
+ detail: z.enum(["low", "high", "original"]).optional(),
294
+ mcpImageTokenBudget: z.number().int().nonnegative().optional(),
295
+ })
296
+ .optional(),
209
297
  /**
210
298
  * OS-level sandbox for shell-tool execution. "auto" picks per platform:
211
299
  * Seatbelt on macOS, bubblewrap on Linux when installed, otherwise off.
@@ -220,6 +308,34 @@ export const SettingsSchema = z
220
308
  network: z.enum(["allow", "deny"]).optional(),
221
309
  })
222
310
  .optional(),
311
+ /**
312
+ * Project-local environment profile. Mirrors Codex's local-environment
313
+ * shape at the settings layer: setup/cleanup scripts can be customized per
314
+ * platform, and env values are stored as KEY=VALUE pairs. Runtime wiring is
315
+ * intentionally separate from the MCP server env model above.
316
+ */
317
+ localEnvironment: z
318
+ .object({
319
+ name: z.string().optional(),
320
+ setupScripts: z
321
+ .object({
322
+ default: z.string().optional(),
323
+ macos: z.string().optional(),
324
+ linux: z.string().optional(),
325
+ windows: z.string().optional(),
326
+ })
327
+ .optional(),
328
+ cleanupScripts: z
329
+ .object({
330
+ default: z.string().optional(),
331
+ macos: z.string().optional(),
332
+ linux: z.string().optional(),
333
+ windows: z.string().optional(),
334
+ })
335
+ .optional(),
336
+ env: z.record(z.string()).optional(),
337
+ })
338
+ .optional(),
223
339
  /**
224
340
  * Shell-hook configuration. Each entry binds a HookEventName to a
225
341
  * shell command; the command receives ctx JSON on stdin and returns
@@ -17,15 +17,22 @@ export interface SkillDefinition {
17
17
  source: "project" | "user" | "plugin";
18
18
  }
19
19
  /**
20
- * Options accepted by scanSkills. The disabled-skill filter is applied
21
- * after the memoized scan returns so the cache stays warm across
22
- * different filter values — changing `settings.disabledSkills` should
23
- * never force a re-scan. Names in `disabledSkills` must match the
24
- * SkillDefinition.name exactly, including any "<plugin>:" prefix —
25
- * see scanInstalledPlugins() at line ~168 for namespace construction.
20
+ * Options accepted by scanSkills. Both filters are applied after the
21
+ * memoized scan returns so the cache stays warm across different filter
22
+ * values — changing `settings.disabledSkills` or `settings.disabledPlugins`
23
+ * should never force a re-scan.
24
+ *
25
+ * - `disabledSkills` names must match the SkillDefinition.name exactly,
26
+ * including any "<plugin>:" prefix — see scanInstalledPlugins() at
27
+ * line ~168 for namespace construction.
28
+ * - `disabledPlugins` names are bare plugin names (no colon suffix).
29
+ * Every skill whose name starts with `${pluginName}:` is filtered.
30
+ * This is the coarse "plugin total switch" knob; `disabledSkills` is
31
+ * the per-skill knob.
26
32
  */
27
33
  export interface ScanSkillsOptions {
28
34
  disabledSkills?: string[];
35
+ disabledPlugins?: string[];
29
36
  }
30
37
  export declare function scanSkills(cwd: string, opts?: ScanSkillsOptions): SkillDefinition[];
31
38
  export declare function invalidateSkillCache(): void;
@@ -160,11 +160,30 @@ function installedPluginsMtime() {
160
160
  const memoized = memoize(scanOnce, (cwd) => `${cwd}\0${userHome()}\0${installedPluginsMtime()}`);
161
161
  export function scanSkills(cwd, opts) {
162
162
  const all = memoized(cwd);
163
- const disabled = opts?.disabledSkills;
164
- if (!disabled || disabled.length === 0)
163
+ const disabledSkills = opts?.disabledSkills;
164
+ const disabledPlugins = opts?.disabledPlugins;
165
+ const hasSkillFilter = disabledSkills && disabledSkills.length > 0;
166
+ const hasPluginFilter = disabledPlugins && disabledPlugins.length > 0;
167
+ if (!hasSkillFilter && !hasPluginFilter)
165
168
  return all;
166
- const set = new Set(disabled);
167
- return all.filter((s) => !set.has(s.name));
169
+ const skillSet = hasSkillFilter ? new Set(disabledSkills) : null;
170
+ const pluginSet = hasPluginFilter ? new Set(disabledPlugins) : null;
171
+ return all.filter((s) => {
172
+ if (skillSet && skillSet.has(s.name))
173
+ return false;
174
+ if (pluginSet) {
175
+ // Use indexOf, not split — skill names may theoretically contain
176
+ // more colons after the first; the namespace boundary is the
177
+ // first ":" only.
178
+ const colon = s.name.indexOf(":");
179
+ if (colon > 0) {
180
+ const prefix = s.name.slice(0, colon);
181
+ if (pluginSet.has(prefix))
182
+ return false;
183
+ }
184
+ }
185
+ return true;
186
+ });
168
187
  }
169
188
  export function invalidateSkillCache() {
170
189
  memoized.cache.clear?.();
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Built-in AddMarketplace tool — register a plugin marketplace source so the
3
+ * user can browse/install plugins from it in the UI. The tool only *adds the
4
+ * source* (git clone + validate marketplace.json via core's addMarketplace);
5
+ * which plugin to install is left to the user. Pairs with WebSearch/WebFetch:
6
+ * the model can discover a marketplace repo, then add it.
7
+ *
8
+ * Side effects (network + git clone + disk write) → permissionDefault "ask".
9
+ */
10
+ import type { ToolDefinition } from "../../types.js";
11
+ export declare const addMarketplaceToolDef: ToolDefinition;
12
+ export declare function addMarketplaceTool(args: Record<string, unknown>): Promise<string>;
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Built-in AddMarketplace tool — register a plugin marketplace source so the
3
+ * user can browse/install plugins from it in the UI. The tool only *adds the
4
+ * source* (git clone + validate marketplace.json via core's addMarketplace);
5
+ * which plugin to install is left to the user. Pairs with WebSearch/WebFetch:
6
+ * the model can discover a marketplace repo, then add it.
7
+ *
8
+ * Side effects (network + git clone + disk write) → permissionDefault "ask".
9
+ */
10
+ import { addMarketplace } from "../../plugins/marketplaceManager.js";
11
+ export const addMarketplaceToolDef = {
12
+ name: "AddMarketplace",
13
+ description: "Register a plugin marketplace source so the user can browse and install " +
14
+ "plugins from it. Provide a short name and a source: either a GitHub repo " +
15
+ "(owner/name) or a git URL. This only ADDS the source — it does not install " +
16
+ "any plugin. Use WebSearch/WebFetch first to find a marketplace repo if you " +
17
+ "don't already have one.",
18
+ inputSchema: {
19
+ type: "object",
20
+ properties: {
21
+ name: {
22
+ type: "string",
23
+ description: "Short local name for this marketplace (e.g. 'official').",
24
+ },
25
+ source_type: {
26
+ type: "string",
27
+ enum: ["github", "git"],
28
+ description: "'github' for an owner/name repo, 'git' for a clone URL.",
29
+ },
30
+ repo: {
31
+ type: "string",
32
+ description: "GitHub repo in owner/name form (required when source_type='github').",
33
+ },
34
+ url: {
35
+ type: "string",
36
+ description: "Git clone URL (required when source_type='git').",
37
+ },
38
+ },
39
+ required: ["name", "source_type"],
40
+ },
41
+ };
42
+ export async function addMarketplaceTool(args) {
43
+ const name = args.name;
44
+ if (typeof name !== "string" || !name.trim()) {
45
+ return "Error: name is required";
46
+ }
47
+ const sourceType = args.source_type;
48
+ let source;
49
+ if (sourceType === "github") {
50
+ const repo = args.repo;
51
+ if (typeof repo !== "string" || !repo.includes("/")) {
52
+ return "Error: github source requires repo in owner/name form";
53
+ }
54
+ source = { source: "github", repo };
55
+ }
56
+ else if (sourceType === "git") {
57
+ const url = args.url;
58
+ if (typeof url !== "string" || !url.trim()) {
59
+ return "Error: git source requires a url";
60
+ }
61
+ source = { source: "git", url };
62
+ }
63
+ else {
64
+ return "Error: source_type must be 'github' or 'git'";
65
+ }
66
+ try {
67
+ const result = await addMarketplace(name, source);
68
+ if (!result.ok) {
69
+ return `Error adding marketplace ${name}: ${result.error}`;
70
+ }
71
+ return `Marketplace '${name}' added. The user can now browse and install plugins from it in the Extensions → Market UI.`;
72
+ }
73
+ catch (err) {
74
+ return `Error adding marketplace ${name}: ${err.message}`;
75
+ }
76
+ }
@@ -12,6 +12,8 @@
12
12
  * RunManager, not here.
13
13
  */
14
14
  export type AsyncAgentStatus = "running" | "completed" | "failed" | "cancelled";
15
+ /** Process-wide cap on concurrent background sub-agents (aligns with Codex max_threads=6). */
16
+ export declare const MAX_BACKGROUND_AGENTS = 6;
15
17
  /**
16
18
  * Minimal structural shape for an entry in an agent's transcript. We avoid
17
19
  * importing the UI's `ChatEntry` here to prevent a tool-system → ui import
@@ -27,7 +29,15 @@ export interface AsyncAgentEntry {
27
29
  agentId: string;
28
30
  /** Short kind label shown in the dock (e.g. "Explore", "Plan"). */
29
31
  name?: string;
32
+ /** Dispatched role (e.g. "general-purpose", "explorer"); shown in the dock
33
+ * so you can see what kind of agent is running. */
34
+ agentType?: string;
30
35
  description: string;
36
+ /** Session that spawned this background agent. Lets the spawning
37
+ * Engine.run wait only on ITS OWN background agents (hasRunningForSession),
38
+ * not every concurrent session's. Undefined only for legacy/ad-hoc callers
39
+ * outside Engine.run. */
40
+ sessionId?: string;
31
41
  status: AsyncAgentStatus;
32
42
  startedAt: number;
33
43
  finishedAt?: number;
@@ -44,6 +54,11 @@ declare class AsyncAgentRegistry {
44
54
  subscribe: (cb: () => void) => (() => void);
45
55
  getSnapshot: () => AsyncAgentEntry[];
46
56
  hasRunning: () => boolean;
57
+ /** True if any background agent spawned by `sessionId` is still running.
58
+ * Drives Engine.run's "wait for my background agents before resolving". */
59
+ hasRunningForSession: (sessionId: string) => boolean;
60
+ /** Count of agents currently in the "running" state (cap enforcement). */
61
+ runningCount(): number;
47
62
  private notify;
48
63
  register(entry: AsyncAgentEntry): void;
49
64
  appendToTranscript(agentId: string, entry: AgentTranscriptEntry): void;
@@ -11,6 +11,8 @@
11
11
  * the right boundary: long-running cross-process work belongs to
12
12
  * RunManager, not here.
13
13
  */
14
+ /** Process-wide cap on concurrent background sub-agents (aligns with Codex max_threads=6). */
15
+ export const MAX_BACKGROUND_AGENTS = 6;
14
16
  class AsyncAgentRegistry {
15
17
  agents = new Map();
16
18
  listeners = new Set();
@@ -28,6 +30,15 @@ class AsyncAgentRegistry {
28
30
  hasRunning = () => {
29
31
  return this.snapshot.some((e) => e.status === "running");
30
32
  };
33
+ /** True if any background agent spawned by `sessionId` is still running.
34
+ * Drives Engine.run's "wait for my background agents before resolving". */
35
+ hasRunningForSession = (sessionId) => {
36
+ return this.snapshot.some((e) => e.status === "running" && e.sessionId === sessionId);
37
+ };
38
+ /** Count of agents currently in the "running" state (cap enforcement). */
39
+ runningCount() {
40
+ return this.snapshot.filter((e) => e.status === "running").length;
41
+ }
31
42
  notify() {
32
43
  this.snapshot = [...this.agents.values()];
33
44
  for (const cb of this.listeners) {
@@ -102,10 +113,9 @@ class AsyncAgentRegistry {
102
113
  catch {
103
114
  // ignore abort errors — we still mark cancelled
104
115
  }
105
- e.status = "cancelled";
106
- e.finishedAt = Date.now();
107
- e.finishedFadeAt = e.finishedAt + 30_000;
108
- this.notify();
116
+ // Reuse markFinished for the status/timestamp/notify bookkeeping rather
117
+ // than duplicating it (the entry is still "running" after abort()).
118
+ this.markFinished(agentId, "cancelled");
109
119
  return true;
110
120
  }
111
121
  reset() {
@@ -8,9 +8,64 @@
8
8
  */
9
9
  import type { ToolDefinition } from "../../types.js";
10
10
  import type { ToolContext } from "../context.js";
11
+ import type { AgentDefinitionRegistry } from "../../agent/agent-definition-registry.js";
12
+ import type { HookRegistry } from "../../hooks/registry.js";
13
+ export interface AgentTypeOverrides {
14
+ resolvedType?: string;
15
+ model?: string;
16
+ maxTurns?: number;
17
+ toolAllowlist?: string[];
18
+ appendSystemPrompt?: string;
19
+ }
20
+ /**
21
+ * Resolve an `agent_type` against the role registry into spawn overrides.
22
+ *
23
+ * - Omitted type + non-empty registry → fall back to a configured role
24
+ * ("general-purpose" if present, else the first available) instead of
25
+ * running a nameless ephemeral agent. Relaxed from the earlier "throw when
26
+ * agent_type omitted": the model habitually omits it, and a hard error just
27
+ * turned every spawn into a failure. Falling back to a real role keeps the
28
+ * tool-allowlist / system-prompt benefits without breaking the call.
29
+ * - Omitted type + empty registry → empty overrides (true ephemeral; nothing
30
+ * to fall back to).
31
+ * - Unknown explicit type → throw, so the LLM gets a clear correction rather
32
+ * than silently running a generic agent.
33
+ */
34
+ export declare function resolveAgentTypeOverrides(agentType: string | undefined, registry: AgentDefinitionRegistry | undefined): AgentTypeOverrides;
35
+ /**
36
+ * Render the "Available agent types" block injected into the Agent tool's
37
+ * description, listing the roles defined in .code-shell/agents/*.md so the
38
+ * model knows it can pass `agent_type` instead of hand-rolling an ad-hoc
39
+ * agent. Without this the model never sees the registry (it lives per-engine,
40
+ * not in the static tool def) and falls back to nameless ephemeral agents —
41
+ * see the Core A/B/C incident. Returns "" when no roles are defined, so the
42
+ * base description is left untouched.
43
+ */
44
+ export declare function buildAgentTypesBlock(registry: AgentDefinitionRegistry | undefined): string;
45
+ /**
46
+ * Produce an Agent tool definition whose description ends with the live
47
+ * available-agent-types listing. Pure: takes the registry, returns a new def
48
+ * (the base `agentToolDef` const is never mutated). When no roles exist the
49
+ * base def is returned unchanged.
50
+ */
51
+ export declare function agentToolDefWithTypes(registry: AgentDefinitionRegistry | undefined): ToolDefinition;
52
+ type SubAgentLifecycle = "subagent_start" | "subagent_finish" | "subagent_error";
53
+ /**
54
+ * Emit a sub-agent lifecycle event via the existing `notification` hook,
55
+ * tagged with a `kind`. No-op when hooks are absent. Fire-and-forget: emit is
56
+ * async, we deliberately `void` it so bookkeeping never blocks on a handler
57
+ * (mirrors the background-completion notification below).
58
+ */
59
+ export declare function emitSubAgentHook(hooks: HookRegistry | undefined, kind: SubAgentLifecycle, payload: {
60
+ agentId: string;
61
+ description: string;
62
+ text?: string;
63
+ error?: string;
64
+ }): void;
11
65
  export declare const agentToolDef: ToolDefinition;
12
66
  export declare function agentTool(args: Record<string, unknown>, ctx?: ToolContext): Promise<string>;
13
67
  export declare const agentStatusToolDef: ToolDefinition;
14
68
  export declare function agentStatusTool(args: Record<string, unknown>): Promise<string>;
15
69
  export declare const agentCancelToolDef: ToolDefinition;
16
70
  export declare function agentCancelTool(args: Record<string, unknown>): Promise<string>;
71
+ export {};