@agentorg/cli 0.0.4 → 0.0.6

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 (206) hide show
  1. package/README.md +18 -102
  2. package/dist/node_modules/@agentorg/hub/dist/src/hub-actor.d.ts +2 -7
  3. package/dist/node_modules/@agentorg/hub/dist/src/hub-actor.js +4 -111
  4. package/dist/node_modules/@agentorg/hub/dist/src/index.d.ts +1 -3
  5. package/dist/node_modules/@agentorg/hub/dist/src/index.js +1 -3
  6. package/dist/node_modules/@agentorg/hub/dist/src/router.d.ts +6 -57
  7. package/dist/node_modules/@agentorg/hub/dist/src/router.js +38 -413
  8. package/dist/node_modules/@agentorg/hub/dist/src/state.d.ts +20 -298
  9. package/dist/node_modules/@agentorg/hub/dist/src/state.js +73 -456
  10. package/dist/node_modules/@agentorg/hub/dist/src/validate.d.ts +1 -3
  11. package/dist/node_modules/@agentorg/hub/dist/src/validate.js +3 -15
  12. package/dist/node_modules/@agentorg/hub/package.json +0 -3
  13. package/dist/node_modules/@agentorg/interfaces/dist/src/agent-provider.d.ts +132 -0
  14. package/dist/node_modules/@agentorg/interfaces/dist/src/agent-provider.js +105 -0
  15. package/dist/node_modules/@agentorg/interfaces/dist/src/agent-settings.d.ts +42 -0
  16. package/dist/node_modules/@agentorg/interfaces/dist/src/agent-settings.js +53 -0
  17. package/dist/node_modules/@agentorg/interfaces/dist/src/chat.d.ts +15 -0
  18. package/dist/node_modules/@agentorg/interfaces/dist/src/chat.js +14 -0
  19. package/dist/node_modules/@agentorg/interfaces/dist/src/hub.d.ts +16 -267
  20. package/dist/node_modules/@agentorg/interfaces/dist/src/hub.js +17 -145
  21. package/dist/node_modules/@agentorg/interfaces/dist/src/index.d.ts +6 -8
  22. package/dist/node_modules/@agentorg/interfaces/dist/src/index.js +6 -8
  23. package/dist/node_modules/@agentorg/interfaces/dist/src/kv.d.ts +2 -2
  24. package/dist/node_modules/@agentorg/interfaces/dist/src/kv.js +2 -2
  25. package/dist/node_modules/@agentorg/interfaces/dist/src/manager.d.ts +272 -0
  26. package/dist/node_modules/@agentorg/interfaces/dist/src/manager.js +185 -0
  27. package/dist/node_modules/@agentorg/interfaces/dist/src/mcp-provider.d.ts +88 -0
  28. package/dist/node_modules/@agentorg/interfaces/dist/src/mcp-provider.js +78 -0
  29. package/dist/node_modules/@agentorg/interfaces/dist/src/tools.d.ts +39 -0
  30. package/dist/node_modules/@agentorg/interfaces/dist/src/tools.js +43 -0
  31. package/dist/node_modules/@agentorg/manager/dist/src/index.d.ts +1 -0
  32. package/dist/node_modules/@agentorg/manager/dist/src/index.js +1 -0
  33. package/dist/node_modules/@agentorg/manager/dist/src/manager.d.ts +21 -0
  34. package/dist/node_modules/@agentorg/manager/dist/src/manager.js +528 -0
  35. package/dist/node_modules/@agentorg/manager/dist/src/skills.d.ts +25 -0
  36. package/dist/node_modules/@agentorg/manager/dist/src/skills.js +145 -0
  37. package/dist/node_modules/@agentorg/manager/package.json +30 -0
  38. package/dist/node_modules/@agentorg/mcp/dist/src/connection.d.ts +33 -0
  39. package/dist/node_modules/@agentorg/mcp/dist/src/connection.js +290 -0
  40. package/dist/node_modules/@agentorg/mcp/dist/src/index.d.ts +1 -0
  41. package/dist/node_modules/@agentorg/mcp/dist/src/index.js +1 -0
  42. package/dist/node_modules/@agentorg/mcp/dist/src/kinds.d.ts +50 -0
  43. package/dist/node_modules/@agentorg/mcp/dist/src/kinds.js +69 -0
  44. package/dist/node_modules/@agentorg/mcp/dist/src/provider.d.ts +22 -0
  45. package/dist/node_modules/@agentorg/mcp/dist/src/provider.js +167 -0
  46. package/dist/node_modules/@agentorg/mcp/package.json +31 -0
  47. package/dist/node_modules/@agentorg/sdk/dist/src/cli.js +3 -23
  48. package/dist/node_modules/@agentorg/sdk/dist/src/client.d.ts +4 -25
  49. package/dist/node_modules/@agentorg/sdk/dist/src/client.js +5 -55
  50. package/dist/node_modules/@agentorg/sdk/dist/src/errors.d.ts +1 -1
  51. package/dist/node_modules/@agentorg/sdk/dist/src/errors.js +3 -3
  52. package/dist/node_modules/@agentorg/sdk/dist/src/index.d.ts +2 -2
  53. package/dist/node_modules/@agentorg/sdk/dist/src/index.js +1 -1
  54. package/dist/node_modules/@agentorg/sdk/dist/src/interface.d.ts +6 -34
  55. package/dist/node_modules/@agentorg/sdk/dist/src/interface.js +3 -24
  56. package/dist/node_modules/@agentorg/sdk/dist/src/module-host.d.ts +8 -17
  57. package/dist/node_modules/@agentorg/sdk/dist/src/module-host.js +15 -87
  58. package/dist/node_modules/@agentorg/sdk/dist/src/module.d.ts +10 -76
  59. package/dist/node_modules/@agentorg/sdk/dist/src/module.js +3 -23
  60. package/dist/node_modules/@agentorg/sdk/dist/src/person-commands.js +0 -5
  61. package/dist/node_modules/@agentorg/sdk/dist/src/runtime.d.ts +3 -27
  62. package/dist/node_modules/@agentorg/sdk/dist/src/runtime.js +5 -100
  63. package/dist/node_modules/@agentorg/sdk/dist/src/testing.d.ts +7 -8
  64. package/dist/node_modules/@agentorg/sdk/dist/src/testing.js +12 -24
  65. package/dist/node_modules/@agentorg/sdk/package.json +4 -37
  66. package/dist/node_modules/@agentorg/shell/dist/app.css +3435 -739
  67. package/dist/node_modules/@agentorg/shell/dist/app.js +204 -202
  68. package/dist/node_modules/@agentorg/shell/package.json +18 -10
  69. package/dist/node_modules/@agentorg/wire/dist/src/frames.d.ts +2 -3
  70. package/dist/node_modules/@agentorg/wire/dist/src/frames.js +2 -3
  71. package/dist/node_modules/@agentorg/wire/dist/src/ops.d.ts +5 -34
  72. package/dist/node_modules/@agentorg/wire/dist/src/ops.js +2 -17
  73. package/dist/node_modules/assistant/dist/src/agent.d.ts +62 -0
  74. package/dist/node_modules/assistant/dist/src/agent.js +226 -0
  75. package/dist/node_modules/assistant/dist/src/engine.d.ts +23 -0
  76. package/dist/node_modules/assistant/dist/src/engine.js +88 -0
  77. package/dist/node_modules/assistant/dist/src/history.d.ts +97 -0
  78. package/dist/node_modules/assistant/dist/src/history.js +235 -0
  79. package/dist/node_modules/assistant/dist/src/local-store.d.ts +3 -0
  80. package/dist/node_modules/assistant/dist/src/local-store.js +58 -0
  81. package/dist/node_modules/assistant/dist/src/provider.d.ts +21 -0
  82. package/dist/node_modules/assistant/dist/src/provider.js +231 -0
  83. package/dist/node_modules/assistant/dist/src/settings.d.ts +17 -0
  84. package/dist/node_modules/assistant/dist/src/settings.js +43 -0
  85. package/dist/node_modules/assistant/dist/src/tools.d.ts +74 -0
  86. package/dist/node_modules/assistant/dist/src/tools.js +123 -0
  87. package/dist/node_modules/assistant/package.json +29 -0
  88. package/dist/node_modules/chatgpt/dist/src/account.d.ts +52 -0
  89. package/dist/node_modules/chatgpt/dist/src/account.js +270 -0
  90. package/dist/node_modules/chatgpt/dist/src/encoding.d.ts +7 -0
  91. package/dist/node_modules/chatgpt/dist/src/encoding.js +20 -0
  92. package/dist/node_modules/chatgpt/dist/src/file-store.d.ts +9 -0
  93. package/dist/node_modules/chatgpt/dist/src/file-store.js +68 -0
  94. package/dist/node_modules/chatgpt/dist/src/index.d.ts +1 -0
  95. package/dist/node_modules/chatgpt/dist/src/index.js +1 -0
  96. package/dist/node_modules/chatgpt/dist/src/jwt.d.ts +15 -0
  97. package/dist/node_modules/chatgpt/dist/src/jwt.js +37 -0
  98. package/dist/node_modules/chatgpt/dist/src/oauth.d.ts +43 -0
  99. package/dist/node_modules/chatgpt/dist/src/oauth.js +104 -0
  100. package/dist/node_modules/chatgpt/dist/src/program.d.ts +23 -0
  101. package/dist/node_modules/chatgpt/dist/src/program.js +41 -0
  102. package/dist/node_modules/chatgpt/dist/src/responses.d.ts +54 -0
  103. package/dist/node_modules/chatgpt/dist/src/responses.js +300 -0
  104. package/dist/node_modules/chatgpt/dist/src/serve.d.ts +65 -0
  105. package/dist/node_modules/chatgpt/dist/src/serve.js +46 -0
  106. package/dist/node_modules/chatgpt/package.json +33 -0
  107. package/dist/src/api.d.ts +5 -34
  108. package/dist/src/api.js +6 -68
  109. package/dist/src/cli.js +3 -7
  110. package/dist/src/gateway.d.ts +6 -7
  111. package/dist/src/gateway.js +39 -285
  112. package/dist/src/index.d.ts +4 -5
  113. package/dist/src/index.js +3 -4
  114. package/dist/src/notes.d.ts +11 -0
  115. package/dist/src/notes.js +64 -0
  116. package/dist/src/oauth.d.ts +16 -0
  117. package/dist/src/oauth.js +46 -0
  118. package/dist/src/programs.d.ts +29 -0
  119. package/dist/src/programs.js +171 -0
  120. package/package.json +3 -11
  121. package/dist/bundled/index.json +0 -6
  122. package/dist/bundled/sha256-01d69bc3888c2a53963f4413d47de909d129ad27c78e9af6d830bb50c3478419.agentorg +0 -0
  123. package/dist/bundled/sha256-84165e3be5c904fc971d983dab31102e07cca725d8629a6fd7d118fa3a0a88b8.agentorg +0 -0
  124. package/dist/bundled/sha256-ade9132b3f34b4c39db92adeadc7e540dc745e4a81b5b54f5d45bf9ec92bca75.agentorg +0 -0
  125. package/dist/bundled/sha256-f4330f5987f37d8cf3aeb44d2f831b573641a87186daa2f811f0c35ba04804f0.agentorg +0 -0
  126. package/dist/node_modules/@agentorg/hub/dist/src/build.d.ts +0 -17
  127. package/dist/node_modules/@agentorg/hub/dist/src/build.js +0 -120
  128. package/dist/node_modules/@agentorg/hub/dist/src/logs.d.ts +0 -33
  129. package/dist/node_modules/@agentorg/hub/dist/src/logs.js +0 -162
  130. package/dist/node_modules/@agentorg/hub/dist/src/net.d.ts +0 -41
  131. package/dist/node_modules/@agentorg/hub/dist/src/net.js +0 -265
  132. package/dist/node_modules/@agentorg/hub/dist/src/processes.d.ts +0 -78
  133. package/dist/node_modules/@agentorg/hub/dist/src/processes.js +0 -485
  134. package/dist/node_modules/@agentorg/hub/dist/src/storage.d.ts +0 -38
  135. package/dist/node_modules/@agentorg/hub/dist/src/storage.js +0 -194
  136. package/dist/node_modules/@agentorg/interfaces/dist/src/http-egress.d.ts +0 -6
  137. package/dist/node_modules/@agentorg/interfaces/dist/src/http-egress.js +0 -7
  138. package/dist/node_modules/@agentorg/interfaces/dist/src/installer.d.ts +0 -191
  139. package/dist/node_modules/@agentorg/interfaces/dist/src/installer.js +0 -136
  140. package/dist/node_modules/@agentorg/interfaces/dist/src/layout.d.ts +0 -47
  141. package/dist/node_modules/@agentorg/interfaces/dist/src/layout.js +0 -52
  142. package/dist/node_modules/@agentorg/interfaces/dist/src/rules.d.ts +0 -35
  143. package/dist/node_modules/@agentorg/interfaces/dist/src/rules.js +0 -37
  144. package/dist/node_modules/@agentorg/interfaces/dist/src/storage-admin.d.ts +0 -23
  145. package/dist/node_modules/@agentorg/interfaces/dist/src/storage-admin.js +0 -31
  146. package/dist/node_modules/@agentorg/interfaces/dist/src/ui-shell.d.ts +0 -14
  147. package/dist/node_modules/@agentorg/interfaces/dist/src/ui-shell.js +0 -26
  148. package/dist/node_modules/@agentorg/interfaces/dist/src/ui-view.d.ts +0 -27
  149. package/dist/node_modules/@agentorg/interfaces/dist/src/ui-view.js +0 -26
  150. package/dist/node_modules/@agentorg/kit/dist/src/chat.d.ts +0 -37
  151. package/dist/node_modules/@agentorg/kit/dist/src/chat.js +0 -131
  152. package/dist/node_modules/@agentorg/kit/dist/src/components.d.ts +0 -94
  153. package/dist/node_modules/@agentorg/kit/dist/src/components.js +0 -66
  154. package/dist/node_modules/@agentorg/kit/dist/src/icons.d.ts +0 -17
  155. package/dist/node_modules/@agentorg/kit/dist/src/icons.js +0 -30
  156. package/dist/node_modules/@agentorg/kit/dist/src/index.d.ts +0 -6
  157. package/dist/node_modules/@agentorg/kit/dist/src/index.js +0 -10
  158. package/dist/node_modules/@agentorg/kit/dist/src/markdown.d.ts +0 -9
  159. package/dist/node_modules/@agentorg/kit/dist/src/markdown.js +0 -14
  160. package/dist/node_modules/@agentorg/kit/dist/src/resizable.d.ts +0 -5
  161. package/dist/node_modules/@agentorg/kit/dist/src/resizable.js +0 -8
  162. package/dist/node_modules/@agentorg/kit/dist/src/styles.d.ts +0 -11
  163. package/dist/node_modules/@agentorg/kit/dist/src/styles.js +0 -166
  164. package/dist/node_modules/@agentorg/kit/package.json +0 -44
  165. package/dist/node_modules/@agentorg/sdk/dist/frame/runtime.js +0 -753
  166. package/dist/node_modules/@agentorg/sdk/dist/host/runner.js +0 -21963
  167. package/dist/node_modules/@agentorg/sdk/dist/src/build.d.ts +0 -2
  168. package/dist/node_modules/@agentorg/sdk/dist/src/build.js +0 -2
  169. package/dist/node_modules/@agentorg/sdk/dist/src/client-http.d.ts +0 -24
  170. package/dist/node_modules/@agentorg/sdk/dist/src/client-http.js +0 -247
  171. package/dist/node_modules/@agentorg/sdk/dist/src/describe.d.ts +0 -13
  172. package/dist/node_modules/@agentorg/sdk/dist/src/describe.js +0 -16
  173. package/dist/node_modules/@agentorg/sdk/dist/src/frame-base.d.ts +0 -8
  174. package/dist/node_modules/@agentorg/sdk/dist/src/frame-base.js +0 -64
  175. package/dist/node_modules/@agentorg/sdk/dist/src/frame-entry.d.ts +0 -1
  176. package/dist/node_modules/@agentorg/sdk/dist/src/frame-entry.js +0 -35
  177. package/dist/node_modules/@agentorg/sdk/dist/src/frame-host.d.ts +0 -57
  178. package/dist/node_modules/@agentorg/sdk/dist/src/frame-host.js +0 -293
  179. package/dist/node_modules/@agentorg/sdk/dist/src/frame-protocol.d.ts +0 -124
  180. package/dist/node_modules/@agentorg/sdk/dist/src/frame-protocol.js +0 -16
  181. package/dist/node_modules/@agentorg/sdk/dist/src/frame.d.ts +0 -25
  182. package/dist/node_modules/@agentorg/sdk/dist/src/frame.js +0 -248
  183. package/dist/node_modules/@agentorg/sdk/dist/src/host-main.d.ts +0 -1
  184. package/dist/node_modules/@agentorg/sdk/dist/src/host-main.js +0 -60
  185. package/dist/node_modules/@agentorg/sdk/dist/src/host.d.ts +0 -25
  186. package/dist/node_modules/@agentorg/sdk/dist/src/host.js +0 -92
  187. package/dist/node_modules/@agentorg/sdk/dist/src/manifest-api.d.ts +0 -2
  188. package/dist/node_modules/@agentorg/sdk/dist/src/manifest-api.js +0 -2
  189. package/dist/node_modules/@agentorg/sdk/dist/src/manifest.d.ts +0 -56
  190. package/dist/node_modules/@agentorg/sdk/dist/src/manifest.js +0 -165
  191. package/dist/node_modules/@agentorg/sdk/dist/src/package.d.ts +0 -60
  192. package/dist/node_modules/@agentorg/sdk/dist/src/package.js +0 -538
  193. package/dist/node_modules/@agentorg/sdk/dist/src/tar.d.ts +0 -7
  194. package/dist/node_modules/@agentorg/sdk/dist/src/tar.js +0 -71
  195. package/dist/node_modules/@agentorg/shell/dist/agent-bindings.js +0 -59
  196. package/dist/node_modules/@agentorg/shell/src/agent-bindings.ts +0 -107
  197. package/dist/src/frames.d.ts +0 -23
  198. package/dist/src/frames.js +0 -78
  199. package/dist/src/layout.d.ts +0 -44
  200. package/dist/src/layout.js +0 -90
  201. package/dist/src/model.d.ts +0 -51
  202. package/dist/src/model.js +0 -230
  203. package/dist/src/rules.d.ts +0 -71
  204. package/dist/src/rules.js +0 -157
  205. package/dist/src/transfer.d.ts +0 -30
  206. package/dist/src/transfer.js +0 -110
