mixdog 0.9.166 → 0.9.167

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 (221) hide show
  1. package/package.json +1 -1
  2. package/scripts/audit-usage-ledger.mjs +86 -0
  3. package/scripts/generate-voice-runtime-manifest.mjs +22 -17
  4. package/scripts/memory-chunk-quality.mjs +128 -0
  5. package/scripts/memory-layer2-check.mjs +133 -0
  6. package/scripts/model-catalog-audit.mjs +6 -0
  7. package/scripts/native-tool-download.mjs +14 -0
  8. package/scripts/prepare-native-assets.mjs +2 -7
  9. package/scripts/tool-failures.mjs +7 -2
  10. package/scripts/verify-release-assets.mjs +48 -90
  11. package/src/defaults/skills/browser-use/SKILL.md +33 -18
  12. package/src/defaults/skills/computer-use/SKILL.md +16 -8
  13. package/src/lib/keychain-cjs.cjs +0 -1
  14. package/src/lib/rules-builder.cjs +4 -1
  15. package/src/rules/agent/40-cycle1-agent.md +21 -13
  16. package/src/rules/lead/01-general.md +8 -3
  17. package/src/rules/shared/10-tool-workflow.md +20 -11
  18. package/src/rules/shared/30-exploration.md +11 -4
  19. package/src/rules/shared/40-editing.md +2 -3
  20. package/src/rules/shared/50-execution.md +6 -3
  21. package/src/rules/shared/60-verification.md +3 -2
  22. package/src/rules/shared/70-delivery.md +0 -4
  23. package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +51 -45
  24. package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +3 -4
  25. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +44 -7
  26. package/src/runtime/agent/orchestrator/agent-trace.mjs +9 -0
  27. package/src/runtime/agent/orchestrator/config.mjs +9 -4
  28. package/src/runtime/agent/orchestrator/context/collect.mjs +25 -1055
  29. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +272 -0
  30. package/src/runtime/agent/orchestrator/context/role-instructions.mjs +296 -0
  31. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +523 -0
  32. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +7 -2
  33. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +13 -14
  34. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +214 -0
  35. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +220 -116
  36. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-tokens.mjs +74 -44
  37. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +191 -29
  38. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +13 -12
  39. package/src/runtime/agent/orchestrator/providers/cursor-wire-guards.mjs +1 -9
  40. package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +5 -2
  41. package/src/runtime/agent/orchestrator/providers/cursor-wire.mjs +48 -25
  42. package/src/runtime/agent/orchestrator/providers/gemini-schema.mjs +28 -2
  43. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +3 -1
  44. package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +1 -8
  45. package/src/runtime/agent/orchestrator/providers/lib/action-input-contract.mjs +32 -0
  46. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +21 -6
  47. package/src/runtime/agent/orchestrator/providers/lib/grok-tool-schema.mjs +61 -13
  48. package/src/runtime/agent/orchestrator/providers/model-catalog-projection.mjs +6 -1
  49. package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +123 -118
  50. package/src/runtime/agent/orchestrator/providers/model-pricing-rates.mjs +54 -0
  51. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +5 -2
  52. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +34 -3
  53. package/src/runtime/agent/orchestrator/providers/openai-codex-endpoints.mjs +21 -0
  54. package/src/runtime/agent/orchestrator/providers/openai-oauth-catalog.mjs +154 -0
  55. package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +2 -1
  56. package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +322 -0
  57. package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +243 -702
  58. package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +2 -2
  59. package/src/runtime/agent/orchestrator/providers/openai-startup-prewarm.mjs +221 -0
  60. package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +3 -2
  61. package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +1 -1
  62. package/src/runtime/agent/orchestrator/providers/provider-catalog-cache.mjs +19 -0
  63. package/src/runtime/agent/orchestrator/providers/provider-model-identities.mjs +40 -0
  64. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +120 -710
  65. package/src/runtime/agent/orchestrator/session/cache/read-cache.mjs +36 -15
  66. package/src/runtime/agent/orchestrator/session/cache/util.mjs +9 -0
  67. package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +17 -4
  68. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +36 -31
  69. package/src/runtime/agent/orchestrator/session/compact.mjs +4 -5
  70. package/src/runtime/agent/orchestrator/session/context-compaction-policy.mjs +6 -5
  71. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +8 -6
  72. package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +121 -0
  73. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +2 -3
  74. package/src/runtime/agent/orchestrator/session/loop/diagnostics.mjs +74 -0
  75. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +44 -17
  76. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +266 -0
  77. package/src/runtime/agent/orchestrator/session/loop/request-boundary.mjs +111 -0
  78. package/src/runtime/agent/orchestrator/session/loop/request-projection.mjs +99 -0
  79. package/src/runtime/agent/orchestrator/session/loop/steering.mjs +91 -0
  80. package/src/runtime/agent/orchestrator/session/loop/usage.mjs +36 -0
  81. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +3 -3
  82. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +12 -0
  83. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +20 -11
  84. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +3 -5
  85. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +9 -3
  86. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +39 -0
  87. package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +3 -2
  88. package/src/runtime/agent/orchestrator/session/tool-batch.mjs +21 -3
  89. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +1 -1
  90. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +2 -3
  91. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +25 -25
  92. package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +62 -10
  93. package/src/runtime/agent/orchestrator/tools/builtin/path-utils.mjs +17 -0
  94. package/src/runtime/agent/orchestrator/tools/builtin/read-batch.mjs +61 -4
  95. package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +13 -9
  96. package/src/runtime/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +12 -2
  97. package/src/runtime/agent/orchestrator/tools/builtin/read-streaming.mjs +3 -2
  98. package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +8 -3
  99. package/src/runtime/agent/orchestrator/tools/builtin/runtime-capabilities.mjs +69 -6
  100. package/src/runtime/agent/orchestrator/tools/builtin.mjs +14 -17
  101. package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +1 -1
  102. package/src/runtime/agent/orchestrator/tools/code-graph/source-access.mjs +1 -1
  103. package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +6 -6
  104. package/src/runtime/agent/orchestrator/tools/patch-tool-defs.mjs +1 -1
  105. package/src/runtime/bridge-discovery.mjs +8 -0
  106. package/src/runtime/browser-bridge/action-schema.mjs +37 -43
  107. package/src/runtime/browser-bridge/client.mjs +111 -99
  108. package/src/runtime/browser-bridge/input-fields.mjs +187 -0
  109. package/src/runtime/browser-bridge/tool-defs.mjs +12 -227
  110. package/src/runtime/computer-bridge/action-schema.mjs +2 -46
  111. package/src/runtime/computer-bridge/client.mjs +69 -77
  112. package/src/runtime/computer-bridge/core-actions.mjs +7 -5
  113. package/src/runtime/computer-bridge/error-recovery.mjs +41 -37
  114. package/src/runtime/computer-bridge/tool-defs.mjs +1 -1
  115. package/src/runtime/github/commands.mjs +4 -1
  116. package/src/runtime/github/contract.mjs +1 -1
  117. package/src/runtime/github/tool.mjs +2 -2
  118. package/src/runtime/media/adapters/antigravity-image.mjs +72 -0
  119. package/src/runtime/media/adapters/gemini-image.mjs +20 -11
  120. package/src/runtime/media/auth.mjs +12 -0
  121. package/src/runtime/media/catalog.mjs +30 -10
  122. package/src/runtime/media/jobs.mjs +4 -0
  123. package/src/runtime/media/lanes.mjs +40 -31
  124. package/src/runtime/memory/index.mjs +2 -9
  125. package/src/runtime/memory/lib/compact-handoff.mjs +26 -18
  126. package/src/runtime/memory/lib/memory-chunk-audit.mjs +41 -0
  127. package/src/runtime/memory/lib/memory-chunk-quality.mjs +388 -0
  128. package/src/runtime/memory/lib/memory-cycle1.mjs +95 -394
  129. package/src/runtime/memory/lib/memory-recall-scope-filter.mjs +29 -4
  130. package/src/runtime/memory/lib/memory-recall-store.mjs +8 -12
  131. package/src/runtime/memory/lib/memory-retrievers.mjs +8 -11
  132. package/src/runtime/memory/lib/memory.mjs +2 -0
  133. package/src/runtime/memory/lib/query-handlers.mjs +98 -144
  134. package/src/runtime/memory/lib/query-ranking.mjs +23 -9
  135. package/src/runtime/memory/lib/recall-format.mjs +37 -27
  136. package/src/runtime/memory/lib/session-ingest-runtime.mjs +14 -8
  137. package/src/runtime/memory/lib/session-ingest.mjs +45 -84
  138. package/src/runtime/memory/lib/transcript-ingest.mjs +19 -21
  139. package/src/runtime/memory/tool-defs.mjs +2 -2
  140. package/src/runtime/office/authoring/pptx-author-session.mjs +3 -7
  141. package/src/runtime/office/core/office-actions-batch.mjs +2 -8
  142. package/src/runtime/office/core/office-actions-open.mjs +124 -0
  143. package/src/runtime/office/core/office-actions-read.mjs +127 -0
  144. package/src/runtime/office/core/office-core.mjs +80 -1
  145. package/src/runtime/office/core/office-sessions.mjs +116 -138
  146. package/src/runtime/office/index.mjs +18 -271
  147. package/src/runtime/office/pdf/pdf-analysis.mjs +2 -2
  148. package/src/runtime/office/pdf/pdf-limits.mjs +2 -0
  149. package/src/runtime/office/tool-defs.mjs +7 -6
  150. package/src/runtime/shared/agent-route-config.mjs +8 -8
  151. package/src/runtime/shared/child-spawn-gate.mjs +10 -13
  152. package/src/runtime/shared/config.mjs +2 -7
  153. package/src/runtime/shared/env.mjs +3 -3
  154. package/src/runtime/shared/err-text.mjs +1 -1
  155. package/src/runtime/shared/extension-scopes.mjs +3 -2
  156. package/src/runtime/shared/heap-cap.mjs +10 -6
  157. package/src/runtime/shared/llm/cost.mjs +35 -10
  158. package/src/runtime/shared/llm/usage-accounting.mjs +11 -1
  159. package/src/runtime/shared/llm/usage-context.mjs +6 -0
  160. package/src/runtime/shared/llm/usage-ledger-import.mjs +5 -0
  161. package/src/runtime/shared/llm/usage-ledger-repair.mjs +109 -0
  162. package/src/runtime/shared/llm/usage-ledger.mjs +59 -20
  163. package/src/runtime/shared/llm/usage-pricing-refresh.mjs +26 -0
  164. package/src/runtime/shared/llm/usage-rollup.mjs +17 -15
  165. package/src/runtime/shared/native-asset.mjs +3 -4
  166. package/src/runtime/shared/object.mjs +4 -0
  167. package/src/runtime/shared/pg-schema-db.mjs +21 -0
  168. package/src/runtime/shared/plugin-metadata.mjs +3 -1
  169. package/src/runtime/shared/resource-admission.mjs +1 -6
  170. package/src/runtime/shared/schedules-db.mjs +8 -24
  171. package/src/runtime/shared/schema-value-error.d.mts +2 -0
  172. package/src/runtime/shared/schema-value-error.mjs +68 -0
  173. package/src/runtime/shared/singleton-owner.mjs +11 -24
  174. package/src/runtime/shared/staged-update.mjs +1 -10
  175. package/src/runtime/shared/tool-card-model.mjs +8 -5
  176. package/src/runtime/shared/tool-execution-contract.mjs +1 -1
  177. package/src/runtime/shared/tool-surface.mjs +1 -5
  178. package/src/runtime/shared/user-data-guard.mjs +1 -4
  179. package/src/runtime/shared/webhooks-db.mjs +8 -24
  180. package/src/runtime/web-search/index.mjs +32 -8
  181. package/src/runtime/web-search/tool-defs.mjs +4 -4
  182. package/src/session-runtime/config-lifecycle.mjs +34 -0
  183. package/src/session-runtime/context-status.mjs +19 -0
  184. package/src/session-runtime/cwd-plugins.mjs +12 -29
  185. package/src/session-runtime/goal-tasks.mjs +2 -2
  186. package/src/session-runtime/goal-tool-defs.mjs +3 -2
  187. package/src/session-runtime/internal-tool-executor.mjs +7 -0
  188. package/src/session-runtime/lifecycle-api.mjs +5 -11
  189. package/src/session-runtime/notification-bus.mjs +41 -0
  190. package/src/session-runtime/prewarm.mjs +22 -0
  191. package/src/session-runtime/runtime-bootstrap.mjs +90 -0
  192. package/src/session-runtime/runtime-core.mjs +88 -202
  193. package/src/session-runtime/runtime-feature-gates.mjs +37 -0
  194. package/src/session-runtime/session-lifecycle.mjs +5 -5
  195. package/src/session-runtime/session-turn-api.mjs +1 -12
  196. package/src/session-runtime/setup-tool/executor.mjs +13 -5
  197. package/src/session-runtime/setup-tool/tool-defs.mjs +52 -46
  198. package/src/session-runtime/tool-defs.mjs +73 -4
  199. package/src/session-runtime/usage-stats-api.mjs +4 -1
  200. package/src/session-runtime/warmup-schedulers.mjs +8 -2
  201. package/src/session-runtime/workflow.mjs +14 -0
  202. package/src/standalone/channel-session-router.mjs +3 -1
  203. package/src/standalone/channel-worker.mjs +18 -9
  204. package/src/standalone/daemon-crash-capture.mjs +534 -0
  205. package/src/standalone/daemon-telemetry.mjs +175 -0
  206. package/src/standalone/daemon.mjs +31 -21
  207. package/src/standalone/session-client.mjs +31 -23
  208. package/src/standalone/usage-dashboard-model.mjs +2 -0
  209. package/src/standalone/usage-stats-hours.mjs +18 -11
  210. package/src/standalone/usage-stats-model.mjs +39 -28
  211. package/src/standalone/usage-stats-period.mjs +43 -45
  212. package/src/tui/app/use-transcript-window.mjs +1 -1
  213. package/src/tui/components/StatusLine.jsx +13 -42
  214. package/src/tui/dist/index.mjs +256 -239
  215. package/src/tui/session/session-api-ext.mjs +44 -41
  216. package/src/tui/session/session-api.mjs +4 -0
  217. package/src/tui/session/tool-card-results.mjs +25 -78
  218. package/src/tui/session/tool-result-status.mjs +94 -1
  219. package/src/tui/session/turn-aggregate-cards.mjs +17 -54
  220. package/src/ui/statusline-format.mjs +6 -26
  221. package/src/workflows/default/WORKFLOW.md +5 -0
