Skip to content

Commit 9bb50a1

Browse files
author
catlog22
committed
feat(websocket): integrate A2UI message handling and answer callback registration
1 parent bb4cd05 commit 9bb50a1

4 files changed

Lines changed: 30 additions & 2 deletions

File tree

ccw/src/core/a2ui/A2UIWebSocketHandler.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,23 @@ export class A2UIWebSocketHandler {
5858
timestamp: number;
5959
}>();
6060

61+
private answerCallback?: (answer: QuestionAnswer) => boolean;
62+
63+
/**
64+
* Register callback for handling question answers
65+
* @param callback - Function to handle incoming answers
66+
*/
67+
registerAnswerCallback(callback: (answer: QuestionAnswer) => boolean): void {
68+
this.answerCallback = callback;
69+
}
70+
71+
/**
72+
* Get the registered answer callback
73+
*/
74+
getAnswerCallback(): ((answer: QuestionAnswer) => boolean) | undefined {
75+
return this.answerCallback;
76+
}
77+
6178
/**
6279
* Send A2UI surface to all connected clients
6380
* @param surfaceUpdate - A2UI surface update to send

ccw/src/core/websocket.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { createHash } from 'crypto';
22
import type { IncomingMessage } from 'http';
33
import type { Duplex } from 'stream';
4+
import { a2uiWebSocketHandler, handleA2UIMessage } from './a2ui/A2UIWebSocketHandler.js';
5+
import { handleAnswer } from '../tools/ask-question.js';
46

57
// WebSocket clients for real-time notifications
68
export const wsClients = new Set<Duplex>();
@@ -174,6 +176,11 @@ export function handleWebSocketUpgrade(req: IncomingMessage, socket: Duplex, _he
174176
case 0x1: // Text frame
175177
if (payload) {
176178
console.log('[WS] Received:', payload);
179+
// Try to handle as A2UI message
180+
const handledAsA2UI = handleA2UIMessage(payload, a2uiWebSocketHandler, handleAnswer);
181+
if (handledAsA2UI) {
182+
console.log('[WS] Handled as A2UI message');
183+
}
177184
}
178185
break;
179186
case 0x8: // Close frame

ccw/src/tools/ask-question.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import type {
1414
AskQuestionResult,
1515
PendingQuestion,
1616
} from '../core/a2ui/A2UITypes.js';
17+
import { a2uiWebSocketHandler } from '../core/a2ui/A2UIWebSocketHandler.js';
1718

1819
// ========== Constants ==========
1920

@@ -332,8 +333,9 @@ export async function execute(params: AskQuestionParams): Promise<ToolResult<Ask
332333
}, params.timeout || DEFAULT_TIMEOUT_MS);
333334
});
334335

335-
// TODO: Send A2UI surface via WebSocket
336-
// This will be handled by A2UIWebSocketHandler
336+
// Send A2UI surface via WebSocket to frontend
337+
const a2uiSurface = createA2UISurface(question, surfaceId);
338+
a2uiWebSocketHandler.sendSurface(a2uiSurface.surfaceUpdate);
337339

338340
// Wait for answer
339341
const result = await resultPromise;

ccw/src/tools/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import * as readFileMod from './read-file.js';
2626
import * as coreMemoryMod from './core-memory.js';
2727
import * as contextCacheMod from './context-cache.js';
2828
import * as skillContextLoaderMod from './skill-context-loader.js';
29+
import * as askQuestionMod from './ask-question.js';
2930
import type { ProgressInfo } from './codex-lens.js';
3031

3132
// Import legacy JS tools
@@ -366,6 +367,7 @@ registerTool(toLegacyTool(readFileMod));
366367
registerTool(toLegacyTool(coreMemoryMod));
367368
registerTool(toLegacyTool(contextCacheMod));
368369
registerTool(toLegacyTool(skillContextLoaderMod));
370+
registerTool(toLegacyTool(askQuestionMod));
369371

370372
// Register legacy JS tools
371373
registerTool(uiGeneratePreviewTool);

0 commit comments

Comments
 (0)