@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
@@ -4,6 +4,10 @@
4
4
  "version": "0.1.0",
5
5
  "description": "Inspect and mutate files under the configured agent work directory and workspace roots.",
6
6
  "extensions": {
7
+ "ai.abot.compatibility": {
8
+ "version": 1,
9
+ "runtimePlatforms": ["linux", "darwin", "win32"]
10
+ },
7
11
  "ai.abot.runtime": {
8
12
  "version": 1,
9
13
  "entrypoint": "./src/index.cjs",
@@ -215,7 +219,7 @@
215
219
  },
216
220
  "write_file": {
217
221
  "catalogGroups": ["write"],
218
- "description": "Create one new file or perform an explicitly requested intentional full-file replacement. Use when the complete desired file is already known, especially for new or nearly empty files. Do not choose write_file for an ordinary addition or change to an existing file when an active existing-target editor can preserve current content. For an explicit existing-file replacement, inspect the complete current file first; prior conversation summaries do not count as current file content. Selection uses only the target path; runtime collects the raw file body over a separate payload channel.",
222
+ "description": "Write a file at the complete path, including its filename; missing parent directories are created automatically. For an empty directory, use an available SYSTEM or EXEC command tool. Use for a new file or explicitly requested full-file replacement whose complete content is known. Ordinary changes to an existing file belong to an available existing-target editor. Before full replacement, inspect the entire current file; conversation summaries are not current file content. Select only the path; the raw file body is authored separately.",
219
223
  "routingCapability": "filesystem_mutation",
220
224
  "controlsRefinement": "mechanical_when_complete",
221
225
  "developmentRoles": ["establish", "mutate"],
@@ -246,7 +250,7 @@
246
250
  "skills": [],
247
251
  "operations": {
248
252
  "write_complete_file": {
249
- "summary": "Create a new file via a separate complete raw-text payload. Paths use the runtime-host namespace; relative paths use the call's working directory under the request's agent work root. Path syntax does not select a SYSTEM OS target. Establish source artifacts before consumers in a connected Worker call; bounded successful artifacts reach later payloads. Existing files require explicit full replacement; use edit_existing_file for ordinary edits. Do not create unrequested adjacent artifacts.",
253
+ "summary": "Write one file via separate complete raw payload; path includes its filename. Missing parents are auto-created; use an available SYSTEM or EXEC command for an empty directory. Paths use the runtime host; relative paths use call cwd under the agent work root, not a SYSTEM OS target. Establish sources before consumers in a Worker call; bounded successful artifacts reach later payloads. Existing files need explicit full replacement; use edit_existing_file for ordinary edits. No unrequested adjacent artifacts.",
250
254
  "input": {
251
255
  "type": "object",
252
256
  "additionalProperties": false,
@@ -1,3 +1,4 @@
1
+ import { writeWindowsFile } from "./windows/operations.js";
1
2
  import { randomUUID } from "node:crypto";
2
3
  import { link, open, rename, rm, type FileHandle } from "node:fs/promises";
3
4
  import { posix } from "node:path";
@@ -23,6 +24,7 @@ export async function atomicWriteText(
23
24
  }>,
24
25
  ): Promise<void> {
25
26
  assertMutationContentSize(input.content);
27
+ if (process.platform === "win32") return writeWindowsFile(input);
26
28
  if (requiresIsolatedDirectoryAuthority()) {
27
29
  await writeWithDirectoryAuthority(input);
28
30
  return;
@@ -1,22 +1,20 @@
1
1
  import { createHash } from "node:crypto";
2
- import { constants, type BigIntStats } from "node:fs";
3
- import { open, realpath, stat, type FileHandle } from "node:fs/promises";
4
- import { relative, sep } from "node:path";
5
2
  import { StringDecoder } from "node:string_decoder";
6
3
  import { TextDecoder } from "node:util";
7
-
8
4
  import type { ResolvedRuntimeToolPath } from "../../../src/plugin-sdk/index.js";
9
-
10
5
  import { fail, FilesystemToolError, rethrowFilesystemError } from "./errors.js";
6
+ import { observeFileSlices } from "./file-observation.js";
7
+ import { sameMetadata, type MutationFileMetadata } from "./file-version.js";
11
8
 
12
- export const MAX_MUTATION_BYTES = 1_048_576;
13
- export const READ_HEAD_BYTES = 24_576;
14
- export const READ_TAIL_BYTES = 12_288;
15
- export const DEV_SCAN_BYTES = 1_048_576;
9
+ export { readExactBytes } from "./file-observation.js";
16
10
  export {
17
11
  readDirectorySample,
18
12
  DIRECTORY_ENTRY_LIMIT,
19
13
  } from "./directory-sample.js";
14
+ export const MAX_MUTATION_BYTES = 1_048_576;
15
+ export const READ_HEAD_BYTES = 24_576;
16
+ export const READ_TAIL_BYTES = 12_288;
17
+ export const DEV_SCAN_BYTES = 1_048_576;
20
18
 
21
19
  export type BoundedText = Readonly<{
22
20
  text: string;
@@ -25,73 +23,23 @@ export type BoundedText = Readonly<{
25
23
  omittedBytes: number;
26
24
  truncated: boolean;
27
25
  }>;
28
-
29
- type MutationFileMetadata = Readonly<{
30
- device: bigint;
31
- inode: bigint;
32
- size: number;
33
- mode: number;
34
- modifiedNs: bigint;
35
- changedNs: bigint;
36
- }>;
37
-
38
26
  export type MutationTargetVersion =
39
27
  | Readonly<{ kind: "absent" }>
40
28
  | Readonly<MutationFileMetadata & { kind: "file"; digest: string }>;
41
-
42
29
  export type MutationSnapshot = Readonly<{
43
30
  content: string | null;
44
31
  version: MutationTargetVersion;
45
32
  }>;
46
33
 
47
- type PositionalFileReader = Readonly<{
48
- read(
49
- buffer: Buffer,
50
- offset: number,
51
- length: number,
52
- position: number,
53
- ): Promise<Readonly<{ bytesRead: number }>>;
54
- }>;
55
-
56
- export async function readExactBytes(
57
- reader: PositionalFileReader,
58
- buffer: Buffer,
59
- position: number,
60
- logicalPath: string,
61
- ): Promise<void> {
62
- let offset = 0;
63
- while (offset < buffer.length) {
64
- const result = await reader.read(
65
- buffer,
66
- offset,
67
- buffer.length - offset,
68
- position + offset,
69
- );
70
- if (result.bytesRead <= 0 || result.bytesRead > buffer.length - offset) {
71
- fail(
72
- "filesystem_read_incomplete",
73
- `File changed or ended before a complete read: ${logicalPath}`,
74
- );
75
- }
76
- offset += result.bytesRead;
77
- }
78
- }
79
-
80
34
  function decodeCompletePrefix(buffer: Buffer): string {
81
35
  return new StringDecoder("utf8").write(buffer);
82
36
  }
83
-
84
37
  function decodeSuffix(buffer: Buffer): string {
85
38
  let start = 0;
86
- while (
87
- start < Math.min(4, buffer.length) &&
88
- (buffer[start]! & 0xc0) === 0x80
89
- ) {
39
+ while (start < Math.min(4, buffer.length) && (buffer[start]! & 0xc0) === 0x80)
90
40
  start += 1;
91
- }
92
41
  return buffer.subarray(start).toString("utf8");
93
42
  }
94
-
95
43
  function decodeMutationText(buffer: Buffer, logicalPath: string): string {
96
44
  try {
97
45
  return new TextDecoder("utf-8", { fatal: true }).decode(buffer);
@@ -103,191 +51,83 @@ function decodeMutationText(buffer: Buffer, logicalPath: string): string {
103
51
  }
104
52
  }
105
53
 
106
- async function openRegularFile(target: ResolvedRuntimeToolPath): Promise<
107
- Readonly<{
108
- handle: FileHandle;
109
- size: number;
110
- metadata: MutationFileMetadata;
111
- }>
112
- > {
113
- let handle: FileHandle | undefined;
114
- try {
115
- if (typeof constants.O_NOFOLLOW !== "number") {
116
- fail(
117
- "filesystem_safe_io_unsupported",
118
- "This platform does not provide the no-follow operation required for a safe read.",
119
- );
120
- }
121
- handle = await open(
122
- target.absolutePath,
123
- constants.O_RDONLY | constants.O_NOFOLLOW,
124
- );
125
- const info = await handle.stat({ bigint: true });
126
- if (!info.isFile()) {
127
- fail("not_a_file", `Expected a regular file: ${target.logicalPath}`);
128
- }
129
- const metadata = metadataFromStat(info, target.logicalPath);
130
- const [canonicalRoot, canonicalTarget] = await Promise.all([
131
- realpath(target.rootPath),
132
- realpath(target.absolutePath),
133
- ]);
134
- const rootRelative = relative(canonicalRoot, canonicalTarget);
135
- if (
136
- rootRelative === ".." ||
137
- rootRelative.startsWith(`..${sep}`) ||
138
- rootRelative.startsWith(sep)
139
- ) {
140
- fail(
141
- "filesystem_path_changed",
142
- `File changed outside its configured root: ${target.logicalPath}`,
143
- );
144
- }
145
- const pathIdentity = await stat(canonicalTarget, { bigint: true });
146
- if (
147
- !pathIdentity.isFile() ||
148
- pathIdentity.dev !== info.dev ||
149
- pathIdentity.ino !== info.ino
150
- ) {
151
- fail(
152
- "filesystem_path_changed",
153
- `File changed while it was being opened: ${target.logicalPath}`,
154
- );
155
- }
156
- return Object.freeze({ handle, size: metadata.size, metadata });
157
- } catch (error: unknown) {
158
- await handle?.close().catch(() => undefined);
159
- rethrowFilesystemError(error, "inspect", target.logicalPath);
160
- }
161
- }
162
-
163
54
  export async function readBoundedText(
164
55
  target: ResolvedRuntimeToolPath,
165
- options: Readonly<{
166
- headBytes?: number;
167
- tailBytes?: number;
168
- }> = {},
56
+ options: Readonly<{ headBytes?: number; tailBytes?: number }> = {},
169
57
  ): Promise<BoundedText> {
170
- const file = await openRegularFile(target);
171
- const headBytes = options.headBytes ?? READ_HEAD_BYTES;
172
- const tailBytes = options.tailBytes ?? READ_TAIL_BYTES;
173
- const byteBudget = headBytes + tailBytes;
174
- try {
175
- if (file.size <= byteBudget) {
176
- const buffer = Buffer.alloc(file.size);
177
- await readExactBytes(file.handle, buffer, 0, target.logicalPath);
178
- await assertFileStable(file, target.logicalPath);
179
- rejectBinary(buffer, target.logicalPath);
180
- return Object.freeze({
181
- text: decodeCompletePrefix(buffer),
182
- byteCount: file.size,
183
- bytesRead: file.size,
184
- omittedBytes: 0,
185
- truncated: false,
186
- });
187
- }
188
- const head = Buffer.alloc(headBytes);
189
- const tail = Buffer.alloc(tailBytes);
190
- await Promise.all([
191
- readExactBytes(file.handle, head, 0, target.logicalPath),
192
- readExactBytes(
193
- file.handle,
194
- tail,
195
- Math.max(0, file.size - tailBytes),
196
- target.logicalPath,
197
- ),
198
- ]);
199
- await assertFileStable(file, target.logicalPath);
200
- rejectBinary(head, target.logicalPath);
201
- rejectBinary(tail, target.logicalPath);
202
- const omittedBytes = Math.max(0, file.size - head.length - tail.length);
203
- return Object.freeze({
204
- text: [
205
- decodeCompletePrefix(head),
206
- `[${omittedBytes} bytes omitted from the middle]`,
207
- decodeSuffix(tail),
208
- ].join("\n"),
209
- byteCount: file.size,
210
- bytesRead: head.length + tail.length,
211
- omittedBytes,
212
- truncated: true,
213
- });
214
- } catch (error: unknown) {
215
- return rethrowFilesystemError(error, "read", target.logicalPath);
216
- } finally {
217
- await file.handle.close().catch(() => undefined);
218
- }
58
+ const observed = await observeFileSlices(target, {
59
+ headBytes: options.headBytes ?? READ_HEAD_BYTES,
60
+ tailBytes: options.tailBytes ?? READ_TAIL_BYTES,
61
+ });
62
+ rejectBinary(observed.head, target.logicalPath);
63
+ rejectBinary(observed.tail, target.logicalPath);
64
+ const bytesRead = observed.head.length + observed.tail.length;
65
+ const omittedBytes = observed.metadata.size - bytesRead;
66
+ const text =
67
+ omittedBytes === 0
68
+ ? decodeCompletePrefix(observed.head)
69
+ : [
70
+ decodeCompletePrefix(observed.head),
71
+ `[${omittedBytes} bytes omitted from the middle]`,
72
+ decodeSuffix(observed.tail),
73
+ ].join("\n");
74
+ return Object.freeze({
75
+ text,
76
+ byteCount: observed.metadata.size,
77
+ bytesRead,
78
+ omittedBytes,
79
+ truncated: omittedBytes > 0,
80
+ });
219
81
  }
220
82
 
221
83
  export async function readPrefixText(
222
84
  target: ResolvedRuntimeToolPath,
223
85
  maxBytes: number = DEV_SCAN_BYTES,
224
86
  ): Promise<BoundedText> {
225
- const file = await openRegularFile(target);
226
- try {
227
- const length = Math.min(file.size, maxBytes);
228
- const buffer = Buffer.alloc(length);
229
- await readExactBytes(file.handle, buffer, 0, target.logicalPath);
230
- await assertFileStable(file, target.logicalPath);
231
- rejectBinary(buffer, target.logicalPath);
232
- return Object.freeze({
233
- text: decodeCompletePrefix(buffer),
234
- byteCount: file.size,
235
- bytesRead: length,
236
- omittedBytes: Math.max(0, file.size - length),
237
- truncated: length < file.size,
238
- });
239
- } catch (error: unknown) {
240
- rethrowFilesystemError(error, "read", target.logicalPath);
241
- } finally {
242
- await file.handle.close().catch(() => undefined);
243
- }
87
+ const observed = await observeFileSlices(target, {
88
+ headBytes: maxBytes,
89
+ tailBytes: 0,
90
+ });
91
+ rejectBinary(observed.head, target.logicalPath);
92
+ return Object.freeze({
93
+ text: decodeCompletePrefix(observed.head),
94
+ byteCount: observed.metadata.size,
95
+ bytesRead: observed.head.length,
96
+ omittedBytes: observed.metadata.size - observed.head.length,
97
+ truncated: observed.head.length < observed.metadata.size,
98
+ });
244
99
  }
245
100
 
246
101
  export async function readMutationSnapshot(
247
102
  target: ResolvedRuntimeToolPath,
248
103
  ): Promise<MutationSnapshot> {
249
- let file: Awaited<ReturnType<typeof openRegularFile>> | undefined;
250
104
  try {
251
- file = await openRegularFile(target);
252
- const byteCount = file.size;
253
- if (byteCount > MAX_MUTATION_BYTES) {
254
- fail(
255
- "file_too_large",
256
- `File exceeds the ${MAX_MUTATION_BYTES}-byte mutation limit: ${target.logicalPath}`,
257
- { byteCount, maxBytes: MAX_MUTATION_BYTES },
258
- );
259
- }
260
- const buffer = Buffer.alloc(byteCount);
261
- await readExactBytes(file.handle, buffer, 0, target.logicalPath);
262
- const afterRead = metadataFromStat(
263
- await file.handle.stat({ bigint: true }),
264
- target.logicalPath,
265
- );
266
- if (!sameMetadata(file.metadata, afterRead)) {
267
- failTargetChanged(target.logicalPath, "file", "file");
268
- }
269
- rejectBinary(buffer, target.logicalPath);
105
+ const observed = await observeFileSlices(target, {
106
+ headBytes: MAX_MUTATION_BYTES,
107
+ tailBytes: 0,
108
+ maximumFileBytes: MAX_MUTATION_BYTES,
109
+ });
110
+ rejectBinary(observed.head, target.logicalPath);
270
111
  return Object.freeze({
271
- content: decodeMutationText(buffer, target.logicalPath),
112
+ content: decodeMutationText(observed.head, target.logicalPath),
272
113
  version: Object.freeze({
273
114
  kind: "file",
274
- ...file.metadata,
275
- digest: digest(buffer),
115
+ ...observed.metadata,
116
+ digest: digest(observed.head),
276
117
  }),
277
118
  });
278
- } catch (error: unknown) {
279
- if (
280
- error instanceof FilesystemToolError &&
281
- error.code === "file_not_found"
282
- ) {
119
+ } catch (error) {
120
+ if (error instanceof FilesystemToolError && error.code === "file_not_found")
283
121
  return Object.freeze({
284
122
  content: null,
285
123
  version: Object.freeze({ kind: "absent" }),
286
124
  });
287
- }
125
+ if (
126
+ error instanceof FilesystemToolError &&
127
+ error.code === "filesystem_read_changed"
128
+ )
129
+ failTargetChanged(target.logicalPath, "file", "file");
288
130
  return rethrowFilesystemError(error, "read", target.logicalPath);
289
- } finally {
290
- await file?.handle.close().catch(() => undefined);
291
131
  }
292
132
  }
293
133
 
@@ -295,44 +135,29 @@ export async function assertMutationTargetUnchanged(
295
135
  target: ResolvedRuntimeToolPath,
296
136
  expected: MutationTargetVersion,
297
137
  ): Promise<void> {
298
- let file: Awaited<ReturnType<typeof openRegularFile>> | undefined;
138
+ let current: MutationSnapshot;
299
139
  try {
300
- file = await openRegularFile(target);
301
- } catch (error: unknown) {
302
- if (
140
+ current = await readMutationSnapshot(target);
141
+ } catch (error) {
142
+ const changedContents =
303
143
  error instanceof FilesystemToolError &&
304
- error.code === "file_not_found"
305
- ) {
306
- if (expected.kind === "absent") return;
307
- failTargetChanged(target.logicalPath, expected.kind, "absent");
308
- }
144
+ [
145
+ "file_too_large",
146
+ "binary_file_unsupported",
147
+ "filesystem_invalid_encoding",
148
+ ].includes(error.code);
149
+ if (changedContents)
150
+ failTargetChanged(target.logicalPath, expected.kind, "file");
309
151
  throw error;
310
152
  }
311
-
312
- try {
313
- if (expected.kind === "absent") {
314
- failTargetChanged(target.logicalPath, "absent", "file");
315
- }
316
- if (!sameMetadata(expected, file.metadata)) {
317
- failTargetChanged(target.logicalPath, "file", "file");
318
- }
319
- const buffer = Buffer.alloc(file.size);
320
- await readExactBytes(file.handle, buffer, 0, target.logicalPath);
321
- const afterRead = metadataFromStat(
322
- await file.handle.stat({ bigint: true }),
323
- target.logicalPath,
324
- );
325
- if (
326
- !sameMetadata(file.metadata, afterRead) ||
327
- digest(buffer) !== expected.digest
328
- ) {
329
- failTargetChanged(target.logicalPath, "file", "file");
330
- }
331
- } catch (error: unknown) {
332
- return rethrowFilesystemError(error, "inspect", target.logicalPath);
333
- } finally {
334
- await file.handle.close().catch(() => undefined);
335
- }
153
+ if (current.version.kind !== expected.kind)
154
+ failTargetChanged(target.logicalPath, expected.kind, current.version.kind);
155
+ if (current.version.kind === "absent" || expected.kind === "absent") return;
156
+ if (
157
+ !sameMetadata(expected, current.version) ||
158
+ expected.digest !== current.version.digest
159
+ )
160
+ failTargetChanged(target.logicalPath, "file", "file");
336
161
  }
337
162
 
338
163
  export function assertMutationContentSize(content: string): number {
@@ -346,67 +171,16 @@ export function assertMutationContentSize(content: string): number {
346
171
  }
347
172
  return byteCount;
348
173
  }
349
-
350
174
  function rejectBinary(buffer: Buffer, logicalPath: string): void {
351
- if (buffer.includes(0)) {
175
+ if (buffer.includes(0))
352
176
  fail(
353
177
  "binary_file_unsupported",
354
178
  `Binary file is not supported: ${logicalPath}`,
355
179
  );
356
- }
357
- }
358
-
359
- function metadataFromStat(
360
- info: BigIntStats,
361
- logicalPath: string,
362
- ): MutationFileMetadata {
363
- if (info.size > BigInt(Number.MAX_SAFE_INTEGER)) {
364
- fail("file_too_large", `File is too large to read safely: ${logicalPath}`);
365
- }
366
- return Object.freeze({
367
- device: info.dev,
368
- inode: info.ino,
369
- size: Number(info.size),
370
- mode: Number(info.mode) & 0o7777,
371
- modifiedNs: info.mtimeNs,
372
- changedNs: info.ctimeNs,
373
- });
374
- }
375
-
376
- function sameMetadata(
377
- left: MutationFileMetadata,
378
- right: MutationFileMetadata,
379
- ): boolean {
380
- return (
381
- left.device === right.device &&
382
- left.inode === right.inode &&
383
- left.size === right.size &&
384
- left.mode === right.mode &&
385
- left.modifiedNs === right.modifiedNs &&
386
- left.changedNs === right.changedNs
387
- );
388
- }
389
-
390
- async function assertFileStable(
391
- file: Readonly<{ handle: FileHandle; metadata: MutationFileMetadata }>,
392
- logicalPath: string,
393
- ): Promise<void> {
394
- const afterRead = metadataFromStat(
395
- await file.handle.stat({ bigint: true }),
396
- logicalPath,
397
- );
398
- if (!sameMetadata(file.metadata, afterRead)) {
399
- fail(
400
- "filesystem_read_changed",
401
- `File changed while it was being read: ${logicalPath}`,
402
- );
403
- }
404
180
  }
405
-
406
181
  function digest(buffer: Buffer): string {
407
182
  return createHash("sha256").update(buffer).digest("hex");
408
183
  }
409
-
410
184
  function failTargetChanged(
411
185
  logicalPath: string,
412
186
  expectedState: MutationTargetVersion["kind"],
@@ -1,3 +1,4 @@
1
+ import { sampleWindowsDirectory } from "./windows/operations.js";
1
2
  import { constants, type BigIntStats } from "node:fs";
2
3
  import {
3
4
  open,
@@ -20,6 +21,7 @@ export const DIRECTORY_ENTRY_LIMIT = 160;
20
21
  export async function readDirectorySample(
21
22
  target: ResolvedRuntimeToolPath,
22
23
  ): Promise<Readonly<{ entries: readonly string[]; truncated: boolean }>> {
24
+ if (process.platform === "win32") return sampleWindowsDirectory(target, DIRECTORY_ENTRY_LIMIT);
23
25
  const entries: string[] = [];
24
26
  let handle: FileHandle | undefined;
25
27
  try {
@@ -34,6 +34,17 @@ export function isNodeErrorCode(error: unknown, code: string): boolean {
34
34
  );
35
35
  }
36
36
 
37
+ export function isDirectoryTypeFailure(code: unknown): boolean {
38
+ return code === "not_a_directory" || code === "ENOTDIR";
39
+ }
40
+
41
+ export function failNotDirectory(): never {
42
+ fail(
43
+ "not_a_directory",
44
+ "A component of the requested path is not a directory. An existing file cannot contain child files. Inspect the path and choose a file target under a directory; do not repeat the same operation unchanged or overwrite the blocking file to turn it into a directory.",
45
+ );
46
+ }
47
+
37
48
  export function rethrowFilesystemError(
38
49
  error: unknown,
39
50
  operation: "inspect" | "read" | "write",
@@ -45,6 +56,9 @@ export function rethrowFilesystemError(
45
56
  if (isNodeErrorCode(error, "ENOENT")) {
46
57
  fail("file_not_found", `Path does not exist: ${logicalPath}`);
47
58
  }
59
+ if (error instanceof Error && isDirectoryTypeFailure((error as NodeError).code)) {
60
+ failNotDirectory();
61
+ }
48
62
  if (isNodeErrorCode(error, "EACCES") || isNodeErrorCode(error, "EPERM")) {
49
63
  fail(
50
64
  "filesystem_access_denied",