sweteam 0.1.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/LICENSE +21 -0
- package/README.md +587 -0
- package/dist/adapters/adapter.d.ts +19 -0
- package/dist/adapters/adapter.d.ts.map +1 -0
- package/dist/adapters/adapter.js +20 -0
- package/dist/adapters/adapter.js.map +1 -0
- package/dist/adapters/claude-code.d.ts +13 -0
- package/dist/adapters/claude-code.d.ts.map +1 -0
- package/dist/adapters/claude-code.js +150 -0
- package/dist/adapters/claude-code.js.map +1 -0
- package/dist/adapters/codex.d.ts +13 -0
- package/dist/adapters/codex.d.ts.map +1 -0
- package/dist/adapters/codex.js +100 -0
- package/dist/adapters/codex.js.map +1 -0
- package/dist/adapters/custom.d.ts +16 -0
- package/dist/adapters/custom.d.ts.map +1 -0
- package/dist/adapters/custom.js +167 -0
- package/dist/adapters/custom.js.map +1 -0
- package/dist/adapters/opencode.d.ts +13 -0
- package/dist/adapters/opencode.d.ts.map +1 -0
- package/dist/adapters/opencode.js +100 -0
- package/dist/adapters/opencode.js.map +1 -0
- package/dist/adapters/prompt-detection.d.ts +14 -0
- package/dist/adapters/prompt-detection.d.ts.map +1 -0
- package/dist/adapters/prompt-detection.js +74 -0
- package/dist/adapters/prompt-detection.js.map +1 -0
- package/dist/commands/create.d.ts +8 -0
- package/dist/commands/create.d.ts.map +1 -0
- package/dist/commands/create.js +38 -0
- package/dist/commands/create.js.map +1 -0
- package/dist/commands/delete.d.ts +2 -0
- package/dist/commands/delete.d.ts.map +1 -0
- package/dist/commands/delete.js +22 -0
- package/dist/commands/delete.js.map +1 -0
- package/dist/commands/enter.d.ts +19 -0
- package/dist/commands/enter.d.ts.map +1 -0
- package/dist/commands/enter.js +73 -0
- package/dist/commands/enter.js.map +1 -0
- package/dist/commands/init.d.ts +14 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +52 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +8 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +98 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/show.d.ts +33 -0
- package/dist/commands/show.d.ts.map +1 -0
- package/dist/commands/show.js +142 -0
- package/dist/commands/show.js.map +1 -0
- package/dist/commands/stop.d.ts +2 -0
- package/dist/commands/stop.d.ts.map +1 -0
- package/dist/commands/stop.js +10 -0
- package/dist/commands/stop.js.map +1 -0
- package/dist/config/discovery.d.ts +12 -0
- package/dist/config/discovery.d.ts.map +1 -0
- package/dist/config/discovery.js +62 -0
- package/dist/config/discovery.js.map +1 -0
- package/dist/config/gh-auth.d.ts +5 -0
- package/dist/config/gh-auth.d.ts.map +1 -0
- package/dist/config/gh-auth.js +18 -0
- package/dist/config/gh-auth.js.map +1 -0
- package/dist/config/loader.d.ts +38 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +72 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/db/client.d.ts +10 -0
- package/dist/db/client.d.ts.map +1 -0
- package/dist/db/client.js +84 -0
- package/dist/db/client.js.map +1 -0
- package/dist/db/schema.d.ts +805 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/db/schema.js +66 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/git/git.d.ts +29 -0
- package/dist/git/git.d.ts.map +1 -0
- package/dist/git/git.js +200 -0
- package/dist/git/git.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +154 -0
- package/dist/index.js.map +1 -0
- package/dist/lifecycle.d.ts +5 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +63 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/orchestrator/build-handler.d.ts +20 -0
- package/dist/orchestrator/build-handler.d.ts.map +1 -0
- package/dist/orchestrator/build-handler.js +212 -0
- package/dist/orchestrator/build-handler.js.map +1 -0
- package/dist/orchestrator/dag.d.ts +10 -0
- package/dist/orchestrator/dag.d.ts.map +1 -0
- package/dist/orchestrator/dag.js +70 -0
- package/dist/orchestrator/dag.js.map +1 -0
- package/dist/orchestrator/error-handling.d.ts +21 -0
- package/dist/orchestrator/error-handling.d.ts.map +1 -0
- package/dist/orchestrator/error-handling.js +124 -0
- package/dist/orchestrator/error-handling.js.map +1 -0
- package/dist/orchestrator/feedback-handler.d.ts +36 -0
- package/dist/orchestrator/feedback-handler.d.ts.map +1 -0
- package/dist/orchestrator/feedback-handler.js +316 -0
- package/dist/orchestrator/feedback-handler.js.map +1 -0
- package/dist/orchestrator/orchestrator.d.ts +21 -0
- package/dist/orchestrator/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator/orchestrator.js +188 -0
- package/dist/orchestrator/orchestrator.js.map +1 -0
- package/dist/orchestrator/parallel-runner.d.ts +3 -0
- package/dist/orchestrator/parallel-runner.d.ts.map +1 -0
- package/dist/orchestrator/parallel-runner.js +111 -0
- package/dist/orchestrator/parallel-runner.js.map +1 -0
- package/dist/orchestrator/reviewer.d.ts +20 -0
- package/dist/orchestrator/reviewer.d.ts.map +1 -0
- package/dist/orchestrator/reviewer.js +175 -0
- package/dist/orchestrator/reviewer.js.map +1 -0
- package/dist/orchestrator/task-runner.d.ts +20 -0
- package/dist/orchestrator/task-runner.d.ts.map +1 -0
- package/dist/orchestrator/task-runner.js +122 -0
- package/dist/orchestrator/task-runner.js.map +1 -0
- package/dist/orchestrator/test-runner.d.ts +8 -0
- package/dist/orchestrator/test-runner.d.ts.map +1 -0
- package/dist/orchestrator/test-runner.js +81 -0
- package/dist/orchestrator/test-runner.js.map +1 -0
- package/dist/planner/plan-parser.d.ts +14 -0
- package/dist/planner/plan-parser.d.ts.map +1 -0
- package/dist/planner/plan-parser.js +182 -0
- package/dist/planner/plan-parser.js.map +1 -0
- package/dist/planner/planner.d.ts +9 -0
- package/dist/planner/planner.d.ts.map +1 -0
- package/dist/planner/planner.js +151 -0
- package/dist/planner/planner.js.map +1 -0
- package/dist/repl/repl.d.ts +19 -0
- package/dist/repl/repl.d.ts.map +1 -0
- package/dist/repl/repl.js +505 -0
- package/dist/repl/repl.js.map +1 -0
- package/dist/session/agent-log.d.ts +35 -0
- package/dist/session/agent-log.d.ts.map +1 -0
- package/dist/session/agent-log.js +120 -0
- package/dist/session/agent-log.js.map +1 -0
- package/dist/session/chat.d.ts +38 -0
- package/dist/session/chat.d.ts.map +1 -0
- package/dist/session/chat.js +106 -0
- package/dist/session/chat.js.map +1 -0
- package/dist/session/cost-tracker.d.ts +14 -0
- package/dist/session/cost-tracker.d.ts.map +1 -0
- package/dist/session/cost-tracker.js +61 -0
- package/dist/session/cost-tracker.js.map +1 -0
- package/dist/session/export.d.ts +2 -0
- package/dist/session/export.d.ts.map +1 -0
- package/dist/session/export.js +105 -0
- package/dist/session/export.js.map +1 -0
- package/dist/session/in-session-commands.d.ts +7 -0
- package/dist/session/in-session-commands.d.ts.map +1 -0
- package/dist/session/in-session-commands.js +227 -0
- package/dist/session/in-session-commands.js.map +1 -0
- package/dist/session/interactive.d.ts +37 -0
- package/dist/session/interactive.d.ts.map +1 -0
- package/dist/session/interactive.js +226 -0
- package/dist/session/interactive.js.map +1 -0
- package/dist/session/manager.d.ts +63 -0
- package/dist/session/manager.d.ts.map +1 -0
- package/dist/session/manager.js +229 -0
- package/dist/session/manager.js.map +1 -0
- package/dist/session/resume.d.ts +7 -0
- package/dist/session/resume.d.ts.map +1 -0
- package/dist/session/resume.js +53 -0
- package/dist/session/resume.js.map +1 -0
- package/dist/session/state-machine.d.ts +4 -0
- package/dist/session/state-machine.d.ts.map +1 -0
- package/dist/session/state-machine.js +47 -0
- package/dist/session/state-machine.js.map +1 -0
- package/dist/tui/chat-ui.d.ts +16 -0
- package/dist/tui/chat-ui.d.ts.map +1 -0
- package/dist/tui/chat-ui.js +19 -0
- package/dist/tui/chat-ui.js.map +1 -0
- package/dist/tui/dashboard.d.ts +17 -0
- package/dist/tui/dashboard.d.ts.map +1 -0
- package/dist/tui/dashboard.js +57 -0
- package/dist/tui/dashboard.js.map +1 -0
- package/dist/tui/session-list.d.ts +18 -0
- package/dist/tui/session-list.d.ts.map +1 -0
- package/dist/tui/session-list.js +26 -0
- package/dist/tui/session-list.js.map +1 -0
- package/dist/ui/agent-panel.d.ts +9 -0
- package/dist/ui/agent-panel.d.ts.map +1 -0
- package/dist/ui/agent-panel.js +100 -0
- package/dist/ui/agent-panel.js.map +1 -0
- package/dist/ui/banner.d.ts +10 -0
- package/dist/ui/banner.d.ts.map +1 -0
- package/dist/ui/banner.js +100 -0
- package/dist/ui/banner.js.map +1 -0
- package/dist/ui/markdown.d.ts +19 -0
- package/dist/ui/markdown.d.ts.map +1 -0
- package/dist/ui/markdown.js +174 -0
- package/dist/ui/markdown.js.map +1 -0
- package/dist/ui/prompt.d.ts +24 -0
- package/dist/ui/prompt.d.ts.map +1 -0
- package/dist/ui/prompt.js +226 -0
- package/dist/ui/prompt.js.map +1 -0
- package/dist/utils/time.d.ts +3 -0
- package/dist/utils/time.d.ts.map +1 -0
- package/dist/utils/time.js +29 -0
- package/dist/utils/time.js.map +1 -0
- package/drizzle/migrations/0000_naive_human_fly.sql +56 -0
- package/drizzle/migrations/meta/0000_snapshot.json +395 -0
- package/drizzle/migrations/meta/_journal.json +13 -0
- package/package.json +70 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { eq } from "drizzle-orm";
|
|
2
|
+
import { getDb } from "../db/client.js";
|
|
3
|
+
import { tasks as tasksTable } from "../db/schema.js";
|
|
4
|
+
import { loadConfig } from "../config/loader.js";
|
|
5
|
+
import { addMessage } from "../session/manager.js";
|
|
6
|
+
import { runTask } from "./task-runner.js";
|
|
7
|
+
import { reviewAndMerge } from "./reviewer.js";
|
|
8
|
+
import { buildDag, getReadyTasks } from "./dag.js";
|
|
9
|
+
import { getTasksForSession, displayTaskId } from "./orchestrator.js";
|
|
10
|
+
// Mutex for serializing merge operations
|
|
11
|
+
let merging = false;
|
|
12
|
+
const mergeQueue = [];
|
|
13
|
+
async function withMergeLock(fn) {
|
|
14
|
+
while (merging) {
|
|
15
|
+
await new Promise((resolve) => mergeQueue.push(resolve));
|
|
16
|
+
}
|
|
17
|
+
merging = true;
|
|
18
|
+
try {
|
|
19
|
+
return await fn();
|
|
20
|
+
}
|
|
21
|
+
finally {
|
|
22
|
+
merging = false;
|
|
23
|
+
const next = mergeQueue.shift();
|
|
24
|
+
if (next)
|
|
25
|
+
next();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async function runSingleTask(task, sessionBranch, repoPath, sessionId, maxReviewCycles) {
|
|
29
|
+
addMessage(sessionId, "system", `Starting task ${displayTaskId(task.id)}: ${task.title}`);
|
|
30
|
+
const result = await runTask(task, sessionBranch, repoPath);
|
|
31
|
+
if (!result.success) {
|
|
32
|
+
return { taskId: task.id, success: false };
|
|
33
|
+
}
|
|
34
|
+
// Reload task from DB
|
|
35
|
+
const updatedTasks = getTasksForSession(sessionId);
|
|
36
|
+
const updatedTask = updatedTasks.find((t) => t.id === task.id);
|
|
37
|
+
// Serialize merge operations
|
|
38
|
+
const reviewResult = await withMergeLock(async () => {
|
|
39
|
+
return reviewAndMerge(updatedTask, sessionBranch, repoPath, maxReviewCycles);
|
|
40
|
+
});
|
|
41
|
+
if (reviewResult.merged) {
|
|
42
|
+
addMessage(sessionId, "system", `Task ${displayTaskId(task.id)} completed and merged`);
|
|
43
|
+
return { taskId: task.id, success: true };
|
|
44
|
+
}
|
|
45
|
+
return { taskId: task.id, success: false };
|
|
46
|
+
}
|
|
47
|
+
export async function runParallelOrchestrator(sessionId, repoPath, sessionBranch) {
|
|
48
|
+
const config = loadConfig();
|
|
49
|
+
const maxParallel = config.execution.max_parallel;
|
|
50
|
+
const maxReviewCycles = config.execution.max_review_cycles;
|
|
51
|
+
const allTasks = getTasksForSession(sessionId);
|
|
52
|
+
const dag = buildDag(allTasks);
|
|
53
|
+
const completed = new Set();
|
|
54
|
+
const failed = new Set();
|
|
55
|
+
const blocked = new Set();
|
|
56
|
+
const running = new Set();
|
|
57
|
+
// Pre-populate from existing statuses
|
|
58
|
+
for (const task of allTasks) {
|
|
59
|
+
if (task.status === "done")
|
|
60
|
+
completed.add(task.id);
|
|
61
|
+
if (task.status === "failed")
|
|
62
|
+
failed.add(task.id);
|
|
63
|
+
if (task.status === "blocked")
|
|
64
|
+
blocked.add(task.id);
|
|
65
|
+
}
|
|
66
|
+
const taskMap = new Map(allTasks.map((t) => [t.id, t]));
|
|
67
|
+
while (true) {
|
|
68
|
+
const ready = getReadyTasks(dag, completed, running, failed, blocked);
|
|
69
|
+
if (ready.length === 0 && running.size === 0) {
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
// Launch tasks up to max_parallel
|
|
73
|
+
const toLaunch = ready.slice(0, maxParallel - running.size);
|
|
74
|
+
if (toLaunch.length === 0 && running.size > 0) {
|
|
75
|
+
// Wait for any running task to complete
|
|
76
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const promises = toLaunch.map(async (taskId) => {
|
|
80
|
+
running.add(taskId);
|
|
81
|
+
const task = taskMap.get(taskId);
|
|
82
|
+
const result = await runSingleTask(task, sessionBranch, repoPath, sessionId, maxReviewCycles);
|
|
83
|
+
running.delete(taskId);
|
|
84
|
+
if (result.success) {
|
|
85
|
+
completed.add(taskId);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
failed.add(taskId);
|
|
89
|
+
// Block dependents
|
|
90
|
+
const db = getDb();
|
|
91
|
+
const node = dag.get(taskId);
|
|
92
|
+
if (node) {
|
|
93
|
+
for (const depId of node.dependents) {
|
|
94
|
+
blocked.add(depId);
|
|
95
|
+
db.update(tasksTable)
|
|
96
|
+
.set({ status: "blocked", updatedAt: new Date() })
|
|
97
|
+
.where(eq(tasksTable.id, depId))
|
|
98
|
+
.run();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
await Promise.all(promises);
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
completed: [...completed],
|
|
107
|
+
failed: [...failed],
|
|
108
|
+
blocked: [...blocked],
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=parallel-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parallel-runner.js","sourceRoot":"","sources":["../../src/orchestrator/parallel-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { TaskRecord } from "./task-runner.js";
|
|
2
|
+
export interface ReviewResult {
|
|
3
|
+
verdict: "approve" | "request_changes";
|
|
4
|
+
issues: Array<{
|
|
5
|
+
file?: string;
|
|
6
|
+
line?: number;
|
|
7
|
+
severity?: "error" | "warning";
|
|
8
|
+
message: string;
|
|
9
|
+
}>;
|
|
10
|
+
summary: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function buildReviewerPrompt(task: TaskRecord, diff: string): string;
|
|
13
|
+
export declare function parseReviewResponse(output: string): ReviewResult;
|
|
14
|
+
export declare function reviewTask(task: TaskRecord, diff: string, repoPath: string, onOutput?: (chunk: string) => void, onInputNeeded?: (promptText: string) => Promise<string | null>): Promise<ReviewResult>;
|
|
15
|
+
export declare function mergeTask(task: TaskRecord, sessionBranch: string, repoPath: string): void;
|
|
16
|
+
export declare function reviewAndMerge(task: TaskRecord, sessionBranch: string, repoPath: string, maxCycles?: number, onOutput?: (chunk: string) => void, onInputNeeded?: (promptText: string) => Promise<string | null>): Promise<{
|
|
17
|
+
merged: boolean;
|
|
18
|
+
reviewResult: ReviewResult;
|
|
19
|
+
}>;
|
|
20
|
+
//# sourceMappingURL=reviewer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reviewer.d.ts","sourceRoot":"","sources":["../../src/orchestrator/reviewer.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,SAAS,GAAG,iBAAiB,CAAC;IACvC,MAAM,EAAE,KAAK,CAAC;QACZ,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;QAC/B,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;IACH,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,MAAM,GACX,MAAM,CA6BR;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAoBhE;AAED,wBAAsB,UAAU,CAC9B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,EAClC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAC7D,OAAO,CAAC,YAAY,CAAC,CAevB;AAED,wBAAgB,SAAS,CACvB,IAAI,EAAE,UAAU,EAChB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GACf,IAAI,CAqBN;AAED,wBAAsB,cAAc,CAClC,IAAI,EAAE,UAAU,EAChB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,MAAU,EACrB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,EAClC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAC7D,OAAO,CAAC;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,YAAY,CAAA;CAAE,CAAC,CA6F1D"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { eq } from "drizzle-orm";
|
|
2
|
+
import { getDb } from "../db/client.js";
|
|
3
|
+
import { tasks } from "../db/schema.js";
|
|
4
|
+
import { squashMerge, git } from "../git/git.js";
|
|
5
|
+
import { resolveAdapter } from "../adapters/adapter.js";
|
|
6
|
+
import { loadConfig } from "../config/loader.js";
|
|
7
|
+
import { displayTaskId } from "./orchestrator.js";
|
|
8
|
+
export function buildReviewerPrompt(task, diff) {
|
|
9
|
+
const criteria = task.acceptanceCriteria
|
|
10
|
+
? JSON.parse(task.acceptanceCriteria)
|
|
11
|
+
.map((c) => `- ${c}`)
|
|
12
|
+
.join("\n")
|
|
13
|
+
: "(none specified)";
|
|
14
|
+
return `You are a senior code reviewer. Review this diff for:
|
|
15
|
+
1. Correctness — does it meet the acceptance criteria?
|
|
16
|
+
2. Quality — clean code, no obvious bugs, proper error handling
|
|
17
|
+
3. Scope — only changes what's needed
|
|
18
|
+
|
|
19
|
+
## Task
|
|
20
|
+
${task.title}: ${task.description}
|
|
21
|
+
|
|
22
|
+
## Acceptance Criteria
|
|
23
|
+
${criteria}
|
|
24
|
+
|
|
25
|
+
## Diff
|
|
26
|
+
${diff}
|
|
27
|
+
|
|
28
|
+
Respond with ONLY valid JSON:
|
|
29
|
+
{
|
|
30
|
+
"verdict": "approve" | "request_changes",
|
|
31
|
+
"issues": [
|
|
32
|
+
{ "file": "...", "line": 42, "severity": "error|warning", "message": "..." }
|
|
33
|
+
],
|
|
34
|
+
"summary": "Overall assessment"
|
|
35
|
+
}`;
|
|
36
|
+
}
|
|
37
|
+
export function parseReviewResponse(output) {
|
|
38
|
+
// Try to extract JSON from response
|
|
39
|
+
const jsonMatch = output.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);
|
|
40
|
+
const jsonStr = jsonMatch ? jsonMatch[1] : output;
|
|
41
|
+
try {
|
|
42
|
+
const parsed = JSON.parse(jsonStr.trim());
|
|
43
|
+
return {
|
|
44
|
+
verdict: parsed.verdict === "approve" ? "approve" : "request_changes",
|
|
45
|
+
issues: Array.isArray(parsed.issues) ? parsed.issues : [],
|
|
46
|
+
summary: String(parsed.summary ?? ""),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// If parsing fails, reject — never auto-approve unreviewed code
|
|
51
|
+
return {
|
|
52
|
+
verdict: "request_changes",
|
|
53
|
+
issues: [{ message: "Review response could not be parsed as valid JSON" }],
|
|
54
|
+
summary: "Review response could not be parsed; requesting changes as a safety measure.",
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export async function reviewTask(task, diff, repoPath, onOutput, onInputNeeded) {
|
|
59
|
+
const config = loadConfig();
|
|
60
|
+
const adapter = resolveAdapter(config.roles.reviewer, config);
|
|
61
|
+
const prompt = buildReviewerPrompt(task, diff);
|
|
62
|
+
const result = await adapter.execute({
|
|
63
|
+
prompt,
|
|
64
|
+
cwd: repoPath,
|
|
65
|
+
timeout: 0,
|
|
66
|
+
onOutput,
|
|
67
|
+
onInputNeeded,
|
|
68
|
+
});
|
|
69
|
+
return parseReviewResponse(result.output);
|
|
70
|
+
}
|
|
71
|
+
export function mergeTask(task, sessionBranch, repoPath) {
|
|
72
|
+
const db = getDb();
|
|
73
|
+
if (!task.branchName) {
|
|
74
|
+
throw new Error(`Task ${task.id} has no branch name`);
|
|
75
|
+
}
|
|
76
|
+
squashMerge(task.branchName, sessionBranch, `feat: ${task.title} (#${displayTaskId(task.id)})`, repoPath);
|
|
77
|
+
db.update(tasks)
|
|
78
|
+
.set({
|
|
79
|
+
status: "done",
|
|
80
|
+
updatedAt: new Date(),
|
|
81
|
+
})
|
|
82
|
+
.where(eq(tasks.id, task.id))
|
|
83
|
+
.run();
|
|
84
|
+
}
|
|
85
|
+
export async function reviewAndMerge(task, sessionBranch, repoPath, maxCycles = 3, onOutput, onInputNeeded) {
|
|
86
|
+
const config = loadConfig();
|
|
87
|
+
const db = getDb();
|
|
88
|
+
for (let cycle = 0; cycle < maxCycles; cycle++) {
|
|
89
|
+
// Always get a fresh diff for this review cycle
|
|
90
|
+
const diff = git(["diff", `${sessionBranch}...${task.branchName}`], repoPath);
|
|
91
|
+
const reviewResult = await reviewTask(task, diff, repoPath, onOutput, onInputNeeded);
|
|
92
|
+
// Update review info in DB
|
|
93
|
+
db.update(tasks)
|
|
94
|
+
.set({
|
|
95
|
+
reviewVerdict: reviewResult.verdict,
|
|
96
|
+
reviewIssues: JSON.stringify(reviewResult.issues),
|
|
97
|
+
reviewCycles: cycle + 1,
|
|
98
|
+
updatedAt: new Date(),
|
|
99
|
+
})
|
|
100
|
+
.where(eq(tasks.id, task.id))
|
|
101
|
+
.run();
|
|
102
|
+
if (reviewResult.verdict === "approve") {
|
|
103
|
+
try {
|
|
104
|
+
mergeTask(task, sessionBranch, repoPath);
|
|
105
|
+
}
|
|
106
|
+
catch (mergeErr) {
|
|
107
|
+
const mergeMsg = mergeErr instanceof Error ? mergeErr.message : String(mergeErr);
|
|
108
|
+
// Attempt to abort a failed merge to restore clean state
|
|
109
|
+
try {
|
|
110
|
+
git(["merge", "--abort"], repoPath);
|
|
111
|
+
}
|
|
112
|
+
catch { /* no merge in progress */ }
|
|
113
|
+
db.update(tasks)
|
|
114
|
+
.set({ status: "failed", agentOutput: `Merge failed: ${mergeMsg}`, updatedAt: new Date() })
|
|
115
|
+
.where(eq(tasks.id, task.id))
|
|
116
|
+
.run();
|
|
117
|
+
return { merged: false, reviewResult: { verdict: "request_changes", issues: [{ message: `Merge failed: ${mergeMsg}` }], summary: mergeMsg } };
|
|
118
|
+
}
|
|
119
|
+
return { merged: true, reviewResult };
|
|
120
|
+
}
|
|
121
|
+
// Request changes — feed issues back to coder
|
|
122
|
+
if (cycle < maxCycles - 1) {
|
|
123
|
+
db.update(tasks)
|
|
124
|
+
.set({ status: "fixing", updatedAt: new Date() })
|
|
125
|
+
.where(eq(tasks.id, task.id))
|
|
126
|
+
.run();
|
|
127
|
+
// Ensure we're on the task branch before invoking the coder for fixes
|
|
128
|
+
if (task.branchName) {
|
|
129
|
+
try {
|
|
130
|
+
git(["checkout", task.branchName], repoPath);
|
|
131
|
+
}
|
|
132
|
+
catch { /* may already be on it */ }
|
|
133
|
+
}
|
|
134
|
+
const coderAdapter = resolveAdapter(config.roles.coder, config);
|
|
135
|
+
const fixPrompt = `The reviewer found issues with your implementation. Fix them:
|
|
136
|
+
|
|
137
|
+
${reviewResult.issues.map((i) => `- ${i.file ?? ""}:${i.line ?? ""} [${i.severity ?? "error"}] ${i.message}`).join("\n")}
|
|
138
|
+
|
|
139
|
+
Summary: ${reviewResult.summary}`;
|
|
140
|
+
await coderAdapter.execute({
|
|
141
|
+
prompt: fixPrompt,
|
|
142
|
+
cwd: repoPath,
|
|
143
|
+
timeout: 0,
|
|
144
|
+
onOutput,
|
|
145
|
+
onInputNeeded,
|
|
146
|
+
});
|
|
147
|
+
// Re-commit fixes
|
|
148
|
+
try {
|
|
149
|
+
git(["add", "-A"], repoPath);
|
|
150
|
+
git(["commit", "-m", `fix(${displayTaskId(task.id)}): address review feedback (cycle ${cycle + 2})`], repoPath);
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
// No changes to commit
|
|
154
|
+
}
|
|
155
|
+
db.update(tasks)
|
|
156
|
+
.set({ status: "reviewing", updatedAt: new Date() })
|
|
157
|
+
.where(eq(tasks.id, task.id))
|
|
158
|
+
.run();
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// Max cycles exhausted
|
|
162
|
+
db.update(tasks)
|
|
163
|
+
.set({ status: "failed", updatedAt: new Date() })
|
|
164
|
+
.where(eq(tasks.id, task.id))
|
|
165
|
+
.run();
|
|
166
|
+
return {
|
|
167
|
+
merged: false,
|
|
168
|
+
reviewResult: {
|
|
169
|
+
verdict: "request_changes",
|
|
170
|
+
issues: [],
|
|
171
|
+
summary: `Failed after ${maxCycles} review cycles`,
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=reviewer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reviewer.js","sourceRoot":"","sources":["../../src/orchestrator/reviewer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface TaskRecord {
|
|
2
|
+
id: string;
|
|
3
|
+
sessionId: string;
|
|
4
|
+
title: string;
|
|
5
|
+
description: string;
|
|
6
|
+
filesLikelyTouched: string | null;
|
|
7
|
+
acceptanceCriteria: string | null;
|
|
8
|
+
dependsOn: string | null;
|
|
9
|
+
branchName: string | null;
|
|
10
|
+
status: string;
|
|
11
|
+
diffPatch?: string | null;
|
|
12
|
+
}
|
|
13
|
+
export declare function buildCoderPrompt(task: TaskRecord, dependencyDiffs: string[]): string;
|
|
14
|
+
export declare function getDependencyDiffs(task: TaskRecord): string[];
|
|
15
|
+
export declare function runTask(task: TaskRecord, sessionBranch: string, repoPath: string, onOutput?: (chunk: string) => void, onInputNeeded?: (promptText: string) => Promise<string | null>): Promise<{
|
|
16
|
+
success: boolean;
|
|
17
|
+
output: string;
|
|
18
|
+
diff: string;
|
|
19
|
+
}>;
|
|
20
|
+
//# sourceMappingURL=task-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-runner.d.ts","sourceRoot":"","sources":["../../src/orchestrator/task-runner.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,UAAU,EAChB,eAAe,EAAE,MAAM,EAAE,GACxB,MAAM,CAmCR;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,EAAE,CAoB7D;AAED,wBAAsB,OAAO,CAC3B,IAAI,EAAE,UAAU,EAChB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,EAClC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAC7D,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CA0E7D"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { eq } from "drizzle-orm";
|
|
2
|
+
import { getDb } from "../db/client.js";
|
|
3
|
+
import { tasks } from "../db/schema.js";
|
|
4
|
+
import { git, createBranch, getDiff, getStagedDiff, commitAll } from "../git/git.js";
|
|
5
|
+
import { resolveAdapter } from "../adapters/adapter.js";
|
|
6
|
+
import { loadConfig } from "../config/loader.js";
|
|
7
|
+
import { displayTaskId } from "./orchestrator.js";
|
|
8
|
+
export function buildCoderPrompt(task, dependencyDiffs) {
|
|
9
|
+
const files = task.filesLikelyTouched
|
|
10
|
+
? JSON.parse(task.filesLikelyTouched).join("\n")
|
|
11
|
+
: "(not specified)";
|
|
12
|
+
const criteria = task.acceptanceCriteria
|
|
13
|
+
? JSON.parse(task.acceptanceCriteria)
|
|
14
|
+
.map((c) => `- ${c}`)
|
|
15
|
+
.join("\n")
|
|
16
|
+
: "(none specified)";
|
|
17
|
+
const contextDiffs = dependencyDiffs.length > 0
|
|
18
|
+
? dependencyDiffs.join("\n\n---\n\n")
|
|
19
|
+
: "(no prior tasks)";
|
|
20
|
+
return `You are implementing a specific task in a larger project.
|
|
21
|
+
|
|
22
|
+
## Task
|
|
23
|
+
${task.title}
|
|
24
|
+
|
|
25
|
+
## Description
|
|
26
|
+
${task.description}
|
|
27
|
+
|
|
28
|
+
## Acceptance Criteria
|
|
29
|
+
${criteria}
|
|
30
|
+
|
|
31
|
+
## Files You'll Likely Touch
|
|
32
|
+
${files}
|
|
33
|
+
|
|
34
|
+
## Context from Completed Tasks
|
|
35
|
+
${contextDiffs}
|
|
36
|
+
|
|
37
|
+
Implement this task completely. Create or modify files as needed.
|
|
38
|
+
Do not implement anything outside the scope of this task.`;
|
|
39
|
+
}
|
|
40
|
+
export function getDependencyDiffs(task) {
|
|
41
|
+
if (!task.dependsOn)
|
|
42
|
+
return [];
|
|
43
|
+
const db = getDb();
|
|
44
|
+
const depIds = JSON.parse(task.dependsOn);
|
|
45
|
+
const diffs = [];
|
|
46
|
+
for (const depId of depIds) {
|
|
47
|
+
const rows = db
|
|
48
|
+
.select({ diffPatch: tasks.diffPatch })
|
|
49
|
+
.from(tasks)
|
|
50
|
+
.where(eq(tasks.id, depId))
|
|
51
|
+
.all();
|
|
52
|
+
if (rows.length > 0 && rows[0].diffPatch) {
|
|
53
|
+
diffs.push(rows[0].diffPatch);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return diffs;
|
|
57
|
+
}
|
|
58
|
+
export async function runTask(task, sessionBranch, repoPath, onOutput, onInputNeeded) {
|
|
59
|
+
const config = loadConfig();
|
|
60
|
+
const db = getDb();
|
|
61
|
+
// Create task branch — use dash separator to avoid git ref conflicts.
|
|
62
|
+
// Session branch is "sw/s_ID" so task branch must NOT nest under it
|
|
63
|
+
// (git forbids both refs/heads/sw/X and refs/heads/sw/X/Y).
|
|
64
|
+
// e.g. "s_UclHjgC1:1" → "sw/s_UclHjgC1-1-add-cachetools-dependency"
|
|
65
|
+
const safeBranchId = task.id.replace(/:/g, "-").replace(/[^a-zA-Z0-9/_-]/g, "");
|
|
66
|
+
const branchName = `sw/${safeBranchId}-${task.title.toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, 30)}`;
|
|
67
|
+
createBranch(branchName, sessionBranch, repoPath);
|
|
68
|
+
// Update task in DB
|
|
69
|
+
db.update(tasks)
|
|
70
|
+
.set({
|
|
71
|
+
status: "running",
|
|
72
|
+
branchName,
|
|
73
|
+
updatedAt: new Date(),
|
|
74
|
+
})
|
|
75
|
+
.where(eq(tasks.id, task.id))
|
|
76
|
+
.run();
|
|
77
|
+
// Build prompt
|
|
78
|
+
const depDiffs = getDependencyDiffs(task);
|
|
79
|
+
const prompt = buildCoderPrompt(task, depDiffs);
|
|
80
|
+
// Invoke coder agent
|
|
81
|
+
const adapter = resolveAdapter(config.roles.coder, config);
|
|
82
|
+
try {
|
|
83
|
+
const result = await adapter.execute({
|
|
84
|
+
prompt,
|
|
85
|
+
cwd: repoPath,
|
|
86
|
+
timeout: 0,
|
|
87
|
+
onOutput,
|
|
88
|
+
onInputNeeded,
|
|
89
|
+
});
|
|
90
|
+
// Commit any uncommitted changes the coder left behind (staged or unstaged)
|
|
91
|
+
const uncommitted = getDiff(repoPath) || getStagedDiff(repoPath);
|
|
92
|
+
if (uncommitted.length > 0) {
|
|
93
|
+
commitAll(`feat(${displayTaskId(task.id)}): ${task.title}`, repoPath);
|
|
94
|
+
}
|
|
95
|
+
// Capture the full diff of this task branch vs the session branch
|
|
96
|
+
const diff = git(["diff", `${sessionBranch}...HEAD`], repoPath);
|
|
97
|
+
// Update DB with results
|
|
98
|
+
db.update(tasks)
|
|
99
|
+
.set({
|
|
100
|
+
agentOutput: result.output,
|
|
101
|
+
diffPatch: diff || null,
|
|
102
|
+
status: "reviewing",
|
|
103
|
+
updatedAt: new Date(),
|
|
104
|
+
})
|
|
105
|
+
.where(eq(tasks.id, task.id))
|
|
106
|
+
.run();
|
|
107
|
+
return { success: true, output: result.output, diff };
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
111
|
+
db.update(tasks)
|
|
112
|
+
.set({
|
|
113
|
+
status: "failed",
|
|
114
|
+
agentOutput: `Error: ${message}`,
|
|
115
|
+
updatedAt: new Date(),
|
|
116
|
+
})
|
|
117
|
+
.where(eq(tasks.id, task.id))
|
|
118
|
+
.run();
|
|
119
|
+
return { success: false, output: message, diff: "" };
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=task-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-runner.js","sourceRoot":"","sources":["../../src/orchestrator/task-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface TestResult {
|
|
2
|
+
passed: boolean;
|
|
3
|
+
output: string;
|
|
4
|
+
command: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function runTests(repoPath: string, sessionId: string): TestResult;
|
|
7
|
+
export declare function parseTestFailures(output: string): string[];
|
|
8
|
+
//# sourceMappingURL=test-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-runner.d.ts","sourceRoot":"","sources":["../../src/orchestrator/test-runner.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAqCD,wBAAgB,QAAQ,CACtB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,UAAU,CA+BZ;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAoB1D"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { execFileSync } from "child_process";
|
|
2
|
+
import { existsSync, readFileSync } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { addMessage } from "../session/manager.js";
|
|
5
|
+
function detectTestCommand(repoPath) {
|
|
6
|
+
const pkgPath = join(repoPath, "package.json");
|
|
7
|
+
if (existsSync(pkgPath)) {
|
|
8
|
+
try {
|
|
9
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
10
|
+
if (pkg.scripts?.test && pkg.scripts.test !== 'echo "Error: no test specified" && exit 1') {
|
|
11
|
+
return "npm test";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
catch { }
|
|
15
|
+
}
|
|
16
|
+
if (existsSync(join(repoPath, "Cargo.toml"))) {
|
|
17
|
+
return "cargo test";
|
|
18
|
+
}
|
|
19
|
+
if (existsSync(join(repoPath, "go.mod"))) {
|
|
20
|
+
return "go test ./...";
|
|
21
|
+
}
|
|
22
|
+
if (existsSync(join(repoPath, "pyproject.toml")) || existsSync(join(repoPath, "pytest.ini"))) {
|
|
23
|
+
return "pytest";
|
|
24
|
+
}
|
|
25
|
+
if (existsSync(join(repoPath, "Makefile"))) {
|
|
26
|
+
try {
|
|
27
|
+
const makefile = readFileSync(join(repoPath, "Makefile"), "utf-8");
|
|
28
|
+
if (makefile.includes("test:")) {
|
|
29
|
+
return "make test";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
catch { }
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
export function runTests(repoPath, sessionId) {
|
|
37
|
+
const command = detectTestCommand(repoPath);
|
|
38
|
+
if (!command) {
|
|
39
|
+
return {
|
|
40
|
+
passed: true,
|
|
41
|
+
output: "No test command detected, skipping tests.",
|
|
42
|
+
command: "(none)",
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
addMessage(sessionId, "system", `Running tests: ${command}`);
|
|
46
|
+
try {
|
|
47
|
+
const [cmd, ...args] = command.split(" ");
|
|
48
|
+
const output = execFileSync(cmd, args, {
|
|
49
|
+
cwd: repoPath,
|
|
50
|
+
encoding: "utf-8",
|
|
51
|
+
timeout: 120000,
|
|
52
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
53
|
+
});
|
|
54
|
+
return { passed: true, output, command };
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
const output = err instanceof Error && "stdout" in err
|
|
58
|
+
? String(err.stdout)
|
|
59
|
+
: String(err);
|
|
60
|
+
return { passed: false, output, command };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
export function parseTestFailures(output) {
|
|
64
|
+
const failures = [];
|
|
65
|
+
// Common patterns
|
|
66
|
+
const failPatterns = [
|
|
67
|
+
/FAIL\s+(.+)/g,
|
|
68
|
+
/✗\s+(.+)/g,
|
|
69
|
+
/FAILED\s+(.+)/g,
|
|
70
|
+
/Error:\s+(.+)/g,
|
|
71
|
+
/AssertionError:\s+(.+)/g,
|
|
72
|
+
];
|
|
73
|
+
for (const pattern of failPatterns) {
|
|
74
|
+
let match;
|
|
75
|
+
while ((match = pattern.exec(output)) !== null) {
|
|
76
|
+
failures.push(match[1].trim());
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return failures;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=test-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-runner.js","sourceRoot":"","sources":["../../src/orchestrator/test-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface ParsedTask {
|
|
2
|
+
id: string;
|
|
3
|
+
title: string;
|
|
4
|
+
description: string;
|
|
5
|
+
filesLikelyTouched: string[];
|
|
6
|
+
dependsOn: string[];
|
|
7
|
+
acceptanceCriteria: string[];
|
|
8
|
+
}
|
|
9
|
+
export interface ParsedPlan {
|
|
10
|
+
tasks: ParsedTask[];
|
|
11
|
+
raw: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function parsePlan(agentOutput: string): ParsedPlan;
|
|
14
|
+
//# sourceMappingURL=plan-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-parser.d.ts","sourceRoot":"","sources":["../../src/planner/plan-parser.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,kBAAkB,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;CACb;AA4LD,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,UAAU,CA2BzD"}
|