package/README.md CHANGED
@@ -8,90 +8,37 @@ npx @agentorg/cli
8
8
 
9
9
  It needs Node.js 22.15 or later. It runs AgentOrg on this computer and opens it in your browser; see "The `agentorg` command".
10
10
 
11
- AgentOrg as a dynamic system: Actors and widgets are modules in content-addressed packages, connected through named, versioned interfaces. This repository holds the core, starting with the SDK a package author writes against (`@agentorg/sdk`) and the standard interfaces (`@agentorg/interfaces`). Only `@agentorg/cli` is published; the other packages ship inside it.
11
+ AgentOrg creates and manages agents. Each part is a program that joins a Hub as an Actor, connected to the others through named, versioned interfaces: a model, agent providers, MCP providers, and management.
12
12
 
13
13
  ## Packages
14
14
 
15
- - `@agentorg/sdk`: `defineInterface` (with `method` and `event`) for `rpc`, `stream` and `http` interfaces; `defineActor` for host modules and `defineWidget` for view modules, with typed slot and export handles; the errors `NotConnected`, `Refused` and `OutcomeUnknown`; and `createTestContext` (`@agentorg/sdk/testing`), which runs a module without a Hub. An `rpc` handler gets its input and `{ caller }`, the calling Actor as the Hub names it, and `emit(event, payload, { to })` sends an event only to the subscriptions of the Actor `to` names, so a provider serving several consumers keeps each one's events its own. In `createTestContext`, `call` takes the caller as a fourth argument (the module's own Actor by default) and `emitted` records each event's `to`. `@agentorg/sdk/client` connects a program outside the Hub as an Actor: `connect({hubUrl, actorId, credential, slots, exports})` gives the same handles as a module's context, on the same runtime, with slots bound as the Hub's notices say and `exports.add`/`withdraw()` over the channel; As in a module, implement in `start` (run before the channel opens) and use slots from `onBind`, which runs when a slot becomes usable: bound, or its provider back. `openChannel` is the wire layer beneath it, without local checks. `http` slots `fetch` and `http` exports `serve` over the Hub's stream (HTTP/1.1, one request per stream, `node:http` loaded only when used). The request line carries the consumer's absolute URL, so a handler's `request.url` is exactly the URL the consumer fetched, scheme included; a request line that isn't absolute, or whose host isn't the `Host` header's, is answered 400. A handler that throws `Refused`, `NotConnected` or `OutcomeUnknown` reaches the consumer's `fetch` as that same error (carried as a 502 with an `agentorg-error` header); any other throw is a plain 500 response. `@agentorg/sdk/host` runs a package Actor's host modules in one process, on the same runtime: `runHost({packageDir, actorId, channel, log})` imports each `host` module's bundle, runs every `start`, then says hello over the channel, with each module's slots and exports named `<module>.<name>`. The program the Hub runs is `@agentorg/sdk/host/runner.js`, one self-contained file: it takes `<packageDir> <actorId>`, uses fd 3 as the channel, writes `ctx.log` as JSON lines on stderr, and exits non-zero if a `start` throws or an exception goes uncaught. The SDK's errors keep their class and code between a package's bundle and the runner, though each carries its own copy of the SDK. It reads only itself and the package's folder, so it runs under Node's permission model with exactly those two paths allowed (as real paths: the allow list doesn't follow symlinks). A slot made at run time, another Actor's export exposed to this Actor rather than declared by its package, isn't in `ctx.slots`: `ctx.exposed()` lists those bound now, each as `{slot, described, provider: {actor, export}, call, on}`, with `described` the export's JSON Schemas and `call` one function per method, its values checked by the Hub rather than locally; `ctx.onExposed(fn)` runs after one comes or goes. Every host module of the Actor sees them, under the Actor's slot name; a view module sees none. The Hub's `slot` notice carries such a slot's `exposed` (the export's described interface and its provider) while it is bound, one notice each, including right after hello, which names them among `bound`; `createTestContext` fakes one with `expose(slot, iface, handlers)` and `unexpose(slot)`.
16
- - `@agentorg/interfaces`: the standard interfaces `kv@1`, `ui.view@1`, `chat@1` (a conversation with an agent; a `tool` message may carry the call it stands for, its name, `running`/`done`/`refused`, input and output, sent as `running` when it starts and again under the same id when it ends), `llm.session@1` (stateless model inference, with function tools), `account.login@1` (signing in to an outside account, driven by a person or a program), `http.egress@1` (HTTPS to the public internet), `storage.admin@1` (seeding a new Actor's empty stores), `layout@1` (the person's dashboard), `installer@1` (planning and installing a package) and `ui.shell@1` (what the shell offers a view in its frame: opening an https address and starting sign-in), and the Hub's management interfaces `hub.packages@1`, `hub.actors@1`, `hub.grants@1`, `hub.bindings@1`, `hub.exports@1` and `hub.audit@1`.
17
- - `@agentorg/kit`: the shell's own components, for the shell and for any view, drawn in the theme's tokens by the kit's styles (`KIT_CSS`, every class `kit-`, put first in the document's head when the kit is imported, so a view's own styles win). Accessible primitives on Radix: `Dialog` (focus held inside; Escape and a click outside close it), `Menu` with `MenuItem`, `Switch` and `Tabs`; plain elements for the rest: `Button` (`primary`, `quiet`), `IconButton` (its label is its name), `Field`, `Select` (the browser's own), `Card`, `List`, `Table`, `Meter` and `Actions`; layout pieces that fill and adapt: `Stack`, `Row`, `Fill`, `Scroll`, and `ResizableGroup`, `ResizablePanel` and `ResizeHandle` from react-resizable-panels. `Markdown` renders an agent's GitHub-flavored markdown with react-markdown, safe as it streams: remend first closes what's still open, and raw HTML is shown as text. `Chat` is a conversation on assistant-ui's primitives over an external store: the caller keeps the messages (`ChatEntry`, as `chat@1` has them) and runs the turns (`onSend`, `onCancel`, `onRetry`, `onEarlier`). The person's messages, each run of replies and tool messages as one reply in markdown, a tool message as a card (its name, how it ended, what went in and came back) when it says which tool ran and as its line otherwise; Enter sends, never mid-composition or during a turn, when Send is Stop; a refused send puts the text back; it fills its parent and goes compact below 460 px wide. Its tests run on happy-dom.
15
+ - `@agentorg/sdk`: `defineInterface` (with `method` and `event`) for interfaces, with typed slot and export handles; the errors `NotConnected`, `Refused` and `OutcomeUnknown`; and `createTestContext` (`@agentorg/sdk/testing`), which runs a program's handlers without a Hub. An `rpc` handler gets its input and `{ caller }`, the calling Actor as the Hub names it, and `emit(event, payload, { to })` sends an event only to the subscriptions of the Actor `to` names, so a provider serving several consumers keeps each one's events its own. `@agentorg/sdk/client` connects a program outside the Hub as an Actor: `connect({hubUrl, actorId, credential, slots, exports})` gives typed handles, with slots bound as the Hub's notices say; implement in `start` (run before the channel opens) and use slots from `onBind`, which runs when a slot becomes usable: bound, or its provider back. `openChannel` is the wire layer beneath it, without local checks.
16
+ - `@agentorg/interfaces`: the standard interfaces `kv@1`, `chat@1` (a conversation with an agent; a `tool` message may carry the call it stands for, its name, `running`/`done`/`refused`, input and output, sent as `running` when it starts and again under the same id when it ends; `models` lists the models it can use and the one chosen, and `setModel` chooses, kept with the agent), `llm.session@1` (stateless model inference, with function tools), `account.login@1` (signing in to an outside account, driven by a person or a program), `tools@1` (a set of tools known only at run time, as one fixed contract), `agent.settings@1` (what a running agent reads for its instructions and skills), `mcp.provider@1` and `agent.provider@1` (programs that make connections to MCP servers and agents), and `agents@1`, `connections@1` and `skills@1` (what the person calls to manage them), and the Hub's management interfaces `hub.actors@1`, `hub.grants@1`, `hub.bindings@1`, `hub.exports@1` and `hub.audit@1`.
18
17
  - `@agentorg/wire`: the channel: yamux streams, length-prefixed JSON frames, stream headers and transports.
