mixdog 1.3.4 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (472) hide show
  1. package/LICENSES/oh-my-pi-MIT.txt +23 -0
  2. package/NOTICE.md +17 -2
  3. package/README.md +11 -0
  4. package/package.json +3 -11
  5. package/scripts/daemon-stub.mjs +1 -1
  6. package/scripts/embed-google-oauth-client.mjs +49 -0
  7. package/scripts/gate-local.mjs +4 -2
  8. package/scripts/lib/test-spawn-ledger.mjs +46 -1
  9. package/scripts/native-release-status.mjs +2 -2
  10. package/scripts/recall-history-cases.json +1 -1
  11. package/scripts/suite-health.mjs +10 -1
  12. package/scripts/test.mjs +12 -11
  13. package/src/agents/reviewer/AGENT.md +7 -11
  14. package/src/agents/reviewer/agent.json +1 -1
  15. package/src/defaults/shipped-history.json +25 -1
  16. package/src/defaults/skills/browser-use/SKILL.md +77 -17
  17. package/src/defaults/skills/code-tidy/SKILL.md +142 -270
  18. package/src/defaults/skills/code-tidy/references/agent-cleanup.md +4 -4
  19. package/src/defaults/skills/code-tidy/references/cleanup-report.md +31 -76
  20. package/src/defaults/skills/code-tidy/references/dead-code.md +6 -12
  21. package/src/defaults/skills/computer-use/SKILL.md +33 -9
  22. package/src/defaults/skills/setup/SKILL.md +29 -2
  23. package/src/defaults/skills/setup/references/actions.md +117 -28
  24. package/src/defaults/skills/setup/references/surfaces.md +77 -35
  25. package/src/defaults/skills/setup-guide/SKILL.md +3 -3
  26. package/src/defaults/skills/visualize/SKILL.md +2 -1
  27. package/src/lib/keychain-cjs.cjs +359 -29
  28. package/src/lib/rules-builder.cjs +10 -8
  29. package/src/rules/agent/AGENT.md +6 -6
  30. package/src/rules/agent-mode/AGENT_MODE.md +10 -2
  31. package/src/rules/agent-mode/MIXY.md +12 -0
  32. package/src/rules/lead/LEAD.md +18 -20
  33. package/src/rules/shared/05-tool-calls.md +5 -6
  34. package/src/rules/shared/10-tool-workflow.md +2 -0
  35. package/src/rules/shared/60-verification.md +7 -5
  36. package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -3
  37. package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +193 -0
  38. package/src/runtime/agent/orchestrator/agent-runtime/title-completion.mjs +3 -1
  39. package/src/runtime/agent/orchestrator/agent-trace-format.mjs +3 -1
  40. package/src/runtime/agent/orchestrator/config.mjs +34 -0
  41. package/src/runtime/agent/orchestrator/context/collect.mjs +3 -0
  42. package/src/runtime/agent/orchestrator/context/deferred-tools.mjs +72 -67
  43. package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +54 -1
  44. package/src/runtime/agent/orchestrator/mcp/agent-connectors.mjs +3 -3
  45. package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +177 -73
  46. package/src/runtime/agent/orchestrator/mcp/client.mjs +25 -2
  47. package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +31 -2
  48. package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +16 -3
  49. package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +42 -7
  50. package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +21 -2
  51. package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +23 -0
  52. package/src/runtime/agent/orchestrator/mcp/oauth.mjs +11 -1
  53. package/src/runtime/agent/orchestrator/providers/account-pool.mjs +230 -137
  54. package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +64 -7
  55. package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +18 -5
  56. package/src/runtime/agent/orchestrator/providers/anthropic-cache-warm.mjs +165 -0
  57. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
  58. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +4 -1
  59. package/src/runtime/agent/orchestrator/providers/anthropic-oauth-request/gzip-post.mjs +14 -14
  60. package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +160 -69
  61. package/src/runtime/agent/orchestrator/providers/anthropic-overload-fallback.mjs +25 -3
  62. package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +64 -33
  63. package/src/runtime/agent/orchestrator/providers/anthropic.mjs +135 -87
  64. package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +52 -8
  65. package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +10 -1
  66. package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +22 -6
  67. package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +15 -4
  68. package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +17 -2
  69. package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +142 -104
  70. package/src/runtime/agent/orchestrator/providers/cache-warm-admission.mjs +90 -0
  71. package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
  72. package/src/runtime/agent/orchestrator/providers/cursor-wire-normalization.mjs +10 -4
  73. package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +10 -217
  74. package/src/runtime/agent/orchestrator/providers/cursor-wire-transport.mjs +25 -9
  75. package/src/runtime/agent/orchestrator/providers/cursor.mjs +22 -6
  76. package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +409 -0
  77. package/src/runtime/agent/orchestrator/providers/devin-wire-families.mjs +187 -0
  78. package/src/runtime/agent/orchestrator/providers/devin-wire-identity.mjs +342 -0
  79. package/src/runtime/agent/orchestrator/providers/devin-wire-models.mjs +541 -0
  80. package/src/runtime/agent/orchestrator/providers/devin-wire-protobuf.mjs +305 -0
  81. package/src/runtime/agent/orchestrator/providers/devin-wire-request.mjs +558 -0
  82. package/src/runtime/agent/orchestrator/providers/devin-wire-schema.mjs +880 -0
  83. package/src/runtime/agent/orchestrator/providers/devin-wire-session.mjs +190 -0
  84. package/src/runtime/agent/orchestrator/providers/devin-wire-tool-args.mjs +351 -0
  85. package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +560 -0
  86. package/src/runtime/agent/orchestrator/providers/devin.mjs +491 -0
  87. package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +3 -0
  88. package/src/runtime/agent/orchestrator/providers/gemini-output-limit.mjs +46 -0
  89. package/src/runtime/agent/orchestrator/providers/gemini-reasoning-relay.mjs +30 -0
  90. package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +7 -11
  91. package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +61 -22
  92. package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -0
  93. package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +71 -4
  94. package/src/runtime/agent/orchestrator/providers/gemini.mjs +25 -2
  95. package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
  96. package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +96 -5
  97. package/src/runtime/agent/orchestrator/providers/lib/oauth-token-utils.mjs +17 -3
  98. package/src/runtime/agent/orchestrator/providers/lib/tail-reminder-split.mjs +23 -5
  99. package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +52 -10
  100. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.d.mts +8 -1
  101. package/src/runtime/agent/orchestrator/providers/model-proxy-channel.mjs +1 -0
  102. package/src/runtime/agent/orchestrator/providers/npm-cli-version.mjs +11 -3
  103. package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +19 -1
  104. package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +39 -3
  105. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
  106. package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +2 -0
  107. package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +6 -1
  108. package/src/runtime/agent/orchestrator/providers/openai-oauth-tokens.mjs +10 -9
  109. package/src/runtime/agent/orchestrator/providers/openai-ws-send/send-context.mjs +22 -3
  110. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/attempt-context.mjs +43 -5
  111. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/handshake-failure.mjs +3 -1
  112. package/src/runtime/agent/orchestrator/providers/openai-ws-send-attempts/stream-failure.mjs +6 -3
  113. package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +1 -0
  114. package/src/runtime/agent/orchestrator/providers/provider-availability.mjs +19 -0
  115. package/src/runtime/agent/orchestrator/providers/provider-error-kind.mjs +65 -1
  116. package/src/runtime/agent/orchestrator/providers/quota-reading.mjs +38 -12
  117. package/src/runtime/agent/orchestrator/providers/registry.mjs +43 -3
  118. package/src/runtime/agent/orchestrator/providers/retry-executor.mjs +39 -7
  119. package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +6 -0
  120. package/src/runtime/agent/orchestrator/providers/wire-protobuf-codec.mjs +368 -0
  121. package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +12 -7
  122. package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +2 -0
  123. package/src/runtime/agent/orchestrator/runtime-core/compaction-config-keys.mjs +62 -0
  124. package/src/runtime/agent/orchestrator/runtime-core/config-helpers.mjs +37 -16
  125. package/src/runtime/agent/orchestrator/runtime-core/deferred-tool-delta.mjs +100 -23
  126. package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +1 -1
  127. package/src/runtime/agent/orchestrator/runtime-core/reaction-tool-defs.mjs +133 -0
  128. package/src/runtime/agent/orchestrator/runtime-core/session-text.mjs +2 -0
  129. package/src/runtime/agent/orchestrator/runtime-core/tool-bridge.mjs +19 -4
  130. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
  131. package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +125 -30
  132. package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +23 -5
  133. package/src/runtime/agent/orchestrator/runtime-core/tool-profile.mjs +35 -10
  134. package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +57 -10
  135. package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +9 -6
  136. package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -1
  137. package/src/runtime/agent/orchestrator/session/agent-loop.mjs +18 -0
  138. package/src/runtime/agent/orchestrator/session/agent-room.d.mts +0 -3
  139. package/src/runtime/agent/orchestrator/session/agent-room.mjs +10 -4
  140. package/src/runtime/agent/orchestrator/session/cache-warm.mjs +792 -0
  141. package/src/runtime/agent/orchestrator/session/compact/runner.mjs +148 -25
  142. package/src/runtime/agent/orchestrator/session/compaction-archive-capture.mjs +475 -58
  143. package/src/runtime/agent/orchestrator/session/compaction-archive.mjs +42 -17
  144. package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +8 -0
  145. package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +47 -9
  146. package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +6 -2
  147. package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +36 -4
  148. package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +14 -2
  149. package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +8 -0
  150. package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +18 -22
  151. package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +32 -3
  152. package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +11 -2
  153. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -1
  154. package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +51 -3
  155. package/src/runtime/agent/orchestrator/session/loop/route-fallback.mjs +17 -3
  156. package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +10 -2
  157. package/src/runtime/agent/orchestrator/session/loop/tool-exec/after-hook.mjs +2 -1
  158. package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +14 -4
  159. package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +16 -2
  160. package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +16 -1
  161. package/src/runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs +10 -0
  162. package/src/runtime/agent/orchestrator/session/loop/tool-helpers.mjs +3 -10
  163. package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +23 -5
  164. package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +60 -0
  165. package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +12 -2
  166. package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +19 -1
  167. package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +2 -0
  168. package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +133 -90
  169. package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +14 -0
  170. package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +2 -1
  171. package/src/runtime/agent/orchestrator/session/manager/ask-turn-state.mjs +31 -4
  172. package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +30 -18
  173. package/src/runtime/agent/orchestrator/session/manager/owner-route-fallbacks.mjs +23 -13
  174. package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +11 -2
  175. package/src/runtime/agent/orchestrator/session/manager/provider-replay.mjs +13 -0
  176. package/src/runtime/agent/orchestrator/session/manager/route-fallback-chain.mjs +129 -0
  177. package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +20 -2
  178. package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +2 -0
  179. package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +8 -0
  180. package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +1 -1
  181. package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +13 -0
  182. package/src/runtime/agent/orchestrator/session/manager/tool-resolution.mjs +7 -2
  183. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-journal.mjs +102 -15
  184. package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +18 -5
  185. package/src/runtime/agent/orchestrator/session/message-ids.mjs +5 -3
  186. package/src/runtime/agent/orchestrator/session/message-reactions.mjs +89 -0
  187. package/src/runtime/agent/orchestrator/session/message-reactions.test-support.mjs +75 -0
  188. package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +19 -8
  189. package/src/runtime/agent/orchestrator/session/prompt-cache-idle-gaps.mjs +113 -0
  190. package/src/runtime/agent/orchestrator/session/prompt-cache-touch-store.mjs +127 -0
  191. package/src/runtime/agent/orchestrator/session/routine-result.d.mts +0 -2
  192. package/src/runtime/agent/orchestrator/session/routine-result.mjs +47 -11
  193. package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +20 -2
  194. package/src/runtime/agent/orchestrator/session/sensitive-projection.mjs +100 -0
  195. package/src/runtime/agent/orchestrator/session/sensitive-values.mjs +257 -0
  196. package/src/runtime/agent/orchestrator/session/side-question-store.mjs +20 -7
  197. package/src/runtime/agent/orchestrator/session/side-question.mjs +18 -0
  198. package/src/runtime/agent/orchestrator/session/skill-update-notice.mjs +60 -0
  199. package/src/runtime/agent/orchestrator/session/store/live-state.mjs +6 -3
  200. package/src/runtime/agent/orchestrator/session/store/save-delta.mjs +9 -5
  201. package/src/runtime/agent/orchestrator/session/store/serialize.mjs +9 -8
  202. package/src/runtime/agent/orchestrator/session/store/session-persistence-events.mjs +29 -0
  203. package/src/runtime/agent/orchestrator/session/store-agent-worker-header-cache.mjs +85 -0
  204. package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +133 -18
  205. package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +12 -2
  206. package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +44 -14
  207. package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +84 -3
  208. package/src/runtime/agent/orchestrator/session/stored-attachment-history.mjs +32 -0
  209. package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +11 -5
  210. package/src/runtime/agent/orchestrator/session/thinking-binding.mjs +108 -0
  211. package/src/runtime/agent/orchestrator/session/tool-batch/pre-dispatch.mjs +2 -2
  212. package/src/runtime/agent/orchestrator/session/tool-batch/record-outcome.mjs +2 -1
  213. package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +4 -0
  214. package/src/runtime/agent/orchestrator/session/tool-batch.mjs +5 -0
  215. package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +25 -2
  216. package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-status.mjs +9 -7
  217. package/src/runtime/agent/orchestrator/session/transcript-restore/tool-result-text.mjs +2 -2
  218. package/src/runtime/agent/orchestrator/session/turn-failure.mjs +5 -1
  219. package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +5 -2
  220. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +12 -1
  221. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/misuse-guard.mjs +240 -0
  222. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/result-format.mjs +1 -1
  223. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/shell-cwd.mjs +38 -0
  224. package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +25 -5
  225. package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +65 -7
  226. package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +7 -1
  227. package/src/runtime/agent/orchestrator/tools/shell-command.mjs +36 -13
  228. package/src/runtime/browser-bridge/action-schema.mjs +13 -2
  229. package/src/runtime/browser-bridge/client.mjs +73 -8
  230. package/src/runtime/browser-bridge/input-fields.mjs +8 -9
  231. package/src/runtime/browser-bridge/mail-links.mjs +107 -0
  232. package/src/runtime/browser-bridge/tool-defs.mjs +1 -1
  233. package/src/runtime/channels/lib/config.mjs +6 -61
  234. package/src/runtime/channels/lib/crash-log.mjs +1 -1
  235. package/src/runtime/channels/lib/event-pipeline.mjs +4 -19
  236. package/src/runtime/channels/lib/event-queue.mjs +3 -18
  237. package/src/runtime/channels/lib/owned-runtime/automation-services.mjs +2 -2
  238. package/src/runtime/channels/lib/owned-runtime/automation-start.mjs +3 -4
  239. package/src/runtime/channels/lib/owned-runtime/config-reload.mjs +4 -59
  240. package/src/runtime/channels/lib/owned-runtime/owned-start.mjs +33 -115
  241. package/src/runtime/channels/lib/owned-runtime/owned-stop.mjs +5 -22
  242. package/src/runtime/channels/lib/owned-runtime/state.mjs +2 -8
  243. package/src/runtime/channels/lib/owned-runtime.mjs +6 -23
  244. package/src/runtime/channels/lib/parent-bridge.mjs +2 -2
  245. package/src/runtime/channels/lib/runtime-paths.mjs +4 -43
  246. package/src/runtime/channels/lib/schedule-errors.mjs +51 -0
  247. package/src/runtime/channels/lib/scheduler.mjs +135 -154
  248. package/src/runtime/channels/lib/schedules-db.mjs +83 -11
  249. package/src/runtime/channels/lib/status-snapshot.mjs +1 -1
  250. package/src/runtime/channels/lib/tool-dispatch.mjs +14 -2
  251. package/src/runtime/channels/lib/webhooks-db.mjs +5 -9
  252. package/src/runtime/channels/lib/worker-bootstrap.mjs +0 -1
  253. package/src/runtime/channels/lib/worker-ipc.mjs +0 -1
  254. package/src/runtime/channels/lib/worker-main.mjs +19 -34
  255. package/src/runtime/computer-bridge/action-schema.mjs +42 -1
  256. package/src/runtime/computer-bridge/actions.mjs +9 -1
  257. package/src/runtime/computer-bridge/client.mjs +180 -8
  258. package/src/runtime/computer-bridge/core-actions.mjs +2 -2
  259. package/src/runtime/computer-bridge/error-recovery.mjs +27 -2
  260. package/src/runtime/computer-bridge/linux-readiness.mjs +65 -23
  261. package/src/runtime/computer-bridge/pending-continuation.mjs +1 -1
  262. package/src/runtime/connectors/connector-accounts-mcp.mjs +230 -0
  263. package/src/runtime/connectors/gmail-app-password.mjs +172 -39
  264. package/src/runtime/connectors/google-mcp.mjs +10 -12
  265. package/src/runtime/memory/lib/pg/adapter.mjs +77 -70
  266. package/src/runtime/memory/lib/pg/supervisor.mjs +24 -12
  267. package/src/runtime/memory/lib/runtime-fetcher.mjs +23 -5
  268. package/src/runtime/office/com/com-adapter.mjs +17 -1
  269. package/src/runtime/office/com/office-com-host.ps1 +51 -1
  270. package/src/runtime/office/pdf/cfb-fixture.mjs +328 -0
  271. package/src/runtime/office/pdf/cfb-protection.mjs +311 -0
  272. package/src/runtime/office/pdf/document-preview.mjs +326 -8
  273. package/src/runtime/office/pdf/ooxml-crypto.mjs +469 -0
  274. package/src/runtime/office/pdf/ooxml-key-worker.mjs +14 -0
  275. package/src/runtime/office/portable/portable-soffice.mjs +45 -5
  276. package/src/runtime/session-search/session-search-db.mjs +73 -9
  277. package/src/runtime/session-search/session-search-ingest.mjs +110 -20
  278. package/src/runtime/shared/abort-race.mjs +89 -0
  279. package/src/runtime/shared/agent-avatar.d.mts +0 -1
  280. package/src/runtime/shared/agent-kind.mjs +4 -3
  281. package/src/runtime/shared/bot-hops.mjs +62 -2
  282. package/src/runtime/shared/bounded-download.mjs +8 -3
  283. package/src/runtime/shared/config.mjs +51 -35
  284. package/src/runtime/shared/connector-accounts.mjs +20 -10
  285. package/src/runtime/shared/connector-catalog.d.mts +33 -2
  286. package/src/runtime/shared/connector-catalog.mjs +166 -8
  287. package/src/runtime/shared/connector-triggers.mjs +22 -19
  288. package/src/runtime/shared/defaults-separation.mjs +2 -14
  289. package/src/runtime/shared/delegated-approval-host.mjs +103 -11
  290. package/src/runtime/shared/developer-options.mjs +32 -1
  291. package/src/runtime/shared/err-text.mjs +24 -15
  292. package/src/runtime/shared/file-permissions.d.mts +0 -8
  293. package/src/runtime/shared/file-permissions.mjs +0 -11
  294. package/src/runtime/shared/git-direct.test-support.mjs +19 -0
  295. package/src/runtime/shared/google-oauth-client.generated.json +4 -0
  296. package/src/runtime/shared/google-oauth-client.mjs +34 -9
  297. package/src/runtime/shared/heartbeat-interval.d.mts +4 -0
  298. package/src/runtime/shared/heartbeat-interval.mjs +19 -0
  299. package/src/runtime/shared/idle-auto-clear-gate.mjs +104 -0
  300. package/src/runtime/shared/llm/anthropic-betas.mjs +7 -0
  301. package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +12 -0
  302. package/src/runtime/shared/llm/provider-catalog-registry.mjs +1 -0
  303. package/src/runtime/shared/llm/usage-rollup.mjs +1 -1
  304. package/src/runtime/shared/llm/well-formed.mjs +66 -0
  305. package/src/runtime/shared/mixy-presence.mjs +22 -0
  306. package/src/runtime/shared/orchestration.d.mts +2 -0
  307. package/src/runtime/shared/pg-schema-db.mjs +27 -16
  308. package/src/runtime/shared/profile-config.cjs +1 -1
  309. package/src/runtime/shared/prompt-origin.d.mts +4 -0
  310. package/src/runtime/shared/prompt-origin.mjs +21 -0
  311. package/src/runtime/shared/provider-accounts.mjs +231 -59
  312. package/src/runtime/shared/provider-api-key.mjs +19 -8
  313. package/src/runtime/shared/provider-display-name.mjs +29 -0
  314. package/src/runtime/shared/provider-timeout-phase.mjs +2 -0
  315. package/src/runtime/shared/routine-trigger.d.mts +2 -0
  316. package/src/runtime/shared/routine-trigger.mjs +52 -0
  317. package/src/runtime/shared/sensitive-path-rules.d.mts +2 -10
  318. package/src/runtime/shared/sensitive-path-rules.mjs +19 -41
  319. package/src/runtime/shared/session-activity-signal.mjs +34 -1
  320. package/src/runtime/shared/session-sidebar-host.d.mts +1 -1
  321. package/src/runtime/shared/session-sidebar-host.mjs +7 -3
  322. package/src/runtime/shared/session-turn-prelude.mjs +18 -0
  323. package/src/runtime/shared/tool-execution-contract.mjs +2 -0
  324. package/src/runtime/shared/tool-result-summary.mjs +1 -14
  325. package/src/runtime/shared/transcript-metadata.mjs +38 -0
  326. package/src/runtime/shared/user-data-guard.mjs +30 -2
  327. package/src/runtime/shared/worktrees/activity-gate.mjs +12 -5
  328. package/src/runtime/shared/worktrees/test-support.mjs +9 -4
  329. package/src/runtime/terminal-bridge/client.mjs +10 -1
  330. package/src/runtime/visualize-bridge/client.mjs +27 -8
  331. package/src/runtime/visualize-bridge/tool-defs.mjs +22 -8
  332. package/src/runtime/visualize-bridge/tool-meta.d.mts +5 -0
  333. package/src/runtime/visualize-bridge/tool-meta.mjs +22 -0
  334. package/src/runtime/web-search/lib/fetch-pipeline.mjs +2 -2
  335. package/src/session-runtime/agent-home-delivery.mjs +486 -179
  336. package/src/session-runtime/agent-room-delivery.mjs +28 -1
  337. package/src/session-runtime/agent-task-sessions.mjs +561 -199
  338. package/src/session-runtime/boot/apis.mjs +9 -0
  339. package/src/session-runtime/boot/begin.mjs +3 -2
  340. package/src/session-runtime/boot/infrastructure.mjs +4 -0
  341. package/src/session-runtime/boot/providers.mjs +3 -0
  342. package/src/session-runtime/boot/tools.mjs +8 -1
  343. package/src/session-runtime/bot-chain.mjs +32 -0
  344. package/src/session-runtime/bot-status.mjs +7 -4
  345. package/src/session-runtime/channel-config-api.mjs +63 -17
  346. package/src/session-runtime/config-lifecycle.mjs +6 -0
  347. package/src/session-runtime/connector-merge-migration.mjs +305 -0
  348. package/src/session-runtime/internal-tool-executor/ask-user-tool.mjs +132 -28
  349. package/src/session-runtime/internal-tool-executor/bridge-tools.mjs +2 -0
  350. package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +45 -0
  351. package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +72 -5
  352. package/src/session-runtime/internal-tool-executor.mjs +4 -0
  353. package/src/session-runtime/lifecycle/inheritance.mjs +16 -3
  354. package/src/session-runtime/lifecycle/session-catalog.mjs +3 -1
  355. package/src/session-runtime/lifecycle/teardown/runtime-stops.mjs +50 -4
  356. package/src/session-runtime/lifecycle/teardown.mjs +23 -5
  357. package/src/session-runtime/mcp-glue/server-catalog.mjs +61 -3
  358. package/src/session-runtime/mcp-oauth-login.mjs +5 -3
  359. package/src/session-runtime/mixy-heartbeat.mjs +927 -0
  360. package/src/session-runtime/model-route/route-tuning.mjs +10 -6
  361. package/src/session-runtime/notification-bus.mjs +31 -117
  362. package/src/session-runtime/notification-completion-queue.mjs +54 -0
  363. package/src/session-runtime/notification-listeners.mjs +76 -0
  364. package/src/session-runtime/owned-automation-run.mjs +35 -13
  365. package/src/session-runtime/prewarm/channel-start.mjs +3 -7
  366. package/src/session-runtime/provider-auth/login.mjs +7 -0
  367. package/src/session-runtime/provider-models/row-hydration.mjs +13 -2
  368. package/src/session-runtime/resource-mcp-api.mjs +143 -224
  369. package/src/session-runtime/resource-mcp-connector-accounts.mjs +163 -0
  370. package/src/session-runtime/resource-mcp-oauth-api.mjs +217 -0
  371. package/src/session-runtime/resource-mcp-secrets.mjs +82 -0
  372. package/src/session-runtime/resource-mcp-servers.mjs +78 -0
  373. package/src/session-runtime/resource-mcp-store.mjs +49 -0
  374. package/src/session-runtime/routine-home-turn.mjs +33 -6
  375. package/src/session-runtime/routine-owner.mjs +40 -9
  376. package/src/session-runtime/schedule-session-run.mjs +7 -3
  377. package/src/session-runtime/services/agent-tool/close-flow.mjs +3 -0
  378. package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +8 -12
  379. package/src/session-runtime/services/agent-tool/spawn-preset.mjs +7 -2
  380. package/src/session-runtime/services/agent-tool/tag-registry.mjs +1 -0
  381. package/src/session-runtime/services/agent-tool/worker-index/awaiting-user-sync.mjs +51 -0
  382. package/src/session-runtime/services/agent-tool/worker-index/disposal.mjs +55 -0
  383. package/src/session-runtime/services/agent-tool/worker-index/released-store.mjs +123 -0
  384. package/src/session-runtime/services/agent-tool/worker-index/restart-settlement.mjs +112 -0
  385. package/src/session-runtime/services/agent-tool/worker-index/row-reads.mjs +36 -0
  386. package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +2 -0
  387. package/src/session-runtime/services/agent-tool/worker-index/row-store.mjs +17 -4
  388. package/src/session-runtime/services/agent-tool/worker-index/row-writes.mjs +58 -0
  389. package/src/session-runtime/services/agent-tool/worker-index.mjs +41 -241
  390. package/src/session-runtime/services/agent-tool/worker-rows.mjs +3 -0
  391. package/src/session-runtime/services/channel-admin.mjs +73 -31
  392. package/src/session-runtime/services/channel-session-router.mjs +4 -2
  393. package/src/session-runtime/services/channel-worker.mjs +1 -1
  394. package/src/session-runtime/services/provider-admin.mjs +128 -25
  395. package/src/session-runtime/services/schedule-access.mjs +14 -0
  396. package/src/session-runtime/services/seeds.mjs +0 -28
  397. package/src/session-runtime/services/usage-dashboard-model.mjs +1 -0
  398. package/src/session-runtime/session-compaction-sync.mjs +27 -0
  399. package/src/session-runtime/session-create/session-options.mjs +8 -4
  400. package/src/session-runtime/settings-builtin-tools-api.mjs +11 -0
  401. package/src/session-runtime/settings-compaction-api.mjs +2 -40
  402. package/src/session-runtime/settings-system-api.mjs +28 -1
  403. package/src/session-runtime/setup-tool/agent-settings-actions.mjs +65 -0
  404. package/src/session-runtime/setup-tool/executor.mjs +187 -29
  405. package/src/session-runtime/setup-tool/extended-actions.mjs +33 -2
  406. package/src/session-runtime/setup-tool/session-route-actions.mjs +152 -0
  407. package/src/session-runtime/setup-tool/settings-contract.mjs +68 -6
  408. package/src/session-runtime/setup-tool/tool-defs.mjs +92 -6
  409. package/src/session-runtime/task-session-route.mjs +99 -0
  410. package/src/session-runtime/tool-policy/agent-profile-fold.mjs +17 -13
  411. package/src/session-runtime/tool-policy/policy-stage.mjs +21 -4
  412. package/src/session-runtime/tool-policy/surface-helpers.mjs +2 -3
  413. package/src/session-runtime/tool-surface.mjs +4 -0
  414. package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
  415. package/src/session-runtime/workflow-agents-api/agent-editor.mjs +98 -21
  416. package/src/session-runtime/workflow-agents-api/style-and-mode.mjs +4 -0
  417. package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +6 -1
  418. package/src/session-runtime/workspace/transitions.mjs +10 -2
  419. package/src/standalone/channel-transport/client-registry/client-records.mjs +65 -0
  420. package/src/standalone/channel-transport/client-registry/client-registration.mjs +118 -0
  421. package/src/standalone/channel-transport/client-registry.mjs +24 -163
  422. package/src/standalone/channel-transport.mjs +1 -1
  423. package/src/standalone/daemon-channels-loader.mjs +10 -8
  424. package/src/standalone/daemon-session-control/list-page.mjs +72 -0
  425. package/src/standalone/daemon-session-control/request.mjs +51 -0
  426. package/src/standalone/daemon-session-control/room-host.mjs +57 -0
  427. package/src/standalone/daemon-session-control/route-control.mjs +48 -0
  428. package/src/standalone/daemon-session-control/send-turn.mjs +60 -0
  429. package/src/standalone/daemon-session-control/worktree-control.mjs +40 -0
  430. package/src/standalone/daemon-session-control.mjs +161 -157
  431. package/src/standalone/daemon.mjs +33 -2
  432. package/src/standalone/session-client.mjs +7 -3
  433. package/src/standalone/session-protocol.mjs +10 -0
  434. package/src/standalone/session-service/agent-tree/agent-cancel.mjs +6 -2
  435. package/src/standalone/session-service/agent-tree/agent-child.mjs +1 -0
  436. package/src/standalone/session-service/quota-resume.mjs +3 -0
  437. package/src/standalone/session-service/retention/busy.mjs +65 -1
  438. package/src/standalone/session-service/session-calls/session-action.mjs +23 -2
  439. package/src/standalone/session-service/session-calls/session-turns.mjs +6 -0
  440. package/src/standalone/session-service/session-calls/session-views.mjs +8 -0
  441. package/src/standalone/session-service.mjs +13 -0
  442. package/src/standalone/session-tool-output.mjs +21 -10
  443. package/src/tui/app/model-options.mjs +4 -27
  444. package/src/tui/dist/index.mjs +81 -65
  445. package/src/tui/session/agent-job-feed/model-notification.mjs +3 -0
  446. package/src/tui/session/initial-state.mjs +3 -0
  447. package/src/tui/session/notice-surface.mjs +23 -1
  448. package/src/tui/session/queue-helpers.mjs +3 -42
  449. package/src/tui/session/session-api/integrations.mjs +1 -0
  450. package/src/tui/session/session-api/lifecycle.mjs +8 -0
  451. package/src/tui/session/session-api/routes-agent-definitions.mjs +14 -2
  452. package/src/tui/session/session-api/routes-write.mjs +5 -1
  453. package/src/tui/session/session-api/routes.mjs +1 -0
  454. package/src/tui/session/session-api/settings.mjs +30 -2
  455. package/src/tui/session/session-flow/auto-clear.mjs +4 -33
  456. package/src/tui/session/session-flow/drain-closed-queue.mjs +38 -0
  457. package/src/tui/session/session-flow/drain-enqueue.mjs +86 -0
  458. package/src/tui/session/session-flow/drain-retry.mjs +35 -0
  459. package/src/tui/session/session-flow/drain.mjs +118 -149
  460. package/src/tui/session/session-flow/queue/entry-shape.mjs +5 -0
  461. package/src/tui/session/session-flow/queue/take-entries.mjs +5 -2
  462. package/src/tui/session/tool-approval-delegation.mjs +64 -0
  463. package/src/tui/session/tool-approval-request.mjs +39 -0
  464. package/src/tui/session/tool-approval-settle.mjs +62 -0
  465. package/src/tui/session/tool-approval.mjs +69 -115
  466. package/src/tui/session/tui-steering-persist.mjs +8 -1
  467. package/src/tui/session/turn-stream.mjs +36 -3
  468. package/src/tui/session/turn.mjs +23 -2
  469. package/src/vendor/statusline/bin/statusline-route.mjs +1 -219
  470. package/src/vendor/statusline/src/gateway/route-meta.mjs +35 -13
  471. package/scripts/code-graph-description-contract.mjs +0 -188
  472. package/src/runtime/channels/lib/owned-runtime/ownership-refresh.mjs +0 -36
