Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion plugins/codex/scripts/lib/codex.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,16 @@ function looksLikeVerificationCommand(command) {
);
}

// Prompts shaped by the gpt-5-4-prompting skill carry the job in a `<task>` block,
// often after other instructions, so name the thread after that block when present.
function taskThreadNameSource(prompt) {
const text = String(prompt ?? "");
const taskBlock = /<task>([\s\S]*?)(?:<\/task>|$)/.exec(text)?.[1];
return taskBlock?.trim() ? taskBlock : text;
}

function buildTaskThreadName(prompt) {
const excerpt = shorten(prompt, 56);
const excerpt = shorten(taskThreadNameSource(prompt), 56);
return excerpt ? `${TASK_THREAD_PREFIX}: ${excerpt}` : TASK_THREAD_PREFIX;
}

Expand Down
48 changes: 48 additions & 0 deletions tests/runtime.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,54 @@ test("task runs when the active provider does not require OpenAI login", () => {
assert.match(result.stdout, /Handled the requested task/);
});

test("task names the thread after the <task> block of a structured prompt", () => {
const repo = makeTempDir();
const binDir = makeTempDir();
installFakeCodex(binDir);
initGitRepo(repo);
const promptPath = path.join(repo, "prompt.txt");
fs.writeFileSync(
promptPath,
[
"Stay read-only.",
"<task>",
"Fix the flaky login test",
"</task>",
"<structured_output_contract>",
"Return a numbered list.",
"</structured_output_contract>"
].join("\n"),
"utf8"
);

const result = run("node", [SCRIPT, "task", "--prompt-file", promptPath], {
cwd: repo,
env: buildEnv(binDir)
});

assert.equal(result.status, 0, result.stderr);
const fakeState = JSON.parse(fs.readFileSync(path.join(binDir, "fake-codex-state.json"), "utf8"));
assert.equal(fakeState.threads[0].name, "Codex Companion Task: Fix the flaky login test");
});

test("task names the thread after the prompt when it has no <task> block", () => {
const repo = makeTempDir();
const binDir = makeTempDir();
installFakeCodex(binDir);
initGitRepo(repo);
const promptPath = path.join(repo, "prompt.txt");
fs.writeFileSync(promptPath, "check Map<string> typing in the auth module", "utf8");

const result = run("node", [SCRIPT, "task", "--prompt-file", promptPath], {
cwd: repo,
env: buildEnv(binDir)
});

assert.equal(result.status, 0, result.stderr);
const fakeState = JSON.parse(fs.readFileSync(path.join(binDir, "fake-codex-state.json"), "utf8"));
assert.equal(fakeState.threads[0].name, "Codex Companion Task: check Map<string> typing in the auth module");
});

test("task runs without auth preflight so Codex can refresh an expired session", () => {
const repo = makeTempDir();
const binDir = makeTempDir();
Expand Down