@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
@@ -1,6 +1,6 @@
1
1
  import { type IncomingMessage, type ServerResponse } from "node:http";
2
2
  import { Hub } from "@agentorg/hub";
3
- import { type FirstRun, type FirstRunOptions } from "./model.js";
3
+ import { type Programs, type ProgramsOptions } from "./programs.js";
4
4
  /** A route another part of the app adds, such as the model Actor's sign-in callback (step 5). */
5
5
  export type Route = (request: IncomingMessage, response: ServerResponse, url: URL) => void;
6
6
  export interface AppOptions {
@@ -11,10 +11,9 @@ export interface AppOptions {
11
11
  /** Where the shell's static files are; `@agentorg/shell`'s build by default. */
12
12
  shell?: string;
13
13
  /**
14
- * The first run, at each start after the person's store is bound: on by default; `false` leaves
15
- * the home as it is.
14
+ * How the first run, at each start, logs and reaches ChatGPT: the app's own by default.
16
15
  */
17
- firstRun?: FirstRunOptions | false;
16
+ firstRun?: Pick<ProgramsOptions, "fetch" | "log">;
18
17
  }
19
18
  export interface App {
20
19
  /** The gateway's origin, `http://127.0.0.1:<port>`. */
@@ -22,8 +21,8 @@ export interface App {
22
21
  /** Where external Actors reach the Hub. */
23
22
  readonly hubUrl: string;
24
23
  readonly hub: Hub;
25
- /** This start's first run: what it found or made, once it's done; none when it was off. */
26
- readonly firstRun?: Promise<FirstRun | undefined>;
24
+ /** This start's first run: the programs it started, once it's done. */
25
+ readonly firstRun: Promise<Programs | undefined>;
27
26
  /** A fresh one-time sign-in address, `<url>/signin#<code>`. */
28
27
  signInUrl(): string;
29
28
  /** Serve `path` with `route`, for another part of the app. */
@@ -41,6 +40,6 @@ export interface App {
41
40
  * The app: a Hub in this process, and the person's gateway, its single running instance. The
42
41
  * gateway holds the person's one channel to the Hub. Browser tabs and the CLI are the person's UIs,
43
42
  * not channels: they reach the gateway at `/api`, and their calls run through the person's slots,
44
- * or as a view's Actor for a view's. The gateway exports `layout@1`, kept in the person's store.
43
+ * and the person's notes are the app's own file.
45
44
  */
46
45
  export declare function startApp(options: AppOptions): Promise<App>;
@@ -3,33 +3,30 @@ import { createServer } from "node:http";
3
3
  import { createRequire } from "node:module";
4
4
  import { dirname, join, normalize, resolve, sep } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
- import { Hub, listen, PERSON, STORAGE } from "@agentorg/hub";
7
- import { accountLogin, appRules, hubActors, hubAudit, hubBindings, hubExports, hubGrants, hubPackages, installer, kv, layout, } from "@agentorg/interfaces";
6
+ import { Hub, listen, PERSON } from "@agentorg/hub";
7
+ import { accountLogin, agents, connections, hubActors, hubAudit, hubBindings, hubExports, hubGrants, skills, } from "@agentorg/interfaces";
8
8
  import { Refused } from "@agentorg/sdk";
9
9
  import { connect } from "@agentorg/sdk/client";
10
10
  import { WebSocketServer } from "ws";
11
11
  import { serveSocket } from "./api.js";
12
- import { serveFrame } from "./frames.js";
13
- import { Layout } from "./layout.js";
14
- import { firstRun, oauthRoute } from "./model.js";
15
- import { Rules } from "./rules.js";
12
+ import { Notes } from "./notes.js";
13
+ import { oauthRoute } from "./oauth.js";
14
+ import { closePackageActors, startPrograms, } from "./programs.js";
16
15
  import { SignIn } from "./signin.js";
17
- import { MAX_TRANSFER, packageArchive, pinnedHashes, readSystem, withTemporaryFile, writeSystem, } from "./transfer.js";
18
16
  /**
19
- * The person's slots the gateway declares: every `hub.*` it holds, its own store, and the two the
20
- * first run binds (either may be unbound): `installer`, and `login`, the model's account sign-in.
17
+ * The person's slots the gateway declares: every `hub.*` it holds, and what the first run binds
18
+ * (any may be unbound): `login`, the model's account sign-in, and management's three.
21
19
  */
22
20
  const SLOTS = {
23
- packages: hubPackages,
24
21
  actors: hubActors,
25
22
  bindings: hubBindings,
26
23
  grants: hubGrants,
27
24
  exports: hubExports,
28
25
  audit: hubAudit,
29
- store: kv,
30
26
  login: accountLogin,
31
- /** The installer, bound by the app's first run: plans, installs, exports and imports. */
32
- installer,
27
+ agents,
28
+ connections,
29
+ skills,
33
30
  };
34
31
  const STATIC = join(dirname(fileURLToPath(import.meta.url)), "..", "..", "static");
35
32
  /** The shell's built files, `@agentorg/shell`'s `dist`. */
@@ -52,11 +49,12 @@ function writePrivate(file, text) {
52
49
  * The app: a Hub in this process, and the person's gateway, its single running instance. The
53
50
  * gateway holds the person's one channel to the Hub. Browser tabs and the CLI are the person's UIs,
54
51
  * not channels: they reach the gateway at `/api`, and their calls run through the person's slots,
55
- * or as a view's Actor for a view's. The gateway exports `layout@1`, kept in the person's store.
52
+ * and the person's notes are the app's own file.
56
53
  */
57
54
  export async function startApp(options) {
58
55
  const home = resolve(options.home);
59
56
  mkdirSync(home, { recursive: true, mode: 0o700 });
57
+ closePackageActors(home);
60
58
  const hub = Hub.open(home);
61
59
  const listener = await listen(hub, {}).catch((error) => {
62
60
  hub.close();
@@ -64,134 +62,39 @@ export async function startApp(options) {
64
62
  });
65
63
  writePrivate(join(home, "url"), `${listener.url}\n`);
66
64
  const signIn = new SignIn();
67
- const changes = new Set();
68
- /** Who hears that a rule was turned on or off. */
69
- const ruleChanges = new Set();
70
- let emitChanged = () => { };
71
- const isView = (actorId, module) => {
72
- try {
73
- const actor = hub.state.actor(actorId);
74
- if (actor.package === "external" || actor.package === "builtin" || actor.state === "closed")
75
- return false;
76
- const { modules } = hub.state.package(actor.package).manifest;
77
- return Object.hasOwn(modules, module) && modules[module]?.placement === "view";
78
- }
79
- catch {
80
- return false;
81
- }
82
- };
83
65
  const credential = readFileSync(join(home, "person-credential"), "utf8").trim();
84
- let logic;
66
+ /** The app's own notes: what the shell remembers. */
67
+ const notes = new Notes(join(home, "app-notes.json"));
85
68
  const person = await connect({
86
69
  hubUrl: listener.url,
87
70
  actorId: PERSON,
88
71
  credential,
89
72
  slots: SLOTS,
90
- exports: { layout },
91
- start(ctx) {
92
- logic = new Layout({
93
- store: () => ({
94
- get: (key) => ctx.slots.store.call.get({ key }),
95
- set: (key, value) => ctx.slots.store.call.set({ key, value: value }),
96
- }),
97
- isView,
98
- changed: () => emitChanged(),
99
- });
100
- const served = logic;
101
- ctx.exports.layout.implement({
102
- get: () => served.get(),
103
- // Who placed it is the caller the Hub names, never the input.
104
- place: (input, { caller }) => served.place(input, caller),
105
- remove: (input) => served.remove(input),
106
- move: (input) => served.move(input),
107
- });
108
- emitChanged = () => {
109
- ctx.exports.layout.emit("changed", {});
110
- for (const tell of [...changes])
111
- tell();
112
- };
113
- },
114
73
  }).catch((error) => {
115
74
  void listener.close();
116
75
  hub.close();
117
76
  throw error;
118
77
  });
119
- const layoutLogic = logic;
120
- // The person's store, where the layout is kept, is the built-in storage's: bound at each start,
121
- // explicitly, as the Hub binds nothing by default.
122
- if (!hub.state.binding(PERSON, "store"))
123
- await person.slots.grants.call
124
- .bind({ consumer: PERSON, slot: "store", provider: STORAGE, export: "kv" })
125
- .catch((error) => {
126
- person.close();
127
- void listener.close();
128
- hub.close();
129
- throw error;
130
- });
131
- /** The person's side of `/api`: its slots, and `layout`, its own export, served here. */
78
+ /** A slot exposed to the person at run time: here exactly while it is bound. */
79
+ const exposedSlot = (slot) => person.exposed().find((one) => one.slot === slot);
132
80
  const personSide = {
133
81
  async call(slot, method, input) {
134
- if (slot === "rules") {
135
- // The person's named rules, the gateway's own, checked as a call through the Hub would be.
136
- const spec = Object.hasOwn(appRules.methods, method)
137
- ? appRules.methods[method]
138
- : undefined;
139
- if (!spec)
140
- throw new Refused("invalid", `rules has no method ${method}.`);
141
- const parsed = spec.input.safeParse(input);
142
- if (!parsed.success)
143
- throw new Refused("invalid", `rules.${method}: ${parsed.error.message}`);
144
- const result = method === "set"
145
- ? await rules.set(parsed.data)
146
- : await rules.list();
147
- const checked = spec.output.safeParse(result);
148
- if (!checked.success)
149
- throw new Refused("bad_output", `rules.${method}: ${checked.error.message}`);
150
- return checked.data;
151
- }
152
- if (slot === "layout") {
153
- const spec = Object.hasOwn(layout.methods, method)
154
- ? layout.methods[method]
155
- : undefined;
156
- if (!spec)
157
- throw new Refused("invalid", `layout has no method ${method}.`);
158
- const parsed = spec.input.safeParse(input);
159
- if (!parsed.success)
160
- throw new Refused("invalid", `layout.${method}: ${parsed.error.message}`);
161
- // Through /api, the caller is the person.
162
- const result = await layoutLogic[method](parsed.data, PERSON);
163
- // Checked as a call through the Hub would be: what's stored may not fit.
164
- const checked = spec.output.safeParse(result);
165
- if (!checked.success)
166
- throw new Refused("bad_output", `layout.${method}: ${checked.error.message}`);
167
- return checked.data;
168
- }
169
- if (!Object.hasOwn(SLOTS, slot))
82
+ if (slot === "store")
83
+ return notes.call(method, input);
84
+ const exposed = Object.hasOwn(SLOTS, slot) ? undefined : exposedSlot(slot);
85
+ if (!exposed && !Object.hasOwn(SLOTS, slot))
170
86
  throw new Refused("invalid", `The person has no slot ${slot}.`);
171
- const calls = person.slots[slot].call;
87
+ const calls = (exposed?.call ?? person.slots[slot].call);
172
88
  const call = Object.hasOwn(calls, method) ? calls[method] : undefined;
173
89
  if (!call)
174
90
  throw new Refused("invalid", `${slot} has no method ${method}.`);
175
91
  return call(input);
176
92
  },
177
93
  subscribe(slot, event, send) {
178
- if (slot === "rules") {
179
- if (event !== "changed")
180
- throw new Refused("invalid", "rules has one event, changed.");
181
- const tell = () => send({});
182
- ruleChanges.add(tell);
183
- return () => void ruleChanges.delete(tell);
184
- }
185
- if (slot === "layout") {
186
- if (event !== "changed")
187
- throw new Refused("invalid", "layout has one event, changed.");
188
- const tell = () => send({});
189
- changes.add(tell);
190
- return () => void changes.delete(tell);
191
- }
192
- if (!Object.hasOwn(SLOTS, slot))
94
+ const exposed = Object.hasOwn(SLOTS, slot) ? undefined : exposedSlot(slot);
95
+ if (!exposed && !Object.hasOwn(SLOTS, slot))
193
96
  throw new Refused("invalid", `The person has no slot ${slot}.`);
194
- const handle = person.slots[slot];
97
+ const handle = (exposed ?? person.slots[slot]);
195
98
  try {
196
99
  return handle.on(event, send);
197
100
  }
@@ -200,40 +103,17 @@ export async function startApp(options) {
200
103
  }
201
104
  },
202
105
  };
203
- const views = {
204
- call: (view, slot, method, input) => hub.viewCall(view.actor, view.module, slot, method, input),
205
- subscribe: (view, slot, event, send, end) => hub.viewSubscribe(view.actor, view.module, slot, event, send, () => end()),
206
- slots: (view, onSlot) => hub.viewSlots(view.actor, view.module, onSlot),
207
- log: (view, level, message, fields) => hub.viewLog(view.actor, view.module, {
208
- level,
209
- message,
210
- ...(fields ? { data: fields } : {}),
211
- }),
212
- };
213
106
  // The first run, beside serving: the shell follows the person's bindings as they're made, so it
214
107
  // needn't wait. What it can't do is logged and tried at the next start.
215
- const ran = options.firstRun === false
216
- ? undefined
217
- : firstRun(personSide, {
218
- log: (message) => process.stderr.write(`${message}\n`),
219
- connected: (actorId) => hub.connected(actorId),
220
- ...options.firstRun,
221
- }).catch((error) => {
222
- process.stderr.write(`First run didn't work: ${error instanceof Error ? error.message : String(error)}\n`);
223
- return undefined;
224
- });
225
- // The person's named rules: off until turned on; their engine starts once the first run is done.
226
- const rules = new Rules({
227
- person: personSide,
108
+ const ran = startPrograms(personSide, {
109
+ home,
110
+ hubUrl: listener.url,
228
111
  log: (message) => process.stderr.write(`${message}\n`),
229
- changed: () => {
230
- for (const tell of [...ruleChanges])
231
- tell();
232
- },
112
+ ...options.firstRun,
113
+ }).catch((error) => {
114
+ process.stderr.write(`First run didn't work: ${error instanceof Error ? error.message : String(error)}\n`);
115
+ return undefined;
233
116
  });
234
- void Promise.resolve(ran)
235
- .then(() => rules.start())
236
- .catch((error) => process.stderr.write(`The rules didn't start: ${error instanceof Error ? error.message : String(error)}\n`));
237
117
  /** The app's own pages: scripts and styles from here only, framed by nothing. */
238
118
  const appCsp = [
239
119
  "default-src 'self'",
@@ -241,7 +121,7 @@ export async function startApp(options) {
241
121
  "style-src 'self' 'unsafe-inline'",
242
122
  "img-src 'self' data:",
243
123
  "connect-src 'self'",
244
- "frame-src 'self'",
124
+ "frame-src 'none'",
245
125
  "object-src 'none'",
246
126
  "base-uri 'none'",
247
127
  "form-action 'self'",
@@ -266,15 +146,6 @@ export async function startApp(options) {
266
146
  const route = routes.get(url.pathname);
267
147
  if (route)
268
148
  return route(request, response, url);
269
- if (url.pathname.startsWith("/frames/")) {
270
- const served = request.method === "GET"
271
- ? serveFrame(url.pathname, origin, bundleOf, request.headers.origin)
272
- : undefined;
273
- if (!served)
274
- return void response.writeHead(404).end();
275
- response.writeHead(served.status, served.headers).end(served.body);
276
- return;
277
- }
278
149
  if (url.pathname === "/api/session" && request.method === "POST") {
279
150
  // Same-origin only: a cross-site form can't trade a code it saw.
280
151
  if (request.headers.origin !== origin)
@@ -294,14 +165,6 @@ export async function startApp(options) {
294
165
  response.writeHead(200, { "Content-Type": "application/json", "Cache-Control": "no-store" });
295
166
  return void response.end(JSON.stringify({ session }));
296
167
  }
297
- // A package's archive, and a system's file, both ways: for the person's UIs only, a tab by its
298
- // session and the CLI by its token, as a bearer, which no other page can send.
299
- if (url.pathname.startsWith("/packages") || url.pathname === "/system") {
300
- const bearer = /^Bearer (\S+)$/.exec(request.headers.authorization ?? "")?.[1];
301
- if (!signIn.isCli(request.headers.authorization) && !signIn.isSession(bearer))
302
- return void response.writeHead(401).end();
303
- return transfer(request, response, url);
304
- }
305
168
  if (url.pathname === "/api/code" && request.method === "POST") {
306
169
  // The CLI's way to sign a browser in again: a fresh code, for its token only.
307
170
  if (!signIn.isCli(request.headers.authorization))
@@ -333,98 +196,6 @@ export async function startApp(options) {
333
196
  });
334
197
  response.end(request.method === "HEAD" ? undefined : body);
335
198
  };
336
- /** Answer a transfer's failure as `/api` answers a call's: `{error}`, with a fitting status. */
337
- const failure = (response, error) => {
338
- const body = error instanceof Refused
339
- ? { name: "Refused", message: error.message, code: error.code }
340
- : error instanceof Error &&
341
- (error.name === "NotConnected" || error.name === "OutcomeUnknown")
342
- ? { name: error.name, message: error.message }
343
- : { name: "Refused", message: "The gateway couldn't handle this.", code: "internal" };
344
- const status = body.code === "too_large"
345
- ? 413
346
- : body.code === "invalid" || body.code === "unknown"
347
- ? 400
348
- : 409;
349
- response.writeHead(status, { "Content-Type": "application/json", "Cache-Control": "no-store" });
350
- response.end(JSON.stringify({ error: body }));
351
- };
352
- const sendFile = (response, name, bytes) => {
353
- response.writeHead(200, {
354
- "Content-Type": "application/octet-stream",
355
- "Content-Disposition": `attachment; filename="${name.replace(/[^\w.@-]/g, "_")}"`,
356
- "Cache-Control": "no-store",
357
- "X-Content-Type-Options": "nosniff",
358
- });
359
- response.end(bytes);
360
- };
361
- /**
362
- * `GET /packages/<hash>.agentorg`: a stored package's archive. `POST /packages`: an archive to
363
- * add, verified by the Hub. `GET /system`: the system's file, its composition and every package
364
- * it pins. `POST /system`: a system file, its packages added (each one's hash checked against
365
- * its name), then imported with the person's authority.
366
- */
367
- const transfer = async (request, response, url) => {
368
- try {
369
- const archive = /^\/packages\/(sha256-[0-9a-f]{64})\.agentorg$/.exec(url.pathname);
370
- if (archive && request.method === "GET") {
371
- const hash = archive[1];
372
- const bytes = packageArchive(home, hash);
373
- if (!bytes)
374
- throw new Refused("unknown", `No package ${hash}.`);
375
- const { manifest } = hub.state.package(hash);
376
- return sendFile(response, `${manifest.name}-${manifest.version}.agentorg`, bytes);
377
- }
378
- if (url.pathname === "/packages" && request.method === "POST") {
379
- const bytes = await readBytes(request, MAX_TRANSFER);
380
- const added = await withTemporaryFile(home, "upload.agentorg", bytes, (path) => person.slots.packages.call.add({ path }));
381
- response.writeHead(200, {
382
- "Content-Type": "application/json",
383
- "Cache-Control": "no-store",
384
- });
385
- return void response.end(JSON.stringify(added));
386
- }
387
- if (url.pathname === "/system" && request.method === "GET") {
388
- const { composition } = await person.slots.installer.call.exportSystem({});
389
- const archives = new Map();
390
- for (const hash of pinnedHashes(composition)) {
391
- const bytes = packageArchive(home, hash);
392
- if (bytes)
393
- archives.set(hash, bytes);
394
- }
395
- return sendFile(response, "system.agentorg-system", writeSystem(composition, archives));
396
- }
397
- if (url.pathname === "/system" && request.method === "POST") {
398
- const { composition, packages } = readSystem(await readBytes(request, MAX_TRANSFER));
399
- // Named by its hash, so the Hub refuses an archive whose hash isn't its name.
400
- for (const [hash, bytes] of packages)
401
- await withTemporaryFile(home, `${hash}.agentorg`, bytes, (path) => person.slots.packages.call.add({ path }));
402
- const imported = await person.slots.installer.call.importSystem({ composition });
403
- response.writeHead(200, {
404
- "Content-Type": "application/json",
405
- "Cache-Control": "no-store",
406
- });
407
- return void response.end(JSON.stringify(imported));
408
- }
409
- response.writeHead(405).end();
410
- }
411
- catch (error) {
412
- failure(response, error);
413
- }
414
- };
415
- const bundleOf = (hash, module) => {
416
- try {
417
- const entry = hub.state.package(hash).manifest.modules[module];
418
- if (entry?.placement !== "view")
419
- return undefined;
420
- const dir = join(home, "packages", hash);
421
- const file = resolve(dir, entry.entry);
422
- return file.startsWith(dir + sep) ? file : undefined;
423
- }
424
- catch {
425
- return undefined;
426
- }
427
- };
428
199
  const sockets = new WebSocketServer({ noServer: true, maxPayload: MAX_MESSAGE });
429
200
  server.on("upgrade", (request, socket, head) => {
430
201
  // An upgraded socket has no error handler of its own: a client that resets would crash the app.
@@ -441,7 +212,7 @@ export async function startApp(options) {
441
212
  sockets.handleUpgrade(request, socket, head, (ws) => {
442
213
  let served;
443
214
  const serve = () => {
444
- served = serveSocket({ send: (text) => ws.send(text), close: (code, reason) => ws.close(code, reason) }, { person: personSide, views });
215
+ served = serveSocket({ send: (text) => ws.send(text), close: (code, reason) => ws.close(code, reason) }, { person: personSide });
445
216
  };
446
217
  // The CLI is in by its token; a tab says its session first, or is closed.
447
218
  if (cli)
@@ -487,21 +258,21 @@ export async function startApp(options) {
487
258
  writePrivate(join(home, "app.json"), `${JSON.stringify({ url: origin, pid: process.pid })}\n`);
488
259
  let closing;
489
260
  let stopped = () => { };
261
+ let lost = false;
490
262
  const closed = new Promise((done) => {
491
- stopped = () => done({ lost: false });
263
+ stopped = () => done({ lost });
492
264
  // The person's channel gone (taken over, or the Hub gone): the gateway can't serve, so it stops.
493
265
  void person.closed.then(() => {
494
266
  if (!closing) {
267
+ lost = true;
495
268
  void close();
496
- done({ lost: true });
497
269
  }
498
270
  });
499
271
  });
500
272
  const close = () => {
501
273
  closing ??= (async () => {
502
274
  // A first run still going finishes first, so it isn't cut off half way.
503
- await ran;
504
- rules.close();
275
+ const programs = await ran;
505
276
  const ours = (file, text) => {
506
277
  if (file === "cli-token")
507
278
  return text.trim() === signIn.cliToken;
@@ -531,6 +302,7 @@ export async function startApp(options) {
531
302
  const serverClosed = new Promise((done) => server.close(() => done()));
532
303
  server.closeAllConnections();
533
304
  await serverClosed;
305
+ await programs?.close();
534
306
  person.close();
535
307
  await person.closed;
536
308
  await listener.close();
@@ -543,7 +315,7 @@ export async function startApp(options) {
543
315
  url: origin,
544
316
  hubUrl: listener.url,
545
317
  hub,
546
- ...(ran ? { firstRun: ran } : {}),
318
+ firstRun: ran,
547
319
  signInUrl: () => `${origin}/signin#${signIn.code()}`,
548
320
  route: (path, route) => void routes.set(path, route),
549
321
  close,
@@ -574,24 +346,6 @@ function contentType(file) {
574
346
  return "image/svg+xml";
575
347
  return "application/octet-stream";
576
348
  }
577
- /** A request's body as bytes, up to `max`: past it, `Refused("too_large")`. */
578
- function readBytes(request, max) {
579
- return new Promise((done, failed) => {
580
- const chunks = [];
581
- let size = 0;
582
- request.on("data", (chunk) => {
583
- size += chunk.length;
584
- if (size > max) {
585
- request.destroy();
586
- failed(new Refused("too_large", `A file here is ${max / 1024 / 1024} MiB at most.`));
587
- }
588
- else
589
- chunks.push(chunk);
590
- });
591
- request.on("end", () => done(new Uint8Array(Buffer.concat(chunks))));
592
- request.on("error", failed);
593
- });
594
- }
595
349
  function readBody(request) {
596
350
  return new Promise((done, failed) => {
597
351
  let body = "";
@@ -1,7 +1,6 @@
1
- export { type PersonSide, type Socket, serveSocket, type View, type ViewCalls } from "./api.js";
2
- export { frameCsp, serveFrame, type ViewBundle } from "./frames.js";
1
+ export { type PersonSide, type Socket, serveSocket } from "./api.js";
3
2
  export { type App, type AppOptions, type Route, startApp } from "./gateway.js";
4
- export { LAYOUT_KEY, Layout, type LayoutStore, type PlacementRecord } from "./layout.js";
5
- export { type FirstRun, type FirstRunOptions, firstRun, oauthRoute, type PersonCalls, type Target, } from "./model.js";
3
+ export { Notes } from "./notes.js";
4
+ export { oauthRoute, type PersonCalls } from "./oauth.js";
5
+ export { type Programs, type ProgramsOptions, startPrograms } from "./programs.js";
6
6
  export { SignIn } from "./signin.js";
7
- export { MAX_TRANSFER, packageArchive, pinnedHashes, readSystem, type SystemComposition, withTemporaryFile, writeSystem, } from "./transfer.js";
package/dist/src/index.js CHANGED
@@ -1,7 +1,6 @@
1
1
  export { serveSocket } from "./api.js";
2
- export { frameCsp, serveFrame } from "./frames.js";
3
2
  export { startApp } from "./gateway.js";
4
- export { LAYOUT_KEY, Layout } from "./layout.js";
5
- export { firstRun, oauthRoute, } from "./model.js";
3
+ export { Notes } from "./notes.js";
4
+ export { oauthRoute } from "./oauth.js";
5
+ export { startPrograms } from "./programs.js";
6
6
  export { SignIn } from "./signin.js";
7
- export { MAX_TRANSFER, packageArchive, pinnedHashes, readSystem, withTemporaryFile, writeSystem, } from "./transfer.js";
@@ -0,0 +1,11 @@
1
+ /** A file of JSON values by key, answering as `kv@1` does. Each write replaces it whole. */
2
+ export declare class Notes {
3
+ #private;
4
+ constructor(file: string);
5
+ get(key: string): {
6
+ value?: unknown;
7
+ };
8
+ set(key: string, value: unknown): object;
9
+ /** One `kv@1` call, checked as a call through the Hub would be. */
10
+ call(method: string, input: unknown): unknown;
11
+ }
@@ -0,0 +1,64 @@
1
+ // The app's own notes: what the person's pages and the gateway keep, in one private file.
2
+ import { readFileSync, renameSync, writeFileSync } from "node:fs";
3
+ import { kv } from "@agentorg/interfaces";
4
+ import { Refused } from "@agentorg/sdk";
5
+ /** Keys read at once by a `list`. */
6
+ const PAGE = 1000;
7
+ /** A file of JSON values by key, answering as `kv@1` does. Each write replaces it whole. */
8
+ export class Notes {
9
+ #file;
10
+ #values;
11
+ constructor(file) {
12
+ this.#file = file;
13
+ let raw;
14
+ try {
15
+ raw = readFileSync(file, "utf8");
16
+ }
17
+ catch (error) {
18
+ if (error.code !== "ENOENT")
19
+ throw error;
20
+ }
21
+ this.#values = raw === undefined ? {} : JSON.parse(raw);
22
+ }
23
+ get(key) {
24
+ return Object.hasOwn(this.#values, key) ? { value: this.#values[key] } : {};
25
+ }
26
+ set(key, value) {
27
+ this.#values[key] = value;
28
+ this.#save();
29
+ return {};
30
+ }
31
+ /** One `kv@1` call, checked as a call through the Hub would be. */
32
+ call(method, input) {
33
+ const spec = Object.hasOwn(kv.methods, method)
34
+ ? kv.methods[method]
35
+ : undefined;
36
+ if (!spec)
37
+ throw new Refused("invalid", `store has no method ${method}.`);
38
+ const parsed = spec.input.safeParse(input);
39
+ if (!parsed.success)
40
+ throw new Refused("invalid", `store.${method}: ${parsed.error.message}`);
41
+ const given = parsed.data;
42
+ if (method === "get")
43
+ return this.get(given.key);
44
+ if (method === "set")
45
+ return this.set(given.key, given.value);
46
+ if (method === "delete") {
47
+ const deleted = Object.hasOwn(this.#values, given.key);
48
+ delete this.#values[given.key];
49
+ if (deleted)
50
+ this.#save();
51
+ return { deleted };
52
+ }
53
+ const { prefix = "", after, limit = PAGE } = given;
54
+ const found = Object.keys(this.#values)
55
+ .filter((key) => key.startsWith(prefix) && (after === undefined || key > after))
56
+ .sort();
57
+ const keys = found.slice(0, limit);
58
+ return { keys, next: found.length > limit ? (keys.at(-1) ?? null) : null };
59
+ }
60
+ #save() {
61
+ writeFileSync(`${this.#file}.tmp`, JSON.stringify(this.#values), { mode: 0o600, flush: true });
62
+ renameSync(`${this.#file}.tmp`, this.#file);
63
+ }
64
+ }
@@ -0,0 +1,16 @@
1
+ import type { IncomingMessage, ServerResponse } from "node:http";
2
+ /**
3
+ * How the app's parts reach the Hub: the person's own calls, as `/api` makes them. A call that
4
+ * doesn't reach its provider rejects with an error named `NotConnected`, as `/api` names it.
5
+ */
6
+ export interface PersonCalls {
7
+ call(slot: string, method: string, input: unknown): Promise<unknown>;
8
+ }
9
+ /**
10
+ * `/oauth/chatgpt`: where ChatGPT sends the browser back. It hands the whole callback address to
11
+ * the person's `login.complete`, then sends the tab on to `?result=<outcome>`, an address without
12
+ * the sign-in's code, so the code stays out of the tab's address and history; that page says how
13
+ * it went and links back to the shell. The code is never logged or shown, and no page sends a
14
+ * referrer.
15
+ */
16
+ export declare function oauthRoute(person: PersonCalls): (request: IncomingMessage, response: ServerResponse, url: URL) => void;