@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,132 @@
1
+ import { randomBytes, timingSafeEqual } from "node:crypto";
2
+ import { isIP } from "node:net";
3
+ export const RUNTIME_WEB_CAPABILITY_HEADER = "x-rynx-runtime-capability";
4
+ export const RUNTIME_WEB_CAPABILITY_QUERY = "capability";
5
+ /**
6
+ * Process-lifetime CSRF capability shared by the Runtime HTTP BFF and its
7
+ * browser WebSocket upgrades. It is not a daemon-management credential.
8
+ */
9
+ export const RUNTIME_WEB_CAPABILITY = randomBytes(32).toString("base64url");
10
+ export function runtimeWebAccessPolicyForBindHost(bindHost) {
11
+ const normalized = normalizeAddress(bindHost.trim().replace(/^\[|\]$/g, ""))?.toLowerCase();
12
+ return {
13
+ mode: normalized === "127.0.0.1" || normalized === "::1" || normalized === "localhost"
14
+ ? "loopback"
15
+ : "host",
16
+ };
17
+ }
18
+ /**
19
+ * Authorize a browser request before any Runtime lease or terminal is opened.
20
+ * Socket address and the original Host header are both checked to resist DNS
21
+ * rebinding; mutation metadata and the capability provide the CSRF fence.
22
+ */
23
+ export function authorizeRuntimeWebRequest(request, options = {}) {
24
+ const access = options.access ?? { mode: "loopback" };
25
+ if (access.mode === "loopback" && !isLoopbackAddress(request.socket.remoteAddress)) {
26
+ return { status: 403, error: "loopback_only" };
27
+ }
28
+ const host = originalHostHeader(request);
29
+ if (!host || !isAllowedHostAuthority(request, host, access)) {
30
+ return { status: 403, error: "invalid_host" };
31
+ }
32
+ if (!options.mutation)
33
+ return undefined;
34
+ if (!isSameOriginBrowserMutation(request, host)) {
35
+ return { status: 403, error: "cross_origin" };
36
+ }
37
+ if (!safeTokenEquals(options.capability ?? "", RUNTIME_WEB_CAPABILITY)) {
38
+ return { status: 401, error: "invalid_runtime_capability" };
39
+ }
40
+ return undefined;
41
+ }
42
+ function isLoopbackAddress(value) {
43
+ const normalized = normalizeAddress(value);
44
+ return normalized === "127.0.0.1" || normalized === "::1";
45
+ }
46
+ function normalizeAddress(value) {
47
+ return value?.startsWith("::ffff:") ? value.slice("::ffff:".length) : value;
48
+ }
49
+ /** Read the HTTP/1 Host header exactly as received; duplicate Hosts fail closed. */
50
+ function originalHostHeader(request) {
51
+ let host;
52
+ const raw = request.rawHeaders;
53
+ for (let index = 0; index < raw.length; index += 2) {
54
+ if (raw[index]?.toLowerCase() !== "host")
55
+ continue;
56
+ if (host !== undefined)
57
+ return undefined;
58
+ host = raw[index + 1];
59
+ }
60
+ return host;
61
+ }
62
+ function isAllowedHostAuthority(request, host, access) {
63
+ if (isLoopbackHostAuthority(host)) {
64
+ return isLoopbackAddress(request.socket.remoteAddress);
65
+ }
66
+ if (access.mode !== "host")
67
+ return false;
68
+ const hostAddress = ipHostAuthorityAddress(host);
69
+ const localAddress = normalizeAddress(request.socket.localAddress);
70
+ return hostAddress !== undefined && localAddress !== undefined &&
71
+ hostAddress.toLowerCase() === localAddress.toLowerCase();
72
+ }
73
+ function isLoopbackHostAuthority(value) {
74
+ if (value.length === 0 || value !== value.trim())
75
+ return false;
76
+ const match = /^(?:localhost|127\.0\.0\.1|\[::1\])(?::(\d{1,5}))?$/i.exec(value);
77
+ if (!match)
78
+ return false;
79
+ if (match[1] === undefined)
80
+ return true;
81
+ const port = Number(match[1]);
82
+ return Number.isInteger(port) && port >= 1 && port <= 65_535;
83
+ }
84
+ function ipHostAuthorityAddress(value) {
85
+ if (value.length === 0 || value !== value.trim())
86
+ return undefined;
87
+ const match = /^(?:([0-9.]+)|\[([0-9a-f:.]+)\])(?::(\d{1,5}))?$/i.exec(value);
88
+ if (!match)
89
+ return undefined;
90
+ const address = match[1] ?? match[2];
91
+ if (isIP(address) === 0)
92
+ return undefined;
93
+ if (match[3] !== undefined) {
94
+ const port = Number(match[3]);
95
+ if (!Number.isInteger(port) || port < 1 || port > 65_535)
96
+ return undefined;
97
+ }
98
+ return address;
99
+ }
100
+ function isSameOriginBrowserMutation(request, host) {
101
+ const fetchSite = singleHeader(request.headers["sec-fetch-site"]).trim().toLowerCase();
102
+ if (fetchSite && fetchSite !== "same-origin")
103
+ return false;
104
+ const origin = singleHeader(request.headers.origin).trim();
105
+ if (origin) {
106
+ try {
107
+ const parsed = new URL(origin);
108
+ const directScheme = request.socket.encrypted ? "https" : "http";
109
+ const expected = new URL(`${directScheme}://${host}`);
110
+ if (parsed.username ||
111
+ parsed.password ||
112
+ parsed.pathname !== "/" ||
113
+ parsed.search ||
114
+ parsed.hash ||
115
+ parsed.origin !== expected.origin) {
116
+ return false;
117
+ }
118
+ }
119
+ catch {
120
+ return false;
121
+ }
122
+ }
123
+ return fetchSite === "same-origin" || origin.length > 0;
124
+ }
125
+ function singleHeader(value) {
126
+ return typeof value === "string" ? value : "";
127
+ }
128
+ function safeTokenEquals(actual, expected) {
129
+ const left = Buffer.from(actual, "utf8");
130
+ const right = Buffer.from(expected, "utf8");
131
+ return left.byteLength === right.byteLength && timingSafeEqual(left, right);
132
+ }
package/dist/server.d.ts CHANGED
@@ -1,11 +1,53 @@
1
+ import type { Server as HttpServer } from "node:http";
1
2
  import Koa from "koa";
