Files
pi-gui/test/protocol.test.js

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" },
},
);
});