baro-ai 0.1.0 → 0.2.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/chunk-HWC47EK2.js +61 -0
- package/dist/cli.js +173 -55
- package/dist/core/executor.js +18 -70
- package/package.json +1 -1
- package/dist/chunk-3RG5ZIWI.js +0 -10
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// src/core/cli-task.ts
|
|
2
|
+
import { spawn } from "child_process";
|
|
3
|
+
var CliTask = class {
|
|
4
|
+
id;
|
|
5
|
+
opts;
|
|
6
|
+
constructor(opts) {
|
|
7
|
+
this.id = opts.id;
|
|
8
|
+
this.opts = opts;
|
|
9
|
+
}
|
|
10
|
+
execute() {
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
const start = Date.now();
|
|
13
|
+
let stdout = "";
|
|
14
|
+
let stderr = "";
|
|
15
|
+
const proc = spawn(this.opts.command, this.opts.args, {
|
|
16
|
+
cwd: this.opts.cwd,
|
|
17
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
18
|
+
env: { ...process.env }
|
|
19
|
+
});
|
|
20
|
+
proc.stdout.on("data", (chunk) => {
|
|
21
|
+
const text = chunk.toString();
|
|
22
|
+
stdout += text;
|
|
23
|
+
if (this.opts.onStdout) {
|
|
24
|
+
for (const line of text.split("\n").filter(Boolean)) {
|
|
25
|
+
this.opts.onStdout(line);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
proc.stderr.on("data", (chunk) => {
|
|
30
|
+
const text = chunk.toString();
|
|
31
|
+
stderr += text;
|
|
32
|
+
if (this.opts.onStderr) {
|
|
33
|
+
for (const line of text.split("\n").filter(Boolean)) {
|
|
34
|
+
this.opts.onStderr(line);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
proc.on("error", (err) => {
|
|
39
|
+
reject(new Error(`Failed to spawn ${this.opts.command}: ${err.message}`));
|
|
40
|
+
});
|
|
41
|
+
proc.on("close", (code) => {
|
|
42
|
+
const result = {
|
|
43
|
+
stdout,
|
|
44
|
+
stderr,
|
|
45
|
+
exitCode: code ?? 1,
|
|
46
|
+
durationMs: Date.now() - start
|
|
47
|
+
};
|
|
48
|
+
if (code === 0) resolve(result);
|
|
49
|
+
else {
|
|
50
|
+
const err = new Error(`${this.opts.command} exited with code ${code}`);
|
|
51
|
+
err.result = result;
|
|
52
|
+
reject(err);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export {
|
|
60
|
+
CliTask
|
|
61
|
+
};
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
} from "./chunk-
|
|
3
|
+
CliTask
|
|
4
|
+
} from "./chunk-HWC47EK2.js";
|
|
5
5
|
|
|
6
6
|
// src/cli.tsx
|
|
7
7
|
import { render, Box as Box6 } from "ink";
|
|
@@ -9,6 +9,7 @@ import { render, Box as Box6 } from "ink";
|
|
|
9
9
|
// src/App.tsx
|
|
10
10
|
import { useState as useState3 } from "react";
|
|
11
11
|
import { useApp as useApp2, useInput as useInput4 } from "ink";
|
|
12
|
+
import * as fs5 from "fs";
|
|
12
13
|
|
|
13
14
|
// src/screens/ApiKeyScreen.tsx
|
|
14
15
|
import { useState } from "react";
|
|
@@ -222,10 +223,10 @@ function createCodebaseTools(cwd) {
|
|
|
222
223
|
required: ["path"],
|
|
223
224
|
additionalProperties: false
|
|
224
225
|
},
|
|
225
|
-
async invoke(
|
|
226
|
-
const target = safePath(cwd,
|
|
227
|
-
if (!target || !fs2.existsSync(target)) return `Directory not found: ${
|
|
228
|
-
if (!fs2.statSync(target).isDirectory()) return `Not a directory: ${
|
|
226
|
+
async invoke(args2) {
|
|
227
|
+
const target = safePath(cwd, args2.path || ".");
|
|
228
|
+
if (!target || !fs2.existsSync(target)) return `Directory not found: ${args2.path}`;
|
|
229
|
+
if (!fs2.statSync(target).isDirectory()) return `Not a directory: ${args2.path}`;
|
|
229
230
|
const results = [];
|
|
230
231
|
function walk(dir, prefix, depth) {
|
|
231
232
|
if (results.length >= 200 || depth > 4) return;
|
|
@@ -234,7 +235,7 @@ function createCodebaseTools(cwd) {
|
|
|
234
235
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
235
236
|
if (entry.isDirectory()) {
|
|
236
237
|
results.push(rel + "/");
|
|
237
|
-
if (
|
|
238
|
+
if (args2.recursive) walk(path2.join(dir, entry.name), rel, depth + 1);
|
|
238
239
|
} else {
|
|
239
240
|
results.push(rel);
|
|
240
241
|
}
|
|
@@ -255,10 +256,10 @@ function createCodebaseTools(cwd) {
|
|
|
255
256
|
required: ["path"],
|
|
256
257
|
additionalProperties: false
|
|
257
258
|
},
|
|
258
|
-
async invoke(
|
|
259
|
-
const target = safePath(cwd,
|
|
260
|
-
if (!target || !fs2.existsSync(target)) return `File not found: ${
|
|
261
|
-
if (fs2.statSync(target).isDirectory()) return `${
|
|
259
|
+
async invoke(args2) {
|
|
260
|
+
const target = safePath(cwd, args2.path);
|
|
261
|
+
if (!target || !fs2.existsSync(target)) return `File not found: ${args2.path}`;
|
|
262
|
+
if (fs2.statSync(target).isDirectory()) return `${args2.path} is a directory. Use list_files.`;
|
|
262
263
|
if (fs2.statSync(target).size > 5e5) return `File too large (${(fs2.statSync(target).size / 1024).toFixed(0)}KB)`;
|
|
263
264
|
let content = fs2.readFileSync(target, "utf-8");
|
|
264
265
|
if (content.length > MAX_FILE_SIZE) {
|
|
@@ -280,13 +281,13 @@ function createCodebaseTools(cwd) {
|
|
|
280
281
|
required: ["pattern"],
|
|
281
282
|
additionalProperties: false
|
|
282
283
|
},
|
|
283
|
-
async invoke(
|
|
284
|
-
const searchDir = safePath(cwd,
|
|
285
|
-
if (!searchDir || !fs2.existsSync(searchDir)) return `Directory not found: ${
|
|
284
|
+
async invoke(args2) {
|
|
285
|
+
const searchDir = safePath(cwd, args2.path || ".");
|
|
286
|
+
if (!searchDir || !fs2.existsSync(searchDir)) return `Directory not found: ${args2.path}`;
|
|
286
287
|
try {
|
|
287
288
|
const excludes = Array.from(IGNORE).map((d) => `--exclude-dir=${d}`).join(" ");
|
|
288
|
-
const include =
|
|
289
|
-
const cmd = `grep -rn -i ${excludes} ${include} --max-count=50 -- ${JSON.stringify(
|
|
289
|
+
const include = args2.file_pattern ? `--include='${args2.file_pattern}'` : "";
|
|
290
|
+
const cmd = `grep -rn -i ${excludes} ${include} --max-count=50 -- ${JSON.stringify(args2.pattern)} ${JSON.stringify(searchDir)} 2>/dev/null || true`;
|
|
290
291
|
const output = execSync(cmd, { encoding: "utf-8", maxBuffer: 1024 * 1024 });
|
|
291
292
|
const lines = output.split("\n").filter(Boolean).map(
|
|
292
293
|
(line) => line.startsWith(cwd) ? line.slice(cwd.length + 1) : line
|
|
@@ -446,26 +447,136 @@ var Planner = class {
|
|
|
446
447
|
}
|
|
447
448
|
};
|
|
448
449
|
|
|
450
|
+
// src/core/claude-planner.ts
|
|
451
|
+
var SYSTEM_PROMPT2 = `You are an expert software architect. Break down the user's project goal into concrete user stories that form a dependency DAG.
|
|
452
|
+
|
|
453
|
+
You MUST explore the existing codebase first using your tools (read files, list directories, etc.) before generating the plan.
|
|
454
|
+
|
|
455
|
+
Output ONLY valid JSON matching this exact schema (no markdown, no explanation, just JSON):
|
|
456
|
+
{
|
|
457
|
+
"project": "short project name",
|
|
458
|
+
"branchName": "kebab-case-branch-name",
|
|
459
|
+
"description": "one-line description",
|
|
460
|
+
"userStories": [
|
|
461
|
+
{
|
|
462
|
+
"id": "S1",
|
|
463
|
+
"priority": 1,
|
|
464
|
+
"title": "short title",
|
|
465
|
+
"description": "what to implement",
|
|
466
|
+
"dependsOn": [],
|
|
467
|
+
"retries": 2,
|
|
468
|
+
"acceptance": ["testable criterion"],
|
|
469
|
+
"tests": ["npm test"]
|
|
470
|
+
}
|
|
471
|
+
]
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
Rules:
|
|
475
|
+
- Each story: single focused unit of work for one AI agent
|
|
476
|
+
- Use dependsOn for dependencies; same-priority stories with no deps run IN PARALLEL
|
|
477
|
+
- Keep stories small (15-60 min of work each)
|
|
478
|
+
- Include testable acceptance criteria and test commands
|
|
479
|
+
- No circular dependencies
|
|
480
|
+
- Start with foundational stories, build up
|
|
481
|
+
- IDs: S1, S2, S3...
|
|
482
|
+
- Build on existing code, don't recreate what exists
|
|
483
|
+
- Output ONLY the JSON, nothing else`;
|
|
484
|
+
var ClaudePlanner = class {
|
|
485
|
+
cwd;
|
|
486
|
+
onLog;
|
|
487
|
+
constructor(options = {}) {
|
|
488
|
+
this.cwd = options.cwd ?? process.cwd();
|
|
489
|
+
this.onLog = options.onLog;
|
|
490
|
+
}
|
|
491
|
+
async send(userMessage) {
|
|
492
|
+
const prompt = `${SYSTEM_PROMPT2}
|
|
493
|
+
|
|
494
|
+
User goal: ${userMessage}`;
|
|
495
|
+
const task = new CliTask({
|
|
496
|
+
id: "planner",
|
|
497
|
+
command: "claude",
|
|
498
|
+
args: [
|
|
499
|
+
"--dangerously-skip-permissions",
|
|
500
|
+
"--output-format",
|
|
501
|
+
"json",
|
|
502
|
+
"-p",
|
|
503
|
+
prompt
|
|
504
|
+
],
|
|
505
|
+
cwd: this.cwd,
|
|
506
|
+
onStdout: (line) => this.onLog?.(line),
|
|
507
|
+
onStderr: (line) => this.onLog?.(line)
|
|
508
|
+
});
|
|
509
|
+
const result = await task.execute();
|
|
510
|
+
let jsonText = result.stdout.trim();
|
|
511
|
+
try {
|
|
512
|
+
const wrapper = JSON.parse(jsonText);
|
|
513
|
+
if (wrapper.result) {
|
|
514
|
+
jsonText = wrapper.result;
|
|
515
|
+
}
|
|
516
|
+
} catch {
|
|
517
|
+
}
|
|
518
|
+
const jsonMatch = jsonText.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
519
|
+
if (jsonMatch) {
|
|
520
|
+
jsonText = jsonMatch[1].trim();
|
|
521
|
+
}
|
|
522
|
+
let prd;
|
|
523
|
+
try {
|
|
524
|
+
prd = JSON.parse(jsonText);
|
|
525
|
+
} catch {
|
|
526
|
+
throw new Error("Claude didn't return valid JSON. Try again with a clearer goal.");
|
|
527
|
+
}
|
|
528
|
+
if (!prd.project || !prd.userStories) {
|
|
529
|
+
throw new Error("Invalid plan format. Missing project or userStories.");
|
|
530
|
+
}
|
|
531
|
+
return {
|
|
532
|
+
...prd,
|
|
533
|
+
userStories: prd.userStories.map((s) => ({
|
|
534
|
+
id: s.id ?? "S?",
|
|
535
|
+
priority: s.priority ?? 0,
|
|
536
|
+
title: s.title ?? "",
|
|
537
|
+
description: s.description ?? "",
|
|
538
|
+
dependsOn: s.dependsOn ?? [],
|
|
539
|
+
retries: s.retries ?? 2,
|
|
540
|
+
acceptance: s.acceptance ?? [],
|
|
541
|
+
tests: s.tests ?? [],
|
|
542
|
+
passes: false,
|
|
543
|
+
completedAt: null,
|
|
544
|
+
durationSecs: null
|
|
545
|
+
}))
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
};
|
|
549
|
+
|
|
449
550
|
// src/screens/PlanScreen.tsx
|
|
450
551
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
451
|
-
function PlanScreen({ onPlanReady, onQuit }) {
|
|
552
|
+
function PlanScreen({ plannerMode: plannerMode2, onPlanReady, onQuit }) {
|
|
452
553
|
const [input, setInput] = useState2("");
|
|
453
554
|
const [loading, setLoading] = useState2(false);
|
|
454
555
|
const [tokenCount, setTokenCount] = useState2(0);
|
|
455
556
|
const [toolCalls, setToolCalls] = useState2([]);
|
|
456
557
|
const [error, setError] = useState2("");
|
|
457
|
-
const [planner] = useState2(() =>
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
558
|
+
const [planner] = useState2(() => {
|
|
559
|
+
if (plannerMode2 === "openai") {
|
|
560
|
+
return new Planner({
|
|
561
|
+
cwd: process.cwd(),
|
|
562
|
+
onToken: () => setTokenCount((c) => c + 1),
|
|
563
|
+
onToolCall: (name, args2) => {
|
|
564
|
+
let label = name;
|
|
565
|
+
if (name === "read_file") label = `Reading ${args2?.path ?? "..."}`;
|
|
566
|
+
else if (name === "grep") label = `Searching for "${args2?.pattern ?? "..."}"`;
|
|
567
|
+
else if (name === "list_files") label = `Listing ${args2?.path || "root"}`;
|
|
568
|
+
else if (name === "file_tree") label = "Scanning project structure";
|
|
569
|
+
setToolCalls((prev) => [...prev.slice(-8), label]);
|
|
570
|
+
}
|
|
571
|
+
});
|
|
467
572
|
}
|
|
468
|
-
|
|
573
|
+
return new ClaudePlanner({
|
|
574
|
+
cwd: process.cwd(),
|
|
575
|
+
onLog: (line) => {
|
|
576
|
+
setToolCalls((prev) => [...prev.slice(-8), line.slice(0, 80)]);
|
|
577
|
+
}
|
|
578
|
+
});
|
|
579
|
+
});
|
|
469
580
|
const submit = useCallback(async () => {
|
|
470
581
|
const goal = input.trim();
|
|
471
582
|
if (!goal) return;
|
|
@@ -665,14 +776,12 @@ function ExecuteScreen({ prd, onDone }) {
|
|
|
665
776
|
|
|
666
777
|
// src/App.tsx
|
|
667
778
|
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
668
|
-
function App() {
|
|
779
|
+
function App({ plannerMode: plannerMode2 }) {
|
|
669
780
|
const app = useApp2();
|
|
670
781
|
const [screen, setScreen] = useState3(() => {
|
|
671
|
-
if (
|
|
672
|
-
|
|
673
|
-
}
|
|
782
|
+
if (plannerMode2 === "claude") return "plan";
|
|
783
|
+
if (process.env.OPENAI_API_KEY) return "plan";
|
|
674
784
|
try {
|
|
675
|
-
const fs5 = __require("fs");
|
|
676
785
|
const home = process.env.HOME ?? "";
|
|
677
786
|
const envPath = `${home}/.baro/.env`;
|
|
678
787
|
if (fs5.existsSync(envPath)) {
|
|
@@ -681,33 +790,24 @@ function App() {
|
|
|
681
790
|
const [key, val] = line.split("=");
|
|
682
791
|
if (key && val) process.env[key.trim()] = val.trim();
|
|
683
792
|
}
|
|
684
|
-
if (process.env.OPENAI_API_KEY
|
|
685
|
-
return "plan";
|
|
686
|
-
}
|
|
793
|
+
if (process.env.OPENAI_API_KEY) return "plan";
|
|
687
794
|
}
|
|
688
795
|
} catch {
|
|
689
796
|
}
|
|
690
797
|
return "apikey";
|
|
691
798
|
});
|
|
692
799
|
const [prd, setPrd] = useState3(null);
|
|
693
|
-
useInput4((
|
|
694
|
-
if (key.escape && screen === "execute")
|
|
695
|
-
app.exit();
|
|
696
|
-
}
|
|
800
|
+
useInput4((_input, key) => {
|
|
801
|
+
if (key.escape && screen === "execute") app.exit();
|
|
697
802
|
});
|
|
698
803
|
if (screen === "apikey") {
|
|
699
|
-
return /* @__PURE__ */ jsx5(
|
|
700
|
-
ApiKeyScreen,
|
|
701
|
-
{
|
|
702
|
-
onComplete: () => setScreen("plan"),
|
|
703
|
-
onQuit: () => app.exit()
|
|
704
|
-
}
|
|
705
|
-
);
|
|
804
|
+
return /* @__PURE__ */ jsx5(ApiKeyScreen, { onComplete: () => setScreen("plan"), onQuit: () => app.exit() });
|
|
706
805
|
}
|
|
707
806
|
if (screen === "plan") {
|
|
708
807
|
return /* @__PURE__ */ jsx5(
|
|
709
808
|
PlanScreen,
|
|
710
809
|
{
|
|
810
|
+
plannerMode: plannerMode2,
|
|
711
811
|
onPlanReady: (plan) => {
|
|
712
812
|
setPrd(plan);
|
|
713
813
|
setScreen("review");
|
|
@@ -727,18 +827,36 @@ function App() {
|
|
|
727
827
|
}
|
|
728
828
|
);
|
|
729
829
|
}
|
|
730
|
-
return /* @__PURE__ */ jsx5(
|
|
731
|
-
ExecuteScreen,
|
|
732
|
-
{
|
|
733
|
-
prd,
|
|
734
|
-
onDone: () => app.exit()
|
|
735
|
-
}
|
|
736
|
-
);
|
|
830
|
+
return /* @__PURE__ */ jsx5(ExecuteScreen, { prd, onDone: () => app.exit() });
|
|
737
831
|
}
|
|
738
832
|
|
|
739
833
|
// src/cli.tsx
|
|
740
834
|
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
835
|
+
var args = process.argv.slice(2);
|
|
836
|
+
var plannerMode = "claude";
|
|
837
|
+
for (let i = 0; i < args.length; i++) {
|
|
838
|
+
if (args[i] === "--planner" && args[i + 1]) {
|
|
839
|
+
const val = args[i + 1].toLowerCase();
|
|
840
|
+
if (val === "openai" || val === "gpt" || val.startsWith("gpt-")) {
|
|
841
|
+
plannerMode = "openai";
|
|
842
|
+
}
|
|
843
|
+
i++;
|
|
844
|
+
}
|
|
845
|
+
if (args[i] === "--help" || args[i] === "-h") {
|
|
846
|
+
console.log(`
|
|
847
|
+
baro - autonomous parallel coding
|
|
848
|
+
|
|
849
|
+
Usage:
|
|
850
|
+
baro Plan with Claude Code, execute with Claude Code
|
|
851
|
+
baro --planner openai Plan with GPT-5.4 (needs OPENAI_API_KEY)
|
|
852
|
+
|
|
853
|
+
The default mode requires only Claude Code CLI installed.
|
|
854
|
+
No API keys needed.
|
|
855
|
+
`);
|
|
856
|
+
process.exit(0);
|
|
857
|
+
}
|
|
858
|
+
}
|
|
741
859
|
process.stdout.write("\x1B[2J\x1B[H");
|
|
742
860
|
render(
|
|
743
|
-
/* @__PURE__ */ jsx6(Box6, { width: "100%", flexDirection: "column", alignItems: "flex-start", children: /* @__PURE__ */ jsx6(App, {}) })
|
|
861
|
+
/* @__PURE__ */ jsx6(Box6, { width: "100%", flexDirection: "column", alignItems: "flex-start", children: /* @__PURE__ */ jsx6(App, { plannerMode }) })
|
|
744
862
|
);
|
package/dist/core/executor.js
CHANGED
|
@@ -1,68 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
2
|
+
import {
|
|
3
|
+
CliTask
|
|
4
|
+
} from "../chunk-HWC47EK2.js";
|
|
3
5
|
|
|
4
6
|
// src/core/executor.ts
|
|
5
7
|
import * as path from "path";
|
|
6
8
|
import * as fs from "fs";
|
|
7
9
|
|
|
8
|
-
// src/core/cli-task.ts
|
|
9
|
-
import { spawn } from "child_process";
|
|
10
|
-
var CliTask = class {
|
|
11
|
-
id;
|
|
12
|
-
opts;
|
|
13
|
-
constructor(opts) {
|
|
14
|
-
this.id = opts.id;
|
|
15
|
-
this.opts = opts;
|
|
16
|
-
}
|
|
17
|
-
execute() {
|
|
18
|
-
return new Promise((resolve, reject) => {
|
|
19
|
-
const start = Date.now();
|
|
20
|
-
let stdout = "";
|
|
21
|
-
let stderr = "";
|
|
22
|
-
const proc = spawn(this.opts.command, this.opts.args, {
|
|
23
|
-
cwd: this.opts.cwd,
|
|
24
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
25
|
-
env: { ...process.env }
|
|
26
|
-
});
|
|
27
|
-
proc.stdout.on("data", (chunk) => {
|
|
28
|
-
const text = chunk.toString();
|
|
29
|
-
stdout += text;
|
|
30
|
-
if (this.opts.onStdout) {
|
|
31
|
-
for (const line of text.split("\n").filter(Boolean)) {
|
|
32
|
-
this.opts.onStdout(line);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
proc.stderr.on("data", (chunk) => {
|
|
37
|
-
const text = chunk.toString();
|
|
38
|
-
stderr += text;
|
|
39
|
-
if (this.opts.onStderr) {
|
|
40
|
-
for (const line of text.split("\n").filter(Boolean)) {
|
|
41
|
-
this.opts.onStderr(line);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
proc.on("error", (err) => {
|
|
46
|
-
reject(new Error(`Failed to spawn ${this.opts.command}: ${err.message}`));
|
|
47
|
-
});
|
|
48
|
-
proc.on("close", (code) => {
|
|
49
|
-
const result = {
|
|
50
|
-
stdout,
|
|
51
|
-
stderr,
|
|
52
|
-
exitCode: code ?? 1,
|
|
53
|
-
durationMs: Date.now() - start
|
|
54
|
-
};
|
|
55
|
-
if (code === 0) resolve(result);
|
|
56
|
-
else {
|
|
57
|
-
const err = new Error(`${this.opts.command} exited with code ${code}`);
|
|
58
|
-
err.result = result;
|
|
59
|
-
reject(err);
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
|
|
66
10
|
// src/core/dag.ts
|
|
67
11
|
function buildDag(stories) {
|
|
68
12
|
const incomplete = stories.filter((s) => !s.passes);
|
|
@@ -137,7 +81,7 @@ async function main() {
|
|
|
137
81
|
const task = new CliTask({
|
|
138
82
|
id: story.id,
|
|
139
83
|
command: "claude",
|
|
140
|
-
args: ["--dangerously-skip-permissions", "--output-format", "stream-json", "-p", prompt],
|
|
84
|
+
args: ["--dangerously-skip-permissions", "--output-format", "stream-json", "--verbose", "-p", prompt],
|
|
141
85
|
cwd,
|
|
142
86
|
onStdout: (line) => {
|
|
143
87
|
try {
|
|
@@ -149,23 +93,27 @@ async function main() {
|
|
|
149
93
|
emit({ type: "story_log", id: story.id, line: l });
|
|
150
94
|
}
|
|
151
95
|
} else if (block.type === "tool_use") {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
if (text.length > 0) {
|
|
156
|
-
emit({ type: "story_log", id: story.id, line: text.slice(0, 150) });
|
|
157
|
-
}
|
|
96
|
+
const input = JSON.stringify(block.input ?? {});
|
|
97
|
+
const preview = input.length > 80 ? input.slice(0, 80) + "..." : input;
|
|
98
|
+
emit({ type: "story_log", id: story.id, line: `\u2699 ${block.name} ${preview}` });
|
|
158
99
|
}
|
|
159
100
|
}
|
|
101
|
+
} else if (ev.type === "system" && ev.subtype === "init") {
|
|
102
|
+
emit({ type: "story_log", id: story.id, line: `Model: ${ev.model ?? "unknown"}` });
|
|
160
103
|
} else if (ev.type === "result") {
|
|
104
|
+
if (ev.result) {
|
|
105
|
+
for (const l of String(ev.result).split("\n").slice(0, 3)) {
|
|
106
|
+
if (l.trim()) emit({ type: "story_log", id: story.id, line: l });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
161
109
|
}
|
|
162
110
|
} catch {
|
|
163
|
-
if (line.trim()) {
|
|
164
|
-
emit({ type: "story_log", id: story.id, line });
|
|
165
|
-
}
|
|
111
|
+
if (line.trim()) emit({ type: "story_log", id: story.id, line });
|
|
166
112
|
}
|
|
167
113
|
},
|
|
168
|
-
onStderr: (line) =>
|
|
114
|
+
onStderr: (line) => {
|
|
115
|
+
if (line.trim()) emit({ type: "story_log", id: story.id, line });
|
|
116
|
+
}
|
|
169
117
|
});
|
|
170
118
|
const result = await task.execute();
|
|
171
119
|
const dur = Math.round(result.durationMs / 1e3);
|
package/package.json
CHANGED
package/dist/chunk-3RG5ZIWI.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
-
}) : x)(function(x) {
|
|
4
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
export {
|
|
9
|
-
__require
|
|
10
|
-
};
|