voidx 2.0.6__tar.gz → 2.1.1__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.
- {voidx-2.0.6 → voidx-2.1.1}/PKG-INFO +1 -1
- {voidx-2.0.6 → voidx-2.1.1}/pyproject.toml +4 -1
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/__init__.py +1 -1
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/agents.py +55 -21
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/graph/compaction.py +69 -57
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/graph/contracts.py +28 -11
- voidx-2.1.1/src/voidx/agent/graph/convergence.py +169 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/graph/core.py +299 -131
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/graph/permissions.py +1 -2
- voidx-2.1.1/src/voidx/agent/graph/run_loop.py +304 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/graph/runtime.py +1 -3
- voidx-2.1.1/src/voidx/agent/graph/session_mixin.py +60 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/graph/streaming.py +5 -2
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/graph/subagent.py +70 -17
- voidx-2.1.1/src/voidx/agent/graph/title_mixin.py +211 -0
- voidx-2.1.1/src/voidx/agent/graph/todo_events.py +21 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/graph/tool_execution.py +116 -11
- voidx-2.1.1/src/voidx/agent/graph/topology.py +95 -0
- voidx-2.1.1/src/voidx/agent/graph/transcript_mixin.py +34 -0
- voidx-2.1.1/src/voidx/agent/graph/turn_mixin.py +422 -0
- voidx-2.1.1/src/voidx/agent/graph/wiring.py +105 -0
- voidx-2.1.1/src/voidx/agent/message_rows.py +99 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/runtime_context.py +236 -101
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/slash/code_ide.py +1 -1
- voidx-2.1.1/src/voidx/agent/slash/guide.py +19 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/slash/handler.py +301 -149
- voidx-2.1.1/src/voidx/agent/slash/init.py +95 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/slash/lsp.py +7 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/slash/mcp.py +32 -2
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/slash/model.py +0 -20
- voidx-2.1.1/src/voidx/agent/slash/profile.py +161 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/slash/runtime.py +22 -0
- voidx-2.1.1/src/voidx/agent/slash/session.py +239 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/state.py +1 -0
- voidx-2.1.1/src/voidx/agent/task_state.py +23 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/tool_filters.py +2 -5
- voidx-2.1.1/src/voidx/config/__init__.py +47 -0
- voidx-2.1.1/src/voidx/config/cli.py +1 -0
- voidx-2.1.1/src/voidx/config/enums.py +60 -0
- voidx-2.1.1/src/voidx/config/models.py +145 -0
- voidx-2.1.1/src/voidx/config/permissions.py +24 -0
- voidx-2.1.1/src/voidx/config/settings.py +327 -0
- voidx-2.1.1/src/voidx/config/settings_agent.py +34 -0
- voidx-2.1.1/src/voidx/config/settings_api_keys.py +53 -0
- voidx-2.1.1/src/voidx/config/settings_code_ide.py +21 -0
- voidx-2.1.1/src/voidx/config/settings_custom.py +70 -0
- voidx-2.1.1/src/voidx/config/settings_mcp.py +65 -0
- voidx-2.1.1/src/voidx/config/settings_permissions.py +86 -0
- voidx-2.1.1/src/voidx/config/settings_skills.py +52 -0
- voidx-2.1.1/src/voidx/config/settings_utils.py +9 -0
- voidx-2.1.1/src/voidx/config/settings_web.py +42 -0
- voidx-2.1.1/src/voidx/data/__init__.py +1 -0
- voidx-2.1.1/src/voidx/data/intent_classifier.json +1 -0
- voidx-2.0.6/src/voidx/ui/output/diff.py → voidx-2.1.1/src/voidx/diffing.py +37 -141
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/llm/catalog.py +3 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/llm/compaction.py +218 -26
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/llm/instruction.py +28 -1
- voidx-2.1.1/src/voidx/llm/message_markers.py +14 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/llm/provider.py +8 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/lsp/detector.py +8 -125
- voidx-2.1.1/src/voidx/lsp/detector_data.py +130 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/lsp/manager.py +62 -2
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/lsp/schema.py +1 -1
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/main.py +9 -4
- voidx-2.1.1/src/voidx/mcp/client/__init__.py +11 -0
- voidx-2.1.1/src/voidx/mcp/client/base.py +352 -0
- voidx-2.1.1/src/voidx/mcp/client/errors.py +15 -0
- voidx-2.1.1/src/voidx/mcp/client/http_transport.py +120 -0
- voidx-2.1.1/src/voidx/mcp/client/sse_transport.py +151 -0
- voidx-2.1.1/src/voidx/mcp/client/stdio_transport.py +114 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/memory/context_frames.py +1 -1
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/memory/runtime_state.py +21 -4
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/memory/session.py +38 -3
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/memory/store.py +2 -0
- voidx-2.1.1/src/voidx/permission/context.py +59 -0
- voidx-2.1.1/src/voidx/permission/engine.py +183 -0
- voidx-2.0.6/src/voidx/permission/engine.py → voidx-2.1.1/src/voidx/permission/rules.py +25 -222
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/permission/service.py +17 -16
- voidx-2.1.1/src/voidx/runtime/__init__.py +39 -0
- voidx-2.1.1/src/voidx/runtime/intent.py +96 -0
- voidx-2.1.1/src/voidx/runtime/intent_classifier.py +262 -0
- {voidx-2.0.6/src/voidx/agent → voidx-2.1.1/src/voidx/runtime}/task_state.py +80 -23
- voidx-2.1.1/src/voidx/runtime/ui.py +247 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/skills/bundled/superpowers/brainstorming/SKILL.md +1 -1
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/skills/registry.py +26 -2
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/tools/agent.py +44 -15
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/tools/base.py +1 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/tools/bash.py +1 -1
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/tools/clarify.py +12 -3
- voidx-2.1.1/src/voidx/tools/file_ops.py +618 -0
- voidx-2.1.1/src/voidx/tools/git.py +644 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/tools/lsp.py +1 -1
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/tools/on_intent.py +1 -2
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/tools/plan_checkpoint.py +6 -3
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/tools/registry.py +20 -2
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/tools/task_tracker.py +1 -1
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/tools/todo.py +8 -1
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/commands.py +13 -0
- voidx-2.1.1/src/voidx/ui/output/agent_display.py +25 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/output/capture.py +5 -1
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/output/console/formatting.py +3 -1
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/output/console/streaming.py +42 -86
- voidx-2.1.1/src/voidx/ui/output/diff.py +130 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/output/dock/app.py +3 -176
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/output/dock/nodes.py +8 -157
- voidx-2.1.1/src/voidx/ui/output/dock/nodes_permission.py +50 -0
- voidx-2.1.1/src/voidx/ui/output/dock/nodes_startup.py +60 -0
- voidx-2.1.1/src/voidx/ui/output/dock/nodes_status.py +79 -0
- voidx-2.1.1/src/voidx/ui/output/dock/status.py +66 -0
- voidx-2.1.1/src/voidx/ui/output/dock/stream.py +153 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/output/events/__init__.py +100 -10
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/output/events/schema.py +24 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/output/tree.py +63 -3
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/session.py +39 -2
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/tools/__init__.py +3 -0
- voidx-2.1.1/src/voidx/ui/tools/clipboard_text.py +72 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/transcript.py +1 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/tui/app.py +154 -248
- voidx-2.1.1/src/voidx/ui/tui/choice_mixin.py +48 -0
- voidx-2.1.1/src/voidx/ui/tui/clipboard_mixin.py +83 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/tui/input.py +114 -2
- voidx-2.1.1/src/voidx/ui/tui/overlays.py +113 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/tui/parser.py +28 -11
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/tui/renderer.py +116 -124
- voidx-2.1.1/src/voidx/ui/tui/state.py +201 -0
- voidx-2.1.1/src/voidx/ui/tui/terminal_mixin.py +42 -0
- voidx-2.1.1/src/voidx/ui/tui/text_prompt_mixin.py +49 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx.egg-info/PKG-INFO +1 -1
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx.egg-info/SOURCES.txt +65 -2
- voidx-2.1.1/tests/test_clipboard_text.py +22 -0
- {voidx-2.0.6 → voidx-2.1.1}/tests/test_compaction.py +270 -2
- {voidx-2.0.6 → voidx-2.1.1}/tests/test_config.py +141 -2
- voidx-2.1.1/tests/test_instruction_cache.py +31 -0
- voidx-2.1.1/tests/test_intent_classifier_phase_a.py +159 -0
- {voidx-2.0.6 → voidx-2.1.1}/tests/test_lsp.py +100 -1
- voidx-2.1.1/tests/test_main_startup.py +129 -0
- {voidx-2.0.6 → voidx-2.1.1}/tests/test_npm_package.py +2 -2
- {voidx-2.0.6 → voidx-2.1.1}/tests/test_pure_tui.py +416 -14
- voidx-2.1.1/tests/test_runtime_intent_classifier.py +166 -0
- voidx-2.1.1/tests/test_runtime_ui.py +71 -0
- {voidx-2.0.6 → voidx-2.1.1}/tests/test_skills.py +34 -0
- {voidx-2.0.6 → voidx-2.1.1}/tests/test_tree_smoke.py +71 -0
- {voidx-2.0.6 → voidx-2.1.1}/tests/test_ui_events.py +241 -8
- {voidx-2.0.6 → voidx-2.1.1}/tests/test_ui_gateway.py +38 -0
- {voidx-2.0.6 → voidx-2.1.1}/tests/test_ui_session_changes.py +85 -0
- voidx-2.0.6/src/voidx/agent/graph/run_loop.py +0 -673
- voidx-2.0.6/src/voidx/agent/message_rows.py +0 -36
- voidx-2.0.6/src/voidx/config.py +0 -737
- voidx-2.0.6/src/voidx/mcp/client.py +0 -723
- voidx-2.0.6/src/voidx/tools/file_ops.py +0 -208
- {voidx-2.0.6 → voidx-2.1.1}/README.md +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/setup.cfg +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/__init__.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/attachments.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/graph/__init__.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/intent_refinement.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/slash/__init__.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/slash/skills.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/agent/tool_messages.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/llm/__init__.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/llm/context.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/llm/usage.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/lsp/__init__.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/lsp/client.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/lsp/config.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/lsp/errors.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/lsp/service.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/mcp/__init__.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/mcp/manager.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/mcp/schema.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/mcp/tool.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/mcp_servers/__init__.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/mcp_servers/web.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/memory/__init__.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/memory/model_profiles.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/memory/transcript.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/permission/__init__.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/permission/evaluate.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/permission/sandbox.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/permission/schema.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/permission/wildcard.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/skills/__init__.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/skills/bundled/superpowers/receiving-code-review/SKILL.md +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/skills/bundled/superpowers/requesting-code-review/SKILL.md +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/skills/bundled/superpowers/systematic-debugging/SKILL.md +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/skills/bundled/superpowers/test-driven-development/SKILL.md +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/skills/bundled/superpowers/verification-before-completion/SKILL.md +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/skills/bundled/superpowers/writing-design-docs/SKILL.md +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/skills/bundled/superpowers/writing-design-docs/templates/api-doc.md +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/skills/bundled/superpowers/writing-design-docs/templates/prd.md +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/skills/bundled/superpowers/writing-design-docs/templates/readme.md +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/skills/bundled/superpowers/writing-design-docs/templates/rfc.md +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/skills/bundled/superpowers/writing-design-docs/templates/tech-design.md +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/skills/bundled/superpowers/writing-plans/SKILL.md +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/skills/policy.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/skills/runtime.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/skills/schema.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/skills/service.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/tools/__init__.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/tools/doc_template.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/tools/repomap.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/tools/search.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/tools/task_status.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/tools/web_content.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/tools/web_mcp.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/tools/webfetch.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/tools/websearch.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/__init__.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/frontend.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/gateway/__init__.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/gateway/bootstrap.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/gateway/server.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/gateway/session.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/output/__init__.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/output/browse.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/output/console/__init__.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/output/console/app.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/output/dock/__init__.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/output/dock/formatting.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/output/dock/state.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/output/types.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/protocol/__init__.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/protocol/commands.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/protocol/envelope.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/protocol/requests.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/protocol/schema.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/protocol/transcript.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/tools/attachment_tokens.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/tools/clipboard_image.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/tools/code_ide.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/tools/file_picker.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/tui/__init__.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/tui/helpers.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx/ui/tui/panels.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx.egg-info/dependency_links.txt +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx.egg-info/entry_points.txt +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx.egg-info/requires.txt +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/src/voidx.egg-info/top_level.txt +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/tests/test_clipboard_image.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/tests/test_code_ide.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/tests/test_llm_provider.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/tests/test_llm_usage.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/tests/test_main.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/tests/test_mcp.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/tests/test_scrollback_flush.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/tests/test_startup.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/tests/test_ui_diff.py +0 -0
- {voidx-2.0.6 → voidx-2.1.1}/tests/test_ui_frontend_protocol.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "voidx"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.1.1"
|
|
4
4
|
description = "A coding agent that quantifies everything and solves with tools, not fuzzy prompts."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -47,6 +47,9 @@ where = ["src"]
|
|
|
47
47
|
"bundled/superpowers/*/SKILL.md",
|
|
48
48
|
"bundled/superpowers/*/templates/*.md",
|
|
49
49
|
]
|
|
50
|
+
"voidx.data" = [
|
|
51
|
+
"intent_classifier.json",
|
|
52
|
+
]
|
|
50
53
|
|
|
51
54
|
[tool.pytest.ini_options]
|
|
52
55
|
asyncio_mode = "auto"
|
|
@@ -47,6 +47,7 @@ BASE_SYSTEM_PROMPT = """You are voidx, a coding agent that lives in the terminal
|
|
|
47
47
|
- Do not expose internal role names unless the user asks about architecture.
|
|
48
48
|
- Never claim work is complete until it has been verified.
|
|
49
49
|
|
|
50
|
+
|
|
50
51
|
## Workflow Skills
|
|
51
52
|
|
|
52
53
|
- voidx may activate workflow skills such as systematic-debugging,
|
|
@@ -55,12 +56,6 @@ BASE_SYSTEM_PROMPT = """You are voidx, a coding agent that lives in the terminal
|
|
|
55
56
|
- The Current Task State lists active workflow skills for this turn.
|
|
56
57
|
- The Active Skills section contains the full instructions for active skills.
|
|
57
58
|
- Follow active workflow skills before acting.
|
|
58
|
-
|
|
59
|
-
## Parallel Execution
|
|
60
|
-
|
|
61
|
-
- Multiple tool calls in one model response run in parallel.
|
|
62
|
-
- Tool calls across separate model responses run sequentially.
|
|
63
|
-
- Batch independent reads/searches together; keep dependent work sequential.
|
|
64
59
|
"""
|
|
65
60
|
|
|
66
61
|
|
|
@@ -103,7 +98,7 @@ surgical edits directly when that is the shortest safe path.
|
|
|
103
98
|
running write-capable commands, or delegating implement.
|
|
104
99
|
|
|
105
100
|
4. **Code changes**
|
|
106
|
-
- Small, local, or mechanical changes → read first, then call write/edit
|
|
101
|
+
- Small, local, or mechanical changes → read first, then call write/edit/apply_patch
|
|
107
102
|
yourself and verify.
|
|
108
103
|
- If investigation finds a concrete edit but the user asked only to inspect,
|
|
109
104
|
design, or review, stop and report the proposed change. Ask for
|
|
@@ -127,12 +122,6 @@ surgical edits directly when that is the shortest safe path.
|
|
|
127
122
|
approval or clarification, call plan_checkpoint or clarify yourself.
|
|
128
123
|
- Don't tell the user "done" until changes are verified.
|
|
129
124
|
- Child agents have isolated context — give them complete, self-contained briefs.
|
|
130
|
-
|
|
131
|
-
## Parallel Execution
|
|
132
|
-
- Multiple tool calls in ONE response → they run in parallel.
|
|
133
|
-
- Tool calls across SEPARATE responses → they run sequentially.
|
|
134
|
-
- Batch independent work: read 3 files at once, search + fetch in the same step.
|
|
135
|
-
- Sequential work: search first, then read based on what you found.
|
|
136
125
|
"""
|
|
137
126
|
|
|
138
127
|
# Plan mode prompt — injected when plan_mode=True
|
|
@@ -199,7 +188,7 @@ You are the dedicated executor for broad or isolated implementation tasks.
|
|
|
199
188
|
|
|
200
189
|
## Rules
|
|
201
190
|
- Read before writing. Never guess file contents.
|
|
202
|
-
- Make minimal, precise edits. Use edit with exact old_string matches.
|
|
191
|
+
- Make minimal, precise edits. Use edit with exact old_string matches, or apply_patch for unified diffs and multi-file changes.
|
|
203
192
|
- Follow the plan if one was provided.
|
|
204
193
|
- Run tests/bash after changes to verify.
|
|
205
194
|
- Return: what files were changed, what was done, any issues encountered.
|
|
@@ -260,6 +249,13 @@ class AgentDef(BaseModel):
|
|
|
260
249
|
max_steps: int = 25
|
|
261
250
|
hidden: bool = False # hidden from user-facing lists?
|
|
262
251
|
model: str | None = None # None = inherit from parent
|
|
252
|
+
mcp_tools: bool = False # can see registered MCP tools
|
|
253
|
+
|
|
254
|
+
def with_max_steps(self, value: int) -> "AgentDef":
|
|
255
|
+
"""Return a copy with max_steps overridden."""
|
|
256
|
+
if value == self.max_steps:
|
|
257
|
+
return self
|
|
258
|
+
return self.model_copy(update={"max_steps": value})
|
|
263
259
|
|
|
264
260
|
@property
|
|
265
261
|
def role_prompt(self) -> str:
|
|
@@ -282,6 +278,8 @@ class AgentDef(BaseModel):
|
|
|
282
278
|
lines.append(f"- Available tools: {', '.join(self.tools)}")
|
|
283
279
|
else:
|
|
284
280
|
lines.append("- Available tools: none")
|
|
281
|
+
if self.mcp_tools:
|
|
282
|
+
lines.append("- MCP tools: available when configured; each call is permission-gated")
|
|
285
283
|
if not self.can_write:
|
|
286
284
|
lines.append("- Constraint: this role must not write or edit files.")
|
|
287
285
|
if not self.can_delegate:
|
|
@@ -298,6 +296,39 @@ ROLE_PROMPTS = {
|
|
|
298
296
|
PROMPTLESS_AGENTS = {"compaction", "title"}
|
|
299
297
|
|
|
300
298
|
|
|
299
|
+
def role_prompt_for_llm(agent: AgentDef, *, parallel_subagents_enabled: bool = False) -> str:
|
|
300
|
+
"""Return the role prompt with runtime-gated child-agent scheduling rules."""
|
|
301
|
+
|
|
302
|
+
prompt = agent.role_prompt
|
|
303
|
+
if agent.name != "orchestrator":
|
|
304
|
+
return prompt
|
|
305
|
+
child_agent_prompt = _parallel_subagents_prompt(
|
|
306
|
+
enabled=parallel_subagents_enabled,
|
|
307
|
+
)
|
|
308
|
+
if not prompt:
|
|
309
|
+
return child_agent_prompt
|
|
310
|
+
return f"{prompt.rstrip()}\n\n{child_agent_prompt}"
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
def _parallel_subagents_prompt(*, enabled: bool) -> str:
|
|
314
|
+
if enabled:
|
|
315
|
+
return """## Child-Agent Scheduling
|
|
316
|
+
|
|
317
|
+
- For independent child-agent tasks, you may issue multiple `agent` tool calls
|
|
318
|
+
in one response. They will run concurrently up to the configured limit.
|
|
319
|
+
- Each child-agent brief must be complete and self-contained.
|
|
320
|
+
- Keep dependent child-agent work sequential: wait for the result before
|
|
321
|
+
delegating follow-up work that depends on it.
|
|
322
|
+
- Batch independent read/search tools when useful; keep dependent tool work
|
|
323
|
+
sequential."""
|
|
324
|
+
return """## Child-Agent Scheduling
|
|
325
|
+
|
|
326
|
+
- Delegate at most one child agent in a response. Wait for that result before
|
|
327
|
+
deciding whether another child agent is needed.
|
|
328
|
+
- Batch independent non-agent read/search tools when useful; keep dependent
|
|
329
|
+
work sequential."""
|
|
330
|
+
|
|
331
|
+
|
|
301
332
|
# ── built-in agents ────────────────────────────────────────────────────────
|
|
302
333
|
|
|
303
334
|
BUILTIN_AGENTS: dict[str, AgentDef] = {
|
|
@@ -311,12 +342,13 @@ BUILTIN_AGENTS: dict[str, AgentDef] = {
|
|
|
311
342
|
"read", "glob", "grep", "bash", "agent", "task_status", "todo",
|
|
312
343
|
"webfetch", "websearch", "repo_map",
|
|
313
344
|
"lsp_diagnostics", "lsp_symbols", "lsp_definition", "lsp_references",
|
|
314
|
-
"write", "edit", "lsp_format",
|
|
345
|
+
"write", "edit", "apply_patch", "lsp_format",
|
|
315
346
|
],
|
|
316
347
|
can_write=True,
|
|
317
348
|
can_delegate=True,
|
|
318
|
-
max_steps=
|
|
349
|
+
max_steps=100,
|
|
319
350
|
hidden=False,
|
|
351
|
+
mcp_tools=True,
|
|
320
352
|
),
|
|
321
353
|
"explore": AgentDef(
|
|
322
354
|
name="explore",
|
|
@@ -331,7 +363,7 @@ BUILTIN_AGENTS: dict[str, AgentDef] = {
|
|
|
331
363
|
],
|
|
332
364
|
can_write=False,
|
|
333
365
|
can_delegate=False,
|
|
334
|
-
max_steps=
|
|
366
|
+
max_steps=25,
|
|
335
367
|
hidden=False,
|
|
336
368
|
|
|
337
369
|
),
|
|
@@ -347,7 +379,7 @@ BUILTIN_AGENTS: dict[str, AgentDef] = {
|
|
|
347
379
|
],
|
|
348
380
|
can_write=False,
|
|
349
381
|
can_delegate=False,
|
|
350
|
-
max_steps=
|
|
382
|
+
max_steps=30,
|
|
351
383
|
hidden=False,
|
|
352
384
|
),
|
|
353
385
|
"implement": AgentDef(
|
|
@@ -356,13 +388,13 @@ BUILTIN_AGENTS: dict[str, AgentDef] = {
|
|
|
356
388
|
when_to_use="Use for all code writing, file editing, refactoring, bug fixing, "
|
|
357
389
|
"and bash execution. Give complete, self-contained task descriptions.",
|
|
358
390
|
tools=[
|
|
359
|
-
"read", "write", "edit", "glob", "grep", "bash", "todo", "repo_map",
|
|
391
|
+
"read", "write", "edit", "apply_patch", "glob", "grep", "bash", "todo", "repo_map",
|
|
360
392
|
"lsp_diagnostics", "lsp_symbols", "lsp_definition", "lsp_references",
|
|
361
393
|
"lsp_format",
|
|
362
394
|
],
|
|
363
395
|
can_write=True,
|
|
364
396
|
can_delegate=False,
|
|
365
|
-
max_steps=
|
|
397
|
+
max_steps=100,
|
|
366
398
|
hidden=False,
|
|
367
399
|
),
|
|
368
400
|
"review": AgentDef(
|
|
@@ -377,7 +409,7 @@ BUILTIN_AGENTS: dict[str, AgentDef] = {
|
|
|
377
409
|
],
|
|
378
410
|
can_write=False,
|
|
379
411
|
can_delegate=False,
|
|
380
|
-
max_steps=
|
|
412
|
+
max_steps=30,
|
|
381
413
|
hidden=False,
|
|
382
414
|
),
|
|
383
415
|
# ── hidden agents (not user-visible, internal only) ───────────────
|
|
@@ -435,6 +467,8 @@ def child_agent_descriptions_for_llm() -> str:
|
|
|
435
467
|
lines = ["Available child agents and the tools they have access to:"]
|
|
436
468
|
for agent in get_subagents():
|
|
437
469
|
tools_str = ", ".join(agent.tools)
|
|
470
|
+
if agent.mcp_tools:
|
|
471
|
+
tools_str = f"{tools_str}, MCP tools" if tools_str else "MCP tools"
|
|
438
472
|
lines.append(
|
|
439
473
|
f"- {agent.name}: {agent.description}\n"
|
|
440
474
|
f" Tools: {tools_str}\n"
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import logging
|
|
5
6
|
from typing import TYPE_CHECKING
|
|
6
7
|
|
|
7
|
-
from langchain_core.messages import
|
|
8
|
+
from langchain_core.messages import HumanMessage, SystemMessage
|
|
8
9
|
|
|
9
10
|
from voidx.agent.message_rows import messages_from_rows
|
|
10
11
|
from voidx.agent.graph.runtime import console, ui
|
|
@@ -13,14 +14,22 @@ from voidx.llm.compaction import COMPACTION_MAX_RETRIES, CompactionService
|
|
|
13
14
|
from voidx.llm.provider import resolve_protocol
|
|
14
15
|
from voidx.llm.usage import estimate_context_tokens, estimate_message_tokens, extract_token_usage
|
|
15
16
|
from voidx.memory.context_frames import save_context_frame_from_messages
|
|
16
|
-
from voidx.ui
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
from voidx.runtime.ui import (
|
|
18
|
+
StatusFinished,
|
|
19
|
+
StatusUpdated,
|
|
20
|
+
StreamingRenderer,
|
|
21
|
+
dock,
|
|
22
|
+
ui_events,
|
|
23
|
+
via_events,
|
|
24
|
+
)
|
|
19
25
|
|
|
20
26
|
if TYPE_CHECKING:
|
|
21
27
|
from voidx.agent.graph.contracts import GraphCompactionHost
|
|
22
28
|
|
|
23
29
|
|
|
30
|
+
logger = logging.getLogger(__name__)
|
|
31
|
+
|
|
32
|
+
|
|
24
33
|
class GraphCompactionMixin:
|
|
25
34
|
async def _maybe_compact(
|
|
26
35
|
self: GraphCompactionHost,
|
|
@@ -33,8 +42,7 @@ class GraphCompactionMixin:
|
|
|
33
42
|
"""Check overflow and compact if needed.
|
|
34
43
|
|
|
35
44
|
Returns the messages removed from the live context and the persisted
|
|
36
|
-
tail anchor id when
|
|
37
|
-
tail anchor, so it returns None for the second value.
|
|
45
|
+
tail anchor id when compaction removes an older complete turn.
|
|
38
46
|
"""
|
|
39
47
|
total_tokens = estimate_context_tokens(messages, self.config.model.model)
|
|
40
48
|
tokens = {"total": total_tokens, "input": total_tokens, "output": 0, "reasoning": 0}
|
|
@@ -73,40 +81,23 @@ class GraphCompactionMixin:
|
|
|
73
81
|
else "[yellow]Compacting context...[/yellow]"
|
|
74
82
|
)
|
|
75
83
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if not head_msgs or not tail_id:
|
|
79
|
-
# Hard fallback: keep only last 6 messages
|
|
80
|
-
keep = min(6, len(messages))
|
|
81
|
-
if via_events():
|
|
82
|
-
await ui_events.emit(StatusUpdated(
|
|
83
|
-
status_id="compaction",
|
|
84
|
-
label="Compacting context",
|
|
85
|
-
detail=f"fallback truncation, keeping last {keep} messages",
|
|
86
|
-
stage="compacting",
|
|
87
|
-
))
|
|
88
|
-
else:
|
|
89
|
-
ui.print(f"[dim]Aggressive truncation: keeping last {keep} messages[/dim]")
|
|
90
|
-
|
|
91
|
-
removed = _truncate_to_recent_messages(messages, keep)
|
|
92
|
-
# Generate a basic summary from the removed messages
|
|
93
|
-
fallback = CompactionService.fallback_summary(removed)
|
|
94
|
-
self._pending_summary = fallback
|
|
95
|
-
self._compaction_summary = fallback
|
|
96
|
-
self._compaction.compaction_count += 1
|
|
84
|
+
selection = self._compaction.select_details(messages)
|
|
85
|
+
head_msgs, tail_id = selection.head, selection.tail_id
|
|
97
86
|
|
|
87
|
+
if not selection.should_compact:
|
|
98
88
|
if via_events():
|
|
99
89
|
await ui_events.emit(StatusFinished(
|
|
100
90
|
status_id="compaction",
|
|
101
|
-
label=
|
|
91
|
+
label="Compaction skipped: no older complete turn to summarize",
|
|
102
92
|
remove=False,
|
|
103
93
|
))
|
|
104
|
-
return
|
|
94
|
+
return None, None
|
|
105
95
|
|
|
106
96
|
# Run compaction agent with retries
|
|
107
97
|
summary = None
|
|
108
98
|
previous_summary = getattr(self, "_compaction_summary", "") or None
|
|
109
99
|
last_error: Exception | None = None
|
|
100
|
+
returned_no_summary = False
|
|
110
101
|
|
|
111
102
|
for attempt in range(1, COMPACTION_MAX_RETRIES + 2): # 1 initial + N retries
|
|
112
103
|
try:
|
|
@@ -121,8 +112,11 @@ class GraphCompactionMixin:
|
|
|
121
112
|
summary = await self._run_compaction_agent(head_msgs, previous_summary)
|
|
122
113
|
if summary:
|
|
123
114
|
break
|
|
115
|
+
returned_no_summary = True
|
|
116
|
+
last_error = None
|
|
124
117
|
except Exception as e:
|
|
125
118
|
last_error = e
|
|
119
|
+
returned_no_summary = False
|
|
126
120
|
if attempt <= COMPACTION_MAX_RETRIES:
|
|
127
121
|
if via_events():
|
|
128
122
|
await ui_events.emit(StatusUpdated(
|
|
@@ -135,37 +129,43 @@ class GraphCompactionMixin:
|
|
|
135
129
|
ui.print(f"[dim]Compaction agent failed ({e}) — retrying ({attempt}/{COMPACTION_MAX_RETRIES})[/dim]")
|
|
136
130
|
|
|
137
131
|
if not summary:
|
|
138
|
-
# All retries exhausted —
|
|
132
|
+
# All retries exhausted — use an extracted summary, but keep the selected tail.
|
|
133
|
+
if last_error:
|
|
134
|
+
failure_detail = f"{type(last_error).__name__}: {last_error}"
|
|
135
|
+
elif returned_no_summary:
|
|
136
|
+
failure_detail = "compaction agent returned no summary"
|
|
137
|
+
else:
|
|
138
|
+
failure_detail = "compaction agent did not produce a summary"
|
|
139
139
|
if via_events():
|
|
140
|
-
err_detail = f"{last_error}; " if last_error else ""
|
|
141
140
|
await ui_events.emit(StatusUpdated(
|
|
142
141
|
status_id="compaction",
|
|
143
142
|
label="Compaction agent failed",
|
|
144
|
-
detail=f"{
|
|
143
|
+
detail=f"{failure_detail}; using extracted summary",
|
|
145
144
|
stage="compacting",
|
|
146
145
|
))
|
|
147
146
|
else:
|
|
148
|
-
err_msg = f" ({
|
|
149
|
-
ui.print(f"[dim]Compaction agent failed{err_msg} —
|
|
150
|
-
|
|
151
|
-
removed = _truncate_to_recent_messages(messages, keep)
|
|
152
|
-
# Generate a basic summary from the removed messages
|
|
153
|
-
fallback = CompactionService.fallback_summary(head_msgs if head_msgs else removed)
|
|
147
|
+
err_msg = f" ({failure_detail})"
|
|
148
|
+
ui.print(f"[dim]Compaction agent failed{err_msg} — using extracted summary[/dim]")
|
|
149
|
+
fallback = CompactionService.fallback_summary(head_msgs)
|
|
154
150
|
self._pending_summary = fallback
|
|
155
151
|
self._compaction_summary = fallback
|
|
156
152
|
self._compaction.compaction_count += 1
|
|
153
|
+
tail_msgs = messages[selection.keep_from:]
|
|
154
|
+
messages.clear()
|
|
155
|
+
messages.extend(tail_msgs)
|
|
156
|
+
await self._persist_compaction(head_msgs)
|
|
157
157
|
if via_events():
|
|
158
158
|
await ui_events.emit(StatusFinished(
|
|
159
159
|
status_id="compaction",
|
|
160
|
-
label=f"Compaction fallback
|
|
160
|
+
label=f"Compaction fallback summarized {len(head_msgs)} messages",
|
|
161
|
+
detail=f"{failure_detail}; using extracted summary",
|
|
161
162
|
ok=False,
|
|
162
163
|
remove=False,
|
|
163
164
|
))
|
|
164
|
-
return
|
|
165
|
+
return head_msgs, tail_id
|
|
165
166
|
|
|
166
167
|
if summary:
|
|
167
|
-
|
|
168
|
-
tail_msgs = messages[keep_from:]
|
|
168
|
+
tail_msgs = messages[selection.keep_from:]
|
|
169
169
|
messages.clear()
|
|
170
170
|
messages.extend(tail_msgs)
|
|
171
171
|
self._pending_summary = summary
|
|
@@ -222,6 +222,13 @@ class GraphCompactionMixin:
|
|
|
222
222
|
cache = getattr(self, "_session_msg_cache", None)
|
|
223
223
|
if cache is not None:
|
|
224
224
|
self._session_msg_cache = [r for r in cache if r.id is not None and r.id > last_message_id]
|
|
225
|
+
context_cache = getattr(self, "_context_cache", None)
|
|
226
|
+
if context_cache is not None:
|
|
227
|
+
context_cache.row_messages = {
|
|
228
|
+
row_id: entry
|
|
229
|
+
for row_id, entry in context_cache.row_messages.items()
|
|
230
|
+
if row_id > last_message_id
|
|
231
|
+
}
|
|
225
232
|
|
|
226
233
|
async def _compact_session_history(self: GraphCompactionHost, *, force: bool = True) -> bool:
|
|
227
234
|
if getattr(self, "_session", None) is None:
|
|
@@ -252,7 +259,12 @@ class GraphCompactionMixin:
|
|
|
252
259
|
return None
|
|
253
260
|
|
|
254
261
|
prompt = self._compaction.build_prompt(head_messages, previous_summary)
|
|
255
|
-
renderer = StreamingRenderer(
|
|
262
|
+
renderer = StreamingRenderer(
|
|
263
|
+
console,
|
|
264
|
+
debug=self._debug,
|
|
265
|
+
stream_to_dock=False,
|
|
266
|
+
headless=True,
|
|
267
|
+
)
|
|
256
268
|
|
|
257
269
|
messages = [SystemMessage(content=COMPACTION_PROMPT)]
|
|
258
270
|
messages.append(HumanMessage(content=prompt))
|
|
@@ -284,7 +296,20 @@ class GraphCompactionMixin:
|
|
|
284
296
|
cache_key=f"{self.config.model.provider}/{self.config.model.model}",
|
|
285
297
|
)
|
|
286
298
|
text = extract_text(assistant_msg)
|
|
287
|
-
|
|
299
|
+
if text:
|
|
300
|
+
return text
|
|
301
|
+
logger.warning(
|
|
302
|
+
"Compaction agent returned empty text: message_type=%s content_type=%s",
|
|
303
|
+
type(assistant_msg).__name__,
|
|
304
|
+
_content_type_summary(getattr(assistant_msg, "content", None)),
|
|
305
|
+
)
|
|
306
|
+
return None
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def _content_type_summary(content: object) -> str:
|
|
310
|
+
if isinstance(content, list):
|
|
311
|
+
return ",".join(type(item).__name__ for item in content) or "list(empty)"
|
|
312
|
+
return type(content).__name__
|
|
288
313
|
|
|
289
314
|
|
|
290
315
|
def _max_persisted_message_id(messages: list) -> int | None:
|
|
@@ -296,16 +321,3 @@ def _max_persisted_message_id(messages: list) -> int | None:
|
|
|
296
321
|
except (TypeError, ValueError):
|
|
297
322
|
continue
|
|
298
323
|
return max(ids) if ids else None
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
def _truncate_to_recent_messages(messages: list, keep: int) -> list:
|
|
302
|
-
original = list(messages)
|
|
303
|
-
system_msgs = [m for m in original if isinstance(m, SystemMessage)]
|
|
304
|
-
other_msgs = [m for m in original if not isinstance(m, SystemMessage)]
|
|
305
|
-
tail_msgs = other_msgs[-keep:] if keep > 0 else []
|
|
306
|
-
retained_ids = {id(m) for m in [*system_msgs, *tail_msgs]}
|
|
307
|
-
removed = [m for m in original if id(m) not in retained_ids]
|
|
308
|
-
messages.clear()
|
|
309
|
-
messages.extend(system_msgs)
|
|
310
|
-
messages.extend(tail_msgs)
|
|
311
|
-
return removed
|
|
@@ -7,11 +7,12 @@ changing the runtime inheritance model.
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
import asyncio
|
|
11
|
+
from typing import Any, Protocol
|
|
11
12
|
|
|
12
13
|
from langchain_core.messages import BaseMessage
|
|
13
14
|
|
|
14
|
-
from voidx.agent.runtime_context import InteractionMode
|
|
15
|
+
from voidx.agent.runtime_context import ContextCompilerCache, InteractionMode
|
|
15
16
|
from voidx.agent.state import AgentState
|
|
16
17
|
from voidx.agent.task_state import TaskRun, TaskState
|
|
17
18
|
from voidx.config import Config, Settings
|
|
@@ -22,10 +23,6 @@ from voidx.memory.session import SessionInfo
|
|
|
22
23
|
from voidx.permission.service import PermissionService
|
|
23
24
|
from voidx.tools.registry import ToolRegistry
|
|
24
25
|
from voidx.tools.task_tracker import TaskTracker
|
|
25
|
-
from voidx.ui.output.tree import OutputNode, OutputTree
|
|
26
|
-
|
|
27
|
-
if TYPE_CHECKING:
|
|
28
|
-
from voidx.ui.tui import PureTui
|
|
29
26
|
|
|
30
27
|
|
|
31
28
|
class GraphComponentHost(Protocol):
|
|
@@ -47,18 +44,22 @@ class GraphComponentHost(Protocol):
|
|
|
47
44
|
_interaction_mode: InteractionMode
|
|
48
45
|
_debug: bool
|
|
49
46
|
_file_mtimes: dict[str, float]
|
|
50
|
-
_turn_node:
|
|
51
|
-
_current_tree:
|
|
47
|
+
_turn_node: Any | None
|
|
48
|
+
_current_tree: Any | None
|
|
52
49
|
_current_messages: list[BaseMessage] | None
|
|
53
50
|
_sub_buffers: dict[str, list[BaseMessage]]
|
|
54
51
|
_pending_summary: str | None
|
|
55
52
|
_compaction_summary: str
|
|
56
53
|
_session_msg_cache: list[Any] | None
|
|
57
|
-
|
|
54
|
+
_context_cache: ContextCompilerCache
|
|
55
|
+
_app: Any | None
|
|
58
56
|
_usage_stats: UsageStats
|
|
59
57
|
_compaction: CompactionService
|
|
60
58
|
_task_state: TaskState
|
|
61
59
|
_task_run: TaskRun
|
|
60
|
+
_clear_session_tasks: set[asyncio.Task[None]]
|
|
61
|
+
_title_generation: int
|
|
62
|
+
_title_task: asyncio.Task[None] | None
|
|
62
63
|
|
|
63
64
|
_mcp_manager: Any
|
|
64
65
|
_lsp_manager: Any
|
|
@@ -70,15 +71,31 @@ class GraphComponentHost(Protocol):
|
|
|
70
71
|
@property
|
|
71
72
|
def _plan_mode(self) -> bool: ...
|
|
72
73
|
|
|
73
|
-
async def _show_startup(
|
|
74
|
+
async def _show_startup(
|
|
75
|
+
self,
|
|
76
|
+
*,
|
|
77
|
+
append_transcript: bool = False,
|
|
78
|
+
prefer_direct: bool = False,
|
|
79
|
+
) -> None: ...
|
|
74
80
|
def _startup_title(self) -> str: ...
|
|
75
81
|
async def _handle_web_command(self, app: Any, command: Any) -> None: ...
|
|
76
82
|
async def _handle_user_input(self, app: Any, user_input: str) -> tuple[bool, str | None]: ...
|
|
77
|
-
async def _run_once(self, user_text: str) -> None: ...
|
|
83
|
+
async def _run_once(self, user_text: str, *, display_text: str | None = None) -> None: ...
|
|
78
84
|
async def _dispatch_slash(self, inp: str) -> bool: ...
|
|
79
85
|
async def _restore_runtime_state(self) -> None: ...
|
|
80
86
|
async def _persist_runtime_state(self) -> None: ...
|
|
81
87
|
async def _clear_runtime_state(self) -> None: ...
|
|
88
|
+
def _reset_runtime_state_memory(self) -> None: ...
|
|
89
|
+
def _invalidate_session_title_generation(self) -> None: ...
|
|
90
|
+
def _temporary_session_title(self, text: str) -> str: ...
|
|
91
|
+
def _schedule_session_title_generation(
|
|
92
|
+
self,
|
|
93
|
+
session_id: str,
|
|
94
|
+
first_user_text: str,
|
|
95
|
+
temporary_title: str,
|
|
96
|
+
) -> None: ...
|
|
97
|
+
async def regenerate_session_title(self) -> bool: ...
|
|
98
|
+
async def _delete_empty_current_session(self) -> None: ...
|
|
82
99
|
async def _persist_transcript_snapshot(self) -> None: ...
|
|
83
100
|
async def _restore_transcript_snapshot(self, *, append: bool = False) -> bool: ...
|
|
84
101
|
|