@sema-agent/cli 1.0.6 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -26,6 +26,19 @@ max_tokens truncation error.
26
26
  - `sema -p "…"` — non-interactive print mode for scripts and pipes
27
27
  - `sema update` — self-update from the npm registry
28
28
 
29
+ ## Migrating from `@sema-ai/cli`
30
+
31
+ The old `@sema-ai/cli` scope is deprecated — this package replaces it. Both packages install
32
+ the same `sema` binary, so with both installed, which one runs depends on your PATH order.
33
+ Uninstall the old package first; that is the only clean fix:
34
+
35
+ ```sh
36
+ npm uninstall -g @sema-ai/cli
37
+ npm install -g @sema-agent/cli
38
+ ```
39
+
40
+ Your config and sessions live in `~/.sema` and are untouched by the switch.
41
+
29
42
  ## License
30
43
 
31
44
  [BUSL-1.1](./LICENSE) — free for personal, educational, research, and other non-commercial use;
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@sema-agent/cli",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@sema-agent/cli",
9
- "version": "1.0.6",
9
+ "version": "1.0.7",
10
10
  "license": "BUSL-1.1",
11
11
  "dependencies": {
12
12
  "@sema-agent/sdk": "0.0.50",
13
- "@sema-agent/server": "1.207.0"
13
+ "@sema-agent/server": "1.209.0"
14
14
  },
15
15
  "bin": {
16
16
  "sema": "sema.js"
@@ -629,9 +629,9 @@
629
629
  }
630
630
  },
631
631
  "node_modules/@sema-agent/core": {
632
- "version": "1.296.1",
633
- "resolved": "https://registry.npmjs.org/@sema-agent/core/-/core-1.296.1.tgz",
634
- "integrity": "sha512-ZdVBb8ISoqGnc5cPD/eNWBnSXJ19YGcVOU/PIf2T63FRzmjv+KP5JLJ+8v2IR8nbwpi5bogmGb50WwM2bmUnjQ==",
632
+ "version": "1.298.0",
633
+ "resolved": "https://registry.npmjs.org/@sema-agent/core/-/core-1.298.0.tgz",
634
+ "integrity": "sha512-OlmEHWz7Vg2E9l6xLvcD4evBZwYCC5zDgpO7SugRMq5vgWU+VDbMIWqMUXgZgHQc+1+QVAAcgfVOGADx7KjqGQ==",
635
635
  "license": "BUSL-1.1",
636
636
  "dependencies": {
637
637
  "@modelcontextprotocol/sdk": "1.29.0",
@@ -645,9 +645,9 @@
645
645
  }
646
646
  },
647
647
  "node_modules/@sema-agent/registry-core": {
648
- "version": "0.10.11",
649
- "resolved": "https://registry.npmjs.org/@sema-agent/registry-core/-/registry-core-0.10.11.tgz",
650
- "integrity": "sha512-PO/4OihhSEh9Ury0J3cDJiZ2ol/XEMKzF8K+4qhrenQ/FNFvlC432rNmrIv4t1k1xXcff+1bjttCUhopxIx2yg==",
648
+ "version": "0.10.12",
649
+ "resolved": "https://registry.npmjs.org/@sema-agent/registry-core/-/registry-core-0.10.12.tgz",
650
+ "integrity": "sha512-1ES+7mE64gx2cV1b7a3yGd1MeR59FSbP+y1pHR+LSpB+Ua1S3lGIQSE03GnBnfK1f6c0x3KaWgcLo7tZl3GEnQ==",
651
651
  "license": "BUSL-1.1",
652
652
  "dependencies": {
653
653
  "zod": "^3.24.0"
@@ -678,13 +678,13 @@
678
678
  }
679
679
  },
