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.
Files changed (30) hide show
  1. code_puppy/agents/agent_creator_agent.py +49 -1
  2. code_puppy/agents/agent_helios.py +122 -0
  3. code_puppy/agents/agent_manager.py +26 -2
  4. code_puppy/agents/json_agent.py +30 -7
  5. code_puppy/claude_cache_client.py +9 -9
  6. code_puppy/command_line/colors_menu.py +2 -0
  7. code_puppy/command_line/command_handler.py +1 -0
  8. code_puppy/command_line/config_commands.py +3 -1
  9. code_puppy/command_line/uc_menu.py +890 -0
  10. code_puppy/config.py +29 -0
  11. code_puppy/messaging/messages.py +18 -0
  12. code_puppy/messaging/rich_renderer.py +35 -0
  13. code_puppy/messaging/subagent_console.py +0 -1
  14. code_puppy/plugins/claude_code_oauth/README.md +1 -1
  15. code_puppy/plugins/claude_code_oauth/SETUP.md +1 -1
  16. code_puppy/plugins/claude_code_oauth/utils.py +44 -13
  17. code_puppy/plugins/universal_constructor/__init__.py +13 -0
  18. code_puppy/plugins/universal_constructor/models.py +138 -0
  19. code_puppy/plugins/universal_constructor/register_callbacks.py +47 -0
  20. code_puppy/plugins/universal_constructor/registry.py +304 -0
  21. code_puppy/plugins/universal_constructor/sandbox.py +584 -0
  22. code_puppy/tools/__init__.py +138 -1
  23. code_puppy/tools/universal_constructor.py +889 -0
  24. {code_puppy-0.0.372.dist-info → code_puppy-0.0.374.dist-info}/METADATA +1 -1
  25. {code_puppy-0.0.372.dist-info → code_puppy-0.0.374.dist-info}/RECORD +30 -22
  26. {code_puppy-0.0.372.data → code_puppy-0.0.374.data}/data/code_puppy/models.json +0 -0
  27. {code_puppy-0.0.372.data → code_puppy-0.0.374.data}/data/code_puppy/models_dev_api.json +0 -0
  28. {code_puppy-0.0.372.dist-info → code_puppy-0.0.374.dist-info}/WHEEL +0 -0
  29. {code_puppy-0.0.372.dist-info → code_puppy-0.0.374.dist-info}/entry_points.txt +0 -0
  30. {code_puppy-0.0.372.dist-info → code_puppy-0.0.374.dist-info}/licenses/LICENSE +0 -0
@@ -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