213 lines
4.4 KiB
JavaScript
213 lines
4.4 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
import {
|
|
MAX_FRAME_BYTES,
|
|
ProtocolError,
|
|
parseRequestFrame,
|
|
validateEvent,
|
|
} from "../src/protocol/index.js";
|
|
|
|
const request = (value) =>
|
|
JSON.stringify({ version: "v1", id: "request-1", ...value });
|
|
|
|
test("accepts a command scoped to its selected agent", () => {
|
|
assert.deepEqual(
|
|
parseRequestFrame(
|
|
request({
|
|
op: "prompt",
|
|
agentId: "agent-main",
|
|
payload: { message: "implement the protocol" },
|
|
}),
|
|
),
|
|
{
|
|
version: "v1",
|
|
id: "request-1",
|
|
op: "prompt",
|
|
agentId: "agent-main",
|
|
payload: { message: "implement the protocol" },
|
|
},
|
|
);
|
|
});
|
|
|
|
test("accepts an agent transcript request without a synthetic cursor", () => {
|
|
assert.deepEqual(
|
|
parseRequestFrame(request({ op: "get_transcript", agentId: "agent-main" })),
|
|
{
|
|
version: "v1",
|
|
id: "request-1",
|
|
op: "get_transcript",
|
|
agentId: "agent-main",
|
|
},
|
|
);
|
|
});
|
|
|
|
test("accepts bridge-managed directory and session operations", () => {
|
|
assert.deepEqual(parseRequestFrame(request({ op: "list_directories" })), {
|
|
version: "v1",
|
|
id: "request-1",
|
|
op: "list_directories",
|
|
});
|
|
assert.deepEqual(
|
|
parseRequestFrame(
|
|
request({
|
|
op: "forget_directory",
|
|
payload: { worktreePath: "/projects/feature" },
|
|
}),
|
|
),
|
|
{
|
|
version: "v1",
|
|
id: "request-1",
|
|
op: "forget_directory",
|
|
payload: { worktreePath: "/projects/feature" },
|
|
},
|
|
);
|
|
assert.deepEqual(
|
|
parseRequestFrame(request({ op: "list_sessions", agentId: "agent-main" })),
|
|
{
|
|
version: "v1",
|
|
id: "request-1",
|
|
op: "list_sessions",
|
|
agentId: "agent-main",
|
|
},
|
|
);
|
|
assert.deepEqual(
|
|
parseRequestFrame(request({ op: "new_session", agentId: "agent-main" })),
|
|
{
|
|
version: "v1",
|
|
id: "request-1",
|
|
op: "new_session",
|
|
agentId: "agent-main",
|
|
},
|
|
);
|
|
assert.deepEqual(
|
|
parseRequestFrame(
|
|
request({
|
|
op: "switch_session",
|
|
agentId: "agent-main",
|
|
payload: { sessionPath: "/sessions/session.jsonl" },
|
|
}),
|
|
),
|
|
{
|
|
version: "v1",
|
|
id: "request-1",
|
|
op: "switch_session",
|
|
agentId: "agent-main",
|
|
payload: { sessionPath: "/sessions/session.jsonl" },
|
|
},
|
|
);
|
|
assert.throws(
|
|
() =>
|
|
parseRequestFrame(
|
|
request({
|
|
op: "switch_session",
|
|
agentId: "agent-main",
|
|
payload: { sessionPath: "relative.jsonl" },
|
|
}),
|
|
),
|
|
/must be absolute/,
|
|
);
|
|
});
|
|
|
|
test("accepts an agent session-statistics request", () => {
|
|
assert.deepEqual(
|
|
parseRequestFrame(
|
|
request({ op: "get_session_stats", agentId: "agent-main" }),
|
|
),
|
|
{
|
|
version: "v1",
|
|
id: "request-1",
|
|
op: "get_session_stats",
|
|
agentId: "agent-main",
|
|
},
|
|
);
|
|
});
|
|
|
|
test("accepts a default composer submit request", () => {
|
|
assert.deepEqual(
|
|
parseRequestFrame(
|
|
request({
|
|
op: "submit_prompt",
|
|
agentId: "agent-main",
|
|
payload: { message: "Continue" },
|
|
}),
|
|
),
|
|
{
|
|
version: "v1",
|
|
id: "request-1",
|
|
op: "submit_prompt",
|
|
agentId: "agent-main",
|
|
payload: { message: "Continue" },
|
|
},
|
|
);
|
|
});
|
|
|
|
test("accepts a selected agent get_commands request", () => {
|
|
assert.deepEqual(
|
|
parseRequestFrame(request({ op: "get_commands", agentId: "agent-main" })),
|
|
{
|
|
version: "v1",
|
|
id: "request-1",
|
|
op: "get_commands",
|
|
agentId: "agent-main",
|
|
},
|
|
);
|
|
});
|
|
|
|
test("rejects malformed, unknown, and oversized frames", () => {
|
|
assert.throws(() => parseRequestFrame("not json"), ProtocolError);
|
|
assert.throws(
|
|
() => parseRequestFrame(request({ op: "teleport" })),
|
|
/not supported/,
|
|
);
|
|
assert.throws(
|
|
() => parseRequestFrame("x".repeat(MAX_FRAME_BYTES + 1)),
|
|
/frame exceeds/,
|
|
);
|
|
});
|
|
|
|
test("rejects cross-worktree routing fields on agent commands", () => {
|
|
assert.throws(
|
|
() =>
|
|
parseRequestFrame(
|
|
request({
|
|
op: "prompt",
|
|
agentId: "agent-main",
|
|
payload: { message: "wrong worktree", worktreePath: "/other" },
|
|
}),
|
|
),
|
|
/not supported/,
|
|
);
|
|
});
|
|
|
|
test("requires explicit absolute worktree selection", () => {
|
|
assert.throws(
|
|
() =>
|
|
parseRequestFrame(
|
|
request({
|
|
op: "select_agent",
|
|
payload: { worktreePath: "relative/project" },
|
|
}),
|
|
),
|
|
/must be absolute/,
|
|
);
|
|
});
|
|
|
|
test("normalizes sequenced bridge events", () => {
|
|
assert.deepEqual(
|
|
validateEvent({
|
|
version: "v1",
|
|
seq: 2,
|
|
type: "extension_ui_request",
|
|
agentId: "agent-main",
|
|
data: { id: "extension-1", method: "confirm" },
|
|
}),
|
|
{
|
|
version: "v1",
|
|
seq: 2,
|
|
type: "extension_ui_request",
|
|
agentId: "agent-main",
|
|
data: { id: "extension-1", method: "confirm" },
|
|
},
|
|
);
|
|
});
|