claudish 7.48.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 +1066 -420
- 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",
|
|
@@ -29640,6 +29640,48 @@ var init_base_api_format = __esm(() => {
|
|
|
29640
29640
|
});
|
|
29641
29641
|
|
|
29642
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
|
+
}
|
|
29643
29685
|
var AnthropicAPIFormat;
|
|
29644
29686
|
var init_anthropic_api_format = __esm(() => {
|
|
29645
29687
|
init_base_api_format();
|
|
@@ -29684,14 +29726,16 @@ var init_anthropic_api_format = __esm(() => {
|
|
|
29684
29726
|
return claudeRequest.tools || [];
|
|
29685
29727
|
}
|
|
29686
29728
|
buildPayload(claudeRequest, messages, tools) {
|
|
29729
|
+
const { messages: cleanMessages, hoisted } = hoistInlineSystem(messages);
|
|
29687
29730
|
const payload = {
|
|
29688
29731
|
model: this.modelId,
|
|
29689
|
-
messages,
|
|
29732
|
+
messages: cleanMessages,
|
|
29690
29733
|
max_tokens: claudeRequest.max_tokens || 4096,
|
|
29691
29734
|
stream: true
|
|
29692
29735
|
};
|
|
29693
|
-
|
|
29694
|
-
|
|
29736
|
+
const system = mergeSystem(claudeRequest.system, hoisted);
|
|
29737
|
+
if (system !== undefined) {
|
|
29738
|
+
payload.system = system;
|
|
29695
29739
|
}
|
|
29696
29740
|
if (tools.length > 0) {
|
|
29697
29741
|
payload.tools = tools;
|
|
@@ -34884,14 +34928,14 @@ var init_config = __esm(() => {
|
|
|
34884
34928
|
});
|
|
34885
34929
|
|
|
34886
34930
|
// src/behavior/harness.ts
|
|
34887
|
-
function extractAvailableSkills(
|
|
34888
|
-
if (!
|
|
34931
|
+
function extractAvailableSkills(systemText2) {
|
|
34932
|
+
if (!systemText2)
|
|
34889
34933
|
return [];
|
|
34890
|
-
const start = SKILL_SECTION.exec(
|
|
34934
|
+
const start = SKILL_SECTION.exec(systemText2);
|
|
34891
34935
|
if (!start)
|
|
34892
34936
|
return [];
|
|
34893
34937
|
const out = [];
|
|
34894
|
-
const body =
|
|
34938
|
+
const body = systemText2.slice(start.index + start[0].length);
|
|
34895
34939
|
for (const line of body.split(`
|
|
34896
34940
|
`)) {
|
|
34897
34941
|
const trimmed2 = line.trim();
|
|
@@ -38024,6 +38068,170 @@ var init_anthropic_error = __esm(() => {
|
|
|
38024
38068
|
CONTROL_CHARS = /[\x00-\x1F\x7F]/g;
|
|
38025
38069
|
});
|
|
38026
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
|
+
|
|
38027
38235
|
// src/handlers/shared/connection-error.ts
|
|
38028
38236
|
function findConnectionCode(error46) {
|
|
38029
38237
|
let e = error46;
|
|
@@ -38584,6 +38792,31 @@ function createAnthropicPassthroughStream(c, response, opts) {
|
|
|
38584
38792
|
const filterThinking = opts.adapter?.shouldFilterThinking() ?? false;
|
|
38585
38793
|
const interceptToolFrame = createToolRepairInterceptor(opts);
|
|
38586
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
|
+
};
|
|
38587
38820
|
const flushPendingEvent = (controller) => {
|
|
38588
38821
|
if (pendingEventLine !== null && !isClosed) {
|
|
38589
38822
|
controller.enqueue(encoder.encode(`${pendingEventLine}
|
|
@@ -38601,6 +38834,48 @@ function createAnthropicPassthroughStream(c, response, opts) {
|
|
|
38601
38834
|
}
|
|
38602
38835
|
flushPendingEvent(controller);
|
|
38603
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 {}
|
|
38604
38879
|
};
|
|
38605
38880
|
return c.body(new ReadableStream({
|
|
38606
38881
|
async start(controller) {
|
|
@@ -38621,12 +38896,9 @@ data: {"type":"ping"}
|
|
|
38621
38896
|
try {
|
|
38622
38897
|
const reader = response.body.getReader();
|
|
38623
38898
|
let buffer = "";
|
|
38624
|
-
let inputTokens = 0;
|
|
38625
|
-
let outputTokens = 0;
|
|
38626
38899
|
let totalLines = 0;
|
|
38627
38900
|
let textChunks = 0;
|
|
38628
38901
|
let toolUseBlocks = 0;
|
|
38629
|
-
let stopReason = null;
|
|
38630
38902
|
let insideThinkingBlock = false;
|
|
38631
38903
|
let thinkingBlocksSuppressed = 0;
|
|
38632
38904
|
let suppressedFrame = false;
|
|
@@ -38691,6 +38963,7 @@ data: ${JSON.stringify({
|
|
|
38691
38963
|
flushPendingEvent(controller);
|
|
38692
38964
|
controller.enqueue(encoder.encode(`${modifiedLine}
|
|
38693
38965
|
`));
|
|
38966
|
+
noteLifecycle(data, reindexed);
|
|
38694
38967
|
}
|
|
38695
38968
|
} else {
|
|
38696
38969
|
enqueueData(controller, data, line);
|
|
@@ -38813,6 +39086,13 @@ data: ${JSON.stringify({
|
|
|
38813
39086
|
}
|
|
38814
39087
|
} catch (e) {
|
|
38815
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 {}
|
|
38816
39096
|
if (!isClosed) {
|
|
38817
39097
|
isClosed = true;
|
|
38818
39098
|
if (pingInterval) {
|
|
@@ -40773,9 +41053,12 @@ class ComposedHandler {
|
|
|
40773
41053
|
behaviorSession?.noteTurnComplete(this.tokenTracker.getInputTokens());
|
|
40774
41054
|
} catch {}
|
|
40775
41055
|
};
|
|
40776
|
-
|
|
41056
|
+
const streamed = this.handleStream(c, response, adapter, claudeRequest, toolNameMap, onStreamComplete, (code, message) => {
|
|
40777
41057
|
streamApiError = { code, message };
|
|
40778
41058
|
}, behaviorSession);
|
|
41059
|
+
if (payload?.stream === true)
|
|
41060
|
+
return streamed;
|
|
41061
|
+
return sseResponseToJson(streamed, this.bareModelName);
|
|
40779
41062
|
}
|
|
40780
41063
|
async settleResponsesStreamHead(initial, reissue) {
|
|
40781
41064
|
let response = initial;
|
|
@@ -41084,6 +41367,7 @@ var init_composed_handler = __esm(() => {
|
|
|
41084
41367
|
init_telemetry();
|
|
41085
41368
|
init_transform();
|
|
41086
41369
|
init_anthropic_error();
|
|
41370
|
+
init_collect_sse_message();
|
|
41087
41371
|
init_connection_error();
|
|
41088
41372
|
init_devin_stream_head_sniffer();
|
|
41089
41373
|
init_openai_compat();
|
|
@@ -44029,6 +44313,83 @@ var init_channel = __esm(() => {
|
|
|
44029
44313
|
init_session_manager();
|
|
44030
44314
|
});
|
|
44031
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
|
+
|
|
44032
44393
|
// src/providers/cache-ttl.ts
|
|
44033
44394
|
var FIREBASE_CACHE_TTL_HOURS = 24, FIREBASE_CACHE_TTL_MS;
|
|
44034
44395
|
var init_cache_ttl = __esm(() => {
|
|
@@ -46892,6 +47253,34 @@ var init_native_handler_advisor = __esm(() => {
|
|
|
46892
47253
|
advisorToolUseIds = new Set;
|
|
46893
47254
|
});
|
|
46894
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
|
+
|
|
46895
47284
|
// src/handlers/native-handler.ts
|
|
46896
47285
|
async function resolveAdvisorKeys() {
|
|
46897
47286
|
const keyFromAuthority = async (name) => {
|
|
@@ -46937,6 +47326,10 @@ class NativeHandler {
|
|
|
46937
47326
|
async handle(c, payload) {
|
|
46938
47327
|
const originalHeaders = c.req.header();
|
|
46939
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
|
+
}
|
|
46940
47333
|
const advisorCfg = loadAdvisorSwapConfig(this.advisorModels, this.advisorCollector);
|
|
46941
47334
|
let advisorSwapped = null;
|
|
46942
47335
|
let advisorRewrittenIds = [];
|
|
@@ -47958,7 +48351,8 @@ var init_vertex_oauth = __esm(() => {
|
|
|
47958
48351
|
|
|
47959
48352
|
// src/providers/provider-profiles.ts
|
|
47960
48353
|
function requiresResponsesApi(modelName) {
|
|
47961
|
-
|
|
48354
|
+
const name = modelName.toLowerCase();
|
|
48355
|
+
return /^gpt-5\.6/.test(name) || name.includes("codex");
|
|
47962
48356
|
}
|
|
47963
48357
|
function createHandlerForProvider(ctx) {
|
|
47964
48358
|
const profile = PROVIDER_PROFILES[ctx.provider.name] ?? getRuntimeProfiles().get(ctx.provider.name);
|
|
@@ -49720,7 +50114,7 @@ import {
|
|
|
49720
50114
|
} from "fs";
|
|
49721
50115
|
import { join as join28, resolve as resolve3 } from "path";
|
|
49722
50116
|
function classifyRunOutput(opts) {
|
|
49723
|
-
const { outputSize, stdoutTail, stderr, minOutputBytes } = opts;
|
|
50117
|
+
const { outputSize, stdoutTail, stderr, minOutputBytes, requirePattern, fullOutput } = opts;
|
|
49724
50118
|
const apiError = API_ERROR_RE.exec(stdoutTail);
|
|
49725
50119
|
if (apiError) {
|
|
49726
50120
|
return {
|
|
@@ -49748,6 +50142,21 @@ function classifyRunOutput(opts) {
|
|
|
49748
50142
|
detail: `Child exited 0 but produced only ${outputSize} B of stdout ` + `(caller required at least ${minOutputBytes} B).`
|
|
49749
50143
|
};
|
|
49750
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
|
+
}
|
|
49751
50160
|
return null;
|
|
49752
50161
|
}
|
|
49753
50162
|
function persistErrorLog(errorLogPath, header, stderr, stdoutTail) {
|
|
@@ -49826,8 +50235,28 @@ function setupSession(sessionPath, models, input) {
|
|
|
49826
50235
|
writeFileSync12(join28(sessionPath, "status.json"), JSON.stringify(status, null, 2), "utf-8");
|
|
49827
50236
|
return manifest;
|
|
49828
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
|
+
}
|
|
49829
50257
|
async function runModels(sessionPath, opts = {}) {
|
|
49830
50258
|
const timeoutMs = (opts.timeout ?? 300) * 1000;
|
|
50259
|
+
assertValidRequirePattern(opts.requirePattern);
|
|
49831
50260
|
const manifest = JSON.parse(readFileSync18(join28(sessionPath, "manifest.json"), "utf-8"));
|
|
49832
50261
|
const statusPath = join28(sessionPath, "status.json");
|
|
49833
50262
|
const inputPath = join28(sessionPath, "input.md");
|
|
@@ -49839,6 +50268,7 @@ async function runModels(sessionPath, opts = {}) {
|
|
|
49839
50268
|
writeFileSync12(statusPath, JSON.stringify(statusCache, null, 2), "utf-8");
|
|
49840
50269
|
}
|
|
49841
50270
|
const minOutputBytes = opts.minOutputBytes ?? DEFAULT_MIN_OUTPUT_BYTES;
|
|
50271
|
+
const requirePattern = opts.requirePattern;
|
|
49842
50272
|
mkdirSync12(statsDir(sessionPath), { recursive: true });
|
|
49843
50273
|
const processes = new Map;
|
|
49844
50274
|
const runtimes = new Map;
|
|
@@ -49905,7 +50335,20 @@ async function runModels(sessionPath, opts = {}) {
|
|
|
49905
50335
|
resolved = true;
|
|
49906
50336
|
const outputSize = byteCount;
|
|
49907
50337
|
const crashed = exitCode !== 0;
|
|
49908
|
-
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
|
+
});
|
|
49909
50352
|
const failed = crashed || degraded !== null;
|
|
49910
50353
|
const state = crashed ? "FAILED" : degraded ? "EMPTY" : "COMPLETED";
|
|
49911
50354
|
if (failed) {
|
|
@@ -50438,6 +50881,7 @@ ${block.join(`
|
|
|
50438
50881
|
required: ["model", "prompt"]
|
|
50439
50882
|
},
|
|
50440
50883
|
group: "low-level",
|
|
50884
|
+
heartbeat: true,
|
|
50441
50885
|
handler: async (args) => {
|
|
50442
50886
|
try {
|
|
50443
50887
|
const result = await runPromptViaProxy(args.model, args.prompt, args.system_prompt, args.max_tokens);
|
|
@@ -50658,7 +51102,8 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
|
|
|
50658
51102
|
required: ["models", "prompt"]
|
|
50659
51103
|
},
|
|
50660
51104
|
group: "low-level",
|
|
50661
|
-
|
|
51105
|
+
heartbeat: true,
|
|
51106
|
+
handler: async (args, ctx) => {
|
|
50662
51107
|
const modelIds = args.models;
|
|
50663
51108
|
const prompt = args.prompt;
|
|
50664
51109
|
const systemPrompt = args.system_prompt;
|
|
@@ -50675,6 +51120,7 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
|
|
|
50675
51120
|
error: error46 instanceof Error ? error46.message : String(error46)
|
|
50676
51121
|
});
|
|
50677
51122
|
}
|
|
51123
|
+
ctx.reportProgress(`compare_models: ${results.length}/${modelIds.length} models done`);
|
|
50678
51124
|
}
|
|
50679
51125
|
let output = `# Model Comparison
|
|
50680
51126
|
|
|
@@ -50740,12 +51186,21 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
|
|
|
50740
51186
|
type: "string",
|
|
50741
51187
|
description: "Task prompt text (or place input.md in the session directory before calling)"
|
|
50742
51188
|
},
|
|
50743
|
-
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
|
+
}
|
|
50744
51198
|
},
|
|
50745
51199
|
required: ["mode", "path"]
|
|
50746
51200
|
},
|
|
50747
51201
|
group: "agentic",
|
|
50748
|
-
|
|
51202
|
+
heartbeat: true,
|
|
51203
|
+
handler: async (args, ctx) => {
|
|
50749
51204
|
try {
|
|
50750
51205
|
const mode = args.mode;
|
|
50751
51206
|
const path = args.path;
|
|
@@ -50753,19 +51208,26 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
|
|
|
50753
51208
|
const judges = args.judges;
|
|
50754
51209
|
const input = args.input;
|
|
50755
51210
|
const timeout = args.timeout;
|
|
51211
|
+
const requirePattern = args.require_pattern;
|
|
51212
|
+
const minOutputBytes = args.min_output_bytes;
|
|
50756
51213
|
const resolved = validateSessionPath(path);
|
|
50757
51214
|
const teamSessionId = resolved.split("/").filter(Boolean).pop() ?? "team";
|
|
50758
51215
|
const teamCreatedAt = new Date().toISOString();
|
|
50759
51216
|
const runOpts = {
|
|
50760
51217
|
timeout,
|
|
50761
|
-
|
|
50762
|
-
|
|
50763
|
-
|
|
50764
|
-
|
|
50765
|
-
|
|
50766
|
-
|
|
50767
|
-
|
|
50768
|
-
|
|
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
|
+
}
|
|
50769
51231
|
};
|
|
50770
51232
|
switch (mode) {
|
|
50771
51233
|
case "run": {
|
|
@@ -51200,6 +51662,7 @@ To report this error, use the report_error tool with error_type: "provider_failu
|
|
|
51200
51662
|
watchNotificationResult(result, { sessionId: p.sessionId, eventType: p.event });
|
|
51201
51663
|
} catch {}
|
|
51202
51664
|
};
|
|
51665
|
+
const progressIntervalMs = resolveProgressIntervalMs();
|
|
51203
51666
|
const allTools = defineTools(sessionManager, notifyChannel);
|
|
51204
51667
|
const enabledTools = allTools.filter((t) => enabledGroups.has(t.group));
|
|
51205
51668
|
const toolMap = new Map(enabledTools.map((t) => [t.name, t]));
|
|
@@ -51211,7 +51674,7 @@ To report this error, use the report_error tool with error_type: "provider_failu
|
|
|
51211
51674
|
inputSchema: t.inputSchema
|
|
51212
51675
|
}))
|
|
51213
51676
|
}));
|
|
51214
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
51677
|
+
server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
51215
51678
|
const { name, arguments: args } = request.params;
|
|
51216
51679
|
const tool = toolMap.get(name);
|
|
51217
51680
|
if (!tool) {
|
|
@@ -51220,8 +51683,15 @@ To report this error, use the report_error tool with error_type: "provider_failu
|
|
|
51220
51683
|
isError: true
|
|
51221
51684
|
};
|
|
51222
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) };
|
|
51223
51693
|
try {
|
|
51224
|
-
return await tool.handler(args ?? {});
|
|
51694
|
+
return await tool.handler(args ?? {}, ctx);
|
|
51225
51695
|
} catch (error46) {
|
|
51226
51696
|
return {
|
|
51227
51697
|
content: [
|
|
@@ -51232,6 +51702,8 @@ To report this error, use the report_error tool with error_type: "provider_failu
|
|
|
51232
51702
|
],
|
|
51233
51703
|
isError: true
|
|
51234
51704
|
};
|
|
51705
|
+
} finally {
|
|
51706
|
+
heartbeat.stop();
|
|
51235
51707
|
}
|
|
51236
51708
|
});
|
|
51237
51709
|
const transport = new StdioServerTransport;
|
|
@@ -51279,6 +51751,7 @@ var init_mcp_server = __esm(() => {
|
|
|
51279
51751
|
init_prehydrate();
|
|
51280
51752
|
init_diagnostics();
|
|
51281
51753
|
init_channel();
|
|
51754
|
+
init_progress_heartbeat();
|
|
51282
51755
|
init_model_loader();
|
|
51283
51756
|
init_port_manager();
|
|
51284
51757
|
init_onepassword();
|
|
@@ -51297,7 +51770,8 @@ var init_mcp_server = __esm(() => {
|
|
|
51297
51770
|
timeout: "raise `timeout`, or pick a faster model",
|
|
51298
51771
|
api_error: "retry once, or route via a different provider (or@<model>)",
|
|
51299
51772
|
background_task_ceiling: "set CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS=0 for children, or forbid background work in the prompt",
|
|
51300
|
-
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"
|
|
51301
51775
|
};
|
|
51302
51776
|
sanitize = sanitizeForReport;
|
|
51303
51777
|
EVENT_TO_TASK_STATUS = new Map([
|
|
@@ -51603,6 +52077,440 @@ var init_behavior_command = __esm(() => {
|
|
|
51603
52077
|
init_profile_config();
|
|
51604
52078
|
});
|
|
51605
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
|
+
|
|
51606
52514
|
// src/auth/credentials/source.ts
|
|
51607
52515
|
function describeSourceSync(p, config3) {
|
|
51608
52516
|
if (p.isLocal)
|
|
@@ -63014,8 +63922,8 @@ var init_RemoveFileError = __esm(() => {
|
|
|
63014
63922
|
});
|
|
63015
63923
|
|
|
63016
63924
|
// ../../node_modules/.bun/@inquirer+external-editor@2.0.1+04f2146be16c61ef/node_modules/@inquirer/external-editor/dist/index.js
|
|
63017
|
-
import { spawn as
|
|
63018
|
-
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";
|
|
63019
63927
|
import path from "path";
|
|
63020
63928
|
import os from "os";
|
|
63021
63929
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
@@ -63124,14 +64032,14 @@ class ExternalEditor {
|
|
|
63124
64032
|
if (Object.prototype.hasOwnProperty.call(this.fileOptions, "mode")) {
|
|
63125
64033
|
opt.mode = this.fileOptions.mode;
|
|
63126
64034
|
}
|
|
63127
|
-
|
|
64035
|
+
writeFileSync16(this.tempFile, this.text, opt);
|
|
63128
64036
|
} catch (createFileError) {
|
|
63129
64037
|
throw new CreateFileError(createFileError);
|
|
63130
64038
|
}
|
|
63131
64039
|
}
|
|
63132
64040
|
readTemporaryFile() {
|
|
63133
64041
|
try {
|
|
63134
|
-
const tempFileBuffer =
|
|
64042
|
+
const tempFileBuffer = readFileSync24(this.tempFile);
|
|
63135
64043
|
if (tempFileBuffer.length === 0) {
|
|
63136
64044
|
this.text = "";
|
|
63137
64045
|
} else {
|
|
@@ -63162,7 +64070,7 @@ class ExternalEditor {
|
|
|
63162
64070
|
}
|
|
63163
64071
|
launchEditorAsync(callback) {
|
|
63164
64072
|
try {
|
|
63165
|
-
const editorProcess =
|
|
64073
|
+
const editorProcess = spawn4(this.editor.bin, this.editor.args.concat([this.tempFile]), { stdio: "inherit" });
|
|
63166
64074
|
editorProcess.on("exit", (code) => {
|
|
63167
64075
|
this.lastExitStatus = code;
|
|
63168
64076
|
setImmediate(callback);
|
|
@@ -64112,9 +65020,9 @@ var init_dist16 = __esm(() => {
|
|
|
64112
65020
|
|
|
64113
65021
|
// src/auth/antigravity-oauth.ts
|
|
64114
65022
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
64115
|
-
import { existsSync as
|
|
65023
|
+
import { existsSync as existsSync24, unlinkSync as unlinkSync6 } from "fs";
|
|
64116
65024
|
import { homedir as homedir28 } from "os";
|
|
64117
|
-
import { join as
|
|
65025
|
+
import { join as join32 } from "path";
|
|
64118
65026
|
async function defaultSuggestModel() {
|
|
64119
65027
|
try {
|
|
64120
65028
|
const tok = readSharedAntigravityToken();
|
|
@@ -64235,8 +65143,8 @@ No session detected yet. Starting the Antigravity CLI interactively \u2014
|
|
|
64235
65143
|
async logout(deps) {
|
|
64236
65144
|
deleteSharedAntigravityToken(deps);
|
|
64237
65145
|
try {
|
|
64238
|
-
const tokenFile =
|
|
64239
|
-
if (
|
|
65146
|
+
const tokenFile = join32(homedir28(), ".gemini", "antigravity-cli", "antigravity-oauth-token");
|
|
65147
|
+
if (existsSync24(tokenFile))
|
|
64240
65148
|
unlinkSync6(tokenFile);
|
|
64241
65149
|
} catch {}
|
|
64242
65150
|
log("[AntigravityOAuth] Antigravity session cleared (keychain + agy token file)");
|
|
@@ -68322,22 +69230,22 @@ __export(exports_cli, {
|
|
|
68322
69230
|
});
|
|
68323
69231
|
import {
|
|
68324
69232
|
copyFileSync as copyFileSync2,
|
|
68325
|
-
existsSync as
|
|
69233
|
+
existsSync as existsSync25,
|
|
68326
69234
|
mkdirSync as mkdirSync14,
|
|
68327
|
-
readFileSync as
|
|
69235
|
+
readFileSync as readFileSync25,
|
|
68328
69236
|
readdirSync as readdirSync5,
|
|
68329
69237
|
unlinkSync as unlinkSync7,
|
|
68330
|
-
writeFileSync as
|
|
69238
|
+
writeFileSync as writeFileSync17
|
|
68331
69239
|
} from "fs";
|
|
68332
69240
|
import { homedir as homedir29 } from "os";
|
|
68333
|
-
import { dirname as
|
|
68334
|
-
import { fileURLToPath as
|
|
69241
|
+
import { dirname as dirname11, join as join33 } from "path";
|
|
69242
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
68335
69243
|
function getVersion3() {
|
|
68336
69244
|
return VERSION;
|
|
68337
69245
|
}
|
|
68338
69246
|
function clearAllModelCaches() {
|
|
68339
|
-
const cacheDir =
|
|
68340
|
-
if (!
|
|
69247
|
+
const cacheDir = join33(homedir29(), ".claudish");
|
|
69248
|
+
if (!existsSync25(cacheDir))
|
|
68341
69249
|
return;
|
|
68342
69250
|
const cachePatterns = ["pricing-cache.json", "recommended-models-cache.json"];
|
|
68343
69251
|
let cleared = 0;
|
|
@@ -68345,7 +69253,7 @@ function clearAllModelCaches() {
|
|
|
68345
69253
|
const files = readdirSync5(cacheDir);
|
|
68346
69254
|
for (const file2 of files) {
|
|
68347
69255
|
if (cachePatterns.includes(file2)) {
|
|
68348
|
-
unlinkSync7(
|
|
69256
|
+
unlinkSync7(join33(cacheDir, file2));
|
|
68349
69257
|
cleared++;
|
|
68350
69258
|
}
|
|
68351
69259
|
}
|
|
@@ -68578,7 +69486,7 @@ async function parseArgs(args) {
|
|
|
68578
69486
|
printVersion();
|
|
68579
69487
|
process.exit(0);
|
|
68580
69488
|
} else if (arg === "--help" || arg === "-h") {
|
|
68581
|
-
|
|
69489
|
+
printHelp2();
|
|
68582
69490
|
process.exit(0);
|
|
68583
69491
|
} else if (arg === "--help-ai") {
|
|
68584
69492
|
printAIAgentGuide();
|
|
@@ -68760,15 +69668,15 @@ Usage: claudish --models --provider <slug>`);
|
|
|
68760
69668
|
});
|
|
68761
69669
|
config3.resolvedDefaultProvider = resolved;
|
|
68762
69670
|
if (resolved.legacyAutoPromoted && !config3.quiet) {
|
|
68763
|
-
const markerFile =
|
|
68764
|
-
if (!
|
|
69671
|
+
const markerFile = join33(homedir29(), ".claudish", ".legacy-litellm-hint-shown");
|
|
69672
|
+
if (!existsSync25(markerFile)) {
|
|
68765
69673
|
const hint = buildLegacyHint(resolved);
|
|
68766
69674
|
if (hint) {
|
|
68767
69675
|
console.error(hint);
|
|
68768
69676
|
}
|
|
68769
69677
|
try {
|
|
68770
|
-
mkdirSync14(
|
|
68771
|
-
|
|
69678
|
+
mkdirSync14(dirname11(markerFile), { recursive: true });
|
|
69679
|
+
writeFileSync17(markerFile, new Date().toISOString(), "utf-8");
|
|
68772
69680
|
} catch {}
|
|
68773
69681
|
}
|
|
68774
69682
|
}
|
|
@@ -69535,7 +70443,7 @@ async function probeModelRouting(models, jsonOutput, options = { live: true, tim
|
|
|
69535
70443
|
await tui.shutdown();
|
|
69536
70444
|
}
|
|
69537
70445
|
}
|
|
69538
|
-
function
|
|
70446
|
+
function printHelp2() {
|
|
69539
70447
|
const useColor = !!process.stdout.isTTY && !process.env.NO_COLOR;
|
|
69540
70448
|
const c = (code) => (s) => useColor ? `\x1B[${code}m${s}\x1B[0m` : s;
|
|
69541
70449
|
const bold4 = c("1");
|
|
@@ -69838,8 +70746,8 @@ ${h("MORE INFO")}
|
|
|
69838
70746
|
}
|
|
69839
70747
|
function printAIAgentGuide() {
|
|
69840
70748
|
try {
|
|
69841
|
-
const guidePath =
|
|
69842
|
-
const guideContent =
|
|
70749
|
+
const guidePath = join33(__dirname3, "../AI_AGENT_GUIDE.md");
|
|
70750
|
+
const guideContent = readFileSync25(guidePath, "utf-8");
|
|
69843
70751
|
console.log(guideContent);
|
|
69844
70752
|
} catch (error46) {
|
|
69845
70753
|
console.error("Error reading AI Agent Guide:");
|
|
@@ -69855,19 +70763,19 @@ async function initializeClaudishSkill() {
|
|
|
69855
70763
|
console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
|
|
69856
70764
|
`);
|
|
69857
70765
|
const cwd = process.cwd();
|
|
69858
|
-
const claudeDir =
|
|
69859
|
-
const skillsDir =
|
|
69860
|
-
const claudishSkillDir =
|
|
69861
|
-
const skillFile =
|
|
69862
|
-
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)) {
|
|
69863
70771
|
console.log("\u2705 Claudish skill already installed at:");
|
|
69864
70772
|
console.log(` ${skillFile}
|
|
69865
70773
|
`);
|
|
69866
70774
|
console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
|
|
69867
70775
|
return;
|
|
69868
70776
|
}
|
|
69869
|
-
const sourceSkillPath =
|
|
69870
|
-
if (!
|
|
70777
|
+
const sourceSkillPath = join33(__dirname3, "../skills/claudish-usage/SKILL.md");
|
|
70778
|
+
if (!existsSync25(sourceSkillPath)) {
|
|
69871
70779
|
console.error("\u274C Error: Claudish skill file not found in installation.");
|
|
69872
70780
|
console.error(` Expected at: ${sourceSkillPath}`);
|
|
69873
70781
|
console.error(`
|
|
@@ -69876,15 +70784,15 @@ async function initializeClaudishSkill() {
|
|
|
69876
70784
|
process.exit(1);
|
|
69877
70785
|
}
|
|
69878
70786
|
try {
|
|
69879
|
-
if (!
|
|
70787
|
+
if (!existsSync25(claudeDir)) {
|
|
69880
70788
|
mkdirSync14(claudeDir, { recursive: true });
|
|
69881
70789
|
console.log("\uD83D\uDCC1 Created .claude/ directory");
|
|
69882
70790
|
}
|
|
69883
|
-
if (!
|
|
70791
|
+
if (!existsSync25(skillsDir)) {
|
|
69884
70792
|
mkdirSync14(skillsDir, { recursive: true });
|
|
69885
70793
|
console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
|
|
69886
70794
|
}
|
|
69887
|
-
if (!
|
|
70795
|
+
if (!existsSync25(claudishSkillDir)) {
|
|
69888
70796
|
mkdirSync14(claudishSkillDir, { recursive: true });
|
|
69889
70797
|
console.log("\uD83D\uDCC1 Created .claude/skills/claudish-usage/ directory");
|
|
69890
70798
|
}
|
|
@@ -69956,8 +70864,8 @@ var init_cli = __esm(() => {
|
|
|
69956
70864
|
init_provider_definitions();
|
|
69957
70865
|
init_routing_rules();
|
|
69958
70866
|
init_provider_resolver();
|
|
69959
|
-
__filename3 =
|
|
69960
|
-
__dirname3 =
|
|
70867
|
+
__filename3 = fileURLToPath3(import.meta.url);
|
|
70868
|
+
__dirname3 = dirname11(__filename3);
|
|
69961
70869
|
});
|
|
69962
70870
|
|
|
69963
70871
|
// src/update-checker.ts
|
|
@@ -69969,33 +70877,33 @@ __export(exports_update_checker, {
|
|
|
69969
70877
|
clearCache: () => clearCache,
|
|
69970
70878
|
checkForUpdates: () => checkForUpdates
|
|
69971
70879
|
});
|
|
69972
|
-
import { existsSync as
|
|
70880
|
+
import { existsSync as existsSync26, mkdirSync as mkdirSync15, readFileSync as readFileSync26, unlinkSync as unlinkSync8, writeFileSync as writeFileSync18 } from "fs";
|
|
69973
70881
|
import { homedir as homedir30, platform as platform2, tmpdir } from "os";
|
|
69974
|
-
import { join as
|
|
70882
|
+
import { join as join34 } from "path";
|
|
69975
70883
|
function getCacheFilePath() {
|
|
69976
70884
|
let cacheDir;
|
|
69977
70885
|
if (isWindows) {
|
|
69978
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
69979
|
-
cacheDir =
|
|
70886
|
+
const localAppData = process.env.LOCALAPPDATA || join34(homedir30(), "AppData", "Local");
|
|
70887
|
+
cacheDir = join34(localAppData, "claudish");
|
|
69980
70888
|
} else {
|
|
69981
|
-
cacheDir =
|
|
70889
|
+
cacheDir = join34(homedir30(), ".cache", "claudish");
|
|
69982
70890
|
}
|
|
69983
70891
|
try {
|
|
69984
|
-
if (!
|
|
70892
|
+
if (!existsSync26(cacheDir)) {
|
|
69985
70893
|
mkdirSync15(cacheDir, { recursive: true });
|
|
69986
70894
|
}
|
|
69987
|
-
return
|
|
70895
|
+
return join34(cacheDir, "update-check.json");
|
|
69988
70896
|
} catch {
|
|
69989
|
-
return
|
|
70897
|
+
return join34(tmpdir(), "claudish-update-check.json");
|
|
69990
70898
|
}
|
|
69991
70899
|
}
|
|
69992
70900
|
function readCache() {
|
|
69993
70901
|
try {
|
|
69994
70902
|
const cachePath = getCacheFilePath();
|
|
69995
|
-
if (!
|
|
70903
|
+
if (!existsSync26(cachePath)) {
|
|
69996
70904
|
return null;
|
|
69997
70905
|
}
|
|
69998
|
-
const data = JSON.parse(
|
|
70906
|
+
const data = JSON.parse(readFileSync26(cachePath, "utf-8"));
|
|
69999
70907
|
return data;
|
|
70000
70908
|
} catch {
|
|
70001
70909
|
return null;
|
|
@@ -70008,7 +70916,7 @@ function writeCache(latestVersion) {
|
|
|
70008
70916
|
lastCheck: Date.now(),
|
|
70009
70917
|
latestVersion
|
|
70010
70918
|
};
|
|
70011
|
-
|
|
70919
|
+
writeFileSync18(cachePath, JSON.stringify(data), "utf-8");
|
|
70012
70920
|
} catch {}
|
|
70013
70921
|
}
|
|
70014
70922
|
function isCacheValid(cache2) {
|
|
@@ -70018,7 +70926,7 @@ function isCacheValid(cache2) {
|
|
|
70018
70926
|
function clearCache() {
|
|
70019
70927
|
try {
|
|
70020
70928
|
const cachePath = getCacheFilePath();
|
|
70021
|
-
if (
|
|
70929
|
+
if (existsSync26(cachePath)) {
|
|
70022
70930
|
unlinkSync8(cachePath);
|
|
70023
70931
|
}
|
|
70024
70932
|
} catch {}
|
|
@@ -70106,7 +71014,7 @@ var exports_update_command = {};
|
|
|
70106
71014
|
__export(exports_update_command, {
|
|
70107
71015
|
updateCommand: () => updateCommand
|
|
70108
71016
|
});
|
|
70109
|
-
import { execSync } from "child_process";
|
|
71017
|
+
import { execSync as execSync2 } from "child_process";
|
|
70110
71018
|
function detectInstallationMethod() {
|
|
70111
71019
|
const scriptPath = process.argv[1] || "";
|
|
70112
71020
|
if (scriptPath.includes("/opt/homebrew/") || scriptPath.includes("/usr/local/Cellar/")) {
|
|
@@ -70134,7 +71042,7 @@ function getUpdateCommand(method) {
|
|
|
70134
71042
|
}
|
|
70135
71043
|
async function executeUpdate(command) {
|
|
70136
71044
|
try {
|
|
70137
|
-
|
|
71045
|
+
execSync2(command, {
|
|
70138
71046
|
stdio: "inherit",
|
|
70139
71047
|
shell: process.platform === "win32" ? "cmd.exe" : "/bin/sh"
|
|
70140
71048
|
});
|
|
@@ -70271,7 +71179,7 @@ ${BOLD2}Unable to detect installation method.${RESET2}`);
|
|
|
70271
71179
|
}
|
|
70272
71180
|
function fetchLatestVersionViaNpm() {
|
|
70273
71181
|
try {
|
|
70274
|
-
const output =
|
|
71182
|
+
const output = execSync2("npm view claudish version", {
|
|
70275
71183
|
encoding: "utf-8",
|
|
70276
71184
|
timeout: 20000,
|
|
70277
71185
|
stdio: ["ignore", "pipe", "ignore"]
|
|
@@ -70903,15 +71811,15 @@ var init_local_liveness = __esm(() => {
|
|
|
70903
71811
|
});
|
|
70904
71812
|
|
|
70905
71813
|
// src/providers/probe-catalog.ts
|
|
70906
|
-
import { existsSync as
|
|
71814
|
+
import { existsSync as existsSync27, mkdirSync as mkdirSync16, readFileSync as readFileSync27, writeFileSync as writeFileSync19 } from "fs";
|
|
70907
71815
|
import { homedir as homedir31 } from "os";
|
|
70908
|
-
import { dirname as
|
|
71816
|
+
import { dirname as dirname12, join as join35 } from "path";
|
|
70909
71817
|
function readProbeModelsCache(path2 = PROBE_MODELS_CACHE_PATH) {
|
|
70910
|
-
if (!
|
|
71818
|
+
if (!existsSync27(path2))
|
|
70911
71819
|
return null;
|
|
70912
71820
|
let raw2;
|
|
70913
71821
|
try {
|
|
70914
|
-
raw2 = JSON.parse(
|
|
71822
|
+
raw2 = JSON.parse(readFileSync27(path2, "utf-8"));
|
|
70915
71823
|
} catch {
|
|
70916
71824
|
return null;
|
|
70917
71825
|
}
|
|
@@ -70920,8 +71828,8 @@ function readProbeModelsCache(path2 = PROBE_MODELS_CACHE_PATH) {
|
|
|
70920
71828
|
return raw2;
|
|
70921
71829
|
}
|
|
70922
71830
|
function writeProbeModelsCache(data, path2 = PROBE_MODELS_CACHE_PATH) {
|
|
70923
|
-
mkdirSync16(
|
|
70924
|
-
|
|
71831
|
+
mkdirSync16(dirname12(path2), { recursive: true });
|
|
71832
|
+
writeFileSync19(path2, JSON.stringify(data), "utf-8");
|
|
70925
71833
|
}
|
|
70926
71834
|
function isCacheFresh(data, ttlMs = CACHE_TTL_MS4) {
|
|
70927
71835
|
if (!data?.generatedAt)
|
|
@@ -71040,7 +71948,7 @@ function isValidResponse(raw2) {
|
|
|
71040
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;
|
|
71041
71949
|
var init_probe_catalog = __esm(() => {
|
|
71042
71950
|
CACHE_TTL_MS4 = 60 * 60 * 1000;
|
|
71043
|
-
PROBE_MODELS_CACHE_PATH =
|
|
71951
|
+
PROBE_MODELS_CACHE_PATH = join35(homedir31(), ".claudish", "probe-models.json");
|
|
71044
71952
|
});
|
|
71045
71953
|
|
|
71046
71954
|
// src/tui/constants.ts
|
|
@@ -77387,20 +78295,20 @@ __export(exports_claude_runner, {
|
|
|
77387
78295
|
MIN_AUTO_COMPACT_WINDOW: () => MIN_AUTO_COMPACT_WINDOW,
|
|
77388
78296
|
CLAUDE_CODE_DEFAULT_MAX_CONTEXT: () => CLAUDE_CODE_DEFAULT_MAX_CONTEXT
|
|
77389
78297
|
});
|
|
77390
|
-
import { spawn as
|
|
78298
|
+
import { spawn as spawn5 } from "child_process";
|
|
77391
78299
|
import {
|
|
77392
78300
|
closeSync as closeSync4,
|
|
77393
|
-
existsSync as
|
|
78301
|
+
existsSync as existsSync28,
|
|
77394
78302
|
mkdirSync as mkdirSync17,
|
|
77395
78303
|
openSync as openSync4,
|
|
77396
|
-
readFileSync as
|
|
78304
|
+
readFileSync as readFileSync28,
|
|
77397
78305
|
readdirSync as readdirSync6,
|
|
77398
78306
|
statSync as statSync5,
|
|
77399
78307
|
unlinkSync as unlinkSync9,
|
|
77400
|
-
writeFileSync as
|
|
78308
|
+
writeFileSync as writeFileSync20
|
|
77401
78309
|
} from "fs";
|
|
77402
78310
|
import { homedir as homedir32, tmpdir as tmpdir2 } from "os";
|
|
77403
|
-
import { dirname as
|
|
78311
|
+
import { dirname as dirname13, join as join36 } from "path";
|
|
77404
78312
|
import { isatty } from "tty";
|
|
77405
78313
|
function releaseTerminalIsolation() {
|
|
77406
78314
|
if (!restoreTerminal)
|
|
@@ -77435,14 +78343,14 @@ function isProxyAuthMode(config3) {
|
|
|
77435
78343
|
}
|
|
77436
78344
|
function managedSettingsPath() {
|
|
77437
78345
|
if (isWindows2()) {
|
|
77438
|
-
return
|
|
78346
|
+
return join36(process.env.PROGRAMDATA || "C:\\ProgramData", "ClaudeCode", "managed-settings.json");
|
|
77439
78347
|
}
|
|
77440
78348
|
if (process.platform === "darwin") {
|
|
77441
78349
|
return "/Library/Application Support/ClaudeCode/managed-settings.json";
|
|
77442
78350
|
}
|
|
77443
78351
|
return "/etc/claude-code/managed-settings.json";
|
|
77444
78352
|
}
|
|
77445
|
-
function managedSettingsForcesClaudeAi(readFile3 =
|
|
78353
|
+
function managedSettingsForcesClaudeAi(readFile3 = readFileSync28) {
|
|
77446
78354
|
try {
|
|
77447
78355
|
const raw2 = readFile3(managedSettingsPath(), "utf-8");
|
|
77448
78356
|
const parsed = JSON.parse(raw2);
|
|
@@ -77456,9 +78364,9 @@ function isWindows2() {
|
|
|
77456
78364
|
}
|
|
77457
78365
|
function createStatusLineScript(tokenFilePath) {
|
|
77458
78366
|
const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
|
|
77459
|
-
const claudishDir =
|
|
78367
|
+
const claudishDir = join36(homeDir, ".claudish");
|
|
77460
78368
|
const timestamp = Date.now();
|
|
77461
|
-
const scriptPath =
|
|
78369
|
+
const scriptPath = join36(claudishDir, `status-${timestamp}.js`);
|
|
77462
78370
|
const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
|
|
77463
78371
|
const script = `
|
|
77464
78372
|
const fs = require('fs');
|
|
@@ -77585,13 +78493,13 @@ process.stdin.on('end', () => {
|
|
|
77585
78493
|
}
|
|
77586
78494
|
});
|
|
77587
78495
|
`;
|
|
77588
|
-
|
|
78496
|
+
writeFileSync20(scriptPath, script, "utf-8");
|
|
77589
78497
|
return scriptPath;
|
|
77590
78498
|
}
|
|
77591
78499
|
function initializeTokenFile(tokenFilePath) {
|
|
77592
78500
|
try {
|
|
77593
|
-
mkdirSync17(
|
|
77594
|
-
|
|
78501
|
+
mkdirSync17(dirname13(tokenFilePath), { recursive: true });
|
|
78502
|
+
writeFileSync20(tokenFilePath, JSON.stringify({
|
|
77595
78503
|
input_tokens: 0,
|
|
77596
78504
|
output_tokens: 0,
|
|
77597
78505
|
total_tokens: 0,
|
|
@@ -77622,7 +78530,7 @@ function cleanupStaleTokenFiles(dir, now = Date.now(), maxAgeMs = STALE_TOKEN_FI
|
|
|
77622
78530
|
if (!name.startsWith("tokens-") || !name.endsWith(".json"))
|
|
77623
78531
|
continue;
|
|
77624
78532
|
scanned++;
|
|
77625
|
-
const full =
|
|
78533
|
+
const full = join36(dir, name);
|
|
77626
78534
|
try {
|
|
77627
78535
|
if (statSync5(full).mtimeMs >= cutoff)
|
|
77628
78536
|
continue;
|
|
@@ -77639,7 +78547,7 @@ function parseSettingsArg(value) {
|
|
|
77639
78547
|
if (value.trimStart().startsWith("{")) {
|
|
77640
78548
|
return JSON.parse(value);
|
|
77641
78549
|
}
|
|
77642
|
-
return JSON.parse(
|
|
78550
|
+
return JSON.parse(readFileSync28(value, "utf-8"));
|
|
77643
78551
|
}
|
|
77644
78552
|
function parseSettingsArgSafe(value) {
|
|
77645
78553
|
try {
|
|
@@ -77651,13 +78559,13 @@ function parseSettingsArgSafe(value) {
|
|
|
77651
78559
|
}
|
|
77652
78560
|
function userSettingsFileCandidates(cwd) {
|
|
77653
78561
|
return [
|
|
77654
|
-
|
|
77655
|
-
|
|
77656
|
-
|
|
78562
|
+
join36(homedir32(), ".claude", "settings.json"),
|
|
78563
|
+
join36(cwd, ".claude", "settings.json"),
|
|
78564
|
+
join36(cwd, ".claude", "settings.local.json")
|
|
77657
78565
|
];
|
|
77658
78566
|
}
|
|
77659
78567
|
function discoverUserStatusLineCommand(claudeArgs = [], cwd = process.cwd()) {
|
|
77660
|
-
const sources = userSettingsFileCandidates(cwd).filter((file2) =>
|
|
78568
|
+
const sources = userSettingsFileCandidates(cwd).filter((file2) => existsSync28(file2));
|
|
77661
78569
|
const idx = claudeArgs.indexOf("--settings");
|
|
77662
78570
|
const settingsArg = idx === -1 ? undefined : claudeArgs[idx + 1];
|
|
77663
78571
|
if (settingsArg)
|
|
@@ -77694,13 +78602,13 @@ function buildChainedStatusCommand(userCommand, claudishBody, claudishSegment) {
|
|
|
77694
78602
|
}
|
|
77695
78603
|
function createTempSettingsFile(_modelDisplay, port, proxyAuthMode, userStatusLineCommand) {
|
|
77696
78604
|
const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
|
|
77697
|
-
const claudishDir =
|
|
78605
|
+
const claudishDir = join36(homeDir, ".claudish");
|
|
77698
78606
|
try {
|
|
77699
78607
|
mkdirSync17(claudishDir, { recursive: true });
|
|
77700
78608
|
} catch {}
|
|
77701
78609
|
const timestamp = Date.now();
|
|
77702
|
-
const tempPath =
|
|
77703
|
-
const tokenFilePath =
|
|
78610
|
+
const tempPath = join36(claudishDir, `settings-${timestamp}.json`);
|
|
78611
|
+
const tokenFilePath = join36(claudishDir, `tokens-${port}.json`);
|
|
77704
78612
|
cleanupStaleTokenFiles(claudishDir);
|
|
77705
78613
|
initializeTokenFile(tokenFilePath);
|
|
77706
78614
|
let statusCommand;
|
|
@@ -77733,7 +78641,7 @@ function createTempSettingsFile(_modelDisplay, port, proxyAuthMode, userStatusLi
|
|
|
77733
78641
|
padding: 0
|
|
77734
78642
|
};
|
|
77735
78643
|
const settings = buildClaudishSettingsOverlay(statusLine, proxyAuthMode);
|
|
77736
|
-
|
|
78644
|
+
writeFileSync20(tempPath, JSON.stringify(settings, null, 2), "utf-8");
|
|
77737
78645
|
return { path: tempPath, statusLine, tokenFilePath };
|
|
77738
78646
|
}
|
|
77739
78647
|
function buildClaudishSettingsOverlay(statusLine, proxyAuthMode) {
|
|
@@ -77758,7 +78666,7 @@ function mergeUserSettingsIfPresent(config3, tempSettingsPath, statusLine, proxy
|
|
|
77758
78666
|
if (proxyAuthMode && !("forceLoginMethod" in userSettings)) {
|
|
77759
78667
|
userSettings.forceLoginMethod = "console";
|
|
77760
78668
|
}
|
|
77761
|
-
|
|
78669
|
+
writeFileSync20(tempSettingsPath, JSON.stringify(userSettings, null, 2), "utf-8");
|
|
77762
78670
|
} catch {
|
|
77763
78671
|
if (!config3.quiet) {
|
|
77764
78672
|
console.warn(`[claudish] Warning: could not merge user settings: ${userSettingsValue}`);
|
|
@@ -77951,7 +78859,7 @@ async function runClaudeWithProxy(config3, proxyUrl, onCleanup) {
|
|
|
77951
78859
|
console.error(`
|
|
77952
78860
|
Or set CLAUDE_PATH to your custom installation:`);
|
|
77953
78861
|
const home = homedir32();
|
|
77954
|
-
const localPath = isWindows2() ?
|
|
78862
|
+
const localPath = isWindows2() ? join36(home, ".claude", "local", "claude.exe") : join36(home, ".claude", "local", "claude");
|
|
77955
78863
|
console.error(` export CLAUDE_PATH=${localPath}`);
|
|
77956
78864
|
process.exit(1);
|
|
77957
78865
|
}
|
|
@@ -77975,7 +78883,7 @@ Or set CLAUDE_PATH to your custom installation:`);
|
|
|
77975
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.");
|
|
77976
78884
|
}
|
|
77977
78885
|
const stdio = ttyFd !== undefined ? [0, ttyFd, ttyFd] : "inherit";
|
|
77978
|
-
const proc =
|
|
78886
|
+
const proc = spawn5(spawnCommand, claudeArgs, {
|
|
77979
78887
|
env,
|
|
77980
78888
|
stdio,
|
|
77981
78889
|
shell: needsShell
|
|
@@ -78031,23 +78939,23 @@ function setupSignalHandlers(proc, tempSettingsPath, quiet, onCleanup) {
|
|
|
78031
78939
|
async function findClaudeBinary() {
|
|
78032
78940
|
const isWindows3 = process.platform === "win32";
|
|
78033
78941
|
if (process.env.CLAUDE_PATH) {
|
|
78034
|
-
if (
|
|
78942
|
+
if (existsSync28(process.env.CLAUDE_PATH)) {
|
|
78035
78943
|
return process.env.CLAUDE_PATH;
|
|
78036
78944
|
}
|
|
78037
78945
|
}
|
|
78038
78946
|
const home = homedir32();
|
|
78039
|
-
const localPath = isWindows3 ?
|
|
78040
|
-
if (
|
|
78947
|
+
const localPath = isWindows3 ? join36(home, ".claude", "local", "claude.exe") : join36(home, ".claude", "local", "claude");
|
|
78948
|
+
if (existsSync28(localPath)) {
|
|
78041
78949
|
return localPath;
|
|
78042
78950
|
}
|
|
78043
78951
|
if (isWindows3) {
|
|
78044
78952
|
const windowsPaths = [
|
|
78045
|
-
|
|
78046
|
-
|
|
78047
|
-
|
|
78953
|
+
join36(home, "AppData", "Roaming", "npm", "claude.cmd"),
|
|
78954
|
+
join36(home, ".npm-global", "claude.cmd"),
|
|
78955
|
+
join36(home, "node_modules", ".bin", "claude.cmd")
|
|
78048
78956
|
];
|
|
78049
78957
|
for (const path2 of windowsPaths) {
|
|
78050
|
-
if (
|
|
78958
|
+
if (existsSync28(path2)) {
|
|
78051
78959
|
return path2;
|
|
78052
78960
|
}
|
|
78053
78961
|
}
|
|
@@ -78055,21 +78963,21 @@ async function findClaudeBinary() {
|
|
|
78055
78963
|
const commonPaths = [
|
|
78056
78964
|
"/usr/local/bin/claude",
|
|
78057
78965
|
"/opt/homebrew/bin/claude",
|
|
78058
|
-
|
|
78059
|
-
|
|
78060
|
-
|
|
78966
|
+
join36(home, ".npm-global/bin/claude"),
|
|
78967
|
+
join36(home, ".local/bin/claude"),
|
|
78968
|
+
join36(home, "node_modules/.bin/claude"),
|
|
78061
78969
|
"/data/data/com.termux/files/usr/bin/claude",
|
|
78062
|
-
|
|
78970
|
+
join36(home, "../usr/bin/claude")
|
|
78063
78971
|
];
|
|
78064
78972
|
for (const path2 of commonPaths) {
|
|
78065
|
-
if (
|
|
78973
|
+
if (existsSync28(path2)) {
|
|
78066
78974
|
return path2;
|
|
78067
78975
|
}
|
|
78068
78976
|
}
|
|
78069
78977
|
}
|
|
78070
78978
|
try {
|
|
78071
78979
|
const shellCommand = isWindows3 ? "where claude" : "command -v claude";
|
|
78072
|
-
const proc =
|
|
78980
|
+
const proc = spawn5(shellCommand, [], {
|
|
78073
78981
|
stdio: "pipe",
|
|
78074
78982
|
shell: true
|
|
78075
78983
|
});
|
|
@@ -78121,18 +79029,18 @@ __export(exports_diag_output, {
|
|
|
78121
79029
|
NullDiagOutput: () => NullDiagOutput,
|
|
78122
79030
|
LogFileDiagOutput: () => LogFileDiagOutput
|
|
78123
79031
|
});
|
|
78124
|
-
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";
|
|
78125
79033
|
import { homedir as homedir33 } from "os";
|
|
78126
|
-
import { join as
|
|
79034
|
+
import { join as join37 } from "path";
|
|
78127
79035
|
function getClaudishDir() {
|
|
78128
|
-
const dir =
|
|
79036
|
+
const dir = join37(homedir33(), ".claudish");
|
|
78129
79037
|
try {
|
|
78130
79038
|
mkdirSync18(dir, { recursive: true });
|
|
78131
79039
|
} catch {}
|
|
78132
79040
|
return dir;
|
|
78133
79041
|
}
|
|
78134
79042
|
function getDiagLogPath() {
|
|
78135
|
-
return
|
|
79043
|
+
return join37(getClaudishDir(), `diag-${process.pid}.log`);
|
|
78136
79044
|
}
|
|
78137
79045
|
|
|
78138
79046
|
class LogFileDiagOutput {
|
|
@@ -78141,7 +79049,7 @@ class LogFileDiagOutput {
|
|
|
78141
79049
|
constructor() {
|
|
78142
79050
|
this.logPath = getDiagLogPath();
|
|
78143
79051
|
try {
|
|
78144
|
-
|
|
79052
|
+
writeFileSync21(this.logPath, `--- claudish diag session ${new Date().toISOString()} ---
|
|
78145
79053
|
`);
|
|
78146
79054
|
} catch {}
|
|
78147
79055
|
this.stream = createWriteStream3(this.logPath, { flags: "a" });
|
|
@@ -78328,279 +79236,6 @@ var init_catalog_warm = __esm(() => {
|
|
|
78328
79236
|
];
|
|
78329
79237
|
});
|
|
78330
79238
|
|
|
78331
|
-
// src/team-grid.ts
|
|
78332
|
-
var exports_team_grid = {};
|
|
78333
|
-
__export(exports_team_grid, {
|
|
78334
|
-
runWithGrid: () => runWithGrid
|
|
78335
|
-
});
|
|
78336
|
-
import { spawn as spawn5 } from "child_process";
|
|
78337
|
-
import { execSync as execSync2 } from "child_process";
|
|
78338
|
-
import { existsSync as existsSync28, readFileSync as readFileSync27, writeFileSync as writeFileSync21 } from "fs";
|
|
78339
|
-
import { connect as netConnect } from "net";
|
|
78340
|
-
import { dirname as dirname13, join as join36 } from "path";
|
|
78341
|
-
import { setTimeout as wait } from "timers/promises";
|
|
78342
|
-
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
78343
|
-
function resolveRouteInfo(modelId) {
|
|
78344
|
-
const parsed = parseModelSpec(modelId);
|
|
78345
|
-
if (parsed.isExplicitProvider) {
|
|
78346
|
-
return { chain: [parsed.provider], source: "direct" };
|
|
78347
|
-
}
|
|
78348
|
-
const local = loadLocalConfig();
|
|
78349
|
-
if (local?.routing && Object.keys(local.routing).length > 0) {
|
|
78350
|
-
const matched2 = matchRoutingRule(parsed.model, local.routing);
|
|
78351
|
-
if (matched2) {
|
|
78352
|
-
const routes = buildRoutingChain(matched2, parsed.model);
|
|
78353
|
-
const pattern = Object.keys(local.routing).find((k) => {
|
|
78354
|
-
if (k === parsed.model)
|
|
78355
|
-
return true;
|
|
78356
|
-
if (k.includes("*")) {
|
|
78357
|
-
const star = k.indexOf("*");
|
|
78358
|
-
return parsed.model.startsWith(k.slice(0, star)) && parsed.model.endsWith(k.slice(star + 1));
|
|
78359
|
-
}
|
|
78360
|
-
return false;
|
|
78361
|
-
});
|
|
78362
|
-
return {
|
|
78363
|
-
chain: routes.map((r) => r.displayName),
|
|
78364
|
-
source: "project routing",
|
|
78365
|
-
sourceDetail: pattern
|
|
78366
|
-
};
|
|
78367
|
-
}
|
|
78368
|
-
}
|
|
78369
|
-
const global_ = loadConfig();
|
|
78370
|
-
if (global_.routing && Object.keys(global_.routing).length > 0) {
|
|
78371
|
-
const matched2 = matchRoutingRule(parsed.model, global_.routing);
|
|
78372
|
-
if (matched2) {
|
|
78373
|
-
const routes = buildRoutingChain(matched2, parsed.model);
|
|
78374
|
-
const pattern = Object.keys(global_.routing).find((k) => {
|
|
78375
|
-
if (k === parsed.model)
|
|
78376
|
-
return true;
|
|
78377
|
-
if (k.includes("*")) {
|
|
78378
|
-
const star = k.indexOf("*");
|
|
78379
|
-
return parsed.model.startsWith(k.slice(0, star)) && parsed.model.endsWith(k.slice(star + 1));
|
|
78380
|
-
}
|
|
78381
|
-
return false;
|
|
78382
|
-
});
|
|
78383
|
-
return {
|
|
78384
|
-
chain: routes.map((r) => r.displayName),
|
|
78385
|
-
source: "user routing",
|
|
78386
|
-
sourceDetail: pattern
|
|
78387
|
-
};
|
|
78388
|
-
}
|
|
78389
|
-
}
|
|
78390
|
-
const merged = loadRoutingRules();
|
|
78391
|
-
const matched = matchRoutingRule(parsed.model, merged);
|
|
78392
|
-
if (matched) {
|
|
78393
|
-
const routes = buildRoutingChain(matched, parsed.model);
|
|
78394
|
-
return {
|
|
78395
|
-
chain: routes.map((r) => r.displayName),
|
|
78396
|
-
source: "auto"
|
|
78397
|
-
};
|
|
78398
|
-
}
|
|
78399
|
-
return {
|
|
78400
|
-
chain: [],
|
|
78401
|
-
source: "auto"
|
|
78402
|
-
};
|
|
78403
|
-
}
|
|
78404
|
-
function pickBannerColor(model, used) {
|
|
78405
|
-
let hash2 = 0;
|
|
78406
|
-
for (let i = 0;i < model.length; i++)
|
|
78407
|
-
hash2 = (hash2 << 5) - hash2 + model.charCodeAt(i) | 0;
|
|
78408
|
-
const start = Math.abs(hash2) % BANNER_BG_COLORS.length;
|
|
78409
|
-
let idx = start;
|
|
78410
|
-
if (used.size < BANNER_BG_COLORS.length) {
|
|
78411
|
-
while (used.has(idx))
|
|
78412
|
-
idx = (idx + 1) % BANNER_BG_COLORS.length;
|
|
78413
|
-
}
|
|
78414
|
-
used.add(idx);
|
|
78415
|
-
return BANNER_BG_COLORS[idx];
|
|
78416
|
-
}
|
|
78417
|
-
function buildPaneHeader(model, prompt, bg) {
|
|
78418
|
-
const route2 = resolveRouteInfo(model);
|
|
78419
|
-
const esc2 = (s) => s.replace(/'/g, "'\\''");
|
|
78420
|
-
const chainStr2 = route2.chain.join(" \u2192 ");
|
|
78421
|
-
const sourceLabel = route2.sourceDetail ? `${route2.source}: ${route2.sourceDetail}` : route2.source;
|
|
78422
|
-
const lines = [];
|
|
78423
|
-
lines.push(`printf '\\033[1;97;${bg}m %s \\033[0m\\n' '${esc2(model)}';`);
|
|
78424
|
-
lines.push(`printf '\\033[2m route: ${esc2(chainStr2)} (${esc2(sourceLabel)})\\033[0m\\n' ;`);
|
|
78425
|
-
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';`);
|
|
78426
|
-
const promptForShell = esc2(prompt).replace(/\n/g, "\\n");
|
|
78427
|
-
lines.push(`printf '%b\\n' '${promptForShell}' | fold -s -w 78 | sed 's/^/ /';`);
|
|
78428
|
-
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';`);
|
|
78429
|
-
return lines.join(" ");
|
|
78430
|
-
}
|
|
78431
|
-
function findMagmuxBinary() {
|
|
78432
|
-
const thisFile = fileURLToPath3(import.meta.url);
|
|
78433
|
-
const thisDir = dirname13(thisFile);
|
|
78434
|
-
const pkgRoot = join36(thisDir, "..");
|
|
78435
|
-
const platform3 = process.platform;
|
|
78436
|
-
const arch = process.arch;
|
|
78437
|
-
const bundledMagmux = join36(pkgRoot, "native", `magmux-${platform3}-${arch}`);
|
|
78438
|
-
if (existsSync28(bundledMagmux))
|
|
78439
|
-
return bundledMagmux;
|
|
78440
|
-
try {
|
|
78441
|
-
const pkgName = `@claudish/magmux-${platform3}-${arch}`;
|
|
78442
|
-
let searchDir = pkgRoot;
|
|
78443
|
-
for (let i = 0;i < 5; i++) {
|
|
78444
|
-
const candidate = join36(searchDir, "node_modules", pkgName, "bin", "magmux");
|
|
78445
|
-
if (existsSync28(candidate))
|
|
78446
|
-
return candidate;
|
|
78447
|
-
const parent = dirname13(searchDir);
|
|
78448
|
-
if (parent === searchDir)
|
|
78449
|
-
break;
|
|
78450
|
-
searchDir = parent;
|
|
78451
|
-
}
|
|
78452
|
-
} catch {}
|
|
78453
|
-
try {
|
|
78454
|
-
const result = execSync2("which magmux", { encoding: "utf-8" }).trim();
|
|
78455
|
-
if (result)
|
|
78456
|
-
return result;
|
|
78457
|
-
} catch {}
|
|
78458
|
-
throw new Error(`magmux not found. Install it:
|
|
78459
|
-
brew install MadAppGang/tap/magmux`);
|
|
78460
|
-
}
|
|
78461
|
-
async function subscribeToMagmux(sockPath, onEvent) {
|
|
78462
|
-
let client = null;
|
|
78463
|
-
for (let attempt = 0;attempt < 40; attempt++) {
|
|
78464
|
-
if (existsSync28(sockPath)) {
|
|
78465
|
-
try {
|
|
78466
|
-
client = await new Promise((resolve5, reject) => {
|
|
78467
|
-
const s = netConnect(sockPath);
|
|
78468
|
-
s.once("connect", () => resolve5(s));
|
|
78469
|
-
s.once("error", reject);
|
|
78470
|
-
});
|
|
78471
|
-
break;
|
|
78472
|
-
} catch {}
|
|
78473
|
-
}
|
|
78474
|
-
await wait(50);
|
|
78475
|
-
}
|
|
78476
|
-
if (!client) {
|
|
78477
|
-
return { results: null, client: null };
|
|
78478
|
-
}
|
|
78479
|
-
return await new Promise((resolve5) => {
|
|
78480
|
-
let buf = "";
|
|
78481
|
-
let finalResults = null;
|
|
78482
|
-
client.on("data", (chunk) => {
|
|
78483
|
-
buf += chunk.toString("utf-8");
|
|
78484
|
-
let nl = buf.indexOf(`
|
|
78485
|
-
`);
|
|
78486
|
-
while (nl >= 0) {
|
|
78487
|
-
const line = buf.slice(0, nl).trim();
|
|
78488
|
-
buf = buf.slice(nl + 1);
|
|
78489
|
-
nl = buf.indexOf(`
|
|
78490
|
-
`);
|
|
78491
|
-
if (!line)
|
|
78492
|
-
continue;
|
|
78493
|
-
try {
|
|
78494
|
-
const evt = JSON.parse(line);
|
|
78495
|
-
onEvent?.(evt);
|
|
78496
|
-
if (evt.type === "results") {
|
|
78497
|
-
finalResults = evt;
|
|
78498
|
-
}
|
|
78499
|
-
} catch {}
|
|
78500
|
-
}
|
|
78501
|
-
});
|
|
78502
|
-
const done = () => resolve5({ results: finalResults, client });
|
|
78503
|
-
client.once("end", done);
|
|
78504
|
-
client.once("close", done);
|
|
78505
|
-
client.once("error", done);
|
|
78506
|
-
});
|
|
78507
|
-
}
|
|
78508
|
-
function buildTeamStatus(manifest, startedAt, results) {
|
|
78509
|
-
const anonIds = Object.keys(manifest.models);
|
|
78510
|
-
const models = {};
|
|
78511
|
-
for (let i = 0;i < anonIds.length; i++) {
|
|
78512
|
-
const anonId = anonIds[i];
|
|
78513
|
-
const result = results?.find((r) => r.pane === i);
|
|
78514
|
-
if (!result) {
|
|
78515
|
-
models[anonId] = {
|
|
78516
|
-
state: "TIMEOUT",
|
|
78517
|
-
exitCode: null,
|
|
78518
|
-
startedAt,
|
|
78519
|
-
completedAt: null,
|
|
78520
|
-
outputSize: 0
|
|
78521
|
-
};
|
|
78522
|
-
continue;
|
|
78523
|
-
}
|
|
78524
|
-
let state;
|
|
78525
|
-
switch (result.state) {
|
|
78526
|
-
case "completed":
|
|
78527
|
-
case "awaiting_input":
|
|
78528
|
-
state = "COMPLETED";
|
|
78529
|
-
break;
|
|
78530
|
-
case "failed":
|
|
78531
|
-
state = "FAILED";
|
|
78532
|
-
break;
|
|
78533
|
-
default:
|
|
78534
|
-
state = "TIMEOUT";
|
|
78535
|
-
}
|
|
78536
|
-
models[anonId] = {
|
|
78537
|
-
state,
|
|
78538
|
-
exitCode: result.exitCode,
|
|
78539
|
-
startedAt: result.startedAt ?? startedAt,
|
|
78540
|
-
completedAt: result.completedAt ?? new Date().toISOString(),
|
|
78541
|
-
outputSize: result.response?.length ?? 0
|
|
78542
|
-
};
|
|
78543
|
-
}
|
|
78544
|
-
return { startedAt, models };
|
|
78545
|
-
}
|
|
78546
|
-
async function runWithGrid(sessionPath, models, input, opts) {
|
|
78547
|
-
const mode = opts?.mode ?? "default";
|
|
78548
|
-
const keep = opts?.keep ?? false;
|
|
78549
|
-
const manifest = setupSession(sessionPath, models, input);
|
|
78550
|
-
const startedAt = new Date().toISOString();
|
|
78551
|
-
const gridfilePath = join36(sessionPath, "gridfile.txt");
|
|
78552
|
-
const prompt = readFileSync27(join36(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
|
|
78553
|
-
const rawPrompt = readFileSync27(join36(sessionPath, "input.md"), "utf-8");
|
|
78554
|
-
const usedBannerColors = new Set;
|
|
78555
|
-
const gridLines = Object.entries(manifest.models).map(([anonId]) => {
|
|
78556
|
-
const model = manifest.models[anonId].model;
|
|
78557
|
-
if (mode === "interactive") {
|
|
78558
|
-
return `claudish --model ${model} -i --dangerously-skip-permissions '${prompt}'`;
|
|
78559
|
-
}
|
|
78560
|
-
const bg = pickBannerColor(model, usedBannerColors);
|
|
78561
|
-
const header = buildPaneHeader(model, rawPrompt, bg);
|
|
78562
|
-
return `${header} claudish --model ${model} -y --quiet '${prompt}'`;
|
|
78563
|
-
});
|
|
78564
|
-
writeFileSync21(gridfilePath, `${gridLines.join(`
|
|
78565
|
-
`)}
|
|
78566
|
-
`, "utf-8");
|
|
78567
|
-
const magmuxPath = findMagmuxBinary();
|
|
78568
|
-
const spawnArgs = ["-g", gridfilePath];
|
|
78569
|
-
if (!keep && mode === "default") {
|
|
78570
|
-
spawnArgs.push("-w");
|
|
78571
|
-
}
|
|
78572
|
-
const proc = spawn5(magmuxPath, spawnArgs, {
|
|
78573
|
-
stdio: "inherit",
|
|
78574
|
-
env: { ...process.env }
|
|
78575
|
-
});
|
|
78576
|
-
const sockPath = `/tmp/magmux-${proc.pid}.sock`;
|
|
78577
|
-
const subscription = subscribeToMagmux(sockPath);
|
|
78578
|
-
const procExit = new Promise((resolve5) => {
|
|
78579
|
-
proc.on("exit", () => resolve5());
|
|
78580
|
-
proc.on("error", () => resolve5());
|
|
78581
|
-
});
|
|
78582
|
-
const [{ results }] = await Promise.all([subscription, procExit]);
|
|
78583
|
-
const status = buildTeamStatus(manifest, startedAt, results?.panes ?? null);
|
|
78584
|
-
const statusPath = join36(sessionPath, "status.json");
|
|
78585
|
-
writeFileSync21(statusPath, JSON.stringify(status, null, 2), "utf-8");
|
|
78586
|
-
return status;
|
|
78587
|
-
}
|
|
78588
|
-
var BANNER_BG_COLORS;
|
|
78589
|
-
var init_team_grid = __esm(() => {
|
|
78590
|
-
init_profile_config();
|
|
78591
|
-
init_model_parser();
|
|
78592
|
-
init_routing_rules();
|
|
78593
|
-
init_team_orchestrator();
|
|
78594
|
-
BANNER_BG_COLORS = [
|
|
78595
|
-
"48;2;40;90;180",
|
|
78596
|
-
"48;2;140;60;160",
|
|
78597
|
-
"48;2;30;130;100",
|
|
78598
|
-
"48;2;160;80;40",
|
|
78599
|
-
"48;2;60;120;60",
|
|
78600
|
-
"48;2;160;50;70"
|
|
78601
|
-
];
|
|
78602
|
-
});
|
|
78603
|
-
|
|
78604
79239
|
// src/tui/viz/text.ts
|
|
78605
79240
|
function columns(n, fn, arg = "width") {
|
|
78606
79241
|
if (!Number.isFinite(n))
|
|
@@ -79003,7 +79638,7 @@ __export(exports_session_discovery, {
|
|
|
79003
79638
|
import { execFile, execFileSync as execFileSync2 } from "child_process";
|
|
79004
79639
|
import { closeSync as closeSync5, openSync as openSync5, readSync, readdirSync as readdirSync7, statSync as statSync6 } from "fs";
|
|
79005
79640
|
import { homedir as homedir34 } from "os";
|
|
79006
|
-
import { basename, join as
|
|
79641
|
+
import { basename, join as join38 } from "path";
|
|
79007
79642
|
function slugForPath(absPath) {
|
|
79008
79643
|
return absPath.replace(/[/.]/g, "-");
|
|
79009
79644
|
}
|
|
@@ -79052,7 +79687,7 @@ function projectDirs() {
|
|
|
79052
79687
|
}
|
|
79053
79688
|
}
|
|
79054
79689
|
function sessionsIn(dirName) {
|
|
79055
|
-
const dir =
|
|
79690
|
+
const dir = join38(PROJECTS_DIR, dirName);
|
|
79056
79691
|
let names;
|
|
79057
79692
|
try {
|
|
79058
79693
|
names = readdirSync7(dir).filter((n) => n.endsWith(".jsonl"));
|
|
@@ -79061,7 +79696,7 @@ function sessionsIn(dirName) {
|
|
|
79061
79696
|
}
|
|
79062
79697
|
const rows = [];
|
|
79063
79698
|
for (const n of names) {
|
|
79064
|
-
const file2 =
|
|
79699
|
+
const file2 = join38(dir, n);
|
|
79065
79700
|
try {
|
|
79066
79701
|
const st = statSync6(file2);
|
|
79067
79702
|
if (st.size === 0)
|
|
@@ -79420,7 +80055,7 @@ function findLatestSessionId(cwd = process.cwd(), sinceMs = 0) {
|
|
|
79420
80055
|
}
|
|
79421
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;
|
|
79422
80057
|
var init_session_discovery = __esm(() => {
|
|
79423
|
-
PROJECTS_DIR =
|
|
80058
|
+
PROJECTS_DIR = join38(homedir34(), ".claude", "projects");
|
|
79424
80059
|
HEAD_BYTES = 64 * 1024;
|
|
79425
80060
|
TAIL_BYTES = 128 * 1024;
|
|
79426
80061
|
HARNESS_ENVELOPES = [
|
|
@@ -81112,22 +81747,26 @@ __export(exports_session_stats, {
|
|
|
81112
81747
|
readSessionStats: () => readSessionStats,
|
|
81113
81748
|
computeSavings: () => computeSavings
|
|
81114
81749
|
});
|
|
81115
|
-
import { readFileSync as
|
|
81750
|
+
import { readFileSync as readFileSync29 } from "fs";
|
|
81116
81751
|
import { homedir as homedir35 } from "os";
|
|
81117
|
-
import { join as
|
|
81752
|
+
import { join as join39 } from "path";
|
|
81118
81753
|
function tokenFilePath(port) {
|
|
81119
|
-
return process.env.CLAUDISH_TOKEN_FILE ||
|
|
81754
|
+
return process.env.CLAUDISH_TOKEN_FILE || join39(homedir35(), ".claudish", `tokens-${port}.json`);
|
|
81120
81755
|
}
|
|
81121
|
-
function readSessionStats(port) {
|
|
81756
|
+
function readSessionStats(port, opts) {
|
|
81122
81757
|
let raw2;
|
|
81123
81758
|
try {
|
|
81124
|
-
raw2 = JSON.parse(
|
|
81759
|
+
raw2 = JSON.parse(readFileSync29(tokenFilePath(port), "utf-8"));
|
|
81125
81760
|
} catch {
|
|
81126
81761
|
return null;
|
|
81127
81762
|
}
|
|
81128
81763
|
if (!raw2 || typeof raw2 !== "object")
|
|
81129
81764
|
return null;
|
|
81130
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;
|
|
81131
81770
|
const inputTokens = num(d.input_tokens);
|
|
81132
81771
|
const outputTokens = num(d.output_tokens);
|
|
81133
81772
|
if (inputTokens <= 0 && outputTokens <= 0)
|
|
@@ -81457,8 +82096,8 @@ var init_session_summary = __esm(() => {
|
|
|
81457
82096
|
init_op_source();
|
|
81458
82097
|
init_startup_trace();
|
|
81459
82098
|
var import_dotenv3 = __toESM(require_main(), 1);
|
|
81460
|
-
import { existsSync as existsSync29, readFileSync as
|
|
81461
|
-
import { join as
|
|
82099
|
+
import { existsSync as existsSync29, readFileSync as readFileSync30 } from "fs";
|
|
82100
|
+
import { join as join40, resolve as resolve5 } from "path";
|
|
81462
82101
|
import_dotenv3.config({ quiet: true });
|
|
81463
82102
|
function classifyStartupKind() {
|
|
81464
82103
|
const argv = process.argv.slice(2);
|
|
@@ -81592,6 +82231,7 @@ var isConfigCommand = firstPositional === "config";
|
|
|
81592
82231
|
var isServeCommand = firstPositional === "serve";
|
|
81593
82232
|
var isProvidersCommand = firstPositional === "providers";
|
|
81594
82233
|
var isBehaviorCommand = firstPositional === "behavior";
|
|
82234
|
+
var isTeamCommand = firstPositional === "team";
|
|
81595
82235
|
var isLoginCommand = firstPositional === "login";
|
|
81596
82236
|
var isLogoutCommand = firstPositional === "logout";
|
|
81597
82237
|
var isQuotaCommand = firstPositional === "quota" || firstPositional === "usage";
|
|
@@ -81617,6 +82257,12 @@ if (isMcpMode) {
|
|
|
81617
82257
|
console.error(`[claudish behavior] ${e instanceof Error ? e.message : String(e)}`);
|
|
81618
82258
|
process.exit(1);
|
|
81619
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
|
+
}));
|
|
81620
82266
|
} else if (isProvidersCommand) {
|
|
81621
82267
|
const json2 = args.includes("--json");
|
|
81622
82268
|
Promise.resolve().then(() => (init_providers_command(), exports_providers_command)).then((m) => m.providersCommand({ json: json2 }).catch((e) => {
|
|
@@ -81701,14 +82347,14 @@ async function runCli() {
|
|
|
81701
82347
|
if (cliConfig.team && cliConfig.team.length > 0) {
|
|
81702
82348
|
let prompt = cliConfig.claudeArgs.join(" ");
|
|
81703
82349
|
if (cliConfig.inputFile) {
|
|
81704
|
-
prompt =
|
|
82350
|
+
prompt = readFileSync30(cliConfig.inputFile, "utf-8");
|
|
81705
82351
|
}
|
|
81706
82352
|
if (!prompt.trim()) {
|
|
81707
82353
|
console.error("Error: --team requires a prompt (positional args or -f <file>)");
|
|
81708
82354
|
process.exit(1);
|
|
81709
82355
|
}
|
|
81710
82356
|
const mode = cliConfig.teamMode ?? "default";
|
|
81711
|
-
const sessionPath =
|
|
82357
|
+
const sessionPath = join40(process.cwd(), `.claudish-team-${Date.now()}`);
|
|
81712
82358
|
if (mode === "json") {
|
|
81713
82359
|
const { setupSession: setupSession2, runModels: runModels2 } = await Promise.resolve().then(() => (init_team_orchestrator(), exports_team_orchestrator));
|
|
81714
82360
|
setupSession2(sessionPath, cliConfig.team, prompt);
|
|
@@ -81718,9 +82364,9 @@ async function runCli() {
|
|
|
81718
82364
|
});
|
|
81719
82365
|
const result = { ...status2, responses: {} };
|
|
81720
82366
|
for (const anonId of Object.keys(status2.models)) {
|
|
81721
|
-
const responsePath =
|
|
82367
|
+
const responsePath = join40(sessionPath, `response-${anonId}.md`);
|
|
81722
82368
|
try {
|
|
81723
|
-
const raw2 =
|
|
82369
|
+
const raw2 = readFileSync30(responsePath, "utf-8").trim();
|
|
81724
82370
|
try {
|
|
81725
82371
|
result.responses[anonId] = JSON.parse(raw2);
|
|
81726
82372
|
} catch {
|