Skip to content
Merged
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
16 changes: 7 additions & 9 deletions src/CodexAcpServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1469,7 +1469,7 @@ export class CodexAcpServer {
case "contextCompaction":
return [createCompletedContextCompactionUpdate(item)];
case "plan":
return [this.createPlanUpdate(item)];
return [this.createPlanMessageUpdate(item)];
}
}

Expand Down Expand Up @@ -1520,16 +1520,14 @@ export class CodexAcpServer {
};
}

private createPlanUpdate(
private createPlanMessageUpdate(
item: ThreadItem & { type: "plan" }
): UpdateSessionEvent {
return {
sessionUpdate: "agent_message_chunk",
content: {
type: "text",
text: `Plan:\n${item.text}`,
},
};
return createAgentTextMessageChunk(
item.text,
item.id,
createCodexMessagePhaseMeta("final_answer"),
);
}

private userInputToContentBlocks(input: UserInput): acp.ContentBlock[] {
Expand Down
39 changes: 37 additions & 2 deletions src/CodexEventHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import type {
ItemStartedNotification,
ThreadItem,
ModelReroutedNotification,
PlanDeltaNotification,
ReasoningSummaryPartAddedNotification,
ReasoningSummaryTextDeltaNotification,
ReasoningTextDeltaNotification,
Expand Down Expand Up @@ -76,6 +77,7 @@ export class CodexEventHandler {
private readonly activeGuardianApprovalReviews = new Set<string>();
private readonly activeImageGenerationItems = new Set<string>();
private readonly emittedImageViewItems = new Set<string>();
private readonly planDeltaTextByItemId = new Map<string, string>();
private readonly seenReasoningDeltaItemIds = new Set<string>();
private readonly terminalCommandIds = new Set<string>();
private readonly terminalCommandOutputIds = new Set<string>();
Expand Down Expand Up @@ -110,6 +112,8 @@ export class CodexEventHandler {
switch (notification.method) {
case "item/agentMessage/delta":
return await this.createTextEvent(notification.params);
case "item/plan/delta":
return this.createPlanDeltaEvent(notification.params);
Comment on lines +115 to +116
case "item/started":
return await this.createItemEvent(notification.params);
case "item/completed":
Expand Down Expand Up @@ -223,7 +227,6 @@ export class CodexEventHandler {
case "rawResponseItem/completed":
case "rawResponse/completed":
case "thread/started":
case "item/plan/delta":
case "remoteControl/status/changed":
case "app/list/updated":
case "thread/settings/updated":
Expand Down Expand Up @@ -293,6 +296,15 @@ export class CodexEventHandler {
return this.createAgentThoughtEvent(event.delta, event.itemId);
}

private createPlanDeltaEvent(event: PlanDeltaNotification): UpdateSessionEvent | null {
if (event.delta.length === 0) {
return null;
}
const text = this.planDeltaTextByItemId.get(event.itemId) ?? "";
this.planDeltaTextByItemId.set(event.itemId, text + event.delta);
Comment on lines +303 to +304
return null;
}

private createReasoningSectionBreakEvent(event: ReasoningSummaryPartAddedNotification): UpdateSessionEvent {
this.seenReasoningDeltaItemIds.add(event.itemId);
return this.createAgentThoughtEvent("\n\n", event.itemId);
Expand Down Expand Up @@ -389,6 +401,11 @@ export class CodexEventHandler {
case "agentMessage":
this.rememberAgentMessagePhase(event.item);
return null;
case "plan": {
const deltaText = this.planDeltaTextByItemId.get(event.item.id) ?? "";
this.planDeltaTextByItemId.delete(event.item.id);
return this.createCompletedPlanEvent(event.item, deltaText);
}
case "exitedReviewMode":
return this.createExitedReviewModeEvent(event.item);
case "contextCompaction":
Expand All @@ -404,7 +421,6 @@ export class CodexEventHandler {
case "userMessage":
case "hookPrompt":
case "enteredReviewMode":
case "plan":
return null;

}
Expand All @@ -423,6 +439,25 @@ export class CodexEventHandler {
return this.createAgentThoughtEvent(text, item.id);
}

private createCompletedPlanEvent(
item: ThreadItem & { type: "plan" },
deltaText: string,
): UpdateSessionEvent | null {
const text = item.text.length > 0 ? item.text : deltaText;
if (text.length === 0) {
return null;
}
return this.createPlanTextEvent(text, item.id);
}

private createPlanTextEvent(text: string, messageId: string): UpdateSessionEvent {
return createAgentTextMessageChunk(
text,
messageId,
createCodexMessagePhaseMeta("final_answer"),
);
}

private createExitedReviewModeEvent(item: ThreadItem & { type: "exitedReviewMode" }): UpdateSessionEvent | null {
const text = item.review.trim();
if (text.length === 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,15 @@
"sessionId": "session-legacy",
"update": {
"sessionUpdate": "agent_message_chunk",
"messageId": "item-plan-1",
"content": {
"type": "text",
"text": "Plan:\nInspect project files"
"text": "Inspect project files"
},
"_meta": {
"codex": {
"phase": "final_answer"
}
}
}
}
Expand Down
23 changes: 23 additions & 0 deletions src/__tests__/CodexACPAgent/data/plan-checklist-update.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"method": "sessionUpdate",
"args": [
{
"sessionId": "test-session-id",
"update": {
"sessionUpdate": "plan",
"entries": [
{
"status": "completed",
"content": "Add the event mapping",
"priority": "medium"
},
{
"status": "in_progress",
"content": "Verify it in Zed",
"priority": "medium"
}
]
}
}
]
}
21 changes: 21 additions & 0 deletions src/__tests__/CodexACPAgent/data/plan-completed-fallback.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"method": "sessionUpdate",
"args": [
{
"sessionId": "test-session-id",
"update": {
"sessionUpdate": "agent_message_chunk",
"messageId": "plan-2",
"content": {
"type": "text",
"text": "### Fallback plan\n\n1. Use the completed item."
},
"_meta": {
"codex": {
"phase": "final_answer"
}
}
}
}
]
}
21 changes: 21 additions & 0 deletions src/__tests__/CodexACPAgent/data/plan-delta-fallback.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"method": "sessionUpdate",
"args": [
{
"sessionId": "test-session-id",
"update": {
"sessionUpdate": "agent_message_chunk",
"messageId": "plan-2",
"content": {
"type": "text",
"text": "### Buffered plan\n\n1. Use the buffered fallback."
},
"_meta": {
"codex": {
"phase": "final_answer"
}
}
}
}
]
}
21 changes: 21 additions & 0 deletions src/__tests__/CodexACPAgent/data/plan-deltas.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"method": "sessionUpdate",
"args": [
{
"sessionId": "test-session-id",
"update": {
"sessionUpdate": "agent_message_chunk",
"messageId": "plan-1",
"content": {
"type": "text",
"text": "Completed text should not duplicate the streamed plan."
},
"_meta": {
"codex": {
"phase": "final_answer"
}
}
}
}
]
}
Loading