mcp-codex-worker 0.1.25 → 0.1.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,6 +6,7 @@ import { CODEX_CAPABILITIES } from './provider-capabilities.js';
6
6
  import { BaseProviderAdapter, } from './base-adapter.js';
7
7
  import { CodexRuntime } from '../services/codex-runtime.js';
8
8
  import { attachPauseFlow } from './codex-pause-flow.js';
9
+ import { attachEventCapture } from './codex-event-capture.js';
9
10
  import { REQUEST_TIMEOUT_MS } from '../config/defaults.js';
10
11
  // ---------------------------------------------------------------------------
11
12
  // Adapter
@@ -34,11 +35,14 @@ export class CodexAdapter extends BaseProviderAdapter {
34
35
  async executeSession(handle, prompt, _signal, options) {
35
36
  const runtime = this.getRuntime();
36
37
  let detachPauseFlow;
38
+ let detachEventCapture;
37
39
  let removeExitListener;
38
40
  // Clean up listeners only once, regardless of which path triggers it.
39
41
  const cleanup = () => {
40
42
  detachPauseFlow?.();
41
43
  detachPauseFlow = undefined;
44
+ detachEventCapture?.();
45
+ detachEventCapture = undefined;
42
46
  removeExitListener?.();
43
47
  removeExitListener = undefined;
44
48
  };
@@ -62,6 +66,7 @@ export class CodexAdapter extends BaseProviderAdapter {
62
66
  const client = runtime
63
67
  .getCurrentClient();
64
68
  detachPauseFlow = attachPauseFlow(client, handle, threadId);
69
+ detachEventCapture = attachEventCapture(client, handle, threadId);
65
70
  // 3b. Listen for app-server crashes. If the process exits while the
66
71
  // task is paused (WAITING_ANSWER), mark it failed so the
67
72
  // orchestrator doesn't wait on a ghost.
@@ -1 +1 @@
1
- {"version":3,"file":"codex-adapter.js","sourceRoot":"","sources":["../../../src/execution/codex-adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"codex-adapter.js","sourceRoot":"","sources":["../../../src/execution/codex-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { AppServerClient } from '../services/app-server-client.js';
2
+ import type { TaskHandle } from '../task/task-handle.js';
3
+ /**
4
+ * Listen for `notification` events on the AppServerClient, capture agent
5
+ * messages, command output, file diffs, and errors — writing them to the
6
+ * TaskHandle's output methods. Returns an unsubscribe function.
7
+ */
8
+ export declare function attachEventCapture(client: AppServerClient, handle: TaskHandle, threadId: string): () => void;
@@ -0,0 +1,137 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Helpers
3
+ // ---------------------------------------------------------------------------
4
+ function asObject(value) {
5
+ if (!value || typeof value !== 'object' || Array.isArray(value))
6
+ return undefined;
7
+ return value;
8
+ }
9
+ function asString(value) {
10
+ return typeof value === 'string' ? value : undefined;
11
+ }
12
+ function ts() {
13
+ const d = new Date();
14
+ return [d.getHours(), d.getMinutes(), d.getSeconds()]
15
+ .map(n => String(n).padStart(2, '0'))
16
+ .join(':');
17
+ }
18
+ function truncate(text, max = 200) {
19
+ const oneLine = text.replace(/\n/g, ' ').trim();
20
+ return oneLine.length <= max ? oneLine : oneLine.slice(0, max) + '...';
21
+ }
22
+ function countDiffLines(diff) {
23
+ let added = 0, removed = 0;
24
+ for (const line of diff.split('\n')) {
25
+ if (line.startsWith('+') && !line.startsWith('+++'))
26
+ added++;
27
+ if (line.startsWith('-') && !line.startsWith('---'))
28
+ removed++;
29
+ }
30
+ return { added, removed };
31
+ }
32
+ // ---------------------------------------------------------------------------
33
+ // Attachment: wire event capture onto an AppServerClient + TaskHandle
34
+ // ---------------------------------------------------------------------------
35
+ /**
36
+ * Listen for `notification` events on the AppServerClient, capture agent
37
+ * messages, command output, file diffs, and errors — writing them to the
38
+ * TaskHandle's output methods. Returns an unsubscribe function.
39
+ */
40
+ export function attachEventCapture(client, handle, threadId) {
41
+ const agentMessageBuffers = new Map();
42
+ const commandOutputBuffers = new Map();
43
+ const onNotification = (notification) => {
44
+ const params = asObject(notification.params);
45
+ if (asString(params?.threadId) !== threadId)
46
+ return;
47
+ switch (notification.method) {
48
+ // -- agent message deltas -----------------------------------------------
49
+ case 'item/agentMessage/delta': {
50
+ const itemId = asString(params?.itemId);
51
+ const delta = asString(params?.delta);
52
+ if (!itemId || !delta)
53
+ break;
54
+ const existing = agentMessageBuffers.get(itemId) ?? '';
55
+ agentMessageBuffers.set(itemId, existing + delta);
56
+ break;
57
+ }
58
+ // -- command output deltas ----------------------------------------------
59
+ case 'item/commandExecution/outputDelta': {
60
+ const itemId = asString(params?.itemId);
61
+ const delta = asString(params?.delta);
62
+ if (!itemId || !delta)
63
+ break;
64
+ const existing = commandOutputBuffers.get(itemId) ?? '';
65
+ commandOutputBuffers.set(itemId, existing + delta);
66
+ handle.writeOutputFileOnly(delta);
67
+ break;
68
+ }
69
+ // -- item completed -----------------------------------------------------
70
+ case 'item/completed': {
71
+ const item = asObject(params?.item);
72
+ const itemType = asString(item?.type);
73
+ const itemId = asString(item?.id);
74
+ if (itemType === 'agentMessage') {
75
+ const text = (itemId ? agentMessageBuffers.get(itemId) : undefined)
76
+ ?? asString(item?.text) ?? '';
77
+ handle.writeOutput(`[${ts()}] agent: ${truncate(text)}`);
78
+ handle.writeOutputFileOnly(`[${ts()}] === agent message ===\n${text}`);
79
+ if (itemId)
80
+ agentMessageBuffers.delete(itemId);
81
+ }
82
+ else if (itemType === 'commandExecution') {
83
+ const command = asString(item?.command) ?? 'unknown';
84
+ const exitCode = typeof item?.exitCode === 'number' ? item.exitCode : undefined;
85
+ const durationMs = typeof item?.durationMs === 'number' ? item.durationMs : undefined;
86
+ const duration = durationMs !== undefined ? (durationMs / 1000).toFixed(1) + 's' : '';
87
+ handle.writeOutput(`[${ts()}] cmd: ${command} (exit ${exitCode ?? '?'}${duration ? ', ' + duration : ''})`);
88
+ if (itemId) {
89
+ const accumulated = commandOutputBuffers.get(itemId);
90
+ if (accumulated) {
91
+ handle.writeOutputFileOnly(`[${ts()}] === command output: ${command} ===\n${accumulated}`);
92
+ }
93
+ commandOutputBuffers.delete(itemId);
94
+ }
95
+ }
96
+ else if (itemType === 'fileChange') {
97
+ const changes = Array.isArray(item?.changes) ? item.changes : [];
98
+ for (const raw of changes) {
99
+ const change = asObject(raw);
100
+ if (!change)
101
+ continue;
102
+ const path = asString(change.path) ?? 'unknown';
103
+ const diff = asString(change.diff) ?? '';
104
+ const { added, removed } = countDiffLines(diff);
105
+ handle.writeOutput(`[${ts()}] edit: ${path} (+${added} -${removed})`);
106
+ handle.writeOutputFileOnly(`[${ts()}] === file diff: ${path} ===\n${diff}`);
107
+ }
108
+ }
109
+ break;
110
+ }
111
+ // -- turn diff ----------------------------------------------------------
112
+ case 'turn/diff/updated': {
113
+ const diff = asString(params?.diff);
114
+ if (diff) {
115
+ handle.writeOutputFileOnly(`[${ts()}] === turn diff ===\n${diff}`);
116
+ }
117
+ break;
118
+ }
119
+ // -- error --------------------------------------------------------------
120
+ case 'error': {
121
+ const errorObj = asObject(params?.error);
122
+ const message = asString(errorObj?.message) ?? asString(params?.message) ?? 'unknown';
123
+ const codexErrorInfo = asString(errorObj?.codexErrorInfo) ?? asString(params?.codexErrorInfo) ?? 'unknown';
124
+ handle.writeOutput(`[${ts()}] ERROR: ${codexErrorInfo} — ${truncate(message)}`);
125
+ handle.writeOutputFileOnly(`[${ts()}] === error ===\n${message}\ncodexErrorInfo: ${codexErrorInfo}`);
126
+ break;
127
+ }
128
+ default:
129
+ break;
130
+ }
131
+ };
132
+ client.on('notification', onNotification);
133
+ return () => {
134
+ client.off('notification', onNotification);
135
+ };
136
+ }
137
+ //# sourceMappingURL=codex-event-capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-event-capture.js","sourceRoot":"","sources":["../../../src/execution/codex-event-capture.ts"],"names":[],"mappings":"AAIA,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,SAAS,QAAQ,CAAC,KAAc;IAC9B,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAClF,OAAO,KAAgC,CAAC;AAC1C,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC;AAED,SAAS,EAAE;IACT,MAAM,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;IACrB,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC;SAClD,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;SACpC,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY,EAAE,GAAG,GAAG,GAAG;IACvC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAChD,OAAO,OAAO,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC;AACzE,CAAC;AAED,SAAS,cAAc,CAAC,IAAY;IAClC,IAAI,KAAK,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;YAAE,KAAK,EAAE,CAAC;QAC7D,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;IACjE,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAC5B,CAAC;AAED,8EAA8E;AAC9E,sEAAsE;AACtE,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAuB,EACvB,MAAkB,EAClB,QAAgB;IAEhB,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAkB,CAAC;IACtD,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEvD,MAAM,cAAc,GAAG,CAAC,YAAkC,EAAE,EAAE;QAC5D,MAAM,MAAM,GAAG,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAC7C,IAAI,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,KAAK,QAAQ;YAAE,OAAO;QAEpD,QAAQ,YAAY,CAAC,MAAM,EAAE,CAAC;YAC5B,0EAA0E;YAC1E,KAAK,yBAAyB,CAAC,CAAC,CAAC;gBAC/B,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBACxC,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;gBACtC,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK;oBAAE,MAAM;gBAC7B,MAAM,QAAQ,GAAG,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;gBACvD,mBAAmB,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,GAAG,KAAK,CAAC,CAAC;gBAClD,MAAM;YACR,CAAC;YAED,0EAA0E;YAC1E,KAAK,mCAAmC,CAAC,CAAC,CAAC;gBACzC,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBACxC,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;gBACtC,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK;oBAAE,MAAM;gBAC7B,MAAM,QAAQ,GAAG,oBAAoB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;gBACxD,oBAAoB,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,GAAG,KAAK,CAAC,CAAC;gBACnD,MAAM,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;gBAClC,MAAM;YACR,CAAC;YAED,0EAA0E;YAC1E,KAAK,gBAAgB,CAAC,CAAC,CAAC;gBACtB,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBACpC,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBACtC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBAElC,IAAI,QAAQ,KAAK,cAAc,EAAE,CAAC;oBAChC,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,mBAAmB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;2BAC9D,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;oBAChC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,YAAY,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;oBACzD,MAAM,CAAC,mBAAmB,CAAC,IAAI,EAAE,EAAE,4BAA4B,IAAI,EAAE,CAAC,CAAC;oBACvE,IAAI,MAAM;wBAAE,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBACjD,CAAC;qBAAM,IAAI,QAAQ,KAAK,kBAAkB,EAAE,CAAC;oBAC3C,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,SAAS,CAAC;oBACrD,MAAM,QAAQ,GAAG,OAAO,IAAI,EAAE,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;oBAChF,MAAM,UAAU,GAAG,OAAO,IAAI,EAAE,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;oBACtF,MAAM,QAAQ,GAAG,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;oBACtF,MAAM,CAAC,WAAW,CAChB,IAAI,EAAE,EAAE,UAAU,OAAO,UAAU,QAAQ,IAAI,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,CACxF,CAAC;oBACF,IAAI,MAAM,EAAE,CAAC;wBACX,MAAM,WAAW,GAAG,oBAAoB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;wBACrD,IAAI,WAAW,EAAE,CAAC;4BAChB,MAAM,CAAC,mBAAmB,CACxB,IAAI,EAAE,EAAE,yBAAyB,OAAO,SAAS,WAAW,EAAE,CAC/D,CAAC;wBACJ,CAAC;wBACD,oBAAoB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;oBACtC,CAAC;gBACH,CAAC;qBAAM,IAAI,QAAQ,KAAK,YAAY,EAAE,CAAC;oBACrC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAE,IAAI,CAAC,OAAqB,CAAC,CAAC,CAAC,EAAE,CAAC;oBAChF,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;wBAC1B,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;wBAC7B,IAAI,CAAC,MAAM;4BAAE,SAAS;wBACtB,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC;wBAChD,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;wBACzC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;wBAChD,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,WAAW,IAAI,MAAM,KAAK,KAAK,OAAO,GAAG,CAAC,CAAC;wBACtE,MAAM,CAAC,mBAAmB,CAAC,IAAI,EAAE,EAAE,oBAAoB,IAAI,SAAS,IAAI,EAAE,CAAC,CAAC;oBAC9E,CAAC;gBACH,CAAC;gBACD,MAAM;YACR,CAAC;YAED,0EAA0E;YAC1E,KAAK,mBAAmB,CAAC,CAAC,CAAC;gBACzB,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBACpC,IAAI,IAAI,EAAE,CAAC;oBACT,MAAM,CAAC,mBAAmB,CAAC,IAAI,EAAE,EAAE,wBAAwB,IAAI,EAAE,CAAC,CAAC;gBACrE,CAAC;gBACD,MAAM;YACR,CAAC;YAED,0EAA0E;YAC1E,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;gBACzC,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,SAAS,CAAC;gBACtF,MAAM,cAAc,GAAG,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,IAAI,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC,IAAI,SAAS,CAAC;gBAC3G,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,YAAY,cAAc,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;gBAChF,MAAM,CAAC,mBAAmB,CACxB,IAAI,EAAE,EAAE,oBAAoB,OAAO,qBAAqB,cAAc,EAAE,CACzE,CAAC;gBACF,MAAM;YACR,CAAC;YAED;gBACE,MAAM;QACV,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;IAC1C,OAAO,GAAG,EAAE;QACV,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;IAC7C,CAAC,CAAC;AACJ,CAAC"}
package/dist/src/index.js CHANGED
@@ -57,20 +57,45 @@ server.setRequestHandler(UnsubscribeRequestSchema, async (request) => {
57
57
  });
58
58
  async function main() {
59
59
  await app.initialize();
60
- // Wire state-change notifications: when any task status changes,
61
- // notify MCP clients that the scoreboard and task detail resources are updated.
60
+ // Auto-subscribe the scoreboard so every connected client gets updates
61
+ // without needing to explicitly call resources/subscribe.
62
+ subscriptions.subscribe('task:///all');
62
63
  const taskManager = app.getTaskManager();
64
+ // --- Task creation: new resource URIs appear ---
65
+ taskManager.onTaskCreate((task) => {
66
+ // Tell clients the resource list changed (new task:///<id> URIs)
67
+ server.sendResourceListChanged().catch(() => { });
68
+ // Also notify the scoreboard since a new entry appeared
69
+ server.sendResourceUpdated({ uri: 'task:///all' }).catch(() => { });
70
+ });
71
+ // --- Status changes: task completed, failed, etc. ---
63
72
  taskManager.onStatusChange((task) => {
64
- // Notify subscribed URIs matching this task
65
73
  const uris = subscriptions.getMatchingSubscriptions(task.id);
66
74
  for (const uri of uris) {
67
75
  server.sendResourceUpdated({ uri }).catch(() => { });
68
76
  }
69
- // Always notify the scoreboard even without explicit subscription
77
+ // Scoreboard is always auto-subscribed, but ensure it's notified
70
78
  if (!uris.includes('task:///all')) {
71
79
  server.sendResourceUpdated({ uri: 'task:///all' }).catch(() => { });
72
80
  }
73
81
  });
82
+ // --- Output changes: new agent messages, command output, diffs ---
83
+ // Throttled: notify at most once per second per task to avoid flooding
84
+ // clients on rapid streaming deltas.
85
+ const outputNotifyTimers = new Map();
86
+ taskManager.onOutput((taskId) => {
87
+ if (outputNotifyTimers.has(taskId))
88
+ return;
89
+ const timer = setTimeout(() => {
90
+ outputNotifyTimers.delete(taskId);
91
+ const uris = subscriptions.getMatchingSubscriptions(taskId);
92
+ for (const uri of uris) {
93
+ server.sendResourceUpdated({ uri }).catch(() => { });
94
+ }
95
+ }, 1000);
96
+ timer.unref();
97
+ outputNotifyTimers.set(taskId, timer);
98
+ });
74
99
  const transport = new StdioServerTransport();
75
100
  await server.connect(transport);
76
101
  process.stdin.resume();
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-codex-worker",
3
- "version": "0.1.25",
3
+ "version": "0.1.27",
4
4
  "description": "MCP server bridge for Codex app-server",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",
@@ -15,6 +15,7 @@ import {
15
15
  import { CodexRuntime } from '../services/codex-runtime.js';
16
16
  import type { AppServerClient } from '../services/app-server-client.js';
17
17
  import { attachPauseFlow } from './codex-pause-flow.js';
18
+ import { attachEventCapture } from './codex-event-capture.js';
18
19
  import { REQUEST_TIMEOUT_MS } from '../config/defaults.js';
19
20
 
20
21
  // ---------------------------------------------------------------------------
@@ -67,12 +68,15 @@ export class CodexAdapter extends BaseProviderAdapter {
67
68
  ): Promise<void> {
68
69
  const runtime = this.getRuntime();
69
70
  let detachPauseFlow: (() => void) | undefined;
71
+ let detachEventCapture: (() => void) | undefined;
70
72
  let removeExitListener: (() => void) | undefined;
71
73
 
72
74
  // Clean up listeners only once, regardless of which path triggers it.
73
75
  const cleanup = () => {
74
76
  detachPauseFlow?.();
75
77
  detachPauseFlow = undefined;
78
+ detachEventCapture?.();
79
+ detachEventCapture = undefined;
76
80
  removeExitListener?.();
77
81
  removeExitListener = undefined;
78
82
  };
@@ -101,6 +105,7 @@ export class CodexAdapter extends BaseProviderAdapter {
101
105
  const client = (runtime as unknown as { getCurrentClient(): AppServerClient })
102
106
  .getCurrentClient();
103
107
  detachPauseFlow = attachPauseFlow(client, handle, threadId);
108
+ detachEventCapture = attachEventCapture(client, handle, threadId);
104
109
 
105
110
  // 3b. Listen for app-server crashes. If the process exits while the
106
111
  // task is paused (WAITING_ANSWER), mark it failed so the
@@ -0,0 +1,156 @@
1
+ import type { AppServerClient } from '../services/app-server-client.js';
2
+ import type { TaskHandle } from '../task/task-handle.js';
3
+ import type { JsonLineNotification } from '../types/codex.js';
4
+
5
+ // ---------------------------------------------------------------------------
6
+ // Helpers
7
+ // ---------------------------------------------------------------------------
8
+
9
+ function asObject(value: unknown): Record<string, unknown> | undefined {
10
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined;
11
+ return value as Record<string, unknown>;
12
+ }
13
+
14
+ function asString(value: unknown): string | undefined {
15
+ return typeof value === 'string' ? value : undefined;
16
+ }
17
+
18
+ function ts(): string {
19
+ const d = new Date();
20
+ return [d.getHours(), d.getMinutes(), d.getSeconds()]
21
+ .map(n => String(n).padStart(2, '0'))
22
+ .join(':');
23
+ }
24
+
25
+ function truncate(text: string, max = 200): string {
26
+ const oneLine = text.replace(/\n/g, ' ').trim();
27
+ return oneLine.length <= max ? oneLine : oneLine.slice(0, max) + '...';
28
+ }
29
+
30
+ function countDiffLines(diff: string): { added: number; removed: number } {
31
+ let added = 0, removed = 0;
32
+ for (const line of diff.split('\n')) {
33
+ if (line.startsWith('+') && !line.startsWith('+++')) added++;
34
+ if (line.startsWith('-') && !line.startsWith('---')) removed++;
35
+ }
36
+ return { added, removed };
37
+ }
38
+
39
+ // ---------------------------------------------------------------------------
40
+ // Attachment: wire event capture onto an AppServerClient + TaskHandle
41
+ // ---------------------------------------------------------------------------
42
+
43
+ /**
44
+ * Listen for `notification` events on the AppServerClient, capture agent
45
+ * messages, command output, file diffs, and errors — writing them to the
46
+ * TaskHandle's output methods. Returns an unsubscribe function.
47
+ */
48
+ export function attachEventCapture(
49
+ client: AppServerClient,
50
+ handle: TaskHandle,
51
+ threadId: string,
52
+ ): () => void {
53
+ const agentMessageBuffers = new Map<string, string>();
54
+ const commandOutputBuffers = new Map<string, string>();
55
+
56
+ const onNotification = (notification: JsonLineNotification) => {
57
+ const params = asObject(notification.params);
58
+ if (asString(params?.threadId) !== threadId) return;
59
+
60
+ switch (notification.method) {
61
+ // -- agent message deltas -----------------------------------------------
62
+ case 'item/agentMessage/delta': {
63
+ const itemId = asString(params?.itemId);
64
+ const delta = asString(params?.delta);
65
+ if (!itemId || !delta) break;
66
+ const existing = agentMessageBuffers.get(itemId) ?? '';
67
+ agentMessageBuffers.set(itemId, existing + delta);
68
+ break;
69
+ }
70
+
71
+ // -- command output deltas ----------------------------------------------
72
+ case 'item/commandExecution/outputDelta': {
73
+ const itemId = asString(params?.itemId);
74
+ const delta = asString(params?.delta);
75
+ if (!itemId || !delta) break;
76
+ const existing = commandOutputBuffers.get(itemId) ?? '';
77
+ commandOutputBuffers.set(itemId, existing + delta);
78
+ handle.writeOutputFileOnly(delta);
79
+ break;
80
+ }
81
+
82
+ // -- item completed -----------------------------------------------------
83
+ case 'item/completed': {
84
+ const item = asObject(params?.item);
85
+ const itemType = asString(item?.type);
86
+ const itemId = asString(item?.id);
87
+
88
+ if (itemType === 'agentMessage') {
89
+ const text = (itemId ? agentMessageBuffers.get(itemId) : undefined)
90
+ ?? asString(item?.text) ?? '';
91
+ handle.writeOutput(`[${ts()}] agent: ${truncate(text)}`);
92
+ handle.writeOutputFileOnly(`[${ts()}] === agent message ===\n${text}`);
93
+ if (itemId) agentMessageBuffers.delete(itemId);
94
+ } else if (itemType === 'commandExecution') {
95
+ const command = asString(item?.command) ?? 'unknown';
96
+ const exitCode = typeof item?.exitCode === 'number' ? item.exitCode : undefined;
97
+ const durationMs = typeof item?.durationMs === 'number' ? item.durationMs : undefined;
98
+ const duration = durationMs !== undefined ? (durationMs / 1000).toFixed(1) + 's' : '';
99
+ handle.writeOutput(
100
+ `[${ts()}] cmd: ${command} (exit ${exitCode ?? '?'}${duration ? ', ' + duration : ''})`,
101
+ );
102
+ if (itemId) {
103
+ const accumulated = commandOutputBuffers.get(itemId);
104
+ if (accumulated) {
105
+ handle.writeOutputFileOnly(
106
+ `[${ts()}] === command output: ${command} ===\n${accumulated}`,
107
+ );
108
+ }
109
+ commandOutputBuffers.delete(itemId);
110
+ }
111
+ } else if (itemType === 'fileChange') {
112
+ const changes = Array.isArray(item?.changes) ? (item.changes as unknown[]) : [];
113
+ for (const raw of changes) {
114
+ const change = asObject(raw);
115
+ if (!change) continue;
116
+ const path = asString(change.path) ?? 'unknown';
117
+ const diff = asString(change.diff) ?? '';
118
+ const { added, removed } = countDiffLines(diff);
119
+ handle.writeOutput(`[${ts()}] edit: ${path} (+${added} -${removed})`);
120
+ handle.writeOutputFileOnly(`[${ts()}] === file diff: ${path} ===\n${diff}`);
121
+ }
122
+ }
123
+ break;
124
+ }
125
+
126
+ // -- turn diff ----------------------------------------------------------
127
+ case 'turn/diff/updated': {
128
+ const diff = asString(params?.diff);
129
+ if (diff) {
130
+ handle.writeOutputFileOnly(`[${ts()}] === turn diff ===\n${diff}`);
131
+ }
132
+ break;
133
+ }
134
+
135
+ // -- error --------------------------------------------------------------
136
+ case 'error': {
137
+ const errorObj = asObject(params?.error);
138
+ const message = asString(errorObj?.message) ?? asString(params?.message) ?? 'unknown';
139
+ const codexErrorInfo = asString(errorObj?.codexErrorInfo) ?? asString(params?.codexErrorInfo) ?? 'unknown';
140
+ handle.writeOutput(`[${ts()}] ERROR: ${codexErrorInfo} — ${truncate(message)}`);
141
+ handle.writeOutputFileOnly(
142
+ `[${ts()}] === error ===\n${message}\ncodexErrorInfo: ${codexErrorInfo}`,
143
+ );
144
+ break;
145
+ }
146
+
147
+ default:
148
+ break;
149
+ }
150
+ };
151
+
152
+ client.on('notification', onNotification);
153
+ return () => {
154
+ client.off('notification', onNotification);
155
+ };
156
+ }
package/src/index.ts CHANGED
@@ -80,21 +80,49 @@ server.setRequestHandler(UnsubscribeRequestSchema, async (request) => {
80
80
  async function main(): Promise<void> {
81
81
  await app.initialize();
82
82
 
83
- // Wire state-change notifications: when any task status changes,
84
- // notify MCP clients that the scoreboard and task detail resources are updated.
83
+ // Auto-subscribe the scoreboard so every connected client gets updates
84
+ // without needing to explicitly call resources/subscribe.
85
+ subscriptions.subscribe('task:///all');
86
+
85
87
  const taskManager = app.getTaskManager();
88
+
89
+ // --- Task creation: new resource URIs appear ---
90
+ taskManager.onTaskCreate((task) => {
91
+ // Tell clients the resource list changed (new task:///<id> URIs)
92
+ server.sendResourceListChanged().catch(() => {});
93
+ // Also notify the scoreboard since a new entry appeared
94
+ server.sendResourceUpdated({ uri: 'task:///all' }).catch(() => {});
95
+ });
96
+
97
+ // --- Status changes: task completed, failed, etc. ---
86
98
  taskManager.onStatusChange((task) => {
87
- // Notify subscribed URIs matching this task
88
99
  const uris = subscriptions.getMatchingSubscriptions(task.id);
89
100
  for (const uri of uris) {
90
101
  server.sendResourceUpdated({ uri }).catch(() => {});
91
102
  }
92
- // Always notify the scoreboard even without explicit subscription
103
+ // Scoreboard is always auto-subscribed, but ensure it's notified
93
104
  if (!uris.includes('task:///all')) {
94
105
  server.sendResourceUpdated({ uri: 'task:///all' }).catch(() => {});
95
106
  }
96
107
  });
97
108
 
109
+ // --- Output changes: new agent messages, command output, diffs ---
110
+ // Throttled: notify at most once per second per task to avoid flooding
111
+ // clients on rapid streaming deltas.
112
+ const outputNotifyTimers = new Map<string, ReturnType<typeof setTimeout>>();
113
+ taskManager.onOutput((taskId) => {
114
+ if (outputNotifyTimers.has(taskId)) return;
115
+ const timer = setTimeout(() => {
116
+ outputNotifyTimers.delete(taskId);
117
+ const uris = subscriptions.getMatchingSubscriptions(taskId);
118
+ for (const uri of uris) {
119
+ server.sendResourceUpdated({ uri }).catch(() => {});
120
+ }
121
+ }, 1000);
122
+ timer.unref();
123
+ outputNotifyTimers.set(taskId, timer);
124
+ });
125
+
98
126
  const transport = new StdioServerTransport();
99
127
  await server.connect(transport);
100
128
  process.stdin.resume();