Skip to content

Commit 06261ef

Browse files
committed
Lock constructor prompt on abort recovery and share the helper
1 parent 2d1f961 commit 06261ef

2 files changed

Lines changed: 19 additions & 15 deletions

File tree

src/director.test.ts

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -510,18 +510,15 @@ describe("chatDirector compaction", () => {
510510
} as unknown as ReactorInboundEvent;
511511
}
512512

513-
function chatDirectorWithContinuation(onContinuation?: () => void) {
514-
return createChatDirector("", [], {
513+
function chatDirectorWithContinuation(systemPrompt: string, onContinuation?: () => void) {
514+
return createChatDirector(systemPrompt, [], {
515515
onTasksChange: () => {},
516516
requestContinuation: onContinuation ?? (() => {}),
517517
});
518518
}
519519

520520
test("compacts at the tool.done pause once over threshold", async () => {
521-
const director = createChatDirector("Corbits operating prompt", [], {
522-
onTasksChange: () => {},
523-
requestContinuation: () => {},
524-
});
521+
const director = chatDirectorWithContinuation("Corbits operating prompt");
525522
await director.decide(overThresholdToolTurn(), longState, mockCapabilities);
526523
const actions = actionsArray(
527524
await director.decide(makeToolDoneEvent("t1"), longState, mockCapabilities),
@@ -552,7 +549,7 @@ describe("chatDirector compaction", () => {
552549
// turn); it now falls through to the base director's terminal
553550
// checkpoint + reply instead of recovering.
554551
test("does not re-issue inference for a timeout already exhausted by the harness", async () => {
555-
const director = chatDirectorWithContinuation();
552+
const director = chatDirectorWithContinuation("");
556553
const timeout = {
557554
type: "inference.error",
558555
error: { category: "timeout", message: "request timed out" },
@@ -564,7 +561,7 @@ describe("chatDirector compaction", () => {
564561
});
565562

566563
test("recovers an internally aborted inference but keeps explicit abort terminal", async () => {
567-
const director = chatDirectorWithContinuation();
564+
const director = chatDirectorWithContinuation("Corbits operating prompt");
568565
const internalAbort = {
569566
type: "inference.error",
570567
error: {
@@ -577,6 +574,10 @@ describe("chatDirector compaction", () => {
577574
await director.decide(internalAbort, longState, mockCapabilities),
578575
);
579576
expect(recovered.some((action) => action.type === "infer")).toBe(true);
577+
const infer = recovered.find((action) => action.type === "infer");
578+
const options: ExtendedInferenceOptions | undefined =
579+
infer?.type === "infer" ? infer.options : undefined;
580+
expect(options?.systemPrompt).toBe("Corbits operating prompt");
580581

581582
const explicitAbort = {
582583
type: "abort",
@@ -588,7 +589,7 @@ describe("chatDirector compaction", () => {
588589
});
589590

590591
test("does not auto-recover user-stop aborted inference errors", async () => {
591-
const director = chatDirectorWithContinuation();
592+
const director = chatDirectorWithContinuation("");
592593
const userStopAbort = {
593594
type: "inference.error",
594595
error: {
@@ -609,10 +610,10 @@ describe("chatDirector compaction", () => {
609610

610611
test("a context_overflow inference error triggers compact-and-retry, not a terminal reply", async () => {
611612
let continuations = 0;
612-
const director = createChatDirector("Corbits operating prompt", [], {
613-
onTasksChange: () => {},
614-
requestContinuation: () => continuations++,
615-
});
613+
const director = chatDirectorWithContinuation(
614+
"Corbits operating prompt",
615+
() => continuations++,
616+
);
616617
const actions = actionsArray(
617618
await director.decide(overflowError(), longState, mockCapabilities),
618619
);
@@ -632,7 +633,7 @@ describe("chatDirector compaction", () => {
632633
});
633634

634635
test("overflow recovery is bounded so an incompressible history cannot loop forever", async () => {
635-
const director = chatDirectorWithContinuation();
636+
const director = chatDirectorWithContinuation("");
636637
for (let i = 0; i < 2; i++) {
637638
const actions = actionsArray(
638639
await director.decide(overflowError(), longState, mockCapabilities),
@@ -647,7 +648,7 @@ describe("chatDirector compaction", () => {
647648
});
648649

649650
test("chat posture is preserved: an idle turn never terminates the session", async () => {
650-
const director = chatDirectorWithContinuation();
651+
const director = chatDirectorWithContinuation("");
651652
const idle = actionsArray(
652653
await director.decide(textInferenceDone(10), longState, mockCapabilities),
653654
);

tests/unit/codex-responses-adapter.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ describe("codex-responses buildRequest", () => {
8888
expect(body["tool_choice"]).toBe("auto");
8989
});
9090

91+
// Adapter mapping only: compacted history still uses instructions, not a
92+
// developer item. ChatDirector tests own the lock that infer carries the
93+
// constructor systemPrompt after compaction or recovery.
9194
test("sends compacted history with the system prompt as instructions and no developer item", () => {
9295
const systemPrompt = "Corbits operating prompt";
9396
const turns: ConversationTurn[] = [

0 commit comments

Comments
 (0)