@rynx-ai/server 0.1.0 → 0.1.10-beta.2

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 (65) hide show
  1. package/dist/browser-surface-control-queue.d.ts +42 -0
  2. package/dist/browser-surface-control-queue.js +187 -0
  3. package/dist/browser-surface-ws.d.ts +16 -0
  4. package/dist/browser-surface-ws.js +356 -0
  5. package/dist/control-api.d.ts +76 -4
  6. package/dist/control-api.js +3014 -133
  7. package/dist/control-web/assets/highlighted-body-OFNGDK62-DHu2g-rk.js +1 -0
  8. package/dist/control-web/assets/index-B6Pb5j9M.js +666 -0
  9. package/dist/control-web/assets/index-BU-_Qud_.css +32 -0
  10. package/dist/control-web/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
  11. package/dist/control-web/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
  12. package/dist/control-web/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
  13. package/dist/control-web/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
  14. package/dist/control-web/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
  15. package/dist/control-web/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
  16. package/dist/control-web/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
  17. package/dist/control-web/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
  18. package/dist/control-web/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
  19. package/dist/control-web/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
  20. package/dist/control-web/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  21. package/dist/control-web/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
  22. package/dist/control-web/assets/mermaid-GHXKKRXX-CSYzOmBR.js +131 -0
  23. package/dist/control-web/assets/rynx-wordmark-LL1QRYHD.png +0 -0
  24. package/dist/control-web/favicon.png +0 -0
  25. package/dist/control-web/favicon.svg +38 -0
  26. package/dist/control-web/index.html +16 -0
  27. package/dist/control-web-dist.d.ts +1 -1
  28. package/dist/control-web-dist.js +19 -14
  29. package/dist/desktop-browser-host.d.ts +170 -0
  30. package/dist/desktop-browser-host.js +1018 -0
  31. package/dist/direct-runtime-browser-inspect-server.d.ts +72 -0
  32. package/dist/direct-runtime-browser-inspect-server.js +749 -0
  33. package/dist/direct-runtime-browser-surface-server.d.ts +74 -0
  34. package/dist/direct-runtime-browser-surface-server.js +821 -0
  35. package/dist/direct-runtime-server.d.ts +143 -0
  36. package/dist/direct-runtime-server.js +1959 -0
  37. package/dist/emulator-surface-ws.d.ts +8 -0
  38. package/dist/emulator-surface-ws.js +198 -0
  39. package/dist/machine-session-service.d.ts +265 -0
  40. package/dist/machine-session-service.js +822 -0
  41. package/dist/provider-cli-host.d.ts +10 -0
  42. package/dist/provider-cli-host.js +1 -0
  43. package/dist/remote-runtime-dispatcher.d.ts +94 -0
  44. package/dist/remote-runtime-dispatcher.js +403 -0
  45. package/dist/remote-runtime-session-projection.d.ts +19 -0
  46. package/dist/remote-runtime-session-projection.js +566 -0
  47. package/dist/remote-runtime.d.ts +22 -0
  48. package/dist/remote-runtime.js +32 -0
  49. package/dist/runtime-web-auth.d.ts +26 -0
  50. package/dist/runtime-web-auth.js +132 -0
  51. package/dist/server.d.ts +364 -12
  52. package/dist/server.js +341 -100
  53. package/dist/session-browser-service.d.ts +248 -0
  54. package/dist/session-browser-service.js +772 -0
  55. package/dist/session-browser-surface-coordinator.d.ts +24 -0
  56. package/dist/session-browser-surface-coordinator.js +669 -0
  57. package/dist/session-emulator-service.d.ts +167 -0
  58. package/dist/session-emulator-service.js +464 -0
  59. package/dist/session-runtime-index.d.ts +23 -0
  60. package/dist/session-runtime-index.js +96 -0
  61. package/dist/session-terminal-host.d.ts +51 -0
  62. package/dist/session-terminal-host.js +270 -0
  63. package/dist/terminal-ws.d.ts +12 -20
  64. package/dist/terminal-ws.js +421 -97
  65. package/package.json +14 -7
