claudish 7.24.0 → 7.25.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 +697 -143
- 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.25.0";
|
|
655
655
|
|
|
656
656
|
// src/logger.ts
|
|
657
657
|
var exports_logger = {};
|
|
@@ -27006,6 +27006,9 @@ function loadConfig() {
|
|
|
27006
27006
|
if (config2.customEndpoints !== undefined) {
|
|
27007
27007
|
merged.customEndpoints = config2.customEndpoints;
|
|
27008
27008
|
}
|
|
27009
|
+
if (config2.behavior !== undefined) {
|
|
27010
|
+
merged.behavior = config2.behavior;
|
|
27011
|
+
}
|
|
27009
27012
|
return merged;
|
|
27010
27013
|
} catch (error46) {
|
|
27011
27014
|
console.error(`Warning: Failed to load config, using defaults: ${error46}`);
|
|
@@ -36790,6 +36793,555 @@ ${text}`;
|
|
|
36790
36793
|
};
|
|
36791
36794
|
});
|
|
36792
36795
|
|
|
36796
|
+
// ../../node_modules/.bun/zod@4.1.13/node_modules/zod/index.js
|
|
36797
|
+
var init_zod = __esm(() => {
|
|
36798
|
+
init_external2();
|
|
36799
|
+
init_external2();
|
|
36800
|
+
});
|
|
36801
|
+
|
|
36802
|
+
// src/behavior/config.ts
|
|
36803
|
+
function parseBehaviorConfig(raw2) {
|
|
36804
|
+
if (raw2 === undefined || raw2 === null)
|
|
36805
|
+
return {};
|
|
36806
|
+
const result = BehaviorConfigSchema.safeParse(raw2);
|
|
36807
|
+
if (!result.success) {
|
|
36808
|
+
logStderr(`[behavior] Ignoring invalid "behavior" config: ${result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")}`);
|
|
36809
|
+
return {};
|
|
36810
|
+
}
|
|
36811
|
+
return result.data;
|
|
36812
|
+
}
|
|
36813
|
+
function resolveSeverity(ruleId, defaultSeverity, config2) {
|
|
36814
|
+
const rules = config2.rules;
|
|
36815
|
+
if (!rules)
|
|
36816
|
+
return defaultSeverity;
|
|
36817
|
+
const exact = rules[ruleId];
|
|
36818
|
+
if (exact)
|
|
36819
|
+
return exact;
|
|
36820
|
+
let best = null;
|
|
36821
|
+
for (const [pattern, severity] of Object.entries(rules)) {
|
|
36822
|
+
if (!pattern.includes("*"))
|
|
36823
|
+
continue;
|
|
36824
|
+
if (!globMatches(pattern, ruleId))
|
|
36825
|
+
continue;
|
|
36826
|
+
const len = pattern.replace(/\*/g, "").length;
|
|
36827
|
+
if (!best || len > best.len)
|
|
36828
|
+
best = { len, severity };
|
|
36829
|
+
}
|
|
36830
|
+
return best ? best.severity : defaultSeverity;
|
|
36831
|
+
}
|
|
36832
|
+
function globMatches(pattern, value) {
|
|
36833
|
+
const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
36834
|
+
return new RegExp(`^${escaped}$`).test(value);
|
|
36835
|
+
}
|
|
36836
|
+
var SeveritySchema, BehaviorConfigSchema;
|
|
36837
|
+
var init_config = __esm(() => {
|
|
36838
|
+
init_zod();
|
|
36839
|
+
init_logger();
|
|
36840
|
+
SeveritySchema = exports_external.enum(["off", "warn", "fix"]);
|
|
36841
|
+
BehaviorConfigSchema = exports_external.object({
|
|
36842
|
+
preset: exports_external.string().optional(),
|
|
36843
|
+
rules: exports_external.record(exports_external.string(), SeveritySchema).optional(),
|
|
36844
|
+
hooks: exports_external.array(exports_external.string()).optional(),
|
|
36845
|
+
observer: exports_external.object({
|
|
36846
|
+
enabled: exports_external.boolean().optional(),
|
|
36847
|
+
mode: exports_external.enum(["off", "suggest", "enforce"]).optional(),
|
|
36848
|
+
model: exports_external.string().optional(),
|
|
36849
|
+
timeoutMs: exports_external.number().int().positive().optional()
|
|
36850
|
+
}).optional()
|
|
36851
|
+
});
|
|
36852
|
+
});
|
|
36853
|
+
|
|
36854
|
+
// src/behavior/harness.ts
|
|
36855
|
+
function textOf(value) {
|
|
36856
|
+
if (!value)
|
|
36857
|
+
return "";
|
|
36858
|
+
if (typeof value === "string")
|
|
36859
|
+
return value;
|
|
36860
|
+
if (Array.isArray(value)) {
|
|
36861
|
+
let out = "";
|
|
36862
|
+
for (const part of value) {
|
|
36863
|
+
if (typeof part === "string")
|
|
36864
|
+
out += part;
|
|
36865
|
+
else if (typeof part?.text === "string")
|
|
36866
|
+
out += part.text;
|
|
36867
|
+
else if (typeof part?.content === "string")
|
|
36868
|
+
out += part.content;
|
|
36869
|
+
}
|
|
36870
|
+
return out;
|
|
36871
|
+
}
|
|
36872
|
+
if (typeof value?.text === "string")
|
|
36873
|
+
return value.text;
|
|
36874
|
+
return "";
|
|
36875
|
+
}
|
|
36876
|
+
function matchPlanPath(text) {
|
|
36877
|
+
if (!PLAN_MODE_HINT.test(text))
|
|
36878
|
+
return;
|
|
36879
|
+
for (const re of PLAN_PATH_PATTERNS) {
|
|
36880
|
+
const m = re.exec(text);
|
|
36881
|
+
if (m?.[1])
|
|
36882
|
+
return m[1];
|
|
36883
|
+
}
|
|
36884
|
+
return;
|
|
36885
|
+
}
|
|
36886
|
+
function detectHarnessFacts(claudeRequest) {
|
|
36887
|
+
const facts = { planModeActive: false };
|
|
36888
|
+
let planPath = matchPlanPath(textOf(claudeRequest?.system));
|
|
36889
|
+
if (!planPath && Array.isArray(claudeRequest?.messages)) {
|
|
36890
|
+
const messages = claudeRequest.messages;
|
|
36891
|
+
for (let i = messages.length - 1;i >= 0; i--) {
|
|
36892
|
+
planPath = matchPlanPath(textOf(messages[i]?.content));
|
|
36893
|
+
if (planPath)
|
|
36894
|
+
break;
|
|
36895
|
+
}
|
|
36896
|
+
}
|
|
36897
|
+
if (planPath) {
|
|
36898
|
+
facts.planModeActive = true;
|
|
36899
|
+
facts.planFilePath = planPath;
|
|
36900
|
+
const slash = planPath.lastIndexOf("/");
|
|
36901
|
+
if (slash > 0)
|
|
36902
|
+
facts.planDir = planPath.slice(0, slash);
|
|
36903
|
+
}
|
|
36904
|
+
return facts;
|
|
36905
|
+
}
|
|
36906
|
+
var PLAN_PATH_PATTERNS, PLAN_MODE_HINT;
|
|
36907
|
+
var init_harness = __esm(() => {
|
|
36908
|
+
PLAN_PATH_PATTERNS = [
|
|
36909
|
+
/You should create your plan at\s+(\S+?\.md)/,
|
|
36910
|
+
/A plan file already exists at\s+(\S+?\.md)/,
|
|
36911
|
+
/Read-only except plan file\s*\(([^)]+\.md)\)/
|
|
36912
|
+
];
|
|
36913
|
+
PLAN_MODE_HINT = /plan file|create your plan at|Plan mode is active|Plan mode still active/i;
|
|
36914
|
+
});
|
|
36915
|
+
|
|
36916
|
+
// src/behavior/engine.ts
|
|
36917
|
+
class BehaviorSession {
|
|
36918
|
+
active;
|
|
36919
|
+
modelId;
|
|
36920
|
+
providerName;
|
|
36921
|
+
facts = { planModeActive: false };
|
|
36922
|
+
bufferedTools = new Set;
|
|
36923
|
+
constructor(active, modelId, providerName) {
|
|
36924
|
+
this.active = active;
|
|
36925
|
+
this.modelId = modelId;
|
|
36926
|
+
this.providerName = providerName;
|
|
36927
|
+
}
|
|
36928
|
+
armBuffering() {
|
|
36929
|
+
const armed = new Set;
|
|
36930
|
+
for (const { rule, severity } of this.active) {
|
|
36931
|
+
if (severity !== "fix")
|
|
36932
|
+
continue;
|
|
36933
|
+
if (rule.armed && !rule.armed(this.facts))
|
|
36934
|
+
continue;
|
|
36935
|
+
for (const t of rule.interceptsTools ?? [])
|
|
36936
|
+
armed.add(t);
|
|
36937
|
+
}
|
|
36938
|
+
this.bufferedTools = armed;
|
|
36939
|
+
}
|
|
36940
|
+
get harness() {
|
|
36941
|
+
return this.facts;
|
|
36942
|
+
}
|
|
36943
|
+
get isNoop() {
|
|
36944
|
+
return this.active.length === 0;
|
|
36945
|
+
}
|
|
36946
|
+
applyRequest(claudeRequest, claudeTools, tools, messages) {
|
|
36947
|
+
if (this.active.length === 0)
|
|
36948
|
+
return;
|
|
36949
|
+
this.facts = detectHarnessFacts(claudeRequest);
|
|
36950
|
+
this.armBuffering();
|
|
36951
|
+
const ctx = {
|
|
36952
|
+
modelId: this.modelId,
|
|
36953
|
+
providerName: this.providerName,
|
|
36954
|
+
isNativeAnthropic: false,
|
|
36955
|
+
claudeRequest,
|
|
36956
|
+
claudeTools,
|
|
36957
|
+
tools,
|
|
36958
|
+
messages,
|
|
36959
|
+
harness: this.facts
|
|
36960
|
+
};
|
|
36961
|
+
for (const { rule, severity } of this.active) {
|
|
36962
|
+
if (!rule.onRequest)
|
|
36963
|
+
continue;
|
|
36964
|
+
let actions = [];
|
|
36965
|
+
try {
|
|
36966
|
+
actions = rule.onRequest(ctx) ?? [];
|
|
36967
|
+
} catch (err) {
|
|
36968
|
+
log(`[behavior] rule ${rule.id} onRequest threw: ${err}`);
|
|
36969
|
+
continue;
|
|
36970
|
+
}
|
|
36971
|
+
for (const action of actions)
|
|
36972
|
+
this.applyAction(rule.id, severity, action, ctx);
|
|
36973
|
+
}
|
|
36974
|
+
}
|
|
36975
|
+
interceptsTool(toolName) {
|
|
36976
|
+
return this.bufferedTools.has(toolName);
|
|
36977
|
+
}
|
|
36978
|
+
repairToolCall(toolName, rawArgs) {
|
|
36979
|
+
if (!this.bufferedTools.has(toolName))
|
|
36980
|
+
return null;
|
|
36981
|
+
let args = {};
|
|
36982
|
+
try {
|
|
36983
|
+
const parsed = JSON.parse(rawArgs || "{}");
|
|
36984
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed))
|
|
36985
|
+
args = parsed;
|
|
36986
|
+
} catch {
|
|
36987
|
+
return null;
|
|
36988
|
+
}
|
|
36989
|
+
let changed = false;
|
|
36990
|
+
for (const { rule, severity } of this.active) {
|
|
36991
|
+
if (!rule.onToolCall)
|
|
36992
|
+
continue;
|
|
36993
|
+
if (!(rule.interceptsTools ?? []).includes(toolName))
|
|
36994
|
+
continue;
|
|
36995
|
+
let actions = [];
|
|
36996
|
+
try {
|
|
36997
|
+
actions = rule.onToolCall({
|
|
36998
|
+
modelId: this.modelId,
|
|
36999
|
+
toolName,
|
|
37000
|
+
args,
|
|
37001
|
+
rawArgs,
|
|
37002
|
+
harness: this.facts
|
|
37003
|
+
}) ?? [];
|
|
37004
|
+
} catch (err) {
|
|
37005
|
+
log(`[behavior] rule ${rule.id} onToolCall threw: ${err}`);
|
|
37006
|
+
continue;
|
|
37007
|
+
}
|
|
37008
|
+
for (const action of actions) {
|
|
37009
|
+
if (action.type === "warn") {
|
|
37010
|
+
log(`[behavior] ${rule.id} (warn): ${action.message}`);
|
|
37011
|
+
continue;
|
|
37012
|
+
}
|
|
37013
|
+
if (action.type !== "repairToolArgs")
|
|
37014
|
+
continue;
|
|
37015
|
+
if (severity !== "fix") {
|
|
37016
|
+
log(`[behavior] ${rule.id} (warn-only, not applied): ${action.reason}`);
|
|
37017
|
+
continue;
|
|
37018
|
+
}
|
|
37019
|
+
args = action.args;
|
|
37020
|
+
changed = true;
|
|
37021
|
+
log(`[behavior] ${rule.id} repaired ${toolName}: ${action.reason}`);
|
|
37022
|
+
}
|
|
37023
|
+
}
|
|
37024
|
+
return changed ? JSON.stringify(args) : null;
|
|
37025
|
+
}
|
|
37026
|
+
applyAction(ruleId, severity, action, ctx) {
|
|
37027
|
+
if (action.type === "warn") {
|
|
37028
|
+
log(`[behavior] ${ruleId} (warn): ${action.message}`);
|
|
37029
|
+
return;
|
|
37030
|
+
}
|
|
37031
|
+
if (severity !== "fix") {
|
|
37032
|
+
log(`[behavior] ${ruleId} (warn-only, not applied): ${action.type}`);
|
|
37033
|
+
return;
|
|
37034
|
+
}
|
|
37035
|
+
switch (action.type) {
|
|
37036
|
+
case "injectSystemNote": {
|
|
37037
|
+
const req = ctx.claudeRequest;
|
|
37038
|
+
if (typeof req.system === "string") {
|
|
37039
|
+
req.system = `${req.system}
|
|
37040
|
+
|
|
37041
|
+
${action.text}`;
|
|
37042
|
+
} else if (Array.isArray(req.system)) {
|
|
37043
|
+
req.system.push({ type: "text", text: action.text });
|
|
37044
|
+
} else {
|
|
37045
|
+
req.system = action.text;
|
|
37046
|
+
}
|
|
37047
|
+
log(`[behavior] ${ruleId} injected system note (${action.text.length} chars)`);
|
|
37048
|
+
break;
|
|
37049
|
+
}
|
|
37050
|
+
case "rewriteToolDescription": {
|
|
37051
|
+
let hits = 0;
|
|
37052
|
+
for (const t of ctx.claudeTools) {
|
|
37053
|
+
if (t?.name !== action.tool)
|
|
37054
|
+
continue;
|
|
37055
|
+
t.description = `${t.description ?? ""}${action.append}`;
|
|
37056
|
+
hits++;
|
|
37057
|
+
}
|
|
37058
|
+
for (const t of ctx.tools) {
|
|
37059
|
+
const fn = t?.function ?? t;
|
|
37060
|
+
if (fn?.name !== action.tool)
|
|
37061
|
+
continue;
|
|
37062
|
+
fn.description = `${fn.description ?? ""}${action.append}`;
|
|
37063
|
+
hits++;
|
|
37064
|
+
}
|
|
37065
|
+
log(`[behavior] ${ruleId} rewrote description of ${action.tool} (${hits} site(s))`);
|
|
37066
|
+
break;
|
|
37067
|
+
}
|
|
37068
|
+
case "repairToolArgs":
|
|
37069
|
+
log(`[behavior] ${ruleId} returned repairToolArgs from onRequest \u2014 ignored`);
|
|
37070
|
+
break;
|
|
37071
|
+
}
|
|
37072
|
+
}
|
|
37073
|
+
}
|
|
37074
|
+
|
|
37075
|
+
class BehaviorEngine {
|
|
37076
|
+
config;
|
|
37077
|
+
rules;
|
|
37078
|
+
constructor(config2, rules) {
|
|
37079
|
+
this.config = config2;
|
|
37080
|
+
this.rules = rules;
|
|
37081
|
+
}
|
|
37082
|
+
startSession(params) {
|
|
37083
|
+
const active = [];
|
|
37084
|
+
if (!params.isNativeAnthropic) {
|
|
37085
|
+
for (const rule of this.rules) {
|
|
37086
|
+
const severity = resolveSeverity(rule.id, rule.defaultSeverity, this.config);
|
|
37087
|
+
if (severity === "off")
|
|
37088
|
+
continue;
|
|
37089
|
+
let applies = false;
|
|
37090
|
+
try {
|
|
37091
|
+
applies = rule.appliesTo(params);
|
|
37092
|
+
} catch (err) {
|
|
37093
|
+
log(`[behavior] rule ${rule.id} appliesTo threw: ${err}`);
|
|
37094
|
+
continue;
|
|
37095
|
+
}
|
|
37096
|
+
if (applies)
|
|
37097
|
+
active.push({ rule, severity });
|
|
37098
|
+
}
|
|
37099
|
+
}
|
|
37100
|
+
if (active.length > 0) {
|
|
37101
|
+
log(`[behavior] ${active.length} rule(s) active for ${params.modelId}: ` + active.map((a) => `${a.rule.id}=${a.severity}`).join(", "));
|
|
37102
|
+
}
|
|
37103
|
+
return new BehaviorSession(active, params.modelId, params.providerName);
|
|
37104
|
+
}
|
|
37105
|
+
}
|
|
37106
|
+
var init_engine = __esm(() => {
|
|
37107
|
+
init_logger();
|
|
37108
|
+
init_config();
|
|
37109
|
+
init_harness();
|
|
37110
|
+
});
|
|
37111
|
+
|
|
37112
|
+
// src/behavior/rules/plan-mode.ts
|
|
37113
|
+
function directoryOf(filePath) {
|
|
37114
|
+
const slash = filePath.lastIndexOf("/");
|
|
37115
|
+
return slash > 0 ? filePath.slice(0, slash) : undefined;
|
|
37116
|
+
}
|
|
37117
|
+
var WRITE_TOOLS, planFilePathRule, PLAN_MODE_RULES;
|
|
37118
|
+
var init_plan_mode = __esm(() => {
|
|
37119
|
+
WRITE_TOOLS = ["Write", "Edit", "NotebookEdit"];
|
|
37120
|
+
planFilePathRule = {
|
|
37121
|
+
id: "plan-mode/plan-file-path",
|
|
37122
|
+
description: "Keep plan-mode writes on the plan file Claude Code assigned, and name that " + "path in the ExitPlanMode description.",
|
|
37123
|
+
defaultSeverity: "fix",
|
|
37124
|
+
interceptsTools: WRITE_TOOLS,
|
|
37125
|
+
appliesTo: ({ isNativeAnthropic }) => !isNativeAnthropic,
|
|
37126
|
+
armed: (facts) => facts.planModeActive === true,
|
|
37127
|
+
onRequest(ctx) {
|
|
37128
|
+
const { planModeActive, planFilePath } = ctx.harness;
|
|
37129
|
+
if (!planModeActive || !planFilePath)
|
|
37130
|
+
return [];
|
|
37131
|
+
const hasExitPlanMode = ctx.claudeTools.some((t) => t?.name === "ExitPlanMode") || ctx.tools.some((t) => (t?.function ?? t)?.name === "ExitPlanMode");
|
|
37132
|
+
if (!hasExitPlanMode)
|
|
37133
|
+
return [];
|
|
37134
|
+
return [
|
|
37135
|
+
{
|
|
37136
|
+
type: "rewriteToolDescription",
|
|
37137
|
+
tool: "ExitPlanMode",
|
|
37138
|
+
append: `
|
|
37139
|
+
|
|
37140
|
+
## Plan file for THIS session
|
|
37141
|
+
Your plan MUST be written to exactly this path:
|
|
37142
|
+
${planFilePath}
|
|
37143
|
+
Do not invent a different filename, and do not derive one from the task. Claude Code reads only that exact path; a plan written anywhere else is invisible to it and the approval will show "No plan found".`
|
|
37144
|
+
}
|
|
37145
|
+
];
|
|
37146
|
+
},
|
|
37147
|
+
onToolCall(ctx) {
|
|
37148
|
+
const { planFilePath, planDir } = ctx.harness;
|
|
37149
|
+
if (!planFilePath || !planDir)
|
|
37150
|
+
return [];
|
|
37151
|
+
const filePath = ctx.args.file_path;
|
|
37152
|
+
if (typeof filePath !== "string" || filePath === planFilePath)
|
|
37153
|
+
return [];
|
|
37154
|
+
if (directoryOf(filePath) !== planDir)
|
|
37155
|
+
return [];
|
|
37156
|
+
return [
|
|
37157
|
+
{
|
|
37158
|
+
type: "repairToolArgs",
|
|
37159
|
+
args: { ...ctx.args, file_path: planFilePath },
|
|
37160
|
+
reason: `redirected ${ctx.toolName} from ${filePath} to the session's assigned ` + `plan file ${planFilePath}`
|
|
37161
|
+
}
|
|
37162
|
+
];
|
|
37163
|
+
}
|
|
37164
|
+
};
|
|
37165
|
+
PLAN_MODE_RULES = [planFilePathRule];
|
|
37166
|
+
});
|
|
37167
|
+
|
|
37168
|
+
// src/behavior/hooks.ts
|
|
37169
|
+
import { isAbsolute, resolve } from "path";
|
|
37170
|
+
function isBehaviorRule(value) {
|
|
37171
|
+
return !!value && typeof value === "object" && typeof value.id === "string" && value.id.length > 0 && typeof value.appliesTo === "function" && (value.onRequest === undefined || typeof value.onRequest === "function") && (value.onToolCall === undefined || typeof value.onToolCall === "function");
|
|
37172
|
+
}
|
|
37173
|
+
function collectRules(mod) {
|
|
37174
|
+
const found = [];
|
|
37175
|
+
const consider = (v) => {
|
|
37176
|
+
if (Array.isArray(v))
|
|
37177
|
+
v.forEach(consider);
|
|
37178
|
+
else if (isBehaviorRule(v))
|
|
37179
|
+
found.push(v);
|
|
37180
|
+
};
|
|
37181
|
+
consider(mod?.default);
|
|
37182
|
+
consider(mod?.rules);
|
|
37183
|
+
for (const [key, value] of Object.entries(mod ?? {})) {
|
|
37184
|
+
if (key === "default" || key === "rules")
|
|
37185
|
+
continue;
|
|
37186
|
+
consider(value);
|
|
37187
|
+
}
|
|
37188
|
+
return [...new Set(found)];
|
|
37189
|
+
}
|
|
37190
|
+
function shortName(path) {
|
|
37191
|
+
const base = path.split("/").pop() ?? path;
|
|
37192
|
+
return base.replace(/\.[cm]?[jt]s$/, "");
|
|
37193
|
+
}
|
|
37194
|
+
async function loadHookRules(paths, cwd = process.cwd()) {
|
|
37195
|
+
if (!paths?.length)
|
|
37196
|
+
return [];
|
|
37197
|
+
const loaded = [];
|
|
37198
|
+
const seen = new Set;
|
|
37199
|
+
for (const raw2 of paths) {
|
|
37200
|
+
const abs = isAbsolute(raw2) ? raw2 : resolve(cwd, raw2);
|
|
37201
|
+
const rules = await importHook(abs, raw2);
|
|
37202
|
+
for (const rule of rules)
|
|
37203
|
+
namespaceInto(rule, abs, seen, loaded);
|
|
37204
|
+
}
|
|
37205
|
+
if (loaded.length > 0) {
|
|
37206
|
+
logStderr(`[behavior] Loaded ${loaded.length} hook rule(s): ${loaded.map((r) => r.id).join(", ")}`);
|
|
37207
|
+
}
|
|
37208
|
+
return loaded;
|
|
37209
|
+
}
|
|
37210
|
+
async function importHook(abs, raw2) {
|
|
37211
|
+
let mod;
|
|
37212
|
+
try {
|
|
37213
|
+
mod = await import(abs);
|
|
37214
|
+
} catch (err) {
|
|
37215
|
+
logStderr(`[behavior] Skipping hook ${raw2}: ${err instanceof Error ? err.message : err}`);
|
|
37216
|
+
return [];
|
|
37217
|
+
}
|
|
37218
|
+
const rules = collectRules(mod);
|
|
37219
|
+
if (rules.length === 0) {
|
|
37220
|
+
logStderr(`[behavior] Hook ${raw2} exported no valid BehaviorRule \u2014 skipped`);
|
|
37221
|
+
}
|
|
37222
|
+
return rules;
|
|
37223
|
+
}
|
|
37224
|
+
function namespaceInto(rule, abs, seen, out) {
|
|
37225
|
+
const namespaced = `hook:${shortName(abs)}/${rule.id}`;
|
|
37226
|
+
if (seen.has(namespaced)) {
|
|
37227
|
+
logStderr(`[behavior] Duplicate hook rule ${namespaced} \u2014 keeping the first`);
|
|
37228
|
+
return;
|
|
37229
|
+
}
|
|
37230
|
+
seen.add(namespaced);
|
|
37231
|
+
out.push({
|
|
37232
|
+
...rule,
|
|
37233
|
+
id: namespaced,
|
|
37234
|
+
defaultSeverity: rule.defaultSeverity ?? "warn"
|
|
37235
|
+
});
|
|
37236
|
+
}
|
|
37237
|
+
var init_hooks = __esm(() => {
|
|
37238
|
+
init_logger();
|
|
37239
|
+
});
|
|
37240
|
+
|
|
37241
|
+
// src/behavior/observer/digest.ts
|
|
37242
|
+
var PATH_KEYS;
|
|
37243
|
+
var init_digest = __esm(() => {
|
|
37244
|
+
PATH_KEYS = new Set(["file_path", "path", "notebook_path", "filePath"]);
|
|
37245
|
+
});
|
|
37246
|
+
|
|
37247
|
+
// src/providers/ollama-discovery.ts
|
|
37248
|
+
function ollamaBaseUrl() {
|
|
37249
|
+
return process.env.OLLAMA_HOST || process.env.OLLAMA_BASE_URL || "http://localhost:11434";
|
|
37250
|
+
}
|
|
37251
|
+
async function fetchOllamaModels(options = {}) {
|
|
37252
|
+
const { enrichCapabilities = true } = options;
|
|
37253
|
+
const host = ollamaBaseUrl();
|
|
37254
|
+
try {
|
|
37255
|
+
const response = await fetch(`${host}/api/tags`, {
|
|
37256
|
+
signal: AbortSignal.timeout(3000)
|
|
37257
|
+
});
|
|
37258
|
+
if (!response.ok)
|
|
37259
|
+
return [];
|
|
37260
|
+
const data = await response.json();
|
|
37261
|
+
const models = data.models || [];
|
|
37262
|
+
const enriched = await Promise.all(models.map(async (m) => {
|
|
37263
|
+
let capabilities = [];
|
|
37264
|
+
if (enrichCapabilities) {
|
|
37265
|
+
try {
|
|
37266
|
+
const showResponse = await fetch(`${host}/api/show`, {
|
|
37267
|
+
method: "POST",
|
|
37268
|
+
headers: { "Content-Type": "application/json" },
|
|
37269
|
+
body: JSON.stringify({ name: m.name }),
|
|
37270
|
+
signal: AbortSignal.timeout(2000)
|
|
37271
|
+
});
|
|
37272
|
+
if (showResponse.ok) {
|
|
37273
|
+
const showData = await showResponse.json();
|
|
37274
|
+
capabilities = showData.capabilities || [];
|
|
37275
|
+
}
|
|
37276
|
+
} catch {}
|
|
37277
|
+
}
|
|
37278
|
+
const nameLower = String(m.name).toLowerCase();
|
|
37279
|
+
const supportsTools = capabilities.includes("tools");
|
|
37280
|
+
const isEmbeddingModel = capabilities.includes("embedding") || nameLower.includes("embed");
|
|
37281
|
+
const sizeInfo = m.details?.parameter_size || "unknown size";
|
|
37282
|
+
const toolsIndicator = supportsTools ? "\u2713 tools" : "\u2717 no tools";
|
|
37283
|
+
return {
|
|
37284
|
+
id: `ollama/${m.name}`,
|
|
37285
|
+
name: m.name,
|
|
37286
|
+
description: `Local Ollama model (${sizeInfo}, ${toolsIndicator})`,
|
|
37287
|
+
provider: "ollama",
|
|
37288
|
+
pricing: { prompt: "0", completion: "0" },
|
|
37289
|
+
isLocal: true,
|
|
37290
|
+
supportsTools,
|
|
37291
|
+
isEmbeddingModel,
|
|
37292
|
+
capabilities,
|
|
37293
|
+
details: m.details,
|
|
37294
|
+
size: m.size
|
|
37295
|
+
};
|
|
37296
|
+
}));
|
|
37297
|
+
return enriched.filter((m) => !m.isEmbeddingModel);
|
|
37298
|
+
} catch {
|
|
37299
|
+
return [];
|
|
37300
|
+
}
|
|
37301
|
+
}
|
|
37302
|
+
|
|
37303
|
+
// src/behavior/observer/client.ts
|
|
37304
|
+
var init_client = __esm(() => {
|
|
37305
|
+
init_logger();
|
|
37306
|
+
});
|
|
37307
|
+
|
|
37308
|
+
// src/behavior/observer/corpus.ts
|
|
37309
|
+
var WRITE_TOOLS2;
|
|
37310
|
+
var init_corpus = __esm(() => {
|
|
37311
|
+
WRITE_TOOLS2 = new Set(["Write", "Edit", "NotebookEdit"]);
|
|
37312
|
+
});
|
|
37313
|
+
|
|
37314
|
+
// src/behavior/index.ts
|
|
37315
|
+
function createBehaviorEngine(rawConfig, extraRules = []) {
|
|
37316
|
+
return new BehaviorEngine(parseBehaviorConfig(rawConfig), [...BUILTIN_RULES, ...extraRules]);
|
|
37317
|
+
}
|
|
37318
|
+
function getBehaviorEngine() {
|
|
37319
|
+
if (!sharedEngine) {
|
|
37320
|
+
sharedEngine = createBehaviorEngine(loadConfig().behavior, hookRules);
|
|
37321
|
+
}
|
|
37322
|
+
return sharedEngine;
|
|
37323
|
+
}
|
|
37324
|
+
function registerHookRules(rules) {
|
|
37325
|
+
hookRules = [...hookRules, ...rules];
|
|
37326
|
+
sharedEngine = null;
|
|
37327
|
+
}
|
|
37328
|
+
var BUILTIN_RULES, sharedEngine = null, hookRules;
|
|
37329
|
+
var init_behavior = __esm(() => {
|
|
37330
|
+
init_profile_config();
|
|
37331
|
+
init_config();
|
|
37332
|
+
init_engine();
|
|
37333
|
+
init_plan_mode();
|
|
37334
|
+
init_engine();
|
|
37335
|
+
init_config();
|
|
37336
|
+
init_harness();
|
|
37337
|
+
init_hooks();
|
|
37338
|
+
init_digest();
|
|
37339
|
+
init_client();
|
|
37340
|
+
init_corpus();
|
|
37341
|
+
BUILTIN_RULES = [...PLAN_MODE_RULES];
|
|
37342
|
+
hookRules = [];
|
|
37343
|
+
});
|
|
37344
|
+
|
|
36793
37345
|
// src/middleware/manager.ts
|
|
36794
37346
|
class MiddlewareManager {
|
|
36795
37347
|
middlewares = [];
|
|
@@ -37112,7 +37664,7 @@ class OpenAIProviderTransport {
|
|
|
37112
37664
|
delayMs = 500 * (attempt + 1);
|
|
37113
37665
|
}
|
|
37114
37666
|
log(`[${this.displayName}] 429 rate limited, retry ${attempt + 1}/${maxRetries} in ${(delayMs / 1000).toFixed(1)}s`);
|
|
37115
|
-
await new Promise((
|
|
37667
|
+
await new Promise((resolve2) => setTimeout(resolve2, delayMs));
|
|
37116
37668
|
continue;
|
|
37117
37669
|
}
|
|
37118
37670
|
return response;
|
|
@@ -37831,11 +38383,11 @@ async function runConsentPrompt(ctx) {
|
|
|
37831
38383
|
Does NOT send: prompts, paths, API keys, or credentials.
|
|
37832
38384
|
Disable anytime: claudish telemetry off
|
|
37833
38385
|
`);
|
|
37834
|
-
const answer = await new Promise((
|
|
38386
|
+
const answer = await new Promise((resolve2) => {
|
|
37835
38387
|
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
37836
38388
|
rl.question("Send anonymous error report? [y/N] ", (ans) => {
|
|
37837
38389
|
rl.close();
|
|
37838
|
-
|
|
38390
|
+
resolve2(ans.trim().toLowerCase());
|
|
37839
38391
|
});
|
|
37840
38392
|
});
|
|
37841
38393
|
const accepted = answer === "y" || answer === "yes";
|
|
@@ -38576,8 +39128,8 @@ async function sniffResponsesStreamHead(response, opts = {}) {
|
|
|
38576
39128
|
return { kind: "clean", response: replayResponse() };
|
|
38577
39129
|
}
|
|
38578
39130
|
let timer;
|
|
38579
|
-
const timeout = new Promise((
|
|
38580
|
-
timer = setTimeout(() =>
|
|
39131
|
+
const timeout = new Promise((resolve2) => {
|
|
39132
|
+
timer = setTimeout(() => resolve2("timeout"), remaining);
|
|
38581
39133
|
});
|
|
38582
39134
|
let result;
|
|
38583
39135
|
try {
|
|
@@ -39306,6 +39858,7 @@ function createResponsesStreamHandler(c, response, opts) {
|
|
|
39306
39858
|
let lastActivity = Date.now();
|
|
39307
39859
|
let pingInterval = null;
|
|
39308
39860
|
let isClosed = false;
|
|
39861
|
+
const streamMetadata = new Map;
|
|
39309
39862
|
const functionCalls = new Map;
|
|
39310
39863
|
const openToolBlocks = new Set;
|
|
39311
39864
|
const stream = new ReadableStream({
|
|
@@ -39337,6 +39890,13 @@ data: ${JSON.stringify(data)}
|
|
|
39337
39890
|
};
|
|
39338
39891
|
const closeTools = () => {
|
|
39339
39892
|
for (const fnCall of openToolBlocks) {
|
|
39893
|
+
if (fnCall.buffered && fnCall.arguments) {
|
|
39894
|
+
send("content_block_delta", {
|
|
39895
|
+
type: "content_block_delta",
|
|
39896
|
+
index: fnCall.index,
|
|
39897
|
+
delta: { type: "input_json_delta", partial_json: fnCall.arguments }
|
|
39898
|
+
});
|
|
39899
|
+
}
|
|
39340
39900
|
send("content_block_stop", { type: "content_block_stop", index: fnCall.index });
|
|
39341
39901
|
}
|
|
39342
39902
|
openToolBlocks.clear();
|
|
@@ -39383,6 +39943,14 @@ data: ${JSON.stringify(data)}
|
|
|
39383
39943
|
}
|
|
39384
39944
|
try {
|
|
39385
39945
|
const event = JSON.parse(data);
|
|
39946
|
+
if (opts.middlewareManager) {
|
|
39947
|
+
await opts.middlewareManager.afterStreamChunk({
|
|
39948
|
+
modelId: opts.modelName,
|
|
39949
|
+
chunk: event,
|
|
39950
|
+
delta: event,
|
|
39951
|
+
metadata: streamMetadata
|
|
39952
|
+
});
|
|
39953
|
+
}
|
|
39386
39954
|
if (getLogLevel() === "debug" && event.type) {
|
|
39387
39955
|
log(`[ResponsesSSE] Event: ${event.type}`);
|
|
39388
39956
|
}
|
|
@@ -39414,7 +39982,8 @@ data: ${JSON.stringify(data)}
|
|
|
39414
39982
|
name: fnName,
|
|
39415
39983
|
arguments: "",
|
|
39416
39984
|
index: curIdx++,
|
|
39417
|
-
claudeId: callId
|
|
39985
|
+
claudeId: callId,
|
|
39986
|
+
buffered: opts.shouldBufferTool?.(fnName) === true
|
|
39418
39987
|
};
|
|
39419
39988
|
functionCalls.set(openaiCallId, fnCallData);
|
|
39420
39989
|
if (itemId && itemId !== openaiCallId) {
|
|
@@ -39463,11 +40032,13 @@ data: ${JSON.stringify(data)}
|
|
|
39463
40032
|
const fnCall = functionCalls.get(callId);
|
|
39464
40033
|
if (fnCall) {
|
|
39465
40034
|
fnCall.arguments += event.delta || "";
|
|
39466
|
-
|
|
39467
|
-
|
|
39468
|
-
|
|
39469
|
-
|
|
39470
|
-
|
|
40035
|
+
if (!fnCall.buffered) {
|
|
40036
|
+
send("content_block_delta", {
|
|
40037
|
+
type: "content_block_delta",
|
|
40038
|
+
index: fnCall.index,
|
|
40039
|
+
delta: { type: "input_json_delta", partial_json: event.delta || "" }
|
|
40040
|
+
});
|
|
40041
|
+
}
|
|
39471
40042
|
}
|
|
39472
40043
|
} else if (event.type === "response.output_item.done") {
|
|
39473
40044
|
if (event.item?.type === "reasoning" && event.item.encrypted_content) {
|
|
@@ -39482,6 +40053,23 @@ data: ${JSON.stringify(data)}
|
|
|
39482
40053
|
const callId = event.item.call_id || event.item.id;
|
|
39483
40054
|
const fnCall = functionCalls.get(callId) || functionCalls.get(event.item.id);
|
|
39484
40055
|
if (fnCall && openToolBlocks.has(fnCall)) {
|
|
40056
|
+
if (fnCall.buffered) {
|
|
40057
|
+
let finalArgs = fnCall.arguments;
|
|
40058
|
+
try {
|
|
40059
|
+
const repaired = opts.onToolCall?.(fnCall.name, finalArgs);
|
|
40060
|
+
if (typeof repaired === "string" && repaired !== finalArgs) {
|
|
40061
|
+
log(`[ResponsesSSE] tool call repaired: ${fnCall.name}`);
|
|
40062
|
+
finalArgs = repaired;
|
|
40063
|
+
}
|
|
40064
|
+
} catch (err) {
|
|
40065
|
+
log(`[ResponsesSSE] onToolCall threw for ${fnCall.name}: ${err}`);
|
|
40066
|
+
}
|
|
40067
|
+
send("content_block_delta", {
|
|
40068
|
+
type: "content_block_delta",
|
|
40069
|
+
index: fnCall.index,
|
|
40070
|
+
delta: { type: "input_json_delta", partial_json: finalArgs }
|
|
40071
|
+
});
|
|
40072
|
+
}
|
|
39485
40073
|
send("content_block_stop", { type: "content_block_stop", index: fnCall.index });
|
|
39486
40074
|
openToolBlocks.delete(fnCall);
|
|
39487
40075
|
}
|
|
@@ -39573,6 +40161,9 @@ data: ${JSON.stringify(data)}
|
|
|
39573
40161
|
isClosed = true;
|
|
39574
40162
|
if (opts.onTokenUpdate)
|
|
39575
40163
|
opts.onTokenUpdate(inputTokens, outputTokens);
|
|
40164
|
+
if (opts.middlewareManager) {
|
|
40165
|
+
await opts.middlewareManager.afterStreamComplete(opts.modelName, streamMetadata);
|
|
40166
|
+
}
|
|
39576
40167
|
safeClose();
|
|
39577
40168
|
} catch (error46) {
|
|
39578
40169
|
if (pingInterval) {
|
|
@@ -39809,6 +40400,7 @@ class ComposedHandler {
|
|
|
39809
40400
|
explicitAdapter;
|
|
39810
40401
|
modelAdapter;
|
|
39811
40402
|
middlewareManager;
|
|
40403
|
+
behaviorEngine;
|
|
39812
40404
|
tokenTracker;
|
|
39813
40405
|
targetModel;
|
|
39814
40406
|
bareModelName;
|
|
@@ -39835,6 +40427,7 @@ class ComposedHandler {
|
|
|
39835
40427
|
this.middlewareManager.register(new GeminiThoughtSignatureMiddleware);
|
|
39836
40428
|
}
|
|
39837
40429
|
this.middlewareManager.initialize().catch((err) => log(`[ComposedHandler:${this.bareModelName}] Middleware init error: ${err}`));
|
|
40430
|
+
this.behaviorEngine = getBehaviorEngine();
|
|
39838
40431
|
this.tokenTracker = new TokenTracker(port, {
|
|
39839
40432
|
contextWindow: this.getModelContextWindow(),
|
|
39840
40433
|
providerName: provider.name,
|
|
@@ -39947,6 +40540,22 @@ class ComposedHandler {
|
|
|
39947
40540
|
log(`[${this.provider.displayName}] Tools: ${toolNames}`);
|
|
39948
40541
|
}
|
|
39949
40542
|
}
|
|
40543
|
+
await this.middlewareManager.beforeRequest({
|
|
40544
|
+
modelId: this.bareModelName,
|
|
40545
|
+
messages,
|
|
40546
|
+
tools,
|
|
40547
|
+
stream: true,
|
|
40548
|
+
claudeRequest,
|
|
40549
|
+
claudeTools: claudeRequest.tools ?? []
|
|
40550
|
+
});
|
|
40551
|
+
const behaviorSession = this.behaviorEngine.startSession({
|
|
40552
|
+
modelId: this.bareModelName,
|
|
40553
|
+
providerName: this.provider.name,
|
|
40554
|
+
isNativeAnthropic: /^claude[-.]/i.test(this.bareModelName) || this.provider.name === "anthropic"
|
|
40555
|
+
});
|
|
40556
|
+
if (!behaviorSession.isNoop) {
|
|
40557
|
+
behaviorSession.applyRequest(claudeRequest, claudeRequest.tools ?? [], tools, messages);
|
|
40558
|
+
}
|
|
39950
40559
|
let requestPayload = adapter.buildPayload(claudeRequest, messages, tools);
|
|
39951
40560
|
const extraFields = this.provider.getExtraPayloadFields?.();
|
|
39952
40561
|
if (extraFields) {
|
|
@@ -39993,12 +40602,6 @@ class ComposedHandler {
|
|
|
39993
40602
|
if (this.provider.transformPayload) {
|
|
39994
40603
|
requestPayload = this.provider.transformPayload(requestPayload);
|
|
39995
40604
|
}
|
|
39996
|
-
await this.middlewareManager.beforeRequest({
|
|
39997
|
-
modelId: this.bareModelName,
|
|
39998
|
-
messages,
|
|
39999
|
-
tools,
|
|
40000
|
-
stream: true
|
|
40001
|
-
});
|
|
40002
40605
|
const endpoint = this.provider.getEndpoint(this.targetModel);
|
|
40003
40606
|
const headers = await this.provider.getHeaders();
|
|
40004
40607
|
headers["Content-Type"] = "application/json";
|
|
@@ -40280,7 +40883,7 @@ class ComposedHandler {
|
|
|
40280
40883
|
};
|
|
40281
40884
|
return this.handleStream(c, response, adapter, claudeRequest, toolNameMap, onStreamComplete, (code, message) => {
|
|
40282
40885
|
streamApiError = { code, message };
|
|
40283
|
-
});
|
|
40886
|
+
}, behaviorSession);
|
|
40284
40887
|
}
|
|
40285
40888
|
async settleResponsesStreamHead(initial, reissue) {
|
|
40286
40889
|
let response = initial;
|
|
@@ -40299,7 +40902,7 @@ class ComposedHandler {
|
|
|
40299
40902
|
};
|
|
40300
40903
|
}
|
|
40301
40904
|
log(`[${this.provider.displayName}] in-stream ${verdict.code} before any output \u2014 ` + `retry ${attempt + 1}/${STREAM_RETRY_DELAYS_MS.length} in ${delayMs / 1000}s`);
|
|
40302
|
-
await new Promise((
|
|
40905
|
+
await new Promise((resolve2) => setTimeout(resolve2, delayMs));
|
|
40303
40906
|
let next;
|
|
40304
40907
|
try {
|
|
40305
40908
|
next = await reissue();
|
|
@@ -40328,7 +40931,7 @@ class ComposedHandler {
|
|
|
40328
40931
|
resolveStreamFormat() {
|
|
40329
40932
|
return this.provider.overrideStreamFormat?.() ?? this.explicitAdapter?.getStreamFormat() ?? this.modelAdapter?.getStreamFormat() ?? this.getAdapter().getStreamFormat();
|
|
40330
40933
|
}
|
|
40331
|
-
handleStream(c, response, adapter, claudeRequest, toolNameMap, onComplete, onApiError) {
|
|
40934
|
+
handleStream(c, response, adapter, claudeRequest, toolNameMap, onComplete, onApiError, behaviorSession) {
|
|
40332
40935
|
let pendingOnComplete = onComplete;
|
|
40333
40936
|
const onTokenUpdate = (input, output) => {
|
|
40334
40937
|
const strategy = this.options.tokenStrategy || "standard";
|
|
@@ -40365,7 +40968,10 @@ class ComposedHandler {
|
|
|
40365
40968
|
toolNameMap: adapter.getToolNameMap(),
|
|
40366
40969
|
contextWindow: lookupModelForProvider(this.bareModelName, this.provider.name),
|
|
40367
40970
|
onApiError,
|
|
40368
|
-
priorInputTokens
|
|
40971
|
+
priorInputTokens,
|
|
40972
|
+
middlewareManager: this.middlewareManager,
|
|
40973
|
+
shouldBufferTool: (name) => behaviorSession?.interceptsTool(name) ?? false,
|
|
40974
|
+
onToolCall: (name, argsJson) => behaviorSession?.repairToolCall(name, argsJson) ?? null
|
|
40369
40975
|
});
|
|
40370
40976
|
case "anthropic-sse":
|
|
40371
40977
|
return createAnthropicPassthroughStream(c, response, {
|
|
@@ -40461,6 +41067,7 @@ var STREAM_RETRY_DELAYS_MS;
|
|
|
40461
41067
|
var init_composed_handler = __esm(() => {
|
|
40462
41068
|
init_dialect_manager();
|
|
40463
41069
|
init_logger();
|
|
41070
|
+
init_behavior();
|
|
40464
41071
|
init_middleware();
|
|
40465
41072
|
init_openai();
|
|
40466
41073
|
init_vision_proxy();
|
|
@@ -41258,12 +41865,6 @@ var init_api_key_map = __esm(() => {
|
|
|
41258
41865
|
};
|
|
41259
41866
|
});
|
|
41260
41867
|
|
|
41261
|
-
// ../../node_modules/.bun/zod@4.1.13/node_modules/zod/index.js
|
|
41262
|
-
var init_zod = __esm(() => {
|
|
41263
|
-
init_external2();
|
|
41264
|
-
init_external2();
|
|
41265
|
-
});
|
|
41266
|
-
|
|
41267
41868
|
// src/adapters/anthropic-api-format.ts
|
|
41268
41869
|
var AnthropicAPIFormat;
|
|
41269
41870
|
var init_anthropic_api_format = __esm(() => {
|
|
@@ -41541,7 +42142,7 @@ class AnthropicProviderTransport {
|
|
|
41541
42142
|
delayMs = 500 * (attempt + 1);
|
|
41542
42143
|
}
|
|
41543
42144
|
log(`[${this.displayName}] 429 rate limited, retry ${attempt + 1}/${maxRetries} in ${(delayMs / 1000).toFixed(1)}s`);
|
|
41544
|
-
await new Promise((
|
|
42145
|
+
await new Promise((resolve2) => setTimeout(resolve2, delayMs));
|
|
41545
42146
|
continue;
|
|
41546
42147
|
}
|
|
41547
42148
|
return response;
|
|
@@ -41722,14 +42323,14 @@ async function discoverViaOllama(baseUrl, cacheKey) {
|
|
|
41722
42323
|
let connectionError;
|
|
41723
42324
|
let loadedRaw = [];
|
|
41724
42325
|
try {
|
|
41725
|
-
loadedRaw = await
|
|
42326
|
+
loadedRaw = await fetchOllamaModels2(`${baseUrl}/api/ps`);
|
|
41726
42327
|
} catch (e) {
|
|
41727
42328
|
connectionError = classifyFetchError(e, `${baseUrl}/api/ps`);
|
|
41728
42329
|
}
|
|
41729
42330
|
let allRaw = loadedRaw;
|
|
41730
42331
|
if (allRaw.length === 0) {
|
|
41731
42332
|
try {
|
|
41732
|
-
allRaw = await
|
|
42333
|
+
allRaw = await fetchOllamaModels2(`${baseUrl}/api/tags`);
|
|
41733
42334
|
} catch (e) {
|
|
41734
42335
|
connectionError ??= classifyFetchError(e, `${baseUrl}/api/tags`);
|
|
41735
42336
|
}
|
|
@@ -41840,7 +42441,7 @@ function extractLMStudioModels(body) {
|
|
|
41840
42441
|
}
|
|
41841
42442
|
return out;
|
|
41842
42443
|
}
|
|
41843
|
-
async function
|
|
42444
|
+
async function fetchOllamaModels2(url2) {
|
|
41844
42445
|
const response = await fetch(url2, {
|
|
41845
42446
|
method: "GET",
|
|
41846
42447
|
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
|
|
@@ -42272,7 +42873,7 @@ var init_ollama_api_format = __esm(() => {
|
|
|
42272
42873
|
// src/providers/api-key-provenance.ts
|
|
42273
42874
|
import { existsSync as existsSync15, readFileSync as readFileSync12 } from "fs";
|
|
42274
42875
|
import { homedir as homedir18 } from "os";
|
|
42275
|
-
import { join as join18, resolve } from "path";
|
|
42876
|
+
import { join as join18, resolve as resolve2 } from "path";
|
|
42276
42877
|
function activeConfigPath() {
|
|
42277
42878
|
return activeGlobalConfigFile(join18(homedir18(), ".claudish", "config.json"));
|
|
42278
42879
|
}
|
|
@@ -42292,7 +42893,7 @@ function resolveApiKeyProvenance(envVar, aliases) {
|
|
|
42292
42893
|
const allVars = [envVar, ...aliases || []];
|
|
42293
42894
|
const dotenvValue = readDotenvKey(allVars);
|
|
42294
42895
|
layers.push({
|
|
42295
|
-
source: `.env (${
|
|
42896
|
+
source: `.env (${resolve2(".env")})`,
|
|
42296
42897
|
maskedValue: maskKey(dotenvValue),
|
|
42297
42898
|
isActive: false
|
|
42298
42899
|
});
|
|
@@ -42350,7 +42951,7 @@ function formatProvenanceLog(p) {
|
|
|
42350
42951
|
}
|
|
42351
42952
|
function readDotenvKey(envVars) {
|
|
42352
42953
|
try {
|
|
42353
|
-
const dotenvPath =
|
|
42954
|
+
const dotenvPath = resolve2(".env");
|
|
42354
42955
|
if (!existsSync15(dotenvPath))
|
|
42355
42956
|
return null;
|
|
42356
42957
|
const parsed = import_dotenv.parse(readFileSync12(dotenvPath, "utf-8"));
|
|
@@ -42407,10 +43008,10 @@ class GeminiRequestQueue {
|
|
|
42407
43008
|
log(`[GeminiQueue] Queue full (${this.queue.length}/${this.maxQueueSize}), rejecting request`);
|
|
42408
43009
|
throw new Error("Gemini request queue full. Please retry later.");
|
|
42409
43010
|
}
|
|
42410
|
-
return new Promise((
|
|
43011
|
+
return new Promise((resolve3, reject) => {
|
|
42411
43012
|
const queuedRequest = {
|
|
42412
43013
|
fetchFn,
|
|
42413
|
-
resolve:
|
|
43014
|
+
resolve: resolve3,
|
|
42414
43015
|
reject
|
|
42415
43016
|
};
|
|
42416
43017
|
this.queue.push(queuedRequest);
|
|
@@ -42466,7 +43067,7 @@ class GeminiRequestQueue {
|
|
|
42466
43067
|
if (timeSinceLastRequest < delayMs) {
|
|
42467
43068
|
const waitMs = delayMs - timeSinceLastRequest;
|
|
42468
43069
|
log(`[GeminiQueue] Waiting ${waitMs}ms before next request`);
|
|
42469
|
-
await new Promise((
|
|
43070
|
+
await new Promise((resolve3) => setTimeout(resolve3, waitMs));
|
|
42470
43071
|
}
|
|
42471
43072
|
}
|
|
42472
43073
|
handleRateLimitResponse(errorText) {
|
|
@@ -43264,10 +43865,10 @@ class LocalModelQueue {
|
|
|
43264
43865
|
}
|
|
43265
43866
|
throw new Error(`Local model queue full (${this.queue.length}/${this.maxQueueSize}). GPU is overloaded. Please wait for current requests to complete.`);
|
|
43266
43867
|
}
|
|
43267
|
-
return new Promise((
|
|
43868
|
+
return new Promise((resolve3, reject) => {
|
|
43268
43869
|
const queuedRequest = {
|
|
43269
43870
|
fetchFn,
|
|
43270
|
-
resolve:
|
|
43871
|
+
resolve: resolve3,
|
|
43271
43872
|
reject,
|
|
43272
43873
|
providerId
|
|
43273
43874
|
};
|
|
@@ -43362,7 +43963,7 @@ class LocalModelQueue {
|
|
|
43362
43963
|
return parsed;
|
|
43363
43964
|
}
|
|
43364
43965
|
delay(ms) {
|
|
43365
|
-
return new Promise((
|
|
43966
|
+
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
43366
43967
|
}
|
|
43367
43968
|
getStats() {
|
|
43368
43969
|
return {
|
|
@@ -43664,10 +44265,10 @@ class OpenRouterRequestQueue {
|
|
|
43664
44265
|
}
|
|
43665
44266
|
throw new Error(`OpenRouter request queue full (${this.queue.length}/${this.maxQueueSize}). The API is rate-limited. Please wait and try again.`);
|
|
43666
44267
|
}
|
|
43667
|
-
return new Promise((
|
|
44268
|
+
return new Promise((resolve3, reject) => {
|
|
43668
44269
|
const queuedRequest = {
|
|
43669
44270
|
fetchFn,
|
|
43670
|
-
resolve:
|
|
44271
|
+
resolve: resolve3,
|
|
43671
44272
|
reject
|
|
43672
44273
|
};
|
|
43673
44274
|
this.queue.push(queuedRequest);
|
|
@@ -43735,7 +44336,7 @@ class OpenRouterRequestQueue {
|
|
|
43735
44336
|
if (getLogLevel() === "debug") {
|
|
43736
44337
|
log(`[OpenRouterQueue] Waiting ${waitMs}ms before next request`);
|
|
43737
44338
|
}
|
|
43738
|
-
await new Promise((
|
|
44339
|
+
await new Promise((resolve3) => setTimeout(resolve3, waitMs));
|
|
43739
44340
|
}
|
|
43740
44341
|
}
|
|
43741
44342
|
calculateDelay() {
|
|
@@ -44009,6 +44610,13 @@ async function createProxyServer(port, _openrouterApiKey, model, monitorMode = f
|
|
|
44009
44610
|
} catch (err) {
|
|
44010
44611
|
log(`[Proxy] customEndpoints load skipped: ${err instanceof Error ? err.message : String(err)}`);
|
|
44011
44612
|
}
|
|
44613
|
+
try {
|
|
44614
|
+
const hookRules2 = await loadHookRules(parseBehaviorConfig(loadConfig().behavior).hooks);
|
|
44615
|
+
if (hookRules2.length > 0)
|
|
44616
|
+
registerHookRules(hookRules2);
|
|
44617
|
+
} catch (err) {
|
|
44618
|
+
log(`[Proxy] behavior hooks load skipped: ${err instanceof Error ? err.message : String(err)}`);
|
|
44619
|
+
}
|
|
44012
44620
|
const nativeHandler = new NativeHandler(anthropicApiKey, options.advisorModels, options.advisorCollector);
|
|
44013
44621
|
const openRouterHandlers = new Map;
|
|
44014
44622
|
const localProviderHandlers = new Map;
|
|
@@ -44415,6 +45023,8 @@ var init_proxy_server = __esm(() => {
|
|
|
44415
45023
|
init_model_loader();
|
|
44416
45024
|
init_profile_config();
|
|
44417
45025
|
init_api_key_map();
|
|
45026
|
+
init_behavior();
|
|
45027
|
+
init_hooks();
|
|
44418
45028
|
init_custom_endpoints_loader();
|
|
44419
45029
|
init_model_catalog_resolver();
|
|
44420
45030
|
init_model_parser();
|
|
@@ -44457,9 +45067,9 @@ import {
|
|
|
44457
45067
|
readdirSync as readdirSync2,
|
|
44458
45068
|
writeFileSync as writeFileSync11
|
|
44459
45069
|
} from "fs";
|
|
44460
|
-
import { join as join20, resolve as
|
|
45070
|
+
import { join as join20, resolve as resolve3 } from "path";
|
|
44461
45071
|
function validateSessionPath(sessionPath) {
|
|
44462
|
-
const resolved =
|
|
45072
|
+
const resolved = resolve3(sessionPath);
|
|
44463
45073
|
const cwd = process.cwd();
|
|
44464
45074
|
if (!resolved.startsWith(`${cwd}/`) && resolved !== cwd) {
|
|
44465
45075
|
throw new Error(`Session path must be within current directory: ${sessionPath}`);
|
|
@@ -44571,7 +45181,7 @@ async function runModels(sessionPath, opts = {}) {
|
|
|
44571
45181
|
});
|
|
44572
45182
|
proc.stdin?.write(inputContent);
|
|
44573
45183
|
proc.stdin?.end();
|
|
44574
|
-
const completionPromise = new Promise((
|
|
45184
|
+
const completionPromise = new Promise((resolve4) => {
|
|
44575
45185
|
let exitCode = null;
|
|
44576
45186
|
let resolved = false;
|
|
44577
45187
|
const finish = () => {
|
|
@@ -44579,7 +45189,7 @@ async function runModels(sessionPath, opts = {}) {
|
|
|
44579
45189
|
return;
|
|
44580
45190
|
if (statusCache.models[anonId].state === "TIMEOUT") {
|
|
44581
45191
|
resolved = true;
|
|
44582
|
-
|
|
45192
|
+
resolve4();
|
|
44583
45193
|
return;
|
|
44584
45194
|
}
|
|
44585
45195
|
resolved = true;
|
|
@@ -44599,14 +45209,14 @@ async function runModels(sessionPath, opts = {}) {
|
|
|
44599
45209
|
} : undefined
|
|
44600
45210
|
});
|
|
44601
45211
|
opts.onStatusChange?.(anonId, statusCache.models[anonId]);
|
|
44602
|
-
|
|
45212
|
+
resolve4();
|
|
44603
45213
|
};
|
|
44604
45214
|
outputStream.on("close", finish);
|
|
44605
45215
|
proc.on("exit", (code) => {
|
|
44606
45216
|
const current = statusCache.models[anonId];
|
|
44607
45217
|
if (current?.state === "TIMEOUT") {
|
|
44608
45218
|
resolved = true;
|
|
44609
|
-
|
|
45219
|
+
resolve4();
|
|
44610
45220
|
return;
|
|
44611
45221
|
}
|
|
44612
45222
|
if (stderr) {
|
|
@@ -44624,7 +45234,7 @@ async function runModels(sessionPath, opts = {}) {
|
|
|
44624
45234
|
let timeoutHandle = null;
|
|
44625
45235
|
await Promise.race([
|
|
44626
45236
|
Promise.all(completionPromises),
|
|
44627
|
-
new Promise((
|
|
45237
|
+
new Promise((resolve4) => {
|
|
44628
45238
|
timeoutHandle = setTimeout(() => {
|
|
44629
45239
|
for (const [id, proc] of processes) {
|
|
44630
45240
|
const current = statusCache.models[id];
|
|
@@ -44638,7 +45248,7 @@ async function runModels(sessionPath, opts = {}) {
|
|
|
44638
45248
|
opts.onStatusChange?.(id, statusCache.models[id]);
|
|
44639
45249
|
}
|
|
44640
45250
|
}
|
|
44641
|
-
|
|
45251
|
+
resolve4();
|
|
44642
45252
|
}, timeoutMs);
|
|
44643
45253
|
})
|
|
44644
45254
|
]);
|
|
@@ -47685,13 +48295,13 @@ var PromisePolyfill;
|
|
|
47685
48295
|
var init_promise_polyfill = __esm(() => {
|
|
47686
48296
|
PromisePolyfill = class PromisePolyfill extends Promise {
|
|
47687
48297
|
static withResolver() {
|
|
47688
|
-
let
|
|
48298
|
+
let resolve4;
|
|
47689
48299
|
let reject;
|
|
47690
48300
|
const promise3 = new Promise((res, rej) => {
|
|
47691
|
-
|
|
48301
|
+
resolve4 = res;
|
|
47692
48302
|
reject = rej;
|
|
47693
48303
|
});
|
|
47694
|
-
return { promise: promise3, resolve:
|
|
48304
|
+
return { promise: promise3, resolve: resolve4, reject };
|
|
47695
48305
|
}
|
|
47696
48306
|
};
|
|
47697
48307
|
});
|
|
@@ -47728,7 +48338,7 @@ function createPrompt(view) {
|
|
|
47728
48338
|
output
|
|
47729
48339
|
});
|
|
47730
48340
|
const screen = new ScreenManager(rl);
|
|
47731
|
-
const { promise: promise3, resolve:
|
|
48341
|
+
const { promise: promise3, resolve: resolve4, reject } = PromisePolyfill.withResolver();
|
|
47732
48342
|
const cancel = () => reject(new CancelPromptError);
|
|
47733
48343
|
if (signal) {
|
|
47734
48344
|
const abort = () => reject(new AbortPromptError({ cause: signal.reason }));
|
|
@@ -47755,7 +48365,7 @@ function createPrompt(view) {
|
|
|
47755
48365
|
cycle(() => {
|
|
47756
48366
|
try {
|
|
47757
48367
|
const nextView = view(config3, (value) => {
|
|
47758
|
-
setImmediate(() =>
|
|
48368
|
+
setImmediate(() => resolve4(value));
|
|
47759
48369
|
});
|
|
47760
48370
|
if (nextView === undefined) {
|
|
47761
48371
|
const callerFilename = callSites[1]?.getFileName();
|
|
@@ -53596,7 +54206,7 @@ var require_lib2 = __commonJS((exports) => {
|
|
|
53596
54206
|
return matches;
|
|
53597
54207
|
};
|
|
53598
54208
|
exports.analyse = analyse;
|
|
53599
|
-
var detectFile = (filepath, opts = {}) => new Promise((
|
|
54209
|
+
var detectFile = (filepath, opts = {}) => new Promise((resolve4, reject) => {
|
|
53600
54210
|
let fd;
|
|
53601
54211
|
const fs = (0, node_1.default)();
|
|
53602
54212
|
const handler = (err, buffer) => {
|
|
@@ -53606,7 +54216,7 @@ var require_lib2 = __commonJS((exports) => {
|
|
|
53606
54216
|
if (err) {
|
|
53607
54217
|
reject(err);
|
|
53608
54218
|
} else if (buffer) {
|
|
53609
|
-
|
|
54219
|
+
resolve4((0, exports.detect)(buffer));
|
|
53610
54220
|
} else {
|
|
53611
54221
|
reject(new Error("No error and no buffer received"));
|
|
53612
54222
|
}
|
|
@@ -58867,7 +59477,7 @@ __export(exports_config, {
|
|
|
58867
59477
|
DEFAULT_PORT_RANGE: () => DEFAULT_PORT_RANGE
|
|
58868
59478
|
});
|
|
58869
59479
|
var DEFAULT_PORT_RANGE, ENV, OPENROUTER_API_URL2 = "https://openrouter.ai/api/v1/chat/completions", OPENROUTER_HEADERS;
|
|
58870
|
-
var
|
|
59480
|
+
var init_config2 = __esm(() => {
|
|
58871
59481
|
DEFAULT_PORT_RANGE = { start: 3000, end: 9000 };
|
|
58872
59482
|
ENV = {
|
|
58873
59483
|
OPENROUTER_API_KEY: "OPENROUTER_API_KEY",
|
|
@@ -59162,62 +59772,6 @@ var init_model_discovery = __esm(() => {
|
|
|
59162
59772
|
_cache2 = new Map;
|
|
59163
59773
|
});
|
|
59164
59774
|
|
|
59165
|
-
// src/providers/ollama-discovery.ts
|
|
59166
|
-
function ollamaBaseUrl() {
|
|
59167
|
-
return process.env.OLLAMA_HOST || process.env.OLLAMA_BASE_URL || "http://localhost:11434";
|
|
59168
|
-
}
|
|
59169
|
-
async function fetchOllamaModels2(options = {}) {
|
|
59170
|
-
const { enrichCapabilities = true } = options;
|
|
59171
|
-
const host = ollamaBaseUrl();
|
|
59172
|
-
try {
|
|
59173
|
-
const response = await fetch(`${host}/api/tags`, {
|
|
59174
|
-
signal: AbortSignal.timeout(3000)
|
|
59175
|
-
});
|
|
59176
|
-
if (!response.ok)
|
|
59177
|
-
return [];
|
|
59178
|
-
const data = await response.json();
|
|
59179
|
-
const models = data.models || [];
|
|
59180
|
-
const enriched = await Promise.all(models.map(async (m) => {
|
|
59181
|
-
let capabilities = [];
|
|
59182
|
-
if (enrichCapabilities) {
|
|
59183
|
-
try {
|
|
59184
|
-
const showResponse = await fetch(`${host}/api/show`, {
|
|
59185
|
-
method: "POST",
|
|
59186
|
-
headers: { "Content-Type": "application/json" },
|
|
59187
|
-
body: JSON.stringify({ name: m.name }),
|
|
59188
|
-
signal: AbortSignal.timeout(2000)
|
|
59189
|
-
});
|
|
59190
|
-
if (showResponse.ok) {
|
|
59191
|
-
const showData = await showResponse.json();
|
|
59192
|
-
capabilities = showData.capabilities || [];
|
|
59193
|
-
}
|
|
59194
|
-
} catch {}
|
|
59195
|
-
}
|
|
59196
|
-
const nameLower = String(m.name).toLowerCase();
|
|
59197
|
-
const supportsTools = capabilities.includes("tools");
|
|
59198
|
-
const isEmbeddingModel = capabilities.includes("embedding") || nameLower.includes("embed");
|
|
59199
|
-
const sizeInfo = m.details?.parameter_size || "unknown size";
|
|
59200
|
-
const toolsIndicator = supportsTools ? "\u2713 tools" : "\u2717 no tools";
|
|
59201
|
-
return {
|
|
59202
|
-
id: `ollama/${m.name}`,
|
|
59203
|
-
name: m.name,
|
|
59204
|
-
description: `Local Ollama model (${sizeInfo}, ${toolsIndicator})`,
|
|
59205
|
-
provider: "ollama",
|
|
59206
|
-
pricing: { prompt: "0", completion: "0" },
|
|
59207
|
-
isLocal: true,
|
|
59208
|
-
supportsTools,
|
|
59209
|
-
isEmbeddingModel,
|
|
59210
|
-
capabilities,
|
|
59211
|
-
details: m.details,
|
|
59212
|
-
size: m.size
|
|
59213
|
-
};
|
|
59214
|
-
}));
|
|
59215
|
-
return enriched.filter((m) => !m.isEmbeddingModel);
|
|
59216
|
-
} catch {
|
|
59217
|
-
return [];
|
|
59218
|
-
}
|
|
59219
|
-
}
|
|
59220
|
-
|
|
59221
59775
|
// src/model-selector.ts
|
|
59222
59776
|
var exports_model_selector = {};
|
|
59223
59777
|
__export(exports_model_selector, {
|
|
@@ -59749,7 +60303,7 @@ async function selectModelFromProvider(provider, tierName, recommendedModels, _f
|
|
|
59749
60303
|
}
|
|
59750
60304
|
}
|
|
59751
60305
|
if (provider === "ollama") {
|
|
59752
|
-
const ollamaModels = await
|
|
60306
|
+
const ollamaModels = await fetchOllamaModels({ enrichCapabilities: false });
|
|
59753
60307
|
const chatModels = ollamaModels.map((m) => ({
|
|
59754
60308
|
id: m.name,
|
|
59755
60309
|
name: m.name,
|
|
@@ -62688,8 +63242,8 @@ async function startProbeTui(initial) {
|
|
|
62688
63242
|
});
|
|
62689
63243
|
const store = new ProbeStore(initial);
|
|
62690
63244
|
let resolveQuit;
|
|
62691
|
-
const quitPromise = new Promise((
|
|
62692
|
-
resolveQuit =
|
|
63245
|
+
const quitPromise = new Promise((resolve4) => {
|
|
63246
|
+
resolveQuit = resolve4;
|
|
62693
63247
|
});
|
|
62694
63248
|
let quit = false;
|
|
62695
63249
|
const onQuit = () => {
|
|
@@ -63300,7 +63854,7 @@ Local providers`);
|
|
|
63300
63854
|
console.log(` ${"\u2500".repeat(70)}`);
|
|
63301
63855
|
let ollamaLine = " Ollama: not running";
|
|
63302
63856
|
try {
|
|
63303
|
-
const ollamaModels = await
|
|
63857
|
+
const ollamaModels = await fetchOllamaModels();
|
|
63304
63858
|
if (ollamaModels.length > 0) {
|
|
63305
63859
|
const toolCount = ollamaModels.filter((m) => m.supportsTools).length;
|
|
63306
63860
|
ollamaLine = ` Ollama: ${ollamaModels.length} models installed (${toolCount} with tools) \u2014 use: claudish --model ollama@<name>`;
|
|
@@ -64358,7 +64912,7 @@ function printAvailableModels() {
|
|
|
64358
64912
|
}
|
|
64359
64913
|
var __filename3, __dirname3;
|
|
64360
64914
|
var init_cli = __esm(() => {
|
|
64361
|
-
|
|
64915
|
+
init_config2();
|
|
64362
64916
|
init_model_loader();
|
|
64363
64917
|
init_model_selector();
|
|
64364
64918
|
init_probe_results_printer();
|
|
@@ -64474,7 +65028,7 @@ async function fetchLatestVersionOrThrow(options = {}) {
|
|
|
64474
65028
|
} catch (error46) {
|
|
64475
65029
|
lastError = error46 instanceof Error && error46.name === "AbortError" ? new Error(`request timed out after ${timeoutMs}ms`) : error46 instanceof Error ? error46 : new Error(String(error46));
|
|
64476
65030
|
if (attempt < retries) {
|
|
64477
|
-
await new Promise((
|
|
65031
|
+
await new Promise((resolve4) => setTimeout(resolve4, 300 * (attempt + 1)));
|
|
64478
65032
|
}
|
|
64479
65033
|
} finally {
|
|
64480
65034
|
clearTimeout(timeout);
|
|
@@ -70207,14 +70761,14 @@ function App({ requestLogin } = {}) {
|
|
|
70207
70761
|
return resolveSdkAuth({
|
|
70208
70762
|
interactive: true,
|
|
70209
70763
|
configAccount: readOnepasswordAccount(),
|
|
70210
|
-
onNeedsPicker: (accounts) => new Promise((
|
|
70764
|
+
onNeedsPicker: (accounts) => new Promise((resolve4) => {
|
|
70211
70765
|
setOpAccounts(accounts);
|
|
70212
70766
|
setOpAccountCursor(0);
|
|
70213
70767
|
opPickerResolver.current = (url2) => {
|
|
70214
70768
|
if (url2?.trim())
|
|
70215
70769
|
saveOnepasswordAccount(url2.trim(), "global");
|
|
70216
70770
|
opPickerResolver.current = null;
|
|
70217
|
-
|
|
70771
|
+
resolve4(url2);
|
|
70218
70772
|
};
|
|
70219
70773
|
setMode("pick_op_account");
|
|
70220
70774
|
})
|
|
@@ -71660,8 +72214,8 @@ async function startConfigTui() {
|
|
|
71660
72214
|
const renderer = await createCliRenderer2({
|
|
71661
72215
|
exitOnCtrlC: false
|
|
71662
72216
|
});
|
|
71663
|
-
await new Promise((
|
|
71664
|
-
renderer.once("destroy", () =>
|
|
72217
|
+
await new Promise((resolve4) => {
|
|
72218
|
+
renderer.once("destroy", () => resolve4());
|
|
71665
72219
|
createRoot2(renderer).render(/* @__PURE__ */ jsxDEV17(App, {
|
|
71666
72220
|
requestLogin
|
|
71667
72221
|
}, undefined, false, undefined, this));
|
|
@@ -72211,10 +72765,10 @@ Or set CLAUDE_PATH to your custom installation:`);
|
|
|
72211
72765
|
});
|
|
72212
72766
|
}
|
|
72213
72767
|
setupSignalHandlers(proc, tempSettingsPath, config3.quiet, onCleanup);
|
|
72214
|
-
const exitCode = await new Promise((
|
|
72768
|
+
const exitCode = await new Promise((resolve4) => {
|
|
72215
72769
|
proc.on("exit", (code) => {
|
|
72216
72770
|
setClaudeCodeRunning(false);
|
|
72217
|
-
|
|
72771
|
+
resolve4(code ?? 1);
|
|
72218
72772
|
});
|
|
72219
72773
|
});
|
|
72220
72774
|
releaseTerminalIsolation();
|
|
@@ -72294,9 +72848,9 @@ async function findClaudeBinary() {
|
|
|
72294
72848
|
proc.stdout?.on("data", (data) => {
|
|
72295
72849
|
output += data.toString();
|
|
72296
72850
|
});
|
|
72297
|
-
const exitCode = await new Promise((
|
|
72851
|
+
const exitCode = await new Promise((resolve4) => {
|
|
72298
72852
|
proc.on("exit", (code) => {
|
|
72299
|
-
|
|
72853
|
+
resolve4(code ?? 1);
|
|
72300
72854
|
});
|
|
72301
72855
|
});
|
|
72302
72856
|
if (exitCode === 0 && output.trim()) {
|
|
@@ -72319,7 +72873,7 @@ async function checkClaudeInstalled() {
|
|
|
72319
72873
|
var restoreTerminal = null, MIN_AUTO_COMPACT_WINDOW = 200000;
|
|
72320
72874
|
var init_claude_runner = __esm(() => {
|
|
72321
72875
|
init_model_catalog();
|
|
72322
|
-
|
|
72876
|
+
init_config2();
|
|
72323
72877
|
init_logger();
|
|
72324
72878
|
init_profile_config();
|
|
72325
72879
|
init_model_discovery();
|
|
@@ -72686,9 +73240,9 @@ async function subscribeToMagmux(sockPath, onEvent) {
|
|
|
72686
73240
|
for (let attempt = 0;attempt < 40; attempt++) {
|
|
72687
73241
|
if (existsSync24(sockPath)) {
|
|
72688
73242
|
try {
|
|
72689
|
-
client = await new Promise((
|
|
73243
|
+
client = await new Promise((resolve4, reject) => {
|
|
72690
73244
|
const s = netConnect(sockPath);
|
|
72691
|
-
s.once("connect", () =>
|
|
73245
|
+
s.once("connect", () => resolve4(s));
|
|
72692
73246
|
s.once("error", reject);
|
|
72693
73247
|
});
|
|
72694
73248
|
break;
|
|
@@ -72699,7 +73253,7 @@ async function subscribeToMagmux(sockPath, onEvent) {
|
|
|
72699
73253
|
if (!client) {
|
|
72700
73254
|
return { results: null, client: null };
|
|
72701
73255
|
}
|
|
72702
|
-
return await new Promise((
|
|
73256
|
+
return await new Promise((resolve4) => {
|
|
72703
73257
|
let buf = "";
|
|
72704
73258
|
let finalResults = null;
|
|
72705
73259
|
client.on("data", (chunk) => {
|
|
@@ -72722,7 +73276,7 @@ async function subscribeToMagmux(sockPath, onEvent) {
|
|
|
72722
73276
|
} catch {}
|
|
72723
73277
|
}
|
|
72724
73278
|
});
|
|
72725
|
-
const done = () =>
|
|
73279
|
+
const done = () => resolve4({ results: finalResults, client });
|
|
72726
73280
|
client.once("end", done);
|
|
72727
73281
|
client.once("close", done);
|
|
72728
73282
|
client.once("error", done);
|
|
@@ -72798,9 +73352,9 @@ async function runWithGrid(sessionPath, models, input, opts) {
|
|
|
72798
73352
|
});
|
|
72799
73353
|
const sockPath = `/tmp/magmux-${proc.pid}.sock`;
|
|
72800
73354
|
const subscription = subscribeToMagmux(sockPath);
|
|
72801
|
-
const procExit = new Promise((
|
|
72802
|
-
proc.on("exit", () =>
|
|
72803
|
-
proc.on("error", () =>
|
|
73355
|
+
const procExit = new Promise((resolve4) => {
|
|
73356
|
+
proc.on("exit", () => resolve4());
|
|
73357
|
+
proc.on("error", () => resolve4());
|
|
72804
73358
|
});
|
|
72805
73359
|
const [{ results }] = await Promise.all([subscription, procExit]);
|
|
72806
73360
|
const status = buildTeamStatus(manifest, startedAt, results?.panes ?? null);
|
|
@@ -72829,7 +73383,7 @@ init_op_source();
|
|
|
72829
73383
|
init_startup_trace();
|
|
72830
73384
|
var import_dotenv3 = __toESM(require_main(), 1);
|
|
72831
73385
|
import { existsSync as existsSync25, readFileSync as readFileSync23 } from "fs";
|
|
72832
|
-
import { join as join28, resolve as
|
|
73386
|
+
import { join as join28, resolve as resolve4 } from "path";
|
|
72833
73387
|
import_dotenv3.config({ quiet: true });
|
|
72834
73388
|
function classifyStartupKind() {
|
|
72835
73389
|
const argv = process.argv.slice(2);
|
|
@@ -72927,7 +73481,7 @@ async function applyOpImport() {
|
|
|
72927
73481
|
async function applyConfigOverride() {
|
|
72928
73482
|
const { planConfigOverride: planConfigOverride2, setConfigFileOverride: setConfigFileOverride2 } = await Promise.resolve().then(() => exports_config_override);
|
|
72929
73483
|
const plan = planConfigOverride2(process.argv.slice(2), process.env, {
|
|
72930
|
-
resolve:
|
|
73484
|
+
resolve: resolve4,
|
|
72931
73485
|
exists: existsSync25
|
|
72932
73486
|
});
|
|
72933
73487
|
if (plan.kind === "none")
|
|
@@ -73036,7 +73590,7 @@ async function runCli() {
|
|
|
73036
73590
|
const endImports = beginSpan("startup:cli-imports");
|
|
73037
73591
|
const { checkClaudeInstalled: checkClaudeInstalled2, runClaudeWithProxy: runClaudeWithProxy2 } = await Promise.resolve().then(() => (init_claude_runner(), exports_claude_runner));
|
|
73038
73592
|
const { parseArgs: parseArgs2, getVersion: getVersion4 } = await Promise.resolve().then(() => (init_cli(), exports_cli));
|
|
73039
|
-
const { DEFAULT_PORT_RANGE: DEFAULT_PORT_RANGE2 } = await Promise.resolve().then(() => (
|
|
73593
|
+
const { DEFAULT_PORT_RANGE: DEFAULT_PORT_RANGE2 } = await Promise.resolve().then(() => (init_config2(), exports_config));
|
|
73040
73594
|
const { selectModel: selectModel2, promptForApiKey: promptForApiKey2 } = await Promise.resolve().then(() => (init_model_selector(), exports_model_selector));
|
|
73041
73595
|
const {
|
|
73042
73596
|
resolveModelProvider: resolveModelProvider2,
|
|
@@ -73129,11 +73683,11 @@ Team Status`);
|
|
|
73129
73683
|
You can disable it anytime with: --no-auto-approve
|
|
73130
73684
|
|
|
73131
73685
|
`);
|
|
73132
|
-
const answer = await new Promise((
|
|
73686
|
+
const answer = await new Promise((resolve5) => {
|
|
73133
73687
|
const rl = createInterface2({ input: process.stdin, output: process.stderr });
|
|
73134
73688
|
rl.question("Enable auto-approve? [Y/n] ", (ans) => {
|
|
73135
73689
|
rl.close();
|
|
73136
|
-
|
|
73690
|
+
resolve5(ans.trim().toLowerCase());
|
|
73137
73691
|
});
|
|
73138
73692
|
});
|
|
73139
73693
|
const declined = answer === "n" || answer === "no";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudish",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.25.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.25.0",
|
|
64
|
+
"@claudish/magmux-darwin-x64": "7.25.0",
|
|
65
|
+
"@claudish/magmux-linux-arm64": "7.25.0",
|
|
66
|
+
"@claudish/magmux-linux-x64": "7.25.0"
|
|
67
67
|
},
|
|
68
68
|
"author": "Jack Rudenko <i@madappgang.com>",
|
|
69
69
|
"license": "MIT",
|