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.
Files changed (136) hide show
  1. package/dist/agent/index.js +125 -22
  2. package/dist/agent/index.js.map +1 -1
  3. package/dist/cli.js +532 -395
  4. package/dist/cli.js.map +1 -1
  5. package/dist/index.js +532 -395
  6. package/dist/index.js.map +1 -1
  7. package/dist/server/index.js +532 -395
  8. package/dist/server/index.js.map +1 -1
  9. package/dist/tools/index.d.ts +19 -36
  10. package/dist/tools/index.js +99 -10
  11. package/dist/tools/index.js.map +1 -1
  12. package/package.json +1 -1
  13. package/web/.next/BUILD_ID +1 -1
  14. package/web/.next/standalone/web/.next/BUILD_ID +1 -1
  15. package/web/.next/standalone/web/.next/build-manifest.json +2 -2
  16. package/web/.next/standalone/web/.next/prerender-manifest.json +3 -3
  17. package/web/.next/standalone/web/.next/server/app/(main)/page.js.nft.json +1 -1
  18. package/web/.next/standalone/web/.next/server/app/(main)/page_client-reference-manifest.js +1 -1
  19. package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page.js.nft.json +1 -1
  20. package/web/.next/standalone/web/.next/server/app/(main)/session/[id]/page_client-reference-manifest.js +1 -1
  21. package/web/.next/standalone/web/.next/server/app/_global-error.html +2 -2
  22. package/web/.next/standalone/web/.next/server/app/_global-error.rsc +1 -1
  23. package/web/.next/standalone/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  24. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  25. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  26. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  27. package/web/.next/standalone/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  28. package/web/.next/standalone/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  29. package/web/.next/standalone/web/.next/server/app/_not-found.html +1 -1
  30. package/web/.next/standalone/web/.next/server/app/_not-found.rsc +2 -2
  31. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  32. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  33. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
  34. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  35. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  36. package/web/.next/standalone/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  37. package/web/.next/standalone/web/.next/server/app/docs/installation/page_client-reference-manifest.js +1 -1
  38. package/web/.next/standalone/web/.next/server/app/docs/installation.html +2 -2
  39. package/web/.next/standalone/web/.next/server/app/docs/installation.rsc +2 -2
  40. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_full.segment.rsc +2 -2
  41. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_head.segment.rsc +1 -1
  42. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_index.segment.rsc +2 -2
  43. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/_tree.segment.rsc +2 -2
  44. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation/__PAGE__.segment.rsc +1 -1
  45. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs/installation.segment.rsc +1 -1
  46. package/web/.next/standalone/web/.next/server/app/docs/installation.segments/docs.segment.rsc +1 -1
  47. package/web/.next/standalone/web/.next/server/app/docs/page_client-reference-manifest.js +1 -1
  48. package/web/.next/standalone/web/.next/server/app/docs/skills/page_client-reference-manifest.js +1 -1
  49. package/web/.next/standalone/web/.next/server/app/docs/skills.html +2 -2
  50. package/web/.next/standalone/web/.next/server/app/docs/skills.rsc +2 -2
  51. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_full.segment.rsc +2 -2
  52. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_head.segment.rsc +1 -1
  53. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_index.segment.rsc +2 -2
  54. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/_tree.segment.rsc +2 -2
  55. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills/__PAGE__.segment.rsc +1 -1
  56. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs/skills.segment.rsc +1 -1
  57. package/web/.next/standalone/web/.next/server/app/docs/skills.segments/docs.segment.rsc +1 -1
  58. package/web/.next/standalone/web/.next/server/app/docs/tools/page_client-reference-manifest.js +1 -1
  59. package/web/.next/standalone/web/.next/server/app/docs/tools.html +2 -2
  60. package/web/.next/standalone/web/.next/server/app/docs/tools.rsc +2 -2
  61. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_full.segment.rsc +2 -2
  62. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_head.segment.rsc +1 -1
  63. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_index.segment.rsc +2 -2
  64. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/_tree.segment.rsc +2 -2
  65. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools/__PAGE__.segment.rsc +1 -1
  66. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs/tools.segment.rsc +1 -1
  67. package/web/.next/standalone/web/.next/server/app/docs/tools.segments/docs.segment.rsc +1 -1
  68. package/web/.next/standalone/web/.next/server/app/docs.html +2 -2
  69. package/web/.next/standalone/web/.next/server/app/docs.rsc +2 -2
  70. package/web/.next/standalone/web/.next/server/app/docs.segments/_full.segment.rsc +2 -2
  71. package/web/.next/standalone/web/.next/server/app/docs.segments/_head.segment.rsc +1 -1
  72. package/web/.next/standalone/web/.next/server/app/docs.segments/_index.segment.rsc +2 -2
  73. package/web/.next/standalone/web/.next/server/app/docs.segments/_tree.segment.rsc +2 -2
  74. package/web/.next/standalone/web/.next/server/app/docs.segments/docs/__PAGE__.segment.rsc +1 -1
  75. package/web/.next/standalone/web/.next/server/app/docs.segments/docs.segment.rsc +1 -1
  76. package/web/.next/standalone/web/.next/server/app/embed/[id]/page.js.nft.json +1 -1
  77. package/web/.next/standalone/web/.next/server/app/embed/[id]/page_client-reference-manifest.js +1 -1
  78. package/web/.next/standalone/web/.next/server/app/index.html +1 -1
  79. package/web/.next/standalone/web/.next/server/app/index.rsc +4 -4
  80. package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p/__PAGE__.segment.rsc +2 -2
  81. package/web/.next/standalone/web/.next/server/app/index.segments/!KG1haW4p.segment.rsc +2 -2
  82. package/web/.next/standalone/web/.next/server/app/index.segments/_full.segment.rsc +4 -4
  83. package/web/.next/standalone/web/.next/server/app/index.segments/_head.segment.rsc +1 -1
  84. package/web/.next/standalone/web/.next/server/app/index.segments/_index.segment.rsc +2 -2
  85. package/web/.next/standalone/web/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  86. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_02a118f9._.js → 2374f_00f7fe07._.js} +1 -1
  87. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_ad08e83a._.js → 2374f_2801b766._.js} +1 -1
  88. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_0ed477f8._.js → 2374f_369747ce._.js} +1 -1
  89. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_3b51a934._.js → 2374f_60d8842c._.js} +1 -1
  90. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_acf3dfe4._.js → 2374f_806bd012._.js} +1 -1
  91. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_db3e363b._.js → 2374f_8dc0f9aa._.js} +1 -1
  92. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_f0d7e130._.js → 2374f_9adc1edb._.js} +1 -1
  93. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_5ebfcf1a._.js → 2374f_b7f45fdf._.js} +1 -1
  94. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_12bad06e._.js → 2374f_c13c8f4f._.js} +1 -1
  95. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_fc992d90._.js → 2374f_cc6c6363._.js} +1 -1
  96. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_3e519469._.js → 2374f_d58d0276._.js} +1 -1
  97. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_a0f483d1._.js → 2374f_ecd2bdca._.js} +1 -1
  98. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_c1d54c16._.js → 2374f_f363c084._.js} +1 -1
  99. package/web/.next/standalone/web/.next/server/chunks/ssr/{2374f_2526ca80._.js → 2374f_fdfc7f3d._.js} +1 -1
  100. package/web/.next/standalone/web/.next/server/chunks/ssr/{[root-of-the-server]__06818a54._.js → [root-of-the-server]__25b25c9d._.js} +2 -2
  101. package/web/.next/standalone/web/.next/server/chunks/ssr/{[root-of-the-server]__a1877334._.js → [root-of-the-server]__9d3a7cbf._.js} +4 -4
  102. package/web/.next/standalone/web/.next/server/chunks/ssr/{web_cc5f7515._.js → web_08242997._.js} +2 -2
  103. package/web/.next/standalone/web/.next/server/chunks/ssr/{web_2b3a5919._.js → web_123ffe97._.js} +2 -2
  104. package/web/.next/standalone/web/.next/server/chunks/ssr/{web_38156da8._.js → web_99b01335._.js} +2 -2
  105. package/web/.next/standalone/web/.next/server/pages/404.html +1 -1
  106. package/web/.next/standalone/web/.next/server/pages/500.html +2 -2
  107. package/web/.next/standalone/web/.next/server/server-reference-manifest.js +1 -1
  108. package/web/.next/standalone/web/.next/server/server-reference-manifest.json +1 -1
  109. package/web/.next/standalone/web/.next/static/chunks/{f95d41079838994a.js → 2624c966c288fd41.js} +3 -3
  110. package/web/.next/standalone/web/.next/static/chunks/74b64476a24dd71e.css +1 -0
  111. package/web/.next/standalone/web/.next/static/{static/chunks/fc39a194539da104.js → chunks/8af263bc97c0c9ee.js} +1 -1
  112. package/web/.next/{static/chunks/2cafc7cb79454d33.js → standalone/web/.next/static/chunks/cfadc93a98190e5a.js} +1 -1
  113. package/web/.next/standalone/web/.next/static/static/chunks/{f95d41079838994a.js → 2624c966c288fd41.js} +3 -3
  114. package/web/.next/standalone/web/.next/static/static/chunks/74b64476a24dd71e.css +1 -0
  115. package/web/.next/{static/chunks/fc39a194539da104.js → standalone/web/.next/static/static/chunks/8af263bc97c0c9ee.js} +1 -1
  116. package/web/.next/standalone/web/.next/static/{chunks/2cafc7cb79454d33.js → static/chunks/cfadc93a98190e5a.js} +1 -1
  117. package/web/.next/standalone/web/src/components/ai-elements/todo-panel.tsx +194 -110
  118. package/web/.next/standalone/web/src/components/ai-elements/todo-tool.tsx +78 -1
  119. package/web/.next/standalone/web/src/components/chat-interface.tsx +15 -9
  120. package/web/.next/standalone/web/src/lib/api.ts +17 -0
  121. package/web/.next/static/chunks/{f95d41079838994a.js → 2624c966c288fd41.js} +3 -3
  122. package/web/.next/static/chunks/74b64476a24dd71e.css +1 -0
  123. package/web/.next/{standalone/web/.next/static/chunks/fc39a194539da104.js → static/chunks/8af263bc97c0c9ee.js} +1 -1
  124. package/web/.next/{standalone/web/.next/static/static/chunks/2cafc7cb79454d33.js → static/chunks/cfadc93a98190e5a.js} +1 -1
  125. package/web/.next/standalone/web/.next/static/chunks/41a5c049931b2c77.css +0 -1
  126. package/web/.next/standalone/web/.next/static/static/chunks/41a5c049931b2c77.css +0 -1
  127. package/web/.next/static/chunks/41a5c049931b2c77.css +0 -1
  128. /package/web/.next/standalone/web/.next/static/{aCZCpTkVv_k-RisOFPegk → J0gen1p9aNjUNIU1NDO5h}/_buildManifest.js +0 -0
  129. /package/web/.next/standalone/web/.next/static/{aCZCpTkVv_k-RisOFPegk → J0gen1p9aNjUNIU1NDO5h}/_clientMiddlewareManifest.json +0 -0
  130. /package/web/.next/standalone/web/.next/static/{aCZCpTkVv_k-RisOFPegk → J0gen1p9aNjUNIU1NDO5h}/_ssgManifest.js +0 -0
  131. /package/web/.next/standalone/web/.next/static/static/{aCZCpTkVv_k-RisOFPegk → J0gen1p9aNjUNIU1NDO5h}/_buildManifest.js +0 -0
  132. /package/web/.next/standalone/web/.next/static/static/{aCZCpTkVv_k-RisOFPegk → J0gen1p9aNjUNIU1NDO5h}/_clientMiddlewareManifest.json +0 -0
  133. /package/web/.next/standalone/web/.next/static/static/{aCZCpTkVv_k-RisOFPegk → J0gen1p9aNjUNIU1NDO5h}/_ssgManifest.js +0 -0
  134. /package/web/.next/static/{aCZCpTkVv_k-RisOFPegk → J0gen1p9aNjUNIU1NDO5h}/_buildManifest.js +0 -0
  135. /package/web/.next/static/{aCZCpTkVv_k-RisOFPegk → J0gen1p9aNjUNIU1NDO5h}/_clientMiddlewareManifest.json +0 -0
  136. /package/web/.next/static/{aCZCpTkVv_k-RisOFPegk → J0gen1p9aNjUNIU1NDO5h}/_ssgManifest.js +0 -0
