@agentorg/cli 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/README.md +18 -102
  2. package/dist/node_modules/@agentorg/hub/dist/src/hub-actor.d.ts +2 -7
  3. package/dist/node_modules/@agentorg/hub/dist/src/hub-actor.js +4 -144
  4. package/dist/node_modules/@agentorg/hub/dist/src/index.d.ts +1 -3
  5. package/dist/node_modules/@agentorg/hub/dist/src/index.js +1 -3
  6. package/dist/node_modules/@agentorg/hub/dist/src/router.d.ts +6 -57
  7. package/dist/node_modules/@agentorg/hub/dist/src/router.js +38 -413
  8. package/dist/node_modules/@agentorg/hub/dist/src/state.d.ts +17 -317
  9. package/dist/node_modules/@agentorg/hub/dist/src/state.js +42 -536
  10. package/dist/node_modules/@agentorg/hub/dist/src/validate.d.ts +1 -3
  11. package/dist/node_modules/@agentorg/hub/dist/src/validate.js +3 -15
  12. package/dist/node_modules/@agentorg/hub/package.json +0 -3
  13. package/dist/node_modules/@agentorg/interfaces/dist/src/agent-provider.d.ts +132 -0
  14. package/dist/node_modules/@agentorg/interfaces/dist/src/agent-provider.js +105 -0
  15. package/dist/node_modules/@agentorg/interfaces/dist/src/agent-settings.d.ts +42 -0
  16. package/dist/node_modules/@agentorg/interfaces/dist/src/agent-settings.js +53 -0
  17. package/dist/node_modules/@agentorg/interfaces/dist/src/chat.d.ts +15 -0
  18. package/dist/node_modules/@agentorg/interfaces/dist/src/chat.js +14 -0
  19. package/dist/node_modules/@agentorg/interfaces/dist/src/hub.d.ts +16 -286
  20. package/dist/node_modules/@agentorg/interfaces/dist/src/hub.js +17 -159
  21. package/dist/node_modules/@agentorg/interfaces/dist/src/index.d.ts +6 -8
  22. package/dist/node_modules/@agentorg/interfaces/dist/src/index.js +6 -8
  23. package/dist/node_modules/@agentorg/interfaces/dist/src/kv.d.ts +2 -2
  24. package/dist/node_modules/@agentorg/interfaces/dist/src/kv.js +2 -2
  25. package/dist/node_modules/@agentorg/interfaces/dist/src/manager.d.ts +272 -0
  26. package/dist/node_modules/@agentorg/interfaces/dist/src/manager.js +185 -0
  27. package/dist/node_modules/@agentorg/interfaces/dist/src/mcp-provider.d.ts +88 -0
  28. package/dist/node_modules/@agentorg/interfaces/dist/src/mcp-provider.js +78 -0
  29. package/dist/node_modules/@agentorg/interfaces/dist/src/tools.d.ts +39 -0
  30. package/dist/node_modules/@agentorg/interfaces/dist/src/tools.js +43 -0
  31. package/dist/node_modules/@agentorg/manager/dist/src/index.d.ts +1 -0
  32. package/dist/node_modules/@agentorg/manager/dist/src/index.js +1 -0
  33. package/dist/node_modules/@agentorg/manager/dist/src/manager.d.ts +21 -0
  34. package/dist/node_modules/@agentorg/manager/dist/src/manager.js +528 -0
  35. package/dist/node_modules/@agentorg/manager/dist/src/skills.d.ts +25 -0
  36. package/dist/node_modules/@agentorg/manager/dist/src/skills.js +145 -0
  37. package/dist/node_modules/@agentorg/manager/package.json +30 -0
  38. package/dist/node_modules/@agentorg/mcp/dist/src/connection.d.ts +33 -0
  39. package/dist/node_modules/@agentorg/mcp/dist/src/connection.js +290 -0
  40. package/dist/node_modules/@agentorg/mcp/dist/src/index.d.ts +1 -0
  41. package/dist/node_modules/@agentorg/mcp/dist/src/index.js +1 -0
  42. package/dist/node_modules/@agentorg/mcp/dist/src/kinds.d.ts +50 -0
  43. package/dist/node_modules/@agentorg/mcp/dist/src/kinds.js +69 -0
  44. package/dist/node_modules/@agentorg/mcp/dist/src/provider.d.ts +22 -0
  45. package/dist/node_modules/@agentorg/mcp/dist/src/provider.js +167 -0
  46. package/dist/node_modules/@agentorg/mcp/package.json +31 -0
  47. package/dist/node_modules/@agentorg/sdk/dist/src/cli.js +3 -23
  48. package/dist/node_modules/@agentorg/sdk/dist/src/client.d.ts +4 -25
  49. package/dist/node_modules/@agentorg/sdk/dist/src/client.js +5 -55
  50. package/dist/node_modules/@agentorg/sdk/dist/src/errors.d.ts +1 -1
  51. package/dist/node_modules/@agentorg/sdk/dist/src/errors.js +3 -3
  52. package/dist/node_modules/@agentorg/sdk/dist/src/index.d.ts +2 -2
  53. package/dist/node_modules/@agentorg/sdk/dist/src/index.js +1 -1
  54. package/dist/node_modules/@agentorg/sdk/dist/src/interface.d.ts +6 -34
  55. package/dist/node_modules/@agentorg/sdk/dist/src/interface.js +3 -24
  56. package/dist/node_modules/@agentorg/sdk/dist/src/module-host.d.ts +8 -17
  57. package/dist/node_modules/@agentorg/sdk/dist/src/module-host.js +15 -87
  58. package/dist/node_modules/@agentorg/sdk/dist/src/module.d.ts +10 -76
  59. package/dist/node_modules/@agentorg/sdk/dist/src/module.js +3 -23
  60. package/dist/node_modules/@agentorg/sdk/dist/src/person-commands.js +0 -5
  61. package/dist/node_modules/@agentorg/sdk/dist/src/runtime.d.ts +3 -27
  62. package/dist/node_modules/@agentorg/sdk/dist/src/runtime.js +5 -100
  63. package/dist/node_modules/@agentorg/sdk/dist/src/testing.d.ts +7 -8
  64. package/dist/node_modules/@agentorg/sdk/dist/src/testing.js +12 -24
  65. package/dist/node_modules/@agentorg/sdk/package.json +4 -37
  66. package/dist/node_modules/@agentorg/shell/dist/app.css +3435 -739
  67. package/dist/node_modules/@agentorg/shell/dist/app.js +204 -202
  68. package/dist/node_modules/@agentorg/shell/package.json +18 -10
  69. package/dist/node_modules/@agentorg/wire/dist/src/frames.d.ts +2 -3
  70. package/dist/node_modules/@agentorg/wire/dist/src/frames.js +2 -3
  71. package/dist/node_modules/@agentorg/wire/dist/src/ops.d.ts +5 -34
  72. package/dist/node_modules/@agentorg/wire/dist/src/ops.js +2 -17
  73. package/dist/node_modules/assistant/dist/src/agent.d.ts +62 -0
  74. package/dist/node_modules/assistant/dist/src/agent.js +226 -0
  75. package/dist/node_modules/assistant/dist/src/engine.d.ts +23 -0
  76. package/dist/node_modules/assistant/dist/src/engine.js +88 -0
  77. package/dist/node_modules/assistant/dist/src/history.d.ts +97 -0
  78. package/dist/node_modules/assistant/dist/src/history.js +235 -0
  79. package/dist/node_modules/assistant/dist/src/local-store.d.ts +3 -0
  80. package/dist/node_modules/assistant/dist/src/local-store.js +58 -0
  81. package/dist/node_modules/assistant/dist/src/provider.d.ts +21 -0
  82. package/dist/node_modules/assistant/dist/src/provider.js +231 -0
  83. package/dist/node_modules/assistant/dist/src/settings.d.ts +17 -0
  84. package/dist/node_modules/assistant/dist/src/settings.js +43 -0
  85. package/dist/node_modules/assistant/dist/src/tools.d.ts +74 -0
  86. package/dist/node_modules/assistant/dist/src/tools.js +123 -0
  87. package/dist/node_modules/assistant/package.json +29 -0
  88. package/dist/node_modules/chatgpt/dist/src/account.d.ts +52 -0
  89. package/dist/node_modules/chatgpt/dist/src/account.js +270 -0
  90. package/dist/node_modules/chatgpt/dist/src/encoding.d.ts +7 -0
  91. package/dist/node_modules/chatgpt/dist/src/encoding.js +20 -0
  92. package/dist/node_modules/chatgpt/dist/src/file-store.d.ts +9 -0
  93. package/dist/node_modules/chatgpt/dist/src/file-store.js +68 -0
  94. package/dist/node_modules/chatgpt/dist/src/index.d.ts +1 -0
  95. package/dist/node_modules/chatgpt/dist/src/index.js +1 -0
  96. package/dist/node_modules/chatgpt/dist/src/jwt.d.ts +15 -0
  97. package/dist/node_modules/chatgpt/dist/src/jwt.js +37 -0
  98. package/dist/node_modules/chatgpt/dist/src/oauth.d.ts +43 -0
  99. package/dist/node_modules/chatgpt/dist/src/oauth.js +104 -0
  100. package/dist/node_modules/chatgpt/dist/src/program.d.ts +23 -0
  101. package/dist/node_modules/chatgpt/dist/src/program.js +41 -0
  102. package/dist/node_modules/chatgpt/dist/src/responses.d.ts +54 -0
  103. package/dist/node_modules/chatgpt/dist/src/responses.js +300 -0
  104. package/dist/node_modules/chatgpt/dist/src/serve.d.ts +65 -0
  105. package/dist/node_modules/chatgpt/dist/src/serve.js +46 -0
  106. package/dist/node_modules/chatgpt/package.json +33 -0
  107. package/dist/src/api.d.ts +5 -34
  108. package/dist/src/api.js +6 -68
  109. package/dist/src/cli.js +3 -7
  110. package/dist/src/gateway.d.ts +6 -7
  111. package/dist/src/gateway.js +39 -285
  112. package/dist/src/index.d.ts +4 -5
  113. package/dist/src/index.js +3 -4
  114. package/dist/src/notes.d.ts +11 -0
  115. package/dist/src/notes.js +64 -0
  116. package/dist/src/oauth.d.ts +16 -0
  117. package/dist/src/oauth.js +46 -0
  118. package/dist/src/programs.d.ts +29 -0
  119. package/dist/src/programs.js +171 -0
  120. package/package.json +3 -11
  121. package/dist/bundled/index.json +0 -6
  122. package/dist/bundled/sha256-0e91cc3d0e9762b81abc2427b5496b20f383abcd6fb97d928a8d50e956b54d1f.agentorg +0 -0
  123. package/dist/bundled/sha256-1f64ca62a0209d767d6aa6c4feb50b0653d60f10bebbc301f79bd3a37e0153c1.agentorg +0 -0
  124. package/dist/bundled/sha256-4055f8fddf6b90f3d356543f554b2a9e9a2c4a8827a8774f8f87952dc1692331.agentorg +0 -0
  125. package/dist/bundled/sha256-e356ea3c1899138a8494baf521556831006f38534fa9e92ae873e7e6956c3a46.agentorg +0 -0
  126. package/dist/node_modules/@agentorg/hub/dist/src/build.d.ts +0 -17
  127. package/dist/node_modules/@agentorg/hub/dist/src/build.js +0 -120
  128. package/dist/node_modules/@agentorg/hub/dist/src/logs.d.ts +0 -33
  129. package/dist/node_modules/@agentorg/hub/dist/src/logs.js +0 -162
  130. package/dist/node_modules/@agentorg/hub/dist/src/net.d.ts +0 -41
  131. package/dist/node_modules/@agentorg/hub/dist/src/net.js +0 -265
  132. package/dist/node_modules/@agentorg/hub/dist/src/processes.d.ts +0 -78
  133. package/dist/node_modules/@agentorg/hub/dist/src/processes.js +0 -485
  134. package/dist/node_modules/@agentorg/hub/dist/src/storage.d.ts +0 -38
  135. package/dist/node_modules/@agentorg/hub/dist/src/storage.js +0 -194
  136. package/dist/node_modules/@agentorg/interfaces/dist/src/http-egress.d.ts +0 -6
  137. package/dist/node_modules/@agentorg/interfaces/dist/src/http-egress.js +0 -7
  138. package/dist/node_modules/@agentorg/interfaces/dist/src/installer.d.ts +0 -191
  139. package/dist/node_modules/@agentorg/interfaces/dist/src/installer.js +0 -136
  140. package/dist/node_modules/@agentorg/interfaces/dist/src/layout.d.ts +0 -47
  141. package/dist/node_modules/@agentorg/interfaces/dist/src/layout.js +0 -52
  142. package/dist/node_modules/@agentorg/interfaces/dist/src/rules.d.ts +0 -35
  143. package/dist/node_modules/@agentorg/interfaces/dist/src/rules.js +0 -37
  144. package/dist/node_modules/@agentorg/interfaces/dist/src/storage-admin.d.ts +0 -23
  145. package/dist/node_modules/@agentorg/interfaces/dist/src/storage-admin.js +0 -31
  146. package/dist/node_modules/@agentorg/interfaces/dist/src/ui-shell.d.ts +0 -14
  147. package/dist/node_modules/@agentorg/interfaces/dist/src/ui-shell.js +0 -26
  148. package/dist/node_modules/@agentorg/interfaces/dist/src/ui-view.d.ts +0 -27
  149. package/dist/node_modules/@agentorg/interfaces/dist/src/ui-view.js +0 -26
  150. package/dist/node_modules/@agentorg/kit/dist/src/chat.d.ts +0 -37
  151. package/dist/node_modules/@agentorg/kit/dist/src/chat.js +0 -131
  152. package/dist/node_modules/@agentorg/kit/dist/src/components.d.ts +0 -94
  153. package/dist/node_modules/@agentorg/kit/dist/src/components.js +0 -66
  154. package/dist/node_modules/@agentorg/kit/dist/src/icons.d.ts +0 -17
  155. package/dist/node_modules/@agentorg/kit/dist/src/icons.js +0 -30
  156. package/dist/node_modules/@agentorg/kit/dist/src/index.d.ts +0 -6
  157. package/dist/node_modules/@agentorg/kit/dist/src/index.js +0 -10
  158. package/dist/node_modules/@agentorg/kit/dist/src/markdown.d.ts +0 -9
  159. package/dist/node_modules/@agentorg/kit/dist/src/markdown.js +0 -14
  160. package/dist/node_modules/@agentorg/kit/dist/src/resizable.d.ts +0 -5
  161. package/dist/node_modules/@agentorg/kit/dist/src/resizable.js +0 -8
  162. package/dist/node_modules/@agentorg/kit/dist/src/styles.d.ts +0 -11
  163. package/dist/node_modules/@agentorg/kit/dist/src/styles.js +0 -166
  164. package/dist/node_modules/@agentorg/kit/package.json +0 -44
  165. package/dist/node_modules/@agentorg/sdk/dist/frame/runtime.js +0 -753
  166. package/dist/node_modules/@agentorg/sdk/dist/host/runner.js +0 -21963
  167. package/dist/node_modules/@agentorg/sdk/dist/src/build.d.ts +0 -2
  168. package/dist/node_modules/@agentorg/sdk/dist/src/build.js +0 -2
  169. package/dist/node_modules/@agentorg/sdk/dist/src/client-http.d.ts +0 -24
  170. package/dist/node_modules/@agentorg/sdk/dist/src/client-http.js +0 -247
  171. package/dist/node_modules/@agentorg/sdk/dist/src/describe.d.ts +0 -13
  172. package/dist/node_modules/@agentorg/sdk/dist/src/describe.js +0 -16
  173. package/dist/node_modules/@agentorg/sdk/dist/src/frame-base.d.ts +0 -8
  174. package/dist/node_modules/@agentorg/sdk/dist/src/frame-base.js +0 -64
  175. package/dist/node_modules/@agentorg/sdk/dist/src/frame-entry.d.ts +0 -1
  176. package/dist/node_modules/@agentorg/sdk/dist/src/frame-entry.js +0 -35
  177. package/dist/node_modules/@agentorg/sdk/dist/src/frame-host.d.ts +0 -57
  178. package/dist/node_modules/@agentorg/sdk/dist/src/frame-host.js +0 -293
  179. package/dist/node_modules/@agentorg/sdk/dist/src/frame-protocol.d.ts +0 -124
  180. package/dist/node_modules/@agentorg/sdk/dist/src/frame-protocol.js +0 -16
  181. package/dist/node_modules/@agentorg/sdk/dist/src/frame.d.ts +0 -25
  182. package/dist/node_modules/@agentorg/sdk/dist/src/frame.js +0 -248
  183. package/dist/node_modules/@agentorg/sdk/dist/src/host-main.d.ts +0 -1
  184. package/dist/node_modules/@agentorg/sdk/dist/src/host-main.js +0 -60
  185. package/dist/node_modules/@agentorg/sdk/dist/src/host.d.ts +0 -25
  186. package/dist/node_modules/@agentorg/sdk/dist/src/host.js +0 -92
  187. package/dist/node_modules/@agentorg/sdk/dist/src/manifest-api.d.ts +0 -2
  188. package/dist/node_modules/@agentorg/sdk/dist/src/manifest-api.js +0 -2
  189. package/dist/node_modules/@agentorg/sdk/dist/src/manifest.d.ts +0 -56
  190. package/dist/node_modules/@agentorg/sdk/dist/src/manifest.js +0 -165
  191. package/dist/node_modules/@agentorg/sdk/dist/src/package.d.ts +0 -60
  192. package/dist/node_modules/@agentorg/sdk/dist/src/package.js +0 -538
  193. package/dist/node_modules/@agentorg/sdk/dist/src/tar.d.ts +0 -7
  194. package/dist/node_modules/@agentorg/sdk/dist/src/tar.js +0 -71
  195. package/dist/node_modules/@agentorg/shell/dist/agent-bindings.js +0 -59
  196. package/dist/node_modules/@agentorg/shell/src/agent-bindings.ts +0 -107
  197. package/dist/src/frames.d.ts +0 -23
  198. package/dist/src/frames.js +0 -78
  199. package/dist/src/layout.d.ts +0 -44
  200. package/dist/src/layout.js +0 -90
  201. package/dist/src/model.d.ts +0 -54
  202. package/dist/src/model.js +0 -299
  203. package/dist/src/rules.d.ts +0 -71
  204. package/dist/src/rules.js +0 -157
  205. package/dist/src/transfer.d.ts +0 -30
  206. package/dist/src/transfer.js +0 -110
