todo-agent 0.3.5__py3-none-any.whl → 0.3.6__py3-none-any.whl

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.
todo_agent/_version.py CHANGED
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.3.5'
32
- __version_tuple__ = version_tuple = (0, 3, 5)
31
+ __version__ = version = '0.3.6'
32
+ __version_tuple__ = version_tuple = (0, 3, 6)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -104,23 +104,28 @@ Example: add_task(description='Put out trash and recycling', project='weekly', c
104
104
 
105
105
  **Parent Task Format**: `(A) Child task description +project @context due:YYYY-MM-DD duration:2h parent:12`
106
106
 
107
- ### Task Completion Protocol
107
+ ### Task Completion Protocol
108
+ NOTE: use complete_task() for existing non-recurring tasks
108
109
  1. **Discovery**: Use `list_tasks()` to search semantically in active tasks
109
- 2. **For Recurring Tasks** (containing +daily, +weekly, +monthly, +weekdays, etc.):
110
+ 2. **For Non-Recurring Tasks**:
111
+ - The task will NOT have the tag "rec:"
112
+ - Single match → use `complete_task(task_number='XX')` to mark existing active tasks complete
113
+ - Multiple/fuzzy → show options
114
+ - No match → suggest alternatives
115
+ 3. **For Recurring Tasks** (containing +daily, +weekly, +monthly, +weekdays, etc.):
116
+ - The task will have the tag "rec:"
110
117
  - **USE** `create_completed_task()` with the original task number as parent_number
111
118
  - **PRESERVE** the original recurring task for future occurrences. **IMPORTANT** DO NOT MARK COMPLETE! DO NOT MODIFY!
112
119
  - **TOOL CALL**: `create_completed_task(description='Task description', parent_number='XX', completion_date='YYYY-MM-DD', context='context', project='project')`
113
- 3. **For Non-Recurring Tasks**:
114
- - Single match → use `complete_task(task_number='XX')`
115
- - Multiple/fuzzy → show options
116
- - No match → suggest alternatives
120
+
117
121
 
118
122
  ### Recurring Task Completion Examples
123
+ NOTE: ONLY USE create_completed_task() for RECURRING TASKS!
119
124
  - **User says**: "I put out the trash" → Find `(B) Put out trash and recycling +weekly +thursday @home duration:5m`
120
- - **Tool Call**: `create_completed_task(description='Put out trash and recycling', parent_number='B', completion_date='YYYY-MM-DD', context='home', project='weekly')`
125
+ - **Tool Call**: ONLY FOR EXISTING TASKS! `create_completed_task(description='Put out trash and recycling', parent_number='B', completion_date='YYYY-MM-DD', context='home', project='weekly')`
121
126
  - **Result**: Original task remains active for next Thursday
122
127
  - **User says**: "Done with standup" → Find `Standup meeting at 9:00AM +daily +weekdays @office duration:10m`
123
- - **Tool Call**: `create_completed_task(description='Standup meeting at 9:00AM', parent_number='XX', completion_date='YYYY-MM-DD', context='office', project='daily')`
128
+ - **Tool Call**: ONLY FOR EXISTING TASKS! `create_completed_task(description='Standup meeting at 9:00AM', parent_number='XX', completion_date='YYYY-MM-DD', context='office', project='daily')`
124
129
  - **Result**: Original task remains active for next weekday
125
130
 
126
131
  ### Task Suggestions
@@ -182,6 +182,10 @@ class TodoShell:
182
182
  """Archive completed tasks."""
183
183
  return self.execute(["todo.sh", "-f", "archive"])
184
184
 
185
+ def get_help(self) -> str:
186
+ """Get todo.sh help output."""
187
+ return self.execute(["todo.sh", "help"], suppress_color=False)
188
+
185
189
  def set_due_date(self, task_number: int, due_date: str) -> str:
186
190
  """
187
191
  Set or update due date for a task by intelligently rewriting it.
@@ -225,6 +225,23 @@ class CLI:
225
225
  self.console.print(table)
226
226
  self.console.print("Or just type your request naturally!", style="italic green")
227
227
 
228
+ def _print_todo_help(self) -> None:
229
+ """Print todo.sh help information."""
230
+ try:
231
+ # Get todo.sh help output
232
+ help_output = self.todo_shell.get_help()
233
+ formatted_output = TaskFormatter.format_task_list(help_output)
234
+ help_panel = PanelFormatter.create_task_panel(
235
+ formatted_output, title="📋 Todo.sh Help"
236
+ )
237
+ self.console.print(help_panel)
238
+ except Exception as e:
239
+ self.logger.error(f"Error getting todo.sh help: {e!s}")
240
+ error_msg = ResponseFormatter.format_error(
241
+ f"Failed to get todo.sh help: {e!s}"
242
+ )
243
+ self.console.print(error_msg)
244
+
228
245
  def _print_about(self) -> None:
229
246
  """Print about information in a formatted panel."""
230
247
  about_panel = PanelFormatter.create_about_panel()
@@ -280,6 +297,37 @@ class CLI:
280
297
  if not user_input:
281
298
  continue
282
299
 
300
+ # Handle todo.sh passthrough commands (starting with /)
301
+ if user_input.startswith("/"):
302
+ self.logger.debug(
303
+ f"Processing todo.sh passthrough command: {user_input}"
304
+ )
305
+ try:
306
+ # Remove the leading / and execute as todo.sh command
307
+ todo_command = user_input[1:].strip()
308
+ if not todo_command:
309
+ self.console.print(
310
+ ResponseFormatter.format_error("Empty todo.sh command")
311
+ )
312
+ continue
313
+
314
+ # Execute the todo.sh command directly
315
+ output = self.todo_shell.execute(
316
+ ["todo.sh", *todo_command.split()]
317
+ )
318
+ formatted_output = TaskFormatter.format_task_list(output)
319
+ task_panel = PanelFormatter.create_task_panel(
320
+ formatted_output, title="📋 Todo.sh Output"
321
+ )
322
+ self.console.print(task_panel)
323
+ except Exception as e:
324
+ self.logger.error(f"Error executing todo.sh command: {e!s}")
325
+ error_msg = ResponseFormatter.format_error(
326
+ f"Todo.sh command failed: {e!s}"
327
+ )
328
+ self.console.print(error_msg)
329
+ continue
330
+
283
331
  # Handle special commands
284
332
  if user_input.lower() == "clear":
285
333
  self.logger.info("User requested conversation clear")
@@ -302,6 +350,11 @@ class CLI:
302
350
  self._print_help()
303
351
  continue
304
352
 
353
+ if user_input.lower() == "todo-help":
354
+ self.logger.debug("User requested todo.sh help")
355
+ self._print_todo_help()
356
+ continue
357
+
305
358
  if user_input.lower() == "about":
306
359
  self.logger.debug("User requested about information")
307
360
  self._print_about()
@@ -357,6 +357,7 @@ class TableFormatter:
357
357
  ("clear", "Clear conversation history"),
358
358
  ("stats", "Show conversation statistics"),
359
359
  ("help", "Show this help message"),
360
+ ("todo-help", "Show todo.sh help"),
360
361
  ("about", "Show application information"),
361
362
  ("list", "List all tasks (no LLM interaction)"),
362
363
  ("done", "List completed tasks (no LLM interaction)"),
@@ -626,13 +626,14 @@ class ToolCallHandler:
626
626
  "name": "create_completed_task",
627
627
  "description": (
628
628
  "Create a task and immediately mark it as completed. "
629
- "USE CASE: Call this when user says they completed something on a specific date (e.g., 'I did the laundry today', 'I finished the report yesterday', 'I cleaned the garage last week') "
629
+ "USE CASE: WHEN NO MATCH IS FOUND! Call this when user says they completed something on a specific date (e.g., 'I did the laundry today', 'I finished the report yesterday', 'I cleaned the garage last week') "
630
630
  "and you have already researched existing tasks to determine no match exists. "
631
- "WORKFLOW: 1) Use list_tasks() to search for existing tasks, 2) Use list_completed_tasks() to verify it's not already done, "
632
- "3) If no match found, call this tool to create and complete the task in one operation. "
631
+ "WORKFLOW: 1) Use list_tasks() to search for existing tasks, "
632
+ "2) Use list_completed_tasks() to verify it's not already done, "
633
+ "3) If a match is found, use complete_task() to mark it complete, "
634
+ "4) If no match found, call this tool to create and complete the task in one operation. "
633
635
  "STRATEGIC CONTEXT: This is a convenience tool for the common pattern of 'I did X on [date]' - "
634
- "it creates a task with the specified completion date and immediately marks it complete. "
635
- "The LLM should handle the research and decision-making about whether to use this tool."
636
+ "when no task match is found, it creates a task with the specified completion date and immediately marks it complete. "
636
637
  ),
637
638
  "parameters": {
638
639
  "type": "object",
todo_agent/main.py CHANGED
@@ -12,7 +12,7 @@ from .interface.cli import CLI
12
12
  def main() -> None:
13
13
  """Main application entry point."""
14
14
  from ._version import __version__
15
-
15
+
16
16
  parser = argparse.ArgumentParser(
17
17
  description=f"Todo.sh LLM Agent - Natural language task management (v{__version__})",
18
18
  formatter_class=argparse.RawDescriptionHelpFormatter,
@@ -27,18 +27,20 @@ Examples:
27
27
  )
28
28
 
29
29
  parser.add_argument(
30
- "--version", "-v",
30
+ "--version",
31
+ "-v",
31
32
  action="version",
32
33
  version=f"%(prog)s {__version__}",
33
34
  help="Show version information and exit",
34
35
  )
35
-
36
+
36
37
  parser.add_argument(
37
- "--help", "-h",
38
+ "--help",
39
+ "-h",
38
40
  action="help",
39
41
  help="Show this help message and exit",
40
42
  )
41
-
43
+
42
44
  parser.add_argument(
43
45
  "command",
44
46
  nargs="?",
@@ -53,11 +55,28 @@ Examples:
53
55
  if args.command:
54
56
  # Single command mode
55
57
  # Handle special commands that don't need LLM processing
56
- if args.command.lower() in ["help", "about"]:
58
+ if args.command.lower() in ["help", "about", "todo-help"]:
57
59
  if args.command.lower() == "help":
58
60
  cli._print_help()
59
61
  elif args.command.lower() == "about":
60
62
  cli._print_about()
63
+ elif args.command.lower() == "todo-help":
64
+ cli._print_todo_help()
65
+ elif args.command.startswith("/"):
66
+ # Handle todo.sh passthrough commands
67
+ try:
68
+ # Remove the leading / and execute as todo.sh command
69
+ todo_command = args.command[1:].strip()
70
+ if not todo_command:
71
+ print("Error: Empty todo.sh command")
72
+ sys.exit(1)
73
+
74
+ # Execute the todo.sh command directly
75
+ output = cli.todo_shell.execute(["todo.sh", *todo_command.split()])
76
+ print(output)
77
+ except Exception as e:
78
+ print(f"Error: Todo.sh command failed: {e}")
79
+ sys.exit(1)
61
80
  else:
62
81
  # Process through LLM
63
82
  response = cli.run_single_request(args.command)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: todo-agent
3
- Version: 0.3.5
3
+ Version: 0.3.6
4
4
  Summary: A natural language interface for todo.sh task management
5
5
  Author: codeprimate
6
6
  Maintainer: codeprimate
@@ -1,6 +1,6 @@
1
1
  todo_agent/__init__.py,sha256=RUowhd14r3tqB_7rl83unGV8oBjra3UOIl7jix-33fk,254
2
- todo_agent/_version.py,sha256=UAb2Toi6SAdScDfq1uKRRv5QpMUuRtJqqwNxTMGe5Q4,704
3
- todo_agent/main.py,sha256=DfcZuTsHkmpm6kw0coB0-B677K3hyRwutWIuO4noQ3w,2026
2
+ todo_agent/_version.py,sha256=DPG4bRRG7SLMPQyCzFx7koj75iQndn-UI-ENmNbYVCQ,704
3
+ todo_agent/main.py,sha256=3kFRat2mG_57z1JR6UzsWDGLZ8G8EYuw9h9F8Xpo_mc,2857
4
4
  todo_agent/core/__init__.py,sha256=QAZ4it63pXv5-DxtNcuSAmg7ZnCY5ackI5yycvKHr9I,365
5
5
  todo_agent/core/conversation_manager.py,sha256=9aAWogswZe9Cs7wKT47RG-cLh1LQ5D9RbhUHJVUyTS8,13549
6
6
  todo_agent/core/exceptions.py,sha256=ilVL5hyPHGYQXsLm0pYivMbhbamupG77r8TbiQr2tAU,2034
@@ -14,17 +14,17 @@ todo_agent/infrastructure/llm_client_factory.py,sha256=-tktnVOIF7B45WR7AuLoi7MKn
14
14
  todo_agent/infrastructure/logger.py,sha256=2ykG_0lyzmEGxDF6ZRl1qiTUGDuFeQgzv4Na6vRmXcM,4110
15
15
  todo_agent/infrastructure/ollama_client.py,sha256=V_zAeBjIEzB8PZXyzFeiLMLA5qf3y4WV2_6Vqxn1ujc,5629
16
16
  todo_agent/infrastructure/openrouter_client.py,sha256=0pxIKvHItwVijFz8l4loOeCa4HUpMvTYROcwYJh3iyI,6748
17
- todo_agent/infrastructure/todo_shell.py,sha256=2iPPhsLsTcjVx8Wv2mJJBu11kLJOK9Tk5KBAyVQ3Yjs,20596
17
+ todo_agent/infrastructure/todo_shell.py,sha256=ft7wKWykMKEHD1ZD_k1R8a_Zje7vLnG1yD8770TNVBQ,20738
18
18
  todo_agent/infrastructure/token_counter.py,sha256=PCKheOVJbp1s89yhh_i6iKgURMt9mVoYkwjQJCc2xCE,4958
19
- todo_agent/infrastructure/prompts/system_prompt.txt,sha256=ZHGYgd7lCuWaSX5io3IYWFhdjcGbdqKXf2uhEWdbzQ8,12380
19
+ todo_agent/infrastructure/prompts/system_prompt.txt,sha256=DwvuXoSZY5-lRk1WcinU57PIqGH-omy1oC5P5FBEOog,12670
20
20
  todo_agent/interface/__init__.py,sha256=vDD3rQu4qDkpvVwGVtkDzE1M4IiSHYzTif4GbYSFWaI,457
21
- todo_agent/interface/cli.py,sha256=Ikh5AYoOZnNUVXzHjfv2bsE33yK3VhCdzza83HOzFp8,16460
22
- todo_agent/interface/formatters.py,sha256=a9PW-5DbY8K5QYZjBXFZSdzlCmy263kwBI9nXgP8LXI,20081
21
+ todo_agent/interface/cli.py,sha256=opVubVwLlcU5ImUyGlS21Es49xuzNjkivPiEsxRiLj0,18922
22
+ todo_agent/interface/formatters.py,sha256=Kcm8-E9OkvjnqaUvQuwrYKqUmknduAUP5z0A6rOaeG8,20129
23
23
  todo_agent/interface/progress.py,sha256=EpPa20Hrnjv_TBIp0tzViVciThqsOvAHuYO4v2rc8eI,1751
24
- todo_agent/interface/tools.py,sha256=Q6h2zpe1yRUwJOZZFArjXgBN6WPDI56CDQQJcdF1I5M,54448
25
- todo_agent-0.3.5.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
26
- todo_agent-0.3.5.dist-info/METADATA,sha256=eP-pVo55MQvK1G9b9vaoOhir6fQnjOr4CD-D8n29Ha0,10056
27
- todo_agent-0.3.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
28
- todo_agent-0.3.5.dist-info/entry_points.txt,sha256=4W7LrCib6AXP5IZDwWRht8S5gutLu5oNfTJHGbt4oHs,52
29
- todo_agent-0.3.5.dist-info/top_level.txt,sha256=a65mlPIhPZHuq2bRIi_sCMAIJsUddvXt171OBF6r6co,11
30
- todo_agent-0.3.5.dist-info/RECORD,,
24
+ todo_agent/interface/tools.py,sha256=U3LF7VZy27n2aLbxDD7uIEt8OPeXgXCz0I83ins4WdM,54507
25
+ todo_agent-0.3.6.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
26
+ todo_agent-0.3.6.dist-info/METADATA,sha256=iqTh--OWn4ocfSIVeK3F35RC7SoFc4nASidx8K67Bos,10056
27
+ todo_agent-0.3.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
28
+ todo_agent-0.3.6.dist-info/entry_points.txt,sha256=4W7LrCib6AXP5IZDwWRht8S5gutLu5oNfTJHGbt4oHs,52
29
+ todo_agent-0.3.6.dist-info/top_level.txt,sha256=a65mlPIhPZHuq2bRIi_sCMAIJsUddvXt171OBF6r6co,11
30
+ todo_agent-0.3.6.dist-info/RECORD,,