2
- import { ConversationRuntime, type AppConfig, type ChannelFactory, type ChannelInstanceDescriptor, type SessionBus, type SessionLogStore, type SessionRegistry } from "@rynx-ai/core";
3
- import { RunnerManager, type CodexSessionStore } from "@rynx-ai/runtime";
3
+ import { ConversationRuntime, type AgentCapabilities, type AgentSessionStore, type AppConfig, type ChannelInstanceDescriptor, type SessionEvent, type SessionBus, type SessionLogStore, type SessionRegistry } from "@rynx-ai/core";
4
+ import type { SessionInteractionResolution } from "@rynx-ai/protocol";
5
+ import type { ControlRuntimeShareAddress, DaemonBrowserArtifactCleanResult, DaemonBrowserArtifactInstallInput, DaemonBrowserArtifactInstallResult, DaemonBrowserArtifactUpdateInput, DaemonBrowserArtifactVersionResult, DaemonCleanupSessionsInput, DaemonCleanupSessionsResult, DaemonChromeInspectionConfigureInput, DaemonChromeInspectionStatus, DaemonShutdownIfIdleResult } from "@rynx-ai/protocol/control";
6
+ import type { PluginInstallCommitInput, PluginInstallCommitResult, PluginInstallPreparation, PluginInstallPrepareInput, PluginManagementItem } from "@rynx-ai/protocol/plugin-management";
7
+ import type { PairingOffer } from "@rynx-ai/protocol/direct-runtime";
8
+ import type { DaemonStatus } from "@rynx-ai/protocol/remote-runtime";
9
+ import type { RuntimeBrowserBootstrapCredential, RuntimeBrowserEndpointDescriptor } from "@rynx-ai/protocol/runtime-browser-bootstrap";
10
+ import type { RuntimeBrowserInspectMessage, RuntimeBrowserInspectTarget } from "@rynx-ai/protocol/runtime-browser-inspect";
11
+ import type { RuntimeBrowserSurfaceClientFrame, RuntimeBrowserSurfaceImageFrame, RuntimeBrowserSurfaceOpenFrame, RuntimeBrowserSurfaceReadyFrame, RuntimeBrowserSurfaceServerFrame } from "@rynx-ai/protocol/runtime-browser-surface";
12
+ import type { RuntimeEmulatorSurfaceImageFrame, RuntimeEmulatorSurfaceReadyFrame } from "@rynx-ai/protocol/runtime-emulator-surface";
13
+ import type { RemoteRuntimeRpcMethod, RemoteRuntimeRpcParams, RemoteRuntimeRpcResultFor, RemoteRuntimeSequencedSessionEvent } from "@rynx-ai/protocol/remote-runtime-rpc";
14
+ import type { PluginAgentSummary, PluginResolvedSessionExecution, PluginSessionExecutionSnapshot } from "@rynx-ai/plugin-sdk";
15
+ import { RunnerManager, type CodexSessionStore, type RunnerSessionContextProvider } from "@rynx-ai/runtime";
4
16
  import { ChannelManager } from "./channel-manager.js";
