@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,482 @@
|
|
|
1
|
+
// The units' provider, and the connector to AgentComputer. A computer is one the service runs: this
|
|
2
|
+
// asks the service for it through its SDK, then opens an ordinary `url` connection to each endpoint
|
|
3
|
+
// with the computer's token. The web unit is one connection to a hosted server. Nothing here starts
|
|
4
|
+
// a service. The control token and each computer's token stay in this provider's private file.
|
|
5
|
+
import { randomBytes } from "node:crypto";
|
|
6
|
+
import { chmodSync, mkdirSync, readFileSync, renameSync, statSync, writeFileSync } from "node:fs";
|
|
7
|
+
import { readFile } from "node:fs/promises";
|
|
8
|
+
import { homedir } from "node:os";
|
|
9
|
+
import { isAbsolute, join } from "node:path";
|
|
10
|
+
import { fileURLToPath } from "node:url";
|
|
11
|
+
import { Computer, ComputerError } from "@agentorg/computer";
|
|
12
|
+
import { hubActors, unitProvider } from "@agentorg/interfaces";
|
|
13
|
+
import { Connection, parseConnection } from "@agentorg/mcp";
|
|
14
|
+
import { Refused } from "@agentorg/sdk";
|
|
15
|
+
import { connect } from "@agentorg/sdk/client";
|
|
16
|
+
import { z } from "zod";
|
|
17
|
+
import { ANOTHER, BROWSER_SLOT, COMPUTER, computerUnit, INSTALL_STEPS, LOCAL, SKILLS, WEB, WEB_UNIT, } from "./unit.js";
|
|
18
|
+
const Link = z.object({
|
|
19
|
+
slot: z.string(),
|
|
20
|
+
actor: z.string(),
|
|
21
|
+
credential: z.string(),
|
|
22
|
+
url: z.string(),
|
|
23
|
+
});
|
|
24
|
+
const Stored = z.object({
|
|
25
|
+
agent: z.string(),
|
|
26
|
+
links: z.array(Link),
|
|
27
|
+
/** The computer behind them. A service at an address is reached with what is kept here. */
|
|
28
|
+
computer: z
|
|
29
|
+
.object({
|
|
30
|
+
id: z.string(),
|
|
31
|
+
token: z.string(),
|
|
32
|
+
service: z.union([
|
|
33
|
+
z.object({ local: z.literal(true) }),
|
|
34
|
+
z.object({ apiUrl: z.string(), apiKey: z.string() }),
|
|
35
|
+
]),
|
|
36
|
+
})
|
|
37
|
+
.optional(),
|
|
38
|
+
});
|
|
39
|
+
const FILE = "instances.json";
|
|
40
|
+
const SKILLS_DIR = fileURLToPath(new URL("../../skills/", import.meta.url));
|
|
41
|
+
const EXA_URL = "https://mcp.exa.ai/mcp?tools=web_search_exa,web_fetch_exa";
|
|
42
|
+
const SERVICE_ANSWERS_MS = 2000;
|
|
43
|
+
const SAYS = {
|
|
44
|
+
read: "reads files",
|
|
45
|
+
files: "reads and changes files",
|
|
46
|
+
terminal: "files and terminal",
|
|
47
|
+
};
|
|
48
|
+
const LEVELS = ["read", "files", "terminal"];
|
|
49
|
+
const messageOf = (error) => (error instanceof Error ? error.message : String(error));
|
|
50
|
+
const quiet = { info() { }, warn() { }, error() { } };
|
|
51
|
+
/** An endpoint at the address the service was reached on, whatever the service calls itself. */
|
|
52
|
+
const at = (apiUrl, endpoint) => {
|
|
53
|
+
const url = new URL(endpoint);
|
|
54
|
+
const { origin } = new URL(apiUrl);
|
|
55
|
+
return `${origin}${url.pathname}${url.search}`;
|
|
56
|
+
};
|
|
57
|
+
/** A live session's socket, at the address the service was reached on. */
|
|
58
|
+
const socketAt = (apiUrl, socket) => {
|
|
59
|
+
const { pathname, search } = new URL(socket);
|
|
60
|
+
const reached = new URL(apiUrl);
|
|
61
|
+
return `${reached.protocol === "https:" ? "wss:" : "ws:"}//${reached.host}${pathname}${search}`;
|
|
62
|
+
};
|
|
63
|
+
/** How long a computer's own surfaces may take to say what they are, in a status. */
|
|
64
|
+
const SURFACES_MS = 2000;
|
|
65
|
+
/** How long what they said is used again: a status is asked for often. */
|
|
66
|
+
const SURFACES_FRESH_MS = 10_000;
|
|
67
|
+
/** The same folders the service looks in itself. */
|
|
68
|
+
const defaultDataFolder = () => process.env.AGENTCOMPUTER_DATA ??
|
|
69
|
+
(process.env.XDG_DATA_HOME
|
|
70
|
+
? join(process.env.XDG_DATA_HOME, "agentcomputer")
|
|
71
|
+
: join(homedir(), ".local", "share", "agentcomputer"));
|
|
72
|
+
/** A folder as a person writes it: `~/` is their home. */
|
|
73
|
+
const fromHome = (folder) => typeof folder === "string" && folder.startsWith("~/")
|
|
74
|
+
? join(homedir(), folder.slice(2))
|
|
75
|
+
: folder;
|
|
76
|
+
/** What is wrong with what was filled in; nothing means it can be applied. */
|
|
77
|
+
function problems(unit, values, found, secrets) {
|
|
78
|
+
const wrong = [];
|
|
79
|
+
if (unit === WEB) {
|
|
80
|
+
if (values.service !== "exa")
|
|
81
|
+
wrong.push({ field: "service", message: "Choose a service." });
|
|
82
|
+
return wrong;
|
|
83
|
+
}
|
|
84
|
+
if ((values.service === LOCAL || values.service === undefined) && !found)
|
|
85
|
+
wrong.push({ field: "service", message: INSTALL_STEPS });
|
|
86
|
+
else if (values.service === ANOTHER) {
|
|
87
|
+
const given = secrets.includes("token") ? { token: "given" } : {};
|
|
88
|
+
const { why } = parseConnection("url", { url: values.address }, given);
|
|
89
|
+
if (why)
|
|
90
|
+
wrong.push({ field: "address", message: `That address won't do. ${why}` });
|
|
91
|
+
}
|
|
92
|
+
else if (values.service !== LOCAL)
|
|
93
|
+
wrong.push({ field: "service", message: "Choose a service." });
|
|
94
|
+
if (values.access === "none") {
|
|
95
|
+
if (values.browser !== true)
|
|
96
|
+
wrong.push({
|
|
97
|
+
field: "access",
|
|
98
|
+
message: "With no files, no commands and no browser, there's no computer.",
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
else if (!LEVELS.includes(values.access))
|
|
102
|
+
wrong.push({ field: "access", message: "Choose what it can do." });
|
|
103
|
+
const workspace = fromHome(values.workspace);
|
|
104
|
+
if (values.service === LOCAL && workspace !== undefined) {
|
|
105
|
+
let folder = false;
|
|
106
|
+
try {
|
|
107
|
+
folder = isAbsolute(workspace) && statSync(workspace).isDirectory();
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
// Reported as not being a folder.
|
|
111
|
+
}
|
|
112
|
+
if (!folder)
|
|
113
|
+
wrong.push({ field: "workspace", message: `There's no folder at ${workspace}.` });
|
|
114
|
+
}
|
|
115
|
+
return wrong;
|
|
116
|
+
}
|
|
117
|
+
/** Run the units' provider as an Actor exporting `unit.provider@1` as `provider`. */
|
|
118
|
+
export async function startComputerProvider(options) {
|
|
119
|
+
const log = options.log ?? quiet;
|
|
120
|
+
const { hubUrl, dir } = options;
|
|
121
|
+
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
122
|
+
chmodSync(dir, 0o700);
|
|
123
|
+
const path = join(dir, FILE);
|
|
124
|
+
const read = () => {
|
|
125
|
+
let raw;
|
|
126
|
+
try {
|
|
127
|
+
raw = readFileSync(path, "utf8");
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
if (error.code === "ENOENT")
|
|
131
|
+
return {};
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
return z.record(z.string(), Stored).parse(JSON.parse(raw));
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
renameSync(path, `${path}.unreadable-${Date.now()}`);
|
|
139
|
+
log.error("The computers file can't be read: it is set aside and starts empty.");
|
|
140
|
+
return {};
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
const stored = read();
|
|
144
|
+
const save = () => {
|
|
145
|
+
writeFileSync(`${path}.tmp`, JSON.stringify(stored), { mode: 0o600, flush: true });
|
|
146
|
+
renameSync(`${path}.tmp`, path);
|
|
147
|
+
};
|
|
148
|
+
/** A service on this machine, by what it wrote; it needn't be running. */
|
|
149
|
+
const localService = () => {
|
|
150
|
+
const data = options.dataFolder ?? defaultDataFolder();
|
|
151
|
+
try {
|
|
152
|
+
const { url, pid } = JSON.parse(readFileSync(join(data, "server.json"), "utf8"));
|
|
153
|
+
// A service that crashed leaves this behind: nothing else on its port gets the token.
|
|
154
|
+
process.kill(pid, 0);
|
|
155
|
+
return { apiUrl: url, apiKey: readFileSync(join(data, "control-token"), "utf8").trim() };
|
|
156
|
+
}
|
|
157
|
+
catch {
|
|
158
|
+
return undefined;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
/** The service on this machine, if it answers now. */
|
|
162
|
+
const findLocal = async () => {
|
|
163
|
+
const reached = localService();
|
|
164
|
+
if (!reached)
|
|
165
|
+
return undefined;
|
|
166
|
+
let timer;
|
|
167
|
+
try {
|
|
168
|
+
return await Promise.race([
|
|
169
|
+
Computer.serviceInfo(reached),
|
|
170
|
+
new Promise((resolve) => {
|
|
171
|
+
timer = setTimeout(resolve, SERVICE_ANSWERS_MS, undefined);
|
|
172
|
+
}),
|
|
173
|
+
]);
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
return undefined;
|
|
177
|
+
}
|
|
178
|
+
finally {
|
|
179
|
+
clearTimeout(timer);
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
const running = new Map();
|
|
183
|
+
/** Connect a link. A service on this machine may have moved to another port since. */
|
|
184
|
+
const open = async ({ url, actor, credential }, computer) => {
|
|
185
|
+
const moved = computer && "local" in computer.service ? localService()?.apiUrl : undefined;
|
|
186
|
+
const token = computer?.token;
|
|
187
|
+
const server = new Connection({ kind: "url", url: moved ? at(moved, url) : url }, token ? { token } : {}, log, options.timing);
|
|
188
|
+
await server.join({ hubUrl, actorId: actor, credential });
|
|
189
|
+
return server;
|
|
190
|
+
};
|
|
191
|
+
const endAll = () => Promise.all([...running.values()].flat().map((server) => server.end()));
|
|
192
|
+
const held = (instance) => {
|
|
193
|
+
const found = stored[instance];
|
|
194
|
+
const servers = running.get(instance);
|
|
195
|
+
if (!found || !servers)
|
|
196
|
+
throw new Refused("unknown", `This provider holds nothing named ${instance}.`);
|
|
197
|
+
return { found, servers };
|
|
198
|
+
};
|
|
199
|
+
const reachOf = (service) => "local" in service ? localService() : service;
|
|
200
|
+
/**
|
|
201
|
+
* The computer goes. Only a service having trouble is worth another try: one that can't be
|
|
202
|
+
* reached, or no longer takes this token, mustn't keep the agent from going.
|
|
203
|
+
*/
|
|
204
|
+
const killComputer = async ({ id, service }) => {
|
|
205
|
+
const reached = reachOf(service);
|
|
206
|
+
try {
|
|
207
|
+
if (!reached)
|
|
208
|
+
throw new Error("The service isn't there.");
|
|
209
|
+
await Computer.kill(id, reached);
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
if (error instanceof ComputerError && error.code >= 500)
|
|
213
|
+
throw error;
|
|
214
|
+
if (!(error instanceof ComputerError && error.code === 404))
|
|
215
|
+
log.error(`A computer may be left on its service: ${messageOf(error)}`);
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
for (const [instance, entry] of Object.entries(stored)) {
|
|
219
|
+
const servers = [];
|
|
220
|
+
try {
|
|
221
|
+
for (const link of entry.links)
|
|
222
|
+
servers.push(await open(link, entry.computer));
|
|
223
|
+
running.set(instance, servers);
|
|
224
|
+
for (const server of servers)
|
|
225
|
+
server.run();
|
|
226
|
+
}
|
|
227
|
+
catch (error) {
|
|
228
|
+
log.error(`${instance} didn't rejoin the Hub: ${String(error)}`);
|
|
229
|
+
await Promise.all(servers.map((server) => server.end()));
|
|
230
|
+
// The Hub no longer knows it: its Actors were closed while the provider was away.
|
|
231
|
+
if (error instanceof Refused && error.code === "forbidden") {
|
|
232
|
+
if (entry.computer)
|
|
233
|
+
await killComputer(entry.computer).catch(() => { });
|
|
234
|
+
delete stored[instance];
|
|
235
|
+
save();
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/** The folder an agent with this name works in when none is named. It stays when the agent goes. */
|
|
240
|
+
const agentFolder = (agentName) => {
|
|
241
|
+
const safe = agentName
|
|
242
|
+
.trim()
|
|
243
|
+
.replace(/[/\\\p{Cc}]/gu, "-")
|
|
244
|
+
.replace(/^\.+/, "")
|
|
245
|
+
.trim() || "agent";
|
|
246
|
+
const folder = join(options.agentsFolder ?? join(homedir(), "Agents"), safe);
|
|
247
|
+
try {
|
|
248
|
+
mkdirSync(folder, { recursive: true });
|
|
249
|
+
}
|
|
250
|
+
catch {
|
|
251
|
+
throw new Refused("invalid", `The folder ${folder} can't be made.`);
|
|
252
|
+
}
|
|
253
|
+
return folder;
|
|
254
|
+
};
|
|
255
|
+
/** What of a computer can be opened live, as its service says; none if it can't say now. */
|
|
256
|
+
const asked = new Map();
|
|
257
|
+
/** One question at a time per computer, and its answer kept a little while. */
|
|
258
|
+
const surfacesOf = (computer) => {
|
|
259
|
+
const kept = asked.get(computer.id);
|
|
260
|
+
if (kept && Date.now() - kept.at < SURFACES_FRESH_MS)
|
|
261
|
+
return kept.answer;
|
|
262
|
+
const answer = askSurfaces(computer);
|
|
263
|
+
asked.set(computer.id, { at: Date.now(), answer });
|
|
264
|
+
return answer;
|
|
265
|
+
};
|
|
266
|
+
const askSurfaces = async (computer) => {
|
|
267
|
+
const reached = reachOf(computer.service);
|
|
268
|
+
if (!reached)
|
|
269
|
+
return undefined;
|
|
270
|
+
let timer;
|
|
271
|
+
try {
|
|
272
|
+
const info = await Promise.race([
|
|
273
|
+
Computer.getInfo(computer.id, reached),
|
|
274
|
+
new Promise((resolve) => {
|
|
275
|
+
timer = setTimeout(resolve, SURFACES_MS, undefined);
|
|
276
|
+
}),
|
|
277
|
+
]);
|
|
278
|
+
return info?.surfaces.map(({ surface, protocol, operate, unavailable }) => ({
|
|
279
|
+
surface,
|
|
280
|
+
protocol,
|
|
281
|
+
operate,
|
|
282
|
+
...(unavailable ? { unavailable } : {}),
|
|
283
|
+
}));
|
|
284
|
+
}
|
|
285
|
+
catch {
|
|
286
|
+
return undefined;
|
|
287
|
+
}
|
|
288
|
+
finally {
|
|
289
|
+
clearTimeout(timer);
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
/** Make the computer, and say what each of its endpoints is. */
|
|
293
|
+
const makeComputer = async (values, secrets, name, agent, agentName) => {
|
|
294
|
+
const local = values.service === LOCAL;
|
|
295
|
+
const reached = local
|
|
296
|
+
? localService()
|
|
297
|
+
: { apiUrl: String(values.address).replace(/\/$/, ""), apiKey: secrets.token };
|
|
298
|
+
if (!reached)
|
|
299
|
+
throw new Refused("invalid", INSTALL_STEPS);
|
|
300
|
+
const { isolation } = await Computer.serviceInfo(reached);
|
|
301
|
+
const access = values.access;
|
|
302
|
+
const workspace = (local
|
|
303
|
+
? (fromHome(values.workspace) ?? (agentName ? agentFolder(agentName) : undefined))
|
|
304
|
+
: values.path);
|
|
305
|
+
const computer = await Computer.create({
|
|
306
|
+
...reached,
|
|
307
|
+
access,
|
|
308
|
+
browser: values.browser === true,
|
|
309
|
+
name,
|
|
310
|
+
metadata: { agent },
|
|
311
|
+
...(workspace ? { workspace } : {}),
|
|
312
|
+
});
|
|
313
|
+
// The folder, so the person can find it: the service says where one it made is.
|
|
314
|
+
const folder = workspace ??
|
|
315
|
+
(await computer.getInfo().then((info) => info.workspace, () => null));
|
|
316
|
+
const where = local ? "this machine" : new URL(reached.apiUrl).host;
|
|
317
|
+
const on = isolation === "container" ? `${where}, in a container` : `${where}, no isolation`;
|
|
318
|
+
const servers = [];
|
|
319
|
+
if (access !== "none")
|
|
320
|
+
servers.push({
|
|
321
|
+
slot: COMPUTER,
|
|
322
|
+
url: at(reached.apiUrl, computer.getMcpUrl("computer")),
|
|
323
|
+
target: `${on}: ${SAYS[access]}${folder ? ` in ${folder}` : ""}`,
|
|
324
|
+
});
|
|
325
|
+
if (values.browser === true)
|
|
326
|
+
servers.push({
|
|
327
|
+
slot: BROWSER_SLOT,
|
|
328
|
+
url: at(reached.apiUrl, computer.getMcpUrl("browser")),
|
|
329
|
+
target: `A browser, ${on}`,
|
|
330
|
+
});
|
|
331
|
+
const held = {
|
|
332
|
+
id: computer.computerID,
|
|
333
|
+
token: computer.getMcpToken(),
|
|
334
|
+
service: local ? { local: true } : reached,
|
|
335
|
+
};
|
|
336
|
+
return { servers, computer: held };
|
|
337
|
+
};
|
|
338
|
+
let closing = false;
|
|
339
|
+
const provider = await connect({
|
|
340
|
+
hubUrl,
|
|
341
|
+
actorId: options.actorId,
|
|
342
|
+
credential: options.credential,
|
|
343
|
+
slots: { actors: hubActors },
|
|
344
|
+
exports: { provider: unitProvider },
|
|
345
|
+
log,
|
|
346
|
+
start(ctx) {
|
|
347
|
+
const known = (unit) => {
|
|
348
|
+
if (unit !== COMPUTER && unit !== WEB)
|
|
349
|
+
throw new Refused("unknown", `This provider has no unit ${unit}.`);
|
|
350
|
+
};
|
|
351
|
+
ctx.exports.provider.implement({
|
|
352
|
+
units: async () => ({ units: [computerUnit(await findLocal()), WEB_UNIT] }),
|
|
353
|
+
async skill({ unit, name, path: file }) {
|
|
354
|
+
if (!SKILLS[unit]?.includes(name) || file !== "SKILL.md")
|
|
355
|
+
throw new Refused("unknown", `${unit} has no file ${file} of a skill ${name}.`);
|
|
356
|
+
return { text: await readFile(join(SKILLS_DIR, name, file), "utf8") };
|
|
357
|
+
},
|
|
358
|
+
async check({ unit, values, secrets }) {
|
|
359
|
+
known(unit);
|
|
360
|
+
return { problems: problems(unit, values, await findLocal(), secrets) };
|
|
361
|
+
},
|
|
362
|
+
async apply({ unit, values, secrets, name, agent, agentName }) {
|
|
363
|
+
known(unit);
|
|
364
|
+
const wrong = problems(unit, values, await findLocal(), Object.keys(secrets));
|
|
365
|
+
if (wrong.length > 0)
|
|
366
|
+
throw new Refused("invalid", wrong.map((problem) => problem.message).join(" "));
|
|
367
|
+
const instance = `${unit}_${randomBytes(9).toString("hex")}`;
|
|
368
|
+
const web = { url: options.webUrl ?? EXA_URL };
|
|
369
|
+
const { servers, computer } = unit === WEB
|
|
370
|
+
? {
|
|
371
|
+
servers: [{ slot: WEB, url: web.url, target: new URL(web.url).host }],
|
|
372
|
+
computer: undefined,
|
|
373
|
+
}
|
|
374
|
+
: await makeComputer(values, secrets, name, agent, agentName);
|
|
375
|
+
const entry = { agent, links: [], ...(computer ? { computer } : {}) };
|
|
376
|
+
const made = [];
|
|
377
|
+
const connections = [];
|
|
378
|
+
try {
|
|
379
|
+
for (const { slot, url, target } of servers) {
|
|
380
|
+
// A name of its own for each, as a computer can be two Actors.
|
|
381
|
+
const { actorId, credential } = await ctx.slots.actors.call.create({
|
|
382
|
+
name: servers.length > 1 ? `${name} (${slot})`.slice(0, 128) : name,
|
|
383
|
+
});
|
|
384
|
+
const link = { slot, actor: actorId, credential: credential, url };
|
|
385
|
+
entry.links.push(link);
|
|
386
|
+
made.push(await open(link, computer));
|
|
387
|
+
connections.push({ slot, connection: actorId, target });
|
|
388
|
+
}
|
|
389
|
+
if (closing)
|
|
390
|
+
throw new Refused("unavailable", "This provider is stopping.");
|
|
391
|
+
running.set(instance, made);
|
|
392
|
+
stored[instance] = entry;
|
|
393
|
+
save();
|
|
394
|
+
for (const server of made)
|
|
395
|
+
server.run();
|
|
396
|
+
}
|
|
397
|
+
catch (error) {
|
|
398
|
+
running.delete(instance);
|
|
399
|
+
delete stored[instance];
|
|
400
|
+
await Promise.all(made.map((server) => server.end()));
|
|
401
|
+
for (const { actor } of entry.links)
|
|
402
|
+
await ctx.slots.actors.call.close({ actorId: actor }).catch(() => { });
|
|
403
|
+
if (computer)
|
|
404
|
+
await killComputer(computer).catch((failed) => log.warn(`A computer may be left on its service: ${String(failed)}`));
|
|
405
|
+
throw error;
|
|
406
|
+
}
|
|
407
|
+
return { instance, connections, results: [] };
|
|
408
|
+
},
|
|
409
|
+
status: async ({ instance }) => {
|
|
410
|
+
const { found, servers } = held(instance);
|
|
411
|
+
const each = servers.map((server, i) => ({
|
|
412
|
+
connection: found.links[i].actor,
|
|
413
|
+
...server.status(),
|
|
414
|
+
}));
|
|
415
|
+
const down = each.find((one) => one.state === "down");
|
|
416
|
+
const waiting = each.some((one) => one.state === "connecting");
|
|
417
|
+
const surfaces = found.computer ? await surfacesOf(found.computer) : undefined;
|
|
418
|
+
return {
|
|
419
|
+
state: down
|
|
420
|
+
? "down"
|
|
421
|
+
: waiting
|
|
422
|
+
? "connecting"
|
|
423
|
+
: "connected",
|
|
424
|
+
...(down?.detail ? { detail: down.detail } : {}),
|
|
425
|
+
connections: each,
|
|
426
|
+
...(surfaces ? { surfaces } : {}),
|
|
427
|
+
};
|
|
428
|
+
},
|
|
429
|
+
async live({ instance, surface, mode }) {
|
|
430
|
+
const { found } = held(instance);
|
|
431
|
+
const reached = found.computer && reachOf(found.computer.service);
|
|
432
|
+
if (!found.computer || !reached)
|
|
433
|
+
throw new Refused("unknown", "Nothing of this can be opened live.");
|
|
434
|
+
try {
|
|
435
|
+
const session = await Computer.createLiveSession(found.computer.id, { surface: surface, mode }, reached);
|
|
436
|
+
return {
|
|
437
|
+
url: socketAt(reached.apiUrl, session.url),
|
|
438
|
+
protocol: session.protocol,
|
|
439
|
+
expiresAt: session.expiresAt,
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
catch (error) {
|
|
443
|
+
if (!(error instanceof ComputerError))
|
|
444
|
+
throw error;
|
|
445
|
+
throw new Refused(error.code === 404 || error.code === 400
|
|
446
|
+
? "unknown"
|
|
447
|
+
: error.code === 409
|
|
448
|
+
? "state"
|
|
449
|
+
: "failed", error.message);
|
|
450
|
+
}
|
|
451
|
+
},
|
|
452
|
+
async remove({ instance }) {
|
|
453
|
+
const { found, servers } = held(instance);
|
|
454
|
+
// First: if the service refuses, the rest is still here to be tried again.
|
|
455
|
+
if (found.computer)
|
|
456
|
+
await killComputer(found.computer);
|
|
457
|
+
for (const { actor } of found.links)
|
|
458
|
+
await ctx.slots.actors.call.close({ actorId: actor });
|
|
459
|
+
running.delete(instance);
|
|
460
|
+
delete stored[instance];
|
|
461
|
+
try {
|
|
462
|
+
save();
|
|
463
|
+
}
|
|
464
|
+
finally {
|
|
465
|
+
await Promise.all(servers.map((server) => server.end()));
|
|
466
|
+
}
|
|
467
|
+
return {};
|
|
468
|
+
},
|
|
469
|
+
});
|
|
470
|
+
},
|
|
471
|
+
}).catch(async (error) => {
|
|
472
|
+
await endAll();
|
|
473
|
+
throw error;
|
|
474
|
+
});
|
|
475
|
+
return {
|
|
476
|
+
async close() {
|
|
477
|
+
closing = true;
|
|
478
|
+
await endAll();
|
|
479
|
+
provider.close();
|
|
480
|
+
},
|
|
481
|
+
};
|
|
482
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Unit } from "@agentorg/interfaces";
|
|
2
|
+
import type { z } from "zod";
|
|
3
|
+
export declare const COMPUTER = "computer";
|
|
4
|
+
export declare const WEB = "web";
|
|
5
|
+
export declare const BROWSER_SLOT = "browser";
|
|
6
|
+
export type Access = "read" | "files" | "terminal";
|
|
7
|
+
export declare const LOCAL = "local";
|
|
8
|
+
export declare const ANOTHER = "another";
|
|
9
|
+
/** What to do when there is no service here: the app never starts or ships one. */
|
|
10
|
+
export declare const INSTALL_STEPS = "No AgentComputer is running on this machine. Install it with npm install -g @agentorg/computer, start it with agentcomputer serve, and try again.";
|
|
11
|
+
/** How the service on this machine isolates its computers, if one is running. */
|
|
12
|
+
export type Found = {
|
|
13
|
+
isolation: "none" | "container";
|
|
14
|
+
} | undefined;
|
|
15
|
+
/** The form as it stands now, with what was found on this machine. */
|
|
16
|
+
export declare const computerUnit: (found: Found) => z.input<typeof Unit>;
|
|
17
|
+
export declare const WEB_UNIT: z.input<typeof Unit>;
|
|
18
|
+
/** The skills each unit can give, by name. */
|
|
19
|
+
export declare const SKILLS: Record<string, string[]>;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
export const COMPUTER = "computer";
|
|
2
|
+
export const WEB = "web";
|
|
3
|
+
export const BROWSER_SLOT = "browser";
|
|
4
|
+
const SKILL = "SKILL.md";
|
|
5
|
+
const skill = (name) => ({ name, files: [SKILL] });
|
|
6
|
+
const WITH_FILES = { slots: [{ name: COMPUTER }], skills: [skill("files"), skill("computer")] };
|
|
7
|
+
export const LOCAL = "local";
|
|
8
|
+
export const ANOTHER = "another";
|
|
9
|
+
/** What to do when there is no service here: the app never starts or ships one. */
|
|
10
|
+
export const INSTALL_STEPS = "No AgentComputer is running on this machine. Install it with npm install -g @agentorg/computer, start it with agentcomputer serve, and try again.";
|
|
11
|
+
const localLine = (found) => !found
|
|
12
|
+
? INSTALL_STEPS
|
|
13
|
+
: found.isolation === "container"
|
|
14
|
+
? "On this machine, started by you. Each computer is a container of its own."
|
|
15
|
+
: "On this machine, started by you. No isolation: it acts as you, and with a terminal it reaches everything you can.";
|
|
16
|
+
/** The form as it stands now, with what was found on this machine. */
|
|
17
|
+
export const computerUnit = (found) => ({
|
|
18
|
+
id: COMPUTER,
|
|
19
|
+
title: "Computer",
|
|
20
|
+
description: "A place for the agent to work: a folder, how far it can act on it, and a browser.",
|
|
21
|
+
form: [
|
|
22
|
+
{
|
|
23
|
+
id: "service",
|
|
24
|
+
type: "choice",
|
|
25
|
+
value: "string",
|
|
26
|
+
title: "Service",
|
|
27
|
+
description: "Where its computer runs, and how that's kept apart from everything else.",
|
|
28
|
+
// Not required: with none found, `check` says what to do, which is more than "fill this in".
|
|
29
|
+
...(found ? { default: LOCAL } : {}),
|
|
30
|
+
options: [
|
|
31
|
+
{ value: LOCAL, title: "This machine", description: localLine(found) },
|
|
32
|
+
{
|
|
33
|
+
value: ANOTHER,
|
|
34
|
+
title: "Another address",
|
|
35
|
+
description: "A service elsewhere. What a computer can reach depends on how it isolates.",
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: "address",
|
|
41
|
+
type: "text",
|
|
42
|
+
value: "string",
|
|
43
|
+
title: "Address",
|
|
44
|
+
description: "The service's address, over https unless it's on this machine.",
|
|
45
|
+
required: true,
|
|
46
|
+
visible: { field: "service", in: [ANOTHER] },
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: "token",
|
|
50
|
+
type: "secret",
|
|
51
|
+
value: "secret",
|
|
52
|
+
title: "Token",
|
|
53
|
+
description: "The service's control token. It's asked each time and never saved in a template.",
|
|
54
|
+
required: true,
|
|
55
|
+
visible: { field: "service", in: [ANOTHER] },
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: "access",
|
|
59
|
+
authority: "setting",
|
|
60
|
+
type: "choice",
|
|
61
|
+
value: "string",
|
|
62
|
+
title: "What it can do",
|
|
63
|
+
required: true,
|
|
64
|
+
options: [
|
|
65
|
+
{ value: "none", title: "Nothing", description: "It has no files and can't run anything." },
|
|
66
|
+
{
|
|
67
|
+
value: "read",
|
|
68
|
+
title: "Read files",
|
|
69
|
+
description: "It can read files in its working directory, but can't change them or run anything.",
|
|
70
|
+
adds: WITH_FILES,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
value: "files",
|
|
74
|
+
title: "Read and change files",
|
|
75
|
+
description: "It can read and change files in its working directory, but can't run anything.",
|
|
76
|
+
adds: WITH_FILES,
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
value: "terminal",
|
|
80
|
+
title: "Files and terminal",
|
|
81
|
+
description: "It can run any command, so it can reach every file and program you can.",
|
|
82
|
+
adds: {
|
|
83
|
+
slots: [{ name: COMPUTER }],
|
|
84
|
+
skills: [skill("terminal"), skill("files"), skill("computer")],
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
id: "browser",
|
|
91
|
+
authority: "setting",
|
|
92
|
+
type: "toggle",
|
|
93
|
+
value: "boolean",
|
|
94
|
+
title: "Browser",
|
|
95
|
+
description: "It can open web pages and act on them, in a browser of its own.",
|
|
96
|
+
default: false,
|
|
97
|
+
adds: { slots: [{ name: BROWSER_SLOT }], skills: [skill("browser")] },
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: "workspace",
|
|
101
|
+
type: "directory",
|
|
102
|
+
value: "string",
|
|
103
|
+
title: "Working directory",
|
|
104
|
+
description: "The folder it works in. Left empty, it's a folder with the agent's name in ~/Agents, made if it's missing. Its file tools stay inside it by a check, not a sandbox. Removing the agent leaves it.",
|
|
105
|
+
placeholder: "~/Agents/{name}",
|
|
106
|
+
visible: { field: "service", in: [LOCAL] },
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
id: "path",
|
|
110
|
+
type: "text",
|
|
111
|
+
value: "string",
|
|
112
|
+
title: "Working directory",
|
|
113
|
+
description: "A path on the service's machine. Removing the agent leaves it.",
|
|
114
|
+
visible: { field: "service", in: [ANOTHER] },
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
needs: [],
|
|
118
|
+
gives: { slots: [], skills: [], results: [] },
|
|
119
|
+
});
|
|
120
|
+
export const WEB_UNIT = {
|
|
121
|
+
id: WEB,
|
|
122
|
+
title: "Web search",
|
|
123
|
+
description: "Search the web and read pages.",
|
|
124
|
+
form: [
|
|
125
|
+
{
|
|
126
|
+
id: "service",
|
|
127
|
+
authority: "setting",
|
|
128
|
+
type: "choice",
|
|
129
|
+
value: "string",
|
|
130
|
+
title: "Service",
|
|
131
|
+
required: true,
|
|
132
|
+
default: "exa",
|
|
133
|
+
options: [
|
|
134
|
+
{
|
|
135
|
+
value: "exa",
|
|
136
|
+
title: "Exa",
|
|
137
|
+
description: "It searches and reads pages through Exa, which sees what it looks for.",
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
},
|
|
141
|
+
],
|
|
142
|
+
needs: [],
|
|
143
|
+
gives: { slots: [{ name: WEB }], skills: [skill("web-research")], results: [] },
|
|
144
|
+
};
|
|
145
|
+
/** The skills each unit can give, by name. */
|
|
146
|
+
export const SKILLS = {
|
|
147
|
+
[COMPUTER]: ["terminal", "files", "computer", "browser"],
|
|
148
|
+
[WEB]: ["web-research"],
|
|
149
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agentorg/computer-connector",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"description": "The computer unit: a terminal and files for an agent, on a machine the person chooses",
|
|
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
|
+
"skills"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\" && tsc -p tsconfig.json",
|
|
20
|
+
"test": "node --test \"dist/test/**/*.test.js\""
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@agentorg/computer": "0.0.10",
|
|
24
|
+
"@agentorg/interfaces": "0.0.0",
|
|
25
|
+
"@agentorg/mcp": "0.0.0",
|
|
26
|
+
"@agentorg/sdk": "0.0.0",
|
|
27
|
+
"zod": "^4.6.7"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@agentorg/hub": "0.0.0",
|
|
31
|
+
"@modelcontextprotocol/server": "2.4.0"
|
|
32
|
+
}
|
|
33
|
+
}
|