@sema-agent/cli 1.0.67 → 1.0.68

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/sema-main.js CHANGED
@@ -40445,7 +40445,7 @@ var init_gitFilesystem = __esm({
40445
40445
  }
40446
40446
  watchPath(path28, callback) {
40447
40447
  this.watchedPaths.push(path28);
40448
- watchFile(path28, { interval: WATCH_INTERVAL_MS }, callback);
40448
+ watchFile(path28, { interval: WATCH_INTERVAL_MS, persistent: false }, callback);
40449
40449
  }
40450
40450
  /**
40451
40451
  * Watch the loose ref file for the current branch.
@@ -65953,11 +65953,11 @@ var init_types3 = __esm({
65953
65953
  "Show thinking summaries in the transcript view (ctrl+o). Default: false."
65954
65954
  ),
65955
65955
  skipDangerousModePermissionPrompt: external_exports.boolean().optional().describe(
65956
- "Whether the user has accepted the bypass permissions mode dialog"
65956
+ "Whether the user has accepted the bypass permissions mode dialog. Remembers the warning screen only \u2014 it is NOT an approval switch and never changes what gets approved."
65957
65957
  ),
65958
65958
  ...true ? {
65959
65959
  skipAutoPermissionPrompt: external_exports.boolean().optional().describe(
65960
- "Whether the user has accepted the auto mode opt-in dialog"
65960
+ "Whether the user has accepted the auto mode opt-in dialog. Remembers the opt-in screen only \u2014 it is NOT an approval switch and never changes what gets approved."
65961
65961
  ),
65962
65962
  useAutoModeDuringPlan: external_exports.boolean().optional().describe(
65963
65963
  "Whether plan mode uses auto mode semantics when auto mode is available (default: true)"
@@ -73313,8 +73313,8 @@ function defaultMaxTokensFor(contextWindow, perModelCap) {
73313
73313
  const ctx = normalizeCtx(contextWindow);
73314
73314
  const base = ctx >= 5e5 ? 64e3 : 32e3;
73315
73315
  const quarter = Math.floor(ctx / 4);
73316
- const cap = typeof perModelCap === "number" && Number.isFinite(perModelCap) && perModelCap > 0 ? perModelCap : Infinity;
73317
- return Math.min(base, quarter, cap);
73316
+ const cap2 = typeof perModelCap === "number" && Number.isFinite(perModelCap) && perModelCap > 0 ? perModelCap : Infinity;
73317
+ return Math.min(base, quarter, cap2);
73318
73318
  }
73319
73319
  function tierChoicesFor(contextWindow) {
73320
73320
  const ctx = normalizeCtx(contextWindow);
@@ -130801,20 +130801,20 @@ function drainAdaptive(node, pending2, innerHeight) {
130801
130801
  const step = abs <= SCROLL_INSTANT_THRESHOLD ? abs : abs < SCROLL_HIGH_PENDING ? SCROLL_STEP_MED : SCROLL_STEP_HIGH;
130802
130802
  applied += sign * step;
130803
130803
  const rem = abs - step;
130804
- const cap = Math.max(1, innerHeight - 1);
130804
+ const cap2 = Math.max(1, innerHeight - 1);
130805
130805
  const totalAbs = Math.abs(applied);
130806
- if (totalAbs > cap) {
130807
- const excess = totalAbs - cap;
130806
+ if (totalAbs > cap2) {
130807
+ const excess = totalAbs - cap2;
130808
130808
  node.pendingScrollDelta = sign * (rem + excess);
130809
- return sign * cap;
130809
+ return sign * cap2;
130810
130810
  }
130811
130811
  node.pendingScrollDelta = rem > 0 ? sign * rem : void 0;
130812
130812
  return applied;
130813
130813
  }
130814
130814
  function drainProportional(node, pending2, innerHeight) {
130815
130815
  const abs = Math.abs(pending2);
130816
- const cap = Math.max(1, innerHeight - 1);
130817
- const step = Math.min(cap, Math.max(SCROLL_MIN_PER_FRAME, abs * 3 >> 2));
130816
+ const cap2 = Math.max(1, innerHeight - 1);
130817
+ const step = Math.min(cap2, Math.max(SCROLL_MIN_PER_FRAME, abs * 3 >> 2));
130818
130818
  if (abs <= step) {
130819
130819
  node.pendingScrollDelta = void 0;
130820
130820
  return pending2;
@@ -136505,6 +136505,8 @@ var init_lastTurnUsageStore = __esm({
136505
136505
  // build-src/src/seam/adapter/runStream.ts
136506
136506
  var runStream_exports = {};
136507
136507
  __export(runStream_exports, {
136508
+ _resetHostDroppedFrameMemoForTest: () => _resetHostDroppedFrameMemoForTest,
136509
+ hostDroppedFrameSink: () => hostDroppedFrameSink,
136508
136510
  isRunStreamActive: () => isRunStreamActive,
136509
136511
  runStream: () => runStream2
136510
136512
  });
@@ -136550,20 +136552,47 @@ function hostSink(e) {
136550
136552
  });
136551
136553
  }
136552
136554
  }
136555
+ function consoleLegForDroppedFrame(type, line) {
136556
+ if (reportedDroppedTypes2.has(type)) return;
136557
+ if (reportedDroppedTypes2.size < DROPPED_TYPE_MEMO_CAP2) reportedDroppedTypes2.add(type);
136558
+ console.error(line);
136559
+ }
136560
+ function _resetHostDroppedFrameMemoForTest() {
136561
+ reportedDroppedTypes2.clear();
136562
+ }
136563
+ function hostDroppedFrameSink(info) {
136564
+ const clean = (v2) => (
136565
+ // eslint-disable-next-line no-control-regex
136566
+ String(v2).replace(/[\x00-\x1f\x7f]/g, ".").slice(0, 120)
136567
+ );
136568
+ const type = clean(info.type);
136569
+ const line = `[sema][wire] dropped engine frame: type=${type} why=${clean(info.why)} \u2014 this build's projector has no arm for it (engine newer than the client, or a malformed frame). It renders NOWHERE.`;
136570
+ void Promise.resolve().then(() => (init_debug(), debug_exports)).then((m2) => {
136571
+ m2.logForDebugging(line, { level: "warn" });
136572
+ if (!m2.isDebugMode() && process.env.USER_TYPE !== "ant") consoleLegForDroppedFrame(type, line);
136573
+ }).catch(() => consoleLegForDroppedFrame(type, line));
136574
+ }
136553
136575
  function runStream2(events3, ctx, handle2 = {}) {
136554
136576
  const seen2 = { busy: null };
136555
136577
  const projected2 = runStream(
136556
136578
  watchActiveRunBusy(events3, seen2),
136557
- { ...ctx, emitChrome: ctx.emitChrome ?? hostSink },
136579
+ {
136580
+ ...ctx,
136581
+ emitChrome: ctx.emitChrome ?? hostSink,
136582
+ onDroppedFrame: ctx.onDroppedFrame ?? hostDroppedFrameSink
136583
+ },
136558
136584
  handle2
136559
136585
  );
136560
136586
  return rewriteActiveRunBusyRow(projected2, seen2);
136561
136587
  }
136588
+ var reportedDroppedTypes2, DROPPED_TYPE_MEMO_CAP2;
136562
136589
  var init_runStream2 = __esm({
136563
136590
  "build-src/src/seam/adapter/runStream.ts"() {
136564
136591
  init_dist();
136565
136592
  init_activeRunSelfHeal();
136566
136593
  init_dist();
136594
+ reportedDroppedTypes2 = /* @__PURE__ */ new Set();
136595
+ DROPPED_TYPE_MEMO_CAP2 = 64;
136567
136596
  }
136568
136597
  });
136569
136598
 