5
- import { type ControlPlaneDeps } from "./control-api.js";
17
+ import { type ControlPlaneDeps, type LocalSessionResourceHost, type SessionResourceLifecycle } from "./control-api.js";
18
+ import type { DaemonRuntimeHost } from "./remote-runtime.js";
19
+ import { type AttachDesktopBrowserHostServerOptions } from "./desktop-browser-host.js";
20
+ import { SessionRuntimeIndex } from "./session-runtime-index.js";
21
+ import type { SessionEmulatorService } from "./session-emulator-service.js";
22
+ import { type SessionTerminalHost } from "./session-terminal-host.js";
23
+ import type { ProviderCliManagementHost } from "./provider-cli-host.js";
24
+ import { type RuntimeWebAccessPolicy } from "./runtime-web-auth.js";
6
25
  export { ChannelManager } from "./channel-manager.js";
7
26
  export type { ChannelInstanceStatus } from "./channel-manager.js";
8
- export type { ControlPlaneDeps, StoredSessionMeta } from "./control-api.js";
27
+ export type { ProviderCliManagementHost, ProviderCliStatusHost, } from "./provider-cli-host.js";
28
+ export { MachineSessionService, MachineSessionServiceFailure, MachineSessionServiceInputError, synthesizeSessionTitle, } from "./machine-session-service.js";
29
+ export type { MachineSessionAgentCatalogPort, MachineSessionCreateInput, MachineSessionCreateResult, MachineSessionDeleteResult, MachineSessionInterruptPort, MachineSessionInterruptResult, MachineSessionInteractionResult, MachineSessionListInput, MachineSessionListPage, MachineSessionMessageResult, MachineSessionMessageEnqueueResult, MachineSessionMessageInput, MachineSessionMessageOperationState, MachineSessionPendingMessage, MachineSessionPendingMessagePort, MachineSessionPreparedInput, MachineSessionResourcePort, MachineSessionRunnerPort, MachineSessionRuntimeStatePort, MachineSessionServiceFailureCode, MachineSessionServiceOptions, MachineSessionServicePorts, MachineSessionSnapshotInput, MachineSessionSnapshotPage, MachineSessionWatch, } from "./machine-session-service.js";
30
+ export { SessionBrowserHostError, SessionBrowserService, SessionBrowserServiceError, SessionBrowserSurfaceUnsupportedError, } from "./session-browser-service.js";
31
+ export type { SessionBrowserHost, SessionBrowserHostCreateInput, SessionBrowserHostErrorCode, SessionBrowserHostEvent, SessionBrowserHostHandle, SessionBrowserHostPage, SessionBrowserHostSurfaceFrame, SessionBrowserHostSurfaceOpenInput, SessionBrowserHostSurfaceSource, SessionBrowserHostSurfaceTrustedInput, SessionBrowserHostSurfaceViewport, SessionBrowserHostSnapshot, SessionBrowserInspectionEndpoint, SessionBrowserInspectionTarget, SessionBrowserRegistryPort, SessionBrowserServiceErrorCode, SessionBrowserServiceOptions, SessionBrowserServicePorts, SessionBrowserSurfaceOpenInput, SessionBrowserSurfaceSource, } from "./session-browser-service.js";
32
+ export { SessionEmulatorBindingConflictError, SessionEmulatorService, SessionEmulatorServiceError, } from "./session-emulator-service.js";
33
+ export type { SessionEmulatorBindingRecord, SessionEmulatorBindingStore, SessionEmulatorServiceErrorCode, SessionEmulatorServiceOptions, SessionEmulatorSurface, } from "./session-emulator-service.js";
34
+ export { SessionBrowserSurfaceCoordinator } from "./session-browser-surface-coordinator.js";
35
+ export type { SessionBrowserSurfaceCoordinatorOptions, } from "./session-browser-surface-coordinator.js";
36
+ export { attachDesktopBrowserHostServer, createDesktopFirstSessionBrowserHost, DesktopBrowserHostAbsentError, DesktopBrowserHostProtocolError, DesktopBrowserHostRegistry, } from "./desktop-browser-host.js";
37
+ export type { AttachDesktopBrowserHostServerOptions, DesktopBrowserHostRegistryOptions, } from "./desktop-browser-host.js";
38
+ export type { ControlPlaneDeps, LocalSessionResourceHost, StoredSessionMeta, } from "./control-api.js";
39
+ export { createDaemonRuntimeHost, encodeDaemonStatus } from "./remote-runtime.js";
40
+ export type { DaemonRuntimeHost, DaemonRuntimeSnapshot } from "./remote-runtime.js";
41
+ export { DIRECT_RUNTIME_CONTROL_PATH, DirectRuntimeConnectionHub, startDirectRuntimeServer, } from "./direct-runtime-server.js";
42
+ export type { DirectRuntimeAuthenticationResult, DirectRuntimeAuthenticator, DirectRuntimeEmulatorSurfaceAttachment, DirectRuntimeEmulatorSurfaceHost, DirectRuntimePeer, DirectRuntimeServer, DirectRuntimeServerLimits, StartDirectRuntimeServerOptions, } from "./direct-runtime-server.js";
43
+ export { attachDirectRuntimeBrowserSurfaceServer, DirectRuntimeBrowserSurfaceHostError, } from "./direct-runtime-browser-surface-server.js";
44
+ export { attachDirectRuntimeBrowserInspectServer, DirectRuntimeBrowserInspectHostError, } from "./direct-runtime-browser-inspect-server.js";
45
+ export type { AttachDirectRuntimeBrowserInspectServerOptions, DirectRuntimeBrowserInspectAttachment, DirectRuntimeBrowserInspectConnectionHub, DirectRuntimeBrowserInspectHost, DirectRuntimeBrowserInspectServer, DirectRuntimeBrowserInspectServerLimits, DirectRuntimeBrowserInspectTransportCloseReason, } from "./direct-runtime-browser-inspect-server.js";
46
+ export type { AttachDirectRuntimeBrowserSurfaceServerOptions, DirectRuntimeBrowserSurfaceAttachment, DirectRuntimeBrowserSurfaceAttachmentEvent, DirectRuntimeBrowserSurfaceConnectionHub, DirectRuntimeBrowserSurfaceHost, DirectRuntimeBrowserSurfaceServer, DirectRuntimeBrowserSurfaceServerLimits, DirectRuntimeBrowserSurfaceTransportCloseReason, } from "./direct-runtime-browser-surface-server.js";
47
+ export { RemoteRuntimeDispatcher } from "./remote-runtime-dispatcher.js";
48
+ export type { AuthenticatedRuntimeSubject, RemoteRuntimeEmulatorHost, RemoteRuntimeSessionEmulatorHost, RemoteRuntimeDispatchContext, RemoteRuntimeDispatcherOptions, } from "./remote-runtime-dispatcher.js";
49
+ export { createRunnerSessionTerminalHost, SessionTerminalOpenError, SessionTerminalStreamError, } from "./session-terminal-host.js";
50
+ export type { RunnerSessionTerminalHostOptions, RunnerSessionTerminalHost, SessionTerminalAttachment, SessionTerminalCloseInfo, SessionTerminalCloseReason, SessionTerminalHost, SessionTerminalOpenErrorCode, SessionTerminalOpenOptions, SessionTerminalRole, } from "./session-terminal-host.js";
9
51
  export type { ControlChannel, ControlChannelType, ControlInstanceConfig, ControlInstanceStatus, ControlAgentSummary, } from "@rynx-ai/protocol/control";
