1import * as NodeAssert from "node:assert/strict";
2
3import { describe, it } from "vite-plus/test";
4
5import {
6 buildCodexAdditionalContext,
7 buildCodexDeveloperInstructions,
8} from "./CodexDeveloperInstructions.ts";
9
10describe("buildCodexDeveloperInstructions", () => {
11 it("appends runtime info after the mode instructions", () => {
12 const instructions = runtimeInstructions({
13 model: "gpt-5.3-codex",
14 reasoningEffort: "high",
15 });
16
17 NodeAssert.match(
18 buildCodexDeveloperInstructions("default"),
19 /^<collaboration_mode># Collaboration Mode: Default/,
20 );
21 NodeAssert.match(instructions, /T3 Code/);
22 NodeAssert.match(instructions, /Codex harness/);
23 NodeAssert.match(instructions, /as gpt-5\.3-codex with high reasoning effort/);
24 });
25
26 it("describes Markdown media support in the runtime context in both modes", () => {
27 {
28 const instructions = runtimeInstructions({
29 model: "gpt-5.3-codex",
30 reasoningEffort: "high",
31 });
32 NodeAssert.match(
33 instructions,
34 /<runtime_info>.*embed images and videos.*Markdown.*<\/runtime_info>/,
35 );
36 }
37 });
38
39 it("includes runtime info alongside plan mode instructions", () => {
40 const instructions = runtimeInstructions({
41 model: "gpt-5.3-codex",
42 reasoningEffort: "medium",
43 });
44
45 NodeAssert.match(buildCodexDeveloperInstructions("plan"), /^<collaboration_mode># Plan Mode/);
46 NodeAssert.match(instructions, /as gpt-5\.3-codex with medium reasoning effort/);
47 });
48
49 it("varies with the model and effort of each turn", () => {
50 const first = runtimeInstructions({
51 model: "gpt-5.3-codex",
52 reasoningEffort: "medium",
53 });
54 const second = runtimeInstructions({
55 model: "gpt-5.4",
56 reasoningEffort: "high",
57 });
58
59 NodeAssert.notEqual(first, second);
60 });
61
62 it("flattens multiline metadata into single-line runtime info", () => {
63 const instructions = runtimeInstructions({
64 model: "gpt\n5.3\ncodex",
65 reasoningEffort: " high\neffort ",
66 });
67
68 NodeAssert.match(instructions, /as gpt 5\.3 codex with high effort reasoning effort/);
69 NodeAssert.doesNotMatch(instructions, /<runtime_info>[^<]*\n/);
70 });
71});
72
73describe("T3 browser developer instructions", () => {
74 const runtime = { model: "gpt-5.3-codex", reasoningEffort: "high" };
75
76 it("prefers the product-native preview tools in both collaboration modes", () => {
77 {
78 const instructions = toolInstructions(runtime, true);
79 NodeAssert.match(instructions, /t3-code/);
80 NodeAssert.match(instructions, /preview_status/);
81 NodeAssert.match(instructions, /preview_open/);
82 NodeAssert.match(instructions, /Do not switch to global browser skills/);
83 }
84 });
85
86 it("omits the browser block entirely when the preview tools are not attached", () => {
87 for (const mode of ["default", "plan"] as const) {
88 const instructions = toolInstructions(runtime, false);
89 NodeAssert.doesNotMatch(instructions, /preview_status/);
90 NodeAssert.doesNotMatch(instructions, /preview_open/);
91 NodeAssert.doesNotMatch(instructions, /T3 Code collaborative browser/);
92 // Steering away from other browser automation must go with the tools;
93 // keeping it would leave the model talked out of its only option.
94 NodeAssert.doesNotMatch(instructions, /Do not switch to global browser skills/);
95 // The rest of the collaboration mode is untouched.
96 NodeAssert.match(buildCodexDeveloperInstructions(mode), /<collaboration_mode>/);
97 NodeAssert.match(buildCodexDeveloperInstructions(mode), /<\/collaboration_mode>/);
98 }
99 });
100
101 it("tracks the turn's MCP configuration rather than defaulting to on", () => {
102 NodeAssert.match(toolInstructions(runtime, true), /preview_open/);
103 NodeAssert.doesNotMatch(toolInstructions(runtime, false), /preview_open/);
104 });
105});
106
107function runtimeInstructions(runtime: Parameters<typeof buildCodexAdditionalContext>[0]) {
108 return buildCodexAdditionalContext(runtime).t3_code_runtime!.value;
109}
110function toolInstructions(
111 runtime: Parameters<typeof buildCodexAdditionalContext>[0],
112 available: boolean,
113) {
114 return buildCodexAdditionalContext(runtime, available).t3_code_tools?.value ?? "";
115}