@runweave/server-linux-x64 0.1.12 → 0.1.13

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
@@ -6,8 +6,8 @@
6
6
  "protocolVersion": 1,
7
7
  "entry": "pty-host/index.cjs"
8
8
  },
9
- "version": "0.1.12",
10
- "sourceRevision": "2137d8fa9eae70d0ab4070212c1cb4e8bb9e2fa6",
9
+ "version": "0.1.13",
10
+ "sourceRevision": "da67d523de925abb4f2b958f949fd50a3ac2b5bb",
11
11
  "platform": "linux",
12
12
  "arch": "x64",
13
13
  "nodeModuleAbi": "127",
@@ -30,7 +30,7 @@
30
30
  {
31
31
  "path": "app-server/build-info.json",
32
32
  "size": 286,
33
- "sha256": "c702c8fd4632749a3ce27aa0f7e3a66fb0129017b37f7876efb37665551c461e"
33
+ "sha256": "9c7c169c3553261b2cc8b7d83bc7d2fb7f7e16d75e8d3ae8bd8b0fa0ffc28307"
34
34
  },
35
35
  {
36
36
  "path": "app-server/configuration-compatibility.json",
@@ -40,7 +40,7 @@
40
40
  {
41
41
  "path": "app-server/index.cjs",
42
42
  "size": 1991601,
43
- "sha256": "64e03d0435f018c50d94975eb46713c1540f79581dd26e0a0cb759a9511dccd6"
43
+ "sha256": "d99ba7fb4934b29a6cc499e8212fb1f098d01127b499b1b1d241b0ea20f28211"
44
44
  },
45
45
  {
46
46
  "path": "app-server/index.cjs.map",
@@ -55,7 +55,7 @@
55
55
  {
56
56
  "path": "backend/build-info.json",
57
57
  "size": 286,
58
- "sha256": "3511fdc3647f318b6400f7e9e2292da567fa5ea5df89ce6b66f4a89ec9d4264b"
58
+ "sha256": "bd960ff86288c8d4553d3d0444a66ae4dec7d3f902d34b53810f00f4be4f931b"
59
59
  },
60
60
  {
61
61
  "path": "backend/dev-resources/control.cjs",
@@ -69,8 +69,8 @@
69
69
  },
70
70
  {
71
71
  "path": "backend/index.cjs",
72
- "size": 5748904,
73
- "sha256": "b77195be61f40ef783fea4f7a1d5553b87a6d4866734b1af3b9e7485308f2f33"
72
+ "size": 5753065,
73
+ "sha256": "55247579573e991db66d087db63c29a17a3147ea2fb43560c1ef61eed54f23e7"
74
74
  },
75
75
  {
76
76
  "path": "backend/ios-simulators/device_shutdown.py",
@@ -505,12 +505,12 @@
505
505
  {
506
506
  "path": "frontend/dist/build-info.json",
507
507
  "size": 286,
508
- "sha256": "01065e5cb1381b3ea289e128d9d1e23da843832590bd950451b1a7e21f19ef35"
508
+ "sha256": "77cffa6df1475be5a25363546a40125d700ae5736c04a33b80312ce440dbaca7"
509
509
  },
510
510
  {
511
511
  "path": "frontend/dist/companion.html",
512
512
  "size": 822,
513
- "sha256": "19a85b076b2a17d4ecfe30606c44b8338e9197f96bb0bfb576097cb4fb9c0233"
513
+ "sha256": "724bf62ecacd1f23e651185eb112ff0f1d6f180076a31c4c61cd6801b69f7ba1"
514
514
  },
515
515
  {
516
516
  "path": "frontend/dist/icons/apple-touch-icon.png",
@@ -535,7 +535,7 @@
535
535
  {
536
536
  "path": "frontend/dist/index.html",
537
537
  "size": 1028,
538
- "sha256": "61ba75aadb6b23c6440af75d9875adee493fda7ea166bfb435ba9b215c50e360"
538
+ "sha256": "468e70be64ca45305732605cbc4f3c7e5338661a523783be8a705525c58a6c1c"
539
539
  },
540
540
  {
541
541
  "path": "frontend/dist/manifest.webmanifest",
@@ -1859,8 +1859,8 @@
1859
1859
  },
1860
1860
  {
1861
1861
  "path": "pty-host/index.cjs",
1862
- "size": 918397,
1863
- "sha256": "796bcb6e2b758c27db284ca11c5080a17f015ee1f880fca73aaf88e170c01bf5"
1862
+ "size": 918936,
1863
+ "sha256": "764642ecafe1b4e3f28ef9a84451e17d469257878e9730e73e6953eb060e2125"
1864
1864
  },
1865
1865
  {
1866
1866
  "path": "scripts/toolkit/codex-state.mjs",
package/native.tar.gz CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runweave/server-linux-x64",
3
- "version": "0.1.12",
3
+ "version": "0.1.13",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "version": "0.1.0",
3
- "buildId": "20261109T114447447Z-2137d8fa",
4
- "sourceRevision": "2137d8fa9eae70d0ab4070212c1cb4e8bb9e2fa6",
3
+ "buildId": "20261109T123037865Z-da67d523",
4
+ "sourceRevision": "da67d523de925abb4f2b958f949fd50a3ac2b5bb",
5
5
  "sourceDirty": false,
6
- "builtAt": "2026-11-09T11:44:47.447Z",
6
+ "builtAt": "2026-11-09T12:30:37.865Z",
7
7
  "contentSha256": "ee24c2adfe7a38b0f7698d68d8493b560042b699baba92c63e79961518d9a9af"
8
8
  }
@@ -1,4 +1,4 @@
1
- /* runweave:build-info */var __RUNWEAVE_BUILD_INFO__={"version":"0.1.0","buildId":"20261109T114447447Z-2137d8fa","sourceRevision":"2137d8fa9eae70d0ab4070212c1cb4e8bb9e2fa6","sourceDirty":false,"builtAt":"2026-11-09T11:44:47.447Z","contentSha256":"ee24c2adfe7a38b0f7698d68d8493b560042b699baba92c63e79961518d9a9af"};
1
+ /* runweave:build-info */var __RUNWEAVE_BUILD_INFO__={"version":"0.1.0","buildId":"20261109T123037865Z-da67d523","sourceRevision":"da67d523de925abb4f2b958f949fd50a3ac2b5bb","sourceDirty":false,"builtAt":"2026-11-09T12:30:37.865Z","contentSha256":"ee24c2adfe7a38b0f7698d68d8493b560042b699baba92c63e79961518d9a9af"};
2
2
  const __IMPORT_META_URL__ = require('url').pathToFileURL(__filename).href;
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "version": "0.1.0",
3
- "buildId": "20261109T114446842Z-2137d8fa",
4
- "sourceRevision": "2137d8fa9eae70d0ab4070212c1cb4e8bb9e2fa6",
3
+ "buildId": "20261109T123037121Z-da67d523",
4
+ "sourceRevision": "da67d523de925abb4f2b958f949fd50a3ac2b5bb",
5
5
  "sourceDirty": false,
6
- "builtAt": "2026-11-09T11:44:46.842Z",
7
- "contentSha256": "170984239a9c787cca301a61b3656704c8500945c978db6f3b97a5f716b40682"
6
+ "builtAt": "2026-11-09T12:30:37.121Z",
7
+ "contentSha256": "fd2cc32d5678e48707cff4a53f44897eb73eb0eff1b7584fc1da101e402cb2a2"
8
8
  }
@@ -1,4 +1,4 @@
1
- /* runweave:build-info */var __RUNWEAVE_BUILD_INFO__={"version":"0.1.0","buildId":"20261109T114446842Z-2137d8fa","sourceRevision":"2137d8fa9eae70d0ab4070212c1cb4e8bb9e2fa6","sourceDirty":false,"builtAt":"2026-11-09T11:44:46.842Z","contentSha256":"170984239a9c787cca301a61b3656704c8500945c978db6f3b97a5f716b40682"};
1
+ /* runweave:build-info */var __RUNWEAVE_BUILD_INFO__={"version":"0.1.0","buildId":"20261109T123037121Z-da67d523","sourceRevision":"da67d523de925abb4f2b958f949fd50a3ac2b5bb","sourceDirty":false,"builtAt":"2026-11-09T12:30:37.121Z","contentSha256":"fd2cc32d5678e48707cff4a53f44897eb73eb0eff1b7584fc1da101e402cb2a2"};
2
2
  const __IMPORT_META_URL__ = require('url').pathToFileURL(__filename).href;
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -71434,6 +71434,21 @@ function buildAgentResumeArgs(agent, thread) {
71434
71434
  return [resumeFlags[agent] ?? "resume", thread];
71435
71435
  }
71436
71436
 
71437
+ // packages/shared/src/terminal/shell.ts
71438
+ function terminalShellName(command) {
71439
+ return (command.split(/[\\/]/).at(-1) ?? command).toLowerCase().replace(/\.exe$/, "");
71440
+ }
71441
+ function isInteractiveShellLaunch(launch) {
71442
+ const name = terminalShellName(launch.command);
71443
+ if (!["sh", "bash", "zsh", "dash", "ksh", "fish", "powershell", "pwsh", "cmd"].includes(name)) return false;
71444
+ return !(launch.args ?? []).some((arg) => {
71445
+ const value = arg.toLowerCase();
71446
+ if (name === "cmd") return !/^\/(?:d|q|a|u|e:(?:on|off)|f:(?:on|off)|v:(?:on|off))$/.test(value);
71447
+ if (name === "powershell" || name === "pwsh") return !["-nologo", "-noprofile", "-noexit", "-login", "-l"].includes(value);
71448
+ return ["--help", "--version"].includes(value) || !value.startsWith("-") || value === "--" || /^-[^-]*[cs]/.test(value) || /^--(?:command|init-command)(?:=|$)/.test(value);
71449
+ });
71450
+ }
71451
+
71437
71452
  // backend/src/terminal/runtime/pi-editor.ts
71438
71453
  var import_node_crypto12 = require("node:crypto");
71439
71454
  var import_node_http = require("node:http");
@@ -71575,7 +71590,19 @@ function buildAgentResumeCommand(thread) {
71575
71590
  thread.sessionFile ?? thread.threadId
71576
71591
  )
71577
71592
  ];
71578
- return `${shellQuote(thread.executable ?? thread.provider)} ${args.map(shellQuote).join(" ")}
71593
+ const configured = thread.provider === "codex" ? settingText("agents.codex.binary")?.trim() : ["trae", "traex", "traecli"].includes(thread.provider) ? settingText("agents.traex.binary")?.trim() : void 0;
71594
+ const executable = thread.executable ?? configured ?? thread.provider;
71595
+ const shell = terminalShellName(thread.shell ?? "sh");
71596
+ if (["powershell", "pwsh", "cmd"].includes(shell)) {
71597
+ const parts = [executable, ...args];
71598
+ if (parts.some((part) => [...part].some((character) => character.charCodeAt(0) < 32 || character.charCodeAt(0) === 127)))
71599
+ throw new Error("Agent resume arguments contain terminal control characters");
71600
+ const command = `& ${parts.map((part) => `'${part.replaceAll("'", "''")}'`).join(" ")}`;
71601
+ return shell === "cmd" ? `powershell.exe -NoProfile -EncodedCommand ${Buffer.from(command, "utf16le").toString("base64")}
71602
+ ` : `${command}
71603
+ `;
71604
+ }
71605
+ return `${shellQuote(executable)} ${args.map(shellQuote).join(" ")}
71579
71606
  `;
71580
71607
  }
71581
71608
  function shellQuote(value) {
@@ -71878,21 +71905,6 @@ var aiDiagnosticLog = createAiDiagnosticLog({
71878
71905
  source: "backend"
71879
71906
  });
71880
71907
 
71881
- // packages/shared/src/terminal/shell.ts
71882
- function terminalShellName(command) {
71883
- return (command.split(/[\\/]/).at(-1) ?? command).toLowerCase().replace(/\.exe$/, "");
71884
- }
71885
- function isInteractiveShellLaunch(launch) {
71886
- const name = terminalShellName(launch.command);
71887
- if (!["sh", "bash", "zsh", "dash", "ksh", "fish", "powershell", "pwsh", "cmd"].includes(name)) return false;
71888
- return !(launch.args ?? []).some((arg) => {
71889
- const value = arg.toLowerCase();
71890
- if (name === "cmd") return !/^\/(?:d|q|a|u|e:(?:on|off)|f:(?:on|off)|v:(?:on|off))$/.test(value);
71891
- if (name === "powershell" || name === "pwsh") return !["-nologo", "-noprofile", "-noexit", "-login", "-l"].includes(value);
71892
- return ["--help", "--version"].includes(value) || !value.startsWith("-") || value === "--" || /^-[^-]*[cs]/.test(value) || /^--(?:command|init-command)(?:=|$)/.test(value);
71893
- });
71894
- }
71895
-
71896
71908
  // backend/src/terminal/runtime/pty-host-client.ts
71897
71909
  var import_node_crypto15 = require("node:crypto");
71898
71910
 
@@ -72069,27 +72081,37 @@ var ownerId = (0, import_node_crypto15.randomUUID)();
72069
72081
  var connection;
72070
72082
  var generation;
72071
72083
  var hostInstanceId;
72084
+ var upstreams;
72072
72085
  var stopped = false;
72073
72086
  function usesPtyHost() {
72074
72087
  return process.platform === "win32" && Boolean(process.env.RUNWEAVE_RUNTIME_RELEASE_ID);
72075
72088
  }
72076
72089
  async function getPtyHost() {
72077
72090
  if (stopped) throw new Error("HOST_CLIENT_STOPPED");
72078
- connection ??= PtyHostClient.connect(configuration().context, ownerId, generation, hostInstanceId).then((client) => {
72091
+ connection ??= PtyHostClient.connect(configuration().context, ownerId, generation, hostInstanceId).then(async (client) => {
72079
72092
  generation = client.generation;
72080
72093
  hostInstanceId = client.descriptor.hostInstanceId;
72081
72094
  client.disconnected.add(() => {
72082
72095
  connection = void 0;
72083
72096
  });
72084
- return client;
72097
+ try {
72098
+ if (upstreams) await client.request("setUpstreams", upstreams);
72099
+ return client;
72100
+ } catch (error2) {
72101
+ client.close();
72102
+ throw error2;
72103
+ }
72085
72104
  }).catch((error2) => {
72086
72105
  connection = void 0;
72087
72106
  throw error2;
72088
72107
  });
72089
72108
  return connection;
72090
72109
  }
72091
- async function syncPtyHostUpstreams(upstreams) {
72092
- if (usesPtyHost()) await (await getPtyHost()).request("setUpstreams", upstreams);
72110
+ async function syncPtyHostUpstreams(value) {
72111
+ if (usesPtyHost()) {
72112
+ upstreams = { ...value };
72113
+ await (await getPtyHost()).request("setUpstreams", value);
72114
+ }
72093
72115
  }
72094
72116
  async function createHostedPty(options) {
72095
72117
  const client = await getPtyHost();
@@ -73186,63 +73208,139 @@ function createTerminalRuntimeRecorder(terminalSessionManager, terminalSessionId
73186
73208
  };
73187
73209
  }
73188
73210
 
73211
+ // backend/src/terminal/runtime/recovery-policy.ts
73212
+ var RebuildWindowMs = 6e4;
73213
+ var MaxRebuildAttempts = 3;
73214
+ var TerminalRebuildLimitError = class extends Error {
73215
+ constructor(terminalSessionId, count, windowMs, maxAttempts, runtime = "terminal") {
73216
+ super(`${runtime} session rebuild exceeded ${maxAttempts} attempts in ${windowMs} ms for ${terminalSessionId}`);
73217
+ this.terminalSessionId = terminalSessionId;
73218
+ this.count = count;
73219
+ this.windowMs = windowMs;
73220
+ this.maxAttempts = maxAttempts;
73221
+ this.name = "TerminalRebuildLimitError";
73222
+ }
73223
+ };
73224
+ function recordTerminalRebuildAttempt(history, terminalSessionId, now2 = Date.now()) {
73225
+ const attempts = (history.get(terminalSessionId) ?? []).filter((timestamp3) => timestamp3 >= now2 - RebuildWindowMs);
73226
+ history.set(terminalSessionId, attempts);
73227
+ if (attempts.length >= MaxRebuildAttempts)
73228
+ throw new TerminalRebuildLimitError(terminalSessionId, attempts.length + 1, RebuildWindowMs, MaxRebuildAttempts);
73229
+ attempts.push(now2);
73230
+ return { allowed: true, count: attempts.length, windowMs: RebuildWindowMs, maxAttempts: MaxRebuildAttempts };
73231
+ }
73232
+ function resolveAgentThreadToResume(session) {
73233
+ const activeProvider = getAgentForCommand(session.activeCommand) ?? (session.terminalState?.state.startsWith("agent_") ? session.terminalState.agent : null);
73234
+ if (!activeProvider) return null;
73235
+ const currentThreadId = session.threadId?.trim();
73236
+ const currentProvider = session.threadProvider ?? (currentThreadId ? "codex" : void 0);
73237
+ if (currentThreadId && currentProvider === activeProvider)
73238
+ return { provider: activeProvider, threadId: currentThreadId };
73239
+ const recentThreadId = session.lastThreadId?.trim();
73240
+ return recentThreadId && session.lastThreadProvider === activeProvider ? { provider: activeProvider, threadId: recentThreadId } : null;
73241
+ }
73242
+
73189
73243
  // backend/src/terminal/runtime/pty-host-runtime.ts
73190
73244
  var launches = /* @__PURE__ */ new Map();
73245
+ var rebuildAttempts = /* @__PURE__ */ new Map();
73191
73246
  function ensureHostedTerminal(options) {
73192
73247
  const previous = launches.get(options.session.id);
73193
73248
  if (previous) return previous;
73194
- const launch = (async () => {
73195
- const { session, terminalSessionManager, runtimeRegistry } = options;
73196
- const existing = runtimeRegistry.getSessionRuntime(session.id);
73197
- if (existing) return existing;
73198
- let binding = session.ptyHost;
73199
- const creating = !binding;
73200
- if (!binding) {
73201
- binding = { hostInstanceId: (await getPtyHost()).descriptor.hostInstanceId, sessionInstanceId: (0, import_node_crypto16.randomUUID)() };
73202
- await terminalSessionManager.updateRuntimeMetadata(session.id, { runtimeKind: "pty", ptyHost: binding, recoverable: true });
73203
- }
73204
- const fallback = creating ? resolveTerminalFallbackLaunchConfig(session) : null;
73205
- const terminalEnv = buildTerminalRuntimeEnvironment({ terminalSessionId: session.id, projectId: session.projectId, source: session.source });
73206
- const runtime = await createHostedPty({
73207
- terminalSessionId: session.id,
73208
- binding,
73209
- onLaunch: async (launch2) => {
73210
- if (launch2.fallbackReason) logger.warn("terminal.pty-host.fallback.activated", { terminalSessionId: session.id, command: launch2.command, reason: launch2.fallbackReason });
73211
- await terminalSessionManager.updateSessionLaunch(session.id, { command: launch2.command, args: launch2.args });
73212
- },
73213
- create: creating ? {
73214
- sessionInstanceId: binding.sessionInstanceId,
73215
- terminalSessionId: session.id,
73216
- projectId: session.projectId,
73217
- command: session.command,
73218
- args: session.args,
73219
- cwd: session.cwd,
73220
- cols: 80,
73221
- rows: 24,
73222
- env: buildPtyEnv(process.env, terminalEnv, session.command),
73223
- ...fallback ? { fallback: { ...fallback, env: buildPtyEnv(process.env, terminalEnv, fallback.command) } } : {}
73224
- } : void 0
73225
- });
73226
- runtimeRegistry.createRuntime(session.id, runtime);
73227
- runtimeRegistry.ensureRecorder(session.id, createTerminalRuntimeRecorder(terminalSessionManager, session.id));
73228
- return runtime;
73229
- })().catch((error2) => {
73230
- if (error2 instanceof Error && error2.message === "HOST_SESSION_GONE") {
73231
- options.terminalSessionManager.markExited(options.session.id);
73232
- }
73233
- throw error2;
73234
- }).finally(() => {
73249
+ const launch = attachOrRebuild(options).finally(() => {
73235
73250
  launches.delete(options.session.id);
73236
73251
  });
73237
73252
  launches.set(options.session.id, launch);
73238
73253
  return launch;
73239
73254
  }
73255
+ async function attachOrRebuild(options) {
73256
+ const { session, terminalSessionManager, runtimeRegistry } = options;
73257
+ const existing = runtimeRegistry.getSessionRuntime(session.id);
73258
+ if (existing) return { runtime: existing };
73259
+ let runtime;
73260
+ let warning;
73261
+ try {
73262
+ runtime = await launchHostedTerminal(options, !session.ptyHost);
73263
+ } catch (error2) {
73264
+ if (!(error2 instanceof Error) || error2.message !== "HOST_SESSION_GONE" || session.status !== "running") throw error2;
73265
+ ({ runtime, warning } = await rebuildHostedTerminal(options));
73266
+ }
73267
+ runtimeRegistry.createRuntime(session.id, runtime);
73268
+ runtimeRegistry.ensureRecorder(session.id, createTerminalRuntimeRecorder(terminalSessionManager, session.id));
73269
+ return { runtime, warning };
73270
+ }
73271
+ async function launchHostedTerminal(options, creating) {
73272
+ const { session, terminalSessionManager } = options;
73273
+ let binding = session.ptyHost;
73274
+ if (creating) {
73275
+ binding = { hostInstanceId: (await getPtyHost()).descriptor.hostInstanceId, sessionInstanceId: (0, import_node_crypto16.randomUUID)() };
73276
+ await terminalSessionManager.updateRuntimeMetadata(session.id, { runtimeKind: "pty", ptyHost: binding, recoverable: true });
73277
+ }
73278
+ if (!binding) throw new Error("HOST_SESSION_GONE");
73279
+ const fallback = creating ? resolveTerminalFallbackLaunchConfig(session) : null;
73280
+ const terminalEnv = buildTerminalRuntimeEnvironment({ terminalSessionId: session.id, projectId: session.projectId, source: session.source });
73281
+ return createHostedPty({
73282
+ terminalSessionId: session.id,
73283
+ binding,
73284
+ onLaunch: async (launch) => {
73285
+ if (launch.fallbackReason) logger.warn("terminal.pty-host.fallback.activated", { terminalSessionId: session.id, command: launch.command, reason: launch.fallbackReason });
73286
+ await terminalSessionManager.updateSessionLaunch(session.id, { command: launch.command, args: launch.args });
73287
+ },
73288
+ create: creating ? {
73289
+ sessionInstanceId: binding.sessionInstanceId,
73290
+ terminalSessionId: session.id,
73291
+ projectId: session.projectId,
73292
+ command: session.command,
73293
+ args: session.args,
73294
+ cwd: session.cwd,
73295
+ cols: 80,
73296
+ rows: 24,
73297
+ env: buildPtyEnv(process.env, terminalEnv, session.command),
73298
+ ...fallback ? { fallback: { ...fallback, env: buildPtyEnv(process.env, terminalEnv, fallback.command) } } : {}
73299
+ } : void 0
73300
+ });
73301
+ }
73302
+ async function rebuildHostedTerminal(options) {
73303
+ const { session, terminalSessionManager } = options;
73304
+ const interactive = isInteractiveShellLaunch(session);
73305
+ const thread = interactive ? resolveAgentThreadToResume(session) : null;
73306
+ let warning = "Command exited; returned to a shell.";
73307
+ if (interactive) {
73308
+ try {
73309
+ const attempt = recordTerminalRebuildAttempt(rebuildAttempts, session.id);
73310
+ warning = thread ? `Original PTY Host session was lost; starting ${thread.provider} resume from saved threadId (${attempt.count}/${attempt.maxAttempts}).` : `Original PTY Host session was lost; created a fresh terminal session (${attempt.count}/${attempt.maxAttempts}).`;
73311
+ } catch (error2) {
73312
+ if (error2 instanceof TerminalRebuildLimitError) {
73313
+ await terminalSessionManager.updateRuntimeMetadata(session.id, { runtimeKind: "pty", ptyHost: session.ptyHost, recoverable: false });
73314
+ terminalSessionManager.markExited(session.id, 1);
73315
+ }
73316
+ throw error2;
73317
+ }
73318
+ } else {
73319
+ await terminalSessionManager.updateSessionLaunch(session.id, resolveDefaultTerminalLaunchConfig());
73320
+ await terminalSessionManager.updateSessionMetadata(session.id, { cwd: session.cwd, activeCommand: null });
73321
+ terminalSessionManager.markRunning(session.id);
73322
+ }
73323
+ const sessionFile = thread ? await getAgentAdapter(thread.provider).resolveResumeTarget(thread.threadId, session.pi) : void 0;
73324
+ const runtime = await launchHostedTerminal(options, true);
73325
+ try {
73326
+ if (thread) {
73327
+ const command = buildAgentResumeCommand({ ...thread, sessionFile, shell: session.command });
73328
+ await runtime.hosted.writeSteps([{ type: "text", data: command.replace(/\n$/, "") }, { type: "delay", ms: 200 }, { type: "text", data: "\r" }], `recovery:${session.ptyHost.sessionInstanceId}`);
73329
+ await terminalSessionManager.updateSessionThreadId(session.id, thread.threadId, thread.provider);
73330
+ }
73331
+ } catch (error2) {
73332
+ runtime.dispose();
73333
+ throw error2;
73334
+ }
73335
+ logger.warn("terminal.pty-host.session-missing.rebuild", { terminalSessionId: session.id, warning });
73336
+ return { runtime, warning };
73337
+ }
73240
73338
  async function reconcileHostedTerminals(manager, registry2) {
73241
73339
  if (!usesPtyHost()) return;
73242
73340
  for (const session of manager.listSessions()) {
73243
73341
  if (session.runtimeKind !== "pty" || session.status !== "running") continue;
73244
73342
  if (!session.ptyHost) {
73245
- if (session.status === "running") manager.markExited(session.id);
73343
+ manager.markExited(session.id);
73246
73344
  continue;
73247
73345
  }
73248
73346
  try {
@@ -73296,8 +73394,6 @@ var import_node_fs16 = require("node:fs");
73296
73394
  var import_node_path25 = __toESM(require("node:path"), 1);
73297
73395
  var RUNWEAVE_TMUX_PREFIX = "runweave-";
73298
73396
  var TmuxCommandTimeoutMs = 5e3;
73299
- var RebuildWindowMs = 6e4;
73300
- var MaxRebuildAttempts = 3;
73301
73397
  var CaptureHistoryLines = 5e3;
73302
73398
  var InteractivePaneReadyMinWaitMs = 1e3;
73303
73399
  var InteractivePaneReadyStableMs = 200;
@@ -74050,28 +74146,13 @@ var TmuxSessionService = class extends TmuxProcess {
74050
74146
  return orphanedSessions;
74051
74147
  }
74052
74148
  recordRebuildAttempt(terminalSessionId) {
74053
- const now2 = this.now();
74054
- const windowStart = now2 - RebuildWindowMs;
74055
- const attempts = (this.rebuildAttempts.get(terminalSessionId) ?? []).filter(
74056
- (timestamp3) => timestamp3 >= windowStart
74057
- );
74058
- if (attempts.length >= MaxRebuildAttempts) {
74059
- this.rebuildAttempts.set(terminalSessionId, attempts);
74060
- throw new TmuxRebuildLimitError(
74061
- terminalSessionId,
74062
- attempts.length + 1,
74063
- RebuildWindowMs,
74064
- MaxRebuildAttempts
74065
- );
74149
+ try {
74150
+ return recordTerminalRebuildAttempt(this.rebuildAttempts, terminalSessionId, this.now());
74151
+ } catch (error2) {
74152
+ if (error2 instanceof TerminalRebuildLimitError)
74153
+ throw new TmuxRebuildLimitError(error2.terminalSessionId, error2.count, error2.windowMs, error2.maxAttempts);
74154
+ throw error2;
74066
74155
  }
74067
- attempts.push(now2);
74068
- this.rebuildAttempts.set(terminalSessionId, attempts);
74069
- return {
74070
- allowed: true,
74071
- count: attempts.length,
74072
- windowMs: RebuildWindowMs,
74073
- maxAttempts: MaxRebuildAttempts
74074
- };
74075
74156
  }
74076
74157
  };
74077
74158
 
@@ -74812,7 +74893,7 @@ async function ensureTerminalRuntime(options) {
74812
74893
  };
74813
74894
  });
74814
74895
  }
74815
- if (options.session.ptyHost || usesPtyHost()) return { runtime: await ensureHostedTerminal(options) };
74896
+ if (options.session.ptyHost || usesPtyHost()) return ensureHostedTerminal(options);
74816
74897
  const runtime = options.ptyService.spawnSession({
74817
74898
  command: options.session.command,
74818
74899
  args: options.session.args,
@@ -74852,19 +74933,6 @@ async function ensureTerminalRuntime(options) {
74852
74933
  function isInteractiveShellLaunch2(command, args) {
74853
74934
  return isInteractiveShellLaunch({ command, args });
74854
74935
  }
74855
- function resolveAgentThreadToResume(session) {
74856
- const activeProvider = getAgentForCommand(session.activeCommand);
74857
- if (!activeProvider) {
74858
- return null;
74859
- }
74860
- const currentThreadId = session.threadId?.trim();
74861
- const currentProvider = session.threadProvider ?? (currentThreadId ? "codex" : void 0);
74862
- if (currentThreadId && currentProvider === activeProvider) {
74863
- return { provider: activeProvider, threadId: currentThreadId };
74864
- }
74865
- const recentThreadId = session.lastThreadId?.trim();
74866
- return recentThreadId && session.lastThreadProvider === activeProvider ? { provider: activeProvider, threadId: recentThreadId } : null;
74867
- }
74868
74936
  function createTmuxInputPacedRuntime(runtime) {
74869
74937
  const queuedInput = [];
74870
74938
  let holdInputUntil = 0;
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "version": "0.1.0",
3
- "buildId": "20261109T114445902Z-2137d8fa",
4
- "sourceRevision": "2137d8fa9eae70d0ab4070212c1cb4e8bb9e2fa6",
3
+ "buildId": "20261109T123036078Z-da67d523",
4
+ "sourceRevision": "da67d523de925abb4f2b958f949fd50a3ac2b5bb",
5
5
  "sourceDirty": false,
6
- "builtAt": "2026-11-09T11:44:45.902Z",
6
+ "builtAt": "2026-11-09T12:30:36.078Z",
7
7
  "contentSha256": "d88edba1ac622f799a43f96f04cacdfb2052f2b959dae733f3feb164b615427b"
8
8
  }
@@ -1,6 +1,6 @@
1
1
  <!doctype html>
2
2
  <html lang="zh-CN">
3
- <head><script data-runweave-build-info>var __RUNWEAVE_BUILD_INFO__={"version":"0.1.0","buildId":"20261109T114445902Z-2137d8fa","sourceRevision":"2137d8fa9eae70d0ab4070212c1cb4e8bb9e2fa6","sourceDirty":false,"builtAt":"2026-11-09T11:44:45.902Z","contentSha256":"d88edba1ac622f799a43f96f04cacdfb2052f2b959dae733f3feb164b615427b"};</script>
3
+ <head><script data-runweave-build-info>var __RUNWEAVE_BUILD_INFO__={"version":"0.1.0","buildId":"20261109T123036078Z-da67d523","sourceRevision":"da67d523de925abb4f2b958f949fd50a3ac2b5bb","sourceDirty":false,"builtAt":"2026-11-09T12:30:36.078Z","contentSha256":"d88edba1ac622f799a43f96f04cacdfb2052f2b959dae733f3feb164b615427b"};</script>
4
4
 
5
5
  <meta charset="UTF-8" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
@@ -1,6 +1,6 @@
1
1
  <!doctype html>
2
2
  <html lang="en">
3
- <head><script data-runweave-build-info>var __RUNWEAVE_BUILD_INFO__={"version":"0.1.0","buildId":"20261109T114445902Z-2137d8fa","sourceRevision":"2137d8fa9eae70d0ab4070212c1cb4e8bb9e2fa6","sourceDirty":false,"builtAt":"2026-11-09T11:44:45.902Z","contentSha256":"d88edba1ac622f799a43f96f04cacdfb2052f2b959dae733f3feb164b615427b"};</script>
3
+ <head><script data-runweave-build-info>var __RUNWEAVE_BUILD_INFO__={"version":"0.1.0","buildId":"20261109T123036078Z-da67d523","sourceRevision":"da67d523de925abb4f2b958f949fd50a3ac2b5bb","sourceDirty":false,"builtAt":"2026-11-09T12:30:36.078Z","contentSha256":"d88edba1ac622f799a43f96f04cacdfb2052f2b959dae733f3feb164b615427b"};</script>
4
4
 
5
5
  <meta charset="UTF-8" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
@@ -18953,6 +18953,7 @@ var NEVER = INVALID;
18953
18953
  // packages/pty-host/src/discovery.ts
18954
18954
  var import_node_crypto = require("node:crypto");
18955
18955
  var import_node_fs4 = require("node:fs");
18956
+ var import_promises = require("node:fs/promises");
18956
18957
  var import_node_path2 = __toESM(require("node:path"), 1);
18957
18958
  var import_node_os = __toESM(require("node:os"), 1);
18958
18959
  function hostPaths(scope) {
@@ -18982,10 +18983,27 @@ function prepareHostDirectory(scope) {
18982
18983
  readPrivateFile(paths.token, 256);
18983
18984
  return paths;
18984
18985
  }
18985
- function writeHostJson(file, data) {
18986
+ async function writeHostJson(file, data) {
18986
18987
  const temporary = `${file}.${(0, import_node_crypto.randomUUID)()}.tmp`;
18987
18988
  (0, import_node_fs4.writeFileSync)(temporary, JSON.stringify(data) + "\n", { mode: 384, flag: "wx" });
18988
- (0, import_node_fs4.renameSync)(temporary, file);
18989
+ const deadline = Date.now() + 5e3;
18990
+ try {
18991
+ for (; ; ) {
18992
+ try {
18993
+ await (0, import_promises.rename)(temporary, file);
18994
+ return;
18995
+ } catch (error) {
18996
+ if (process.platform !== "win32" || !["EPERM", "EACCES", "EBUSY"].includes(error.code ?? "") || Date.now() >= deadline) throw error;
18997
+ await new Promise((resolve) => setTimeout(resolve, 50));
18998
+ }
18999
+ }
19000
+ } catch (error) {
19001
+ try {
19002
+ (0, import_node_fs4.rmSync)(temporary, { force: true });
19003
+ } catch {
19004
+ }
19005
+ throw error;
19006
+ }
18989
19007
  }
18990
19008
 
18991
19009
  // packages/pty-host/src/gateway.ts
@@ -20181,7 +20199,7 @@ async function startHost(scope, release) {
20181
20199
  gatewayUrl: gateway.url,
20182
20200
  release
20183
20201
  };
20184
- writeHostJson(paths.descriptor, descriptor);
20202
+ await writeHostJson(paths.descriptor, descriptor);
20185
20203
  process.once("SIGTERM", () => {
20186
20204
  void shutdown();
20187
20205
  });