@abot-ai/runtime 1.7.0 → 1.8.1

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 (532) hide show
  1. package/README.md +216 -222
  2. package/dist/src/capabilities/tool-definition-validator/definition-parser.js +8 -0
  3. package/dist/src/capabilities/tool-request-resources.d.ts +3 -0
  4. package/dist/src/capabilities/tool-types.d.ts +4 -0
  5. package/dist/src/cli/abot.js +2 -0
  6. package/dist/src/cli/host-companion-bundle.mjs +751 -333
  7. package/dist/src/computer-access/collection-consent.d.ts +9 -0
  8. package/dist/src/computer-access/collection-consent.js +47 -0
  9. package/dist/src/computer-access/command-output-capture.d.ts +17 -6
  10. package/dist/src/computer-access/command-output-capture.js +134 -68
  11. package/dist/src/computer-access/command-output-protection.d.ts +17 -0
  12. package/dist/src/computer-access/command-output-protection.js +59 -0
  13. package/dist/src/computer-access/companion/command-output.d.ts +1 -0
  14. package/dist/src/computer-access/companion/command-output.js +23 -6
  15. package/dist/src/computer-access/companion/install-link-macos.js +2 -1
  16. package/dist/src/computer-access/companion/native-notifications.js +3 -2
  17. package/dist/src/computer-access/companion/native-session.js +6 -2
  18. package/dist/src/computer-access/companion/observation-filter.js +2 -26
  19. package/dist/src/computer-access/companion/observation-process.d.ts +2 -0
  20. package/dist/src/computer-access/companion/observation-process.js +51 -25
  21. package/dist/src/computer-access/companion/observation-redaction.d.ts +2 -7
  22. package/dist/src/computer-access/companion/observation-redaction.js +2 -111
  23. package/dist/src/computer-access/companion/secret-protection-protocol.d.ts +6 -0
  24. package/dist/src/computer-access/companion/secret-protection-protocol.js +6 -0
  25. package/dist/src/computer-access/computer/companion-sessions.js +7 -6
  26. package/dist/src/computer-access/computer/unix-native-process.js +23 -11
  27. package/dist/src/computer-access/handlers.d.ts +2 -1
  28. package/dist/src/computer-access/handlers.js +79 -11
  29. package/dist/src/computer-access/host-observation.d.ts +3 -3
  30. package/dist/src/computer-access/native-observation-connection.d.ts +12 -0
  31. package/dist/src/computer-access/native-observation-connection.js +78 -0
  32. package/dist/src/computer-access/native-observation-ownership.d.ts +6 -0
  33. package/dist/src/computer-access/native-observation-ownership.js +55 -0
  34. package/dist/src/computer-access/native-observation-shutdown.d.ts +7 -0
  35. package/dist/src/computer-access/native-observation-shutdown.js +58 -0
  36. package/dist/src/computer-access/observation-source.d.ts +6 -0
  37. package/dist/src/computer-access/observation-source.js +10 -0
  38. package/dist/src/computer-access/security/desktop-result.d.ts +8 -0
  39. package/dist/src/computer-access/security/desktop-result.js +146 -0
  40. package/dist/src/computer-access/security/observed-error.d.ts +2 -0
  41. package/dist/src/computer-access/security/observed-error.js +10 -0
  42. package/dist/src/computer-access/security/secret-text.d.ts +7 -0
  43. package/dist/src/computer-access/security/secret-text.js +111 -0
  44. package/dist/src/computer-access/security/system-results.d.ts +2 -0
  45. package/dist/src/computer-access/security/system-results.js +53 -0
  46. package/dist/src/computer-access/system-result-protection.d.ts +11 -0
  47. package/dist/src/computer-access/system-result-protection.js +1 -0
  48. package/dist/src/model-gateway/observability/provider-response-capture.d.ts +60 -0
  49. package/dist/src/model-gateway/observability/provider-response-capture.js +68 -0
  50. package/dist/src/model-gateway/observability/provider-response-prefix.d.ts +7 -0
  51. package/dist/src/model-gateway/observability/provider-response-prefix.js +14 -0
  52. package/dist/src/model-gateway/observability/provider-response-tail.d.ts +8 -0
  53. package/dist/src/model-gateway/observability/provider-response-tail.js +28 -0
  54. package/dist/src/model-gateway/observability/provider-sse-diagnostics.d.ts +30 -0
  55. package/dist/src/model-gateway/observability/provider-sse-diagnostics.js +119 -0
  56. package/dist/src/model-gateway/observability/provider-trace.js +30 -8
  57. package/dist/src/model-gateway/protocol/message-contract.d.ts +1 -0
  58. package/dist/src/model-gateway/protocol/message-contract.js +1 -1
  59. package/dist/src/model-gateway/providers/ollama/adapter.js +8 -2
  60. package/dist/src/model-gateway/providers/ollama/stream-normalizer.js +70 -50
  61. package/dist/src/model-gateway/providers/ollama/stream-termination.d.ts +6 -0
  62. package/dist/src/model-gateway/providers/ollama/stream-termination.js +20 -0
  63. package/dist/src/model-gateway/providers/openai/adapter.js +9 -7
  64. package/dist/src/model-gateway/providers/openai/diagnostics.d.ts +0 -1
  65. package/dist/src/model-gateway/providers/openai/diagnostics.js +0 -9
  66. package/dist/src/model-gateway/providers/openai/function-output.d.ts +11 -0
  67. package/dist/src/model-gateway/providers/openai/function-output.js +37 -0
  68. package/dist/src/model-gateway/providers/openai/function-result.d.ts +7 -0
  69. package/dist/src/model-gateway/providers/openai/function-result.js +35 -0
  70. package/dist/src/model-gateway/providers/openai/message-output-policy.d.ts +3 -0
  71. package/dist/src/model-gateway/providers/openai/message-output-policy.js +16 -0
  72. package/dist/src/model-gateway/providers/openai/payload.d.ts +0 -2
  73. package/dist/src/model-gateway/providers/openai/payload.js +6 -23
  74. package/dist/src/model-gateway/providers/openai/response-lifetime.d.ts +2 -0
  75. package/dist/src/model-gateway/providers/openai/response-lifetime.js +64 -0
  76. package/dist/src/model-gateway/providers/openai/sse-data.d.ts +9 -0
  77. package/dist/src/model-gateway/providers/openai/sse-data.js +67 -0
  78. package/dist/src/model-gateway/providers/openai/stream-normalizer.d.ts +10 -22
  79. package/dist/src/model-gateway/providers/openai/stream-normalizer.js +78 -79
  80. package/dist/src/model-gateway/providers/openai/stream.js +13 -41
  81. package/dist/src/model-gateway/providers/openai/structured-message-output.d.ts +42 -0
  82. package/dist/src/model-gateway/providers/openai/structured-message-output.js +175 -0
  83. package/dist/src/model-gateway/server/chat-handler.js +5 -7
  84. package/dist/src/model-gateway/server/chat-stream-response.d.ts +7 -0
  85. package/dist/src/model-gateway/server/chat-stream-response.js +25 -0
  86. package/dist/src/model-gateway/server.js +5 -1
  87. package/dist/src/plugin-contract/index.d.ts +1 -0
  88. package/dist/src/plugin-contract/index.js +1 -0
  89. package/dist/src/plugin-contract/manifest.d.ts +2 -0
  90. package/dist/src/plugin-contract/manifest.js +1 -0
  91. package/dist/src/plugin-contract/platform-compatibility.d.ts +16 -0
  92. package/dist/src/plugin-contract/platform-compatibility.js +3 -0
  93. package/dist/src/plugin-sdk/computer-access.d.ts +4 -0
  94. package/dist/src/plugin-sdk/computer-access.js +1 -0
  95. package/dist/src/plugin-sdk/files-windows/process.d.ts +3 -0
  96. package/dist/src/plugin-sdk/files-windows/process.js +93 -0
  97. package/dist/src/plugin-sdk/files-windows/read-script.d.ts +1 -0
  98. package/dist/src/plugin-sdk/files-windows/read-script.js +43 -0
  99. package/dist/src/plugin-sdk/files-windows/read.d.ts +6 -0
  100. package/dist/src/plugin-sdk/files-windows/read.js +56 -0
  101. package/dist/src/plugin-sdk/files-windows/result.d.ts +4 -0
  102. package/dist/src/plugin-sdk/files-windows/result.js +67 -0
  103. package/dist/src/plugin-sdk/files.js +4 -0
  104. package/dist/src/plugin-sdk/index.d.ts +1 -0
  105. package/dist/src/plugin-sdk/index.js +1 -0
  106. package/dist/src/plugin-sdk/mutation-result.d.ts +7 -0
  107. package/dist/src/plugin-sdk/mutation-result.js +11 -0
  108. package/dist/src/runtime/adapters/long-term-memory/file-lock/acquisition.js +20 -3
  109. package/dist/src/runtime/adapters/long-term-memory/file-lock/owner-record.js +3 -1
  110. package/dist/src/runtime/adapters/long-term-memory/file-lock/path-observation.d.ts +3 -0
  111. package/dist/src/runtime/adapters/long-term-memory/file-lock/path-observation.js +20 -0
  112. package/dist/src/runtime/adapters/long-term-memory/file-lock/snapshot.js +7 -3
  113. package/dist/src/runtime/adapters/passive-learning-runtime.d.ts +1 -1
  114. package/dist/src/runtime/adapters/passive-learning-runtime.js +3 -3
  115. package/dist/src/runtime/adapters/registered-tool-worker-capabilities/payload-rejection.d.ts +2 -2
  116. package/dist/src/runtime/adapters/registered-tool-worker-capabilities/payload-rejection.js +2 -2
  117. package/dist/src/runtime/adapters/registered-tool-worker-capabilities/prepared-execution.js +17 -11
  118. package/dist/src/runtime/adapters/runtime-observation-connection.d.ts +5 -0
  119. package/dist/src/runtime/adapters/runtime-observation-connection.js +13 -0
  120. package/dist/src/runtime/capabilities/tool-availability.js +6 -0
  121. package/dist/src/runtime/context/capability-brief.d.ts +2 -2
  122. package/dist/src/runtime/context/capability-brief.js +3 -3
  123. package/dist/src/runtime/context/capability-descriptions.d.ts +3 -2
  124. package/dist/src/runtime/context/capability-descriptions.js +57 -20
  125. package/dist/src/runtime/local-host/windows-private-access.js +2 -0
  126. package/dist/src/runtime/long-term-memory/conversation-authoring/context.d.ts +6 -1
  127. package/dist/src/runtime/long-term-memory/conversation-authoring/context.js +51 -25
  128. package/dist/src/runtime/long-term-memory/initial-context.d.ts +17 -0
  129. package/dist/src/runtime/long-term-memory/initial-context.js +57 -0
  130. package/dist/src/runtime/long-term-memory/projection.js +1 -1
  131. package/dist/src/runtime/orchestration/role-calls/candidate-validation.js +2 -1
  132. package/dist/src/runtime/orchestration/role-calls/checkpoint-state.d.ts +1 -1
  133. package/dist/src/runtime/orchestration/role-calls/checkpoint-state.js +5 -2
  134. package/dist/src/runtime/orchestration/role-calls/contracts.d.ts +2 -1
  135. package/dist/src/runtime/orchestration/role-calls/ledger.d.ts +2 -1
  136. package/dist/src/runtime/orchestration/role-calls/ledger.js +2 -2
  137. package/dist/src/runtime/orchestration/role-calls/memory-recall-contract.d.ts +7 -0
  138. package/dist/src/runtime/orchestration/role-calls/memory-recall-state-validation.d.ts +2 -0
  139. package/dist/src/runtime/orchestration/role-calls/memory-recall-state-validation.js +88 -0
  140. package/dist/src/runtime/orchestration/role-calls/reducer.d.ts +1 -1
  141. package/dist/src/runtime/orchestration/role-calls/reducer.js +2 -1
  142. package/dist/src/runtime/orchestration/worker-capabilities/contracts.d.ts +3 -1
  143. package/dist/src/runtime/orchestration/worker-capabilities/contracts.js +1 -1
  144. package/dist/src/runtime/orchestration/worker-capabilities/execution/approval-group.js +5 -1
  145. package/dist/src/runtime/orchestration/worker-capabilities/execution/execution-freshness.d.ts +5 -0
  146. package/dist/src/runtime/orchestration/worker-capabilities/execution/execution-freshness.js +31 -0
  147. package/dist/src/runtime/passive-learning/application-catalog.js +3 -1
  148. package/dist/src/runtime/passive-learning/collection-source.js +7 -0
  149. package/dist/src/runtime/passive-learning/service.js +2 -3
  150. package/dist/src/runtime/passive-learning/status-projection.d.ts +2 -0
  151. package/dist/src/runtime/passive-learning/status-projection.js +9 -0
  152. package/dist/src/runtime/plugins/installation/package.d.ts +8 -0
  153. package/dist/src/runtime/plugins/installation/package.js +2 -0
  154. package/dist/src/runtime/plugins/installation/service.d.ts +7 -0
  155. package/dist/src/runtime/plugins/loader.js +24 -14
  156. package/dist/src/runtime/plugins/manifest-platform-compatibility.d.ts +2 -0
  157. package/dist/src/runtime/plugins/manifest-platform-compatibility.js +39 -0
  158. package/dist/src/runtime/plugins/manifest-projection.js +3 -0
  159. package/dist/src/runtime/plugins/manifest-validator.js +9 -1
  160. package/dist/src/runtime/plugins/platform-compatibility.d.ts +4 -0
  161. package/dist/src/runtime/plugins/platform-compatibility.js +44 -0
  162. package/dist/src/runtime/request/approval-wait/activation-events.js +19 -7
  163. package/dist/src/runtime/request/approval-wait/execution-compaction-restore.d.ts +20 -0
  164. package/dist/src/runtime/request/approval-wait/execution-compaction-restore.js +118 -0
  165. package/dist/src/runtime/request/approval-wait/super-compaction-restore.js +2 -1
  166. package/dist/src/runtime/request/capability-execution-freshness.js +6 -1
  167. package/dist/src/runtime/request/execution-agent-root-execution.js +11 -1
  168. package/dist/src/runtime/request/prepared-execution.js +3 -0
  169. package/dist/src/runtime/request/root-contract.d.ts +2 -0
  170. package/dist/src/runtime/request/root-execution-kernel.js +1 -0
  171. package/dist/src/runtime/request/runner.js +9 -3
  172. package/dist/src/runtime/request/supervisor-root-execution.js +6 -0
  173. package/dist/src/runtime/steps/execution-agent/capability-result-context.d.ts +6 -0
  174. package/dist/src/runtime/steps/execution-agent/capability-result-context.js +29 -0
  175. package/dist/src/runtime/steps/execution-agent/contracts.d.ts +10 -0
  176. package/dist/src/runtime/steps/execution-agent/decision-parsing.js +13 -1
  177. package/dist/src/runtime/steps/execution-agent/direct-response-configuration.d.ts +3 -0
  178. package/dist/src/runtime/steps/execution-agent/direct-response-configuration.js +64 -0
  179. package/dist/src/runtime/steps/execution-agent/direct-response-contract.d.ts +7 -0
  180. package/dist/src/runtime/steps/execution-agent/direct-response-contract.js +56 -0
  181. package/dist/src/runtime/steps/execution-agent/direct-response-policy.d.ts +9 -0
  182. package/dist/src/runtime/steps/execution-agent/direct-response-policy.js +30 -0
  183. package/dist/src/runtime/steps/execution-agent/direct-response-prompt.d.ts +7 -0
  184. package/dist/src/runtime/steps/execution-agent/direct-response-prompt.js +43 -0
  185. package/dist/src/runtime/steps/execution-agent/format.js +4 -3
  186. package/dist/src/runtime/steps/execution-agent/input.d.ts +2 -0
  187. package/dist/src/runtime/steps/execution-agent/input.js +22 -1
  188. package/dist/src/runtime/steps/execution-agent/plugin-catalog.d.ts +4 -0
  189. package/dist/src/runtime/steps/execution-agent/plugin-catalog.js +8 -0
  190. package/dist/src/runtime/steps/execution-agent/prompt.d.ts +1 -0
  191. package/dist/src/runtime/steps/execution-agent/prompt.js +7 -8
  192. package/dist/src/runtime/steps/execution-agent/response-prompt.js +1 -0
  193. package/dist/src/runtime/steps/execution-agent/response-run.js +5 -11
  194. package/dist/src/runtime/steps/execution-agent/run.js +4 -1
  195. package/dist/src/runtime/steps/execution-agent/state-context.d.ts +3 -5
  196. package/dist/src/runtime/steps/execution-agent/state-context.js +5 -51
  197. package/dist/src/runtime/steps/execution-agent/work-plan-contract.d.ts +1 -3
  198. package/dist/src/runtime/steps/execution-agent/work-plan-contract.js +0 -55
  199. package/dist/src/runtime/steps/execution-agent/work-plan-schema.d.ts +3 -0
  200. package/dist/src/runtime/steps/execution-agent/work-plan-schema.js +61 -0
  201. package/dist/src/runtime/steps/planner-decision/capability-brief.d.ts +2 -0
  202. package/dist/src/runtime/steps/planner-decision/prompt.js +26 -49
  203. package/dist/src/runtime/steps/supervisor-decision/input.d.ts +1 -0
  204. package/dist/src/runtime/steps/supervisor-decision/input.js +5 -0
  205. package/dist/src/runtime/steps/supervisor-decision/prompt.d.ts +1 -0
  206. package/dist/src/runtime/steps/supervisor-decision/prompt.js +6 -2
  207. package/dist/src/runtime/steps/supervisor-decision/run.d.ts +1 -0
  208. package/dist/src/runtime/steps/supervisor-decision/run.js +4 -0
  209. package/dist/src/runtime/steps/supervisor-response/run.d.ts +2 -0
  210. package/dist/src/runtime/steps/supervisor-response/run.js +3 -6
  211. package/dist/src/sessions/durable-session-commit.js +3 -3
  212. package/dist/src/sessions/prepared-session-replacement.d.ts +6 -0
  213. package/dist/src/sessions/prepared-session-replacement.js +46 -0
  214. package/dist/src/sessions/session-store.js +3 -3
  215. package/dist/src/shared/passive-observation-self-exclusion.d.ts +5 -0
  216. package/dist/src/shared/passive-observation-self-exclusion.js +37 -0
  217. package/dist/src/shared/windows-file-io/authority-script.d.ts +1 -0
  218. package/dist/src/shared/windows-file-io/authority-script.js +94 -0
  219. package/dist/src/shared/windows-file-io/native-script.d.ts +2 -0
  220. package/dist/src/shared/windows-file-io/native-script.js +120 -0
  221. package/dist/src/shared/windows-file-io/read-bytes-script.d.ts +1 -0
  222. package/dist/src/shared/windows-file-io/read-bytes-script.js +18 -0
  223. package/dist/src/shared/windows-job-object.d.ts +2 -0
  224. package/dist/src/shared/windows-job-object.js +66 -0
  225. package/dist/src/web-ui/app/ARCHITECTURE.md +1 -1
  226. package/dist/src/web-ui/app/app-bootstrap.js +14 -1
  227. package/dist/src/web-ui/app/app-state.js +0 -7
  228. package/dist/src/web-ui/app/app.js +54 -156
  229. package/dist/src/web-ui/app/components/automations/node-inspector.js +3 -2
  230. package/dist/src/web-ui/app/components/automations/step-editor-dialog.js +3 -0
  231. package/dist/src/web-ui/app/components/automations/timeline.js +3 -2
  232. package/dist/src/web-ui/app/components/composer-submission-notice.js +50 -0
  233. package/dist/src/web-ui/app/components/config-workspace/model-plugin-permissions.js +7 -1
  234. package/dist/src/web-ui/app/components/config-workspace/workspace-mutations.js +22 -2
  235. package/dist/src/web-ui/app/components/dashboard/compact-layout.js +137 -0
  236. package/dist/src/web-ui/app/components/dashboard/icons.js +5 -0
  237. package/dist/src/web-ui/app/components/dashboard/widget-card.js +85 -0
  238. package/dist/src/web-ui/app/components/dashboard/widget-dialog.js +83 -0
  239. package/dist/src/web-ui/app/components/dashboard/widget-summaries.js +155 -0
  240. package/dist/src/web-ui/app/components/dashboard/workspace.js +28 -4
  241. package/dist/src/web-ui/app/components/home-guidance/daily-review.js +2 -2
  242. package/dist/src/web-ui/app/components/home-guidance/home-guidance.js +20 -6
  243. package/dist/src/web-ui/app/components/model-setup/context-window-feedback.js +53 -0
  244. package/dist/src/web-ui/app/components/model-setup/save-flow.js +3 -1
  245. package/dist/src/web-ui/app/components/model-setup/save-outcome.js +1 -0
  246. package/dist/src/web-ui/app/components/model-setup/wizard.js +12 -0
  247. package/dist/src/web-ui/app/components/operations-summary.js +2 -1
  248. package/dist/src/web-ui/app/components/passive-learning/activity-controls.js +4 -0
  249. package/dist/src/web-ui/app/components/passive-learning/collection-access.js +35 -0
  250. package/dist/src/web-ui/app/components/passive-learning/collection-consent-dialog.js +59 -0
  251. package/dist/src/web-ui/app/components/passive-learning/collection-consent-gate.js +94 -0
  252. package/dist/src/web-ui/app/components/passive-learning/computer-update-notice.js +6 -0
  253. package/dist/src/web-ui/app/components/passive-learning/failure-copy.js +1 -0
  254. package/dist/src/web-ui/app/components/passive-learning/home-widget-preview.js +32 -0
  255. package/dist/src/web-ui/app/components/passive-learning/home.js +11 -3
  256. package/dist/src/web-ui/app/components/passive-learning/macos-collection-restart-notice.js +1 -0
  257. package/dist/src/web-ui/app/components/passive-learning/memory.js +2 -4
  258. package/dist/src/web-ui/app/components/passive-learning/workspace-view.js +2 -2
  259. package/dist/src/web-ui/app/components/plugins/compatibility.js +13 -0
  260. package/dist/src/web-ui/app/components/plugins/discovery-rendering.js +9 -1
  261. package/dist/src/web-ui/app/components/plugins/installation-compatibility.js +7 -0
  262. package/dist/src/web-ui/app/components/plugins/installation.js +2 -1
  263. package/dist/src/web-ui/app/components/plugins/rendering.js +3 -0
  264. package/dist/src/web-ui/app/components/reasoning-override-prompt.js +82 -0
  265. package/dist/src/web-ui/app/components/runtime-config-activation.js +22 -8
  266. package/dist/src/web-ui/app/components/runtime-setup/optional-steps.js +7 -4
  267. package/dist/src/web-ui/app/components/runtime-setup/plugins.js +3 -1
  268. package/dist/src/web-ui/app/components/runtime-setup/rendering.js +6 -4
  269. package/dist/src/web-ui/app/components/runtime-setup-guide.d.ts +1 -0
  270. package/dist/src/web-ui/app/components/schedules/details.js +3 -2
  271. package/dist/src/web-ui/app/components/schedules/form.js +10 -8
  272. package/dist/src/web-ui/app/components/schedules/workspace.js +23 -4
  273. package/dist/src/web-ui/app/components/session-sidebar-sections.js +2 -2
  274. package/dist/src/web-ui/app/components/spark-chat/handoff-actions.js +9 -3
  275. package/dist/src/web-ui/app/components/spark-chat/panel.js +1 -1
  276. package/dist/src/web-ui/app/components/spark-chat/placement.js +4 -7
  277. package/dist/src/web-ui/app/components/spark-chat/settings.js +8 -4
  278. package/dist/src/web-ui/app/components/system-host/home-widget-permission-preview.js +75 -0
  279. package/dist/src/web-ui/app/components/system-host/home-widget-summary.js +93 -0
  280. package/dist/src/web-ui/app/components/system-host/macos-permission-rendering.js +2 -2
  281. package/dist/src/web-ui/app/components/system-host/macos-permissions.js +2 -0
  282. package/dist/src/web-ui/app/components/system-host/native-windows-access.js +50 -0
  283. package/dist/src/web-ui/app/components/system-host/rendering.js +6 -3
  284. package/dist/src/web-ui/app/components/system-host/windows-store-setup.js +2 -2
  285. package/dist/src/web-ui/app/components/workspace-storage-notice.js +37 -0
  286. package/dist/src/web-ui/app/computer-access-feature.js +13 -1
  287. package/dist/src/web-ui/app/configuration-environment-refresh.js +27 -34
  288. package/dist/src/web-ui/app/configuration-feature.js +11 -1
  289. package/dist/src/web-ui/app/controllers/app-event-bindings.js +38 -105
  290. package/dist/src/web-ui/app/controllers/chat-request-controller.d.ts +28 -0
  291. package/dist/src/web-ui/app/controllers/chat-request-controller.js +34 -66
  292. package/dist/src/web-ui/app/controllers/composer-attachments-controller.d.ts +15 -40
  293. package/dist/src/web-ui/app/controllers/composer-attachments-controller.js +26 -69
  294. package/dist/src/web-ui/app/controllers/composer-draft-view.d.ts +27 -0
  295. package/dist/src/web-ui/app/controllers/composer-draft-view.js +48 -0
  296. package/dist/src/web-ui/app/controllers/composer-drafts.d.ts +55 -0
  297. package/dist/src/web-ui/app/controllers/composer-drafts.js +120 -0
  298. package/dist/src/web-ui/app/controllers/composer-feature.d.ts +65 -0
  299. package/dist/src/web-ui/app/controllers/composer-feature.js +124 -0
  300. package/dist/src/web-ui/app/controllers/composer-queue-controller.d.ts +33 -94
  301. package/dist/src/web-ui/app/controllers/composer-queue-controller.js +185 -251
  302. package/dist/src/web-ui/app/controllers/composer-submission-lifecycle.d.ts +48 -0
  303. package/dist/src/web-ui/app/controllers/composer-submission-lifecycle.js +97 -0
  304. package/dist/src/web-ui/app/controllers/composer-submit-controller.d.ts +30 -61
  305. package/dist/src/web-ui/app/controllers/composer-submit-controller.js +56 -138
  306. package/dist/src/web-ui/app/controllers/composer-surface-controller.js +6 -0
  307. package/dist/src/web-ui/app/controllers/composer-workspace-controller.d.ts +22 -40
  308. package/dist/src/web-ui/app/controllers/composer-workspace-controller.js +49 -165
  309. package/dist/src/web-ui/app/controllers/conversation-navigation-intent.js +15 -0
  310. package/dist/src/web-ui/app/controllers/conversation-request-hydration.js +20 -17
  311. package/dist/src/web-ui/app/controllers/conversation-session-controller.d.ts +1 -2
  312. package/dist/src/web-ui/app/controllers/conversation-session-controller.js +49 -22
  313. package/dist/src/web-ui/app/controllers/conversation-workspace-activation.js +27 -0
  314. package/dist/src/web-ui/app/controllers/daily-memory-review.js +15 -16
  315. package/dist/src/web-ui/app/controllers/environment-transition.js +126 -0
  316. package/dist/src/web-ui/app/controllers/environment-workspace-preparation.js +18 -0
  317. package/dist/src/web-ui/app/controllers/home-composer-feature.d.ts +14 -36
  318. package/dist/src/web-ui/app/controllers/home-composer-feature.js +17 -114
  319. package/dist/src/web-ui/app/controllers/home-conversation-activation.js +6 -8
  320. package/dist/src/web-ui/app/controllers/operations-controller.js +2 -1
  321. package/dist/src/web-ui/app/controllers/passive-learning-controller.js +56 -0
  322. package/dist/src/web-ui/app/controllers/projects-controller.d.ts +1 -1
  323. package/dist/src/web-ui/app/controllers/projects-controller.js +6 -1
  324. package/dist/src/web-ui/app/controllers/reasoning-mode-controller.js +174 -0
  325. package/dist/src/web-ui/app/controllers/runtime-selection-controller.d.ts +7 -0
  326. package/dist/src/web-ui/app/controllers/runtime-selection-controller.js +20 -155
  327. package/dist/src/web-ui/app/controllers/session-controller.js +33 -17
  328. package/dist/src/web-ui/app/controllers/session-pin-updates.js +14 -0
  329. package/dist/src/web-ui/app/controllers/session-sidebar-controller.js +12 -14
  330. package/dist/src/web-ui/app/controllers/spark-chat-sync.js +2 -2
  331. package/dist/src/web-ui/app/controllers/steer-controller.js +9 -7
  332. package/dist/src/web-ui/app/controllers/tool-permission-mode-controller.js +1 -1
  333. package/dist/src/web-ui/app/controllers/workspace-conversation-opener.js +34 -0
  334. package/dist/src/web-ui/app/dashboard-feature.js +12 -2
  335. package/dist/src/web-ui/app/lib/reasoning-controls.js +40 -0
  336. package/dist/src/web-ui/app/lib/session-composer-queue-ownership.js +58 -0
  337. package/dist/src/web-ui/app/lib/session-composer-queue.d.ts +12 -0
  338. package/dist/src/web-ui/app/lib/session-composer-queue.js +25 -6
  339. package/dist/src/web-ui/app/passive-learning-feature.js +18 -5
  340. package/dist/src/web-ui/app/schedules-feature.js +5 -3
  341. package/dist/src/web-ui/app/services/client-preferences.d.ts +18 -10
  342. package/dist/src/web-ui/app/services/client-preferences.js +25 -16
  343. package/dist/src/web-ui/app/services/home-guidance-preferences.js +13 -13
  344. package/dist/src/web-ui/app/services/reasoning-override.js +12 -0
  345. package/dist/src/web-ui/app/services/runtime-web-client/automations.js +10 -2
  346. package/dist/src/web-ui/app/services/runtime-web-client/memory.js +7 -2
  347. package/dist/src/web-ui/app/services/runtime-web-client/system-host.js +2 -0
  348. package/dist/src/web-ui/app/services/runtime-web-client.d.ts +2 -0
  349. package/dist/src/web-ui/app/services/runtime-web-client.js +2 -0
  350. package/dist/src/web-ui/app/services/server-composer-queue.js +32 -0
  351. package/dist/src/web-ui/app/services/session-sidebar-preferences.js +5 -5
  352. package/dist/src/web-ui/app/services/workspace-state-storage.js +116 -0
  353. package/dist/src/web-ui/app/services/workspace-state.js +27 -0
  354. package/dist/src/web-ui/app/spark-chat-conversation.js +34 -45
  355. package/dist/src/web-ui/app/spark-chat-feature.js +10 -4
  356. package/dist/src/web-ui/app/styles/21-composer-controls.css +16 -0
  357. package/dist/src/web-ui/app/styles/41-plugin-management.css +8 -0
  358. package/dist/src/web-ui/app/styles/42-model-plugin-permissions.css +1 -0
  359. package/dist/src/web-ui/app/styles/49-collection-consent.css +30 -0
  360. package/dist/src/web-ui/app/styles/64-workspace-storage.css +23 -0
  361. package/dist/src/web-ui/app/styles/95-home-widgets.css +109 -0
  362. package/dist/src/web-ui/app/styles.css +3 -0
  363. package/dist/src/web-ui/client-state/contracts.d.ts +15 -0
  364. package/dist/src/web-ui/client-state/contracts.js +13 -0
  365. package/dist/src/web-ui/client-state/preference-shapes.d.ts +2 -0
  366. package/dist/src/web-ui/client-state/preference-shapes.js +80 -0
  367. package/dist/src/web-ui/client-state/preferences.d.ts +3 -0
  368. package/dist/src/web-ui/client-state/preferences.js +84 -0
  369. package/dist/src/web-ui/client-state/queue.d.ts +3 -0
  370. package/dist/src/web-ui/client-state/queue.js +43 -0
  371. package/dist/src/web-ui/client-state/routes.d.ts +7 -0
  372. package/dist/src/web-ui/client-state/routes.js +58 -0
  373. package/dist/src/web-ui/client-state/store.d.ts +14 -0
  374. package/dist/src/web-ui/client-state/store.js +88 -0
  375. package/dist/src/web-ui/local-runtime/configuration-activation-source.js +2 -0
  376. package/dist/src/web-ui/local-runtime/http.js +11 -2
  377. package/dist/src/web-ui/local-runtime/model-context-capacity-error.d.ts +14 -0
  378. package/dist/src/web-ui/local-runtime/model-context-capacity-error.js +28 -0
  379. package/dist/src/web-ui/local-runtime/model-setup-context-window.d.ts +15 -0
  380. package/dist/src/web-ui/local-runtime/model-setup-context-window.js +25 -0
  381. package/dist/src/web-ui/local-runtime/model-setup-routes.js +2 -0
  382. package/dist/src/web-ui/local-runtime/model-setup-service.js +5 -2
  383. package/dist/src/web-ui/local-runtime/model-setup-validation.d.ts +1 -0
  384. package/dist/src/web-ui/local-runtime/model-setup-validation.js +14 -7
  385. package/dist/src/web-ui/local-runtime/request-body-error.d.ts +11 -0
  386. package/dist/src/web-ui/local-runtime/request-body-error.js +14 -0
  387. package/dist/src/web-ui/local-runtime/request-control-observation.js +2 -2
  388. package/dist/src/web-ui/local-runtime/request-execution.js +18 -18
  389. package/dist/src/web-ui/local-runtime/runtime-setup-connection-edit.d.ts +2 -0
  390. package/dist/src/web-ui/local-runtime/runtime-setup-connection-edit.js +35 -22
  391. package/dist/src/web-ui/local-runtime/runtime-setup-context-window.d.ts +2 -9
  392. package/dist/src/web-ui/local-runtime/runtime-setup-context-window.js +4 -27
  393. package/dist/src/web-ui/local-runtime/runtime-setup-credentials.d.ts +15 -1
  394. package/dist/src/web-ui/local-runtime/runtime-setup-credentials.js +30 -11
  395. package/dist/src/web-ui/local-runtime/runtime-setup-edit-files.d.ts +20 -0
  396. package/dist/src/web-ui/local-runtime/runtime-setup-edit-files.js +104 -0
  397. package/dist/src/web-ui/local-runtime/runtime-setup-edit-journal.d.ts +29 -0
  398. package/dist/src/web-ui/local-runtime/runtime-setup-edit-journal.js +151 -0
  399. package/dist/src/web-ui/local-runtime/runtime-setup-edit-recovery.d.ts +7 -0
  400. package/dist/src/web-ui/local-runtime/runtime-setup-edit-recovery.js +87 -0
  401. package/dist/src/web-ui/local-runtime/runtime-setup-edit-transaction.d.ts +3 -0
  402. package/dist/src/web-ui/local-runtime/runtime-setup-edit-transaction.js +37 -0
  403. package/dist/src/web-ui/local-runtime/runtime-setup-service.js +4 -0
  404. package/dist/src/web-ui/local-runtime-backend.js +14 -0
  405. package/dist/src/web-ui/plugin-management-catalog.d.ts +3 -1
  406. package/dist/src/web-ui/plugin-management-catalog.js +3 -1
  407. package/dist/src/web-ui/plugin-management-service.d.ts +1 -0
  408. package/dist/src/web-ui/plugin-removal-service.d.ts +1 -0
  409. package/dist/src/web-ui/server-readiness.d.ts +3 -0
  410. package/dist/src/web-ui/server-readiness.js +36 -0
  411. package/dist/src/web-ui/server.d.ts +2 -0
  412. package/dist/src/web-ui/server.js +23 -1
  413. package/dist/src/web-ui/system-host-service.js +13 -2
  414. package/dist/src/web-ui/system-host-setup/collection-consent-route.d.ts +3 -0
  415. package/dist/src/web-ui/system-host-setup/collection-consent-route.js +30 -0
  416. package/docs/installation.md +44 -5
  417. package/docs/plugins.md +174 -28
  418. package/docs/tool-execution-result-evidence-contract.md +57 -0
  419. package/docs/windows-companion-store.md +5 -0
  420. package/package.json +4 -2
  421. package/plugins/capability-brief/plugin.json +5 -1
  422. package/plugins/code-outline/README.md +20 -0
  423. package/plugins/code-outline/plugin.json +2 -1
  424. package/plugins/code-outline/source/index.ts +16 -20
  425. package/plugins/code-outline/source/read-failure.ts +40 -0
  426. package/plugins/code-outline/src/index.cjs +614 -29
  427. package/plugins/document-reader/README.md +33 -0
  428. package/plugins/document-reader/plugin.json +2 -1
  429. package/plugins/document-reader/source/pdf-contract.ts +57 -0
  430. package/plugins/document-reader/source/pdf-parser.ts +139 -0
  431. package/plugins/document-reader/source/pdf-process-main.ts +56 -0
  432. package/plugins/document-reader/source/pdf-process.ts +207 -0
  433. package/plugins/document-reader/source/pdf-result.ts +79 -0
  434. package/plugins/document-reader/source/pdf-worker.ts +39 -303
  435. package/plugins/document-reader/source/pdf.ts +4 -1
  436. package/plugins/document-reader/source/read-failure.ts +37 -0
  437. package/plugins/document-reader/source/reader.ts +3 -19
  438. package/plugins/document-reader/src/index.cjs +995 -211
  439. package/plugins/exec/README.md +19 -0
  440. package/plugins/exec/plugin.json +4 -3
  441. package/plugins/exec/skills/exec_skill/SKILL.md +3 -2
  442. package/plugins/exec/source/filesystem-file-observer.ts +98 -0
  443. package/plugins/exec/source/filesystem-observer.ts +8 -79
  444. package/plugins/exec/source/output-files.ts +12 -6
  445. package/plugins/exec/source/paths.ts +3 -1
  446. package/plugins/exec/source/process-manager.ts +8 -24
  447. package/plugins/exec/source/shell-platform.ts +19 -3
  448. package/plugins/exec/source/shell-process.ts +55 -0
  449. package/plugins/exec/source/windows-job-source.ts +1 -0
  450. package/plugins/exec/source/windows-shell-bootstrap.ts +20 -0
  451. package/plugins/exec/src/index.cjs +252 -96
  452. package/plugins/filesystem/README.md +65 -0
  453. package/plugins/filesystem/plugin.json +7 -3
  454. package/plugins/filesystem/source/atomic-write.ts +2 -0
  455. package/plugins/filesystem/source/bounded-io.ts +80 -306
  456. package/plugins/filesystem/source/directory-sample.ts +2 -0
  457. package/plugins/filesystem/source/errors.ts +14 -0
  458. package/plugins/filesystem/source/file-observation.ts +151 -0
  459. package/plugins/filesystem/source/file-version.ts +41 -0
  460. package/plugins/filesystem/source/index.ts +6 -0
  461. package/plugins/filesystem/source/mutation-coordinator.ts +1 -0
  462. package/plugins/filesystem/source/windows/authority-script.ts +1 -0
  463. package/plugins/filesystem/source/windows/native-script.ts +1 -0
  464. package/plugins/filesystem/source/windows/operations.ts +197 -0
  465. package/plugins/filesystem/source/windows/process.ts +214 -0
  466. package/plugins/filesystem/source/windows/publication-script.ts +29 -0
  467. package/plugins/filesystem/source/windows/read-script.ts +63 -0
  468. package/plugins/filesystem/source/windows/request-availability.ts +67 -0
  469. package/plugins/filesystem/source/windows/source.ts +42 -0
  470. package/plugins/filesystem/source/windows/storage-script.ts +11 -0
  471. package/plugins/filesystem/source/windows/streams-script.ts +24 -0
  472. package/plugins/filesystem/source/windows/write-script.ts +86 -0
  473. package/plugins/filesystem/src/index.cjs +1208 -322
  474. package/plugins/json-inspector/README.md +18 -0
  475. package/plugins/json-inspector/plugin.json +2 -1
  476. package/plugins/json-inspector/source/index.ts +16 -19
  477. package/plugins/json-inspector/source/read-failure.ts +42 -0
  478. package/plugins/json-inspector/src/index.cjs +612 -27
  479. package/plugins/local-search/README.md +29 -0
  480. package/plugins/local-search/plugin.json +2 -1
  481. package/plugins/local-search/source/errors.ts +2 -0
  482. package/plugins/local-search/source/paths.ts +3 -0
  483. package/plugins/local-search/source/ripgrep-process.ts +31 -5
  484. package/plugins/local-search/source/ripgrep.ts +3 -3
  485. package/plugins/local-search/source/windows-authority.ts +99 -0
  486. package/plugins/local-search/source/windows-search-lease.ts +49 -0
  487. package/plugins/local-search/source/windows-search-process.ts +91 -0
  488. package/plugins/local-search/source/windows-search-script.ts +52 -0
  489. package/plugins/local-search/src/index.cjs +595 -26
  490. package/plugins/memory/plugin.json +5 -1
  491. package/plugins/memory/source/lock-directory-claim.ts +56 -0
  492. package/plugins/memory/source/lock-owner-file.ts +71 -0
  493. package/plugins/memory/source/lock-path-observation.ts +26 -0
  494. package/plugins/memory/source/prepared-memory-replacement.ts +40 -0
  495. package/plugins/memory/source/store-lock.ts +12 -7
  496. package/plugins/memory/source/store.ts +3 -2
  497. package/plugins/memory/src/index.cjs +174 -25
  498. package/plugins/project-orientation/README.md +23 -0
  499. package/plugins/project-orientation/plugin.json +2 -1
  500. package/plugins/project-orientation/source/index.ts +12 -9
  501. package/plugins/project-orientation/source/inspection-failure.ts +70 -0
  502. package/plugins/project-orientation/source/manifest-summary.ts +9 -2
  503. package/plugins/project-orientation/source/tree.ts +6 -0
  504. package/plugins/project-orientation/src/index.cjs +647 -31
  505. package/plugins/system/README.md +51 -15
  506. package/plugins/system/plugin.json +6 -2
  507. package/plugins/system/skills/system_actions/SKILL.md +1 -1
  508. package/plugins/system/source/command-working-directory.ts +47 -0
  509. package/plugins/system/source/computer/handlers.ts +13 -9
  510. package/plugins/system/source/computer/observation-result.ts +10 -5
  511. package/plugins/system/source/computer/request-computers.ts +10 -3
  512. package/plugins/system/source/computer/request-modules.ts +3 -6
  513. package/plugins/system/source/computer/runtime-platform.ts +18 -0
  514. package/plugins/system/source/host-dispatch.ts +18 -2
  515. package/plugins/system/source/index.ts +5 -3
  516. package/plugins/system/source/local-command-output-retention.ts +16 -0
  517. package/plugins/system/source/local-command-output.ts +16 -8
  518. package/plugins/system/source/request-system-modules.ts +12 -2
  519. package/plugins/system/source/request-target-snapshot.ts +2 -1
  520. package/plugins/system/source/security/desktop-result.ts +177 -0
  521. package/plugins/system/source/security/observed-error.ts +10 -0
  522. package/plugins/system/source/security/secret-text.ts +118 -0
  523. package/plugins/system/source/security/system-results.ts +62 -0
  524. package/plugins/system/source/security/windows-output-directory.ts +82 -0
  525. package/plugins/system/src/index.cjs +837 -151
  526. package/plugins/system-probe/plugin.json +9 -3
  527. package/plugins/system-probe/source/disk-path.ts +8 -0
  528. package/plugins/system-probe/source/index.ts +10 -5
  529. package/plugins/system-probe/source/machine-load.ts +33 -0
  530. package/plugins/system-probe/source/metrics.ts +6 -8
  531. package/plugins/system-probe/src/index.cjs +49 -16
  532. package/plugins/web/plugin.json +5 -1
