@rynx-ai/server 0.1.11-beta.3 → 0.1.11-beta.5

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.
@@ -7,8 +7,8 @@
7
7
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
8
8
  <link rel="icon" type="image/png" href="/favicon.png" />
9
9
  <title>rynx · control</title>
10
- <script type="module" crossorigin src="/assets/index-BnX7NWJX.js"></script>
11
- <link rel="stylesheet" crossorigin href="/assets/index-CUoWRX2i.css">
10
+ <script type="module" crossorigin src="/assets/index-D56JQ9oi.js"></script>
11
+ <link rel="stylesheet" crossorigin href="/assets/index-5n6D-i-c.css">
12
12
  </head>
13
13
  <body>
14
14
  <div id="root"></div>
@@ -1,8 +1,8 @@
1
1
  import { type AdmissionReservation, type AgentRuntimeId, type ConversationRuntime, type ResolvedExecutionSnapshot, type SessionWorkspaceSnapshot, type SessionProviderId, type MachineSessionRecord, type ReasoningEffort, type RuntimeUserInput, type SessionBus, type SessionLogStore, type SessionRegistry } from "@rynx-ai/core";
2
2
  import type { SequencedSessionEvent, SessionEvent, SessionInteractionResolution, SessionItem, UserContentPart } from "@rynx-ai/protocol";
3
3
  import type { RemoteRuntimeSessionResourceDeleteParams, RemoteRuntimeSessionResourceDeleteResult, RemoteRuntimeSessionResourceGetParams, RemoteRuntimeSessionResourceGetResult, RemoteRuntimeSessionResourcePolicyResult, RemoteRuntimeSessionResourceReadParams, RemoteRuntimeSessionResourceReadResult, RemoteRuntimeSessionResourceUploadBeginParams, RemoteRuntimeSessionResourceUploadBeginResult, RemoteRuntimeSessionResourceUploadChunkParams, RemoteRuntimeSessionResourceUploadChunkResult, RemoteRuntimeSessionResourceUploadCommitParams, RemoteRuntimeSessionResourceUploadCommitResult } from "@rynx-ai/protocol/remote-runtime-rpc";
4
- import type { ControlAgentSummary, ControlSessionInteractionResolveDisposition, ControlSessionRuntimeSnapshot } from "@rynx-ai/protocol/control";
5
- import { type RemoteRuntimeSessionInterruptResult, type RemoteRuntimeSessionLaunchOptionsListResult, type RemoteRuntimeSessionListParams, type RemoteRuntimeSessionListResult, type RemoteRuntimeSessionSnapshotParams } from "@rynx-ai/protocol/remote-runtime-rpc";
4
+ import type { ControlAgentModelOption, ControlAgentSummary, ControlSessionInteractionResolveDisposition, ControlSessionRuntimeSnapshot, SessionPermissionPreset } from "@rynx-ai/protocol/control";
5
+ import { type RemoteRuntimeSessionInterruptResult, type RemoteRuntimeSessionExecutionGetResult, type RemoteRuntimeSessionExecutionUpdateParams, type RemoteRuntimeSessionExecutionUpdateResult, type RemoteRuntimeSessionLaunchOptionsListResult, type RemoteRuntimeSessionListParams, type RemoteRuntimeSessionListResult, type RemoteRuntimeSessionSnapshotParams } from "@rynx-ai/protocol/remote-runtime-rpc";
6
6
  import type { CodexRuntimeStatus, InjectOutcome } from "@rynx-ai/runtime";
