execweave 0.8.27__tar.gz → 0.8.29__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.
- {execweave-0.8.27 → execweave-0.8.29}/PKG-INFO +10 -2
- {execweave-0.8.27 → execweave-0.8.29}/README.md +9 -1
- {execweave-0.8.27 → execweave-0.8.29}/pyproject.toml +2 -2
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/__init__.py +1 -1
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/framework_adapters/autogen.py +48 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/framework_adapters/base.py +56 -1
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/framework_adapters/camel.py +35 -5
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/framework_adapters/metagpt.py +20 -2
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/live_core.py +16 -6
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/provider_record.py +1 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_agent_panel.py +28 -3
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/workflow.py +60 -3
- {execweave-0.8.27 → execweave-0.8.29}/.gitignore +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/LICENSE +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/__main__.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/_conversation_records_core.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/_dashboard_shell_base.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/_http_proxy_base.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/_http_proxy_bounded.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/_http_proxy_stage.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/agent_bootstrap.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/agent_topology.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/agent_trace.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/agy_preview_sanitize.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/analysis.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/anthropic.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/anthropic_cli.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/anthropic_full_fidelity.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/antigravity_adapter.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/antigravity_adapter_base.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/antigravity_full_fidelity.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/antigravity_full_fidelity_base.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/antigravity_full_fidelity_collaboration_base.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/antigravity_hook_cli.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/antigravity_record.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/antigravity_subagent_linkage.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/antigravity_trace_capability.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/auto_specialized.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/backends.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/benchmark.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/claude_adapter.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/claude_child_transcript.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/claude_delegation.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/claude_full_fidelity.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/claude_hook_cli.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/claude_hook_contract.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/claude_model_observer.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/claude_record.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/cli.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/codex_adapter.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/codex_conversation.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/codex_full_fidelity.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/codex_hook_cli.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/codex_hook_entry.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/codex_hook_lifecycle.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/codex_message_diagnostics.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/codex_message_transport_diagnostics.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/codex_record.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/codex_rollout_structures.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/codex_rollout_trace.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/codex_rollout_trace_base.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/collector.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/command.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/content_evidence.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/content_store.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/conversation_archive.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/conversation_message_identity.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/conversation_preview.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/conversation_preview_antigravity.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/conversation_preview_claude.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/conversation_preview_codex.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/conversation_preview_common.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/conversation_preview_generic.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/conversation_preview_lines.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/conversation_preview_transcript.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/conversation_records.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/conversation_records_antigravity.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/conversation_records_codex.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/conversation_records_common.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/conversation_records_ollama.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/correlation.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/cursor_adapter.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/cursor_delegation.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/cursor_delegation_base.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/cursor_full_fidelity.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/cursor_hook_cli.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/cursor_hook_contract.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/cursor_lifecycle.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/cursor_record.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/dashboard_shell.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/entry.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/evidence_availability.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/evidence_grade.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/fidelity.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/filesystem.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/focus.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/framework_adapters/__init__.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/framework_adapters/registry.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/graph.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/graph_ops.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/http_proxy.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/http_proxy_cli.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/inference_gateway.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/inference_gateway_cli.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/inference_gateway_full_fidelity.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/inference_identity.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/inference_identity_cli.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/integrity.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/integrity_cli.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/litellm_callback.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/litellm_callback_cli.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/live.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/live_view.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/live_view_extra_style.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/live_view_markup.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/live_view_process_layout.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/live_view_readability.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/live_view_script_a.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/live_view_script_b.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/live_view_script_c.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/live_view_script_d.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/live_view_style.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/model_runtime.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/model_runtime_cli.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/model_runtime_full_fidelity.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/openai_compatible.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/openai_compatible_cli.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/openai_compatible_full_fidelity.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/opencode_adapter.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/opencode_event_contract.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/opencode_full_fidelity.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/opencode_hook_cli.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/opencode_plugin_cli.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/opencode_record.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/opencode_task_linkage.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/overhead_benchmark.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/provider_capability.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/provider_lifecycle.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/rule_pack.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/rule_pack_cli.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/runtime_endpoint_availability.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/scalability_benchmark.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/schema.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/scope.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/semantic.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/sink.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/strace_backend.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/stream_assembly.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/theme.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/top.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/top_cli.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/validate.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/vendor/dagre.min.js +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/view_cli.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_agent_panel_antigravity.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_agent_panel_claude.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_agent_panel_codex.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_agent_panel_cursor.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_agent_panel_default.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_agent_panel_ollama.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_agent_panel_opencode.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_agent_panel_registry.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_content_inspector.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_dashboard_clean.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_dashboard_focus.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_dashboard_hardening.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_dashboard_hardening_v2.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_dashboard_pr70.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_edge_decross.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_execution_flow.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_execution_flow_provider_normalization.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_execution_flow_safety.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_external_endpoints.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_flow_canvas.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_flow_layout.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_gif.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_layout_geometry.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_layout_v2.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_layout_v2_detached.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_limits.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_live_layout.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_projection.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_projection_base.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_projection_bridges.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_semantic_projection.py +0 -0
- {execweave-0.8.27 → execweave-0.8.29}/src/execweave/viewer_tool_mirror_identity.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: execweave
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.29
|
|
4
4
|
Summary: Turn AI-agent runtime behavior into a local interactive execution graph.
|
|
5
5
|
Project-URL: Homepage, https://github.com/Irish-kw/ExecWeave
|
|
6
6
|
Project-URL: Repository, https://github.com/Irish-kw/ExecWeave
|
|
@@ -388,5 +388,13 @@ Paper context: Li et al., *CAMEL: Communicative Agents for "Mind" Exploration of
|
|
|
388
388
|
|
|
389
389
|
```python
|
|
390
390
|
from execweave.framework_adapters import AdapterContext, CAMELAdapter
|
|
391
|
-
|
|
391
|
+
context = AdapterContext.from_environment("camel", capture_mode="prompt_and_response")
|
|
392
|
+
adapter = CAMELAdapter(context)
|
|
393
|
+
task = adapter.task_created("task-1", content="Inspect the endpoint and report completion.")
|
|
392
394
|
```
|
|
395
|
+
|
|
396
|
+
When the application is launched by `execweave record` or `execweave live`,
|
|
397
|
+
the adapter automatically joins that run and the finished Dashboard is built
|
|
398
|
+
from the merged runtime plus framework evidence. Task prompts and routed
|
|
399
|
+
messages remain local content references and are visible from their task and
|
|
400
|
+
agent nodes.
|
|
@@ -328,5 +328,13 @@ Paper context: Li et al., *CAMEL: Communicative Agents for "Mind" Exploration of
|
|
|
328
328
|
|
|
329
329
|
```python
|
|
330
330
|
from execweave.framework_adapters import AdapterContext, CAMELAdapter
|
|
331
|
-
|
|
331
|
+
context = AdapterContext.from_environment("camel", capture_mode="prompt_and_response")
|
|
332
|
+
adapter = CAMELAdapter(context)
|
|
333
|
+
task = adapter.task_created("task-1", content="Inspect the endpoint and report completion.")
|
|
332
334
|
```
|
|
335
|
+
|
|
336
|
+
When the application is launched by `execweave record` or `execweave live`,
|
|
337
|
+
the adapter automatically joins that run and the finished Dashboard is built
|
|
338
|
+
from the merged runtime plus framework evidence. Task prompts and routed
|
|
339
|
+
messages remain local content references and are visible from their task and
|
|
340
|
+
agent nodes.
|
|
@@ -4,8 +4,8 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "execweave"
|
|
7
|
-
# ExecWeave v0.8.
|
|
8
|
-
version = "0.8.
|
|
7
|
+
# ExecWeave v0.8.29 release metadata
|
|
8
|
+
version = "0.8.29"
|
|
9
9
|
description = "Turn AI-agent runtime behavior into a local interactive execution graph."
|
|
10
10
|
readme = "README.md"
|
|
11
11
|
requires-python = ">=3.10"
|
|
@@ -15,6 +15,7 @@ from .base import (
|
|
|
15
15
|
FrameworkCompatibility,
|
|
16
16
|
MessageRecord,
|
|
17
17
|
ModelCallRecord,
|
|
18
|
+
TaskRecord,
|
|
18
19
|
ToolCallRecord,
|
|
19
20
|
)
|
|
20
21
|
|
|
@@ -26,6 +27,13 @@ class AutoGenAdapter(FrameworkAdapter):
|
|
|
26
27
|
"AGENT_CREATED",
|
|
27
28
|
"AGENT_STARTED",
|
|
28
29
|
"AGENT_STOPPED",
|
|
30
|
+
"TASK_CREATED",
|
|
31
|
+
"TASK_ASSIGNED",
|
|
32
|
+
"TASK_STARTED",
|
|
33
|
+
"TASK_UPDATED",
|
|
34
|
+
"TASK_COMPLETED",
|
|
35
|
+
"TASK_FAILED",
|
|
36
|
+
"TASK_CONTENT_RECORDED",
|
|
29
37
|
"MESSAGE_SENT",
|
|
30
38
|
"MESSAGE_RECEIVED",
|
|
31
39
|
"MODEL_REQUEST",
|
|
@@ -86,6 +94,46 @@ class AutoGenAdapter(FrameworkAdapter):
|
|
|
86
94
|
self.context.record_agent(AgentRecord(agent, role=role, process=process, attributes=attributes))
|
|
87
95
|
return agent
|
|
88
96
|
|
|
97
|
+
def observe_task(
|
|
98
|
+
self,
|
|
99
|
+
task_id: str | int,
|
|
100
|
+
*,
|
|
101
|
+
owner: EntityRef | None = None,
|
|
102
|
+
name: str | None = None,
|
|
103
|
+
content: str | None = None,
|
|
104
|
+
content_kind: str = "task_prompt",
|
|
105
|
+
status: str = "created",
|
|
106
|
+
**attributes: Any,
|
|
107
|
+
) -> EntityRef:
|
|
108
|
+
"""Record an authoritative AutoGen task and its visible task prompt."""
|
|
109
|
+
entity_attributes = dict(attributes)
|
|
110
|
+
if content is not None and self.context.capture_policy.mode in {
|
|
111
|
+
"prompt_only",
|
|
112
|
+
"prompt_and_response",
|
|
113
|
+
}:
|
|
114
|
+
entity_attributes.setdefault("task_prompt", content)
|
|
115
|
+
task = self.task(task_id, name=name, provider="autogen", **entity_attributes)
|
|
116
|
+
event = {
|
|
117
|
+
"created": "TASK_CREATED",
|
|
118
|
+
"started": "TASK_STARTED",
|
|
119
|
+
"updated": "TASK_UPDATED",
|
|
120
|
+
"completed": "TASK_COMPLETED",
|
|
121
|
+
"failed": "TASK_FAILED",
|
|
122
|
+
}.get(status)
|
|
123
|
+
if event is None:
|
|
124
|
+
raise ValueError(f"unsupported AutoGen task status: {status}")
|
|
125
|
+
self.context.record_task(
|
|
126
|
+
TaskRecord(
|
|
127
|
+
task,
|
|
128
|
+
owner=owner,
|
|
129
|
+
content=content,
|
|
130
|
+
content_kind=content_kind,
|
|
131
|
+
attributes=attributes,
|
|
132
|
+
),
|
|
133
|
+
event_type=event,
|
|
134
|
+
)
|
|
135
|
+
return task
|
|
136
|
+
|
|
89
137
|
def observe_message(
|
|
90
138
|
self,
|
|
91
139
|
message_id: str | int,
|
|
@@ -11,6 +11,7 @@ import hashlib
|
|
|
11
11
|
import json
|
|
12
12
|
import os
|
|
13
13
|
import re
|
|
14
|
+
import sys
|
|
14
15
|
import threading
|
|
15
16
|
import time
|
|
16
17
|
from dataclasses import asdict, dataclass, field
|
|
@@ -19,6 +20,8 @@ from pathlib import Path
|
|
|
19
20
|
from typing import Any, Literal, Mapping
|
|
20
21
|
from uuid import uuid4
|
|
21
22
|
|
|
23
|
+
import psutil
|
|
24
|
+
|
|
22
25
|
from ..content_store import ContentReference, FullFidelityContentStore
|
|
23
26
|
from ..schema import SCHEMA_VERSION
|
|
24
27
|
|
|
@@ -33,6 +36,7 @@ CANONICAL_EVENT_TYPES = frozenset(
|
|
|
33
36
|
{
|
|
34
37
|
"AGENT_CREATED", "AGENT_STARTED", "AGENT_STOPPED",
|
|
35
38
|
"TASK_CREATED", "TASK_ASSIGNED", "TASK_STARTED", "TASK_UPDATED",
|
|
39
|
+
"TASK_CONTENT_RECORDED",
|
|
36
40
|
"TASK_COMPLETED", "TASK_FAILED",
|
|
37
41
|
"MESSAGE_SENT", "MESSAGE_RECEIVED", "MESSAGE_UNROUTED",
|
|
38
42
|
"MODEL_REQUEST", "MODEL_RESPONSE", "MODEL_FAILURE",
|
|
@@ -136,6 +140,20 @@ class ProcessRef:
|
|
|
136
140
|
return EntityRef("process_reference", f"process-reference:{identity}", self.executable or f"pid {self.pid}", attributes)
|
|
137
141
|
|
|
138
142
|
|
|
143
|
+
def _current_process_ref() -> ProcessRef:
|
|
144
|
+
"""Return the authoritative identity of the adapter's current process."""
|
|
145
|
+
process = psutil.Process(os.getpid())
|
|
146
|
+
try:
|
|
147
|
+
create_time = process.create_time()
|
|
148
|
+
except (psutil.AccessDenied, psutil.NoSuchProcess, psutil.ZombieProcess):
|
|
149
|
+
create_time = None
|
|
150
|
+
try:
|
|
151
|
+
executable = process.exe()
|
|
152
|
+
except (psutil.AccessDenied, psutil.NoSuchProcess, psutil.ZombieProcess):
|
|
153
|
+
executable = sys.executable
|
|
154
|
+
return ProcessRef(os.getpid(), create_time, executable or sys.executable)
|
|
155
|
+
|
|
156
|
+
|
|
139
157
|
@dataclass(frozen=True)
|
|
140
158
|
class AdapterCapabilities:
|
|
141
159
|
events: tuple[str, ...] = ()
|
|
@@ -298,6 +316,8 @@ class TaskRecord:
|
|
|
298
316
|
task: EntityRef
|
|
299
317
|
owner: EntityRef | None = None
|
|
300
318
|
parent_task: EntityRef | None = None
|
|
319
|
+
content: str | None = None
|
|
320
|
+
content_kind: str = "task_prompt"
|
|
301
321
|
attributes: Mapping[str, Any] = field(default_factory=dict)
|
|
302
322
|
|
|
303
323
|
|
|
@@ -359,6 +379,12 @@ class AdapterContext:
|
|
|
359
379
|
|
|
360
380
|
@classmethod
|
|
361
381
|
def from_environment(cls, framework: str, *, capture_mode: CaptureMode = "metadata_only", content_root: str | Path | None = None, run_id: str | None = None, session_id: str | None = None, conversation_id: str | None = None, process: ProcessRef | None = None) -> "AdapterContext":
|
|
382
|
+
if (
|
|
383
|
+
process is None
|
|
384
|
+
and os.environ.get("EXECWEAVE_SEMANTIC_SIDECAR")
|
|
385
|
+
and os.environ.get("EXECWEAVE_SESSION_ID")
|
|
386
|
+
):
|
|
387
|
+
process = _current_process_ref()
|
|
362
388
|
return cls(framework=framework, run_id=run_id, session_id=session_id, conversation_id=conversation_id, content_root=content_root, capture_policy=ContentCapturePolicy(capture_mode), process=process)
|
|
363
389
|
|
|
364
390
|
def entity(self, entity_type: str, native_id: str | int | None, *, name: str | None = None, attributes: Mapping[str, Any] | None = None) -> EntityRef:
|
|
@@ -391,9 +417,38 @@ class AdapterContext:
|
|
|
391
417
|
return record.agent
|
|
392
418
|
|
|
393
419
|
def record_task(self, record: TaskRecord, *, event_type: str = "TASK_CREATED") -> EntityRef:
|
|
394
|
-
|
|
420
|
+
content_reference = None
|
|
421
|
+
if record.content is not None:
|
|
422
|
+
content_kind = record.content_kind
|
|
423
|
+
if "." not in content_kind:
|
|
424
|
+
content_kind = f"{self.framework}.{content_kind}"
|
|
425
|
+
content_reference = self.content.put_text(record.content, content_kind=content_kind)
|
|
426
|
+
task_attributes = {
|
|
427
|
+
"parent_task_id": record.parent_task.id if record.parent_task else None,
|
|
428
|
+
**self.content.reference_attributes(content_reference),
|
|
429
|
+
**dict(record.attributes),
|
|
430
|
+
}
|
|
431
|
+
self.emit(event_type, event_type, source=record.owner, target=record.task, attributes=task_attributes)
|
|
395
432
|
if record.parent_task is not None:
|
|
396
433
|
self.emit("TASK_CREATED", "PARENT_TASK", source=record.parent_task, target=record.task, attributes={"parent_task_id": record.parent_task.id})
|
|
434
|
+
if content_reference is not None:
|
|
435
|
+
content = EntityRef(
|
|
436
|
+
"observed_content",
|
|
437
|
+
f"observed-content:task:sha256:{content_reference.sha256}",
|
|
438
|
+
content_reference.content_kind,
|
|
439
|
+
content_reference.to_dict(),
|
|
440
|
+
)
|
|
441
|
+
self.emit(
|
|
442
|
+
"TASK_CONTENT_RECORDED",
|
|
443
|
+
"HAS_TASK_CONTENT",
|
|
444
|
+
source=record.task,
|
|
445
|
+
target=content,
|
|
446
|
+
attributes={
|
|
447
|
+
"task_id": record.task.id,
|
|
448
|
+
"conversation_scope": "task",
|
|
449
|
+
**self.content.reference_attributes(content_reference),
|
|
450
|
+
},
|
|
451
|
+
)
|
|
397
452
|
return record.task
|
|
398
453
|
|
|
399
454
|
def record_message(self, record: MessageRecord) -> EntityRef:
|
|
@@ -11,7 +11,7 @@ from .base import AdapterCapabilities, AdapterContext, AgentRecord, EntityRef, F
|
|
|
11
11
|
class CAMELAdapter(FrameworkAdapter):
|
|
12
12
|
framework_name = "camel"
|
|
13
13
|
capabilities = AdapterCapabilities(
|
|
14
|
-
events=("AGENT_CREATED", "AGENT_STARTED", "AGENT_STOPPED", "TASK_CREATED", "TASK_ASSIGNED", "TASK_STARTED", "TASK_UPDATED", "TASK_COMPLETED", "TASK_FAILED", "MESSAGE_SENT", "MESSAGE_RECEIVED", "MESSAGE_UNROUTED", "MODEL_REQUEST", "MODEL_RESPONSE", "MODEL_FAILURE"),
|
|
14
|
+
events=("AGENT_CREATED", "AGENT_STARTED", "AGENT_STOPPED", "TASK_CREATED", "TASK_ASSIGNED", "TASK_STARTED", "TASK_UPDATED", "TASK_COMPLETED", "TASK_FAILED", "TASK_CONTENT_RECORDED", "MESSAGE_SENT", "MESSAGE_RECEIVED", "MESSAGE_UNROUTED", "MODEL_REQUEST", "MODEL_RESPONSE", "MODEL_FAILURE"),
|
|
15
15
|
content_modes=("metadata_only", "content_ref_only", "prompt_only", "prompt_and_response"),
|
|
16
16
|
authoritative_surfaces=("camel.societies.workforce.WorkforceCallback", "camel.models.BaseModelBackend.run", "camel.models.BaseModelBackend.arun"),
|
|
17
17
|
known_limitations=("WorkforceCallback LogEvent does not expose the emitting worker or recipient; those log messages are explicitly marked MESSAGE_UNROUTED and correlated to the observed process instead of being assigned to a guessed agent.", "A created worker is not treated as assigned until CAMEL reports a task assignment."),
|
|
@@ -21,6 +21,7 @@ class CAMELAdapter(FrameworkAdapter):
|
|
|
21
21
|
super().__init__(context)
|
|
22
22
|
self._agents: dict[str, EntityRef] = {}
|
|
23
23
|
self._tasks: dict[str, EntityRef] = {}
|
|
24
|
+
self._active_tasks_by_agent: dict[str, EntityRef] = {}
|
|
24
25
|
self._message_counter = 0
|
|
25
26
|
|
|
26
27
|
@classmethod
|
|
@@ -44,18 +45,43 @@ class CAMELAdapter(FrameworkAdapter):
|
|
|
44
45
|
def agent_stopped(self, agent: EntityRef, **attributes: Any) -> None:
|
|
45
46
|
self.emit("AGENT_STOPPED", "AGENT_STOPPED", source=agent, attributes=attributes)
|
|
46
47
|
|
|
47
|
-
def task_event(self, event_type: str, native_id: str | int, *, name: str | None = None, owner: EntityRef | None = None, parent: EntityRef | None = None, **attributes: Any) -> EntityRef:
|
|
48
|
-
|
|
48
|
+
def task_event(self, event_type: str, native_id: str | int, *, name: str | None = None, owner: EntityRef | None = None, parent: EntityRef | None = None, content: str | None = None, content_kind: str = "task_prompt", **attributes: Any) -> EntityRef:
|
|
49
|
+
existing = self._tasks.get(str(native_id))
|
|
50
|
+
if existing is not None and name is None and content is None and not attributes:
|
|
51
|
+
task = existing
|
|
52
|
+
else:
|
|
53
|
+
entity_attributes = dict(attributes)
|
|
54
|
+
if content is not None and self.context.capture_policy.mode in {
|
|
55
|
+
"prompt_only",
|
|
56
|
+
"prompt_and_response",
|
|
57
|
+
}:
|
|
58
|
+
entity_attributes.setdefault("task_prompt", content)
|
|
59
|
+
task = self.task(native_id, name=name, provider="camel", **entity_attributes)
|
|
49
60
|
self._tasks[str(native_id)] = task
|
|
50
|
-
self.context.record_task(
|
|
61
|
+
self.context.record_task(
|
|
62
|
+
TaskRecord(
|
|
63
|
+
task,
|
|
64
|
+
owner=owner,
|
|
65
|
+
parent_task=parent,
|
|
66
|
+
content=content,
|
|
67
|
+
content_kind=content_kind,
|
|
68
|
+
attributes=attributes,
|
|
69
|
+
),
|
|
70
|
+
event_type=event_type,
|
|
71
|
+
)
|
|
51
72
|
return task
|
|
52
73
|
|
|
53
74
|
def task_created(self, native_id: str | int, **kwargs: Any) -> EntityRef:
|
|
54
75
|
return self.task_event("TASK_CREATED", native_id, **kwargs)
|
|
55
76
|
|
|
56
77
|
def task_assigned(self, task: EntityRef, agent: EntityRef, **attributes: Any) -> None:
|
|
78
|
+
self._active_tasks_by_agent[agent.id] = task
|
|
57
79
|
self.emit("TASK_ASSIGNED", "ASSIGNED_TO", source=task, target=agent, attributes=attributes)
|
|
58
80
|
|
|
81
|
+
def active_task_for(self, agent: EntityRef | None) -> EntityRef | None:
|
|
82
|
+
"""Return the latest provider-observed task assigned to an agent."""
|
|
83
|
+
return self._active_tasks_by_agent.get(agent.id) if agent is not None else None
|
|
84
|
+
|
|
59
85
|
def task_started(self, task: EntityRef, agent: EntityRef | None = None, **attributes: Any) -> None:
|
|
60
86
|
self.emit("TASK_STARTED", "TASK_STARTED", source=agent or task, target=task, attributes=attributes)
|
|
61
87
|
|
|
@@ -170,7 +196,11 @@ class CAMELAdapter(FrameworkAdapter):
|
|
|
170
196
|
if name == "log_worker_created":
|
|
171
197
|
return self.agent_created(_native(payload, "worker_id", "id", "name"), name=_string(_value(payload, "name", "role")), role=_string(_value(payload, "role", "worker_type")))
|
|
172
198
|
if name == "log_task_created":
|
|
173
|
-
|
|
199
|
+
task_key = _native(payload, "task_id", "id", "name")
|
|
200
|
+
existing = self._tasks.get(str(task_key))
|
|
201
|
+
if existing is not None:
|
|
202
|
+
return existing
|
|
203
|
+
return self.task_created(task_key, name=_string(_value(payload, "name", "description")))
|
|
174
204
|
if name == "log_task_assigned":
|
|
175
205
|
task_key = _native(payload, "task_id", "id", "name")
|
|
176
206
|
task = self._tasks.get(str(task_key)) or self.task_created(task_key)
|
|
@@ -30,6 +30,7 @@ class MetaGPTAdapter(FrameworkAdapter):
|
|
|
30
30
|
"TASK_COMPLETED",
|
|
31
31
|
"TASK_FAILED",
|
|
32
32
|
"TASK_UPDATED",
|
|
33
|
+
"TASK_CONTENT_RECORDED",
|
|
33
34
|
"MESSAGE_SENT",
|
|
34
35
|
"MESSAGE_RECEIVED",
|
|
35
36
|
"MODEL_REQUEST",
|
|
@@ -96,10 +97,18 @@ class MetaGPTAdapter(FrameworkAdapter):
|
|
|
96
97
|
*,
|
|
97
98
|
owner: EntityRef | None = None,
|
|
98
99
|
name: str | None = None,
|
|
100
|
+
content: str | None = None,
|
|
101
|
+
content_kind: str = "task_prompt",
|
|
99
102
|
status: str = "created",
|
|
100
103
|
**attributes: Any,
|
|
101
104
|
) -> EntityRef:
|
|
102
|
-
|
|
105
|
+
entity_attributes = dict(attributes)
|
|
106
|
+
if content is not None and self.context.capture_policy.mode in {
|
|
107
|
+
"prompt_only",
|
|
108
|
+
"prompt_and_response",
|
|
109
|
+
}:
|
|
110
|
+
entity_attributes.setdefault("task_prompt", content)
|
|
111
|
+
task = self.task(task_id, name=name, provider="metagpt", **entity_attributes)
|
|
103
112
|
event = {
|
|
104
113
|
"created": "TASK_CREATED",
|
|
105
114
|
"started": "TASK_STARTED",
|
|
@@ -108,7 +117,16 @@ class MetaGPTAdapter(FrameworkAdapter):
|
|
|
108
117
|
}.get(status)
|
|
109
118
|
if event is None:
|
|
110
119
|
raise ValueError(f"unsupported MetaGPT task status: {status}")
|
|
111
|
-
self.context.record_task(
|
|
120
|
+
self.context.record_task(
|
|
121
|
+
TaskRecord(
|
|
122
|
+
task,
|
|
123
|
+
owner=owner,
|
|
124
|
+
content=content,
|
|
125
|
+
content_kind=content_kind,
|
|
126
|
+
attributes=attributes,
|
|
127
|
+
),
|
|
128
|
+
event_type=event,
|
|
129
|
+
)
|
|
112
130
|
return task
|
|
113
131
|
|
|
114
132
|
def observe_message(
|
|
@@ -37,6 +37,8 @@ from .viewer import (
|
|
|
37
37
|
LIVE_DELTA_HISTORY = 256
|
|
38
38
|
LIVE_DELTA_HISTORY_BYTES = 8 * 1024 * 1024
|
|
39
39
|
_SEMANTIC_ENV = "EXECWEAVE_SEMANTIC_SIDECAR"
|
|
40
|
+
_RUN_ID_ENV = "EXECWEAVE_RUN_ID"
|
|
41
|
+
_SESSION_ID_ENV = "EXECWEAVE_SESSION_ID"
|
|
40
42
|
_LIVE_TOKEN_HEADER = "X-ExecWeave-Token"
|
|
41
43
|
|
|
42
44
|
_FINAL_THEME_CSS = """
|
|
@@ -737,16 +739,24 @@ def run_live(
|
|
|
737
739
|
webbrowser.open(authenticated_live_url)
|
|
738
740
|
|
|
739
741
|
return_code = 1
|
|
740
|
-
|
|
741
|
-
|
|
742
|
+
environment_updates = {
|
|
743
|
+
_SEMANTIC_ENV: str(semantic_path),
|
|
744
|
+
_RUN_ID_ENV: session_id,
|
|
745
|
+
_SESSION_ID_ENV: session_id,
|
|
746
|
+
}
|
|
747
|
+
previous_environment = {
|
|
748
|
+
key: os.environ.get(key) for key in environment_updates
|
|
749
|
+
}
|
|
750
|
+
os.environ.update(environment_updates)
|
|
742
751
|
try:
|
|
743
752
|
try:
|
|
744
753
|
return_code = collector.run(command)
|
|
745
754
|
finally:
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
755
|
+
for key, value in previous_environment.items():
|
|
756
|
+
if value is None:
|
|
757
|
+
os.environ.pop(key, None)
|
|
758
|
+
else:
|
|
759
|
+
os.environ[key] = value
|
|
750
760
|
|
|
751
761
|
validation = validate_event_stream(event_path)
|
|
752
762
|
if not validation.valid:
|
|
@@ -372,6 +372,10 @@ function execweaveNodeCardsBase(node){
|
|
|
372
372
|
add('Command',a.command);
|
|
373
373
|
add('Working directory',a.cwd);
|
|
374
374
|
add('Backend',a.backend);
|
|
375
|
+
}else if(kind==='task'){
|
|
376
|
+
add('Task',a.task_prompt||a.prompt||a.description||node?.name);
|
|
377
|
+
add('Prompt',a.task_prompt||a.prompt||a.description);
|
|
378
|
+
add('Provider',a.provider);
|
|
375
379
|
}else if(kind==='network_endpoint'){
|
|
376
380
|
const endpoints=Array.isArray(a.endpoints)?a.endpoints:[];
|
|
377
381
|
if(endpoints.length){
|
|
@@ -414,6 +418,26 @@ function toolOccurrenceSection(node){
|
|
|
414
418
|
});
|
|
415
419
|
return section;
|
|
416
420
|
}
|
|
421
|
+
function execweaveAssignedTaskText(agent){
|
|
422
|
+
if(!agent||String(agent.type||'')!=='agent')return '';
|
|
423
|
+
const graph=rawGraph(),nodes=Array.isArray(graph.nodes)?graph.nodes:[],edges=Array.isArray(graph.edges)?graph.edges:[];
|
|
424
|
+
const nodeMap=new Map(nodes.filter(node=>node&&node.id).map(node=>[String(node.id),node]));
|
|
425
|
+
const exactAssignment=['ASSIGNED','AGENT','TASK'].join('_');
|
|
426
|
+
const direct=edges.filter(edge=>edge&&String(edge.target||'')===String(agent.id||'')&&['ASSIGNED_TO',exactAssignment].includes(String(edge.relation||''))).sort((a,b)=>(Number(a.first_sequence)||0)-(Number(b.first_sequence)||0));
|
|
427
|
+
const owned=edges.filter(edge=>edge&&String(edge.source||'')===String(agent.id||'')&&String(edge.relation||'')==='TASK_CREATED').sort((a,b)=>(Number(a.first_sequence)||0)-(Number(b.first_sequence)||0));
|
|
428
|
+
const started=edges.filter(edge=>edge&&String(edge.source||'')===String(agent.id||'')&&String(edge.relation||'')==='TASK_STARTED').sort((a,b)=>(Number(a.first_sequence)||0)-(Number(b.first_sequence)||0));
|
|
429
|
+
const edge=direct.at(-1)||owned.at(-1)||started.at(-1);if(!edge)return '';
|
|
430
|
+
const taskId=direct.length?edge.source:edge.target,task=nodeMap.get(String(taskId||''));
|
|
431
|
+
if(!task||String(task.type||'')!=='task')return '';
|
|
432
|
+
const a=attrs(task);return commandText(a.task_prompt||a.prompt||a.description||task.name);
|
|
433
|
+
}
|
|
434
|
+
function execweaveFillAssignedTask(round,node,isRoot){
|
|
435
|
+
const task=execweaveAssignedTaskText(node);if(!task)return round;
|
|
436
|
+
const value=round||{cards:[]},cards=Array.isArray(value.cards)?value.cards.map(card=>[card[0],card[1]]):[];
|
|
437
|
+
const label=isRoot?'Prompt':'Task',index=cards.findIndex(card=>String(card[0]||'')===label);
|
|
438
|
+
if(index<0)cards.unshift([label,task]);else if(!commandText(cards[index][1]))cards[index][1]=task;
|
|
439
|
+
return{...value,cards};
|
|
440
|
+
}
|
|
417
441
|
function renderNode(node){
|
|
418
442
|
const rows=nodeCards(node);
|
|
419
443
|
if(!rows.length)return false;
|
|
@@ -432,10 +456,11 @@ function render(node){
|
|
|
432
456
|
selectedNode=node;selectedConversationSignature=conversationSignature(node);detailsEmpty.hidden=true;details.replaceChildren();
|
|
433
457
|
const record=recordFor(node),preview=record?.conversation_preview||{},path=String(preview.agent_path||nodePath(node)||'').trim(),messages=Array.isArray(preview.messages)?preview.messages:[];
|
|
434
458
|
const isRoot=nodeHasRootAuthority(node)||previewUsesRootRenderer(preview);
|
|
435
|
-
const rounds=isRoot?rootRounds(messages,path||'/root'):childRounds(messages,path);
|
|
459
|
+
const rounds=(isRoot?rootRounds(messages,path||'/root'):childRounds(messages,path)).map(round=>execweaveFillAssignedTask(round,node,isRoot));
|
|
436
460
|
const tools=toolCallsFor(String(node.id||''));
|
|
437
|
-
const
|
|
438
|
-
if(
|
|
461
|
+
const frameworkCommunication=attrs(node).conversation_scope==='framework_agent'?uniqueTexts(messages.filter(message=>isObserved(message)&&!isInjected(message)&&String(message?.kind||'')==='agent_message')).join('\n\n'):'';
|
|
462
|
+
const appendTools=()=>{if(frameworkCommunication)details.appendChild(card('Agent communication',frameworkCommunication));if(tools)details.appendChild(card('Tools',tools))};
|
|
463
|
+
if(rounds.length<2){const fallback={cards:isRoot?[['Prompt',''],['Final response','']]:[['Task',''],['Thinking',''],['Response','']]};details.appendChild(roundView(rounds[0]||execweaveFillAssignedTask(fallback,node,isRoot)));appendTools();return true}
|
|
439
464
|
// A subagent borrows the moment and the wording of the unique canonical root round
|
|
440
465
|
// it belongs to. If root identity is ambiguous, the child keeps its own timestamp.
|
|
441
466
|
const runs=isRoot?rounds:runRounds();
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import os
|
|
3
4
|
from dataclasses import dataclass
|
|
4
5
|
from pathlib import Path
|
|
5
6
|
from uuid import uuid4
|
|
@@ -7,11 +8,16 @@ from uuid import uuid4
|
|
|
7
8
|
from .backends import BackendName, create_collector, resolve_backend
|
|
8
9
|
from .fidelity import write_fidelity_report
|
|
9
10
|
from .graph import build_execution_graph, write_execution_graph
|
|
11
|
+
from .semantic import merge_semantic_sidecar
|
|
10
12
|
from .sink import JsonlSink
|
|
11
13
|
from .theme import ensure_viewer_theme
|
|
12
14
|
from .validate import validate_event_stream
|
|
13
15
|
from .viewer_projection import strip_internal_hook_execution_graph, write_graph_html
|
|
14
16
|
|
|
17
|
+
_SEMANTIC_ENV = "EXECWEAVE_SEMANTIC_SIDECAR"
|
|
18
|
+
_RUN_ID_ENV = "EXECWEAVE_RUN_ID"
|
|
19
|
+
_SESSION_ID_ENV = "EXECWEAVE_SESSION_ID"
|
|
20
|
+
|
|
15
21
|
|
|
16
22
|
@dataclass(frozen=True)
|
|
17
23
|
class RecordResult:
|
|
@@ -26,6 +32,9 @@ class RecordResult:
|
|
|
26
32
|
event_count: int
|
|
27
33
|
node_count: int
|
|
28
34
|
edge_count: int
|
|
35
|
+
semantic_sidecar: Path | None = None
|
|
36
|
+
materialized_event_stream: Path | None = None
|
|
37
|
+
semantic_event_count: int = 0
|
|
29
38
|
|
|
30
39
|
def to_dict(self) -> dict[str, object]:
|
|
31
40
|
return {
|
|
@@ -40,6 +49,15 @@ class RecordResult:
|
|
|
40
49
|
"event_count": self.event_count,
|
|
41
50
|
"node_count": self.node_count,
|
|
42
51
|
"edge_count": self.edge_count,
|
|
52
|
+
"semantic_sidecar": (
|
|
53
|
+
str(self.semantic_sidecar) if self.semantic_sidecar is not None else None
|
|
54
|
+
),
|
|
55
|
+
"materialized_event_stream": (
|
|
56
|
+
str(self.materialized_event_stream)
|
|
57
|
+
if self.materialized_event_stream is not None
|
|
58
|
+
else str(self.event_stream)
|
|
59
|
+
),
|
|
60
|
+
"semantic_event_count": self.semantic_event_count,
|
|
43
61
|
}
|
|
44
62
|
|
|
45
63
|
|
|
@@ -61,6 +79,7 @@ def record_to_viewer(
|
|
|
61
79
|
collect_network: bool = True,
|
|
62
80
|
keep_raw_trace: bool = False,
|
|
63
81
|
open_browser: bool = False,
|
|
82
|
+
integrate_semantic: bool = True,
|
|
64
83
|
) -> RecordResult:
|
|
65
84
|
"""Record one command and materialize a local graph/viewer after it exits."""
|
|
66
85
|
if not command:
|
|
@@ -79,7 +98,12 @@ def record_to_viewer(
|
|
|
79
98
|
fidelity_path = run_dir / "fidelity.json"
|
|
80
99
|
graph_path = run_dir / "graph.json"
|
|
81
100
|
viewer_path = run_dir / "viewer.html"
|
|
82
|
-
|
|
101
|
+
semantic_path = run_dir / "semantic.jsonl"
|
|
102
|
+
merged_event_path = run_dir / "events.semantic.jsonl"
|
|
103
|
+
artifacts = [event_path, fidelity_path, graph_path, viewer_path]
|
|
104
|
+
if integrate_semantic:
|
|
105
|
+
artifacts.extend([semantic_path, merged_event_path])
|
|
106
|
+
_preflight_artifacts(artifacts)
|
|
83
107
|
|
|
84
108
|
sink = JsonlSink(event_path)
|
|
85
109
|
resolved = resolve_backend(backend)
|
|
@@ -94,14 +118,44 @@ def record_to_viewer(
|
|
|
94
118
|
keep_raw_trace=keep_raw_trace,
|
|
95
119
|
)
|
|
96
120
|
|
|
97
|
-
|
|
121
|
+
environment_updates = {
|
|
122
|
+
_RUN_ID_ENV: session_id,
|
|
123
|
+
_SESSION_ID_ENV: session_id,
|
|
124
|
+
}
|
|
125
|
+
if integrate_semantic:
|
|
126
|
+
environment_updates[_SEMANTIC_ENV] = str(semantic_path)
|
|
127
|
+
previous_environment = {
|
|
128
|
+
key: os.environ.get(key) for key in environment_updates
|
|
129
|
+
}
|
|
130
|
+
os.environ.update(environment_updates)
|
|
131
|
+
try:
|
|
132
|
+
return_code = collector.run(command)
|
|
133
|
+
finally:
|
|
134
|
+
for key, value in previous_environment.items():
|
|
135
|
+
if value is None:
|
|
136
|
+
os.environ.pop(key, None)
|
|
137
|
+
else:
|
|
138
|
+
os.environ[key] = value
|
|
98
139
|
|
|
99
140
|
validation = validate_event_stream(event_path)
|
|
100
141
|
if not validation.valid:
|
|
101
142
|
details = "; ".join(validation.errors)
|
|
102
143
|
raise RuntimeError(f"recorded event stream failed validation: {details}")
|
|
103
144
|
|
|
104
|
-
|
|
145
|
+
materialized_event_path = event_path
|
|
146
|
+
semantic_event_count = 0
|
|
147
|
+
if integrate_semantic and semantic_path.exists() and semantic_path.stat().st_size > 0:
|
|
148
|
+
semantic_merge = merge_semantic_sidecar(
|
|
149
|
+
event_path,
|
|
150
|
+
semantic_path,
|
|
151
|
+
merged_event_path,
|
|
152
|
+
)
|
|
153
|
+
materialized_event_path = merged_event_path
|
|
154
|
+
semantic_event_count = semantic_merge.semantic_event_count
|
|
155
|
+
|
|
156
|
+
execution_graph = strip_internal_hook_execution_graph(
|
|
157
|
+
build_execution_graph(materialized_event_path)
|
|
158
|
+
)
|
|
105
159
|
write_fidelity_report(execution_graph.fidelity, fidelity_path)
|
|
106
160
|
write_execution_graph(execution_graph, graph_path)
|
|
107
161
|
write_graph_html(execution_graph.to_dict(), viewer_path, open_browser=False)
|
|
@@ -123,4 +177,7 @@ def record_to_viewer(
|
|
|
123
177
|
event_count=execution_graph.event_count,
|
|
124
178
|
node_count=len(execution_graph.nodes),
|
|
125
179
|
edge_count=len(execution_graph.edges),
|
|
180
|
+
semantic_sidecar=semantic_path.resolve() if integrate_semantic else None,
|
|
181
|
+
materialized_event_stream=materialized_event_path.resolve(),
|
|
182
|
+
semantic_event_count=semantic_event_count,
|
|
126
183
|
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{execweave-0.8.27 → execweave-0.8.29}/src/execweave/antigravity_full_fidelity_collaboration_base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|