Skip to content

Mirror: Fix ZenMux model metadata and native tool message handling (#5831)#30

Merged
jeremylongshore merged 5 commits intomainfrom
mirror/PR-5831
Feb 15, 2026
Merged

Mirror: Fix ZenMux model metadata and native tool message handling (#5831)#30
jeremylongshore merged 5 commits intomainfrom
mirror/PR-5831

Conversation

@jeremylongshore
Copy link
Copy Markdown
Owner

Mirror of upstream PR #5831

Verdict: APPROVE | Tier 5

Review: kilocode-5831-review.md

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 15, 2026

Warning

Rate limit exceeded

@jeremylongshore has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 29 minutes and 15 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch mirror/PR-5831

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @jeremylongshore, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request focuses on enhancing the stability and functionality of the ZenMux provider and improving overall error handling within the system. Key updates include refining ZenMux model metadata to better support native tools and ensuring reliable tool-calling behavior. Additionally, the changes introduce more robust error processing for streaming operations across various AI providers, allowing for more accurate error reporting and retry mechanisms. A significant fix addresses the processing of slash commands within tool results, ensuring user commands are correctly interpreted in all contexts. Finally, the integration with the Model Context Protocol now dynamically updates available capabilities, leading to a more responsive and up-to-date user experience.

Highlights

  • ZenMux Model Enhancements: Updated ZenMux model metadata to explicitly support native tools and set the default tool protocol. This includes robust handling of model cache entries with invalid context window values.
  • Improved ZenMux Tooling & Context: Enhanced ZenMux tool-calling reliability to prevent looping issues and ensure transformed request messages are preserved. Fixed context window detection to avoid erroneous condensing loops.
  • Robust Error Handling: Significantly improved error handling across AI providers, particularly for streaming errors. This includes better extraction of error messages, status codes, and detailed payloads from various error structures (e.g., AI SDK, AWS metadata).
  • Slash Command Processing Fix: Corrected an issue where slash commands within 'tool_result' blocks were ignored, ensuring proper processing and transformation of these commands.
  • Dynamic MCP Notifications: Enhanced the Model Context Protocol (MCP) integration to dynamically refresh available server capabilities (tools, resources, prompts) upon receiving 'list_changed' notifications from the MCP server.
Changelog
  • .changeset/free-toes-hammer.md
    • fix(mentions): process slash commands in tool_result blocks
    • Previously, parseKiloSlashCommands was only called for text blocks, causing slash commands in tool_result blocks to be ignored. This fix extends the processing to tool_result blocks by using the new processTextContent helper function that combines parseMentions and parseKiloSlashCommands.
    • The regression test ensures that slash commands in tool responses are properly processed and transformed.
  • .changeset/slow-pillows-tap.md
    • Fix Kilo Quota | OpenRouter error handling and retry flow
  • .changeset/zenmux-context-window-fix.md
    • Fixed ZenMux context window detection to prevent erroneous context-condensing loops.
  • .changeset/zenmux-native-tools-reliability.md
    • Fixed ZenMux tool-calling reliability to avoid repeated "tool not used" loops and preserve transformed request messages.
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/auto-triage.yml
Activity
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Mirror: Fix ZenMux model metadata and native tool message handling

🐞 Bug fix ✨ Enhancement 🧪 Tests

Grey Divider

Walkthroughs

Description
• **ZenMux native tools reliability**: Fixed native tool metadata merging, message format handling,
  and context window detection to prevent "tool not used" loops
• **Slash command processing in tool results**: Extended parseKiloSlashCommands to handle
  tool_result blocks, fixing a regression where slash commands were not processed in tool results
• **ZenMux model cache validation**: Added self-healing logic to reject stale cache entries with
  invalid context window values from v5.7.0
• **Enhanced error handling**: Improved nested error payload extraction and status code resolution
  for better error propagation from providers
• **MCP notification handlers**: Added support for ResourceListChanged, ToolListChanged, and
  PromptListChanged notifications with dynamic capability refresh
• **Stream error handling**: Added error handling for AI SDK stream error parts to surface
  provider-specific errors
• **Comprehensive test coverage**: Added test suites for ZenMux native tools, MCP notifications,
  error handling, model fetching, and slash command processing
• **GitHub Actions auto-triage**: Added workflow for automatic issue and PR labeling
Diagram
flowchart LR
  A["ZenMux Model Fetcher"] -->|"native tools defaults"| B["Model Info"]
  B -->|"merge metadata"| C["ZenMux Stream"]
  C -->|"OpenAI format messages"| D["Native Tool Support"]
  E["Tool Results"] -->|"parse slash commands"| F["Content Processing"]
  G["MCP Server"] -->|"list change notifications"| H["Notification Service"]
  H -->|"refresh callback"| I["Capability Refresh"]
  J["Provider Errors"] -->|"extract nested payload"| K["Error Handler"]
  K -->|"normalized errors"| L["Stream Processing"]
Loading

Grey Divider

File Changes

1. src/services/mcp/kilocode/__tests__/NotificationService.spec.ts 🧪 Tests +346/-0

Comprehensive test suite for MCP notification service

• Added comprehensive test suite for NotificationService with 346 lines of test coverage
• Tests verify notification handler registration for logging, resource, tool, and prompt list
 changes
• Tests validate proper message formatting, error handling, and callback invocation
• Tests ensure fallback handler logs unhandled notifications without showing user notifications

src/services/mcp/kilocode/tests/NotificationService.spec.ts


2. src/core/mentions/__tests__/processKiloUserContentMentions.spec.ts 🧪 Tests +191/-0

Regression tests for slash commands in tool results

• Added regression test suite for slash command processing in tool_result blocks
• Tests verify that parseKiloSlashCommands is called for both string and array content in tool
 results
• Tests validate slash command transformation and proper handling of content without mention tags
• Includes detailed comments explaining the bug and expected behavior

src/core/mentions/tests/processKiloUserContentMentions.spec.ts


3. src/api/providers/__tests__/zenmux-native-tools.spec.ts 🧪 Tests +175/-0

ZenMux native tools and message pipeline tests

• Added test suite for ZenMux native tools and message pipeline handling
• Tests verify native tool metadata merging when model cache lacks native metadata
• Tests validate tool and tool choice parameters are passed correctly for native protocol
• Tests ensure tools are omitted for XML protocol and DeepSeek R1 messages are transformed

src/api/providers/tests/zenmux-native-tools.spec.ts


View more (27)
4. src/api/providers/utils/error-handler.ts Error handling +112/-8

Enhanced error handling with nested payload extraction

• Added helper functions for robust error payload extraction and status code resolution
• Implemented extractErrorPayload() to safely parse nested error structures from various payload
 formats
• Enhanced error message resolution to prefer nested provider errors over generic "No output
 generated" messages
• Improved status code detection from multiple possible error object properties

src/api/providers/utils/error-handler.ts


5. src/api/providers/zenmux.ts ✨ Enhancement +27/-18

ZenMux native tools and message format improvements

• Modified createZenMuxStream() to accept pre-converted OpenAI messages instead of Anthropic
 format
• Added toolChoice and parallelToolCalls parameters to stream creation for native tool support
• Updated getModel() to merge NATIVE_TOOL_DEFAULTS with cached model info
• Enhanced tool protocol resolution to use metadata-provided toolProtocol when available

src/api/providers/zenmux.ts


6. src/core/mentions/processKiloUserContentMentions.ts 🐞 Bug fix +51/-38

Process slash commands in tool result blocks

• Extracted text processing logic into reusable processTextContent() helper function
• Extended slash command processing to tool_result blocks (both string and array content)
• Consolidated parseMentions and parseKiloSlashCommands calls for consistent handling
• Properly propagates needsRulesFileCheck flag from tool result processing

src/core/mentions/processKiloUserContentMentions.ts


7. src/api/providers/openai-compatible.ts Error handling +57/-46

Stream error handling for OpenAI-compatible providers

• Added error handling for AI SDK stream error parts to surface provider errors
• Wrapped stream processing in try-catch to normalize errors via handleProviderError()
• Detects and throws stream error parts before processing other stream events
• Ensures proper error propagation with provider-specific context

src/api/providers/openai-compatible.ts


8. src/services/mcp/kilocode/NotificationService.ts ✨ Enhancement +56/-4

MCP notification handlers for capability refresh

• Added handlers for ResourceListChanged, ToolListChanged, and PromptListChanged notifications
• Implemented RefreshCapabilitiesCallback type for capability refresh on list changes
• Changed fallback handler to log unhandled notifications silently instead of showing user
 notifications
• Added comprehensive JSDoc documentation for the connect() method

src/services/mcp/kilocode/NotificationService.ts


9. src/api/providers/__tests__/moonshot.spec.ts 🧪 Tests +67/-0

Moonshot stream error handling tests

• Added test for normalized stream errors from fullStream error parts with status and details
• Added test for surfacing nested provider errors when usage promise rejects with generic message
• Tests verify proper error message extraction and status code preservation
• Tests ensure partial responses are yielded before error is thrown

src/api/providers/tests/moonshot.spec.ts


10. src/api/providers/utils/__tests__/error-handler.spec.ts 🧪 Tests +40/-0

Error handler tests for nested payloads

• Added test for preserving statusCode field from Error objects
• Added test for extracting message and details from responseBody payload
• Added test for AWS metadata httpStatusCode fallback
• Tests verify proper error normalization across different error object structures

src/api/providers/utils/tests/error-handler.spec.ts


11. src/api/providers/fetchers/__tests__/zenmux.spec.ts 🧪 Tests +70/-0

ZenMux model fetcher tests

• Added test suite for getZenmuxModels() function
• Tests verify context_length mapping from ZenMux model payload to contextWindow
• Tests validate fallback to default context window when optional metadata is missing
• Tests ensure native tools defaults are applied to all models

src/api/providers/fetchers/tests/zenmux.spec.ts


12. src/api/providers/fetchers/zenmux.ts ✨ Enhancement +15/-6

ZenMux model fetcher with native tools support

• Updated ZenMux model schema to include optional display_name, context_length, and
 input_modalities
• Changed base URL to use openRouterBaseUrl option when available
• Added native tools support defaults (supportsNativeTools: true, defaultToolProtocol: "native")
• Improved context window handling with fallback to default when missing or zero

src/api/providers/fetchers/zenmux.ts


13. src/api/providers/fetchers/modelCache.ts 🐞 Bug fix +19/-0

ZenMux model cache validation and self-healing

• Added validation to reject stale ZenMux cache entries with invalid contextWindow values
• Implemented hasInvalidZenmuxContextWindow() helper to detect zero or negative context windows
• Added self-healing logic to ignore stale cache from v5.7.0 where contextWindow was persisted as
 0
• Logs warnings when stale cache is detected and ignored

src/api/providers/fetchers/modelCache.ts


14. src/api/providers/fetchers/__tests__/modelCache.spec.ts 🧪 Tests +43/-0

Model cache validation tests for ZenMux

• Added test to verify rejection of stale ZenMux cache with invalid contextWindow
• Added test to verify acceptance of valid ZenMux cache entries
• Tests ensure console warnings are logged for stale cache detection
• Tests validate that disk fallback is skipped for invalid memory cache

src/api/providers/fetchers/tests/modelCache.spec.ts


15. src/services/mcp/McpHub.ts ✨ Enhancement +6/-1

MCP capability refresh on server notifications

• Updated kiloNotificationService.connect() call to pass refresh callback
• Callback invokes fetchAvailableServerCapabilities() and notifyWebviewOfServerChanges() on list
 changes
• Enables dynamic capability updates when MCP server notifies of tool, resource, or prompt changes

src/services/mcp/McpHub.ts


16. packages/types/src/providers/zenmux.ts ✨ Enhancement +4/-0

ZenMux default model native tools support

• Added supportsNativeTools: true to zenmuxDefaultModelInfo
• Added defaultToolProtocol: "native" to zenmuxDefaultModelInfo
• Ensures all ZenMux models default to native tool support

packages/types/src/providers/zenmux.ts


17. .github/workflows/auto-triage.yml ⚙️ Configuration changes +126/-0

GitHub Actions auto-triage workflow

• Added new GitHub Actions workflow for automatic issue and PR triage
• Workflow uses Kilo Code CLI to analyze and label issues/PRs
• Includes comprehensive label categories for components, types, platforms, and providers
• Implements safety checks to skip bot-created items and limit label additions

.github/workflows/auto-triage.yml


18. .changeset/free-toes-hammer.md 📝 Documentation +14/-0

Changelog for tool result slash command fix

• Changelog entry for slash command processing fix in tool_result blocks
• Documents the bug where parseKiloSlashCommands was not called for tool results
• References the regression test that validates the fix

.changeset/free-toes-hammer.md


19. .changeset/zenmux-native-tools-reliability.md 📝 Documentation +5/-0

Changelog for ZenMux native tools reliability

• Changelog entry for ZenMux native tool-calling reliability improvements
• Documents fix for "tool not used" loops and message transformation preservation

.changeset/zenmux-native-tools-reliability.md


20. .changeset/zenmux-context-window-fix.md 📝 Documentation +5/-0

Changelog for ZenMux context window fix

• Changelog entry for ZenMux context window detection fix
• Documents prevention of erroneous context-condensing loops

.changeset/zenmux-context-window-fix.md


21. .changeset/slow-pillows-tap.md 📝 Documentation +5/-0

Changelog for error handling and retry improvements

• Changelog entry for Kilo Quota and OpenRouter error handling improvements
• Documents retry flow enhancements

.changeset/slow-pillows-tap.md


22. .beads/sync-state.json Miscellaneous +7/-0

Beads synchronization state metadata

• Beads sync state tracking file with failure information
• Records last failure timestamp and backoff period
• Indicates manual sync is needed due to missing remote ref

.beads/sync-state.json


23. .beads/beads.left.meta.json Miscellaneous +1/-0

Beads version and commit metadata

• Beads metadata file tracking version and commit information
• Records version 0.49.1 and associated commit hash

.beads/beads.left.meta.json


24. .beads/metadata.json ⚙️ Configuration changes +4/-0

Beads database configuration

• Beads configuration file specifying database and export settings
• Defines database file path and JSONL export location

.beads/metadata.json


25. .beads/.local_version Miscellaneous +1/-0

Beads local version tracking

• Local version file for Beads tracking
• Records version 0.49.1

.beads/.local_version


26. .beads/last-touched Miscellaneous +1/-0

Beads last touched metadata

• Beads metadata file tracking last touched identifier
• Records "kilo-ko9" as the last touched reference

.beads/last-touched


27. .beads/daemon.pid Miscellaneous +1/-0

Beads daemon process tracking

• Beads daemon process ID file
• Records PID 171809

.beads/daemon.pid


28. .beads/beads.db-shm Miscellaneous +0/-0

SQLite database shared memory file update

• SQLite shared memory file updated with binary database state changes
• File transitioned from empty state to populated with database transaction data
• Contains serialized database page information and transaction metadata

.beads/beads.db-shm


29. .beads/beads.db-wal Additional files +0/-0

...

.beads/beads.db-wal


30. .beads/beads.left.jsonl Additional files +0/-0

...

.beads/beads.left.jsonl


Grey Divider

Qodo Logo

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces several significant improvements and fixes. It correctly handles ZenMux model metadata, particularly the contextWindow, and adds support for native tools. Error handling has been made more robust across providers, with better extraction of details from streaming and nested errors. A bug preventing slash command processing in tool_result blocks has been fixed through a nice refactoring. Additionally, the MCP client is now more dynamic, capable of refreshing its capabilities in response to server notifications. The changes are well-tested and improve the overall stability and functionality of the system.

tools,
tool_choice: tools ? "auto" : undefined,
tool_choice: toolChoice ?? "auto",
parallel_tool_calls: enableParallelToolCalls ? true : false,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The expression enableParallelToolCalls ? true : false is redundant as enableParallelToolCalls is already a boolean. You can simplify this to just enableParallelToolCalls for better readability.

parallel_tool_calls: enableParallelToolCalls,

@jeremylongshore jeremylongshore merged commit 759c24d into main Feb 15, 2026
11 of 15 checks passed
@github-actions
Copy link
Copy Markdown

Failed to generate code suggestions for PR

@qodo-code-review
Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (2) 📎 Requirement gaps (0)

Grey Divider


Action required

1. zenmux.ts changes lack markers 📘 Rule violation ⛯ Reliability
Description
Changes were made to an upstream-shared file under src/ without being wrapped in kilocode_change
markers, increasing the risk of upstream sync merge conflicts. Only a subset of the modifications in
the file are annotated.
Code

src/api/providers/fetchers/zenmux.ts[37]

+	const baseURL = options?.openRouterBaseUrl || "https://zenmux.ai/api/v1"
Evidence
Compliance ID 7 requires kilocode_change markers for modifications to upstream-shared src/
files. The PR changes the ZenMux fetcher logic (e.g., base URL selection and schema fields) without
kilocode_change markers in those modified areas.

AGENTS.md
src/api/providers/fetchers/zenmux.ts[37-37]
src/api/providers/fetchers/zenmux.ts[15-17]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Updates to an upstream-shared file under `src/` were introduced without `kilocode_change` markers around the modified sections, which can increase merge conflicts during upstream sync.

## Issue Context
Rule requires Kilo-specific modifications in upstream-shared code to be annotated with `kilocode_change` markers.

## Fix Focus Areas
- src/api/providers/fetchers/zenmux.ts[15-17]
- src/api/providers/fetchers/zenmux.ts[37-37]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Committed .beads artifacts 🐞 Bug ⛯ Reliability
Description
The PR adds multiple .beads/ machine-generated runtime/state files (SQLite db/shm/wal, PID, sync
state, timestamps) that are not stable source artifacts. This will bloat the repo, create frequent
merge conflicts, and leak local environment metadata (paths/PIDs).
Code

.beads/beads.db-shm[R1-5]

+��-�����������������L������r�tN�A�N��Ĵ�
+��"����-�����������������L������r�tN�A�N��Ĵ�
+��"����������������������������������������������
+���������������
+������� ���1���2���6���=���E���H�������<���F���L�����������	���
Evidence
The repo already contains .beads state showing machine-specific values (absolute local path and
PID), and another part of the repo explicitly ignores .beads/, suggesting it’s a generated
directory; only .beads/issues.jsonl appears to have merge configuration, not SQLite runtime files.

.beads/daemon.lock[1-6]
apps/kilocode-docs/.gitignore[1-10]
apps/kilocode-docs/.gitattributes[1-3]
.gitignore[1-79]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The PR introduces `.beads/` runtime artifacts (SQLite db/shm/wal, pid files, sync-state, timestamps). These are generated, machine-specific, and will cause repo bloat + merge churn.

### Issue Context
The repo already shows `.beads/` containing absolute local paths and PIDs, and another app explicitly ignores `.beads/`. Only `.beads/issues.jsonl` appears to be treated as a versionable artifact.

### Fix Focus Areas
- .gitignore[1-120]
- .beads/beads.db-shm[1-10]
- .beads/daemon.pid[1-2]
- .beads/sync-state.json[1-20]
- .beads/metadata.json[1-20]
- .beads/beads.left.meta.json[1-5]
- .beads/.local_version[1-2]

### Expected fix
- Delete generated `.beads` runtime/state files from the repo.
- Add `.beads/` ignore patterns in the root `.gitignore`.
- If `issues.jsonl` must remain tracked, use a negation rule (`!.beads/issues.jsonl`) and keep the rest ignored.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. LLM can over-edit via gh 🐞 Bug ⛨ Security
Description
The auto-triage workflow enables LLM-driven command execution and allowlists gh issue edit / `gh
pr edit`, but the CLI approval logic uses prefix matching—so these allowlist entries permit
arbitrary edits (title/body/etc.), not just label adds. Because issue/PR title/body is untrusted
user input, prompt injection can cause unintended repository actions within the granted permissions.
Code

.github/workflows/auto-triage.yml[R40-74]

+          KILO_AUTO_APPROVAL_ENABLED: "true"
+          KILO_AUTO_APPROVAL_EXECUTE_ENABLED: "true"
+          KILO_AUTO_APPROVAL_EXECUTE_ALLOWED: "gh issue edit,gh pr edit"
+          KILO_AUTO_APPROVAL_EXECUTE_DENIED: "gh issue close,gh issue delete,gh issue transfer,gh issue lock,gh issue unlock,gh pr close,gh pr merge,gh repo,gh auth,gh secret,gh variable,rm,sudo,curl,wget,bash,sh,python,node,npm,npx"
+          KILO_TELEMETRY: "false"
+          # Determine event type and extract data
+          EVENT_TYPE: ${{ github.event_name }}
+          ITEM_NUMBER: ${{ github.event_name == 'issues' && github.event.issue.number || github.event.pull_request.number }}
+          ITEM_TITLE: ${{ github.event_name == 'issues' && github.event.issue.title || github.event.pull_request.title }}
+          ITEM_BODY: ${{ github.event_name == 'issues' && github.event.issue.body || github.event.pull_request.body }}
+        run: |
+          # Sanitize body - remove shell metacharacters
+          SAFE_BODY=$(echo "$ITEM_BODY" | head -c 2000 | tr -d '`$(){}[]|;&<>\\' | tr '\n' ' ')
+          
+          # Determine gh command based on event type
+          if [ "$EVENT_TYPE" = "issues" ]; then
+            GH_CMD="gh issue edit"
+            ITEM_TYPE="issue"
+          else
+            GH_CMD="gh pr edit"
+            ITEM_TYPE="pull request"
+          fi
+          
+          kilocode --auto "Triage this GitHub ${ITEM_TYPE}:
+
+          Number: ${ITEM_NUMBER}
+          Title: ${ITEM_TITLE}
+          Body: ${SAFE_BODY}
+
+          ## Your Task
+          Add appropriate labels to this ${ITEM_TYPE}.
+
+          ## Command Format
+          Use ONLY: ${GH_CMD} ${ITEM_NUMBER} --add-label \"<label>\"
+
Evidence
The workflow explicitly enables execute auto-approval and allows gh issue edit/gh pr edit. The
CLI’s matching function approves commands when the command starts with an allowed prefix, so any `gh
issue edit …` invocation (with arbitrary flags) is auto-approved, even if the prompt asked for
labels only.

.github/workflows/auto-triage.yml[40-44]
cli/src/services/approvalDecision.ts[28-59]
cli/src/services/approvalDecision.ts[171-236]
.github/workflows/auto-triage.yml[63-74]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The workflow enables auto-execution of LLM-produced shell commands and allowlists `gh issue edit` / `gh pr edit`. The CLI allowlist matcher is prefix-based, so any `gh issue edit ...` command (including changing title/body) will be auto-approved. This is vulnerable to prompt injection from untrusted issue/PR content.

### Issue Context
The workflow’s prompt instructs “labels only”, but enforcement is not technical—only prompt-based. The approval layer is prefix-based, not argument-constrained.

### Fix Focus Areas
- .github/workflows/auto-triage.yml[33-74]
- cli/src/services/approvalDecision.ts[28-59]
- cli/src/services/approvalDecision.ts[171-236]

### Expected fix
Choose one:
1) Disable execute auto-approval in this workflow and implement labeling via GitHub API directly in the workflow (deterministic, no shell execution).
2) Replace allowed commands with a single wrapper script (e.g. `./scripts/triage-add-label.sh`) that:
  - accepts only (item_type, item_number, label)
  - validates `label` is in the known label list
  - runs `gh issue/pr edit ... --add-label ...`
  Then allowlist ONLY that wrapper script.
