code-puppy 0.0.72__py3-none-any.whl → 0.0.74__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.
- code_puppy/agent.py +3 -1
- code_puppy/command_line/meta_command_handler.py +11 -6
- code_puppy/command_line/motd.py +1 -1
- code_puppy/config.py +2 -0
- code_puppy/main.py +6 -5
- code_puppy/tools/file_modifications.py +1 -1
- code_puppy/tools/ts_code_map.py +10 -2
- {code_puppy-0.0.72.dist-info → code_puppy-0.0.74.dist-info}/METADATA +2 -2
- {code_puppy-0.0.72.dist-info → code_puppy-0.0.74.dist-info}/RECORD +13 -13
- {code_puppy-0.0.72.data → code_puppy-0.0.74.data}/data/code_puppy/models.json +0 -0
- {code_puppy-0.0.72.dist-info → code_puppy-0.0.74.dist-info}/WHEEL +0 -0
- {code_puppy-0.0.72.dist-info → code_puppy-0.0.74.dist-info}/entry_points.txt +0 -0
- {code_puppy-0.0.72.dist-info → code_puppy-0.0.74.dist-info}/licenses/LICENSE +0 -0
code_puppy/agent.py
CHANGED
|
@@ -67,6 +67,7 @@ def session_memory():
|
|
|
67
67
|
|
|
68
68
|
def _load_mcp_servers():
|
|
69
69
|
from code_puppy.config import load_mcp_server_configs
|
|
70
|
+
|
|
70
71
|
configs = load_mcp_server_configs()
|
|
71
72
|
servers = []
|
|
72
73
|
for name, conf in configs.items():
|
|
@@ -76,6 +77,7 @@ def _load_mcp_servers():
|
|
|
76
77
|
servers.append(MCPServerSSE(url))
|
|
77
78
|
return servers
|
|
78
79
|
|
|
80
|
+
|
|
79
81
|
def reload_code_generation_agent():
|
|
80
82
|
"""Force-reload the agent, usually after a model change."""
|
|
81
83
|
global _code_generation_agent, _LAST_MODEL_NAME
|
|
@@ -104,7 +106,7 @@ def reload_code_generation_agent():
|
|
|
104
106
|
instructions=instructions,
|
|
105
107
|
output_type=AgentResponse,
|
|
106
108
|
retries=3,
|
|
107
|
-
mcp_servers=mcp_servers
|
|
109
|
+
mcp_servers=mcp_servers,
|
|
108
110
|
)
|
|
109
111
|
register_all_tools(agent)
|
|
110
112
|
_code_generation_agent = agent
|
|
@@ -8,6 +8,7 @@ from code_puppy.command_line.model_picker_completion import (
|
|
|
8
8
|
)
|
|
9
9
|
from code_puppy.config import get_config_keys
|
|
10
10
|
from code_puppy.command_line.utils import make_directory_table
|
|
11
|
+
from code_puppy.command_line.motd import print_motd
|
|
11
12
|
|
|
12
13
|
META_COMMANDS_HELP = """
|
|
13
14
|
[bold magenta]Meta Commands Help[/bold magenta]
|
|
@@ -22,8 +23,6 @@ META_COMMANDS_HELP = """
|
|
|
22
23
|
"""
|
|
23
24
|
|
|
24
25
|
|
|
25
|
-
from code_puppy.command_line.motd import print_motd
|
|
26
|
-
|
|
27
26
|
def handle_meta_command(command: str, console: Console) -> bool:
|
|
28
27
|
"""
|
|
29
28
|
Handle meta/config commands prefixed with '~'.
|
|
@@ -75,20 +74,26 @@ def handle_meta_command(command: str, console: Console) -> bool:
|
|
|
75
74
|
|
|
76
75
|
if command.strip().startswith("~show"):
|
|
77
76
|
from code_puppy.command_line.model_picker_completion import get_active_model
|
|
78
|
-
from code_puppy.config import
|
|
77
|
+
from code_puppy.config import (
|
|
78
|
+
get_owner_name,
|
|
79
|
+
get_puppy_name,
|
|
80
|
+
get_yolo_mode,
|
|
81
|
+
get_message_history_limit,
|
|
82
|
+
)
|
|
83
|
+
|
|
79
84
|
puppy_name = get_puppy_name()
|
|
80
85
|
owner_name = get_owner_name()
|
|
81
86
|
model = get_active_model()
|
|
82
87
|
yolo_mode = get_yolo_mode()
|
|
83
88
|
msg_limit = get_message_history_limit()
|
|
84
|
-
console.print(f
|
|
89
|
+
console.print(f"""[bold magenta]🐶 Puppy Status[/bold magenta]
|
|
85
90
|
|
|
86
91
|
[bold]puppy_name:[/bold] [cyan]{puppy_name}[/cyan]
|
|
87
92
|
[bold]owner_name:[/bold] [cyan]{owner_name}[/cyan]
|
|
88
93
|
[bold]model:[/bold] [green]{model}[/green]
|
|
89
|
-
[bold]YOLO_MODE:[/bold] {
|
|
94
|
+
[bold]YOLO_MODE:[/bold] {"[red]ON[/red]" if yolo_mode else "[yellow]off[/yellow]"}
|
|
90
95
|
[bold]message_history_limit:[/bold] Keeping last [cyan]{msg_limit}[/cyan] messages in context
|
|
91
|
-
|
|
96
|
+
""")
|
|
92
97
|
return True
|
|
93
98
|
|
|
94
99
|
if command.startswith("~set"):
|
code_puppy/command_line/motd.py
CHANGED
code_puppy/config.py
CHANGED
|
@@ -72,6 +72,7 @@ def get_message_history_limit():
|
|
|
72
72
|
except (ValueError, TypeError):
|
|
73
73
|
return 40
|
|
74
74
|
|
|
75
|
+
|
|
75
76
|
# --- CONFIG SETTER STARTS HERE ---
|
|
76
77
|
def get_config_keys():
|
|
77
78
|
"""
|
|
@@ -117,6 +118,7 @@ def load_mcp_server_configs():
|
|
|
117
118
|
print(f"Failed to load MCP servers - {str(e)}")
|
|
118
119
|
return {}
|
|
119
120
|
|
|
121
|
+
|
|
120
122
|
def get_model_name():
|
|
121
123
|
"""Returns the last used model name stored in config, or None if unset."""
|
|
122
124
|
return get_value("model") or "gpt-4.1"
|
code_puppy/main.py
CHANGED
|
@@ -4,7 +4,6 @@ import os
|
|
|
4
4
|
import sys
|
|
5
5
|
|
|
6
6
|
from dotenv import load_dotenv
|
|
7
|
-
from pydantic_ai.messages import ToolCallPart, ToolReturnPart
|
|
8
7
|
from rich.console import Console, ConsoleOptions, RenderResult
|
|
9
8
|
from rich.markdown import CodeBlock, Markdown
|
|
10
9
|
from rich.syntax import Syntax
|
|
@@ -116,9 +115,10 @@ async def interactive_mode(history_file_path: str) -> None:
|
|
|
116
115
|
# Show MOTD if user hasn't seen it after an update
|
|
117
116
|
try:
|
|
118
117
|
from code_puppy.command_line.motd import print_motd
|
|
118
|
+
|
|
119
119
|
print_motd(console, force=False)
|
|
120
120
|
except Exception as e:
|
|
121
|
-
console.print(f
|
|
121
|
+
console.print(f"[yellow]MOTD error: {e}[/yellow]")
|
|
122
122
|
|
|
123
123
|
# Check if prompt_toolkit is installed
|
|
124
124
|
try:
|
|
@@ -235,19 +235,21 @@ async def interactive_mode(history_file_path: str) -> None:
|
|
|
235
235
|
]
|
|
236
236
|
# 2. Append to existing history and keep only the most recent set by config
|
|
237
237
|
from code_puppy.config import get_message_history_limit
|
|
238
|
+
|
|
238
239
|
message_history.extend(filtered)
|
|
239
240
|
|
|
240
241
|
# --- BEGIN GROUP-AWARE TRUNCATION LOGIC ---
|
|
241
242
|
limit = get_message_history_limit()
|
|
242
243
|
if len(message_history) > limit:
|
|
244
|
+
|
|
243
245
|
def group_by_tool_call_id(msgs):
|
|
244
246
|
grouped = {}
|
|
245
247
|
no_group = []
|
|
246
248
|
for m in msgs:
|
|
247
249
|
# Find all tool_call_id in message parts
|
|
248
250
|
tool_call_ids = set()
|
|
249
|
-
for part in getattr(m,
|
|
250
|
-
if hasattr(part,
|
|
251
|
+
for part in getattr(m, "parts", []):
|
|
252
|
+
if hasattr(part, "tool_call_id") and part.tool_call_id:
|
|
251
253
|
tool_call_ids.add(part.tool_call_id)
|
|
252
254
|
if tool_call_ids:
|
|
253
255
|
for tcid in tool_call_ids:
|
|
@@ -271,7 +273,6 @@ async def interactive_mode(history_file_path: str) -> None:
|
|
|
271
273
|
message_history = truncated
|
|
272
274
|
# --- END GROUP-AWARE TRUNCATION LOGIC ---
|
|
273
275
|
|
|
274
|
-
|
|
275
276
|
if agent_response and agent_response.awaiting_user_input:
|
|
276
277
|
console.print(
|
|
277
278
|
"\n[bold yellow]\u26a0 Agent needs your input to continue.[/bold yellow]"
|
|
@@ -110,7 +110,7 @@ def _replace_in_file(
|
|
|
110
110
|
orig_lines = modified.splitlines()
|
|
111
111
|
loc, score = _find_best_window(orig_lines, old_snippet)
|
|
112
112
|
|
|
113
|
-
if score < 0.95 or loc
|
|
113
|
+
if score < 0.95 or loc is None:
|
|
114
114
|
return {
|
|
115
115
|
"error": "No suitable match in file (JW < 0.95)",
|
|
116
116
|
"jw_score": score,
|
code_puppy/tools/ts_code_map.py
CHANGED
|
@@ -392,7 +392,11 @@ def _walk_fix(ts_node, rich_parent, info):
|
|
|
392
392
|
n_type = child.type
|
|
393
393
|
if n_type in nodes_cfg:
|
|
394
394
|
style = nodes_cfg[n_type].keywords["style"]
|
|
395
|
-
ident =
|
|
395
|
+
ident = (
|
|
396
|
+
child.child_by_field_name(name_field)
|
|
397
|
+
if name_field
|
|
398
|
+
else _first_identifier(child)
|
|
399
|
+
)
|
|
396
400
|
label_text = ident.text.decode() if ident else "<anon>"
|
|
397
401
|
label = nodes_cfg[n_type].func(label_text)
|
|
398
402
|
emoji = _emoji_for_node_type(n_type)
|
|
@@ -402,6 +406,8 @@ def _walk_fix(ts_node, rich_parent, info):
|
|
|
402
406
|
_walk_fix(child, branch, info)
|
|
403
407
|
else:
|
|
404
408
|
_walk_fix(child, rich_parent, info)
|
|
409
|
+
|
|
410
|
+
|
|
405
411
|
# ----------------------------------------------------------------------
|
|
406
412
|
|
|
407
413
|
|
|
@@ -465,7 +471,9 @@ def make_code_map(directory: str, ignore_tests: bool = True) -> str:
|
|
|
465
471
|
base_tree = RichTree(Text(Path(directory).name, style="bold magenta"))
|
|
466
472
|
|
|
467
473
|
# Cache to ensure we reuse RichTree nodes per directory path
|
|
468
|
-
dir_nodes: dict[str, RichTree] = {
|
|
474
|
+
dir_nodes: dict[str, RichTree] = {
|
|
475
|
+
Path(directory).resolve(): base_tree
|
|
476
|
+
} # key=abs path
|
|
469
477
|
|
|
470
478
|
for root, dirs, files in os.walk(directory):
|
|
471
479
|
# ignore dot-folders early
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code-puppy
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.74
|
|
4
4
|
Summary: Code generation agent
|
|
5
5
|
Author: Michael Pfaffenberger
|
|
6
6
|
License: MIT
|
|
@@ -146,7 +146,7 @@ Ensure that all components follow these color schemes to promote consistency in
|
|
|
146
146
|
|
|
147
147
|
## Using MCP Servers for External Tools
|
|
148
148
|
|
|
149
|
-
Code Puppy supports **MCP (Model Context Protocol) servers** to give you access to external code tools and advanced features like code search, documentation lookups, and more—including Context7 integration for deep docs and search!
|
|
149
|
+
Code Puppy supports **MCP (Model Context Protocol) servers** to give you access to external code tools and advanced features like code search, documentation lookups, and more—including Context7 (https://context7.com/) integration for deep docs and search!
|
|
150
150
|
|
|
151
151
|
### What is an MCP Server?
|
|
152
152
|
An MCP server is a standalone process (can be local or remote) that offers specialized functionality (plugins, doc search, code analysis, etc.). Code Puppy can connect to one or more MCP servers at startup, unlocking these extra commands inside your coding agent.
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
code_puppy/__init__.py,sha256=-ANvE6Xe5NlWDIRCIfL1x-rgtCZ6zM2Ye9NphFoULSY,82
|
|
2
|
-
code_puppy/agent.py,sha256=
|
|
2
|
+
code_puppy/agent.py,sha256=hhVrBhT3MAhzs61cSnZ7Au7lrjoFAewfh6fGkawEQQo,4084
|
|
3
3
|
code_puppy/agent_prompts.py,sha256=DnPNubiFtD6Ot76cIsxedJEaEVYS5AaxR3JWJM5nXNg,6925
|
|
4
|
-
code_puppy/config.py,sha256=
|
|
5
|
-
code_puppy/main.py,sha256
|
|
4
|
+
code_puppy/config.py,sha256=r5nw5ChOP8xd_K5yo8U5OtO2gy2bFhARiyNtDp1JrwQ,5013
|
|
5
|
+
code_puppy/main.py,sha256=-wC_Bs2vbu9r9kdajKcSjddQ1nHFnpifLUX6nhbATZw,12478
|
|
6
6
|
code_puppy/model_factory.py,sha256=jZH96zE5GMTK3RWjUpZB4HjbSO3fSaAzjRoQh8Y8lfg,7711
|
|
7
7
|
code_puppy/models.json,sha256=AY1dcFd3bMFaJBjU_u-PjsrnmcKbjjtGhjL3uYfqpW8,1692
|
|
8
8
|
code_puppy/session_memory.py,sha256=4sgAAjbXdLSi8hETpd56tgtrG6hqMUuZWDlJOu6BQjA,2735
|
|
9
9
|
code_puppy/version_checker.py,sha256=aRGulzuY4C4CdFvU1rITduyL-1xTFsn4GiD1uSfOl_Y,396
|
|
10
10
|
code_puppy/command_line/__init__.py,sha256=y7WeRemfYppk8KVbCGeAIiTuiOszIURCDjOMZv_YRmU,45
|
|
11
11
|
code_puppy/command_line/file_path_completion.py,sha256=gw8NpIxa6GOpczUJRyh7VNZwoXKKn-yvCqit7h2y6Gg,2931
|
|
12
|
-
code_puppy/command_line/meta_command_handler.py,sha256=
|
|
12
|
+
code_puppy/command_line/meta_command_handler.py,sha256=L7qP2g0Faz0V7bMH4YK3s03OWWuQFtK7Sh-Kt2zmmEQ,6182
|
|
13
13
|
code_puppy/command_line/model_picker_completion.py,sha256=NkyZZG7IhcVWSJ3ADytwCA5f8DpNeVs759Qtqs4fQtY,3733
|
|
14
|
-
code_puppy/command_line/motd.py,sha256=
|
|
14
|
+
code_puppy/command_line/motd.py,sha256=3HuwCMuu0_hZa7UCGnOY5EcG103y2jMFWo28NwY-GDQ,1846
|
|
15
15
|
code_puppy/command_line/prompt_toolkit_completion.py,sha256=_gP0FIOgHDNHTTWLNL0XNzr6sO0ISe7Mec1uQNo9kcM,8337
|
|
16
16
|
code_puppy/command_line/utils.py,sha256=7eyxDHjPjPB9wGDJQQcXV_zOsGdYsFgI0SGCetVmTqE,1251
|
|
17
17
|
code_puppy/tools/__init__.py,sha256=J_HCbkivdr1rP5vfucxttXhGmTBx0S2LNoDMrbaE-Fc,558
|
|
18
18
|
code_puppy/tools/command_runner.py,sha256=cEphrDyr12CoqpKizzaxhMHhG1HiVcqXArTkwc6lvxU,6760
|
|
19
19
|
code_puppy/tools/common.py,sha256=M53zhiXZAmPdvi1Y_bzCxgvEmifOvRRJvYPARYRZqHw,2253
|
|
20
|
-
code_puppy/tools/file_modifications.py,sha256=
|
|
20
|
+
code_puppy/tools/file_modifications.py,sha256=uEUXoB0F4h3Blzgeq4ggejv1GKAc8OdeTvntf58gsrQ,13072
|
|
21
21
|
code_puppy/tools/file_operations.py,sha256=xqj7MiK6sGTaC8NMrMRTybWlXG32S-DjybqJtnufRcI,11715
|
|
22
|
-
code_puppy/tools/ts_code_map.py,sha256
|
|
22
|
+
code_puppy/tools/ts_code_map.py,sha256=o-u8p5vsYwitfDtVEoPS-7MwWn2xHzwtIQLo1_WMhQs,17647
|
|
23
23
|
code_puppy/tools/web_search.py,sha256=sA2ierjuuYA517-uhb5s53SgeVsyOe1nExoZsrU1Fps,1284
|
|
24
|
-
code_puppy-0.0.
|
|
25
|
-
code_puppy-0.0.
|
|
26
|
-
code_puppy-0.0.
|
|
27
|
-
code_puppy-0.0.
|
|
28
|
-
code_puppy-0.0.
|
|
29
|
-
code_puppy-0.0.
|
|
24
|
+
code_puppy-0.0.74.data/data/code_puppy/models.json,sha256=AY1dcFd3bMFaJBjU_u-PjsrnmcKbjjtGhjL3uYfqpW8,1692
|
|
25
|
+
code_puppy-0.0.74.dist-info/METADATA,sha256=biL4TR0F1r-BMFHSjpTLvKxNdtYJ3zXhh5_3HQXVzYQ,6417
|
|
26
|
+
code_puppy-0.0.74.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
27
|
+
code_puppy-0.0.74.dist-info/entry_points.txt,sha256=d8YkBvIUxF-dHNJAj-x4fPEqizbY5d_TwvYpc01U5kw,58
|
|
28
|
+
code_puppy-0.0.74.dist-info/licenses/LICENSE,sha256=31u8x0SPgdOq3izJX41kgFazWsM43zPEF9eskzqbJMY,1075
|
|
29
|
+
code_puppy-0.0.74.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|