10
52
  export interface CreateAppOptions {
11
53
  config?: AppConfig;
@@ -20,16 +62,27 @@ export interface CreateAppOptions {
20
62
  sessionLog?: SessionLogStore;
21
63
  runnerManager?: RunnerManager;
22
64
  sessionStore?: CodexSessionStore;
65
+ pluginRuntimeStatus?: () => unknown;
66
+ pluginRuntimeReload?: (pluginId: string) => Promise<unknown>;
67
+ pluginRuntimeEnsure?: (pluginId: string) => Promise<unknown>;
68
+ daemonManagement?: DaemonManagementHost;
69
+ remoteRuntime?: DaemonRuntimeHost;
70
+ remoteRuntimeAdmin?: RemoteRuntimeAdminHost;
71
+ runtimeTargetControl?: RuntimeTargetControlHost;
72
+ runtimeWebAccess?: RuntimeWebAccessPolicy;
73
+ runtimeConnectionResolver?: RuntimeConnectionResolverHost;
74
+ localSessionResources?: LocalSessionResourceHost;
75
+ sessionEmulators?: SessionEmulatorService;
76
+ /** Host lifecycle signal for ending SSE/video streams before drain. */
77
+ shutdownSignal?: AbortSignal;
78
+ sessionRuntimeIndex?: SessionRuntimeIndex;
79
+ sessionLifecycle?: SessionResourceLifecycle;
80
+ runtimeLocalBrowser?: RuntimeLocalBrowserAutomationHost;
81
+ providerClis?: ProviderCliManagementHost;
23
82
  };
24
83
  }