@@ -0,0 +1,38 @@
1
+ // The shell tool's optional `cwd` argument: where one command runs. Omitted,
2
+ // the command runs in the session cwd; a relative value resolves against it.
3
+ import { stat } from 'node:fs/promises';
4
+ import { homedir } from 'node:os';
5
+ import { resolve } from 'node:path';
6
+
7
+ // `~`, `~/x` (and `~\x` on Windows) name the user's home folder.
8
+ function expandHome(path) {
9
+ if (path === '~') return homedir();
10
+ if (path.startsWith('~/') || (process.platform === 'win32' && path.startsWith('~\\'))) {
11
+ return resolve(homedir(), path.slice(2));
12
+ }
13
+ return path;
14
+ }
15
+
16
+ /** The directory a shell call runs in: its `cwd` argument resolved against the session cwd. */
17
+ export function effectiveShellCwd(args, sessionCwd) {
18
+ const requested = args?.cwd;
19
+ // Trim only decides blank; a name with edge spaces is used as given.
20
+ if (typeof requested !== 'string' || requested.trim() === '') return sessionCwd;
21
+ return resolve(sessionCwd || process.cwd(), expandHome(requested));
22
+ }
23
+
24
+ /** The cwd hooks and approvals see for a tool call: the effective one for shell, the session cwd otherwise. */
25
+ export function effectiveToolCwd(toolName, args, sessionCwd) {
26
+ return toolName === 'shell' ? effectiveShellCwd(args, sessionCwd) : sessionCwd;
27
+ }
28
+
29
+ /** An error naming the path when `dir` is not an existing directory, else null. */
30
+ export async function shellCwdError(dir) {
31
+ let info;
32
+ try {
33
+ info = await stat(dir);
34
+ } catch {
35
+ return `shell cwd "${dir}" does not exist`;
36
+ }
37
+ return info.isDirectory() ? null : `shell cwd "${dir}" is not a directory`;
38
+ }
@@ -25,6 +25,8 @@ import { planShellDeadlines } from './bash-tool/deadline-plan.mjs';
25
25
  import { planShellInvocation } from './bash-tool/invocation-plan.mjs';
