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
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"type": "module",
"devDependencies": {
"@types/node": "^24.10.1",
"@openai/codex": "^0.80.0",
"@openai/codex": "^0.87.0",
"tsx": "^4.20.6",
"typescript": "^5.9.3",
"vitest": "^4.0.10"
Expand Down
8 changes: 4 additions & 4 deletions src/CodexAcpClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,19 +268,19 @@ function buildPromptItems(prompt: acp.ContentBlock[]): UserInput[] {
return prompt.map((block): UserInput | null => {
switch (block.type) {
case "text":
return {type: "text", text: block.text};
return {type: "text", text: block.text, text_elements: []};
case "image": {
const url = block.uri ?? `data:${block.mimeType};base64,${block.data}`;
return {type: "image", url};
}
case "resource_link":
return {type: "text", text: formatUriAsLink(block.name, block.uri)};
return {type: "text", text: formatUriAsLink(block.name, block.uri), text_elements: []};
case "resource": {
const resource = block.resource as EmbeddedResourceResource;
if ("text" in resource) {
const link = formatUriAsLink(null, resource.uri);
const context = `<context ref="${resource.uri}">\n${resource.text}\n</context>`;
return {type: "text", text: `${link}\n${context}`};
return {type: "text", text: `${link}\n${context}`, text_elements: []};
}
return null;
}
Expand Down Expand Up @@ -326,4 +326,4 @@ function mergeGatewayConfig(config: JsonObject, gatewayConfig: GatewayConfig | n
} else {
return config;
}
}
}
16 changes: 16 additions & 0 deletions src/CodexEventHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type {
AgentMessageDeltaNotification, CodexErrorInfo,
CommandAction,
CommandExecutionStatus,
ConfigWarningNotification,
ErrorNotification,
FileUpdateChange,
ItemCompletedNotification,
Expand Down Expand Up @@ -100,6 +101,8 @@ export class CodexEventHandler {
case "account/rateLimits/updated":
this.handleRateLimitsUpdated(notification.params);
return null;
case "configWarning":
return await this.createConfigWarningEvent(notification.params);
case "thread/compacted":
case "windows/worldWritableWarning":
case "account/login/completed":
Expand All @@ -124,12 +127,24 @@ export class CodexEventHandler {
}
}

private async createConfigWarningEvent(event: ConfigWarningNotification): Promise<UpdateSessionEvent> {
const detailsText = event.details ? `\n\n${event.details}` : "";
return {
sessionUpdate: "agent_message_chunk",
content: {
type: "text",
text: `Config warning: ${event.summary}${detailsText}\n\n`
}
}
}

private async createItemEvent(event: ItemStartedNotification): Promise<UpdateSessionEvent | null> {
switch (event.item.type) {
case "fileChange":
return await this.createFileChangeEvent(event.item)
case "commandExecution":
return await this.createCommandEvent(event.item)
case "collabAgentToolCall":
case "userMessage":
case "agentMessage":
case "reasoning":
Expand Down Expand Up @@ -161,6 +176,7 @@ export class CodexEventHandler {
text: summary
}
}
case "collabAgentToolCall":
case "userMessage":
case "agentMessage":
case "mcpToolCall":
Expand Down
21 changes: 15 additions & 6 deletions src/__tests__/CodexACPAgent/data/auth-with-key.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,26 +86,35 @@
{
"id": "id",
"model": "model",
"displayName": "gpt-5.1-codex-max",
"description": "Codex-optimized flagship for deep and fast reasoning.",
"displayName": "gpt-5.2-codex",
"description": "Latest frontier agentic coding model.",
"supportedReasoningEfforts": "supportedReasoningEfforts",
"defaultReasoningEffort": "medium",
"isDefault": true
},
{
"id": "id",
"model": "model",
"displayName": "gpt-5.1-codex-mini",
"description": "Optimized for codex. Cheaper, faster, but less capable.",
"displayName": "gpt-5.2",
"description": "Latest frontier model with improvements across knowledge, reasoning and coding",
"supportedReasoningEfforts": "supportedReasoningEfforts",
"defaultReasoningEffort": "medium",
"isDefault": false
},
{
"id": "id",
"model": "model",
"displayName": "gpt-5.2",
"description": "Latest frontier model with improvements across knowledge, reasoning and coding",
"displayName": "gpt-5.1-codex-max",
"description": "Codex-optimized flagship for deep and fast reasoning.",
"supportedReasoningEfforts": "supportedReasoningEfforts",
"defaultReasoningEffort": "medium",
"isDefault": false
},
{
"id": "id",
"model": "model",
"displayName": "gpt-5.1-codex-mini",
"description": "Optimized for codex. Cheaper, faster, but less capable.",
"supportedReasoningEfforts": "supportedReasoningEfforts",
"defaultReasoningEffort": "medium",
"isDefault": false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,22 @@
"input": [
{
"type": "text",
"text": "Hello"
"text": "Hello",
"text_elements": []
},
{
"type": "image",
"url": "https://example.com/image.png"
},
{
"type": "text",
"text": "[@report.txt](file:///tmp/report.txt)"
"text": "[@report.txt](file:///tmp/report.txt)",
"text_elements": []
},
{
"type": "text",
"text": "[@notes.txt](file:///tmp/notes.txt)\n<context ref=\"file:///tmp/notes.txt\">\nNotes body\n</context>"
"text": "[@notes.txt](file:///tmp/notes.txt)\n<context ref=\"file:///tmp/notes.txt\">\nNotes body\n</context>",
"text_elements": []
}
],
"approvalPolicy": "on-request",
Expand Down
8 changes: 8 additions & 0 deletions src/app-server/AgentStatus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!

// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.

/**
* Agent lifecycle status, derived from emitted events.
*/
export type AgentStatus = "pending_init" | "running" | { "completed": string | null } | { "errored": string } | "shutdown" | "not_found";
13 changes: 13 additions & 0 deletions src/app-server/ByteRange.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!

// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.

export type ByteRange = {
/**
* Start byte offset (inclusive) within the UTF-8 text buffer.
*/
start: number,
/**
* End byte offset (exclusive) within the UTF-8 text buffer.
*/
end: number, };
2 changes: 1 addition & 1 deletion src/app-server/ClientRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@ import type { TurnStartParams } from "./v2/TurnStartParams";
/**
* Request from the client to the server.
*/
export type ClientRequest = { "method": "initialize", id: RequestId, params: InitializeParams, } | { "method": "thread/start", id: RequestId, params: ThreadStartParams, } | { "method": "thread/resume", id: RequestId, params: ThreadResumeParams, } | { "method": "thread/fork", id: RequestId, params: ThreadForkParams, } | { "method": "thread/archive", id: RequestId, params: ThreadArchiveParams, } | { "method": "thread/rollback", id: RequestId, params: ThreadRollbackParams, } | { "method": "thread/list", id: RequestId, params: ThreadListParams, } | { "method": "thread/loaded/list", id: RequestId, params: ThreadLoadedListParams, } | { "method": "skills/list", id: RequestId, params: SkillsListParams, } | { "method": "turn/start", id: RequestId, params: TurnStartParams, } | { "method": "turn/interrupt", id: RequestId, params: TurnInterruptParams, } | { "method": "review/start", id: RequestId, params: ReviewStartParams, } | { "method": "model/list", id: RequestId, params: ModelListParams, } | { "method": "mcpServer/oauth/login", id: RequestId, params: McpServerOauthLoginParams, } | { "method": "mcpServerStatus/list", id: RequestId, params: ListMcpServerStatusParams, } | { "method": "account/login/start", id: RequestId, params: LoginAccountParams, } | { "method": "account/login/cancel", id: RequestId, params: CancelLoginAccountParams, } | { "method": "account/logout", id: RequestId, params: undefined, } | { "method": "account/rateLimits/read", id: RequestId, params: undefined, } | { "method": "feedback/upload", id: RequestId, params: FeedbackUploadParams, } | { "method": "command/exec", id: RequestId, params: CommandExecParams, } | { "method": "config/read", id: RequestId, params: ConfigReadParams, } | { "method": "config/value/write", id: RequestId, params: ConfigValueWriteParams, } | { "method": "config/batchWrite", id: RequestId, params: ConfigBatchWriteParams, } | { "method": "configRequirements/read", id: RequestId, params: undefined, } | { "method": "account/read", id: RequestId, params: GetAccountParams, } | { "method": "newConversation", id: RequestId, params: NewConversationParams, } | { "method": "getConversationSummary", id: RequestId, params: GetConversationSummaryParams, } | { "method": "listConversations", id: RequestId, params: ListConversationsParams, } | { "method": "resumeConversation", id: RequestId, params: ResumeConversationParams, } | { "method": "forkConversation", id: RequestId, params: ForkConversationParams, } | { "method": "archiveConversation", id: RequestId, params: ArchiveConversationParams, } | { "method": "sendUserMessage", id: RequestId, params: SendUserMessageParams, } | { "method": "sendUserTurn", id: RequestId, params: SendUserTurnParams, } | { "method": "interruptConversation", id: RequestId, params: InterruptConversationParams, } | { "method": "addConversationListener", id: RequestId, params: AddConversationListenerParams, } | { "method": "removeConversationListener", id: RequestId, params: RemoveConversationListenerParams, } | { "method": "gitDiffToRemote", id: RequestId, params: GitDiffToRemoteParams, } | { "method": "loginApiKey", id: RequestId, params: LoginApiKeyParams, } | { "method": "loginChatGpt", id: RequestId, params: undefined, } | { "method": "cancelLoginChatGpt", id: RequestId, params: CancelLoginChatGptParams, } | { "method": "logoutChatGpt", id: RequestId, params: undefined, } | { "method": "getAuthStatus", id: RequestId, params: GetAuthStatusParams, } | { "method": "getUserSavedConfig", id: RequestId, params: undefined, } | { "method": "setDefaultModel", id: RequestId, params: SetDefaultModelParams, } | { "method": "getUserAgent", id: RequestId, params: undefined, } | { "method": "userInfo", id: RequestId, params: undefined, } | { "method": "fuzzyFileSearch", id: RequestId, params: FuzzyFileSearchParams, } | { "method": "execOneOffCommand", id: RequestId, params: ExecOneOffCommandParams, };
export type ClientRequest = { "method": "initialize", id: RequestId, params: InitializeParams, } | { "method": "thread/start", id: RequestId, params: ThreadStartParams, } | { "method": "thread/resume", id: RequestId, params: ThreadResumeParams, } | { "method": "thread/fork", id: RequestId, params: ThreadForkParams, } | { "method": "thread/archive", id: RequestId, params: ThreadArchiveParams, } | { "method": "thread/rollback", id: RequestId, params: ThreadRollbackParams, } | { "method": "thread/list", id: RequestId, params: ThreadListParams, } | { "method": "thread/loaded/list", id: RequestId, params: ThreadLoadedListParams, } | { "method": "skills/list", id: RequestId, params: SkillsListParams, } | { "method": "turn/start", id: RequestId, params: TurnStartParams, } | { "method": "turn/interrupt", id: RequestId, params: TurnInterruptParams, } | { "method": "review/start", id: RequestId, params: ReviewStartParams, } | { "method": "model/list", id: RequestId, params: ModelListParams, } | { "method": "mcpServer/oauth/login", id: RequestId, params: McpServerOauthLoginParams, } | { "method": "config/mcpServer/reload", id: RequestId, params: undefined, } | { "method": "mcpServerStatus/list", id: RequestId, params: ListMcpServerStatusParams, } | { "method": "account/login/start", id: RequestId, params: LoginAccountParams, } | { "method": "account/login/cancel", id: RequestId, params: CancelLoginAccountParams, } | { "method": "account/logout", id: RequestId, params: undefined, } | { "method": "account/rateLimits/read", id: RequestId, params: undefined, } | { "method": "feedback/upload", id: RequestId, params: FeedbackUploadParams, } | { "method": "command/exec", id: RequestId, params: CommandExecParams, } | { "method": "config/read", id: RequestId, params: ConfigReadParams, } | { "method": "config/value/write", id: RequestId, params: ConfigValueWriteParams, } | { "method": "config/batchWrite", id: RequestId, params: ConfigBatchWriteParams, } | { "method": "configRequirements/read", id: RequestId, params: undefined, } | { "method": "account/read", id: RequestId, params: GetAccountParams, } | { "method": "newConversation", id: RequestId, params: NewConversationParams, } | { "method": "getConversationSummary", id: RequestId, params: GetConversationSummaryParams, } | { "method": "listConversations", id: RequestId, params: ListConversationsParams, } | { "method": "resumeConversation", id: RequestId, params: ResumeConversationParams, } | { "method": "forkConversation", id: RequestId, params: ForkConversationParams, } | { "method": "archiveConversation", id: RequestId, params: ArchiveConversationParams, } | { "method": "sendUserMessage", id: RequestId, params: SendUserMessageParams, } | { "method": "sendUserTurn", id: RequestId, params: SendUserTurnParams, } | { "method": "interruptConversation", id: RequestId, params: InterruptConversationParams, } | { "method": "addConversationListener", id: RequestId, params: AddConversationListenerParams, } | { "method": "removeConversationListener", id: RequestId, params: RemoveConversationListenerParams, } | { "method": "gitDiffToRemote", id: RequestId, params: GitDiffToRemoteParams, } | { "method": "loginApiKey", id: RequestId, params: LoginApiKeyParams, } | { "method": "loginChatGpt", id: RequestId, params: undefined, } | { "method": "cancelLoginChatGpt", id: RequestId, params: CancelLoginChatGptParams, } | { "method": "logoutChatGpt", id: RequestId, params: undefined, } | { "method": "getAuthStatus", id: RequestId, params: GetAuthStatusParams, } | { "method": "getUserSavedConfig", id: RequestId, params: undefined, } | { "method": "setDefaultModel", id: RequestId, params: SetDefaultModelParams, } | { "method": "getUserAgent", id: RequestId, params: undefined, } | { "method": "userInfo", id: RequestId, params: undefined, } | { "method": "fuzzyFileSearch", id: RequestId, params: FuzzyFileSearchParams, } | { "method": "execOneOffCommand", id: RequestId, params: ExecOneOffCommandParams, };
23 changes: 23 additions & 0 deletions src/app-server/CollabAgentInteractionBeginEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!

// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ThreadId } from "./ThreadId";

export type CollabAgentInteractionBeginEvent = {
/**
* Identifier for the collab tool call.
*/
call_id: string,
/**
* Thread ID of the sender.
*/
sender_thread_id: ThreadId,
/**
* Thread ID of the receiver.
*/
receiver_thread_id: ThreadId,
/**
* Prompt sent from the sender to the receiver. Can be empty to prevent CoT
* leaking at the beginning.
*/
prompt: string, };
28 changes: 28 additions & 0 deletions src/app-server/CollabAgentInteractionEndEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!

// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { AgentStatus } from "./AgentStatus";
import type { ThreadId } from "./ThreadId";

export type CollabAgentInteractionEndEvent = {
/**
* Identifier for the collab tool call.
*/
call_id: string,
/**
* Thread ID of the sender.
*/
sender_thread_id: ThreadId,
/**
* Thread ID of the receiver.
*/
receiver_thread_id: ThreadId,
/**
* Prompt sent from the sender to the receiver. Can be empty to prevent CoT
* leaking at the beginning.
*/
prompt: string,
/**
* Last known status of the receiver agent reported to the sender agent.
*/
status: AgentStatus, };
19 changes: 19 additions & 0 deletions src/app-server/CollabAgentSpawnBeginEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!

// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ThreadId } from "./ThreadId";

export type CollabAgentSpawnBeginEvent = {
/**
* Identifier for the collab tool call.
*/
call_id: string,
/**
* Thread ID of the sender.
*/
sender_thread_id: ThreadId,
/**
* Initial prompt sent to the agent. Can be empty to prevent CoT leaking at the
* beginning.
*/
prompt: string, };
28 changes: 28 additions & 0 deletions src/app-server/CollabAgentSpawnEndEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!

// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { AgentStatus } from "./AgentStatus";
import type { ThreadId } from "./ThreadId";

export type CollabAgentSpawnEndEvent = {
/**
* Identifier for the collab tool call.
*/
call_id: string,
/**
* Thread ID of the sender.
*/
sender_thread_id: ThreadId,
/**
* Thread ID of the newly spawned agent, if it was created.
*/
new_thread_id: ThreadId | null,
/**
* Initial prompt sent to the agent. Can be empty to prevent CoT leaking at the
* beginning.
*/
prompt: string,
/**
* Last known status of the new agent reported to the sender agent.
*/
status: AgentStatus, };
18 changes: 18 additions & 0 deletions src/app-server/CollabCloseBeginEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!

// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ThreadId } from "./ThreadId";

export type CollabCloseBeginEvent = {
/**
* Identifier for the collab tool call.
*/
call_id: string,
/**
* Thread ID of the sender.
*/
sender_thread_id: ThreadId,
/**
* Thread ID of the receiver.
*/
receiver_thread_id: ThreadId, };
24 changes: 24 additions & 0 deletions src/app-server/CollabCloseEndEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!

// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { AgentStatus } from "./AgentStatus";
import type { ThreadId } from "./ThreadId";

export type CollabCloseEndEvent = {
/**
* Identifier for the collab tool call.
*/
call_id: string,
/**
* Thread ID of the sender.
*/
sender_thread_id: ThreadId,
/**
* Thread ID of the receiver.
*/
receiver_thread_id: ThreadId,
/**
* Last known status of the receiver agent reported to the sender agent before
* the close.
*/
status: AgentStatus, };
18 changes: 18 additions & 0 deletions src/app-server/CollabWaitingBeginEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// GENERATED CODE! DO NOT MODIFY BY HAND!

// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { ThreadId } from "./ThreadId";

export type CollabWaitingBeginEvent = {
/**
* Thread ID of the sender.
*/
sender_thread_id: ThreadId,
/**
* Thread ID of the receivers.
*/
receiver_thread_ids: Array<ThreadId>,
/**
* ID of the waiting call.
*/
call_id: string, };
Loading