mcp-codex-worker 0.1.1 → 0.1.3

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.
@@ -352,6 +352,12 @@ export class AppServerClient extends EventEmitter {
352
352
  }));
353
353
  }
354
354
 
355
+ listOperationsForThread(threadId: string): RuntimeOperation[] {
356
+ return [...this.operations.values()]
357
+ .filter((op) => op.threadId === threadId)
358
+ .map((op) => ({ ...op, pendingRequestIds: [...op.pendingRequestIds] }));
359
+ }
360
+
355
361
  listServerRequests(includeResolved = false): PendingServerRequest[] {
356
362
  return [...this.serverRequests.values()]
357
363
  .filter((request) => includeResolved || request.status === 'pending')
@@ -574,8 +580,7 @@ export class AppServerClient extends EventEmitter {
574
580
  }
575
581
 
576
582
  if (notification.method === 'error') {
577
- const params = asObject(notification.params);
578
- const message = typeof params?.message === 'string' ? params.message : 'Codex reported an error.';
583
+ const message = this.extractErrorNotificationMessage(notification.params);
579
584
  for (const operation of this.operations.values()) {
580
585
  if (operation.status === 'running' && operation.threadId === threadId && TURN_LIFECYCLE_METHODS.has(operation.method)) {
581
586
  operation.status = 'failed';
@@ -586,6 +591,55 @@ export class AppServerClient extends EventEmitter {
586
591
  }
587
592
  }
588
593
 
594
+ /**
595
+ * Pulls a human-readable message out of an `error` notification.
596
+ *
597
+ * The Codex app-server emits `ErrorNotification` with shape
598
+ * `{ error: { message, codexErrorInfo, additionalDetails }, willRetry, threadId, turnId }`
599
+ * (see src/protocol/v2/ErrorNotification.ts). We surface the nested message and
600
+ * append the `codexErrorInfo` tag so downstream classifiers in
601
+ * `codex-runtime.ts` (isAuthSignal / isRateLimitSignal) can match on keywords
602
+ * like `unauthorized` or `usageLimitExceeded` to drive profile failover.
603
+ */
604
+ private extractErrorNotificationMessage(params: unknown): string {
605
+ const paramsObject = asObject(params);
606
+ const errorObject = asObject(paramsObject?.error);
607
+ const nestedMessage = typeof errorObject?.message === 'string'
608
+ ? errorObject.message
609
+ : undefined;
610
+ const flatMessage = typeof paramsObject?.message === 'string'
611
+ ? paramsObject.message
612
+ : undefined;
613
+ const rawMessage = nestedMessage ?? flatMessage;
614
+
615
+ const codexErrorInfo = this.normalizeCodexErrorInfo(errorObject?.codexErrorInfo);
616
+
617
+ if (rawMessage && codexErrorInfo) {
618
+ return `${rawMessage} [${codexErrorInfo}]`;
619
+ }
620
+ if (rawMessage) {
621
+ return rawMessage;
622
+ }
623
+ if (codexErrorInfo) {
624
+ return `Codex reported an error: ${codexErrorInfo}`;
625
+ }
626
+ return 'Codex reported an error.';
627
+ }
628
+
629
+ private normalizeCodexErrorInfo(value: unknown): string | undefined {
630
+ if (typeof value === 'string') {
631
+ return value;
632
+ }
633
+ const object = asObject(value);
634
+ if (object) {
635
+ const [key] = Object.keys(object);
636
+ if (key) {
637
+ return key;
638
+ }
639
+ }
640
+ return undefined;
641
+ }
642
+
589
643
  private extractThreadIdFromParams(params: unknown): string | undefined {
590
644
  const object = asObject(params);
591
645
  const threadId = object?.threadId;
@@ -8,7 +8,7 @@ import {
8
8
  CODEX_APP_SERVER_COMMAND_ENV,
9
9
  REQUEST_TIMEOUT_MS,
10
10
  } from '../config/defaults.js';
11
- import type { PendingServerRequest } from '../types/codex.js';
11
+ import type { PendingServerRequest, RuntimeOperation } from '../types/codex.js';
12
12
  import { AppServerClient, type BridgedOperationResult } from './app-server-client.js';
13
13
  import { appendFleetDeveloperInstructions } from './fleet-mode.js';
14
14
  import {
@@ -366,6 +366,22 @@ export class CodexRuntime {
366
366
  };
367
367
  }
368
368
 
369
+ getOperationsForThread(threadId: string): RuntimeOperation[] {
370
+ try {
371
+ return this.getCurrentClient().listOperationsForThread(threadId);
372
+ } catch {
373
+ return [];
374
+ }
375
+ }
376
+
377
+ getAllOperations(): RuntimeOperation[] {
378
+ try {
379
+ return this.getCurrentClient().listOperations();
380
+ } catch {
381
+ return [];
382
+ }
383
+ }
384
+
369
385
  async getThreadEvents(threadId: string): Promise<unknown[]> {
370
386
  return this.getCurrentClient().getThreadEvents(threadId);
371
387
  }