@rynx-ai/runtime 0.1.0 → 0.1.9

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.
Files changed (53) hide show
  1. package/dist/claude/executor.d.ts +3 -5
  2. package/dist/claude/executor.js +3 -5
  3. package/dist/claude/native-bridge.d.ts +74 -17
  4. package/dist/claude/native-bridge.js +225 -30
  5. package/dist/claude/native-hook-main.js +291 -39
  6. package/dist/claude/native-hooks.d.ts +3 -2
  7. package/dist/claude/native-hooks.js +15 -6
  8. package/dist/claude/native-integration.d.ts +78 -5
  9. package/dist/claude/native-integration.js +417 -26
  10. package/dist/claude/settings.d.ts +8 -0
  11. package/dist/claude/settings.js +50 -0
  12. package/dist/claude/transcript.d.ts +2 -2
  13. package/dist/claude/transcript.js +3 -3
  14. package/dist/codex/rollout-synth.js +1 -1
  15. package/dist/codex-app-server/client.d.ts +26 -40
  16. package/dist/codex-app-server/client.js +1128 -99
  17. package/dist/codex-app-server/forwarder.d.ts +7 -7
  18. package/dist/codex-app-server/forwarder.js +11 -5
  19. package/dist/codex-app-server/mapping.d.ts +1 -1
  20. package/dist/codex-app-server/mapping.js +27 -2
  21. package/dist/codex-app-server/protocol.d.ts +238 -4
  22. package/dist/codex-app-server/transport.d.ts +20 -5
  23. package/dist/codex-app-server/transport.js +93 -40
  24. package/dist/codex-app-server/ws-channel.d.ts +3 -3
  25. package/dist/codex-app-server/ws-channel.js +23 -7
  26. package/dist/codex-child-env.js +33 -0
  27. package/dist/codex-home.d.ts +6 -6
  28. package/dist/codex-home.js +8 -9
  29. package/dist/codex-session-store.d.ts +2 -1
  30. package/dist/host.d.ts +34 -33
  31. package/dist/host.js +531 -91
  32. package/dist/index.d.ts +4 -3
  33. package/dist/index.js +1 -1
  34. package/dist/interactions.d.ts +61 -0
  35. package/dist/interactions.js +236 -0
  36. package/dist/models-catalog.d.ts +1 -1
  37. package/dist/models-catalog.js +1 -1
  38. package/dist/runner/child.d.ts +9 -1
  39. package/dist/runner/child.js +93 -15
  40. package/dist/runner/manager.d.ts +59 -10
  41. package/dist/runner/manager.js +385 -41
  42. package/dist/runner/protocol.d.ts +18 -7
  43. package/dist/runner-main.js +9 -6
  44. package/dist/runtime-status.js +1 -1
  45. package/dist/terminal/claude-tui.d.ts +8 -3
  46. package/dist/terminal/claude-tui.js +6 -2
  47. package/dist/terminal/codex-tui.d.ts +3 -3
  48. package/dist/terminal/codex-tui.js +1 -1
  49. package/dist/terminal/registry.d.ts +1 -1
  50. package/dist/terminal/registry.js +1 -1
  51. package/dist/terminal/tmux.d.ts +6 -6
  52. package/dist/terminal/tmux.js +10 -10
  53. package/package.json +3 -3
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Persistent codex session forwarder — the heart of omnigent's codex-native
2
+ * Persistent codex session forwarder — the heart of reference implementation's codex-native
3
3
  * model, ported to rynx. It subscribes to a session's app-server for the whole
4
4
  * session lifetime (not just one turn) and maps every thread notification to a
5
5
  * typed {@link AgentEvent}, so turns started by ANY client — the web composer OR
@@ -10,9 +10,9 @@
10
10
  * (or a fatal error) closes it. The turn's codex `turnId` is surfaced on
11
11
  * {@link CodexForwarderSink.onTurnStart} so the normalizer's `responseId` is
12
12
  * DETERMINISTIC (`resp_codex_<turnId>`) — the same turn always maps to the same
