@abot-ai/runtime 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (443) hide show
  1. package/dist/src/capabilities/tool-request-resources.d.ts +3 -0
  2. package/dist/src/cli/abot.js +2 -0
  3. package/dist/src/cli/host-companion-bundle.mjs +751 -333
  4. package/dist/src/computer-access/collection-consent.d.ts +9 -0
  5. package/dist/src/computer-access/collection-consent.js +47 -0
  6. package/dist/src/computer-access/command-output-capture.d.ts +17 -6
  7. package/dist/src/computer-access/command-output-capture.js +134 -68
  8. package/dist/src/computer-access/command-output-protection.d.ts +17 -0
  9. package/dist/src/computer-access/command-output-protection.js +59 -0
  10. package/dist/src/computer-access/companion/command-output.d.ts +1 -0
  11. package/dist/src/computer-access/companion/command-output.js +23 -6
  12. package/dist/src/computer-access/companion/install-link-macos.js +2 -1
  13. package/dist/src/computer-access/companion/native-notifications.js +3 -2
  14. package/dist/src/computer-access/companion/native-session.js +6 -2
  15. package/dist/src/computer-access/companion/observation-filter.js +2 -26
  16. package/dist/src/computer-access/companion/observation-process.d.ts +2 -0
  17. package/dist/src/computer-access/companion/observation-process.js +51 -25
  18. package/dist/src/computer-access/companion/observation-redaction.d.ts +2 -7
  19. package/dist/src/computer-access/companion/observation-redaction.js +2 -111
  20. package/dist/src/computer-access/companion/secret-protection-protocol.d.ts +6 -0
  21. package/dist/src/computer-access/companion/secret-protection-protocol.js +6 -0
  22. package/dist/src/computer-access/computer/companion-sessions.js +7 -6
  23. package/dist/src/computer-access/computer/unix-native-process.js +23 -11
  24. package/dist/src/computer-access/handlers.d.ts +2 -1
  25. package/dist/src/computer-access/handlers.js +79 -11
  26. package/dist/src/computer-access/host-observation.d.ts +3 -3
  27. package/dist/src/computer-access/native-observation-connection.d.ts +12 -0
  28. package/dist/src/computer-access/native-observation-connection.js +78 -0
  29. package/dist/src/computer-access/native-observation-ownership.d.ts +6 -0
  30. package/dist/src/computer-access/native-observation-ownership.js +55 -0
  31. package/dist/src/computer-access/native-observation-shutdown.d.ts +7 -0
  32. package/dist/src/computer-access/native-observation-shutdown.js +58 -0
  33. package/dist/src/computer-access/observation-source.d.ts +6 -0
  34. package/dist/src/computer-access/observation-source.js +10 -0
  35. package/dist/src/computer-access/security/desktop-result.d.ts +8 -0
  36. package/dist/src/computer-access/security/desktop-result.js +146 -0
  37. package/dist/src/computer-access/security/observed-error.d.ts +2 -0
  38. package/dist/src/computer-access/security/observed-error.js +10 -0
  39. package/dist/src/computer-access/security/secret-text.d.ts +7 -0
  40. package/dist/src/computer-access/security/secret-text.js +111 -0
  41. package/dist/src/computer-access/security/system-results.d.ts +2 -0
  42. package/dist/src/computer-access/security/system-results.js +53 -0
  43. package/dist/src/computer-access/system-result-protection.d.ts +11 -0
  44. package/dist/src/computer-access/system-result-protection.js +1 -0
  45. package/dist/src/model-gateway/observability/provider-response-capture.d.ts +60 -0
  46. package/dist/src/model-gateway/observability/provider-response-capture.js +68 -0
  47. package/dist/src/model-gateway/observability/provider-response-prefix.d.ts +7 -0
  48. package/dist/src/model-gateway/observability/provider-response-prefix.js +14 -0
  49. package/dist/src/model-gateway/observability/provider-response-tail.d.ts +8 -0
  50. package/dist/src/model-gateway/observability/provider-response-tail.js +28 -0
  51. package/dist/src/model-gateway/observability/provider-sse-diagnostics.d.ts +30 -0
  52. package/dist/src/model-gateway/observability/provider-sse-diagnostics.js +119 -0
  53. package/dist/src/model-gateway/observability/provider-trace.js +30 -8
  54. package/dist/src/model-gateway/providers/ollama/adapter.js +8 -2
  55. package/dist/src/model-gateway/providers/ollama/stream-normalizer.js +70 -50
  56. package/dist/src/model-gateway/providers/ollama/stream-termination.d.ts +6 -0
  57. package/dist/src/model-gateway/providers/ollama/stream-termination.js +20 -0
  58. package/dist/src/model-gateway/providers/openai/adapter.js +9 -7
  59. package/dist/src/model-gateway/providers/openai/diagnostics.d.ts +0 -1
  60. package/dist/src/model-gateway/providers/openai/diagnostics.js +0 -9
  61. package/dist/src/model-gateway/providers/openai/function-output.d.ts +11 -0
  62. package/dist/src/model-gateway/providers/openai/function-output.js +37 -0
  63. package/dist/src/model-gateway/providers/openai/function-result.d.ts +7 -0
  64. package/dist/src/model-gateway/providers/openai/function-result.js +35 -0
  65. package/dist/src/model-gateway/providers/openai/message-output-policy.d.ts +3 -0
  66. package/dist/src/model-gateway/providers/openai/message-output-policy.js +16 -0
  67. package/dist/src/model-gateway/providers/openai/payload.d.ts +0 -2
  68. package/dist/src/model-gateway/providers/openai/payload.js +6 -23
  69. package/dist/src/model-gateway/providers/openai/response-lifetime.d.ts +2 -0
  70. package/dist/src/model-gateway/providers/openai/response-lifetime.js +64 -0
  71. package/dist/src/model-gateway/providers/openai/sse-data.d.ts +9 -0
  72. package/dist/src/model-gateway/providers/openai/sse-data.js +67 -0
  73. package/dist/src/model-gateway/providers/openai/stream-normalizer.d.ts +10 -22
  74. package/dist/src/model-gateway/providers/openai/stream-normalizer.js +78 -79
  75. package/dist/src/model-gateway/providers/openai/stream.js +13 -41
  76. package/dist/src/model-gateway/providers/openai/structured-message-output.d.ts +42 -0
  77. package/dist/src/model-gateway/providers/openai/structured-message-output.js +175 -0
  78. package/dist/src/model-gateway/server.js +5 -1
  79. package/dist/src/plugin-contract/index.d.ts +1 -0
  80. package/dist/src/plugin-contract/index.js +1 -0
  81. package/dist/src/plugin-contract/manifest.d.ts +2 -0
  82. package/dist/src/plugin-contract/manifest.js +1 -0
  83. package/dist/src/plugin-contract/platform-compatibility.d.ts +16 -0
  84. package/dist/src/plugin-contract/platform-compatibility.js +3 -0
  85. package/dist/src/plugin-sdk/computer-access.d.ts +4 -0
  86. package/dist/src/plugin-sdk/computer-access.js +1 -0
  87. package/dist/src/plugin-sdk/files-windows/process.d.ts +3 -0
  88. package/dist/src/plugin-sdk/files-windows/process.js +93 -0
  89. package/dist/src/plugin-sdk/files-windows/read-script.d.ts +1 -0
  90. package/dist/src/plugin-sdk/files-windows/read-script.js +43 -0
  91. package/dist/src/plugin-sdk/files-windows/read.d.ts +6 -0
  92. package/dist/src/plugin-sdk/files-windows/read.js +56 -0
  93. package/dist/src/plugin-sdk/files-windows/result.d.ts +4 -0
  94. package/dist/src/plugin-sdk/files-windows/result.js +67 -0
  95. package/dist/src/plugin-sdk/files.js +4 -0
  96. package/dist/src/plugin-sdk/index.d.ts +1 -0
  97. package/dist/src/plugin-sdk/index.js +1 -0
  98. package/dist/src/plugin-sdk/mutation-result.d.ts +7 -0
  99. package/dist/src/plugin-sdk/mutation-result.js +11 -0
  100. package/dist/src/runtime/adapters/long-term-memory/file-lock/acquisition.js +20 -3
  101. package/dist/src/runtime/adapters/long-term-memory/file-lock/owner-record.js +3 -1
  102. package/dist/src/runtime/adapters/long-term-memory/file-lock/path-observation.d.ts +3 -0
  103. package/dist/src/runtime/adapters/long-term-memory/file-lock/path-observation.js +20 -0
  104. package/dist/src/runtime/adapters/long-term-memory/file-lock/snapshot.js +7 -3
  105. package/dist/src/runtime/adapters/passive-learning-runtime.d.ts +1 -1
  106. package/dist/src/runtime/adapters/passive-learning-runtime.js +3 -3
  107. package/dist/src/runtime/adapters/runtime-observation-connection.d.ts +5 -0
  108. package/dist/src/runtime/adapters/runtime-observation-connection.js +13 -0
  109. package/dist/src/runtime/local-host/windows-private-access.js +2 -0
  110. package/dist/src/runtime/passive-learning/application-catalog.js +3 -1
  111. package/dist/src/runtime/passive-learning/collection-source.js +7 -0
  112. package/dist/src/runtime/passive-learning/service.js +2 -3
  113. package/dist/src/runtime/passive-learning/status-projection.d.ts +2 -0
  114. package/dist/src/runtime/passive-learning/status-projection.js +9 -0
  115. package/dist/src/runtime/plugins/installation/package.d.ts +8 -0
  116. package/dist/src/runtime/plugins/installation/package.js +2 -0
  117. package/dist/src/runtime/plugins/installation/service.d.ts +7 -0
  118. package/dist/src/runtime/plugins/loader.js +24 -14
  119. package/dist/src/runtime/plugins/manifest-platform-compatibility.d.ts +2 -0
  120. package/dist/src/runtime/plugins/manifest-platform-compatibility.js +39 -0
  121. package/dist/src/runtime/plugins/manifest-validator.js +9 -1
  122. package/dist/src/runtime/plugins/platform-compatibility.d.ts +4 -0
  123. package/dist/src/runtime/plugins/platform-compatibility.js +44 -0
  124. package/dist/src/runtime/request/approval-wait/activation-events.js +19 -7
  125. package/dist/src/runtime/request/approval-wait/execution-compaction-restore.d.ts +20 -0
  126. package/dist/src/runtime/request/approval-wait/execution-compaction-restore.js +118 -0
  127. package/dist/src/runtime/request/approval-wait/super-compaction-restore.js +2 -1
  128. package/dist/src/runtime/request/prepared-execution.js +3 -0
  129. package/dist/src/runtime/steps/execution-agent/capability-result-context.d.ts +6 -0
  130. package/dist/src/runtime/steps/execution-agent/capability-result-context.js +29 -0
  131. package/dist/src/runtime/steps/execution-agent/format.js +2 -3
  132. package/dist/src/runtime/steps/execution-agent/input.js +1 -1
  133. package/dist/src/runtime/steps/execution-agent/prompt.js +5 -5
  134. package/dist/src/runtime/steps/execution-agent/response-prompt.js +1 -0
  135. package/dist/src/runtime/steps/execution-agent/state-context.d.ts +2 -3
  136. package/dist/src/runtime/steps/execution-agent/state-context.js +26 -35
  137. package/dist/src/runtime/steps/execution-agent/work-plan-contract.d.ts +1 -3
  138. package/dist/src/runtime/steps/execution-agent/work-plan-contract.js +0 -55
  139. package/dist/src/runtime/steps/execution-agent/work-plan-schema.d.ts +3 -0
  140. package/dist/src/runtime/steps/execution-agent/work-plan-schema.js +61 -0
  141. package/dist/src/sessions/durable-session-commit.js +3 -3
  142. package/dist/src/sessions/prepared-session-replacement.d.ts +6 -0
  143. package/dist/src/sessions/prepared-session-replacement.js +46 -0
  144. package/dist/src/sessions/session-store.js +3 -3
  145. package/dist/src/shared/passive-observation-self-exclusion.d.ts +5 -0
  146. package/dist/src/shared/passive-observation-self-exclusion.js +37 -0
  147. package/dist/src/shared/windows-file-io/authority-script.d.ts +1 -0
  148. package/dist/src/shared/windows-file-io/authority-script.js +94 -0
  149. package/dist/src/shared/windows-file-io/native-script.d.ts +2 -0
  150. package/dist/src/shared/windows-file-io/native-script.js +120 -0
  151. package/dist/src/shared/windows-file-io/read-bytes-script.d.ts +1 -0
  152. package/dist/src/shared/windows-file-io/read-bytes-script.js +18 -0
  153. package/dist/src/shared/windows-job-object.d.ts +2 -0
  154. package/dist/src/shared/windows-job-object.js +66 -0
  155. package/dist/src/web-ui/app/app-bootstrap.js +14 -1
  156. package/dist/src/web-ui/app/app-state.js +0 -7
  157. package/dist/src/web-ui/app/app.js +53 -156
  158. package/dist/src/web-ui/app/components/automations/node-inspector.js +3 -2
  159. package/dist/src/web-ui/app/components/automations/step-editor-dialog.js +3 -0
  160. package/dist/src/web-ui/app/components/composer-submission-notice.js +50 -0
  161. package/dist/src/web-ui/app/components/config-workspace/model-plugin-permissions.js +7 -1
  162. package/dist/src/web-ui/app/components/config-workspace/workspace-mutations.js +22 -2
  163. package/dist/src/web-ui/app/components/home-guidance/daily-review.js +2 -2
  164. package/dist/src/web-ui/app/components/home-guidance/home-guidance.js +20 -6
  165. package/dist/src/web-ui/app/components/model-setup/context-window-feedback.js +53 -0
  166. package/dist/src/web-ui/app/components/model-setup/save-flow.js +3 -1
  167. package/dist/src/web-ui/app/components/model-setup/save-outcome.js +1 -0
  168. package/dist/src/web-ui/app/components/model-setup/wizard.js +12 -0
  169. package/dist/src/web-ui/app/components/passive-learning/activity-controls.js +4 -0
  170. package/dist/src/web-ui/app/components/passive-learning/collection-access.js +35 -0
  171. package/dist/src/web-ui/app/components/passive-learning/collection-consent-dialog.js +59 -0
  172. package/dist/src/web-ui/app/components/passive-learning/collection-consent-gate.js +94 -0
  173. package/dist/src/web-ui/app/components/passive-learning/computer-update-notice.js +6 -0
  174. package/dist/src/web-ui/app/components/passive-learning/failure-copy.js +1 -0
  175. package/dist/src/web-ui/app/components/passive-learning/home.js +7 -2
  176. package/dist/src/web-ui/app/components/passive-learning/macos-collection-restart-notice.js +1 -0
  177. package/dist/src/web-ui/app/components/passive-learning/memory.js +2 -4
  178. package/dist/src/web-ui/app/components/passive-learning/workspace-view.js +2 -2
  179. package/dist/src/web-ui/app/components/plugins/compatibility.js +13 -0
  180. package/dist/src/web-ui/app/components/plugins/discovery-rendering.js +9 -1
  181. package/dist/src/web-ui/app/components/plugins/installation-compatibility.js +7 -0
  182. package/dist/src/web-ui/app/components/plugins/installation.js +2 -1
  183. package/dist/src/web-ui/app/components/plugins/rendering.js +3 -0
  184. package/dist/src/web-ui/app/components/reasoning-override-prompt.js +82 -0
  185. package/dist/src/web-ui/app/components/runtime-config-activation.js +22 -8
  186. package/dist/src/web-ui/app/components/runtime-setup/optional-steps.js +7 -4
  187. package/dist/src/web-ui/app/components/runtime-setup/plugins.js +3 -1
  188. package/dist/src/web-ui/app/components/runtime-setup/rendering.js +6 -4
  189. package/dist/src/web-ui/app/components/runtime-setup-guide.d.ts +1 -0
  190. package/dist/src/web-ui/app/components/schedules/form.js +10 -8
  191. package/dist/src/web-ui/app/components/schedules/workspace.js +23 -4
  192. package/dist/src/web-ui/app/components/session-sidebar-sections.js +2 -2
  193. package/dist/src/web-ui/app/components/spark-chat/handoff-actions.js +9 -3
  194. package/dist/src/web-ui/app/components/spark-chat/placement.js +4 -7
  195. package/dist/src/web-ui/app/components/spark-chat/settings.js +7 -3
  196. package/dist/src/web-ui/app/components/system-host/macos-permissions.js +2 -0
  197. package/dist/src/web-ui/app/components/system-host/native-windows-access.js +50 -0
  198. package/dist/src/web-ui/app/components/system-host/rendering.js +3 -0
  199. package/dist/src/web-ui/app/components/workspace-storage-notice.js +37 -0
  200. package/dist/src/web-ui/app/configuration-environment-refresh.js +27 -34
  201. package/dist/src/web-ui/app/configuration-feature.js +9 -1
  202. package/dist/src/web-ui/app/controllers/app-event-bindings.js +38 -105
  203. package/dist/src/web-ui/app/controllers/chat-request-controller.d.ts +28 -0
  204. package/dist/src/web-ui/app/controllers/chat-request-controller.js +34 -66
  205. package/dist/src/web-ui/app/controllers/composer-attachments-controller.d.ts +15 -40
  206. package/dist/src/web-ui/app/controllers/composer-attachments-controller.js +26 -69
  207. package/dist/src/web-ui/app/controllers/composer-draft-view.d.ts +27 -0
  208. package/dist/src/web-ui/app/controllers/composer-draft-view.js +48 -0
  209. package/dist/src/web-ui/app/controllers/composer-drafts.d.ts +55 -0
  210. package/dist/src/web-ui/app/controllers/composer-drafts.js +120 -0
  211. package/dist/src/web-ui/app/controllers/composer-feature.d.ts +65 -0
  212. package/dist/src/web-ui/app/controllers/composer-feature.js +124 -0
  213. package/dist/src/web-ui/app/controllers/composer-queue-controller.d.ts +33 -94
  214. package/dist/src/web-ui/app/controllers/composer-queue-controller.js +185 -251
  215. package/dist/src/web-ui/app/controllers/composer-submission-lifecycle.d.ts +48 -0
  216. package/dist/src/web-ui/app/controllers/composer-submission-lifecycle.js +97 -0
  217. package/dist/src/web-ui/app/controllers/composer-submit-controller.d.ts +30 -61
  218. package/dist/src/web-ui/app/controllers/composer-submit-controller.js +56 -138
  219. package/dist/src/web-ui/app/controllers/composer-surface-controller.js +6 -0
  220. package/dist/src/web-ui/app/controllers/composer-workspace-controller.d.ts +22 -40
  221. package/dist/src/web-ui/app/controllers/composer-workspace-controller.js +49 -165
  222. package/dist/src/web-ui/app/controllers/conversation-navigation-intent.js +15 -0
  223. package/dist/src/web-ui/app/controllers/conversation-request-hydration.js +20 -17
  224. package/dist/src/web-ui/app/controllers/conversation-session-controller.d.ts +1 -2
  225. package/dist/src/web-ui/app/controllers/conversation-session-controller.js +49 -22
  226. package/dist/src/web-ui/app/controllers/conversation-workspace-activation.js +27 -0
  227. package/dist/src/web-ui/app/controllers/daily-memory-review.js +15 -16
  228. package/dist/src/web-ui/app/controllers/environment-transition.js +126 -0
  229. package/dist/src/web-ui/app/controllers/environment-workspace-preparation.js +18 -0
  230. package/dist/src/web-ui/app/controllers/home-composer-feature.d.ts +14 -36
  231. package/dist/src/web-ui/app/controllers/home-composer-feature.js +17 -114
  232. package/dist/src/web-ui/app/controllers/home-conversation-activation.js +6 -8
  233. package/dist/src/web-ui/app/controllers/passive-learning-controller.js +56 -0
  234. package/dist/src/web-ui/app/controllers/projects-controller.d.ts +1 -1
  235. package/dist/src/web-ui/app/controllers/projects-controller.js +6 -1
  236. package/dist/src/web-ui/app/controllers/reasoning-mode-controller.js +174 -0
  237. package/dist/src/web-ui/app/controllers/runtime-selection-controller.d.ts +7 -0
  238. package/dist/src/web-ui/app/controllers/runtime-selection-controller.js +20 -155
  239. package/dist/src/web-ui/app/controllers/session-controller.js +33 -17
  240. package/dist/src/web-ui/app/controllers/session-pin-updates.js +14 -0
  241. package/dist/src/web-ui/app/controllers/session-sidebar-controller.js +12 -14
  242. package/dist/src/web-ui/app/controllers/spark-chat-sync.js +2 -2
  243. package/dist/src/web-ui/app/controllers/steer-controller.js +9 -7
  244. package/dist/src/web-ui/app/controllers/tool-permission-mode-controller.js +1 -1
  245. package/dist/src/web-ui/app/controllers/workspace-conversation-opener.js +34 -0
  246. package/dist/src/web-ui/app/dashboard-feature.js +3 -2
  247. package/dist/src/web-ui/app/lib/reasoning-controls.js +35 -0
  248. package/dist/src/web-ui/app/lib/session-composer-queue-ownership.js +58 -0
  249. package/dist/src/web-ui/app/lib/session-composer-queue.d.ts +12 -0
  250. package/dist/src/web-ui/app/lib/session-composer-queue.js +25 -6
  251. package/dist/src/web-ui/app/passive-learning-feature.js +16 -3
  252. package/dist/src/web-ui/app/schedules-feature.js +5 -3
  253. package/dist/src/web-ui/app/services/client-preferences.d.ts +18 -10
  254. package/dist/src/web-ui/app/services/client-preferences.js +25 -16
  255. package/dist/src/web-ui/app/services/home-guidance-preferences.js +13 -13
  256. package/dist/src/web-ui/app/services/reasoning-override.js +12 -0
  257. package/dist/src/web-ui/app/services/runtime-web-client/automations.js +10 -2
  258. package/dist/src/web-ui/app/services/runtime-web-client/memory.js +7 -2
  259. package/dist/src/web-ui/app/services/runtime-web-client/system-host.js +2 -0
  260. package/dist/src/web-ui/app/services/runtime-web-client.d.ts +2 -0
  261. package/dist/src/web-ui/app/services/runtime-web-client.js +2 -0
  262. package/dist/src/web-ui/app/services/server-composer-queue.js +32 -0
  263. package/dist/src/web-ui/app/services/session-sidebar-preferences.js +5 -5
  264. package/dist/src/web-ui/app/services/workspace-state-storage.js +116 -0
  265. package/dist/src/web-ui/app/services/workspace-state.js +27 -0
  266. package/dist/src/web-ui/app/spark-chat-conversation.js +34 -45
  267. package/dist/src/web-ui/app/spark-chat-feature.js +10 -4
  268. package/dist/src/web-ui/app/styles/21-composer-controls.css +16 -0
  269. package/dist/src/web-ui/app/styles/41-plugin-management.css +8 -0
  270. package/dist/src/web-ui/app/styles/42-model-plugin-permissions.css +1 -0
  271. package/dist/src/web-ui/app/styles/49-collection-consent.css +30 -0
  272. package/dist/src/web-ui/app/styles/64-workspace-storage.css +23 -0
  273. package/dist/src/web-ui/app/styles.css +2 -0
  274. package/dist/src/web-ui/client-state/contracts.d.ts +15 -0
  275. package/dist/src/web-ui/client-state/contracts.js +13 -0
  276. package/dist/src/web-ui/client-state/preference-shapes.d.ts +2 -0
  277. package/dist/src/web-ui/client-state/preference-shapes.js +80 -0
  278. package/dist/src/web-ui/client-state/preferences.d.ts +3 -0
  279. package/dist/src/web-ui/client-state/preferences.js +84 -0
  280. package/dist/src/web-ui/client-state/queue.d.ts +3 -0
  281. package/dist/src/web-ui/client-state/queue.js +43 -0
  282. package/dist/src/web-ui/client-state/routes.d.ts +7 -0
  283. package/dist/src/web-ui/client-state/routes.js +58 -0
  284. package/dist/src/web-ui/client-state/store.d.ts +14 -0
  285. package/dist/src/web-ui/client-state/store.js +88 -0
  286. package/dist/src/web-ui/local-runtime/configuration-activation-source.js +2 -0
  287. package/dist/src/web-ui/local-runtime/http.js +11 -2
  288. package/dist/src/web-ui/local-runtime/model-context-capacity-error.d.ts +14 -0
  289. package/dist/src/web-ui/local-runtime/model-context-capacity-error.js +28 -0
  290. package/dist/src/web-ui/local-runtime/model-setup-context-window.d.ts +15 -0
  291. package/dist/src/web-ui/local-runtime/model-setup-context-window.js +25 -0
  292. package/dist/src/web-ui/local-runtime/model-setup-routes.js +2 -0
  293. package/dist/src/web-ui/local-runtime/model-setup-service.js +5 -2
  294. package/dist/src/web-ui/local-runtime/model-setup-validation.d.ts +1 -0
  295. package/dist/src/web-ui/local-runtime/model-setup-validation.js +14 -7
  296. package/dist/src/web-ui/local-runtime/request-body-error.d.ts +11 -0
  297. package/dist/src/web-ui/local-runtime/request-body-error.js +14 -0
  298. package/dist/src/web-ui/local-runtime/request-control-observation.js +2 -2
  299. package/dist/src/web-ui/local-runtime/request-execution.js +18 -18
  300. package/dist/src/web-ui/local-runtime/runtime-setup-connection-edit.d.ts +2 -0
  301. package/dist/src/web-ui/local-runtime/runtime-setup-connection-edit.js +35 -22
  302. package/dist/src/web-ui/local-runtime/runtime-setup-context-window.d.ts +2 -9
  303. package/dist/src/web-ui/local-runtime/runtime-setup-context-window.js +4 -27
  304. package/dist/src/web-ui/local-runtime/runtime-setup-credentials.d.ts +15 -1
  305. package/dist/src/web-ui/local-runtime/runtime-setup-credentials.js +30 -11
  306. package/dist/src/web-ui/local-runtime/runtime-setup-edit-files.d.ts +20 -0
  307. package/dist/src/web-ui/local-runtime/runtime-setup-edit-files.js +104 -0
  308. package/dist/src/web-ui/local-runtime/runtime-setup-edit-journal.d.ts +29 -0
  309. package/dist/src/web-ui/local-runtime/runtime-setup-edit-journal.js +151 -0
  310. package/dist/src/web-ui/local-runtime/runtime-setup-edit-recovery.d.ts +7 -0
  311. package/dist/src/web-ui/local-runtime/runtime-setup-edit-recovery.js +87 -0
  312. package/dist/src/web-ui/local-runtime/runtime-setup-edit-transaction.d.ts +3 -0
  313. package/dist/src/web-ui/local-runtime/runtime-setup-edit-transaction.js +37 -0
  314. package/dist/src/web-ui/local-runtime/runtime-setup-service.js +4 -0
  315. package/dist/src/web-ui/local-runtime-backend.js +14 -0
  316. package/dist/src/web-ui/plugin-management-catalog.d.ts +3 -1
  317. package/dist/src/web-ui/plugin-management-catalog.js +3 -1
  318. package/dist/src/web-ui/plugin-management-service.d.ts +1 -0
  319. package/dist/src/web-ui/plugin-removal-service.d.ts +1 -0
  320. package/dist/src/web-ui/server-readiness.d.ts +3 -0
  321. package/dist/src/web-ui/server-readiness.js +36 -0
  322. package/dist/src/web-ui/server.d.ts +2 -0
  323. package/dist/src/web-ui/server.js +23 -1
  324. package/dist/src/web-ui/system-host-service.js +13 -2
  325. package/dist/src/web-ui/system-host-setup/collection-consent-route.d.ts +3 -0
  326. package/dist/src/web-ui/system-host-setup/collection-consent-route.js +30 -0
  327. package/docs/installation.md +44 -5
  328. package/docs/plugins.md +145 -4
  329. package/docs/tool-execution-result-evidence-contract.md +57 -0
  330. package/docs/windows-companion-store.md +5 -0
  331. package/package.json +4 -2
  332. package/plugins/capability-brief/plugin.json +4 -0
  333. package/plugins/code-outline/README.md +20 -0
  334. package/plugins/code-outline/plugin.json +1 -0
  335. package/plugins/code-outline/source/index.ts +16 -20
  336. package/plugins/code-outline/source/read-failure.ts +40 -0
  337. package/plugins/code-outline/src/index.cjs +614 -29
  338. package/plugins/document-reader/README.md +33 -0
  339. package/plugins/document-reader/plugin.json +1 -0
  340. package/plugins/document-reader/source/pdf-contract.ts +57 -0
  341. package/plugins/document-reader/source/pdf-parser.ts +139 -0
  342. package/plugins/document-reader/source/pdf-process-main.ts +56 -0
  343. package/plugins/document-reader/source/pdf-process.ts +207 -0
  344. package/plugins/document-reader/source/pdf-result.ts +79 -0
  345. package/plugins/document-reader/source/pdf-worker.ts +39 -303
  346. package/plugins/document-reader/source/pdf.ts +4 -1
  347. package/plugins/document-reader/source/read-failure.ts +37 -0
  348. package/plugins/document-reader/source/reader.ts +3 -19
  349. package/plugins/document-reader/src/index.cjs +995 -211
  350. package/plugins/exec/README.md +19 -0
  351. package/plugins/exec/plugin.json +4 -3
  352. package/plugins/exec/skills/exec_skill/SKILL.md +3 -2
  353. package/plugins/exec/source/filesystem-file-observer.ts +98 -0
  354. package/plugins/exec/source/filesystem-observer.ts +8 -79
  355. package/plugins/exec/source/output-files.ts +12 -6
  356. package/plugins/exec/source/paths.ts +3 -1
  357. package/plugins/exec/source/process-manager.ts +8 -24
  358. package/plugins/exec/source/shell-platform.ts +19 -3
  359. package/plugins/exec/source/shell-process.ts +55 -0
  360. package/plugins/exec/source/windows-job-source.ts +1 -0
  361. package/plugins/exec/source/windows-shell-bootstrap.ts +20 -0
  362. package/plugins/exec/src/index.cjs +252 -96
  363. package/plugins/filesystem/README.md +65 -0
  364. package/plugins/filesystem/plugin.json +6 -2
  365. package/plugins/filesystem/source/atomic-write.ts +2 -0
  366. package/plugins/filesystem/source/bounded-io.ts +80 -306
  367. package/plugins/filesystem/source/directory-sample.ts +2 -0
  368. package/plugins/filesystem/source/errors.ts +14 -0
  369. package/plugins/filesystem/source/file-observation.ts +151 -0
  370. package/plugins/filesystem/source/file-version.ts +41 -0
  371. package/plugins/filesystem/source/index.ts +6 -0
  372. package/plugins/filesystem/source/mutation-coordinator.ts +1 -0
  373. package/plugins/filesystem/source/windows/authority-script.ts +1 -0
  374. package/plugins/filesystem/source/windows/native-script.ts +1 -0
  375. package/plugins/filesystem/source/windows/operations.ts +197 -0
  376. package/plugins/filesystem/source/windows/process.ts +214 -0
  377. package/plugins/filesystem/source/windows/publication-script.ts +29 -0
  378. package/plugins/filesystem/source/windows/read-script.ts +63 -0
  379. package/plugins/filesystem/source/windows/request-availability.ts +67 -0
  380. package/plugins/filesystem/source/windows/source.ts +42 -0
  381. package/plugins/filesystem/source/windows/storage-script.ts +11 -0
  382. package/plugins/filesystem/source/windows/streams-script.ts +24 -0
  383. package/plugins/filesystem/source/windows/write-script.ts +86 -0
  384. package/plugins/filesystem/src/index.cjs +1208 -322
  385. package/plugins/json-inspector/README.md +18 -0
  386. package/plugins/json-inspector/plugin.json +1 -0
  387. package/plugins/json-inspector/source/index.ts +16 -19
  388. package/plugins/json-inspector/source/read-failure.ts +42 -0
  389. package/plugins/json-inspector/src/index.cjs +612 -27
  390. package/plugins/local-search/README.md +29 -0
  391. package/plugins/local-search/plugin.json +1 -0
  392. package/plugins/local-search/source/errors.ts +2 -0
  393. package/plugins/local-search/source/paths.ts +3 -0
  394. package/plugins/local-search/source/ripgrep-process.ts +31 -5
  395. package/plugins/local-search/source/ripgrep.ts +3 -3
  396. package/plugins/local-search/source/windows-authority.ts +99 -0
  397. package/plugins/local-search/source/windows-search-lease.ts +49 -0
  398. package/plugins/local-search/source/windows-search-process.ts +91 -0
  399. package/plugins/local-search/source/windows-search-script.ts +52 -0
  400. package/plugins/local-search/src/index.cjs +595 -26
  401. package/plugins/memory/plugin.json +4 -0
  402. package/plugins/memory/source/lock-directory-claim.ts +56 -0
  403. package/plugins/memory/source/lock-owner-file.ts +71 -0
  404. package/plugins/memory/source/lock-path-observation.ts +26 -0
  405. package/plugins/memory/source/prepared-memory-replacement.ts +40 -0
  406. package/plugins/memory/source/store-lock.ts +12 -7
  407. package/plugins/memory/source/store.ts +3 -2
  408. package/plugins/memory/src/index.cjs +174 -25
  409. package/plugins/project-orientation/README.md +23 -0
  410. package/plugins/project-orientation/plugin.json +1 -0
  411. package/plugins/project-orientation/source/index.ts +12 -9
  412. package/plugins/project-orientation/source/inspection-failure.ts +70 -0
  413. package/plugins/project-orientation/source/manifest-summary.ts +9 -2
  414. package/plugins/project-orientation/source/tree.ts +6 -0
  415. package/plugins/project-orientation/src/index.cjs +647 -31
  416. package/plugins/system/README.md +51 -15
  417. package/plugins/system/plugin.json +5 -1
  418. package/plugins/system/skills/system_actions/SKILL.md +1 -1
  419. package/plugins/system/source/command-working-directory.ts +47 -0
  420. package/plugins/system/source/computer/handlers.ts +13 -9
  421. package/plugins/system/source/computer/observation-result.ts +10 -5
  422. package/plugins/system/source/computer/request-computers.ts +10 -3
  423. package/plugins/system/source/computer/request-modules.ts +3 -6
  424. package/plugins/system/source/computer/runtime-platform.ts +18 -0
  425. package/plugins/system/source/host-dispatch.ts +18 -2
  426. package/plugins/system/source/index.ts +5 -3
  427. package/plugins/system/source/local-command-output-retention.ts +16 -0
  428. package/plugins/system/source/local-command-output.ts +16 -8
  429. package/plugins/system/source/request-system-modules.ts +12 -2
  430. package/plugins/system/source/request-target-snapshot.ts +2 -1
  431. package/plugins/system/source/security/desktop-result.ts +177 -0
  432. package/plugins/system/source/security/observed-error.ts +10 -0
  433. package/plugins/system/source/security/secret-text.ts +118 -0
  434. package/plugins/system/source/security/system-results.ts +62 -0
  435. package/plugins/system/source/security/windows-output-directory.ts +82 -0
  436. package/plugins/system/src/index.cjs +837 -151
  437. package/plugins/system-probe/plugin.json +8 -2
  438. package/plugins/system-probe/source/disk-path.ts +8 -0
  439. package/plugins/system-probe/source/index.ts +10 -5
  440. package/plugins/system-probe/source/machine-load.ts +33 -0
  441. package/plugins/system-probe/source/metrics.ts +6 -8
  442. package/plugins/system-probe/src/index.cjs +49 -16
  443. package/plugins/web/plugin.json +4 -0
