@abot-ai/runtime 1.6.0 → 1.7.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 (380) hide show
  1. package/README.md +2 -0
  2. package/dist/src/bridge/request-steering.js +60 -15
  3. package/dist/src/capabilities/normal-invocation/contracts.d.ts +3 -0
  4. package/dist/src/capabilities/normal-invocation/output-channels.d.ts +10 -0
  5. package/dist/src/capabilities/normal-invocation/output-channels.js +29 -0
  6. package/dist/src/capabilities/normal-invocation/validator.js +4 -2
  7. package/dist/src/capabilities/tool-types.d.ts +1 -1
  8. package/dist/src/cli/host-companion-bundle.mjs +7570 -6781
  9. package/dist/src/cli/host-companion-entry.js +5 -22
  10. package/dist/src/cli/host-companion-input.d.ts +3 -0
  11. package/dist/src/cli/host-companion-input.js +21 -0
  12. package/dist/src/cli/host-companion-lifecycle.d.ts +11 -0
  13. package/dist/src/cli/host-companion-lifecycle.js +32 -0
  14. package/dist/src/cli/host-companion-setup-target.d.ts +4 -0
  15. package/dist/src/cli/host-companion-setup-target.js +17 -0
  16. package/dist/src/cli/host-companion-startup.d.ts +2 -0
  17. package/dist/src/cli/host-companion-startup.js +7 -2
  18. package/dist/src/cli/host-companion.d.ts +6 -0
  19. package/dist/src/cli/host-companion.js +30 -27
  20. package/dist/src/cli/windows-companion-store-entry.d.ts +9 -0
  21. package/dist/src/cli/windows-companion-store-entry.js +67 -0
  22. package/dist/src/computer-access/command-output-capture.d.ts +37 -0
  23. package/dist/src/computer-access/command-output-capture.js +136 -0
  24. package/dist/src/computer-access/command-output-retention.d.ts +5 -0
  25. package/dist/src/computer-access/command-output-retention.js +90 -0
  26. package/dist/src/computer-access/command-output.d.ts +7 -0
  27. package/dist/src/computer-access/command-output.js +1 -0
  28. package/dist/src/computer-access/commands.d.ts +1 -0
  29. package/dist/src/computer-access/commands.js +1 -1
  30. package/dist/src/computer-access/companion/command-output-protocol.d.ts +12 -0
  31. package/dist/src/computer-access/companion/command-output-protocol.js +28 -0
  32. package/dist/src/computer-access/companion/command-output.d.ts +13 -0
  33. package/dist/src/computer-access/companion/command-output.js +110 -0
  34. package/dist/src/computer-access/companion/install-link-macos.d.ts +7 -0
  35. package/dist/src/computer-access/companion/install-link-macos.js +48 -0
  36. package/dist/src/computer-access/companion/install-link-registration.d.ts +4 -0
  37. package/dist/src/computer-access/companion/install-link-registration.js +184 -0
  38. package/dist/src/computer-access/companion/install-link-windows.d.ts +4 -0
  39. package/dist/src/computer-access/companion/install-link-windows.js +65 -0
  40. package/dist/src/computer-access/companion/install-link.d.ts +9 -0
  41. package/dist/src/computer-access/companion/install-link.js +54 -0
  42. package/dist/src/computer-access/companion/native-messages.js +3 -0
  43. package/dist/src/computer-access/companion/native-session.d.ts +1 -0
  44. package/dist/src/computer-access/companion/native-session.js +14 -2
  45. package/dist/src/computer-access/companion/native-supervisor.js +1 -0
  46. package/dist/src/computer-access/companion/notification-windows.d.ts +1 -1
  47. package/dist/src/computer-access/companion/notification-windows.js +8 -3
  48. package/dist/src/computer-access/companion/protocol.d.ts +1 -1
  49. package/dist/src/computer-access/companion/protocol.js +6 -0
  50. package/dist/src/computer-access/companion/release-version.d.ts +1 -1
  51. package/dist/src/computer-access/companion/release-version.js +1 -1
  52. package/dist/src/computer-access/companion/windows-store/connection-error.d.ts +7 -0
  53. package/dist/src/computer-access/companion/windows-store/connection-error.js +19 -0
  54. package/dist/src/computer-access/companion/windows-store/connection-link.d.ts +13 -0
  55. package/dist/src/computer-access/companion/windows-store/connection-link.js +109 -0
  56. package/dist/src/computer-access/companion/windows-store/identity.d.ts +13 -0
  57. package/dist/src/computer-access/companion/windows-store/identity.js +13 -0
  58. package/dist/src/computer-access/companion/windows-store/lifecycle.d.ts +5 -0
  59. package/dist/src/computer-access/companion/windows-store/lifecycle.js +90 -0
  60. package/dist/src/computer-access/contracts.d.ts +1 -1
  61. package/dist/src/computer-access/handlers.d.ts +2 -1
  62. package/dist/src/computer-access/handlers.js +5 -1
  63. package/dist/src/computer-access/process-capture.d.ts +6 -0
  64. package/dist/src/computer-access/process-capture.js +1 -0
  65. package/dist/src/computer-access/process-result.d.ts +2 -0
  66. package/dist/src/computer-access/process-result.js +14 -6
  67. package/dist/src/computer-access/process-runner.d.ts +2 -1
  68. package/dist/src/computer-access/process-runner.js +21 -13
  69. package/dist/src/model-gateway/server/configuration.d.ts +2 -0
  70. package/dist/src/model-gateway/server/configuration.js +73 -21
  71. package/dist/src/plugin-contract/install-source.d.ts +13 -0
  72. package/dist/src/plugin-contract/install-source.js +99 -0
  73. package/dist/src/plugin-contract/manifest.d.ts +2 -1
  74. package/dist/src/plugin-sdk/computer-access.d.ts +8 -0
  75. package/dist/src/plugin-sdk/computer-access.js +5 -0
  76. package/dist/src/runtime/adapters/in-memory-session-store.js +6 -16
  77. package/dist/src/runtime/admin/config-control.js +2 -1
  78. package/dist/src/runtime/automations/catalog.d.ts +3 -0
  79. package/dist/src/runtime/automations/catalog.js +1 -0
  80. package/dist/src/runtime/automations/model-dependency-projection.d.ts +2 -0
  81. package/dist/src/runtime/automations/service.d.ts +2 -0
  82. package/dist/src/runtime/capabilities/automation-builder/authoring-reference.d.ts +10 -5
  83. package/dist/src/runtime/capabilities/automation-builder/authoring-reference.js +8 -7
  84. package/dist/src/runtime/capabilities/automation-builder/payload-instructions.d.ts +2 -2
  85. package/dist/src/runtime/capabilities/automation-builder/payload-instructions.js +2 -2
  86. package/dist/src/runtime/capabilities/automation-builder/tool-contract.d.ts +2 -2
  87. package/dist/src/runtime/capabilities/automations/authoring-catalog.js +1 -1
  88. package/dist/src/runtime/capabilities/automations/authoring-preparation.d.ts +11 -5
  89. package/dist/src/runtime/capabilities/automations/tool-module.js +1 -1
  90. package/dist/src/runtime/capabilities/request-permission-catalog.d.ts +3 -1
  91. package/dist/src/runtime/capabilities/request-permission-catalog.js +21 -2
  92. package/dist/src/runtime/capabilities/request-permission-tool-registry.d.ts +2 -1
  93. package/dist/src/runtime/capabilities/request-permission-tool-registry.js +18 -10
  94. package/dist/src/runtime/capabilities/request-runtime-tool-registry.d.ts +2 -0
  95. package/dist/src/runtime/capabilities/request-runtime-tool-registry.js +1 -1
  96. package/dist/src/runtime/capabilities/scheduling/create-operations.d.ts +6 -0
  97. package/dist/src/runtime/config/builders.js +6 -5
  98. package/dist/src/runtime/config/effective-model-config-validation.js +4 -35
  99. package/dist/src/runtime/config/fields.js +15 -0
  100. package/dist/src/runtime/config/model-context-capacity.d.ts +20 -0
  101. package/dist/src/runtime/config/model-context-capacity.js +55 -0
  102. package/dist/src/runtime/config/model-execution-policy.d.ts +5 -1
  103. package/dist/src/runtime/config/model-execution-policy.js +16 -0
  104. package/dist/src/runtime/config/model-plugin-config.d.ts +8 -0
  105. package/dist/src/runtime/config/model-plugin-config.js +40 -0
  106. package/dist/src/runtime/config/schema.js +5 -1
  107. package/dist/src/runtime/config/validation/model-profile-validation.js +2 -0
  108. package/dist/src/runtime/config/validation/runtime-config-validation-contract.d.ts +3 -1
  109. package/dist/src/runtime/config/validation/runtime-config-validation-contract.js +3 -1
  110. package/dist/src/runtime/config/validation/runtime-root-section-validation.js +11 -4
  111. package/dist/src/runtime/config/validation/web-ui-config-validation.js +3 -2
  112. package/dist/src/runtime/config/web-ui.d.ts +5 -0
  113. package/dist/src/runtime/config/web-ui.js +5 -0
  114. package/dist/src/runtime/config.js +2 -0
  115. package/dist/src/runtime/local-application.d.ts +2 -0
  116. package/dist/src/runtime/local-host/app-owner.js +50 -6
  117. package/dist/src/runtime/local-host/app-request-control.d.ts +3 -1
  118. package/dist/src/runtime/local-host/app-request-control.js +91 -11
  119. package/dist/src/runtime/local-host/client-requests.js +32 -5
  120. package/dist/src/runtime/local-host/client-services.d.ts +2 -0
  121. package/dist/src/runtime/local-host/local-request-diagnostics.d.ts +9 -0
  122. package/dist/src/runtime/local-host/local-request-diagnostics.js +47 -0
  123. package/dist/src/runtime/local-host/saved-approvals.js +23 -2
  124. package/dist/src/runtime/model/model-selection.js +4 -1
  125. package/dist/src/runtime/observability/request-control-diagnostics.d.ts +6 -0
  126. package/dist/src/runtime/observability/request-control-diagnostics.js +52 -0
  127. package/dist/src/runtime/plugins/configuration-context.d.ts +9 -0
  128. package/dist/src/runtime/plugins/configuration-context.js +42 -0
  129. package/dist/src/runtime/plugins/configuration-settings.d.ts +2 -0
  130. package/dist/src/runtime/plugins/configuration-settings.js +26 -0
  131. package/dist/src/runtime/plugins/configuration-store.d.ts +23 -0
  132. package/dist/src/runtime/plugins/configuration-store.js +100 -0
  133. package/dist/src/runtime/plugins/configuration-write.d.ts +5 -0
  134. package/dist/src/runtime/plugins/configuration-write.js +58 -0
  135. package/dist/src/runtime/plugins/installation/archive.d.ts +2 -0
  136. package/dist/src/runtime/plugins/installation/archive.js +107 -0
  137. package/dist/src/runtime/plugins/installation/github-download.d.ts +9 -0
  138. package/dist/src/runtime/plugins/installation/github-download.js +72 -0
  139. package/dist/src/runtime/plugins/installation/installed-package.d.ts +9 -0
  140. package/dist/src/runtime/plugins/installation/installed-package.js +66 -0
  141. package/dist/src/runtime/plugins/installation/package.d.ts +45 -0
  142. package/dist/src/runtime/plugins/installation/package.js +79 -0
  143. package/dist/src/runtime/plugins/installation/portable-path.d.ts +2 -0
  144. package/dist/src/runtime/plugins/installation/portable-path.js +10 -0
  145. package/dist/src/runtime/plugins/installation/publication.d.ts +10 -0
  146. package/dist/src/runtime/plugins/installation/publication.js +17 -0
  147. package/dist/src/runtime/plugins/installation/service.d.ts +41 -0
  148. package/dist/src/runtime/plugins/installation/service.js +80 -0
  149. package/dist/src/runtime/plugins/loader.js +15 -29
  150. package/dist/src/runtime/plugins/manifest-projection.js +1 -0
  151. package/dist/src/runtime/plugins/manifest-validator.js +3 -0
  152. package/dist/src/runtime/plugins/module-cache.d.ts +2 -0
  153. package/dist/src/runtime/plugins/module-cache.js +19 -0
  154. package/dist/src/runtime/plugins/selection.d.ts +2 -0
  155. package/dist/src/runtime/plugins/selection.js +16 -11
  156. package/dist/src/runtime/ports.d.ts +6 -4
  157. package/dist/src/runtime/request/dependencies.d.ts +2 -1
  158. package/dist/src/runtime/request/execution-payload-compacted-evidence.d.ts +1 -1
  159. package/dist/src/runtime/request/handler.js +8 -0
  160. package/dist/src/runtime/request/prepared-execution.js +6 -1
  161. package/dist/src/runtime/request/request-steering.d.ts +4 -0
  162. package/dist/src/runtime/request/request-steering.js +37 -12
  163. package/dist/src/runtime/request/worker-capability-composition.d.ts +2 -0
  164. package/dist/src/runtime/request/worker-capability-composition.js +4 -1
  165. package/dist/src/runtime/scheduler/journal-index-state.d.ts +1 -1
  166. package/dist/src/sessions/assistant-initiative-message.d.ts +3 -0
  167. package/dist/src/sessions/assistant-initiative-message.js +12 -0
  168. package/dist/src/sessions/assistant-initiative.d.ts +2 -2
  169. package/dist/src/sessions/assistant-initiative.js +1 -7
  170. package/dist/src/sessions/durable-session-commit.d.ts +2 -1
  171. package/dist/src/sessions/durable-session-commit.js +6 -1
  172. package/dist/src/sessions/metadata/projection.d.ts +15 -0
  173. package/dist/src/sessions/metadata/projection.js +55 -0
  174. package/dist/src/sessions/metadata/publication.d.ts +12 -0
  175. package/dist/src/sessions/metadata/publication.js +78 -0
  176. package/dist/src/sessions/metadata/source-receipt.d.ts +5 -0
  177. package/dist/src/sessions/metadata/source-receipt.js +42 -0
  178. package/dist/src/sessions/metadata/store.d.ts +7 -0
  179. package/dist/src/sessions/metadata/store.js +119 -0
  180. package/dist/src/sessions/record/projection.d.ts +3 -1
  181. package/dist/src/sessions/record/projection.js +26 -18
  182. package/dist/src/sessions/request-lifecycle/service.js +3 -3
  183. package/dist/src/sessions/session-service.d.ts +2 -4
  184. package/dist/src/sessions/session-service.js +4 -16
  185. package/dist/src/sessions/session-store.d.ts +2 -1
  186. package/dist/src/sessions/session-store.js +9 -3
  187. package/dist/src/sessions/snapshot.d.ts +17 -0
  188. package/dist/src/sessions/snapshot.js +105 -0
  189. package/dist/src/sessions/types.d.ts +2 -0
  190. package/dist/src/shared/tool-selection.d.ts +2 -0
  191. package/dist/src/shared/tool-selection.js +7 -0
  192. package/dist/src/web-ui/app/ARCHITECTURE.md +14 -0
  193. package/dist/src/web-ui/app/app.js +6 -3
  194. package/dist/src/web-ui/app/components/config-workspace/config-model.js +2 -0
  195. package/dist/src/web-ui/app/components/config-workspace/model-plugin-permissions.js +130 -0
  196. package/dist/src/web-ui/app/components/config-workspace/model-plugin-selection.js +180 -0
  197. package/dist/src/web-ui/app/components/config-workspace/model-plugin-view-state.js +114 -0
  198. package/dist/src/web-ui/app/components/config-workspace/model-rendering.js +3 -0
  199. package/dist/src/web-ui/app/components/config-workspace/model-summary.js +39 -0
  200. package/dist/src/web-ui/app/components/config-workspace/summary-rendering.js +30 -0
  201. package/dist/src/web-ui/app/components/config-workspace/workspace-events.js +37 -0
  202. package/dist/src/web-ui/app/components/config-workspace/workspace-mutations.js +2 -0
  203. package/dist/src/web-ui/app/components/config-workspace/workspace-persistence.js +9 -1
  204. package/dist/src/web-ui/app/components/config-workspace/workspace-view.js +23 -67
  205. package/dist/src/web-ui/app/components/config-workspace.js +11 -2
  206. package/dist/src/web-ui/app/components/conversation-view.js +36 -5
  207. package/dist/src/web-ui/app/components/dashboard/recent-conversations.js +2 -1
  208. package/dist/src/web-ui/app/components/dashboard/workspace.js +2 -1
  209. package/dist/src/web-ui/app/components/operations-summary.js +105 -0
  210. package/dist/src/web-ui/app/components/passive-learning/home.js +1 -9
  211. package/dist/src/web-ui/app/components/plugins/configuration-draft.js +34 -0
  212. package/dist/src/web-ui/app/components/plugins/configuration-editor.js +147 -0
  213. package/dist/src/web-ui/app/components/plugins/configuration-fields.js +103 -0
  214. package/dist/src/web-ui/app/components/plugins/configuration-retained-secrets.js +20 -0
  215. package/dist/src/web-ui/app/components/plugins/configuration-settings.js +108 -0
  216. package/dist/src/web-ui/app/components/plugins/discovery-rendering.js +37 -0
  217. package/dist/src/web-ui/app/components/plugins/installation.js +212 -0
  218. package/dist/src/web-ui/app/components/plugins/manager.js +160 -6
  219. package/dist/src/web-ui/app/components/plugins/removal.js +130 -0
  220. package/dist/src/web-ui/app/components/plugins/rendering.js +14 -2
  221. package/dist/src/web-ui/app/components/plugins/summary.js +54 -0
  222. package/dist/src/web-ui/app/components/plugins/tabs.js +31 -0
  223. package/dist/src/web-ui/app/components/plugins/view-state.js +3 -1
  224. package/dist/src/web-ui/app/components/runtime-setup/connection-form.js +5 -2
  225. package/dist/src/web-ui/app/components/runtime-setup/connection-state.js +9 -1
  226. package/dist/src/web-ui/app/components/runtime-setup/context-window-feedback.js +71 -0
  227. package/dist/src/web-ui/app/components/runtime-setup/optional-steps.js +2 -0
  228. package/dist/src/web-ui/app/components/runtime-setup-guide.js +15 -3
  229. package/dist/src/web-ui/app/components/spark-chat/empty-state.js +1 -0
  230. package/dist/src/web-ui/app/components/spark-chat/panel.js +1 -0
  231. package/dist/src/web-ui/app/components/system-host/connection-card.js +35 -0
  232. package/dist/src/web-ui/app/components/system-host/macos-setup.js +1 -1
  233. package/dist/src/web-ui/app/components/system-host/manager.js +45 -12
  234. package/dist/src/web-ui/app/components/system-host/rendering.js +111 -106
  235. package/dist/src/web-ui/app/components/system-host/windows-store-setup.js +293 -0
  236. package/dist/src/web-ui/app/components/workspace-shell.js +6 -0
  237. package/dist/src/web-ui/app/computer-access-feature.js +22 -5
  238. package/dist/src/web-ui/app/configuration-feature.js +35 -2
  239. package/dist/src/web-ui/app/controllers/app-event-bindings.js +4 -1
  240. package/dist/src/web-ui/app/controllers/conversation-read-state-controller.d.ts +1 -0
  241. package/dist/src/web-ui/app/controllers/conversation-read-state-controller.js +7 -3
  242. package/dist/src/web-ui/app/controllers/conversation-request-hydration.js +88 -0
  243. package/dist/src/web-ui/app/controllers/conversation-session-controller.d.ts +9 -3
  244. package/dist/src/web-ui/app/controllers/conversation-session-controller.js +52 -144
  245. package/dist/src/web-ui/app/controllers/history-pagination.js +111 -0
  246. package/dist/src/web-ui/app/controllers/operations-controller.d.ts +12 -0
  247. package/dist/src/web-ui/app/controllers/operations-controller.js +28 -21
  248. package/dist/src/web-ui/app/controllers/runtime-onboarding-controller.d.ts +1 -0
  249. package/dist/src/web-ui/app/controllers/runtime-onboarding-controller.js +11 -0
  250. package/dist/src/web-ui/app/controllers/session-controller.js +10 -2
  251. package/dist/src/web-ui/app/controllers/session-list-pagination.js +71 -0
  252. package/dist/src/web-ui/app/controllers/session-sidebar-controller.js +6 -4
  253. package/dist/src/web-ui/app/controllers/spark-chat-reading.js +1 -0
  254. package/dist/src/web-ui/app/controllers/spark-chat-sync.js +24 -5
  255. package/dist/src/web-ui/app/controllers/workspace-route-controller.js +21 -19
  256. package/dist/src/web-ui/app/dashboard-feature.js +2 -2
  257. package/dist/src/web-ui/app/index.html +6 -2
  258. package/dist/src/web-ui/app/lib/history-page-messages.js +49 -0
  259. package/dist/src/web-ui/app/lib/request-lifecycle-view.js +8 -0
  260. package/dist/src/web-ui/app/lib/workspace-route.d.ts +3 -0
  261. package/dist/src/web-ui/app/lib/workspace-route.js +4 -0
  262. package/dist/src/web-ui/app/passive-learning-feature.js +0 -1
  263. package/dist/src/web-ui/app/runtime-onboarding-feature.js +3 -0
  264. package/dist/src/web-ui/app/schedules-feature.js +1 -1
  265. package/dist/src/web-ui/app/services/runtime-web-client/configuration.js +20 -0
  266. package/dist/src/web-ui/app/services/runtime-web-client/plugin-configuration.js +19 -0
  267. package/dist/src/web-ui/app/services/runtime-web-client/spark-chat.js +4 -4
  268. package/dist/src/web-ui/app/services/runtime-web-client/system-host.js +2 -0
  269. package/dist/src/web-ui/app/services/runtime-web-client.d.ts +6 -1
  270. package/dist/src/web-ui/app/services/runtime-web-client.js +12 -3
  271. package/dist/src/web-ui/app/spark-chat-feature.js +76 -19
  272. package/dist/src/web-ui/app/styles/11-product-links.css +30 -0
  273. package/dist/src/web-ui/app/styles/41-plugin-configuration.css +79 -0
  274. package/dist/src/web-ui/app/styles/41-plugin-discovery.css +132 -0
  275. package/dist/src/web-ui/app/styles/41-plugin-management.css +6 -0
  276. package/dist/src/web-ui/app/styles/42-model-plugin-permissions.css +173 -0
  277. package/dist/src/web-ui/app/styles/46-system-host.css +61 -107
  278. package/dist/src/web-ui/app/styles/47-config-controls.css +13 -1
  279. package/dist/src/web-ui/app/styles/54-spark-chat.css +33 -1
  280. package/dist/src/web-ui/app/styles.css +4 -0
  281. package/dist/src/web-ui/local-runtime/api-router.js +11 -6
  282. package/dist/src/web-ui/local-runtime/approval-request-attachment.js +14 -5
  283. package/dist/src/web-ui/local-runtime/configuration-activation-source.d.ts +1 -1
  284. package/dist/src/web-ui/local-runtime/configuration-activation-source.js +9 -3
  285. package/dist/src/web-ui/local-runtime/contracts.d.ts +4 -3
  286. package/dist/src/web-ui/local-runtime/environment-registry.d.ts +5 -1
  287. package/dist/src/web-ui/local-runtime/environment-registry.js +53 -11
  288. package/dist/src/web-ui/local-runtime/history-pagination.d.ts +16 -0
  289. package/dist/src/web-ui/local-runtime/history-pagination.js +20 -0
  290. package/dist/src/web-ui/local-runtime/plugin-configuration-routes.d.ts +16 -0
  291. package/dist/src/web-ui/local-runtime/plugin-configuration-routes.js +68 -0
  292. package/dist/src/web-ui/local-runtime/plugin-installation-routes.d.ts +16 -0
  293. package/dist/src/web-ui/local-runtime/plugin-installation-routes.js +96 -0
  294. package/dist/src/web-ui/local-runtime/plugin-management-routes.d.ts +8 -1
  295. package/dist/src/web-ui/local-runtime/plugin-management-routes.js +17 -0
  296. package/dist/src/web-ui/local-runtime/plugin-mutation-admission.d.ts +7 -0
  297. package/dist/src/web-ui/local-runtime/plugin-mutation-admission.js +17 -0
  298. package/dist/src/web-ui/local-runtime/plugin-removal-routes.d.ts +18 -0
  299. package/dist/src/web-ui/local-runtime/plugin-removal-routes.js +60 -0
  300. package/dist/src/web-ui/local-runtime/realtime-controller.js +41 -2
  301. package/dist/src/web-ui/local-runtime/request-cancellation-route.js +28 -1
  302. package/dist/src/web-ui/local-runtime/request-control-observation.d.ts +19 -0
  303. package/dist/src/web-ui/local-runtime/request-control-observation.js +80 -0
  304. package/dist/src/web-ui/local-runtime/request-execution.js +69 -37
  305. package/dist/src/web-ui/local-runtime/runtime-setup-context-window.d.ts +20 -0
  306. package/dist/src/web-ui/local-runtime/runtime-setup-context-window.js +44 -0
  307. package/dist/src/web-ui/local-runtime/runtime-setup-routes.js +2 -0
  308. package/dist/src/web-ui/local-runtime/runtime-setup-validation.js +9 -2
  309. package/dist/src/web-ui/local-runtime/session-routes.d.ts +1 -0
  310. package/dist/src/web-ui/local-runtime/session-routes.js +16 -4
  311. package/dist/src/web-ui/local-runtime/spark-chat-routes.js +4 -3
  312. package/dist/src/web-ui/plugin-capability-selection.js +4 -1
  313. package/dist/src/web-ui/plugin-configuration-input.d.ts +12 -0
  314. package/dist/src/web-ui/plugin-configuration-input.js +68 -0
  315. package/dist/src/web-ui/plugin-configuration-retained-secrets.d.ts +9 -0
  316. package/dist/src/web-ui/plugin-configuration-retained-secrets.js +48 -0
  317. package/dist/src/web-ui/plugin-configuration-service.d.ts +52 -0
  318. package/dist/src/web-ui/plugin-configuration-service.js +66 -0
  319. package/dist/src/web-ui/plugin-configuration-view.d.ts +25 -0
  320. package/dist/src/web-ui/plugin-configuration-view.js +45 -0
  321. package/dist/src/web-ui/plugin-disabled-selection.d.ts +7 -0
  322. package/dist/src/web-ui/plugin-disabled-selection.js +17 -0
  323. package/dist/src/web-ui/plugin-management-catalog.d.ts +3 -1
  324. package/dist/src/web-ui/plugin-management-catalog.js +11 -1
  325. package/dist/src/web-ui/plugin-management-selection.js +22 -9
  326. package/dist/src/web-ui/plugin-management-service.d.ts +5 -1
  327. package/dist/src/web-ui/plugin-management-service.js +11 -7
  328. package/dist/src/web-ui/plugin-removal-error.d.ts +7 -0
  329. package/dist/src/web-ui/plugin-removal-error.js +16 -0
  330. package/dist/src/web-ui/plugin-removal-service.d.ts +30 -0
  331. package/dist/src/web-ui/plugin-removal-service.js +109 -0
  332. package/dist/src/web-ui/runtime-setup-gateway.d.ts +6 -2
  333. package/dist/src/web-ui/runtime-setup-gateway.js +30 -10
  334. package/dist/src/web-ui/server.js +6 -2
  335. package/dist/src/web-ui/session-read-state/overview.d.ts +42 -0
  336. package/dist/src/web-ui/session-read-state/overview.js +16 -0
  337. package/dist/src/web-ui/session-read-state/pagination.d.ts +15 -0
  338. package/dist/src/web-ui/session-read-state/pagination.js +42 -0
  339. package/dist/src/web-ui/session-read-state/projection.d.ts +4 -3
  340. package/dist/src/web-ui/session-read-state/service.d.ts +213 -20
  341. package/dist/src/web-ui/session-read-state/service.js +25 -23
  342. package/dist/src/web-ui/session-read-state/visible-messages.d.ts +3 -3
  343. package/dist/src/web-ui/system-host-setup/companion-linux.js +1 -1
  344. package/dist/src/web-ui/system-host-setup/installer-contract.d.ts +1 -1
  345. package/dist/src/web-ui/system-host-setup/installer-contract.js +2 -2
  346. package/dist/src/web-ui/system-host-setup/installers.js +0 -7
  347. package/dist/src/web-ui/system-host-setup/local-connection.d.ts +4 -1
  348. package/dist/src/web-ui/system-host-setup/local-connection.js +10 -17
  349. package/dist/src/web-ui/system-host-setup/routes.d.ts +2 -0
  350. package/dist/src/web-ui/system-host-setup/routes.js +32 -9
  351. package/dist/src/web-ui/system-host-setup/setup-mutation.d.ts +9 -0
  352. package/dist/src/web-ui/system-host-setup/setup-mutation.js +27 -0
  353. package/dist/src/web-ui/system-host-setup/windows-store-route.d.ts +13 -0
  354. package/dist/src/web-ui/system-host-setup/windows-store-route.js +68 -0
  355. package/docs/configuration.md +46 -0
  356. package/docs/installation.md +45 -24
  357. package/docs/plugins.md +165 -2
  358. package/docs/projects-and-full-plus.md +2 -6
  359. package/docs/runtime-library.md +0 -1
  360. package/docs/windows-companion-store.md +127 -0
  361. package/package.json +3 -3
  362. package/plugins/document-reader/plugin.json +1 -0
  363. package/plugins/exec/plugin.json +3 -0
  364. package/plugins/filesystem/plugin.json +2 -0
  365. package/plugins/local-search/plugin.json +1 -0
  366. package/plugins/system/README.md +43 -3
  367. package/plugins/system/plugin.json +5 -0
  368. package/plugins/system/source/companion-command-output.ts +82 -0
  369. package/plugins/system/source/host-dispatch.ts +4 -0
  370. package/plugins/system/source/index.ts +11 -5
  371. package/plugins/system/source/local-command-output.ts +61 -0
  372. package/plugins/system/source/request-system-modules.ts +2 -0
  373. package/plugins/system/src/index.cjs +474 -39
  374. package/plugins/web/README.md +2 -2
  375. package/plugins/web/plugin.json +4 -0
  376. package/runtime.config.schema.json +25 -1
  377. package/src/runtime/README.md +12 -2
  378. package/dist/src/web-ui/system-host-setup/companion-windows.d.ts +0 -2
  379. package/dist/src/web-ui/system-host-setup/companion-windows.js +0 -108
  380. package/docs/publishing.md +0 -167
