@rynx-ai/runtime 0.1.11-beta.24 → 0.1.11-beta.25
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.
- package/dist/claude/native-hook-main.js +62 -0
- package/dist/claude/native-integration.js +1 -1
- package/dist/codex-app-server/forwarder.d.ts +16 -1
- package/dist/codex-app-server/forwarder.js +61 -17
- package/dist/codex-app-server/mapping.js +16 -1
- package/dist/codex-app-server/protocol.d.ts +25 -1
- package/dist/host.d.ts +15 -7
- package/dist/host.js +430 -24
- package/dist/runner/child.d.ts +7 -4
- package/dist/runner/child.js +29 -3
- package/dist/runner/manager.d.ts +9 -3
- package/dist/runner/manager.js +53 -7
- package/dist/runner/protocol.d.ts +16 -1
- package/dist/terminal/registry.js +1 -1
- package/dist/terminal/tmux.d.ts +5 -5
- package/dist/terminal/tmux.js +6 -6
- package/package.json +2 -2
|
@@ -176,6 +176,43 @@ function permissionRequest(id, payload, toolInput, suggestions) {
|
|
|
176
176
|
const toolName = asString(payload.tool_name) ?? "tool";
|
|
177
177
|
const command = asString(toolInput.command) ?? asString(toolInput.file_path);
|
|
178
178
|
const cwd = asString(payload.cwd);
|
|
179
|
+
if (toolName === "ExitPlanMode") {
|
|
180
|
+
const plan = asString(toolInput.plan) ?? "Plan details were not provided by Claude.";
|
|
181
|
+
return {
|
|
182
|
+
interactionId: id,
|
|
183
|
+
kind: "permission",
|
|
184
|
+
title: "Plan review",
|
|
185
|
+
fields: [{
|
|
186
|
+
id: "feedback",
|
|
187
|
+
type: "text",
|
|
188
|
+
label: "What should change about the plan?",
|
|
189
|
+
required: false,
|
|
190
|
+
multiline: true,
|
|
191
|
+
placeholder: "Revision feedback (optional)",
|
|
192
|
+
}],
|
|
193
|
+
actions: [
|
|
194
|
+
{
|
|
195
|
+
id: "allow_auto",
|
|
196
|
+
label: "Yes, and use auto mode",
|
|
197
|
+
style: "primary",
|
|
198
|
+
requiresAnswers: false,
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
id: "allow_manual",
|
|
202
|
+
label: "Yes, manually approve edits",
|
|
203
|
+
requiresAnswers: false,
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
id: "deny_feedback",
|
|
207
|
+
label: "Reject with feedback",
|
|
208
|
+
style: "danger",
|
|
209
|
+
requiresAnswers: false,
|
|
210
|
+
},
|
|
211
|
+
],
|
|
212
|
+
context: { toolName, summary: plan },
|
|
213
|
+
createdAt: Date.now(),
|
|
214
|
+
};
|
|
215
|
+
}
|
|
179
216
|
return {
|
|
180
217
|
interactionId: id,
|
|
181
218
|
kind: "permission",
|
|
@@ -261,6 +298,31 @@ function nativeVerdict(hookKind, payload, result, suggestions) {
|
|
|
261
298
|
},
|
|
262
299
|
};
|
|
263
300
|
}
|
|
301
|
+
if (toolName === "ExitPlanMode") {
|
|
302
|
+
const feedback = answerText(resolution.answers?.feedback).trim();
|
|
303
|
+
const behavior = resolution.actionId === "allow_auto" ||
|
|
304
|
+
resolution.actionId === "allow_manual"
|
|
305
|
+
? "allow"
|
|
306
|
+
: "deny";
|
|
307
|
+
return {
|
|
308
|
+
hookSpecificOutput: {
|
|
309
|
+
hookEventName: "PermissionRequest",
|
|
310
|
+
decision: {
|
|
311
|
+
behavior,
|
|
312
|
+
...(behavior === "deny" && feedback ? { message: feedback } : {}),
|
|
313
|
+
...(behavior === "allow"
|
|
314
|
+
? {
|
|
315
|
+
updatedPermissions: [{
|
|
316
|
+
type: "setMode",
|
|
317
|
+
mode: resolution.actionId === "allow_auto" ? "auto" : "default",
|
|
318
|
+
destination: "session",
|
|
319
|
+
}],
|
|
320
|
+
}
|
|
321
|
+
: {}),
|
|
322
|
+
},
|
|
323
|
+
},
|
|
324
|
+
};
|
|
325
|
+
}
|
|
264
326
|
const suggestionMatch = /^allow_suggestion_(\d+)$/.exec(resolution.actionId);
|
|
265
327
|
const suggestionIndex = suggestionMatch ? Number(suggestionMatch[1]) : -1;
|
|
266
328
|
const selectedSuggestion = Number.isSafeInteger(suggestionIndex)
|
|
@@ -29,7 +29,7 @@ const MAX_SUBMISSION_OBSERVATIONS = 64;
|
|
|
29
29
|
const INTERACTION_ACK_TIMEOUT_MS = 5_000;
|
|
30
30
|
// Claude writes this synthetic user record after Escape (including a tool-use
|
|
31
31
|
// interruption). It is lifecycle, not a new prompt. Kept aligned with
|
|
32
|
-
//
|
|
32
|
+
// reference implementation's `_CLAUDE_INTERRUPT_RECORD_RE`.
|
|
33
33
|
const CLAUDE_INTERRUPT_RECORD_RE = /^\[Request interrupted by user(?: for tool use)?\]$/;
|
|
34
34
|
const INTERACTION_LEASE_TIMEOUT_MS = 30_000;
|
|
35
35
|
function processIsAlive(pid) {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
import type { AgentEvent, UserContentPart } from "@rynx-ai/core";
|
|
25
25
|
import type { CodexAppServerClient } from "./client.js";
|
|
26
26
|
import type { McpStartupPlan } from "./mcp-startup.js";
|
|
27
|
-
import type { ResumedTurn } from "./protocol.js";
|
|
27
|
+
import type { CollaborationModeKind, ResumedTurn } from "./protocol.js";
|
|
28
28
|
export interface CodexForwarderSink {
|
|
29
29
|
/** A turn began. `turnId` is codex's turn id, used to derive a stable
|
|
30
30
|
* `responseId`. Start a fresh normalizer/response. */
|
|
@@ -58,6 +58,16 @@ export interface CodexForwarderSink {
|
|
|
58
58
|
/** The thread showed activity (a turn/item began, so its rollout now exists).
|
|
59
59
|
* Fired once; lets a parked `thread/resume` retry (reference implementation's ready signal). */
|
|
60
60
|
onThreadActive?(): void;
|
|
61
|
+
/** The native TUI or another app-server client changed collaboration mode. */
|
|
62
|
+
onCollaborationModeChanged?(mode: CollaborationModeKind): void;
|
|
63
|
+
/** Codex's terminal-local Plan picker is not emitted by app-server today.
|
|
64
|
+
* Synthesize it only after a live Plan item and its Turn both complete. */
|
|
65
|
+
onPlanImplementationPrompt?(prompt: CodexPlanImplementationPrompt): void;
|
|
66
|
+
}
|
|
67
|
+
export interface CodexPlanImplementationPrompt {
|
|
68
|
+
threadId: string;
|
|
69
|
+
turnId: string;
|
|
70
|
+
text: string;
|
|
61
71
|
}
|
|
62
72
|
export interface CodexSessionForwarderOptions {
|
|
63
73
|
/** Some Codex-lineage runtimes publish the final item one frame after
|
|
@@ -101,6 +111,8 @@ export declare class CodexSessionForwarder {
|
|
|
101
111
|
/** Per-(thread,turn) position counter for items lacking a stable codex id
|
|
102
112
|
* (peek-then-advance; advanced only on a successful claim). reference implementation anon path. */
|
|
103
113
|
private readonly anonCounters;
|
|
114
|
+
private pendingPlanImplementation;
|
|
115
|
+
private replayingBackfill;
|
|
104
116
|
constructor(client: CodexAppServerClient, sink: CodexForwarderSink, options?: CodexSessionForwarderOptions);
|
|
105
117
|
/** Begin mirroring. Idempotent. */
|
|
106
118
|
start(): void;
|
|
@@ -136,6 +148,9 @@ export declare class CodexSessionForwarder {
|
|
|
136
148
|
* not doubled.
|
|
137
149
|
*/
|
|
138
150
|
replayBackfill(turns: ResumedTurn[]): void;
|
|
151
|
+
/** Suppress our synthesized picker when a future app-server emits the native
|
|
152
|
+
* `plan_implementation` request itself. */
|
|
153
|
+
noteNativePlanImplementationPrompt(turnId?: string): void;
|
|
139
154
|
/** Fail an open response exactly once when its observer or terminal exits. */
|
|
140
155
|
failOpenTurn(error: Error): boolean;
|
|
141
156
|
private handle;
|
|
@@ -86,6 +86,8 @@ export class CodexSessionForwarder {
|
|
|
86
86
|
/** Per-(thread,turn) position counter for items lacking a stable codex id
|
|
87
87
|
* (peek-then-advance; advanced only on a successful claim). reference implementation anon path. */
|
|
88
88
|
anonCounters = new Map();
|
|
89
|
+
pendingPlanImplementation = null;
|
|
90
|
+
replayingBackfill = false;
|
|
89
91
|
constructor(client, sink, options = {}) {
|
|
90
92
|
this.client = client;
|
|
91
93
|
this.sink = sink;
|
|
@@ -191,22 +193,37 @@ export class CodexSessionForwarder {
|
|
|
191
193
|
* not doubled.
|
|
192
194
|
*/
|
|
193
195
|
replayBackfill(turns) {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
this.
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
this.
|
|
208
|
-
|
|
209
|
-
|
|
196
|
+
this.replayingBackfill = true;
|
|
197
|
+
try {
|
|
198
|
+
for (const turn of turns) {
|
|
199
|
+
const turnId = turn.id ?? turn.turnId;
|
|
200
|
+
if (turnId)
|
|
201
|
+
this.currentTurnIdValue = turnId;
|
|
202
|
+
this.ensureTurn();
|
|
203
|
+
for (const item of turn.items ?? [])
|
|
204
|
+
this.processCompletedItem(item);
|
|
205
|
+
if (codexResumeTerminalStatus(turn) === undefined)
|
|
206
|
+
continue;
|
|
207
|
+
const mapped = mapCodexNotification("turn/completed", { turn });
|
|
208
|
+
this.turnOpen = false;
|
|
209
|
+
this.currentTurnIdValue = null;
|
|
210
|
+
if (mapped.fatalError)
|
|
211
|
+
this.sink.onTurnError(mapped.fatalError);
|
|
212
|
+
else
|
|
213
|
+
this.sink.onTurnEnd(mapped.usage);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
finally {
|
|
217
|
+
this.replayingBackfill = false;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
/** Suppress our synthesized picker when a future app-server emits the native
|
|
221
|
+
* `plan_implementation` request itself. */
|
|
222
|
+
noteNativePlanImplementationPrompt(turnId) {
|
|
223
|
+
if (!this.pendingPlanImplementation)
|
|
224
|
+
return;
|
|
225
|
+
if (!turnId || this.pendingPlanImplementation.turnId === turnId) {
|
|
226
|
+
this.pendingPlanImplementation = null;
|
|
210
227
|
}
|
|
211
228
|
}
|
|
212
229
|
/** Fail an open response exactly once when its observer or terminal exits. */
|
|
@@ -248,6 +265,14 @@ export class CodexSessionForwarder {
|
|
|
248
265
|
this.handleMcpStartupStatus(params);
|
|
249
266
|
return;
|
|
250
267
|
}
|
|
268
|
+
if (method === "thread/settings/updated") {
|
|
269
|
+
const threadSettings = params?.threadSettings;
|
|
270
|
+
const mode = (threadSettings?.collaborationMode ?? threadSettings?.collaboration_mode)?.mode;
|
|
271
|
+
if (mode === "plan" || mode === "default") {
|
|
272
|
+
this.sink.onCollaborationModeChanged?.(mode);
|
|
273
|
+
}
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
251
276
|
if (isThreadIdle(method, params) || isModelOutput(method, params)) {
|
|
252
277
|
this.settleMcpStartup();
|
|
253
278
|
}
|
|
@@ -400,6 +425,14 @@ export class CodexSessionForwarder {
|
|
|
400
425
|
}
|
|
401
426
|
settle(completion) {
|
|
402
427
|
this.flushDeferredAssistantMessage();
|
|
428
|
+
const completedTurnId = this.pendingCompletionTurnId ?? this.currentTurnIdValue;
|
|
429
|
+
const planPrompt = completion.kind === "end" &&
|
|
430
|
+
this.pendingPlanImplementation?.turnId === completedTurnId
|
|
431
|
+
? this.pendingPlanImplementation
|
|
432
|
+
: null;
|
|
433
|
+
if (this.pendingPlanImplementation?.turnId === completedTurnId) {
|
|
434
|
+
this.pendingPlanImplementation = null;
|
|
435
|
+
}
|
|
403
436
|
this.turnOpen = false;
|
|
404
437
|
this.currentTurnIdValue = null;
|
|
405
438
|
this.pendingCompletionTurnId = null;
|
|
@@ -411,8 +444,11 @@ export class CodexSessionForwarder {
|
|
|
411
444
|
else
|
|
412
445
|
this.sink.onTurnEnd(completion.usage);
|
|
413
446
|
}
|
|
414
|
-
else
|
|
447
|
+
else {
|
|
415
448
|
this.sink.onTurnEnd(completion.usage);
|
|
449
|
+
if (planPrompt)
|
|
450
|
+
this.sink.onPlanImplementationPrompt?.(planPrompt);
|
|
451
|
+
}
|
|
416
452
|
}
|
|
417
453
|
handleMcpStartupStatus(params) {
|
|
418
454
|
const update = params;
|
|
@@ -504,6 +540,14 @@ export class CodexSessionForwarder {
|
|
|
504
540
|
this.sink.onUserMessage?.(userContent);
|
|
505
541
|
return;
|
|
506
542
|
}
|
|
543
|
+
if (item.type === "plan" && !this.replayingBackfill) {
|
|
544
|
+
const text = item.text?.trim();
|
|
545
|
+
const turnId = this.currentTurnIdValue ?? this.pendingCompletionTurnId;
|
|
546
|
+
const threadId = this.currentThreadIdValue;
|
|
547
|
+
if (text && turnId && threadId) {
|
|
548
|
+
this.pendingPlanImplementation = { threadId, turnId, text };
|
|
549
|
+
}
|
|
550
|
+
}
|
|
507
551
|
const mapped = mapCodexItem("item/completed", item);
|
|
508
552
|
const canonicalEvents = mapped.events.filter((event) => event.type !== "runtime_debug");
|
|
509
553
|
if (canonicalEvents.length === 0)
|
|
@@ -208,7 +208,11 @@ export function mapCodexItem(method, item) {
|
|
|
208
208
|
return { events };
|
|
209
209
|
}
|
|
210
210
|
case "plan": {
|
|
211
|
-
|
|
211
|
+
const text = item.text?.trim() ?? "";
|
|
212
|
+
if (isEnd && text) {
|
|
213
|
+
events.push({ type: "message_completed", itemId: item.id, text });
|
|
214
|
+
return { events, finalText: text };
|
|
215
|
+
}
|
|
212
216
|
return { events };
|
|
213
217
|
}
|
|
214
218
|
case "reasoning": {
|
|
@@ -276,6 +280,17 @@ export function mapCodexNotification(method, params) {
|
|
|
276
280
|
}
|
|
277
281
|
return { events };
|
|
278
282
|
}
|
|
283
|
+
case "item/plan/delta": {
|
|
284
|
+
const delta = typed.params.delta ?? "";
|
|
285
|
+
if (delta) {
|
|
286
|
+
events.push({
|
|
287
|
+
type: "token",
|
|
288
|
+
text: delta,
|
|
289
|
+
metadata: { source: "app_server", itemId: typed.params.itemId },
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
return { events };
|
|
293
|
+
}
|
|
279
294
|
case "item/reasoning/summaryTextDelta":
|
|
280
295
|
case "item/reasoning/textDelta": {
|
|
281
296
|
const p = typed.params;
|
|
@@ -87,6 +87,16 @@ export interface PermissionProfileModificationParams {
|
|
|
87
87
|
export type PermissionSelection = string | PermissionProfileSelectionParams;
|
|
88
88
|
/** Open since Codex App Server 0.144; values are advertised by `model/list`. */
|
|
89
89
|
export type ReasoningEffort = string;
|
|
90
|
+
export type CollaborationModeKind = "plan" | "default";
|
|
91
|
+
/** Full Codex-lineage mode snapshot required by the App Server wire protocol. */
|
|
92
|
+
export interface CollaborationMode {
|
|
93
|
+
mode: CollaborationModeKind;
|
|
94
|
+
settings: {
|
|
95
|
+
model: string;
|
|
96
|
+
reasoning_effort: ReasoningEffort | null;
|
|
97
|
+
developer_instructions: string | null;
|
|
98
|
+
};
|
|
99
|
+
}
|
|
90
100
|
export interface ThreadStartParams {
|
|
91
101
|
model?: string | null;
|
|
92
102
|
modelProvider?: string | null;
|
|
@@ -102,6 +112,8 @@ export interface ThreadStartParams {
|
|
|
102
112
|
baseInstructions?: string | null;
|
|
103
113
|
developerInstructions?: string | null;
|
|
104
114
|
ephemeral?: boolean | null;
|
|
115
|
+
/** Native UI intent for a context-clearing fresh thread. */
|
|
116
|
+
sessionStartSource?: "clear" | string;
|
|
105
117
|
}
|
|
106
118
|
export interface ThreadResumeParams extends ThreadStartParams {
|
|
107
119
|
threadId: string;
|
|
@@ -157,6 +169,7 @@ export interface TurnStartParams {
|
|
|
157
169
|
permissions?: PermissionSelection | null;
|
|
158
170
|
model?: string | null;
|
|
159
171
|
effort?: ReasoningEffort | null;
|
|
172
|
+
collaborationMode?: CollaborationMode | null;
|
|
160
173
|
}
|
|
161
174
|
export interface TurnInterruptParams {
|
|
162
175
|
threadId: string;
|
|
@@ -304,7 +317,7 @@ export interface ThreadSettingsUpdateParams {
|
|
|
304
317
|
serviceTier?: string | null;
|
|
305
318
|
effort?: ReasoningEffort | null;
|
|
306
319
|
summary?: string | null;
|
|
307
|
-
collaborationMode?:
|
|
320
|
+
collaborationMode?: CollaborationMode | null;
|
|
308
321
|
personality?: string | null;
|
|
309
322
|
}
|
|
310
323
|
export interface ModelListParams {
|
|
@@ -478,6 +491,14 @@ export interface QueueStatusNotificationParams {
|
|
|
478
491
|
export type ServerNotification = {
|
|
479
492
|
method: "thread/started";
|
|
480
493
|
params: ThreadStartedNotificationParams;
|
|
494
|
+
} | {
|
|
495
|
+
method: "thread/settings/updated";
|
|
496
|
+
params: {
|
|
497
|
+
threadId: string;
|
|
498
|
+
threadSettings: {
|
|
499
|
+
collaborationMode?: CollaborationMode | null;
|
|
500
|
+
} & Record<string, unknown>;
|
|
501
|
+
};
|
|
481
502
|
} | {
|
|
482
503
|
method: "turn/started";
|
|
483
504
|
params: TurnStartedNotificationParams;
|
|
@@ -499,6 +520,9 @@ export type ServerNotification = {
|
|
|
499
520
|
} | {
|
|
500
521
|
method: "item/agentMessage/delta";
|
|
501
522
|
params: AgentMessageDeltaNotificationParams;
|
|
523
|
+
} | {
|
|
524
|
+
method: "item/plan/delta";
|
|
525
|
+
params: AgentMessageDeltaNotificationParams;
|
|
502
526
|
} | {
|
|
503
527
|
method: "item/reasoning/summaryTextDelta";
|
|
504
528
|
params: ReasoningSummaryTextDeltaNotificationParams;
|
package/dist/host.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ResolvedExecutionSnapshot, type ResolvedExecutionBudget, type RuntimeUserInput, type LiveSessionFailure, type SessionWorkspaceSnapshot, type SessionInteractionResolution, type SessionEvent } from "@rynx-ai/core";
|
|
1
|
+
import { type ResolvedExecutionSnapshot, type ResolvedExecutionBudget, type RuntimeTurnOptions, type RuntimeUserInput, type SessionCollaborationMode, type LiveSessionFailure, type SessionWorkspaceSnapshot, type SessionInteractionResolution, type SessionEvent } from "@rynx-ai/core";
|
|
2
2
|
import { type AgentRuntimeId } from "@rynx-ai/core";
|
|
3
3
|
import { type AppConfig } from "@rynx-ai/core";
|
|
4
4
|
import { createCodexChildEnv } from "./codex-child-env.js";
|
|
@@ -189,6 +189,13 @@ export declare class LocalAgentHost implements CodexCapabilities {
|
|
|
189
189
|
private createAppServerClient;
|
|
190
190
|
/** Resolve a pending native question/approval without opening a new Turn. */
|
|
191
191
|
resolveInteraction(localThreadId: string, interactionId: string, resolution: SessionInteractionResolution): Promise<ResolveInteractionResult>;
|
|
192
|
+
/** Apply collaboration mode to an already-loaded Codex-lineage thread. The
|
|
193
|
+
* caller persists only after this native RPC succeeds. */
|
|
194
|
+
updateCollaborationMode(localThreadId: string, mode: SessionCollaborationMode): Promise<void>;
|
|
195
|
+
/** Apply one explicit collaboration mode to the current native thread and
|
|
196
|
+
* remember only a successful RPC. A supplied client is already initialized
|
|
197
|
+
* and remains owned by its caller (used by cold-resume preload). */
|
|
198
|
+
private applyLiveCollaborationMode;
|
|
192
199
|
/**
|
|
193
200
|
* The command to run in a session's live terminal so it co-drives the codex
|
|
194
201
|
* app-server thread (Phase D). Returns `null` when live-terminal is off, the
|
|
@@ -227,7 +234,7 @@ export declare class LocalAgentHost implements CodexCapabilities {
|
|
|
227
234
|
* Fresh sessions already connected their discovery listener before launch;
|
|
228
235
|
* this is therefore an idempotent no-op for them and for a healthy observer. */
|
|
229
236
|
startLiveCodexObserver(localThreadId: string): void;
|
|
230
|
-
/**
|
|
237
|
+
/** reference implementation treats the forwarder as a required component of one native
|
|
231
238
|
* lifecycle: if its transport dies, it closes the app-server instead of
|
|
232
239
|
* accepting turns that can no longer reach the canonical mirror. */
|
|
233
240
|
private failObserverLifecycle;
|
|
@@ -237,7 +244,7 @@ export declare class LocalAgentHost implements CodexCapabilities {
|
|
|
237
244
|
* Subscribe the forwarder connection to a thread (reference implementation's
|
|
238
245
|
* `_subscribe_until_ready`). A fresh TUI thread has no rollout until its first
|
|
239
246
|
* turn, so `thread/resume` is retried: park until the forwarder observes the
|
|
240
|
-
* thread active, then retry. Like
|
|
247
|
+
* thread active, then retry. Like reference implementation, the first attempt always uses
|
|
241
248
|
* `excludeTurns`: a known-session cold resume therefore never reconstructs
|
|
242
249
|
* historical running/completed state. Only a fresh thread whose first attempt
|
|
243
250
|
* failed as not-ready retries without `excludeTurns`, backfilling the newly
|
|
@@ -273,7 +280,7 @@ export declare class LocalAgentHost implements CodexCapabilities {
|
|
|
273
280
|
* forwarder). Park-until-ready (~60s), aligning reference implementation's executor waiting for
|
|
274
281
|
* the bridge instead of a short race that falls back to a second output path.
|
|
275
282
|
*/
|
|
276
|
-
injectMessage(localThreadId: string, input: RuntimeUserInput | string): Promise<InjectResult>;
|
|
283
|
+
injectMessage(localThreadId: string, input: RuntimeUserInput | string, options?: RuntimeTurnOptions): Promise<InjectResult>;
|
|
277
284
|
/**
|
|
278
285
|
* Interrupt the session's active turn — the web Stop button. codex: the
|
|
279
286
|
* app-server `turn/interrupt` on the active `{threadId, turnId}` (exactly what
|
|
@@ -288,7 +295,7 @@ export declare class LocalAgentHost implements CodexCapabilities {
|
|
|
288
295
|
deferClaudeInteractionCleanup?: boolean;
|
|
289
296
|
}): void;
|
|
290
297
|
/** Tear down one codex-lineage native runtime without deleting its durable
|
|
291
|
-
* session-store binding.
|
|
298
|
+
* session-store binding. reference implementation couples its auxiliary Terminal, observer,
|
|
292
299
|
* forwarder and per-session app-server as one disposable runtime envelope;
|
|
293
300
|
* the next message recreates that envelope and cold-resumes the native id. */
|
|
294
301
|
teardownLiveCodexSession(localThreadId: string, error?: Error): boolean;
|
|
@@ -321,8 +328,9 @@ export declare class LocalAgentHost implements CodexCapabilities {
|
|
|
321
328
|
* would fail and (pre-reference implementation) fall through to a second output path. */
|
|
322
329
|
private waitInjector;
|
|
323
330
|
/** Attach a session's tmux pane injector (from the runner-child, which owns the
|
|
324
|
-
* terminal registry — the host does not hold tmux).
|
|
325
|
-
*
|
|
331
|
+
* terminal registry — the host does not hold tmux). Claude uses it for normal
|
|
332
|
+
* message injection; Codex uses it only to dismiss the exact TUI-local Plan
|
|
333
|
+
* picker after its synthetic Web form is submitted. Idempotent. */
|
|
326
334
|
attachTerminalInjector(localThreadId: string, injector: TerminalInjector): void;
|
|
327
335
|
/** Close an active native response when its terminal or runner disappears. */
|
|
328
336
|
failLiveSession(localThreadId: string, error: Error): boolean;
|