import { describe, expect, it } from "vitest"; import { PROVIDER_SEND_TURN_MAX_ATTACHMENTS, providerEventSchema, providerRespondToRequestInputSchema, providerSendTurnInputSchema, providerSessionStartInputSchema,} from "./provider"; describe("providerSessionStartInputSchema", () => { it("defaults to codex with safe policies", () => { const parsed = providerSessionStartInputSchema.parse({}); expect(parsed.provider).toBe("codex"); expect(parsed.approvalPolicy).toBe("never"); expect(parsed.sandboxMode).toBe("workspace-write"); }); it("accepts optional resumeThreadId", () => { const parsed = providerSessionStartInputSchema.parse({ resumeThreadId: "thread_123", }); expect(parsed.resumeThreadId).toBe("thread_123"); }); it("rejects blank resumeThreadId", () => { expect(() => providerSessionStartInputSchema.parse({ resumeThreadId: " ", }), ).toThrow(); });}); describe("providerSendTurnInputSchema", () => { it("trims input text and optional model/effort", () => { const parsed = providerSendTurnInputSchema.parse({ sessionId: "sess_1", input: " summarize this repo ", model: " gpt-5.2-codex ", effort: " high ", }); expect(parsed.input).toBe("summarize this repo"); expect(parsed.attachments).toEqual([]); expect(parsed.model).toBe("gpt-5.2-codex"); expect(parsed.effort).toBe("high"); }); it("accepts image-only turns", () => { const parsed = providerSendTurnInputSchema.parse({ sessionId: "sess_1", attachments: [ { type: "image", name: "diagram.png", mimeType: "image/png", sizeBytes: 1_024, dataUrl: "data:image/png;base64,AAAA", }, ], }); expect(parsed.input).toBeUndefined(); expect(parsed.attachments).toHaveLength(1); }); it("rejects turns with neither text nor attachments", () => { expect(() => providerSendTurnInputSchema.parse({ sessionId: "sess_1", }), ).toThrow(); }); it("rejects non-image data urls", () => { expect(() => providerSendTurnInputSchema.parse({ sessionId: "sess_1", attachments: [ { type: "image", name: "not-image.txt", mimeType: "text/plain", sizeBytes: 25, dataUrl: "data:text/plain;base64,QQ==", }, ], }), ).toThrow(); }); it("rejects more than the max attachment count", () => { expect(() => providerSendTurnInputSchema.parse({ sessionId: "sess_1", attachments: Array.from({ length: PROVIDER_SEND_TURN_MAX_ATTACHMENTS + 1 }, (_, index) => ({ type: "image" as const, name: `image-${index}.png`, mimeType: "image/png", sizeBytes: 1_024, dataUrl: "data:image/png;base64,AAAA", })), }), ).toThrow(); });}); describe("providerEventSchema", () => { it("accepts notification events with routing metadata", () => { const parsed = providerEventSchema.parse({ id: "evt_1", kind: "notification", provider: "codex", sessionId: "sess_1", createdAt: "2026-01-01T00:00:00.000Z", method: "item/agentMessage/delta", threadId: "thr_1", turnId: "turn_1", itemId: "item_1", textDelta: "hi", }); expect(parsed.method).toBe("item/agentMessage/delta"); }); it("accepts request approval metadata", () => { const parsed = providerEventSchema.parse({ id: "evt_2", kind: "request", provider: "codex", sessionId: "sess_1", createdAt: "2026-01-01T00:00:00.000Z", method: "item/commandExecution/requestApproval", requestId: "req_123", requestKind: "command", }); expect(parsed.requestId).toBe("req_123"); expect(parsed.requestKind).toBe("command"); });}); describe("providerRespondToRequestInputSchema", () => { it("accepts valid decisions", () => { const parsed = providerRespondToRequestInputSchema.parse({ sessionId: "sess_1", requestId: "req_1", decision: "acceptForSession", }); expect(parsed.decision).toBe("acceptForSession"); }); it("rejects unknown decisions", () => { expect(() => providerRespondToRequestInputSchema.parse({ sessionId: "sess_1", requestId: "req_1", decision: "always", }), ).toThrow(); });});
import { describe, expect, it } from "vitest";
import {
PROVIDER_SEND_TURN_MAX_ATTACHMENTS,
providerEventSchema,
providerRespondToRequestInputSchema,
providerSendTurnInputSchema,
providerSessionStartInputSchema,
} from "./provider";
describe("providerSessionStartInputSchema", () => {
it("defaults to codex with safe policies", () => {
const parsed = providerSessionStartInputSchema.parse({});
expect(parsed.provider).toBe("codex");
expect(parsed.approvalPolicy).toBe("never");
expect(parsed.sandboxMode).toBe("workspace-write");
});
it("accepts optional resumeThreadId", () => {
const parsed = providerSessionStartInputSchema.parse({
resumeThreadId: "thread_123",
});
expect(parsed.resumeThreadId).toBe("thread_123");
});
it("rejects blank resumeThreadId", () => {
expect(() =>
providerSessionStartInputSchema.parse({
resumeThreadId: " ",
}),
).toThrow();
});
});
describe("providerSendTurnInputSchema", () => {
it("trims input text and optional model/effort", () => {
const parsed = providerSendTurnInputSchema.parse({
sessionId: "sess_1",
input: " summarize this repo ",
model: " gpt-5.2-codex ",
effort: " high ",
});
expect(parsed.input).toBe("summarize this repo");
expect(parsed.attachments).toEqual([]);
expect(parsed.model).toBe("gpt-5.2-codex");
expect(parsed.effort).toBe("high");
});
it("accepts image-only turns", () => {
const parsed = providerSendTurnInputSchema.parse({
sessionId: "sess_1",
attachments: [
{
type: "image",
name: "diagram.png",
mimeType: "image/png",
sizeBytes: 1_024,
dataUrl: "data:image/png;base64,AAAA",
},
],
});
expect(parsed.input).toBeUndefined();
expect(parsed.attachments).toHaveLength(1);
});
it("rejects turns with neither text nor attachments", () => {
expect(() =>
providerSendTurnInputSchema.parse({
sessionId: "sess_1",
}),
).toThrow();
});
it("rejects non-image data urls", () => {
expect(() =>
providerSendTurnInputSchema.parse({
sessionId: "sess_1",
attachments: [
{
type: "image",
name: "not-image.txt",
mimeType: "text/plain",
sizeBytes: 25,
dataUrl: "data:text/plain;base64,QQ==",
},
],
}),
).toThrow();
});
it("rejects more than the max attachment count", () => {
expect(() =>
providerSendTurnInputSchema.parse({
sessionId: "sess_1",
attachments: Array.from({ length: PROVIDER_SEND_TURN_MAX_ATTACHMENTS + 1 }, (_, index) => ({
type: "image" as const,
name: `image-${index}.png`,
mimeType: "image/png",
sizeBytes: 1_024,
dataUrl: "data:image/png;base64,AAAA",
})),
}),
).toThrow();
});
});
describe("providerEventSchema", () => {
it("accepts notification events with routing metadata", () => {
const parsed = providerEventSchema.parse({
id: "evt_1",
kind: "notification",
provider: "codex",
sessionId: "sess_1",
createdAt: "2026-01-01T00:00:00.000Z",
method: "item/agentMessage/delta",
threadId: "thr_1",
turnId: "turn_1",
itemId: "item_1",
textDelta: "hi",
});
expect(parsed.method).toBe("item/agentMessage/delta");
});
it("accepts request approval metadata", () => {
const parsed = providerEventSchema.parse({
id: "evt_2",
kind: "request",
provider: "codex",
sessionId: "sess_1",
createdAt: "2026-01-01T00:00:00.000Z",
method: "item/commandExecution/requestApproval",
requestId: "req_123",
requestKind: "command",
});
expect(parsed.requestId).toBe("req_123");
expect(parsed.requestKind).toBe("command");
});
});
describe("providerRespondToRequestInputSchema", () => {
it("accepts valid decisions", () => {
const parsed = providerRespondToRequestInputSchema.parse({
sessionId: "sess_1",
requestId: "req_1",
decision: "acceptForSession",
});
expect(parsed.decision).toBe("acceptForSession");
});
it("rejects unknown decisions", () => {
expect(() =>
providerRespondToRequestInputSchema.parse({
sessionId: "sess_1",
requestId: "req_1",
decision: "always",
}),
).toThrow();
});
});