@@ -252,6 +252,9 @@ function canHandOffContextText(original, assessed, budget) {
252
252
  // src/capabilities/tool-media.ts
253
253
  var TOOL_IMAGE_MAX_BYTES = 10 * 1024 * 1024;
254
254
 
255
+ // src/computer-access/companion/secret-protection-protocol.ts
256
+ var HOST_SECRET_PROTECTION_CAPABILITY = "host_secret_protection_v1";
257
+
255
258
  // src/computer-access/companion/broker-client.ts
256
259
  var import_node_net = require("node:net");
257
260
 
@@ -270,25 +273,25 @@ function hostStateDirectory(rootDir) {
270
273
  }
271
274
  function ensureHostStateDirectory(directory) {
272
275
  (0, import_node_fs.mkdirSync)(directory, { recursive: true, mode: 448 });
273
- const stat4 = (0, import_node_fs.lstatSync)(directory);
274
- if (!stat4.isDirectory()) throw new Error("host_state_directory_invalid");
276
+ const stat3 = (0, import_node_fs.lstatSync)(directory);
277
+ if (!stat3.isDirectory()) throw new Error("host_state_directory_invalid");
275
278
  if (process.platform === "win32") return;
276
- if (stat4.uid !== process.getuid?.())
279
+ if (stat3.uid !== process.getuid?.())
277
280
  throw new Error("host_state_owner_invalid");
278
- if ((stat4.mode & 63) !== 0)
281
+ if ((stat3.mode & 63) !== 0)
279
282
  throw new Error("host_state_directory_not_private");
280
283
  }
281
284
  function readHostPrivateJson(path) {
282
285
  try {
283
- const stat4 = (0, import_node_fs.lstatSync)(path);
284
- if (!stat4.isFile()) throw new Error("host_state_file_invalid");
286
+ const stat3 = (0, import_node_fs.lstatSync)(path);
287
+ if (!stat3.isFile()) throw new Error("host_state_file_invalid");
285
288
  if (process.platform !== "win32") {
286
- if (stat4.uid !== process.getuid?.())
289
+ if (stat3.uid !== process.getuid?.())
287
290
  throw new Error("host_state_owner_invalid");
288
- if ((stat4.mode & 63) !== 0)
291
+ if ((stat3.mode & 63) !== 0)
289
292
  throw new Error("host_state_file_not_private");
290
293
  }
291
- if (stat4.size > 16384) throw new Error("host_state_file_too_large");
294
+ if (stat3.size > 16384) throw new Error("host_state_file_too_large");
292
295
  return JSON.parse((0, import_node_fs.readFileSync)(path, "utf8"));
293
296
  } catch (error) {
294
297
  if (error.code === "ENOENT") return void 0;
@@ -2139,7 +2142,7 @@ function createUnixNativeProcess(options) {
2139
2142
  let failedReason;
2140
2143
  let buffer = Buffer.alloc(0);
2141
2144
  let queue = Promise.resolve();
2142
- let lastResult;
2145
+ let lastDesktop;
2143
2146
  function interruptedResult(reason) {
2144
2147
  const dispatch = pending?.request.operation === "act" ? pending.dispatch ?? {
2145
2148
  status: "unknown",
@@ -2147,12 +2150,8 @@ function createUnixNativeProcess(options) {
2147
2150
  reason
2148
2151
  } : void 0;
2149
2152
  const result = unavailableUnixDesktop(options.platform, reason, dispatch);
2150
- if (!lastResult) return result;
2151
- return {
2152
- ...result,
2153
- desktop: { ...lastResult.desktop, available: false, reason },
2154
- windows: lastResult.windows
2155
- };
2153
+ if (!lastDesktop) return result;
2154
+ return { ...result, desktop: { ...result.desktop, ...lastDesktop } };
2156
2155
  }
2157
2156
  function terminate(reason) {
2158
2157
  failedReason = reason;
@@ -2165,6 +2164,7 @@ function createUnixNativeProcess(options) {
2165
2164
  retiring.once("exit", () => clearTimeout(hardStop));
2166
2165
  }
2167
2166
  child = void 0;
2167
+ buffer.fill(0);
2168
2168
  buffer = Buffer.alloc(0);
2169
2169
  }
2170
2170
  function receiveLine(line) {
@@ -2180,7 +2180,17 @@ function createUnixNativeProcess(options) {
2180
2180
  }
2181
2181
  if (message.type !== "result") throw new Error("native_protocol_invalid");
2182
2182
  const result = readUnixNativeResult(message.result, options.platform);
2183
- lastResult = result;
2183
+ lastDesktop = {
2184
+ binding: result.desktop.binding,
2185
+ bounds: {
2186
+ x: result.desktop.bounds.x,
2187
+ y: result.desktop.bounds.y,
2188
+ width: result.desktop.bounds.width,
2189
+ height: result.desktop.bounds.height
2190
+ },
2191
+ coordinateSpace: result.desktop.coordinateSpace,
2192
+ targetingGuarantee: result.desktop.targetingGuarantee
2193
+ };
2184
2194
  pending.finish(result);
2185
2195
  }
2186
2196
  function ensureHelper() {
@@ -2193,15 +2203,19 @@ function createUnixNativeProcess(options) {
2193
2203
  child.stderr.resume();
2194
2204
  child.stdout.on("data", (chunk) => {
2195
2205
  if (closed || failedReason) return;
2196
- buffer = Buffer.concat([buffer, chunk]);
2206
+ const previous = buffer;
2207
+ buffer = Buffer.concat([previous, chunk]);
2208
+ previous.fill(0);
2197
2209
  if (buffer.length > NATIVE_JSON_LIMIT) {
2198
2210
  terminate("computer_native_result_limit");
2199
2211
  return;
2200
2212
  }
2201
2213
  let boundary = buffer.indexOf(10);
2202
2214
  while (boundary >= 0) {
2203
- const line = buffer.subarray(0, boundary).toString("utf8");
2204
- buffer = buffer.subarray(boundary + 1);
2215
+ const received = buffer;
2216
+ const line = received.subarray(0, boundary).toString("utf8");
2217
+ buffer = Buffer.from(received.subarray(boundary + 1));
2218
+ received.fill(0);
2205
2219
  try {
2206
2220
  receiveLine(line);
2207
2221
  } catch {
@@ -5114,15 +5128,60 @@ function identityExcerpt(identity) {
5114
5128
  }
5115
5129
 
5116
5130
  // src/computer-access/handlers.ts
5117
- function withSystemOperationErrors(operation) {
5131
+ var PROTECTION_FAILURE = "The system result could not be protected for delivery.";
5132
+ function protectSystemResult(operation) {
5133
+ try {
5134
+ return operation();
5135
+ } catch {
5136
+ throw new SystemOperationError("system_result_protection_failed", PROTECTION_FAILURE);
5137
+ }
5138
+ }
5139
+ function failedSystemProtectionReceipt(target, result, evidenceScope) {
5140
+ const safeProcess = {
5141
+ status: result.status,
5142
+ exitCode: result.exitCode,
5143
+ outputTruncated: result.outputTruncated,
5144
+ stdout: "[UNAVAILABLE: result protection failed]",
5145
+ stderr: "[UNAVAILABLE: result protection failed]",
5146
+ ...result.spawnedProcess ? {
5147
+ spawnedProcess: {
5148
+ pid: result.spawnedProcess.pid,
5149
+ pidNamespace: result.spawnedProcess.pidNamespace,
5150
+ identitySource: result.spawnedProcess.identitySource,
5151
+ executable: "[REDACTED]"
5152
+ }
5153
+ } : {}
5154
+ };
5155
+ const receipt = systemProcessResult(target, safeProcess, evidenceScope);
5156
+ return failureResult({
5157
+ errorCode: "system_result_protection_failed",
5158
+ message: PROTECTION_FAILURE,
5159
+ output: "The operation was dispatched. Inspect the process receipt before another action; the command was not replayed.\n" + receipt.output,
5160
+ stdout: safeProcess.stdout,
5161
+ stderr: safeProcess.stderr,
5162
+ ...result.exitCode !== null ? { exitCode: result.exitCode } : {},
5163
+ data: receipt.data
5164
+ });
5165
+ }
5166
+ function withSystemOperationErrors(operation, protection) {
5118
5167
  return async (params, context) => {
5119
5168
  try {
5120
5169
  return await operation(params, context);
5121
5170
  } catch (error) {
5171
+ let message = error instanceof Error ? error.message : void 0;
5172
+ try {
5173
+ if (protection && message !== void 0)
5174
+ message = protection.protectMessage(message);
5175
+ } catch {
5176
+ return failureResult({
5177
+ errorCode: "system_result_protection_failed",
5178
+ message: PROTECTION_FAILURE
5179
+ });
5180
+ }
5122
5181
  if (error instanceof SystemOperationError)
5123
5182
  return failureResult({
5124
5183
  errorCode: error.code,
5125
- message: error.message,
5184
+ message,
5126
5185
  data: {
5127
5186
  humanActionRequired: error.code === "system_authorization_required"
5128
5187
  }
@@ -5135,9 +5194,10 @@ function withSystemOperationErrors(operation) {
5135
5194
  }
5136
5195
  };
5137
5196
  }
5138
- function createSystemHandlers(run = runSystemProcess, resolveTarget = (id) => resolveSystemTarget(id, run), commandOutput) {
5197
+ function createSystemHandlers(run = runSystemProcess, resolveTarget = (id) => resolveSystemTarget(id, run), commandOutput, protection) {
5139
5198
  const targets = async () => {
5140
- const observation = await observeSystemTargets(run);
5199
+ const observed = await observeSystemTargets(run);
5200
+ const observation = protection ? protectSystemResult(() => protection.protectTargets(observed)) : observed;
5141
5201
  return successResult({
5142
5202
  output: JSON.stringify(observation),
5143
5203
  data: {
@@ -5149,13 +5209,19 @@ function createSystemHandlers(run = runSystemProcess, resolveTarget = (id) => re
5149
5209
  const command = async (params, context) => {
5150
5210
  const target = await resolveTarget(readSystemTargetId(params.target));
5151
5211
  const output = commandOutput?.(context);
5152
- const result = await executeSystemCommand({
5212
+ const observed = await executeSystemCommand({
5153
5213
  target,
5154
5214
  params,
5155
5215
  run,
5156
5216
  ...output ? { runCommand: output.run } : {},
5157
5217
  ...context?.abortSignal ? { abortSignal: context.abortSignal } : {}
5158
5218
  });
5219
+ let result = observed;
5220
+ try {
5221
+ if (protection) result = protection.protectProcess(observed);
5222
+ } catch {
5223
+ return failedSystemProtectionReceipt(target, observed, "command_process_completion");
5224
+ }
5159
5225
  if (output) return output.present(target, result);
5160
5226
  return systemProcessResult(target, result, "command_process_completion");
5161
5227
  };
@@ -5167,7 +5233,8 @@ function createSystemHandlers(run = runSystemProcess, resolveTarget = (id) => re
5167
5233
  minimum: 1,
5168
5234
  maximum: 100
5169
5235
  });
5170
- const catalog = await readSystemApplications(target, run);
5236
+ const observed = await readSystemApplications(target, run);
5237
+ const catalog = protection ? protectSystemResult(() => protection.protectCatalog(observed)) : observed;
5171
5238
  const { output, data } = systemApplicationObservation(
5172
5239
  target,
5173
5240
  catalog,
@@ -5190,18 +5257,28 @@ function createSystemHandlers(run = runSystemProcess, resolveTarget = (id) => re
5190
5257
  run,
5191
5258
  ...context?.abortSignal ? { abortSignal: context.abortSignal } : {}
5192
5259
  });
5260
+ let process2 = result.process;
5261
+ let application = result.application;
5262
+ try {
5263
+ if (protection) {
5264
+ process2 = protection.protectProcess(result.process);
5265
+ application = protection.protectApplication(result.application);
5266
+ }
5267
+ } catch {
5268
+ return failedSystemProtectionReceipt(target, result.process, "launch_request_dispatch");
5269
+ }
5193
5270
  return systemProcessResult(
5194
5271
  target,
5195
- result.process,
5272
+ process2,
5196
5273
  "launch_request_dispatch",
5197
- result.application
5274
+ application
5198
5275
  );
5199
5276
  };
5200
5277
  return {
5201
- system_targets: withSystemOperationErrors(targets),
5202
- system_command: withSystemOperationErrors(command),
5203
- system_applications: withSystemOperationErrors(applications),
5204
- system_launch: withSystemOperationErrors(launch)
5278
+ system_targets: withSystemOperationErrors(targets, protection),
5279
+ system_command: withSystemOperationErrors(command, protection),
5280
+ system_applications: withSystemOperationErrors(applications, protection),
5281
+ system_launch: withSystemOperationErrors(launch, protection)
5205
5282
  };
5206
5283
  }
5207
5284
 
@@ -5209,19 +5286,74 @@ function createSystemHandlers(run = runSystemProcess, resolveTarget = (id) => re
5209
5286
  var import_node_crypto6 = require("node:crypto");
5210
5287
  var import_node_events = require("node:events");
5211
5288
  var import_node_fs5 = require("node:fs");
5212
- var import_promises6 = require("node:fs/promises");
5289
+ var import_promises7 = require("node:fs/promises");
5213
5290
  var import_node_path8 = require("node:path");
5214
- var import_promises7 = require("node:stream/promises");
5291
+ var import_promises8 = require("node:stream/promises");
5215
5292
 
5216
- // src/computer-access/command-output-retention.ts
5293
+ // src/computer-access/command-output-protection.ts
5217
5294
  var import_promises5 = require("node:fs/promises");
5295
+ var CapturedOutputProtectionError = class extends Error {
5296
+ constructor(reason) {
5297
+ super(reason);
5298
+ this.reason = reason;
5299
+ }
5300
+ reason;
5301
+ };
5302
+ async function protectCapturedOutput(paths, redact) {
5303
+ let stdout, stderr;
5304
+ try {
5305
+ stdout = await protectStream(paths.stdout, redact);
5306
+ stderr = await protectStream(paths.stderr, redact);
5307
+ const writes = await Promise.allSettled([
5308
+ (0, import_promises5.writeFile)(paths.stdout, stdout, { flag: "w", mode: 384, flush: true }),
5309
+ (0, import_promises5.writeFile)(paths.stderr, stderr, { flag: "w", mode: 384, flush: true })
5310
+ ]);
5311
+ if (hasRejectedOutputWrite(writes)) throw new CapturedOutputProtectionError("output_storage_failed");
5312
+ return { stdout, stderr };
5313
+ } catch (error) {
5314
+ stdout?.fill(0);
5315
+ stderr?.fill(0);
5316
+ throw error;
5317
+ }
5318
+ }
5319
+ async function protectStream(path, redact) {
5320
+ let bytes;
5321
+ try {
5322
+ bytes = await (0, import_promises5.readFile)(path);
5323
+ } catch {
5324
+ throw new CapturedOutputProtectionError("output_storage_failed");
5325
+ }
5326
+ try {
5327
+ const text = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
5328
+ const protectedText = redact(text);
5329
+ if (!isProtectedOutputText(protectedText)) throw new Error("output_protection_failed");
5330
+ return Buffer.from(protectedText, "utf8");
5331
+ } catch {
5332
+ throw new CapturedOutputProtectionError("output_protection_failed");
5333
+ } finally {
5334
+ bytes.fill(0);
5335
+ }
5336
+ }
5337
+ async function discardCapturedOutput(paths) {
5338
+ const removed = await Promise.allSettled(Object.values(paths).map((path) => (0, import_promises5.rm)(path, { force: true })));
5339
+ return removed.every((entry) => entry.status === "fulfilled");
5340
+ }
5341
+ function isProtectedOutputText(value) {
5342
+ return typeof value === "string";
5343
+ }
5344
+ function hasRejectedOutputWrite(writes) {
5345
+ return writes.some((entry) => entry.status === "rejected");
5346
+ }
5347
+
5348
+ // src/computer-access/command-output-retention.ts
5349
+ var import_promises6 = require("node:fs/promises");
5218
5350
  var import_node_path7 = require("node:path");
5219
5351
  var DEFAULT_SYSTEM_OUTPUT_RETENTION_MS = 7 * 24 * 60 * 6e4;
5220
5352
  var activeSystemCaptures = /* @__PURE__ */ new Set();
5221
5353
  var jobs = /* @__PURE__ */ new Map();
5222
5354
  var CAPTURE_ID = /^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/;
5223
5355
  async function cleanupSystemOutput(root, retentionMs) {
5224
- const entries = await (0, import_promises5.readdir)(root, { withFileTypes: true }).catch((error) => {
5356
+ const entries = await (0, import_promises6.readdir)(root, { withFileTypes: true }).catch((error) => {
5225
5357
  if (error.code === "ENOENT") return [];
5226
5358
  throw error;
5227
5359
  });
@@ -5230,13 +5362,13 @@ async function cleanupSystemOutput(root, retentionMs) {
5230
5362
  if (!entry.isDirectory() || !CAPTURE_ID.test(entry.name)) continue;
5231
5363
  const directory = (0, import_node_path7.join)(root, entry.name);
5232
5364
  if (activeSystemCaptures.has(directory)) continue;
5233
- const files = await (0, import_promises5.readdir)(directory);
5234
- const times = await Promise.all(files.map(async (file) => (await (0, import_promises5.stat)((0, import_node_path7.join)(directory, file))).mtimeMs));
5235
- const completedAt = Math.max((await (0, import_promises5.stat)(directory)).mtimeMs, ...times);
5365
+ const files = await (0, import_promises6.readdir)(directory);
5366
+ const times = await Promise.all(files.map(async (file) => (await (0, import_promises6.stat)((0, import_node_path7.join)(directory, file))).mtimeMs));
5367
+ const completedAt = Math.max((await (0, import_promises6.stat)(directory)).mtimeMs, ...times);
5236
5368
  const captureRetentionMs = await readCaptureRetention(directory, entry.name, retentionMs);
5237
5369
  if (Date.now() - completedAt < captureRetentionMs) continue;
5238
5370
  if (activeSystemCaptures.has(directory)) continue;
5239
- await (0, import_promises5.rm)(directory, { recursive: true });
5371
+ await (0, import_promises6.rm)(directory, { recursive: true });
5240
5372
  removed += 1;
5241
5373
  }
5242
5374
  return removed;
@@ -5244,7 +5376,7 @@ async function cleanupSystemOutput(root, retentionMs) {
5244
5376
  async function readCaptureRetention(directory, id, fallbackMs) {
5245
5377
  let receipt;
5246
5378
  try {
5247
- receipt = JSON.parse(await (0, import_promises5.readFile)((0, import_node_path7.join)(directory, "receipt.json"), "utf8"));
5379
+ receipt = JSON.parse(await (0, import_promises6.readFile)((0, import_node_path7.join)(directory, "receipt.json"), "utf8"));
5248
5380
  } catch (error) {
5249
5381
  if (error.code === "ENOENT") return fallbackMs;
5250
5382
  if (error instanceof SyntaxError) return fallbackMs;
@@ -5271,7 +5403,7 @@ function scheduleSystemOutputCleanup(root, retentionMs) {
5271
5403
  let empty = false;
5272
5404
  try {
5273
5405
  await cleanupSystemOutput(root, job.retentionMs);
5274
- empty = (await (0, import_promises5.readdir)(root).catch((error) => {
5406
+ empty = (await (0, import_promises6.readdir)(root).catch((error) => {
5275
5407
  if (error.code === "ENOENT") return [];
5276
5408
  throw error;
5277
5409
  })).length === 0;
@@ -5291,30 +5423,36 @@ function scheduleSystemOutputCleanup(root, retentionMs) {
5291
5423
  }
5292
5424
 
5293
5425
  // src/computer-access/command-output-capture.ts
5426
+ var STREAMS = ["stdout", "stderr"];
5294
5427
  var OUTPUT_IO_CHUNK_BYTES = 64 * 1024;
5295
- async function createSystemOutputCapture(root, retentionMs) {
5428
+ async function createSystemOutputCapture(root, retentionMs, redact) {
5429
+ if (!hasOutputProtection(redact))
5430
+ throw new SystemOperationError("system_output_protection_failed", "Command output protection is unavailable. The command was not dispatched.");
5296
5431
  const id = (0, import_node_crypto6.randomUUID)();
5297
5432
  const directory = (0, import_node_path8.join)(root, id);
5298
5433
  activeSystemCaptures.add(directory);
5299
5434
  try {
5300
- await (0, import_promises6.mkdir)(directory, { recursive: true, mode: 448 });
5435
+ await (0, import_promises7.mkdir)(directory, { recursive: true, mode: 448 });
5301
5436
  } catch {
5302
5437
  activeSystemCaptures.delete(directory);
5303
5438
  throw new SystemOperationError("system_output_storage_failed", "Output storage could not be prepared. The command was not dispatched.");
5304
5439
  }
5305
- let failure;
5440
+ let storageFailure, securityFailure;
5306
5441
  let stop;
5307
- let ended = false;
5308
- let retained = false;
5442
+ let ended = false, retained = false, admitted = false;
5443
+ let receipt;
5444
+ let processResult;
5445
+ let finishing;
5309
5446
  const sources = [];
5310
- const streams = ["stdout", "stderr"].map((name) => {
5311
- const path = (0, import_node_path8.join)(directory, name + ".bytes");
5312
- const sink = (0, import_node_fs5.createWriteStream)(path, { flags: "wx", mode: 384, highWaterMark: OUTPUT_IO_CHUNK_BYTES, flush: true });
5313
- const completion = (0, import_promises7.finished)(sink).catch(() => {
5314
- failure ??= "write_failed";
5447
+ const completeStreams = /* @__PURE__ */ new Set();
5448
+ const paths = { stdout: (0, import_node_path8.join)(directory, "stdout.bytes"), stderr: (0, import_node_path8.join)(directory, "stderr.bytes") };
5449
+ const streams = STREAMS.map((name) => {
5450
+ const sink = (0, import_node_fs5.createWriteStream)(paths[name], { flags: "wx", mode: 384, highWaterMark: OUTPUT_IO_CHUNK_BYTES, flush: true });
5451
+ const completion = (0, import_promises8.finished)(sink).catch(() => {
5452
+ storageFailure ??= "write_failed";
5315
5453
  stop?.();
5316
5454
  });
5317
- return { name, path, sink, completion, hash: (0, import_node_crypto6.createHash)("sha256") };
5455
+ return { sink, completion };
5318
5456
  });
5319
5457
  try {
5320
5458
  await Promise.all(streams.map(({ sink }) => (0, import_node_events.once)(sink, "open")));
@@ -5326,19 +5464,30 @@ async function createSystemOutputCapture(root, retentionMs) {
5326
5464
  throw new SystemOperationError("system_output_storage_failed", "Output files could not be opened. The command was not dispatched.");
5327
5465
  }
5328
5466
  scheduleSystemOutputCleanup(root, retentionMs);
5467
+ const failure = () => storageFailure ?? securityFailure;
5329
5468
  const capture = {
5330
5469
  attach(stdout, stderr, onFailure) {
5470
+ if (!canAttachCapture()) {
5471
+ securityFailure ??= "output_protection_failed";
5472
+ onFailure();
5473
+ return;
5474
+ }
5331
5475
  stop = onFailure;
5332
5476
  sources.push(stdout, stderr);
5333
- stdout.on("data", (bytes) => streams[0].hash.update(bytes));
5334
- stderr.on("data", (bytes) => streams[1].hash.update(bytes));
5335
- stdout.pipe(streams[0].sink);
5336
- stderr.pipe(streams[1].sink);
5337
- if (failure) onFailure();
5477
+ for (const [index, source] of sources.entries()) {
5478
+ source.once("end", () => completeStreams.add(STREAMS[index]));
5479
+ source.once("error", () => {
5480
+ securityFailure ??= "output_incomplete";
5481
+ stop?.();
5482
+ });
5483
+ source.pipe(streams[index].sink);
5484
+ }
5485
+ if (failure()) onFailure();
5338
5486
  },
5339
5487
  end() {
5340
5488
  if (ended) return;
5341
5489
  ended = true;
5490
+ if (!hasCompleteStreams()) securityFailure ??= "output_incomplete";
5342
5491
  for (const source of sources) {
5343
5492
  source.unpipe();
5344
5493
  source.destroy();
@@ -5346,14 +5495,105 @@ async function createSystemOutputCapture(root, retentionMs) {
5346
5495
  for (const { sink } of streams) if (!sink.destroyed && !sink.writableEnded) sink.end();
5347
5496
  }
5348
5497
  };
5349
- let receipt;
5498
+ function canAttachCapture() {
5499
+ return sources.length === 0 && !ended;
5500
+ }
5501
+ function hasCompleteStreams() {
5502
+ return completeStreams.size === 2;
5503
+ }
5504
+ function protectProcess2(result) {
5505
+ if (!result) return;
5506
+ let spawnedProcess = result.spawnedProcess;
5507
+ if (spawnedProcess) {
5508
+ let executable = "[REDACTED]";
5509
+ try {
5510
+ executable = redact(spawnedProcess.executable);
5511
+ if (!hasProtectedIdentity(executable)) throw new Error("output_protection_failed");
5512
+ } catch {
5513
+ securityFailure ??= "output_protection_failed";
5514
+ executable = "[REDACTED]";
5515
+ }
5516
+ spawnedProcess = { ...spawnedProcess, executable };
5517
+ }
5518
+ processResult = {
5519
+ exitCode: result.exitCode,
5520
+ status: result.status,
5521
+ outputTruncated: result.outputTruncated,
5522
+ stdout: "",
5523
+ stderr: "",
5524
+ ...spawnedProcess ? { spawnedProcess } : {}
5525
+ };
5526
+ }
5527
+ async function finish(result, materialize = true) {
5528
+ capture.end();
5529
+ await Promise.all(streams.map(({ completion }) => completion));
5530
+ protectProcess2(result);
5531
+ let protectedBytes;
5532
+ try {
5533
+ if (!failure()) {
5534
+ try {
5535
+ protectedBytes = await protectCapturedOutput(paths, redact);
5536
+ } catch (error) {
5537
+ if (isOutputStorageFailure(error)) storageFailure ??= "write_failed";
5538
+ else securityFailure ??= "output_protection_failed";
5539
+ }
5540
+ }
5541
+ if (failure() && !await discardCapturedOutput(paths)) storageFailure = "capture_purge_failed";
5542
+ receipt = {
5543
+ id,
5544
+ stdoutBytes: protectedBytes?.stdout.length ?? 0,
5545
+ stderrBytes: protectedBytes?.stderr.length ?? 0,
5546
+ completedAt: (/* @__PURE__ */ new Date()).toISOString(),
5547
+ retentionMs,
5548
+ complete: !failure(),
5549
+ ...!materialize && protectedBytes ? {
5550
+ stdoutSha256: (0, import_node_crypto6.createHash)("sha256").update(protectedBytes.stdout).digest("hex"),
5551
+ stderrSha256: (0, import_node_crypto6.createHash)("sha256").update(protectedBytes.stderr).digest("hex")
5552
+ } : {}
5553
+ };
5554
+ try {
5555
+ const temporary = (0, import_node_path8.join)(directory, "receipt.tmp");
5556
+ await (0, import_promises7.writeFile)(
5557
+ temporary,
5558
+ JSON.stringify({
5559
+ kind: "system_command_output_v1",
5560
+ ...receipt,
5561
+ processStatus: processResult?.status,
5562
+ exitCode: processResult?.exitCode,
5563
+ spawnedProcess: processResult?.spawnedProcess,
5564
+ ...securityFailure ? { securityFailure } : {},
5565
+ ...storageFailure ? { storageFailure } : {}
5566
+ }),
5567
+ { flag: "wx", mode: 384, flush: true }
5568
+ );
5569
+ await (0, import_promises7.rename)(temporary, (0, import_node_path8.join)(directory, "receipt.json"));
5570
+ } catch {
5571
+ storageFailure ??= "receipt_write_failed";
5572
+ receipt = { ...receipt, complete: false };
5573
+ }
5574
+ admitted = receipt.complete;
5575
+ if (!admitted || !materialize || !protectedBytes) return { stdout: "", stderr: "" };
5576
+ return { stdout: protectedBytes.stdout.toString("utf8"), stderr: protectedBytes.stderr.toString("utf8") };
5577
+ } finally {
5578
+ protectedBytes?.stdout.fill(0);
5579
+ protectedBytes?.stderr.fill(0);
5580
+ if (!retained) activeSystemCaptures.delete(directory);
5581
+ }
5582
+ }
5350
5583
  return {
5351
5584
  capture,
5352
5585
  get receipt() {
5353
5586
  return receipt;
5354
5587
  },
5355
5588
  get failure() {
5356
- return failure;
5589
+ return failure();
5590
+ },
5591
+ get failureKind() {
5592
+ if (storageFailure) return "storage";
5593
+ return securityFailure ? "security" : void 0;
5594
+ },
5595
+ get processResult() {
5596
+ return processResult;
5357
5597
  },
5358
5598
  retain() {
5359
5599
  retained = true;
@@ -5364,68 +5604,40 @@ async function createSystemOutputCapture(root, retentionMs) {
5364
5604
  activeSystemCaptures.delete(directory);
5365
5605
  },
5366
5606
  async read(stream, offset, length) {
5367
- const path = streams.find((entry) => entry.name === stream).path;
5368
- const file = await (0, import_promises6.open)(path, "r");
5607
+ if (!admitted) throw new Error("system_output_unavailable");
5608
+ if (!isAdmittedOutputRead(stream, offset, length, receipt)) throw new Error("system_output_reference_invalid");
5609
+ const file = await (0, import_promises7.open)(paths[stream], "r");
5369
5610
  try {
5370
- const bytes = Buffer.alloc(length);
5371
- const { bytesRead } = await file.read(bytes, 0, length, offset);
5611
+ const size = stream === "stdout" ? receipt.stdoutBytes : receipt.stderrBytes;
5612
+ const bytes = Buffer.alloc(Math.min(length, size - offset));
5613
+ const { bytesRead } = await file.read(bytes, 0, bytes.length, offset);
5372
5614
  return bytes.subarray(0, bytesRead);
5373
5615
  } finally {
5374
5616
  await file.close();
5375
5617
  }
5376
5618
  },
5377
- async finish(result, materialize = true) {
5378
- capture.end();
5379
- try {
5380
- await Promise.all(streams.map(({ completion }) => completion));
5381
- const sizes = await Promise.all(streams.map(async ({ path }) => {
5382
- try {
5383
- return (await (0, import_promises6.stat)(path)).size;
5384
- } catch {
5385
- failure ??= "read_failed";
5386
- return 0;
5387
- }
5388
- }));
5389
- let stdout = "", stderr = "";
5390
- if (!failure && materialize) {
5391
- try {
5392
- [stdout, stderr] = await Promise.all(streams.map(({ path }) => (0, import_promises6.readFile)(path, "utf8")));
5393
- } catch {
5394
- failure = "read_failed";
5395
- }
5396
- }
5397
- const completedAt = Date.now();
5398
- receipt = {
5399
- id,
5400
- stdoutBytes: sizes[0],
5401
- stderrBytes: sizes[1],
5402
- completedAt: new Date(completedAt).toISOString(),
5403
- retentionMs,
5404
- complete: !failure,
5405
- ...!materialize ? { stdoutSha256: streams[0].hash.digest("hex"), stderrSha256: streams[1].hash.digest("hex") } : {}
5406
- };
5407
- try {
5408
- const temporary = (0, import_node_path8.join)(directory, "receipt.tmp");
5409
- await (0, import_promises6.writeFile)(temporary, JSON.stringify({
5410
- kind: "system_command_output_v1",
5411
- ...receipt,
5412
- processStatus: result?.status,
5413
- exitCode: result?.exitCode,
5414
- spawnedProcess: result?.spawnedProcess,
5415
- ...failure ? { storageFailure: failure } : {}
5416
- }), { flag: "wx", mode: 384, flush: true });
5417
- await (0, import_promises6.rename)(temporary, (0, import_node_path8.join)(directory, "receipt.json"));
5418
- } catch {
5419
- failure ??= "receipt_write_failed";
5420
- receipt = { ...receipt, complete: false };
5421
- }
5422
- return { stdout, stderr };
5423
- } finally {
5424
- if (!retained) activeSystemCaptures.delete(directory);
5425
- }
5619
+ finish(result, materialize = true) {
5620
+ finishing ??= finish(result, materialize);
5621
+ return finishing;
5426
5622
  }
5427
5623
  };
5428
5624
  }
5625
+ function hasOutputProtection(value) {
5626
+ return typeof value === "function";
5627
+ }
5628
+ function hasProtectedIdentity(value) {
5629
+ return typeof value === "string";
5630
+ }
5631
+ function isOutputStorageFailure(error) {
5632
+ return error instanceof CapturedOutputProtectionError && error.reason === "output_storage_failed";
5633
+ }
5634
+ function isAdmittedOutputRead(stream, offset, length, receipt) {
5635
+ if (stream !== "stdout" && stream !== "stderr") return false;
5636
+ if (!Number.isSafeInteger(offset) || offset < 0) return false;
5637
+ if (!Number.isSafeInteger(length) || length < 0) return false;
5638
+ const size = stream === "stdout" ? receipt.stdoutBytes : receipt.stderrBytes;
5639
+ return offset <= size;
5640
+ }
5429
5641
 
5430
5642
  // src/computer-access/companion/command-output-protocol.ts
5431
5643
  var SYSTEM_OUTPUT_CAPABILITY = "system_command_output_v1";
@@ -5454,6 +5666,39 @@ function readSystemOutputTransfer(value) {
5454
5666
  };
5455
5667
  }
5456
5668
 
5669
+ // plugins/system/source/command-working-directory.ts
5670
+ var import_node_path9 = require("node:path");
5671
+ function createSystemCommandPathAdapter(adapter, snapshot, resolver) {
5672
+ if (!resolver) return adapter;
5673
+ return {
5674
+ ...adapter,
5675
+ normalizeCall(input) {
5676
+ const call = adapter?.normalizeCall?.(input) ?? input;
5677
+ if (!hasNativeWindowsRelativeDirectory(call, snapshot)) return call;
5678
+ const directory = resolver.resolve(call.params.cwd, {
5679
+ requirePath: true,
5680
+ allowedLocations: ["agent_work", "workspace"]
5681
+ });
5682
+ return {
5683
+ ...call,
5684
+ params: { ...call.params, cwd: directory.absolutePath }
5685
+ };
5686
+ }
5687
+ };
5688
+ }
5689
+ function hasNativeWindowsRelativeDirectory(call, snapshot) {
5690
+ if (call.tool !== "system_command") return false;
5691
+ if (call.params.target !== "windows") return false;
5692
+ if (typeof call.params.cwd !== "string") return false;
5693
+ if (import_node_path9.win32.isAbsolute(call.params.cwd.trim())) return false;
5694
+ const route = snapshot.find((entry) => {
5695
+ if (entry.kind !== "native") return false;
5696
+ if (entry.target.id !== "windows") return false;
5697
+ return entry.target.transport === "native";
5698
+ });
5699
+ return route !== void 0;
5700
+ }
5701
+
5457
5702
  // plugins/system/source/computer/public-action.ts
5458
5703
  function readPublicComputerAction(params) {
5459
5704
  const fields = ["desktop_ref", "observation_ref", "action_kind"];
@@ -5615,6 +5860,113 @@ function fits(value) {
5615
5860
  return Buffer.byteLength(value, "utf8") <= COMPUTER_OBSERVATION_OUTPUT_MAX_BYTES;
5616
5861
  }
5617
5862
 
5863
+ // plugins/system/source/security/secret-text.ts
5864
+ var REDACTED = "[REDACTED]";
5865
+ var CREDENTIAL_KEY_SOURCE = String.raw`(?:[A-Za-z][A-Za-z0-9_-]*\.)*(?:[A-Za-z][A-Za-z0-9]*[-_])*(?:password|passwd|pwd|api[_ -]?key|access[_ -]?token|refresh[_ -]?token|client[_ -]?secret|secret[_ -]?access[_ -]?key|recovery[_ -]?code)`;
5866
+ var credentialIndicator = new RegExp(
5867
+ String.raw`(?<![\p{L}\p{N}_.-])(?:-{1,2})?(?:${CREDENTIAL_KEY_SOURCE}|(?:proxy-)?authorization)[\s"'\\]*[:=]`,
5868
+ "iu"
5869
+ );
5870
+ function detectionText(input) {
5871
+ const percentDecoded = input.replace(
5872
+ /%([0-7][0-9a-f])/giu,
5873
+ (_, hex) => String.fromCharCode(Number.parseInt(hex, 16))
5874
+ );
5875
+ return percentDecoded.replace(
5876
+ /\\(?:u00|x|U000000)([0-7][0-9a-fA-F])/gu,
5877
+ (_, hex) => String.fromCharCode(Number.parseInt(hex, 16))
5878
+ );
5879
+ }
5880
+ function hasPrivateKeyIndicator(text) {
5881
+ return /-----BEGIN (?:[A-Z0-9]+ )*PRIVATE KEY(?: BLOCK)?-----/u.test(text);
5882
+ }
5883
+ function hasUrlCredentials(text) {
5884
+ return /\b[a-z][a-z0-9+.-]*(?::|%3a)(?:\/|%2f){2}[^\s/?#<>]*(?:@|%40)/iu.test(text);
5885
+ }
5886
+ function hasAuthorizationCredentials(text) {
5887
+ for (const match of text.matchAll(
5888
+ /\b(Bearer|Basic)[ \t]+([A-Za-z0-9._~+/-]+={0,2})/giu
5889
+ )) {
5890
+ if (match[1].toLowerCase() === "bearer") return true;
5891
+ const value = match[2];
5892
+ if (!/^[A-Za-z0-9+/]+={0,2}$/u.test(value)) continue;
5893
+ if (value.length < 8) continue;
5894
+ if (Buffer.from(value, "base64").toString("utf8").includes(":")) return true;
5895
+ }
5896
+ return false;
5897
+ }
5898
+ function isAwsAccessKeyValue(value, atEnd) {
5899
+ if (/^[A-Z0-9]{16}$/u.test(value)) return true;
5900
+ if (!atEnd) return false;
5901
+ return /^[A-Z0-9]{4,15}$/u.test(value);
5902
+ }
5903
+ function isRecognizedProviderToken(prefix, value, atEnd) {
5904
+ if (prefix === "AKIA" || prefix === "ASIA")
5905
+ return isAwsAccessKeyValue(value, atEnd);
5906
+ if (value.length >= 20) return true;
5907
+ const partialMinimum = prefix === "sk-" ? 8 : 1;
5908
+ return atEnd && value.length >= partialMinimum;
5909
+ }
5910
+ function hasProviderToken(text) {
5911
+ const provider = /\b(sk-(?:proj-|svcacct-)?|gh[pousr]_|github_pat_|xox[baprs]-|AKIA|ASIA)([A-Za-z0-9_-]+)/gu;
5912
+ for (const match of text.matchAll(provider)) {
5913
+ const atEnd = match.index + match[0].length === text.length;
5914
+ if (isRecognizedProviderToken(match[1], match[2], atEnd)) return true;
5915
+ }
5916
+ return false;
5917
+ }
5918
+ function compactJoseSegmentCount(header) {
5919
+ try {
5920
+ const value = JSON.parse(
5921
+ Buffer.from(header, "base64url").toString("utf8")
5922
+ );
5923
+ if (typeof value !== "object" || value === null || Array.isArray(value))
5924
+ return void 0;
5925
+ const fields = value;
5926
+ if (typeof fields.alg !== "string") return void 0;
5927
+ return typeof fields.enc === "string" ? 5 : 3;
5928
+ } catch {
5929
+ return void 0;
5930
+ }
5931
+ }
5932
+ function hasCompactJoseToken(text) {
5933
+ const jose = /\b([A-Za-z0-9_-]+)(?:\.[A-Za-z0-9_-]*)+/gu;
5934
+ for (const match of text.matchAll(jose)) {
5935
+ const parts = match[0].split(".");
5936
+ const capturedAtEnd = match.index + match[0].length === text.length;
5937
+ for (let index = 0; index < parts.length - 1; index += 1) {
5938
+ const expected = compactJoseSegmentCount(parts[index]);
5939
+ if (expected === void 0) continue;
5940
+ if (expected === 3 && parts[index + 1] === "") continue;
5941
+ if (parts.length - index >= expected) return true;
5942
+ if (capturedAtEnd) return true;
5943
+ }
5944
+ }
5945
+ return false;
5946
+ }
5947
+ function hasSecretIndicator(text) {
5948
+ if (credentialIndicator.test(text)) return true;
5949
+ if (hasPrivateKeyIndicator(text)) return true;
5950
+ if (hasUrlCredentials(text)) return true;
5951
+ if (hasAuthorizationCredentials(text)) return true;
5952
+ if (hasProviderToken(text)) return true;
5953
+ return hasCompactJoseToken(text);
5954
+ }
5955
+ function redactSecretText(input) {
5956
+ if (hasSecretIndicator(input)) return REDACTED;
5957
+ if (hasSecretIndicator(detectionText(input))) return REDACTED;
5958
+ return input;
5959
+ }
5960
+
5961
+ // plugins/system/source/security/observed-error.ts
5962
+ function protectObservedError(error, fallback) {
5963
+ try {
5964
+ return redactSecretText(error instanceof Error ? error.message : fallback);
5965
+ } catch {
5966
+ return "Observed error details withheld because the protection check failed.";
5967
+ }
5968
+ }
5969
+
5618
5970
  // plugins/system/source/computer/request-computers.ts
5619
5971
  var import_node_crypto8 = require("node:crypto");
5620
5972
 
@@ -5704,7 +6056,7 @@ function systemRouteMetadata(route) {
5704
6056
  return {
5705
6057
  displayTarget: route.target,
5706
6058
  transport: "host_companion",
5707
- computerName: route.identity.name
6059
+ computerName: redactSecretText(route.identity.name)
5708
6060
  };
5709
6061
  }
5710
6062
  function observeCapturedSystemTargets(snapshot) {
@@ -5851,7 +6203,7 @@ var DesktopBindings = class {
5851
6203
  this.current = void 0;
5852
6204
  this.windows.clear();
5853
6205
  }
5854
- regionalObservation(observationRef, rectangle) {
6206
+ regionalObservation(observationRef, rectangle2) {
5855
6207
  const current = this.current;
5856
6208
  if (!current || current.id !== observationRef)
5857
6209
  throw new SystemOperationError(
@@ -5859,7 +6211,7 @@ var DesktopBindings = class {
5859
6211
  "Use a current observation to select a smaller region."
5860
6212
  );
5861
6213
  const observation = current.observation;
5862
- if (!isRegionInsideImage(rectangle, observation))
6214
+ if (!isRegionInsideImage(rectangle2, observation))
5863
6215
  throw new SystemOperationError(
5864
6216
  "computer_region_outside_image",
5865
6217
  "Select a region inside the returned image."
@@ -5871,10 +6223,10 @@ var DesktopBindings = class {
5871
6223
  desktopBinding: current.result.desktop.binding,
5872
6224
  expectedGeometry: current.result.desktop.bounds,
5873
6225
  region: {
5874
- x: Math.round(observation.region.x + rectangle.x * scaleX),
5875
- y: Math.round(observation.region.y + rectangle.y * scaleY),
5876
- width: Math.max(1, Math.floor(rectangle.width * scaleX)),
5877
- height: Math.max(1, Math.floor(rectangle.height * scaleY))
6226
+ x: Math.round(observation.region.x + rectangle2.x * scaleX),
6227
+ y: Math.round(observation.region.y + rectangle2.y * scaleY),
6228
+ width: Math.max(1, Math.floor(rectangle2.width * scaleX)),
6229
+ height: Math.max(1, Math.floor(rectangle2.height * scaleY))
5878
6230
  }
5879
6231
  };
5880
6232
  }
@@ -5906,10 +6258,10 @@ function imageRectangle(bounds, observation) {
5906
6258
  height: bounds.height * scaleY
5907
6259
  };
5908
6260
  }
5909
- function isRegionInsideImage(rectangle, observation) {
5910
- if (rectangle.x < 0 || rectangle.y < 0) return false;
5911
- if (rectangle.x + rectangle.width > observation.imageWidth) return false;
5912
- return rectangle.y + rectangle.height <= observation.imageHeight;
6261
+ function isRegionInsideImage(rectangle2, observation) {
6262
+ if (rectangle2.x < 0 || rectangle2.y < 0) return false;
6263
+ if (rectangle2.x + rectangle2.width > observation.imageWidth) return false;
6264
+ return rectangle2.y + rectangle2.height <= observation.imageHeight;
5913
6265
  }
5914
6266
  function translateAction(action, observation) {
5915
6267
  const point = (value) => {
@@ -5934,6 +6286,131 @@ function translateAction(action, observation) {
5934
6286
  return action;
5935
6287
  }
5936
6288
 
6289
+ // plugins/system/source/security/desktop-result.ts
6290
+ function rectangle(value) {
6291
+ return { x: value.x, y: value.y, width: value.width, height: value.height };
6292
+ }
6293
+ function projectDesktopFields(result, text) {
6294
+ const capability = (value) => ({
6295
+ supported: value.supported,
6296
+ available: value.available,
6297
+ ...value.reason === void 0 ? {} : { reason: text(value.reason) }
6298
+ });
6299
+ const desktop = result.desktop;
6300
+ return {
6301
+ desktop: {
6302
+ platform: desktop.platform,
6303
+ binding: desktop.binding,
6304
+ name: text(desktop.name),
6305
+ available: desktop.available,
6306
+ ...desktop.reason === void 0 ? {} : { reason: text(desktop.reason) },
6307
+ bounds: rectangle(desktop.bounds),
6308
+ ...desktop.coordinateSpace === void 0 ? {} : { coordinateSpace: desktop.coordinateSpace },
6309
+ capabilities: {
6310
+ capture: capability(desktop.capabilities.capture),
6311
+ accessibility: capability(desktop.capabilities.accessibility),
6312
+ input: capability(desktop.capabilities.input),
6313
+ windows: capability(desktop.capabilities.windows)
6314
+ },
6315
+ targetingGuarantee: desktop.targetingGuarantee
6316
+ },
6317
+ windows: result.windows.map((window) => ({
6318
+ binding: window.binding,
6319
+ title: text(window.title),
6320
+ ...window.application === void 0 ? {} : { application: text(window.application) },
6321
+ bounds: rectangle(window.bounds),
6322
+ focused: window.focused
6323
+ })),
6324
+ ...result.focusedWindow === void 0 ? {} : { focusedWindow: result.focusedWindow },
6325
+ ...result.observation ? {
6326
+ observation: {
6327
+ capturedAt: text(result.observation.capturedAt),
6328
+ region: rectangle(result.observation.region),
6329
+ imageWidth: result.observation.imageWidth,
6330
+ imageHeight: result.observation.imageHeight,
6331
+ accessibility: result.observation.accessibility.map((node) => ({
6332
+ role: text(node.role),
6333
+ ...node.name === void 0 ? {} : { name: text(node.name) },
6334
+ ...node.value === void 0 ? {} : { value: text(node.value) },
6335
+ ...node.bounds === void 0 ? {} : { bounds: rectangle(node.bounds) },
6336
+ ...node.focused === void 0 ? {} : { focused: node.focused }
6337
+ })),
6338
+ accessibilityTruncated: result.observation.accessibilityTruncated
6339
+ }
6340
+ } : {},
6341
+ ...result.dispatch ? {
6342
+ dispatch: {
6343
+ status: result.dispatch.status,
6344
+ requestedInputCount: result.dispatch.requestedInputCount,
6345
+ ...result.dispatch.acceptedInputCount === void 0 ? {} : { acceptedInputCount: result.dispatch.acceptedInputCount },
6346
+ ...result.dispatch.reason === void 0 ? {} : { reason: text(result.dispatch.reason) }
6347
+ }
6348
+ } : {},
6349
+ ...result.error ? {
6350
+ error: {
6351
+ code: text(result.error.code),
6352
+ message: text(result.error.message)
6353
+ }
6354
+ } : {}
6355
+ };
6356
+ }
6357
+ function protectDesktopResult(result, scan = redactSecretText) {
6358
+ let suspected = false;
6359
+ try {
6360
+ const protectedResult = projectDesktopFields(result, (input) => {
6361
+ const output = scan(input);
6362
+ if (typeof output !== "string")
6363
+ throw new Error("desktop_text_scan_failed");
6364
+ suspected ||= output !== input;
6365
+ return output;
6366
+ });
6367
+ if (!suspected)
6368
+ return {
6369
+ ...protectedResult,
6370
+ ...result.image ? {
6371
+ image: {
6372
+ mimeType: result.image.mimeType,
6373
+ bytes: result.image.bytes
6374
+ }
6375
+ } : {}
6376
+ };
6377
+ result.image?.bytes.fill(0);
6378
+ return {
6379
+ ...protectedResult,
6380
+ ...result.image && !protectedResult.error ? {
6381
+ error: {
6382
+ code: "computer_image_secret_blocked",
6383
+ message: "Image withheld because desktop text contained a suspected secret. The dispatch receipt is unchanged."
6384
+ }
6385
+ } : {}
6386
+ };
6387
+ } catch {
6388
+ result.image?.bytes.fill(0);
6389
+ const safe = projectDesktopFields(result, () => "[REDACTED]");
6390
+ return {
6391
+ desktop: {
6392
+ ...safe.desktop,
6393
+ reason: "Desktop content withheld because its protection check failed."
6394
+ },
6395
+ windows: [],
6396
+ ...safe.focusedWindow === void 0 ? {} : { focusedWindow: safe.focusedWindow },
6397
+ ...safe.dispatch ? { dispatch: safe.dispatch } : {},
6398
+ error: {
6399
+ code: "computer_observation_protection_failed",
6400
+ message: "Desktop content withheld because its protection check failed. The dispatch receipt is unchanged."
6401
+ }
6402
+ };
6403
+ }
6404
+ }
6405
+ function protectNativeDesktopBackend(backend) {
6406
+ return {
6407
+ async execute(request, signal) {
6408
+ return protectDesktopResult(await backend.execute(request, signal));
6409
+ },
6410
+ close: () => backend.close()
6411
+ };
6412
+ }
6413
+
5937
6414
  // plugins/system/source/computer/request-computers.ts
5938
6415
  var RequestComputers = class {
5939
6416
  constructor(rootDir, routes, connection, nativeFactory = createNativeComputerBackend, snapshot) {
@@ -5988,7 +6465,7 @@ var RequestComputers = class {
5988
6465
  "Install the companion from this Runtime build to enable desktop observation and input."
5989
6466
  );
5990
6467
  if (entry.backend) return entry.backend;
5991
- entry.backend = entry.route.kind === "native" ? this.nativeFactory(entry.route.target) : createCompanionComputerBackend(
6468
+ entry.backend = entry.route.kind === "native" ? protectNativeDesktopBackend(this.nativeFactory(entry.route.target)) : createCompanionComputerBackend(
5992
6469
  this.rootDir,
5993
6470
  entry.route,
5994
6471
  this.connection
@@ -6015,7 +6492,7 @@ function computerQueueIdentity(entry) {
6015
6492
  }
6016
6493
  function supportsComputerRoute(route) {
6017
6494
  if (route.kind === "native") return true;
6018
- return route.capabilities?.includes(COMPUTER_CAPABILITY) === true;
6495
+ return route.capabilities?.includes(COMPUTER_CAPABILITY) === true && route.capabilities.includes(HOST_SECRET_PROTECTION_CAPABILITY);
6019
6496
  }
6020
6497
  function restoreComputers(routes, value) {
6021
6498
  if (!value || typeof value !== "object" || !("kind" in value) || value.kind !== "request_computers_v1" || !("entries" in value) || !Array.isArray(value.entries))
@@ -6064,7 +6541,7 @@ async function projectComputerResult(entry, result, context) {
6064
6541
  );
6065
6542
  media.push(image);
6066
6543
  } catch (error) {
6067
- imageFailure = error instanceof Error ? error.message : "Image admission failed.";
6544
+ imageFailure = protectObservedError(error, "Image admission failed.");
6068
6545
  } finally {
6069
6546
  result.image.bytes.fill(0);
6070
6547
  }
@@ -6075,7 +6552,10 @@ async function projectComputerResult(entry, result, context) {
6075
6552
  description.observation_ref = void 0;
6076
6553
  }
6077
6554
  const hasPartialInputDispatch = result.dispatch?.status === "partial";
6078
- const operationError = result.error ?? (hasPartialInputDispatch ? { code: "computer_input_partial", message: "Only part of the input was accepted." } : void 0);
6555
+ const operationError = result.error ?? (hasPartialInputDispatch ? {
6556
+ code: "computer_input_partial",
6557
+ message: "Only part of the input was accepted."
6558
+ } : void 0);
6079
6559
  const data = {
6080
6560
  desktop_ref: entry.ref,
6081
6561
  ...description.observation_ref ? { observation_ref: description.observation_ref } : {},
@@ -6154,7 +6634,10 @@ function createComputerHandlers(computers) {
6154
6634
  } catch (error) {
6155
6635
  return failureResult({
6156
6636
  errorCode: error instanceof SystemOperationError ? error.code : "computer_operation_interrupted",
6157
- message: error instanceof Error ? error.message : "Computer operation interrupted; effects may be partial. Observe before another action."
6637
+ message: protectObservedError(
6638
+ error,
6639
+ "Computer operation interrupted; effects may be partial. Observe before another action."
6640
+ )
6158
6641
  });
6159
6642
  }
6160
6643
  };
@@ -6175,7 +6658,10 @@ function createComputerHandlers(computers) {
6175
6658
  return {
6176
6659
  ...computerRouteLabel(entry),
6177
6660
  available: false,
6178
- reason: error instanceof Error ? error.message : "Desktop inspection failed."
6661
+ reason: protectObservedError(
6662
+ error,
6663
+ "Desktop inspection failed."
6664
+ )
6179
6665
  };
6180
6666
  }
6181
6667
  }
@@ -6244,20 +6730,34 @@ function requireMedia(context) {
6244
6730
  );
6245
6731
  }
6246
6732
 
6733
+ // plugins/system/source/computer/runtime-platform.ts
6734
+ function supportsRuntimeDesktopTools(platform = process.platform) {
6735
+ return platform !== "win32";
6736
+ }
6737
+ function unboundComputerFailure() {
6738
+ if (!supportsRuntimeDesktopTools())
6739
+ return failureResult({
6740
+ errorCode: "computer_runtime_platform_unsupported",
6741
+ message: "Desktop observation and control are unavailable on Windows Runtime. System commands and applications remain available."
6742
+ });
6743
+ return failureResult({
6744
+ errorCode: "computer_request_binding_required",
6745
+ message: "Computer control requires a prepared request."
6746
+ });
6747
+ }
6748
+
6247
6749
  // plugins/system/source/computer/request-modules.ts
6248
6750
  function unboundComputerHandlers() {
6249
6751
  return Object.fromEntries(
6250
6752
  COMPUTER_TOOLS.map((name) => [
6251
6753
  name,
6252
- async () => failureResult({
6253
- errorCode: "computer_request_binding_required",
6254
- message: "Computer control requires a prepared request."
6255
- })
6754
+ async () => unboundComputerFailure()
6256
6755
  ])
6257
6756
  );
6258
6757
  }
6259
6758
  function prepareComputerModules(rootDir, modules, routes, connection, preparation) {
6260
6759
  if (modules.length === 0) return [];
6760
+ if (!supportsRuntimeDesktopTools()) return [];
6261
6761
  const computers = new RequestComputers(
6262
6762
  rootDir,
6263
6763
  routes,
@@ -6415,7 +6915,17 @@ function boundOperation(input, operation) {
6415
6915
  const route = requireSystemRequestRoute(input.snapshot, params.target);
6416
6916
  if (route.kind === "native")
6417
6917
  return await input.nativeHandlers[operation](params, context);
6418
- if (operation === "system_command" && supportsCompanionCommandOutput(route))
6918
+ if (!supportsProtectedCompanionResults(route.capabilities))
6919
+ return failureResult({
6920
+ errorCode: "system_companion_protection_upgrade_required",
6921
+ message: "Update Companion to enable protected system results. The operation was not dispatched."
6922
+ });
6923
+ if (operation === "system_command" && !supportsCompanionCommandOutput(route))
6924
+ return failureResult({
6925
+ errorCode: "system_companion_protection_upgrade_required",
6926
+ message: "Update Companion to enable protected complete command output. The command was not dispatched."
6927
+ });
6928
+ if (operation === "system_command")
6419
6929
  return await executeCompanionCommand({ ...input, route, params, context });
6420
6930
  return await input.connection.executeHostOperation(input.rootDir, {
6421
6931
  hostId: route.hostId,
@@ -6426,7 +6936,7 @@ function boundOperation(input, operation) {
6426
6936
  });
6427
6937
  } catch (error) {
6428
6938
  if (error instanceof SystemOperationError)
6429
- return failureResult({ errorCode: error.code, message: error.message });
6939
+ return failureResult({ errorCode: error.code, message: redactSecretText(error.message) });
6430
6940
  return failureResult({
6431
6941
  errorCode: "system_execution_route_failed",
6432
6942
  message: "The bound execution route failed. No other destination was attempted; effects may be partial if dispatch began."
@@ -6434,6 +6944,9 @@ function boundOperation(input, operation) {
6434
6944
  }
6435
6945
  };
6436
6946
  }
6947
+ function supportsProtectedCompanionResults(capabilities) {
6948
+ return capabilities?.includes(HOST_SECRET_PROTECTION_CAPABILITY) === true;
6949
+ }
6437
6950
  function hasConnectionControl(params) {
6438
6951
  if (Object.hasOwn(params, "host_id")) return true;
6439
6952
  if (Object.hasOwn(params, "hostId")) return true;
@@ -6473,7 +6986,14 @@ async function prepareSystemRequestModules(rootDir, modules, dependencies = {},
6473
6986
  outputRetentionMs: dependencies.outputRetentionMs
6474
6987
  });
6475
6988
  return Object.freeze([
6476
- ...modules.filter((module2) => !isComputerTool(module2.definition.name)).map((module2) => projectSystemRequestModule(module2, snapshot, handlers)),
6989
+ ...modules.filter((module2) => !isComputerTool(module2.definition.name)).map(
6990
+ (module2) => projectSystemRequestModule(
6991
+ module2,
6992
+ snapshot,
6993
+ handlers,
6994
+ preparation?.runtimePathResolver
6995
+ )
6996
+ ),
6477
6997
  ...computerModules
6478
6998
  ]);
6479
6999
  }
@@ -6490,7 +7010,7 @@ function uniqueSystemCommandRoutes(candidates) {
6490
7010
  return true;
6491
7011
  });
6492
7012
  }
6493
- function projectSystemRequestModule(module2, snapshot, handlers) {
7013
+ function projectSystemRequestModule(module2, snapshot, handlers, resolver) {
6494
7014
  const targets = Object.freeze(snapshot.map(routeTargetId));
6495
7015
  const availability = ` Available targets for this request: ${targets.join(", ")}.`;
6496
7016
  return Object.freeze({
@@ -6511,7 +7031,7 @@ function projectSystemRequestModule(module2, snapshot, handlers) {
6511
7031
  },
6512
7032
  implementation: handlers[module2.definition.name],
6513
7033
  adapter: {
6514
- ...module2.adapter,
7034
+ ...createSystemCommandPathAdapter(module2.adapter, snapshot, resolver),
6515
7035
  executionBinding: systemExecutionBinding(snapshot)
6516
7036
  }
6517
7037
  });
@@ -6532,18 +7052,128 @@ function systemExecutionBinding(snapshot) {
6532
7052
  }
6533
7053
 
6534
7054
  // plugins/system/source/local-command-output.ts
6535
- var import_node_path9 = require("node:path");
7055
+ var import_node_path11 = require("node:path");
7056
+
7057
+ // plugins/system/source/security/windows-output-directory.ts
7058
+ var import_node_child_process5 = require("node:child_process");
7059
+ var import_promises9 = require("node:fs/promises");
7060
+ var import_node_path10 = require("node:path");
7061
+ var import_node_util2 = require("node:util");
7062
+ var execute = (0, import_node_util2.promisify)(import_node_child_process5.execFile);
7063
+ var privateDirectoryScript = `
7064
+ $env:PSModulePath = "$PSHOME\\Modules"
7065
+ $ErrorActionPreference = 'Stop'
7066
+ $target = $env:ABOT_SYSTEM_OUTPUT_DIRECTORY
7067
+ $current = [System.Security.Principal.WindowsIdentity]::GetCurrent().User
7068
+ $item = Get-Item -LiteralPath $target -Force
7069
+ if (-not $item.PSIsContainer) { exit 2 }
7070
+ if (($item.Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0) { exit 2 }
7071
+ $inherit = [System.Security.AccessControl.InheritanceFlags]'ContainerInherit, ObjectInherit'
7072
+ if ($env:ABOT_SYSTEM_OUTPUT_CREATE_PRIVATE -eq '1') {
7073
+ $acl = New-Object System.Security.AccessControl.DirectorySecurity
7074
+ $acl.SetOwner($current)
7075
+ $acl.SetAccessRuleProtection($true, $false)
7076
+ $rule = New-Object System.Security.AccessControl.FileSystemAccessRule($current, 'FullControl', $inherit, [System.Security.AccessControl.PropagationFlags]::None, [System.Security.AccessControl.AccessControlType]::Allow)
7077
+ $acl.AddAccessRule($rule)
7078
+ Set-Acl -LiteralPath $target -AclObject $acl
7079
+ }
7080
+ $observed = Get-Acl -LiteralPath $target
7081
+ if ($observed.GetOwner([System.Security.Principal.SecurityIdentifier]).Value -ne $current.Value) { exit 3 }
7082
+ if (-not $observed.AreAccessRulesProtected) { exit 4 }
7083
+ $rules = @($observed.GetAccessRules($true, $true, [System.Security.Principal.SecurityIdentifier]))
7084
+ if ($rules.Count -ne 1) { exit 5 }
7085
+ $rule = $rules[0]
7086
+ if ($rule.IdentityReference.Value -ne $current.Value) { exit 5 }
7087
+ if ($rule.AccessControlType -ne [System.Security.AccessControl.AccessControlType]::Allow) { exit 5 }
7088
+ if ($rule.FileSystemRights -ne [System.Security.AccessControl.FileSystemRights]::FullControl) { exit 5 }
7089
+ if ($rule.InheritanceFlags -ne $inherit) { exit 5 }
7090
+ if ($rule.PropagationFlags -ne [System.Security.AccessControl.PropagationFlags]::None) { exit 5 }
7091
+ `;
7092
+ async function verifyPrivateOutputDirectory(directory, create = false) {
7093
+ const info = await (0, import_promises9.lstat)(directory);
7094
+ if (!info.isDirectory() || info.isSymbolicLink()) throw new Error("output_directory_unavailable");
7095
+ const powershell = (0, import_node_path10.join)(process.env.SystemRoot ?? "C:\\Windows", "System32", "WindowsPowerShell", "v1.0", "powershell.exe");
7096
+ await execute(powershell, [
7097
+ "-NoProfile",
7098
+ "-NonInteractive",
7099
+ "-EncodedCommand",
7100
+ Buffer.from(privateDirectoryScript, "utf16le").toString("base64")
7101
+ ], {
7102
+ windowsHide: true,
7103
+ timeout: 1e4,
7104
+ maxBuffer: 16384,
7105
+ env: { ...process.env, ABOT_SYSTEM_OUTPUT_DIRECTORY: directory, ABOT_SYSTEM_OUTPUT_CREATE_PRIVATE: create ? "1" : "0" }
7106
+ });
7107
+ }
7108
+ function isAbsentPath(error) {
7109
+ if (!error || typeof error !== "object" || !("code" in error)) return false;
7110
+ return error.code === "ENOENT";
7111
+ }
7112
+ async function hasOutputDirectoryPath(directory) {
7113
+ try {
7114
+ await (0, import_promises9.lstat)(directory);
7115
+ return true;
7116
+ } catch (error) {
7117
+ if (isAbsentPath(error)) return false;
7118
+ throw error;
7119
+ }
7120
+ }
7121
+ async function installPrivateOutputDirectory(directory) {
7122
+ if (await hasOutputDirectoryPath(directory)) return;
7123
+ const parent = (0, import_node_path10.dirname)(directory);
7124
+ await (0, import_promises9.mkdir)(parent, { recursive: true });
7125
+ const candidate = await (0, import_promises9.mkdtemp)((0, import_node_path10.join)(parent, `.${(0, import_node_path10.basename)(directory)}.private-`));
7126
+ try {
7127
+ await verifyPrivateOutputDirectory(candidate, true);
7128
+ try {
7129
+ await (0, import_promises9.rename)(candidate, directory);
7130
+ } catch (error) {
7131
+ if (!await hasOutputDirectoryPath(directory)) throw error;
7132
+ }
7133
+ } finally {
7134
+ await (0, import_promises9.rmdir)(candidate).catch((error) => {
7135
+ if (!isAbsentPath(error)) throw error;
7136
+ });
7137
+ }
7138
+ }
7139
+ async function ensureWindowsOutputDirectory(directory) {
7140
+ if (process.platform !== "win32") return;
7141
+ try {
7142
+ await installPrivateOutputDirectory(directory);
7143
+ await verifyPrivateOutputDirectory(directory);
7144
+ } catch {
7145
+ throw new SystemOperationError("system_output_storage_failed", "Private output storage could not be prepared. The command was not dispatched.");
7146
+ }
7147
+ }
7148
+
7149
+ // plugins/system/source/local-command-output-retention.ts
7150
+ function scheduleLocalSystemOutputCleanup(root, retentionMs) {
7151
+ if (process.platform !== "win32") {
7152
+ scheduleSystemOutputCleanup(root, retentionMs);
7153
+ return Promise.resolve();
7154
+ }
7155
+ return ensureWindowsOutputDirectory(root).then(
7156
+ () => scheduleSystemOutputCleanup(root, retentionMs),
7157
+ () => process.emitWarning("SYSTEM output cleanup skipped because private storage could not be verified.", {
7158
+ code: "SYSTEM_OUTPUT_PRIVATE_STORAGE_UNAVAILABLE"
7159
+ })
7160
+ );
7161
+ }
7162
+
7163
+ // plugins/system/source/local-command-output.ts
6536
7164
  var CONTEXT_STREAMS = Object.freeze(["stdout", "stderr"]);
6537
7165
  function createLocalSystemCommandOutput(plugin) {
6538
- const root = (0, import_node_path9.join)(plugin.stateDir, "command-output");
7166
+ const root = (0, import_node_path11.join)(plugin.stateDir, "command-output");
6539
7167
  const retentionMs = systemCommandOutputRetentionMs(plugin);
6540
- scheduleSystemOutputCleanup(root, retentionMs);
7168
+ const initialization = scheduleLocalSystemOutputCleanup(root, retentionMs);
6541
7169
  return (context) => {
6542
7170
  let captured;
6543
7171
  return {
6544
7172
  async run(input) {
6545
7173
  if (input.abortSignal?.aborted) return runSystemProcess(input);
6546
- captured = await createSystemOutputCapture(root, retentionMs);
7174
+ await initialization;
7175
+ await ensureWindowsOutputDirectory(root);
7176
+ captured = await createSystemOutputCapture(root, retentionMs, redactSecretText);
6547
7177
  let result;
6548
7178
  try {
6549
7179
  result = await runSystemProcess(input, captured.capture);
@@ -6553,14 +7183,14 @@ function createLocalSystemCommandOutput(plugin) {
6553
7183
  }
6554
7184
  const streams = await captured.finish(result);
6555
7185
  return {
6556
- ...result,
7186
+ ...captured.processResult,
6557
7187
  stdout: streams.stdout,
6558
- stderr: streams.stderr || result.stderr,
7188
+ stderr: streams.stderr,
6559
7189
  outputTruncated: Boolean(captured.failure)
6560
7190
  };
6561
7191
  },
6562
7192
  async present(target, result) {
6563
- if (captured?.failure) return outputFailure(target, result, context, captured.receipt, captured.failure);
7193
+ if (captured?.failure) return outputFailure(target, result, context, captured.receipt, captured.failure, captured.failureKind);
6564
7194
  const receipt = buildSystemProcessResult(target, result, "command_process_completion");
6565
7195
  const delivered = deliverPluginTextResult({
6566
7196
  ...receipt,
@@ -6573,9 +7203,10 @@ function createLocalSystemCommandOutput(plugin) {
6573
7203
  };
6574
7204
  };
6575
7205
  }
6576
- function outputFailure(target, result, context, capture, storageFailure) {
7206
+ function outputFailure(target, result, context, capture, captureFailure, failureKind) {
7207
+ const failureCode = failureKind === "security" ? "system_output_protection_failed" : "system_output_storage_failed";
6577
7208
  return failureResult({
6578
- errorCode: storageFailure ? "system_output_storage_failed" : "system_output_delivery_pending",
7209
+ errorCode: captureFailure ? failureCode : "system_output_delivery_pending",
6579
7210
  message: "The command was dispatched. Its output could not be delivered completely; do not repeat the command just to retrieve output. Inspect the process receipt and retained capture.",
6580
7211
  ...result.exitCode !== null ? { exitCode: result.exitCode } : {},
6581
7212
  data: {
@@ -6585,7 +7216,8 @@ function outputFailure(target, result, context, capture, storageFailure) {
6585
7216
  spawnedProcess: result.spawnedProcess ?? null,
6586
7217
  exitCode: result.exitCode,
6587
7218
  outputCapture: capture ?? null,
6588
- ...storageFailure ? { storageFailure } : {},
7219
+ ...captureFailure && failureKind === "security" ? { securityFailure: captureFailure } : {},
7220
+ ...captureFailure && failureKind !== "security" ? { storageFailure: captureFailure } : {},
6589
7221
  outputDelivery: "pending",
6590
7222
  evidenceScope: "command_process_completion",
6591
7223
  independentOutcomeCheck: "not_performed",
@@ -6602,14 +7234,68 @@ function systemCommandOutputRetentionMs(plugin) {
6602
7234
  });
6603
7235
  }
6604
7236
 
7237
+ // plugins/system/source/security/system-results.ts
7238
+ var INCOMPLETE_STREAM = "[UNAVAILABLE: incomplete output cannot be scanned for secrets]";
7239
+ var SENSITIVE_TARGET = "Target unavailable because its shell identity contains sensitive text.";
7240
+ function protectApplication(application) {
7241
+ if (redactSecretText(application.id) !== application.id) return void 0;
7242
+ return { ...application, name: redactSecretText(application.name) };
7243
+ }
7244
+ function protectCatalog(catalog) {
7245
+ const applications = catalog.applications.flatMap((application) => {
7246
+ const protectedApplication = protectApplication(application);
7247
+ return protectedApplication ? [protectedApplication] : [];
7248
+ });
7249
+ return {
7250
+ ...catalog,
7251
+ applications,
7252
+ complete: catalog.complete && applications.length === catalog.applications.length,
7253
+ scope: { ...catalog.scope, roots: catalog.scope.roots.map(redactSecretText) }
7254
+ };
7255
+ }
7256
+ function protectTargets(observation) {
7257
+ return {
7258
+ ...observation,
7259
+ host: { ...observation.host, kernelRelease: redactSecretText(observation.host.kernelRelease) },
7260
+ targets: observation.targets.map((target) => {
7261
+ if (!target.available)
7262
+ return { ...target, reason: redactSecretText(target.reason) };
7263
+ if (redactSecretText(target.shell) !== target.shell)
7264
+ return { id: target.id, available: false, reason: SENSITIVE_TARGET };
7265
+ return target;
7266
+ })
7267
+ };
7268
+ }
7269
+ function protectProcess(result) {
7270
+ return {
7271
+ ...result,
7272
+ stdout: result.outputTruncated ? INCOMPLETE_STREAM : redactSecretText(result.stdout),
7273
+ stderr: result.outputTruncated ? INCOMPLETE_STREAM : redactSecretText(result.stderr),
7274
+ ...result.spawnedProcess ? {
7275
+ spawnedProcess: {
7276
+ ...result.spawnedProcess,
7277
+ executable: redactSecretText(result.spawnedProcess.executable)
7278
+ }
7279
+ } : {}
7280
+ };
7281
+ }
7282
+ var systemResultProtection = Object.freeze({
7283
+ protectTargets,
7284
+ protectCatalog,
7285
+ protectProcess,
7286
+ protectApplication,
7287
+ protectMessage: redactSecretText
7288
+ });
7289
+
6605
7290
  // plugins/system/source/index.ts
6606
7291
  var index_default = defineRuntimePlugin((context) => {
6607
7292
  const output = createLocalSystemCommandOutput(context);
6608
7293
  return {
6609
- handlers: { ...createSystemHandlers(void 0, void 0, output), ...unboundComputerHandlers() },
7294
+ handlers: { ...createSystemHandlers(void 0, void 0, output, systemResultProtection), ...unboundComputerHandlers() },
6610
7295
  prepareRequest: (modules, preparation) => prepareSystemRequestModules(context.rootDir, modules, {
6611
7296
  outputRetentionMs: systemCommandOutputRetentionMs(context),
6612
- createNativeHandlers: (resolve) => createSystemHandlers(void 0, resolve, output)
7297
+ observeTargets: async () => systemResultProtection.protectTargets(await observeSystemTargets()),
7298
+ createNativeHandlers: (resolve) => createSystemHandlers(void 0, resolve, output, systemResultProtection)
6613
7299
  }, preparation)
6614
7300
  };
6615
7301
  });