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:
@@ -0,0 +1,73 @@
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { createRest, RestOutcome, USER_AGENT } from "../src/rest.mjs";
|
||||
|
||||
function fakeFetch(script) {
|
||||
const calls = [];
|
||||
const fetch = async (url, init) => {
|
||||
calls.push({ url, init });
|
||||
const next = script.shift();
|
||||
if (!next) throw new Error("fake fetch: no scripted response");
|
||||
if (next.throw) throw Object.assign(new Error(next.throw), { code: "ECONNRESET" });
|
||||
return { status: next.status, text: async () => (next.body === undefined ? "" : JSON.stringify(next.body)) };
|
||||
};
|
||||
return { fetch, calls };
|
||||
}
|
||||
|
||||
const TOKEN = "T0KEN-not-real-1234567890";
|
||||
|
||||
test("rest: createMessage sends nonce, enforce_nonce, empty allowed_mentions and a soft reply reference", async () => {
|
||||
const f = fakeFetch([{ status: 200, body: { id: "m1" } }]);
|
||||
const rest = createRest({ token: TOKEN, fetch: f.fetch });
|
||||
const r = await rest.createMessage("c1", { content: "hi", nonce: "n1", replyTo: "orig" });
|
||||
assert.deepEqual(r, { messageId: "m1", status: 200 });
|
||||
const call = f.calls[0];
|
||||
assert.equal(call.url, "https://discord.com/api/v10/channels/c1/messages");
|
||||
assert.equal(call.init.method, "POST");
|
||||
assert.equal(call.init.headers.Authorization, `Bot ${TOKEN}`);
|
||||
assert.equal(call.init.headers["User-Agent"], USER_AGENT);
|
||||
assert.deepEqual(JSON.parse(call.init.body), {
|
||||
content: "hi", nonce: "n1", enforce_nonce: true,
|
||||
allowed_mentions: { parse: [], replied_user: false },
|
||||
message_reference: { message_id: "orig", fail_if_not_exists: false },
|
||||
});
|
||||
});
|
||||
|
||||
test("rest: 429 waits retry_after and retries; 4xx is refused; 5xx and socket errors are unknown", async () => {
|
||||
const waits = [];
|
||||
const sleep = async (ms) => waits.push(ms);
|
||||
let f = fakeFetch([{ status: 429, body: { retry_after: 0.25 } }, { status: 200, body: { id: "m2" } }]);
|
||||
let rest = createRest({ token: TOKEN, fetch: f.fetch, sleep });
|
||||
const r = await rest.createMessage("c1", { content: "hi", nonce: "n2" });
|
||||
assert.equal(r.messageId, "m2");
|
||||
assert.deepEqual(waits, [250]);
|
||||
assert.equal(f.calls.length, 2);
|
||||
|
||||
f = fakeFetch([{ status: 403, body: { code: 50001, message: "Missing Access" } }]);
|
||||
rest = createRest({ token: TOKEN, fetch: f.fetch, sleep });
|
||||
await assert.rejects(rest.createMessage("c1", { content: "hi", nonce: "n3" }), (err) => err instanceof RestOutcome && err.kind === "refused" && err.details.status === 403);
|
||||
|
||||
f = fakeFetch([{ status: 502, body: { message: "bad gateway" } }]);
|
||||
rest = createRest({ token: TOKEN, fetch: f.fetch, sleep });
|
||||
await assert.rejects(rest.createMessage("c1", { content: "hi", nonce: "n4" }), (err) => err instanceof RestOutcome && err.kind === "unknown");
|
||||
|
||||
f = fakeFetch([{ throw: "socket hang up" }]);
|
||||
rest = createRest({ token: TOKEN, fetch: f.fetch, sleep });
|
||||
await assert.rejects(rest.createMessage("c1", { content: "hi", nonce: "n5" }), (err) => err instanceof RestOutcome && err.kind === "unknown" && !err.message.includes(TOKEN));
|
||||
|
||||
// Bounded 429 retries: four 429s in a row end refused.
|
||||
f = fakeFetch([429, 429, 429, 429].map(() => ({ status: 429, body: { retry_after: 0.01 } })));
|
||||
rest = createRest({ token: TOKEN, fetch: f.fetch, sleep });
|
||||
await assert.rejects(rest.createMessage("c1", { content: "hi", nonce: "n6" }), (err) => err.kind === "refused" && err.details.status === 429);
|
||||
assert.equal(f.calls.length, 4);
|
||||
});
|
||||
|
||||
test("rest: content and nonce limits are enforced locally; typing never throws", async () => {
|
||||
const f = fakeFetch([{ status: 500 }, { throw: "down" }]);
|
||||
const rest = createRest({ token: TOKEN, fetch: f.fetch });
|
||||
await assert.rejects(rest.createMessage("c", { content: "x".repeat(2001), nonce: "n" }), /1..2000/);
|
||||
await assert.rejects(rest.createMessage("c", { content: "x", nonce: "n".repeat(26) }), /1..25/);
|
||||
await rest.typing("c");
|
||||
await rest.typing("c");
|
||||
assert.equal(f.calls.length, 2);
|
||||
});
|
||||
Reference in New Issue
Block a user