@@ -0,0 +1,151 @@
1
+ import { constants } from "node:fs";
2
+ import { open, realpath, stat, type FileHandle } from "node:fs/promises";
3
+ import { relative, sep } from "node:path";
4
+ import type { ResolvedRuntimeToolPath } from "../../../src/plugin-sdk/index.js";
5
+ import { fail, rethrowFilesystemError } from "./errors.js";
6
+ import {
7
+ metadataFromStat,
8
+ sameMetadata,
9
+ type MutationFileMetadata,
10
+ } from "./file-version.js";
11
+ import { readWindowsFileSlices } from "./windows/operations.js";
12
+
13
+ type PositionalFileReader = Readonly<{
14
+ read(
15
+ buffer: Buffer,
16
+ offset: number,
17
+ length: number,
18
+ position: number,
19
+ ): Promise<Readonly<{ bytesRead: number }>>;
20
+ }>;
21
+
22
+ export async function readExactBytes(
23
+ reader: PositionalFileReader,
24
+ buffer: Buffer,
25
+ position: number,
26
+ logicalPath: string,
27
+ ): Promise<void> {
28
+ let offset = 0;
29
+ while (offset < buffer.length) {
30
+ const result = await reader.read(
31
+ buffer,
32
+ offset,
33
+ buffer.length - offset,
34
+ position + offset,
35
+ );
36
+ if (result.bytesRead <= 0 || result.bytesRead > buffer.length - offset) {
37
+ fail(
38
+ "filesystem_read_incomplete",
39
+ `File changed or ended before a complete read: ${logicalPath}`,
40
+ );
41
+ }
42
+ offset += result.bytesRead;
43
+ }
44
+ }
45
+
46
+ async function openRegularFile(target: ResolvedRuntimeToolPath): Promise<
47
+ Readonly<{
48
+ handle: FileHandle;
49
+ size: number;
50
+ metadata: MutationFileMetadata;
51
+ }>
52
+ > {
53
+ let handle: FileHandle | undefined;
54
+ try {
55
+ if (typeof constants.O_NOFOLLOW !== "number") {
56
+ fail(
57
+ "filesystem_safe_io_unsupported",
58
+ "This platform does not provide the no-follow operation required for a safe read.",
59
+ );
60
+ }
61
+ handle = await open(
62
+ target.absolutePath,
63
+ constants.O_RDONLY | constants.O_NOFOLLOW,
64
+ );
65
+ const info = await handle.stat({ bigint: true });
66
+ if (!info.isFile()) {
67
+ fail("not_a_file", `Expected a regular file: ${target.logicalPath}`);
68
+ }
69
+ const metadata = metadataFromStat(info, target.logicalPath);
70
+ const [canonicalRoot, canonicalTarget] = await Promise.all([
71
+ realpath(target.rootPath),
72
+ realpath(target.absolutePath),
73
+ ]);
74
+ const rootRelative = relative(canonicalRoot, canonicalTarget);
75
+ if (
76
+ rootRelative === ".." ||
77
+ rootRelative.startsWith(`..${sep}`) ||
78
+ rootRelative.startsWith(sep)
79
+ ) {
80
+ fail(
81
+ "filesystem_path_changed",
82
+ `File changed outside its configured root: ${target.logicalPath}`,
83
+ );
84
+ }
85
+ const pathIdentity = await stat(canonicalTarget, { bigint: true });
86
+ if (
87
+ !pathIdentity.isFile() ||
88
+ pathIdentity.dev !== info.dev ||
89
+ pathIdentity.ino !== info.ino
90
+ ) {
91
+ fail(
92
+ "filesystem_path_changed",
93
+ `File changed while it was being opened: ${target.logicalPath}`,
94
+ );
95
+ }
96
+ return Object.freeze({ handle, size: metadata.size, metadata });
97
+ } catch (error: unknown) {
98
+ await handle?.close().catch(() => undefined);
99
+ rethrowFilesystemError(error, "inspect", target.logicalPath);
100
+ }
101
+ }
102
+
103
+ export async function observeFileSlices(
104
+ target: ResolvedRuntimeToolPath,
105
+ options: Readonly<{
106
+ headBytes: number;
107
+ tailBytes: number;
108
+ maximumFileBytes?: number;
109
+ }>,
110
+ ): Promise<
111
+ Readonly<{ metadata: MutationFileMetadata; head: Buffer; tail: Buffer }>
112
+ > {
113
+ if (process.platform === "win32")
114
+ return readWindowsFileSlices(target, options);
115
+ const file = await openRegularFile(target);
116
+ try {
117
+ if (
118
+ options.maximumFileBytes !== undefined &&
119
+ file.size > options.maximumFileBytes
120
+ )
121
+ fail(
122
+ "file_too_large",
123
+ `File exceeds the mutation byte limit: ${target.logicalPath}`,
124
+ { byteCount: file.size, maxBytes: options.maximumFileBytes },
125
+ );
126
+ const complete = file.size <= options.headBytes + options.tailBytes;
127
+ const head = Buffer.alloc(complete ? file.size : options.headBytes);
128
+ const tail = Buffer.alloc(complete ? 0 : options.tailBytes);
129
+ await readExactBytes(file.handle, head, 0, target.logicalPath);
130
+ await readExactBytes(
131
+ file.handle,
132
+ tail,
133
+ file.size - tail.length,
134
+ target.logicalPath,
135
+ );
136
+ const after = metadataFromStat(
137
+ await file.handle.stat({ bigint: true }),
138
+ target.logicalPath,
139
+ );
140
+ if (!sameMetadata(file.metadata, after))
141
+ fail(
142
+ "filesystem_read_changed",
143
+ `File changed while it was being read: ${target.logicalPath}`,
144
+ );
145
+ return Object.freeze({ metadata: file.metadata, head, tail });
146
+ } catch (error) {
147
+ return rethrowFilesystemError(error, "read", target.logicalPath);
148
+ } finally {
149
+ await file.handle.close().catch(() => undefined);
150
+ }
151
+ }
@@ -0,0 +1,41 @@
1
+ import type { BigIntStats } from "node:fs";
2
+ import { fail } from "./errors.js";
3
+
4
+ export type MutationFileMetadata = Readonly<{
5
+ device: bigint;
6
+ inode: bigint;
7
+ size: number;
8
+ mode: number;
9
+ modifiedNs: bigint;
10
+ changedNs: bigint;
11
+ }>;
12
+
13
+ export function metadataFromStat(
14
+ info: BigIntStats,
15
+ logicalPath: string,
16
+ ): MutationFileMetadata {
17
+ if (info.size > BigInt(Number.MAX_SAFE_INTEGER))
18
+ fail("file_too_large", `File is too large to read safely: ${logicalPath}`);
19
+ return Object.freeze({
20
+ device: info.dev,
21
+ inode: info.ino,
22
+ size: Number(info.size),
23
+ mode: Number(info.mode) & 0o7777,
24
+ modifiedNs: info.mtimeNs,
25
+ changedNs: info.ctimeNs,
26
+ });
27
+ }
28
+
29
+ export function sameMetadata(
30
+ left: MutationFileMetadata,
31
+ right: MutationFileMetadata,
32
+ ): boolean {
33
+ return (
34
+ left.device === right.device &&
35
+ left.inode === right.inode &&
36
+ left.size === right.size &&
37
+ left.mode === right.mode &&
38
+ left.modifiedNs === right.modifiedNs &&
39
+ left.changedNs === right.changedNs
40
+ );
41
+ }
@@ -1,3 +1,4 @@
1
+ import { prepareFilesystemRequest } from "./windows/request-availability.js";
1
2
  import {
2
3
  defineRuntimePlugin,
3
4
  failureFromError,
@@ -27,6 +28,10 @@ function settle(
27
28
  errorCode: error.code,
28
29
  message: error.message,
29
30
  data: error.data,
31
+ ...(error.code === "filesystem_windows_interrupted" &&
32
+ context?.abortSignal?.aborted
33
+ ? { interruption: "aborted" as const }
34
+ : {}),
30
35
  });
