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.
- package/dist/index.js +401 -108
- 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.
|
|
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
|
|
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
|
|
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
|
-
|
|
38199
|
-
|
|
38200
|
-
|
|
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 [
|
|
38203
|
-
|
|
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(
|
|
38241
|
+
if (!globMatches(keyRule, ruleId))
|
|
38206
38242
|
continue;
|
|
38207
|
-
const
|
|
38208
|
-
if (!best ||
|
|
38209
|
-
best = {
|
|
38243
|
+
const score = specificity(keyRule);
|
|
38244
|
+
if (!best || score > best.score)
|
|
38245
|
+
best = { score, severity };
|
|
38210
38246
|
}
|
|
38211
|
-
return best ? best.severity :
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
49047
|
-
|
|
49048
|
-
|
|
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(
|
|
75119
|
+
function managedSettingsForcesClaudeAi(readFile2 = readFileSync24) {
|
|
74833
75120
|
try {
|
|
74834
|
-
const raw2 =
|
|
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) =>
|
|
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.
|
|
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.
|
|
64
|
-
"@claudish/magmux-darwin-x64": "7.
|
|
65
|
-
"@claudish/magmux-linux-arm64": "7.
|
|
66
|
-
"@claudish/magmux-linux-x64": "7.
|
|
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",
|