drydock-cli 3.1.16__tar.gz → 3.1.17__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.
- {drydock_cli-3.1.16/drydock_cli.egg-info → drydock_cli-3.1.17}/PKG-INFO +1 -1
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/comms/__init__.py +2 -2
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/comms/channels.py +21 -34
- {drydock_cli-3.1.16 → drydock_cli-3.1.17/drydock_cli.egg-info}/PKG-INFO +1 -1
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/pyproject.toml +1 -1
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/LICENSE +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/NOTICE +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/README.md +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/__init__.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/__main__.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/advisor.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/agent.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/bash_safety.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/budget.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/builtin_skills/__init__.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/builtin_skills/document-canvas.md +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/builtin_skills/fiar-assess.md +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/builtin_skills/fiar-cap.md +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/builtin_skills/fiar-evidence.md +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/builtin_skills/fiar-readiness.md +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/builtin_skills/ml-data.md +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/builtin_skills/ml-debug.md +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/builtin_skills/ml-finetune.md +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/builtin_skills/ml-metrics.md +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/builtin_skills/ml-rl.md +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/builtin_skills/ml-train.md +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/builtin_skills/nist-ai-rmf.md +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/builtin_skills/nist-csf.md +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/builtin_skills/rmf-categorize.md +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/builtin_skills/rmf-control.md +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/builtin_skills/rmf-poam.md +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/builtin_skills/rmf-review.md +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/builtin_skills/stig-assess.md +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/builtin_skills/stig-remediate.md +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/cci.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/cli.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/comms/attention.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/comms/events.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/compaction.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/config.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/detect.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/doccanvas.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/events.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/extract.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/fiar.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/gittools.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/graphrag.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/guards.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/loop_detect.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/mcp.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/phases.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/poam.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/progress.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/providers.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/ratchet.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/recipes.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/recovery.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/resume.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/rmf.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/rmf_graph.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/skills.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/stig.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/subagents.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/suggest.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/task_state.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/tool_policy.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/tool_registry.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/tool_result.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/tool_select.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/tool_validate.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/tools/__init__.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/trajectory.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/tui/__init__.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/tui/app.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/tui/approval.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/tui/messages.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/tui/widgets.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/tuning.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/verification.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock/web.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock_cli.egg-info/SOURCES.txt +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock_cli.egg-info/dependency_links.txt +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock_cli.egg-info/entry_points.txt +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock_cli.egg-info/requires.txt +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/drydock_cli.egg-info/top_level.txt +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/setup.cfg +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_advisor.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_approval.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_back_command.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_bash_background.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_bash_binary_output.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_bash_crossplatform.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_bash_output_bounding.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_bash_process_group.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_bash_safety.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_bash_sanitize.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_bash_shell.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_bash_stdin.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_bash_stop_partial.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_bash_timeout_network.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_bash_timeout_param.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_budget.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_cci.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_cli_agents.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_comms.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_compact_command.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_compaction.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_config.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_config_migration.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_context_limit_config.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_context_limit_issue25.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_criteria_coverage.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_cycling_detection.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_declared_deps.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_degenerate_argument.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_detect.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_dispatch.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_doccanvas.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_e2e_connected.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_edit_replace_all.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_edit_thrash_and_compaction.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_effort_governor.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_empty_response.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_events.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_extract.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_failure_loop.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_fiar.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_first_run_setup.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_gittools.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_glob_edit_edges.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_graphify_example.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_graphrag.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_graphrag_quoted_path.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_graphrag_sqlite.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_grep_and_read_robust.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_guards_and_tools.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_hallucinated_tools.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_leaked_tool_call.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_loop_detect.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_mcp.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_model_registry.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_oneshot_unreachable.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_overthink_interrupt.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_phases.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_plan_autocontinue.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_poam.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_progress.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_providers_unreachable.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_ratchet.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_read_index.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_recipes.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_recovery.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_recovery_config.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_recovery_integration.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_repeated_outcome.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_repetition_interrupt.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_resume_events.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_resume_restore.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_resume_snapshot.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_rmf.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_rmf_graph.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_rmf_stig_graph.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_rolling_plan.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_runaway_repetition.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_screenshot.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_server_probe.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_skills.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_sqlite_events.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_stall_retry.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_stig.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_stop.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_streaming_newlines.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_subagent.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_subagents.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_suggest.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_system_prompt_help.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_task_state.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_timeline.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_todo.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_tool_arg_coercion.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_tool_arg_coercion_more.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_tool_arg_parsing.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_tool_canonical.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_tool_policy.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_tool_result.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_tool_select.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_tool_validate.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_tools_undo.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_trajectory.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_tui.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_tuning.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_verification_gate.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_viewimage.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_vision_input.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_web_tools.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_windows_shell.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_worker_subagent.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_write_content_coerce.py +0 -0
- {drydock_cli-3.1.16 → drydock_cli-3.1.17}/tests/test_xccdf.py +0 -0
|
@@ -14,7 +14,7 @@ from __future__ import annotations
|
|
|
14
14
|
|
|
15
15
|
from .events import Decision, Event, Presence, Severity, NON_SUPPRESSIBLE
|
|
16
16
|
from .attention import AttentionPolicy, AttentionConfig
|
|
17
|
-
from .channels import Delivery,
|
|
17
|
+
from .channels import Delivery, LogChannel, MessageProvider
|
|
18
18
|
|
|
19
19
|
_policy = AttentionPolicy()
|
|
20
20
|
_delivery = Delivery()
|
|
@@ -53,6 +53,6 @@ def emit_event(type: str, severity: Severity = Severity.INFORMATIONAL,
|
|
|
53
53
|
|
|
54
54
|
__all__ = [
|
|
55
55
|
"Decision", "Event", "Presence", "Severity", "NON_SUPPRESSIBLE",
|
|
56
|
-
"AttentionPolicy", "AttentionConfig", "Delivery", "
|
|
56
|
+
"AttentionPolicy", "AttentionConfig", "Delivery", "MessageProvider",
|
|
57
57
|
"LogChannel", "emit_event", "configure", "set_presence",
|
|
58
58
|
]
|
|
@@ -1,48 +1,26 @@
|
|
|
1
1
|
"""Drydock Comms — channel delivery (PRD §15/§17). Routes a Decision to a place:
|
|
2
2
|
LOG→file, DISPLAY→stdout/TUI, MESSAGE→messaging provider, SPEAK→TTS (stub).
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
PROVENANCE: the published core ships NO outbound network sender — drydock's
|
|
5
|
+
identity is clean, no-phone-home code. Messaging is a PLUGGABLE ADAPTER: core
|
|
6
|
+
defines the `MessageProvider` interface only; the application (or the fleet)
|
|
7
|
+
injects a concrete sender via `comms.configure(...)`. A MESSAGE decision with no
|
|
8
|
+
injected provider falls back to display+log, so nothing is silently lost.
|
|
7
9
|
"""
|
|
8
10
|
from __future__ import annotations
|
|
9
11
|
|
|
10
|
-
import os
|
|
11
12
|
import json
|
|
12
|
-
import urllib.request
|
|
13
|
-
import urllib.parse
|
|
14
13
|
|
|
15
14
|
from .events import Decision, Event
|
|
16
15
|
|
|
17
16
|
|
|
18
17
|
class MessageProvider:
|
|
18
|
+
"""Interface for a messaging channel. Concrete network senders live OUTSIDE
|
|
19
|
+
the published core (injected by the app) — the core stays phone-home-free."""
|
|
19
20
|
def send(self, text: str) -> bool: # pragma: no cover - interface
|
|
20
21
|
raise NotImplementedError
|
|
21
22
|
|
|
22
23
|
|
|
23
|
-
class TelegramProvider(MessageProvider):
|
|
24
|
-
"""Minimal, dependency-free Telegram sender (stdlib urllib). Reads token/chat
|
|
25
|
-
from args or env (DRYDOCK_TG_TOKEN / DRYDOCK_TG_CHAT)."""
|
|
26
|
-
|
|
27
|
-
def __init__(self, token: str | None = None, chat_id: str | None = None):
|
|
28
|
-
self.token = token or os.environ.get("DRYDOCK_TG_TOKEN", "")
|
|
29
|
-
self.chat_id = chat_id or os.environ.get("DRYDOCK_TG_CHAT", "")
|
|
30
|
-
|
|
31
|
-
def configured(self) -> bool:
|
|
32
|
-
return bool(self.token and self.chat_id)
|
|
33
|
-
|
|
34
|
-
def send(self, text: str) -> bool:
|
|
35
|
-
if not self.configured():
|
|
36
|
-
return False
|
|
37
|
-
url = f"https://api.telegram.org/bot{self.token}/sendMessage"
|
|
38
|
-
data = urllib.parse.urlencode({"chat_id": self.chat_id, "text": text}).encode()
|
|
39
|
-
try:
|
|
40
|
-
with urllib.request.urlopen(url, data=data, timeout=10) as r:
|
|
41
|
-
return r.status == 200
|
|
42
|
-
except Exception: # noqa: BLE001 — comms failure must never crash the task
|
|
43
|
-
return False
|
|
44
|
-
|
|
45
|
-
|
|
46
24
|
class LogChannel:
|
|
47
25
|
def __init__(self, path: str = "/tmp/drydock_comms.log"):
|
|
48
26
|
self.path = path
|
|
@@ -70,14 +48,24 @@ def format_for_human(event: Event) -> str:
|
|
|
70
48
|
|
|
71
49
|
|
|
72
50
|
class Delivery:
|
|
73
|
-
"""Executes a Decision. Returns True if it reached the intended channel.
|
|
51
|
+
"""Executes a Decision. Returns True if it reached the intended channel.
|
|
52
|
+
|
|
53
|
+
message_provider is None by default (the clean core has no network sender);
|
|
54
|
+
apps inject one via comms.configure(). With no provider, MESSAGE/SPEAK fall
|
|
55
|
+
back to display+log so a non-suppressible event is never silently dropped."""
|
|
74
56
|
def __init__(self, message_provider: MessageProvider | None = None,
|
|
75
57
|
log: LogChannel | None = None, display=print, speak=None):
|
|
76
|
-
self.message_provider = message_provider
|
|
58
|
+
self.message_provider = message_provider
|
|
77
59
|
self.log = log or LogChannel()
|
|
78
60
|
self.display = display
|
|
79
61
|
self.speak = speak
|
|
80
62
|
|
|
63
|
+
def _send_message(self, text: str) -> bool:
|
|
64
|
+
if self.message_provider is not None:
|
|
65
|
+
return self.message_provider.send(text)
|
|
66
|
+
self.display(f"drydock [no messaging provider]: {text}") # never lose it
|
|
67
|
+
return False
|
|
68
|
+
|
|
81
69
|
def deliver(self, event: Event, decision: Decision) -> bool:
|
|
82
70
|
self.log.write(event, decision) # everything is always logged
|
|
83
71
|
text = format_for_human(event)
|
|
@@ -87,11 +75,10 @@ class Delivery:
|
|
|
87
75
|
self.display(f"drydock: {text}")
|
|
88
76
|
return True
|
|
89
77
|
if decision == Decision.MESSAGE:
|
|
90
|
-
return self.
|
|
78
|
+
return self._send_message(f"Drydock: {text}")
|
|
91
79
|
if decision == Decision.SPEAK:
|
|
92
80
|
if self.speak:
|
|
93
81
|
self.speak(text)
|
|
94
82
|
return True
|
|
95
|
-
# no TTS
|
|
96
|
-
return self.message_provider.send(f"Drydock: {text}")
|
|
83
|
+
return self._send_message(f"Drydock: {text}") # no TTS yet → message
|
|
97
84
|
return False
|
|
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
|
|
|
7
7
|
# PyPI distribution name is drydock-cli (the established install name, continued
|
|
8
8
|
# from the retired v2 fork); the import package + CLI command stay `drydock`.
|
|
9
9
|
name = "drydock-cli"
|
|
10
|
-
version = "3.1.
|
|
10
|
+
version = "3.1.17"
|
|
11
11
|
description = "Drydock — a local, provider-agnostic terminal coding agent for local LLMs"
|
|
12
12
|
readme = "README.md"
|
|
13
13
|
requires-python = ">=3.11"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|