25
84
  export interface StartServerOptions {
26
85
  config?: AppConfig;
27
- /**
28
- * Legacy: channel plugins to mount as one shared-context batch. Kept for
29
- * back-compat (and tests); the daemon now uses {@link loadInstances} so each
30
- * instance gets its own context. Empty ⇒ a pure `/health` server.
31
- */
32
- channelFactories?: ChannelFactory[];
33
86
  /** Static set of channel instances to mount, each with its own context. */
34
87
  channelInstances?: ChannelInstanceDescriptor[];
35
88
  /**
@@ -55,12 +108,311 @@ export interface StartServerOptions {
55
108
  * per session; the control plane lists every session uniformly from it.
56
109
  */
57
110
  sessionRegistry?: SessionRegistry;
111
+ /** Trusted daemon-side bridge for isolated plugin runners. Installed plugin
112
+ * code never receives these objects; the bridge projects capability-gated
113
+ * JSON RPC from them. */
114
+ pluginRuntime?: PluginRuntimeLifecycle;
115
+ /** Narrow, loopback-only bridge for resident-daemon management clients. */
116
+ daemonManagement?: DaemonManagementHost;
117
+ /** Transport-independent Remote Runtime application port. */
118
+ remoteRuntime?: DaemonRuntimeHost;
119
+ /** Loopback-only enrollment and client-grant administration. */
120
+ remoteRuntimeAdmin?: RemoteRuntimeAdminHost;
121
+ /** Local BFF authority for explicit Local or Direct Runtime targets. */
122
+ runtimeTargetControl?: RuntimeTargetControlHost;
123
+ /** Secret-owning backend resolver for explicit Local or Direct Runtime calls. */
124
+ runtimeConnectionResolver?: RuntimeConnectionResolverHost;
125
+ /** In-process resource authority used only by the Local Runtime BFF. */
126
+ localSessionResources?: LocalSessionResourceHost;
127
+ /** Runtime-owned Session Emulator binding authority for Local compatibility routes. */
128
+ sessionEmulators?: SessionEmulatorService;
129
+ /** Pre-composed daemon-owned Session runtime. Supplying this lets the daemon
130
+ * inject the same application service into Local HTTP and Direct Runtime
131
+ * adapters without mirroring Session state into another owner. */
132
+ sessionRuntimeServices?: SessionRuntimeServices;
133
+ /** Shared fence for Session-owned resources on canonical and legacy deletes. */
134
+ sessionLifecycle?: SessionResourceLifecycle;
135
+ /** Shared local terminal host. Supplying this lets Local HTTP/WebSocket and
136
+ * Direct Runtime attachments contribute to one activity count. */
137
+ sessionTerminals?: SessionTerminalHost;
138
+ /** Runtime-local, Session-capability-authorized CDP bootstrap. Never remote. */
139
+ runtimeLocalBrowser?: RuntimeLocalBrowserAutomationHost;
140
+ /** Runtime-owned provider CLI inspection and local lifecycle operations. */
141
+ providerClis?: ProviderCliManagementHost;
142
+ /** Private resident-app Browser Host socket, authenticated by daemonManagement. */
143
+ desktopBrowserHost?: Omit<AttachDesktopBrowserHostServerOptions, "managementToken">;
144
+ }
145
+ export interface SessionRuntimeServices {
146
+ sessionStore: CodexSessionStore;
147
+ runnerManager: RunnerManager;
148
+ sessionBus: SessionBus;
149
+ sessionRuntimeIndex: SessionRuntimeIndex;
150
+ conversationRuntime: ConversationRuntime;
151
+ }
152
+ export interface PluginRuntimeHostServices {
153
+ conversationRuntime: ConversationRuntime;
154
+ capabilities: AgentCapabilities;
155
+ sessionStore: AgentSessionStore;
156
+ sessionRegistry: SessionRegistry;
157
+ agentCatalog: {
158
+ list(): Promise<PluginAgentSummary[]>;
159
+ get(id: string): Promise<PluginAgentSummary | null>;
160
+ resolveExecution(input: {
161
+ defaultAgent?: string;
162
+ session: PluginSessionExecutionSnapshot;
163
+ }): Promise<PluginResolvedSessionExecution>;
164
+ };
165
+ interruptSession(sessionId: string): Promise<boolean>;
166
+ resolveSessionInteraction(sessionId: string, interactionId: string, resolution: SessionInteractionResolution): Promise<{
167
+ disposition: "applied" | "already_resolved" | "not_found" | "invalid";
168
+ }>;
169
+ }
170
+ export interface PluginRuntimeLifecycle {
171
+ bindHostServices(services: PluginRuntimeHostServices): void;
172
+ startPluginRuntimes(): Promise<void>;
173
+ reloadPluginRuntime(pluginId: string): Promise<unknown>;
174
+ ensurePluginRuntime(pluginId: string): Promise<unknown>;
175
+ /** Cached process/contribution health; must not block on plugin RPC. */
176
+ statusSnapshot(): unknown;
177
+ dispose(): Promise<void>;
178
+ }
179
+ export interface DaemonControlIdentity {
180
+ installationId: string;
181
+ algorithm: "Ed25519";
182
+ publicKey: string;
183
+ }
184
+ export interface PluginCliInvocationInput {
185
+ pluginId: string;
186
+ args: string[];
187
+ stdin?: string;
188
+ }
189
+ export interface PluginCliInvocationOutput {
190
+ code: number;
191
+ stdout: string;
192
+ stderr: string;
193
+ truncated: boolean;
194
+ }
195
+ export interface DaemonManagementInvocationContext {
196
+ signal: AbortSignal;
197
+ }
198
+ export interface PluginManagementHost {
199
+ listPlugins(): {
200
+ plugins: PluginManagementItem[];
201
+ } | Promise<{
202
+ plugins: PluginManagementItem[];
203
+ }>;
204
+ setPluginEnabled(pluginId: string, enabled: boolean): PluginManagementItem | undefined | Promise<PluginManagementItem | undefined>;
205
+ uninstallPlugin(pluginId: string): Promise<boolean>;
206
+ prepareInstallation(input: PluginInstallPrepareInput, context: DaemonManagementInvocationContext): Promise<PluginInstallPreparation>;
207
+ commitInstallation(token: string, input: PluginInstallCommitInput, context: DaemonManagementInvocationContext): Promise<PluginInstallCommitResult>;
208
+ cancelPreparation(token: string): boolean | Promise<boolean>;
209
+ dispose?(): void | Promise<void>;
210
+ }
211
+ export interface BrowserArtifactManagementHost {
212
+ install(input: DaemonBrowserArtifactInstallInput, context: DaemonManagementInvocationContext): Promise<DaemonBrowserArtifactInstallResult>;
213
+ update(input: DaemonBrowserArtifactUpdateInput, context: DaemonManagementInvocationContext): Promise<DaemonBrowserArtifactInstallResult>;
214
+ version(): DaemonBrowserArtifactVersionResult;
215
+ clean(): DaemonBrowserArtifactCleanResult;
216
+ }
217
+ export interface MaintenanceManagementHost {
218
+ cleanupSessions(input: DaemonCleanupSessionsInput): DaemonCleanupSessionsResult;
219
+ }
220
+ export interface ChromeInspectionManagementHost {
221
+ status(): DaemonChromeInspectionStatus | Promise<DaemonChromeInspectionStatus>;
222
+ configure(input: DaemonChromeInspectionConfigureInput): Promise<DaemonChromeInspectionStatus>;
223
+ }
224
+ /** The complete local management authority injected by the daemon composition root. */
225
+ export interface DaemonManagementHost {
226
+ managementToken: string;
227
+ identity(): DaemonControlIdentity;
228
+ /** Public, non-secret health signal used to detect an in-place daemon rebuild. */
229
+ buildStatus?(): {
230
+ restartRequired: boolean;
231
+ };
232
+ /** Perform one final activity check and schedule shutdown only when idle. */
233
+ shutdownIfIdle?(): DaemonShutdownIfIdleResult;
234
+ /** Stateful plugin registry operations owned by the resident daemon. */
235
+ pluginManagement?: PluginManagementHost;
236
+ /** Stateful Chrome for Testing artifact operations owned by the daemon. */
237
+ browserArtifacts?: BrowserArtifactManagementHost;
238
+ /** Destructive maintenance operations over daemon-owned state. */
239
+ maintenance?: MaintenanceManagementHost;
240
+ /** Local Chrome DevTools discovery gateway configuration and readiness. */
241
+ chromeInspection?: ChromeInspectionManagementHost;
242
+ invokePluginCli(input: PluginCliInvocationInput, context: DaemonManagementInvocationContext): Promise<PluginCliInvocationOutput>;
243
+ }
244
+ /**
245
+ * Runtime-local Browser automation bootstrap. Returning `undefined` means the
246
+ * Session capability was not accepted; implementations must not reveal which
247
+ * half of the credential was wrong.
248
+ */
249
+ export interface RuntimeLocalBrowserAutomationHost {
250
+ authorizeCredential(credential: RuntimeBrowserBootstrapCredential): boolean | Promise<boolean>;
251
+ endpointForCredential(credential: RuntimeBrowserBootstrapCredential): Promise<RuntimeBrowserEndpointDescriptor | undefined>;
252
+ endpointForSession(sessionId: string): Promise<RuntimeBrowserEndpointDescriptor>;
253
+ }
254
+ export interface RemoteRuntimeClientGrantView {
255
+ grantId: string;
256
+ clientId: string;
257
+ clientLabel: string | null;
258
+ clientKeyFingerprint: string;
259
+ authorities: string[];
260
+ createdAt: string;
261
+ revokedAt: string | null;
262
+ lastUsedAt: string | null;
58
263
  }
