xdog-coding 2.4.2__tar.gz → 2.4.4__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.
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/PKG-INFO +119 -21
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/README.md +113 -17
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/pyproject.toml +7 -4
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/__init__.py +1 -1
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/acp/backend.py +52 -30
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/acp/server.py +33 -18
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/config.py +33 -10
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/agent_session.py +319 -158
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/child_agents.py +35 -9
- xdog_coding-2.4.4/src/xdog/coding/core/command_names.py +19 -0
- xdog_coding-2.4.4/src/xdog/coding/core/goal_adapter.py +370 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/resource_loader.py +46 -26
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/sdk.py +35 -57
- xdog_coding-2.4.4/src/xdog/coding/core/session_history.py +23 -0
- xdog_coding-2.4.4/src/xdog/coding/core/session_lifecycle.py +160 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/session_manager.py +93 -30
- xdog_coding-2.4.4/src/xdog/coding/core/session_preparation.py +20 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/session_staging.py +3 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/sessions/controller.py +143 -50
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/sessions/inbox_models.py +1 -1
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/sessions/inbox_runtime.py +56 -14
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/sessions/inbox_store.py +37 -4
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/sessions/intake.py +1 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/sessions/ownership.py +8 -2
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/sessions/runtime.py +50 -59
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/sessions/store.py +51 -20
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/slash_commands.py +45 -12
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/main.py +22 -39
- xdog_coding-2.4.4/src/xdog/coding/modes/interactive/components/custom_editor.py +21 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/modes/interactive/interactive_mode.py +30 -27
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/modes/interactive/session_events.py +10 -12
- xdog_coding-2.4.4/tests/goal_installed_consumer.py +237 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_access_scope.py +11 -6
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_acp_artifact_contract.py +7 -5
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_acp_offline_inbox.py +2 -2
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_acp_review_regressions.py +48 -19
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_active_tool_retirement.py +13 -8
- xdog_coding-2.4.4/tests/test_admission_navigation_owner.py +201 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_batch_mode_errors.py +6 -3
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_child_agents.py +50 -9
- xdog_coding-2.4.4/tests/test_cli_extension_trust.py +69 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_compaction_controls_ui.py +3 -2
- xdog_coding-2.4.4/tests/test_effective_configuration.py +88 -0
- xdog_coding-2.4.4/tests/test_goal_adapter.py +302 -0
- xdog_coding-2.4.4/tests/test_goal_extension_views.py +212 -0
- xdog_coding-2.4.4/tests/test_goal_lifecycle.py +267 -0
- xdog_coding-2.4.4/tests/test_history_commit_owner.py +114 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_inbox_auto_consume.py +5 -2
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_inbox_controller.py +2 -2
- xdog_coding-2.4.4/tests/test_input_store_capacity.py +106 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_no_coding_rpc.py +2 -3
- xdog_coding-2.4.4/tests/test_owner_review_regressions.py +202 -0
- xdog_coding-2.4.4/tests/test_prompt_preparation.py +103 -0
- xdog_coding-2.4.4/tests/test_public_extension_commands.py +82 -0
- xdog_coding-2.4.4/tests/test_resource_loader.py +76 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_runtime_prompt.py +3 -2
- xdog_coding-2.4.4/tests/test_session_close_owner.py +345 -0
- xdog_coding-2.4.4/tests/test_session_identity_boundaries.py +153 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_session_mode_routing.py +2 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_session_ownership.py +7 -6
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_session_smoke.py +2 -2
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_slash_skills.py +5 -2
- xdog_coding-2.4.4/tests/test_unified_inbox_review_fixes.py +397 -0
- xdog_coding-2.4.2/src/xdog/coding/core/extensions/__init__.py +0 -1
- xdog_coding-2.4.2/src/xdog/coding/core/extensions/loader.py +0 -116
- xdog_coding-2.4.2/src/xdog/coding/core/extensions/runner.py +0 -79
- xdog_coding-2.4.2/src/xdog/coding/core/extensions/types.py +0 -11
- xdog_coding-2.4.2/src/xdog/coding/modes/interactive/components/custom_editor.py +0 -30
- xdog_coding-2.4.2/tests/test_resource_loader.py +0 -50
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/.gitignore +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/LICENSE +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/LICENSE-EXCEPTION.md +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/acp/__init__.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/acp/bridge.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/acp/cli.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/acp/client.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/acp/extensions.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/acp/ingress.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/acp/ingress_backend.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/acp/ingress_main.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/cli/__init__.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/cli/args.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/cli/config_selector.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/cli/enqueue.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/cli/file_processor.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/cli/initial_message.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/cli/list_models.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/cli/session_picker.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/__init__.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/bash_executor.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/canonical_source.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/compaction/__init__.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/compaction/compaction.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/compaction/utils.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/context_messages.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/defaults.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/event_bus.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/exec_utils.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/inbox_commands.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/keybindings.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/messages.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/model_catalog.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/navigation.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/permissions.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/prompt_templates.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/remote_session.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/sessions/__init__.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/sessions/availability.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/sessions/batches.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/sessions/inbox_views.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/sessions/models.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/sessions/operations.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/sessions/router.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/sessions/turns.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/settings_manager.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/system_prompt.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/timings.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/tools/__init__.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/core/transcript_source.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/modes/__init__.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/modes/interactive/__init__.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/modes/interactive/components/__init__.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/modes/interactive/components/assistant_message.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/modes/interactive/components/chat_log.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/modes/interactive/components/editor_layout.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/modes/interactive/components/footer.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/modes/interactive/components/permission_prompt.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/modes/interactive/components/tool_execution.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/modes/interactive/components/user_message.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/modes/interactive/provider_auth.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/modes/interactive/run_status.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/modes/interactive/session_presenter.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/modes/interactive/theme.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/modes/interactive/tool_renderers.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/modes/print_mode.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/py.typed +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/utils/__init__.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/utils/frontmatter.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/utils/git.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/utils/mime.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/utils/shell.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/src/xdog/coding/utils/sleep.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/acp_owner_agent.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/batch_helpers.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/conftest.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/extension_session_helpers.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/fixtures/benchmark_tui.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/fixtures/terminal_client.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/fixtures/terminal_review.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/session_owner_process.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_acp_backend.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_acp_batch_intake.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_acp_bridge.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_acp_cli.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_acp_enqueue_cli.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_acp_ingress.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_acp_ingress_lifecycle.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_acp_optional_imports.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_active_tool_persistence.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_after_run_compaction.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_after_run_name.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_agent_session.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_batch_config.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_batch_display.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_batch_turns.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_child_active_tools.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_child_image_admission.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_child_image_submission.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_child_queue_ui.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_cli_args.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_cli_config_selector.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_cli_file_processor.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_coding_config.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_command_artifact_export_ui.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_compact_layout.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_compaction_recovery.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_context_message_compaction.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_event_bus.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_extension_command_results_ui.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_extension_core_readonly.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_extension_editor_ui.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_extension_input_draft_isolation.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_extension_input_ui.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_extension_navigation_ui.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_extension_provider_startup.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_extension_readonly_ui.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_extension_session_context_ui.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_footer_context.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_image_composer.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_image_lifecycle_admission.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_inbox_activation_navigation.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_inbox_commands.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_inbox_crash.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_inbox_display.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_inbox_store.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_inbox_v2.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_interactive_commands.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_interactive_keymap.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_interactive_mode.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_live_extensions.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_mcp_auth_projection.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_mcp_browser.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_mcp_catalog_watch_ui.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_mcp_combined_watch_ui.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_mcp_manual_picker_ui.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_mcp_modern_browser_cancel.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_mcp_modern_browser_ui.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_mcp_retired_gateway.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_mcp_roots_review_ui.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_mcp_sampling_ui.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_mcp_task_terminal.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_messages.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_native_session_queue.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_no_legacy_event_host.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_oauth_ui.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_owned_native_model.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_permissions.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_prompt_templates.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_provider_oauth_ui.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_queue_controls.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_readonly_ui.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_removed_child_return_ui.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_rendered_image_context.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_renderer_contracts_ui.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_repository_review.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_retained_history.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_run_status.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_saved_child_drafts.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_saved_source_ui.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_sdk_compaction_compat.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_sdk_runtime_compatibility.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_sdk_session_state.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_session_batches.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_session_control_fences.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_session_controller.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_session_history_display.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_session_input_store.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_session_manager.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_session_message_display.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_session_name_ui.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_session_navigation.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_session_picker.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_session_router.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_session_staging.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_session_turns.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_settings_manager.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_skill_controls_ui.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_slash_commands.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_system_prompt.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_terminal_acceptance.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_timings.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_tools_browser.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_transcript_interaction.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_transcript_output.py +0 -0
- {xdog_coding-2.4.2 → xdog_coding-2.4.4}/tests/test_tui_usability.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: xdog-coding
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.4
|
|
4
4
|
Summary: Interactive coding agent CLI
|
|
5
5
|
Project-URL: Homepage, https://xdog.942295.xyz
|
|
6
6
|
Project-URL: Repository, https://github.com/litterzhang/xdog
|
|
@@ -23,9 +23,11 @@ Requires-Dist: agent-client-protocol<0.13,>=0.12.1; python_version < '3.15'
|
|
|
23
23
|
Requires-Dist: click>=8.1.0
|
|
24
24
|
Requires-Dist: pydantic>=2.0
|
|
25
25
|
Requires-Dist: pyyaml>=6.0
|
|
26
|
-
Requires-Dist: xdog-agent>=2.4.
|
|
27
|
-
Requires-Dist: xdog-ai[openai]>=2.4.
|
|
28
|
-
Requires-Dist: xdog-tui>=2.4.
|
|
26
|
+
Requires-Dist: xdog-agent>=2.4.4
|
|
27
|
+
Requires-Dist: xdog-ai[openai]>=2.4.4
|
|
28
|
+
Requires-Dist: xdog-tui>=2.4.4
|
|
29
|
+
Provides-Extra: skills
|
|
30
|
+
Requires-Dist: xdog-skills>=2.4.4; extra == 'skills'
|
|
29
31
|
Description-Content-Type: text/markdown
|
|
30
32
|
|
|
31
33
|
# xdog-coding
|
|
@@ -578,7 +580,8 @@ continuation silently reconnects, replays POSTs or expands configured disclosure
|
|
|
578
580
|
|
|
579
581
|
### Task planning and host read-only scope
|
|
580
582
|
|
|
581
|
-
The builtin **`xdog-planning`** skill
|
|
583
|
+
The builtin **`xdog-planning`** skill, supplied by `xdog-skills` (install the
|
|
584
|
+
`skills` extra), uses ordinary conversation or task documents
|
|
582
585
|
for objectives, dependencies, acceptance criteria and evidence-backed progress.
|
|
583
586
|
It does not create a separate plan database, inspector, execution mode or model
|
|
584
587
|
loop. The former `/plan`, `PlanPanel` and `update_plan` UI/tool APIs are removed.
|
|
@@ -775,7 +778,7 @@ none of these interfaces grants tool permission or full Pi API compatibility.
|
|
|
775
778
|
|
|
776
779
|
### Supervised child agents
|
|
777
780
|
|
|
778
|
-
`/agents start TASK` starts
|
|
781
|
+
`/agents start TASK` starts host-managed read-only child work. `/agents start --inherit
|
|
779
782
|
TASK` inherits the current host policy; it does not copy approval grants or bypass
|
|
780
783
|
read-only. Inspect with `/agents list` or `/agents inspect ID`; use `steer ID TEXT`,
|
|
781
784
|
`follow-up ID TEXT`, `cancel ID`, `wait ID` and `close ID` under `/agents`.
|
|
@@ -784,10 +787,34 @@ recursively delegate through their parent's supervision tools.
|
|
|
784
787
|
|
|
785
788
|
Children share the workspace, so coordinate conflicting writes. Context is copied
|
|
786
789
|
at admission through a complete tool/result checkpoint. Model/options/tool execution
|
|
787
|
-
mode are inherited.
|
|
788
|
-
|
|
789
|
-
threshold
|
|
790
|
-
|
|
790
|
+
mode are inherited. There is no fixed concurrent-child or retained-record count
|
|
791
|
+
limit, elapsed-time deadline, model-call cap or cumulative reported-token stop
|
|
792
|
+
threshold. The main Agent/host manages lifecycle with cancel/wait/close. Usage
|
|
793
|
+
counters remain reported usage, not exact billable accounting; actual model
|
|
794
|
+
output/context limits, permissions and message/input/image/per-file capacities
|
|
795
|
+
still apply. Complete history uses atomic segmented persistence instead of a
|
|
796
|
+
cumulative 512 KiB / 2,000-message execution cutoff; tool/result pairs are not
|
|
797
|
+
silently truncated.
|
|
798
|
+
|
|
799
|
+
Coding and Claw child factories explicitly enable the Agent's existing built-in
|
|
800
|
+
compaction policy through `AgentConfig(compaction=selected.compaction(child_stream))`
|
|
801
|
+
and provide `archive_compaction=store.archive_compaction` to the supervisor.
|
|
802
|
+
This does **not** change the generic Agent default: automatic compaction is off
|
|
803
|
+
unless explicitly configured. The selected helper uses the executing adapter's
|
|
804
|
+
real context/prompt/output capacity; unknown metadata, context capacity or output
|
|
805
|
+
reserve returns `None` (auto-compaction remains off), not a guessed fallback.
|
|
806
|
+
A host requiring automatic compaction must reject that case or explicitly supply
|
|
807
|
+
trusted capacity/reserve through native `CompactionConfig`.
|
|
808
|
+
|
|
809
|
+
With the policy enabled, one long tool turn can compact repeatedly at safe paired
|
|
810
|
+
boundaries. The supervisor waits for a durable full pre-compaction snapshot before
|
|
811
|
+
the native summary request starts. Archive, summary or stream-cleanup failure does
|
|
812
|
+
not commit a history cut, and cancellation settles owned writes/cleanup. The native
|
|
813
|
+
summary's per-request timeout/capacity checks remain; there is no replacement child
|
|
814
|
+
lifetime cap. Inspect shows the current retained context, possibly with summaries;
|
|
815
|
+
`children.store.compaction_archives(child_id)` reads full earlier snapshots without
|
|
816
|
+
replay. These child archives are separate from the parent session's `/tree`
|
|
817
|
+
compaction checkpoints.
|
|
791
818
|
|
|
792
819
|
Each child has independent Coding approvals and extension workers/state. Parent
|
|
793
820
|
validation/context hooks and current read-only/permission gates remain authoritative;
|
|
@@ -830,10 +857,10 @@ still uses silent no-UI answers to avoid borrowing its separate dialog reservati
|
|
|
830
857
|
Complex extension forms are removed; basic child dialogs retain these ownership and cancellation checks.
|
|
831
858
|
|
|
832
859
|
|
|
833
|
-
### Child specialization and limits
|
|
860
|
+
### Child specialization and protocol limits
|
|
834
861
|
|
|
835
862
|
`/agents start --label Reviewer --instructions "Inspect only" --tools filesystem,current_time
|
|
836
|
-
--fresh --
|
|
863
|
+
--fresh -- TASK` specializes a child without
|
|
837
864
|
changing parent permissions. Options precede the task; `--` preserves a task that
|
|
838
865
|
starts with flags. Plain tasks preserve quotes/newlines. `--tools none` gives the
|
|
839
866
|
child no executable tools; otherwise selected names must exist in its inherited tool
|
|
@@ -842,11 +869,15 @@ fail visibly. Instructions append to, rather than replace, parent restrictions.
|
|
|
842
869
|
|
|
843
870
|
In `/agents` press `n`, then Ctrl+G for settings JSON. Supported keys are `label`,
|
|
844
871
|
`instructions`, `tools` (array or null for inherited tools), `inherit_context`,
|
|
845
|
-
`
|
|
872
|
+
`model`, `thinking` and `preset`. Enter applies the settings draft only;
|
|
846
873
|
start review requires every page to be painted before confirmation. Resize invalidates
|
|
847
874
|
that review. This confirmation does NOT approve tool use. Effective settings persist
|
|
848
|
-
with child results and appear in complete child source.
|
|
849
|
-
|
|
875
|
+
with child results and appear in complete child source. Runtime budget options
|
|
876
|
+
`--timeout`, `--calls`, `--tokens` and config/preset keys `timeout`, `max_model_calls`,
|
|
877
|
+
`max_tokens` are removed and rejected for new starts. Historical child records with
|
|
878
|
+
these budget fields remain readable; the fields are inert and never reapply a
|
|
879
|
+
budget or restart work. This removal does not remove the actual model's per-request
|
|
880
|
+
output token ceiling.
|
|
850
881
|
`--fresh` omits canonical history/child entry inheritance, not mandatory parent
|
|
851
882
|
validation/context or the shared workspace. Model/reasoning inherit by default; explicit overrides now use the actual adapter.
|
|
852
883
|
Named presets now use explicit user configuration. Claw specialized
|
|
@@ -870,9 +901,12 @@ host native-tool overrides. Switching to a nonreasoning model disables inherited
|
|
|
870
901
|
reasoning; unsupported positive choices fail visibly. Model switches omit inherited/
|
|
871
902
|
transformed provider continuity and old reasoning from the CHILD copy, leaving parent
|
|
872
903
|
provenance/history intact. Transformed images are validated; oversized switched-model
|
|
873
|
-
contexts
|
|
874
|
-
|
|
875
|
-
|
|
904
|
+
contexts use the same built-in text-token estimate as native compaction, rather
|
|
905
|
+
than comparing text bytes to token capacity. This is not exact tokenizer accounting.
|
|
906
|
+
Host-enabled compaction runs before forwarding the next model request; context that
|
|
907
|
+
cannot be safely compacted or fit still fails explicitly with original history
|
|
908
|
+
retained. Image/capability and actual output limits remain enforced. Parent
|
|
909
|
+
model/options/settings/grants never change. Named presets use explicit user configuration.
|
|
876
910
|
|
|
877
911
|
|
|
878
912
|
### Named child presets
|
|
@@ -889,15 +923,14 @@ using this descriptor shape:
|
|
|
889
923
|
"instructions": "Review requested code; return findings with file locations.",
|
|
890
924
|
"tools": ["filesystem", "current_time"],
|
|
891
925
|
"inherit_context": false,
|
|
892
|
-
"
|
|
893
|
-
"max_tokens": 8000
|
|
926
|
+
"label": "Reviewer"
|
|
894
927
|
}
|
|
895
928
|
}
|
|
896
929
|
}
|
|
897
930
|
}
|
|
898
931
|
```
|
|
899
932
|
|
|
900
|
-
Browse `/agents presets`, or use `/agents start --preset reviewer --
|
|
933
|
+
Browse `/agents presets`, or use `/agents start --preset reviewer --label Audit --
|
|
901
934
|
TASK`. Explicit flags override template fields. Ctrl+P selects a template in a new
|
|
902
935
|
child form, Ctrl+G adjusts the draft, and full expanded settings/task review still
|
|
903
936
|
precedes execution. Selection itself makes no model request. Templates cannot encode
|
|
@@ -2622,3 +2655,68 @@ and widget layouts are removed. Native approval and recovery reviews remain host
|
|
|
2622
2655
|
owned; they expose no plugin layout or editor/session-mutation authority. Core TUI
|
|
2623
2656
|
overlays, transcript fullscreen, Unicode, clipping, cursor and tool-approval behavior
|
|
2624
2657
|
remain.
|
|
2658
|
+
|
|
2659
|
+
## Session ownership and reliable shutdown
|
|
2660
|
+
|
|
2661
|
+
Coding's TUI, print, SDK and ACP ingress share one session controller and Agent.
|
|
2662
|
+
Persistent writer locks live under `<sessions>/.owners`; they do not depend on
|
|
2663
|
+
`TMPDIR`. Short private Linux Unix socket/discovery files are separate, under
|
|
2664
|
+
`/tmp/xdog-coding-<uid>/<store-hash>`. Stop older Coding processes before upgrading:
|
|
2665
|
+
old binaries do not participate in this store-anchored writer-lock protocol. Do
|
|
2666
|
+
not run mixed old/new writers against the same session store.
|
|
2667
|
+
|
|
2668
|
+
SDK applications should `await session.aclose()` in `finally`. Closure is
|
|
2669
|
+
idempotent, waits for actual child/Goal/extension/MCP cleanup, and reports cleanup
|
|
2670
|
+
errors only after attempting the other resources. Cancellation of a waiter does
|
|
2671
|
+
not abandon the underlying close. `session.dispose()` requests the same close
|
|
2672
|
+
and returns a concurrent Future; synchronous applications can wait on `.result()`.
|
|
2673
|
+
Do not block an asynchronous caller loop with `.result()`; await `aclose()` instead.
|
|
2674
|
+
Synchronous construction and controls can be called with `asyncio.to_thread` when
|
|
2675
|
+
used from an async application. A receiver accepting a queued message does not
|
|
2676
|
+
require message approval; existing approval applies to tool execution only.
|
|
2677
|
+
|
|
2678
|
+
Automatic project instructions come **only** from the working directory's
|
|
2679
|
+
`AGENTS.md`, `.coding/INSTRUCTIONS.md` and `.coding/instructions.md`. There is no
|
|
2680
|
+
parent walk. Other harness configuration files are not automatic instruction
|
|
2681
|
+
sources; they remain ordinary files that users can explicitly read or attach under
|
|
2682
|
+
normal file-access and permission rules. There is no filename denylist.
|
|
2683
|
+
Each automatic source must be a regular UTF-8 file of at most 64 KiB; symlinks,
|
|
2684
|
+
special files and unreadable/oversized sources cause an explicit preparation error. Missing files are optional. These
|
|
2685
|
+
instructions are refreshed in owned off-loop preparation before a turn, reach the
|
|
2686
|
+
actual model prompt, and never grant tool permissions. The Agent alone renders
|
|
2687
|
+
skill indexes and session/turn-scoped bodies; loading a skill starts no observer,
|
|
2688
|
+
model, receiver or daemon.
|
|
2689
|
+
|
|
2690
|
+
`CreateSessionOptions.thinking_level` is honored, including explicit `"off"`.
|
|
2691
|
+
Initial `allowed_tools` configuration is a **tool selection**, not authorization:
|
|
2692
|
+
absent/null falls through to a lower layer, `[]` selects no tools, and a nonempty
|
|
2693
|
+
list selects those configured names. Caller options/overrides take precedence
|
|
2694
|
+
over saved explicit choices, then project and global configuration. Choices are
|
|
2695
|
+
not unioned. Unavailable saved names do not create tools or gain authority later;
|
|
2696
|
+
normal permission checks still apply to the selected tools.
|
|
2697
|
+
|
|
2698
|
+
The separate input history ledger has a common **64 MiB** read/write bound.
|
|
2699
|
+
Admission reserves final-state, batch-ID and bounded diagnostic space for every
|
|
2700
|
+
unfinished input; if it cannot fit, it is refused before acknowledgement. Errors
|
|
2701
|
+
retain up to 4096 characters with an explicit truncation marker; batch IDs are
|
|
2702
|
+
limited to 256 UTF-8 bytes. Accepted execution facts are never silently deleted.
|
|
2703
|
+
At capacity, explicitly start another session rather than automatically archiving
|
|
2704
|
+
or replaying requests. Recovery marks unfinished execution interrupted and never
|
|
2705
|
+
replays potentially executed tool effects automatically.
|
|
2706
|
+
|
|
2707
|
+
Ordinary turn history uses one immutable, original-owner disk commit, off the
|
|
2708
|
+
model loop, before publishing saved state and completing producer receipts.
|
|
2709
|
+
File replacement synchronizes the file and parent directory. A failed or
|
|
2710
|
+
uncertain history commit retains the live executed tail and fences further turns;
|
|
2711
|
+
close and explicitly reload/inspect the saved state before continuing. Concurrent
|
|
2712
|
+
metadata revision conflicts fail closed instead of overwriting newer facts.
|
|
2713
|
+
These are local filesystem/process guarantees, not hardware power-loss
|
|
2714
|
+
exactly-once execution or an OS security sandbox. No existing user data is migrated
|
|
2715
|
+
or discarded automatically.
|
|
2716
|
+
|
|
2717
|
+
Enabled extensions may declare a public slash name. The packaged `goal_ui`
|
|
2718
|
+
display exposes `/goals [GOAL_ID | page OFFSET]`; `/goal` remains the skill name.
|
|
2719
|
+
This is generic extension routing, not a Coding-specific Goal command. Public
|
|
2720
|
+
names appear in help/completion and cannot shadow builtin or skill commands;
|
|
2721
|
+
model tool names and permissions do not change. See
|
|
2722
|
+
`docs/extension-public-commands.md` for the shared Coding/Claw contract.
|
|
@@ -548,7 +548,8 @@ continuation silently reconnects, replays POSTs or expands configured disclosure
|
|
|
548
548
|
|
|
549
549
|
### Task planning and host read-only scope
|
|
550
550
|
|
|
551
|
-
The builtin **`xdog-planning`** skill
|
|
551
|
+
The builtin **`xdog-planning`** skill, supplied by `xdog-skills` (install the
|
|
552
|
+
`skills` extra), uses ordinary conversation or task documents
|
|
552
553
|
for objectives, dependencies, acceptance criteria and evidence-backed progress.
|
|
553
554
|
It does not create a separate plan database, inspector, execution mode or model
|
|
554
555
|
loop. The former `/plan`, `PlanPanel` and `update_plan` UI/tool APIs are removed.
|
|
@@ -745,7 +746,7 @@ none of these interfaces grants tool permission or full Pi API compatibility.
|
|
|
745
746
|
|
|
746
747
|
### Supervised child agents
|
|
747
748
|
|
|
748
|
-
`/agents start TASK` starts
|
|
749
|
+
`/agents start TASK` starts host-managed read-only child work. `/agents start --inherit
|
|
749
750
|
TASK` inherits the current host policy; it does not copy approval grants or bypass
|
|
750
751
|
read-only. Inspect with `/agents list` or `/agents inspect ID`; use `steer ID TEXT`,
|
|
751
752
|
`follow-up ID TEXT`, `cancel ID`, `wait ID` and `close ID` under `/agents`.
|
|
@@ -754,10 +755,34 @@ recursively delegate through their parent's supervision tools.
|
|
|
754
755
|
|
|
755
756
|
Children share the workspace, so coordinate conflicting writes. Context is copied
|
|
756
757
|
at admission through a complete tool/result checkpoint. Model/options/tool execution
|
|
757
|
-
mode are inherited.
|
|
758
|
-
|
|
759
|
-
threshold
|
|
760
|
-
|
|
758
|
+
mode are inherited. There is no fixed concurrent-child or retained-record count
|
|
759
|
+
limit, elapsed-time deadline, model-call cap or cumulative reported-token stop
|
|
760
|
+
threshold. The main Agent/host manages lifecycle with cancel/wait/close. Usage
|
|
761
|
+
counters remain reported usage, not exact billable accounting; actual model
|
|
762
|
+
output/context limits, permissions and message/input/image/per-file capacities
|
|
763
|
+
still apply. Complete history uses atomic segmented persistence instead of a
|
|
764
|
+
cumulative 512 KiB / 2,000-message execution cutoff; tool/result pairs are not
|
|
765
|
+
silently truncated.
|
|
766
|
+
|
|
767
|
+
Coding and Claw child factories explicitly enable the Agent's existing built-in
|
|
768
|
+
compaction policy through `AgentConfig(compaction=selected.compaction(child_stream))`
|
|
769
|
+
and provide `archive_compaction=store.archive_compaction` to the supervisor.
|
|
770
|
+
This does **not** change the generic Agent default: automatic compaction is off
|
|
771
|
+
unless explicitly configured. The selected helper uses the executing adapter's
|
|
772
|
+
real context/prompt/output capacity; unknown metadata, context capacity or output
|
|
773
|
+
reserve returns `None` (auto-compaction remains off), not a guessed fallback.
|
|
774
|
+
A host requiring automatic compaction must reject that case or explicitly supply
|
|
775
|
+
trusted capacity/reserve through native `CompactionConfig`.
|
|
776
|
+
|
|
777
|
+
With the policy enabled, one long tool turn can compact repeatedly at safe paired
|
|
778
|
+
boundaries. The supervisor waits for a durable full pre-compaction snapshot before
|
|
779
|
+
the native summary request starts. Archive, summary or stream-cleanup failure does
|
|
780
|
+
not commit a history cut, and cancellation settles owned writes/cleanup. The native
|
|
781
|
+
summary's per-request timeout/capacity checks remain; there is no replacement child
|
|
782
|
+
lifetime cap. Inspect shows the current retained context, possibly with summaries;
|
|
783
|
+
`children.store.compaction_archives(child_id)` reads full earlier snapshots without
|
|
784
|
+
replay. These child archives are separate from the parent session's `/tree`
|
|
785
|
+
compaction checkpoints.
|
|
761
786
|
|
|
762
787
|
Each child has independent Coding approvals and extension workers/state. Parent
|
|
763
788
|
validation/context hooks and current read-only/permission gates remain authoritative;
|
|
@@ -800,10 +825,10 @@ still uses silent no-UI answers to avoid borrowing its separate dialog reservati
|
|
|
800
825
|
Complex extension forms are removed; basic child dialogs retain these ownership and cancellation checks.
|
|
801
826
|
|
|
802
827
|
|
|
803
|
-
### Child specialization and limits
|
|
828
|
+
### Child specialization and protocol limits
|
|
804
829
|
|
|
805
830
|
`/agents start --label Reviewer --instructions "Inspect only" --tools filesystem,current_time
|
|
806
|
-
--fresh --
|
|
831
|
+
--fresh -- TASK` specializes a child without
|
|
807
832
|
changing parent permissions. Options precede the task; `--` preserves a task that
|
|
808
833
|
starts with flags. Plain tasks preserve quotes/newlines. `--tools none` gives the
|
|
809
834
|
child no executable tools; otherwise selected names must exist in its inherited tool
|
|
@@ -812,11 +837,15 @@ fail visibly. Instructions append to, rather than replace, parent restrictions.
|
|
|
812
837
|
|
|
813
838
|
In `/agents` press `n`, then Ctrl+G for settings JSON. Supported keys are `label`,
|
|
814
839
|
`instructions`, `tools` (array or null for inherited tools), `inherit_context`,
|
|
815
|
-
`
|
|
840
|
+
`model`, `thinking` and `preset`. Enter applies the settings draft only;
|
|
816
841
|
start review requires every page to be painted before confirmation. Resize invalidates
|
|
817
842
|
that review. This confirmation does NOT approve tool use. Effective settings persist
|
|
818
|
-
with child results and appear in complete child source.
|
|
819
|
-
|
|
843
|
+
with child results and appear in complete child source. Runtime budget options
|
|
844
|
+
`--timeout`, `--calls`, `--tokens` and config/preset keys `timeout`, `max_model_calls`,
|
|
845
|
+
`max_tokens` are removed and rejected for new starts. Historical child records with
|
|
846
|
+
these budget fields remain readable; the fields are inert and never reapply a
|
|
847
|
+
budget or restart work. This removal does not remove the actual model's per-request
|
|
848
|
+
output token ceiling.
|
|
820
849
|
`--fresh` omits canonical history/child entry inheritance, not mandatory parent
|
|
821
850
|
validation/context or the shared workspace. Model/reasoning inherit by default; explicit overrides now use the actual adapter.
|
|
822
851
|
Named presets now use explicit user configuration. Claw specialized
|
|
@@ -840,9 +869,12 @@ host native-tool overrides. Switching to a nonreasoning model disables inherited
|
|
|
840
869
|
reasoning; unsupported positive choices fail visibly. Model switches omit inherited/
|
|
841
870
|
transformed provider continuity and old reasoning from the CHILD copy, leaving parent
|
|
842
871
|
provenance/history intact. Transformed images are validated; oversized switched-model
|
|
843
|
-
contexts
|
|
844
|
-
|
|
845
|
-
|
|
872
|
+
contexts use the same built-in text-token estimate as native compaction, rather
|
|
873
|
+
than comparing text bytes to token capacity. This is not exact tokenizer accounting.
|
|
874
|
+
Host-enabled compaction runs before forwarding the next model request; context that
|
|
875
|
+
cannot be safely compacted or fit still fails explicitly with original history
|
|
876
|
+
retained. Image/capability and actual output limits remain enforced. Parent
|
|
877
|
+
model/options/settings/grants never change. Named presets use explicit user configuration.
|
|
846
878
|
|
|
847
879
|
|
|
848
880
|
### Named child presets
|
|
@@ -859,15 +891,14 @@ using this descriptor shape:
|
|
|
859
891
|
"instructions": "Review requested code; return findings with file locations.",
|
|
860
892
|
"tools": ["filesystem", "current_time"],
|
|
861
893
|
"inherit_context": false,
|
|
862
|
-
"
|
|
863
|
-
"max_tokens": 8000
|
|
894
|
+
"label": "Reviewer"
|
|
864
895
|
}
|
|
865
896
|
}
|
|
866
897
|
}
|
|
867
898
|
}
|
|
868
899
|
```
|
|
869
900
|
|
|
870
|
-
Browse `/agents presets`, or use `/agents start --preset reviewer --
|
|
901
|
+
Browse `/agents presets`, or use `/agents start --preset reviewer --label Audit --
|
|
871
902
|
TASK`. Explicit flags override template fields. Ctrl+P selects a template in a new
|
|
872
903
|
child form, Ctrl+G adjusts the draft, and full expanded settings/task review still
|
|
873
904
|
precedes execution. Selection itself makes no model request. Templates cannot encode
|
|
@@ -2592,3 +2623,68 @@ and widget layouts are removed. Native approval and recovery reviews remain host
|
|
|
2592
2623
|
owned; they expose no plugin layout or editor/session-mutation authority. Core TUI
|
|
2593
2624
|
overlays, transcript fullscreen, Unicode, clipping, cursor and tool-approval behavior
|
|
2594
2625
|
remain.
|
|
2626
|
+
|
|
2627
|
+
## Session ownership and reliable shutdown
|
|
2628
|
+
|
|
2629
|
+
Coding's TUI, print, SDK and ACP ingress share one session controller and Agent.
|
|
2630
|
+
Persistent writer locks live under `<sessions>/.owners`; they do not depend on
|
|
2631
|
+
`TMPDIR`. Short private Linux Unix socket/discovery files are separate, under
|
|
2632
|
+
`/tmp/xdog-coding-<uid>/<store-hash>`. Stop older Coding processes before upgrading:
|
|
2633
|
+
old binaries do not participate in this store-anchored writer-lock protocol. Do
|
|
2634
|
+
not run mixed old/new writers against the same session store.
|
|
2635
|
+
|
|
2636
|
+
SDK applications should `await session.aclose()` in `finally`. Closure is
|
|
2637
|
+
idempotent, waits for actual child/Goal/extension/MCP cleanup, and reports cleanup
|
|
2638
|
+
errors only after attempting the other resources. Cancellation of a waiter does
|
|
2639
|
+
not abandon the underlying close. `session.dispose()` requests the same close
|
|
2640
|
+
and returns a concurrent Future; synchronous applications can wait on `.result()`.
|
|
2641
|
+
Do not block an asynchronous caller loop with `.result()`; await `aclose()` instead.
|
|
2642
|
+
Synchronous construction and controls can be called with `asyncio.to_thread` when
|
|
2643
|
+
used from an async application. A receiver accepting a queued message does not
|
|
2644
|
+
require message approval; existing approval applies to tool execution only.
|
|
2645
|
+
|
|
2646
|
+
Automatic project instructions come **only** from the working directory's
|
|
2647
|
+
`AGENTS.md`, `.coding/INSTRUCTIONS.md` and `.coding/instructions.md`. There is no
|
|
2648
|
+
parent walk. Other harness configuration files are not automatic instruction
|
|
2649
|
+
sources; they remain ordinary files that users can explicitly read or attach under
|
|
2650
|
+
normal file-access and permission rules. There is no filename denylist.
|
|
2651
|
+
Each automatic source must be a regular UTF-8 file of at most 64 KiB; symlinks,
|
|
2652
|
+
special files and unreadable/oversized sources cause an explicit preparation error. Missing files are optional. These
|
|
2653
|
+
instructions are refreshed in owned off-loop preparation before a turn, reach the
|
|
2654
|
+
actual model prompt, and never grant tool permissions. The Agent alone renders
|
|
2655
|
+
skill indexes and session/turn-scoped bodies; loading a skill starts no observer,
|
|
2656
|
+
model, receiver or daemon.
|
|
2657
|
+
|
|
2658
|
+
`CreateSessionOptions.thinking_level` is honored, including explicit `"off"`.
|
|
2659
|
+
Initial `allowed_tools` configuration is a **tool selection**, not authorization:
|
|
2660
|
+
absent/null falls through to a lower layer, `[]` selects no tools, and a nonempty
|
|
2661
|
+
list selects those configured names. Caller options/overrides take precedence
|
|
2662
|
+
over saved explicit choices, then project and global configuration. Choices are
|
|
2663
|
+
not unioned. Unavailable saved names do not create tools or gain authority later;
|
|
2664
|
+
normal permission checks still apply to the selected tools.
|
|
2665
|
+
|
|
2666
|
+
The separate input history ledger has a common **64 MiB** read/write bound.
|
|
2667
|
+
Admission reserves final-state, batch-ID and bounded diagnostic space for every
|
|
2668
|
+
unfinished input; if it cannot fit, it is refused before acknowledgement. Errors
|
|
2669
|
+
retain up to 4096 characters with an explicit truncation marker; batch IDs are
|
|
2670
|
+
limited to 256 UTF-8 bytes. Accepted execution facts are never silently deleted.
|
|
2671
|
+
At capacity, explicitly start another session rather than automatically archiving
|
|
2672
|
+
or replaying requests. Recovery marks unfinished execution interrupted and never
|
|
2673
|
+
replays potentially executed tool effects automatically.
|
|
2674
|
+
|
|
2675
|
+
Ordinary turn history uses one immutable, original-owner disk commit, off the
|
|
2676
|
+
model loop, before publishing saved state and completing producer receipts.
|
|
2677
|
+
File replacement synchronizes the file and parent directory. A failed or
|
|
2678
|
+
uncertain history commit retains the live executed tail and fences further turns;
|
|
2679
|
+
close and explicitly reload/inspect the saved state before continuing. Concurrent
|
|
2680
|
+
metadata revision conflicts fail closed instead of overwriting newer facts.
|
|
2681
|
+
These are local filesystem/process guarantees, not hardware power-loss
|
|
2682
|
+
exactly-once execution or an OS security sandbox. No existing user data is migrated
|
|
2683
|
+
or discarded automatically.
|
|
2684
|
+
|
|
2685
|
+
Enabled extensions may declare a public slash name. The packaged `goal_ui`
|
|
2686
|
+
display exposes `/goals [GOAL_ID | page OFFSET]`; `/goal` remains the skill name.
|
|
2687
|
+
This is generic extension routing, not a Coding-specific Goal command. Public
|
|
2688
|
+
names appear in help/completion and cannot shadow builtin or skill commands;
|
|
2689
|
+
model tool names and permissions do not change. See
|
|
2690
|
+
`docs/extension-public-commands.md` for the shared Coding/Claw contract.
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "xdog-coding"
|
|
7
|
-
version = "2.4.
|
|
7
|
+
version = "2.4.4"
|
|
8
8
|
description = "Interactive coding agent CLI"
|
|
9
9
|
requires-python = ">=3.12"
|
|
10
10
|
classifiers = [
|
|
@@ -22,15 +22,18 @@ readme = "README.md"
|
|
|
22
22
|
license = "AGPL-3.0-or-later"
|
|
23
23
|
license-files = ["LICENSE", "LICENSE-EXCEPTION.md"]
|
|
24
24
|
dependencies = [
|
|
25
|
-
"xdog-ai[openai]>=2.4.
|
|
26
|
-
"xdog-agent>=2.4.
|
|
25
|
+
"xdog-ai[openai]>=2.4.4",
|
|
26
|
+
"xdog-agent>=2.4.4",
|
|
27
27
|
"agent-client-protocol>=0.12.1,<0.13; python_version < '3.15'",
|
|
28
|
-
"xdog-tui>=2.4.
|
|
28
|
+
"xdog-tui>=2.4.4",
|
|
29
29
|
"pyyaml>=6.0",
|
|
30
30
|
"click>=8.1.0",
|
|
31
31
|
"pydantic>=2.0",
|
|
32
32
|
]
|
|
33
33
|
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
skills = ["xdog-skills>=2.4.4"]
|
|
36
|
+
|
|
34
37
|
[project.urls]
|
|
35
38
|
Homepage = "https://xdog.942295.xyz"
|
|
36
39
|
Repository = "https://github.com/litterzhang/xdog"
|
|
@@ -89,17 +89,19 @@ class CodingBackend:
|
|
|
89
89
|
try:
|
|
90
90
|
session = await asyncio.shield(task)
|
|
91
91
|
except asyncio.CancelledError:
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
from xdog.agent.async_work import wait_owned
|
|
93
|
+
async def settle_construction() -> None:
|
|
94
|
+
late_session = await task
|
|
95
|
+
await late_session.aclose()
|
|
96
|
+
await wait_owned(asyncio.create_task(settle_construction(), name='coding-acp-canceled-construction'))
|
|
94
97
|
raise
|
|
95
|
-
runtime = SessionRuntime(session, bound=False, router=self.router)
|
|
96
|
-
runtime.start()
|
|
97
98
|
try:
|
|
99
|
+
runtime = SessionRuntime(session, bound=False, router=self.router)
|
|
100
|
+
runtime.start()
|
|
98
101
|
from xdog.coding.acp.server import serve_local
|
|
99
|
-
|
|
100
102
|
server = await serve_local(runtime)
|
|
101
103
|
except BaseException:
|
|
102
|
-
await
|
|
104
|
+
await session.aclose()
|
|
103
105
|
raise
|
|
104
106
|
self._owned[session.session_id] = peer.id, runtime, server
|
|
105
107
|
ref = SessionRef(session.session_id, session.working_dir, runtime.controller.generation)
|
|
@@ -300,31 +302,51 @@ class CodingBackend:
|
|
|
300
302
|
await asyncio.wrap_future(running.controller.cancel(running.ticket.id, peer_id=peer.id))
|
|
301
303
|
|
|
302
304
|
async def disconnect(self, peer: Peer) -> None:
|
|
303
|
-
|
|
305
|
+
from functools import partial
|
|
306
|
+
|
|
307
|
+
from xdog.agent.async_work import settle_cleanup
|
|
304
308
|
pending = tuple(row for key, row in self._running.items() if key[0] == peer.id)
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
309
|
+
async def ingress() -> None:
|
|
310
|
+
await self._inbox.disconnect(peer)
|
|
311
|
+
async def requests() -> None:
|
|
312
|
+
for row in pending:
|
|
313
|
+
if row.ticket is None and not row.task.cancelling():
|
|
314
|
+
row.task.cancel()
|
|
315
|
+
async def disconnect(controller: SessionController) -> None:
|
|
316
|
+
await asyncio.wrap_future(controller.disconnect(peer.id))
|
|
317
|
+
async def join() -> None:
|
|
318
|
+
tasks = [row.task for row in pending if row.task is not asyncio.current_task()]
|
|
319
|
+
for task in tasks:
|
|
320
|
+
if not task.done() and not task.cancelling():
|
|
321
|
+
task.cancel()
|
|
322
|
+
if tasks:
|
|
323
|
+
await asyncio.gather(*tasks, return_exceptions=True)
|
|
324
|
+
controllers = {row.controller for row in pending}
|
|
325
|
+
await settle_cleanup(*(partial(disconnect, controller) for controller in controllers),
|
|
326
|
+
join, message='ACP request retirement failed')
|
|
327
|
+
async def remote(key: tuple[str, str], attachment: AcpAttachment) -> None:
|
|
328
|
+
try:
|
|
329
|
+
await attachment.close()
|
|
330
|
+
finally:
|
|
331
|
+
self._remote.pop(key, None)
|
|
332
|
+
async def owned(identifier: str, runtime: SessionRuntime) -> None:
|
|
333
|
+
try:
|
|
334
|
+
# The session owns its CURRENT endpoint too. Closing the saved
|
|
335
|
+
# old endpoint first would bypass all remaining resource cleanup.
|
|
336
|
+
await runtime.session.aclose()
|
|
337
|
+
finally:
|
|
338
|
+
if runtime.session._lease is None:
|
|
339
|
+
self._owned.pop(identifier, None)
|
|
340
|
+
async def references() -> None:
|
|
341
|
+
for key in tuple(self._refs):
|
|
342
|
+
if key[0] == peer.id:
|
|
343
|
+
self._refs.pop(key, None)
|
|
344
|
+
owned_sessions = tuple(self._owned.items())
|
|
345
|
+
await settle_cleanup(ingress, requests,
|
|
346
|
+
*(partial(remote, key, attachment) for key, attachment in tuple(self._remote.items()) if key[0] == peer.id),
|
|
347
|
+
*(partial(owned, identifier, runtime) for identifier, (owner, runtime, _server) in owned_sessions
|
|
348
|
+
if owner == peer.id), references, message='ACP peer cleanup failed')
|
|
349
|
+
|
|
328
350
|
async def extension(self, peer: Peer, method: str, params: dict[str, Any]) -> dict[str, Any]:
|
|
329
351
|
if method in {'xdog/enqueue', 'xdog/inbox_status'}:
|
|
330
352
|
target = params.get('session_id')
|
|
@@ -22,6 +22,7 @@ class LocalServer:
|
|
|
22
22
|
self.identity: tuple[int, int] | None = None
|
|
23
23
|
self.server: asyncio.AbstractServer | None = None
|
|
24
24
|
self.closing = False
|
|
25
|
+
self._closing: asyncio.Task[None] | None = None
|
|
25
26
|
self.writers: set[asyncio.StreamWriter] = set()
|
|
26
27
|
self.tasks: set[asyncio.Task[None]] = set()
|
|
27
28
|
|
|
@@ -47,24 +48,38 @@ class LocalServer:
|
|
|
47
48
|
await writer.wait_closed()
|
|
48
49
|
|
|
49
50
|
async def close(self) -> None:
|
|
50
|
-
|
|
51
|
-
if self.
|
|
52
|
-
self.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
51
|
+
from xdog.agent.async_work import wait_owned
|
|
52
|
+
if self._closing is None:
|
|
53
|
+
self.closing = True
|
|
54
|
+
self._closing = asyncio.create_task(self._close(), name='coding-endpoint-close')
|
|
55
|
+
await wait_owned(self._closing)
|
|
56
|
+
|
|
57
|
+
async def _close(self) -> None:
|
|
58
|
+
from xdog.agent.async_work import settle_cleanup
|
|
59
|
+
from xdog.coding.core.session_lifecycle import settle_sync
|
|
60
|
+
async def transports() -> None:
|
|
61
|
+
steps = [writer.close for writer in tuple(self.writers)]
|
|
62
|
+
if self.server is not None:
|
|
63
|
+
steps.insert(0, self.server.close)
|
|
64
|
+
settle_sync(*steps, message='ACP transport close failed')
|
|
65
|
+
async def server() -> None:
|
|
66
|
+
if self.server is not None:
|
|
67
|
+
await self.server.wait_closed()
|
|
68
|
+
self.server = None
|
|
69
|
+
async def peers() -> None:
|
|
70
|
+
if self.tasks:
|
|
71
|
+
# Disconnect/request errors are peer outcomes, not cleanup errors.
|
|
72
|
+
await asyncio.gather(*tuple(self.tasks), return_exceptions=True)
|
|
73
|
+
async def unlink() -> None:
|
|
74
|
+
path = self.record.address
|
|
75
|
+
if path.exists():
|
|
76
|
+
info = path.lstat()
|
|
77
|
+
if (stat.S_ISSOCK(info.st_mode) and info.st_uid == os.getuid()
|
|
78
|
+
and (info.st_dev, info.st_ino) == self.identity):
|
|
79
|
+
path.unlink()
|
|
80
|
+
async def registry() -> None:
|
|
81
|
+
self.runtime.registry.remove(self.record)
|
|
82
|
+
await settle_cleanup(transports, server, peers, unlink, registry, message='ACP endpoint cleanup failed')
|
|
68
83
|
|
|
69
84
|
|
|
70
85
|
async def serve_local(runtime: SessionRuntime) -> LocalServer:
|