@rynx-ai/server 0.1.11-beta.21 → 0.1.11-beta.23

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,7 +7,7 @@
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-dOafa0IY.js"></script>
10
+ <script type="module" crossorigin src="/assets/index-D-5t2eCT.js"></script>
11
11
  <link rel="stylesheet" crossorigin href="/assets/index-0noHpRXD.css">
12
12
  </head>
13
13
  <body>
@@ -1,12 +1,11 @@
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";
1
+ import { type AdmissionReservation, type AgentRuntimeId, type ConversationRuntime, type ResolvedExecutionSnapshot, type SessionWorkspaceSnapshot, type SessionProviderId, type MachineSessionRecord, type LiveSessionFailure, 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
4
  import type { ControlAgentModelOption, ControlAgentSummary, ControlSessionInteractionResolveDisposition, ControlSessionRuntimeSnapshot, SessionPermissionPreset } from "@rynx-ai/protocol/control";
5
5
  import { type RemoteRuntimeSessionInterruptResult, type RemoteRuntimeSessionExecutionGetResult, type RemoteRuntimeSessionExecutionUpdateParams, type RemoteRuntimeSessionExecutionUpdateResult, type RemoteRuntimeSessionLaunchOptionsListResult, type RemoteRuntimeSessionListParams, type RemoteRuntimeSessionListResult, type RemoteRuntimeSessionSnapshotParams } from "@rynx-ai/protocol/remote-runtime-rpc";
6
- import type { CodexRuntimeStatus, InjectOutcome } from "@rynx-ai/runtime";
6
+ import type { CodexRuntimeStatus, InjectResult } from "@rynx-ai/runtime";
7
7
  export interface MachineSessionRuntimeStatePort {
8
8
  snapshot(sessionId: string): ControlSessionRuntimeSnapshot;
9
- beginResponseHandoff?(sessionId: string, responseId: string): () => void;
10
9
  remove?(sessionId: string): void;
11
10
  }
12
11
  export interface MachineSessionInterruptPort {
@@ -68,7 +67,8 @@ export interface MachineSessionRunnerPort {
68
67
  execution?: ResolvedExecutionSnapshot;
69
68
  }): Promise<boolean>;
70
69
  lastLiveSessionError?(sessionId: string): string | undefined;
71
- injectMessage(sessionId: string, input: RuntimeUserInput | string): Promise<InjectOutcome>;
70
+ lastLiveSessionFailure?(sessionId: string): LiveSessionFailure | undefined;
71
+ injectMessage(sessionId: string, input: RuntimeUserInput | string): Promise<InjectResult>;
72
72
  stopRunner(sessionId: string): void;
73
73
  resolveInteraction(sessionId: string, interactionId: string, resolution: SessionInteractionResolution): Promise<{
74
74
  disposition: ControlSessionInteractionResolveDisposition;
@@ -275,7 +275,8 @@ export type MachineSessionServiceFailureCode = "not_found" | "failed_preconditio
275
275
  export declare class MachineSessionServiceFailure extends Error {
276
276
  readonly code: MachineSessionServiceFailureCode;
277
277
  readonly detail?: string | undefined;
278
- constructor(code: MachineSessionServiceFailureCode, message: string, detail?: string | undefined);
278
+ readonly runtimeFailure?: LiveSessionFailure | undefined;
279
+ constructor(code: MachineSessionServiceFailureCode, message: string, detail?: string | undefined, runtimeFailure?: LiveSessionFailure | undefined);
279
280
  }
280
281
  /** Application boundary shared by an in-process Local adapter and Direct RPC. */
281
282
  export declare class MachineSessionService {
@@ -7,8 +7,8 @@
7
7
  * Direct adapters can therefore expose the same behavior without copying state
8
8
  * into a Control Plane database.
9
9
  */
10
- import { createHash, randomUUID } from "node:crypto";
11
- import { SESSION_PROVIDER_IDS, getRuntimeProfile, isSessionProviderId, newSessionItemId, newSessionId, normalizeSessionTitle, } from "@rynx-ai/core";
10
+ import { createHash } from "node:crypto";
11
+ import { SESSION_PROVIDER_IDS, getRuntimeProfile, isSessionProviderId, newSessionId, normalizeSessionTitle, } from "@rynx-ai/core";
12
12
  import { REMOTE_RUNTIME_SESSION_DEFAULT_PAGE_SIZE, REMOTE_RUNTIME_SESSION_MAX_CURSOR_CHARS, REMOTE_RUNTIME_SESSION_MAX_ID_CHARS, REMOTE_RUNTIME_SESSION_MAX_PAGE_SIZE, } from "@rynx-ai/protocol/remote-runtime-rpc";
13
13
  const DEFAULT_LIST_LIMIT = REMOTE_RUNTIME_SESSION_DEFAULT_PAGE_SIZE;
14
14
  const MAX_LIST_LIMIT = REMOTE_RUNTIME_SESSION_MAX_PAGE_SIZE;
@@ -31,10 +31,12 @@ export class MachineSessionServiceInputError extends Error {
31
31
  export class MachineSessionServiceFailure extends Error {
32
32
  code;
33
33
  detail;
34
- constructor(code, message, detail) {
34
+ runtimeFailure;
35
+ constructor(code, message, detail, runtimeFailure) {
35
36
  super(message);
36
37
  this.code = code;
37
38
  this.detail = detail;
39
+ this.runtimeFailure = runtimeFailure;
38
40
  this.name = "MachineSessionServiceFailure";
39
41
  }
40
42
  }
@@ -506,93 +508,51 @@ export class MachineSessionService {
506
508
  if (request.clientMessageId) {
507
509
  await resources?.markMessageInjecting(sessionId, request.clientMessageId);
508
510
  }
509
- const responseId = this.ports.publishEvent ? `resp_${randomUUID()}` : undefined;
510
- if (responseId) {
511
- await this.ports.publishEvent(sessionId, {
512
- type: "session.input.consumed",
513
- item: {
514
- id: newSessionItemId("message"),
515
- sessionId,
516
- position: 0,
517
- responseId,
518
- status: "completed",
519
- createdAt: Date.now(),
520
- type: "message",
521
- data: {
522
- role: "user",
523
- content: prepared.input.content.map((part) => part.type === "text"
524
- ? { type: "input_text", text: part.text }
525
- : { ...part.resource }),
526
- },
527
- },
528
- });
529
- await this.ports.publishEvent(sessionId, {
530
- type: "session.status",
531
- sessionId,
532
- responseId,
533
- status: "running",
534
- statusKind: "startup",
535
- });
536
- }
537
- const abandonResponseHandoff = responseId
538
- ? this.ports.runtimeState.beginResponseHandoff?.(sessionId, responseId)
539
- : undefined;
540
- const clearStartup = async (status) => {
541
- if (!responseId)
542
- return;
543
- await this.ports.publishEvent(sessionId, {
544
- type: "session.status",
545
- sessionId,
546
- responseId,
547
- status,
548
- });
549
- };
550
511
  let execution;
551
512
  try {
552
513
  execution = await this.ensureLiveSession(sessionId, meta);
553
514
  }
554
515
  catch (error) {
555
- abandonResponseHandoff?.();
556
- await clearStartup("idle");
557
516
  if (request.clientMessageId) {
558
517
  await resources?.markMessageFailedNotStarted(sessionId, request.clientMessageId, error instanceof Error ? error.message : String(error));
559
518
  }
560
519
  throw error;
561
520
  }
562
- let outcome;
521
+ let result;
563
522
  try {
564
- const runtimeInput = responseId
565
- ? { ...prepared.input, responseId }
566
- : prepared.input;
567
- outcome = await execution.runner.injectMessage(sessionId, responseId || needsPreparedOperation ? runtimeInput : request.message);
523
+ result = await execution.runner.injectMessage(sessionId, needsPreparedOperation ? prepared.input : request.message);
568
524
  }
569
525
  catch (error) {
570
- abandonResponseHandoff?.();
571
- await clearStartup("idle");
526
+ const failure = execution.runner.lastLiveSessionFailure?.(sessionId)
527
+ ?? liveSessionFailureFrom(error);
528
+ const reason = failure?.message
529
+ ?? (error instanceof Error ? error.message : String(error));
572
530
  if (request.clientMessageId) {
573
- await Promise.resolve(resources?.markMessageOutcomeUnknown(sessionId, request.clientMessageId, error instanceof Error ? error.message : String(error))).catch(() => undefined);
531
+ await Promise.resolve(resources?.markMessageOutcomeUnknown(sessionId, request.clientMessageId, reason)).catch(() => undefined);
574
532
  }
575
- throw new MachineSessionServiceFailure("outcome_unknown", "live injection outcome is unknown");
533
+ throw new MachineSessionServiceFailure("outcome_unknown", "live injection outcome is unknown", reason, failure);
576
534
  }
535
+ const outcome = result.outcome;
577
536
  if (outcome === "failed") {
578
- abandonResponseHandoff?.();
579
- await clearStartup("idle");
537
+ const failure = execution.runner.lastLiveSessionFailure?.(sessionId);
538
+ const reason = failure?.message
539
+ ?? execution.runner.lastLiveSessionError?.(sessionId)
540
+ ?? `live injection ${outcome}`;
580
541
  if (request.clientMessageId) {
581
- await resources?.markMessageOutcomeUnknown(sessionId, request.clientMessageId, `live injection ${outcome}`);
542
+ await resources?.markMessageOutcomeUnknown(sessionId, request.clientMessageId, reason);
582
543
  }
583
- throw new MachineSessionServiceFailure("outcome_unknown", `live injection ${outcome}`);
544
+ throw new MachineSessionServiceFailure("outcome_unknown", `live injection ${outcome}`, reason, failure);
584
545
  }
585
546
  if (outcome !== "injected" && outcome !== "steered") {
586
- abandonResponseHandoff?.();
587
- await clearStartup("idle");
547
+ const failure = execution.runner.lastLiveSessionFailure?.(sessionId);
548
+ const reason = failure?.message
549
+ ?? execution.runner.lastLiveSessionError?.(sessionId)
550
+ ?? `live injection ${outcome}`;
588
551
  if (request.clientMessageId) {
589
- await resources?.markMessageFailedNotStarted(sessionId, request.clientMessageId, `live injection ${outcome}`);
552
+ await resources?.markMessageFailedNotStarted(sessionId, request.clientMessageId, reason);
590
553
  }
591
- throw new MachineSessionServiceFailure("failed_precondition", `live injection ${outcome}`);
554
+ throw new MachineSessionServiceFailure("failed_precondition", `live injection ${outcome}`, reason, failure);
592
555
  }
593
- if (outcome === "steered")
594
- abandonResponseHandoff?.();
595
- await clearStartup("running");
596
556
  if (request.clientMessageId) {
597
557
  try {
598
558
  await resources?.markMessageInjected(sessionId, request.clientMessageId);
@@ -679,7 +639,8 @@ export class MachineSessionService {
679
639
  request.execution.runner.ensureLiveSession.bind(request.execution.runner);
680
640
  const started = await start(sessionId, request.options);
681
641
  if (!started) {
682
- throw new MachineSessionServiceFailure("failed_precondition", `Provider terminal unavailable (${request.liveRuntime})`, request.execution.runner.lastLiveSessionError?.(sessionId));
642
+ const failure = request.execution.runner.lastLiveSessionFailure?.(sessionId);
643
+ throw new MachineSessionServiceFailure("failed_precondition", `Provider terminal unavailable (${request.liveRuntime})`, failure?.message ?? request.execution.runner.lastLiveSessionError?.(sessionId), failure);
683
644
  }
684
645
  return { ok: true };
685
646
  }
@@ -687,7 +648,8 @@ export class MachineSessionService {
687
648
  const request = await this.liveSessionRequest(sessionId, meta);
688
649
  const live = await request.execution.runner.ensureLiveSession(sessionId, request.options);
689
650
  if (!live) {
690
- throw new MachineSessionServiceFailure("failed_precondition", `live session unavailable (${request.liveRuntime})`, request.execution.runner.lastLiveSessionError?.(sessionId));
651
+ const failure = request.execution.runner.lastLiveSessionFailure?.(sessionId);
652
+ throw new MachineSessionServiceFailure("failed_precondition", `live session unavailable (${request.liveRuntime})`, failure?.message ?? request.execution.runner.lastLiveSessionError?.(sessionId), failure);
691
653
  }
692
654
  return request.execution;
693
655
  }
@@ -822,7 +784,7 @@ export class MachineSessionService {
822
784
  current.message !== pending.message)
823
785
  return;
824
786
  injectionAttempted = true;
825
- const outcome = await execution.runner.injectMessage(sessionId, pending.message);
787
+ const { outcome } = await execution.runner.injectMessage(sessionId, pending.message);
826
788
  if (outcome === "injected" || outcome === "steered") {
827
789
  await Promise.resolve(pendingStore.delete(sessionId)).catch(async () => {
828
790
  await Promise.resolve(pendingStore.markOutcomeUnknown(sessionId)).catch(() => undefined);
@@ -1132,6 +1094,20 @@ function cloneRuntimeSnapshot(snapshot) {
1132
1094
  })),
1133
1095
  };
1134
1096
  }
1097
+ function liveSessionFailureFrom(error) {
1098
+ if (!error || typeof error !== "object")
1099
+ return undefined;
1100
+ const candidate = error;
1101
+ if (typeof candidate.message !== "string" ||
1102
+ typeof candidate.code !== "string" ||
1103
+ typeof candidate.statusCode !== "number")
1104
+ return undefined;
1105
+ return {
1106
+ message: candidate.message,
1107
+ code: candidate.code,
1108
+ statusCode: candidate.statusCode,
1109
+ };
1110
+ }
1135
1111
  function requestLimit(value, fallback, maximum, field) {
1136
1112
  return value === undefined ? Math.min(fallback, maximum) : boundedInteger(value, 1, maximum, field);
1137
1113
  }
@@ -347,7 +347,10 @@ function mapHostError(request, error) {
347
347
  : error.code === "conflict"
348
348
  ? "Remote Session resource conflicts with existing state"
349
349
  : "Remote Session operation may have been applied";
350
- return { code: error.code, message };
350
+ // Native lifecycle failures are already reduced to a user-safe phase and
351
+ // concrete Provider cause. Preserve that text over Direct Runtime so the
352
+ // remote UI does not collapse every startup failure into one wrapper.
353
+ return { code: error.code, message: error.runtimeFailure?.message ?? message };
351
354
  }
352
355
  if (request.method === "session.interrupt") {
353
356
  return {
@@ -534,6 +534,7 @@ function assertEventScope(event, expectedSessionId) {
534
534
  case "session.interaction.requested":
535
535
  case "session.interaction.resolved":
536
536
  case "session.interaction.cancelled":
537
+ case "session.interrupted":
537
538
  case "session.todos":
538
539
  case "session.rotated":
539
540
  actual = event.sessionId;
package/dist/server.d.ts CHANGED
@@ -4,7 +4,7 @@ import { ConversationRuntime, type AdmissionReservation, type AgentCapabilities,
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
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
+ import type { PluginAgentSummary, PluginJsonValue, PluginResolvedSessionExecution, PluginSessionActivitySnapshot, PluginSessionExecutionSnapshot } from "@rynx-ai/plugin-sdk";
8
8
  import type { PairingOffer } from "@rynx-ai/protocol/direct-runtime";
9
9
  import type { DaemonStatus } from "@rynx-ai/protocol/remote-runtime";
10
10
  import type { RuntimeBrowserBootstrapCredential, RuntimeBrowserEndpointDescriptor } from "@rynx-ai/protocol/runtime-browser-bootstrap";
@@ -12,7 +12,6 @@ import type { RuntimeBrowserInspectMessage, RuntimeBrowserInspectTarget } from "
12
12
  import type { RuntimeBrowserSurfaceClientFrame, RuntimeBrowserSurfaceImageFrame, RuntimeBrowserSurfaceOpenFrame, RuntimeBrowserSurfaceReadyFrame, RuntimeBrowserSurfaceServerFrame } from "@rynx-ai/protocol/runtime-browser-surface";
13
13
  import type { RuntimeEmulatorSurfaceImageFrame, RuntimeEmulatorSurfaceReadyFrame } from "@rynx-ai/protocol/runtime-emulator-surface";
14
14
  import type { RemoteRuntimeRpcMethod, RemoteRuntimeRpcParams, RemoteRuntimeRpcResultFor, RemoteRuntimeSequencedSessionEvent } from "@rynx-ai/protocol/remote-runtime-rpc";
15
- import type { PluginAgentSummary, PluginResolvedSessionExecution, PluginSessionExecutionSnapshot } from "@rynx-ai/plugin-sdk";
16
15
  import { RunnerManager, type CodexSessionStore, type RunnerSessionContextProvider } from "@rynx-ai/runtime";
17
16
  import { type ControlPlaneDeps, type LocalSessionResourceHost, type SessionResourceLifecycle } from "./control-api.js";
18
17
  import type { MachineSessionService } from "./machine-session-service.js";
@@ -160,6 +159,7 @@ export interface PluginRuntimeHostServices {
160
159
  session: PluginSessionExecutionSnapshot;
161
160
  }): Promise<PluginResolvedSessionExecution>;
162
161
  };
162
+ sessionActivity(sessionId: string): PluginSessionActivitySnapshot;
163
163
  interruptSession(sessionId: string): Promise<boolean>;
164
164
  terminateSession?(sessionId: string): Promise<boolean>;
165
165
  resolveSessionInteraction(sessionId: string, interactionId: string, resolution: SessionInteractionResolution): Promise<{
@@ -350,7 +350,7 @@ export interface RuntimeConnectionLease {
350
350
  };
351
351
  call<M extends RemoteRuntimeRpcMethod>(method: M, params: RemoteRuntimeRpcParams<M>, options?: {
352
352
  signal?: AbortSignal;
353
- timeoutMs?: number;
353
+ timeoutMs?: number | null;
354
354
  }): Promise<RemoteRuntimeRpcResultFor<M>>;
355
355
  subscribeSessionEvents(sessionId: string, options?: {
356
356
  signal?: AbortSignal;
package/dist/server.js CHANGED
@@ -75,7 +75,6 @@ export function createSessionRuntimeServices(input) {
75
75
  config: input.config,
76
76
  executor: runnerManager,
77
77
  sessionBus,
78
- sessionEventSink: mirrorSessionEvent,
79
78
  });
80
79
  runnerManager.onMirror((sessionId, event) => {
81
80
  void mirrorSessionEvent(sessionId, event).catch((error) => {
@@ -222,6 +221,15 @@ export async function startServer({ config = loadConfig(), control, sessionLog,
222
221
  session: input.session,
223
222
  }),
224
223
  },
224
+ sessionActivity: (sessionId) => {
225
+ const snapshot = sessionRuntimeIndex.snapshot(sessionId);
226
+ return {
227
+ ...snapshot,
228
+ status: snapshot.pendingInteractions.length > 0
229
+ ? "waiting"
230
+ : snapshot.status,
231
+ };
232
+ },
225
233
  interruptSession: (sessionId) => runnerManager.interruptLiveSession(sessionId),
226
234
  terminateSession: (sessionId) => runnerManager.terminateLiveSession(sessionId),
227
235
  resolveSessionInteraction: (sessionId, interactionId, resolution) => runnerManager.resolveInteraction(sessionId, interactionId, resolution),
@@ -13,12 +13,6 @@ export interface SessionRuntimeActivitySnapshot {
13
13
  */
14
14
  export declare class SessionRuntimeIndex {
15
15
  private readonly sessions;
16
- /**
17
- * Make an accepted Turn visible before the request admission reservation is
18
- * released. The returned callback only abandons the pre-created handoff; once
19
- * response.created arrives, the native response remains authoritative.
20
- */
21
- beginResponseHandoff(sessionId: string, responseId: string): () => void;
22
16
  observe(sessionId: string, event: SessionEvent): void;
23
17
  snapshot(sessionId: string): SessionRuntimeSnapshot;
24
18
  /** Aggregate only process-live work; durable Session history is not activity. */
@@ -6,48 +6,33 @@
6
6
  */
7
7
  export class SessionRuntimeIndex {
8
8
  sessions = new Map();
9
- /**
10
- * Make an accepted Turn visible before the request admission reservation is
11
- * released. The returned callback only abandons the pre-created handoff; once
12
- * response.created arrives, the native response remains authoritative.
13
- */
14
- beginResponseHandoff(sessionId, responseId) {
15
- const state = this.state(sessionId);
16
- state.pendingResponseIds.add(responseId);
17
- state.status = "running";
18
- state.statusKind = "startup";
19
- let pending = true;
20
- return () => {
21
- if (!pending)
22
- return;
23
- pending = false;
24
- state.pendingResponseIds.delete(responseId);
25
- };
26
- }
27
9
  observe(sessionId, event) {
28
10
  const state = this.state(sessionId);
29
11
  switch (event.type) {
30
12
  case "response.created":
31
- state.pendingResponseIds.delete(event.responseId);
32
13
  state.activeResponseIds.add(event.responseId);
33
14
  state.status = "running";
34
15
  state.statusKind = undefined;
35
16
  return;
36
17
  case "response.completed":
37
- state.pendingResponseIds.delete(event.responseId);
38
18
  state.activeResponseIds.delete(event.responseId);
39
19
  this.removeResponseInteractions(state, event.responseId);
40
20
  state.status = this.hasRunningTurn(state) ? "running" : "idle";
41
21
  state.statusKind = undefined;
42
22
  return;
43
23
  case "response.failed":
44
- state.pendingResponseIds.delete(event.responseId);
45
24
  state.activeResponseIds.delete(event.responseId);
46
25
  this.removeResponseInteractions(state, event.responseId);
47
26
  // Response failure is Turn-local. It must not poison a reusable Session.
48
27
  state.status = this.hasRunningTurn(state) ? "running" : "idle";
49
28
  state.statusKind = undefined;
50
29
  return;
30
+ case "session.interrupted":
31
+ state.activeResponseIds.delete(event.responseId);
32
+ this.removeResponseInteractions(state, event.responseId);
33
+ state.status = this.hasRunningTurn(state) ? "running" : "idle";
34
+ state.statusKind = undefined;
35
+ return;
51
36
  case "session.status":
52
37
  state.status =
53
38
  state.pendingInteractions.size > 0 || this.hasRunningTurn(state)
@@ -56,7 +41,6 @@ export class SessionRuntimeIndex {
56
41
  state.statusKind = event.statusKind;
57
42
  return;
58
43
  case "session.interaction.requested":
59
- state.pendingResponseIds.delete(event.responseId);
60
44
  state.pendingInteractions.set(event.interaction.interactionId, {
61
45
  responseId: event.responseId,
62
46
  interaction: event.interaction,
@@ -71,7 +55,6 @@ export class SessionRuntimeIndex {
71
55
  state.status = this.hasRunningTurn(state) ? "running" : state.status;
72
56
  return;
73
57
  case "session.rotated":
74
- state.pendingResponseIds.clear();
75
58
  state.activeResponseIds.clear();
76
59
  state.pendingInteractions.clear();
77
60
  state.status = "idle";
@@ -99,7 +82,7 @@ export class SessionRuntimeIndex {
99
82
  let runningTurns = 0;
100
83
  let pendingInteractions = 0;
101
84
  for (const state of this.sessions.values()) {
102
- runningTurns += state.pendingResponseIds.size + state.activeResponseIds.size;
85
+ runningTurns += state.activeResponseIds.size;
103
86
  pendingInteractions += state.pendingInteractions.size;
104
87
  }
105
88
  return { runningTurns, pendingInteractions };
@@ -112,7 +95,6 @@ export class SessionRuntimeIndex {
112
95
  if (!state) {
113
96
  state = {
114
97
  status: "idle",
115
- pendingResponseIds: new Set(),
116
98
  activeResponseIds: new Set(),
117
99
  pendingInteractions: new Map(),
118
100
  };
@@ -127,6 +109,6 @@ export class SessionRuntimeIndex {
127
109
  }
128
110
  }
129
111
  hasRunningTurn(state) {
130
- return state.pendingResponseIds.size > 0 || state.activeResponseIds.size > 0;
112
+ return state.activeResponseIds.size > 0;
131
113
  }
132
114
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rynx-ai/server",
3
- "version": "0.1.11-beta.21",
3
+ "version": "0.1.11-beta.23",
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/core": "0.1.11-beta.21",
31
- "@rynx-ai/plugin-sdk": "0.1.11-beta.21",
32
- "@rynx-ai/protocol": "0.1.11-beta.21",
33
- "@rynx-ai/remote-runtime-e2ee": "0.1.11-beta.21",
34
- "@rynx-ai/runtime": "0.1.11-beta.21"
30
+ "@rynx-ai/core": "0.1.11-beta.23",
31
+ "@rynx-ai/plugin-sdk": "0.1.11-beta.23",
32
+ "@rynx-ai/protocol": "0.1.11-beta.23",
33
+ "@rynx-ai/remote-runtime-e2ee": "0.1.11-beta.23",
34
+ "@rynx-ai/runtime": "0.1.11-beta.23"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@types/ws": "^8.18.1",
38
- "@rynx-ai/control-web": "0.1.11-beta.21"
38
+ "@rynx-ai/control-web": "0.1.11-beta.23"
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/",