@agentorg/cli 0.0.3 → 0.0.5
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.
- package/README.md +15 -11
- package/dist/bundled/index.json +4 -4
- package/dist/bundled/{sha256-87e121cbe58279f3a633e61c9773b61fc17fd53eac3d7c6f037925cbfd5d5384.agentorg → sha256-0e91cc3d0e9762b81abc2427b5496b20f383abcd6fb97d928a8d50e956b54d1f.agentorg} +0 -0
- package/dist/bundled/sha256-1f64ca62a0209d767d6aa6c4feb50b0653d60f10bebbc301f79bd3a37e0153c1.agentorg +0 -0
- package/dist/bundled/{sha256-51ecf151e590f5e57f28229d4cb36e4932a2f1670e50ddf1a3ccf335a1ee146d.agentorg → sha256-4055f8fddf6b90f3d356543f554b2a9e9a2c4a8827a8774f8f87952dc1692331.agentorg} +0 -0
- package/dist/bundled/{sha256-b76ec31282e5b863ee9569dfd9d50b283a21101cbe1b3fac23d1cbcf16b9a408.agentorg → sha256-e356ea3c1899138a8494baf521556831006f38534fa9e92ae873e7e6956c3a46.agentorg} +0 -0
- package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/build.d.ts +2 -2
- package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/build.js +14 -4
- package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/hub-actor.js +41 -0
- package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/index.d.ts +1 -1
- package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/index.js +1 -1
- package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/router.js +40 -16
- package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/state.d.ts +87 -2
- package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/state.js +312 -60
- package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/storage.d.ts +2 -1
- package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/storage.js +3 -2
- package/{node_modules → dist/node_modules}/@agentorg/hub/package.json +3 -0
- package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/hub.d.ts +62 -3
- package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/hub.js +54 -3
- package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/index.d.ts +1 -0
- package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/index.js +1 -0
- package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/installer.d.ts +37 -0
- package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/installer.js +34 -3
- package/dist/node_modules/@agentorg/interfaces/dist/src/rules.d.ts +35 -0
- package/dist/node_modules/@agentorg/interfaces/dist/src/rules.js +37 -0
- package/dist/node_modules/@agentorg/kit/dist/src/chat.d.ts +37 -0
- package/dist/node_modules/@agentorg/kit/dist/src/chat.js +131 -0
- package/dist/node_modules/@agentorg/kit/dist/src/components.d.ts +94 -0
- package/dist/node_modules/@agentorg/kit/dist/src/components.js +66 -0
- package/dist/node_modules/@agentorg/kit/dist/src/icons.d.ts +17 -0
- package/dist/node_modules/@agentorg/kit/dist/src/icons.js +30 -0
- package/dist/node_modules/@agentorg/kit/dist/src/index.d.ts +6 -0
- package/dist/node_modules/@agentorg/kit/dist/src/index.js +10 -0
- package/dist/node_modules/@agentorg/kit/dist/src/markdown.d.ts +9 -0
- package/dist/node_modules/@agentorg/kit/dist/src/markdown.js +14 -0
- package/dist/node_modules/@agentorg/kit/dist/src/resizable.d.ts +5 -0
- package/dist/node_modules/@agentorg/kit/dist/src/resizable.js +8 -0
- package/dist/node_modules/@agentorg/kit/dist/src/styles.d.ts +11 -0
- package/dist/node_modules/@agentorg/kit/dist/src/styles.js +166 -0
- package/dist/node_modules/@agentorg/kit/package.json +44 -0
- package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/frame/runtime.js +172 -17
- package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/host/runner.js +168 -11
- package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/client.d.ts +18 -0
- package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/client.js +24 -3
- package/dist/node_modules/@agentorg/sdk/dist/src/frame-base.d.ts +8 -0
- package/dist/node_modules/@agentorg/sdk/dist/src/frame-base.js +64 -0
- package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame-entry.js +4 -4
- package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame-host.d.ts +1 -10
- package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame-host.js +0 -23
- package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame-protocol.d.ts +0 -8
- package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame.d.ts +0 -2
- package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame.js +0 -8
- package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/host.js +5 -0
- package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/index.d.ts +1 -1
- package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/module-host.d.ts +6 -1
- package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/module-host.js +24 -1
- package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/module.d.ts +30 -1
- package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/package.js +111 -6
- package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/runtime.d.ts +22 -1
- package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/runtime.js +114 -0
- package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/testing.d.ts +14 -2
- package/dist/node_modules/@agentorg/sdk/dist/src/testing.js +89 -0
- package/{node_modules → dist/node_modules}/@agentorg/shell/dist/app.css +27 -144
- package/dist/node_modules/@agentorg/shell/dist/app.js +219 -0
- package/{node_modules → dist/node_modules}/@agentorg/shell/package.json +1 -0
- package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/index.d.ts +1 -1
- package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/ops.d.ts +14 -1
- package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/ops.js +22 -2
- package/dist/src/cli.js +23 -0
- package/dist/src/gateway.js +42 -1
- package/dist/src/model.d.ts +7 -4
- package/dist/src/model.js +83 -14
- package/dist/src/rules.d.ts +71 -0
- package/dist/src/rules.js +157 -0
- package/package.json +13 -16
- package/dist/bundled/sha256-e4c0e857cea3a721998effe2ca859c4011978b9bc36e63c058bfc17c27a1772e.agentorg +0 -0
- package/node_modules/@agentorg/sdk/dist/src/testing.js +0 -51
- package/node_modules/@agentorg/shell/dist/app.js +0 -9
- /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/hub-actor.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/logs.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/logs.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/net.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/net.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/processes.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/processes.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/router.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/server.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/server.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/validate-worker.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/validate-worker.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/validate.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/hub/dist/src/validate.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/account-login.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/account-login.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/chat.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/chat.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/http-egress.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/http-egress.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/kv.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/kv.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/layout.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/layout.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/llm-session.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/llm-session.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/storage-admin.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/storage-admin.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/ui-shell.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/ui-shell.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/ui-view.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/interfaces/dist/src/ui-view.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/interfaces/package.json +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/build.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/build.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/canonical.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/canonical.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/cli.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/cli.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/client-http.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/client-http.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/describe.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/describe.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/errors.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/errors.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame-entry.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/frame-protocol.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/host-main.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/host-main.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/host.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/index.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/interface.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/interface.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/manifest-api.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/manifest-api.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/manifest.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/manifest.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/module.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/package.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/person-commands.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/person-commands.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/tar.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/dist/src/tar.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/sdk/package.json +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/shell/dist/agent-bindings.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/shell/dist/index.html +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/shell/src/agent-bindings.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/bytes.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/bytes.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/frames.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/frames.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/index.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/transports.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/transports.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/yamux.d.ts +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/wire/dist/src/yamux.js +0 -0
- /package/{node_modules → dist/node_modules}/@agentorg/wire/package.json +0 -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
|
-
/**
|
|
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
|
-
|
|
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);
|
package/dist/src/gateway.js
CHANGED
|
@@ -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;
|
package/dist/src/model.d.ts
CHANGED
|
@@ -35,10 +35,13 @@ export interface FirstRun {
|
|
|
35
35
|
* The first run, at every start after the person's store is bound: add the bundled packages,
|
|
36
36
|
* ensure the installer (made by the person, with its bindings, started), bind the person's
|
|
37
37
|
* `installer` to it, ensure the model Actor installed through it (`web` to `egress`, `store` to
|
|
38
|
-
* storage's `kv`, started), and bind the person's `login` to the model's. What
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
38
|
+
* storage's `kv`, started), and bind the person's `login` to the model's. What earlier runs made
|
|
39
|
+
* (recorded in the person's store) is kept and brought to this build: an installer or model Actor
|
|
40
|
+
* on another package is upgraded in place, with its id, its store and its bindings; so is an agent
|
|
41
|
+
* on an assistant build an earlier run bundled (by the hashes recorded, never by a package's
|
|
42
|
+
* name). A binding an upgrade drops, its interface having changed, is made again where its ends
|
|
43
|
+
* match now. A step that fails is logged and the rest still runs where it can; the next start
|
|
44
|
+
* tries again.
|
|
42
45
|
*/
|
|
43
46
|
export declare function firstRun(person: PersonCalls, options?: FirstRunOptions): Promise<FirstRun>;
|
|
44
47
|
/**
|
package/dist/src/model.js
CHANGED
|
@@ -35,10 +35,13 @@ const INSTALLER_BINDINGS = [
|
|
|
35
35
|
* The first run, at every start after the person's store is bound: add the bundled packages,
|
|
36
36
|
* ensure the installer (made by the person, with its bindings, started), bind the person's
|
|
37
37
|
* `installer` to it, ensure the model Actor installed through it (`web` to `egress`, `store` to
|
|
38
|
-
* storage's `kv`, started), and bind the person's `login` to the model's. What
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
38
|
+
* storage's `kv`, started), and bind the person's `login` to the model's. What earlier runs made
|
|
39
|
+
* (recorded in the person's store) is kept and brought to this build: an installer or model Actor
|
|
40
|
+
* on another package is upgraded in place, with its id, its store and its bindings; so is an agent
|
|
41
|
+
* on an assistant build an earlier run bundled (by the hashes recorded, never by a package's
|
|
42
|
+
* name). A binding an upgrade drops, its interface having changed, is made again where its ends
|
|
43
|
+
* match now. A step that fails is logged and the rest still runs where it can; the next start
|
|
44
|
+
* tries again.
|
|
42
45
|
*/
|
|
43
46
|
export async function firstRun(person, options = {}) {
|
|
44
47
|
const log = options.log ?? (() => { });
|
|
@@ -63,17 +66,48 @@ export async function firstRun(person, options = {}) {
|
|
|
63
66
|
// What earlier runs made, by role, kept while it isn't closed. Unread, nothing is made: a run that
|
|
64
67
|
// couldn't see its record would make a second installer.
|
|
65
68
|
const read = (await call("store", "get", { key: RECORD })).value;
|
|
66
|
-
const
|
|
69
|
+
const kept = (read ?? {});
|
|
70
|
+
// Every assistant build a run has bundled, by hash: an agent on one of them is this app's to
|
|
71
|
+
// bring to this build. Never a package by its name, which an agent's own package could take.
|
|
72
|
+
const earlier = [
|
|
73
|
+
...(Array.isArray(kept.assistants) ? kept.assistants : []),
|
|
74
|
+
kept.assistant,
|
|
75
|
+
].filter((hash) => typeof hash === "string");
|
|
76
|
+
const isWiring = (wiring) => typeof wiring === "object" &&
|
|
77
|
+
wiring !== null &&
|
|
78
|
+
["consumer", "slot", "provider", "export"].every((key) => typeof wiring[key] === "string");
|
|
79
|
+
const record = {
|
|
80
|
+
...Object.fromEntries(Object.entries(kept).filter(([role, id]) => (role === "installer" || role === "chatgpt" || role === "assistant") &&
|
|
81
|
+
typeof id === "string")),
|
|
82
|
+
...(earlier.length ? { assistants: [...new Set(earlier)] } : {}),
|
|
83
|
+
...(Array.isArray(kept.rebind) && kept.rebind.some(isWiring)
|
|
84
|
+
? { rebind: kept.rebind.filter(isWiring) }
|
|
85
|
+
: {}),
|
|
86
|
+
};
|
|
87
|
+
const save = () => call("store", "set", { key: RECORD, value: { ...record } });
|
|
67
88
|
const remember = (role, actorId) => {
|
|
68
89
|
record[role] = actorId;
|
|
69
|
-
return
|
|
90
|
+
return save();
|
|
70
91
|
};
|
|
71
|
-
// The assistant New agent installs is this build's, by hash
|
|
72
|
-
// an agent's own package could take.
|
|
92
|
+
// The assistant New agent installs is this build's, by hash.
|
|
73
93
|
if (packages.assistant) {
|
|
74
94
|
record.assistant = packages.assistant;
|
|
75
|
-
|
|
95
|
+
record.assistants = [...new Set([...earlier, packages.assistant])];
|
|
96
|
+
await attempt("recording the assistant", save);
|
|
76
97
|
}
|
|
98
|
+
/** Run this build's package as an Actor an earlier run made, keeping its id and its store. */
|
|
99
|
+
const upgrade = async (actor, hash, what) => {
|
|
100
|
+
const { dropped: lost } = await call("actors", "upgrade", {
|
|
101
|
+
actorId: actor.actorId,
|
|
102
|
+
package: hash,
|
|
103
|
+
});
|
|
104
|
+
if (lost.length) {
|
|
105
|
+
record.rebind = [...(record.rebind ?? []), ...lost];
|
|
106
|
+
await attempt("recording the bindings to make again", save);
|
|
107
|
+
}
|
|
108
|
+
log(`First run: upgraded ${what} (${actor.actorId}) to this build${lost.length ? `; ${lost.length} of its bindings to make again` : ""}.`);
|
|
109
|
+
return { ...actor, package: hash };
|
|
110
|
+
};
|
|
77
111
|
/** The Actor an earlier run made for `role`, unless it is gone or closed. */
|
|
78
112
|
const madeBefore = async (role) => {
|
|
79
113
|
const id = record[role];
|
|
@@ -129,9 +163,12 @@ export async function firstRun(person, options = {}) {
|
|
|
129
163
|
actor = { actorId, name: "Installer", package: hash, state: "created" };
|
|
130
164
|
}
|
|
131
165
|
else {
|
|
166
|
+
const hash = packages[INSTALLER];
|
|
167
|
+
const before = actor;
|
|
168
|
+
if (hash && actor.package !== hash)
|
|
169
|
+
actor =
|
|
170
|
+
(await attempt("upgrading the installer", () => upgrade(before, hash, "the installer"))) ?? actor;
|
|
132
171
|
await rebind(actor, INSTALLER_BINDINGS);
|
|
133
|
-
if (actor.package !== packages[INSTALLER])
|
|
134
|
-
log("First run: kept the installer; the bundled build is added, not used.");
|
|
135
172
|
}
|
|
136
173
|
await personSlot("installer", { actor: actor.actorId, export: "installer.installer" });
|
|
137
174
|
await running(actor);
|
|
@@ -143,11 +180,14 @@ export async function firstRun(person, options = {}) {
|
|
|
143
180
|
{ slot: "model.store", provider: "storage", export: "kv" },
|
|
144
181
|
];
|
|
145
182
|
const chatgpt = await attempt("ChatGPT", async () => {
|
|
146
|
-
|
|
183
|
+
let actor = await madeBefore("chatgpt");
|
|
147
184
|
if (actor) {
|
|
185
|
+
const hash = packages[CHATGPT];
|
|
186
|
+
const before = actor;
|
|
187
|
+
if (hash && actor.package !== hash)
|
|
188
|
+
actor =
|
|
189
|
+
(await attempt("upgrading ChatGPT", () => upgrade(before, hash, "ChatGPT"))) ?? actor;
|
|
148
190
|
await rebind(actor, chatgptBindings);
|
|
149
|
-
if (actor.package !== packages[CHATGPT])
|
|
150
|
-
log("First run: kept ChatGPT; the bundled build is added, not used.");
|
|
151
191
|
await running(actor);
|
|
152
192
|
return actor.actorId;
|
|
153
193
|
}
|
|
@@ -176,6 +216,35 @@ export async function firstRun(person, options = {}) {
|
|
|
176
216
|
});
|
|
177
217
|
if (chatgpt)
|
|
178
218
|
await attempt("binding the login", () => personSlot("login", { actor: chatgpt, export: "model.login" }));
|
|
219
|
+
// Agents on an assistant build an earlier run bundled: brought to this build's assistant.
|
|
220
|
+
const assistant = packages.assistant;
|
|
221
|
+
if (assistant) {
|
|
222
|
+
const agents = await attempt("finding agents on earlier builds", async () => (await call("actors", "list")).actors.filter((a) => a.state !== "closed" && a.package !== assistant && earlier.includes(a.package)));
|
|
223
|
+
for (const agent of agents ?? [])
|
|
224
|
+
await attempt(`upgrading ${agent.name}`, () => upgrade(agent, assistant, `the agent ${agent.name}`));
|
|
225
|
+
}
|
|
226
|
+
// What upgrades dropped, this run or one that stopped before this, made again where its slot is
|
|
227
|
+
// still unbound: the ends now match, both on this build. One that can't be yet (an upgrade
|
|
228
|
+
// failed, or its ends still differ) is logged and kept for the next start.
|
|
229
|
+
if (record.rebind) {
|
|
230
|
+
const left = [];
|
|
231
|
+
for (const wiring of record.rebind) {
|
|
232
|
+
const made = await attempt(`binding ${wiring.slot} again`, async () => {
|
|
233
|
+
if ((await bindingsOf(wiring.consumer)).some((b) => b.slot === wiring.slot))
|
|
234
|
+
return true;
|
|
235
|
+
await call("grants", "bind", wiring);
|
|
236
|
+
log(`First run: bound ${wiring.consumer}'s ${wiring.slot} again.`);
|
|
237
|
+
return true;
|
|
238
|
+
});
|
|
239
|
+
if (!made)
|
|
240
|
+
left.push(wiring);
|
|
241
|
+
}
|
|
242
|
+
if (left.length)
|
|
243
|
+
record.rebind = left;
|
|
244
|
+
else
|
|
245
|
+
delete record.rebind;
|
|
246
|
+
await attempt("recording the bindings made again", save);
|
|
247
|
+
}
|
|
179
248
|
return {
|
|
180
249
|
packages,
|
|
181
250
|
...(installer ? { installer } : {}),
|
|
@@ -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
|
+
"version": "0.0.5",
|
|
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
|
-
"@
|
|
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
|
}
|