@@ -0,0 +1,8 @@
1
+ import type { Server } from "node:http";
2
+ import { WebSocketServer } from "ws";
3
+ import { type RuntimeWebAccessPolicy } from "./runtime-web-auth.js";
4
+ import type { RuntimeConnectionResolverHost } from "./server.js";
5
+ export declare function attachEmulatorSurfaceWs(server: Server, deps: {
6
+ runtimeConnectionResolver?: RuntimeConnectionResolverHost;
7
+ runtimeWebAccess?: RuntimeWebAccessPolicy;
8
+ }): WebSocketServer;
@@ -0,0 +1,198 @@
1
+ import { WebSocket, WebSocketServer } from "ws";
2
+ import { parseRuntimeEmulatorSurfaceClientFrame, RUNTIME_EMULATOR_SURFACE_MAX_FRAME_RATE, } from "@rynx-ai/protocol/runtime-emulator-surface";
3
+ import { authorizeRuntimeWebRequest, RUNTIME_WEB_CAPABILITY_QUERY, } from "./runtime-web-auth.js";
4
+ const SURFACE_PATH = /^\/api\/runtimes\/([^/]+)\/sessions\/([^/]+)\/emulator\/surface$/;
5
+ const SELECTOR_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._~-]{0,255}$/;
6
+ const MAX_ID_BYTES = 512;
7
+ const MAX_BUFFERED_BYTES = 24 * 1024 * 1024;
8
+ const OPEN_TIMEOUT_MS = 10_000;
9
+ const KEEPALIVE_MS = 15_000;
10
+ const MAX_QUEUED_INPUTS = 64;
11
+ export function attachEmulatorSurfaceWs(server, deps) {
12
+ const wss = new WebSocketServer({ noServer: true, perMessageDeflate: false, maxPayload: 4 * 1024 });
13
+ server.on("upgrade", (request, socket, head) => {
14
+ const parsed = parseUpgrade(request);
15
+ if (!parsed)
16
+ return;
17
+ if ("failure" in parsed)
18
+ return rejectUpgrade(socket, 400, parsed.failure);
19
+ const authorization = authorizeRuntimeWebRequest(request, {
20
+ mutation: true,
21
+ capability: parsed.url.searchParams.get(RUNTIME_WEB_CAPABILITY_QUERY) ?? "",
22
+ access: deps.runtimeWebAccess,
23
+ });
24
+ if (authorization)
25
+ return rejectUpgrade(socket, authorization.status, authorization.error);
26
+ try {
27
+ wss.handleUpgrade(request, socket, head, (ws) => {
28
+ void handleConnection(ws, parsed.url, parsed.route, deps);
29
+ });
30
+ }
31
+ catch {
32
+ rejectUpgrade(socket, 400, "invalid Emulator Surface WebSocket upgrade");
33
+ }
34
+ });
35
+ return wss;
36
+ }
37
+ async function handleConnection(ws, url, route, deps) {
38
+ const bindingId = url.searchParams.get("bindingId");
39
+ const maximumFrameRate = Number(url.searchParams.get("maximumFrameRate") ?? "3");
40
+ if (!validId(bindingId) ||
41
+ !Number.isSafeInteger(maximumFrameRate) ||
42
+ maximumFrameRate < 1 ||
43
+ maximumFrameRate > RUNTIME_EMULATOR_SURFACE_MAX_FRAME_RATE) {
44
+ ws.close(4400, "invalid Emulator Surface options");
45
+ return;
46
+ }
47
+ if (!deps.runtimeConnectionResolver) {
48
+ ws.close(4406, "Emulator Surface is unavailable");
49
+ return;
50
+ }
51
+ const controller = new AbortController();
52
+ let lease;
53
+ let surface;
54
+ let cleaned = false;
55
+ let cleanupPromise;
56
+ let queuedInputs = 0;
57
+ let inputTail = Promise.resolve();
58
+ const cleanup = () => {
59
+ if (cleanupPromise)
60
+ return cleanupPromise;
61
+ cleaned = true;
62
+ cleanupPromise = (async () => {
63
+ controller.abort(new Error("Emulator Surface browser disconnected"));
64
+ try {
65
+ await surface?.close();
66
+ }
67
+ finally {
68
+ lease?.release();
69
+ }
70
+ })();
71
+ return cleanupPromise;
72
+ };
73
+ const keepalive = setInterval(() => {
74
+ if (ws.readyState === WebSocket.OPEN)
75
+ ws.ping();
76
+ }, KEEPALIVE_MS);
77
+ keepalive.unref?.();
78
+ ws.on("message", (data, isBinary) => {
79
+ if (isBinary || !surface) {
80
+ ws.close(4400, "invalid Emulator Surface browser input");
81
+ void cleanup().catch(() => undefined);
82
+ return;
83
+ }
84
+ let frame;
85
+ try {
86
+ frame = parseRuntimeEmulatorSurfaceClientFrame(JSON.parse(data.toString()));
87
+ }
88
+ catch {
89
+ ws.close(4400, "invalid Emulator Surface browser input");
90
+ void cleanup().catch(() => undefined);
91
+ return;
92
+ }
93
+ if (frame.type !== "emulator.surface.touch" || frame.surfaceId !== surface.ready.surfaceId) {
94
+ ws.close(4400, "Emulator Surface browser input does not match the active Surface");
95
+ void cleanup().catch(() => undefined);
96
+ return;
97
+ }
98
+ if (queuedInputs >= MAX_QUEUED_INPUTS) {
99
+ ws.close(4408, "Emulator Surface browser input queue is full");
100
+ void cleanup().catch(() => undefined);
101
+ return;
102
+ }
103
+ queuedInputs += 1;
104
+ inputTail = inputTail
105
+ .then(async () => {
106
+ if (cleaned || !surface)
107
+ return;
108
+ await surface.sendTouch({
109
+ phase: frame.phase,
110
+ x: frame.x,
111
+ y: frame.y,
112
+ });
113
+ })
114
+ .catch(() => {
115
+ if (!cleaned)
116
+ ws.close(4500, "Emulator Surface input failed");
117
+ void cleanup().catch(() => undefined);
118
+ })
119
+ .finally(() => { queuedInputs -= 1; });
120
+ });
121
+ ws.on("close", () => void cleanup().catch(() => undefined));
122
+ ws.on("error", () => void cleanup().catch(() => undefined));
123
+ try {
124
+ lease = await deps.runtimeConnectionResolver.acquire(route.selector, { signal: controller.signal });
125
+ if (lease.target.selector !== route.selector)
126
+ throw new Error("Runtime resolver returned a mismatched target");
127
+ surface = await lease.openEmulatorSurface(route.sessionId, bindingId, {
128
+ signal: controller.signal,
129
+ timeoutMs: OPEN_TIMEOUT_MS,
130
+ maximumFrameRate,
131
+ });
132
+ if (cleaned)
133
+ return;
134
+ await send(ws, JSON.stringify(surface.ready));
135
+ for await (const frame of surface) {
136
+ if (cleaned)
137
+ return;
138
+ if (ws.bufferedAmount + frame.encodedBytes.byteLength > MAX_BUFFERED_BYTES) {
139
+ ws.close(4408, "Emulator Surface browser is too slow");
140
+ return;
141
+ }
142
+ await send(ws, frame.encodedBytes, true);
143
+ }
144
+ if (!cleaned)
145
+ ws.close(1000, "Emulator Surface ended");
146
+ }
147
+ catch (error) {
148
+ if (!cleaned && ws.readyState === WebSocket.OPEN) {
149
+ const message = error instanceof Error ? error.message : "Emulator Surface failed";
150
+ // 4406 is an actionable daemon-upgrade state. A temporarily offline
151
+ // Runtime can also report "unavailable" and must stay on the ordinary
152
+ // reconnect path instead of flashing a false upgrade error.
153
+ ws.close(message.includes("semantic capability") ? 4406 : 4500, message.slice(0, 120));
154
+ }
155
+ }
156
+ finally {
157
+ clearInterval(keepalive);
158
+ await cleanup().catch(() => undefined);
159
+ }
160
+ }
161
+ function parseUpgrade(request) {
162
+ let url;
163
+ try {
164
+ url = new URL(request.url ?? "", "http://localhost");
165
+ }
166
+ catch {
167
+ return undefined;
168
+ }
169
+ const match = SURFACE_PATH.exec(url.pathname);
170
+ if (!match)
171
+ return undefined;
172
+ try {
173
+ const selector = decodeURIComponent(match[1]);
174
+ const sessionId = decodeURIComponent(match[2]);
175
+ if (!SELECTOR_PATTERN.test(selector) || !validId(sessionId))
176
+ return { failure: "invalid Emulator Surface route" };
177
+ return { url, route: { selector, sessionId } };
178
+ }
179
+ catch {
180
+ return { failure: "invalid Emulator Surface route encoding" };
181
+ }
182
+ }
183
+ function validId(value) {
184
+ return typeof value === "string" && value.length > 0 && Buffer.byteLength(value, "utf8") <= MAX_ID_BYTES && /^[\x21-\x7e]+$/.test(value);
185
+ }
186
+ function send(ws, data, binary = false) {
187
+ return new Promise((resolve, reject) => {
188
+ if (ws.readyState !== WebSocket.OPEN)
189
+ return reject(new Error("Emulator Surface WebSocket is closed"));
190
+ ws.send(data, { binary }, (error) => error ? reject(error) : resolve());
191
+ });
192
+ }
193
+ function rejectUpgrade(socket, status, message) {
194
+ if (socket.destroyed)
195
+ return;
196
+ const label = status === 401 ? "Unauthorized" : status === 403 ? "Forbidden" : "Bad Request";
197
+ socket.end(`HTTP/1.1 ${status} ${label}\r\nConnection: close\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Length: ${Buffer.byteLength(message)}\r\n\r\n${message}`);
198
+ }
@@ -0,0 +1,265 @@
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";
12
+ 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";
16
+ export interface MachineSessionRuntimeStatePort {
17
+ snapshot(sessionId: string): ControlSessionRuntimeSnapshot;
18
+ remove?(sessionId: string): void;
19
+ }
20
+ export interface MachineSessionInterruptPort {
21
+ interrupt(sessionId: string): Promise<boolean>;
22
+ }
23
+ export interface MachineSessionAgentCatalogPort {
24
+ list(): Promise<ControlAgentSummary[]>;
25
+ }
26
+ export interface MachineSessionPendingMessage {
27
+ sessionId: string;
28
+ message: string;
29
+ createdAt: string;
30
+ state: "queued" | "outcome_unknown";
31
+ }
32
+ /** Durable one-message admission queue used while a Provider needs setup. */
33
+ export interface MachineSessionPendingMessagePort {
34
+ put(message: Omit<MachineSessionPendingMessage, "state">): boolean | Promise<boolean>;
35
+ get(sessionId: string): MachineSessionPendingMessage | undefined | Promise<MachineSessionPendingMessage | undefined>;
36
+ list(): MachineSessionPendingMessage[] | Promise<MachineSessionPendingMessage[]>;
37
+ markOutcomeUnknown(sessionId: string): void | Promise<void>;
38
+ delete(sessionId: string): void | Promise<void>;
39
+ }
40
+ export type MachineSessionMessageOperationState = "prepared" | "injecting" | "injected" | "mirrored" | "outcome_unknown" | "failed_not_started";
41
+ export interface MachineSessionPreparedInput {
42
+ input: RuntimeUserInput;
43
+ title: string;
44
+ operationState?: MachineSessionMessageOperationState;
45
+ }
46
+ /** Target-daemon resource authority. Transfer methods are deliberately chunked
47
+ * below the 64 KiB Direct Runtime frame; `prepareInput` is the only method that
48
+ * can turn opaque browser-visible ids into runtime-local file paths. */
49
+ export interface MachineSessionResourcePort {
50
+ policy(sessionId: string): RemoteRuntimeSessionResourcePolicyResult;
51
+ beginUpload(input: RemoteRuntimeSessionResourceUploadBeginParams): Promise<RemoteRuntimeSessionResourceUploadBeginResult>;
52
+ writeUploadChunk(input: RemoteRuntimeSessionResourceUploadChunkParams): Promise<RemoteRuntimeSessionResourceUploadChunkResult>;
53
+ commitUpload(input: RemoteRuntimeSessionResourceUploadCommitParams): Promise<RemoteRuntimeSessionResourceUploadCommitResult>;
54
+ getResource(input: RemoteRuntimeSessionResourceGetParams): Promise<RemoteRuntimeSessionResourceGetResult>;
55
+ readResource(input: RemoteRuntimeSessionResourceReadParams): Promise<RemoteRuntimeSessionResourceReadResult>;
56
+ deleteResource(input: RemoteRuntimeSessionResourceDeleteParams): Promise<RemoteRuntimeSessionResourceDeleteResult>;
57
+ prepareInput(sessionId: string, content: UserContentPart[], clientMessageId?: string): Promise<MachineSessionPreparedInput>;
58
+ markMessageInjecting(sessionId: string, clientMessageId: string): void | Promise<void>;
59
+ markMessageInjected(sessionId: string, clientMessageId: string): void | Promise<void>;
60
+ markMessageOutcomeUnknown(sessionId: string, clientMessageId: string, reason: string): void | Promise<void>;
61
+ markMessageFailedNotStarted(sessionId: string, clientMessageId: string, reason: string): void | Promise<void>;
62
+ deleteSession(sessionId: string): void | Promise<void>;
63
+ }
64
+ export interface MachineSessionRunnerPort {
65
+ ensureLiveSession(sessionId: string, options?: {
66
+ cwd?: string;
67
+ cols?: number;
68
+ rows?: number;
69
+ runtime?: AgentRuntimeId;
70
+ reasoningEffort?: ReasoningEffort;
71
+ agentName?: string;
72
+ agentSpec?: AgentSpec;
73
+ }): Promise<boolean>;
74
+ /** Start the Provider TUI pane without waiting for its native thread to bind. */
75
+ startLiveSession?(sessionId: string, options?: {
76
+ cwd?: string;
77
+ cols?: number;
78
+ rows?: number;
79
+ runtime?: AgentRuntimeId;
80
+ reasoningEffort?: ReasoningEffort;
81
+ agentName?: string;
82
+ agentSpec?: AgentSpec;
83
+ }): Promise<boolean>;
84
+ lastLiveSessionError?(sessionId: string): string | undefined;
85
+ injectMessage(sessionId: string, input: RuntimeUserInput | string): Promise<InjectOutcome>;
86
+ stopRunner(sessionId: string): void;
87
+ resolveInteraction(sessionId: string, interactionId: string, resolution: SessionInteractionResolution): Promise<{
88
+ disposition: ControlSessionInteractionResolveDisposition;
89
+ }>;
90
+ /** Backend-free readiness probe for launch options and direct Provider creation. */
91
+ getStatus?(options: {
92
+ runtime: AgentRuntimeId;
93
+ }): Promise<CodexRuntimeStatus>;
94
+ }
95
+ export interface MachineSessionServicePorts {
96
+ registry: Pick<SessionRegistry, "create" | "get" | "list" | "setTitle" | "remove">;
97
+ log: Pick<SessionLogStore, "list" | "listSessions" | "snapshot" | "deleteSession">;
98
+ events: Pick<SessionBus, "subscribe"> & Partial<Pick<SessionBus, "close">>;
99
+ runtimeState: MachineSessionRuntimeStatePort;
100
+ interruption: MachineSessionInterruptPort;
101
+ /** External Session-owned resources fenced before and finalized after deletion. */
102
+ lifecycle?: {
103
+ beforeDelete?(sessionId: string): void | Promise<void>;
104
+ afterDelete?(sessionId: string): void | Promise<void>;
105
+ };
106
+ /** Target-daemon catalog. Exposed only as bounded Session creation options. */
107
+ agents?: MachineSessionAgentCatalogPort;
108
+ /** Durable first messages that must not reach a Provider setup prompt. */
109
+ pendingMessages?: MachineSessionPendingMessagePort;
110
+ resources?: MachineSessionResourcePort;
111
+ /** Native Session execution belongs to the target daemon, never the caller. */
112
+ execution?: {
113
+ runtime: Pick<ConversationRuntime, "resolveRuntime">;
114
+ runner: MachineSessionRunnerPort;
115
+ sessionStore?: Pick<CodexSessionStore, "get">;
116
+ };
117
+ }
118
+ export interface MachineSessionServiceOptions {
119
+ /** Maximum summaries returned in one list page. */
120
+ maxListLimit?: number;
121
+ /** JSON byte budget for one complete list page. */
122
+ listPageMaxBytes?: number;
123
+ /** Maximum items returned in one transcript page. */
124
+ maxSnapshotItemLimit?: number;
125
+ /** JSON byte budget for one complete transcript page. */
126
+ snapshotPageMaxBytes?: number;
127
+ /** Bound for the current registry/log merge until storage offers keyset paging. */
128
+ directoryScanLimit?: number;
129
+ /** Delay between setup-readiness retries for durable pending messages. */
130
+ pendingMessageRetryMs?: number;
131
+ }
132
+ export type MachineSessionListInput = RemoteRuntimeSessionListParams;
133
+ export interface MachineSessionListPage extends RemoteRuntimeSessionListResult {
134
+ /** True when the storage-side directory exceeded the bounded merge window. */
135
+ directoryTruncated: boolean;
136
+ }
137
+ export type MachineSessionSnapshotInput = RemoteRuntimeSessionSnapshotParams;
138
+ export interface MachineSessionSnapshotPage {
139
+ sessionId: string;
140
+ /** Canonical daemon-owned items; the Direct adapter projects payloads later. */
141
+ items: SessionItem[];
142
+ runtime: ControlSessionRuntimeSnapshot;
143
+ hasMore: boolean;
144
+ nextAfterId?: string;
145
+ }
146
+ export type MachineSessionInterruptResult = RemoteRuntimeSessionInterruptResult;
147
+ interface MachineSessionCreateOptions {
148
+ model?: string;
149
+ reasoningEffort?: ReasoningEffort;
150
+ title?: string;
151
+ }
152
+ export type MachineSessionCreateInput = MachineSessionCreateOptions & ({
153
+ agent: string;
154
+ provider?: never;
155
+ } | {
156
+ provider: SessionProviderId;
157
+ agent?: never;
158
+ });
159
+ export interface MachineSessionCreateResult {
160
+ sessionId: string;
161
+ }
162
+ export interface MachineSessionMessageResult {
163
+ ok: true;
164
+ injected: true;
165
+ }
166
+ export interface MachineSessionMessageInput {
167
+ message?: string;
168
+ content?: UserContentPart[];
169
+ clientMessageId?: string;
170
+ }
171
+ export interface MachineSessionMessageEnqueueResult {
172
+ ok: true;
173
+ queued: true;
174
+ }
175
+ export interface MachineSessionTerminalStartResult {
176
+ ok: true;
177
+ }
178
+ export interface MachineSessionDeleteResult {
179
+ ok: true;
180
+ }
181
+ export interface MachineSessionInteractionResult {
182
+ disposition: ControlSessionInteractionResolveDisposition;
183
+ }
184
+ /**
185
+ * A process-live event tail. `cancel` is idempotent and settles a pending
186
+ * consumer read even when the underlying bus iterator does not settle its own
187
+ * pending `next()` on `return()`.
188
+ */
189
+ export interface MachineSessionWatch extends AsyncIterable<SequencedSessionEvent> {
190
+ readonly sessionId: string;
191
+ cancel(): Promise<void>;
192
+ }
193
+ export declare class MachineSessionServiceInputError extends Error {
194
+ constructor(message: string);
195
+ }
196
+ export type MachineSessionServiceFailureCode = "not_found" | "failed_precondition" | "conflict" | "outcome_unknown";
197
+ /** Expected application failure; adapters decide how to represent it on the wire. */
198
+ export declare class MachineSessionServiceFailure extends Error {
199
+ readonly code: MachineSessionServiceFailureCode;
200
+ readonly detail?: string | undefined;
201
+ constructor(code: MachineSessionServiceFailureCode, message: string, detail?: string | undefined);
202
+ }
203
+ /** Application boundary shared by an in-process Local adapter and Direct RPC. */
204
+ export declare class MachineSessionService {
205
+ private readonly ports;
206
+ private readonly maxListLimit;
207
+ private readonly listPageMaxBytes;
208
+ private readonly maxSnapshotItemLimit;
209
+ private readonly snapshotPageMaxBytes;
210
+ private readonly directoryScanLimit;
211
+ private readonly pendingMessageRetryMs;
212
+ private readonly pendingDeliveries;
213
+ private readonly cancelledPendingDeliveries;
214
+ constructor(ports: MachineSessionServicePorts, options?: MachineSessionServiceOptions);
215
+ list(input?: MachineSessionListInput): Promise<MachineSessionListPage>;
216
+ snapshot(input: MachineSessionSnapshotInput): Promise<MachineSessionSnapshotPage>;
217
+ /**
218
+ * Install a live subscriber synchronously, before returning control to an
219
+ * adapter. The adapter may now acknowledge readiness and request snapshot
220
+ * pages while buffering this tail, closing the subscribe/snapshot race.
221
+ */
222
+ watch(sessionIdInput: string, options?: {
223
+ signal?: AbortSignal;
224
+ }): MachineSessionWatch;
225
+ interrupt(sessionIdInput: string): Promise<MachineSessionInterruptResult>;
226
+ /** Session-scoped projection of the target daemon's own Agent catalog. */
227
+ agentOptions(): Promise<{
228
+ agents: ControlAgentSummary[];
229
+ }>;
230
+ /** Target-owned Provider readiness plus the existing Agent preset catalog. */
231
+ launchOptions(): Promise<RemoteRuntimeSessionLaunchOptionsListResult>;
232
+ /** Create target-owned Session identity from one Agent preset or direct Provider. */
233
+ create(input: MachineSessionCreateInput): Promise<MachineSessionCreateResult>;
234
+ /** Inject one turn through the target daemon's native single-writer runner. */
235
+ sendMessage(sessionIdInput: string, messageInput: string | MachineSessionMessageInput): Promise<MachineSessionMessageResult>;
236
+ resourcePolicy(sessionIdInput: string): RemoteRuntimeSessionResourcePolicyResult;
237
+ beginResourceUpload(input: RemoteRuntimeSessionResourceUploadBeginParams): Promise<RemoteRuntimeSessionResourceUploadBeginResult>;
238
+ writeResourceUploadChunk(input: RemoteRuntimeSessionResourceUploadChunkParams): Promise<RemoteRuntimeSessionResourceUploadChunkResult>;
239
+ commitResourceUpload(input: RemoteRuntimeSessionResourceUploadCommitParams): Promise<RemoteRuntimeSessionResourceUploadCommitResult>;
240
+ getResource(input: RemoteRuntimeSessionResourceGetParams): Promise<RemoteRuntimeSessionResourceGetResult>;
241
+ readResource(input: RemoteRuntimeSessionResourceReadParams): Promise<RemoteRuntimeSessionResourceReadResult>;
242
+ deleteResource(input: RemoteRuntimeSessionResourceDeleteParams): Promise<RemoteRuntimeSessionResourceDeleteResult>;
243
+ /** Persist the first task while login/onboarding owns the Provider TUI. The
244
+ * delivery worker starts the pane now, waits for a real native thread, then
245
+ * injects exactly once. `failed` is fenced as outcome_unknown and never retried. */
246
+ enqueueMessage(sessionIdInput: string, messageInput: string): Promise<MachineSessionMessageEnqueueResult>;
247
+ /** Explicitly restore the target daemon's live runner without starting a turn. */
248
+ startTerminal(sessionIdInput: string): Promise<MachineSessionTerminalStartResult>;
249
+ private ensureLiveSession;
250
+ private liveSessionRequest;
251
+ resolveInteraction(sessionIdInput: string, interactionIdInput: string, resolution: SessionInteractionResolution): Promise<MachineSessionInteractionResult>;
252
+ delete(sessionIdInput: string): Promise<MachineSessionDeleteResult>;
253
+ private requireAgents;
254
+ private requireResources;
255
+ private requireResourceSession;
256
+ private resumePendingDeliveries;
257
+ private schedulePendingDelivery;
258
+ private deliverPendingMessage;
259
+ private runtimeReadiness;
260
+ private probeRuntimeReadiness;
261
+ private requireExecution;
262
+ }
263
+ /** One-line title derived from the first user message; no model call. */
264
+ export declare function synthesizeSessionTitle(message: string, limit?: number): string;
265
+ export {};