264
+ /** Local operator authority for enabling new Direct clients and revoking them. */
265
+ export interface RemoteRuntimeAdminHost {
266
+ listShareAddresses(): ControlRuntimeShareAddress[];
267
+ createPairingOffer(input?: {
268
+ clientLabel?: string;
269
+ /** Host or ws(s) endpoint advertised by this individual access link. */
270
+ address?: string;
271
+ }): PairingOffer;
272
+ listClientGrants(): RemoteRuntimeClientGrantView[];
273
+ revokeClientGrant(grantId: string): {
274
+ revoked: boolean;
275
+ closedConnections: number;
276
+ };
277
+ deleteRevokedClientGrant(grantId: string): {
278
+ deleted: boolean;
279
+ };
280
+ }
281
+ /** Secret-free Runtime target projection safe for the local Control Plane UI. */
282
+ export interface RuntimeTargetView {
283
+ /** Client-local selector: the reserved `local` selector or an opaque daemon id. */
284
+ selector: string;
285
+ daemonId: string;
286
+ displayName: string;
287
+ binding: "local" | "direct";
288
+ endpoint?: string;
289
+ identityKeyFingerprint?: string;
290
+ createdAt?: string;
291
+ }
292
+ export interface RuntimeTargetTestResult {
293
+ target: RuntimeTargetView;
294
+ status: DaemonStatus;
295
+ }
296
+ export interface RuntimeTargetPairResult {
297
+ target: RuntimeTargetView;
298
+ /** Authenticated status probe completed before the target is reported paired. */
299
+ status: DaemonStatus;
300
+ }
301
+ /** Local backend seam; credentials and pinned identity keys never cross it. */
302
+ export interface RuntimeTargetControlHost {
303
+ list(): RuntimeTargetView[] | Promise<RuntimeTargetView[]>;
304
+ pair(input: {
305
+ offer: unknown;
306
+ displayName?: string;
307
+ replaceExisting?: boolean;
308
+ expectedDaemonId?: string;
309
+ }): RuntimeTargetPairResult | Promise<RuntimeTargetPairResult>;
310
+ test(selector: string): RuntimeTargetTestResult | Promise<RuntimeTargetTestResult>;
311
+ forget(daemonId: string): {
312
+ forgotten: true;
313
+ } | Promise<{
314
+ forgotten: true;
315
+ }>;
316
+ }
317
+ /** Secret-free logical Runtime connection leased by the local Control Plane BFF. */
318
+ export interface RuntimeConnectionLease {
319
+ readonly target: {
320
+ selector: string;
321
+ daemonId: string;
322
+ };
323
+ call<M extends RemoteRuntimeRpcMethod>(method: M, params: RemoteRuntimeRpcParams<M>, options?: {
324
+ signal?: AbortSignal;
325
+ timeoutMs?: number;
326
+ }): Promise<RemoteRuntimeRpcResultFor<M>>;
327
+ subscribeSessionEvents(sessionId: string, options?: {
328
+ signal?: AbortSignal;
329
+ timeoutMs?: number;
330
+ }): Promise<RuntimeSessionEventsSubscription>;
331
+ openSessionTerminal(sessionId: string, options: {
332
+ role: "owner" | "read-only";
333
+ cols: number;
334
+ rows: number;
335
+ signal?: AbortSignal;
336
+ timeoutMs?: number;
337
+ }): Promise<import("./session-terminal-host.js").SessionTerminalAttachment>;
338
+ openBrowserSurface(frame: RuntimeBrowserSurfaceOpenFrame, options?: {
339
+ signal?: AbortSignal;
340
+ timeoutMs?: number;
341
+ }): Promise<RuntimeBrowserSurfaceConnection>;
342
+ openBrowserInspect(target: RuntimeBrowserInspectTarget, options?: {
343
+ signal?: AbortSignal;
344
+ timeoutMs?: number;
345
+ }): Promise<RuntimeBrowserInspectConnection>;
346
+ openEmulatorSurface(sessionId: string, bindingId: string, options?: {
347
+ signal?: AbortSignal;
348
+ timeoutMs?: number;
349
+ maximumFrameRate?: number;
350
+ }): Promise<RuntimeEmulatorSurfaceConnection>;
351
+ release(): void;
352
+ }
353
+ /** Secret-free Browser presentation stream owned by one selected Runtime. */
354
+ export interface RuntimeBrowserSurfaceConnection extends AsyncIterable<RuntimeBrowserSurfaceEvent> {
355
+ readonly ready: RuntimeBrowserSurfaceReadyFrame;
356
+ send(frame: Exclude<RuntimeBrowserSurfaceClientFrame, RuntimeBrowserSurfaceOpenFrame>): Promise<void>;
357
+ close(): Promise<void>;
358
+ }
359
+ export type RuntimeBrowserSurfaceEvent = Exclude<RuntimeBrowserSurfaceServerFrame, RuntimeBrowserSurfaceReadyFrame> | RuntimeBrowserSurfaceImageFrame;
360
+ /** Dedicated transparent CDP stream owned by one selected Runtime page. */
361
+ export interface RuntimeBrowserInspectConnection extends AsyncIterable<RuntimeBrowserInspectMessage> {
362
+ readonly daemonInstanceId: string;
363
+ send(message: RuntimeBrowserInspectMessage): Promise<void>;
364
+ close(): Promise<void>;
365
+ }
366
+ export interface RuntimeEmulatorSurfaceConnection extends AsyncIterable<RuntimeEmulatorSurfaceImageFrame> {
367
+ readonly ready: RuntimeEmulatorSurfaceReadyFrame;
368
+ sendTouch(point: {
369
+ phase: "begin" | "move" | "end";
370
+ x: number;
371
+ y: number;
372
+ }): Promise<void>;
373
+ close(): Promise<void>;
374
+ }
375
+ /** One Runtime-owned live Session tail. The lease must outlive this handle. */
376
+ export interface RuntimeSessionEventsSubscription extends AsyncIterable<RemoteRuntimeSequencedSessionEvent> {
377
+ readonly sessionId: string;
378
+ readonly daemonInstanceId: string;
379
+ close(): Promise<void>;
380
+ }
381
+ /** Application-facing half of the daemon-owned connection manager. */
382
+ export interface RuntimeConnectionResolverHost {
383
+ acquire(selector: string, options?: {
384
+ signal?: AbortSignal;
385
+ }): Promise<RuntimeConnectionLease>;
386
+ }
387
+ /** HTTP server plus an idempotent join point for all daemon-owned resources. */
388
+ export interface RynxServer extends HttpServer {
389
+ /** Synchronously stop new HTTP admission without closing upgraded Hosts. */
390
+ stopAccepting(): void;
391
+ shutdown(): Promise<void>;
392
+ }
393
+ /** Preserve one session's mirror order without serializing unrelated sessions. */
394
+ export declare class SessionMirrorQueue {
395
+ private readonly persist;
396
+ private readonly tails;
397
+ constructor(persist: (sessionId: string, event: SessionEvent) => Promise<void>);
398
+ enqueue(sessionId: string, event: SessionEvent): Promise<void>;
399
+ }
400
+ /**
401
+ * Compose the process-owned Session runtime once. The daemon may call this
402
+ * before creating its Direct dispatcher; {@link startServer} accepts the same
403
+ * bundle and therefore does not create a second bus, runtime index, or runner.
404
+ */
405
+ export declare function createSessionRuntimeServices(input: {
406
+ config: AppConfig;
407
+ sessionLog?: SessionLogStore;
408
+ onMirrorError?: (error: unknown, sessionId: string) => void;
409
+ sessionContextProvider?: RunnerSessionContextProvider;
410
+ }): SessionRuntimeServices;
59
411
  /**
60
412
  * The HTTP surface is just a liveness probe for container orchestration — all
61
413
  * agent capabilities are forwarded through the mounted channel plugins (the
62
414
  * Lark bot reaches its server over an outbound WebSocket long connection), so
63
415
  * no agent request / response / SSE endpoints are exposed here.
64
416
  */
65
- export declare function createApp({ control }?: CreateAppOptions): Koa<Koa.DefaultState, Koa.DefaultContext>;
66
- export declare function startServer({ config, channelFactories, channelInstances, loadInstances, control, sessionLog, sessionRegistry, }?: StartServerOptions): Promise<import("node:http").Server<typeof import("node:http").IncomingMessage, typeof import("node:http").ServerResponse>>;
417
+ export declare function createApp({ config, control }?: CreateAppOptions): Koa<Koa.DefaultState, Koa.DefaultContext>;
418
+ export declare function startServer({ config, channelInstances, loadInstances, control, sessionLog, sessionRegistry, pluginRuntime, daemonManagement, remoteRuntime, remoteRuntimeAdmin, runtimeTargetControl, runtimeConnectionResolver, localSessionResources, sessionEmulators, sessionRuntimeServices, sessionLifecycle, sessionTerminals, runtimeLocalBrowser, providerClis, desktopBrowserHost, }?: StartServerOptions): Promise<RynxServer>;