3) Extend the command-approval mechanism to support strict patterns/structured output so that only `--add-label` operations can be auto-approved (argument-level validation, not prefix-level).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. openRouterBaseUrl misnamed here 📘 Rule violation ✓ Correctness
Description
The ZenMux fetcher uses options?.openRouterBaseUrl to build the ZenMux endpoint, which is
misleading naming and can cause confusion or incorrect configuration. This harms self-documentation
and makes the intent of the option unclear.
Code

src/api/providers/fetchers/zenmux.ts[37]

+	const baseURL = options?.openRouterBaseUrl || "https://zenmux.ai/api/v1"
Evidence
Compliance ID 2 requires identifiers to clearly express purpose and avoid misleading names. The code
selects the ZenMux base URL using an option named for a different provider (openRouterBaseUrl),
which is not self-documenting and suggests the wrong configuration source.

Rule 2: Generic: Meaningful Naming and Self-Documenting Code
src/api/providers/fetchers/zenmux.ts[37-37]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
ZenMux model fetching uses `options?.openRouterBaseUrl`, which is misleading and undermines self-documenting code.

## Issue Context
This code is specifically fetching ZenMux models (`/models` on ZenMux), so the option name should communicate ZenMux intent (or a provider-agnostic name if shared).

## Fix Focus Areas
- src/api/providers/fetchers/zenmux.ts[37-37]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

): Promise<Record<string, ModelInfo>> {
const models: Record<string, ModelInfo> = {}
const baseURL = "https://zenmux.ai/api/v1"
const baseURL = options?.openRouterBaseUrl || "https://zenmux.ai/api/v1"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. zenmux.ts changes lack markers 📘 Rule violation ⛯ Reliability

Changes were made to an upstream-shared file under src/ without being wrapped in kilocode_change
markers, increasing the risk of upstream sync merge conflicts. Only a subset of the modifications in
the file are annotated.
Agent Prompt
## Issue description
Updates to an upstream-shared file under `src/` were introduced without `kilocode_change` markers around the modified sections, which can increase merge conflicts during upstream sync.

## Issue Context
Rule requires Kilo-specific modifications in upstream-shared code to be annotated with `kilocode_change` markers.

## Fix Focus Areas
- src/api/providers/fetchers/zenmux.ts[15-17]
- src/api/providers/fetchers/zenmux.ts[37-37]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +40 to +74
KILO_AUTO_APPROVAL_ENABLED: "true"
KILO_AUTO_APPROVAL_EXECUTE_ENABLED: "true"
KILO_AUTO_APPROVAL_EXECUTE_ALLOWED: "gh issue edit,gh pr edit"
KILO_AUTO_APPROVAL_EXECUTE_DENIED: "gh issue close,gh issue delete,gh issue transfer,gh issue lock,gh issue unlock,gh pr close,gh pr merge,gh repo,gh auth,gh secret,gh variable,rm,sudo,curl,wget,bash,sh,python,node,npm,npx"
KILO_TELEMETRY: "false"
# Determine event type and extract data
EVENT_TYPE: ${{ github.event_name }}
ITEM_NUMBER: ${{ github.event_name == 'issues' && github.event.issue.number || github.event.pull_request.number }}
ITEM_TITLE: ${{ github.event_name == 'issues' && github.event.issue.title || github.event.pull_request.title }}
ITEM_BODY: ${{ github.event_name == 'issues' && github.event.issue.body || github.event.pull_request.body }}
run: |
# Sanitize body - remove shell metacharacters
SAFE_BODY=$(echo "$ITEM_BODY" | head -c 2000 | tr -d '`$(){}[]|;&<>\\' | tr '\n' ' ')

# Determine gh command based on event type
if [ "$EVENT_TYPE" = "issues" ]; then
GH_CMD="gh issue edit"
ITEM_TYPE="issue"
else
GH_CMD="gh pr edit"
ITEM_TYPE="pull request"
fi

kilocode --auto "Triage this GitHub ${ITEM_TYPE}:

Number: ${ITEM_NUMBER}
Title: ${ITEM_TITLE}
Body: ${SAFE_BODY}

## Your Task
Add appropriate labels to this ${ITEM_TYPE}.

## Command Format
Use ONLY: ${GH_CMD} ${ITEM_NUMBER} --add-label \"<label>\"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Llm can over-edit via gh 🐞 Bug ⛨ Security

The auto-triage workflow enables LLM-driven command execution and allowlists gh issue edit / `gh
pr edit`, but the CLI approval logic uses prefix matching—so these allowlist entries permit
arbitrary edits (title/body/etc.), not just label adds. Because issue/PR title/body is untrusted
user input, prompt injection can cause unintended repository actions within the granted permissions.
Agent Prompt
### Issue description
The workflow enables auto-execution of LLM-produced shell commands and allowlists `gh issue edit` / `gh pr edit`. The CLI allowlist matcher is prefix-based, so any `gh issue edit ...` command (including changing title/body) will be auto-approved. This is vulnerable to prompt injection from untrusted issue/PR content.

### Issue Context
The workflow’s prompt instructs “labels only”, but enforcement is not technical—only prompt-based. The approval layer is prefix-based, not argument-constrained.

### Fix Focus Areas
- .github/workflows/auto-triage.yml[33-74]
- cli/src/services/approvalDecision.ts[28-59]
- cli/src/services/approvalDecision.ts[171-236]

### Expected fix
Choose one:
1) Disable execute auto-approval in this workflow and implement labeling via GitHub API directly in the workflow (deterministic, no shell execution).
2) Replace allowed commands with a single wrapper script (e.g. `./scripts/triage-add-label.sh`) that:
   - accepts only (item_type, item_number, label)
   - validates `label` is in the known label list
   - runs `gh issue/pr edit ... --add-label ...`
   Then allowlist ONLY that wrapper script.
