@super-one/cli 0.57.0-alpha → 0.57.2-alpha

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/MANIFEST.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@super-one/cli",
3
- "version": "0.57.0-alpha",
3
+ "version": "0.57.2-alpha",
4
4
  "kind": "npm",
5
5
  "minNodeMajor": 20,
6
- "builtAt": "2026-08-22T22:14:12.822Z"
6
+ "builtAt": "2026-08-23T12:34:59.159Z"
7
7
  }
package/lib/cli.mjs CHANGED
@@ -24566,6 +24566,23 @@ var init_types = __esm({
24566
24566
  }
24567
24567
  });
24568
24568
 
24569
+ // ../../packages/runtime/src/session/runtime-policy.ts
24570
+ function getRuntimeIdleTimeoutMs(activeRuntimeCount) {
24571
+ if (activeRuntimeCount <= 4) return TWENTY_MINUTES_MS;
24572
+ if (activeRuntimeCount <= 8) return TEN_MINUTES_MS;
24573
+ return FIVE_MINUTES_MS;
24574
+ }
24575
+ var SESSION_RUNTIME_REAPER_INTERVAL_MS, TWENTY_MINUTES_MS, TEN_MINUTES_MS, FIVE_MINUTES_MS;
24576
+ var init_runtime_policy = __esm({
24577
+ "../../packages/runtime/src/session/runtime-policy.ts"() {
24578
+ "use strict";
24579
+ SESSION_RUNTIME_REAPER_INTERVAL_MS = 3e4;
24580
+ TWENTY_MINUTES_MS = 20 * 60 * 1e3;
24581
+ TEN_MINUTES_MS = 10 * 60 * 1e3;
24582
+ FIVE_MINUTES_MS = 5 * 60 * 1e3;
24583
+ }
24584
+ });
24585
+
24569
24586
  // ../../packages/runtime/src/session/session-runtime.ts
24570
24587
  import { randomUUID as randomUUID4 } from "node:crypto";
