sparkecoder 0.1.83 → 0.1.85
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/agent/index.js +125 -22
- package/dist/agent/index.js.map +1 -1
- package/dist/cli.js +532 -395
- package/dist/cli.js.map +1 -1
- package/dist/index.js +532 -395
- package/dist/index.js.map +1 -1
- package/dist/server/index.js +532 -395
- package/dist/server/index.js.map +1 -1
- package/dist/tools/index.d.ts +19 -36
- package/dist/tools/index.js +99 -10
- package/dist/tools/index.js.map +1 -1
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/web/.next/build-manifest.json +2 -2
- package/web/.next/standalone/web/.next/prerender-manifest.json +3 -3
- package/web/.next/standalone/web/.next/server/app/(main)/page.js.nft.json +1 -1
- package/web/.next/standalone/web/.next/server/app/(main)/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page.js.nft.json +1 -1
- package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/standalone/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.html +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_full.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_index.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_tree.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/skills.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_full.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_index.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_tree.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/tools.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_full.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_index.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_tree.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.html +2 -2
- package/web/.next/standalone/web/.next/server/app/docs.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs.segments/_full.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/_index.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs.segments/_tree.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/docs.segments/docs.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/embed/[id]/page.js.nft.json +1 -1
- package/web/.next/standalone/web/.next/server/app/embed/[id]/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/app/index.html +1 -1
- package/web/.next/standalone/web/.next/server/app/index.rsc +4 -4
- package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p/__PAGE__.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/web/.next/standalone/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/web/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_02a118f9._.js → 2374f_00f7fe07._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_ad08e83a._.js → 2374f_2801b766._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_0ed477f8._.js → 2374f_369747ce._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_3b51a934._.js → 2374f_60d8842c._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_acf3dfe4._.js → 2374f_806bd012._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_db3e363b._.js → 2374f_8dc0f9aa._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_f0d7e130._.js → 2374f_9adc1edb._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_5ebfcf1a._.js → 2374f_b7f45fdf._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_12bad06e._.js → 2374f_c13c8f4f._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_fc992d90._.js → 2374f_cc6c6363._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_3e519469._.js → 2374f_d58d0276._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_a0f483d1._.js → 2374f_ecd2bdca._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_c1d54c16._.js → 2374f_f363c084._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_2526ca80._.js → 2374f_fdfc7f3d._.js} +1 -1
- package/web/.next/standalone/web/.next/server/chunks/ssr/{[root-of-the-server]__06818a54._.js → [root-of-the-server]__25b25c9d._.js} +2 -2
- package/web/.next/standalone/web/.next/server/chunks/ssr/{[root-of-the-server]__a1877334._.js → [root-of-the-server]__9d3a7cbf._.js} +4 -4
- package/web/.next/standalone/web/.next/server/chunks/ssr/{web_cc5f7515._.js → web_08242997._.js} +2 -2
- package/web/.next/standalone/web/.next/server/chunks/ssr/{web_2b3a5919._.js → web_123ffe97._.js} +2 -2
- package/web/.next/standalone/web/.next/server/chunks/ssr/{web_38156da8._.js → web_99b01335._.js} +2 -2
- package/web/.next/standalone/web/.next/server/pages/404.html +1 -1
- package/web/.next/standalone/web/.next/server/pages/500.html +2 -2
- package/web/.next/standalone/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/standalone/web/.next/server/server-reference-manifest.json +1 -1
- package/web/.next/standalone/web/.next/static/chunks/{f95d41079838994a.js → 2624c966c288fd41.js} +3 -3
- package/web/.next/standalone/web/.next/static/chunks/74b64476a24dd71e.css +1 -0
- package/web/.next/standalone/web/.next/static/{static/chunks/fc39a194539da104.js → chunks/8af263bc97c0c9ee.js} +1 -1
- package/web/.next/{static/chunks/2cafc7cb79454d33.js → standalone/web/.next/static/chunks/cfadc93a98190e5a.js} +1 -1
- package/web/.next/standalone/web/.next/static/static/chunks/{f95d41079838994a.js → 2624c966c288fd41.js} +3 -3
- package/web/.next/standalone/web/.next/static/static/chunks/74b64476a24dd71e.css +1 -0
- package/web/.next/{static/chunks/fc39a194539da104.js → standalone/web/.next/static/static/chunks/8af263bc97c0c9ee.js} +1 -1
- package/web/.next/standalone/web/.next/static/{chunks/2cafc7cb79454d33.js → static/chunks/cfadc93a98190e5a.js} +1 -1
- package/web/.next/standalone/web/src/components/ai-elements/todo-panel.tsx +194 -110
- package/web/.next/standalone/web/src/components/ai-elements/todo-tool.tsx +78 -1
- package/web/.next/standalone/web/src/components/chat-interface.tsx +15 -9
- package/web/.next/standalone/web/src/lib/api.ts +17 -0
- package/web/.next/static/chunks/{f95d41079838994a.js → 2624c966c288fd41.js} +3 -3
- package/web/.next/static/chunks/74b64476a24dd71e.css +1 -0
- package/web/.next/{standalone/web/.next/static/chunks/fc39a194539da104.js → static/chunks/8af263bc97c0c9ee.js} +1 -1
- package/web/.next/{standalone/web/.next/static/static/chunks/2cafc7cb79454d33.js → static/chunks/cfadc93a98190e5a.js} +1 -1
- package/web/.next/standalone/web/.next/static/chunks/41a5c049931b2c77.css +0 -1
- package/web/.next/standalone/web/.next/static/static/chunks/41a5c049931b2c77.css +0 -1
- package/web/.next/static/chunks/41a5c049931b2c77.css +0 -1
- /package/web/.next/standalone/web/.next/static/{aCZCpTkVv_k-RisOFPegk → J0gen1p9aNjUNIU1NDO5h}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/{aCZCpTkVv_k-RisOFPegk → J0gen1p9aNjUNIU1NDO5h}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/{aCZCpTkVv_k-RisOFPegk → J0gen1p9aNjUNIU1NDO5h}/_ssgManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{aCZCpTkVv_k-RisOFPegk → J0gen1p9aNjUNIU1NDO5h}/_buildManifest.js +0 -0
- /package/web/.next/standalone/web/.next/static/static/{aCZCpTkVv_k-RisOFPegk → J0gen1p9aNjUNIU1NDO5h}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/standalone/web/.next/static/static/{aCZCpTkVv_k-RisOFPegk → J0gen1p9aNjUNIU1NDO5h}/_ssgManifest.js +0 -0
- /package/web/.next/static/{aCZCpTkVv_k-RisOFPegk → J0gen1p9aNjUNIU1NDO5h}/_buildManifest.js +0 -0
- /package/web/.next/static/{aCZCpTkVv_k-RisOFPegk → J0gen1p9aNjUNIU1NDO5h}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{aCZCpTkVv_k-RisOFPegk → J0gen1p9aNjUNIU1NDO5h}/_ssgManifest.js +0 -0
package/dist/agent/index.js
CHANGED
|
@@ -3649,22 +3649,27 @@ function createTodoTool(options) {
|
|
|
3649
3649
|
- "clear": Remove all todo items from the list
|
|
3650
3650
|
|
|
3651
3651
|
## Plan Actions (for complex, multi-phase work)
|
|
3652
|
-
- "save_plan": Create or update a named plan
|
|
3652
|
+
- "save_plan": Create or update a named plan. When saved and no active todos exist, todos are AUTO-CREATED from the first uncompleted phase.
|
|
3653
3653
|
- "list_plans": List all plans for this session
|
|
3654
3654
|
- "get_plan": Read a specific plan by name
|
|
3655
3655
|
- "delete_plan": Remove a plan
|
|
3656
3656
|
|
|
3657
3657
|
## Plans vs Todos
|
|
3658
3658
|
- **Plans** are the big picture \u2014 the full spec with phases, subtasks, notes, and decisions. They persist on disk and are always injected into your context, even after old messages are summarized.
|
|
3659
|
-
- **Todos** are your current focus \u2014 the immediate steps you're working on right now.
|
|
3659
|
+
- **Todos** are your current focus \u2014 the immediate steps you're working on right now, auto-derived from plan phases.
|
|
3660
3660
|
|
|
3661
3661
|
## Workflow for complex tasks
|
|
3662
|
-
1. Create a plan with phases and subtasks (save_plan)
|
|
3663
|
-
2.
|
|
3664
|
-
3.
|
|
3665
|
-
4.
|
|
3666
|
-
5.
|
|
3667
|
-
|
|
3662
|
+
1. Create a plan with phases and subtasks using checkboxes (save_plan) \u2014 todos are auto-created from Phase 1
|
|
3663
|
+
2. Work through the todos, marking them as you go
|
|
3664
|
+
3. When all todos are done, update the plan: mark the completed phase heading with [completed] and its items with [x]
|
|
3665
|
+
4. Call save_plan again with the updated content \u2014 todos are auto-created from the next uncompleted phase
|
|
3666
|
+
5. Repeat until all phases are complete, then delete_plan
|
|
3667
|
+
|
|
3668
|
+
## Auto-todo creation rules
|
|
3669
|
+
- Only triggers when there are NO active (pending/in_progress) todos
|
|
3670
|
+
- Skips phases with [completed] in the heading
|
|
3671
|
+
- Skips sections named Overview, Notes, Key Decisions, etc.
|
|
3672
|
+
- Only top-level checklist items (- [ ]) become todos \u2014 indented sub-items are task details
|
|
3668
3673
|
|
|
3669
3674
|
## Plan format
|
|
3670
3675
|
Plans should be markdown with this structure:
|
|
@@ -3748,10 +3753,34 @@ Plans should be markdown with this structure:
|
|
|
3748
3753
|
error: `Todo item not found: ${todoId}`
|
|
3749
3754
|
};
|
|
3750
3755
|
}
|
|
3756
|
+
let planContinuation;
|
|
3757
|
+
if (status === "completed") {
|
|
3758
|
+
const allTodos = await todoQueries.getBySession(options.sessionId);
|
|
3759
|
+
const allDone = allTodos.every(
|
|
3760
|
+
(t) => t.status === "completed" || t.status === "cancelled"
|
|
3761
|
+
);
|
|
3762
|
+
if (allDone) {
|
|
3763
|
+
const plansDir = getPlansDir(options.workingDirectory, options.sessionId);
|
|
3764
|
+
if (existsSync9(plansDir)) {
|
|
3765
|
+
const planFiles = readdirSync(plansDir).filter((f) => f.endsWith(".md"));
|
|
3766
|
+
for (const f of planFiles) {
|
|
3767
|
+
try {
|
|
3768
|
+
const content = await readFile6(join4(plansDir, f), "utf-8");
|
|
3769
|
+
if (parseNextUncompletedPhase(content) !== null) {
|
|
3770
|
+
planContinuation = "All todos are done but your plan has remaining phases. Update the plan now: mark the completed phase heading with [completed] and its items with [x], then call save_plan to save \u2014 new todos will be auto-created from the next phase.";
|
|
3771
|
+
break;
|
|
3772
|
+
}
|
|
3773
|
+
} catch {
|
|
3774
|
+
}
|
|
3775
|
+
}
|
|
3776
|
+
}
|
|
3777
|
+
}
|
|
3778
|
+
}
|
|
3751
3779
|
return {
|
|
3752
3780
|
success: true,
|
|
3753
3781
|
action: "mark",
|
|
3754
|
-
item: formatTodoItem(updated)
|
|
3782
|
+
item: formatTodoItem(updated),
|
|
3783
|
+
...planContinuation ? { planContinuation } : {}
|
|
3755
3784
|
};
|
|
3756
3785
|
}
|
|
3757
3786
|
case "clear": {
|
|
@@ -3774,13 +3803,32 @@ Plans should be markdown with this structure:
|
|
|
3774
3803
|
const filename = `${slugify(planName)}.md`;
|
|
3775
3804
|
const filePath = join4(dir, filename);
|
|
3776
3805
|
await writeFile4(filePath, planContent, "utf-8");
|
|
3806
|
+
const existingTodos = await todoQueries.getBySession(options.sessionId);
|
|
3807
|
+
const hasActiveTodos = existingTodos.some(
|
|
3808
|
+
(t) => t.status === "pending" || t.status === "in_progress"
|
|
3809
|
+
);
|
|
3810
|
+
let autoCreatedTodos = [];
|
|
3811
|
+
if (!hasActiveTodos) {
|
|
3812
|
+
const nextPhase = parseNextUncompletedPhase(planContent);
|
|
3813
|
+
if (nextPhase) {
|
|
3814
|
+
const created = await todoQueries.createMany(
|
|
3815
|
+
options.sessionId,
|
|
3816
|
+
nextPhase.tasks.map((task, i) => ({ content: task, order: i }))
|
|
3817
|
+
);
|
|
3818
|
+
autoCreatedTodos = created.map(formatTodoItem);
|
|
3819
|
+
}
|
|
3820
|
+
}
|
|
3777
3821
|
return {
|
|
3778
3822
|
success: true,
|
|
3779
3823
|
action: "save_plan",
|
|
3780
3824
|
planName,
|
|
3781
3825
|
filename,
|
|
3782
3826
|
path: filePath,
|
|
3783
|
-
sizeChars: planContent.length
|
|
3827
|
+
sizeChars: planContent.length,
|
|
3828
|
+
...autoCreatedTodos.length > 0 ? {
|
|
3829
|
+
autoCreatedTodos,
|
|
3830
|
+
autoCreatedFromPhase: "Created todos from the first uncompleted phase. Start working on them!"
|
|
3831
|
+
} : {}
|
|
3784
3832
|
};
|
|
3785
3833
|
}
|
|
3786
3834
|
case "list_plans": {
|
|
@@ -3861,6 +3909,47 @@ function formatTodoItem(item) {
|
|
|
3861
3909
|
createdAt: item.createdAt.toISOString()
|
|
3862
3910
|
};
|
|
3863
3911
|
}
|
|
3912
|
+
function parseNextUncompletedPhase(content) {
|
|
3913
|
+
const lines = content.split("\n");
|
|
3914
|
+
let currentPhase = null;
|
|
3915
|
+
let currentTasks = [];
|
|
3916
|
+
let hasUncompletedTask = false;
|
|
3917
|
+
for (const line of lines) {
|
|
3918
|
+
const h2Match = line.match(/^##\s+(.+)/);
|
|
3919
|
+
if (h2Match) {
|
|
3920
|
+
if (currentPhase && hasUncompletedTask && currentTasks.length > 0) {
|
|
3921
|
+
return { phaseName: currentPhase, tasks: currentTasks };
|
|
3922
|
+
}
|
|
3923
|
+
const headingText = h2Match[1].trim();
|
|
3924
|
+
if (/^(overview|notes|key decisions|context|summary|references)\b/i.test(headingText)) {
|
|
3925
|
+
currentPhase = null;
|
|
3926
|
+
currentTasks = [];
|
|
3927
|
+
hasUncompletedTask = false;
|
|
3928
|
+
continue;
|
|
3929
|
+
}
|
|
3930
|
+
if (/\[completed\]/i.test(headingText)) {
|
|
3931
|
+
currentPhase = null;
|
|
3932
|
+
currentTasks = [];
|
|
3933
|
+
hasUncompletedTask = false;
|
|
3934
|
+
continue;
|
|
3935
|
+
}
|
|
3936
|
+
currentPhase = headingText.replace(/\s*\[(in_progress|pending|completed)\]\s*/gi, "").replace(/^Phase\s+\d+[:\s]*/i, "").trim();
|
|
3937
|
+
currentTasks = [];
|
|
3938
|
+
hasUncompletedTask = false;
|
|
3939
|
+
continue;
|
|
3940
|
+
}
|
|
3941
|
+
if (!currentPhase) continue;
|
|
3942
|
+
const uncheckedMatch = line.match(/^[-*]\s+\[\s\]\s+(.+)/);
|
|
3943
|
+
if (uncheckedMatch) {
|
|
3944
|
+
currentTasks.push(uncheckedMatch[1].trim());
|
|
3945
|
+
hasUncompletedTask = true;
|
|
3946
|
+
}
|
|
3947
|
+
}
|
|
3948
|
+
if (currentPhase && hasUncompletedTask && currentTasks.length > 0) {
|
|
3949
|
+
return { phaseName: currentPhase, tasks: currentTasks };
|
|
3950
|
+
}
|
|
3951
|
+
return null;
|
|
3952
|
+
}
|
|
3864
3953
|
async function readSessionPlans(workingDirectory, sessionId) {
|
|
3865
3954
|
const dir = getPlansDir(workingDirectory, sessionId);
|
|
3866
3955
|
if (!existsSync9(dir)) return [];
|
|
@@ -5595,7 +5684,11 @@ async function buildSystemPrompt(options) {
|
|
|
5595
5684
|
const todos = await todoQueries.getBySession(sessionId);
|
|
5596
5685
|
const todosContext = formatTodosForContext(todos);
|
|
5597
5686
|
const plans = await readSessionPlans(workingDirectory, sessionId);
|
|
5598
|
-
const
|
|
5687
|
+
const allTodosDone = todos.length > 0 && todos.every(
|
|
5688
|
+
(t) => t.status === "completed" || t.status === "cancelled"
|
|
5689
|
+
);
|
|
5690
|
+
const hasNoTodos = todos.length === 0;
|
|
5691
|
+
const plansContext = formatPlansForContext(plans, allTodosDone || hasNoTodos);
|
|
5599
5692
|
const platform2 = process.platform === "win32" ? "Windows" : process.platform === "darwin" ? "macOS" : "Linux";
|
|
5600
5693
|
const currentDate = (/* @__PURE__ */ new Date()).toLocaleDateString("en-US", { weekday: "long", year: "numeric", month: "long", day: "numeric" });
|
|
5601
5694
|
const searchInstructions = getSearchInstructions();
|
|
@@ -5628,16 +5721,19 @@ Use the **todo tool** to manage both immediate tasks AND persistent plans:
|
|
|
5628
5721
|
|
|
5629
5722
|
**For complex, multi-phase tasks:** Create a persistent **plan** first.
|
|
5630
5723
|
1. Research the codebase to understand what you're working with
|
|
5631
|
-
2. Create a plan with save_plan \u2014 a structured markdown document with phases and subtasks
|
|
5632
|
-
3.
|
|
5633
|
-
4. Work through the todos
|
|
5634
|
-
5. When done, update the plan
|
|
5635
|
-
6.
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
Plans persist on disk and are always injected into your context \u2014 they survive context compaction even in very long sessions
|
|
5639
|
-
|
|
5640
|
-
|
|
5724
|
+
2. Create a plan with save_plan \u2014 a structured markdown document with phases and subtasks using checkboxes (- [ ] for uncompleted, - [x] for completed)
|
|
5725
|
+
3. Todos are **auto-created** from the first uncompleted phase when you save the plan (if no active todos exist)
|
|
5726
|
+
4. Work through the todos, marking them as you go
|
|
5727
|
+
5. When all todos are done, update the plan: change completed phase heading to include [completed], mark all its items with [x], then call save_plan again \u2014 new todos will be auto-created from the next uncompleted phase
|
|
5728
|
+
6. Repeat until all phases are complete, then delete the plan
|
|
5729
|
+
|
|
5730
|
+
**Key details:**
|
|
5731
|
+
- Plans persist on disk and are always injected into your context \u2014 they survive context compaction even in very long sessions
|
|
5732
|
+
- You can have multiple plans active at once (e.g., one for frontend work, one for backend)
|
|
5733
|
+
- When you save a plan and there are no active todos, the system automatically creates todos from the first uncompleted phase (phases with [completed] in the heading are skipped)
|
|
5734
|
+
- Only top-level checklist items (- [ ]) become todos \u2014 indented sub-items are part of the task detail
|
|
5735
|
+
- Sections named Overview, Notes, Key Decisions, etc. are not treated as phases
|
|
5736
|
+
- You can clear the todo list and restart it, and do multiple things inside of one session
|
|
5641
5737
|
|
|
5642
5738
|
### bash Tool
|
|
5643
5739
|
The bash tool runs commands in the terminal. Every command runs in its own session with logs saved to disk.
|
|
@@ -5888,7 +5984,7 @@ function formatTodosForContext(todos) {
|
|
|
5888
5984
|
}
|
|
5889
5985
|
var MAX_PLAN_CHARS = 3e4;
|
|
5890
5986
|
var MAX_TOTAL_PLANS_CHARS = 6e4;
|
|
5891
|
-
function formatPlansForContext(plans) {
|
|
5987
|
+
function formatPlansForContext(plans, shouldContinue) {
|
|
5892
5988
|
if (plans.length === 0) return "";
|
|
5893
5989
|
let totalChars = 0;
|
|
5894
5990
|
const sections = [];
|
|
@@ -5897,6 +5993,13 @@ function formatPlansForContext(plans) {
|
|
|
5897
5993
|
sections.push("These plans persist across context compaction \u2014 they are always available.");
|
|
5898
5994
|
sections.push("When you finish your current todos, check these plans for the next uncompleted phase,");
|
|
5899
5995
|
sections.push("update the plan (mark completed items with [x]), then create new todos for the next phase.");
|
|
5996
|
+
if (shouldContinue) {
|
|
5997
|
+
sections.push("");
|
|
5998
|
+
sections.push("**>>> ACTION NEEDED: Your current todos are all done but the plan has remaining phases. To continue:**");
|
|
5999
|
+
sections.push("**1. Update the plan content: change the completed phase heading to include [completed] and mark its items with [x]**");
|
|
6000
|
+
sections.push("**2. Call save_plan with the updated content \u2014 new todos will be auto-created from the next uncompleted phase**");
|
|
6001
|
+
sections.push("**3. Continue working on the new todos <<<**");
|
|
6002
|
+
}
|
|
5900
6003
|
sections.push("");
|
|
5901
6004
|
for (const plan of plans) {
|
|
5902
6005
|
let content = plan.content;
|