3) Extend the command-approval mechanism to support strict patterns/structured output so that only `--add-label` operations can be auto-approved (argument-level validation, not prefix-level).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@jeremylongshore jeremylongshore deleted the mirror/PR-5831 branch February 15, 2026 03:12
@jeremylongshore
Copy link
Copy Markdown
Owner Author

Review: kilocode Kilo-Org#5831

Fix ZenMux model metadata and native tool message handling by @Neonsy

Methodology

Checklist

Check Result Notes
Correctness PASS Fixes real bug: stale cache with contextWindow=0 caused condensing loops; native tool passthrough was broken
Conventions PASS Uses kilocode_change markers correctly throughout
Changeset PASS Two changesets: context window fix + native tools reliability
Tests PASS 288 new test lines across 3 test files covering all fix paths
i18n N/A No user-facing strings
Types PASS Default model info updated with native tool fields
Security PASS No security surface changes
Scope PASS Tightly scoped to ZenMux provider and its cache layer

Findings

1. NATIVE_TOOL_DEFAULTS spread ordering in getModel (severity: gray)

let info = { ...NATIVE_TOOL_DEFAULTS, ...(this.models[id] ?? zenmuxDefaultModelInfo) }

Since NATIVE_TOOL_DEFAULTS is spread first, any cached model that explicitly sets supportsNativeTools: false would correctly override the defaults. However, models from the cache that simply omit these fields would not get the defaults merged -- they would be undefined. This is actually the correct behavior since the spread of zenmuxDefaultModelInfo already includes the new fields. No issue, just noting the ordering is intentional.

