deepagents-cli 0.0.4__tar.gz → 0.0.6__tar.gz

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.

Potentially problematic release.


This version of deepagents-cli might be problematic. Click here for more details.

Files changed (27) hide show
  1. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/PKG-INFO +2 -2
  2. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/deepagents_cli/agent.py +39 -28
  3. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/deepagents_cli/commands.py +3 -0
  4. deepagents_cli-0.0.6/deepagents_cli/default_agent_prompt.md +110 -0
  5. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/deepagents_cli/main.py +11 -2
  6. deepagents_cli-0.0.6/deepagents_cli/token_utils.py +63 -0
  7. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/deepagents_cli/ui.py +39 -5
  8. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/deepagents_cli.egg-info/PKG-INFO +2 -2
  9. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/deepagents_cli.egg-info/SOURCES.txt +2 -0
  10. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/deepagents_cli.egg-info/requires.txt +1 -1
  11. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/pyproject.toml +5 -2
  12. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/README.md +0 -0
  13. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/deepagents_cli/__init__.py +0 -0
  14. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/deepagents_cli/__main__.py +0 -0
  15. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/deepagents_cli/cli.py +0 -0
  16. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/deepagents_cli/config.py +0 -0
  17. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/deepagents_cli/execution.py +0 -0
  18. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/deepagents_cli/file_ops.py +0 -0
  19. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/deepagents_cli/input.py +0 -0
  20. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/deepagents_cli/py.typed +0 -0
  21. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/deepagents_cli/tools.py +0 -0
  22. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/deepagents_cli.egg-info/dependency_links.txt +0 -0
  23. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/deepagents_cli.egg-info/entry_points.txt +0 -0
  24. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/deepagents_cli.egg-info/top_level.txt +0 -0
  25. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/setup.cfg +0 -0
  26. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/tests/test_file_ops.py +0 -0
  27. {deepagents_cli-0.0.4 → deepagents_cli-0.0.6}/tests/test_placeholder.py +0 -0
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepagents-cli
3
- Version: 0.0.4
3
+ Version: 0.0.6
4
4
  Summary: Deepagents CLI
5
5
  License: MIT
6
6
  Requires-Python: <4.0,>=3.11
7
7
  Description-Content-Type: text/markdown
8
- Requires-Dist: deepagents==0.2.2
8
+ Requires-Dist: deepagents==0.2.3
9
9
  Requires-Dist: requests
10
10
  Requires-Dist: rich>=13.0.0
11
11
  Requires-Dist: prompt-toolkit>=3.0.52
@@ -79,35 +79,13 @@ def reset_agent(agent_name: str, source_agent: str = None):
79
79
  console.print(f"Location: {agent_dir}\n", style=COLORS["dim"])
80
80
 
81
81
 
82
- def create_agent_with_config(model, assistant_id: str, tools: list):
83
- """Create and configure an agent with the specified model and tools."""
84
- shell_middleware = ResumableShellToolMiddleware(
85
- workspace_root=os.getcwd(), execution_policy=HostExecutionPolicy()
86
- )
82
+ def get_system_prompt() -> str:
83
+ """Get the base system prompt for the agent.
87
84
 
88
- # For long-term memory, point to ~/.deepagents/AGENT_NAME/ with /memories/ prefix
89
- agent_dir = Path.home() / ".deepagents" / assistant_id
90
- agent_dir.mkdir(parents=True, exist_ok=True)
91
- agent_md = agent_dir / "agent.md"
92
- if not agent_md.exists():
93
- source_content = get_default_coding_instructions()
94
- agent_md.write_text(source_content)
95
-
96
- # Long-term backend - rooted at agent directory
97
- # This handles both /memories/ files and /agent.md
98
- long_term_backend = FilesystemBackend(root_dir=agent_dir, virtual_mode=True)
99
-
100
- # Composite backend: current working directory for default, agent directory for /memories/
101
- backend = CompositeBackend(
102
- default=FilesystemBackend(), routes={"/memories/": long_term_backend}
103
- )
104
-
105
- # Use the same backend for agent memory middleware
106
- agent_middleware = [
107
- AgentMemoryMiddleware(backend=long_term_backend, memory_path="/memories/"),
108
- shell_middleware,
109
- ]
110
- system_prompt = f"""### Current Working Directory
85
+ Returns:
86
+ The system prompt string (without agent.md content)
87
+ """
88
+ return f"""### Current Working Directory
111
89
 
