import { assert, it } from "@effect/vitest";import * as Schema from "effect/Schema"; import * as CodexSchema from "./schema.ts"; const isGetAccountResponse = Schema.is(CodexSchema.V2GetAccountResponse);const isThreadReadResponse = Schema.is(CodexSchema.V2ThreadReadResponse);const isThreadResumeResponse = Schema.is(CodexSchema.V2ThreadResumeResponse);const isThreadRollbackResponse = Schema.is(CodexSchema.V2ThreadRollbackResponse);const isThreadForkResponse = Schema.is(CodexSchema.V2ThreadForkResponse);const isTurnCompletedNotification = Schema.is(CodexSchema.V2TurnCompletedNotification);const decodeThreadResumeResponse = Schema.decodeUnknownSync(CodexSchema.V2ThreadResumeResponse); it("keeps async questions in live notifications and thread history", () => { const item = { type: "agentMessage", id: "question-1", text: "Which package?\n- pnpm\n- npm\n\nWhat should it be named?", phase: "final_answer", delivery: "async", questions: [ { title: "Which package manager?", options: ["pnpm", "npm"] }, { title: "What should it be named?" }, ], } as const; for (const schema of [ CodexSchema.ServerNotification__ThreadItem, CodexSchema.V2ItemStartedNotification__ThreadItem, CodexSchema.V2ItemCompletedNotification__ThreadItem, CodexSchema.V2ThreadReadResponse__ThreadItem, CodexSchema.V2ThreadResumeResponse__ThreadItem, ]) { assert.deepEqual(Schema.decodeUnknownSync(schema)(item), item); }}); it("accepts Codex 0.150 multi-agent values", () => { const schemas = [ CodexSchema.ServerNotification__SubAgentActivityKind, CodexSchema.V2ItemStartedNotification__SubAgentActivityKind, CodexSchema.V2ItemCompletedNotification__SubAgentActivityKind, CodexSchema.V2ThreadReadResponse__SubAgentActivityKind, CodexSchema.V2ThreadResumeResponse__SubAgentActivityKind, ]; for (const schema of schemas) { assert.equal(Schema.is(schema)("completed"), true); } for (const tool of ["sendMessage", "followupTask", "interruptAgent", "listAgents"]) { assert.equal(Schema.is(CodexSchema.ServerNotification__CollabAgentTool)(tool), true); assert.equal(Schema.is(CodexSchema.V2ThreadResumeResponse__CollabAgentTool)(tool), true); } assert.equal( Schema.is(CodexSchema.ServerNotification__CollabAgentToolCallStatus)("interrupted"), true, ); assert.equal( Schema.is(CodexSchema.V2ThreadResumeResponse__CollabAgentToolCallStatus)("interrupted"), true, ); const resumeResponse = { approvalPolicy: "never", approvalsReviewer: "user", cwd: "/tmp/project", model: "gpt-5.6-sol", modelProvider: "openai", sandbox: { type: "dangerFullAccess" }, thread: { cliVersion: "0.150.0", createdAt: 0, cwd: "/tmp/project", ephemeral: false, id: "root-thread", modelProvider: "openai", preview: "", sessionId: "session-1", source: "cli", status: { type: "idle" }, turns: [ { id: "turn-1", status: "completed", items: [ { agentsStates: {}, id: "item-1", receiverThreadIds: ["child-thread"], senderThreadId: "root-thread", status: "interrupted", tool: "followupTask", type: "collabAgentToolCall", }, ], }, ], updatedAt: 0, }, }; assert.equal(Schema.is(CodexSchema.V2ThreadResumeResponse)(resumeResponse), true);}); it("accepts Codex rate limit errors for thread responses", () => { const failedThread = { cliVersion: "0.150.0", createdAt: 0, cwd: "/tmp/project", ephemeral: false, id: "thread-1", modelProvider: "openai", preview: "", sessionId: "session-1", source: "cli", status: { type: "idle" }, turns: [ { error: { codexErrorInfo: "rateLimitExceeded", message: "Rate limit exceeded", }, id: "turn-1", items: [], status: "failed", }, ], updatedAt: 0, }; assert.equal(isThreadReadResponse({ thread: failedThread }), true); assert.equal( isThreadResumeResponse({ approvalPolicy: "never", approvalsReviewer: "user", cwd: "/tmp/project", model: "gpt-5.6-sol", modelProvider: "openai", sandbox: { type: "dangerFullAccess" }, thread: failedThread, }), true, ); assert.equal(isThreadRollbackResponse({ thread: failedThread }), true);}); it("accepts Codex misalignment policy errors for thread responses", () => { const failedThread = { cliVersion: "0.150.0", createdAt: 0, cwd: "/tmp/project", ephemeral: false, id: "thread-1", modelProvider: "openai", preview: "", sessionId: "session-1", source: "cli", status: { type: "idle" }, turns: [ { error: { codexErrorInfo: "misalignmentPolicyViolation", message: "Misalignment policy violation", }, id: "turn-1", items: [], status: "failed", }, ], updatedAt: 0, }; const resumeLikeResponse = { approvalPolicy: "never", approvalsReviewer: "user", cwd: "/tmp/project", model: "gpt-5.6-sol", modelProvider: "openai", sandbox: { type: "dangerFullAccess" }, thread: failedThread, }; assert.equal(isThreadReadResponse({ thread: failedThread }), true); assert.equal(isThreadResumeResponse(resumeLikeResponse), true); assert.equal(isThreadRollbackResponse({ thread: failedThread }), true); assert.equal(isThreadForkResponse(resumeLikeResponse), true); const decodedResume = decodeThreadResumeResponse(resumeLikeResponse); assert.equal(decodedResume.thread.turns[0]?.error?.codexErrorInfo, "misalignmentPolicyViolation"); assert.equal( isTurnCompletedNotification({ threadId: "thread-1", turn: { error: { codexErrorInfo: "misalignmentPolicyViolation", message: "Misalignment policy violation", }, id: "turn-1", items: [], status: "failed", }, }), true, );}); it("accepts Codex 0.150 account plan values", () => { const planTypes = [ "self_serve_business_prolite", "ent26", "enterprise_cbp_automation", "edu_plus", "edu_pro", ]; for (const planType of planTypes) { const accountResponse = { account: { email: "user@example.com", planType, type: "chatgpt", }, requiresOpenaiAuth: true, }; assert.equal(isGetAccountResponse(accountResponse), true); }});
import { assert, it } from "@effect/vitest";
import * as Schema from "effect/Schema";
import * as CodexSchema from "./schema.ts";
const isGetAccountResponse = Schema.is(CodexSchema.V2GetAccountResponse);
const isThreadReadResponse = Schema.is(CodexSchema.V2ThreadReadResponse);
const isThreadResumeResponse = Schema.is(CodexSchema.V2ThreadResumeResponse);
const isThreadRollbackResponse = Schema.is(CodexSchema.V2ThreadRollbackResponse);
const isThreadForkResponse = Schema.is(CodexSchema.V2ThreadForkResponse);
const isTurnCompletedNotification = Schema.is(CodexSchema.V2TurnCompletedNotification);
const decodeThreadResumeResponse = Schema.decodeUnknownSync(CodexSchema.V2ThreadResumeResponse);
it("keeps async questions in live notifications and thread history", () => {
const item = {
type: "agentMessage",
id: "question-1",
text: "Which package?\n- pnpm\n- npm\n\nWhat should it be named?",
phase: "final_answer",
delivery: "async",
questions: [
{ title: "Which package manager?", options: ["pnpm", "npm"] },
{ title: "What should it be named?" },
],
} as const;
for (const schema of [
CodexSchema.ServerNotification__ThreadItem,
CodexSchema.V2ItemStartedNotification__ThreadItem,
CodexSchema.V2ItemCompletedNotification__ThreadItem,
CodexSchema.V2ThreadReadResponse__ThreadItem,
CodexSchema.V2ThreadResumeResponse__ThreadItem,
]) {
assert.deepEqual(Schema.decodeUnknownSync(schema)(item), item);
}
});
it("accepts Codex 0.150 multi-agent values", () => {
const schemas = [
CodexSchema.ServerNotification__SubAgentActivityKind,
CodexSchema.V2ItemStartedNotification__SubAgentActivityKind,
CodexSchema.V2ItemCompletedNotification__SubAgentActivityKind,
CodexSchema.V2ThreadReadResponse__SubAgentActivityKind,
CodexSchema.V2ThreadResumeResponse__SubAgentActivityKind,
];
for (const schema of schemas) {
assert.equal(Schema.is(schema)("completed"), true);
}
for (const tool of ["sendMessage", "followupTask", "interruptAgent", "listAgents"]) {
assert.equal(Schema.is(CodexSchema.ServerNotification__CollabAgentTool)(tool), true);
assert.equal(Schema.is(CodexSchema.V2ThreadResumeResponse__CollabAgentTool)(tool), true);
}
assert.equal(
Schema.is(CodexSchema.ServerNotification__CollabAgentToolCallStatus)("interrupted"),
true,
);
assert.equal(
Schema.is(CodexSchema.V2ThreadResumeResponse__CollabAgentToolCallStatus)("interrupted"),
true,
);
const resumeResponse = {
approvalPolicy: "never",
approvalsReviewer: "user",
cwd: "/tmp/project",
model: "gpt-5.6-sol",
modelProvider: "openai",
sandbox: { type: "dangerFullAccess" },
thread: {
cliVersion: "0.150.0",
createdAt: 0,
cwd: "/tmp/project",
ephemeral: false,
id: "root-thread",
modelProvider: "openai",
preview: "",
sessionId: "session-1",
source: "cli",
status: { type: "idle" },
turns: [
{
id: "turn-1",
status: "completed",
items: [
{
agentsStates: {},
id: "item-1",
receiverThreadIds: ["child-thread"],
senderThreadId: "root-thread",
status: "interrupted",
tool: "followupTask",
type: "collabAgentToolCall",
},
],
},
],
updatedAt: 0,
},
};
assert.equal(Schema.is(CodexSchema.V2ThreadResumeResponse)(resumeResponse), true);
});
it("accepts Codex rate limit errors for thread responses", () => {
const failedThread = {
cliVersion: "0.150.0",
createdAt: 0,
cwd: "/tmp/project",
ephemeral: false,
id: "thread-1",
modelProvider: "openai",
preview: "",
sessionId: "session-1",
source: "cli",
status: { type: "idle" },
turns: [
{
error: {
codexErrorInfo: "rateLimitExceeded",
message: "Rate limit exceeded",
},
id: "turn-1",
items: [],
status: "failed",
},
],
updatedAt: 0,
};
assert.equal(isThreadReadResponse({ thread: failedThread }), true);
assert.equal(
isThreadResumeResponse({
approvalPolicy: "never",
approvalsReviewer: "user",
cwd: "/tmp/project",
model: "gpt-5.6-sol",
modelProvider: "openai",
sandbox: { type: "dangerFullAccess" },
thread: failedThread,
}),
true,
);
assert.equal(isThreadRollbackResponse({ thread: failedThread }), true);
});
it("accepts Codex misalignment policy errors for thread responses", () => {
const failedThread = {
cliVersion: "0.150.0",
createdAt: 0,
cwd: "/tmp/project",
ephemeral: false,
id: "thread-1",
modelProvider: "openai",
preview: "",
sessionId: "session-1",
source: "cli",
status: { type: "idle" },
turns: [
{
error: {
codexErrorInfo: "misalignmentPolicyViolation",
message: "Misalignment policy violation",
},
id: "turn-1",
items: [],
status: "failed",
},
],
updatedAt: 0,
};
const resumeLikeResponse = {
approvalPolicy: "never",
approvalsReviewer: "user",
cwd: "/tmp/project",
model: "gpt-5.6-sol",
modelProvider: "openai",
sandbox: { type: "dangerFullAccess" },
thread: failedThread,
};
assert.equal(isThreadReadResponse({ thread: failedThread }), true);
assert.equal(isThreadResumeResponse(resumeLikeResponse), true);
assert.equal(isThreadRollbackResponse({ thread: failedThread }), true);
assert.equal(isThreadForkResponse(resumeLikeResponse), true);
const decodedResume = decodeThreadResumeResponse(resumeLikeResponse);
assert.equal(decodedResume.thread.turns[0]?.error?.codexErrorInfo, "misalignmentPolicyViolation");
assert.equal(
isTurnCompletedNotification({
threadId: "thread-1",
turn: {
error: {
codexErrorInfo: "misalignmentPolicyViolation",
message: "Misalignment policy violation",
},
id: "turn-1",
items: [],
status: "failed",
},
}),
true,
);
});
it("accepts Codex 0.150 account plan values", () => {
const planTypes = [
"self_serve_business_prolite",
"ent26",
"enterprise_cbp_automation",
"edu_plus",
"edu_pro",
];
for (const planType of planTypes) {
const accountResponse = {
account: {
email: "user@example.com",
planType,
type: "chatgpt",
},
requiresOpenaiAuth: true,
};
assert.equal(isGetAccountResponse(accountResponse), true);
}
});