code-puppy 0.0.372__py3-none-any.whl → 0.0.374__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/agents/agent_creator_agent.py +49 -1
- code_puppy/agents/agent_helios.py +122 -0
- code_puppy/agents/agent_manager.py +26 -2
- code_puppy/agents/json_agent.py +30 -7
- code_puppy/claude_cache_client.py +9 -9
- code_puppy/command_line/colors_menu.py +2 -0
- code_puppy/command_line/command_handler.py +1 -0
- code_puppy/command_line/config_commands.py +3 -1
- code_puppy/command_line/uc_menu.py +890 -0
- code_puppy/config.py +29 -0
- code_puppy/messaging/messages.py +18 -0
- code_puppy/messaging/rich_renderer.py +35 -0
- code_puppy/messaging/subagent_console.py +0 -1
- code_puppy/plugins/claude_code_oauth/README.md +1 -1
- code_puppy/plugins/claude_code_oauth/SETUP.md +1 -1
- code_puppy/plugins/claude_code_oauth/utils.py +44 -13
- code_puppy/plugins/universal_constructor/__init__.py +13 -0
- code_puppy/plugins/universal_constructor/models.py +138 -0
- code_puppy/plugins/universal_constructor/register_callbacks.py +47 -0
- code_puppy/plugins/universal_constructor/registry.py +304 -0
- code_puppy/plugins/universal_constructor/sandbox.py +584 -0
- code_puppy/tools/__init__.py +138 -1
- code_puppy/tools/universal_constructor.py +889 -0
- {code_puppy-0.0.372.dist-info → code_puppy-0.0.374.dist-info}/METADATA +1 -1
- {code_puppy-0.0.372.dist-info → code_puppy-0.0.374.dist-info}/RECORD +30 -22
- {code_puppy-0.0.372.data → code_puppy-0.0.374.data}/data/code_puppy/models.json +0 -0
- {code_puppy-0.0.372.data → code_puppy-0.0.374.data}/data/code_puppy/models_dev_api.json +0 -0
- {code_puppy-0.0.372.dist-info → code_puppy-0.0.374.dist-info}/WHEEL +0 -0
- {code_puppy-0.0.372.dist-info → code_puppy-0.0.374.dist-info}/entry_points.txt +0 -0
- {code_puppy-0.0.372.dist-info → code_puppy-0.0.374.dist-info}/licenses/LICENSE +0 -0
code_puppy/tools/__init__.py
CHANGED
|
@@ -87,6 +87,7 @@ from code_puppy.tools.file_operations import (
|
|
|
87
87
|
register_list_files,
|
|
88
88
|
register_read_file,
|
|
89
89
|
)
|
|
90
|
+
from code_puppy.tools.universal_constructor import register_universal_constructor
|
|
90
91
|
|
|
91
92
|
# Map of tool names to their individual registration functions
|
|
92
93
|
TOOL_REGISTRY = {
|
|
@@ -163,6 +164,8 @@ TOOL_REGISTRY = {
|
|
|
163
164
|
"terminal_read_output": register_terminal_read_output,
|
|
164
165
|
"terminal_compare_mockup": register_terminal_compare_mockup,
|
|
165
166
|
"load_image_for_analysis": register_load_image,
|
|
167
|
+
# Universal Constructor
|
|
168
|
+
"universal_constructor": register_universal_constructor,
|
|
166
169
|
}
|
|
167
170
|
|
|
168
171
|
|
|
@@ -171,19 +174,153 @@ def register_tools_for_agent(agent, tool_names: list[str]):
|
|
|
171
174
|
|
|
172
175
|
Args:
|
|
173
176
|
agent: The agent to register tools to.
|
|
174
|
-
tool_names: List of tool names to register.
|
|
177
|
+
tool_names: List of tool names to register. UC tools are prefixed with "uc:".
|
|
175
178
|
"""
|
|
179
|
+
from code_puppy.config import get_universal_constructor_enabled
|
|
180
|
+
|
|
176
181
|
for tool_name in tool_names:
|
|
182
|
+
# Handle UC tools (prefixed with "uc:")
|
|
183
|
+
if tool_name.startswith("uc:"):
|
|
184
|
+
# Skip UC tools if UC is disabled
|
|
185
|
+
if not get_universal_constructor_enabled():
|
|
186
|
+
continue
|
|
187
|
+
uc_tool_name = tool_name[3:] # Remove "uc:" prefix
|
|
188
|
+
_register_uc_tool_wrapper(agent, uc_tool_name)
|
|
189
|
+
continue
|
|
190
|
+
|
|
177
191
|
if tool_name not in TOOL_REGISTRY:
|
|
178
192
|
# Skip unknown tools with a warning instead of failing
|
|
179
193
|
emit_warning(f"Warning: Unknown tool '{tool_name}' requested, skipping...")
|
|
180
194
|
continue
|
|
181
195
|
|
|
196
|
+
# Check if Universal Constructor is disabled
|
|
197
|
+
if (
|
|
198
|
+
tool_name == "universal_constructor"
|
|
199
|
+
and not get_universal_constructor_enabled()
|
|
200
|
+
):
|
|
201
|
+
continue # Skip UC if disabled in config
|
|
202
|
+
|
|
182
203
|
# Register the individual tool
|
|
183
204
|
register_func = TOOL_REGISTRY[tool_name]
|
|
184
205
|
register_func(agent)
|
|
185
206
|
|
|
186
207
|
|
|
208
|
+
def _register_uc_tool_wrapper(agent, uc_tool_name: str):
|
|
209
|
+
"""Register a wrapper for a UC tool that calls it via the UC registry.
|
|
210
|
+
|
|
211
|
+
This creates a dynamic tool that wraps the UC tool, preserving its
|
|
212
|
+
parameter signature so pydantic-ai can generate proper JSON schema.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
agent: The agent to register the tool wrapper to.
|
|
216
|
+
uc_tool_name: The full name of the UC tool (e.g., "api.weather").
|
|
217
|
+
"""
|
|
218
|
+
import inspect
|
|
219
|
+
from typing import Any
|
|
220
|
+
|
|
221
|
+
from pydantic_ai import RunContext
|
|
222
|
+
|
|
223
|
+
# Get tool info and function from registry
|
|
224
|
+
try:
|
|
225
|
+
from code_puppy.plugins.universal_constructor.registry import get_registry
|
|
226
|
+
|
|
227
|
+
registry = get_registry()
|
|
228
|
+
tool_info = registry.get_tool(uc_tool_name)
|
|
229
|
+
if not tool_info:
|
|
230
|
+
emit_warning(f"Warning: UC tool '{uc_tool_name}' not found, skipping...")
|
|
231
|
+
return
|
|
232
|
+
|
|
233
|
+
func = registry.get_tool_function(uc_tool_name)
|
|
234
|
+
if not func:
|
|
235
|
+
emit_warning(
|
|
236
|
+
f"Warning: UC tool '{uc_tool_name}' function not found, skipping..."
|
|
237
|
+
)
|
|
238
|
+
return
|
|
239
|
+
|
|
240
|
+
description = tool_info.meta.description
|
|
241
|
+
docstring = tool_info.docstring or description
|
|
242
|
+
except Exception as e:
|
|
243
|
+
emit_warning(f"Warning: Failed to get UC tool '{uc_tool_name}' info: {e}")
|
|
244
|
+
return
|
|
245
|
+
|
|
246
|
+
# Get the original function's signature
|
|
247
|
+
try:
|
|
248
|
+
sig = inspect.signature(func)
|
|
249
|
+
# Get annotations from the original function
|
|
250
|
+
annotations = getattr(func, "__annotations__", {}).copy()
|
|
251
|
+
except (ValueError, TypeError):
|
|
252
|
+
sig = None
|
|
253
|
+
annotations = {}
|
|
254
|
+
|
|
255
|
+
# Create wrapper that preserves the signature
|
|
256
|
+
def make_uc_wrapper(
|
|
257
|
+
tool_name: str, original_func, original_sig, original_annotations
|
|
258
|
+
):
|
|
259
|
+
# Build the wrapper function
|
|
260
|
+
async def uc_tool_wrapper(context: RunContext, **kwargs: Any) -> Any:
|
|
261
|
+
"""Dynamically generated wrapper for a UC tool."""
|
|
262
|
+
try:
|
|
263
|
+
result = original_func(**kwargs)
|
|
264
|
+
# Await async tool implementations
|
|
265
|
+
if inspect.isawaitable(result):
|
|
266
|
+
result = await result
|
|
267
|
+
return result
|
|
268
|
+
except Exception as e:
|
|
269
|
+
return {"error": f"UC tool '{tool_name}' failed: {e}"}
|
|
270
|
+
|
|
271
|
+
# Copy signature info from original function
|
|
272
|
+
uc_tool_wrapper.__name__ = tool_name.replace(".", "_")
|
|
273
|
+
uc_tool_wrapper.__doc__ = (
|
|
274
|
+
f"{docstring}\n\nThis is a Universal Constructor tool."
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
# Preserve annotations for pydantic-ai schema generation
|
|
278
|
+
if original_annotations:
|
|
279
|
+
# Add 'context' param and copy original params (excluding 'return')
|
|
280
|
+
new_annotations = {"context": RunContext}
|
|
281
|
+
for param_name, param_type in original_annotations.items():
|
|
282
|
+
if param_name != "return":
|
|
283
|
+
new_annotations[param_name] = param_type
|
|
284
|
+
if "return" in original_annotations:
|
|
285
|
+
new_annotations["return"] = original_annotations["return"]
|
|
286
|
+
else:
|
|
287
|
+
new_annotations["return"] = Any
|
|
288
|
+
uc_tool_wrapper.__annotations__ = new_annotations
|
|
289
|
+
|
|
290
|
+
# Try to set __signature__ for better introspection
|
|
291
|
+
if original_sig:
|
|
292
|
+
try:
|
|
293
|
+
# Build new parameters list: context first, then original params
|
|
294
|
+
new_params = [
|
|
295
|
+
inspect.Parameter(
|
|
296
|
+
"context",
|
|
297
|
+
inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
|
298
|
+
annotation=RunContext,
|
|
299
|
+
)
|
|
300
|
+
]
|
|
301
|
+
for param in original_sig.parameters.values():
|
|
302
|
+
new_params.append(param)
|
|
303
|
+
|
|
304
|
+
# Create new signature with return annotation
|
|
305
|
+
return_annotation = original_annotations.get("return", Any)
|
|
306
|
+
new_sig = original_sig.replace(
|
|
307
|
+
parameters=new_params, return_annotation=return_annotation
|
|
308
|
+
)
|
|
309
|
+
uc_tool_wrapper.__signature__ = new_sig
|
|
310
|
+
except (ValueError, TypeError):
|
|
311
|
+
pass # Signature manipulation failed, continue without it
|
|
312
|
+
|
|
313
|
+
return uc_tool_wrapper
|
|
314
|
+
|
|
315
|
+
wrapper = make_uc_wrapper(uc_tool_name, func, sig, annotations)
|
|
316
|
+
|
|
317
|
+
# Register the wrapper as a tool
|
|
318
|
+
try:
|
|
319
|
+
agent.tool(wrapper)
|
|
320
|
+
except Exception as e:
|
|
321
|
+
emit_warning(f"Warning: Failed to register UC tool '{uc_tool_name}': {e}")
|
|
322
|
+
|
|
323
|
+
|
|
187
324
|
def register_all_tools(agent):
|
|
188
325
|
"""Register all available tools to the provided agent.
|
|
189
326
|
|