@cydm/pie 1.0.2 → 1.0.4

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.
@@ -3716,6 +3716,9 @@ function logHttp(level, message, data) {
3716
3716
  }
3717
3717
  }
3718
3718
  }
3719
+ function isAbortErrorMessage(message) {
3720
+ return message === "Request was aborted" || message === "Operation aborted";
3721
+ }
3719
3722
  initLogFile();
3720
3723
  var nodeHttps = null;
3721
3724
  var nodeHttp = null;
@@ -3976,6 +3979,13 @@ var NodeHttpClient = class {
3976
3979
  resolve(response);
3977
3980
  });
3978
3981
  req.on("error", (e) => {
3982
+ if (isAbortErrorMessage(e.message) && options.signal?.aborted) {
3983
+ logHttp("DEBUG", `Request [${requestId}] aborted`, {
3984
+ totalTimeMs: Date.now() - requestStartTime
3985
+ });
3986
+ reject(e);
3987
+ return;
3988
+ }
3979
3989
  logHttp("ERROR", `Request [${requestId}] failed`, {
3980
3990
  error: e.message,
3981
3991
  totalTimeMs: Date.now() - requestStartTime
package/dist/cli.js CHANGED
@@ -4914,6 +4914,9 @@ function logHttp(level, message, data) {
4914
4914
  }
4915
4915
  }
4916
4916
  }
4917
+ function isAbortErrorMessage(message) {
4918
+ return message === "Request was aborted" || message === "Operation aborted";
4919
+ }
4917
4920
  function getNodeHttps() {
4918
4921
  if (!nodeHttps) {
4919
4922
  nodeHttps = require3("https");
@@ -5184,6 +5187,13 @@ var init_http = __esm({
5184
5187
  resolve5(response);
5185
5188
  });
5186
5189
  req.on("error", (e) => {
5190
+ if (isAbortErrorMessage(e.message) && options.signal?.aborted) {
5191
+ logHttp("DEBUG", `Request [${requestId}] aborted`, {
5192
+ totalTimeMs: Date.now() - requestStartTime
5193
+ });
5194
+ reject(e);
5195
+ return;
5196
+ }
5187
5197
  logHttp("ERROR", `Request [${requestId}] failed`, {
5188
5198
  error: e.message,
5189
5199
  totalTimeMs: Date.now() - requestStartTime
@@ -65450,6 +65460,7 @@ init_file_logger();
65450
65460
  import * as fs4 from "node:fs";
65451
65461
  import * as os2 from "os";
65452
65462
  import * as path3 from "path";
65463
+ import { pathToFileURL } from "node:url";
65453
65464
 
65454
65465
  // src/config.ts
65455
65466
  import { existsSync as existsSync3, mkdirSync as mkdirSync4, readFileSync as readFileSync2, renameSync } from "fs";
@@ -65823,7 +65834,7 @@ function resolvePath(extPath, cwd) {
65823
65834
  }
65824
65835
  async function loadExtensionModule(extensionPath) {
65825
65836
  try {
65826
- const module = await import(extensionPath);
65837
+ const module = await import(normalizeExtensionImportPath(extensionPath));
65827
65838
  const factory = module.default ?? module;
65828
65839
  if (typeof factory !== "function") {
65829
65840
  return null;
@@ -65835,6 +65846,15 @@ async function loadExtensionModule(extensionPath) {
65835
65846
  );
65836
65847
  }
65837
65848
  }
65849
+ function normalizeExtensionImportPath(extensionPath) {
65850
+ if (/^[a-zA-Z]:[\\/]/.test(extensionPath)) {
65851
+ return `file:///${extensionPath.replace(/\\/g, "/")}`;
65852
+ }
65853
+ if (path3.isAbsolute(extensionPath)) {
65854
+ return pathToFileURL(extensionPath).href;
65855
+ }
65856
+ return extensionPath;
65857
+ }
65838
65858
  async function loadExtension2(extensionPath, cwd, uiContext, abortFn, isIdleFn, hasUI, actions) {
65839
65859
  const resolvedPath = resolvePath(extensionPath, cwd);
65840
65860
  if (!fs4.existsSync(resolvedPath)) {
@@ -69294,6 +69314,75 @@ function findFirstChangedLine(oldText, newText) {
69294
69314
  return void 0;
69295
69315
  }
69296
69316
 
69317
+ // src/todo/render.ts
69318
+ var TODO_STATUS_ICONS = {
69319
+ completed: "\u2713",
69320
+ "in-progress": "\u25C9",
69321
+ "not-started": "\u25CB"
69322
+ };
69323
+ function formatTodoTitle(todo, activeTheme) {
69324
+ if (todo.status === "completed") {
69325
+ return activeTheme.fg("dim", activeTheme.strikethrough(todo.title));
69326
+ }
69327
+ if (todo.status === "in-progress") {
69328
+ return activeTheme.fg("warning", todo.title);
69329
+ }
69330
+ return activeTheme.fg("muted", todo.title);
69331
+ }
69332
+ function formatTodoIcon(todo, activeTheme) {
69333
+ const icon = TODO_STATUS_ICONS[todo.status] ?? "?";
69334
+ if (todo.status === "completed") {
69335
+ return activeTheme.fg("success", icon);
69336
+ }
69337
+ if (todo.status === "in-progress") {
69338
+ return activeTheme.fg("warning", icon);
69339
+ }
69340
+ return activeTheme.fg("muted", icon);
69341
+ }
69342
+ function renderManageTodoListCall(args, activeTheme = theme) {
69343
+ let text = activeTheme.fg("toolTitle", activeTheme.bold("manage_todo_list "));
69344
+ text += activeTheme.fg("muted", args.operation || "...");
69345
+ if (args.operation === "write" && Array.isArray(args.todoList)) {
69346
+ const count = args.todoList.length;
69347
+ text += activeTheme.fg("dim", ` (${count} item${count === 1 ? "" : "s"})`);
69348
+ }
69349
+ return text;
69350
+ }
69351
+ function renderManageTodoListResult(result, options, activeTheme = theme) {
69352
+ const details = result.details;
69353
+ if (!details) {
69354
+ const firstText = result.content?.find((item) => item.type === "text" && typeof item.text === "string")?.text;
69355
+ return firstText || "";
69356
+ }
69357
+ if (details.error) {
69358
+ return activeTheme.fg("error", `\u2717 ${details.error}`);
69359
+ }
69360
+ const todos = details.todos || [];
69361
+ if (todos.length === 0) {
69362
+ return activeTheme.fg("dim", "No todos");
69363
+ }
69364
+ const completed = todos.filter((todo) => todo.status === "completed").length;
69365
+ let text = `${activeTheme.fg("success", "\u2713")} ${activeTheme.fg("muted", `${completed}/${todos.length} completed`)}`;
69366
+ if (options.expanded) {
69367
+ for (const todo of todos) {
69368
+ text += `
69369
+ ${formatTodoIcon(todo, activeTheme)} ${activeTheme.fg("accent", `${todo.id}.`)} ${formatTodoTitle(todo, activeTheme)}`;
69370
+ }
69371
+ }
69372
+ return text;
69373
+ }
69374
+ function renderTodoWidgetLines(todos, activeTheme = theme) {
69375
+ if (todos.length === 0) {
69376
+ return [];
69377
+ }
69378
+ const completed = todos.filter((todo) => todo.status === "completed").length;
69379
+ const lines = [activeTheme.fg("muted", `Todo List - ${completed}/${todos.length} completed`)];
69380
+ for (const todo of todos) {
69381
+ lines.push(` ${formatTodoIcon(todo, activeTheme)} ${activeTheme.fg("accent", `${todo.id}.`)} ${formatTodoTitle(todo, activeTheme)}`);
69382
+ }
69383
+ return lines;
69384
+ }
69385
+
69297
69386
  // src/components/tool-execution.ts
69298
69387
  function formatSize3(bytes) {
69299
69388
  if (bytes < 1024) return `${bytes}B`;
@@ -69376,7 +69465,13 @@ var ToolExecutionComponent = class extends Container {
69376
69465
  formatToolExecution() {
69377
69466
  let text = "";
69378
69467
  const invalidArg = theme.fg("error", "[invalid arg]");
69379
- if (this.toolName === "read") {
69468
+ if (this.toolName === "manage_todo_list") {
69469
+ text = renderManageTodoListCall(this.args, theme);
69470
+ if (this.result) {
69471
+ text += `
69472
+ ${renderManageTodoListResult(this.result, { expanded: this.expanded }, theme)}`;
69473
+ }
69474
+ } else if (this.toolName === "read") {
69380
69475
  const rawPath = str(this.args?.file_path ?? this.args?.path);
69381
69476
  const path18 = rawPath !== null ? shortenPath(rawPath) : null;
69382
69477
  const offset = this.args?.offset;
@@ -69712,6 +69807,27 @@ ${theme.fg("error", "Error: " + errorOutput)}`;
69712
69807
  }
69713
69808
  };
69714
69809
 
69810
+ // src/components/todo-widget.ts
69811
+ var TodoWidgetComponent = class extends Container {
69812
+ state;
69813
+ constructor(state) {
69814
+ super();
69815
+ this.state = state;
69816
+ this.refresh();
69817
+ }
69818
+ refresh() {
69819
+ this.clear();
69820
+ const lines = renderTodoWidgetLines(this.state.read());
69821
+ if (lines.length === 0) {
69822
+ return;
69823
+ }
69824
+ this.addChild(new Spacer(1));
69825
+ for (const line of lines) {
69826
+ this.addChild(new Text(line, 1, 0));
69827
+ }
69828
+ }
69829
+ };
69830
+
69715
69831
  // src/components/tree-selector.ts
69716
69832
  var RESET = "\x1B[0m";
69717
69833
  var INVERSE = "\x1B[7m";
@@ -74698,6 +74814,8 @@ var InteractiveMode = class {
74698
74814
  footerData;
74699
74815
  editor;
74700
74816
  editorContainer;
74817
+ todoWidgetContainer;
74818
+ todoWidget;
74701
74819
  keybindings;
74702
74820
  sessionManager;
74703
74821
  skills;
@@ -74807,6 +74925,11 @@ var InteractiveMode = class {
74807
74925
  this.skillsSection = formatSkillsForPrompt(options.skills);
74808
74926
  }
74809
74927
  options;
74928
+ refreshTodoWidget() {
74929
+ this.todoWidget.refresh();
74930
+ this.todoWidgetContainer.invalidate?.();
74931
+ this.safeRequestRender();
74932
+ }
74810
74933
  async init() {
74811
74934
  const savedLevel = this.options.settingsManager.getDefaultThinkingLevel();
74812
74935
  if (savedLevel) {
@@ -74827,6 +74950,8 @@ var InteractiveMode = class {
74827
74950
  });
74828
74951
  this.updateTerminalTitle();
74829
74952
  this.setupUI();
74953
+ this.options.todoState.restoreFromMessages(this.sessionManager.getMessages());
74954
+ this.refreshTodoWidget();
74830
74955
  this.setupAutocomplete();
74831
74956
  this.setupAgentSubscription();
74832
74957
  this.setupEditorSubmitHandler();
@@ -75724,6 +75849,9 @@ ${newToolsSection}`
75724
75849
  contextWindow: this.options.model?.contextWindow ?? 0
75725
75850
  });
75726
75851
  this.editorContainer = new Container();
75852
+ this.todoWidgetContainer = new Container();
75853
+ this.todoWidget = new TodoWidgetComponent(this.options.todoState);
75854
+ this.todoWidgetContainer.addChild(this.todoWidget);
75727
75855
  const editorTheme = getEditorTheme();
75728
75856
  this.editor = new Editor(this.ui, editorTheme, { paddingX: 1 });
75729
75857
  this.editor.onChange = () => {
@@ -75737,6 +75865,7 @@ ${newToolsSection}`
75737
75865
  this.editorContainer.addChild(this.editor);
75738
75866
  this.ui.addChild(this.chatContainer);
75739
75867
  this.ui.addChild(this.pendingMessagesContainer);
75868
+ this.ui.addChild(this.todoWidgetContainer);
75740
75869
  this.ui.addChild(new Spacer());
75741
75870
  this.ui.addChild(this.footer);
75742
75871
  this.ui.addChild(this.editorContainer);
@@ -75976,7 +76105,18 @@ ${newToolsSection}`
75976
76105
  thinkingContent += content2.thinking || "";
75977
76106
  } else if (content2.type === "toolCall") {
75978
76107
  const toolCall = content2;
75979
- const toolId = toolCall.id || toolCall.name;
76108
+ const contentIndex = message.content.indexOf(content2);
76109
+ const partialToolId = `__partial_tool__:${contentIndex}`;
76110
+ const toolId = toolCall.id || partialToolId;
76111
+ if (toolCall.id && !this.pendingTools.has(toolCall.id) && this.pendingTools.has(partialToolId)) {
76112
+ const existingComponent = this.pendingTools.get(partialToolId);
76113
+ if (existingComponent) {
76114
+ this.pendingTools.delete(partialToolId);
76115
+ this.pendingTools.set(toolCall.id, existingComponent);
76116
+ existingComponent.updateArgs(toolCall.arguments);
76117
+ }
76118
+ continue;
76119
+ }
75980
76120
  if (!this.pendingTools.has(toolId)) {
75981
76121
  const toolComponent = new ToolExecutionComponent(
75982
76122
  toolCall.name,
@@ -76064,6 +76204,9 @@ ${newToolsSection}`
76064
76204
  );
76065
76205
  }
76066
76206
  }
76207
+ if (event.toolName === "manage_todo_list") {
76208
+ this.refreshTodoWidget();
76209
+ }
76067
76210
  this.footer.setState({ lifecycleEvent: "tool_execution_end" });
76068
76211
  this.emitExtensionEvent({
76069
76212
  type: "tool:execution:end",
@@ -76868,6 +77011,7 @@ ${newToolsSection}`
76868
77011
  this.safeRequestRender();
76869
77012
  this.agent.abort();
76870
77013
  const cleanup = async () => {
77014
+ let timedOut = false;
76871
77015
  try {
76872
77016
  await Promise.race([
76873
77017
  this.agent.waitForIdle(),
@@ -76876,12 +77020,19 @@ ${newToolsSection}`
76876
77020
  )
76877
77021
  ]);
76878
77022
  } catch {
77023
+ timedOut = true;
77024
+ }
77025
+ if (timedOut || this.agent.state.isStreaming) {
77026
+ this.agent.resetProcessingState();
76879
77027
  }
76880
77028
  this.isProcessing = false;
76881
77029
  this.setSubmitLock(false);
76882
77030
  this.isInterrupting = false;
77031
+ this.streamingComponent = void 0;
77032
+ this.queuedSubmissionText = void 0;
76883
77033
  this.footer.setState({ status: "ready" });
76884
77034
  this.pendingTools.clear();
77035
+ this.ui.setFocus(this.editor);
76885
77036
  this.chatContainer.addChild(new Text(theme.fg("warning", "\u26A0 Interrupted by user"), 1, 0));
76886
77037
  this.chatContainer.addChild(new Spacer(1));
76887
77038
  this.safeRequestRender();
@@ -77399,11 +77550,13 @@ ${newToolsSection}`
77399
77550
  this.updateTerminalTitle();
77400
77551
  const messages = this.sessionManager.getMessages();
77401
77552
  const conversationMessages = messages.filter(
77402
- (msg) => msg.role === "user" || msg.role === "assistant"
77553
+ (msg) => msg.role === "user" || msg.role === "assistant" || msg.role === "toolResult"
77403
77554
  );
77404
77555
  this.agent.resetProcessingState();
77405
77556
  this.agent.replaceMessages(conversationMessages);
77406
77557
  this.lastSyncedMessageCount = this.agent.state.messages.length;
77558
+ this.options.todoState.restoreFromMessages(messages);
77559
+ this.refreshTodoWidget();
77407
77560
  this.chatContainer.clear();
77408
77561
  this.lastStatusSpacer = void 0;
77409
77562
  this.lastStatusText = void 0;
@@ -78053,6 +78206,9 @@ ${args}` : skillBlock;
78053
78206
  this.chatContainer.addChild(new Spacer(1));
78054
78207
  this.chatContainer.addChild(new Text(theme.fg("accent", `$ ${command}`), 1, 0));
78055
78208
  this.editor.setText("");
78209
+ const outputContainer = new Container();
78210
+ outputContainer.addChild(new Spacer(1));
78211
+ this.chatContainer.addChild(outputContainer);
78056
78212
  this.ui.requestRender();
78057
78213
  const { spawn: spawn3 } = await import("child_process");
78058
78214
  const child = spawn3("bash", ["-c", command], {
@@ -78060,16 +78216,9 @@ ${args}` : skillBlock;
78060
78216
  env: process.env
78061
78217
  });
78062
78218
  let output = "";
78063
- let isOutputAdded = false;
78064
- const outputContainer = new Container();
78065
- outputContainer.addChild(new Spacer(1));
78066
78219
  child.stdout.on("data", (data) => {
78067
78220
  const text = data.toString();
78068
78221
  output += text;
78069
- if (!isOutputAdded) {
78070
- this.chatContainer.addChild(outputContainer);
78071
- isOutputAdded = true;
78072
- }
78073
78222
  const lines = text.split("\n");
78074
78223
  for (const line of lines) {
78075
78224
  if (line || lines.indexOf(line) < lines.length - 1) {
@@ -78081,10 +78230,6 @@ ${args}` : skillBlock;
78081
78230
  child.stderr.on("data", (data) => {
78082
78231
  const text = data.toString();
78083
78232
  output += text;
78084
- if (!isOutputAdded) {
78085
- this.chatContainer.addChild(outputContainer);
78086
- isOutputAdded = true;
78087
- }
78088
78233
  const lines = text.split("\n");
78089
78234
  for (const line of lines) {
78090
78235
  if (line || lines.indexOf(line) < lines.length - 1) {
@@ -78719,6 +78864,177 @@ var ModelRegistry = class {
78719
78864
  }
78720
78865
  };
78721
78866
 
78867
+ // src/todo/state-manager.ts
78868
+ var TodoStateManager = class {
78869
+ todos = [];
78870
+ read() {
78871
+ return this.todos.map((todo) => ({ ...todo }));
78872
+ }
78873
+ write(todos) {
78874
+ this.todos = todos.map((todo) => ({ ...todo }));
78875
+ }
78876
+ clear() {
78877
+ this.todos = [];
78878
+ }
78879
+ getStats() {
78880
+ const total = this.todos.length;
78881
+ const completed = this.todos.filter((todo) => todo.status === "completed").length;
78882
+ const inProgress = this.todos.filter((todo) => todo.status === "in-progress").length;
78883
+ return {
78884
+ total,
78885
+ completed,
78886
+ inProgress,
78887
+ notStarted: total - completed - inProgress
78888
+ };
78889
+ }
78890
+ validate(todos) {
78891
+ const errors = [];
78892
+ if (!Array.isArray(todos)) {
78893
+ return { valid: false, errors: ["todoList must be an array"] };
78894
+ }
78895
+ const validStatuses = /* @__PURE__ */ new Set(["not-started", "in-progress", "completed"]);
78896
+ for (let index = 0; index < todos.length; index++) {
78897
+ const item = todos[index];
78898
+ const prefix = `Item ${index + 1}`;
78899
+ if (typeof item?.id !== "number" || !Number.isInteger(item.id) || item.id < 1) {
78900
+ errors.push(`${prefix}: 'id' must be a positive integer`);
78901
+ }
78902
+ if (typeof item?.title !== "string" || item.title.trim().length === 0) {
78903
+ errors.push(`${prefix}: 'title' is required`);
78904
+ }
78905
+ if (typeof item?.description !== "string") {
78906
+ errors.push(`${prefix}: 'description' must be a string`);
78907
+ }
78908
+ if (!validStatuses.has(item?.status)) {
78909
+ errors.push(`${prefix}: 'status' must be one of: not-started, in-progress, completed`);
78910
+ }
78911
+ if (item?.id !== index + 1) {
78912
+ errors.push(`${prefix}: ids must be sequential starting from 1`);
78913
+ }
78914
+ }
78915
+ return { valid: errors.length === 0, errors };
78916
+ }
78917
+ restoreFromMessages(messages) {
78918
+ this.todos = [];
78919
+ for (const message of messages) {
78920
+ if (message.role !== "toolResult" || message.toolName !== "manage_todo_list") {
78921
+ continue;
78922
+ }
78923
+ const details = message.details;
78924
+ if (details?.todos) {
78925
+ this.todos = details.todos.map((todo) => ({ ...todo }));
78926
+ }
78927
+ }
78928
+ }
78929
+ };
78930
+
78931
+ // src/todo/tool.ts
78932
+ init_esm();
78933
+ function stringEnum(values, description) {
78934
+ return Type.Union(values.map((value) => Type.Literal(value)), { description });
78935
+ }
78936
+ var TodoItemSchema = Type.Object({
78937
+ id: Type.Number({ description: "Unique identifier for the todo. Use sequential numbers starting from 1." }),
78938
+ title: Type.String({ description: "Concise action-oriented todo label (3-7 words). Displayed in the UI." }),
78939
+ description: Type.String({
78940
+ description: "Detailed context, requirements, or implementation notes for the todo item."
78941
+ }),
78942
+ status: stringEnum(
78943
+ ["not-started", "in-progress", "completed"],
78944
+ "not-started: Not begun | in-progress: Currently working | completed: Fully finished with no blockers"
78945
+ )
78946
+ });
78947
+ var ManageTodoListParams = Type.Object({
78948
+ operation: stringEnum(
78949
+ ["write", "read"],
78950
+ "write: Replace entire todo list with new content. read: Retrieve current todo list."
78951
+ ),
78952
+ todoList: Type.Optional(
78953
+ Type.Array(TodoItemSchema, {
78954
+ description: "Complete array of all todo items. Required for write. Must include ALL items."
78955
+ })
78956
+ )
78957
+ });
78958
+ var MANAGE_TODO_LIST_DESCRIPTION = `Manage a structured todo list to track progress and plan tasks throughout your coding session.
78959
+
78960
+ Use this tool for complex multi-step work, especially when:
78961
+ - The task needs planning or progress tracking
78962
+ - The user provided multiple requests
78963
+ - You need to break a larger change into actionable steps
78964
+ - You are about to start or finish a tracked step
78965
+
78966
+ Workflow:
78967
+ 1. Write the full todo list with clear action items
78968
+ 2. Mark the current item as in-progress before starting it
78969
+ 3. Complete the work for that item
78970
+ 4. Mark it completed immediately
78971
+ 5. Continue until all items are done
78972
+
78973
+ Always send the full list on write. Partial updates are not supported.`;
78974
+ function successMessage(todos) {
78975
+ const total = todos.length;
78976
+ const completed = todos.filter((todo) => todo.status === "completed").length;
78977
+ let message = `Todos have been modified successfully. ${completed}/${total} completed. Ensure that you continue to use the todo list to track your progress. Please proceed with the current tasks if applicable.`;
78978
+ if (total < 3) {
78979
+ message += "\n\nWarning: Small todo list (<3 items). This task might not need a todo list.";
78980
+ }
78981
+ return message;
78982
+ }
78983
+ function createManageTodoListTool(state) {
78984
+ return {
78985
+ name: "manage_todo_list",
78986
+ label: "manage_todo_list",
78987
+ description: MANAGE_TODO_LIST_DESCRIPTION,
78988
+ parameters: ManageTodoListParams,
78989
+ execute: async (_toolCallId, params) => {
78990
+ if (params.operation === "read") {
78991
+ const todos2 = state.read();
78992
+ return {
78993
+ content: [
78994
+ {
78995
+ type: "text",
78996
+ text: todos2.length ? JSON.stringify(todos2, null, 2) : "No todos. Use write operation to create a todo list."
78997
+ }
78998
+ ],
78999
+ details: { operation: "read", todos: todos2 }
79000
+ };
79001
+ }
79002
+ if (!params.todoList || !Array.isArray(params.todoList)) {
79003
+ return {
79004
+ content: [{ type: "text", text: "Error: todoList is required for write operation." }],
79005
+ details: { operation: "write", todos: state.read(), error: "todoList required" },
79006
+ isError: true
79007
+ };
79008
+ }
79009
+ const todoList = params.todoList;
79010
+ const validation = state.validate(todoList);
79011
+ if (!validation.valid) {
79012
+ return {
79013
+ content: [
79014
+ {
79015
+ type: "text",
79016
+ text: `Validation failed:
79017
+ ${validation.errors.map((error) => ` - ${error}`).join("\n")}`
79018
+ }
79019
+ ],
79020
+ details: {
79021
+ operation: "write",
79022
+ todos: state.read(),
79023
+ error: validation.errors.join("; ")
79024
+ },
79025
+ isError: true
79026
+ };
79027
+ }
79028
+ state.write(todoList);
79029
+ const todos = state.read();
79030
+ return {
79031
+ content: [{ type: "text", text: successMessage(todos) }],
79032
+ details: { operation: "write", todos }
79033
+ };
79034
+ }
79035
+ };
79036
+ }
79037
+
78722
79038
  // src/cli.ts
78723
79039
  enableEarlyLogBuffer();
78724
79040
  var logError = (msg, err) => {
@@ -78810,7 +79126,8 @@ async function startChat(initialPrompt, testCommand) {
78810
79126
  settingsManager.setDefaultModelAndProvider(provider, modelId);
78811
79127
  const cwd = process.cwd();
78812
79128
  const fsOptions = { allowlistedDirs: [CONFIG_DIR] };
78813
- const tools = [...createFileSystemTools(cwd, fsOptions), createBashTool(cwd)];
79129
+ const todoState = new TodoStateManager();
79130
+ const tools = [...createFileSystemTools(cwd, fsOptions), createBashTool(cwd), createManageTodoListTool(todoState)];
78814
79131
  const sessionManager = createSessionManager({ sessionsDir: SESSIONS_DIR });
78815
79132
  if (explicitSessionId) {
78816
79133
  const loaded = await sessionManager.loadSession(explicitSessionId);
@@ -78928,6 +79245,7 @@ Current working directory: ${cwd}${skillsSection}`;
78928
79245
  model,
78929
79246
  apiKey,
78930
79247
  tools,
79248
+ todoState,
78931
79249
  sessionManager,
78932
79250
  skills,
78933
79251
  cwd,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cydm/pie",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Pie AI Agent CLI",
5
5
  "type": "module",
6
6
  "bin": {