@agentorg/cli 0.0.3 → 0.0.4

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 (153) hide show
  1. package/README.md +14 -10
  2. package/dist/bundled/index.json +4 -4
  3. package/dist/bundled/{sha256-87e121cbe58279f3a633e61c9773b61fc17fd53eac3d7c6f037925cbfd5d5384.agentorg → sha256-01d69bc3888c2a53963f4413d47de909d129ad27c78e9af6d830bb50c3478419.agentorg} +0 -0
  4. package/dist/bundled/{sha256-51ecf151e590f5e57f28229d4cb36e4932a2f1670e50ddf1a3ccf335a1ee146d.agentorg → sha256-84165e3be5c904fc971d983dab31102e07cca725d8629a6fd7d118fa3a0a88b8.agentorg} +0 -0
  5. package/dist/bundled/sha256-ade9132b3f34b4c39db92adeadc7e540dc745e4a81b5b54f5d45bf9ec92bca75.agentorg +0 -0
  6. package/dist/bundled/{sha256-b76ec31282e5b863ee9569dfd9d50b283a21101cbe1b3fac23d1cbcf16b9a408.agentorg → sha256-f4330f5987f37d8cf3aeb44d2f831b573641a87186daa2f811f0c35ba04804f0.agentorg} +0 -0
  7. package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/build.d.ts +2 -2
  8. package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/build.js +14 -4
  9. package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/hub-actor.js +8 -0
  10. package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/index.d.ts +1 -1
  11. package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/index.js +1 -1
  12. package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/router.js +40 -16
  13. package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/state.d.ts +63 -0
  14. package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/state.js +177 -36
  15. package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/storage.d.ts +2 -1
  16. package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/storage.js +3 -2
  17. package/{node_modules → dist/node_modules}/@agentorg/hub/package.json +3 -0
  18. package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/hub.d.ts +43 -3
  19. package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/hub.js +40 -3
  20. package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/index.d.ts +1 -0
  21. package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/index.js +1 -0
  22. package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/installer.d.ts +37 -0
  23. package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/installer.js +34 -3
  24. package/dist/node_modules/@agentorg/interfaces/dist/src/rules.d.ts +35 -0
  25. package/dist/node_modules/@agentorg/interfaces/dist/src/rules.js +37 -0
  26. package/dist/node_modules/@agentorg/kit/dist/src/chat.d.ts +37 -0
  27. package/dist/node_modules/@agentorg/kit/dist/src/chat.js +131 -0
  28. package/dist/node_modules/@agentorg/kit/dist/src/components.d.ts +94 -0
  29. package/dist/node_modules/@agentorg/kit/dist/src/components.js +66 -0
  30. package/dist/node_modules/@agentorg/kit/dist/src/icons.d.ts +17 -0
  31. package/dist/node_modules/@agentorg/kit/dist/src/icons.js +30 -0
  32. package/dist/node_modules/@agentorg/kit/dist/src/index.d.ts +6 -0
  33. package/dist/node_modules/@agentorg/kit/dist/src/index.js +10 -0
  34. package/dist/node_modules/@agentorg/kit/dist/src/markdown.d.ts +9 -0
  35. package/dist/node_modules/@agentorg/kit/dist/src/markdown.js +14 -0
  36. package/dist/node_modules/@agentorg/kit/dist/src/resizable.d.ts +5 -0
  37. package/dist/node_modules/@agentorg/kit/dist/src/resizable.js +8 -0
  38. package/dist/node_modules/@agentorg/kit/dist/src/styles.d.ts +11 -0
  39. package/dist/node_modules/@agentorg/kit/dist/src/styles.js +166 -0
  40. package/dist/node_modules/@agentorg/kit/package.json +44 -0
  41. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/frame/runtime.js +172 -17
  42. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/host/runner.js +168 -11
  43. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/client.d.ts +18 -0
  44. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/client.js +24 -3
  45. package/dist/node_modules/@agentorg/sdk/dist/src/frame-base.d.ts +8 -0
  46. package/dist/node_modules/@agentorg/sdk/dist/src/frame-base.js +64 -0
  47. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame-entry.js +4 -4
  48. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame-host.d.ts +1 -10
  49. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame-host.js +0 -23
  50. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame-protocol.d.ts +0 -8
  51. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame.d.ts +0 -2
  52. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame.js +0 -8
  53. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/host.js +5 -0
  54. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/index.d.ts +1 -1
  55. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/module-host.d.ts +6 -1
  56. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/module-host.js +24 -1
  57. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/module.d.ts +30 -1
  58. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/package.js +111 -6
  59. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/runtime.d.ts +22 -1
  60. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/runtime.js +114 -0
  61. package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/testing.d.ts +14 -2
  62. package/dist/node_modules/@agentorg/sdk/dist/src/testing.js +89 -0
  63. package/{node_modules → dist/node_modules}/@agentorg/shell/dist/app.css +27 -144
  64. package/dist/node_modules/@agentorg/shell/dist/app.js +219 -0
  65. package/{node_modules → dist/node_modules}/@agentorg/shell/package.json +1 -0
  66. package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/index.d.ts +1 -1
  67. package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/ops.d.ts +14 -1
  68. package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/ops.js +22 -2
  69. package/dist/src/cli.js +23 -0
  70. package/dist/src/gateway.js +42 -1
  71. package/dist/src/rules.d.ts +71 -0
  72. package/dist/src/rules.js +157 -0
  73. package/package.json +13 -16
  74. package/dist/bundled/sha256-e4c0e857cea3a721998effe2ca859c4011978b9bc36e63c058bfc17c27a1772e.agentorg +0 -0
  75. package/node_modules/@agentorg/sdk/dist/src/testing.js +0 -51
  76. package/node_modules/@agentorg/shell/dist/app.js +0 -9
  77. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/hub-actor.d.ts +0 -0
  78. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/logs.d.ts +0 -0
  79. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/logs.js +0 -0
  80. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/net.d.ts +0 -0
  81. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/net.js +0 -0
  82. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/processes.d.ts +0 -0
  83. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/processes.js +0 -0
  84. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/router.d.ts +0 -0
  85. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/server.d.ts +0 -0
  86. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/server.js +0 -0
  87. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/validate-worker.d.ts +0 -0
  88. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/validate-worker.js +0 -0
  89. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/validate.d.ts +0 -0
  90. /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/validate.js +0 -0
  91. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/account-login.d.ts +0 -0
  92. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/account-login.js +0 -0
  93. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/chat.d.ts +0 -0
  94. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/chat.js +0 -0
  95. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/http-egress.d.ts +0 -0
  96. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/http-egress.js +0 -0
  97. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/kv.d.ts +0 -0
  98. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/kv.js +0 -0
  99. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/layout.d.ts +0 -0
  100. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/layout.js +0 -0
  101. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/llm-session.d.ts +0 -0
  102. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/llm-session.js +0 -0
  103. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/storage-admin.d.ts +0 -0
  104. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/storage-admin.js +0 -0
  105. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/ui-shell.d.ts +0 -0
  106. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/ui-shell.js +0 -0
  107. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/ui-view.d.ts +0 -0
  108. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/ui-view.js +0 -0
  109. /package/{node_modules → dist/node_modules}/@agentorg/interfaces/package.json +0 -0
  110. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/build.d.ts +0 -0
  111. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/build.js +0 -0
  112. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/canonical.d.ts +0 -0
  113. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/canonical.js +0 -0
  114. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/cli.d.ts +0 -0
  115. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/cli.js +0 -0
  116. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/client-http.d.ts +0 -0
  117. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/client-http.js +0 -0
  118. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/describe.d.ts +0 -0
  119. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/describe.js +0 -0
  120. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/errors.d.ts +0 -0
  121. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/errors.js +0 -0
  122. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame-entry.d.ts +0 -0
  123. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame-protocol.js +0 -0
  124. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/host-main.d.ts +0 -0
  125. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/host-main.js +0 -0
  126. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/host.d.ts +0 -0
  127. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/index.js +0 -0
  128. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/interface.d.ts +0 -0
  129. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/interface.js +0 -0
  130. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/manifest-api.d.ts +0 -0
  131. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/manifest-api.js +0 -0
  132. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/manifest.d.ts +0 -0
  133. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/manifest.js +0 -0
  134. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/module.js +0 -0
  135. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/package.d.ts +0 -0
  136. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/person-commands.d.ts +0 -0
  137. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/person-commands.js +0 -0
  138. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/tar.d.ts +0 -0
  139. /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/tar.js +0 -0
  140. /package/{node_modules → dist/node_modules}/@agentorg/sdk/package.json +0 -0
  141. /package/{node_modules → dist/node_modules}/@agentorg/shell/dist/agent-bindings.js +0 -0
  142. /package/{node_modules → dist/node_modules}/@agentorg/shell/dist/index.html +0 -0
  143. /package/{node_modules → dist/node_modules}/@agentorg/shell/src/agent-bindings.ts +0 -0
  144. /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/bytes.d.ts +0 -0
  145. /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/bytes.js +0 -0
  146. /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/frames.d.ts +0 -0
  147. /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/frames.js +0 -0
  148. /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/index.js +0 -0
  149. /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/transports.d.ts +0 -0
  150. /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/transports.js +0 -0
  151. /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/yamux.d.ts +0 -0
  152. /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/yamux.js +0 -0
  153. /package/{node_modules → dist/node_modules}/@agentorg/wire/package.json +0 -0