19
- - `installer`: a bundled host package that turns packages into working Actors, exporting `installer@1`. Bound to the Hub's management (`hub.packages`, `hub.actors`, `hub.grants`, `hub.exports` and `hub.bindings`, which makes it the person's delegated manager) and to `storage.admin@1`, it proposes and installs. `plan({package})` lists each slot the package doesn't wire itself, with the exports that could serve it now: exactly its interface and schema hash, on Actors that aren't stopped or closed. `install({package, name, connections, start?})` makes the Actor with exactly those connections, all or none. It grants nothing its caller couldn't: each connection's export side must be the caller's (the provider, bound to that export, or a manager), else the whole install is refused (`forbidden`, listing every such connection) and nothing is made. It seeds each store bound to `storage.kv` from the package's `seed` (an object of key to value per `module.slot`), starts the Actor if asked (a seed or start that fails closes it), and lists the slots left unbound and the seeds that couldn't land (`unseeded`). It never picks a connection itself. `install` records the new Actor as made for its caller (`installedFor`, which grants nothing), and takes `expose: [{export, to}]`: the new Actor's exports to expose, each to one Actor, all or none like the connections. A manager's are made at once (`granted`, with the slot); one to the caller itself is left for the caller to file, its result giving the exact `hub.grants.expose` call, which makes it the caller's own request (`request`); any other is refused `forbidden`, saying a manager could, and nothing is created. Only `rpc` exports of the package's host modules can be listed, and the Hub's own Actors take no slots. `plan({package, expose})` lists each entry with how it would settle, and refuses one `install` would refuse. Nothing is exposed that isn't listed. Bound to the person's `layout@1` too, it carries a system between homes as data: `exportSystem()`, for a manager only (it lists every binding and the person's layout; any other caller is refused `forbidden`), gives an `agentorg.system/1` composition (every package Actor that isn't closed, by a name of its own, with its package as `name@version#hash` and whether it runs; the connections among them and to the built-in Actors, as `{consumer, slot, provider, export}` by names; and the layout's placements), never credentials, tokens, stores or logs, and lists what it leaves out (external Actors and what connects to them). `importSystem({composition})` makes it again with the caller's authority (connecting the new Actors to each other takes a manager): it creates the Actors whose packages are here (a taken name gets a suffix), binds the connections, seeds, starts what ran and places the layout, all or nothing, and lists what it couldn't: a package that isn't here or is another version (whoever holds the composition's folder adds its archives first) and what depends on it, an Actor that needs a sign-in, a seed that can't land, and the placements unless the caller holds the person's layout. The exporting home's installer stays out: every home has its own. An import never grants management: a connection to `hub` or to `storage.admin` is recorded by an export but never made by an import, even a manager's (a composition may come from anyone); it comes back in `ungranted`, for the person to grant one by one.
20
- - `@agentorg/hub`: the core. Its state, in `node:sqlite` in a private home: Actors, a verified package store (`hub.packages.add` takes an archive by path; `hub.packages.build` takes a package's source as data, `package.json` and files under `src/` up to 768 KiB, builds it as `agentorg build` does, but reading no tsconfig, in a scratch folder of the home that is always removed: its files import only `@agentorg/sdk`, `@agentorg/interfaces`, `zod`, and for views `react`, `react-dom` and `@agentorg/kit` (JSX compiles to `react/jsx-runtime`), by name, each only within its own package, nothing outside the package's folder, and nothing by a pattern; a library's own imports are its own, and only the files resolved for it are read; a library's wrapped modules are named in the bundle by their library and version (`agentorg-library:react@19.3.1/cjs/react.production.js`), never by where it is installed, in `agentorg build` and Hub builds alike, so a package names no machine's folders and builds the same on any install; a Hub build resolves each allowed package's entry file from the Hub's own install, so in that file esbuild omits Node's ESM-to-CommonJS interop flag, which `agentorg build` keeps: no package allowed now behaves differently for it, but a Hub build's bytes can differ from `agentorg build`'s for packages that use them; at most 16 modules, 16 MiB built and 60 s; one build per caller at a time; and it adds the result. Reading each module's definition runs the source's code, so the Hub runs it in the same OS sandbox as host processes, and where those can't start, `build` is refused `unsupported` with the same reason. A failed build is `Refused("build")` with the build's message, which names no path outside the package), what each Actor takes and offers, bindings, binding requests and an audit trail. A binding is the grant, and it needs both ends: the export side (the provider, an Actor already bound to that export, or a manager) and the slot side (the consumer itself, or a manager). Through `hub.grants@1`, a caller with both ends binds; one with a single end approves the other end's open request or asks that end's approvers; one with neither is refused. `hub.grants.expose({provider, export, to, as?})` exposes an `rpc` export to one Actor: a slot made on `to` at run time, typed by the export's interface and bound to it in one step, named `as` (one word of at most 48 characters) or by default the provider's name camelCased, `_` and the export's last part (`Pocket Side Quests`' `logic.quests` is `pocketSideQuests_quests`), made unique on `to` with `_2`, `_3`…. Its authority is a binding's, `to` being the consumer: with both ends it is made; with one it is a request (`exposed: true` on the request, its `slot` the name it will have), which the other end approves by calling `expose` with the request's fields; with neither it is refused, naming who could. Exposing the same export to the same Actor again gives its slot back. A request reserves no name: the first exposure made under it has it, and the requests it settles close; one Actor has at most 32 exposure requests open toward another. An Actor that declares a slot of its own under an exposed slot's name takes the name, and the exposure goes. The slot goes with its binding: `unexpose({to, slot})`, `unbind`, the export withdrawn or either end closed; `hub.bindings` marks such a binding `exposed: true`. The Hub's own Actors take no slots. A manager creating an Actor for another (the installer, for its caller) passes `for`, shown as `installedFor` on the Actor: provenance only, from which the Hub grants nothing. A decision goes to the request's approvers and its requester, which can also read its requests' outcomes with `mine`. A manager is any Actor bound to `hub.bindings@1`. `hub.actors.create` can bind the new Actor's slots at once, with the creator's export side. The router serves it over WebSocket (`listen`), one yamux channel per Actor: a client's first stream is `hello` with its credential, then every `call`, `subscribe`, `open` and `http` stream is resolved through its binding, validated against the interface's JSON Schemas in both directions (ajv, 2020-12, in a pool of worker threads, each check under a time budget, since schemas come from Actors), forwarded to the provider with the caller named, and audited. A provider accepts or refuses an `open` or `http` stream with one body before any raw bytes. An Actor offers and withdraws exports at run time on its own channel (`offer`, `withdraw`). An Actor learns which of its slots are bound from hello's result, then from a `slot` notice on each change. A pipe the Hub makes for a package Actor's process says hello as that Actor without a credential (the pipe is the proof) and declares nothing (the manifest does). Every `serve` stream names the caller and the caller's slot, so a provider can keep state per consumer slot. `hub.actors.start` runs a package Actor's host modules in their own process: `node` under its permission model (reading only the runner and the package's folder, no child processes or workers), with an empty environment, a 256 MB heap and the channel on fd 3, inside the OS sandbox (`sandbox-exec` on macOS, a user, network and PID namespace with `unshare` on Linux), so it has no network, no DNS and no other process to signal. The Actor is running once its process says hello, within 30 s. `stop` sends SIGTERM, then SIGKILL after 5 s. A process that exits otherwise has crashed: it is restarted after a backoff from 1 s doubling to 60 s (starting over after 10 minutes up), and `hub.actors.get` counts `restarts` and keeps the `lastExit`. Every Actor's record in `hub.actors` says whether it is `connected`, holding a channel to the Hub now: an external Actor while its program is connected (the person while the app runs: its gateway holds the person's channel), a package Actor while its process is, so a running one isn't while its process starts or restarts; the built-in Actors are the Hub itself and have none. `hub.actors`' `changed` event names an Actor whose record may differ: made, started, stopped, closed, its process exited, or connected or gone; the audit trail records no connections. Actors running when the Hub stopped are started again when it opens. Where the sandbox can't run (stock Ubuntu restricts unprivileged user namespaces), `start` is refused with `unsupported` and every package Actor's `host` says why and what to change; the Hub probes again at each start. `hub.actors.logs` reads an Actor's log lines: its `ctx.log` entries and anything else its process writes (stdout as `info`, stderr as `error`). For the person's shell, `Hub.viewCall` and `Hub.viewSubscribe` run a package Actor's view module's calls and events in the Hub's process, as that Actor, through `<module>.<slot>`, and `Hub.viewSlots` tells the gateway a view module's slots: those bound now, then each change, and each bound again when it is usable again: its provider's channel comes back, or its Actor's own, since a view calls only while its Actor runs; `hub.actors.get` lists a package Actor's `views`. `Hub.viewLog` writes a view module's log line to its Actor's log, marked with the module; the Hub bounds each line itself (a known level, 4 KiB of text, 16 fields of 1 KiB) and rotates each Actor's log once at 1 MiB. The built-in `storage` Actor exports `kv@1`: one store per consumer slot (keyed by the consumer and slot the router names), in `<home>/storage.db`; values up to 256 KiB and 64 MiB per Actor, past which `Refused("quota")`; stores outlive unbinding and go when their Actor is closed. Its `admin` export (`storage.admin@1`, bound only to the installer) seeds a new Actor's store from its package's `seed`: all entries or none, into an empty store only, within the same limits, and audited as `storage.seed` with the consumer, the slot and how many entries. The built-in `net` Actor exports `egress` (`http.egress@1`): a consumer's request, made from the Hub's process to the public internet over HTTPS only. Its host is resolved and every address checked (loopback, private, shared, link-local including the cloud metadata address, multicast, reserved and documentation ranges, and their IPv4-mapped forms are refused), and the connection goes to the checked address with the name for SNI and the certificate, so a second resolution can't move it. Plain `http:`, a refused address and a name that resolves to one throw `Refused("forbidden")` at the consumer's `fetch`; a host that can't be reached before anything is sent throws `Refused("unreachable")`, and a failure after, or 5 minutes without a byte, throws `OutcomeUnknown`. Redirects come back as they are. Each request's method, host and status are audited as `net`'s; paths, queries and bodies never are. The `hub` Actor's six exports are served through the same path. A refusal that names an Actor names it as "Name (id)", and says what the caller can do instead: who could grant it, what to call, or what to do first.
18
+ - `@agentorg/hub`: the core. Its state, in `node:sqlite` in a private home: Actors, what each takes and offers, bindings and an audit trail. An Actor is a program that connects itself, with a credential. A binding is the grant, and it needs both ends: the export side (the provider, an Actor already bound to that export, or a manager) and the slot side (the consumer itself, or a manager). Through `hub.grants@1`, a caller with both ends binds; any other is refused. `hub.grants.expose({provider, export, to, as?})` exposes an `rpc` export to one Actor: a slot made on `to` at run time, typed by the export's interface and bound to it in one step, named `as` (one word of at most 48 characters) or by default the provider's name camelCased, `_` and the export's last part, made unique on `to` with `_2`, `_3`…. Its authority is a binding's, `to` being the consumer. Exposing the same export to the same Actor again gives its slot back. The slot goes with its binding: `unexpose({to, slot})`, `unbind`, the export no longer declared or either end closed; `hub.bindings` marks such a binding `exposed: true`. A manager is any Actor bound to `hub.bindings@1`. `hub.actors.create` can bind the new Actor's slots at once, with the creator's export side. The router serves it over WebSocket (`listen`), one yamux channel per Actor: a client's first stream is `hello` with its credential, then every `call` and `subscribe` stream is resolved through its binding, validated against the interface's JSON Schemas in both directions (ajv, 2020-12, in a pool of worker threads, each check under a time budget, since schemas come from Actors), forwarded to the provider with the caller named, and audited. An Actor learns which of its slots are bound from hello's result, then from a `slot` notice on each change. Every Actor's record in `hub.actors` says whether it is `connected`, holding a channel to the Hub now, and `hub.actors`' `changed` event names an Actor whose record may differ. When a redeclaration changes the interface of a bound name, the bindings whose other end doesn't declare the new one are dropped (audited as `binding.drop`). A refusal that names an Actor names it as "Name (id)", and says what the caller can do instead.
21
19
  - `@agentorg/cli`: AgentOrg as one app. `agentorg` runs a Hub, the person's gateway and the shell on loopback; see "The app: the person's gateway".
22
- - `chatgpt`: the model Actor, a package with one host module. It signs in with ChatGPT for the person's plan (`account.login@1`: OpenAI's OAuth for open-source apps, with dynamic registration, PKCE and a verified id_token; refresh tokens rotate, one refresh at a time) and serves `llm.session@1` on that plan through the Responses API, streamed and stored nowhere. Its whole network is its `web: http.egress@1` slot and its sign-in lives in its `store: kv@1` slot; the tokens never leave it except to that store: never in a reply, an event, a log or a refusal. It never uses an API key or API billing: a usage limit is refused `usage_limit`, with where to manage it. Its tests run against an in-process fake of OpenAI, so none reaches OpenAI.
23
- - `assistant`: an agent, a package whose host module `logic` exports `chat@1` and runs the agent loop itself, with the model behind its `model: llm.session@1` slot. Its tools are its other bound slots (`layout`, `packages`, `actors`, `grants`, `exports` and `installer`), and every slot exposed to it at run time (`ctx.exposed()`): each method becomes a function tool named `<slot>__<method>` (a dot in the slot's name as `_`; a name past 64 characters is left out) with the method's input JSON Schema, so it can do exactly what it is connected to, and a call runs through the slot, checked and audited by the Hub. With `packages` and `installer: installer@1` bound, it can extend the system: its instructions then give the package format (views may use React and `@agentorg/kit`'s components), with a whole counter package and a view on the kit as the examples (`EXAMPLE` in `src/logic.ts`, built by its tests as the Hub builds), and the steps: `packages__build` with the files, fixing errors from the build's message; `installer__plan`; `installer__install` with explicit connections (a store to `storage.kv`); then `layout__place` with the new Actor's view. A turn makes at most 20 tool calls, and a function's output is cut at 16 KiB. Its chat is kept in its `store: kv@1` slot: each message once, its text and a call's arguments cut to fit a stored value, and the newest 2,000 messages (16 MiB) kept. The model is sent the newest whole exchanges that fit 400 KB of JSON (instructions and tool schemas aside), and always the latest one; if that alone is over, its oldest function outputs are left out, each call keeping an output. Its view module `chat` is the chat itself, the kit's `Chat` over its `chat: chat@1` slot: the record (the newest 100, earlier pages on request), the replies as they stream, in markdown, and a composer, with "Using ChatGPT plan" and "Manage usage" beside it, Retry under the last reply, and the action each refusal calls for (Manage usage, Continue with ChatGPT, Retry), which it asks of the shell through its `shell: ui.shell@1` slot.
20
+ - `@agentorg/mcp`: the built-in MCP provider, an external Actor exporting `mcp.provider@1` as `provider`, and the only code that imports the MCP client (`@modelcontextprotocol/client`). `startMcpProvider({hubUrl, actorId, credential, dir})` runs it; its slot `actors` is bound to `hub.actors@1`. It offers two kinds: `url` attaches to a server over Streamable HTTP, sending `secrets.token` as a bearer token on every request (only over https or to this machine), and `command` starts a local server over stdio, with the basic environment and each of its `secrets` as an environment variable. Each connection joins the Hub as its own Actor exporting `tools@1` as `tools`: `list` and `call` go to the server, a tool's result comes back as text, with `failed` when the tool reported an error, and `changed` fires when the server's tools change or it goes or comes back. While a server is away `list` and `call` are refused `not_connected`, and the provider tries again after a backoff from 1 s doubling to 60 s (starting over after 10 minutes up). `create`'s `secrets` are write-only: the values cross once and go only to the provider's private `dir`, never into `params`, `target`, `detail`, status or a log (what a server prints is scrubbed of them). Each connection's Hub credential, parameters and secrets are kept in that folder, and connections rejoin at its next start. A server started by `command` is an ordinary process with the person's rights, outside the Hub's sandbox.
21
+ - `@agentorg/manager`: management, an external Actor exporting `agents@1`, `connections@1`, `skills@1` and, as `settings`, `agent.settings@1`. `startManager({hubUrl, actorId, credential, dir})` runs it; bound to `hub.actors@1`, `hub.grants@1` and `hub.bindings@1`, it is a manager. A provider of either sort is connected by exposing its export to it: the Hub's slots are the only list. It keeps what the Hub can't know, in its private `dir`: each connection's origin, each agent's provider, creatable, instructions and skills, and the skills as `SKILL.md` folders. Status is read when asked, what a connection is exposed to is the Hub's bindings, and `secrets` go straight to the provider. `agents.create` is all or none: the provider makes the agent, its `settings` are bound, its skills added (one whose name is here keeps the one here), each connection it needs made or picked and exposed under its slot, and its chat exposed to the person; if a step fails, what this creation made is removed. An agent reads only its own instructions and skills, and only it hears that they changed.
22
+ - `chatgpt`: the model, a program. It signs in with ChatGPT for the person's plan (`account.login@1`: OpenAI's OAuth for open-source apps, with dynamic registration, PKCE and a verified id_token; refresh tokens rotate, one refresh at a time) and serves `llm.session@1` on that plan through the Responses API, streamed and stored nowhere. The tokens never leave it: never in a reply, an event, a log or a refusal. It never uses an API key or API billing: a usage limit is refused `usage_limit`, with where to manage it. `startChatGPT({hubUrl, actorId, credential, dir})` runs it as an Actor exporting `login` and `session` with no slots at all: the sign-in is in `sign-in.json` in its private `dir` (mode 0600, written through before a change is acknowledged, since a rotated refresh token can't be had again), and it reaches OpenAI over the network directly, https only, with redirects returned as they are. Its tests run against an in-process fake of OpenAI, so none reaches OpenAI.
23
+ - `assistant`: the agent engine and the bundled agent provider. `startAgentProvider` runs an external Actor exporting `agent.provider@1` as `provider`, which offers one creatable, Assistant. Each agent is its own Actor on its own channel in that process, exporting `chat@1`, with the model behind `model: llm.session@1`, instructions and skills from an optional `settings: agent.settings@1`, and tools from each `tools@1` slot exposed to it. Its transcript and model choice stay in the provider's private folder.
24
24
 
25
- ### Why `ui.view@1` is different
25
+ ## Errors
26
26
 
27
- Every interface crosses the wire as schemas, and a module's handles are derived from them, with one exception. `ui.view@1` is a view module's render surface: the view draws into its own frame's DOM, which no message can carry. So its export handle is `implement({ mount(el, { theme, size }), resize?(size) })`, where `el` is the frame's root element, and the frame runtime maps the wire methods `mount`, `resize` and `unmount` onto it. Don't copy this shape for another interface; anything a module offers to others belongs in schemas.
28
-
29
- ### A view's frame
30
-
31
- A shell runs each view module in its own sandboxed frame, with an opaque origin and no network. The frame holds only the SDK's frame runtime, `@agentorg/sdk/frame/runtime.js`, one self-contained script, and the view's bundle. The shell hands the frame one `MessagePort` (`openFrame`, then `new FrameHost(port, handlers)` from `@agentorg/sdk/frame/host`). Everything the view reaches crosses that port:
32
-
33
- - **Load:** the shell names the view's bundle and which of its slots are bound. The frame imports it, runs `start` on the same runtime a host module uses, then binds the slots, so `onBind` runs for each one bound. A frame loads one view, only a `view` module, and takes one port, from its parent window only.
34
- - **Slots:** a call or subscription on a slot goes to the shell, which runs it as the view's Actor; the shell says when a slot is bound, unbound or usable again. A view's `stream` and `http` slots aren't served yet.
35
- - **`ui.view@1`:** the shell drives `mount`, `resize` and `unmount`. At mount, the theme's CSS variables (names starting `--`) are set on the frame's document.
36
- - **`ui.shell@1`:** the shell's own interface, the mirror of `ui.view@1`. A view's slot of it is bound by the frame runtime itself, never by the Hub, so it is always bound. `openExternal({url})` takes only an `https:` URL, which the host checks; the shell's handler must open it in a new tab with no opener (`noopener`). `signIn()` starts the shell's own sign-in. Each method has one call in flight at a time. A frame can't open windows itself.
37
- - **Logs:** the view's `ctx.log` and any error it doesn't catch go to the shell, for its Actor's log.
38
- - **Size and base styles:** the placement decides a frame's size, never its content: the view learns it from `mount` and `resize`. Before the view loads, the frame runtime puts a base stylesheet first in the document (`FRAME_BASE`): the document and body fill the frame on a transparent background, content that grows scrolls inside with no visible scrollbar, and plain HTML (text, headings, lists, buttons, inputs, checkboxes, tables, code) is drawn in the theme's tokens. Every rule is in `:where()`, so any rule the view writes outranks it.
39
-
40
- The frame isn't trusted: `FrameHost` checks every message, drops what doesn't fit, and refuses what it can't serve. A frame holds one subscription per slot and event, 64 at most, and 64 calls in flight, past which a call is refused `busy`; its log lines are cut, their fields rebuilt as a small fresh object, and past 50 lines in 10 s the rest are dropped.
41
-
42
- ## Building a package
43
-
44
- A package's `package.json` names its modules, its own wiring and any seed state:
45
-
46
- ```json
47
- "agentorg": {
48
- "modules": { "logic": "src/logic.ts", "panel": "src/panel.ts" },
49
- "connections": [["panel.board", "logic.board"]],
50
- "seed": { "logic.store": { "cards": [] } }
51
- }
52
- ```
53
-
54
- `seed` is optional initial state for state slots, keyed by `"module.slot"`; the build checks each slot exists. It is the only runtime state a package may carry.
55
-
56
- `agentorg build [dir]` (from `@agentorg/sdk`; `buildPackage` in `@agentorg/sdk/build`) then:
57
-
58
- - bundles each module, with every library it uses, into one ESM file, `dist/<module>.js`, with no imports at run time and no Node built-ins. JSX uses the automatic runtime (no file needs React in scope), and `process.env.NODE_ENV` is `"production"`, so a view built with React and the kit runs in a frame, which has no `process`;
59
- - reads each module's definition from its code and writes `agentorg.json`: each module's placement, slots and exports, every interface's JSON Schemas and hash, the package's `connections` and `seed`;
60
- - hashes the tree, `agentorg.json` and `dist/`, as SHA-256 over the canonical list of each file's path and SHA-256, and archives it as `<hash>.agentorg`, a deterministic tar. The tree goes to `agentorg-build/package/` and the archive beside it.
61
-
62
- It finds `@agentorg/sdk`, `@agentorg/interfaces` and `zod` from the package's own folder, so it works in a checkout of this repository, where they are. With `agentorg` installed from npm, build through the running app instead: `agentorg call packages build '{"files": {"package.json": "…", "src/logic.ts": "…"}}'` is the Hub's build (`hub.packages.build`), which takes the source as data, builds it as above against the SDK, the interfaces, zod, React, react-dom and the kit it ships with, and adds the package.
63
-
64
- A signature is detached: a file named `agentorg.sig` beside the package, signing the package hash, so it is never inside what it signs. The manifest has no signature field.
65
-
66
- The build bundles; it doesn't type-check. Run `tsc --noEmit` on the package first.
67
-
68
- `@agentorg/sdk/manifest` reads packages without esbuild, for a Hub or an installer: `verifyArchive(bytes, hash)` checks an archive holds exactly `agentorg.json` and each module's entry, hashes to the expected hash, and has a sound manifest (`checkManifest`: its shape, each interface's recorded hash against its schemas, and its connections). Problems are returned, not thrown.
69
-
70
- The examples folder holds the spec's board package; its tests build it.
71
-
72
- ### Module top levels have no side effects
73
-
74
- To read a module's definition, the build runs the module's code in a separate Node process (Node 22.15 or later) under the permission model: it can read only its own scratch folder, write nothing, and start no processes; Node built-ins can't be imported, and the network globals are gone. A definition that takes over 30 seconds to read is stopped. Widget bundles run there too, in Node, not a browser. So a module's top level must only define: no I/O, no timers that do work, no DOM globals such as `document` or `window`. Do that work in `start()`. A top level that tries fails the build with a message naming the module and what it touched.
75
-
76
- ### Errors
77
-
78
- - `NotConnected`: the slot is unbound, or the export was withdrawn.
27
+ - `NotConnected`: the slot is unbound, or the export is no longer declared.
79
28
  - `Refused` with code `invalid`: the caller's input broke the interface's schema. Nothing ran.
80
29
  - `Refused` with code `bad_output`: the provider ran, and its reply or event broke the contract. The call may have had its effect; read state before retrying.
81
30
  - `Refused` with code `unimplemented`: the export has no handler for that method yet.
82
31
  - `OutcomeUnknown`: the channel dropped mid-call. Read state before retrying.
83
32
 
84
- ### The `agentorg` command
33
+ ## The `agentorg` command
85
34
 
86
35
  `@agentorg/cli` provides `agentorg`.
87
36
 
88
37
  - **`agentorg`**, with no command, runs AgentOrg: a Hub in its home, the person's gateway and the shell, on `127.0.0.1` (`--port N`, else any free port). It opens the browser already signed in, and prints only its address, never a sign-in code. `--no-open` doesn't open a browser. The code is in the address it hands the system's opener; on Linux, other local users can see that program's arguments for the moment it runs, and the code works for 60 s.
89
38
  - **`agentorg --version`** prints the version. An option the command doesn't know is refused with the usage (exit 2); it never starts the app.
90
39
  - **`agentorg open`** signs a browser in to the running app again.
91
- - **`agentorg build [dir]`** builds a package, as the SDK's build does, in a checkout of this repository. Installed from npm, build with `agentorg call packages build '{"files": {…}}'`, the Hub's build.
92
40
  - **`agentorg hub [--port N]`** runs a bare Hub in its home, without the gateway or the shell, serving WebSocket on loopback, and writes the address to `<home>/url`.
93
41
  - **The person's commands**, one per hub method:
94
- - `agentorg add <file.agentorg>`;
95
42
  - `agentorg actors|bindings|exports|audit`;
96
43
  - `agentorg bind <consumer.slot> <provider.export>`;
97
44
  - `agentorg call <slot> <method> [json]`.
@@ -107,14 +54,13 @@ To read a module's definition, the build runs the module's code in a separate No
107
54
  From a clone, after `npm ci` and `npm run build`, with `agentorg` being `node packages/app/dist/src/cli.js`:
108
55
 
109
56
  1. **Run the app:** `agentorg`. It prints its address and opens the shell in the browser, already signed in; `agentorg open` signs a browser in again.
110
- 2. **Find the board:** the app's first run added it. `agentorg call packages list` shows its hash, under the name `board`.
111
- 3. **Install it with its store, started,** through the installer the first run made:
57
+ 2. **See what can be created:** `agentorg call agents creatable`. It lists the Assistant, with the id of the provider offering it.
58
+ 3. **Create an agent:**
112
59
 
113
60
  ```sh
114
- agentorg call installer install '{"package":"<hash>","name":"Board","connections":{"logic.store":{"actor":"storage","export":"kv"}},"start":true}'
61
+ agentorg call agents create '{"provider":"<provider>","creatable":"assistant","name":"Scout","answers":{}}'
115
62
  ```
116
- 4. **Place its panel on home:** `agentorg call layout place '{"actor":"<actorId>","module":"panel","title":"Launch"}'`. It shows in the shell at once.
117
- 5. **Add a card** in the panel: type it and press Enter. It is kept in the board's store, so it's there after a reload, and after the board's process restarts (`actors stop`, then `actors start`).
63
+ 4. **Open it in the shell,** sign in to ChatGPT there, and chat with it.
118
64
 
119
65
  ## The app: the person's gateway
120
66
 
@@ -124,40 +70,10 @@ From a clone, after `npm ci` and `npm run build`, with `agentorg` being `node pa
124
70
  - **`/api`:** one WebSocket per tab, with the same calls a channel carries, as JSON:
125
71
  - `{id, op: "call", slot, method, input}` is answered `{id, result}` or `{id, error}`;
126
72
  - `{sub, op: "subscribe", slot, event}` gets `{sub, payload}` per event, and `{sub, end: true}` when it ends; `{sub, op: "unsubscribe"}` stops it.
127
- - `{sub, op: "slots", view: {actor, module}}` watches a view's slots through the Hub's `viewSlots`: first `{sub, payload: {bound: [slot]}}`, every slot bound now, then `{sub, payload: {slot, bound}}` per change, `bound` again when the slot is usable again. A module that isn't a view is refused, as `{sub, end: true, error}`.
128
- - `{op: "log", view: {actor, module}, level, message, fields?}` adds a line to the view's Actor's log, through the Hub's `viewLog`, which bounds it as a frame's line is; nothing answers.
129
73
 
130
74
  A socket holds 256 subscriptions and 64 calls in flight at most (past it, `busy`). A tab's socket must come from the gateway's own `Origin`, and its first message must be `{op: "hello", session}` with a live session, answered `{op: "hello"}`; otherwise it's closed with code 4401, and the tab signs in again. The CLI gets in with the token in `<home>/cli-token` (0600, new at each start) as a bearer. The gateway answers only to `127.0.0.1:<port>` in `Host`, so a page that rebinds DNS to loopback gets nothing.
131
- - **What the calls reach:**
132
- - Calls run through the person's slots: `packages`, `actors`, `bindings`, `grants`, `exports`, `audit`, `store`, and the two the first run binds, either of which may be unbound: `installer` (`installer@1`) and `login` (`account.login@1`, the model's sign-in).
133
- - `layout` is the person's own export, served by the gateway.
134
- - With `view: {actor, module}`, a call runs as that view's Actor, through the Hub's view path (`viewCall` and `viewSubscribe`). The Hub refuses a module that isn't one of the Actor's views, or an Actor that isn't running.
135
- - **The first run,** at every start once the person's store is bound, beside serving: the shell follows the person's bindings as they're made (`firstRun` in `src/model.ts`; `app.firstRun` settles with what it made; `startApp({firstRun: false})` leaves a home as it is):
136
- - it adds the bundled packages, `installer`, `chatgpt`, `assistant` and the `board` example, built into `dist/bundled` with the app (`scripts/bundle.js`);
137
- - it makes the installer as the person, with its seven bindings (`hub.packages`, `hub.actors`, `hub.grants`, `hub.exports`, `hub.bindings`, `storage.admin` and `person.layout`), starts it, and binds the person's `installer` to it;
138
- - once the installer's process is connected, it installs ChatGPT through `installer.install`, with `model.web` to `net.egress` and `model.store` to `storage.kv`, started, and binds the person's `login` to its `model.login`.
139
-
140
- It records the Actors it made, and the bundled assistant's hash, in the person's store (`app/first-run`), and trusts only those, never an Actor because of the name its package gives itself. Each step reads what is there first, so a restart, or a first run that stopped half way, converges and makes nothing twice: a recorded Actor that lost one of its slots' bindings gets it again (of the slots its package declares), and one of an older build is kept. A recorded Actor that was closed is made again. A step that fails is logged and tried again at the next start.
75
+ - **What the calls reach:** the person's slots: `actors`, `bindings`, `grants`, `exports`, `audit`, and the four the first run binds: `login` (`account.login@1`, the model's sign-in), `agents`, `connections` and `skills`. A slot exposed to the person at run time, such as an agent's `chat@1`, is reached under its name from `bindings.list`. `store` answers from the app's own notes, `<home>/app-notes.json`.
76
+ - **The first run,** at every start, beside serving (`startPrograms` in `src/programs.ts`; `app.firstRun` settles with what it started): ChatGPT, the agent provider, the MCP provider and management, each an Actor of its own run in this process, with a private folder and a credential under `<home>/programs`. Each provider is connected by exposing its export to management. Each step reads what is there first, so a restart, or a first run that stopped half way, makes nothing twice. Any package Actor an earlier release left is closed before the Hub opens, and its files are left where they are.
141
77
  - **`/oauth/chatgpt`:** where ChatGPT sends the browser back after sign-in. It takes `GET` only and hands the whole address, which holds the sign-in's code, to `login.complete`. Then it sends the tab on (303) to `/oauth/chatgpt?result=<outcome>`, so the code leaves the tab's address and history; that page says how it went and links back to the shell. The code is never logged or shown, and no referrer is sent.
142
- - **Named rules, `app.rules@1`:** conveniences the person turns on, served by the gateway on `/api` as `rules` (`list`, `set`, and `changed`). Each is named and off until the person turns it on, and the ones that are on are kept in the person's store under `app/rules`. The gateway acts on a rule that is on as the person, a manager, so only within what the person could grant: it hears each request through `grants.requested`, and goes through the open ones at start and whenever a rule is turned on. It approves a match the way an approver does, with the call the request asked for, and never declines; whatever no rule matches stays for the person.
143
- - **"Let an agent use what it installs"** (`agents-use-what-they-install`) approves a request to expose an Actor's export to the agent it was installed for (its `installedFor`), while the Actor isn't closed. `installedFor` is provenance only: nothing but a rule that is on acts on it.
144
- - **`layout@1`:** the person exports it, so a program bound to it places a view as the person does. Each placement records `by`, the Actor that placed it, from the call's caller as the Hub names it (the person, through `/api`); no input sets it. The layout is kept in the person's `store` slot (`kv@1`) under the key `layout`, and the app binds that slot to the built-in `storage` where there is one.
145
- - `place` takes only a `view` module of a package Actor, with no `after` meaning last.
146
- - `move` with no `after` means first.
147
- - Every change tells `changed`.
148
- - **Packages and systems, as files:** for the person's UIs only, a tab by its session and the CLI by its token, sent as `Authorization: Bearer`, which no other page can send.
149
- - `GET /packages/<hash>.agentorg`: a stored package's archive, made again from its stored tree in the SDK's deterministic tar, so the same bytes `agentorg build` writes.
150
- - `POST /packages`: an archive to add, through a private temporary file in the home, verified by `hub.packages.add`, then deleted. It's answered with the package's hash and manifest.
151
- - `GET /system`: the system's file, `<name>.agentorg-system`, a tar of `composition.json` (the installer's `exportSystem`) and `packages/<hash>.agentorg` for every package it pins.
152
- - `POST /system`: a system file. Its entries must be exactly `composition.json` and `packages/sha256-<64 hex>.agentorg`, regular files only. Each package is added under its hash's name, so one whose hash isn't its name is refused. Then the installer's `importSystem` runs with the person's authority.
153
- - Files are 64 MiB at most (`too_large`, 413 past it), and failures answer `{error}` as `/api` does.
154
- - The person's `installer` slot, bound by the app's first run, serves both.
155
- - **`/frames/`:** a view's frame, its runtime and its bundle, for `view` modules only, and only by package hash. Every response's policy is `sandbox allow-scripts`, so whatever loads there runs on an opaque origin, even opened as a top page, and never as the shell's origin, where the session is. It allows scripts only from the gateway's `/frames/`, inline styles, and no fetches, forms or windows. The frame's origin is opaque, so its module scripts are CORS requests from `Origin: null`: only those are answered `Access-Control-Allow-Origin: null`, and nothing there reads or needs the session.
156
78
  - **The app's own pages** carry a policy of their own: scripts and styles from the app only, framed by nothing.
157
- - **The shell,** `@agentorg/shell`, is what the gateway serves at `/`: one socket to `/api`, and nothing it decides on its own. It is built on `@agentorg/kit`: its dialogs, menus, switches, tabs, icons and the column's handle are the kit's.
158
- - **Agents** are the package Actors with a `chat` view. Selecting one mounts that view in the main container, with the placements beside it whose `actor` is that agent or whose `by` is. Between them, a handle (dragged, or the arrow keys) sets that column's width, from 280 to 640 px and at most half the stage, kept in this browser; an agent with nothing beside it has no column, and its chat takes the width. A placed view's frame fills its placement, whatever it draws: beside an agent, the column's height is shared among its placements, each at least 220 px (the column scrolls past that), and on Home each placement is 300 px high. The handle is react-resizable-panels', through the kit; while it's dragged, frames take no pointer events, so a drag over a view keeps going.
159
- - **Home** shows the open grant requests, with Allow and Decline, then every placement of `layout@1`, in order. Each event (`layout` `changed`, `grants` `requested` and `decided`, `actors` `changed`, and the audit's package and binding entries) reads its part again. A subscription the gateway ends is made again after a wait (1 s, growing to 30 s while it keeps ending), and what it says is read again then; a view's own subscriptions end in its frame instead.
160
- - **Settings** reads the Actors, packages and connections through `hub.*`, and the ChatGPT account through `login` when it's bound; the person is "you". An external Actor, the person included, shows whether it's connected; a package Actor its process state; a built-in one runs inside the Hub. **Packages** downloads each archive (`GET /packages/<hash>.agentorg`) and installs one from a file: uploaded to `POST /packages`, then `installer.plan` shows each slot's candidates (a slot's only one preselected), `installer.install` makes it with the person's picks (a connection the person can't grant is named, to leave unconnected), and its views can be placed on home; slots left unconnected and seeds that didn't land are listed. **System** exports the system as one file (`GET /system`), listing what it leaves out, and imports one (`POST /system`): what it made, what isn't as it was, and each management connection, for the person to grant one by one.
161
- - **New agent** is offered once the first run has recorded the app's assistant, by hash, in the person's store (`app/first-run`), never a package found by its name. It is `installer.install` of that package with step 5's connections plus `logic.installer` to the installer, less the grants switched off, started, all or nothing; then it opens. The ChatGPT and installer it connects to are the ones the person's `login` and `installer` are bound to. `installAgent` in `@agentorg/shell/agent-bindings` makes that call, for a test too, and returns the installer's answer. "install Actors" needs "create and run Actors": with that off, it is off too and can't be switched on. A refusal is said plainly in the dialog, in room kept for it: a grant that isn't the person's to give, by name, or that AgentOrg isn't set up yet. A grant left on that the installer didn't connect, or a seed that didn't land, is listed before the agent opens.
162
- - **Views** each get their own frame and `FrameHost`. Their calls run with `view: {actor, module}`, `openExternal` opens a new tab with no opener, `signIn` is the shell's ChatGPT sign-in, and their log lines go to their Actor's log (`agentorg call actors logs`). Each frame watches its view's slots while it's open, loads with the bound ones, and passes the frame each change, so a view placed before its Actor runs comes alive when it does.
163
- - **ChatGPT sign-in** calls `login.start`, opens the consent page in a new tab, and moves on when `login` says `signed_in`. Until the Actor the person's `login` is bound to is connected, its button is disabled and says ChatGPT is starting; nothing opens from a wait, and a sign-in asked for meanwhile (a view's `signIn`) is refused with "ChatGPT is still starting. Try again in a moment." The one-time plan notice is remembered in the person's store under `ui/plan-notice`.
79
+ - **The shell,** `@agentorg/shell`, is what the gateway serves at `/`: one socket to `/api`, and nothing it decides on its own. Its pages are fixed: Agents, one agent, Chat, Skills, MCP connections and Settings, each reading the person's slots and what is exposed to the person.
@@ -1,5 +1,4 @@
1
- import type { Processes } from "./processes.js";
2
- import type { AuditRecord, Decision, HubState, RequestRecord } from "./state.js";
1
+ import type { AuditRecord, HubState } from "./state.js";
3
2
  type Listener = {
4
3
  caller: string;
5
4
  emit(payload: unknown): void;
@@ -12,14 +11,10 @@ type Listener = {
12
11
  export declare class HubActor {
13
12
  #private;
14
13
  /** `connected` says whether an Actor has a channel to the Hub now. */
15
- constructor(state: HubState, processes: Processes, connected: (actorId: string) => boolean);
14
+ constructor(state: HubState, connected: (actorId: string) => boolean);
16
15
  call(exported: string, method: string, caller: string, input: unknown): Promise<unknown>;
17
16
  /** Listen to one of the hub's events; returns the way to stop. */
18
17
  subscribe(exported: string, event: string, listener: Listener): () => void;
19
- /** A request, to the subscribers who could approve it. */
20
- requested(request: RequestRecord, approvers: string[]): void;
21
- /** A decision, to the subscribers its request went to and its requester. */
22
- decided(request: RequestRecord, status: Decision, approvers: string[]): void;
23
18
  exportsChanged(actor: string): void;
24
19
  /** An Actor's record changed, or it connected or went: what `hub.actors` gives for it may differ. */
25
20
  actorChanged(actor: string): void;
@@ -1,6 +1,4 @@
1
1
  import { Refused } from "@agentorg/sdk";
2
- import { buildSource, checkSource } from "./build.js";
3
- import { readLogs } from "./logs.js";
4
2
  const wiring = (input) => ({
5
3
  consumer: String(input.consumer),
6
4
  slot: String(input.slot),
@@ -15,113 +13,24 @@ const wiring = (input) => ({
15
13
  export class HubActor {
16
14
  #listeners = new Map();
17
15
  #handlers;
18
- /** The build running now, if any; the next one waits for it. */
19
- #building = Promise.resolve();
20
- /** Callers with a build waiting or running. */
21
- #builders = new Set();
22
16
  /** `connected` says whether an Actor has a channel to the Hub now. */
23
- constructor(state, processes, connected) {
24
- /**
25
- * A package Actor's record with its view modules, which a shell can place, and whether this
26
- * machine can run its process now.
27
- */
28
- const withViews = (actor) => {
29
- if (actor.package === "external" || actor.package === "builtin")
30
- return actor;
31
- const host = processes.status;
32
- const record = host ? { ...actor, host } : actor;
33
- let modules;
34
- try {
35
- ({ modules } = state.package(actor.package).manifest);
36
- }
37
- catch {
38
- return record; // A closed Actor's package may be gone.
39
- }
40
- return {
41
- ...record,
42
- views: Object.keys(modules).filter((name) => modules[name]?.placement === "view"),
43
- };
44
- };
45
- /** An Actor's record as `hub.actors` gives it: with its views, and whether it is connected. */
17
+ constructor(state, connected) {
18
+ /** An Actor's record as `hub.actors` gives it, with whether it is connected. */
46
19
  const recordOf = (actor) => ({
47
- ...withViews(actor),
20
+ ...actor,
48
21
  connected: connected(actor.actorId),
49
22
  });
50
23
  this.#handlers = {
51
- packages: {
52
- add: (caller, input) => state.addPackage(caller, String(input.path)),
53
- list: () => ({ packages: state.packages() }),
54
- get: (_, input) => state.package(String(input.hash)),
55
- remove: (caller, input) => state.removePackage(caller, String(input.hash)),
56
- // One build at a time: each runs esbuild and a describer process. The source is checked
57
- // before it waits, and a caller has one build waiting or running at most.
58
- build: async (caller, input) => {
59
- const entries = checkSource(input.files);
60
- // A build runs the source's code in the OS sandbox: where host processes can't run,
61
- // neither can a build, and the reason is the same.
62
- await processes.ready();
63
- if (this.#builders.has(caller))
64
- throw new Refused("busy", "A build of yours is already waiting or running.");
65
- this.#builders.add(caller);
66
- const sandbox = (paths) => {
67
- const command = processes.sandboxCommand(paths);
68
- if (!command)
69
- throw new Refused("unsupported", "Host Actors can't start here.");
70
- return command;
71
- };
72
- const next = this.#building.then(() => buildSource(state.home, entries, sandbox, (file) => {
73
- const added = state.addPackage(caller, file);
74
- state.auditHub("package.build", { hash: added.hash, name: added.manifest.name, version: added.manifest.version }, caller);
75
- return added;
76
- }));
77
- this.#building = next.catch(() => { });
78
- return next.finally(() => this.#builders.delete(caller));
79
- },
80
- },
81
24
  actors: {
82
25
  create: (caller, input) => state.createActor(caller, {
83
26
  name: String(input.name),
84
- ...(typeof input.package === "string" ? { package: input.package } : {}),
85
27
  ...(Array.isArray(input.bindings)
86
28
  ? { bindings: input.bindings }
87
29
  : {}),
88
- ...(typeof input.for === "string" ? { for: input.for } : {}),
89
30
  }),
90
31
  list: () => ({ actors: state.actors().map(recordOf) }),
91
32
  get: (_, input) => recordOf(state.actor(String(input.actorId))),
92
- start: async (caller, input) => {
93
- const actorId = String(input.actorId);
94
- state.checkStart(caller, actorId);
95
- // Probed again each time, so a change on the machine shows.
96
- await processes.ready();
97
- state.start(caller, actorId);
98
- processes.start(actorId);
99
- },
100
- // The state changes first, so the exit that follows is never taken for a crash.
101
- stop: async (caller, input) => {
102
- const actorId = String(input.actorId);
103
- state.stop(caller, actorId);
104
- await processes.stop(actorId);
105
- },
106
- // A running Actor is stopped first, as `stop` does it: recorded as stopped, so nothing
107
- // waiting to start it runs it again, then its process is let go with stop's grace. Then
108
- // the Actor is closed.
109
- close: async (caller, input) => {
110
- const actorId = String(input.actorId);
111
- const actor = state.actor(actorId);
112
- if (actor.state === "running" &&
113
- actor.package !== "external" &&
114
- actor.package !== "builtin")
115
- state.stop(caller, actorId);
116
- await processes.stop(actorId);
117
- state.closeActor(caller, actorId);
118
- },
119
- logs: (_, input) => {
120
- // The Actor must exist; its lines are its process's output and its views' lines.
121
- const { actorId } = state.actor(String(input.actorId));
122
- const limit = typeof input.limit === "number" ? input.limit : 100;
123
- return { lines: readLogs(state.home, actorId, limit) };
124
- },
33
+ close: (caller, input) => state.closeActor(caller, String(input.actorId)),
125
34
  },
126
35
  grants: {
127
36
  bind: (caller, input) => state.bind(caller, wiring(input)),
@@ -133,14 +42,6 @@ export class HubActor {
133
42
  ...(typeof input.as === "string" ? { as: input.as } : {}),
134
43
  }),
135
44
  unexpose: (caller, input) => state.unexpose(caller, String(input.to), String(input.slot)),
136
- request: (caller, input) => ({
137
- requestId: state.request(caller, wiring(input), String(input.reason)).requestId,
138
- }),
139
- requests: (caller) => ({ requests: state.requests(caller) }),
140
- mine: (caller, input) => ({
141
- requests: state.mine(caller, typeof input.limit === "number" ? input.limit : 100),
142
- }),
143
- decline: (caller, input) => state.decline(caller, String(input.requestId)),
144
45
  },
145
46
  bindings: {
146
47
  list: (_, input) => ({
@@ -178,14 +79,6 @@ export class HubActor {
178
79
  if (!to || to(listener.caller))
179
80
  listener.emit(payload);
180
81
  }
181
- /** A request, to the subscribers who could approve it. */
182
- requested(request, approvers) {
183
- this.#send("grants.requested", request, (caller) => approvers.includes(caller));
184
- }
185
- /** A decision, to the subscribers its request went to and its requester. */
186
- decided(request, status, approvers) {
187
- this.#send("grants.decided", { request, status }, (caller) => approvers.includes(caller));
188
- }
189
82
  exportsChanged(actor) {
190
83
  this.#send("exports.changed", { actor });
191
84
  }
@@ -1,6 +1,4 @@
1
1
  export { HubActor } from "./hub-actor.js";
2
- export { blockedAddresses, isPublicAddress, type NetOptions } from "./net.js";
3
2
  export { type ChannelHandle, Hub, type HubOptions } from "./router.js";
4
3
  export { type Listener, listen } from "./server.js";
5
- export { type ActorRecord, type ActorState, type AuditRecord, type BindingRecord, type CallOutcome, type Decision, type Declaration, type Exit, exposedName, HUB, HubState, NET, PERSON, type RequestRecord, type Side, STORAGE, type StateEvents, type Wiring, } from "./state.js";
6
- export { STORAGE_LIMITS, type StorageLimits } from "./storage.js";
4
+ export { type ActorRecord, type ActorState, type AuditRecord, type BindingRecord, type CallOutcome, type Declaration, exposedName, HUB, HubState, PERSON, type Side, type StateEvents, type Wiring, } from "./state.js";
@@ -1,6 +1,4 @@
1
1
  export { HubActor } from "./hub-actor.js";
2
- export { blockedAddresses, isPublicAddress } from "./net.js";
3
2
  export { Hub } from "./router.js";
4
3
  export { listen } from "./server.js";
5
- export { exposedName, HUB, HubState, NET, PERSON, STORAGE, } from "./state.js";
6
- export { STORAGE_LIMITS } from "./storage.js";
4
+ export { exposedName, HUB, HubState, PERSON, } from "./state.js";
@@ -1,33 +1,22 @@
1
1
  import { type Duplex } from "@agentorg/wire";
2
- import { type NetOptions } from "./net.js";
3
- import { type ProcessOptions } from "./processes.js";
4
2
  import { HubState } from "./state.js";
5
- import { type StorageLimits } from "./storage.js";
6
3
  export interface HubOptions {
7
4
  /** How long a new channel has to finish hello before it is closed. */
8
5
  helloTimeoutMs?: number;
9
6
  /**
10
- * How long a provider has to answer a call, or to accept or refuse an open or http stream; past
7
+ * How long a provider has to answer a call; past
11
8
  * it the caller gets OutcomeUnknown and the provider's stream is reset.
12
9
  */
13
10
  answerTimeoutMs?: number;
14
- /** What a consumer's stores may hold (defaults in storage.ts). */
15
- storage?: StorageLimits;
16
11
  /** The schema-check pool: its size and each check's budget (defaults in validate.ts). */
17
12
  checks?: {
18
13
  size?: number;
19
14
  budgetMs?: number;
20
15
  compileBudgetMs?: number;
21
16
  };
22
- /** Package Actors' processes: their sandbox, memory and timings (defaults in processes.ts). */
23
- processes?: ProcessOptions;
24
- /** The built-in `net` Actor's resolver, extra CA and idle timeout (defaults in net.ts). */
25
- net?: NetOptions;
26
17
  }
27
18
  /** A channel the Hub took: `closed` settles when it ends. */
28
19
  export interface ChannelHandle {
29
- /** Settles when the channel's hello is admitted; never, if it isn't. */
30
- admitted: Promise<void>;
31
20
  closed: Promise<void>;
32
21
  close(): void;
33
22
  }
@@ -42,56 +31,16 @@ export declare class Hub {
42
31
  #private;
43
32
  readonly state: HubState;
44
33
  private constructor();
45
- /**
46
- * Open the Hub in its home. The host sandbox is probed at once; when it is available, package
47
- * Actors recorded as `running` get their processes back.
48
- */
34
+ /** Open the Hub in its home. */
49
35
  static open(home: string, options?: HubOptions): Hub;
50
36
  /** Whether an Actor has a channel now. */
51
37
  connected(actorId: string): boolean;
52
38
  /**
53
39
  * Take a channel. Its first stream must be `hello`, and nothing else may open before it is
54
- * admitted. An external client's hello carries its credential, within the hello deadline. A
55
- * channel the Hub made itself, a pipe to a package Actor's process it spawned, is given with
56
- * that Actor's id: its hello names that Actor and needs no credential, and its spawner keeps
57
- * the deadline. The handle settles when the channel ends, and closes it.
58
- */
59
- accept(channel: Duplex, admitted?: {
60
- actorId: string;
61
- }): ChannelHandle;
62
- /**
63
- * A call from one of a package Actor's view modules, run in this process for the gateway that
64
- * shows it (step 4): through `<module>.<slot>` of the Actor, as the Actor, checked and audited
65
- * like any call. A module that isn't a view of the Actor's package is refused.
66
- */
67
- viewCall(actorId: string, module: string, slot: string, method: string, input: unknown): Promise<unknown>;
68
- /**
69
- * Events of a view module's slot, as `viewCall` reaches its methods. `onEvent` may return a
70
- * promise: the next event waits for it. Returns how to stop; `onEnd` hears when it ended
71
- * otherwise, with the reason if it wasn't a clean end.
72
- */
73
- viewSubscribe(actorId: string, module: string, slot: string, event: string, onEvent: (payload: unknown) => void | Promise<void>, onEnd?: (error?: Error) => void): () => void;
74
- /**
75
- * A view module's slots, for the gateway's frame that shows it: `onSlot` hears each slot (named
76
- * within the module, as `viewCall` takes it) that is bound now, at once, then every change:
77
- * bound, unbound, and bound again when it is usable again: its provider's channel or the
78
- * Actor's own comes back. Refused unless `module` is one of the view modules of the Actor's
79
- * package; the Actor needn't be running. Returns how to stop, the only way a listener goes
80
- * (closing the Actor unbinds each slot, which it hears, but doesn't stop it).
81
- */
82
- viewSlots(actorId: string, module: string, onSlot: (slot: string, bound: boolean) => void): () => void;
83
- /**
84
- * A line a view module logged, into its Actor's log, marked with the module. The Hub bounds it
85
- * itself: a known level, the text cut to 4 KiB, at most 16 fields of 1 KiB each, and its own time.
86
- * Refused `forbidden` for a module that isn't a view, `unknown` for no such Actor (or a closed
87
- * one whose package is gone); the Actor may be stopped or closed. Not audited: it isn't a call.
88
- * A line the disk won't take is dropped.
40
+ * admitted. A hello carries the Actor's credential, within the hello deadline. The handle settles
41
+ * when the channel ends, and closes it.
89
42
  */
90
- viewLog(actorId: string, module: string, line: {
91
- level: string;
92
- message: string;
93
- data?: Record<string, unknown>;
94
- }): void;
95
- /** Kill every host process, close every channel, admitted or not, then the state. */
43
+ accept(channel: Duplex): ChannelHandle;
44
+ /** Close every channel, admitted or not, then the state. */
96
45
  close(): void;
97
46
  }