@@ -4,7 +4,8 @@
4
4
  * they do for a UI click. The facade is read lazily because runtime-core
5
5
  * registers the tool executor before it finishes assembling the API object. */
6
6
  import { builtinFeatureActive } from '../builtin-features.mjs';
7
- import { SETUP_ACTIONS, SETUP_OPEN_TARGETS, SETUP_STATUS_DOMAINS } from './tool-defs.mjs';
7
+ import { SETUP_ACTIONS, SETUP_ACTION_FIELDS, SETUP_OPEN_TARGETS, SETUP_STATUS_DOMAINS, SETUP_TOOL_DEFS, SETUP_BUILTIN_TOGGLE_FEATURES } from './tool-defs.mjs';
8
+ import { schemaValueError } from '../../runtime/shared/schema-value-error.mjs';
8
9
 
9
10
  const clean = (value) => String(value ?? '').trim();
10
11
 
@@ -48,8 +49,7 @@ function requireText(value, label) {
48
49
  return text;
49
50
  }
50
51
 
51
- function routeInput(route) {
52
- const source = route && typeof route === 'object' ? route : {};
52
+ function routeInput(source) {
53
53
  const next = {};
54
54
  if (clean(source.provider) || Object.prototype.hasOwnProperty.call(source, 'provider')) next.provider = clean(source.provider);
55
55
  if (clean(source.model)) next.model = clean(source.model);
@@ -192,6 +192,14 @@ export function createSetupToolExecutor({ getApi, getConfig, notifySessionUi, ge
192
192
 
193
193
  async function execute(args = {}) {
194
194
  const action = requireEnum(args?.action, SETUP_ACTIONS, 'action');
195
+ const validationError = schemaValueError({ ...args, action }, SETUP_TOOL_DEFS[0].inputSchema, 'setup');
196
+ if (validationError) throw new Error(`[tool-input-validation] ${validationError}`);
197
+ const fields = SETUP_ACTION_FIELDS[action].split(' ').filter(Boolean);
198
+ const allowed = fields.map((field) => field.replace(/\?$/, ''));
199
+ const extras = Object.keys(args).filter((field) => field !== 'action' && !allowed.includes(field));
200
+ if (extras.length) throw new Error(`[tool-input-validation] setup.${action} does not accept field(s): ${extras.join(', ')}`);
201
+ const missing = fields.find((field) => !field.endsWith('?') && !Object.hasOwn(args, field));
202
+ if (missing) throw new Error(`[tool-input-validation] ${missing} is required for setup.${action}`);
195
203
  const rt = action === 'status' || action === 'open' ? null : api();
196
204
  switch (action) {
197
205
  case 'status': {
@@ -235,7 +243,7 @@ export function createSetupToolExecutor({ getApi, getConfig, notifySessionUi, ge
235
243
  case 'set_recap_enabled': return rt.setRecapEnabled(requireBoolean(args.enabled));
236
244
  case 'set_web_search_enabled': return await rt.setWebSearchEnabled(requireBoolean(args.enabled));
237
245
  case 'set_builtin_enabled': {
238
- const name = requireEnum(args.name, ['git', 'office', 'localProvider'], 'name');
246
+ const name = requireEnum(args.name, SETUP_BUILTIN_TOGGLE_FEATURES, 'name');
239
247
  return await rt.setBuiltinToolEnabled(name, requireBoolean(args.enabled));
240
248
  }
241
249
  case 'set_first_use_approval': {
@@ -298,7 +306,7 @@ export function createSetupToolExecutor({ getApi, getConfig, notifySessionUi, ge
298
306
  }
299
307
  case 'set_extension_scope': {
300
308
  const kind = requireEnum(args.kind, ['skills', 'mcp', 'plugins'], 'kind');
301
- const projects = Array.isArray(args.projects) ? args.projects.map(clean).filter(Boolean) : [];
309
+ const projects = args.projects.map(clean);
302
310
  const status = await rt.setExtensionScope(kind, requireText(args.name, 'name'), projects);
303
311
  if (kind === 'mcp') return { mcp: mcpRows(status) };
304
312
  return status || {};
@@ -47,48 +47,54 @@ export const SETUP_OPEN_TARGETS = Object.freeze([
47
47
  'context',
48
48
  ]);
49
49
 
50
- export const SETUP_ACTIONS = Object.freeze([
51
- 'status',
52
- 'open',
53
- 'set_route',
54
- 'set_agent_route',
55
- 'set_web_search_route',
56
- 'set_workflow',
57
- 'set_output_style',
58
- 'set_profile',
59
- 'set_autoclear',
60
- 'set_compaction',
61
- 'set_memory_enabled',
62
- 'set_recap_enabled',
63
- 'set_web_search_enabled',
64
- 'set_builtin_enabled',
65
- 'set_first_use_approval',
66
- 'install_builtin',
67
- 'install_local_model',
68
- 'start_local_installation',
69
- 'cancel_local_installation',
70
- 'set_local_idle_ttl',
71
- 'search_local_models',
72
- 'inspect_hf_model',
73
- 'register_hf_model',
74
- 'local_model_details',
75
- 'maintain_local_model',
76
- 'delete_local_model',
77
- 'set_system_shell',
78
- 'set_auto_update',
79
- 'forget_provider_auth',
80
- 'add_mcp_server',
81
- 'save_mcp_server',
82
- 'remove_mcp_server',
83
- 'set_mcp_enabled',
84
- 'reconnect_mcp',
85
- 'set_disabled_skills',
86
- 'set_extension_scope',
87
- 'add_plugin',
88
- 'update_plugin',
89
- 'set_plugin_enabled',
90
- 'remove_plugin',
91
- ]);
50
+ // Runtime dispatch contract. A trailing ? denotes an optional field. Keep
51
+ // this out of the wire schema: field descriptions already name their actions.
52
+ export const SETUP_ACTION_FIELDS = Object.freeze({
53
+ status: 'domain?',
54
+ open: 'target',
55
+ set_route: 'route',
56
+ set_agent_route: 'agent route',
57
+ set_web_search_route: 'route',
58
+ set_workflow: 'workflow',
59
+ set_output_style: 'style',
60
+ set_profile: 'profile',
61
+ set_autoclear: 'autoclear',
62
+ set_compaction: 'enabled',
63
+ set_memory_enabled: 'enabled',
64
+ set_recap_enabled: 'enabled',
65
+ set_web_search_enabled: 'enabled',
66
+ set_builtin_enabled: 'name enabled',
67
+ set_first_use_approval: 'name enabled',
68
+ install_builtin: 'name',
69
+ install_local_model: 'modelId',
70
+ start_local_installation: 'phase modelId?',
71
+ cancel_local_installation: 'jobId',
72
+ set_local_idle_ttl: 'idleTtlSeconds?',
73
+ search_local_models: 'query',
74
+ inspect_hf_model: 'repository filename? contextWindow?',
75
+ register_hf_model: 'previewId licenseAccepted',
76
+ local_model_details: 'modelId',
77
+ maintain_local_model: 'modelId operation',
78
+ delete_local_model: 'confirmationToken',
79
+ set_system_shell: 'command',
80
+ set_auto_update: 'enabled',
81
+ forget_provider_auth: 'name',
82
+ add_mcp_server: 'server',
83
+ save_mcp_server: 'server',
84
+ remove_mcp_server: 'name',
85
+ set_mcp_enabled: 'name enabled',
86
+ reconnect_mcp: '',
87
+ set_disabled_skills: 'skills',
88
+ set_extension_scope: 'kind name projects',
89
+ add_plugin: 'source',
90
+ update_plugin: 'name',
91
+ set_plugin_enabled: 'name enabled',
92
+ remove_plugin: 'name',
93
+ });
94
+
95
+ export const SETUP_ACTIONS = Object.freeze(Object.keys(SETUP_ACTION_FIELDS));
96
+
97
+ export const SETUP_BUILTIN_TOGGLE_FEATURES = Object.freeze(['git', 'office', 'localProvider']);
92
98
 
93
99
  const ROUTE_SCHEMA = {
94
100
  type: 'object',
@@ -119,7 +125,7 @@ export const SETUP_TOOL_DEFS = Object.freeze([
119
125
  additionalProperties: false,
120
126
  required: ['action'],
121
127
  properties: {
122
- action: { type: 'string', enum: [...SETUP_ACTIONS] },
128
+ action: { type: 'string', enum: [...SETUP_ACTIONS], description: 'Pass only fields for this action.' },
123
129
  domain: { type: 'string', enum: [...SETUP_STATUS_DOMAINS], description: 'status: which domain to read; default summary.' },
124
130
  target: { type: 'string', enum: [...SETUP_OPEN_TARGETS], description: 'open: settings surface, named by its slash command.' },
125
131
  route: { ...ROUTE_SCHEMA, description: 'set_route / set_agent_route / set_web_search_route. set_agent_route with provider "" restores inheritance.' },
@@ -140,7 +146,7 @@ export const SETUP_TOOL_DEFS = Object.freeze([
140
146
  },
141
147
  },
142
148
  enabled: { type: 'boolean', description: 'Boolean setters (set_*_enabled, set_first_use_approval, set_compaction, set_auto_update, set_mcp_enabled, set_plugin_enabled).' },
143
- name: { type: 'string', description: 'Feature (git|memory|office|localProvider; browser|computer for set_first_use_approval), MCP server, plugin id, or provider id, per action.' },
149
+ name: { type: 'string', description: `set_builtin_enabled: ${SETUP_BUILTIN_TOGGLE_FEATURES.join('|')}; install_builtin also accepts memory. Memory toggles use set_memory_enabled. set_first_use_approval: browser|computer; else MCP/plugin/provider id.` },
144
150
  modelId: { type: 'string', description: 'install_local_model: exact model id from status domain local-provider; runtime must already be installed.' },
145
151
  phase: { type: 'string', enum: ['runtime', 'model'], description: 'start_local_installation: which managed asset to install or resume. Model phase requires modelId.' },
146
152
  jobId: { type: 'string', description: 'cancel_local_installation: current jobId from local-provider status.' },
@@ -153,12 +159,12 @@ export const SETUP_TOOL_DEFS = Object.freeze([
153
159
  licenseAccepted: { type: 'boolean', description: 'register_hf_model: explicit acceptance of the inspected license and installation plan.' },
154
160
  operation: { type: 'string', enum: ['verify', 'repair'], description: 'maintain_local_model: verify SHA-256 or redownload the pinned model; returns a background job.' },
155
161
  confirmationToken: { type: 'string', description: 'delete_local_model: unexpired token from local_model_details.' },
156
- command: { type: 'string', description: 'set_system_shell: shell command; empty restores automatic selection.' },
162
+ command: { type: 'string', description: 'set_system_shell: required shell command; "" restores automatic selection.' },
157
163
  server: { type: 'object', additionalProperties: true, description: 'add_mcp_server / save_mcp_server: {name, type, command, args, cwd, env} or {name, type, url, headers}.' },
158
164
  skills: { type: 'array', items: { type: 'string' }, description: 'set_disabled_skills: full list of disabled skill names.' },
159
165
  source: { type: 'string', description: 'add_plugin: Git URL, owner/repo, or local path.' },
160
166
  kind: { type: 'string', enum: ['skills', 'mcp', 'plugins'], description: 'set_extension_scope: which extension list `name` belongs to.' },
161
- projects: { type: 'array', items: { type: 'string' }, description: 'set_extension_scope: project root paths the extension is limited to; empty = every project.' },
167
+ projects: { type: 'array', items: { type: 'string', minLength: 1, pattern: '\\S' }, description: 'set_extension_scope: required project roots; [] = every project.' },
162
168
  },
163
169
  },
164
170
  },
@@ -13,11 +13,11 @@ export const TOOL_SEARCH_TOOL = {
13
13
  openWorldHint: false,
14
14
  agentHidden: true,
15
15
  },
16
- description: 'Load full schemas for exact deferred tool names/aliases not already available; returns function descriptions and parameter schemas.',
16
+ description: 'Load full schemas for missing deferred tool names/aliases; batch needed names in one call.',
17
17
  inputSchema: {
18
18
  type: 'object',
19
19
  properties: {
20
- names: { anyOf: [{ type: 'string' }, { type: 'array', items: { type: 'string' } }], description: 'Exact deferred tool names/aliases to load.' },
20
+ names: { anyOf: [{ type: 'string' }, { type: 'array', items: { type: 'string' } }], description: 'Exact name(s)/aliases.' },
21
21
  },
22
22
  required: ['names'],
23
23
  additionalProperties: false,
@@ -35,11 +35,12 @@ export const CWD_TOOL = {
35
35
  openWorldHint: false,
36
36
  agentHidden: true,
37
37
  },
38
- description: 'Show the active Project, or set it to path. A shell-local cd does not change the Project.',
38
+ description: 'Show or switch the working directory (active Project). action=list returns the registered projects (name, path); when the user gives a project name instead of a path, list first, then set with the matching path and ask only if several candidates match. path must be an existing directory. A shell-local cd does not change the Project.',
39
39
  inputSchema: {
40
40
  type: 'object',
41
41
  properties: {
42
- path: { type: 'string', description: 'New Project directory. Omit to show the active Project.' },
42
+ action: { type: 'string', enum: ['get', 'set', 'list'], description: 'get shows the active Project (default without path), set switches to path, list returns registered projects.' },
43
+ path: { type: 'string', description: 'Existing directory to switch to (implies action=set).' },
43
44
  },
44
45
  additionalProperties: false,
45
46
  },
@@ -73,3 +74,71 @@ export const LEAD_DISALLOWED_TOOLS = Object.freeze([
73
74
  'set_goal_tasks',
74
75
  'update_goal',
75
76
  ]);
77
+
78
+ // The runtime surfaces named tools from each optional tool-def module, never
79
+ // "whatever the module exports": a module that grows a tool must be admitted
80
+ // here before it can reach a session.
81
+ const WEB_SEARCH_RUNTIME_TOOLS = ['web_search', 'web_fetch', 'local_fetch', 'image_fetch'];
82
+ const MEMORY_RUNTIME_TOOLS = ['recall', 'memory'];
83
+ const CODE_GRAPH_RUNTIME_TOOLS = ['code_graph'];
84
+ const BROWSER_RUNTIME_TOOLS = ['browser', 'browser_devtools'];
85
+ const COMPUTER_RUNTIME_TOOLS = ['computer'];
86
+ const OFFICE_RUNTIME_TOOLS = ['office'];
87
+ const MEDIA_RUNTIME_TOOLS = ['media'];
88
+
89
+ const admitted = (tools, names) => (tools || []).filter((tool) => names.includes(tool?.name));
90
+
91
+ /**
92
+ * Assemble this runtime's tool definitions from the loaded tool-def modules.
93
+ * Pure: callers resolve their own availability flags (skills env gate, channel
94
+ * ownership) and pass the already-built goal/agent tool arrays.
95
+ *
96
+ * - `standaloneTools` is the model-facing set (also the deferred catalog base).
97
+ * - `internalToolDefs` adds the `public: false` web-search tools: reachable
98
+ * through the internal executor for other tools, never advertised to a model.
99
+ */
100
+ export function collectStandaloneToolDefs({
101
+ webSearchToolDefs,
102
+ memoryToolDefs,
103
+ channelToolDefs,
104
+ codeGraphToolDefs,
105
+ browserToolDefs = [],
106
+ computerToolDefs = [],
107
+ officeToolDefs = [],
108
+ mediaToolDefs = [],
109
+ setupToolDefs = [],
110
+ goalTools = [],
111
+ agentTools = [],
112
+ isChannelTool = () => false,
113
+ skillToolEnabled = true,
114
+ }) {
115
+ const webSearchRuntimeTools = admitted(webSearchToolDefs?.TOOL_DEFS, WEB_SEARCH_RUNTIME_TOOLS);
116
+ const standaloneTools = [
117
+ TOOL_SEARCH_TOOL,
118
+ ...(skillToolEnabled ? [SKILL_TOOL] : []),
119
+ CWD_TOOL,
120
+ ...webSearchRuntimeTools.filter((tool) => tool?.public !== false),
121
+ ...admitted(memoryToolDefs?.TOOL_DEFS, MEMORY_RUNTIME_TOOLS),
122
+ ...(channelToolDefs?.TOOL_DEFS || []).filter((tool) => isChannelTool(tool?.name)),
123
+ ...admitted(codeGraphToolDefs?.CODE_GRAPH_TOOL_DEFS, CODE_GRAPH_RUNTIME_TOOLS),
124
+ ...admitted(browserToolDefs, BROWSER_RUNTIME_TOOLS),
125
+ ...admitted(computerToolDefs, COMPUTER_RUNTIME_TOOLS),
126
+ ...admitted(officeToolDefs, OFFICE_RUNTIME_TOOLS),
127
+ ...admitted(mediaToolDefs, MEDIA_RUNTIME_TOOLS),
128
+ ...setupToolDefs,
129
+ ...goalTools,
130
+ ...agentTools,
131
+ ];
132
+ return {
133
+ standaloneTools,
134
+ internalToolDefs: [
135
+ ...standaloneTools,
136
+ ...webSearchRuntimeTools.filter((tool) => tool?.public === false),
137
+ ],
138
+ // Workflow-aware model surface: a pack that declares an EMPTY agents list
139
+ // (Solo) must not advertise the agent tool at all — the model calling a
140
+ // schema-visible tool that policy always rejects is a guaranteed error turn
141
+ // (user-reported in Solo). Names derive from the live agent tool defs.
142
+ agentToolNames: new Set(agentTools.map((tool) => String(tool?.name || '')).filter(Boolean)),
143
+ };
144
+ }
@@ -2,6 +2,7 @@
2
2
  // dependencies after the one-time import of surviving historical originals.
3
3
  import { getUsageLedger } from '../runtime/shared/llm/usage-ledger.mjs';
4
4
  import { importUsageHistory } from '../runtime/shared/llm/usage-ledger-import.mjs';
5
+ import { refreshUnpricedUsage } from '../runtime/shared/llm/usage-pricing-refresh.mjs';
5
6
  import { resolvePluginData } from '../runtime/shared/plugin-paths.mjs';
6
7
  import { usageStatsSnapshot } from '../standalone/usage-stats-model.mjs';
7
8
  import { resolveUsageStatsPeriod } from '../standalone/usage-stats-period.mjs';
@@ -39,16 +40,18 @@ export function createUsageStatsApi({ ledger = getUsageLedger, importHistory = i
39
40
  .finally(() => { importing = null; });
40
41
  await importing;
41
42
  }
43
+ refreshUnpricedUsage(store);
42
44
  // Imports may take time: their newly retained timestamps must not fall
43
45
  // beyond a clock captured before the import started.
44
46
  const now = Date.now();
45
47
  // Keep the existing days API for non-desktop callers.
46
48
  const period = options?.view == null ? null : resolveUsageStatsPeriod({
47
- view: options.view, anchor: options.anchor, now,
49
+ view: options.view, anchor: options.anchor, startDay: options.startDay, endDay: options.endDay, now,
48
50
  });
49
51
  const snapshot = usageStatsSnapshot({
50
52
  rollup: store.rollup({
51
53
  hourlyDay: period?.view === 'hour' ? period.startDay : null,
54
+ ...(period?.view === 'hour' ? { fromMs: period.fromMs, toMs: period.toMs } : {}),
52
55
  ...(period ? {
53
56
  fromDay: period.startDay || undefined,
54
57
  toDay: usageRollupDayKey(period.toMs),
@@ -146,8 +146,14 @@ export function createWarmupSchedulers({
146
146
  return;
147
147
  }
148
148
  void warmCatalogsInBackground()
149
- .then(() => bootProfile('model-catalog:warm-ready'))
150
- .catch((error) => bootProfile('model-catalog:warm-failed', { error: error?.message || String(error) }));
149
+ .then((result) => {
150
+ bootProfile('model-catalog:warm-ready');
151
+ scheduleModelCatalogWarmup(result?.retryAfterMs ?? 6 * 60 * 60 * 1000);
152
+ })
153
+ .catch((error) => {
154
+ bootProfile('model-catalog:warm-failed', { error: error?.message || String(error) });
155
+ scheduleModelCatalogWarmup(60_000);
156
+ });
151
157
  }, delayMs);
152
158
  timers.modelCatalogWarmupTimer.unref?.();
153
159
  }
@@ -431,6 +431,20 @@ export function normalizeWebSearchRouteConfig(routeLike, fallback = {}) {
431
431
  };
432
432
  }
433
433
 
434
+ // The runtime's web-search route is never "unconfigured": an unset or invalid
435
+ // candidate falls through to the next one, and an empty list resolves to the
436
+ // default "follow the Main Model" route.
437
+ export function webSearchRouteOrDefault(...routeLikes) {
438
+ for (const routeLike of routeLikes) {
439
+ const normalized = normalizeWebSearchRouteConfig(routeLike);
440
+ if (normalized) return normalized;
441
+ }
442
+ return normalizeWebSearchRouteConfig({
443
+ provider: WEB_SEARCH_DEFAULT_PROVIDER,
444
+ model: WEB_SEARCH_DEFAULT_MODEL,
445
+ });
446
+ }
447
+
434
448
  export function normalizeWorkflowRoute(routeLike, fallback = {}) {
435
449
  const provider = clean(routeLike?.provider) || clean(fallback.provider);
436
450
  const model = clean(routeLike?.model) || clean(fallback.model);
@@ -1,6 +1,8 @@
1
1
  import { channelNotificationModelContent } from '../runtime/shared/channel-notification-routing.mjs';
2
2
 
3
- const CHANNEL_NOTIFICATION_METHOD = 'notifications/claude/channel';
3
+ /** The one inbound channel notification method. Exported so every consumer
4
+ * (daemon router, session runtime) matches the same wire name. */
5
+ export const CHANNEL_NOTIFICATION_METHOD = 'notifications/claude/channel';
4
6
 
5
7
  export function createChannelSessionRouter({
6
8
  getSessionService,
@@ -10,6 +10,7 @@ import { detachedSpawnOpts } from '../runtime/shared/spawn-flags.mjs';
10
10
  import { scrubLoaderVars } from '../runtime/agent/orchestrator/tools/env-scrub.mjs';
11
11
  import { withHeapCap } from '../runtime/shared/heap-cap.mjs';
12
12
  import { rotateBoundedLog, PLUGIN_LOG_MAX_BYTES, PLUGIN_LOG_KEEP_BYTES } from '../lib/mixdog-debug.cjs';
13
+ import { beginDaemonSpawnCapture } from './daemon-crash-capture.mjs';
13
14
  import { attachChannel, readChannelDiscovery, probeChannelHealth } from './channel-client.mjs';
14
15
 
15
16
  const CHANNEL_TOOLS = new Set([
@@ -195,34 +196,40 @@ export function createStandaloneChannelWorker({
195
196
  function spawnDaemonCandidate() {
196
197
  return new Promise((resolveSpawn) => {
197
198
  let settled = false;
199
+ // fd 2 is a capture FILE, not a pipe: a V8 fatal abort is written below
200
+ // every JS hook and a pipe stops being drained once this worker detaches.
201
+ const capture = beginDaemonSpawnCapture({
202
+ launcher: 'channel-worker',
203
+ dataDir,
204
+ log: (line) => logLine(logPath, line),
205
+ });
198
206
  const done = () => {
199
207
  if (settled) return;
200
208
  settled = true;
209
+ capture.mirror();
201
210
  resolveSpawn();
202
211
  };
212
+ // Same singleton daemon as the session spawn path, so the same heap policy.
213
+ const execArgv = withHeapCap('daemon', ['--require', WORKER_PRELOAD]);
203
214
  let daemon;
204
215
  try {
205
216
  daemon = fork(daemonEntry(), [], {
206
217
  cwd,
207
- // Same singleton daemon as the session spawn path, so the same cap.
208
- execArgv: withHeapCap('daemon', ['--require', WORKER_PRELOAD]),
209
- stdio: ['ignore', 'ignore', 'pipe', 'ipc'],
218
+ execArgv,
219
+ stdio: ['ignore', 'ignore', capture.stderrStdio, 'ipc'],
210
220
  env: daemonEnv(),
211
221
  ...detachedSpawnOpts,
212
222
  });
213
223
  } catch (error) {
224
+ capture.noteSpawnError(error);
214
225
  logLine(logPath, `daemon spawn failed: ${error?.message || error}`);
215
226
  done();
216
227
  return;
217
228
  }
218
- const mirrorStderr = (chunk) => {
219
- const text = String(chunk || '').trimEnd();
220
- if (text) logLine(logPath, text);
221
- };
222
- daemon.stderr?.on('data', mirrorStderr);
229
+ capture.track(daemon, { detached: Boolean(detachedSpawnOpts.detached), execArgv });
223
230
  daemon.once('message', (message) => {
224
231
  if (message?.type !== 'ready') return;
225
- try { daemon.stderr?.off?.('data', mirrorStderr); } catch {}
232
+ capture.noteReady();
226
233
  try { daemon.disconnect?.(); } catch {}
227
234
  try { daemon.unref?.(); } catch {}
228
235
  try { daemon.stderr?.unref?.(); } catch {}
@@ -230,6 +237,8 @@ export function createStandaloneChannelWorker({
230
237
  });
231
238
  daemon.once('exit', done);
232
239
  daemon.once('error', (error) => {
240
+ // An async spawn failure may never emit 'exit'; the sidecar still gets it.
241
+ capture.noteSpawnError(error);
233
242
  logLine(logPath, `daemon spawn error: ${error?.message || error}`);
234
243
  done();
235
244
  });