deepagents-cli 0.0.4__tar.gz → 0.0.5__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 (26) hide show
  1. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/PKG-INFO +2 -2
  2. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/deepagents_cli/agent.py +39 -28
  3. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/deepagents_cli/commands.py +3 -0
  4. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/deepagents_cli/main.py +11 -2
  5. deepagents_cli-0.0.5/deepagents_cli/token_utils.py +63 -0
  6. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/deepagents_cli/ui.py +39 -5
  7. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/deepagents_cli.egg-info/PKG-INFO +2 -2
  8. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/deepagents_cli.egg-info/SOURCES.txt +1 -0
  9. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/deepagents_cli.egg-info/requires.txt +1 -1
  10. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/pyproject.toml +2 -2
  11. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/README.md +0 -0
  12. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/deepagents_cli/__init__.py +0 -0
  13. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/deepagents_cli/__main__.py +0 -0
  14. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/deepagents_cli/cli.py +0 -0
  15. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/deepagents_cli/config.py +0 -0
  16. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/deepagents_cli/execution.py +0 -0
  17. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/deepagents_cli/file_ops.py +0 -0
  18. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/deepagents_cli/input.py +0 -0
  19. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/deepagents_cli/py.typed +0 -0
  20. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/deepagents_cli/tools.py +0 -0
  21. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/deepagents_cli.egg-info/dependency_links.txt +0 -0
  22. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/deepagents_cli.egg-info/entry_points.txt +0 -0
  23. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/deepagents_cli.egg-info/top_level.txt +0 -0
  24. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/setup.cfg +0 -0
  25. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/tests/test_file_ops.py +0 -0
  26. {deepagents_cli-0.0.4 → deepagents_cli-0.0.5}/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.5
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']}")
@@ -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.5
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
@@ -11,6 +11,7 @@ deepagents_cli/file_ops.py
11
11
  deepagents_cli/input.py
12
12
  deepagents_cli/main.py
13
13
  deepagents_cli/py.typed
14
+ deepagents_cli/token_utils.py
14
15
  deepagents_cli/tools.py
15
16
  deepagents_cli/ui.py
16
17
  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.5"
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",
File without changes
File without changes