@@ -104,15 +104,12 @@ declare function createTodoTool(options: TodoToolOptions): ai.Tool<{
104
104
  createdAt: string;
105
105
  }[];
106
106
  stats?: undefined;
107
- item?: undefined;
108
107
  itemsRemoved?: undefined;
109
- planName?: undefined;
110
- filename?: undefined;
111
- path?: undefined;
112
- sizeChars?: undefined;
113
108
  plans?: undefined;
114
109
  count?: undefined;
110
+ planName?: undefined;
115
111
  content?: undefined;
112
+ sizeChars?: undefined;
116
113
  deleted?: undefined;
117
114
  error?: undefined;
118
115
  } | {
@@ -133,18 +130,16 @@ declare function createTodoTool(options: TodoToolOptions): ai.Tool<{
133
130
  createdAt: string;
134
131
  }[];
135
132
  itemsAdded?: undefined;
136
- item?: undefined;
137
133
  itemsRemoved?: undefined;
138
- planName?: undefined;
139
- filename?: undefined;
140
- path?: undefined;
141
- sizeChars?: undefined;
142
134
  plans?: undefined;
143
135
  count?: undefined;
136
+ planName?: undefined;
144
137
  content?: undefined;
138
+ sizeChars?: undefined;
145
139
  deleted?: undefined;
146
140
  error?: undefined;
147
141
  } | {
142
+ planContinuation?: string | undefined;
148
143
  success: boolean;
149
144
  action: string;
150
145
  item: {
@@ -158,13 +153,11 @@ declare function createTodoTool(options: TodoToolOptions): ai.Tool<{
158
153
  items?: undefined;
159
154
  stats?: undefined;
160
155
  itemsRemoved?: undefined;
161
- planName?: undefined;
162
- filename?: undefined;
163
- path?: undefined;
164
- sizeChars?: undefined;
165
156
  plans?: undefined;
166
157
  count?: undefined;
158
+ planName?: undefined;
167
159
  content?: undefined;
160
+ sizeChars?: undefined;
168
161
  deleted?: undefined;
169
162
  error?: undefined;
170
163
  } | {
@@ -174,17 +167,20 @@ declare function createTodoTool(options: TodoToolOptions): ai.Tool<{
174
167
  itemsAdded?: undefined;
175
168
  items?: undefined;
176
169
  stats?: undefined;
177
- item?: undefined;
178
- planName?: undefined;
179
- filename?: undefined;
180
- path?: undefined;
181
- sizeChars?: undefined;
182
170
  plans?: undefined;
183
171
  count?: undefined;
172
+ planName?: undefined;
184
173
  content?: undefined;
174
+ sizeChars?: undefined;
185
175
  deleted?: undefined;
186
176
  error?: undefined;
187
177
  } | {
178
+ autoCreatedTodos?: {
179
+ id: string;
180
+ content: string;
181
+ status: string;
182
+ }[] | undefined;
183
+ autoCreatedFromPhase?: string | undefined;
188
184
  success: boolean;
189
185
  action: string;
190
186
  planName: string;
@@ -194,7 +190,6 @@ declare function createTodoTool(options: TodoToolOptions): ai.Tool<{
194
190
  itemsAdded?: undefined;
195
191
  items?: undefined;
196
192
  stats?: undefined;
197
- item?: undefined;
198
193
  itemsRemoved?: undefined;
199
194
  plans?: undefined;
200
195
  count?: undefined;
@@ -214,13 +209,10 @@ declare function createTodoTool(options: TodoToolOptions): ai.Tool<{
214
209
  itemsAdded?: undefined;
215
210
  items?: undefined;
216
211
  stats?: undefined;
217
- item?: undefined;
218
212
  itemsRemoved?: undefined;
219
213
  planName?: undefined;
220
- filename?: undefined;
221
- path?: undefined;
222
- sizeChars?: undefined;
223
214
  content?: undefined;
215
+ sizeChars?: undefined;
224
216
  deleted?: undefined;
225
217
  error?: undefined;
226
218
  } | {
@@ -232,10 +224,7 @@ declare function createTodoTool(options: TodoToolOptions): ai.Tool<{
232
224
  itemsAdded?: undefined;
233
225
  items?: undefined;
234
226
  stats?: undefined;
235
- item?: undefined;
236
227
  itemsRemoved?: undefined;
237
- filename?: undefined;
238
- path?: undefined;
239
228
  plans?: undefined;
240
229
  count?: undefined;
241
230
  deleted?: undefined;
@@ -248,14 +237,11 @@ declare function createTodoTool(options: TodoToolOptions): ai.Tool<{
248
237
  itemsAdded?: undefined;
249
238
  items?: undefined;
250
239
  stats?: undefined;
251
- item?: undefined;
252
240
  itemsRemoved?: undefined;
253
- filename?: undefined;
254
- path?: undefined;
255
- sizeChars?: undefined;
256
241
  plans?: undefined;
257
242
  count?: undefined;
258
243
  content?: undefined;
244
+ sizeChars?: undefined;
259
245
  error?: undefined;
260
246
  } | {
261
247
  success: boolean;
@@ -264,15 +250,12 @@ declare function createTodoTool(options: TodoToolOptions): ai.Tool<{
264
250
  itemsAdded?: undefined;
265
251
  items?: undefined;
266
252
  stats?: undefined;
267
- item?: undefined;
268
253
  itemsRemoved?: undefined;
269
- planName?: undefined;
270
- filename?: undefined;
271
- path?: undefined;
272
- sizeChars?: undefined;
273
254
  plans?: undefined;
274
255
  count?: undefined;
256
+ planName?: undefined;
275
257
  content?: undefined;
258
+ sizeChars?: undefined;
276
259
  deleted?: undefined;
277
260
  }>;
278
261
 
@@ -2779,22 +2779,27 @@ function createTodoTool(options) {
2779
2779
  - "clear": Remove all todo items from the list
2780
2780
 
2781
2781
  ## Plan Actions (for complex, multi-phase work)
2782
- - "save_plan": Create or update a named plan \u2014 a persistent markdown document with hierarchical tasks, subtasks, and notes. Plans survive context compaction and are always available.
2782
+ - "save_plan": Create or update a named plan. When saved and no active todos exist, todos are AUTO-CREATED from the first uncompleted phase.
2783
2783
  - "list_plans": List all plans for this session
2784
2784
  - "get_plan": Read a specific plan by name
2785
2785
  - "delete_plan": Remove a plan
2786
2786
 
2787
2787
  ## Plans vs Todos
2788
2788
  - **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.
2789
- - **Todos** are your current focus \u2014 the immediate steps you're working on right now.
2789
+ - **Todos** are your current focus \u2014 the immediate steps you're working on right now, auto-derived from plan phases.
2790
2790
 
2791
2791
  ## Workflow for complex tasks
2792
- 1. Create a plan with phases and subtasks (save_plan)
2793
- 2. Create todos from the first uncompleted phase (add)
2794
- 3. Work through the todos, marking them as you go
2795
- 4. When all current todos are done, update the plan (mark completed sections with [x]) and save it
2796
- 5. Create new todos from the next uncompleted phase
2797
- 6. Repeat until the plan is fully complete
2792
+ 1. Create a plan with phases and subtasks using checkboxes (save_plan) \u2014 todos are auto-created from Phase 1
2793
+ 2. Work through the todos, marking them as you go
2794
+ 3. When all todos are done, update the plan: mark the completed phase heading with [completed] and its items with [x]
2795
+ 4. Call save_plan again with the updated content \u2014 todos are auto-created from the next uncompleted phase
2796
+ 5. Repeat until all phases are complete, then delete_plan
2797
+
2798
+ ## Auto-todo creation rules
2799
+ - Only triggers when there are NO active (pending/in_progress) todos
2800
+ - Skips phases with [completed] in the heading
2801
+ - Skips sections named Overview, Notes, Key Decisions, etc.
2802
+ - Only top-level checklist items (- [ ]) become todos \u2014 indented sub-items are task details
2798
2803
 
2799
2804
  ## Plan format
2800
2805
  Plans should be markdown with this structure:
@@ -2878,10 +2883,34 @@ Plans should be markdown with this structure:
2878
2883
  error: `Todo item not found: ${todoId}`
2879
2884
  };
2880
2885
  }
2886
+ let planContinuation;
2887
+ if (status === "completed") {
2888
+ const allTodos = await todoQueries.getBySession(options.sessionId);
2889
+ const allDone = allTodos.every(
2890
+ (t) => t.status === "completed" || t.status === "cancelled"
2891
+ );
2892
+ if (allDone) {
2893
+ const plansDir = getPlansDir(options.workingDirectory, options.sessionId);
2894
+ if (existsSync9(plansDir)) {
2895
+ const planFiles = readdirSync(plansDir).filter((f) => f.endsWith(".md"));
2896
+ for (const f of planFiles) {
2897
+ try {
2898
+ const content = await readFile6(join4(plansDir, f), "utf-8");
2899
+ if (parseNextUncompletedPhase(content) !== null) {
2900
+ 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.";
2901
+ break;
2902
+ }
2903
+ } catch {
2904
+ }
2905
+ }
2906
+ }
2907
+ }
2908
+ }
2881
2909
  return {
2882
2910
  success: true,
2883
2911
  action: "mark",
2884
- item: formatTodoItem(updated)
2912
+ item: formatTodoItem(updated),
2913
+ ...planContinuation ? { planContinuation } : {}
2885
2914
  };
2886
2915
  }
2887
2916
  case "clear": {
@@ -2904,13 +2933,32 @@ Plans should be markdown with this structure:
2904
2933
  const filename = `${slugify(planName)}.md`;
2905
2934
  const filePath = join4(dir, filename);
2906
2935
  await writeFile4(filePath, planContent, "utf-8");
2936
+ const existingTodos = await todoQueries.getBySession(options.sessionId);
2937
+ const hasActiveTodos = existingTodos.some(
2938
+ (t) => t.status === "pending" || t.status === "in_progress"
2939
+ );
2940
+ let autoCreatedTodos = [];
2941
+ if (!hasActiveTodos) {
2942
+ const nextPhase = parseNextUncompletedPhase(planContent);
2943
+ if (nextPhase) {
2944
+ const created = await todoQueries.createMany(
2945
+ options.sessionId,
2946
+ nextPhase.tasks.map((task, i) => ({ content: task, order: i }))
2947
+ );
2948
+ autoCreatedTodos = created.map(formatTodoItem);
2949
+ }
2950
+ }
2907
2951
  return {
2908
2952
  success: true,
2909
2953
  action: "save_plan",
2910
2954
  planName,
2911
2955
  filename,
2912
2956
  path: filePath,
2913
- sizeChars: planContent.length
2957
+ sizeChars: planContent.length,
2958
+ ...autoCreatedTodos.length > 0 ? {
2959
+ autoCreatedTodos,
2960
+ autoCreatedFromPhase: "Created todos from the first uncompleted phase. Start working on them!"
2961
+ } : {}
2914
2962
  };
2915
2963
  }
2916
2964
  case "list_plans": {
@@ -2991,6 +3039,47 @@ function formatTodoItem(item) {
2991
3039
  createdAt: item.createdAt.toISOString()
2992
3040
  };
2993
3041
  }
3042
+ function parseNextUncompletedPhase(content) {
3043
+ const lines = content.split("\n");
3044
+ let currentPhase = null;
3045
+ let currentTasks = [];
3046
+ let hasUncompletedTask = false;
3047
+ for (const line of lines) {
3048
+ const h2Match = line.match(/^##\s+(.+)/);
3049
+ if (h2Match) {
3050
+ if (currentPhase && hasUncompletedTask && currentTasks.length > 0) {
3051
+ return { phaseName: currentPhase, tasks: currentTasks };
3052
+ }
3053
+ const headingText = h2Match[1].trim();
3054
+ if (/^(overview|notes|key decisions|context|summary|references)\b/i.test(headingText)) {
3055
+ currentPhase = null;
3056
+ currentTasks = [];
3057
+ hasUncompletedTask = false;
3058
+ continue;
3059
+ }
3060
+ if (/\[completed\]/i.test(headingText)) {
3061
+ currentPhase = null;
3062
+ currentTasks = [];
3063
+ hasUncompletedTask = false;
3064
+ continue;
3065
+ }
3066
+ currentPhase = headingText.replace(/\s*\[(in_progress|pending|completed)\]\s*/gi, "").replace(/^Phase\s+\d+[:\s]*/i, "").trim();
3067
+ currentTasks = [];
3068
+ hasUncompletedTask = false;
3069
+ continue;
3070
+ }
3071
+ if (!currentPhase) continue;
3072
+ const uncheckedMatch = line.match(/^[-*]\s+\[\s\]\s+(.+)/);
3073
+ if (uncheckedMatch) {
3074
+ currentTasks.push(uncheckedMatch[1].trim());
3075
+ hasUncompletedTask = true;
3076
+ }
3077
+ }
3078
+ if (currentPhase && hasUncompletedTask && currentTasks.length > 0) {
3079
+ return { phaseName: currentPhase, tasks: currentTasks };
3080
+ }
3081
+ return null;
3082
+ }
2994
3083
 
2995
3084
  // src/tools/load-skill.ts
2996
3085
  import { tool as tool5 } from "ai";