ferix-code 0.0.2 → 0.0.3-beta.1
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-ENDDBBCW.js +74 -0
- package/dist/chunk-ILHJ3OBF.js +37 -0
- package/dist/chunk-XIEB473E.js +358 -0
- package/dist/index.js +1013 -1606
- package/dist/prompt-YXBU2FXF.js +14 -0
- package/dist/task-generation-YN2MKKY4.js +50 -0
- package/package.json +6 -1
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
init_esm_shims
|
|
4
|
+
} from "./chunk-ILHJ3OBF.js";
|
|
5
|
+
|
|
6
|
+
// src/commands/code/domain/errors.ts
|
|
7
|
+
init_esm_shims();
|
|
8
|
+
import { Data } from "effect";
|
|
9
|
+
var LLMError = class extends Data.TaggedError("LLMError") {
|
|
10
|
+
};
|
|
11
|
+
var ParseError = class extends Data.TaggedError("ParseError") {
|
|
12
|
+
};
|
|
13
|
+
var PlanStoreError = class extends Data.TaggedError("PlanStoreError") {
|
|
14
|
+
};
|
|
15
|
+
var SessionStoreError = class extends Data.TaggedError("SessionStoreError") {
|
|
16
|
+
};
|
|
17
|
+
var ProgressStoreError = class extends Data.TaggedError("ProgressStoreError") {
|
|
18
|
+
};
|
|
19
|
+
var GuardrailsStoreError = class extends Data.TaggedError(
|
|
20
|
+
"GuardrailsStoreError"
|
|
21
|
+
) {
|
|
22
|
+
};
|
|
23
|
+
var OrchestratorError = class extends Data.TaggedError("OrchestratorError") {
|
|
24
|
+
};
|
|
25
|
+
var GitError = class extends Data.TaggedError("GitError") {
|
|
26
|
+
};
|
|
27
|
+
var TokenBudgetError = class extends Data.TaggedError("TokenBudgetError") {
|
|
28
|
+
};
|
|
29
|
+
var RetryExhaustedError = class extends Data.TaggedError(
|
|
30
|
+
"RetryExhaustedError"
|
|
31
|
+
) {
|
|
32
|
+
};
|
|
33
|
+
var StateStoreError = class extends Data.TaggedError("StateStoreError") {
|
|
34
|
+
};
|
|
35
|
+
var PromptStoreError = class extends Data.TaggedError("PromptStoreError") {
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// src/commands/code/domain/schemas/task-generation.ts
|
|
39
|
+
init_esm_shims();
|
|
40
|
+
import { Schema as S } from "effect";
|
|
41
|
+
var GeneratedTaskStatusSchema = S.Literal(
|
|
42
|
+
"pending",
|
|
43
|
+
"in_progress",
|
|
44
|
+
"done",
|
|
45
|
+
"failed"
|
|
46
|
+
);
|
|
47
|
+
var GeneratedTaskSchema = S.Struct({
|
|
48
|
+
id: S.String,
|
|
49
|
+
title: S.String,
|
|
50
|
+
description: S.String,
|
|
51
|
+
status: GeneratedTaskStatusSchema,
|
|
52
|
+
steps: S.Array(S.String)
|
|
53
|
+
});
|
|
54
|
+
var TasksFileSchema = S.Struct({
|
|
55
|
+
sessionId: S.String,
|
|
56
|
+
originalTask: S.String,
|
|
57
|
+
tasks: S.Array(GeneratedTaskSchema)
|
|
58
|
+
});
|
|
59
|
+
function formatTasksJson(tasksFile) {
|
|
60
|
+
return JSON.stringify(tasksFile, null, 2);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export {
|
|
64
|
+
LLMError,
|
|
65
|
+
PlanStoreError,
|
|
66
|
+
SessionStoreError,
|
|
67
|
+
ProgressStoreError,
|
|
68
|
+
GuardrailsStoreError,
|
|
69
|
+
OrchestratorError,
|
|
70
|
+
GitError,
|
|
71
|
+
StateStoreError,
|
|
72
|
+
PromptStoreError,
|
|
73
|
+
formatTasksJson
|
|
74
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __esm = (fn, res) => function __init() {
|
|
7
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
8
|
+
};
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
22
|
+
|
|
23
|
+
// ../../node_modules/.bun/tsup@8.5.1+8346c6f35f8a3409/node_modules/tsup/assets/esm_shims.js
|
|
24
|
+
import path from "path";
|
|
25
|
+
import { fileURLToPath } from "url";
|
|
26
|
+
var init_esm_shims = __esm({
|
|
27
|
+
"../../node_modules/.bun/tsup@8.5.1+8346c6f35f8a3409/node_modules/tsup/assets/esm_shims.js"() {
|
|
28
|
+
"use strict";
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
export {
|
|
33
|
+
__esm,
|
|
34
|
+
__export,
|
|
35
|
+
__toCommonJS,
|
|
36
|
+
init_esm_shims
|
|
37
|
+
};
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
init_esm_shims
|
|
4
|
+
} from "./chunk-ILHJ3OBF.js";
|
|
5
|
+
|
|
6
|
+
// src/commands/code/orchestrator/prompt.ts
|
|
7
|
+
init_esm_shims();
|
|
8
|
+
var DEFAULT_SYSTEM_PROMPT = `You are executing a ralph loop - an iterative AI coding workflow.
|
|
9
|
+
|
|
10
|
+
Your output must include structured signals that the orchestrator will parse.
|
|
11
|
+
These signals MUST appear on their own lines, not inside code blocks.
|
|
12
|
+
|
|
13
|
+
## Signal Format
|
|
14
|
+
|
|
15
|
+
Use these XML-like tags to communicate structured information:
|
|
16
|
+
|
|
17
|
+
### Task Breakdown (discovery phase only)
|
|
18
|
+
<ferix:tasks>
|
|
19
|
+
<task id="1">Brief description of first task</task>
|
|
20
|
+
<task id="2">Brief description of second task</task>
|
|
21
|
+
</ferix:tasks>
|
|
22
|
+
|
|
23
|
+
### Phase Planning
|
|
24
|
+
<ferix:phases task="1">
|
|
25
|
+
<phase id="1.1">First phase description</phase>
|
|
26
|
+
<phase id="1.2">Second phase description</phase>
|
|
27
|
+
</ferix:phases>
|
|
28
|
+
|
|
29
|
+
### Success Criteria
|
|
30
|
+
<ferix:criteria task="1">
|
|
31
|
+
<criterion id="1.c1">First criterion</criterion>
|
|
32
|
+
<criterion id="1.c2">Second criterion</criterion>
|
|
33
|
+
</ferix:criteria>
|
|
34
|
+
|
|
35
|
+
### Phase Lifecycle
|
|
36
|
+
<ferix:phase-start id="1.1"/>
|
|
37
|
+
<ferix:phase-done id="1.1"/>
|
|
38
|
+
<ferix:phase-failed id="1.1">reason</ferix:phase-failed>
|
|
39
|
+
|
|
40
|
+
### Criterion Verification
|
|
41
|
+
<ferix:criterion-passed id="1.c1"/>
|
|
42
|
+
<ferix:criterion-failed id="1.c1" reason="Explanation"/>
|
|
43
|
+
|
|
44
|
+
### Stage Completion
|
|
45
|
+
<ferix:check-passed/>
|
|
46
|
+
<ferix:check-failed/>
|
|
47
|
+
<ferix:review-complete/>
|
|
48
|
+
<ferix:review-changes-made/>
|
|
49
|
+
|
|
50
|
+
### Task Completion
|
|
51
|
+
<ferix:task-complete id="1">
|
|
52
|
+
<summary>Brief summary of what was done</summary>
|
|
53
|
+
<files-modified>file1.ts, file2.ts</files-modified>
|
|
54
|
+
<files-created>new-file.ts</files-created>
|
|
55
|
+
</ferix:task-complete>
|
|
56
|
+
|
|
57
|
+
### Loop Completion (use ONLY when ALL tasks are done)
|
|
58
|
+
<ferix:complete>
|
|
59
|
+
|
|
60
|
+
\u26A0\uFE0F IMPORTANT: Only emit <ferix:complete> after ALL tasks in the plan are complete.
|
|
61
|
+
After completing a single task, emit <ferix:task-complete> and continue to the next task.
|
|
62
|
+
|
|
63
|
+
IMPORTANT: Always emit signals on their own lines, never inside markdown code blocks.`;
|
|
64
|
+
var DISCOVERY_SYSTEM_PROMPT = `You are in the DISCOVERY phase of a ralph loop - an iterative AI coding workflow.
|
|
65
|
+
|
|
66
|
+
Your goal is to:
|
|
67
|
+
1. Generate a short, descriptive name for this session
|
|
68
|
+
2. Analyze the task and break it into SMALL, GRANULAR subtasks
|
|
69
|
+
|
|
70
|
+
Your output must include these signals that the orchestrator will parse.
|
|
71
|
+
These signals MUST appear on their own lines, not inside code blocks.
|
|
72
|
+
|
|
73
|
+
## Signal Format
|
|
74
|
+
|
|
75
|
+
### Session Name (REQUIRED - emit first)
|
|
76
|
+
<ferix:session-name>short-descriptive-name</ferix:session-name>
|
|
77
|
+
|
|
78
|
+
Guidelines for session name:
|
|
79
|
+
- Use 2-5 words in kebab-case (lowercase with hyphens)
|
|
80
|
+
- Describe the main purpose/feature being worked on
|
|
81
|
+
- Keep it concise but meaningful
|
|
82
|
+
- Examples: "add-dark-mode", "fix-auth-flow", "refactor-api-endpoints", "update-user-profile-ui"
|
|
83
|
+
|
|
84
|
+
### Task Breakdown (REQUIRED)
|
|
85
|
+
<ferix:tasks>
|
|
86
|
+
<task id="1">Brief description of first task</task>
|
|
87
|
+
<task id="2">Brief description of second task</task>
|
|
88
|
+
</ferix:tasks>
|
|
89
|
+
|
|
90
|
+
## Task Granularity Rules (CRITICAL)
|
|
91
|
+
|
|
92
|
+
Apply the **"one sentence without 'and'" test**:
|
|
93
|
+
- If describing a task requires "and" to connect unrelated functions, split it
|
|
94
|
+
- Good: "Add login endpoint that validates credentials and returns JWT"
|
|
95
|
+
- Bad: "Handle authentication, user profiles, and billing"
|
|
96
|
+
|
|
97
|
+
Each task MUST be:
|
|
98
|
+
- Small enough to complete in ONE context window
|
|
99
|
+
- Testable in isolation with automated checks
|
|
100
|
+
- A single logical unit of work
|
|
101
|
+
|
|
102
|
+
For a typical feature, create 5-15 tasks.
|
|
103
|
+
For complex projects, create 50-200+ discrete tasks.
|
|
104
|
+
|
|
105
|
+
## CRITICAL: Task Exclusions
|
|
106
|
+
|
|
107
|
+
Do NOT create tasks for any of the following - these are handled automatically by the orchestrator:
|
|
108
|
+
- Running verification commands (bun lint, bun format, eslint, prettier, etc.)
|
|
109
|
+
- Running tests (bun test, jest, vitest, etc.)
|
|
110
|
+
- Running build commands (bun build, tsc, etc.)
|
|
111
|
+
- Any "Verification", "Testing", or "Testing Plan" sections from PRDs
|
|
112
|
+
- Final cleanup, validation, or quality check steps
|
|
113
|
+
- Commands that just run and check output without changing code
|
|
114
|
+
|
|
115
|
+
Tasks should ONLY be for implementation work that creates or modifies source code files.
|
|
116
|
+
Verification commands are run automatically after each task completes - do not create tasks for them.
|
|
117
|
+
|
|
118
|
+
IMPORTANT: Always emit signals on their own lines, never inside markdown code blocks.`;
|
|
119
|
+
var DEFAULT_PLANNING_PROMPT = `## Phase 2: PLANNING
|
|
120
|
+
|
|
121
|
+
If no phases are defined for the current task, define them now.
|
|
122
|
+
Emit a <ferix:phases> block with the execution phases.`;
|
|
123
|
+
var DEFAULT_EXECUTION_PROMPT = `## Phase 3: EXECUTION
|
|
124
|
+
|
|
125
|
+
Execute each phase in order:
|
|
126
|
+
1. Emit <ferix:phase-start id="X.Y"/>
|
|
127
|
+
2. Do the work for that phase
|
|
128
|
+
3. Emit <ferix:phase-done id="X.Y"/> or <ferix:phase-failed id="X.Y">reason</ferix:phase-failed>`;
|
|
129
|
+
var DEFAULT_CHECK_PROMPT = `## Phase 4: CHECK
|
|
130
|
+
|
|
131
|
+
Verify all success criteria are met:
|
|
132
|
+
- For each criterion, emit <ferix:criterion-passed id="X.cY"/> or <ferix:criterion-failed id="X.cY" reason="..."/>
|
|
133
|
+
- Then emit <ferix:check-passed/> or <ferix:check-failed/>`;
|
|
134
|
+
var DEFAULT_REVIEW_PROMPT = `## Phase 6: REVIEW
|
|
135
|
+
|
|
136
|
+
Review the code for quality:
|
|
137
|
+
- Is it clean and well-organized?
|
|
138
|
+
- Are there any obvious improvements?
|
|
139
|
+
- If you make changes, emit <ferix:review-changes-made/>
|
|
140
|
+
- When done, emit <ferix:review-complete/>`;
|
|
141
|
+
var DEFAULT_COMPLETION_PROMPT = `## Completion
|
|
142
|
+
|
|
143
|
+
When you finish the CURRENT task, emit:
|
|
144
|
+
<ferix:task-complete id="N">
|
|
145
|
+
<summary>What was accomplished</summary>
|
|
146
|
+
<files-modified>list of modified files</files-modified>
|
|
147
|
+
<files-created>list of new files</files-created>
|
|
148
|
+
</ferix:task-complete>
|
|
149
|
+
|
|
150
|
+
After emitting task-complete, CONTINUE working on the next pending task.
|
|
151
|
+
|
|
152
|
+
\u26A0\uFE0F ONLY emit <ferix:complete> when ALL tasks in the plan are done.
|
|
153
|
+
Do NOT emit <ferix:complete> after completing just one task - continue to the next task instead.`;
|
|
154
|
+
function getPhasePrompt(phase, prompts, defaultPrompt) {
|
|
155
|
+
return prompts?.phases?.[phase] ?? defaultPrompt;
|
|
156
|
+
}
|
|
157
|
+
function buildSystemPrompt(prompts) {
|
|
158
|
+
return prompts?.systemPrompt ?? DEFAULT_SYSTEM_PROMPT;
|
|
159
|
+
}
|
|
160
|
+
function buildVerifyPrompt(verifyCommands, prompts) {
|
|
161
|
+
const defaultVerifyPrompt = `## Phase 5: VERIFY
|
|
162
|
+
|
|
163
|
+
Run these verification commands:
|
|
164
|
+
${verifyCommands.map((cmd) => `- ${cmd}`).join("\n")}
|
|
165
|
+
|
|
166
|
+
If any fail, fix the issues and re-verify.
|
|
167
|
+
|
|
168
|
+
IMPORTANT: Once ALL verification commands pass:
|
|
169
|
+
- Emit <ferix:task-complete id="N"> with a summary of what was done
|
|
170
|
+
- If this was the last task, also emit <ferix:complete>
|
|
171
|
+
- Do NOT run verification again after it passes`;
|
|
172
|
+
return prompts?.phases?.verify ?? defaultVerifyPrompt;
|
|
173
|
+
}
|
|
174
|
+
var TASK_STATUS_ICONS = {
|
|
175
|
+
done: "[x]",
|
|
176
|
+
in_progress: "[~]",
|
|
177
|
+
pending: "[ ]",
|
|
178
|
+
planning: "[~]",
|
|
179
|
+
failed: "[!]",
|
|
180
|
+
skipped: "[-]"
|
|
181
|
+
};
|
|
182
|
+
function buildTaskListSection(plan) {
|
|
183
|
+
if (plan.tasks.length === 0) {
|
|
184
|
+
return "";
|
|
185
|
+
}
|
|
186
|
+
const completedCount = plan.tasks.filter((t) => t.status === "done").length;
|
|
187
|
+
const totalCount = plan.tasks.length;
|
|
188
|
+
const lines = [
|
|
189
|
+
"## Task Progress",
|
|
190
|
+
"",
|
|
191
|
+
`Status: ${completedCount}/${totalCount} complete`,
|
|
192
|
+
""
|
|
193
|
+
];
|
|
194
|
+
const currentTaskId = plan.tasks.find(
|
|
195
|
+
(t) => t.status === "in_progress" || t.status === "pending"
|
|
196
|
+
)?.id;
|
|
197
|
+
for (const task of plan.tasks) {
|
|
198
|
+
const icon = TASK_STATUS_ICONS[task.status];
|
|
199
|
+
const currentMarker = task.id === currentTaskId ? " \u2190 current" : "";
|
|
200
|
+
lines.push(
|
|
201
|
+
`- ${icon} Task ${task.id}: ${task.title} (${task.status})${currentMarker}`
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
return lines.join("\n");
|
|
205
|
+
}
|
|
206
|
+
function buildCurrentTaskSection(plan) {
|
|
207
|
+
const currentTask = plan.tasks.find(
|
|
208
|
+
(t) => t.status === "in_progress" || t.status === "pending"
|
|
209
|
+
);
|
|
210
|
+
if (!currentTask) {
|
|
211
|
+
return void 0;
|
|
212
|
+
}
|
|
213
|
+
const phasesSection = currentTask.phases.length > 0 ? `### Phases
|
|
214
|
+
${currentTask.phases.map((p) => `- ${p.id}: ${p.description} (${p.status})`).join("\n")}` : "No phases defined yet. Emit a <ferix:phases> block to define phases.";
|
|
215
|
+
const criteriaSection = currentTask.criteria.length > 0 ? `### Success Criteria
|
|
216
|
+
${currentTask.criteria.map((c) => `- ${c.id}: ${c.description} (${c.status})`).join("\n")}` : "";
|
|
217
|
+
return `## Current Task
|
|
218
|
+
|
|
219
|
+
Task ${currentTask.id}: ${currentTask.title}
|
|
220
|
+
|
|
221
|
+
${currentTask.description}
|
|
222
|
+
|
|
223
|
+
${phasesSection}
|
|
224
|
+
|
|
225
|
+
${criteriaSection}`;
|
|
226
|
+
}
|
|
227
|
+
function buildDiscoveryPrompt(config) {
|
|
228
|
+
const sections = [];
|
|
229
|
+
sections.push(DISCOVERY_SYSTEM_PROMPT);
|
|
230
|
+
if (config.prompts?.additionalContext) {
|
|
231
|
+
sections.push(
|
|
232
|
+
`## Additional Context
|
|
233
|
+
|
|
234
|
+
${config.prompts.additionalContext}`
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
sections.push(`## Task
|
|
238
|
+
|
|
239
|
+
${config.task}`);
|
|
240
|
+
sections.push(`## Instructions
|
|
241
|
+
|
|
242
|
+
Analyze the task above and:
|
|
243
|
+
|
|
244
|
+
1. **Generate a session name** (2-5 words, kebab-case)
|
|
245
|
+
- Should describe the main purpose of this work
|
|
246
|
+
- Emit: <ferix:session-name>your-descriptive-name</ferix:session-name>
|
|
247
|
+
|
|
248
|
+
2. **Break the task into logical subtasks** (2-6 tasks)
|
|
249
|
+
- Read and understand what needs to be done
|
|
250
|
+
- Identify the main components or steps
|
|
251
|
+
- Emit: <ferix:tasks>...</ferix:tasks>
|
|
252
|
+
|
|
253
|
+
Each task should be:
|
|
254
|
+
- Self-contained and independently verifiable
|
|
255
|
+
- Clear and specific
|
|
256
|
+
- Ordered logically (dependencies first)
|
|
257
|
+
- ONLY for code implementation (NOT for running lint/test/build commands)
|
|
258
|
+
|
|
259
|
+
REMINDER: Do NOT create tasks for verification steps like "Run lint", "Run tests", "Verify changes", etc.
|
|
260
|
+
The orchestrator handles verification automatically after each task completes.
|
|
261
|
+
If the PRD has a "Verification" or "Testing" section, IGNORE it when creating tasks.
|
|
262
|
+
|
|
263
|
+
Begin your analysis now.`);
|
|
264
|
+
return sections.join("\n\n");
|
|
265
|
+
}
|
|
266
|
+
function buildPrompt(config, iteration, plan) {
|
|
267
|
+
const prompts = config.prompts;
|
|
268
|
+
const sections = [];
|
|
269
|
+
sections.push(buildSystemPrompt(prompts));
|
|
270
|
+
if (prompts?.additionalContext) {
|
|
271
|
+
sections.push(`## Additional Context
|
|
272
|
+
|
|
273
|
+
${prompts.additionalContext}`);
|
|
274
|
+
}
|
|
275
|
+
sections.push(`## Task
|
|
276
|
+
|
|
277
|
+
${config.task}`);
|
|
278
|
+
if (plan && plan.tasks.length > 0) {
|
|
279
|
+
const taskListSection = buildTaskListSection(plan);
|
|
280
|
+
if (taskListSection) {
|
|
281
|
+
sections.push(taskListSection);
|
|
282
|
+
}
|
|
283
|
+
const taskSection = buildCurrentTaskSection(plan);
|
|
284
|
+
if (taskSection) {
|
|
285
|
+
sections.push(taskSection);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
sections.push(getPhasePrompt("planning", prompts, DEFAULT_PLANNING_PROMPT));
|
|
289
|
+
sections.push(getPhasePrompt("execution", prompts, DEFAULT_EXECUTION_PROMPT));
|
|
290
|
+
sections.push(getPhasePrompt("check", prompts, DEFAULT_CHECK_PROMPT));
|
|
291
|
+
if (config.verifyCommands.length > 0 && plan && !areAllTasksComplete(plan)) {
|
|
292
|
+
const currentTask = plan.tasks.find(
|
|
293
|
+
(t) => t.status === "in_progress" || t.status === "pending"
|
|
294
|
+
);
|
|
295
|
+
if (currentTask) {
|
|
296
|
+
sections.push(buildVerifyPrompt(config.verifyCommands, prompts));
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
sections.push(getPhasePrompt("review", prompts, DEFAULT_REVIEW_PROMPT));
|
|
300
|
+
sections.push(
|
|
301
|
+
getPhasePrompt("completion", prompts, DEFAULT_COMPLETION_PROMPT)
|
|
302
|
+
);
|
|
303
|
+
sections.push(`---
|
|
304
|
+
|
|
305
|
+
Iteration ${iteration} of ${config.maxIterations || "unlimited"}
|
|
306
|
+
|
|
307
|
+
Begin.`);
|
|
308
|
+
return sections.join("\n\n");
|
|
309
|
+
}
|
|
310
|
+
function areAllTasksComplete(plan) {
|
|
311
|
+
if (!plan || plan.tasks.length === 0) {
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
return plan.tasks.every((t) => t.status === "done" || t.status === "skipped");
|
|
315
|
+
}
|
|
316
|
+
function buildSessionState(config, iteration, sessionId, plan, recentProgress = []) {
|
|
317
|
+
const currentTask = plan?.tasks.find(
|
|
318
|
+
(t) => t.status === "in_progress" || t.status === "pending"
|
|
319
|
+
);
|
|
320
|
+
const taskSummary = plan ? {
|
|
321
|
+
total: plan.tasks.length,
|
|
322
|
+
done: plan.tasks.filter((t) => t.status === "done").length,
|
|
323
|
+
inProgress: plan.tasks.filter((t) => t.status === "in_progress").length,
|
|
324
|
+
pending: plan.tasks.filter(
|
|
325
|
+
(t) => t.status === "pending" || t.status === "planning"
|
|
326
|
+
).length
|
|
327
|
+
} : { total: 0, done: 0, inProgress: 0, pending: 0 };
|
|
328
|
+
return {
|
|
329
|
+
sessionId,
|
|
330
|
+
originalTask: config.task,
|
|
331
|
+
iteration,
|
|
332
|
+
maxIterations: config.maxIterations,
|
|
333
|
+
taskSummary,
|
|
334
|
+
currentTask: currentTask ? {
|
|
335
|
+
id: currentTask.id,
|
|
336
|
+
title: currentTask.title,
|
|
337
|
+
description: currentTask.description,
|
|
338
|
+
phases: currentTask.phases.map((p) => ({
|
|
339
|
+
id: p.id,
|
|
340
|
+
description: p.description,
|
|
341
|
+
status: p.status
|
|
342
|
+
})),
|
|
343
|
+
criteria: currentTask.criteria.map((c) => ({
|
|
344
|
+
id: c.id,
|
|
345
|
+
description: c.description,
|
|
346
|
+
status: c.status
|
|
347
|
+
}))
|
|
348
|
+
} : null,
|
|
349
|
+
recentProgress
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
export {
|
|
354
|
+
buildDiscoveryPrompt,
|
|
355
|
+
buildPrompt,
|
|
356
|
+
areAllTasksComplete,
|
|
357
|
+
buildSessionState
|
|
358
|
+
};
|