orbitx 0.2.8 → 0.3.0
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 +478 -456
- package/dist/agents/backend.d.ts +4 -0
- package/dist/agents/backend.d.ts.map +1 -0
- package/dist/agents/backend.js +54 -0
- package/dist/agents/backend.js.map +1 -0
- package/dist/agents/frontend.d.ts +4 -0
- package/dist/agents/frontend.d.ts.map +1 -0
- package/dist/agents/frontend.js +50 -0
- package/dist/agents/frontend.js.map +1 -0
- package/dist/agents/index.d.ts +10 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +22 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/planner.d.ts +4 -0
- package/dist/agents/planner.d.ts.map +1 -0
- package/dist/agents/planner.js +86 -0
- package/dist/agents/planner.js.map +1 -0
- package/dist/agents/protocol.d.ts +5 -0
- package/dist/agents/protocol.d.ts.map +1 -0
- package/dist/agents/protocol.js +70 -0
- package/dist/agents/protocol.js.map +1 -0
- package/dist/agents/reasoner.d.ts +5 -0
- package/dist/agents/reasoner.d.ts.map +1 -0
- package/dist/agents/reasoner.js +96 -0
- package/dist/agents/reasoner.js.map +1 -0
- package/dist/agents/research.d.ts +4 -0
- package/dist/agents/research.d.ts.map +1 -0
- package/dist/agents/research.js +28 -0
- package/dist/agents/research.js.map +1 -0
- package/dist/agents/tester.d.ts +4 -0
- package/dist/agents/tester.d.ts.map +1 -0
- package/dist/agents/tester.js +70 -0
- package/dist/agents/tester.js.map +1 -0
- package/dist/core/agent-definition.d.ts +61 -0
- package/dist/core/agent-definition.d.ts.map +1 -0
- package/dist/core/agent-definition.js +82 -0
- package/dist/core/agent-definition.js.map +1 -0
- package/dist/core/ai-provider.d.ts +3 -0
- package/dist/core/ai-provider.d.ts.map +1 -1
- package/dist/core/ai-provider.js.map +1 -1
- package/dist/core/anthropic-provider.d.ts +1 -0
- package/dist/core/anthropic-provider.d.ts.map +1 -1
- package/dist/core/anthropic-provider.js +3 -0
- package/dist/core/anthropic-provider.js.map +1 -1
- package/dist/core/base-agent.d.ts +52 -29
- package/dist/core/base-agent.d.ts.map +1 -1
- package/dist/core/base-agent.js +123 -27
- package/dist/core/base-agent.js.map +1 -1
- package/dist/core/deepseek-provider.d.ts +1 -0
- package/dist/core/deepseek-provider.d.ts.map +1 -1
- package/dist/core/deepseek-provider.js +3 -0
- package/dist/core/deepseek-provider.js.map +1 -1
- package/dist/core/mcp-computer.d.ts +14 -1
- package/dist/core/mcp-computer.d.ts.map +1 -1
- package/dist/core/mcp-computer.js +352 -71
- package/dist/core/mcp-computer.js.map +1 -1
- package/dist/core/ollama-provider.d.ts +1 -0
- package/dist/core/ollama-provider.d.ts.map +1 -1
- package/dist/core/ollama-provider.js +3 -0
- package/dist/core/ollama-provider.js.map +1 -1
- package/dist/core/openai-provider.d.ts +1 -0
- package/dist/core/openai-provider.d.ts.map +1 -1
- package/dist/core/openai-provider.js +3 -0
- package/dist/core/openai-provider.js.map +1 -1
- package/dist/core/swarm-base.d.ts +88 -0
- package/dist/core/swarm-base.d.ts.map +1 -0
- package/dist/core/swarm-base.js +427 -0
- package/dist/core/swarm-base.js.map +1 -0
- package/dist/index.d.ts +7 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/tests/agents/default-agents.test.d.ts +2 -0
- package/dist/tests/agents/default-agents.test.d.ts.map +1 -0
- package/dist/tests/agents/default-agents.test.js +106 -0
- package/dist/tests/agents/default-agents.test.js.map +1 -0
- package/dist/tests/core/agent-definition.test.d.ts +2 -0
- package/dist/tests/core/agent-definition.test.d.ts.map +1 -0
- package/dist/tests/core/agent-definition.test.js +99 -0
- package/dist/tests/core/agent-definition.test.js.map +1 -0
- package/dist/tests/core/scripted-provider.d.ts +38 -0
- package/dist/tests/core/scripted-provider.d.ts.map +1 -0
- package/dist/tests/core/scripted-provider.js +85 -0
- package/dist/tests/core/scripted-provider.js.map +1 -0
- package/dist/tests/core/swarm-base.test.d.ts +2 -0
- package/dist/tests/core/swarm-base.test.d.ts.map +1 -0
- package/dist/tests/core/swarm-base.test.js +387 -0
- package/dist/tests/core/swarm-base.test.js.map +1 -0
- package/dist/tests/index.d.ts +3 -0
- package/dist/tests/index.d.ts.map +1 -1
- package/dist/tests/index.js +3 -0
- package/dist/tests/index.js.map +1 -1
- package/dist/tests/tools/agent/agent-tools.test.js +225 -153
- package/dist/tests/tools/agent/agent-tools.test.js.map +1 -1
- package/dist/tools/agent/active.d.ts +5 -0
- package/dist/tools/agent/active.d.ts.map +1 -0
- package/dist/tools/agent/active.js +40 -0
- package/dist/tools/agent/active.js.map +1 -0
- package/dist/tools/agent/fire.d.ts +5 -0
- package/dist/tools/agent/fire.d.ts.map +1 -0
- package/dist/tools/agent/fire.js +38 -0
- package/dist/tools/agent/fire.js.map +1 -0
- package/dist/tools/agent/hire.d.ts +2 -2
- package/dist/tools/agent/hire.d.ts.map +1 -1
- package/dist/tools/agent/hire.js +43 -10
- package/dist/tools/agent/hire.js.map +1 -1
- package/dist/tools/agent/index.d.ts +22 -19
- package/dist/tools/agent/index.d.ts.map +1 -1
- package/dist/tools/agent/index.js +29 -21
- package/dist/tools/agent/index.js.map +1 -1
- package/dist/tools/agent/prompt.d.ts +2 -2
- package/dist/tools/agent/prompt.d.ts.map +1 -1
- package/dist/tools/agent/prompt.js +19 -53
- package/dist/tools/agent/prompt.js.map +1 -1
- package/dist/tools/agent/registry.d.ts +74 -24
- package/dist/tools/agent/registry.d.ts.map +1 -1
- package/dist/tools/agent/registry.js +93 -48
- package/dist/tools/agent/registry.js.map +1 -1
- package/dist/tools/agent/report-group.d.ts +5 -0
- package/dist/tools/agent/report-group.d.ts.map +1 -0
- package/dist/tools/agent/report-group.js +50 -0
- package/dist/tools/agent/report-group.js.map +1 -0
- package/dist/tools/agent/report-parent.d.ts +5 -0
- package/dist/tools/agent/report-parent.d.ts.map +1 -0
- package/dist/tools/agent/report-parent.js +36 -0
- package/dist/tools/agent/report-parent.js.map +1 -0
- package/dist/tools/agent/types.d.ts +5 -0
- package/dist/tools/agent/types.d.ts.map +1 -0
- package/dist/tools/agent/types.js +17 -0
- package/dist/tools/agent/types.js.map +1 -0
- package/docs/agents.md +173 -212
- package/docs/api-reference.md +9 -4
- package/docs/getting-started.md +78 -78
- package/docs/index.md +24 -23
- package/docs/mcp-architecture.md +29 -6
- package/docs/providers.md +258 -254
- package/docs/skills.md +0 -1
- package/docs/streaming.md +133 -133
- package/docs/swarm.md +503 -0
- package/docs/tools.md +214 -212
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/agents/backend.ts"],"names":[],"mappings":"AAAA,OAAwB,EAAe,KAAK,YAAY,EAA4B,MAAM,6BAA6B,CAAC;AAMxH,eAAO,MAAM,YAAY,EAAE,YA+CL,CAAC;AAEvB,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import AgentDefinition, { selectTools } from "../core/agent-definition.js";
|
|
2
|
+
import { NodeBackendSkill } from "../skills/node-backend.js";
|
|
3
|
+
import { BackendSecuritySkill } from "../skills/backend-security.js";
|
|
4
|
+
import { CodeVerificationSkill } from "../skills/code-verification.js";
|
|
5
|
+
import { PRODUCTION_BAR, WORKER_PROTOCOL } from "./protocol.js";
|
|
6
|
+
export const BackendAgent = ({ tools = [], ...overrides } = {}) => new AgentDefinition({
|
|
7
|
+
type: "backend",
|
|
8
|
+
description: "Server-side engineer. HTTP APIs, data models, auth and sessions, migrations, integrations, backend tests. Hire for anything that runs on a server or touches a database.",
|
|
9
|
+
rating: { backend: 10, security: 8, testing: 7, frontend: 2, planning: 3 },
|
|
10
|
+
skills: [NodeBackendSkill(), BackendSecuritySkill(), CodeVerificationSkill()],
|
|
11
|
+
tools: selectTools(tools, [
|
|
12
|
+
"fs-*",
|
|
13
|
+
"bash-*",
|
|
14
|
+
"get-current-time",
|
|
15
|
+
"agent-report-parent",
|
|
16
|
+
"agent-report-group",
|
|
17
|
+
]),
|
|
18
|
+
instruction: `You are a backend engineer working inside a swarm.
|
|
19
|
+
|
|
20
|
+
Read the code around a change before making it, and follow the conventions already in the project rather than the ones you would have picked.
|
|
21
|
+
|
|
22
|
+
# What a server has to get right
|
|
23
|
+
|
|
24
|
+
You own the boundary between the outside world and everything behind it. These are the failures that only ever show up in production, and every one of them is cheaper to get right now than to find later:
|
|
25
|
+
|
|
26
|
+
- **Validate every untrusted input at the boundary**, before it reaches any logic — types, ranges, required fields, sizes. Reject with a specific error rather than coercing something plausible out of it.
|
|
27
|
+
- **Never trust a client-supplied id for authorization.** Who the caller *is* comes from the session or token; what they are allowed to touch is checked server-side, per request, every time. An endpoint that returns someone else's record because they guessed the id is the most common real breach there is.
|
|
28
|
+
- **Assume any request can arrive twice, out of order, or concurrently.** Decide what that means for each write, rather than letting a race decide for you.
|
|
29
|
+
- **Everything you call can be slow or down** — a database, another service, the filesystem. Give outbound calls a timeout, and decide what your endpoint returns when the answer never comes.
|
|
30
|
+
- **Shut down cleanly.** Handle the termination signal, stop accepting new work, let in-flight requests finish, close connections. A process that is killed mid-write is how data gets corrupted.
|
|
31
|
+
- **Set the boring defaults**: a body-size limit, CORS scoped to the origins that actually need it, security headers, and no stack traces in a response body.
|
|
32
|
+
|
|
33
|
+
# You also own the API contract
|
|
34
|
+
|
|
35
|
+
Frontend agents will be built against your API without ever seeing your code, and a tester will check your server against what you wrote down. So a feature is not finished until the contract for it is written to a file in the project (\`API.md\` or whatever the project already uses) and summarised in your report. For every endpoint:
|
|
36
|
+
|
|
37
|
+
- method and full path, including path parameters
|
|
38
|
+
- request shape: headers that matter, query parameters, body fields with names, types, and which are required
|
|
39
|
+
- response shape for success: status code and body fields with names and types, including what is nullable
|
|
40
|
+
- error responses it can actually return, with status codes and body shape
|
|
41
|
+
- auth: what the caller must send, and what happens when it is missing or wrong
|
|
42
|
+
|
|
43
|
+
Write what the code actually does, not what you meant it to do — if you changed a field name late, change it here too. An inaccurate contract is worse than a missing one: several agents will build on it in parallel before anyone finds out.
|
|
44
|
+
|
|
45
|
+
When a tester reports a divergence between your server and this document, fix whichever side is actually wrong and say which you changed.
|
|
46
|
+
|
|
47
|
+
Finish by proving the change works: run the tests, the build, or the command that exercises it, and report what you actually observed — not what you expect would happen if it were run. If something is broken and you could not fix it, say so and say why.
|
|
48
|
+
|
|
49
|
+
${PRODUCTION_BAR}
|
|
50
|
+
|
|
51
|
+
${WORKER_PROTOCOL}`,
|
|
52
|
+
}).with(overrides);
|
|
53
|
+
export default BackendAgent;
|
|
54
|
+
//# sourceMappingURL=backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.js","sourceRoot":"","sources":["../../src/agents/backend.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,EAAE,EAAE,WAAW,EAA+C,MAAM,6BAA6B,CAAC;AACxH,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhE,MAAM,CAAC,MAAM,YAAY,GAAiB,CAAC,EAAE,KAAK,GAAG,EAAE,EAAE,GAAG,SAAS,KAA0B,EAAE,EAAE,EAAE,CACjG,IAAI,eAAe,CAAC;IAChB,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,0KAA0K;IACvL,MAAM,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE;IAC1E,MAAM,EAAE,CAAC,gBAAgB,EAAE,EAAE,oBAAoB,EAAE,EAAE,qBAAqB,EAAE,CAAC;IAC7E,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE;QACtB,MAAM;QACN,QAAQ;QACR,kBAAkB;QAClB,qBAAqB;QACrB,oBAAoB;KACvB,CAAC;IACF,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BnB,cAAc;;EAEd,eAAe,EAAE;CACd,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAEvB,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontend.d.ts","sourceRoot":"","sources":["../../src/agents/frontend.ts"],"names":[],"mappings":"AAAA,OAAwB,EAAe,KAAK,YAAY,EAA4B,MAAM,6BAA6B,CAAC;AAMxH,eAAO,MAAM,aAAa,EAAE,YA2CN,CAAC;AAEvB,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import AgentDefinition, { selectTools } from "../core/agent-definition.js";
|
|
2
|
+
import { ReactFrontendSkill } from "../skills/react-frontend.js";
|
|
3
|
+
import { UiUxDesignSkill } from "../skills/ui-ux-design.js";
|
|
4
|
+
import { CodeVerificationSkill } from "../skills/code-verification.js";
|
|
5
|
+
import { PRODUCTION_BAR, TEAM_PROTOCOL, WORKER_PROTOCOL } from "./protocol.js";
|
|
6
|
+
export const FrontendAgent = ({ tools = [], ...overrides } = {}) => new AgentDefinition({
|
|
7
|
+
type: "frontend",
|
|
8
|
+
description: "Client-side engineer. Components, state, routing, styling, accessibility, and checking the result in a real browser. Hire for anything a user sees or clicks.",
|
|
9
|
+
rating: { frontend: 10, design: 7, testing: 6, backend: 2, planning: 3 },
|
|
10
|
+
skills: [ReactFrontendSkill(), UiUxDesignSkill(), CodeVerificationSkill()],
|
|
11
|
+
tools: selectTools(tools, [
|
|
12
|
+
"fs-*",
|
|
13
|
+
"bash-*",
|
|
14
|
+
"browser-*",
|
|
15
|
+
"read-image",
|
|
16
|
+
"get-current-time",
|
|
17
|
+
"agent-report-parent",
|
|
18
|
+
"agent-report-group",
|
|
19
|
+
]),
|
|
20
|
+
instruction: `You are a frontend engineer working inside a swarm, usually one of two or three building the same app at the same time.
|
|
21
|
+
|
|
22
|
+
Match the project's existing components, styling approach, and state conventions instead of introducing your own. Build for the states a real screen has — loading, empty, error, and too much data — not just the happy path, and keep it usable by keyboard and screen reader.
|
|
23
|
+
|
|
24
|
+
# Build against the API contract you were given
|
|
25
|
+
|
|
26
|
+
You cannot see the backend, and you must not guess at it. The API documentation handed to you has been verified against the running server, so treat it as the source of truth: exact paths, exact field names, exact types, the error responses it says can happen. If something you need is genuinely missing from it, say so in your report rather than inventing an endpoint — and never quietly change the shape of a request because it seemed more sensible.
|
|
27
|
+
|
|
28
|
+
If the API turns out to behave differently from its documentation, that is a finding: tell your group immediately, so nobody else builds on the same wrong assumption, and put it in your report.
|
|
29
|
+
|
|
30
|
+
# A screen that is only ever seen working is not finished
|
|
31
|
+
|
|
32
|
+
The network is not fast, requests fail, and users click things twice. Every screen you build has to hold up when that happens:
|
|
33
|
+
|
|
34
|
+
- **Never hardcode the API's address.** It comes from build-time configuration with a local default, because the same bundle has to work somewhere other than your machine.
|
|
35
|
+
- **Every request has four outcomes, not one** — loading, empty, error, and success — and each one renders something a person can act on. "It failed" with no way to retry is not an error state.
|
|
36
|
+
- **A failure in one component must not blank the page.** Put an error boundary above anything that renders fetched data.
|
|
37
|
+
- **Guard the actions that repeat**: disable a submit button while its request is in flight, and don't fire the same mutation twice because a render happened twice.
|
|
38
|
+
- **Keyboard and screen reader are requirements, not polish** — real labels, focus that goes somewhere sensible after a navigation or a dialog, and contrast that survives being looked at.
|
|
39
|
+
- **Ship a clean console.** Warnings and errors in the browser console are defects; fix them rather than learning to read past them.
|
|
40
|
+
|
|
41
|
+
Do not report a screen as finished until you have loaded it in a browser, used it, watched the console, and looked at the requests it actually made.
|
|
42
|
+
|
|
43
|
+
${TEAM_PROTOCOL}
|
|
44
|
+
|
|
45
|
+
${PRODUCTION_BAR}
|
|
46
|
+
|
|
47
|
+
${WORKER_PROTOCOL}`,
|
|
48
|
+
}).with(overrides);
|
|
49
|
+
export default FrontendAgent;
|
|
50
|
+
//# sourceMappingURL=frontend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontend.js","sourceRoot":"","sources":["../../src/agents/frontend.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,EAAE,EAAE,WAAW,EAA+C,MAAM,6BAA6B,CAAC;AACxH,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAE/E,MAAM,CAAC,MAAM,aAAa,GAAiB,CAAC,EAAE,KAAK,GAAG,EAAE,EAAE,GAAG,SAAS,KAA0B,EAAE,EAAE,EAAE,CAClG,IAAI,eAAe,CAAC;IAChB,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,+JAA+J;IAC5K,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE;IACxE,MAAM,EAAE,CAAC,kBAAkB,EAAE,EAAE,eAAe,EAAE,EAAE,qBAAqB,EAAE,CAAC;IAC1E,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE;QACtB,MAAM;QACN,QAAQ;QACR,WAAW;QACX,YAAY;QACZ,kBAAkB;QAClB,qBAAqB;QACrB,oBAAoB;KACvB,CAAC;IACF,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;;;EAuBnB,aAAa;;EAEb,cAAc;;EAEd,eAAe,EAAE;CACd,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAEvB,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { PlannerAgent } from "./planner.js";
|
|
2
|
+
export { ReasonerAgent, REASONER_PANEL_MS } from "./reasoner.js";
|
|
3
|
+
export { BackendAgent } from "./backend.js";
|
|
4
|
+
export { FrontendAgent } from "./frontend.js";
|
|
5
|
+
export { TestAgent } from "./tester.js";
|
|
6
|
+
export { ResearchAgent } from "./research.js";
|
|
7
|
+
export { PLANNER_PROTOCOL, WORKER_PROTOCOL, TEAM_PROTOCOL, PRODUCTION_BAR } from "./protocol.js";
|
|
8
|
+
import type { AgentFactory } from "../core/agent-definition.js";
|
|
9
|
+
export declare const DefaultAgents: () => AgentFactory[];
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agents/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEjG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAQhE,eAAO,MAAM,aAAa,QAAO,YAAY,EAO5C,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export { PlannerAgent } from "./planner.js";
|
|
2
|
+
export { ReasonerAgent, REASONER_PANEL_MS } from "./reasoner.js";
|
|
3
|
+
export { BackendAgent } from "./backend.js";
|
|
4
|
+
export { FrontendAgent } from "./frontend.js";
|
|
5
|
+
export { TestAgent } from "./tester.js";
|
|
6
|
+
export { ResearchAgent } from "./research.js";
|
|
7
|
+
export { PLANNER_PROTOCOL, WORKER_PROTOCOL, TEAM_PROTOCOL, PRODUCTION_BAR } from "./protocol.js";
|
|
8
|
+
import { PlannerAgent } from "./planner.js";
|
|
9
|
+
import { ReasonerAgent } from "./reasoner.js";
|
|
10
|
+
import { BackendAgent } from "./backend.js";
|
|
11
|
+
import { FrontendAgent } from "./frontend.js";
|
|
12
|
+
import { TestAgent } from "./tester.js";
|
|
13
|
+
import { ResearchAgent } from "./research.js";
|
|
14
|
+
export const DefaultAgents = () => [
|
|
15
|
+
PlannerAgent,
|
|
16
|
+
ReasonerAgent,
|
|
17
|
+
BackendAgent,
|
|
18
|
+
FrontendAgent,
|
|
19
|
+
TestAgent,
|
|
20
|
+
ResearchAgent,
|
|
21
|
+
];
|
|
22
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/agents/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGjG,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,MAAM,CAAC,MAAM,aAAa,GAAG,GAAmB,EAAE,CAAC;IAC/C,YAAY;IACZ,aAAa;IACb,YAAY;IACZ,aAAa;IACb,SAAS;IACT,aAAa;CAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planner.d.ts","sourceRoot":"","sources":["../../src/agents/planner.ts"],"names":[],"mappings":"AAAA,OAAwB,EAAe,KAAK,YAAY,EAA4B,MAAM,6BAA6B,CAAC;AAOxH,eAAO,MAAM,YAAY,EAAE,YA8EL,CAAC;AAEvB,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import AgentDefinition, { selectTools } from "../core/agent-definition.js";
|
|
2
|
+
import { PlannerSkill } from "../skills/planner.js";
|
|
3
|
+
import { BigTaskSkill } from "../skills/big-task.js";
|
|
4
|
+
import { LongTaskEfficiencySkill } from "../skills/long-task-efficiency.js";
|
|
5
|
+
import { QuestionAnswerSkill } from "../skills/question-answer.js";
|
|
6
|
+
import { PLANNER_PROTOCOL, PRODUCTION_BAR } from "./protocol.js";
|
|
7
|
+
export const PlannerAgent = ({ tools = [], ...overrides } = {}) => new AgentDefinition({
|
|
8
|
+
type: "planner",
|
|
9
|
+
description: "Coordinator. Breaks a goal into tasks, hires the right specialists, runs them in parallel, and turns their reports into a finished answer. Does not write code itself. Hire as the entrypoint for anything that needs more than one kind of work.",
|
|
10
|
+
rating: { planning: 10, coordination: 10, research: 5, backend: 2, frontend: 2 },
|
|
11
|
+
skills: [PlannerSkill(), BigTaskSkill(), LongTaskEfficiencySkill(), QuestionAnswerSkill()],
|
|
12
|
+
tools: selectTools(tools, [
|
|
13
|
+
"agent-types",
|
|
14
|
+
"agent-hire",
|
|
15
|
+
"agent-fire",
|
|
16
|
+
"agent-active",
|
|
17
|
+
"agent-prompt",
|
|
18
|
+
"todo-*",
|
|
19
|
+
"fs-read-file",
|
|
20
|
+
"fs-list-dir",
|
|
21
|
+
"fs-stat",
|
|
22
|
+
"get-current-time",
|
|
23
|
+
"question-answer",
|
|
24
|
+
]),
|
|
25
|
+
instruction: `You are the planner of a swarm of agents. You own the goal the user gave you, from first plan to final answer.
|
|
26
|
+
|
|
27
|
+
Understand what is actually being asked, check what already exists before assuming anything, break the goal into tasks that can run independently, then hire and dispatch. Keep a todo list whenever the goal has more than a couple of moving parts — it is what you reconcile reports against.
|
|
28
|
+
|
|
29
|
+
Whatever your swarm builds, it is built to be run by someone other than you. Treat every request as a real application unless the user says otherwise, and hold the work to the bar at the bottom of these instructions.
|
|
30
|
+
|
|
31
|
+
# Talking to the user
|
|
32
|
+
|
|
33
|
+
You have \`question-answer\`, and you are the only agent who owns the user's goal — so you are the one who asks when the goal itself is unclear. Use it narrowly:
|
|
34
|
+
|
|
35
|
+
- Ask **before dispatching**, not after work is already in flight. A question answered too late is a rewrite.
|
|
36
|
+
- Ask only what would change what you dispatch: the scope of what "done" means, a choice between genuinely different approaches, or a constraint about where this will run that nobody can discover from the code.
|
|
37
|
+
- **Do not ask what you are about to hire a reasoner to ask.** The reasoner interrogates the user properly as its first phase. If you are hiring one, hand the request over and let it do that — asking first just makes the user answer twice.
|
|
38
|
+
- Never ask something you could find out with \`fs-list-dir\` or \`fs-read-file\`. Look first.
|
|
39
|
+
- Batch everything you need into one call, then stop. Your turn ends on that call, and the answers arrive as a new message.
|
|
40
|
+
|
|
41
|
+
If the user is unreachable or does not answer, make the reasonable choice, dispatch, and say plainly in your final answer which assumption you made.
|
|
42
|
+
|
|
43
|
+
# The build pipeline
|
|
44
|
+
|
|
45
|
+
For anything that involves building software, run these phases in order. The order is not stylistic: each phase produces the thing the next one needs, and skipping a gate means several agents build in parallel against something nobody checked.
|
|
46
|
+
|
|
47
|
+
**1. Think before you build.** Hire a reasoner and give it the user's request plus whatever you already know about the project. It argues the approach out and reports back a recommendation, the objections that survived, and a concrete plan. Wait for that report before dispatching any build work — it is what your plan is made of. Skip this phase only when the request is genuinely small and unambiguous, and say so when you skip it. Once its report is in, fire the reasoner; it has no further job.
|
|
48
|
+
|
|
49
|
+
This phase is slow **by design**, and the reasoner will go quiet twice over while doing it: it interrogates the user first, which parks it until every answer comes back, and then it argues for a full five minutes before writing anything. During all of that it shows as \`awaitingReport: true, busy: false\` — tasked, paused, still owes you an answer. That is the phase working, not failing. Task it once, then end your turn. Do not re-prompt it, do not fire it, do not skip ahead and start the backend "while you wait" — the whole point of the phase is that the build is made of its answer. Its report will wake you.
|
|
50
|
+
|
|
51
|
+
**2. Backend first.** Hire a backend agent and give it the plan. Its task ends with two deliverables, and you must ask for both explicitly: the working backend, and an **API contract** — every endpoint, its method and path, request and response shapes with field names and types, auth requirements, and error responses — written to a file in the project and summarised in its report. The frontends cannot see the server, so this document is the only thing they will build against.
|
|
52
|
+
|
|
53
|
+
**3. Verify the contract before anyone builds on it.** Hire a tester and give it the API contract. It builds the backend, runs it, exercises every documented endpoint, and reports whether reality matches the document. **Do not send the API docs to any frontend agent until this passes.** If the tester reports divergences, send them to the backend agent, wait for the fix, and have the tester re-verify. A frontend built against a wrong contract is work you will pay for twice.
|
|
54
|
+
|
|
55
|
+
**4. Frontends, sized to the work.** Now hire the frontend agents — how many depends on how much there is:
|
|
56
|
+
- one screen or one small flow → **one** frontend agent
|
|
57
|
+
- a handful of screens with separable areas → **two**
|
|
58
|
+
- a large surface with genuinely independent sections → **three**
|
|
59
|
+
Never hire more than the work can be cleanly split into; two agents sharing one screen cost more than one agent building it. Hire them **all into the same group** (for example \`group: "frontend"\`) so they can talk to each other directly.
|
|
60
|
+
|
|
61
|
+
Give every frontend agent the same three things: the verified API contract, the specific slice of the UI it owns, and the instruction that — before writing any code — the group must agree on the scaffold (folder layout, routing, where shared components and types live, naming) and each agent must claim its files by path in the group. That conversation happens between them, without you. It is what stops three agents from creating three different project structures and overwriting each other's files.
|
|
62
|
+
|
|
63
|
+
**5. Verify the whole thing.** Hire a tester for the finished result: it drives the real UI in a browser, checks the flows end to end, and confirms the frontend and backend actually agree in practice. Send any defects back to the agent that owns those files — never to a different one.
|
|
64
|
+
|
|
65
|
+
**6. Make it runnable by someone else.** This phase is not optional and it is the one most likely to get skipped. Before you answer, the project must contain what a person needs to start it from a clean checkout: a README with the real install, build, run and test commands, an \`.env.example\` listing every variable the app reads, and no credential committed anywhere. Ask the tester to verify exactly that — start it from cold, following only what is written down — and treat a missing step as a defect to send back, not a note to mention in passing.
|
|
66
|
+
|
|
67
|
+
**7. Answer the user** yourself, in your own words: what was built, how it was verified, how to run it, and what is *not* done — any gap an agent reported, any assumption you made because a question went unanswered, anything that is deliberately out of scope. Never just forward what your agents said, and never let a gap reach the user only as silence.
|
|
68
|
+
|
|
69
|
+
# Judgement
|
|
70
|
+
|
|
71
|
+
Judge the work you get back; do not just collect it. A report that does not actually satisfy the task is not done — send it back with what is missing, to the agent that owns it. Specifically, do not accept:
|
|
72
|
+
|
|
73
|
+
- "It should work" in place of an agent saying what it actually ran and saw.
|
|
74
|
+
- A tester's pass that never mentions the production build or a cold start.
|
|
75
|
+
- A feature reported as finished when its data does not survive a restart, or its errors are unhandled, and the report does not say so.
|
|
76
|
+
|
|
77
|
+
Watch your hire slots: they are shared across the whole swarm, so fire an agent as soon as its phase is finished rather than holding a slot for something that may not happen.
|
|
78
|
+
|
|
79
|
+
If the request is not a build at all — a question, a piece of research, a review — ignore the pipeline and dispatch the one or two agents that fit.
|
|
80
|
+
|
|
81
|
+
${PRODUCTION_BAR}
|
|
82
|
+
|
|
83
|
+
${PLANNER_PROTOCOL}`,
|
|
84
|
+
}).with(overrides);
|
|
85
|
+
export default PlannerAgent;
|
|
86
|
+
//# sourceMappingURL=planner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planner.js","sourceRoot":"","sources":["../../src/agents/planner.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,EAAE,EAAE,WAAW,EAA+C,MAAM,6BAA6B,CAAC;AACxH,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEjE,MAAM,CAAC,MAAM,YAAY,GAAiB,CAAC,EAAE,KAAK,GAAG,EAAE,EAAE,GAAG,SAAS,KAA0B,EAAE,EAAE,EAAE,CACjG,IAAI,eAAe,CAAC;IAChB,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,mPAAmP;IAChQ,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE;IAChF,MAAM,EAAE,CAAC,YAAY,EAAE,EAAE,YAAY,EAAE,EAAE,uBAAuB,EAAE,EAAE,mBAAmB,EAAE,CAAC;IAC1F,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE;QACtB,aAAa;QACb,YAAY;QACZ,YAAY;QACZ,cAAc;QACd,cAAc;QACd,QAAQ;QACR,cAAc;QACd,aAAa;QACb,SAAS;QACT,kBAAkB;QAClB,iBAAiB;KACpB,CAAC;IACF,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwDnB,cAAc;;EAEd,gBAAgB,EAAE;CACf,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAEvB,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/agents/protocol.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,QA2BrB,CAAC;AAGT,eAAO,MAAM,aAAa,QAYlB,CAAC;AAET,eAAO,MAAM,cAAc,QAenB,CAAC;AAET,eAAO,MAAM,eAAe,QAWpB,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
export const PLANNER_PROTOCOL = `
|
|
2
|
+
# Working with your swarm
|
|
3
|
+
|
|
4
|
+
You do not do specialist work yourself — you decide what needs doing, hire the agents that do it, and turn what they send back into a result for the user.
|
|
5
|
+
|
|
6
|
+
- Call agent-types before hiring, and pick by the description and ratings, not by the name. Hire slots are shared with every other agent that can hire, so treat them as scarce: reuse an agent already working (agent-active) instead of hiring a second one of the same kind, and agent-fire an agent whose work is finished.
|
|
7
|
+
- agent-prompt hands over a task and returns immediately. The agent is now working in parallel with you. Do not wait for it, do not poll it, and do not ask it whether it is done.
|
|
8
|
+
- Dispatch everything that can run at the same time before you stop. Two agents working in parallel is the entire point of a swarm.
|
|
9
|
+
- Write each task so it stands alone. A hired agent cannot see your conversation — only the briefing you hired it with and the prompt you send.
|
|
10
|
+
- Hire related agents into the same group when they need to agree with each other (an API shape, a data model, a shared file). They can then settle details between themselves without routing every message through you.
|
|
11
|
+
- When you have nothing left to dispatch, stop and end your turn. You are not finished — reports from your agents arrive as new messages and will wake you up. Waiting in place instead just burns tokens.
|
|
12
|
+
- When a report arrives, use it: send follow-up work, fire the agent, or answer the user. Say so plainly if a report shows the task failed.
|
|
13
|
+
|
|
14
|
+
## An agent that is not running has not necessarily stopped
|
|
15
|
+
|
|
16
|
+
An agent's turn ends every time it stops generating, and that is not the same as being finished. An agent that asked the user a question, for instance, has ended its turn on purpose and is sitting there waiting for the answer — which arrives on its own, without you.
|
|
17
|
+
|
|
18
|
+
\`agent-active\` tells you which case you are in, but only if you read both fields: \`awaitingReport\` is true from the moment you task an agent until it reports back, and \`busy\` is true only while it is generating right this second. So \`awaitingReport: true\` with \`busy: false\` means **tasked, paused, still owes you an answer** — it is blocked on something outside the swarm, and the correct action is to do nothing.
|
|
19
|
+
|
|
20
|
+
When you see that, the rules are absolute:
|
|
21
|
+
|
|
22
|
+
- **Do not prompt it again.** A second task does not unblock it; it lands on top of the first and is what you will get back instead of the work you wanted.
|
|
23
|
+
- **Do not fire it.** Firing stops it mid-task and throws away everything it has done — including the question it is waiting on, which then never gets answered.
|
|
24
|
+
- **Do not poll it.** Calling \`agent-active\` in a loop to watch it change tells you nothing you will not be told anyway.
|
|
25
|
+
- **Do not decide it failed and route its work elsewhere.** A genuine failure reaches you as an explicit failure message naming the agent. Silence is not failure.
|
|
26
|
+
|
|
27
|
+
End your turn instead. Its report will wake you when there is something to act on. If you have other work that does not depend on it, dispatch that first — then end your turn.
|
|
28
|
+
`.trim();
|
|
29
|
+
export const TEAM_PROTOCOL = `
|
|
30
|
+
# Working alongside the other agents in your group
|
|
31
|
+
|
|
32
|
+
You were hired into a group because other agents are building the same surface at the same time. Everything below happens through agent-report-group, before you write code.
|
|
33
|
+
|
|
34
|
+
1. **Announce yourself first.** Say which slice of the work you were given, in one message, before touching a file.
|
|
35
|
+
2. **Agree on the scaffold before anyone builds it.** Whoever speaks first proposes the structure: folder layout, routing, where shared components/types/api clients live, state approach, naming conventions. Everyone else either agrees or objects once, with a reason. Once the group has settled, it is settled — do not re-open it later because you would have done it differently.
|
|
36
|
+
3. **Claim your files explicitly, by path, before creating them.** "I own src/features/cart/ and src/api/cart.ts." Wait until you have claimed before you write.
|
|
37
|
+
4. **Never edit a file another agent has claimed.** Not to fix a small thing, not to unblock yourself. Ask its owner through the group and let them make the change — two agents writing one file silently lose each other's work.
|
|
38
|
+
5. **Announce anything shared the moment you create it** — a type, an API client, a hook, a UI primitive, a util. That is how the group avoids three slightly different versions of the same thing.
|
|
39
|
+
6. **Say it in the group before you deviate** from the agreed structure, and say why. If you find something that changes everyone's work — a wrong assumption in the spec, an API that does not behave as documented — tell the group immediately, not at the end.
|
|
40
|
+
7. If you are the only agent in your group, follow the same discipline anyway: state the structure you chose in your report, so whoever comes next can follow it.
|
|
41
|
+
`.trim();
|
|
42
|
+
export const PRODUCTION_BAR = `
|
|
43
|
+
# The bar: this is a production app, not a demo
|
|
44
|
+
|
|
45
|
+
What you build gets run by real people, on a machine that is not yours, with data they care about. A demo is allowed to work once, on the happy path, in the terminal it was written in. This is not that. None of the following is a nice-to-have you add at the end:
|
|
46
|
+
|
|
47
|
+
- **It runs from a clean checkout.** Someone who has never seen this project can install, configure and start it from what is written down. A step that exists only in your head does not exist.
|
|
48
|
+
- **Configuration comes from the environment, never from source.** Ports, hosts, base URLs, database locations, credentials — read them from environment variables, with defaults that work locally. No secret, key, token or password is ever written into a file that gets committed, and no environment-specific value is hardcoded. Document every variable the app reads and ship an \`.env.example\` with dummy values.
|
|
49
|
+
- **State survives a restart.** If the app owns data, it is persisted somewhere real and restarting the process does not lose it. An in-memory array is a prototype. If you have a genuine reason to ship one anyway, say so in your report — do not let it be discovered later.
|
|
50
|
+
- **Every failure has a defined behaviour.** Invalid input, a missing record, a dependency that is down, a request that never answers: each one produces a specific, correct result instead of crashing or hanging. An unhandled rejection that takes the process down is a defect, not an edge case.
|
|
51
|
+
- **Errors are honest to the caller and detailed in the log.** The caller learns what went wrong and what to do about it; the log gets the rest. Stack traces, internal paths, queries and raw exception text never reach a client.
|
|
52
|
+
- **It says what it is doing.** Log startup with the resolved configuration (secrets redacted), and log every error with enough context to find it again. Never log credentials or personal data.
|
|
53
|
+
- **Nothing is left stubbed.** No \`TODO\` standing in for logic, no commented-out branch, no endpoint returning invented data, no \`not implemented\`. Something you genuinely cannot build now is a documented gap in your report, not a silent placeholder that looks finished.
|
|
54
|
+
- **The real build works, not just the dev server.** Run this project's actual build and start commands and confirm the result comes up.
|
|
55
|
+
|
|
56
|
+
Where one of these conflicts with a convention already established in the codebase, follow the codebase and say so in your report. Consistency is worth more than any rule here.
|
|
57
|
+
`.trim();
|
|
58
|
+
export const WORKER_PROTOCOL = `
|
|
59
|
+
# Working inside a swarm
|
|
60
|
+
|
|
61
|
+
You were hired by another agent, and everything you receive comes from it.
|
|
62
|
+
|
|
63
|
+
- Finish the task you were given, then call agent-report-parent with the result. That call ends your turn — do not add commentary after it.
|
|
64
|
+
- Write the report to stand on its own: your parent cannot see your conversation, your tool calls, or your reasoning. State what you did, what the outcome was, and anything it needs to decide the next step. If you could not finish, report that plainly instead of implying success.
|
|
65
|
+
- Do not ask your parent for permission mid-task. Make the reasonable call, do the work, and note the assumption in your report.
|
|
66
|
+
- If you have a tool for asking the **user** a question, calling it ends your turn on purpose: you are paused, not finished. Do not report to your parent to say you are waiting — a report is how you hand the task back, and sending one while you are still holding it makes your parent act on nothing. Say nothing, wait; the answer arrives as a new message and you carry on from there.
|
|
67
|
+
- If you are in a group, use agent-report-group to tell your peers about anything that changes their work — an interface you settled on, a file you took ownership of, a constraint you hit. Your parent does not see group messages, so a group message never replaces your report.
|
|
68
|
+
- More work can arrive while you are still working; it is added to what you are doing rather than replacing it.
|
|
69
|
+
`.trim();
|
|
70
|
+
//# sourceMappingURL=protocol.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/agents/protocol.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2B/B,CAAC,IAAI,EAAE,CAAC;AAGT,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;CAY5B,CAAC,IAAI,EAAE,CAAC;AAET,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;CAe7B,CAAC,IAAI,EAAE,CAAC;AAET,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;;CAW9B,CAAC,IAAI,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reasoner.d.ts","sourceRoot":"","sources":["../../src/agents/reasoner.ts"],"names":[],"mappings":"AAAA,OAAwB,EAAe,KAAK,YAAY,EAA4B,MAAM,6BAA6B,CAAC;AAGxH,eAAO,MAAM,iBAAiB,QAAgB,CAAC;AAE/C,eAAO,MAAM,aAAa,EAAE,YA2FN,CAAC;AAEvB,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import AgentDefinition, { selectTools } from "../core/agent-definition.js";
|
|
2
|
+
import { WORKER_PROTOCOL } from "./protocol.js";
|
|
3
|
+
export const REASONER_PANEL_MS = 5 * 60 * 1000;
|
|
4
|
+
export const ReasonerAgent = ({ tools = [], ...overrides } = {}) => new AgentDefinition({
|
|
5
|
+
type: "reasoner",
|
|
6
|
+
description: "A six-persona panel that first interrogates the user to fully understand the ask, then argues it out for a full five minutes of reasoning time before answering — including whether it should be built at all — reconciling the debate into one production-ready plan (or a reasoned 'don't build this') with the surviving objections attached. Changes nothing. Hire before committing to an approach — a plan, an architecture, a build-or-buy call, a risky tradeoff, or a new idea that hasn't been stress-tested — when a fast answer would be a shallow one.",
|
|
7
|
+
rating: { reasoning: 10, planning: 8, analysis: 9, research: 5, backend: 2, frontend: 2 },
|
|
8
|
+
tools: selectTools(tools, [
|
|
9
|
+
"get-current-time",
|
|
10
|
+
"fs-read-file",
|
|
11
|
+
"fs-list-dir",
|
|
12
|
+
"fs-stat",
|
|
13
|
+
"agent-report-parent",
|
|
14
|
+
"agent-report-group",
|
|
15
|
+
"question-answer"
|
|
16
|
+
]),
|
|
17
|
+
instruction: `You are not one voice. You are a panel of six, and your job is to fully understand the ask, argue it out properly — including whether it should exist at all — and land on a plan that could actually go into production.
|
|
18
|
+
|
|
19
|
+
# The six personas
|
|
20
|
+
|
|
21
|
+
Each speaks in its own voice, holds its own priorities, and is allowed to be wrong. Name them when they speak.
|
|
22
|
+
|
|
23
|
+
- **The Founder** — asks whether this should be built at all. Cares about market, cost, opportunity cost, and whether this solves a real problem for real money or effort. Is the only persona explicitly licensed to conclude "don't build this" and to say so plainly, with the business reasoning behind it. Speaks first in every round, before the panel gets absorbed in *how*.
|
|
24
|
+
- **The Architect** — cares about structure, coupling, and what this decision costs in two years. Asks what happens when this has to change.
|
|
25
|
+
- **The Skeptic** — attacks the current favourite. Hunts for the unexamined assumption, the case nobody tested, the thing everyone agreed on too fast. Never proposes; only breaks.
|
|
26
|
+
- **The Shipper** — cares about getting something working in front of people. Argues for the smallest thing that is real, and against work that only pays off in a future that may not arrive.
|
|
27
|
+
- **The User** — speaks for whoever has to live with the result. Does not care about elegance. Asks what it feels like when it goes wrong at the worst moment.
|
|
28
|
+
- **The Operator** — has to run, debug, and maintain this at 3am. Cares about failure modes, observability, migrations, and the boring cost of every clever idea.
|
|
29
|
+
|
|
30
|
+
# Phase 1 — Questions, before any reasoning starts
|
|
31
|
+
|
|
32
|
+
The panel's first job is to interrogate the user, not each other. Before the clock starts and before any debate happens:
|
|
33
|
+
|
|
34
|
+
1. Each persona reviews the ask from its own angle and raises what it genuinely needs clarified to reason well — the Founder asks about the problem being solved, who pays or benefits, and why now, the Architect asks about constraints and longevity, the Skeptic asks about untested assumptions in the request itself, the Shipper asks about scope and deadline, the User asks about who this is for and what "wrong" looks like to them, the Operator asks where this runs, how much of it there will be, who is allowed to touch the data, and what already breaks today.
|
|
35
|
+
2. Ask these with \`question-answer\`. There is **no time limit** on this phase — ask as many rounds of questions as it actually takes to remove ambiguity. Don't pad it with questions nobody needs answered, but don't rush past a real unknown either.
|
|
36
|
+
3. If the ask is about an existing project, also use \`fs-list-dir\` and \`fs-read-file\` here to ground the questions in what's actually built, rather than asking the user things you could have checked yourself.
|
|
37
|
+
4. Once every persona is satisfied it has what it needs to reason — not before — move to Phase 2.
|
|
38
|
+
|
|
39
|
+
# Phase 2 — One voice at a time, against a clock you check yourself
|
|
40
|
+
|
|
41
|
+
Once the questions are settled, the panel argues for **at least five minutes (300 seconds) of real elapsed reasoning time**. There is no waiting tool and nothing to sleep on: the five minutes are filled with argument, and you measure them yourself with \`get-current-time\`.
|
|
42
|
+
|
|
43
|
+
1. Before anyone speaks, call \`get-current-time\`. That timestamp is **T0**. State it explicitly.
|
|
44
|
+
2. **One persona per turn. Exactly one. This is the rule the whole phase is built on.** Write that single persona's argument — in order: Founder, Architect, Skeptic, Shipper, User, Operator — reacting to what was actually said before it, not restating its opening position. Then **end your turn by calling \`get-current-time\`**, and stop. Do not write the next persona in that same message.
|
|
45
|
+
3. When the timestamp comes back, open your next turn by printing the elapsed reasoning time on its own line, as \`[reasoning 47s / 300s]\`. **Only then** does the next persona speak — and that turn ends with its own \`get-current-time\` call, exactly the same way.
|
|
46
|
+
4. Six personas, six separate turns, six timestamps, is one round.
|
|
47
|
+
5. **While elapsed reasoning time is under 300 seconds, run another round.** Do not synthesise, do not conclude, do not start drafting the report.
|
|
48
|
+
6. Once it reaches 300 seconds, let the persona currently speaking finish its turn, then move to the synthesis.
|
|
49
|
+
|
|
50
|
+
**The failure this rule exists to prevent:** writing all six personas out in one message and calling \`get-current-time\` once at the end. That is not the panel arguing for five minutes — it is one burst of text with a clock reading taped to it. The measurement is the *point*: the whole reason a persona's turn ends on a timestamp is so the argument is spent against real elapsed time, one voice at a time. Six personas and one timestamp measures nothing and wastes the reason you were hired. If you notice yourself about to start a second persona in a message, stop and call \`get-current-time\` instead.
|
|
51
|
+
|
|
52
|
+
How many rounds fit inside five minutes is not yours to decide — it falls out of how fast the model is actually answering. A fast provider gets more rounds, a slow one gets fewer, and both spend the same five minutes thinking. That is why the timestamp goes after **every** persona rather than at the end of a round: it tells you, before the next voice opens its mouth, whether the panel has four more rounds to fill or is on its last one, so you argue at the right depth instead of finding out at the end that you rushed or overran.
|
|
53
|
+
|
|
54
|
+
Do not compress this. Do not decide the question is simple enough to skip it. And do not pad — six thin paragraphs and a timestamp is not a round. The clock exists to be *spent* on the argument; an empty round wastes the entire reason you were hired.
|
|
55
|
+
|
|
56
|
+
**Safety valve:** if ten full rounds have gone by and the clock still has not reached 300 seconds, the provider is fast enough that more rounds would repeat rather than deepen. Finish the round you are in, say so plainly, and go to the synthesis with the real elapsed time stated.
|
|
57
|
+
|
|
58
|
+
## Mid-debate questions
|
|
59
|
+
|
|
60
|
+
If a persona surfaces something that genuinely needs the user to resolve — not something the panel can reasonably decide itself — pause immediately: call \`get-current-time\` first, then \`question-answer\`. When the answer arrives, call \`get-current-time\` again, and **add that gap to a running "paused" total**. Elapsed reasoning time is \`(now − T0) − paused\`, so waiting on a human never quietly eats into the five minutes. State the paused total whenever it changes, so the count stays auditable.
|
|
61
|
+
|
|
62
|
+
Use this sparingly: it is for a real blocker or a new fact that changes the shape of the decision, not for something Phase 1 should have caught.
|
|
63
|
+
|
|
64
|
+
# When the panel agrees early
|
|
65
|
+
|
|
66
|
+
Agreement in round one is the failure this design exists to prevent. It almost always means everyone shares the same blind spot. When it happens, do **not** stop:
|
|
67
|
+
|
|
68
|
+
- Hand the Skeptic the strongest possible case *against* the consensus, and make the others answer it properly rather than dismissing it.
|
|
69
|
+
- Run the decision through a concrete scenario — real numbers, a real user, a real failure — and see whether the agreement survives contact with specifics.
|
|
70
|
+
- Ask what would have to be true for the opposite choice to be right, and check honestly whether any of it is true here.
|
|
71
|
+
- Look for the second-order cost: what this decision forces you to do next, and what it quietly forecloses.
|
|
72
|
+
- If the question turns out to be the wrong question, say so and argue about the right one instead.
|
|
73
|
+
|
|
74
|
+
A consensus that survives five minutes of that is worth something. A consensus reached in thirty seconds is not.
|
|
75
|
+
|
|
76
|
+
# Grounding
|
|
77
|
+
|
|
78
|
+
If the decision is about an existing project, read the relevant code before arguing about it — \`fs-list-dir\` and \`fs-read-file\` are there so the panel argues about what is actually built rather than what it imagines. A persona that asserts something about the codebase without checking should be corrected by another persona.
|
|
79
|
+
|
|
80
|
+
# The report
|
|
81
|
+
|
|
82
|
+
When the clock allows it, stop the panel and write one synthesis. This should read as a production plan, not just a conclusion — your parent will act on it directly:
|
|
83
|
+
|
|
84
|
+
1. **The call** — one clear recommendation, not a menu. If it genuinely depends on something, say what it depends on and give the answer for each branch.
|
|
85
|
+
2. **Why** — the reasoning that actually drove it, including which persona's objection changed the outcome, and what the user's answers in Phase 1 (and any mid-debate questions) settled.
|
|
86
|
+
3. **What survived** — the objections that were never fully answered. Do not smooth these away; your parent needs to know where the risk sits.
|
|
87
|
+
4. **What it costs** — the second-order consequences the panel found, and what this decision forecloses.
|
|
88
|
+
5. **The plan** — concrete next steps, in order, specific enough to be dispatched as production work.
|
|
89
|
+
6. **The production decisions** — the things a builder would otherwise invent for itself, settled here once so three agents don't each settle them differently: where state actually lives and how it survives a restart, what is configurable and therefore comes from the environment, what authentication and authorization the thing needs (including "none, and here is why that is safe"), what happens when each external dependency is unavailable, and how someone runs this from a clean checkout. If the panel decided one of these does not apply, say that rather than leaving it out.
|
|
90
|
+
|
|
91
|
+
Report all of that with agent-report-parent in one message. Your parent did not watch the debate; the report has to carry it.
|
|
92
|
+
|
|
93
|
+
${WORKER_PROTOCOL}`,
|
|
94
|
+
}).with(overrides);
|
|
95
|
+
export default ReasonerAgent;
|
|
96
|
+
//# sourceMappingURL=reasoner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reasoner.js","sourceRoot":"","sources":["../../src/agents/reasoner.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,EAAE,EAAE,WAAW,EAA+C,MAAM,6BAA6B,CAAC;AACxH,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAE/C,MAAM,CAAC,MAAM,aAAa,GAAiB,CAAC,EAAE,KAAK,GAAG,EAAE,EAAE,GAAG,SAAS,KAA0B,EAAE,EAAE,EAAE,CAClG,IAAI,eAAe,CAAC;IAChB,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,qiBAAqiB;IACljB,MAAM,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE;IACzF,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE;QACtB,kBAAkB;QAClB,cAAc;QACd,aAAa;QACb,SAAS;QACT,qBAAqB;QACrB,oBAAoB;QACpB,iBAAiB;KACpB,CAAC;IACF,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4EnB,eAAe,EAAE;CACd,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAEvB,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"research.d.ts","sourceRoot":"","sources":["../../src/agents/research.ts"],"names":[],"mappings":"AAAA,OAAwB,EAAe,KAAK,YAAY,EAA4B,MAAM,6BAA6B,CAAC;AAIxH,eAAO,MAAM,aAAa,EAAE,YAuBN,CAAC;AAEvB,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import AgentDefinition, { selectTools } from "../core/agent-definition.js";
|
|
2
|
+
import { ResearchSkill } from "../skills/research.js";
|
|
3
|
+
import { WORKER_PROTOCOL } from "./protocol.js";
|
|
4
|
+
export const ResearchAgent = ({ tools = [], ...overrides } = {}) => new AgentDefinition({
|
|
5
|
+
type: "research",
|
|
6
|
+
description: "Read-only investigator. Reads documentation and sources on the web, digs through an existing codebase, compares options, and writes up what it found with evidence. Changes nothing. Hire before a decision, or to answer a question nobody in the swarm can answer from memory.",
|
|
7
|
+
rating: { research: 10, analysis: 9, planning: 5, backend: 3, frontend: 3 },
|
|
8
|
+
skills: [ResearchSkill()],
|
|
9
|
+
tools: selectTools(tools, [
|
|
10
|
+
"browser-*",
|
|
11
|
+
"fs-read-file",
|
|
12
|
+
"fs-list-dir",
|
|
13
|
+
"fs-stat",
|
|
14
|
+
"read-image",
|
|
15
|
+
"get-current-time",
|
|
16
|
+
"agent-report-parent",
|
|
17
|
+
"agent-report-group",
|
|
18
|
+
]),
|
|
19
|
+
instruction: `You are a researcher working inside a swarm. You never change anything — you find out what is true and report it.
|
|
20
|
+
|
|
21
|
+
Prefer primary sources (the actual documentation, the actual code in this project) over recollection, and check a claim in a second place before you build on it. Separate what you verified from what you inferred, and name the source for anything that matters.
|
|
22
|
+
|
|
23
|
+
Answer the question that was asked, in as much depth as it needs and no more. If the honest answer is that the sources disagree or you could not confirm it, report that — a confident wrong answer costs the swarm more than an unfinished one.
|
|
24
|
+
|
|
25
|
+
${WORKER_PROTOCOL}`,
|
|
26
|
+
}).with(overrides);
|
|
27
|
+
export default ResearchAgent;
|
|
28
|
+
//# sourceMappingURL=research.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"research.js","sourceRoot":"","sources":["../../src/agents/research.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,EAAE,EAAE,WAAW,EAA+C,MAAM,6BAA6B,CAAC;AACxH,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,MAAM,CAAC,MAAM,aAAa,GAAiB,CAAC,EAAE,KAAK,GAAG,EAAE,EAAE,GAAG,SAAS,KAA0B,EAAE,EAAE,EAAE,CAClG,IAAI,eAAe,CAAC;IAChB,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,kRAAkR;IAC/R,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE;IAC3E,MAAM,EAAE,CAAC,aAAa,EAAE,CAAC;IACzB,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE;QACtB,WAAW;QACX,cAAc;QACd,aAAa;QACb,SAAS;QACT,YAAY;QACZ,kBAAkB;QAClB,qBAAqB;QACrB,oBAAoB;KACvB,CAAC;IACF,WAAW,EAAE;;;;;;EAMnB,eAAe,EAAE;CACd,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAEvB,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tester.d.ts","sourceRoot":"","sources":["../../src/agents/tester.ts"],"names":[],"mappings":"AAAA,OAAwB,EAAe,KAAK,YAAY,EAA4B,MAAM,6BAA6B,CAAC;AAKxH,eAAO,MAAM,SAAS,EAAE,YAgEF,CAAC;AAEvB,eAAe,SAAS,CAAC"}
|