@sema-agent/cli 1.0.1 → 1.0.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/sema.js +999 -689
package/sema.js CHANGED
@@ -2,6 +2,7 @@
2
2
  import { createRequire as __semaCreateRequire } from 'node:module';
3
3
  const require = __semaCreateRequire(import.meta.url);
4
4
  process.env.SEMA_FULL_REPL = process.env.SEMA_FULL_REPL || "1";
5
+ process.env.NODE_ENV = process.env.NODE_ENV || "production";
5
6
  // Sema shell (built from a re-syncable CC v2.1.187 copy; telemetry no-op-aliased, no Anthropic backend)
6
7
 
7
8
  var __create = Object.create;
@@ -11235,10 +11236,10 @@ async function setupSkills(ctx) {
11235
11236
  try {
11236
11237
  const versionId = await resolveSkillVersion(client4, skill.skill_id, skill.version);
11237
11238
  const version5 = await client4.beta.skills.versions.retrieve(versionId, { skill_id: skill.skill_id });
11238
- let dirname88 = path3.basename(version5.name.trim());
11239
- if (dirname88 === "" || dirname88 === "." || dirname88 === "..")
11240
- dirname88 = skill.skill_id;
11241
- const dest = path3.resolve(skillsRoot, dirname88);
11239
+ let dirname89 = path3.basename(version5.name.trim());
11240
+ if (dirname89 === "" || dirname89 === "." || dirname89 === "..")
11241
+ dirname89 = skill.skill_id;
11242
+ const dest = path3.resolve(skillsRoot, dirname89);
11242
11243
  if (dest !== skillsRoot && !dest.startsWith(skillsRoot + path3.sep)) {
11243
11244
  log2.warn("skill name escapes the skills dir; skipping", {
11244
11245
  component: "agent-tool-context",
@@ -19764,7 +19765,7 @@ var require_cross_spawn = __commonJS({
19764
19765
  enoent.hookChildProcess(spawned, parsed);
19765
19766
  return spawned;
19766
19767
  }
19767
- function spawnSync12(command8, args, options) {
19768
+ function spawnSync13(command8, args, options) {
19768
19769
  const parsed = parse14(command8, args, options);
19769
19770
  const result = cp2.spawnSync(parsed.command, parsed.args, parsed.options);
19770
19771
  result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
@@ -19772,7 +19773,7 @@ var require_cross_spawn = __commonJS({
19772
19773
  }
19773
19774
  module2.exports = spawn17;
19774
19775
  module2.exports.spawn = spawn17;
19775
- module2.exports.sync = spawnSync12;
19776
+ module2.exports.sync = spawnSync13;
19776
19777
  module2.exports._parse = parse14;
19777
19778
  module2.exports._enoent = enoent;
19778
19779
  }
@@ -103077,7 +103078,7 @@ var init_ErrorOverview = __esm({
103077
103078
  var import_react9, TerminalSizeContext;
103078
103079
  var init_TerminalSizeContext = __esm({
103079
103080
  "build-src/src/ink/components/TerminalSizeContext.tsx"() {
103080
- import_react9 = __toESM(require_react());
103081
+ import_react9 = __toESM(require_react(), 1);
103081
103082
  TerminalSizeContext = (0, import_react9.createContext)(null);
103082
103083
  }
103083
103084
  });
@@ -126443,7 +126444,7 @@ var require_snapshot_recorder = __commonJS({
126443
126444
  "node_modules/undici/lib/mock/snapshot-recorder.js"(exports2, module2) {
126444
126445
  "use strict";
126445
126446
  var { writeFile: writeFile54, readFile: readFile59, mkdir: mkdir51 } = __require("node:fs/promises");
126446
- var { dirname: dirname88, resolve: resolve53 } = __require("node:path");
126447
+ var { dirname: dirname89, resolve: resolve53 } = __require("node:path");
126447
126448
  var { setTimeout: setTimeout3, clearTimeout: clearTimeout2 } = __require("node:timers");
126448
126449
  var { InvalidArgumentError: InvalidArgumentError2, UndiciError } = require_errors();
126449
126450
  var { hashId, isUrlExcludedFactory, normalizeHeaders: normalizeHeaders3, createHeaderFilters } = require_snapshot_utils();
@@ -126689,7 +126690,7 @@ var require_snapshot_recorder = __commonJS({
126689
126690
  throw new InvalidArgumentError2("Snapshot path is required");
126690
126691
  }
126691
126692
  const resolvedPath = resolve53(path27);
126692
- await mkdir51(dirname88(resolvedPath), { recursive: true });
126693
+ await mkdir51(dirname89(resolvedPath), { recursive: true });
126693
126694
  const data = Array.from(this.#snapshots.entries()).map(([hash2, snapshot2]) => ({
126694
126695
  hash: hash2,
126695
126696
  snapshot: snapshot2
@@ -155228,9 +155229,9 @@ var init_handler = __esm({
155228
155229
  if (this.fsw.closed) {
155229
155230
  return;
155230
155231
  }
155231
- const dirname88 = sp.dirname(file2);
155232
+ const dirname89 = sp.dirname(file2);
155232
155233
  const basename67 = sp.basename(file2);
155233
- const parent2 = this.fsw._getWatchedDir(dirname88);
155234
+ const parent2 = this.fsw._getWatchedDir(dirname89);
155234
155235
  let prevStats = stats3;
155235
155236
  if (parent2.has(basename67))
155236
155237
  return;
@@ -155257,7 +155258,7 @@ var init_handler = __esm({
155257
155258
  prevStats = newStats2;
155258
155259
  }
155259
155260
  } catch (error52) {
155260
- this.fsw._remove(dirname88, basename67);
155261
+ this.fsw._remove(dirname89, basename67);
155261
155262
  }
155262
155263
  } else if (parent2.has(basename67)) {
155263
155264
  const at = newStats.atimeMs;
@@ -185465,7 +185466,7 @@ var require_dist4 = __commonJS({
185465
185466
  var src_exports = {};
185466
185467
  __export2(src_exports, {
185467
185468
  Socks5Server: () => Socks5Server,
185468
- createServer: () => createServer9,
185469
+ createServer: () => createServer10,
185469
185470
  defaultConnectionHandler: () => connectionHandler_default
185470
185471
  });
185471
185472
  module2.exports = __toCommonJS2(src_exports);
@@ -185668,12 +185669,12 @@ var require_dist4 = __commonJS({
185668
185669
  this.socket.resume();
185669
185670
  }
185670
185671
  };
185671
- var import_net6 = __toESM2(__require("net"));
185672
+ var import_net7 = __toESM2(__require("net"));
185672
185673
  function connectionHandler_default(connection, sendStatus) {
185673
185674
  if (connection.command !== "connect") return sendStatus("COMMAND_NOT_SUPPORTED");
185674
185675
  connection.socket.on("error", () => {
185675
185676
  });
185676
- const stream5 = import_net6.default.createConnection({
185677
+ const stream5 = import_net7.default.createConnection({
185677
185678
  host: connection.destAddress,
185678
185679
  port: connection.destPort
185679
185680
  });
@@ -185756,7 +185757,7 @@ var require_dist4 = __commonJS({
185756
185757
  return this;
185757
185758
  }
185758
185759
  };
185759
- function createServer9(opts) {
185760
+ function createServer10(opts) {
185760
185761
  const server = new Socks5Server();
185761
185762
  if (opts?.auth) server.setAuthHandler((conn) => {
185762
185763
  return conn.username === opts.auth.username && conn.password === opts.auth.password;
@@ -186357,8 +186358,8 @@ function generateProxyEnvVars(httpProxyPort, socksProxyPort, caCertPath, proxyAu
186357
186358
  const auth3 = proxyAuthToken2 ? `srt:${proxyAuthToken2}@` : "";
186358
186359
  const envVars = [`SANDBOX_RUNTIME=1`];
186359
186360
  if (!skipTmpdir) {
186360
- const tmpdir16 = process.env.CLAUDE_CODE_TMPDIR || process.env.CLAUDE_TMPDIR || "/tmp/claude";
186361
- envVars.push(`TMPDIR=${tmpdir16}`);
186361
+ const tmpdir17 = process.env.CLAUDE_CODE_TMPDIR || process.env.CLAUDE_TMPDIR || "/tmp/claude";
186362
+ envVars.push(`TMPDIR=${tmpdir17}`);
186362
186363
  }
186363
186364
  if (caCertPath) {
186364
186365
  for (const v2 of CA_TRUST_VARS) {
@@ -227307,11 +227308,11 @@ async function createBashShellProvider(shellPath, options) {
227307
227308
  }
227308
227309
  lastSnapshotFilePath = snapshotFilePath;
227309
227310
  currentSandboxTmpDir = opts.sandboxTmpDir;
227310
- const tmpdir16 = osTmpdir();
227311
+ const tmpdir17 = osTmpdir();
227311
227312
  const isWindows2 = getPlatform() === "windows";
227312
- const shellTmpdir = isWindows2 ? windowsPathToPosixPath(tmpdir16) : tmpdir16;
227313
+ const shellTmpdir = isWindows2 ? windowsPathToPosixPath(tmpdir17) : tmpdir17;
227313
227314
  const shellCwdFilePath = opts.useSandbox ? posixJoin(opts.sandboxTmpDir, `cwd-${opts.id}`) : posixJoin(shellTmpdir, `claude-${opts.id}-cwd`);
227314
- const cwdFilePath = opts.useSandbox ? posixJoin(opts.sandboxTmpDir, `cwd-${opts.id}`) : nativeJoin(tmpdir16, `claude-${opts.id}-cwd`);
227315
+ const cwdFilePath = opts.useSandbox ? posixJoin(opts.sandboxTmpDir, `cwd-${opts.id}`) : nativeJoin(tmpdir17, `claude-${opts.id}-cwd`);
227315
227316
  const normalizedCommand = rewriteWindowsNullRedirect(command8);
227316
227317
  const addStdinRedirect = shouldAddStdinRedirect(normalizedCommand);
227317
227318
  let quotedCommand = quoteShellCommand(normalizedCommand, addStdinRedirect);
@@ -266876,7 +266877,7 @@ var require_websocket2 = __commonJS({
266876
266877
  var http3 = __require("http");
266877
266878
  var net = __require("net");
266878
266879
  var tls = __require("tls");
266879
- var { randomBytes: randomBytes26, createHash: createHash26 } = __require("crypto");
266880
+ var { randomBytes: randomBytes26, createHash: createHash27 } = __require("crypto");
266880
266881
  var { Duplex, Readable: Readable5 } = __require("stream");
266881
266882
  var { URL: URL6 } = __require("url");
266882
266883
  var PerMessageDeflate2 = require_permessage_deflate2();
@@ -267544,7 +267545,7 @@ var require_websocket2 = __commonJS({
267544
267545
  abortHandshake(websocket, socket, "Invalid Upgrade header");
267545
267546
  return;
267546
267547
  }
267547
- const digest = createHash26("sha1").update(key + GUID).digest("base64");
267548
+ const digest = createHash27("sha1").update(key + GUID).digest("base64");
267548
267549
  if (res.headers["sec-websocket-accept"] !== digest) {
267549
267550
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
267550
267551
  return;
@@ -267913,7 +267914,7 @@ var require_websocket_server = __commonJS({
267913
267914
  var EventEmitter5 = __require("events");
267914
267915
  var http3 = __require("http");
267915
267916
  var { Duplex } = __require("stream");
267916
- var { createHash: createHash26 } = __require("crypto");
267917
+ var { createHash: createHash27 } = __require("crypto");
267917
267918
  var extension2 = require_extension();
267918
267919
  var PerMessageDeflate2 = require_permessage_deflate2();
267919
267920
  var subprotocol2 = require_subprotocol();
@@ -268220,7 +268221,7 @@ var require_websocket_server = __commonJS({
268220
268221
  );
268221
268222
  }
268222
268223
  if (this._state > RUNNING) return abortHandshake(socket, 503);
268223
- const digest = createHash26("sha1").update(key + GUID).digest("base64");
268224
+ const digest = createHash27("sha1").update(key + GUID).digest("base64");
268224
268225
  const headers = [
268225
268226
  "HTTP/1.1 101 Switching Protocols",
268226
268227
  "Upgrade: websocket",
@@ -329814,9 +329815,9 @@ function streamingTailWrap(unstableSuffix) {
329814
329815
  var import_compiler_runtime43, import_react43, import_jsx_runtime53, TOKEN_CACHE_MAX, tokenCache, MD_SYNTAX_RE;
329815
329816
  var init_Markdown = __esm({
329816
329817
  "build-src/src/components/Markdown.tsx"() {
329817
- import_compiler_runtime43 = __toESM(require_compiler_runtime());
329818
+ import_compiler_runtime43 = __toESM(require_compiler_runtime(), 1);
329818
329819
  init_marked_esm();
329819
- import_react43 = __toESM(require_react());
329820
+ import_react43 = __toESM(require_react(), 1);
329820
329821
  init_useSettings();
329821
329822
  init_ink2();
329822
329823
  init_cliHighlight();
@@ -329824,7 +329825,7 @@ var init_Markdown = __esm({
329824
329825
  init_markdown();
329825
329826
  init_messages4();
329826
329827
  init_MarkdownTable();
329827
- import_jsx_runtime53 = __toESM(require_jsx_runtime());
329828
+ import_jsx_runtime53 = __toESM(require_jsx_runtime(), 1);
329828
329829
  TOKEN_CACHE_MAX = 500;
329829
329830
  tokenCache = /* @__PURE__ */ new Map();
329830
329831
  MD_SYNTAX_RE = /[#*`|[>\-_~]|\n\n|^\d+\. |\n\d+\. /;
@@ -351681,7 +351682,7 @@ function useClaudeAiLimits() {
351681
351682
  var import_react64;
351682
351683
  var init_claudeAiLimitsHook = __esm({
351683
351684
  "build-src/src/services/claudeAiLimitsHook.ts"() {
351684
- import_react64 = __toESM(require_react(), 1);
351685
+ import_react64 = __toESM(require_react());
351685
351686
  init_claudeAiLimits();
351686
351687
  }
351687
351688
  });
@@ -361974,6 +361975,7 @@ __export(state_exports2, {
361974
361975
  import { spawnSync as spawnSync6 } from "child_process";
361975
361976
  import { createHash as createHash18, randomBytes as randomBytes13 } from "crypto";
361976
361977
  import { chmod as chmod9, mkdir as mkdir23, readdir as readdir17, readFile as readFile28, rename as rename8, unlink as unlink13, writeFile as writeFile21 } from "fs/promises";
361978
+ import { tmpdir as tmpdir9 } from "os";
361977
361979
  import { join as join93 } from "path";
361978
361980
  function isTerminalJobState(state3) {
361979
361981
  return state3 === "done" || state3 === "failed" || state3 === "stopped";
@@ -362123,11 +362125,13 @@ function getDaemonJsonPath() {
362123
362125
  return join93(getClaudeConfigHomeDir(), "daemon.json");
362124
362126
  }
362125
362127
  function getDaemonSocketPath() {
362128
+ const h = createHash18("sha256").update(getClaudeConfigHomeDir()).digest("hex").slice(0, 12);
362126
362129
  if (process.platform === "win32") {
362127
- const h = createHash18("sha256").update(getClaudeConfigHomeDir()).digest("hex").slice(0, 12);
362128
362130
  return `\\\\.\\pipe\\sema-daemon-${h}`;
362129
362131
  }
362130
- return join93(getClaudeConfigHomeDir(), "daemon.sock");
362132
+ let dir = join93(tmpdir9(), `sema-d-${h}`);
362133
+ if (join93(dir, "d.sock").length > 100) dir = `/tmp/sema-d-${h}`;
362134
+ return join93(dir, "d.sock");
362131
362135
  }
362132
362136
  function getDaemonLogPath() {
362133
362137
  return join93(getClaudeConfigHomeDir(), "daemon.log");
@@ -362233,7 +362237,7 @@ __export(client_exports2, {
362233
362237
  dispatchJob: () => dispatchJob,
362234
362238
  ensureDaemonRunning: () => ensureDaemonRunning
362235
362239
  });
362236
- import { spawn as spawn8 } from "child_process";
362240
+ import { spawn as spawn8, spawnSync as spawnSync7 } from "child_process";
362237
362241
  import { randomUUID as randomUUID17 } from "crypto";
362238
362242
  import { mkdir as mkdir24, rename as rename9, writeFile as writeFile22 } from "fs/promises";
362239
362243
  import { createConnection as createConnection2 } from "net";
@@ -362278,18 +362282,54 @@ async function pingOk(info) {
362278
362282
  return false;
362279
362283
  }
362280
362284
  }
362285
+ function spawnDaemonViaWmi() {
362286
+ const script = process.argv[1];
362287
+ if (!script) return false;
362288
+ const cmdLine = [
362289
+ `"${process.execPath}"`,
362290
+ `"${script}"`,
362291
+ "daemon",
362292
+ "run",
362293
+ "--origin",
362294
+ "transient",
362295
+ "--config-dir",
362296
+ `"${getClaudeConfigHomeDir()}"`
362297
+ ].join(" ");
362298
+ const psCmdLine = cmdLine.replace(/'/g, "''");
362299
+ const ps = `$si = New-CimInstance -ClassName Win32_ProcessStartup -ClientOnly -Property @{ShowWindow=[UInt16]0};$r = Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{CommandLine='${psCmdLine}'; ProcessStartupInformation=$si};if ($r.ReturnValue -eq 0) { exit 0 } else { exit 1 }`;
362300
+ const r = spawnSync7(
362301
+ "powershell",
362302
+ [
362303
+ "-NoProfile",
362304
+ "-NonInteractive",
362305
+ // -EncodedCommand: the script carries quotes/braces — never trust cmd-line re-quoting
362306
+ "-EncodedCommand",
362307
+ Buffer.from(ps, "utf16le").toString("base64")
362308
+ ],
362309
+ { stdio: "ignore", windowsHide: true, timeout: 15e3 }
362310
+ );
362311
+ return !r.error && r.status === 0;
362312
+ }
362281
362313
  async function ensureDaemonRunning() {
362282
362314
  let info = await readDaemonInfo();
362283
362315
  if (info && isDaemonAlive(info) && await pingOk(info)) return info;
362284
- const child = spawn8(
362285
- process.execPath,
362286
- [process.argv[1], "daemon", "run", "--origin", "transient"],
362287
- // detached: survives this CLI (POSIX setsid; win32 DETACHED_PROCESS — the supervisor must
362288
- // outlive its spawner on both). windowsHide keeps win32 from flashing a console window
362289
- // (no-op elsewhere; core host-platform precedent).
362290
- { detached: true, stdio: "ignore", env: process.env, windowsHide: true }
362291
- );
362292
- child.unref();
362316
+ const wmiSpawned = process.platform === "win32" && spawnDaemonViaWmi();
362317
+ if (!wmiSpawned) {
362318
+ if (process.platform === "win32") {
362319
+ console.error(
362320
+ "sema: WMI spawn unavailable \u2014 background tasks may not survive this session (daemon inherits the session Job object)"
362321
+ );
362322
+ }
362323
+ const child = spawn8(
362324
+ process.execPath,
362325
+ [process.argv[1], "daemon", "run", "--origin", "transient"],
362326
+ // detached: survives this CLI (POSIX setsid; win32 DETACHED_PROCESS — the supervisor must
362327
+ // outlive its spawner on both). windowsHide keeps win32 from flashing a console window
362328
+ // (no-op elsewhere; core host-platform precedent).
362329
+ { detached: true, stdio: "ignore", env: process.env, windowsHide: true }
362330
+ );
362331
+ child.unref();
362332
+ }
362293
362333
  for (let i = 0; i < 40; i++) {
362294
362334
  await sleep4(150);
362295
362335
  info = await readDaemonInfo();
@@ -362365,6 +362405,7 @@ async function dispatchJob(job) {
362365
362405
  var MAX_RPC_BYTES, sleep4;
362366
362406
  var init_client7 = __esm({
362367
362407
  "build-src/src/daemon/client.ts"() {
362408
+ init_envUtils();
362368
362409
  init_state2();
362369
362410
  MAX_RPC_BYTES = 1048576;
362370
362411
  sleep4 = (ms) => new Promise((r) => setTimeout(r, ms));
@@ -362844,7 +362885,7 @@ __export(bg_exports, {
362844
362885
  stripLogAnsi: () => stripLogAnsi,
362845
362886
  tmuxSessionName: () => tmuxSessionName
362846
362887
  });
362847
- import { spawnSync as spawnSync7 } from "child_process";
362888
+ import { spawnSync as spawnSync8 } from "child_process";
362848
362889
  import { randomUUID as randomUUID18 } from "crypto";
362849
362890
  import { chmod as chmod10, mkdir as mkdir25, readdir as readdir18, readFile as readFile29, rm as rmrf, unlink as unlink14, writeFile as writeFile23 } from "fs/promises";
362850
362891
  import { join as join95 } from "path";
@@ -362878,6 +362919,13 @@ async function listSessions() {
362878
362919
  }
362879
362920
  try {
362880
362921
  const rec = JSON.parse(await readFile29(join95(dir, file2), "utf8"));
362922
+ if (rec.startedAt !== void 0 && processStartedAfter2(pid, rec.startedAt + 15e3) === true) {
362923
+ if (getPlatform() !== "wsl") {
362924
+ await unlink14(join95(dir, file2)).catch(() => {
362925
+ });
362926
+ }
362927
+ continue;
362928
+ }
362881
362929
  out6.push({ ...rec, pid });
362882
362930
  } catch {
362883
362931
  }
@@ -363107,9 +363155,9 @@ async function attachHandler(id, extraArgs = []) {
363107
363155
  if (!rec) return;
363108
363156
  const short = shortId(rec);
363109
363157
  const tmuxName = tmuxSessionName(rec);
363110
- const has2 = spawnSync7("tmux", ["has-session", "-t", `=${tmuxName}`], { stdio: "ignore" });
363158
+ const has2 = spawnSync8("tmux", ["has-session", "-t", `=${tmuxName}`], { stdio: "ignore" });
363111
363159
  if (has2.status === 0) {
363112
- const r2 = spawnSync7("tmux", ["attach-session", "-t", `=${tmuxName}`], { stdio: "inherit" });
363160
+ const r2 = spawnSync8("tmux", ["attach-session", "-t", `=${tmuxName}`], { stdio: "inherit" });
363113
363161
  process.exitCode = r2.status ?? 0;
363114
363162
  return;
363115
363163
  }
@@ -363123,7 +363171,7 @@ async function attachHandler(id, extraArgs = []) {
363123
363171
  }
363124
363172
  process.stderr.write(`no tmux session for ${short} \u2014 resuming ${rec.sessionId} in this terminal instead
363125
363173
  `);
363126
- const r = spawnSync7(
363174
+ const r = spawnSync8(
363127
363175
  process.execPath,
363128
363176
  [process.argv[1], "--resume", rec.sessionId],
363129
363177
  {
@@ -363136,13 +363184,7 @@ async function attachHandler(id, extraArgs = []) {
363136
363184
  process.exitCode = r.status ?? 0;
363137
363185
  }
363138
363186
  function processStartedAfter2(pid, epochMs) {
363139
- const r = spawnSync7("ps", ["-p", String(pid), "-o", "etime="], { encoding: "utf8" });
363140
- if (r.error || r.status !== 0) return null;
363141
- const m2 = /^(?:(\d+)-)?(?:(\d+):)?(\d+):(\d+)$/.exec((r.stdout ?? "").trim());
363142
- if (!m2) return null;
363143
- const [, d2, h, min, s] = m2;
363144
- const elapsedMs2 = (((Number(d2 ?? 0) * 24 + Number(h ?? 0)) * 60 + Number(min)) * 60 + Number(s)) * 1e3;
363145
- return Date.now() - elapsedMs2 > epochMs;
363187
+ return processStartedAfter(pid, epochMs);
363146
363188
  }
363147
363189
  function assessKillIdentity(rec, freshText) {
363148
363190
  if (freshText === null) return "gone";
@@ -363215,7 +363257,7 @@ async function legacyKill(resolved) {
363215
363257
  const freshText = await readFile29(pidFile, "utf8").catch(() => null);
363216
363258
  const identity3 = assessKillIdentity(rec, freshText);
363217
363259
  if (identity3 === "gone") {
363218
- spawnSync7("tmux", ["kill-session", "-t", `=${tmuxSessionName(rec)}`], { stdio: "ignore" });
363260
+ spawnSync8("tmux", ["kill-session", "-t", `=${tmuxSessionName(rec)}`], { stdio: "ignore" });
363219
363261
  process.stdout.write(`stopped ${short}
363220
363262
  `);
363221
363263
  return;
@@ -363244,7 +363286,7 @@ async function legacyKill(resolved) {
363244
363286
  }
363245
363287
  await unlink14(pidFile).catch(() => {
363246
363288
  });
363247
- spawnSync7("tmux", ["kill-session", "-t", `=${tmuxSessionName(rec)}`], { stdio: "ignore" });
363289
+ spawnSync8("tmux", ["kill-session", "-t", `=${tmuxSessionName(rec)}`], { stdio: "ignore" });
363248
363290
  process.stdout.write(`stopped ${short}
363249
363291
  `);
363250
363292
  }
@@ -363370,14 +363412,14 @@ async function rmHandler(id, extraArgs = []) {
363370
363412
  let keptWorktree;
363371
363413
  let keptReason;
363372
363414
  if (st2?.worktreePath) {
363373
- const dirty2 = spawnSync7("git", ["-C", st2.worktreePath, "status", "--porcelain"], {
363415
+ const dirty2 = spawnSync8("git", ["-C", st2.worktreePath, "status", "--porcelain"], {
363374
363416
  encoding: "utf8"
363375
363417
  });
363376
363418
  if (dirty2.status === 0 && (dirty2.stdout ?? "").trim().length > 0) {
363377
363419
  keptWorktree = st2.worktreePath;
363378
363420
  keptReason = "dirty";
363379
363421
  } else if (dirty2.status === 0) {
363380
- const removed = spawnSync7("git", ["-C", st2.cwd, "worktree", "remove", "--force", st2.worktreePath], {
363422
+ const removed = spawnSync8("git", ["-C", st2.cwd, "worktree", "remove", "--force", st2.worktreePath], {
363381
363423
  stdio: "ignore"
363382
363424
  });
363383
363425
  if (removed.status !== 0) {
@@ -363596,7 +363638,7 @@ async function handleBgFlag(args) {
363596
363638
  await handleBgFlagDaemon(rest, head);
363597
363639
  return;
363598
363640
  }
363599
- const tmuxOk = spawnSync7("tmux", ["-V"], { stdio: "ignore" });
363641
+ const tmuxOk = spawnSync8("tmux", ["-V"], { stdio: "ignore" });
363600
363642
  if (tmuxOk.error || tmuxOk.status !== 0) {
363601
363643
  process.stderr.write("Couldn't start the session \u2014 --bg requires tmux (not found on PATH)\n");
363602
363644
  process.exitCode = 1;
@@ -363633,7 +363675,7 @@ async function handleBgFlag(args) {
363633
363675
  await chmod10(envFile, 384);
363634
363676
  const inner = `. ${shq(envFile)}; rm -f ${shq(envFile)}; exec ${shq(process.execPath)} ${childArgs.map(shq).join(" ")}`;
363635
363677
  const cmd = `exec sh -c ${shq(inner)}`;
363636
- const spawned = spawnSync7(
363678
+ const spawned = spawnSync8(
363637
363679
  "tmux",
363638
363680
  ["new-session", "-d", "-s", tmuxName, "-c", process.cwd(), cmd],
363639
363681
  { stdio: ["ignore", "ignore", "pipe"] }
@@ -363647,10 +363689,10 @@ async function handleBgFlag(args) {
363647
363689
  process.exitCode = 1;
363648
363690
  return;
363649
363691
  }
363650
- spawnSync7("tmux", ["pipe-pane", "-t", `=${tmuxName}:`, "-o", `cat >> ${shq(logPath)}`], {
363692
+ spawnSync8("tmux", ["pipe-pane", "-t", `=${tmuxName}:`, "-o", `cat >> ${shq(logPath)}`], {
363651
363693
  stdio: "ignore"
363652
363694
  });
363653
- const paneOut = spawnSync7(
363695
+ const paneOut = spawnSync8(
363654
363696
  "tmux",
363655
363697
  ["display-message", "-p", "-t", `=${tmuxName}:`, "#{pane_pid}"],
363656
363698
  { encoding: "utf8" }
@@ -363681,6 +363723,7 @@ var LOGS_TAIL_LINES, killHandler;
363681
363723
  var init_bg2 = __esm({
363682
363724
  "build-src/src/cli/bg.ts"() {
363683
363725
  init_source2();
363726
+ init_state2();
363684
363727
  init_envUtils();
363685
363728
  init_genericProcessUtils();
363686
363729
  init_platform();
@@ -364371,11 +364414,11 @@ var init_filesApi = __esm({
364371
364414
 
364372
364415
  // build-src/src/utils/tempfile.ts
364373
364416
  import { createHash as createHash19, randomUUID as randomUUID20 } from "crypto";
364374
- import { tmpdir as tmpdir9 } from "os";
364417
+ import { tmpdir as tmpdir10 } from "os";
364375
364418
  import { join as join97 } from "path";
364376
364419
  function generateTempFilePath(prefix = "claude-prompt", extension2 = ".md", options) {
364377
364420
  const id = options?.contentHash ? createHash19("sha256").update(options.contentHash).digest("hex").slice(0, 16) : randomUUID20();
364378
- return join97(tmpdir9(), `${prefix}-${id}${extension2}`);
364421
+ return join97(tmpdir10(), `${prefix}-${id}${extension2}`);
364379
364422
  }
364380
364423
  var init_tempfile = __esm({
364381
364424
  "build-src/src/utils/tempfile.ts"() {
@@ -426781,6 +426824,24 @@ var init_engineRuntimeStatus = __esm({
426781
426824
  }
426782
426825
  });
426783
426826
 
426827
+ // build-src/src/sema/enginePortDerive.ts
426828
+ import { createHash as createHash21 } from "crypto";
426829
+ function derivedDefaultEnginePort(configHome = getClaudeConfigHomeDir()) {
426830
+ const h = createHash21("sha256").update(configHome).digest();
426831
+ return DERIVED_ENGINE_PORT_BASE + h.readUInt32BE(0) % DERIVED_ENGINE_PORT_SPAN;
426832
+ }
426833
+ function derivedPortCandidate(base, i) {
426834
+ return DERIVED_ENGINE_PORT_BASE + (base - DERIVED_ENGINE_PORT_BASE + i) % DERIVED_ENGINE_PORT_SPAN;
426835
+ }
426836
+ var DERIVED_ENGINE_PORT_BASE, DERIVED_ENGINE_PORT_SPAN;
426837
+ var init_enginePortDerive = __esm({
426838
+ "build-src/src/sema/enginePortDerive.ts"() {
426839
+ init_envUtils();
426840
+ DERIVED_ENGINE_PORT_BASE = 43e3;
426841
+ DERIVED_ENGINE_PORT_SPAN = 2e3;
426842
+ }
426843
+ });
426844
+
426784
426845
  // build-src/src/sema/cloudProfile.ts
426785
426846
  import { existsSync as existsSync12, mkdirSync as mkdirSync10, readFileSync as readFileSync22, writeFileSync as writeFileSync9, chmodSync as chmodSync4 } from "fs";
426786
426847
  import { homedir as homedir30 } from "os";
@@ -427374,7 +427435,7 @@ function configuredEnginePort() {
427374
427435
  if (Number.isInteger(p) && p > 0 && p < 65536) {
427375
427436
  return { port: p, source: fromSettings !== void 0 ? "settings" : "env" };
427376
427437
  }
427377
- return { port: 47362, source: "default" };
427438
+ return { port: derivedDefaultEnginePort(), source: "default" };
427378
427439
  }
427379
427440
  function configuredPort() {
427380
427441
  return configuredEnginePort().port;
@@ -427433,6 +427494,7 @@ var ENGINE_URL_ENV, TRUSTED_ENGINE_HOSTS_KEY, SYNC_ENGINE_URL_ENV, AUTO_SYNC_SOU
427433
427494
  var init_engineTarget = __esm({
427434
427495
  "build-src/src/sema/engineTarget.ts"() {
427435
427496
  init_envUtils();
427497
+ init_enginePortDerive();
427436
427498
  init_cloudExecutionPolicy();
427437
427499
  ENGINE_URL_ENV = "SEMA_ENGINE_URL";
427438
427500
  TRUSTED_ENGINE_HOSTS_KEY = "trustedEngineHosts";
@@ -427733,7 +427795,7 @@ __export(cloudConfigWire_exports, {
427733
427795
  refreshCloudConfigNow: () => refreshCloudConfigNow,
427734
427796
  shadowModelsExists: () => shadowModelsExists
427735
427797
  });
427736
- import { createHash as createHash21 } from "node:crypto";
427798
+ import { createHash as createHash22 } from "node:crypto";
427737
427799
  import { existsSync as existsSync14, mkdirSync as mkdirSync12, readFileSync as readFileSync24, writeFileSync as writeFileSync11 } from "node:fs";
427738
427800
  import { dirname as dirname55, join as join117 } from "node:path";
427739
427801
  function cloudConfigEnabled() {
@@ -427780,7 +427842,7 @@ function writeShadowModels(profileName, modelsDoc) {
427780
427842
  }
427781
427843
  }
427782
427844
  function sha256Address(content) {
427783
- return `sha256:${createHash21("sha256").update(content, "utf8").digest("hex")}`;
427845
+ return `sha256:${createHash22("sha256").update(content, "utf8").digest("hex")}`;
427784
427846
  }
427785
427847
  async function getJson(url4, accessToken, headers = {}) {
427786
427848
  const res = await fetch(url4, {
@@ -427999,7 +428061,6 @@ var init_cloudConfigWire = __esm({
427999
428061
  // build-src/src/sema/engineLifecycleManager.ts
428000
428062
  var engineLifecycleManager_exports = {};
428001
428063
  __export(engineLifecycleManager_exports, {
428002
- DEFAULT_ENGINE_PORT: () => DEFAULT_ENGINE_PORT,
428003
428064
  applyOpenAiEnvAliases: () => applyOpenAiEnvAliases,
428004
428065
  assembleChildEnv: () => assembleChildEnv,
428005
428066
  describeEngineInitFailure: () => describeEngineInitFailure,
@@ -428014,6 +428075,8 @@ __export(engineLifecycleManager_exports, {
428014
428075
  initEngineLifecycle: () => initEngineLifecycle,
428015
428076
  isLocalEngineActive: () => isLocalEngineActive,
428016
428077
  isProcessAlive: () => isProcessAlive,
428078
+ pickFreeEnginePort: () => pickFreeEnginePort,
428079
+ pinnedEnginePort: () => pinnedEnginePort,
428017
428080
  probeHealth: () => probeHealth,
428018
428081
  probeLocalEngineHealth: () => probeLocalEngineHealth,
428019
428082
  readMemorySyncSettings: () => readMemorySyncSettings,
@@ -428028,12 +428091,14 @@ __export(engineLifecycleManager_exports, {
428028
428091
  startHealthCheckLoop: () => startHealthCheckLoop
428029
428092
  });
428030
428093
  import { spawn as spawn10 } from "child_process";
428094
+ import { createServer as createServer7 } from "net";
428031
428095
  import {
428032
428096
  closeSync as closeSync7,
428033
428097
  existsSync as existsSync15,
428034
428098
  fsyncSync as fsyncSync5,
428035
428099
  mkdirSync as mkdirSync13,
428036
428100
  openSync as openSync8,
428101
+ readdirSync as readdirSync7,
428037
428102
  readFileSync as readFileSync25,
428038
428103
  realpathSync as realpathSync6,
428039
428104
  renameSync as renameSync5,
@@ -428428,13 +428493,70 @@ async function reapStaleEngine(portFile, opts) {
428428
428493
  }
428429
428494
  }
428430
428495
  }
428431
- function selectPort() {
428496
+ function otherSessionsMidTurn() {
428497
+ const dir = join118(getClaudeConfigHomeDir(), "sessions");
428498
+ let files2;
428499
+ try {
428500
+ files2 = readdirSync7(dir);
428501
+ } catch {
428502
+ return 0;
428503
+ }
428504
+ let busy = 0;
428505
+ for (const f of files2) {
428506
+ if (!/^\d+\.json$/.test(f)) continue;
428507
+ const pid = Number.parseInt(f.slice(0, -5), 10);
428508
+ if (pid === process.pid || !isProcessAlive(pid)) continue;
428509
+ try {
428510
+ const rec = JSON.parse(readFileSync25(join118(dir, f), "utf8"));
428511
+ if (rec.kind === "daemon") continue;
428512
+ if (rec.status !== "busy" && rec.status !== "waiting") continue;
428513
+ if (rec.startedAt !== void 0 && processStartedAfter(pid, rec.startedAt + 15e3) === true) {
428514
+ continue;
428515
+ }
428516
+ busy++;
428517
+ } catch {
428518
+ }
428519
+ }
428520
+ return busy;
428521
+ }
428522
+ function pinnedEnginePort() {
428432
428523
  const override = process.env.SEMA_ENGINE_PORT;
428433
428524
  if (override) {
428434
428525
  const p = Number.parseInt(override, 10);
428435
428526
  if (Number.isInteger(p) && p > 0 && p < 65536) return p;
428436
428527
  }
428437
- return DEFAULT_ENGINE_PORT;
428528
+ return null;
428529
+ }
428530
+ function portIsFree(port) {
428531
+ return new Promise((resolve53) => {
428532
+ const srv = createServer7();
428533
+ srv.once("error", () => resolve53(false));
428534
+ try {
428535
+ srv.listen({ port, host: "127.0.0.1", exclusive: true }, () => {
428536
+ srv.close(() => resolve53(true));
428537
+ });
428538
+ } catch {
428539
+ resolve53(false);
428540
+ }
428541
+ });
428542
+ }
428543
+ async function pickFreeEnginePort(configHome = getClaudeConfigHomeDir()) {
428544
+ const base = derivedDefaultEnginePort(configHome);
428545
+ for (let i = 0; i < DERIVED_PORT_PROBE_MAX; i++) {
428546
+ const candidate = derivedPortCandidate(base, i);
428547
+ if (await portIsFree(candidate)) {
428548
+ if (candidate !== base) {
428549
+ logForDebugging(
428550
+ `[engine-lifecycle] derived default port ${base} is busy \u2014 linear-probed to free port ${candidate}`
428551
+ );
428552
+ }
428553
+ return candidate;
428554
+ }
428555
+ }
428556
+ logForDebugging(
428557
+ `[engine-lifecycle] no free port within ${DERIVED_PORT_PROBE_MAX} probes from derived ${base} \u2014 falling back to ${base} (handshake gate reports honestly)`
428558
+ );
428559
+ return base;
428438
428560
  }
428439
428561
  async function initEngineLifecycle() {
428440
428562
  return recordInitResult(await initEngineLifecycleInner());
@@ -428482,10 +428604,21 @@ async function initEngineLifecycleInner() {
428482
428604
  const wantVersion = localEngineVersion();
428483
428605
  const versionStale = health2 !== null && wantVersion !== void 0 && health2.version !== wantVersion;
428484
428606
  const sourceStale = (existing.configSource ?? "local") !== engineConfigSource;
428485
- const desiredPort = selectPort();
428486
- const portStale = existing.port !== desiredPort;
428607
+ const desiredPort = pinnedEnginePort();
428608
+ const portStale = desiredPort !== null && existing.port !== desiredPort;
428487
428609
  const pidStale = health2 !== null && typeof health2.pid === "number" && health2.pid !== existing.pid;
428488
- if (health2 && !versionStale && !sourceStale && !portStale && !pidStale && healthIdentityMatches(health2, expectedDataRoot)) {
428610
+ const engineCompatible = health2 !== null && !versionStale && !sourceStale && !pidStale && healthIdentityMatches(health2, expectedDataRoot);
428611
+ let portMoveDeferred = false;
428612
+ if (engineCompatible && portStale) {
428613
+ const midTurn = otherSessionsMidTurn();
428614
+ if (midTurn > 0) {
428615
+ portMoveDeferred = true;
428616
+ logForDebugging(
428617
+ `[engine-lifecycle] port-config mismatch (anchor port=${existing.port} != configured ${desiredPort}) but ${midTurn} local session(s) are mid-turn \u2014 deferring the restart, reusing the engine on port ${existing.port} (the port moves on a later launch when no turn is in flight)`
428618
+ );
428619
+ }
428620
+ }
428621
+ if (engineCompatible && (!portStale || portMoveDeferred)) {
428489
428622
  const baseUrl2 = `http://127.0.0.1:${existing.port}`;
428490
428623
  const instance2 = {
428491
428624
  port: existing.port,
@@ -428513,7 +428646,7 @@ async function initEngineLifecycleInner() {
428513
428646
  await reapStaleEngine(existing, { killPid: false });
428514
428647
  }
428515
428648
  }
428516
- const port = selectPort();
428649
+ const port = pinnedEnginePort() ?? await pickFreeEnginePort(configHome);
428517
428650
  const entry = resolveEngineEntry();
428518
428651
  if (!entry) {
428519
428652
  logForDebugging(
@@ -428783,6 +428916,32 @@ function attachOwnedEngineExitWatch(instance) {
428783
428916
  function resetDeadRespawnStateForTests() {
428784
428917
  deadRespawnInFlight = false;
428785
428918
  recentDeathTimestamps = [];
428919
+ cooldownRetryPending = false;
428920
+ cooldownRetryLevel = 0;
428921
+ }
428922
+ function nextCooldownDelayMs() {
428923
+ return Math.min(CRASH_LOOP_COOLDOWN_BASE_MS * 2 ** cooldownRetryLevel, CRASH_LOOP_COOLDOWN_CAP_MS);
428924
+ }
428925
+ function scheduleCooldownRetry(deps2) {
428926
+ if (cooldownRetryPending) return;
428927
+ cooldownRetryPending = true;
428928
+ const delay = nextCooldownDelayMs();
428929
+ cooldownRetryLevel++;
428930
+ logForDebugging(
428931
+ `[engine-lifecycle] engine auto-restart parked \u2014 cooldown retry scheduled in ${Math.round(delay / 1e3)}s`
428932
+ );
428933
+ const fire = () => {
428934
+ cooldownRetryPending = false;
428935
+ recentDeathTimestamps = [];
428936
+ void runEngineDeadRespawn(deps2).catch(() => {
428937
+ });
428938
+ };
428939
+ if (deps2.scheduleRetry) {
428940
+ deps2.scheduleRetry(fire, delay);
428941
+ return;
428942
+ }
428943
+ const t2 = setTimeout(fire, delay);
428944
+ if (typeof t2.unref === "function") t2.unref();
428786
428945
  }
428787
428946
  async function runEngineDeadRespawn(deps2) {
428788
428947
  if (deadRespawnInFlight) return false;
@@ -428795,13 +428954,15 @@ async function runEngineDeadRespawn(deps2) {
428795
428954
  recentDeathTimestamps = recentDeathTimestamps.filter((d2) => t2 - d2 < CRASH_LOOP_WINDOW_MS);
428796
428955
  recentDeathTimestamps.push(t2);
428797
428956
  if (recentDeathTimestamps.length > CRASH_LOOP_MAX_DEATHS) {
428957
+ const retryInS = Math.round(nextCooldownDelayMs() / 1e3);
428798
428958
  logForDebugging(
428799
- `[engine-lifecycle] engine died ${recentDeathTimestamps.length} times inside ${CRASH_LOOP_WINDOW_MS / 6e4}min \u2014 crash loop, auto-restart paused`
428959
+ `[engine-lifecycle] engine died ${recentDeathTimestamps.length} times inside ${CRASH_LOOP_WINDOW_MS / 6e4}min \u2014 crash loop, auto-restart paused (cooldown retry in ${retryInS}s)`
428800
428960
  );
428801
428961
  setEngineRuntimeStatus({
428802
428962
  phase: "failed",
428803
- detail: `engine crashed ${recentDeathTimestamps.length} times in ${CRASH_LOOP_WINDOW_MS / 6e4} minutes \u2014 auto-restart paused; check the engine log or run sema doctor`
428963
+ detail: `engine crashed ${recentDeathTimestamps.length} times in ${CRASH_LOOP_WINDOW_MS / 6e4} minutes \u2014 auto-restart paused; retrying automatically in ${retryInS}s (or run sema doctor)`
428804
428964
  });
428965
+ scheduleCooldownRetry(deps2);
428805
428966
  return false;
428806
428967
  }
428807
428968
  for (let i = 0; i < backoff3.length; i++) {
@@ -428814,6 +428975,7 @@ async function runEngineDeadRespawn(deps2) {
428814
428975
  }
428815
428976
  if (ok2) {
428816
428977
  logForDebugging(`[engine-lifecycle] dead-respawn succeeded on attempt ${i + 1}/${backoff3.length}`);
428978
+ cooldownRetryLevel = 0;
428817
428979
  setEngineRuntimeStatus({ phase: "recovered" });
428818
428980
  return true;
428819
428981
  }
@@ -428824,8 +428986,9 @@ async function runEngineDeadRespawn(deps2) {
428824
428986
  }
428825
428987
  setEngineRuntimeStatus({
428826
428988
  phase: "failed",
428827
- detail: `automatic engine restart failed after ${backoff3.length} attempts \u2014 run sema doctor or restart sema`
428989
+ detail: `automatic engine restart failed after ${backoff3.length} attempts \u2014 retrying automatically in ${Math.round(nextCooldownDelayMs() / 1e3)}s (or run sema doctor / restart sema)`
428828
428990
  });
428991
+ scheduleCooldownRetry(deps2);
428829
428992
  return false;
428830
428993
  } finally {
428831
428994
  deadRespawnInFlight = false;
@@ -428926,15 +429089,16 @@ async function waitForExit(pid, timeoutMs) {
428926
429089
  }
428927
429090
  return !isProcessAlive(pid);
428928
429091
  }
428929
- var DEFAULT_ENGINE_PORT, PORT_FILE_VERSION, HEALTH_POLL_INTERVAL_MS, HEALTH_POLL_MAX_ATTEMPTS, HEALTH_FETCH_TIMEOUT_MS, HEARTBEAT_INTERVAL_MS2, HEARTBEAT_MAX_MISSES, SHUTDOWN_GRACE_MS, SHUTDOWN_SECOND_TERM_GRACE_MS, LOCK_OPTS3, WORKFLOW_SIZE_GUIDELINE_VALUES, lastServiceAuthToken, lastInitFailureReason, lastInitFailureDetail, localEngineActive, expectedExitPids, onOwnedEngineExitCb, deadRespawnInFlight, CRASH_LOOP_WINDOW_MS, CRASH_LOOP_MAX_DEATHS, recentDeathTimestamps;
429092
+ var PORT_FILE_VERSION, HEALTH_POLL_INTERVAL_MS, HEALTH_POLL_MAX_ATTEMPTS, HEALTH_FETCH_TIMEOUT_MS, HEARTBEAT_INTERVAL_MS2, HEARTBEAT_MAX_MISSES, SHUTDOWN_GRACE_MS, SHUTDOWN_SECOND_TERM_GRACE_MS, LOCK_OPTS3, WORKFLOW_SIZE_GUIDELINE_VALUES, lastServiceAuthToken, lastInitFailureReason, lastInitFailureDetail, localEngineActive, DERIVED_PORT_PROBE_MAX, expectedExitPids, onOwnedEngineExitCb, deadRespawnInFlight, CRASH_LOOP_WINDOW_MS, CRASH_LOOP_MAX_DEATHS, recentDeathTimestamps, CRASH_LOOP_COOLDOWN_BASE_MS, CRASH_LOOP_COOLDOWN_CAP_MS, cooldownRetryPending, cooldownRetryLevel;
428930
429093
  var init_engineLifecycleManager = __esm({
428931
429094
  "build-src/src/sema/engineLifecycleManager.ts"() {
429095
+ init_state2();
428932
429096
  init_envUtils();
429097
+ init_enginePortDerive();
428933
429098
  init_ccConfigFallback();
428934
429099
  init_engineRuntimeStatus();
428935
429100
  init_lockfile();
428936
429101
  init_debug();
428937
- DEFAULT_ENGINE_PORT = 47362;
428938
429102
  PORT_FILE_VERSION = 1;
428939
429103
  HEALTH_POLL_INTERVAL_MS = 200;
428940
429104
  HEALTH_POLL_MAX_ATTEMPTS = 75;
@@ -428946,12 +429110,515 @@ var init_engineLifecycleManager = __esm({
428946
429110
  LOCK_OPTS3 = { stale: 1e4, retries: { retries: 3, minTimeout: 50 } };
428947
429111
  WORKFLOW_SIZE_GUIDELINE_VALUES = ["unrestricted", "small", "medium", "large"];
428948
429112
  localEngineActive = false;
429113
+ DERIVED_PORT_PROBE_MAX = 32;
428949
429114
  expectedExitPids = /* @__PURE__ */ new Set();
428950
429115
  onOwnedEngineExitCb = null;
428951
429116
  deadRespawnInFlight = false;
428952
429117
  CRASH_LOOP_WINDOW_MS = 5 * 6e4;
428953
429118
  CRASH_LOOP_MAX_DEATHS = 3;
428954
429119
  recentDeathTimestamps = [];
429120
+ CRASH_LOOP_COOLDOWN_BASE_MS = 6e4;
429121
+ CRASH_LOOP_COOLDOWN_CAP_MS = 10 * 6e4;
429122
+ cooldownRetryPending = false;
429123
+ cooldownRetryLevel = 0;
429124
+ }
429125
+ });
429126
+
429127
+ // build-src/src/utils/sessionState.ts
429128
+ function setSessionStateChangedListener(cb) {
429129
+ stateListener = cb;
429130
+ }
429131
+ function setSessionMetadataChangedListener(cb) {
429132
+ metadataListener = cb;
429133
+ }
429134
+ function setPermissionModeChangedListener(cb) {
429135
+ permissionModeListener = cb;
429136
+ }
429137
+ function getSessionState() {
429138
+ return currentState;
429139
+ }
429140
+ function notifySessionStateChanged(state3, details) {
429141
+ currentState = state3;
429142
+ stateListener?.(state3, details);
429143
+ if (state3 === "requires_action" && details) {
429144
+ hasPendingAction = true;
429145
+ metadataListener?.({
429146
+ pending_action: details
429147
+ });
429148
+ } else if (hasPendingAction) {
429149
+ hasPendingAction = false;
429150
+ metadataListener?.({ pending_action: null });
429151
+ }
429152
+ if (state3 === "idle") {
429153
+ metadataListener?.({ task_summary: null });
429154
+ }
429155
+ if (isEnvTruthy(process.env.SEMA_CODE_EMIT_SESSION_STATE_EVENTS)) {
429156
+ enqueueSdkEvent({
429157
+ type: "system",
429158
+ subtype: "session_state_changed",
429159
+ state: state3
429160
+ });
429161
+ }
429162
+ }
429163
+ function notifySessionMetadataChanged(metadata2) {
429164
+ metadataListener?.(metadata2);
429165
+ }
429166
+ function notifyPermissionModeChanged(mode) {
429167
+ permissionModeListener?.(mode);
429168
+ }
429169
+ var stateListener, metadataListener, permissionModeListener, hasPendingAction, currentState;
429170
+ var init_sessionState = __esm({
429171
+ "build-src/src/utils/sessionState.ts"() {
429172
+ init_envUtils();
429173
+ init_sdkEventQueue();
429174
+ stateListener = null;
429175
+ metadataListener = null;
429176
+ permissionModeListener = null;
429177
+ hasPendingAction = false;
429178
+ currentState = "idle";
429179
+ }
429180
+ });
429181
+
429182
+ // build-src/src/utils/taskSummary.ts
429183
+ var taskSummary_exports = {};
429184
+ __export(taskSummary_exports, {
429185
+ bgJobShort: () => bgJobShort,
429186
+ blockedSummaryFor: () => blockedSummaryFor,
429187
+ classifiedToPostTurnSummary: () => classifiedToPostTurnSummary,
429188
+ classifierSummaryEnabled: () => classifierSummaryEnabled,
429189
+ classifyTurnTail: () => classifyTurnTail,
429190
+ emitTurnEndSummary: () => emitTurnEndSummary,
429191
+ heuristicFallback: () => heuristicFallback,
429192
+ notifySessionActivityForSummary: () => notifySessionActivityForSummary,
429193
+ preClassifyTail: () => preClassifyTail,
429194
+ reportBgEngineDown: () => reportBgEngineDown,
429195
+ runClassifierSummaryForBlocked: () => runClassifierSummaryForBlocked,
429196
+ turnTail: () => turnTail
429197
+ });
429198
+ import { basename as basename35 } from "path";
429199
+ function classifierSummaryEnabled() {
429200
+ const v2 = process.env.SEMA_CODE_CLASSIFIER_SUMMARY ?? process.env[CLASSIFIER_SUMMARY_ENV];
429201
+ if (v2 === void 0) return true;
429202
+ return !/^(0|false|off|no|none)$/i.test(v2.trim());
429203
+ }
429204
+ function bgJobShort() {
429205
+ const dir = process.env.SEMA_JOB_DIR;
429206
+ if (!dir) return null;
429207
+ const short = basename35(dir);
429208
+ return short.length > 0 ? short : null;
429209
+ }
429210
+ function truncateDetail(s, max2 = DETAIL_MAX) {
429211
+ if (s.length <= max2) return s;
429212
+ let r = max2 - 1;
429213
+ const c2 = s.charCodeAt(r - 1);
429214
+ if (c2 >= 55296 && c2 <= 56319) r--;
429215
+ return s.slice(0, r) + "\u2026";
429216
+ }
429217
+ function insideCodeFence(e, t2) {
429218
+ let open20 = null;
429219
+ let openLen = 0;
429220
+ let o = 0;
429221
+ while (o < t2) {
429222
+ const i = e.indexOf("```", o);
429223
+ const s = e.indexOf("~~~", o);
429224
+ const a = i === -1 ? s : s === -1 ? i : Math.min(i, s);
429225
+ if (a === -1 || a >= t2) break;
429226
+ const ch2 = e[a];
429227
+ let c2 = a - 1;
429228
+ let u3 = 0;
429229
+ while (c2 >= 0 && e[c2] === " " && u3 < 3) {
429230
+ c2--;
429231
+ u3++;
429232
+ }
429233
+ const atLineStart = c2 < 0 || e[c2] === "\n";
429234
+ let len = 3;
429235
+ o = a + 3;
429236
+ while (e[o] === ch2) {
429237
+ o++;
429238
+ len++;
429239
+ }
429240
+ if (!atLineStart) continue;
429241
+ if (open20 === null) {
429242
+ open20 = ch2;
429243
+ openLen = len;
429244
+ } else if (open20 === ch2 && len >= openLen) {
429245
+ open20 = null;
429246
+ openLen = 0;
429247
+ }
429248
+ }
429249
+ return open20 !== null;
429250
+ }
429251
+ function latestMarker(full, window2, windowStart) {
429252
+ let best;
429253
+ const table = [
429254
+ ["failed", FAILED_MARKER],
429255
+ ["blocked", NEEDS_INPUT_MARKER],
429256
+ ["blocked", BLOCKED_MARKER],
429257
+ ["blocked", IM_BLOCKED_MARKER]
429258
+ ];
429259
+ for (const [state3, re] of table) {
429260
+ for (const m2 of window2.matchAll(re)) {
429261
+ if (insideCodeFence(full, windowStart + m2.index)) continue;
429262
+ if (!best || m2.index > best.index) {
429263
+ best = {
429264
+ state: state3,
429265
+ capture: m2[1].trim(),
429266
+ index: m2.index,
429267
+ end: m2.index + m2[0].length
429268
+ };
429269
+ }
429270
+ }
429271
+ }
429272
+ return best;
429273
+ }
429274
+ function preClassifyTail(text2) {
429275
+ const t2 = text2.trim();
429276
+ if (!t2) return null;
429277
+ let window2 = t2.slice(-800);
429278
+ let windowStart = t2.length - window2.length;
429279
+ let resultMatch;
429280
+ for (const m2 of window2.matchAll(/(?:^|\n)\s*result:\s*(.+?)\s*(?:\n|$)/gi)) {
429281
+ if (!insideCodeFence(t2, windowStart + m2.index)) resultMatch = m2;
429282
+ }
429283
+ if (resultMatch) {
429284
+ const after = resultMatch.index + resultMatch[0].length;
429285
+ window2 = window2.slice(after);
429286
+ windowStart += after;
429287
+ }
429288
+ const marker = latestMarker(t2, window2, windowStart);
429289
+ if (resultMatch && !marker) {
429290
+ const detail = truncateDetail(resultMatch[1]);
429291
+ const hasNext = [...window2.matchAll(/(?:^|\n)\s*next:\s*\S/gi)].some(
429292
+ (m2) => !insideCodeFence(t2, windowStart + m2.index)
429293
+ );
429294
+ if (hasNext) return { branch: "result-then-next", state: "working", tempo: "idle", detail };
429295
+ return { branch: "result-marker", state: "done", tempo: "idle", detail };
429296
+ }
429297
+ if (marker?.state === "failed") {
429298
+ return { branch: "failed-marker", state: "failed", tempo: "idle", detail: truncateDetail(marker.capture) };
429299
+ }
429300
+ if (marker?.state === "blocked") {
429301
+ const after = window2.slice(marker.end);
429302
+ const paras = after.split(/\n\s*\n/).filter((p) => p.trim().length > 0).length;
429303
+ if (paras >= 3) return null;
429304
+ if (!/\bnothing (?:needed|required) from you\b|\bno(?: user)? action (?:needed|required)\b/i.test(
429305
+ window2
429306
+ )) {
429307
+ const m2 = truncateDetail(marker.capture);
429308
+ return { branch: "blocked-marker", state: "blocked", tempo: "blocked", needs: m2, detail: m2 };
429309
+ }
429310
+ return null;
429311
+ }
429312
+ const tail800 = t2.slice(-800);
429313
+ if (/[??]\s*$/.test(tail800) && tail800.replace(/[??\s]+$/, "").length >= 4) {
429314
+ const f = Math.max(
429315
+ tail800.lastIndexOf("\n"),
429316
+ tail800.lastIndexOf(". "),
429317
+ tail800.lastIndexOf("! "),
429318
+ tail800.lastIndexOf("? ", tail800.length - 2)
429319
+ );
429320
+ if (!insideCodeFence(t2, t2.length - tail800.length + f)) {
429321
+ const q2 = truncateDetail(tail800.slice(f + 1).trim());
429322
+ if (!OPTIONAL_OFFER.test(q2)) {
429323
+ return { branch: "trailing-q", state: "blocked", tempo: "blocked", needs: q2, detail: q2 };
429324
+ }
429325
+ return null;
429326
+ }
429327
+ }
429328
+ const a = Math.max(
429329
+ 0,
429330
+ tail800.lastIndexOf(". "),
429331
+ tail800.lastIndexOf("! "),
429332
+ tail800.lastIndexOf("? "),
429333
+ tail800.lastIndexOf("\n")
429334
+ );
429335
+ const l3 = tail800.slice(a).replace(/^[.!?\s]+/, "");
429336
+ const fenced = insideCodeFence(t2, t2.length - tail800.length + a);
429337
+ const waitExt = WAIT_EXTERNAL.exec(l3);
429338
+ if (waitExt && !fenced) {
429339
+ return { branch: "wait-external", state: "working", tempo: "idle", detail: truncateDetail(waitExt[0]) };
429340
+ }
429341
+ const awaiting = AWAITING_USER.exec(l3);
429342
+ if (awaiting && !fenced) {
429343
+ const f = truncateDetail(l3.slice(awaiting.index).trim());
429344
+ return { branch: "awaiting-user", state: "blocked", tempo: "blocked", needs: f, detail: f };
429345
+ }
429346
+ const ask2 = ASK_VERB.exec(l3);
429347
+ if (ask2 && !fenced) {
429348
+ const f = truncateDetail(l3.slice(ask2.index).trim());
429349
+ return { branch: "ask-verb", state: "blocked", tempo: "blocked", needs: f, detail: f };
429350
+ }
429351
+ if (!fenced && AUTH_PROSE.test(l3)) {
429352
+ return {
429353
+ branch: "auth-prose",
429354
+ state: "blocked",
429355
+ tempo: "blocked",
429356
+ needs: truncateDetail(l3),
429357
+ detail: "authentication required"
429358
+ };
429359
+ }
429360
+ if (!fenced && WORKING_VERB.test(l3) && !NOT_FORWARD_INTENT.test(l3)) {
429361
+ return { branch: "working-verb", state: "working", tempo: "active", detail: truncateDetail(l3) };
429362
+ }
429363
+ if (!fenced && AGENTS_STATUS.test(l3)) {
429364
+ return { branch: "agents-status", state: "working", tempo: "idle", detail: truncateDetail(l3) };
429365
+ }
429366
+ if (!fenced && WILL_CHECK_BACK.test(l3)) {
429367
+ return { branch: "will-check-back", state: "working", tempo: "idle", detail: truncateDetail(l3) };
429368
+ }
429369
+ if (!fenced && CANT_PROCEED.test(l3)) {
429370
+ const f = truncateDetail(l3);
429371
+ return { branch: "cant-proceed", state: "blocked", tempo: "blocked", detail: f, needs: f };
429372
+ }
429373
+ if (!fenced && GIVING_UP.test(l3)) {
429374
+ return { branch: "giving-up", state: "failed", tempo: "idle", detail: truncateDetail(l3) };
429375
+ }
429376
+ if (!fenced && PUSHED_COMMITTED.test(l3)) {
429377
+ return { branch: "pushed-committed", state: "done", tempo: "idle", detail: truncateDetail(l3) };
429378
+ }
429379
+ if (!fenced && READY_FOR.test(l3)) {
429380
+ return { branch: "ready-for", state: "done", tempo: "idle", detail: truncateDetail(l3) };
429381
+ }
429382
+ if (!fenced && VERDICT_MARKER.test(l3)) {
429383
+ return { branch: "verdict-marker", state: "done", tempo: "idle", detail: truncateDetail(l3) };
429384
+ }
429385
+ if (!fenced && PLEASE_DO_X.test(l3)) {
429386
+ const f = truncateDetail(l3);
429387
+ return { branch: "please-do-x", state: "blocked", tempo: "blocked", detail: f, needs: f };
429388
+ }
429389
+ if (!fenced && STOPPING_HERE.test(l3)) {
429390
+ const f = truncateDetail(l3);
429391
+ return { branch: "stopping-here", state: "blocked", tempo: "blocked", detail: f, needs: f };
429392
+ }
429393
+ return null;
429394
+ }
429395
+ function heuristicFallback(text2) {
429396
+ const line = text2.split("\n").map((l3) => l3.trim()).findLast(Boolean);
429397
+ return {
429398
+ branch: "heuristic",
429399
+ state: "working",
429400
+ tempo: "idle",
429401
+ detail: line ? truncateDetail(line) : "\u2014"
429402
+ };
429403
+ }
429404
+ function classifyTurnTail(text2) {
429405
+ const c2 = preClassifyTail(text2) ?? heuristicFallback(text2);
429406
+ if (c2.tempo === "active" && c2.state === "working") return { ...c2, tempo: "idle" };
429407
+ return c2;
429408
+ }
429409
+ function classifiedToPostTurnSummary(c2) {
429410
+ return {
429411
+ status_category: c2.state === "blocked" ? "blocked" : "review_ready",
429412
+ status_detail: c2.detail,
429413
+ needs_action: c2.state === "blocked" ? c2.needs ?? "" : ""
429414
+ };
429415
+ }
429416
+ function assistantText(m2) {
429417
+ const c2 = m2.message?.content;
429418
+ if (typeof c2 === "string") return c2.trim();
429419
+ if (!Array.isArray(c2)) return "";
429420
+ return c2.map((b3) => b3?.type === "text" && typeof b3.text === "string" ? b3.text : "").filter(Boolean).join("\n").trim();
429421
+ }
429422
+ function turnTail(messages) {
429423
+ const msgs = messages;
429424
+ let start = 0;
429425
+ for (let i = msgs.length - 1; i >= 0; i--) {
429426
+ const m2 = msgs[i];
429427
+ if (m2.type === "user" && !m2.isMeta && typeof m2.message?.content === "string") {
429428
+ start = i + 1;
429429
+ break;
429430
+ }
429431
+ }
429432
+ const parts = [];
429433
+ let lastAssistantUuid = "";
429434
+ for (let i = start; i < msgs.length; i++) {
429435
+ const m2 = msgs[i];
429436
+ if (m2.type !== "assistant" || m2.isApiErrorMessage) continue;
429437
+ const text2 = assistantText(m2);
429438
+ if (text2) parts.push(text2);
429439
+ if (typeof m2.uuid === "string") lastAssistantUuid = m2.uuid;
429440
+ }
429441
+ return { text: parts.join("\n\n"), lastAssistantUuid };
429442
+ }
429443
+ function chainBgWrite(fn2) {
429444
+ bgWriteChain = bgWriteChain.then(fn2).catch(() => {
429445
+ });
429446
+ return bgWriteChain;
429447
+ }
429448
+ async function writeBgTurnEnd(short, c2) {
429449
+ bgBlockedByActivity = false;
429450
+ const cur = await readJobState(short);
429451
+ if (!cur) return;
429452
+ const curTerminal = isTerminalJobState(cur.state);
429453
+ const nextTerminal = c2.state === "done" || c2.state === "failed";
429454
+ const terminal = curTerminal || nextTerminal;
429455
+ await patchJobState(short, {
429456
+ state: curTerminal ? cur.state : c2.state,
429457
+ detail: c2.detail,
429458
+ tempo: terminal ? "idle" : c2.tempo,
429459
+ needs: c2.tempo === "blocked" && !terminal ? c2.needs : void 0,
429460
+ ...terminal && !cur.firstTerminalAt ? { firstTerminalAt: Date.now() } : {}
429461
+ });
429462
+ }
429463
+ function reportBgEngineDown(detail) {
429464
+ const short = bgJobShort();
429465
+ if (!short) return;
429466
+ void chainBgWrite(async () => {
429467
+ const cur = await readJobState(short);
429468
+ if (!cur || isTerminalJobState(cur.state)) return;
429469
+ await patchJobState(short, {
429470
+ state: "failed",
429471
+ detail: `engine down \u2014 ${detail}`,
429472
+ tempo: "idle",
429473
+ needs: void 0,
429474
+ firstTerminalAt: cur.firstTerminalAt ?? Date.now()
429475
+ });
429476
+ });
429477
+ }
429478
+ function emitForegroundSummary(c2, summarizesUuid) {
429479
+ const y2 = classifiedToPostTurnSummary(c2);
429480
+ notifySessionMetadataChanged({ post_turn_summary: y2 });
429481
+ enqueueSdkEvent({
429482
+ type: "system",
429483
+ subtype: "post_turn_summary",
429484
+ summarizes_uuid: summarizesUuid,
429485
+ status_category: y2.status_category,
429486
+ status_detail: y2.status_detail,
429487
+ needs_action: y2.needs_action,
429488
+ is_noteworthy: false,
429489
+ title: "",
429490
+ description: "",
429491
+ recent_action: "",
429492
+ artifact_urls: []
429493
+ });
429494
+ }
429495
+ async function emitTurnEndSummary(messages) {
429496
+ if (!classifierSummaryEnabled()) return;
429497
+ const { text: text2, lastAssistantUuid } = turnTail(messages);
429498
+ if (!/[\p{L}\p{N}]/u.test(text2)) return;
429499
+ const classified = classifyTurnTail(text2);
429500
+ const short = bgJobShort();
429501
+ if (short) {
429502
+ await chainBgWrite(() => writeBgTurnEnd(short, classified));
429503
+ return;
429504
+ }
429505
+ emitForegroundSummary(classified, lastAssistantUuid);
429506
+ }
429507
+ function blockedSummaryFor(details) {
429508
+ if (details.tool_name.startsWith("dialog:")) {
429509
+ return {
429510
+ status_category: "blocked",
429511
+ status_detail: "Waiting on a user dialog",
429512
+ needs_action: details.action_description ?? ""
429513
+ };
429514
+ }
429515
+ return {
429516
+ status_category: "blocked",
429517
+ status_detail: `Waiting on permission: ${details.tool_name}`,
429518
+ needs_action: `Approve or deny ${details.tool_name}`
429519
+ };
429520
+ }
429521
+ function runClassifierSummaryForBlocked(details) {
429522
+ if (!classifierSummaryEnabled()) return;
429523
+ if (bgJobShort()) return;
429524
+ notifySessionMetadataChanged({ post_turn_summary: blockedSummaryFor(details) });
429525
+ }
429526
+ async function writeBgBlocked(short, summary) {
429527
+ const cur = await readJobState(short);
429528
+ if (!cur || isTerminalJobState(cur.state)) return;
429529
+ if (cur.tempo === "blocked" && cur.needs === summary.needs_action) return;
429530
+ await patchJobState(short, {
429531
+ state: "blocked",
429532
+ tempo: "blocked",
429533
+ detail: summary.status_detail,
429534
+ needs: summary.needs_action || summary.status_detail
429535
+ });
429536
+ }
429537
+ async function writeBgUnblocked(short, busy) {
429538
+ const cur = await readJobState(short);
429539
+ if (!cur) return;
429540
+ if (busy) {
429541
+ bgBlockedByActivity = false;
429542
+ if (cur.tempo === "active" && !isTerminalJobState(cur.state) && cur.state !== "blocked") return;
429543
+ const reviving = isTerminalJobState(cur.state);
429544
+ await patchJobState(
429545
+ short,
429546
+ {
429547
+ state: reviving || cur.state === "blocked" ? "working" : cur.state,
429548
+ tempo: "active",
429549
+ needs: void 0,
429550
+ ...reviving ? { firstTerminalAt: void 0 } : {}
429551
+ },
429552
+ { allowRevive: true }
429553
+ );
429554
+ return;
429555
+ }
429556
+ if (!bgBlockedByActivity) return;
429557
+ bgBlockedByActivity = false;
429558
+ if (cur.tempo !== "blocked" || isSettledJobState(cur)) return;
429559
+ await patchJobState(short, {
429560
+ state: cur.state === "blocked" ? "working" : cur.state,
429561
+ tempo: "idle",
429562
+ needs: void 0
429563
+ });
429564
+ }
429565
+ function notifySessionActivityForSummary(input) {
429566
+ if (!classifierSummaryEnabled()) return;
429567
+ const prev = prevActivityStatus;
429568
+ prevActivityStatus = input.status;
429569
+ const short = bgJobShort();
429570
+ if (input.status === "waiting") {
429571
+ const w2 = input.waitingFor ?? "";
429572
+ const details = w2.startsWith("approve ") ? { tool_name: w2.slice("approve ".length), action_description: w2 } : { tool_name: "dialog:" + (w2 || "input"), action_description: w2 || "input needed" };
429573
+ const summary = blockedSummaryFor(details);
429574
+ if (short) {
429575
+ bgBlockedByActivity = true;
429576
+ void chainBgWrite(() => writeBgBlocked(short, summary));
429577
+ } else {
429578
+ notifySessionMetadataChanged({ post_turn_summary: summary });
429579
+ }
429580
+ return;
429581
+ }
429582
+ if (input.status === "idle" && prev === "busy" && input.getMessages) {
429583
+ const messages = input.getMessages();
429584
+ void emitTurnEndSummary(messages);
429585
+ return;
429586
+ }
429587
+ if (short) {
429588
+ void chainBgWrite(() => writeBgUnblocked(short, input.status === "busy"));
429589
+ }
429590
+ }
429591
+ var CLASSIFIER_SUMMARY_ENV, DETAIL_MAX, FAILED_MARKER, NEEDS_INPUT_MARKER, BLOCKED_MARKER, IM_BLOCKED_MARKER, OPTIONAL_OFFER, WORKING_VERB, NOT_FORWARD_INTENT, AGENTS_STATUS, WILL_CHECK_BACK, CANT_PROCEED, GIVING_UP, PUSHED_COMMITTED, READY_FOR, VERDICT_MARKER, PLEASE_DO_X, STOPPING_HERE, WAIT_EXTERNAL, AWAITING_USER, ASK_VERB, AUTH_PROSE, bgWriteChain, bgBlockedByActivity, prevActivityStatus;
429592
+ var init_taskSummary = __esm({
429593
+ "build-src/src/utils/taskSummary.ts"() {
429594
+ init_state2();
429595
+ init_sdkEventQueue();
429596
+ init_sessionState();
429597
+ CLASSIFIER_SUMMARY_ENV = "CLAUDE_CODE_CLASSIFIER_SUMMARY";
429598
+ DETAIL_MAX = 800;
429599
+ FAILED_MARKER = /(?:^|\n)\s*failed\s*[:—–-]\s*(.{3,200}?)(?=\n|$)/gi;
429600
+ NEEDS_INPUT_MARKER = /(?:^|\n)\s*needs input\s*[:—–-]\s*(.{3,200}?)(?=\n|$)/gi;
429601
+ BLOCKED_MARKER = /(?:^|\n)\s*blocked\s*[:—–-]\s*(.{3,200}?)(?=\n|$)/gi;
429602
+ IM_BLOCKED_MARKER = /\bI'?m blocked\s*[:—–-]\s*(.{3,200}?)(?=\n|$)/gi;
429603
+ OPTIONAL_OFFER = /\b(?:want|like) me to\b|\b(?:shall|should) I also\b/i;
429604
+ WORKING_VERB = /^(?:(?:Now|Next|Then|Alright|OK|Okay|Right|Good|First|Also),?\s+)?(?:Let me (?!know\b)|(?:I(?:'?ll| will) |I'?m going to |Going to )(?!need\b|require\b|wait\b|leave\b|hold\b|skip\b|stop\b)|Proceeding |Moving (?:on|to)\b|Continuing |Starting |Trying |Checking |Looking |Searching |Reading |Investigating |Running |Re-?running |Building |Rebuilding |Installing |Fetching |Applying |Fixing |Patching |Updating |Adding |Removing |Deleting |Importing |Refactoring |Rewriting |Writing |Grepping |Scanning |Wrapping |Switching |Testing |Verifying |Regenerating |Pushing |Pulling |Reviewing |Examining |Loading |Compiling |Parsing |Analyzing |Tracing |Exploring )/i;
429605
+ NOT_FORWARD_INTENT = /\b(?:once |when |after |until |as soon as )(?:you|it|the|that|this|they)\b|\bagain in\b|\bcheck back\b|\bin ~?\d+\s*(?:s(?:ec(?:ond)?s?)?|m(?:in(?:ute)?s?)?|h(?:ours?|rs?)?)\b|\bthen\.?\s*$|\bwhichever you\b|\bhold(?:ing)? for your\b|\b(?:to|and) wait for\b|\bgive it (?:more |some )?time\b|\bif (?:you(?:'d| want| prefer| need|'re)?|that(?:'s| helps| works)?|useful|needed|helpful|desired)\b|\b(?:isn'?t|not|won'?t) going to work\b/i;
429606
+ AGENTS_STATUS = /^(?:(?:\*\*)?[1-9]\d* (?:agent|cron|task|fork|job|worker|PR|check)s? (?:in flight|remaining|active|still (?:running|working)|pending|running|launched)\b|(?:Continuous )?(?:[Ll]oop|[Cc]rons?|[Bb]abysit) (?:active|healthy|continuing|running|will keep|continues)\b|Waiting for (?:the )?(?:agent|cron|task|fork|worker|job|remaining|them)s?\b|Agents? will report back\b|Waiting\.?$)/;
429607
+ WILL_CHECK_BACK = /^(?:I will|I'll|Will) (?:check back|re-?check|poll|look again|retry|re-?run|try again) (?:(?:when|once|after|until) (?!your?\b)|in\b|again\b)/i;
429608
+ CANT_PROCEED = /^I (?:can(?:'?t|not)|am unable to) (?:proceed|continue|make (?:any )?progress|complete|fix this)\b/i;
429609
+ GIVING_UP = /^(?:Giving up|I(?:'m| am) giving up|The task is not actionable)\b/i;
429610
+ PUSHED_COMMITTED = /^(?:Pushed (?:to `|`[0-9a-f]{7,})|Committed as `?[0-9a-f]{7,}\b|Commit: `?[0-9a-f]{7,}\b|(?:Opened|Created) PR #?\d)/;
429611
+ READY_FOR = /^Ready (?:for review|to (?:upload|merge|ship|land))\b/;
429612
+ VERDICT_MARKER = /^VERDICT: (?:PASS|FAIL)\b/;
429613
+ PLEASE_DO_X = /^Please (?:start|run|provide|grant|export|add|install|configure|give me|paste|point me|set (?:the |up |`?[A-Z][A-Z0-9_]+\b))/;
429614
+ STOPPING_HERE = /^(?:Stopping here|I've stopped here|Parked (?:the|this) branch|Paused here)(?:\.|$| —| -| until| pending| since| because)/i;
429615
+ WAIT_EXTERNAL = /\b(?:waiting (?:for|on)|pending)\s+(?:the\s+)?(?:CI|build|tests?|reviewer|deploy(?:ment)?|workflow|checks?|rollout|merge queue)\b/i;
429616
+ AWAITING_USER = /\b(?:awaiting|waiting (?:for|on)|pending)\s+(?:your\s+(?:feedback|input|decision|response|approval|direction|guidance|go-ahead)|you\b|the user\b)/i;
429617
+ ASK_VERB = /\b(please (?:run|provide|confirm|clarify|choose|let me know)|let me know (?:which|what|how|when)|which (?:option|approach|one)|should I (?:proceed|continue|use))\b/i;
429618
+ AUTH_PROSE = /\b(not logged in|please run \/login|authentication failed|invalid api key|oauth token (?:expired|revoked)|credit balance (?:is )?too low|usage limit reached|mcp (?:server )?(?:authentication|auth|authorization|unauthorized)|mcp (?:server )?(?:credential|token) (?:missing|expired|invalid)|401 unauthorized|403 forbidden|token (?:has )?expired|bad credentials|gh auth login|gcloud auth login|aws (?:sso )?login)\b/i;
429619
+ bgWriteChain = Promise.resolve();
429620
+ bgBlockedByActivity = false;
429621
+ prevActivityStatus = "idle";
428955
429622
  }
428956
429623
  });
428957
429624
 
@@ -428961,7 +429628,7 @@ import {
428961
429628
  existsSync as existsSync16,
428962
429629
  mkdirSync as mkdirSync14,
428963
429630
  renameSync as renameSync6,
428964
- readdirSync as readdirSync7,
429631
+ readdirSync as readdirSync8,
428965
429632
  statSync as statSync8,
428966
429633
  writeFileSync as writeFileSync13
428967
429634
  } from "node:fs";
@@ -429023,7 +429690,7 @@ function copyTreeSkipExisting(srcDir, destDir, onlyTopNames) {
429023
429690
  if (!existsSync16(srcDir)) return { copied, skipped };
429024
429691
  let entries;
429025
429692
  try {
429026
- entries = readdirSync7(srcDir);
429693
+ entries = readdirSync8(srcDir);
429027
429694
  } catch {
429028
429695
  return { copied, skipped };
429029
429696
  }
@@ -429571,6 +430238,40 @@ __export(seamQuery_exports, {
429571
430238
  setSeamWebSearch: () => setSeamWebSearch,
429572
430239
  toTaskRequest: () => toTaskRequest
429573
430240
  });
430241
+ function isBgHeadlessWorker() {
430242
+ return process.env.SEMA_CODE_SESSION_KIND === "bg" && !!process.env.SEMA_JOB_DIR && !!process.env.SEMA_LIVE_BASEURL;
430243
+ }
430244
+ async function probeLiveEngineOk() {
430245
+ const base = process.env.SEMA_LIVE_BASEURL;
430246
+ if (!base) return false;
430247
+ try {
430248
+ const ctl = new AbortController();
430249
+ const t2 = setTimeout(() => ctl.abort(), 2e3);
430250
+ const res = await fetch(`${base}/health`, { signal: ctl.signal });
430251
+ clearTimeout(t2);
430252
+ if (!res.ok) return false;
430253
+ const body = await res.json();
430254
+ return body?.status === "ok";
430255
+ } catch {
430256
+ return false;
430257
+ }
430258
+ }
430259
+ async function waitForBgEngineRecovery(signal) {
430260
+ const until = Date.now() + BG_RECOVERY_WAIT_MS;
430261
+ let lastProbe = 0;
430262
+ while (Date.now() < until) {
430263
+ if (signal?.aborted) return false;
430264
+ const st2 = getEngineRuntimeStatus();
430265
+ if (st2.phase === "failed") return false;
430266
+ if (st2.phase === "recovered") return true;
430267
+ if (Date.now() - lastProbe >= 2e3) {
430268
+ lastProbe = Date.now();
430269
+ if (await probeLiveEngineOk()) return true;
430270
+ }
430271
+ await new Promise((r) => setTimeout(r, 500));
430272
+ }
430273
+ return false;
430274
+ }
429574
430275
  function uuid5() {
429575
430276
  const g5 = typeof globalThis !== "undefined" ? globalThis.crypto : void 0;
429576
430277
  if (g5 && typeof g5.randomUUID === "function") return g5.randomUUID();
@@ -429894,6 +430595,13 @@ async function* query(params) {
429894
430595
  why = describeEngineInitFailure2(getLastEngineInitFailure2());
429895
430596
  } catch {
429896
430597
  }
430598
+ if (process.env.SEMA_CODE_SESSION_KIND === "bg" && process.env.SEMA_JOB_DIR) {
430599
+ try {
430600
+ const { reportBgEngineDown: reportBgEngineDown2 } = await Promise.resolve().then(() => (init_taskSummary(), taskSummary_exports));
430601
+ reportBgEngineDown2(`engine unavailable \u2014 ${why}`);
430602
+ } catch {
430603
+ }
430604
+ }
429897
430605
  yield createAssistantAPIErrorMessage({
429898
430606
  content: `The sema engine is not running, so this message was NOT sent to any model.
429899
430607
  Why: ${why}.
@@ -430005,26 +430713,60 @@ Setup looks unfinished (no model was saved). Run \`sema onboard\` to finish setu
430005
430713
  }
430006
430714
  }
430007
430715
  };
430008
- try {
430009
- const sdk = makeAdapterQuery(client2.tasks.stream(req, { signal }), { sessionId });
430010
- for await (const ccEvent of sdkMessagesToCcEvents(sdk, { sessionId, uuid: uuid5, signal })) {
430011
- trackToolLifecycle(ccEvent);
430012
- yield ccEvent;
430013
- }
430014
- } catch (err8) {
430015
- if (!signal?.aborted) {
430016
- logError(err8);
430017
- if (process.env.SEMA_DEBUG) {
430018
- console.error("[sema][seamQuery] live submit failed \u2014 rendering CC API-error row:", err8);
430716
+ let bgTearResends = 0;
430717
+ let retryStream = true;
430718
+ while (retryStream) {
430719
+ retryStream = false;
430720
+ try {
430721
+ const sdk = makeAdapterQuery(client2.tasks.stream(req, { signal }), { sessionId });
430722
+ for await (const ccEvent of sdkMessagesToCcEvents(sdk, { sessionId, uuid: uuid5, signal })) {
430723
+ trackToolLifecycle(ccEvent);
430724
+ yield ccEvent;
430019
430725
  }
430020
- if (process.env.SEMA_LIVE_BASEURL) {
430021
- logTurnJournal({ type: "turn_aborted", reason: "engine_error" });
430726
+ } catch (err8) {
430727
+ if (!signal?.aborted) {
430728
+ logError(err8);
430729
+ if (process.env.SEMA_DEBUG) {
430730
+ console.error("[sema][seamQuery] live submit failed \u2014 rendering CC API-error row:", err8);
430731
+ }
430732
+ if (process.env.SEMA_LIVE_BASEURL) {
430733
+ logTurnJournal({ type: "turn_aborted", reason: "engine_error" });
430734
+ }
430735
+ const tearVerdict = await classifyStreamTear().catch(() => "not-restart");
430736
+ if (isBgHeadlessWorker() && (tearVerdict === "restarted" || tearVerdict === "engine-down") && bgTearResends < BG_TEAR_MAX_RESENDS) {
430737
+ bgTearResends++;
430738
+ yield createAssistantAPIErrorMessage({
430739
+ content: tearVerdict === "restarted" ? `Engine restarted while this turn was streaming. This background session will resend the interrupted prompt automatically (attempt ${bgTearResends}/${BG_TEAR_MAX_RESENDS}).` : `The local engine stopped responding mid-turn. This background session is waiting for the engine to come back and will resend the interrupted prompt automatically (attempt ${bgTearResends}/${BG_TEAR_MAX_RESENDS}).`,
430740
+ error: "unknown"
430741
+ });
430742
+ const back = tearVerdict === "restarted" ? true : await waitForBgEngineRecovery(signal);
430743
+ if (back && !signal?.aborted) {
430744
+ if (setInProgress && engineOpenToolIds.size > 0) {
430745
+ const leftover = [...engineOpenToolIds];
430746
+ engineOpenToolIds.clear();
430747
+ setInProgress((prev) => {
430748
+ const next = new Set(prev);
430749
+ for (const id of leftover) next.delete(id);
430750
+ return next;
430751
+ });
430752
+ }
430753
+ retryStream = true;
430754
+ continue;
430755
+ }
430756
+ try {
430757
+ const { reportBgEngineDown: reportBgEngineDown2 } = await Promise.resolve().then(() => (init_taskSummary(), taskSummary_exports));
430758
+ const st2 = getEngineRuntimeStatus();
430759
+ reportBgEngineDown2(
430760
+ st2.phase === "failed" ? st2.detail ?? "automatic engine restart failed" : "engine did not come back within the auto-resend window"
430761
+ );
430762
+ } catch {
430763
+ }
430764
+ }
430765
+ yield createAssistantAPIErrorMessage({
430766
+ content: tearVerdict === "restarted" ? "Engine restarted while this turn was streaming (likely an update). The session is intact \u2014 press \u2191 then enter to resend the interrupted prompt." : tearVerdict === "engine-down" ? "The local engine stopped responding mid-turn (it may have crashed). The session is intact \u2014 sema is restarting the engine automatically; watch the engine status line above the input and resend once it shows the engine is back." : semaApiErrorContent(err8, req.scenario),
430767
+ error: "unknown"
430768
+ });
430022
430769
  }
430023
- const tearVerdict = await classifyStreamTear().catch(() => "not-restart");
430024
- yield createAssistantAPIErrorMessage({
430025
- content: tearVerdict === "restarted" ? "Engine restarted while this turn was streaming (likely an update). The session is intact \u2014 press \u2191 then enter to resend the interrupted prompt." : tearVerdict === "engine-down" ? "The local engine stopped responding mid-turn (it may have crashed). The session is intact \u2014 sema is restarting the engine automatically; watch the engine status line above the input and resend once it shows the engine is back." : semaApiErrorContent(err8, req.scenario),
430026
- error: "unknown"
430027
- });
430028
430770
  }
430029
430771
  }
430030
430772
  publishEngineAgentPanelEvent({ kind: "sweep" });
@@ -430087,7 +430829,7 @@ async function cancelEngineRun(taskId) {
430087
430829
  } catch {
430088
430830
  }
430089
430831
  }
430090
- var client2, clientExplicitlySet, seamSettings, seamWebSearch, seamSkills, seamMcp, seamRewindCapture, seamPendingRewind, INTERRUPT_WIRE_MARKER, seamPendingInterrupt, seamHistorySeedPending, seamSandbox, seamAutoSandboxInjected, HISTORY_SEED_MAX_CHARS, SCENARIO_KEYS, API_ERROR_PREFIX, defaultGatePrompt, canUseTool;
430832
+ var BG_TEAR_MAX_RESENDS, BG_RECOVERY_WAIT_MS, client2, clientExplicitlySet, seamSettings, seamWebSearch, seamSkills, seamMcp, seamRewindCapture, seamPendingRewind, INTERRUPT_WIRE_MARKER, seamPendingInterrupt, seamHistorySeedPending, seamSandbox, seamAutoSandboxInjected, HISTORY_SEED_MAX_CHARS, SCENARIO_KEYS, API_ERROR_PREFIX, defaultGatePrompt, canUseTool;
430091
430833
  var init_seamQuery = __esm({
430092
430834
  "build-src/src/sema/seamQuery.ts"() {
430093
430835
  init_adapter();
@@ -430120,6 +430862,9 @@ var init_seamQuery = __esm({
430120
430862
  init_scenarioNotAllowedCopy();
430121
430863
  init_messages4();
430122
430864
  init_log2();
430865
+ init_engineRuntimeStatus();
430866
+ BG_TEAR_MAX_RESENDS = 2;
430867
+ BG_RECOVERY_WAIT_MS = 12e4;
430123
430868
  client2 = makeMockClient();
430124
430869
  clientExplicitlySet = false;
430125
430870
  seamRewindCapture = true;
@@ -432591,14 +433336,14 @@ var init_terminalSetup = __esm({
432591
433336
  });
432592
433337
 
432593
433338
  // build-src/src/utils/pasteStore.ts
432594
- import { createHash as createHash22 } from "crypto";
433339
+ import { createHash as createHash23 } from "crypto";
432595
433340
  import { mkdir as mkdir31, readdir as readdir22, readFile as readFile36, stat as stat36, unlink as unlink18, writeFile as writeFile31 } from "fs/promises";
432596
433341
  import { join as join124 } from "path";
432597
433342
  function getPasteStoreDir() {
432598
433343
  return join124(getClaudeConfigHomeDir(), PASTE_STORE_DIR);
432599
433344
  }
432600
433345
  function hashPastedText(content) {
432601
- return createHash22("sha256").update(content).digest("hex").slice(0, 16);
433346
+ return createHash23("sha256").update(content).digest("hex").slice(0, 16);
432602
433347
  }
432603
433348
  function getPastePath(hash2) {
432604
433349
  return join124(getPasteStoreDir(), `${hash2}.txt`);
@@ -434504,7 +435249,7 @@ var init_pasteReturnBuffer = __esm({
434504
435249
  });
434505
435250
 
434506
435251
  // build-src/src/hooks/usePasteHandler.ts
434507
- import { basename as basename35 } from "path";
435252
+ import { basename as basename36 } from "path";
434508
435253
  function usePasteHandler({
434509
435254
  onPaste,
434510
435255
  onInput,
@@ -434582,7 +435327,7 @@ function usePasteHandler({
434582
435327
  );
434583
435328
  if (validImages.length > 0) {
434584
435329
  for (const imageData of validImages) {
434585
- const filename = basename35(imageData.path);
435330
+ const filename = basename36(imageData.path);
434586
435331
  onImagePaste2(
434587
435332
  imageData.base64,
434588
435333
  imageData.mediaType,
@@ -435182,7 +435927,7 @@ var init_TextInput = __esm({
435182
435927
  });
435183
435928
 
435184
435929
  // build-src/src/utils/suggestions/directoryCompletion.ts
435185
- import { basename as basename36, dirname as dirname60, join as join126, sep as sep27 } from "path";
435930
+ import { basename as basename37, dirname as dirname60, join as join126, sep as sep27 } from "path";
435186
435931
  function parsePartialPath(partialPath, basePath) {
435187
435932
  if (!partialPath) {
435188
435933
  const directory2 = basePath || getCwd();
@@ -435193,7 +435938,7 @@ function parsePartialPath(partialPath, basePath) {
435193
435938
  return { directory: resolved, prefix: "" };
435194
435939
  }
435195
435940
  const directory = dirname60(resolved);
435196
- const prefix = basename36(partialPath);
435941
+ const prefix = basename37(partialPath);
435197
435942
  return { directory, prefix };
435198
435943
  }
435199
435944
  async function scanDirectory(dirPath) {
@@ -438730,7 +439475,7 @@ __export(copy_exports, {
438730
439475
  fileExtension: () => fileExtension2
438731
439476
  });
438732
439477
  import { mkdir as mkdir32, writeFile as writeFile33 } from "fs/promises";
438733
- import { tmpdir as tmpdir10 } from "os";
439478
+ import { tmpdir as tmpdir11 } from "os";
438734
439479
  import { join as join130 } from "path";
438735
439480
  function extractCodeBlocks(markdown) {
438736
439481
  const tokens = g2.lexer(stripPromptXMLTags(markdown));
@@ -439045,7 +439790,7 @@ var init_copy = __esm({
439045
439790
  init_messages4();
439046
439791
  init_stringUtils();
439047
439792
  import_jsx_runtime174 = __toESM(require_jsx_runtime(), 1);
439048
- COPY_DIR = join130(tmpdir10(), "claude");
439793
+ COPY_DIR = join130(tmpdir11(), "claude");
439049
439794
  RESPONSE_FILENAME = "response.md";
439050
439795
  MAX_LOOKBACK = 20;
439051
439796
  call11 = async (onDone, context3, args) => {
@@ -445030,11 +445775,11 @@ var init_ansiToPng = __esm({
445030
445775
 
445031
445776
  // build-src/src/utils/screenshotClipboard.ts
445032
445777
  import { mkdir as mkdir33, unlink as unlink19, writeFile as writeFile34 } from "fs/promises";
445033
- import { tmpdir as tmpdir11 } from "os";
445778
+ import { tmpdir as tmpdir12 } from "os";
445034
445779
  import { join as join133 } from "path";
445035
445780
  async function copyAnsiToClipboard(ansiText, options) {
445036
445781
  try {
445037
- const tempDir = join133(tmpdir11(), "claude-code-screenshots");
445782
+ const tempDir = join133(tmpdir12(), "claude-code-screenshots");
445038
445783
  await mkdir33(tempDir, { recursive: true });
445039
445784
  const pngPath = join133(tempDir, `screenshot-${Date.now()}.png`);
445040
445785
  const pngBuffer = ansiToPng(ansiText, options);
@@ -445122,7 +445867,7 @@ var init_screenshotClipboard = __esm({
445122
445867
 
445123
445868
  // build-src/src/utils/stats.ts
445124
445869
  import { open as open15 } from "fs/promises";
445125
- import { basename as basename37, join as join134, sep as sep29 } from "path";
445870
+ import { basename as basename38, join as join134, sep as sep29 } from "path";
445126
445871
  async function processSessionFiles(sessionFiles, options = {}) {
445127
445872
  const { fromDate, toDate } = options;
445128
445873
  const fs15 = getFsImplementation();
@@ -445184,7 +445929,7 @@ async function processSessionFiles(sessionFiles, options = {}) {
445184
445929
  );
445185
445930
  continue;
445186
445931
  }
445187
- const sessionId = basename37(sessionFile, ".jsonl");
445932
+ const sessionId = basename38(sessionFile, ".jsonl");
445188
445933
  const messages = [];
445189
445934
  for (const entry of entries) {
445190
445935
  if (isTranscriptMessage(entry)) {
@@ -445196,7 +445941,7 @@ async function processSessionFiles(sessionFiles, options = {}) {
445196
445941
  if (messages.length === 0) continue;
445197
445942
  const isSubagentFile = sessionFile.includes(`${sep29}subagents${sep29}`);
445198
445943
  if (false) {
445199
- const parentSessionId = isSubagentFile ? basename37(dirname63(dirname63(sessionFile))) : sessionId;
445944
+ const parentSessionId = isSubagentFile ? basename38(dirname63(dirname63(sessionFile))) : sessionId;
445200
445945
  if (!sessionsWithShotCount.has(parentSessionId)) {
445201
445946
  const shotCount = extractShotCountFromMessages(messages);
445202
445947
  if (shotCount !== null) {
@@ -449926,14 +450671,14 @@ var init_versions4 = __esm({
449926
450671
  // build-src/src/utils/editor.ts
449927
450672
  import {
449928
450673
  spawn as spawn11,
449929
- spawnSync as spawnSync8
450674
+ spawnSync as spawnSync9
449930
450675
  } from "child_process";
449931
- import { basename as basename38 } from "path";
450676
+ import { basename as basename39 } from "path";
449932
450677
  function isCommandAvailable3(command8) {
449933
450678
  return !!whichSync(command8);
449934
450679
  }
449935
450680
  function classifyGuiEditor(editor) {
449936
- const base = basename38(editor.split(" ")[0] ?? "");
450681
+ const base = basename39(editor.split(" ")[0] ?? "");
449937
450682
  return GUI_EDITORS.find((g5) => base.includes(g5));
449938
450683
  }
449939
450684
  function guiGotoArgv(guiFamily, filePath, line) {
@@ -449968,14 +450713,14 @@ function openFileInExternalEditor(filePath, line) {
449968
450713
  }
449969
450714
  const inkInstance = instances_default.get(process.stdout);
449970
450715
  if (!inkInstance) return false;
449971
- const useGotoLine = line && PLUS_N_EDITORS.test(basename38(base));
450716
+ const useGotoLine = line && PLUS_N_EDITORS.test(basename39(base));
449972
450717
  inkInstance.enterAlternateScreen();
449973
450718
  try {
449974
450719
  const syncOpts = { stdio: "inherit" };
449975
450720
  let result;
449976
450721
  if (process.platform === "win32") {
449977
450722
  const lineArg = useGotoLine ? `+${line} ` : "";
449978
- result = spawnSync8(`${editor} ${lineArg}"${filePath}"`, {
450723
+ result = spawnSync9(`${editor} ${lineArg}"${filePath}"`, {
449979
450724
  ...syncOpts,
449980
450725
  shell: true
449981
450726
  });
@@ -449984,7 +450729,7 @@ function openFileInExternalEditor(filePath, line) {
449984
450729
  ...editorArgs,
449985
450730
  ...useGotoLine ? [`+${line}`, filePath] : [filePath]
449986
450731
  ];
449987
- result = spawnSync8(base, args, syncOpts);
450732
+ result = spawnSync9(base, args, syncOpts);
449988
450733
  }
449989
450734
  if (result.error) {
449990
450735
  logForDebugging(`editor spawn failed: ${result.error}`, {
@@ -456402,7 +457147,7 @@ var init_channelPermissions = __esm({
456402
457147
  });
456403
457148
 
456404
457149
  // build-src/src/services/mcp/useManageMCPConnections.ts
456405
- import { basename as basename39 } from "path";
457150
+ import { basename as basename40 } from "path";
456406
457151
  function getErrorKey(error52) {
456407
457152
  const plugin2 = "plugin" in error52 ? error52.plugin : "no-plugin";
456408
457153
  return `${error52.type}:${error52.source}:${plugin2}`;
@@ -457014,7 +457759,7 @@ function useManageMCPConnections(dynamicMcpConfig, isStrictMcpConfig = false) {
457014
457759
  else if (serverConfig.scope === "dynamic") counts.plugin++;
457015
457760
  else if (serverConfig.scope === "claudeai") counts.claudeai++;
457016
457761
  if (process.env.USER_TYPE === "ant" && !isMcpServerDisabled(name) && (serverConfig.type === void 0 || serverConfig.type === "stdio") && "command" in serverConfig) {
457017
- stdioCommands.push(basename39(serverConfig.command));
457762
+ stdioCommands.push(basename40(serverConfig.command));
457018
457763
  }
457019
457764
  }
457020
457765
  logEvent("tengu_mcp_servers", {
@@ -461233,7 +461978,7 @@ var init_tipHistory = __esm({
461233
461978
  });
461234
461979
 
461235
461980
  // build-src/src/commands/plugin/DiscoverPlugins.tsx
461236
- import { basename as basename40 } from "path";
461981
+ import { basename as basename41 } from "path";
461237
461982
  function formatSuggestionReason(hit) {
461238
461983
  switch (hit.signal) {
461239
461984
  case "cwd":
@@ -461249,7 +461994,7 @@ function formatSuggestionReason(hit) {
461249
461994
  }
461250
461995
  }
461251
461996
  function formatSuggestionFile(file2) {
461252
- return truncateToWidth(basename40(file2).replaceAll("\\", "/"), 32);
461997
+ return truncateToWidth(basename41(file2).replaceAll("\\", "/"), 32);
461253
461998
  }
461254
461999
  function DiscoverPlugins({
461255
462000
  error: error52,
@@ -475801,8 +476546,8 @@ var init_sema_brand = __esm({
475801
476546
  "Slash-command gating wired to the fleet capability handshake"
475802
476547
  ]
475803
476548
  },
475804
- productVersion: "1.0.1",
475805
- announcement: "sema 1.0.1 \u2014 rolling engine upgrades, session auto-titles, and the sci-fi welcome you are looking at"
476549
+ productVersion: "1.0.2",
476550
+ announcement: "sema 1.0.2 \u2014 background tasks survive your ssh session, engines stop fighting over ports, and long sessions stay lean"
475806
476551
  };
475807
476552
  }
475808
476553
  });
@@ -482865,7 +483610,7 @@ var init_share = __esm({
482865
483610
 
482866
483611
  // build-src/src/components/skills/SkillsMenu.tsx
482867
483612
  import { existsSync as existsSync19, mkdirSync as mkdirSync17, renameSync as renameSync7 } from "node:fs";
482868
- import { basename as basename43, dirname as dirname68, join as join146 } from "node:path";
483613
+ import { basename as basename44, dirname as dirname68, join as join146 } from "node:path";
482869
483614
  function skillSourceDisplayName(source) {
482870
483615
  switch (source) {
482871
483616
  case "mcp":
@@ -483032,7 +483777,7 @@ function SkillsMenu({ onExit: onExit2, commands }) {
483032
483777
  `skills-removed-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`
483033
483778
  );
483034
483779
  mkdirSync17(removedDir, { recursive: true });
483035
- let target = join146(removedDir, basename43(skill.skillRoot));
483780
+ let target = join146(removedDir, basename44(skill.skillRoot));
483036
483781
  if (existsSync19(target)) target = `${target}-${Date.now()}`;
483037
483782
  renameSync7(skill.skillRoot, target);
483038
483783
  const nameStillPresent = skills2.some(
@@ -510343,14 +511088,14 @@ var exit_exports = {};
510343
511088
  __export(exit_exports, {
510344
511089
  call: () => call65
510345
511090
  });
510346
- import { spawnSync as spawnSync9 } from "child_process";
511091
+ import { spawnSync as spawnSync10 } from "child_process";
510347
511092
  function getRandomGoodbyeMessage2() {
510348
511093
  return sample_default(GOODBYE_MESSAGES2) ?? "Goodbye!";
510349
511094
  }
510350
511095
  async function call65(onDone) {
510351
511096
  if (isBgSession()) {
510352
511097
  onDone();
510353
- spawnSync9("tmux", ["detach-client"], {
511098
+ spawnSync10("tmux", ["detach-client"], {
510354
511099
  stdio: "ignore"
510355
511100
  });
510356
511101
  return null;
@@ -512902,7 +513647,7 @@ import {
512902
513647
  unlink as unlink23,
512903
513648
  writeFile as writeFile44
512904
513649
  } from "fs/promises";
512905
- import { tmpdir as tmpdir12 } from "os";
513650
+ import { tmpdir as tmpdir13 } from "os";
512906
513651
  import { extname as extname14, join as join158 } from "path";
512907
513652
  function getAnalysisModel() {
512908
513653
  return getDefaultOpusModel();
@@ -514630,7 +515375,7 @@ var init_insights = __esm({
514630
515375
  } : async () => 0;
514631
515376
  collectFromRemoteHost = process.env.USER_TYPE === "ant" ? async (homespace, destDir) => {
514632
515377
  const result = { copied: 0, skipped: 0 };
514633
- const tempDir = await mkdtemp(join158(tmpdir12(), "claude-hs-"));
515378
+ const tempDir = await mkdtemp(join158(tmpdir13(), "claude-hs-"));
514634
515379
  try {
514635
515380
  const scpResult = await execFileNoThrow(
514636
515381
  "scp",
@@ -515935,7 +516680,7 @@ import {
515935
516680
  unlink as unlink24,
515936
516681
  writeFile as writeFile45
515937
516682
  } from "fs/promises";
515938
- import { basename as basename44, dirname as dirname71, join as join159 } from "path";
516683
+ import { basename as basename45, dirname as dirname71, join as join159 } from "path";
515939
516684
  function isTranscriptMessage(entry) {
515940
516685
  return entry.type === "user" || entry.type === "assistant" || entry.type === "attachment" || entry.type === "system";
515941
516686
  }
@@ -517990,7 +518735,7 @@ async function getSessionFilesWithMtime(projectDir2) {
517990
518735
  const candidates = [];
517991
518736
  for (const dirent of dirents) {
517992
518737
  if (!dirent.isFile() || !dirent.name.endsWith(".jsonl")) continue;
517993
- const sessionId = validateUuid(basename44(dirent.name, ".jsonl"));
518738
+ const sessionId = validateUuid(basename45(dirent.name, ".jsonl"));
517994
518739
  if (!sessionId) continue;
517995
518740
  candidates.push({ sessionId, filePath: join159(projectDir2, dirent.name) });
517996
518741
  }
@@ -519430,7 +520175,7 @@ var init_agentMemory = __esm({
519430
520175
 
519431
520176
  // build-src/src/utils/permissions/filesystem.ts
519432
520177
  import { randomBytes as randomBytes20 } from "crypto";
519433
- import { homedir as homedir42, tmpdir as tmpdir13 } from "os";
520178
+ import { homedir as homedir42, tmpdir as tmpdir14 } from "os";
519434
520179
  import { join as join161, normalize as normalize16, posix as posix8, sep as sep34 } from "path";
519435
520180
  function normalizeCaseForComparison2(path27) {
519436
520181
  return path27.toLowerCase();
@@ -520414,7 +521159,7 @@ var init_filesystem = __esm({
520414
521159
  ];
520415
521160
  DIR_SEP = posix8.sep;
520416
521161
  getClaudeTempDir = memoize_default(function getClaudeTempDir2() {
520417
- const baseTmpDir = process.env.SEMA_CODE_TMPDIR || (getPlatform() === "windows" ? tmpdir13() : "/tmp");
521162
+ const baseTmpDir = process.env.SEMA_CODE_TMPDIR || (getPlatform() === "windows" ? tmpdir14() : "/tmp");
520418
521163
  const fs15 = getFsImplementation();
520419
521164
  let resolvedBaseTmpDir = baseTmpDir;
520420
521165
  try {
@@ -522024,7 +522769,7 @@ __export(hooks_exports2, {
522024
522769
  hasWorktreeCreateHook: () => hasWorktreeCreateHook,
522025
522770
  shouldSkipHookDueToTrust: () => shouldSkipHookDueToTrust
522026
522771
  });
522027
- import { basename as basename45 } from "path";
522772
+ import { basename as basename46 } from "path";
522028
522773
  import { spawn as spawn12 } from "child_process";
522029
522774
  import { randomUUID as randomUUID32 } from "crypto";
522030
522775
  function getSessionEndHookTimeoutMs() {
@@ -522899,7 +523644,7 @@ async function getMatchingHooks(appState, sessionId, hookEvent, hookInput, tools
522899
523644
  matchQuery = hookInput.load_reason;
522900
523645
  break;
522901
523646
  case "FileChanged":
522902
- matchQuery = basename45(hookInput.file_path);
523647
+ matchQuery = basename46(hookInput.file_path);
522903
523648
  break;
522904
523649
  default:
522905
523650
  break;
@@ -525186,7 +525931,7 @@ import {
525186
525931
  symlink as symlink5,
525187
525932
  utimes as utimes2
525188
525933
  } from "fs/promises";
525189
- import { basename as basename46, dirname as dirname72, join as join163 } from "path";
525934
+ import { basename as basename47, dirname as dirname72, join as join163 } from "path";
525190
525935
  function validateWorktreeSlug(slug) {
525191
525936
  if (slug.length > MAX_WORKTREE_SLUG_LENGTH) {
525192
525937
  throw new Error(
@@ -525243,7 +525988,7 @@ function restoreWorktreeSession(session2) {
525243
525988
  currentWorktreeSession = session2;
525244
525989
  }
525245
525990
  function generateTmuxSessionName(repoPath, branch2) {
525246
- const repoName = basename46(repoPath);
525991
+ const repoName = basename47(repoPath);
525247
525992
  const combined = `${repoName}_${branch2}`;
525248
525993
  return combined.replace(/[/.]/g, "_");
525249
525994
  }
@@ -526494,7 +527239,7 @@ var init_prompts3 = __esm({
526494
527239
  });
526495
527240
 
526496
527241
  // build-src/src/utils/api.ts
526497
- import { createHash as createHash23 } from "crypto";
527242
+ import { createHash as createHash24 } from "crypto";
526498
527243
  function filterSwarmFieldsFromSchema(toolName2, schema) {
526499
527244
  const fieldsToRemove = SWARM_FIELDS_BY_TOOL[toolName2];
526500
527245
  if (!fieldsToRemove || fieldsToRemove.length === 0) {
@@ -526588,7 +527333,7 @@ function logAPIPrefix(systemPrompt) {
526588
527333
  20
526589
527334
  ),
526590
527335
  length: firstSystemPrompt?.length ?? 0,
526591
- hash: firstSystemPrompt ? createHash23("sha256").update(firstSystemPrompt).digest("hex") : ""
527336
+ hash: firstSystemPrompt ? createHash24("sha256").update(firstSystemPrompt).digest("hex") : ""
526592
527337
  });
526593
527338
  }
526594
527339
  function splitSysPromptPrefix(systemPrompt, options) {
@@ -532639,7 +533384,7 @@ var init_markdownConfigLoader = __esm({
532639
533384
  });
532640
533385
 
532641
533386
  // build-src/src/outputStyles/loadOutputStylesDir.ts
532642
- import { basename as basename47 } from "path";
533387
+ import { basename as basename48 } from "path";
532643
533388
  var getOutputStyleDirStyles;
532644
533389
  var init_loadOutputStylesDir = __esm({
532645
533390
  "build-src/src/outputStyles/loadOutputStylesDir.ts"() {
@@ -532658,7 +533403,7 @@ var init_loadOutputStylesDir = __esm({
532658
533403
  );
532659
533404
  const styles5 = markdownFiles.map(({ filePath, frontmatter: frontmatter2, content, source }) => {
532660
533405
  try {
532661
- const fileName = basename47(filePath);
533406
+ const fileName = basename48(filePath);
532662
533407
  const styleName = fileName.replace(/\.md$/, "");
532663
533408
  const name = frontmatter2["name"] || styleName;
532664
533409
  const description = coerceDescriptionToString(
@@ -566278,7 +567023,7 @@ var require_cross_spawn2 = __commonJS({
566278
567023
  enoent.hookChildProcess(spawned, parsed);
566279
567024
  return spawned;
566280
567025
  }
566281
- function spawnSync12(command8, args, options) {
567026
+ function spawnSync13(command8, args, options) {
566282
567027
  const parsed = parse14(command8, args, options);
566283
567028
  const result = cp2.spawnSync(parsed.command, parsed.args, parsed.options);
566284
567029
  result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
@@ -566286,7 +567031,7 @@ var require_cross_spawn2 = __commonJS({
566286
567031
  }
566287
567032
  module2.exports = spawn17;
566288
567033
  module2.exports.spawn = spawn17;
566289
- module2.exports.sync = spawnSync12;
567034
+ module2.exports.sync = spawnSync13;
566290
567035
  module2.exports._parse = parse14;
566291
567036
  module2.exports._enoent = enoent;
566292
567037
  }
@@ -566620,7 +567365,7 @@ var init_streamableHttp2 = __esm({
566620
567365
  });
566621
567366
 
566622
567367
  // ../ai-agent-core/dist/core/mcp.js
566623
- import { tmpdir as tmpdir14 } from "node:os";
567368
+ import { tmpdir as tmpdir15 } from "node:os";
566624
567369
  import { join as join165 } from "node:path";
566625
567370
  var MCP_IMAGE_MAX_BASE64, IMAGE_TARGET_RAW_SIZE3, MCP_BLOB_DIR;
566626
567371
  var init_mcp5 = __esm({
@@ -566633,7 +567378,7 @@ var init_mcp5 = __esm({
566633
567378
  init_untrusted_text();
566634
567379
  MCP_IMAGE_MAX_BASE64 = 5 * 1024 * 1024;
566635
567380
  IMAGE_TARGET_RAW_SIZE3 = MCP_IMAGE_MAX_BASE64 * 3 / 4;
566636
- MCP_BLOB_DIR = join165(tmpdir14(), "sema-mcp-blobs");
567381
+ MCP_BLOB_DIR = join165(tmpdir15(), "sema-mcp-blobs");
566637
567382
  }
566638
567383
  });
566639
567384
 
@@ -568796,7 +569541,7 @@ var init_lsp = __esm({
568796
569541
  });
568797
569542
 
568798
569543
  // ../ai-agent-core/dist/core/runner/prepare-task.js
568799
- import { createHash as createHash24, randomBytes as randomBytes24 } from "node:crypto";
569544
+ import { createHash as createHash25, randomBytes as randomBytes24 } from "node:crypto";
568800
569545
  var PROMPT_HASH_SALT, DEFAULT_RESOURCE_TTL_MS, DEFAULT_UNATTENDED_APPROVAL_TTL_MS;
568801
569546
  var init_prepare_task = __esm({
568802
569547
  "../ai-agent-core/dist/core/runner/prepare-task.js"() {
@@ -574586,7 +575331,7 @@ var init_managedEnv = __esm({
574586
575331
  });
574587
575332
 
574588
575333
  // build-src/src/upstreamproxy/relay.ts
574589
- import { createServer as createServer7 } from "node:net";
575334
+ import { createServer as createServer8 } from "node:net";
574590
575335
  function encodeChunk(data) {
574591
575336
  const len = data.length;
574592
575337
  const varint = [];
@@ -574688,7 +575433,7 @@ function startBunRelay(wsUrl, authHeader, wsAuthHeader) {
574688
575433
  async function startNodeRelay(wsUrl, authHeader, wsAuthHeader) {
574689
575434
  nodeWSCtor = (await Promise.resolve().then(() => (init_wrapper(), wrapper_exports))).default;
574690
575435
  const states = /* @__PURE__ */ new WeakMap();
574691
- const server = createServer7((sock) => {
575436
+ const server = createServer8((sock) => {
574692
575437
  const st2 = newConnState();
574693
575438
  states.set(sock, st2);
574694
575439
  const adapter2 = {
@@ -578875,61 +579620,6 @@ var init_fpsMetrics = __esm({
578875
579620
  }
578876
579621
  });
578877
579622
 
578878
- // build-src/src/utils/sessionState.ts
578879
- function setSessionStateChangedListener(cb) {
578880
- stateListener = cb;
578881
- }
578882
- function setSessionMetadataChangedListener(cb) {
578883
- metadataListener = cb;
578884
- }
578885
- function setPermissionModeChangedListener(cb) {
578886
- permissionModeListener = cb;
578887
- }
578888
- function getSessionState() {
578889
- return currentState;
578890
- }
578891
- function notifySessionStateChanged(state3, details) {
578892
- currentState = state3;
578893
- stateListener?.(state3, details);
578894
- if (state3 === "requires_action" && details) {
578895
- hasPendingAction = true;
578896
- metadataListener?.({
578897
- pending_action: details
578898
- });
578899
- } else if (hasPendingAction) {
578900
- hasPendingAction = false;
578901
- metadataListener?.({ pending_action: null });
578902
- }
578903
- if (state3 === "idle") {
578904
- metadataListener?.({ task_summary: null });
578905
- }
578906
- if (isEnvTruthy(process.env.SEMA_CODE_EMIT_SESSION_STATE_EVENTS)) {
578907
- enqueueSdkEvent({
578908
- type: "system",
578909
- subtype: "session_state_changed",
578910
- state: state3
578911
- });
578912
- }
578913
- }
578914
- function notifySessionMetadataChanged(metadata2) {
578915
- metadataListener?.(metadata2);
578916
- }
578917
- function notifyPermissionModeChanged(mode) {
578918
- permissionModeListener?.(mode);
578919
- }
578920
- var stateListener, metadataListener, permissionModeListener, hasPendingAction, currentState;
578921
- var init_sessionState = __esm({
578922
- "build-src/src/utils/sessionState.ts"() {
578923
- init_envUtils();
578924
- init_sdkEventQueue();
578925
- stateListener = null;
578926
- metadataListener = null;
578927
- permissionModeListener = null;
578928
- hasPendingAction = false;
578929
- currentState = "idle";
578930
- }
578931
- });
578932
-
578933
579623
  // build-src/src/state/onChangeAppState.ts
578934
579624
  function externalMetadataToAppState(metadata2) {
578935
579625
  return (prev) => ({
@@ -585889,7 +586579,7 @@ var init_FileEditToolDiff = __esm({
585889
586579
 
585890
586580
  // build-src/src/hooks/useDiffInIDE.ts
585891
586581
  import { randomUUID as randomUUID37 } from "crypto";
585892
- import { basename as basename49 } from "path";
586582
+ import { basename as basename50 } from "path";
585893
586583
  function useDiffInIDE({
585894
586584
  onChange,
585895
586585
  toolUseContext,
@@ -585901,7 +586591,7 @@ function useDiffInIDE({
585901
586591
  const [hasError, setHasError] = (0, import_react225.useState)(false);
585902
586592
  const sha = (0, import_react225.useMemo)(() => randomUUID37().slice(0, 6), []);
585903
586593
  const tabName = (0, import_react225.useMemo)(
585904
- () => `\u273B [Sema] ${basename49(filePath)} (${sha}) \u29C9`,
586594
+ () => `\u273B [Sema] ${basename50(filePath)} (${sha}) \u29C9`,
585905
586595
  [filePath, sha]
585906
586596
  );
585907
586597
  const shouldShowDiffInIDE = hasAccessToIDEExtensionDiffFeature(toolUseContext.options.mcpClients) && getGlobalConfig().diffTool === "auto" && // Diffs should only be for file edits.
@@ -586115,7 +586805,7 @@ var init_useDiffInIDE = __esm({
586115
586805
  });
586116
586806
 
586117
586807
  // build-src/src/components/ShowInIDEPrompt.tsx
586118
- import { basename as basename50, relative as relative28 } from "path";
586808
+ import { basename as basename51, relative as relative28 } from "path";
586119
586809
  function ShowInIDEPrompt(t0) {
586120
586810
  const $3 = (0, import_compiler_runtime273.c)(36);
586121
586811
  const {
@@ -586162,7 +586852,7 @@ function ShowInIDEPrompt(t0) {
586162
586852
  }
586163
586853
  let t4;
586164
586854
  if ($3[5] !== filePath) {
586165
- t4 = basename50(filePath);
586855
+ t4 = basename51(filePath);
586166
586856
  $3[5] = filePath;
586167
586857
  $3[6] = t4;
586168
586858
  } else {
@@ -586297,7 +586987,7 @@ var init_ShowInIDEPrompt = __esm({
586297
586987
 
586298
586988
  // build-src/src/components/permissions/FilePermissionDialog/permissionOptions.tsx
586299
586989
  import { homedir as homedir45 } from "os";
586300
- import { basename as basename51, join as join168, sep as sep36 } from "path";
586990
+ import { basename as basename52, join as join168, sep as sep36 } from "path";
586301
586991
  function isInClaudeFolder(filePath) {
586302
586992
  const absolutePath = expandPath(filePath);
586303
586993
  const claudeFolderPath = expandPath(`${getOriginalCwd()}/.claude`);
@@ -586375,7 +587065,7 @@ function getFilePermissionOptions({
586375
587065
  }
586376
587066
  } else {
586377
587067
  const dirPath = getDirectoryForPath(filePath);
586378
- const dirName = basename51(dirPath) || "this directory";
587068
+ const dirName = basename52(dirPath) || "this directory";
586379
587069
  if (operationType === "read") {
586380
587070
  sessionLabel = /* @__PURE__ */ (0, import_jsx_runtime396.jsxs)(ThemedText, { children: [
586381
587071
  "Yes, allow reading from ",
@@ -586849,7 +587539,7 @@ var init_FilePermissionDialog = __esm({
586849
587539
  });
586850
587540
 
586851
587541
  // build-src/src/components/permissions/SedEditPermissionRequest/SedEditPermissionRequest.tsx
586852
- import { basename as basename52, relative as relative30 } from "path";
587542
+ import { basename as basename53, relative as relative30 } from "path";
586853
587543
  function SedEditPermissionRequest(t0) {
586854
587544
  const $3 = (0, import_compiler_runtime274.c)(9);
586855
587545
  let props;
@@ -587016,7 +587706,7 @@ function SedEditPermissionRequestInner(t0) {
587016
587706
  }
587017
587707
  let t10;
587018
587708
  if ($3[16] !== filePath) {
587019
- t10 = basename52(filePath);
587709
+ t10 = basename53(filePath);
587020
587710
  $3[16] = filePath;
587021
587711
  $3[17] = t10;
587022
587712
  } else {
@@ -587217,7 +587907,7 @@ var init_useShellPermissionFeedback = __esm({
587217
587907
  });
587218
587908
 
587219
587909
  // build-src/src/components/permissions/shellPermissionHelpers.tsx
587220
- import { basename as basename53, sep as sep37 } from "path";
587910
+ import { basename as basename54, sep as sep37 } from "path";
587221
587911
  function commandListDisplay(commands) {
587222
587912
  switch (commands.length) {
587223
587913
  case 0:
@@ -587248,7 +587938,7 @@ function commandListDisplayTruncated(commands) {
587248
587938
  }
587249
587939
  function formatPathList(paths3) {
587250
587940
  if (paths3.length === 0) return "";
587251
- const names = paths3.map((p) => basename53(p) || p);
587941
+ const names = paths3.map((p) => basename54(p) || p);
587252
587942
  if (names.length === 1) {
587253
587943
  return /* @__PURE__ */ (0, import_jsx_runtime399.jsxs)(ThemedText, { children: [
587254
587944
  /* @__PURE__ */ (0, import_jsx_runtime399.jsx)(ThemedText, { bold: true, children: names[0] }),
@@ -587292,7 +587982,7 @@ function generateShellSuggestionsLabel(suggestions, shellToolName, commandTransf
587292
587982
  if (hasReadPaths && !hasDirectories && !hasCommands) {
587293
587983
  if (readPaths.length === 1) {
587294
587984
  const firstPath = readPaths[0];
587295
- const dirName = basename53(firstPath) || firstPath;
587985
+ const dirName = basename54(firstPath) || firstPath;
587296
587986
  return /* @__PURE__ */ (0, import_jsx_runtime399.jsxs)(ThemedText, { children: [
587297
587987
  "Yes, allow reading from ",
587298
587988
  /* @__PURE__ */ (0, import_jsx_runtime399.jsx)(ThemedText, { bold: true, children: dirName }),
@@ -587309,7 +587999,7 @@ function generateShellSuggestionsLabel(suggestions, shellToolName, commandTransf
587309
587999
  if (hasDirectories && !hasReadPaths && !hasCommands) {
587310
588000
  if (directories.length === 1) {
587311
588001
  const firstDir = directories[0];
587312
- const dirName = basename53(firstDir) || firstDir;
588002
+ const dirName = basename54(firstDir) || firstDir;
587313
588003
  return /* @__PURE__ */ (0, import_jsx_runtime399.jsxs)(ThemedText, { children: [
587314
588004
  "Yes, and always allow access to ",
587315
588005
  /* @__PURE__ */ (0, import_jsx_runtime399.jsx)(ThemedText, { bold: true, children: dirName }),
@@ -589350,7 +590040,7 @@ var init_ideDiffConfig = __esm({
589350
590040
  });
589351
590041
 
589352
590042
  // build-src/src/components/permissions/FileEditPermissionRequest/FileEditPermissionRequest.tsx
589353
- import { basename as basename54, relative as relative31 } from "path";
590043
+ import { basename as basename55, relative as relative31 } from "path";
589354
590044
  function FileEditPermissionRequest(props) {
589355
590045
  const $3 = (0, import_compiler_runtime279.c)(51);
589356
590046
  const parseInput4 = _temp132;
@@ -589393,7 +590083,7 @@ function FileEditPermissionRequest(props) {
589393
590083
  t3 = " ";
589394
590084
  T0 = ThemedText;
589395
590085
  t0 = true;
589396
- t1 = basename54(file_path);
590086
+ t1 = basename55(file_path);
589397
590087
  $3[0] = props.onDone;
589398
590088
  $3[1] = props.onReject;
589399
590089
  $3[2] = props.toolUseConfirm;
@@ -589752,7 +590442,7 @@ var init_FileWriteToolDiff = __esm({
589752
590442
  });
589753
590443
 
589754
590444
  // build-src/src/components/permissions/FileWritePermissionRequest/FileWritePermissionRequest.tsx
589755
- import { basename as basename55, relative as relative32 } from "path";
590445
+ import { basename as basename56, relative as relative32 } from "path";
589756
590446
  function FileWritePermissionRequest(props) {
589757
590447
  const $3 = (0, import_compiler_runtime282.c)(30);
589758
590448
  const parseInput4 = _temp135;
@@ -589820,7 +590510,7 @@ function FileWritePermissionRequest(props) {
589820
590510
  }
589821
590511
  let t9;
589822
590512
  if ($3[7] !== file_path) {
589823
- t9 = basename55(file_path);
590513
+ t9 = basename56(file_path);
589824
590514
  $3[7] = file_path;
589825
590515
  $3[8] = t9;
589826
590516
  } else {
@@ -590156,7 +590846,7 @@ var init_NotebookEditToolDiff = __esm({
590156
590846
  });
590157
590847
 
590158
590848
  // build-src/src/components/permissions/NotebookEditPermissionRequest/NotebookEditPermissionRequest.tsx
590159
- import { basename as basename56 } from "path";
590849
+ import { basename as basename57 } from "path";
590160
590850
  function NotebookEditPermissionRequest(props) {
590161
590851
  const $3 = (0, import_compiler_runtime284.c)(52);
590162
590852
  const parseInput4 = _temp137;
@@ -590200,7 +590890,7 @@ function NotebookEditPermissionRequest(props) {
590200
590890
  t4 = " ";
590201
590891
  T0 = ThemedText;
590202
590892
  t0 = true;
590203
- t1 = basename56(notebook_path);
590893
+ t1 = basename57(notebook_path);
590204
590894
  $3[0] = props.onDone;
590205
590895
  $3[1] = props.onReject;
590206
590896
  $3[2] = props.toolUseConfirm;
@@ -593659,7 +594349,7 @@ var init_useUpdateNotification = __esm({
593659
594349
 
593660
594350
  // build-src/src/sema/overrides/chrome-autoupdater-status.tsx
593661
594351
  import { statSync as statSync11 } from "node:fs";
593662
- import { basename as basename57 } from "path";
594352
+ import { basename as basename58 } from "path";
593663
594353
  function resolveRestoreFailedHint() {
593664
594354
  return null;
593665
594355
  }
@@ -593741,14 +594431,14 @@ function AutoUpdater({
593741
594431
  /* @__PURE__ */ (0, import_jsx_runtime419.jsxs)(ThemedText, { color: "error", wrap: "truncate", children: [
593742
594432
  /* @__PURE__ */ (0, import_jsx_runtime419.jsx)(StatusIcon2, { status: "error", withSpace: true }),
593743
594433
  "Update failed and ",
593744
- basename57(restoreHint.originalPath),
594434
+ basename58(restoreHint.originalPath),
593745
594435
  " could not be restored \u2014 it was preserved at:"
593746
594436
  ] }),
593747
594437
  /* @__PURE__ */ (0, import_jsx_runtime419.jsxs)(ThemedText, { color: "error", wrap: "truncate", children: [
593748
594438
  restoreHint.preservedPath,
593749
594439
  " \xB7 rename it back to",
593750
594440
  " ",
593751
- basename57(restoreHint.originalPath),
594441
+ basename58(restoreHint.originalPath),
593752
594442
  " or run",
593753
594443
  " ",
593754
594444
  /* @__PURE__ */ (0, import_jsx_runtime419.jsxs)(ThemedText, { bold: true, children: [
@@ -594143,7 +594833,7 @@ var init_AutoUpdaterWrapper = __esm({
594143
594833
  });
594144
594834
 
594145
594835
  // build-src/src/components/IdeStatusIndicator.tsx
594146
- import { basename as basename58 } from "path";
594836
+ import { basename as basename59 } from "path";
594147
594837
  function IdeStatusIndicator(t0) {
594148
594838
  const $3 = (0, import_compiler_runtime294.c)(7);
594149
594839
  const {
@@ -594179,7 +594869,7 @@ function IdeStatusIndicator(t0) {
594179
594869
  if (ideSelection.filePath) {
594180
594870
  let t1;
594181
594871
  if ($3[3] !== ideSelection.filePath) {
594182
- t1 = basename58(ideSelection.filePath);
594872
+ t1 = basename59(ideSelection.filePath);
594183
594873
  $3[3] = ideSelection.filePath;
594184
594874
  $3[4] = t1;
594185
594875
  } else {
@@ -597281,7 +597971,7 @@ var init_slackChannelSuggestions = __esm({
597281
597971
  });
597282
597972
 
597283
597973
  // build-src/src/hooks/unifiedSuggestions.ts
597284
- import { basename as basename59 } from "path";
597974
+ import { basename as basename60 } from "path";
597285
597975
  function createSuggestionFromSource(source) {
597286
597976
  switch (source.type) {
597287
597977
  case "file":
@@ -597347,7 +598037,7 @@ async function generateUnifiedSuggestions(query2, mcpResources, agents3, showOnE
597347
598037
  description: suggestion.description,
597348
598038
  path: suggestion.displayText,
597349
598039
  // Use displayText as path for files
597350
- filename: basename59(suggestion.displayText),
598040
+ filename: basename60(suggestion.displayText),
597351
598041
  score: suggestion.metadata?.score
597352
598042
  })
597353
598043
  );
@@ -598755,7 +599445,7 @@ var init_AutoModeOptInDialog = __esm({
598755
599445
  });
598756
599446
 
598757
599447
  // build-src/src/components/BridgeDialog.tsx
598758
- import { basename as basename60 } from "path";
599448
+ import { basename as basename61 } from "path";
598759
599449
  function BridgeDialog(t0) {
598760
599450
  const $3 = (0, import_compiler_runtime298.c)(87);
598761
599451
  const {
@@ -598778,7 +599468,7 @@ function BridgeDialog(t0) {
598778
599468
  const [branchName, setBranchName] = (0, import_react256.useState)("");
598779
599469
  let t1;
598780
599470
  if ($3[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
598781
- t1 = basename60(getOriginalCwd());
599471
+ t1 = basename61(getOriginalCwd());
598782
599472
  $3[0] = t1;
598783
599473
  } else {
598784
599474
  t1 = $3[0];
@@ -613289,7 +613979,7 @@ __export(asciicast_exports, {
613289
613979
  renameRecordingForSession: () => renameRecordingForSession
613290
613980
  });
613291
613981
  import { appendFile as appendFile5, rename as rename14 } from "fs/promises";
613292
- import { basename as basename61, dirname as dirname74, join as join172 } from "path";
613982
+ import { basename as basename62, dirname as dirname74, join as join172 } from "path";
613293
613983
  function getRecordFilePath() {
613294
613984
  if (recordingState.filePath !== null) {
613295
613985
  return recordingState.filePath;
@@ -613341,8 +614031,8 @@ async function renameRecordingForSession() {
613341
614031
  return;
613342
614032
  }
613343
614033
  await recorder?.flush();
613344
- const oldName = basename61(oldPath);
613345
- const newName = basename61(newPath);
614034
+ const oldName = basename62(oldPath);
614035
+ const newName = basename62(newPath);
613346
614036
  try {
613347
614037
  await rename14(oldPath, newPath);
613348
614038
  recordingState.filePath = newPath;
@@ -623365,441 +624055,14 @@ var init_ScrollKeybindingHandler = __esm({
623365
624055
  }
623366
624056
  });
623367
624057
 
623368
- // build-src/src/utils/taskSummary.ts
623369
- var taskSummary_exports = {};
623370
- __export(taskSummary_exports, {
623371
- bgJobShort: () => bgJobShort,
623372
- blockedSummaryFor: () => blockedSummaryFor,
623373
- classifiedToPostTurnSummary: () => classifiedToPostTurnSummary,
623374
- classifierSummaryEnabled: () => classifierSummaryEnabled,
623375
- classifyTurnTail: () => classifyTurnTail,
623376
- emitTurnEndSummary: () => emitTurnEndSummary,
623377
- heuristicFallback: () => heuristicFallback,
623378
- notifySessionActivityForSummary: () => notifySessionActivityForSummary,
623379
- preClassifyTail: () => preClassifyTail,
623380
- runClassifierSummaryForBlocked: () => runClassifierSummaryForBlocked,
623381
- turnTail: () => turnTail
623382
- });
623383
- import { basename as basename62 } from "path";
623384
- function classifierSummaryEnabled() {
623385
- const v2 = process.env.SEMA_CODE_CLASSIFIER_SUMMARY ?? process.env[CLASSIFIER_SUMMARY_ENV];
623386
- if (v2 === void 0) return true;
623387
- return !/^(0|false|off|no|none)$/i.test(v2.trim());
623388
- }
623389
- function bgJobShort() {
623390
- const dir = process.env.SEMA_JOB_DIR;
623391
- if (!dir) return null;
623392
- const short = basename62(dir);
623393
- return short.length > 0 ? short : null;
623394
- }
623395
- function truncateDetail(s, max2 = DETAIL_MAX) {
623396
- if (s.length <= max2) return s;
623397
- let r = max2 - 1;
623398
- const c2 = s.charCodeAt(r - 1);
623399
- if (c2 >= 55296 && c2 <= 56319) r--;
623400
- return s.slice(0, r) + "\u2026";
623401
- }
623402
- function insideCodeFence(e, t2) {
623403
- let open20 = null;
623404
- let openLen = 0;
623405
- let o = 0;
623406
- while (o < t2) {
623407
- const i = e.indexOf("```", o);
623408
- const s = e.indexOf("~~~", o);
623409
- const a = i === -1 ? s : s === -1 ? i : Math.min(i, s);
623410
- if (a === -1 || a >= t2) break;
623411
- const ch2 = e[a];
623412
- let c2 = a - 1;
623413
- let u3 = 0;
623414
- while (c2 >= 0 && e[c2] === " " && u3 < 3) {
623415
- c2--;
623416
- u3++;
623417
- }
623418
- const atLineStart = c2 < 0 || e[c2] === "\n";
623419
- let len = 3;
623420
- o = a + 3;
623421
- while (e[o] === ch2) {
623422
- o++;
623423
- len++;
623424
- }
623425
- if (!atLineStart) continue;
623426
- if (open20 === null) {
623427
- open20 = ch2;
623428
- openLen = len;
623429
- } else if (open20 === ch2 && len >= openLen) {
623430
- open20 = null;
623431
- openLen = 0;
623432
- }
623433
- }
623434
- return open20 !== null;
623435
- }
623436
- function latestMarker(full, window2, windowStart) {
623437
- let best;
623438
- const table = [
623439
- ["failed", FAILED_MARKER],
623440
- ["blocked", NEEDS_INPUT_MARKER],
623441
- ["blocked", BLOCKED_MARKER],
623442
- ["blocked", IM_BLOCKED_MARKER]
623443
- ];
623444
- for (const [state3, re] of table) {
623445
- for (const m2 of window2.matchAll(re)) {
623446
- if (insideCodeFence(full, windowStart + m2.index)) continue;
623447
- if (!best || m2.index > best.index) {
623448
- best = {
623449
- state: state3,
623450
- capture: m2[1].trim(),
623451
- index: m2.index,
623452
- end: m2.index + m2[0].length
623453
- };
623454
- }
623455
- }
623456
- }
623457
- return best;
623458
- }
623459
- function preClassifyTail(text2) {
623460
- const t2 = text2.trim();
623461
- if (!t2) return null;
623462
- let window2 = t2.slice(-800);
623463
- let windowStart = t2.length - window2.length;
623464
- let resultMatch;
623465
- for (const m2 of window2.matchAll(/(?:^|\n)\s*result:\s*(.+?)\s*(?:\n|$)/gi)) {
623466
- if (!insideCodeFence(t2, windowStart + m2.index)) resultMatch = m2;
623467
- }
623468
- if (resultMatch) {
623469
- const after = resultMatch.index + resultMatch[0].length;
623470
- window2 = window2.slice(after);
623471
- windowStart += after;
623472
- }
623473
- const marker = latestMarker(t2, window2, windowStart);
623474
- if (resultMatch && !marker) {
623475
- const detail = truncateDetail(resultMatch[1]);
623476
- const hasNext = [...window2.matchAll(/(?:^|\n)\s*next:\s*\S/gi)].some(
623477
- (m2) => !insideCodeFence(t2, windowStart + m2.index)
623478
- );
623479
- if (hasNext) return { branch: "result-then-next", state: "working", tempo: "idle", detail };
623480
- return { branch: "result-marker", state: "done", tempo: "idle", detail };
623481
- }
623482
- if (marker?.state === "failed") {
623483
- return { branch: "failed-marker", state: "failed", tempo: "idle", detail: truncateDetail(marker.capture) };
623484
- }
623485
- if (marker?.state === "blocked") {
623486
- const after = window2.slice(marker.end);
623487
- const paras = after.split(/\n\s*\n/).filter((p) => p.trim().length > 0).length;
623488
- if (paras >= 3) return null;
623489
- if (!/\bnothing (?:needed|required) from you\b|\bno(?: user)? action (?:needed|required)\b/i.test(
623490
- window2
623491
- )) {
623492
- const m2 = truncateDetail(marker.capture);
623493
- return { branch: "blocked-marker", state: "blocked", tempo: "blocked", needs: m2, detail: m2 };
623494
- }
623495
- return null;
623496
- }
623497
- const tail800 = t2.slice(-800);
623498
- if (/[??]\s*$/.test(tail800) && tail800.replace(/[??\s]+$/, "").length >= 4) {
623499
- const f = Math.max(
623500
- tail800.lastIndexOf("\n"),
623501
- tail800.lastIndexOf(". "),
623502
- tail800.lastIndexOf("! "),
623503
- tail800.lastIndexOf("? ", tail800.length - 2)
623504
- );
623505
- if (!insideCodeFence(t2, t2.length - tail800.length + f)) {
623506
- const q2 = truncateDetail(tail800.slice(f + 1).trim());
623507
- if (!OPTIONAL_OFFER.test(q2)) {
623508
- return { branch: "trailing-q", state: "blocked", tempo: "blocked", needs: q2, detail: q2 };
623509
- }
623510
- return null;
623511
- }
623512
- }
623513
- const a = Math.max(
623514
- 0,
623515
- tail800.lastIndexOf(". "),
623516
- tail800.lastIndexOf("! "),
623517
- tail800.lastIndexOf("? "),
623518
- tail800.lastIndexOf("\n")
623519
- );
623520
- const l3 = tail800.slice(a).replace(/^[.!?\s]+/, "");
623521
- const fenced = insideCodeFence(t2, t2.length - tail800.length + a);
623522
- const waitExt = WAIT_EXTERNAL.exec(l3);
623523
- if (waitExt && !fenced) {
623524
- return { branch: "wait-external", state: "working", tempo: "idle", detail: truncateDetail(waitExt[0]) };
623525
- }
623526
- const awaiting = AWAITING_USER.exec(l3);
623527
- if (awaiting && !fenced) {
623528
- const f = truncateDetail(l3.slice(awaiting.index).trim());
623529
- return { branch: "awaiting-user", state: "blocked", tempo: "blocked", needs: f, detail: f };
623530
- }
623531
- const ask2 = ASK_VERB.exec(l3);
623532
- if (ask2 && !fenced) {
623533
- const f = truncateDetail(l3.slice(ask2.index).trim());
623534
- return { branch: "ask-verb", state: "blocked", tempo: "blocked", needs: f, detail: f };
623535
- }
623536
- if (!fenced && AUTH_PROSE.test(l3)) {
623537
- return {
623538
- branch: "auth-prose",
623539
- state: "blocked",
623540
- tempo: "blocked",
623541
- needs: truncateDetail(l3),
623542
- detail: "authentication required"
623543
- };
623544
- }
623545
- if (!fenced && WORKING_VERB.test(l3) && !NOT_FORWARD_INTENT.test(l3)) {
623546
- return { branch: "working-verb", state: "working", tempo: "active", detail: truncateDetail(l3) };
623547
- }
623548
- if (!fenced && AGENTS_STATUS.test(l3)) {
623549
- return { branch: "agents-status", state: "working", tempo: "idle", detail: truncateDetail(l3) };
623550
- }
623551
- if (!fenced && WILL_CHECK_BACK.test(l3)) {
623552
- return { branch: "will-check-back", state: "working", tempo: "idle", detail: truncateDetail(l3) };
623553
- }
623554
- if (!fenced && CANT_PROCEED.test(l3)) {
623555
- const f = truncateDetail(l3);
623556
- return { branch: "cant-proceed", state: "blocked", tempo: "blocked", detail: f, needs: f };
623557
- }
623558
- if (!fenced && GIVING_UP.test(l3)) {
623559
- return { branch: "giving-up", state: "failed", tempo: "idle", detail: truncateDetail(l3) };
623560
- }
623561
- if (!fenced && PUSHED_COMMITTED.test(l3)) {
623562
- return { branch: "pushed-committed", state: "done", tempo: "idle", detail: truncateDetail(l3) };
623563
- }
623564
- if (!fenced && READY_FOR.test(l3)) {
623565
- return { branch: "ready-for", state: "done", tempo: "idle", detail: truncateDetail(l3) };
623566
- }
623567
- if (!fenced && VERDICT_MARKER.test(l3)) {
623568
- return { branch: "verdict-marker", state: "done", tempo: "idle", detail: truncateDetail(l3) };
623569
- }
623570
- if (!fenced && PLEASE_DO_X.test(l3)) {
623571
- const f = truncateDetail(l3);
623572
- return { branch: "please-do-x", state: "blocked", tempo: "blocked", detail: f, needs: f };
623573
- }
623574
- if (!fenced && STOPPING_HERE.test(l3)) {
623575
- const f = truncateDetail(l3);
623576
- return { branch: "stopping-here", state: "blocked", tempo: "blocked", detail: f, needs: f };
623577
- }
623578
- return null;
623579
- }
623580
- function heuristicFallback(text2) {
623581
- const line = text2.split("\n").map((l3) => l3.trim()).findLast(Boolean);
623582
- return {
623583
- branch: "heuristic",
623584
- state: "working",
623585
- tempo: "idle",
623586
- detail: line ? truncateDetail(line) : "\u2014"
623587
- };
623588
- }
623589
- function classifyTurnTail(text2) {
623590
- const c2 = preClassifyTail(text2) ?? heuristicFallback(text2);
623591
- if (c2.tempo === "active" && c2.state === "working") return { ...c2, tempo: "idle" };
623592
- return c2;
623593
- }
623594
- function classifiedToPostTurnSummary(c2) {
623595
- return {
623596
- status_category: c2.state === "blocked" ? "blocked" : "review_ready",
623597
- status_detail: c2.detail,
623598
- needs_action: c2.state === "blocked" ? c2.needs ?? "" : ""
623599
- };
623600
- }
623601
- function assistantText(m2) {
623602
- const c2 = m2.message?.content;
623603
- if (typeof c2 === "string") return c2.trim();
623604
- if (!Array.isArray(c2)) return "";
623605
- return c2.map((b3) => b3?.type === "text" && typeof b3.text === "string" ? b3.text : "").filter(Boolean).join("\n").trim();
623606
- }
623607
- function turnTail(messages) {
623608
- const msgs = messages;
623609
- let start = 0;
623610
- for (let i = msgs.length - 1; i >= 0; i--) {
623611
- const m2 = msgs[i];
623612
- if (m2.type === "user" && !m2.isMeta && typeof m2.message?.content === "string") {
623613
- start = i + 1;
623614
- break;
623615
- }
623616
- }
623617
- const parts = [];
623618
- let lastAssistantUuid = "";
623619
- for (let i = start; i < msgs.length; i++) {
623620
- const m2 = msgs[i];
623621
- if (m2.type !== "assistant" || m2.isApiErrorMessage) continue;
623622
- const text2 = assistantText(m2);
623623
- if (text2) parts.push(text2);
623624
- if (typeof m2.uuid === "string") lastAssistantUuid = m2.uuid;
623625
- }
623626
- return { text: parts.join("\n\n"), lastAssistantUuid };
623627
- }
623628
- function chainBgWrite(fn2) {
623629
- bgWriteChain = bgWriteChain.then(fn2).catch(() => {
623630
- });
623631
- return bgWriteChain;
623632
- }
623633
- async function writeBgTurnEnd(short, c2) {
623634
- bgBlockedByActivity = false;
623635
- const cur = await readJobState(short);
623636
- if (!cur) return;
623637
- const curTerminal = isTerminalJobState(cur.state);
623638
- const nextTerminal = c2.state === "done" || c2.state === "failed";
623639
- const terminal = curTerminal || nextTerminal;
623640
- await patchJobState(short, {
623641
- state: curTerminal ? cur.state : c2.state,
623642
- detail: c2.detail,
623643
- tempo: terminal ? "idle" : c2.tempo,
623644
- needs: c2.tempo === "blocked" && !terminal ? c2.needs : void 0,
623645
- ...terminal && !cur.firstTerminalAt ? { firstTerminalAt: Date.now() } : {}
623646
- });
623647
- }
623648
- function emitForegroundSummary(c2, summarizesUuid) {
623649
- const y2 = classifiedToPostTurnSummary(c2);
623650
- notifySessionMetadataChanged({ post_turn_summary: y2 });
623651
- enqueueSdkEvent({
623652
- type: "system",
623653
- subtype: "post_turn_summary",
623654
- summarizes_uuid: summarizesUuid,
623655
- status_category: y2.status_category,
623656
- status_detail: y2.status_detail,
623657
- needs_action: y2.needs_action,
623658
- is_noteworthy: false,
623659
- title: "",
623660
- description: "",
623661
- recent_action: "",
623662
- artifact_urls: []
623663
- });
623664
- }
623665
- async function emitTurnEndSummary(messages) {
623666
- if (!classifierSummaryEnabled()) return;
623667
- const { text: text2, lastAssistantUuid } = turnTail(messages);
623668
- if (!/[\p{L}\p{N}]/u.test(text2)) return;
623669
- const classified = classifyTurnTail(text2);
623670
- const short = bgJobShort();
623671
- if (short) {
623672
- await chainBgWrite(() => writeBgTurnEnd(short, classified));
623673
- return;
623674
- }
623675
- emitForegroundSummary(classified, lastAssistantUuid);
623676
- }
623677
- function blockedSummaryFor(details) {
623678
- if (details.tool_name.startsWith("dialog:")) {
623679
- return {
623680
- status_category: "blocked",
623681
- status_detail: "Waiting on a user dialog",
623682
- needs_action: details.action_description ?? ""
623683
- };
623684
- }
623685
- return {
623686
- status_category: "blocked",
623687
- status_detail: `Waiting on permission: ${details.tool_name}`,
623688
- needs_action: `Approve or deny ${details.tool_name}`
623689
- };
623690
- }
623691
- function runClassifierSummaryForBlocked(details) {
623692
- if (!classifierSummaryEnabled()) return;
623693
- if (bgJobShort()) return;
623694
- notifySessionMetadataChanged({ post_turn_summary: blockedSummaryFor(details) });
623695
- }
623696
- async function writeBgBlocked(short, summary) {
623697
- const cur = await readJobState(short);
623698
- if (!cur || isTerminalJobState(cur.state)) return;
623699
- if (cur.tempo === "blocked" && cur.needs === summary.needs_action) return;
623700
- await patchJobState(short, {
623701
- state: "blocked",
623702
- tempo: "blocked",
623703
- detail: summary.status_detail,
623704
- needs: summary.needs_action || summary.status_detail
623705
- });
623706
- }
623707
- async function writeBgUnblocked(short, busy) {
623708
- const cur = await readJobState(short);
623709
- if (!cur) return;
623710
- if (busy) {
623711
- bgBlockedByActivity = false;
623712
- if (cur.tempo === "active" && !isTerminalJobState(cur.state) && cur.state !== "blocked") return;
623713
- const reviving = isTerminalJobState(cur.state);
623714
- await patchJobState(
623715
- short,
623716
- {
623717
- state: reviving || cur.state === "blocked" ? "working" : cur.state,
623718
- tempo: "active",
623719
- needs: void 0,
623720
- ...reviving ? { firstTerminalAt: void 0 } : {}
623721
- },
623722
- { allowRevive: true }
623723
- );
623724
- return;
623725
- }
623726
- if (!bgBlockedByActivity) return;
623727
- bgBlockedByActivity = false;
623728
- if (cur.tempo !== "blocked" || isSettledJobState(cur)) return;
623729
- await patchJobState(short, {
623730
- state: cur.state === "blocked" ? "working" : cur.state,
623731
- tempo: "idle",
623732
- needs: void 0
623733
- });
623734
- }
623735
- function notifySessionActivityForSummary(input) {
623736
- if (!classifierSummaryEnabled()) return;
623737
- const prev = prevActivityStatus;
623738
- prevActivityStatus = input.status;
623739
- const short = bgJobShort();
623740
- if (input.status === "waiting") {
623741
- const w2 = input.waitingFor ?? "";
623742
- const details = w2.startsWith("approve ") ? { tool_name: w2.slice("approve ".length), action_description: w2 } : { tool_name: "dialog:" + (w2 || "input"), action_description: w2 || "input needed" };
623743
- const summary = blockedSummaryFor(details);
623744
- if (short) {
623745
- bgBlockedByActivity = true;
623746
- void chainBgWrite(() => writeBgBlocked(short, summary));
623747
- } else {
623748
- notifySessionMetadataChanged({ post_turn_summary: summary });
623749
- }
623750
- return;
623751
- }
623752
- if (input.status === "idle" && prev === "busy" && input.getMessages) {
623753
- const messages = input.getMessages();
623754
- void emitTurnEndSummary(messages);
623755
- return;
623756
- }
623757
- if (short) {
623758
- void chainBgWrite(() => writeBgUnblocked(short, input.status === "busy"));
623759
- }
623760
- }
623761
- var CLASSIFIER_SUMMARY_ENV, DETAIL_MAX, FAILED_MARKER, NEEDS_INPUT_MARKER, BLOCKED_MARKER, IM_BLOCKED_MARKER, OPTIONAL_OFFER, WORKING_VERB, NOT_FORWARD_INTENT, AGENTS_STATUS, WILL_CHECK_BACK, CANT_PROCEED, GIVING_UP, PUSHED_COMMITTED, READY_FOR, VERDICT_MARKER, PLEASE_DO_X, STOPPING_HERE, WAIT_EXTERNAL, AWAITING_USER, ASK_VERB, AUTH_PROSE, bgWriteChain, bgBlockedByActivity, prevActivityStatus;
623762
- var init_taskSummary = __esm({
623763
- "build-src/src/utils/taskSummary.ts"() {
623764
- init_state2();
623765
- init_sdkEventQueue();
623766
- init_sessionState();
623767
- CLASSIFIER_SUMMARY_ENV = "CLAUDE_CODE_CLASSIFIER_SUMMARY";
623768
- DETAIL_MAX = 800;
623769
- FAILED_MARKER = /(?:^|\n)\s*failed\s*[:—–-]\s*(.{3,200}?)(?=\n|$)/gi;
623770
- NEEDS_INPUT_MARKER = /(?:^|\n)\s*needs input\s*[:—–-]\s*(.{3,200}?)(?=\n|$)/gi;
623771
- BLOCKED_MARKER = /(?:^|\n)\s*blocked\s*[:—–-]\s*(.{3,200}?)(?=\n|$)/gi;
623772
- IM_BLOCKED_MARKER = /\bI'?m blocked\s*[:—–-]\s*(.{3,200}?)(?=\n|$)/gi;
623773
- OPTIONAL_OFFER = /\b(?:want|like) me to\b|\b(?:shall|should) I also\b/i;
623774
- WORKING_VERB = /^(?:(?:Now|Next|Then|Alright|OK|Okay|Right|Good|First|Also),?\s+)?(?:Let me (?!know\b)|(?:I(?:'?ll| will) |I'?m going to |Going to )(?!need\b|require\b|wait\b|leave\b|hold\b|skip\b|stop\b)|Proceeding |Moving (?:on|to)\b|Continuing |Starting |Trying |Checking |Looking |Searching |Reading |Investigating |Running |Re-?running |Building |Rebuilding |Installing |Fetching |Applying |Fixing |Patching |Updating |Adding |Removing |Deleting |Importing |Refactoring |Rewriting |Writing |Grepping |Scanning |Wrapping |Switching |Testing |Verifying |Regenerating |Pushing |Pulling |Reviewing |Examining |Loading |Compiling |Parsing |Analyzing |Tracing |Exploring )/i;
623775
- NOT_FORWARD_INTENT = /\b(?:once |when |after |until |as soon as )(?:you|it|the|that|this|they)\b|\bagain in\b|\bcheck back\b|\bin ~?\d+\s*(?:s(?:ec(?:ond)?s?)?|m(?:in(?:ute)?s?)?|h(?:ours?|rs?)?)\b|\bthen\.?\s*$|\bwhichever you\b|\bhold(?:ing)? for your\b|\b(?:to|and) wait for\b|\bgive it (?:more |some )?time\b|\bif (?:you(?:'d| want| prefer| need|'re)?|that(?:'s| helps| works)?|useful|needed|helpful|desired)\b|\b(?:isn'?t|not|won'?t) going to work\b/i;
623776
- AGENTS_STATUS = /^(?:(?:\*\*)?[1-9]\d* (?:agent|cron|task|fork|job|worker|PR|check)s? (?:in flight|remaining|active|still (?:running|working)|pending|running|launched)\b|(?:Continuous )?(?:[Ll]oop|[Cc]rons?|[Bb]abysit) (?:active|healthy|continuing|running|will keep|continues)\b|Waiting for (?:the )?(?:agent|cron|task|fork|worker|job|remaining|them)s?\b|Agents? will report back\b|Waiting\.?$)/;
623777
- WILL_CHECK_BACK = /^(?:I will|I'll|Will) (?:check back|re-?check|poll|look again|retry|re-?run|try again) (?:(?:when|once|after|until) (?!your?\b)|in\b|again\b)/i;
623778
- CANT_PROCEED = /^I (?:can(?:'?t|not)|am unable to) (?:proceed|continue|make (?:any )?progress|complete|fix this)\b/i;
623779
- GIVING_UP = /^(?:Giving up|I(?:'m| am) giving up|The task is not actionable)\b/i;
623780
- PUSHED_COMMITTED = /^(?:Pushed (?:to `|`[0-9a-f]{7,})|Committed as `?[0-9a-f]{7,}\b|Commit: `?[0-9a-f]{7,}\b|(?:Opened|Created) PR #?\d)/;
623781
- READY_FOR = /^Ready (?:for review|to (?:upload|merge|ship|land))\b/;
623782
- VERDICT_MARKER = /^VERDICT: (?:PASS|FAIL)\b/;
623783
- PLEASE_DO_X = /^Please (?:start|run|provide|grant|export|add|install|configure|give me|paste|point me|set (?:the |up |`?[A-Z][A-Z0-9_]+\b))/;
623784
- STOPPING_HERE = /^(?:Stopping here|I've stopped here|Parked (?:the|this) branch|Paused here)(?:\.|$| —| -| until| pending| since| because)/i;
623785
- WAIT_EXTERNAL = /\b(?:waiting (?:for|on)|pending)\s+(?:the\s+)?(?:CI|build|tests?|reviewer|deploy(?:ment)?|workflow|checks?|rollout|merge queue)\b/i;
623786
- AWAITING_USER = /\b(?:awaiting|waiting (?:for|on)|pending)\s+(?:your\s+(?:feedback|input|decision|response|approval|direction|guidance|go-ahead)|you\b|the user\b)/i;
623787
- ASK_VERB = /\b(please (?:run|provide|confirm|clarify|choose|let me know)|let me know (?:which|what|how|when)|which (?:option|approach|one)|should I (?:proceed|continue|use))\b/i;
623788
- AUTH_PROSE = /\b(not logged in|please run \/login|authentication failed|invalid api key|oauth token (?:expired|revoked)|credit balance (?:is )?too low|usage limit reached|mcp (?:server )?(?:authentication|auth|authorization|unauthorized)|mcp (?:server )?(?:credential|token) (?:missing|expired|invalid)|401 unauthorized|403 forbidden|token (?:has )?expired|bad credentials|gh auth login|gcloud auth login|aws (?:sso )?login)\b/i;
623789
- bgWriteChain = Promise.resolve();
623790
- bgBlockedByActivity = false;
623791
- prevActivityStatus = "idle";
623792
- }
623793
- });
623794
-
623795
624058
  // build-src/src/screens/REPL.tsx
623796
624059
  var REPL_exports = {};
623797
624060
  __export(REPL_exports, {
623798
624061
  REPL: () => REPL
623799
624062
  });
623800
- import { spawnSync as spawnSync10 } from "child_process";
624063
+ import { spawnSync as spawnSync11 } from "child_process";
623801
624064
  import { dirname as dirname76, join as join175 } from "path";
623802
- import { tmpdir as tmpdir15 } from "os";
624065
+ import { tmpdir as tmpdir16 } from "os";
623803
624066
  import { writeFile as writeFile48 } from "fs/promises";
623804
624067
  import { randomUUID as randomUUID50 } from "crypto";
623805
624068
  function TranscriptModeFooter(t0) {
@@ -626215,7 +626478,7 @@ Error: sandbox required but unavailable: ${reason}
626215
626478
  const handleExit = (0, import_react337.useCallback)(async () => {
626216
626479
  setIsExiting(true);
626217
626480
  if (isBgSession()) {
626218
- spawnSync10("tmux", ["detach-client"], {
626481
+ spawnSync11("tmux", ["detach-client"], {
626219
626482
  stdio: "ignore"
626220
626483
  });
626221
626484
  setIsExiting(false);
@@ -626747,7 +627010,7 @@ Note: ctrl + z now suspends Sema, ctrl + _ undoes input.
626747
627010
  const w2 = Math.max(80, (process.stdout.columns ?? 80) - 6);
626748
627011
  const raw2 = await renderMessagesToPlainText(deferredMessages, tools, w2);
626749
627012
  const text2 = raw2.replace(/[ \t]+$/gm, "");
626750
- const path27 = join175(tmpdir15(), `cc-transcript-${Date.now()}.txt`);
627013
+ const path27 = join175(tmpdir16(), `cc-transcript-${Date.now()}.txt`);
626751
627014
  await writeFile48(path27, text2);
626752
627015
  const opened = openFileInExternalEditor(path27);
626753
627016
  setStatus(opened ? `opening ${path27}` : `wrote ${path27} \xB7 no $VISUAL/$EDITOR set`);
@@ -632952,7 +633215,7 @@ async function collectEngineRows() {
632952
633215
  try {
632953
633216
  return configuredEnginePort();
632954
633217
  } catch {
632955
- return { port: DEFAULT_ENGINE_PORT, source: "default" };
633218
+ return { port: derivedDefaultEnginePort(), source: "default" };
632956
633219
  }
632957
633220
  })();
632958
633221
  const configuredPort2 = cp2.port;
@@ -633165,6 +633428,7 @@ var init_semaSections = __esm({
633165
633428
  init_ink2();
633166
633429
  init_envUtils();
633167
633430
  init_engineLifecycleManager();
633431
+ init_enginePortDerive();
633168
633432
  init_engineTarget();
633169
633433
  init_semaUpdater();
633170
633434
  init_axesRows();
@@ -651961,8 +652225,8 @@ __export(cloudResources_exports, {
651961
652225
  cloudResourceRemove: () => cloudResourceRemove,
651962
652226
  cloudResourceSync: () => cloudResourceSync
651963
652227
  });
651964
- import { createHash as createHash25 } from "node:crypto";
651965
- import { existsSync as existsSync25, readdirSync as readdirSync8, readFileSync as readFileSync39, statSync as statSync12 } from "node:fs";
652228
+ import { createHash as createHash26 } from "node:crypto";
652229
+ import { existsSync as existsSync25, readdirSync as readdirSync9, readFileSync as readFileSync39, statSync as statSync12 } from "node:fs";
651966
652230
  import { basename as basename64, dirname as dirname81, isAbsolute as isAbsolute32, join as join186, resolve as resolve47 } from "node:path";
651967
652231
  function fail4(e) {
651968
652232
  err6(`Error: ${e instanceof Error ? e.message : String(e)}`);
@@ -652558,7 +652822,7 @@ async function readSkillEntry(file2, fallbackName) {
652558
652822
  if (!content) {
652559
652823
  return { name, display: display2, entry: null, notes: [], skipReason: `${file2} has no body after the frontmatter \u2014 nothing to upload.` };
652560
652824
  }
652561
- const contentHash = `sha256:${createHash25("sha256").update(content, "utf8").digest("hex")}`;
652825
+ const contentHash = `sha256:${createHash26("sha256").update(content, "utf8").digest("hex")}`;
652562
652826
  return {
652563
652827
  name,
652564
652828
  display: display2,
@@ -652572,7 +652836,7 @@ async function loadLocalSkillEntries() {
652572
652836
  for (const root2 of roots) {
652573
652837
  let dirs = [];
652574
652838
  try {
652575
- dirs = readdirSync8(root2).filter((d2) => {
652839
+ dirs = readdirSync9(root2).filter((d2) => {
652576
652840
  try {
652577
652841
  return statSync12(join186(root2, d2)).isDirectory() && existsSync25(join186(root2, d2, "SKILL.md"));
652578
652842
  } catch {
@@ -657389,7 +657653,7 @@ import {
657389
657653
  copyFileSync as copyFileSync5,
657390
657654
  existsSync as existsSync27,
657391
657655
  mkdirSync as mkdirSync21,
657392
- readdirSync as readdirSync9,
657656
+ readdirSync as readdirSync10,
657393
657657
  readFileSync as readFileSync40,
657394
657658
  statSync as statSync14
657395
657659
  } from "node:fs";
@@ -657536,7 +657800,7 @@ function syncTree(srcDir, destDir, labelBase, opts, report) {
657536
657800
  syncPlainFile(srcDir, destDir, labelBase, opts, report);
657537
657801
  return;
657538
657802
  }
657539
- for (const name of readdirSync9(srcDir)) {
657803
+ for (const name of readdirSync10(srcDir)) {
657540
657804
  const srcChild = join189(srcDir, name);
657541
657805
  const destChild = join189(destDir, name);
657542
657806
  let childStat;
@@ -658357,7 +658621,7 @@ var init_navStack = __esm({
658357
658621
  });
658358
658622
 
658359
658623
  // build-src/src/sema/config/skillsChannels.ts
658360
- import { existsSync as existsSync28, mkdirSync as mkdirSync22, readdirSync as readdirSync10, readFileSync as readFileSync43, realpathSync as realpathSync11, renameSync as renameSync8, statSync as statSync15 } from "node:fs";
658624
+ import { existsSync as existsSync28, mkdirSync as mkdirSync22, readdirSync as readdirSync11, readFileSync as readFileSync43, realpathSync as realpathSync11, renameSync as renameSync8, statSync as statSync15 } from "node:fs";
658361
658625
  import { basename as basename66, dirname as dirname85, join as join192 } from "node:path";
658362
658626
  function skillsDirFor(source) {
658363
658627
  return source === "user" ? join192(getClaudeConfigHomeDir(), "skills") : join192(getCwd(), ".sema", "skills");
@@ -658414,7 +658678,7 @@ function listInstalledSkills() {
658414
658678
  const dir = skillsDirFor(source);
658415
658679
  let entries;
658416
658680
  try {
658417
- entries = readdirSync10(dir).filter((n2) => !n2.startsWith("."));
658681
+ entries = readdirSync11(dir).filter((n2) => !n2.startsWith("."));
658418
658682
  } catch {
658419
658683
  continue;
658420
658684
  }
@@ -658535,7 +658799,7 @@ function settingsEnv3() {
658535
658799
  function configuredEnginePort2() {
658536
658800
  const raw2 = settingsEnv3().SEMA_ENGINE_PORT ?? process.env.SEMA_ENGINE_PORT;
658537
658801
  const p = raw2 ? Number.parseInt(raw2, 10) : NaN;
658538
- return Number.isInteger(p) && p > 0 && p < 65536 ? p : DEFAULT_ENGINE_PORT;
658802
+ return Number.isInteger(p) && p > 0 && p < 65536 ? p : derivedDefaultEnginePort();
658539
658803
  }
658540
658804
  function engineSummary() {
658541
658805
  const autostart = process.env.SEMA_TOC_ENGINE === "0" ? "autostart off" : "autostart on";
@@ -658559,7 +658823,7 @@ function portEditScreen() {
658559
658823
  title: "Engine \xB7 port",
658560
658824
  label: "Port:",
658561
658825
  initial: String(configuredEnginePort2()),
658562
- placeholder: String(DEFAULT_ENGINE_PORT),
658826
+ placeholder: String(derivedDefaultEnginePort()),
658563
658827
  onSubmit: (v2) => {
658564
658828
  const p = Number.parseInt(v2, 10);
658565
658829
  if (!Number.isInteger(p) || p <= 0 || p >= 65536) {
@@ -658640,7 +658904,7 @@ var init_EngineScreen = __esm({
658640
658904
  init_select();
658641
658905
  init_semaSections();
658642
658906
  init_envUtils();
658643
- init_engineLifecycleManager();
658907
+ init_enginePortDerive();
658644
658908
  init_applyOnboard();
658645
658909
  init_catalogScreens();
658646
658910
  import_jsx_runtime509 = __toESM(require_jsx_runtime(), 1);
@@ -664200,7 +664464,7 @@ Auth: unix socket -R \u2192 local proxy`, "info");
664200
664464
  pendingHookMessages
664201
664465
  }, renderAndRun);
664202
664466
  }
664203
- }).version("sema 1.0.1", "-v, --version", "Output the version number");
664467
+ }).version("sema 1.0.2", "-v, --version", "Output the version number");
664204
664468
  program2.option("-w, --worktree [name]", "Create a new git worktree for this session (optionally specify a name)");
664205
664469
  program2.option("--tmux", "Create a tmux session for the worktree (requires --worktree). Uses iTerm2 native panes when available; use --tmux=classic for traditional tmux.");
664206
664470
  if (canUserConfigureAdvisor()) {
@@ -665187,8 +665451,8 @@ Auth: unix socket -R \u2192 local proxy`, "info");
665187
665451
  const completed = await onboardHandler2();
665188
665452
  if (completed && process.env.SEMA_ONBOARD_NO_LAUNCH !== "1") {
665189
665453
  try {
665190
- const { spawnSync: spawnSync12 } = await import("node:child_process");
665191
- spawnSync12(process.execPath, [process.argv[1]], { stdio: "inherit" });
665454
+ const { spawnSync: spawnSync13 } = await import("node:child_process");
665455
+ spawnSync13(process.execPath, [process.argv[1]], { stdio: "inherit" });
665192
665456
  } catch {
665193
665457
  }
665194
665458
  }
@@ -668505,12 +668769,12 @@ var init_skillsFill = __esm({
668505
668769
  });
668506
668770
 
668507
668771
  // build-src/mock/commands/teamOnboarding.ts
668508
- import { existsSync as existsSync31, readdirSync as readdirSync11 } from "fs";
668772
+ import { existsSync as existsSync31, readdirSync as readdirSync12 } from "fs";
668509
668773
  function hasWorkspaceData() {
668510
668774
  try {
668511
668775
  const dir = getProjectsDir2();
668512
668776
  if (!existsSync31(dir)) return false;
668513
- return readdirSync11(dir).length > 0;
668777
+ return readdirSync12(dir).length > 0;
668514
668778
  } catch {
668515
668779
  return false;
668516
668780
  }
@@ -669771,6 +670035,17 @@ async function runDaemonWorker(kind) {
669771
670035
  });
669772
670036
  const { installWorkerVirtualTerminal: installWorkerVirtualTerminal2 } = await Promise.resolve().then(() => (init_workerScreen(), workerScreen_exports));
669773
670037
  installWorkerVirtualTerminal2({ cols: config5.cols, rows: config5.rows, jobDir: config5.jobDir });
670038
+ try {
670039
+ const { subscribeEngineRuntimeStatus: subscribeEngineRuntimeStatus2, getEngineRuntimeStatus: getEngineRuntimeStatus2 } = await Promise.resolve().then(() => (init_engineRuntimeStatus(), engineRuntimeStatus_exports));
670040
+ const { reportBgEngineDown: reportBgEngineDown2 } = await Promise.resolve().then(() => (init_taskSummary(), taskSummary_exports));
670041
+ subscribeEngineRuntimeStatus2(() => {
670042
+ const st2 = getEngineRuntimeStatus2();
670043
+ if (st2.phase === "failed") {
670044
+ reportBgEngineDown2(st2.detail ?? "automatic engine restart failed");
670045
+ }
670046
+ });
670047
+ } catch {
670048
+ }
669774
670049
  process.argv = [process.argv[0], process.argv[1], ...config5.argv ?? []];
669775
670050
  const { launchReplProduction: launchReplProduction2 } = await Promise.resolve().then(() => (init_replEntry(), replEntry_exports));
669776
670051
  await launchReplProduction2();
@@ -669788,8 +670063,8 @@ __export(main_exports2, {
669788
670063
  import { spawn as spawn16 } from "child_process";
669789
670064
  import { createWriteStream as createWriteStream5 } from "fs";
669790
670065
  import { chmod as chmod13, mkdir as mkdir50, readFile as readFile58, readdir as readdir33, rename as rename15, stat as stat54, unlink as unlink28 } from "fs/promises";
669791
- import { createConnection as createConnection4, createServer as createServer8 } from "net";
669792
- import { join as join201 } from "path";
670066
+ import { createConnection as createConnection4, createServer as createServer9 } from "net";
670067
+ import { dirname as dirname88, join as join201 } from "path";
669793
670068
  function probeSocketAlive(sockPath, timeoutMs = 1500) {
669794
670069
  return (async () => {
669795
670070
  const info = await readDaemonInfo();
@@ -669829,6 +670104,10 @@ function parseOrigin(args) {
669829
670104
  return v2 === "service" ? "service" : "transient";
669830
670105
  }
669831
670106
  async function daemonMain(args) {
670107
+ const cdIdx = args.indexOf("--config-dir");
670108
+ if (cdIdx >= 0 && args[cdIdx + 1]) {
670109
+ process.env.SEMA_CONFIG_DIR = args[cdIdx + 1];
670110
+ }
669832
670111
  const sub = args[0];
669833
670112
  switch (sub) {
669834
670113
  case "run": {
@@ -669893,6 +670172,8 @@ async function daemonMain(args) {
669893
670172
  const isHelp = sub === void 0 || sub === "--help" || sub === "-h";
669894
670173
  const usage = `Usage: sema daemon <run|status|stop>
669895
670174
  run [--origin transient|service] start the background supervisor
670175
+ [--config-dir <path>] explicit config home (win32 WMI spawn leg \u2014
670176
+ the WMI child doesn't inherit the caller's env)
669896
670177
  status show supervisor + workers
669897
670178
  stop stop the supervisor (workers keep running)
669898
670179
  `;
@@ -669976,8 +670257,11 @@ var init_main4 = __esm({
669976
670257
  }
669977
670258
  this.log = createWriteStream5(logPath, { flags: "a", mode: 384 });
669978
670259
  const sockPath = getDaemonSocketPath();
670260
+ if (process.platform !== "win32") {
670261
+ await mkdir50(dirname88(sockPath), { recursive: true, mode: 448 });
670262
+ }
669979
670263
  const listen = () => new Promise((resolve53, reject2) => {
669980
- const s = createServer8((conn) => this.handleConnection(conn));
670264
+ const s = createServer9((conn) => this.handleConnection(conn));
669981
670265
  s.once("error", reject2);
669982
670266
  s.listen(sockPath, () => {
669983
670267
  this.server = s;
@@ -670704,10 +670988,16 @@ function cleanName(s) {
670704
670988
  return t2 || void 0;
670705
670989
  }
670706
670990
  async function loadJobs(cwdFilter) {
670991
+ const daemonInfo = await readDaemonInfo();
670992
+ const daemonUp = daemonInfo !== null && isDaemonAlive(daemonInfo);
670707
670993
  const out6 = [];
670708
670994
  for (const short of await listJobShorts()) {
670709
- const state3 = await readJobState(short);
670995
+ let state3 = await readJobState(short);
670710
670996
  if (!state3) continue;
670997
+ if (!isTerminalJobState(state3.state) && Number.isFinite(state3.pid) && !isJobWorkerAlive(state3) && !(state3.state === "crashed" && daemonUp)) {
670998
+ const reaped = await markJobTerminal(short, "failed", "interrupted", { reaped: true });
670999
+ if (reaped) state3 = reaped;
671000
+ }
670711
671001
  if (!underCwd(cwdFilter, state3.cwd)) continue;
670712
671002
  out6.push({ short, state: state3 });
670713
671003
  }
@@ -670799,7 +671089,7 @@ __export(agentsView_exports, {
670799
671089
  agentsHandler: () => agentsHandler2
670800
671090
  });
670801
671091
  import { rm as rmrf2 } from "fs/promises";
670802
- import { spawnSync as spawnSync11 } from "child_process";
671092
+ import { spawnSync as spawnSync12 } from "child_process";
670803
671093
  async function stopJobFromView(short) {
670804
671094
  const { stopDaemonWorker: stopDaemonWorker2 } = await Promise.resolve().then(() => (init_respawn(), respawn_exports));
670805
671095
  const { confirmed, error: error52 } = await stopDaemonWorker2(short);
@@ -670822,14 +671112,14 @@ async function deleteJobFromView(short) {
670822
671112
  let keptWorktree;
670823
671113
  let keptReason;
670824
671114
  if (st2?.worktreePath) {
670825
- const dirty2 = spawnSync11("git", ["-C", st2.worktreePath, "status", "--porcelain"], {
671115
+ const dirty2 = spawnSync12("git", ["-C", st2.worktreePath, "status", "--porcelain"], {
670826
671116
  encoding: "utf8"
670827
671117
  });
670828
671118
  if (dirty2.status === 0 && (dirty2.stdout ?? "").trim().length > 0) {
670829
671119
  keptWorktree = st2.worktreePath;
670830
671120
  keptReason = "dirty";
670831
671121
  } else if (dirty2.status === 0) {
670832
- const removed = spawnSync11(
671122
+ const removed = spawnSync12(
670833
671123
  "git",
670834
671124
  ["-C", st2.cwd, "worktree", "remove", "--force", st2.worktreePath],
670835
671125
  { stdio: "ignore" }
@@ -671824,7 +672114,27 @@ async function launchReplProduction() {
671824
672114
  })();
671825
672115
  });
671826
672116
  };
671827
- const r = await initEngineLifecycle2();
672117
+ let r = await initEngineLifecycle2();
672118
+ if (!r.baseUrl && process.env.SEMA_CODE_SESSION_KIND === "bg" && process.env.SEMA_JOB_DIR) {
672119
+ const bgInitBackoffMs = [2e3, 5e3, 1e4, 2e4, 4e4];
672120
+ for (let i = 0; i < bgInitBackoffMs.length && !r.baseUrl; i++) {
672121
+ console.error(
672122
+ `[sema] bg worker: engine unavailable (${r.reason ?? "unknown"}) \u2014 retrying start ${i + 1}/${bgInitBackoffMs.length} in ${bgInitBackoffMs[i] / 1e3}s`
672123
+ );
672124
+ await new Promise((res) => setTimeout(res, bgInitBackoffMs[i]));
672125
+ r = await initEngineLifecycle2();
672126
+ }
672127
+ if (!r.baseUrl) {
672128
+ try {
672129
+ const { describeEngineInitFailure: describeEngineInitFailure2, getLastEngineInitFailure: getLastEngineInitFailure2 } = await Promise.resolve().then(() => (init_engineLifecycleManager(), engineLifecycleManager_exports));
672130
+ const { reportBgEngineDown: reportBgEngineDown2 } = await Promise.resolve().then(() => (init_taskSummary(), taskSummary_exports));
672131
+ reportBgEngineDown2(
672132
+ `engine unavailable \u2014 ${describeEngineInitFailure2(getLastEngineInitFailure2())}`
672133
+ );
672134
+ } catch {
672135
+ }
672136
+ }
672137
+ }
671828
672138
  if (r.baseUrl) {
671829
672139
  process.env.SEMA_LIVE_BASEURL = r.baseUrl;
671830
672140
  const tok = getServiceAuthToken2();