tsugite-cli 0.23.1__tar.gz → 0.23.2__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.23.1 → tsugite_cli-0.23.2}/PKG-INFO +1 -1
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/pyproject.toml +1 -1
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/agent_preparation.py +4 -2
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/agent_runner/history_integration.py +4 -7
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/agent_runner/runner.py +2 -1
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/cli/agents.py +2 -1
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/cli/run.py +2 -1
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/core/executor.py +9 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/providers/anthropic.py +1 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/providers/model_registry.py +8 -4
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/providers/openai_compat.py +2 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/tools/__init__.py +15 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/ui/jsonl.py +14 -1
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/usage/quota.py +8 -10
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/utils.py +1 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/.gitignore +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/AGENTS.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/CONTRIBUTING.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/LICENSE +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/README.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/__init__.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/agent_inheritance.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/agent_runner/__init__.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/agent_runner/exec_directives.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/agent_runner/exec_runner.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/agent_runner/helpers.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/agent_runner/metrics.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/agent_runner/models.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/agent_runner/steps.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/agent_runner/validation.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/agent_utils.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/approval.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/attachments/__init__.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/attachments/agent_config.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/attachments/auto_context.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/attachments/base.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/attachments/delegation.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/attachments/file.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/attachments/inline.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/attachments/storage.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/attachments/url.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/builtin_agents/.gitkeep +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/builtin_agents/code_searcher.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/builtin_agents/default.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/builtin_agents/file_searcher.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/builtin_agents/job_verifier.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/builtin_agents/job_worker.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/builtin_agents/onboard.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/builtin_context.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/builtin_skills/.gitkeep +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/builtin_skills/codebase-exploration/SKILL.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/builtin_skills/external-agent-bridge/SKILL.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/builtin_skills/python-math/SKILL.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/builtin_skills/response-patterns/SKILL.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/builtin_skills/scheduling/SKILL.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/builtin_skills/skill-authoring/SKILL.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/builtin_skills/tsugite-agent-basics/SKILL.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/builtin_skills/tsugite-jinja-reference/SKILL.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/builtin_skills/tsugite-skill-basics/SKILL.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/cache.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/cancellation.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/cli/__init__.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/cli/attachments.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/cli/cache.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/cli/chat.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/cli/config.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/cli/daemon.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/cli/exec.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/cli/helpers.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/cli/history.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/cli/init.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/cli/models.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/cli/plugins.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/cli/render.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/cli/secrets.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/cli/skills.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/cli/tools.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/cli/usage.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/cli/validate.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/cli/workspace.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/config.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/console.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/constants.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/context.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/context_block.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/core/__init__.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/core/agent.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/core/content_blocks.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/core/executor_registry.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/core/memory.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/core/proxy.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/core/record_store.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/core/sandbox.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/core/state.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/core/subprocess_executor.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/core/tools.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/events/__init__.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/events/base.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/events/bus.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/events/events.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/events/helpers.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/exceptions.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/history/__init__.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/history/base.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/history/models.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/history/reconstruction.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/history/registry.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/history/sqlite_backend.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/history/sqlite_conn.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/history/sqlite_schema.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/history/ui_events.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/hooks.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/interaction.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/md_agents.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/models.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/options.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/permissions.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/plugins.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/prompt_xml.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/providers/__init__.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/providers/base.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/providers/model_cache.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/providers/ollama.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/providers/openrouter.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/py.typed +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/renderer.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/schemas/__init__.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/schemas/agent.schema.json +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/secrets/__init__.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/secrets/backend.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/secrets/env.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/secrets/exec.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/secrets/file.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/secrets/masking.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/secrets/redaction.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/secrets/registry.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/secrets/sqlite.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/shell_tool_config.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/skill_discovery.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/templates/AGENTS.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/templates/IDENTITY.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/templates/MEMORY.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/templates/USER.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/templates/personas/casual-technical.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/templates/personas/marvin.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/templates/personas/minimal.md +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/tools/agents.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/tools/artifacts.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/tools/daemon_control.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/tools/fs.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/tools/history.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/tools/http.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/tools/interactive.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/tools/jobs.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/tools/notify.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/tools/schedule.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/tools/secrets.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/tools/sessions.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/tools/shell.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/tools/shell_tools.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/tools/skills.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/tools/time.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/tsugite.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/ui/__init__.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/ui/base.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/ui/chat.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/ui/dispatch.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/ui/helpers.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/ui/plain.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/ui/repl_chat.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/ui/repl_commands.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/ui/repl_completer.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/ui/repl_handler.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/ui_context.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/ui_surfaces.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/usage/__init__.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/usage/store.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/user_agent.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/workspace/__init__.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/workspace/models.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/workspace/session.py +0 -0
- {tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/workspace/templates.py +0 -0
|
@@ -152,7 +152,8 @@ class AgentPreparer:
|
|
|
152
152
|
|
|
153
153
|
A front-matter attachment defines its cache tier and replaces a same-named
|
|
154
154
|
caller attachment. Legacy `-filename` string entries drop a same-named
|
|
155
|
-
entry. Front-matter paths render with `paths` and resolve against
|
|
155
|
+
entry. Front-matter paths render with `paths` and resolve against the
|
|
156
|
+
workspace, or the CWD when the run has no workspace.
|
|
156
157
|
"""
|
|
157
158
|
all_attachments = list(attachments or [])
|
|
158
159
|
|
|
@@ -160,7 +161,8 @@ class AgentPreparer:
|
|
|
160
161
|
if removals:
|
|
161
162
|
all_attachments = [a for a in all_attachments if a.name not in removals]
|
|
162
163
|
|
|
163
|
-
|
|
164
|
+
base = paths["WORKSPACE_DIR"] or paths["CWD"]
|
|
165
|
+
loaded, bindings = resolve_agent_config_attachments(keep_items, Path(base), paths)
|
|
164
166
|
all_attachments = loaded + all_attachments
|
|
165
167
|
|
|
166
168
|
seen_names: set[str] = set()
|
|
@@ -92,14 +92,11 @@ def _current_turn_already_has_user_input(storage: Session) -> bool:
|
|
|
92
92
|
session_end after it; the post-hoc save_run_to_history on the error path
|
|
93
93
|
would otherwise record a second, identical one (a duplicate user bubble).
|
|
94
94
|
A genuinely repeated message opens a new turn *after* the prior session_end,
|
|
95
|
-
so this stays False for it.
|
|
95
|
+
so this stays False for it. A final_result also ends a turn: compaction copies
|
|
96
|
+
retained turns into the successor without their session_end.
|
|
96
97
|
"""
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
return False
|
|
100
|
-
if event.type == "user_input":
|
|
101
|
-
return True
|
|
102
|
-
return False
|
|
98
|
+
events = list(storage.iter_events(types=("user_input", "session_end", "final_result")))
|
|
99
|
+
return bool(events) and events[-1].type == "user_input"
|
|
103
100
|
|
|
104
101
|
|
|
105
102
|
def record_user_input(
|
|
@@ -1281,6 +1281,7 @@ def preview_multistep_agent(
|
|
|
1281
1281
|
|
|
1282
1282
|
# Extract steps
|
|
1283
1283
|
from tsugite.md_agents import extract_step_directives, has_step_directives
|
|
1284
|
+
from tsugite.tools import format_tool_specs
|
|
1284
1285
|
|
|
1285
1286
|
if not has_step_directives(agent.content):
|
|
1286
1287
|
output("[yellow]This is a single-step agent (no step directives).[/yellow]", is_warning=True)
|
|
@@ -1302,7 +1303,7 @@ def preview_multistep_agent(
|
|
|
1302
1303
|
output(f"Prompt: {prompt}")
|
|
1303
1304
|
output(f"Steps: {len(steps)}")
|
|
1304
1305
|
output(f"Model: {resolve_effective_model(agent_model=agent.config.model) or 'unknown'}")
|
|
1305
|
-
output(f"Tools: {
|
|
1306
|
+
output(f"Tools: {format_tool_specs(agent.config.tools) if agent.config.tools else 'None'}")
|
|
1306
1307
|
output("")
|
|
1307
1308
|
|
|
1308
1309
|
# Show steps in table format
|
|
@@ -75,6 +75,7 @@ def agents_show(
|
|
|
75
75
|
"""
|
|
76
76
|
from tsugite.agent_inheritance import find_agent_file
|
|
77
77
|
from tsugite.md_agents import parse_agent_file
|
|
78
|
+
from tsugite.tools import format_tool_spec
|
|
78
79
|
|
|
79
80
|
try:
|
|
80
81
|
agent_file = Path(agent_path)
|
|
@@ -113,7 +114,7 @@ def agents_show(
|
|
|
113
114
|
if config.tools:
|
|
114
115
|
console.print(f"\n[bold]Tools ({len(config.tools)}):[/bold]")
|
|
115
116
|
for tool in config.tools:
|
|
116
|
-
console.print(f" • {tool}")
|
|
117
|
+
console.print(f" • {format_tool_spec(tool)}")
|
|
117
118
|
|
|
118
119
|
if config.extends:
|
|
119
120
|
console.print(f"\n[bold]Extends:[/bold] {config.extends}")
|
|
@@ -288,6 +288,7 @@ def run(
|
|
|
288
288
|
from tsugite.console import get_stderr_console
|
|
289
289
|
from tsugite.md_agents import validate_agent_execution
|
|
290
290
|
from tsugite.secrets import init_cli as init_secrets
|
|
291
|
+
from tsugite.tools import format_tool_specs
|
|
291
292
|
from tsugite.utils import should_use_plain_output
|
|
292
293
|
|
|
293
294
|
from . import console
|
|
@@ -562,7 +563,7 @@ def run(
|
|
|
562
563
|
"Directory": str(Path.cwd()),
|
|
563
564
|
"Model": resolve_effective_model(exec_opts.model_override, agent_info.get("model_raw")) or "unknown",
|
|
564
565
|
"Instructions": instruction_label,
|
|
565
|
-
"Tools":
|
|
566
|
+
"Tools": format_tool_specs(agent_info.get("tools", [])),
|
|
566
567
|
}
|
|
567
568
|
|
|
568
569
|
agent_attachments = agent_info.get("attachments")
|
|
@@ -98,6 +98,13 @@ def _jsonable_call_args(kwargs: Dict[str, Any]) -> Dict[str, Any]:
|
|
|
98
98
|
return safe
|
|
99
99
|
|
|
100
100
|
|
|
101
|
+
NAME_ERROR_NOTE = (
|
|
102
|
+
" (each code block starts with a fresh namespace: names from earlier blocks and"
|
|
103
|
+
" <content> blocks do not carry over, so re-import or recompute them, or keep"
|
|
104
|
+
" values in state['key'])"
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
|
|
101
108
|
def truncate_observation(text: str, max_output_kb: int = MAX_EXECUTION_OUTPUT_KB) -> tuple[str, bool]:
|
|
102
109
|
"""Clip text to the observation cap, returning (text, was_truncated).
|
|
103
110
|
|
|
@@ -134,6 +141,8 @@ def build_execution_result(
|
|
|
134
141
|
|
|
135
142
|
children = [El("output", [output], inline=True)]
|
|
136
143
|
if error:
|
|
144
|
+
if error.startswith("NameError:"):
|
|
145
|
+
error += NAME_ERROR_NOTE
|
|
137
146
|
children.append(El("error", [error], inline=True))
|
|
138
147
|
if traceback:
|
|
139
148
|
children.append(El("traceback", [traceback], inline=True))
|
|
@@ -48,6 +48,7 @@ _ANTHROPIC_MODELS: dict[str, ModelInfo] = {
|
|
|
48
48
|
"anthropic/claude-opus-4-7": ModelInfo(max_input_tokens=1_000_000, max_output_tokens=128_000, input_cost_per_million=5.0, output_cost_per_million=25.0, supports_vision=True, supports_reasoning=True, supported_effort_levels=["low", "medium", "high", "xhigh", "max"], thinking_style="adaptive"),
|
|
49
49
|
"anthropic/claude-opus-4-8": ModelInfo(max_input_tokens=1_000_000, max_output_tokens=128_000, input_cost_per_million=5.0, output_cost_per_million=25.0, supports_vision=True, supports_reasoning=True, supported_effort_levels=["low", "medium", "high", "xhigh", "max"], thinking_style="adaptive"),
|
|
50
50
|
"anthropic/claude-opus-5": ModelInfo(max_input_tokens=1_000_000, max_output_tokens=128_000, input_cost_per_million=5.0, output_cost_per_million=25.0, supports_vision=True, supports_reasoning=True, supported_effort_levels=["low", "medium", "high", "xhigh", "max"], thinking_style="adaptive"),
|
|
51
|
+
"anthropic/claude-opus-5-5": ModelInfo(max_input_tokens=1_000_000, max_output_tokens=128_000, input_cost_per_million=4.0, output_cost_per_million=20.0, supports_vision=True, supports_reasoning=True, supported_effort_levels=["low", "medium", "high", "xhigh", "max"], thinking_style="adaptive"),
|
|
51
52
|
"anthropic/claude-sonnet-4-5": ModelInfo(max_input_tokens=1_000_000, max_output_tokens=64_000, input_cost_per_million=3.0, output_cost_per_million=15.0, supports_vision=True, supports_reasoning=True, supported_effort_levels=["low", "medium", "high", "max"], thinking_style="budget_tokens"),
|
|
52
53
|
"anthropic/claude-sonnet-4-5-20250929": ModelInfo(max_input_tokens=1_000_000, max_output_tokens=64_000, input_cost_per_million=3.0, output_cost_per_million=15.0, supports_vision=True, supports_reasoning=True, supported_effort_levels=["low", "medium", "high", "max"], thinking_style="budget_tokens"),
|
|
53
54
|
"anthropic/claude-sonnet-4-6": ModelInfo(max_input_tokens=1_000_000, max_output_tokens=128_000, input_cost_per_million=3.0, output_cost_per_million=15.0, supports_vision=True, supports_reasoning=True, supported_effort_levels=["low", "medium", "high", "max"], thinking_style="budget_tokens"),
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import re
|
|
6
|
+
|
|
5
7
|
from .base import ModelInfo, Usage
|
|
6
8
|
|
|
7
9
|
_REGISTRY: dict[str, ModelInfo] = {}
|
|
@@ -22,11 +24,13 @@ def get_model_info(provider: str, model: str) -> ModelInfo | None:
|
|
|
22
24
|
for reg_key, info in _REGISTRY.items():
|
|
23
25
|
if not key.startswith(reg_key) or len(reg_key) <= best_len:
|
|
24
26
|
continue
|
|
25
|
-
# Only treat the prefix as the same model when the remainder is a
|
|
26
|
-
# continuation (e.g. "-20250805"), not a distinct variant
|
|
27
|
-
#
|
|
27
|
+
# Only treat the prefix as the same model when the remainder is a dated
|
|
28
|
+
# continuation (e.g. "-20250805", "-2024-05-13"), not a distinct variant
|
|
29
|
+
# ("-mini", "-turbo") or a point release ("-5"). An unlisted variant
|
|
30
|
+
# would otherwise silently inherit a sibling's pricing. A year is 4+
|
|
31
|
+
# digits, so require the digit run right after the dash to be that long.
|
|
28
32
|
suffix = key[len(reg_key) :]
|
|
29
|
-
if suffix and not
|
|
33
|
+
if suffix and not re.match(r"^-\d{4}", suffix):
|
|
30
34
|
continue
|
|
31
35
|
best_match = info
|
|
32
36
|
best_len = len(reg_key)
|
|
@@ -55,6 +55,8 @@ _OPENAI_MODELS: dict[str, ModelInfo] = {
|
|
|
55
55
|
"openai/gpt-5.6-sol": ModelInfo(max_input_tokens=1_050_000, max_output_tokens=128_000, input_cost_per_million=4.0, output_cost_per_million=20.0, supports_vision=True, supports_reasoning=True, supported_effort_levels=["none", "low", "medium", "high", "xhigh", "max"]),
|
|
56
56
|
"openai/gpt-5.6-terra": ModelInfo(max_input_tokens=1_050_000, max_output_tokens=128_000, input_cost_per_million=2.0, output_cost_per_million=12.0, supports_vision=True, supports_reasoning=True, supported_effort_levels=["none", "low", "medium", "high", "xhigh", "max"]),
|
|
57
57
|
"openai/gpt-6-astra": ModelInfo(max_input_tokens=1_050_000, max_output_tokens=128_000, input_cost_per_million=10.0, output_cost_per_million=50.0, supports_vision=True, supports_reasoning=True, supported_effort_levels=["low", "medium", "high", "xhigh", "max"]),
|
|
58
|
+
"openai/gpt-6-luna": ModelInfo(max_input_tokens=1_050_000, max_output_tokens=128_000, input_cost_per_million=0.1, output_cost_per_million=0.5, supports_vision=True, supports_reasoning=True, supported_effort_levels=["none", "low", "medium", "high", "xhigh", "max"]),
|
|
59
|
+
"openai/gpt-6-sol": ModelInfo(max_input_tokens=1_050_000, max_output_tokens=128_000, input_cost_per_million=2.0, output_cost_per_million=10.0, supports_vision=True, supports_reasoning=True, supported_effort_levels=["none", "low", "medium", "high", "xhigh", "max"]),
|
|
58
60
|
"openai/o1": ModelInfo(max_input_tokens=200_000, max_output_tokens=100_000, input_cost_per_million=15.0, output_cost_per_million=60.0, supports_vision=True, supports_reasoning=True, supported_effort_levels=["low", "medium", "high"]),
|
|
59
61
|
"openai/o1-pro": ModelInfo(max_input_tokens=200_000, max_output_tokens=100_000, input_cost_per_million=150.0, output_cost_per_million=600.0, supports_vision=True, supports_reasoning=True, supported_effort_levels=["low", "medium", "high"]),
|
|
60
62
|
"openai/o3": ModelInfo(max_input_tokens=200_000, max_output_tokens=100_000, input_cost_per_million=2.0, output_cost_per_million=8.0, supports_vision=True, supports_reasoning=True, supported_effort_levels=["low", "medium", "high"]),
|
|
@@ -376,6 +376,21 @@ def expand_tool_specs(tool_specs: List[str], strict: bool = False) -> List[str]:
|
|
|
376
376
|
return result
|
|
377
377
|
|
|
378
378
|
|
|
379
|
+
def format_tool_spec(spec: str) -> str:
|
|
380
|
+
"""Render one frontmatter tool spec for console output, with `@category` as `name (toolset)`.
|
|
381
|
+
|
|
382
|
+
An agent that shells out to tsugite reads this through its own tool layer, where `@name`
|
|
383
|
+
expands as a file mention if it matches a directory.
|
|
384
|
+
"""
|
|
385
|
+
prefix, name = ("-", spec[1:]) if spec.startswith("-") else ("", spec)
|
|
386
|
+
return f"{prefix}{name[1:]} (toolset)" if name.startswith("@") else spec
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
def format_tool_specs(tool_specs: List[str]) -> str:
|
|
390
|
+
"""Render a frontmatter tool list as one comma-separated line."""
|
|
391
|
+
return ", ".join(format_tool_spec(spec) for spec in tool_specs)
|
|
392
|
+
|
|
393
|
+
|
|
379
394
|
def load_custom_shell_tools() -> None:
|
|
380
395
|
"""Register the shell tools defined in custom_tools.yaml.
|
|
381
396
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""JSONL UI handler for subprocess-based subagent communication."""
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
-
from typing import Any, Dict
|
|
4
|
+
from typing import Any, Dict, Optional
|
|
5
5
|
|
|
6
6
|
from tsugite.events import (
|
|
7
7
|
CodeExecutionEvent,
|
|
@@ -32,6 +32,7 @@ from tsugite.events import (
|
|
|
32
32
|
ToolResultEvent,
|
|
33
33
|
WarningEvent,
|
|
34
34
|
)
|
|
35
|
+
from tsugite.events.base import BaseEvent
|
|
35
36
|
from tsugite.ui.dispatch import EventDispatchMixin, handles
|
|
36
37
|
|
|
37
38
|
# Event types that share the same file-io payload shape
|
|
@@ -73,6 +74,17 @@ class JSONLUIHandler(EventDispatchMixin):
|
|
|
73
74
|
- Failed tool: {"type": "tool_result", "tool": "read_file", "success": false, "error": "..."}
|
|
74
75
|
"""
|
|
75
76
|
|
|
77
|
+
final_seen = False
|
|
78
|
+
latest_prompt_messages: Optional[list] = None
|
|
79
|
+
|
|
80
|
+
def handle_event(self, event: BaseEvent) -> None:
|
|
81
|
+
if isinstance(event, PromptSnapshotEvent):
|
|
82
|
+
if event.messages:
|
|
83
|
+
self.latest_prompt_messages = event.messages
|
|
84
|
+
if not event.token_breakdown:
|
|
85
|
+
return
|
|
86
|
+
super().handle_event(event)
|
|
87
|
+
|
|
76
88
|
@handles(TaskStartEvent)
|
|
77
89
|
def _handle_task_start(self, event: TaskStartEvent) -> None:
|
|
78
90
|
self._emit("init", {"agent": event.task, "model": event.model})
|
|
@@ -132,6 +144,7 @@ class JSONLUIHandler(EventDispatchMixin):
|
|
|
132
144
|
|
|
133
145
|
@handles(FinalAnswerEvent)
|
|
134
146
|
def _handle_final_answer(self, event: FinalAnswerEvent) -> None:
|
|
147
|
+
self.final_seen = True
|
|
135
148
|
self._emit(
|
|
136
149
|
"final_result",
|
|
137
150
|
{
|
|
@@ -3,9 +3,8 @@ subscription or budget the user has consumed ("week 73%, resets Aug 19").
|
|
|
3
3
|
|
|
4
4
|
A source is contributed by a plugin through the ``tsugite.usage_providers``
|
|
5
5
|
entry point (a module-only entry point whose import registers the source) and
|
|
6
|
-
fetches from
|
|
7
|
-
field
|
|
8
|
-
let the two disagree.
|
|
6
|
+
fetches from that provider's local state or API. The shape has no severity
|
|
7
|
+
field because the UI derives its own warn threshold.
|
|
9
8
|
"""
|
|
10
9
|
|
|
11
10
|
from __future__ import annotations
|
|
@@ -31,8 +30,8 @@ class QuotaWindow:
|
|
|
31
30
|
|
|
32
31
|
@dataclass(frozen=True)
|
|
33
32
|
class QuotaReport:
|
|
34
|
-
"""One provider's quota. ``error`` is set instead of windows when
|
|
35
|
-
|
|
33
|
+
"""One provider's quota. ``error`` is set instead of windows when the
|
|
34
|
+
source could not be read."""
|
|
36
35
|
|
|
37
36
|
provider: str
|
|
38
37
|
label: str
|
|
@@ -69,10 +68,9 @@ def reset_quota_sources() -> None:
|
|
|
69
68
|
|
|
70
69
|
|
|
71
70
|
def ensure_loaded() -> None:
|
|
72
|
-
"""Import the ``tsugite.usage_providers`` entry-point modules once,
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
waits for it rather than seeing an empty registry."""
|
|
71
|
+
"""Import the ``tsugite.usage_providers`` entry-point modules once, before
|
|
72
|
+
the registry is read. A daemon worker thread racing the first load waits
|
|
73
|
+
for it."""
|
|
76
74
|
global _loaded
|
|
77
75
|
if _loaded:
|
|
78
76
|
return
|
|
@@ -102,7 +100,7 @@ def collect_quota_reports() -> list[dict]:
|
|
|
102
100
|
logger.warning("Quota source '%s' failed: %s", source.provider, e)
|
|
103
101
|
report = QuotaReport(provider=source.provider, label=source.label, error=str(e))
|
|
104
102
|
row = asdict(report)
|
|
105
|
-
# asdict keeps
|
|
103
|
+
# asdict keeps windows as a tuple and the wire shape is an array.
|
|
106
104
|
row["windows"] = list(row["windows"])
|
|
107
105
|
rows.append(row)
|
|
108
106
|
return rows
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/builtin_skills/codebase-exploration/SKILL.md
RENAMED
|
File without changes
|
{tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/builtin_skills/external-agent-bridge/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/builtin_skills/tsugite-agent-basics/SKILL.md
RENAMED
|
File without changes
|
{tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/builtin_skills/tsugite-jinja-reference/SKILL.md
RENAMED
|
File without changes
|
{tsugite_cli-0.23.1 → tsugite_cli-0.23.2}/tsugite/builtin_skills/tsugite-skill-basics/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|