[Init] Initial commit - NetMesh terminal manager
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled

This commit is contained in:
2026-09-13 18:24:01 +08:00
commit 3c72efcb7f
3255 changed files with 907009 additions and 0 deletions

View File

@@ -0,0 +1,607 @@
const test = require("node:test");
const assert = require("node:assert/strict");
const { CodebuddySessionManager, computeOptionsFingerprint } = require("./codebuddySessionManager.cjs");
function collector() {
const events = [];
const emitter = {
text: (t) => events.push({ k: "text", t }),
reasoning: (d) => events.push({ k: "reasoning", d }),
toolCall: (name, args, id) => events.push({ k: "toolCall", name, args, id }),
toolResult: (id, out, name) => events.push({ k: "toolResult", id, out, name }),
usage: (usage) => events.push({ k: "usage", usage }),
status: (m) => events.push({ k: "status", m }),
sessionId: (s) => events.push({ k: "sessionId", s }),
emitDone: () => events.push({ k: "done" }),
emitError: (m) => events.push({ k: "error", m }),
emitEvent: (ev) => events.push({ k: "event", ev }),
};
return { events, emitter };
}
/** Create a fake V2 session that yields predefined messages. */
function fakeSession(messages, opts = {}) {
let sentMessages = [];
let closed = false;
let interruptCalls = 0;
return {
sessionId: opts.sessionId || "fake-sess-1",
sentMessages,
get closed() { return closed; },
get interruptCalls() { return interruptCalls; },
async connect() {},
async send(msg) { sentMessages.push(msg); },
async *stream() { for (const m of messages) yield m; },
async interrupt() { interruptCalls += 1; },
async setModel(model) { this._model = model; },
setHooks(hooks) { this._hooks = hooks; },
setCanUseTool(handler) { this._canUseTool = handler; },
close() { closed = true; },
};
}
test("getOrCreateSession reuses existing session when options match", async () => {
const mgr = new CodebuddySessionManager();
const session = fakeSession([], { sessionId: "existing-sess" });
const opts = { cwd: "/tmp", model: "glm-5" };
mgr.sessions.set("reuse-key", { session, fingerprint: computeOptionsFingerprint(opts) });
const result = await mgr.getOrCreateSession({
sessionKey: "reuse-key",
sessionOptions: opts,
});
assert.equal(result, session);
});
test("getOrCreateSession refreshes turn-scoped callbacks on a reused session", async () => {
let createdOptions;
const session = fakeSession([], { sessionId: "callback-session" });
const mgr = new CodebuddySessionManager({
loadSdk: async () => ({
unstable_v2_createSession: (options) => {
createdOptions = options;
return session;
},
unstable_v2_resumeSession: () => session,
}),
});
const firstEvents = [];
const secondEvents = [];
const firstOptions = {
cwd: "/tmp",
hooks: { Notification: [{ hooks: [() => firstEvents.push("hook")] }] },
canUseTool: async () => ({ behavior: "allow", updatedInput: {} }),
elicitation: {
create: async () => {
firstEvents.push("elicitation");
return { action: "accept" };
},
},
};
const secondOptions = {
cwd: "/tmp",
hooks: { Notification: [{ hooks: [() => secondEvents.push("hook")] }] },
canUseTool: async () => ({ behavior: "deny", message: "second turn" }),
elicitation: {
create: async () => {
secondEvents.push("elicitation");
return { action: "decline" };
},
},
};
const first = await mgr.getOrCreateSession({
sessionKey: "callback-key",
sessionOptions: firstOptions,
});
const second = await mgr.getOrCreateSession({
sessionKey: "callback-key",
sessionOptions: secondOptions,
});
assert.equal(first, session);
assert.equal(second, session);
assert.equal(session._hooks, secondOptions.hooks);
assert.equal(session._canUseTool, secondOptions.canUseTool);
assert.notEqual(createdOptions.elicitation, firstOptions.elicitation);
await session._hooks.Notification[0].hooks[0]();
assert.deepEqual(await session._canUseTool(), {
behavior: "deny",
message: "second turn",
});
assert.deepEqual(
await createdOptions.elicitation.create({}, { signal: new AbortController().signal }),
{ action: "decline" },
);
assert.deepEqual(firstEvents, []);
assert.deepEqual(secondEvents, ["hook", "elicitation"]);
});
test("getOrCreateSession closes stale session when options change", async () => {
const oldSession = fakeSession([], { sessionId: "old-sess" });
const replacementSession = fakeSession([], { sessionId: "new-sess" });
const mgr = new CodebuddySessionManager({
loadSdk: async () => ({
unstable_v2_createSession: () => replacementSession,
unstable_v2_resumeSession: () => replacementSession,
}),
});
const oldOpts = { cwd: "/tmp", model: "glm-4" };
const newOpts = { cwd: "/tmp", model: "glm-5" };
mgr.sessions.set("stale-key", {
session: oldSession,
fingerprint: computeOptionsFingerprint(oldOpts),
});
const result = await mgr.getOrCreateSession({
sessionKey: "stale-key",
sessionOptions: newOpts,
});
assert.ok(oldSession.closed);
assert.equal(result, replacementSession);
assert.equal(mgr.sessions.get("stale-key").session, replacementSession);
assert.equal(
mgr.sessions.get("stale-key").fingerprint,
computeOptionsFingerprint(newOpts),
);
});
test("runTurn closes a session when initial send fails before fallback", async () => {
const session = fakeSession([], { sessionId: "failed-connect-session" });
session.send = async () => {
throw new Error("connect failed");
};
const mgr = new CodebuddySessionManager({
loadSdk: async () => ({
unstable_v2_createSession: () => session,
unstable_v2_resumeSession: () => session,
}),
});
const { events, emitter } = collector();
const result = await mgr.runTurn({
sessionKey: "failed-connect-key",
prompt: "hello",
attachments: [],
options: { abortController: new AbortController() },
emitter,
sessionOptions: {},
});
assert.equal(result, null);
assert.equal(session.closed, true);
assert.equal(mgr.sessions.has("failed-connect-key"), false);
assert.deepEqual(events, []);
});
test("runTurn closes and evicts a session when response streaming fails", async () => {
const session = fakeSession([], { sessionId: "failed-stream-session" });
session.stream = async function* stream() {
throw new Error("transport died");
};
const mgr = new CodebuddySessionManager({
loadSdk: async () => ({
unstable_v2_createSession: () => session,
unstable_v2_resumeSession: () => session,
}),
});
const { events, emitter } = collector();
const result = await mgr.runTurn({
sessionKey: "failed-stream-key",
prompt: "hello",
attachments: [],
options: { abortController: new AbortController() },
emitter,
sessionOptions: {},
});
assert.deepEqual(result, {
sessionId: "failed-stream-session",
usedV2: true,
});
assert.equal(session.closed, true);
assert.equal(mgr.sessions.has("failed-stream-key"), false);
assert.deepEqual(events, [
{ k: "sessionId", s: "failed-stream-session" },
{ k: "error", m: "transport died" },
]);
});
test("computeOptionsFingerprint detects option changes", () => {
const base = {
cwd: "/tmp",
model: "glm-5",
maxTurns: 10,
effort: "high",
extraArgs: { "dangerously-skip-permissions": null },
};
const same = {
cwd: "/tmp",
model: "glm-5",
maxTurns: 10,
effort: "high",
extraArgs: { "dangerously-skip-permissions": null },
};
const diffModel = { cwd: "/tmp", model: "glm-4", maxTurns: 10, effort: "high" };
const diffMaxTurns = { cwd: "/tmp", model: "glm-5", maxTurns: 20, effort: "high" };
const diffEffort = { cwd: "/tmp", model: "glm-5", maxTurns: 10, effort: "low" };
const diffExtraArgs = {
...base,
extraArgs: { "dangerously-skip-permissions": "false" },
};
assert.equal(computeOptionsFingerprint(base), computeOptionsFingerprint(same));
assert.notEqual(computeOptionsFingerprint(base), computeOptionsFingerprint(diffModel));
assert.notEqual(computeOptionsFingerprint(base), computeOptionsFingerprint(diffMaxTurns));
assert.notEqual(computeOptionsFingerprint(base), computeOptionsFingerprint(diffEffort));
assert.notEqual(computeOptionsFingerprint(base), computeOptionsFingerprint(diffExtraArgs));
});
test("getOrCreateSession never reuses sessions with unserializable option fingerprints", async () => {
const circular = {};
circular.self = circular;
const oldSession = fakeSession([], { sessionId: "circular-old" });
const replacementSession = fakeSession([], { sessionId: "circular-new" });
const mgr = new CodebuddySessionManager({
loadSdk: async () => ({
unstable_v2_createSession: () => replacementSession,
unstable_v2_resumeSession: () => replacementSession,
}),
});
mgr.sessions.set("circular-key", {
session: oldSession,
fingerprint: computeOptionsFingerprint({ mcpServers: circular }),
});
const result = await mgr.getOrCreateSession({
sessionKey: "circular-key",
sessionOptions: { mcpServers: circular },
});
assert.equal(result, replacementSession);
assert.equal(oldSession.closed, true);
assert.equal(mgr.sessions.get("circular-key").session, replacementSession);
});
test("runTurn streams messages via V2 session when available", async () => {
const mgr = new CodebuddySessionManager();
const messages = [
{ type: "system", session_id: "sess-v2" },
{ type: "stream_event", event: { type: "content_block_delta", delta: { type: "text_delta", text: "hi from v2" } } },
];
const session = fakeSession(messages, { sessionId: "sess-v2" });
// Pre-populate the session map to bypass SDK import.
mgr.sessions.set("preloaded-key", { session, fingerprint: computeOptionsFingerprint({}) });
const { events, emitter } = collector();
const result = await mgr.runTurn({
sessionKey: "preloaded-key",
prompt: "say hi",
attachments: [],
options: { abortController: new AbortController() },
emitter,
sessionOptions: {},
});
assert.deepEqual(result, { sessionId: "sess-v2", usedV2: true });
assert.ok(events.some((e) => e.k === "text" && e.t === "hi from v2"));
assert.ok(events.some((e) => e.k === "done"));
assert.deepEqual(
events.filter((event) => event.k === "sessionId"),
[{ k: "sessionId", s: "sess-v2" }],
);
assert.ok(session.sentMessages.includes("say hi"));
});
test("runTurn sends before connecting a resumed session and skips replayed history", async () => {
let explicitlyConnected = false;
const session = fakeSession([], { sessionId: "resumed-session" });
session.connect = async () => {
explicitlyConnected = true;
};
session.send = async (message) => {
session.sentMessages.push(message);
};
session.stream = async function* stream() {
if (explicitlyConnected) {
yield {
type: "assistant",
message: { content: [{ type: "text", text: "old response" }] },
};
}
yield {
type: "assistant",
message: { content: [{ type: "text", text: "new response" }] },
};
};
const mgr = new CodebuddySessionManager({
loadSdk: async () => ({
unstable_v2_createSession: () => session,
unstable_v2_resumeSession: () => session,
}),
});
const { events, emitter } = collector();
const result = await mgr.runTurn({
sessionKey: "resumed-key",
prompt: "new question",
attachments: [],
options: { abortController: new AbortController() },
emitter,
sessionOptions: {},
resumeSessionId: "resumed-session",
});
assert.deepEqual(result, { sessionId: "resumed-session", usedV2: true });
assert.equal(explicitlyConnected, false);
assert.deepEqual(session.sentMessages, ["new question"]);
assert.deepEqual(
events.filter((event) => event.k === "text").map((event) => event.t),
["new response"],
);
assert.deepEqual(
events.filter((event) => event.k === "sessionId"),
[{ k: "sessionId", s: "resumed-session" }],
);
});
test("runTurn does not connect or send when already aborted", async () => {
let loadSdkCalls = 0;
const mgr = new CodebuddySessionManager({
loadSdk: async () => {
loadSdkCalls += 1;
return {};
},
});
const controller = new AbortController();
controller.abort();
const { events, emitter } = collector();
const result = await mgr.runTurn({
sessionKey: "pre-aborted-key",
prompt: "must not run",
attachments: [],
options: { abortController: controller },
emitter,
sessionOptions: {},
});
assert.deepEqual(result, { sessionId: null, usedV2: true });
assert.equal(loadSdkCalls, 0);
assert.deepEqual(events, [{ k: "done" }]);
});
test("runTurn does not stream when aborted while the initial send connects", async () => {
let releaseSend;
const session = fakeSession([], { sessionId: "slow-connect-session" });
session.send = (message) => new Promise((resolve) => {
session.sentMessages.push(message);
releaseSend = resolve;
});
const mgr = new CodebuddySessionManager({
loadSdk: async () => ({
unstable_v2_createSession: () => session,
unstable_v2_resumeSession: () => session,
}),
});
const controller = new AbortController();
const { events, emitter } = collector();
const runPromise = mgr.runTurn({
sessionKey: "slow-connect-key",
prompt: "must not run",
attachments: [],
options: { abortController: controller },
emitter,
sessionOptions: {},
});
await new Promise((resolve) => setImmediate(resolve));
assert.equal(typeof releaseSend, "function");
controller.abort();
releaseSend();
const result = await runPromise;
assert.deepEqual(result, {
sessionId: "slow-connect-session",
usedV2: true,
});
assert.deepEqual(session.sentMessages, ["must not run"]);
assert.equal(session.interruptCalls, 1);
assert.deepEqual(events, [{ k: "done" }]);
});
test("runTurn treats an abort rejection while streaming as normal completion", async () => {
let rejectStream;
const session = fakeSession([], { sessionId: "stream-abort-session" });
session.stream = async function* stream() {
await new Promise((_resolve, reject) => {
rejectStream = reject;
});
};
session.interrupt = async () => {
rejectStream?.(new Error("interrupted"));
};
const mgr = new CodebuddySessionManager({
loadSdk: async () => ({
unstable_v2_createSession: () => session,
unstable_v2_resumeSession: () => session,
}),
});
const controller = new AbortController();
const { events, emitter } = collector();
const runPromise = mgr.runTurn({
sessionKey: "stream-abort-key",
prompt: "wait",
attachments: [],
options: { abortController: controller },
emitter,
sessionOptions: {},
});
await new Promise((resolve) => setImmediate(resolve));
controller.abort();
assert.deepEqual(await runPromise, {
sessionId: "stream-abort-session",
usedV2: true,
});
assert.ok(mgr.sessions.has("stream-abort-key"));
assert.equal(session.closed, false);
assert.deepEqual(events, [
{ k: "sessionId", s: "stream-abort-session" },
{ k: "done" },
]);
});
test("steer returns unsupported when no session exists", async () => {
const mgr = new CodebuddySessionManager();
const { emitter } = collector();
const result = await mgr.steer({
sessionKey: "nonexistent",
prompt: "follow up",
attachments: [],
emitter,
});
assert.deepEqual(result, { status: "unsupported" });
});
test("steer stays unsupported because Session.send resets the active SDK stream", async () => {
const mgr = new CodebuddySessionManager();
const session = fakeSession([]);
mgr.sessions.set("steer-key", {
session,
fingerprint: computeOptionsFingerprint({}),
});
const result = await mgr.steer({
sessionKey: "steer-key",
prompt: "now do this",
attachments: [],
});
assert.deepEqual(result, { status: "unsupported" });
assert.deepEqual(session.sentMessages, []);
});
test("closeSession removes and closes the session", () => {
const mgr = new CodebuddySessionManager();
const session = fakeSession([]);
mgr.sessions.set("close-key", { session, fingerprint: null });
mgr.closeSession("close-key");
assert.ok(!mgr.sessions.has("close-key"));
assert.ok(session.closed);
});
test("closeForChat closes all sessions matching the chat prefix", () => {
const mgr = new CodebuddySessionManager();
const s1 = fakeSession([]);
const s2 = fakeSession([]);
const s3 = fakeSession([]);
mgr.sessions.set("chat1\u0000codebuddy\u0000/bin/cb\u0000sdk", { session: s1, fingerprint: null });
mgr.sessions.set("chat1\u0000codebuddy\u0000/other/cb\u0000sdk", { session: s2, fingerprint: null });
mgr.sessions.set("chat2\u0000codebuddy\u0000/bin/cb\u0000sdk", { session: s3, fingerprint: null });
mgr.closeForChat("chat1");
assert.ok(!mgr.sessions.has("chat1\u0000codebuddy\u0000/bin/cb\u0000sdk"));
assert.ok(!mgr.sessions.has("chat1\u0000codebuddy\u0000/other/cb\u0000sdk"));
assert.ok(mgr.sessions.has("chat2\u0000codebuddy\u0000/bin/cb\u0000sdk"));
assert.ok(s1.closed);
assert.ok(s2.closed);
assert.ok(!s3.closed);
});
test("closeForChat cancels pending elicitations scoped to the chat", () => {
const mgr = new CodebuddySessionManager();
const resolved = [];
mgr.elicitationPending.set("el-chat1", {
resolve: (v) => resolved.push(["el-chat1", v]),
reject: () => {},
chatSessionId: "chat1",
});
mgr.elicitationPending.set("el-chat2", {
resolve: (v) => resolved.push(["el-chat2", v]),
reject: () => {},
chatSessionId: "chat2",
});
mgr.closeForChat("chat1");
assert.deepEqual(resolved, [["el-chat1", { action: "cancel" }]]);
assert.ok(!mgr.elicitationPending.has("el-chat1"));
assert.ok(mgr.elicitationPending.has("el-chat2"));
});
test("closeAll closes every session", () => {
const mgr = new CodebuddySessionManager();
const s1 = fakeSession([]);
const s2 = fakeSession([]);
mgr.sessions.set("a", { session: s1, fingerprint: null });
mgr.sessions.set("b", { session: s2, fingerprint: null });
mgr.closeAll();
assert.equal(mgr.sessions.size, 0);
assert.ok(s1.closed);
assert.ok(s2.closed);
});
test("closeAll cancels every pending elicitation", () => {
const mgr = new CodebuddySessionManager();
const resolved = [];
mgr.elicitationPending.set("el-a", {
resolve: (v) => resolved.push(["el-a", v]),
reject: () => {},
chatSessionId: "chat1",
});
mgr.elicitationPending.set("el-b", {
resolve: (v) => resolved.push(["el-b", v]),
reject: () => {},
chatSessionId: "chat2",
});
mgr.closeAll();
assert.equal(mgr.elicitationPending.size, 0);
assert.deepEqual(resolved, [
["el-a", { action: "cancel" }],
["el-b", { action: "cancel" }],
]);
});
test("setModel returns false when session does not exist", async () => {
const mgr = new CodebuddySessionManager();
const result = await mgr.setModel("missing", "new-model");
assert.equal(result, false);
});
test("setModel delegates to the session", async () => {
const mgr = new CodebuddySessionManager();
const session = fakeSession([]);
mgr.sessions.set("model-key", { session, fingerprint: null });
const result = await mgr.setModel("model-key", "glm-5");
assert.equal(result, true);
assert.equal(session._model, "glm-5");
});
test("resolveElicitation resolves pending and returns true", () => {
const mgr = new CodebuddySessionManager();
let resolved;
mgr.elicitationPending.set("el-1", {
resolve: (v) => { resolved = v; },
reject: () => {},
});
const ok = mgr.resolveElicitation("el-1", { action: "accept" });
assert.equal(ok, true);
assert.deepEqual(resolved, { action: "accept" });
assert.ok(!mgr.elicitationPending.has("el-1"));
});
test("resolveElicitation returns false for unknown id", () => {
const mgr = new CodebuddySessionManager();
const ok = mgr.resolveElicitation("unknown", { action: "cancel" });
assert.equal(ok, false);
});