@agentorg/cli 0.0.5 → 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 -144
- 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 +17 -317
- package/dist/node_modules/@agentorg/hub/dist/src/state.js +42 -536
- 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 -286
- package/dist/node_modules/@agentorg/interfaces/dist/src/hub.js +17 -159
- 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-0e91cc3d0e9762b81abc2427b5496b20f383abcd6fb97d928a8d50e956b54d1f.agentorg +0 -0
- package/dist/bundled/sha256-1f64ca62a0209d767d6aa6c4feb50b0653d60f10bebbc301f79bd3a37e0153c1.agentorg +0 -0
- package/dist/bundled/sha256-4055f8fddf6b90f3d356543f554b2a9e9a2c4a8827a8774f8f87952dc1692331.agentorg +0 -0
- package/dist/bundled/sha256-e356ea3c1899138a8494baf521556831006f38534fa9e92ae873e7e6956c3a46.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 -54
- package/dist/src/model.js +0 -299
- 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
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The assistant's record of its chat, kept in its `store` slot: one key per message, holding the
|
|
3
|
+
* Responses items it stands for, and for a tool message the line the person sees. It is read once,
|
|
4
|
+
* then kept in memory, and the oldest messages are deleted past a retention cap.
|
|
5
|
+
*/
|
|
6
|
+
import { type ChatMessage, Item, type kv } from "@agentorg/interfaces";
|
|
7
|
+
import type { Log, Slot } from "@agentorg/sdk";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
export type ResponseItem = z.output<typeof Item>;
|
|
10
|
+
declare const Entry: z.ZodObject<{
|
|
11
|
+
id: z.ZodString;
|
|
12
|
+
role: z.ZodEnum<{
|
|
13
|
+
assistant: "assistant";
|
|
14
|
+
tool: "tool";
|
|
15
|
+
user: "user";
|
|
16
|
+
}>;
|
|
17
|
+
text: z.ZodOptional<z.ZodString>;
|
|
18
|
+
at: z.ZodString;
|
|
19
|
+
items: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
20
|
+
type: z.ZodLiteral<"message">;
|
|
21
|
+
role: z.ZodEnum<{
|
|
22
|
+
assistant: "assistant";
|
|
23
|
+
user: "user";
|
|
24
|
+
}>;
|
|
25
|
+
content: z.ZodString;
|
|
26
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
27
|
+
type: z.ZodLiteral<"function_call">;
|
|
28
|
+
callId: z.ZodString;
|
|
29
|
+
name: z.ZodString;
|
|
30
|
+
arguments: z.ZodString;
|
|
31
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
32
|
+
type: z.ZodLiteral<"function_call_output">;
|
|
33
|
+
callId: z.ZodString;
|
|
34
|
+
output: z.ZodString;
|
|
35
|
+
}, z.core.$strip>], "type">>;
|
|
36
|
+
state: z.ZodOptional<z.ZodEnum<{
|
|
37
|
+
done: "done";
|
|
38
|
+
refused: "refused";
|
|
39
|
+
}>>;
|
|
40
|
+
}, z.core.$strip>;
|
|
41
|
+
export type Entry = z.output<typeof Entry>;
|
|
42
|
+
/** What the model is sent of the past: the newest exchanges up to this many bytes of JSON. */
|
|
43
|
+
export declare const INPUT_BUDGET = 400000;
|
|
44
|
+
/** At most this many messages are kept, in at most this many bytes, oldest deleted first. */
|
|
45
|
+
export declare const KEEP = 2000;
|
|
46
|
+
export declare const KEEP_BYTES: number;
|
|
47
|
+
/** The first `length` UTF-16 units of `text`, never ending inside a surrogate pair. */
|
|
48
|
+
export declare function head(text: string, length: number): string;
|
|
49
|
+
/** `text`, cut so its JSON fits `max` bytes, saying so when it is cut. */
|
|
50
|
+
export declare function fitted(text: string, max: number): string;
|
|
51
|
+
/** What the person sees of a message. */
|
|
52
|
+
export declare const textOf: (entry: Entry) => string;
|
|
53
|
+
/** A call's arguments as they are kept and shown: past their cap, a note in their place. */
|
|
54
|
+
export declare const argumentsOf: (args: string) => string;
|
|
55
|
+
/**
|
|
56
|
+
* A message as the chat shows it. A tool message whose call ran carries `tool`: the call's name,
|
|
57
|
+
* how it ended, its arguments and its output.
|
|
58
|
+
*/
|
|
59
|
+
export declare function messageOf(entry: Entry): z.input<typeof ChatMessage>;
|
|
60
|
+
export declare function createHistory(store: Slot<typeof kv>["call"], log: Log, limits?: {
|
|
61
|
+
keep: number;
|
|
62
|
+
keepBytes: number;
|
|
63
|
+
}): {
|
|
64
|
+
/**
|
|
65
|
+
* Keep a message, under `id` or its own number, and delete the oldest past the cap. A tool
|
|
66
|
+
* message the store refuses is still kept in memory, since its call has run.
|
|
67
|
+
*/
|
|
68
|
+
append(entry: Omit<Entry, "id" | "at">, id?: string): Promise<Entry>;
|
|
69
|
+
/** Forget everything after the message `id`: a retry takes the place of what followed it. */
|
|
70
|
+
dropAfter(id: string): Promise<void>;
|
|
71
|
+
/** The person's last message, if any. */
|
|
72
|
+
lastUser(): Promise<Entry | undefined>;
|
|
73
|
+
/** Messages before `before`, oldest first, as many as fit `limit` and one frame. */
|
|
74
|
+
page(before: string | undefined, limit: number): Promise<{
|
|
75
|
+
messages: {
|
|
76
|
+
id: string;
|
|
77
|
+
role: "assistant" | "tool" | "user";
|
|
78
|
+
text: string;
|
|
79
|
+
at: string;
|
|
80
|
+
tool?: {
|
|
81
|
+
name: string;
|
|
82
|
+
state: "done" | "refused" | "running";
|
|
83
|
+
input?: string | undefined;
|
|
84
|
+
output?: string | undefined;
|
|
85
|
+
} | undefined;
|
|
86
|
+
}[];
|
|
87
|
+
more: boolean;
|
|
88
|
+
}>;
|
|
89
|
+
/**
|
|
90
|
+
* The conversation to send: the newest whole exchanges (each from a user message on) that fit
|
|
91
|
+
* the budget, and always the latest one. A latest one that alone is over the budget has its
|
|
92
|
+
* oldest function arguments and outputs left out, each call still paired with an output.
|
|
93
|
+
*/
|
|
94
|
+
input(): Promise<ResponseItem[]>;
|
|
95
|
+
};
|
|
96
|
+
export type History = ReturnType<typeof createHistory>;
|
|
97
|
+
export {};
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The assistant's record of its chat, kept in its `store` slot: one key per message, holding the
|
|
3
|
+
* Responses items it stands for, and for a tool message the line the person sees. It is read once,
|
|
4
|
+
* then kept in memory, and the oldest messages are deleted past a retention cap.
|
|
5
|
+
*/
|
|
6
|
+
import { Item } from "@agentorg/interfaces";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
const Entry = z.object({
|
|
9
|
+
id: z.string(),
|
|
10
|
+
role: z.enum(["user", "assistant", "tool"]),
|
|
11
|
+
/** What the person sees, for a tool message; the others show their message items. */
|
|
12
|
+
text: z.string().optional(),
|
|
13
|
+
at: z.string(),
|
|
14
|
+
items: z.array(Item),
|
|
15
|
+
/** For a tool message whose call ran: how it ended. */
|
|
16
|
+
state: z.enum(["done", "refused"]).optional(),
|
|
17
|
+
});
|
|
18
|
+
const PREFIX = "msg/";
|
|
19
|
+
const keyOf = (seq) => `${PREFIX}${String(seq).padStart(12, "0")}`;
|
|
20
|
+
/** What the model is sent of the past: the newest exchanges up to this many bytes of JSON. */
|
|
21
|
+
export const INPUT_BUDGET = 400_000;
|
|
22
|
+
/** At most this many messages are kept, in at most this many bytes, oldest deleted first. */
|
|
23
|
+
export const KEEP = 2000;
|
|
24
|
+
export const KEEP_BYTES = 16 * 1024 * 1024;
|
|
25
|
+
/** A stored message's text, and a call's arguments, are cut to fit these, in bytes of JSON. */
|
|
26
|
+
const MAX_TEXT = 192 * 1024;
|
|
27
|
+
const MAX_ARGUMENTS = 16 * 1024;
|
|
28
|
+
/** A history page stays well inside one frame. */
|
|
29
|
+
const PAGE_BUDGET = 512 * 1024;
|
|
30
|
+
const encoder = new TextEncoder();
|
|
31
|
+
const size = (value) => encoder.encode(JSON.stringify(value)).byteLength;
|
|
32
|
+
const LEFT_OUT = "(Left out: the conversation was too large to send it.)";
|
|
33
|
+
const ARGUMENTS_LEFT_OUT = '{"left_out":"too large to keep"}';
|
|
34
|
+
/** The first `length` UTF-16 units of `text`, never ending inside a surrogate pair. */
|
|
35
|
+
export function head(text, length) {
|
|
36
|
+
const cut = text.slice(0, length);
|
|
37
|
+
return /[\uD800-\uDBFF]$/.test(cut) ? cut.slice(0, -1) : cut;
|
|
38
|
+
}
|
|
39
|
+
/** `text`, cut so its JSON fits `max` bytes, saying so when it is cut. */
|
|
40
|
+
export function fitted(text, max) {
|
|
41
|
+
let kept = text;
|
|
42
|
+
for (let bytes = size(kept); bytes > max; bytes = size(kept))
|
|
43
|
+
kept = `${head(kept, Math.floor((kept.length * max) / bytes) - 16)}… (cut)`;
|
|
44
|
+
return kept;
|
|
45
|
+
}
|
|
46
|
+
/** A chat message shows at most this much; the record keeps all of it. */
|
|
47
|
+
const MAX_SHOWN = 100_000;
|
|
48
|
+
/** What the person sees of a message. */
|
|
49
|
+
export const textOf = (entry) => head(entry.text ??
|
|
50
|
+
entry.items.flatMap((item) => (item.type === "message" ? [item.content] : [])).join(""), MAX_SHOWN);
|
|
51
|
+
/** A call's arguments as they are kept and shown: past their cap, a note in their place. */
|
|
52
|
+
export const argumentsOf = (args) => size(args) > MAX_ARGUMENTS ? ARGUMENTS_LEFT_OUT : args;
|
|
53
|
+
/**
|
|
54
|
+
* A message as the chat shows it. A tool message whose call ran carries `tool`: the call's name,
|
|
55
|
+
* how it ended, its arguments and its output.
|
|
56
|
+
*/
|
|
57
|
+
export function messageOf(entry) {
|
|
58
|
+
const message = { id: entry.id, role: entry.role, text: textOf(entry), at: entry.at };
|
|
59
|
+
const call = entry.items.find((item) => item.type === "function_call");
|
|
60
|
+
if (entry.role !== "tool" || !entry.state || !call)
|
|
61
|
+
return message;
|
|
62
|
+
const output = entry.items.find((item) => item.type === "function_call_output");
|
|
63
|
+
return {
|
|
64
|
+
...message,
|
|
65
|
+
tool: {
|
|
66
|
+
name: head(call.name, 128),
|
|
67
|
+
state: entry.state,
|
|
68
|
+
input: head(call.arguments, MAX_SHOWN),
|
|
69
|
+
...(output ? { output: head(output.output, MAX_SHOWN) } : {}),
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/** A message as it is stored: each text once, and nothing past its cap. */
|
|
74
|
+
const kept = (entry) => ({
|
|
75
|
+
...entry,
|
|
76
|
+
items: entry.items.map((item) => {
|
|
77
|
+
if (item.type === "message")
|
|
78
|
+
return { ...item, content: fitted(item.content, MAX_TEXT) };
|
|
79
|
+
if (item.type === "function_call_output")
|
|
80
|
+
return { ...item, output: fitted(item.output, MAX_TEXT) };
|
|
81
|
+
return { ...item, arguments: argumentsOf(item.arguments) };
|
|
82
|
+
}),
|
|
83
|
+
});
|
|
84
|
+
/** Stored messages read at once when the record is first loaded. */
|
|
85
|
+
const READS = 16;
|
|
86
|
+
export function createHistory(store, log, limits = { keep: KEEP, keepBytes: KEEP_BYTES }) {
|
|
87
|
+
let loaded;
|
|
88
|
+
const load = () => {
|
|
89
|
+
if (loaded)
|
|
90
|
+
return loaded;
|
|
91
|
+
const attempt = (async () => {
|
|
92
|
+
const records = [];
|
|
93
|
+
let last = 0;
|
|
94
|
+
let bytes = 0;
|
|
95
|
+
let after;
|
|
96
|
+
do {
|
|
97
|
+
const page = await store.list({ prefix: PREFIX, limit: 1000, ...(after ? { after } : {}) });
|
|
98
|
+
// A few at a time, in order: a long record shouldn't hold up the first send one read at
|
|
99
|
+
// a time, nor flood the Hub.
|
|
100
|
+
for (let at = 0; at < page.keys.length; at += READS) {
|
|
101
|
+
const keys = page.keys.slice(at, at + READS);
|
|
102
|
+
const values = await Promise.all(keys.map((key) => store.get({ key })));
|
|
103
|
+
keys.forEach((key, i) => {
|
|
104
|
+
last = Math.max(last, Number(key.slice(PREFIX.length)) || 0);
|
|
105
|
+
const parsed = Entry.safeParse(values[i]?.value);
|
|
106
|
+
if (!parsed.success) {
|
|
107
|
+
log.warn("A stored message didn't read back; it is left out.", { key });
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const record = { key, entry: parsed.data, bytes: size(parsed.data) };
|
|
111
|
+
records.push(record);
|
|
112
|
+
bytes += record.bytes;
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
after = page.next ?? undefined;
|
|
116
|
+
} while (after);
|
|
117
|
+
return { records, last, bytes };
|
|
118
|
+
})();
|
|
119
|
+
loaded = attempt;
|
|
120
|
+
attempt.catch(() => {
|
|
121
|
+
if (loaded === attempt)
|
|
122
|
+
loaded = undefined;
|
|
123
|
+
});
|
|
124
|
+
return attempt;
|
|
125
|
+
};
|
|
126
|
+
return {
|
|
127
|
+
/**
|
|
128
|
+
* Keep a message, under `id` or its own number, and delete the oldest past the cap. A tool
|
|
129
|
+
* message the store refuses is still kept in memory, since its call has run.
|
|
130
|
+
*/
|
|
131
|
+
async append(entry, id) {
|
|
132
|
+
const state = await load();
|
|
133
|
+
const key = keyOf(++state.last);
|
|
134
|
+
const record = {
|
|
135
|
+
key,
|
|
136
|
+
entry: kept({ id: id ?? key.slice(PREFIX.length), at: new Date().toISOString(), ...entry }),
|
|
137
|
+
bytes: 0,
|
|
138
|
+
};
|
|
139
|
+
record.bytes = size(record.entry);
|
|
140
|
+
state.records.push(record);
|
|
141
|
+
state.bytes += record.bytes;
|
|
142
|
+
try {
|
|
143
|
+
await store.set({ key, value: record.entry });
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
if (entry.role !== "tool") {
|
|
147
|
+
state.records.splice(state.records.indexOf(record), 1);
|
|
148
|
+
state.bytes -= record.bytes;
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
log.error("A tool message couldn't be stored; it is kept until a restart.", {
|
|
152
|
+
error: String(error),
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
while (state.records.length > 1 &&
|
|
156
|
+
(state.records.length > limits.keep || state.bytes > limits.keepBytes)) {
|
|
157
|
+
const oldest = state.records.shift();
|
|
158
|
+
state.bytes -= oldest.bytes;
|
|
159
|
+
await store.delete({ key: oldest.key }).catch((error) => log.warn("An old message couldn't be deleted.", {
|
|
160
|
+
key: oldest.key,
|
|
161
|
+
error: String(error),
|
|
162
|
+
}));
|
|
163
|
+
}
|
|
164
|
+
return record.entry;
|
|
165
|
+
},
|
|
166
|
+
/** Forget everything after the message `id`: a retry takes the place of what followed it. */
|
|
167
|
+
async dropAfter(id) {
|
|
168
|
+
const state = await load();
|
|
169
|
+
const at = state.records.findLastIndex((record) => record.entry.id === id);
|
|
170
|
+
if (at === -1)
|
|
171
|
+
return;
|
|
172
|
+
for (const gone of state.records.splice(at + 1)) {
|
|
173
|
+
state.bytes -= gone.bytes;
|
|
174
|
+
await store.delete({ key: gone.key }).catch((error) => log.warn("A replaced message couldn't be deleted.", {
|
|
175
|
+
key: gone.key,
|
|
176
|
+
error: String(error),
|
|
177
|
+
}));
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
/** The person's last message, if any. */
|
|
181
|
+
async lastUser() {
|
|
182
|
+
return (await load()).records.findLast((record) => record.entry.role === "user")?.entry;
|
|
183
|
+
},
|
|
184
|
+
/** Messages before `before`, oldest first, as many as fit `limit` and one frame. */
|
|
185
|
+
async page(before, limit) {
|
|
186
|
+
const { records } = await load();
|
|
187
|
+
const end = before === undefined
|
|
188
|
+
? records.length
|
|
189
|
+
: records.findIndex((record) => record.entry.id === before);
|
|
190
|
+
const messages = [];
|
|
191
|
+
let bytes = 0;
|
|
192
|
+
let start = Math.max(end, 0);
|
|
193
|
+
while (start > 0 && messages.length < limit) {
|
|
194
|
+
const { entry } = records[start - 1];
|
|
195
|
+
const message = messageOf(entry);
|
|
196
|
+
bytes += size(message);
|
|
197
|
+
if (bytes > PAGE_BUDGET && messages.length > 0)
|
|
198
|
+
break;
|
|
199
|
+
messages.unshift(message);
|
|
200
|
+
start--;
|
|
201
|
+
}
|
|
202
|
+
return { messages, more: start > 0 };
|
|
203
|
+
},
|
|
204
|
+
/**
|
|
205
|
+
* The conversation to send: the newest whole exchanges (each from a user message on) that fit
|
|
206
|
+
* the budget, and always the latest one. A latest one that alone is over the budget has its
|
|
207
|
+
* oldest function arguments and outputs left out, each call still paired with an output.
|
|
208
|
+
*/
|
|
209
|
+
async input() {
|
|
210
|
+
const { records } = await load();
|
|
211
|
+
const exchanges = [];
|
|
212
|
+
for (const { entry } of records) {
|
|
213
|
+
if (entry.role === "user" || exchanges.length === 0)
|
|
214
|
+
exchanges.push([]);
|
|
215
|
+
exchanges.at(-1)?.push(...entry.items);
|
|
216
|
+
}
|
|
217
|
+
let total = exchanges.reduce((sum, items) => sum + size(items), 0);
|
|
218
|
+
while (exchanges.length > 1 && total > INPUT_BUDGET)
|
|
219
|
+
total -= size(exchanges.shift());
|
|
220
|
+
const items = exchanges.flat();
|
|
221
|
+
for (let i = 0; i < items.length && total > INPUT_BUDGET; i++) {
|
|
222
|
+
const item = items[i];
|
|
223
|
+
if (item.type === "function_call_output" && item.output !== LEFT_OUT) {
|
|
224
|
+
total -= size(item.output) - size(LEFT_OUT);
|
|
225
|
+
items[i] = { ...item, output: LEFT_OUT };
|
|
226
|
+
}
|
|
227
|
+
else if (item.type === "function_call" && item.arguments !== ARGUMENTS_LEFT_OUT) {
|
|
228
|
+
total -= size(item.arguments) - size(ARGUMENTS_LEFT_OUT);
|
|
229
|
+
items[i] = { ...item, arguments: ARGUMENTS_LEFT_OUT };
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return items;
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The engine's record when it runs as an ordinary program: one small JSON file per key, in the
|
|
3
|
+
* agent's own folder. A new message writes one file, however long the record is, and each write
|
|
4
|
+
* lands whole. It answers as `kv@1` does, so the history reads it as it reads any store.
|
|
5
|
+
*/
|
|
6
|
+
import { randomUUID } from "node:crypto";
|
|
7
|
+
import { mkdir, readdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
const missing = (error) => error.code === "ENOENT";
|
|
10
|
+
export function createLocalStore(dir) {
|
|
11
|
+
const keys = join(dir, "kv");
|
|
12
|
+
const scratch = join(dir, "tmp");
|
|
13
|
+
const pathOf = (key) => join(keys, encodeURIComponent(key));
|
|
14
|
+
return {
|
|
15
|
+
async get({ key }) {
|
|
16
|
+
try {
|
|
17
|
+
return { value: JSON.parse(await readFile(pathOf(key), "utf8")) };
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
if (missing(error))
|
|
21
|
+
return {};
|
|
22
|
+
throw error;
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
async set({ key, value }) {
|
|
26
|
+
await mkdir(keys, { recursive: true, mode: 0o700 });
|
|
27
|
+
await mkdir(scratch, { recursive: true, mode: 0o700 });
|
|
28
|
+
const temporary = join(scratch, randomUUID());
|
|
29
|
+
await writeFile(temporary, JSON.stringify(value), { mode: 0o600, flush: true });
|
|
30
|
+
await rename(temporary, pathOf(key));
|
|
31
|
+
return {};
|
|
32
|
+
},
|
|
33
|
+
async delete({ key }) {
|
|
34
|
+
try {
|
|
35
|
+
await rm(pathOf(key));
|
|
36
|
+
return { deleted: true };
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
if (missing(error))
|
|
40
|
+
return { deleted: false };
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
async list({ prefix = "", after, limit = 1000 }) {
|
|
45
|
+
const names = await readdir(keys).catch((error) => {
|
|
46
|
+
if (missing(error))
|
|
47
|
+
return [];
|
|
48
|
+
throw error;
|
|
49
|
+
});
|
|
50
|
+
const found = names
|
|
51
|
+
.map(decodeURIComponent)
|
|
52
|
+
.filter((key) => key.startsWith(prefix) && (after === undefined || key > after))
|
|
53
|
+
.sort();
|
|
54
|
+
const page = found.slice(0, limit);
|
|
55
|
+
return { keys: page, next: found.length > limit ? (page.at(-1) ?? null) : null };
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type Log } from "@agentorg/sdk";
|
|
2
|
+
export interface AgentProviderOptions {
|
|
3
|
+
hubUrl: string;
|
|
4
|
+
/** The provider's own Actor, bound to `hub.actors@1` at `actors` and to the model at `model`. */
|
|
5
|
+
actorId: string;
|
|
6
|
+
credential: string;
|
|
7
|
+
/** The export its `model` slot is bound to, which each agent it makes is bound to in turn. */
|
|
8
|
+
model: {
|
|
9
|
+
actor: string;
|
|
10
|
+
export: string;
|
|
11
|
+
};
|
|
12
|
+
/** A private folder of the provider's, which holds each agent's credential and record. */
|
|
13
|
+
dir: string;
|
|
14
|
+
log?: Log;
|
|
15
|
+
}
|
|
16
|
+
export interface AgentProvider {
|
|
17
|
+
/** Leave the Hub and stop every agent. They stay, and those not stopped resume at the next start. */
|
|
18
|
+
close(): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
/** Run the bundled agent provider as an Actor exporting `agent.provider@1` as `provider`. */
|
|
21
|
+
export declare function startAgentProvider(options: AgentProviderOptions): Promise<AgentProvider>;
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The bundled agent provider: it offers one creatable, Assistant, and runs each agent in this
|
|
3
|
+
* process as its own Actor on its own channel. Stopping an agent closes its channel; starting it
|
|
4
|
+
* opens one. Each agent's record and model choice are kept in the provider's private folder.
|
|
5
|
+
*/
|
|
6
|
+
import { chmodSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
7
|
+
import { rm } from "node:fs/promises";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { agentProvider, agentSettings, chat, hubActors, llmSession } from "@agentorg/interfaces";
|
|
10
|
+
import { Refused } from "@agentorg/sdk";
|
|
11
|
+
import { connect } from "@agentorg/sdk/client";
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
import { startEngine } from "./engine.js";
|
|
14
|
+
import { createLocalStore } from "./local-store.js";
|
|
15
|
+
const ASSISTANT_INSTRUCTIONS = `You are an assistant in AgentOrg, working for the person who created you.
|
|
16
|
+
You act only through your tools, and your tools are exactly the connections the person gave you. If something needs a connection you don't have, say which.
|
|
17
|
+
Before you promise to do something, check that one of your tools does it. A connection you are given later shows up as new tools at your next turn; until then, don't say you can use it.
|
|
18
|
+
Keep replies short and plain.`;
|
|
19
|
+
const ASSISTANT = {
|
|
20
|
+
id: "assistant",
|
|
21
|
+
title: "Assistant",
|
|
22
|
+
description: "An agent that chats, and acts through the connections you give it.",
|
|
23
|
+
instructions: ASSISTANT_INSTRUCTIONS,
|
|
24
|
+
asks: [],
|
|
25
|
+
skills: [],
|
|
26
|
+
mcp: [],
|
|
27
|
+
};
|
|
28
|
+
/** What is kept of an agent between runs, in the provider's private file. */
|
|
29
|
+
const Stored = z.object({ credential: z.string(), stopped: z.boolean() });
|
|
30
|
+
const FILE = "agents.json";
|
|
31
|
+
const quiet = { info() { }, warn() { }, error() { } };
|
|
32
|
+
/** Run the bundled agent provider as an Actor exporting `agent.provider@1` as `provider`. */
|
|
33
|
+
export async function startAgentProvider(options) {
|
|
34
|
+
const log = options.log ?? quiet;
|
|
35
|
+
const { hubUrl, dir } = options;
|
|
36
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
37
|
+
chmodSync(dir, 0o700);
|
|
38
|
+
const path = join(dir, FILE);
|
|
39
|
+
const folderOf = (agent) => join(dir, "agents", agent);
|
|
40
|
+
/** The file; one that can't be read is set aside, so the agents in it can be recovered by hand. */
|
|
41
|
+
const read = () => {
|
|
42
|
+
let raw;
|
|
43
|
+
try {
|
|
44
|
+
raw = readFileSync(path, "utf8");
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
if (error.code === "ENOENT")
|
|
48
|
+
return {};
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
return z.record(z.string(), Stored).parse(JSON.parse(raw));
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
renameSync(path, `${path}.unreadable-${Date.now()}`);
|
|
56
|
+
log.error("The agents file can't be read: it is set aside and starts empty.");
|
|
57
|
+
return {};
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const stored = read();
|
|
61
|
+
const save = () => {
|
|
62
|
+
writeFileSync(`${path}.tmp`, JSON.stringify(stored), { mode: 0o600, flush: true });
|
|
63
|
+
renameSync(`${path}.tmp`, path);
|
|
64
|
+
};
|
|
65
|
+
const agents = new Map();
|
|
66
|
+
let closing = false;
|
|
67
|
+
const held = (agent) => {
|
|
68
|
+
const found = agents.get(agent);
|
|
69
|
+
if (!found)
|
|
70
|
+
throw new Refused("unknown", `This provider made no agent ${agent}.`);
|
|
71
|
+
return found;
|
|
72
|
+
};
|
|
73
|
+
const inTurn = (agent, work) => {
|
|
74
|
+
const one = held(agent);
|
|
75
|
+
const done = one.queue.then(() => work(one));
|
|
76
|
+
one.queue = done.catch(() => { });
|
|
77
|
+
return done;
|
|
78
|
+
};
|
|
79
|
+
/** Join the Hub as the agent, with its engine running. */
|
|
80
|
+
const open = async (agent, one) => {
|
|
81
|
+
one.state = "starting";
|
|
82
|
+
delete one.detail;
|
|
83
|
+
let engine;
|
|
84
|
+
try {
|
|
85
|
+
const channel = await connect({
|
|
86
|
+
hubUrl,
|
|
87
|
+
actorId: agent,
|
|
88
|
+
credential: stored[agent].credential,
|
|
89
|
+
slots: { model: llmSession, settings: agentSettings },
|
|
90
|
+
exports: { chat },
|
|
91
|
+
log,
|
|
92
|
+
start(ctx) {
|
|
93
|
+
engine = startEngine(ctx, {
|
|
94
|
+
store: createLocalStore(folderOf(agent)),
|
|
95
|
+
instructions: () => ASSISTANT_INSTRUCTIONS,
|
|
96
|
+
});
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
one.channel = channel;
|
|
100
|
+
one.engine = engine;
|
|
101
|
+
one.state = "running";
|
|
102
|
+
void channel.closed.then(() => {
|
|
103
|
+
if (one.channel !== channel)
|
|
104
|
+
return;
|
|
105
|
+
delete one.channel;
|
|
106
|
+
one.state = "down";
|
|
107
|
+
one.detail = "Its connection to the Hub ended.";
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
one.state = "down";
|
|
112
|
+
one.detail = error instanceof Error ? error.message : String(error);
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
/** Cut its turn, close its channel, and wait until its engine has written all it will. */
|
|
117
|
+
const halt = async (one) => {
|
|
118
|
+
const { channel, engine } = one;
|
|
119
|
+
delete one.channel;
|
|
120
|
+
if (!channel || !engine)
|
|
121
|
+
return;
|
|
122
|
+
await engine.cancel();
|
|
123
|
+
channel.close();
|
|
124
|
+
await channel.closed;
|
|
125
|
+
await engine.settled();
|
|
126
|
+
};
|
|
127
|
+
await Promise.all(Object.entries(stored).map(async ([agent, { stopped }]) => {
|
|
128
|
+
const one = { state: "stopped", queue: Promise.resolve() };
|
|
129
|
+
agents.set(agent, one);
|
|
130
|
+
if (stopped)
|
|
131
|
+
return;
|
|
132
|
+
try {
|
|
133
|
+
await open(agent, one);
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
log.error(`Agent ${agent} didn't rejoin the Hub: ${String(error)}`);
|
|
137
|
+
// The Hub no longer knows it: its Actor was closed while the provider was away.
|
|
138
|
+
if (error instanceof Refused && error.code === "forbidden") {
|
|
139
|
+
agents.delete(agent);
|
|
140
|
+
delete stored[agent];
|
|
141
|
+
save();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}));
|
|
145
|
+
const haltAll = () => Promise.all([...agents.keys()].map((agent) => inTurn(agent, halt).catch(() => { })));
|
|
146
|
+
const provider = await connect({
|
|
147
|
+
hubUrl,
|
|
148
|
+
actorId: options.actorId,
|
|
149
|
+
credential: options.credential,
|
|
150
|
+
slots: { actors: hubActors, model: llmSession },
|
|
151
|
+
exports: { provider: agentProvider },
|
|
152
|
+
log,
|
|
153
|
+
start(ctx) {
|
|
154
|
+
ctx.exports.provider.implement({
|
|
155
|
+
creatable: async () => ({ creatables: [ASSISTANT] }),
|
|
156
|
+
skill: async ({ creatable, name, path: file }) => {
|
|
157
|
+
throw new Refused("unknown", `${creatable} has no file ${file} of a skill ${name}.`);
|
|
158
|
+
},
|
|
159
|
+
async create({ creatable, name }) {
|
|
160
|
+
if (creatable !== ASSISTANT.id)
|
|
161
|
+
throw new Refused("unknown", `This provider offers no ${creatable}.`);
|
|
162
|
+
// The provider is bound to the model's export, so it can give the agent that binding.
|
|
163
|
+
const { actorId: agent, credential } = await ctx.slots.actors.call.create({
|
|
164
|
+
name,
|
|
165
|
+
bindings: [
|
|
166
|
+
{ slot: "model", provider: options.model.actor, export: options.model.export },
|
|
167
|
+
],
|
|
168
|
+
});
|
|
169
|
+
const one = { state: "starting", queue: Promise.resolve() };
|
|
170
|
+
try {
|
|
171
|
+
stored[agent] = { credential: credential, stopped: false };
|
|
172
|
+
await open(agent, one);
|
|
173
|
+
if (closing)
|
|
174
|
+
throw new Refused("unavailable", "This provider is stopping.");
|
|
175
|
+
agents.set(agent, one);
|
|
176
|
+
save();
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
delete stored[agent];
|
|
180
|
+
await halt(one);
|
|
181
|
+
await ctx.slots.actors.call.close({ actorId: agent }).catch(() => { });
|
|
182
|
+
await rm(folderOf(agent), { recursive: true, force: true });
|
|
183
|
+
throw error;
|
|
184
|
+
}
|
|
185
|
+
return { agent, settings: "settings", chat: "chat" };
|
|
186
|
+
},
|
|
187
|
+
status: async ({ agent }) => {
|
|
188
|
+
const { state, detail } = held(agent);
|
|
189
|
+
return { state, ...(detail ? { detail } : {}) };
|
|
190
|
+
},
|
|
191
|
+
start: ({ agent }) => inTurn(agent, async (one) => {
|
|
192
|
+
if (one.state === "running")
|
|
193
|
+
return {};
|
|
194
|
+
stored[agent].stopped = false;
|
|
195
|
+
save();
|
|
196
|
+
await open(agent, one);
|
|
197
|
+
return {};
|
|
198
|
+
}),
|
|
199
|
+
stop: ({ agent }) => inTurn(agent, async (one) => {
|
|
200
|
+
stored[agent].stopped = true;
|
|
201
|
+
save();
|
|
202
|
+
await halt(one);
|
|
203
|
+
one.state = "stopped";
|
|
204
|
+
delete one.detail;
|
|
205
|
+
return {};
|
|
206
|
+
}),
|
|
207
|
+
remove: ({ agent }) => inTurn(agent, async (one) => {
|
|
208
|
+
await halt(one);
|
|
209
|
+
one.state = "down";
|
|
210
|
+
one.detail = "It is being removed.";
|
|
211
|
+
await ctx.slots.actors.call.close({ actorId: agent });
|
|
212
|
+
agents.delete(agent);
|
|
213
|
+
delete stored[agent];
|
|
214
|
+
save();
|
|
215
|
+
await rm(folderOf(agent), { recursive: true, force: true });
|
|
216
|
+
return {};
|
|
217
|
+
}),
|
|
218
|
+
});
|
|
219
|
+
},
|
|
220
|
+
}).catch(async (error) => {
|
|
221
|
+
await haltAll();
|
|
222
|
+
throw error;
|
|
223
|
+
});
|
|
224
|
+
return {
|
|
225
|
+
async close() {
|
|
226
|
+
closing = true;
|
|
227
|
+
await haltAll();
|
|
228
|
+
provider.close();
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the `settings` slot adds to a request: the skills exposed to this agent, named in its
|
|
3
|
+
* instructions, and one tool to read them. A skill's text is read only when the model asks for it.
|
|
4
|
+
*/
|
|
5
|
+
import type { agentSettings, SkillEntry } from "@agentorg/interfaces";
|
|
6
|
+
import type { Slot } from "@agentorg/sdk";
|
|
7
|
+
import type { z } from "zod";
|
|
8
|
+
import type { Candidate, LeftOut } from "./tools.js";
|
|
9
|
+
/** The longest instructions a request can carry. */
|
|
10
|
+
export declare const MAX_INSTRUCTIONS = 200000;
|
|
11
|
+
/** The agent's instructions and the skills that fit in them; any that don't are reported. */
|
|
12
|
+
export declare function instructionsWith(instructions: string, skills: z.output<typeof SkillEntry>[]): {
|
|
13
|
+
instructions: string;
|
|
14
|
+
leftOut: LeftOut[];
|
|
15
|
+
};
|
|
16
|
+
/** The one way the model reads a skill: its `SKILL.md`, or a file of its folder by `path`. */
|
|
17
|
+
export declare function skillTool(slot: Slot<typeof agentSettings>): Candidate;
|