-
Notifications
You must be signed in to change notification settings - Fork 52
Fix/edit tool calls #103
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix/edit tool calls #103
Changes from 4 commits
d53d7b8
6c83fc4
4c9030c
291feb1
1ee6ac7
e7740de
010f53b
021f6f7
2d15c14
6de9ec0
2ae2d64
a8751e8
1498add
05417a3
a0849cc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,6 +35,7 @@ import type { | |
| ListMcpServerStatusParams, | ||
| ListMcpServerStatusResponse, ConfigReadParams, ConfigReadResponse, | ||
| } from "./app-server/v2"; | ||
| import { logger } from "./Logger"; | ||
|
|
||
| export interface ApprovalHandler { | ||
| handleCommandExecution(params: CommandExecutionRequestApprovalParams): Promise<CommandExecutionRequestApprovalResponse>; | ||
|
|
@@ -60,6 +61,8 @@ const FileChangeApprovalRequest = new RequestType< | |
| export class CodexAppServerClient { | ||
| readonly connection: MessageConnection; | ||
| private approvalHandlers = new Map<string, ApprovalHandler>(); | ||
| private readonly notificationHandlers = new Map<string, (event: ServerNotification) => void | Promise<void>>(); | ||
|
i1bro marked this conversation as resolved.
Outdated
|
||
| private readonly notificationQueues = new Map<string, Promise<void> | null>(); | ||
| private mcpStartupCompleteVersion = 0; | ||
| private lastMcpStartupComplete: McpStartupCompleteEvent | null = null; | ||
| private readonly mcpStartupCompleteResolvers: Array<SignalResolver<McpStartupCompleteEvent>> = []; | ||
|
|
@@ -190,22 +193,56 @@ export class CodexAppServerClient { | |
| * Registers a notification handler for a specific session. | ||
| * Replaces any existing handler for the same session, preventing handler accumulation. | ||
| */ | ||
| onServerNotification(sessionId: string, callback: (event: ServerNotification) => void) { | ||
| onServerNotification(sessionId: string, callback: (event: ServerNotification) => void | Promise<void>) { | ||
|
i1bro marked this conversation as resolved.
Outdated
|
||
| this.notificationHandlers.set(sessionId, callback); | ||
| this.notificationQueues.set(sessionId, null); | ||
| } | ||
|
|
||
| private codexEventHandlers: Array<(event: CodexConnectionEvent) => void> = []; | ||
| onClientTransportEvent(callback: (event: CodexConnectionEvent) => void){ | ||
| this.codexEventHandlers.push(callback); | ||
| } | ||
|
|
||
| private notificationHandlers = new Map<string, (event: ServerNotification) => void>(); | ||
| private notify(notification: ServerNotification) { | ||
| for (const notificationHandler of this.notificationHandlers.values()) { | ||
| notificationHandler(notification); | ||
| for (const [sessionId, notificationHandler] of this.notificationHandlers.entries()) { | ||
| const queue = this.notificationQueues.get(sessionId); | ||
| if (queue) { | ||
| const next = queue | ||
| .then(() => notificationHandler(notification)) | ||
| .catch((error) => { | ||
| logger.error("Error handling server notification", error); | ||
| }); | ||
| this.notificationQueues.set(sessionId, this.trackNotificationQueue(sessionId, next)); | ||
| continue; | ||
| } | ||
|
|
||
| try { | ||
| const result = notificationHandler(notification); | ||
| if (result instanceof Promise) { | ||
| const next = result.catch((error) => { | ||
| logger.error("Error handling server notification", error); | ||
| }); | ||
| this.notificationQueues.set(sessionId, this.trackNotificationQueue(sessionId, next)); | ||
| } | ||
| } catch (error) { | ||
| logger.error("Error handling server notification", error); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| async flushServerNotifications(sessionId: string): Promise<void> { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure why do we need a queue and then why we need to flush it instead of handling events?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because sendPrompt() must not return until all earlier events have been handled. |
||
| await (this.notificationQueues.get(sessionId) ?? Promise.resolve()); | ||
| } | ||
|
|
||
| private trackNotificationQueue(sessionId: string, queue: Promise<void>): Promise<void> { | ||
| const trackedQueue = queue.finally(() => { | ||
| if (this.notificationQueues.get(sessionId) === trackedQueue) { | ||
| this.notificationQueues.set(sessionId, null); | ||
| } | ||
| }); | ||
| return trackedQueue; | ||
| } | ||
|
|
||
| private resolveSignal<T>( | ||
| event: T, | ||
| version: number, | ||
|
|
||
This file was deleted.
Uh oh!
There was an error while loading. Please reload this page.