@@ -24,6 +24,7 @@
24
24
  },
25
25
  "devDependencies": {
26
26
  "@agentorg/interfaces": "0.0.0",
27
+ "@agentorg/kit": "0.0.0",
27
28
  "@agentorg/sdk": "0.0.0",
28
29
  "@types/react": "19.3.0",
29
30
  "@types/react-dom": "19.3.0",
@@ -1,4 +1,4 @@
1
1
  export { encodeFrame, FrameError, FrameReader, MAX_FRAME } from "./frames.js";
2
- export { type Body, eventBody, type Header, HeaderError, input, parseBody, parseHeader, result, type WireError, type WireErrorName, wireError, } from "./ops.js";
2
+ export { type Body, type Exposure, eventBody, type Header, HeaderError, input, parseBody, parseHeader, result, type WireError, type WireErrorName, wireError, } from "./ops.js";
3
3
  export { MAX_UNREAD, memoryPair, type WebSocketLike, webSocketChannel } from "./transports.js";
4
4
  export { type Duplex, GO_AWAY, Session, type SessionOptions, YamuxError, type YamuxStream, } from "./yamux.js";
@@ -69,11 +69,16 @@ export type Header =
69
69
  op: "withdraw";
70
70
  name: string;
71
71
  }
72
- /** From the Hub to an Actor: one of its slots was bound or unbound. */
72
+ /**
73
+ * From the Hub to an Actor: one of its slots was bound or unbound. A slot made at run time (an
74
+ * export exposed to this Actor) carries `exposed` while bound: the export's described interface
75
+ * and which Actor's export it is. Unbound, it is gone.
76
+ */
73
77
  | {
74
78
  op: "slot";
75
79
  name: string;
76
80
  bound: boolean;
81
+ exposed?: Exposure;
77
82
  }
