agent-relay 2.2.23 ā 2.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/dist/index.cjs +199 -3
- package/package.json +64 -21
- package/packages/acp-bridge/package.json +2 -2
- package/packages/api-types/package.json +1 -1
- package/packages/benchmark/package.json +5 -5
- package/packages/bridge/package.json +7 -7
- package/packages/cli-tester/package.json +1 -1
- package/packages/config/package.json +2 -2
- package/packages/continuity/package.json +2 -2
- package/packages/daemon/dist/cloud-sync.d.ts +13 -1
- package/packages/daemon/dist/cloud-sync.d.ts.map +1 -1
- package/packages/daemon/dist/cloud-sync.js +169 -5
- package/packages/daemon/dist/cloud-sync.js.map +1 -1
- package/packages/daemon/dist/server.d.ts +5 -0
- package/packages/daemon/dist/server.d.ts.map +1 -1
- package/packages/daemon/dist/server.js +50 -0
- package/packages/daemon/dist/server.js.map +1 -1
- package/packages/daemon/package.json +12 -12
- package/packages/daemon/src/cloud-sync.ts +201 -5
- package/packages/daemon/src/server.ts +61 -0
- package/packages/hooks/package.json +4 -4
- package/packages/mcp/package.json +5 -5
- package/packages/memory/package.json +2 -2
- package/packages/policy/package.json +2 -2
- package/packages/protocol/package.json +1 -1
- package/packages/resiliency/package.json +1 -1
- package/packages/sdk/dist/client.d.ts +1 -1
- package/packages/sdk/dist/client.js +2 -2
- package/packages/sdk/package.json +3 -3
- package/packages/sdk/src/client.ts +2 -2
- package/packages/sdk-ts/README.md +65 -0
- package/packages/sdk-ts/dist/__tests__/integration.test.d.ts +2 -0
- package/packages/sdk-ts/dist/__tests__/integration.test.d.ts.map +1 -0
- package/packages/sdk-ts/dist/__tests__/integration.test.js +139 -0
- package/packages/sdk-ts/dist/__tests__/integration.test.js.map +1 -0
- package/packages/sdk-ts/dist/__tests__/quickstart.test.d.ts +2 -0
- package/packages/sdk-ts/dist/__tests__/quickstart.test.d.ts.map +1 -0
- package/packages/sdk-ts/dist/__tests__/quickstart.test.js +176 -0
- package/packages/sdk-ts/dist/__tests__/quickstart.test.js.map +1 -0
- package/packages/sdk-ts/dist/browser.d.ts +16 -0
- package/packages/sdk-ts/dist/browser.d.ts.map +1 -0
- package/packages/sdk-ts/dist/browser.js +19 -0
- package/packages/sdk-ts/dist/browser.js.map +1 -0
- package/packages/sdk-ts/dist/client.d.ts +91 -0
- package/packages/sdk-ts/dist/client.d.ts.map +1 -0
- package/packages/sdk-ts/dist/client.js +360 -0
- package/packages/sdk-ts/dist/client.js.map +1 -0
- package/packages/sdk-ts/dist/consensus-helpers.d.ts +103 -0
- package/packages/sdk-ts/dist/consensus-helpers.d.ts.map +1 -0
- package/packages/sdk-ts/dist/consensus-helpers.js +147 -0
- package/packages/sdk-ts/dist/consensus-helpers.js.map +1 -0
- package/packages/sdk-ts/dist/consensus.d.ts +72 -0
- package/packages/sdk-ts/dist/consensus.d.ts.map +1 -0
- package/packages/sdk-ts/dist/consensus.js +378 -0
- package/packages/sdk-ts/dist/consensus.js.map +1 -0
- package/packages/sdk-ts/dist/examples/demo.d.ts +2 -0
- package/packages/sdk-ts/dist/examples/demo.d.ts.map +1 -0
- package/packages/sdk-ts/dist/examples/demo.js +63 -0
- package/packages/sdk-ts/dist/examples/demo.js.map +1 -0
- package/packages/sdk-ts/dist/examples/example.d.ts +2 -0
- package/packages/sdk-ts/dist/examples/example.d.ts.map +1 -0
- package/packages/sdk-ts/dist/examples/example.js +80 -0
- package/packages/sdk-ts/dist/examples/example.js.map +1 -0
- package/packages/sdk-ts/dist/examples/quickstart.d.ts +2 -0
- package/packages/sdk-ts/dist/examples/quickstart.d.ts.map +1 -0
- package/packages/sdk-ts/dist/examples/quickstart.js +56 -0
- package/packages/sdk-ts/dist/examples/quickstart.js.map +1 -0
- package/packages/sdk-ts/dist/examples/ralph-loop.d.ts +2 -0
- package/packages/sdk-ts/dist/examples/ralph-loop.d.ts.map +1 -0
- package/packages/sdk-ts/dist/examples/ralph-loop.js +281 -0
- package/packages/sdk-ts/dist/examples/ralph-loop.js.map +1 -0
- package/packages/sdk-ts/dist/index.d.ts +9 -0
- package/packages/sdk-ts/dist/index.d.ts.map +1 -0
- package/packages/sdk-ts/dist/index.js +9 -0
- package/packages/sdk-ts/dist/index.js.map +1 -0
- package/packages/sdk-ts/dist/logs.d.ts +47 -0
- package/packages/sdk-ts/dist/logs.d.ts.map +1 -0
- package/packages/sdk-ts/dist/logs.js +137 -0
- package/packages/sdk-ts/dist/logs.js.map +1 -0
- package/packages/sdk-ts/dist/protocol.d.ts +249 -0
- package/packages/sdk-ts/dist/protocol.d.ts.map +1 -0
- package/packages/sdk-ts/dist/protocol.js +2 -0
- package/packages/sdk-ts/dist/protocol.js.map +1 -0
- package/packages/sdk-ts/dist/pty.d.ts +8 -0
- package/packages/sdk-ts/dist/pty.d.ts.map +1 -0
- package/packages/sdk-ts/dist/pty.js +14 -0
- package/packages/sdk-ts/dist/pty.js.map +1 -0
- package/packages/sdk-ts/dist/relay.d.ts +118 -0
- package/packages/sdk-ts/dist/relay.d.ts.map +1 -0
- package/packages/sdk-ts/dist/relay.js +355 -0
- package/packages/sdk-ts/dist/relay.js.map +1 -0
- package/packages/sdk-ts/dist/relaycast.d.ts +57 -0
- package/packages/sdk-ts/dist/relaycast.d.ts.map +1 -0
- package/packages/sdk-ts/dist/relaycast.js +110 -0
- package/packages/sdk-ts/dist/relaycast.js.map +1 -0
- package/packages/sdk-ts/dist/shadow.d.ts +100 -0
- package/packages/sdk-ts/dist/shadow.d.ts.map +1 -0
- package/packages/sdk-ts/dist/shadow.js +174 -0
- package/packages/sdk-ts/dist/shadow.js.map +1 -0
- package/packages/sdk-ts/package.json +75 -0
- package/packages/sdk-ts/scripts/bundle-agent-relay.mjs +53 -0
- package/packages/sdk-ts/src/__tests__/integration.test.ts +170 -0
- package/packages/sdk-ts/src/__tests__/quickstart.test.ts +198 -0
- package/packages/sdk-ts/src/browser.ts +57 -0
- package/packages/sdk-ts/src/client.ts +491 -0
- package/packages/sdk-ts/src/consensus-helpers.ts +253 -0
- package/packages/sdk-ts/src/consensus.ts +506 -0
- package/packages/sdk-ts/src/examples/demo.ts +88 -0
- package/packages/sdk-ts/src/examples/example.ts +91 -0
- package/packages/sdk-ts/src/examples/quickstart.ts +72 -0
- package/packages/sdk-ts/src/examples/ralph-loop.ts +352 -0
- package/packages/sdk-ts/src/examples/sample-prd.json +37 -0
- package/packages/sdk-ts/src/index.ts +8 -0
- package/packages/sdk-ts/src/logs.ts +163 -0
- package/packages/sdk-ts/src/protocol.ts +266 -0
- package/packages/sdk-ts/src/pty.ts +16 -0
- package/packages/sdk-ts/src/relay.ts +454 -0
- package/packages/sdk-ts/src/relaycast.ts +143 -0
- package/packages/sdk-ts/src/shadow.ts +230 -0
- package/packages/sdk-ts/tsconfig.json +16 -0
- package/packages/spawner/package.json +1 -1
- package/packages/state/package.json +1 -1
- package/packages/storage/package.json +2 -2
- package/packages/telemetry/package.json +1 -1
- package/packages/trajectory/package.json +2 -2
- package/packages/user-directory/package.json +2 -2
- package/packages/utils/package.json +3 -3
- package/packages/wrapper/dist/client.js +1 -1
- package/packages/wrapper/package.json +6 -6
- package/packages/wrapper/src/client.test.ts +1 -1
- package/packages/wrapper/src/client.ts +1 -1
- package/packages/mcp/SPEC.md +0 -1922
- package/packages/mcp/STAFFING_PLAN.md +0 -294
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runnable demo ā shows the full AgentRelay message flow with real output.
|
|
3
|
+
* Uses `cat` as a universally-available stand-in for agent CLIs.
|
|
4
|
+
*
|
|
5
|
+
* Run:
|
|
6
|
+
* npm run build && npm run demo
|
|
7
|
+
*/
|
|
8
|
+
import { AgentRelay } from "../relay.js";
|
|
9
|
+
const relay = new AgentRelay({ env: process.env });
|
|
10
|
+
// āā Event hooks āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
11
|
+
relay.onMessageReceived = (message) => {
|
|
12
|
+
console.log(` šØ received ā from=${message.from} to=${message.to} text="${message.text}"`);
|
|
13
|
+
};
|
|
14
|
+
relay.onMessageSent = (message) => {
|
|
15
|
+
console.log(` š¤ sent ā from=${message.from} to=${message.to} text="${message.text}"`);
|
|
16
|
+
};
|
|
17
|
+
relay.onAgentSpawned = (agent) => {
|
|
18
|
+
console.log(` š¢ spawned ā ${agent.name} (${agent.runtime})`);
|
|
19
|
+
};
|
|
20
|
+
relay.onAgentReleased = (agent) => {
|
|
21
|
+
console.log(` š“ released ā ${agent.name}`);
|
|
22
|
+
};
|
|
23
|
+
relay.onAgentExited = (agent) => {
|
|
24
|
+
console.log(` āŖ exited ā ${agent.name}`);
|
|
25
|
+
};
|
|
26
|
+
// āā Spawn agents āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
27
|
+
console.log("\nāāā Spawning agents āāā\n");
|
|
28
|
+
const [agentA, agentB] = await Promise.all([
|
|
29
|
+
relay.spawnPty({ name: "AgentA", cli: "claude", args: ["--print"], channels: ["general"] }),
|
|
30
|
+
relay.spawnPty({ name: "AgentB", cli: "claude", args: ["--print"], channels: ["general"] }),
|
|
31
|
+
]);
|
|
32
|
+
// āā Send messages āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
33
|
+
console.log("\nāāā Sending messages āāā\n");
|
|
34
|
+
const human = relay.human({ name: "System" });
|
|
35
|
+
await human.sendMessage({ to: agentA.name, text: "Hello AgentA, welcome!" });
|
|
36
|
+
await human.sendMessage({ to: agentB.name, text: "Hello AgentB, welcome!" });
|
|
37
|
+
// Agent-to-agent messaging
|
|
38
|
+
await agentA.sendMessage({ to: agentB.name, text: "Hey B, got a task for you" });
|
|
39
|
+
await agentB.sendMessage({ to: agentA.name, text: "On it!" });
|
|
40
|
+
// Threaded conversation
|
|
41
|
+
const thread = await human.sendMessage({ to: agentA.name, text: "Status update?" });
|
|
42
|
+
await agentA.sendMessage({ to: human.name, text: "All good!", threadId: thread.eventId });
|
|
43
|
+
// Priority messages
|
|
44
|
+
await human.sendMessage({ to: agentA.name, text: "Critical alert!", priority: 0 });
|
|
45
|
+
await human.sendMessage({ to: agentB.name, text: "Low priority FYI", priority: 4 });
|
|
46
|
+
// Small delay to let events propagate
|
|
47
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
48
|
+
// āā List agents āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
49
|
+
console.log("\nāāā Active agents āāā\n");
|
|
50
|
+
const agents = await relay.listAgents();
|
|
51
|
+
for (const agent of agents) {
|
|
52
|
+
console.log(` ⢠${agent.name} runtime=${agent.runtime} channels=[${agent.channels}]`);
|
|
53
|
+
}
|
|
54
|
+
// āā Release all āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
55
|
+
console.log("\nāāā Releasing agents āāā\n");
|
|
56
|
+
for (const agent of agents) {
|
|
57
|
+
await agent.release();
|
|
58
|
+
}
|
|
59
|
+
await new Promise((r) => setTimeout(r, 300));
|
|
60
|
+
// āā Shutdown āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
61
|
+
await relay.shutdown();
|
|
62
|
+
console.log("\nāāā Done āāā\n");
|
|
63
|
+
//# sourceMappingURL=demo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demo.js","sourceRoot":"","sources":["../../src/examples/demo.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"example.d.ts","sourceRoot":"","sources":["../../src/examples/example.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { AgentRelayClient } from "../client.js";
|
|
2
|
+
function parseArgs(raw) {
|
|
3
|
+
if (!raw || raw.trim() === "") {
|
|
4
|
+
return [];
|
|
5
|
+
}
|
|
6
|
+
return raw
|
|
7
|
+
.split(" ")
|
|
8
|
+
.map((part) => part.trim())
|
|
9
|
+
.filter((part) => part.length > 0);
|
|
10
|
+
}
|
|
11
|
+
function now() {
|
|
12
|
+
return new Date().toISOString();
|
|
13
|
+
}
|
|
14
|
+
async function main() {
|
|
15
|
+
const codexCmd = process.env.CODEX_CMD ?? "codex";
|
|
16
|
+
const codexArgs = parseArgs(process.env.CODEX_ARGS);
|
|
17
|
+
const channel = process.env.RELAY_CHANNEL ?? "general";
|
|
18
|
+
const xName = process.env.AGENT_X_NAME ?? "CodexX";
|
|
19
|
+
const oName = process.env.AGENT_O_NAME ?? "CodexO";
|
|
20
|
+
const client = await AgentRelayClient.start({
|
|
21
|
+
channels: [channel],
|
|
22
|
+
});
|
|
23
|
+
const stopLogging = client.onEvent((event) => {
|
|
24
|
+
console.log(`[${now()}] event`, JSON.stringify(event));
|
|
25
|
+
});
|
|
26
|
+
const stopStderrLogging = client.onBrokerStderr((line) => {
|
|
27
|
+
console.log(`[${now()}] broker:stderr ${line}`);
|
|
28
|
+
});
|
|
29
|
+
const cleanup = async () => {
|
|
30
|
+
console.log(`[${now()}] cleaning up agents + broker`);
|
|
31
|
+
try {
|
|
32
|
+
await client.release(xName);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// ignore
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
await client.release(oName);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// ignore
|
|
42
|
+
}
|
|
43
|
+
await client.shutdown();
|
|
44
|
+
stopLogging();
|
|
45
|
+
stopStderrLogging();
|
|
46
|
+
};
|
|
47
|
+
process.on("SIGINT", async () => {
|
|
48
|
+
console.log(`[${now()}] SIGINT received`);
|
|
49
|
+
await cleanup();
|
|
50
|
+
process.exit(0);
|
|
51
|
+
});
|
|
52
|
+
process.on("SIGTERM", async () => {
|
|
53
|
+
console.log(`[${now()}] SIGTERM received`);
|
|
54
|
+
await cleanup();
|
|
55
|
+
process.exit(0);
|
|
56
|
+
});
|
|
57
|
+
console.log(`[${now()}] spawning ${xName} (${codexCmd} ${codexArgs.join(" ")})`);
|
|
58
|
+
await client.spawnPty({
|
|
59
|
+
name: xName,
|
|
60
|
+
cli: codexCmd,
|
|
61
|
+
args: codexArgs,
|
|
62
|
+
channels: [channel],
|
|
63
|
+
});
|
|
64
|
+
console.log(`[${now()}] spawning ${oName} (${codexCmd} ${codexArgs.join(" ")})`);
|
|
65
|
+
await client.spawnPty({
|
|
66
|
+
name: oName,
|
|
67
|
+
cli: codexCmd,
|
|
68
|
+
args: codexArgs,
|
|
69
|
+
channels: [channel],
|
|
70
|
+
});
|
|
71
|
+
console.log(`[${now()}] workers spawned. send kickoff via Relaycast (MCP relay_send) and watch events here (Ctrl+C to stop).`);
|
|
72
|
+
await new Promise(() => {
|
|
73
|
+
// keep process alive while events stream
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
main().catch((error) => {
|
|
77
|
+
console.error(`[${now()}] fatal`, error);
|
|
78
|
+
process.exit(1);
|
|
79
|
+
});
|
|
80
|
+
//# sourceMappingURL=example.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"example.js","sourceRoot":"","sources":["../../src/examples/example.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quickstart.d.ts","sourceRoot":"","sources":["../../src/examples/quickstart.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quickstart ā shows the clean AgentRelay facade API.
|
|
3
|
+
*
|
|
4
|
+
* Run:
|
|
5
|
+
* npm run build && npm run quickstart
|
|
6
|
+
*
|
|
7
|
+
* Environment:
|
|
8
|
+
* RELAY_API_KEY ā Relaycast workspace key (required)
|
|
9
|
+
* AGENT_RELAY_BIN ā path to agent-relay binary (optional)
|
|
10
|
+
*/
|
|
11
|
+
import { AgentRelay } from "../relay.js";
|
|
12
|
+
// The Relay is the communication backbone for your agents.
|
|
13
|
+
// Drop it into your codebase and let your agents communicate.
|
|
14
|
+
const relay = new AgentRelay();
|
|
15
|
+
// āā Event hooks āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
16
|
+
relay.onMessageReceived = (message) => {
|
|
17
|
+
console.log(`message received ā from=${message.from} to=${message.to}`);
|
|
18
|
+
};
|
|
19
|
+
relay.onMessageSent = (message) => {
|
|
20
|
+
console.log(`message sent ā from=${message.from} to=${message.to}`);
|
|
21
|
+
};
|
|
22
|
+
relay.onAgentSpawned = (agent) => {
|
|
23
|
+
console.log(`agent spawned ā ${agent.name} (${agent.runtime})`);
|
|
24
|
+
};
|
|
25
|
+
relay.onAgentReleased = (agent) => {
|
|
26
|
+
console.log(`agent released ā ${agent.name}`);
|
|
27
|
+
};
|
|
28
|
+
relay.onAgentExited = (agent) => {
|
|
29
|
+
console.log(`agent exited ā ${agent.name}`);
|
|
30
|
+
};
|
|
31
|
+
// āā Create agents with sane defaults, running locally āāāāāāāāāāāāāāāāāāāāāāā
|
|
32
|
+
const [codex, claude, gemini] = await Promise.all([
|
|
33
|
+
relay.codex.spawn(),
|
|
34
|
+
relay.claude.spawn(),
|
|
35
|
+
relay.gemini.spawn(),
|
|
36
|
+
]);
|
|
37
|
+
// āā Configure messaging with custom CLI agents āāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
38
|
+
const worker1 = await relay.spawnPty({
|
|
39
|
+
name: "Worker1",
|
|
40
|
+
cli: "codex",
|
|
41
|
+
args: ["--model", "gpt-5"],
|
|
42
|
+
channels: ["general"],
|
|
43
|
+
});
|
|
44
|
+
// āā Control messaging from non-agent sources āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
45
|
+
const human = relay.human({ name: "System" });
|
|
46
|
+
await human.sendMessage({ to: codex.name, text: "Hello, world!" });
|
|
47
|
+
// āā List agents āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
48
|
+
const agents = await relay.listAgents();
|
|
49
|
+
for (const agent of agents) {
|
|
50
|
+
console.log(` ${agent.name} runtime=${agent.runtime} channels=[${agent.channels}]`);
|
|
51
|
+
}
|
|
52
|
+
for (const agent of agents) {
|
|
53
|
+
await agent.release();
|
|
54
|
+
}
|
|
55
|
+
await relay.shutdown();
|
|
56
|
+
//# sourceMappingURL=quickstart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quickstart.js","sourceRoot":"","sources":["../../src/examples/quickstart.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,2DAA2D;AAC3D,8DAA8D;AAC9D,MAAM,KAAK,GAAG,IAAI,UAAU,EAAE,CAAC;AAE/B,+EAA+E;AAE/E,KAAK,CAAC,iBAAiB,GAAG,CAAC,OAAO,EAAE,EAAE;IACpC,OAAO,CAAC,GAAG,CAAC,4BAA4B,OAAO,CAAC,IAAI,OAAO,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;AAC3E,CAAC,CAAC;AAEF,KAAK,CAAC,aAAa,GAAG,CAAC,OAAO,EAAE,EAAE;IAChC,OAAO,CAAC,GAAG,CAAC,4BAA4B,OAAO,CAAC,IAAI,OAAO,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;AAC3E,CAAC,CAAC;AAEF,KAAK,CAAC,cAAc,GAAG,CAAC,KAAK,EAAE,EAAE;IAC/B,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC;AACtE,CAAC,CAAC;AAEF,KAAK,CAAC,eAAe,GAAG,CAAC,KAAK,EAAE,EAAE;IAChC,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;AACnD,CAAC,CAAC;AAEF,KAAK,CAAC,aAAa,GAAG,CAAC,KAAK,EAAE,EAAE;IAC9B,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;AACnD,CAAC,CAAC;AAEF,+EAA+E;AAE/E,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;IAChD,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE;IACnB,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE;IACpB,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE;CACrB,CAAC,CAAC;AAEH,8EAA8E;AAE9E,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC;IACnC,IAAI,EAAE,SAAS;IACf,GAAG,EAAE,OAAO;IACZ,IAAI,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC;IAC1B,QAAQ,EAAE,CAAC,SAAS,CAAC;CACtB,CAAC,CAAC;AAEH,+EAA+E;AAE/E,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;AAC9C,MAAM,KAAK,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,CAAC;AAEnE,+EAA+E;AAE/E,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC;AACxC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;IAC3B,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,aAAa,KAAK,CAAC,OAAO,eAAe,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC;AACzF,CAAC;AAED,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;IAC3B,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC;AACxB,CAAC;AAED,MAAM,KAAK,CAAC,QAAQ,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ralph-loop.d.ts","sourceRoot":"","sources":["../../src/examples/ralph-loop.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ralph Loop ā Claude + Codex pair-programming through a PRD.
|
|
3
|
+
*
|
|
4
|
+
* Each iteration spawns TWO agents that work together simultaneously:
|
|
5
|
+
* - Claude (PTY) ā the architect. Plans, guides, and reviews.
|
|
6
|
+
* - Codex (PTY, --full-auto) ā the builder. Implements the code.
|
|
7
|
+
*
|
|
8
|
+
* Both agents join #general and communicate in real-time:
|
|
9
|
+
* 1. Claude receives the story and posts an implementation plan
|
|
10
|
+
* 2. Codex receives the story + sees Claude's plan on #general
|
|
11
|
+
* 3. As Codex works, Claude can course-correct via the channel
|
|
12
|
+
* 4. When Codex finishes, Claude reviews and posts REVIEW:PASS/FAIL
|
|
13
|
+
* 5. Quality checks run, story marked done or retried with feedback
|
|
14
|
+
*
|
|
15
|
+
* Why two agents instead of one?
|
|
16
|
+
* - Claude reasons about architecture, Codex executes rapidly
|
|
17
|
+
* - They see each other's messages in real-time (not just handoffs)
|
|
18
|
+
* - Fresh eyes on review catch mistakes a single agent misses
|
|
19
|
+
* - Each iteration is doubly effective ā thinking + doing in parallel
|
|
20
|
+
*
|
|
21
|
+
* Run:
|
|
22
|
+
* npx tsc && npm run ralph
|
|
23
|
+
*
|
|
24
|
+
* References:
|
|
25
|
+
* https://github.com/snarktank/ralph
|
|
26
|
+
* https://ghuntley.com/ralph/
|
|
27
|
+
*/
|
|
28
|
+
import fs from "node:fs";
|
|
29
|
+
import { execSync } from "node:child_process";
|
|
30
|
+
import { AgentRelay } from "../relay.js";
|
|
31
|
+
// āā Configuration āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
32
|
+
const PRD_PATH = process.env.PRD_PATH ?? "prd.json";
|
|
33
|
+
const PROGRESS_PATH = process.env.PROGRESS_PATH ?? "progress.txt";
|
|
34
|
+
const MAX_ITERATIONS = Number(process.env.MAX_ITERATIONS ?? 10);
|
|
35
|
+
const MAX_REVIEW_ROUNDS = Number(process.env.MAX_REVIEW_ROUNDS ?? 2);
|
|
36
|
+
const QUALITY_CMD = process.env.QUALITY_CMD ?? "npm run check";
|
|
37
|
+
/** Max time (ms) to wait for both agents per round before releasing them. */
|
|
38
|
+
const ROUND_TIMEOUT_MS = Number(process.env.ROUND_TIMEOUT_MS ?? 5 * 60 * 1000);
|
|
39
|
+
// āā Helpers āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
40
|
+
function loadPrd() {
|
|
41
|
+
return JSON.parse(fs.readFileSync(PRD_PATH, "utf-8"));
|
|
42
|
+
}
|
|
43
|
+
function savePrd(prd) {
|
|
44
|
+
fs.writeFileSync(PRD_PATH, JSON.stringify(prd, null, 2) + "\n");
|
|
45
|
+
}
|
|
46
|
+
function appendProgress(entry) {
|
|
47
|
+
const line = `[${new Date().toISOString()}] ${entry}\n`;
|
|
48
|
+
fs.appendFileSync(PROGRESS_PATH, line);
|
|
49
|
+
}
|
|
50
|
+
function readProgress() {
|
|
51
|
+
return fs.existsSync(PROGRESS_PATH)
|
|
52
|
+
? fs.readFileSync(PROGRESS_PATH, "utf-8")
|
|
53
|
+
: "";
|
|
54
|
+
}
|
|
55
|
+
function nextStory(prd) {
|
|
56
|
+
return prd.userStories.find((s) => !s.passes);
|
|
57
|
+
}
|
|
58
|
+
function runQualityChecks() {
|
|
59
|
+
try {
|
|
60
|
+
const output = execSync(QUALITY_CMD, { encoding: "utf-8", stdio: "pipe" });
|
|
61
|
+
return { passed: true, output };
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
const output = err.stdout ?? String(err);
|
|
65
|
+
return { passed: false, output };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// āā Prompt builders āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
69
|
+
function architectPrompt(story, progress) {
|
|
70
|
+
const criteria = story.acceptanceCriteria.map((c) => ` - ${c}`).join("\n");
|
|
71
|
+
return [
|
|
72
|
+
`## Architect: ${story.title}`,
|
|
73
|
+
``,
|
|
74
|
+
`You are the architect. A Codex agent ("Builder") is working alongside you.`,
|
|
75
|
+
`You are both on the #general channel and can communicate freely.`,
|
|
76
|
+
``,
|
|
77
|
+
`### How to communicate`,
|
|
78
|
+
`Use the Relaycast MCP tools to post messages to #general:`,
|
|
79
|
+
`1. Call set_workspace_key with your RELAY_API_KEY env var`,
|
|
80
|
+
`2. Register as an agent using your name`,
|
|
81
|
+
`3. Use post_message to send to the #general channel`,
|
|
82
|
+
``,
|
|
83
|
+
story.description,
|
|
84
|
+
``,
|
|
85
|
+
`### Acceptance Criteria`,
|
|
86
|
+
criteria,
|
|
87
|
+
``,
|
|
88
|
+
`### Previous Learnings`,
|
|
89
|
+
progress || "(first story)",
|
|
90
|
+
``,
|
|
91
|
+
`### Your job`,
|
|
92
|
+
`1. Post a concise implementation plan to #general (files, changes, edge cases)`,
|
|
93
|
+
`2. Monitor the Builder's progress messages on the channel`,
|
|
94
|
+
`3. Provide guidance if the Builder asks questions or goes off track`,
|
|
95
|
+
`4. When the Builder says it's done, review the git diff`,
|
|
96
|
+
`5. Post exactly "REVIEW:PASS" to #general if all criteria are met`,
|
|
97
|
+
`6. Post exactly "REVIEW:FAIL" followed by feedback to #general if issues remain`,
|
|
98
|
+
``,
|
|
99
|
+
`IMPORTANT: You MUST use Relaycast MCP tools to post messages. This is how`,
|
|
100
|
+
`the orchestrator knows you're done. Post your plan first, then your verdict.`,
|
|
101
|
+
].join("\n");
|
|
102
|
+
}
|
|
103
|
+
function builderPrompt(story, progress, reviewFeedback) {
|
|
104
|
+
const criteria = story.acceptanceCriteria.map((c) => ` - ${c}`).join("\n");
|
|
105
|
+
const sections = [
|
|
106
|
+
`## Builder: ${story.title}`,
|
|
107
|
+
``,
|
|
108
|
+
`You are the builder. A Claude agent ("Architect") is guiding you on #general.`,
|
|
109
|
+
`Read the Architect's plan from the channel and implement it.`,
|
|
110
|
+
``,
|
|
111
|
+
`### How to communicate`,
|
|
112
|
+
`Use the Relaycast MCP tools to post messages to #general:`,
|
|
113
|
+
`1. Call set_workspace_key with your RELAY_API_KEY env var`,
|
|
114
|
+
`2. Register as an agent using your name`,
|
|
115
|
+
`3. Use post_message to send to the #general channel`,
|
|
116
|
+
``,
|
|
117
|
+
story.description,
|
|
118
|
+
``,
|
|
119
|
+
`### Acceptance Criteria`,
|
|
120
|
+
criteria,
|
|
121
|
+
];
|
|
122
|
+
if (reviewFeedback) {
|
|
123
|
+
sections.push(``, `### Review Feedback (fix these issues first)`, reviewFeedback);
|
|
124
|
+
}
|
|
125
|
+
sections.push(``, `### Previous Learnings`, progress || "(first story)", ``, `### Your job`, `1. Read the Architect's plan from #general`, `2. Implement the changes`, `3. Post progress updates to #general as you work`, `4. When done, post exactly "IMPLEMENTATION COMPLETE" to #general`, ``, `IMPORTANT: You MUST use Relaycast MCP tools to post messages. This is how`, `the orchestrator knows you're done.`);
|
|
126
|
+
return sections.join("\n");
|
|
127
|
+
}
|
|
128
|
+
// āā Main loop āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
129
|
+
const relay = new AgentRelay({ env: process.env });
|
|
130
|
+
const channelLog = [];
|
|
131
|
+
relay.onMessageReceived = (msg) => {
|
|
132
|
+
channelLog.push(msg);
|
|
133
|
+
console.log(` š¬ ${msg.from}: "${msg.text.slice(0, 80)}ā¦"`);
|
|
134
|
+
};
|
|
135
|
+
relay.onAgentSpawned = (agent) => console.log(` š¢ ${agent.name} spawned (${agent.runtime})`);
|
|
136
|
+
relay.onAgentReleased = (agent) => console.log(` š“ ${agent.name} released`);
|
|
137
|
+
relay.onAgentExited = (agent) => console.log(` āŖ ${agent.name} exited`);
|
|
138
|
+
relay.onMessageSent = (msg) => console.log(` š¤ ā ${msg.to}: "${msg.text.slice(0, 60)}ā¦"`);
|
|
139
|
+
const prd = loadPrd();
|
|
140
|
+
const orchestrator = relay.human({ name: "Ralph" });
|
|
141
|
+
console.log(`\nāā Ralph Loop (Claude + Codex) āā`);
|
|
142
|
+
console.log(` branch: ${prd.branchName}`);
|
|
143
|
+
console.log(` stories: ${prd.userStories.length}`);
|
|
144
|
+
console.log(` remaining: ${prd.userStories.filter((s) => !s.passes).length}`);
|
|
145
|
+
console.log(` max iterations: ${MAX_ITERATIONS}`);
|
|
146
|
+
console.log(` max review rounds: ${MAX_REVIEW_ROUNDS}\n`);
|
|
147
|
+
let iteration = 0;
|
|
148
|
+
while (iteration < MAX_ITERATIONS) {
|
|
149
|
+
const story = nextStory(prd);
|
|
150
|
+
if (!story)
|
|
151
|
+
break;
|
|
152
|
+
iteration++;
|
|
153
|
+
console.log(`\nāā Story ${story.id}: ${story.title} (iteration ${iteration}) āā\n`);
|
|
154
|
+
let reviewFeedback;
|
|
155
|
+
let storyPassed = false;
|
|
156
|
+
for (let round = 0; round < MAX_REVIEW_ROUNDS; round++) {
|
|
157
|
+
const roundLabel = round === 0 ? "initial" : `fix-${round}`;
|
|
158
|
+
const progress = readProgress();
|
|
159
|
+
// āā Spawn both agents concurrently āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
160
|
+
console.log(` ā” Spawning Claude (architect) + Codex (builder) ā round: ${roundLabel}`);
|
|
161
|
+
const [architect, builder] = await Promise.all([
|
|
162
|
+
relay.claude.spawn({
|
|
163
|
+
name: `Architect-${story.id}-${roundLabel}`,
|
|
164
|
+
channels: ["general"],
|
|
165
|
+
}),
|
|
166
|
+
relay.codex.spawn({
|
|
167
|
+
name: `Builder-${story.id}-${roundLabel}`,
|
|
168
|
+
args: ["--full-auto"],
|
|
169
|
+
channels: ["general"],
|
|
170
|
+
}),
|
|
171
|
+
]);
|
|
172
|
+
// āā Inject tasks via relay āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
173
|
+
// Claude gets the architect prompt first so it can post the plan
|
|
174
|
+
await orchestrator.sendMessage({
|
|
175
|
+
to: architect.name,
|
|
176
|
+
text: architectPrompt(story, progress),
|
|
177
|
+
});
|
|
178
|
+
// Small delay so Claude's plan arrives before Codex starts reading
|
|
179
|
+
await new Promise((r) => setTimeout(r, 2000));
|
|
180
|
+
await orchestrator.sendMessage({
|
|
181
|
+
to: builder.name,
|
|
182
|
+
text: builderPrompt(story, progress, reviewFeedback),
|
|
183
|
+
});
|
|
184
|
+
// āā Wait for agents to finish or detect completion āāāāāāāāāāāāāāāāāāāā
|
|
185
|
+
// Interactive agents don't exit on their own, so we poll channel
|
|
186
|
+
// messages for completion signals and release them when done.
|
|
187
|
+
console.log(` ā³ Claude + Codex working together on #generalā¦`);
|
|
188
|
+
const startLen = channelLog.length;
|
|
189
|
+
const deadline = Date.now() + ROUND_TIMEOUT_MS;
|
|
190
|
+
let verdict;
|
|
191
|
+
// Poll every 5s for completion signals in channel messages
|
|
192
|
+
while (Date.now() < deadline) {
|
|
193
|
+
const recent = channelLog.slice(startLen);
|
|
194
|
+
// Check if Claude posted a review verdict
|
|
195
|
+
const review = recent.find((m) => m.text.includes("REVIEW:PASS") || m.text.includes("REVIEW:FAIL"));
|
|
196
|
+
if (review) {
|
|
197
|
+
verdict = review.text;
|
|
198
|
+
console.log(` š Claude posted verdict`);
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
// Check if Codex signaled completion (Claude may still be reviewing)
|
|
202
|
+
const implDone = recent.find((m) => m.text.includes("IMPLEMENTATION COMPLETE"));
|
|
203
|
+
if (implDone) {
|
|
204
|
+
console.log(` š Codex finished, waiting for Claude's reviewā¦`);
|
|
205
|
+
// Give Claude up to 60s more to post a verdict
|
|
206
|
+
const reviewDeadline = Date.now() + 60_000;
|
|
207
|
+
while (Date.now() < reviewDeadline) {
|
|
208
|
+
await new Promise((r) => setTimeout(r, 3000));
|
|
209
|
+
const afterImpl = channelLog.slice(startLen);
|
|
210
|
+
const rv = afterImpl.find((m) => m.text.includes("REVIEW:PASS") || m.text.includes("REVIEW:FAIL"));
|
|
211
|
+
if (rv) {
|
|
212
|
+
verdict = rv.text;
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
// Check if either agent exited on its own
|
|
219
|
+
const archResult = await architect.waitForExit(0);
|
|
220
|
+
const buildResult = await builder.waitForExit(0);
|
|
221
|
+
if (archResult !== "timeout" && buildResult !== "timeout")
|
|
222
|
+
break;
|
|
223
|
+
await new Promise((r) => setTimeout(r, 5000));
|
|
224
|
+
}
|
|
225
|
+
// Release both agents (they're interactive so won't exit on their own)
|
|
226
|
+
const cleanup = async (agent) => {
|
|
227
|
+
try {
|
|
228
|
+
await agent.release();
|
|
229
|
+
}
|
|
230
|
+
catch { /* already exited */ }
|
|
231
|
+
};
|
|
232
|
+
await Promise.all([cleanup(architect), cleanup(builder)]);
|
|
233
|
+
// āā Quality gate āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
234
|
+
console.log(` š running quality checksā¦`);
|
|
235
|
+
const quality = runQualityChecks();
|
|
236
|
+
if (!quality.passed) {
|
|
237
|
+
appendProgress(`ā ${story.id} round=${roundLabel} ā quality checks failed`);
|
|
238
|
+
reviewFeedback = `Quality checks failed:\n${quality.output.slice(0, 500)}`;
|
|
239
|
+
console.log(` ā quality checks failed\n`);
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
// āā Check verdict āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
243
|
+
if (verdict?.includes("REVIEW:PASS")) {
|
|
244
|
+
storyPassed = true;
|
|
245
|
+
appendProgress(`ā
${story.id} ā ${story.title} ā PASSED (round=${roundLabel})`);
|
|
246
|
+
console.log(` ā
story passed!\n`);
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
else if (verdict?.includes("REVIEW:FAIL")) {
|
|
250
|
+
const failText = verdict.replace("REVIEW:FAIL", "").trim();
|
|
251
|
+
reviewFeedback = failText;
|
|
252
|
+
appendProgress(`š ${story.id} round=${roundLabel} ā review failed: ${reviewFeedback.slice(0, 200)}`);
|
|
253
|
+
console.log(` š review failed, starting new round\n`);
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
// No verdict from Claude ā quality passed so accept it
|
|
257
|
+
storyPassed = true;
|
|
258
|
+
appendProgress(`ā
${story.id} ā ${story.title} ā PASSED (quality only, round=${roundLabel})`);
|
|
259
|
+
console.log(` ā
quality passed (no explicit review verdict)\n`);
|
|
260
|
+
break;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (storyPassed) {
|
|
264
|
+
story.passes = true;
|
|
265
|
+
savePrd(prd);
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
appendProgress(`ā ļø ${story.id} ā exhausted review rounds, moving on`);
|
|
269
|
+
console.log(` ā ļø exhausted ${MAX_REVIEW_ROUNDS} review rounds for ${story.id}\n`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
// āā Summary āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
273
|
+
const remaining = prd.userStories.filter((s) => !s.passes);
|
|
274
|
+
if (remaining.length === 0) {
|
|
275
|
+
console.log(`\nš COMPLETE ā all stories pass.`);
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
console.log(`\nā ļø ${remaining.length} stories remain after ${iteration} iterations.`);
|
|
279
|
+
}
|
|
280
|
+
await relay.shutdown();
|
|
281
|
+
//# sourceMappingURL=ralph-loop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ralph-loop.js","sourceRoot":"","sources":["../../src/examples/ralph-loop.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./protocol.js";
|
|
2
|
+
export * from "./client.js";
|
|
3
|
+
export * from "./relaycast.js";
|
|
4
|
+
export * from "./pty.js";
|
|
5
|
+
export * from "./relay.js";
|
|
6
|
+
export * from "./logs.js";
|
|
7
|
+
export * from "./consensus.js";
|
|
8
|
+
export * from "./shadow.js";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./protocol.js";
|
|
2
|
+
export * from "./client.js";
|
|
3
|
+
export * from "./relaycast.js";
|
|
4
|
+
export * from "./pty.js";
|
|
5
|
+
export * from "./relay.js";
|
|
6
|
+
export * from "./logs.js";
|
|
7
|
+
export * from "./consensus.js";
|
|
8
|
+
export * from "./shadow.js";
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log reading utilities for the broker SDK.
|
|
3
|
+
*
|
|
4
|
+
* Reads agent logs from the local filesystem at
|
|
5
|
+
* `.agent-relay/worker-logs/{agent}.log`.
|
|
6
|
+
*/
|
|
7
|
+
export interface GetLogsOptions {
|
|
8
|
+
/** Directory containing worker logs. Defaults to `.agent-relay/worker-logs` in cwd. */
|
|
9
|
+
logsDir?: string;
|
|
10
|
+
/** Number of lines to return from the end. Default: 50 */
|
|
11
|
+
lines?: number;
|
|
12
|
+
}
|
|
13
|
+
export interface LogsResult {
|
|
14
|
+
agent: string;
|
|
15
|
+
content: string;
|
|
16
|
+
found: boolean;
|
|
17
|
+
lineCount: number;
|
|
18
|
+
/** Other agents that have log files (populated when `found` is false). */
|
|
19
|
+
availableAgents?: string[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Get logs for a specific agent.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* import { getLogs } from "agent-relay/broker";
|
|
27
|
+
*
|
|
28
|
+
* const result = await getLogs("Worker1", { lines: 100 });
|
|
29
|
+
* if (result.found) {
|
|
30
|
+
* console.log(result.content);
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare function getLogs(agent: string, options?: GetLogsOptions): Promise<LogsResult>;
|
|
35
|
+
/**
|
|
36
|
+
* List all agents that have log files.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* import { listLoggedAgents } from "agent-relay/broker";
|
|
41
|
+
*
|
|
42
|
+
* const agents = await listLoggedAgents();
|
|
43
|
+
* console.log("Agents with logs:", agents);
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare function listLoggedAgents(logsDir?: string): Promise<string[]>;
|
|
47
|
+
//# sourceMappingURL=logs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../src/logs.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,WAAW,cAAc;IAC7B,uFAAuF;IACvF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AA2ED;;;;;;;;;;;;GAYG;AACH,wBAAsB,OAAO,CAC3B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,cAAmB,GAC3B,OAAO,CAAC,UAAU,CAAC,CAuBrB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAW1E"}
|