2. createZenMuxStream signature change is well-handled (severity: gray)

The method signature changes from (client, systemPrompt, messages, ...) to (client, openAiMessages, ...). The caller now passes pre-transformed OpenAI messages instead of raw Anthropic messages, which preserves DeepSeek R1 transforms and other message-level mutations. This is the core fix for the "tool not used" retry loops.

3. Stale cache self-healing is ZenMux-specific (severity: gray)

The hasInvalidZenmuxContextWindow check in modelCache.ts only applies to the zenmux provider. This is appropriate since the bug was specific to ZenMux v5.7.0 cache entries. The function correctly checks (model.contextWindow ?? 0) <= 0 to catch both 0 and missing values.

4. Tool protocol lock respected via metadata.toolProtocol (severity: gray)

The PR passes metadata?.toolProtocol as the third argument to resolveToolProtocol(), which the Kilo fork added to respect task-locked protocols. This ensures resumed tasks keep their original tool protocol setting. Good attention to the fork's specific extension.

CI Status

Check Result
compile PASS
test-extension (ubuntu) PASS
test-extension (windows) PASS
test-webview (ubuntu) PASS
test-webview (windows) PASS
test-cli PASS
test-jetbrains PASS
build-cli PASS
check-translations PASS

Code Snippets

Core fix -- using pre-transformed messages for stream creation:

