@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
@@ -1,6 +1,20 @@
1
1
  /**
2
2
  * Hook registry with priority-based chain-of-responsibility execution.
3
3
  */
4
+ // Strictness order for merging hook permission decisions across the chain.
5
+ // Higher = stricter. deny wins over ask wins over allow.
6
+ const DECISION_RANK = { deny: 2, ask: 1, allow: 0 };
7
+ /**
8
+ * Merge two hook decisions, keeping the stricter one. `undefined` (no prior
9
+ * decision) yields the incoming one. Prevents a later handler from relaxing
10
+ * an earlier handler's deny — aligns with the executor's clampHookDecision
11
+ * "downgrades only" rule.
12
+ */
13
+ function stricterDecision(prev, next) {
14
+ if (prev === undefined)
15
+ return next;
16
+ return DECISION_RANK[next] >= DECISION_RANK[prev] ? next : prev;
17
+ }
4
18
  export class HookRegistry {
5
19
  hooks = new Map();
6
20
  register(eventName, handler, priority = 0, name) {
@@ -11,6 +25,22 @@ export class HookRegistry {
11
25
  // Sort by priority descending (highest first)
12
26
  this.hooks.get(eventName).sort((a, b) => b.priority - a.priority);
13
27
  }
28
+ /**
29
+ * Remove a previously-registered handler by identity. Used for handlers
30
+ * with a run-scoped lifetime (e.g. the per-run GoalStopHook) so they don't
31
+ * leak across subsequent runs on the same long-lived registry. No-op if
32
+ * the handler isn't registered for that event.
33
+ */
34
+ unregister(eventName, handler) {
35
+ const list = this.hooks.get(eventName);
36
+ if (!list)
37
+ return;
38
+ const next = list.filter((h) => h.handler !== handler);
39
+ if (next.length === 0)
40
+ this.hooks.delete(eventName);
41
+ else
42
+ this.hooks.set(eventName, next);
43
+ }
14
44
  async emit(eventName, data = {}) {
15
45
  const handlers = this.hooks.get(eventName);
16
46
  if (!handlers?.length)
@@ -28,7 +58,10 @@ export class HookRegistry {
28
58
  aggregated.messages = [...(aggregated.messages ?? []), ...result.messages];
29
59
  }
30
60
  if (result.decision) {
31
- aggregated.decision = result.decision;
61
+ // Strictest decision across the chain wins (deny > ask > allow),
62
+ // not last-write-wins. Otherwise a low-priority (later-running)
63
+ // handler could relax a high-priority handler's deny to allow.
64
+ aggregated.decision = stricterDecision(aggregated.decision, result.decision);
32
65
  }
33
66
  // Last-write-wins for input/prompt rewrites — the priority order
34
67
  // already determined which handler "owns" the override.
@@ -45,6 +78,10 @@ export class HookRegistry {
45
78
  ? `${aggregated.additionalContext}\n\n${result.additionalContext}`
46
79
  : result.additionalContext;
47
80
  }
81
+ // on_stop: any handler asking to continue blocks termination.
82
+ if (result.continueSession) {
83
+ aggregated.continueSession = true;
84
+ }
48
85
  if (result.stop) {
49
86
  aggregated.stop = true;
50
87
  break;
@@ -30,6 +30,8 @@
30
30
  */
31
31
  import type { HookContext, HookResult } from "./events.js";
32
32
  import type { SettingsHookConfig } from "../types.js";
33
+ import { validateHookResult } from "./hook-output.js";
34
+ export { validateHookResult };
33
35
  /**
34
36
  * Run one shell-hook command and return the parsed HookResult. Catches
35
37
  * every failure mode (spawn error, timeout, malformed JSON) and
@@ -29,6 +29,10 @@
29
29
  * On timeout we SIGTERM then SIGKILL, log, and return {}.
30
30
  */
31
31
  import { spawn } from "node:child_process";
32
+ import { MAX_HOOK_OUTPUT_BYTES, validateHookResult } from "./hook-output.js";
33
+ // Re-export so existing call sites that import { validateHookResult } from
34
+ // "./shell-runner.js" (e.g. tests) keep compiling.
35
+ export { validateHookResult };
32
36
  const DEFAULT_TIMEOUT_MS = 60_000;
33
37
  /**
34
38
  * Run one shell-hook command and return the parsed HookResult. Catches
@@ -86,10 +90,38 @@ export async function runShellHook(config, ctx) {
86
90
  }
87
91
  settle({});
88
92
  }, timeoutMs);
93
+ // Byte cap: once we cross MAX_HOOK_OUTPUT_BYTES on stdout, kill the
94
+ // child and surface a 'cap exceeded' failure. A misbehaving handler
95
+ // can otherwise hold the engine memory hostage while we accumulate
96
+ // its output. Stderr is also capped but treated more leniently —
97
+ // truncated, not fatal — since stderr is just diagnostic chatter.
98
+ let stdoutBytes = 0;
99
+ let stdoutCapped = false;
100
+ let stderrCapped = false;
89
101
  child.stdout?.on("data", (chunk) => {
102
+ stdoutBytes += chunk.length;
103
+ if (stdoutBytes > MAX_HOOK_OUTPUT_BYTES) {
104
+ if (!stdoutCapped) {
105
+ stdoutCapped = true;
106
+ // eslint-disable-next-line no-console
107
+ console.warn(`[hooks] ${config.event} hook stdout exceeded ${MAX_HOOK_OUTPUT_BYTES} bytes — killing`);
108
+ try {
109
+ child.kill("SIGTERM");
110
+ }
111
+ catch { /* already exited */ }
112
+ }
113
+ return;
114
+ }
90
115
  stdout += chunk.toString("utf8");
91
116
  });
