tsugite-cli 0.17.2__tar.gz → 0.17.3__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.17.2 → tsugite_cli-0.17.3}/PKG-INFO +1 -1
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/pyproject.toml +1 -1
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/agent_runner/runner.py +1 -1
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/core/agent.py +21 -9
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/tools/jobs.py +7 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/tools/schedule.py +19 -6
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/.gitignore +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/AGENTS.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/CONTRIBUTING.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/LICENSE +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/README.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/__init__.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/agent_inheritance.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/agent_preparation.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/agent_runner/__init__.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/agent_runner/exec_directives.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/agent_runner/exec_runner.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/agent_runner/helpers.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/agent_runner/history_integration.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/agent_runner/metrics.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/agent_runner/models.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/agent_runner/validation.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/agent_utils.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/attachments/__init__.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/attachments/auto_context.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/attachments/base.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/attachments/file.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/attachments/inline.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/attachments/storage.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/attachments/url.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/builtin_agents/.gitkeep +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/builtin_agents/code_searcher.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/builtin_agents/default.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/builtin_agents/file_searcher.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/builtin_agents/job_verifier.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/builtin_agents/job_worker.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/builtin_agents/onboard.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/builtin_skills/.gitkeep +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/builtin_skills/codebase-exploration/SKILL.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/builtin_skills/external-agent-bridge/SKILL.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/builtin_skills/python-math/SKILL.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/builtin_skills/response-patterns/SKILL.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/builtin_skills/scheduling/SKILL.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/builtin_skills/skill-authoring/SKILL.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/builtin_skills/tsugite-agent-basics/SKILL.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/builtin_skills/tsugite-jinja-reference/SKILL.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/builtin_skills/tsugite-skill-basics/SKILL.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/cache.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/cancellation.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/cli/__init__.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/cli/agents.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/cli/attachments.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/cli/cache.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/cli/chat.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/cli/config.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/cli/daemon.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/cli/exec.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/cli/helpers.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/cli/history.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/cli/init.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/cli/models.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/cli/plugins.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/cli/render.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/cli/run.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/cli/secrets.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/cli/skills.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/cli/tools.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/cli/usage.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/cli/validate.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/cli/workspace.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/config.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/console.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/constants.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/core/__init__.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/core/content_blocks.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/core/executor.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/core/executor_registry.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/core/memory.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/core/proxy.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/core/record_store.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/core/sandbox.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/core/state.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/core/subprocess_executor.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/core/tools.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/events/__init__.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/events/base.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/events/bus.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/events/events.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/events/helpers.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/exceptions.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/history/__init__.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/history/base.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/history/models.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/history/reconstruction.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/history/registry.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/history/sqlite_backend.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/history/sqlite_conn.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/history/sqlite_schema.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/history/storage.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/history/ui_events.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/hooks.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/interaction.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/md_agents.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/models.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/options.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/plugins.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/providers/__init__.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/providers/anthropic.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/providers/base.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/providers/model_cache.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/providers/model_registry.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/providers/ollama.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/providers/openai_compat.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/providers/openrouter.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/py.typed +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/renderer.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/schemas/__init__.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/schemas/agent.schema.json +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/secrets/__init__.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/secrets/backend.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/secrets/env.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/secrets/exec.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/secrets/file.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/secrets/masking.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/secrets/registry.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/secrets/sqlite.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/shell_tool_config.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/skill_discovery.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/templates/AGENTS.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/templates/IDENTITY.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/templates/MEMORY.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/templates/USER.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/templates/personas/casual-technical.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/templates/personas/marvin.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/templates/personas/minimal.md +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/tools/__init__.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/tools/agents.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/tools/fs.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/tools/history.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/tools/http.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/tools/interactive.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/tools/notify.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/tools/scratchpad.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/tools/secrets.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/tools/sessions.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/tools/shell.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/tools/shell_tools.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/tools/skills.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/tools/time.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/tsugite.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/ui/__init__.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/ui/base.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/ui/chat.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/ui/helpers.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/ui/jsonl.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/ui/plain.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/ui/repl_chat.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/ui/repl_commands.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/ui/repl_completer.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/ui/repl_handler.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/ui_context.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/usage/__init__.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/usage/store.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/user_agent.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/utils.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/workspace/__init__.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/workspace/context.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/workspace/models.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/workspace/session.py +0 -0
- {tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/workspace/templates.py +0 -0
|
@@ -681,7 +681,7 @@ async def _execute_agent_with_prompt(
|
|
|
681
681
|
model=model_string,
|
|
682
682
|
source="cli",
|
|
683
683
|
total_tokens=agent.total_tokens,
|
|
684
|
-
cost_usd=agent.
|
|
684
|
+
cost_usd=agent.reported_cost,
|
|
685
685
|
cache_creation_tokens=agent.cache_creation_tokens,
|
|
686
686
|
cache_read_tokens=agent.cache_read_tokens,
|
|
687
687
|
)
|
|
@@ -339,6 +339,9 @@ class TsugiteAgent:
|
|
|
339
339
|
self._resume_after_compaction = resume_after_compaction
|
|
340
340
|
|
|
341
341
|
self.total_cost = 0.0
|
|
342
|
+
# Distinguishes "provider reported $0" (subscription models) from "no
|
|
343
|
+
# cost data at all" (interrupted turn) - only the latter records NULL.
|
|
344
|
+
self.cost_reported = False
|
|
342
345
|
self.total_tokens = 0
|
|
343
346
|
self.last_input_tokens = 0
|
|
344
347
|
self.cache_creation_tokens = 0
|
|
@@ -571,7 +574,7 @@ class TsugiteAgent:
|
|
|
571
574
|
"answer": str(final_value)[:500] if final_value is not None else "",
|
|
572
575
|
"turns": turn_num + 1,
|
|
573
576
|
"tokens": total_tokens,
|
|
574
|
-
"cost": self.
|
|
577
|
+
"cost": self.reported_cost,
|
|
575
578
|
}
|
|
576
579
|
|
|
577
580
|
from tsugite.hooks import fire_hooks_background
|
|
@@ -585,13 +588,13 @@ class TsugiteAgent:
|
|
|
585
588
|
answer_data=_safe_json(final_value),
|
|
586
589
|
turns=turn_num + 1,
|
|
587
590
|
tokens=total_tokens,
|
|
588
|
-
cost=self.
|
|
591
|
+
cost=self.reported_cost,
|
|
589
592
|
)
|
|
590
593
|
)
|
|
591
594
|
self.event_bus.emit(
|
|
592
595
|
CostSummaryEvent(
|
|
593
596
|
tokens=total_tokens,
|
|
594
|
-
cost=self.
|
|
597
|
+
cost=self.reported_cost,
|
|
595
598
|
model=self.model_name,
|
|
596
599
|
duration_seconds=time.time() - start_time,
|
|
597
600
|
cache_creation_input_tokens=self.cache_creation_tokens or None,
|
|
@@ -610,7 +613,7 @@ class TsugiteAgent:
|
|
|
610
613
|
return AgentResult(
|
|
611
614
|
output=final_value,
|
|
612
615
|
token_usage=total_tokens,
|
|
613
|
-
cost=self.
|
|
616
|
+
cost=self.reported_cost,
|
|
614
617
|
steps=self.memory.steps,
|
|
615
618
|
error=error_message,
|
|
616
619
|
provider_state=self._provider.get_state(),
|
|
@@ -731,7 +734,7 @@ class TsugiteAgent:
|
|
|
731
734
|
self.event_bus.emit(StreamCompleteEvent())
|
|
732
735
|
|
|
733
736
|
if final_chunk and final_chunk.usage:
|
|
734
|
-
step_cost = self._accumulate_usage(final_chunk.usage, final_chunk.cost
|
|
737
|
+
step_cost = self._accumulate_usage(final_chunk.usage, final_chunk.cost)
|
|
735
738
|
|
|
736
739
|
accumulated_content, spoofed = escape_runtime_injection_tags(accumulated_content)
|
|
737
740
|
parsed = self._parse_response_from_text(accumulated_content)
|
|
@@ -765,8 +768,10 @@ class TsugiteAgent:
|
|
|
765
768
|
|
|
766
769
|
step_cost = response.cost or 0.0
|
|
767
770
|
if response.usage:
|
|
768
|
-
self._accumulate_usage(response.usage,
|
|
771
|
+
self._accumulate_usage(response.usage, response.cost)
|
|
769
772
|
else:
|
|
773
|
+
if response.cost is not None:
|
|
774
|
+
self.cost_reported = True
|
|
770
775
|
self.total_cost += step_cost
|
|
771
776
|
|
|
772
777
|
if response.reasoning_content:
|
|
@@ -1135,7 +1140,12 @@ class TsugiteAgent:
|
|
|
1135
1140
|
parts.append('warning="approaching turn limit, wrap up soon"')
|
|
1136
1141
|
return f"\n<tsugite_budget {' '.join(parts)} />"
|
|
1137
1142
|
|
|
1138
|
-
|
|
1143
|
+
@property
|
|
1144
|
+
def reported_cost(self) -> float | None:
|
|
1145
|
+
"""Cumulative cost when any provider response carried one, else None."""
|
|
1146
|
+
return self.total_cost if (self.cost_reported or self.total_cost > 0) else None
|
|
1147
|
+
|
|
1148
|
+
def _accumulate_usage(self, usage, cost: float | None = None) -> float:
|
|
1139
1149
|
"""Update cumulative token/cost counters from a usage object.
|
|
1140
1150
|
|
|
1141
1151
|
Returns the step cost for caller convenience.
|
|
@@ -1146,8 +1156,10 @@ class TsugiteAgent:
|
|
|
1146
1156
|
)
|
|
1147
1157
|
self.cache_creation_tokens += usage.cache_creation_input_tokens or 0
|
|
1148
1158
|
self.cache_read_tokens += usage.cache_read_input_tokens or 0
|
|
1149
|
-
|
|
1150
|
-
|
|
1159
|
+
if cost is not None:
|
|
1160
|
+
self.cost_reported = True
|
|
1161
|
+
self.total_cost += cost or 0.0
|
|
1162
|
+
return cost or 0.0
|
|
1151
1163
|
|
|
1152
1164
|
def _parse_response_from_text(self, content: str) -> ParsedResponse:
|
|
1153
1165
|
"""Parse text content into thought, code, and content blocks."""
|
|
@@ -37,6 +37,7 @@ def spawn_job(
|
|
|
37
37
|
repo: Optional[str] = None,
|
|
38
38
|
model: Optional[str] = None,
|
|
39
39
|
verifier_model: Optional[str] = None,
|
|
40
|
+
model_ladder: Optional[list] = None,
|
|
40
41
|
timeout_minutes: int = 30,
|
|
41
42
|
agent: Optional[str] = None,
|
|
42
43
|
max_attempts: Optional[int] = None,
|
|
@@ -67,6 +68,11 @@ def spawn_job(
|
|
|
67
68
|
verifier_model: Optional separate model for the verifier round. Defaults
|
|
68
69
|
to `model` (then the workspace default) when unset - handy to pin
|
|
69
70
|
verification to a cheaper/more-available model than the worker.
|
|
71
|
+
model_ladder: Ordered "cheap first" model list, e.g.
|
|
72
|
+
["claude_code:haiku", "claude_code:opus"]. The Job starts on the
|
|
73
|
+
first entry; when a rung exhausts its verifier attempts or the
|
|
74
|
+
worker dies on a usage/rate limit, the next attempt escalates to
|
|
75
|
+
the next model with a fresh budget. Overrides `model`.
|
|
70
76
|
timeout_minutes: Per-phase budget for each worker run and verifier round
|
|
71
77
|
(re-armed each phase, not a whole-job wall clock); on expiry the Job
|
|
72
78
|
transitions to `stuck`.
|
|
@@ -104,6 +110,7 @@ def spawn_job(
|
|
|
104
110
|
repo=repo,
|
|
105
111
|
model=model,
|
|
106
112
|
verifier_model=verifier_model,
|
|
113
|
+
model_ladder=model_ladder,
|
|
107
114
|
agent=agent,
|
|
108
115
|
timeout_minutes=timeout_minutes,
|
|
109
116
|
spawned_by="agent-tool",
|
|
@@ -36,14 +36,27 @@ def _call(fn, *args, **kwargs):
|
|
|
36
36
|
return call_on_loop(_loop, fn, *args, timeout=10, **kwargs)
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
def _validate_notify(notify
|
|
40
|
-
"""
|
|
39
|
+
def _validate_notify(notify, notify_tool: bool) -> Optional[list[str]]:
|
|
40
|
+
"""Normalize and validate the notify argument; returns the coerced list.
|
|
41
|
+
|
|
42
|
+
Agents pass booleans and bare strings here in practice - those must coerce
|
|
43
|
+
or produce a message that names the argument and the expected type, never
|
|
44
|
+
leak "'bool' object is not iterable"."""
|
|
45
|
+
if notify is True or (notify is not None and notify is not False and not isinstance(notify, (list, str))):
|
|
46
|
+
channels = f"Available channels: {', '.join(sorted(_channel_names))}" if _channel_names else ""
|
|
47
|
+
got = "True" if notify is True else type(notify).__name__
|
|
48
|
+
raise ValueError(f"notify must be a list of channel names, got {got}. {channels}".strip())
|
|
49
|
+
if notify is False:
|
|
50
|
+
notify = None
|
|
51
|
+
elif isinstance(notify, str):
|
|
52
|
+
notify = [notify]
|
|
41
53
|
if notify_tool and not notify:
|
|
42
54
|
raise ValueError("notify_tool=True requires a non-empty 'notify' list")
|
|
43
55
|
if notify:
|
|
44
56
|
unknown = set(notify) - _channel_names
|
|
45
57
|
if unknown:
|
|
46
58
|
raise ValueError(f"Unknown notification channel(s): {', '.join(sorted(unknown))}")
|
|
59
|
+
return notify
|
|
47
60
|
|
|
48
61
|
|
|
49
62
|
def _validate_agent(agent: str) -> None:
|
|
@@ -128,7 +141,7 @@ def schedule_create(
|
|
|
128
141
|
if not prompt and not agent_file:
|
|
129
142
|
raise ValueError("Provide at least one of 'prompt' or 'agent_file'")
|
|
130
143
|
|
|
131
|
-
_validate_notify(notify, notify_tool)
|
|
144
|
+
notify = _validate_notify(notify, notify_tool)
|
|
132
145
|
agent = _resolve_agent(agent)
|
|
133
146
|
_validate_agent(agent)
|
|
134
147
|
|
|
@@ -274,8 +287,8 @@ def schedule_update(
|
|
|
274
287
|
fields = {k: v for k, v in simple.items() if v is not None}
|
|
275
288
|
|
|
276
289
|
if notify is not None:
|
|
277
|
-
_validate_notify(notify, False)
|
|
278
|
-
fields["notify"] = notify
|
|
290
|
+
notify = _validate_notify(notify, False)
|
|
291
|
+
fields["notify"] = notify or []
|
|
279
292
|
if notify_tool is not None:
|
|
280
293
|
if notify_tool:
|
|
281
294
|
effective_notify = notify if notify is not None else _call(_scheduler.get, id).notify
|
|
@@ -436,7 +449,7 @@ def background_task(
|
|
|
436
449
|
if on_complete and (not isinstance(on_complete, dict) or on_complete.get("action") != "reply"):
|
|
437
450
|
raise ValueError("on_complete must be {'action': 'reply'}")
|
|
438
451
|
|
|
439
|
-
_validate_notify(notify, notify_tool)
|
|
452
|
+
notify = _validate_notify(notify, notify_tool)
|
|
440
453
|
agent = _resolve_agent(agent)
|
|
441
454
|
_validate_agent(agent)
|
|
442
455
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
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.17.2 → tsugite_cli-0.17.3}/tsugite/builtin_skills/codebase-exploration/SKILL.md
RENAMED
|
File without changes
|
{tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/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.17.2 → tsugite_cli-0.17.3}/tsugite/builtin_skills/tsugite-agent-basics/SKILL.md
RENAMED
|
File without changes
|
{tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/tsugite/builtin_skills/tsugite-jinja-reference/SKILL.md
RENAMED
|
File without changes
|
{tsugite_cli-0.17.2 → tsugite_cli-0.17.3}/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
|