26
26
  import { renderBackgroundedResult } from './bash-tool/backgrounded-result.mjs';
27
27
  import { renderCompletedResult } from './bash-tool/completed-result.mjs';
28
+ import { effectiveShellCwd, shellCwdError } from './bash-tool/shell-cwd.mjs';
29
+ import { guardShellCall, requestedShellType } from './bash-tool/misuse-guard.mjs';
28
30
 
29
31
  export {
30
32
  SURVIVING_DESCENDANTS_WARNING,
@@ -64,9 +66,26 @@ function settleMutationCaches(shellEffects, backgroundJobId, runSettled = null)
64
66
  }
65
67
 
66
68
  export async function executeBashTool(args, workDir, options = {}) {
67
- // Every call starts from the current Project root. A command-local `cd`
68
- // never creates a second session cwd authority beside the dedicated cwd tool.
69
- const bashWorkDir = workDir;
69
+ // The tool-exec layer already guarded the call before its hooks ran and left
70
+ // its notes; a direct caller is guarded here.
71
+ const guarded = Array.isArray(options?.shellGuardNotes)
72
+ ? { args, notes: options.shellGuardNotes }
73
+ : guardShellCall(args, {
74
+ shellType: requestedShellType(args),
75
+ agent: options?.agent,
76
+ sessionId: options?.sessionId,
77
+ telemetry: options?.resultTelemetry,
78
+ });
79
+ if (guarded.failure) return guarded.failure;
80
+ args = guarded.args;
81
+ const guardNotes = guarded.notes;
82
+ // A call starts from the current Project root unless it names a `cwd`. A
83
+ // command-local `cd` never creates a second session cwd authority beside it.
84
+ const bashWorkDir = effectiveShellCwd(args, workDir);
85
+ if (bashWorkDir !== workDir) {
86
+ const cwdError = await shellCwdError(bashWorkDir);
87
+ if (cwdError) return formatShellToolFailure(cwdError);
88
+ }
70
89
  // Approval comes from the runtime's options, never from model-supplied args.
71
90
  const elevationApproved = options?.elevationApproved === true;
72
91
  const prepared = prepareShellCommand(args, { elevationApproved });
@@ -106,6 +125,7 @@ export async function executeBashTool(args, workDir, options = {}) {
106
125
  shellArg: invocation.execShellArg,
107
126
  shellArgs: invocation.execShellArgs,
108
127
  command: invocation.wrappedCommand,
128
+ displayCommand: command,
109
129
  execScript: invocation.execScript,
110
130
  directArgv: invocation.directArgv,
111
131
  elevationApproved,
@@ -147,12 +167,12 @@ export async function executeBashTool(args, workDir, options = {}) {
147
167
  stdout,
148
168
  stderr,
149
169
  };
150
- if (backgrounded) return renderBackgroundedResult(rendering);
170
+ if (backgrounded) return renderBackgroundedResult({ ...rendering, notes: guardNotes.join('\n') });
151
171
  return renderCompletedResult({
152
172
  ...rendering,
153
173
  analysisCommand,
154
174
  timeout: deadlines.timeout,
155
- rewriteNote: [wmicRewrite?.note, bashismRewrite?.note].filter(Boolean).join('\n'),
175
+ rewriteNote: [wmicRewrite?.note, bashismRewrite?.note, ...guardNotes].filter(Boolean).join('\n'),
156
176
  });
157
177
  } finally {
158
178
  inputWake?.dispose();
@@ -27,13 +27,67 @@ export const TASK_WAIT_TIMEOUT_DEFAULT_MS = TASK_WAIT_DEFAULT_MS;
27
27
  export const TASK_WAIT_TIMEOUT_MIN_MS = TASK_WAIT_MIN_MS;
28
28
  export const TASK_WAIT_TIMEOUT_MAX_MS = TASK_WAIT_MAX_MS;
29
29
  const _holdS = budgetSeconds(SHELL_HOLD_DEFAULT_MS);
30
- const _shellSyntaxCheat =
31
- process.platform === 'win32'
32
- ? " PowerShell: ; between independent commands, if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } between dependent ones; no heredoc, </dev/null or | head/tail/wc (Select-Object -First/-Last); multiline python/node via @'…'@ | python - (node -); 2>$null; /c/→C:\\; $PID is reserved."
33
- : ' Bash: chain dependent commands with &&; multiline input via a quoted heredoc delimiter, not extra quoting/escape layers.';
34
30
  // Process-stable switch used to describe foreground-only execution accurately.
35
31
  const _shellBackgroundDisabled = envFlag('MIXDOG_SHELL_DISABLE_BACKGROUND_TASKS');
36
32
 
33
+ // Shell kinds the description is written for: 'powershell' or 'posix' (bash,
34
+ // zsh, sh, Git Bash, WSL), the `shellType` of the runtime's resolved shell.
35
+ // BUILTIN_TOOLS is static, so it carries the platform's default kind; a
36
+ // session whose configured system shell is the other kind gets the matching
37
+ // text through bindShellKind where the session tool schema is assembled.
38
+ const _defaultShellKind = process.platform === 'win32' ? 'powershell' : 'posix';
39
+
40
+ // The kind's banned commands → replacement tool. `edit/apply_patch` is
41
+ // rewritten per model by the edit-dialect surface filter.
42
+ export function buildShellRoutingRules(kind = _defaultShellKind) {
43
+ const pairs =
44
+ kind === 'powershell'
45
+ ? 'Get-Content/gc/cat/type→read; Get-ChildItem/dir/ls→list/glob/find; Select-String/findstr→grep; Set-Content/Add-Content/Out-File/`>`→edit/apply_patch'
46
+ : 'cat/head/tail/less→read; ls/tree→list; find→glob/find; grep/rg/ag→grep; file authoring via sed/awk/echo >/tee/heredoc→edit/apply_patch';
47
+ return `Never use shell commands/scripts for work other tools cover: ${pairs}; git→git (-C <dir> for other folders); code structure→code_graph.`;
48
+ }
49
+
50
+ function buildShellDescription(kind) {
51
+ const run = _shellBackgroundDisabled
52
+ ? 'Commands run in the foreground until completion.'
53
+ : `Holds ${_holdS}s; then, or on input/task notification, backgrounds with task_id (command keeps running). Completion is automatic; never poll, and never sleep/poll-loop inside the shell (background:true or wait_ms instead; for an external job, background a command that exits when it ends). Result needed now: task wait. Known-long finite run: wait_ms up to ${SHELL_HOLD_MAX_MS}. Independent long runs, servers/watchers: background:true; cancel them when done.`;
54
+ return `Run programs, builds, tests and computation. ${buildShellRoutingRules(kind)} ${run}`;
55
+ }
56
+
57
+ function buildShellCommandDescription(kind) {
58
+ const cheat =
59
+ kind === 'powershell'
60
+ ? " PowerShell: ; between independent commands, if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } between dependent ones; no Bash heredocs or </dev/null; Select-Object shapes program output, not file reads; multiline python/node via @'…'@ | python - (node -); 2>$null; /c/→C:\\; $PID is reserved."
61
+ : ' Bash: chain dependent commands with &&; multiline input via a quoted heredoc delimiter, not extra quoting/escape layers.';
62
+ return `Command.${cheat}`;
63
+ }
64
+
65
+ // One bound copy per (tool, kind), so a session's shell tool keeps its identity
66
+ // and bytes from turn to turn.
67
+ const _boundShellTools = new WeakMap();
68
+
69
+ /** The shell tool with the text of `kind`, when that differs from the static default. */
70
+ export function bindShellKind(tool, kind) {
71
+ if (tool?.name !== 'shell' || kind === _defaultShellKind || (kind !== 'powershell' && kind !== 'posix')) return tool;
72
+ const cached = _boundShellTools.get(tool)?.get(kind);
73
+ if (cached) return cached;
74
+ const properties = tool.inputSchema?.properties || {};
75
+ const bound = {
76
+ ...tool,
77
+ description: buildShellDescription(kind),
78
+ inputSchema: {
79
+ ...tool.inputSchema,
80
+ properties: {
81
+ ...properties,
82
+ command: { ...properties.command, description: buildShellCommandDescription(kind) },
83
+ },
84
+ },
85
+ };
86
+ if (!_boundShellTools.has(tool)) _boundShellTools.set(tool, new Map());
87
+ _boundShellTools.get(tool).set(kind, bound);
88
+ return bound;
89
+ }
90
+
37
91
  export const BUILTIN_TOOLS = [
38
92
  {
39
93
  name: 'read',
@@ -151,11 +205,15 @@ export const BUILTIN_TOOLS = [
151
205
  openWorldHint: true,
152
206
  compressible: true,
153
207
  },
154
- description: `Run programs, builds, tests and computation. Never use shell commands or scripts for work covered by dedicated tools: cat/head/tail→read, ls→list, find→glob, filename lookup→find, grep/rg→grep, code structure→code_graph, file edits/writes (sed/awk/redirection)→edit/apply_patch, Git→git when that tool is on the surface. Tool names are not shell commands. ${_shellBackgroundDisabled ? 'Commands run in the foreground until completion.' : `Holds up to ${_holdS}s for the result. Still running at ${_holdS}s, or new user input or a task notification arrives: it moves to the background (never killed) and returns task_id plus output so far. Completion is delivered automatically; task wait only when you need the result now. If no execution slot frees, the command is queued as a background task. Dev servers/watchers: background:true, and stop them with task cancel when done.`}`,
208
+ description: buildShellDescription(_defaultShellKind),
155
209
  inputSchema: {
156
210
  type: 'object',
157
211
  properties: {
158
- command: { type: 'string', description: `Command.${_shellSyntaxCheat}` },
212
+ command: { type: 'string', description: buildShellCommandDescription(_defaultShellKind) },
213
+ cwd: {
214
+ type: 'string',
215
+ description: 'Working directory; default the Project. Use it instead of cd/Set-Location.',
216
+ },
159
217
  timeout_ms: {
160
218
  type: 'integer',
161
219
  minimum: 0,
@@ -165,7 +223,7 @@ export const BUILTIN_TOOLS = [
165
223
  type: 'integer',
166
224
  minimum: SHELL_HOLD_MIN_MS,
167
225
  maximum: SHELL_HOLD_MAX_MS,
168
- description: `Hold in ms before a still-running command moves to the background (default ${SHELL_HOLD_DEFAULT_MS}). Usually omit.`,
226
+ description: `Hold in ms before a still-running command moves to the background (default ${SHELL_HOLD_DEFAULT_MS}). Usually omit; for a long finite command needed next, set up to ${SHELL_HOLD_MAX_MS}.`,
169
227
  },
170
228
  background: {
171
229
  type: 'boolean',
@@ -17,6 +17,10 @@ export function setConfiguredShell(value = '') {
17
17
  _resolvedShellByKind.clear();
18
18
  }
19
19
 
20
+ export function getConfiguredShell() {
21
+ return _configuredShell || '';
22
+ }
23
+
20
24
  function shellTypeFor(shell) {
21
25
  const stem = basename(String(shell || ''))
22
26
  .toLowerCase()
@@ -49,7 +53,9 @@ function allExistingPathsFromPath(commandName) {
49
53
  let cwd = '';
50
54
  try {
51
55
  cwd = process.cwd();
52
- } catch {}
56
+ } catch {
57
+ // the working directory may have been removed; search PATH entries only
58
+ }
53
59
  const entries = [cwd, ...rawPath.split(delimiter)]
54
60
  .map((entry) => entry.trim().replace(/^"(.*)"$/, '$1'))
55
61
  .filter(Boolean);
@@ -112,7 +112,9 @@ function _abortableDelay(ms, signal) {
112
112
  if (onAbort && signal) {
113
113
  try {
114
114
  signal.removeEventListener('abort', onAbort);
115
- } catch {}
115
+ } catch {
116
+ // the abort listener may already be gone
117
+ }
116
118
  }
117
119
  resolveDelay();
118
120
  }, ms);
@@ -173,7 +175,9 @@ async function acquireShellLeaseBounded(
173
175
  } catch {
174
176
  try {
175
177
  ctl.abort();
176
- } catch {}
178
+ } catch {
179
+ // the controller may already be aborted
180
+ }
177
181
  }
178
182
  };
179
183
  if (abortSignal) {
@@ -184,7 +188,9 @@ async function acquireShellLeaseBounded(
184
188
  const deadline = setTimeout(() => {
185
189
  try {
186
190
  ctl.abort(_admissionSaturationError(admission, waitMs, ownerKey));
187
- } catch {}
191
+ } catch {
192
+ // the controller may already be aborted
193
+ }
188
194
  }, waitMs);
189
195
  if (deadline.unref) deadline.unref();
190
196
  try {
@@ -212,7 +218,9 @@ async function acquireShellLeaseBounded(
212
218
  if (abortSignal) {
213
219
  try {
214
220
  abortSignal.removeEventListener('abort', onAbort);
215
- } catch {}
221
+ } catch {
222
+ // the abort listener may already be gone
223
+ }
216
224
  }
217
225
  }
218
226
  }
@@ -238,7 +246,7 @@ async function admitAndSpawn(run, params, { admissionWaitMs, onSaturated }) {
238
246
  run.resourceLease = await acquireShellLeaseBounded(admission, {
239
247
  abortSignal,
240
248
  waitMs: admissionWaitMs,
241
- label: `[task_id: ${run.foregroundRecordId}] ${String(command || '').slice(0, 120)}`,
249
+ label: `[task_id: ${run.foregroundRecordId}] ${String(params.displayCommand ?? command ?? '').slice(0, 120)}`,
242
250
  ownerKey: ownerSessionId,
243
251
  });
244
252
  const policyErr = await _execPolicyBlockMessage(command, elevationApproved === true);
@@ -295,11 +303,11 @@ function queueSaturatedAsTask(run, saturation, spec) {
295
303
  taskId,
296
304
  surface: 'shell',
297
305
  operation: 'shell',
298
- label: String(spec.command || '')
306
+ label: String(spec.displayCommand ?? spec.command ?? '')
299
307
  .replace(/\s+/g, ' ')
300
308
  .slice(0, 120),
301
309
  context: { callerSessionId: spec.ownerSessionId, clientHostPid: spec.clientHostPid },
302
- input: { command: spec.command, cwd: spec.cwd },
310
+ input: { command: spec.displayCommand ?? spec.command, cwd: spec.cwd },
303
311
  meta: { task_id: taskId, stdout: null, stderr: null, cwd: spec.cwd, timeoutMs: spec.backgroundDeadlineMs || 0 },
304
312
  resultType: 'shell_task_result',
305
313
  // While the command runs in the foreground, its abort handler snapshots
@@ -311,7 +319,9 @@ function queueSaturatedAsTask(run, saturation, spec) {
311
319
  if (!promotedJobId) return;
312
320
  try {
313
321
  killShellJob(promotedJobId);
314
- } catch {}
322
+ } catch {
323
+ // the job may already have exited
324
+ }
315
325
  },
316
326
  run: async () => {
317
327
  const result = await execShellCommand({
@@ -332,7 +342,9 @@ function queueSaturatedAsTask(run, saturation, spec) {
332
342
  if (queuedAbort.signal.aborted) {
333
343
  try {
334
344
  killShellJob(promotedJobId);
335
- } catch {}
345
+ } catch {
346
+ // the promoted job may already have exited
347
+ }
336
348
  }
337
349
  return settleQueuedPromotion(promotedJobId);
338
350
  }
@@ -375,7 +387,9 @@ function settleSetupFailure(run, err) {
375
387
  clearForegroundTimers(run);
376
388
  try {
377
389
  treeKill(run.child);
378
- } catch {}
390
+ } catch {
391
+ // the child may already have exited
392
+ }
379
393
  void releaseResourceLease(run);
380
394
  run.resolveResult(failedResult(run, String(err?.message || err), 'spawn failed'));
381
395
  }
@@ -451,7 +465,9 @@ function armProgressTimers(run, { onProgress, onOutputTail }) {
451
465
  const secs = Math.round(elapsedSinceStart(run) / 1000);
452
466
  try {
453
467
  onProgress(`running ${secs}s`);
454
- } catch {}
468
+ } catch {
469
+ // the progress sink is advisory
470
+ }
455
471
  }, 2000);
456
472
  if (run.progressTimer.unref) run.progressTimer.unref();
457
473
  }
@@ -549,7 +565,9 @@ function armDeadlines(
549
565
  };
550
566
  try {
551
567
  abortSignal.addEventListener('abort', run.abortHandler, { once: true });
552
- } catch {}
568
+ } catch {
569
+ // caller cancellation registration is best-effort
570
+ }
553
571
  }
554
572
  }
555
573
 
@@ -588,6 +606,10 @@ export function execShellCommand(options) {
588
606
  // hands the script to the shell out-of-band — see the POSIX env+eval path in
589
607
  // bash-tool.mjs, which keeps the command body out of the child's argv.
590
608
  execScript = null,
609
+ // What the agent passed, when `command` carries execution wrappers (the
610
+ // PowerShell UTF-8 prefix, the filter-tee rewrite). Job labels and
611
+ // records show this text; only the spawn runs `command`.
612
+ displayCommand = null,
591
613
  // The user approved this call's elevation 'ask' decision (runtime-set).
592
614
  elevationApproved = false,
593
615
  } = options;
@@ -612,6 +634,7 @@ export function execShellCommand(options) {
612
634
  abortSignal,
613
635
  directArgv,
614
636
  execScript,
637
+ displayCommand,
615
638
  elevationApproved,
616
639
  ownerSessionId,
617
640
  clientHostPid,
@@ -635,7 +658,7 @@ export function execShellCommand(options) {
635
658
  attachChildExit(run, releasePromotedCapture);
636
659
  const fireAutoBackground = createAutoBackground({
637
660
  run,
638
- command,
661
+ command: displayCommand ?? command,
639
662
  cwd,
640
663
  clientHostPid,
641
664
  ownerSessionId,
@@ -101,7 +101,7 @@ const CONTRACT_ROWS = [
101
101
  // the host.
102
102
  contract(
103
103
  'fill',
104
- [...POST_ACTION_SNAPSHOT, 'ref', 'target', 'text', 'checked', 'fields', 'submit', 'savedAccount'],
104
+ [...POST_ACTION_SNAPSHOT, 'ref', 'target', 'text', 'checked', 'fields', 'submit', 'savedAccount', 'sensitive'],
105
105
  [['ref', 'text'], ['target', 'text'], ['ref', 'checked'], ['target', 'checked'], ['fields'], ['savedAccount']]
106
106
  ),
107
107
  contract(
@@ -257,7 +257,6 @@ const SEQUENCE_STEP_STRING_LIMITS = [
257
257
  ['textGone', 10_000],
258
258
  ['url', 8_192],
259
259
  ['key', 100],
260
- ['savedAccount', 320],
261
260
  ];
262
261
 
263
262
  // The validation error of one sequence step, '' when it is well-formed.
@@ -688,10 +687,22 @@ function ruleOperationError(action, input) {
688
687
  return '';
689
688
  }
690
689
 
690
+ /** A sensitive fill's text is kept out of every stored transcript (sensitive-values.mjs)
691
+ * at any length; an empty one has nothing to protect and is refused. */
692
+ function sensitiveFillError(action, input) {
693
+ if (action !== 'fill' || input.sensitive !== true) return '';
694
+ const fields = Array.isArray(input.fields) ? input.fields : [];
695
+ const values = [input.text, ...fields.flatMap((field) => [field?.text, field?.value])];
696
+ return values.some((value) => typeof value === 'string' && value.length === 0)
697
+ ? 'browser action "fill" input.sensitive text must not be empty'
698
+ : '';
699
+ }
700
+
691
701
  // Action-specific rules, in the order they are reported.
692
702
  const ACTION_RULES = [
693
703
  navigateError,
694
704
  fillFieldsError,
705
+ sensitiveFillError,
695
706
  scrollError,
696
707
  screenshotOptionsError,
697
708
  snapshotTargetError,
@@ -9,6 +9,7 @@
9
9
  */
10
10
  import { BROWSER_OBSERVATION_ACTIONS, validateBrowserToolArgs } from './action-schema.mjs';
11
11
  import { bridgeDiscoveryChanged, readBridgeDiscovery, readBridgeDiscoveryDetail } from '../bridge-discovery.mjs';
12
+ import { mailLinkFor } from './mail-links.mjs';
12
13
  import { traceBrowserTiming } from './timing.mjs';
13
14
  import { base64ByteLength, inlineFileKind } from '../shared/inline-file-kind.mjs';
14
15
  import { MAX_IMAGE_BYTES, SUPPORTED_IMAGE_MIME_TYPES } from '../attachments/limits.mjs';
@@ -28,6 +29,39 @@ const MAX_IMAGE_BASE64_CHARS = Math.ceil((MAX_IMAGE_BYTES * 4) / 3) + 4;
28
29
  const MAX_FILE_BASE64_CHARS = Math.ceil((8 * 1024 * 1024 * 4) / 3) + 4;
29
30
  const RETRYABLE_ACTIONS = new Set(BROWSER_OBSERVATION_ACTIONS);
30
31
  const browserTurns = new Map();
32
+ /** Sessions that have issued a browser command; only they have turn
33
+ * boundaries worth telling the desktop. */
34
+ const browserSessions = new Set();
35
+
36
+ /** A turn's start, sent before it reasons or runs any tool: the desktop keeps
37
+ * the session's pages out of reclaim while a turn is live, even one that never
38
+ * issues a browser command. Remembers the bridge so the turn's end reaches it.
39
+ * A session that never used the browser has nothing to tell the desktop (its
40
+ * first command marks it live there). */
41
+ export async function beginBrowserTurn(sessionId, turnId) {
42
+ if (!browserSessions.has(sessionId)) return;
43
+ const discovery = readBridgeDiscovery(DISCOVERY_FILE);
44
+ if (!discovery || !(turnId > 0)) return;
45
+ rememberBrowserTurn(sessionId, turnId, discovery);
46
+ const result = await requestBridgeWithin(
47
+ discovery,
48
+ JSON.stringify({ action: 'begin_turn', session_id: sessionId, turn_id: turnId }),
49
+ undefined,
50
+ { sessionId, turnId, action: 'begin_turn' }
51
+ );
52
+ if (result.status !== 200 || result.body?.ok === false || result.body?.error) {
53
+ throw new Error(
54
+ `Browser turn start failed (HTTP ${result.status}): ${result.body?.error || 'bridge rejected start'}`
55
+ );
56
+ }
57
+ }
58
+
59
+ /** The session is gone for good (deleted): it no longer has turn boundaries to
60
+ * tell the desktop, and no turn of it will finish. */
61
+ export function forgetBrowserSession(sessionId) {
62
+ browserSessions.delete(sessionId);
63
+ browserTurns.delete(sessionId);
64
+ }
31
65
 
32
66
  /** Terminal lifecycle cleanup uses the exact bridge that owned this turn.
33
67
  * It is never retried after dispatch and never inherits the cancelled tool signal. */
@@ -57,13 +91,16 @@ export async function finishBrowserTurn(sessionId, turnId, { aborted = false } =
57
91
  }
58
92
  }
59
93
 
94
+ const SECRET_FILL_OUTCOMES = new Set(['entered', 'no_field', 'page_changed', 'blocked', 'expired']);
95
+
60
96
  /** Runtime-only: fill the secret the user handed the desktop for `requestId`
61
- * into the page's focused password field through the host's isolated-world
62
- * fill. The value never passes through here; the host answers only
63
- * 'provided' or 'skipped'. */
97
+ * into the field of the page it was bound to (browserHandoffPage), through
98
+ * the host's isolated-world fill. The value never passes through here; the
99
+ * host answers only the outcome ('entered', 'no_field', 'page_changed',
100
+ * 'blocked', 'expired'); no desktop or an unknown answer is 'blocked'. */
64
101
  export async function browserSecretInput(sessionId, requestId, { signal } = {}) {
65
102
  const discovery = readBridgeDiscovery(DISCOVERY_FILE);
66
- if (!discovery || !sessionId || !requestId) return 'skipped';
103
+ if (!discovery || !sessionId || !requestId) return 'blocked';
67
104
  try {
68
105
  const result = await requestBridgeWithin(
69
106
  discovery,
@@ -71,11 +108,33 @@ export async function browserSecretInput(sessionId, requestId, { signal } = {})
71
108
  signal,
72
109
  { sessionId, action: 'secret_input' }
73
110
  );
74
- return result.status === 200 && result.body?.ok !== false && result.body?.value?.text === 'provided'
75
- ? 'provided'
76
- : 'skipped';
111
+ const text = result.status === 200 && result.body?.ok !== false ? result.body?.value?.text : '';
112
+ return SECRET_FILL_OUTCOMES.has(text) ? text : 'blocked';
113
+ } catch {
114
+ return 'blocked';
115
+ }
116
+ }
117
+
118
+ /** Runtime-only facts about a session's page for an ask_user handoff, with no
119
+ * value in either direction: `secret_bind` binds `request_id` to the page
120
+ * (`tab`, else the agent's page) and says its origin and field kind;
121
+ * `login_accounts` lists the masked saved logins of `url`'s origin;
122
+ * `page_url` says where the page is now. null when the desktop is absent or
123
+ * refuses. */
124
+ export async function browserHandoffPage(sessionId, action, fields = {}, { signal } = {}) {
125
+ const discovery = readBridgeDiscovery(DISCOVERY_FILE);
126
+ if (!discovery || !sessionId) return null;
127
+ try {
128
+ const result = await requestBridgeWithin(
129
+ discovery,
130
+ JSON.stringify({ ...fields, action, session_id: String(sessionId) }),
131
+ signal,
132
+ { sessionId, action }
133
+ );
134
+ const value = result.status === 200 && result.body?.ok !== false ? result.body?.value : null;
135
+ return value && typeof value === 'object' ? value : null;
77
136
  } catch {
78
- return 'skipped';
137
+ return null;
79
138
  }
80
139
  }
81
140
 
@@ -271,10 +330,15 @@ export async function executeBrowserTool(args, options = {}) {
271
330
  if (!validated.ok) return browserToolError(validated.error);
272
331
  const sessionId = String(options.sessionId || '').trim();
273
332
  if (!sessionId) return browserToolError('browser session context is unavailable');
333
+ const mailLink = validated.action === 'navigate' ? mailLinkFor(sessionId, validated.input.url) : null;
274
334
  const payload = {
275
335
  action: validated.action,
276
336
  ...validated.input,
277
337
  session_id: sessionId,
338
+ // Runtime-set, never from the model's arguments: this exact URL is a link
339
+ // of a mail the runtime read for this session (mail-links.mjs), which the
340
+ // desktop may open although it carries a token.
341
+ ...(mailLink ? { mail_link: mailLink } : {}),
278
342
  // Set by the runtime from the session, never from the model's arguments: a
279
343
  // schedule/webhook run (or work it started) whose saved routine is the
280
344
  // user's grant for submits, posts and uploads (human-gate/run-policy.mjs).
@@ -291,6 +355,7 @@ export async function executeBrowserTool(args, options = {}) {
291
355
  }
292
356
  let discovery = readBridgeDiscovery(DISCOVERY_FILE);
293
357
  if (!discovery) return browserToolError(unavailableMessage());
358
+ browserSessions.add(sessionId);
294
359
  rememberBrowserTurn(sessionId, payload.turn_id, discovery);
295
360
  // An observation can be reported as a plain failure; a state-changing action
296
361
  // that may already have run must say so instead.
@@ -56,7 +56,7 @@ export const BROWSER_INPUT_FIELDS = {
56
56
  type: 'string',
57
57
  enum: ['semantic', 'visual', 'both'],
58
58
  description:
59
- 'snapshot only: semantic refs (default), visual image, or both. Coordinates need both; fullPage and ref/target crops need visual. navigate uses includeScreenshot.',
59
+ 'snapshot only: semantic refs (default), visual, or both. Coordinates need both; fullPage and ref/target crops need visual. navigate: includeScreenshot.',
60
60
  },
61
61
  fullPage: { type: 'boolean', description: 'Full-document screenshot; inspection-only.' },
62
62
  format: {
@@ -132,7 +132,7 @@ export const BROWSER_INPUT_FIELDS = {
132
132
  items: { type: 'string', maxLength: 60 },
133
133
  minItems: 1,
134
134
  maxItems: 12,
135
- description: 'extract only: attribute names per match; text and name always included.',
135
+ description: 'extract only: attribute names per match (text and name always come).',
136
136
  },
137
137
  operation: {
138
138
  type: 'string',
@@ -233,8 +233,7 @@ export const BROWSER_INPUT_FIELDS = {
233
233
  downloadId: {
234
234
  type: 'string',
235
235
  maxLength: 100,
236
- description:
237
- 'downloads only: d1/d2 ID; omitted, wait pins the newest (or next) download and attach takes the newest completed file.',
236
+ description: 'downloads only: d1/d2 ID; omitted: wait pins the newest (or next), attach the newest completed.',
238
237
  },
239
238
  wait: { type: 'boolean', description: 'downloads only: wait up to timeoutMs for completion.' },
240
239
  attach: { type: 'boolean', description: 'downloads only: attach the completed file (≤ 8 MiB) to the result.' },
@@ -245,11 +244,11 @@ export const BROWSER_INPUT_FIELDS = {
245
244
  },
246
245
  textGone: { type: 'string', maxLength: 10000, description: 'wait: page-text substring that must disappear.' },
247
246
  submit: { type: 'boolean', description: 'fill or type: press Enter afterward.' },
247
+ sensitive: { type: 'boolean', description: 'fill: code/secret text; redacted in output and transcript.' },
248
248
  savedAccount: {
249
249
  type: 'string',
250
- maxLength: 320,
251
250
  description:
252
- 'fill: account or masked label saved for this HTTPS site; fills the whole sign-in form, password kept on the host. No ref/target/text; submit presses Enter.',
251
+ 'fill: saved login (account or masked label) of this HTTPS site; fills the sign-in form, password stays on the host. No ref/target/text.',
253
252
  },
254
253
  key: {
255
254
  type: 'string',
@@ -326,7 +325,7 @@ export const BROWSER_INPUT_FIELDS = {
326
325
  checked: { type: 'boolean' },
327
326
  key: { type: 'string', maxLength: 100 },
328
327
  submit: { type: 'boolean' },
329
- savedAccount: { type: 'string', maxLength: 320, description: 'fill: as input.savedAccount.' },
328
+ savedAccount: { type: 'string', description: 'fill: as input.savedAccount.' },
330
329
  dx: { type: 'integer' },
331
330
  dy: { type: 'integer' },
332
331
  textGone: { type: 'string', maxLength: 10000 },
@@ -399,12 +398,12 @@ export const BROWSER_INPUT_FIELDS = {
399
398
  type: 'string',
400
399
  maxLength: 64,
401
400
  description:
402
- 'Session-local page ID p1/p2… from list_tabs (v1/v2 aliases work), or a background page name; background:true creates one. Popups are named background pages.',
401
+ 'Page ID p1/p2… from list_tabs (or v1/v2), or a background page name (background:true makes one; popups get one).',
403
402
  },
404
403
  background: {
405
404
  type: 'boolean',
406
405
  description:
407
- 'true creates/targets a hidden support page; false reveals it until task end; omitted never promotes a named one. open without true keeps it for user handoff.',
406
+ 'true: create/target a hidden support page; false: reveal it until task end; omitted never promotes a named one. open without true keeps it for handoff.',
408
407
  },
409
408
  },
410
409
  };