oh-pi 0.1.53 → 0.1.54
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/package.json
CHANGED
|
@@ -72,7 +72,7 @@ function makeInitialScoutTask(goal: string): Task {
|
|
|
72
72
|
|
|
73
73
|
function childTaskFromParsed(
|
|
74
74
|
parentId: string,
|
|
75
|
-
parsed: { title: string; description: string; files: string[]; caste: AntCaste; priority: TaskPriority },
|
|
75
|
+
parsed: { title: string; description: string; files: string[]; caste: AntCaste; priority: TaskPriority; context?: string },
|
|
76
76
|
): Task {
|
|
77
77
|
return {
|
|
78
78
|
id: makeTaskId(),
|
|
@@ -83,6 +83,7 @@ function childTaskFromParsed(
|
|
|
83
83
|
status: "pending",
|
|
84
84
|
priority: parsed.priority,
|
|
85
85
|
files: parsed.files,
|
|
86
|
+
context: parsed.context || undefined,
|
|
86
87
|
claimedBy: null,
|
|
87
88
|
result: null,
|
|
88
89
|
error: null,
|
|
@@ -398,9 +399,18 @@ export async function runColony(opts: QueenOptions): Promise<ColonyState> {
|
|
|
398
399
|
await runAntWave({ ...waveBase, caste: "worker" });
|
|
399
400
|
}
|
|
400
401
|
|
|
402
|
+
// ═══ Auto-check: run tsc before soldier review ═══
|
|
403
|
+
let tscPassed = true;
|
|
404
|
+
try {
|
|
405
|
+
const { execSync } = await import("node:child_process");
|
|
406
|
+
execSync("npx tsc --noEmit", { cwd: opts.cwd, timeout: 30000, stdio: "pipe" });
|
|
407
|
+
} catch {
|
|
408
|
+
tscPassed = false;
|
|
409
|
+
}
|
|
410
|
+
|
|
401
411
|
// ═══ Phase 3: 审查 ═══
|
|
402
412
|
const completedWorkerTasks = nest.getAllTasks().filter(t => t.caste === "worker" && t.status === "done");
|
|
403
|
-
if (completedWorkerTasks.length > 0) {
|
|
413
|
+
if (completedWorkerTasks.length > 0 && (!tscPassed || completedWorkerTasks.length > 3)) {
|
|
404
414
|
nest.updateState({ status: "reviewing" });
|
|
405
415
|
callbacks.onPhase("reviewing", "Dispatching soldier ants to review changes...");
|
|
406
416
|
const reviewTask = makeReviewTask(completedWorkerTasks);
|
|
@@ -57,6 +57,7 @@ export interface ParsedSubTask {
|
|
|
57
57
|
files: string[];
|
|
58
58
|
caste: AntCaste;
|
|
59
59
|
priority: 1 | 2 | 3 | 4 | 5;
|
|
60
|
+
context?: string;
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
const CASTE_PROMPTS: Record<AntCaste, string> = {
|
|
@@ -67,6 +68,7 @@ Behavior:
|
|
|
67
68
|
- Identify files, functions, dependencies related to the goal
|
|
68
69
|
- IMPORTANT: After EACH tool call, summarize what you found so far. Do NOT wait until the end.
|
|
69
70
|
- Report findings as structured intelligence for Worker Ants
|
|
71
|
+
- For each recommended task, include the KEY code snippets (with file:line) the worker will need — this saves workers from re-reading files
|
|
70
72
|
|
|
71
73
|
Output format (MUST follow exactly):
|
|
72
74
|
## Discoveries
|
|
@@ -79,6 +81,7 @@ For each task the colony should do next:
|
|
|
79
81
|
- files: <comma-separated file paths>
|
|
80
82
|
- caste: worker
|
|
81
83
|
- priority: <1-5, 1=highest>
|
|
84
|
+
- context: <relevant code snippets that the worker will need, with file:line references>
|
|
82
85
|
|
|
83
86
|
## Warnings
|
|
84
87
|
Any risks, blockers, or conflicts detected.`,
|
|
@@ -142,6 +145,9 @@ function buildPrompt(task: Task, pheromoneContext: string, castePrompt: string,
|
|
|
142
145
|
if (task.files.length > 0) {
|
|
143
146
|
prompt += `**Files scope:** ${task.files.join(", ")}\n`;
|
|
144
147
|
}
|
|
148
|
+
if (task.context) {
|
|
149
|
+
prompt += `\n## Pre-loaded Context (from scout)\n${task.context}\n`;
|
|
150
|
+
}
|
|
145
151
|
if (/[\u4e00-\u9fff]/.test(task.description)) {
|
|
146
152
|
prompt += '\nIMPORTANT: Follow the language requirements specified in the task description. If the task says to write in Chinese, write in Chinese.\n';
|
|
147
153
|
}
|
|
@@ -152,13 +158,18 @@ function buildPrompt(task: Task, pheromoneContext: string, castePrompt: string,
|
|
|
152
158
|
function parseSubTasks(output: string): ParsedSubTask[] {
|
|
153
159
|
const tasks: ParsedSubTask[] = [];
|
|
154
160
|
const regex = /### TASK:\s*(.+)\n(?:- description:\s*(.+)\n)?(?:- files:\s*(.+)\n)?(?:- caste:\s*(\w+)\n)?(?:- priority:\s*(\d))?/g;
|
|
161
|
+
const taskBlocks = output.split(/(?=### TASK:)/);
|
|
155
162
|
for (const m of output.matchAll(regex)) {
|
|
163
|
+
const block = taskBlocks.find(b => b.includes(`### TASK: ${m[1]?.trim()}`)) || "";
|
|
164
|
+
const ctxMatch = block.match(/- context:\s*([\s\S]*?)(?=### TASK:|## |\n\n|$)/);
|
|
165
|
+
const context = ctxMatch?.[1]?.trim() || undefined;
|
|
156
166
|
tasks.push({
|
|
157
167
|
title: m[1]?.trim() || "Untitled",
|
|
158
168
|
description: m[2]?.trim() || m[1]?.trim() || "",
|
|
159
169
|
files: (m[3]?.trim() || "").split(",").map(f => f.trim()).filter(Boolean),
|
|
160
170
|
caste: (m[4]?.trim() as AntCaste) || "worker",
|
|
161
171
|
priority: (parseInt(m[5] || "3") as 1 | 2 | 3 | 4 | 5) || 3,
|
|
172
|
+
context,
|
|
162
173
|
});
|
|
163
174
|
}
|
|
164
175
|
return tasks;
|