From 699b765e1c5e132088a07c8904e1265012bc90c0 Mon Sep 17 00:00:00 2001 From: Weishi Zeng Date: Sat, 11 Jul 2026 16:47:58 -0700 Subject: [PATCH 1/6] Add claude-fable-5 to litellm proxy and bump claude code to 2.1.207 Fable pricing ($10/$50 per 1M, cache 1.25e-5/1e-6) mirrored from litellm's model_prices_and_context_window map, registered inline in both litellm configs and mngr_usage's MODEL_PRICING. Claude Code pin bumped at all five sites (Dockerfile ARG, snapshot script, CI workflows); the matching default-workspace-template pin bump lands in a separate PR. Co-Authored-By: Claude Fable 5 --- .github/actions/tmr-setup/action.yml | 2 +- .github/workflows/release-tests.yml | 4 ++-- apps/modal_litellm/README.md | 4 ++++ apps/modal_litellm/app.py | 8 ++++++++ apps/modal_litellm/changelog/mngr-fable.md | 1 + dev/changelog/mngr-fable.md | 1 + libs/mngr/changelog/mngr-fable.md | 1 + libs/mngr/imbue/mngr/resources/Dockerfile | 2 +- libs/mngr_usage/changelog/mngr-fable.md | 1 + libs/mngr_usage/imbue/mngr_usage/pricing.py | 7 +++++++ litellm_proxy/config.yaml | 10 ++++++++++ scripts/snapshot_minds_e2e_state.py | 2 +- 12 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 apps/modal_litellm/changelog/mngr-fable.md create mode 100644 dev/changelog/mngr-fable.md create mode 100644 libs/mngr/changelog/mngr-fable.md create mode 100644 libs/mngr_usage/changelog/mngr-fable.md diff --git a/.github/actions/tmr-setup/action.yml b/.github/actions/tmr-setup/action.yml index b4d58b9f0c..beea522c98 100644 --- a/.github/actions/tmr-setup/action.yml +++ b/.github/actions/tmr-setup/action.yml @@ -23,7 +23,7 @@ runs: - name: Install Claude Code CLI shell: bash - run: npm install -g @anthropic-ai/claude-code@2.1.160 + run: npm install -g @anthropic-ai/claude-code@2.1.207 - name: Configure git identity shell: bash diff --git a/.github/workflows/release-tests.yml b/.github/workflows/release-tests.yml index f728cbf48e..ad72d96b99 100644 --- a/.github/workflows/release-tests.yml +++ b/.github/workflows/release-tests.yml @@ -66,7 +66,7 @@ jobs: run: uv sync --all-packages - name: Install Claude Code CLI - run: npm install -g @anthropic-ai/claude-code@2.1.160 + run: npm install -g @anthropic-ai/claude-code@2.1.207 - name: Run Docker release tests run: PYTEST_MAX_DURATION_SECONDS=900 uv run pytest -n 0 --timeout 600 --no-cov --cov-fail-under=0 -v --tb=short --ignore apps/minds -m '(docker or docker_sdk) and release' @@ -117,7 +117,7 @@ jobs: run: brew install tmux unison - name: Install Claude Code CLI - run: npm install -g @anthropic-ai/claude-code@2.1.160 + run: npm install -g @anthropic-ai/claude-code@2.1.207 - name: Configure Docker Hub mirror if: runner.os == 'Linux' diff --git a/apps/modal_litellm/README.md b/apps/modal_litellm/README.md index d2df3e41b2..84905cac05 100644 --- a/apps/modal_litellm/README.md +++ b/apps/modal_litellm/README.md @@ -91,6 +91,10 @@ even on litellm versions whose bundled price map predates a model. The model list lives in `apps/modal_litellm/app.py` (`LITELLM_CONFIG`) and is mirrored in `litellm_proxy/config.yaml`; `config_drift_test.py` fails if the two diverge. +Fable ($10 / $50 per 1M input / output): + +- `claude-fable-5` + Opus (current price tier, $5 / $25 per 1M input / output): - `claude-opus-4-8` (latest Opus) diff --git a/apps/modal_litellm/app.py b/apps/modal_litellm/app.py index 0c4027a01c..54f4d80c89 100644 --- a/apps/modal_litellm/app.py +++ b/apps/modal_litellm/app.py @@ -68,6 +68,12 @@ # predates a model (e.g. claude-opus-4-8 only landed in litellm's price map # in the 1.88.0 pre-release line). MUST stay in sync with # litellm_proxy/config.yaml -- config_drift_test.py enforces this. +_FABLE_PRICING = { + "input_cost_per_token": 0.00001, + "output_cost_per_token": 0.00005, + "cache_creation_input_token_cost": 0.0000125, + "cache_read_input_token_cost": 0.000001, +} _OPUS_PRICING = { "input_cost_per_token": 0.000005, "output_cost_per_token": 0.000025, @@ -108,6 +114,8 @@ def _model_entry(model_name: str, pricing: dict[str, float]) -> dict[str, object LITELLM_CONFIG = { "model_list": [ + # Fable (Mythos-class tier above Opus). + _model_entry("claude-fable-5", _FABLE_PRICING), # Current Opus line. _model_entry("claude-opus-4-8", _OPUS_PRICING), _model_entry("claude-opus-4-7", _OPUS_PRICING), diff --git a/apps/modal_litellm/changelog/mngr-fable.md b/apps/modal_litellm/changelog/mngr-fable.md new file mode 100644 index 0000000000..1e38b592da --- /dev/null +++ b/apps/modal_litellm/changelog/mngr-fable.md @@ -0,0 +1 @@ +Add `claude-fable-5` to the LiteLLM proxy model list with inline pricing ($10 / $50 per 1M input / output tokens, cache write 1.25e-5, cache read 1e-6, mirrored from litellm's price map), so workspaces using imbue_cloud virtual keys can run Claude Fable 5 with correct cost tracking. diff --git a/dev/changelog/mngr-fable.md b/dev/changelog/mngr-fable.md new file mode 100644 index 0000000000..ffdb175a96 --- /dev/null +++ b/dev/changelog/mngr-fable.md @@ -0,0 +1 @@ +Bump the pinned Claude Code CLI version from 2.1.160 to 2.1.207 in CI workflows (`release-tests.yml`, `tmr-setup` action) and the minds e2e snapshot script, matching the new workspace pin that supports Claude Fable 5. diff --git a/libs/mngr/changelog/mngr-fable.md b/libs/mngr/changelog/mngr-fable.md new file mode 100644 index 0000000000..ecfbad62c7 --- /dev/null +++ b/libs/mngr/changelog/mngr-fable.md @@ -0,0 +1 @@ +Bump the release-sandbox Dockerfile's pinned Claude Code version from 2.1.160 to 2.1.207, which supports the Claude Fable 5 model. Must land together with the matching `[agent_types.claude].version` bump in default-workspace-template. diff --git a/libs/mngr/imbue/mngr/resources/Dockerfile b/libs/mngr/imbue/mngr/resources/Dockerfile index 209a593521..3f3258efe6 100644 --- a/libs/mngr/imbue/mngr/resources/Dockerfile +++ b/libs/mngr/imbue/mngr/resources/Dockerfile @@ -69,7 +69,7 @@ ENV PATH="/root/.local/bin:$PATH" # .mngr/settings.toml pin (`[agent_types.claude].version`). The release-test # `test_claude_code_version_matches_default_workspace_template_pin` enforces the # sync; bump both together when rolling a new claude release. -ARG CLAUDE_CODE_VERSION="2.1.160" +ARG CLAUDE_CODE_VERSION="2.1.207" RUN curl -fsSL https://claude.ai/install.sh > /tmp/install_claude.sh && ( if [ -n "$CLAUDE_CODE_VERSION" ]; then cat /tmp/install_claude.sh | bash -s "$CLAUDE_CODE_VERSION"; else cat /tmp/install_claude.sh | bash; fi && test -x /root/.local/bin/claude ) || ( cat /tmp/install_claude.sh && exit 1 ) ENV CLAUDE_CODE_VERSION=${CLAUDE_CODE_VERSION} diff --git a/libs/mngr_usage/changelog/mngr-fable.md b/libs/mngr_usage/changelog/mngr-fable.md new file mode 100644 index 0000000000..21ceee4c3b --- /dev/null +++ b/libs/mngr_usage/changelog/mngr-fable.md @@ -0,0 +1 @@ +Add `anthropic/claude-fable-5` to the usage pricing table ($10 / $50 per 1M input / output tokens), so token-only usage sources report cost for Claude Fable 5 instead of showing it as unpriced. diff --git a/libs/mngr_usage/imbue/mngr_usage/pricing.py b/libs/mngr_usage/imbue/mngr_usage/pricing.py index d83a836bf4..c6c0f2e86d 100644 --- a/libs/mngr_usage/imbue/mngr_usage/pricing.py +++ b/libs/mngr_usage/imbue/mngr_usage/pricing.py @@ -48,6 +48,12 @@ class PerTokenPrices(FrozenModel): # Anthropic per-token pricing, mirrored verbatim from apps/modal_litellm/app.py # (which itself mirrors litellm's map). Grouped by tier so the "same price" # relationship across model ids stays explicit, exactly as modal_litellm does. +_FABLE_PRICES: Final[PerTokenPrices] = PerTokenPrices( + input_cost_per_token=0.00001, + output_cost_per_token=0.00005, + cache_creation_input_token_cost=0.0000125, + cache_read_input_token_cost=0.000001, +) _OPUS_PRICES: Final[PerTokenPrices] = PerTokenPrices( input_cost_per_token=0.000005, output_cost_per_token=0.000025, @@ -122,6 +128,7 @@ class PerTokenPrices(FrozenModel): # apps/modal_litellm (drift test); OpenAI stays in sync with litellm directly # (litellm_pricing_test). MODEL_PRICING: Final[dict[str, PerTokenPrices]] = { + "anthropic/claude-fable-5": _FABLE_PRICES, "anthropic/claude-opus-4-8": _OPUS_PRICES, "anthropic/claude-opus-4-7": _OPUS_PRICES, "anthropic/claude-opus-4-6": _OPUS_PRICES, diff --git a/litellm_proxy/config.yaml b/litellm_proxy/config.yaml index 3c0daebbcf..123c08be37 100644 --- a/litellm_proxy/config.yaml +++ b/litellm_proxy/config.yaml @@ -5,6 +5,16 @@ # model_prices_and_context_window map) so cost tracking is correct even on # litellm versions whose bundled price map predates a model. model_list: + # Fable (Mythos-class tier above Opus). + - model_name: claude-fable-5 + litellm_params: + model: anthropic/claude-fable-5 + api_key: os.environ/ANTHROPIC_API_KEY + input_cost_per_token: 0.00001 + output_cost_per_token: 0.00005 + cache_creation_input_token_cost: 0.0000125 + cache_read_input_token_cost: 0.000001 + # Current Opus line. - model_name: claude-opus-4-8 litellm_params: diff --git a/scripts/snapshot_minds_e2e_state.py b/scripts/snapshot_minds_e2e_state.py index c00208d10a..939fa21044 100644 --- a/scripts/snapshot_minds_e2e_state.py +++ b/scripts/snapshot_minds_e2e_state.py @@ -96,7 +96,7 @@ # Keep these in sync with apps/minds/.nvmrc and apps/minds/package.json engines. _NODE_VERSION: Final[str] = "24.15.0" _PNPM_VERSION: Final[str] = "10.33.4" -_CLAUDE_CODE_VERSION: Final[str] = "2.1.160" +_CLAUDE_CODE_VERSION: Final[str] = "2.1.207" # In-sandbox entrypoint that invokes the shared e2e workspace runner the # pytest test also uses, but without the test's mngr-destroy cleanup. The From e6c5bbd00eee4eaa8f29e7c1e16872900aaf11fd Mon Sep 17 00:00:00 2001 From: Weishi Zeng Date: Sat, 11 Jul 2026 16:56:57 -0700 Subject: [PATCH 2/6] Simplify Fable model-list comment Co-Authored-By: Claude Fable 5 --- apps/modal_litellm/app.py | 2 +- litellm_proxy/config.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/modal_litellm/app.py b/apps/modal_litellm/app.py index 54f4d80c89..c6bfa6f67f 100644 --- a/apps/modal_litellm/app.py +++ b/apps/modal_litellm/app.py @@ -114,7 +114,7 @@ def _model_entry(model_name: str, pricing: dict[str, float]) -> dict[str, object LITELLM_CONFIG = { "model_list": [ - # Fable (Mythos-class tier above Opus). + # Fable line. _model_entry("claude-fable-5", _FABLE_PRICING), # Current Opus line. _model_entry("claude-opus-4-8", _OPUS_PRICING), diff --git a/litellm_proxy/config.yaml b/litellm_proxy/config.yaml index 123c08be37..a284a323c8 100644 --- a/litellm_proxy/config.yaml +++ b/litellm_proxy/config.yaml @@ -5,7 +5,7 @@ # model_prices_and_context_window map) so cost tracking is correct even on # litellm versions whose bundled price map predates a model. model_list: - # Fable (Mythos-class tier above Opus). + # Fable line. - model_name: claude-fable-5 litellm_params: model: anthropic/claude-fable-5 From 981816072c9c1dfe68e1fc07a21efdc4f0416580 Mon Sep 17 00:00:00 2001 From: Weishi Zeng Date: Sat, 11 Jul 2026 17:19:02 -0700 Subject: [PATCH 3/6] Document the litellm_proxy config change in the dev changelog Problem: dev/changelog/mngr-fable.md described only the Claude Code CLI version bump, omitting the claude-fable-5 addition to the repo-root litellm_proxy/config.yaml, which is also a dev-project change. Fix: add a second bullet covering the config.yaml model addition and its inline pricing, matching how the prior model-lineup PR documented it. Co-Authored-By: Claude Fable 5 --- dev/changelog/mngr-fable.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dev/changelog/mngr-fable.md b/dev/changelog/mngr-fable.md index ffdb175a96..d9a05fdd7c 100644 --- a/dev/changelog/mngr-fable.md +++ b/dev/changelog/mngr-fable.md @@ -1 +1,3 @@ -Bump the pinned Claude Code CLI version from 2.1.160 to 2.1.207 in CI workflows (`release-tests.yml`, `tmr-setup` action) and the minds e2e snapshot script, matching the new workspace pin that supports Claude Fable 5. +- Bump the pinned Claude Code CLI version from 2.1.160 to 2.1.207 in CI workflows (`release-tests.yml`, `tmr-setup` action) and the minds e2e snapshot script, matching the new workspace pin that supports Claude Fable 5. + +- Add `claude-fable-5` with inline pricing ($10 / $50 per 1M input / output tokens, cache write 1.25e-5, cache read 1e-6) to the repo-root local-dev LiteLLM proxy config (`litellm_proxy/config.yaml`), kept in sync with `apps/modal_litellm/app.py` by a drift test. From 0c16a062fdae87b6495ba16bfd547eddb49ba8e8 Mon Sep 17 00:00:00 2001 From: Weishi Zeng Date: Sat, 11 Jul 2026 17:20:13 -0700 Subject: [PATCH 4/6] Add Fable pricing to the Agent SDK price table Problem: the mngr_robinhood Agent SDK resolves per-model pricing by family substring (haiku/sonnet/opus only), so claude-fable-5 sessions reported ResultMessage.total_cost_usd=None -- the same unpriced gap this branch closed in mngr_usage's token->USD table. Fix: add _FABLE_PRICING (input $10 / output $50 per 1M, cache write $12.50, cache read $1.00, matching litellm's price map) and a fable family entry, with a resolve test and a mngr_robinhood changelog entry. Co-Authored-By: Claude Fable 5 --- libs/mngr_robinhood/changelog/mngr-fable.md | 1 + .../imbue/mngr_robinhood/_agent_sdk/pricing.py | 7 +++++++ .../imbue/mngr_robinhood/_agent_sdk/pricing_test.py | 1 + 3 files changed, 9 insertions(+) create mode 100644 libs/mngr_robinhood/changelog/mngr-fable.md diff --git a/libs/mngr_robinhood/changelog/mngr-fable.md b/libs/mngr_robinhood/changelog/mngr-fable.md new file mode 100644 index 0000000000..97b8d8d7a1 --- /dev/null +++ b/libs/mngr_robinhood/changelog/mngr-fable.md @@ -0,0 +1 @@ +Add a Claude Fable family entry ($10 / $50 per 1M input / output tokens, cache write $12.50, cache read $1.00) to the Agent SDK per-model price table, so `ResultMessage.total_cost_usd` is populated for `claude-fable-5` sessions instead of being left unset. diff --git a/libs/mngr_robinhood/imbue/mngr_robinhood/_agent_sdk/pricing.py b/libs/mngr_robinhood/imbue/mngr_robinhood/_agent_sdk/pricing.py index 04fcd758af..1f59aa20c8 100644 --- a/libs/mngr_robinhood/imbue/mngr_robinhood/_agent_sdk/pricing.py +++ b/libs/mngr_robinhood/imbue/mngr_robinhood/_agent_sdk/pricing.py @@ -52,6 +52,12 @@ class ModelPricing(FrozenModel): cache_write_usd_per_million=Decimal("6.25"), cache_read_usd_per_million=Decimal("0.50"), ) +_FABLE_PRICING: Final[ModelPricing] = ModelPricing( + input_usd_per_million=Decimal("10.00"), + output_usd_per_million=Decimal("50.00"), + cache_write_usd_per_million=Decimal("12.50"), + cache_read_usd_per_million=Decimal("1.00"), +) # Model-id substrings mapped to their pricing, checked in order. claude model ids look like # ``claude-haiku-4-5-20251001`` / ``claude-sonnet-4-6`` / ``claude-opus-4-8``, so a family @@ -60,6 +66,7 @@ class ModelPricing(FrozenModel): ("haiku", _HAIKU_PRICING), ("sonnet", _SONNET_PRICING), ("opus", _OPUS_PRICING), + ("fable", _FABLE_PRICING), ) diff --git a/libs/mngr_robinhood/imbue/mngr_robinhood/_agent_sdk/pricing_test.py b/libs/mngr_robinhood/imbue/mngr_robinhood/_agent_sdk/pricing_test.py index 74f9863781..a7fd23557d 100644 --- a/libs/mngr_robinhood/imbue/mngr_robinhood/_agent_sdk/pricing_test.py +++ b/libs/mngr_robinhood/imbue/mngr_robinhood/_agent_sdk/pricing_test.py @@ -7,6 +7,7 @@ def test_resolve_model_pricing_matches_family_for_dated_and_alias_ids() -> None: assert resolve_model_pricing("claude-haiku-4-5-20251001") is resolve_model_pricing("haiku") assert resolve_model_pricing("claude-sonnet-4-6") is resolve_model_pricing("sonnet") assert resolve_model_pricing("claude-opus-4-8") is resolve_model_pricing("opus") + assert resolve_model_pricing("claude-fable-5") is resolve_model_pricing("fable") def test_resolve_model_pricing_is_none_for_unknown_model() -> None: From 9cbe5c5b910057172d72bd6239803bf45eef3c66 Mon Sep 17 00:00:00 2001 From: Weishi Zeng Date: Tue, 14 Jul 2026 14:35:53 -0700 Subject: [PATCH 5/6] Add auto_disable_questions to ClaudeAgentConfig Recent Claude Code releases no longer treat AskUserQuestion as a permission prompt, so auto_allow_permissions alone no longer keeps an unattended agent from blocking on a question. The new opt-in field appends '--disallowed-tools AskUserQuestion' to the agent invocation. Appended as a separate repeated flag: verified against claude 2.1.207 that repeated --disallowed-tools flags accumulate, so a list already supplied via cli_args survives. Not enabled in this repo's own .mngr/settings.toml (agents here run interactively where questions are wanted). default-workspace-template keeps covering this via its raw cli_args for now: its vendored mngr predates the field and ClaudeAgentConfig forbids unknown keys, so the template can only switch to the typed field after the next vendor sync. Co-Authored-By: Claude Fable 5 --- libs/mngr_claude/changelog/mngr-fable.md | 1 + libs/mngr_claude/imbue/mngr_claude/plugin.py | 9 +++++ .../imbue/mngr_claude/plugin_test.py | 36 +++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 libs/mngr_claude/changelog/mngr-fable.md diff --git a/libs/mngr_claude/changelog/mngr-fable.md b/libs/mngr_claude/changelog/mngr-fable.md new file mode 100644 index 0000000000..84d62d77d7 --- /dev/null +++ b/libs/mngr_claude/changelog/mngr-fable.md @@ -0,0 +1 @@ +Add `auto_disable_questions` to `ClaudeAgentConfig`: when True, appends `--disallowed-tools AskUserQuestion` to the agent invocation so unattended agents can't block on questions (recent Claude Code releases no longer treat AskUserQuestion as a permission prompt, so `auto_allow_permissions` alone no longer covers it). Appended as a separate flag; Claude accumulates repeated `--disallowed-tools` flags, so a list already supplied via `cli_args` is preserved. diff --git a/libs/mngr_claude/imbue/mngr_claude/plugin.py b/libs/mngr_claude/imbue/mngr_claude/plugin.py index 01a8d10a3d..477bb2a5a4 100644 --- a/libs/mngr_claude/imbue/mngr_claude/plugin.py +++ b/libs/mngr_claude/imbue/mngr_claude/plugin.py @@ -311,6 +311,11 @@ class ClaudeAgentConfig(AgentTypeConfig): description="When True, adds a PermissionRequest hook that auto-allows all permission dialogs. " "This means Claude Code will never pause for permission approval.", ) + auto_disable_questions: bool = Field( + default=False, + description="When True, adds `--disallowed-tools AskUserQuestion` to the agent invocation to " + "prevent it from ever asking questions (which can cause the agent to get blocked)", + ) settings_overrides: Annotated[dict[str, Any], SettingsPatchField()] = Field( default_factory=dict, description="A patch merged onto your home Claude settings at provisioning. A bare key assigns " @@ -2360,6 +2365,10 @@ def assemble_command( # (Claude is last-wins) -- the accepted, documented limitation of that mode. cli_args = self.agent_config.cli_args all_extra_args = cli_args + quote_agent_args(agent_args) + # Claude accumulates repeated --disallowed-tools flags, so appending here + # cannot clobber a list already present in cli_args/agent_args. + if self.agent_config.auto_disable_questions: + all_extra_args = all_extra_args + ("--disallowed-tools", "AskUserQuestion") args_str = " ".join(all_extra_args) if all_extra_args else "" # Read the latest session ID from the tracking file written by the SessionStart hook. diff --git a/libs/mngr_claude/imbue/mngr_claude/plugin_test.py b/libs/mngr_claude/imbue/mngr_claude/plugin_test.py index 2af64cd372..18c6a7deac 100644 --- a/libs/mngr_claude/imbue/mngr_claude/plugin_test.py +++ b/libs/mngr_claude/imbue/mngr_claude/plugin_test.py @@ -493,6 +493,42 @@ def test_claude_agent_assemble_command_with_cli_args_and_agent_args( assert parsed.create_args == ["--verbose", "--model", "opus"] +def test_claude_agent_assemble_command_auto_disable_questions_appends_flag( + local_provider: LocalProviderInstance, tmp_path: Path, temp_mngr_ctx: MngrContext +) -> None: + """auto_disable_questions=True should append --disallowed-tools AskUserQuestion after all other args.""" + agent, host = make_claude_agent( + local_provider, + tmp_path, + temp_mngr_ctx, + agent_config=ClaudeAgentConfig( + cli_args=("--disallowed-tools", "TodoWrite"), + auto_disable_questions=True, + check_installation=False, + ), + ) + + command = agent.assemble_command(host=host, agent_args=(), command_override=None) + + parsed = _ParsedAssembleCommand(str(command)) + # Appended as a second --disallowed-tools flag (claude accumulates repeats), + # so the cli_args-supplied list is preserved. + expected = ["--disallowed-tools", "TodoWrite", "--disallowed-tools", "AskUserQuestion"] + assert parsed.resume_args == expected + assert parsed.create_args == expected + + +def test_claude_agent_assemble_command_auto_disable_questions_off_by_default( + local_provider: LocalProviderInstance, tmp_path: Path, temp_mngr_ctx: MngrContext +) -> None: + """Default config should not add any --disallowed-tools flag.""" + agent, host = make_claude_agent(local_provider, tmp_path, temp_mngr_ctx) + + command = agent.assemble_command(host=host, agent_args=(), command_override=None) + + assert "--disallowed-tools" not in shlex.split(str(command)) + + def test_claude_agent_assemble_command_passes_user_settings_through( local_provider: LocalProviderInstance, tmp_path: Path, temp_mngr_ctx: MngrContext ) -> None: From 97f351e8c1eb9a7812cfabb260bd7578be92d332 Mon Sep 17 00:00:00 2001 From: Weishi Zeng Date: Tue, 14 Jul 2026 14:44:26 -0700 Subject: [PATCH 6/6] Reword disallowed-tools flag comment Co-Authored-By: Claude Fable 5 --- libs/mngr_claude/imbue/mngr_claude/plugin.py | 3 +-- libs/mngr_claude/imbue/mngr_claude/plugin_test.py | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libs/mngr_claude/imbue/mngr_claude/plugin.py b/libs/mngr_claude/imbue/mngr_claude/plugin.py index 477bb2a5a4..0891d05510 100644 --- a/libs/mngr_claude/imbue/mngr_claude/plugin.py +++ b/libs/mngr_claude/imbue/mngr_claude/plugin.py @@ -2365,8 +2365,7 @@ def assemble_command( # (Claude is last-wins) -- the accepted, documented limitation of that mode. cli_args = self.agent_config.cli_args all_extra_args = cli_args + quote_agent_args(agent_args) - # Claude accumulates repeated --disallowed-tools flags, so appending here - # cannot clobber a list already present in cli_args/agent_args. + # Claude appends & unions repeated --disallowed-tools flags. if self.agent_config.auto_disable_questions: all_extra_args = all_extra_args + ("--disallowed-tools", "AskUserQuestion") args_str = " ".join(all_extra_args) if all_extra_args else "" diff --git a/libs/mngr_claude/imbue/mngr_claude/plugin_test.py b/libs/mngr_claude/imbue/mngr_claude/plugin_test.py index 18c6a7deac..1c4f0c6f84 100644 --- a/libs/mngr_claude/imbue/mngr_claude/plugin_test.py +++ b/libs/mngr_claude/imbue/mngr_claude/plugin_test.py @@ -511,8 +511,8 @@ def test_claude_agent_assemble_command_auto_disable_questions_appends_flag( command = agent.assemble_command(host=host, agent_args=(), command_override=None) parsed = _ParsedAssembleCommand(str(command)) - # Appended as a second --disallowed-tools flag (claude accumulates repeats), - # so the cli_args-supplied list is preserved. + # Appended as a second --disallowed-tools flag (claude appends & unions + # repeated flags), so the cli_args-supplied list is preserved. expected = ["--disallowed-tools", "TodoWrite", "--disallowed-tools", "AskUserQuestion"] assert parsed.resume_args == expected assert parsed.create_args == expected