@agentorg/cli 0.0.5 → 0.0.7
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 +23 -104
- package/dist/node_modules/@agentorg/computer/LICENSE +201 -0
- package/dist/node_modules/@agentorg/computer/NOTICE +2 -0
- package/dist/node_modules/@agentorg/computer/dist/THIRD_PARTY_LICENSES.txt +1321 -0
- package/dist/node_modules/@agentorg/computer/dist/sdk.js +24909 -0
- package/dist/node_modules/@agentorg/computer/dist/types/generated/schema.d.ts +860 -0
- package/dist/node_modules/@agentorg/computer/dist/types/sdk.d.ts +242 -0
- package/dist/node_modules/@agentorg/computer/package.json +12 -0
- package/dist/node_modules/@agentorg/computer-connector/dist/src/index.d.ts +1 -0
- package/dist/node_modules/@agentorg/computer-connector/dist/src/index.js +1 -0
- package/dist/node_modules/@agentorg/computer-connector/dist/src/provider.d.ts +24 -0
- package/dist/node_modules/@agentorg/computer-connector/dist/src/provider.js +482 -0
- package/dist/node_modules/@agentorg/computer-connector/dist/src/unit.d.ts +19 -0
- package/dist/node_modules/@agentorg/computer-connector/dist/src/unit.js +149 -0
- package/dist/node_modules/@agentorg/computer-connector/package.json +33 -0
- package/dist/node_modules/@agentorg/computer-connector/skills/browser/SKILL.md +31 -0
- package/dist/node_modules/@agentorg/computer-connector/skills/computer/SKILL.md +30 -0
- package/dist/node_modules/@agentorg/computer-connector/skills/files/SKILL.md +28 -0
- package/dist/node_modules/@agentorg/computer-connector/skills/terminal/SKILL.md +39 -0
- package/dist/node_modules/@agentorg/computer-connector/skills/web-research/SKILL.md +29 -0
- 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 +9 -58
- package/dist/node_modules/@agentorg/hub/dist/src/router.js +41 -414
- 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 +19 -17
- package/dist/node_modules/@agentorg/hub/package.json +0 -3
- package/dist/node_modules/@agentorg/interfaces/dist/src/agent-provider.d.ts +119 -0
- package/dist/node_modules/@agentorg/interfaces/dist/src/agent-provider.js +96 -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 +93 -38
- package/dist/node_modules/@agentorg/interfaces/dist/src/chat.js +71 -22
- package/dist/node_modules/@agentorg/interfaces/dist/src/connection.d.ts +36 -0
- package/dist/node_modules/@agentorg/interfaces/dist/src/connection.js +31 -0
- package/dist/node_modules/@agentorg/interfaces/dist/src/folders.d.ts +19 -0
- package/dist/node_modules/@agentorg/interfaces/dist/src/folders.js +25 -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 +9 -9
- package/dist/node_modules/@agentorg/interfaces/dist/src/index.js +9 -9
- 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/llm-session.d.ts +2 -0
- package/dist/node_modules/@agentorg/interfaces/dist/src/llm-session.js +2 -1
- package/dist/node_modules/@agentorg/interfaces/dist/src/manager.d.ts +626 -0
- package/dist/node_modules/@agentorg/interfaces/dist/src/manager.js +349 -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/interfaces/dist/src/units.d.ts +460 -0
- package/dist/node_modules/@agentorg/interfaces/dist/src/units.js +204 -0
- package/dist/node_modules/@agentorg/looper/dist/src/index.d.ts +5 -0
- package/dist/node_modules/@agentorg/looper/dist/src/index.js +5 -0
- package/dist/node_modules/@agentorg/looper/dist/src/loop.d.ts +75 -0
- package/dist/node_modules/@agentorg/looper/dist/src/loop.js +332 -0
- package/dist/node_modules/@agentorg/looper/dist/src/looper.d.ts +71 -0
- package/dist/node_modules/@agentorg/looper/dist/src/looper.js +282 -0
- package/dist/node_modules/@agentorg/looper/dist/src/record.d.ts +99 -0
- package/dist/node_modules/@agentorg/looper/dist/src/record.js +278 -0
- package/dist/node_modules/@agentorg/looper/dist/src/tools.d.ts +11 -0
- package/dist/node_modules/@agentorg/looper/dist/src/tools.js +42 -0
- package/dist/node_modules/@agentorg/looper/dist/src/types.d.ts +147 -0
- package/dist/node_modules/@agentorg/looper/dist/src/types.js +32 -0
- package/dist/node_modules/@agentorg/looper/package.json +24 -0
- package/dist/node_modules/@agentorg/manager/dist/src/activity.d.ts +18 -0
- package/dist/node_modules/@agentorg/manager/dist/src/activity.js +65 -0
- package/dist/node_modules/@agentorg/manager/dist/src/control.d.ts +134 -0
- package/dist/node_modules/@agentorg/manager/dist/src/control.js +1115 -0
- package/dist/node_modules/@agentorg/manager/dist/src/form.d.ts +40 -0
- package/dist/node_modules/@agentorg/manager/dist/src/form.js +191 -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 +25 -0
- package/dist/node_modules/@agentorg/manager/dist/src/manager.js +680 -0
- package/dist/node_modules/@agentorg/manager/dist/src/skills.d.ts +27 -0
- package/dist/node_modules/@agentorg/manager/dist/src/skills.js +152 -0
- package/dist/node_modules/@agentorg/manager/dist/src/stack.d.ts +454 -0
- package/dist/node_modules/@agentorg/manager/dist/src/stack.js +917 -0
- package/dist/node_modules/@agentorg/manager/package.json +30 -0
- package/dist/node_modules/@agentorg/mcp/dist/src/connection.d.ts +34 -0
- package/dist/node_modules/@agentorg/mcp/dist/src/connection.js +296 -0
- package/dist/node_modules/@agentorg/mcp/dist/src/index.d.ts +4 -0
- package/dist/node_modules/@agentorg/mcp/dist/src/index.js +4 -0
- package/dist/node_modules/@agentorg/mcp/dist/src/kinds.d.ts +158 -0
- package/dist/node_modules/@agentorg/mcp/dist/src/kinds.js +164 -0
- package/dist/node_modules/@agentorg/mcp/dist/src/provider.d.ts +22 -0
- package/dist/node_modules/@agentorg/mcp/dist/src/provider.js +197 -0
- package/dist/node_modules/@agentorg/mcp/dist/src/public.d.ts +6 -0
- package/dist/node_modules/@agentorg/mcp/dist/src/public.js +72 -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/filled.d.ts +21 -0
- package/dist/node_modules/@agentorg/sdk/dist/src/filled.js +24 -0
- package/dist/node_modules/@agentorg/sdk/dist/src/index.d.ts +3 -2
- package/dist/node_modules/@agentorg/sdk/dist/src/index.js +2 -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 +4624 -739
- package/dist/node_modules/@agentorg/shell/dist/app.js +245 -202
- package/dist/node_modules/@agentorg/shell/package.json +23 -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/chats.d.ts +92 -0
- package/dist/node_modules/assistant/dist/src/chats.js +357 -0
- package/dist/node_modules/assistant/dist/src/engine.d.ts +42 -0
- package/dist/node_modules/assistant/dist/src/engine.js +160 -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 +259 -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 +57 -0
- package/dist/node_modules/assistant/dist/src/tools.js +102 -0
- package/dist/node_modules/assistant/package.json +30 -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 +10 -68
- package/dist/src/cli.js +3 -7
- package/dist/src/folders.d.ts +2 -0
- package/dist/src/folders.js +45 -0
- package/dist/src/gateway.d.ts +13 -8
- package/dist/src/gateway.js +119 -296
- package/dist/src/index.d.ts +4 -5
- package/dist/src/index.js +3 -4
- package/dist/src/live.d.ts +17 -0
- package/dist/src/live.js +109 -0
- 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 +36 -0
- package/dist/src/programs.js +198 -0
- package/dist/src/signin.d.ts +12 -3
- package/dist/src/signin.js +30 -6
- package/package.json +4 -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,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agentorg/manager",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"description": "Management: creating agents and connecting skills and MCP servers to them",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/src/index.d.ts",
|
|
11
|
+
"default": "./dist/src/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist/src"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\" && tsc -p tsconfig.json",
|
|
19
|
+
"test": "node --test \"dist/test/**/*.test.js\""
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@agentorg/interfaces": "0.0.0",
|
|
23
|
+
"@agentorg/sdk": "0.0.0",
|
|
24
|
+
"yaml": "2.9.1",
|
|
25
|
+
"zod": "^4.6.7"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@agentorg/hub": "0.0.0"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type Log } from "@agentorg/sdk";
|
|
2
|
+
import type { Secrets, Spec } from "./kinds.js";
|
|
3
|
+
/**
|
|
4
|
+
* One connection to one MCP server, and its Actor. The Actor stays on the Hub while the server
|
|
5
|
+
* comes and goes: the connection is kept up, tried again after a backoff when it ends, and says
|
|
6
|
+
* `changed` whenever the tools it can offer change, that being up or down too.
|
|
7
|
+
*/
|
|
8
|
+
export interface Timing {
|
|
9
|
+
pingEveryMs?: number;
|
|
10
|
+
firstDelayMs?: number;
|
|
11
|
+
}
|
|
12
|
+
export declare class Connection {
|
|
13
|
+
#private;
|
|
14
|
+
/** `hide` names tools of the server that are never offered or run through this connection. */
|
|
15
|
+
constructor(spec: Spec, secrets: Secrets, log: Log, timing?: Timing, hide?: readonly string[]);
|
|
16
|
+
/** Join the Hub as the connection's Actor, offering its tools. */
|
|
17
|
+
join(hub: {
|
|
18
|
+
hubUrl: string;
|
|
19
|
+
actorId: string;
|
|
20
|
+
credential: string;
|
|
21
|
+
}): Promise<void>;
|
|
22
|
+
/** Keep the server connected, from now until the connection ends. */
|
|
23
|
+
run(): void;
|
|
24
|
+
status(): {
|
|
25
|
+
state: "connected" | "connecting" | "down";
|
|
26
|
+
detail?: string | undefined;
|
|
27
|
+
tools: {
|
|
28
|
+
name: string;
|
|
29
|
+
description?: string | undefined;
|
|
30
|
+
}[];
|
|
31
|
+
};
|
|
32
|
+
/** End it: the server is let go and the Actor leaves the Hub. */
|
|
33
|
+
end(): Promise<void>;
|
|
34
|
+
}
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import { tools } from "@agentorg/interfaces";
|
|
2
|
+
import { Refused } from "@agentorg/sdk";
|
|
3
|
+
import { connect } from "@agentorg/sdk/client";
|
|
4
|
+
import { Client, ProtocolError, SdkError, SdkErrorCode, StreamableHTTPClientTransport, } from "@modelcontextprotocol/client";
|
|
5
|
+
import { getDefaultEnvironment, StdioClientTransport } from "@modelcontextprotocol/client/stdio";
|
|
6
|
+
import { publicFetch } from "./public.js";
|
|
7
|
+
/** How often a connection asks its server whether it is there, and how long it waits. */
|
|
8
|
+
const PING_EVERY_MS = 30_000;
|
|
9
|
+
const PING_TIMEOUT_MS = 10_000;
|
|
10
|
+
const FIRST_DELAY_MS = 1_000;
|
|
11
|
+
const MAX_DELAY_MS = 60_000;
|
|
12
|
+
/** A server up this long is well again: the next failure starts over from the first delay. */
|
|
13
|
+
const STEADY_MS = 10 * 60_000;
|
|
14
|
+
/** What `tools@1` carries: its limits, and room in one frame for a list. */
|
|
15
|
+
const NAME_MAX = 128;
|
|
16
|
+
const DESCRIPTION_MAX = 16_384;
|
|
17
|
+
const STATUS_DESCRIPTION_MAX = 512;
|
|
18
|
+
const OUTPUT_MAX = 200_000;
|
|
19
|
+
const LIST_ROOM = 900 * 1024;
|
|
20
|
+
const cut = (text, max) => text.length <= max ? text : `${text.slice(0, max - 40)}… [cut: ${text.length} characters]`;
|
|
21
|
+
const messageOf = (error) => (error instanceof Error ? error.message : String(error));
|
|
22
|
+
/** The tools a server lists, fitted to what `tools@1` can carry; what can't be is logged. */
|
|
23
|
+
function fit(listed, log) {
|
|
24
|
+
const kept = [];
|
|
25
|
+
let room = LIST_ROOM;
|
|
26
|
+
for (const tool of listed) {
|
|
27
|
+
const entry = {
|
|
28
|
+
name: tool.name,
|
|
29
|
+
...(tool.description ? { description: cut(tool.description, DESCRIPTION_MAX) } : {}),
|
|
30
|
+
inputSchema: tool.inputSchema,
|
|
31
|
+
};
|
|
32
|
+
const size = Buffer.byteLength(JSON.stringify(entry));
|
|
33
|
+
if (tool.name.length < 1 || tool.name.length > NAME_MAX || size > room) {
|
|
34
|
+
log.warn(`Left out the tool ${tool.name.slice(0, NAME_MAX)}: it doesn't fit tools@1.`);
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
room -= size;
|
|
38
|
+
kept.push(entry);
|
|
39
|
+
}
|
|
40
|
+
return kept;
|
|
41
|
+
}
|
|
42
|
+
/** A tool's result as text: its text blocks as they are, and what else it held by name. */
|
|
43
|
+
function textOf(result) {
|
|
44
|
+
const parts = (result.content ?? []).map((block) => {
|
|
45
|
+
switch (block.type) {
|
|
46
|
+
case "text":
|
|
47
|
+
return block.text;
|
|
48
|
+
case "resource":
|
|
49
|
+
return "text" in block.resource ? block.resource.text : `[resource ${block.resource.uri}]`;
|
|
50
|
+
case "resource_link":
|
|
51
|
+
return `[resource ${block.uri}]`;
|
|
52
|
+
default:
|
|
53
|
+
return `[${block.type}]`;
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
if (parts.length === 0 && result.structuredContent)
|
|
57
|
+
return JSON.stringify(result.structuredContent);
|
|
58
|
+
return parts.join("\n");
|
|
59
|
+
}
|
|
60
|
+
function transportOf(spec, secrets, log) {
|
|
61
|
+
if (spec.kind === "url") {
|
|
62
|
+
const { token } = secrets;
|
|
63
|
+
return new StreamableHTTPClientTransport(new URL(spec.url), {
|
|
64
|
+
...(token ? { requestInit: { headers: { Authorization: `Bearer ${token}` } } } : {}),
|
|
65
|
+
// Checked at each request, so a name that later points home is refused then.
|
|
66
|
+
...(spec.public ? { fetch: publicFetch } : {}),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
const transport = new StdioClientTransport({
|
|
70
|
+
command: spec.command,
|
|
71
|
+
args: spec.args ?? [],
|
|
72
|
+
env: { ...getDefaultEnvironment(), ...secrets },
|
|
73
|
+
stderr: "pipe",
|
|
74
|
+
...(spec.cwd ? { cwd: spec.cwd } : {}),
|
|
75
|
+
});
|
|
76
|
+
// By whole lines, so a secret the server prints can't be split past the log's scrubbing.
|
|
77
|
+
let line = "";
|
|
78
|
+
transport.stderr?.on("data", (chunk) => {
|
|
79
|
+
const parts = (line + String(chunk)).split("\n");
|
|
80
|
+
line = (parts.pop() ?? "").slice(-65_536);
|
|
81
|
+
for (const part of parts)
|
|
82
|
+
log.warn(part);
|
|
83
|
+
});
|
|
84
|
+
return transport;
|
|
85
|
+
}
|
|
86
|
+
export class Connection {
|
|
87
|
+
#state = "connecting";
|
|
88
|
+
#detail;
|
|
89
|
+
#tools = [];
|
|
90
|
+
#mcp;
|
|
91
|
+
#hub;
|
|
92
|
+
#ended = false;
|
|
93
|
+
#wake;
|
|
94
|
+
/** Ends the current session at once, whatever its transport is still waiting for. */
|
|
95
|
+
#lose;
|
|
96
|
+
#running;
|
|
97
|
+
#spec;
|
|
98
|
+
#hide;
|
|
99
|
+
#secrets;
|
|
100
|
+
#log;
|
|
101
|
+
#scrub;
|
|
102
|
+
#pingEveryMs;
|
|
103
|
+
#firstDelayMs;
|
|
104
|
+
/** `hide` names tools of the server that are never offered or run through this connection. */
|
|
105
|
+
constructor(spec, secrets, log, timing = {}, hide = []) {
|
|
106
|
+
this.#hide = new Set(hide);
|
|
107
|
+
this.#spec = spec;
|
|
108
|
+
this.#secrets = secrets;
|
|
109
|
+
this.#pingEveryMs = timing.pingEveryMs ?? PING_EVERY_MS;
|
|
110
|
+
this.#firstDelayMs = timing.firstDelayMs ?? FIRST_DELAY_MS;
|
|
111
|
+
// What is secret never leaves in a log, a detail or an error: its values, and an address's query.
|
|
112
|
+
const query = spec.kind === "url" ? new URL(spec.url).search : "";
|
|
113
|
+
// A value that spans lines is also hidden line by line, as a server prints it; longest first.
|
|
114
|
+
const hidden = [
|
|
115
|
+
...Object.values(secrets).flatMap((value) => [
|
|
116
|
+
value,
|
|
117
|
+
...value.split(/\r?\n/).filter((line) => line.length > 0),
|
|
118
|
+
]),
|
|
119
|
+
...(query.length > 1 ? [query] : []),
|
|
120
|
+
].sort((a, b) => b.length - a.length);
|
|
121
|
+
this.#scrub = (text) => hidden.reduce((out, value) => out.replaceAll(value, "[hidden]"), text);
|
|
122
|
+
const clean = (message) => cut(this.#scrub(message), 4000);
|
|
123
|
+
this.#log = {
|
|
124
|
+
info: (message, fields) => log.info(clean(message), fields),
|
|
125
|
+
warn: (message, fields) => log.warn(clean(message), fields),
|
|
126
|
+
error: (message, fields) => log.error(clean(message), fields),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/** Join the Hub as the connection's Actor, offering its tools. */
|
|
130
|
+
async join(hub) {
|
|
131
|
+
this.#hub = await connect({
|
|
132
|
+
...hub,
|
|
133
|
+
exports: { tools },
|
|
134
|
+
log: this.#log,
|
|
135
|
+
start: (ctx) => {
|
|
136
|
+
ctx.exports.tools.implement({
|
|
137
|
+
list: () => {
|
|
138
|
+
this.#requireUp();
|
|
139
|
+
return { tools: this.#tools };
|
|
140
|
+
},
|
|
141
|
+
call: ({ name, arguments: args }) => this.#call(name, args),
|
|
142
|
+
});
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
/** Keep the server connected, from now until the connection ends. */
|
|
147
|
+
run() {
|
|
148
|
+
this.#running = this.#keepUp();
|
|
149
|
+
}
|
|
150
|
+
status() {
|
|
151
|
+
return {
|
|
152
|
+
state: this.#state,
|
|
153
|
+
...(this.#detail ? { detail: this.#detail } : {}),
|
|
154
|
+
tools: this.#tools.map((tool) => ({
|
|
155
|
+
name: tool.name,
|
|
156
|
+
...(tool.description ? { description: cut(tool.description, STATUS_DESCRIPTION_MAX) } : {}),
|
|
157
|
+
})),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
/** End it: the server is let go and the Actor leaves the Hub. */
|
|
161
|
+
async end() {
|
|
162
|
+
this.#ended = true;
|
|
163
|
+
this.#wake?.();
|
|
164
|
+
this.#lose?.();
|
|
165
|
+
await this.#mcp?.close().catch(() => { });
|
|
166
|
+
await this.#running;
|
|
167
|
+
this.#hub?.close();
|
|
168
|
+
}
|
|
169
|
+
#requireUp() {
|
|
170
|
+
if (this.#state !== "connected")
|
|
171
|
+
throw new Refused("not_connected", this.#detail ?? "The server isn't connected yet.");
|
|
172
|
+
}
|
|
173
|
+
async #call(name, args) {
|
|
174
|
+
this.#requireUp();
|
|
175
|
+
if (!this.#tools.some((tool) => tool.name === name))
|
|
176
|
+
throw new Refused("unknown", `This connection has no tool named ${name}.`);
|
|
177
|
+
const mcp = this.#mcp;
|
|
178
|
+
try {
|
|
179
|
+
const result = await mcp.callTool({ name, arguments: args });
|
|
180
|
+
return {
|
|
181
|
+
output: cut(textOf(result), OUTPUT_MAX),
|
|
182
|
+
...(result.isError ? { failed: true } : {}),
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
if (this.#gone(error)) {
|
|
187
|
+
this.#lose?.();
|
|
188
|
+
throw new Refused("not_connected", `The server went away during ${name}.`);
|
|
189
|
+
}
|
|
190
|
+
return { output: cut(this.#scrub(messageOf(error)), 2000), failed: true };
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/** Whether an error says the server can't be reached, rather than that one request failed. */
|
|
194
|
+
#gone(error) {
|
|
195
|
+
if (error instanceof TypeError)
|
|
196
|
+
return true;
|
|
197
|
+
return (error instanceof SdkError &&
|
|
198
|
+
(error.code === SdkErrorCode.ConnectionClosed || error.code === SdkErrorCode.NotConnected));
|
|
199
|
+
}
|
|
200
|
+
#set(state, detail) {
|
|
201
|
+
const changed = state !== this.#state && (state === "connected" || this.#state === "connected");
|
|
202
|
+
this.#state = state;
|
|
203
|
+
this.#detail = detail === undefined ? undefined : cut(this.#scrub(detail), 2000);
|
|
204
|
+
if (state !== "connected")
|
|
205
|
+
this.#tools = [];
|
|
206
|
+
if (changed)
|
|
207
|
+
this.#changed();
|
|
208
|
+
}
|
|
209
|
+
#changed() {
|
|
210
|
+
this.#hub?.exports.tools.emit("changed", {});
|
|
211
|
+
}
|
|
212
|
+
async #keepUp() {
|
|
213
|
+
let delay = this.#firstDelayMs;
|
|
214
|
+
while (!this.#ended) {
|
|
215
|
+
const began = Date.now();
|
|
216
|
+
const why = await this.#session();
|
|
217
|
+
if (this.#ended)
|
|
218
|
+
return;
|
|
219
|
+
this.#set("down", why);
|
|
220
|
+
if (Date.now() - began >= STEADY_MS)
|
|
221
|
+
delay = this.#firstDelayMs;
|
|
222
|
+
await new Promise((resolve) => {
|
|
223
|
+
const timer = setTimeout(resolve, delay);
|
|
224
|
+
this.#wake = () => {
|
|
225
|
+
clearTimeout(timer);
|
|
226
|
+
resolve();
|
|
227
|
+
};
|
|
228
|
+
});
|
|
229
|
+
delay = Math.min(delay * 2, MAX_DELAY_MS);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/** One connection to the server, for as long as it lasts; it resolves with why it ended. */
|
|
233
|
+
async #session() {
|
|
234
|
+
const log = this.#log;
|
|
235
|
+
const mcp = new Client({ name: "agentorg", version: "0" }, {
|
|
236
|
+
listChanged: {
|
|
237
|
+
tools: {
|
|
238
|
+
autoRefresh: false,
|
|
239
|
+
onChanged: () => {
|
|
240
|
+
this.#refresh(mcp).then(() => this.#changed(), (error) => log.warn(`Listing the tools again didn't work: ${messageOf(error)}`));
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
});
|
|
245
|
+
this.#mcp = mcp;
|
|
246
|
+
let over = false;
|
|
247
|
+
const closed = new Promise((resolve) => {
|
|
248
|
+
const done = () => {
|
|
249
|
+
over = true;
|
|
250
|
+
resolve();
|
|
251
|
+
};
|
|
252
|
+
mcp.onclose = done;
|
|
253
|
+
this.#lose = done;
|
|
254
|
+
});
|
|
255
|
+
let pinging;
|
|
256
|
+
try {
|
|
257
|
+
// A failed start closes before it rejects: what it rejects with is the reason to give.
|
|
258
|
+
for (const step of [
|
|
259
|
+
() => mcp.connect(transportOf(this.#spec, this.#secrets, log)),
|
|
260
|
+
() => this.#refresh(mcp),
|
|
261
|
+
]) {
|
|
262
|
+
const going = step();
|
|
263
|
+
await Promise.race([going, closed]);
|
|
264
|
+
if (this.#ended)
|
|
265
|
+
return "";
|
|
266
|
+
if (over) {
|
|
267
|
+
await going;
|
|
268
|
+
return "The connection to the server ended.";
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
this.#set("connected");
|
|
272
|
+
// An address's transport says nothing when its server dies: asking is how that's noticed.
|
|
273
|
+
pinging = setInterval(() => {
|
|
274
|
+
mcp.ping({ timeout: PING_TIMEOUT_MS }).catch((error) => {
|
|
275
|
+
if (!(error instanceof ProtocolError))
|
|
276
|
+
this.#lose?.();
|
|
277
|
+
});
|
|
278
|
+
}, this.#pingEveryMs);
|
|
279
|
+
await closed;
|
|
280
|
+
return "The connection to the server ended.";
|
|
281
|
+
}
|
|
282
|
+
catch (error) {
|
|
283
|
+
return messageOf(error);
|
|
284
|
+
}
|
|
285
|
+
finally {
|
|
286
|
+
clearInterval(pinging);
|
|
287
|
+
this.#mcp = undefined;
|
|
288
|
+
this.#lose = undefined;
|
|
289
|
+
await mcp.close().catch(() => { });
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
async #refresh(mcp) {
|
|
293
|
+
const { tools: listed } = await mcp.listTools();
|
|
294
|
+
this.#tools = fit(listed.filter((tool) => !this.#hide.has(tool.name)), this.#log);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
declare const UrlParams: z.ZodObject<{
|
|
3
|
+
url: z.ZodURL;
|
|
4
|
+
public: z.ZodOptional<z.ZodBoolean>;
|
|
5
|
+
}, z.core.$strict>;
|
|
6
|
+
declare const CommandParams: z.ZodObject<{
|
|
7
|
+
command: z.ZodString;
|
|
8
|
+
args: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
9
|
+
cwd: z.ZodOptional<z.ZodString>;
|
|
10
|
+
}, z.core.$strict>;
|
|
11
|
+
export type Spec = ({
|
|
12
|
+
kind: "url";
|
|
13
|
+
} & z.infer<typeof UrlParams>) | ({
|
|
14
|
+
kind: "command";
|
|
15
|
+
} & z.infer<typeof CommandParams>);
|
|
16
|
+
export type Secrets = Record<string, string>;
|
|
17
|
+
export declare const KINDS: readonly [{
|
|
18
|
+
readonly kind: "url";
|
|
19
|
+
readonly title: "A server at an address";
|
|
20
|
+
readonly params: z.ZodObject<{
|
|
21
|
+
url: z.ZodURL;
|
|
22
|
+
public: z.ZodOptional<z.ZodBoolean>;
|
|
23
|
+
}, z.core.$strict>;
|
|
24
|
+
readonly secrets: z.ZodObject<{
|
|
25
|
+
token: z.ZodOptional<z.ZodString>;
|
|
26
|
+
}, z.core.$strict>;
|
|
27
|
+
}, {
|
|
28
|
+
readonly kind: "command";
|
|
29
|
+
readonly title: "A local server this machine starts";
|
|
30
|
+
readonly params: z.ZodObject<{
|
|
31
|
+
command: z.ZodString;
|
|
32
|
+
args: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
33
|
+
cwd: z.ZodOptional<z.ZodString>;
|
|
34
|
+
}, z.core.$strict>;
|
|
35
|
+
readonly secrets: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
36
|
+
}];
|
|
37
|
+
/** Each kind as a unit: it gives one connection, under the name it is filled in with. */
|
|
38
|
+
export declare const UNITS: ({
|
|
39
|
+
id: string;
|
|
40
|
+
title: string;
|
|
41
|
+
description: string;
|
|
42
|
+
form: ({
|
|
43
|
+
readonly id: "slot";
|
|
44
|
+
readonly type: "text";
|
|
45
|
+
readonly value: "string";
|
|
46
|
+
readonly title: "Name";
|
|
47
|
+
readonly description: "What the agent knows this connection as.";
|
|
48
|
+
readonly required: true;
|
|
49
|
+
} | {
|
|
50
|
+
id: string;
|
|
51
|
+
authority: "contacts";
|
|
52
|
+
type: string;
|
|
53
|
+
value: "string";
|
|
54
|
+
title: string;
|
|
55
|
+
description: string;
|
|
56
|
+
required: true;
|
|
57
|
+
} | {
|
|
58
|
+
authority?: undefined;
|
|
59
|
+
required?: undefined;
|
|
60
|
+
id: string;
|
|
61
|
+
type: string;
|
|
62
|
+
value: "secret";
|
|
63
|
+
title: string;
|
|
64
|
+
description?: undefined;
|
|
65
|
+
} | {
|
|
66
|
+
authority?: undefined;
|
|
67
|
+
required?: undefined;
|
|
68
|
+
id: string;
|
|
69
|
+
type: string;
|
|
70
|
+
value: "boolean";
|
|
71
|
+
title: string;
|
|
72
|
+
description: string;
|
|
73
|
+
})[];
|
|
74
|
+
needs: never[];
|
|
75
|
+
gives: {
|
|
76
|
+
slots: {
|
|
77
|
+
field: string;
|
|
78
|
+
}[];
|
|
79
|
+
skills: never[];
|
|
80
|
+
results: never[];
|
|
81
|
+
};
|
|
82
|
+
} | {
|
|
83
|
+
id: string;
|
|
84
|
+
title: string;
|
|
85
|
+
description: string;
|
|
86
|
+
form: ({
|
|
87
|
+
readonly id: "slot";
|
|
88
|
+
readonly type: "text";
|
|
89
|
+
readonly value: "string";
|
|
90
|
+
readonly title: "Name";
|
|
91
|
+
readonly description: "What the agent knows this connection as.";
|
|
92
|
+
readonly required: true;
|
|
93
|
+
} | {
|
|
94
|
+
description?: undefined;
|
|
95
|
+
id: string;
|
|
96
|
+
authority: "runs";
|
|
97
|
+
type: string;
|
|
98
|
+
value: "string";
|
|
99
|
+
title: string;
|
|
100
|
+
required: true;
|
|
101
|
+
} | {
|
|
102
|
+
required?: undefined;
|
|
103
|
+
description?: undefined;
|
|
104
|
+
id: string;
|
|
105
|
+
authority: "runs";
|
|
106
|
+
type: string;
|
|
107
|
+
value: "strings";
|
|
108
|
+
title: string;
|
|
109
|
+
} | {
|
|
110
|
+
required?: undefined;
|
|
111
|
+
description?: undefined;
|
|
112
|
+
id: string;
|
|
113
|
+
authority: "runs";
|
|
114
|
+
type: string;
|
|
115
|
+
value: "string";
|
|
116
|
+
title: string;
|
|
117
|
+
} | {
|
|
118
|
+
authority?: undefined;
|
|
119
|
+
required?: undefined;
|
|
120
|
+
id: string;
|
|
121
|
+
type: string;
|
|
122
|
+
value: "secret";
|
|
123
|
+
title: string;
|
|
124
|
+
description: string;
|
|
125
|
+
})[];
|
|
126
|
+
needs: never[];
|
|
127
|
+
gives: {
|
|
128
|
+
slots: {
|
|
129
|
+
field: string;
|
|
130
|
+
}[];
|
|
131
|
+
skills: never[];
|
|
132
|
+
results: never[];
|
|
133
|
+
};
|
|
134
|
+
})[];
|
|
135
|
+
/**
|
|
136
|
+
* What a unit's secrets mean to a connection: the lines are environment variables by name.
|
|
137
|
+
* Secrets that come by name already are as they are. A line is named by position, never by content.
|
|
138
|
+
*/
|
|
139
|
+
export declare function namedSecrets(secrets: Secrets): {
|
|
140
|
+
secrets?: Secrets;
|
|
141
|
+
why?: string;
|
|
142
|
+
};
|
|
143
|
+
/** What a connection's parameters and secrets say, or why they don't fit its kind. */
|
|
144
|
+
export declare function parseConnection(kind: string, params: unknown, secrets: unknown): {
|
|
145
|
+
spec: Spec;
|
|
146
|
+
secrets: Secrets;
|
|
147
|
+
why?: undefined;
|
|
148
|
+
} | {
|
|
149
|
+
spec?: undefined;
|
|
150
|
+
secrets?: undefined;
|
|
151
|
+
why: string;
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* What a connection attaches to or runs, for people to read. An address loses its query, which is
|
|
155
|
+
* where a secret would be.
|
|
156
|
+
*/
|
|
157
|
+
export declare function targetOf(spec: Spec): string;
|
|
158
|
+
export {};
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const SecretValue = z.string().min(1).max(16_384);
|
|
3
|
+
const EnvName = z
|
|
4
|
+
.string()
|
|
5
|
+
.regex(/^[A-Za-z_][A-Za-z0-9_]*$/)
|
|
6
|
+
.max(256);
|
|
7
|
+
const UrlParams = z.strictObject({
|
|
8
|
+
url: z
|
|
9
|
+
.url({ protocol: /^https?$/ })
|
|
10
|
+
.max(4096)
|
|
11
|
+
.refine((url) => {
|
|
12
|
+
if (!URL.canParse(url))
|
|
13
|
+
return true; // Said already, by `z.url`.
|
|
14
|
+
const { username, password } = new URL(url);
|
|
15
|
+
return !username && !password;
|
|
16
|
+
}, "An address can't hold a user or a password: give a token as a secret.")
|
|
17
|
+
.meta({ title: "Address" }),
|
|
18
|
+
public: z.boolean().optional().meta({ title: "Public addresses only" }),
|
|
19
|
+
});
|
|
20
|
+
/** The bearer token sent to the server on every request. */
|
|
21
|
+
const UrlSecrets = z.strictObject({ token: SecretValue.optional().meta({ title: "Token" }) });
|
|
22
|
+
const CommandParams = z.strictObject({
|
|
23
|
+
command: z.string().min(1).max(4096).meta({ title: "Command" }),
|
|
24
|
+
args: z.array(z.string().max(4096)).max(256).optional().meta({ title: "Arguments" }),
|
|
25
|
+
cwd: z.string().min(1).max(4096).optional().meta({ title: "Working folder" }),
|
|
26
|
+
});
|
|
27
|
+
/** Each one is an environment variable of the server, by its name. */
|
|
28
|
+
const CommandSecrets = z.record(EnvName, SecretValue);
|
|
29
|
+
export const KINDS = [
|
|
30
|
+
{ kind: "url", title: "A server at an address", params: UrlParams, secrets: UrlSecrets },
|
|
31
|
+
{
|
|
32
|
+
kind: "command",
|
|
33
|
+
title: "A local server this machine starts",
|
|
34
|
+
params: CommandParams,
|
|
35
|
+
secrets: CommandSecrets,
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
/** The secret holding a command's environment as lines; named so that no variable is called it. */
|
|
39
|
+
const LINES = "agentorgEnvironmentLines";
|
|
40
|
+
const NAME = {
|
|
41
|
+
id: "slot",
|
|
42
|
+
type: "text",
|
|
43
|
+
value: "string",
|
|
44
|
+
title: "Name",
|
|
45
|
+
description: "What the agent knows this connection as.",
|
|
46
|
+
required: true,
|
|
47
|
+
};
|
|
48
|
+
const GIVES = { slots: [{ field: "slot" }], skills: [], results: [] };
|
|
49
|
+
/** Each kind as a unit: it gives one connection, under the name it is filled in with. */
|
|
50
|
+
export const UNITS = [
|
|
51
|
+
{
|
|
52
|
+
id: "url",
|
|
53
|
+
title: "A server at an address",
|
|
54
|
+
description: "Connects to an MCP server over HTTP.",
|
|
55
|
+
form: [
|
|
56
|
+
{
|
|
57
|
+
id: "url",
|
|
58
|
+
authority: "contacts",
|
|
59
|
+
type: "text",
|
|
60
|
+
value: "string",
|
|
61
|
+
title: "Address",
|
|
62
|
+
description: "It is shown and kept as written: a token goes in Token.",
|
|
63
|
+
required: true,
|
|
64
|
+
},
|
|
65
|
+
{ id: "token", type: "secret", value: "secret", title: "Token" },
|
|
66
|
+
{
|
|
67
|
+
id: "public",
|
|
68
|
+
type: "toggle",
|
|
69
|
+
value: "boolean",
|
|
70
|
+
title: "Public addresses only",
|
|
71
|
+
description: "It reaches only https servers on the public internet, never this machine or its network, and follows no redirect.",
|
|
72
|
+
},
|
|
73
|
+
NAME,
|
|
74
|
+
],
|
|
75
|
+
needs: [],
|
|
76
|
+
gives: GIVES,
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
id: "command",
|
|
80
|
+
title: "A local server this machine starts",
|
|
81
|
+
description: "Starts an MCP server with this app's rights.",
|
|
82
|
+
form: [
|
|
83
|
+
{
|
|
84
|
+
id: "command",
|
|
85
|
+
authority: "runs",
|
|
86
|
+
type: "text",
|
|
87
|
+
value: "string",
|
|
88
|
+
title: "Command",
|
|
89
|
+
required: true,
|
|
90
|
+
},
|
|
91
|
+
{ id: "args", authority: "runs", type: "lines", value: "strings", title: "Arguments" },
|
|
92
|
+
{ id: "cwd", authority: "runs", type: "directory", value: "string", title: "Working folder" },
|
|
93
|
+
{
|
|
94
|
+
id: LINES,
|
|
95
|
+
type: "environment",
|
|
96
|
+
value: "secret",
|
|
97
|
+
title: "Secrets",
|
|
98
|
+
description: "One NAME=value per line: each is an environment variable of the server.",
|
|
99
|
+
},
|
|
100
|
+
NAME,
|
|
101
|
+
],
|
|
102
|
+
needs: [],
|
|
103
|
+
gives: GIVES,
|
|
104
|
+
},
|
|
105
|
+
];
|
|
106
|
+
/**
|
|
107
|
+
* What a unit's secrets mean to a connection: the lines are environment variables by name.
|
|
108
|
+
* Secrets that come by name already are as they are. A line is named by position, never by content.
|
|
109
|
+
*/
|
|
110
|
+
export function namedSecrets(secrets) {
|
|
111
|
+
const { [LINES]: lines, ...named } = secrets;
|
|
112
|
+
if (lines === undefined)
|
|
113
|
+
return { secrets: named };
|
|
114
|
+
for (const [index, line] of lines.split(/\r?\n/).entries()) {
|
|
115
|
+
if (line.trim() === "")
|
|
116
|
+
continue;
|
|
117
|
+
const split = line.indexOf("=");
|
|
118
|
+
if (split < 1)
|
|
119
|
+
return { why: `Line ${index + 1} of the secrets isn't NAME=value.` };
|
|
120
|
+
named[line.slice(0, split).trim()] = line.slice(split + 1);
|
|
121
|
+
}
|
|
122
|
+
return { secrets: named };
|
|
123
|
+
}
|
|
124
|
+
const LOOPBACK = new Set(["127.0.0.1", "localhost", "[::1]"]);
|
|
125
|
+
/** What a connection's parameters and secrets say, or why they don't fit its kind. */
|
|
126
|
+
export function parseConnection(kind, params, secrets) {
|
|
127
|
+
const found = KINDS.find((k) => k.kind === kind);
|
|
128
|
+
if (!found)
|
|
129
|
+
return { why: `No kind is named ${kind}: this provider offers url and command.` };
|
|
130
|
+
const parsed = found.params.safeParse(params);
|
|
131
|
+
if (!parsed.success)
|
|
132
|
+
return { why: `${kind}: ${z.prettifyError(parsed.error)}` };
|
|
133
|
+
const hidden = found.secrets.safeParse(secrets ?? {});
|
|
134
|
+
// Named by what's wrong with their shape only: a refusal never repeats a value.
|
|
135
|
+
if (!hidden.success)
|
|
136
|
+
return { why: `${kind}: its secrets don't fit: ${found.title}.` };
|
|
137
|
+
const spec = { kind, ...parsed.data };
|
|
138
|
+
if (spec.kind === "url" && spec.public) {
|
|
139
|
+
if (new URL(spec.url).protocol !== "https:")
|
|
140
|
+
return { why: "A public address is https." };
|
|
141
|
+
if ("token" in hidden.data)
|
|
142
|
+
return { why: "A public-only connection takes no token." };
|
|
143
|
+
}
|
|
144
|
+
if (spec.kind === "url" && "token" in hidden.data) {
|
|
145
|
+
const url = new URL(spec.url);
|
|
146
|
+
if (url.protocol === "http:" && !LOOPBACK.has(url.hostname))
|
|
147
|
+
return { why: "A token is sent only over https, or to this machine." };
|
|
148
|
+
}
|
|
149
|
+
return { spec, secrets: hidden.data };
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* What a connection attaches to or runs, for people to read. An address loses its query, which is
|
|
153
|
+
* where a secret would be.
|
|
154
|
+
*/
|
|
155
|
+
export function targetOf(spec) {
|
|
156
|
+
if (spec.kind === "url") {
|
|
157
|
+
const url = new URL(spec.url);
|
|
158
|
+
url.search = "";
|
|
159
|
+
url.hash = "";
|
|
160
|
+
return url.href.slice(0, 4096);
|
|
161
|
+
}
|
|
162
|
+
const line = [spec.command, ...(spec.args ?? [])].join(" ");
|
|
163
|
+
return (spec.cwd ? `${line} (in ${spec.cwd})` : line).slice(0, 4096);
|
|
164
|
+
}
|