@@ -167698,12 +167727,12 @@ function getContextWindowForModel(model, betas) {
167698
167727
  if (has1mContext(model)) {
167699
167728
  return 1e6;
167700
167729
  }
167701
- const cap = getModelCapability(model);
167702
- if (cap?.max_input_tokens && cap.max_input_tokens >= 1e5) {
167703
- if (cap.max_input_tokens > MODEL_CONTEXT_WINDOW_DEFAULT && is1mContextDisabled()) {
167730
+ const cap2 = getModelCapability(model);
167731
+ if (cap2?.max_input_tokens && cap2.max_input_tokens >= 1e5) {
167732
+ if (cap2.max_input_tokens > MODEL_CONTEXT_WINDOW_DEFAULT && is1mContextDisabled()) {
167704
167733
  return MODEL_CONTEXT_WINDOW_DEFAULT;
167705
167734
  }
167706
- return cap.max_input_tokens;
167735
+ return cap2.max_input_tokens;
167707
167736
  }
167708
167737
  if (betas?.includes(CONTEXT_1M_BETA_HEADER) && modelSupports1M(model)) {
167709
167738
  return 1e6;
@@ -167792,9 +167821,9 @@ function getModelMaxOutputTokens(model) {
167792
167821
  defaultTokens = MAX_OUTPUT_TOKENS_DEFAULT;
167793
167822
  upperLimit = MAX_OUTPUT_TOKENS_UPPER_LIMIT;
167794
167823
  }
167795
- const cap = getModelCapability(model);
167796
- if (cap?.max_tokens && cap.max_tokens >= 4096) {
167797
- upperLimit = cap.max_tokens;
167824
+ const cap2 = getModelCapability(model);
167825
+ if (cap2?.max_tokens && cap2.max_tokens >= 4096) {
167826
+ upperLimit = cap2.max_tokens;
167798
167827
  defaultTokens = Math.min(defaultTokens, upperLimit);
167799
167828
  }
167800
167829
  return { default: defaultTokens, upperLimit };
@@ -223432,59 +223461,6 @@ var init_rewindAnchorSidecar = __esm({
223432
223461
  list() {
223433
223462
  return [...this.index.entries()].map(([uuid8, taskId]) => ({ uuid: uuid8, taskId }));
223434
223463
  }
223435
- /**
223436
- * Drop all anchors whose record belongs to `shellSessionId` and rewrite the file (compaction — the only
223437
- * non-append operation, rare: used on /clear or session delete). Reads existing records, filters, atomic
223438
- * temp+rename. Best-effort.
223439
- */
223440
- deleteBySession(shellSessionId) {
223441
- if (!this.path) {
223442
- return;
223443
- }
223444
- let raw2;
223445
- try {
223446
- raw2 = readFileSync18(this.path, "utf8");
223447
- } catch {
223448
- return;
223449
- }
223450
- const kept = [];
223451
- const droppedUuids = /* @__PURE__ */ new Set();
223452
- for (const line of raw2.split("\n")) {
223453
- if (line.length === 0) continue;
223454
- try {
223455
- const rec = JSON.parse(line);
223456
- if (!rec || typeof rec.uuid !== "string") continue;
223457
- if (rec.shellSessionId === shellSessionId) {
223458
- droppedUuids.add(rec.uuid);
223459
- } else {
223460
- kept.push(rec);
223461
- }
223462
- } catch {
223463
- }
223464
- }
223465
- for (const uuid8 of droppedUuids) this.index.delete(uuid8);
223466
- const body = kept.map((r) => JSON.stringify(r) + "\n").join("");
223467
- const tmp = `${this.path}.tmp-${process.pid}`;
223468
- let release2;
223469
- try {
223470
- release2 = lockSyncRetry(this.path, LOCK_OPTS);
223471
- } catch {
223472
- release2 = void 0;
223473
- }
223474
- try {
223475
- writeFileSync10(tmp, body, { mode: 384 });
223476
- renameSync9(tmp, this.path);
223477
- } catch (err8) {
223478
- logForDebugging3(`rewindAnchorSidecar: compaction failed: ${err8}`);
223479
- } finally {
223480
- if (release2) {
223481
- try {
223482
- release2();
223483
- } catch {
223484
- }
223485
- }
223486
- }
223487
- }
223488
223464
  /**
223489
223465
  * Clear ALL anchors for the current sidecar file (it is per-session — filename = sessionId), truncating
223490
223466
  * the file to empty. Used on /clear. Atomic temp+rename. Best-effort.
@@ -234314,6 +234290,15 @@ var init_bashClassifier = __esm({
234314
234290
  });
234315
234291
 
234316
234292
  // build-src/src/utils/permissions/permissionsLoader.ts
234293
+ var permissionsLoader_exports = {};
234294
+ __export(permissionsLoader_exports, {
234295
+ addPermissionRulesToSettings: () => addPermissionRulesToSettings,
234296
+ deletePermissionRuleFromSettings: () => deletePermissionRuleFromSettings,
234297
+ getPermissionRulesForSource: () => getPermissionRulesForSource,
234298
+ loadAllPermissionRulesFromDisk: () => loadAllPermissionRulesFromDisk,
234299
+ shouldAllowManagedPermissionRulesOnly: () => shouldAllowManagedPermissionRulesOnly,
234300
+ shouldShowAlwaysAllowOptions: () => shouldShowAlwaysAllowOptions
234301
+ });
234317
234302
  function shouldAllowManagedPermissionRulesOnly() {
234318
234303
  return getSettingsForSource("policySettings")?.allowManagedPermissionRulesOnly === true;
234319
234304
  }
@@ -238518,6 +238503,33 @@ var init_pathValidation2 = __esm({
238518
238503
  });
238519
238504
 
238520
238505
  // build-src/src/tools/BashTool/bashPermissions.ts
238506
+ var bashPermissions_exports = {};
238507
+ __export(bashPermissions_exports, {
238508
+ BINARY_HIJACK_VARS: () => BINARY_HIJACK_VARS,
238509
+ MAX_SUBCOMMANDS_FOR_SECURITY_CHECK: () => MAX_SUBCOMMANDS_FOR_SECURITY_CHECK,
238510
+ MAX_SUGGESTED_RULES_FOR_COMPOUND: () => MAX_SUGGESTED_RULES_FOR_COMPOUND,
238511
+ awaitClassifierAutoApproval: () => awaitClassifierAutoApproval,
238512
+ bashPermissionRule: () => bashPermissionRule,
238513
+ bashToolCheckExactMatchPermission: () => bashToolCheckExactMatchPermission,
238514
+ bashToolCheckPermission: () => bashToolCheckPermission,
238515
+ bashToolHasPermission: () => bashToolHasPermission,
238516
+ checkCommandAndSuggestRules: () => checkCommandAndSuggestRules,
238517
+ clearSpeculativeChecks: () => clearSpeculativeChecks,
238518
+ commandHasAnyCd: () => commandHasAnyCd,
238519
+ consumeSpeculativeClassifierCheck: () => consumeSpeculativeClassifierCheck,
238520
+ executeAsyncClassifierCheck: () => executeAsyncClassifierCheck,
238521
+ getFirstWordPrefix: () => getFirstWordPrefix,
238522
+ getSimpleCommandPrefix: () => getSimpleCommandPrefix,
238523
+ isNormalizedCdCommand: () => isNormalizedCdCommand,
238524
+ isNormalizedGitCommand: () => isNormalizedGitCommand,
238525
+ matchWildcardPattern: () => matchWildcardPattern2,
238526
+ peekSpeculativeClassifierCheck: () => peekSpeculativeClassifierCheck,
238527
+ permissionRuleExtractPrefix: () => permissionRuleExtractPrefix3,
238528
+ startSpeculativeClassifierCheck: () => startSpeculativeClassifierCheck,
238529
+ stripAllLeadingEnvVars: () => stripAllLeadingEnvVars,
238530
+ stripSafeWrappers: () => stripSafeWrappers,
238531
+ stripWrappersFromArgv: () => stripWrappersFromArgv2
238532
+ });
238521
238533
  function logClassifierResultForAnts(command8, behavior, descriptions, result) {
238522
238534
  if (process.env.USER_TYPE !== "ant") {
238523
238535
  return;
@@ -238680,6 +238692,45 @@ function stripSafeWrappers(command8) {
238680
238692
  }
238681
238693
  return stripped.trim();
238682
238694
  }
238695
+ function skipTimeoutFlags2(a) {
238696
+ let i = 1;
238697
+ while (i < a.length) {
238698
+ const arg = a[i];
238699
+ const next = a[i + 1];
238700
+ if (arg === "--foreground" || arg === "--preserve-status" || arg === "--verbose")
238701
+ i++;
238702
+ else if (/^--(?:kill-after|signal)=[A-Za-z0-9_.+-]+$/.test(arg)) i++;
238703
+ else if ((arg === "--kill-after" || arg === "--signal") && next && TIMEOUT_FLAG_VALUE_RE2.test(next))
238704
+ i += 2;
238705
+ else if (arg === "--") {
238706
+ i++;
238707
+ break;
238708
+ } else if (arg.startsWith("--")) return -1;
238709
+ else if (arg === "-v") i++;
238710
+ else if ((arg === "-k" || arg === "-s") && next && TIMEOUT_FLAG_VALUE_RE2.test(next))
238711
+ i += 2;
238712
+ else if (/^-[ks][A-Za-z0-9_.+-]+$/.test(arg)) i++;
238713
+ else if (arg.startsWith("-")) return -1;
238714
+ else break;
238715
+ }
238716
+ return i;
238717
+ }
238718
+ function stripWrappersFromArgv2(argv) {
238719
+ let a = argv;
238720
+ for (; ; ) {
238721
+ if (a[0] === "time" || a[0] === "nohup") {
238722
+ a = a.slice(a[1] === "--" ? 2 : 1);
238723
+ } else if (a[0] === "timeout") {
238724
+ const i = skipTimeoutFlags2(a);
238725
+ if (i < 0 || !a[i] || !/^\d+(?:\.\d+)?[smhd]?$/.test(a[i])) return a;
238726
+ a = a.slice(i + 1);
238727
+ } else if (a[0] === "nice" && a[1] === "-n" && a[2] && /^-?\d+$/.test(a[2])) {
238728
+ a = a.slice(a[3] === "--" ? 4 : 3);
238729
+ } else {
238730
+ return a;
238731
+ }
238732
+ }
238733
+ }
238683
238734
  function stripAllLeadingEnvVars(command8, blocklist) {
238684
238735
  const ENV_VAR_PATTERN = /^([A-Za-z_][A-Za-z0-9_]*(?:\[[^\]]*\])?)\+?=(?:'[^'\n\r]*'|"(?:\\.|[^"$`\\\n\r])*"|\\.|[^ \t\n\r$`;|&()<>\\\\'"])*[ \t]+/;
238685
238736
  let stripped = command8;
@@ -238979,9 +239030,96 @@ function checkSemanticsDeny(input, toolPermissionContext, commands) {
238979
239030
  }
238980
239031
  return null;
238981
239032
  }
239033
+ function peekSpeculativeClassifierCheck(command8) {
239034
+ return speculativeChecks.get(command8);
239035
+ }
239036
+ function startSpeculativeClassifierCheck(command8, toolPermissionContext, signal, isNonInteractiveSession) {
239037
+ if (!isClassifierPermissionsEnabled()) return false;
239038
+ if (toolPermissionContext.mode === "auto")
239039
+ return false;
239040
+ if (toolPermissionContext.mode === "bypassPermissions") return false;
239041
+ const allowDescriptions = getBashPromptAllowDescriptions(
239042
+ toolPermissionContext
239043
+ );
239044
+ if (allowDescriptions.length === 0) return false;
239045
+ const cwd5 = getCwd();
239046
+ const promise2 = classifyBashCommand(
239047
+ command8,
239048
+ cwd5,
239049
+ allowDescriptions,
239050
+ "allow",
239051
+ signal,
239052
+ isNonInteractiveSession
239053
+ );
239054
+ promise2.catch(() => {
239055
+ });
239056
+ speculativeChecks.set(command8, promise2);
239057
+ return true;
239058
+ }
239059
+ function consumeSpeculativeClassifierCheck(command8) {
239060
+ const promise2 = speculativeChecks.get(command8);
239061
+ if (promise2) {
239062
+ speculativeChecks.delete(command8);
239063
+ }
239064
+ return promise2;
239065
+ }
238982
239066
  function clearSpeculativeChecks() {
238983
239067
  speculativeChecks.clear();
238984
239068
  }
239069
+ async function awaitClassifierAutoApproval(pendingCheck, signal, isNonInteractiveSession) {
239070
+ const { command: command8, cwd: cwd5, descriptions } = pendingCheck;
239071
+ const speculativeResult = consumeSpeculativeClassifierCheck(command8);
239072
+ const classifierResult = speculativeResult ? await speculativeResult : await classifyBashCommand(
239073
+ command8,
239074
+ cwd5,
239075
+ descriptions,
239076
+ "allow",
239077
+ signal,
239078
+ isNonInteractiveSession
239079
+ );
239080
+ logClassifierResultForAnts(command8, "allow", descriptions, classifierResult);
239081
+ if (false) {
239082
+ return {
239083
+ type: "classifier",
239084
+ classifier: "bash_allow",
239085
+ reason: `Allowed by prompt rule: "${classifierResult.matchedDescription}"`
239086
+ };
239087
+ }
239088
+ return void 0;
239089
+ }
239090
+ async function executeAsyncClassifierCheck(pendingCheck, signal, isNonInteractiveSession, callbacks) {
239091
+ const { command: command8, cwd: cwd5, descriptions } = pendingCheck;
239092
+ const speculativeResult = consumeSpeculativeClassifierCheck(command8);
239093
+ let classifierResult;
239094
+ try {
239095
+ classifierResult = speculativeResult ? await speculativeResult : await classifyBashCommand(
239096
+ command8,
239097
+ cwd5,
239098
+ descriptions,
239099
+ "allow",
239100
+ signal,
239101
+ isNonInteractiveSession
239102
+ );
239103
+ } catch (error51) {
239104
+ if (error51 instanceof APIUserAbortError || error51 instanceof AbortError) {
239105
+ callbacks.onComplete?.();
239106
+ return;
239107
+ }
239108
+ callbacks.onComplete?.();
239109
+ throw error51;
239110
+ }
239111
+ logClassifierResultForAnts(command8, "allow", descriptions, classifierResult);
239112
+ if (!callbacks.shouldContinue()) return;
239113
+ if (false) {
239114
+ callbacks.onAllow({
239115
+ type: "classifier",
239116
+ classifier: "bash_allow",
239117
+ reason: `Allowed by prompt rule: "${classifierResult.matchedDescription}"`
239118
+ });
239119
+ } else {
239120
+ callbacks.onComplete?.();
239121
+ }
239122
+ }
238985
239123
  async function bashToolHasPermission(input, context3, getCommandSubcommandPrefixFn = getCommandSubcommandPrefix) {
238986
239124
  let appState = context3.getAppState();
238987
239125
  const injectionCheckDisabled = isEnvTruthy(
@@ -239577,7 +239715,7 @@ function commandHasAnyCd(command8) {
239577
239715
  (subcmd) => isNormalizedCdCommand(subcmd.trim())
239578
239716
  );
239579
239717
  }
239580
- var bashCommandIsSafeAsync, splitCommand, ENV_VAR_ASSIGN_RE, MAX_SUBCOMMANDS_FOR_SECURITY_CHECK, MAX_SUGGESTED_RULES_FOR_COMPOUND, BARE_SHELL_PREFIXES, permissionRuleExtractPrefix3, bashPermissionRule, SAFE_ENV_VARS2, ANT_ONLY_SAFE_ENV_VARS, BINARY_HIJACK_VARS, bashToolCheckExactMatchPermission, bashToolCheckPermission, speculativeChecks;
239718
+ var bashCommandIsSafeAsync, splitCommand, ENV_VAR_ASSIGN_RE, MAX_SUBCOMMANDS_FOR_SECURITY_CHECK, MAX_SUGGESTED_RULES_FOR_COMPOUND, BARE_SHELL_PREFIXES, permissionRuleExtractPrefix3, bashPermissionRule, SAFE_ENV_VARS2, ANT_ONLY_SAFE_ENV_VARS, TIMEOUT_FLAG_VALUE_RE2, BINARY_HIJACK_VARS, bashToolCheckExactMatchPermission, bashToolCheckPermission, speculativeChecks;
239581
239719
  var init_bashPermissions = __esm({
239582
239720
  "build-src/src/tools/BashTool/bashPermissions.ts"() {
239583
239721
  init_sdk();
@@ -239793,6 +239931,7 @@ var init_bashPermissions = __esm({
239793
239931
  "GROWTHBOOK_API_KEY"
239794
239932
  // self-hosted growthbook
239795
239933
  ]);
239934
+ TIMEOUT_FLAG_VALUE_RE2 = /^[A-Za-z0-9_.+-]+$/;
239796
239935
  BINARY_HIJACK_VARS = /^(LD_|DYLD_|PATH$)/;
239797
239936
  bashToolCheckExactMatchPermission = (input, toolPermissionContext) => {
239798
239937
  const command8 = input.command.trim();
@@ -382966,7 +383105,7 @@ function createInProcessCanUseTool(identity3, abortController, onPermissionWaitM
382966
383105
  return result;
382967
383106
  }
382968
383107
  if (false) {
382969
- const classifierDecision = await awaitClassifierAutoApproval(
383108
+ const classifierDecision = await awaitClassifierAutoApproval2(
382970
383109
  result.pendingClassifierCheck,
382971
383110
  abortController.signal,
382972
383111
  toolUseContext.options.isNonInteractiveSession
@@ -395177,16 +395316,29 @@ var init_RejectedToolUseMessage = __esm({
395177
395316
  });
395178
395317
 
395179
395318
  // build-src/src/components/messages/UserToolResultMessage/UserToolErrorMessage.tsx
395319
+ function unwrapWholeSystemReminder(content) {
395320
+ const OPEN = "<system-reminder>";
395321
+ const CLOSE = "</system-reminder>";
395322
+ const trimmed2 = content.trim();
395323
+ if (!trimmed2.startsWith(OPEN) || !trimmed2.endsWith(CLOSE)) return content;
395324
+ return trimmed2.split(OPEN).join("").split(CLOSE).join("").trim();
395325
+ }
395326
+ function normalizeEngineReminderParam(p) {
395327
+ if (typeof p.content !== "string") return p;
395328
+ const unwrapped = unwrapWholeSystemReminder(p.content);
395329
+ return unwrapped === p.content ? p : { ...p, content: unwrapped };
395330
+ }
395180
395331
  function UserToolErrorMessage(t0) {
395181
395332
  const $3 = (0, import_compiler_runtime105.c)(14);
395182
395333
  const {
395183
395334
  progressMessagesForMessage,
395184
395335
  tool,
395185
395336
  tools,
395186
- param,
395337
+ param: rawParam,
395187
395338
  verbose,
395188
395339
  isTranscriptMode
395189
395340
  } = t0;
395341
+ const param = normalizeEngineReminderParam(rawParam);
395190
395342
  if (typeof param.content === "string" && param.content.includes(INTERRUPT_MESSAGE_FOR_TOOL_USE)) {
395191
395343
  let t12;
395192
395344
  if ($3[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
@@ -399733,6 +399885,7 @@ var client_exports2 = {};
399733
399885
  __export(client_exports2, {
399734
399886
  MAX_RPC_BYTES: () => MAX_RPC_BYTES,
399735
399887
  daemonRpc: () => daemonRpc,
399888
+ daemonStartupFailureMessage: () => daemonStartupFailureMessage,
399736
399889
  dispatchJob: () => dispatchJob,
399737
399890
  ensureDaemonRunning: () => ensureDaemonRunning
399738
399891
  });
@@ -399829,13 +399982,16 @@ async function ensureDaemonRunning() {
399829
399982
  );
399830
399983
  child.unref();
399831
399984
  }
399832
- for (let i = 0; i < 40; i++) {
399985
+ for (let i = 0; i < 100; i++) {
399833
399986
  await sleep5(150);
399834
399987
  info = await readDaemonInfo();
399835
399988
  if (info && isDaemonAlive(info) && await pingOk(info)) return info;
399836
399989
  }
399837
399990
  return null;
399838
399991
  }
399992
+ function daemonStartupFailureMessage(registeredLate) {
399993
+ return registeredLate ? "the daemon registered but did not answer pings within the startup window \u2014 it may still be starting (slow machine) or wedged; check daemon.log" : "the daemon did not register within the startup window \u2014 slow first boot or a crash on boot; check daemon.log";
399994
+ }
399839
399995
  function mapResponse(r) {
399840
399996
  if (r.ok) return { ok: true, pid: r.pid };
399841
399997
  if (r.code === "short-alive" || r.code === "stale-short") {
@@ -399847,10 +400003,11 @@ function mapResponse(r) {
399847
400003
  async function dispatchJob(job) {
399848
400004
  let info = await ensureDaemonRunning();
399849
400005
  if (!info) {
400006
+ const late3 = await readDaemonInfo();
399850
400007
  return {
399851
400008
  ok: false,
399852
400009
  code: "daemon-unreachable",
399853
- message: "the daemon was spawned but never came up (it likely crashed on boot)"
400010
+ message: daemonStartupFailureMessage(late3 !== null)
399854
400011
  };
399855
400012
  }
399856
400013
  const nonce = randomUUID18();
@@ -409825,7 +409982,7 @@ var require_select = __commonJS({
409825
409982
  return url3.replace(/^(?:\w+:\/\/|\/+)/, "").replace(/(?:\/+|\/*#.*?)$/, "").split("/", num).join("/");
409826
409983
  };
409827
409984
  var parseNth = function(param_, test2) {
409828
- var param = param_.replace(/\s+/g, ""), cap;
409985
+ var param = param_.replace(/\s+/g, ""), cap2;
409829
409986
  if (param === "even") {
409830
409987
  param = "2n+0";
409831
409988
  } else if (param === "odd") {
@@ -409833,10 +409990,10 @@ var require_select = __commonJS({
409833
409990
  } else if (param.indexOf("n") === -1) {
409834
409991
  param = "0n" + param;
409835
409992
  }
409836
- cap = /^([+-])?(\d+)?n([+-])?(\d+)?$/.exec(param);
409993
+ cap2 = /^([+-])?(\d+)?n([+-])?(\d+)?$/.exec(param);
409837
409994
  return {
409838
- group: cap[1] === "-" ? -(cap[2] || 1) : +(cap[2] || 1),
409839
- offset: cap[4] ? cap[3] === "-" ? -cap[4] : +cap[4] : 0
409995
+ group: cap2[1] === "-" ? -(cap2[2] || 1) : +(cap2[2] || 1),
409996
+ offset: cap2[4] ? cap2[3] === "-" ? -cap2[4] : +cap2[4] : 0
409840
409997
  };
409841
409998
  };
409842
409999
  var nth = function(param_, test2, last3) {
@@ -410251,23 +410408,23 @@ var require_select = __commonJS({
410251
410408
  rules.ident = replace(rules.ident, "cssid", rules.cssid);
410252
410409
  rules.str_escape = replace(rules.str_escape, "escape", rules.escape);
410253
410410
  var compile = function(sel_) {
410254
- var sel = sel_.replace(/^\s+|\s+$/g, ""), test2, filter2 = [], buff = [], subject, qname, cap, op, ref;
410411
+ var sel = sel_.replace(/^\s+|\s+$/g, ""), test2, filter2 = [], buff = [], subject, qname, cap2, op, ref;
410255
410412
  while (sel) {
410256
- if (cap = rules.qname.exec(sel)) {
410257
- sel = sel.substring(cap[0].length);
410258
- qname = decodeid(cap[1]);
410413
+ if (cap2 = rules.qname.exec(sel)) {
410414
+ sel = sel.substring(cap2[0].length);
410415
+ qname = decodeid(cap2[1]);
410259
410416
  buff.push(tok(qname, true));
410260
- } else if (cap = rules.simple.exec(sel)) {
410261
- sel = sel.substring(cap[0].length);
410417
+ } else if (cap2 = rules.simple.exec(sel)) {
410418
+ sel = sel.substring(cap2[0].length);
410262
410419
  qname = "*";
410263
410420
  buff.push(tok(qname, true));
410264
- buff.push(tok(cap));
410421
+ buff.push(tok(cap2));
410265
410422
  } else {
410266
410423
  throw new SyntaxError("Invalid selector.");
410267
410424
  }
410268
- while (cap = rules.simple.exec(sel)) {
410269
- sel = sel.substring(cap[0].length);
410270
- buff.push(tok(cap));
410425
+ while (cap2 = rules.simple.exec(sel)) {
410426
+ sel = sel.substring(cap2[0].length);
410427
+ buff.push(tok(cap2));
410271
410428
  }
410272
410429
  if (sel[0] === "!") {
410273
410430
  sel = sel.substring(1);
@@ -410275,16 +410432,16 @@ var require_select = __commonJS({
410275
410432
  subject.qname = qname;
410276
410433
  buff.push(subject.simple);
410277
410434
  }
410278
- if (cap = rules.ref.exec(sel)) {
410279
- sel = sel.substring(cap[0].length);
410280
- ref = combinators.ref(makeSimple(buff), decodeid(cap[1]));
410435
+ if (cap2 = rules.ref.exec(sel)) {
410436
+ sel = sel.substring(cap2[0].length);
410437
+ ref = combinators.ref(makeSimple(buff), decodeid(cap2[1]));
410281
410438
  filter2.push(ref.combinator);
410282
410439
  buff = [];
410283
410440
  continue;
410284
410441
  }
410285
- if (cap = rules.combinator.exec(sel)) {
410286
- sel = sel.substring(cap[0].length);
410287
- op = cap[1] || cap[2] || cap[3];
410442
+ if (cap2 = rules.combinator.exec(sel)) {
410443
+ sel = sel.substring(cap2[0].length);
410444
+ op = cap2[1] || cap2[2] || cap2[3];
410288
410445
  if (op === ",") {
410289
410446
  filter2.push(combinators.noop(makeSimple(buff)));
410290
410447
  break;
@@ -410316,23 +410473,23 @@ var require_select = __commonJS({
410316
410473
  }
410317
410474
  return test2;
410318
410475
  };
410319
- var tok = function(cap, qname) {
410476
+ var tok = function(cap2, qname) {
410320
410477
  if (qname) {
410321
- return cap === "*" ? selectors["*"] : selectors.type(cap);
410478
+ return cap2 === "*" ? selectors["*"] : selectors.type(cap2);
410322
410479
  }
410323
- if (cap[1]) {
410324
- return cap[1][0] === "." ? selectors.attr("class", "~=", decodeid(cap[1].substring(1)), false) : selectors.attr("id", "=", decodeid(cap[1].substring(1)), false);
410480
+ if (cap2[1]) {
410481
+ return cap2[1][0] === "." ? selectors.attr("class", "~=", decodeid(cap2[1].substring(1)), false) : selectors.attr("id", "=", decodeid(cap2[1].substring(1)), false);
410325
410482
  }
410326
- if (cap[2]) {
410327
- return cap[3] ? selectors[decodeid(cap[2])](unquote(cap[3])) : selectors[decodeid(cap[2])];
410483
+ if (cap2[2]) {
410484
+ return cap2[3] ? selectors[decodeid(cap2[2])](unquote(cap2[3])) : selectors[decodeid(cap2[2])];
410328
410485
  }
410329
- if (cap[4]) {
410330
- var value = cap[6];
410486
+ if (cap2[4]) {
410487
+ var value = cap2[6];
410331
410488
  var i = /["'\s]\s*I$/i.test(value);
410332
410489
  if (i) {
410333
410490
  value = value.replace(/\s*I$/i, "");
410334
410491
  }
410335
- return selectors.attr(decodeid(cap[4]), cap[5] || "-", unquote(value), i);
410492
+ return selectors.attr(decodeid(cap2[4]), cap2[5] || "-", unquote(value), i);
410336
410493
  }
410337
410494
  throw new SyntaxError("Unknown Selector.");
410338
410495
  };
@@ -458721,6 +458878,26 @@ var init_classifierDecision = __esm({
458721
458878
  });
458722
458879
 
458723
458880
  // build-src/src/utils/permissions/permissions.ts
458881
+ var permissions_exports2 = {};
458882
+ __export(permissions_exports2, {
458883
+ applyPermissionRulesToPermissionContext: () => applyPermissionRulesToPermissionContext,
458884
+ checkRuleBasedPermissions: () => checkRuleBasedPermissions,
458885
+ createPermissionRequestMessage: () => createPermissionRequestMessage,
458886
+ deletePermissionRule: () => deletePermissionRule,
458887
+ filterDeniedAgents: () => filterDeniedAgents,
458888
+ getAllowRules: () => getAllowRules,
458889
+ getAskRuleForTool: () => getAskRuleForTool,
458890
+ getAskRules: () => getAskRules,
458891
+ getDenyRuleForAgent: () => getDenyRuleForAgent,
458892
+ getDenyRuleForTool: () => getDenyRuleForTool,
458893
+ getDenyRules: () => getDenyRules,
458894
+ getRuleByContentsForTool: () => getRuleByContentsForTool,
458895
+ getRuleByContentsForToolName: () => getRuleByContentsForToolName,
458896
+ hasPermissionsToUseTool: () => hasPermissionsToUseTool,
458897
+ permissionRuleSourceDisplayString: () => permissionRuleSourceDisplayString,
458898
+ syncPermissionRulesFromDisk: () => syncPermissionRulesFromDisk,
458899
+ toolAlwaysAllowedRule: () => toolAlwaysAllowedRule
458900
+ });
458724
458901
  function permissionRuleSourceDisplayString(source) {
458725
458902
  return getSettingSourceDisplayNameLowercase(source);
458726
458903
  }
@@ -458999,6 +459176,57 @@ Latest blocked action: ${classifierReason}`
458999
459176
  }
459000
459177
  };
459001
459178
  }
459179
+ async function checkRuleBasedPermissions(tool, input, context3) {
459180
+ const appState = context3.getAppState();
459181
+ const denyRule = getDenyRuleForTool(appState.toolPermissionContext, tool);
459182
+ if (denyRule) {
459183
+ return {
459184
+ behavior: "deny",
459185
+ decisionReason: {
459186
+ type: "rule",
459187
+ rule: denyRule
459188
+ },
459189
+ message: `Permission to use ${tool.name} has been denied.`
459190
+ };
459191
+ }
459192
+ const askRule = getAskRuleForTool(appState.toolPermissionContext, tool);
459193
+ if (askRule) {
459194
+ const canSandboxAutoAllow = tool.name === BASH_TOOL_NAME && SandboxManager2.isSandboxingEnabled() && SandboxManager2.isAutoAllowBashIfSandboxedEnabled() && shouldUseSandbox(input);
459195
+ if (!canSandboxAutoAllow) {
459196
+ return {
459197
+ behavior: "ask",
459198
+ decisionReason: {
459199
+ type: "rule",
459200
+ rule: askRule
459201
+ },
459202
+ message: createPermissionRequestMessage(tool.name)
459203
+ };
459204
+ }
459205
+ }
459206
+ let toolPermissionResult = {
459207
+ behavior: "passthrough",
459208
+ message: createPermissionRequestMessage(tool.name)
459209
+ };
459210
+ try {
459211
+ const parsedInput = tool.inputSchema.parse(input);
459212
+ toolPermissionResult = await tool.checkPermissions(parsedInput, context3);
459213
+ } catch (e) {
459214
+ if (e instanceof AbortError || e instanceof APIUserAbortError) {
459215
+ throw e;
459216
+ }
459217
+ logError(e);
459218
+ }
459219
+ if (toolPermissionResult?.behavior === "deny") {
459220
+ return toolPermissionResult;
459221
+ }
459222
+ if (toolPermissionResult?.behavior === "ask" && toolPermissionResult.decisionReason?.type === "rule" && toolPermissionResult.decisionReason.rule.ruleBehavior === "ask") {
459223
+ return toolPermissionResult;
459224
+ }
459225
+ if (toolPermissionResult?.behavior === "ask" && toolPermissionResult.decisionReason?.type === "safetyCheck") {
459226
+ return toolPermissionResult;
459227
+ }
459228
+ return null;
459229
+ }
459002
459230
  async function hasPermissionsToUseToolInner(tool, input, context3) {
459003
459231
  if (context3.abortController.signal.aborted) {
459004
459232
  throw new AbortError();
@@ -501978,8 +502206,8 @@ var init_sema_brand = __esm({
501978
502206
  "Bulk stop now lists the rows it could not stop with a named reason, and quota/scenario refusals carry a plain-language line next to the machine-readable error"
501979
502207
  ]
501980
502208
  },
501981
- productVersion: "1.0.67",
501982
- announcement: 'sema 1.0.67 \u2014 Final verification is now OFF by default for -p runs: it could overwrite a correct result while re-checking it; opt in with --final-verify or SEMA_HEADLESS_FINAL_VERIFY=true. --max-tokens now actually enforces a token budget (the old wire key was never adopted by the engine \u2014 requests silently ran unbounded; the run now fails loudly with partial output when the budget is hit). A sub-agent that pauses at an approval gate is reported honestly end-to-end (engine-side fix; the shell-side workaround was removed), and when the session is locked by an active run, every message now shows the concrete way out instead of a bare busy error. Engine crash recovery is bounded: after ~35 minutes of automatic retries sema stops, tells you how long it tried, and leaves a working manual retry. Workflow agent details now show "requested <model> \u2192 running on <model>" when a delegated agent ran on a different model than asked. Engine 6.4.0, core 5.10.0, SDK 6.3.0, client-core 0.17.1, registry-core 0.14.0.'
502209
+ productVersion: "1.0.68",
502210
+ announcement: "sema 1.0.68 \u2014 Approvals got faster and quieter: permission rules you save in settings.json (permissions.allow/deny/ask) now actually apply in the interactive REPL, and a remembered allow rule answers the engine's approval gate instantly \u2014 no card, no pause, no suspend penalty. Reading your own config directory (~/.sema) no longer triggers a permission prompt on every read (engine 6.6.0 read-only whitelist); writes still ask. A background-task daemon that starts slowly on a cold machine is no longer misreported as crashed (startup window 6s \u2192 15s, and the error now distinguishes slow from dead). The setup wizard renders correctly in narrow 80-column terminals (help text word-wraps instead of losing the end of sentences) and no longer scrambles the option list if you paste an extremely long endpoint URL. Engine 6.6.0, core 5.11.0, SDK 6.5.0, client-core 0.17.1, registry-core 0.14.0."
501983
502211
  };
501984
502212
  }
501985
502213
  });
@@ -508313,8 +508541,8 @@ var require_sema_brand = __commonJS({
508313
508541
  "Bulk stop now lists the rows it could not stop with a named reason, and quota/scenario refusals carry a plain-language line next to the machine-readable error"
508314
508542
  ]
508315
508543
  },
508316
- productVersion: "1.0.67",
508317
- announcement: 'sema 1.0.67 \u2014 Final verification is now OFF by default for -p runs: it could overwrite a correct result while re-checking it; opt in with --final-verify or SEMA_HEADLESS_FINAL_VERIFY=true. --max-tokens now actually enforces a token budget (the old wire key was never adopted by the engine \u2014 requests silently ran unbounded; the run now fails loudly with partial output when the budget is hit). A sub-agent that pauses at an approval gate is reported honestly end-to-end (engine-side fix; the shell-side workaround was removed), and when the session is locked by an active run, every message now shows the concrete way out instead of a bare busy error. Engine crash recovery is bounded: after ~35 minutes of automatic retries sema stops, tells you how long it tried, and leaves a working manual retry. Workflow agent details now show "requested <model> \u2192 running on <model>" when a delegated agent ran on a different model than asked. Engine 6.4.0, core 5.10.0, SDK 6.3.0, client-core 0.17.1, registry-core 0.14.0.'
508544
+ productVersion: "1.0.68",
508545
+ announcement: "sema 1.0.68 \u2014 Approvals got faster and quieter: permission rules you save in settings.json (permissions.allow/deny/ask) now actually apply in the interactive REPL, and a remembered allow rule answers the engine's approval gate instantly \u2014 no card, no pause, no suspend penalty. Reading your own config directory (~/.sema) no longer triggers a permission prompt on every read (engine 6.6.0 read-only whitelist); writes still ask. A background-task daemon that starts slowly on a cold machine is no longer misreported as crashed (startup window 6s \u2192 15s, and the error now distinguishes slow from dead). The setup wizard renders correctly in narrow 80-column terminals (help text word-wraps instead of losing the end of sentences) and no longer scrambles the option list if you paste an extremely long endpoint URL. Engine 6.6.0, core 5.11.0, SDK 6.5.0, client-core 0.17.1, registry-core 0.14.0."
508318
508546
  };
508319
508547
  }
508320
508548
  });
@@ -508376,12 +508604,12 @@ function dropTextInBriefTurns(messages, briefToolNames) {
508376
508604
  return t2 === void 0 || !turnsWithBrief.has(t2);
508377
508605
  });
508378
508606
  }
508379
- function computeSliceStart(collapsed, anchorRef, cap = MAX_MESSAGES_WITHOUT_VIRTUALIZATION, step = MESSAGE_CAP_STEP) {
508607
+ function computeSliceStart(collapsed, anchorRef, cap2 = MAX_MESSAGES_WITHOUT_VIRTUALIZATION, step = MESSAGE_CAP_STEP) {
508380
508608
  const anchor = anchorRef.current;
508381
508609
  const anchorIdx = anchor ? collapsed.findIndex((m2) => m2.uuid === anchor.uuid) : -1;
508382
- let start = anchorIdx >= 0 ? anchorIdx : anchor ? Math.min(anchor.idx, Math.max(0, collapsed.length - cap)) : 0;
508383
- if (collapsed.length - start > cap + step) {
508384
- start = collapsed.length - cap;
508610
+ let start = anchorIdx >= 0 ? anchorIdx : anchor ? Math.min(anchor.idx, Math.max(0, collapsed.length - cap2)) : 0;
508611
+ if (collapsed.length - start > cap2 + step) {
508612
+ start = collapsed.length - cap2;
508385
508613
  }
508386
508614
  const msgAtStart = collapsed[start];
508387
508615
  if (msgAtStart && (anchor?.uuid !== msgAtStart.uuid || anchor.idx !== start)) {
@@ -529261,8 +529489,8 @@ var init_PermissionRuleList = __esm({
529261
529489
  });
529262
529490
 
529263
529491
  // build-src/src/commands/permissions/permissions.tsx
529264
- var permissions_exports2 = {};
529265
- __export(permissions_exports2, {
529492
+ var permissions_exports3 = {};
529493
+ __export(permissions_exports3, {
529266
529494
  call: () => call46
529267
529495
  });
529268
529496
  var import_jsx_runtime307, call46;
@@ -529289,7 +529517,7 @@ var init_permissions4 = __esm({
529289
529517
  aliases: ["allowed-tools"],
529290
529518
  // 218 parity (aligned 2026-07-24, F8b): "and", not "&".
529291
529519
  description: "Manage allow and deny tool permission rules",
529292
- load: () => Promise.resolve().then(() => (init_permissions3(), permissions_exports2))
529520
+ load: () => Promise.resolve().then(() => (init_permissions3(), permissions_exports3))
529293
529521
  };
529294
529522
  permissions_default = permissions;
529295
529523
  }
@@ -547647,6 +547875,38 @@ var init_agentMemory = __esm({
547647
547875
  });
547648
547876
 
547649
547877
  // build-src/src/utils/permissions/filesystem.ts
547878
+ var filesystem_exports = {};
547879
+ __export(filesystem_exports, {
547880
+ DANGEROUS_DIRECTORIES: () => DANGEROUS_DIRECTORIES2,
547881
+ DANGEROUS_FILES: () => DANGEROUS_FILES2,
547882
+ allWorkingDirectories: () => allWorkingDirectories,
547883
+ checkEditableInternalPath: () => checkEditableInternalPath,
547884
+ checkPathSafetyForAutoEdit: () => checkPathSafetyForAutoEdit,
547885
+ checkReadPermissionForTool: () => checkReadPermissionForTool,
547886
+ checkReadableInternalPath: () => checkReadableInternalPath,
547887
+ checkWritePermissionForTool: () => checkWritePermissionForTool,
547888
+ ensureScratchpadDir: () => ensureScratchpadDir,
547889
+ generateSuggestions: () => generateSuggestions,
547890
+ getBundledSkillsRoot: () => getBundledSkillsRoot,
547891
+ getClaudeSkillScope: () => getClaudeSkillScope,
547892
+ getClaudeTempDir: () => getClaudeTempDir,
547893
+ getClaudeTempDirName: () => getClaudeTempDirName,
547894
+ getFileReadIgnorePatterns: () => getFileReadIgnorePatterns,
547895
+ getProjectTempDir: () => getProjectTempDir,
547896
+ getResolvedWorkingDirPaths: () => getResolvedWorkingDirPaths,
547897
+ getScratchpadDir: () => getScratchpadDir,
547898
+ getSessionMemoryDir: () => getSessionMemoryDir,
547899
+ getSessionMemoryPath: () => getSessionMemoryPath,
547900
+ isClaudeSettingsPath: () => isClaudeSettingsPath,
547901
+ isScratchpadEnabled: () => isScratchpadEnabled,
547902
+ matchingRuleForInput: () => matchingRuleForInput,
547903
+ normalizeCaseForComparison: () => normalizeCaseForComparison2,
547904
+ normalizePatternsToPath: () => normalizePatternsToPath,
547905
+ pathInAllowedWorkingPath: () => pathInAllowedWorkingPath,
547906
+ pathInWorkingPath: () => pathInWorkingPath,
547907
+ relativePath: () => relativePath,
547908
+ toPosixPath: () => toPosixPath
547909
+ });
547650
547910
  import { randomBytes as randomBytes21 } from "crypto";
547651
547911
  import { homedir as homedir42, tmpdir as tmpdir14 } from "os";
547652
547912
  import { join as join166, normalize as normalize17, posix as posix8, sep as sep36 } from "path";
@@ -568986,6 +569246,7 @@ var init_background_agent_store = __esm({
568986
569246
  "errorCode",
568987
569247
  "errorRetryable",
568988
569248
  "errorKind",
569249
+ "errorRetryAfterMs",
568989
569250
  "resultIsPartial",
568990
569251
  "summary",
568991
569252
  "recentSteps",
@@ -569286,10 +569547,10 @@ function statusFromBackground(status3, exitCode) {
569286
569547
  return exitCode === 0 ? "completed" : "failed";
569287
569548
  return "failed";
569288
569549
  }
569289
- function rollSpoolText(spool, s, cap, onDrop) {
569290
- if (s.length <= cap)
569550
+ function rollSpoolText(spool, s, cap2, onDrop) {
569551
+ if (s.length <= cap2)
569291
569552
  return s;
569292
- const half = Math.floor(cap / 2);
569553
+ const half = Math.floor(cap2 / 2);
569293
569554
  const dropped2 = s.slice(half, s.length - half);
569294
569555
  spool.rolledChars += dropped2.length;
569295
569556
  onDrop?.(dropped2);
@@ -570813,6 +571074,8 @@ function settleBackgroundAgentLane(core, id, outcome) {
570813
571074
  handle2.errorRetryable = outcome.retryable;
570814
571075
  if (outcome.errorKind !== void 0)
570815
571076
  handle2.errorKind = outcome.errorKind;
571077
+ if (outcome.retryAfterMs !== void 0)
571078
+ handle2.errorRetryAfterMs = outcome.retryAfterMs;
570816
571079
  }
570817
571080
  handle2.updatedAt = Date.now();
570818
571081
  if (outcome.seq !== void 0)
@@ -570830,7 +571093,8 @@ function settleBackgroundAgentLane(core, id, outcome) {
570830
571093
  ...handle2.error !== void 0 ? { error: handle2.error } : {},
570831
571094
  ...handle2.errorCode !== void 0 ? { errorCode: handle2.errorCode } : {},
570832
571095
  ...handle2.errorRetryable !== void 0 ? { errorRetryable: handle2.errorRetryable } : {},
570833
- ...handle2.errorKind !== void 0 ? { errorKind: handle2.errorKind } : {}
571096
+ ...handle2.errorKind !== void 0 ? { errorKind: handle2.errorKind } : {},
571097
+ ...handle2.errorRetryAfterMs !== void 0 ? { errorRetryAfterMs: handle2.errorRetryAfterMs } : {}
570834
571098
  }, ["parkedCheckpointToken", "parkClaimId", "parkedAt"]);
570835
571099
  return outcome.status;
570836
571100
  }
@@ -570957,6 +571221,7 @@ function reviveBackgroundAgentLane(core, id, access7, abort) {
570957
571221
  handle2.errorCode = void 0;
570958
571222
  handle2.errorRetryable = void 0;
570959
571223
  handle2.errorKind = void 0;
571224
+ handle2.errorRetryAfterMs = void 0;
570960
571225
  handle2.resultIsPartial = void 0;
570961
571226
  handle2.stopSource = void 0;
570962
571227
  handle2.completionId = void 0;
@@ -571141,6 +571406,7 @@ function buildAgentPollDetails(input) {
571141
571406
  ...failed && input.error !== void 0 ? { error: delimitUntrusted("agent error", boundedRedactedSummary(input.error, 300)) } : {},
571142
571407
  ...failed && input.errorCode !== void 0 ? { errorCode: input.errorCode } : {},
571143
571408
  ...failed && input.errorRetryable !== void 0 ? { retryable: input.errorRetryable } : {},
571409
+ ...failed && input.errorRetryAfterMs !== void 0 ? { retryAfterMs: input.errorRetryAfterMs } : {},
571144
571410
  ...input.resultIsPartial === true ? { partial_result: true } : {},
571145
571411
  ...input.completionId !== void 0 ? { completionId: input.completionId } : {}
571146
571412
  };
@@ -571158,7 +571424,7 @@ The agent is durably suspended, waiting for an approval decision. It resumes whe
571158
571424
  })
571159
571425
  };
571160
571426
  }
571161
- const kindClause = row2.status === "failed" && row2.errorKind !== void 0 && row2.errorRetryable !== void 0 ? ` (error_kind: ${row2.errorKind}, retryable: ${row2.errorRetryable})` : "";
571427
+ const kindClause = row2.status === "failed" && row2.errorKind !== void 0 && row2.errorRetryable !== void 0 ? ` (error_kind: ${row2.errorKind}, retryable: ${row2.errorRetryable}${row2.errorRetryAfterMs !== void 0 ? `, retry_after_ms: ${row2.errorRetryAfterMs}` : ""})` : "";
571162
571428
  const body = `status: ${row2.status}
571163
571429
  ${row2.error ? `error: ${row2.error}${kindClause}
571164
571430
  ` : ""}${row2.finalOutput ? `--- result${row2.resultIsPartial ? " (partial \u2014 produced before the task was stopped)" : ""} ---
@@ -571174,6 +571440,7 @@ ${clipTaskOutput(row2.finalOutputFull ?? row2.finalOutput)}` : "(no result text)
571174
571440
  ...row2.error !== void 0 ? { error: row2.error } : {},
571175
571441
  ...row2.errorCode !== void 0 ? { errorCode: row2.errorCode } : {},
571176
571442
  ...row2.errorRetryable !== void 0 ? { errorRetryable: row2.errorRetryable } : {},
571443
+ ...row2.errorRetryAfterMs !== void 0 ? { errorRetryAfterMs: row2.errorRetryAfterMs } : {},
571177
571444
  ...row2.resultIsPartial === true ? { resultIsPartial: true } : {},
571178
571445
  ...row2.completionId !== void 0 ? { completionId: row2.completionId } : {}
571179
571446
  }),
@@ -571214,7 +571481,7 @@ The agent is durably suspended, waiting for an approval decision. It resumes whe
571214
571481
  }
571215
571482
  const fullResult = handle2.result ? handle2.resultFull ?? handle2.result : void 0;
571216
571483
  const resultText = fullResult !== void 0 ? await spillClippedAgentResult(handle2, fullResult, clipTaskOutput(fullResult, handle2.outputFile), store, sessionId) : void 0;
571217
- const kindClause = handle2.status === "failed" && handle2.errorKind !== void 0 && handle2.errorRetryable !== void 0 ? ` (error_kind: ${handle2.errorKind}, retryable: ${handle2.errorRetryable})` : "";
571484
+ const kindClause = handle2.status === "failed" && handle2.errorKind !== void 0 && handle2.errorRetryable !== void 0 ? ` (error_kind: ${handle2.errorKind}, retryable: ${handle2.errorRetryable}${handle2.errorRetryAfterMs !== void 0 ? `, retry_after_ms: ${handle2.errorRetryAfterMs}` : ""})` : "";
571218
571485
  const body = running ? oneShot === true ? `status: running
571219
571486
  This is a ONE-SHOT submission \u2014 there is no later turn for a background notification to land in, so do NOT end your turn expecting one. Actively wait instead: TaskOutput({ task_id: "${handle2.id}", block: true }). If it is still running after the wait, wait again (bounded) rather than ending the turn, or write out your best available answer now if you are near your own time budget.` : `status: running
571220
571487
  The agent is still working \u2014 you will be notified when it completes.` : `status: ${handle2.status}
@@ -571232,6 +571499,7 @@ ${resultText}` : "(no result text)"}`;
571232
571499
  ...handle2.error !== void 0 ? { error: handle2.error } : {},
571233
571500
  ...handle2.errorCode !== void 0 ? { errorCode: handle2.errorCode } : {},
571234
571501
  ...handle2.errorRetryable !== void 0 ? { errorRetryable: handle2.errorRetryable } : {},
571502
+ ...handle2.errorRetryAfterMs !== void 0 ? { errorRetryAfterMs: handle2.errorRetryAfterMs } : {},
571235
571503
  ...handle2.resultIsPartial === true ? { resultIsPartial: true } : {},
571236
571504
  ...handle2.completionId !== void 0 ? { completionId: handle2.completionId } : {}
571237
571505
  }),
@@ -571405,9 +571673,9 @@ async function drainBashTailBestEffort(handle2) {
571405
571673
  if (drained.ok && (drained.value.stdout.length > 0 || drained.value.stderr.length > 0)) {
571406
571674
  if (handle2.spool !== void 0) {
571407
571675
  const spool = handle2.spool;
571408
- const cap = 2 * TASK_OUTPUT_MAX_CHARS;
571409
- spool.stdout = rollSpoolText(spool, spool.stdout + drained.value.stdout, cap);
571410
- spool.stderr = rollSpoolText(spool, spool.stderr + drained.value.stderr, cap);
571676
+ const cap2 = 2 * TASK_OUTPUT_MAX_CHARS;
571677
+ spool.stdout = rollSpoolText(spool, spool.stdout + drained.value.stdout, cap2);
571678
+ spool.stderr = rollSpoolText(spool, spool.stderr + drained.value.stderr, cap2);
571411
571679
  const ap = await handle2.env.appendFile(handle2.outputFile, drained.value.stdout + drained.value.stderr);
571412
571680
  if (!ap.ok)
571413
571681
  spool.mirrorFailed = true;
@@ -573880,7 +574148,7 @@ var init_skills_directory = __esm({
573880
574148
  });
573881
574149
 
573882
574150
  // node_modules/@sema-agent/core/dist/tools/web.js
573883
- var DEFAULT_MAX_BYTES, ERROR_BODY_CONVERT_MAX_CHARS, HTML_CONVERT_MAX_CHARS;
574151
+ var DEFAULT_MAX_BYTES, GROUNDING_RATIO_MAX_TEXT_CHARS, GROUNDING_ECHO_MAX_CHARS, ERROR_BODY_CONVERT_MAX_CHARS, HTML_CONVERT_MAX_CHARS;
573884
574152
  var init_web = __esm({
573885
574153
  "node_modules/@sema-agent/core/dist/tools/web.js"() {
573886
574154
  init_build3();
@@ -573891,6 +574159,8 @@ var init_web = __esm({
573891
574159
  init_safety();
573892
574160
  init_pdf2();
573893
574161
  DEFAULT_MAX_BYTES = 2 * 1024 * 1024;
574162
+ GROUNDING_RATIO_MAX_TEXT_CHARS = 2e3;
574163
+ GROUNDING_ECHO_MAX_CHARS = GROUNDING_RATIO_MAX_TEXT_CHARS + 100;
573894
574164
  ERROR_BODY_CONVERT_MAX_CHARS = 64 * 1024;
573895
574165
  HTML_CONVERT_MAX_CHARS = 256 * 1024;
573896
574166
  }
@@ -589795,7 +590065,7 @@ async function startWorkPollLoop({
589795
590065
  if (hbConfig.non_exclusive_heartbeat_interval_ms <= 0) break;
589796
590066
  const info = getHeartbeatInfo();
589797
590067
  if (!info) break;
589798
- const cap = capacitySignal();
590068
+ const cap2 = capacitySignal();
589799
590069
  try {
589800
590070
  await api2.heartbeatWork(
589801
590071
  info.environmentId,
@@ -589807,7 +590077,7 @@ async function startWorkPollLoop({
589807
590077
  `[bridge:repl:heartbeat] Failed: ${errorMessage(err8)}`
589808
590078
  );
589809
590079
  if (err8 instanceof BridgeFatalError) {
589810
- cap.cleanup();
590080
+ cap2.cleanup();
589811
590081
  logEvent("tengu_bridge_heartbeat_error", {
589812
590082
  status: err8.status,
589813
590083
  error_type: err8.status === 401 || err8.status === 403 ? "auth_failed" : "fatal"
@@ -589826,9 +590096,9 @@ async function startWorkPollLoop({
589826
590096
  hbCycles++;
589827
590097
  await sleep2(
589828
590098
  hbConfig.non_exclusive_heartbeat_interval_ms,
589829
- cap.signal
590099
+ cap2.signal
589830
590100
  );
589831
- cap.cleanup();
590101
+ cap2.cleanup();
589832
590102
  }
589833
590103
  const exitReason = needsBackoff ? "error" : signal.aborted ? "shutdown" : !isAtCapacity() ? "capacity_changed" : pollDeadline !== null && Date.now() >= pollDeadline ? "poll_due" : "config_disabled";
589834
590104
  logEvent("tengu_bridge_heartbeat_mode_exited", {
@@ -589846,10 +590116,10 @@ async function startWorkPollLoop({
589846
590116
  }
589847
590117
  const sleepMs2 = atCapMs > 0 ? atCapMs : pollConfig.non_exclusive_heartbeat_interval_ms;
589848
590118
  if (sleepMs2 > 0) {
589849
- const cap = capacitySignal();
590119
+ const cap2 = capacitySignal();
589850
590120
  const sleepStart = Date.now();
589851
- await sleep2(sleepMs2, cap.signal);
589852
- cap.cleanup();
590121
+ await sleep2(sleepMs2, cap2.signal);
590122
+ cap2.cleanup();
589853
590123
  const overrun = Date.now() - sleepStart - sleepMs2;
589854
590124
  if (overrun > 6e4) {
589855
590125
  logForDebugging(
@@ -616922,7 +617192,7 @@ function pickDiverseCoreFiles(sortedPaths, want) {
616922
617192
  const picked = [];
616923
617193
  const seenBasenames = /* @__PURE__ */ new Set();
616924
617194
  const dirTally = /* @__PURE__ */ new Map();
616925
- for (let cap = 1; picked.length < want && cap <= want; cap++) {
617195
+ for (let cap2 = 1; picked.length < want && cap2 <= want; cap2++) {
616926
617196
  for (const p of sortedPaths) {
616927
617197
  if (picked.length >= want) break;
616928
617198
  if (!isCoreFile(p)) continue;
@@ -616930,7 +617200,7 @@ function pickDiverseCoreFiles(sortedPaths, want) {
616930
617200
  const base = lastSep >= 0 ? p.slice(lastSep + 1) : p;
616931
617201
  if (!base || seenBasenames.has(base)) continue;
616932
617202
  const dir = lastSep >= 0 ? p.slice(0, lastSep) : ".";
616933
- if ((dirTally.get(dir) ?? 0) >= cap) continue;
617203
+ if ((dirTally.get(dir) ?? 0) >= cap2) continue;
616934
617204
  picked.push(base);
616935
617205
  seenBasenames.add(base);
616936
617206
  dirTally.set(dir, (dirTally.get(dir) ?? 0) + 1);
@@ -623706,7 +623976,7 @@ function createPermissionContext(tool, input, toolUseContext, assistantMessage,
623706
623976
  if (tool.name !== BASH_TOOL_NAME3 || !pendingClassifierCheck) {
623707
623977
  return null;
623708
623978
  }
623709
- const classifierDecision = await awaitClassifierAutoApproval2(
623979
+ const classifierDecision = await awaitClassifierAutoApproval3(
623710
623980
  pendingClassifierCheck,
623711
623981
  toolUseContext.abortController.signal,
623712
623982
  toolUseContext.options.isNonInteractiveSession
@@ -624151,7 +624421,7 @@ function handleInteractivePermission(params, resolve57) {
624151
624421
  }
624152
624422
  if (false) {
624153
624423
  setClassifierChecking2(ctx.toolUseID);
624154
- void executeAsyncClassifierCheck(
624424
+ void executeAsyncClassifierCheck2(
624155
624425
  result.pendingClassifierCheck,
624156
624426
  ctx.toolUseContext.abortController.signal,
624157
624427
  ctx.toolUseContext.options.isNonInteractiveSession,
@@ -624427,14 +624697,14 @@ function useCanUseTool(setToolUseConfirmQueue, setToolPermissionContext) {
624427
624697
  return;
624428
624698
  }
624429
624699
  if (false) {
624430
- const speculativePromise = peekSpeculativeClassifierCheck(input.command);
624700
+ const speculativePromise = peekSpeculativeClassifierCheck2(input.command);
624431
624701
  if (speculativePromise) {
624432
624702
  const raceResult = await Promise.race([speculativePromise.then(_temp), new Promise(_temp2)]);
624433
624703
  if (ctx.resolveIfAborted(resolve57)) {
624434
624704
  return;
624435
624705
  }
624436
624706
  if (raceResult.type === "result" && raceResult.result.matches && raceResult.result.confidence === "high" && false) {
624437
- consumeSpeculativeClassifierCheck(input.command);
624707
+ consumeSpeculativeClassifierCheck2(input.command);
624438
624708
  const matchedRule = raceResult.result.matchedDescription ?? void 0;
624439
624709
  if (matchedRule) {
624440
624710
  setClassifierApproval3(toolUseID, matchedRule);
@@ -636071,16 +636341,16 @@ function computeWheelStep(state4, dir, now2) {
636071
636341
  }
636072
636342
  if (state4.wheelMode) {
636073
636343
  const m2 = Math.pow(0.5, gap2 / WHEEL_DECAY_HALFLIFE_MS);
636074
- const cap = Math.max(WHEEL_MODE_CAP, state4.base * 2);
636344
+ const cap2 = Math.max(WHEEL_MODE_CAP, state4.base * 2);
636075
636345
  const next = 1 + (state4.mult - 1) * m2 + WHEEL_MODE_STEP * m2;
636076
- state4.mult = Math.min(cap, next, state4.mult + WHEEL_MODE_RAMP);
636346
+ state4.mult = Math.min(cap2, next, state4.mult + WHEEL_MODE_RAMP);
636077
636347
  return Math.floor(state4.mult);
636078
636348
  }
636079
636349
  if (gap2 > WHEEL_ACCEL_WINDOW_MS) {
636080
636350
  state4.mult = state4.base;
636081
636351
  } else {
636082
- const cap = Math.max(WHEEL_ACCEL_MAX, state4.base * 2);
636083
- state4.mult = Math.min(cap, state4.mult + WHEEL_ACCEL_STEP);
636352
+ const cap2 = Math.max(WHEEL_ACCEL_MAX, state4.base * 2);
636353
+ state4.mult = Math.min(cap2, state4.mult + WHEEL_ACCEL_STEP);
636084
636354
  }
636085
636355
  return Math.floor(state4.mult);
636086
636356
  }
@@ -636094,8 +636364,8 @@ function computeWheelStep(state4, dir, now2) {
636094
636364
  state4.frac = 0;
636095
636365
  } else {
636096
636366
  const m2 = Math.pow(0.5, gap / WHEEL_DECAY_HALFLIFE_MS);
636097
- const cap = gap >= WHEEL_DECAY_GAP_MS ? WHEEL_DECAY_CAP_SLOW : WHEEL_DECAY_CAP_FAST;
636098
- state4.mult = Math.min(cap, 1 + (state4.mult - 1) * m2 + WHEEL_DECAY_STEP * m2);
636367
+ const cap2 = gap >= WHEEL_DECAY_GAP_MS ? WHEEL_DECAY_CAP_SLOW : WHEEL_DECAY_CAP_FAST;
636368
+ state4.mult = Math.min(cap2, 1 + (state4.mult - 1) * m2 + WHEEL_DECAY_STEP * m2);
636099
636369
  }
636100
636370
  const total = state4.mult + state4.frac;
636101
636371
  const rows2 = Math.floor(total);
@@ -644614,9 +644884,9 @@ be shared and iterated on outside the terminal:
644614
644884
  Skip this step if the review was invoked only to feed another tool (e.g. a
644615
644885
  workflow step whose caller handles its own output).
644616
644886
  `;
644617
- outputAsJson = (cap) => `## Output
644887
+ outputAsJson = (cap2) => `## Output
644618
644888
 
644619
- Return findings as a JSON array of at most ${cap} objects:
644889
+ Return findings as a JSON array of at most ${cap2} objects:
644620
644890
 
644621
644891
  \`\`\`json
644622
644892
  [
@@ -644629,19 +644899,19 @@ Return findings as a JSON array of at most ${cap} objects:
644629
644899
  ]
644630
644900
  \`\`\`
644631
644901
 
644632
- Ranked most-severe first. If more than ${cap} survive, keep the ${cap} most
644902
+ Ranked most-severe first. If more than ${cap2} survive, keep the ${cap2} most
644633
644903
  severe. If nothing survives verification, return \`[]\`.
644634
644904
  `;
644635
- outputViaReportFindings = (cap) => `## Output
644905
+ outputViaReportFindings = (cap2) => `## Output
644636
644906
 
644637
644907
  Call the ${REPORT_FINDINGS_TOOL_NAME} tool once to report this review's results
644638
- with \`{level, findings}\`. \`findings\` is at most ${cap} entries ranked
644908
+ with \`{level, findings}\`. \`findings\` is at most ${cap2} entries ranked
644639
644909
  most-severe first; each entry has \`file\`, \`line\`, \`summary\`,
644640
644910
  \`failure_scenario\`, and \`category\` \u2014 a short kebab-case slug for the angle
644641
644911
  that produced it (\`correctness\`, \`simplification\`, \`efficiency\`,
644642
644912
  \`reuse\`, \`altitude\`, \`conventions\`, or a more specific slug like
644643
644913
  \`test-coverage\` when one fits better) \u2014 plus \`verdict\` when a verify pass
644644
- produced one. If more than ${cap} survive, keep the ${cap} most severe. If
644914
+ produced one. If more than ${cap2} survive, keep the ${cap2} most severe. If
644645
644915
  nothing survives verification, call it with an empty array. Do not also print
644646
644916
  the findings as text.
644647
644917
  `;
@@ -644809,14 +645079,14 @@ Output at most **8 findings**, most-severe first, one line each:
644809
645079
  \`path/to/file.ext:123 \u2014 what's wrong and the concrete failure\`.
644810
645080
  Target at least min(files_changed, 4) findings \u2014 if you see fewer, widen to other hunks in the same diff before stopping. If fewer than 4 genuine findings exist, emit what you have.
644811
645081
  `;
644812
- withRecallFloor = (output) => (cap) => output(cap).replace(
645082
+ withRecallFloor = (output) => (cap2) => output(cap2).replace(
644813
645083
  "## Output\n",
644814
645084
  `## Output
644815
645085
 
644816
- Target **at least ${Math.floor(cap / 2)} findings**. If fewer genuine findings exist, emit what you have \u2014 do not invent to hit the floor.
645086
+ Target **at least ${Math.floor(cap2 / 2)} findings**. If fewer genuine findings exist, emit what you have \u2014 do not invent to hit the floor.
644817
645087
  `
644818
645088
  ).replace(/nothing survives verification/g, "nothing survives");
644819
- o48Cell = (header, stance, cap) => (output) => `\`${header}\`
645089
+ o48Cell = (header, stance, cap2) => (output) => `\`${header}\`
644820
645090
 
644821
645091
  ${stance}
644822
645092
 
@@ -644841,7 +645111,7 @@ silently drop half-believed candidates are the dominant cause of misses.
644841
645111
 
644842
645112
  Pool all candidates. Dedup near-duplicates only (same defect, same location, same reason \u2192 keep one). Do NOT run verifiers; do NOT re-judge. Sort by severity.
644843
645113
 
644844
- ${withRecallFloor(output)(cap)}`;
645114
+ ${withRecallFloor(output)(cap2)}`;
644845
645115
  cellO48Medium = o48Cell(
644846
645116
  "medium effort \u2192 8 inline angles \u2192 dedup (no verify) \u2192 \u22648 findings",
644847
645117
  `You are reviewing for **correctness bugs**: surface every plausible bug. At this
@@ -651126,6 +651396,141 @@ var init_classifierVerdictWire2 = __esm({
651126
651396
  }
651127
651397
  });
651128
651398
 
651399
+ // build-src/src/sema/engineGateSyncAllow.ts
651400
+ function cap() {
651401
+ if (budgetCap !== null) return budgetCap;
651402
+ const raw2 = process.env.SEMA_GATE_SYNC_ALLOW_BUDGET;
651403
+ const parsed = raw2 !== void 0 && raw2 !== "" ? Number(raw2) : Number.NaN;
651404
+ budgetCap = Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : DEFAULT_BUDGET;
651405
+ return budgetCap;
651406
+ }
651407
+ function readPermissionContext() {
651408
+ try {
651409
+ const state4 = getAppStateStoreRef()?.getState?.();
651410
+ return state4?.toolPermissionContext ?? null;
651411
+ } catch {
651412
+ return null;
651413
+ }
651414
+ }
651415
+ function canonicalToolName(name) {
651416
+ const n2 = name.replace(/[\s_-]+/g, "").toLowerCase();
651417
+ if (n2 === "bash") return { canonical: "Bash", family: "bash" };
651418
+ if (n2 === "write" || n2 === "filewrite") return { canonical: "Write", family: "fsWrite", pathKey: "file_path" };
651419
+ if (n2 === "edit" || n2 === "fileedit") return { canonical: "Edit", family: "fsWrite", pathKey: "file_path" };
651420
+ if (n2 === "multiedit") return { canonical: "MultiEdit", family: "fsWrite", pathKey: "file_path" };
651421
+ if (n2 === "notebookedit")
651422
+ return { canonical: "NotebookEdit", family: "fsWrite", pathKey: "notebook_path" };
651423
+ return { canonical: name, family: "other" };
651424
+ }
651425
+ function permissionsModule() {
651426
+ return init_permissions2(), __toCommonJS(permissions_exports2);
651427
+ }
651428
+ function filesystemModule() {
651429
+ return init_filesystem(), __toCommonJS(filesystem_exports);
651430
+ }
651431
+ function bashPermissionsModule() {
651432
+ return init_bashPermissions(), __toCommonJS(bashPermissions_exports);
651433
+ }
651434
+ function bashVerdict(ctx, args) {
651435
+ const command8 = args.command;
651436
+ if (typeof command8 !== "string" || command8.trim() === "") {
651437
+ return { allow: false, reason: "bash gate carries no command string" };
651438
+ }
651439
+ const result = bashPermissionsModule().bashToolCheckPermission(
651440
+ { command: command8 },
651441
+ ctx
651442
+ );
651443
+ if (result.behavior !== "allow") return { allow: false, reason: `bash rules say ${String(result.behavior)}` };
651444
+ if (result.decisionReason?.type !== "rule") {
651445
+ return { allow: false, reason: `bash allow came from ${String(result.decisionReason?.type)}, not a remembered rule` };
651446
+ }
651447
+ return { allow: true, reason: "remembered Bash allow rule" };
651448
+ }
651449
+ function fsWriteVerdict(ctx, canonical2, pathKey2, args) {
651450
+ const perms = permissionsModule();
651451
+ const tool = { name: canonical2, mcpInfo: void 0 };
651452
+ if (perms.getDenyRuleForTool(ctx, tool) !== null) return { allow: false, reason: "tool-level deny rule" };
651453
+ if (perms.getAskRuleForTool(ctx, tool) !== null) return { allow: false, reason: "tool-level ask rule" };
651454
+ const path28 = args[pathKey2];
651455
+ if (typeof path28 === "string" && path28 !== "") {
651456
+ const fs15 = filesystemModule();
651457
+ if (fs15.matchingRuleForInput(path28, ctx, "edit", "deny") !== null) return { allow: false, reason: "path deny rule" };
651458
+ if (fs15.matchingRuleForInput(path28, ctx, "edit", "ask") !== null) return { allow: false, reason: "path ask rule" };
651459
+ if (fs15.matchingRuleForInput(path28, ctx, "edit", "allow") !== null) {
651460
+ return { allow: true, reason: "remembered path allow rule" };
651461
+ }
651462
+ }
651463
+ if (perms.toolAlwaysAllowedRule(ctx, tool) !== null) {
651464
+ return { allow: true, reason: "remembered whole-tool allow rule" };
651465
+ }
651466
+ return { allow: false, reason: "no remembered allow rule for this write" };
651467
+ }
651468
+ function genericVerdict(ctx, canonical2) {
651469
+ const perms = permissionsModule();
651470
+ const tool = { name: canonical2, mcpInfo: void 0 };
651471
+ if (perms.getDenyRuleForTool(ctx, tool) !== null) return { allow: false, reason: "tool-level deny rule" };
651472
+ if (perms.getAskRuleForTool(ctx, tool) !== null) return { allow: false, reason: "tool-level ask rule" };
651473
+ if (perms.toolAlwaysAllowedRule(ctx, tool) !== null) {
651474
+ return { allow: true, reason: "remembered whole-tool allow rule" };
651475
+ }
651476
+ return { allow: false, reason: "no remembered allow rule for this tool" };
651477
+ }
651478
+ function _evaluateWithContextForTest(ctx, req) {
651479
+ if (ctx === null) return { allow: false, reason: "no toolPermissionContext on this lane" };
651480
+ if (!SYNC_ALLOW_MODES.has(ctx.mode)) return { allow: false, reason: `mode ${ctx.mode} never auto-allows` };
651481
+ if (typeof req.args !== "object" || req.args === null) {
651482
+ return { allow: false, reason: "gate carries no tool input (argsOmitted?)" };
651483
+ }
651484
+ const args = req.args;
651485
+ const { canonical: canonical2, family, pathKey: pathKey2 } = canonicalToolName(req.toolName);
651486
+ try {
651487
+ if (family === "bash") return bashVerdict(ctx, args);
651488
+ if (family === "fsWrite") return fsWriteVerdict(ctx, canonical2, pathKey2 ?? "file_path", args);
651489
+ return genericVerdict(ctx, canonical2);
651490
+ } catch (e) {
651491
+ logForDebugging(`engineGateSyncAllow: rule evaluation threw for "${req.toolName}": ${String(e)}`);
651492
+ return { allow: false, reason: "rule evaluation failed" };
651493
+ }
651494
+ }
651495
+ function evaluateEngineGateSyncAllow(req) {
651496
+ const ctx = readPermissionContext();
651497
+ const verdict = _evaluateWithContextForTest(ctx, req);
651498
+ if (!verdict.allow) {
651499
+ let allowRuleCount = -1;
651500
+ try {
651501
+ if (ctx) allowRuleCount = permissionsModule().getAllowRules(ctx).length;
651502
+ } catch {
651503
+ }
651504
+ logForDebugging(
651505
+ `engineGateSyncAllow: no sync allow for "${req.toolName}" (${verdict.reason}; mode=${ctx?.mode ?? "none"}, allowRules=${allowRuleCount})`
651506
+ );
651507
+ return verdict;
651508
+ }
651509
+ if (budgetUsed >= cap()) {
651510
+ if (!budgetExhaustedLogged) {
651511
+ budgetExhaustedLogged = true;
651512
+ logForDebugging(
651513
+ `engineGateSyncAllow: programmatic-allow budget exhausted (${budgetUsed}/${cap()}) \u2014 every further gate goes back to the approval card`
651514
+ );
651515
+ }
651516
+ return { allow: false, reason: "programmatic-allow budget exhausted" };
651517
+ }
651518
+ budgetUsed++;
651519
+ return verdict;
651520
+ }
651521
+ var SYNC_ALLOW_MODES, DEFAULT_BUDGET, budgetUsed, budgetCap, budgetExhaustedLogged;
651522
+ var init_engineGateSyncAllow = __esm({
651523
+ "build-src/src/sema/engineGateSyncAllow.ts"() {
651524
+ init_appStateRef();
651525
+ init_debug();
651526
+ SYNC_ALLOW_MODES = /* @__PURE__ */ new Set(["default", "acceptEdits", "auto"]);
651527
+ DEFAULT_BUDGET = 100;
651528
+ budgetUsed = 0;
651529
+ budgetCap = null;
651530
+ budgetExhaustedLogged = false;
651531
+ }
651532
+ });
651533
+
651129
651534
  // build-src/src/sema/liveToolApprovalWire.ts
651130
651535
  function toolForName(name) {
651131
651536
  const n2 = name.replace(/[\s_-]+/g, "").toLowerCase();
@@ -651172,6 +651577,13 @@ function shellApprovalCardPort(req) {
651172
651577
  );
651173
651578
  return Promise.resolve({ kind: "deny" });
651174
651579
  }
651580
+ const syncAllow = evaluateEngineGateSyncAllow({ toolName: req.toolName, args: req.args });
651581
+ if (syncAllow.allow) {
651582
+ logForDebugging(
651583
+ `liveToolApprovalWire: gate for "${req.toolName}" auto-allowed synchronously (${syncAllow.reason}) \u2014 no card, no park`
651584
+ );
651585
+ return Promise.resolve({ kind: "allow", allowSession: false });
651586
+ }
651175
651587
  const tool = toolForName(req.toolName);
651176
651588
  if (!tool) {
651177
651589
  return Promise.resolve({ kind: "failed", reason: `no shell tool card for gate tool "${req.toolName}"` });
@@ -651260,6 +651672,7 @@ var init_liveToolApprovalWire = __esm({
651260
651672
  init_PermissionUpdate();
651261
651673
  init_appStateRef();
651262
651674
  init_debug();
651675
+ init_engineGateSyncAllow();
651263
651676
  init_dist();
651264
651677
  asWireTool = (t2) => t2;
651265
651678
  installShellApprovalCardPort();
@@ -651669,6 +652082,12 @@ function toLiveRequest(req, capturedSessionId) {
651669
652082
  } catch {
651670
652083
  }
651671
652084
  }
652085
+ if (out6.additionalReadDirectories === void 0) {
652086
+ try {
652087
+ out6.additionalReadDirectories = [getClaudeConfigHomeDir()];
652088
+ } catch {
652089
+ }
652090
+ }
651672
652091
  if (out6.forwardSubagentEvents === void 0) {
651673
652092
  ;
651674
652093
  out6.forwardSubagentEvents = true;
@@ -651988,6 +652407,7 @@ var init_liveClient = __esm({
651988
652407
  init_sessionStorage();
651989
652408
  init_turnCommitSignal();
651990
652409
  init_appStateRef();
652410
+ init_envUtils();
651991
652411
  init_dist();
651992
652412
  init_agentsWire();
651993
652413
  init_detachWire2();
@@ -652096,9 +652516,9 @@ __export(printStreamJsonContract_exports, {
652096
652516
  import { randomUUID as randomUUID55 } from "crypto";
652097
652517
  function terminalReasonForResult(msg) {
652098
652518
  const code2 = msg.errorCode;
652099
- if (code2 === "limits.max_turns_exceeded") return "max_turns";
652100
- if (code2 === "limits.max_cost_exceeded") return "budget_exhausted";
652101
- if (code2 === "output.invalid") return "structured_output_retry_exhausted";
652519
+ if (code2 === LIMITS_MAX_TURNS_EXCEEDED) return "max_turns";
652520
+ if (code2 === LIMITS_MAX_COST_EXCEEDED) return "budget_exhausted";
652521
+ if (code2 === OUTPUT_INVALID) return "structured_output_retry_exhausted";
652102
652522
  if (msg.is_error !== true && msg.subtype === "success") {
652103
652523
  return "completed";
652104
652524
  }
@@ -652176,6 +652596,7 @@ async function buildPrintInitMessage(params, sessionId) {
652176
652596
  var PrintStreamProjector;
652177
652597
  var init_printStreamJsonContract = __esm({
652178
652598
  "build-src/src/sema/printStreamJsonContract.ts"() {
652599
+ init_dist();
652179
652600
  init_modelContextResolver();
652180
652601
  PrintStreamProjector = class {
652181
652602
  includePartial;
@@ -665381,18 +665802,18 @@ async function runBridgeLoop(config4, environmentId, environmentSecret, api2, sp
665381
665802
  while (!loopSignal.aborted && activeSessions.size >= config4.maxSessions && (pollDeadline === null || Date.now() < pollDeadline)) {
665382
665803
  const hbConfig = getPollIntervalConfig();
665383
665804
  if (hbConfig.non_exclusive_heartbeat_interval_ms <= 0) break;
665384
- const cap = capacityWake.signal();
665805
+ const cap2 = capacityWake.signal();
665385
665806
  hbResult = await heartbeatActiveWorkItems();
665386
665807
  if (hbResult === "auth_failed" || hbResult === "fatal") {
665387
- cap.cleanup();
665808
+ cap2.cleanup();
665388
665809
  break;
665389
665810
  }
665390
665811
  hbCycles++;
665391
665812
  await sleep2(
665392
665813
  hbConfig.non_exclusive_heartbeat_interval_ms,
665393
- cap.signal
665814
+ cap2.signal
665394
665815
  );
665395
- cap.cleanup();
665816
+ cap2.cleanup();
665396
665817
  }
665397
665818
  const exitReason = hbResult === "auth_failed" || hbResult === "fatal" ? hbResult : loopSignal.aborted ? "shutdown" : activeSessions.size < config4.maxSessions ? "capacity_changed" : pollDeadline !== null && Date.now() >= pollDeadline ? "poll_due" : "config_disabled";
665398
665819
  logEvent("tengu_bridge_heartbeat_mode_exited", {
@@ -665406,17 +665827,17 @@ async function runBridgeLoop(config4, environmentId, environmentSecret, api2, sp
665406
665827
  );
665407
665828
  }
665408
665829
  if (hbResult === "auth_failed" || hbResult === "fatal") {
665409
- const cap = capacityWake.signal();
665830
+ const cap2 = capacityWake.signal();
665410
665831
  await sleep2(
665411
665832
  atCapMs > 0 ? atCapMs : pollConfig.non_exclusive_heartbeat_interval_ms,
665412
- cap.signal
665833
+ cap2.signal
665413
665834
  );
665414
- cap.cleanup();
665835
+ cap2.cleanup();
665415
665836
  }
665416
665837
  } else if (atCapMs > 0) {
665417
- const cap = capacityWake.signal();
665418
- await sleep2(atCapMs, cap.signal);
665419
- cap.cleanup();
665838
+ const cap2 = capacityWake.signal();
665839
+ await sleep2(atCapMs, cap2.signal);
665840
+ cap2.cleanup();
665420
665841
  }
665421
665842
  } else {
665422
665843
  const interval = activeSessions.size > 0 ? pollConfig.multisession_poll_interval_ms_partial_capacity : pollConfig.multisession_poll_interval_ms_not_at_capacity;
@@ -665430,20 +665851,20 @@ async function runBridgeLoop(config4, environmentId, environmentSecret, api2, sp
665430
665851
  `[bridge:work] Skipping already-completed workId=${work.id}`
665431
665852
  );
665432
665853
  if (atCapacityBeforeSwitch) {
665433
- const cap = capacityWake.signal();
665854
+ const cap2 = capacityWake.signal();
665434
665855
  if (pollConfig.non_exclusive_heartbeat_interval_ms > 0) {
665435
665856
  await heartbeatActiveWorkItems();
665436
665857
  await sleep2(
665437
665858
  pollConfig.non_exclusive_heartbeat_interval_ms,
665438
- cap.signal
665859
+ cap2.signal
665439
665860
  );
665440
665861
  } else if (pollConfig.multisession_poll_interval_ms_at_capacity > 0) {
665441
665862
  await sleep2(
665442
665863
  pollConfig.multisession_poll_interval_ms_at_capacity,
665443
- cap.signal
665864
+ cap2.signal
665444
665865
  );
665445
665866
  }
665446
- cap.cleanup();
665867
+ cap2.cleanup();
665447
665868
  } else {
665448
665869
  await sleep2(1e3, loopSignal);
665449
665870
  }
@@ -665469,20 +665890,20 @@ async function runBridgeLoop(config4, environmentId, environmentSecret, api2, sp
665469
665890
  )
665470
665891
  );
665471
665892
  if (atCapacityBeforeSwitch) {
665472
- const cap = capacityWake.signal();
665893
+ const cap2 = capacityWake.signal();
665473
665894
  if (pollConfig.non_exclusive_heartbeat_interval_ms > 0) {
665474
665895
  await heartbeatActiveWorkItems();
665475
665896
  await sleep2(
665476
665897
  pollConfig.non_exclusive_heartbeat_interval_ms,
665477
- cap.signal
665898
+ cap2.signal
665478
665899
  );
665479
665900
  } else if (pollConfig.multisession_poll_interval_ms_at_capacity > 0) {
665480
665901
  await sleep2(
665481
665902
  pollConfig.multisession_poll_interval_ms_at_capacity,
665482
- cap.signal
665903
+ cap2.signal
665483
665904
  );
665484
665905
  }
665485
- cap.cleanup();
665906
+ cap2.cleanup();
665486
665907
  }
665487
665908
  continue;
665488
665909
  }
@@ -665777,20 +666198,20 @@ async function runBridgeLoop(config4, environmentId, environmentSecret, api2, sp
665777
666198
  break;
665778
666199
  }
665779
666200
  if (atCapacityBeforeSwitch) {
665780
- const cap = capacityWake.signal();
666201
+ const cap2 = capacityWake.signal();
665781
666202
  if (pollConfig.non_exclusive_heartbeat_interval_ms > 0) {
665782
666203
  await heartbeatActiveWorkItems();
665783
666204
  await sleep2(
665784
666205
  pollConfig.non_exclusive_heartbeat_interval_ms,
665785
- cap.signal
666206
+ cap2.signal
665786
666207
  );
665787
666208
  } else if (pollConfig.multisession_poll_interval_ms_at_capacity > 0) {
665788
666209
  await sleep2(
665789
666210
  pollConfig.multisession_poll_interval_ms_at_capacity,
665790
- cap.signal
666211
+ cap2.signal
665791
666212
  );
665792
666213
  }
665793
- cap.cleanup();
666214
+ cap2.cleanup();
665794
666215
  }
665795
666216
  } catch (err8) {
665796
666217
  if (loopSignal.aborted) {
@@ -670774,7 +671195,11 @@ function HubHeader({
670774
671195
  ] })
670775
671196
  ] }),
670776
671197
  /* @__PURE__ */ (0, import_jsx_runtime492.jsx)(ThemedText, { dimColor: true, children: subtitle }),
670777
- intro ? /* @__PURE__ */ (0, import_jsx_runtime492.jsx)(ThemedBox_default, { marginTop: 1, width: 96, children: /* @__PURE__ */ (0, import_jsx_runtime492.jsx)(ThemedText, { dimColor: true, children: intro }) }) : null
671198
+ intro ? (
671199
+ // BUG-0006:固定 width=96 在 80×24 终端下每个换行行都被硬裁掉 81-96 列丢字
671200
+ // (裁点恰在 ~80 字节,截断处接空行的签名即由此来);maxWidth 让盒随终端收缩换行。
671201
+ /* @__PURE__ */ (0, import_jsx_runtime492.jsx)(ThemedBox_default, { marginTop: 1, maxWidth: 96, children: /* @__PURE__ */ (0, import_jsx_runtime492.jsx)(ThemedText, { dimColor: true, children: intro }) })
671202
+ ) : null
670778
671203
  ] });
670779
671204
  }
670780
671205
  function FormField({
@@ -671242,11 +671667,11 @@ function modelFormScreen(opts) {
671242
671667
  // 新增流程压根不显示,用户会误以为 Label 就是那个"身份"字段,而它的旧文案「display name in
671243
671668
  // the Hub」没说清楚留空会怎样。实际行为(modelChannels.ts:717):留空 → provider 分组名回落
671244
671669
  // 成通用的 channel 名(如"Custom provider"),不是回落到 Model ID。文案说清楚这一后果。
671245
- { label: `Label: ${draft.label || "(optional)"}`, value: "label", description: `edit \xB7 override how this entry's provider groups in the Hub (blank \u2192 generic "Custom provider")`, dimDescription: true },
671246
- { label: `Endpoint: ${draft.baseUrl || "(required \u2014 edit)"}`, value: "url", description: "edit", dimDescription: true },
671670
+ { label: `Label: ${clampShown(draft.label) || "(optional)"}`, value: "label", description: `edit \xB7 override how this entry's provider groups in the Hub (blank \u2192 generic "Custom provider")`, dimDescription: true },
671671
+ { label: `Endpoint: ${clampShown(draft.baseUrl) || "(required \u2014 edit)"}`, value: "url", description: "edit", dimDescription: true },
671247
671672
  { label: `API shape: ${draft.api}`, value: "api", description: "edit", dimDescription: true },
671248
671673
  { label: `API key: ${draft.apiKey ? "\u2022\u2022\u2022\u2022" + draft.apiKey.slice(-4) : "(not set)"}`, value: "key", description: "edit", dimDescription: true },
671249
- { label: `Model ID: ${draft.modelId || "(required \u2014 edit)"}`, value: "id", description: "edit", dimDescription: true },
671674
+ { label: `Model ID: ${clampShown(draft.modelId) || "(required \u2014 edit)"}`, value: "id", description: "edit", dimDescription: true },
671250
671675
  { label: `Context window: ${fmt(draft.contextWindow)}`, value: "ctx", description: "pick 64K/128K/200K/256K/512K/1M or custom", dimDescription: true },
671251
671676
  {
671252
671677
  label: `Max output tokens: ${fmt(draft.maxTokens)}`,
@@ -671257,10 +671682,13 @@ function modelFormScreen(opts) {
671257
671682
  ];
671258
671683
  return /* @__PURE__ */ (0, import_jsx_runtime494.jsxs)(ThemedBox_default, { flexDirection: "column", paddingLeft: 1, children: [
671259
671684
  /* @__PURE__ */ (0, import_jsx_runtime494.jsx)(HubHeader, { subtitle: opts.title, intro: opts.intro }),
671260
- opts.hint ? /* @__PURE__ */ (0, import_jsx_runtime494.jsx)(ThemedBox_default, { marginBottom: 1, width: 96, children: /* @__PURE__ */ (0, import_jsx_runtime494.jsx)(ThemedText, { color: "yellow", children: opts.hint }) }) : null,
671685
+ opts.hint ? (
671686
+ // BUG-0006:固定 width 在 80 列终端下溢出被硬裁丢字;maxWidth 让盒随终端收缩换行
671687
+ /* @__PURE__ */ (0, import_jsx_runtime494.jsx)(ThemedBox_default, { marginBottom: 1, maxWidth: 96, children: /* @__PURE__ */ (0, import_jsx_runtime494.jsx)(ThemedText, { color: "yellow", children: opts.hint }) })
671688
+ ) : null,
671261
671689
  /* @__PURE__ */ (0, import_jsx_runtime494.jsx)(ThemedBox_default, { flexDirection: "column", paddingLeft: 1, marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime494.jsxs)(ThemedText, { children: [
671262
671690
  /* @__PURE__ */ (0, import_jsx_runtime494.jsx)(ThemedText, { dimColor: true, children: "Endpoint " }),
671263
- /* @__PURE__ */ (0, import_jsx_runtime494.jsx)(ThemedText, { children: draft.baseUrl || "(not set)" }),
671691
+ /* @__PURE__ */ (0, import_jsx_runtime494.jsx)(ThemedText, { children: clampShown(draft.baseUrl) || "(not set)" }),
671264
671692
  /* @__PURE__ */ (0, import_jsx_runtime494.jsxs)(ThemedText, { dimColor: true, children: [
671265
671693
  " ",
671266
671694
  draft.api
@@ -671882,7 +672310,7 @@ function ModelHubBody({
671882
672310
  slimHeader: onboard?.slimHeader
671883
672311
  }
671884
672312
  ),
671885
- onboard ? /* @__PURE__ */ (0, import_jsx_runtime494.jsx)(ThemedBox_default, { marginBottom: 1, width: 100, children: /* @__PURE__ */ (0, import_jsx_runtime494.jsx)(ThemedText, { dimColor: true, children: onboard.blurb }) }) : null,
672313
+ onboard ? /* @__PURE__ */ (0, import_jsx_runtime494.jsx)(ThemedBox_default, { marginBottom: 1, maxWidth: 100, children: /* @__PURE__ */ (0, import_jsx_runtime494.jsx)(ThemedText, { dimColor: true, children: onboard.blurb }) }) : null,
671886
672314
  message ? /* @__PURE__ */ (0, import_jsx_runtime494.jsx)(ThemedBox_default, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime494.jsx)(ThemedText, { color: "yellow", children: message }) }) : null,
671887
672315
  confirmDelete ? /* @__PURE__ */ (0, import_jsx_runtime494.jsxs)(ThemedBox_default, { marginBottom: 1, flexDirection: "column", children: [
671888
672316
  /* @__PURE__ */ (0, import_jsx_runtime494.jsxs)(ThemedText, { color: "red", children: [
@@ -671965,7 +672393,7 @@ function ModelHubBody({
671965
672393
  ] }) })
671966
672394
  ] });
671967
672395
  }
671968
- var React184, import_jsx_runtime494, hostOf3, SUPPORTED_CHANNELS, channelModelCount;
672396
+ var React184, import_jsx_runtime494, clampShown, hostOf3, SUPPORTED_CHANNELS, channelModelCount;
671969
672397
  var init_ModelHub = __esm({
671970
672398
  "build-src/src/sema/config/ModelHub.tsx"() {
671971
672399
  React184 = __toESM(require_react(), 1);
@@ -671984,11 +672412,12 @@ var init_ModelHub = __esm({
671984
672412
  init_catalogScreens();
671985
672413
  init_providerLinks();
671986
672414
  import_jsx_runtime494 = __toESM(require_jsx_runtime(), 1);
672415
+ clampShown = (v2, max2 = 64) => v2 && v2.length > max2 ? `${v2.slice(0, 30)}\u2026${v2.slice(-30)}` : v2 ?? "";
671987
672416
  hostOf3 = (u) => {
671988
672417
  try {
671989
672418
  return new URL(u).host;
671990
672419
  } catch {
671991
- return u;
672420
+ return clampShown(u);
671992
672421
  }
671993
672422
  };
671994
672423
  SUPPORTED_CHANNELS = ["claude-code", "openclaw", "hermes"];
@@ -672118,7 +672547,10 @@ function ManualAddBody({
672118
672547
  intro: "Point sema at any MCP server by hand. It's saved to your user scope (all projects) when you confirm."
672119
672548
  }
672120
672549
  ),
672121
- error51 ? /* @__PURE__ */ (0, import_jsx_runtime495.jsx)(ThemedBox_default, { marginBottom: 1, width: 96, children: /* @__PURE__ */ (0, import_jsx_runtime495.jsx)(ThemedText, { color: "red", children: error51 }) }) : null,
672550
+ error51 ? (
672551
+ // BUG-0006 同族:固定 width 窄终端溢出硬裁,maxWidth 随终端收缩换行
672552
+ /* @__PURE__ */ (0, import_jsx_runtime495.jsx)(ThemedBox_default, { marginBottom: 1, maxWidth: 96, children: /* @__PURE__ */ (0, import_jsx_runtime495.jsx)(ThemedText, { color: "red", children: error51 }) })
672553
+ ) : null,
672122
672554
  /* @__PURE__ */ (0, import_jsx_runtime495.jsx)(
672123
672555
  Select,
672124
672556
  {
@@ -672326,7 +672758,7 @@ function McpHubBody({
672326
672758
  slimHeader: onboard?.slimHeader
672327
672759
  }
672328
672760
  ),
672329
- onboard ? /* @__PURE__ */ (0, import_jsx_runtime495.jsx)(ThemedBox_default, { marginBottom: 1, width: 100, children: /* @__PURE__ */ (0, import_jsx_runtime495.jsx)(ThemedText, { dimColor: true, children: onboard.blurb }) }) : null,
672761
+ onboard ? /* @__PURE__ */ (0, import_jsx_runtime495.jsx)(ThemedBox_default, { marginBottom: 1, maxWidth: 100, children: /* @__PURE__ */ (0, import_jsx_runtime495.jsx)(ThemedText, { dimColor: true, children: onboard.blurb }) }) : null,
672330
672762
  message ? /* @__PURE__ */ (0, import_jsx_runtime495.jsx)(ThemedBox_default, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime495.jsx)(ThemedText, { color: "yellow", children: message }) }) : null,
672331
672763
  confirmDelete ? /* @__PURE__ */ (0, import_jsx_runtime495.jsxs)(ThemedBox_default, { marginBottom: 1, flexDirection: "column", children: [
672332
672764
  /* @__PURE__ */ (0, import_jsx_runtime495.jsxs)(ThemedText, { color: "red", children: [
@@ -672773,8 +673205,8 @@ function PluginsHubBody({
672773
673205
  slimHeader: onboard?.slimHeader
672774
673206
  }
672775
673207
  ),
672776
- onboard ? /* @__PURE__ */ (0, import_jsx_runtime497.jsx)(ThemedBox_default, { marginBottom: 1, width: 100, children: /* @__PURE__ */ (0, import_jsx_runtime497.jsx)(ThemedText, { dimColor: true, children: onboard.blurb }) }) : null,
672777
- message ? /* @__PURE__ */ (0, import_jsx_runtime497.jsx)(ThemedBox_default, { marginBottom: 1, width: 100, children: /* @__PURE__ */ (0, import_jsx_runtime497.jsx)(ThemedText, { color: "yellow", children: message }) }) : null,
673208
+ onboard ? /* @__PURE__ */ (0, import_jsx_runtime497.jsx)(ThemedBox_default, { marginBottom: 1, maxWidth: 100, children: /* @__PURE__ */ (0, import_jsx_runtime497.jsx)(ThemedText, { dimColor: true, children: onboard.blurb }) }) : null,
673209
+ message ? /* @__PURE__ */ (0, import_jsx_runtime497.jsx)(ThemedBox_default, { marginBottom: 1, maxWidth: 100, children: /* @__PURE__ */ (0, import_jsx_runtime497.jsx)(ThemedText, { color: "yellow", children: message }) }) : null,
672778
673210
  confirmDelete ? /* @__PURE__ */ (0, import_jsx_runtime497.jsxs)(ThemedBox_default, { marginBottom: 1, flexDirection: "column", children: [
672779
673211
  /* @__PURE__ */ (0, import_jsx_runtime497.jsxs)(ThemedText, { color: "red", children: [
672780
673212
  "Uninstall ",
@@ -672986,7 +673418,7 @@ function TiersHubBody({
672986
673418
  }
672987
673419
  return /* @__PURE__ */ (0, import_jsx_runtime498.jsxs)(ThemedBox_default, { flexDirection: "column", paddingLeft: 1, children: [
672988
673420
  /* @__PURE__ */ (0, import_jsx_runtime498.jsx)(TiersHeader, { subtitle: "Model tiers \u2014 named tier bindings, switch as a set" }),
672989
- message ? /* @__PURE__ */ (0, import_jsx_runtime498.jsx)(ThemedBox_default, { marginBottom: 1, width: 100, children: /* @__PURE__ */ (0, import_jsx_runtime498.jsx)(ThemedText, { color: "yellow", children: message }) }) : null,
673421
+ message ? /* @__PURE__ */ (0, import_jsx_runtime498.jsx)(ThemedBox_default, { marginBottom: 1, maxWidth: 100, children: /* @__PURE__ */ (0, import_jsx_runtime498.jsx)(ThemedText, { color: "yellow", children: message }) }) : null,
672990
673422
  confirmDelete ? /* @__PURE__ */ (0, import_jsx_runtime498.jsxs)(ThemedBox_default, { marginBottom: 1, flexDirection: "column", children: [
672991
673423
  /* @__PURE__ */ (0, import_jsx_runtime498.jsxs)(ThemedText, { color: "red", children: [
672992
673424
  'Delete group "',
@@ -673188,7 +673620,7 @@ function GroupEditBody({
673188
673620
  slimHeader: Boolean(onboard)
673189
673621
  }
673190
673622
  ),
673191
- onboard ? /* @__PURE__ */ (0, import_jsx_runtime498.jsx)(ThemedBox_default, { marginBottom: 1, width: 100, children: /* @__PURE__ */ (0, import_jsx_runtime498.jsx)(ThemedText, { dimColor: true, children: onboard.blurb }) }) : null,
673623
+ onboard ? /* @__PURE__ */ (0, import_jsx_runtime498.jsx)(ThemedBox_default, { marginBottom: 1, maxWidth: 100, children: /* @__PURE__ */ (0, import_jsx_runtime498.jsx)(ThemedText, { dimColor: true, children: onboard.blurb }) }) : null,
673192
673624
  /* @__PURE__ */ (0, import_jsx_runtime498.jsx)(
673193
673625
  Select,
673194
673626
  {
@@ -673436,7 +673868,7 @@ function skillDetailScreen(skill) {
673436
673868
  formatTokens(skill.tokens),
673437
673869
  " tok"
673438
673870
  ] }),
673439
- /* @__PURE__ */ (0, import_jsx_runtime499.jsx)(ThemedBox_default, { marginTop: 1, width: 96, children: /* @__PURE__ */ (0, import_jsx_runtime499.jsx)(ThemedText, { children: skill.description ?? /* @__PURE__ */ (0, import_jsx_runtime499.jsx)(ThemedText, { dimColor: true, children: "(no description in frontmatter)" }) }) })
673871
+ /* @__PURE__ */ (0, import_jsx_runtime499.jsx)(ThemedBox_default, { marginTop: 1, maxWidth: 96, children: /* @__PURE__ */ (0, import_jsx_runtime499.jsx)(ThemedText, { children: skill.description ?? /* @__PURE__ */ (0, import_jsx_runtime499.jsx)(ThemedText, { dimColor: true, children: "(no description in frontmatter)" }) }) })
673440
673872
  ] }),
673441
673873
  /* @__PURE__ */ (0, import_jsx_runtime499.jsx)(
673442
673874
  Select,
@@ -673586,7 +674018,7 @@ function SkillsHubBody({
673586
674018
  slimHeader: onboard?.slimHeader
673587
674019
  }
673588
674020
  ),
673589
- onboard ? /* @__PURE__ */ (0, import_jsx_runtime499.jsx)(ThemedBox_default, { marginBottom: 1, width: 100, children: /* @__PURE__ */ (0, import_jsx_runtime499.jsx)(ThemedText, { dimColor: true, children: onboard.blurb }) }) : null,
674021
+ onboard ? /* @__PURE__ */ (0, import_jsx_runtime499.jsx)(ThemedBox_default, { marginBottom: 1, maxWidth: 100, children: /* @__PURE__ */ (0, import_jsx_runtime499.jsx)(ThemedText, { dimColor: true, children: onboard.blurb }) }) : null,
673590
674022
  message ? /* @__PURE__ */ (0, import_jsx_runtime499.jsx)(ThemedBox_default, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime499.jsx)(ThemedText, { color: "yellow", children: message }) }) : null,
673591
674023
  confirmDelete ? /* @__PURE__ */ (0, import_jsx_runtime499.jsxs)(ThemedBox_default, { marginBottom: 1, flexDirection: "column", children: [
673592
674024
  /* @__PURE__ */ (0, import_jsx_runtime499.jsxs)(ThemedText, { color: "red", children: [
@@ -675243,7 +675675,7 @@ async function run() {
675243
675675
  throw new InvalidArgumentError(`It must be one of: ${allowed.join(", ")}`);
675244
675676
  }
675245
675677
  return value;
675246
- })).option("--sandbox <profile>", `Sandbox image profile for submitted runs: a profile name (explicit; k8s-lane workers only \u2014 list with 'sema cloud images list'), or 'auto' to let the model pick via its SelectEnvironment tool (advisory; choice + reason are echoed in the reply). Omit for the worker default image.`).option("--scenario <name>", `Engine scenario for submitted runs (only works with --print): route the run through a deployment-defined scenario (tool roster + system prompt). Unknown names fall back to the default scenario. Omit for the default scenario; a persistent default can be set via SEMA_HEADLESS_SCENARIO in the settings.json env block.`).option("--final-verify", `Enable a final-verification pass for submitted runs (only works with --print; off by default). When enabled, headless -p runs that write files get up to two extra verification turns before finishing. A persistent default can be set via SEMA_HEADLESS_FINAL_VERIFY=true in the settings.json env block. Yields automatically (with a notice) when a Stop hook is configured.`).option("--no-final-verify", `Explicitly disable the final-verification pass for submitted runs (only works with --print). Verification is off by default, so this flag only matters to override --final-verify or a persistent SEMA_HEADLESS_FINAL_VERIFY=true default; it always wins.`).option("--deadline <sec>", `Wall-clock limit in seconds for submitted runs (only works with --print; sema superset \u2014 no upstream equivalent). The run fails loudly with its partial output when the limit is hit; integer between 30 and 86400. A persistent default can be set via SEMA_HEADLESS_DEADLINE_SEC in the settings.json env block.`).option("--max-tokens <n>", `Total token budget for submitted runs (only works with --print; sema superset \u2014 no upstream equivalent). The primary recommended limit: the run fails loudly with its partial output when the budget is exhausted; positive integer. A persistent default can be set via SEMA_HEADLESS_MAX_TOKENS in the settings.json env block.`).option("--agent <agent>", `Agent for the current session. Overrides the 'agent' setting.`).option("--betas <betas...>", "Beta headers to include in API requests (API key users only)").option("--fallback-model <model>", "Enable automatic fallback to specified model when default model is overloaded (only works with --print)").addOption(new Option("--workload <tag>", "Workload tag for billing-header attribution (cc_workload). Process-scoped; set by SDK daemon callers that spawn subprocesses for cron work. (only works with --print)").hideHelp()).option("--settings <file-or-json>", "Path to a settings JSON file or a JSON string to load additional settings from").option("--add-dir <directories...>", "Additional directories to allow tool access to").option("--ide", "Automatically connect to IDE on startup if exactly one valid IDE is available", () => true).option("--strict-mcp-config", "Only use MCP servers from --mcp-config, ignoring all other MCP configurations", () => true).option("--session-id <uuid>", "Use a specific session ID for the conversation (must be a valid UUID)").option("-n, --name <name>", "Set a display name for this session (shown in /resume and terminal title)").option("--agents <json>", `JSON object defining custom agents (e.g. '{"reviewer": {"description": "Reviews code", "prompt": "You are a code reviewer"}}')`).option("--setting-sources <sources>", "Comma-separated list of setting sources to load (user, project, local).").option("--plugin-dir <path>", "Load plugins from a directory for this session only (repeatable: --plugin-dir A --plugin-dir B)", (val, prev) => [...prev, val], []).addOption(new Option("--plugin-dir-no-mcp <path>", "Like --plugin-dir but the engine will not read this plugin's .mcp.json (caller owns its MCP connections)").argParser((val, prev) => [...prev, val]).default([]).hideHelp()).option("--plugin-url <url>", "Fetch a plugin .zip from a URL for this session only (repeatable: --plugin-url A --plugin-url B)", (val, prev) => [...prev, ...val.split(/\s+/).filter(Boolean)], []).option("--disable-slash-commands", "Disable all skills", () => true).option("--chrome", "Enable Claude in Chrome integration").option("--no-chrome", "Disable Claude in Chrome integration").option("--file <specs...>", "File resources to download at startup. Format: file_id:relative_path (e.g., --file file_abc:doc.txt file_def:img.png)").action(async (prompt, options) => {
675678
+ })).option("--sandbox <profile>", `Sandbox image profile for submitted runs: a profile name (explicit; k8s-lane workers only \u2014 list with 'sema cloud images list'), or 'auto' to let the model pick via its SelectEnvironment tool (advisory; choice + reason are echoed in the reply). Omit for the worker default image.`).option("--scenario <name>", `Engine scenario for submitted runs (only works with --print): route the run through a deployment-defined scenario (tool roster + system prompt). Unknown names fall back to the default scenario. Omit for the default scenario; a persistent default can be set via SEMA_HEADLESS_SCENARIO in the settings.json env block.`).option("--final-verify", `Enable a final-verification pass for submitted runs (only works with --print; off by default). When enabled, headless -p runs that write files get up to two extra verification turns before finishing. A persistent default can be set via SEMA_HEADLESS_FINAL_VERIFY=true in the settings.json env block. Yields automatically (with a notice) when a Stop hook is configured.`).option("--no-final-verify", `Explicitly disable the final-verification pass for submitted runs (only works with --print). Verification is off by default, so this flag only matters to override --final-verify or a persistent SEMA_HEADLESS_FINAL_VERIFY=true default; it always wins.`).option("--deadline <sec>", `Wall-clock limit in seconds for submitted runs (only works with --print; sema superset \u2014 no upstream equivalent). The run fails loudly with its partial output when the limit is hit; integer between 30 and 86400. A persistent default can be set via SEMA_HEADLESS_DEADLINE_SEC in the settings.json env block.`).option("--max-tokens <n>", `Per-request output-token cap for submitted runs (only works with --print; sema superset \u2014 no upstream equivalent). Caps each model response rather than the whole run: hitting the cap cuts generation mid-stream, and a cut inside tool-call arguments surfaces as a provider truncation error; positive integer. A persistent default can be set via SEMA_HEADLESS_MAX_TOKENS in the settings.json env block.`).option("--agent <agent>", `Agent for the current session. Overrides the 'agent' setting.`).option("--betas <betas...>", "Beta headers to include in API requests (API key users only)").option("--fallback-model <model>", "Enable automatic fallback to specified model when default model is overloaded (only works with --print)").addOption(new Option("--workload <tag>", "Workload tag for billing-header attribution (cc_workload). Process-scoped; set by SDK daemon callers that spawn subprocesses for cron work. (only works with --print)").hideHelp()).option("--settings <file-or-json>", "Path to a settings JSON file or a JSON string to load additional settings from").option("--add-dir <directories...>", "Additional directories to allow tool access to").option("--ide", "Automatically connect to IDE on startup if exactly one valid IDE is available", () => true).option("--strict-mcp-config", "Only use MCP servers from --mcp-config, ignoring all other MCP configurations", () => true).option("--session-id <uuid>", "Use a specific session ID for the conversation (must be a valid UUID)").option("-n, --name <name>", "Set a display name for this session (shown in /resume and terminal title)").option("--agents <json>", `JSON object defining custom agents (e.g. '{"reviewer": {"description": "Reviews code", "prompt": "You are a code reviewer"}}')`).option("--setting-sources <sources>", "Comma-separated list of setting sources to load (user, project, local).").option("--plugin-dir <path>", "Load plugins from a directory for this session only (repeatable: --plugin-dir A --plugin-dir B)", (val, prev) => [...prev, val], []).addOption(new Option("--plugin-dir-no-mcp <path>", "Like --plugin-dir but the engine will not read this plugin's .mcp.json (caller owns its MCP connections)").argParser((val, prev) => [...prev, val]).default([]).hideHelp()).option("--plugin-url <url>", "Fetch a plugin .zip from a URL for this session only (repeatable: --plugin-url A --plugin-url B)", (val, prev) => [...prev, ...val.split(/\s+/).filter(Boolean)], []).option("--disable-slash-commands", "Disable all skills", () => true).option("--chrome", "Enable Claude in Chrome integration").option("--no-chrome", "Disable Claude in Chrome integration").option("--file <specs...>", "File resources to download at startup. Format: file_id:relative_path (e.g., --file file_abc:doc.txt file_def:img.png)").action(async (prompt, options) => {
675247
675679
  profileCheckpoint("action_handler_start");
675248
675680
  {
675249
675681
  const UNWIRED_FLAGS = [
@@ -677382,7 +677814,7 @@ Auth: unix socket -R \u2192 local proxy`, "info");
677382
677814
  pendingHookMessages
677383
677815
  }, renderAndRun);
677384
677816
  }
677385
- }).version("sema 1.0.67", "-v, --version", "Output the version number");
677817
+ }).version("sema 1.0.68", "-v, --version", "Output the version number");
677386
677818
  program2.option("-w, --worktree [name]", "Create a new git worktree for this session (optionally specify a name)");
677387
677819
  program2.option("--tmux", "Create a tmux session for the worktree (requires --worktree). Uses iTerm2 native panes when available; use --tmux=classic for traditional tmux.");
677388
677820
  if (canUserConfigureAdvisor()) {
@@ -687463,6 +687895,27 @@ async function launchReplProduction() {
687463
687895
  } catch (e) {
687464
687896
  if (process.env.SEMA_DEBUG) console.error("[sema] permission-flag plumbing soft-failed:", e);
687465
687897
  }
687898
+ try {
687899
+ const tpc = initialState.toolPermissionContext;
687900
+ const { loadAllPermissionRulesFromDisk: loadAllPermissionRulesFromDisk2 } = await Promise.resolve().then(() => (init_permissionsLoader(), permissionsLoader_exports));
687901
+ const { applyPermissionRulesToPermissionContext: applyPermissionRulesToPermissionContext2 } = await Promise.resolve().then(() => (init_permissions2(), permissions_exports2));
687902
+ const rulesFromDisk = loadAllPermissionRulesFromDisk2();
687903
+ if (rulesFromDisk.length > 0) {
687904
+ let next = applyPermissionRulesToPermissionContext2(tpc, rulesFromDisk);
687905
+ if (tpc.mode === "auto") {
687906
+ const { stripDangerousPermissionsForAutoMode: stripDangerousPermissionsForAutoMode2 } = await Promise.resolve().then(() => (init_permissionSetup(), permissionSetup_exports));
687907
+ next = stripDangerousPermissionsForAutoMode2(next);
687908
+ }
687909
+ Object.assign(tpc, next);
687910
+ }
687911
+ if (process.env.SEMA_DEBUG) {
687912
+ console.error(
687913
+ `[sema] permission rules from disk: ${rulesFromDisk.length} loaded (mode=${String(tpc.mode)})`
687914
+ );
687915
+ }
687916
+ } catch (e) {
687917
+ if (process.env.SEMA_DEBUG) console.error("[sema] permission-rule load soft-failed (rules stay empty):", e);
687918
+ }
687466
687919
  let mcpDynamicConfig = {};
687467
687920
  try {
687468
687921
  const mcpState = initialState.mcp;