// Before: rebuilt messages from raw, losing transforms
const openAiMessages: OpenAI.Chat.ChatCompletionMessageParam[] = [
    { role: "system", content: systemPrompt },
    ...convertToOpenAiMessages(messages),
]

// After: uses already-transformed openAiMessages passed from caller
async createZenMuxStream(
    client: OpenAI,
    openAiMessages: OpenAI.Chat.ChatCompletionMessageParam[],
    model: { id: string; info: ModelInfo },
    ...
)

Stale cache self-healing:

function hasInvalidZenmuxContextWindow(models: ModelRecord): boolean {
    return Object.values(models).some((model) => (model.contextWindow ?? 0) <= 0)
}

Verdict

APPROVE -- This is a well-structured fix for two related ZenMux reliability issues. The context window cache hardening prevents erroneous condensing loops from stale v5.7.0 cache entries. The message pipeline refactor preserves transforms (especially for DeepSeek R1) and correctly gates native tool parameters based on the task-locked protocol. All CI checks pass. The test coverage is targeted and regression-focused. Community user testing on Discord confirms the fix resolves the reported "tool not used" retry loops.

@jeremylongshore
Copy link
Copy Markdown
Owner Author

Review Journal: kilocode Kilo-Org#5831

PR: #5831 |
Title: Fix ZenMux model metadata and native tool message handling |
Author: @Neonsy |
Category: feature | Tier: 5 | Size: 387 lines, 9 files


