claudish 7.49.0 → 7.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +186 -15
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -729,7 +729,7 @@ var init_onepassword_config = __esm(() => {
|
|
|
729
729
|
});
|
|
730
730
|
|
|
731
731
|
// src/version.ts
|
|
732
|
-
var VERSION = "7.
|
|
732
|
+
var VERSION = "7.50.0";
|
|
733
733
|
|
|
734
734
|
// src/logger.ts
|
|
735
735
|
var exports_logger = {};
|
|
@@ -50087,12 +50087,132 @@ function writeStatusFile(sessionPath, manifest, status, opts) {
|
|
|
50087
50087
|
var CHANNEL_LINE_BUDGET = 58;
|
|
50088
50088
|
var init_team_stats = () => {};
|
|
50089
50089
|
|
|
50090
|
+
// src/team-stream-capture.ts
|
|
50091
|
+
function extractAssistantText(event) {
|
|
50092
|
+
if (event.type !== "assistant")
|
|
50093
|
+
return [];
|
|
50094
|
+
const message = event.message;
|
|
50095
|
+
const content = message?.content;
|
|
50096
|
+
if (typeof content === "string") {
|
|
50097
|
+
return content.length > 0 ? [content] : [];
|
|
50098
|
+
}
|
|
50099
|
+
if (!Array.isArray(content))
|
|
50100
|
+
return [];
|
|
50101
|
+
const out = [];
|
|
50102
|
+
for (const raw2 of content) {
|
|
50103
|
+
const block = raw2;
|
|
50104
|
+
if (block?.type !== "text")
|
|
50105
|
+
continue;
|
|
50106
|
+
if (typeof block.text !== "string" || block.text.length === 0)
|
|
50107
|
+
continue;
|
|
50108
|
+
out.push(block.text);
|
|
50109
|
+
}
|
|
50110
|
+
return out;
|
|
50111
|
+
}
|
|
50112
|
+
function createAssistantTextCapture() {
|
|
50113
|
+
let pending = "";
|
|
50114
|
+
let emittedAny = false;
|
|
50115
|
+
let endsWithNewline = false;
|
|
50116
|
+
let dedupeTail = "";
|
|
50117
|
+
let lastWasMessage = false;
|
|
50118
|
+
const record4 = (text, kind) => {
|
|
50119
|
+
emittedAny = true;
|
|
50120
|
+
lastWasMessage = kind === "message";
|
|
50121
|
+
endsWithNewline = text.endsWith(`
|
|
50122
|
+
`);
|
|
50123
|
+
dedupeTail = (dedupeTail + text).slice(-DEDUPE_TAIL_LIMIT);
|
|
50124
|
+
};
|
|
50125
|
+
const messageSeparator = () => {
|
|
50126
|
+
if (!emittedAny)
|
|
50127
|
+
return "";
|
|
50128
|
+
return endsWithNewline ? `
|
|
50129
|
+
` : `
|
|
50130
|
+
|
|
50131
|
+
`;
|
|
50132
|
+
};
|
|
50133
|
+
const rawSeparator = () => {
|
|
50134
|
+
if (!emittedAny || endsWithNewline)
|
|
50135
|
+
return "";
|
|
50136
|
+
return `
|
|
50137
|
+
`;
|
|
50138
|
+
};
|
|
50139
|
+
const consumeLine = (line, terminated) => {
|
|
50140
|
+
if (line.trim().length === 0)
|
|
50141
|
+
return "";
|
|
50142
|
+
const passthrough = () => {
|
|
50143
|
+
const out = `${rawSeparator()}${line}${terminated ? `
|
|
50144
|
+
` : ""}`;
|
|
50145
|
+
record4(out, "raw");
|
|
50146
|
+
return out;
|
|
50147
|
+
};
|
|
50148
|
+
let event;
|
|
50149
|
+
try {
|
|
50150
|
+
event = JSON.parse(line);
|
|
50151
|
+
} catch {
|
|
50152
|
+
return passthrough();
|
|
50153
|
+
}
|
|
50154
|
+
if (typeof event.type !== "string" || !STREAM_JSON_EVENT_TYPES.has(event.type)) {
|
|
50155
|
+
return passthrough();
|
|
50156
|
+
}
|
|
50157
|
+
const texts = extractAssistantText(event);
|
|
50158
|
+
if (texts.length > 0) {
|
|
50159
|
+
let out = "";
|
|
50160
|
+
for (const text of texts) {
|
|
50161
|
+
const piece = `${messageSeparator()}${text}`;
|
|
50162
|
+
out += piece;
|
|
50163
|
+
record4(piece, "message");
|
|
50164
|
+
}
|
|
50165
|
+
return out;
|
|
50166
|
+
}
|
|
50167
|
+
if (event.type === "result" && event.is_error === true) {
|
|
50168
|
+
const result = typeof event.result === "string" ? event.result : "";
|
|
50169
|
+
if (result.trim().length > 0 && !dedupeTail.includes(result)) {
|
|
50170
|
+
const out = `${messageSeparator()}${result}`;
|
|
50171
|
+
record4(out, "message");
|
|
50172
|
+
return out;
|
|
50173
|
+
}
|
|
50174
|
+
}
|
|
50175
|
+
return "";
|
|
50176
|
+
};
|
|
50177
|
+
return {
|
|
50178
|
+
write(chunk) {
|
|
50179
|
+
pending += chunk;
|
|
50180
|
+
let out = "";
|
|
50181
|
+
let newlineAt = pending.indexOf(`
|
|
50182
|
+
`);
|
|
50183
|
+
while (newlineAt !== -1) {
|
|
50184
|
+
const line = pending.slice(0, newlineAt);
|
|
50185
|
+
pending = pending.slice(newlineAt + 1);
|
|
50186
|
+
out += consumeLine(line, true);
|
|
50187
|
+
newlineAt = pending.indexOf(`
|
|
50188
|
+
`);
|
|
50189
|
+
}
|
|
50190
|
+
return out;
|
|
50191
|
+
},
|
|
50192
|
+
end() {
|
|
50193
|
+
let out = pending.length > 0 ? consumeLine(pending, false) : "";
|
|
50194
|
+
pending = "";
|
|
50195
|
+
if (emittedAny && !endsWithNewline && lastWasMessage) {
|
|
50196
|
+
out += `
|
|
50197
|
+
`;
|
|
50198
|
+
endsWithNewline = true;
|
|
50199
|
+
}
|
|
50200
|
+
return out;
|
|
50201
|
+
}
|
|
50202
|
+
};
|
|
50203
|
+
}
|
|
50204
|
+
var DEDUPE_TAIL_LIMIT = 4096, STREAM_JSON_EVENT_TYPES;
|
|
50205
|
+
var init_team_stream_capture = __esm(() => {
|
|
50206
|
+
STREAM_JSON_EVENT_TYPES = new Set(["system", "assistant", "user", "result"]);
|
|
50207
|
+
});
|
|
50208
|
+
|
|
50090
50209
|
// src/team-orchestrator.ts
|
|
50091
50210
|
var exports_team_orchestrator = {};
|
|
50092
50211
|
__export(exports_team_orchestrator, {
|
|
50093
50212
|
validateSessionPath: () => validateSessionPath,
|
|
50094
50213
|
setupSession: () => setupSession,
|
|
50095
50214
|
runModels: () => runModels,
|
|
50215
|
+
resolveCaptureMode: () => resolveCaptureMode,
|
|
50096
50216
|
parseJudgeVotes: () => parseJudgeVotes,
|
|
50097
50217
|
judgeResponses: () => judgeResponses,
|
|
50098
50218
|
getStatus: () => getStatus,
|
|
@@ -50100,6 +50220,7 @@ __export(exports_team_orchestrator, {
|
|
|
50100
50220
|
classifyRunOutput: () => classifyRunOutput,
|
|
50101
50221
|
buildJudgePrompt: () => buildJudgePrompt,
|
|
50102
50222
|
aggregateVerdict: () => aggregateVerdict,
|
|
50223
|
+
TEAM_CAPTURE_ENV_VAR: () => TEAM_CAPTURE_ENV_VAR,
|
|
50103
50224
|
STDOUT_TAIL_LIMIT: () => STDOUT_TAIL_LIMIT,
|
|
50104
50225
|
DEFAULT_MIN_OUTPUT_BYTES: () => DEFAULT_MIN_OUTPUT_BYTES
|
|
50105
50226
|
});
|
|
@@ -50113,8 +50234,21 @@ import {
|
|
|
50113
50234
|
writeFileSync as writeFileSync12
|
|
50114
50235
|
} from "fs";
|
|
50115
50236
|
import { join as join28, resolve as resolve3 } from "path";
|
|
50237
|
+
function resolveCaptureMode(explicit, env = process.env) {
|
|
50238
|
+
if (explicit)
|
|
50239
|
+
return explicit;
|
|
50240
|
+
return env[TEAM_CAPTURE_ENV_VAR]?.trim().toLowerCase() === "print" ? "print" : "stream-json";
|
|
50241
|
+
}
|
|
50116
50242
|
function classifyRunOutput(opts) {
|
|
50117
|
-
const {
|
|
50243
|
+
const {
|
|
50244
|
+
outputSize,
|
|
50245
|
+
stdoutTail,
|
|
50246
|
+
stderr,
|
|
50247
|
+
minOutputBytes,
|
|
50248
|
+
requirePattern,
|
|
50249
|
+
fullOutput,
|
|
50250
|
+
captureMode = "print"
|
|
50251
|
+
} = opts;
|
|
50118
50252
|
const apiError = API_ERROR_RE.exec(stdoutTail);
|
|
50119
50253
|
if (apiError) {
|
|
50120
50254
|
return {
|
|
@@ -50151,9 +50285,10 @@ function classifyRunOutput(opts) {
|
|
|
50151
50285
|
re = null;
|
|
50152
50286
|
}
|
|
50153
50287
|
if (re && !re.test(haystack)) {
|
|
50288
|
+
const cause = captureMode === "stream-json" ? "Every assistant message this child produced was captured and concatenated, " + "so this is not the print-mode dropout: the model genuinely never emitted the " + "required shape. Re-prompt it, or relax the contract." : "This is the signature of a child that answered and then took one more turn: " + "`claude -p` prints only the FINAL assistant message, so a background task " + "completing (or any late notification) replaces the real answer with an " + "epilogue about it. The answer was generated, it just was not the last thing " + "said \u2014 re-run with the default stream-json capture to keep it.";
|
|
50154
50289
|
return {
|
|
50155
50290
|
reason: "shape_mismatch",
|
|
50156
|
-
detail: `Child exited 0 with ${outputSize} B, but the response does not match the ` + `required pattern /${requirePattern}/.
|
|
50291
|
+
detail: `Child exited 0 with ${outputSize} B, but the response does not match the ` + `required pattern /${requirePattern}/. ${cause}`
|
|
50157
50292
|
};
|
|
50158
50293
|
}
|
|
50159
50294
|
}
|
|
@@ -50269,6 +50404,7 @@ async function runModels(sessionPath, opts = {}) {
|
|
|
50269
50404
|
}
|
|
50270
50405
|
const minOutputBytes = opts.minOutputBytes ?? DEFAULT_MIN_OUTPUT_BYTES;
|
|
50271
50406
|
const requirePattern = opts.requirePattern;
|
|
50407
|
+
const captureMode = resolveCaptureMode(opts.captureMode);
|
|
50272
50408
|
mkdirSync12(statsDir(sessionPath), { recursive: true });
|
|
50273
50409
|
const processes = new Map;
|
|
50274
50410
|
const runtimes = new Map;
|
|
@@ -50285,7 +50421,14 @@ async function runModels(sessionPath, opts = {}) {
|
|
|
50285
50421
|
const outputPath = join28(sessionPath, `response-${anonId}.md`);
|
|
50286
50422
|
const errorLogPath = join28(sessionPath, "errors", `${anonId}.log`);
|
|
50287
50423
|
const spawnModel = spawnPlan.pinned.get(entry.model) ?? entry.model;
|
|
50288
|
-
const args = [
|
|
50424
|
+
const args = [
|
|
50425
|
+
"--model",
|
|
50426
|
+
spawnModel,
|
|
50427
|
+
"-y",
|
|
50428
|
+
"--stdin",
|
|
50429
|
+
...captureMode === "stream-json" ? ["--verbose", "--quiet", "--output-format", "stream-json"] : ["--quiet"],
|
|
50430
|
+
...opts.claudeFlags ?? []
|
|
50431
|
+
];
|
|
50289
50432
|
updateModelStatus(anonId, {
|
|
50290
50433
|
state: "RUNNING",
|
|
50291
50434
|
startedAt: new Date().toISOString()
|
|
@@ -50301,12 +50444,36 @@ async function runModels(sessionPath, opts = {}) {
|
|
|
50301
50444
|
});
|
|
50302
50445
|
let byteCount = 0;
|
|
50303
50446
|
let stdoutTail = "";
|
|
50304
|
-
proc.stdout?.on("data", (chunk) => {
|
|
50305
|
-
byteCount += chunk.length;
|
|
50306
|
-
stdoutTail = (stdoutTail + chunk.toString()).slice(-STDOUT_TAIL_LIMIT);
|
|
50307
|
-
});
|
|
50308
50447
|
const outputStream = createWriteStream2(outputPath);
|
|
50309
|
-
|
|
50448
|
+
let flushPartial = () => {};
|
|
50449
|
+
if (captureMode === "print") {
|
|
50450
|
+
proc.stdout?.on("data", (chunk) => {
|
|
50451
|
+
byteCount += chunk.length;
|
|
50452
|
+
stdoutTail = (stdoutTail + chunk.toString()).slice(-STDOUT_TAIL_LIMIT);
|
|
50453
|
+
});
|
|
50454
|
+
proc.stdout?.pipe(outputStream);
|
|
50455
|
+
} else {
|
|
50456
|
+
const capture = createAssistantTextCapture();
|
|
50457
|
+
const absorb = (text) => {
|
|
50458
|
+
if (text.length === 0)
|
|
50459
|
+
return;
|
|
50460
|
+
byteCount += Buffer.byteLength(text);
|
|
50461
|
+
stdoutTail = (stdoutTail + text).slice(-STDOUT_TAIL_LIMIT);
|
|
50462
|
+
outputStream.write(text);
|
|
50463
|
+
};
|
|
50464
|
+
proc.stdout?.on("data", (chunk) => absorb(capture.write(chunk.toString())));
|
|
50465
|
+
flushPartial = () => absorb(capture.end());
|
|
50466
|
+
let captureFinalized = false;
|
|
50467
|
+
const finalizeCapture = () => {
|
|
50468
|
+
if (captureFinalized)
|
|
50469
|
+
return;
|
|
50470
|
+
captureFinalized = true;
|
|
50471
|
+
absorb(capture.end());
|
|
50472
|
+
outputStream.end();
|
|
50473
|
+
};
|
|
50474
|
+
proc.stdout?.on("end", finalizeCapture);
|
|
50475
|
+
proc.stdout?.on("close", finalizeCapture);
|
|
50476
|
+
}
|
|
50310
50477
|
let stderr = "";
|
|
50311
50478
|
proc.stderr?.on("data", (chunk) => {
|
|
50312
50479
|
stderr += chunk.toString();
|
|
@@ -50317,7 +50484,8 @@ async function runModels(sessionPath, opts = {}) {
|
|
|
50317
50484
|
errorLogPath,
|
|
50318
50485
|
getStderr: () => stderr,
|
|
50319
50486
|
getStdoutTail: () => stdoutTail,
|
|
50320
|
-
getByteCount: () => byteCount
|
|
50487
|
+
getByteCount: () => byteCount,
|
|
50488
|
+
flushPartial: () => flushPartial()
|
|
50321
50489
|
});
|
|
50322
50490
|
proc.stdin?.write(inputContent);
|
|
50323
50491
|
proc.stdin?.end();
|
|
@@ -50347,7 +50515,8 @@ async function runModels(sessionPath, opts = {}) {
|
|
|
50347
50515
|
stderr,
|
|
50348
50516
|
minOutputBytes,
|
|
50349
50517
|
requirePattern,
|
|
50350
|
-
fullOutput
|
|
50518
|
+
fullOutput,
|
|
50519
|
+
captureMode
|
|
50351
50520
|
});
|
|
50352
50521
|
const failed = crashed || degraded !== null;
|
|
50353
50522
|
const state = crashed ? "FAILED" : degraded ? "EMPTY" : "COMPLETED";
|
|
@@ -50444,10 +50613,11 @@ async function runModels(sessionPath, opts = {}) {
|
|
|
50444
50613
|
if (!proc.killed)
|
|
50445
50614
|
proc.kill("SIGTERM");
|
|
50446
50615
|
const rt = runtimes.get(id);
|
|
50616
|
+
rt?.flushPartial();
|
|
50447
50617
|
const stderr = rt?.getStderr() ?? "";
|
|
50448
50618
|
const stdoutTail = rt?.getStdoutTail() ?? "";
|
|
50449
50619
|
const bytes2 = rt?.getByteCount() ?? 0;
|
|
50450
|
-
const detail = `Killed by the orchestrator after ${timeoutMs / 1000}s with ${bytes2} B of stdout. ` + "
|
|
50620
|
+
const detail = `Killed by the orchestrator after ${timeoutMs / 1000}s with ${bytes2} B of stdout. ` + "That figure counts the ANSWER, not the wire format, so 0 B means the child had " + `not produced an assistant message yet \u2014 "did not finish", not "produced nothing".`;
|
|
50451
50621
|
if (rt)
|
|
50452
50622
|
persistErrorLog(rt.errorLogPath, `TIMEOUT: ${detail}`, stderr, stdoutTail);
|
|
50453
50623
|
updateModelStatus(id, {
|
|
@@ -50659,11 +50829,12 @@ function formatVerdict(verdict, sessionPath) {
|
|
|
50659
50829
|
}
|
|
50660
50830
|
return output;
|
|
50661
50831
|
}
|
|
50662
|
-
var STDOUT_TAIL_LIMIT = 4000, API_ERROR_RE, BG_CEILING_RE, DEFAULT_MIN_OUTPUT_BYTES = 0, SENTINEL_MODELS;
|
|
50832
|
+
var TEAM_CAPTURE_ENV_VAR = "CLAUDISH_TEAM_CAPTURE", STDOUT_TAIL_LIMIT = 4000, API_ERROR_RE, BG_CEILING_RE, DEFAULT_MIN_OUTPUT_BYTES = 0, SENTINEL_MODELS;
|
|
50663
50833
|
var init_team_orchestrator = __esm(() => {
|
|
50664
50834
|
init_prehydrate();
|
|
50665
50835
|
init_redact();
|
|
50666
50836
|
init_team_stats();
|
|
50837
|
+
init_team_stream_capture();
|
|
50667
50838
|
API_ERROR_RE = /\[API Error:\s*([^\]]{0,300})\]/i;
|
|
50668
50839
|
BG_CEILING_RE = /Background tasks still running after (\d+)s; terminating/i;
|
|
50669
50840
|
SENTINEL_MODELS = new Set([
|
|
@@ -51189,7 +51360,7 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
|
|
|
51189
51360
|
timeout: { type: "number", description: "Per-model timeout in seconds (default: 300)" },
|
|
51190
51361
|
require_pattern: {
|
|
51191
51362
|
type: "string",
|
|
51192
|
-
description: "Regex the response MUST match, or the slot is reported FAILED (state EMPTY, " + "reason 'shape_mismatch') instead of succeeded. Strongly recommended whenever " + "your prompt mandates an output shape \u2014 e.g. '```vote' for a voting panel. " + "Exit code 0 is not a success oracle:
|
|
51363
|
+
description: "Regex the response MUST match, or the slot is reported FAILED (state EMPTY, " + "reason 'shape_mismatch') instead of succeeded. Strongly recommended whenever " + "your prompt mandates an output shape \u2014 e.g. '```vote' for a voting panel. " + "Exit code 0 is not a success oracle: it is 0 on API errors and on a child " + "that simply never followed the format. Answers are no longer LOST to print " + "mode (every assistant message is captured), so a mismatch now means the model " + "did not produce the shape, not that the shape was discarded."
|
|
51193
51364
|
},
|
|
51194
51365
|
min_output_bytes: {
|
|
51195
51366
|
type: "number",
|
|
@@ -51771,7 +51942,7 @@ var init_mcp_server = __esm(() => {
|
|
|
51771
51942
|
api_error: "retry once, or route via a different provider (or@<model>)",
|
|
51772
51943
|
background_task_ceiling: "set CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS=0 for children, or forbid background work in the prompt",
|
|
51773
51944
|
empty_output: "retry once; if it repeats, drop the model",
|
|
51774
|
-
shape_mismatch: "the
|
|
51945
|
+
shape_mismatch: "the response does not carry the shape you required. Every assistant message the " + "child emitted was captured, 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"
|
|
51775
51946
|
};
|
|
51776
51947
|
sanitize = sanitizeForReport;
|
|
51777
51948
|
EVENT_TO_TASK_STATUS = new Map([
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudish",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.50.0",
|
|
4
4
|
"description": "Run Claude Code with any model - OpenRouter, Ollama, LM Studio & local models",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -60,10 +60,10 @@
|
|
|
60
60
|
"ai"
|
|
61
61
|
],
|
|
62
62
|
"optionalDependencies": {
|
|
63
|
-
"@claudish/magmux-darwin-arm64": "7.
|
|
64
|
-
"@claudish/magmux-darwin-x64": "7.
|
|
65
|
-
"@claudish/magmux-linux-arm64": "7.
|
|
66
|
-
"@claudish/magmux-linux-x64": "7.
|
|
63
|
+
"@claudish/magmux-darwin-arm64": "7.50.0",
|
|
64
|
+
"@claudish/magmux-darwin-x64": "7.50.0",
|
|
65
|
+
"@claudish/magmux-linux-arm64": "7.50.0",
|
|
66
|
+
"@claudish/magmux-linux-x64": "7.50.0"
|
|
67
67
|
},
|
|
68
68
|
"author": "Jack Rudenko <i@madappgang.com>",
|
|
69
69
|
"license": "MIT",
|