claudish 10.6.2 → 10.7.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/AI_AGENT_GUIDE.md +13 -5
- package/dist/index.js +742 -479
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -112,9 +112,25 @@ import { realpathSync } from "fs";
|
|
|
112
112
|
function isPaneShellManagedKey(key) {
|
|
113
113
|
return key.startsWith("MAGMUX_") || PANE_SHELL_MANAGED_KEYS.includes(key);
|
|
114
114
|
}
|
|
115
|
-
function
|
|
115
|
+
function inMcpSession(env = process.env) {
|
|
116
116
|
return env[ENV.CLAUDISH_PANE_CHILD] === "1";
|
|
117
117
|
}
|
|
118
|
+
function isPaneChild(env = process.env) {
|
|
119
|
+
return inMcpSession(env) && Boolean(env[ENV.CLAUDISH_PANE_CWD]);
|
|
120
|
+
}
|
|
121
|
+
function nestedLaunchRefusal(env = process.env) {
|
|
122
|
+
if (!inMcpSession(env) || isPaneChild(env))
|
|
123
|
+
return null;
|
|
124
|
+
return NESTED_SESSION_REFUSAL;
|
|
125
|
+
}
|
|
126
|
+
function assertNotNested(env = process.env) {
|
|
127
|
+
const reason = nestedLaunchRefusal(env);
|
|
128
|
+
if (reason === null)
|
|
129
|
+
return;
|
|
130
|
+
process.stderr.write(`claudish: nested session refused: ${reason}
|
|
131
|
+
`);
|
|
132
|
+
process.exit(PANE_CHILD_REFUSED_EXIT);
|
|
133
|
+
}
|
|
118
134
|
function applyPaneEnvSnapshot(env) {
|
|
119
135
|
const raw = env[ENV.CLAUDISH_PANE_ENV];
|
|
120
136
|
if (raw === undefined)
|
|
@@ -207,14 +223,10 @@ function assertPaneChildInteractive(config, env = process.env) {
|
|
|
207
223
|
if (reason !== null)
|
|
208
224
|
refuse(reason);
|
|
209
225
|
}
|
|
210
|
-
var PANE_CHILD_REFUSED_EXIT = 64,
|
|
226
|
+
var PANE_CHILD_REFUSED_EXIT = 64, PANE_LAUNCH_VARS, PANE_SHELL_MANAGED_KEYS, NESTED_SESSION_REFUSAL = "already inside a session started by the claudish MCP server; one level of nesting is the limit", processCwdOps, bootNotes, bootstrapped = false;
|
|
211
227
|
var init_child_env = __esm(() => {
|
|
212
228
|
init_config();
|
|
213
|
-
|
|
214
|
-
ENV.CLAUDISH_PANE_CHILD,
|
|
215
|
-
ENV.CLAUDISH_PANE_ENV,
|
|
216
|
-
ENV.CLAUDISH_PANE_CWD
|
|
217
|
-
];
|
|
229
|
+
PANE_LAUNCH_VARS = [ENV.CLAUDISH_PANE_ENV, ENV.CLAUDISH_PANE_CWD];
|
|
218
230
|
PANE_SHELL_MANAGED_KEYS = [
|
|
219
231
|
"COLUMNS",
|
|
220
232
|
"LINES",
|
|
@@ -889,7 +901,7 @@ var init_onepassword_config = __esm(() => {
|
|
|
889
901
|
});
|
|
890
902
|
|
|
891
903
|
// src/version.ts
|
|
892
|
-
var VERSION = "10.
|
|
904
|
+
var VERSION = "10.7.0";
|
|
893
905
|
|
|
894
906
|
// src/logger.ts
|
|
895
907
|
import { appendFile, existsSync as existsSync2, mkdirSync, readdirSync, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
@@ -18816,6 +18828,10 @@ function lookupModelReasoningStatus(modelId, cachePath) {
|
|
|
18816
18828
|
const entry = findCacheEntry(modelId, cachePath);
|
|
18817
18829
|
return entry ? reasoningStatusOf(entry) : undefined;
|
|
18818
18830
|
}
|
|
18831
|
+
function lookupModelMaxOutputTokens(modelId, cachePath) {
|
|
18832
|
+
const value = findCacheEntry(modelId, cachePath)?.maxOutputTokens;
|
|
18833
|
+
return typeof value === "number" && value > 0 ? value : undefined;
|
|
18834
|
+
}
|
|
18819
18835
|
function lookupRouteReasoningMode(modelId, provider, cachePath) {
|
|
18820
18836
|
return findCacheEntry(modelId, cachePath)?.aggregators?.find((aggregator) => catalogRouteMatchesProvider(aggregator.route, provider))?.reasoning?.mode;
|
|
18821
18837
|
}
|
|
@@ -20933,6 +20949,7 @@ ${merged}`;
|
|
|
20933
20949
|
var AnthropicAPIFormat;
|
|
20934
20950
|
var init_anthropic_api_format = __esm(() => {
|
|
20935
20951
|
init_base_api_format();
|
|
20952
|
+
init_model_catalog();
|
|
20936
20953
|
AnthropicAPIFormat = class AnthropicAPIFormat extends BaseAPIFormat {
|
|
20937
20954
|
constructor(modelId, _providerName) {
|
|
20938
20955
|
super(modelId);
|
|
@@ -20973,14 +20990,24 @@ var init_anthropic_api_format = __esm(() => {
|
|
|
20973
20990
|
convertTools(claudeRequest, _summarize) {
|
|
20974
20991
|
return claudeRequest.tools || [];
|
|
20975
20992
|
}
|
|
20993
|
+
outputLimitFor(claudeRequest) {
|
|
20994
|
+
const inbound = claudeRequest?.max_tokens;
|
|
20995
|
+
if (typeof inbound === "number")
|
|
20996
|
+
return inbound;
|
|
20997
|
+
if (this.modelId.includes("@"))
|
|
20998
|
+
return;
|
|
20999
|
+
return lookupModelMaxOutputTokens(this.modelId);
|
|
21000
|
+
}
|
|
20976
21001
|
buildPayload(claudeRequest, messages, tools) {
|
|
20977
21002
|
const { messages: cleanMessages, hoisted } = hoistInlineSystem(messages);
|
|
20978
21003
|
const payload = {
|
|
20979
21004
|
model: this.modelId,
|
|
20980
21005
|
messages: cleanMessages,
|
|
20981
|
-
max_tokens: claudeRequest.max_tokens || 4096,
|
|
20982
21006
|
stream: true
|
|
20983
21007
|
};
|
|
21008
|
+
const maxTokens = this.outputLimitFor(claudeRequest);
|
|
21009
|
+
if (maxTokens !== undefined)
|
|
21010
|
+
payload.max_tokens = maxTokens;
|
|
20984
21011
|
const system = mergeSystem(claudeRequest.system, hoisted);
|
|
20985
21012
|
if (system !== undefined) {
|
|
20986
21013
|
payload.system = system;
|
|
@@ -31123,6 +31150,7 @@ function resolveConnection(provider, modelName, cachePath = ALL_MODELS_CACHE_PAT
|
|
|
31123
31150
|
wire: found.connection.wire,
|
|
31124
31151
|
profile,
|
|
31125
31152
|
generationId: cache.routeRegistry.generationId,
|
|
31153
|
+
...typeof found.entry.maxOutputTokens === "number" && found.entry.maxOutputTokens > 0 ? { maxOutputTokens: found.entry.maxOutputTokens } : {},
|
|
31126
31154
|
...ownerWire ? { ownerWire } : {}
|
|
31127
31155
|
}
|
|
31128
31156
|
};
|
|
@@ -32563,6 +32591,19 @@ function wireChoicesFromClaudeRequest(claudeRequest, pinnedEffort) {
|
|
|
32563
32591
|
maxTokens: typeof claudeRequest?.max_tokens === "number" ? claudeRequest.max_tokens : undefined
|
|
32564
32592
|
};
|
|
32565
32593
|
}
|
|
32594
|
+
function outputLimitToSend(wire, choices, result) {
|
|
32595
|
+
if (typeof choices.maxTokens === "number")
|
|
32596
|
+
return choices.maxTokens;
|
|
32597
|
+
if (!LIMIT_REQUIRED_APIS.has(wire.api))
|
|
32598
|
+
return;
|
|
32599
|
+
const ceiling = choices.catalogMaxOutputTokens;
|
|
32600
|
+
if (typeof ceiling === "number" && ceiling > 0) {
|
|
32601
|
+
result.notes.push(`request has no output limit: sent the catalog's maxOutputTokens ${ceiling}`);
|
|
32602
|
+
return ceiling;
|
|
32603
|
+
}
|
|
32604
|
+
result.notes.push("request has no output limit and the catalog publishes no maxOutputTokens: none sent");
|
|
32605
|
+
return;
|
|
32606
|
+
}
|
|
32566
32607
|
function shapeRequestFromWire(body, wire, choices, owner) {
|
|
32567
32608
|
const result = { headers: [], notes: [], borrowed: [] };
|
|
32568
32609
|
stripWireDecisions(body, wire.api);
|
|
@@ -32573,12 +32614,13 @@ function shapeRequestFromWire(body, wire, choices, owner) {
|
|
|
32573
32614
|
result.borrowed.push(path);
|
|
32574
32615
|
};
|
|
32575
32616
|
const sameApiOwner = owner && owner !== wire && owner.api === wire.api ? owner : undefined;
|
|
32617
|
+
const maxTokens = outputLimitToSend(wire, choices, result);
|
|
32576
32618
|
if (typeof wire.tokenParam === "string") {
|
|
32577
|
-
if (typeof
|
|
32578
|
-
body[wire.tokenParam] =
|
|
32619
|
+
if (typeof maxTokens === "number")
|
|
32620
|
+
body[wire.tokenParam] = maxTokens;
|
|
32579
32621
|
} else if (wire.api !== "gemini") {
|
|
32580
|
-
if (wire.tokenParam.status === "unknown" && sameApiOwner && typeof sameApiOwner.tokenParam === "string" && typeof
|
|
32581
|
-
borrow(`/${sameApiOwner.tokenParam}`,
|
|
32622
|
+
if (wire.tokenParam.status === "unknown" && sameApiOwner && typeof sameApiOwner.tokenParam === "string" && typeof maxTokens === "number") {
|
|
32623
|
+
borrow(`/${sameApiOwner.tokenParam}`, maxTokens);
|
|
32582
32624
|
result.notes.push(`tokenParam ${wire.tokenParam.status}: trying the owner's ${sameApiOwner.tokenParam}`);
|
|
32583
32625
|
} else {
|
|
32584
32626
|
result.notes.push(`tokenParam ${wire.tokenParam.status}: no output limit sent`);
|
|
@@ -32629,7 +32671,7 @@ function mergeWireHeaders(headers, extra) {
|
|
|
32629
32671
|
headers[key] = `${existing},${header.value}`;
|
|
32630
32672
|
}
|
|
32631
32673
|
}
|
|
32632
|
-
var WIRE_EFFORT_ORDER, WIRE_SPEEDS, TOKEN_LIMIT_FIELDS, DECISION_POINTERS;
|
|
32674
|
+
var WIRE_EFFORT_ORDER, WIRE_SPEEDS, TOKEN_LIMIT_FIELDS, DECISION_POINTERS, LIMIT_REQUIRED_APIS;
|
|
32633
32675
|
var init_wire_request = __esm(() => {
|
|
32634
32676
|
WIRE_EFFORT_ORDER = [
|
|
32635
32677
|
"none",
|
|
@@ -32661,6 +32703,7 @@ var init_wire_request = __esm(() => {
|
|
|
32661
32703
|
"/service_tier",
|
|
32662
32704
|
"/speed"
|
|
32663
32705
|
];
|
|
32706
|
+
LIMIT_REQUIRED_APIS = new Set(["anthropic-messages"]);
|
|
32664
32707
|
});
|
|
32665
32708
|
|
|
32666
32709
|
// src/providers/wire-markers.ts
|
|
@@ -32909,7 +32952,7 @@ var init_vision_proxy = __esm(() => {
|
|
|
32909
32952
|
init_catalog_query();
|
|
32910
32953
|
});
|
|
32911
32954
|
|
|
32912
|
-
// src/
|
|
32955
|
+
// src/mcp-session/home-dir.ts
|
|
32913
32956
|
import { homedir as homedir23 } from "os";
|
|
32914
32957
|
import { join as join23 } from "path";
|
|
32915
32958
|
function userHomeFrom(env, homedirFn = homedir23) {
|
|
@@ -33239,8 +33282,8 @@ class SessionEventRegistry {
|
|
|
33239
33282
|
}
|
|
33240
33283
|
var MISS_TTL_MS = 5000, MAX_MISSES = 5, IDLE_SWEEP_MS, sessionEvents;
|
|
33241
33284
|
var init_session_events = __esm(() => {
|
|
33242
|
-
init_home_dir();
|
|
33243
33285
|
init_logger();
|
|
33286
|
+
init_home_dir();
|
|
33244
33287
|
init_event_translator();
|
|
33245
33288
|
init_transcript_tailer();
|
|
33246
33289
|
IDLE_SWEEP_MS = 30 * 60 * 1000;
|
|
@@ -37469,6 +37512,7 @@ class ComposedHandler {
|
|
|
37469
37512
|
if (wire?.status === "known") {
|
|
37470
37513
|
const choices = {
|
|
37471
37514
|
...wireChoicesFromClaudeRequest(claudeRequest, this.options.effortOverride),
|
|
37515
|
+
catalogMaxOutputTokens: this.options.connection?.maxOutputTokens,
|
|
37472
37516
|
acceptServedModelChange: process.env.CLAUDISH_ACCEPT_SERVED_MODEL === "1"
|
|
37473
37517
|
};
|
|
37474
37518
|
const markers = wireMarkerContext.getStore();
|
|
@@ -43905,67 +43949,7 @@ var init_prehydrate = __esm(() => {
|
|
|
43905
43949
|
init_op_source();
|
|
43906
43950
|
});
|
|
43907
43951
|
|
|
43908
|
-
// src/
|
|
43909
|
-
import { appendFileSync as appendFileSync5 } from "fs";
|
|
43910
|
-
function traceEnabled() {
|
|
43911
|
-
return process.env[TRACE_ENV] === "1";
|
|
43912
|
-
}
|
|
43913
|
-
function emit(line) {
|
|
43914
|
-
const formatted = `[channel-trace] ${line}
|
|
43915
|
-
`;
|
|
43916
|
-
process.stderr.write(formatted);
|
|
43917
|
-
const filePath = process.env[TRACE_FILE_ENV];
|
|
43918
|
-
if (filePath) {
|
|
43919
|
-
try {
|
|
43920
|
-
appendFileSync5(filePath, formatted);
|
|
43921
|
-
} catch {}
|
|
43922
|
-
}
|
|
43923
|
-
}
|
|
43924
|
-
function wrapStateChange(fn) {
|
|
43925
|
-
if (!traceEnabled())
|
|
43926
|
-
return fn;
|
|
43927
|
-
return (sessionId, event) => {
|
|
43928
|
-
emit(`fired sid=${sessionId} type=${event.type} model=${event.model} elapsed=${event.elapsedSeconds}s`);
|
|
43929
|
-
try {
|
|
43930
|
-
fn(sessionId, event);
|
|
43931
|
-
emit(`callback returned sid=${sessionId} type=${event.type}`);
|
|
43932
|
-
} catch (err) {
|
|
43933
|
-
emit(`callback THREW sid=${sessionId} type=${event.type} err=${err?.message ?? err}`);
|
|
43934
|
-
throw err;
|
|
43935
|
-
}
|
|
43936
|
-
};
|
|
43937
|
-
}
|
|
43938
|
-
function watchNotificationResult(result, context) {
|
|
43939
|
-
if (!traceEnabled())
|
|
43940
|
-
return;
|
|
43941
|
-
if (result && typeof result.then === "function") {
|
|
43942
|
-
result.catch((err) => {
|
|
43943
|
-
emit(`notification REJECTED sid=${context.sessionId} type=${context.eventType} err=${err?.message ?? err}`);
|
|
43944
|
-
});
|
|
43945
|
-
}
|
|
43946
|
-
}
|
|
43947
|
-
function installWireTap() {
|
|
43948
|
-
if (!traceEnabled())
|
|
43949
|
-
return;
|
|
43950
|
-
if (wireTapInstalled)
|
|
43951
|
-
return;
|
|
43952
|
-
wireTapInstalled = true;
|
|
43953
|
-
const originalWrite = process.stdout.write.bind(process.stdout);
|
|
43954
|
-
process.stdout.write = (chunk, ...rest) => {
|
|
43955
|
-
try {
|
|
43956
|
-
const text = typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf-8");
|
|
43957
|
-
if (text.includes('"notifications/claude/channel"')) {
|
|
43958
|
-
emit(`WIRE-OUT ${text.trim()}`);
|
|
43959
|
-
}
|
|
43960
|
-
} catch {}
|
|
43961
|
-
return originalWrite(chunk, ...rest);
|
|
43962
|
-
};
|
|
43963
|
-
emit("wire tap installed");
|
|
43964
|
-
}
|
|
43965
|
-
var TRACE_ENV = "CLAUDISH_CHANNEL_TRACE", TRACE_FILE_ENV = "CLAUDISH_CHANNEL_TRACE_FILE", wireTapInstalled = false;
|
|
43966
|
-
var init_diagnostics = () => {};
|
|
43967
|
-
|
|
43968
|
-
// src/channel/scrollback-buffer.ts
|
|
43952
|
+
// src/mcp-session/scrollback-buffer.ts
|
|
43969
43953
|
class ScrollbackBuffer {
|
|
43970
43954
|
lines;
|
|
43971
43955
|
head;
|
|
@@ -44086,8 +44070,116 @@ var init_contract = __esm(() => {
|
|
|
44086
44070
|
};
|
|
44087
44071
|
});
|
|
44088
44072
|
|
|
44073
|
+
// src/pane/reason-detail.ts
|
|
44074
|
+
import { closeSync as closeSync6, fstatSync, openSync as openSync6, readSync as readSync2 } from "fs";
|
|
44075
|
+
function reasonDetail(input, upstreamRecords = []) {
|
|
44076
|
+
if (!isTerminalState(input.state) || input.state === "COMPLETED")
|
|
44077
|
+
return null;
|
|
44078
|
+
if (input.reason === "api_error") {
|
|
44079
|
+
const last = upstreamRecords.length ? upstreamRecords[upstreamRecords.length - 1] : undefined;
|
|
44080
|
+
const upstream = last === undefined ? null : upstreamMessage(last);
|
|
44081
|
+
if (upstream)
|
|
44082
|
+
return oneLine4(upstream);
|
|
44083
|
+
const child = firstLine(input.detail);
|
|
44084
|
+
return child ? oneLine4(apiErrorText(child)) : null;
|
|
44085
|
+
}
|
|
44086
|
+
const first = firstLine(input.detail);
|
|
44087
|
+
return first ? oneLine4(first) : null;
|
|
44088
|
+
}
|
|
44089
|
+
function upstreamRecordsFor(input, upstreamLogPath) {
|
|
44090
|
+
if (!upstreamLogPath || input.reason !== "api_error" || !isTerminalState(input.state))
|
|
44091
|
+
return [];
|
|
44092
|
+
return readTailLines(upstreamLogPath, UPSTREAM_TAIL_BYTES);
|
|
44093
|
+
}
|
|
44094
|
+
function firstLine(text) {
|
|
44095
|
+
if (!text)
|
|
44096
|
+
return null;
|
|
44097
|
+
const line = text.split(/\r?\n/).find((l) => l.trim().length > 0);
|
|
44098
|
+
return line ? line.trim() : null;
|
|
44099
|
+
}
|
|
44100
|
+
function oneLine4(text) {
|
|
44101
|
+
const flat = text.replace(/\s+/g, " ").trim();
|
|
44102
|
+
if (!flat)
|
|
44103
|
+
return null;
|
|
44104
|
+
return flat.length > REASON_DETAIL_MAX_CHARS ? `${flat.slice(0, REASON_DETAIL_MAX_CHARS - 1).trimEnd()}\u2026` : flat;
|
|
44105
|
+
}
|
|
44106
|
+
function apiErrorText(detail) {
|
|
44107
|
+
const text = detail.split(" \xB7 ")[0].replace(/^The turn ended in an API error(?:\s*\(status \d+\))?:\s*/i, "").replace(/^API Error:?\s*(?:\d{3}\b)?\s*/i, "").trim();
|
|
44108
|
+
if (/^[[{]/.test(text))
|
|
44109
|
+
return messageOfJsonText(text) ?? "";
|
|
44110
|
+
return text;
|
|
44111
|
+
}
|
|
44112
|
+
function upstreamMessage(record) {
|
|
44113
|
+
let parsed;
|
|
44114
|
+
try {
|
|
44115
|
+
parsed = JSON.parse(record);
|
|
44116
|
+
} catch {
|
|
44117
|
+
return null;
|
|
44118
|
+
}
|
|
44119
|
+
if (!isObject3(parsed))
|
|
44120
|
+
return null;
|
|
44121
|
+
const body = parsed.body;
|
|
44122
|
+
if (typeof body === "string")
|
|
44123
|
+
return messageOfJsonText(body);
|
|
44124
|
+
return messageOf(body);
|
|
44125
|
+
}
|
|
44126
|
+
function messageOfJsonText(text) {
|
|
44127
|
+
try {
|
|
44128
|
+
return messageOf(JSON.parse(text));
|
|
44129
|
+
} catch {
|
|
44130
|
+
const m = /"error"\s*:\s*\{[^{}]*?"message"\s*:\s*"((?:[^"\\]|\\.)*)"/.exec(text);
|
|
44131
|
+
if (!m)
|
|
44132
|
+
return null;
|
|
44133
|
+
try {
|
|
44134
|
+
return nonEmpty2(JSON.parse(`"${m[1]}"`));
|
|
44135
|
+
} catch {
|
|
44136
|
+
return null;
|
|
44137
|
+
}
|
|
44138
|
+
}
|
|
44139
|
+
}
|
|
44140
|
+
function messageOf(value) {
|
|
44141
|
+
const v = Array.isArray(value) ? value[0] : value;
|
|
44142
|
+
if (!isObject3(v) || !isObject3(v.error))
|
|
44143
|
+
return null;
|
|
44144
|
+
return nonEmpty2(v.error.message);
|
|
44145
|
+
}
|
|
44146
|
+
function nonEmpty2(v) {
|
|
44147
|
+
return typeof v === "string" && v.trim().length > 0 ? v : null;
|
|
44148
|
+
}
|
|
44149
|
+
function isObject3(v) {
|
|
44150
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
44151
|
+
}
|
|
44152
|
+
function readTailLines(path, maxBytes) {
|
|
44153
|
+
let fd = null;
|
|
44154
|
+
try {
|
|
44155
|
+
fd = openSync6(path, "r");
|
|
44156
|
+
const size = fstatSync(fd).size;
|
|
44157
|
+
const start = Math.max(0, size - maxBytes);
|
|
44158
|
+
const buf = Buffer.alloc(size - start);
|
|
44159
|
+
readSync2(fd, buf, 0, buf.length, start);
|
|
44160
|
+
const lines = buf.toString("utf-8").split(`
|
|
44161
|
+
`);
|
|
44162
|
+
if (start > 0)
|
|
44163
|
+
lines.shift();
|
|
44164
|
+
return lines.filter((l) => l.trim().length > 0);
|
|
44165
|
+
} catch {
|
|
44166
|
+
return [];
|
|
44167
|
+
} finally {
|
|
44168
|
+
if (fd !== null) {
|
|
44169
|
+
try {
|
|
44170
|
+
closeSync6(fd);
|
|
44171
|
+
} catch {}
|
|
44172
|
+
}
|
|
44173
|
+
}
|
|
44174
|
+
}
|
|
44175
|
+
var REASON_DETAIL_MAX_CHARS = 160, UPSTREAM_TAIL_BYTES;
|
|
44176
|
+
var init_reason_detail = __esm(() => {
|
|
44177
|
+
init_contract();
|
|
44178
|
+
UPSTREAM_TAIL_BYTES = 16 * 1024;
|
|
44179
|
+
});
|
|
44180
|
+
|
|
44089
44181
|
// src/pane/slot-row.ts
|
|
44090
|
-
function toSlotRow(id, snap, acct, now = Date.now()) {
|
|
44182
|
+
function toSlotRow(id, snap, acct, now = Date.now(), upstreamRecords = []) {
|
|
44091
44183
|
const terminal = isTerminalState(snap.state);
|
|
44092
44184
|
let idle = null;
|
|
44093
44185
|
if (!terminal && snap.lastActivityAt) {
|
|
@@ -44101,6 +44193,7 @@ function toSlotRow(id, snap, acct, now = Date.now()) {
|
|
|
44101
44193
|
provider: acct.provider,
|
|
44102
44194
|
state: snap.state,
|
|
44103
44195
|
reason: snap.state === "COMPLETED" || !terminal ? null : snap.reason,
|
|
44196
|
+
reason_detail: reasonDetail({ state: snap.state, reason: snap.reason, detail: snap.detail }, upstreamRecords),
|
|
44104
44197
|
tokens_in: acct.tokensIn,
|
|
44105
44198
|
tokens_out: acct.tokensOut,
|
|
44106
44199
|
cost_usd: acct.costUsd,
|
|
@@ -44114,6 +44207,7 @@ function toSlotRow(id, snap, acct, now = Date.now()) {
|
|
|
44114
44207
|
}
|
|
44115
44208
|
var init_slot_row = __esm(() => {
|
|
44116
44209
|
init_contract();
|
|
44210
|
+
init_reason_detail();
|
|
44117
44211
|
});
|
|
44118
44212
|
|
|
44119
44213
|
// src/pane/prompt-delivery.ts
|
|
@@ -51951,7 +52045,7 @@ function truncateKeepingLink(text, max = 400) {
|
|
|
51951
52045
|
const prose = (lastSpace > room * 0.5 ? head.slice(0, lastSpace) : head).trimEnd();
|
|
51952
52046
|
return `${prose}... ${url}`;
|
|
51953
52047
|
}
|
|
51954
|
-
function
|
|
52048
|
+
function oneLine5(text) {
|
|
51955
52049
|
return text.replace(/\s+/g, " ").trim();
|
|
51956
52050
|
}
|
|
51957
52051
|
function messageFromJson(text) {
|
|
@@ -51974,9 +52068,9 @@ function extractErrorMessage(body) {
|
|
|
51974
52068
|
return;
|
|
51975
52069
|
const direct = messageFromJson(body);
|
|
51976
52070
|
if (direct)
|
|
51977
|
-
return truncateKeepingLink(
|
|
52071
|
+
return truncateKeepingLink(oneLine5(unwrapFrame(direct)));
|
|
51978
52072
|
const unwrapped = unwrapFrame(body);
|
|
51979
|
-
const trimmed =
|
|
52073
|
+
const trimmed = oneLine5(unwrapped);
|
|
51980
52074
|
if (!trimmed)
|
|
51981
52075
|
return;
|
|
51982
52076
|
return truncateKeepingLink(trimmed);
|
|
@@ -57023,7 +57117,7 @@ If you cannot use structured tool_calls, format as JSON:
|
|
|
57023
57117
|
});
|
|
57024
57118
|
|
|
57025
57119
|
// src/handlers/native-handler-advisor.ts
|
|
57026
|
-
import { appendFileSync as
|
|
57120
|
+
import { appendFileSync as appendFileSync5 } from "fs";
|
|
57027
57121
|
function loadAdvisorSwapConfig(cliModels, cliCollector) {
|
|
57028
57122
|
return {
|
|
57029
57123
|
enabled: process.env.CLAUDISH_SWAP_ADVISOR === "1" || (cliModels?.length ?? 0) > 0,
|
|
@@ -57118,7 +57212,7 @@ function appendLine(path, line) {
|
|
|
57118
57212
|
if (!path)
|
|
57119
57213
|
return;
|
|
57120
57214
|
try {
|
|
57121
|
-
|
|
57215
|
+
appendFileSync5(path, `${line}
|
|
57122
57216
|
`);
|
|
57123
57217
|
} catch {}
|
|
57124
57218
|
}
|
|
@@ -59489,7 +59583,7 @@ var init_pricing_cache = __esm(() => {
|
|
|
59489
59583
|
});
|
|
59490
59584
|
|
|
59491
59585
|
// src/proxy-server.ts
|
|
59492
|
-
import { appendFileSync as
|
|
59586
|
+
import { appendFileSync as appendFileSync6, mkdirSync as mkdirSync15 } from "fs";
|
|
59493
59587
|
import { join as join35 } from "path";
|
|
59494
59588
|
function isTerminalRoutingFailure(e) {
|
|
59495
59589
|
return e instanceof RoutingError;
|
|
@@ -59523,7 +59617,7 @@ function maybeCaptureClassifierRequest(c, body) {
|
|
|
59523
59617
|
"x-api-key": c.req.header("x-api-key") ? "<present>" : null
|
|
59524
59618
|
}
|
|
59525
59619
|
};
|
|
59526
|
-
|
|
59620
|
+
appendFileSync6(join35(dir, "classifier-capture.jsonl"), `${JSON.stringify(record)}
|
|
59527
59621
|
`);
|
|
59528
59622
|
} catch {}
|
|
59529
59623
|
}
|
|
@@ -61553,7 +61647,7 @@ ${h("ENVIRONMENT VARIABLES")}
|
|
|
61553
61647
|
${blue("CLAUDISH_DIAG_MODE")} Diagnostic output: auto / logfile / off
|
|
61554
61648
|
${blue("CLAUDISH_DEBUG")} Always enable debug logging: 1 / true ${dim("(same as -d)")}
|
|
61555
61649
|
${blue("CLAUDISH_ANTHROPIC_API_BILLING")} Bill native Claude to your API key ${dim("(see --anthropic-api-billing)")}
|
|
61556
|
-
${blue("CLAUDISH_MCP_TOOLS")} MCP tool gating: all / low-level / agentic /
|
|
61650
|
+
${blue("CLAUDISH_MCP_TOOLS")} MCP tool gating: all / low-level / agentic / session / debug
|
|
61557
61651
|
${blue("CLAUDISH_MODEL_OPUS")} Override model for Opus role
|
|
61558
61652
|
${blue("CLAUDISH_MODEL_SONNET")} Override model for Sonnet role
|
|
61559
61653
|
${blue("CLAUDISH_MODEL_HAIKU")} Override model for Haiku role
|
|
@@ -61863,11 +61957,11 @@ var init_magmux_binary = () => {};
|
|
|
61863
61957
|
// src/launcher/magmux-wrapper.ts
|
|
61864
61958
|
import {
|
|
61865
61959
|
chmodSync,
|
|
61866
|
-
closeSync as
|
|
61960
|
+
closeSync as closeSync7,
|
|
61867
61961
|
existsSync as existsSync27,
|
|
61868
61962
|
mkdirSync as mkdirSync17,
|
|
61869
61963
|
mkdtempSync,
|
|
61870
|
-
openSync as
|
|
61964
|
+
openSync as openSync7,
|
|
61871
61965
|
rmSync as rmSync2,
|
|
61872
61966
|
writeFileSync as writeFileSync16
|
|
61873
61967
|
} from "fs";
|
|
@@ -61914,7 +62008,7 @@ function buildLauncherScript(claudeBinary, claudeArgs, deltas) {
|
|
|
61914
62008
|
}
|
|
61915
62009
|
function magmuxPaneCapability(input) {
|
|
61916
62010
|
const parentEnv = input.parentEnv ?? process.env;
|
|
61917
|
-
if (
|
|
62011
|
+
if (inMcpSession(parentEnv))
|
|
61918
62012
|
return { kind: "none", reason: "pane-child" };
|
|
61919
62013
|
if (!input.interactive)
|
|
61920
62014
|
return { kind: "none", reason: "not-interactive" };
|
|
@@ -61943,11 +62037,11 @@ function planMagmuxWrap(input) {
|
|
|
61943
62037
|
const scriptPath = join38(scriptDir, "claude-launch.sh");
|
|
61944
62038
|
const parentEnv = input.parentEnv ?? process.env;
|
|
61945
62039
|
const deltas = envDeltas(parentEnv, input.childEnv);
|
|
61946
|
-
const fd =
|
|
62040
|
+
const fd = openSync7(scriptPath, "wx", 384);
|
|
61947
62041
|
try {
|
|
61948
62042
|
writeFileSync16(fd, buildLauncherScript(input.claudeBinary, input.claudeArgs, deltas));
|
|
61949
62043
|
} finally {
|
|
61950
|
-
|
|
62044
|
+
closeSync7(fd);
|
|
61951
62045
|
}
|
|
61952
62046
|
const env = { ...input.childEnv };
|
|
61953
62047
|
for (const k of STRIPPED_CHILD_VARS)
|
|
@@ -62415,13 +62509,13 @@ function sockPathFor(root, id) {
|
|
|
62415
62509
|
throw new PaneRootError(`pane socket path ${p} is ${Buffer.byteLength(p)} bytes; it must be < 100`);
|
|
62416
62510
|
return p;
|
|
62417
62511
|
}
|
|
62418
|
-
function
|
|
62512
|
+
function isStrippedFromChildEnv(key) {
|
|
62419
62513
|
return STRIPPED_CHILD_VARS.includes(key) || key.startsWith("MAGMUX_") || TERMINAL_IDENTITY_VARS.includes(key) || TERMINAL_IDENTITY_PREFIXES.some((p) => key.startsWith(p)) || HOST_IDENTITY_VARS.includes(key);
|
|
62420
62514
|
}
|
|
62421
62515
|
function buildPaneEnv(input) {
|
|
62422
62516
|
const env = {};
|
|
62423
62517
|
for (const [k, v] of Object.entries(input.parentEnv)) {
|
|
62424
|
-
if (v === undefined ||
|
|
62518
|
+
if (v === undefined || isStrippedFromChildEnv(k))
|
|
62425
62519
|
continue;
|
|
62426
62520
|
env[k] = v;
|
|
62427
62521
|
}
|
|
@@ -63352,7 +63446,7 @@ var init_pane_registry = __esm(() => {
|
|
|
63352
63446
|
sweptRoots = new Set;
|
|
63353
63447
|
});
|
|
63354
63448
|
|
|
63355
|
-
// src/
|
|
63449
|
+
// src/mcp-session/parent-session.ts
|
|
63356
63450
|
import { readFile as readFile4 } from "fs/promises";
|
|
63357
63451
|
import { join as join42 } from "path";
|
|
63358
63452
|
function positiveInt(value) {
|
|
@@ -64001,11 +64095,11 @@ var init_slot_state = __esm(() => {
|
|
|
64001
64095
|
|
|
64002
64096
|
// src/pane/transcript-follower.ts
|
|
64003
64097
|
import {
|
|
64004
|
-
closeSync as
|
|
64098
|
+
closeSync as closeSync8,
|
|
64005
64099
|
existsSync as existsSync29,
|
|
64006
|
-
fstatSync,
|
|
64007
|
-
openSync as
|
|
64008
|
-
readSync as
|
|
64100
|
+
fstatSync as fstatSync2,
|
|
64101
|
+
openSync as openSync8,
|
|
64102
|
+
readSync as readSync3,
|
|
64009
64103
|
readdirSync as readdirSync7,
|
|
64010
64104
|
realpathSync as realpathSync2,
|
|
64011
64105
|
statSync as statSync8
|
|
@@ -64440,16 +64534,16 @@ class Tail {
|
|
|
64440
64534
|
read() {
|
|
64441
64535
|
let fd;
|
|
64442
64536
|
try {
|
|
64443
|
-
fd =
|
|
64537
|
+
fd = openSync8(this.path, "r");
|
|
64444
64538
|
} catch {
|
|
64445
64539
|
return [];
|
|
64446
64540
|
}
|
|
64447
64541
|
try {
|
|
64448
|
-
const size =
|
|
64542
|
+
const size = fstatSync2(fd).size;
|
|
64449
64543
|
if (size <= this.offset)
|
|
64450
64544
|
return [];
|
|
64451
64545
|
const chunk = Buffer.alloc(size - this.offset);
|
|
64452
|
-
const got =
|
|
64546
|
+
const got = readSync3(fd, chunk, 0, chunk.length, this.offset);
|
|
64453
64547
|
this.offset += got;
|
|
64454
64548
|
const fresh = chunk.subarray(0, got);
|
|
64455
64549
|
const buf = this.rest.length ? Buffer.concat([this.rest, fresh]) : fresh;
|
|
@@ -64466,7 +64560,7 @@ class Tail {
|
|
|
64466
64560
|
this.rest = Buffer.from(buf.subarray(start));
|
|
64467
64561
|
return out;
|
|
64468
64562
|
} finally {
|
|
64469
|
-
|
|
64563
|
+
closeSync8(fd);
|
|
64470
64564
|
}
|
|
64471
64565
|
}
|
|
64472
64566
|
}
|
|
@@ -65192,9 +65286,12 @@ class PaneSessionImpl {
|
|
|
65192
65286
|
this.deliver(this.admission);
|
|
65193
65287
|
}
|
|
65194
65288
|
async deliver(adm) {
|
|
65195
|
-
|
|
65289
|
+
if (await this.typeAndSubmit(adm.plan))
|
|
65290
|
+
adm.deliveredAt = Date.now();
|
|
65291
|
+
}
|
|
65292
|
+
async typeAndSubmit(plan) {
|
|
65196
65293
|
if (plan.mode !== "typed" && plan.mode !== "file" && plan.mode !== "command")
|
|
65197
|
-
return;
|
|
65294
|
+
return false;
|
|
65198
65295
|
if (plan.mode === "command") {
|
|
65199
65296
|
await this.typeLine(plan.line, false);
|
|
65200
65297
|
await this.nextFrame(500);
|
|
@@ -65206,7 +65303,7 @@ class PaneSessionImpl {
|
|
|
65206
65303
|
} else {
|
|
65207
65304
|
await this.typeLine(plan.line, true);
|
|
65208
65305
|
}
|
|
65209
|
-
|
|
65306
|
+
return true;
|
|
65210
65307
|
}
|
|
65211
65308
|
async typeLine(text, enter) {
|
|
65212
65309
|
let why = "disconnected";
|
|
@@ -65310,16 +65407,44 @@ class PaneSessionImpl {
|
|
|
65310
65407
|
this.fire("admit_abandoned");
|
|
65311
65408
|
return true;
|
|
65312
65409
|
}
|
|
65410
|
+
async awaitClearedBox(adm, head) {
|
|
65411
|
+
const end = Date.now() + this.t("nudgeClearDeadlineMs", NUDGE_CLEAR_DEADLINE_MS);
|
|
65412
|
+
for (;; ) {
|
|
65413
|
+
if (this.admission !== adm || this.phase !== "ADMITTING")
|
|
65414
|
+
return "gone";
|
|
65415
|
+
const box = inputBox(this.screen);
|
|
65416
|
+
if (box && box.text === "")
|
|
65417
|
+
return "empty";
|
|
65418
|
+
if (box && !box.text.startsWith(head))
|
|
65419
|
+
return "other";
|
|
65420
|
+
const left = end - Date.now();
|
|
65421
|
+
if (left <= 0)
|
|
65422
|
+
return box ? "line" : "other";
|
|
65423
|
+
await this.nextFrame(left);
|
|
65424
|
+
}
|
|
65425
|
+
}
|
|
65313
65426
|
nudge(adm) {
|
|
65314
65427
|
const box = inputBox(this.screen);
|
|
65315
65428
|
const line = adm.plan.mode === "control" || adm.plan.mode === "refused" ? "" : adm.plan.line;
|
|
65316
|
-
|
|
65429
|
+
const head = line.slice(0, 40);
|
|
65430
|
+
if (!adm.resent && box && line && box.text.startsWith(head)) {
|
|
65317
65431
|
adm.resent = true;
|
|
65318
65432
|
this.anomaly("resent_enter");
|
|
65319
65433
|
(async () => {
|
|
65320
65434
|
if (box.menuOpen)
|
|
65321
65435
|
await this.key("escape");
|
|
65322
|
-
await this.key("
|
|
65436
|
+
await this.key("ctrl-u");
|
|
65437
|
+
const after = await this.awaitClearedBox(adm, head);
|
|
65438
|
+
if (after === "gone")
|
|
65439
|
+
return;
|
|
65440
|
+
if (after === "empty") {
|
|
65441
|
+
this.anomaly("retyped_prompt");
|
|
65442
|
+
await this.typeAndSubmit(adm.plan);
|
|
65443
|
+
} else if (after === "line") {
|
|
65444
|
+
await this.key("enter");
|
|
65445
|
+
} else {
|
|
65446
|
+
this.anomaly("clear_failed");
|
|
65447
|
+
}
|
|
65323
65448
|
})();
|
|
65324
65449
|
return;
|
|
65325
65450
|
}
|
|
@@ -66033,7 +66158,7 @@ async function startPaneSession(o) {
|
|
|
66033
66158
|
await session.start({ magmuxBinary: magmux.binary, env: p.magmuxEnv, cwd: p.cwd });
|
|
66034
66159
|
return session;
|
|
66035
66160
|
}
|
|
66036
|
-
var BOOT_TIMEOUT_MS = 90000, ADMIT_TIMEOUT_MS = 30000, RESEND_AFTER_MS = 1e4, DEGRADED_ENTRY_MS = 1e4, SCREEN_SETTLE_QUIET_MS = 3000, PANEL_SETTLE_MS = 500, REPL_STABLE_MS =
|
|
66161
|
+
var BOOT_TIMEOUT_MS = 90000, ADMIT_TIMEOUT_MS = 30000, RESEND_AFTER_MS = 1e4, DEGRADED_ENTRY_MS = 1e4, SCREEN_SETTLE_QUIET_MS = 3000, PANEL_SETTLE_MS = 500, REPL_STABLE_MS = 3000, NUDGE_CLEAR_DEADLINE_MS = 3000, BOOT_STATIC_MS = 5000, TICK_MS = 250, WATCH_FPS = 4, POLL_BACKSTOP_MS = 1000, TURN_END_MISSING_FACTOR = 3, REGISTRY_READ_MS = 250, REGISTRY_DISAGREE_MS = 2000, REGISTRY_MISSING_MS = 5000, MAX_ANOMALY_KEYS = 64, KEPT_ANSWERS = 4, EVENT_REASON, VERDICT_EVENT, PaneStartError;
|
|
66037
66162
|
var init_pane_session = __esm(() => {
|
|
66038
66163
|
init_parent_session();
|
|
66039
66164
|
init_process_tree();
|
|
@@ -66073,6 +66198,7 @@ var init_pane_session = __esm(() => {
|
|
|
66073
66198
|
// src/pane/index.ts
|
|
66074
66199
|
var init_pane = __esm(() => {
|
|
66075
66200
|
init_slot_row();
|
|
66201
|
+
init_reason_detail();
|
|
66076
66202
|
init_prompt_delivery();
|
|
66077
66203
|
init_accounting();
|
|
66078
66204
|
init_pane_launch();
|
|
@@ -66098,7 +66224,7 @@ __export(exports_session_discovery, {
|
|
|
66098
66224
|
transcriptPathFor: () => transcriptPathFor
|
|
66099
66225
|
});
|
|
66100
66226
|
import { execFile as execFile3, execFileSync as execFileSync3 } from "child_process";
|
|
66101
|
-
import { closeSync as
|
|
66227
|
+
import { closeSync as closeSync9, openSync as openSync9, readSync as readSync4, readdirSync as readdirSync8, realpathSync as realpathSync4, statSync as statSync10 } from "fs";
|
|
66102
66228
|
import { basename as basename2, join as join46 } from "path";
|
|
66103
66229
|
function projectsDir(env = process.env) {
|
|
66104
66230
|
return join46(claudeConfigDir(env), "projects");
|
|
@@ -66348,16 +66474,16 @@ function readChunk(file, pos, len) {
|
|
|
66348
66474
|
return "";
|
|
66349
66475
|
let fd = null;
|
|
66350
66476
|
try {
|
|
66351
|
-
fd =
|
|
66477
|
+
fd = openSync9(file, "r");
|
|
66352
66478
|
const buf = Buffer.allocUnsafe(len);
|
|
66353
|
-
const n =
|
|
66479
|
+
const n = readSync4(fd, buf, 0, len, pos);
|
|
66354
66480
|
return buf.subarray(0, n).toString("utf-8");
|
|
66355
66481
|
} catch {
|
|
66356
66482
|
return "";
|
|
66357
66483
|
} finally {
|
|
66358
66484
|
if (fd !== null) {
|
|
66359
66485
|
try {
|
|
66360
|
-
|
|
66486
|
+
closeSync9(fd);
|
|
66361
66487
|
} catch {}
|
|
66362
66488
|
}
|
|
66363
66489
|
}
|
|
@@ -66613,6 +66739,9 @@ function refreshAccounting(e, snap) {
|
|
|
66613
66739
|
function notableAnomalies(snap) {
|
|
66614
66740
|
return snap.anomalies.filter((a) => a.startsWith("background_shell_open") || a.startsWith("turn_end_record_missing") || a.startsWith("prompt_not_read"));
|
|
66615
66741
|
}
|
|
66742
|
+
function upstreamLogPath(path, id) {
|
|
66743
|
+
return join47(path, "errors", `${id}-upstream.jsonl`);
|
|
66744
|
+
}
|
|
66616
66745
|
function neverSpawnedRow(e, m) {
|
|
66617
66746
|
return {
|
|
66618
66747
|
slot: e.id,
|
|
@@ -66620,6 +66749,11 @@ function neverSpawnedRow(e, m) {
|
|
|
66620
66749
|
provider: e.acct.provider,
|
|
66621
66750
|
state: m?.state ?? "FAILED",
|
|
66622
66751
|
reason: m?.error?.reason ?? "pane_lost",
|
|
66752
|
+
reason_detail: reasonDetail({
|
|
66753
|
+
state: m?.state ?? "FAILED",
|
|
66754
|
+
reason: m?.error?.reason ?? "pane_lost",
|
|
66755
|
+
detail: m?.error?.detail
|
|
66756
|
+
}),
|
|
66623
66757
|
tokens_in: null,
|
|
66624
66758
|
tokens_out: null,
|
|
66625
66759
|
cost_usd: null,
|
|
@@ -66635,7 +66769,7 @@ function liveSlotRow(run, e) {
|
|
|
66635
66769
|
if (!e.session)
|
|
66636
66770
|
return neverSpawnedRow(e, run.status.models[e.id]);
|
|
66637
66771
|
const snap = e.session.snapshot();
|
|
66638
|
-
return toSlotRow({ slot: e.id, model: e.model, spawnModel: e.spawnModel }, snap, refreshAccounting(e, snap));
|
|
66772
|
+
return toSlotRow({ slot: e.id, model: e.model, spawnModel: e.spawnModel }, snap, refreshAccounting(e, snap), Date.now(), upstreamRecordsFor(snap, upstreamLogPath(run.path, e.id)));
|
|
66639
66773
|
}
|
|
66640
66774
|
function outcomeOf(states) {
|
|
66641
66775
|
const ok = states.filter((s) => s === "COMPLETED").length;
|
|
@@ -66674,12 +66808,15 @@ function teamRunRowFromDisk(path, status) {
|
|
|
66674
66808
|
const slots = Object.entries(status.models ?? {}).sort(([a], [b]) => a.localeCompare(b)).map(([id, m]) => {
|
|
66675
66809
|
const { state, known } = closedState(m?.state);
|
|
66676
66810
|
const terminal = isTerminalState(state);
|
|
66811
|
+
const reason = !known || !terminal || state === "COMPLETED" ? null : m?.error?.reason ?? null;
|
|
66812
|
+
const why = { state, reason, detail: m?.error?.detail };
|
|
66677
66813
|
return {
|
|
66678
66814
|
slot: id,
|
|
66679
66815
|
model: m?.model ?? manifest?.models[id]?.model ?? "unknown",
|
|
66680
66816
|
provider: m?.provider ?? null,
|
|
66681
66817
|
state,
|
|
66682
|
-
reason
|
|
66818
|
+
reason,
|
|
66819
|
+
reason_detail: reasonDetail(why, upstreamRecordsFor(why, upstreamLogPath(path, id))),
|
|
66683
66820
|
tokens_in: m?.tokensIn ?? null,
|
|
66684
66821
|
tokens_out: m?.tokensOut ?? null,
|
|
66685
66822
|
cost_usd: m?.costUsd ?? null,
|
|
@@ -67073,7 +67210,7 @@ async function startModelsIn(flight, sessionPath, opts) {
|
|
|
67073
67210
|
const entries = new Map;
|
|
67074
67211
|
let run = null;
|
|
67075
67212
|
const errorLogPathOf = (id) => join47(path, "errors", `${id}.log`);
|
|
67076
|
-
const upstreamLogOf = (id) =>
|
|
67213
|
+
const upstreamLogOf = (id) => upstreamLogPath(path, id);
|
|
67077
67214
|
const commandOf = (e) => ["claudish", "-i", "--model", e.spawnModel ?? e.model, "-y", "--quiet", ...claudeFlags].join(" ");
|
|
67078
67215
|
function writeResponse(e, text) {
|
|
67079
67216
|
e.answer = text;
|
|
@@ -67635,17 +67772,17 @@ var init_team_orchestrator = __esm(() => {
|
|
|
67635
67772
|
CANCELLED_DETAIL = `Stopped on the caller's instruction via team(mode:"cancel"). ` + "Whatever the child had written up to that point is in its response file.";
|
|
67636
67773
|
});
|
|
67637
67774
|
|
|
67638
|
-
// src/
|
|
67775
|
+
// src/mcp-session/session-manager.ts
|
|
67639
67776
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
67640
67777
|
import {
|
|
67641
|
-
appendFileSync as
|
|
67642
|
-
closeSync as
|
|
67778
|
+
appendFileSync as appendFileSync7,
|
|
67779
|
+
closeSync as closeSync10,
|
|
67643
67780
|
createWriteStream,
|
|
67644
67781
|
existsSync as existsSync31,
|
|
67645
67782
|
mkdirSync as mkdirSync20,
|
|
67646
|
-
openSync as
|
|
67783
|
+
openSync as openSync10,
|
|
67647
67784
|
readFileSync as readFileSync30,
|
|
67648
|
-
readSync as
|
|
67785
|
+
readSync as readSync5,
|
|
67649
67786
|
renameSync as renameSync4,
|
|
67650
67787
|
statSync as statSync12,
|
|
67651
67788
|
writeFileSync as writeFileSync21
|
|
@@ -67657,7 +67794,7 @@ function normaliseTimeoutSeconds(raw) {
|
|
|
67657
67794
|
return DEFAULT_TIMEOUT;
|
|
67658
67795
|
return Math.min(MAX_TIMEOUT, Math.max(1, Math.round(n)));
|
|
67659
67796
|
}
|
|
67660
|
-
function
|
|
67797
|
+
function sessionEventFor(snap) {
|
|
67661
67798
|
switch (snap.state) {
|
|
67662
67799
|
case "STARTING":
|
|
67663
67800
|
return { event: "starting", tool: null };
|
|
@@ -67679,7 +67816,7 @@ function channelEventFor(snap) {
|
|
|
67679
67816
|
return { event: "failed", tool: null };
|
|
67680
67817
|
}
|
|
67681
67818
|
}
|
|
67682
|
-
function sessionRowOf(info) {
|
|
67819
|
+
function sessionRowOf(info, upstreamRecords = []) {
|
|
67683
67820
|
const terminal = isTerminalState(info.state);
|
|
67684
67821
|
return {
|
|
67685
67822
|
slot: info.sessionId,
|
|
@@ -67687,6 +67824,7 @@ function sessionRowOf(info) {
|
|
|
67687
67824
|
provider: info.provider,
|
|
67688
67825
|
state: info.state,
|
|
67689
67826
|
reason: info.state === "COMPLETED" || !terminal ? null : info.reason,
|
|
67827
|
+
reason_detail: reasonDetail(info, upstreamRecords),
|
|
67690
67828
|
tokens_in: info.tokensIn,
|
|
67691
67829
|
tokens_out: info.tokensOut,
|
|
67692
67830
|
cost_usd: info.costUsd,
|
|
@@ -67741,15 +67879,6 @@ function writeJsonAtomic(path, value) {
|
|
|
67741
67879
|
writeFileSync21(tmp, JSON.stringify(value, null, 2), "utf-8");
|
|
67742
67880
|
renameSync4(tmp, path);
|
|
67743
67881
|
}
|
|
67744
|
-
function anomalyCount(anomalies, key) {
|
|
67745
|
-
for (const a of anomalies) {
|
|
67746
|
-
if (a === key)
|
|
67747
|
-
return 1;
|
|
67748
|
-
if (a.startsWith(`${key} \xD7`))
|
|
67749
|
-
return Number(a.slice(key.length + 2)) || 1;
|
|
67750
|
-
}
|
|
67751
|
-
return 0;
|
|
67752
|
-
}
|
|
67753
67882
|
function anomalyKey(a) {
|
|
67754
67883
|
const at = a.lastIndexOf(" \xD7");
|
|
67755
67884
|
return at > 0 ? a.slice(0, at) : a;
|
|
@@ -67763,20 +67892,20 @@ function readTailText(path, maxBytes) {
|
|
|
67763
67892
|
const start = Math.max(0, size - maxBytes);
|
|
67764
67893
|
const length = size - start;
|
|
67765
67894
|
const buf = Buffer.alloc(length);
|
|
67766
|
-
fd =
|
|
67767
|
-
|
|
67895
|
+
fd = openSync10(path, "r");
|
|
67896
|
+
readSync5(fd, buf, 0, length, start);
|
|
67768
67897
|
return { text: buf.toString("utf-8"), truncated: start > 0 };
|
|
67769
67898
|
} catch {
|
|
67770
67899
|
return null;
|
|
67771
67900
|
} finally {
|
|
67772
67901
|
if (fd !== null) {
|
|
67773
67902
|
try {
|
|
67774
|
-
|
|
67903
|
+
closeSync10(fd);
|
|
67775
67904
|
} catch {}
|
|
67776
67905
|
}
|
|
67777
67906
|
}
|
|
67778
67907
|
}
|
|
67779
|
-
function
|
|
67908
|
+
function readTailLines2(path, maxBytes) {
|
|
67780
67909
|
const tail = readTailText(path, maxBytes);
|
|
67781
67910
|
if (!tail)
|
|
67782
67911
|
return [];
|
|
@@ -67863,7 +67992,6 @@ class SessionManager {
|
|
|
67863
67992
|
scrollbackCapacity;
|
|
67864
67993
|
sessionsDir;
|
|
67865
67994
|
terminalRetentionMs;
|
|
67866
|
-
onStateChange;
|
|
67867
67995
|
parentEnv;
|
|
67868
67996
|
paneTimings;
|
|
67869
67997
|
starting = 0;
|
|
@@ -67880,7 +68008,6 @@ class SessionManager {
|
|
|
67880
68008
|
this.scrollbackCapacity = options?.scrollbackCapacity ?? DEFAULT_SCROLLBACK;
|
|
67881
68009
|
this.terminalRetentionMs = options?.terminalRetentionMs ?? TERMINAL_RETENTION_MS;
|
|
67882
68010
|
this.sessionsDir = options?.sessionsDir ?? sessionsDirFrom(process.env);
|
|
67883
|
-
this.onStateChange = options?.onStateChange;
|
|
67884
68011
|
this.parentEnv = options?.parentEnv ?? process.env;
|
|
67885
68012
|
this.paneTimings = options?.paneTimings;
|
|
67886
68013
|
}
|
|
@@ -68087,16 +68214,9 @@ class SessionManager {
|
|
|
68087
68214
|
waitSince: null,
|
|
68088
68215
|
ended: false,
|
|
68089
68216
|
evictHandle: null,
|
|
68090
|
-
lastEvent: "starting",
|
|
68091
|
-
lastFrameTool: null,
|
|
68092
|
-
lastFrameToolCount: 0,
|
|
68093
|
-
lastToolFrameAt: 0,
|
|
68094
68217
|
lastLoggedTool: null,
|
|
68095
68218
|
assistantIdsLogged: 0,
|
|
68096
|
-
anomaliesLogged: new Set
|
|
68097
|
-
sendRejectedSeen: 0,
|
|
68098
|
-
pendingMeta: {},
|
|
68099
|
-
blockText: null
|
|
68219
|
+
anomaliesLogged: new Set
|
|
68100
68220
|
};
|
|
68101
68221
|
}
|
|
68102
68222
|
async startPane(entry, opts, p) {
|
|
@@ -68145,7 +68265,6 @@ class SessionManager {
|
|
|
68145
68265
|
info.elapsedSeconds = elapsedSecondsBetween(info.startedAt, Date.parse(at));
|
|
68146
68266
|
this.appendEvent(entry, { type: "state", from: "STARTING", to: "FAILED", at });
|
|
68147
68267
|
this.endRecords(entry, null);
|
|
68148
|
-
this.emitFrame(entry, { state: "FAILED", activity: null, toolCalls: 0 });
|
|
68149
68268
|
}
|
|
68150
68269
|
decide(entry, turn) {
|
|
68151
68270
|
this.appendAnswer(entry, turn.index, turn.answer);
|
|
@@ -68166,7 +68285,6 @@ class SessionManager {
|
|
|
68166
68285
|
return { state: "FAILED", reason: "api_error", detail: v?.detail ?? "API error" };
|
|
68167
68286
|
}
|
|
68168
68287
|
if (turn.delivery.complete === false) {
|
|
68169
|
-
entry.pendingMeta.prompt_not_read = "true";
|
|
68170
68288
|
this.appendEvent(entry, {
|
|
68171
68289
|
type: "anomaly",
|
|
68172
68290
|
key: "prompt_not_read",
|
|
@@ -68178,8 +68296,7 @@ class SessionManager {
|
|
|
68178
68296
|
}
|
|
68179
68297
|
return "continue";
|
|
68180
68298
|
}
|
|
68181
|
-
onBlocked(
|
|
68182
|
-
entry.blockText = b.text;
|
|
68299
|
+
onBlocked(_entry, _b) {
|
|
68183
68300
|
return "wait";
|
|
68184
68301
|
}
|
|
68185
68302
|
onPaneTransition(entry, t) {
|
|
@@ -68190,18 +68307,14 @@ class SessionManager {
|
|
|
68190
68307
|
this.recordWaitTransition(entry, t.from, t.to, t.at, snap);
|
|
68191
68308
|
this.appendEvent(entry, { type: "state", from: t.from, to: t.to, at: t.at });
|
|
68192
68309
|
this.logPaneFacts(entry, snap);
|
|
68193
|
-
if (!isWaiting(t.to))
|
|
68194
|
-
entry.blockText = null;
|
|
68195
68310
|
if (isTerminalState(t.to))
|
|
68196
68311
|
this.onTerminal(entry, snap);
|
|
68197
|
-
this.emitFrame(entry, snap);
|
|
68198
68312
|
}
|
|
68199
68313
|
onPaneChange(entry, snap) {
|
|
68200
68314
|
if (entry.ended)
|
|
68201
68315
|
return;
|
|
68202
68316
|
this.applySnapshot(entry, snap);
|
|
68203
68317
|
this.logPaneFacts(entry, snap);
|
|
68204
|
-
this.emitFrame(entry, snap);
|
|
68205
68318
|
}
|
|
68206
68319
|
onTerminal(entry, snap) {
|
|
68207
68320
|
const session = entry.session;
|
|
@@ -68239,7 +68352,7 @@ class SessionManager {
|
|
|
68239
68352
|
wait: "closed",
|
|
68240
68353
|
since: entry.waitSince,
|
|
68241
68354
|
at: entry.info.completedAt ?? new Date().toISOString(),
|
|
68242
|
-
to:
|
|
68355
|
+
to: sessionEventFor(entry.info).event
|
|
68243
68356
|
});
|
|
68244
68357
|
entry.waitSince = null;
|
|
68245
68358
|
}
|
|
@@ -68289,7 +68402,7 @@ class SessionManager {
|
|
|
68289
68402
|
at
|
|
68290
68403
|
});
|
|
68291
68404
|
}
|
|
68292
|
-
const { tool } =
|
|
68405
|
+
const { tool } = sessionEventFor(snap);
|
|
68293
68406
|
if (tool && tool !== entry.lastLoggedTool)
|
|
68294
68407
|
this.appendEvent(entry, { type: "tool", name: tool, at });
|
|
68295
68408
|
entry.lastLoggedTool = tool;
|
|
@@ -68300,66 +68413,6 @@ class SessionManager {
|
|
|
68300
68413
|
entry.anomaliesLogged.add(key);
|
|
68301
68414
|
this.appendEvent(entry, { type: "anomaly", key, at });
|
|
68302
68415
|
}
|
|
68303
|
-
const rejected = anomalyCount(snap.anomalies, "send_not_accepted");
|
|
68304
|
-
if (rejected > entry.sendRejectedSeen) {
|
|
68305
|
-
entry.sendRejectedSeen = rejected;
|
|
68306
|
-
entry.pendingMeta.send_rejected = "true";
|
|
68307
|
-
}
|
|
68308
|
-
}
|
|
68309
|
-
emitFrame(entry, snap) {
|
|
68310
|
-
const { event, tool } = channelEventFor(snap);
|
|
68311
|
-
const now = Date.now();
|
|
68312
|
-
const changed = event !== entry.lastEvent;
|
|
68313
|
-
const toolRepeat = !changed && event === "tool_executing" && (tool !== entry.lastFrameTool || snap.toolCalls !== entry.lastFrameToolCount) && now - entry.lastToolFrameAt >= 1000;
|
|
68314
|
-
if (!changed && !toolRepeat)
|
|
68315
|
-
return;
|
|
68316
|
-
entry.lastEvent = event;
|
|
68317
|
-
if (event === "tool_executing") {
|
|
68318
|
-
entry.lastFrameTool = tool;
|
|
68319
|
-
entry.lastFrameToolCount = snap.toolCalls;
|
|
68320
|
-
entry.lastToolFrameAt = now;
|
|
68321
|
-
}
|
|
68322
|
-
const extraMeta = {
|
|
68323
|
-
...tool ? { tool, tool_count: String(snap.toolCalls) } : {},
|
|
68324
|
-
...snap.activity ? { activity: snap.activity } : {},
|
|
68325
|
-
...entry.pendingMeta
|
|
68326
|
-
};
|
|
68327
|
-
entry.pendingMeta = {};
|
|
68328
|
-
try {
|
|
68329
|
-
this.onStateChange?.(entry.info.sessionId, {
|
|
68330
|
-
type: event,
|
|
68331
|
-
model: entry.info.model,
|
|
68332
|
-
content: this.frameContent(entry, event, tool),
|
|
68333
|
-
elapsedSeconds: entry.info.elapsedSeconds,
|
|
68334
|
-
createdAt: entry.info.startedAt,
|
|
68335
|
-
extraMeta
|
|
68336
|
-
});
|
|
68337
|
-
} catch {}
|
|
68338
|
-
}
|
|
68339
|
-
frameContent(entry, event, tool) {
|
|
68340
|
-
const info = entry.info;
|
|
68341
|
-
switch (event) {
|
|
68342
|
-
case "running":
|
|
68343
|
-
return "The turn is running.";
|
|
68344
|
-
case "tool_executing":
|
|
68345
|
-
return `Using ${tool}.`;
|
|
68346
|
-
case "waiting_for_input":
|
|
68347
|
-
return entry.blockText ? `The model asked a question; send_input declines it and becomes the next prompt.
|
|
68348
|
-
${entry.blockText}` : "The turn finished; waiting for send_input.";
|
|
68349
|
-
case "awaiting_permission":
|
|
68350
|
-
return `A permission dialog is open for ${info.activity ?? "a tool"}; send_input declines it and becomes the next prompt.${entry.blockText ? `
|
|
68351
|
-
${entry.blockText}` : ""}`;
|
|
68352
|
-
case "completed":
|
|
68353
|
-
return `Session completed (${info.turnsCompleted} turn(s)). Call get_output for the answer.`;
|
|
68354
|
-
case "cancelled":
|
|
68355
|
-
return "Session cancelled.";
|
|
68356
|
-
case "timeout":
|
|
68357
|
-
return `Timeout after ${info.timeoutSeconds}s; the pane was closed.`;
|
|
68358
|
-
case "failed":
|
|
68359
|
-
return `${info.state} ${info.reason ?? ""}${info.detail ? `: ${info.detail}` : ""}`.trim();
|
|
68360
|
-
default:
|
|
68361
|
-
return "";
|
|
68362
|
-
}
|
|
68363
68416
|
}
|
|
68364
68417
|
sendInput(sessionId, text) {
|
|
68365
68418
|
const entry = this.liveEntry(sessionId);
|
|
@@ -68403,7 +68456,7 @@ ${entry.blockText}` : ""}`;
|
|
|
68403
68456
|
return {
|
|
68404
68457
|
sessionId,
|
|
68405
68458
|
state: info.state,
|
|
68406
|
-
event:
|
|
68459
|
+
event: sessionEventFor(info).event,
|
|
68407
68460
|
reason: isTerminalState(info.state) && info.state !== "COMPLETED" ? info.reason : null,
|
|
68408
68461
|
detail: info.detail,
|
|
68409
68462
|
model: info.model,
|
|
@@ -68427,7 +68480,7 @@ ${entry.blockText}` : ""}`;
|
|
|
68427
68480
|
...this.paneFacts(entry),
|
|
68428
68481
|
recentEvents: limit === 0 ? [] : entry.eventRing.slice(-limit),
|
|
68429
68482
|
eventsTotal: entry.eventRing.length,
|
|
68430
|
-
upstreamErrors:
|
|
68483
|
+
upstreamErrors: readTailLines2(entry.upstreamErrorLogPath, UPSTREAM_ERROR_TAIL_BYTES),
|
|
68431
68484
|
claudeSessionId: info.claudeSessionId,
|
|
68432
68485
|
transcriptPath: info.transcriptPath,
|
|
68433
68486
|
sessionDir: entry.sessionDir,
|
|
@@ -68493,7 +68546,15 @@ ${entry.blockText}` : ""}`;
|
|
|
68493
68546
|
return sessions;
|
|
68494
68547
|
}
|
|
68495
68548
|
listSessionRows(includeCompleted = false) {
|
|
68496
|
-
|
|
68549
|
+
const rows = [];
|
|
68550
|
+
for (const entry of this.sessions.values()) {
|
|
68551
|
+
this.refresh(entry);
|
|
68552
|
+
if (!includeCompleted && isTerminalState(entry.info.state))
|
|
68553
|
+
continue;
|
|
68554
|
+
const info = { ...entry.info };
|
|
68555
|
+
rows.push(sessionRowOf(info, upstreamRecordsFor(info, entry.upstreamErrorLogPath)));
|
|
68556
|
+
}
|
|
68557
|
+
return rows;
|
|
68497
68558
|
}
|
|
68498
68559
|
getSession(sessionId) {
|
|
68499
68560
|
const entry = this.sessions.get(sessionId);
|
|
@@ -68598,13 +68659,13 @@ ${entry.blockText}` : ""}`;
|
|
|
68598
68659
|
const eventLogPath = join48(sessionDir, "events.jsonl");
|
|
68599
68660
|
const upstreamErrorLogPath = join48(sessionDir, "upstream-errors.jsonl");
|
|
68600
68661
|
const outputLogPath = join48(sessionDir, "output.log");
|
|
68601
|
-
const events =
|
|
68662
|
+
const events = readTailLines2(eventLogPath, EVENT_TAIL_BYTES);
|
|
68602
68663
|
const outputTail = readTailText(outputLogPath, OUTPUT_TAIL_BYTES);
|
|
68603
68664
|
const screen = readTailText(join48(sessionDir, "screen.txt"), SCREEN_READ_BYTES);
|
|
68604
68665
|
return {
|
|
68605
68666
|
sessionId: info.sessionId,
|
|
68606
68667
|
state: info.state,
|
|
68607
|
-
event:
|
|
68668
|
+
event: sessionEventFor(info).event,
|
|
68608
68669
|
reason: info.reason,
|
|
68609
68670
|
detail: info.detail,
|
|
68610
68671
|
model: info.model,
|
|
@@ -68654,7 +68715,7 @@ ${entry.blockText}` : ""}`;
|
|
|
68654
68715
|
};
|
|
68655
68716
|
}),
|
|
68656
68717
|
eventsTotal: events.length,
|
|
68657
|
-
upstreamErrors:
|
|
68718
|
+
upstreamErrors: readTailLines2(upstreamErrorLogPath, UPSTREAM_ERROR_TAIL_BYTES),
|
|
68658
68719
|
claudeSessionId: info.claudeSessionId || null,
|
|
68659
68720
|
transcriptPath: info.transcriptPath || null,
|
|
68660
68721
|
sessionDir,
|
|
@@ -68708,7 +68769,7 @@ ${entry.blockText}` : ""}`;
|
|
|
68708
68769
|
entry.eventLogBytes += Buffer.byteLength(payload, "utf-8");
|
|
68709
68770
|
const capped = entry.eventLogBytes >= EVENT_LOG_LIMIT;
|
|
68710
68771
|
try {
|
|
68711
|
-
|
|
68772
|
+
appendFileSync7(entry.eventLogPath, capped ? `${payload}{"type":"claudish_truncated","limit_bytes":${EVENT_LOG_LIMIT}}
|
|
68712
68773
|
` : payload);
|
|
68713
68774
|
} catch {}
|
|
68714
68775
|
}
|
|
@@ -68725,7 +68786,7 @@ ${entry.blockText}` : ""}`;
|
|
|
68725
68786
|
wait: "closed",
|
|
68726
68787
|
since: entry.waitSince ?? at,
|
|
68727
68788
|
at,
|
|
68728
|
-
to:
|
|
68789
|
+
to: sessionEventFor(snap).event
|
|
68729
68790
|
});
|
|
68730
68791
|
entry.waitSince = null;
|
|
68731
68792
|
}
|
|
@@ -68737,7 +68798,7 @@ ${entry.blockText}` : ""}`;
|
|
|
68737
68798
|
`;
|
|
68738
68799
|
entry.waitLogBytes += Buffer.byteLength(payload, "utf-8");
|
|
68739
68800
|
try {
|
|
68740
|
-
|
|
68801
|
+
appendFileSync7(entry.waitLogPath, payload);
|
|
68741
68802
|
} catch (err) {
|
|
68742
68803
|
process.stderr.write(`[claudish] session ${entry.info.sessionId}: could not append to waits.jsonl: ` + `${err instanceof Error ? err.message : String(err)}
|
|
68743
68804
|
`);
|
|
@@ -68871,16 +68932,36 @@ var init_session_manager = __esm(() => {
|
|
|
68871
68932
|
SCREEN_READ_BYTES = 64 * 1024;
|
|
68872
68933
|
});
|
|
68873
68934
|
|
|
68874
|
-
// src/
|
|
68935
|
+
// src/mcp-session/types.ts
|
|
68875
68936
|
var init_types3 = () => {};
|
|
68876
68937
|
|
|
68877
|
-
// src/
|
|
68878
|
-
var
|
|
68938
|
+
// src/mcp-session/index.ts
|
|
68939
|
+
var init_mcp_session = __esm(() => {
|
|
68879
68940
|
init_scrollback_buffer();
|
|
68880
68941
|
init_session_manager();
|
|
68881
68942
|
init_types3();
|
|
68882
68943
|
});
|
|
68883
68944
|
|
|
68945
|
+
// src/mcp/nested-mode.ts
|
|
68946
|
+
var NESTED_MCP_TOOL_NAMES, NESTED_INSTRUCTIONS = `Claudish MCP server provides access to external AI models for one-shot calls.
|
|
68947
|
+
|
|
68948
|
+
## Nested mode \u2014 no sessions
|
|
68949
|
+
|
|
68950
|
+
This server runs inside a session that a claudish MCP server started (CLAUDISH_PANE_CHILD=1). One level of nesting is the limit, so these tools are not registered: create_session, team, send_input, get_output, cancel_session, list_sessions, get_diagnostics, capture_session, preflight, report_error. No channel notifications are sent.
|
|
68951
|
+
|
|
68952
|
+
- run_prompt or compare_models: a one-shot answer from another model.
|
|
68953
|
+
- list_models, search_models: find a model.
|
|
68954
|
+
|
|
68955
|
+
Do not start a claudish session another way: \`claudish -p\`, an interactive claudish or \`claudish team\` run from this session's shell exits 64 with "nested session refused".`;
|
|
68956
|
+
var init_nested_mode = __esm(() => {
|
|
68957
|
+
NESTED_MCP_TOOL_NAMES = [
|
|
68958
|
+
"run_prompt",
|
|
68959
|
+
"list_models",
|
|
68960
|
+
"search_models",
|
|
68961
|
+
"compare_models"
|
|
68962
|
+
];
|
|
68963
|
+
});
|
|
68964
|
+
|
|
68884
68965
|
// src/mcp/progress-heartbeat.ts
|
|
68885
68966
|
function isProgressToken(v) {
|
|
68886
68967
|
return typeof v === "string" || typeof v === "number" && Number.isFinite(v);
|
|
@@ -68958,10 +69039,243 @@ var init_progress_heartbeat = __esm(() => {
|
|
|
68958
69039
|
});
|
|
68959
69040
|
});
|
|
68960
69041
|
|
|
69042
|
+
// src/mcp/run-prompt-claude-code.ts
|
|
69043
|
+
import { spawn as spawn2 } from "child_process";
|
|
69044
|
+
import { mkdirSync as mkdirSync21, mkdtempSync as mkdtempSync3, rmSync as rmSync5, writeFileSync as writeFileSync22 } from "fs";
|
|
69045
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
69046
|
+
import { join as join49 } from "path";
|
|
69047
|
+
function claudeCodePrintArgv(model, systemPromptFile) {
|
|
69048
|
+
const head = [PRINT_FLAGS[0], "--model", model, ...PRINT_FLAGS.slice(1)];
|
|
69049
|
+
return systemPromptFile !== undefined ? [...head, "--system-prompt-file", systemPromptFile] : [...head, "--system-prompt", ""];
|
|
69050
|
+
}
|
|
69051
|
+
function claudeCodePrintEnv(parent) {
|
|
69052
|
+
const env = {};
|
|
69053
|
+
for (const [k, v] of Object.entries(parent)) {
|
|
69054
|
+
if (v === undefined || isStrippedFromChildEnv(k))
|
|
69055
|
+
continue;
|
|
69056
|
+
if (PRINT_CHILD_DROPPED_MARKERS.includes(k))
|
|
69057
|
+
continue;
|
|
69058
|
+
env[k] = v;
|
|
69059
|
+
}
|
|
69060
|
+
delete env.ANTHROPIC_API_KEY;
|
|
69061
|
+
delete env.ANTHROPIC_AUTH_TOKEN;
|
|
69062
|
+
delete env.ANTHROPIC_BASE_URL;
|
|
69063
|
+
return env;
|
|
69064
|
+
}
|
|
69065
|
+
function isFrame(v) {
|
|
69066
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
69067
|
+
}
|
|
69068
|
+
function parseJsonDocument(stdout) {
|
|
69069
|
+
const text = stdout.trim();
|
|
69070
|
+
if (!text)
|
|
69071
|
+
return;
|
|
69072
|
+
try {
|
|
69073
|
+
return JSON.parse(text);
|
|
69074
|
+
} catch {
|
|
69075
|
+
const lines = text.split(`
|
|
69076
|
+
`);
|
|
69077
|
+
for (let i = lines.length - 1;i >= 0; i--) {
|
|
69078
|
+
const line = lines[i].trim();
|
|
69079
|
+
if (!line.startsWith("[") && !line.startsWith("{"))
|
|
69080
|
+
continue;
|
|
69081
|
+
try {
|
|
69082
|
+
return JSON.parse(line);
|
|
69083
|
+
} catch {}
|
|
69084
|
+
}
|
|
69085
|
+
return;
|
|
69086
|
+
}
|
|
69087
|
+
}
|
|
69088
|
+
function num(v) {
|
|
69089
|
+
return typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
69090
|
+
}
|
|
69091
|
+
function parseClaudeCodePrintOutput(stdout) {
|
|
69092
|
+
const doc = parseJsonDocument(stdout);
|
|
69093
|
+
const frames = Array.isArray(doc) ? doc.filter(isFrame) : isFrame(doc) ? [doc] : [];
|
|
69094
|
+
let result;
|
|
69095
|
+
let init;
|
|
69096
|
+
for (const f of frames) {
|
|
69097
|
+
if (f.type === "result")
|
|
69098
|
+
result = f;
|
|
69099
|
+
else if (f.type === "system" && f.subtype === "init" && init === undefined)
|
|
69100
|
+
init = f;
|
|
69101
|
+
}
|
|
69102
|
+
if (!result)
|
|
69103
|
+
return null;
|
|
69104
|
+
const parsed = {
|
|
69105
|
+
result: typeof result.result === "string" ? result.result : "",
|
|
69106
|
+
isError: result.is_error === true,
|
|
69107
|
+
apiErrorStatus: typeof result.api_error_status === "number" ? result.api_error_status : null
|
|
69108
|
+
};
|
|
69109
|
+
if (typeof result.terminal_reason === "string")
|
|
69110
|
+
parsed.terminalReason = result.terminal_reason;
|
|
69111
|
+
if (isFrame(result.usage)) {
|
|
69112
|
+
const u = result.usage;
|
|
69113
|
+
parsed.usage = {
|
|
69114
|
+
input: num(u.input_tokens) + num(u.cache_creation_input_tokens) + num(u.cache_read_input_tokens),
|
|
69115
|
+
output: num(u.output_tokens)
|
|
69116
|
+
};
|
|
69117
|
+
}
|
|
69118
|
+
if (init && typeof init.apiKeySource === "string")
|
|
69119
|
+
parsed.apiKeySource = init.apiKeySource;
|
|
69120
|
+
return parsed;
|
|
69121
|
+
}
|
|
69122
|
+
function authFrom(apiKeySource) {
|
|
69123
|
+
if (apiKeySource === undefined)
|
|
69124
|
+
return;
|
|
69125
|
+
return apiKeySource === "none" ? "subscription" : apiKeySource;
|
|
69126
|
+
}
|
|
69127
|
+
function killGroup(proc) {
|
|
69128
|
+
const send = (sig) => {
|
|
69129
|
+
if (proc.exitCode !== null || proc.signalCode !== null)
|
|
69130
|
+
return;
|
|
69131
|
+
try {
|
|
69132
|
+
if (proc.pid !== undefined)
|
|
69133
|
+
process.kill(-proc.pid, sig);
|
|
69134
|
+
else
|
|
69135
|
+
proc.kill(sig);
|
|
69136
|
+
} catch {
|
|
69137
|
+
try {
|
|
69138
|
+
proc.kill(sig);
|
|
69139
|
+
} catch {}
|
|
69140
|
+
}
|
|
69141
|
+
};
|
|
69142
|
+
send("SIGTERM");
|
|
69143
|
+
const timer = setTimeout(() => send("SIGKILL"), KILL_GRACE_MS);
|
|
69144
|
+
timer.unref?.();
|
|
69145
|
+
}
|
|
69146
|
+
function stopAllClaudeCodePrintChildren() {
|
|
69147
|
+
for (const proc of inFlight2)
|
|
69148
|
+
killGroup(proc);
|
|
69149
|
+
}
|
|
69150
|
+
function stderrTail(stderr) {
|
|
69151
|
+
return sanitizeForReport(stderr.slice(-STDERR_TAIL_CHARS).trim());
|
|
69152
|
+
}
|
|
69153
|
+
async function runPromptViaClaudeCode(model, prompt, systemPrompt, opts = {}) {
|
|
69154
|
+
const signal = opts.signal;
|
|
69155
|
+
if (signal?.aborted)
|
|
69156
|
+
throw new Error("cancelled");
|
|
69157
|
+
const parentEnv = opts.parentEnv ?? process.env;
|
|
69158
|
+
let launch;
|
|
69159
|
+
try {
|
|
69160
|
+
launch = resolveClaudishLaunch(parentEnv);
|
|
69161
|
+
} catch (e) {
|
|
69162
|
+
throw new Error(`cannot start claudish (${parentEnv.CLAUDISH_BIN?.trim() || "claudish"}): ${e instanceof Error ? e.message : String(e)}`);
|
|
69163
|
+
}
|
|
69164
|
+
const root = mkdtempSync3(join49(tmpdir2(), "claudish-run-prompt-"));
|
|
69165
|
+
try {
|
|
69166
|
+
const cwd = join49(root, "cwd");
|
|
69167
|
+
mkdirSync21(cwd, { mode: 448 });
|
|
69168
|
+
let systemPromptFile;
|
|
69169
|
+
if (typeof systemPrompt === "string" && systemPrompt.length > 0) {
|
|
69170
|
+
systemPromptFile = join49(root, "system-prompt.txt");
|
|
69171
|
+
writeFileSync22(systemPromptFile, systemPrompt, { mode: 384 });
|
|
69172
|
+
}
|
|
69173
|
+
const argv = claudeCodePrintArgv(model, systemPromptFile);
|
|
69174
|
+
const outcome = await runChild(launch, argv, cwd, claudeCodePrintEnv(parentEnv), prompt, signal);
|
|
69175
|
+
if (signal?.aborted)
|
|
69176
|
+
throw new Error("cancelled");
|
|
69177
|
+
const parsed = parseClaudeCodePrintOutput(outcome.stdout);
|
|
69178
|
+
if (parsed === null) {
|
|
69179
|
+
const how = outcome.code !== null ? `exited ${outcome.code}` : `exited ${outcome.signal ?? "?"}`;
|
|
69180
|
+
const tail = stderrTail(outcome.stderr);
|
|
69181
|
+
const noFrame = outcome.code === 0 ? " with no result frame in its output" : "";
|
|
69182
|
+
throw new Error(`claudish -p ${how}${noFrame}${tail ? `: ${tail}` : ""}`);
|
|
69183
|
+
}
|
|
69184
|
+
if (parsed.isError) {
|
|
69185
|
+
const status = parsed.apiErrorStatus !== null ? ` (HTTP ${parsed.apiErrorStatus})` : "";
|
|
69186
|
+
throw new Error(`Claude Code: ${parsed.result || parsed.terminalReason || "error"}${status}`);
|
|
69187
|
+
}
|
|
69188
|
+
if (parsed.result === "")
|
|
69189
|
+
throw new Error("Model returned empty response");
|
|
69190
|
+
const answer = { content: parsed.result };
|
|
69191
|
+
if (parsed.usage)
|
|
69192
|
+
answer.usage = parsed.usage;
|
|
69193
|
+
const auth = authFrom(parsed.apiKeySource);
|
|
69194
|
+
if (auth !== undefined)
|
|
69195
|
+
answer.auth = auth;
|
|
69196
|
+
return answer;
|
|
69197
|
+
} finally {
|
|
69198
|
+
rmSync5(root, { recursive: true, force: true });
|
|
69199
|
+
}
|
|
69200
|
+
}
|
|
69201
|
+
function runChild(launch, argv, cwd, env, prompt, signal) {
|
|
69202
|
+
return new Promise((resolvePromise, reject) => {
|
|
69203
|
+
let proc;
|
|
69204
|
+
try {
|
|
69205
|
+
proc = spawn2(launch.command, [...launch.prefixArgs, ...argv], {
|
|
69206
|
+
cwd,
|
|
69207
|
+
env,
|
|
69208
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
69209
|
+
detached: true
|
|
69210
|
+
});
|
|
69211
|
+
} catch (e) {
|
|
69212
|
+
reject(startError(launch.command, e));
|
|
69213
|
+
return;
|
|
69214
|
+
}
|
|
69215
|
+
let stdout = "";
|
|
69216
|
+
let stderr = "";
|
|
69217
|
+
let settled = false;
|
|
69218
|
+
const onAbort = () => killGroup(proc);
|
|
69219
|
+
const finish = (fn) => {
|
|
69220
|
+
if (settled)
|
|
69221
|
+
return;
|
|
69222
|
+
settled = true;
|
|
69223
|
+
inFlight2.delete(proc);
|
|
69224
|
+
signal?.removeEventListener("abort", onAbort);
|
|
69225
|
+
fn();
|
|
69226
|
+
};
|
|
69227
|
+
proc.stdout?.setEncoding("utf8");
|
|
69228
|
+
proc.stderr?.setEncoding("utf8");
|
|
69229
|
+
proc.stdout?.on("data", (chunk) => {
|
|
69230
|
+
stdout += chunk;
|
|
69231
|
+
});
|
|
69232
|
+
proc.stderr?.on("data", (chunk) => {
|
|
69233
|
+
stderr += chunk;
|
|
69234
|
+
});
|
|
69235
|
+
proc.stdin?.on("error", () => {});
|
|
69236
|
+
proc.on("error", (e) => finish(() => reject(startError(launch.command, e))));
|
|
69237
|
+
proc.on("close", (code, sig) => finish(() => resolvePromise({ code, signal: sig, stdout, stderr })));
|
|
69238
|
+
inFlight2.add(proc);
|
|
69239
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
69240
|
+
if (signal?.aborted)
|
|
69241
|
+
onAbort();
|
|
69242
|
+
proc.stdin?.end(prompt);
|
|
69243
|
+
});
|
|
69244
|
+
}
|
|
69245
|
+
function startError(command, e) {
|
|
69246
|
+
const code = e?.code;
|
|
69247
|
+
const detail = typeof code === "string" ? code : e instanceof Error ? e.message : String(e ?? "unknown");
|
|
69248
|
+
return new Error(`cannot start claudish (${command}): ${detail}`);
|
|
69249
|
+
}
|
|
69250
|
+
var PRINT_FLAGS, PRINT_CHILD_DROPPED_MARKERS, inFlight2, KILL_GRACE_MS = 5000, STDERR_TAIL_CHARS = 2000;
|
|
69251
|
+
var init_run_prompt_claude_code = __esm(() => {
|
|
69252
|
+
init_config();
|
|
69253
|
+
init_child_env();
|
|
69254
|
+
init_pane_launch();
|
|
69255
|
+
init_redact();
|
|
69256
|
+
PRINT_FLAGS = [
|
|
69257
|
+
"-p",
|
|
69258
|
+
"--output-format",
|
|
69259
|
+
"json",
|
|
69260
|
+
"--tools",
|
|
69261
|
+
"",
|
|
69262
|
+
"--strict-mcp-config",
|
|
69263
|
+
"--setting-sources",
|
|
69264
|
+
"",
|
|
69265
|
+
"--disable-slash-commands",
|
|
69266
|
+
"--no-session-persistence"
|
|
69267
|
+
];
|
|
69268
|
+
PRINT_CHILD_DROPPED_MARKERS = [
|
|
69269
|
+
...PANE_LAUNCH_VARS,
|
|
69270
|
+
ENV.CLAUDISH_PANE_CHILD
|
|
69271
|
+
];
|
|
69272
|
+
inFlight2 = new Set;
|
|
69273
|
+
});
|
|
69274
|
+
|
|
68961
69275
|
// src/mcp-server.ts
|
|
68962
|
-
import { existsSync as existsSync32, mkdirSync as
|
|
69276
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync22, readFileSync as readFileSync31, readdirSync as readdirSync10, writeFileSync as writeFileSync23 } from "fs";
|
|
68963
69277
|
import { homedir as homedir33 } from "os";
|
|
68964
|
-
import { dirname as dirname14, join as
|
|
69278
|
+
import { dirname as dirname14, join as join50, resolve as resolve6 } from "path";
|
|
68965
69279
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
68966
69280
|
async function loadAllModels(forceRefresh = false) {
|
|
68967
69281
|
if (!forceRefresh && existsSync32(OPENROUTER_MODELS_CACHE_PATH)) {
|
|
@@ -68980,8 +69294,8 @@ async function loadAllModels(forceRefresh = false) {
|
|
|
68980
69294
|
throw new Error(`API returned ${response.status}`);
|
|
68981
69295
|
const data = await response.json();
|
|
68982
69296
|
const models = data.data || [];
|
|
68983
|
-
|
|
68984
|
-
|
|
69297
|
+
mkdirSync22(CLAUDISH_CACHE_DIR, { recursive: true });
|
|
69298
|
+
writeFileSync23(OPENROUTER_MODELS_CACHE_PATH, JSON.stringify({ lastUpdated: new Date().toISOString(), models }), "utf-8");
|
|
68985
69299
|
return models;
|
|
68986
69300
|
} catch {
|
|
68987
69301
|
if (existsSync32(OPENROUTER_MODELS_CACHE_PATH)) {
|
|
@@ -69037,12 +69351,11 @@ function parseAnthropicSse(raw) {
|
|
|
69037
69351
|
}
|
|
69038
69352
|
return { text, usage: hasUsage ? { input: inputTokens, output: outputTokens } : undefined };
|
|
69039
69353
|
}
|
|
69040
|
-
async function runPromptViaProxy(model, prompt, systemPrompt
|
|
69354
|
+
async function runPromptViaProxy(model, prompt, systemPrompt) {
|
|
69041
69355
|
const proxy = await getProxy();
|
|
69042
69356
|
const body = {
|
|
69043
69357
|
model,
|
|
69044
69358
|
messages: [{ role: "user", content: prompt }],
|
|
69045
|
-
max_tokens: maxTokens || 4096,
|
|
69046
69359
|
stream: true
|
|
69047
69360
|
};
|
|
69048
69361
|
if (systemPrompt) {
|
|
@@ -69064,6 +69377,26 @@ async function runPromptViaProxy(model, prompt, systemPrompt, maxTokens) {
|
|
|
69064
69377
|
}
|
|
69065
69378
|
return { content: parsed.text, usage: parsed.usage };
|
|
69066
69379
|
}
|
|
69380
|
+
async function runPrompt(model, prompt, systemPrompt, signal) {
|
|
69381
|
+
if (nativeRouteFor(model) !== null) {
|
|
69382
|
+
return runPromptViaClaudeCode(model, prompt, systemPrompt, { signal });
|
|
69383
|
+
}
|
|
69384
|
+
return runPromptViaProxy(model, prompt, systemPrompt);
|
|
69385
|
+
}
|
|
69386
|
+
function formatRunPromptResult(result) {
|
|
69387
|
+
const footer = [];
|
|
69388
|
+
if (result.usage) {
|
|
69389
|
+
footer.push(`Tokens: ${result.usage.input} input, ${result.usage.output} output`);
|
|
69390
|
+
}
|
|
69391
|
+
if (result.auth !== undefined) {
|
|
69392
|
+
footer.push(result.auth === "subscription" ? "Auth: Claude Code login (subscription)" : `Auth: ${result.auth}`);
|
|
69393
|
+
}
|
|
69394
|
+
return footer.length > 0 ? `${result.content}
|
|
69395
|
+
|
|
69396
|
+
---
|
|
69397
|
+
${footer.join(`
|
|
69398
|
+
`)}` : result.content;
|
|
69399
|
+
}
|
|
69067
69400
|
function fuzzyScore(text, query) {
|
|
69068
69401
|
const lowerText = text.toLowerCase();
|
|
69069
69402
|
const lowerQuery = query.toLowerCase();
|
|
@@ -69278,8 +69611,9 @@ async function teamContractVerb(mode, args) {
|
|
|
69278
69611
|
return contractErrorAnswer(e);
|
|
69279
69612
|
}
|
|
69280
69613
|
}
|
|
69281
|
-
function defineTools(sessionManager,
|
|
69614
|
+
function defineTools(sessionManager, nested) {
|
|
69282
69615
|
const tools = [];
|
|
69616
|
+
const reportHint = (text) => nested ? "" : text;
|
|
69283
69617
|
function withOpFailureContext(message, subject) {
|
|
69284
69618
|
const block = renderOpFailureBlock(subject);
|
|
69285
69619
|
return block.length === 0 ? message : `${message}
|
|
@@ -69289,43 +69623,35 @@ ${block.join(`
|
|
|
69289
69623
|
}
|
|
69290
69624
|
tools.push({
|
|
69291
69625
|
name: "run_prompt",
|
|
69292
|
-
description: "
|
|
69626
|
+
description: "One quick prompt, straight to one model's API: a single request and its answer. No " + "Claude Code session, no tools, no files, no conversation state \u2014 this is not subagent " + "work. For a task that needs tools, files or more than one turn, use create_session " + "(one model) or team (several models). Non-Claude models (Kimi, GLM, Qwen, MiniMax, " + "Gemini, GPT, Grok, \u2026) go through claudish's routing straight to the provider's API. " + "A Claude model name (claude-*, opus, sonnet, haiku) runs as one Claude Code " + "print-mode call on the user's own Claude Code login, with tools, MCP servers and " + "settings off.",
|
|
69293
69627
|
inputSchema: {
|
|
69294
69628
|
type: "object",
|
|
69295
69629
|
properties: {
|
|
69296
69630
|
model: {
|
|
69297
69631
|
type: "string",
|
|
69298
|
-
description: "Model name or
|
|
69632
|
+
description: "Model name or model spec. A bare name auto-routes to the best provider; " + "'provider@model' pins the provider (e.g. 'google@gemini-4-argon', " + "'or@x-ai/grok-4.7'). A bare Claude name (claude-*, opus, sonnet, haiku) runs on " + "Claude Code's own login."
|
|
69299
69633
|
},
|
|
69300
69634
|
prompt: { type: "string", description: "The prompt to send to the model" },
|
|
69301
|
-
system_prompt: { type: "string", description: "Optional system prompt" }
|
|
69302
|
-
max_tokens: { type: "number", description: "Maximum tokens in response (default: 4096)" }
|
|
69635
|
+
system_prompt: { type: "string", description: "Optional system prompt" }
|
|
69303
69636
|
},
|
|
69304
69637
|
required: ["model", "prompt"]
|
|
69305
69638
|
},
|
|
69306
69639
|
group: "low-level",
|
|
69307
69640
|
heartbeat: true,
|
|
69308
|
-
handler: async (args) => {
|
|
69641
|
+
handler: async (args, ctx) => {
|
|
69309
69642
|
try {
|
|
69310
|
-
const result = await
|
|
69311
|
-
|
|
69312
|
-
if (result.usage) {
|
|
69313
|
-
response += `
|
|
69314
|
-
|
|
69315
|
-
---
|
|
69316
|
-
Tokens: ${result.usage.input} input, ${result.usage.output} output`;
|
|
69317
|
-
}
|
|
69318
|
-
return { content: [{ type: "text", text: response }] };
|
|
69643
|
+
const result = await runPrompt(args.model, args.prompt, args.system_prompt, ctx.signal);
|
|
69644
|
+
return { content: [{ type: "text", text: formatRunPromptResult(result) }] };
|
|
69319
69645
|
} catch (error) {
|
|
69320
69646
|
const errMsg = error instanceof Error ? error.message : String(error);
|
|
69321
69647
|
return {
|
|
69322
69648
|
content: [
|
|
69323
69649
|
{
|
|
69324
69650
|
type: "text",
|
|
69325
|
-
text: withOpFailureContext(`Error: ${errMsg}
|
|
69651
|
+
text: withOpFailureContext(`Error: ${errMsg}${reportHint(`
|
|
69326
69652
|
|
|
69327
69653
|
---
|
|
69328
|
-
**To report this error**, use the \`report_error\` tool with \`error_type: "provider_failure"\` and \`model: "${args.model}"
|
|
69654
|
+
**To report this error**, use the \`report_error\` tool with \`error_type: "provider_failure"\` and \`model: "${args.model}"\`.`)}`, `while routing ${args.model}`)
|
|
69329
69655
|
}
|
|
69330
69656
|
],
|
|
69331
69657
|
isError: true
|
|
@@ -69467,35 +69793,30 @@ Use with: run_prompt(model="${suggested}", prompt="your prompt")`;
|
|
|
69467
69793
|
});
|
|
69468
69794
|
tools.push({
|
|
69469
69795
|
name: "compare_models",
|
|
69470
|
-
description: "
|
|
69796
|
+
description: "DEBUG. Send the same single prompt to several models, one after another, and show " + "their answers side by side \u2014 to check that routes answer or to eyeball raw answers. " + "Each model gets exactly what run_prompt sends: one request, no tools, no Claude Code " + "session. Not for real work: use team for a blind-judged multi-model run, or " + "create_session for one model doing a task.",
|
|
69471
69797
|
inputSchema: {
|
|
69472
69798
|
type: "object",
|
|
69473
69799
|
properties: {
|
|
69474
69800
|
models: {
|
|
69475
69801
|
type: "array",
|
|
69476
69802
|
items: { type: "string" },
|
|
69477
|
-
description: "List of model
|
|
69803
|
+
description: "List of model names or model specs to compare, in the order to run them"
|
|
69478
69804
|
},
|
|
69479
69805
|
prompt: { type: "string", description: "The prompt to send to all models" },
|
|
69480
|
-
system_prompt: { type: "string", description: "Optional system prompt" }
|
|
69481
|
-
max_tokens: {
|
|
69482
|
-
type: "number",
|
|
69483
|
-
description: "Maximum tokens in response (omit to let model decide)"
|
|
69484
|
-
}
|
|
69806
|
+
system_prompt: { type: "string", description: "Optional system prompt" }
|
|
69485
69807
|
},
|
|
69486
69808
|
required: ["models", "prompt"]
|
|
69487
69809
|
},
|
|
69488
|
-
group: "
|
|
69810
|
+
group: "debug",
|
|
69489
69811
|
heartbeat: true,
|
|
69490
69812
|
handler: async (args, ctx) => {
|
|
69491
69813
|
const modelIds = args.models;
|
|
69492
69814
|
const prompt = args.prompt;
|
|
69493
69815
|
const systemPrompt = args.system_prompt;
|
|
69494
|
-
const maxTokens = args.max_tokens;
|
|
69495
69816
|
const results = [];
|
|
69496
69817
|
for (const model of modelIds) {
|
|
69497
69818
|
try {
|
|
69498
|
-
const result = await
|
|
69819
|
+
const result = await runPrompt(model, prompt, systemPrompt, ctx.signal);
|
|
69499
69820
|
results.push({ model, response: result.content, tokens: result.usage });
|
|
69500
69821
|
} catch (error) {
|
|
69501
69822
|
results.push({
|
|
@@ -69536,7 +69857,7 @@ Use with: run_prompt(model="${suggested}", prompt="your prompt")`;
|
|
|
69536
69857
|
}
|
|
69537
69858
|
const failed = results.filter((r) => r.error);
|
|
69538
69859
|
if (failed.length > 0) {
|
|
69539
|
-
output += '---\n**To report failed model(s)**, use the `report_error` tool with `error_type: "provider_failure"` and the model ID(s) above.\n';
|
|
69860
|
+
output += reportHint('---\n**To report failed model(s)**, use the `report_error` tool with `error_type: "provider_failure"` and the model ID(s) above.\n');
|
|
69540
69861
|
}
|
|
69541
69862
|
return { content: [{ type: "text", text: output }] };
|
|
69542
69863
|
}
|
|
@@ -69749,28 +70070,18 @@ Use with: run_prompt(model="${suggested}", prompt="your prompt")`;
|
|
|
69749
70070
|
const minOutputBytes = args.min_output_bytes;
|
|
69750
70071
|
const childFlags = buildChildClaudeFlags(args.agent, args.claude_flags) ?? [];
|
|
69751
70072
|
const resolved = validateSessionPath(path);
|
|
69752
|
-
const teamSessionId = resolved.split("/").filter(Boolean).pop() ?? "team";
|
|
69753
|
-
const teamCreatedAt = new Date().toISOString();
|
|
69754
70073
|
const runOpts = {
|
|
69755
70074
|
requirePattern,
|
|
69756
70075
|
minOutputBytes,
|
|
69757
70076
|
claudeFlags: childFlags,
|
|
69758
70077
|
onProgress: (u) => {
|
|
69759
70078
|
ctx.reportProgress(`team: ${u.phase}`);
|
|
69760
|
-
notifyChannel({
|
|
69761
|
-
content: u.rendered,
|
|
69762
|
-
sessionId: teamSessionId,
|
|
69763
|
-
event: u.phase === "settled" ? u.allFailed ? "failed" : "completed" : "running",
|
|
69764
|
-
model: "team",
|
|
69765
|
-
elapsedSeconds: (Date.now() - Date.parse(teamCreatedAt)) / 1000,
|
|
69766
|
-
createdAt: teamCreatedAt
|
|
69767
|
-
});
|
|
69768
70079
|
}
|
|
69769
70080
|
};
|
|
69770
70081
|
const promptText = () => {
|
|
69771
70082
|
if (input !== undefined)
|
|
69772
70083
|
return input;
|
|
69773
|
-
const existing =
|
|
70084
|
+
const existing = join50(resolved, "input.md");
|
|
69774
70085
|
return existsSync32(existing) ? readFileSync31(existing, "utf-8") : undefined;
|
|
69775
70086
|
};
|
|
69776
70087
|
switch (mode) {
|
|
@@ -69929,16 +70240,16 @@ Use with: run_prompt(model="${suggested}", prompt="your prompt")`;
|
|
|
69929
70240
|
const sp = session_path;
|
|
69930
70241
|
for (const file of ["status.json", "manifest.json", "input.md"]) {
|
|
69931
70242
|
try {
|
|
69932
|
-
sessionData[file] = readFileSync31(
|
|
70243
|
+
sessionData[file] = readFileSync31(join50(sp, file), "utf-8");
|
|
69933
70244
|
} catch {}
|
|
69934
70245
|
}
|
|
69935
70246
|
try {
|
|
69936
|
-
const errorDir =
|
|
70247
|
+
const errorDir = join50(sp, "errors");
|
|
69937
70248
|
if (existsSync32(errorDir)) {
|
|
69938
70249
|
for (const f of readdirSync10(errorDir)) {
|
|
69939
70250
|
if (f.endsWith(".log")) {
|
|
69940
70251
|
try {
|
|
69941
|
-
sessionData[`errors/${f}`] = readFileSync31(
|
|
70252
|
+
sessionData[`errors/${f}`] = readFileSync31(join50(errorDir, f), "utf-8");
|
|
69942
70253
|
} catch {}
|
|
69943
70254
|
}
|
|
69944
70255
|
}
|
|
@@ -69948,7 +70259,7 @@ Use with: run_prompt(model="${suggested}", prompt="your prompt")`;
|
|
|
69948
70259
|
for (const f of readdirSync10(sp)) {
|
|
69949
70260
|
if (f.startsWith("response-") && f.endsWith(".md")) {
|
|
69950
70261
|
try {
|
|
69951
|
-
const content = readFileSync31(
|
|
70262
|
+
const content = readFileSync31(join50(sp, f), "utf-8");
|
|
69952
70263
|
sessionData[f] = content.slice(0, 200) + (content.length > 200 ? "... (truncated)" : "");
|
|
69953
70264
|
} catch {}
|
|
69954
70265
|
}
|
|
@@ -69957,7 +70268,7 @@ Use with: run_prompt(model="${suggested}", prompt="your prompt")`;
|
|
|
69957
70268
|
}
|
|
69958
70269
|
let version = "unknown";
|
|
69959
70270
|
try {
|
|
69960
|
-
const pkgPath =
|
|
70271
|
+
const pkgPath = join50(__dirname3, "../package.json");
|
|
69961
70272
|
if (existsSync32(pkgPath)) {
|
|
69962
70273
|
version = JSON.parse(readFileSync31(pkgPath, "utf-8")).version;
|
|
69963
70274
|
}
|
|
@@ -70037,7 +70348,7 @@ Report manually at https://github.com/anthropics/claudish/issues${autoSendHint}`
|
|
|
70037
70348
|
});
|
|
70038
70349
|
tools.push({
|
|
70039
70350
|
name: "create_session",
|
|
70040
|
-
description: "Create a new claudish proxy session for an external model: an interactive Claude Code running " + "it in its own headless magmux pane. Returns at once with state STARTING;
|
|
70351
|
+
description: "Create a new claudish proxy session for an external model: an interactive Claude Code running " + "it in its own headless magmux pane. Returns at once with state STARTING; nothing is " + "pushed while it runs: poll list_sessions (about once every 10 s) for its state, then " + "call get_output once it is COMPLETED. With a prompt it is one-shot (it ends when that turn " + "settles); without one it is interactive and waits for send_input. Needs magmux >= 0.14.0 " + "(darwin and linux).",
|
|
70041
70352
|
inputSchema: {
|
|
70042
70353
|
type: "object",
|
|
70043
70354
|
properties: {
|
|
@@ -70070,7 +70381,7 @@ Report manually at https://github.com/anthropics/claudish/issues${autoSendHint}`
|
|
|
70070
70381
|
},
|
|
70071
70382
|
required: ["model"]
|
|
70072
70383
|
},
|
|
70073
|
-
group: "
|
|
70384
|
+
group: "session",
|
|
70074
70385
|
handler: async (args) => {
|
|
70075
70386
|
try {
|
|
70076
70387
|
const claudishFlags = buildChildClaudeFlags(args.agent, args.claude_flags) ?? [];
|
|
@@ -70138,7 +70449,7 @@ Report manually at https://github.com/anthropics/claudish/issues${autoSendHint}`
|
|
|
70138
70449
|
},
|
|
70139
70450
|
required: ["session_id", "text"]
|
|
70140
70451
|
},
|
|
70141
|
-
group: "
|
|
70452
|
+
group: "session",
|
|
70142
70453
|
handler: async (args) => {
|
|
70143
70454
|
const result = sessionManager.sendInput(args.session_id, args.text);
|
|
70144
70455
|
return {
|
|
@@ -70148,7 +70459,7 @@ Report manually at https://github.com/anthropics/claudish/issues${autoSendHint}`
|
|
|
70148
70459
|
});
|
|
70149
70460
|
tools.push({
|
|
70150
70461
|
name: "get_output",
|
|
70151
|
-
description: "Get a session's answer prose (each settled turn's assistant text, from its transcript). " + "Call
|
|
70462
|
+
description: "Get a session's answer prose (each settled turn's assistant text, from its transcript). " + "Call once list_sessions shows the session COMPLETED (or between turns of an " + "interactive session).",
|
|
70152
70463
|
inputSchema: {
|
|
70153
70464
|
type: "object",
|
|
70154
70465
|
properties: {
|
|
@@ -70160,7 +70471,7 @@ Report manually at https://github.com/anthropics/claudish/issues${autoSendHint}`
|
|
|
70160
70471
|
},
|
|
70161
70472
|
required: ["session_id"]
|
|
70162
70473
|
},
|
|
70163
|
-
group: "
|
|
70474
|
+
group: "session",
|
|
70164
70475
|
handler: async (args) => {
|
|
70165
70476
|
try {
|
|
70166
70477
|
const output = sessionManager.getOutput(args.session_id, args.tail_lines);
|
|
@@ -70190,7 +70501,7 @@ Report manually at https://github.com/anthropics/claudish/issues${autoSendHint}`
|
|
|
70190
70501
|
},
|
|
70191
70502
|
required: ["session_id"]
|
|
70192
70503
|
},
|
|
70193
|
-
group: "
|
|
70504
|
+
group: "session",
|
|
70194
70505
|
handler: async (args) => {
|
|
70195
70506
|
try {
|
|
70196
70507
|
const sessionId = optionalString(args.session_id, "session_id");
|
|
@@ -70204,7 +70515,7 @@ Report manually at https://github.com/anthropics/claudish/issues${autoSendHint}`
|
|
|
70204
70515
|
});
|
|
70205
70516
|
tools.push({
|
|
70206
70517
|
name: "list_sessions",
|
|
70207
|
-
description: "List
|
|
70518
|
+
description: "List sessions: {contract_version, capabilities, sessions}. Optionally include " + "finished ones. Each row reports `state`, `activity` and `idle_seconds`: how long since " + "the session's screen or transcript last changed. Nothing kills a session for being " + "idle \u2014 a child inside a long Bash call is silent and working \u2014 so this is yours to " + "judge against the task you set, and `cancel_session` is yours to call if the answer is no. " + "A failed row's `reason_detail` is one line saying why (for api_error, the provider's " + "own error message); it is null while the session is live and on COMPLETED.",
|
|
70208
70519
|
inputSchema: {
|
|
70209
70520
|
type: "object",
|
|
70210
70521
|
properties: {
|
|
@@ -70214,7 +70525,7 @@ Report manually at https://github.com/anthropics/claudish/issues${autoSendHint}`
|
|
|
70214
70525
|
}
|
|
70215
70526
|
}
|
|
70216
70527
|
},
|
|
70217
|
-
group: "
|
|
70528
|
+
group: "session",
|
|
70218
70529
|
handler: async (args) => {
|
|
70219
70530
|
try {
|
|
70220
70531
|
const includeCompleted = optionalBoolean(args.include_completed, "include_completed");
|
|
@@ -70229,7 +70540,7 @@ Report manually at https://github.com/anthropics/claudish/issues${autoSendHint}`
|
|
|
70229
70540
|
});
|
|
70230
70541
|
tools.push({
|
|
70231
70542
|
name: "get_diagnostics",
|
|
70232
|
-
description: "Explain what a
|
|
70543
|
+
description: "Explain what a session actually did \u2014 its final screen, upstream error bodies, " + "the recent state records, anomalies, the resolved model chain, accounting, and the paths " + "to the full records (transcript included). Call this FIRST whenever a session fails, times " + "out, or completes with empty or surprising output; it needs no re-run and no debug flag. " + "`idleSeconds` reports how long since the screen or transcript last changed, and is null " + "once the session is no longer live. It is information, never a verdict: claudish does " + "not terminate a session for silence.",
|
|
70233
70544
|
inputSchema: {
|
|
70234
70545
|
type: "object",
|
|
70235
70546
|
properties: {
|
|
@@ -70241,7 +70552,7 @@ Report manually at https://github.com/anthropics/claudish/issues${autoSendHint}`
|
|
|
70241
70552
|
},
|
|
70242
70553
|
required: ["session_id"]
|
|
70243
70554
|
},
|
|
70244
|
-
group: "
|
|
70555
|
+
group: "session",
|
|
70245
70556
|
handler: async (args) => {
|
|
70246
70557
|
try {
|
|
70247
70558
|
const diagnostics = sessionManager.getDiagnostics(args.session_id, args.event_limit);
|
|
@@ -70279,7 +70590,7 @@ Report manually at https://github.com/anthropics/claudish/issues${autoSendHint}`
|
|
|
70279
70590
|
},
|
|
70280
70591
|
required: ["session_id"]
|
|
70281
70592
|
},
|
|
70282
|
-
group: "
|
|
70593
|
+
group: "session",
|
|
70283
70594
|
handler: async (args) => {
|
|
70284
70595
|
try {
|
|
70285
70596
|
const sessionId = optionalString(args.session_id, "session_id");
|
|
@@ -70301,79 +70612,38 @@ function resolveToolGroups(mode) {
|
|
|
70301
70612
|
return new Set(["low-level"]);
|
|
70302
70613
|
case "agentic":
|
|
70303
70614
|
return new Set(["agentic"]);
|
|
70304
|
-
case "
|
|
70305
|
-
return new Set(["
|
|
70615
|
+
case "session":
|
|
70616
|
+
return new Set(["session"]);
|
|
70617
|
+
case "debug":
|
|
70618
|
+
return new Set(["debug"]);
|
|
70306
70619
|
default:
|
|
70307
|
-
return new Set(["low-level", "agentic", "
|
|
70620
|
+
return new Set(["low-level", "agentic", "session", "debug"]);
|
|
70308
70621
|
}
|
|
70309
70622
|
}
|
|
70310
|
-
function
|
|
70311
|
-
|
|
70623
|
+
function unknownToolModeWarning(mode) {
|
|
70624
|
+
if (TOOL_MODES.includes(mode))
|
|
70625
|
+
return;
|
|
70626
|
+
const renamed = mode === "channel" ? " (`channel` was renamed to `session`)" : "";
|
|
70627
|
+
return `[claudish] CLAUDISH_MCP_TOOLS=${JSON.stringify(mode)} is not a tool mode${renamed}; selecting all tools. Valid values: ${TOOL_MODES.join(", ")}`;
|
|
70312
70628
|
}
|
|
70313
70629
|
async function main() {
|
|
70314
70630
|
const toolMode = (process.env.CLAUDISH_MCP_TOOLS || "all").toLowerCase();
|
|
70631
|
+
const nested = inMcpSession();
|
|
70315
70632
|
const enabledGroups = resolveToolGroups(toolMode);
|
|
70316
|
-
const
|
|
70317
|
-
|
|
70318
|
-
|
|
70319
|
-
|
|
70320
|
-
},
|
|
70321
|
-
instructions: INSTRUCTIONS
|
|
70322
|
-
});
|
|
70323
|
-
const sessionManager = new SessionManager
|
|
70324
|
-
onStateChange: wrapStateChange((sessionId, event) => {
|
|
70325
|
-
const notificationContent = event.type === "failed" || event.type === "timeout" ? `${event.content}
|
|
70326
|
-
|
|
70327
|
-
Call get_diagnostics with session_id: "${sessionId}" for the final screen, the upstream error bodies and the transcript path. To report it, use the report_error tool with error_type: "provider_failure" and model: "${event.model}".` : event.content;
|
|
70328
|
-
const result = server.notification({
|
|
70329
|
-
method: "notifications/claude/channel",
|
|
70330
|
-
params: {
|
|
70331
|
-
content: notificationContent,
|
|
70332
|
-
meta: {
|
|
70333
|
-
session_id: sessionId,
|
|
70334
|
-
event: event.type,
|
|
70335
|
-
model: event.model,
|
|
70336
|
-
elapsed_seconds: String(event.elapsedSeconds),
|
|
70337
|
-
task_id: sessionId,
|
|
70338
|
-
status: mapEventToTaskStatus(event.type),
|
|
70339
|
-
created_at: event.createdAt,
|
|
70340
|
-
last_updated_at: new Date().toISOString(),
|
|
70341
|
-
...event.extraMeta
|
|
70342
|
-
}
|
|
70343
|
-
}
|
|
70344
|
-
});
|
|
70345
|
-
watchNotificationResult(result, { sessionId, eventType: event.type });
|
|
70346
|
-
})
|
|
70347
|
-
});
|
|
70348
|
-
const channelEnabled = enabledGroups.has("channel");
|
|
70349
|
-
const notifyChannel = (p) => {
|
|
70350
|
-
if (!channelEnabled)
|
|
70351
|
-
return;
|
|
70352
|
-
try {
|
|
70353
|
-
const result = server.notification({
|
|
70354
|
-
method: "notifications/claude/channel",
|
|
70355
|
-
params: {
|
|
70356
|
-
content: p.content,
|
|
70357
|
-
meta: {
|
|
70358
|
-
session_id: p.sessionId,
|
|
70359
|
-
event: p.event,
|
|
70360
|
-
model: p.model,
|
|
70361
|
-
elapsed_seconds: String(Math.round(p.elapsedSeconds)),
|
|
70362
|
-
task_id: p.sessionId,
|
|
70363
|
-
status: mapEventToTaskStatus(p.event),
|
|
70364
|
-
created_at: p.createdAt,
|
|
70365
|
-
last_updated_at: new Date().toISOString()
|
|
70366
|
-
}
|
|
70367
|
-
}
|
|
70368
|
-
});
|
|
70369
|
-
watchNotificationResult(result, { sessionId: p.sessionId, eventType: p.event });
|
|
70370
|
-
} catch {}
|
|
70371
|
-
};
|
|
70633
|
+
const toolModeWarning = unknownToolModeWarning(toolMode);
|
|
70634
|
+
if (toolModeWarning)
|
|
70635
|
+
console.error(toolModeWarning);
|
|
70636
|
+
const server = new Server({ name: "claudish", version: VERSION }, {
|
|
70637
|
+
capabilities: { tools: {} },
|
|
70638
|
+
instructions: nested ? NESTED_INSTRUCTIONS : INSTRUCTIONS
|
|
70639
|
+
});
|
|
70640
|
+
const sessionManager = new SessionManager;
|
|
70372
70641
|
const progressIntervalMs = resolveProgressIntervalMs();
|
|
70373
|
-
const allTools = defineTools(sessionManager,
|
|
70374
|
-
const
|
|
70642
|
+
const allTools = defineTools(sessionManager, nested);
|
|
70643
|
+
const nestedNames = NESTED_MCP_TOOL_NAMES;
|
|
70644
|
+
const enabledTools = allTools.filter((t) => enabledGroups.has(t.group) && (!nested || nestedNames.includes(t.name)));
|
|
70375
70645
|
const toolMap = new Map(enabledTools.map((t) => [t.name, t]));
|
|
70376
|
-
console.error(`[claudish] MCP server started (tools: ${toolMode}, ${enabledTools.length} tools)`);
|
|
70646
|
+
console.error(`[claudish] MCP server started (tools: ${nested ? "nested" : toolMode}, ${enabledTools.length} tools)`);
|
|
70377
70647
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
70378
70648
|
tools: enabledTools.map((t) => ({
|
|
70379
70649
|
name: t.name,
|
|
@@ -70397,7 +70667,8 @@ Call get_diagnostics with session_id: "${sessionId}" for the final screen, the u
|
|
|
70397
70667
|
send: (frame) => extra.sendNotification({ method: "notifications/progress", params: frame })
|
|
70398
70668
|
}) : NOOP_HEARTBEAT;
|
|
70399
70669
|
const ctx = {
|
|
70400
|
-
reportProgress: (message) => heartbeat.tick(message)
|
|
70670
|
+
reportProgress: (message) => heartbeat.tick(message),
|
|
70671
|
+
signal: extra.signal
|
|
70401
70672
|
};
|
|
70402
70673
|
try {
|
|
70403
70674
|
return await tool.handler(args ?? {}, ctx);
|
|
@@ -70416,7 +70687,6 @@ Call get_diagnostics with session_id: "${sessionId}" for the final screen, the u
|
|
|
70416
70687
|
}
|
|
70417
70688
|
});
|
|
70418
70689
|
const transport = new StdioServerTransport;
|
|
70419
|
-
installWireTap();
|
|
70420
70690
|
await server.connect(transport);
|
|
70421
70691
|
installMcpShutdown(sessionManager);
|
|
70422
70692
|
ensureSwept(sockRootFor()).catch(() => {
|
|
@@ -70425,6 +70695,7 @@ Call get_diagnostics with session_id: "${sessionId}" for the final screen, the u
|
|
|
70425
70695
|
}
|
|
70426
70696
|
function installMcpShutdown(sessionManager) {
|
|
70427
70697
|
const before = async () => {
|
|
70698
|
+
stopAllClaudeCodePrintChildren();
|
|
70428
70699
|
await Promise.allSettled([shutdownAllTeamRuns(), sessionManager.shutdownAll()]);
|
|
70429
70700
|
};
|
|
70430
70701
|
installPaneShutdownHooks({ stdin: true, before });
|
|
@@ -70435,50 +70706,45 @@ function startMcpServer() {
|
|
|
70435
70706
|
process.exit(1);
|
|
70436
70707
|
});
|
|
70437
70708
|
}
|
|
70438
|
-
var import_dotenv2, __filename3, __dirname3, CLAUDISH_CACHE_DIR, OPENROUTER_MODELS_CACHE_PATH, CACHE_MAX_AGE_DAYS = 2, INSTRUCTIONS = `Claudish MCP server
|
|
70709
|
+
var import_dotenv2, __filename3, __dirname3, CLAUDISH_CACHE_DIR, OPENROUTER_MODELS_CACHE_PATH, CACHE_MAX_AGE_DAYS = 2, INSTRUCTIONS = `Claudish MCP server gives you access to external AI models (OpenRouter, Ollama, LM Studio and every claudish provider), and to Claude models on the user's own Claude Code login.
|
|
70439
70710
|
|
|
70440
|
-
##
|
|
70711
|
+
## Which tool
|
|
70441
70712
|
|
|
70442
|
-
|
|
70713
|
+
- run_prompt: one quick prompt to one model's API. One request, one answer; no tools, no files, no session.
|
|
70714
|
+
- create_session: one model doing a task as a full Claude Code session (tools, files, several turns).
|
|
70715
|
+
- team: several models on the same task, each a full Claude Code session, with optional blind judging.
|
|
70443
70716
|
|
|
70444
|
-
|
|
70717
|
+
## Sessions
|
|
70445
70718
|
|
|
70446
|
-
|
|
70447
|
-
- tool_executing: The model is using a tool (Read, Write, Bash, etc.). Carries tool and tool_count.
|
|
70448
|
-
- input_required (event waiting_for_input): The session waits for send_input: an interactive session between turns, or a session stopped on a question (meta activity "AskUserQuestion"). A send declines a question and becomes the next prompt.
|
|
70449
|
-
- input_required (event awaiting_permission): A permission or plan-approval dialog is open. A send declines it and becomes the next prompt.
|
|
70450
|
-
- completed: The session finished successfully. Call get_output to retrieve the full output.
|
|
70451
|
-
- failed: The session failed (boot, prompt not accepted or not read, child exited, API error, pane lost). Call get_diagnostics for the cause.
|
|
70452
|
-
- timeout: The session hit its timeout_seconds; the pane was closed. Call get_diagnostics to see how far it got.
|
|
70453
|
-
- cancelled: The session was cancelled via cancel_session.
|
|
70719
|
+
Each session is an interactive Claude Code running the model in its own headless terminal pane. Nothing is pushed to you while it runs: poll.
|
|
70454
70720
|
|
|
70455
|
-
|
|
70721
|
+
1. create_session returns {session_id, state: "STARTING"} at once while Claude Code boots.
|
|
70722
|
+
2. Poll list_sessions (include_completed: true), about once every 10 seconds. Each row has state, activity, idle_seconds and accounting.
|
|
70723
|
+
- STARTING: booting, or the first prompt is not yet accepted.
|
|
70724
|
+
- RUNNING: a turn is in progress (activity names the tool in use).
|
|
70725
|
+
- AWAITING_INPUT: waiting for send_input \u2014 an interactive session between turns, or a turn stopped on a question (activity "AskUserQuestion"). A send declines a question and becomes the next prompt.
|
|
70726
|
+
- AWAITING_PERMISSION: a permission or plan-approval dialog is open. A send declines it and becomes the next prompt.
|
|
70727
|
+
- COMPLETED, FAILED, TIMEOUT, CANCELLED, EMPTY: finished.
|
|
70728
|
+
3. send_input may be called at any time; it is queued until the session is idle.
|
|
70729
|
+
4. COMPLETED: call get_output for the answer.
|
|
70730
|
+
5. FAILED or TIMEOUT \u2014 or COMPLETED with an empty or surprising answer \u2014 call get_diagnostics. It returns the child's final screen, the upstream error bodies, the recent state records, the resolved model chain and the paths to the full records. It needs no re-run and no debug flag.
|
|
70731
|
+
6. capture_session reads a session's current screen; cancel_session stops it. Nothing stops a session for being idle: a child inside a long build is silent and working.
|
|
70456
70732
|
|
|
70457
|
-
|
|
70458
|
-
2. Watch for <channel> notifications \u2014 they arrive automatically.
|
|
70459
|
-
3. send_input may be called at any time; it is queued until the session is idle. On input_required, call send_input with the answer.
|
|
70460
|
-
4. On completed: call get_output to get the full response.
|
|
70461
|
-
5. On failed or timeout \u2014 or on a completed session whose output is empty or
|
|
70462
|
-
surprising \u2014 call get_diagnostics. It returns the child's final screen, the
|
|
70463
|
-
upstream error bodies, the recent state records, the resolved model chain and the
|
|
70464
|
-
paths to the full records. It needs no re-run and no debug flag.
|
|
70465
|
-
6. Use list_sessions to see sessions: each row has state, activity, idle_seconds and accounting.
|
|
70466
|
-
7. Use capture_session to read a session's current terminal screen.
|
|
70467
|
-
8. Use cancel_session to stop a running session.
|
|
70468
|
-
|
|
70469
|
-
The session_id in the channel tag's meta attributes is the key for all tool calls.`, proxyInstance = null, proxyStarting = null, SCORE_TIE_EPSILON = 0.000001, NEXT_STEP, sanitize2, TASK_STATUS_BY_EVENT, EVENT_TO_TASK_STATUS;
|
|
70733
|
+
The session_id from create_session is the key for every session tool.`, proxyInstance = null, proxyStarting = null, SCORE_TIE_EPSILON = 0.000001, NEXT_STEP, sanitize2, TOOL_MODES;
|
|
70470
70734
|
var init_mcp_server = __esm(() => {
|
|
70471
70735
|
init_server2();
|
|
70472
70736
|
init_stdio2();
|
|
70473
70737
|
init_types();
|
|
70474
70738
|
init_model_catalog();
|
|
70475
70739
|
init_prehydrate();
|
|
70476
|
-
init_diagnostics();
|
|
70477
|
-
init_channel();
|
|
70478
|
-
init_parent_session();
|
|
70479
70740
|
init_remote_provider_types();
|
|
70741
|
+
init_mcp_session();
|
|
70742
|
+
init_parent_session();
|
|
70743
|
+
init_nested_mode();
|
|
70480
70744
|
init_progress_heartbeat();
|
|
70745
|
+
init_run_prompt_claude_code();
|
|
70481
70746
|
init_model_loader();
|
|
70747
|
+
init_child_env();
|
|
70482
70748
|
init_pane();
|
|
70483
70749
|
init_port_manager();
|
|
70484
70750
|
init_endpoint_registration();
|
|
@@ -70495,8 +70761,8 @@ var init_mcp_server = __esm(() => {
|
|
|
70495
70761
|
import_dotenv2.config({ quiet: true });
|
|
70496
70762
|
__filename3 = fileURLToPath3(import.meta.url);
|
|
70497
70763
|
__dirname3 = dirname14(__filename3);
|
|
70498
|
-
CLAUDISH_CACHE_DIR =
|
|
70499
|
-
OPENROUTER_MODELS_CACHE_PATH =
|
|
70764
|
+
CLAUDISH_CACHE_DIR = join50(homedir33(), ".claudish");
|
|
70765
|
+
OPENROUTER_MODELS_CACHE_PATH = join50(CLAUDISH_CACHE_DIR, "openrouter-models.json");
|
|
70500
70766
|
NEXT_STEP = {
|
|
70501
70767
|
cancelled: "you stopped this slot; nothing is wrong with it. Re-run it if you still want its vote",
|
|
70502
70768
|
timeout: "grid mode only \u2014 magmux ended the pane. The orchestrator has no deadline",
|
|
@@ -70515,18 +70781,7 @@ var init_mcp_server = __esm(() => {
|
|
|
70515
70781
|
shape_mismatch: "the answer (assistant text after the task was read) did not match. Every assistant " + "message of the turn was read from the transcript, so nothing was lost in transit \u2014 " + "the model did not produce it. Re-prompt with the required format restated; do NOT " + "count this slot as a vote"
|
|
70516
70782
|
};
|
|
70517
70783
|
sanitize2 = sanitizeForReport;
|
|
70518
|
-
|
|
70519
|
-
starting: "working",
|
|
70520
|
-
running: "working",
|
|
70521
|
-
tool_executing: "working",
|
|
70522
|
-
waiting_for_input: "input_required",
|
|
70523
|
-
awaiting_permission: "input_required",
|
|
70524
|
-
completed: "completed",
|
|
70525
|
-
failed: "failed",
|
|
70526
|
-
cancelled: "cancelled",
|
|
70527
|
-
timeout: "failed"
|
|
70528
|
-
};
|
|
70529
|
-
EVENT_TO_TASK_STATUS = new Map(Object.entries(TASK_STATUS_BY_EVENT));
|
|
70784
|
+
TOOL_MODES = ["all", "low-level", "agentic", "session", "debug"];
|
|
70530
70785
|
});
|
|
70531
70786
|
|
|
70532
70787
|
// src/serve-command.ts
|
|
@@ -70629,7 +70884,7 @@ var init_serve_command = __esm(() => {
|
|
|
70629
70884
|
});
|
|
70630
70885
|
|
|
70631
70886
|
// src/behavior-command.ts
|
|
70632
|
-
import { existsSync as existsSync34, readFileSync as readFileSync33, writeFileSync as
|
|
70887
|
+
import { existsSync as existsSync34, readFileSync as readFileSync33, writeFileSync as writeFileSync24 } from "fs";
|
|
70633
70888
|
function severityColor(sev) {
|
|
70634
70889
|
if (sev === "fix")
|
|
70635
70890
|
return green(sev);
|
|
@@ -70737,7 +70992,7 @@ function setTelemetryEnabled(value) {
|
|
|
70737
70992
|
const behavior = cfg.behavior && typeof cfg.behavior === "object" && !Array.isArray(cfg.behavior) ? { ...cfg.behavior } : {};
|
|
70738
70993
|
behavior.telemetry = { enabled: value };
|
|
70739
70994
|
cfg.behavior = behavior;
|
|
70740
|
-
|
|
70995
|
+
writeFileSync24(path, `${JSON.stringify(cfg, null, 2)}
|
|
70741
70996
|
`, "utf-8");
|
|
70742
70997
|
}
|
|
70743
70998
|
function showTelemetry(action, json) {
|
|
@@ -70829,10 +71084,10 @@ var init_behavior_command = __esm(() => {
|
|
|
70829
71084
|
});
|
|
70830
71085
|
|
|
70831
71086
|
// src/team-grid.ts
|
|
70832
|
-
import { spawn as
|
|
70833
|
-
import { existsSync as existsSync35, readFileSync as readFileSync34, writeFileSync as
|
|
71087
|
+
import { spawn as spawn3 } from "child_process";
|
|
71088
|
+
import { existsSync as existsSync35, readFileSync as readFileSync34, writeFileSync as writeFileSync25 } from "fs";
|
|
70834
71089
|
import { connect as netConnect2 } from "net";
|
|
70835
|
-
import { join as
|
|
71090
|
+
import { join as join51 } from "path";
|
|
70836
71091
|
import { setTimeout as wait } from "timers/promises";
|
|
70837
71092
|
function paneRouteLine(explanation) {
|
|
70838
71093
|
const origin = describeRouteExplanation(explanation);
|
|
@@ -70982,9 +71237,9 @@ async function runWithGrid(sessionPath, models, input, opts) {
|
|
|
70982
71237
|
const keep = opts?.keep ?? false;
|
|
70983
71238
|
const manifest = setupSession(sessionPath, models, input);
|
|
70984
71239
|
const startedAt = new Date().toISOString();
|
|
70985
|
-
const gridfilePath =
|
|
70986
|
-
const prompt = readFileSync34(
|
|
70987
|
-
const rawPrompt = readFileSync34(
|
|
71240
|
+
const gridfilePath = join51(sessionPath, "gridfile.txt");
|
|
71241
|
+
const prompt = readFileSync34(join51(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
|
|
71242
|
+
const rawPrompt = readFileSync34(join51(sessionPath, "input.md"), "utf-8");
|
|
70988
71243
|
const usedBannerColors = new Set;
|
|
70989
71244
|
const routeLines = mode === "interactive" ? new Map : await resolvePaneRouteLines(Object.values(manifest.models).map((entry) => entry.model));
|
|
70990
71245
|
const gridLines = Object.entries(manifest.models).map(([anonId]) => {
|
|
@@ -70996,7 +71251,7 @@ async function runWithGrid(sessionPath, models, input, opts) {
|
|
|
70996
71251
|
const header = buildPaneHeader(model, routeLines.get(model) ?? "", rawPrompt, bg);
|
|
70997
71252
|
return `${header} claudish --model ${model} -y --quiet '${prompt}'`;
|
|
70998
71253
|
});
|
|
70999
|
-
|
|
71254
|
+
writeFileSync25(gridfilePath, `${gridLines.join(`
|
|
71000
71255
|
`)}
|
|
71001
71256
|
`, "utf-8");
|
|
71002
71257
|
const magmuxPath = findMagmuxBinary();
|
|
@@ -71004,7 +71259,7 @@ async function runWithGrid(sessionPath, models, input, opts) {
|
|
|
71004
71259
|
if (!keep && mode === "default") {
|
|
71005
71260
|
spawnArgs.push("-w");
|
|
71006
71261
|
}
|
|
71007
|
-
const proc =
|
|
71262
|
+
const proc = spawn3(magmuxPath, spawnArgs, {
|
|
71008
71263
|
stdio: "inherit",
|
|
71009
71264
|
env: { ...process.env }
|
|
71010
71265
|
});
|
|
@@ -71016,8 +71271,8 @@ async function runWithGrid(sessionPath, models, input, opts) {
|
|
|
71016
71271
|
});
|
|
71017
71272
|
const [{ results }] = await Promise.all([subscription, procExit]);
|
|
71018
71273
|
const status = buildTeamStatus(manifest, startedAt, results?.panes ?? null);
|
|
71019
|
-
const statusPath =
|
|
71020
|
-
|
|
71274
|
+
const statusPath = join51(sessionPath, "status.json");
|
|
71275
|
+
writeFileSync25(statusPath, JSON.stringify(status, null, 2), "utf-8");
|
|
71021
71276
|
return status;
|
|
71022
71277
|
}
|
|
71023
71278
|
var BANNER_BG_COLORS;
|
|
@@ -71037,7 +71292,7 @@ var init_team_grid = __esm(() => {
|
|
|
71037
71292
|
|
|
71038
71293
|
// src/team-cli.ts
|
|
71039
71294
|
import { readFileSync as readFileSync35 } from "fs";
|
|
71040
|
-
import { join as
|
|
71295
|
+
import { join as join52 } from "path";
|
|
71041
71296
|
async function runPaneTeam(sessionPath, models, input, opts) {
|
|
71042
71297
|
installPaneShutdownHooks({ exitAfter: true });
|
|
71043
71298
|
try {
|
|
@@ -71114,6 +71369,8 @@ async function teamCommand(args) {
|
|
|
71114
71369
|
const firstArg = args[0] ?? "";
|
|
71115
71370
|
const legacySubs = ["run", "judge", "run-and-judge", "status"];
|
|
71116
71371
|
const subcommand = legacySubs.includes(firstArg) ? firstArg : "run";
|
|
71372
|
+
if (subcommand !== "status")
|
|
71373
|
+
assertNotNested();
|
|
71117
71374
|
const rawSessionPath = getFlag(args, "--path") ?? ".";
|
|
71118
71375
|
let sessionPath;
|
|
71119
71376
|
try {
|
|
@@ -71173,7 +71430,7 @@ async function teamCommand(args) {
|
|
|
71173
71430
|
}
|
|
71174
71431
|
case "judge": {
|
|
71175
71432
|
await judgeResponses(sessionPath, { judges });
|
|
71176
|
-
console.log(readFileSync35(
|
|
71433
|
+
console.log(readFileSync35(join52(sessionPath, "verdict.md"), "utf-8"));
|
|
71177
71434
|
break;
|
|
71178
71435
|
}
|
|
71179
71436
|
case "run-and-judge": {
|
|
@@ -71189,7 +71446,7 @@ async function teamCommand(args) {
|
|
|
71189
71446
|
});
|
|
71190
71447
|
printStatus(status);
|
|
71191
71448
|
await judgeResponses(sessionPath, { judges });
|
|
71192
|
-
console.log(readFileSync35(
|
|
71449
|
+
console.log(readFileSync35(join52(sessionPath, "verdict.md"), "utf-8"));
|
|
71193
71450
|
break;
|
|
71194
71451
|
}
|
|
71195
71452
|
case "status": {
|
|
@@ -71200,6 +71457,7 @@ async function teamCommand(args) {
|
|
|
71200
71457
|
}
|
|
71201
71458
|
}
|
|
71202
71459
|
var init_team_cli = __esm(() => {
|
|
71460
|
+
init_child_env();
|
|
71203
71461
|
init_pane();
|
|
71204
71462
|
init_team_orchestrator();
|
|
71205
71463
|
});
|
|
@@ -71762,7 +72020,7 @@ var init_keychain_command = __esm(() => {
|
|
|
71762
72020
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
71763
72021
|
import { existsSync as existsSync36, unlinkSync as unlinkSync9 } from "fs";
|
|
71764
72022
|
import { homedir as homedir34 } from "os";
|
|
71765
|
-
import { join as
|
|
72023
|
+
import { join as join53 } from "path";
|
|
71766
72024
|
async function defaultSuggestModel() {
|
|
71767
72025
|
try {
|
|
71768
72026
|
const tok = readSharedAntigravityToken();
|
|
@@ -71883,7 +72141,7 @@ No session detected yet. Starting the Antigravity CLI interactively \u2014
|
|
|
71883
72141
|
async logout(deps) {
|
|
71884
72142
|
deleteSharedAntigravityToken(deps);
|
|
71885
72143
|
try {
|
|
71886
|
-
const tokenFile =
|
|
72144
|
+
const tokenFile = join53(homedir34(), ".gemini", "antigravity-cli", "antigravity-oauth-token");
|
|
71887
72145
|
if (existsSync36(tokenFile))
|
|
71888
72146
|
unlinkSync9(tokenFile);
|
|
71889
72147
|
} catch {}
|
|
@@ -80145,20 +80403,20 @@ var init_terminal_isolation = __esm(() => {
|
|
|
80145
80403
|
});
|
|
80146
80404
|
|
|
80147
80405
|
// src/claude-runner.ts
|
|
80148
|
-
import { spawn as
|
|
80406
|
+
import { spawn as spawn4, spawnSync as spawnSync4 } from "child_process";
|
|
80149
80407
|
import {
|
|
80150
|
-
closeSync as
|
|
80408
|
+
closeSync as closeSync11,
|
|
80151
80409
|
existsSync as existsSync38,
|
|
80152
|
-
mkdirSync as
|
|
80153
|
-
openSync as
|
|
80410
|
+
mkdirSync as mkdirSync23,
|
|
80411
|
+
openSync as openSync11,
|
|
80154
80412
|
readFileSync as readFileSync36,
|
|
80155
80413
|
readdirSync as readdirSync11,
|
|
80156
80414
|
statSync as statSync13,
|
|
80157
80415
|
unlinkSync as unlinkSync10,
|
|
80158
|
-
writeFileSync as
|
|
80416
|
+
writeFileSync as writeFileSync26
|
|
80159
80417
|
} from "fs";
|
|
80160
|
-
import { homedir as homedir35, tmpdir as
|
|
80161
|
-
import { dirname as dirname15, join as
|
|
80418
|
+
import { homedir as homedir35, tmpdir as tmpdir3 } from "os";
|
|
80419
|
+
import { dirname as dirname15, join as join54 } from "path";
|
|
80162
80420
|
import { isatty } from "tty";
|
|
80163
80421
|
function releaseTerminalIsolation() {
|
|
80164
80422
|
if (!restoreTerminal)
|
|
@@ -80223,7 +80481,7 @@ function hasResolvableAnthropicAuth(deps = {}) {
|
|
|
80223
80481
|
if (isRealAnthropicEnvCredential(env, "ANTHROPIC_API_KEY") || isRealAnthropicEnvCredential(env, "ANTHROPIC_AUTH_TOKEN")) {
|
|
80224
80482
|
return true;
|
|
80225
80483
|
}
|
|
80226
|
-
if (fileExists(
|
|
80484
|
+
if (fileExists(join54(homedir35(), ".claude", ".credentials.json")))
|
|
80227
80485
|
return true;
|
|
80228
80486
|
return keychainProbe();
|
|
80229
80487
|
}
|
|
@@ -80238,7 +80496,7 @@ function isProxyAuthMode(config) {
|
|
|
80238
80496
|
}
|
|
80239
80497
|
function managedSettingsPath() {
|
|
80240
80498
|
if (isWindows2()) {
|
|
80241
|
-
return
|
|
80499
|
+
return join54(process.env.PROGRAMDATA || "C:\\ProgramData", "ClaudeCode", "managed-settings.json");
|
|
80242
80500
|
}
|
|
80243
80501
|
if (process.platform === "darwin") {
|
|
80244
80502
|
return "/Library/Application Support/ClaudeCode/managed-settings.json";
|
|
@@ -80258,10 +80516,10 @@ function isWindows2() {
|
|
|
80258
80516
|
return process.platform === "win32";
|
|
80259
80517
|
}
|
|
80260
80518
|
function createStatusLineScript(tokenFilePath) {
|
|
80261
|
-
const homeDir = process.env.HOME || process.env.USERPROFILE ||
|
|
80262
|
-
const claudishDir =
|
|
80519
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir3();
|
|
80520
|
+
const claudishDir = join54(homeDir, ".claudish");
|
|
80263
80521
|
const timestamp = Date.now();
|
|
80264
|
-
const scriptPath =
|
|
80522
|
+
const scriptPath = join54(claudishDir, `status-${timestamp}.js`);
|
|
80265
80523
|
const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
|
|
80266
80524
|
const light = getThemeMode() === "light";
|
|
80267
80525
|
const cyanCode = light ? "38;2;14;116;144" : "96";
|
|
@@ -80394,13 +80652,13 @@ process.stdin.on('end', () => {
|
|
|
80394
80652
|
}
|
|
80395
80653
|
});
|
|
80396
80654
|
`;
|
|
80397
|
-
|
|
80655
|
+
writeFileSync26(scriptPath, script, "utf-8");
|
|
80398
80656
|
return scriptPath;
|
|
80399
80657
|
}
|
|
80400
80658
|
function initializeTokenFile(tokenFilePath) {
|
|
80401
80659
|
try {
|
|
80402
|
-
|
|
80403
|
-
|
|
80660
|
+
mkdirSync23(dirname15(tokenFilePath), { recursive: true });
|
|
80661
|
+
writeFileSync26(tokenFilePath, JSON.stringify({
|
|
80404
80662
|
input_tokens: 0,
|
|
80405
80663
|
output_tokens: 0,
|
|
80406
80664
|
total_tokens: 0,
|
|
@@ -80431,7 +80689,7 @@ function cleanupStaleTokenFiles(dir, now = Date.now(), maxAgeMs = STALE_TOKEN_FI
|
|
|
80431
80689
|
if (!name.startsWith("tokens-") || !name.endsWith(".json"))
|
|
80432
80690
|
continue;
|
|
80433
80691
|
scanned++;
|
|
80434
|
-
const full =
|
|
80692
|
+
const full = join54(dir, name);
|
|
80435
80693
|
try {
|
|
80436
80694
|
if (statSync13(full).mtimeMs >= cutoff)
|
|
80437
80695
|
continue;
|
|
@@ -80460,9 +80718,9 @@ function parseSettingsArgSafe(value) {
|
|
|
80460
80718
|
}
|
|
80461
80719
|
function userSettingsFileCandidates(cwd) {
|
|
80462
80720
|
return [
|
|
80463
|
-
|
|
80464
|
-
|
|
80465
|
-
|
|
80721
|
+
join54(homedir35(), ".claude", "settings.json"),
|
|
80722
|
+
join54(cwd, ".claude", "settings.json"),
|
|
80723
|
+
join54(cwd, ".claude", "settings.local.json")
|
|
80466
80724
|
];
|
|
80467
80725
|
}
|
|
80468
80726
|
function discoverUserStatusLineCommand(claudeArgs = [], cwd = process.cwd()) {
|
|
@@ -80502,13 +80760,13 @@ function buildChainedStatusCommand(userCommand, claudishBody, claudishSegment) {
|
|
|
80502
80760
|
return `JSON=$(cat); ${runUser}; ${claudishBody}; SEG=$(${claudishSegment}); ${separator}; ${emit}`;
|
|
80503
80761
|
}
|
|
80504
80762
|
function createTempSettingsFile(_modelDisplay, port, proxyAuthMode, userStatusLineCommand) {
|
|
80505
|
-
const homeDir = process.env.HOME || process.env.USERPROFILE ||
|
|
80506
|
-
const claudishDir =
|
|
80763
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir3();
|
|
80764
|
+
const claudishDir = join54(homeDir, ".claudish");
|
|
80507
80765
|
try {
|
|
80508
|
-
|
|
80766
|
+
mkdirSync23(claudishDir, { recursive: true });
|
|
80509
80767
|
} catch {}
|
|
80510
80768
|
const timestamp = Date.now();
|
|
80511
|
-
const tempPath =
|
|
80769
|
+
const tempPath = join54(claudishDir, `settings-${timestamp}.json`);
|
|
80512
80770
|
const assignedFile = assignedTokenFile(process.env) !== null;
|
|
80513
80771
|
const tokenFilePath = resolveTokenFilePath(port);
|
|
80514
80772
|
cleanupStaleTokenFiles(claudishDir);
|
|
@@ -80545,7 +80803,7 @@ function createTempSettingsFile(_modelDisplay, port, proxyAuthMode, userStatusLi
|
|
|
80545
80803
|
padding: 0
|
|
80546
80804
|
};
|
|
80547
80805
|
const settings = buildClaudishSettingsOverlay(statusLine, proxyAuthMode);
|
|
80548
|
-
|
|
80806
|
+
writeFileSync26(tempPath, JSON.stringify(settings, null, 2), "utf-8");
|
|
80549
80807
|
return { path: tempPath, statusLine, tokenFilePath };
|
|
80550
80808
|
}
|
|
80551
80809
|
function scrubChildEnv(env, opts) {
|
|
@@ -80553,7 +80811,7 @@ function scrubChildEnv(env, opts) {
|
|
|
80553
80811
|
for (const key of STRIPPED_CHILD_VARS)
|
|
80554
80812
|
delete env[key];
|
|
80555
80813
|
}
|
|
80556
|
-
for (const key of
|
|
80814
|
+
for (const key of PANE_LAUNCH_VARS)
|
|
80557
80815
|
delete env[key];
|
|
80558
80816
|
}
|
|
80559
80817
|
function buildClaudishSettingsOverlay(statusLine, proxyAuthMode, paneChild = isPaneChild()) {
|
|
@@ -80563,6 +80821,7 @@ function buildClaudishSettingsOverlay(statusLine, proxyAuthMode, paneChild = isP
|
|
|
80563
80821
|
}
|
|
80564
80822
|
if (paneChild) {
|
|
80565
80823
|
settings.skipDangerousModePermissionPrompt = true;
|
|
80824
|
+
settings.editorMode = "normal";
|
|
80566
80825
|
}
|
|
80567
80826
|
return settings;
|
|
80568
80827
|
}
|
|
@@ -80584,7 +80843,10 @@ function mergeUserSettingsIfPresent(config, tempSettingsPath, statusLine, proxyA
|
|
|
80584
80843
|
if (paneChild && !("skipDangerousModePermissionPrompt" in userSettings)) {
|
|
80585
80844
|
userSettings.skipDangerousModePermissionPrompt = true;
|
|
80586
80845
|
}
|
|
80587
|
-
|
|
80846
|
+
if (paneChild) {
|
|
80847
|
+
userSettings.editorMode = "normal";
|
|
80848
|
+
}
|
|
80849
|
+
writeFileSync26(tempSettingsPath, JSON.stringify(userSettings, null, 2), "utf-8");
|
|
80588
80850
|
} catch {
|
|
80589
80851
|
if (!config.quiet) {
|
|
80590
80852
|
console.warn(`[claudish] Warning: could not merge user settings: ${userSettingsValue}`);
|
|
@@ -80883,7 +81145,7 @@ async function runClaudeWithProxy(config, proxyUrl, onCleanup) {
|
|
|
80883
81145
|
console.error(`
|
|
80884
81146
|
Or set CLAUDE_PATH to your custom installation:`);
|
|
80885
81147
|
const home = homedir35();
|
|
80886
|
-
const localPath = isWindows2() ?
|
|
81148
|
+
const localPath = isWindows2() ? join54(home, ".claude", "local", "claude.exe") : join54(home, ".claude", "local", "claude");
|
|
80887
81149
|
console.error(` export CLAUDE_PATH=${localPath}`);
|
|
80888
81150
|
process.exit(1);
|
|
80889
81151
|
}
|
|
@@ -80894,11 +81156,11 @@ Or set CLAUDE_PATH to your custom installation:`);
|
|
|
80894
81156
|
const childWantsTty = config.interactive && !process.stdout.isTTY && Boolean(process.stdin.isTTY);
|
|
80895
81157
|
if (childWantsTty) {
|
|
80896
81158
|
try {
|
|
80897
|
-
const fd =
|
|
81159
|
+
const fd = openSync11("/dev/fd/0", "r+");
|
|
80898
81160
|
if (isatty(fd)) {
|
|
80899
81161
|
ttyFd = fd;
|
|
80900
81162
|
} else {
|
|
80901
|
-
|
|
81163
|
+
closeSync11(fd);
|
|
80902
81164
|
}
|
|
80903
81165
|
} catch {
|
|
80904
81166
|
ttyFd = undefined;
|
|
@@ -80917,7 +81179,7 @@ Or set CLAUDE_PATH to your custom installation:`);
|
|
|
80917
81179
|
stdoutIsTty: Boolean(process.stdout.isTTY),
|
|
80918
81180
|
magmuxBinary: paneCapability.magmux
|
|
80919
81181
|
}) : null;
|
|
80920
|
-
const proc = wrap ?
|
|
81182
|
+
const proc = wrap ? spawn4(wrap.command, wrap.args, { env: wrap.env, stdio, shell: false }) : spawn4(spawnCommand, claudeArgs, {
|
|
80921
81183
|
env,
|
|
80922
81184
|
stdio,
|
|
80923
81185
|
shell: needsShell
|
|
@@ -80943,7 +81205,7 @@ Or set CLAUDE_PATH to your custom installation:`);
|
|
|
80943
81205
|
const fdToClose = ttyFd;
|
|
80944
81206
|
proc.on("spawn", () => {
|
|
80945
81207
|
try {
|
|
80946
|
-
|
|
81208
|
+
closeSync11(fdToClose);
|
|
80947
81209
|
} catch {}
|
|
80948
81210
|
});
|
|
80949
81211
|
}
|
|
@@ -80996,15 +81258,15 @@ async function findClaudeBinary() {
|
|
|
80996
81258
|
}
|
|
80997
81259
|
}
|
|
80998
81260
|
const home = homedir35();
|
|
80999
|
-
const localPath = isWindows ?
|
|
81261
|
+
const localPath = isWindows ? join54(home, ".claude", "local", "claude.exe") : join54(home, ".claude", "local", "claude");
|
|
81000
81262
|
if (existsSync38(localPath)) {
|
|
81001
81263
|
return localPath;
|
|
81002
81264
|
}
|
|
81003
81265
|
if (isWindows) {
|
|
81004
81266
|
const windowsPaths = [
|
|
81005
|
-
|
|
81006
|
-
|
|
81007
|
-
|
|
81267
|
+
join54(home, "AppData", "Roaming", "npm", "claude.cmd"),
|
|
81268
|
+
join54(home, ".npm-global", "claude.cmd"),
|
|
81269
|
+
join54(home, "node_modules", ".bin", "claude.cmd")
|
|
81008
81270
|
];
|
|
81009
81271
|
for (const path of windowsPaths) {
|
|
81010
81272
|
if (existsSync38(path)) {
|
|
@@ -81015,11 +81277,11 @@ async function findClaudeBinary() {
|
|
|
81015
81277
|
const commonPaths = [
|
|
81016
81278
|
"/usr/local/bin/claude",
|
|
81017
81279
|
"/opt/homebrew/bin/claude",
|
|
81018
|
-
|
|
81019
|
-
|
|
81020
|
-
|
|
81280
|
+
join54(home, ".npm-global/bin/claude"),
|
|
81281
|
+
join54(home, ".local/bin/claude"),
|
|
81282
|
+
join54(home, "node_modules/.bin/claude"),
|
|
81021
81283
|
"/data/data/com.termux/files/usr/bin/claude",
|
|
81022
|
-
|
|
81284
|
+
join54(home, "../usr/bin/claude")
|
|
81023
81285
|
];
|
|
81024
81286
|
for (const path of commonPaths) {
|
|
81025
81287
|
if (existsSync38(path)) {
|
|
@@ -81029,7 +81291,7 @@ async function findClaudeBinary() {
|
|
|
81029
81291
|
}
|
|
81030
81292
|
try {
|
|
81031
81293
|
const shellCommand = isWindows ? "where claude" : "command -v claude";
|
|
81032
|
-
const proc =
|
|
81294
|
+
const proc = spawn4(shellCommand, [], {
|
|
81033
81295
|
stdio: "pipe",
|
|
81034
81296
|
shell: true
|
|
81035
81297
|
});
|
|
@@ -81102,18 +81364,18 @@ var init_claude_runner = __esm(() => {
|
|
|
81102
81364
|
});
|
|
81103
81365
|
|
|
81104
81366
|
// src/diag-output.ts
|
|
81105
|
-
import { createWriteStream as createWriteStream2, mkdirSync as
|
|
81367
|
+
import { createWriteStream as createWriteStream2, mkdirSync as mkdirSync24, unlinkSync as unlinkSync11, writeFileSync as writeFileSync27 } from "fs";
|
|
81106
81368
|
import { homedir as homedir36 } from "os";
|
|
81107
|
-
import { join as
|
|
81369
|
+
import { join as join55 } from "path";
|
|
81108
81370
|
function getClaudishDir() {
|
|
81109
|
-
const dir =
|
|
81371
|
+
const dir = join55(homedir36(), ".claudish");
|
|
81110
81372
|
try {
|
|
81111
|
-
|
|
81373
|
+
mkdirSync24(dir, { recursive: true });
|
|
81112
81374
|
} catch {}
|
|
81113
81375
|
return dir;
|
|
81114
81376
|
}
|
|
81115
81377
|
function getDiagLogPath() {
|
|
81116
|
-
return
|
|
81378
|
+
return join55(getClaudishDir(), `diag-${process.pid}.log`);
|
|
81117
81379
|
}
|
|
81118
81380
|
|
|
81119
81381
|
class LogFileDiagOutput {
|
|
@@ -81122,7 +81384,7 @@ class LogFileDiagOutput {
|
|
|
81122
81384
|
constructor() {
|
|
81123
81385
|
this.logPath = getDiagLogPath();
|
|
81124
81386
|
try {
|
|
81125
|
-
|
|
81387
|
+
writeFileSync27(this.logPath, `--- claudish diag session ${new Date().toISOString()} ---
|
|
81126
81388
|
`);
|
|
81127
81389
|
} catch {}
|
|
81128
81390
|
this.stream = createWriteStream2(this.logPath, { flags: "a" });
|
|
@@ -81603,7 +81865,7 @@ var init_advisor_startup = __esm(() => {
|
|
|
81603
81865
|
});
|
|
81604
81866
|
|
|
81605
81867
|
// src/session/conversation.ts
|
|
81606
|
-
import { closeSync as
|
|
81868
|
+
import { closeSync as closeSync12, openSync as openSync12, readSync as readSync6, statSync as statSync14 } from "fs";
|
|
81607
81869
|
import { StringDecoder } from "string_decoder";
|
|
81608
81870
|
function looksLikeTurn(line) {
|
|
81609
81871
|
const assistant = line.includes('"type":"assistant"');
|
|
@@ -81659,7 +81921,7 @@ function readConversation(file, opts = {}) {
|
|
|
81659
81921
|
let fd = null;
|
|
81660
81922
|
try {
|
|
81661
81923
|
const size = statSync14(file).size;
|
|
81662
|
-
fd =
|
|
81924
|
+
fd = openSync12(file, "r");
|
|
81663
81925
|
const buf = Buffer.allocUnsafe(chunkBytes);
|
|
81664
81926
|
const decoder = new StringDecoder("utf-8");
|
|
81665
81927
|
let pending = "";
|
|
@@ -81691,7 +81953,7 @@ function readConversation(file, opts = {}) {
|
|
|
81691
81953
|
take({ role: raw.role, text, elided });
|
|
81692
81954
|
};
|
|
81693
81955
|
while (pos < size) {
|
|
81694
|
-
const n =
|
|
81956
|
+
const n = readSync6(fd, buf, 0, Math.min(chunkBytes, size - pos), pos);
|
|
81695
81957
|
if (n <= 0)
|
|
81696
81958
|
break;
|
|
81697
81959
|
pos += n;
|
|
@@ -81715,7 +81977,7 @@ function readConversation(file, opts = {}) {
|
|
|
81715
81977
|
} catch {} finally {
|
|
81716
81978
|
if (fd !== null) {
|
|
81717
81979
|
try {
|
|
81718
|
-
|
|
81980
|
+
closeSync12(fd);
|
|
81719
81981
|
} catch {}
|
|
81720
81982
|
}
|
|
81721
81983
|
}
|
|
@@ -83329,30 +83591,30 @@ function readSessionStats(port, opts) {
|
|
|
83329
83591
|
return null;
|
|
83330
83592
|
const d = raw;
|
|
83331
83593
|
const processStartMs = opts?.processStartMs ?? Date.now() - Math.round(process.uptime() * 1000);
|
|
83332
|
-
const trackerStartedAt =
|
|
83594
|
+
const trackerStartedAt = num2(d.started_at);
|
|
83333
83595
|
if (trackerStartedAt <= 0 || trackerStartedAt < processStartMs)
|
|
83334
83596
|
return null;
|
|
83335
|
-
const inputTokens =
|
|
83336
|
-
const outputTokens =
|
|
83597
|
+
const inputTokens = num2(d.input_tokens);
|
|
83598
|
+
const outputTokens = num2(d.output_tokens);
|
|
83337
83599
|
if (inputTokens <= 0 && outputTokens <= 0)
|
|
83338
83600
|
return null;
|
|
83339
|
-
const costUsd =
|
|
83601
|
+
const costUsd = num2(d.total_cost);
|
|
83340
83602
|
const isFree = d.is_free === true;
|
|
83341
83603
|
const contextWindow = typeof d.context_window === "number" ? d.context_window : null;
|
|
83342
83604
|
const contextUsed = contextWindow && contextWindow > 0 ? Math.min(1, Math.max(0, inputTokens / contextWindow)) : null;
|
|
83343
|
-
const toolCalls = Array.isArray(d.tool_calls) ? d.tool_calls.map((t) => t).filter((t) => typeof t?.name === "string" &&
|
|
83344
|
-
const startedAt =
|
|
83345
|
-
const updatedAt =
|
|
83605
|
+
const toolCalls = Array.isArray(d.tool_calls) ? d.tool_calls.map((t) => t).filter((t) => typeof t?.name === "string" && num2(t.count) > 0).map((t) => ({ name: String(t.name), count: num2(t.count) })) : [];
|
|
83606
|
+
const startedAt = num2(d.started_at);
|
|
83607
|
+
const updatedAt = num2(d.updated_at);
|
|
83346
83608
|
const durationMs = startedAt > 0 && updatedAt > startedAt ? updatedAt - startedAt : 0;
|
|
83347
|
-
const billedInputTokens =
|
|
83348
|
-
const rawIn = billedInputTokens / 1e6 *
|
|
83349
|
-
const rawOut = outputTokens / 1e6 *
|
|
83609
|
+
const billedInputTokens = num2(d.billed_input_tokens) || inputTokens;
|
|
83610
|
+
const rawIn = billedInputTokens / 1e6 * num2(d.input_per_m);
|
|
83611
|
+
const rawOut = outputTokens / 1e6 * num2(d.output_per_m);
|
|
83350
83612
|
const rawTotal = rawIn + rawOut;
|
|
83351
83613
|
const scale = rawTotal > 0 && costUsd > 0 ? costUsd / rawTotal : 0;
|
|
83352
83614
|
return {
|
|
83353
83615
|
inputTokens,
|
|
83354
83616
|
outputTokens,
|
|
83355
|
-
totalTokens:
|
|
83617
|
+
totalTokens: num2(d.total_tokens) || inputTokens + outputTokens,
|
|
83356
83618
|
costUsd,
|
|
83357
83619
|
isFree,
|
|
83358
83620
|
isEstimated: d.is_estimated === true,
|
|
@@ -83380,7 +83642,7 @@ function computeSavings(inputTokens, outputTokens, actualUsd) {
|
|
|
83380
83642
|
};
|
|
83381
83643
|
});
|
|
83382
83644
|
}
|
|
83383
|
-
var
|
|
83645
|
+
var num2 = (v) => typeof v === "number" && Number.isFinite(v) ? v : 0;
|
|
83384
83646
|
var init_session_stats = __esm(() => {
|
|
83385
83647
|
init_baseline_pricing();
|
|
83386
83648
|
init_token_file();
|
|
@@ -83682,7 +83944,7 @@ init_startup_trace();
|
|
|
83682
83944
|
init_picker_cancelled();
|
|
83683
83945
|
var import_dotenv3 = __toESM(require_main(), 1);
|
|
83684
83946
|
import { existsSync as existsSync39, readFileSync as readFileSync38 } from "fs";
|
|
83685
|
-
import { join as
|
|
83947
|
+
import { join as join56, resolve as resolve7 } from "path";
|
|
83686
83948
|
|
|
83687
83949
|
// src/tui/runtime/should-open-picker.ts
|
|
83688
83950
|
function noModelConfigured(gate) {
|
|
@@ -83974,6 +84236,7 @@ async function runCli() {
|
|
|
83974
84236
|
await detectAndSetThemeMode();
|
|
83975
84237
|
});
|
|
83976
84238
|
const cliConfig = await traceSpan("startup:parse-args", () => parseArgs(process.argv.slice(2)));
|
|
84239
|
+
assertNotNested();
|
|
83977
84240
|
assertPaneChildInteractive(cliConfig);
|
|
83978
84241
|
await traceSpan("startup:endpoint-registration", async () => {
|
|
83979
84242
|
await Promise.resolve().then(() => init_endpoint_registration());
|
|
@@ -83989,7 +84252,7 @@ async function runCli() {
|
|
|
83989
84252
|
process.exit(1);
|
|
83990
84253
|
}
|
|
83991
84254
|
const mode = cliConfig.teamMode ?? "default";
|
|
83992
|
-
const sessionPath =
|
|
84255
|
+
const sessionPath = join56(process.cwd(), `.claudish-team-${Date.now()}`);
|
|
83993
84256
|
if (mode === "json") {
|
|
83994
84257
|
await Promise.resolve().then(() => init_pane());
|
|
83995
84258
|
await Promise.resolve().then(() => init_team_orchestrator());
|
|
@@ -84009,7 +84272,7 @@ async function runCli() {
|
|
|
84009
84272
|
const status = await runModels(sessionPath);
|
|
84010
84273
|
const result = { ...status, responses: {} };
|
|
84011
84274
|
for (const anonId of Object.keys(status.models)) {
|
|
84012
|
-
const responsePath =
|
|
84275
|
+
const responsePath = join56(sessionPath, `response-${anonId}.md`);
|
|
84013
84276
|
try {
|
|
84014
84277
|
const raw = readFileSync38(responsePath, "utf-8").trim();
|
|
84015
84278
|
try {
|