Summary

Fixes two related ZenMux provider bugs: (1) stale model cache with contextWindow=0 caused infinite condensing loops, and (2) native tool calling was broken because message transforms were being rebuilt instead of passed through. Well-tested fix with Discord user validation. Approve.

First Impressions

Two changesets signal this is a combined fix. The PR description is thorough with clear problem statement, implementation details, and test instructions. The author (Neonsy) is a repeat contributor with good pattern awareness.

What I Looked At

  • src/api/providers/zenmux.ts -- handler changes (message pipeline refactor, tool protocol gating)
  • packages/types/src/providers/zenmux.ts -- default model info additions
  • src/api/providers/fetchers/zenmux.ts -- fetcher enhancements (context_length mapping, native tool metadata)
  • src/api/providers/fetchers/modelCache.ts -- stale cache self-healing
  • src/api/providers/__tests__/zenmux-native-tools.spec.ts -- new test file (175 lines)
  • src/api/providers/fetchers/__tests__/zenmux.spec.ts -- new fetcher tests (70 lines)
  • src/api/providers/fetchers/__tests__/modelCache.spec.ts -- cache validation tests (43 lines)
  • Cross-referenced resolveToolProtocol signature to verify 3-arg form
  • Cross-referenced NATIVE_TOOL_DEFAULTS from @roo-code/types