13
- * response id across snapshot/live, so items converge (omnigent's `codex_{turnId}`).
13
+ * response id across snapshot/live, so items converge (reference implementation's `codex_{turnId}`).
14
14
  *
15
- * omnigent's subscribe-then-mirror model (verified against real codex 0.142.5):
15
+ * reference implementation's subscribe-then-mirror model (verified against real codex 0.142.5):
16
16
  * the app-server delivers a thread's item/turn notifications to a connection that
17
17
  * has `thread/resume`d it. A fresh TUI-created thread has no rollout until its
18
18
  * first turn, so resume is parked until {@link CodexForwarderSink.onThreadActive}
@@ -41,7 +41,7 @@ export interface CodexForwarderSink {
41
41
  * or a resume). The host persists the id + starts the subscribe loop. */
42
42
  onThreadStarted?(threadId: string): void;
43
43
  /** The thread showed activity (a turn/item began, so its rollout now exists).
44
- * Fired once; lets a parked `thread/resume` retry (omnigent's ready signal). */
44
+ * Fired once; lets a parked `thread/resume` retry (reference implementation's ready signal). */
45
45
  onThreadActive?(): void;
46
46
  }
47
47
  export declare class CodexSessionForwarder {
@@ -54,10 +54,10 @@ export declare class CodexSessionForwarder {
54
54
  private activeSignaled;
55
55
  /** Completed-item dedup keys already mirrored (live vs resume backfill). Key =
56
56
  * `threadId:turnId:item.id`; anonymous items use a per-(thread,turn) position
57
- * counter. Mirrors omnigent `_completed_item_key` + `synced_item_keys`. */
57
+ * counter. Mirrors reference implementation `_completed_item_key` + `synced_item_keys`. */
58
58
  private readonly seenCompletedItems;
59
59
  /** Per-(thread,turn) position counter for items lacking a stable codex id
60
- * (peek-then-advance; advanced only on a successful claim). omnigent anon path. */
60
+ * (peek-then-advance; advanced only on a successful claim). reference implementation anon path. */
61
61
  private readonly anonCounters;
62
62
  constructor(client: CodexAppServerClient, sink: CodexForwarderSink);
63
63
  /** Begin mirroring. Idempotent. */
@@ -85,7 +85,7 @@ export declare class CodexSessionForwarder {
85
85
  * `threadId:turnId:item.id` — identical across replay + live, so the second
86
86
  * delivery is dropped. Items without a codex id fall back to a per-(thread,turn)
87
87
  * position counter (peeked here; advanced only on a successful claim, via
88
- * {@link advanceAnonCounter}). Mirrors omnigent `_completed_item_key`. */
88
+ * {@link advanceAnonCounter}). Mirrors reference implementation `_completed_item_key`. */
89
89
  private completedItemKey;
90
90
  private advanceAnonCounter;
91
91
  private ensureTurn;
@@ -19,7 +19,7 @@ function userMessageText(item) {
19
19
  return text || undefined;
20
20
  }
21
21
  /** Whether a notification implies the thread is now active (its first turn has
22
- * begun, so the rollout exists). Mirrors omnigent's `_event_indicates_thread_active`. */
22
+ * begun, so the rollout exists). Mirrors reference implementation's `_event_indicates_thread_active`. */
23
23
  function indicatesActive(method, params) {
24
24
  if (method.startsWith("turn/") || method.startsWith("item/"))
25
25
  return true;
@@ -39,10 +39,10 @@ export class CodexSessionForwarder {
39
39
  activeSignaled = false;
40
40
  /** Completed-item dedup keys already mirrored (live vs resume backfill). Key =
41
41
  * `threadId:turnId:item.id`; anonymous items use a per-(thread,turn) position
42
- * counter. Mirrors omnigent `_completed_item_key` + `synced_item_keys`. */
42
+ * counter. Mirrors reference implementation `_completed_item_key` + `synced_item_keys`. */
43
43
  seenCompletedItems = new Set();
44
44
  /** Per-(thread,turn) position counter for items lacking a stable codex id
45
- * (peek-then-advance; advanced only on a successful claim). omnigent anon path. */
45
+ * (peek-then-advance; advanced only on a successful claim). reference implementation anon path. */
46
46
  anonCounters = new Map();
47
47
  constructor(client, sink) {
48
48
  this.client = client;
@@ -91,8 +91,14 @@ export class CodexSessionForwarder {
91
91
  this.ensureTurn();
92
92
  for (const item of turn.items ?? [])
93
93
  this.processCompletedItem(item);
94
+ if (turn.status === "inProgress")
95
+ continue;
96
+ const mapped = mapCodexNotification("turn/completed", { turn });
94
97
  this.turnOpen = false;
95
- this.sink.onTurnEnd();
98
+ if (mapped.fatalError)
99
+ this.sink.onTurnError(mapped.fatalError);
100
+ else
101
+ this.sink.onTurnEnd(mapped.usage);
96
102
  }
97
103
  }
98
104
  handle(method, params) {
@@ -166,7 +172,7 @@ export class CodexSessionForwarder {
166
172
  * `threadId:turnId:item.id` — identical across replay + live, so the second
167
173
  * delivery is dropped. Items without a codex id fall back to a per-(thread,turn)
168
174
  * position counter (peeked here; advanced only on a successful claim, via
169
- * {@link advanceAnonCounter}). Mirrors omnigent `_completed_item_key`. */
175
+ * {@link advanceAnonCounter}). Mirrors reference implementation `_completed_item_key`. */
170
176
  completedItemKey(item) {
171
177
  const threadId = this.currentThreadIdValue ?? "thread";
172
178
  const turnId = this.currentTurnIdValue ?? "turn";
@@ -2,7 +2,7 @@
2
2
  * Pure codex app-server notification → {@link AgentEvent} mapping. Extracted from
3
3
  * the executor so BOTH the per-turn executor and the persistent session
4
4
  * forwarder (which mirrors every thread turn — web- AND TUI-initiated — into the
5
- * canonical log, omnigent's codex-native model) share one mapping.
5
+ * canonical log, reference implementation's codex-native model) share one mapping.
6
6
  */
7
7
  import type { AgentEvent } from "@rynx-ai/core";
8
8
  import type { ThreadItem } from "./protocol.js";
@@ -1,3 +1,13 @@
1
+ function turnError(error, fallback) {
2
+ if (typeof error === "string" && error.trim())
3
+ return new Error(error);
4
+ if (error && typeof error === "object" && "message" in error) {
5
+ const message = error.message;
6
+ if (typeof message === "string" && message.trim())
7
+ return new Error(message);
8
+ }
9
+ return new Error(fallback);
10
+ }
1
11
  /** Map one thread item (`item/started` | `item/completed`) to events. */
2
12
  export function mapCodexItem(method, item) {
3
13
  const events = [];
@@ -112,12 +122,27 @@ export function mapCodexNotification(method, params) {
112
122
  switch (typed.method) {
113
123
  case "thread/started":
114
124
  return { events };
125
+ case "serverRequest/resolved":
126
+ // Interaction lifecycle is handled by CodexAppServerClient. It is not
127
+ // model output and must never open or close a Turn in the forwarder.
128
+ return { events };
115
129
  case "turn/started":
116
130
  return { events };
117
131
  case "turn/completed": {
118
132
  const turnPayload = typed.params?.turn;
119
- if (turnPayload?.status === "failed" && turnPayload.error?.message) {
120
- return { events, fatalError: new Error(turnPayload.error.message), turnCompleted: true };
133
+ if (turnPayload?.status === "failed") {
134
+ return {
135
+ events,
136
+ fatalError: turnError(turnPayload.error, "Codex turn failed"),
137
+ turnCompleted: true,
138
+ };
139
+ }
140
+ if (turnPayload?.status === "interrupted") {
141
+ return {
142
+ events,
143
+ fatalError: turnError(turnPayload.error, "Codex turn was interrupted"),
144
+ turnCompleted: true,
145
+ };
121
146
  }
122
147
  return { events, turnCompleted: true };
123
148
  }
@@ -58,7 +58,8 @@ export interface GetAuthStatusResponse {
58
58
  }
59
59
  export type AskForApproval = "untrusted" | "on-failure" | "on-request" | "never";
60
60
  export type SandboxMode = "read-only" | "workspace-write" | "danger-full-access";
61
- export type ReasoningEffort = "none" | "minimal" | "low" | "medium" | "high" | "xhigh";
61
+ /** Open since Codex App Server 0.144; values are advertised by `model/list`. */
62
+ export type ReasoningEffort = string;
62
63
  export interface ThreadStartParams {
63
64
  model?: string | null;
64
65
  modelProvider?: string | null;
@@ -75,13 +76,15 @@ export interface ThreadResumeParams extends ThreadStartParams {
75
76
  /** When true, the resume response omits the thread's `turns` backlog (used to
76
77
  * SUBSCRIBE without re-replaying history). When false/absent, the response
77
78
  * carries `thread.turns[].items[]` — the backfill the forwarder replays for a
78
- * fresh thread's first turn (omnigent's `_replay_resume_response`). */
79
+ * fresh thread's first turn (reference implementation's `_replay_resume_response`). */
79
80
  excludeTurns?: boolean;
80
81
  }
81
82
  /** One turn in a resumed thread's backlog (`thread/resume` response). */
82
83
  export interface ResumedTurn {
83
84
  id?: string;
84
85
  turnId?: string;
86
+ status: TurnStatus;
87
+ error?: unknown;
85
88
  items?: ThreadItem[];
86
89
  }
87
90
  /** The `thread` object a `thread/resume` response carries (id + optional backlog). */
@@ -256,6 +259,11 @@ export interface ModelInfo {
256
259
  hidden?: boolean;
257
260
  isDefault?: boolean;
258
261
  supportsPersonality?: boolean;
262
+ supportedReasoningEfforts?: Array<{
263
+ reasoningEffort: ReasoningEffort;
264
+ description?: string;
265
+ }>;
266
+ defaultReasoningEffort?: ReasoningEffort;
259
267
  [key: string]: unknown;
260
268
  }
261
269
  export interface ModelListResponse {
@@ -450,11 +458,26 @@ export interface CommandExecutionRequestApprovalParams {
450
458
  itemId: string;
451
459
  startedAtMs: number;
452
460
  approvalId?: string | null;
461
+ environmentId: string | null;
453
462
  reason?: string | null;
463
+ networkApprovalContext?: NetworkApprovalContext | null;
454
464
  command?: string | null;
455
465
  cwd?: string | null;
456
- }
457
- export type CommandExecutionApprovalDecision = "accept" | "acceptForSession" | "decline" | "cancel";
466
+ commandActions?: Array<Record<string, unknown>> | null;
467
+ additionalPermissions?: AdditionalPermissionProfile | null;
468
+ proposedExecpolicyAmendment?: string[] | null;
469
+ proposedNetworkPolicyAmendments?: NetworkPolicyAmendment[] | null;
470
+ availableDecisions?: CommandExecutionApprovalDecision[] | null;
471
+ }
472
+ export type CommandExecutionApprovalDecision = "accept" | "acceptForSession" | {
473
+ acceptWithExecpolicyAmendment: {
474
+ execpolicy_amendment: string[];
475
+ };
476
+ } | {
477
+ applyNetworkPolicyAmendment: {
478
+ network_policy_amendment: NetworkPolicyAmendment;
479
+ };
480
+ } | "decline" | "cancel";
458
481
  export interface CommandExecutionRequestApprovalResponse {
459
482
  decision: CommandExecutionApprovalDecision;
460
483
  }
@@ -470,3 +493,214 @@ export type FileChangeApprovalDecision = "accept" | "acceptForSession" | "declin
470
493
  export interface FileChangeRequestApprovalResponse {
471
494
  decision: FileChangeApprovalDecision;
472
495
  }
496
+ /** Legacy/experimental app-server approval methods still emitted by current
497
+ * Codex builds alongside the v2 item approval methods. */
498
+ export interface ExecCommandApprovalParams {
499
+ conversationId: string;
500
+ callId: string;
501
+ approvalId: string | null;
502
+ command: string[];
503
+ cwd: string;
504
+ reason: string | null;
505
+ }
506
+ export interface ApplyPatchApprovalParams {
507
+ conversationId: string;
508
+ callId: string;
509
+ fileChanges: Record<string, {
510
+ type: "add" | "delete";
511
+ content: string;
512
+ } | {
513
+ type: "update";
514
+ unified_diff: string;
515
+ move_path: string | null;
516
+ }>;
517
+ reason: string | null;
518
+ grantRoot: string | null;
519
+ }
520
+ export type LegacyReviewDecision = "approved" | "approved_for_session" | "denied" | "timed_out" | "abort";
521
+ export interface LegacyApprovalResponse {
522
+ decision: LegacyReviewDecision;
523
+ }
524
+ /** EXPERIMENTAL request_user_input question advertised by Codex app-server. */
525
+ export interface ToolRequestUserInputQuestion {
526
+ id: string;
527
+ header: string;
528
+ question: string;
529
+ isOther: boolean;
530
+ isSecret: boolean;
531
+ options: Array<{
532
+ label: string;
533
+ description: string;
534
+ }> | null;
535
+ }
536
+ export interface ToolRequestUserInputParams {
537
+ threadId: string;
538
+ turnId: string;
539
+ itemId: string;
540
+ questions: ToolRequestUserInputQuestion[];
541
+ autoResolutionMs: number | null;
542
+ }
543
+ export interface ToolRequestUserInputResponse {
544
+ answers: Record<string, {
545
+ answers: string[];
546
+ }>;
547
+ }
548
+ export interface McpElicitationConstOption {
549
+ const: string;
550
+ title: string;
551
+ }
552
+ export type McpElicitationPrimitiveSchema = {
553
+ type: "string";
554
+ title?: string;
555
+ description?: string;
556
+ minLength?: number;
557
+ maxLength?: number;
558
+ format?: "email" | "uri" | "date" | "date-time";
559
+ default?: string;
560
+ } | {
561
+ type: "string";
562
+ title?: string;
563
+ description?: string;
564
+ enum: string[];
565
+ enumNames?: string[];
566
+ default?: string;
567
+ } | {
568
+ type: "string";
569
+ title?: string;
570
+ description?: string;
571
+ oneOf: McpElicitationConstOption[];
572
+ default?: string;
573
+ } | {
574
+ type: "array";
575
+ title?: string;
576
+ description?: string;
577
+ minItems?: number;
578
+ maxItems?: number;
579
+ items: {
580
+ type: "string";
581
+ enum: string[];
582
+ } | {
583
+ anyOf: McpElicitationConstOption[];
584
+ };
585
+ default?: string[];
586
+ } | {
587
+ type: "number" | "integer";
588
+ title?: string;
589
+ description?: string;
590
+ minimum?: number;
591
+ maximum?: number;
592
+ default?: number;
593
+ } | {
594
+ type: "boolean";
595
+ title?: string;
596
+ description?: string;
597
+ default?: boolean;
598
+ };
599
+ export interface McpElicitationSchema {
600
+ $schema?: string;
601
+ type: "object";
602
+ properties: Record<string, McpElicitationPrimitiveSchema>;
603
+ required?: string[];
604
+ }
605
+ /** MCP elicitation request. `openai/form` deliberately keeps its schema open. */
606
+ export type McpServerElicitationRequestParams = {
607
+ threadId: string;
608
+ turnId: string | null;
609
+ serverName: string;
610
+ } & ({
611
+ mode: "form";
612
+ message: string;
613
+ requestedSchema: McpElicitationSchema;
614
+ _meta: unknown;
615
+ } | {
616
+ mode: "openai/form";
617
+ message: string;
618
+ requestedSchema: Record<string, unknown>;
619
+ _meta: unknown;
620
+ } | {
621
+ mode: "url";
622
+ message: string;
623
+ url: string;
624
+ elicitationId: string;
625
+ _meta: unknown;
626
+ });
627
+ export interface McpServerElicitationRequestResponse {
628
+ action: "accept" | "decline" | "cancel";
629
+ content: unknown | null;
630
+ _meta: unknown | null;
631
+ }
632
+ export interface AdditionalNetworkPermissions {
633
+ enabled: boolean | null;
634
+ }
635
+ export type FileSystemSpecialPath = {
636
+ kind: "root";
637
+ } | {
638
+ kind: "minimal";
639
+ } | {
640
+ kind: "project_roots";
641
+ subpath: string | null;
642
+ } | {
643
+ kind: "tmpdir";
644
+ } | {
645
+ kind: "slash_tmp";
646
+ } | {
647
+ kind: "unknown";
648
+ path: string;
649
+ subpath: string | null;
650
+ };
651
+ export type FileSystemPath = {
652
+ type: "path";
653
+ path: string;
654
+ } | {
655
+ type: "glob_pattern";
656
+ pattern: string;
657
+ } | {
658
+ type: "special";
659
+ value: FileSystemSpecialPath;
660
+ };
661
+ export interface FileSystemSandboxEntry {
662
+ path: FileSystemPath;
663
+ access: "read" | "write" | "deny";
664
+ }
665
+ export interface AdditionalFileSystemPermissions {
666
+ read: string[] | null;
667
+ write: string[] | null;
668
+ globScanMaxDepth?: number;
669
+ entries?: FileSystemSandboxEntry[];
670
+ }
671
+ export interface AdditionalPermissionProfile {
672
+ network: AdditionalNetworkPermissions | null;
673
+ fileSystem: AdditionalFileSystemPermissions | null;
674
+ }
675
+ export interface NetworkApprovalContext {
676
+ host: string;
677
+ protocol: "http" | "https" | "socks5Tcp" | "socks5Udp";
678
+ }
679
+ export interface NetworkPolicyAmendment {
680
+ host: string;
681
+ action: "allow" | "deny";
682
+ }
683
+ export type RequestPermissionProfile = AdditionalPermissionProfile;
684
+ export interface PermissionsRequestApprovalParams {
685
+ threadId: string;
686
+ turnId: string;
687
+ itemId: string;
688
+ environmentId: string | null;
689
+ startedAtMs: number;
690
+ cwd: string;
691
+ reason: string | null;
692
+ permissions: RequestPermissionProfile;
693
+ }
694
+ export interface PermissionsRequestApprovalResponse {
695
+ permissions: {
696
+ network?: AdditionalNetworkPermissions;
697
+ fileSystem?: AdditionalFileSystemPermissions;
698
+ };
699
+ scope: "turn" | "session";
700
+ strictAutoReview?: boolean;
701
+ }
702
+ /** A different app-server client (usually the native TUI) answered first. */
703
+ export interface ServerRequestResolvedNotificationParams {
704
+ threadId?: string;
705
+ requestId: RequestId;
706
+ }
@@ -1,5 +1,5 @@
1
1
  import { EventEmitter } from "node:events";
2
- import type { SandboxMode } from "./protocol.js";
2
+ import type { RequestId, SandboxMode } from "./protocol.js";
3
3
  export declare function buildAppServerSpawnArgs(sandboxMode: SandboxMode, listen?: string): string[];
4
4
  /** app-server args WITHOUT `--listen` — for a channel that appends its own
5
5
  * transport endpoint (e.g. {@link import("./ws-channel.js").WsRpcChannel}). */
@@ -29,7 +29,7 @@ export interface RpcChannel {
29
29
  /** Establish the channel (connect / await readiness). */
30
30
  start(): Promise<void>;
31
31
  /** Write one framed message (already newline-terminated). */
32
- send(line: string): void;
32
+ send(line: string): void | Promise<void>;
33
33
  /** Register the inbound-line handler (one framed message per call). */
34
34
  onLine(cb: (line: string) => void): void;
35
35
  /** Register the close/error handler. */
@@ -64,8 +64,17 @@ export declare class CodexTransportError extends Error {
64
64
  readonly data?: unknown;
65
65
  constructor(message: string, code?: number, data?: unknown);
66
66
  }
67
- export type ServerRequestHandler = (method: string, params: unknown) => Promise<unknown> | unknown;
67
+ export type ServerRequestHandler = (method: string, params: unknown, requestId: RequestId) => Promise<unknown | typeof NO_SERVER_RESPONSE> | unknown | typeof NO_SERVER_RESPONSE;
68
+ /** A server request was resolved by another app-server client. In that case the
69
+ * local handler must settle without sending a second JSON-RPC response. */
70
+ export declare const NO_SERVER_RESPONSE: unique symbol;
68
71
  export type ServerNotificationHandler = (method: string, params: unknown) => void;
72
+ export type ServerRequestResponseDeliveryHandler = (requestId: RequestId, result: {
73
+ delivered: true;
74
+ } | {
75
+ delivered: false;
76
+ error: Error;
77
+ }) => void;
69
78
  export interface CodexAppServerTransportOptions {
70
79
  /** Default stdio transport: spawns `app-server --listen stdio://`. Mutually
71
80
  * exclusive with {@link channel}; provide exactly one. */
@@ -83,6 +92,10 @@ export interface CodexAppServerTransportOptions {
83
92
  * propagated back to the server.
84
93
  */
85
94
  onNotification?: ServerNotificationHandler;
95
+ /** Reports whether a server-request response was actually handed to the
96
+ * transport. Provider acknowledgement still arrives separately as
97
+ * `serverRequest/resolved`. */
98
+ onServerRequestResponseDelivery?: ServerRequestResponseDeliveryHandler;
86
99
  }
87
100
  interface TransportEvents {
88
101
  exit: [code: number | null, signal: NodeJS.Signals | null];
@@ -109,6 +122,7 @@ export declare class CodexAppServerTransport extends EventEmitter {
109
122
  private readonly logger;
110
123
  private readonly onServerRequest?;
111
124
  private readonly onNotification?;
125
+ private readonly onServerRequestResponseDelivery?;
112
126
  private child;
113
127
  private rl;
114
128
  private stderrRl;
@@ -116,14 +130,14 @@ export declare class CodexAppServerTransport extends EventEmitter {
116
130
  private readonly pending;
117
131
  private startPromise;
118
132
  private exited;
119
- constructor({ spawner, channel, logger, onServerRequest, onNotification, }: CodexAppServerTransportOptions);
133
+ constructor({ spawner, channel, logger, onServerRequest, onNotification, onServerRequestResponseDelivery, }: CodexAppServerTransportOptions);
120
134
  emit<K extends keyof TransportEvents>(event: K, ...args: TransportEvents[K]): boolean;
121
135
  on<K extends keyof TransportEvents>(event: K, listener: (...args: TransportEvents[K]) => void): this;
122
136
  off<K extends keyof TransportEvents>(event: K, listener: (...args: TransportEvents[K]) => void): this;
123
137
  isRunning(): boolean;
124
138
  ensureStarted(): Promise<void>;
125
139
  sendRequest<TResult = unknown>(method: string, params?: unknown): Promise<TResult>;
126
- sendNotification(method: string, params?: unknown): void;
140
+ sendNotification(method: string, params?: unknown): Promise<void>;
127
141
  stop(signal?: NodeJS.Signals): Promise<void>;
128
142
  private startTransport;
129
143
  private startChild;
@@ -134,6 +148,7 @@ export declare class CodexAppServerTransport extends EventEmitter {
134
148
  private handleErrorEnvelope;
135
149
  private handleServerRequest;
136
150
  private respondToServerRequest;
151
+ private notifyServerRequestResponseDelivery;
137
152
  private handleNotification;
138
153
  }
139
154
  export {};