24571
24588
  function redactTaskNotificationForDisplay(content) {
@@ -24674,6 +24691,7 @@ var init_session_runtime = __esm({
24674
24691
  init_miniapp_prompt_tags();
24675
24692
  init_host_action_store();
24676
24693
  init_types();
24694
+ init_runtime_policy();
24677
24695
  init_types();
24678
24696
  DEFAULT_AGENTS_CONFIRM_TIMEOUT_MS = 10 * 6e4;
24679
24697
  SessionRuntime = class {
@@ -24688,6 +24706,13 @@ var init_session_runtime = __esm({
24688
24706
  this.hostActions = opts?.hostActions ?? null;
24689
24707
  this.hydrateFromStore();
24690
24708
  this.reconcileAfterRestart();
24709
+ const runtimeReaperIntervalMs = opts?.runtimeReaperIntervalMs ?? SESSION_RUNTIME_REAPER_INTERVAL_MS;
24710
+ if (runtimeReaperIntervalMs > 0 && this.turnRunner.listActiveRuntimes && this.turnRunner.disposeSession) {
24711
+ this.runtimeReaperTimer = setInterval(() => {
24712
+ void this.reapIdleRuntimes();
24713
+ }, runtimeReaperIntervalMs);
24714
+ this.runtimeReaperTimer.unref?.();
24715
+ }
24691
24716
  if (this.hostActions) {
24692
24717
  this.hostActions.subscribe(() => this.wakeHostActionPollers());
24693
24718
  this.hostActionExpiryTimer = setInterval(() => {
@@ -24720,6 +24745,8 @@ var init_session_runtime = __esm({
24720
24745
  /** Long-poll waiters woken on host action change. */
24721
24746
  hostActionPollWaiters = /* @__PURE__ */ new Set();
24722
24747
  hostActionExpiryTimer = null;
24748
+ runtimeReaperTimer = null;
24749
+ runtimeReleases = /* @__PURE__ */ new Set();
24723
24750
  /**
24724
24751
  * Per-session FIFO of turns accepted while status is streaming for harnesses
24725
24752
  * without a live inject channel (e.g. Codex). Claude uses concurrent
@@ -24737,6 +24764,36 @@ var init_session_runtime = __esm({
24737
24764
  isDisposing() {
24738
24765
  return this.disposing;
24739
24766
  }
24767
+ /** Release idle long-lived harness processes without ending resumable sessions. */
24768
+ async reapIdleRuntimes(now = Date.now()) {
24769
+ if (this.disposing) return;
24770
+ const listActiveRuntimes = this.turnRunner.listActiveRuntimes;
24771
+ const disposeSession = this.turnRunner.disposeSession;
24772
+ if (!listActiveRuntimes || !disposeSession) return;
24773
+ const bySession = /* @__PURE__ */ new Map();
24774
+ for (const entry of listActiveRuntimes()) {
24775
+ const previous = bySession.get(entry.sessionId);
24776
+ bySession.set(entry.sessionId, previous ? {
24777
+ sessionId: entry.sessionId,
24778
+ lastActivityAt: Math.max(previous.lastActivityAt, entry.lastActivityAt),
24779
+ busy: previous.busy || entry.busy
24780
+ } : entry);
24781
+ }
24782
+ if (bySession.size === 0) return;
24783
+ const timeoutMs = getRuntimeIdleTimeoutMs(bySession.size);
24784
+ const releases = [];
24785
+ for (const entry of bySession.values()) {
24786
+ if (entry.busy || now - entry.lastActivityAt < timeoutMs) continue;
24787
+ if (this.runtimeReleases.has(entry.sessionId)) continue;
24788
+ const session = this.live.get(entry.sessionId);
24789
+ if (session?.status === "streaming" || session?.pendingInteraction != null || (this.activeTurnCounts.get(entry.sessionId) ?? 0) > 0) continue;
24790
+ this.runtimeReleases.add(entry.sessionId);
24791
+ releases.push(
24792
+ Promise.resolve().then(() => disposeSession(entry.sessionId)).catch(() => void 0).finally(() => this.runtimeReleases.delete(entry.sessionId))
24793
+ );
24794
+ }
24795
+ await Promise.all(releases);
24796
+ }
24740
24797
  hydrateFromStore() {
24741
24798
  for (const session of this.store.loadAll()) {
24742
24799
  this.live.set(session.sessionId, session);
@@ -26341,6 +26398,10 @@ var init_session_runtime = __esm({
26341
26398
  */
26342
26399
  async dispose(timeoutMs = 5e3) {
26343
26400
  this.disposing = true;
26401
+ if (this.runtimeReaperTimer) {
26402
+ clearInterval(this.runtimeReaperTimer);
26403
+ this.runtimeReaperTimer = null;
26404
+ }
26344
26405
  if (this.hostActionExpiryTimer) {
26345
26406
  clearInterval(this.hostActionExpiryTimer);
26346
26407
  this.hostActionExpiryTimer = null;
@@ -27030,6 +27091,7 @@ var init_session = __esm({
27030
27091
  "../../packages/runtime/src/session/index.ts"() {
27031
27092
  "use strict";
27032
27093
  init_session_runtime();
27094
+ init_runtime_policy();
27033
27095
  init_event_log();
27034
27096
  init_message_catalog();
27035
27097
  init_sqlite_session_store();
@@ -31561,14 +31623,19 @@ function createNodeClaudeTurnRunner(opts) {
31561
31623
  live,
31562
31624
  hostActionDispose: hostActionMcp ? () => hostActionMcp.dispose() : null,
31563
31625
  cwd,
31564
- mcpDiskKey: mcpDiskKeyOf(merged.diskNames)
31626
+ mcpDiskKey: mcpDiskKeyOf(merged.diskNames),
31627
+ busyCount: 0,
31628
+ lastActivityAt: Date.now()
31565
31629
  };
31566
31630
  lives.set(sessionKey, entry);
31567
31631
  }
31568
31632
  const prepared = prepareTurnPrompt(input.text, cwd, input.images);
31569
31633
  const content = prepared.kind === "text" ? prepared.text : prepared.content;
31634
+ const activeEntry = entry;
31635
+ activeEntry.busyCount += 1;
31636
+ activeEntry.lastActivityAt = Date.now();
31570
31637
  try {
31571
- const result = await entry.live.sendTurn({
31638
+ const result = await activeEntry.live.sendTurn({
31572
31639
  content,
31573
31640
  messageId: input.messageId,
31574
31641
  clientMessageId: input.messageId,
@@ -31613,6 +31680,9 @@ function createNodeClaudeTurnRunner(opts) {
31613
31680
  } catch (err) {
31614
31681
  await disposeEntry(sessionKey);
31615
31682
  throw err;
31683
+ } finally {
31684
+ activeEntry.busyCount = Math.max(0, activeEntry.busyCount - 1);
31685
+ activeEntry.lastActivityAt = Date.now();
31616
31686
  }
31617
31687
  };
31618
31688
  runner.disposeSession = async (sessionId) => {
@@ -31622,6 +31692,11 @@ function createNodeClaudeTurnRunner(opts) {
31622
31692
  const keys = [...lives.keys()];
31623
31693
  await Promise.all(keys.map((id) => disposeEntry(id)));
31624
31694
  };
31695
+ runner.listActiveRuntimes = () => [...lives.entries()].map(([sessionId, entry]) => ({
31696
+ sessionId,
31697
+ lastActivityAt: entry.lastActivityAt,
31698
+ busy: entry.busyCount > 0
31699
+ }));
31625
31700
  return runner;
31626
31701
  }
31627
31702
  var CLAUDE_SESSION_RESUME_PREFIX;
@@ -62923,7 +62998,9 @@ function createNodeCodexTurnRunner(opts) {
62923
62998
  activeTurnId: null,
62924
62999
  cwd,
62925
63000
  providerEnvKey,
62926
- chain: Promise.resolve()
63001
+ chain: Promise.resolve(),
63002
+ busyCount: 0,
63003
+ lastActivityAt: Date.now()
62927
63004
  };
62928
63005
  liveBySession.set(sessionId, live);
62929
63006
  return live;
@@ -62978,21 +63055,28 @@ function createNodeCodexTurnRunner(opts) {
62978
63055
  if (!live2?.threadId || !live2.activeTurnId) {
62979
63056
  throw new Error("No active Codex turn to steer");
62980
63057
  }
62981
- const result = await runCodexAppServerTurn({
62982
- client: live2.client,
62983
- prompt,
62984
- cwd: live2.cwd,
62985
- threadId: live2.threadId,
62986
- turnKind: "steer",
62987
- expectedTurnId: live2.activeTurnId,
62988
- skipThreadSetup: true,
62989
- signal: input.signal
62990
- });
62991
- return {
62992
- finalText: result.finalText,
62993
- providerResume: result.threadId ? `thread:${result.threadId}` : null,
62994
- skipAssistantTranscript: true
62995
- };
63058
+ live2.busyCount += 1;
63059
+ live2.lastActivityAt = Date.now();
63060
+ try {
63061
+ const result = await runCodexAppServerTurn({
63062
+ client: live2.client,
63063
+ prompt,
63064
+ cwd: live2.cwd,
63065
+ threadId: live2.threadId,
63066
+ turnKind: "steer",
63067
+ expectedTurnId: live2.activeTurnId,
63068
+ skipThreadSetup: true,
63069
+ signal: input.signal
63070
+ });
63071
+ return {
63072
+ finalText: result.finalText,
63073
+ providerResume: result.threadId ? `thread:${result.threadId}` : null,
63074
+ skipAssistantTranscript: true
63075
+ };
63076
+ } finally {
63077
+ live2.busyCount = Math.max(0, live2.busyCount - 1);
63078
+ live2.lastActivityAt = Date.now();
63079
+ }
62996
63080
  }
62997
63081
  const live = await openLive(sessionId, binary, authEnv, cwd);
62998
63082
  const fullTurn = async () => {
@@ -63067,12 +63151,18 @@ function createNodeCodexTurnRunner(opts) {
63067
63151
  throw err;
63068
63152
  }
63069
63153
  };
63154
+ live.busyCount += 1;
63155
+ live.lastActivityAt = Date.now();
63070
63156
  const next = live.chain.then(fullTurn, fullTurn);
63071
- live.chain = next.then(
63157
+ const tracked = next.finally(() => {
63158
+ live.busyCount = Math.max(0, live.busyCount - 1);
63159
+ live.lastActivityAt = Date.now();
63160
+ });
63161
+ live.chain = tracked.then(
63072
63162
  () => void 0,
63073
63163
  () => void 0
63074
63164
  );
63075
- return next;
63165
+ return tracked;
63076
63166
  };
63077
63167
  runner.disposeSession = async (sessionId) => {
63078
63168
  await disposeLive(sessionId);
@@ -63081,6 +63171,11 @@ function createNodeCodexTurnRunner(opts) {
63081
63171
  const ids = [...liveBySession.keys()];
63082
63172
  await Promise.all(ids.map((id) => disposeLive(id)));
63083
63173
  };
63174
+ runner.listActiveRuntimes = () => [...liveBySession.entries()].map(([sessionId, live]) => ({
63175
+ sessionId,
63176
+ lastActivityAt: live.lastActivityAt,
63177
+ busy: live.busyCount > 0
63178
+ }));
63084
63179
  return runner;
63085
63180
  }
63086
63181
  function createProductionTurnRunner(opts) {
@@ -63132,6 +63227,10 @@ function createProductionTurnRunner(opts) {
63132
63227
  runner.disposeAll = async () => {
63133
63228
  await Promise.all([claude.disposeAll?.(), codex.disposeAll?.()]);
63134
63229
  };
63230
+ runner.listActiveRuntimes = () => [
63231
+ ...claude.listActiveRuntimes?.() ?? [],
63232
+ ...codex.listActiveRuntimes?.() ?? []
63233
+ ];
63135
63234
  return runner;
63136
63235
  }
63137
63236
  var init_codex_turn_runner = __esm({
@@ -70562,8 +70661,8 @@ import { fileURLToPath } from "node:url";
70562
70661
  function resolveCliReleaseVersion() {
70563
70662
  const fromEnv = process.env.SUPERONE_CLI_VERSION?.trim();
70564
70663
  if (fromEnv) return fromEnv;
70565
- if ("0.57.0-alpha".trim()) {
70566
- return "0.57.0-alpha".trim();
70664
+ if ("0.57.2-alpha".trim()) {
70665
+ return "0.57.2-alpha".trim();
70567
70666
  }
70568
70667
  const fromDist = readDistManifestVersion();
70569
70668
  if (fromDist) return fromDist;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@super-one/cli",
3
- "version": "0.57.0-alpha",
3
+ "version": "0.57.2-alpha",
4
4
  "description": "SuperOne headless node CLI — remote execution environment (RPC, workspaces, sessions).",
5
5
  "type": "module",
6
6
  "license": "BUSL-1.1",