orbitx 0.2.9 → 0.3.2

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 (213) hide show
  1. package/Readme.md +478 -456
  2. package/dist/agents/backend.d.ts +4 -0
  3. package/dist/agents/backend.d.ts.map +1 -0
  4. package/dist/agents/backend.js +54 -0
  5. package/dist/agents/backend.js.map +1 -0
  6. package/dist/agents/frontend.d.ts +4 -0
  7. package/dist/agents/frontend.d.ts.map +1 -0
  8. package/dist/agents/frontend.js +50 -0
  9. package/dist/agents/frontend.js.map +1 -0
  10. package/dist/agents/index.d.ts +10 -0
  11. package/dist/agents/index.d.ts.map +1 -0
  12. package/dist/agents/index.js +22 -0
  13. package/dist/agents/index.js.map +1 -0
  14. package/dist/agents/planner.d.ts +4 -0
  15. package/dist/agents/planner.d.ts.map +1 -0
  16. package/dist/agents/planner.js +86 -0
  17. package/dist/agents/planner.js.map +1 -0
  18. package/dist/agents/protocol.d.ts +5 -0
  19. package/dist/agents/protocol.d.ts.map +1 -0
  20. package/dist/agents/protocol.js +70 -0
  21. package/dist/agents/protocol.js.map +1 -0
  22. package/dist/agents/reasoner.d.ts +5 -0
  23. package/dist/agents/reasoner.d.ts.map +1 -0
  24. package/dist/agents/reasoner.js +96 -0
  25. package/dist/agents/reasoner.js.map +1 -0
  26. package/dist/agents/research.d.ts +4 -0
  27. package/dist/agents/research.d.ts.map +1 -0
  28. package/dist/agents/research.js +28 -0
  29. package/dist/agents/research.js.map +1 -0
  30. package/dist/agents/tester.d.ts +4 -0
  31. package/dist/agents/tester.d.ts.map +1 -0
  32. package/dist/agents/tester.js +70 -0
  33. package/dist/agents/tester.js.map +1 -0
  34. package/dist/core/agent-definition.d.ts +61 -0
  35. package/dist/core/agent-definition.d.ts.map +1 -0
  36. package/dist/core/agent-definition.js +82 -0
  37. package/dist/core/agent-definition.js.map +1 -0
  38. package/dist/core/ai-ask.d.ts +28 -0
  39. package/dist/core/ai-ask.d.ts.map +1 -0
  40. package/dist/core/ai-ask.js +80 -0
  41. package/dist/core/ai-ask.js.map +1 -0
  42. package/dist/core/ai-provider.d.ts +3 -0
  43. package/dist/core/ai-provider.d.ts.map +1 -1
  44. package/dist/core/ai-provider.js.map +1 -1
  45. package/dist/core/anthropic-provider.d.ts +1 -0
  46. package/dist/core/anthropic-provider.d.ts.map +1 -1
  47. package/dist/core/anthropic-provider.js +3 -0
  48. package/dist/core/anthropic-provider.js.map +1 -1
  49. package/dist/core/base-agent.d.ts +51 -28
  50. package/dist/core/base-agent.d.ts.map +1 -1
  51. package/dist/core/base-agent.js +118 -26
  52. package/dist/core/base-agent.js.map +1 -1
  53. package/dist/core/deepseek-provider.d.ts +1 -0
  54. package/dist/core/deepseek-provider.d.ts.map +1 -1
  55. package/dist/core/deepseek-provider.js +3 -0
  56. package/dist/core/deepseek-provider.js.map +1 -1
  57. package/dist/core/mcp-auto-execution-policy.d.ts +22 -0
  58. package/dist/core/mcp-auto-execution-policy.d.ts.map +1 -0
  59. package/dist/core/mcp-auto-execution-policy.js +85 -0
  60. package/dist/core/mcp-auto-execution-policy.js.map +1 -0
  61. package/dist/core/mcp-computer.d.ts +14 -1
  62. package/dist/core/mcp-computer.d.ts.map +1 -1
  63. package/dist/core/mcp-computer.js +352 -71
  64. package/dist/core/mcp-computer.js.map +1 -1
  65. package/dist/core/ollama-provider.d.ts +1 -0
  66. package/dist/core/ollama-provider.d.ts.map +1 -1
  67. package/dist/core/ollama-provider.js +3 -0
  68. package/dist/core/ollama-provider.js.map +1 -1
  69. package/dist/core/openai-provider.d.ts +1 -0
  70. package/dist/core/openai-provider.d.ts.map +1 -1
  71. package/dist/core/openai-provider.js +3 -0
  72. package/dist/core/openai-provider.js.map +1 -1
  73. package/dist/core/stateless-agent.d.ts +30 -0
  74. package/dist/core/stateless-agent.d.ts.map +1 -0
  75. package/dist/core/stateless-agent.js +79 -0
  76. package/dist/core/stateless-agent.js.map +1 -0
  77. package/dist/core/swarm-base.d.ts +88 -0
  78. package/dist/core/swarm-base.d.ts.map +1 -0
  79. package/dist/core/swarm-base.js +427 -0
  80. package/dist/core/swarm-base.js.map +1 -0
  81. package/dist/index.d.ts +13 -5
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +7 -3
  84. package/dist/index.js.map +1 -1
  85. package/dist/tests/agents/default-agents.test.d.ts +2 -0
  86. package/dist/tests/agents/default-agents.test.d.ts.map +1 -0
  87. package/dist/tests/agents/default-agents.test.js +106 -0
  88. package/dist/tests/agents/default-agents.test.js.map +1 -0
  89. package/dist/tests/core/agent-definition.test.d.ts +2 -0
  90. package/dist/tests/core/agent-definition.test.d.ts.map +1 -0
  91. package/dist/tests/core/agent-definition.test.js +99 -0
  92. package/dist/tests/core/agent-definition.test.js.map +1 -0
  93. package/dist/tests/core/ai-ask.test.d.ts +2 -0
  94. package/dist/tests/core/ai-ask.test.d.ts.map +1 -0
  95. package/dist/tests/core/ai-ask.test.js +101 -0
  96. package/dist/tests/core/ai-ask.test.js.map +1 -0
  97. package/dist/tests/core/mcp-auto-execution-policy.test.d.ts +2 -0
  98. package/dist/tests/core/mcp-auto-execution-policy.test.d.ts.map +1 -0
  99. package/dist/tests/core/mcp-auto-execution-policy.test.js +107 -0
  100. package/dist/tests/core/mcp-auto-execution-policy.test.js.map +1 -0
  101. package/dist/tests/core/scripted-provider.d.ts +38 -0
  102. package/dist/tests/core/scripted-provider.d.ts.map +1 -0
  103. package/dist/tests/core/scripted-provider.js +85 -0
  104. package/dist/tests/core/scripted-provider.js.map +1 -0
  105. package/dist/tests/core/stateless-agent.test.d.ts +2 -0
  106. package/dist/tests/core/stateless-agent.test.d.ts.map +1 -0
  107. package/dist/tests/core/stateless-agent.test.js +73 -0
  108. package/dist/tests/core/stateless-agent.test.js.map +1 -0
  109. package/dist/tests/core/swarm-base.test.d.ts +2 -0
  110. package/dist/tests/core/swarm-base.test.d.ts.map +1 -0
  111. package/dist/tests/core/swarm-base.test.js +387 -0
  112. package/dist/tests/core/swarm-base.test.js.map +1 -0
  113. package/dist/tests/index.d.ts +6 -0
  114. package/dist/tests/index.d.ts.map +1 -1
  115. package/dist/tests/index.js +6 -0
  116. package/dist/tests/index.js.map +1 -1
  117. package/dist/tests/tools/agent/agent-tools.test.js +225 -153
  118. package/dist/tests/tools/agent/agent-tools.test.js.map +1 -1
  119. package/dist/tools/agent/active.d.ts +5 -0
  120. package/dist/tools/agent/active.d.ts.map +1 -0
  121. package/dist/tools/agent/active.js +40 -0
  122. package/dist/tools/agent/active.js.map +1 -0
  123. package/dist/tools/agent/fire.d.ts +5 -0
  124. package/dist/tools/agent/fire.d.ts.map +1 -0
  125. package/dist/tools/agent/fire.js +38 -0
  126. package/dist/tools/agent/fire.js.map +1 -0
  127. package/dist/tools/agent/hire.d.ts +2 -2
  128. package/dist/tools/agent/hire.d.ts.map +1 -1
  129. package/dist/tools/agent/hire.js +43 -10
  130. package/dist/tools/agent/hire.js.map +1 -1
  131. package/dist/tools/agent/index.d.ts +22 -19
  132. package/dist/tools/agent/index.d.ts.map +1 -1
  133. package/dist/tools/agent/index.js +29 -21
  134. package/dist/tools/agent/index.js.map +1 -1
  135. package/dist/tools/agent/prompt.d.ts +2 -2
  136. package/dist/tools/agent/prompt.d.ts.map +1 -1
  137. package/dist/tools/agent/prompt.js +19 -53
  138. package/dist/tools/agent/prompt.js.map +1 -1
  139. package/dist/tools/agent/registry.d.ts +74 -24
  140. package/dist/tools/agent/registry.d.ts.map +1 -1
  141. package/dist/tools/agent/registry.js +93 -48
  142. package/dist/tools/agent/registry.js.map +1 -1
  143. package/dist/tools/agent/report-group.d.ts +5 -0
  144. package/dist/tools/agent/report-group.d.ts.map +1 -0
  145. package/dist/tools/agent/report-group.js +50 -0
  146. package/dist/tools/agent/report-group.js.map +1 -0
  147. package/dist/tools/agent/report-parent.d.ts +5 -0
  148. package/dist/tools/agent/report-parent.d.ts.map +1 -0
  149. package/dist/tools/agent/report-parent.js +36 -0
  150. package/dist/tools/agent/report-parent.js.map +1 -0
  151. package/dist/tools/agent/types.d.ts +5 -0
  152. package/dist/tools/agent/types.d.ts.map +1 -0
  153. package/dist/tools/agent/types.js +17 -0
  154. package/dist/tools/agent/types.js.map +1 -0
  155. package/docs/agents.md +249 -228
  156. package/docs/api-reference.md +9 -4
  157. package/docs/getting-started.md +78 -78
  158. package/docs/index.md +24 -23
  159. package/docs/mcp-architecture.md +71 -6
  160. package/docs/providers.md +258 -254
  161. package/docs/skills.md +0 -1
  162. package/docs/streaming.md +133 -133
  163. package/docs/swarm.md +503 -0
  164. package/docs/tools.md +214 -212
  165. package/package.json +1 -1
  166. package/dist/core/image-describer.d.ts +0 -19
  167. package/dist/core/image-describer.d.ts.map +0 -1
  168. package/dist/core/image-describer.js +0 -37
  169. package/dist/core/image-describer.js.map +0 -1
  170. package/dist/core/worker-agent.d.ts +0 -43
  171. package/dist/core/worker-agent.d.ts.map +0 -1
  172. package/dist/core/worker-agent.js +0 -40
  173. package/dist/core/worker-agent.js.map +0 -1
  174. package/dist/skills/shopping.d.ts +0 -4
  175. package/dist/skills/shopping.d.ts.map +0 -1
  176. package/dist/skills/shopping.js +0 -71
  177. package/dist/skills/shopping.js.map +0 -1
  178. package/dist/tools/agent/interaction.d.ts +0 -25
  179. package/dist/tools/agent/interaction.d.ts.map +0 -1
  180. package/dist/tools/agent/interaction.js +0 -14
  181. package/dist/tools/agent/interaction.js.map +0 -1
  182. package/dist/tools/agent/list.d.ts +0 -5
  183. package/dist/tools/agent/list.d.ts.map +0 -1
  184. package/dist/tools/agent/list.js +0 -16
  185. package/dist/tools/agent/list.js.map +0 -1
  186. package/dist/tools/agent/report.d.ts +0 -12
  187. package/dist/tools/agent/report.d.ts.map +0 -1
  188. package/dist/tools/agent/report.js +0 -31
  189. package/dist/tools/agent/report.js.map +0 -1
  190. package/dist/tools/bash/interaction.d.ts +0 -29
  191. package/dist/tools/bash/interaction.d.ts.map +0 -1
  192. package/dist/tools/bash/interaction.js +0 -13
  193. package/dist/tools/bash/interaction.js.map +0 -1
  194. package/dist/tools/browser/interaction.d.ts +0 -49
  195. package/dist/tools/browser/interaction.d.ts.map +0 -1
  196. package/dist/tools/browser/interaction.js +0 -14
  197. package/dist/tools/browser/interaction.js.map +0 -1
  198. package/dist/tools/fs/interaction.d.ts +0 -37
  199. package/dist/tools/fs/interaction.d.ts.map +0 -1
  200. package/dist/tools/fs/interaction.js +0 -13
  201. package/dist/tools/fs/interaction.js.map +0 -1
  202. package/dist/tools/present/interaction.d.ts +0 -17
  203. package/dist/tools/present/interaction.d.ts.map +0 -1
  204. package/dist/tools/present/interaction.js +0 -15
  205. package/dist/tools/present/interaction.js.map +0 -1
  206. package/dist/tools/question-answer/interaction.d.ts +0 -14
  207. package/dist/tools/question-answer/interaction.d.ts.map +0 -1
  208. package/dist/tools/question-answer/interaction.js +0 -13
  209. package/dist/tools/question-answer/interaction.js.map +0 -1
  210. package/dist/tools/todo/interaction.d.ts +0 -30
  211. package/dist/tools/todo/interaction.d.ts.map +0 -1
  212. package/dist/tools/todo/interaction.js +0 -13
  213. package/dist/tools/todo/interaction.js.map +0 -1