@@ -0,0 +1,145 @@
1
+ import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync, } from "node:fs";
2
+ import { basename, dirname, join, relative, sep } from "node:path";
3
+ import { SKILL_FILE_MAX, SkillEntry, SkillName, SkillPath } from "@agentorg/interfaces";
4
+ import { Refused } from "@agentorg/sdk";
5
+ import { parse } from "yaml";
6
+ const MANIFEST = "SKILL.md";
7
+ const MAX_FILES = 256;
8
+ const FRONT_MATTER = /^---\r?\n([\s\S]*?)\r?\n---[ \t]*(?:\r?\n|$)/;
9
+ const utf8 = new TextDecoder("utf-8", { fatal: true });
10
+ /** What a `SKILL.md` says of itself, from its front matter, or refused. */
11
+ function entryOf(text) {
12
+ const matter = FRONT_MATTER.exec(text)?.[1];
13
+ let fields;
14
+ try {
15
+ fields = matter === undefined ? undefined : parse(matter);
16
+ }
17
+ catch {
18
+ fields = undefined;
19
+ }
20
+ const entry = SkillEntry.safeParse(fields && typeof fields === "object"
21
+ ? {
22
+ name: fields.name,
23
+ description: fields.description,
24
+ }
25
+ : undefined);
26
+ if (!entry.success || entry.data.description.trim() === "")
27
+ throw new Refused("invalid", `${MANIFEST} needs front matter with a name (lowercase words joined by hyphens) and a description.`);
28
+ return entry.data;
29
+ }
30
+ /** Every file under `root`, by its path inside it; a link is refused, since it could leave it. */
31
+ function walk(root, each) {
32
+ for (const found of readdirSync(root, { withFileTypes: true, recursive: true })) {
33
+ if (found.isDirectory())
34
+ continue;
35
+ const file = join(found.parentPath, found.name);
36
+ if (!found.isFile())
37
+ throw new Refused("invalid", `${relative(root, file)} isn't a plain file.`);
38
+ each(file, relative(root, file).split(sep).join("/"));
39
+ }
40
+ }
41
+ /** A skill's folder on this machine, as files; each must be text within a skill's limits. */
42
+ export function readSkillFolder(folder) {
43
+ const files = {};
44
+ try {
45
+ if (!statSync(folder).isDirectory())
46
+ throw new Error("not a folder");
47
+ }
48
+ catch {
49
+ throw new Refused("invalid", `${folder} isn't a folder here.`);
50
+ }
51
+ walk(folder, (file, path) => {
52
+ if (basename(path) === ".DS_Store")
53
+ return;
54
+ if (Object.keys(files).length >= MAX_FILES)
55
+ throw new Refused("invalid", `A skill holds at most ${MAX_FILES} files.`);
56
+ if (!SkillPath.safeParse(path).success)
57
+ throw new Refused("invalid", `${path} isn't a name a skill's file can have.`);
58
+ const bytes = readFileSync(file);
59
+ if (bytes.length > SKILL_FILE_MAX)
60
+ throw new Refused("invalid", `${path} is over ${SKILL_FILE_MAX} bytes.`);
61
+ try {
62
+ files[path] = utf8.decode(bytes);
63
+ }
64
+ catch {
65
+ throw new Refused("invalid", `${path} isn't text.`);
66
+ }
67
+ });
68
+ return files;
69
+ }
70
+ /** The skills, each a `SKILL.md` folder under `dir`. What each says of itself is read from it. */
71
+ export function createSkills(dir) {
72
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
73
+ const folderOf = (name) => join(dir, name);
74
+ const read = (name, path = MANIFEST) => {
75
+ try {
76
+ return readFileSync(join(folderOf(name), path), "utf8");
77
+ }
78
+ catch {
79
+ return undefined;
80
+ }
81
+ };
82
+ const entry = (name) => {
83
+ const text = read(name);
84
+ return text === undefined ? undefined : entryOf(text);
85
+ };
86
+ return {
87
+ has: (name) => read(name) !== undefined,
88
+ entry,
89
+ read,
90
+ list() {
91
+ return readdirSync(dir, { withFileTypes: true })
92
+ .filter((found) => found.isDirectory() && SkillName.safeParse(found.name).success)
93
+ .map((found) => entry(found.name))
94
+ .filter((found) => found !== undefined)
95
+ .sort((a, b) => a.name.localeCompare(b.name));
96
+ },
97
+ paths(name) {
98
+ const paths = [];
99
+ walk(folderOf(name), (_, path) => paths.push(path));
100
+ return paths.sort();
101
+ },
102
+ /**
103
+ * Add a skill, or replace the one of its name, whole: it is never seen half written. With
104
+ * `expected`, a skill that calls itself anything else is refused before anything is touched.
105
+ */
106
+ add(files, expected) {
107
+ const manifest = files[MANIFEST];
108
+ if (manifest === undefined)
109
+ throw new Refused("invalid", `A skill needs a ${MANIFEST}.`);
110
+ const found = entryOf(manifest);
111
+ if (expected !== undefined && found.name !== expected)
112
+ throw new Refused("invalid", `The skill ${expected} names itself ${found.name}.`);
113
+ // Named so `list` passes it by: a skill's name can't start with a dot.
114
+ const adding = join(dir, `.adding-${crypto.randomUUID()}`);
115
+ try {
116
+ for (const [path, text] of Object.entries(files)) {
117
+ const file = join(adding, path);
118
+ mkdirSync(dirname(file), { recursive: true, mode: 0o700 });
119
+ writeFileSync(file, text, { mode: 0o600 });
120
+ }
121
+ const final = folderOf(found.name);
122
+ const aside = join(dir, `.replaced-${crypto.randomUUID()}`);
123
+ const replacing = existsSync(final);
124
+ if (replacing)
125
+ renameSync(final, aside);
126
+ try {
127
+ renameSync(adding, final);
128
+ }
129
+ catch (error) {
130
+ if (replacing)
131
+ renameSync(aside, final);
132
+ throw error;
133
+ }
134
+ rmSync(aside, { recursive: true, force: true });
135
+ }
136
+ finally {
137
+ rmSync(adding, { recursive: true, force: true });
138
+ }
139
+ return found;
140
+ },
141
+ remove(name) {
142
+ rmSync(folderOf(name), { recursive: true, force: true });
143
+ },
144
+ };
145
+ }
@@ -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,33 @@
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
+ constructor(spec: Spec, secrets: Secrets, log: Log, timing?: Timing);
15
+ /** Join the Hub as the connection's Actor, offering its tools. */
16
+ join(hub: {
17
+ hubUrl: string;
18
+ actorId: string;
19
+ credential: string;
20
+ }): Promise<void>;
21
+ /** Keep the server connected, from now until the connection ends. */
22
+ run(): void;
23
+ status(): {
24
+ state: "connected" | "connecting" | "down";
25
+ detail?: string | undefined;
26
+ tools: {
27
+ name: string;
28
+ description?: string | undefined;
29
+ }[];
30
+ };
31
+ /** End it: the server is let go and the Actor leaves the Hub. */
32
+ end(): Promise<void>;
33
+ }
@@ -0,0 +1,290 @@
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
+ /** How often a connection asks its server whether it is there, and how long it waits. */
7
+ const PING_EVERY_MS = 30_000;
8
+ const PING_TIMEOUT_MS = 10_000;
9
+ const FIRST_DELAY_MS = 1_000;
10
+ const MAX_DELAY_MS = 60_000;
11
+ /** A server up this long is well again: the next failure starts over from the first delay. */
12
+ const STEADY_MS = 10 * 60_000;
13
+ /** What `tools@1` carries: its limits, and room in one frame for a list. */
14
+ const NAME_MAX = 128;
15
+ const DESCRIPTION_MAX = 16_384;
16
+ const STATUS_DESCRIPTION_MAX = 512;
17
+ const OUTPUT_MAX = 200_000;
18
+ const LIST_ROOM = 900 * 1024;
19
+ const cut = (text, max) => text.length <= max ? text : `${text.slice(0, max - 40)}… [cut: ${text.length} characters]`;
20
+ const messageOf = (error) => (error instanceof Error ? error.message : String(error));
21
+ /** The tools a server lists, fitted to what `tools@1` can carry; what can't be is logged. */
22
+ function fit(listed, log) {
23
+ const kept = [];
24
+ let room = LIST_ROOM;
25
+ for (const tool of listed) {
26
+ const entry = {
27
+ name: tool.name,
28
+ ...(tool.description ? { description: cut(tool.description, DESCRIPTION_MAX) } : {}),
29
+ inputSchema: tool.inputSchema,
30
+ };
31
+ const size = Buffer.byteLength(JSON.stringify(entry));
32
+ if (tool.name.length < 1 || tool.name.length > NAME_MAX || size > room) {
33
+ log.warn(`Left out the tool ${tool.name.slice(0, NAME_MAX)}: it doesn't fit tools@1.`);
34
+ continue;
35
+ }
36
+ room -= size;
37
+ kept.push(entry);
38
+ }
39
+ return kept;
40
+ }
41
+ /** A tool's result as text: its text blocks as they are, and what else it held by name. */
42
+ function textOf(result) {
43
+ const parts = (result.content ?? []).map((block) => {
44
+ switch (block.type) {
45
+ case "text":
46
+ return block.text;
47
+ case "resource":
48
+ return "text" in block.resource ? block.resource.text : `[resource ${block.resource.uri}]`;
49
+ case "resource_link":
50
+ return `[resource ${block.uri}]`;
51
+ default:
52
+ return `[${block.type}]`;
53
+ }
54
+ });
55
+ if (parts.length === 0 && result.structuredContent)
56
+ return JSON.stringify(result.structuredContent);
57
+ return parts.join("\n");
58
+ }
59
+ function transportOf(spec, secrets, log) {
60
+ if (spec.kind === "url") {
61
+ const { token } = secrets;
62
+ return new StreamableHTTPClientTransport(new URL(spec.url), {
63
+ ...(token ? { requestInit: { headers: { Authorization: `Bearer ${token}` } } } : {}),
64
+ });
65
+ }
66
+ const transport = new StdioClientTransport({
67
+ command: spec.command,
68
+ args: spec.args ?? [],
69
+ env: { ...getDefaultEnvironment(), ...secrets },
70
+ stderr: "pipe",
71
+ ...(spec.cwd ? { cwd: spec.cwd } : {}),
72
+ });
73
+ // By whole lines, so a secret the server prints can't be split past the log's scrubbing.
74
+ let line = "";
75
+ transport.stderr?.on("data", (chunk) => {
76
+ const parts = (line + String(chunk)).split("\n");
77
+ line = (parts.pop() ?? "").slice(-65_536);
78
+ for (const part of parts)
79
+ log.warn(part);
80
+ });
81
+ return transport;
82
+ }
83
+ export class Connection {
84
+ #state = "connecting";
85
+ #detail;
86
+ #tools = [];
87
+ #mcp;
88
+ #hub;
89
+ #ended = false;
90
+ #wake;
91
+ /** Ends the current session at once, whatever its transport is still waiting for. */
92
+ #lose;
93
+ #running;
94
+ #spec;
95
+ #secrets;
96
+ #log;
97
+ #scrub;
98
+ #pingEveryMs;
99
+ #firstDelayMs;
100
+ constructor(spec, secrets, log, timing = {}) {
101
+ this.#spec = spec;
102
+ this.#secrets = secrets;
103
+ this.#pingEveryMs = timing.pingEveryMs ?? PING_EVERY_MS;
104
+ this.#firstDelayMs = timing.firstDelayMs ?? FIRST_DELAY_MS;
105
+ // What is secret never leaves in a log, a detail or an error: its values, and an address's query.
106
+ const query = spec.kind === "url" ? new URL(spec.url).search : "";
107
+ // A value that spans lines is also hidden line by line, as a server prints it; longest first.
108
+ const hidden = [
109
+ ...Object.values(secrets).flatMap((value) => [
110
+ value,
111
+ ...value.split(/\r?\n/).filter((line) => line.length > 0),
112
+ ]),
113
+ ...(query.length > 1 ? [query] : []),
114
+ ].sort((a, b) => b.length - a.length);
115
+ this.#scrub = (text) => hidden.reduce((out, value) => out.replaceAll(value, "[hidden]"), text);
116
+ const clean = (message) => cut(this.#scrub(message), 4000);
117
+ this.#log = {
118
+ info: (message, fields) => log.info(clean(message), fields),
119
+ warn: (message, fields) => log.warn(clean(message), fields),
120
+ error: (message, fields) => log.error(clean(message), fields),
121
+ };
122
+ }
123
+ /** Join the Hub as the connection's Actor, offering its tools. */
124
+ async join(hub) {
125
+ this.#hub = await connect({
126
+ ...hub,
127
+ exports: { tools },
128
+ log: this.#log,
129
+ start: (ctx) => {
130
+ ctx.exports.tools.implement({
131
+ list: () => {
132
+ this.#requireUp();
133
+ return { tools: this.#tools };
134
+ },
135
+ call: ({ name, arguments: args }) => this.#call(name, args),
136
+ });
137
+ },
138
+ });
139
+ }
140
+ /** Keep the server connected, from now until the connection ends. */
141
+ run() {
142
+ this.#running = this.#keepUp();
143
+ }
144
+ status() {
145
+ return {
146
+ state: this.#state,
147
+ ...(this.#detail ? { detail: this.#detail } : {}),
148
+ tools: this.#tools.map((tool) => ({
149
+ name: tool.name,
150
+ ...(tool.description ? { description: cut(tool.description, STATUS_DESCRIPTION_MAX) } : {}),
151
+ })),
152
+ };
153
+ }
154
+ /** End it: the server is let go and the Actor leaves the Hub. */
155
+ async end() {
156
+ this.#ended = true;
157
+ this.#wake?.();
158
+ this.#lose?.();
159
+ await this.#mcp?.close().catch(() => { });
160
+ await this.#running;
161
+ this.#hub?.close();
162
+ }
163
+ #requireUp() {
164
+ if (this.#state !== "connected")
165
+ throw new Refused("not_connected", this.#detail ?? "The server isn't connected yet.");
166
+ }
167
+ async #call(name, args) {
168
+ this.#requireUp();
169
+ if (!this.#tools.some((tool) => tool.name === name))
170
+ throw new Refused("unknown", `This connection has no tool named ${name}.`);
171
+ const mcp = this.#mcp;
172
+ try {
173
+ const result = await mcp.callTool({ name, arguments: args });
174
+ return {
175
+ output: cut(textOf(result), OUTPUT_MAX),
176
+ ...(result.isError ? { failed: true } : {}),
177
+ };
178
+ }
179
+ catch (error) {
180
+ if (this.#gone(error)) {
181
+ this.#lose?.();
182
+ throw new Refused("not_connected", `The server went away during ${name}.`);
183
+ }
184
+ return { output: cut(this.#scrub(messageOf(error)), 2000), failed: true };
185
+ }
186
+ }
187
+ /** Whether an error says the server can't be reached, rather than that one request failed. */
188
+ #gone(error) {
189
+ if (error instanceof TypeError)
190
+ return true;
191
+ return (error instanceof SdkError &&
192
+ (error.code === SdkErrorCode.ConnectionClosed || error.code === SdkErrorCode.NotConnected));
193
+ }
194
+ #set(state, detail) {
195
+ const changed = state !== this.#state && (state === "connected" || this.#state === "connected");
196
+ this.#state = state;
197
+ this.#detail = detail === undefined ? undefined : cut(this.#scrub(detail), 2000);
198
+ if (state !== "connected")
199
+ this.#tools = [];
200
+ if (changed)
201
+ this.#changed();
202
+ }
203
+ #changed() {
204
+ this.#hub?.exports.tools.emit("changed", {});
205
+ }
206
+ async #keepUp() {
207
+ let delay = this.#firstDelayMs;
208
+ while (!this.#ended) {
209
+ const began = Date.now();
210
+ const why = await this.#session();
211
+ if (this.#ended)
212
+ return;
213
+ this.#set("down", why);
214
+ if (Date.now() - began >= STEADY_MS)
215
+ delay = this.#firstDelayMs;
216
+ await new Promise((resolve) => {
217
+ const timer = setTimeout(resolve, delay);
218
+ this.#wake = () => {
219
+ clearTimeout(timer);
220
+ resolve();
221
+ };
222
+ });
223
+ delay = Math.min(delay * 2, MAX_DELAY_MS);
224
+ }
225
+ }
226
+ /** One connection to the server, for as long as it lasts; it resolves with why it ended. */
227
+ async #session() {
228
+ const log = this.#log;
229
+ const mcp = new Client({ name: "agentorg", version: "0" }, {
230
+ listChanged: {
231
+ tools: {
232
+ autoRefresh: false,
233
+ onChanged: () => {
234
+ this.#refresh(mcp).then(() => this.#changed(), (error) => log.warn(`Listing the tools again didn't work: ${messageOf(error)}`));
235
+ },
236
+ },
237
+ },
238
+ });
239
+ this.#mcp = mcp;
240
+ let over = false;
241
+ const closed = new Promise((resolve) => {
242
+ const done = () => {
243
+ over = true;
244
+ resolve();
245
+ };
246
+ mcp.onclose = done;
247
+ this.#lose = done;
248
+ });
249
+ let pinging;
250
+ try {
251
+ // A failed start closes before it rejects: what it rejects with is the reason to give.
252
+ for (const step of [
253
+ () => mcp.connect(transportOf(this.#spec, this.#secrets, log)),
254
+ () => this.#refresh(mcp),
255
+ ]) {
256
+ const going = step();
257
+ await Promise.race([going, closed]);
258
+ if (this.#ended)
259
+ return "";
260
+ if (over) {
261
+ await going;
262
+ return "The connection to the server ended.";
263
+ }
264
+ }
265
+ this.#set("connected");
266
+ // An address's transport says nothing when its server dies: asking is how that's noticed.
267
+ pinging = setInterval(() => {
268
+ mcp.ping({ timeout: PING_TIMEOUT_MS }).catch((error) => {
269
+ if (!(error instanceof ProtocolError))
270
+ this.#lose?.();
271
+ });
272
+ }, this.#pingEveryMs);
273
+ await closed;
274
+ return "The connection to the server ended.";
275
+ }
276
+ catch (error) {
277
+ return messageOf(error);
278
+ }
279
+ finally {
280
+ clearInterval(pinging);
281
+ this.#mcp = undefined;
282
+ this.#lose = undefined;
283
+ await mcp.close().catch(() => { });
284
+ }
285
+ }
286
+ async #refresh(mcp) {
287
+ const { tools: listed } = await mcp.listTools();
288
+ this.#tools = fit(listed, this.#log);
289
+ }
290
+ }
@@ -0,0 +1 @@
1
+ export { type McpProvider, type McpProviderOptions, startMcpProvider } from "./provider.js";
@@ -0,0 +1 @@
1
+ export { startMcpProvider } from "./provider.js";
@@ -0,0 +1,50 @@
1
+ import { z } from "zod";
2
+ declare const UrlParams: z.ZodObject<{
3
+ url: z.ZodURL;
4
+ }, z.core.$strict>;
5
+ declare const CommandParams: z.ZodObject<{
6
+ command: z.ZodString;
7
+ args: z.ZodOptional<z.ZodArray<z.ZodString>>;
8
+ cwd: z.ZodOptional<z.ZodString>;
9
+ }, z.core.$strict>;
10
+ export type Spec = ({
11
+ kind: "url";
12
+ } & z.infer<typeof UrlParams>) | ({
13
+ kind: "command";
14
+ } & z.infer<typeof CommandParams>);
15
+ export type Secrets = Record<string, string>;
16
+ export declare const KINDS: readonly [{
17
+ readonly kind: "url";
18
+ readonly title: "A server at an address";
19
+ readonly params: z.ZodObject<{
20
+ url: z.ZodURL;
21
+ }, z.core.$strict>;
22
+ readonly secrets: z.ZodObject<{
23
+ token: z.ZodOptional<z.ZodString>;
24
+ }, z.core.$strict>;
25
+ }, {
26
+ readonly kind: "command";
27
+ readonly title: "A local server this machine starts";
28
+ readonly params: z.ZodObject<{
29
+ command: z.ZodString;
30
+ args: z.ZodOptional<z.ZodArray<z.ZodString>>;
31
+ cwd: z.ZodOptional<z.ZodString>;
32
+ }, z.core.$strict>;
33
+ readonly secrets: z.ZodRecord<z.ZodString, z.ZodString>;
34
+ }];
35
+ /** What a connection's parameters and secrets say, or why they don't fit its kind. */
36
+ export declare function parseConnection(kind: string, params: unknown, secrets: unknown): {
37
+ spec: Spec;
38
+ secrets: Secrets;
39
+ why?: undefined;
40
+ } | {
41
+ spec?: undefined;
42
+ secrets?: undefined;
43
+ why: string;
44
+ };
45
+ /**
46
+ * What a connection attaches to or runs, for people to read. An address loses its query, which is
47
+ * where a secret would be.
48
+ */
49
+ export declare function targetOf(spec: Spec): string;
50
+ export {};
@@ -0,0 +1,69 @@
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
+ const { username, password } = new URL(url);
13
+ return !username && !password;
14
+ }, "An address can't hold a user or a password: give a token as a secret.")
15
+ .meta({ title: "Address" }),
16
+ });
17
+ /** The bearer token sent to the server on every request. */
18
+ const UrlSecrets = z.strictObject({ token: SecretValue.optional().meta({ title: "Token" }) });
19
+ const CommandParams = z.strictObject({
20
+ command: z.string().min(1).max(4096).meta({ title: "Command" }),
21
+ args: z.array(z.string().max(4096)).max(256).optional().meta({ title: "Arguments" }),
22
+ cwd: z.string().min(1).max(4096).optional().meta({ title: "Working folder" }),
23
+ });
24
+ /** Each one is an environment variable of the server, by its name. */
25
+ const CommandSecrets = z.record(EnvName, SecretValue);
26
+ export const KINDS = [
27
+ { kind: "url", title: "A server at an address", params: UrlParams, secrets: UrlSecrets },
28
+ {
29
+ kind: "command",
30
+ title: "A local server this machine starts",
31
+ params: CommandParams,
32
+ secrets: CommandSecrets,
33
+ },
34
+ ];
35
+ const LOOPBACK = new Set(["127.0.0.1", "localhost", "[::1]"]);
36
+ /** What a connection's parameters and secrets say, or why they don't fit its kind. */
37
+ export function parseConnection(kind, params, secrets) {
38
+ const found = KINDS.find((k) => k.kind === kind);
39
+ if (!found)
40
+ return { why: `No kind is named ${kind}: this provider offers url and command.` };
41
+ const parsed = found.params.safeParse(params);
42
+ if (!parsed.success)
43
+ return { why: `${kind}: ${z.prettifyError(parsed.error)}` };
44
+ const hidden = found.secrets.safeParse(secrets ?? {});
45
+ // Named by what's wrong with their shape only: a refusal never repeats a value.
46
+ if (!hidden.success)
47
+ return { why: `${kind}: its secrets don't fit: ${found.title}.` };
48
+ const spec = { kind, ...parsed.data };
49
+ if (spec.kind === "url" && "token" in hidden.data) {
50
+ const url = new URL(spec.url);
51
+ if (url.protocol === "http:" && !LOOPBACK.has(url.hostname))
52
+ return { why: "A token is sent only over https, or to this machine." };
53
+ }
54
+ return { spec, secrets: hidden.data };
55
+ }
56
+ /**
57
+ * What a connection attaches to or runs, for people to read. An address loses its query, which is
58
+ * where a secret would be.
59
+ */
60
+ export function targetOf(spec) {
61
+ if (spec.kind === "url") {
62
+ const url = new URL(spec.url);
63
+ url.search = "";
64
+ url.hash = "";
65
+ return url.href.slice(0, 4096);
66
+ }
67
+ const line = [spec.command, ...(spec.args ?? [])].join(" ");
68
+ return (spec.cwd ? `${line} (in ${spec.cwd})` : line).slice(0, 4096);
69
+ }
@@ -0,0 +1,22 @@
1
+ import { type Log } from "@agentorg/sdk";
2
+ import { type Timing } from "./connection.js";
3
+ export interface McpProviderOptions {
4
+ hubUrl: string;
5
+ /** The provider's own Actor, bound to `hub.actors@1` at its slot `actors`. */
6
+ actorId: string;
7
+ credential: string;
8
+ /** A private folder of the provider's, which holds each connection's Hub credential. */
9
+ dir: string;
10
+ log?: Log;
11
+ /** How often a server is checked, and the first wait before trying one again. For tests. */
12
+ timing?: Timing;
13
+ }
14
+ export interface McpProvider {
15
+ /** Leave the Hub and let every server go. The connections stay, and resume at the next start. */
16
+ close(): Promise<void>;
17
+ }
18
+ /**
19
+ * Run the built-in MCP provider as an Actor exporting `mcp.provider@1` as `provider`. It offers two
20
+ * kinds, `url` and `command`; a server it starts runs with this process's rights. Connections made earlier are joined again at the start.
21
+ */
22
+ export declare function startMcpProvider(options: McpProviderOptions): Promise<McpProvider>;