@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
package/dist/host.d.ts CHANGED
@@ -1,8 +1,9 @@
1
- import { type AgentSpec, type ResolvedExecutionBudget, type SessionEvent } from "@rynx-ai/core";
1
+ import { type AgentSpec, type ReasoningEffort, type ResolvedExecutionBudget, 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";
5
5
  import type { InjectOutcome } from "./runner/protocol.js";
6
+ import type { ResolveInteractionResult } from "./interactions.js";
6
7
  import { CodexAppServerClient } from "./codex-app-server/client.js";
7
8
  import type { ModelListResponse, ThreadGoal } from "./codex-app-server/protocol.js";
8
9
  import { type TerminalInjector } from "./claude/native-integration.js";
@@ -107,7 +108,9 @@ export type RetargetMirror = (newSessionId: string, meta: {
107
108
  parentSessionId?: string;
108
109
  }) => void;
109
110
  export interface LiveSessionOpts {
111
+ cwd?: string;
110
112
  runtime?: AgentRuntimeId;
113
+ reasoningEffort?: ReasoningEffort;
111
114
  /** Preset agent id (or inline {@link LiveSessionOpts.agentSpec}), so the live
112
115
  * launch applies the agent's model / skills / instructions — not just the
113
116
  * runtime. Absent ⇒ falls back to the config defaults (prior behavior). */
@@ -140,6 +143,9 @@ export declare class LocalAgentHost implements CodexCapabilities {
140
143
  private cachedCodexHome?;
141
144
  private readonly liveSessions;
142
145
  private readonly liveClaudeSessions;
146
+ /** Claude forwarders stopped before their terminal is killed. Runner shutdown
147
+ * finalizes these synchronously afterwards to scrub raw interaction answers. */
148
+ private readonly pendingClaudeFinalizers;
143
149
  private readonly liveEnsuring;
144
150
  constructor({ config, commandRunner, sessionStore, allowedRoots, appServerClient, now, backendIdleTtlMs, forwarderClientFactory, sessionId, }: {
145
151
  config: AppConfig;
@@ -172,13 +178,8 @@ export declare class LocalAgentHost implements CodexCapabilities {
172
178
  /** This session's private CODEX_HOME (prepared once), shared by its app-server + TUI. */
173
179
  private codexHome;
174
180
  private createAppServerClient;
175
- /**
176
- * Deliver a user's decision for a pending interactive approval (Phase D).
177
- * Routes to the codex app-server client for the thread's runtime. Returns
178
- * false when no matching pending approval exists (unknown id / already
179
- * resolved / claude runtime).
180
- */
181
- resolveApproval(localThreadId: string, approvalId: string, decision: "acceptForSession" | "accept" | "decline" | "cancel"): Promise<boolean>;
181
+ /** Resolve a pending native question/approval without opening a new Turn. */
182
+ resolveInteraction(localThreadId: string, interactionId: string, resolution: SessionInteractionResolution): Promise<ResolveInteractionResult>;
182
183
  /**
183
184
  * The command to run in a session's live terminal so it co-drives the codex
184
185
  * app-server thread (Phase D). Returns `null` when live-terminal is off, the
@@ -195,7 +196,7 @@ export declare class LocalAgentHost implements CodexCapabilities {
195
196
  } | null>;
196
197
  /**
197
198
  * Bring up (idempotently) a session's persistent codex forwarder and emit its
198
- * mirrored {@link SessionEvent}s. omnigent's codex-native single-writer model:
199
+ * mirrored {@link SessionEvent}s. reference implementation's codex-native single-writer model:
199
200
  * this forwarder is the SOLE producer of the session's canonical events — every
200
201
  * turn on the thread, web-composer-injected AND co-driving-`codex --remote`-TUI
201
202
  * initiated. Each turn gets a {@link SessionNormalizer} whose `responseId` is
@@ -211,11 +212,12 @@ export declare class LocalAgentHost implements CodexCapabilities {
211
212
  */
212
213
  ensureLiveCodexSession(localThreadId: string, emit: (event: SessionEvent) => void, opts?: LiveSessionOpts): Promise<boolean>;
213
214
  private startLiveCodexSession;
215
+ private refreshLiveCodexSession;
214
216
  /** Bind a session's codex thread id once known (TUI broadcast or store): persist
215
217
  * it, unblock injection, and kick off the resume-subscribe loop (once). */
216
218
  private onLiveThreadStarted;
217
219
  /**
218
- * Subscribe the forwarder connection to a thread (omnigent's
220
+ * Subscribe the forwarder connection to a thread (reference implementation's
219
221
  * `_subscribe_until_ready`). A fresh TUI thread has no rollout until its first
220
222
  * turn, so `thread/resume` is retried: park until the forwarder observes the
221
223
  * thread active, then retry WITHOUT `excludeTurns` so the response backfills the
@@ -227,7 +229,7 @@ export declare class LocalAgentHost implements CodexCapabilities {
227
229
  * no live session. Injection and the runner's `live.ready` gate on this. */
228
230
  waitLiveReady(localThreadId: string, timeoutMs?: number): Promise<boolean>;
229
231
  /**
230
- * Inject a user turn into a session's live codex thread — omnigent's
232
+ * Inject a user turn into a session's live codex thread — reference implementation's
231
233
  * single-writer web send. `turn/steer` when a turn is open (mid-turn
232
234
  * supplement), else `turn/start`. NEVER creates a thread (the TUI owns creation;
233
235
  * this targets the id the forwarder captured). Serialized per session so two
@@ -236,67 +238,66 @@ export declare class LocalAgentHost implements CodexCapabilities {
236
238
  * Returns an {@link InjectOutcome}: `notLive` when this session has no live
237
239
  * forwarder (caller may use the run path); `notReady`/`failed` are hard errors
238
240
  * the caller reports WITHOUT re-running (re-running double-writes alongside the
239
- * forwarder). Park-until-ready (~60s), aligning omnigent's executor waiting for
241
+ * forwarder). Park-until-ready (~60s), aligning reference implementation's executor waiting for
240
242
  * the bridge instead of a short race that falls back to a second output path.
241
243
  */
242
244
  injectMessage(localThreadId: string, text: string): Promise<InjectOutcome>;
243
245
  /**
244
246
  * Interrupt the session's active turn — the web Stop button. codex: the
245
247
  * app-server `turn/interrupt` on the active `{threadId, turnId}` (exactly what
246
- * codex's own TUI interrupt key sends — omnigent `_handle_codex_native_interrupt`).
247
- * claude: an Escape keystroke into the pane (no app-server — omnigent
248
+ * codex's own TUI interrupt key sends — reference implementation `_handle_codex_native_interrupt`).
249
+ * claude: an Escape keystroke into the pane (no app-server — reference implementation
248
250
  * `inject_interrupt`). Returns false as a no-op when there is no active turn.
249
251
  */
250
252
  interruptLive(localThreadId: string): Promise<boolean>;
251
253
  /** Stop + drop a session's live forwarder and its dedicated connection (session
252
254
  * close / runner shutdown). The backend inject client is shared — left running. */
253
- stopLiveCodexSession(localThreadId: string): void;
255
+ stopLiveCodexSession(localThreadId: string, opts?: {
256
+ deferClaudeInteractionCleanup?: boolean;
257
+ }): void;
258
+ /** Complete the second shutdown phase after the runner has killed all native
259
+ * terminals and hook subprocesses. Must run before the runner process exits. */
260
+ finalizeStoppedLiveSessions(): void;
254
261
  /** The interactive `claude` TUI spec for a claude-native live session: the real
255
262
  * `claude` binary with rynx's hooks (`--settings`), resuming the bound session.
256
263
  * Trust is pre-seeded so the daemon-spawned TUI never blocks on a first-run
257
- * prompt. (PermissionRequest approvals land in Phase 6; until then the TUI
258
- * surfaces its own permission prompt in the co-driven pane.) */
264
+ * prompt. Questions and PermissionRequest approvals use the runtime-local
265
+ * generic interaction bridge and remain inside the active Turn. */
259
266
  private claudeTerminalSpec;
260
267
  /** Bring up a claude-native live forwarder: prepare the bridge dir (the TUI's
261
268
  * hooks write into it), then tail bridge + transcript and drive a per-turn
262
269
  * {@link SessionNormalizer} → `emit` (the SAME sink shape the codex path uses). */
263
- /** Resolve an agent spec's launch config — model + the session skill env —
270
+ /** Resolve an agent spec's launch config — model, instructions, and the session skill env —
264
271
  * for a LIVE native session, reusing the same core resolvers the non-live
265
272
  * run path uses ({@link resolveAgentExecution} for the model,
266
- * {@link resolveAgent} for skills). Instructions are intentionally NOT
267
- * returned: the co-driven TUI runs on vendor defaults (see
268
- * startLiveClaudeSession).
273
+ * {@link resolveAgent} for instructions and skills).
269
274
  *
270
275
  * Skills are spec-rooted: each declared ref is replayed into a
271
276
  * SESSION-scoped temp dir (cache-accelerated); the owner's catalog plays no
272
- * role, and no spec / no `skills` means ZERO skills. The env-build report
273
- * (installs, failures, content drift) is logged a declared skill that
274
- * can't be provisioned is loudly absent, never silent; the session still
275
- * starts. `skillsCleanup` removes the session dir (call on session stop). */
277
+ * role, and no spec / no `skills` means ZERO skills. Every declared skill
278
+ * must resolve at its declared content hash; missing, failed, or drifted
279
+ * materialization aborts launch before a native session starts.
280
+ * `skillsCleanup` removes the session dir (call on session stop). */
276
281
  private resolveLiveAgentConfig;
277
282
  private startLiveClaudeSession;
278
283
  /** Persist claude's discovered session id (reusing the `codexSessionId` store
279
284
  * field, as the claude executor already does) and release the readiness gate. */
280
285
  private onClaudeDiscovered;
281
- /** Inject a web message into a claude-native pane via tmux (omnigent recipe),
286
+ /** Inject a web message into a claude-native pane via tmux (reference implementation recipe),
282
287
  * serialized per session. Parks until the thread is ready AND the tmux injector
283
288
  * is (re)attached, then pastes; `injectViaTerminal` RAISES if the prompt never
284
- * appears (omnigent RAISE), so a not-ready pane is a hard error — NOT a
289
+ * appears (reference implementation RAISE), so a not-ready pane is a hard error — NOT a
285
290
  * fall-through-to-run signal. Returns {@link InjectOutcome}. */
286
291
  private injectClaude;
287
292
  /** Park until the claude session's tmux injector is (re)attached by the
288
293
  * runner-child, or the deadline passes. Pane relaunch re-attaches it via
289
294
  * {@link attachTerminalInjector}; without this a message during that window
290
- * would fail and (pre-omnigent) fall through to a second output path. */
295
+ * would fail and (pre-reference implementation) fall through to a second output path. */
291
296
  private waitInjector;
292
297
  /** Attach a session's tmux pane injector (from the runner-child, which owns the
293
298
  * terminal registry — the host does not hold tmux). Ignored for codex sessions
294
299
  * (they inject via the app-server). Idempotent. */
295
300
  attachTerminalInjector(localThreadId: string, injector: TerminalInjector): void;
296
- /** The PermissionRequest hook's server target from the runner-child env (the
297
- * daemon control URL + token), or undefined when unset — then no permission
298
- * hook is registered and claude surfaces its own TUI prompt in the pane. */
299
- private claudePermissionConfig;
300
301
  /** List the models a runtime exposes (App Server for codex/traex; static for claude). */
301
302
  listModels(runtime?: AgentRuntimeId): Promise<ModelListResponse | null>;
302
303
  /**
@@ -320,5 +321,5 @@ export { createCodexChildEnv };
320
321
  export declare function isUnsupportedMethodError(error: unknown): boolean;
321
322
  /** A `thread/resume` failure meaning the thread has no (or an empty) rollout yet
322
323
  * — a fresh TUI thread before its first turn. Retryable (park until active).
323
- * Mirrors omnigent's `_is_thread_not_ready_error`. */
324
+ * Mirrors reference implementation's `_is_thread_not_ready_error`. */
324
325
  export declare function isThreadNotReadyError(error: unknown): boolean;