680
680
  "node_modules/@sema-agent/server": {
681
- "version": "1.207.0",
682
- "resolved": "https://registry.npmjs.org/@sema-agent/server/-/server-1.207.0.tgz",
683
- "integrity": "sha512-bMn7tYCoAD4MAqMuqGWm8o4txi5ZpDG2VYeb71klhHzHNc/kQeQStY5dKZaG+jG7jRraJuRi8qBJ0AGjCwmRnA==",
681
+ "version": "1.209.0",
682
+ "resolved": "https://registry.npmjs.org/@sema-agent/server/-/server-1.209.0.tgz",
683
+ "integrity": "sha512-y2Uj+TYqwDLV3DELdvk7ZYxHmmrXx+sHKcN+6KWEOpWdmEW5E68yXiGzjpRJyBtTL1YOIvSu2b7SM/I5UpJtBA==",
684
684
  "license": "BUSL-1.1",
685
685
  "dependencies": {
686
- "@sema-agent/core": "^1.296.0",
687
- "@sema-agent/registry-core": "^0.10.11",
686
+ "@sema-agent/core": "^1.296.1",
687
+ "@sema-agent/registry-core": "^0.10.12",
688
688
  "e2b": "^2.28.0",
689
689
  "libsodium-wrappers": "^0.8.4",
690
690
  "mysql2": "^3.22.4",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/cli",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "Sema — your own Claude Code-grade coding agent, in the terminal.",
5
5
  "license": "BUSL-1.1",
6
6
  "bin": {
@@ -22,13 +22,13 @@
22
22
  ],
23
23
  "dependencies": {
24
24
  "@sema-agent/sdk": "0.0.50",
25
- "@sema-agent/server": "1.207.0"
25
+ "@sema-agent/server": "1.209.0"
26
26
  },
27
27
  "overrides": {
28
- "@sema-agent/core": "1.296.1",
29
- "@sema-agent/registry-core": "0.10.11"
28
+ "@sema-agent/core": "1.298.0",
29
+ "@sema-agent/registry-core": "0.10.12"
30
30
  },
31
- "semaEngineVersion": "server 1.207.0 / core 1.296.1 / registry-core 0.10.11",
31
+ "semaEngineVersion": "server 1.209.0 / core 1.298.0 / registry-core 0.10.12",
32
32
  "engines": {
33
33
  "node": ">=18"
34
34
  }
package/sema.js CHANGED
@@ -114152,7 +114152,7 @@ var require_diagnostics = __commonJS({
114152
114152
  proxyConnected: diagnosticsChannel.channel("undici:proxy:connected")
114153
114153
  };
114154
114154
  var isTrackingClientEvents = false;
114155
- function trackClientEvents(debugLog = undiciDebugLog) {
114155
+ function trackClientEvents(debugLog2 = undiciDebugLog) {
114156
114156
  if (isTrackingClientEvents) {
114157
114157
  return;
114158
114158
  }
@@ -114167,7 +114167,7 @@ var require_diagnostics = __commonJS({
114167
114167
  const {
114168
114168
  connectParams: { version: version5, protocol, port, host }
114169
114169
  } = evt;
114170
- debugLog(
114170
+ debugLog2(
114171
114171
  "connecting to %s%s using %s%s",
114172
114172
  host,
114173
114173
  port ? `:${port}` : "",
@@ -114182,7 +114182,7 @@ var require_diagnostics = __commonJS({
114182
114182
  const {
114183
114183
  connectParams: { version: version5, protocol, port, host }
114184
114184
  } = evt;
114185
- debugLog(
114185
+ debugLog2(
114186
114186
  "connected to %s%s using %s%s",
114187
114187
  host,
114188
114188
  port ? `:${port}` : "",
@@ -114198,7 +114198,7 @@ var require_diagnostics = __commonJS({
114198
114198
  connectParams: { version: version5, protocol, port, host },
114199
114199
  error: error52
114200
114200
  } = evt;
114201
- debugLog(
114201
+ debugLog2(
114202
114202
  "connection to %s%s using %s%s errored - %s",
114203
114203
  host,
114204
114204
  port ? `:${port}` : "",
@@ -114214,12 +114214,12 @@ var require_diagnostics = __commonJS({
114214
114214
  const {
114215
114215
  request: { method, path: path27, origin: origin2 }
114216
114216
  } = evt;
114217
- debugLog("sending request to %s %s%s", method, origin2, path27);
114217
+ debugLog2("sending request to %s %s%s", method, origin2, path27);
114218
114218
  }
114219
114219
  );
114220
114220
  }
114221
114221
  var isTrackingRequestEvents = false;
114222
- function trackRequestEvents(debugLog = undiciDebugLog) {
114222
+ function trackRequestEvents(debugLog2 = undiciDebugLog) {
114223
114223
  if (isTrackingRequestEvents) {
114224
114224
  return;
114225
114225
  }
@@ -114235,7 +114235,7 @@ var require_diagnostics = __commonJS({
114235
114235
  request: { method, path: path27, origin: origin2 },
114236
114236
  response: { statusCode }
114237
114237
  } = evt;
114238
- debugLog(
114238
+ debugLog2(
114239
114239
  "received response to %s %s%s - HTTP %d",
114240
114240
  method,
114241
114241
  origin2,
@@ -114250,7 +114250,7 @@ var require_diagnostics = __commonJS({
114250
114250
  const {
114251
114251
  request: { method, path: path27, origin: origin2 }
114252
114252
  } = evt;
114253
- debugLog("trailers received from %s %s%s", method, origin2, path27);
114253
+ debugLog2("trailers received from %s %s%s", method, origin2, path27);
114254
114254
  }
114255
114255
  );
114256
114256
  diagnosticsChannel.subscribe(
@@ -114260,7 +114260,7 @@ var require_diagnostics = __commonJS({
114260
114260
  request: { method, path: path27, origin: origin2 },
114261
114261
  error: error52
114262
114262
  } = evt;
114263
- debugLog(
114263
+ debugLog2(
114264
114264
  "request to %s %s%s errored - %s",
114265
114265
  method,
114266
114266
  origin2,
@@ -114271,7 +114271,7 @@ var require_diagnostics = __commonJS({
114271
114271
  );
114272
114272
  }
114273
114273
  var isTrackingWebSocketEvents = false;
114274
- function trackWebSocketEvents(debugLog = websocketDebuglog) {
114274
+ function trackWebSocketEvents(debugLog2 = websocketDebuglog) {
114275
114275
  if (isTrackingWebSocketEvents) {
114276
114276
  return;
114277
114277
  }
@@ -114285,9 +114285,9 @@ var require_diagnostics = __commonJS({
114285
114285
  (evt) => {
114286
114286
  if (evt.address != null) {
114287
114287
  const { address, port } = evt.address;
114288
- debugLog("connection opened %s%s", address, port ? `:${port}` : "");
114288
+ debugLog2("connection opened %s%s", address, port ? `:${port}` : "");
114289
114289
  } else {
114290
- debugLog("connection opened");
114290
+ debugLog2("connection opened");
114291
114291
  }
114292
114292
  }
114293
114293
  );
@@ -114295,7 +114295,7 @@ var require_diagnostics = __commonJS({
114295
114295
  "undici:websocket:close",
114296
114296
  (evt) => {
114297
114297
  const { websocket, code: code2, reason } = evt;
114298
- debugLog(
114298
+ debugLog2(
114299
114299
  "closed connection to %s - %s %s",
114300
114300
  websocket.url,
114301
114301
  code2,
@@ -114306,19 +114306,19 @@ var require_diagnostics = __commonJS({
114306
114306
  diagnosticsChannel.subscribe(
114307
114307
  "undici:websocket:socket_error",
114308
114308
  (err8) => {
114309
- debugLog("connection errored - %s", err8.message);
114309
+ debugLog2("connection errored - %s", err8.message);
114310
114310
  }
114311
114311
  );
114312
114312
  diagnosticsChannel.subscribe(
114313
114313
  "undici:websocket:ping",
114314
114314
  (evt) => {
114315
- debugLog("ping received");
114315
+ debugLog2("ping received");
114316
114316
  }
114317
114317
  );
114318
114318
  diagnosticsChannel.subscribe(
114319
114319
  "undici:websocket:pong",
114320
114320
  (evt) => {
114321
- debugLog("pong received");
114321
+ debugLog2("pong received");
114322
114322
  }
114323
114323
  );
114324
114324
  }
@@ -157421,6 +157421,7 @@ __export(engineTarget_exports, {
157421
157421
  engineRoutingRefusalActive: () => engineRoutingRefusalActive,
157422
157422
  evaluateEngineRouting: () => evaluateEngineRouting,
157423
157423
  execAxisReading: () => execAxisReading,
157424
+ isEngineTransportError: () => isEngineTransportError,
157424
157425
  isLoopbackEngineUrl: () => isLoopbackEngineUrl,
157425
157426
  isTrustedEngineHost: () => isTrustedEngineHost,
157426
157427
  normalizeEngineUrl: () => normalizeEngineUrl,
@@ -157576,9 +157577,19 @@ function enginePinUnreachableHint(pin) {
157576
157577
  const settingsPath = join34(getClaudeConfigHomeDir(), "settings.json");
157577
157578
  const where = pin.source === "settings" ? `${ENGINE_URL_ENV} in ${settingsPath} (env block)` : `the ${ENGINE_URL_ENV} environment variable`;
157578
157579
  const removal = pin.source === "settings" ? `remove the "${ENGINE_URL_ENV}" key from ${settingsPath} (or run \`sema cloud engine disconnect\`)` : `unset it in your shell (e.g. \`unset ${ENGINE_URL_ENV}\`)`;
157579
- return `The engine target is pinned to ${pin.url} by ${where}, so sema did not start a local engine.
157580
- \xB7 Intentional remote engine? Start it at that address, then send your message again.
157581
- \xB7 Leftover from an older install? ${removal} \u2014 the next launch self-spawns a local engine.`;
157580
+ return `The engine at ${ENGINE_URL_ENV}=${pin.url} is unreachable \u2014 that pin comes from ${where}, so sema did not start a local engine.
157581
+ \xB7 Intentional remote engine? Check it is running and the port is right, then send your message again.
157582
+ \xB7 Leftover from an older install, or want the shell-managed engine back? ${removal} \u2014 the next launch self-spawns a local engine.
157583
+ \xB7 Not sure? Run \`sema doctor\` to see the engine status.`;
157584
+ }
157585
+ function isEngineTransportError(err8) {
157586
+ const e = err8;
157587
+ if (typeof e?.status === "number") return false;
157588
+ const cause = e?.cause;
157589
+ const detail = typeof cause?.message === "string" && cause.message.length > 0 && cause.message || typeof e?.message === "string" && e.message.length > 0 && e.message || String(err8);
157590
+ return e?.cause !== void 0 || /fetch failed|ECONNREFUSED|ECONNRESET|ETIMEDOUT|EAI_AGAIN|ENOTFOUND|EHOSTUNREACH|ENETUNREACH|EPIPE|socket hang up|UND_ERR|terminated|other side closed/i.test(
157591
+ detail
157592
+ );
157582
157593
  }
157583
157594
  function noteEnginePinUnreachable(pin) {
157584
157595
  enginePinUnreachable = pin;
@@ -449263,7 +449274,7 @@ function Settings({
449263
449274
  var import_react113, import_jsx_runtime191;
449264
449275
  var init_cmd_config = __esm({
449265
449276
  "build-src/src/sema/overrides/cmd-config.tsx"() {
449266
- import_react113 = __toESM(require_react());
449277
+ import_react113 = __toESM(require_react(), 1);
449267
449278
  init_useKeybinding();
449268
449279
  init_useExitOnCtrlCDWithKeybindings();
449269
449280
  init_useTerminalSize();
@@ -449274,7 +449285,7 @@ var init_cmd_config = __esm({
449274
449285
  init_Config();
449275
449286
  init_settings_usage();
449276
449287
  init_Stats();
449277
- import_jsx_runtime191 = __toESM(require_jsx_runtime());
449288
+ import_jsx_runtime191 = __toESM(require_jsx_runtime(), 1);
449278
449289
  }
449279
449290
  });
449280
449291
 
@@ -454558,7 +454569,9 @@ var init_init_verifiers = __esm({
454558
454569
  return [
454559
454570
  {
454560
454571
  type: "text",
454561
- text: `Use the TodoWrite tool to track your progress through this multi-step task.
454572
+ // CC209 对表(2026-07-16):交互 roster 的追踪工具是 TaskCreate/TaskUpdate(TodoV2 恒开;
454573
+ // 引擎 core 1.296+ 同款默认,TodoWrite 默认不装载)——别指名模型摸不到的工具。
454574
+ text: `Use the task tracking tools (TaskCreate/TaskUpdate) to track your progress through this multi-step task.
454562
454575
 
454563
454576
  ## Goal
454564
454577
 
@@ -478122,8 +478135,8 @@ var init_sema_brand = __esm({
478122
478135
  "Slash-command gating wired to the fleet capability handshake"
478123
478136
  ]
478124
478137
  },
478125
- productVersion: "1.0.6",
478126
- announcement: "sema 1.0.6 \u2014 custom subagents in .sema/agents/ now run on your chosen model end-to-end, -p exits honestly instead of silently succeeding when a question parks the run, onboarding gets big step titles, and the code scenario (full engineering persona) is the new default"
478138
+ productVersion: "1.0.7",
478139
+ announcement: "sema 1.0.7 \u2014 headless -p now reconnects through stream blips instead of dying (bounded retry + result recovery), a dead SEMA_ENGINE_URL gets a clear three-step diagnosis in both REPL and -p, and one corrupt config.d file no longer silently drops your whole model catalog"
478127
478140
  };
478128
478141
  }
478129
478142
  });
@@ -481062,8 +481075,8 @@ var require_sema_brand = __commonJS({
481062
481075
  "Slash-command gating wired to the fleet capability handshake"
481063
481076
  ]
481064
481077
  },
481065
- productVersion: "1.0.6",
481066
- announcement: "sema 1.0.6 \u2014 custom subagents in .sema/agents/ now run on your chosen model end-to-end, -p exits honestly instead of silently succeeding when a question parks the run, onboarding gets big step titles, and the code scenario (full engineering persona) is the new default"
481078
+ productVersion: "1.0.7",
481079
+ announcement: "sema 1.0.7 \u2014 headless -p now reconnects through stream blips instead of dying (bounded retry + result recovery), a dead SEMA_ENGINE_URL gets a clear three-step diagnosis in both REPL and -p, and one corrupt config.d file no longer silently drops your whole model catalog"
481067
481080
  };
481068
481081
  }
481069
481082
  });
@@ -620491,8 +620504,8 @@ function _temp161() {
620491
620504
  var import_compiler_runtime316, import_react313, SETTINGS_ERRORS_NOTIFICATION_KEY;
620492
620505
  var init_useSettingsErrors = __esm({
620493
620506
  "build-src/src/hooks/notifs/useSettingsErrors.tsx"() {
620494
- import_compiler_runtime316 = __toESM(require_compiler_runtime());
620495
- import_react313 = __toESM(require_react());
620507
+ import_compiler_runtime316 = __toESM(require_compiler_runtime(), 1);
620508
+ import_react313 = __toESM(require_react(), 1);
620496
620509
  init_notifications();
620497
620510
  init_state();
620498
620511
  init_allErrors();
@@ -640696,6 +640709,357 @@ var init_agentsWire = __esm({
640696
640709
  }
640697
640710
  });
640698
640711
 
640712
+ // build-src/src/sema/limitsWire.ts
640713
+ var limitsWire_exports = {};
640714
+ __export(limitsWire_exports, {
640715
+ DEADLINE_SEC_MAX: () => DEADLINE_SEC_MAX,
640716
+ DEADLINE_SEC_MIN: () => DEADLINE_SEC_MIN,
640717
+ HEADLESS_DEADLINE_ENV: () => HEADLESS_DEADLINE_ENV,
640718
+ HEADLESS_MAX_TURNS_ENV: () => HEADLESS_MAX_TURNS_ENV,
640719
+ LIMITS_WIRE_MIN_ENGINE: () => LIMITS_WIRE_MIN_ENGINE,
640720
+ MAX_TURNS_MAX: () => MAX_TURNS_MAX,
640721
+ MAX_TURNS_MIN: () => MAX_TURNS_MIN,
640722
+ engineLimitsSupportWarning: () => engineLimitsSupportWarning,
640723
+ headlessLimitsFromEnv: () => headlessLimitsFromEnv,
640724
+ limitsForPrint: () => limitsForPrint,
640725
+ parseLimitsArgv: () => parseLimitsArgv,
640726
+ versionSupportsLimits: () => versionSupportsLimits
640727
+ });
640728
+ function lastFlagValue(argv, name) {
640729
+ const eq2 = `${name}=`;
640730
+ let present = false;
640731
+ let raw2;
640732
+ let valueMissing = false;
640733
+ for (let i = 0; i < argv.length; i++) {
640734
+ const a = argv[i];
640735
+ if (a === "--") break;
640736
+ if (a === name) {
640737
+ present = true;
640738
+ const nxt = argv[i + 1];
640739
+ if (nxt === void 0 || nxt.startsWith("-")) {
640740
+ valueMissing = true;
640741
+ raw2 = void 0;
640742
+ continue;
640743
+ }
640744
+ valueMissing = false;
640745
+ raw2 = nxt;
640746
+ i++;
640747
+ } else if (a.startsWith(eq2)) {
640748
+ present = true;
640749
+ valueMissing = false;
640750
+ raw2 = a.slice(eq2.length);
640751
+ }
640752
+ }
640753
+ if (present && (valueMissing || raw2 === void 0)) return { present: true };
640754
+ return present ? { present: true, raw: raw2 } : { present: false };
640755
+ }
640756
+ function parseIntInDomain(raw2, min, max2) {
640757
+ const v2 = raw2.trim();
640758
+ if (!INT_RE.test(v2)) return null;
640759
+ const n2 = Number(v2);
640760
+ if (!Number.isSafeInteger(n2) || n2 < min || n2 > max2) return null;
640761
+ return n2;
640762
+ }
640763
+ function parseLimitsArgv(argv) {
640764
+ const limits = {};
640765
+ const flaggedFlags = [];
640766
+ const dl = lastFlagValue(argv, "--deadline");
640767
+ if (dl.present) {
640768
+ const n2 = dl.raw !== void 0 ? parseIntInDomain(dl.raw, DEADLINE_SEC_MIN, DEADLINE_SEC_MAX) : null;
640769
+ if (n2 === null) return { ok: false, error: DEADLINE_USAGE };
640770
+ limits.timeoutSec = n2;
640771
+ flaggedFlags.push("--deadline");
640772
+ }
640773
+ const mt2 = lastFlagValue(argv, "--max-turns");
640774
+ if (mt2.present) {
640775
+ const n2 = mt2.raw !== void 0 ? parseIntInDomain(mt2.raw, MAX_TURNS_MIN, MAX_TURNS_MAX) : null;
640776
+ if (n2 === null) return { ok: false, error: MAX_TURNS_USAGE };
640777
+ limits.maxTurns = n2;
640778
+ flaggedFlags.push("--max-turns");
640779
+ }
640780
+ return {
640781
+ ok: true,
640782
+ ...flaggedFlags.length > 0 ? { limits } : {},
640783
+ flaggedFlags
640784
+ };
640785
+ }
640786
+ function headlessLimitsFromEnv(env5 = process.env) {
640787
+ const out6 = {};
640788
+ const dl = env5[HEADLESS_DEADLINE_ENV]?.trim();
640789
+ if (dl) {
640790
+ const n2 = parseIntInDomain(dl, DEADLINE_SEC_MIN, DEADLINE_SEC_MAX);
640791
+ if (n2 !== null) out6.timeoutSec = n2;
640792
+ else if (env5.SEMA_DEBUG) {
640793
+ console.error(`[sema] ${HEADLESS_DEADLINE_ENV}="${dl}" is not an integer in ${DEADLINE_SEC_MIN}..${DEADLINE_SEC_MAX} \u2014 ignoring the settings default`);
640794
+ }
640795
+ }
640796
+ const mt2 = env5[HEADLESS_MAX_TURNS_ENV]?.trim();
640797
+ if (mt2) {
640798
+ const n2 = parseIntInDomain(mt2, MAX_TURNS_MIN, MAX_TURNS_MAX);
640799
+ if (n2 !== null) out6.maxTurns = n2;
640800
+ else if (env5.SEMA_DEBUG) {
640801
+ console.error(`[sema] ${HEADLESS_MAX_TURNS_ENV}="${mt2}" is not an integer in ${MAX_TURNS_MIN}..${MAX_TURNS_MAX} \u2014 ignoring the settings default`);
640802
+ }
640803
+ }
640804
+ return out6.timeoutSec !== void 0 || out6.maxTurns !== void 0 ? out6 : void 0;
640805
+ }
640806
+ function limitsForPrint(argv, env5 = process.env) {
640807
+ const parsed = parseLimitsArgv(argv);
640808
+ if (!parsed.ok) return parsed;
640809
+ const fromEnv = headlessLimitsFromEnv(env5);
640810
+ const merged = { ...fromEnv ?? {}, ...parsed.limits ?? {} };
640811
+ const any3 = merged.timeoutSec !== void 0 || merged.maxTurns !== void 0;
640812
+ return { ok: true, ...any3 ? { limits: merged } : {}, flaggedFlags: parsed.flaggedFlags };
640813
+ }
640814
+ function versionSupportsLimits(v2) {
640815
+ const m2 = v2 ? /^(\d+)\.(\d+)\.(\d+)/.exec(v2) : null;
640816
+ if (!m2) return false;
640817
+ const [a, b3, c2] = [Number(m2[1]), Number(m2[2]), Number(m2[3])];
640818
+ const [ma, mb, mc] = LIMITS_WIRE_MIN_ENGINE;
640819
+ if (a !== ma) return a > ma;
640820
+ if (b3 !== mb) return b3 > mb;
640821
+ return c2 >= mc;
640822
+ }
640823
+ async function engineLimitsSupportWarning(baseUrl, flaggedFlags, opts) {
640824
+ const fetchImpl = opts?.fetchImpl ?? fetch;
640825
+ const controller = new AbortController();
640826
+ const timer2 = setTimeout(() => controller.abort(), opts?.timeoutMs ?? 1500);
640827
+ try {
640828
+ const res = await fetchImpl(`${baseUrl.replace(/\/+$/, "")}/health`, {
640829
+ method: "GET",
640830
+ signal: controller.signal
640831
+ });
640832
+ if (!res.ok) return void 0;
640833
+ const body = await res.json();
640834
+ const version5 = typeof body?.version === "string" ? body.version : void 0;
640835
+ if (versionSupportsLimits(version5)) return void 0;
640836
+ const flags = flaggedFlags.length > 0 ? flaggedFlags.join("/") : "--deadline/--max-turns";
640837
+ return `[sema] engine ${version5 ?? "(unversioned, pre-1.96)"} does not support ${flags} (needs \u22651.196.0); the flag will be ignored by the engine`;
640838
+ } catch {
640839
+ return void 0;
640840
+ } finally {
640841
+ clearTimeout(timer2);
640842
+ }
640843
+ }
640844
+ var HEADLESS_DEADLINE_ENV, HEADLESS_MAX_TURNS_ENV, DEADLINE_SEC_MIN, DEADLINE_SEC_MAX, MAX_TURNS_MIN, MAX_TURNS_MAX, LIMITS_WIRE_MIN_ENGINE, DEADLINE_USAGE, MAX_TURNS_USAGE, INT_RE;
640845
+ var init_limitsWire = __esm({
640846
+ "build-src/src/sema/limitsWire.ts"() {
640847
+ HEADLESS_DEADLINE_ENV = "SEMA_HEADLESS_DEADLINE_SEC";
640848
+ HEADLESS_MAX_TURNS_ENV = "SEMA_HEADLESS_MAX_TURNS";
640849
+ DEADLINE_SEC_MIN = 30;
640850
+ DEADLINE_SEC_MAX = 86400;
640851
+ MAX_TURNS_MIN = 1;
640852
+ MAX_TURNS_MAX = 1e3;
640853
+ LIMITS_WIRE_MIN_ENGINE = [1, 196, 0];
640854
+ DEADLINE_USAGE = `sema: --deadline expects a whole number of seconds between ${DEADLINE_SEC_MIN} and ${DEADLINE_SEC_MAX}.
640855
+ --deadline <sec> soft wall-clock budget for this run (sema superset \u2014 no upstream equivalent):
640856
+ the engine paces itself (nudges + call caps) and finalizes gracefully near the deadline
640857
+ (no flag) no deadline \u2014 today's behaviour`;
640858
+ MAX_TURNS_USAGE = `sema: --max-turns expects a whole number of turns between ${MAX_TURNS_MIN} and ${MAX_TURNS_MAX}.
640859
+ --max-turns <n> maximum number of agentic turns for this run (upstream-aligned flag,
640860
+ enforced engine-side on the sema seam)
640861
+ (no flag) no turn cap \u2014 today's behaviour`;
640862
+ INT_RE = /^\d+$/;
640863
+ }
640864
+ });
640865
+
640866
+ // build-src/src/sema/detachWire.ts
640867
+ var detachWire_exports = {};
640868
+ __export(detachWire_exports, {
640869
+ DETACH_DURABLE_OFF_400_ANCHOR: () => DETACH_DURABLE_OFF_400_ANCHOR,
640870
+ DETACH_HEADER: () => DETACH_HEADER,
640871
+ DETACH_WIRE_MIN_ENGINE: () => DETACH_WIRE_MIN_ENGINE,
640872
+ HEADLESS_DETACH_ENV: () => HEADLESS_DETACH_ENV,
640873
+ _resetDetachWireForTest: () => _resetDetachWireForTest,
640874
+ armDetachCancel: () => armDetachCancel,
640875
+ detachDurableOffHint: () => detachDurableOffHint,
640876
+ detachedTaskId: () => detachedTaskId,
640877
+ engineSupportsDetach: () => engineSupportsDetach,
640878
+ fireBestEffortDetachCancel: () => fireBestEffortDetachCancel,
640879
+ headlessDetachDisabledByEnv: () => headlessDetachDisabledByEnv,
640880
+ isDetachArmed: () => isDetachArmed,
640881
+ resolveHeadlessDetach: () => resolveHeadlessDetach,
640882
+ versionSupportsDetach: () => versionSupportsDetach
640883
+ });
640884
+ function headlessDetachDisabledByEnv(env5 = process.env) {
640885
+ const v2 = env5[HEADLESS_DETACH_ENV]?.trim().toLowerCase();
640886
+ return v2 === "false" || v2 === "0";
640887
+ }
640888
+ async function engineSupportsDetach(baseUrl, opts) {
640889
+ const fetchImpl = opts?.fetchImpl ?? fetch;
640890
+ const controller = new AbortController();
640891
+ const timer2 = setTimeout(() => controller.abort(), opts?.timeoutMs ?? 1500);
640892
+ try {
640893
+ const res = await fetchImpl(`${baseUrl.replace(/\/+$/, "")}/health`, {
640894
+ method: "GET",
640895
+ signal: controller.signal
640896
+ });
640897
+ if (!res.ok) return true;
640898
+ const body = await res.json();
640899
+ const version5 = typeof body?.version === "string" ? body.version : void 0;
640900
+ return versionSupportsDetach(version5);
640901
+ } catch {
640902
+ return true;
640903
+ } finally {
640904
+ clearTimeout(timer2);
640905
+ }
640906
+ }
640907
+ async function resolveHeadlessDetach(baseUrl, env5 = process.env, opts) {
640908
+ if (headlessDetachDisabledByEnv(env5)) return { on: false, reason: "env-off" };
640909
+ if (env5.SEMA_ENGINE_URL) {
640910
+ const ok2 = await engineSupportsDetach(baseUrl, opts);
640911
+ if (!ok2) return { on: false, reason: "old-engine" };
640912
+ }
640913
+ return { on: true, reason: "default-on" };
640914
+ }
640915
+ function detachDurableOffHint(err8) {
640916
+ if (!isDetachArmed()) return null;
640917
+ const e = err8;
640918
+ if (e?.status !== 400) return null;
640919
+ const msg = typeof e?.message === "string" ? e.message : "";
640920
+ if (!msg.includes(DETACH_DURABLE_OFF_400_ANCHOR)) return null;
640921
+ return "engine has durable runs disabled \u2014 detach-on-disconnect unavailable; interrupted turns will abort (SEMA_HEADLESS_DETACH=false to silence)";
640922
+ }
640923
+ function armDetachCancel(arm) {
640924
+ cancelArm = arm;
640925
+ }
640926
+ function isDetachArmed() {
640927
+ return cancelArm !== null;
640928
+ }
640929
+ function detachedTaskId() {
640930
+ return cancelArm?.getTaskId() ?? null;
640931
+ }
640932
+ function _resetDetachWireForTest() {
640933
+ cancelArm = null;
640934
+ }
640935
+ function fireBestEffortDetachCancel(fetchImpl = fetch) {
640936
+ const arm = cancelArm;
640937
+ if (!arm) return false;
640938
+ const taskId = arm.getTaskId();
640939
+ if (!taskId) return false;
640940
+ try {
640941
+ const controller = new AbortController();
640942
+ const timer2 = setTimeout(() => controller.abort(), 1500);
640943
+ timer2.unref?.();
640944
+ void fetchImpl(`${arm.baseUrl.replace(/\/+$/, "")}/v1/runs/${encodeURIComponent(taskId)}/cancel`, {
640945
+ method: "POST",
640946
+ headers: {
640947
+ authorization: `Bearer ${arm.authToken}`,
640948
+ "x-agent-principal": arm.principal
640949
+ },
640950
+ signal: controller.signal
640951
+ }).catch(() => {
640952
+ }).finally(() => clearTimeout(timer2));
640953
+ return true;
640954
+ } catch {
640955
+ return false;
640956
+ }
640957
+ }
640958
+ var DETACH_HEADER, HEADLESS_DETACH_ENV, DETACH_WIRE_MIN_ENGINE, versionSupportsDetach, DETACH_DURABLE_OFF_400_ANCHOR, cancelArm;
640959
+ var init_detachWire = __esm({
640960
+ "build-src/src/sema/detachWire.ts"() {
640961
+ init_limitsWire();
640962
+ DETACH_HEADER = "x-detach-on-disconnect";
640963
+ HEADLESS_DETACH_ENV = "SEMA_HEADLESS_DETACH";
640964
+ DETACH_WIRE_MIN_ENGINE = [1, 196, 0];
640965
+ versionSupportsDetach = versionSupportsLimits;
640966
+ DETACH_DURABLE_OFF_400_ANCHOR = "x-detach-on-disconnect requires a durable run";
640967
+ cancelArm = null;
640968
+ }
640969
+ });
640970
+
640971
+ // build-src/src/sema/headlessReconnectWire.ts
640972
+ function debugLog(msg) {
640973
+ if (process.env.SEMA_DEBUG) {
640974
+ console.error(`[sema] headless reconnect: ${msg}`);
640975
+ }
640976
+ }
640977
+ function terminalEventFromRunRow(row2) {
640978
+ if (!row2 || typeof row2.status !== "string") return null;
640979
+ if (row2.status === "completed" || row2.status === "failed") {
640980
+ if (row2.result && typeof row2.result === "object") {
640981
+ return { type: "done", result: row2.result };
640982
+ }
640983
+ if (row2.status === "failed") {
640984
+ return {
640985
+ type: "failed",
640986
+ ...row2.errorCode ? { errorCode: row2.errorCode } : {},
640987
+ errorMessage: row2.error ?? "run failed"
640988
+ };
640989
+ }
640990
+ }
640991
+ return null;
640992
+ }
640993
+ async function* withHeadlessR1Reconnect(live, deps2) {
640994
+ let originalTearErr;
640995
+ try {
640996
+ for await (const ev of live) {
640997
+ yield ev;
640998
+ const t2 = ev?.type;
640999
+ if (t2 === "done" || t2 === "failed") return;
641000
+ }
641001
+ return;
641002
+ } catch (e) {
641003
+ originalTearErr = e;
641004
+ }
641005
+ let attempts = 0;
641006
+ let lastSeenSeq;
641007
+ const probe3 = deps2.probeAlive ?? probeEngineAlive;
641008
+ for (; ; ) {
641009
+ if (deps2.signal?.aborted) throw originalTearErr;
641010
+ if (!isSseIdleError(originalTearErr)) throw originalTearErr;
641011
+ const taskId = deps2.getTaskId();
641012
+ if (!taskId) throw originalTearErr;
641013
+ if (attempts >= HEADLESS_RECONNECT_MAX) {
641014
+ debugLog(`budget exhausted (${attempts}/${HEADLESS_RECONNECT_MAX}) \u2014 falling to the honest death path`);
641015
+ throw originalTearErr;
641016
+ }
641017
+ attempts++;
641018
+ if (!await probe3(deps2.baseUrl)) throw originalTearErr;
641019
+ debugLog(`attempt ${attempts}/${HEADLESS_RECONNECT_MAX} \u2014 switching to runs.events(${taskId}${lastSeenSeq !== void 0 ? `, Last-Event-ID ${lastSeenSeq}` : ""})`);
641020
+ try {
641021
+ const cont = deps2.openEvents(taskId, lastSeenSeq !== void 0 ? String(lastSeenSeq) : void 0);
641022
+ for await (const ev of cont) {
641023
+ if (deps2.signal?.aborted) return;
641024
+ const rec = ev;
641025
+ const t2 = rec?.type;
641026
+ if (t2 === void 0) continue;
641027
+ if (t2 === "error") {
641028
+ debugLog(`runs.events lane frame type=error code=${String(rec?.code ?? "")} \u2014 SDK resumes with Last-Event-ID internally`);
641029
+ continue;
641030
+ }
641031
+ const seq = typeof rec?.id === "string" && /^\d+$/.test(rec.id) ? Number(rec.id) : void 0;
641032
+ if (seq !== void 0) {
641033
+ if (lastSeenSeq !== void 0 && seq <= lastSeenSeq) continue;
641034
+ lastSeenSeq = seq;
641035
+ }
641036
+ if (t2 === "done" || t2 === "failed") debugLog(`resumed to terminal (${String(t2)}) after ${attempts} reconnect(s)`);
641037
+ yield ev;
641038
+ if (t2 === "done" || t2 === "failed") return;
641039
+ }
641040
+ if (deps2.signal?.aborted) return;
641041
+ debugLog("runs.events continuation ended without a terminal frame");
641042
+ } catch (contErr) {
641043
+ debugLog(`runs.events continuation failed: ${contErr instanceof Error ? contErr.message : String(contErr)}`);
641044
+ if (deps2.signal?.aborted) throw originalTearErr;
641045
+ const row2 = await deps2.getRun(taskId).catch(() => null);
641046
+ const terminal = terminalEventFromRunRow(row2);
641047
+ if (terminal) {
641048
+ debugLog(`run row terminal (${String(row2?.status)}) \u2014 synthesizing the terminal frame (R1b)`);
641049
+ yield terminal;
641050
+ return;
641051
+ }
641052
+ }
641053
+ }
641054
+ }
641055
+ var HEADLESS_RECONNECT_MAX;
641056
+ var init_headlessReconnectWire = __esm({
641057
+ "build-src/src/sema/headlessReconnectWire.ts"() {
641058
+ init_sseIdleTriage();
641059
+ HEADLESS_RECONNECT_MAX = 2;
641060
+ }
641061
+ });
641062
+
640699
641063
  // build-src/src/sema/liveClient.ts
640700
641064
  var liveClient_exports = {};
640701
641065
  __export(liveClient_exports, {
@@ -640863,6 +641227,7 @@ function createLiveConversationClient(config5) {
640863
641227
  stream(req, opts) {
640864
641228
  const open20 = () => {
640865
641229
  let headerAcquired = false;
641230
+ let earlyTaskId = null;
640866
641231
  const heartbeatGraceMs = resolveSseHeartbeatGraceMs();
640867
641232
  const live = client4.tasks.stream(toLiveRequest(req, getLiveSessionId()), {
640868
641233
  ...opts,
@@ -640875,6 +641240,7 @@ function createLiveConversationClient(config5) {
640875
641240
  const early = res.headers?.get?.("x-task-id");
640876
641241
  if (typeof early === "string" && early.length > 0) {
640877
641242
  headerAcquired = true;
641243
+ earlyTaskId = early;
640878
641244
  bindTaskIdEarly(early);
640879
641245
  persistEngineTaskId(early);
640880
641246
  setActiveEngineTaskId(early);
@@ -640885,13 +641251,29 @@ function createLiveConversationClient(config5) {
640885
641251
  }
640886
641252
  }
640887
641253
  });
641254
+ const source = opts?.headers?.[DETACH_HEADER] === "true" ? withHeadlessR1Reconnect(live, {
641255
+ baseUrl: baseUrlTrimmed,
641256
+ getTaskId: () => earlyTaskId,
641257
+ openEvents: (taskId, lastEventId) => client4.runs.events(taskId, {
641258
+ ...lastEventId !== void 0 ? { lastEventId } : {},
641259
+ ...opts?.signal ? { signal: opts.signal } : {}
641260
+ }),
641261
+ getRun: async (taskId) => {
641262
+ try {
641263
+ return await client4.runs.get(taskId, opts?.signal ? { signal: opts.signal } : void 0);
641264
+ } catch {
641265
+ return null;
641266
+ }
641267
+ },
641268
+ ...opts?.signal ? { signal: opts.signal } : {}
641269
+ }) : live;
640888
641270
  return diagnoseSseIdleTear(
640889
641271
  normalizeToolNames(
640890
641272
  captureSessionId(
640891
641273
  // §4④ engine 1.163 — AskUserQuestion parks the run `suspended` (no `question` frames anymore);
640892
641274
  // the bridge turns that park into dialog → approvals.decide → runs.events continuation, INSIDE
640893
641275
  // this same generator, so the turn keeps flowing to its real terminal (liveHitlAskWire.ts).
640894
- bridgeAskUserQuestionGates(demuxQuestionFrames(live), hitlDeps, {
641276
+ bridgeAskUserQuestionGates(demuxQuestionFrames(source), hitlDeps, {
640895
641277
  ...opts?.signal ? { signal: opts.signal } : {}
640896
641278
  }),
640897
641279
  (sid) => {
@@ -640990,6 +641372,8 @@ var init_liveClient = __esm({
640990
641372
  init_appStateRef();
640991
641373
  init_sseIdleTriage();
640992
641374
  init_agentsWire();
641375
+ init_detachWire();
641376
+ init_headlessReconnectWire();
640993
641377
  init_mockClient();
640994
641378
  ENGINE_TO_CC_TOOL = {
640995
641379
  bash: "Bash",
@@ -641168,160 +641552,6 @@ var init_finalVerifyWire = __esm({
641168
641552
  }
641169
641553
  });
641170
641554
 
641171
- // build-src/src/sema/limitsWire.ts
641172
- var limitsWire_exports = {};
641173
- __export(limitsWire_exports, {
641174
- DEADLINE_SEC_MAX: () => DEADLINE_SEC_MAX,
641175
- DEADLINE_SEC_MIN: () => DEADLINE_SEC_MIN,
641176
- HEADLESS_DEADLINE_ENV: () => HEADLESS_DEADLINE_ENV,
641177
- HEADLESS_MAX_TURNS_ENV: () => HEADLESS_MAX_TURNS_ENV,
641178
- LIMITS_WIRE_MIN_ENGINE: () => LIMITS_WIRE_MIN_ENGINE,
641179
- MAX_TURNS_MAX: () => MAX_TURNS_MAX,
641180
- MAX_TURNS_MIN: () => MAX_TURNS_MIN,
641181
- engineLimitsSupportWarning: () => engineLimitsSupportWarning,
641182
- headlessLimitsFromEnv: () => headlessLimitsFromEnv,
641183
- limitsForPrint: () => limitsForPrint,
641184
- parseLimitsArgv: () => parseLimitsArgv,
641185
- versionSupportsLimits: () => versionSupportsLimits
641186
- });
641187
- function lastFlagValue(argv, name) {
641188
- const eq2 = `${name}=`;
641189
- let present = false;
641190
- let raw2;
641191
- let valueMissing = false;
641192
- for (let i = 0; i < argv.length; i++) {
641193
- const a = argv[i];
641194
- if (a === "--") break;
641195
- if (a === name) {
641196
- present = true;
641197
- const nxt = argv[i + 1];
641198
- if (nxt === void 0 || nxt.startsWith("-")) {
641199
- valueMissing = true;
641200
- raw2 = void 0;
641201
- continue;
641202
- }
641203
- valueMissing = false;
641204
- raw2 = nxt;
641205
- i++;
641206
- } else if (a.startsWith(eq2)) {
641207
- present = true;
641208
- valueMissing = false;
641209
- raw2 = a.slice(eq2.length);
641210
- }
641211
- }
641212
- if (present && (valueMissing || raw2 === void 0)) return { present: true };
641213
- return present ? { present: true, raw: raw2 } : { present: false };
641214
- }
641215
- function parseIntInDomain(raw2, min, max2) {
641216
- const v2 = raw2.trim();
641217
- if (!INT_RE.test(v2)) return null;
641218
- const n2 = Number(v2);
641219
- if (!Number.isSafeInteger(n2) || n2 < min || n2 > max2) return null;
641220
- return n2;
641221
- }
641222
- function parseLimitsArgv(argv) {
641223
- const limits = {};
641224
- const flaggedFlags = [];
641225
- const dl = lastFlagValue(argv, "--deadline");
641226
- if (dl.present) {
641227
- const n2 = dl.raw !== void 0 ? parseIntInDomain(dl.raw, DEADLINE_SEC_MIN, DEADLINE_SEC_MAX) : null;
641228
- if (n2 === null) return { ok: false, error: DEADLINE_USAGE };
641229
- limits.timeoutSec = n2;
641230
- flaggedFlags.push("--deadline");
641231
- }
641232
- const mt2 = lastFlagValue(argv, "--max-turns");
641233
- if (mt2.present) {
641234
- const n2 = mt2.raw !== void 0 ? parseIntInDomain(mt2.raw, MAX_TURNS_MIN, MAX_TURNS_MAX) : null;
641235
- if (n2 === null) return { ok: false, error: MAX_TURNS_USAGE };
641236
- limits.maxTurns = n2;
641237
- flaggedFlags.push("--max-turns");
641238
- }
641239
- return {
641240
- ok: true,
641241
- ...flaggedFlags.length > 0 ? { limits } : {},
641242
- flaggedFlags
641243
- };
641244
- }
641245
- function headlessLimitsFromEnv(env5 = process.env) {
641246
- const out6 = {};
641247
- const dl = env5[HEADLESS_DEADLINE_ENV]?.trim();
641248
- if (dl) {
641249
- const n2 = parseIntInDomain(dl, DEADLINE_SEC_MIN, DEADLINE_SEC_MAX);
641250
- if (n2 !== null) out6.timeoutSec = n2;
641251
- else if (env5.SEMA_DEBUG) {
641252
- console.error(`[sema] ${HEADLESS_DEADLINE_ENV}="${dl}" is not an integer in ${DEADLINE_SEC_MIN}..${DEADLINE_SEC_MAX} \u2014 ignoring the settings default`);
641253
- }
641254
- }
641255
- const mt2 = env5[HEADLESS_MAX_TURNS_ENV]?.trim();
641256
- if (mt2) {
641257
- const n2 = parseIntInDomain(mt2, MAX_TURNS_MIN, MAX_TURNS_MAX);
641258
- if (n2 !== null) out6.maxTurns = n2;
641259
- else if (env5.SEMA_DEBUG) {
641260
- console.error(`[sema] ${HEADLESS_MAX_TURNS_ENV}="${mt2}" is not an integer in ${MAX_TURNS_MIN}..${MAX_TURNS_MAX} \u2014 ignoring the settings default`);
641261
- }
641262
- }
641263
- return out6.timeoutSec !== void 0 || out6.maxTurns !== void 0 ? out6 : void 0;
641264
- }
641265
- function limitsForPrint(argv, env5 = process.env) {
641266
- const parsed = parseLimitsArgv(argv);
641267
- if (!parsed.ok) return parsed;
641268
- const fromEnv = headlessLimitsFromEnv(env5);
641269
- const merged = { ...fromEnv ?? {}, ...parsed.limits ?? {} };
641270
- const any3 = merged.timeoutSec !== void 0 || merged.maxTurns !== void 0;
641271
- return { ok: true, ...any3 ? { limits: merged } : {}, flaggedFlags: parsed.flaggedFlags };
641272
- }
641273
- function versionSupportsLimits(v2) {
641274
- const m2 = v2 ? /^(\d+)\.(\d+)\.(\d+)/.exec(v2) : null;
641275
- if (!m2) return false;
641276
- const [a, b3, c2] = [Number(m2[1]), Number(m2[2]), Number(m2[3])];
641277
- const [ma, mb, mc] = LIMITS_WIRE_MIN_ENGINE;
641278
- if (a !== ma) return a > ma;
641279
- if (b3 !== mb) return b3 > mb;
641280
- return c2 >= mc;
641281
- }
641282
- async function engineLimitsSupportWarning(baseUrl, flaggedFlags, opts) {
641283
- const fetchImpl = opts?.fetchImpl ?? fetch;
641284
- const controller = new AbortController();
641285
- const timer2 = setTimeout(() => controller.abort(), opts?.timeoutMs ?? 1500);
641286
- try {
641287
- const res = await fetchImpl(`${baseUrl.replace(/\/+$/, "")}/health`, {
641288
- method: "GET",
641289
- signal: controller.signal
641290
- });
641291
- if (!res.ok) return void 0;
641292
- const body = await res.json();
641293
- const version5 = typeof body?.version === "string" ? body.version : void 0;
641294
- if (versionSupportsLimits(version5)) return void 0;
641295
- const flags = flaggedFlags.length > 0 ? flaggedFlags.join("/") : "--deadline/--max-turns";
641296
- return `[sema] engine ${version5 ?? "(unversioned, pre-1.96)"} does not support ${flags} (needs \u22651.196.0); the flag will be ignored by the engine`;
641297
- } catch {
641298
- return void 0;
641299
- } finally {
641300
- clearTimeout(timer2);
641301
- }
641302
- }
641303
- var HEADLESS_DEADLINE_ENV, HEADLESS_MAX_TURNS_ENV, DEADLINE_SEC_MIN, DEADLINE_SEC_MAX, MAX_TURNS_MIN, MAX_TURNS_MAX, LIMITS_WIRE_MIN_ENGINE, DEADLINE_USAGE, MAX_TURNS_USAGE, INT_RE;
641304
- var init_limitsWire = __esm({
641305
- "build-src/src/sema/limitsWire.ts"() {
641306
- HEADLESS_DEADLINE_ENV = "SEMA_HEADLESS_DEADLINE_SEC";
641307
- HEADLESS_MAX_TURNS_ENV = "SEMA_HEADLESS_MAX_TURNS";
641308
- DEADLINE_SEC_MIN = 30;
641309
- DEADLINE_SEC_MAX = 86400;
641310
- MAX_TURNS_MIN = 1;
641311
- MAX_TURNS_MAX = 1e3;
641312
- LIMITS_WIRE_MIN_ENGINE = [1, 196, 0];
641313
- DEADLINE_USAGE = `sema: --deadline expects a whole number of seconds between ${DEADLINE_SEC_MIN} and ${DEADLINE_SEC_MAX}.
641314
- --deadline <sec> soft wall-clock budget for this run (sema superset \u2014 no upstream equivalent):
641315
- the engine paces itself (nudges + call caps) and finalizes gracefully near the deadline
641316
- (no flag) no deadline \u2014 today's behaviour`;
641317
- MAX_TURNS_USAGE = `sema: --max-turns expects a whole number of turns between ${MAX_TURNS_MIN} and ${MAX_TURNS_MAX}.
641318
- --max-turns <n> maximum number of agentic turns for this run (upstream-aligned flag,
641319
- enforced engine-side on the sema seam)
641320
- (no flag) no turn cap \u2014 today's behaviour`;
641321
- INT_RE = /^\d+$/;
641322
- }
641323
- });
641324
-
641325
641555
  // build-src/src/sema/headlessPermissionModeWire.ts
641326
641556
  var headlessPermissionModeWire_exports = {};
641327
641557
  __export(headlessPermissionModeWire_exports, {
@@ -641394,111 +641624,6 @@ var init_headlessPermissionModeWire = __esm({
641394
641624
  }
641395
641625
  });
641396
641626
 
641397
- // build-src/src/sema/detachWire.ts
641398
- var detachWire_exports = {};
641399
- __export(detachWire_exports, {
641400
- DETACH_DURABLE_OFF_400_ANCHOR: () => DETACH_DURABLE_OFF_400_ANCHOR,
641401
- DETACH_HEADER: () => DETACH_HEADER,
641402
- DETACH_WIRE_MIN_ENGINE: () => DETACH_WIRE_MIN_ENGINE,
641403
- HEADLESS_DETACH_ENV: () => HEADLESS_DETACH_ENV,
641404
- _resetDetachWireForTest: () => _resetDetachWireForTest,
641405
- armDetachCancel: () => armDetachCancel,
641406
- detachDurableOffHint: () => detachDurableOffHint,
641407
- detachedTaskId: () => detachedTaskId,
641408
- engineSupportsDetach: () => engineSupportsDetach,
641409
- fireBestEffortDetachCancel: () => fireBestEffortDetachCancel,
641410
- headlessDetachDisabledByEnv: () => headlessDetachDisabledByEnv,
641411
- isDetachArmed: () => isDetachArmed,
641412
- resolveHeadlessDetach: () => resolveHeadlessDetach,
641413
- versionSupportsDetach: () => versionSupportsDetach
641414
- });
641415
- function headlessDetachDisabledByEnv(env5 = process.env) {
641416
- const v2 = env5[HEADLESS_DETACH_ENV]?.trim().toLowerCase();
641417
- return v2 === "false" || v2 === "0";
641418
- }
641419
- async function engineSupportsDetach(baseUrl, opts) {
641420
- const fetchImpl = opts?.fetchImpl ?? fetch;
641421
- const controller = new AbortController();
641422
- const timer2 = setTimeout(() => controller.abort(), opts?.timeoutMs ?? 1500);
641423
- try {
641424
- const res = await fetchImpl(`${baseUrl.replace(/\/+$/, "")}/health`, {
641425
- method: "GET",
641426
- signal: controller.signal
641427
- });
641428
- if (!res.ok) return true;
641429
- const body = await res.json();
641430
- const version5 = typeof body?.version === "string" ? body.version : void 0;
641431
- return versionSupportsDetach(version5);
641432
- } catch {
641433
- return true;
641434
- } finally {
641435
- clearTimeout(timer2);
641436
- }
641437
- }
641438
- async function resolveHeadlessDetach(baseUrl, env5 = process.env, opts) {
641439
- if (headlessDetachDisabledByEnv(env5)) return { on: false, reason: "env-off" };
641440
- if (env5.SEMA_ENGINE_URL) {
641441
- const ok2 = await engineSupportsDetach(baseUrl, opts);
641442
- if (!ok2) return { on: false, reason: "old-engine" };
641443
- }
641444
- return { on: true, reason: "default-on" };
641445
- }
641446
- function detachDurableOffHint(err8) {
641447
- if (!isDetachArmed()) return null;
641448
- const e = err8;
641449
- if (e?.status !== 400) return null;
641450
- const msg = typeof e?.message === "string" ? e.message : "";
641451
- if (!msg.includes(DETACH_DURABLE_OFF_400_ANCHOR)) return null;
641452
- return "engine has durable runs disabled \u2014 detach-on-disconnect unavailable; interrupted turns will abort (SEMA_HEADLESS_DETACH=false to silence)";
641453
- }
641454
- function armDetachCancel(arm) {
641455
- cancelArm = arm;
641456
- }
641457
- function isDetachArmed() {
641458
- return cancelArm !== null;
641459
- }
641460
- function detachedTaskId() {
641461
- return cancelArm?.getTaskId() ?? null;
641462
- }
641463
- function _resetDetachWireForTest() {
641464
- cancelArm = null;
641465
- }
641466
- function fireBestEffortDetachCancel(fetchImpl = fetch) {
641467
- const arm = cancelArm;
641468
- if (!arm) return false;
641469
- const taskId = arm.getTaskId();
641470
- if (!taskId) return false;
641471
- try {
641472
- const controller = new AbortController();
641473
- const timer2 = setTimeout(() => controller.abort(), 1500);
641474
- timer2.unref?.();
641475
- void fetchImpl(`${arm.baseUrl.replace(/\/+$/, "")}/v1/runs/${encodeURIComponent(taskId)}/cancel`, {
641476
- method: "POST",
641477
- headers: {
641478
- authorization: `Bearer ${arm.authToken}`,
641479
- "x-agent-principal": arm.principal
641480
- },
641481
- signal: controller.signal
641482
- }).catch(() => {
641483
- }).finally(() => clearTimeout(timer2));
641484
- return true;
641485
- } catch {
641486
- return false;
641487
- }
641488
- }
641489
- var DETACH_HEADER, HEADLESS_DETACH_ENV, DETACH_WIRE_MIN_ENGINE, versionSupportsDetach, DETACH_DURABLE_OFF_400_ANCHOR, cancelArm;
641490
- var init_detachWire = __esm({
641491
- "build-src/src/sema/detachWire.ts"() {
641492
- init_limitsWire();
641493
- DETACH_HEADER = "x-detach-on-disconnect";
641494
- HEADLESS_DETACH_ENV = "SEMA_HEADLESS_DETACH";
641495
- DETACH_WIRE_MIN_ENGINE = [1, 196, 0];
641496
- versionSupportsDetach = versionSupportsLimits;
641497
- DETACH_DURABLE_OFF_400_ANCHOR = "x-detach-on-disconnect requires a durable run";
641498
- cancelArm = null;
641499
- }
641500
- });
641501
-
641502
641627
  // build-src/src/sema/printStreamJsonContract.ts
641503
641628
  var printStreamJsonContract_exports = {};
641504
641629
  __export(printStreamJsonContract_exports, {
@@ -642133,6 +642258,17 @@ async function* ask(params) {
642133
642258
  }
642134
642259
  } catch {
642135
642260
  }
642261
+ try {
642262
+ const { activeEnginePin: activeEnginePin2, enginePinUnreachableHint: enginePinUnreachableHint2, isEngineTransportError: isEngineTransportError2 } = await Promise.resolve().then(() => (init_engineTarget(), engineTarget_exports));
642263
+ const { engineAliveIdleElapsedMs: engineAliveIdleElapsedMs2 } = await Promise.resolve().then(() => (init_sseIdleTriage(), sseIdleTriage_exports));
642264
+ if (engineAliveIdleElapsedMs2(streamErr) === void 0 && isEngineTransportError2(streamErr)) {
642265
+ const pin = activeEnginePin2();
642266
+ if (pin) {
642267
+ console.error(enginePinUnreachableHint2(pin));
642268
+ }
642269
+ }
642270
+ } catch {
642271
+ }
642136
642272
  try {
642137
642273
  const dw = await Promise.resolve().then(() => (init_detachWire(), detachWire_exports));
642138
642274
  const dHint = dw.detachDurableOffHint(streamErr);
@@ -666083,7 +666219,7 @@ Auth: unix socket -R \u2192 local proxy`, "info");
666083
666219
  pendingHookMessages
666084
666220
  }, renderAndRun);
666085
666221
  }
666086
- }).version("sema 1.0.6", "-v, --version", "Output the version number");
666222
+ }).version("sema 1.0.7", "-v, --version", "Output the version number");
666087
666223
  program2.option("-w, --worktree [name]", "Create a new git worktree for this session (optionally specify a name)");
666088
666224
  program2.option("--tmux", "Create a tmux session for the worktree (requires --worktree). Uses iTerm2 native panes when available; use --tmux=classic for traditional tmux.");
666089
666225
  if (canUserConfigureAdvisor()) {