@rynx-ai/server 0.1.10 → 0.1.11-beta.10

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 (30) hide show
  1. package/dist/control-api.d.ts +17 -52
  2. package/dist/control-api.js +755 -341
  3. package/dist/control-web/assets/{highlighted-body-OFNGDK62-DgFZpTNw.js → highlighted-body-OFNGDK62-IdclXfSt.js} +1 -1
  4. package/dist/control-web/assets/index-5n6D-i-c.css +32 -0
  5. package/dist/control-web/assets/index-DhsO7WjD.js +709 -0
  6. package/dist/control-web/assets/{mermaid-GHXKKRXX-BDikE3W1.js → mermaid-GHXKKRXX-BqMPrbIZ.js} +3 -3
  7. package/dist/control-web/index.html +2 -2
  8. package/dist/control-web-dist.d.ts +1 -1
  9. package/dist/control-web-dist.js +4 -2
  10. package/dist/machine-session-service.d.ts +135 -27
  11. package/dist/machine-session-service.js +410 -58
  12. package/dist/remote-runtime-dispatcher.d.ts +12 -2
  13. package/dist/remote-runtime-dispatcher.js +56 -0
  14. package/dist/remote-runtime-session-projection.js +1 -0
  15. package/dist/server.d.ts +59 -29
  16. package/dist/server.js +158 -143
  17. package/dist/session-browser-service.d.ts +8 -0
  18. package/dist/session-browser-service.js +37 -20
  19. package/dist/session-portal.d.ts +42 -0
  20. package/dist/session-portal.js +746 -0
  21. package/dist/session-runtime-index.d.ts +7 -0
  22. package/dist/session-runtime-index.js +42 -6
  23. package/dist/session-terminal-host.d.ts +6 -0
  24. package/dist/session-terminal-host.js +56 -41
  25. package/dist/terminal-ws.js +8 -6
  26. package/package.json +7 -7
  27. package/dist/channel-manager.d.ts +0 -60
  28. package/dist/channel-manager.js +0 -106
  29. package/dist/control-web/assets/index-CnVtOmLv.css +0 -32
  30. package/dist/control-web/assets/index-Dlywgy58.js +0 -661
@@ -7,8 +7,8 @@
7
7
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
8
8
  <link rel="icon" type="image/png" href="/favicon.png" />
9
9
  <title>rynx · control</title>
10
- <script type="module" crossorigin src="/assets/index-Dlywgy58.js"></script>
11
- <link rel="stylesheet" crossorigin href="/assets/index-CnVtOmLv.css">
10
+ <script type="module" crossorigin src="/assets/index-DhsO7WjD.js"></script>
11
+ <link rel="stylesheet" crossorigin href="/assets/index-5n6D-i-c.css">
12
12
  </head>
13
13
  <body>
14
14
  <div id="root"></div>
@@ -3,4 +3,4 @@ import type { Context } from "koa";
3
3
  export declare function resolveControlWebDist(): string | null;
4
4
  /** Serve a static file from the SPA dir; missing non-asset paths fall back to
5
5
  * index.html (client-side routing), missing assets return 404. */
6
- export declare function sendSpaFile(ctx: Context, distDir: string, basePath?: string): Promise<void>;
6
+ export declare function sendSpaFile(ctx: Context, distDir: string, basePath?: string, transformIndex?: (html: string) => string): Promise<void>;
@@ -37,7 +37,7 @@ export function resolveControlWebDist() {
37
37
  }
38
38
  /** Serve a static file from the SPA dir; missing non-asset paths fall back to
39
39
  * index.html (client-side routing), missing assets return 404. */
40
- export async function sendSpaFile(ctx, distDir, basePath = "/") {
40
+ export async function sendSpaFile(ctx, distDir, basePath = "/", transformIndex) {
41
41
  const path = basePath !== "/" && ctx.path.startsWith(basePath)
42
42
  ? ctx.path.slice(basePath.length) || "/"
43
43
  : ctx.path;
@@ -64,5 +64,7 @@ export async function sendSpaFile(ctx, distDir, basePath = "/") {
64
64
  }
65
65
  }
66
66
  ctx.type = CONTENT_TYPES[ext] ?? "application/octet-stream";
67
- ctx.body = data;
67
+ ctx.body = ext === ".html" && transformIndex
68
+ ? transformIndex(data.toString("utf8"))
69
+ : data;
68
70
  }