78
83
  /**
79
84
  * From the Hub to a provider: the same four, naming its export, who is calling, and through which
@@ -89,6 +94,14 @@ export type Header =
89
94
  event?: string;
90
95
  params?: unknown;
91
96
  };
97
+ /** A slot made at run time, as the Hub describes it: the export's interface, and whose it is. */
98
+ export interface Exposure {
99
+ interface: unknown;
100
+ provider: {
101
+ actor: string;
102
+ export: string;
103
+ };
104
+ }
92
105
  export type WireErrorName = "NotConnected" | "Refused" | "OutcomeUnknown";
93
106
  /** How a refusal crosses the wire; the SDK maps it to its error classes. */
94
107
  export interface WireError {
@@ -37,10 +37,30 @@ export function parseHeader(value) {
37
37
  return { op: "offer", name: text(value, "name"), interface: value.interface };
38
38
  case "withdraw":
39
39
  return { op: "withdraw", name: text(value, "name") };
40
- case "slot":
40
+ case "slot": {
41
41
  if (typeof value.bound !== "boolean")
42
42
  throw new HeaderError("A slot header needs bound.");
43
- return { op: "slot", name: text(value, "name"), bound: value.bound };
43
+ if (!("exposed" in value))
44
+ return { op: "slot", name: text(value, "name"), bound: value.bound };
45
+ const exposed = value.exposed;
46
+ if (!value.bound ||
47
+ !isRecord(exposed) ||
48
+ !isRecord(exposed.interface) ||
49
+ !isRecord(exposed.provider))
50
+ throw new HeaderError("A slot header's exposed is a bound slot's {interface, provider}.");
51
+ return {
52
+ op: "slot",
53
+ name: text(value, "name"),
54
+ bound: true,
55
+ exposed: {
56
+ interface: exposed.interface,
57
+ provider: {
58
+ actor: text(exposed.provider, "actor"),
59
+ export: text(exposed.provider, "export"),
60
+ },
61
+ },
62
+ };
63
+ }
44
64
  case "serve": {
45
65
  const kind = value.kind;
46
66
  if (kind !== "call" && kind !== "subscribe" && kind !== "open" && kind !== "http")
package/dist/src/cli.js CHANGED
@@ -6,6 +6,7 @@ import { parseArgs } from "node:util";
6
6
  import { hubHome, personCall, UsageError } from "@agentorg/sdk/person-commands";
7
7
  import WebSocket from "ws";
8
8
  const USAGE = `Usage: agentorg [command] [--home DIR]
9
+ agentorg --version
9
10
 
10
11
  (no command) [--port N] [--no-open] run AgentOrg: the Hub, your gateway and the shell
11
12
  open sign a browser in to the running app
@@ -37,11 +38,33 @@ const { values, positionals } = parseArgs({
37
38
  port: { type: "string" },
38
39
  "no-open": { type: "boolean" },
39
40
  help: { type: "boolean", short: "h" },
41
+ version: { type: "boolean" },
40
42
  },
41
43
  allowPositionals: true,
42
44
  strict: false,
43
45
  });
44
46
  const [command, ...rest] = positionals;
47
+ // `build` and `hub` are the SDK's, which reads their options itself, strictly. Everything else is
48
+ // this command's: an option it doesn't know is a mistake, never a reason to start the app.
49
+ if (command !== "build" && command !== "hub") {
50
+ const unknown = Object.keys(values).find((name) => !["home", "port", "no-open", "help", "version"].includes(name));
51
+ if (unknown !== undefined)
52
+ usage(`Unknown option ${unknown.length === 1 ? "-" : "--"}${unknown}. An argument that starts with - goes after --.`);
53
+ // A value is a word of its own: an option in its place means the value is missing.
54
+ for (const [name, what] of [
55
+ ["home", "a directory"],
56
+ ["port", "a port number"],
57
+ ]) {
58
+ const value = values[name];
59
+ if (typeof value === "boolean" || value?.startsWith("-"))
60
+ usage(`--${name} takes ${what}.`);
61
+ }
62
+ }
63
+ if (values.version && command === undefined) {
64
+ const own = new URL("../../package.json", import.meta.url);
65
+ write(process.stdout, JSON.parse(readFileSync(own, "utf8")).version);
66
+ process.exit(0);
67
+ }
45
68
  if (values.help && command === undefined) {
46
69
  process.stdout.write(USAGE);
47
70
  process.exit(0);
@@ -4,7 +4,7 @@ import { createRequire } from "node:module";
4
4
  import { dirname, join, normalize, resolve, sep } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { Hub, listen, PERSON, STORAGE } from "@agentorg/hub";
7
- import { accountLogin, hubActors, hubAudit, hubBindings, hubExports, hubGrants, hubPackages, installer, kv, layout, } from "@agentorg/interfaces";
7
+ import { accountLogin, appRules, hubActors, hubAudit, hubBindings, hubExports, hubGrants, hubPackages, installer, kv, layout, } from "@agentorg/interfaces";
8
8
  import { Refused } from "@agentorg/sdk";
9
9
  import { connect } from "@agentorg/sdk/client";
10
10
  import { WebSocketServer } from "ws";
@@ -12,6 +12,7 @@ import { serveSocket } from "./api.js";
12
12
  import { serveFrame } from "./frames.js";
13
13
  import { Layout } from "./layout.js";
14
14
  import { firstRun, oauthRoute } from "./model.js";
15
+ import { Rules } from "./rules.js";
15
16
  import { SignIn } from "./signin.js";
16
17
  import { MAX_TRANSFER, packageArchive, pinnedHashes, readSystem, withTemporaryFile, writeSystem, } from "./transfer.js";
17
18
  /**
@@ -64,6 +65,8 @@ export async function startApp(options) {
64
65
  writePrivate(join(home, "url"), `${listener.url}\n`);
65
66
  const signIn = new SignIn();
66
67
  const changes = new Set();
68
+ /** Who hears that a rule was turned on or off. */
69
+ const ruleChanges = new Set();
67
70
  let emitChanged = () => { };
68
71
  const isView = (actorId, module) => {
69
72
  try {
@@ -128,6 +131,24 @@ export async function startApp(options) {
128
131
  /** The person's side of `/api`: its slots, and `layout`, its own export, served here. */
129
132
  const personSide = {
130
133
  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
+ }
131
152
  if (slot === "layout") {
132
153
  const spec = Object.hasOwn(layout.methods, method)
133
154
  ? layout.methods[method]
@@ -154,6 +175,13 @@ export async function startApp(options) {
154
175
  return call(input);
155
176
  },
156
177
  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
+ }
157
185
  if (slot === "layout") {
158
186
  if (event !== "changed")
159
187
  throw new Refused("invalid", "layout has one event, changed.");
@@ -194,6 +222,18 @@ export async function startApp(options) {
194
222
  process.stderr.write(`First run didn't work: ${error instanceof Error ? error.message : String(error)}\n`);
195
223
  return undefined;
196
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,
228
+ log: (message) => process.stderr.write(`${message}\n`),
229
+ changed: () => {
230
+ for (const tell of [...ruleChanges])
231
+ tell();
232
+ },
233
+ });
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`));
197
237
  /** The app's own pages: scripts and styles from here only, framed by nothing. */
198
238
  const appCsp = [
199
239
  "default-src 'self'",
@@ -461,6 +501,7 @@ export async function startApp(options) {
461
501
  closing ??= (async () => {
462
502
  // A first run still going finishes first, so it isn't cut off half way.
463
503
  await ran;
504
+ rules.close();
464
505
  const ours = (file, text) => {
465
506
  if (file === "cli-token")
466
507
  return text.trim() === signIn.cliToken;
@@ -0,0 +1,71 @@
1
+ import type { PersonSide } from "./api.js";
2
+ /** Where the rules that are on are kept, in the person's store: `{<id>: {on}}`. */
3
+ export declare const RULES_KEY = "app/rules";
4
+ /** An exposure a request asks for: `provider`'s `export`, as a slot on `to`. */
5
+ export interface Exposure {
6
+ provider: string;
7
+ export: string;
8
+ to: string;
9
+ as?: string;
10
+ }
11
+ /** An exposure as a request asks for it: by whom, and which side it lacks. */
12
+ export interface Asked extends Exposure {
13
+ requestedBy?: string;
14
+ /** The side the requester lacks: `export` when it holds the slot side, as `to` does. */
15
+ needs?: string;
16
+ }
17
+ /** An open request, as `hub.grants` tells it. */
18
+ export interface Request {
19
+ requestId: string;
20
+ [field: string]: unknown;
21
+ }
22
+ /**
23
+ * The exposure an open request asks for, if it asks for one. The one place that reads the Hub's
24
+ * request shape for exposures.
25
+ */
26
+ export declare function exposureOf(request: Request): Asked | undefined;
27
+ interface Definition {
28
+ id: string;
29
+ name: string;
30
+ says: string;
31
+ /** Whether this rule approves the exposure, read from the Hub as the person. */
32
+ approves(asked: Asked, person: PersonSide): Promise<boolean>;
33
+ }
34
+ /** The rules the app knows, in the order Settings lists them. */
35
+ export declare const DEFINITIONS: readonly Definition[];
36
+ export interface RulesOptions {
37
+ person: PersonSide;
38
+ /** Where the rules say what they approved, and what they couldn't. */
39
+ log?: (message: string) => void;
40
+ /** Told after a rule is turned on or off. */
41
+ changed?: () => void;
42
+ }
43
+ /**
44
+ * The rules, for `app.rules@1`, and their engine: it hears each request the person could approve,
45
+ * and goes through the open ones at start and whenever a rule is turned on. It approves a request a
46
+ * rule that is on matches, as an approver does, with the call the request asked for; the Hub checks
47
+ * that the person could grant it. It never declines: anything no rule matches stays for the person.
48
+ */
49
+ export declare class Rules {
50
+ #private;
51
+ constructor(options: RulesOptions);
52
+ list(): Promise<{
53
+ rules: {
54
+ id: string;
55
+ name: string;
56
+ says: string;
57
+ on: boolean;
58
+ }[];
59
+ }>;
60
+ set({ id, on }: {
61
+ id: string;
62
+ on: boolean;
63
+ }): Promise<Record<string, never>>;
64
+ /** Hear each new request, and settle the open ones. */
65
+ start(): Promise<void>;
66
+ /** Stop: nothing more is heard, and a sweep under way approves nothing more. */
67
+ close(): void;
68
+ /** Go through every open request the person could approve. */
69
+ sweep(): Promise<void>;
70
+ }
71
+ export {};
@@ -0,0 +1,157 @@
1
+ // The person's named rules: conveniences the person turns on, held by the gateway, which acts on a
2
+ // rule that is on as the person (a manager) and only within what the person could grant. Each rule
3
+ // is named and visible, and off until the person turns it on; nothing else acts on provenance.
4
+ import { Refused } from "@agentorg/sdk";
5
+ /** Where the rules that are on are kept, in the person's store: `{<id>: {on}}`. */
6
+ export const RULES_KEY = "app/rules";
7
+ /**
8
+ * The exposure an open request asks for, if it asks for one. The one place that reads the Hub's
9
+ * request shape for exposures.
10
+ */
11
+ export function exposureOf(request) {
12
+ const { exposed, provider, export: name, consumer, slot, requestedBy, needs, } = request;
13
+ if (exposed !== true)
14
+ return undefined;
15
+ if (typeof provider !== "string" || typeof name !== "string" || typeof consumer !== "string")
16
+ return undefined;
17
+ return {
18
+ provider,
19
+ export: name,
20
+ to: consumer,
21
+ ...(typeof slot === "string" ? { as: slot } : {}),
22
+ ...(typeof requestedBy === "string" ? { requestedBy } : {}),
23
+ ...(typeof needs === "string" ? { needs } : {}),
24
+ };
25
+ }
26
+ /** The rules the app knows, in the order Settings lists them. */
27
+ export const DEFINITIONS = [
28
+ {
29
+ id: "agents-use-what-they-install",
30
+ name: "Let an agent use what it installs",
31
+ says: "When an agent asks to use an Actor it installed, approve it.",
32
+ async approves(asked, person) {
33
+ // The agent asked for itself: it holds its slot side and lacks the export side.
34
+ if (asked.requestedBy !== asked.to || asked.needs !== "export")
35
+ return false;
36
+ // Provenance only: who the installer installed it for. The Hub grants nothing from it.
37
+ const actor = (await person.call("actors", "get", { actorId: asked.provider }));
38
+ return actor.state !== "closed" && actor.installedFor === asked.to;
39
+ },
40
+ },
41
+ ];
42
+ /**
43
+ * The rules, for `app.rules@1`, and their engine: it hears each request the person could approve,
44
+ * and goes through the open ones at start and whenever a rule is turned on. It approves a request a
45
+ * rule that is on matches, as an approver does, with the call the request asked for; the Hub checks
46
+ * that the person could grant it. It never declines: anything no rule matches stays for the person.
47
+ */
48
+ export class Rules {
49
+ #person;
50
+ #log;
51
+ #changed;
52
+ /** Requests being settled, so an event and a sweep don't settle one twice. */
53
+ #settling = new Set();
54
+ #stop;
55
+ #closed = false;
56
+ /** Turning rules on and off, one at a time, so none is lost. */
57
+ #setting = Promise.resolve();
58
+ constructor(options) {
59
+ this.#person = options.person;
60
+ this.#log = options.log ?? (() => { });
61
+ this.#changed = options.changed ?? (() => { });
62
+ }
63
+ /** The ids of the rules that are on. */
64
+ async #on() {
65
+ const { value } = (await this.#person.call("store", "get", { key: RULES_KEY }));
66
+ const held = typeof value === "object" && value !== null ? value : {};
67
+ return new Set(DEFINITIONS.filter((rule) => held[rule.id]?.on === true).map((rule) => rule.id));
68
+ }
69
+ async list() {
70
+ const on = await this.#on();
71
+ return {
72
+ rules: DEFINITIONS.map(({ id, name, says }) => ({ id, name, says, on: on.has(id) })),
73
+ };
74
+ }
75
+ set({ id, on }) {
76
+ if (!DEFINITIONS.some((rule) => rule.id === id))
77
+ return Promise.reject(new Refused("unknown", `There is no rule ${id}.`));
78
+ const done = this.#setting.then(async () => {
79
+ const now = await this.#on();
80
+ if (on)
81
+ now.add(id);
82
+ else
83
+ now.delete(id);
84
+ await this.#person.call("store", "set", {
85
+ key: RULES_KEY,
86
+ value: Object.fromEntries([...now].map((ruleId) => [ruleId, { on: true }])),
87
+ });
88
+ this.#changed();
89
+ // Turned on, it settles what already waits for it; a sweep that fails is logged, as the
90
+ // rule is on either way.
91
+ if (on)
92
+ await this.sweep().catch((error) => this.#log(`The rules couldn't go through what waits: ${messageOf(error)}`));
93
+ return {};
94
+ });
95
+ this.#setting = done.catch(() => { });
96
+ return done;
97
+ }
98
+ /** Hear each new request, and settle the open ones. */
99
+ async start() {
100
+ await this.sweep();
101
+ }
102
+ /** Hear each new request, once; heard again after a subscription that ended. */
103
+ #listen() {
104
+ if (this.#closed)
105
+ return;
106
+ this.#stop ??= this.#person.subscribe("grants", "requested", (request) => void this.#settle(request), () => {
107
+ this.#stop = undefined;
108
+ });
109
+ }
110
+ /** Stop: nothing more is heard, and a sweep under way approves nothing more. */
111
+ close() {
112
+ this.#closed = true;
113
+ this.#stop?.();
114
+ this.#stop = undefined;
115
+ }
116
+ /** Go through every open request the person could approve. */
117
+ async sweep() {
118
+ this.#listen();
119
+ for (const request of await this.#open())
120
+ await this.#settle(request);
121
+ }
122
+ async #open() {
123
+ if (this.#closed)
124
+ return [];
125
+ return (await this.#person.call("grants", "requests", {}))
126
+ .requests;
127
+ }
128
+ async #settle(request) {
129
+ const asked = exposureOf(request);
130
+ if (!asked || this.#closed || this.#settling.has(request.requestId))
131
+ return;
132
+ this.#settling.add(request.requestId);
133
+ try {
134
+ const on = await this.#on();
135
+ for (const rule of DEFINITIONS) {
136
+ if (!on.has(rule.id) || !(await rule.approves(asked, this.#person)))
137
+ continue;
138
+ // Still open just before: one the person declined, or that was settled meanwhile, is left.
139
+ if (!(await this.#open()).some((open) => open.requestId === request.requestId))
140
+ return;
141
+ const { provider, export: name, to, as } = asked;
142
+ const exposure = { provider, export: name, to, ...(as ? { as } : {}) };
143
+ // As an approver approves: the call the request asked for, checked by the Hub.
144
+ await this.#person.call("grants", "expose", exposure);
145
+ this.#log(`Rule "${rule.name}" approved ${exposure.provider}'s ${exposure.export} for ${exposure.to}.`);
146
+ return;
147
+ }
148
+ }
149
+ catch (error) {
150
+ this.#log(`A rule couldn't settle request ${request.requestId}: ${messageOf(error)}`);
151
+ }
152
+ finally {
153
+ this.#settling.delete(request.requestId);
154
+ }
155
+ }
156
+ }
157
+ const messageOf = (error) => (error instanceof Error ? error.message : String(error));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentorg/cli",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "description": "AgentOrg as one app: the Hub, the person's gateway and the shell, on loopback.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -24,27 +24,24 @@
24
24
  "files": [
25
25
  "dist/src",
26
26
  "dist/bundled",
27
- "static"
27
+ "static",
28
+ "dist/node_modules"
28
29
  ],
29
30
  "dependencies": {
30
- "@agentorg/hub": "0.0.0",
31
- "@agentorg/interfaces": "0.0.0",
32
- "@agentorg/sdk": "0.0.0",
33
- "@agentorg/shell": "0.0.0",
31
+ "@assistant-ui/react": "^0.15.32",
34
32
  "ajv": "^8.20.0",
35
33
  "esbuild": "0.28.2",
34
+ "radix-ui": "^1.8.1",
35
+ "react": "^19.3.1",
36
+ "react-dom": "^19.3.1",
37
+ "react-markdown": "^10.1.0",
38
+ "react-resizable-panels": "^4.19.1",
39
+ "remark-gfm": "^4.0.1",
40
+ "remend": "^1.4.0",
36
41
  "ws": "^8.22.1",
37
- "zod": "^4.6.7",
38
- "@agentorg/wire": "0.0.0"
42
+ "zod": "^4.6.7"
39
43
  },
40
44
  "publishConfig": {
41
45
  "access": "public"
42
- },
43
- "bundleDependencies": [
44
- "@agentorg/wire",
45
- "@agentorg/sdk",
46
- "@agentorg/interfaces",
47
- "@agentorg/hub",
48
- "@agentorg/shell"
49
- ]
46
+ }
50
47
  }
@@ -1,51 +0,0 @@
1
- import { Refused } from "./errors.js";
2
- import { createRuntime } from "./runtime.js";
3
- export function createTestContext(definition, options = {}) {
4
- const emitted = [];
5
- const logs = [];
6
- const line = (level) => (message, fields) => void logs.push(fields === undefined ? { level, message } : { level, message, fields });
7
- const log = { info: line("info"), warn: line("warn"), error: line("error") };
8
- const self = options.actorId ?? "test-actor";
9
- const runtime = createRuntime(definition, {
10
- self: { actorId: self, module: options.module ?? "main" },
11
- log,
12
- onEmit: (exportName, event, payload, to) => void emitted.push({
13
- export: exportName,
14
- event,
15
- payload,
16
- ...(to === undefined ? {} : { to }),
17
- }),
18
- });
19
- return {
20
- ...runtime,
21
- call: (exportName, method, input, caller = self) => runtime.call(exportName, method, input, caller),
22
- bind(slot, fake) {
23
- const iface = definition.slots[slot];
24
- let provider;
25
- if (iface.kind === "rpc") {
26
- const handlers = fake;
27
- // The module itself is the caller of its own slot.
28
- const call = { caller: self };
29
- provider = {
30
- async call(method, input) {
31
- const handler = Object.hasOwn(handlers, method) ? handlers[method] : undefined;
32
- if (!handler)
33
- throw new Refused("unimplemented", `${slot}.${method} isn't faked.`);
34
- return handler(input, call);
35
- },
36
- };
37
- }
38
- else if (iface.kind === "stream") {
39
- const open = fake;
40
- provider = { open: async (params) => open(params) };
41
- }
42
- else {
43
- const fetch = fake;
44
- provider = { fetch: async (request) => fetch(request) };
45
- }
46
- return runtime.bind(slot, provider);
47
- },
48
- emitted,
49
- logs,
50
- };
51
- }