feat(discord): connector pilot for the Sage seat, reviewed candidate (#1509)

Zero-dependency Discord connector under packages/discord: binding
validation, REST and gateway clients, pi engine adapter, journal with
append-only inbox, outbox, admissions and notices, and a run.lock
ownership record {pid, start, boot} whose identity is checked three ways
and whose cleanup is gated by STOP. CLI check|run|stop|unlock via
scripts/discord.sh; offline suite scripts/test-discord.sh (28 checks,
87 node tests).

Reviewed by rev-code-02 on #1509 over nine rounds; approved exact tree
4e0feb6758c0a7e4a71483912a8e0d3e3ec95aef at comment 26170. Corrections
(1) to (12) recorded in BUILD-LOG. No listener started, no token read,
no Discord write; the live pilot follows this commit per the brief.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
2026-09-13 01:15:37 -05:00
co-authored by Claude Fable 5.1
parent b023841c8a
commit 786e379c49
34 changed files with 4641 additions and 1 deletions
+85
View File
@@ -0,0 +1,85 @@
// A stand-in for `pi --mode rpc`. Reads JSONL commands on stdin, writes
// events on stdout. Behaviour is scripted per prompt text:
// "slow <ms>" answer "slow reply" after <ms>
// "garbage" emit one malformed line
// "error" end the turn with stopReason error
// anything else answer "echo: <text>" immediately
// A prompt received while busy without streamingBehavior is refused, as pi
// does. Every command is mirrored to FAKE_PI_LOG when set.
import { appendFileSync } from "node:fs";
const logPath = process.env.FAKE_PI_LOG;
const out = (o) => process.stdout.write(JSON.stringify(o) + "\n");
let busy = false;
const queue = [];
function assistant(text, stopReason = "stop") {
return { role: "assistant", content: text === null ? [] : [{ type: "text", text }], stopReason, usage: { input: 3, output: 2 }, model: "fake", provider: "fake" };
}
function run(text) {
busy = true;
out({ type: "agent_start" });
out({ type: "turn_start" });
const finish = (message) => {
out({ type: "turn_end", message, toolResults: [] });
out({ type: "agent_end", messages: [message] });
if (queue.length > 0) {
run(queue.shift());
return;
}
busy = false;
out({ type: "agent_settled" });
};
const m = /^slow (\d+)$/.exec(text);
if (m) {
const timer = setTimeout(() => finish(assistant("slow reply")), Number(m[1]));
current = { timer, finish };
return;
}
if (text === "garbage") {
process.stdout.write("this is not json\n");
finish(assistant("after garbage"));
return;
}
if (text === "error") {
finish({ ...assistant(null, "error"), errorMessage: "fake provider error" });
return;
}
finish(assistant(`echo: ${text}`));
}
let current = null;
let buffer = "";
process.stdin.setEncoding("utf8");
process.stdin.on("data", (chunk) => {
buffer += chunk;
let idx;
while ((idx = buffer.indexOf("\n")) !== -1) {
const line = buffer.slice(0, idx);
buffer = buffer.slice(idx + 1);
if (!line) continue;
const cmd = JSON.parse(line);
if (logPath) appendFileSync(logPath, line + "\n");
if (cmd.type === "prompt") {
if (busy && !cmd.streamingBehavior) {
out({ id: cmd.id, type: "response", command: "prompt", success: false, error: "agent is streaming; specify streamingBehavior" });
continue;
}
out({ id: cmd.id, type: "response", command: "prompt", success: true });
if (busy) queue.push(cmd.message);
else run(cmd.message);
} else if (cmd.type === "abort") {
out({ id: cmd.id, type: "response", command: "abort", success: true });
if (current) {
clearTimeout(current.timer);
const f = current.finish;
current = null;
f(assistant("", "aborted"));
}
} else {
out({ id: cmd.id, type: "response", command: cmd.type, success: true, data: {} });
}
}
});
process.stdin.on("end", () => process.exit(0));