31
36
  }
32
37
  return failureFromError(error, {
@@ -42,6 +47,7 @@ export default defineRuntimePlugin((context) => {
42
47
  const paths = createFilesystemPathService(context.runtimePathResolver);
43
48
  const mutations = getProcessFilesystemMutationCoordinator();
44
49
  return Object.freeze({
50
+ prepareRequest: prepareFilesystemRequest,
45
51
  handlers: Object.freeze({
46
52
  dev_view: settle(createDevViewHandler(paths), "dev_view"),
47
53
  edit_file: settle(createEditFileHandler(paths, mutations), "edit_file"),
@@ -10,6 +10,7 @@ function createFilesystemMutationCoordinator(): FilesystemMutationCoordinator {
10
10
  targetKey: string,
11
11
  task: () => Promise<T>,
12
12
  ): Promise<T> {
13
+ if (process.platform === "win32") targetKey = targetKey.toUpperCase();
13
14
  const previous = tails.get(targetKey) ?? Promise.resolve();
14
15
  let release!: () => void;
15
16
  const current = new Promise<void>((resolve) => {
@@ -0,0 +1 @@
1
+ export { WINDOWS_FILESYSTEM_AUTHORITY } from "../../../../src/shared/windows-file-io/authority-script.js";
@@ -0,0 +1 @@
1
+ export { WINDOWS_FILESYSTEM_NATIVE } from "../../../../src/shared/windows-file-io/native-script.js";
@@ -0,0 +1,197 @@
1
+ import { open, type FileHandle } from "node:fs/promises";
2
+ import { win32 } from "node:path";
3
+ import type { ResolvedRuntimeToolPath } from "../../../../src/plugin-sdk/index.js";
4
+ import { fail, rethrowFilesystemError } from "../errors.js";
5
+ import type { MutationFileMetadata } from "../file-version.js";
6
+ import type { MutationTargetVersion } from "../bounded-io.js";
7
+ import { executeWindowsFilesystem } from "./request-availability.js";
8
+
9
+ type NativeMetadata = {
10
+ device: string;
11
+ inode: string;
12
+ size: number;
13
+ mode: number;
14
+ modifiedNs: string;
15
+ changedNs: string;
16
+ };
17
+
18
+ async function withTarget<Result>(
19
+ target: ResolvedRuntimeToolPath,
20
+ run: (
21
+ request: Readonly<Record<string, unknown>>,
22
+ root: FileHandle,
23
+ ) => Promise<Result>,
24
+ ): Promise<Result> {
25
+ const expectedPath = win32.resolve(target.rootPath, target.relativePath);
26
+ if (win32.relative(expectedPath, target.absolutePath) !== "")
27
+ fail(
28
+ "filesystem_path_changed",
29
+ "The resolved file target no longer matches its root.",
30
+ );
31
+ const relative = win32.relative(target.rootPath, expectedPath);
32
+ if (
33
+ win32.isAbsolute(relative) ||
34
+ relative === ".." ||
35
+ relative.startsWith("..\\")
36
+ )
37
+ fail(
38
+ "filesystem_path_changed",
39
+ "The file target is outside its configured root.",
40
+ );
41
+ let root: FileHandle | undefined;
42
+ try {
43
+ root = await open(target.rootPath, "r");
44
+ const identity = await root.stat({ bigint: true });
45
+ if (!identity.isDirectory())
46
+ fail("not_a_directory", "The configured root is not a directory.");
47
+ if (identity.ino <= 0n)
48
+ fail(
49
+ "filesystem_safe_io_unsupported",
50
+ "The configured filesystem does not provide a stable file identity.",
51
+ );
52
+ return await run(
53
+ {
54
+ rootPath: target.rootPath,
55
+ relativePath: target.relativePath,
56
+ rootIdentity: {
57
+ device: String(identity.dev),
58
+ inode: String(identity.ino),
59
+ birthtimeNs: String(identity.birthtimeNs),
60
+ },
61
+ },
62
+ root,
63
+ );
64
+ } catch (error) {
65
+ return rethrowFilesystemError(error, "inspect", target.logicalPath);
66
+ } finally {
67
+ await root?.close().catch(() => undefined);
68
+ }
69
+ }
70
+
71
+ function decodeMetadata(value: NativeMetadata): MutationFileMetadata {
72
+ const validSize = Number.isSafeInteger(value?.size) && value.size >= 0;
73
+ if (!validSize || !Number.isSafeInteger(value?.mode))
74
+ fail(
75
+ "filesystem_windows_response_invalid",
76
+ "The filesystem helper returned invalid file metadata.",
77
+ );
78
+ const fields = [value.device, value.inode, value.modifiedNs, value.changedNs];
79
+ if (
80
+ !fields.every(
81
+ (field) => typeof field === "string" && /^-?\d{1,30}$/u.test(field),
82
+ )
83
+ )
84
+ fail(
85
+ "filesystem_windows_response_invalid",
86
+ "The filesystem helper returned invalid file identity.",
87
+ );
88
+ return Object.freeze({
89
+ device: BigInt(value.device),
90
+ inode: BigInt(value.inode),
91
+ size: value.size,
92
+ mode: value.mode,
93
+ modifiedNs: BigInt(value.modifiedNs),
94
+ changedNs: BigInt(value.changedNs),
95
+ });
96
+ }
97
+
98
+ export async function readWindowsFileSlices(
99
+ target: ResolvedRuntimeToolPath,
100
+ options: Readonly<{
101
+ headBytes: number;
102
+ tailBytes: number;
103
+ maximumFileBytes?: number;
104
+ }>,
105
+ ): Promise<
106
+ Readonly<{ metadata: MutationFileMetadata; head: Buffer; tail: Buffer }>
107
+ > {
108
+ return withTarget(target, async (request) => {
109
+ const result = (await executeWindowsFilesystem({
110
+ ...request,
111
+ operation: "read",
112
+ ...options,
113
+ maximumFileBytes: options.maximumFileBytes ?? 0,
114
+ })) as { metadata: NativeMetadata; head: string; tail: string };
115
+ const metadata = decodeMetadata(result?.metadata);
116
+ if (typeof result.head !== "string" || typeof result.tail !== "string")
117
+ fail(
118
+ "filesystem_windows_response_invalid",
119
+ "The filesystem helper returned invalid file bytes.",
120
+ );
121
+ const head = Buffer.from(result.head, "base64"),
122
+ tail = Buffer.from(result.tail, "base64");
123
+ const complete = metadata.size <= options.headBytes + options.tailBytes;
124
+ const expectedHead = complete ? metadata.size : options.headBytes;
125
+ const expectedTail = complete ? 0 : options.tailBytes;
126
+ if (head.length !== expectedHead || tail.length !== expectedTail)
127
+ fail(
128
+ "filesystem_read_incomplete",
129
+ "The filesystem helper returned incomplete file bytes.",
130
+ );
131
+ return Object.freeze({ metadata, head, tail });
132
+ });
133
+ }
134
+
135
+ export async function sampleWindowsDirectory(
136
+ target: ResolvedRuntimeToolPath,
137
+ maxEntries: number,
138
+ ): Promise<Readonly<{ entries: readonly string[]; truncated: boolean }>> {
139
+ return withTarget(target, async (request) => {
140
+ const result = (await executeWindowsFilesystem({
141
+ ...request,
142
+ operation: "sample",
143
+ maxEntries,
144
+ })) as {
145
+ entries: string[];
146
+ truncated: boolean;
147
+ };
148
+ if (
149
+ !Array.isArray(result?.entries) ||
150
+ result.entries.length > maxEntries ||
151
+ !result.entries.every((entry) => typeof entry === "string") ||
152
+ typeof result.truncated !== "boolean"
153
+ )
154
+ fail(
155
+ "filesystem_windows_response_invalid",
156
+ "The filesystem helper returned an invalid directory sample.",
157
+ );
158
+ return Object.freeze({
159
+ entries: Object.freeze(result.entries.sort((a, b) => a.localeCompare(b))),
160
+ truncated: result.truncated,
161
+ });
162
+ });
163
+ }
164
+
165
+ export async function writeWindowsFile(
166
+ input: Readonly<{
167
+ target: ResolvedRuntimeToolPath;
168
+ content: string;
169
+ expectedVersion: MutationTargetVersion;
170
+ onCommitted?: (root: FileHandle) => void;
171
+ }>,
172
+ ): Promise<void> {
173
+ await withTarget(input.target, async (request, root) => {
174
+ const expected = Object.fromEntries(
175
+ Object.entries(input.expectedVersion).map(([key, value]) => [
176
+ key,
177
+ typeof value === "bigint" ? String(value) : value,
178
+ ]),
179
+ );
180
+ const result = (await executeWindowsFilesystem({
181
+ ...request,
182
+ operation: "write",
183
+ content: Buffer.from(input.content, "utf8").toString("base64"),
184
+ expected,
185
+ })) as { committed?: unknown };
186
+ if (result?.committed !== true)
187
+ fail(
188
+ "filesystem_windows_response_invalid",
189
+ "The filesystem helper did not confirm the write; do not repeat it automatically.",
190
+ );
191
+ try {
192
+ input.onCommitted?.(root);
193
+ } catch {
194
+ /* Presentation cannot undo a committed write. */
195
+ }
196
+ });
197
+ }
@@ -0,0 +1,214 @@
1
+ import { spawn } from "node:child_process";
2
+ import { join } from "node:path";
3
+ import { failNotDirectory, FilesystemToolError, isDirectoryTypeFailure } from "../errors.js";
4
+ import { WINDOWS_FILESYSTEM_SOURCE } from "./source.js";
5
+
6
+ const MAX_MESSAGE_BYTES = 2 * 1024 * 1024;
7
+ const BOOTSTRAP = [
8
+ "$ErrorActionPreference='Stop'",
9
+ 'if ($ExecutionContext.SessionState.LanguageMode -ne \'FullLanguage\') { Write-Output \'{"ok":false,"code":"filesystem_windows_policy_blocked"}\'; exit 0 }',
10
+ "$env:PSModulePath=[IO.Path]::Combine($PSHOME,'Modules')",
11
+ "[Console]::InputEncoding=[Text.UTF8Encoding]::new($false)",
12
+ "[Console]::OutputEncoding=[Text.UTF8Encoding]::new($false)",
13
+ "$started=$false",
14
+ "try {",
15
+ "$envelope=[Console]::In.ReadToEnd() | ConvertFrom-Json",
16
+ "Add-Type -ReferencedAssemblies @('System.Web.Extensions') -TypeDefinition $envelope.source",
17
+ "$started=$true",
18
+ "[Console]::Write([AbotFilesystem]::Run($envelope.request))",
19
+ '} catch { if ($started) { [Console]::Write(\'{"ok":false,"code":"filesystem_windows_operation_unreported"}\') } else { [Console]::Write(\'{"ok":false,"code":"filesystem_windows_helper_unavailable"}\') } }',
20
+ ].join(";");
21
+ const NATIVE_CODES = new Set([
22
+ "file_not_found",
23
+ "file_too_large",
24
+ "not_a_file",
25
+ "not_a_directory",
26
+ "filesystem_access_denied",
27
+ "filesystem_safe_io_unsupported",
28
+ "filesystem_storage_attributes_unsupported",
29
+ "filesystem_named_streams_unsupported",
30
+ "filesystem_windows_publication_unsupported",
31
+ "filesystem_path_changed",
32
+ "filesystem_target_changed",
33
+ "filesystem_invalid_path",
34
+ "filesystem_read_changed",
35
+ "filesystem_read_incomplete",
36
+ "filesystem_invalid_request",
37
+ "filesystem_native_operation_failed",
38
+ "filesystem_windows_policy_blocked",
39
+ "filesystem_windows_helper_unavailable",
40
+ ]);
41
+
42
+ export function isWindowsHelperBlocked(
43
+ error: unknown,
44
+ ): error is FilesystemToolError {
45
+ if (!(error instanceof FilesystemToolError)) return false;
46
+ return (
47
+ error.code === "filesystem_windows_policy_blocked" ||
48
+ error.code === "filesystem_windows_helper_unavailable"
49
+ );
50
+ }
51
+
52
+ function helperFailure(code: string, mutation: boolean): FilesystemToolError {
53
+ if (code === "filesystem_windows_publication_unsupported")
54
+ return new FilesystemToolError(
55
+ code,
56
+ "Windows cannot safely publish this file. Writes require Windows 10 version 1809 or newer and a filesystem supporting hard links, such as NTFS. The destination was left unchanged. Do not retry this write on the same unsupported target.",
57
+ {
58
+ retryable: false,
59
+ blockedBy: "filesystem_publication_support",
60
+ targetUnchanged: true,
61
+ },
62
+ );
63
+ if (code === "filesystem_named_streams_unsupported")
64
+ return new FilesystemToolError(
65
+ code,
66
+ "This file has Windows named data streams, which may include download-origin security information. Editing it is not supported; the original file and its streams were left unchanged. Do not retry this edit or remove the streams to bypass the restriction.",
67
+ {
68
+ retryable: false,
69
+ blockedBy: "file_named_streams",
70
+ targetUnchanged: true,
71
+ },
72
+ );
73
+ if (code === "filesystem_storage_attributes_unsupported")
74
+ return new FilesystemToolError(
75
+ code,
76
+ "This file uses EFS encryption or NTFS compression. Editing it is not supported; the original file was left unchanged. Do not retry this edit or remove its storage attributes to bypass the restriction.",
77
+ {
78
+ retryable: false,
79
+ blockedBy: "file_storage_attributes",
80
+ targetUnchanged: true,
81
+ },
82
+ );
83
+ if (code === "filesystem_windows_policy_blocked")
84
+ return new FilesystemToolError(
85
+ code,
86
+ "Windows policy blocks the filesystem helper. No file operation ran. Retrying cannot resolve this restriction; ask the user to contact their administrator. Do not bypass the restriction.",
87
+ {
88
+ retryable: false,
89
+ blockedBy: "system_policy",
90
+ operationOutcome: "not_started",
91
+ },
92
+ );
93
+ if (code === "filesystem_windows_helper_unavailable")
94
+ return new FilesystemToolError(
95
+ code,
96
+ "The Windows filesystem helper is unavailable. No file operation ran. Do not retry in this request; the user must resolve helper availability first.",
97
+ {
98
+ retryable: false,
99
+ blockedBy: "helper_availability",
100
+ operationOutcome: "not_started",
101
+ },
102
+ );
103
+ return new FilesystemToolError(
104
+ code,
105
+ mutation
106
+ ? "The filesystem helper did not report a completed operation. The file state is unknown; do not repeat the write automatically."
107
+ : "The Windows filesystem helper did not complete the read.",
108
+ {
109
+ retryable: false,
110
+ operationOutcome: mutation ? "unknown" : "not_started",
111
+ },
112
+ );
113
+ }
114
+
115
+ /** One isolated operation. Never changes Windows policy, installs software or retries a write. */
116
+ export async function runWindowsFilesystem(
117
+ request: Readonly<Record<string, unknown>>,
118
+ signal?: AbortSignal,
119
+ spawnProcess: typeof spawn = spawn,
120
+ ): Promise<unknown> {
121
+ const mutation = request.operation === "write";
122
+ if (signal?.aborted)
123
+ throw helperFailure("filesystem_windows_interrupted", false);
124
+ const input = JSON.stringify({
125
+ source: WINDOWS_FILESYSTEM_SOURCE,
126
+ request: JSON.stringify(request),
127
+ });
128
+ if (Buffer.byteLength(input) > MAX_MESSAGE_BYTES)
129
+ throw new FilesystemToolError(
130
+ "filesystem_invalid_request",
131
+ "Filesystem helper input exceeds its byte limit.",
132
+ );
133
+ const executable = join(
134
+ process.env.SystemRoot ?? "C:\\Windows",
135
+ "System32",
136
+ "WindowsPowerShell",
137
+ "v1.0",
138
+ "powershell.exe",
139
+ );
140
+ const raw = await new Promise<string>((resolve, reject) => {
141
+ const child = spawnProcess(
142
+ executable,
143
+ ["-NoLogo", "-NoProfile", "-NonInteractive", "-Command", BOOTSTRAP],
144
+ { windowsHide: true, stdio: ["pipe", "pipe", "pipe"] },
145
+ );
146
+ const chunks: Buffer[] = [];
147
+ let bytes = 0;
148
+ let failure: FilesystemToolError | undefined;
149
+ const stop = (code: string) => {
150
+ failure ??= helperFailure(code, mutation);
151
+ child.kill("SIGKILL");
152
+ };
153
+ const abort = () => stop("filesystem_windows_interrupted");
154
+ const timer = setTimeout(() => stop("filesystem_windows_timeout"), 15_000);
155
+ timer.unref();
156
+ signal?.addEventListener("abort", abort, { once: true });
157
+ child.stdout.on("data", (chunk: Buffer) => {
158
+ bytes += chunk.length;
159
+ if (bytes > MAX_MESSAGE_BYTES) {
160
+ stop("filesystem_windows_output_limit");
161
+ return;
162
+ }
163
+ chunks.push(chunk);
164
+ });
165
+ // Native diagnostics can contain paths or file contents; never return them as tool evidence.
166
+ child.stderr.resume();
167
+ child.stdin.on("error", () => stop("filesystem_windows_transport_failed"));
168
+ child.once("error", () => {
169
+ failure ??=
170
+ child.pid === undefined
171
+ ? helperFailure("filesystem_windows_helper_unavailable", false)
172
+ : helperFailure("filesystem_windows_transport_failed", mutation);
173
+ });
174
+ child.once("close", (code) => {
175
+ clearTimeout(timer);
176
+ signal?.removeEventListener("abort", abort);
177
+ if (failure) {
178
+ reject(failure);
179
+ return;
180
+ }
181
+ if (code !== 0) {
182
+ reject(helperFailure("filesystem_windows_transport_failed", mutation));
183
+ return;
184
+ }
185
+ resolve(Buffer.concat(chunks).toString("utf8"));
186
+ });
187
+ if (signal?.aborted) {
188
+ abort();
189
+ return;
190
+ }
191
+ child.stdin.end(input, "utf8");
192
+ });
193
+ let envelope: { ok?: unknown; result?: unknown; code?: unknown };
194
+ try {
195
+ envelope = JSON.parse(raw) as typeof envelope;
196
+ } catch {
197
+ throw helperFailure("filesystem_windows_response_invalid", mutation);
198
+ }
199
+ if (envelope?.ok === true) return envelope.result;
200
+ const code = typeof envelope?.code === "string" ? envelope.code : "";
201
+ if (!NATIVE_CODES.has(code))
202
+ throw helperFailure("filesystem_windows_response_invalid", mutation);
203
+ if (isDirectoryTypeFailure(code)) failNotDirectory();
204
+ if (
205
+ code === "filesystem_storage_attributes_unsupported" ||
206
+ code === "filesystem_named_streams_unsupported"
207
+ )
208
+ throw helperFailure(code, mutation);
209
+ if (code.startsWith("filesystem_windows_")) throw helperFailure(code, false);
210
+ throw new FilesystemToolError(
211
+ code,
212
+ "The filesystem operation was rejected: " + code + ".",
213
+ );
214
+ }
@@ -0,0 +1,29 @@
1
+ /** Publish the prepared file while its temporary name stays delete-on-close. */
2
+ export const WINDOWS_FILESYSTEM_PUBLICATION = String.raw`
3
+ public static partial class AbotFilesystem {
4
+ static void CheckLinkPublication(int status) {
5
+ if (status >= 0) return;
6
+ uint error=RtlNtStatusToDosError(status);
7
+ if (error == 1 || error == 50 || error == 87)
8
+ throw new FsFault("filesystem_windows_publication_unsupported");
9
+ NativeFailure(error);
10
+ }
11
+ static void PublishLinkRelative(SafeFileHandle file, SafeFileHandle parent, string name, bool replace) {
12
+ byte[] bytes=Encoding.Unicode.GetBytes(name);
13
+ int rootOffset=IntPtr.Size == 8 ? 8 : 4;
14
+ int lengthOffset=rootOffset+IntPtr.Size, nameOffset=lengthOffset+4;
15
+ IntPtr buffer=Marshal.AllocHGlobal(nameOffset+bytes.Length);
16
+ try {
17
+ for (int i=0;i<nameOffset;i++) Marshal.WriteByte(buffer, i, 0);
18
+ // FileLinkInformationEx: replace the destination atomically, retaining
19
+ // existing observations. Closing this handle deletes only its temporary name.
20
+ Marshal.WriteInt32(buffer, 0, replace ? 3 : 0);
21
+ Marshal.WriteIntPtr(buffer, rootOffset, parent.DangerousGetHandle());
22
+ Marshal.WriteInt32(buffer, lengthOffset, bytes.Length);
23
+ Marshal.Copy(bytes, 0, IntPtr.Add(buffer, nameOffset), bytes.Length);
24
+ IoStatus status;
25
+ CheckLinkPublication(NtSetInformationFile(file, out status, buffer, (uint)(nameOffset+bytes.Length), 72));
26
+ } finally { Marshal.FreeHGlobal(buffer); }
27
+ }
28
+ }
29
+ `;