@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.
- package/README.md +18 -102
- package/dist/node_modules/@agentorg/hub/dist/src/hub-actor.d.ts +2 -7
- package/dist/node_modules/@agentorg/hub/dist/src/hub-actor.js +4 -111
- package/dist/node_modules/@agentorg/hub/dist/src/index.d.ts +1 -3
- package/dist/node_modules/@agentorg/hub/dist/src/index.js +1 -3
- package/dist/node_modules/@agentorg/hub/dist/src/router.d.ts +6 -57
- package/dist/node_modules/@agentorg/hub/dist/src/router.js +38 -413
- package/dist/node_modules/@agentorg/hub/dist/src/state.d.ts +20 -298
- package/dist/node_modules/@agentorg/hub/dist/src/state.js +73 -456
- package/dist/node_modules/@agentorg/hub/dist/src/validate.d.ts +1 -3
- package/dist/node_modules/@agentorg/hub/dist/src/validate.js +3 -15
- package/dist/node_modules/@agentorg/hub/package.json +0 -3
- package/dist/node_modules/@agentorg/interfaces/dist/src/agent-provider.d.ts +132 -0
- package/dist/node_modules/@agentorg/interfaces/dist/src/agent-provider.js +105 -0
- package/dist/node_modules/@agentorg/interfaces/dist/src/agent-settings.d.ts +42 -0
- package/dist/node_modules/@agentorg/interfaces/dist/src/agent-settings.js +53 -0
- package/dist/node_modules/@agentorg/interfaces/dist/src/chat.d.ts +15 -0
- package/dist/node_modules/@agentorg/interfaces/dist/src/chat.js +14 -0
- package/dist/node_modules/@agentorg/interfaces/dist/src/hub.d.ts +16 -267
- package/dist/node_modules/@agentorg/interfaces/dist/src/hub.js +17 -145
- package/dist/node_modules/@agentorg/interfaces/dist/src/index.d.ts +6 -8
- package/dist/node_modules/@agentorg/interfaces/dist/src/index.js +6 -8
- package/dist/node_modules/@agentorg/interfaces/dist/src/kv.d.ts +2 -2
- package/dist/node_modules/@agentorg/interfaces/dist/src/kv.js +2 -2
- package/dist/node_modules/@agentorg/interfaces/dist/src/manager.d.ts +272 -0
- package/dist/node_modules/@agentorg/interfaces/dist/src/manager.js +185 -0
- package/dist/node_modules/@agentorg/interfaces/dist/src/mcp-provider.d.ts +88 -0
- package/dist/node_modules/@agentorg/interfaces/dist/src/mcp-provider.js +78 -0
- package/dist/node_modules/@agentorg/interfaces/dist/src/tools.d.ts +39 -0
- package/dist/node_modules/@agentorg/interfaces/dist/src/tools.js +43 -0
- package/dist/node_modules/@agentorg/manager/dist/src/index.d.ts +1 -0
- package/dist/node_modules/@agentorg/manager/dist/src/index.js +1 -0
- package/dist/node_modules/@agentorg/manager/dist/src/manager.d.ts +21 -0
- package/dist/node_modules/@agentorg/manager/dist/src/manager.js +528 -0
- package/dist/node_modules/@agentorg/manager/dist/src/skills.d.ts +25 -0
- package/dist/node_modules/@agentorg/manager/dist/src/skills.js +145 -0
- package/dist/node_modules/@agentorg/manager/package.json +30 -0
- package/dist/node_modules/@agentorg/mcp/dist/src/connection.d.ts +33 -0
- package/dist/node_modules/@agentorg/mcp/dist/src/connection.js +290 -0
- package/dist/node_modules/@agentorg/mcp/dist/src/index.d.ts +1 -0
- package/dist/node_modules/@agentorg/mcp/dist/src/index.js +1 -0
- package/dist/node_modules/@agentorg/mcp/dist/src/kinds.d.ts +50 -0
- package/dist/node_modules/@agentorg/mcp/dist/src/kinds.js +69 -0
- package/dist/node_modules/@agentorg/mcp/dist/src/provider.d.ts +22 -0
- package/dist/node_modules/@agentorg/mcp/dist/src/provider.js +167 -0
- package/dist/node_modules/@agentorg/mcp/package.json +31 -0
- package/dist/node_modules/@agentorg/sdk/dist/src/cli.js +3 -23
- package/dist/node_modules/@agentorg/sdk/dist/src/client.d.ts +4 -25
- package/dist/node_modules/@agentorg/sdk/dist/src/client.js +5 -55
- package/dist/node_modules/@agentorg/sdk/dist/src/errors.d.ts +1 -1
- package/dist/node_modules/@agentorg/sdk/dist/src/errors.js +3 -3
- package/dist/node_modules/@agentorg/sdk/dist/src/index.d.ts +2 -2
- package/dist/node_modules/@agentorg/sdk/dist/src/index.js +1 -1
- package/dist/node_modules/@agentorg/sdk/dist/src/interface.d.ts +6 -34
- package/dist/node_modules/@agentorg/sdk/dist/src/interface.js +3 -24
- package/dist/node_modules/@agentorg/sdk/dist/src/module-host.d.ts +8 -17
- package/dist/node_modules/@agentorg/sdk/dist/src/module-host.js +15 -87
- package/dist/node_modules/@agentorg/sdk/dist/src/module.d.ts +10 -76
- package/dist/node_modules/@agentorg/sdk/dist/src/module.js +3 -23
- package/dist/node_modules/@agentorg/sdk/dist/src/person-commands.js +0 -5
- package/dist/node_modules/@agentorg/sdk/dist/src/runtime.d.ts +3 -27
- package/dist/node_modules/@agentorg/sdk/dist/src/runtime.js +5 -100
- package/dist/node_modules/@agentorg/sdk/dist/src/testing.d.ts +7 -8
- package/dist/node_modules/@agentorg/sdk/dist/src/testing.js +12 -24
- package/dist/node_modules/@agentorg/sdk/package.json +4 -37
- package/dist/node_modules/@agentorg/shell/dist/app.css +3435 -739
- package/dist/node_modules/@agentorg/shell/dist/app.js +204 -202
- package/dist/node_modules/@agentorg/shell/package.json +18 -10
- package/dist/node_modules/@agentorg/wire/dist/src/frames.d.ts +2 -3
- package/dist/node_modules/@agentorg/wire/dist/src/frames.js +2 -3
- package/dist/node_modules/@agentorg/wire/dist/src/ops.d.ts +5 -34
- package/dist/node_modules/@agentorg/wire/dist/src/ops.js +2 -17
- package/dist/node_modules/assistant/dist/src/agent.d.ts +62 -0
- package/dist/node_modules/assistant/dist/src/agent.js +226 -0
- package/dist/node_modules/assistant/dist/src/engine.d.ts +23 -0
- package/dist/node_modules/assistant/dist/src/engine.js +88 -0
- package/dist/node_modules/assistant/dist/src/history.d.ts +97 -0
- package/dist/node_modules/assistant/dist/src/history.js +235 -0
- package/dist/node_modules/assistant/dist/src/local-store.d.ts +3 -0
- package/dist/node_modules/assistant/dist/src/local-store.js +58 -0
- package/dist/node_modules/assistant/dist/src/provider.d.ts +21 -0
- package/dist/node_modules/assistant/dist/src/provider.js +231 -0
- package/dist/node_modules/assistant/dist/src/settings.d.ts +17 -0
- package/dist/node_modules/assistant/dist/src/settings.js +43 -0
- package/dist/node_modules/assistant/dist/src/tools.d.ts +74 -0
- package/dist/node_modules/assistant/dist/src/tools.js +123 -0
- package/dist/node_modules/assistant/package.json +29 -0
- package/dist/node_modules/chatgpt/dist/src/account.d.ts +52 -0
- package/dist/node_modules/chatgpt/dist/src/account.js +270 -0
- package/dist/node_modules/chatgpt/dist/src/encoding.d.ts +7 -0
- package/dist/node_modules/chatgpt/dist/src/encoding.js +20 -0
- package/dist/node_modules/chatgpt/dist/src/file-store.d.ts +9 -0
- package/dist/node_modules/chatgpt/dist/src/file-store.js +68 -0
- package/dist/node_modules/chatgpt/dist/src/index.d.ts +1 -0
- package/dist/node_modules/chatgpt/dist/src/index.js +1 -0
- package/dist/node_modules/chatgpt/dist/src/jwt.d.ts +15 -0
- package/dist/node_modules/chatgpt/dist/src/jwt.js +37 -0
- package/dist/node_modules/chatgpt/dist/src/oauth.d.ts +43 -0
- package/dist/node_modules/chatgpt/dist/src/oauth.js +104 -0
- package/dist/node_modules/chatgpt/dist/src/program.d.ts +23 -0
- package/dist/node_modules/chatgpt/dist/src/program.js +41 -0
- package/dist/node_modules/chatgpt/dist/src/responses.d.ts +54 -0
- package/dist/node_modules/chatgpt/dist/src/responses.js +300 -0
- package/dist/node_modules/chatgpt/dist/src/serve.d.ts +65 -0
- package/dist/node_modules/chatgpt/dist/src/serve.js +46 -0
- package/dist/node_modules/chatgpt/package.json +33 -0
- package/dist/src/api.d.ts +5 -34
- package/dist/src/api.js +6 -68
- package/dist/src/cli.js +3 -7
- package/dist/src/gateway.d.ts +6 -7
- package/dist/src/gateway.js +39 -285
- package/dist/src/index.d.ts +4 -5
- package/dist/src/index.js +3 -4
- package/dist/src/notes.d.ts +11 -0
- package/dist/src/notes.js +64 -0
- package/dist/src/oauth.d.ts +16 -0
- package/dist/src/oauth.js +46 -0
- package/dist/src/programs.d.ts +29 -0
- package/dist/src/programs.js +171 -0
- package/package.json +3 -11
- package/dist/bundled/index.json +0 -6
- package/dist/bundled/sha256-01d69bc3888c2a53963f4413d47de909d129ad27c78e9af6d830bb50c3478419.agentorg +0 -0
- package/dist/bundled/sha256-84165e3be5c904fc971d983dab31102e07cca725d8629a6fd7d118fa3a0a88b8.agentorg +0 -0
- package/dist/bundled/sha256-ade9132b3f34b4c39db92adeadc7e540dc745e4a81b5b54f5d45bf9ec92bca75.agentorg +0 -0
- package/dist/bundled/sha256-f4330f5987f37d8cf3aeb44d2f831b573641a87186daa2f811f0c35ba04804f0.agentorg +0 -0
- package/dist/node_modules/@agentorg/hub/dist/src/build.d.ts +0 -17
- package/dist/node_modules/@agentorg/hub/dist/src/build.js +0 -120
- package/dist/node_modules/@agentorg/hub/dist/src/logs.d.ts +0 -33
- package/dist/node_modules/@agentorg/hub/dist/src/logs.js +0 -162
- package/dist/node_modules/@agentorg/hub/dist/src/net.d.ts +0 -41
- package/dist/node_modules/@agentorg/hub/dist/src/net.js +0 -265
- package/dist/node_modules/@agentorg/hub/dist/src/processes.d.ts +0 -78
- package/dist/node_modules/@agentorg/hub/dist/src/processes.js +0 -485
- package/dist/node_modules/@agentorg/hub/dist/src/storage.d.ts +0 -38
- package/dist/node_modules/@agentorg/hub/dist/src/storage.js +0 -194
- package/dist/node_modules/@agentorg/interfaces/dist/src/http-egress.d.ts +0 -6
- package/dist/node_modules/@agentorg/interfaces/dist/src/http-egress.js +0 -7
- package/dist/node_modules/@agentorg/interfaces/dist/src/installer.d.ts +0 -191
- package/dist/node_modules/@agentorg/interfaces/dist/src/installer.js +0 -136
- package/dist/node_modules/@agentorg/interfaces/dist/src/layout.d.ts +0 -47
- package/dist/node_modules/@agentorg/interfaces/dist/src/layout.js +0 -52
- package/dist/node_modules/@agentorg/interfaces/dist/src/rules.d.ts +0 -35
- package/dist/node_modules/@agentorg/interfaces/dist/src/rules.js +0 -37
- package/dist/node_modules/@agentorg/interfaces/dist/src/storage-admin.d.ts +0 -23
- package/dist/node_modules/@agentorg/interfaces/dist/src/storage-admin.js +0 -31
- package/dist/node_modules/@agentorg/interfaces/dist/src/ui-shell.d.ts +0 -14
- package/dist/node_modules/@agentorg/interfaces/dist/src/ui-shell.js +0 -26
- package/dist/node_modules/@agentorg/interfaces/dist/src/ui-view.d.ts +0 -27
- package/dist/node_modules/@agentorg/interfaces/dist/src/ui-view.js +0 -26
- package/dist/node_modules/@agentorg/kit/dist/src/chat.d.ts +0 -37
- package/dist/node_modules/@agentorg/kit/dist/src/chat.js +0 -131
- package/dist/node_modules/@agentorg/kit/dist/src/components.d.ts +0 -94
- package/dist/node_modules/@agentorg/kit/dist/src/components.js +0 -66
- package/dist/node_modules/@agentorg/kit/dist/src/icons.d.ts +0 -17
- package/dist/node_modules/@agentorg/kit/dist/src/icons.js +0 -30
- package/dist/node_modules/@agentorg/kit/dist/src/index.d.ts +0 -6
- package/dist/node_modules/@agentorg/kit/dist/src/index.js +0 -10
- package/dist/node_modules/@agentorg/kit/dist/src/markdown.d.ts +0 -9
- package/dist/node_modules/@agentorg/kit/dist/src/markdown.js +0 -14
- package/dist/node_modules/@agentorg/kit/dist/src/resizable.d.ts +0 -5
- package/dist/node_modules/@agentorg/kit/dist/src/resizable.js +0 -8
- package/dist/node_modules/@agentorg/kit/dist/src/styles.d.ts +0 -11
- package/dist/node_modules/@agentorg/kit/dist/src/styles.js +0 -166
- package/dist/node_modules/@agentorg/kit/package.json +0 -44
- package/dist/node_modules/@agentorg/sdk/dist/frame/runtime.js +0 -753
- package/dist/node_modules/@agentorg/sdk/dist/host/runner.js +0 -21963
- package/dist/node_modules/@agentorg/sdk/dist/src/build.d.ts +0 -2
- package/dist/node_modules/@agentorg/sdk/dist/src/build.js +0 -2
- package/dist/node_modules/@agentorg/sdk/dist/src/client-http.d.ts +0 -24
- package/dist/node_modules/@agentorg/sdk/dist/src/client-http.js +0 -247
- package/dist/node_modules/@agentorg/sdk/dist/src/describe.d.ts +0 -13
- package/dist/node_modules/@agentorg/sdk/dist/src/describe.js +0 -16
- package/dist/node_modules/@agentorg/sdk/dist/src/frame-base.d.ts +0 -8
- package/dist/node_modules/@agentorg/sdk/dist/src/frame-base.js +0 -64
- package/dist/node_modules/@agentorg/sdk/dist/src/frame-entry.d.ts +0 -1
- package/dist/node_modules/@agentorg/sdk/dist/src/frame-entry.js +0 -35
- package/dist/node_modules/@agentorg/sdk/dist/src/frame-host.d.ts +0 -57
- package/dist/node_modules/@agentorg/sdk/dist/src/frame-host.js +0 -293
- package/dist/node_modules/@agentorg/sdk/dist/src/frame-protocol.d.ts +0 -124
- package/dist/node_modules/@agentorg/sdk/dist/src/frame-protocol.js +0 -16
- package/dist/node_modules/@agentorg/sdk/dist/src/frame.d.ts +0 -25
- package/dist/node_modules/@agentorg/sdk/dist/src/frame.js +0 -248
- package/dist/node_modules/@agentorg/sdk/dist/src/host-main.d.ts +0 -1
- package/dist/node_modules/@agentorg/sdk/dist/src/host-main.js +0 -60
- package/dist/node_modules/@agentorg/sdk/dist/src/host.d.ts +0 -25
- package/dist/node_modules/@agentorg/sdk/dist/src/host.js +0 -92
- package/dist/node_modules/@agentorg/sdk/dist/src/manifest-api.d.ts +0 -2
- package/dist/node_modules/@agentorg/sdk/dist/src/manifest-api.js +0 -2
- package/dist/node_modules/@agentorg/sdk/dist/src/manifest.d.ts +0 -56
- package/dist/node_modules/@agentorg/sdk/dist/src/manifest.js +0 -165
- package/dist/node_modules/@agentorg/sdk/dist/src/package.d.ts +0 -60
- package/dist/node_modules/@agentorg/sdk/dist/src/package.js +0 -538
- package/dist/node_modules/@agentorg/sdk/dist/src/tar.d.ts +0 -7
- package/dist/node_modules/@agentorg/sdk/dist/src/tar.js +0 -71
- package/dist/node_modules/@agentorg/shell/dist/agent-bindings.js +0 -59
- package/dist/node_modules/@agentorg/shell/src/agent-bindings.ts +0 -107
- package/dist/src/frames.d.ts +0 -23
- package/dist/src/frames.js +0 -78
- package/dist/src/layout.d.ts +0 -44
- package/dist/src/layout.js +0 -90
- package/dist/src/model.d.ts +0 -51
- package/dist/src/model.js +0 -230
- package/dist/src/rules.d.ts +0 -71
- package/dist/src/rules.js +0 -157
- package/dist/src/transfer.d.ts +0 -30
- package/dist/src/transfer.js +0 -110
package/dist/src/gateway.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type IncomingMessage, type ServerResponse } from "node:http";
|
|
2
2
|
import { Hub } from "@agentorg/hub";
|
|
3
|
-
import { type
|
|
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
|
-
*
|
|
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?:
|
|
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:
|
|
26
|
-
readonly firstRun
|
|
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
|
-
*
|
|
43
|
+
* and the person's notes are the app's own file.
|
|
45
44
|
*/
|
|
46
45
|
export declare function startApp(options: AppOptions): Promise<App>;
|
package/dist/src/gateway.js
CHANGED
|
@@ -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
|
|
7
|
-
import { accountLogin,
|
|
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 {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
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,
|
|
20
|
-
*
|
|
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
|
-
|
|
32
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
120
|
-
|
|
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 === "
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
-
|
|
179
|
-
|
|
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 =
|
|
216
|
-
|
|
217
|
-
:
|
|
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
|
-
|
|
230
|
-
|
|
231
|
-
|
|
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 '
|
|
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
|
|
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
|
|
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
|
-
|
|
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 = "";
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
export { type PersonSide, type Socket, serveSocket
|
|
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 {
|
|
5
|
-
export {
|
|
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 {
|
|
5
|
-
export {
|
|
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;
|