claudish 7.31.0 → 7.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +401 -108
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -651,7 +651,7 @@ var init_onepassword_config = __esm(() => {
651
651
  });
652
652
 
653
653
  // src/version.ts
654
- var VERSION = "7.31.0";
654
+ var VERSION = "7.33.0";
655
655
 
656
656
  // src/logger.ts
657
657
  var exports_logger = {};
@@ -912,6 +912,22 @@ var init_logger = __esm(() => {
912
912
  });
913
913
 
914
914
  // src/startup-trace.ts
915
+ var exports_startup_trace = {};
916
+ __export(exports_startup_trace, {
917
+ traceSpan: () => traceSpan,
918
+ suppressStartupTraceTerminalOutput: () => suppressStartupTraceTerminalOutput,
919
+ setStartupAuthKind: () => setStartupAuthKind,
920
+ finalizeStartupTrace: () => finalizeStartupTrace,
921
+ beginSpan: () => beginSpan,
922
+ beginQueuedSpan: () => beginQueuedSpan,
923
+ addSpanMeta: () => addSpanMeta,
924
+ __resetStartupTraceForTests: () => __resetStartupTraceForTests,
925
+ __getStartupSpansForTests: () => __getStartupSpansForTests,
926
+ __configureStartupTraceForTests: () => __configureStartupTraceForTests,
927
+ STARTUP_METRICS_MAX_LINES: () => STARTUP_METRICS_MAX_LINES,
928
+ STARTUP_METRICS_FILE: () => STARTUP_METRICS_FILE,
929
+ SLOW_START_THRESHOLD_MS: () => SLOW_START_THRESHOLD_MS
930
+ });
915
931
  import { appendFileSync, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
916
932
  import { homedir as homedir3 } from "os";
917
933
  import { dirname, join as join3 } from "path";
@@ -1166,6 +1182,25 @@ function finalizeStartupTrace(context, opts = {}) {
1166
1182
  } catch {}
1167
1183
  } catch {}
1168
1184
  }
1185
+ function __configureStartupTraceForTests(overrides) {
1186
+ seams = { ...defaultSeams(), ...overrides };
1187
+ spans = [];
1188
+ finalized = false;
1189
+ authKind = "none";
1190
+ terminalSuppressed = false;
1191
+ suppressedLogSink = undefined;
1192
+ }
1193
+ function __resetStartupTraceForTests() {
1194
+ seams = defaultSeams();
1195
+ spans = [];
1196
+ finalized = false;
1197
+ authKind = "none";
1198
+ terminalSuppressed = false;
1199
+ suppressedLogSink = undefined;
1200
+ }
1201
+ function __getStartupSpansForTests() {
1202
+ return spans.map((s) => ({ ...s, meta: s.meta ? { ...s.meta } : undefined }));
1203
+ }
1169
1204
  var STARTUP_METRICS_FILE, STARTUP_METRICS_MAX_LINES = 500, SLOW_START_THRESHOLD_MS = 8000, MAX_BUFFERED_SPANS = 500, seams, spans, finalized = false, authKind = "none", terminalSuppressed = false, suppressedLogSink;