92
117
  child.stderr?.on("data", (chunk) => {
118
+ if (stderr.length + chunk.length > MAX_HOOK_OUTPUT_BYTES) {
119
+ if (!stderrCapped) {
120
+ stderrCapped = true;
121
+ stderr += "\n…[stderr truncated]";
122
+ }
123
+ return;
124
+ }
93
125
  stderr += chunk.toString("utf8");
94
126
  });
95
127
  child.on("error", (err) => {
@@ -100,6 +132,12 @@ export async function runShellHook(config, ctx) {
100
132
  });
101
133
  child.on("close", (code) => {
102
134
  clearTimeout(timer);
135
+ if (stdoutCapped) {
136
+ // eslint-disable-next-line no-console
137
+ console.error(`[hooks] ${config.event} hook killed due to oversized stdout (> ${MAX_HOOK_OUTPUT_BYTES} bytes)`);
138
+ settle({});
139
+ return;
140
+ }
103
141
  if (code === 0) {
104
142
  const trimmed = stdout.trim();
105
143
  if (trimmed.length === 0) {
@@ -108,10 +146,13 @@ export async function runShellHook(config, ctx) {
108
146
  }
109
147
  try {
110
148
  const parsed = JSON.parse(trimmed);
111
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
112
- settle(parsed);
149
+ const validated = validateHookResult(parsed);
150
+ if (validated) {
151
+ settle(validated);
113
152
  }
114
153
  else {
154
+ // eslint-disable-next-line no-console
155
+ console.warn(`[hooks] ${config.event} hook returned a value that failed HookResult schema, ignoring. stdout:`, trimmed.slice(0, 200));
115
156
  settle({});
116
157
  }
117
158
  }
package/dist/index.d.ts CHANGED
@@ -4,10 +4,12 @@
4
4
  * Public API exports.
5
5
  */
6
6
  export declare const VERSION = "0.5.0-rc.0";
7
- export type { Message, ContentBlock, ToolDefinition, ToolCall, ToolResult, RegisteredTool, TranscriptEvent, TranscriptEventType, SessionState, SessionStatus, TokenUsage, CompiledInput, PermissionDecision, PermissionMode, PermissionRule, TurnPhase, TurnResult, TerminalReason, StreamEvent, StreamCallback, LLMConfig, LLMResponse, Settings, MCPServerConfig, } from "./types.js";
7
+ export type { Message, ContentBlock, ToolDefinition, ToolCall, ToolResult, RegisteredTool, TranscriptEvent, TranscriptEventType, SessionState, SessionStatus, TokenUsage, CompiledInput, PermissionDecision, PermissionMode, PermissionRule, TurnPhase, TurnResult, TerminalReason, StreamEvent, StreamCallback, LLMConfig, ClientDefaults, LLMResponse, Settings, MCPServerConfig, } from "./types.js";
8
8
  export { FrameworkError, LLMError, LLMRateLimitError, ContextLimitError, ToolError, ToolNotFoundError, ToolExecutionError, ToolTimeoutError, PermissionDeniedError, SessionError, TranscriptError, ConfigError, SandboxUnavailableError, } from "./exceptions.js";
9
- export { Engine } from "./engine/engine.js";
9
+ export { Engine, loadAgentDefinitionsForCwd } from "./engine/engine.js";
10
10
  export type { EngineConfig, EngineHookConfig, EngineResult } from "./engine/engine.js";
11
+ export { parseAgentDefinition, serializeAgentDefinition, type AgentDefinition, } from "./agent/agent-definition.js";
12
+ export { AgentDefinitionRegistry, type AgentSourceDir, } from "./agent/agent-definition-registry.js";
11
13
  export type { CostStateStore, CostStateSnapshot } from "./engine/cost-store.js";
12
14
  export { EngineRuntime } from "./engine/runtime.js";
13
15
  export type { EngineRuntimeOptions } from "./engine/runtime.js";
@@ -23,6 +25,8 @@ export { ToolExecutor } from "./tool-system/executor.js";
23
25
  export { PermissionClassifier, HeadlessApprovalBackend, AutoApprovalBackend } from "./tool-system/permission.js";
24
26
  export type { ApprovalBackend } from "./tool-system/permission.js";
25
27
  export { BUILTIN_TOOLS } from "./tool-system/builtin/index.js";
28
+ export type { BuiltinTool, BuiltinToolFn } from "./tool-system/builtin/index.js";
29
+ export { makeUpdateAutomationMemoryTool } from "./tool-system/builtin/update-automation-memory.js";
26
30
  export { MCPManager } from "./tool-system/mcp-manager.js";
27
31
  export type { AskUserFn } from "./tool-system/builtin/ask-user.js";
28
32
  export type { Task, TaskStatus } from "./tool-system/builtin/task.js";
@@ -32,13 +36,15 @@ export { wrapHookMessages } from "./hooks/inject.js";
32
36
  export { AgentServer, type AgentServerOptions } from "./protocol/server.js";
33
37
  export { AgentClient, type BackgroundAgentCompletedHandler } from "./protocol/client.js";
34
38
  export { createInProcessTransport, StdioTransport, type Transport, } from "./protocol/transport.js";
39
+ export { SocketTransport, listenTcp, type TcpListenResult, } from "./protocol/tcp-transport.js";
35
40
  export { createServer, createClient, type CreateServerOptions, type CreateClientOptions, type ServerHandle, } from "./protocol/factories.js";
36
41
  export { Methods, ErrorCodes, type RpcMessage, type RunResult, } from "./protocol/types.js";
37
42
  export { Transcript } from "./session/transcript.js";
38
43
  export { SessionManager } from "./session/session-manager.js";
39
44
  export { FileHistory } from "./session/file-history.js";
40
45
  export { MemoryManager } from "./session/memory.js";
41
- export type { MemoryEntry } from "./session/memory.js";
46
+ export type { MemoryEntry, MemoryScope } from "./session/memory.js";
47
+ export { runDreamConsolidation, type DreamConsolidationInput, type DreamConsolidationResult, } from "./services/dream-consolidation.js";
42
48
  export type { FileSnapshot } from "./session/file-history.js";
43
49
  export { PromptComposer } from "./prompt/composer.js";
44
50
  export { SectionCache } from "./prompt/section-cache.js";
@@ -54,6 +60,21 @@ export { applyToolResultPersistence, createContentReplacementState, reconstructC
54
60
  export type { ContentReplacementState } from "./context/tool-result-storage.js";
55
61
  export { scanSkills, invalidateSkillCache } from "./skills/index.js";
56
62
  export type { SkillDefinition } from "./skills/index.js";
63
+ export { CapabilityService, CapabilityNotFoundError, projectBuiltin, projectMcp, projectSkills, projectPlugins, } from "./capability-control/index.js";
64
+ export type { CapabilityServiceDeps, CapabilityDescriptor, CapabilityControl, } from "./capability-control/index.js";
65
+ export { readInstalledPlugins } from "./plugins/installedPlugins.js";
66
+ export type { InstalledPluginsV2 } from "./plugins/types.js";
67
+ export { installPluginFromPath } from "./plugins/installer/install.js";
68
+ export { installPluginFromSource } from "./plugins/installer/installFromSource.js";
69
+ export { parseSource, type ParsedSource } from "./plugins/installer/parseSource.js";
70
+ export { detectPluginFormat } from "./plugins/installer/detectFormat.js";
71
+ export { CodexPluginManifest, CSMeta, PluginInstallError, } from "./plugins/installer/types.js";
72
+ export { mergePluginMcpServers } from "./plugins/installer/loadPluginMcp.js";
73
+ export { pluginAgentDirs } from "./plugins/installer/loadPluginAgents.js";
74
+ export { appendInstallEntry, pluginInstallKey, removeInstallEntries, } from "./plugins/installedPlugins.js";
75
+ export { uninstallPluginByName } from "./plugins/installer/uninstall.js";
76
+ export { listInstalledPlugins, type PluginListRow } from "./plugins/installer/list.js";
77
+ export { updatePluginByName, type UpdateResult } from "./plugins/installer/update.js";
57
78
  export { Arena } from "./arena/arena.js";
58
79
  export { MODEL_PRESETS, getMaxOutputTokens } from "./arena/model-presets.js";
59
80
  export type { ModelPreset } from "./arena/model-presets.js";
@@ -69,11 +90,12 @@ export { transitionClaim, resolveClaimStatus, markUnderReview, applyReviewResult
69
90
  export type { ArenaConfig, ArenaMode, ArenaResultV2, ArenaStrategy, ArenaParticipant, ArenaBaseContext, ArenaFinding, FindingReview, ParticipantReport, ArenaConsensus, ArenaConsensusItem, ArenaRoadmapPhase, ArenaProgressEvent, ArenaPlan, ArenaLens, ArenaLensName, ArenaSourceKind, ArenaArtifact, ArenaQuickFact, FindingKind, PeerVerdict, ToolTrace, EvidencePacket, FindingEvidenceLink, ResearchDossier, ClaimStatus, ClaimRecord, ClaimChallenge, ClaimAdjudication, RequestedCheck, DebateRound, DebateTurn, TargetedCheckTask, SharedResearchLedger, RoundResearchDigest, ArenaExecutionLimits, } from "./arena/types.js";
70
91
  export { IterativeArena, defaultIterateConvergence, iterateDiffRatio, iterateCodeFormat, iterateDocumentFormat, getIterateFormat, } from "./arena/index.js";
71
92
  export type { IterateConfig, IterateResult, IterateSubject, IterateFormat, IterateProgressEvent, IterateFormatPack, Draft, DraftCandidate, Critique, CritiqueCategory, CritiqueEvidence, CritiqueSeverity, ConvergenceSignal, Round, AuthorRotation, StoppedReason, CheckpointFn, CheckpointContext, CheckpointAction, } from "./arena/index.js";
72
- export { RunManager, type RunManagerConfig, type RunStore, FileRunStore, RunQueue, EngineRunner, type EngineRunnerConfig, type RunExecutionHandle, type RunExecutor, type CustomToolEntry, RunApprovalBackend, createRunAskUserFn, type RunLifecycleHooks, CheckpointWriter, ArtifactTracker, RunLock, Heartbeat, NoopEvaluator, CompositeEvaluator, type Evaluator, type EvaluatorResult, type EvaluatorContext, type RunStatus, type RunSnapshot, type RunEvent, type RunCheckpoint, type RunApproval, type RunArtifactRef, type SubmitRunInput, type ResumeRunInput, type ListRunsQuery, type RunStreamEvent, type RunStreamCallback, type DetachFn, VALID_TRANSITIONS, createRunManager, type CreateRunManagerOptions, } from "./run/index.js";
93
+ export { RunManager, type RunManagerConfig, type RunStore, FileRunStore, RunQueue, EngineRunner, AUTOMATION_PROMPT_NOTE, AUTOMATION_RUN_SOURCE, type EngineRunnerConfig, type RunExecutionHandle, type RunExecutor, type CustomToolEntry, RunApprovalBackend, createRunAskUserFn, type RunLifecycleHooks, CheckpointWriter, ArtifactTracker, RunLock, type RunLockConfig, type RunLockAcquireResult, Heartbeat, NoopEvaluator, CompositeEvaluator, type Evaluator, type EvaluatorResult, type EvaluatorContext, type RunStatus, type RunSnapshot, type RunEvent, type RunCheckpoint, type RunApproval, type RunArtifactRef, type SubmitRunInput, type ResumeRunInput, type ListRunsQuery, type RunStreamEvent, type RunStreamCallback, type DetachFn, VALID_TRANSITIONS, createRunManager, type CreateRunManagerOptions, } from "./run/index.js";
73
94
  export { defineProduct, type ProductDefinition, type ProductPreset, type ProductAdapter, type ProductContract, type CustomTool, type ProductRuntimeOptions, type ProductInstance, } from "./product/index.js";
74
95
  export { logger } from "./logging/logger.js";
75
- export { SettingsManager } from "./settings/manager.js";
96
+ export { SettingsManager, type SettingsScope } from "./settings/manager.js";
76
97
  export { SettingsSchema, validateSettings } from "./settings/schema.js";
98
+ export { personalizationFrom, type PersonalizationConfig } from "./settings/personalization.js";
77
99
  export { getSessionId, switchSession, getOriginalCwd, setOriginalCwd, getProjectRoot, setProjectRoot, getCwdState, getIsInteractive, updateLastInteractionTime, flushInteractionTime, markScrollActivity, type AttributedCounter, type ChannelEntry, } from "./state.js";
78
100
  export { getGraphemeSegmenter, firstGrapheme, lastGrapheme, getWordSegmenter, getRelativeTimeFormat, getTimeZone, getSystemLocaleLanguage, } from "./utils/intl.js";
79
101
  export { env } from "./utils/env.js";
@@ -96,15 +118,16 @@ export { getCurrentVersion, checkForUpdate, scheduleAutoInstallOnExit, getUpdate
96
118
  export { isGitRepo, getCurrentBranch, getGitStatus, getGitDiff, getGitDiffStat, getGitLog, gitAdd, gitCommit, gitListBranches, gitCheckout, ghAvailable, ghPrComments, } from "./git/utils.js";
97
119
  export { getInteractiveApprovalBackend } from "./tool-system/permission.js";
98
120
  export { defaultSandboxConfig, type SandboxConfig, } from "./tool-system/sandbox/index.js";
99
- export { buildNotificationMessage, buildNotificationSummary, notificationQueue, agentNotificationBus, notificationItemToStreamEvent, } from "./tool-system/builtin/agent-notifications.js";
121
+ export { buildNotificationMessage, buildNotificationSummary, notificationQueue, agentNotificationBus, notificationItemToStreamEvent, type NotificationItem, } from "./tool-system/builtin/agent-notifications.js";
100
122
  export type { BackgroundAgentCompletedEvent } from "./types.js";
123
+ export { startAutomation, type StartAutomationDeps, type AutomationHandle, CronScheduler, cronScheduler, type CronJob, type CronPermissionLevel, type CreateJobOptions, type UpdateJobPatch, CronStore, defaultCronStorePath, bindCronToEngine, bindCronToRunManager, type CronRunner, type CronRunRequest, type CronRunResult, type RunSubmitter, isCronExpression, parseCronExpression, nextCronTime, type ParsedCron, resolveWritePolicy, wrapUntrustedInput, type WritePolicy, runWriteJobInWorktree, type WriteJobGitOps, type RunWriteJobInput, type RunWriteJobResult, } from "./automation/index.js";
101
124
  export { asyncAgentRegistry, type AsyncAgentEntry, } from "./tool-system/builtin/agent-registry.js";
102
125
  export { createInProcessClient } from "./protocol/helpers.js";
103
126
  export type { ProtocolModelEntry } from "./protocol/types.js";
104
127
  export { formatArenaResult, printArenaResult, renderProgress, createProgressRenderer, type OutputSink, } from "./arena/render/terminal.js";
105
128
  export { formatArenaResultForSession } from "./arena/render/session.js";
106
129
  export { installPlugin, uninstallPlugin, listInstalled, } from "./plugins/pluginInstaller.js";
107
- export { addMarketplace, removeMarketplace, listMarketplaces, } from "./plugins/marketplaceManager.js";
130
+ export { addMarketplace, removeMarketplace, listMarketplaces, loadMarketplace, } from "./plugins/marketplaceManager.js";
108
131
  export { parseMarketplaceInput, deriveMarketplaceName, } from "./plugins/parseMarketplaceInput.js";
109
132
  export { scanPluginCommands, type PluginCommand, } from "./plugins/pluginCommandsLoader.js";
110
133
  export { type CachedModel, defaultCacheDir, } from "./llm/model-cache.js";
@@ -112,6 +135,8 @@ export { fetchModelList, type FetchResult, } from "./llm/model-fetcher.js";
112
135
  export { sanitizeApiKey, hasNonAsciiPrintable, } from "./llm/api-key-sanitize.js";
113
136
  export { PROVIDER_KINDS, type ProviderKindName, } from "./llm/provider-kinds.js";
114
137
  export { capabilitiesFor, type Capability, } from "./llm/capabilities/index.js";
138
+ export { reasoningControlFor, type ReasoningControl, } from "./llm/capabilities/reasoning-control.js";
139
+ export { REASONING_EFFORTS, type ReasoningSetting, } from "./llm/reasoning-setting.js";
115
140
  export { type ProviderConfig } from "./llm/provider-catalog.js";
116
141
  export { syncOpenRouterCatalog, getOpenRouterSnapshot, } from "./data/openrouter-sync.js";
117
142
  export type { ApprovalRequest, ApprovalResult, ApprovalScope, TaskInfo, } from "./types.js";
package/dist/index.js CHANGED
@@ -7,7 +7,9 @@ export const VERSION = "0.5.0-rc.0";
7
7
  // ─── Exceptions ──────────────────────────────────────────────────
8
8
  export { FrameworkError, LLMError, LLMRateLimitError, ContextLimitError, ToolError, ToolNotFoundError, ToolExecutionError, ToolTimeoutError, PermissionDeniedError, SessionError, TranscriptError, ConfigError, SandboxUnavailableError, } from "./exceptions.js";
9
9
  // ─── Engine (primary API) ────────────────────────────────────────
10
- export { Engine } from "./engine/engine.js";
10
+ export { Engine, loadAgentDefinitionsForCwd } from "./engine/engine.js";
11
+ export { parseAgentDefinition, serializeAgentDefinition, } from "./agent/agent-definition.js";
12
+ export { AgentDefinitionRegistry, } from "./agent/agent-definition-registry.js";
11
13
  export { EngineRuntime } from "./engine/runtime.js";
12
14
  export { ChatSessionManager } from "./protocol/chat-session-manager.js";
13
15
  // ─── LLM ─────────────────────────────────────────────────────────
@@ -21,6 +23,7 @@ export { ToolRegistry } from "./tool-system/registry.js";
21
23
  export { ToolExecutor } from "./tool-system/executor.js";
22
24
  export { PermissionClassifier, HeadlessApprovalBackend, AutoApprovalBackend } from "./tool-system/permission.js";
23
25
  export { BUILTIN_TOOLS } from "./tool-system/builtin/index.js";
26
+ export { makeUpdateAutomationMemoryTool } from "./tool-system/builtin/update-automation-memory.js";
24
27
  export { MCPManager } from "./tool-system/mcp-manager.js";
25
28
  // ─── Hooks ───────────────────────────────────────────────────────
26
29
  export { HookRegistry } from "./hooks/registry.js";
@@ -29,6 +32,7 @@ export { wrapHookMessages } from "./hooks/inject.js";
29
32
  export { AgentServer } from "./protocol/server.js";
30
33
  export { AgentClient } from "./protocol/client.js";
31
34
  export { createInProcessTransport, StdioTransport, } from "./protocol/transport.js";
35
+ export { SocketTransport, listenTcp, } from "./protocol/tcp-transport.js";
32
36
  // Recommended public factories — see protocol/factories.ts for the
33
37
  // stable construction contract referenced by standard §7.
34
38
  export { createServer, createClient, } from "./protocol/factories.js";
@@ -38,6 +42,7 @@ export { Transcript } from "./session/transcript.js";
38
42
  export { SessionManager } from "./session/session-manager.js";
39
43
  export { FileHistory } from "./session/file-history.js";
40
44
  export { MemoryManager } from "./session/memory.js";
45
+ export { runDreamConsolidation, } from "./services/dream-consolidation.js";
41
46
  // ─── Prompt ──────────────────────────────────────────────────────
42
47
  export { PromptComposer } from "./prompt/composer.js";
43
48
  export { SectionCache } from "./prompt/section-cache.js";
@@ -51,6 +56,21 @@ export { estimateTokens, microcompact, windowCompact, truncateToolResult, buildS
51
56
  export { applyToolResultPersistence, createContentReplacementState, reconstructContentReplacementState, resolveToolResultsDir, isPersistedReplacement, DEFAULT_PERSIST_THRESHOLD, PER_MESSAGE_AGGREGATE_CAP, PREVIEW_SIZE, } from "./context/tool-result-storage.js";
52
57
  // ─── Skills ──────────────────────────────────────────────────────
53
58
  export { scanSkills, invalidateSkillCache } from "./skills/index.js";
59
+ // ─── Capability control (扩展能力 backend) ───────────────────────
60
+ export { CapabilityService, CapabilityNotFoundError, projectBuiltin, projectMcp, projectSkills, projectPlugins, } from "./capability-control/index.js";
61
+ export { readInstalledPlugins } from "./plugins/installedPlugins.js";
62
+ // ─── Plugin installer (CC + Codex) ───────────────────────────────
63
+ export { installPluginFromPath } from "./plugins/installer/install.js";
64
+ export { installPluginFromSource } from "./plugins/installer/installFromSource.js";
65
+ export { parseSource } from "./plugins/installer/parseSource.js";
66
+ export { detectPluginFormat } from "./plugins/installer/detectFormat.js";
67
+ export { CodexPluginManifest, CSMeta, PluginInstallError, } from "./plugins/installer/types.js";
68
+ export { mergePluginMcpServers } from "./plugins/installer/loadPluginMcp.js";
69
+ export { pluginAgentDirs } from "./plugins/installer/loadPluginAgents.js";
70
+ export { appendInstallEntry, pluginInstallKey, removeInstallEntries, } from "./plugins/installedPlugins.js";
71
+ export { uninstallPluginByName } from "./plugins/installer/uninstall.js";
72
+ export { listInstalledPlugins } from "./plugins/installer/list.js";
73
+ export { updatePluginByName } from "./plugins/installer/update.js";
54
74
  // ─── Arena ───────────────────────────────────────────────────────
55
75
  export { Arena } from "./arena/arena.js";
56
76
  export { MODEL_PRESETS, getMaxOutputTokens } from "./arena/model-presets.js";
@@ -75,7 +95,7 @@ RunManager, FileRunStore,
75
95
  // Queue
76
96
  RunQueue,
77
97
  // Runner
78
- EngineRunner,
98
+ EngineRunner, AUTOMATION_PROMPT_NOTE, AUTOMATION_RUN_SOURCE,
79
99
  // Approval / Input adapters
80
100
  RunApprovalBackend, createRunAskUserFn,
81
101
  // Checkpoint & Artifacts
@@ -93,6 +113,7 @@ export { logger } from "./logging/logger.js";
93
113
  // ─── Settings ────────────────────────────────────────────────────
94
114
  export { SettingsManager } from "./settings/manager.js";
95
115
  export { SettingsSchema, validateSettings } from "./settings/schema.js";
116
+ export { personalizationFrom } from "./settings/personalization.js";
96
117
  // ─── State (runtime singletons shared with TUI) ──────────────────
97
118
  export { getSessionId, switchSession, getOriginalCwd, setOriginalCwd, getProjectRoot, setProjectRoot, getCwdState, getIsInteractive, updateLastInteractionTime, flushInteractionTime, markScrollActivity, } from "./state.js";
98
119
  // ─── Utils (shared primitives used by TUI) ───────────────────────
@@ -124,6 +145,10 @@ export { isGitRepo, getCurrentBranch, getGitStatus, getGitDiff, getGitDiffStat,
124
145
  export { getInteractiveApprovalBackend } from "./tool-system/permission.js";
125
146
  export { defaultSandboxConfig, } from "./tool-system/sandbox/index.js";
126
147
  export { buildNotificationMessage, buildNotificationSummary, notificationQueue, agentNotificationBus, notificationItemToStreamEvent, } from "./tool-system/builtin/agent-notifications.js";
148
+ // Automation — zero-env-dependency scheduling module (startAutomation facade
149
+ // + scheduler/store/runner). Hosts (Electron main, future CLI server) load
150
+ // this and inject store + runner. See docs/automation-plan-2026-05-31.md.
151
+ export { startAutomation, CronScheduler, cronScheduler, CronStore, defaultCronStorePath, bindCronToEngine, bindCronToRunManager, isCronExpression, parseCronExpression, nextCronTime, resolveWritePolicy, wrapUntrustedInput, runWriteJobInWorktree, } from "./automation/index.js";
127
152
  export { asyncAgentRegistry, } from "./tool-system/builtin/agent-registry.js";
128
153
  // ─── Protocol (extended for TUI) ────────────────────────────────
129
154
  export { createInProcessClient } from "./protocol/helpers.js";
@@ -132,7 +157,7 @@ export { formatArenaResult, printArenaResult, renderProgress, createProgressRend
132
157
  export { formatArenaResultForSession } from "./arena/render/session.js";
133
158
  // ─── Plugins ─────────────────────────────────────────────────────
134
159
  export { installPlugin, uninstallPlugin, listInstalled, } from "./plugins/pluginInstaller.js";
135
- export { addMarketplace, removeMarketplace, listMarketplaces, } from "./plugins/marketplaceManager.js";
160
+ export { addMarketplace, removeMarketplace, listMarketplaces, loadMarketplace, } from "./plugins/marketplaceManager.js";
136
161
  export { parseMarketplaceInput, deriveMarketplaceName, } from "./plugins/parseMarketplaceInput.js";
137
162
  export { scanPluginCommands, } from "./plugins/pluginCommandsLoader.js";
138
163
  // ─── LLM (extended for TUI) ─────────────────────────────────────
@@ -141,5 +166,7 @@ export { fetchModelList, } from "./llm/model-fetcher.js";
141
166
  export { sanitizeApiKey, hasNonAsciiPrintable, } from "./llm/api-key-sanitize.js";
142
167
  export { PROVIDER_KINDS, } from "./llm/provider-kinds.js";
143
168
  export { capabilitiesFor, } from "./llm/capabilities/index.js";
169
+ export { reasoningControlFor, } from "./llm/capabilities/reasoning-control.js";
170
+ export { REASONING_EFFORTS, } from "./llm/reasoning-setting.js";
144
171
  // ─── Data ────────────────────────────────────────────────────────
145
172
  export { syncOpenRouterCatalog, getOpenRouterSnapshot, } from "./data/openrouter-sync.js";
@@ -0,0 +1,24 @@
1
+ /**
2
+ * reasoningControlFor — projects a model's ReasoningShape into "what control
3
+ * the UI should render". The UI never branches on provider; it switches on
4
+ * ReasoningControl.kind. Mirrors the capability-control descriptor pattern.
5
+ */
6
+ import type { ProviderKindName } from "../provider-kinds.js";
7
+ import type { ReasoningEffort } from "./types.js";
8
+ export type ReasoningControl = {
9
+ kind: "none";
10
+ } | {
11
+ kind: "toggle";
12
+ default: boolean;
13
+ } | {
14
+ kind: "effort";
15
+ options: ReasoningEffort[];
16
+ default: ReasoningEffort;
17
+ } | {
18
+ kind: "budget";
19
+ min: number;
20
+ default: number;
21
+ } | {
22
+ kind: "adaptive";
23
+ };
24
+ export declare function reasoningControlFor(kind: ProviderKindName, model: string): ReasoningControl;
@@ -0,0 +1,38 @@
1
+ import { capabilitiesFor } from "./index.js";
2
+ const FULL_EFFORTS = ["minimal", "low", "medium", "high"];
3
+ export function reasoningControlFor(kind, model) {
4
+ const cap = capabilitiesFor(kind, model);
5
+ const r = cap.reasoning;
6
+ switch (r.kind) {
7
+ case "none":
8
+ return { kind: "none" };
9
+ case "deepseek-thinking":
10
+ return { kind: "toggle", default: true };
11
+ case "anthropic-adaptive":
12
+ return { kind: "adaptive" };
13
+ case "anthropic-budget":
14
+ return {
15
+ kind: "budget",
16
+ min: r.minBudgetTokens,
17
+ default: Math.max(r.minBudgetTokens, 4096),
18
+ };
19
+ case "openrouter-reasoning":
20
+ // OpenRouter normalizes to minimal..high (no xhigh passthrough).
21
+ return { kind: "effort", options: FULL_EFFORTS, default: "medium" };
22
+ case "openai-effort": {
23
+ // Prefer the capability's first-class supportedEfforts list (gpt-5.5 →
24
+ // low..xhigh, magistral → [high]). Fall back to the default four levels
25
+ // when a rule didn't specify one. We no longer infer the level set from
26
+ // disabledEffort — that's a wire-detail two vendors can coincidentally
27
+ // share (gpt-5.5 and magistral both use "none"), so inferring misrendered
28
+ // magistral as a gpt-5.5-style control.
29
+ const options = r.supportedEfforts && r.supportedEfforts.length > 0
30
+ ? r.supportedEfforts
31
+ : FULL_EFFORTS;
32
+ // Default to "medium" if available, else the first offered level
33
+ // (magistral has only "high", so its default is "high").
34
+ const def = options.includes("medium") ? "medium" : options[0];
35
+ return { kind: "effort", options, default: def };
36
+ }
37
+ }
38
+ }
@@ -39,10 +39,18 @@ export const RULES = [
39
39
  "temperature", "top_p", "presence_penalty",
40
40
  "frequency_penalty", "logit_bias", "logprobs", "top_logprobs",
41
41
  ]),
42
- reasoning: { kind: "openai-effort", disabledEffort: "none" },
42
+ reasoning: {
43
+ kind: "openai-effort",
44
+ disabledEffort: "none",
45
+ supportedEfforts: ["low", "medium", "high", "xhigh"], // no "minimal"; adds "xhigh"
46
+ },
43
47
  echoReasoning: "optional",
48
+ // 400s on `max_tokens is too large: ... at most 128000`. Clamp here so a
49
+ // stale 384000 (copied from a DeepSeek/OpenRouter entry on a prior model)
50
+ // can't bleed in after a hot switch.
51
+ maxOutputTokens: 128_000,
44
52
  },
45
- why: "OpenAI gpt-5.5+ accepts reasoning_effort none|low|medium|high|xhigh (no `minimal`).",
53
+ why: "OpenAI gpt-5.5+ accepts reasoning_effort none|low|medium|high|xhigh (no `minimal`); output cap 128k.",
46
54
  },
47
55
  // ─── OpenAI native — o-series + gpt-5 through gpt-5.4 ──────────
48
56
  {
@@ -63,6 +71,24 @@ export const RULES = [
63
71
  },
64
72
  why: "OpenAI o-series + gpt-5..5.4 reject classic sampling params; use max_completion_tokens + reasoning_effort.",
65
73
  },
74
+ // ─── OpenAI native — gpt-4o / gpt-4-turbo (multimodal, non-reasoning) ──
75
+ // The famous vision models. They are NOT reasoning models, so they keep
76
+ // classic sampling params + max_tokens — only `supportsVision` differs
77
+ // from DEFAULT_CAPABILITY. Listed AFTER the gpt-5+ rules (those anchor on
78
+ // gpt-[5-9]) so neither family masks the other. Without this rule gpt-4o
79
+ // falls through to DEFAULT_CAPABILITY (supportsVision:false) and a famous
80
+ // vision model gets its history images stripped / new attachments rejected.
81
+ {
82
+ kind: "openai",
83
+ // gpt-4o, gpt-4o-mini, gpt-4-turbo, gpt-4-vision-preview, gpt-4.1*.
84
+ // gpt-4o has no separator before the "o"; the rest are `-`/`.`-separated.
85
+ // Stays clear of gpt-3.5-turbo (no vision) and gpt-5+ (handled above).
86
+ match: /^gpt-4o(?:[-.]|$)|^gpt-4(?:\.1|-turbo|-vision)(?:[-.]|$)/i,
87
+ capability: {
88
+ supportsVision: true,
89
+ },
90
+ why: "OpenAI gpt-4o / gpt-4o-mini / gpt-4-turbo / gpt-4.1 are multimodal but non-reasoning; only vision differs from default.",
91
+ },
66
92
  // ─── DeepSeek ──────────────────────────────────────────────────
67
93
  {
68
94
  kind: "deepseek",
@@ -196,7 +222,11 @@ export const RULES = [
196
222
  // Magistral series exposes reasoning_effort: high|none — no minimal/low/medium.
197
223
  match: /^magistral/i,
198
224
  capability: {
199
- reasoning: { kind: "openai-effort", disabledEffort: "none" },
225
+ reasoning: {
226
+ kind: "openai-effort",
227
+ disabledEffort: "none",
228
+ supportedEfforts: ["high"], // magistral: only high|none — "none" is the off value
229
+ },
200
230
  },
201
231
  why: "Mistral magistral models accept only reasoning_effort `high` or `none`.",
202
232
  },
@@ -9,8 +9,11 @@
9
9
  * `rules.ts` — vendor docs, not folklore.
10
10
  */
11
11
  import type { ProviderKindName } from "../provider-kinds.js";
12
- /** OpenAI-style reasoning effort levels — shared by several vendors. */
13
- export type ReasoningEffort = "minimal" | "low" | "medium" | "high";
12
+ /**
13
+ * OpenAI-style reasoning effort levels shared by several vendors.
14
+ * `xhigh` is gpt-5.5+ only (which also drops `minimal`); see rules.ts.
15
+ */
16
+ export type ReasoningEffort = "minimal" | "low" | "medium" | "high" | "xhigh";
14
17
  /** A binary thinking switch, like DeepSeek V4 and Z.AI GLM use. */
15
18
  export type ThinkingSwitch = "enabled" | "disabled";
16
19
  /**
@@ -31,10 +34,19 @@ export type ReasoningShape = {
31
34
  * "disabled" — defaults to `"minimal"` (OpenAI), but vendors with a
32
35
  * narrower vocabulary override it (e.g. xAI Grok 4.3 has no `"minimal"`;
33
36
  * Mistral Magistral only accepts `"high"` and `"none"`).
37
+ *
38
+ * `supportedEfforts` is the FIRST-CLASS list of levels a UI may offer for
39
+ * this model. Set it whenever the vocabulary differs from the default
40
+ * `["minimal","low","medium","high"]` — e.g. gpt-5.5 is
41
+ * `["low","medium","high","xhigh"]`, Mistral magistral is `["high"]`. The UI
42
+ * (reasoningControlFor) reads this directly instead of inferring the
43
+ * level set from `disabledEffort`, which is a wire-detail, not a
44
+ * capability marker (two unrelated vendors can share `disabledEffort:"none"`).
34
45
  */
35
46
  | {
36
47
  kind: "openai-effort";
37
48
  disabledEffort?: ReasoningEffort | "none";
49
+ supportedEfforts?: ReasoningEffort[];
38
50
  }
39
51
  /** Anthropic Claude 4.x ≤ 4.5 — `{thinking: {type: "enabled", budget_tokens: N}}`. */
40
52
  | {
@@ -95,6 +107,14 @@ export interface Capability {
95
107
  parallelToolCalls: ParallelToolCallsShape;
96
108
  /** Streaming usage reporting shape. */
97
109
  streamUsage: StreamUsageShape;
110
+ /**
111
+ * Known hard ceiling for max-output-tokens, when the vendor publishes one
112
+ * and exceeding it 400s. Used to clamp a requested/inherited max_tokens so
113
+ * a stale catalog value (e.g. 384000 copied from a DeepSeek/OpenRouter
114
+ * entry) can't bleed onto a smaller-cap model after a hot switch. Undefined
115
+ * = no known cap → send the request value unclamped.
116
+ */
117
+ maxOutputTokens?: number;
98
118
  }
99
119
  /**
100
120
  * Conservative default — used when no rule matches. Picks "send everything
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Clamp a requested max-output-tokens value to a model's known output cap.
3
+ *
4
+ * Background: model-pool copies a catalog `maxOutputTokens` straight into
5
+ * LLMConfig.maxTokens. For some OpenRouter/DeepSeek entries that value is huge
6
+ * (e.g. 384000) and bleeds onto a model with a much smaller cap after a hot
7
+ * switch, producing `max_tokens is too large` 400s. When the capability layer
8
+ * knows the model's real ceiling we clamp to it; when it doesn't we pass the
9
+ * value through (or omit it entirely when there is no request value).
10
+ */
11
+ export declare function clampMaxTokens(requested: number | undefined, cap: number | undefined): number | undefined;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Clamp a requested max-output-tokens value to a model's known output cap.
3
+ *
4
+ * Background: model-pool copies a catalog `maxOutputTokens` straight into
5
+ * LLMConfig.maxTokens. For some OpenRouter/DeepSeek entries that value is huge
6
+ * (e.g. 384000) and bleeds onto a model with a much smaller cap after a hot
7
+ * switch, producing `max_tokens is too large` 400s. When the capability layer
8
+ * knows the model's real ceiling we clamp to it; when it doesn't we pass the
9
+ * value through (or omit it entirely when there is no request value).
10
+ */
11
+ export function clampMaxTokens(requested, cap) {
12
+ if (requested === undefined)
13
+ return undefined;
14
+ if (cap === undefined)
15
+ return requested;
16
+ return Math.min(requested, cap);
17
+ }