@@ -0,0 +1,106 @@
1
+ import { test, describe } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { DefaultAgents, PlannerAgent, ReasonerAgent, BackendAgent, FrontendAgent, TestAgent, ResearchAgent, getAgentTools, FsTools, BashTools, BrowserTools, TodoTools, UtilTools, QuestionAnswerTools, } from "../../index.js";
4
+ const pool = () => [
5
+ ...getAgentTools({ maxHired: 3 }).tools,
6
+ ...FsTools(),
7
+ ...BashTools(),
8
+ ...BrowserTools(),
9
+ ...TodoTools(),
10
+ ...UtilTools(),
11
+ ...QuestionAnswerTools(),
12
+ ];
13
+ const toolNames = (factory) => factory({ tools: pool() }).getDefinition().tools.map(t => t.getOptions().name);
14
+ describe("agents/default", () => {
15
+ test("DefaultAgents is a usable roster covering the whole build pipeline", () => {
16
+ const tools = pool();
17
+ const types = DefaultAgents().map(factory => factory({ tools }).getType());
18
+ assert.deepStrictEqual(types, ["planner", "reasoner", "backend", "frontend", "tester", "research"]);
19
+ });
20
+ test("every default definition has a description a hiring model can judge from", () => {
21
+ const tools = pool();
22
+ for (const factory of DefaultAgents()) {
23
+ const { description, instruction, rating } = factory({ tools }).getDefinition();
24
+ assert.ok(description.length > 40, `${factory.name} description is too thin to hire from`);
25
+ assert.ok(instruction.length > 100, `${factory.name} instruction is too thin`);
26
+ assert.ok(rating && Object.keys(rating).length > 0, `${factory.name} has no ratings`);
27
+ }
28
+ });
29
+ test("the planner gets the hiring tools and no way to edit the project itself", () => {
30
+ const names = toolNames(PlannerAgent);
31
+ for (const hiring of ["agent-types", "agent-hire", "agent-fire", "agent-active", "agent-prompt"]) {
32
+ assert.ok(names.includes(hiring), `planner is missing ${hiring}`);
33
+ }
34
+ assert.ok(names.includes("fs-read-file"), "planner should still be able to read the project");
35
+ assert.ok(!names.includes("fs-write-file"), "a planner that can write starts doing the work itself");
36
+ assert.ok(!names.includes("bash-run"));
37
+ assert.ok(!names.includes("agent-report-parent"), "the entrypoint has nobody to report to");
38
+ });
39
+ test("workers get the reporting tools and not the hiring ones", () => {
40
+ for (const factory of [ReasonerAgent, BackendAgent, FrontendAgent, TestAgent, ResearchAgent]) {
41
+ const names = toolNames(factory);
42
+ assert.ok(names.includes("agent-report-parent"), `${factory.name} cannot report back`);
43
+ assert.ok(names.includes("agent-report-group"), `${factory.name} cannot talk to its group`);
44
+ assert.ok(!names.includes("agent-hire"), `${factory.name} should not be hiring`);
45
+ }
46
+ });
47
+ test("each worker picks the tools its own job needs", () => {
48
+ const backend = toolNames(BackendAgent);
49
+ assert.ok(backend.includes("fs-write-file") && backend.includes("bash-run"));
50
+ assert.ok(!backend.includes("browser-navigate"), "backend has no reason to drive a browser");
51
+ const frontend = toolNames(FrontendAgent);
52
+ assert.ok(frontend.includes("fs-write-file") && frontend.includes("browser-navigate"));
53
+ const research = toolNames(ResearchAgent);
54
+ assert.ok(research.includes("browser-navigate") && research.includes("fs-read-file"));
55
+ assert.ok(!research.includes("fs-write-file"), "a read-only agent must not be able to write");
56
+ assert.ok(!research.includes("bash-run"), "a read-only agent must not be able to run commands");
57
+ const tester = toolNames(TestAgent);
58
+ assert.ok(tester.includes("bash-run"), "the tester has to be able to build and run what it checks");
59
+ assert.ok(tester.includes("browser-navigate"), "the tester has to drive the real UI");
60
+ assert.ok(tester.includes("fs-write-file"), "the tester writes test files, though never production code");
61
+ });
62
+ test("the reasoner can measure and pace its own five minutes, and cannot build anything", () => {
63
+ const names = toolNames(ReasonerAgent);
64
+ assert.ok(names.includes("get-current-time"), "the panel's clock is measured, not estimated");
65
+ assert.ok(!names.includes("delay"), "the five minutes are filled with argument — there is nothing to sleep on");
66
+ assert.ok(names.includes("question-answer"), "the panel interrogates the user before it reasons");
67
+ assert.ok(names.includes("fs-read-file"), "it should argue about the real project");
68
+ assert.ok(!names.includes("fs-write-file"), "the reasoner thinks, it does not build");
69
+ assert.ok(!names.includes("bash-run"));
70
+ });
71
+ test("the pipeline the planner describes matches the roster it can hire from", () => {
72
+ const tools = pool();
73
+ const instruction = PlannerAgent({ tools }).getDefinition().instruction;
74
+ const types = DefaultAgents().map(factory => factory({ tools }).getType());
75
+ for (const type of types.filter(t => t !== "planner" && t !== "research")) {
76
+ assert.match(instruction, new RegExp(type), `the planner never mentions the ${type} it can hire`);
77
+ }
78
+ });
79
+ test("frontend agents are told how to share a project without overwriting each other", () => {
80
+ const instruction = FrontendAgent({ tools: pool() }).getDefinition().instruction;
81
+ assert.match(instruction, /claim your files/i);
82
+ assert.match(instruction, /never edit a file another agent has claimed/i);
83
+ assert.match(instruction, /agree on the scaffold/i);
84
+ });
85
+ test("a definition only picks what the app actually constructed", () => {
86
+ const names = BackendAgent({ tools: [...UtilTools()] }).getDefinition().tools.map(t => t.getOptions().name);
87
+ assert.deepStrictEqual(names, ["get-current-time"]);
88
+ });
89
+ test("factory overrides apply on top of the shipped persona", () => {
90
+ const definition = BackendAgent({
91
+ tools: pool(),
92
+ instruction: { append: "This project uses Postgres." },
93
+ safetyPolicies: "Never touch anything outside /workspace.",
94
+ }).getDefinition();
95
+ assert.match(definition.instruction, /You are a backend engineer/);
96
+ assert.match(definition.instruction, /This project uses Postgres\.$/);
97
+ assert.strictEqual(definition.safetyPolicies, "Never touch anything outside /workspace.");
98
+ });
99
+ test("skills come along with the definition and bring their own tools", () => {
100
+ const definition = BackendAgent({ tools: pool() });
101
+ const skills = definition.getDefinition().skills ?? [];
102
+ assert.ok(skills.length >= 3);
103
+ assert.ok(definition.getAllTools().length >= definition.getDefinition().tools.length);
104
+ });
105
+ });
106
+ //# sourceMappingURL=default-agents.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-agents.test.js","sourceRoot":"","sources":["../../../src/tests/agents/default-agents.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=agent-definition.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-definition.test.d.ts","sourceRoot":"","sources":["../../../src/tests/core/agent-definition.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,99 @@
1
+ import { test, describe } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { AgentDefinition, applyTextOverride, selectTools, Skill, MCPTool, GetCurrentTimeTool, DelayTool, FsReadFileTool, FsWriteFileTool } from "../../index.js";
4
+ import { ScriptedProvider } from "./scripted-provider.js";
5
+ const pool = () => [GetCurrentTimeTool(), DelayTool(), FsReadFileTool(), FsWriteFileTool()];
6
+ const definition = (tools, extra = {}) => new AgentDefinition({
7
+ type: "worker",
8
+ description: "does work",
9
+ instruction: "BASE INSTRUCTION",
10
+ safetyPolicies: "BASE POLICY",
11
+ tools,
12
+ ...extra,
13
+ });
14
+ describe("core/agent-definition", () => {
15
+ test("applyTextOverride: undefined keeps the base, a bare string replaces it", () => {
16
+ assert.strictEqual(applyTextOverride("base"), "base");
17
+ assert.strictEqual(applyTextOverride("base", "new"), "new");
18
+ assert.strictEqual(applyTextOverride("base", { replace: "new" }), "new");
19
+ });
20
+ test("applyTextOverride: append and prepend keep the base text", () => {
21
+ assert.strictEqual(applyTextOverride("base", { append: "more" }), "base\n\nmore");
22
+ assert.strictEqual(applyTextOverride("base", { prepend: "first" }), "first\n\nbase");
23
+ });
24
+ test("applyTextOverride: an empty base doesn't leave stray blank lines", () => {
25
+ assert.strictEqual(applyTextOverride("", { append: "only" }), "only");
26
+ assert.strictEqual(applyTextOverride("", { prepend: "only" }), "only");
27
+ });
28
+ test("selectTools: picks by exact name, in the order asked for", () => {
29
+ const picked = selectTools(pool(), ["fs-read-file", "get-current-time"]);
30
+ assert.deepStrictEqual(picked.map(t => t.getOptions().name), ["fs-read-file", "get-current-time"]);
31
+ });
32
+ test("selectTools: a trailing * matches by prefix, and duplicates are dropped", () => {
33
+ const picked = selectTools(pool(), ["fs-*", "fs-read-file"]);
34
+ assert.deepStrictEqual(picked.map(t => t.getOptions().name), ["fs-read-file", "fs-write-file"]);
35
+ });
36
+ test("selectTools: a name the app didn't construct is skipped, not an error", () => {
37
+ const picked = selectTools(pool(), ["fs-read-file", "browser-navigate"]);
38
+ assert.deepStrictEqual(picked.map(t => t.getOptions().name), ["fs-read-file"]);
39
+ });
40
+ test("with(): returns a new definition and leaves the original untouched", () => {
41
+ const original = definition(pool());
42
+ const derived = original.with({ instruction: { append: "EXTRA" }, safetyPolicies: "REPLACED" });
43
+ assert.notStrictEqual(original, derived);
44
+ assert.strictEqual(original.getDefinition().instruction, "BASE INSTRUCTION");
45
+ assert.strictEqual(original.getDefinition().safetyPolicies, "BASE POLICY");
46
+ assert.strictEqual(derived.getDefinition().instruction, "BASE INSTRUCTION\n\nEXTRA");
47
+ assert.strictEqual(derived.getDefinition().safetyPolicies, "REPLACED");
48
+ });
49
+ test("with(): appends stack in call order, so swarm-wide lands before per-type", () => {
50
+ const derived = definition(pool())
51
+ .with({ instruction: { append: "SWARM WIDE" } })
52
+ .with({ instruction: { append: "PER TYPE" } });
53
+ assert.strictEqual(derived.getDefinition().instruction, "BASE INSTRUCTION\n\nSWARM WIDE\n\nPER TYPE");
54
+ });
55
+ test("with(): extraTools are appended and deduped", () => {
56
+ const tools = pool();
57
+ const derived = definition([tools[0]]).with({ extraTools: [tools[1], tools[0]] });
58
+ assert.deepStrictEqual(derived.getDefinition().tools.map(t => t.getOptions().name), ["get-current-time", "delay"]);
59
+ });
60
+ test("with(): no overrides returns the same instance", () => {
61
+ const original = definition(pool());
62
+ assert.strictEqual(original.with(), original);
63
+ });
64
+ test("getAllTools(): skill tools are merged in, without duplicating a tool already picked", () => {
65
+ const tools = pool();
66
+ const skill = new Skill({ name: "s", description: "d", instructions: "i", tools: [tools[0], tools[2]] });
67
+ const built = definition([tools[0], tools[1]], { skills: [skill] });
68
+ assert.deepStrictEqual(built.getAllTools().map(t => t.getOptions().name), ["get-current-time", "delay", "fs-read-file"]);
69
+ });
70
+ test("buildProps(): the swarm's runtime fills what the definition left open", () => {
71
+ const provider = new ScriptedProvider("p", () => ({ content: "hi" }));
72
+ const props = definition(pool()).buildProps({
73
+ aiProvider: provider,
74
+ mcpClient: {},
75
+ maxMemorizeToken: 4242,
76
+ features: { executeProviderFromMCPTool: true },
77
+ });
78
+ assert.strictEqual(props.aiProvider, provider);
79
+ assert.strictEqual(props.maxMemorizeToken, 4242);
80
+ assert.deepStrictEqual(props.features, { executeProviderFromMCPTool: true });
81
+ assert.strictEqual(props.instruction, "BASE INSTRUCTION");
82
+ assert.strictEqual(props.initData, undefined);
83
+ });
84
+ test("buildProps(): a definition's own provider and limits win over the swarm's", () => {
85
+ const swarmProvider = new ScriptedProvider("swarm", () => ({ content: "hi" }));
86
+ const ownProvider = new ScriptedProvider("own", () => ({ content: "hi" }));
87
+ const props = definition(pool(), { aiProvider: ownProvider, maxMemorizeToken: 10 }).buildProps({
88
+ aiProvider: swarmProvider,
89
+ mcpClient: {},
90
+ maxMemorizeToken: 4242,
91
+ });
92
+ assert.strictEqual(props.aiProvider, ownProvider);
93
+ assert.strictEqual(props.maxMemorizeToken, 10);
94
+ });
95
+ test("a definition without a type is rejected", () => {
96
+ assert.throws(() => new AgentDefinition({ type: "", description: "d", instruction: "i", tools: [] }), /`type` is required/);
97
+ });
98
+ });
99
+ //# sourceMappingURL=agent-definition.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-definition.test.js","sourceRoot":"","sources":["../../../src/tests/core/agent-definition.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ai-ask.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-ask.test.d.ts","sourceRoot":"","sources":["../../../src/tests/core/ai-ask.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,101 @@
1
+ import { test, describe } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { AIASK } from "../../index.js";
4
+ import { ScriptedProvider } from "./scripted-provider.js";
5
+ describe("core/ai-ask", () => {
6
+ test("run(): a valid first attempt returns immediately with valid:true, attempts:1", async () => {
7
+ const provider = new ScriptedProvider("p", () => ({
8
+ toolCalls: [{ name: "submit_answer", inputs: { valid: true, score: 7 } }],
9
+ }));
10
+ const ask = new AIASK({
11
+ instruction: "classify the input",
12
+ aiModel: provider,
13
+ outputStructure: [
14
+ { name: "valid", type: "boolean", description: "whether it's valid" },
15
+ { name: "score", type: "number", description: "confidence 0-10" },
16
+ ],
17
+ });
18
+ const result = await ask.run("check this");
19
+ assert.deepStrictEqual(result.output, { valid: true, score: 7 });
20
+ assert.strictEqual(result.valid, true);
21
+ assert.strictEqual(result.attempts, 1);
22
+ assert.strictEqual(result.errors, undefined);
23
+ });
24
+ test("run(): a missing required field triggers a retry, and a corrected 2nd attempt succeeds", async () => {
25
+ const provider = new ScriptedProvider("p", [
26
+ () => ({ toolCalls: [{ name: "submit_answer", inputs: { valid: true } }] }), // 1st attempt, missing "score"
27
+ () => ({ toolCalls: [{ name: "submit_answer", inputs: { valid: true, score: 9 } }] }), // 2nd attempt, corrected
28
+ ]);
29
+ const ask = new AIASK({
30
+ instruction: "classify the input",
31
+ aiModel: provider,
32
+ outputStructure: [
33
+ { name: "valid", type: "boolean", description: "whether it's valid" },
34
+ { name: "score", type: "number", description: "confidence 0-10" },
35
+ ],
36
+ });
37
+ const result = await ask.run("check this");
38
+ assert.deepStrictEqual(result.output, { valid: true, score: 9 });
39
+ assert.strictEqual(result.valid, true);
40
+ assert.strictEqual(result.attempts, 2);
41
+ });
42
+ test("run(): a wrong-typed field is rejected as invalid", async () => {
43
+ const provider = new ScriptedProvider("p", () => ({
44
+ toolCalls: [{ name: "submit_answer", inputs: { valid: "yes" } }], // should be boolean
45
+ }));
46
+ const ask = new AIASK({
47
+ instruction: "x",
48
+ aiModel: provider,
49
+ outputStructure: [{ name: "valid", type: "boolean", description: "d" }],
50
+ });
51
+ const result = await ask.run("go");
52
+ assert.strictEqual(result.valid, false);
53
+ assert.strictEqual(result.attempts, 3);
54
+ assert.match(result.errors[0], /should be boolean/);
55
+ });
56
+ test("run(): plain text instead of calling the tool counts as a failed attempt and retries", async () => {
57
+ const provider = new ScriptedProvider("p", [
58
+ () => ({ content: "I think it's valid" }), // no tool call at all
59
+ () => ({ toolCalls: [{ name: "submit_answer", inputs: { valid: true } }] }),
60
+ ]);
61
+ const ask = new AIASK({
62
+ instruction: "x",
63
+ aiModel: provider,
64
+ outputStructure: [{ name: "valid", type: "boolean", description: "d" }],
65
+ });
66
+ const result = await ask.run("go");
67
+ assert.strictEqual(result.valid, true);
68
+ assert.strictEqual(result.attempts, 2);
69
+ });
70
+ test("run(): gives up after 3 attempts, returning the last best-effort output with valid:false", async () => {
71
+ const provider = new ScriptedProvider("p", () => ({ content: "nope, just text" }));
72
+ const ask = new AIASK({
73
+ instruction: "x",
74
+ aiModel: provider,
75
+ outputStructure: [{ name: "valid", type: "boolean", description: "d" }],
76
+ });
77
+ const result = await ask.run("go");
78
+ assert.strictEqual(result.valid, false);
79
+ assert.strictEqual(result.attempts, 3);
80
+ assert.deepStrictEqual(result.output, {});
81
+ assert.strictEqual(result.errors.length, 1);
82
+ assert.strictEqual(provider.getCallCount(), 3, "one chat() call per attempt, no automatic follow-up");
83
+ });
84
+ test("run(): an optional field (required: false) may be omitted without failing validation", async () => {
85
+ const provider = new ScriptedProvider("p", () => ({
86
+ toolCalls: [{ name: "submit_answer", inputs: { valid: true } }],
87
+ }));
88
+ const ask = new AIASK({
89
+ instruction: "x",
90
+ aiModel: provider,
91
+ outputStructure: [
92
+ { name: "valid", type: "boolean", description: "d" },
93
+ { name: "note", type: "string", description: "d", required: false },
94
+ ],
95
+ });
96
+ const result = await ask.run("go");
97
+ assert.strictEqual(result.valid, true);
98
+ assert.strictEqual(result.attempts, 1);
99
+ });
100
+ });
101
+ //# sourceMappingURL=ai-ask.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-ask.test.js","sourceRoot":"","sources":["../../../src/tests/core/ai-ask.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=mcp-auto-execution-policy.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-auto-execution-policy.test.d.ts","sourceRoot":"","sources":["../../../src/tests/core/mcp-auto-execution-policy.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,107 @@
1
+ import { test, describe } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { MCPAutoExecutionPolicy } from "../../index.js";
4
+ import { ScriptedProvider } from "./scripted-provider.js";
5
+ const request = (overrides = {}) => ({
6
+ toolName: "bash-run",
7
+ inputs: { command: "rm -rf /" },
8
+ envID: "env",
9
+ toolCallId: "call-1",
10
+ ...overrides,
11
+ });
12
+ describe("core/mcp-auto-execution-policy", () => {
13
+ test("authorize(): an unwatched tool is authorized immediately, no model call, no verdict recorded", async () => {
14
+ const provider = new ScriptedProvider("p", () => ({ content: "should never be called" }));
15
+ const policy = new MCPAutoExecutionPolicy({ aiModel: provider });
16
+ const authorized = await policy.authorize(request({ toolName: "get-current-time", inputs: {}, toolCallId: "call-time" }));
17
+ assert.strictEqual(authorized, true);
18
+ assert.strictEqual(provider.getCallCount(), 0);
19
+ assert.strictEqual(policy.getVerdict("call-time"), undefined);
20
+ });
21
+ test("authorize(): bash-run always goes to the model — no path field to short-circuit on", async () => {
22
+ const provider = new ScriptedProvider("p", () => ({
23
+ toolCalls: [{ name: "submit_answer", inputs: { harmful: true, reason: "destroys the filesystem" } }],
24
+ }));
25
+ const policy = new MCPAutoExecutionPolicy({ aiModel: provider });
26
+ const authorized = await policy.authorize(request());
27
+ assert.strictEqual(authorized, false);
28
+ assert.strictEqual(provider.getCallCount(), 1);
29
+ });
30
+ test("authorize(): a watched fs call whose path resolves inside scope is authorized locally, no model call", async () => {
31
+ const provider = new ScriptedProvider("p", () => ({ content: "should never be called" }));
32
+ const policy = new MCPAutoExecutionPolicy({ aiModel: provider, scopeDir: process.cwd() });
33
+ const authorized = await policy.authorize(request({
34
+ toolName: "fs-write-file",
35
+ inputs: { path: "some/nested/file.txt", content: "hello" },
36
+ toolCallId: "call-write-in-scope",
37
+ }));
38
+ assert.strictEqual(authorized, true);
39
+ assert.strictEqual(provider.getCallCount(), 0);
40
+ assert.strictEqual(policy.getVerdict("call-write-in-scope").harmful, false);
41
+ assert.match(policy.getVerdict("call-write-in-scope").reason, /skipped model review/);
42
+ });
43
+ test("authorize(): a watched fs call whose path resolves outside scope escalates to the model", async () => {
44
+ const provider = new ScriptedProvider("p", () => ({
45
+ toolCalls: [{ name: "submit_answer", inputs: { harmful: true, reason: "writes outside the project" } }],
46
+ }));
47
+ const policy = new MCPAutoExecutionPolicy({ aiModel: provider, scopeDir: process.cwd() });
48
+ const authorized = await policy.authorize(request({
49
+ toolName: "fs-write-file",
50
+ inputs: { path: "../../outside.txt", content: "hello" },
51
+ }));
52
+ assert.strictEqual(authorized, false);
53
+ assert.strictEqual(provider.getCallCount(), 1);
54
+ });
55
+ test("authorize(): fs-move requires BOTH from and to inside scope to skip the model", async () => {
56
+ const provider = new ScriptedProvider("p", () => ({
57
+ toolCalls: [{ name: "submit_answer", inputs: { harmful: false, reason: "fine" } }],
58
+ }));
59
+ const policy = new MCPAutoExecutionPolicy({ aiModel: provider, scopeDir: process.cwd() });
60
+ await policy.authorize(request({
61
+ toolName: "fs-move",
62
+ inputs: { from: "in-scope.txt", to: "../outside.txt" },
63
+ }));
64
+ assert.strictEqual(provider.getCallCount(), 1, "one path outside scope forces a model review");
65
+ });
66
+ test("authorize(): file content is stripped before it ever reaches the model", async () => {
67
+ let seenPrompt = "";
68
+ const provider = new ScriptedProvider("p", ({ messages }) => {
69
+ seenPrompt = messages.at(-1)?.content ?? "";
70
+ return { toolCalls: [{ name: "submit_answer", inputs: { harmful: false, reason: "fine" } }] };
71
+ });
72
+ const policy = new MCPAutoExecutionPolicy({ aiModel: provider, scopeDir: "/some/other/scope" });
73
+ await policy.authorize(request({
74
+ toolName: "fs-write-file",
75
+ inputs: { path: "secrets.txt", content: "super-secret-password-do-not-leak-this" },
76
+ }));
77
+ assert.doesNotMatch(seenPrompt, /super-secret-password-do-not-leak-this/);
78
+ assert.match(seenPrompt, /omitted, \d+ bytes/);
79
+ });
80
+ test("getVerdict() / getLastVerdict() / onVerdict expose the reviewed verdict", async () => {
81
+ const provider = new ScriptedProvider("p", () => ({
82
+ toolCalls: [{ name: "submit_answer", inputs: { harmful: true, reason: "irreversible deletion" } }],
83
+ }));
84
+ const calls = [];
85
+ const policy = new MCPAutoExecutionPolicy({ aiModel: provider, onVerdict: (request, verdict) => calls.push({ request, verdict }) });
86
+ await policy.authorize(request({ toolCallId: "call-42" }));
87
+ assert.deepStrictEqual(policy.getVerdict("call-42"), { harmful: true, reason: "irreversible deletion" });
88
+ assert.deepStrictEqual(policy.getLastVerdict(), { harmful: true, reason: "irreversible deletion" });
89
+ assert.strictEqual(calls.length, 1);
90
+ });
91
+ test("authorize(): fails closed (denies) when the safety check itself can't produce a valid verdict", async () => {
92
+ const provider = new ScriptedProvider("p", () => ({ content: "I refuse to answer in JSON" }));
93
+ const policy = new MCPAutoExecutionPolicy({ aiModel: provider });
94
+ const authorized = await policy.authorize(request());
95
+ assert.strictEqual(authorized, false);
96
+ assert.strictEqual(policy.getVerdict("call-1").harmful, true);
97
+ });
98
+ test("watchedTools: a custom set overrides the default", async () => {
99
+ const provider = new ScriptedProvider("p", () => ({
100
+ toolCalls: [{ name: "submit_answer", inputs: { harmful: true, reason: "not allowed at all" } }],
101
+ }));
102
+ const policy = new MCPAutoExecutionPolicy({ aiModel: provider, watchedTools: ["todo-remove-list"] });
103
+ assert.strictEqual(await policy.authorize(request({ toolName: "bash-run" })), true, "bash-run isn't watched anymore");
104
+ assert.strictEqual(await policy.authorize(request({ toolName: "todo-remove-list", inputs: {} })), false);
105
+ });
106
+ });
107
+ //# sourceMappingURL=mcp-auto-execution-policy.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-auto-execution-policy.test.js","sourceRoot":"","sources":["../../../src/tests/core/mcp-auto-execution-policy.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import { AIProvider } from "../../index.js";
2
+ import type { ChatResponse, Message, ProviderCapabilities, StreamCallback, ToolSchema } from "../../index.js";
3
+ export interface ScriptedResult {
4
+ content?: string;
5
+ toolCalls?: {
6
+ name: string;
7
+ inputs: Record<string, any>;
8
+ }[];
9
+ /** Hold the "model" here for a moment, so a test can get a second call in while this turn is still running. */
10
+ delayMs?: number;
11
+ }
12
+ export type ScriptedTurn = (context: {
13
+ messages: Message[];
14
+ call: number;
15
+ }) => ScriptedResult;
16
+ /**
17
+ * A provider that answers from a script instead of a model, so swarm behavior
18
+ * can be tested without a network call.
19
+ *
20
+ * It streams each tool call before returning, exactly as the real providers do,
21
+ * so anything watching the stream (SwarmBase tags every chunk with the agent that
22
+ * produced it) sees what it would see in a real run.
23
+ */
24
+ export declare class ScriptedProvider extends AIProvider {
25
+ #private;
26
+ constructor(name: string, script: ScriptedTurn | ScriptedTurn[]);
27
+ getModel(): string;
28
+ chat(messages: Message[], streamCallback?: StreamCallback, _tools?: ToolSchema[], _signal?: AbortSignal): Promise<ChatResponse>;
29
+ getCapabilities(): ProviderCapabilities;
30
+ setOption(): void;
31
+ getCallCount(): number;
32
+ }
33
+ /** The parsed output of the most recent result for `toolName`, as the model would read it. */
34
+ export declare function lastToolOutput(messages: Message[], toolName: string): any;
35
+ /** Text of the newest user-role message — how a delivered task, report, or group message arrives. */
36
+ export declare function lastUserMessage(messages: Message[]): string;
37
+ export default ScriptedProvider;
38
+ //# sourceMappingURL=scripted-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scripted-provider.d.ts","sourceRoot":"","sources":["../../../src/tests/core/scripted-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE9G,MAAM,WAAW,cAAc;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;KAAE,EAAE,CAAC;IAC5D,+GAA+G;IAC/G,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE;IAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,KAAK,cAAc,CAAC;AAE9F;;;;;;;GAOG;AACH,qBAAa,gBAAiB,SAAQ,UAAU;;gBAMhC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,YAAY,EAAE;IAQ/D,QAAQ,IAAI,MAAM;IAIZ,IAAI,CACN,QAAQ,EAAE,OAAO,EAAE,EACnB,cAAc,CAAC,EAAE,cAAc,EAC/B,MAAM,CAAC,EAAE,UAAU,EAAE,EACrB,OAAO,CAAC,EAAE,WAAW,GACtB,OAAO,CAAC,YAAY,CAAC;IAkCxB,eAAe,IAAI,oBAAoB;IAIvC,SAAS,IAAI,IAAI;IAEjB,YAAY,IAAI,MAAM;CAGzB;AAED,8FAA8F;AAC9F,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,GAAG,CAYzE;AAED,qGAAqG;AACrG,wBAAgB,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAK3D;AAED,eAAe,gBAAgB,CAAC"}
@@ -0,0 +1,85 @@
1
+ import { AIProvider } from "../../index.js";
2
+ /**
3
+ * A provider that answers from a script instead of a model, so swarm behavior
4
+ * can be tested without a network call.
5
+ *
6
+ * It streams each tool call before returning, exactly as the real providers do,
7
+ * so anything watching the stream (SwarmBase tags every chunk with the agent that
8
+ * produced it) sees what it would see in a real run.
9
+ */
10
+ export class ScriptedProvider extends AIProvider {
11
+ #name;
12
+ #turn;
13
+ #calls = 0;
14
+ #ids = 0;
15
+ constructor(name, script) {
16
+ super();
17
+ this.#name = name;
18
+ this.#turn = Array.isArray(script)
19
+ ? ({ messages, call }) => (script[call] ?? (() => ({ content: "(no script left)" })))({ messages, call })
20
+ : script;
21
+ }
22
+ getModel() {
23
+ return `scripted-${this.#name}`;
24
+ }
25
+ async chat(messages, streamCallback, _tools, _signal) {
26
+ const call = this.#calls++;
27
+ const result = this.#turn({ messages, call });
28
+ if (result.delayMs) {
29
+ await new Promise(resolve => setTimeout(resolve, result.delayMs));
30
+ }
31
+ const toolCalls = (result.toolCalls ?? []).map(tc => ({
32
+ id: `${this.#name}-call-${++this.#ids}`,
33
+ name: tc.name,
34
+ inputs: tc.inputs,
35
+ }));
36
+ const usage = { inputMissTokens: 1, inputCacheTokens: 0, outputTokens: 1 };
37
+ for (const toolCall of toolCalls) {
38
+ await streamCallback?.({ role: "assistant", content: "", done: false, toolCalls: [toolCall], usage });
39
+ }
40
+ const content = result.content ?? "";
41
+ if (content) {
42
+ await streamCallback?.({ role: "assistant", content, done: false, usage });
43
+ }
44
+ await streamCallback?.({ role: "assistant", content: "", done: true, usage });
45
+ return {
46
+ content,
47
+ inputMissTokens: 1,
48
+ inputCacheTokens: 0,
49
+ outputTokens: 1,
50
+ ...(toolCalls.length ? { toolCalls } : {}),
51
+ };
52
+ }
53
+ getCapabilities() {
54
+ return { supportsTools: true, supportsImages: false, contextWindow: 200000, safeUsageRatio: 0.5 };
55
+ }
56
+ setOption() { }
57
+ getCallCount() {
58
+ return this.#calls;
59
+ }
60
+ }
61
+ /** The parsed output of the most recent result for `toolName`, as the model would read it. */
62
+ export function lastToolOutput(messages, toolName) {
63
+ for (let i = messages.length - 1; i >= 0; i--) {
64
+ const message = messages[i];
65
+ if (message.role === "tool" && message.toolName === toolName) {
66
+ try {
67
+ return JSON.parse(message.content ?? "{}");
68
+ }
69
+ catch {
70
+ return { raw: message.content };
71
+ }
72
+ }
73
+ }
74
+ return undefined;
75
+ }
76
+ /** Text of the newest user-role message — how a delivered task, report, or group message arrives. */
77
+ export function lastUserMessage(messages) {
78
+ for (let i = messages.length - 1; i >= 0; i--) {
79
+ if (messages[i].role === "user")
80
+ return messages[i].content ?? "";
81
+ }
82
+ return "";
83
+ }
84
+ export default ScriptedProvider;
85
+ //# sourceMappingURL=scripted-provider.js.map