7
7
  export interface MachineSessionRuntimeStatePort {
8
8
  snapshot(sessionId: string): ControlSessionRuntimeSnapshot;
@@ -130,7 +130,7 @@ export interface MachineSessionForkStorePort {
130
130
  markTargetDeleted(sessionId: string): void | Promise<void>;
131
131
  }
132
132
  export interface MachineSessionServicePorts {
133
- registry: Pick<SessionRegistry, "create" | "get" | "list" | "setTitle" | "remove">;
133
+ registry: Pick<SessionRegistry, "create" | "get" | "list" | "setTitle" | "setExecution" | "remove">;
134
134
  log: Pick<SessionLogStore, "list" | "listSessions" | "snapshot" | "deleteSession">;
135
135
  events: Pick<SessionBus, "subscribe"> & Partial<Pick<SessionBus, "close">>;
136
136
  /** Canonical persistence + fan-out for user turns accepted before a native
@@ -156,8 +156,10 @@ export interface MachineSessionServicePorts {
156
156
  provider?: SessionProviderId;
157
157
  model?: string;
158
158
  reasoningEffort?: ReasoningEffort;
159
+ permissionPreset?: SessionPermissionPreset;
159
160
  cwd: string;
160
161
  }): Promise<ResolvedExecutionSnapshot>;
162
+ listModels?(provider: SessionProviderId): Promise<ControlAgentModelOption[]>;
161
163
  runner: MachineSessionRunnerPort;
162
164
  };
163
165
  /** Resolve a temporary Project selection, or create a Session-only fallback directory. */
@@ -206,6 +208,7 @@ export type MachineSessionInterruptResult = RemoteRuntimeSessionInterruptResult;
206
208
  interface MachineSessionCreateOptions {
207
209
  model?: string;
208
210
  reasoningEffort?: ReasoningEffort;
211
+ permissionPreset?: SessionPermissionPreset;
209
212
  title?: string;
210
213
  projectId?: string;
211
214
  }
@@ -306,6 +309,12 @@ export declare class MachineSessionService {
306
309
  }>;
307
310
  /** Target-owned Provider readiness plus the existing Agent preset catalog. */
308
311
  launchOptions(): Promise<RemoteRuntimeSessionLaunchOptionsListResult>;
312
+ /** Read the effective model defaults used for the next turn. */
313
+ executionSettings(sessionIdInput: string): Promise<RemoteRuntimeSessionExecutionGetResult>;
314
+ /** Replace only the model defaults of an idle Session. The runner is closed
315
+ * so every Provider resumes its native context with the new settings on the
316
+ * next turn. */
317
+ updateExecutionSettings(input: RemoteRuntimeSessionExecutionUpdateParams): Promise<RemoteRuntimeSessionExecutionUpdateResult>;
309
318
  /** Create target-owned Session identity from one Agent preset or direct Provider. */
310
319
  create(input: MachineSessionCreateInput): Promise<MachineSessionCreateResult>;
311
320
  private createAdmitted;
@@ -159,11 +159,18 @@ export class MachineSessionService {
159
159
  const statusCache = new Map();
160
160
  const { agents } = await this.agentOptions();
161
161
  const [providers, launchAgents] = await Promise.all([
162
- Promise.all(SESSION_PROVIDER_IDS.map(async (provider) => ({
163
- id: provider,
164
- name: getRuntimeProfile(provider).displayName,
165
- ...await this.runtimeReadiness(provider, statusCache),
166
- }))),
162
+ Promise.all(SESSION_PROVIDER_IDS.map(async (provider) => {
163
+ const execution = this.ports.execution;
164
+ const models = execution?.listModels
165
+ ? await execution.listModels(provider).catch(() => [])
166
+ : undefined;
167
+ return {
168
+ id: provider,
169
+ name: getRuntimeProfile(provider).displayName,
170
+ ...await this.runtimeReadiness(provider, statusCache),
171
+ ...(models === undefined ? {} : { models }),
172
+ };
173
+ })),
167
174
  Promise.all(agents.map(async (agent) => {
168
175
  const execution = this.ports.execution;
169
176
  if (!execution) {
@@ -192,6 +199,59 @@ export class MachineSessionService {
192
199
  ]);
193
200
  return { providers, agents: launchAgents };
194
201
  }
202
+ /** Read the effective model defaults used for the next turn. */
203
+ async executionSettings(sessionIdInput) {
204
+ const sessionId = validOpaqueToken(sessionIdInput, "sessionId", MAX_SESSION_ID_CHARS);
205
+ const meta = this.ports.registry.get(sessionId);
206
+ if (!meta) {
207
+ throw new MachineSessionServiceFailure("not_found", "session not found");
208
+ }
209
+ return executionSettingsResult(meta.execution);
210
+ }
211
+ /** Replace only the model defaults of an idle Session. The runner is closed
212
+ * so every Provider resumes its native context with the new settings on the
213
+ * next turn. */
214
+ async updateExecutionSettings(input) {
215
+ const sessionId = validOpaqueToken(input.sessionId, "sessionId", MAX_SESSION_ID_CHARS);
216
+ const modelId = validRequiredText(input.model, "model");
217
+ const meta = this.ports.registry.get(sessionId);
218
+ if (!meta) {
219
+ throw new MachineSessionServiceFailure("not_found", "session not found");
220
+ }
221
+ await this.assertNotForkReserved(sessionId);
222
+ const runtime = this.ports.runtimeState.snapshot(sessionId);
223
+ const pendingMessage = await this.ports.pendingMessages?.get(sessionId);
224
+ if (runtime.status !== "idle" ||
225
+ runtime.activeResponseIds.length > 0 ||
226
+ runtime.pendingInteractions.length > 0 ||
227
+ pendingMessage) {
228
+ throw new MachineSessionServiceFailure("failed_precondition", "Session must be idle before changing model settings");
229
+ }
230
+ const executionPort = this.requireExecution();
231
+ if (!executionPort.listModels) {
232
+ throw new MachineSessionServiceFailure("failed_precondition", "Runtime model catalog is unavailable");
233
+ }
234
+ const models = await executionPort.listModels(meta.execution.provider);
235
+ const model = models.find((candidate) => candidate.id === modelId);
236
+ if (!model) {
237
+ throw new MachineSessionServiceInputError(`model is not available for ${meta.execution.provider}`);
238
+ }
239
+ const reasoningEffort = input.reasoningEffort === null
240
+ ? null
241
+ : validRequiredText(input.reasoningEffort, "reasoningEffort");
242
+ if (reasoningEffort !== null &&
243
+ !model.reasoningOptions.some((option) => option.value === reasoningEffort)) {
244
+ throw new MachineSessionServiceInputError(`reasoningEffort is not available for model ${model.id}`);
245
+ }
246
+ const nextExecution = {
247
+ ...structuredClone(meta.execution),
248
+ model: model.id,
249
+ reasoningEffort,
250
+ };
251
+ this.ports.registry.setExecution(sessionId, nextExecution);
252
+ executionPort.runner.stopRunner(sessionId);
253
+ return executionSettingsResult(nextExecution);
254
+ }
195
255
  /** Create target-owned Session identity from one Agent preset or direct Provider. */
196
256
  async create(input) {
197
257
  return this.withAdmission(() => this.createAdmitted(input));
@@ -223,6 +283,7 @@ export class MachineSessionService {
223
283
  ...target,
224
284
  ...(input.model === undefined ? {} : { model: input.model }),
225
285
  ...(input.reasoningEffort === undefined ? {} : { reasoningEffort: input.reasoningEffort }),
286
+ ...(input.permissionPreset === undefined ? {} : { permissionPreset: input.permissionPreset }),
226
287
  cwd: workspace.cwd,
227
288
  });
228
289
  const sessionId = newSessionId();
@@ -997,6 +1058,13 @@ function sessionSummary(id, meta, log, runtimeState, pendingState) {
997
1058
  updatedAt: validTimestamp(updatedAt, "updatedAt"),
998
1059
  };
999
1060
  }
1061
+ function executionSettingsResult(execution) {
1062
+ return {
1063
+ provider: execution.provider,
1064
+ model: execution.model,
1065
+ reasoningEffort: execution.reasoningEffort,
1066
+ };
1067
+ }
1000
1068
  function compareMetaRecency(left, right) {
1001
1069
  const leftTime = validTimestamp(left.updatedAt ?? left.createdAt, "updatedAt");
1002
1070
  const rightTime = validTimestamp(right.updatedAt ?? right.createdAt, "updatedAt");
@@ -1091,6 +1159,15 @@ function validOpaqueToken(value, field, maximum) {
1091
1159
  }
1092
1160
  return value;
1093
1161
  }
1162
+ function validRequiredText(value, field) {
1163
+ if (typeof value !== "string" || value.trim().length === 0 || value.length > 512) {
1164
+ throw new MachineSessionServiceInputError(`${field} must be a non-empty string of at most 512 characters`);
1165
+ }
1166
+ if (/[\u0000-\u001f\u007f]/.test(value)) {
1167
+ throw new MachineSessionServiceInputError(`${field} contains invalid control characters`);
1168
+ }
1169
+ return value.trim();
1170
+ }
1094
1171
  function validTimestamp(value, field) {
1095
1172
  if (typeof value !== "string" || !Number.isFinite(Date.parse(value))) {
1096
1173
  throw new MachineSessionServiceInputError(`${field} must be a valid timestamp`);
@@ -34,7 +34,7 @@ export interface RemoteRuntimeProjectHost {
34
34
  update(projectId: string, input: RemoteRuntimeProjectCreateParams): RemoteRuntimeProject | undefined | Promise<RemoteRuntimeProject | undefined>;
35
35
  remove(projectId: string): boolean | Promise<boolean>;
36
36
  }
37
- export type RemoteRuntimeSessionHost = Pick<MachineSessionService, "list" | "snapshot" | "watch" | "interrupt" | "agentOptions" | "launchOptions" | "create" | "fork" | "sendMessage" | "resourcePolicy" | "beginResourceUpload" | "writeResourceUploadChunk" | "commitResourceUpload" | "getResource" | "readResource" | "deleteResource" | "enqueueMessage" | "startTerminal" | "delete" | "resolveInteraction">;
37
+ export type RemoteRuntimeSessionHost = Pick<MachineSessionService, "list" | "snapshot" | "watch" | "interrupt" | "agentOptions" | "launchOptions" | "executionSettings" | "updateExecutionSettings" | "create" | "fork" | "sendMessage" | "resourcePolicy" | "beginResourceUpload" | "writeResourceUploadChunk" | "commitResourceUpload" | "getResource" | "readResource" | "deleteResource" | "enqueueMessage" | "startTerminal" | "delete" | "resolveInteraction">;
38
38
  export type RemoteRuntimeBrowserHost = Pick<SessionBrowserService, "getState" | "open" | "close" | "createPage" | "closePage" | "activatePage" | "navigatePage" | "goBack" | "goForward" | "reload">;
39
39
  export type RemoteRuntimeSessionEmulatorHost = Pick<SessionEmulatorService, "getState" | "listDevices" | "attach" | "detach" | "tap" | "type" | "button" | "rotate" | "launch" | "gesture" | "releaseDevice" | "stopDevice">;
40
40
  export interface OpenRemoteRuntimeSessionEvents {
@@ -125,6 +125,10 @@ export class RemoteRuntimeDispatcher {
125
125
  return await this.withSessions(request, (sessions) => sessions.agentOptions());
126
126
  case "session.launchOptions.list":
127
127
  return await this.withSessions(request, (sessions) => sessions.launchOptions());
128
+ case "session.execution.get":
129
+ return await this.withSessions(request, (sessions) => sessions.executionSettings(request.params.sessionId));
130
+ case "session.execution.update":
131
+ return await this.withSessions(request, (sessions) => sessions.updateExecutionSettings(request.params));
128
132
  case "session.create":
129
133
  return await this.withSessions(request, (sessions) => sessions.create(request.params));
130
134
  case "session.fork":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rynx-ai/server",
3
- "version": "0.1.11-beta.3",
3
+ "version": "0.1.11-beta.5",
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/plugin-sdk": "0.1.11-beta.3",
31
- "@rynx-ai/protocol": "0.1.11-beta.3",
32
- "@rynx-ai/core": "0.1.11-beta.3",
33
- "@rynx-ai/remote-runtime-e2ee": "0.1.11-beta.3",
34
- "@rynx-ai/runtime": "0.1.11-beta.3"
30
+ "@rynx-ai/core": "0.1.11-beta.5",
31
+ "@rynx-ai/plugin-sdk": "0.1.11-beta.5",
32
+ "@rynx-ai/protocol": "0.1.11-beta.5",
33
+ "@rynx-ai/remote-runtime-e2ee": "0.1.11-beta.5",
34
+ "@rynx-ai/runtime": "0.1.11-beta.5"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@types/ws": "^8.18.1",
38
- "@rynx-ai/control-web": "0.1.11-beta.3"
38
+ "@rynx-ai/control-web": "0.1.11-beta.5"
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/",