connectonion 0.5.10__py3-none-any.whl → 0.6.1__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.
- connectonion/__init__.py +17 -16
- connectonion/cli/browser_agent/browser.py +488 -145
- connectonion/cli/browser_agent/scroll_strategies.py +276 -0
- connectonion/cli/commands/copy_commands.py +24 -1
- connectonion/cli/commands/deploy_commands.py +15 -0
- connectonion/cli/commands/eval_commands.py +286 -0
- connectonion/cli/commands/project_cmd_lib.py +1 -1
- connectonion/cli/main.py +11 -0
- connectonion/console.py +5 -5
- connectonion/core/__init__.py +53 -0
- connectonion/{agent.py → core/agent.py} +18 -15
- connectonion/{llm.py → core/llm.py} +9 -19
- connectonion/{tool_executor.py → core/tool_executor.py} +3 -2
- connectonion/{tool_factory.py → core/tool_factory.py} +3 -1
- connectonion/debug/__init__.py +51 -0
- connectonion/{interactive_debugger.py → debug/auto_debug.py} +7 -7
- connectonion/{auto_debug_exception.py → debug/auto_debug_exception.py} +3 -3
- connectonion/{debugger_ui.py → debug/auto_debug_ui.py} +1 -1
- connectonion/{debug_explainer → debug/debug_explainer}/explain_agent.py +1 -1
- connectonion/{debug_explainer → debug/debug_explainer}/explain_context.py +1 -1
- connectonion/{execution_analyzer → debug/execution_analyzer}/execution_analysis.py +1 -1
- connectonion/debug/runtime_inspector/__init__.py +13 -0
- connectonion/{debug_agent → debug/runtime_inspector}/agent.py +1 -1
- connectonion/{xray.py → debug/xray.py} +1 -1
- connectonion/llm_do.py +1 -1
- connectonion/logger.py +305 -135
- connectonion/network/__init__.py +37 -0
- connectonion/{announce.py → network/announce.py} +1 -1
- connectonion/{asgi.py → network/asgi.py} +122 -2
- connectonion/{connect.py → network/connect.py} +1 -1
- connectonion/network/connection.py +123 -0
- connectonion/{host.py → network/host.py} +31 -11
- connectonion/{trust.py → network/trust.py} +1 -1
- connectonion/tui/__init__.py +22 -0
- connectonion/tui/chat.py +647 -0
- connectonion/useful_events_handlers/reflect.py +2 -2
- connectonion/useful_plugins/__init__.py +4 -3
- connectonion/useful_plugins/calendar_plugin.py +2 -2
- connectonion/useful_plugins/eval.py +2 -2
- connectonion/useful_plugins/gmail_plugin.py +2 -2
- connectonion/useful_plugins/image_result_formatter.py +2 -2
- connectonion/useful_plugins/re_act.py +2 -2
- connectonion/useful_plugins/shell_approval.py +2 -2
- connectonion/useful_plugins/ui_stream.py +164 -0
- {connectonion-0.5.10.dist-info → connectonion-0.6.1.dist-info}/METADATA +4 -3
- connectonion-0.6.1.dist-info/RECORD +123 -0
- connectonion/debug_agent/__init__.py +0 -13
- connectonion-0.5.10.dist-info/RECORD +0 -115
- /connectonion/{events.py → core/events.py} +0 -0
- /connectonion/{tool_registry.py → core/tool_registry.py} +0 -0
- /connectonion/{usage.py → core/usage.py} +0 -0
- /connectonion/{debug_explainer → debug/debug_explainer}/__init__.py +0 -0
- /connectonion/{debug_explainer → debug/debug_explainer}/explainer_prompt.md +0 -0
- /connectonion/{debug_explainer → debug/debug_explainer}/root_cause_analysis_prompt.md +0 -0
- /connectonion/{decorators.py → debug/decorators.py} +0 -0
- /connectonion/{execution_analyzer → debug/execution_analyzer}/__init__.py +0 -0
- /connectonion/{execution_analyzer → debug/execution_analyzer}/execution_analysis_prompt.md +0 -0
- /connectonion/{debug_agent → debug/runtime_inspector}/prompts/debug_assistant.md +0 -0
- /connectonion/{debug_agent → debug/runtime_inspector}/runtime_inspector.py +0 -0
- /connectonion/{relay.py → network/relay.py} +0 -0
- /connectonion/{static → network/static}/docs.html +0 -0
- /connectonion/{trust_agents.py → network/trust_agents.py} +0 -0
- /connectonion/{trust_functions.py → network/trust_functions.py} +0 -0
- {connectonion-0.5.10.dist-info → connectonion-0.6.1.dist-info}/WHEEL +0 -0
- {connectonion-0.5.10.dist-info → connectonion-0.6.1.dist-info}/entry_points.txt +0 -0
connectonion/console.py
CHANGED
|
@@ -110,7 +110,7 @@ class Console:
|
|
|
110
110
|
● ─────────────────────
|
|
111
111
|
connectonion v0.5.1
|
|
112
112
|
o4-mini · 3 tools
|
|
113
|
-
.co/logs/ · .co/
|
|
113
|
+
.co/logs/ · .co/evals/
|
|
114
114
|
|
|
115
115
|
Args:
|
|
116
116
|
agent_name: Name of the agent
|
|
@@ -156,7 +156,7 @@ class Console:
|
|
|
156
156
|
|
|
157
157
|
# Add log paths if logging is enabled
|
|
158
158
|
if log_dir:
|
|
159
|
-
lines.append(f" [{DIM_COLOR}]{log_dir}logs/ · {log_dir}
|
|
159
|
+
lines.append(f" [{DIM_COLOR}]{log_dir}logs/ · {log_dir}evals/[/{DIM_COLOR}]")
|
|
160
160
|
|
|
161
161
|
# Add Aaron's message for free tier users
|
|
162
162
|
if aaron_message:
|
|
@@ -182,7 +182,7 @@ class Console:
|
|
|
182
182
|
if meta_line:
|
|
183
183
|
plain_lines.append(f" {meta_line}")
|
|
184
184
|
if log_dir:
|
|
185
|
-
plain_lines.append(f" {log_dir}logs/ · {log_dir}
|
|
185
|
+
plain_lines.append(f" {log_dir}logs/ · {log_dir}evals/")
|
|
186
186
|
if aaron_message:
|
|
187
187
|
plain_lines.append(f" {aaron_message}")
|
|
188
188
|
plain_lines.append(f" {separator}")
|
|
@@ -484,12 +484,12 @@ class Console:
|
|
|
484
484
|
|
|
485
485
|
[co] ═══════════════════════════════════════
|
|
486
486
|
[co] ✓ done · 2.3k tokens · $0.005 · 3.4s
|
|
487
|
-
[co] saved → .co/
|
|
487
|
+
[co] saved → .co/evals/research-assistant.yaml
|
|
488
488
|
|
|
489
489
|
Args:
|
|
490
490
|
duration_s: Total duration in seconds
|
|
491
491
|
session: Agent's current_session dict (contains trace with usage)
|
|
492
|
-
session_path: Optional path to
|
|
492
|
+
session_path: Optional path to eval file
|
|
493
493
|
"""
|
|
494
494
|
# Calculate totals from trace
|
|
495
495
|
trace = session.get('trace', [])
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Core agent execution engine.
|
|
2
|
+
|
|
3
|
+
This module contains the minimal set of components needed to run an agent:
|
|
4
|
+
- Agent: Main orchestrator
|
|
5
|
+
- LLM: Multi-provider LLM abstraction
|
|
6
|
+
- Events: Event system for lifecycle hooks
|
|
7
|
+
- Tools: Tool execution, factory, and registry
|
|
8
|
+
- Usage: Token tracking and cost calculation
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from .agent import Agent
|
|
12
|
+
from .llm import LLM, create_llm, TokenUsage
|
|
13
|
+
from .events import (
|
|
14
|
+
EventHandler,
|
|
15
|
+
after_user_input,
|
|
16
|
+
before_llm,
|
|
17
|
+
after_llm,
|
|
18
|
+
before_each_tool,
|
|
19
|
+
before_tools,
|
|
20
|
+
after_each_tool,
|
|
21
|
+
after_tools,
|
|
22
|
+
on_error,
|
|
23
|
+
on_complete,
|
|
24
|
+
)
|
|
25
|
+
from .tool_factory import create_tool_from_function, extract_methods_from_instance, is_class_instance
|
|
26
|
+
from .tool_registry import ToolRegistry
|
|
27
|
+
from .tool_executor import execute_and_record_tools, execute_single_tool
|
|
28
|
+
from .usage import TokenUsage, calculate_cost, get_context_limit
|
|
29
|
+
|
|
30
|
+
__all__ = [
|
|
31
|
+
"Agent",
|
|
32
|
+
"LLM",
|
|
33
|
+
"create_llm",
|
|
34
|
+
"TokenUsage",
|
|
35
|
+
"EventHandler",
|
|
36
|
+
"after_user_input",
|
|
37
|
+
"before_llm",
|
|
38
|
+
"after_llm",
|
|
39
|
+
"before_each_tool",
|
|
40
|
+
"before_tools",
|
|
41
|
+
"after_each_tool",
|
|
42
|
+
"after_tools",
|
|
43
|
+
"on_error",
|
|
44
|
+
"on_complete",
|
|
45
|
+
"create_tool_from_function",
|
|
46
|
+
"extract_methods_from_instance",
|
|
47
|
+
"is_class_instance",
|
|
48
|
+
"ToolRegistry",
|
|
49
|
+
"execute_and_record_tools",
|
|
50
|
+
"execute_single_tool",
|
|
51
|
+
"calculate_cost",
|
|
52
|
+
"get_context_limit",
|
|
53
|
+
]
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
Purpose: Orchestrate AI agent execution with LLM calls, tool execution, and automatic logging
|
|
3
3
|
LLM-Note:
|
|
4
4
|
Dependencies: imports from [llm.py, tool_factory.py, prompts.py, decorators.py, logger.py, tool_executor.py, tool_registry.py] | imported by [__init__.py, debug_agent/__init__.py] | tested by [tests/test_agent.py, tests/test_agent_prompts.py, tests/test_agent_workflows.py]
|
|
5
|
-
Data flow: receives user prompt: str from Agent.input() → creates/extends current_session with messages → calls llm.complete() with tool schemas → receives LLMResponse with tool_calls → executes tools via tool_executor.execute_and_record_tools() → appends tool results to messages → repeats loop until no tool_calls or max_iterations → logger logs to .co/logs/{name}.log and .co/
|
|
6
|
-
State/Effects: modifies self.current_session['messages', 'trace', 'turn', 'iteration'] | writes to .co/logs/{name}.log and .co/
|
|
7
|
-
Integration: exposes Agent(name, tools, system_prompt, model, log, quiet), .input(prompt), .execute_tool(name, args), .add_tool(func), .remove_tool(name), .list_tools(), .reset_conversation() | tools stored in ToolRegistry with attribute access (agent.tools.tool_name) and instance storage (agent.tools.gmail) | tool execution delegates to tool_executor module | log defaults to .co/logs/ (None), can be True (current dir), False (disabled), or custom path | quiet=True suppresses console but keeps
|
|
5
|
+
Data flow: receives user prompt: str from Agent.input() → creates/extends current_session with messages → calls llm.complete() with tool schemas → receives LLMResponse with tool_calls → executes tools via tool_executor.execute_and_record_tools() → appends tool results to messages → repeats loop until no tool_calls or max_iterations → logger logs to .co/logs/{name}.log and .co/evals/{name}.yaml → returns final response: str
|
|
6
|
+
State/Effects: modifies self.current_session['messages', 'trace', 'turn', 'iteration'] | writes to .co/logs/{name}.log and .co/evals/ via logger.py
|
|
7
|
+
Integration: exposes Agent(name, tools, system_prompt, model, log, quiet), .input(prompt), .execute_tool(name, args), .add_tool(func), .remove_tool(name), .list_tools(), .reset_conversation() | tools stored in ToolRegistry with attribute access (agent.tools.tool_name) and instance storage (agent.tools.gmail) | tool execution delegates to tool_executor module | log defaults to .co/logs/ (None), can be True (current dir), False (disabled), or custom path | quiet=True suppresses console but keeps eval logging | trust enforcement moved to host() for network access control
|
|
8
8
|
Performance: max_iterations=10 default (configurable per-input) | session state persists across turns for multi-turn conversations | ToolRegistry provides O(1) tool lookup via .get() or attribute access
|
|
9
9
|
Errors: LLM errors bubble up | tool execution errors captured in trace and returned to LLM for retry
|
|
10
10
|
"""
|
|
@@ -18,11 +18,11 @@ from .llm import LLM, create_llm, TokenUsage
|
|
|
18
18
|
from .usage import get_context_limit
|
|
19
19
|
from .tool_factory import create_tool_from_function, extract_methods_from_instance, is_class_instance
|
|
20
20
|
from .tool_registry import ToolRegistry
|
|
21
|
-
from
|
|
22
|
-
from .decorators import (
|
|
21
|
+
from ..prompts import load_system_prompt
|
|
22
|
+
from ..debug.decorators import (
|
|
23
23
|
_is_replay_enabled # Only need this for replay check
|
|
24
24
|
)
|
|
25
|
-
from
|
|
25
|
+
from ..logger import Logger
|
|
26
26
|
from .tool_executor import execute_and_record_tools, execute_single_tool
|
|
27
27
|
from .events import EventHandler
|
|
28
28
|
|
|
@@ -51,11 +51,14 @@ class Agent:
|
|
|
51
51
|
# Current session context (runtime only)
|
|
52
52
|
self.current_session = None
|
|
53
53
|
|
|
54
|
+
# Connection to client (None locally, injected by host() for WebSocket)
|
|
55
|
+
self.connection = None
|
|
56
|
+
|
|
54
57
|
# Token usage tracking
|
|
55
58
|
self.total_cost: float = 0.0 # Cumulative cost in USD
|
|
56
59
|
self.last_usage: Optional[TokenUsage] = None # From most recent LLM call
|
|
57
60
|
|
|
58
|
-
# Initialize logger (unified: terminal + file + YAML
|
|
61
|
+
# Initialize logger (unified: terminal + file + YAML evals)
|
|
59
62
|
# Environment variable override (highest priority)
|
|
60
63
|
effective_log = log
|
|
61
64
|
if os.getenv('CONNECTONION_LOG'):
|
|
@@ -250,16 +253,16 @@ class Agent:
|
|
|
250
253
|
|
|
251
254
|
self.current_session['result'] = result
|
|
252
255
|
|
|
253
|
-
# Print completion summary
|
|
254
|
-
if self.logger.console:
|
|
255
|
-
session_path = f".co/sessions/{self.name}.yaml" if self.logger.enable_sessions else None
|
|
256
|
-
self.logger.console.print_completion(duration, self.current_session, session_path)
|
|
257
|
-
|
|
258
256
|
self._invoke_events('on_complete')
|
|
259
257
|
|
|
260
|
-
# Log turn to YAML
|
|
258
|
+
# Log turn to YAML eval (after on_complete so handlers can modify state)
|
|
261
259
|
self.logger.log_turn(prompt, result, duration * 1000, self.current_session, self.llm.model)
|
|
262
260
|
|
|
261
|
+
# Print completion summary (after log_turn so we have the eval path)
|
|
262
|
+
if self.logger.console:
|
|
263
|
+
eval_path = self.logger.get_eval_path()
|
|
264
|
+
self.logger.console.print_completion(duration, self.current_session, eval_path)
|
|
265
|
+
|
|
263
266
|
return result
|
|
264
267
|
|
|
265
268
|
def reset_conversation(self):
|
|
@@ -444,7 +447,7 @@ class Agent:
|
|
|
444
447
|
# Single prompt mode
|
|
445
448
|
agent.auto_debug("Find information about Python")
|
|
446
449
|
"""
|
|
447
|
-
from .
|
|
448
|
-
debugger =
|
|
450
|
+
from .debug import AutoDebugger
|
|
451
|
+
debugger = AutoDebugger(self)
|
|
449
452
|
debugger.start_debug_session(prompt)
|
|
450
453
|
|
|
@@ -734,28 +734,18 @@ class OpenOnionLLM(LLM):
|
|
|
734
734
|
)
|
|
735
735
|
|
|
736
736
|
def structured_complete(self, messages: List[Dict], output_schema: Type[BaseModel], **kwargs) -> BaseModel:
|
|
737
|
-
"""Get structured Pydantic output using OpenAI-compatible API.
|
|
738
|
-
|
|
737
|
+
"""Get structured Pydantic output using OpenAI-compatible chat completions API.
|
|
738
|
+
|
|
739
|
+
Uses beta.chat.completions.parse() which routes through /v1/chat/completions,
|
|
740
|
+
allowing proper provider routing for Gemini, OpenAI, and other models.
|
|
741
|
+
"""
|
|
742
|
+
completion = self.client.beta.chat.completions.parse(
|
|
739
743
|
model=self.model,
|
|
740
|
-
|
|
741
|
-
|
|
744
|
+
messages=messages,
|
|
745
|
+
response_format=output_schema,
|
|
742
746
|
**kwargs
|
|
743
747
|
)
|
|
744
|
-
|
|
745
|
-
# Handle edge cases
|
|
746
|
-
if response.status == "incomplete":
|
|
747
|
-
if response.incomplete_details.reason == "max_output_tokens":
|
|
748
|
-
raise ValueError("Response incomplete: maximum output tokens reached")
|
|
749
|
-
elif response.incomplete_details.reason == "content_filter":
|
|
750
|
-
raise ValueError("Response incomplete: content filtered")
|
|
751
|
-
|
|
752
|
-
# Check for refusal
|
|
753
|
-
if response.output and len(response.output) > 0:
|
|
754
|
-
first_content = response.output[0].content[0] if response.output[0].content else None
|
|
755
|
-
if first_content and hasattr(first_content, 'type') and first_content.type == "refusal":
|
|
756
|
-
raise ValueError(f"Model refused to respond: {first_content.refusal}")
|
|
757
|
-
|
|
758
|
-
return response.output_parsed
|
|
748
|
+
return completion.choices[0].message.parsed
|
|
759
749
|
|
|
760
750
|
|
|
761
751
|
def create_llm(model: str, api_key: Optional[str] = None, **kwargs) -> LLM:
|
|
@@ -13,7 +13,7 @@ import time
|
|
|
13
13
|
import json
|
|
14
14
|
from typing import List, Dict, Any, Optional, Callable
|
|
15
15
|
|
|
16
|
-
from .xray import (
|
|
16
|
+
from ..debug.xray import (
|
|
17
17
|
inject_xray_context,
|
|
18
18
|
clear_xray_context,
|
|
19
19
|
is_xray_enabled
|
|
@@ -165,7 +165,8 @@ def execute_single_tool(
|
|
|
165
165
|
agent.current_session['pending_tool'] = {
|
|
166
166
|
'name': tool_name,
|
|
167
167
|
'arguments': tool_args,
|
|
168
|
-
'id': tool_id
|
|
168
|
+
'id': tool_id,
|
|
169
|
+
'description': getattr(tool_func, 'description', '')
|
|
169
170
|
}
|
|
170
171
|
|
|
171
172
|
# Invoke before_each_tool events
|
|
@@ -29,7 +29,9 @@ def create_tool_from_function(func: Callable) -> Callable:
|
|
|
29
29
|
by inspecting its signature and docstring.
|
|
30
30
|
"""
|
|
31
31
|
name = func.__name__
|
|
32
|
-
|
|
32
|
+
raw_doc = inspect.getdoc(func)
|
|
33
|
+
# Extract summary only (first paragraph) - Args/Returns sections are not sent to LLM
|
|
34
|
+
description = raw_doc.split('\n\n')[0].strip() if raw_doc else f"Execute the {name} tool."
|
|
33
35
|
|
|
34
36
|
# Build the parameters schema from the function signature
|
|
35
37
|
sig = inspect.signature(func)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""Debug tools for agent development and troubleshooting.
|
|
2
|
+
|
|
3
|
+
This module contains:
|
|
4
|
+
- xray: Runtime context injection for tool inspection
|
|
5
|
+
- decorators: replay, xray_replay for debugging
|
|
6
|
+
- auto_debug: Interactive debugging with breakpoints (AutoDebugger, AutoDebugUI)
|
|
7
|
+
- auto_debug_exception: Exception handling and debugging
|
|
8
|
+
- runtime_inspector: AI-powered runtime state inspection for crash debugging
|
|
9
|
+
- debug_explainer: AI-powered explanation of tool choices
|
|
10
|
+
|
|
11
|
+
Note: Uses lazy imports to avoid circular dependency with agent.py
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
# xray and decorators can be imported eagerly (no circular dependency)
|
|
15
|
+
from .xray import xray
|
|
16
|
+
from .decorators import replay, xray_replay
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"xray",
|
|
20
|
+
"replay",
|
|
21
|
+
"xray_replay",
|
|
22
|
+
"AutoDebugger",
|
|
23
|
+
"AutoDebugUI",
|
|
24
|
+
"BreakpointContext",
|
|
25
|
+
"BreakpointAction",
|
|
26
|
+
"auto_debug_exception",
|
|
27
|
+
"create_debug_agent",
|
|
28
|
+
"RuntimeInspector",
|
|
29
|
+
"explain_tool_choice",
|
|
30
|
+
"RuntimeContext",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def __getattr__(name):
|
|
35
|
+
"""Lazy import to avoid circular dependency with agent.py."""
|
|
36
|
+
if name == "AutoDebugger":
|
|
37
|
+
from .auto_debug import AutoDebugger
|
|
38
|
+
return AutoDebugger
|
|
39
|
+
elif name in ("AutoDebugUI", "BreakpointContext", "BreakpointAction"):
|
|
40
|
+
from .auto_debug_ui import AutoDebugUI, BreakpointContext, BreakpointAction
|
|
41
|
+
return {"AutoDebugUI": AutoDebugUI, "BreakpointContext": BreakpointContext, "BreakpointAction": BreakpointAction}[name]
|
|
42
|
+
elif name == "auto_debug_exception":
|
|
43
|
+
from .auto_debug_exception import auto_debug_exception
|
|
44
|
+
return auto_debug_exception
|
|
45
|
+
elif name in ("create_debug_agent", "RuntimeInspector"):
|
|
46
|
+
from .runtime_inspector import create_debug_agent, RuntimeInspector
|
|
47
|
+
return {"create_debug_agent": create_debug_agent, "RuntimeInspector": RuntimeInspector}[name]
|
|
48
|
+
elif name in ("explain_tool_choice", "RuntimeContext"):
|
|
49
|
+
from .debug_explainer import explain_tool_choice, RuntimeContext
|
|
50
|
+
return {"explain_tool_choice": explain_tool_choice, "RuntimeContext": RuntimeContext}[name]
|
|
51
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
@@ -13,25 +13,25 @@ LLM-Note:
|
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
15
|
from typing import Any, Dict, Optional, List
|
|
16
|
-
from .
|
|
16
|
+
from .auto_debug_ui import AutoDebugUI, BreakpointContext, BreakpointAction
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
class
|
|
19
|
+
class AutoDebugger:
|
|
20
20
|
"""Orchestrates debugging sessions for AI agents.
|
|
21
21
|
|
|
22
22
|
This class handles the debugging logic and intercepts tool execution,
|
|
23
23
|
delegating all UI interactions to the DebuggerUI class.
|
|
24
24
|
"""
|
|
25
25
|
|
|
26
|
-
def __init__(self, agent: Any, ui: Optional[
|
|
26
|
+
def __init__(self, agent: Any, ui: Optional[AutoDebugUI] = None):
|
|
27
27
|
"""Initialize debugger with an agent instance and optional UI.
|
|
28
28
|
|
|
29
29
|
Args:
|
|
30
30
|
agent: The Agent instance to debug
|
|
31
|
-
ui: Optional
|
|
31
|
+
ui: Optional AutoDebugUI instance (creates default if None)
|
|
32
32
|
"""
|
|
33
33
|
self.agent = agent
|
|
34
|
-
self.ui = ui or
|
|
34
|
+
self.ui = ui or AutoDebugUI()
|
|
35
35
|
self.original_execute_single_tool = None
|
|
36
36
|
|
|
37
37
|
def start_debug_session(self, prompt: Optional[str] = None):
|
|
@@ -99,7 +99,7 @@ class InteractiveDebugger:
|
|
|
99
99
|
- Pause execution and show UI if breakpoint conditions are met
|
|
100
100
|
- Only affect this specific agent instance
|
|
101
101
|
"""
|
|
102
|
-
from
|
|
102
|
+
from ..core import tool_executor
|
|
103
103
|
from .xray import is_xray_enabled
|
|
104
104
|
|
|
105
105
|
# Store original function for restoration later
|
|
@@ -141,7 +141,7 @@ class InteractiveDebugger:
|
|
|
141
141
|
tool execution function.
|
|
142
142
|
"""
|
|
143
143
|
if self.original_execute_single_tool:
|
|
144
|
-
from
|
|
144
|
+
from ..core import tool_executor
|
|
145
145
|
tool_executor.execute_single_tool = self.original_execute_single_tool
|
|
146
146
|
|
|
147
147
|
def _show_breakpoint_ui_and_wait_for_continue(self, tool_name: str, tool_args: Dict, trace_entry: Dict):
|
|
@@ -57,7 +57,7 @@ def auto_debug_exception(model: str = "o4-mini"):
|
|
|
57
57
|
original_hook(exc_type, exc_value, exception_traceback)
|
|
58
58
|
|
|
59
59
|
# Then add our AI analysis
|
|
60
|
-
from
|
|
60
|
+
from ..console import Console
|
|
61
61
|
console = Console()
|
|
62
62
|
|
|
63
63
|
# Find the most relevant frame (last user code, not library)
|
|
@@ -125,7 +125,7 @@ def auto_debug_exception(model: str = "o4-mini"):
|
|
|
125
125
|
|
|
126
126
|
try:
|
|
127
127
|
# Use debug agent with runtime inspection tools
|
|
128
|
-
from .
|
|
128
|
+
from .runtime_inspector import create_debug_agent
|
|
129
129
|
|
|
130
130
|
# Pass the actual frame and traceback for runtime inspection!
|
|
131
131
|
agent = create_debug_agent(
|
|
@@ -176,6 +176,6 @@ You have LIVE ACCESS to the crashed program's state! Use your tools to investiga
|
|
|
176
176
|
sys.excepthook = handle_exception
|
|
177
177
|
|
|
178
178
|
# Simple confirmation
|
|
179
|
-
from
|
|
179
|
+
from ..console import Console
|
|
180
180
|
console = Console()
|
|
181
181
|
console.print(f"[green]✅ Exception debugging enabled[/green] - AI will analyze uncaught exceptions with runtime inspection")
|
|
@@ -16,7 +16,7 @@ Analyzes the entire execution trace and provides suggestions for improvement.
|
|
|
16
16
|
from pathlib import Path
|
|
17
17
|
from pydantic import BaseModel
|
|
18
18
|
from typing import List
|
|
19
|
-
from
|
|
19
|
+
from ...llm_do import llm_do
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
class ExecutionAnalysis(BaseModel):
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Runtime inspector for AI-powered crash debugging.
|
|
2
|
+
|
|
3
|
+
Provides RuntimeInspector class and factory function to create debug agents
|
|
4
|
+
that can experiment, test, and validate fixes using actual crashed program data.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .agent import create_debug_agent
|
|
8
|
+
from .runtime_inspector import RuntimeInspector
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"create_debug_agent",
|
|
12
|
+
"RuntimeInspector"
|
|
13
|
+
]
|
|
@@ -14,7 +14,7 @@ This module provides the @xray decorator and xray context for debugging AI agent
|
|
|
14
14
|
See everything your agent is thinking during tool execution.
|
|
15
15
|
|
|
16
16
|
Usage:
|
|
17
|
-
from connectonion
|
|
17
|
+
from connectonion import xray # or: from connectonion.debug import xray
|
|
18
18
|
|
|
19
19
|
@xray
|
|
20
20
|
def my_tool(query: str):
|
connectonion/llm_do.py
CHANGED
|
@@ -222,7 +222,7 @@ from typing import Union, Type, Optional, TypeVar
|
|
|
222
222
|
from pathlib import Path
|
|
223
223
|
from pydantic import BaseModel
|
|
224
224
|
from .prompts import load_system_prompt
|
|
225
|
-
from .llm import create_llm
|
|
225
|
+
from .core.llm import create_llm
|
|
226
226
|
|
|
227
227
|
T = TypeVar('T', bound=BaseModel)
|
|
228
228
|
|