@@ -1,20 +1,12 @@
1
- /**
2
- * Daemon-owned application service for the first Remote Runtime Session slice.
3
- *
4
- * This service deliberately has no HTTP, Koa, WebSocket, or Direct-binding
5
- * knowledge. Durable records, live state, events, and interruption remain owned
6
- * by the daemon process and arrive through narrow injected ports. Local and
7
- * Direct adapters can therefore expose the same behavior without copying state
8
- * into a Control Plane database.
9
- */
10
- import { type AgentRuntimeId, type AgentSpec, type ConversationRuntime, type SessionProviderId, type ReasoningEffort, type RuntimeUserInput, type SessionBus, type SessionLogStore, type SessionRegistry } from "@rynx-ai/core";
11
- import type { SequencedSessionEvent, SessionInteractionResolution, SessionItem, UserContentPart } from "@rynx-ai/protocol";
1
+ import { type AdmissionReservation, type AgentRuntimeId, type ConversationRuntime, type ResolvedExecutionSnapshot, type SessionWorkspaceSnapshot, type SessionProviderId, type MachineSessionRecord, type ReasoningEffort, type RuntimeUserInput, type SessionBus, type SessionLogStore, type SessionRegistry } from "@rynx-ai/core";
2
+ import type { SequencedSessionEvent, SessionEvent, SessionInteractionResolution, SessionItem, UserContentPart } from "@rynx-ai/protocol";
12
3
  import type { RemoteRuntimeSessionResourceDeleteParams, RemoteRuntimeSessionResourceDeleteResult, RemoteRuntimeSessionResourceGetParams, RemoteRuntimeSessionResourceGetResult, RemoteRuntimeSessionResourcePolicyResult, RemoteRuntimeSessionResourceReadParams, RemoteRuntimeSessionResourceReadResult, RemoteRuntimeSessionResourceUploadBeginParams, RemoteRuntimeSessionResourceUploadBeginResult, RemoteRuntimeSessionResourceUploadChunkParams, RemoteRuntimeSessionResourceUploadChunkResult, RemoteRuntimeSessionResourceUploadCommitParams, RemoteRuntimeSessionResourceUploadCommitResult } from "@rynx-ai/protocol/remote-runtime-rpc";
13
- import type { ControlAgentSummary, ControlSessionInteractionResolveDisposition, ControlSessionRuntimeSnapshot } from "@rynx-ai/protocol/control";
14
- import { type RemoteRuntimeSessionInterruptResult, type RemoteRuntimeSessionLaunchOptionsListResult, type RemoteRuntimeSessionListParams, type RemoteRuntimeSessionListResult, type RemoteRuntimeSessionSnapshotParams } from "@rynx-ai/protocol/remote-runtime-rpc";
15
- import { type CodexRuntimeStatus, type CodexSessionStore, type InjectOutcome } from "@rynx-ai/runtime";
4
+ import type { ControlAgentModelOption, ControlAgentSummary, ControlSessionInteractionResolveDisposition, ControlSessionRuntimeSnapshot, SessionPermissionPreset } from "@rynx-ai/protocol/control";
5
+ import { type RemoteRuntimeSessionInterruptResult, type RemoteRuntimeSessionExecutionGetResult, type RemoteRuntimeSessionExecutionUpdateParams, type RemoteRuntimeSessionExecutionUpdateResult, type RemoteRuntimeSessionLaunchOptionsListResult, type RemoteRuntimeSessionListParams, type RemoteRuntimeSessionListResult, type RemoteRuntimeSessionSnapshotParams } from "@rynx-ai/protocol/remote-runtime-rpc";
6
+ import type { CodexRuntimeStatus, InjectOutcome } from "@rynx-ai/runtime";
16
7
  export interface MachineSessionRuntimeStatePort {
17
8
  snapshot(sessionId: string): ControlSessionRuntimeSnapshot;
9
+ beginResponseHandoff?(sessionId: string, responseId: string): () => void;
18
10
  remove?(sessionId: string): void;
19
11
  }