@@ -0,0 +1,52 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { readFileSync } from "node:fs";
3
+ import { traceDebug } from "./debug-logger.js";
4
+ export { classifyRuntimeErrorType as diagnosticErrorType } from "./error-type.js";
5
+ let fallbackId = 0;
6
+ /** Diagnostic identity only; never used for request admission or ownership. */
7
+ export function createRequestControlDiagnosticId(prefix) {
8
+ try {
9
+ return `${prefix}-${randomUUID()}`;
10
+ }
11
+ catch {
12
+ return `${prefix}-${process.pid}-${Date.now()}-${++fallbackId}`;
13
+ }
14
+ }
15
+ const processInstanceId = createRequestControlDiagnosticId("process");
16
+ let packageIdentity;
17
+ function readPackageIdentity() {
18
+ // Source and compiled layouts. Installed packages do not require a Git checkout.
19
+ for (const relative of [
20
+ "../../../package.json",
21
+ "../../../../package.json",
22
+ ]) {
23
+ try {
24
+ const value = JSON.parse(readFileSync(new URL(relative, import.meta.url), "utf8"));
25
+ if (value.name !== "@abot-ai/runtime")
26
+ continue;
27
+ return {
28
+ runtimeVersion: typeof value.version === "string" ? value.version : "unknown",
29
+ packageRevision: typeof value.gitHead === "string" ? value.gitHead : null,
30
+ };
31
+ }
32
+ catch {
33
+ // Metadata may be absent in an embedded host; it cannot block execution.
34
+ }
35
+ }
36
+ return { runtimeVersion: "unknown", packageRevision: null };
37
+ }
38
+ /** Best-effort, content-free diagnostics must never change a control result. */
39
+ export function traceRequestControl(scope, event, fields = {}) {
40
+ try {
41
+ packageIdentity ??= readPackageIdentity();
42
+ traceDebug(scope, event, {
43
+ ...packageIdentity,
44
+ pid: process.pid,
45
+ processInstanceId,
46
+ ...fields,
47
+ });
48
+ }
49
+ catch {
50
+ // Includes synchronous serialization/console failures; disk writes are best effort.
51
+ }
52
+ }
@@ -0,0 +1,9 @@
1
+ import type { RuntimePluginLoadContext } from "../../plugin-contract/entrypoint.js";
2
+ import type { AbotRuntimePluginExtension } from "../../plugin-contract/manifest.js";
3
+ import type { PluginLocalConfiguration } from "./configuration-store.js";
4
+ export type PluginConfigurationDeclaration = Pick<AbotRuntimePluginExtension, "settings" | "secrets">;
5
+ export declare function effectivePluginSettings(declaration: PluginConfigurationDeclaration, local?: PluginLocalConfiguration): Record<string, unknown>;
6
+ export declare function configuredPluginSecret(name: string, declaration: {
7
+ env: string;
8
+ }, local?: PluginLocalConfiguration): string | undefined;
9
+ export declare function pluginLoadConfiguration(pluginId: string, declaration: PluginConfigurationDeclaration, local?: PluginLocalConfiguration): Pick<RuntimePluginLoadContext, "config" | "secrets">;
@@ -0,0 +1,42 @@
1
+ import { requireRetainedPluginSettingTypes } from "./configuration-settings.js";
2
+ export function effectivePluginSettings(declaration, local) {
3
+ return Object.fromEntries(Object.entries(declaration.settings?.defaults ?? {}).map(([name, fallback]) => [
4
+ name,
5
+ structuredClone(local && Object.hasOwn(local.settings, name)
6
+ ? local.settings[name]
7
+ : fallback),
8
+ ]));
9
+ }
10
+ export function configuredPluginSecret(name, declaration, local) {
11
+ const saved = local?.secrets[name];
12
+ if (saved?.env === declaration.env)
13
+ return saved.value?.trim() ? saved.value : undefined;
14
+ const inherited = process.env[declaration.env];
15
+ return inherited?.trim() ? inherited : undefined;
16
+ }
17
+ export function pluginLoadConfiguration(pluginId, declaration, local) {
18
+ requireRetainedPluginSettingTypes(pluginId, declaration.settings?.defaults ?? {}, local?.settings);
19
+ const declarations = declaration.secrets ?? {};
20
+ for (const [name, secret] of Object.entries(declarations)) {
21
+ if (!secret.required)
22
+ continue;
23
+ if (configuredPluginSecret(name, secret, local))
24
+ continue;
25
+ throw new Error(`Runtime plugin ${pluginId} requires secret ${name} from environment variable ${secret.env}`);
26
+ }
27
+ const secrets = Object.keys(declarations).length
28
+ ? Object.freeze({
29
+ get(name) {
30
+ if (!Object.hasOwn(declarations, name))
31
+ throw new Error(`Runtime plugin ${pluginId} requested undeclared secret ${name}`);
32
+ return configuredPluginSecret(name, declarations[name], local);
33
+ },
34
+ })
35
+ : undefined;
36
+ return {
37
+ ...(declaration.settings
38
+ ? { config: effectivePluginSettings(declaration, local) }
39
+ : {}),
40
+ ...(secrets ? { secrets } : {}),
41
+ };
42
+ }
@@ -0,0 +1,2 @@
1
+ export declare function pluginSettingMatchesDefault(value: unknown, fallback: unknown): boolean;
2
+ export declare function requireRetainedPluginSettingTypes(pluginId: string, defaults: Record<string, unknown>, saved?: Record<string, unknown>): void;
@@ -0,0 +1,26 @@
1
+ import { PluginConfigurationError } from "./configuration-store.js";
2
+ function settingKind(value) {
3
+ if (value === null)
4
+ return "null";
5
+ if (Array.isArray(value))
6
+ return "array";
7
+ return typeof value;
8
+ }
9
+ export function pluginSettingMatchesDefault(value, fallback) {
10
+ if (fallback === null)
11
+ return true; // A null default supplies no type information.
12
+ if (typeof value === "number" && !Number.isFinite(value))
13
+ return false;
14
+ return settingKind(value) === settingKind(fallback);
15
+ }
16
+ export function requireRetainedPluginSettingTypes(pluginId, defaults, saved) {
17
+ if (!saved)
18
+ return;
19
+ for (const [name, fallback] of Object.entries(defaults)) {
20
+ if (!Object.hasOwn(saved, name))
21
+ continue;
22
+ if (pluginSettingMatchesDefault(saved[name], fallback))
23
+ continue;
24
+ throw new PluginConfigurationError("invalid_plugin_configuration", `Saved setting ${name} for plugin ${pluginId} does not match its current default type. Correct it in Plugins before applying.`, 409);
25
+ }
26
+ }
@@ -0,0 +1,23 @@
1
+ export type PluginLocalConfiguration = {
2
+ settings: Record<string, unknown>;
3
+ secrets: Record<string, {
4
+ env: string;
5
+ value: string | null;
6
+ }>;
7
+ };
8
+ export type PluginConfigurationStore = Record<string, PluginLocalConfiguration>;
9
+ export type PluginConfigurationSnapshot = {
10
+ plugins: PluginConfigurationStore;
11
+ raw: string | undefined;
12
+ revision: string;
13
+ };
14
+ export declare const PLUGIN_CONFIGURATION_MAX_BYTES: number;
15
+ export declare class PluginConfigurationError extends Error {
16
+ readonly code: string;
17
+ readonly statusCode: number;
18
+ constructor(code: string, message: string, statusCode?: number);
19
+ }
20
+ export declare function isMissingPluginConfiguration(error: unknown): boolean;
21
+ export declare function pluginConfigurationPath(rootDir: string): string;
22
+ export declare function requirePrivateConfigurationDirectory(rootDir: string): void;
23
+ export declare function readPluginConfigurationStore(rootDir: string): PluginConfigurationSnapshot;
@@ -0,0 +1,100 @@
1
+ import { createHash } from "node:crypto";
2
+ import { lstatSync, readFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { isRecord } from "../config/utils.js";
5
+ export const PLUGIN_CONFIGURATION_MAX_BYTES = 1024 * 1024;
6
+ export class PluginConfigurationError extends Error {
7
+ code;
8
+ statusCode;
9
+ constructor(code, message, statusCode = 400) {
10
+ super(message);
11
+ this.code = code;
12
+ this.statusCode = statusCode;
13
+ }
14
+ }
15
+ export function isMissingPluginConfiguration(error) {
16
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
17
+ }
18
+ export function pluginConfigurationPath(rootDir) {
19
+ return join(rootDir, ".runtime", "plugin-configuration.json");
20
+ }
21
+ export function requirePrivateConfigurationDirectory(rootDir) {
22
+ try {
23
+ const info = lstatSync(join(rootDir, ".runtime"));
24
+ if (info.isDirectory() && !info.isSymbolicLink())
25
+ return;
26
+ }
27
+ catch (error) {
28
+ if (isMissingPluginConfiguration(error))
29
+ return;
30
+ throw error;
31
+ }
32
+ throw new PluginConfigurationError("unsafe_plugin_configuration", "Plugin configuration requires a local directory.", 409);
33
+ }
34
+ function isStoredPluginSecret(value) {
35
+ if (!isRecord(value))
36
+ return false;
37
+ if (typeof value.env !== "string")
38
+ return false;
39
+ return value.value === null || typeof value.value === "string";
40
+ }
41
+ function isStoredPluginConfiguration(value) {
42
+ if (!isRecord(value))
43
+ return false;
44
+ if (!isRecord(value.settings))
45
+ return false;
46
+ if (!isRecord(value.secrets))
47
+ return false;
48
+ return Object.values(value.secrets).every(isStoredPluginSecret);
49
+ }
50
+ function parsePluginConfigurationStore(raw) {
51
+ if (raw === undefined)
52
+ return {};
53
+ try {
54
+ const value = JSON.parse(raw);
55
+ if (!isRecord(value))
56
+ throw new Error();
57
+ if (value.version !== 1)
58
+ throw new Error();
59
+ if (!isRecord(value.plugins))
60
+ throw new Error();
61
+ if (!Object.values(value.plugins).every(isStoredPluginConfiguration))
62
+ throw new Error();
63
+ return value.plugins;
64
+ }
65
+ catch {
66
+ throw new PluginConfigurationError("invalid_plugin_configuration_file", "The local plugin configuration file could not be read.", 409);
67
+ }
68
+ }
69
+ function requirePrivatePluginConfigurationPermissions(mode) {
70
+ if (process.platform === "win32")
71
+ return;
72
+ if ((mode & 0o077) === 0)
73
+ return;
74
+ throw new PluginConfigurationError("unsafe_plugin_configuration", "Plugin configuration permissions are too open. Run chmod 600 on .runtime/plugin-configuration.json before retrying.", 409);
75
+ }
76
+ export function readPluginConfigurationStore(rootDir) {
77
+ requirePrivateConfigurationDirectory(rootDir);
78
+ let raw;
79
+ try {
80
+ const path = pluginConfigurationPath(rootDir);
81
+ const info = lstatSync(path);
82
+ if (!info.isFile() || info.isSymbolicLink())
83
+ throw new PluginConfigurationError("unsafe_plugin_configuration", "Plugin configuration must be a regular local file.", 409);
84
+ requirePrivatePluginConfigurationPermissions(info.mode);
85
+ if (info.size > PLUGIN_CONFIGURATION_MAX_BYTES)
86
+ throw new PluginConfigurationError("plugin_configuration_too_large", "The local plugin configuration file is too large.", 409);
87
+ raw = readFileSync(path, "utf8");
88
+ }
89
+ catch (error) {
90
+ if (!isMissingPluginConfiguration(error))
91
+ throw error;
92
+ }
93
+ return {
94
+ plugins: parsePluginConfigurationStore(raw),
95
+ raw,
96
+ revision: createHash("sha256")
97
+ .update(raw === undefined ? "missing" : `present:${raw}`)
98
+ .digest("hex"),
99
+ };
100
+ }
@@ -0,0 +1,5 @@
1
+ import { type PluginConfigurationSnapshot, type PluginConfigurationStore } from "./configuration-store.js";
2
+ /** Writers and Apply take the Runtime config lock before this installation-wide lock. */
3
+ export declare function withPluginConfigurationLock<T>(rootDir: string, operation: () => Promise<T>): Promise<T>;
4
+ /** Caller holds the installation-wide lock through commit and any restoration. */
5
+ export declare function commitPluginConfigurationStore<T>(rootDir: string, previous: PluginConfigurationSnapshot, plugins: PluginConfigurationStore, commit: () => Promise<T>): Promise<T>;
@@ -0,0 +1,58 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { chmod, mkdir, realpath, rename, rm, writeFile, } from "node:fs/promises";
3
+ import { dirname } from "node:path";
4
+ import { withFileLock } from "../adapters/long-term-memory/file-lock.js";
5
+ import { PLUGIN_CONFIGURATION_MAX_BYTES, PluginConfigurationError, pluginConfigurationPath, readPluginConfigurationStore, requirePrivateConfigurationDirectory, } from "./configuration-store.js";
6
+ /** Writers and Apply take the Runtime config lock before this installation-wide lock. */
7
+ export async function withPluginConfigurationLock(rootDir, operation) {
8
+ const root = await realpath(rootDir);
9
+ requirePrivateConfigurationDirectory(root);
10
+ const path = pluginConfigurationPath(root);
11
+ await mkdir(dirname(path), { recursive: true, mode: 0o700 });
12
+ requirePrivateConfigurationDirectory(root);
13
+ return withFileLock(`${path}.lock`, operation, {
14
+ waitMs: Number.POSITIVE_INFINITY,
15
+ });
16
+ }
17
+ function requireUnchangedPluginConfiguration(rootDir, expected) {
18
+ if (readPluginConfigurationStore(rootDir).raw === expected)
19
+ return;
20
+ throw new PluginConfigurationError("plugin_configuration_changed", "Plugin configuration changed. Reload the form before saving.", 409);
21
+ }
22
+ async function replacePluginConfiguration(rootDir, expected, next) {
23
+ const path = pluginConfigurationPath(rootDir);
24
+ requireUnchangedPluginConfiguration(rootDir, expected);
25
+ if (next === undefined) {
26
+ await rm(path);
27
+ return;
28
+ }
29
+ const temporary = `${path}.${randomUUID()}.tmp`;
30
+ try {
31
+ await writeFile(temporary, next, { flag: "wx", mode: 0o600 });
32
+ await chmod(temporary, 0o600);
33
+ requireUnchangedPluginConfiguration(rootDir, expected);
34
+ await rename(temporary, path);
35
+ }
36
+ finally {
37
+ await rm(temporary, { force: true });
38
+ }
39
+ }
40
+ /** Caller holds the installation-wide lock through commit and any restoration. */
41
+ export async function commitPluginConfigurationStore(rootDir, previous, plugins, commit) {
42
+ const next = JSON.stringify({ version: 1, plugins }, null, 2) + "\n";
43
+ if (Buffer.byteLength(next) > PLUGIN_CONFIGURATION_MAX_BYTES)
44
+ throw new PluginConfigurationError("plugin_configuration_too_large", "Plugin configuration is too large.");
45
+ await replacePluginConfiguration(rootDir, previous.raw, next);
46
+ try {
47
+ return await commit();
48
+ }
49
+ catch (error) {
50
+ try {
51
+ await replacePluginConfiguration(rootDir, next, previous.raw);
52
+ }
53
+ catch (restoreError) {
54
+ throw new AggregateError([error, restoreError], "Plugin configuration could not be restored after a failed save.");
55
+ }
56
+ throw error;
57
+ }
58
+ }
@@ -0,0 +1,2 @@
1
+ /** Expand only regular files. Nothing from the repository is executed. */
2
+ export declare function extractPluginArchive(archive: Buffer, destination: string, subdirectory?: string): Promise<string>;
@@ -0,0 +1,107 @@
1
+ import { createHash } from "node:crypto";
2
+ import { mkdir, writeFile } from "node:fs/promises";
3
+ import { dirname, join } from "node:path";
4
+ import JSZip from "jszip";
5
+ import { isPortablePluginPathComponent } from "./portable-path.js";
6
+ import { Readable } from "node:stream";
7
+ import { PluginInstallError } from "../../../plugin-contract/install-source.js";
8
+ function rejectArchive(message) {
9
+ throw new PluginInstallError("plugin_archive_invalid", message);
10
+ }
11
+ function requireArchivePath(name) {
12
+ if (name.length > 1024 || /[\\\u0000-\u001f\u007f:]/u.test(name))
13
+ return rejectArchive("The archive contains an unsupported path.");
14
+ const parts = name.replace(/\/$/u, "").split("/");
15
+ if (parts.some((part) => !part || part === "." || part === ".."))
16
+ return rejectArchive("The archive contains an unsafe path.");
17
+ if (!parts.every(isPortablePluginPathComponent))
18
+ return rejectArchive("The archive contains a non-portable file name.");
19
+ return parts;
20
+ }
21
+ async function boundedEntry(entry, remaining) {
22
+ const stream = new Readable().wrap(entry.nodeStream());
23
+ const chunks = [];
24
+ let size = 0;
25
+ try {
26
+ for await (const chunk of stream) {
27
+ const bytes = Buffer.from(chunk);
28
+ size += bytes.length;
29
+ if (size > Math.min(16 * 1024 * 1024, remaining))
30
+ return rejectArchive("The expanded plugin exceeds its size limit.");
31
+ chunks.push(bytes);
32
+ }
33
+ return Buffer.concat(chunks);
34
+ }
35
+ finally {
36
+ stream.destroy();
37
+ }
38
+ }
39
+ /** Expand only regular files. Nothing from the repository is executed. */
40
+ export async function extractPluginArchive(archive, destination, subdirectory = "") {
41
+ if (archive.length > 25 * 1024 * 1024)
42
+ return rejectArchive("The repository archive is too large.");
43
+ let zip;
44
+ try {
45
+ zip = await JSZip.loadAsync(archive, { createFolders: false });
46
+ }
47
+ catch {
48
+ return rejectArchive("The repository did not contain a valid ZIP archive.");
49
+ }
50
+ const entries = Object.values(zip.files);
51
+ if (entries.length > 2000)
52
+ return rejectArchive("The repository contains too many files.");
53
+ const roots = new Set();
54
+ const seen = new Set();
55
+ const hash = createHash("sha256");
56
+ let total = 0;
57
+ let written = 0;
58
+ const prefix = subdirectory ? subdirectory + "/" : "";
59
+ for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name, "en"))) {
60
+ const original = entry
61
+ .unsafeOriginalName ?? entry.name;
62
+ const parts = requireArchivePath(original);
63
+ if (original !== entry.name)
64
+ return rejectArchive("The archive contains a rewritten path.");
65
+ roots.add(parts[0]);
66
+ if (roots.size !== 1)
67
+ return rejectArchive("The archive must have one repository root.");
68
+ const mode = typeof entry.unixPermissions === "number" ? entry.unixPermissions : 0;
69
+ const kind = mode & 0o170000;
70
+ if (kind && kind !== 0o100000 && kind !== 0o040000)
71
+ return rejectArchive("Plugin archives cannot contain links or special files.");
72
+ if (entry.dir)
73
+ continue;
74
+ if (kind === 0o040000)
75
+ return rejectArchive("The archive has inconsistent file types.");
76
+ const relative = parts.slice(1).join("/");
77
+ if (!relative.startsWith(prefix))
78
+ continue;
79
+ const target = relative.slice(prefix.length);
80
+ if (!target)
81
+ return rejectArchive("The plugin path must select a directory.");
82
+ if (target.split("/").includes(".git"))
83
+ return rejectArchive("Plugin packages cannot contain Git metadata.");
84
+ const identity = target.toLowerCase();
85
+ if (seen.has(identity))
86
+ return rejectArchive("The archive contains conflicting file names.");
87
+ seen.add(identity);
88
+ const bytes = await boundedEntry(entry, 64 * 1024 * 1024 - total);
89
+ total += bytes.length;
90
+ const path = join(destination, target);
91
+ await mkdir(dirname(path), { recursive: true, mode: 0o700 });
92
+ await writeFile(path, bytes, {
93
+ flag: "wx",
94
+ mode: mode & 0o111 ? 0o700 : 0o600,
95
+ });
96
+ hash
97
+ .update(target)
98
+ .update("\0")
99
+ .update(String(bytes.length))
100
+ .update("\0")
101
+ .update(bytes);
102
+ written += 1;
103
+ }
104
+ if (!written)
105
+ return rejectArchive("No plugin files were found in the selected folder.");
106
+ return hash.digest("hex");
107
+ }
@@ -0,0 +1,9 @@
1
+ import { type PluginInstallSource } from "../../../plugin-contract/install-source.js";
2
+ export type PluginDownload = Readonly<{
3
+ source: PluginInstallSource & {
4
+ ref: string;
5
+ };
6
+ archive: Buffer;
7
+ }>;
8
+ export type PluginSourceFetcher = (input: PluginInstallSource) => Promise<PluginDownload>;
9
+ export declare const downloadGitHubPlugin: PluginSourceFetcher;
@@ -0,0 +1,72 @@
1
+ import { PluginInstallError, parsePluginInstallSource, } from "../../../plugin-contract/install-source.js";
2
+ const ARCHIVE_LIMIT = 25 * 1024 * 1024;
3
+ async function readBoundedResponse(response, maximum) {
4
+ if (!response.ok) {
5
+ await response.body?.cancel();
6
+ throw new PluginInstallError("plugin_download_failed", "GitHub could not provide this public repository or revision.", 502);
7
+ }
8
+ if (Number(response.headers.get("content-length") ?? 0) > maximum) {
9
+ await response.body?.cancel();
10
+ throw new PluginInstallError("plugin_download_limit", "The repository archive is too large.");
11
+ }
12
+ if (!response.body)
13
+ throw new PluginInstallError("plugin_download_failed", "GitHub returned no content.", 502);
14
+ const reader = response.body.getReader();
15
+ const chunks = [];
16
+ let length = 0;
17
+ try {
18
+ while (true) {
19
+ const part = await reader.read();
20
+ if (part.done)
21
+ break;
22
+ length += part.value.byteLength;
23
+ if (length > maximum)
24
+ throw new PluginInstallError("plugin_download_limit", "The repository archive is too large.");
25
+ chunks.push(Buffer.from(part.value));
26
+ }
27
+ return Buffer.concat(chunks);
28
+ }
29
+ finally {
30
+ await reader.cancel().catch(() => { });
31
+ reader.releaseLock();
32
+ }
33
+ }
34
+ export const downloadGitHubPlugin = async (input) => {
35
+ const source = parsePluginInstallSource(input);
36
+ const repository = new URL(source.repository).pathname.slice(1);
37
+ const signal = AbortSignal.timeout(60_000);
38
+ try {
39
+ let ref = source.ref;
40
+ if (!ref) {
41
+ const response = await fetch(`https://api.github.com/repos/${repository}`, {
42
+ headers: { accept: "application/vnd.github+json" },
43
+ redirect: "error",
44
+ signal,
45
+ });
46
+ const metadata = JSON.parse((await readBoundedResponse(response, 256 * 1024)).toString("utf8"));
47
+ if (typeof metadata.default_branch !== "string")
48
+ throw new Error("missing_branch");
49
+ ref = metadata.default_branch;
50
+ }
51
+ const response = await fetch(`https://api.github.com/repos/${repository}/commits/${encodeURIComponent(ref)}`, {
52
+ headers: { accept: "application/vnd.github+json" },
53
+ redirect: "error",
54
+ signal,
55
+ });
56
+ const commit = JSON.parse((await readBoundedResponse(response, 2 * 1024 * 1024)).toString("utf8"));
57
+ if (typeof commit.sha !== "string" || !/^[a-f0-9]{40}$/u.test(commit.sha))
58
+ throw new Error("invalid_commit");
59
+ if (/^[a-f0-9]{40}$/u.test(ref) && commit.sha !== ref)
60
+ throw new Error("commit_mismatch");
61
+ const archiveResponse = await fetch(`https://codeload.github.com/${repository}/zip/${commit.sha}`, { redirect: "error", signal });
62
+ return {
63
+ source: { ...source, ref: commit.sha },
64
+ archive: await readBoundedResponse(archiveResponse, ARCHIVE_LIMIT),
65
+ };
66
+ }
67
+ catch (error) {
68
+ if (error instanceof PluginInstallError)
69
+ throw error;
70
+ throw new PluginInstallError("plugin_download_failed", "The GitHub download failed or timed out. Check the repository and revision.", 502);
71
+ }
72
+ };
@@ -0,0 +1,9 @@
1
+ import type { DiscoveredAgentPluginManifest } from "../discovered-manifest.js";
2
+ /** Stable package identity also works after moving it outside the discovery directory. */
3
+ export declare function installedPluginPackageIdentity(path: string): string | undefined;
4
+ /** Only installer-owned, direct consumer folders are removable. Never follow links. */
5
+ export declare function installedPluginPackage(rootDir: string, plugin: DiscoveredAgentPluginManifest): {
6
+ path: string;
7
+ identity: string;
8
+ packageIdentity: string;
9
+ } | undefined;
@@ -0,0 +1,66 @@
1
+ import { lstatSync, readFileSync, realpathSync } from "node:fs";
2
+ import { join, resolve } from "node:path";
3
+ import { parsePluginInstallSource } from "../../../plugin-contract/install-source.js";
4
+ import { isPortablePluginPathComponent } from "./portable-path.js";
5
+ /** Stable package identity also works after moving it outside the discovery directory. */
6
+ export function installedPluginPackageIdentity(path) {
7
+ try {
8
+ const folder = lstatSync(path);
9
+ const receiptPath = join(path, ".abot-install.json");
10
+ const receiptStat = lstatSync(receiptPath);
11
+ if (!folder.isDirectory() ||
12
+ !receiptStat.isFile() ||
13
+ receiptStat.size > 4096)
14
+ return undefined;
15
+ const receipt = JSON.parse(readFileSync(receiptPath, "utf8"));
16
+ if (receipt.schemaVersion !== 1 ||
17
+ typeof receipt.digest !== "string" ||
18
+ !/^[a-f0-9]{64}$/u.test(receipt.digest) ||
19
+ typeof receipt.installedAt !== "string" ||
20
+ !Number.isFinite(Date.parse(receipt.installedAt)))
21
+ return undefined;
22
+ const source = parsePluginInstallSource(receipt.source);
23
+ if (!source.ref || !/^[a-f0-9]{40}$/u.test(source.ref))
24
+ return undefined;
25
+ const manifestPath = join(path, "plugin.json");
26
+ const manifestStat = lstatSync(manifestPath);
27
+ if (!manifestStat.isFile())
28
+ return undefined;
29
+ return JSON.stringify([
30
+ folder.dev,
31
+ folder.ino,
32
+ folder.birthtimeMs,
33
+ receipt,
34
+ readFileSync(manifestPath, "utf8"),
35
+ ]);
36
+ }
37
+ catch {
38
+ return undefined;
39
+ }
40
+ }
41
+ /** Only installer-owned, direct consumer folders are removable. Never follow links. */
42
+ export function installedPluginPackage(rootDir, plugin) {
43
+ const id = plugin.manifest.name;
44
+ if (!isPortablePluginPathComponent(id))
45
+ return undefined;
46
+ try {
47
+ const directory = join(realpathSync(rootDir), "plugins");
48
+ const path = join(directory, id);
49
+ if (resolve(plugin.pluginRoot) !== path)
50
+ return undefined;
51
+ const parent = lstatSync(directory);
52
+ if (!parent.isDirectory())
53
+ return undefined;
54
+ const packageIdentity = installedPluginPackageIdentity(path);
55
+ if (!packageIdentity)
56
+ return undefined;
57
+ return {
58
+ path,
59
+ packageIdentity,
60
+ identity: JSON.stringify([parent.dev, parent.ino, packageIdentity]),
61
+ };
62
+ }
63
+ catch {
64
+ return undefined;
65
+ }
66
+ }
@@ -0,0 +1,45 @@
1
+ import { type PluginInstallSource } from "../../../plugin-contract/install-source.js";
2
+ import { ABOT_RUNTIME_EXTENSION } from "../../../plugin-contract/manifest.js";
3
+ import { type PluginSourceFetcher } from "./github-download.js";
4
+ export declare function preparePluginPackage(rootDir: string, source: PluginInstallSource, download?: PluginSourceFetcher): Promise<{
5
+ staging: string;
6
+ manifest: Readonly<{
7
+ $schema: typeof import("../../../plugin-contract/manifest.js").AGENT_PLUGIN_MANIFEST_SCHEMA;
8
+ name: string;
9
+ version?: string;
10
+ description?: string;
11
+ extensions: Readonly<{
12
+ [ABOT_RUNTIME_EXTENSION]: import("../../../plugin-contract/manifest.js").AbotRuntimePluginExtension;
13
+ [namespace: string]: unknown;
14
+ }>;
15
+ }>;
16
+ review: {
17
+ source: Readonly<{
18
+ repository: string;
19
+ ref?: string;
20
+ path?: string;
21
+ }> & {
22
+ ref: string;
23
+ };
24
+ digest: string;
25
+ id: string;
26
+ version: string;
27
+ description: string;
28
+ capabilities: {
29
+ id: string;
30
+ description: string;
31
+ operations: {
32
+ name: string;
33
+ effect: import("../../../capabilities/tool-types.js").ToolNormalInvocationEffect;
34
+ approval: import("../../../capabilities/tool-types.js").ToolNormalInvocationApproval;
35
+ }[];
36
+ }[];
37
+ settings: Readonly<Record<string, unknown>>;
38
+ secrets: {
39
+ name: string;
40
+ env: string;
41
+ required: boolean;
42
+ }[];
43
+ };
44
+ }>;
45
+ export declare function requireNewPluginIdentity(rootDir: string, id: string, capabilityIds: readonly string[]): void;