1170
1205
  var init_startup_trace = __esm(() => {
1171
1206
  STARTUP_METRICS_FILE = join3(homedir3(), ".claudish", "startup-metrics.jsonl");
@@ -1173,6 +1208,17 @@ var init_startup_trace = __esm(() => {
1173
1208
  spans = [];
1174
1209
  });
1175
1210
 
1211
+ // src/env-placeholder.ts
1212
+ function realValue(v) {
1213
+ if (!v)
1214
+ return;
1215
+ return UNEXPANDED_PLACEHOLDER.test(v.trim()) ? undefined : v;
1216
+ }
1217
+ var UNEXPANDED_PLACEHOLDER;
1218
+ var init_env_placeholder = __esm(() => {
1219
+ UNEXPANDED_PLACEHOLDER = /^\$\{[^}]*\}$/;
1220
+ });
1221
+
1176
1222
  // src/providers/onepassword-handshake-lock.ts
1177
1223
  import { closeSync, mkdirSync as mkdirSync3, openSync, readFileSync as readFileSync3, rmSync, statSync, writeSync } from "fs";
1178
1224
  import { homedir as homedir4 } from "os";
@@ -3785,6 +3831,7 @@ __export(exports_onepassword, {
3785
3831
  resetSdkClientCache: () => resetSdkClientCache,
3786
3832
  resetOpFailures: () => resetOpFailures,
3787
3833
  renderOpFailureNotice: () => renderOpFailureNotice,
3834
+ renderOpFailureBlock: () => renderOpFailureBlock,
3788
3835
  recordOpHydratedVars: () => recordOpHydratedVars,
3789
3836
  recordOpFailure: () => recordOpFailure,
3790
3837
  readEnvironment: () => readEnvironment,
@@ -3809,6 +3856,7 @@ __export(exports_onepassword, {
3809
3856
  detectSdkAuth: () => detectSdkAuth,
3810
3857
  defaultSdkClientFactory: () => defaultSdkClientFactory,
3811
3858
  defaultScreenLockProbe: () => defaultScreenLockProbe,
3859
+ defaultOpDefaultAccountProbe: () => defaultOpDefaultAccountProbe,
3812
3860
  defaultOpAccountLister: () => defaultOpAccountLister,
3813
3861
  defaultAppLockProbe: () => defaultAppLockProbe,
3814
3862
  currentLockCause: () => currentLockCause,
@@ -3847,9 +3895,12 @@ function wasOpAuthorizationDenied() {
3847
3895
  return opSourceFailures.some((f) => /denied authorization/i.test(f.message));
3848
3896
  }
3849
3897
  function renderOpFailureNotice(envVar) {
3898
+ return renderOpFailureBlock(`for ${envVar} this run`);
3899
+ }
3900
+ function renderOpFailureBlock(subject) {
3850
3901
  if (opSourceFailures.length === 0)
3851
3902
  return [];
3852
- const lines = [`1Password was consulted for ${envVar} this run and failed:`];
3903
+ const lines = [`1Password was consulted ${subject} and failed:`];
3853
3904
  for (const f of opSourceFailures) {
3854
3905
  const where = f.source ? `${f.kind} ${f.source}` : f.kind;
3855
3906
  lines.push(` ${where} \u2014 ${f.message.split(`
@@ -4373,7 +4424,7 @@ function detectSdkAuth(env = process.env) {
4373
4424
  }
4374
4425
  function resolveDesktopAccount(opts = {}) {
4375
4426
  const env = opts.env ?? process.env;
4376
- const envAccount = env.OP_ACCOUNT?.trim();
4427
+ const envAccount = realValue(env.OP_ACCOUNT)?.trim();
4377
4428
  if (envAccount)
4378
4429
  return { accountName: envAccount };
4379
4430
  const configAccount = opts.configAccount?.trim();
@@ -4393,10 +4444,17 @@ function resolveDesktopAccount(opts = {}) {
4393
4444
  if (opts.interactive) {
4394
4445
  return { needsPicker: accounts };
4395
4446
  }
4447
+ const probe = opts.opDefaultAccountProbe ?? defaultOpDefaultAccountProbe;
4448
+ const defaultUuid = probe();
4449
+ if (defaultUuid) {
4450
+ const match = accounts.find((a) => a.account_uuid === defaultUuid);
4451
+ if (match)
4452
+ return { accountName: match.url };
4453
+ }
4396
4454
  const listing = accounts.map((a) => ` - ${a.url}${a.email ? ` (${a.email})` : ""}`).join(`
4397
4455
  `);
4398
4456
  return {
4399
- error: `Multiple 1Password accounts are available and this is a non-interactive session, so claudish can't prompt you to pick one. ${remediation}
4457
+ error: `Multiple 1Password accounts are available, this is a non-interactive session, and \`op\` could not name a default account. ${remediation}
4400
4458
  Accounts:
4401
4459
  ${listing}`
4402
4460
  };
@@ -4410,7 +4468,8 @@ async function resolveSdkAuth(opts = {}) {
4410
4468
  env,
4411
4469
  configAccount: opts.configAccount,
4412
4470
  interactive: opts.interactive,
4413
- opAccountLister: opts.opAccountLister
4471
+ opAccountLister: opts.opAccountLister,
4472
+ opDefaultAccountProbe: opts.opDefaultAccountProbe
4414
4473
  });
4415
4474
  if ("accountName" in result) {
4416
4475
  return { kind: "desktop", accountName: result.accountName };
@@ -4578,8 +4637,19 @@ var OP_REF_RE, opHydratedVars, opSourceFailures, ENV_VAR_NAME_RE, sdkClientCache
4578
4637
  } catch {
4579
4638
  return null;
4580
4639
  }
4640
+ }, defaultOpDefaultAccountProbe = () => {
4641
+ try {
4642
+ const res = spawnSync("op", ["account", "get", "--format=json"], { encoding: "utf-8" });
4643
+ if (res.error || res.status !== 0)
4644
+ return null;
4645
+ const parsed = JSON.parse(res.stdout ?? "");
4646
+ return typeof parsed.id === "string" && parsed.id ? parsed.id : null;
4647
+ } catch {
4648
+ return null;
4649
+ }
4581
4650
  };
4582
4651
  var init_onepassword = __esm(() => {
4652
+ init_env_placeholder();
4583
4653
  init_startup_trace();
4584
4654
  init_onepassword_handshake_lock();
4585
4655
  OP_REF_RE = /^op:\/\/[^\s]+$/;
@@ -29656,11 +29726,6 @@ var init_antigravity_credential = __esm(() => {
29656
29726
  import { existsSync as existsSync8 } from "fs";
29657
29727
  import { homedir as homedir10 } from "os";
29658
29728
  import { join as join10 } from "path";
29659
- function realValue(v) {
29660
- if (!v)
29661
- return;
29662
- return UNEXPANDED_PLACEHOLDER.test(v.trim()) ? undefined : v;
29663
- }
29664
29729
 
29665
29730
  class ApiKeyCredentialProvider {
29666
29731
  catalogName;
@@ -29763,11 +29828,10 @@ class ApiKeyCredentialProvider {
29763
29828
  return { headers };
29764
29829
  }
29765
29830
  }
29766
- var UNEXPANDED_PLACEHOLDER;
29767
29831
  var init_api_key_credential = __esm(() => {
29832
+ init_env_placeholder();
29768
29833
  init_profile_config();
29769
29834
  init_op_source();
29770
- UNEXPANDED_PLACEHOLDER = /^\$\{[^}]*\}$/;
29771
29835
  });
29772
29836
 
29773
29837
  // src/auth/codex-oauth.ts
@@ -33319,44 +33383,6 @@ async function isPortAvailable(port) {
33319
33383
  }
33320
33384
  var init_port_manager = () => {};
33321
33385
 
33322
- // src/redact.ts
33323
- function isPlaceholder(value) {
33324
- return PLACEHOLDER.test(value.trim());
33325
- }
33326
- function redactSecrets(text) {
33327
- if (!text)
33328
- return "";
33329
- let out = text;
33330
- out = out.replace(ASSIGNMENT_RE, (match, lhs, value) => isPlaceholder(value) ? match : `${lhs}${MASK}`);
33331
- for (const { re } of TOKEN_PATTERNS) {
33332
- out = out.replace(re, (match) => {
33333
- const scheme = /^(Bearer|Basic|Token)\s/.exec(match);
33334
- return scheme ? `${scheme[1]} ${MASK}` : MASK;
33335
- });
33336
- }
33337
- return out;
33338
- }
33339
- function sanitizeForReport(text) {
33340
- if (!text)
33341
- return "";
33342
- return redactSecrets(text).replace(/\/Users\/[^/\s]+/g, "/Users/***").replace(/\/home\/[^/\s]+/g, "/home/***").replace(/[A-Z]:\\Users\\[^\\\s]+/gi, "C:\\Users\\***").replace(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g, "***@***.***");
33343
- }
33344
- var MASK = "***REDACTED***", PLACEHOLDER, ASSIGNMENT_RE, TOKEN_PATTERNS;
33345
- var init_redact = __esm(() => {
33346
- PLACEHOLDER = /^(['"`]?)(your[-_a-z0-9]*|<[^>]*>|\.\.\.|x{3,}|\*{3,}|REDACTED|CHANGEME|TODO|\$\{[^}]*\}|)(['"`]?)$/i;
33347
- ASSIGNMENT_RE = /(["']?\b[A-Z][A-Z0-9_]*(?:_API_KEY|_KEY|_TOKEN|_SECRET|_PASSWORD)\b["']?\s*[:=]\s*)(["'`]?\$\{[^}]*\}["'`]?|["'`]?[^\s"'`,}]+["'`]?)/g;
33348
- TOKEN_PATTERNS = [
33349
- { name: "sk", re: /\bsk-[A-Za-z0-9_-]{16,}/g },
33350
- { name: "google", re: /\bAIza[A-Za-z0-9_-]{20,}/g },
33351
- { name: "xai", re: /\bxai-[A-Za-z0-9_-]{16,}/g },
33352
- { name: "github", re: /\bgh[posur]_[A-Za-z0-9]{20,}/g },
33353
- { name: "aws", re: /\bAKIA[0-9A-Z]{12,}/g },
33354
- { name: "jwt", re: /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}/g },
33355
- { name: "zhipu", re: /\b[0-9a-f]{32}\.[A-Za-z0-9]{16}\b/g },
33356
- { name: "bearer", re: /\b(?:Bearer|Basic|Token)\s+[A-Za-z0-9_.\-+/=]{12,}/g }
33357
- ];
33358
- });
33359
-
33360
33386
  // ../../node_modules/.bun/hono@4.10.6/node_modules/hono/dist/compose.js
33361
33387
  var compose = (middleware, onError, onNotFound) => {
33362
33388
  return (context, next) => {
@@ -36651,6 +36677,7 @@ data: ${JSON.stringify(d)}
36651
36677
  output_tokens: state.usage?.completion_tokens || 0
36652
36678
  }
36653
36679
  });
36680
+ behavior?.onTurnEnd?.();
36654
36681
  send("message_stop", { type: "message_stop" });
36655
36682
  }
36656
36683
  if (onTokenUpdate) {
@@ -36717,6 +36744,7 @@ data: ${JSON.stringify(d)}
36717
36744
  });
36718
36745
  }
36719
36746
  if (delta.reasoning_content) {
36747
+ behavior?.onAssistantText?.(delta.reasoning_content, "reasoning");
36720
36748
  state.lastActivity = Date.now();
36721
36749
  if (!state.reasoningStarted) {
36722
36750
  state.reasoningIdx = state.curIdx++;
@@ -36734,6 +36762,8 @@ data: ${JSON.stringify(d)}
36734
36762
  });
36735
36763
  }
36736
36764
  const txt = delta.content || "";
36765
+ if (txt)
36766
+ behavior?.onAssistantText?.(txt, "text");
36737
36767
  log(`[Streaming] Text chunk: "${txt.substring(0, 30).replace(/\n/g, "\\n")}" (${txt.length} chars)`);
36738
36768
  if (txt) {
36739
36769
  state.lastActivity = Date.now();
@@ -38191,24 +38221,44 @@ function parseBehaviorConfig(raw2) {
38191
38221
  }
38192
38222
  return result.data;
38193
38223
  }
38194
- function resolveSeverity(ruleId, defaultSeverity, config2) {
38224
+ function resolveSeverity(ruleId, defaultSeverity, config2, modelId) {
38195
38225
  const rules = config2.rules;
38196
38226
  if (!rules)
38197
38227
  return defaultSeverity;
38198
- const exact = rules[ruleId];
38199
- if (exact)
38200
- return exact;
38228
+ if (modelId) {
38229
+ const scoped = bestMatch(rules, ruleId, modelId);
38230
+ if (scoped)
38231
+ return scoped;
38232
+ }
38233
+ return bestMatch(rules, ruleId, undefined) ?? defaultSeverity;
38234
+ }
38235
+ function bestMatch(rules, ruleId, modelId) {
38201
38236
  let best = null;
38202
- for (const [pattern, severity] of Object.entries(rules)) {
38203
- if (!pattern.includes("*"))
38237
+ for (const [key, severity] of Object.entries(rules)) {
38238
+ const { model: keyModel, rule: keyRule } = parseRuleKey(key);
38239
+ if (!scopeMatches(keyModel, modelId))
38204
38240
  continue;
38205
- if (!globMatches(pattern, ruleId))
38241
+ if (!globMatches(keyRule, ruleId))
38206
38242
  continue;
38207
- const len = pattern.replace(/\*/g, "").length;
38208
- if (!best || len > best.len)
38209
- best = { len, severity };
38243
+ const score = specificity(keyRule);
38244
+ if (!best || score > best.score)
38245
+ best = { score, severity };
38210
38246
  }
38211
- return best ? best.severity : defaultSeverity;
38247
+ return best ? best.severity : null;
38248
+ }
38249
+ function parseRuleKey(key) {
38250
+ const sep = key.indexOf(":");
38251
+ if (sep <= 0 || key.startsWith("hook:"))
38252
+ return { rule: key };
38253
+ return { model: key.slice(0, sep), rule: key.slice(sep + 1) };
38254
+ }
38255
+ function scopeMatches(keyModel, modelId) {
38256
+ if (modelId === undefined)
38257
+ return keyModel === undefined;
38258
+ return keyModel !== undefined && globMatches(keyModel, modelId);
38259
+ }
38260
+ function specificity(pattern) {
38261
+ return pattern.includes("*") ? pattern.replace(/\*/g, "").length : Number.MAX_SAFE_INTEGER;
38212
38262
  }
38213
38263
  function globMatches(pattern, value) {
38214
38264
  const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
@@ -38235,6 +38285,41 @@ var init_config = __esm(() => {
38235
38285
  });
38236
38286
 
38237
38287
  // src/behavior/harness.ts
38288
+ function extractAvailableSkills(systemText) {
38289
+ if (!systemText)
38290
+ return [];
38291
+ const start = SKILL_SECTION.exec(systemText);
38292
+ if (!start)
38293
+ return [];
38294
+ const out = [];
38295
+ const body = systemText.slice(start.index + start[0].length);
38296
+ for (const line of body.split(`
38297
+ `)) {
38298
+ const trimmed = line.trim();
38299
+ if (!trimmed)
38300
+ continue;
38301
+ const m = SKILL_LINE.exec(trimmed);
38302
+ if (!m) {
38303
+ if (out.length > 0)
38304
+ break;
38305
+ continue;
38306
+ }
38307
+ out.push({ name: m[1], description: m[2].trim() });
38308
+ }
38309
+ return out;
38310
+ }
38311
+ function extractSessionId(claudeRequest) {
38312
+ const raw2 = claudeRequest?.metadata?.user_id;
38313
+ if (typeof raw2 !== "string")
38314
+ return;
38315
+ try {
38316
+ const parsed = JSON.parse(raw2);
38317
+ const id = parsed?.session_id;
38318
+ return typeof id === "string" && id.length > 0 ? id : undefined;
38319
+ } catch {
38320
+ return;
38321
+ }
38322
+ }
38238
38323
  function textOf(value) {
38239
38324
  if (!value)
38240
38325
  return "";
@@ -38286,7 +38371,7 @@ function detectHarnessFacts(claudeRequest) {
38286
38371
  }
38287
38372
  return facts;
38288
38373
  }
38289
- var PLAN_PATH_PATTERNS, PLAN_MODE_HINT;
38374
+ var PLAN_PATH_PATTERNS, PLAN_MODE_HINT, SKILL_SECTION, SKILL_LINE;
38290
38375
  var init_harness = __esm(() => {
38291
38376
  PLAN_PATH_PATTERNS = [
38292
38377
  /You should create your plan at\s+(\S+?\.md)/,
@@ -38294,10 +38379,12 @@ var init_harness = __esm(() => {
38294
38379
  /Read-only except plan file\s*\(([^)]+\.md)\)/
38295
38380
  ];
38296
38381
  PLAN_MODE_HINT = /plan file|create your plan at|Plan mode is active|Plan mode still active/i;
38382
+ SKILL_SECTION = /The following skills are available[^\n]*\n/;
38383
+ SKILL_LINE = /^-\s+([a-z0-9][a-z0-9:_-]*):\s*(.+)$/i;
38297
38384
  });
38298
38385
 
38299
38386
  // src/behavior/journal.ts
38300
- import { appendFile as appendFile2, mkdir, stat } from "fs/promises";
38387
+ import { appendFile as appendFile2, mkdir, readFile, rename, stat, writeFile } from "fs/promises";
38301
38388
  import { homedir as homedir18 } from "os";
38302
38389
  import { dirname as dirname6, join as join18 } from "path";
38303
38390
  function classifyPath(observed, expected) {
@@ -38313,28 +38400,46 @@ function classifyPath(observed, expected) {
38313
38400
  function journalPath() {
38314
38401
  return join18(homedir18(), ".claudish", "behavior-journal.jsonl");
38315
38402
  }
38403
+ async function prune(path) {
38404
+ const content = await readFile(path, "utf8");
38405
+ const lines = content.split(`
38406
+ `).filter(Boolean);
38407
+ let kept = 0;
38408
+ let firstKept = lines.length;
38409
+ for (let i = lines.length - 1;i >= 0; i--) {
38410
+ const cost = Buffer.byteLength(lines[i]) + 1;
38411
+ if (kept + cost > PRUNE_TO_BYTES)
38412
+ break;
38413
+ kept += cost;
38414
+ firstKept = i;
38415
+ }
38416
+ const survivors = lines.slice(firstKept);
38417
+ const tmp = `${path}.pruning`;
38418
+ await writeFile(tmp, survivors.length ? `${survivors.join(`
38419
+ `)}
38420
+ ` : "");
38421
+ await rename(tmp, path);
38422
+ log(`[behavior:journal] pruned ${lines.length - survivors.length} of ${lines.length} entries ` + `to stay under ${Math.round(MAX_JOURNAL_BYTES / 1e6)}MB`);
38423
+ }
38316
38424
  async function recordDecision(entry, path = journalPath()) {
38317
38425
  try {
38318
38426
  const size = await stat(path).then((s) => s.size, () => 0);
38319
- if (size > MAX_JOURNAL_BYTES) {
38320
- if (!capWarned) {
38321
- capWarned = true;
38322
- log(`[behavior:journal] ${path} exceeded ${Math.round(MAX_JOURNAL_BYTES / 1e6)}MB \u2014 ` + "no longer recording. Archive or delete it to resume.");
38323
- }
38324
- return;
38325
- }
38326
38427
  if (size === 0)
38327
38428
  await mkdir(dirname6(path), { recursive: true }).catch(() => {});
38429
+ if (size > MAX_JOURNAL_BYTES) {
38430
+ await prune(path).catch((err) => log(`[behavior:journal] prune failed: ${err}`));
38431
+ }
38328
38432
  await appendFile2(path, `${JSON.stringify(entry)}
38329
38433
  `);
38330
38434
  } catch (err) {
38331
38435
  log(`[behavior:journal] could not record: ${err}`);
38332
38436
  }
38333
38437
  }
38334
- var MAX_JOURNAL_BYTES, capWarned = false;
38438
+ var MAX_JOURNAL_BYTES, PRUNE_TO_BYTES;
38335
38439
  var init_journal = __esm(() => {
38336
38440
  init_logger();
38337
38441
  MAX_JOURNAL_BYTES = 32 * 1024 * 1024;
38442
+ PRUNE_TO_BYTES = Math.floor(MAX_JOURNAL_BYTES * 0.6);
38338
38443
  });
38339
38444
 
38340
38445
  // src/behavior/observer/digest.ts
@@ -38551,13 +38656,23 @@ class BehaviorSession {
38551
38656
  modelId;
38552
38657
  providerName;
38553
38658
  config;
38659
+ engine;
38554
38660
  facts = { planModeActive: false };
38555
38661
  bufferedTools = new Set;
38556
- constructor(active, modelId, providerName, config2 = {}) {
38662
+ textBuf = "";
38663
+ reasoningBuf = "";
38664
+ toolsCalled = [];
38665
+ sessionId;
38666
+ systemText = "";
38667
+ get watchesOutput() {
38668
+ return this.active.some((a) => typeof a.rule.onModelOutput === "function");
38669
+ }
38670
+ constructor(active, modelId, providerName, config2 = {}, engine = { queueCorrection() {}, drainCorrections: () => [] }) {
38557
38671
  this.active = active;
38558
38672
  this.modelId = modelId;
38559
38673
  this.providerName = providerName;
38560
38674
  this.config = config2;
38675
+ this.engine = engine;
38561
38676
  }
38562
38677
  get observerOn() {
38563
38678
  return this.config.observer?.enabled === true && (this.config.observer.mode ?? "suggest") !== "off";
@@ -38591,7 +38706,26 @@ class BehaviorSession {
38591
38706
  if (this.active.length === 0)
38592
38707
  return;
38593
38708
  this.facts = detectHarnessFacts(claudeRequest);
38709
+ this.sessionId = extractSessionId(claudeRequest);
38710
+ this.systemText = typeof claudeRequest?.system === "string" ? claudeRequest.system : String(claudeRequest?.system ?? "");
38711
+ this.facts.sessionId = this.sessionId;
38712
+ this.facts.skills = extractAvailableSkills(this.systemText);
38594
38713
  this.armBuffering();
38714
+ if (this.sessionId) {
38715
+ for (const text of this.engine.drainCorrections(this.sessionId)) {
38716
+ this.applyAction("behavior/pending-correction", "fix", { type: "injectSystemNote", text }, {
38717
+ modelId: this.modelId,
38718
+ providerName: this.providerName,
38719
+ isNativeAnthropic: false,
38720
+ claudeRequest,
38721
+ claudeTools,
38722
+ tools,
38723
+ messages,
38724
+ systemText: this.systemText,
38725
+ harness: this.facts
38726
+ });
38727
+ }
38728
+ }
38595
38729
  const ctx = {
38596
38730
  modelId: this.modelId,
38597
38731
  providerName: this.providerName,
@@ -38600,6 +38734,7 @@ class BehaviorSession {
38600
38734
  claudeTools,
38601
38735
  tools,
38602
38736
  messages,
38737
+ systemText: this.systemText,
38603
38738
  harness: this.facts
38604
38739
  };
38605
38740
  for (const { rule, severity } of this.active) {
@@ -38619,6 +38754,66 @@ class BehaviorSession {
38619
38754
  interceptsTool(toolName) {
38620
38755
  return this.bufferedTools.has(toolName);
38621
38756
  }
38757
+ observeText(text, kind = "text") {
38758
+ if (!this.watchesOutput || !text)
38759
+ return;
38760
+ const buf = kind === "reasoning" ? this.reasoningBuf : this.textBuf;
38761
+ if (buf.length >= MAX_OBSERVED_CHARS)
38762
+ return;
38763
+ if (kind === "reasoning")
38764
+ this.reasoningBuf += text;
38765
+ else
38766
+ this.textBuf += text;
38767
+ }
38768
+ observeToolCall(toolName) {
38769
+ if (!this.watchesOutput)
38770
+ return;
38771
+ if (this.toolsCalled.length < MAX_OBSERVED_TOOLS)
38772
+ this.toolsCalled.push(toolName);
38773
+ }
38774
+ finishTurn() {
38775
+ if (!this.watchesOutput)
38776
+ return;
38777
+ const ctx = {
38778
+ modelId: this.modelId,
38779
+ providerName: this.providerName,
38780
+ text: this.textBuf,
38781
+ reasoning: this.reasoningBuf,
38782
+ toolsCalled: this.toolsCalled,
38783
+ harness: this.facts
38784
+ };
38785
+ for (const { rule, severity } of this.active) {
38786
+ if (!rule.onModelOutput)
38787
+ continue;
38788
+ let actions = [];
38789
+ try {
38790
+ actions = rule.onModelOutput(ctx) ?? [];
38791
+ } catch (err) {
38792
+ log(`[behavior] rule ${rule.id} onModelOutput threw: ${err}`);
38793
+ continue;
38794
+ }
38795
+ for (const action of actions) {
38796
+ if (action.type === "warn") {
38797
+ log(`[behavior] ${rule.id} (output): ${action.message}`);
38798
+ this.journal("model_output", "warned", { ruleId: rule.id, note: action.message });
38799
+ continue;
38800
+ }
38801
+ if (action.type !== "injectSystemNote")
38802
+ continue;
38803
+ if (severity !== "fix") {
38804
+ this.journal("model_output", "warned", { ruleId: rule.id, note: "correction withheld" });
38805
+ continue;
38806
+ }
38807
+ if (this.sessionId)
38808
+ this.engine.queueCorrection(this.sessionId, action.text);
38809
+ this.journal("model_output", "matched", { ruleId: rule.id, note: "correction queued" });
38810
+ log(`[behavior] ${rule.id} queued a correction for the next request`);
38811
+ }
38812
+ }
38813
+ this.textBuf = "";
38814
+ this.reasoningBuf = "";
38815
+ this.toolsCalled = [];
38816
+ }
38622
38817
  repairToolCall(toolName, rawArgs) {
38623
38818
  if (!this.bufferedTools.has(toolName))
38624
38819
  return null;
@@ -38786,15 +38981,32 @@ ${action.text}`;
38786
38981
  class BehaviorEngine {
38787
38982
  config;
38788
38983
  rules;
38984
+ corrections = new Map;
38789
38985
  constructor(config2, rules) {
38790
38986
  this.config = config2;
38791
38987
  this.rules = rules;
38792
38988
  }
38989
+ queueCorrection(key, text) {
38990
+ const list = this.corrections.get(key) ?? [];
38991
+ list.push(text);
38992
+ this.corrections.set(key, list);
38993
+ while (this.corrections.size > MAX_TRACKED_CONVERSATIONS) {
38994
+ const oldest = this.corrections.keys().next().value;
38995
+ if (oldest === undefined)
38996
+ break;
38997
+ this.corrections.delete(oldest);
38998
+ }
38999
+ }
39000
+ drainCorrections(key) {
39001
+ const list = this.corrections.get(key) ?? [];
39002
+ this.corrections.delete(key);
39003
+ return list;
39004
+ }
38793
39005
  startSession(params) {
38794
39006
  const active = [];
38795
39007
  if (!params.isNativeAnthropic) {
38796
39008
  for (const rule of this.rules) {
38797
- const severity = resolveSeverity(rule.id, rule.defaultSeverity, this.config);
39009
+ const severity = resolveSeverity(rule.id, rule.defaultSeverity, this.config, params.modelId);
38798
39010
  if (severity === "off")
38799
39011
  continue;
38800
39012
  let applies = false;
@@ -38811,14 +39023,16 @@ class BehaviorEngine {
38811
39023
  if (active.length > 0) {
38812
39024
  log(`[behavior] ${active.length} rule(s) active for ${params.modelId}: ` + active.map((a) => `${a.rule.id}=${a.severity}`).join(", "));
38813
39025
  }
38814
- return new BehaviorSession(active, params.modelId, params.providerName, this.config);
39026
+ return new BehaviorSession(active, params.modelId, params.providerName, this.config, this);
38815
39027
  }
38816
39028
  }
39029
+ var MAX_OBSERVED_CHARS, MAX_OBSERVED_TOOLS = 200, MAX_TRACKED_CONVERSATIONS = 64;
38817
39030
  var init_engine = __esm(() => {
38818
39031
  init_logger();
38819
39032
  init_config();
38820
39033
  init_harness();
38821
39034
  init_journal();
39035
+ MAX_OBSERVED_CHARS = 64 * 1024;
38822
39036
  });
38823
39037
 
38824
39038
  // src/behavior/rules/plan-mode.ts
@@ -41248,11 +41462,13 @@ data: ${JSON.stringify({
41248
41462
  }
41249
41463
  if (data.type === "content_block_delta" && data.delta?.type === "text_delta") {
41250
41464
  const txt = data.delta.text || "";
41465
+ opts.onAssistantText?.(txt, "text");
41251
41466
  textChunks++;
41252
41467
  log(`[AnthropicSSE] Text chunk: "${txt.substring(0, 30).replace(/\n/g, "\\n")}" (${txt.length} chars)`);
41253
41468
  }
41254
41469
  if (data.type === "content_block_start" && data.content_block?.type === "tool_use") {
41255
41470
  toolUseBlocks++;
41471
+ opts.onToolCallObserved?.(data.content_block.name);
41256
41472
  log(`[AnthropicSSE] Tool use: ${data.content_block.name}`);
41257
41473
  }
41258
41474
  if (data.type === "message_delta" && data.delta?.stop_reason) {
@@ -41292,10 +41508,12 @@ data: ${JSON.stringify({
41292
41508
  outputTokens = data.usage.output_tokens || outputTokens;
41293
41509
  }
41294
41510
  if (data.type === "content_block_delta" && data.delta?.type === "text_delta") {
41511
+ opts.onAssistantText?.(data.delta.text || "", "text");
41295
41512
  textChunks++;
41296
41513
  }
41297
41514
  if (data.type === "content_block_start" && data.content_block?.type === "tool_use") {
41298
41515
  toolUseBlocks++;
41516
+ opts.onToolCallObserved?.(data.content_block.name);
41299
41517
  log(`[AnthropicSSE] Tool use: ${data.content_block.name}`);
41300
41518
  }
41301
41519
  if (data.type === "message_delta" && data.delta?.stop_reason) {
@@ -41306,6 +41524,7 @@ data: ${JSON.stringify({
41306
41524
  }
41307
41525
  }
41308
41526
  log(`[AnthropicSSE] Stream complete for ${opts.modelName}: ${totalLines} lines, ${textChunks} text chunks, ${toolUseBlocks} tool_use blocks, stop_reason=${stopReason}${filterThinking ? `, filtered ${thinkingBlocksSuppressed} thinking blocks` : ""}`);
41527
+ opts.onTurnEnd?.();
41309
41528
  if (opts.onTokenUpdate) {
41310
41529
  opts.onTokenUpdate(inputTokens, outputTokens);
41311
41530
  }
@@ -41434,6 +41653,7 @@ data: ${JSON.stringify(data)}
41434
41653
  output_tokens: outputTokens
41435
41654
  }
41436
41655
  });
41656
+ opts.onTurnEnd?.();
41437
41657
  send("message_stop", { type: "message_stop" });
41438
41658
  }
41439
41659
  if (!isClosed) {
@@ -41541,6 +41761,7 @@ data: ${JSON.stringify(data)}
41541
41761
  const toolIdx = toolCalls.size;
41542
41762
  const toolId = `toolu_${Date.now()}_${toolIdx}`;
41543
41763
  const blockIndex = curIdx++;
41764
+ opts.onToolCallObserved?.(part.functionCall.name);
41544
41765
  let args = JSON.stringify(part.functionCall.args || {});
41545
41766
  if (opts.repairToolArgs) {
41546
41767
  try {
@@ -41879,6 +42100,7 @@ data: ${JSON.stringify(data)}
41879
42100
  log(`[ResponsesSSE] Event: ${event.type}`);
41880
42101
  }
41881
42102
  if (event.type === "response.output_text.delta") {
42103
+ opts.onAssistantText?.(event.delta ?? "", "text");
41882
42104
  closeReasoning();
41883
42105
  if (textIdx < 0) {
41884
42106
  textIdx = curIdx++;
@@ -41914,6 +42136,7 @@ data: ${JSON.stringify(data)}
41914
42136
  functionCalls.set(itemId, fnCallData);
41915
42137
  }
41916
42138
  openToolBlocks.add(fnCallData);
42139
+ opts.onToolCallObserved?.(fnName);
41917
42140
  if (pendingReasoning.length > 0) {
41918
42141
  rememberReasoningForCall(callId, pendingReasoning);
41919
42142
  pendingReasoning = [];
@@ -41926,6 +42149,7 @@ data: ${JSON.stringify(data)}
41926
42149
  hasToolUse = true;
41927
42150
  }
41928
42151
  } else if (event.type === "response.reasoning_summary_text.delta") {
42152
+ opts.onAssistantText?.(event.delta ?? "", "reasoning");
41929
42153
  const summaryIndex = typeof event.summary_index === "number" ? event.summary_index : 0;
41930
42154
  if (reasoningIdx < 0) {
41931
42155
  closeText();
@@ -42088,6 +42312,7 @@ data: ${JSON.stringify(data)}
42088
42312
  if (opts.middlewareManager) {
42089
42313
  await opts.middlewareManager.afterStreamComplete(opts.modelName, streamMetadata);
42090
42314
  }
42315
+ opts.onTurnEnd?.();
42091
42316
  safeClose();
42092
42317
  } catch (error46) {
42093
42318
  if (pingInterval) {
@@ -42904,7 +43129,10 @@ class ComposedHandler {
42904
43129
  case "openai-sse":
42905
43130
  return createStreamingResponseHandler(c, response, adapter, this.bareModelName, this.middlewareManager, onTokenUpdate, claudeRequest.tools, toolNameMap, priorInputTokens, behaviorSession && {
42906
43131
  shouldBufferTool: (name) => behaviorSession.interceptsTool(name),
42907
- onToolCall: (name, argsJson) => behaviorSession.repairToolCall(name, argsJson)
43132
+ onToolCall: (name, argsJson) => behaviorSession.repairToolCall(name, argsJson),
43133
+ onAssistantText: (text, kind) => behaviorSession.observeText(text, kind),
43134
+ onToolCallObserved: (name) => behaviorSession.observeToolCall(name),
43135
+ onTurnEnd: () => behaviorSession.finishTurn()
42908
43136
  });
42909
43137
  case "openai-responses-sse":
42910
43138
  return createResponsesStreamHandler(c, response, {
@@ -42916,7 +43144,10 @@ class ComposedHandler {
42916
43144
  priorInputTokens,
42917
43145
  middlewareManager: this.middlewareManager,
42918
43146
  shouldBufferTool: (name) => behaviorSession?.interceptsTool(name) ?? false,
42919
- onToolCall: (name, argsJson) => behaviorSession?.repairToolCall(name, argsJson) ?? null
43147
+ onToolCall: (name, argsJson) => behaviorSession?.repairToolCall(name, argsJson) ?? null,
43148
+ onAssistantText: (text, kind) => behaviorSession?.observeText(text, kind),
43149
+ onToolCallObserved: (name) => behaviorSession?.observeToolCall(name),
43150
+ onTurnEnd: () => behaviorSession?.finishTurn()
42920
43151
  });
42921
43152
  case "anthropic-sse":
42922
43153
  return createAnthropicPassthroughStream(c, response, {
@@ -42924,7 +43155,10 @@ class ComposedHandler {
42924
43155
  onTokenUpdate,
42925
43156
  adapter: this.modelAdapter ?? adapter,
42926
43157
  shouldBufferTool: (name) => behaviorSession?.interceptsTool(name) ?? false,
42927
- repairToolArgs: (name, argsJson) => behaviorSession?.repairToolCall(name, argsJson) ?? null
43158
+ repairToolArgs: (name, argsJson) => behaviorSession?.repairToolCall(name, argsJson) ?? null,
43159
+ onAssistantText: (text, kind) => behaviorSession?.observeText(text, kind),
43160
+ onToolCallObserved: (name) => behaviorSession?.observeToolCall(name),
43161
+ onTurnEnd: () => behaviorSession?.finishTurn()
42928
43162
  });
42929
43163
  case "gemini-sse": {
42930
43164
  const onToolCall = (toolId, name, thoughtSignature) => {
@@ -42939,6 +43173,9 @@ class ComposedHandler {
42939
43173
  onTokenUpdate,
42940
43174
  onToolCall,
42941
43175
  repairToolArgs: (name, argsJson) => behaviorSession?.repairToolCall(name, argsJson) ?? null,
43176
+ onAssistantText: (text, kind) => behaviorSession?.observeText(text, kind),
43177
+ onToolCallObserved: (name) => behaviorSession?.observeToolCall(name),
43178
+ onTurnEnd: () => behaviorSession?.finishTurn(),
42942
43179
  unwrapResponse: this.options.unwrapGeminiResponse,
42943
43180
  priorInputTokens
42944
43181
  });
@@ -47062,6 +47299,44 @@ var init_proxy_server = __esm(() => {
47062
47299
  };
47063
47300
  });
47064
47301
 
47302
+ // src/redact.ts
47303
+ function isPlaceholder(value) {
47304
+ return PLACEHOLDER.test(value.trim());
47305
+ }
47306
+ function redactSecrets(text) {
47307
+ if (!text)
47308
+ return "";
47309
+ let out = text;
47310
+ out = out.replace(ASSIGNMENT_RE, (match2, lhs, value) => isPlaceholder(value) ? match2 : `${lhs}${MASK}`);
47311
+ for (const { re } of TOKEN_PATTERNS) {
47312
+ out = out.replace(re, (match2) => {
47313
+ const scheme = /^(Bearer|Basic|Token)\s/.exec(match2);
47314
+ return scheme ? `${scheme[1]} ${MASK}` : MASK;
47315
+ });
47316
+ }
47317
+ return out;
47318
+ }
47319
+ function sanitizeForReport(text) {
47320
+ if (!text)
47321
+ return "";
47322
+ return redactSecrets(text).replace(/\/Users\/[^/\s]+/g, "/Users/***").replace(/\/home\/[^/\s]+/g, "/home/***").replace(/[A-Z]:\\Users\\[^\\\s]+/gi, "C:\\Users\\***").replace(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g, "***@***.***");
47323
+ }
47324
+ var MASK = "***REDACTED***", PLACEHOLDER, ASSIGNMENT_RE, TOKEN_PATTERNS;
47325
+ var init_redact = __esm(() => {
47326
+ PLACEHOLDER = /^(['"`]?)(your[-_a-z0-9]*|<[^>]*>|\.\.\.|x{3,}|\*{3,}|REDACTED|CHANGEME|TODO|\$\{[^}]*\}|)(['"`]?)$/i;
47327
+ ASSIGNMENT_RE = /(["']?\b[A-Z][A-Z0-9_]*(?:_API_KEY|_KEY|_TOKEN|_SECRET|_PASSWORD)\b["']?\s*[:=]\s*)(["'`]?\$\{[^}]*\}["'`]?|["'`]?[^\s"'`,}]+["'`]?)/g;
47328
+ TOKEN_PATTERNS = [
47329
+ { name: "sk", re: /\bsk-[A-Za-z0-9_-]{16,}/g },
47330
+ { name: "google", re: /\bAIza[A-Za-z0-9_-]{20,}/g },
47331
+ { name: "xai", re: /\bxai-[A-Za-z0-9_-]{16,}/g },
47332
+ { name: "github", re: /\bgh[posur]_[A-Za-z0-9]{20,}/g },
47333
+ { name: "aws", re: /\bAKIA[0-9A-Z]{12,}/g },
47334
+ { name: "jwt", re: /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}/g },
47335
+ { name: "zhipu", re: /\b[0-9a-f]{32}\.[A-Za-z0-9]{16}\b/g },
47336
+ { name: "bearer", re: /\b(?:Bearer|Basic|Token)\s+[A-Za-z0-9_.\-+/=]{12,}/g }
47337
+ ];
47338
+ });
47339
+
47065
47340
  // src/team-stats.ts
47066
47341
  import { existsSync as existsSync18, readFileSync as readFileSync16, writeFileSync as writeFileSync11 } from "fs";
47067
47342
  import { join as join25 } from "path";
@@ -47950,6 +48225,13 @@ function formatTeamResult(status, sessionPath) {
47950
48225
  }
47951
48226
  function defineTools(sessionManager, notifyChannel) {
47952
48227
  const tools = [];
48228
+ function withOpFailureContext(message, subject) {
48229
+ const block = renderOpFailureBlock(subject);
48230
+ return block.length === 0 ? message : `${message}
48231
+
48232
+ ${block.join(`
48233
+ `)}`;
48234
+ }
47953
48235
  tools.push({
47954
48236
  name: "run_prompt",
47955
48237
  description: "Run a prompt through any model \u2014 supports all providers (Kimi, GLM, Qwen, MiniMax, Gemini, GPT, Grok, etc.) with auto-routing, fallback chains, and custom routing rules.",
@@ -47984,10 +48266,10 @@ Tokens: ${result.usage.input} input, ${result.usage.output} output`;
47984
48266
  content: [
47985
48267
  {
47986
48268
  type: "text",
47987
- text: `Error: ${errMsg}
48269
+ text: withOpFailureContext(`Error: ${errMsg}
47988
48270
 
47989
48271
  ---
47990
- **To report this error**, use the \`report_error\` tool with \`error_type: "provider_failure"\` and \`model: "${args.model}"\`.`
48272
+ **To report this error**, use the \`report_error\` tool with \`error_type: "provider_failure"\` and \`model: "${args.model}"\`.`, `while routing ${args.model}`)
47991
48273
  }
47992
48274
  ],
47993
48275
  isError: true
@@ -48330,7 +48612,7 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
48330
48612
  content: [
48331
48613
  {
48332
48614
  type: "text",
48333
- text: `Error: ${error46 instanceof Error ? error46.message : String(error46)}`
48615
+ text: withOpFailureContext(`Error: ${error46 instanceof Error ? error46.message : String(error46)}`, "while running the team")
48334
48616
  }
48335
48617
  ],
48336
48618
  isError: true
@@ -48546,10 +48828,10 @@ Report manually at https://github.com/anthropics/claudish/issues${autoSendHint}`
48546
48828
  content: [
48547
48829
  {
48548
48830
  type: "text",
48549
- text: `Error creating session: ${errMsg}
48831
+ text: withOpFailureContext(`Error creating session: ${errMsg}
48550
48832
 
48551
48833
  ---
48552
- **To report this error**, use the \`report_error\` tool with \`error_type: "provider_failure"\` and \`model: "${args.model}"\`.`
48834
+ **To report this error**, use the \`report_error\` tool with \`error_type: "provider_failure"\` and \`model: "${args.model}"\`.`, `while routing ${args.model}`)
48553
48835
  }
48554
48836
  ],
48555
48837
  isError: true
@@ -48805,9 +49087,10 @@ var init_mcp_server = __esm(() => {
48805
49087
  init_channel();
48806
49088
  init_model_loader();
48807
49089
  init_port_manager();
48808
- init_redact();
49090
+ init_onepassword();
48809
49091
  init_provider_definitions();
48810
49092
  init_proxy_server();
49093
+ init_redact();
48811
49094
  init_team_orchestrator();
48812
49095
  import_dotenv2 = __toESM(require_main(), 1);
48813
49096
  import_dotenv2.config({ quiet: true });
@@ -48981,6 +49264,28 @@ Behavior rules
48981
49264
  console.log(` ${dim2(`observer model: ${obs.model}`)}`);
48982
49265
  console.log();
48983
49266
  }
49267
+ function printByModel(records) {
49268
+ const byModel = new Map;
49269
+ for (const r of records) {
49270
+ const m = r.model ?? "unknown";
49271
+ const e = byModel.get(m) ?? { ok: 0, degraded: 0 };
49272
+ if (r.outcome === "degraded")
49273
+ e.degraded++;
49274
+ else
49275
+ e.ok++;
49276
+ byModel.set(m, e);
49277
+ }
49278
+ if (byModel.size === 0)
49279
+ return;
49280
+ console.log(bold2(` by model (degraded / ok)
49281
+ `));
49282
+ const ranked = [...byModel.entries()].sort((a, b) => b[1].degraded - a[1].degraded || b[1].ok - a[1].ok);
49283
+ for (const [model, v] of ranked) {
49284
+ const flag = v.degraded > 0 ? yellow(String(v.degraded)) : dim2(String(v.degraded));
49285
+ console.log(` ${model.padEnd(26)} ${flag} / ${v.ok}`);
49286
+ }
49287
+ console.log();
49288
+ }
48984
49289
  function showCorpus(write, json2) {
48985
49290
  const result = buildCorpus({ write });
48986
49291
  if (json2) {
@@ -48999,25 +49304,7 @@ Behavior divergence corpus
48999
49304
  console.log(` ${yellow("degraded (no plan)")} : ${degraded.length}`);
49000
49305
  console.log(` of those, a rule would have fired on ${catchable.length}
49001
49306
  `);
49002
- const byModel = new Map;
49003
- for (const r of result.records) {
49004
- const m = r.model ?? "unknown";
49005
- const e = byModel.get(m) ?? { ok: 0, degraded: 0 };
49006
- if (r.outcome === "degraded")
49007
- e.degraded++;
49008
- else
49009
- e.ok++;
49010
- byModel.set(m, e);
49011
- }
49012
- if (byModel.size > 0) {
49013
- console.log(bold2(` by model (degraded / ok)
49014
- `));
49015
- for (const [model, v] of [...byModel.entries()].sort((a, b) => b[1].degraded - a[1].degraded || b[1].ok - a[1].ok)) {
49016
- const flag = v.degraded > 0 ? yellow(String(v.degraded)) : dim2("0");
49017
- console.log(` ${model.padEnd(26)} ${flag} / ${v.ok}`);
49018
- }
49019
- console.log();
49020
- }
49307
+ printByModel(result.records);
49021
49308
  if (result.outputPath) {
49022
49309
  console.log(dim2(` appended to ${result.outputPath}
49023
49310
  `));
@@ -49043,9 +49330,9 @@ async function behaviorCommand(argv) {
49043
49330
  default:
49044
49331
  console.error(`Unknown action "${action}".
49045
49332
 
49046
- ` + `Usage:
49047
- ` + ` claudish behavior rules [--json]
49048
- ` + ` claudish behavior corpus [--write] [--json]
49333
+ Usage:
49334
+ claudish behavior rules [--json]
49335
+ claudish behavior corpus [--write] [--json]
49049
49336
  `);
49050
49337
  process.exit(1);
49051
49338
  }
@@ -74829,9 +75116,9 @@ function managedSettingsPath() {
74829
75116
  }
74830
75117
  return "/etc/claude-code/managed-settings.json";
74831
75118
  }
74832
- function managedSettingsForcesClaudeAi(readFile = readFileSync24) {
75119
+ function managedSettingsForcesClaudeAi(readFile2 = readFileSync24) {
74833
75120
  try {
74834
- const raw2 = readFile(managedSettingsPath(), "utf-8");
75121
+ const raw2 = readFile2(managedSettingsPath(), "utf-8");
74835
75122
  const parsed = JSON.parse(raw2);
74836
75123
  return parsed.forceLoginMethod === "claudeai";
74837
75124
  } catch {
@@ -76152,7 +76439,13 @@ var isLegacyGeminiLogout = args.includes("--gemini-logout");
76152
76439
  var isLegacyKimiLogin = args.includes("--kimi-login");
76153
76440
  var isLegacyKimiLogout = args.includes("--kimi-logout");
76154
76441
  if (isMcpMode) {
76155
- Promise.resolve().then(() => (init_mcp_server(), exports_mcp_server)).then((mcp) => mcp.startMcpServer());
76442
+ Promise.resolve().then(() => (init_mcp_server(), exports_mcp_server)).then(async (mcp) => {
76443
+ mcp.startMcpServer();
76444
+ if (process.env.CLAUDISH_STARTUP_TRACE === "1") {
76445
+ const { finalizeStartupTrace: finalizeStartupTrace2 } = await Promise.resolve().then(() => (init_startup_trace(), exports_startup_trace));
76446
+ finalizeStartupTrace2("mcp", { quiet: true });
76447
+ }
76448
+ });
76156
76449
  } else if (isServeCommand) {
76157
76450
  const serveArgIndex = args.indexOf("serve");
76158
76451
  Promise.resolve().then(() => (init_serve_command(), exports_serve_command)).then((m) => m.serveCommand(args.slice(serveArgIndex + 1)).catch((e) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "7.31.0",
3
+ "version": "7.33.0",
4
4
  "description": "Run Claude Code with any model - OpenRouter, Ollama, LM Studio & local models",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -60,10 +60,10 @@
60
60
  "ai"
61
61
  ],
62
62
  "optionalDependencies": {
63
- "@claudish/magmux-darwin-arm64": "7.31.0",
64
- "@claudish/magmux-darwin-x64": "7.31.0",
65
- "@claudish/magmux-linux-arm64": "7.31.0",
66
- "@claudish/magmux-linux-x64": "7.31.0"
63
+ "@claudish/magmux-darwin-arm64": "7.33.0",
64
+ "@claudish/magmux-darwin-x64": "7.33.0",
65
+ "@claudish/magmux-linux-arm64": "7.33.0",
66
+ "@claudish/magmux-linux-x64": "7.33.0"
67
67
  },
68
68
  "author": "Jack Rudenko <i@madappgang.com>",
69
69
  "license": "MIT",