20
12
  export interface MachineSessionInterruptPort {
@@ -63,23 +55,17 @@ export interface MachineSessionResourcePort {
63
55
  }
64
56
  export interface MachineSessionRunnerPort {
65
57
  ensureLiveSession(sessionId: string, options?: {
66
- cwd?: string;
67
58
  cols?: number;
68
59
  rows?: number;
69
- runtime?: AgentRuntimeId;
70
- reasoningEffort?: ReasoningEffort;
71
- agentName?: string;
72
- agentSpec?: AgentSpec;
60
+ workspace?: SessionWorkspaceSnapshot;
61
+ execution?: ResolvedExecutionSnapshot;
73
62
  }): Promise<boolean>;
74
63
  /** Start the Provider TUI pane without waiting for its native thread to bind. */
75
64
  startLiveSession?(sessionId: string, options?: {
76
- cwd?: string;
77
65
  cols?: number;
78
66
  rows?: number;
79
- runtime?: AgentRuntimeId;
80
- reasoningEffort?: ReasoningEffort;
81
- agentName?: string;
82
- agentSpec?: AgentSpec;
67
+ workspace?: SessionWorkspaceSnapshot;
68
+ execution?: ResolvedExecutionSnapshot;
83
69
  }): Promise<boolean>;
84
70
  lastLiveSessionError?(sessionId: string): string | undefined;
85
71
  injectMessage(sessionId: string, input: RuntimeUserInput | string): Promise<InjectOutcome>;
@@ -87,15 +73,69 @@ export interface MachineSessionRunnerPort {
87
73
  resolveInteraction(sessionId: string, interactionId: string, resolution: SessionInteractionResolution): Promise<{
88
74
  disposition: ControlSessionInteractionResolveDisposition;
89
75
  }>;
76
+ /** Internal Provider fork. RunnerManager fences both source and target before
77
+ * invoking `beforeProviderFork`, then commits the native Provider context. */
78
+ forkSession?(sourceSessionId: string, targetSessionId: string, options: {
79
+ workspace: SessionWorkspaceSnapshot;
80
+ execution: ResolvedExecutionSnapshot;
81
+ beforeProviderFork: () => Promise<void>;
82
+ }): Promise<{
83
+ ok: true;
84
+ } | {
85
+ ok: false;
86
+ message: string;
87
+ }>;
90
88
  /** Backend-free readiness probe for launch options and direct Provider creation. */
91
89
  getStatus?(options: {
92
90
  runtime: AgentRuntimeId;
93
91
  }): Promise<CodexRuntimeStatus>;
94
92
  }
93
+ export type MachineSessionForkOperationState = "reserved" | "completed" | "target_deleted";
94
+ export interface MachineSessionForkOperationRecord {
95
+ operationId: string;
96
+ requestHash: string;
97
+ sourceSessionId: string;
98
+ targetSessionId: string;
99
+ title?: string;
100
+ forkPosition?: number;
101
+ state: MachineSessionForkOperationState;
102
+ error?: string;
103
+ }
104
+ /** Durable idempotency + atomic Session/history/resource publication boundary.
105
+ * The daemon implementation owns SQLite and resource files; the application
106
+ * service never exposes a target before this port commits it. */
107
+ export interface MachineSessionForkStorePort {
108
+ claim(input: {
109
+ operationId: string;
110
+ requestHash: string;
111
+ sourceSessionId: string;
112
+ title?: string;
113
+ }): MachineSessionForkOperationRecord | Promise<MachineSessionForkOperationRecord>;
114
+ commit(input: {
115
+ operationId: string;
116
+ target: MachineSessionRecord;
117
+ items: SessionItem[];
118
+ }): void | Promise<void>;
119
+ /** Publish a fork already performed inside a live Provider TUI. Unlike
120
+ * `commit`, this has no caller-supplied idempotency operation because the
121
+ * Provider-created target Session id is itself the durable identity. */
122
+ publishNativeFork(input: {
123
+ sourceSessionId: string;
124
+ target: MachineSessionRecord;
125
+ items: SessionItem[];
126
+ }): void | Promise<void>;
127
+ markError(operationId: string, error: string): void | Promise<void>;
128
+ listReserved(): MachineSessionForkOperationRecord[] | Promise<MachineSessionForkOperationRecord[]>;
129
+ hasReservedSource(sessionId: string): boolean | Promise<boolean>;
130
+ markTargetDeleted(sessionId: string): void | Promise<void>;
131
+ }
95
132
  export interface MachineSessionServicePorts {
96
- registry: Pick<SessionRegistry, "create" | "get" | "list" | "setTitle" | "remove">;
133
+ registry: Pick<SessionRegistry, "create" | "get" | "list" | "setTitle" | "setExecution" | "remove">;
97
134
  log: Pick<SessionLogStore, "list" | "listSessions" | "snapshot" | "deleteSession">;
98
135
  events: Pick<SessionBus, "subscribe"> & Partial<Pick<SessionBus, "close">>;
136
+ /** Canonical persistence + fan-out for user turns accepted before a native
137
+ * Terminal has finished starting. */
138
+ publishEvent?: (sessionId: string, event: SessionEvent) => void | Promise<void>;
99
139
  runtimeState: MachineSessionRuntimeStatePort;
100
140
  interruption: MachineSessionInterruptPort;
101
141
  /** External Session-owned resources fenced before and finalized after deletion. */
@@ -111,9 +151,25 @@ export interface MachineSessionServicePorts {
111
151
  /** Native Session execution belongs to the target daemon, never the caller. */
112
152
  execution?: {
113
153
  runtime: Pick<ConversationRuntime, "resolveRuntime">;
154
+ resolve(input: {
155
+ agent?: string;
156
+ provider?: SessionProviderId;
157
+ model?: string | null;
158
+ reasoningEffort?: ReasoningEffort;
159
+ permissionPreset?: SessionPermissionPreset;
160
+ cwd: string;
161
+ }): Promise<ResolvedExecutionSnapshot>;
162
+ listModels?(provider: SessionProviderId): Promise<ControlAgentModelOption[]>;
114
163
  runner: MachineSessionRunnerPort;
115
- sessionStore?: Pick<CodexSessionStore, "get">;
116
164
  };
165
+ /** Resolve a temporary Project selection, or create a Session-only fallback directory. */
166
+ workspace?: {
167
+ resolve(projectId?: string): Promise<SessionWorkspaceSnapshot>;
168
+ /** Remove an unbound Session-only allocation after creation fails. Project
169
+ * directories are never passed to this hook. */
170
+ discardUnbound?(workspace: SessionWorkspaceSnapshot): Promise<void>;
171
+ };
172
+ forks?: MachineSessionForkStorePort;
117
173
  }
118
174
  export interface MachineSessionServiceOptions {
119
175
  /** Maximum summaries returned in one list page. */
@@ -128,6 +184,11 @@ export interface MachineSessionServiceOptions {
128
184
  directoryScanLimit?: number;
129
185
  /** Delay between setup-readiness retries for durable pending messages. */
130
186
  pendingMessageRetryMs?: number;
187
+ /** Dynamic daemon-wide admission fence used during process replacement. */
188
+ admissionOpen?: () => boolean;
189
+ /** Atomically reserves one work-producing admission until it is rejected or
190
+ * has become visible in the daemon activity projection. */
191
+ admissionReserve?: () => AdmissionReservation | undefined;
131
192
  }
132
193
  export type MachineSessionListInput = RemoteRuntimeSessionListParams;
133
194
  export interface MachineSessionListPage extends RemoteRuntimeSessionListResult {
@@ -145,9 +206,11 @@ export interface MachineSessionSnapshotPage {
145
206
  }
146
207
  export type MachineSessionInterruptResult = RemoteRuntimeSessionInterruptResult;
147
208
  interface MachineSessionCreateOptions {
148
- model?: string;
209
+ model?: string | null;
149
210
  reasoningEffort?: ReasoningEffort;
211
+ permissionPreset?: SessionPermissionPreset;
150
212
  title?: string;
213
+ projectId?: string;
151
214
  }
152
215
  export type MachineSessionCreateInput = MachineSessionCreateOptions & ({
153
216
  agent: string;
@@ -159,6 +222,20 @@ export type MachineSessionCreateInput = MachineSessionCreateOptions & ({
159
222
  export interface MachineSessionCreateResult {
160
223
  sessionId: string;
161
224
  }
225
+ export interface MachineSessionForkInput {
226
+ sourceSessionId: string;
227
+ operationId: string;
228
+ title?: string;
229
+ }
230
+ export interface MachineSessionForkResult {
231
+ sessionId: string;
232
+ disposition: "created" | "replayed";
233
+ }
234
+ export interface MachineSessionNativeRotationInput {
235
+ sourceSessionId: string;
236
+ targetSessionId: string;
237
+ kind: "clear" | "fork";
238
+ }
162
239
  export interface MachineSessionMessageResult {
163
240
  ok: true;
164
241
  injected: true;
@@ -209,8 +286,11 @@ export declare class MachineSessionService {
209
286
  private readonly snapshotPageMaxBytes;
210
287
  private readonly directoryScanLimit;
211
288
  private readonly pendingMessageRetryMs;
289
+ private readonly admissionOpen;
290
+ private readonly admissionReserve;
212
291
  private readonly pendingDeliveries;
213
292
  private readonly cancelledPendingDeliveries;
293
+ private readonly forkTasks;
214
294
  constructor(ports: MachineSessionServicePorts, options?: MachineSessionServiceOptions);
215
295
  list(input?: MachineSessionListInput): Promise<MachineSessionListPage>;
216
296
  snapshot(input: MachineSessionSnapshotInput): Promise<MachineSessionSnapshotPage>;
@@ -229,10 +309,30 @@ export declare class MachineSessionService {
229
309
  }>;
230
310
  /** Target-owned Provider readiness plus the existing Agent preset catalog. */
231
311
  launchOptions(): Promise<RemoteRuntimeSessionLaunchOptionsListResult>;
312
+ /** Read the effective model defaults used for the next turn. */
313
+ executionSettings(sessionIdInput: string): Promise<RemoteRuntimeSessionExecutionGetResult>;
314
+ /** Replace the Turn defaults of an idle Session. Execution settings are
315
+ * passed through to the Provider CLI, which owns availability validation.
316
+ * The runner is closed so every Provider resumes its native context with
317
+ * the new settings on the next turn. */
318
+ updateExecutionSettings(input: RemoteRuntimeSessionExecutionUpdateParams): Promise<RemoteRuntimeSessionExecutionUpdateResult>;
232
319
  /** Create target-owned Session identity from one Agent preset or direct Provider. */
233
320
  create(input: MachineSessionCreateInput): Promise<MachineSessionCreateResult>;
321
+ private createAdmitted;
322
+ /** Create one independent Session at the source's stable Provider/canonical
323
+ * boundary. Project and Agent selectors are intentionally absent: the target
324
+ * receives exact copies of the source's already-frozen snapshots. */
325
+ fork(input: MachineSessionForkInput): Promise<MachineSessionForkResult>;
326
+ private forkAdmitted;
327
+ /** Publish a Provider TUI `/clear` or `/fork` after its native binding has
328
+ * already been persisted. The source snapshots remain the only workspace and
329
+ * execution authority; Provider events cannot alter them during rotation. */
330
+ recordNativeRotation(input: MachineSessionNativeRotationInput): Promise<void>;
331
+ private performFork;
332
+ private assertForkableSource;
234
333
  /** Inject one turn through the target daemon's native single-writer runner. */
235
334
  sendMessage(sessionIdInput: string, messageInput: string | MachineSessionMessageInput): Promise<MachineSessionMessageResult>;
335
+ private sendMessageAdmitted;
236
336
  resourcePolicy(sessionIdInput: string): RemoteRuntimeSessionResourcePolicyResult;
237
337
  beginResourceUpload(input: RemoteRuntimeSessionResourceUploadBeginParams): Promise<RemoteRuntimeSessionResourceUploadBeginResult>;
238
338
  writeResourceUploadChunk(input: RemoteRuntimeSessionResourceUploadChunkParams): Promise<RemoteRuntimeSessionResourceUploadChunkResult>;
@@ -244,13 +344,17 @@ export declare class MachineSessionService {
244
344
  * delivery worker starts the pane now, waits for a real native thread, then
245
345
  * injects exactly once. `failed` is fenced as outcome_unknown and never retried. */
246
346
  enqueueMessage(sessionIdInput: string, messageInput: string): Promise<MachineSessionMessageEnqueueResult>;
347
+ private enqueueMessageAdmitted;
247
348
  /** Explicitly restore the target daemon's live runner without starting a turn. */
248
349
  startTerminal(sessionIdInput: string): Promise<MachineSessionTerminalStartResult>;
350
+ private startTerminalAdmitted;
249
351
  private ensureLiveSession;
250
352
  private liveSessionRequest;
251
353
  resolveInteraction(sessionIdInput: string, interactionIdInput: string, resolution: SessionInteractionResolution): Promise<MachineSessionInteractionResult>;
252
354
  delete(sessionIdInput: string): Promise<MachineSessionDeleteResult>;
253
355
  private requireAgents;
356
+ private reserveAdmission;
357
+ private withAdmission;
254
358
  private requireResources;
255
359
  private requireResourceSession;
256
360
  private resumePendingDeliveries;
@@ -259,6 +363,10 @@ export declare class MachineSessionService {
259
363
  private runtimeReadiness;
260
364
  private probeRuntimeReadiness;
261
365
  private requireExecution;
366
+ private requireWorkspace;
367
+ private requireForks;
368
+ private assertNotForkReserved;
369
+ private resumeReservedForks;
262
370
  }
263
371
  /** One-line title derived from the first user message; no model call. */
264
372
  export declare function synthesizeSessionTitle(message: string, limit?: number): string;