tsugite-cli 0.9.4__tar.gz → 0.11.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.9.4 → tsugite_cli-0.11.0}/.gitignore +4 -1
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/PKG-INFO +103 -114
- tsugite_cli-0.11.0/README.md +148 -0
- tsugite_cli-0.11.0/docs/agents.md +273 -0
- tsugite_cli-0.11.0/docs/secrets.md +136 -0
- tsugite_cli-0.11.0/docs/test_agents/prefresh_readme.md +16 -0
- tsugite_cli-0.11.0/docs/test_agents/template_test.md +14 -0
- tsugite_cli-0.11.0/docs/test_agents/test_agent.md +15 -0
- tsugite_cli-0.11.0/docs/test_agents/test_steps.md +8 -0
- tsugite_cli-0.11.0/mise.toml +22 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/pyproject.toml +8 -4
- tsugite_cli-0.11.0/scripts/backfill_usage.py +98 -0
- tsugite_cli-0.11.0/scripts/update_model_registry.py +189 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/conftest.py +39 -29
- tsugite_cli-0.11.0/tests/core/test_agent.py +732 -0
- tsugite_cli-0.11.0/tests/core/test_agent_context_tokens.py +188 -0
- tsugite_cli-0.11.0/tests/core/test_agent_ui_events.py +421 -0
- tsugite_cli-0.11.0/tests/core/test_content_blocks.py +269 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/daemon/test_http_adapter.py +120 -40
- tsugite_cli-0.11.0/tests/daemon/test_session_metadata_api.py +221 -0
- tsugite_cli-0.11.0/tests/e2e/conftest.py +162 -0
- tsugite_cli-0.11.0/tests/e2e/test_auth.py +27 -0
- tsugite_cli-0.11.0/tests/e2e/test_chat.py +69 -0
- tsugite_cli-0.11.0/tests/e2e/test_context_bar.py +30 -0
- tsugite_cli-0.11.0/tests/e2e/test_history.py +148 -0
- tsugite_cli-0.11.0/tests/e2e/test_page_load.py +37 -0
- tsugite_cli-0.11.0/tests/e2e/test_prompt_inspector.py +53 -0
- tsugite_cli-0.11.0/tests/e2e/test_sessions.py +41 -0
- tsugite_cli-0.11.0/tests/e2e/test_sidebar_redesign.py +73 -0
- tsugite_cli-0.11.0/tests/e2e/test_sse_metadata.py +31 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_builtin_agent_paths.py +14 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_cache_control.py +1 -4
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_chat_cli.py +23 -5
- tsugite_cli-0.11.0/tests/test_claude_code_attachments.py +83 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_claude_code_provider.py +38 -108
- tsugite_cli-0.11.0/tests/test_completion_callbacks.py +479 -0
- tsugite_cli-0.11.0/tests/test_daemon_auth.py +199 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_daemon_compaction_scheduler.py +10 -27
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_daemon_history_persistence.py +1 -1
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_daemon_memory.py +74 -58
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_history.py +25 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_history_models.py +25 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_hooks.py +3 -10
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_http_tools.py +130 -2
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_kvstore.py +1 -0
- tsugite_cli-0.11.0/tests/test_model_registry.py +26 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_models.py +24 -1
- tsugite_cli-0.11.0/tests/test_prompt_snapshot.py +127 -0
- tsugite_cli-0.11.0/tests/test_provider_registry.py +53 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_reasoning_models.py +16 -29
- tsugite_cli-0.11.0/tests/test_secret_access_event.py +69 -0
- tsugite_cli-0.11.0/tests/test_secrets.py +450 -0
- tsugite_cli-0.11.0/tests/test_session_metadata.py +270 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_session_orchestrator_tools.py +8 -6
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_tmux_tools.py +1 -3
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/__init__.py +0 -4
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/agent_preparation.py +17 -10
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/agent_runner/__init__.py +4 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/agent_runner/helpers.py +10 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/agent_runner/history_integration.py +12 -12
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/agent_runner/models.py +2 -3
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/agent_runner/runner.py +61 -34
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/agent_runner/validation.py +1 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/attachments/url.py +2 -12
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_agents/default.md +38 -0
- tsugite_cli-0.11.0/tsugite/builtin_skills/.gitkeep +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/__init__.py +6 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/chat.py +5 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/config.py +0 -1
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/daemon.py +57 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/history.py +3 -1
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/init.py +16 -47
- tsugite_cli-0.11.0/tsugite/cli/models.py +80 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/run.py +17 -4
- tsugite_cli-0.11.0/tsugite/cli/secrets.py +51 -0
- tsugite_cli-0.11.0/tsugite/cli/usage.py +134 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/validate.py +1 -1
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/config.py +10 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/core/__init__.py +1 -1
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/core/agent.py +245 -331
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/core/claude_code.py +1 -1
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/core/executor.py +9 -5
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/adapters/base.py +93 -56
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/adapters/discord.py +38 -6
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/adapters/http.py +418 -43
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/adapters/scheduler_adapter.py +114 -6
- tsugite_cli-0.11.0/tsugite/daemon/auth.py +150 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/commands.py +35 -2
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/compaction_scheduler.py +1 -1
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/config.py +0 -5
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/gateway.py +43 -12
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/memory.py +22 -60
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/scheduler.py +4 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/session_runner.py +90 -11
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/session_store.py +172 -29
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/css/responsive.css +25 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/css/styles.css +84 -2
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/index.html +445 -97
- tsugite_cli-0.11.0/tsugite/daemon/web/js/api.js +97 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/js/app.js +58 -25
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/js/utils.js +20 -2
- tsugite_cli-0.11.0/tsugite/daemon/web/js/views/conversation/attachments.js +96 -0
- tsugite_cli-0.11.0/tsugite/daemon/web/js/views/conversation/history.js +173 -0
- tsugite_cli-0.11.0/tsugite/daemon/web/js/views/conversation/input.js +143 -0
- tsugite_cli-0.11.0/tsugite/daemon/web/js/views/conversation/sessions.js +198 -0
- tsugite_cli-0.11.0/tsugite/daemon/web/js/views/conversation/streaming.js +255 -0
- tsugite_cli-0.11.0/tsugite/daemon/web/js/views/conversations.js +268 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/js/views/schedules.js +29 -9
- tsugite_cli-0.11.0/tsugite/daemon/web/js/views/usage.js +65 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/events/__init__.py +5 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/events/base.py +6 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/events/events.py +21 -1
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/events/helpers.py +11 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/history/models.py +4 -3
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/history/storage.py +8 -2
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/kvstore/__init__.py +1 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/md_agents.py +14 -3
- tsugite_cli-0.11.0/tsugite/models.py +158 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/plugins.py +3 -1
- tsugite_cli-0.11.0/tsugite/providers/__init__.py +100 -0
- tsugite_cli-0.11.0/tsugite/providers/anthropic.py +301 -0
- tsugite_cli-0.11.0/tsugite/providers/base.py +92 -0
- tsugite_cli-0.11.0/tsugite/providers/claude_code.py +257 -0
- tsugite_cli-0.11.0/tsugite/providers/model_cache.py +126 -0
- tsugite_cli-0.11.0/tsugite/providers/model_registry.py +46 -0
- tsugite_cli-0.11.0/tsugite/providers/ollama.py +76 -0
- tsugite_cli-0.11.0/tsugite/providers/openai_compat.py +314 -0
- tsugite_cli-0.11.0/tsugite/providers/openrouter.py +69 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/schemas/agent.schema.json +16 -2
- tsugite_cli-0.11.0/tsugite/secrets/__init__.py +82 -0
- tsugite_cli-0.11.0/tsugite/secrets/backend.py +11 -0
- tsugite_cli-0.11.0/tsugite/secrets/env.py +25 -0
- tsugite_cli-0.11.0/tsugite/secrets/exec.py +75 -0
- tsugite_cli-0.11.0/tsugite/secrets/file.py +43 -0
- tsugite_cli-0.11.0/tsugite/secrets/masking.py +31 -0
- tsugite_cli-0.11.0/tsugite/secrets/registry.py +62 -0
- tsugite_cli-0.11.0/tsugite/secrets/sqlite.py +121 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/__init__.py +8 -6
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/http.py +28 -4
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/kv.py +5 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/schedule.py +16 -0
- tsugite_cli-0.11.0/tsugite/tools/scratchpad.py +101 -0
- tsugite_cli-0.11.0/tsugite/tools/secrets.py +53 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/sessions.py +46 -10
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/skills.py +5 -2
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/tmux.py +2 -7
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/ui/chat.py +5 -2
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/ui/jsonl.py +11 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/ui/repl_chat.py +17 -4
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/ui/repl_commands.py +1 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/ui/repl_handler.py +15 -10
- tsugite_cli-0.11.0/tsugite/usage/__init__.py +5 -0
- tsugite_cli-0.11.0/tsugite/usage/store.py +222 -0
- tsugite_cli-0.11.0/tsugite/user_agent.py +38 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/utils.py +20 -1
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/uv.lock +218 -333
- tsugite_cli-0.9.4/README.md +0 -161
- tsugite_cli-0.9.4/tests/core/test_agent.py +0 -782
- tsugite_cli-0.9.4/tests/core/test_agent_ui_events.py +0 -434
- tsugite_cli-0.9.4/tests/core/test_content_blocks.py +0 -340
- tsugite_cli-0.9.4/tests/test_claude_code_attachments.py +0 -245
- tsugite_cli-0.9.4/tsugite/daemon/web/js/api.js +0 -54
- tsugite_cli-0.9.4/tsugite/daemon/web/js/views/conversations.js +0 -987
- tsugite_cli-0.9.4/tsugite/models.py +0 -282
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/.github/copilot-instructions.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/.github/workflows/ci.yml +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/.github/workflows/docker-publish.yml +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/.github/workflows/pypi-publish.yml +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/AGENTS.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/CLAUDE.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/LICENSE +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/scripts/regenerate_schema.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/README.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/__init__.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/core/__init__.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/core/test_executor.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/core/test_memory.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/core/test_proxy.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/core/test_sandbox.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/core/test_subprocess_executor.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/core/test_tools.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/daemon/__init__.py +0 -0
- /tsugite_cli-0.9.4/tsugite/builtin_agents/.gitkeep → /tsugite_cli-0.11.0/tests/e2e/__init__.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/events/test_event_consolidation.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/smoke_test.sh +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_agent_file_hot_loading.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_agent_inheritance.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_agent_parser.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_agent_sessions.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_agent_skills.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_agent_utils.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_agents_tool.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_attachment_deduplication.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_attachments.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_auto_context_handler.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_auto_discovery.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_background_task_status.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_background_tasks.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_builtin_agents.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_chat_error_handling.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_cli.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_cli_arguments.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_cli_rendering.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_cli_subcommands.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_config.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_continuation.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_custom_shell_tools.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_custom_ui.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_daemon_config.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_daemon_push.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_daemon_scheduler.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_daemon_session_isolation.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_daemon_unified_sessions.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_discord_progress.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_error_display.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_file_references.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_file_tools.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_history_integration.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_history_performance.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_history_tools.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_interaction_backends.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_interactive_context.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_interactive_tool.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_jsonl_ui.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_list_agents_tool.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_mcp_client.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_mcp_server.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_multi_agent.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_multistep_agents.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_orchestrator_heartbeat.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_plugins.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_renderer.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_rendering_scenarios.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_repl_commands.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_repl_completer.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_repl_handler.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_retry_system.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_run_if.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_schedule_model_override.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_scheduler_history_injection.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_schema.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_security_phase1.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_send_message.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_skill_discovery.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_skill_tools.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_stdin.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_subagent_subprocess.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_tool_directives.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_tool_registry.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_workspace_auto_continue.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_workspace_cwd.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_workspace_discovery.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/agent_inheritance.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/agent_runner/metrics.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/agent_utils.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/attachments/__init__.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/attachments/auto_context.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/attachments/base.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/attachments/file.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/attachments/inline.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/attachments/storage.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/attachments/youtube.py +0 -0
- {tsugite_cli-0.9.4/tsugite/builtin_skills → tsugite_cli-0.11.0/tsugite/builtin_agents}/.gitkeep +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_agents/code_searcher.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_agents/file_searcher.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_agents/onboard.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_skills/codebase_exploration.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_skills/python_math.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_skills/response_patterns.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_skills/scheduling.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_skills/skill_authoring.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_skills/tsugite_agent_basics.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_skills/tsugite_jinja_reference.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_skills/tsugite_skill_basics.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cache.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/agents.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/attachments.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/cache.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/helpers.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/mcp.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/plugins.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/render.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/serve.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/tools.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/workspace.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/console.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/constants.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/core/content_blocks.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/core/memory.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/core/proxy.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/core/sandbox.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/core/subprocess_executor.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/core/tools.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/__init__.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/adapters/__init__.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/push.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/css/theme.css +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/icons/icon-192.png +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/icons/icon-512-maskable.png +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/icons/icon-512.png +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/icons/screenshot-narrow.png +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/icons/screenshot-wide.png +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/js/views/dashboard.js +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/js/views/file-editor.js +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/js/views/kvstore.js +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/js/views/webhooks.js +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/js/views/workspace.js +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/manifest.json +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/sw.js +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/webhook_store.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/events/bus.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/exceptions.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/history/__init__.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/history/reconstruction.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/hooks.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/interaction.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/kvstore/backend.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/kvstore/sqlite.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/mcp_client.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/mcp_config.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/mcp_server.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/options.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/renderer.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/schemas/__init__.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/shell_tool_config.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/skill_discovery.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/templates/AGENTS.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/templates/IDENTITY.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/templates/MEMORY.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/templates/USER.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/templates/personas/casual-technical.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/templates/personas/marvin.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/templates/personas/minimal.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/agents.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/fs.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/history.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/interactive.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/notify.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/shell.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/shell_tools.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tsugite.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/ui/__init__.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/ui/base.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/ui/helpers.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/ui/plain.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/ui/repl_completer.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/ui_context.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/workspace/__init__.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/workspace/context.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/workspace/models.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/workspace/session.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/workspace/templates.py +0 -0
|
@@ -167,13 +167,16 @@ cython_debug/
|
|
|
167
167
|
benchmark_results/
|
|
168
168
|
test_output/
|
|
169
169
|
.claude/settings.local.json
|
|
170
|
+
std*.txt
|
|
171
|
+
secrets/*
|
|
170
172
|
|
|
171
173
|
|
|
172
174
|
# TODO: temp - I need to clean up the docs
|
|
173
|
-
docs/
|
|
175
|
+
docs-old/
|
|
174
176
|
examples/
|
|
175
177
|
agents/
|
|
176
178
|
.claude/
|
|
177
179
|
.tsugite/
|
|
178
180
|
benchmarks/
|
|
181
|
+
docker-compose.test.yml
|
|
179
182
|
#### TODO ^^^
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tsugite-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.11.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
|
|
@@ -239,22 +239,24 @@ License: GNU AFFERO GENERAL PUBLIC LICENSE
|
|
|
239
239
|
|
|
240
240
|
You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU AGPL, see <http://www.gnu.org/licenses/>.
|
|
241
241
|
License-File: LICENSE
|
|
242
|
-
Keywords: agents,automation,cli,jinja2
|
|
242
|
+
Keywords: agents,automation,cli,jinja2
|
|
243
243
|
Requires-Python: >=3.11
|
|
244
|
+
Requires-Dist: cryptography>=46.0.5
|
|
244
245
|
Requires-Dist: ddgs>=9.6.0
|
|
245
246
|
Requires-Dist: html2text>=2020.1.16
|
|
246
247
|
Requires-Dist: httpx>=0.25
|
|
247
248
|
Requires-Dist: jinja2>=3.1
|
|
248
|
-
Requires-Dist: litellm<1.82.7,>=1.77.7
|
|
249
249
|
Requires-Dist: mcp>=1.0
|
|
250
|
-
Requires-Dist: nest-asyncio>=1.
|
|
250
|
+
Requires-Dist: nest-asyncio>=1.5.0
|
|
251
251
|
Requires-Dist: pathspec>=0.11.0
|
|
252
252
|
Requires-Dist: portalocker>=2.8.0
|
|
253
253
|
Requires-Dist: prompt-toolkit>=3.0.43
|
|
254
254
|
Requires-Dist: pydantic>=2.12.3
|
|
255
255
|
Requires-Dist: pyyaml>=6.0
|
|
256
256
|
Requires-Dist: questionary>=2.1.1
|
|
257
|
+
Requires-Dist: readability-lxml>=0.8
|
|
257
258
|
Requires-Dist: rich>=13.0
|
|
259
|
+
Requires-Dist: tiktoken>=0.7.0
|
|
258
260
|
Requires-Dist: typer>=0.12
|
|
259
261
|
Requires-Dist: tzlocal>=5.3.1
|
|
260
262
|
Requires-Dist: youtube-transcript-api>=0.6.0
|
|
@@ -269,162 +271,149 @@ Description-Content-Type: text/markdown
|
|
|
269
271
|
|
|
270
272
|
# tsugite
|
|
271
273
|
|
|
272
|
-
Tsugite (
|
|
274
|
+
Tsugite (継ぎ手) is an agent framework where you define AI agents as markdown files and run them from the CLI, a web UI, or through scheduled tasks.
|
|
273
275
|
|
|
274
|
-
|
|
276
|
+
I built it because none of the existing agent frameworks did what I wanted. I needed something self-hosted, model-agnostic, and simple enough that an agent is just a text file I can edit and version control.
|
|
275
277
|
|
|
276
|
-
|
|
278
|
+
Originally it was meant to be a framework for micro-agents inspired by [ESA](https://github.com/meain/esa), but has grown a lot since that goal.
|
|
277
279
|
|
|
278
|
-
|
|
279
|
-
# Recommended: Install with uv
|
|
280
|
-
uv tool install tsugite-cli
|
|
281
|
-
|
|
282
|
-
# Alternative: Install with pipx
|
|
283
|
-
pipx install tsugite-cli
|
|
284
|
-
|
|
285
|
-
# Or with pip
|
|
286
|
-
pip install tsugite-cli
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
**Note:** The package name is `tsugite-cli`, but the command is `tsugite` (or `tsu` for short).
|
|
280
|
+
## What an agent looks like
|
|
290
281
|
|
|
291
|
-
|
|
282
|
+
A simple "hello world" agent looks like:
|
|
292
283
|
|
|
293
|
-
```
|
|
294
|
-
# Run an agent
|
|
295
|
-
tsugite run examples/simple_variable_injection.md "test it"
|
|
296
|
-
|
|
297
|
-
# Create your own agent
|
|
298
|
-
cat > my_agent.md << 'EOF'
|
|
284
|
+
```markdown
|
|
299
285
|
---
|
|
300
|
-
name:
|
|
301
|
-
model:
|
|
286
|
+
name: morning-brief
|
|
287
|
+
model: anthropic:claude-sonnet-4-20250514
|
|
288
|
+
tools: [web_search, fetch_text, write_file, final_answer]
|
|
302
289
|
---
|
|
303
290
|
|
|
304
|
-
|
|
291
|
+
You are a morning briefing assistant.
|
|
305
292
|
|
|
306
|
-
|
|
307
|
-
|
|
293
|
+
Current date: {{ now() }}
|
|
294
|
+
User location: {{ env("LOCATION", "unknown") }}
|
|
308
295
|
|
|
309
|
-
|
|
296
|
+
Check the weather, scan top news, and write a short briefing.
|
|
297
|
+
Use final_answer() to return the result.
|
|
310
298
|
```
|
|
311
299
|
|
|
312
|
-
|
|
300
|
+
YAML frontmatter for config, markdown body for instructions, Jinja for dynamic context. Run it with:
|
|
313
301
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
- **Copy-paste friendly output** - `--plain` flag or auto-detection for pipe/redirect
|
|
302
|
+
```bash
|
|
303
|
+
tsu run +morning-brief "what's happening today"
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Key ideas
|
|
320
307
|
|
|
321
|
-
|
|
308
|
+
- **Agents are markdown.** A basic agent is just markdown with yaml frontmatter. Advanced agents are still just markdown but can use jinja templating and a special `<!--tsu -->` syntax.
|
|
309
|
+
- **Code execution over tool-calling.** Inspired by [smolagents](https://github.com/huggingface/smolagents). Instead of using native tool calling, LLMs write python code. Tools are exposed as python functions.
|
|
310
|
+
- **Any LLM.** Plugin interface to add support for additional LLM providers. Built-in we have openai-compatible apis, ollama, anthropic, and claude code.
|
|
311
|
+
- **Workspaces.** Each workspace is a persistent directory with agents, skills, memory files, and config. The agent runs inside its workspace and can read/write files, spawn sub-agents, manage schedules, and persist state across conversations. Workspaces are entirely optional.
|
|
312
|
+
- **CLI and/or Daemon with a Web UI** Use `tsu run` commands for cli-only, or run `tsu daemon` for a daemon that supports scheduled tasks, a web ui, and some other neat things.
|
|
313
|
+
|
|
314
|
+
## Install
|
|
322
315
|
|
|
323
316
|
```bash
|
|
324
|
-
|
|
325
|
-
|
|
317
|
+
uv tool install tsugite-cli # recommended
|
|
318
|
+
pipx install tsugite-cli # alternative
|
|
319
|
+
pip install tsugite-cli # or plain pip
|
|
320
|
+
```
|
|
326
321
|
|
|
327
|
-
|
|
328
|
-
tsugite run +assistant "task" | grep result
|
|
322
|
+
The package is `tsugite-cli`, the command is `tsugite` (or `tsu` for short).
|
|
329
323
|
|
|
330
|
-
|
|
331
|
-
tsugite run +assistant "task" --headless
|
|
324
|
+
## Quick start
|
|
332
325
|
|
|
333
|
-
|
|
334
|
-
|
|
326
|
+
```bash
|
|
327
|
+
# Initialize a workspace
|
|
328
|
+
tsu init my-workspace
|
|
329
|
+
cd my-workspace
|
|
330
|
+
|
|
331
|
+
# Run the built-in default agent
|
|
332
|
+
tsu run +default "summarize the files in this directory"
|
|
335
333
|
|
|
336
|
-
#
|
|
337
|
-
|
|
338
|
-
tsugite chat --continue CONV_ID
|
|
334
|
+
# Run an agent file directly
|
|
335
|
+
tsu run my-agent.md "do the thing"
|
|
339
336
|
|
|
340
|
-
#
|
|
341
|
-
|
|
342
|
-
tsugite history show CONV_ID
|
|
337
|
+
# Start the web UI
|
|
338
|
+
tsu serve
|
|
343
339
|
```
|
|
344
340
|
|
|
345
|
-
##
|
|
341
|
+
## Features
|
|
346
342
|
|
|
347
|
-
|
|
343
|
+
- **Multi-step workflows** with `<!-- tsu:step -->` to chain steps and pass data between them
|
|
344
|
+
- **Scheduling** built-in cron for recurring agent tasks (daily summaries, monitoring, etc.)
|
|
345
|
+
- **Web UI** for conversations, with Discord as an alternative interface
|
|
346
|
+
- **Sub-agents** that can spawn other agents for specific subtasks
|
|
347
|
+
- **Skills** reusable knowledge files agents can load on demand, mostly compatible with [agentskills.io](https://agentskills.io/)
|
|
348
|
+
- **Hooks** that fire shell commands on lifecycle events (post-tool, pre-message, pre/post-compact)
|
|
349
|
+
- **Sandbox** (linux only) via bubblewrap with filesystem and network isolation
|
|
350
|
+
- **KV store** for persistent agent state
|
|
351
|
+
- **MCP** integration for connecting to MCP servers
|
|
348
352
|
|
|
349
|
-
|
|
350
|
-
# Sandbox with specific domains allowed
|
|
351
|
-
tsu run +default "task" --sandbox --allow-domain "github.com" --allow-domain "*.openai.com"
|
|
353
|
+
## Agents in more detail
|
|
352
354
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
+
Agents support YAML frontmatter for configuration:
|
|
356
|
+
|
|
357
|
+
```yaml
|
|
358
|
+
---
|
|
359
|
+
name: code-reviewer
|
|
360
|
+
model: anthropic:claude-sonnet-4-20250514
|
|
361
|
+
max_turns: 15
|
|
362
|
+
tools: [read_file, list_files, web_search, final_answer]
|
|
363
|
+
auto_load_skills: [coding-standards]
|
|
364
|
+
---
|
|
355
365
|
```
|
|
356
366
|
|
|
357
|
-
|
|
367
|
+
You can restrict which tools an agent has access to, set turn limits, auto-load skills, attach context files, and extend other agents. TODO: See `docs/` for the full spec.
|
|
358
368
|
|
|
359
|
-
|
|
360
|
-
CLI --sandbox --allow-domain "*.github.com"
|
|
361
|
-
└─ SubprocessExecutor writes harness script
|
|
362
|
-
└─ bwrap --unshare-pid --unshare-net --die-with-parent ...
|
|
363
|
-
└─ TCP↔UDS bridge (HTTP_PROXY → Unix socket)
|
|
364
|
-
└─ ConnectProxy filters CONNECT requests by domain:port
|
|
365
|
-
```
|
|
369
|
+
Multi-step agents use `<!--tsu -->` comments as directives:
|
|
366
370
|
|
|
367
|
-
|
|
371
|
+
```markdown
|
|
372
|
+
<!-- tsu:step name="research" model="openai:gpt-4o" -->
|
|
373
|
+
Research the topic and save findings to a variable.
|
|
368
374
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
375
|
+
<!-- tsu:step name="write" -->
|
|
376
|
+
Using the research from the previous step, write a summary.
|
|
377
|
+
The variable `research` is available as a Python variable.
|
|
378
|
+
```
|
|
372
379
|
|
|
373
|
-
|
|
380
|
+
For a complete example, check the built-in [default agent](tsugite/builtin_agents/default.md).
|
|
374
381
|
|
|
375
|
-
|
|
376
|
-
- Network is namespace-isolated; outbound HTTP/HTTPS goes through a filtering CONNECT proxy
|
|
377
|
-
- Direct connections to bare IP addresses are always blocked
|
|
378
|
-
- `--no-network` skips the proxy entirely — no connectivity at all
|
|
382
|
+
## Sandbox
|
|
379
383
|
|
|
380
|
-
|
|
384
|
+
On Linux only (for now), agent code runs inside a [bubblewrap](https://github.com/containers/bubblewrap) sandbox when you pass `--sandbox`:
|
|
381
385
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
| `*.github.com:8080` | port 8080 on subdomains |
|
|
387
|
-
| `*:*` | all domains, all ports |
|
|
386
|
+
```bash
|
|
387
|
+
tsu run +default "task" --sandbox --allow-domain "github.com"
|
|
388
|
+
tsu run +default "task" --sandbox --no-network
|
|
389
|
+
```
|
|
388
390
|
|
|
389
|
-
|
|
391
|
+
Filesystem access is limited to the workspace. Network goes through a filtering proxy that only allows domains you specify.
|
|
390
392
|
|
|
391
|
-
|
|
393
|
+
## Config and Data Directories
|
|
392
394
|
|
|
393
|
-
|
|
394
|
-
hooks:
|
|
395
|
-
post_tool:
|
|
396
|
-
- tools: [write_file]
|
|
397
|
-
run: git add {{ path }}
|
|
398
|
-
wait: true
|
|
399
|
-
|
|
400
|
-
pre_message:
|
|
401
|
-
- run: uridx search "{{ message }}" --limit 5
|
|
402
|
-
capture_as: rag_context
|
|
403
|
-
- run: cat memory/preferences.md
|
|
404
|
-
capture_as: user_preferences
|
|
405
|
-
|
|
406
|
-
pre_compact:
|
|
407
|
-
- run: ./scripts/extract-facts.sh {{ turns_file }}
|
|
408
|
-
wait: true
|
|
409
|
-
|
|
410
|
-
post_compact:
|
|
411
|
-
- run: echo "Compacted {{ turns_compacted }} turns"
|
|
412
|
-
```
|
|
395
|
+
All paths follow [XDG Base Directory](https://specifications.freedesktop.org/basedir-spec/latest/) conventions and can be overridden with the standard environment variables.
|
|
413
396
|
|
|
414
|
-
|
|
397
|
+
| Path | Default | Contents |
|
|
398
|
+
|----------------------------------------|--------------------------------------|----------------------------------------------|
|
|
399
|
+
| `$XDG_CONFIG_HOME/tsugite/` | `~/.config/tsugite/` | `config.json`, `mcp.json`, `daemon.yaml` |
|
|
400
|
+
| `$XDG_DATA_HOME/tsugite/history/` | `~/.local/share/tsugite/history/` | Session history (JSONL per session) |
|
|
401
|
+
| `$XDG_DATA_HOME/tsugite/daemon/` | `~/.local/share/tsugite/daemon/` | Daemon state |
|
|
402
|
+
| `$XDG_DATA_HOME/tsugite/secrets/` | `~/.local/share/tsugite/secrets/` | Encrypted secrets (`secrets.db`) |
|
|
403
|
+
| `$XDG_DATA_HOME/tsugite/kvstore/` | `~/.local/share/tsugite/kvstore/` | Key-value store (`kv.db`) |
|
|
404
|
+
| `$XDG_DATA_HOME/tsugite/usage/` | `~/.local/share/tsugite/usage/` | Usage (cost and token) tracking (`usage.db`) |
|
|
405
|
+
| `$XDG_DATA_HOME/tsugite/workspaces/` | `~/.local/share/tsugite/workspaces/` | Workspace directories |
|
|
406
|
+
| `$XDG_CACHE_HOME/tsugite/attachments/` | `~/.cache/tsugite/attachments/` | Attachment cache |
|
|
415
407
|
|
|
416
|
-
**Hook types:**
|
|
417
|
-
- **`post_tool`** — After successful tool calls. Context: `tool`, plus tool arguments.
|
|
418
|
-
- **`pre_message`** — Before agent execution. Context: `message`, `user_id`, `agent_name`. Use `capture_as` to inject results into agent templates as `{{ var_name }}`.
|
|
419
|
-
- **`pre_compact`** / **`post_compact`** — Around session compaction. Context: `conversation_id`, `user_id`, `agent_name`, `turns_file`, `turn_count`.
|
|
420
408
|
|
|
421
409
|
## Development
|
|
422
410
|
|
|
423
411
|
```bash
|
|
424
|
-
# Clone and install for development
|
|
425
412
|
git clone https://github.com/justyns/tsugite.git
|
|
426
413
|
cd tsugite
|
|
427
414
|
uv sync --dev
|
|
428
415
|
```
|
|
429
416
|
|
|
430
|
-
|
|
417
|
+
## Status
|
|
418
|
+
|
|
419
|
+
This is a personal project I use daily. It works for my use cases but isn't polished for general consumption yet. Issues and PRs welcome, but set expectations accordingly. Documentation is very sparse because I keep changing things.
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# tsugite
|
|
2
|
+
|
|
3
|
+
Tsugite (継ぎ手) is an agent framework where you define AI agents as markdown files and run them from the CLI, a web UI, or through scheduled tasks.
|
|
4
|
+
|
|
5
|
+
I built it because none of the existing agent frameworks did what I wanted. I needed something self-hosted, model-agnostic, and simple enough that an agent is just a text file I can edit and version control.
|
|
6
|
+
|
|
7
|
+
Originally it was meant to be a framework for micro-agents inspired by [ESA](https://github.com/meain/esa), but has grown a lot since that goal.
|
|
8
|
+
|
|
9
|
+
## What an agent looks like
|
|
10
|
+
|
|
11
|
+
A simple "hello world" agent looks like:
|
|
12
|
+
|
|
13
|
+
```markdown
|
|
14
|
+
---
|
|
15
|
+
name: morning-brief
|
|
16
|
+
model: anthropic:claude-sonnet-4-20250514
|
|
17
|
+
tools: [web_search, fetch_text, write_file, final_answer]
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
You are a morning briefing assistant.
|
|
21
|
+
|
|
22
|
+
Current date: {{ now() }}
|
|
23
|
+
User location: {{ env("LOCATION", "unknown") }}
|
|
24
|
+
|
|
25
|
+
Check the weather, scan top news, and write a short briefing.
|
|
26
|
+
Use final_answer() to return the result.
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
YAML frontmatter for config, markdown body for instructions, Jinja for dynamic context. Run it with:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
tsu run +morning-brief "what's happening today"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Key ideas
|
|
36
|
+
|
|
37
|
+
- **Agents are markdown.** A basic agent is just markdown with yaml frontmatter. Advanced agents are still just markdown but can use jinja templating and a special `<!--tsu -->` syntax.
|
|
38
|
+
- **Code execution over tool-calling.** Inspired by [smolagents](https://github.com/huggingface/smolagents). Instead of using native tool calling, LLMs write python code. Tools are exposed as python functions.
|
|
39
|
+
- **Any LLM.** Plugin interface to add support for additional LLM providers. Built-in we have openai-compatible apis, ollama, anthropic, and claude code.
|
|
40
|
+
- **Workspaces.** Each workspace is a persistent directory with agents, skills, memory files, and config. The agent runs inside its workspace and can read/write files, spawn sub-agents, manage schedules, and persist state across conversations. Workspaces are entirely optional.
|
|
41
|
+
- **CLI and/or Daemon with a Web UI** Use `tsu run` commands for cli-only, or run `tsu daemon` for a daemon that supports scheduled tasks, a web ui, and some other neat things.
|
|
42
|
+
|
|
43
|
+
## Install
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
uv tool install tsugite-cli # recommended
|
|
47
|
+
pipx install tsugite-cli # alternative
|
|
48
|
+
pip install tsugite-cli # or plain pip
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The package is `tsugite-cli`, the command is `tsugite` (or `tsu` for short).
|
|
52
|
+
|
|
53
|
+
## Quick start
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Initialize a workspace
|
|
57
|
+
tsu init my-workspace
|
|
58
|
+
cd my-workspace
|
|
59
|
+
|
|
60
|
+
# Run the built-in default agent
|
|
61
|
+
tsu run +default "summarize the files in this directory"
|
|
62
|
+
|
|
63
|
+
# Run an agent file directly
|
|
64
|
+
tsu run my-agent.md "do the thing"
|
|
65
|
+
|
|
66
|
+
# Start the web UI
|
|
67
|
+
tsu serve
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Features
|
|
71
|
+
|
|
72
|
+
- **Multi-step workflows** with `<!-- tsu:step -->` to chain steps and pass data between them
|
|
73
|
+
- **Scheduling** built-in cron for recurring agent tasks (daily summaries, monitoring, etc.)
|
|
74
|
+
- **Web UI** for conversations, with Discord as an alternative interface
|
|
75
|
+
- **Sub-agents** that can spawn other agents for specific subtasks
|
|
76
|
+
- **Skills** reusable knowledge files agents can load on demand, mostly compatible with [agentskills.io](https://agentskills.io/)
|
|
77
|
+
- **Hooks** that fire shell commands on lifecycle events (post-tool, pre-message, pre/post-compact)
|
|
78
|
+
- **Sandbox** (linux only) via bubblewrap with filesystem and network isolation
|
|
79
|
+
- **KV store** for persistent agent state
|
|
80
|
+
- **MCP** integration for connecting to MCP servers
|
|
81
|
+
|
|
82
|
+
## Agents in more detail
|
|
83
|
+
|
|
84
|
+
Agents support YAML frontmatter for configuration:
|
|
85
|
+
|
|
86
|
+
```yaml
|
|
87
|
+
---
|
|
88
|
+
name: code-reviewer
|
|
89
|
+
model: anthropic:claude-sonnet-4-20250514
|
|
90
|
+
max_turns: 15
|
|
91
|
+
tools: [read_file, list_files, web_search, final_answer]
|
|
92
|
+
auto_load_skills: [coding-standards]
|
|
93
|
+
---
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
You can restrict which tools an agent has access to, set turn limits, auto-load skills, attach context files, and extend other agents. TODO: See `docs/` for the full spec.
|
|
97
|
+
|
|
98
|
+
Multi-step agents use `<!--tsu -->` comments as directives:
|
|
99
|
+
|
|
100
|
+
```markdown
|
|
101
|
+
<!-- tsu:step name="research" model="openai:gpt-4o" -->
|
|
102
|
+
Research the topic and save findings to a variable.
|
|
103
|
+
|
|
104
|
+
<!-- tsu:step name="write" -->
|
|
105
|
+
Using the research from the previous step, write a summary.
|
|
106
|
+
The variable `research` is available as a Python variable.
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
For a complete example, check the built-in [default agent](tsugite/builtin_agents/default.md).
|
|
110
|
+
|
|
111
|
+
## Sandbox
|
|
112
|
+
|
|
113
|
+
On Linux only (for now), agent code runs inside a [bubblewrap](https://github.com/containers/bubblewrap) sandbox when you pass `--sandbox`:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
tsu run +default "task" --sandbox --allow-domain "github.com"
|
|
117
|
+
tsu run +default "task" --sandbox --no-network
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Filesystem access is limited to the workspace. Network goes through a filtering proxy that only allows domains you specify.
|
|
121
|
+
|
|
122
|
+
## Config and Data Directories
|
|
123
|
+
|
|
124
|
+
All paths follow [XDG Base Directory](https://specifications.freedesktop.org/basedir-spec/latest/) conventions and can be overridden with the standard environment variables.
|
|
125
|
+
|
|
126
|
+
| Path | Default | Contents |
|
|
127
|
+
|----------------------------------------|--------------------------------------|----------------------------------------------|
|
|
128
|
+
| `$XDG_CONFIG_HOME/tsugite/` | `~/.config/tsugite/` | `config.json`, `mcp.json`, `daemon.yaml` |
|
|
129
|
+
| `$XDG_DATA_HOME/tsugite/history/` | `~/.local/share/tsugite/history/` | Session history (JSONL per session) |
|
|
130
|
+
| `$XDG_DATA_HOME/tsugite/daemon/` | `~/.local/share/tsugite/daemon/` | Daemon state |
|
|
131
|
+
| `$XDG_DATA_HOME/tsugite/secrets/` | `~/.local/share/tsugite/secrets/` | Encrypted secrets (`secrets.db`) |
|
|
132
|
+
| `$XDG_DATA_HOME/tsugite/kvstore/` | `~/.local/share/tsugite/kvstore/` | Key-value store (`kv.db`) |
|
|
133
|
+
| `$XDG_DATA_HOME/tsugite/usage/` | `~/.local/share/tsugite/usage/` | Usage (cost and token) tracking (`usage.db`) |
|
|
134
|
+
| `$XDG_DATA_HOME/tsugite/workspaces/` | `~/.local/share/tsugite/workspaces/` | Workspace directories |
|
|
135
|
+
| `$XDG_CACHE_HOME/tsugite/attachments/` | `~/.cache/tsugite/attachments/` | Attachment cache |
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
## Development
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
git clone https://github.com/justyns/tsugite.git
|
|
142
|
+
cd tsugite
|
|
143
|
+
uv sync --dev
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Status
|
|
147
|
+
|
|
148
|
+
This is a personal project I use daily. It works for my use cases but isn't polished for general consumption yet. Issues and PRs welcome, but set expectations accordingly. Documentation is very sparse because I keep changing things.
|