claudish 7.47.0 → 7.49.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/bin/claudish.cjs +69 -25
- package/dist/index.js +1192 -438
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -729,7 +729,7 @@ var init_onepassword_config = __esm(() => {
|
|
|
729
729
|
});
|
|
730
730
|
|
|
731
731
|
// src/version.ts
|
|
732
|
-
var VERSION = "7.
|
|
732
|
+
var VERSION = "7.49.0";
|
|
733
733
|
|
|
734
734
|
// src/logger.ts
|
|
735
735
|
var exports_logger = {};
|
|
@@ -28142,7 +28142,7 @@ var init_provider_definitions = __esm(() => {
|
|
|
28142
28142
|
name: "minimax",
|
|
28143
28143
|
displayName: "MiniMax",
|
|
28144
28144
|
transport: "anthropic",
|
|
28145
|
-
baseUrl: "https://api.
|
|
28145
|
+
baseUrl: "https://api.minimaxi.com",
|
|
28146
28146
|
baseUrlEnvVars: ["MINIMAX_BASE_URL"],
|
|
28147
28147
|
apiPath: "/anthropic/v1/messages",
|
|
28148
28148
|
apiKeyEnvVar: "MINIMAX_API_KEY",
|
|
@@ -28579,6 +28579,25 @@ var init_provider_definitions = __esm(() => {
|
|
|
28579
28579
|
isDirectApi: true,
|
|
28580
28580
|
description: "Qwen Plan (qc@)"
|
|
28581
28581
|
},
|
|
28582
|
+
{
|
|
28583
|
+
name: "qwen-payg",
|
|
28584
|
+
displayName: "Qwen PAYG",
|
|
28585
|
+
transport: "anthropic",
|
|
28586
|
+
baseUrl: "https://dashscope-intl.aliyuncs.com",
|
|
28587
|
+
baseUrlEnvVars: ["DASHSCOPE_BASE_URL"],
|
|
28588
|
+
apiPath: "/apps/anthropic/v1/messages",
|
|
28589
|
+
apiKeyEnvVar: "DASHSCOPE_API_KEY",
|
|
28590
|
+
apiKeyAliases: ["QWEN_API_KEY"],
|
|
28591
|
+
apiKeyDescription: "Alibaba Model Studio API Key (pay-as-you-go)",
|
|
28592
|
+
apiKeyUrl: "https://www.alibabacloud.com/help/en/model-studio/get-api-key",
|
|
28593
|
+
authScheme: "bearer",
|
|
28594
|
+
shortcuts: ["qp", "dashscope"],
|
|
28595
|
+
shortestPrefix: "qp",
|
|
28596
|
+
legacyPrefixes: [{ prefix: "qp/", stripPrefix: true }],
|
|
28597
|
+
modelDiscovery: { path: "/compatible-mode/v1/models", format: "openai-models-list" },
|
|
28598
|
+
isDirectApi: true,
|
|
28599
|
+
description: "Alibaba Model Studio pay-as-you-go (qp@)"
|
|
28600
|
+
},
|
|
28582
28601
|
{
|
|
28583
28602
|
name: "qwen",
|
|
28584
28603
|
displayName: "Qwen",
|
|
@@ -29621,6 +29640,48 @@ var init_base_api_format = __esm(() => {
|
|
|
29621
29640
|
});
|
|
29622
29641
|
|
|
29623
29642
|
// src/adapters/anthropic-api-format.ts
|
|
29643
|
+
function systemText(content) {
|
|
29644
|
+
if (typeof content === "string")
|
|
29645
|
+
return content;
|
|
29646
|
+
if (Array.isArray(content)) {
|
|
29647
|
+
return content.map((block) => typeof block?.text === "string" ? block.text : "").filter(Boolean).join(`
|
|
29648
|
+
`);
|
|
29649
|
+
}
|
|
29650
|
+
return "";
|
|
29651
|
+
}
|
|
29652
|
+
function hoistInlineSystem(messages) {
|
|
29653
|
+
if (!Array.isArray(messages) || !messages.some((m) => m?.role === "system")) {
|
|
29654
|
+
return { messages, hoisted: [] };
|
|
29655
|
+
}
|
|
29656
|
+
const kept = [];
|
|
29657
|
+
const hoisted = [];
|
|
29658
|
+
for (const msg of messages) {
|
|
29659
|
+
if (msg?.role === "system") {
|
|
29660
|
+
const text = systemText(msg.content);
|
|
29661
|
+
if (text)
|
|
29662
|
+
hoisted.push(text);
|
|
29663
|
+
continue;
|
|
29664
|
+
}
|
|
29665
|
+
kept.push(msg);
|
|
29666
|
+
}
|
|
29667
|
+
return { messages: kept, hoisted };
|
|
29668
|
+
}
|
|
29669
|
+
function mergeSystem(existing, hoisted) {
|
|
29670
|
+
if (hoisted.length === 0)
|
|
29671
|
+
return existing;
|
|
29672
|
+
const merged = hoisted.join(`
|
|
29673
|
+
|
|
29674
|
+
`);
|
|
29675
|
+
if (existing === undefined || existing === null || existing === "")
|
|
29676
|
+
return merged;
|
|
29677
|
+
if (Array.isArray(existing))
|
|
29678
|
+
return [...existing, { type: "text", text: merged }];
|
|
29679
|
+
if (typeof existing === "string")
|
|
29680
|
+
return `${existing}
|
|
29681
|
+
|
|
29682
|
+
${merged}`;
|
|
29683
|
+
return existing;
|
|
29684
|
+
}
|
|
29624
29685
|
var AnthropicAPIFormat;
|
|
29625
29686
|
var init_anthropic_api_format = __esm(() => {
|
|
29626
29687
|
init_base_api_format();
|
|
@@ -29665,14 +29726,16 @@ var init_anthropic_api_format = __esm(() => {
|
|
|
29665
29726
|
return claudeRequest.tools || [];
|
|
29666
29727
|
}
|
|
29667
29728
|
buildPayload(claudeRequest, messages, tools) {
|
|
29729
|
+
const { messages: cleanMessages, hoisted } = hoistInlineSystem(messages);
|
|
29668
29730
|
const payload = {
|
|
29669
29731
|
model: this.modelId,
|
|
29670
|
-
messages,
|
|
29732
|
+
messages: cleanMessages,
|
|
29671
29733
|
max_tokens: claudeRequest.max_tokens || 4096,
|
|
29672
29734
|
stream: true
|
|
29673
29735
|
};
|
|
29674
|
-
|
|
29675
|
-
|
|
29736
|
+
const system = mergeSystem(claudeRequest.system, hoisted);
|
|
29737
|
+
if (system !== undefined) {
|
|
29738
|
+
payload.system = system;
|
|
29676
29739
|
}
|
|
29677
29740
|
if (tools.length > 0) {
|
|
29678
29741
|
payload.tools = tools;
|
|
@@ -34865,14 +34928,14 @@ var init_config = __esm(() => {
|
|
|
34865
34928
|
});
|
|
34866
34929
|
|
|
34867
34930
|
// src/behavior/harness.ts
|
|
34868
|
-
function extractAvailableSkills(
|
|
34869
|
-
if (!
|
|
34931
|
+
function extractAvailableSkills(systemText2) {
|
|
34932
|
+
if (!systemText2)
|
|
34870
34933
|
return [];
|
|
34871
|
-
const start = SKILL_SECTION.exec(
|
|
34934
|
+
const start = SKILL_SECTION.exec(systemText2);
|
|
34872
34935
|
if (!start)
|
|
34873
34936
|
return [];
|
|
34874
34937
|
const out = [];
|
|
34875
|
-
const body =
|
|
34938
|
+
const body = systemText2.slice(start.index + start[0].length);
|
|
34876
34939
|
for (const line of body.split(`
|
|
34877
34940
|
`)) {
|
|
34878
34941
|
const trimmed2 = line.trim();
|
|
@@ -37579,7 +37642,8 @@ var init_telemetry = __esm(() => {
|
|
|
37579
37642
|
"minimax-coding",
|
|
37580
37643
|
"kimi-coding",
|
|
37581
37644
|
"glm-coding",
|
|
37582
|
-
"qwen-cloud"
|
|
37645
|
+
"qwen-cloud",
|
|
37646
|
+
"qwen-payg"
|
|
37583
37647
|
]);
|
|
37584
37648
|
});
|
|
37585
37649
|
|
|
@@ -38004,6 +38068,170 @@ var init_anthropic_error = __esm(() => {
|
|
|
38004
38068
|
CONTROL_CHARS = /[\x00-\x1F\x7F]/g;
|
|
38005
38069
|
});
|
|
38006
38070
|
|
|
38071
|
+
// src/handlers/shared/collect-sse-message.ts
|
|
38072
|
+
function finalizeBlock(block) {
|
|
38073
|
+
if (block.type === "text") {
|
|
38074
|
+
return { type: "text", text: block.text ?? "" };
|
|
38075
|
+
}
|
|
38076
|
+
if (block.type === "thinking") {
|
|
38077
|
+
return {
|
|
38078
|
+
type: "thinking",
|
|
38079
|
+
thinking: block.thinking ?? "",
|
|
38080
|
+
...block.signature ? { signature: block.signature } : {}
|
|
38081
|
+
};
|
|
38082
|
+
}
|
|
38083
|
+
let input = block.input ?? {};
|
|
38084
|
+
if (block.partialJson !== undefined && block.partialJson !== "") {
|
|
38085
|
+
try {
|
|
38086
|
+
input = JSON.parse(block.partialJson);
|
|
38087
|
+
} catch {
|
|
38088
|
+
log(`[CollectSSE] tool_use ${block.name ?? "?"} had unparseable input, emitting empty object`);
|
|
38089
|
+
input = {};
|
|
38090
|
+
}
|
|
38091
|
+
}
|
|
38092
|
+
return {
|
|
38093
|
+
type: "tool_use",
|
|
38094
|
+
id: block.id ?? "",
|
|
38095
|
+
name: block.name ?? "",
|
|
38096
|
+
input
|
|
38097
|
+
};
|
|
38098
|
+
}
|
|
38099
|
+
async function collectSseMessage(sse, fallbackModel, opts = {}) {
|
|
38100
|
+
const message = {
|
|
38101
|
+
id: `msg_${Date.now()}`,
|
|
38102
|
+
type: "message",
|
|
38103
|
+
role: "assistant",
|
|
38104
|
+
model: fallbackModel,
|
|
38105
|
+
content: [],
|
|
38106
|
+
stop_reason: null,
|
|
38107
|
+
stop_sequence: null,
|
|
38108
|
+
usage: { input_tokens: 0, output_tokens: 0 }
|
|
38109
|
+
};
|
|
38110
|
+
const blocks = new Map;
|
|
38111
|
+
const blockAt = (index) => {
|
|
38112
|
+
let block = blocks.get(index);
|
|
38113
|
+
if (!block) {
|
|
38114
|
+
block = { type: "text", text: "" };
|
|
38115
|
+
blocks.set(index, block);
|
|
38116
|
+
}
|
|
38117
|
+
return block;
|
|
38118
|
+
};
|
|
38119
|
+
if (!sse.body)
|
|
38120
|
+
return message;
|
|
38121
|
+
const reader = sse.body.getReader();
|
|
38122
|
+
const decoder = new TextDecoder;
|
|
38123
|
+
const stallMs = opts.stallTimeoutMs ?? STALL_TIMEOUT_MS;
|
|
38124
|
+
let buffer = "";
|
|
38125
|
+
const handle = (data) => {
|
|
38126
|
+
switch (data?.type) {
|
|
38127
|
+
case "message_start": {
|
|
38128
|
+
const m = data.message ?? {};
|
|
38129
|
+
if (m.id)
|
|
38130
|
+
message.id = m.id;
|
|
38131
|
+
if (m.model)
|
|
38132
|
+
message.model = m.model;
|
|
38133
|
+
if (m.usage?.input_tokens != null)
|
|
38134
|
+
message.usage.input_tokens = m.usage.input_tokens;
|
|
38135
|
+
if (m.usage?.output_tokens != null)
|
|
38136
|
+
message.usage.output_tokens = m.usage.output_tokens;
|
|
38137
|
+
break;
|
|
38138
|
+
}
|
|
38139
|
+
case "content_block_start": {
|
|
38140
|
+
const cb = data.content_block ?? {};
|
|
38141
|
+
const kind = cb.type === "thinking" ? "thinking" : cb.type === "tool_use" ? "tool_use" : "text";
|
|
38142
|
+
blocks.set(data.index, {
|
|
38143
|
+
type: kind,
|
|
38144
|
+
text: kind === "text" ? cb.text ?? "" : undefined,
|
|
38145
|
+
thinking: kind === "thinking" ? cb.thinking ?? "" : undefined,
|
|
38146
|
+
id: cb.id,
|
|
38147
|
+
name: cb.name,
|
|
38148
|
+
partialJson: kind === "tool_use" ? "" : undefined
|
|
38149
|
+
});
|
|
38150
|
+
break;
|
|
38151
|
+
}
|
|
38152
|
+
case "content_block_delta": {
|
|
38153
|
+
const block = blockAt(data.index);
|
|
38154
|
+
const d = data.delta ?? {};
|
|
38155
|
+
if (d.type === "text_delta")
|
|
38156
|
+
block.text = (block.text ?? "") + (d.text ?? "");
|
|
38157
|
+
else if (d.type === "thinking_delta")
|
|
38158
|
+
block.thinking = (block.thinking ?? "") + (d.thinking ?? "");
|
|
38159
|
+
else if (d.type === "signature_delta")
|
|
38160
|
+
block.signature = d.signature;
|
|
38161
|
+
else if (d.type === "input_json_delta")
|
|
38162
|
+
block.partialJson = (block.partialJson ?? "") + (d.partial_json ?? "");
|
|
38163
|
+
break;
|
|
38164
|
+
}
|
|
38165
|
+
case "message_delta": {
|
|
38166
|
+
if (data.delta?.stop_reason !== undefined)
|
|
38167
|
+
message.stop_reason = data.delta.stop_reason;
|
|
38168
|
+
if (data.delta?.stop_sequence !== undefined)
|
|
38169
|
+
message.stop_sequence = data.delta.stop_sequence;
|
|
38170
|
+
if (data.usage?.input_tokens != null)
|
|
38171
|
+
message.usage.input_tokens = data.usage.input_tokens;
|
|
38172
|
+
if (data.usage?.output_tokens != null)
|
|
38173
|
+
message.usage.output_tokens = data.usage.output_tokens;
|
|
38174
|
+
break;
|
|
38175
|
+
}
|
|
38176
|
+
default:
|
|
38177
|
+
break;
|
|
38178
|
+
}
|
|
38179
|
+
};
|
|
38180
|
+
try {
|
|
38181
|
+
while (true) {
|
|
38182
|
+
let timer;
|
|
38183
|
+
const chunk = await Promise.race([
|
|
38184
|
+
reader.read(),
|
|
38185
|
+
new Promise((resolve2) => {
|
|
38186
|
+
timer = setTimeout(() => resolve2("stalled"), stallMs);
|
|
38187
|
+
})
|
|
38188
|
+
]);
|
|
38189
|
+
clearTimeout(timer);
|
|
38190
|
+
if (chunk === "stalled") {
|
|
38191
|
+
log(`[CollectSSE] no data for ${stallMs}ms \u2014 returning ${blocks.size} block(s) collected so far`);
|
|
38192
|
+
await reader.cancel().catch(() => {});
|
|
38193
|
+
break;
|
|
38194
|
+
}
|
|
38195
|
+
if (chunk.done)
|
|
38196
|
+
break;
|
|
38197
|
+
buffer += decoder.decode(chunk.value, { stream: true });
|
|
38198
|
+
const lines = buffer.split(`
|
|
38199
|
+
`);
|
|
38200
|
+
buffer = lines.pop() ?? "";
|
|
38201
|
+
for (const line of lines) {
|
|
38202
|
+
if (!line.startsWith("data:"))
|
|
38203
|
+
continue;
|
|
38204
|
+
const payload = line.slice(5).trim();
|
|
38205
|
+
if (!payload || payload === "[DONE]")
|
|
38206
|
+
continue;
|
|
38207
|
+
try {
|
|
38208
|
+
handle(JSON.parse(payload));
|
|
38209
|
+
} catch {}
|
|
38210
|
+
}
|
|
38211
|
+
}
|
|
38212
|
+
} catch (e) {
|
|
38213
|
+
log(`[CollectSSE] read failed, keeping ${blocks.size} block(s): ${e}`);
|
|
38214
|
+
}
|
|
38215
|
+
for (const index of Array.from(blocks.keys()).sort((a, b) => a - b)) {
|
|
38216
|
+
message.content.push(finalizeBlock(blocks.get(index)));
|
|
38217
|
+
}
|
|
38218
|
+
if (message.stop_reason === null) {
|
|
38219
|
+
message.stop_reason = message.content.some((b) => b.type === "tool_use") ? "tool_use" : "end_turn";
|
|
38220
|
+
}
|
|
38221
|
+
return message;
|
|
38222
|
+
}
|
|
38223
|
+
async function sseResponseToJson(sse, fallbackModel, opts = {}) {
|
|
38224
|
+
const message = await collectSseMessage(sse, fallbackModel, opts);
|
|
38225
|
+
return new Response(JSON.stringify(message), {
|
|
38226
|
+
status: 200,
|
|
38227
|
+
headers: { "Content-Type": "application/json" }
|
|
38228
|
+
});
|
|
38229
|
+
}
|
|
38230
|
+
var STALL_TIMEOUT_MS = 120000;
|
|
38231
|
+
var init_collect_sse_message = __esm(() => {
|
|
38232
|
+
init_logger();
|
|
38233
|
+
});
|
|
38234
|
+
|
|
38007
38235
|
// src/handlers/shared/connection-error.ts
|
|
38008
38236
|
function findConnectionCode(error46) {
|
|
38009
38237
|
let e = error46;
|
|
@@ -38564,6 +38792,31 @@ function createAnthropicPassthroughStream(c, response, opts) {
|
|
|
38564
38792
|
const filterThinking = opts.adapter?.shouldFilterThinking() ?? false;
|
|
38565
38793
|
const interceptToolFrame = createToolRepairInterceptor(opts);
|
|
38566
38794
|
let pendingEventLine = null;
|
|
38795
|
+
let inputTokens = 0;
|
|
38796
|
+
let outputTokens = 0;
|
|
38797
|
+
let stopReason = null;
|
|
38798
|
+
let sawMessageStart = false;
|
|
38799
|
+
let sawMessageStop = false;
|
|
38800
|
+
let openBlockIndex = null;
|
|
38801
|
+
const noteLifecycle = (data, emittedIndex) => {
|
|
38802
|
+
switch (data?.type) {
|
|
38803
|
+
case "message_start":
|
|
38804
|
+
sawMessageStart = true;
|
|
38805
|
+
break;
|
|
38806
|
+
case "message_stop":
|
|
38807
|
+
sawMessageStop = true;
|
|
38808
|
+
break;
|
|
38809
|
+
case "content_block_start":
|
|
38810
|
+
if (emittedIndex !== null)
|
|
38811
|
+
openBlockIndex = emittedIndex;
|
|
38812
|
+
break;
|
|
38813
|
+
case "content_block_stop":
|
|
38814
|
+
openBlockIndex = null;
|
|
38815
|
+
break;
|
|
38816
|
+
default:
|
|
38817
|
+
break;
|
|
38818
|
+
}
|
|
38819
|
+
};
|
|
38567
38820
|
const flushPendingEvent = (controller) => {
|
|
38568
38821
|
if (pendingEventLine !== null && !isClosed) {
|
|
38569
38822
|
controller.enqueue(encoder.encode(`${pendingEventLine}
|
|
@@ -38581,6 +38834,48 @@ function createAnthropicPassthroughStream(c, response, opts) {
|
|
|
38581
38834
|
}
|
|
38582
38835
|
flushPendingEvent(controller);
|
|
38583
38836
|
controller.enqueue(encoder.encode(out));
|
|
38837
|
+
noteLifecycle(data, typeof data?.index === "number" ? data.index : null);
|
|
38838
|
+
};
|
|
38839
|
+
const finalizeAbandonedStream = (controller) => {
|
|
38840
|
+
if (isClosed || sawMessageStop)
|
|
38841
|
+
return;
|
|
38842
|
+
const send = (event, data) => {
|
|
38843
|
+
controller.enqueue(encoder.encode(`event: ${event}
|
|
38844
|
+
data: ${JSON.stringify(data)}
|
|
38845
|
+
|
|
38846
|
+
`));
|
|
38847
|
+
};
|
|
38848
|
+
try {
|
|
38849
|
+
if (!sawMessageStart) {
|
|
38850
|
+
send("message_start", {
|
|
38851
|
+
type: "message_start",
|
|
38852
|
+
message: {
|
|
38853
|
+
id: `msg_${Date.now()}`,
|
|
38854
|
+
type: "message",
|
|
38855
|
+
role: "assistant",
|
|
38856
|
+
content: [],
|
|
38857
|
+
model: opts.modelName,
|
|
38858
|
+
stop_reason: null,
|
|
38859
|
+
stop_sequence: null,
|
|
38860
|
+
usage: { input_tokens: inputTokens, output_tokens: outputTokens }
|
|
38861
|
+
}
|
|
38862
|
+
});
|
|
38863
|
+
}
|
|
38864
|
+
if (openBlockIndex !== null) {
|
|
38865
|
+
send("content_block_stop", { type: "content_block_stop", index: openBlockIndex });
|
|
38866
|
+
openBlockIndex = null;
|
|
38867
|
+
}
|
|
38868
|
+
send("message_delta", {
|
|
38869
|
+
type: "message_delta",
|
|
38870
|
+
delta: { stop_reason: stopReason ?? "end_turn", stop_sequence: null },
|
|
38871
|
+
usage: {
|
|
38872
|
+
...inputTokens > 0 ? { input_tokens: inputTokens } : {},
|
|
38873
|
+
output_tokens: outputTokens
|
|
38874
|
+
}
|
|
38875
|
+
});
|
|
38876
|
+
send("message_stop", { type: "message_stop" });
|
|
38877
|
+
sawMessageStop = true;
|
|
38878
|
+
} catch {}
|
|
38584
38879
|
};
|
|
38585
38880
|
return c.body(new ReadableStream({
|
|
38586
38881
|
async start(controller) {
|
|
@@ -38601,12 +38896,9 @@ data: {"type":"ping"}
|
|
|
38601
38896
|
try {
|
|
38602
38897
|
const reader = response.body.getReader();
|
|
38603
38898
|
let buffer = "";
|
|
38604
|
-
let inputTokens = 0;
|
|
38605
|
-
let outputTokens = 0;
|
|
38606
38899
|
let totalLines = 0;
|
|
38607
38900
|
let textChunks = 0;
|
|
38608
38901
|
let toolUseBlocks = 0;
|
|
38609
|
-
let stopReason = null;
|
|
38610
38902
|
let insideThinkingBlock = false;
|
|
38611
38903
|
let thinkingBlocksSuppressed = 0;
|
|
38612
38904
|
let suppressedFrame = false;
|
|
@@ -38671,6 +38963,7 @@ data: ${JSON.stringify({
|
|
|
38671
38963
|
flushPendingEvent(controller);
|
|
38672
38964
|
controller.enqueue(encoder.encode(`${modifiedLine}
|
|
38673
38965
|
`));
|
|
38966
|
+
noteLifecycle(data, reindexed);
|
|
38674
38967
|
}
|
|
38675
38968
|
} else {
|
|
38676
38969
|
enqueueData(controller, data, line);
|
|
@@ -38793,6 +39086,13 @@ data: ${JSON.stringify({
|
|
|
38793
39086
|
}
|
|
38794
39087
|
} catch (e) {
|
|
38795
39088
|
log(`[AnthropicSSE] Stream error: ${e}`);
|
|
39089
|
+
finalizeAbandonedStream(controller);
|
|
39090
|
+
try {
|
|
39091
|
+
opts.onTurnEnd?.();
|
|
39092
|
+
} catch {}
|
|
39093
|
+
try {
|
|
39094
|
+
opts.onTokenUpdate?.(inputTokens, outputTokens);
|
|
39095
|
+
} catch {}
|
|
38796
39096
|
if (!isClosed) {
|
|
38797
39097
|
isClosed = true;
|
|
38798
39098
|
if (pingInterval) {
|
|
@@ -40753,9 +41053,12 @@ class ComposedHandler {
|
|
|
40753
41053
|
behaviorSession?.noteTurnComplete(this.tokenTracker.getInputTokens());
|
|
40754
41054
|
} catch {}
|
|
40755
41055
|
};
|
|
40756
|
-
|
|
41056
|
+
const streamed = this.handleStream(c, response, adapter, claudeRequest, toolNameMap, onStreamComplete, (code, message) => {
|
|
40757
41057
|
streamApiError = { code, message };
|
|
40758
41058
|
}, behaviorSession);
|
|
41059
|
+
if (payload?.stream === true)
|
|
41060
|
+
return streamed;
|
|
41061
|
+
return sseResponseToJson(streamed, this.bareModelName);
|
|
40759
41062
|
}
|
|
40760
41063
|
async settleResponsesStreamHead(initial, reissue) {
|
|
40761
41064
|
let response = initial;
|
|
@@ -41064,6 +41367,7 @@ var init_composed_handler = __esm(() => {
|
|
|
41064
41367
|
init_telemetry();
|
|
41065
41368
|
init_transform();
|
|
41066
41369
|
init_anthropic_error();
|
|
41370
|
+
init_collect_sse_message();
|
|
41067
41371
|
init_connection_error();
|
|
41068
41372
|
init_devin_stream_head_sniffer();
|
|
41069
41373
|
init_openai_compat();
|
|
@@ -41599,6 +41903,40 @@ function toRosterEntry(model) {
|
|
|
41599
41903
|
const { id, ...rest } = model;
|
|
41600
41904
|
return { wireId: id, ...rest };
|
|
41601
41905
|
}
|
|
41906
|
+
function recordFailure(failure) {
|
|
41907
|
+
_failures.set(failure.provider, failure);
|
|
41908
|
+
log(`[model-discovery:${failure.provider}] ${describeDiscoveryFailure(failure)}`);
|
|
41909
|
+
return [];
|
|
41910
|
+
}
|
|
41911
|
+
function getDiscoveryFailure(provider) {
|
|
41912
|
+
return _failures.get(provider);
|
|
41913
|
+
}
|
|
41914
|
+
function hasAuthHeader(headers) {
|
|
41915
|
+
return Object.entries(headers).some(([name, value]) => /^(authorization|x-api-key|api-key)$/i.test(name) && (value ?? "").trim().length > 0);
|
|
41916
|
+
}
|
|
41917
|
+
function oneLine(text, max = 200) {
|
|
41918
|
+
const flat = text.replace(/\s+/g, " ").trim();
|
|
41919
|
+
return flat.length > max ? `${flat.slice(0, max)}\u2026` : flat;
|
|
41920
|
+
}
|
|
41921
|
+
function describeDiscoveryFailure(failure) {
|
|
41922
|
+
const { kind, endpoint, status, detail } = failure;
|
|
41923
|
+
const at = endpoint ? ` at ${endpoint}` : "";
|
|
41924
|
+
const because = detail ? ` \u2014 ${detail}` : "";
|
|
41925
|
+
switch (kind) {
|
|
41926
|
+
case "no-credentials":
|
|
41927
|
+
return `no usable credentials${because}`;
|
|
41928
|
+
case "unauthorized":
|
|
41929
|
+
return `the API key was rejected (HTTP ${status})${at}${because}`;
|
|
41930
|
+
case "http-error":
|
|
41931
|
+
return `the model list returned HTTP ${status}${at}${because}`;
|
|
41932
|
+
case "unreachable":
|
|
41933
|
+
return `the model list was unreachable${at}${because}`;
|
|
41934
|
+
case "malformed":
|
|
41935
|
+
return `the model list was not valid JSON${at}`;
|
|
41936
|
+
case "empty-roster":
|
|
41937
|
+
return `the endpoint answered${at} but listed no models`;
|
|
41938
|
+
}
|
|
41939
|
+
}
|
|
41602
41940
|
function resolveBaseUrl(catalogName) {
|
|
41603
41941
|
const def = getProviderByName(catalogName);
|
|
41604
41942
|
if (!def)
|
|
@@ -41662,14 +42000,14 @@ async function discoverProviderModels(providerName) {
|
|
|
41662
42000
|
const { getServedDevinModels: getServedDevinModels2 } = await Promise.resolve().then(() => (init_devin_models(), exports_devin_models));
|
|
41663
42001
|
const served = await getServedDevinModels2();
|
|
41664
42002
|
if (served.length === 0) {
|
|
41665
|
-
|
|
41666
|
-
return [];
|
|
42003
|
+
return recordFailure({ kind: "empty-roster", provider: providerName });
|
|
41667
42004
|
}
|
|
41668
42005
|
const { devinRosterEntry: devinRosterEntry2 } = await Promise.resolve().then(() => (init_devin(), exports_devin));
|
|
41669
42006
|
const models2 = served.map((model) => {
|
|
41670
42007
|
const { wireId, ...rest } = devinRosterEntry2(model);
|
|
41671
42008
|
return { id: wireId, ...rest };
|
|
41672
42009
|
});
|
|
42010
|
+
_failures.delete(providerName);
|
|
41673
42011
|
log(`[model-discovery:${providerName}] discovered ${models2.length} models`);
|
|
41674
42012
|
_cache.set(providerName, { models: models2, expiresAt: Date.now() + CACHE_TTL_MS });
|
|
41675
42013
|
return models2;
|
|
@@ -41677,13 +42015,15 @@ async function discoverProviderModels(providerName) {
|
|
|
41677
42015
|
if (descriptor.format === "ollama-tags") {
|
|
41678
42016
|
const { fetchOllamaModels: fetchOllamaModels2 } = await Promise.resolve().then(() => exports_ollama_discovery);
|
|
41679
42017
|
const installed = await fetchOllamaModels2({ enrichCapabilities: false });
|
|
41680
|
-
if (installed.length === 0)
|
|
41681
|
-
return
|
|
42018
|
+
if (installed.length === 0) {
|
|
42019
|
+
return recordFailure({ kind: "empty-roster", provider: providerName });
|
|
42020
|
+
}
|
|
41682
42021
|
const models2 = installed.map((model) => ({
|
|
41683
42022
|
id: model.name,
|
|
41684
42023
|
displayName: model.name,
|
|
41685
42024
|
supportsTools: model.supportsTools
|
|
41686
42025
|
}));
|
|
42026
|
+
_failures.delete(providerName);
|
|
41687
42027
|
log(`[model-discovery:${providerName}] discovered ${models2.length} local models`);
|
|
41688
42028
|
_cache.set(providerName, { models: models2, expiresAt: Date.now() + CACHE_TTL_MS });
|
|
41689
42029
|
return models2;
|
|
@@ -41702,8 +42042,15 @@ async function discoverProviderModels(providerName) {
|
|
|
41702
42042
|
const auth = await credentials.getRequestAuth(providerName, { model: "" });
|
|
41703
42043
|
headers = { ...auth.headers };
|
|
41704
42044
|
} catch (e) {
|
|
41705
|
-
|
|
41706
|
-
|
|
42045
|
+
return recordFailure({
|
|
42046
|
+
kind: "no-credentials",
|
|
42047
|
+
provider: providerName,
|
|
42048
|
+
endpoint,
|
|
42049
|
+
detail: oneLine(e?.message ?? "")
|
|
42050
|
+
});
|
|
42051
|
+
}
|
|
42052
|
+
if (!hasAuthHeader(headers)) {
|
|
42053
|
+
return recordFailure({ kind: "no-credentials", provider: providerName, endpoint });
|
|
41707
42054
|
}
|
|
41708
42055
|
}
|
|
41709
42056
|
let response;
|
|
@@ -41714,25 +42061,38 @@ async function discoverProviderModels(providerName) {
|
|
|
41714
42061
|
signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
|
|
41715
42062
|
});
|
|
41716
42063
|
} catch (e) {
|
|
41717
|
-
|
|
41718
|
-
|
|
42064
|
+
return recordFailure({
|
|
42065
|
+
kind: "unreachable",
|
|
42066
|
+
provider: providerName,
|
|
42067
|
+
endpoint,
|
|
42068
|
+
detail: oneLine(e?.message ?? "")
|
|
42069
|
+
});
|
|
41719
42070
|
}
|
|
41720
42071
|
if (!response.ok) {
|
|
41721
|
-
|
|
41722
|
-
|
|
42072
|
+
const unauthorized = response.status === 401 || response.status === 403;
|
|
42073
|
+
let detail = "";
|
|
42074
|
+
try {
|
|
42075
|
+
detail = oneLine(await response.text());
|
|
42076
|
+
} catch {}
|
|
42077
|
+
return recordFailure({
|
|
42078
|
+
kind: unauthorized ? "unauthorized" : "http-error",
|
|
42079
|
+
provider: providerName,
|
|
42080
|
+
endpoint,
|
|
42081
|
+
status: response.status,
|
|
42082
|
+
detail
|
|
42083
|
+
});
|
|
41723
42084
|
}
|
|
41724
42085
|
let body;
|
|
41725
42086
|
try {
|
|
41726
42087
|
body = await response.json();
|
|
41727
42088
|
} catch {
|
|
41728
|
-
|
|
41729
|
-
return [];
|
|
42089
|
+
return recordFailure({ kind: "malformed", provider: providerName, endpoint });
|
|
41730
42090
|
}
|
|
41731
42091
|
const models = parseOpenAIModelsList(body);
|
|
41732
42092
|
if (models.length === 0) {
|
|
41733
|
-
|
|
41734
|
-
return [];
|
|
42093
|
+
return recordFailure({ kind: "empty-roster", provider: providerName, endpoint });
|
|
41735
42094
|
}
|
|
42095
|
+
_failures.delete(providerName);
|
|
41736
42096
|
log(`[model-discovery:${providerName}] discovered ${models.length} models: ` + models.map((m) => `${m.id}(${m.contextWindow ?? "?"})`).join(", "));
|
|
41737
42097
|
_cache.set(providerName, { models, expiresAt: Date.now() + CACHE_TTL_MS });
|
|
41738
42098
|
return models;
|
|
@@ -41748,13 +42108,14 @@ function rankDiscoveredModels(models) {
|
|
|
41748
42108
|
return diff !== 0 ? diff : a.id.localeCompare(b.id);
|
|
41749
42109
|
});
|
|
41750
42110
|
}
|
|
41751
|
-
var CACHE_TTL_MS, FETCH_TIMEOUT_MS = 5000, _cache, MIN_CREATED_SECONDS = 946684800, MAX_CREATED_SECONDS = 4102444800;
|
|
42111
|
+
var CACHE_TTL_MS, FETCH_TIMEOUT_MS = 5000, _cache, _failures, MIN_CREATED_SECONDS = 946684800, MAX_CREATED_SECONDS = 4102444800;
|
|
41752
42112
|
var init_model_discovery = __esm(() => {
|
|
41753
42113
|
init_authority();
|
|
41754
42114
|
init_logger();
|
|
41755
42115
|
init_provider_definitions();
|
|
41756
42116
|
CACHE_TTL_MS = 5 * 60 * 1000;
|
|
41757
42117
|
_cache = new Map;
|
|
42118
|
+
_failures = new Map;
|
|
41758
42119
|
});
|
|
41759
42120
|
|
|
41760
42121
|
// src/providers/transport/probe-discovery.ts
|
|
@@ -42150,9 +42511,10 @@ class AnthropicProviderTransport {
|
|
|
42150
42511
|
}
|
|
42151
42512
|
const discovered = await discoverProviderModels(this.provider.name);
|
|
42152
42513
|
if (discovered.length === 0) {
|
|
42514
|
+
const failure = getDiscoveryFailure(this.provider.name);
|
|
42153
42515
|
return {
|
|
42154
42516
|
model: null,
|
|
42155
|
-
reason: `${this.displayName} listed no models at ${def.modelDiscovery.path} \u2014 check the API key and that the subscription is active`
|
|
42517
|
+
reason: failure ? `${this.displayName}: ${describeDiscoveryFailure(failure)}` : `${this.displayName} listed no models at ${def.modelDiscovery.path} \u2014 check the API key and that the subscription is active`
|
|
42156
42518
|
};
|
|
42157
42519
|
}
|
|
42158
42520
|
const ranked = rankDiscoveredModels(discovered).map((m) => m.id).filter(isChatCapable);
|
|
@@ -42205,6 +42567,7 @@ class AnthropicProviderTransport {
|
|
|
42205
42567
|
kimi: "Kimi",
|
|
42206
42568
|
"kimi-coding": "Kimi Coding",
|
|
42207
42569
|
"qwen-cloud": "Qwen Plan",
|
|
42570
|
+
"qwen-payg": "Qwen PAYG",
|
|
42208
42571
|
moonshot: "Kimi",
|
|
42209
42572
|
"z-ai": "Z.AI"
|
|
42210
42573
|
};
|
|
@@ -42751,6 +43114,7 @@ var init_routing_hints = __esm(() => {
|
|
|
42751
43114
|
sakana: { apiKeyEnvVar: "SAKANA_API_KEY" },
|
|
42752
43115
|
"sakana-subscription": { apiKeyEnvVar: "SAKANA_SUBSCRIPTION_API_KEY" },
|
|
42753
43116
|
"qwen-cloud": { apiKeyEnvVar: "QWEN_CLOUD_PLAN_API_KEY" },
|
|
43117
|
+
"qwen-payg": { apiKeyEnvVar: "DASHSCOPE_API_KEY" },
|
|
42754
43118
|
ollamacloud: { apiKeyEnvVar: "OLLAMA_API_KEY" },
|
|
42755
43119
|
"native-anthropic": { apiKeyEnvVar: "ANTHROPIC_API_KEY" },
|
|
42756
43120
|
openrouter: { apiKeyEnvVar: "OPENROUTER_API_KEY" },
|
|
@@ -42799,7 +43163,7 @@ var init_default_routing_rules = __esm(() => {
|
|
|
42799
43163
|
"k3*": ["kimi-coding", "opencode-zen-go", "kimi", "openrouter"],
|
|
42800
43164
|
"minimax-*": ["minimax-coding", "opencode-zen-go", "minimax", "openrouter"],
|
|
42801
43165
|
"glm-*": ["glm-coding", "opencode-zen-go", "glm", "openrouter"],
|
|
42802
|
-
"qwen3.*": ["qwen-cloud", "opencode-zen-go", "openrouter"],
|
|
43166
|
+
"qwen3.*": ["qwen-cloud", "opencode-zen-go", "qwen-payg", "openrouter"],
|
|
42803
43167
|
"z-ai-*": ["z-ai", "openrouter"],
|
|
42804
43168
|
"deepseek-*": ["opencode-zen-go", "deepseek", "openrouter"],
|
|
42805
43169
|
"mimo-*": ["opencode-zen-go", "openrouter"],
|
|
@@ -43949,6 +44313,83 @@ var init_channel = __esm(() => {
|
|
|
43949
44313
|
init_session_manager();
|
|
43950
44314
|
});
|
|
43951
44315
|
|
|
44316
|
+
// src/mcp/progress-heartbeat.ts
|
|
44317
|
+
function isProgressToken(v) {
|
|
44318
|
+
return typeof v === "string" || typeof v === "number" && Number.isFinite(v);
|
|
44319
|
+
}
|
|
44320
|
+
function clampInterval(ms) {
|
|
44321
|
+
if (ms < MIN_PROGRESS_INTERVAL_MS)
|
|
44322
|
+
return MIN_PROGRESS_INTERVAL_MS;
|
|
44323
|
+
if (ms > MAX_PROGRESS_INTERVAL_MS)
|
|
44324
|
+
return MAX_PROGRESS_INTERVAL_MS;
|
|
44325
|
+
return ms;
|
|
44326
|
+
}
|
|
44327
|
+
function resolveProgressIntervalMs(env = process.env) {
|
|
44328
|
+
const raw = env[PROGRESS_INTERVAL_ENV_VAR];
|
|
44329
|
+
if (raw === undefined || raw === null || raw.trim() === "")
|
|
44330
|
+
return DEFAULT_PROGRESS_INTERVAL_MS;
|
|
44331
|
+
const parsed = Number(raw);
|
|
44332
|
+
if (!Number.isFinite(parsed) || parsed <= 0)
|
|
44333
|
+
return DEFAULT_PROGRESS_INTERVAL_MS;
|
|
44334
|
+
return clampInterval(parsed);
|
|
44335
|
+
}
|
|
44336
|
+
function resolveExplicitIntervalMs(ms) {
|
|
44337
|
+
if (ms === undefined)
|
|
44338
|
+
return DEFAULT_PROGRESS_INTERVAL_MS;
|
|
44339
|
+
if (!Number.isFinite(ms) || ms <= 0)
|
|
44340
|
+
return DEFAULT_PROGRESS_INTERVAL_MS;
|
|
44341
|
+
return Math.min(ms, MAX_PROGRESS_INTERVAL_MS);
|
|
44342
|
+
}
|
|
44343
|
+
function startHeartbeat(opts) {
|
|
44344
|
+
const { token, send, label } = opts;
|
|
44345
|
+
if (!isProgressToken(token))
|
|
44346
|
+
return NOOP_HEARTBEAT;
|
|
44347
|
+
const intervalMs = resolveExplicitIntervalMs(opts.intervalMs);
|
|
44348
|
+
const startedAt = Date.now();
|
|
44349
|
+
let progress = 0;
|
|
44350
|
+
let stopped = false;
|
|
44351
|
+
const emit2 = (message) => {
|
|
44352
|
+
if (stopped)
|
|
44353
|
+
return;
|
|
44354
|
+
progress += 1;
|
|
44355
|
+
try {
|
|
44356
|
+
const elapsedSeconds = Math.round((Date.now() - startedAt) / 1000);
|
|
44357
|
+
const result = send({
|
|
44358
|
+
progressToken: token,
|
|
44359
|
+
progress,
|
|
44360
|
+
message: message ?? `${label}: working (${elapsedSeconds}s)`
|
|
44361
|
+
});
|
|
44362
|
+
if (result && typeof result.then === "function") {
|
|
44363
|
+
result.catch(() => {});
|
|
44364
|
+
}
|
|
44365
|
+
} catch {}
|
|
44366
|
+
};
|
|
44367
|
+
const timer = setInterval(() => emit2(), intervalMs);
|
|
44368
|
+
timer.unref?.();
|
|
44369
|
+
return {
|
|
44370
|
+
tick: (message) => emit2(message),
|
|
44371
|
+
stop: () => {
|
|
44372
|
+
stopped = true;
|
|
44373
|
+
clearInterval(timer);
|
|
44374
|
+
},
|
|
44375
|
+
get active() {
|
|
44376
|
+
return !stopped;
|
|
44377
|
+
},
|
|
44378
|
+
get emitted() {
|
|
44379
|
+
return progress;
|
|
44380
|
+
}
|
|
44381
|
+
};
|
|
44382
|
+
}
|
|
44383
|
+
var DEFAULT_PROGRESS_INTERVAL_MS = 1e4, MIN_PROGRESS_INTERVAL_MS = 1000, MAX_PROGRESS_INTERVAL_MS = 60000, PROGRESS_INTERVAL_ENV_VAR = "CLAUDISH_MCP_PROGRESS_INTERVAL_MS", NOOP_HEARTBEAT;
|
|
44384
|
+
var init_progress_heartbeat = __esm(() => {
|
|
44385
|
+
NOOP_HEARTBEAT = Object.freeze({
|
|
44386
|
+
tick(_message) {},
|
|
44387
|
+
stop() {},
|
|
44388
|
+
active: false,
|
|
44389
|
+
emitted: 0
|
|
44390
|
+
});
|
|
44391
|
+
});
|
|
44392
|
+
|
|
43952
44393
|
// src/providers/cache-ttl.ts
|
|
43953
44394
|
var FIREBASE_CACHE_TTL_HOURS = 24, FIREBASE_CACHE_TTL_MS;
|
|
43954
44395
|
var init_cache_ttl = __esm(() => {
|
|
@@ -46812,6 +47253,34 @@ var init_native_handler_advisor = __esm(() => {
|
|
|
46812
47253
|
advisorToolUseIds = new Set;
|
|
46813
47254
|
});
|
|
46814
47255
|
|
|
47256
|
+
// src/handlers/shared/thinking-signature.ts
|
|
47257
|
+
function isUnsignedThinking(block) {
|
|
47258
|
+
if (!block || typeof block !== "object")
|
|
47259
|
+
return false;
|
|
47260
|
+
const b = block;
|
|
47261
|
+
if (b.type !== "thinking")
|
|
47262
|
+
return false;
|
|
47263
|
+
return typeof b.signature !== "string" || b.signature.length === 0;
|
|
47264
|
+
}
|
|
47265
|
+
function stripUnsignedThinkingBlocks(messages) {
|
|
47266
|
+
if (!Array.isArray(messages))
|
|
47267
|
+
return 0;
|
|
47268
|
+
let removed = 0;
|
|
47269
|
+
for (const message of messages) {
|
|
47270
|
+
if (!message || typeof message !== "object")
|
|
47271
|
+
continue;
|
|
47272
|
+
const content = message.content;
|
|
47273
|
+
if (!Array.isArray(content))
|
|
47274
|
+
continue;
|
|
47275
|
+
const kept = content.filter((block) => !isUnsignedThinking(block));
|
|
47276
|
+
if (kept.length !== content.length) {
|
|
47277
|
+
removed += content.length - kept.length;
|
|
47278
|
+
message.content = kept;
|
|
47279
|
+
}
|
|
47280
|
+
}
|
|
47281
|
+
return removed;
|
|
47282
|
+
}
|
|
47283
|
+
|
|
46815
47284
|
// src/handlers/native-handler.ts
|
|
46816
47285
|
async function resolveAdvisorKeys() {
|
|
46817
47286
|
const keyFromAuthority = async (name) => {
|
|
@@ -46857,6 +47326,10 @@ class NativeHandler {
|
|
|
46857
47326
|
async handle(c, payload) {
|
|
46858
47327
|
const originalHeaders = c.req.header();
|
|
46859
47328
|
const target = payload.model;
|
|
47329
|
+
const strippedThinking = stripUnsignedThinkingBlocks(payload.messages);
|
|
47330
|
+
if (strippedThinking > 0) {
|
|
47331
|
+
log(`[Native] stripped ${strippedThinking} unsigned thinking block(s) from history for ${target} (foreign-provider origin)`);
|
|
47332
|
+
}
|
|
46860
47333
|
const advisorCfg = loadAdvisorSwapConfig(this.advisorModels, this.advisorCollector);
|
|
46861
47334
|
let advisorSwapped = null;
|
|
46862
47335
|
let advisorRewrittenIds = [];
|
|
@@ -47084,6 +47557,7 @@ var init_api_key_map = __esm(() => {
|
|
|
47084
47557
|
aliases: ["SAKANA_CODING_API_KEY"]
|
|
47085
47558
|
},
|
|
47086
47559
|
"qwen-cloud": { envVar: "QWEN_CLOUD_PLAN_API_KEY" },
|
|
47560
|
+
"qwen-payg": { envVar: "DASHSCOPE_API_KEY", aliases: ["QWEN_API_KEY"] },
|
|
47087
47561
|
ollamacloud: { envVar: "OLLAMA_API_KEY" },
|
|
47088
47562
|
"opencode-zen": { envVar: "OPENCODE_API_KEY" },
|
|
47089
47563
|
"opencode-zen-go": { envVar: "OPENCODE_GO_API_KEY", aliases: ["OPENCODE_API_KEY"] },
|
|
@@ -47877,7 +48351,8 @@ var init_vertex_oauth = __esm(() => {
|
|
|
47877
48351
|
|
|
47878
48352
|
// src/providers/provider-profiles.ts
|
|
47879
48353
|
function requiresResponsesApi(modelName) {
|
|
47880
|
-
|
|
48354
|
+
const name = modelName.toLowerCase();
|
|
48355
|
+
return /^gpt-5\.6/.test(name) || name.includes("codex");
|
|
47881
48356
|
}
|
|
47882
48357
|
function createHandlerForProvider(ctx) {
|
|
47883
48358
|
const profile = PROVIDER_PROFILES[ctx.provider.name] ?? getRuntimeProfiles().get(ctx.provider.name);
|
|
@@ -48132,6 +48607,7 @@ var init_provider_profiles = __esm(() => {
|
|
|
48132
48607
|
kimi: anthropicCompatProfile,
|
|
48133
48608
|
"kimi-coding": anthropicCompatProfile,
|
|
48134
48609
|
"qwen-cloud": anthropicCompatProfile,
|
|
48610
|
+
"qwen-payg": anthropicCompatProfile,
|
|
48135
48611
|
"z-ai": anthropicCompatProfile,
|
|
48136
48612
|
glm: glmProfile,
|
|
48137
48613
|
"glm-coding": glmProfile,
|
|
@@ -49638,7 +50114,7 @@ import {
|
|
|
49638
50114
|
} from "fs";
|
|
49639
50115
|
import { join as join28, resolve as resolve3 } from "path";
|
|
49640
50116
|
function classifyRunOutput(opts) {
|
|
49641
|
-
const { outputSize, stdoutTail, stderr, minOutputBytes } = opts;
|
|
50117
|
+
const { outputSize, stdoutTail, stderr, minOutputBytes, requirePattern, fullOutput } = opts;
|
|
49642
50118
|
const apiError = API_ERROR_RE.exec(stdoutTail);
|
|
49643
50119
|
if (apiError) {
|
|
49644
50120
|
return {
|
|
@@ -49666,6 +50142,21 @@ function classifyRunOutput(opts) {
|
|
|
49666
50142
|
detail: `Child exited 0 but produced only ${outputSize} B of stdout ` + `(caller required at least ${minOutputBytes} B).`
|
|
49667
50143
|
};
|
|
49668
50144
|
}
|
|
50145
|
+
if (requirePattern) {
|
|
50146
|
+
const haystack = fullOutput ?? stdoutTail;
|
|
50147
|
+
let re = null;
|
|
50148
|
+
try {
|
|
50149
|
+
re = new RegExp(requirePattern);
|
|
50150
|
+
} catch {
|
|
50151
|
+
re = null;
|
|
50152
|
+
}
|
|
50153
|
+
if (re && !re.test(haystack)) {
|
|
50154
|
+
return {
|
|
50155
|
+
reason: "shape_mismatch",
|
|
50156
|
+
detail: `Child exited 0 with ${outputSize} B, but the response does not match the ` + `required pattern /${requirePattern}/. This is the signature of a child that ` + "answered and then took one more turn: `claude -p` prints only the FINAL " + "assistant message, so a background task completing (or any late notification) " + "replaces the real answer with an epilogue about it. Check the child's " + "transcript \u2014 the answer was generated, it just was not the last thing said."
|
|
50157
|
+
};
|
|
50158
|
+
}
|
|
50159
|
+
}
|
|
49669
50160
|
return null;
|
|
49670
50161
|
}
|
|
49671
50162
|
function persistErrorLog(errorLogPath, header, stderr, stdoutTail) {
|
|
@@ -49744,8 +50235,28 @@ function setupSession(sessionPath, models, input) {
|
|
|
49744
50235
|
writeFileSync12(join28(sessionPath, "status.json"), JSON.stringify(status, null, 2), "utf-8");
|
|
49745
50236
|
return manifest;
|
|
49746
50237
|
}
|
|
50238
|
+
function assertValidRequirePattern(pattern) {
|
|
50239
|
+
if (pattern === undefined)
|
|
50240
|
+
return;
|
|
50241
|
+
try {
|
|
50242
|
+
new RegExp(pattern);
|
|
50243
|
+
} catch (err) {
|
|
50244
|
+
throw new Error(`Invalid requirePattern /${pattern}/: ${err instanceof Error ? err.message : String(err)}`);
|
|
50245
|
+
}
|
|
50246
|
+
}
|
|
50247
|
+
function readFullOutputIfNeeded(opts) {
|
|
50248
|
+
const { crashed, requirePattern, outputSize, outputPath } = opts;
|
|
50249
|
+
if (crashed || !requirePattern || outputSize <= STDOUT_TAIL_LIMIT)
|
|
50250
|
+
return;
|
|
50251
|
+
try {
|
|
50252
|
+
return readFileSync18(outputPath, "utf-8");
|
|
50253
|
+
} catch {
|
|
50254
|
+
return;
|
|
50255
|
+
}
|
|
50256
|
+
}
|
|
49747
50257
|
async function runModels(sessionPath, opts = {}) {
|
|
49748
50258
|
const timeoutMs = (opts.timeout ?? 300) * 1000;
|
|
50259
|
+
assertValidRequirePattern(opts.requirePattern);
|
|
49749
50260
|
const manifest = JSON.parse(readFileSync18(join28(sessionPath, "manifest.json"), "utf-8"));
|
|
49750
50261
|
const statusPath = join28(sessionPath, "status.json");
|
|
49751
50262
|
const inputPath = join28(sessionPath, "input.md");
|
|
@@ -49757,6 +50268,7 @@ async function runModels(sessionPath, opts = {}) {
|
|
|
49757
50268
|
writeFileSync12(statusPath, JSON.stringify(statusCache, null, 2), "utf-8");
|
|
49758
50269
|
}
|
|
49759
50270
|
const minOutputBytes = opts.minOutputBytes ?? DEFAULT_MIN_OUTPUT_BYTES;
|
|
50271
|
+
const requirePattern = opts.requirePattern;
|
|
49760
50272
|
mkdirSync12(statsDir(sessionPath), { recursive: true });
|
|
49761
50273
|
const processes = new Map;
|
|
49762
50274
|
const runtimes = new Map;
|
|
@@ -49823,7 +50335,20 @@ async function runModels(sessionPath, opts = {}) {
|
|
|
49823
50335
|
resolved = true;
|
|
49824
50336
|
const outputSize = byteCount;
|
|
49825
50337
|
const crashed = exitCode !== 0;
|
|
49826
|
-
const
|
|
50338
|
+
const fullOutput = readFullOutputIfNeeded({
|
|
50339
|
+
crashed,
|
|
50340
|
+
requirePattern,
|
|
50341
|
+
outputSize,
|
|
50342
|
+
outputPath
|
|
50343
|
+
});
|
|
50344
|
+
const degraded = crashed ? null : classifyRunOutput({
|
|
50345
|
+
outputSize,
|
|
50346
|
+
stdoutTail,
|
|
50347
|
+
stderr,
|
|
50348
|
+
minOutputBytes,
|
|
50349
|
+
requirePattern,
|
|
50350
|
+
fullOutput
|
|
50351
|
+
});
|
|
49827
50352
|
const failed = crashed || degraded !== null;
|
|
49828
50353
|
const state = crashed ? "FAILED" : degraded ? "EMPTY" : "COMPLETED";
|
|
49829
50354
|
if (failed) {
|
|
@@ -50356,6 +50881,7 @@ ${block.join(`
|
|
|
50356
50881
|
required: ["model", "prompt"]
|
|
50357
50882
|
},
|
|
50358
50883
|
group: "low-level",
|
|
50884
|
+
heartbeat: true,
|
|
50359
50885
|
handler: async (args) => {
|
|
50360
50886
|
try {
|
|
50361
50887
|
const result = await runPromptViaProxy(args.model, args.prompt, args.system_prompt, args.max_tokens);
|
|
@@ -50576,7 +51102,8 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
|
|
|
50576
51102
|
required: ["models", "prompt"]
|
|
50577
51103
|
},
|
|
50578
51104
|
group: "low-level",
|
|
50579
|
-
|
|
51105
|
+
heartbeat: true,
|
|
51106
|
+
handler: async (args, ctx) => {
|
|
50580
51107
|
const modelIds = args.models;
|
|
50581
51108
|
const prompt = args.prompt;
|
|
50582
51109
|
const systemPrompt = args.system_prompt;
|
|
@@ -50593,6 +51120,7 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
|
|
|
50593
51120
|
error: error46 instanceof Error ? error46.message : String(error46)
|
|
50594
51121
|
});
|
|
50595
51122
|
}
|
|
51123
|
+
ctx.reportProgress(`compare_models: ${results.length}/${modelIds.length} models done`);
|
|
50596
51124
|
}
|
|
50597
51125
|
let output = `# Model Comparison
|
|
50598
51126
|
|
|
@@ -50658,12 +51186,21 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
|
|
|
50658
51186
|
type: "string",
|
|
50659
51187
|
description: "Task prompt text (or place input.md in the session directory before calling)"
|
|
50660
51188
|
},
|
|
50661
|
-
timeout: { type: "number", description: "Per-model timeout in seconds (default: 300)" }
|
|
51189
|
+
timeout: { type: "number", description: "Per-model timeout in seconds (default: 300)" },
|
|
51190
|
+
require_pattern: {
|
|
51191
|
+
type: "string",
|
|
51192
|
+
description: "Regex the response MUST match, or the slot is reported FAILED (state EMPTY, " + "reason 'shape_mismatch') instead of succeeded. Strongly recommended whenever " + "your prompt mandates an output shape \u2014 e.g. '```vote' for a voting panel. " + "Exit code 0 is not a success oracle: a child that answers and then takes one " + "more turn (a background Task finishing, a late notification) has its real " + "answer replaced by a short epilogue, because print mode emits only the FINAL " + "assistant message. That lands as a few hundred bytes of plausible prose with " + "exit 0 and no error, and is otherwise indistinguishable from success."
|
|
51193
|
+
},
|
|
51194
|
+
min_output_bytes: {
|
|
51195
|
+
type: "number",
|
|
51196
|
+
description: "Report a slot FAILED if it produced fewer than this many bytes (default 0 = " + "off). A blunter instrument than require_pattern \u2014 short answers can be " + "legitimate \u2014 so prefer require_pattern when you know the expected shape."
|
|
51197
|
+
}
|
|
50662
51198
|
},
|
|
50663
51199
|
required: ["mode", "path"]
|
|
50664
51200
|
},
|
|
50665
51201
|
group: "agentic",
|
|
50666
|
-
|
|
51202
|
+
heartbeat: true,
|
|
51203
|
+
handler: async (args, ctx) => {
|
|
50667
51204
|
try {
|
|
50668
51205
|
const mode = args.mode;
|
|
50669
51206
|
const path = args.path;
|
|
@@ -50671,19 +51208,26 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
|
|
|
50671
51208
|
const judges = args.judges;
|
|
50672
51209
|
const input = args.input;
|
|
50673
51210
|
const timeout = args.timeout;
|
|
51211
|
+
const requirePattern = args.require_pattern;
|
|
51212
|
+
const minOutputBytes = args.min_output_bytes;
|
|
50674
51213
|
const resolved = validateSessionPath(path);
|
|
50675
51214
|
const teamSessionId = resolved.split("/").filter(Boolean).pop() ?? "team";
|
|
50676
51215
|
const teamCreatedAt = new Date().toISOString();
|
|
50677
51216
|
const runOpts = {
|
|
50678
51217
|
timeout,
|
|
50679
|
-
|
|
50680
|
-
|
|
50681
|
-
|
|
50682
|
-
|
|
50683
|
-
|
|
50684
|
-
|
|
50685
|
-
|
|
50686
|
-
|
|
51218
|
+
requirePattern,
|
|
51219
|
+
minOutputBytes,
|
|
51220
|
+
onProgress: (u) => {
|
|
51221
|
+
ctx.reportProgress(`team: ${u.phase}`);
|
|
51222
|
+
notifyChannel({
|
|
51223
|
+
content: u.rendered,
|
|
51224
|
+
sessionId: teamSessionId,
|
|
51225
|
+
event: u.phase === "settled" ? u.allFailed ? "failed" : "completed" : "running",
|
|
51226
|
+
model: "team",
|
|
51227
|
+
elapsedSeconds: (Date.now() - Date.parse(teamCreatedAt)) / 1000,
|
|
51228
|
+
createdAt: teamCreatedAt
|
|
51229
|
+
});
|
|
51230
|
+
}
|
|
50687
51231
|
};
|
|
50688
51232
|
switch (mode) {
|
|
50689
51233
|
case "run": {
|
|
@@ -51118,6 +51662,7 @@ To report this error, use the report_error tool with error_type: "provider_failu
|
|
|
51118
51662
|
watchNotificationResult(result, { sessionId: p.sessionId, eventType: p.event });
|
|
51119
51663
|
} catch {}
|
|
51120
51664
|
};
|
|
51665
|
+
const progressIntervalMs = resolveProgressIntervalMs();
|
|
51121
51666
|
const allTools = defineTools(sessionManager, notifyChannel);
|
|
51122
51667
|
const enabledTools = allTools.filter((t) => enabledGroups.has(t.group));
|
|
51123
51668
|
const toolMap = new Map(enabledTools.map((t) => [t.name, t]));
|
|
@@ -51129,7 +51674,7 @@ To report this error, use the report_error tool with error_type: "provider_failu
|
|
|
51129
51674
|
inputSchema: t.inputSchema
|
|
51130
51675
|
}))
|
|
51131
51676
|
}));
|
|
51132
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
51677
|
+
server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
51133
51678
|
const { name, arguments: args } = request.params;
|
|
51134
51679
|
const tool = toolMap.get(name);
|
|
51135
51680
|
if (!tool) {
|
|
@@ -51138,8 +51683,15 @@ To report this error, use the report_error tool with error_type: "provider_failu
|
|
|
51138
51683
|
isError: true
|
|
51139
51684
|
};
|
|
51140
51685
|
}
|
|
51686
|
+
const heartbeat = tool.heartbeat ? startHeartbeat({
|
|
51687
|
+
token: extra._meta?.progressToken,
|
|
51688
|
+
label: name,
|
|
51689
|
+
intervalMs: progressIntervalMs,
|
|
51690
|
+
send: (frame) => extra.sendNotification({ method: "notifications/progress", params: frame })
|
|
51691
|
+
}) : NOOP_HEARTBEAT;
|
|
51692
|
+
const ctx = { reportProgress: (message) => heartbeat.tick(message) };
|
|
51141
51693
|
try {
|
|
51142
|
-
return await tool.handler(args ?? {});
|
|
51694
|
+
return await tool.handler(args ?? {}, ctx);
|
|
51143
51695
|
} catch (error46) {
|
|
51144
51696
|
return {
|
|
51145
51697
|
content: [
|
|
@@ -51150,6 +51702,8 @@ To report this error, use the report_error tool with error_type: "provider_failu
|
|
|
51150
51702
|
],
|
|
51151
51703
|
isError: true
|
|
51152
51704
|
};
|
|
51705
|
+
} finally {
|
|
51706
|
+
heartbeat.stop();
|
|
51153
51707
|
}
|
|
51154
51708
|
});
|
|
51155
51709
|
const transport = new StdioServerTransport;
|
|
@@ -51197,6 +51751,7 @@ var init_mcp_server = __esm(() => {
|
|
|
51197
51751
|
init_prehydrate();
|
|
51198
51752
|
init_diagnostics();
|
|
51199
51753
|
init_channel();
|
|
51754
|
+
init_progress_heartbeat();
|
|
51200
51755
|
init_model_loader();
|
|
51201
51756
|
init_port_manager();
|
|
51202
51757
|
init_onepassword();
|
|
@@ -51215,7 +51770,8 @@ var init_mcp_server = __esm(() => {
|
|
|
51215
51770
|
timeout: "raise `timeout`, or pick a faster model",
|
|
51216
51771
|
api_error: "retry once, or route via a different provider (or@<model>)",
|
|
51217
51772
|
background_task_ceiling: "set CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS=0 for children, or forbid background work in the prompt",
|
|
51218
|
-
empty_output: "retry once; if it repeats, drop the model"
|
|
51773
|
+
empty_output: "retry once; if it repeats, drop the model",
|
|
51774
|
+
shape_mismatch: "the answer was generated but not captured \u2014 print mode keeps only the FINAL " + "assistant message, so a late background task or notification overwrote it. " + "Retry, and forbid background work in the prompt; do NOT count this slot as a vote"
|
|
51219
51775
|
};
|
|
51220
51776
|
sanitize = sanitizeForReport;
|
|
51221
51777
|
EVENT_TO_TASK_STATUS = new Map([
|
|
@@ -51521,6 +52077,440 @@ var init_behavior_command = __esm(() => {
|
|
|
51521
52077
|
init_profile_config();
|
|
51522
52078
|
});
|
|
51523
52079
|
|
|
52080
|
+
// src/team-grid.ts
|
|
52081
|
+
var exports_team_grid = {};
|
|
52082
|
+
__export(exports_team_grid, {
|
|
52083
|
+
runWithGrid: () => runWithGrid
|
|
52084
|
+
});
|
|
52085
|
+
import { spawn as spawn3 } from "child_process";
|
|
52086
|
+
import { execSync } from "child_process";
|
|
52087
|
+
import { existsSync as existsSync23, readFileSync as readFileSync22, writeFileSync as writeFileSync15 } from "fs";
|
|
52088
|
+
import { connect as netConnect } from "net";
|
|
52089
|
+
import { dirname as dirname10, join as join30 } from "path";
|
|
52090
|
+
import { setTimeout as wait } from "timers/promises";
|
|
52091
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
52092
|
+
function resolveRouteInfo(modelId) {
|
|
52093
|
+
const parsed = parseModelSpec(modelId);
|
|
52094
|
+
if (parsed.isExplicitProvider) {
|
|
52095
|
+
return { chain: [parsed.provider], source: "direct" };
|
|
52096
|
+
}
|
|
52097
|
+
const local = loadLocalConfig();
|
|
52098
|
+
if (local?.routing && Object.keys(local.routing).length > 0) {
|
|
52099
|
+
const matched2 = matchRoutingRule(parsed.model, local.routing);
|
|
52100
|
+
if (matched2) {
|
|
52101
|
+
const routes = buildRoutingChain(matched2, parsed.model);
|
|
52102
|
+
const pattern = Object.keys(local.routing).find((k) => {
|
|
52103
|
+
if (k === parsed.model)
|
|
52104
|
+
return true;
|
|
52105
|
+
if (k.includes("*")) {
|
|
52106
|
+
const star = k.indexOf("*");
|
|
52107
|
+
return parsed.model.startsWith(k.slice(0, star)) && parsed.model.endsWith(k.slice(star + 1));
|
|
52108
|
+
}
|
|
52109
|
+
return false;
|
|
52110
|
+
});
|
|
52111
|
+
return {
|
|
52112
|
+
chain: routes.map((r) => r.displayName),
|
|
52113
|
+
source: "project routing",
|
|
52114
|
+
sourceDetail: pattern
|
|
52115
|
+
};
|
|
52116
|
+
}
|
|
52117
|
+
}
|
|
52118
|
+
const global_ = loadConfig();
|
|
52119
|
+
if (global_.routing && Object.keys(global_.routing).length > 0) {
|
|
52120
|
+
const matched2 = matchRoutingRule(parsed.model, global_.routing);
|
|
52121
|
+
if (matched2) {
|
|
52122
|
+
const routes = buildRoutingChain(matched2, parsed.model);
|
|
52123
|
+
const pattern = Object.keys(global_.routing).find((k) => {
|
|
52124
|
+
if (k === parsed.model)
|
|
52125
|
+
return true;
|
|
52126
|
+
if (k.includes("*")) {
|
|
52127
|
+
const star = k.indexOf("*");
|
|
52128
|
+
return parsed.model.startsWith(k.slice(0, star)) && parsed.model.endsWith(k.slice(star + 1));
|
|
52129
|
+
}
|
|
52130
|
+
return false;
|
|
52131
|
+
});
|
|
52132
|
+
return {
|
|
52133
|
+
chain: routes.map((r) => r.displayName),
|
|
52134
|
+
source: "user routing",
|
|
52135
|
+
sourceDetail: pattern
|
|
52136
|
+
};
|
|
52137
|
+
}
|
|
52138
|
+
}
|
|
52139
|
+
const merged = loadRoutingRules();
|
|
52140
|
+
const matched = matchRoutingRule(parsed.model, merged);
|
|
52141
|
+
if (matched) {
|
|
52142
|
+
const routes = buildRoutingChain(matched, parsed.model);
|
|
52143
|
+
return {
|
|
52144
|
+
chain: routes.map((r) => r.displayName),
|
|
52145
|
+
source: "auto"
|
|
52146
|
+
};
|
|
52147
|
+
}
|
|
52148
|
+
return {
|
|
52149
|
+
chain: [],
|
|
52150
|
+
source: "auto"
|
|
52151
|
+
};
|
|
52152
|
+
}
|
|
52153
|
+
function pickBannerColor(model, used) {
|
|
52154
|
+
let hash2 = 0;
|
|
52155
|
+
for (let i = 0;i < model.length; i++)
|
|
52156
|
+
hash2 = (hash2 << 5) - hash2 + model.charCodeAt(i) | 0;
|
|
52157
|
+
const start = Math.abs(hash2) % BANNER_BG_COLORS.length;
|
|
52158
|
+
let idx = start;
|
|
52159
|
+
if (used.size < BANNER_BG_COLORS.length) {
|
|
52160
|
+
while (used.has(idx))
|
|
52161
|
+
idx = (idx + 1) % BANNER_BG_COLORS.length;
|
|
52162
|
+
}
|
|
52163
|
+
used.add(idx);
|
|
52164
|
+
return BANNER_BG_COLORS[idx];
|
|
52165
|
+
}
|
|
52166
|
+
function buildPaneHeader(model, prompt, bg) {
|
|
52167
|
+
const route2 = resolveRouteInfo(model);
|
|
52168
|
+
const esc2 = (s) => s.replace(/'/g, "'\\''");
|
|
52169
|
+
const chainStr = route2.chain.join(" \u2192 ");
|
|
52170
|
+
const sourceLabel = route2.sourceDetail ? `${route2.source}: ${route2.sourceDetail}` : route2.source;
|
|
52171
|
+
const lines = [];
|
|
52172
|
+
lines.push(`printf '\\033[1;97;${bg}m %s \\033[0m\\n' '${esc2(model)}';`);
|
|
52173
|
+
lines.push(`printf '\\033[2m route: ${esc2(chainStr)} (${esc2(sourceLabel)})\\033[0m\\n' ;`);
|
|
52174
|
+
lines.push(`printf '\\033[2m %s\\033[0m\\n' '\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500';`);
|
|
52175
|
+
const promptForShell = esc2(prompt).replace(/\n/g, "\\n");
|
|
52176
|
+
lines.push(`printf '%b\\n' '${promptForShell}' | fold -s -w 78 | sed 's/^/ /';`);
|
|
52177
|
+
lines.push(`printf '\\033[2m %s\\033[0m\\n\\n' '\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500';`);
|
|
52178
|
+
return lines.join(" ");
|
|
52179
|
+
}
|
|
52180
|
+
function findMagmuxBinary() {
|
|
52181
|
+
const thisFile = fileURLToPath2(import.meta.url);
|
|
52182
|
+
const thisDir = dirname10(thisFile);
|
|
52183
|
+
const pkgRoot = join30(thisDir, "..");
|
|
52184
|
+
const platform2 = process.platform;
|
|
52185
|
+
const arch = process.arch;
|
|
52186
|
+
const bundledMagmux = join30(pkgRoot, "native", `magmux-${platform2}-${arch}`);
|
|
52187
|
+
if (existsSync23(bundledMagmux))
|
|
52188
|
+
return bundledMagmux;
|
|
52189
|
+
try {
|
|
52190
|
+
const pkgName = `@claudish/magmux-${platform2}-${arch}`;
|
|
52191
|
+
let searchDir = pkgRoot;
|
|
52192
|
+
for (let i = 0;i < 5; i++) {
|
|
52193
|
+
const candidate = join30(searchDir, "node_modules", pkgName, "bin", "magmux");
|
|
52194
|
+
if (existsSync23(candidate))
|
|
52195
|
+
return candidate;
|
|
52196
|
+
const parent = dirname10(searchDir);
|
|
52197
|
+
if (parent === searchDir)
|
|
52198
|
+
break;
|
|
52199
|
+
searchDir = parent;
|
|
52200
|
+
}
|
|
52201
|
+
} catch {}
|
|
52202
|
+
try {
|
|
52203
|
+
const result = execSync("which magmux", { encoding: "utf-8" }).trim();
|
|
52204
|
+
if (result)
|
|
52205
|
+
return result;
|
|
52206
|
+
} catch {}
|
|
52207
|
+
throw new Error(`magmux not found. Install it:
|
|
52208
|
+
brew install MadAppGang/tap/magmux`);
|
|
52209
|
+
}
|
|
52210
|
+
async function subscribeToMagmux(sockPath, onEvent) {
|
|
52211
|
+
let client = null;
|
|
52212
|
+
for (let attempt = 0;attempt < 40; attempt++) {
|
|
52213
|
+
if (existsSync23(sockPath)) {
|
|
52214
|
+
try {
|
|
52215
|
+
client = await new Promise((resolve5, reject) => {
|
|
52216
|
+
const s = netConnect(sockPath);
|
|
52217
|
+
s.once("connect", () => resolve5(s));
|
|
52218
|
+
s.once("error", reject);
|
|
52219
|
+
});
|
|
52220
|
+
break;
|
|
52221
|
+
} catch {}
|
|
52222
|
+
}
|
|
52223
|
+
await wait(50);
|
|
52224
|
+
}
|
|
52225
|
+
if (!client) {
|
|
52226
|
+
return { results: null, client: null };
|
|
52227
|
+
}
|
|
52228
|
+
return await new Promise((resolve5) => {
|
|
52229
|
+
let buf = "";
|
|
52230
|
+
let finalResults = null;
|
|
52231
|
+
client.on("data", (chunk) => {
|
|
52232
|
+
buf += chunk.toString("utf-8");
|
|
52233
|
+
let nl = buf.indexOf(`
|
|
52234
|
+
`);
|
|
52235
|
+
while (nl >= 0) {
|
|
52236
|
+
const line = buf.slice(0, nl).trim();
|
|
52237
|
+
buf = buf.slice(nl + 1);
|
|
52238
|
+
nl = buf.indexOf(`
|
|
52239
|
+
`);
|
|
52240
|
+
if (!line)
|
|
52241
|
+
continue;
|
|
52242
|
+
try {
|
|
52243
|
+
const evt = JSON.parse(line);
|
|
52244
|
+
onEvent?.(evt);
|
|
52245
|
+
if (evt.type === "results") {
|
|
52246
|
+
finalResults = evt;
|
|
52247
|
+
}
|
|
52248
|
+
} catch {}
|
|
52249
|
+
}
|
|
52250
|
+
});
|
|
52251
|
+
const done = () => resolve5({ results: finalResults, client });
|
|
52252
|
+
client.once("end", done);
|
|
52253
|
+
client.once("close", done);
|
|
52254
|
+
client.once("error", done);
|
|
52255
|
+
});
|
|
52256
|
+
}
|
|
52257
|
+
function buildTeamStatus(manifest, startedAt, results) {
|
|
52258
|
+
const anonIds = Object.keys(manifest.models);
|
|
52259
|
+
const models = {};
|
|
52260
|
+
for (let i = 0;i < anonIds.length; i++) {
|
|
52261
|
+
const anonId = anonIds[i];
|
|
52262
|
+
const result = results?.find((r) => r.pane === i);
|
|
52263
|
+
if (!result) {
|
|
52264
|
+
models[anonId] = {
|
|
52265
|
+
state: "TIMEOUT",
|
|
52266
|
+
exitCode: null,
|
|
52267
|
+
startedAt,
|
|
52268
|
+
completedAt: null,
|
|
52269
|
+
outputSize: 0
|
|
52270
|
+
};
|
|
52271
|
+
continue;
|
|
52272
|
+
}
|
|
52273
|
+
let state;
|
|
52274
|
+
switch (result.state) {
|
|
52275
|
+
case "completed":
|
|
52276
|
+
case "awaiting_input":
|
|
52277
|
+
state = "COMPLETED";
|
|
52278
|
+
break;
|
|
52279
|
+
case "failed":
|
|
52280
|
+
state = "FAILED";
|
|
52281
|
+
break;
|
|
52282
|
+
default:
|
|
52283
|
+
state = "TIMEOUT";
|
|
52284
|
+
}
|
|
52285
|
+
models[anonId] = {
|
|
52286
|
+
state,
|
|
52287
|
+
exitCode: result.exitCode,
|
|
52288
|
+
startedAt: result.startedAt ?? startedAt,
|
|
52289
|
+
completedAt: result.completedAt ?? new Date().toISOString(),
|
|
52290
|
+
outputSize: result.response?.length ?? 0
|
|
52291
|
+
};
|
|
52292
|
+
}
|
|
52293
|
+
return { startedAt, models };
|
|
52294
|
+
}
|
|
52295
|
+
async function runWithGrid(sessionPath, models, input, opts) {
|
|
52296
|
+
const mode = opts?.mode ?? "default";
|
|
52297
|
+
const keep = opts?.keep ?? false;
|
|
52298
|
+
const manifest = setupSession(sessionPath, models, input);
|
|
52299
|
+
const startedAt = new Date().toISOString();
|
|
52300
|
+
const gridfilePath = join30(sessionPath, "gridfile.txt");
|
|
52301
|
+
const prompt = readFileSync22(join30(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
|
|
52302
|
+
const rawPrompt = readFileSync22(join30(sessionPath, "input.md"), "utf-8");
|
|
52303
|
+
const usedBannerColors = new Set;
|
|
52304
|
+
const gridLines = Object.entries(manifest.models).map(([anonId]) => {
|
|
52305
|
+
const model = manifest.models[anonId].model;
|
|
52306
|
+
if (mode === "interactive") {
|
|
52307
|
+
return `claudish --model ${model} -i --dangerously-skip-permissions '${prompt}'`;
|
|
52308
|
+
}
|
|
52309
|
+
const bg = pickBannerColor(model, usedBannerColors);
|
|
52310
|
+
const header = buildPaneHeader(model, rawPrompt, bg);
|
|
52311
|
+
return `${header} claudish --model ${model} -y --quiet '${prompt}'`;
|
|
52312
|
+
});
|
|
52313
|
+
writeFileSync15(gridfilePath, `${gridLines.join(`
|
|
52314
|
+
`)}
|
|
52315
|
+
`, "utf-8");
|
|
52316
|
+
const magmuxPath = findMagmuxBinary();
|
|
52317
|
+
const spawnArgs = ["-g", gridfilePath];
|
|
52318
|
+
if (!keep && mode === "default") {
|
|
52319
|
+
spawnArgs.push("-w");
|
|
52320
|
+
}
|
|
52321
|
+
const proc = spawn3(magmuxPath, spawnArgs, {
|
|
52322
|
+
stdio: "inherit",
|
|
52323
|
+
env: { ...process.env }
|
|
52324
|
+
});
|
|
52325
|
+
const sockPath = `/tmp/magmux-${proc.pid}.sock`;
|
|
52326
|
+
const subscription = subscribeToMagmux(sockPath);
|
|
52327
|
+
const procExit = new Promise((resolve5) => {
|
|
52328
|
+
proc.on("exit", () => resolve5());
|
|
52329
|
+
proc.on("error", () => resolve5());
|
|
52330
|
+
});
|
|
52331
|
+
const [{ results }] = await Promise.all([subscription, procExit]);
|
|
52332
|
+
const status = buildTeamStatus(manifest, startedAt, results?.panes ?? null);
|
|
52333
|
+
const statusPath = join30(sessionPath, "status.json");
|
|
52334
|
+
writeFileSync15(statusPath, JSON.stringify(status, null, 2), "utf-8");
|
|
52335
|
+
return status;
|
|
52336
|
+
}
|
|
52337
|
+
var BANNER_BG_COLORS;
|
|
52338
|
+
var init_team_grid = __esm(() => {
|
|
52339
|
+
init_profile_config();
|
|
52340
|
+
init_model_parser();
|
|
52341
|
+
init_routing_rules();
|
|
52342
|
+
init_team_orchestrator();
|
|
52343
|
+
BANNER_BG_COLORS = [
|
|
52344
|
+
"48;2;40;90;180",
|
|
52345
|
+
"48;2;140;60;160",
|
|
52346
|
+
"48;2;30;130;100",
|
|
52347
|
+
"48;2;160;80;40",
|
|
52348
|
+
"48;2;60;120;60",
|
|
52349
|
+
"48;2;160;50;70"
|
|
52350
|
+
];
|
|
52351
|
+
});
|
|
52352
|
+
|
|
52353
|
+
// src/team-cli.ts
|
|
52354
|
+
var exports_team_cli = {};
|
|
52355
|
+
__export(exports_team_cli, {
|
|
52356
|
+
teamCommand: () => teamCommand
|
|
52357
|
+
});
|
|
52358
|
+
import { readFileSync as readFileSync23 } from "fs";
|
|
52359
|
+
import { join as join31 } from "path";
|
|
52360
|
+
function getFlag(args, flag) {
|
|
52361
|
+
const idx = args.indexOf(flag);
|
|
52362
|
+
if (idx === -1 || idx + 1 >= args.length)
|
|
52363
|
+
return;
|
|
52364
|
+
return args[idx + 1];
|
|
52365
|
+
}
|
|
52366
|
+
function hasFlag(args, flag) {
|
|
52367
|
+
return args.includes(flag);
|
|
52368
|
+
}
|
|
52369
|
+
function printStatus(status) {
|
|
52370
|
+
const modelIds = Object.keys(status.models).sort();
|
|
52371
|
+
console.log(`
|
|
52372
|
+
Team Status (started: ${status.startedAt})`);
|
|
52373
|
+
console.log("\u2500".repeat(60));
|
|
52374
|
+
for (const id of modelIds) {
|
|
52375
|
+
const m = status.models[id];
|
|
52376
|
+
const duration3 = m.startedAt && m.completedAt ? `${Math.round((new Date(m.completedAt).getTime() - new Date(m.startedAt).getTime()) / 1000)}s` : m.startedAt ? "running" : "pending";
|
|
52377
|
+
const size = m.outputSize > 0 ? ` (${m.outputSize} bytes)` : "";
|
|
52378
|
+
console.log(` ${id} ${m.state.padEnd(10)} ${duration3}${size}`);
|
|
52379
|
+
}
|
|
52380
|
+
console.log("");
|
|
52381
|
+
}
|
|
52382
|
+
function printHelp() {
|
|
52383
|
+
console.log(`
|
|
52384
|
+
Usage: claudish team <subcommand> [options]
|
|
52385
|
+
|
|
52386
|
+
Subcommands:
|
|
52387
|
+
run Run multiple models on a task in parallel
|
|
52388
|
+
judge Blind-judge existing model outputs
|
|
52389
|
+
run-and-judge Run models then judge their outputs
|
|
52390
|
+
status Show current session status
|
|
52391
|
+
|
|
52392
|
+
Options (run / run-and-judge):
|
|
52393
|
+
--path <dir> Session directory (default: .)
|
|
52394
|
+
--models <a,b,...> Comma-separated model IDs to run
|
|
52395
|
+
--input <text> Task prompt (or create input.md in --path beforehand)
|
|
52396
|
+
--timeout <secs> Timeout per model in seconds (default: 300)
|
|
52397
|
+
--grid Show all models in a magmux grid with live output + status bar
|
|
52398
|
+
|
|
52399
|
+
Options (judge / run-and-judge):
|
|
52400
|
+
--judges <a,b,...> Comma-separated judge model IDs (default: same as runners)
|
|
52401
|
+
|
|
52402
|
+
Options (status):
|
|
52403
|
+
--path <dir> Session directory (default: .)
|
|
52404
|
+
|
|
52405
|
+
Examples:
|
|
52406
|
+
claudish team run --path ./review --models minimax-m2.5,kimi-k2.5 --input "Review this code"
|
|
52407
|
+
claudish team run --grid --models kimi-k2.5,gpt-5.4,gemini-3.1-pro --input "Solve this"
|
|
52408
|
+
claudish team judge --path ./review
|
|
52409
|
+
claudish team run-and-judge --path ./review --models gpt-5.4,gemini-3.1-pro-preview --input "Evaluate this design"
|
|
52410
|
+
claudish team status --path ./review
|
|
52411
|
+
`);
|
|
52412
|
+
}
|
|
52413
|
+
async function teamCommand(args) {
|
|
52414
|
+
if (hasFlag(args, "--help") || hasFlag(args, "-h")) {
|
|
52415
|
+
printHelp();
|
|
52416
|
+
process.exit(0);
|
|
52417
|
+
}
|
|
52418
|
+
const firstArg = args[0] ?? "";
|
|
52419
|
+
const legacySubs = ["run", "judge", "run-and-judge", "status"];
|
|
52420
|
+
const subcommand = legacySubs.includes(firstArg) ? firstArg : "run";
|
|
52421
|
+
const rawSessionPath = getFlag(args, "--path") ?? ".";
|
|
52422
|
+
let sessionPath;
|
|
52423
|
+
try {
|
|
52424
|
+
sessionPath = validateSessionPath(rawSessionPath);
|
|
52425
|
+
} catch (err) {
|
|
52426
|
+
console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
52427
|
+
process.exit(1);
|
|
52428
|
+
}
|
|
52429
|
+
const modelsRaw = getFlag(args, "--models");
|
|
52430
|
+
const judgesRaw = getFlag(args, "--judges");
|
|
52431
|
+
const mode = getFlag(args, "--mode") ?? "default";
|
|
52432
|
+
const timeoutStr = getFlag(args, "--timeout");
|
|
52433
|
+
const timeout = timeoutStr ? Number.parseInt(timeoutStr, 10) : 300;
|
|
52434
|
+
let input = getFlag(args, "--input");
|
|
52435
|
+
if (!input) {
|
|
52436
|
+
const flagsWithValues = ["--models", "--judges", "--mode", "--path", "--timeout", "--input"];
|
|
52437
|
+
const positionals = args.filter((a, i) => {
|
|
52438
|
+
if (legacySubs.includes(a) && i === 0)
|
|
52439
|
+
return false;
|
|
52440
|
+
if (a.startsWith("--"))
|
|
52441
|
+
return false;
|
|
52442
|
+
const prev = args[i - 1];
|
|
52443
|
+
if (prev && flagsWithValues.includes(prev))
|
|
52444
|
+
return false;
|
|
52445
|
+
return true;
|
|
52446
|
+
});
|
|
52447
|
+
if (positionals.length > 0)
|
|
52448
|
+
input = positionals.join(" ");
|
|
52449
|
+
}
|
|
52450
|
+
const models = modelsRaw ? modelsRaw.split(",").map((m) => m.trim()).filter(Boolean) : [];
|
|
52451
|
+
const judges = judgesRaw ? judgesRaw.split(",").map((m) => m.trim()).filter(Boolean) : undefined;
|
|
52452
|
+
const effectiveMode = hasFlag(args, "--interactive") ? "interactive" : hasFlag(args, "--grid") ? "default" : mode;
|
|
52453
|
+
switch (subcommand) {
|
|
52454
|
+
case "run": {
|
|
52455
|
+
if (models.length === 0) {
|
|
52456
|
+
console.error("Error: --models is required");
|
|
52457
|
+
printHelp();
|
|
52458
|
+
process.exit(1);
|
|
52459
|
+
}
|
|
52460
|
+
if (effectiveMode === "json") {
|
|
52461
|
+
setupSession(sessionPath, models, input);
|
|
52462
|
+
const runStatus = await runModels(sessionPath, {
|
|
52463
|
+
timeout,
|
|
52464
|
+
onStatusChange: (id, s) => {
|
|
52465
|
+
process.stderr.write(`[team] ${id}: ${s.state}
|
|
52466
|
+
`);
|
|
52467
|
+
}
|
|
52468
|
+
});
|
|
52469
|
+
printStatus(runStatus);
|
|
52470
|
+
} else {
|
|
52471
|
+
const { runWithGrid: runWithGrid2 } = await Promise.resolve().then(() => (init_team_grid(), exports_team_grid));
|
|
52472
|
+
const gridStatus = await runWithGrid2(sessionPath, models, input ?? "", {
|
|
52473
|
+
timeout,
|
|
52474
|
+
mode: effectiveMode === "interactive" ? "interactive" : "default"
|
|
52475
|
+
});
|
|
52476
|
+
printStatus(gridStatus);
|
|
52477
|
+
}
|
|
52478
|
+
break;
|
|
52479
|
+
}
|
|
52480
|
+
case "judge": {
|
|
52481
|
+
await judgeResponses(sessionPath, { judges });
|
|
52482
|
+
console.log(readFileSync23(join31(sessionPath, "verdict.md"), "utf-8"));
|
|
52483
|
+
break;
|
|
52484
|
+
}
|
|
52485
|
+
case "run-and-judge": {
|
|
52486
|
+
if (models.length === 0) {
|
|
52487
|
+
console.error("Error: --models is required");
|
|
52488
|
+
process.exit(1);
|
|
52489
|
+
}
|
|
52490
|
+
setupSession(sessionPath, models, input);
|
|
52491
|
+
const status = await runModels(sessionPath, {
|
|
52492
|
+
timeout,
|
|
52493
|
+
onStatusChange: (id, s) => {
|
|
52494
|
+
process.stderr.write(`[team] ${id}: ${s.state}
|
|
52495
|
+
`);
|
|
52496
|
+
}
|
|
52497
|
+
});
|
|
52498
|
+
printStatus(status);
|
|
52499
|
+
await judgeResponses(sessionPath, { judges });
|
|
52500
|
+
console.log(readFileSync23(join31(sessionPath, "verdict.md"), "utf-8"));
|
|
52501
|
+
break;
|
|
52502
|
+
}
|
|
52503
|
+
case "status": {
|
|
52504
|
+
const statusResult = getStatus(sessionPath);
|
|
52505
|
+
printStatus(statusResult);
|
|
52506
|
+
break;
|
|
52507
|
+
}
|
|
52508
|
+
}
|
|
52509
|
+
}
|
|
52510
|
+
var init_team_cli = __esm(() => {
|
|
52511
|
+
init_team_orchestrator();
|
|
52512
|
+
});
|
|
52513
|
+
|
|
51524
52514
|
// src/auth/credentials/source.ts
|
|
51525
52515
|
function describeSourceSync(p, config3) {
|
|
51526
52516
|
if (p.isLocal)
|
|
@@ -62932,8 +63922,8 @@ var init_RemoveFileError = __esm(() => {
|
|
|
62932
63922
|
});
|
|
62933
63923
|
|
|
62934
63924
|
// ../../node_modules/.bun/@inquirer+external-editor@2.0.1+04f2146be16c61ef/node_modules/@inquirer/external-editor/dist/index.js
|
|
62935
|
-
import { spawn as
|
|
62936
|
-
import { readFileSync as
|
|
63925
|
+
import { spawn as spawn4, spawnSync as spawnSync2 } from "child_process";
|
|
63926
|
+
import { readFileSync as readFileSync24, unlinkSync as unlinkSync5, writeFileSync as writeFileSync16 } from "fs";
|
|
62937
63927
|
import path from "path";
|
|
62938
63928
|
import os from "os";
|
|
62939
63929
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
@@ -63042,14 +64032,14 @@ class ExternalEditor {
|
|
|
63042
64032
|
if (Object.prototype.hasOwnProperty.call(this.fileOptions, "mode")) {
|
|
63043
64033
|
opt.mode = this.fileOptions.mode;
|
|
63044
64034
|
}
|
|
63045
|
-
|
|
64035
|
+
writeFileSync16(this.tempFile, this.text, opt);
|
|
63046
64036
|
} catch (createFileError) {
|
|
63047
64037
|
throw new CreateFileError(createFileError);
|
|
63048
64038
|
}
|
|
63049
64039
|
}
|
|
63050
64040
|
readTemporaryFile() {
|
|
63051
64041
|
try {
|
|
63052
|
-
const tempFileBuffer =
|
|
64042
|
+
const tempFileBuffer = readFileSync24(this.tempFile);
|
|
63053
64043
|
if (tempFileBuffer.length === 0) {
|
|
63054
64044
|
this.text = "";
|
|
63055
64045
|
} else {
|
|
@@ -63080,7 +64070,7 @@ class ExternalEditor {
|
|
|
63080
64070
|
}
|
|
63081
64071
|
launchEditorAsync(callback) {
|
|
63082
64072
|
try {
|
|
63083
|
-
const editorProcess =
|
|
64073
|
+
const editorProcess = spawn4(this.editor.bin, this.editor.args.concat([this.tempFile]), { stdio: "inherit" });
|
|
63084
64074
|
editorProcess.on("exit", (code) => {
|
|
63085
64075
|
this.lastExitStatus = code;
|
|
63086
64076
|
setImmediate(callback);
|
|
@@ -64030,9 +65020,9 @@ var init_dist16 = __esm(() => {
|
|
|
64030
65020
|
|
|
64031
65021
|
// src/auth/antigravity-oauth.ts
|
|
64032
65022
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
64033
|
-
import { existsSync as
|
|
65023
|
+
import { existsSync as existsSync24, unlinkSync as unlinkSync6 } from "fs";
|
|
64034
65024
|
import { homedir as homedir28 } from "os";
|
|
64035
|
-
import { join as
|
|
65025
|
+
import { join as join32 } from "path";
|
|
64036
65026
|
async function defaultSuggestModel() {
|
|
64037
65027
|
try {
|
|
64038
65028
|
const tok = readSharedAntigravityToken();
|
|
@@ -64153,8 +65143,8 @@ No session detected yet. Starting the Antigravity CLI interactively \u2014
|
|
|
64153
65143
|
async logout(deps) {
|
|
64154
65144
|
deleteSharedAntigravityToken(deps);
|
|
64155
65145
|
try {
|
|
64156
|
-
const tokenFile =
|
|
64157
|
-
if (
|
|
65146
|
+
const tokenFile = join32(homedir28(), ".gemini", "antigravity-cli", "antigravity-oauth-token");
|
|
65147
|
+
if (existsSync24(tokenFile))
|
|
64158
65148
|
unlinkSync6(tokenFile);
|
|
64159
65149
|
} catch {}
|
|
64160
65150
|
log("[AntigravityOAuth] Antigravity session cleared (keychain + agy token file)");
|
|
@@ -64684,6 +65674,7 @@ var init_model_catalog2 = __esm(() => {
|
|
|
64684
65674
|
// src/model-selector.ts
|
|
64685
65675
|
var exports_model_selector = {};
|
|
64686
65676
|
__export(exports_model_selector, {
|
|
65677
|
+
warnDiscoveryFailure: () => warnDiscoveryFailure,
|
|
64687
65678
|
selectProfile: () => selectProfile,
|
|
64688
65679
|
selectModelsForProfile: () => selectModelsForProfile,
|
|
64689
65680
|
selectModel: () => selectModel,
|
|
@@ -65235,6 +66226,26 @@ function describeOffer(offer) {
|
|
|
65235
66226
|
});
|
|
65236
66227
|
return `FREE until ${until}`;
|
|
65237
66228
|
}
|
|
66229
|
+
function warnDiscoveryFailure(provider, displayName, def) {
|
|
66230
|
+
const failure = getDiscoveryFailure(provider);
|
|
66231
|
+
if (!failure || failure.kind === "empty-roster")
|
|
66232
|
+
return;
|
|
66233
|
+
process.stderr.write(`
|
|
66234
|
+
\u26A0 ${displayName} could not list its models: ${describeDiscoveryFailure(failure)}
|
|
66235
|
+
`);
|
|
66236
|
+
if (failure.kind === "unauthorized" || failure.kind === "no-credentials") {
|
|
66237
|
+
if (def.apiKeyEnvVar) {
|
|
66238
|
+
process.stderr.write(` Check ${def.apiKeyEnvVar} (a value in your shell overrides stored credentials).
|
|
66239
|
+
`);
|
|
66240
|
+
}
|
|
66241
|
+
if (def.apiKeyUrl)
|
|
66242
|
+
process.stderr.write(` Get a key: ${def.apiKeyUrl}
|
|
66243
|
+
`);
|
|
66244
|
+
}
|
|
66245
|
+
process.stderr.write(` Falling back to manual model entry.
|
|
66246
|
+
|
|
66247
|
+
`);
|
|
66248
|
+
}
|
|
65238
66249
|
async function buildDiscoveredModelRows(provider, displayName, catalog) {
|
|
65239
66250
|
const discovered = rankDiscoveredModels(await discoverProviderModels(provider)).filter((m) => isChatCapable(m.id));
|
|
65240
66251
|
if (discovered.length === 0)
|
|
@@ -65285,6 +66296,8 @@ async function selectModelFromProvider(provider, tierName, recommendedModels, _f
|
|
|
65285
66296
|
const picked = await pickModelFromList(provider, displayName, tierName, discoveredModels);
|
|
65286
66297
|
if (picked)
|
|
65287
66298
|
return picked;
|
|
66299
|
+
} else {
|
|
66300
|
+
warnDiscoveryFailure(provider, displayName, def);
|
|
65288
66301
|
}
|
|
65289
66302
|
}
|
|
65290
66303
|
if (isUserDeployedProvider(provider)) {
|
|
@@ -65499,6 +66512,7 @@ var init_model_selector = __esm(() => {
|
|
|
65499
66512
|
kimi: { name: "Kimi / Moonshot", description: "Direct API" },
|
|
65500
66513
|
"kimi-coding": { name: "Kimi Coding", description: "Coding subscription" },
|
|
65501
66514
|
"qwen-cloud": { name: "Qwen Plan", description: "Alibaba Model Studio subscription" },
|
|
66515
|
+
"qwen-payg": { name: "Qwen PAYG", description: "Alibaba Model Studio pay-as-you-go" },
|
|
65502
66516
|
glm: { name: "GLM / Zhipu", description: "Direct API" },
|
|
65503
66517
|
"glm-coding": { name: "GLM Coding Plan", description: "Coding subscription" },
|
|
65504
66518
|
"z-ai": { name: "Z.AI", description: "Direct API" },
|
|
@@ -65528,6 +66542,7 @@ var init_model_selector = __esm(() => {
|
|
|
65528
66542
|
"kimi",
|
|
65529
66543
|
"kimi-coding",
|
|
65530
66544
|
"qwen-cloud",
|
|
66545
|
+
"qwen-payg",
|
|
65531
66546
|
"glm",
|
|
65532
66547
|
"glm-coding",
|
|
65533
66548
|
"z-ai",
|
|
@@ -68215,22 +69230,22 @@ __export(exports_cli, {
|
|
|
68215
69230
|
});
|
|
68216
69231
|
import {
|
|
68217
69232
|
copyFileSync as copyFileSync2,
|
|
68218
|
-
existsSync as
|
|
69233
|
+
existsSync as existsSync25,
|
|
68219
69234
|
mkdirSync as mkdirSync14,
|
|
68220
|
-
readFileSync as
|
|
69235
|
+
readFileSync as readFileSync25,
|
|
68221
69236
|
readdirSync as readdirSync5,
|
|
68222
69237
|
unlinkSync as unlinkSync7,
|
|
68223
|
-
writeFileSync as
|
|
69238
|
+
writeFileSync as writeFileSync17
|
|
68224
69239
|
} from "fs";
|
|
68225
69240
|
import { homedir as homedir29 } from "os";
|
|
68226
|
-
import { dirname as
|
|
68227
|
-
import { fileURLToPath as
|
|
69241
|
+
import { dirname as dirname11, join as join33 } from "path";
|
|
69242
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
68228
69243
|
function getVersion3() {
|
|
68229
69244
|
return VERSION;
|
|
68230
69245
|
}
|
|
68231
69246
|
function clearAllModelCaches() {
|
|
68232
|
-
const cacheDir =
|
|
68233
|
-
if (!
|
|
69247
|
+
const cacheDir = join33(homedir29(), ".claudish");
|
|
69248
|
+
if (!existsSync25(cacheDir))
|
|
68234
69249
|
return;
|
|
68235
69250
|
const cachePatterns = ["pricing-cache.json", "recommended-models-cache.json"];
|
|
68236
69251
|
let cleared = 0;
|
|
@@ -68238,7 +69253,7 @@ function clearAllModelCaches() {
|
|
|
68238
69253
|
const files = readdirSync5(cacheDir);
|
|
68239
69254
|
for (const file2 of files) {
|
|
68240
69255
|
if (cachePatterns.includes(file2)) {
|
|
68241
|
-
unlinkSync7(
|
|
69256
|
+
unlinkSync7(join33(cacheDir, file2));
|
|
68242
69257
|
cleared++;
|
|
68243
69258
|
}
|
|
68244
69259
|
}
|
|
@@ -68471,7 +69486,7 @@ async function parseArgs(args) {
|
|
|
68471
69486
|
printVersion();
|
|
68472
69487
|
process.exit(0);
|
|
68473
69488
|
} else if (arg === "--help" || arg === "-h") {
|
|
68474
|
-
|
|
69489
|
+
printHelp2();
|
|
68475
69490
|
process.exit(0);
|
|
68476
69491
|
} else if (arg === "--help-ai") {
|
|
68477
69492
|
printAIAgentGuide();
|
|
@@ -68653,15 +69668,15 @@ Usage: claudish --models --provider <slug>`);
|
|
|
68653
69668
|
});
|
|
68654
69669
|
config3.resolvedDefaultProvider = resolved;
|
|
68655
69670
|
if (resolved.legacyAutoPromoted && !config3.quiet) {
|
|
68656
|
-
const markerFile =
|
|
68657
|
-
if (!
|
|
69671
|
+
const markerFile = join33(homedir29(), ".claudish", ".legacy-litellm-hint-shown");
|
|
69672
|
+
if (!existsSync25(markerFile)) {
|
|
68658
69673
|
const hint = buildLegacyHint(resolved);
|
|
68659
69674
|
if (hint) {
|
|
68660
69675
|
console.error(hint);
|
|
68661
69676
|
}
|
|
68662
69677
|
try {
|
|
68663
|
-
mkdirSync14(
|
|
68664
|
-
|
|
69678
|
+
mkdirSync14(dirname11(markerFile), { recursive: true });
|
|
69679
|
+
writeFileSync17(markerFile, new Date().toISOString(), "utf-8");
|
|
68665
69680
|
} catch {}
|
|
68666
69681
|
}
|
|
68667
69682
|
}
|
|
@@ -69106,6 +70121,7 @@ async function probeModelRouting(models, jsonOutput, options = { live: true, tim
|
|
|
69106
70121
|
"kimi",
|
|
69107
70122
|
"kimi-coding",
|
|
69108
70123
|
"qwen-cloud",
|
|
70124
|
+
"qwen-payg",
|
|
69109
70125
|
"z-ai"
|
|
69110
70126
|
];
|
|
69111
70127
|
const isMinimaxModel = modelName.toLowerCase().includes("minimax");
|
|
@@ -69427,7 +70443,7 @@ async function probeModelRouting(models, jsonOutput, options = { live: true, tim
|
|
|
69427
70443
|
await tui.shutdown();
|
|
69428
70444
|
}
|
|
69429
70445
|
}
|
|
69430
|
-
function
|
|
70446
|
+
function printHelp2() {
|
|
69431
70447
|
const useColor = !!process.stdout.isTTY && !process.env.NO_COLOR;
|
|
69432
70448
|
const c = (code) => (s) => useColor ? `\x1B[${code}m${s}\x1B[0m` : s;
|
|
69433
70449
|
const bold4 = c("1");
|
|
@@ -69730,8 +70746,8 @@ ${h("MORE INFO")}
|
|
|
69730
70746
|
}
|
|
69731
70747
|
function printAIAgentGuide() {
|
|
69732
70748
|
try {
|
|
69733
|
-
const guidePath =
|
|
69734
|
-
const guideContent =
|
|
70749
|
+
const guidePath = join33(__dirname3, "../AI_AGENT_GUIDE.md");
|
|
70750
|
+
const guideContent = readFileSync25(guidePath, "utf-8");
|
|
69735
70751
|
console.log(guideContent);
|
|
69736
70752
|
} catch (error46) {
|
|
69737
70753
|
console.error("Error reading AI Agent Guide:");
|
|
@@ -69747,19 +70763,19 @@ async function initializeClaudishSkill() {
|
|
|
69747
70763
|
console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
|
|
69748
70764
|
`);
|
|
69749
70765
|
const cwd = process.cwd();
|
|
69750
|
-
const claudeDir =
|
|
69751
|
-
const skillsDir =
|
|
69752
|
-
const claudishSkillDir =
|
|
69753
|
-
const skillFile =
|
|
69754
|
-
if (
|
|
70766
|
+
const claudeDir = join33(cwd, ".claude");
|
|
70767
|
+
const skillsDir = join33(claudeDir, "skills");
|
|
70768
|
+
const claudishSkillDir = join33(skillsDir, "claudish-usage");
|
|
70769
|
+
const skillFile = join33(claudishSkillDir, "SKILL.md");
|
|
70770
|
+
if (existsSync25(skillFile)) {
|
|
69755
70771
|
console.log("\u2705 Claudish skill already installed at:");
|
|
69756
70772
|
console.log(` ${skillFile}
|
|
69757
70773
|
`);
|
|
69758
70774
|
console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
|
|
69759
70775
|
return;
|
|
69760
70776
|
}
|
|
69761
|
-
const sourceSkillPath =
|
|
69762
|
-
if (!
|
|
70777
|
+
const sourceSkillPath = join33(__dirname3, "../skills/claudish-usage/SKILL.md");
|
|
70778
|
+
if (!existsSync25(sourceSkillPath)) {
|
|
69763
70779
|
console.error("\u274C Error: Claudish skill file not found in installation.");
|
|
69764
70780
|
console.error(` Expected at: ${sourceSkillPath}`);
|
|
69765
70781
|
console.error(`
|
|
@@ -69768,15 +70784,15 @@ async function initializeClaudishSkill() {
|
|
|
69768
70784
|
process.exit(1);
|
|
69769
70785
|
}
|
|
69770
70786
|
try {
|
|
69771
|
-
if (!
|
|
70787
|
+
if (!existsSync25(claudeDir)) {
|
|
69772
70788
|
mkdirSync14(claudeDir, { recursive: true });
|
|
69773
70789
|
console.log("\uD83D\uDCC1 Created .claude/ directory");
|
|
69774
70790
|
}
|
|
69775
|
-
if (!
|
|
70791
|
+
if (!existsSync25(skillsDir)) {
|
|
69776
70792
|
mkdirSync14(skillsDir, { recursive: true });
|
|
69777
70793
|
console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
|
|
69778
70794
|
}
|
|
69779
|
-
if (!
|
|
70795
|
+
if (!existsSync25(claudishSkillDir)) {
|
|
69780
70796
|
mkdirSync14(claudishSkillDir, { recursive: true });
|
|
69781
70797
|
console.log("\uD83D\uDCC1 Created .claude/skills/claudish-usage/ directory");
|
|
69782
70798
|
}
|
|
@@ -69848,8 +70864,8 @@ var init_cli = __esm(() => {
|
|
|
69848
70864
|
init_provider_definitions();
|
|
69849
70865
|
init_routing_rules();
|
|
69850
70866
|
init_provider_resolver();
|
|
69851
|
-
__filename3 =
|
|
69852
|
-
__dirname3 =
|
|
70867
|
+
__filename3 = fileURLToPath3(import.meta.url);
|
|
70868
|
+
__dirname3 = dirname11(__filename3);
|
|
69853
70869
|
});
|
|
69854
70870
|
|
|
69855
70871
|
// src/update-checker.ts
|
|
@@ -69861,33 +70877,33 @@ __export(exports_update_checker, {
|
|
|
69861
70877
|
clearCache: () => clearCache,
|
|
69862
70878
|
checkForUpdates: () => checkForUpdates
|
|
69863
70879
|
});
|
|
69864
|
-
import { existsSync as
|
|
70880
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync15, readFileSync as readFileSync26, unlinkSync as unlinkSync8, writeFileSync as writeFileSync18 } from "fs";
|
|
69865
70881
|
import { homedir as homedir30, platform as platform2, tmpdir } from "os";
|
|
69866
|
-
import { join as
|
|
70882
|
+
import { join as join34 } from "path";
|
|
69867
70883
|
function getCacheFilePath() {
|
|
69868
70884
|
let cacheDir;
|
|
69869
70885
|
if (isWindows) {
|
|
69870
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
69871
|
-
cacheDir =
|
|
70886
|
+
const localAppData = process.env.LOCALAPPDATA || join34(homedir30(), "AppData", "Local");
|
|
70887
|
+
cacheDir = join34(localAppData, "claudish");
|
|
69872
70888
|
} else {
|
|
69873
|
-
cacheDir =
|
|
70889
|
+
cacheDir = join34(homedir30(), ".cache", "claudish");
|
|
69874
70890
|
}
|
|
69875
70891
|
try {
|
|
69876
|
-
if (!
|
|
70892
|
+
if (!existsSync26(cacheDir)) {
|
|
69877
70893
|
mkdirSync15(cacheDir, { recursive: true });
|
|
69878
70894
|
}
|
|
69879
|
-
return
|
|
70895
|
+
return join34(cacheDir, "update-check.json");
|
|
69880
70896
|
} catch {
|
|
69881
|
-
return
|
|
70897
|
+
return join34(tmpdir(), "claudish-update-check.json");
|
|
69882
70898
|
}
|
|
69883
70899
|
}
|
|
69884
70900
|
function readCache() {
|
|
69885
70901
|
try {
|
|
69886
70902
|
const cachePath = getCacheFilePath();
|
|
69887
|
-
if (!
|
|
70903
|
+
if (!existsSync26(cachePath)) {
|
|
69888
70904
|
return null;
|
|
69889
70905
|
}
|
|
69890
|
-
const data = JSON.parse(
|
|
70906
|
+
const data = JSON.parse(readFileSync26(cachePath, "utf-8"));
|
|
69891
70907
|
return data;
|
|
69892
70908
|
} catch {
|
|
69893
70909
|
return null;
|
|
@@ -69900,7 +70916,7 @@ function writeCache(latestVersion) {
|
|
|
69900
70916
|
lastCheck: Date.now(),
|
|
69901
70917
|
latestVersion
|
|
69902
70918
|
};
|
|
69903
|
-
|
|
70919
|
+
writeFileSync18(cachePath, JSON.stringify(data), "utf-8");
|
|
69904
70920
|
} catch {}
|
|
69905
70921
|
}
|
|
69906
70922
|
function isCacheValid(cache2) {
|
|
@@ -69910,7 +70926,7 @@ function isCacheValid(cache2) {
|
|
|
69910
70926
|
function clearCache() {
|
|
69911
70927
|
try {
|
|
69912
70928
|
const cachePath = getCacheFilePath();
|
|
69913
|
-
if (
|
|
70929
|
+
if (existsSync26(cachePath)) {
|
|
69914
70930
|
unlinkSync8(cachePath);
|
|
69915
70931
|
}
|
|
69916
70932
|
} catch {}
|
|
@@ -69998,7 +71014,7 @@ var exports_update_command = {};
|
|
|
69998
71014
|
__export(exports_update_command, {
|
|
69999
71015
|
updateCommand: () => updateCommand
|
|
70000
71016
|
});
|
|
70001
|
-
import { execSync } from "child_process";
|
|
71017
|
+
import { execSync as execSync2 } from "child_process";
|
|
70002
71018
|
function detectInstallationMethod() {
|
|
70003
71019
|
const scriptPath = process.argv[1] || "";
|
|
70004
71020
|
if (scriptPath.includes("/opt/homebrew/") || scriptPath.includes("/usr/local/Cellar/")) {
|
|
@@ -70026,7 +71042,7 @@ function getUpdateCommand(method) {
|
|
|
70026
71042
|
}
|
|
70027
71043
|
async function executeUpdate(command) {
|
|
70028
71044
|
try {
|
|
70029
|
-
|
|
71045
|
+
execSync2(command, {
|
|
70030
71046
|
stdio: "inherit",
|
|
70031
71047
|
shell: process.platform === "win32" ? "cmd.exe" : "/bin/sh"
|
|
70032
71048
|
});
|
|
@@ -70163,7 +71179,7 @@ ${BOLD2}Unable to detect installation method.${RESET2}`);
|
|
|
70163
71179
|
}
|
|
70164
71180
|
function fetchLatestVersionViaNpm() {
|
|
70165
71181
|
try {
|
|
70166
|
-
const output =
|
|
71182
|
+
const output = execSync2("npm view claudish version", {
|
|
70167
71183
|
encoding: "utf-8",
|
|
70168
71184
|
timeout: 20000,
|
|
70169
71185
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -70795,15 +71811,15 @@ var init_local_liveness = __esm(() => {
|
|
|
70795
71811
|
});
|
|
70796
71812
|
|
|
70797
71813
|
// src/providers/probe-catalog.ts
|
|
70798
|
-
import { existsSync as
|
|
71814
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync16, readFileSync as readFileSync27, writeFileSync as writeFileSync19 } from "fs";
|
|
70799
71815
|
import { homedir as homedir31 } from "os";
|
|
70800
|
-
import { dirname as
|
|
71816
|
+
import { dirname as dirname12, join as join35 } from "path";
|
|
70801
71817
|
function readProbeModelsCache(path2 = PROBE_MODELS_CACHE_PATH) {
|
|
70802
|
-
if (!
|
|
71818
|
+
if (!existsSync27(path2))
|
|
70803
71819
|
return null;
|
|
70804
71820
|
let raw2;
|
|
70805
71821
|
try {
|
|
70806
|
-
raw2 = JSON.parse(
|
|
71822
|
+
raw2 = JSON.parse(readFileSync27(path2, "utf-8"));
|
|
70807
71823
|
} catch {
|
|
70808
71824
|
return null;
|
|
70809
71825
|
}
|
|
@@ -70812,8 +71828,8 @@ function readProbeModelsCache(path2 = PROBE_MODELS_CACHE_PATH) {
|
|
|
70812
71828
|
return raw2;
|
|
70813
71829
|
}
|
|
70814
71830
|
function writeProbeModelsCache(data, path2 = PROBE_MODELS_CACHE_PATH) {
|
|
70815
|
-
mkdirSync16(
|
|
70816
|
-
|
|
71831
|
+
mkdirSync16(dirname12(path2), { recursive: true });
|
|
71832
|
+
writeFileSync19(path2, JSON.stringify(data), "utf-8");
|
|
70817
71833
|
}
|
|
70818
71834
|
function isCacheFresh(data, ttlMs = CACHE_TTL_MS4) {
|
|
70819
71835
|
if (!data?.generatedAt)
|
|
@@ -70932,7 +71948,7 @@ function isValidResponse(raw2) {
|
|
|
70932
71948
|
var PROBE_MODELS_URL = "https://us-central1-claudish-6da10.cloudfunctions.net/probeModels", CACHE_TTL_MS4, FETCH_TIMEOUT_MS3 = 15000, PROBE_MODELS_CACHE_PATH, _inFlight = null;
|
|
70933
71949
|
var init_probe_catalog = __esm(() => {
|
|
70934
71950
|
CACHE_TTL_MS4 = 60 * 60 * 1000;
|
|
70935
|
-
PROBE_MODELS_CACHE_PATH =
|
|
71951
|
+
PROBE_MODELS_CACHE_PATH = join35(homedir31(), ".claudish", "probe-models.json");
|
|
70936
71952
|
});
|
|
70937
71953
|
|
|
70938
71954
|
// src/tui/constants.ts
|
|
@@ -77279,20 +78295,20 @@ __export(exports_claude_runner, {
|
|
|
77279
78295
|
MIN_AUTO_COMPACT_WINDOW: () => MIN_AUTO_COMPACT_WINDOW,
|
|
77280
78296
|
CLAUDE_CODE_DEFAULT_MAX_CONTEXT: () => CLAUDE_CODE_DEFAULT_MAX_CONTEXT
|
|
77281
78297
|
});
|
|
77282
|
-
import { spawn as
|
|
78298
|
+
import { spawn as spawn5 } from "child_process";
|
|
77283
78299
|
import {
|
|
77284
78300
|
closeSync as closeSync4,
|
|
77285
|
-
existsSync as
|
|
78301
|
+
existsSync as existsSync28,
|
|
77286
78302
|
mkdirSync as mkdirSync17,
|
|
77287
78303
|
openSync as openSync4,
|
|
77288
|
-
readFileSync as
|
|
78304
|
+
readFileSync as readFileSync28,
|
|
77289
78305
|
readdirSync as readdirSync6,
|
|
77290
78306
|
statSync as statSync5,
|
|
77291
78307
|
unlinkSync as unlinkSync9,
|
|
77292
|
-
writeFileSync as
|
|
78308
|
+
writeFileSync as writeFileSync20
|
|
77293
78309
|
} from "fs";
|
|
77294
78310
|
import { homedir as homedir32, tmpdir as tmpdir2 } from "os";
|
|
77295
|
-
import { dirname as
|
|
78311
|
+
import { dirname as dirname13, join as join36 } from "path";
|
|
77296
78312
|
import { isatty } from "tty";
|
|
77297
78313
|
function releaseTerminalIsolation() {
|
|
77298
78314
|
if (!restoreTerminal)
|
|
@@ -77327,14 +78343,14 @@ function isProxyAuthMode(config3) {
|
|
|
77327
78343
|
}
|
|
77328
78344
|
function managedSettingsPath() {
|
|
77329
78345
|
if (isWindows2()) {
|
|
77330
|
-
return
|
|
78346
|
+
return join36(process.env.PROGRAMDATA || "C:\\ProgramData", "ClaudeCode", "managed-settings.json");
|
|
77331
78347
|
}
|
|
77332
78348
|
if (process.platform === "darwin") {
|
|
77333
78349
|
return "/Library/Application Support/ClaudeCode/managed-settings.json";
|
|
77334
78350
|
}
|
|
77335
78351
|
return "/etc/claude-code/managed-settings.json";
|
|
77336
78352
|
}
|
|
77337
|
-
function managedSettingsForcesClaudeAi(readFile3 =
|
|
78353
|
+
function managedSettingsForcesClaudeAi(readFile3 = readFileSync28) {
|
|
77338
78354
|
try {
|
|
77339
78355
|
const raw2 = readFile3(managedSettingsPath(), "utf-8");
|
|
77340
78356
|
const parsed = JSON.parse(raw2);
|
|
@@ -77348,9 +78364,9 @@ function isWindows2() {
|
|
|
77348
78364
|
}
|
|
77349
78365
|
function createStatusLineScript(tokenFilePath) {
|
|
77350
78366
|
const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
|
|
77351
|
-
const claudishDir =
|
|
78367
|
+
const claudishDir = join36(homeDir, ".claudish");
|
|
77352
78368
|
const timestamp = Date.now();
|
|
77353
|
-
const scriptPath =
|
|
78369
|
+
const scriptPath = join36(claudishDir, `status-${timestamp}.js`);
|
|
77354
78370
|
const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
|
|
77355
78371
|
const script = `
|
|
77356
78372
|
const fs = require('fs');
|
|
@@ -77477,13 +78493,13 @@ process.stdin.on('end', () => {
|
|
|
77477
78493
|
}
|
|
77478
78494
|
});
|
|
77479
78495
|
`;
|
|
77480
|
-
|
|
78496
|
+
writeFileSync20(scriptPath, script, "utf-8");
|
|
77481
78497
|
return scriptPath;
|
|
77482
78498
|
}
|
|
77483
78499
|
function initializeTokenFile(tokenFilePath) {
|
|
77484
78500
|
try {
|
|
77485
|
-
mkdirSync17(
|
|
77486
|
-
|
|
78501
|
+
mkdirSync17(dirname13(tokenFilePath), { recursive: true });
|
|
78502
|
+
writeFileSync20(tokenFilePath, JSON.stringify({
|
|
77487
78503
|
input_tokens: 0,
|
|
77488
78504
|
output_tokens: 0,
|
|
77489
78505
|
total_tokens: 0,
|
|
@@ -77514,7 +78530,7 @@ function cleanupStaleTokenFiles(dir, now = Date.now(), maxAgeMs = STALE_TOKEN_FI
|
|
|
77514
78530
|
if (!name.startsWith("tokens-") || !name.endsWith(".json"))
|
|
77515
78531
|
continue;
|
|
77516
78532
|
scanned++;
|
|
77517
|
-
const full =
|
|
78533
|
+
const full = join36(dir, name);
|
|
77518
78534
|
try {
|
|
77519
78535
|
if (statSync5(full).mtimeMs >= cutoff)
|
|
77520
78536
|
continue;
|
|
@@ -77531,7 +78547,7 @@ function parseSettingsArg(value) {
|
|
|
77531
78547
|
if (value.trimStart().startsWith("{")) {
|
|
77532
78548
|
return JSON.parse(value);
|
|
77533
78549
|
}
|
|
77534
|
-
return JSON.parse(
|
|
78550
|
+
return JSON.parse(readFileSync28(value, "utf-8"));
|
|
77535
78551
|
}
|
|
77536
78552
|
function parseSettingsArgSafe(value) {
|
|
77537
78553
|
try {
|
|
@@ -77543,13 +78559,13 @@ function parseSettingsArgSafe(value) {
|
|
|
77543
78559
|
}
|
|
77544
78560
|
function userSettingsFileCandidates(cwd) {
|
|
77545
78561
|
return [
|
|
77546
|
-
|
|
77547
|
-
|
|
77548
|
-
|
|
78562
|
+
join36(homedir32(), ".claude", "settings.json"),
|
|
78563
|
+
join36(cwd, ".claude", "settings.json"),
|
|
78564
|
+
join36(cwd, ".claude", "settings.local.json")
|
|
77549
78565
|
];
|
|
77550
78566
|
}
|
|
77551
78567
|
function discoverUserStatusLineCommand(claudeArgs = [], cwd = process.cwd()) {
|
|
77552
|
-
const sources = userSettingsFileCandidates(cwd).filter((file2) =>
|
|
78568
|
+
const sources = userSettingsFileCandidates(cwd).filter((file2) => existsSync28(file2));
|
|
77553
78569
|
const idx = claudeArgs.indexOf("--settings");
|
|
77554
78570
|
const settingsArg = idx === -1 ? undefined : claudeArgs[idx + 1];
|
|
77555
78571
|
if (settingsArg)
|
|
@@ -77586,13 +78602,13 @@ function buildChainedStatusCommand(userCommand, claudishBody, claudishSegment) {
|
|
|
77586
78602
|
}
|
|
77587
78603
|
function createTempSettingsFile(_modelDisplay, port, proxyAuthMode, userStatusLineCommand) {
|
|
77588
78604
|
const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
|
|
77589
|
-
const claudishDir =
|
|
78605
|
+
const claudishDir = join36(homeDir, ".claudish");
|
|
77590
78606
|
try {
|
|
77591
78607
|
mkdirSync17(claudishDir, { recursive: true });
|
|
77592
78608
|
} catch {}
|
|
77593
78609
|
const timestamp = Date.now();
|
|
77594
|
-
const tempPath =
|
|
77595
|
-
const tokenFilePath =
|
|
78610
|
+
const tempPath = join36(claudishDir, `settings-${timestamp}.json`);
|
|
78611
|
+
const tokenFilePath = join36(claudishDir, `tokens-${port}.json`);
|
|
77596
78612
|
cleanupStaleTokenFiles(claudishDir);
|
|
77597
78613
|
initializeTokenFile(tokenFilePath);
|
|
77598
78614
|
let statusCommand;
|
|
@@ -77625,7 +78641,7 @@ function createTempSettingsFile(_modelDisplay, port, proxyAuthMode, userStatusLi
|
|
|
77625
78641
|
padding: 0
|
|
77626
78642
|
};
|
|
77627
78643
|
const settings = buildClaudishSettingsOverlay(statusLine, proxyAuthMode);
|
|
77628
|
-
|
|
78644
|
+
writeFileSync20(tempPath, JSON.stringify(settings, null, 2), "utf-8");
|
|
77629
78645
|
return { path: tempPath, statusLine, tokenFilePath };
|
|
77630
78646
|
}
|
|
77631
78647
|
function buildClaudishSettingsOverlay(statusLine, proxyAuthMode) {
|
|
@@ -77650,7 +78666,7 @@ function mergeUserSettingsIfPresent(config3, tempSettingsPath, statusLine, proxy
|
|
|
77650
78666
|
if (proxyAuthMode && !("forceLoginMethod" in userSettings)) {
|
|
77651
78667
|
userSettings.forceLoginMethod = "console";
|
|
77652
78668
|
}
|
|
77653
|
-
|
|
78669
|
+
writeFileSync20(tempSettingsPath, JSON.stringify(userSettings, null, 2), "utf-8");
|
|
77654
78670
|
} catch {
|
|
77655
78671
|
if (!config3.quiet) {
|
|
77656
78672
|
console.warn(`[claudish] Warning: could not merge user settings: ${userSettingsValue}`);
|
|
@@ -77843,7 +78859,7 @@ async function runClaudeWithProxy(config3, proxyUrl, onCleanup) {
|
|
|
77843
78859
|
console.error(`
|
|
77844
78860
|
Or set CLAUDE_PATH to your custom installation:`);
|
|
77845
78861
|
const home = homedir32();
|
|
77846
|
-
const localPath = isWindows2() ?
|
|
78862
|
+
const localPath = isWindows2() ? join36(home, ".claude", "local", "claude.exe") : join36(home, ".claude", "local", "claude");
|
|
77847
78863
|
console.error(` export CLAUDE_PATH=${localPath}`);
|
|
77848
78864
|
process.exit(1);
|
|
77849
78865
|
}
|
|
@@ -77867,7 +78883,7 @@ Or set CLAUDE_PATH to your custom installation:`);
|
|
|
77867
78883
|
console.error("[claudish] An interactive session was requested but no terminal is attached (stdin and stdout are both non-TTY). Pass a prompt argument, or use --stdin / -p for non-interactive mode.");
|
|
77868
78884
|
}
|
|
77869
78885
|
const stdio = ttyFd !== undefined ? [0, ttyFd, ttyFd] : "inherit";
|
|
77870
|
-
const proc =
|
|
78886
|
+
const proc = spawn5(spawnCommand, claudeArgs, {
|
|
77871
78887
|
env,
|
|
77872
78888
|
stdio,
|
|
77873
78889
|
shell: needsShell
|
|
@@ -77923,23 +78939,23 @@ function setupSignalHandlers(proc, tempSettingsPath, quiet, onCleanup) {
|
|
|
77923
78939
|
async function findClaudeBinary() {
|
|
77924
78940
|
const isWindows3 = process.platform === "win32";
|
|
77925
78941
|
if (process.env.CLAUDE_PATH) {
|
|
77926
|
-
if (
|
|
78942
|
+
if (existsSync28(process.env.CLAUDE_PATH)) {
|
|
77927
78943
|
return process.env.CLAUDE_PATH;
|
|
77928
78944
|
}
|
|
77929
78945
|
}
|
|
77930
78946
|
const home = homedir32();
|
|
77931
|
-
const localPath = isWindows3 ?
|
|
77932
|
-
if (
|
|
78947
|
+
const localPath = isWindows3 ? join36(home, ".claude", "local", "claude.exe") : join36(home, ".claude", "local", "claude");
|
|
78948
|
+
if (existsSync28(localPath)) {
|
|
77933
78949
|
return localPath;
|
|
77934
78950
|
}
|
|
77935
78951
|
if (isWindows3) {
|
|
77936
78952
|
const windowsPaths = [
|
|
77937
|
-
|
|
77938
|
-
|
|
77939
|
-
|
|
78953
|
+
join36(home, "AppData", "Roaming", "npm", "claude.cmd"),
|
|
78954
|
+
join36(home, ".npm-global", "claude.cmd"),
|
|
78955
|
+
join36(home, "node_modules", ".bin", "claude.cmd")
|
|
77940
78956
|
];
|
|
77941
78957
|
for (const path2 of windowsPaths) {
|
|
77942
|
-
if (
|
|
78958
|
+
if (existsSync28(path2)) {
|
|
77943
78959
|
return path2;
|
|
77944
78960
|
}
|
|
77945
78961
|
}
|
|
@@ -77947,21 +78963,21 @@ async function findClaudeBinary() {
|
|
|
77947
78963
|
const commonPaths = [
|
|
77948
78964
|
"/usr/local/bin/claude",
|
|
77949
78965
|
"/opt/homebrew/bin/claude",
|
|
77950
|
-
|
|
77951
|
-
|
|
77952
|
-
|
|
78966
|
+
join36(home, ".npm-global/bin/claude"),
|
|
78967
|
+
join36(home, ".local/bin/claude"),
|
|
78968
|
+
join36(home, "node_modules/.bin/claude"),
|
|
77953
78969
|
"/data/data/com.termux/files/usr/bin/claude",
|
|
77954
|
-
|
|
78970
|
+
join36(home, "../usr/bin/claude")
|
|
77955
78971
|
];
|
|
77956
78972
|
for (const path2 of commonPaths) {
|
|
77957
|
-
if (
|
|
78973
|
+
if (existsSync28(path2)) {
|
|
77958
78974
|
return path2;
|
|
77959
78975
|
}
|
|
77960
78976
|
}
|
|
77961
78977
|
}
|
|
77962
78978
|
try {
|
|
77963
78979
|
const shellCommand = isWindows3 ? "where claude" : "command -v claude";
|
|
77964
|
-
const proc =
|
|
78980
|
+
const proc = spawn5(shellCommand, [], {
|
|
77965
78981
|
stdio: "pipe",
|
|
77966
78982
|
shell: true
|
|
77967
78983
|
});
|
|
@@ -78013,18 +79029,18 @@ __export(exports_diag_output, {
|
|
|
78013
79029
|
NullDiagOutput: () => NullDiagOutput,
|
|
78014
79030
|
LogFileDiagOutput: () => LogFileDiagOutput
|
|
78015
79031
|
});
|
|
78016
|
-
import { createWriteStream as createWriteStream3, mkdirSync as mkdirSync18, unlinkSync as unlinkSync10, writeFileSync as
|
|
79032
|
+
import { createWriteStream as createWriteStream3, mkdirSync as mkdirSync18, unlinkSync as unlinkSync10, writeFileSync as writeFileSync21 } from "fs";
|
|
78017
79033
|
import { homedir as homedir33 } from "os";
|
|
78018
|
-
import { join as
|
|
79034
|
+
import { join as join37 } from "path";
|
|
78019
79035
|
function getClaudishDir() {
|
|
78020
|
-
const dir =
|
|
79036
|
+
const dir = join37(homedir33(), ".claudish");
|
|
78021
79037
|
try {
|
|
78022
79038
|
mkdirSync18(dir, { recursive: true });
|
|
78023
79039
|
} catch {}
|
|
78024
79040
|
return dir;
|
|
78025
79041
|
}
|
|
78026
79042
|
function getDiagLogPath() {
|
|
78027
|
-
return
|
|
79043
|
+
return join37(getClaudishDir(), `diag-${process.pid}.log`);
|
|
78028
79044
|
}
|
|
78029
79045
|
|
|
78030
79046
|
class LogFileDiagOutput {
|
|
@@ -78033,7 +79049,7 @@ class LogFileDiagOutput {
|
|
|
78033
79049
|
constructor() {
|
|
78034
79050
|
this.logPath = getDiagLogPath();
|
|
78035
79051
|
try {
|
|
78036
|
-
|
|
79052
|
+
writeFileSync21(this.logPath, `--- claudish diag session ${new Date().toISOString()} ---
|
|
78037
79053
|
`);
|
|
78038
79054
|
} catch {}
|
|
78039
79055
|
this.stream = createWriteStream3(this.logPath, { flags: "a" });
|
|
@@ -78220,279 +79236,6 @@ var init_catalog_warm = __esm(() => {
|
|
|
78220
79236
|
];
|
|
78221
79237
|
});
|
|
78222
79238
|
|
|
78223
|
-
// src/team-grid.ts
|
|
78224
|
-
var exports_team_grid = {};
|
|
78225
|
-
__export(exports_team_grid, {
|
|
78226
|
-
runWithGrid: () => runWithGrid
|
|
78227
|
-
});
|
|
78228
|
-
import { spawn as spawn5 } from "child_process";
|
|
78229
|
-
import { execSync as execSync2 } from "child_process";
|
|
78230
|
-
import { existsSync as existsSync28, readFileSync as readFileSync27, writeFileSync as writeFileSync21 } from "fs";
|
|
78231
|
-
import { connect as netConnect } from "net";
|
|
78232
|
-
import { dirname as dirname13, join as join36 } from "path";
|
|
78233
|
-
import { setTimeout as wait } from "timers/promises";
|
|
78234
|
-
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
78235
|
-
function resolveRouteInfo(modelId) {
|
|
78236
|
-
const parsed = parseModelSpec(modelId);
|
|
78237
|
-
if (parsed.isExplicitProvider) {
|
|
78238
|
-
return { chain: [parsed.provider], source: "direct" };
|
|
78239
|
-
}
|
|
78240
|
-
const local = loadLocalConfig();
|
|
78241
|
-
if (local?.routing && Object.keys(local.routing).length > 0) {
|
|
78242
|
-
const matched2 = matchRoutingRule(parsed.model, local.routing);
|
|
78243
|
-
if (matched2) {
|
|
78244
|
-
const routes = buildRoutingChain(matched2, parsed.model);
|
|
78245
|
-
const pattern = Object.keys(local.routing).find((k) => {
|
|
78246
|
-
if (k === parsed.model)
|
|
78247
|
-
return true;
|
|
78248
|
-
if (k.includes("*")) {
|
|
78249
|
-
const star = k.indexOf("*");
|
|
78250
|
-
return parsed.model.startsWith(k.slice(0, star)) && parsed.model.endsWith(k.slice(star + 1));
|
|
78251
|
-
}
|
|
78252
|
-
return false;
|
|
78253
|
-
});
|
|
78254
|
-
return {
|
|
78255
|
-
chain: routes.map((r) => r.displayName),
|
|
78256
|
-
source: "project routing",
|
|
78257
|
-
sourceDetail: pattern
|
|
78258
|
-
};
|
|
78259
|
-
}
|
|
78260
|
-
}
|
|
78261
|
-
const global_ = loadConfig();
|
|
78262
|
-
if (global_.routing && Object.keys(global_.routing).length > 0) {
|
|
78263
|
-
const matched2 = matchRoutingRule(parsed.model, global_.routing);
|
|
78264
|
-
if (matched2) {
|
|
78265
|
-
const routes = buildRoutingChain(matched2, parsed.model);
|
|
78266
|
-
const pattern = Object.keys(global_.routing).find((k) => {
|
|
78267
|
-
if (k === parsed.model)
|
|
78268
|
-
return true;
|
|
78269
|
-
if (k.includes("*")) {
|
|
78270
|
-
const star = k.indexOf("*");
|
|
78271
|
-
return parsed.model.startsWith(k.slice(0, star)) && parsed.model.endsWith(k.slice(star + 1));
|
|
78272
|
-
}
|
|
78273
|
-
return false;
|
|
78274
|
-
});
|
|
78275
|
-
return {
|
|
78276
|
-
chain: routes.map((r) => r.displayName),
|
|
78277
|
-
source: "user routing",
|
|
78278
|
-
sourceDetail: pattern
|
|
78279
|
-
};
|
|
78280
|
-
}
|
|
78281
|
-
}
|
|
78282
|
-
const merged = loadRoutingRules();
|
|
78283
|
-
const matched = matchRoutingRule(parsed.model, merged);
|
|
78284
|
-
if (matched) {
|
|
78285
|
-
const routes = buildRoutingChain(matched, parsed.model);
|
|
78286
|
-
return {
|
|
78287
|
-
chain: routes.map((r) => r.displayName),
|
|
78288
|
-
source: "auto"
|
|
78289
|
-
};
|
|
78290
|
-
}
|
|
78291
|
-
return {
|
|
78292
|
-
chain: [],
|
|
78293
|
-
source: "auto"
|
|
78294
|
-
};
|
|
78295
|
-
}
|
|
78296
|
-
function pickBannerColor(model, used) {
|
|
78297
|
-
let hash2 = 0;
|
|
78298
|
-
for (let i = 0;i < model.length; i++)
|
|
78299
|
-
hash2 = (hash2 << 5) - hash2 + model.charCodeAt(i) | 0;
|
|
78300
|
-
const start = Math.abs(hash2) % BANNER_BG_COLORS.length;
|
|
78301
|
-
let idx = start;
|
|
78302
|
-
if (used.size < BANNER_BG_COLORS.length) {
|
|
78303
|
-
while (used.has(idx))
|
|
78304
|
-
idx = (idx + 1) % BANNER_BG_COLORS.length;
|
|
78305
|
-
}
|
|
78306
|
-
used.add(idx);
|
|
78307
|
-
return BANNER_BG_COLORS[idx];
|
|
78308
|
-
}
|
|
78309
|
-
function buildPaneHeader(model, prompt, bg) {
|
|
78310
|
-
const route2 = resolveRouteInfo(model);
|
|
78311
|
-
const esc2 = (s) => s.replace(/'/g, "'\\''");
|
|
78312
|
-
const chainStr2 = route2.chain.join(" \u2192 ");
|
|
78313
|
-
const sourceLabel = route2.sourceDetail ? `${route2.source}: ${route2.sourceDetail}` : route2.source;
|
|
78314
|
-
const lines = [];
|
|
78315
|
-
lines.push(`printf '\\033[1;97;${bg}m %s \\033[0m\\n' '${esc2(model)}';`);
|
|
78316
|
-
lines.push(`printf '\\033[2m route: ${esc2(chainStr2)} (${esc2(sourceLabel)})\\033[0m\\n' ;`);
|
|
78317
|
-
lines.push(`printf '\\033[2m %s\\033[0m\\n' '\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500';`);
|
|
78318
|
-
const promptForShell = esc2(prompt).replace(/\n/g, "\\n");
|
|
78319
|
-
lines.push(`printf '%b\\n' '${promptForShell}' | fold -s -w 78 | sed 's/^/ /';`);
|
|
78320
|
-
lines.push(`printf '\\033[2m %s\\033[0m\\n\\n' '\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500';`);
|
|
78321
|
-
return lines.join(" ");
|
|
78322
|
-
}
|
|
78323
|
-
function findMagmuxBinary() {
|
|
78324
|
-
const thisFile = fileURLToPath3(import.meta.url);
|
|
78325
|
-
const thisDir = dirname13(thisFile);
|
|
78326
|
-
const pkgRoot = join36(thisDir, "..");
|
|
78327
|
-
const platform3 = process.platform;
|
|
78328
|
-
const arch = process.arch;
|
|
78329
|
-
const bundledMagmux = join36(pkgRoot, "native", `magmux-${platform3}-${arch}`);
|
|
78330
|
-
if (existsSync28(bundledMagmux))
|
|
78331
|
-
return bundledMagmux;
|
|
78332
|
-
try {
|
|
78333
|
-
const pkgName = `@claudish/magmux-${platform3}-${arch}`;
|
|
78334
|
-
let searchDir = pkgRoot;
|
|
78335
|
-
for (let i = 0;i < 5; i++) {
|
|
78336
|
-
const candidate = join36(searchDir, "node_modules", pkgName, "bin", "magmux");
|
|
78337
|
-
if (existsSync28(candidate))
|
|
78338
|
-
return candidate;
|
|
78339
|
-
const parent = dirname13(searchDir);
|
|
78340
|
-
if (parent === searchDir)
|
|
78341
|
-
break;
|
|
78342
|
-
searchDir = parent;
|
|
78343
|
-
}
|
|
78344
|
-
} catch {}
|
|
78345
|
-
try {
|
|
78346
|
-
const result = execSync2("which magmux", { encoding: "utf-8" }).trim();
|
|
78347
|
-
if (result)
|
|
78348
|
-
return result;
|
|
78349
|
-
} catch {}
|
|
78350
|
-
throw new Error(`magmux not found. Install it:
|
|
78351
|
-
brew install MadAppGang/tap/magmux`);
|
|
78352
|
-
}
|
|
78353
|
-
async function subscribeToMagmux(sockPath, onEvent) {
|
|
78354
|
-
let client = null;
|
|
78355
|
-
for (let attempt = 0;attempt < 40; attempt++) {
|
|
78356
|
-
if (existsSync28(sockPath)) {
|
|
78357
|
-
try {
|
|
78358
|
-
client = await new Promise((resolve5, reject) => {
|
|
78359
|
-
const s = netConnect(sockPath);
|
|
78360
|
-
s.once("connect", () => resolve5(s));
|
|
78361
|
-
s.once("error", reject);
|
|
78362
|
-
});
|
|
78363
|
-
break;
|
|
78364
|
-
} catch {}
|
|
78365
|
-
}
|
|
78366
|
-
await wait(50);
|
|
78367
|
-
}
|
|
78368
|
-
if (!client) {
|
|
78369
|
-
return { results: null, client: null };
|
|
78370
|
-
}
|
|
78371
|
-
return await new Promise((resolve5) => {
|
|
78372
|
-
let buf = "";
|
|
78373
|
-
let finalResults = null;
|
|
78374
|
-
client.on("data", (chunk) => {
|
|
78375
|
-
buf += chunk.toString("utf-8");
|
|
78376
|
-
let nl = buf.indexOf(`
|
|
78377
|
-
`);
|
|
78378
|
-
while (nl >= 0) {
|
|
78379
|
-
const line = buf.slice(0, nl).trim();
|
|
78380
|
-
buf = buf.slice(nl + 1);
|
|
78381
|
-
nl = buf.indexOf(`
|
|
78382
|
-
`);
|
|
78383
|
-
if (!line)
|
|
78384
|
-
continue;
|
|
78385
|
-
try {
|
|
78386
|
-
const evt = JSON.parse(line);
|
|
78387
|
-
onEvent?.(evt);
|
|
78388
|
-
if (evt.type === "results") {
|
|
78389
|
-
finalResults = evt;
|
|
78390
|
-
}
|
|
78391
|
-
} catch {}
|
|
78392
|
-
}
|
|
78393
|
-
});
|
|
78394
|
-
const done = () => resolve5({ results: finalResults, client });
|
|
78395
|
-
client.once("end", done);
|
|
78396
|
-
client.once("close", done);
|
|
78397
|
-
client.once("error", done);
|
|
78398
|
-
});
|
|
78399
|
-
}
|
|
78400
|
-
function buildTeamStatus(manifest, startedAt, results) {
|
|
78401
|
-
const anonIds = Object.keys(manifest.models);
|
|
78402
|
-
const models = {};
|
|
78403
|
-
for (let i = 0;i < anonIds.length; i++) {
|
|
78404
|
-
const anonId = anonIds[i];
|
|
78405
|
-
const result = results?.find((r) => r.pane === i);
|
|
78406
|
-
if (!result) {
|
|
78407
|
-
models[anonId] = {
|
|
78408
|
-
state: "TIMEOUT",
|
|
78409
|
-
exitCode: null,
|
|
78410
|
-
startedAt,
|
|
78411
|
-
completedAt: null,
|
|
78412
|
-
outputSize: 0
|
|
78413
|
-
};
|
|
78414
|
-
continue;
|
|
78415
|
-
}
|
|
78416
|
-
let state;
|
|
78417
|
-
switch (result.state) {
|
|
78418
|
-
case "completed":
|
|
78419
|
-
case "awaiting_input":
|
|
78420
|
-
state = "COMPLETED";
|
|
78421
|
-
break;
|
|
78422
|
-
case "failed":
|
|
78423
|
-
state = "FAILED";
|
|
78424
|
-
break;
|
|
78425
|
-
default:
|
|
78426
|
-
state = "TIMEOUT";
|
|
78427
|
-
}
|
|
78428
|
-
models[anonId] = {
|
|
78429
|
-
state,
|
|
78430
|
-
exitCode: result.exitCode,
|
|
78431
|
-
startedAt: result.startedAt ?? startedAt,
|
|
78432
|
-
completedAt: result.completedAt ?? new Date().toISOString(),
|
|
78433
|
-
outputSize: result.response?.length ?? 0
|
|
78434
|
-
};
|
|
78435
|
-
}
|
|
78436
|
-
return { startedAt, models };
|
|
78437
|
-
}
|
|
78438
|
-
async function runWithGrid(sessionPath, models, input, opts) {
|
|
78439
|
-
const mode = opts?.mode ?? "default";
|
|
78440
|
-
const keep = opts?.keep ?? false;
|
|
78441
|
-
const manifest = setupSession(sessionPath, models, input);
|
|
78442
|
-
const startedAt = new Date().toISOString();
|
|
78443
|
-
const gridfilePath = join36(sessionPath, "gridfile.txt");
|
|
78444
|
-
const prompt = readFileSync27(join36(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
|
|
78445
|
-
const rawPrompt = readFileSync27(join36(sessionPath, "input.md"), "utf-8");
|
|
78446
|
-
const usedBannerColors = new Set;
|
|
78447
|
-
const gridLines = Object.entries(manifest.models).map(([anonId]) => {
|
|
78448
|
-
const model = manifest.models[anonId].model;
|
|
78449
|
-
if (mode === "interactive") {
|
|
78450
|
-
return `claudish --model ${model} -i --dangerously-skip-permissions '${prompt}'`;
|
|
78451
|
-
}
|
|
78452
|
-
const bg = pickBannerColor(model, usedBannerColors);
|
|
78453
|
-
const header = buildPaneHeader(model, rawPrompt, bg);
|
|
78454
|
-
return `${header} claudish --model ${model} -y --quiet '${prompt}'`;
|
|
78455
|
-
});
|
|
78456
|
-
writeFileSync21(gridfilePath, `${gridLines.join(`
|
|
78457
|
-
`)}
|
|
78458
|
-
`, "utf-8");
|
|
78459
|
-
const magmuxPath = findMagmuxBinary();
|
|
78460
|
-
const spawnArgs = ["-g", gridfilePath];
|
|
78461
|
-
if (!keep && mode === "default") {
|
|
78462
|
-
spawnArgs.push("-w");
|
|
78463
|
-
}
|
|
78464
|
-
const proc = spawn5(magmuxPath, spawnArgs, {
|
|
78465
|
-
stdio: "inherit",
|
|
78466
|
-
env: { ...process.env }
|
|
78467
|
-
});
|
|
78468
|
-
const sockPath = `/tmp/magmux-${proc.pid}.sock`;
|
|
78469
|
-
const subscription = subscribeToMagmux(sockPath);
|
|
78470
|
-
const procExit = new Promise((resolve5) => {
|
|
78471
|
-
proc.on("exit", () => resolve5());
|
|
78472
|
-
proc.on("error", () => resolve5());
|
|
78473
|
-
});
|
|
78474
|
-
const [{ results }] = await Promise.all([subscription, procExit]);
|
|
78475
|
-
const status = buildTeamStatus(manifest, startedAt, results?.panes ?? null);
|
|
78476
|
-
const statusPath = join36(sessionPath, "status.json");
|
|
78477
|
-
writeFileSync21(statusPath, JSON.stringify(status, null, 2), "utf-8");
|
|
78478
|
-
return status;
|
|
78479
|
-
}
|
|
78480
|
-
var BANNER_BG_COLORS;
|
|
78481
|
-
var init_team_grid = __esm(() => {
|
|
78482
|
-
init_profile_config();
|
|
78483
|
-
init_model_parser();
|
|
78484
|
-
init_routing_rules();
|
|
78485
|
-
init_team_orchestrator();
|
|
78486
|
-
BANNER_BG_COLORS = [
|
|
78487
|
-
"48;2;40;90;180",
|
|
78488
|
-
"48;2;140;60;160",
|
|
78489
|
-
"48;2;30;130;100",
|
|
78490
|
-
"48;2;160;80;40",
|
|
78491
|
-
"48;2;60;120;60",
|
|
78492
|
-
"48;2;160;50;70"
|
|
78493
|
-
];
|
|
78494
|
-
});
|
|
78495
|
-
|
|
78496
79239
|
// src/tui/viz/text.ts
|
|
78497
79240
|
function columns(n, fn, arg = "width") {
|
|
78498
79241
|
if (!Number.isFinite(n))
|
|
@@ -78895,7 +79638,7 @@ __export(exports_session_discovery, {
|
|
|
78895
79638
|
import { execFile, execFileSync as execFileSync2 } from "child_process";
|
|
78896
79639
|
import { closeSync as closeSync5, openSync as openSync5, readSync, readdirSync as readdirSync7, statSync as statSync6 } from "fs";
|
|
78897
79640
|
import { homedir as homedir34 } from "os";
|
|
78898
|
-
import { basename, join as
|
|
79641
|
+
import { basename, join as join38 } from "path";
|
|
78899
79642
|
function slugForPath(absPath) {
|
|
78900
79643
|
return absPath.replace(/[/.]/g, "-");
|
|
78901
79644
|
}
|
|
@@ -78944,7 +79687,7 @@ function projectDirs() {
|
|
|
78944
79687
|
}
|
|
78945
79688
|
}
|
|
78946
79689
|
function sessionsIn(dirName) {
|
|
78947
|
-
const dir =
|
|
79690
|
+
const dir = join38(PROJECTS_DIR, dirName);
|
|
78948
79691
|
let names;
|
|
78949
79692
|
try {
|
|
78950
79693
|
names = readdirSync7(dir).filter((n) => n.endsWith(".jsonl"));
|
|
@@ -78953,7 +79696,7 @@ function sessionsIn(dirName) {
|
|
|
78953
79696
|
}
|
|
78954
79697
|
const rows = [];
|
|
78955
79698
|
for (const n of names) {
|
|
78956
|
-
const file2 =
|
|
79699
|
+
const file2 = join38(dir, n);
|
|
78957
79700
|
try {
|
|
78958
79701
|
const st = statSync6(file2);
|
|
78959
79702
|
if (st.size === 0)
|
|
@@ -79312,7 +80055,7 @@ function findLatestSessionId(cwd = process.cwd(), sinceMs = 0) {
|
|
|
79312
80055
|
}
|
|
79313
80056
|
var ENTRYPOINT_BYTES = 8192, PROJECTS_DIR, ACTIVE_WINDOW_MS = 120000, HEAD_BYTES, TAIL_BYTES, HARNESS_ENVELOPES, DEEP_TAIL_BYTES, RECENT_AI_TURNS = 5, RECENT_USER_TURNS = 1;
|
|
79314
80057
|
var init_session_discovery = __esm(() => {
|
|
79315
|
-
PROJECTS_DIR =
|
|
80058
|
+
PROJECTS_DIR = join38(homedir34(), ".claude", "projects");
|
|
79316
80059
|
HEAD_BYTES = 64 * 1024;
|
|
79317
80060
|
TAIL_BYTES = 128 * 1024;
|
|
79318
80061
|
HARNESS_ENVELOPES = [
|
|
@@ -81004,22 +81747,26 @@ __export(exports_session_stats, {
|
|
|
81004
81747
|
readSessionStats: () => readSessionStats,
|
|
81005
81748
|
computeSavings: () => computeSavings
|
|
81006
81749
|
});
|
|
81007
|
-
import { readFileSync as
|
|
81750
|
+
import { readFileSync as readFileSync29 } from "fs";
|
|
81008
81751
|
import { homedir as homedir35 } from "os";
|
|
81009
|
-
import { join as
|
|
81752
|
+
import { join as join39 } from "path";
|
|
81010
81753
|
function tokenFilePath(port) {
|
|
81011
|
-
return process.env.CLAUDISH_TOKEN_FILE ||
|
|
81754
|
+
return process.env.CLAUDISH_TOKEN_FILE || join39(homedir35(), ".claudish", `tokens-${port}.json`);
|
|
81012
81755
|
}
|
|
81013
|
-
function readSessionStats(port) {
|
|
81756
|
+
function readSessionStats(port, opts) {
|
|
81014
81757
|
let raw2;
|
|
81015
81758
|
try {
|
|
81016
|
-
raw2 = JSON.parse(
|
|
81759
|
+
raw2 = JSON.parse(readFileSync29(tokenFilePath(port), "utf-8"));
|
|
81017
81760
|
} catch {
|
|
81018
81761
|
return null;
|
|
81019
81762
|
}
|
|
81020
81763
|
if (!raw2 || typeof raw2 !== "object")
|
|
81021
81764
|
return null;
|
|
81022
81765
|
const d = raw2;
|
|
81766
|
+
const processStartMs = opts?.processStartMs ?? Date.now() - Math.round(process.uptime() * 1000);
|
|
81767
|
+
const trackerStartedAt = num(d.started_at);
|
|
81768
|
+
if (trackerStartedAt <= 0 || trackerStartedAt < processStartMs)
|
|
81769
|
+
return null;
|
|
81023
81770
|
const inputTokens = num(d.input_tokens);
|
|
81024
81771
|
const outputTokens = num(d.output_tokens);
|
|
81025
81772
|
if (inputTokens <= 0 && outputTokens <= 0)
|
|
@@ -81349,8 +82096,8 @@ var init_session_summary = __esm(() => {
|
|
|
81349
82096
|
init_op_source();
|
|
81350
82097
|
init_startup_trace();
|
|
81351
82098
|
var import_dotenv3 = __toESM(require_main(), 1);
|
|
81352
|
-
import { existsSync as existsSync29, readFileSync as
|
|
81353
|
-
import { join as
|
|
82099
|
+
import { existsSync as existsSync29, readFileSync as readFileSync30 } from "fs";
|
|
82100
|
+
import { join as join40, resolve as resolve5 } from "path";
|
|
81354
82101
|
import_dotenv3.config({ quiet: true });
|
|
81355
82102
|
function classifyStartupKind() {
|
|
81356
82103
|
const argv = process.argv.slice(2);
|
|
@@ -81484,6 +82231,7 @@ var isConfigCommand = firstPositional === "config";
|
|
|
81484
82231
|
var isServeCommand = firstPositional === "serve";
|
|
81485
82232
|
var isProvidersCommand = firstPositional === "providers";
|
|
81486
82233
|
var isBehaviorCommand = firstPositional === "behavior";
|
|
82234
|
+
var isTeamCommand = firstPositional === "team";
|
|
81487
82235
|
var isLoginCommand = firstPositional === "login";
|
|
81488
82236
|
var isLogoutCommand = firstPositional === "logout";
|
|
81489
82237
|
var isQuotaCommand = firstPositional === "quota" || firstPositional === "usage";
|
|
@@ -81509,6 +82257,12 @@ if (isMcpMode) {
|
|
|
81509
82257
|
console.error(`[claudish behavior] ${e instanceof Error ? e.message : String(e)}`);
|
|
81510
82258
|
process.exit(1);
|
|
81511
82259
|
}));
|
|
82260
|
+
} else if (isTeamCommand) {
|
|
82261
|
+
const teamArgIndex = args.indexOf("team");
|
|
82262
|
+
Promise.resolve().then(() => (init_team_cli(), exports_team_cli)).then((m) => m.teamCommand(args.slice(teamArgIndex + 1)).catch((e) => {
|
|
82263
|
+
console.error(`[claudish team] ${e instanceof Error ? e.message : String(e)}`);
|
|
82264
|
+
process.exit(1);
|
|
82265
|
+
}));
|
|
81512
82266
|
} else if (isProvidersCommand) {
|
|
81513
82267
|
const json2 = args.includes("--json");
|
|
81514
82268
|
Promise.resolve().then(() => (init_providers_command(), exports_providers_command)).then((m) => m.providersCommand({ json: json2 }).catch((e) => {
|
|
@@ -81593,14 +82347,14 @@ async function runCli() {
|
|
|
81593
82347
|
if (cliConfig.team && cliConfig.team.length > 0) {
|
|
81594
82348
|
let prompt = cliConfig.claudeArgs.join(" ");
|
|
81595
82349
|
if (cliConfig.inputFile) {
|
|
81596
|
-
prompt =
|
|
82350
|
+
prompt = readFileSync30(cliConfig.inputFile, "utf-8");
|
|
81597
82351
|
}
|
|
81598
82352
|
if (!prompt.trim()) {
|
|
81599
82353
|
console.error("Error: --team requires a prompt (positional args or -f <file>)");
|
|
81600
82354
|
process.exit(1);
|
|
81601
82355
|
}
|
|
81602
82356
|
const mode = cliConfig.teamMode ?? "default";
|
|
81603
|
-
const sessionPath =
|
|
82357
|
+
const sessionPath = join40(process.cwd(), `.claudish-team-${Date.now()}`);
|
|
81604
82358
|
if (mode === "json") {
|
|
81605
82359
|
const { setupSession: setupSession2, runModels: runModels2 } = await Promise.resolve().then(() => (init_team_orchestrator(), exports_team_orchestrator));
|
|
81606
82360
|
setupSession2(sessionPath, cliConfig.team, prompt);
|
|
@@ -81610,9 +82364,9 @@ async function runCli() {
|
|
|
81610
82364
|
});
|
|
81611
82365
|
const result = { ...status2, responses: {} };
|
|
81612
82366
|
for (const anonId of Object.keys(status2.models)) {
|
|
81613
|
-
const responsePath =
|
|
82367
|
+
const responsePath = join40(sessionPath, `response-${anonId}.md`);
|
|
81614
82368
|
try {
|
|
81615
|
-
const raw2 =
|
|
82369
|
+
const raw2 = readFileSync30(responsePath, "utf-8").trim();
|
|
81616
82370
|
try {
|
|
81617
82371
|
result.responses[anonId] = JSON.parse(raw2);
|
|
81618
82372
|
} catch {
|