feat: add thinking option support and autonomous run handling

This commit is contained in:
Mohamed Boudra
2026-02-21 22:09:48 +07:00
parent c3c8103563
commit d7e2ab4437
35 changed files with 4701 additions and 593 deletions
@@ -0,0 +1,21 @@
import { readFileSync } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { describe, expect, it } from "vitest";
const THIS_DIR = path.dirname(fileURLToPath(import.meta.url));
const DIST_ENCRYPTED_CHANNEL_PATH = path.resolve(THIS_DIR, "../dist/encrypted-channel.js");
describe("relay dist handshake parity", () => {
it("keeps Node dist handshake message types in sync with src", () => {
const distCode = readFileSync(DIST_ENCRYPTED_CHANNEL_PATH, "utf8");
expect(distCode).toContain('type: "e2ee_hello"');
expect(distCode).toContain('type: "e2ee_ready"');
// Guard against accidentally shipping the legacy hello/ready protocol.
expect(distCode).not.toMatch(/\btype:\s*"hello"\b/);
expect(distCode).not.toMatch(/\btype:\s*"ready"\b/);
});
});
+27 -3
View File
@@ -56,6 +56,23 @@ interface E2EEReadyMessage {
type: "e2ee_ready";
}
function buildInvalidHelloError(rawText: string, parsed?: unknown): Error {
const parsedRecord =
parsed && typeof parsed === "object"
? (parsed as Record<string, unknown>)
: null;
const rawType = parsedRecord?.type;
const receivedType =
typeof rawType === "string" ? rawType : rawType === undefined ? "undefined" : typeof rawType;
const hasKey =
typeof parsedRecord?.key === "string" && parsedRecord.key.trim().length > 0;
const compact = rawText.replace(/\s+/g, " ").trim();
const preview = compact.length > 160 ? `${compact.slice(0, 157)}...` : compact;
return new Error(
`Invalid hello message (receivedType=${receivedType}, hasKey=${hasKey}, preview=${JSON.stringify(preview)})`
);
}
const HANDSHAKE_RETRY_MS = 1000;
const MAX_PENDING_SENDS = 200;
@@ -154,9 +171,16 @@ export async function createDaemonChannel(
const helloText =
typeof data === "string" ? data : new TextDecoder().decode(data);
const msg = JSON.parse(helloText) as E2EEHelloMessage;
if (msg.type !== "e2ee_hello" || !msg.key) {
throw new Error("Invalid hello message");
let parsed: unknown;
try {
parsed = JSON.parse(helloText);
} catch {
throw buildInvalidHelloError(helloText);
}
const msg = parsed as Partial<E2EEHelloMessage>;
if (msg.type !== "e2ee_hello" || typeof msg.key !== "string" || !msg.key.trim()) {
throw buildInvalidHelloError(helloText, parsed);
}
// Buffer any subsequent messages that arrive while we're doing async