@whittlelabs/sifter 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin.js +99 -9
- package/bin.js.map +2 -2
- package/package.json +1 -1
package/bin.js
CHANGED
|
@@ -19256,6 +19256,8 @@ var require_claude_code = __commonJS({
|
|
|
19256
19256
|
};
|
|
19257
19257
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
19258
19258
|
exports2.createClaudeCodeExecutor = createClaudeCodeExecutor;
|
|
19259
|
+
exports2.parseStreamJson = parseStreamJson;
|
|
19260
|
+
exports2.relativeWorkspaceReads = relativeWorkspaceReads;
|
|
19259
19261
|
exports2.extractJsonObject = extractJsonObject;
|
|
19260
19262
|
var child_process_1 = require("child_process");
|
|
19261
19263
|
var fs_1 = require("fs");
|
|
@@ -19323,8 +19325,13 @@ var require_claude_code = __commonJS({
|
|
|
19323
19325
|
const childEnv = buildChildEnv(credentials, configDir);
|
|
19324
19326
|
const claudeHints = (0, loom_1.pickProviderHints)(spec, "claude-code");
|
|
19325
19327
|
const hintedModel = typeof claudeHints.model === "string" && claudeHints.model.length > 0 ? claudeHints.model : void 0;
|
|
19326
|
-
const
|
|
19328
|
+
const runCwd = workspace?.cwd ?? this.config.cwd;
|
|
19329
|
+
const { response, readPaths } = await this.runClaude(prompt, spec, runCwd, childEnv, signal, hintedModel);
|
|
19327
19330
|
if (workspace) {
|
|
19331
|
+
response.outputs.push({
|
|
19332
|
+
label: "workspace_reads",
|
|
19333
|
+
content: { paths: relativeWorkspaceReads(readPaths, runCwd) }
|
|
19334
|
+
});
|
|
19328
19335
|
response.outputs.push({
|
|
19329
19336
|
label: "workspace",
|
|
19330
19337
|
content: {
|
|
@@ -19350,9 +19357,12 @@ var require_claude_code = __commonJS({
|
|
|
19350
19357
|
}
|
|
19351
19358
|
runClaude(prompt, spec, cwd, childEnv, signal, modelOverride) {
|
|
19352
19359
|
const outputLabel = spec.outputLabel;
|
|
19360
|
+
const model = modelOverride ?? this.config.model;
|
|
19353
19361
|
return new Promise((resolve, reject) => {
|
|
19354
|
-
const args = ["--print"];
|
|
19355
|
-
|
|
19362
|
+
const args = ["--print", "--output-format", "stream-json", "--verbose"];
|
|
19363
|
+
if (spec.outputSchema && typeof spec.outputSchema === "object" && Object.keys(spec.outputSchema).length > 0) {
|
|
19364
|
+
args.push("--json-schema", JSON.stringify(spec.outputSchema));
|
|
19365
|
+
}
|
|
19356
19366
|
if (model)
|
|
19357
19367
|
args.push("--model", model);
|
|
19358
19368
|
if (this.config.maxTurns !== void 0)
|
|
@@ -19411,13 +19421,28 @@ var require_claude_code = __commonJS({
|
|
|
19411
19421
|
const stdout = Buffer.concat(stdoutChunks).toString("utf-8");
|
|
19412
19422
|
if (code === 0) {
|
|
19413
19423
|
try {
|
|
19414
|
-
const
|
|
19424
|
+
const stream = parseStreamJson(stdout);
|
|
19425
|
+
if (stream.resultMeta?.isError) {
|
|
19426
|
+
throw new Error(`Claude Code reported ${stream.resultMeta.subtype ?? "an error"} on its terminal event`);
|
|
19427
|
+
}
|
|
19428
|
+
const answerText = stream.finalText ?? stdout;
|
|
19429
|
+
const parsed = stream.structuredOutput ?? extractJsonObject(answerText);
|
|
19430
|
+
if (parsed === void 0 && stream.resultMeta) {
|
|
19431
|
+
throw new Error(`claude's final message contained no JSON object (result subtype=${stream.resultMeta.subtype ?? "unknown"}; message head: ${JSON.stringify(answerText.slice(0, 160))})`);
|
|
19432
|
+
}
|
|
19415
19433
|
(0, validate_output_1.assertOutputValid)(spec, parsed);
|
|
19416
19434
|
settle(() => resolve({
|
|
19417
|
-
|
|
19418
|
-
|
|
19419
|
-
|
|
19420
|
-
|
|
19435
|
+
response: {
|
|
19436
|
+
outputs: [{ label: outputLabel, content: parsed ?? { raw: answerText } }],
|
|
19437
|
+
rawText: answerText,
|
|
19438
|
+
parsed,
|
|
19439
|
+
usage: {
|
|
19440
|
+
aiProvider: "claude-code",
|
|
19441
|
+
...model ? { aiModel: model } : {},
|
|
19442
|
+
...stream.usage ?? {}
|
|
19443
|
+
}
|
|
19444
|
+
},
|
|
19445
|
+
readPaths: stream.readPaths
|
|
19421
19446
|
}));
|
|
19422
19447
|
} catch (err) {
|
|
19423
19448
|
settle(() => reject(err instanceof Error ? err : new Error(String(err))));
|
|
@@ -19507,6 +19532,71 @@ var require_claude_code = __commonJS({
|
|
|
19507
19532
|
return credentials;
|
|
19508
19533
|
};
|
|
19509
19534
|
}
|
|
19535
|
+
function parseStreamJson(stdout) {
|
|
19536
|
+
let finalText = null;
|
|
19537
|
+
const readPaths = [];
|
|
19538
|
+
let usage = null;
|
|
19539
|
+
let resultMeta = null;
|
|
19540
|
+
let structuredOutput = null;
|
|
19541
|
+
for (const line of stdout.split("\n")) {
|
|
19542
|
+
const trimmed = line.trim();
|
|
19543
|
+
if (!trimmed.startsWith("{"))
|
|
19544
|
+
continue;
|
|
19545
|
+
let event;
|
|
19546
|
+
try {
|
|
19547
|
+
event = JSON.parse(trimmed);
|
|
19548
|
+
} catch {
|
|
19549
|
+
continue;
|
|
19550
|
+
}
|
|
19551
|
+
if (event.type === "assistant") {
|
|
19552
|
+
const content = event.message?.content;
|
|
19553
|
+
if (!Array.isArray(content))
|
|
19554
|
+
continue;
|
|
19555
|
+
for (const block of content) {
|
|
19556
|
+
const b = block;
|
|
19557
|
+
if (b?.type === "tool_use" && b.name === "Read" && typeof b.input?.file_path === "string") {
|
|
19558
|
+
readPaths.push(b.input.file_path);
|
|
19559
|
+
}
|
|
19560
|
+
}
|
|
19561
|
+
} else if (event.type === "result") {
|
|
19562
|
+
if (typeof event.result === "string" && event.result.trim().length > 0) {
|
|
19563
|
+
finalText = event.result;
|
|
19564
|
+
}
|
|
19565
|
+
resultMeta = {
|
|
19566
|
+
subtype: typeof event.subtype === "string" ? event.subtype : null,
|
|
19567
|
+
isError: event.is_error === true
|
|
19568
|
+
};
|
|
19569
|
+
const so = event.structured_output;
|
|
19570
|
+
if (so && typeof so === "object" && !Array.isArray(so)) {
|
|
19571
|
+
structuredOutput = so;
|
|
19572
|
+
}
|
|
19573
|
+
const u = event.usage;
|
|
19574
|
+
const cost = event.total_cost_usd;
|
|
19575
|
+
usage = {
|
|
19576
|
+
...typeof u?.input_tokens === "number" ? { inputTokens: u.input_tokens } : {},
|
|
19577
|
+
...typeof u?.output_tokens === "number" ? { outputTokens: u.output_tokens } : {},
|
|
19578
|
+
...typeof cost === "number" ? { costUsd: cost } : {}
|
|
19579
|
+
};
|
|
19580
|
+
}
|
|
19581
|
+
}
|
|
19582
|
+
return { finalText, readPaths, usage, resultMeta, structuredOutput };
|
|
19583
|
+
}
|
|
19584
|
+
var MAX_REPORTED_READS = 2e3;
|
|
19585
|
+
function relativeWorkspaceReads(readPaths, cwd) {
|
|
19586
|
+
const root = path_1.default.resolve(cwd);
|
|
19587
|
+
const out = /* @__PURE__ */ new Set();
|
|
19588
|
+
for (const p of readPaths) {
|
|
19589
|
+
const resolved = path_1.default.resolve(root, p);
|
|
19590
|
+
if (resolved === root)
|
|
19591
|
+
continue;
|
|
19592
|
+
if (!resolved.startsWith(root + path_1.default.sep))
|
|
19593
|
+
continue;
|
|
19594
|
+
out.add(resolved.slice(root.length + 1));
|
|
19595
|
+
if (out.size >= MAX_REPORTED_READS)
|
|
19596
|
+
break;
|
|
19597
|
+
}
|
|
19598
|
+
return [...out].sort();
|
|
19599
|
+
}
|
|
19510
19600
|
function extractJsonObject(s) {
|
|
19511
19601
|
const exact = tryParseObject(s);
|
|
19512
19602
|
if (exact)
|
|
@@ -21414,7 +21504,7 @@ var import_shuttle = __toESM(require_dist5());
|
|
|
21414
21504
|
// package.json
|
|
21415
21505
|
var package_default = {
|
|
21416
21506
|
name: "@whittlelabs/sifter",
|
|
21417
|
-
version: "0.
|
|
21507
|
+
version: "0.12.0",
|
|
21418
21508
|
description: "Whittle Sifter: paired AI reviewer for Whittle Sift job pools.",
|
|
21419
21509
|
bin: {
|
|
21420
21510
|
"whittle-sifter": "./dist/bin.js"
|