@rynx-ai/server 0.1.10 → 0.1.11-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.
- package/dist/control-api.d.ts +10 -52
- package/dist/control-api.js +588 -335
- package/dist/control-web/assets/{highlighted-body-OFNGDK62-DgFZpTNw.js → highlighted-body-OFNGDK62-DWWsUtHF.js} +1 -1
- package/dist/control-web/assets/index-BnX7NWJX.js +689 -0
- package/dist/control-web/assets/index-CUoWRX2i.css +32 -0
- package/dist/control-web/assets/{mermaid-GHXKKRXX-BDikE3W1.js → mermaid-GHXKKRXX-C1fxAgiw.js} +3 -3
- package/dist/control-web/index.html +2 -2
- package/dist/machine-session-service.d.ts +106 -23
- package/dist/machine-session-service.js +290 -53
- package/dist/remote-runtime-dispatcher.d.ts +12 -2
- package/dist/remote-runtime-dispatcher.js +52 -0
- package/dist/remote-runtime-session-projection.js +1 -0
- package/dist/server.d.ts +36 -28
- package/dist/server.js +81 -140
- package/dist/session-runtime-index.js +7 -0
- package/package.json +7 -7
- package/dist/channel-manager.d.ts +0 -60
- package/dist/channel-manager.js +0 -106
- package/dist/control-web/assets/index-CnVtOmLv.css +0 -32
- package/dist/control-web/assets/index-Dlywgy58.js +0 -661
package/dist/server.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { Server as HttpServer } from "node:http";
|
|
2
2
|
import Koa from "koa";
|
|
3
|
-
import { ConversationRuntime, type AgentCapabilities, type AgentSessionStore, type AppConfig, type
|
|
3
|
+
import { ConversationRuntime, type AgentCapabilities, type AgentSessionStore, type AppConfig, type SessionEvent, type SessionBus, type SessionLogStore, type SessionRegistry } from "@rynx-ai/core";
|
|
4
4
|
import type { SessionInteractionResolution } from "@rynx-ai/protocol";
|
|
5
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";
|
|
6
|
+
import type { PluginInstallCommitInput, PluginInstallCommitResult, PluginInstallPreparation, PluginInstallPrepareInput, PluginManagementItem, PluginMarketplaceAddInput, PluginMarketplaceItem } from "@rynx-ai/protocol/plugin-management";
|
|
7
|
+
import type { PluginJsonValue } from "@rynx-ai/plugin-sdk";
|
|
7
8
|
import type { PairingOffer } from "@rynx-ai/protocol/direct-runtime";
|
|
8
9
|
import type { DaemonStatus } from "@rynx-ai/protocol/remote-runtime";
|
|
9
10
|
import type { RuntimeBrowserBootstrapCredential, RuntimeBrowserEndpointDescriptor } from "@rynx-ai/protocol/runtime-browser-bootstrap";
|
|
@@ -13,8 +14,8 @@ import type { RuntimeEmulatorSurfaceImageFrame, RuntimeEmulatorSurfaceReadyFrame
|
|
|
13
14
|
import type { RemoteRuntimeRpcMethod, RemoteRuntimeRpcParams, RemoteRuntimeRpcResultFor, RemoteRuntimeSequencedSessionEvent } from "@rynx-ai/protocol/remote-runtime-rpc";
|
|
14
15
|
import type { PluginAgentSummary, PluginResolvedSessionExecution, PluginSessionExecutionSnapshot } from "@rynx-ai/plugin-sdk";
|
|
15
16
|
import { RunnerManager, type CodexSessionStore, type RunnerSessionContextProvider } from "@rynx-ai/runtime";
|
|
16
|
-
import { ChannelManager } from "./channel-manager.js";
|
|
17
17
|
import { type ControlPlaneDeps, type LocalSessionResourceHost, type SessionResourceLifecycle } from "./control-api.js";
|
|
18
|
+
import type { MachineSessionService } from "./machine-session-service.js";
|
|
18
19
|
import type { DaemonRuntimeHost } from "./remote-runtime.js";
|
|
19
20
|
import { type AttachDesktopBrowserHostServerOptions } from "./desktop-browser-host.js";
|
|
20
21
|
import { SessionRuntimeIndex } from "./session-runtime-index.js";
|
|
@@ -22,11 +23,9 @@ import type { SessionEmulatorService } from "./session-emulator-service.js";
|
|
|
22
23
|
import { type SessionTerminalHost } from "./session-terminal-host.js";
|
|
23
24
|
import type { ProviderCliManagementHost } from "./provider-cli-host.js";
|
|
24
25
|
import { type RuntimeWebAccessPolicy } from "./runtime-web-auth.js";
|
|
25
|
-
export { ChannelManager } from "./channel-manager.js";
|
|
26
|
-
export type { ChannelInstanceStatus } from "./channel-manager.js";
|
|
27
26
|
export type { ProviderCliManagementHost, ProviderCliStatusHost, } from "./provider-cli-host.js";
|
|
28
27
|
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";
|
|
28
|
+
export type { MachineSessionAgentCatalogPort, MachineSessionCreateInput, MachineSessionCreateResult, MachineSessionDeleteResult, MachineSessionForkInput, MachineSessionForkOperationRecord, MachineSessionForkOperationState, MachineSessionForkResult, MachineSessionForkStorePort, MachineSessionNativeRotationInput, 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
29
|
export { SessionBrowserHostError, SessionBrowserService, SessionBrowserServiceError, SessionBrowserSurfaceUnsupportedError, } from "./session-browser-service.js";
|
|
31
30
|
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
31
|
export { SessionEmulatorBindingConflictError, SessionEmulatorService, SessionEmulatorServiceError, } from "./session-emulator-service.js";
|
|
@@ -48,14 +47,14 @@ export { RemoteRuntimeDispatcher } from "./remote-runtime-dispatcher.js";
|
|
|
48
47
|
export type { AuthenticatedRuntimeSubject, RemoteRuntimeEmulatorHost, RemoteRuntimeSessionEmulatorHost, RemoteRuntimeDispatchContext, RemoteRuntimeDispatcherOptions, } from "./remote-runtime-dispatcher.js";
|
|
49
48
|
export { createRunnerSessionTerminalHost, SessionTerminalOpenError, SessionTerminalStreamError, } from "./session-terminal-host.js";
|
|
50
49
|
export type { RunnerSessionTerminalHostOptions, RunnerSessionTerminalHost, SessionTerminalAttachment, SessionTerminalCloseInfo, SessionTerminalCloseReason, SessionTerminalHost, SessionTerminalOpenErrorCode, SessionTerminalOpenOptions, SessionTerminalRole, } from "./session-terminal-host.js";
|
|
51
|
-
export type {
|
|
50
|
+
export type { ControlAgentSummary } from "@rynx-ai/protocol/control";
|
|
51
|
+
export { listRuntimeModels } from "@rynx-ai/runtime";
|
|
52
52
|
export interface CreateAppOptions {
|
|
53
53
|
config?: AppConfig;
|
|
54
54
|
/** When present, mount the control plane (page + JSON API) beside `/health`.
|
|
55
55
|
* `runtime`/`sessionBus`/`sessionLog`/`runnerManager` (from `startServer`'s
|
|
56
56
|
* scope) enable the channel-agnostic `/api/sessions` agent-run endpoints. */
|
|
57
57
|
control?: {
|
|
58
|
-
manager: ChannelManager;
|
|
59
58
|
deps: ControlPlaneDeps;
|
|
60
59
|
runtime?: ConversationRuntime;
|
|
61
60
|
sessionBus?: SessionBus;
|
|
@@ -63,8 +62,6 @@ export interface CreateAppOptions {
|
|
|
63
62
|
runnerManager?: RunnerManager;
|
|
64
63
|
sessionStore?: CodexSessionStore;
|
|
65
64
|
pluginRuntimeStatus?: () => unknown;
|
|
66
|
-
pluginRuntimeReload?: (pluginId: string) => Promise<unknown>;
|
|
67
|
-
pluginRuntimeEnsure?: (pluginId: string) => Promise<unknown>;
|
|
68
65
|
daemonManagement?: DaemonManagementHost;
|
|
69
66
|
remoteRuntime?: DaemonRuntimeHost;
|
|
70
67
|
remoteRuntimeAdmin?: RemoteRuntimeAdminHost;
|
|
@@ -72,6 +69,7 @@ export interface CreateAppOptions {
|
|
|
72
69
|
runtimeWebAccess?: RuntimeWebAccessPolicy;
|
|
73
70
|
runtimeConnectionResolver?: RuntimeConnectionResolverHost;
|
|
74
71
|
localSessionResources?: LocalSessionResourceHost;
|
|
72
|
+
localMachineSessions?: MachineSessionService;
|
|
75
73
|
sessionEmulators?: SessionEmulatorService;
|
|
76
74
|
/** Host lifecycle signal for ending SSE/video streams before drain. */
|
|
77
75
|
shutdownSignal?: AbortSignal;
|
|
@@ -83,29 +81,20 @@ export interface CreateAppOptions {
|
|
|
83
81
|
}
|
|
84
82
|
export interface StartServerOptions {
|
|
85
83
|
config?: AppConfig;
|
|
86
|
-
/** Static set of channel instances to mount, each with its own context. */
|
|
87
|
-
channelInstances?: ChannelInstanceDescriptor[];
|
|
88
84
|
/**
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* control plane drives). Takes precedence over `channelInstances`.
|
|
92
|
-
*/
|
|
93
|
-
loadInstances?: () => Promise<ChannelInstanceDescriptor[]>;
|
|
94
|
-
/**
|
|
95
|
-
* Control-plane deps (config + agent-spec mutators + log tail) injected by the
|
|
96
|
-
* daemon. When present (and instances are managed), the server serves the
|
|
97
|
-
* control page + JSON API. Requires `loadInstances`/`channelInstances`.
|
|
85
|
+
* Control-plane deps injected by the daemon. Plugin/channel management is
|
|
86
|
+
* exposed through the plugin host rather than generic channel instances.
|
|
98
87
|
*/
|
|
99
88
|
control?: ControlPlaneDeps;
|
|
100
89
|
/**
|
|
101
90
|
* Durable canonical session log (the daemon injects the SQLite-backed store).
|
|
102
|
-
* Absent
|
|
91
|
+
* Absent means live session events are not persisted by this server.
|
|
103
92
|
*/
|
|
104
93
|
sessionLog?: SessionLogStore;
|
|
105
94
|
/**
|
|
106
|
-
* Unified machine-session registry (the daemon injects the SQLite-backed
|
|
107
|
-
* over `sessions`).
|
|
108
|
-
*
|
|
95
|
+
* Unified machine-session registry (the daemon injects the SQLite-backed
|
|
96
|
+
* store over `sessions`). Plugins reach it through Host RPC; the control plane
|
|
97
|
+
* lists every session uniformly from it.
|
|
109
98
|
*/
|
|
110
99
|
sessionRegistry?: SessionRegistry;
|
|
111
100
|
/** Trusted daemon-side bridge for isolated plugin runners. Installed plugin
|
|
@@ -124,6 +113,8 @@ export interface StartServerOptions {
|
|
|
124
113
|
runtimeConnectionResolver?: RuntimeConnectionResolverHost;
|
|
125
114
|
/** In-process resource authority used only by the Local Runtime BFF. */
|
|
126
115
|
localSessionResources?: LocalSessionResourceHost;
|
|
116
|
+
/** Canonical same-daemon Session service used by Local compatibility routes. */
|
|
117
|
+
localMachineSessions?: MachineSessionService;
|
|
127
118
|
/** Runtime-owned Session Emulator binding authority for Local compatibility routes. */
|
|
128
119
|
sessionEmulators?: SessionEmulatorService;
|
|
129
120
|
/** Pre-composed daemon-owned Session runtime. Supplying this lets the daemon
|
|
@@ -148,6 +139,7 @@ export interface SessionRuntimeServices {
|
|
|
148
139
|
sessionBus: SessionBus;
|
|
149
140
|
sessionRuntimeIndex: SessionRuntimeIndex;
|
|
150
141
|
conversationRuntime: ConversationRuntime;
|
|
142
|
+
publishSessionEvent: (sessionId: string, event: SessionEvent) => Promise<void>;
|
|
151
143
|
}
|
|
152
144
|
export interface PluginRuntimeHostServices {
|
|
153
145
|
conversationRuntime: ConversationRuntime;
|
|
@@ -170,8 +162,6 @@ export interface PluginRuntimeHostServices {
|
|
|
170
162
|
export interface PluginRuntimeLifecycle {
|
|
171
163
|
bindHostServices(services: PluginRuntimeHostServices): void;
|
|
172
164
|
startPluginRuntimes(): Promise<void>;
|
|
173
|
-
reloadPluginRuntime(pluginId: string): Promise<unknown>;
|
|
174
|
-
ensurePluginRuntime(pluginId: string): Promise<unknown>;
|
|
175
165
|
/** Cached process/contribution health; must not block on plugin RPC. */
|
|
176
166
|
statusSnapshot(): unknown;
|
|
177
167
|
dispose(): Promise<void>;
|
|
@@ -206,8 +196,24 @@ export interface PluginManagementHost {
|
|
|
206
196
|
prepareInstallation(input: PluginInstallPrepareInput, context: DaemonManagementInvocationContext): Promise<PluginInstallPreparation>;
|
|
207
197
|
commitInstallation(token: string, input: PluginInstallCommitInput, context: DaemonManagementInvocationContext): Promise<PluginInstallCommitResult>;
|
|
208
198
|
cancelPreparation(token: string): boolean | Promise<boolean>;
|
|
199
|
+
settingsUi(pluginId: string): {
|
|
200
|
+
generation: string;
|
|
201
|
+
assetGeneration: string;
|
|
202
|
+
html: string;
|
|
203
|
+
} | undefined;
|
|
204
|
+
settingsUiAsset(pluginId: string, assetGeneration: string, assetPath: string): {
|
|
205
|
+
contentType: string;
|
|
206
|
+
data: Buffer;
|
|
207
|
+
} | undefined;
|
|
208
|
+
callSettings(pluginId: string, generation: string, method: string, params: PluginJsonValue | undefined, context: DaemonManagementInvocationContext): Promise<PluginJsonValue>;
|
|
209
209
|
dispose?(): void | Promise<void>;
|
|
210
210
|
}
|
|
211
|
+
export interface PluginMarketplaceManagementHost {
|
|
212
|
+
list(): PluginMarketplaceItem[] | Promise<PluginMarketplaceItem[]>;
|
|
213
|
+
add(input: PluginMarketplaceAddInput, context: DaemonManagementInvocationContext): Promise<PluginMarketplaceItem>;
|
|
214
|
+
refresh(id: string, context: DaemonManagementInvocationContext): Promise<PluginMarketplaceItem>;
|
|
215
|
+
remove(id: string): boolean | Promise<boolean>;
|
|
216
|
+
}
|
|
211
217
|
export interface BrowserArtifactManagementHost {
|
|
212
218
|
install(input: DaemonBrowserArtifactInstallInput, context: DaemonManagementInvocationContext): Promise<DaemonBrowserArtifactInstallResult>;
|
|
213
219
|
update(input: DaemonBrowserArtifactUpdateInput, context: DaemonManagementInvocationContext): Promise<DaemonBrowserArtifactInstallResult>;
|
|
@@ -233,6 +239,8 @@ export interface DaemonManagementHost {
|
|
|
233
239
|
shutdownIfIdle?(): DaemonShutdownIfIdleResult;
|
|
234
240
|
/** Stateful plugin registry operations owned by the resident daemon. */
|
|
235
241
|
pluginManagement?: PluginManagementHost;
|
|
242
|
+
/** Registered Git/local plugin catalogs. */
|
|
243
|
+
pluginMarketplaces?: PluginMarketplaceManagementHost;
|
|
236
244
|
/** Stateful Chrome for Testing artifact operations owned by the daemon. */
|
|
237
245
|
browserArtifacts?: BrowserArtifactManagementHost;
|
|
238
246
|
/** Destructive maintenance operations over daemon-owned state. */
|
|
@@ -415,4 +423,4 @@ export declare function createSessionRuntimeServices(input: {
|
|
|
415
423
|
* no agent request / response / SSE endpoints are exposed here.
|
|
416
424
|
*/
|
|
417
425
|
export declare function createApp({ config, control }?: CreateAppOptions): Koa<Koa.DefaultState, Koa.DefaultContext>;
|
|
418
|
-
export declare function startServer({ config,
|
|
426
|
+
export declare function startServer({ config, control, sessionLog, sessionRegistry, pluginRuntime, daemonManagement, remoteRuntime, remoteRuntimeAdmin, runtimeTargetControl, runtimeConnectionResolver, localSessionResources, localMachineSessions, sessionEmulators, sessionRuntimeServices, sessionLifecycle, sessionTerminals, runtimeLocalBrowser, providerClis, desktopBrowserHost, }?: StartServerOptions): Promise<RynxServer>;
|
package/dist/server.js
CHANGED
|
@@ -3,7 +3,6 @@ import Koa from "koa";
|
|
|
3
3
|
import Router from "@koa/router";
|
|
4
4
|
import { loadConfig, listAgentSpecs, loadAgentSpec, resolveSessionExecution, resolveRuntimeModel, ConversationRuntime, InMemorySessionBus, persistSessionEvent, } from "@rynx-ai/core";
|
|
5
5
|
import { RunnerManager, FileCodexSessionStore, resolveCodexSessionStorePath, } from "@rynx-ai/runtime";
|
|
6
|
-
import { ChannelManager } from "./channel-manager.js";
|
|
7
6
|
import { createControlRouter, } from "./control-api.js";
|
|
8
7
|
import { attachEmulatorTouchWs } from "./emulator-touch-ws.js";
|
|
9
8
|
import { attachTerminalWs } from "./terminal-ws.js";
|
|
@@ -14,7 +13,6 @@ import { resolveControlWebDist, sendSpaFile } from "./control-web-dist.js";
|
|
|
14
13
|
import { SessionRuntimeIndex } from "./session-runtime-index.js";
|
|
15
14
|
import { createRunnerSessionTerminalHost, } from "./session-terminal-host.js";
|
|
16
15
|
import { runtimeWebAccessPolicyForBindHost, } from "./runtime-web-auth.js";
|
|
17
|
-
export { ChannelManager } from "./channel-manager.js";
|
|
18
16
|
export { MachineSessionService, MachineSessionServiceFailure, MachineSessionServiceInputError, synthesizeSessionTitle, } from "./machine-session-service.js";
|
|
19
17
|
export { SessionBrowserHostError, SessionBrowserService, SessionBrowserServiceError, SessionBrowserSurfaceUnsupportedError, } from "./session-browser-service.js";
|
|
20
18
|
export { SessionEmulatorBindingConflictError, SessionEmulatorService, SessionEmulatorServiceError, } from "./session-emulator-service.js";
|
|
@@ -26,6 +24,7 @@ export { attachDirectRuntimeBrowserSurfaceServer, DirectRuntimeBrowserSurfaceHos
|
|
|
26
24
|
export { attachDirectRuntimeBrowserInspectServer, DirectRuntimeBrowserInspectHostError, } from "./direct-runtime-browser-inspect-server.js";
|
|
27
25
|
export { RemoteRuntimeDispatcher } from "./remote-runtime-dispatcher.js";
|
|
28
26
|
export { createRunnerSessionTerminalHost, SessionTerminalOpenError, SessionTerminalStreamError, } from "./session-terminal-host.js";
|
|
27
|
+
export { listRuntimeModels } from "@rynx-ai/runtime";
|
|
29
28
|
/** Preserve one session's mirror order without serializing unrelated sessions. */
|
|
30
29
|
export class SessionMirrorQueue {
|
|
31
30
|
persist;
|
|
@@ -63,15 +62,19 @@ export function createSessionRuntimeServices(input) {
|
|
|
63
62
|
});
|
|
64
63
|
const sessionBus = new InMemorySessionBus();
|
|
65
64
|
const sessionRuntimeIndex = new SessionRuntimeIndex();
|
|
65
|
+
const sessionMirrorQueue = new SessionMirrorQueue((sessionId, event) => persistSessionEvent(sessionId, event, { sessionLog: input.sessionLog, sessionBus }));
|
|
66
|
+
const mirrorSessionEvent = (sessionId, event) => {
|
|
67
|
+
sessionRuntimeIndex.observe(sessionId, event);
|
|
68
|
+
return sessionMirrorQueue.enqueue(sessionId, event);
|
|
69
|
+
};
|
|
66
70
|
const conversationRuntime = new ConversationRuntime({
|
|
67
71
|
config: input.config,
|
|
68
72
|
executor: runnerManager,
|
|
69
73
|
sessionBus,
|
|
74
|
+
sessionEventSink: mirrorSessionEvent,
|
|
70
75
|
});
|
|
71
|
-
const sessionMirrorQueue = new SessionMirrorQueue((sessionId, event) => persistSessionEvent(sessionId, event, { sessionLog: input.sessionLog, sessionBus }));
|
|
72
76
|
runnerManager.onMirror((sessionId, event) => {
|
|
73
|
-
|
|
74
|
-
void sessionMirrorQueue.enqueue(sessionId, event).catch((error) => {
|
|
77
|
+
void mirrorSessionEvent(sessionId, event).catch((error) => {
|
|
75
78
|
input.onMirrorError?.(error, sessionId);
|
|
76
79
|
});
|
|
77
80
|
});
|
|
@@ -81,6 +84,7 @@ export function createSessionRuntimeServices(input) {
|
|
|
81
84
|
sessionBus,
|
|
82
85
|
sessionRuntimeIndex,
|
|
83
86
|
conversationRuntime,
|
|
87
|
+
publishSessionEvent: mirrorSessionEvent,
|
|
84
88
|
};
|
|
85
89
|
}
|
|
86
90
|
/**
|
|
@@ -131,7 +135,7 @@ export function createApp({ config = loadConfig(), control } = {}) {
|
|
|
131
135
|
}
|
|
132
136
|
return app;
|
|
133
137
|
}
|
|
134
|
-
export async function startServer({ config = loadConfig(),
|
|
138
|
+
export async function startServer({ config = loadConfig(), control, sessionLog, sessionRegistry, pluginRuntime, daemonManagement, remoteRuntime, remoteRuntimeAdmin, runtimeTargetControl, runtimeConnectionResolver, localSessionResources, localMachineSessions, sessionEmulators, sessionRuntimeServices, sessionLifecycle, sessionTerminals, runtimeLocalBrowser, providerClis, desktopBrowserHost, } = {}) {
|
|
135
139
|
const runtimeWebAccess = runtimeWebAccessPolicyForBindHost(config.HOST);
|
|
136
140
|
const desktopBrowserManagementToken = desktopBrowserHost
|
|
137
141
|
? requireDaemonManagementToken(daemonManagement)
|
|
@@ -148,10 +152,10 @@ export async function startServer({ config = loadConfig(), channelInstances, loa
|
|
|
148
152
|
createRunnerSessionTerminalHost({
|
|
149
153
|
runnerManager,
|
|
150
154
|
resolveLiveSession: async (sessionId) => {
|
|
151
|
-
const session =
|
|
155
|
+
const session = sessionRegistry?.get(sessionId);
|
|
152
156
|
if (!session || !runnerManager.hasLiveSession(sessionId))
|
|
153
157
|
return undefined;
|
|
154
|
-
return { cwd: session.cwd };
|
|
158
|
+
return { cwd: session.workspace.cwd };
|
|
155
159
|
},
|
|
156
160
|
});
|
|
157
161
|
if (pluginRuntime) {
|
|
@@ -178,136 +182,49 @@ export async function startServer({ config = loadConfig(), channelInstances, loa
|
|
|
178
182
|
resolveSessionInteraction: (sessionId, interactionId, resolution) => runnerManager.resolveInteraction(sessionId, interactionId, resolution),
|
|
179
183
|
});
|
|
180
184
|
}
|
|
181
|
-
//
|
|
182
|
-
//
|
|
183
|
-
//
|
|
185
|
+
// Provider TUI `/clear`·`/fork` uses the same publication boundary as an
|
|
186
|
+
// explicit Rynx fork. The manager exposes the transferred terminal only after
|
|
187
|
+
// this resolves, so no target can appear with missing history or metadata.
|
|
184
188
|
runnerManager.onRotate((r) => {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
? { provider: source.provider }
|
|
193
|
-
: {}),
|
|
194
|
-
...(r.model ? { model: r.model } : {}),
|
|
195
|
-
createdAt: new Date().toISOString(),
|
|
189
|
+
if (!localMachineSessions) {
|
|
190
|
+
throw new Error("native Session rotation requires the machine Session service");
|
|
191
|
+
}
|
|
192
|
+
return localMachineSessions.recordNativeRotation({
|
|
193
|
+
sourceSessionId: r.from,
|
|
194
|
+
targetSessionId: r.to,
|
|
195
|
+
kind: r.kind,
|
|
196
196
|
});
|
|
197
197
|
});
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
? (pluginId) => pluginRuntime.reloadPluginRuntime(pluginId)
|
|
229
|
-
: undefined,
|
|
230
|
-
pluginRuntimeEnsure: pluginRuntime
|
|
231
|
-
? (pluginId) => pluginRuntime.ensurePluginRuntime(pluginId)
|
|
232
|
-
: undefined,
|
|
233
|
-
daemonManagement,
|
|
234
|
-
remoteRuntime,
|
|
235
|
-
remoteRuntimeAdmin,
|
|
236
|
-
runtimeTargetControl,
|
|
237
|
-
runtimeConnectionResolver,
|
|
238
|
-
localSessionResources,
|
|
239
|
-
sessionEmulators,
|
|
240
|
-
shutdownSignal: controlShutdown.signal,
|
|
241
|
-
sessionRuntimeIndex,
|
|
242
|
-
sessionLifecycle,
|
|
243
|
-
runtimeLocalBrowser,
|
|
244
|
-
providerClis,
|
|
245
|
-
}
|
|
246
|
-
: undefined,
|
|
247
|
-
});
|
|
248
|
-
return new Promise((resolve) => {
|
|
249
|
-
const server = app.listen(config.PORT, config.HOST, () => {
|
|
250
|
-
console.log(JSON.stringify({
|
|
251
|
-
level: config.LOG_LEVEL,
|
|
252
|
-
msg: "Harness agent server listening",
|
|
253
|
-
host: config.HOST,
|
|
254
|
-
port: config.PORT,
|
|
255
|
-
runtime: config.AGENT_RUNTIME,
|
|
256
|
-
model: resolveRuntimeModel(config, config.AGENT_RUNTIME),
|
|
257
|
-
}));
|
|
258
|
-
const startup = (async () => {
|
|
259
|
-
await pluginRuntime?.startPluginRuntimes();
|
|
260
|
-
await manager.startAll();
|
|
261
|
-
})();
|
|
262
|
-
void startup.catch((error) => {
|
|
263
|
-
console.error(JSON.stringify({
|
|
264
|
-
level: "error",
|
|
265
|
-
type: "plugin-runtime",
|
|
266
|
-
event: "startup_failed",
|
|
267
|
-
error: error instanceof Error ? error.message : String(error),
|
|
268
|
-
}));
|
|
269
|
-
});
|
|
270
|
-
// Live WS bridges share this http.Server (no second port).
|
|
271
|
-
const webSocketServers = [
|
|
272
|
-
attachTerminalWs(server, {
|
|
273
|
-
runtimeConnectionResolver,
|
|
274
|
-
legacyLocalTerminalHost,
|
|
275
|
-
runtimeWebAccess,
|
|
276
|
-
}),
|
|
277
|
-
attachBrowserSurfaceWs(server, { runtimeConnectionResolver, runtimeWebAccess }),
|
|
278
|
-
attachEmulatorSurfaceWs(server, { runtimeConnectionResolver, runtimeWebAccess }),
|
|
279
|
-
];
|
|
280
|
-
if (desktopBrowserHost && desktopBrowserManagementToken) {
|
|
281
|
-
webSocketServers.push(attachDesktopBrowserHostServer(server, {
|
|
282
|
-
...desktopBrowserHost,
|
|
283
|
-
managementToken: desktopBrowserManagementToken,
|
|
284
|
-
}));
|
|
285
|
-
}
|
|
286
|
-
if (control?.emulator) {
|
|
287
|
-
webSocketServers.push(attachEmulatorTouchWs(server, { emulator: control.emulator }));
|
|
288
|
-
}
|
|
289
|
-
resolve(bindServerLifecycle(server, {
|
|
290
|
-
fence: () => {
|
|
291
|
-
controlShutdown.abort(new Error("Rynx server is shutting down"));
|
|
292
|
-
},
|
|
293
|
-
closeUpgrades: async () => {
|
|
294
|
-
await closeWebSocketServers(webSocketServers);
|
|
295
|
-
},
|
|
296
|
-
cleanup: async () => {
|
|
297
|
-
await runCleanupSteps([
|
|
298
|
-
() => startup.catch(() => undefined),
|
|
299
|
-
() => manager.stopAll(),
|
|
300
|
-
() => Promise.resolve(daemonManagement?.pluginManagement?.dispose?.()),
|
|
301
|
-
() => pluginRuntime?.dispose() ?? Promise.resolve(),
|
|
302
|
-
() => runnerManager.stop(),
|
|
303
|
-
]);
|
|
304
|
-
},
|
|
305
|
-
}));
|
|
306
|
-
});
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
// Core-only mode: no chat instances and no plugin code are required.
|
|
310
|
-
const app = createApp();
|
|
198
|
+
const controlShutdown = new AbortController();
|
|
199
|
+
const app = createApp({
|
|
200
|
+
config,
|
|
201
|
+
control: control
|
|
202
|
+
? {
|
|
203
|
+
deps: control,
|
|
204
|
+
runtime: conversationRuntime,
|
|
205
|
+
sessionBus,
|
|
206
|
+
sessionLog,
|
|
207
|
+
runnerManager,
|
|
208
|
+
sessionStore,
|
|
209
|
+
pluginRuntimeStatus: pluginRuntime
|
|
210
|
+
? () => pluginRuntime.statusSnapshot()
|
|
211
|
+
: undefined,
|
|
212
|
+
daemonManagement,
|
|
213
|
+
remoteRuntime,
|
|
214
|
+
remoteRuntimeAdmin,
|
|
215
|
+
runtimeTargetControl,
|
|
216
|
+
runtimeConnectionResolver,
|
|
217
|
+
localSessionResources,
|
|
218
|
+
localMachineSessions,
|
|
219
|
+
sessionEmulators,
|
|
220
|
+
shutdownSignal: controlShutdown.signal,
|
|
221
|
+
sessionRuntimeIndex,
|
|
222
|
+
sessionLifecycle,
|
|
223
|
+
runtimeLocalBrowser,
|
|
224
|
+
providerClis,
|
|
225
|
+
}
|
|
226
|
+
: undefined,
|
|
227
|
+
});
|
|
311
228
|
return new Promise((resolve) => {
|
|
312
229
|
const server = app.listen(config.PORT, config.HOST, () => {
|
|
313
230
|
console.log(JSON.stringify({
|
|
@@ -318,18 +235,42 @@ export async function startServer({ config = loadConfig(), channelInstances, loa
|
|
|
318
235
|
runtime: config.AGENT_RUNTIME,
|
|
319
236
|
model: resolveRuntimeModel(config, config.AGENT_RUNTIME),
|
|
320
237
|
}));
|
|
321
|
-
const
|
|
238
|
+
const startup = pluginRuntime?.startPluginRuntimes() ?? Promise.resolve();
|
|
239
|
+
void startup.catch((error) => {
|
|
240
|
+
console.error(JSON.stringify({
|
|
241
|
+
level: "error",
|
|
242
|
+
type: "plugin-runtime",
|
|
243
|
+
event: "startup_failed",
|
|
244
|
+
error: error instanceof Error ? error.message : String(error),
|
|
245
|
+
}));
|
|
246
|
+
});
|
|
247
|
+
const webSocketServers = [
|
|
248
|
+
attachTerminalWs(server, {
|
|
249
|
+
runtimeConnectionResolver,
|
|
250
|
+
legacyLocalTerminalHost,
|
|
251
|
+
runtimeWebAccess,
|
|
252
|
+
}),
|
|
253
|
+
attachBrowserSurfaceWs(server, { runtimeConnectionResolver, runtimeWebAccess }),
|
|
254
|
+
attachEmulatorSurfaceWs(server, { runtimeConnectionResolver, runtimeWebAccess }),
|
|
255
|
+
];
|
|
322
256
|
if (desktopBrowserHost && desktopBrowserManagementToken) {
|
|
323
257
|
webSocketServers.push(attachDesktopBrowserHostServer(server, {
|
|
324
258
|
...desktopBrowserHost,
|
|
325
259
|
managementToken: desktopBrowserManagementToken,
|
|
326
260
|
}));
|
|
327
261
|
}
|
|
262
|
+
if (control?.emulator) {
|
|
263
|
+
webSocketServers.push(attachEmulatorTouchWs(server, { emulator: control.emulator }));
|
|
264
|
+
}
|
|
328
265
|
resolve(bindServerLifecycle(server, {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
266
|
+
fence: () => controlShutdown.abort(new Error("Rynx server is shutting down")),
|
|
267
|
+
closeUpgrades: () => closeWebSocketServers(webSocketServers),
|
|
268
|
+
cleanup: async () => runCleanupSteps([
|
|
269
|
+
() => startup.catch(() => undefined),
|
|
270
|
+
() => Promise.resolve(daemonManagement?.pluginManagement?.dispose?.()),
|
|
271
|
+
() => pluginRuntime?.dispose() ?? Promise.resolve(),
|
|
272
|
+
() => runnerManager.stop(),
|
|
273
|
+
]),
|
|
333
274
|
}));
|
|
334
275
|
});
|
|
335
276
|
});
|
|
@@ -12,23 +12,27 @@ export class SessionRuntimeIndex {
|
|
|
12
12
|
case "response.created":
|
|
13
13
|
state.activeResponseIds.add(event.responseId);
|
|
14
14
|
state.status = "running";
|
|
15
|
+
state.statusKind = undefined;
|
|
15
16
|
return;
|
|
16
17
|
case "response.completed":
|
|
17
18
|
state.activeResponseIds.delete(event.responseId);
|
|
18
19
|
this.removeResponseInteractions(state, event.responseId);
|
|
19
20
|
state.status = state.activeResponseIds.size > 0 ? "running" : "idle";
|
|
21
|
+
state.statusKind = undefined;
|
|
20
22
|
return;
|
|
21
23
|
case "response.failed":
|
|
22
24
|
state.activeResponseIds.delete(event.responseId);
|
|
23
25
|
this.removeResponseInteractions(state, event.responseId);
|
|
24
26
|
// Response failure is Turn-local. It must not poison a reusable Session.
|
|
25
27
|
state.status = state.activeResponseIds.size > 0 ? "running" : "idle";
|
|
28
|
+
state.statusKind = undefined;
|
|
26
29
|
return;
|
|
27
30
|
case "session.status":
|
|
28
31
|
state.status =
|
|
29
32
|
state.pendingInteractions.size > 0 || state.activeResponseIds.size > 0
|
|
30
33
|
? "running"
|
|
31
34
|
: event.status;
|
|
35
|
+
state.statusKind = event.statusKind;
|
|
32
36
|
return;
|
|
33
37
|
case "session.interaction.requested":
|
|
34
38
|
state.pendingInteractions.set(event.interaction.interactionId, {
|
|
@@ -37,6 +41,7 @@ export class SessionRuntimeIndex {
|
|
|
37
41
|
});
|
|
38
42
|
state.activeResponseIds.add(event.responseId);
|
|
39
43
|
state.status = "running";
|
|
44
|
+
state.statusKind = undefined;
|
|
40
45
|
return;
|
|
41
46
|
case "session.interaction.resolved":
|
|
42
47
|
case "session.interaction.cancelled":
|
|
@@ -47,6 +52,7 @@ export class SessionRuntimeIndex {
|
|
|
47
52
|
state.activeResponseIds.clear();
|
|
48
53
|
state.pendingInteractions.clear();
|
|
49
54
|
state.status = "idle";
|
|
55
|
+
state.statusKind = undefined;
|
|
50
56
|
return;
|
|
51
57
|
default:
|
|
52
58
|
return;
|
|
@@ -58,6 +64,7 @@ export class SessionRuntimeIndex {
|
|
|
58
64
|
return { status: "idle", activeResponseIds: [], pendingInteractions: [] };
|
|
59
65
|
return {
|
|
60
66
|
status: state.pendingInteractions.size > 0 ? "running" : state.status,
|
|
67
|
+
...(state.statusKind === undefined ? {} : { statusKind: state.statusKind }),
|
|
61
68
|
activeResponseIds: [...state.activeResponseIds],
|
|
62
69
|
pendingInteractions: [...state.pendingInteractions.values()],
|
|
63
70
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rynx-ai/server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11-beta.2",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/rynx-ai/rynx.git",
|
|
@@ -27,15 +27,15 @@
|
|
|
27
27
|
"@koa/router": "^15.4.0",
|
|
28
28
|
"koa": "^3.2.0",
|
|
29
29
|
"ws": "^8.21.0",
|
|
30
|
-
"@rynx-ai/
|
|
31
|
-
"@rynx-ai/
|
|
32
|
-
"@rynx-ai/
|
|
33
|
-
"@rynx-ai/remote-runtime-e2ee": "0.1.
|
|
34
|
-
"@rynx-ai/runtime": "0.1.
|
|
30
|
+
"@rynx-ai/core": "0.1.11-beta.2",
|
|
31
|
+
"@rynx-ai/plugin-sdk": "0.1.11-beta.2",
|
|
32
|
+
"@rynx-ai/protocol": "0.1.11-beta.2",
|
|
33
|
+
"@rynx-ai/remote-runtime-e2ee": "0.1.11-beta.2",
|
|
34
|
+
"@rynx-ai/runtime": "0.1.11-beta.2"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/ws": "^8.18.1",
|
|
38
|
-
"@rynx-ai/control-web": "0.1.
|
|
38
|
+
"@rynx-ai/control-web": "0.1.11-beta.2"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build": "rm -rf dist && tsc -p tsconfig.json && mkdir -p dist/control-web && cp -R ../control-web/dist/. dist/control-web/",
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Runtime manager for mounted channel instances in the single-process control
|
|
3
|
-
* plane. Holds live channel handles keyed by instance id and can start / stop /
|
|
4
|
-
* reload a single instance without restarting the daemon — the seam the web
|
|
5
|
-
* control page drives.
|
|
6
|
-
*
|
|
7
|
-
* Shared pieces (host/conversationRuntime/codex session store) are injected once
|
|
8
|
-
* and reused across instances; only the per-instance {@link ChannelContext}
|
|
9
|
-
* fields (instanceId / options / defaultAgent) differ, so two Lark bots get
|
|
10
|
-
* distinct credentials + state while sharing one agent runtime.
|
|
11
|
-
*/
|
|
12
|
-
import type { AgentCapabilities, AgentSessionStore, AppConfig, ChannelInstanceDescriptor, ConversationRuntime, SessionBus, SessionLogStore, SessionRegistry } from "@rynx-ai/core";
|
|
13
|
-
export interface ChannelInstanceStatus {
|
|
14
|
-
instanceId: string;
|
|
15
|
-
type: string;
|
|
16
|
-
running: boolean;
|
|
17
|
-
agent?: string;
|
|
18
|
-
/** Connection state from the channel, or null when it exposes no status. */
|
|
19
|
-
connected: boolean | null;
|
|
20
|
-
lastError?: string | null;
|
|
21
|
-
lastEventAt?: string | null;
|
|
22
|
-
}
|
|
23
|
-
export interface ChannelManagerOptions {
|
|
24
|
-
config: AppConfig;
|
|
25
|
-
conversationRuntime: ConversationRuntime;
|
|
26
|
-
capabilities: AgentCapabilities;
|
|
27
|
-
sessionStore: AgentSessionStore;
|
|
28
|
-
/** Durable canonical session log, shared across instances (absent ⇒ no
|
|
29
|
-
* persistence). */
|
|
30
|
-
sessionLog?: SessionLogStore;
|
|
31
|
-
/** Shared canonical session event bus (one instance ⇒ cross-channel fan-out). */
|
|
32
|
-
sessionBus?: SessionBus;
|
|
33
|
-
/** Unified machine-session registry, shared across instances; channels register
|
|
34
|
-
* their sessions' identity rows here so the control plane lists them. */
|
|
35
|
-
sessionRegistry?: SessionRegistry;
|
|
36
|
-
/** Source of truth for current instance descriptors (daemon reads config). */
|
|
37
|
-
loadInstances: () => Promise<ChannelInstanceDescriptor[]>;
|
|
38
|
-
log?: (line: string) => void;
|
|
39
|
-
}
|
|
40
|
-
export declare class ChannelManager {
|
|
41
|
-
private readonly opts;
|
|
42
|
-
private readonly mounted;
|
|
43
|
-
constructor(opts: ChannelManagerOptions);
|
|
44
|
-
/** Mount + start every enabled instance from `loadInstances`. */
|
|
45
|
-
startAll(): Promise<void>;
|
|
46
|
-
/** Stop every mounted instance (on server close). */
|
|
47
|
-
stopAll(): Promise<void>;
|
|
48
|
-
/** Live status of currently-mounted instances. */
|
|
49
|
-
list(): ChannelInstanceStatus[];
|
|
50
|
-
isRunning(instanceId: string): boolean;
|
|
51
|
-
/** Start one instance by id (re-reads descriptors). No-op if already running. */
|
|
52
|
-
startInstance(instanceId: string): Promise<void>;
|
|
53
|
-
/** Stop + unmount one instance. No-op if not running. */
|
|
54
|
-
stopInstance(instanceId: string): Promise<void>;
|
|
55
|
-
/** Stop then start, picking up edited options/agent. */
|
|
56
|
-
reloadInstance(instanceId: string): Promise<void>;
|
|
57
|
-
private mountAndStart;
|
|
58
|
-
private buildContext;
|
|
59
|
-
private log;
|
|
60
|
-
}
|