tsugite-cli 0.12.2__tar.gz → 0.14.0__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.
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/.github/copilot-instructions.md +3 -5
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/.github/workflows/ci.yml +2 -2
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/.github/workflows/docker-publish.yml +0 -1
- tsugite_cli-0.14.0/.github/workflows/pypi-publish.yml +49 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/.gitignore +2 -1
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/AGENTS.md +144 -17
- tsugite_cli-0.14.0/CONTRIBUTING.md +54 -0
- tsugite_cli-0.14.0/Dockerfile +19 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/PKG-INFO +5 -7
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/README.md +4 -5
- tsugite_cli-0.14.0/cliff.toml +44 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/docs/agents.md +70 -2
- tsugite_cli-0.14.0/docs/plugin-events.md +131 -0
- tsugite_cli-0.14.0/docs/plugin-hooks.md +110 -0
- tsugite_cli-0.14.0/docs/plugin-tools.md +109 -0
- tsugite_cli-0.14.0/docs/plugins.md +139 -0
- tsugite_cli-0.14.0/docs/release_notes/v0.13.0.md +51 -0
- tsugite_cli-0.14.0/docs/release_notes/v0.14.0.md +39 -0
- tsugite_cli-0.14.0/examples/tsugite-example-plugin/pyproject.toml +17 -0
- tsugite_cli-0.14.0/examples/tsugite-example-plugin/tsugite_example_plugin/__init__.py +41 -0
- tsugite_cli-0.14.0/plugins/tsugite-tmux/pyproject.toml +16 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0/plugins/tsugite-tmux}/tests/test_tmux_tools.py +43 -62
- tsugite_cli-0.12.2/tsugite/tools/tmux.py → tsugite_cli-0.14.0/plugins/tsugite-tmux/tsugite_tmux/__init__.py +11 -25
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/pyproject.toml +10 -3
- tsugite_cli-0.14.0/scripts/bump_version.py +90 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/scripts/update_model_registry.py +11 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/README.md +12 -16
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/conftest.py +76 -36
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/core/test_agent.py +154 -79
- tsugite_cli-0.14.0/tests/core/test_agent_event_loop.py +310 -0
- tsugite_cli-0.14.0/tests/core/test_agent_parser_triple_quotes.py +70 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/core/test_agent_ui_events.py +91 -27
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/core/test_content_blocks.py +12 -12
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/core/test_executor.py +133 -25
- tsugite_cli-0.14.0/tests/core/test_executor_escape_tripwire.py +35 -0
- tsugite_cli-0.14.0/tests/core/test_state.py +85 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/core/test_subprocess_executor.py +40 -11
- tsugite_cli-0.14.0/tests/daemon/test_chat_reentrancy.py +399 -0
- tsugite_cli-0.14.0/tests/daemon/test_collect_events.py +106 -0
- tsugite_cli-0.14.0/tests/daemon/test_compaction_command.py +247 -0
- tsugite_cli-0.14.0/tests/daemon/test_event_broadcast_scope.py +64 -0
- tsugite_cli-0.14.0/tests/daemon/test_final_answer_delivery.py +75 -0
- tsugite_cli-0.14.0/tests/daemon/test_http_adapter.py +797 -0
- tsugite_cli-0.14.0/tests/daemon/test_message_context_session_started.py +152 -0
- tsugite_cli-0.14.0/tests/daemon/test_message_context_topic.py +207 -0
- tsugite_cli-0.14.0/tests/daemon/test_prompt_too_long_retry.py +239 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/daemon/test_session_metadata_api.py +28 -0
- tsugite_cli-0.14.0/tests/daemon/test_session_pinning_api.py +284 -0
- tsugite_cli-0.14.0/tests/daemon/test_session_primary_api.py +151 -0
- tsugite_cli-0.14.0/tests/daemon/test_session_store_named_route.py +91 -0
- tsugite_cli-0.14.0/tests/daemon/test_session_store_pinning.py +194 -0
- tsugite_cli-0.14.0/tests/daemon/test_session_store_primary.py +182 -0
- tsugite_cli-0.14.0/tests/daemon/test_skill_trigger_loading.py +154 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/e2e/test_history_code_rendering.py +103 -7
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/e2e/test_markdown_rendering.py +6 -25
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/e2e/test_message_actions.py +26 -33
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/e2e/test_scroll_behavior.py +6 -12
- tsugite_cli-0.14.0/tests/events/test_filtered_subscriptions.py +261 -0
- tsugite_cli-0.14.0/tests/integration/test_concurrent_workspace_cwd.py +88 -0
- tsugite_cli-0.14.0/tests/integration/test_exec_directive_e2e.py +37 -0
- tsugite_cli-0.14.0/tests/integration/test_nested_session_spawn.py +103 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/smoke_test.sh +3 -3
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_agent_inheritance.py +54 -20
- tsugite_cli-0.14.0/tests/test_agent_preparation.py +107 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_agent_sessions.py +198 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_agent_skills.py +10 -30
- tsugite_cli-0.14.0/tests/test_anthropic_extended_thinking.py +198 -0
- tsugite_cli-0.14.0/tests/test_attachments.py +1074 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_background_tasks.py +193 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_builtin_agent_paths.py +1 -1
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_builtin_agents.py +1 -1
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_claude_code_attachments.py +20 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_claude_code_provider.py +340 -3
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_cli.py +47 -6
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_cli_rendering.py +3 -4
- tsugite_cli-0.14.0/tests/test_cli_skills.py +85 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_cli_subcommands.py +0 -30
- tsugite_cli-0.14.0/tests/test_compaction_context_preservation.py +233 -0
- tsugite_cli-0.14.0/tests/test_compaction_event.py +160 -0
- tsugite_cli-0.14.0/tests/test_compaction_progress.py +162 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_daemon_unified_sessions.py +89 -24
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_discord_progress.py +206 -4
- tsugite_cli-0.14.0/tests/test_event_storage.py +153 -0
- tsugite_cli-0.14.0/tests/test_events_to_messages.py +217 -0
- tsugite_cli-0.14.0/tests/test_exceptions.py +17 -0
- tsugite_cli-0.14.0/tests/test_exec_directives.py +309 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_file_tools.py +155 -9
- tsugite_cli-0.14.0/tests/test_fs_tool_workspace.py +89 -0
- tsugite_cli-0.14.0/tests/test_handle_message_flush.py +216 -0
- tsugite_cli-0.14.0/tests/test_history_migrate.py +274 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_hooks.py +89 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_http_tools.py +62 -16
- tsugite_cli-0.14.0/tests/test_interaction_backend_isolation.py +186 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_interactive_context.py +0 -1
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_jsonl_ui.py +41 -0
- tsugite_cli-0.14.0/tests/test_live_event_recording.py +130 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_md_agents_json.py +1 -3
- tsugite_cli-0.14.0/tests/test_memory_sanitize.py +288 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_model_registry.py +11 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_multistep_agents.py +102 -0
- tsugite_cli-0.14.0/tests/test_multistep_retry_side_effects.py +108 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_plugins.py +169 -1
- tsugite_cli-0.14.0/tests/test_post_compaction_counters.py +255 -0
- tsugite_cli-0.14.0/tests/test_provider_turn_heartbeat.py +142 -0
- tsugite_cli-0.14.0/tests/test_reasoning_models.py +127 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_renderer.py +88 -1
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_rendering_scenarios.py +103 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_schedule_model_override.py +39 -0
- tsugite_cli-0.14.0/tests/test_scheduler_history_injection.py +363 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_schema.py +4 -3
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_secrets.py +37 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_security_phase1.py +50 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_session_metadata.py +34 -0
- tsugite_cli-0.14.0/tests/test_session_progress_cache.py +139 -0
- tsugite_cli-0.14.0/tests/test_shell_tool_cwd.py +82 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_skill_discovery.py +172 -4
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_skill_tools.py +103 -0
- tsugite_cli-0.14.0/tests/test_step_render_framework_flags.py +108 -0
- tsugite_cli-0.14.0/tests/test_time_tool.py +47 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_tool_registry.py +13 -0
- tsugite_cli-0.14.0/tests/test_unified_event_log.py +185 -0
- tsugite_cli-0.14.0/tests/test_user_agent.py +99 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/__init__.py +6 -1
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/agent_inheritance.py +16 -20
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/agent_preparation.py +382 -62
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/agent_runner/__init__.py +5 -0
- tsugite_cli-0.14.0/tsugite/agent_runner/exec_directives.py +124 -0
- tsugite_cli-0.14.0/tsugite/agent_runner/exec_runner.py +222 -0
- tsugite_cli-0.14.0/tsugite/agent_runner/history_integration.py +245 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/agent_runner/models.py +1 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/agent_runner/runner.py +226 -80
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/attachments/base.py +16 -1
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/attachments/url.py +6 -5
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/builtin_agents/default.md +48 -20
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/builtin_agents/file_searcher.md +1 -1
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/builtin_agents/onboard.md +1 -1
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/builtin_skills/tsugite-agent-basics/SKILL.md +22 -6
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/cli/__init__.py +2 -4
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/cli/daemon.py +66 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/cli/helpers.py +28 -2
- tsugite_cli-0.14.0/tsugite/cli/history.py +715 -0
- tsugite_cli-0.14.0/tsugite/cli/plugins.py +237 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/cli/render.py +12 -4
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/cli/run.py +43 -21
- tsugite_cli-0.14.0/tsugite/cli/skills.py +77 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/config.py +1 -1
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/core/agent.py +453 -366
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/core/claude_code.py +28 -3
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/core/executor.py +162 -94
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/core/memory.py +3 -0
- tsugite_cli-0.14.0/tsugite/core/state.py +76 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/core/subprocess_executor.py +142 -110
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/core/tools.py +0 -1
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/adapters/base.py +421 -185
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/adapters/discord.py +170 -58
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/adapters/http.py +501 -285
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/adapters/scheduler_adapter.py +99 -33
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/commands.py +7 -5
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/compaction_scheduler.py +10 -2
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/config.py +5 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/gateway.py +9 -2
- tsugite_cli-0.14.0/tsugite/daemon/memory.py +507 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/scheduler.py +21 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/session_runner.py +44 -1
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/session_store.py +524 -41
- tsugite_cli-0.14.0/tsugite/daemon/web/css/console.css +1720 -0
- tsugite_cli-0.14.0/tsugite/daemon/web/css/responsive.css +111 -0
- tsugite_cli-0.14.0/tsugite/daemon/web/css/styles.css +239 -0
- tsugite_cli-0.14.0/tsugite/daemon/web/css/theme.css +61 -0
- tsugite_cli-0.14.0/tsugite/daemon/web/index.html +1772 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/web/js/api.js +10 -2
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/web/js/app.js +81 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/web/js/utils.js +20 -0
- tsugite_cli-0.14.0/tsugite/daemon/web/js/views/conversation/event_types.js +71 -0
- tsugite_cli-0.14.0/tsugite/daemon/web/js/views/conversation/history.js +425 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/web/js/views/conversation/input.js +1 -1
- tsugite_cli-0.14.0/tsugite/daemon/web/js/views/conversation/sessions.js +476 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/web/js/views/conversation/streaming.js +120 -47
- tsugite_cli-0.14.0/tsugite/daemon/web/js/views/conversations.js +687 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/web/js/views/file-editor.js +3 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/web/js/views/usage.js +2 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/web/manifest.json +1 -1
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/events/__init__.py +5 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/events/base.py +14 -0
- tsugite_cli-0.14.0/tsugite/events/bus.py +114 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/events/events.py +40 -1
- tsugite_cli-0.14.0/tsugite/exceptions.py +66 -0
- tsugite_cli-0.14.0/tsugite/history/__init__.py +24 -0
- tsugite_cli-0.14.0/tsugite/history/models.py +46 -0
- tsugite_cli-0.14.0/tsugite/history/reconstruction.py +173 -0
- tsugite_cli-0.14.0/tsugite/history/storage.py +224 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/hooks.py +55 -1
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/md_agents.py +173 -9
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/models.py +59 -6
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/options.py +1 -3
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/plugins.py +91 -37
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/providers/anthropic.py +39 -14
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/providers/base.py +2 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/providers/claude_code.py +37 -7
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/providers/model_registry.py +5 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/providers/openai_compat.py +12 -8
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/renderer.py +138 -21
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/schemas/__init__.py +6 -3
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/schemas/agent.schema.json +80 -24
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/secrets/registry.py +21 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/skill_discovery.py +92 -24
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/tools/__init__.py +22 -8
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/tools/agents.py +27 -17
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/tools/fs.py +139 -27
- tsugite_cli-0.14.0/tsugite/tools/history.py +240 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/tools/http.py +25 -16
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/tools/interactive.py +8 -10
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/tools/schedule.py +22 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/tools/secrets.py +10 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/tools/shell.py +11 -2
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/tools/skills.py +64 -2
- tsugite_cli-0.14.0/tsugite/tools/time.py +16 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/ui/jsonl.py +23 -2
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/ui/repl_commands.py +23 -21
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/user_agent.py +28 -3
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/utils.py +32 -1
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/workspace/models.py +10 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/workspace/session.py +9 -9
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/uv.lock +666 -882
- tsugite_cli-0.12.2/.github/workflows/pypi-publish.yml +0 -37
- tsugite_cli-0.12.2/docs/plugin-hooks.md +0 -64
- tsugite_cli-0.12.2/tests/daemon/test_http_adapter.py +0 -534
- tsugite_cli-0.12.2/tests/test_attachments.py +0 -448
- tsugite_cli-0.12.2/tests/test_cache_control.py +0 -181
- tsugite_cli-0.12.2/tests/test_continuation.py +0 -453
- tsugite_cli-0.12.2/tests/test_daemon_history_persistence.py +0 -514
- tsugite_cli-0.12.2/tests/test_daemon_memory.py +0 -481
- tsugite_cli-0.12.2/tests/test_daemon_session_isolation.py +0 -265
- tsugite_cli-0.12.2/tests/test_history.py +0 -414
- tsugite_cli-0.12.2/tests/test_history_integration.py +0 -715
- tsugite_cli-0.12.2/tests/test_history_models.py +0 -517
- tsugite_cli-0.12.2/tests/test_history_performance.py +0 -202
- tsugite_cli-0.12.2/tests/test_history_tools.py +0 -286
- tsugite_cli-0.12.2/tests/test_mcp_client.py +0 -378
- tsugite_cli-0.12.2/tests/test_mcp_server.py +0 -109
- tsugite_cli-0.12.2/tests/test_reasoning_models.py +0 -62
- tsugite_cli-0.12.2/tests/test_scheduler_history_injection.py +0 -172
- tsugite_cli-0.12.2/tsugite/agent_runner/history_integration.py +0 -306
- tsugite_cli-0.12.2/tsugite/cli/history.py +0 -413
- tsugite_cli-0.12.2/tsugite/cli/mcp.py +0 -193
- tsugite_cli-0.12.2/tsugite/cli/plugins.py +0 -77
- tsugite_cli-0.12.2/tsugite/cli/serve.py +0 -41
- tsugite_cli-0.12.2/tsugite/daemon/memory.py +0 -333
- tsugite_cli-0.12.2/tsugite/daemon/web/css/responsive.css +0 -191
- tsugite_cli-0.12.2/tsugite/daemon/web/css/styles.css +0 -387
- tsugite_cli-0.12.2/tsugite/daemon/web/css/theme.css +0 -47
- tsugite_cli-0.12.2/tsugite/daemon/web/index.html +0 -1344
- tsugite_cli-0.12.2/tsugite/daemon/web/js/views/conversation/history.js +0 -184
- tsugite_cli-0.12.2/tsugite/daemon/web/js/views/conversation/sessions.js +0 -207
- tsugite_cli-0.12.2/tsugite/daemon/web/js/views/conversations.js +0 -345
- tsugite_cli-0.12.2/tsugite/events/bus.py +0 -62
- tsugite_cli-0.12.2/tsugite/exceptions.py +0 -33
- tsugite_cli-0.12.2/tsugite/history/__init__.py +0 -54
- tsugite_cli-0.12.2/tsugite/history/models.py +0 -147
- tsugite_cli-0.12.2/tsugite/history/reconstruction.py +0 -348
- tsugite_cli-0.12.2/tsugite/history/storage.py +0 -619
- tsugite_cli-0.12.2/tsugite/mcp_client.py +0 -221
- tsugite_cli-0.12.2/tsugite/mcp_config.py +0 -174
- tsugite_cli-0.12.2/tsugite/mcp_server.py +0 -144
- tsugite_cli-0.12.2/tsugite/tools/history.py +0 -190
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/CLAUDE.md +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/LICENSE +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/docs/secrets.md +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/docs/test_agents/prefresh_readme.md +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/docs/test_agents/template_test.md +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/docs/test_agents/test_agent.md +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/docs/test_agents/test_steps.md +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/mise.toml +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/scripts/backfill_usage.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/scripts/regenerate_schema.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/__init__.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/core/__init__.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/core/test_agent_context_tokens.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/core/test_memory.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/core/test_proxy.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/core/test_sandbox.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/core/test_tools.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/daemon/__init__.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/e2e/__init__.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/e2e/conftest.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/e2e/test_auth.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/e2e/test_chat.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/e2e/test_context_bar.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/e2e/test_draft_persistence.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/e2e/test_history.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/e2e/test_page_load.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/e2e/test_prompt_inspector.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/e2e/test_sessions.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/e2e/test_sidebar_redesign.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/e2e/test_sse_metadata.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/events/test_event_consolidation.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_agent_file_hot_loading.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_agent_parser.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_agent_utils.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_agents_tool.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_attachment_deduplication.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_auto_context_handler.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_auto_discovery.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_background_task_status.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_chat_cli.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_chat_error_handling.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_cli_arguments.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_completion_callbacks.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_config.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_custom_shell_tools.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_custom_ui.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_daemon_auth.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_daemon_compaction_scheduler.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_daemon_config.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_daemon_push.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_daemon_scheduler.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_error_display.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_file_references.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_interaction_backends.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_interactive_tool.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_list_agents_tool.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_models.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_multi_agent.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_orchestrator_heartbeat.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_prompt_snapshot.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_provider_registry.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_repl_commands.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_repl_completer.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_repl_handler.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_retry_system.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_run_if.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_secret_access_event.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_send_message.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_session_orchestrator_tools.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_stdin.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_subagent_subprocess.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_tool_directives.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_workspace_auto_continue.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_workspace_cwd.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tests/test_workspace_discovery.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/agent_runner/helpers.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/agent_runner/metrics.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/agent_runner/validation.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/agent_utils.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/attachments/__init__.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/attachments/auto_context.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/attachments/file.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/attachments/inline.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/attachments/storage.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/attachments/youtube.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/builtin_agents/.gitkeep +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/builtin_agents/code_searcher.md +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/builtin_skills/.gitkeep +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/builtin_skills/codebase-exploration/SKILL.md +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/builtin_skills/python-math/SKILL.md +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/builtin_skills/response-patterns/SKILL.md +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/builtin_skills/scheduling/SKILL.md +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/builtin_skills/skill-authoring/SKILL.md +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/builtin_skills/tsugite-jinja-reference/SKILL.md +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/builtin_skills/tsugite-skill-basics/SKILL.md +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/cache.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/cli/agents.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/cli/attachments.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/cli/cache.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/cli/chat.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/cli/config.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/cli/init.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/cli/models.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/cli/secrets.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/cli/tools.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/cli/usage.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/cli/validate.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/cli/workspace.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/console.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/constants.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/core/__init__.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/core/content_blocks.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/core/proxy.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/core/sandbox.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/__init__.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/adapters/__init__.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/auth.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/push.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/web/icons/icon-192.png +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/web/icons/icon-512-maskable.png +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/web/icons/icon-512.png +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/web/icons/screenshot-narrow.png +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/web/icons/screenshot-wide.png +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/web/js/vendor/marked.LICENSE.md +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/web/js/vendor/marked.esm.min.js +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/web/js/views/conversation/attachments.js +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/web/js/views/schedules.js +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/web/js/views/webhooks.js +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/web/js/views/workspace.js +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/web/sw.js +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/daemon/webhook_store.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/events/helpers.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/interaction.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/providers/__init__.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/providers/model_cache.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/providers/ollama.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/providers/openrouter.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/secrets/__init__.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/secrets/backend.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/secrets/env.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/secrets/exec.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/secrets/file.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/secrets/masking.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/secrets/sqlite.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/shell_tool_config.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/templates/AGENTS.md +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/templates/IDENTITY.md +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/templates/MEMORY.md +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/templates/USER.md +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/templates/personas/casual-technical.md +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/templates/personas/marvin.md +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/templates/personas/minimal.md +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/tools/notify.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/tools/scratchpad.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/tools/sessions.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/tools/shell_tools.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/tsugite.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/ui/__init__.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/ui/base.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/ui/chat.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/ui/helpers.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/ui/plain.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/ui/repl_chat.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/ui/repl_completer.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/ui/repl_handler.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/ui_context.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/usage/__init__.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/usage/store.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/workspace/__init__.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/workspace/context.py +0 -0
- {tsugite_cli-0.12.2 → tsugite_cli-0.14.0}/tsugite/workspace/templates.py +0 -0
|
@@ -4,16 +4,16 @@ Tsugite is a micro-agent CLI: agents are Markdown + YAML frontmatter, rendered v
|
|
|
4
4
|
|
|
5
5
|
### Architecture
|
|
6
6
|
|
|
7
|
-
**Flow:** `Agent.md` (YAML + Jinja2) → `renderer.py` → `TsugiteAgent` →
|
|
7
|
+
**Flow:** `Agent.md` (YAML + Jinja2) → `renderer.py` → `TsugiteAgent` → Provider → Tools
|
|
8
8
|
|
|
9
9
|
**Key Modules:**
|
|
10
|
-
- `cli/__init__.py` - Typer CLI (run, chat, render, config,
|
|
10
|
+
- `cli/__init__.py` - Typer CLI (run, chat, render, config, tools, agents, attachments, cache)
|
|
11
11
|
- `md_agents.py` - Parse frontmatter + agent resolution + directives
|
|
12
12
|
- `builtin_agents/` - File-based built-in agent definitions (default.md, chat-assistant.md)
|
|
13
13
|
- `agent_inheritance.py` - Agent resolution pipeline + inheritance chain
|
|
14
14
|
- `chat.py` - Chat session management with history
|
|
15
15
|
- `agent_runner.py` - Execution orchestration, prefetch, tool wiring, multi-step
|
|
16
|
-
- `core/agent.py` -
|
|
16
|
+
- `core/agent.py` - agent loop + streaming
|
|
17
17
|
- `renderer.py` - Jinja2 rendering + helpers (now, today, slugify, env, file_exists, read_text, is_file, is_dir)
|
|
18
18
|
- `tools/` - Tool registry + implementations
|
|
19
19
|
- `shell_tool_config.py` + `tools/shell_tools.py` - Custom shell command wrappers
|
|
@@ -62,7 +62,6 @@ File-based agents distributed with the package in `tsugite/builtin_agents/` dire
|
|
|
62
62
|
**Merge rules:**
|
|
63
63
|
- Scalars (model, max_steps): Child overwrites
|
|
64
64
|
- Lists (tools): Merge + deduplicate
|
|
65
|
-
- Dicts (mcp_servers): Merge, child keys override
|
|
66
65
|
- Strings (instructions): Concatenate with `\n\n`
|
|
67
66
|
|
|
68
67
|
**Opt-out:** `extends: none` skips all inheritance.
|
|
@@ -236,7 +235,6 @@ assert tool is not None
|
|
|
236
235
|
|
|
237
236
|
**Safety:**
|
|
238
237
|
- Shell tool guard: Never relax dangerous patterns blocklist
|
|
239
|
-
- MCP: Requires `--trust-mcp-code` flag
|
|
240
238
|
- File ops: Use `Path.resolve()` to prevent traversal
|
|
241
239
|
|
|
242
240
|
**Testing:** Test-first workflow. Add minimal failing test, run target, widen to full suite before merge.
|
|
@@ -28,7 +28,7 @@ jobs:
|
|
|
28
28
|
enable-cache: true
|
|
29
29
|
|
|
30
30
|
- name: Install dependencies
|
|
31
|
-
run: uv sync --dev
|
|
31
|
+
run: uv sync --dev --all-extras
|
|
32
32
|
|
|
33
33
|
- name: Run ruff check
|
|
34
34
|
run: uv run ruff check --show-fixes .
|
|
@@ -58,7 +58,7 @@ jobs:
|
|
|
58
58
|
enable-cache: true
|
|
59
59
|
|
|
60
60
|
- name: Install dependencies
|
|
61
|
-
run: uv sync --dev
|
|
61
|
+
run: uv sync --dev --all-extras
|
|
62
62
|
|
|
63
63
|
- name: Run tests
|
|
64
64
|
run: uv run pytest -v
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build-and-publish:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
permissions:
|
|
13
|
+
contents: write # Required for creating GitHub releases
|
|
14
|
+
id-token: write # Required for PyPI trusted publishing
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- name: Checkout repository
|
|
18
|
+
uses: actions/checkout@v4
|
|
19
|
+
with:
|
|
20
|
+
fetch-depth: 0 # Full history so auto-generated release notes can diff
|
|
21
|
+
|
|
22
|
+
- name: Set up Python
|
|
23
|
+
uses: actions/setup-python@v5
|
|
24
|
+
with:
|
|
25
|
+
python-version: "3.12"
|
|
26
|
+
|
|
27
|
+
- name: Install uv
|
|
28
|
+
uses: astral-sh/setup-uv@v5
|
|
29
|
+
|
|
30
|
+
- name: Build all workspace packages
|
|
31
|
+
run: uv build --all-packages
|
|
32
|
+
|
|
33
|
+
- name: Publish to PyPI
|
|
34
|
+
# Trusted publishing: each package (tsugite-cli, tsugite-tmux, ...) must be
|
|
35
|
+
# registered separately on PyPI as a trusted publisher pointing at this workflow.
|
|
36
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
37
|
+
|
|
38
|
+
- name: Generate release notes from conventional commits
|
|
39
|
+
id: changelog
|
|
40
|
+
uses: orhun/git-cliff-action@v4
|
|
41
|
+
with:
|
|
42
|
+
config: cliff.toml
|
|
43
|
+
args: --latest --strip header
|
|
44
|
+
|
|
45
|
+
- name: Create GitHub release
|
|
46
|
+
uses: softprops/action-gh-release@v2
|
|
47
|
+
with:
|
|
48
|
+
body: ${{ steps.changelog.outputs.content }}
|
|
49
|
+
files: dist/*
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
This file provides guidance to AI agents (tsugite, Claude Code, etc.) when working with code in this repository.
|
|
4
4
|
|
|
5
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for commit message conventions and PR guidelines.
|
|
6
|
+
|
|
5
7
|
## Commands
|
|
6
8
|
|
|
7
9
|
### Development Setup
|
|
8
10
|
```bash
|
|
9
|
-
# Install dependencies
|
|
10
|
-
uv sync --
|
|
11
|
+
# Install dependencies (core + daemon extras + core plugins)
|
|
12
|
+
uv sync --all-extras
|
|
11
13
|
|
|
12
14
|
# Run all tests
|
|
13
15
|
uv run pytest
|
|
@@ -54,7 +56,7 @@ Tsugite is an agentic CLI that executes AI agents defined as markdown files with
|
|
|
54
56
|
1. **CLI Entry** (`tsugite/cli/__init__.py`)
|
|
55
57
|
- Typer-based CLI with subcommands
|
|
56
58
|
- Main commands: `run` (single-shot), `chat` (interactive), `render` (preview)
|
|
57
|
-
- Additional: `daemon`, `workspace`, `init`, `validate`, `
|
|
59
|
+
- Additional: `daemon`, `workspace`, `init`, `validate`, `agents`, `config`, `attachments`, `cache`, `tools`, `history`
|
|
58
60
|
|
|
59
61
|
2. **Agent Resolution & Inheritance** (`tsugite/agent_inheritance.py`)
|
|
60
62
|
- Resolves agent names to file paths using search order:
|
|
@@ -73,6 +75,7 @@ Tsugite is an agentic CLI that executes AI agents defined as markdown files with
|
|
|
73
75
|
- `<!-- tsu:step -->` - Multi-step workflow stages
|
|
74
76
|
- `<!-- tsu:ignore -->` - Documentation blocks (stripped before LLM)
|
|
75
77
|
- `<!-- tsu:tool -->` - Execute tools during rendering
|
|
78
|
+
- `<!-- tsu:exec --> ... <!-- /tsu:exec -->` - Run arbitrary Python at render time, capture result into Jinja context
|
|
76
79
|
|
|
77
80
|
4. **Agent Preparation** (`tsugite/agent_preparation.py`)
|
|
78
81
|
- **Unified preparation pipeline** (used by both `run` and `render` commands)
|
|
@@ -102,22 +105,20 @@ Tsugite is an agentic CLI that executes AI agents defined as markdown files with
|
|
|
102
105
|
- Integrates with history system for conversation continuity
|
|
103
106
|
|
|
104
107
|
7. **LLM Agent Loop** (`tsugite/core/agent.py`)
|
|
105
|
-
- `TsugiteAgent` - Custom agent using
|
|
108
|
+
- `TsugiteAgent` - Custom agent using tsugite's provider abstraction
|
|
106
109
|
- Think-Code-Observation loop (max_turns iterations)
|
|
107
110
|
- Supports reasoning models (o1, o3, Claude extended thinking)
|
|
108
111
|
- Direct control over model parameters (temperature, reasoning_effort)
|
|
109
112
|
- Code execution via `LocalExecutor`
|
|
110
113
|
|
|
111
114
|
8. **Tool System** (`tsugite/tools/`)
|
|
112
|
-
- Tool registry with built-in tools (fs, http, shell,
|
|
113
|
-
-
|
|
114
|
-
-
|
|
115
|
-
- MCP integration (`tsugite/mcp_client.py`)
|
|
116
|
-
- Tool expansion supports globs (`*_search`) and exclusions (`-delete_file`)
|
|
115
|
+
- Tool registry with built-in tools (fs, http, shell, agents, skills, history, interactive) plus optional categories (notify, schedule, scratchpad, sessions, secrets, tmux — gated by `_OPTIONAL_CATEGORIES` in `tools/__init__.py`)
|
|
116
|
+
- Custom shell tools (config-based command wrappers in `tools/shell_tools.py`)
|
|
117
|
+
- Tool expansion supports globs (`*_search`), categories (`@fs`), and exclusions (`-delete_file`)
|
|
117
118
|
|
|
118
119
|
9. **Event System** (`tsugite/events/`)
|
|
119
120
|
- Event-driven architecture for UI decoupling
|
|
120
|
-
-
|
|
121
|
+
- 28 event types: execution, LLM, meta, progress, skills
|
|
121
122
|
- `EventBus` dispatches to multiple handlers
|
|
122
123
|
- Handlers: Rich console, plain text, JSONL, chat, REPL
|
|
123
124
|
|
|
@@ -131,17 +132,16 @@ Tsugite is an agentic CLI that executes AI agents defined as markdown files with
|
|
|
131
132
|
- XDG-compliant paths: `~/.config/tsugite/` or `$XDG_CONFIG_HOME/tsugite/`
|
|
132
133
|
- JSON config with model aliases, default settings
|
|
133
134
|
- Attachment storage (reusable context)
|
|
134
|
-
- MCP server registration
|
|
135
135
|
- Auto-context discovery (CLAUDE.md, AGENTS.md, CONTEXT.md)
|
|
136
136
|
|
|
137
137
|
### Key Data Structures
|
|
138
138
|
|
|
139
|
-
**AgentConfig** (`md_agents.py:
|
|
139
|
+
**AgentConfig** (`md_agents.py:36`)
|
|
140
140
|
- Pydantic model for agent frontmatter
|
|
141
141
|
- Validates all fields (name, model, tools, max_turns, etc.)
|
|
142
142
|
- Schema exported to `tsugite/schemas/agent.schema.json`
|
|
143
143
|
|
|
144
|
-
**PreparedAgent** (`agent_preparation.py:
|
|
144
|
+
**PreparedAgent** (`agent_preparation.py:69`)
|
|
145
145
|
- Dataclass containing everything for execution/display
|
|
146
146
|
- Ensures `render` shows exactly what `run` executes
|
|
147
147
|
- Contains: agent, config, system_message, user_message, tools, context
|
|
@@ -180,6 +180,37 @@ Summarize findings
|
|
|
180
180
|
- Safety: `max_iterations` (default 10) prevents infinite loops
|
|
181
181
|
- Loop context: `{{ iteration }}`, `{{ max_iterations }}`, `{{ is_looping_step }}`
|
|
182
182
|
|
|
183
|
+
### Exec Directives
|
|
184
|
+
|
|
185
|
+
`<!-- tsu:exec name="..." assign="..." -->...<!-- /tsu:exec -->` runs an arbitrary Python block at agent-prep time and binds the return value (or last expression) to a Jinja variable. Use it for deterministic dispatchers, preprocessing, and branching that don't justify an LLM round-trip.
|
|
186
|
+
|
|
187
|
+
```markdown
|
|
188
|
+
<!-- tsu:exec name="dispatch" assign="targets" -->
|
|
189
|
+
import os, json
|
|
190
|
+
out = []
|
|
191
|
+
for p in sorted(os.listdir("inbox")):
|
|
192
|
+
if p.endswith(".json"):
|
|
193
|
+
out.append({"path": p, "source": json.loads(open(f"inbox/{p}").read())["source"]})
|
|
194
|
+
out
|
|
195
|
+
<!-- /tsu:exec -->
|
|
196
|
+
|
|
197
|
+
Inventory: {{ targets }}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**Semantics:**
|
|
201
|
+
- Block body is opaque to Jinja; prior-directive vars (prefetch, tool, earlier exec) arrive as **Python locals**, not via `{{ }}` substitution. So `{{ }}` literals inside Python strings work.
|
|
202
|
+
- Return value: explicit `return_value(x)` or the last expression in the block (Jupyter-style). Explicit `return_value` wins.
|
|
203
|
+
- Plain Python is allowed (`open`, `os`, etc.) - the directive is for trusted preprocessing, distinct from LLM-emitted code in `tsugite/core/subprocess_executor.py`.
|
|
204
|
+
- Top-level only in v1: between/before/after `tsu:step` directives, never inside step content.
|
|
205
|
+
|
|
206
|
+
**Optional attributes:** `assign="var"`, `stdout_assign="var"`, `timeout=30`, `continue_on_error=true`.
|
|
207
|
+
|
|
208
|
+
**Render mode:** `tsu render` executes exec blocks by default. Pass `--no-exec` to substitute placeholders instead (e.g. when the block has side effects you want to inspect without running).
|
|
209
|
+
|
|
210
|
+
**Return-type policy:** values must JSON-serialize. `Path -> str`, `datetime -> isoformat()`, `set -> sorted list` are coerced automatically. Other non-serializable types raise (convert explicitly).
|
|
211
|
+
|
|
212
|
+
See `examples/exec_dispatcher.md` for a runnable inbox-watcher pattern.
|
|
213
|
+
|
|
183
214
|
### Event-Driven UI
|
|
184
215
|
|
|
185
216
|
All UI output goes through the event system:
|
|
@@ -241,7 +272,7 @@ Tsugite supports vision (images), audio, and document understanding through the
|
|
|
241
272
|
**How It Works:**
|
|
242
273
|
|
|
243
274
|
1. **URL Attachments** (Images/Documents):
|
|
244
|
-
-
|
|
275
|
+
- The provider fetches the URL directly (no download overhead — support varies by provider and content type; see `tsugite/attachments/url.py`)
|
|
245
276
|
- Example: `tsu run -f https://example.com/chart.png "Describe this chart"`
|
|
246
277
|
- Automatically detected via HTTP HEAD request
|
|
247
278
|
|
|
@@ -286,6 +317,63 @@ tsu run -f image1.jpg -f image2.jpg "Compare these images"
|
|
|
286
317
|
- YouTube handler: `tsugite/attachments/youtube.py` (fetches transcripts)
|
|
287
318
|
- LLM formatting: `tsugite/core/agent.py:_format_attachment()`
|
|
288
319
|
|
|
320
|
+
#### Frontmatter Attachment Specs
|
|
321
|
+
|
|
322
|
+
The `attachments:` field accepts either plain string paths (legacy) or dict-form `AttachmentSpec` entries. Both forms can be mixed in the same list.
|
|
323
|
+
|
|
324
|
+
**String form** (existing): rendered through Jinja, then loaded as a single file. Prefix with `-` to remove a workspace default (e.g., `-MEMORY.md`).
|
|
325
|
+
|
|
326
|
+
```yaml
|
|
327
|
+
attachments:
|
|
328
|
+
- MEMORY.md
|
|
329
|
+
- "{{ today() }}.md"
|
|
330
|
+
- -SKIP.md # remove a workspace default named SKIP.md
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
**Dict form** (`AttachmentSpec`): adds `assign:`, `mode: index`, glob expansion, and other knobs.
|
|
334
|
+
|
|
335
|
+
```yaml
|
|
336
|
+
attachments:
|
|
337
|
+
- path: MEMORY.md
|
|
338
|
+
assign: memory_content # bind file content as Jinja variable
|
|
339
|
+
|
|
340
|
+
- path: USER.md
|
|
341
|
+
assign: user_prefs
|
|
342
|
+
attach: false # bind variable but don't inject into prompt
|
|
343
|
+
|
|
344
|
+
- path: "memory/topics/*.md" # glob - one Attachment per matched file
|
|
345
|
+
assign: topic_files # bound as list[dict] of {path, content}
|
|
346
|
+
|
|
347
|
+
- path: "memory/topics/*.md"
|
|
348
|
+
mode: index # render path+heading list, not full content
|
|
349
|
+
name: topic_index # explicit attachment name (default derives from glob)
|
|
350
|
+
assign: topics # bound as list[dict] of {path, heading, size_bytes, mtime}
|
|
351
|
+
index_format: first_heading # path_only | first_line | first_heading | frontmatter
|
|
352
|
+
max_entries: 50 # cap, warns if exceeded
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
**Variable shapes** (when `assign:` is set):
|
|
356
|
+
|
|
357
|
+
| Spec | Shape |
|
|
358
|
+
|---|---|
|
|
359
|
+
| `mode: full`, single concrete file | `str` (file content) |
|
|
360
|
+
| `mode: full`, glob | `list[dict]` of `{path, content}` (binaries skipped) |
|
|
361
|
+
| `mode: index` | `list[dict]` of `{path, heading, size_bytes, mtime}` |
|
|
362
|
+
| Single file, missing | `None` |
|
|
363
|
+
| Empty glob | `[]` |
|
|
364
|
+
|
|
365
|
+
**Constraints (validated at parse time):**
|
|
366
|
+
- `assign:` must be a valid Python identifier.
|
|
367
|
+
- Two specs can't share the same `assign` value.
|
|
368
|
+
- `attach: false` requires `assign:` (otherwise the attachment loads for nothing).
|
|
369
|
+
- `path:` cannot start with `-` (use string form for removal).
|
|
370
|
+
|
|
371
|
+
**Index mode rendering** wraps the formatted index in an existing `<attachment>` tag with a `mode="index"` attribute, e.g. `<attachment name="topic_index" mode="index">...</attachment>`. Agents are expected to call `read_file(path=...)` to fetch individual entries on demand.
|
|
372
|
+
|
|
373
|
+
**Collisions:** if an `assign:` name shadows a built-in or prefetch variable, the assignment wins and a warning is logged.
|
|
374
|
+
|
|
375
|
+
See `examples/attachment_assign_demo.md` and `examples/attachment_index_demo.md` for runnable references.
|
|
376
|
+
|
|
289
377
|
## Development Patterns
|
|
290
378
|
|
|
291
379
|
### Adding a New Built-in Agent
|
|
@@ -315,14 +403,31 @@ tsu run -f image1.jpg -f image2.jpg "Compare these images"
|
|
|
315
403
|
|
|
316
404
|
1. Update `AgentConfig` Pydantic model (`md_agents.py`)
|
|
317
405
|
2. Regenerate schema: `uv run python scripts/regenerate_schema.py`
|
|
318
|
-
3. Update documentation in
|
|
406
|
+
3. Update relevant documentation in `AGENTS.md` and any user-facing doc under `docs/`
|
|
319
407
|
4. Add validation tests in `tests/test_agent_parser.py`
|
|
320
408
|
|
|
321
409
|
## Testing Strategy
|
|
322
410
|
|
|
323
|
-
|
|
411
|
+
### TDD is the default
|
|
412
|
+
|
|
413
|
+
For any non-trivial bug fix or feature, write a failing test **first**. Exceptions: typo fixes, docs, pure refactors, and changes the user has explicitly scoped as exploratory.
|
|
414
|
+
|
|
415
|
+
The workflow:
|
|
416
|
+
|
|
417
|
+
1. **Reproduce before fixing.** Write the smallest test that demonstrates the symptom as reported. Run it. If it passes on master, the hypothesis is wrong — do not write a fix. Investigate further, ask the user for more detail, or add logging.
|
|
418
|
+
2. **Implement the fix.** Keep the change minimal. Do not refactor or add adjacent cleanup in the same diff.
|
|
419
|
+
3. **Verify the test is load-bearing.** Temp-revert the production change and re-run. The test must go red again. If it still passes, the test isn't actually exercising the fix — rework it.
|
|
420
|
+
4. **Cover adjacent cases before declaring done.** When touching a parser, protocol boundary, or state machine, enumerate at least two adjacent input shapes and add tests for them. Narrow tests let bugs sneak in through the cases you didn't think about.
|
|
421
|
+
5. **Run the local regression suite.** At minimum, the test files next to the modules you changed. Faster than running everything, catches silent breakage of existing tests.
|
|
422
|
+
6. **Honest uncertainty.** If a hypothesis doesn't reproduce, say so. Don't ship a "probably-this" fix with no failing test to anchor it — that's how placebo fixes get merged.
|
|
423
|
+
|
|
424
|
+
Reproducing tests don't need to be elaborate. A 10-line test that flips red→green is worth more than a 100-line one that nobody understands.
|
|
425
|
+
|
|
426
|
+
### Test layers
|
|
427
|
+
|
|
324
428
|
- **Unit tests**: Individual functions and classes
|
|
325
|
-
- **Pipeline tests**: Mock only `TsugiteAgent
|
|
429
|
+
- **Pipeline tests**: Mock only `TsugiteAgent` / the provider's `acompletion` but exercise the full pipeline (parsing → rendering → preparation → tool expansion → execution). Most tests in the suite are this style.
|
|
430
|
+
- **Integration tests**: Live under `tests/integration/` (not collected by default — see `pyproject.toml` `norecursedirs`). Run explicitly with `uv run pytest tests/integration/`. Good for concurrency, cwd, and daemon-wiring tests that need real threading or a real workspace.
|
|
326
431
|
- **Smoke tests**: `tests/smoke_test.sh` hits a real LLM API (requires `OPENAI_API_KEY`, not run in CI)
|
|
327
432
|
- **Fixtures**: `conftest.py` provides shared test data
|
|
328
433
|
- **Mocking**: Use `@pytest.fixture` for LLM responses
|
|
@@ -348,6 +453,28 @@ tsu run -f image1.jpg -f image2.jpg "Compare these images"
|
|
|
348
453
|
6. **Test both sync and async paths**: Many tools support both execution modes
|
|
349
454
|
7. **Don't embed prompts in adapters/code**: Use context variables + conditional blocks in `default.md` instead. Add new context vars in `_build_agent_context()` (base adapter) and default them in `agent_preparation.py`, then use `{% if var %}` in the agent template. This keeps all prompt content in one place and leverages the existing rendering pipeline.
|
|
350
455
|
|
|
456
|
+
## Web UI
|
|
457
|
+
|
|
458
|
+
The daemon's web UI lives at `tsugite/daemon/web/`.
|
|
459
|
+
|
|
460
|
+
### Stack
|
|
461
|
+
|
|
462
|
+
- **Alpine.js 3** loaded from CDN. No build step. No React. Don't port this to a framework - the design handoff explicitly said match visuals, not internal structure.
|
|
463
|
+
- **Starlette** serves `index.html` plus `/static/{css,js,icons}` and the `/api/*` routes (`tsugite/daemon/adapters/http.py`).
|
|
464
|
+
- CSS lives in three files. Read all three before adding rules: `theme.css` (Catppuccin tokens), `console.css` (Console redesign - the real stylesheet), `styles.css` (legacy modals/auth/forms; ~120 lines, pruned aggressively after the redesign).
|
|
465
|
+
- View modules under `js/views/`: `conversations.js` (orchestrator) + `conversation/{sessions,history,streaming,input,attachments,event_types}.js` mixins, plus `workspace.js`, `schedules.js`, `webhooks.js`, `usage.js`, `file-editor.js`. Shared helpers: `js/api.js` (REST + SSE), `js/utils.js` (markdown, formatters, toast).
|
|
466
|
+
|
|
467
|
+
### Theme tokens
|
|
468
|
+
|
|
469
|
+
- Use **bare token names** - `var(--base)`, `var(--mantle)`, `var(--crust)`, `var(--surface0/1/2)`, `var(--text)`, `var(--lavender)`, `var(--blue)`, `var(--peach)`, etc. The legacy `--ctp-*` aliases were removed.
|
|
470
|
+
- **Visual depth is `crust < mantle < base`** (darker → lighter on Frappé/Mocha/Macchiato). For dark-on-dark panels, panels go `var(--mantle)` and inner cards `var(--surface0)` or `var(--crust)`. Don't put a brighter (`--bg`/`--base`) header over a `--mantle` panel - it inverts the depth on dark themes.
|
|
471
|
+
- Never hardcode hex colors. They won't theme-switch. Even in JS palette objects (e.g. `PI_COLORS` in `conversations.js`), use `var(--pink)` strings - they get embedded into `:style="background: ..."` and resolve through the CSS cascade.
|
|
472
|
+
- `<meta name="theme-color">` is synced to the active theme's `--crust` via an `Alpine.effect` in `app.js` so the PWA status bar / mobile chrome track the theme.
|
|
473
|
+
|
|
474
|
+
### Verification
|
|
475
|
+
|
|
476
|
+
Browser verification on UI changes is mandatory. The smoketest recipe - daemon spinup, Playwright wiring, and the post-redesign DOM selectors - is captured in the agent's project memory file `project_daemon_ui_smoketest.md`. There's also a `project_webui_console_hotzones.md` memory listing the load-bearing assumptions in the new UI (pulse signal, mid-turn reload guards, theme depth, PWA resume, mobile back-buttons) that bit during the redesign and should be re-read before touching session lifecycle, theme tokens, or PWA behaviour.
|
|
477
|
+
|
|
351
478
|
## Code Review Policy
|
|
352
479
|
|
|
353
480
|
- **Automatically run the `code-simplifier:code-simplifier` agent** (via the Task tool) after implementing any changes, without waiting for the user to ask. This catches duplication, unnecessary complexity, and keeps the codebase DRY.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Quick guide for contributors. See [AGENTS.md](AGENTS.md) for architecture and dev commands.
|
|
4
|
+
|
|
5
|
+
## Commit messages
|
|
6
|
+
|
|
7
|
+
Use [Conventional Commits](https://www.conventionalcommits.org/). Format:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
<type>(<scope>): <subject>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Keep the subject on one line, lowercase, no trailing period. Body is optional and rarely needed.
|
|
14
|
+
|
|
15
|
+
### Allowed types
|
|
16
|
+
|
|
17
|
+
These match the groups in `cliff.toml` so release notes generate cleanly:
|
|
18
|
+
|
|
19
|
+
| Type | Use for |
|
|
20
|
+
|------------|--------------------------------------------------------------|
|
|
21
|
+
| `feat` | User-visible new capability |
|
|
22
|
+
| `fix` | Bug fix |
|
|
23
|
+
| `refactor` | Code restructure with no behavior change |
|
|
24
|
+
| `docs` | Documentation only |
|
|
25
|
+
| `test` | Tests only |
|
|
26
|
+
| `chore` | Deps, version bumps, formatting, tooling, lockfile |
|
|
27
|
+
| `ci` | CI/release pipeline only |
|
|
28
|
+
| `revert` | Reverts a prior commit |
|
|
29
|
+
|
|
30
|
+
Don't use other prefixes (`wip:`, `bump:`, `lint:`, `style:`, etc.). Squash WIP commits before merging. Roll lint/format/version bumps into `chore:`.
|
|
31
|
+
|
|
32
|
+
### Breaking changes
|
|
33
|
+
|
|
34
|
+
Append `!` to the type or add a `BREAKING CHANGE:` footer:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
feat!: drop Python 3.10 support
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Scopes
|
|
41
|
+
|
|
42
|
+
Scopes are optional, but should be limited to one of these:
|
|
43
|
+
|
|
44
|
+
`webui`, `daemon`, `agent`, `cli`, `skills`, `history`, `sandbox`
|
|
45
|
+
|
|
46
|
+
### Examples
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
feat(webui): show session topic inline in sidebar
|
|
50
|
+
fix(agent): use ast.parse to locate code block close fence
|
|
51
|
+
refactor(history): per-event JSONL log replaces Turn aggregate
|
|
52
|
+
chore: bump lxml to 6.1.0 (CVE-2026-41066)
|
|
53
|
+
docs: add plugin docs
|
|
54
|
+
```
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
FROM python:3.12-slim
|
|
2
|
+
|
|
3
|
+
RUN apt-get update && apt-get upgrade -y && apt-get install -y --no-install-recommends \
|
|
4
|
+
git \
|
|
5
|
+
ripgrep \
|
|
6
|
+
curl \
|
|
7
|
+
ca-certificates \
|
|
8
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
9
|
+
|
|
10
|
+
COPY . /app
|
|
11
|
+
WORKDIR /app
|
|
12
|
+
RUN pip install --no-cache-dir ".[daemon]"
|
|
13
|
+
|
|
14
|
+
RUN useradd -m tsu && mkdir -p /workspace && chown tsu:tsu /workspace
|
|
15
|
+
USER tsu
|
|
16
|
+
WORKDIR /workspace
|
|
17
|
+
|
|
18
|
+
ENTRYPOINT ["tsu"]
|
|
19
|
+
CMD ["--help"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tsugite-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.14.0
|
|
4
4
|
Summary: Micro-agent runner for task automation using markdown definitions
|
|
5
5
|
Author: Justyn Shull
|
|
6
6
|
License: GNU AFFERO GENERAL PUBLIC LICENSE
|
|
@@ -246,7 +246,6 @@ Requires-Dist: ddgs>=9.6.0
|
|
|
246
246
|
Requires-Dist: html2text>=2020.1.16
|
|
247
247
|
Requires-Dist: httpx>=0.25
|
|
248
248
|
Requires-Dist: jinja2>=3.1
|
|
249
|
-
Requires-Dist: mcp>=1.0
|
|
250
249
|
Requires-Dist: nest-asyncio>=1.5.0
|
|
251
250
|
Requires-Dist: pathspec>=0.11.0
|
|
252
251
|
Requires-Dist: portalocker>=2.8.0
|
|
@@ -334,8 +333,8 @@ tsu run +default "summarize the files in this directory"
|
|
|
334
333
|
# Run an agent file directly
|
|
335
334
|
tsu run my-agent.md "do the thing"
|
|
336
335
|
|
|
337
|
-
# Start the web UI
|
|
338
|
-
tsu
|
|
336
|
+
# Start the daemon (web UI, Discord/Telegram bots)
|
|
337
|
+
tsu daemon
|
|
339
338
|
```
|
|
340
339
|
|
|
341
340
|
## Features
|
|
@@ -347,7 +346,6 @@ tsu serve
|
|
|
347
346
|
- **Skills** directory-based knowledge modules (mostly) following the [agentskills.io](https://agentskills.io/) SKILL.md format
|
|
348
347
|
- **Hooks** that fire shell commands on lifecycle events (post-tool, pre-message, pre/post-compact)
|
|
349
348
|
- **Sandbox** (linux only) via bubblewrap with filesystem and network isolation
|
|
350
|
-
- **MCP** integration for connecting to MCP servers
|
|
351
349
|
|
|
352
350
|
## Agents in more detail
|
|
353
351
|
|
|
@@ -395,7 +393,7 @@ All paths follow [XDG Base Directory](https://specifications.freedesktop.org/bas
|
|
|
395
393
|
|
|
396
394
|
| Path | Default | Contents |
|
|
397
395
|
|----------------------------------------|--------------------------------------|----------------------------------------------|
|
|
398
|
-
| `$XDG_CONFIG_HOME/tsugite/` | `~/.config/tsugite/` | `config.json`, `
|
|
396
|
+
| `$XDG_CONFIG_HOME/tsugite/` | `~/.config/tsugite/` | `config.json`, `daemon.yaml` |
|
|
399
397
|
| `$XDG_DATA_HOME/tsugite/history/` | `~/.local/share/tsugite/history/` | Session history (JSONL per session) |
|
|
400
398
|
| `$XDG_DATA_HOME/tsugite/daemon/` | `~/.local/share/tsugite/daemon/` | Daemon state |
|
|
401
399
|
| `$XDG_DATA_HOME/tsugite/secrets/` | `~/.local/share/tsugite/secrets/` | Encrypted secrets (`secrets.db`) |
|
|
@@ -409,7 +407,7 @@ All paths follow [XDG Base Directory](https://specifications.freedesktop.org/bas
|
|
|
409
407
|
```bash
|
|
410
408
|
git clone https://github.com/justyns/tsugite.git
|
|
411
409
|
cd tsugite
|
|
412
|
-
uv sync --
|
|
410
|
+
uv sync --all-extras
|
|
413
411
|
```
|
|
414
412
|
|
|
415
413
|
## Status
|
|
@@ -63,8 +63,8 @@ tsu run +default "summarize the files in this directory"
|
|
|
63
63
|
# Run an agent file directly
|
|
64
64
|
tsu run my-agent.md "do the thing"
|
|
65
65
|
|
|
66
|
-
# Start the web UI
|
|
67
|
-
tsu
|
|
66
|
+
# Start the daemon (web UI, Discord/Telegram bots)
|
|
67
|
+
tsu daemon
|
|
68
68
|
```
|
|
69
69
|
|
|
70
70
|
## Features
|
|
@@ -76,7 +76,6 @@ tsu serve
|
|
|
76
76
|
- **Skills** directory-based knowledge modules (mostly) following the [agentskills.io](https://agentskills.io/) SKILL.md format
|
|
77
77
|
- **Hooks** that fire shell commands on lifecycle events (post-tool, pre-message, pre/post-compact)
|
|
78
78
|
- **Sandbox** (linux only) via bubblewrap with filesystem and network isolation
|
|
79
|
-
- **MCP** integration for connecting to MCP servers
|
|
80
79
|
|
|
81
80
|
## Agents in more detail
|
|
82
81
|
|
|
@@ -124,7 +123,7 @@ All paths follow [XDG Base Directory](https://specifications.freedesktop.org/bas
|
|
|
124
123
|
|
|
125
124
|
| Path | Default | Contents |
|
|
126
125
|
|----------------------------------------|--------------------------------------|----------------------------------------------|
|
|
127
|
-
| `$XDG_CONFIG_HOME/tsugite/` | `~/.config/tsugite/` | `config.json`, `
|
|
126
|
+
| `$XDG_CONFIG_HOME/tsugite/` | `~/.config/tsugite/` | `config.json`, `daemon.yaml` |
|
|
128
127
|
| `$XDG_DATA_HOME/tsugite/history/` | `~/.local/share/tsugite/history/` | Session history (JSONL per session) |
|
|
129
128
|
| `$XDG_DATA_HOME/tsugite/daemon/` | `~/.local/share/tsugite/daemon/` | Daemon state |
|
|
130
129
|
| `$XDG_DATA_HOME/tsugite/secrets/` | `~/.local/share/tsugite/secrets/` | Encrypted secrets (`secrets.db`) |
|
|
@@ -138,7 +137,7 @@ All paths follow [XDG Base Directory](https://specifications.freedesktop.org/bas
|
|
|
138
137
|
```bash
|
|
139
138
|
git clone https://github.com/justyns/tsugite.git
|
|
140
139
|
cd tsugite
|
|
141
|
-
uv sync --
|
|
140
|
+
uv sync --all-extras
|
|
142
141
|
```
|
|
143
142
|
|
|
144
143
|
## Status
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# git-cliff config for tsugite
|
|
2
|
+
# Generates release notes from conventional commit messages.
|
|
3
|
+
# https://git-cliff.org/docs/configuration
|
|
4
|
+
|
|
5
|
+
[changelog]
|
|
6
|
+
header = ""
|
|
7
|
+
body = """
|
|
8
|
+
{% if version %}\
|
|
9
|
+
## {{ version | trim_start_matches(pat="v") }} ({{ timestamp | date(format="%Y-%m-%d") }})
|
|
10
|
+
{% else %}\
|
|
11
|
+
## Unreleased
|
|
12
|
+
{% endif %}\
|
|
13
|
+
{% for group, commits in commits | group_by(attribute="group") %}
|
|
14
|
+
### {{ group | upper_first }}
|
|
15
|
+
{% for commit in commits %}
|
|
16
|
+
- {{ commit.message | split(pat="\n") | first | trim }}{% if commit.id %} ({{ commit.id | truncate(length=7, end="") }}){% endif %}\
|
|
17
|
+
{% endfor %}
|
|
18
|
+
{% endfor %}\n
|
|
19
|
+
"""
|
|
20
|
+
trim = true
|
|
21
|
+
footer = ""
|
|
22
|
+
|
|
23
|
+
[git]
|
|
24
|
+
conventional_commits = true
|
|
25
|
+
filter_unconventional = false
|
|
26
|
+
split_commits = false
|
|
27
|
+
commit_parsers = [
|
|
28
|
+
{ message = "^feat", group = "Features" },
|
|
29
|
+
{ message = "^fix", group = "Bug Fixes" },
|
|
30
|
+
{ message = "^perf", group = "Performance" },
|
|
31
|
+
{ message = "^refactor", group = "Refactor" },
|
|
32
|
+
{ message = "^docs", group = "Documentation" },
|
|
33
|
+
{ message = "^test", group = "Tests" },
|
|
34
|
+
{ message = "^ci", group = "CI" },
|
|
35
|
+
{ message = "^chore\\(release\\)", skip = true },
|
|
36
|
+
{ message = "^chore", group = "Maintenance" },
|
|
37
|
+
{ message = "^revert", group = "Reverts" },
|
|
38
|
+
{ message = ".*", group = "Other" },
|
|
39
|
+
]
|
|
40
|
+
filter_commits = false
|
|
41
|
+
tag_pattern = "v[0-9]*"
|
|
42
|
+
ignore_tags = ""
|
|
43
|
+
topo_order = false
|
|
44
|
+
sort_commits = "oldest"
|