112
90
  The filesystem backend is currently operating in: `{Path.cwd()}`
113
91
 
@@ -159,6 +137,39 @@ When using the write_todos tool:
159
137
 
160
138
  The todo list is a planning tool - use it judiciously to avoid overwhelming the user with excessive task tracking."""
161
139
 
140
+
141
+ def create_agent_with_config(model, assistant_id: str, tools: list):
142
+ """Create and configure an agent with the specified model and tools."""
143
+ shell_middleware = ResumableShellToolMiddleware(
144
+ workspace_root=os.getcwd(), execution_policy=HostExecutionPolicy()
145
+ )
146
+
147
+ # For long-term memory, point to ~/.deepagents/AGENT_NAME/ with /memories/ prefix
148
+ agent_dir = Path.home() / ".deepagents" / assistant_id
149
+ agent_dir.mkdir(parents=True, exist_ok=True)
150
+ agent_md = agent_dir / "agent.md"
151
+ if not agent_md.exists():
152
+ source_content = get_default_coding_instructions()
153
+ agent_md.write_text(source_content)
154
+
155
+ # Long-term backend - rooted at agent directory
156
+ # This handles both /memories/ files and /agent.md
157
+ long_term_backend = FilesystemBackend(root_dir=agent_dir, virtual_mode=True)
158
+
159
+ # Composite backend: current working directory for default, agent directory for /memories/
160
+ backend = CompositeBackend(
161
+ default=FilesystemBackend(), routes={"/memories/": long_term_backend}
162
+ )
163
+
164
+ # Use the same backend for agent memory middleware
165
+ agent_middleware = [
166
+ AgentMemoryMiddleware(backend=long_term_backend, memory_path="/memories/"),
167
+ shell_middleware,
168
+ ]
169
+
170
+ # Get the system prompt
171
+ system_prompt = get_system_prompt()
172
+
162
173
  # Helper functions for formatting tool descriptions in HITL prompts
163
174
  def format_write_file_description(tool_call: dict) -> str:
164
175
  """Format write_file tool call for approval prompt."""
@@ -20,6 +20,9 @@ def handle_command(command: str, agent, token_tracker: TokenTracker) -> str | bo
20
20
  # Reset agent conversation state
21
21
  agent.checkpointer = InMemorySaver()
22
22
 
23
+ # Reset token tracking to baseline
24
+ token_tracker.reset()
25
+
23
26
  # Clear screen and show fresh UI
24
27
  console.clear()
25
28
  console.print(DEEP_AGENTS_ASCII, style=f"bold {COLORS['primary']}")
@@ -0,0 +1,110 @@
1
+ You are an AI assistant that helps users with various tasks including coding, research, and analysis.
2
+
3
+ # Core Role
4
+ Your core role and behavior may be updated based on user feedback and instructions. When a user tells you how you should behave or what your role should be, update this memory file immediately to reflect that guidance.
5
+
6
+ ## Memory-First Protocol
7
+ You have access to a persistent memory system. ALWAYS follow this protocol:
8
+
9
+ **At session start:**
10
+ - Check `ls /memories/` to see what knowledge you have stored
11
+ - If your role description references specific topics, check /memories/ for relevant guides
12
+
13
+ **Before answering questions:**
14
+ - If asked "what do you know about X?" or "how do I do Y?" → Check `ls /memories/` FIRST
15
+ - If relevant memory files exist → Read them and base your answer on saved knowledge
16
+ - Prefer saved knowledge over general knowledge when available
17
+
18
+ **When learning new information:**
19
+ - If user teaches you something or asks you to remember → Save to `/memories/[topic].md`
20
+ - Use descriptive filenames: `/memories/deep-agents-guide.md` not `/memories/notes.md`
21
+ - After saving, verify by reading back the key points
22
+
23
+ **Important:** Your memories persist across sessions. Information stored in /memories/ is more reliable than general knowledge for topics you've specifically studied.
24
+
25
+ # Tone and Style
26
+ Be concise and direct. Answer in fewer than 4 lines unless the user asks for detail.
27
+ After working on a file, just stop - don't explain what you did unless asked.
28
+ Avoid unnecessary introductions or conclusions.
29
+
30
+ When you run non-trivial bash commands, briefly explain what they do.
31
+
32
+ ## Proactiveness
33
+ Take action when asked, but don't surprise users with unrequested actions.
34
+ If asked how to approach something, answer first before taking action.
35
+
36
+ ## Following Conventions
37
+ - Check existing code for libraries and frameworks before assuming availability
38
+ - Mimic existing code style, naming conventions, and patterns
39
+ - Never add comments unless asked
40
+
41
+ ## Task Management
42
+ Use write_todos for complex multi-step tasks (3+ steps). Mark tasks in_progress before starting, completed immediately after finishing.
43
+ For simple 1-2 step tasks, just do them without todos.
44
+
45
+ ## File Reading Best Practices
46
+
47
+ **CRITICAL**: When exploring codebases or reading multiple files, ALWAYS use pagination to prevent context overflow.
48
+
49
+ **Pattern for codebase exploration:**
50
+ 1. First scan: `read_file(path, limit=100)` - See file structure and key sections
51
+ 2. Targeted read: `read_file(path, offset=100, limit=200)` - Read specific sections if needed
52
+ 3. Full read: Only use `read_file(path)` without limit when necessary for editing
53
+
54
+ **When to paginate:**
55
+ - Reading any file >500 lines
56
+ - Exploring unfamiliar codebases (always start with limit=100)
57
+ - Reading multiple files in sequence
58
+ - Any research or investigation task
59
+
60
+ **When full read is OK:**
61
+ - Small files (<500 lines)
62
+ - Files you need to edit immediately after reading
63
+ - After confirming file size with first scan
64
+
65
+ **Example workflow:**
66
+ ```
67
+ Bad: read_file(/src/large_module.py) # Floods context with 2000+ lines
68
+ Good: read_file(/src/large_module.py, limit=100) # Scan structure first
69
+ read_file(/src/large_module.py, offset=100, limit=100) # Read relevant section
70
+ ```
71
+
72
+ ## Working with Subagents (task tool)
73
+ When delegating to subagents:
74
+ - **Use filesystem for large I/O**: If input instructions are large (>500 words) OR expected output is large, communicate via files
75
+ - Write input context/instructions to a file, tell subagent to read it
76
+ - Ask subagent to write their output to a file, then read it after they return
77
+ - This prevents token bloat and keeps context manageable in both directions
78
+ - **Parallelize independent work**: When tasks are independent, spawn parallel subagents to work simultaneously
79
+ - **Clear specifications**: Tell subagent exactly what format/structure you need in their response or output file
80
+ - **Main agent synthesizes**: Subagents gather/execute, main agent integrates results into final deliverable
81
+
82
+ ## Tools
83
+
84
+ ### execute_bash
85
+ Execute shell commands. Always quote paths with spaces.
86
+ Examples: `pytest /foo/bar/tests` (good), `cd /foo/bar && pytest tests` (bad)
87
+
88
+ ### File Tools
89
+ - read_file: Read file contents (use absolute paths)
90
+ - edit_file: Replace exact strings in files (must read first, provide unique old_string)
91
+ - write_file: Create or overwrite files
92
+ - ls: List directory contents
93
+ - glob: Find files by pattern (e.g., "**/*.py")
94
+ - grep: Search file contents
95
+
96
+ Always use absolute paths starting with /.
97
+
98
+ ### web_search
99
+ Search for documentation, error solutions, and code examples.
100
+
101
+ ### http_request
102
+ Make HTTP requests to APIs (GET, POST, etc.).
103
+
104
+ ## Code References
105
+ When referencing code, use format: `file_path:line_number`
106
+
107
+ ## Documentation
108
+ - Do NOT create excessive markdown summary/documentation files after completing work
109
+ - Focus on the work itself, not documenting what you did
110
+ - Only create documentation when explicitly requested
@@ -93,7 +93,7 @@ def parse_args():
93
93
  return parser.parse_args()
94
94
 
95
95
 
96
- async def simple_cli(agent, assistant_id: str | None, session_state):
96
+ async def simple_cli(agent, assistant_id: str | None, session_state, baseline_tokens: int = 0):
97
97
  """Main CLI loop."""
98
98
  console.clear()
99
99
  console.print(DEEP_AGENTS_ASCII, style=f"bold {COLORS['primary']}")
@@ -131,6 +131,7 @@ async def simple_cli(agent, assistant_id: str | None, session_state):
131
131
  # Create prompt session and token tracker
132
132
  session = create_prompt_session(assistant_id, session_state)
133
133
  token_tracker = TokenTracker()
134
+ token_tracker.set_baseline(baseline_tokens)
134
135
 
135
136
  while True:
136
137
  try:
@@ -181,8 +182,16 @@ async def main(assistant_id: str, session_state):
181
182
 
182
183
  agent = create_agent_with_config(model, assistant_id, tools)
183
184
 
185
+ # Calculate baseline token count for accurate token tracking
186
+ from .agent import get_system_prompt
187
+ from .token_utils import calculate_baseline_tokens
188
+
189
+ agent_dir = Path.home() / ".deepagents" / assistant_id
190
+ system_prompt = get_system_prompt()
191
+ baseline_tokens = calculate_baseline_tokens(model, agent_dir, system_prompt)
192
+
184
193
  try:
185
- await simple_cli(agent, assistant_id, session_state)
194
+ await simple_cli(agent, assistant_id, session_state, baseline_tokens)
186
195
  except Exception as e:
187
196
  console.print(f"\n[bold red]❌ Error:[/bold red] {e}\n")
188
197
 
@@ -0,0 +1,63 @@
1
+ """Utilities for accurate token counting using LangChain models."""
2
+
3
+ from pathlib import Path
4
+
5
+ from langchain_core.messages import SystemMessage
6
+
7
+ from .config import console
8
+
9
+
10
+ def calculate_baseline_tokens(model, agent_dir: Path, system_prompt: str) -> int:
11
+ """Calculate baseline context tokens using the model's official tokenizer.
12
+
13
+ This uses the model's get_num_tokens_from_messages() method to get
14
+ accurate token counts for the initial context (system prompt + agent.md).
15
+
16
+ Note: Tool definitions cannot be accurately counted before the first API call
17
+ due to LangChain limitations. They will be included in the total after the
18
+ first message is sent (~5,000 tokens).
19
+
20
+ Args:
21
+ model: LangChain model instance (ChatAnthropic or ChatOpenAI)
22
+ agent_dir: Path to agent directory containing agent.md
23
+ system_prompt: The base system prompt string
24
+
25
+ Returns:
26
+ Token count for system prompt + agent.md (tools not included)
27
+ """
28
+ # Load agent.md content
29
+ agent_md_path = agent_dir / "agent.md"
30
+ agent_memory = ""
31
+ if agent_md_path.exists():
32
+ agent_memory = agent_md_path.read_text()
33
+
34
+ # Build the complete system prompt as it will be sent
35
+ # This mimics what AgentMemoryMiddleware.wrap_model_call() does
36
+ memory_section = f"<agent_memory>\n{agent_memory}\n</agent_memory>"
37
+
38
+ # Get the long-term memory system prompt
39
+ memory_system_prompt = get_memory_system_prompt()
40
+
41
+ # Combine all parts in the same order as the middleware
42
+ full_system_prompt = memory_section + "\n\n" + system_prompt + "\n\n" + memory_system_prompt
43
+
44
+ # Count tokens using the model's official method
45
+ messages = [SystemMessage(content=full_system_prompt)]
46
+
47
+ try:
48
+ # Note: tools parameter is not supported by LangChain's token counting
49
+ # Tool tokens will be included in the API response after first message
50
+ token_count = model.get_num_tokens_from_messages(messages)
51
+ return token_count
52
+ except Exception as e:
53
+ # Fallback if token counting fails
54
+ console.print(f"[yellow]Warning: Could not calculate baseline tokens: {e}[/yellow]")
55
+ return 0
56
+
57
+
58
+ def get_memory_system_prompt() -> str:
59
+ """Get the long-term memory system prompt text."""
60
+ # Import from agent_memory middleware
61
+ from deepagents.middleware.agent_memory import LONGTERM_MEMORY_SYSTEM_PROMPT
62
+
63
+ return LONGTERM_MEMORY_SYSTEM_PROMPT.format(memory_path="/memories/")
@@ -165,7 +165,22 @@ class TokenTracker:
165
165
  """Track token usage across the conversation."""
166
166
 
167
167
  def __init__(self):
168
- self.current_context = 0
168
+ self.baseline_context = 0 # Baseline system context (system + agent.md + tools)
169
+ self.current_context = 0 # Total context including messages
170
+ self.last_output = 0
171
+
172
+ def set_baseline(self, tokens: int):
173
+ """Set the baseline context token count.
174
+
175
+ Args:
176
+ tokens: The baseline token count (system prompt + agent.md + tools)
177
+ """
178
+ self.baseline_context = tokens
179
+ self.current_context = tokens
180
+
181
+ def reset(self):
182
+ """Reset to baseline (for /clear command)."""
183
+ self.current_context = self.baseline_context
169
184
  self.last_output = 0
170
185
 
171
186
  def add(self, input_tokens: int, output_tokens: int):
@@ -183,12 +198,31 @@ class TokenTracker:
183
198
 
184
199
  def display_session(self):
185
200
  """Display current context size."""
186
- if self.current_context:
187
- console.print("\n[bold]Token Usage:[/bold]", style=COLORS["primary"])
201
+ console.print("\n[bold]Token Usage:[/bold]", style=COLORS["primary"])
202
+
203
+ # Check if we've had any actual API calls yet (current > baseline means we have conversation)
204
+ has_conversation = self.current_context > self.baseline_context
205
+
206
+ if self.baseline_context > 0:
207
+ console.print(
208
+ f" Baseline: {self.baseline_context:,} tokens [dim](system + agent.md)[/dim]",
209
+ style=COLORS["dim"],
210
+ )
211
+
212
+ if not has_conversation:
213
+ # Before first message - warn that tools aren't counted yet
214
+ console.print(
215
+ " [dim]Note: Tool definitions (~5k tokens) included after first message[/dim]"
216
+ )
217
+
218
+ if has_conversation:
219
+ tools_and_conversation = self.current_context - self.baseline_context
188
220
  console.print(
189
- f" Current context: {self.current_context:,} tokens", style=COLORS["dim"]
221
+ f" Tools + conversation: {tools_and_conversation:,} tokens", style=COLORS["dim"]
190
222
  )
191
- console.print()
223
+
224
+ console.print(f" Total: {self.current_context:,} tokens", style="bold " + COLORS["dim"])
225
+ console.print()
192
226
 
193
227
 
194
228
  def render_todo_list(todos: list[dict]) -> None:
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepagents-cli
3
- Version: 0.0.4
3
+ Version: 0.0.6
4
4
  Summary: Deepagents CLI
5
5
  License: MIT
6
6
  Requires-Python: <4.0,>=3.11
7
7
  Description-Content-Type: text/markdown
8
- Requires-Dist: deepagents==0.2.2
8
+ Requires-Dist: deepagents==0.2.3
9
9
  Requires-Dist: requests
10
10
  Requires-Dist: rich>=13.0.0
11
11
  Requires-Dist: prompt-toolkit>=3.0.52
@@ -6,11 +6,13 @@ deepagents_cli/agent.py
6
6
  deepagents_cli/cli.py
7
7
  deepagents_cli/commands.py
8
8
  deepagents_cli/config.py
9
+ deepagents_cli/default_agent_prompt.md
9
10
  deepagents_cli/execution.py
10
11
  deepagents_cli/file_ops.py
11
12
  deepagents_cli/input.py
12
13
  deepagents_cli/main.py
13
14
  deepagents_cli/py.typed
15
+ deepagents_cli/token_utils.py
14
16
  deepagents_cli/tools.py
15
17
  deepagents_cli/ui.py
16
18
  deepagents_cli.egg-info/PKG-INFO
@@ -1,4 +1,4 @@
1
- deepagents==0.2.2
1
+ deepagents==0.2.3
2
2
  requests
3
3
  rich>=13.0.0
4
4
  prompt-toolkit>=3.0.52
@@ -1,12 +1,12 @@
1
1
  [project]
2
2
  name = "deepagents-cli"
3
- version = "0.0.4"
3
+ version = "0.0.6"
4
4
  description = "Deepagents CLI"
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
7
7
  requires-python = ">=3.11,<4.0"
8
8
  dependencies = [
9
- "deepagents==0.2.2",
9
+ "deepagents==0.2.3",
10
10
  "requests",
11
11
  "rich>=13.0.0",
12
12
  "prompt-toolkit>=3.0.52",
@@ -54,6 +54,9 @@ lint = [
54
54
  requires = ["setuptools>=73.0.0", "wheel"]
55
55
  build-backend = "setuptools.build_meta"
56
56
 
57
+ [tool.setuptools.package-data]
58
+ deepagents_cli = ["default_agent_prompt.md"]
59
+
57
60
  [tool.ruff]
58
61
  line-length = 100
59
62
  exclude = []
File without changes
File without changes