Analysis

The root cause analysis is sound:

  1. Context window bug: ZenMux fetcher was setting contextWindow: 0 for models where the API response lacked a context_length field. This triggered the extension's context condensation logic repeatedly. Fix: map context_length from API response, fall back to the default (200K) when missing.

  2. Tool calling bug: createZenMuxStream was rebuilding messages from raw Anthropic format, which lost DeepSeek R1 system-to-user transforms and other protocol-specific mutations. The stream then sent malformed messages, causing "tool not used" retry loops. Fix: pass the already-transformed openAiMessages to the stream method.

The tool protocol gating is done correctly:

const tools = isNativeProtocol ? metadata?.tools : undefined
const toolChoice = isNativeProtocol ? metadata?.tool_choice : undefined
const parallelToolCalls = isNativeProtocol ? (metadata?.parallelToolCalls ?? false) : false

This ensures XML-mode tasks never send native tool parameters.

Verification

  • All 11 CI checks pass
  • Discord user tested with GLM 5.0, Sonnet 4.5, and Minimax 2.5
  • Flaky test failure reported by author is unrelated (known issue)

Lessons Learned

  • Provider message pipelines need to be careful about where transforms happen -- rebuilding from raw messages can lose important mutations
  • Model cache self-healing is a good pattern for handling schema evolution (v5.7.0 cache entries with missing fields)
  • The kilocode_change markers are used correctly and consistently throughout

Review methodology: AI PR Review Case Studies | Reviewed with GWI + Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant