Skip to content

feat(agents): add per-agent step limits - #1815

Merged
kevincodex1 merged 6 commits into
Twigpine:mainfrom
chioarub:feat/agent-step-limits
Jun 30, 2026
Merged

kevincodex1 merged 6 commits into
Twigpine:mainfrom
chioarub:feat/agent-step-limits

Conversation

@chioarub

@chioarub chioarub commented Jun 29, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Add optional per-agent maxSteps configuration so subagents can be capped by tool-use steps.
  • When a capped subagent reaches its limit, further tool calls are blocked and the agent is forced into a concise final summary covering completed work, findings, remaining tasks, and whether another run is needed.

Implementation

  • Parses maxSteps from markdown, JSON, plugin, and SDK agent definitions with positive-integer validation.
  • Tracks executed tool steps across query turns and blocks over-limit tool calls with internally marked synthetic tool results.
  • Preserves prior tool-result normalization while disabling advertised tools for the forced summary turn.
  • Propagates the agent_step_limit terminal reason through subagent execution and debug logging.

Tests

  • bun test src/query/agentStepLimit.test.ts src/query/toolFailureLoopGuard.test.ts src/tools/AgentTool/**/*.test.ts src/utils/plugins/loadPluginAgents.test.ts
  • bun run typecheck
  • bun run typecheck:type-tests
  • bun run build
  • bun run smoke
  • bun run security:pr-scan
  • git diff --check
  • bun run check was also run locally; it failed in full-suite mode with order-dependent failures, and the failed groups passed when rerun in isolation with --feature=UNATTENDED_RETRY --max-concurrency=1.

Risk

  • No linked issue. This is a focused feature PR, but the contribution guide recommends opening an issue before feature work.
  • Default behavior is unchanged unless an agent definition opts into maxSteps.
  • Step-limited agents use non-streaming tool execution so the query loop can count and block tool calls precisely.

Summary by CodeRabbit

  • New Features
    • Added per-agent “step limits” via maxSteps, limiting tool-use steps and triggering forced concise summaries when reached.
    • Extended SDK agent configuration (including V2/per-session) to accept maxSteps, with UI display/grouping for SDK agents.
    • API option now supports messageNormalizationTools override for message/tool normalization control.
  • Bug Fixes
    • Invalid/zero/malformed maxSteps are ignored (default unlimited behavior preserved).
    • Improved agent injection failure visibility and earlier surfacing of injection agent_load_failure events.
  • Documentation
    • Documented “Agent step limits” behavior and examples.
  • Tests
    • Added unit and end-to-end coverage for maxSteps, forced-summary behavior, streaming semantics, and injection/MCP filtering cases.

Add maxSteps agent configuration for markdown, JSON, plugin, and SDK agent definitions. Enforce the limit in subagent query execution by blocking over-limit tool calls, preserving a no-tool summary turn, and recording an agent_step_limit terminal reason. Add focused coverage for default behavior, invalid values, multi-turn accumulation, plugin parsing, failure-loop interaction, and summary-tool blocking.
@coderabbitai

coderabbitai Bot commented Jun 29, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 565f0999-7072-494b-a9be-82730ae15913

📥 Commits

Reviewing files that changed from the base of the PR and between 0f1ebe1 and f7c3d81.

📒 Files selected for processing (4)
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • tests/sdk/query-happy-path.test.ts
  • tests/sdk/sdk-v2-lifecycle.test.ts
💤 Files with no reviewable changes (1)
  • src/entrypoints/sdk/agentDefinitions.ts
📜 Recent review details
⚠️ CI failures not shown inline (2)

GitHub Actions: PR Checks / smoke-and-tests: feat(agents): add per-agent step limits

Conclusion: failure

View job details

mMemorySync/watcher.test.ts:
 (pass) rescheduleCount behavior > increments while push in flight and resets after cap via onDebounceFire [1.00ms]
 (pass) rescheduleCount behavior > clears pushInProgress when executePush completes [2.00ms]
 (pass) rescheduleCount behavior > skips the capped follow-up push when suppression is set mid-flight [1.00ms]
 (pass) rescheduleCount behavior > capped reschedule chains follow-up push after in-flight push completes [2.00ms]
 (pass) rescheduleCount behavior > does not queue multiple duplicate follow-up pushes when one is already queued [5.00ms]
 (pass) executePush identity safety > clears currentPushPromise when it was set to the executing promise [1.00ms]
 (pass) executePush identity safety > preserves currentPushPromise when replaced during yield point [1.00ms]
 ##[endgroup]
 ##[group]src/services/tips/tipLink.test.ts:
 (pass) renderSponsorLink > hyperlinks supported: name is an OSC 8 link, no trailing raw url
 (pass) renderSponsorLink > hyperlinks NOT supported: plain name + dimmed url trailing
 (pass) renderSponsorLink > no url → plain name, nothing trailing (either branch)
 (pass) renderSponsorLink > strips control chars from the advertiser name (no escape injection)
 (pass) renderSponsorLink > rejects non-http(s) URLs (javascript:/file:) → no link
 (pass) renderSponsorLink > strips control chars from the url before validating it
 (pass) renderSponsorLink > a malicious url cannot inject extra escape sequences into the output [1.00ms]
 ##[endgroup]
 ##[group]src/services/tips/gitlawbEarn.test.ts:
 (pass) gitlawb earning tips > disabled by default (no ads config)
 (pass) gitlawb earning tips > enabled once /ads on set enabled + earnCode
 (pass) gitlawb earning tips > cadence: every 2nd eligible slot by default
 (pass) gitlawb earning tips > OPENCLAUDE_ADS_TIP_EVERY=1 shows every turn
 (pass) gitlawb earning tips > disabled → never shows and never increments the counter
 (pass) gitlawb earning tips > content falls back to a st...

GitHub Actions: PR Checks / 2_smoke-and-tests.txt: feat(agents): add per-agent step limits

Conclusion: failure

View job details

rovider flag ignores blank OPENGATEWAY_API_KEY and uses OPENAI_API_KEY fallback [6.00ms]
 (pass) gitlawb opengateway provider flag sends OPENGATEWAY_API_KEY to OPENGATEWAY_BASE_URL override [1.00ms]
 (pass) gitlawb opengateway provider flag sends OPENGATEWAY_API_KEY to custom OPENAI_BASE_URL fallback [2.00ms]
 (pass) gitlawb opengateway provider flag prefers OPENGATEWAY_API_KEY over generic OPENAI_API_KEY for custom base URL [1.00ms]
 (pass) gitlawb opengateway provider flag prefers OPENGATEWAY_API_KEY over generic OPENAI_API_KEYS pool [2.00ms]
 (pass) gitlawb opengateway provider flag uses generic OPENAI_API_KEYS pool before generic OPENAI_API_KEY fallback [1.00ms]
 (pass) gitlawb opengateway stored provider profile key becomes bearer auth [3.00ms]
 (pass) openai route still sends OPENAI_API_KEY as bearer auth [4.00ms]
 (pass) OPENAI_API_KEYS rejects placeholder values before sending requests [5.00ms]
 (pass) OPENAI_API_KEYS rotates to the next key on rate-limit failure [9.00ms]
 (pass) comma-separated OPENAI_API_KEY rotates to the next key on rate-limit failure [4.00ms]
 (pass) OPENAI_API_KEYS does not rotate through pool on provider 5xx outage [3.00ms]
 (pass) OPENAI_API_KEYS preserves cooldown state across client requests [7.00ms]
 (pass) OPENAI_API_KEYS rotates Azure api-key auth on auth failure [4.00ms]
 (pass) OPENAI_API_KEYS does not reuse auth-disabled credentials across client requests [7.00ms]
 (pass) OPENAI_API_KEYS permanently evicts 403 auth failures [11.00ms]
 (pass) does not use BNKR_API_KEY for non-Bankr OpenAI-compatible routes [2.00ms]
 (pass) preserves Gemini tool call extra_content from streaming chunks [2.00ms]
 (pass) preserves Gemini thought signature from streaming delta extra_content [1.00ms]
 (pass) preserves Gemini thought signature from non-streaming message extra_content [2.00ms]
 (pass) converts Gemini raw tool-call text into streaming tool_use blocks [2.00ms]
 (pass) converts Gemini raw tool-call text into non-streaming tool_use bl...
🧰 Additional context used
📓 Path-based instructions (13)
**/*.{ts,tsx,js,jsx,py,json,md}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Follow the existing code style in the touched files

Files:

  • tests/sdk/sdk-v2-lifecycle.test.ts
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/query-happy-path.test.ts
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Add or update tests when the change affects behavior

Files:

  • tests/sdk/sdk-v2-lifecycle.test.ts
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/query-happy-path.test.ts
**/*.test.{ts,tsx,js}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Test the exact provider/model path you changed when possible

Files:

  • tests/sdk/sdk-v2-lifecycle.test.ts
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/query-happy-path.test.ts
**/*.{ts,tsx,js,jsx,py}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Keep comments useful and concise

Files:

  • tests/sdk/sdk-v2-lifecycle.test.ts
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/query-happy-path.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Follow TypeScript strict mode and type safety practices by running typecheck before submitting

Files:

  • tests/sdk/sdk-v2-lifecycle.test.ts
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/query-happy-path.test.ts
**

⚙️ CodeRabbit configuration file

**: # AGENTS.md - AI Agent Coding Guide

This guide is for AI coding agents working in the OpenClaude repository. Read it before changing code, and also follow CONTRIBUTING.md for contributor policy, PR expectations, review follow-up, and project scope.

Project Snapshot

OpenClaude is a coding-agent CLI for cloud and local model providers. It supports OpenAI-compatible APIs, Anthropic, Gemini, DeepSeek, Ollama, MCP, local backends, slash commands, tools, agents, and a React/Ink terminal UI.

The installed CLI runs on Node.js >=22.0.0. Bun is used for source builds, scripts, dependency management, and tests.

Work Style

  • Keep changes focused on one problem.
  • Prefer existing patterns in the file or nearby module.
  • Avoid unrelated formatting, renames, dependency changes, or broad rewrites.
  • Add or update tests when behavior changes.
  • Update docs when setup, commands, provider behavior, or user-facing behavior changes.
  • For new features, larger refactors, dependencies, or runtime changes, follow the issue-first guidance in CONTRIBUTING.md.

Stack And Conventions

  • TypeScript with strict mode and ESM imports.
  • React + Ink for terminal UI.
  • Bun lockfile and Bun scripts for development workflows.
  • Node runtime for the built CLI.
  • Python exists for legacy/local-provider helper code. Do not add new Python code or expand Python-based features unless a maintainer explicitly approves that direction.

Common libraries and patterns:

  • chalk for terminal color.
  • commander for CLI argument parsing.
  • execa for child processes.
  • Existing service, provider, settings, permission, and UI patterns over new abstractions.

Repository Map

  • src/commands/ - slash and CLI command implementations.
  • src/components/ - React/Ink UI components.
  • src/services/ - API, MCP, OAuth, wiki, voice, and other service integrations.
  • src/tools/ - tool implementations.
  • src/utils/ - shared utilities.
  • `src/integration...

Files:

  • tests/sdk/sdk-v2-lifecycle.test.ts
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/query-happy-path.test.ts
**/*

⚙️ CodeRabbit configuration file

**/*: Apply the OpenClaude maintainer review rubric from AGENTS.md. Review the current diff, not stale discussion context. Separate real blockers from suggestions. Do not request changes for vague style churn. Treat approval as merge-ready from CodeRabbit's side, pending required human review and GitHub Checks. If checks are failing or unavailable, say so clearly instead of implying the PR is fully ready.

Files:

  • tests/sdk/sdk-v2-lifecycle.test.ts
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/query-happy-path.test.ts
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}

⚙️ CodeRabbit configuration file

{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}: Review tests for meaningful coverage of the changed behavior, isolation of global/env/config state, async cleanup, fake timers, provider profile leaks, and Windows-compatible assumptions. Block when risky runtime changes lack focused regression coverage or tests assert implementation details while missing the user-visible behavior.

Files:

  • tests/sdk/sdk-v2-lifecycle.test.ts
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/query-happy-path.test.ts
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript with strict mode and ESM imports

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use chalk for terminal color in CLI code

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
{src/commands/**/*.ts,src/entrypoints/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use commander for CLI argument parsing

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
src/{components/permissions,utils/permissions,hooks/toolPermission,tools,entrypoints/sdk}/**

⚙️ CodeRabbit configuration file

src/{components/permissions,utils/permissions,hooks/toolPermission,tools,entrypoints/sdk}/**: Review permission prompts, auto-allow logic, sandbox behavior, SDK permission schemas, shell/PowerShell execution, and background execution paths as security-sensitive. Block on bypasses, unclear trust boundaries, unsafe path handling, missing user visibility, or changes that broaden allowed behavior without an explicit maintainer decision.

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}

⚙️ CodeRabbit configuration file

{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}: Review install, launcher, build, packaging, startup, and entrypoint changes for cross-platform compatibility, tracked-source rewrites, env/config precedence, and release safety. Block on changes that can break Windows/macOS/Linux startup or publish unexpected artifacts.

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
🔇 Additional comments (3)
src/entrypoints/sdk/agentDefinitions.test.ts (1)

9-9: LGTM!

Also applies to: 94-115

tests/sdk/sdk-v2-lifecycle.test.ts (1)

528-532: LGTM!

Also applies to: 547-572

tests/sdk/query-happy-path.test.ts (1)

149-153: LGTM!

Also applies to: 169-189


📝 Walkthrough

Walkthrough

Adds maxSteps support for agents across SDK, loaders, and the query loop, then enforces the limit by blocking extra tool calls and returning reason: 'agent_step_limit' with step counts and a final summary phase.

Changes

Agent Step Limits and SDK Agents

Layer / File(s) Summary
Contracts and markers
src/query/agentStepLimit.ts, src/query/transitions.ts, src/types/message.ts, src/query/toolFailureLoopGuard.ts, src/utils/messages.ts, src/services/api/claude.ts, src/query/toolFailureLoopGuard.test.ts
Adds the step-limit terminal reason, message metadata, synthetic tool-result marker, API normalization override, and failure-guard handling for marked results.
SDK types and agent loading
src/utils/frontmatterParser.ts, src/entrypoints/sdk/coreSchemas.ts, src/entrypoints/sdk.d.ts, README.md, src/tools/AgentTool/loadAgentsDir.ts, src/utils/plugins/loadPluginAgents.ts, src/tools/AgentTool/loadAgentsDir.test.ts, src/utils/plugins/loadPluginAgents.test.ts, tests/sdk/package-consumer-types.test.ts
Adds maxSteps to SDK types, schemas, frontmatter parsing, JSON parsing, plugin agent loading, README guidance, and related tests.
SDK agent injection
src/entrypoints/sdk/agentDefinitions.ts, src/entrypoints/sdk/query.ts, src/entrypoints/sdk/v2.ts, src/entrypoints/sdk/agentDefinitions.test.ts, tests/sdk/query-happy-path.test.ts, tests/sdk/sdk-v2-lifecycle.test.ts
Adds SDK agent definition builders and merges, injects SDK agents during query/session startup, and drains injection failures before prompts.
Query loop enforcement
src/query.ts, src/query/agentStepLimit.test.ts
Tracks agentStepLimit through the query loop, blocks excess tool calls, emits synthetic tool results, requests summary turns, and returns reason: 'agent_step_limit'.
Run-agent wiring and counting
src/tools/AgentTool/agentToolUtils.ts, src/tools/AgentTool/runAgent.ts
Adds maxSteps to runAgent, forwards it into query(), captures the terminal result, and excludes marked step-limit tool uses from counting.
SDK source UI
src/components/ContextVisualization.tsx, src/components/agents/AgentsList.tsx, src/components/agents/types.ts, src/components/agents/utils.ts, src/components/agents/AgentsMenu.tsx, src/components/agents/agentFileUtils.ts, src/utils/analyzeContext.ts, src/utils/settings/constants.ts, src/tools/AgentTool/agentDisplay.ts, src/components/agents/AgentsMenu.test.tsx
Adds the sdk source across agent grouping, display helpers, file-path handling, and agent list/menu visibility rules.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Suggested reviewers

  • jatmn
  • kevincodex1
🚥 Pre-merge checks | ✅ 6 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.79% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (6 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately describes the main change: per-agent step limits.
Description check ✅ Passed The description covers summary, implementation, tests, and risk, though it omits the template's Impact and Notes sections.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Risk Surface Disclosed ✅ Passed PR touches SDK/plugin/MCP paths, and its Risk section says defaults are unchanged and no blocker is introduced.
No Hidden Policy Change ✅ Passed Policy-adjacent changes (maxSteps enforcement, SDK agent precedence, MCP/tool-pool handling) are directly part of the feature and documented; no hidden unrelated policy toggle found.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/entrypoints/sdk/query.ts (1)

545-564: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Validate SDK agents[*].maxSteps before injecting it.

This path copies def.maxSteps straight into injectAgents() with only a truthiness check, so SDK callers can still pass invalid values like -1, 1.5, or '2' at runtime. That breaks the positive-integer contract you added for markdown/JSON/plugin agents and makes SDK-defined agents behave differently from every other agent source.

Suggested fix
+import { AgentDefinitionSchema } from './coreSchemas.js'
+
           if (self.userAgents && Object.keys(self.userAgents).length > 0) {
-            const userAgents: Array<{
-              agentType: string
-              whenToUse: string
-              getSystemPrompt: () => string
-              tools?: string[]
-              disallowedTools?: string[]
-              model?: string
-              maxTurns?: number
-              maxSteps?: number
-            }> = Object.entries(self.userAgents).map(([name, def]) => ({
-              agentType: name,
-              whenToUse: def.description ?? name,
-              getSystemPrompt: () => def.prompt ?? '',
-              ...(def.tools ? { tools: def.tools } : {}),
-              ...(def.disallowedTools ? { disallowedTools: def.disallowedTools } : {}),
-              ...(def.model ? { model: def.model } : {}),
-              ...(def.maxTurns ? { maxTurns: def.maxTurns } : {}),
-              ...(def.maxSteps ? { maxSteps: def.maxSteps } : {}),
-            }))
+            const userAgents = Object.entries(self.userAgents).flatMap(([name, def]) => {
+              const parsed = AgentDefinitionSchema().safeParse(def)
+              if (!parsed.success) {
+                self.pushAgentFailure({
+                  type: 'agent_load_failure',
+                  stage: 'injection',
+                  error_message: `Invalid SDK agent '${name}': ${parsed.error.message}`,
+                })
+                return []
+              }
+
+              return [{
+                agentType: name,
+                whenToUse: parsed.data.description,
+                getSystemPrompt: () => parsed.data.prompt,
+                ...(parsed.data.tools ? { tools: parsed.data.tools } : {}),
+                ...(parsed.data.disallowedTools ? { disallowedTools: parsed.data.disallowedTools } : {}),
+                ...(parsed.data.model ? { model: parsed.data.model } : {}),
+                ...(parsed.data.maxTurns !== undefined ? { maxTurns: parsed.data.maxTurns } : {}),
+                ...(parsed.data.maxSteps !== undefined ? { maxSteps: parsed.data.maxSteps } : {}),
+              }]
+            })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/entrypoints/sdk/query.ts` around lines 545 - 564, The SDK agent mapping
in query.ts is passing def.maxSteps directly into injectAgents() without
validating it, so invalid values can slip through. Update the
userAgents-to-agent conversion in the self.userAgents branch to validate
maxSteps the same way as other agent sources, ensuring it is a positive integer
before including it. Keep the fix localized to the
Object.entries(self.userAgents).map(...) logic and the agent shape used by
injectAgents().
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@README.md`:
- Around line 280-293: Clarify the `maxSteps` docs in the agent configuration
section: `maxSteps` must be a positive integer, and invalid values like `0` or
malformed input are ignored and fall back to the default behavior. Update the
explanation near the `maxSteps` field in the `bounded-researcher` example to
reflect the actual validation behavior so users know only positive integers cap
tool-use steps.

In `@src/query.ts`:
- Around line 2029-2035: The forced-summary path in query.ts is returning too
early from the agent-step termination branch, which prevents the final summary
from ever being produced. Update the logic around
shouldTerminateAgentStepSummary and nextAgentStepLimit so that when
summaryRequested is already true and tool_use is still emitted, the loop stays
alive for one more summary-only turn or synthesizes the final summary instead of
exiting immediately. Keep the fix localized to the summary/termination flow in
the query loop and preserve the existing agent step limit handling for
non-summary cases.

In `@src/query/agentStepLimit.test.ts`:
- Around line 266-270: The agent step limit tests currently only assert the
returned reason, so regressions in the terminal payload fields can slip through.
Update the affected cases in agentStepLimit.test.ts to also assert the full
`agent_step_limit` payload with `toMatchObject(...)`, covering fields like
`turnCount`, `stepsUsed`, and `maxSteps` on the returned result. Use the
existing terminal result assertions around `returned` to locate the right spots
and add at least one focused payload check in each risky scenario.

In `@src/tools/AgentTool/loadAgentsDir.test.ts`:
- Around line 206-225: The duplicate-name merge in
getAgentDefinitionsWithOverrides is still prioritizing the user-scoped agent
over the project-scoped one, so update the precedence logic in loadAgentsDir to
ensure projectSettings entries win when agentType matches. Check the code path
that combines loaded agent definitions and resolves conflicts, and make sure the
project agent’s maxSteps and source are preserved instead of being overwritten
by the user agent.

---

Outside diff comments:
In `@src/entrypoints/sdk/query.ts`:
- Around line 545-564: The SDK agent mapping in query.ts is passing def.maxSteps
directly into injectAgents() without validating it, so invalid values can slip
through. Update the userAgents-to-agent conversion in the self.userAgents branch
to validate maxSteps the same way as other agent sources, ensuring it is a
positive integer before including it. Keep the fix localized to the
Object.entries(self.userAgents).map(...) logic and the agent shape used by
injectAgents().
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 06066b1d-e33e-4274-b341-6ddf10dd80be

📥 Commits

Reviewing files that changed from the base of the PR and between 9bf6aa2 and 4ad1039.

⛔ Files ignored due to path filters (1)
  • src/entrypoints/sdk/coreTypes.generated.ts is excluded by !src/entrypoints/sdk/coreTypes.generated.ts
📒 Files selected for processing (20)
  • README.md
  • src/entrypoints/sdk.d.ts
  • src/entrypoints/sdk/coreSchemas.ts
  • src/entrypoints/sdk/query.ts
  • src/query.ts
  • src/query/agentStepLimit.test.ts
  • src/query/agentStepLimit.ts
  • src/query/toolFailureLoopGuard.test.ts
  • src/query/toolFailureLoopGuard.ts
  • src/query/transitions.ts
  • src/services/api/claude.ts
  • src/tools/AgentTool/agentToolUtils.ts
  • src/tools/AgentTool/loadAgentsDir.test.ts
  • src/tools/AgentTool/loadAgentsDir.ts
  • src/tools/AgentTool/runAgent.ts
  • src/types/message.ts
  • src/utils/frontmatterParser.ts
  • src/utils/messages.ts
  • src/utils/plugins/loadPluginAgents.test.ts
  • src/utils/plugins/loadPluginAgents.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (18)
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript with strict mode and ESM imports

Files:

  • src/query/agentStepLimit.ts
  • src/types/message.ts
  • src/utils/plugins/loadPluginAgents.ts
  • src/utils/plugins/loadPluginAgents.test.ts
  • src/tools/AgentTool/loadAgentsDir.test.ts
  • src/entrypoints/sdk.d.ts
  • src/tools/AgentTool/agentToolUtils.ts
  • src/utils/frontmatterParser.ts
  • src/utils/messages.ts
  • src/services/api/claude.ts
  • src/entrypoints/sdk/query.ts
  • src/query/transitions.ts
  • src/query/toolFailureLoopGuard.test.ts
  • src/tools/AgentTool/loadAgentsDir.ts
  • src/query/toolFailureLoopGuard.ts
  • src/query/agentStepLimit.test.ts
  • src/tools/AgentTool/runAgent.ts
  • src/entrypoints/sdk/coreSchemas.ts
  • src/query.ts
**/*.{ts,tsx,js,jsx,py,json,md}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Follow the existing code style in the touched files

Files:

  • src/query/agentStepLimit.ts
  • src/types/message.ts
  • README.md
  • src/utils/plugins/loadPluginAgents.ts
  • src/utils/plugins/loadPluginAgents.test.ts
  • src/tools/AgentTool/loadAgentsDir.test.ts
  • src/entrypoints/sdk.d.ts
  • src/tools/AgentTool/agentToolUtils.ts
  • src/utils/frontmatterParser.ts
  • src/utils/messages.ts
  • src/services/api/claude.ts
  • src/entrypoints/sdk/query.ts
  • src/query/transitions.ts
  • src/query/toolFailureLoopGuard.test.ts
  • src/tools/AgentTool/loadAgentsDir.ts
  • src/query/toolFailureLoopGuard.ts
  • src/query/agentStepLimit.test.ts
  • src/tools/AgentTool/runAgent.ts
  • src/entrypoints/sdk/coreSchemas.ts
  • src/query.ts
**/*.{ts,tsx,js,jsx,py}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Keep comments useful and concise

Files:

  • src/query/agentStepLimit.ts
  • src/types/message.ts
  • src/utils/plugins/loadPluginAgents.ts
  • src/utils/plugins/loadPluginAgents.test.ts
  • src/tools/AgentTool/loadAgentsDir.test.ts
  • src/entrypoints/sdk.d.ts
  • src/tools/AgentTool/agentToolUtils.ts
  • src/utils/frontmatterParser.ts
  • src/utils/messages.ts
  • src/services/api/claude.ts
  • src/entrypoints/sdk/query.ts
  • src/query/transitions.ts
  • src/query/toolFailureLoopGuard.test.ts
  • src/tools/AgentTool/loadAgentsDir.ts
  • src/query/toolFailureLoopGuard.ts
  • src/query/agentStepLimit.test.ts
  • src/tools/AgentTool/runAgent.ts
  • src/entrypoints/sdk/coreSchemas.ts
  • src/query.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Follow TypeScript strict mode and type safety practices by running typecheck before submitting

Files:

  • src/query/agentStepLimit.ts
  • src/types/message.ts
  • src/utils/plugins/loadPluginAgents.ts
  • src/utils/plugins/loadPluginAgents.test.ts
  • src/tools/AgentTool/loadAgentsDir.test.ts
  • src/entrypoints/sdk.d.ts
  • src/tools/AgentTool/agentToolUtils.ts
  • src/utils/frontmatterParser.ts
  • src/utils/messages.ts
  • src/services/api/claude.ts
  • src/entrypoints/sdk/query.ts
  • src/query/transitions.ts
  • src/query/toolFailureLoopGuard.test.ts
  • src/tools/AgentTool/loadAgentsDir.ts
  • src/query/toolFailureLoopGuard.ts
  • src/query/agentStepLimit.test.ts
  • src/tools/AgentTool/runAgent.ts
  • src/entrypoints/sdk/coreSchemas.ts
  • src/query.ts
**

⚙️ CodeRabbit configuration file

**: # AGENTS.md - AI Agent Coding Guide

This guide is for AI coding agents working in the OpenClaude repository. Read it before changing code, and also follow CONTRIBUTING.md for contributor policy, PR expectations, review follow-up, and project scope.

Project Snapshot

OpenClaude is a coding-agent CLI for cloud and local model providers. It supports OpenAI-compatible APIs, Anthropic, Gemini, DeepSeek, Ollama, MCP, local backends, slash commands, tools, agents, and a React/Ink terminal UI.

The installed CLI runs on Node.js >=22.0.0. Bun is used for source builds, scripts, dependency management, and tests.

Work Style

  • Keep changes focused on one problem.
  • Prefer existing patterns in the file or nearby module.
  • Avoid unrelated formatting, renames, dependency changes, or broad rewrites.
  • Add or update tests when behavior changes.
  • Update docs when setup, commands, provider behavior, or user-facing behavior changes.
  • For new features, larger refactors, dependencies, or runtime changes, follow the issue-first guidance in CONTRIBUTING.md.

Stack And Conventions

  • TypeScript with strict mode and ESM imports.
  • React + Ink for terminal UI.
  • Bun lockfile and Bun scripts for development workflows.
  • Node runtime for the built CLI.
  • Python exists for legacy/local-provider helper code. Do not add new Python code or expand Python-based features unless a maintainer explicitly approves that direction.

Common libraries and patterns:

  • chalk for terminal color.
  • commander for CLI argument parsing.
  • execa for child processes.
  • Existing service, provider, settings, permission, and UI patterns over new abstractions.

Repository Map

  • src/commands/ - slash and CLI command implementations.
  • src/components/ - React/Ink UI components.
  • src/services/ - API, MCP, OAuth, wiki, voice, and other service integrations.
  • src/tools/ - tool implementations.
  • src/utils/ - shared utilities.
  • `src/integration...

Files:

  • src/query/agentStepLimit.ts
  • src/types/message.ts
  • README.md
  • src/utils/plugins/loadPluginAgents.ts
  • src/utils/plugins/loadPluginAgents.test.ts
  • src/tools/AgentTool/loadAgentsDir.test.ts
  • src/entrypoints/sdk.d.ts
  • src/tools/AgentTool/agentToolUtils.ts
  • src/utils/frontmatterParser.ts
  • src/utils/messages.ts
  • src/services/api/claude.ts
  • src/entrypoints/sdk/query.ts
  • src/query/transitions.ts
  • src/query/toolFailureLoopGuard.test.ts
  • src/tools/AgentTool/loadAgentsDir.ts
  • src/query/toolFailureLoopGuard.ts
  • src/query/agentStepLimit.test.ts
  • src/tools/AgentTool/runAgent.ts
  • src/entrypoints/sdk/coreSchemas.ts
  • src/query.ts
**/*

⚙️ CodeRabbit configuration file

**/*: Apply the OpenClaude maintainer review rubric from AGENTS.md. Review the current diff, not stale discussion context. Separate real blockers from suggestions. Do not request changes for vague style churn. Treat approval as merge-ready from CodeRabbit's side, pending required human review and GitHub Checks. If checks are failing or unavailable, say so clearly instead of implying the PR is fully ready.

Files:

  • src/query/agentStepLimit.ts
  • src/types/message.ts
  • README.md
  • src/utils/plugins/loadPluginAgents.ts
  • src/utils/plugins/loadPluginAgents.test.ts
  • src/tools/AgentTool/loadAgentsDir.test.ts
  • src/entrypoints/sdk.d.ts
  • src/tools/AgentTool/agentToolUtils.ts
  • src/utils/frontmatterParser.ts
  • src/utils/messages.ts
  • src/services/api/claude.ts
  • src/entrypoints/sdk/query.ts
  • src/query/transitions.ts
  • src/query/toolFailureLoopGuard.test.ts
  • src/tools/AgentTool/loadAgentsDir.ts
  • src/query/toolFailureLoopGuard.ts
  • src/query/agentStepLimit.test.ts
  • src/tools/AgentTool/runAgent.ts
  • src/entrypoints/sdk/coreSchemas.ts
  • src/query.ts
{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}

⚙️ CodeRabbit configuration file

{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}: Review docs for accuracy against current code behavior. Flag security or provider claims that overpromise, stale install commands, missing setup caveats, and instructions that could push users toward unsafe credential handling. Keep purely wording-level suggestions non-blocking.

Files:

  • README.md
{src/services/**/*.ts,src/utils/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use execa for child processes

Files:

  • src/utils/plugins/loadPluginAgents.ts
  • src/utils/plugins/loadPluginAgents.test.ts
  • src/utils/frontmatterParser.ts
  • src/utils/messages.ts
  • src/services/api/claude.ts
src/{skills,utils/plugins,services/mcp}/**

⚙️ CodeRabbit configuration file

src/{skills,utils/plugins,services/mcp}/**: Review skill/plugin/MCP behavior as a trust boundary. Check registry fetches, local and remote installs, path normalization, hash verification, revocation/trust metadata, tools_required handling, config-home behavior, and startup-time loading. Block on path traversal risk, unverified downloads, silent trust promotion, or unexpected code/tool activation.

Files:

  • src/utils/plugins/loadPluginAgents.ts
  • src/utils/plugins/loadPluginAgents.test.ts
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Add or update tests when the change affects behavior

Files:

  • src/utils/plugins/loadPluginAgents.test.ts
  • src/tools/AgentTool/loadAgentsDir.test.ts
  • src/query/toolFailureLoopGuard.test.ts
  • src/query/agentStepLimit.test.ts
**/*.test.{ts,tsx,js}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Test the exact provider/model path you changed when possible

Files:

  • src/utils/plugins/loadPluginAgents.test.ts
  • src/tools/AgentTool/loadAgentsDir.test.ts
  • src/query/toolFailureLoopGuard.test.ts
  • src/query/agentStepLimit.test.ts
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}

⚙️ CodeRabbit configuration file

{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}: Review tests for meaningful coverage of the changed behavior, isolation of global/env/config state, async cleanup, fake timers, provider profile leaks, and Windows-compatible assumptions. Block when risky runtime changes lack focused regression coverage or tests assert implementation details while missing the user-visible behavior.

Files:

  • src/utils/plugins/loadPluginAgents.test.ts
  • src/tools/AgentTool/loadAgentsDir.test.ts
  • src/query/toolFailureLoopGuard.test.ts
  • src/query/agentStepLimit.test.ts
src/{components/permissions,utils/permissions,hooks/toolPermission,tools,entrypoints/sdk}/**

⚙️ CodeRabbit configuration file

src/{components/permissions,utils/permissions,hooks/toolPermission,tools,entrypoints/sdk}/**: Review permission prompts, auto-allow logic, sandbox behavior, SDK permission schemas, shell/PowerShell execution, and background execution paths as security-sensitive. Block on bypasses, unclear trust boundaries, unsafe path handling, missing user visibility, or changes that broaden allowed behavior without an explicit maintainer decision.

Files:

  • src/tools/AgentTool/loadAgentsDir.test.ts
  • src/tools/AgentTool/agentToolUtils.ts
  • src/entrypoints/sdk/query.ts
  • src/tools/AgentTool/loadAgentsDir.ts
  • src/tools/AgentTool/runAgent.ts
  • src/entrypoints/sdk/coreSchemas.ts
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use chalk for terminal color in CLI code

Files:

  • src/entrypoints/sdk.d.ts
  • src/services/api/claude.ts
  • src/entrypoints/sdk/query.ts
  • src/entrypoints/sdk/coreSchemas.ts
{src/commands/**/*.ts,src/entrypoints/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use commander for CLI argument parsing

Files:

  • src/entrypoints/sdk.d.ts
  • src/entrypoints/sdk/query.ts
  • src/entrypoints/sdk/coreSchemas.ts
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}

⚙️ CodeRabbit configuration file

{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}: Review install, launcher, build, packaging, startup, and entrypoint changes for cross-platform compatibility, tracked-source rewrites, env/config precedence, and release safety. Block on changes that can break Windows/macOS/Linux startup or publish unexpected artifacts.

Files:

  • src/entrypoints/sdk.d.ts
  • src/entrypoints/sdk/query.ts
  • src/entrypoints/sdk/coreSchemas.ts
{src/integrations/**/*.ts,src/services/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Test the exact provider/model path you changed when possible for provider modifications

Files:

  • src/services/api/claude.ts
{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}

⚙️ CodeRabbit configuration file

{src/services/api/**,src/integrations/**,src/utils/model/**,src/utils/provider*.ts,src/commands/provider/**}: Review provider routing, model selection, env precedence, auth/token handling, OpenAI-compatible shims, retries, proxy behavior, and outbound HTTP behavior with high scrutiny. Block on silent default changes, hidden fallback expansion, credential reuse mistakes, hardcoded provider assumptions, or new network reach that is not intentional and documented.

Files:

  • src/services/api/claude.ts
🪛 GitHub Actions: PR Checks / 1_smoke-and-tests.txt
src/tools/AgentTool/loadAgentsDir.test.ts

[error] 225-225: Test failed in 'agent definition loading' > loads maxSteps from markdown agent frontmatter. expect(received).toBe(expected) failed: Expected maxSteps to be 5 but received 1.

🪛 GitHub Actions: PR Checks / smoke-and-tests
src/tools/AgentTool/loadAgentsDir.test.ts

[error] 225-225: Test failed in 'loads maxSteps from markdown agent frontmatter'. expect(received).toBe(expected) failed: Expected 5, Received 1.

🪛 GitHub Check: smoke-and-tests
src/tools/AgentTool/loadAgentsDir.test.ts

[failure] 225-225: error: expect(received).toBe(expected)
Expected: 5
Received: 1

  at <anonymous> (/home/runner/work/openclaude/openclaude/src/tools/AgentTool/loadAgentsDir.test.ts:225:29)
🔇 Additional comments (5)
src/utils/messages.ts (1)

471-490: LGTM!

Also applies to: 528-531

src/services/api/claude.ts (1)

721-721: LGTM!

Also applies to: 1298-1301

src/query/toolFailureLoopGuard.test.ts (1)

25-49: LGTM!

Also applies to: 283-310

src/tools/AgentTool/loadAgentsDir.test.ts (1)

162-204: LGTM!

Also applies to: 228-242

src/utils/plugins/loadPluginAgents.test.ts (1)

16-142: LGTM!

Comment thread README.md
Comment thread src/query.ts
Comment thread src/query/agentStepLimit.test.ts Outdated
Comment thread src/tools/AgentTool/loadAgentsDir.test.ts
@chioarub
chioarub force-pushed the feat/agent-step-limits branch from 3ed4b00 to 011f081 Compare June 29, 2026 13:37

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/entrypoints/sdk/query.ts`:
- Around line 546-557: Avoid mutating the AppState-held agent list before
injection succeeds: in `injectAgents()` the `agentDefs` object already stored on
`self` is being modified when `agentDefs.activeAgents.push(...userAgents)` runs,
so failed injection leaks partial state. Build a separate merged agent list (or
clone `agentDefs`/`activeAgents`) for the injection attempt, and only write back
to the AppState-held object after the injection path completes successfully;
keep the existing `buildSdkUserAgents()` and `pushAgentFailure()` behavior
unchanged.

In `@src/query.ts`:
- Around line 283-299: The hasAssistantSummaryText helper is too strict because
it checks each text block independently, so a valid summary split across
multiple text parts can be missed. Update hasAssistantSummaryText in
src/query.ts to aggregate all text content from assistantMessage.message.content
first, then perform the marker check against the combined string instead of
per-part, so split replies are still recognized as having an assistant summary.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: dd818015-a0d2-4f1d-938e-aa209712c005

📥 Commits

Reviewing files that changed from the base of the PR and between 82f2d11 and 011f081.

📒 Files selected for processing (7)
  • README.md
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
  • src/query.ts
  • src/query/agentStepLimit.test.ts
  • tests/sdk/query-happy-path.test.ts
📜 Review details
⚠️ CI failures not shown inline (2)

GitHub Actions: PR Checks / smoke-and-tests: feat(agents): add per-agent step limits

Conclusion: failure

View job details

behavior > increments while push in flight and resets after cap via onDebounceFire [2.00ms]
 (pass) rescheduleCount behavior > clears pushInProgress when executePush completes [1.00ms]
 (pass) rescheduleCount behavior > skips the capped follow-up push when suppression is set mid-flight [1.00ms]
 (pass) rescheduleCount behavior > capped reschedule chains follow-up push after in-flight push completes [2.00ms]
 (pass) rescheduleCount behavior > does not queue multiple duplicate follow-up pushes when one is already queued [1.00ms]
 (pass) executePush identity safety > clears currentPushPromise when it was set to the executing promise [1.00ms]
 (pass) executePush identity safety > preserves currentPushPromise when replaced during yield point [4.00ms]
 ##[endgroup]
 ##[group]src/services/tips/tipLink.test.ts:
 (pass) renderSponsorLink > hyperlinks supported: name is an OSC 8 link, no trailing raw url [1.00ms]
 (pass) renderSponsorLink > hyperlinks NOT supported: plain name + dimmed url trailing
 (pass) renderSponsorLink > no url → plain name, nothing trailing (either branch)
 (pass) renderSponsorLink > strips control chars from the advertiser name (no escape injection)
 (pass) renderSponsorLink > rejects non-http(s) URLs (javascript:/file:) → no link
 (pass) renderSponsorLink > strips control chars from the url before validating it
 (pass) renderSponsorLink > a malicious url cannot inject extra escape sequences into the output
 ##[endgroup]
 ##[group]src/services/tips/gitlawbEarn.test.ts:
 (pass) gitlawb earning tips > disabled by default (no ads config)
 (pass) gitlawb earning tips > enabled once /ads on set enabled + earnCode
 (pass) gitlawb earning tips > cadence: every 2nd eligible slot by default
 (pass) gitlawb earning tips > OPENCLAUDE_ADS_TIP_EVERY=1 shows every turn
 (pass) gitlawb earning tips > disabled → never shows and never increments the counter
 (pass) gitlawb earning tips > content falls back to a static line when the ads service is unreachable [1.00ms...

GitHub Actions: PR Checks / 0_smoke-and-tests.txt: feat(agents): add per-agent step limits

Conclusion: failure

View job details

trims OPENGATEWAY_API_KEY before bearer auth [5.00ms]
 (pass) gitlawb opengateway provider flag ignores blank OPENGATEWAY_API_KEY and uses OPENAI_API_KEY fallback [6.00ms]
 (pass) gitlawb opengateway provider flag sends OPENGATEWAY_API_KEY to OPENGATEWAY_BASE_URL override [1.00ms]
 (pass) gitlawb opengateway provider flag sends OPENGATEWAY_API_KEY to custom OPENAI_BASE_URL fallback [2.00ms]
 (pass) gitlawb opengateway provider flag prefers OPENGATEWAY_API_KEY over generic OPENAI_API_KEY for custom base URL [1.00ms]
 (pass) gitlawb opengateway provider flag prefers OPENGATEWAY_API_KEY over generic OPENAI_API_KEYS pool [2.00ms]
 (pass) gitlawb opengateway provider flag uses generic OPENAI_API_KEYS pool before generic OPENAI_API_KEY fallback [1.00ms]
 (pass) gitlawb opengateway stored provider profile key becomes bearer auth [2.00ms]
 (pass) openai route still sends OPENAI_API_KEY as bearer auth [5.00ms]
 (pass) OPENAI_API_KEYS rejects placeholder values before sending requests [7.00ms]
 (pass) OPENAI_API_KEYS rotates to the next key on rate-limit failure [7.00ms]
 (pass) comma-separated OPENAI_API_KEY rotates to the next key on rate-limit failure [3.00ms]
 (pass) OPENAI_API_KEYS does not rotate through pool on provider 5xx outage [4.00ms]
 (pass) OPENAI_API_KEYS preserves cooldown state across client requests [6.00ms]
 (pass) OPENAI_API_KEYS rotates Azure api-key auth on auth failure [4.00ms]
 (pass) OPENAI_API_KEYS does not reuse auth-disabled credentials across client requests [6.00ms]
 (pass) OPENAI_API_KEYS permanently evicts 403 auth failures [7.00ms]
 (pass) does not use BNKR_API_KEY for non-Bankr OpenAI-compatible routes [2.00ms]
 (pass) preserves Gemini tool call extra_content from streaming chunks [1.00ms]
 (pass) preserves Gemini thought signature from streaming delta extra_content [1.00ms]
 (pass) preserves Gemini thought signature from non-streaming message extra_content [1.00ms]
 (pass) converts Gemini raw tool-call text into streaming tool_use blocks ...
🧰 Additional context used
📓 Path-based instructions (14)
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript with strict mode and ESM imports

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
  • src/query/agentStepLimit.test.ts
  • src/query.ts
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use chalk for terminal color in CLI code

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
{src/commands/**/*.ts,src/entrypoints/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use commander for CLI argument parsing

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
**/*.{ts,tsx,js,jsx,py,json,md}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Follow the existing code style in the touched files

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/query-happy-path.test.ts
  • README.md
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
  • src/query/agentStepLimit.test.ts
  • src/query.ts
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Add or update tests when the change affects behavior

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/query-happy-path.test.ts
  • src/query/agentStepLimit.test.ts
**/*.test.{ts,tsx,js}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Test the exact provider/model path you changed when possible

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/query-happy-path.test.ts
  • src/query/agentStepLimit.test.ts
**/*.{ts,tsx,js,jsx,py}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Keep comments useful and concise

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/query-happy-path.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
  • src/query/agentStepLimit.test.ts
  • src/query.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Follow TypeScript strict mode and type safety practices by running typecheck before submitting

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/query-happy-path.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
  • src/query/agentStepLimit.test.ts
  • src/query.ts
**

⚙️ CodeRabbit configuration file

**: # AGENTS.md - AI Agent Coding Guide

This guide is for AI coding agents working in the OpenClaude repository. Read it before changing code, and also follow CONTRIBUTING.md for contributor policy, PR expectations, review follow-up, and project scope.

Project Snapshot

OpenClaude is a coding-agent CLI for cloud and local model providers. It supports OpenAI-compatible APIs, Anthropic, Gemini, DeepSeek, Ollama, MCP, local backends, slash commands, tools, agents, and a React/Ink terminal UI.

The installed CLI runs on Node.js >=22.0.0. Bun is used for source builds, scripts, dependency management, and tests.

Work Style

  • Keep changes focused on one problem.
  • Prefer existing patterns in the file or nearby module.
  • Avoid unrelated formatting, renames, dependency changes, or broad rewrites.
  • Add or update tests when behavior changes.
  • Update docs when setup, commands, provider behavior, or user-facing behavior changes.
  • For new features, larger refactors, dependencies, or runtime changes, follow the issue-first guidance in CONTRIBUTING.md.

Stack And Conventions

  • TypeScript with strict mode and ESM imports.
  • React + Ink for terminal UI.
  • Bun lockfile and Bun scripts for development workflows.
  • Node runtime for the built CLI.
  • Python exists for legacy/local-provider helper code. Do not add new Python code or expand Python-based features unless a maintainer explicitly approves that direction.

Common libraries and patterns:

  • chalk for terminal color.
  • commander for CLI argument parsing.
  • execa for child processes.
  • Existing service, provider, settings, permission, and UI patterns over new abstractions.

Repository Map

  • src/commands/ - slash and CLI command implementations.
  • src/components/ - React/Ink UI components.
  • src/services/ - API, MCP, OAuth, wiki, voice, and other service integrations.
  • src/tools/ - tool implementations.
  • src/utils/ - shared utilities.
  • `src/integration...

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/query-happy-path.test.ts
  • README.md
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
  • src/query/agentStepLimit.test.ts
  • src/query.ts
**/*

⚙️ CodeRabbit configuration file

**/*: Apply the OpenClaude maintainer review rubric from AGENTS.md. Review the current diff, not stale discussion context. Separate real blockers from suggestions. Do not request changes for vague style churn. Treat approval as merge-ready from CodeRabbit's side, pending required human review and GitHub Checks. If checks are failing or unavailable, say so clearly instead of implying the PR is fully ready.

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/query-happy-path.test.ts
  • README.md
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
  • src/query/agentStepLimit.test.ts
  • src/query.ts
src/{components/permissions,utils/permissions,hooks/toolPermission,tools,entrypoints/sdk}/**

⚙️ CodeRabbit configuration file

src/{components/permissions,utils/permissions,hooks/toolPermission,tools,entrypoints/sdk}/**: Review permission prompts, auto-allow logic, sandbox behavior, SDK permission schemas, shell/PowerShell execution, and background execution paths as security-sensitive. Block on bypasses, unclear trust boundaries, unsafe path handling, missing user visibility, or changes that broaden allowed behavior without an explicit maintainer decision.

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}

⚙️ CodeRabbit configuration file

{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}: Review install, launcher, build, packaging, startup, and entrypoint changes for cross-platform compatibility, tracked-source rewrites, env/config precedence, and release safety. Block on changes that can break Windows/macOS/Linux startup or publish unexpected artifacts.

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}

⚙️ CodeRabbit configuration file

{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}: Review tests for meaningful coverage of the changed behavior, isolation of global/env/config state, async cleanup, fake timers, provider profile leaks, and Windows-compatible assumptions. Block when risky runtime changes lack focused regression coverage or tests assert implementation details while missing the user-visible behavior.

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/query-happy-path.test.ts
  • src/query/agentStepLimit.test.ts
{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}

⚙️ CodeRabbit configuration file

{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}: Review docs for accuracy against current code behavior. Flag security or provider claims that overpromise, stale install commands, missing setup caveats, and instructions that could push users toward unsafe credential handling. Keep purely wording-level suggestions non-blocking.

Files:

  • README.md
🔇 Additional comments (1)
src/query/agentStepLimit.test.ts (1)

266-271: LGTM!

Also applies to: 408-413, 484-489, 519-519, 536-541, 559-648

Comment thread src/entrypoints/sdk/query.ts Outdated
Comment thread src/query.ts
@chioarub
chioarub force-pushed the feat/agent-step-limits branch from 011f081 to 2840943 Compare June 29, 2026 13:52

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/entrypoints/sdk/agentDefinitions.ts`:
- Around line 45-49: The normalization in agentDefinitions should not fill a
missing SDK agent prompt with an empty string, because that converts an invalid
definition into a valid one. Update the logic around safeParse() and
normalizedDef so prompt remains required and omitted prompts cause validation
failure instead of defaulting to ''. Keep the existing description fallback, but
remove the prompt coercion so the agent_load_failure path is triggered for
malformed definitions.

In `@src/entrypoints/sdk/query.ts`:
- Around line 564-569: Mirror the injected SDK agents into
agentDefinitions.allAgents as well as activeAgents in query.ts after injection
succeeds, since the current state update only patches activeAgents and leaves
consumers like AgentsMenu, MCPSettings, and Doctor without the injected agents.
Update the self.appStateStore.setState path in the injection flow to merge the
injected agent set into both agentDefinitions.activeAgents and
agentDefinitions.allAgents so the SDK-provided agents are visible everywhere
that reads from the full agent list.

In `@tests/sdk/query-happy-path.test.ts`:
- Around line 196-230: The test in query-happy-path.test.ts should also verify
ordering, not just presence, for the failed SDK agent injection path. Update the
existing `failed SDK agent injection does not expose uninjected user agents`
case to assert that the `agent_load_failure` event from
`query()`/`MockQueryEngine` is emitted before any assistant output or other
engine messages, since `drainAgentFailureQueue()` is meant to preserve
pre-output ordering. Keep the existing checks for `stage === 'injection'`, the
injected error message, and `supportedAgents()` not containing `leaky`, but add
an ordering assertion using the collected `messages` array to ensure the failure
event appears first among relevant stream items.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: e3fb0ec2-2cbe-4e7b-86ef-783f12056f94

📥 Commits

Reviewing files that changed from the base of the PR and between 011f081 and 2840943.

📒 Files selected for processing (7)
  • README.md
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
  • src/query.ts
  • src/query/agentStepLimit.test.ts
  • tests/sdk/query-happy-path.test.ts
📜 Review details
⚠️ CI failures not shown inline (2)

GitHub Actions: PR Checks / smoke-and-tests: feat(agents): add per-agent step limits

Conclusion: failure

View job details

diagnostics [3.00ms]
 ##[endgroup]
 ##[group]src/services/teamMemorySync/watcher.test.ts:
 (pass) rescheduleCount behavior > increments while push in flight and resets after cap via onDebounceFire [2.00ms]
 (pass) rescheduleCount behavior > clears pushInProgress when executePush completes [1.00ms]
 (pass) rescheduleCount behavior > skips the capped follow-up push when suppression is set mid-flight [4.00ms]
 (pass) rescheduleCount behavior > capped reschedule chains follow-up push after in-flight push completes [2.00ms]
 (pass) rescheduleCount behavior > does not queue multiple duplicate follow-up pushes when one is already queued [1.00ms]
 (pass) executePush identity safety > clears currentPushPromise when it was set to the executing promise [1.00ms]
 (pass) executePush identity safety > preserves currentPushPromise when replaced during yield point [1.00ms]
 ##[endgroup]
 ##[group]src/services/tips/tipLink.test.ts:
 (pass) renderSponsorLink > hyperlinks supported: name is an OSC 8 link, no trailing raw url
 (pass) renderSponsorLink > hyperlinks NOT supported: plain name + dimmed url trailing
 (pass) renderSponsorLink > no url → plain name, nothing trailing (either branch)
 (pass) renderSponsorLink > strips control chars from the advertiser name (no escape injection)
 (pass) renderSponsorLink > rejects non-http(s) URLs (javascript:/file:) → no link
 (pass) renderSponsorLink > strips control chars from the url before validating it
 (pass) renderSponsorLink > a malicious url cannot inject extra escape sequences into the output
 ##[endgroup]
 ##[group]src/services/tips/gitlawbEarn.test.ts:
 (pass) gitlawb earning tips > disabled by default (no ads config)
 (pass) gitlawb earning tips > enabled once /ads on set enabled + earnCode
 (pass) gitlawb earning tips > cadence: every 2nd eligible slot by default
 (pass) gitlawb earning tips > OPENCLAUDE_ADS_TIP_EVERY=1 shows every turn [1.00ms]
 (pass) gitlawb earning tips > disabled → never shows and never increments the coun...

GitHub Actions: PR Checks / 1_smoke-and-tests.txt: feat(agents): add per-agent step limits

Conclusion: failure

View job details

way provider flag trims OPENGATEWAY_API_KEY before bearer auth [5.00ms]
 (pass) gitlawb opengateway provider flag ignores blank OPENGATEWAY_API_KEY and uses OPENAI_API_KEY fallback [5.00ms]
 (pass) gitlawb opengateway provider flag sends OPENGATEWAY_API_KEY to OPENGATEWAY_BASE_URL override [1.00ms]
 (pass) gitlawb opengateway provider flag sends OPENGATEWAY_API_KEY to custom OPENAI_BASE_URL fallback [2.00ms]
 (pass) gitlawb opengateway provider flag prefers OPENGATEWAY_API_KEY over generic OPENAI_API_KEY for custom base URL [1.00ms]
 (pass) gitlawb opengateway provider flag prefers OPENGATEWAY_API_KEY over generic OPENAI_API_KEYS pool [2.00ms]
 (pass) gitlawb opengateway provider flag uses generic OPENAI_API_KEYS pool before generic OPENAI_API_KEY fallback [1.00ms]
 (pass) gitlawb opengateway stored provider profile key becomes bearer auth [2.00ms]
 (pass) openai route still sends OPENAI_API_KEY as bearer auth [5.00ms]
 (pass) OPENAI_API_KEYS rejects placeholder values before sending requests [4.00ms]
 (pass) OPENAI_API_KEYS rotates to the next key on rate-limit failure [9.00ms]
 (pass) comma-separated OPENAI_API_KEY rotates to the next key on rate-limit failure [3.00ms]
 (pass) OPENAI_API_KEYS does not rotate through pool on provider 5xx outage [3.00ms]
 (pass) OPENAI_API_KEYS preserves cooldown state across client requests [6.00ms]
 (pass) OPENAI_API_KEYS rotates Azure api-key auth on auth failure [4.00ms]
 (pass) OPENAI_API_KEYS does not reuse auth-disabled credentials across client requests [6.00ms]
 (pass) OPENAI_API_KEYS permanently evicts 403 auth failures [8.00ms]
 (pass) does not use BNKR_API_KEY for non-Bankr OpenAI-compatible routes [2.00ms]
 (pass) preserves Gemini tool call extra_content from streaming chunks [1.00ms]
 (pass) preserves Gemini thought signature from streaming delta extra_content [2.00ms]
 (pass) preserves Gemini thought signature from non-streaming message extra_content [1.00ms]
 (pass) converts Gemini raw tool-call text into streamin...
🧰 Additional context used
📓 Path-based instructions (14)
**/*.{ts,tsx,js,jsx,py,json,md}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Follow the existing code style in the touched files

Files:

  • README.md
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • tests/sdk/query-happy-path.test.ts
  • src/entrypoints/sdk/query.ts
  • src/query/agentStepLimit.test.ts
  • src/query.ts
**

⚙️ CodeRabbit configuration file

**: # AGENTS.md - AI Agent Coding Guide

This guide is for AI coding agents working in the OpenClaude repository. Read it before changing code, and also follow CONTRIBUTING.md for contributor policy, PR expectations, review follow-up, and project scope.

Project Snapshot

OpenClaude is a coding-agent CLI for cloud and local model providers. It supports OpenAI-compatible APIs, Anthropic, Gemini, DeepSeek, Ollama, MCP, local backends, slash commands, tools, agents, and a React/Ink terminal UI.

The installed CLI runs on Node.js >=22.0.0. Bun is used for source builds, scripts, dependency management, and tests.

Work Style

  • Keep changes focused on one problem.
  • Prefer existing patterns in the file or nearby module.
  • Avoid unrelated formatting, renames, dependency changes, or broad rewrites.
  • Add or update tests when behavior changes.
  • Update docs when setup, commands, provider behavior, or user-facing behavior changes.
  • For new features, larger refactors, dependencies, or runtime changes, follow the issue-first guidance in CONTRIBUTING.md.

Stack And Conventions

  • TypeScript with strict mode and ESM imports.
  • React + Ink for terminal UI.
  • Bun lockfile and Bun scripts for development workflows.
  • Node runtime for the built CLI.
  • Python exists for legacy/local-provider helper code. Do not add new Python code or expand Python-based features unless a maintainer explicitly approves that direction.

Common libraries and patterns:

  • chalk for terminal color.
  • commander for CLI argument parsing.
  • execa for child processes.
  • Existing service, provider, settings, permission, and UI patterns over new abstractions.

Repository Map

  • src/commands/ - slash and CLI command implementations.
  • src/components/ - React/Ink UI components.
  • src/services/ - API, MCP, OAuth, wiki, voice, and other service integrations.
  • src/tools/ - tool implementations.
  • src/utils/ - shared utilities.
  • `src/integration...

Files:

  • README.md
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • tests/sdk/query-happy-path.test.ts
  • src/entrypoints/sdk/query.ts
  • src/query/agentStepLimit.test.ts
  • src/query.ts
**/*

⚙️ CodeRabbit configuration file

**/*: Apply the OpenClaude maintainer review rubric from AGENTS.md. Review the current diff, not stale discussion context. Separate real blockers from suggestions. Do not request changes for vague style churn. Treat approval as merge-ready from CodeRabbit's side, pending required human review and GitHub Checks. If checks are failing or unavailable, say so clearly instead of implying the PR is fully ready.

Files:

  • README.md
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • tests/sdk/query-happy-path.test.ts
  • src/entrypoints/sdk/query.ts
  • src/query/agentStepLimit.test.ts
  • src/query.ts
{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}

⚙️ CodeRabbit configuration file

{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}: Review docs for accuracy against current code behavior. Flag security or provider claims that overpromise, stale install commands, missing setup caveats, and instructions that could push users toward unsafe credential handling. Keep purely wording-level suggestions non-blocking.

Files:

  • README.md
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript with strict mode and ESM imports

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
  • src/query/agentStepLimit.test.ts
  • src/query.ts
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use chalk for terminal color in CLI code

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
{src/commands/**/*.ts,src/entrypoints/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use commander for CLI argument parsing

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Add or update tests when the change affects behavior

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/query-happy-path.test.ts
  • src/query/agentStepLimit.test.ts
**/*.test.{ts,tsx,js}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Test the exact provider/model path you changed when possible

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/query-happy-path.test.ts
  • src/query/agentStepLimit.test.ts
**/*.{ts,tsx,js,jsx,py}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Keep comments useful and concise

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • tests/sdk/query-happy-path.test.ts
  • src/entrypoints/sdk/query.ts
  • src/query/agentStepLimit.test.ts
  • src/query.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Follow TypeScript strict mode and type safety practices by running typecheck before submitting

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • tests/sdk/query-happy-path.test.ts
  • src/entrypoints/sdk/query.ts
  • src/query/agentStepLimit.test.ts
  • src/query.ts
src/{components/permissions,utils/permissions,hooks/toolPermission,tools,entrypoints/sdk}/**

⚙️ CodeRabbit configuration file

src/{components/permissions,utils/permissions,hooks/toolPermission,tools,entrypoints/sdk}/**: Review permission prompts, auto-allow logic, sandbox behavior, SDK permission schemas, shell/PowerShell execution, and background execution paths as security-sensitive. Block on bypasses, unclear trust boundaries, unsafe path handling, missing user visibility, or changes that broaden allowed behavior without an explicit maintainer decision.

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}

⚙️ CodeRabbit configuration file

{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}: Review install, launcher, build, packaging, startup, and entrypoint changes for cross-platform compatibility, tracked-source rewrites, env/config precedence, and release safety. Block on changes that can break Windows/macOS/Linux startup or publish unexpected artifacts.

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}

⚙️ CodeRabbit configuration file

{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}: Review tests for meaningful coverage of the changed behavior, isolation of global/env/config state, async cleanup, fake timers, provider profile leaks, and Windows-compatible assumptions. Block when risky runtime changes lack focused regression coverage or tests assert implementation details while missing the user-visible behavior.

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/query-happy-path.test.ts
  • src/query/agentStepLimit.test.ts
🔇 Additional comments (2)
src/query.ts (1)

52-52: LGTM!

Also applies to: 264-300, 356-386, 2069-2074

src/query/agentStepLimit.test.ts (1)

266-271: LGTM!

Also applies to: 408-413, 484-489, 519-519, 536-573, 576-662

Comment thread src/entrypoints/sdk/agentDefinitions.ts
Comment thread src/entrypoints/sdk/query.ts Outdated
Comment thread tests/sdk/query-happy-path.test.ts
@chioarub
chioarub force-pushed the feat/agent-step-limits branch from 2840943 to 824a85f Compare June 29, 2026 14:03

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/entrypoints/sdk/query.ts (1)

154-161: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Make description optional in the SDK agents type.

buildSdkUserAgents() accepts a missing description and falls back to the agent name, and src/entrypoints/sdk/agentDefinitions.test.ts now locks that behavior in. Keeping options.agents[*].description required makes a valid runtime shape fail for strict TypeScript callers.

Suggested fix
   agents?: Record<string, {
-    description: string
+    description?: string
     prompt: string
     tools?: string[]
     disallowedTools?: string[]
     model?: string
     maxTurns?: number
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/entrypoints/sdk/query.ts` around lines 154 - 161, Make the SDK agents
type match the runtime behavior by making description optional in the agents
object used in query-related types. Update the Record definition in the query
SDK types so buildSdkUserAgents() can accept agents without a description and
fall back to the agent name, and keep the shape aligned with the
agentDefinitions test coverage.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/sdk/query-happy-path.test.ts`:
- Around line 223-239: The current regression test only verifies
supportedAgents(), so it misses the leaked leaky entry in
appStateStore.agentDefinitions.allAgents after a failed injection. Update the
existing query-happy-path test to assert the user-visible state that
menus/diagnostics use, by checking q.appStateStore.agentDefinitions.allAgents
(or the equivalent all-agents source used by Query) no longer contains leaky
after the agent_load_failure path, while still keeping the failure ordering
assertion and supportedAgents() check in place.

---

Outside diff comments:
In `@src/entrypoints/sdk/query.ts`:
- Around line 154-161: Make the SDK agents type match the runtime behavior by
making description optional in the agents object used in query-related types.
Update the Record definition in the query SDK types so buildSdkUserAgents() can
accept agents without a description and fall back to the agent name, and keep
the shape aligned with the agentDefinitions test coverage.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 770b06e3-3a3d-44d9-8993-524826ad0ea2

📥 Commits

Reviewing files that changed from the base of the PR and between 2840943 and 824a85f.

📒 Files selected for processing (7)
  • README.md
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
  • src/query.ts
  • src/query/agentStepLimit.test.ts
  • tests/sdk/query-happy-path.test.ts
📜 Review details
⚠️ CI failures not shown inline (2)

GitHub Actions: PR Checks / smoke-and-tests: feat(agents): add per-agent step limits

Conclusion: failure

View job details

havior > increments while push in flight and resets after cap via onDebounceFire [1.00ms]
 (pass) rescheduleCount behavior > clears pushInProgress when executePush completes [1.00ms]
 (pass) rescheduleCount behavior > skips the capped follow-up push when suppression is set mid-flight [1.00ms]
 (pass) rescheduleCount behavior > capped reschedule chains follow-up push after in-flight push completes [2.00ms]
 (pass) rescheduleCount behavior > does not queue multiple duplicate follow-up pushes when one is already queued [4.00ms]
 (pass) executePush identity safety > clears currentPushPromise when it was set to the executing promise [2.00ms]
 (pass) executePush identity safety > preserves currentPushPromise when replaced during yield point
 ##[endgroup]
 ##[group]src/services/tips/tipLink.test.ts:
 (pass) renderSponsorLink > hyperlinks supported: name is an OSC 8 link, no trailing raw url
 (pass) renderSponsorLink > hyperlinks NOT supported: plain name + dimmed url trailing
 (pass) renderSponsorLink > no url → plain name, nothing trailing (either branch)
 (pass) renderSponsorLink > strips control chars from the advertiser name (no escape injection)
 (pass) renderSponsorLink > rejects non-http(s) URLs (javascript:/file:) → no link
 (pass) renderSponsorLink > strips control chars from the url before validating it
 (pass) renderSponsorLink > a malicious url cannot inject extra escape sequences into the output
 ##[endgroup]
 ##[group]src/services/tips/gitlawbEarn.test.ts:
 (pass) gitlawb earning tips > disabled by default (no ads config) [1.00ms]
 (pass) gitlawb earning tips > enabled once /ads on set enabled + earnCode
 (pass) gitlawb earning tips > cadence: every 2nd eligible slot by default
 (pass) gitlawb earning tips > OPENCLAUDE_ADS_TIP_EVERY=1 shows every turn
 (pass) gitlawb earning tips > disabled → never shows and never increments the counter
 (pass) gitlawb earning tips > content falls back to a static line when the ads service is unreachable [1.00ms]
 (pass) g...

GitHub Actions: PR Checks / 2_smoke-and-tests.txt: feat(agents): add per-agent step limits

Conclusion: failure

View job details

.00ms]
 (pass) gitlawb opengateway provider flag ignores blank OPENGATEWAY_API_KEY and uses OPENAI_API_KEY fallback [6.00ms]
 (pass) gitlawb opengateway provider flag sends OPENGATEWAY_API_KEY to OPENGATEWAY_BASE_URL override [1.00ms]
 (pass) gitlawb opengateway provider flag sends OPENGATEWAY_API_KEY to custom OPENAI_BASE_URL fallback [1.00ms]
 (pass) gitlawb opengateway provider flag prefers OPENGATEWAY_API_KEY over generic OPENAI_API_KEY for custom base URL [2.00ms]
 (pass) gitlawb opengateway provider flag prefers OPENGATEWAY_API_KEY over generic OPENAI_API_KEYS pool [1.00ms]
 (pass) gitlawb opengateway provider flag uses generic OPENAI_API_KEYS pool before generic OPENAI_API_KEY fallback [2.00ms]
 (pass) gitlawb opengateway stored provider profile key becomes bearer auth [3.00ms]
 (pass) openai route still sends OPENAI_API_KEY as bearer auth [4.00ms]
 (pass) OPENAI_API_KEYS rejects placeholder values before sending requests [6.00ms]
 (pass) OPENAI_API_KEYS rotates to the next key on rate-limit failure [8.00ms]
 (pass) comma-separated OPENAI_API_KEY rotates to the next key on rate-limit failure [3.00ms]
 (pass) OPENAI_API_KEYS does not rotate through pool on provider 5xx outage [4.00ms]
 (pass) OPENAI_API_KEYS preserves cooldown state across client requests [7.00ms]
 (pass) OPENAI_API_KEYS rotates Azure api-key auth on auth failure [4.00ms]
 (pass) OPENAI_API_KEYS does not reuse auth-disabled credentials across client requests [6.00ms]
 (pass) OPENAI_API_KEYS permanently evicts 403 auth failures [7.00ms]
 (pass) does not use BNKR_API_KEY for non-Bankr OpenAI-compatible routes [2.00ms]
 (pass) preserves Gemini tool call extra_content from streaming chunks [2.00ms]
 (pass) preserves Gemini thought signature from streaming delta extra_content [1.00ms]
 (pass) preserves Gemini thought signature from non-streaming message extra_content [1.00ms]
 (pass) converts Gemini raw tool-call text into streaming tool_use blocks [3.00ms]
 (pass) converts Gemini raw tool-call ...
🧰 Additional context used
📓 Path-based instructions (14)
**/*.{ts,tsx,js,jsx,py,json,md}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Follow the existing code style in the touched files

Files:

  • README.md
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
  • tests/sdk/query-happy-path.test.ts
  • src/query/agentStepLimit.test.ts
  • src/query.ts
**

⚙️ CodeRabbit configuration file

**: # AGENTS.md - AI Agent Coding Guide

This guide is for AI coding agents working in the OpenClaude repository. Read it before changing code, and also follow CONTRIBUTING.md for contributor policy, PR expectations, review follow-up, and project scope.

Project Snapshot

OpenClaude is a coding-agent CLI for cloud and local model providers. It supports OpenAI-compatible APIs, Anthropic, Gemini, DeepSeek, Ollama, MCP, local backends, slash commands, tools, agents, and a React/Ink terminal UI.

The installed CLI runs on Node.js >=22.0.0. Bun is used for source builds, scripts, dependency management, and tests.

Work Style

  • Keep changes focused on one problem.
  • Prefer existing patterns in the file or nearby module.
  • Avoid unrelated formatting, renames, dependency changes, or broad rewrites.
  • Add or update tests when behavior changes.
  • Update docs when setup, commands, provider behavior, or user-facing behavior changes.
  • For new features, larger refactors, dependencies, or runtime changes, follow the issue-first guidance in CONTRIBUTING.md.

Stack And Conventions

  • TypeScript with strict mode and ESM imports.
  • React + Ink for terminal UI.
  • Bun lockfile and Bun scripts for development workflows.
  • Node runtime for the built CLI.
  • Python exists for legacy/local-provider helper code. Do not add new Python code or expand Python-based features unless a maintainer explicitly approves that direction.

Common libraries and patterns:

  • chalk for terminal color.
  • commander for CLI argument parsing.
  • execa for child processes.
  • Existing service, provider, settings, permission, and UI patterns over new abstractions.

Repository Map

  • src/commands/ - slash and CLI command implementations.
  • src/components/ - React/Ink UI components.
  • src/services/ - API, MCP, OAuth, wiki, voice, and other service integrations.
  • src/tools/ - tool implementations.
  • src/utils/ - shared utilities.
  • `src/integration...

Files:

  • README.md
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
  • tests/sdk/query-happy-path.test.ts
  • src/query/agentStepLimit.test.ts
  • src/query.ts
**/*

⚙️ CodeRabbit configuration file

**/*: Apply the OpenClaude maintainer review rubric from AGENTS.md. Review the current diff, not stale discussion context. Separate real blockers from suggestions. Do not request changes for vague style churn. Treat approval as merge-ready from CodeRabbit's side, pending required human review and GitHub Checks. If checks are failing or unavailable, say so clearly instead of implying the PR is fully ready.

Files:

  • README.md
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
  • tests/sdk/query-happy-path.test.ts
  • src/query/agentStepLimit.test.ts
  • src/query.ts
{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}

⚙️ CodeRabbit configuration file

{README.md,CONTRIBUTING.md,docs/**,.github/pull_request_template.md}: Review docs for accuracy against current code behavior. Flag security or provider claims that overpromise, stale install commands, missing setup caveats, and instructions that could push users toward unsafe credential handling. Keep purely wording-level suggestions non-blocking.

Files:

  • README.md
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript with strict mode and ESM imports

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
  • src/query/agentStepLimit.test.ts
  • src/query.ts
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use chalk for terminal color in CLI code

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
{src/commands/**/*.ts,src/entrypoints/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use commander for CLI argument parsing

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Add or update tests when the change affects behavior

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/query-happy-path.test.ts
  • src/query/agentStepLimit.test.ts
**/*.test.{ts,tsx,js}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Test the exact provider/model path you changed when possible

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/query-happy-path.test.ts
  • src/query/agentStepLimit.test.ts
**/*.{ts,tsx,js,jsx,py}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Keep comments useful and concise

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
  • tests/sdk/query-happy-path.test.ts
  • src/query/agentStepLimit.test.ts
  • src/query.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Follow TypeScript strict mode and type safety practices by running typecheck before submitting

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
  • tests/sdk/query-happy-path.test.ts
  • src/query/agentStepLimit.test.ts
  • src/query.ts
src/{components/permissions,utils/permissions,hooks/toolPermission,tools,entrypoints/sdk}/**

⚙️ CodeRabbit configuration file

src/{components/permissions,utils/permissions,hooks/toolPermission,tools,entrypoints/sdk}/**: Review permission prompts, auto-allow logic, sandbox behavior, SDK permission schemas, shell/PowerShell execution, and background execution paths as security-sensitive. Block on bypasses, unclear trust boundaries, unsafe path handling, missing user visibility, or changes that broaden allowed behavior without an explicit maintainer decision.

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}

⚙️ CodeRabbit configuration file

{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}: Review install, launcher, build, packaging, startup, and entrypoint changes for cross-platform compatibility, tracked-source rewrites, env/config precedence, and release safety. Block on changes that can break Windows/macOS/Linux startup or publish unexpected artifacts.

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/query.ts
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}

⚙️ CodeRabbit configuration file

{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}: Review tests for meaningful coverage of the changed behavior, isolation of global/env/config state, async cleanup, fake timers, provider profile leaks, and Windows-compatible assumptions. Block when risky runtime changes lack focused regression coverage or tests assert implementation details while missing the user-visible behavior.

Files:

  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/query-happy-path.test.ts
  • src/query/agentStepLimit.test.ts
🔇 Additional comments (2)
src/query.ts (1)

52-52: LGTM!

Also applies to: 264-300, 2069-2074

src/query/agentStepLimit.test.ts (1)

266-271: LGTM!

Also applies to: 408-413, 484-489, 519-519, 536-573, 576-662

Comment thread tests/sdk/query-happy-path.test.ts
@chioarub
chioarub force-pushed the feat/agent-step-limits branch from 824a85f to 0c343cc Compare June 29, 2026 14:15
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 29, 2026

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I found a couple of issues that need to be addressed before this is ready.

Findings

  • [P2] Complete CodeRabbit's request to make SDK agent descriptions optional
    src/entrypoints/sdk/query.ts:154
    buildSdkUserAgents() accepts an SDK agent without description and falls back to the agent name, and the new missingDescription regression test locks that runtime behavior in. The public SDK query option type still requires agents[*].description here and in the exported src/entrypoints/sdk.d.ts, so strict TypeScript callers cannot use this valid runtime shape without casts. Please complete the CodeRabbit request by making the SDK agents description field optional everywhere this query option type is exposed/generated.

  • [P2] Thread SDK agent injection through persistent SDK sessions
    src/entrypoints/sdk/v2.ts:270
    The one-shot SDK query path now builds SDK-provided agents with buildSdkUserAgents(), merges them into both activeAgents and allAgents, and preserves maxSteps before calling injectAgents(). The persistent SDK session path still only loads filesystem agents from getAgentDefinitionsWithOverrides() and injects agentDefs.activeAgents, so SDK-provided agent definitions do not participate in unstable_v2_createSession(...).sendMessage() and therefore cannot use the new maxSteps support there. Please apply the same SDK-agent merge/injection path to persistent SDK sessions or clearly keep this feature out of that API surface.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/entrypoints/sdk/agentDefinitions.ts (1)

64-89: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reject invalid maxSteps/maxTurns instead of dropping them.

Deleting these fields turns a malformed cap into an uncapped agent, so values like 0, 1.5, or JS-typed garbage quietly bypass the new step/turn limit instead of surfacing an agent_load_failure. Let schema validation reject the definition, or report the invalid field here, but don't strip it.

Proposed fix
     const candidate = def as Partial<SdkAgentDefinitionInput>
     const normalizedDef = {
       ...candidate,
       description: candidate.description ?? name,
     }
     const maxTurns = normalizePositiveInteger(candidate.maxTurns)
     const maxSteps = normalizePositiveInteger(candidate.maxSteps)
     if (candidate.maxTurns !== undefined) {
-      if (maxTurns === undefined) {
-        delete normalizedDef.maxTurns
-      } else {
-        normalizedDef.maxTurns = maxTurns
-      }
+      if (maxTurns === undefined) {
+        reportInvalidAgent(name, 'maxTurns must be a positive integer')
+        return []
+      }
+      normalizedDef.maxTurns = maxTurns
     }
     if (candidate.maxSteps !== undefined) {
-      if (maxSteps === undefined) {
-        delete normalizedDef.maxSteps
-      } else {
-        normalizedDef.maxSteps = maxSteps
-      }
+      if (maxSteps === undefined) {
+        reportInvalidAgent(name, 'maxSteps must be a positive integer')
+        return []
+      }
+      normalizedDef.maxSteps = maxSteps
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/entrypoints/sdk/agentDefinitions.ts` around lines 64 - 89, The
normalization in agentDefinitions should not delete invalid maxTurns/maxSteps
values before validation, because that converts malformed caps into uncapped
agents. In the candidate/normalizedDef flow, keep the original values on the
object and let AgentDefinitionSchema().safeParse reject bad inputs, or
explicitly call reportInvalidAgent with the offending field when
normalizePositiveInteger returns undefined for a provided value. Ensure the fix
is applied in the parsing path around normalizePositiveInteger, normalizedDef,
and reportInvalidAgent so invalid limits surface as agent_load_failure instead
of being silently dropped.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/entrypoints/sdk/agentDefinitions.ts`:
- Around line 64-89: The normalization in agentDefinitions should not delete
invalid maxTurns/maxSteps values before validation, because that converts
malformed caps into uncapped agents. In the candidate/normalizedDef flow, keep
the original values on the object and let AgentDefinitionSchema().safeParse
reject bad inputs, or explicitly call reportInvalidAgent with the offending
field when normalizePositiveInteger returns undefined for a provided value.
Ensure the fix is applied in the parsing path around normalizePositiveInteger,
normalizedDef, and reportInvalidAgent so invalid limits surface as
agent_load_failure instead of being silently dropped.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 69d3e608-37d7-4003-8e80-a53720aac72c

📥 Commits

Reviewing files that changed from the base of the PR and between 0c343cc and 0f1ebe1.

📒 Files selected for processing (20)
  • src/components/ContextVisualization.tsx
  • src/components/agents/AgentsList.tsx
  • src/components/agents/AgentsMenu.test.tsx
  • src/components/agents/AgentsMenu.tsx
  • src/components/agents/agentFileUtils.ts
  • src/components/agents/types.ts
  • src/components/agents/utils.ts
  • src/entrypoints/sdk.d.ts
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
  • src/entrypoints/sdk/coreSchemas.ts
  • src/entrypoints/sdk/query.ts
  • src/entrypoints/sdk/v2.ts
  • src/tools/AgentTool/agentDisplay.ts
  • src/tools/AgentTool/loadAgentsDir.ts
  • src/utils/analyzeContext.ts
  • src/utils/settings/constants.ts
  • tests/sdk/package-consumer-types.test.ts
  • tests/sdk/query-happy-path.test.ts
  • tests/sdk/sdk-v2-lifecycle.test.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (15)
src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript with strict mode and ESM imports

Files:

  • src/components/agents/AgentsList.tsx
  • src/utils/settings/constants.ts
  • src/components/agents/agentFileUtils.ts
  • src/components/agents/types.ts
  • src/utils/analyzeContext.ts
  • src/components/agents/utils.ts
  • src/components/agents/AgentsMenu.test.tsx
  • src/entrypoints/sdk/coreSchemas.ts
  • src/entrypoints/sdk.d.ts
  • src/tools/AgentTool/agentDisplay.ts
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/components/agents/AgentsMenu.tsx
  • src/entrypoints/sdk/v2.ts
  • src/components/ContextVisualization.tsx
  • src/entrypoints/sdk/query.ts
  • src/tools/AgentTool/loadAgentsDir.ts
  • src/entrypoints/sdk/agentDefinitions.ts
src/components/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use React + Ink for terminal UI implementations

Files:

  • src/components/agents/AgentsList.tsx
  • src/components/agents/agentFileUtils.ts
  • src/components/agents/types.ts
  • src/components/agents/utils.ts
  • src/components/agents/AgentsMenu.test.tsx
  • src/components/agents/AgentsMenu.tsx
  • src/components/ContextVisualization.tsx
**/*.{ts,tsx,js,jsx,py,json,md}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Follow the existing code style in the touched files

Files:

  • src/components/agents/AgentsList.tsx
  • src/utils/settings/constants.ts
  • src/components/agents/agentFileUtils.ts
  • src/components/agents/types.ts
  • src/utils/analyzeContext.ts
  • src/components/agents/utils.ts
  • tests/sdk/package-consumer-types.test.ts
  • src/components/agents/AgentsMenu.test.tsx
  • src/entrypoints/sdk/coreSchemas.ts
  • src/entrypoints/sdk.d.ts
  • src/tools/AgentTool/agentDisplay.ts
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/components/agents/AgentsMenu.tsx
  • tests/sdk/sdk-v2-lifecycle.test.ts
  • src/entrypoints/sdk/v2.ts
  • src/components/ContextVisualization.tsx
  • src/entrypoints/sdk/query.ts
  • src/tools/AgentTool/loadAgentsDir.ts
  • tests/sdk/query-happy-path.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
**/*.{ts,tsx,js,jsx,py}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Keep comments useful and concise

Files:

  • src/components/agents/AgentsList.tsx
  • src/utils/settings/constants.ts
  • src/components/agents/agentFileUtils.ts
  • src/components/agents/types.ts
  • src/utils/analyzeContext.ts
  • src/components/agents/utils.ts
  • tests/sdk/package-consumer-types.test.ts
  • src/components/agents/AgentsMenu.test.tsx
  • src/entrypoints/sdk/coreSchemas.ts
  • src/entrypoints/sdk.d.ts
  • src/tools/AgentTool/agentDisplay.ts
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/components/agents/AgentsMenu.tsx
  • tests/sdk/sdk-v2-lifecycle.test.ts
  • src/entrypoints/sdk/v2.ts
  • src/components/ContextVisualization.tsx
  • src/entrypoints/sdk/query.ts
  • src/tools/AgentTool/loadAgentsDir.ts
  • tests/sdk/query-happy-path.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Follow TypeScript strict mode and type safety practices by running typecheck before submitting

Files:

  • src/components/agents/AgentsList.tsx
  • src/utils/settings/constants.ts
  • src/components/agents/agentFileUtils.ts
  • src/components/agents/types.ts
  • src/utils/analyzeContext.ts
  • src/components/agents/utils.ts
  • tests/sdk/package-consumer-types.test.ts
  • src/components/agents/AgentsMenu.test.tsx
  • src/entrypoints/sdk/coreSchemas.ts
  • src/entrypoints/sdk.d.ts
  • src/tools/AgentTool/agentDisplay.ts
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/components/agents/AgentsMenu.tsx
  • tests/sdk/sdk-v2-lifecycle.test.ts
  • src/entrypoints/sdk/v2.ts
  • src/components/ContextVisualization.tsx
  • src/entrypoints/sdk/query.ts
  • src/tools/AgentTool/loadAgentsDir.ts
  • tests/sdk/query-happy-path.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
**

⚙️ CodeRabbit configuration file

**: # AGENTS.md - AI Agent Coding Guide

This guide is for AI coding agents working in the OpenClaude repository. Read it before changing code, and also follow CONTRIBUTING.md for contributor policy, PR expectations, review follow-up, and project scope.

Project Snapshot

OpenClaude is a coding-agent CLI for cloud and local model providers. It supports OpenAI-compatible APIs, Anthropic, Gemini, DeepSeek, Ollama, MCP, local backends, slash commands, tools, agents, and a React/Ink terminal UI.

The installed CLI runs on Node.js >=22.0.0. Bun is used for source builds, scripts, dependency management, and tests.

Work Style

  • Keep changes focused on one problem.
  • Prefer existing patterns in the file or nearby module.
  • Avoid unrelated formatting, renames, dependency changes, or broad rewrites.
  • Add or update tests when behavior changes.
  • Update docs when setup, commands, provider behavior, or user-facing behavior changes.
  • For new features, larger refactors, dependencies, or runtime changes, follow the issue-first guidance in CONTRIBUTING.md.

Stack And Conventions

  • TypeScript with strict mode and ESM imports.
  • React + Ink for terminal UI.
  • Bun lockfile and Bun scripts for development workflows.
  • Node runtime for the built CLI.
  • Python exists for legacy/local-provider helper code. Do not add new Python code or expand Python-based features unless a maintainer explicitly approves that direction.

Common libraries and patterns:

  • chalk for terminal color.
  • commander for CLI argument parsing.
  • execa for child processes.
  • Existing service, provider, settings, permission, and UI patterns over new abstractions.

Repository Map

  • src/commands/ - slash and CLI command implementations.
  • src/components/ - React/Ink UI components.
  • src/services/ - API, MCP, OAuth, wiki, voice, and other service integrations.
  • src/tools/ - tool implementations.
  • src/utils/ - shared utilities.
  • `src/integration...

Files:

  • src/components/agents/AgentsList.tsx
  • src/utils/settings/constants.ts
  • src/components/agents/agentFileUtils.ts
  • src/components/agents/types.ts
  • src/utils/analyzeContext.ts
  • src/components/agents/utils.ts
  • tests/sdk/package-consumer-types.test.ts
  • src/components/agents/AgentsMenu.test.tsx
  • src/entrypoints/sdk/coreSchemas.ts
  • src/entrypoints/sdk.d.ts
  • src/tools/AgentTool/agentDisplay.ts
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/components/agents/AgentsMenu.tsx
  • tests/sdk/sdk-v2-lifecycle.test.ts
  • src/entrypoints/sdk/v2.ts
  • src/components/ContextVisualization.tsx
  • src/entrypoints/sdk/query.ts
  • src/tools/AgentTool/loadAgentsDir.ts
  • tests/sdk/query-happy-path.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
**/*

⚙️ CodeRabbit configuration file

**/*: Apply the OpenClaude maintainer review rubric from AGENTS.md. Review the current diff, not stale discussion context. Separate real blockers from suggestions. Do not request changes for vague style churn. Treat approval as merge-ready from CodeRabbit's side, pending required human review and GitHub Checks. If checks are failing or unavailable, say so clearly instead of implying the PR is fully ready.

Files:

  • src/components/agents/AgentsList.tsx
  • src/utils/settings/constants.ts
  • src/components/agents/agentFileUtils.ts
  • src/components/agents/types.ts
  • src/utils/analyzeContext.ts
  • src/components/agents/utils.ts
  • tests/sdk/package-consumer-types.test.ts
  • src/components/agents/AgentsMenu.test.tsx
  • src/entrypoints/sdk/coreSchemas.ts
  • src/entrypoints/sdk.d.ts
  • src/tools/AgentTool/agentDisplay.ts
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/components/agents/AgentsMenu.tsx
  • tests/sdk/sdk-v2-lifecycle.test.ts
  • src/entrypoints/sdk/v2.ts
  • src/components/ContextVisualization.tsx
  • src/entrypoints/sdk/query.ts
  • src/tools/AgentTool/loadAgentsDir.ts
  • tests/sdk/query-happy-path.test.ts
  • src/entrypoints/sdk/agentDefinitions.ts
{src/services/**/*.ts,src/utils/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use execa for child processes

Files:

  • src/utils/settings/constants.ts
  • src/utils/analyzeContext.ts
**/*.test.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Add or update tests when the change affects behavior

Files:

  • tests/sdk/package-consumer-types.test.ts
  • src/components/agents/AgentsMenu.test.tsx
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/sdk-v2-lifecycle.test.ts
  • tests/sdk/query-happy-path.test.ts
**/*.test.{ts,tsx,js}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Test the exact provider/model path you changed when possible

Files:

  • tests/sdk/package-consumer-types.test.ts
  • src/components/agents/AgentsMenu.test.tsx
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/sdk-v2-lifecycle.test.ts
  • tests/sdk/query-happy-path.test.ts
{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}

⚙️ CodeRabbit configuration file

{src/**/*.test.ts,src/**/*.test.tsx,tests/**,scripts/**/*.test.ts,vscode-extension/**/*.test.js}: Review tests for meaningful coverage of the changed behavior, isolation of global/env/config state, async cleanup, fake timers, provider profile leaks, and Windows-compatible assumptions. Block when risky runtime changes lack focused regression coverage or tests assert implementation details while missing the user-visible behavior.

Files:

  • tests/sdk/package-consumer-types.test.ts
  • src/components/agents/AgentsMenu.test.tsx
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • tests/sdk/sdk-v2-lifecycle.test.ts
  • tests/sdk/query-happy-path.test.ts
{src/commands/**/*.ts,src/services/**/*.ts,src/entrypoints/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use chalk for terminal color in CLI code

Files:

  • src/entrypoints/sdk/coreSchemas.ts
  • src/entrypoints/sdk.d.ts
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/v2.ts
  • src/entrypoints/sdk/query.ts
  • src/entrypoints/sdk/agentDefinitions.ts
{src/commands/**/*.ts,src/entrypoints/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Use commander for CLI argument parsing

Files:

  • src/entrypoints/sdk/coreSchemas.ts
  • src/entrypoints/sdk.d.ts
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/v2.ts
  • src/entrypoints/sdk/query.ts
  • src/entrypoints/sdk/agentDefinitions.ts
src/{components/permissions,utils/permissions,hooks/toolPermission,tools,entrypoints/sdk}/**

⚙️ CodeRabbit configuration file

src/{components/permissions,utils/permissions,hooks/toolPermission,tools,entrypoints/sdk}/**: Review permission prompts, auto-allow logic, sandbox behavior, SDK permission schemas, shell/PowerShell execution, and background execution paths as security-sensitive. Block on bypasses, unclear trust boundaries, unsafe path handling, missing user visibility, or changes that broaden allowed behavior without an explicit maintainer decision.

Files:

  • src/entrypoints/sdk/coreSchemas.ts
  • src/tools/AgentTool/agentDisplay.ts
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/v2.ts
  • src/entrypoints/sdk/query.ts
  • src/tools/AgentTool/loadAgentsDir.ts
  • src/entrypoints/sdk/agentDefinitions.ts
{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}

⚙️ CodeRabbit configuration file

{bin/**,scripts/**,package.json,src/setup.ts,src/main.tsx,src/entrypoints/**}: Review install, launcher, build, packaging, startup, and entrypoint changes for cross-platform compatibility, tracked-source rewrites, env/config precedence, and release safety. Block on changes that can break Windows/macOS/Linux startup or publish unexpected artifacts.

Files:

  • src/entrypoints/sdk/coreSchemas.ts
  • src/entrypoints/sdk.d.ts
  • src/entrypoints/sdk/agentDefinitions.test.ts
  • src/entrypoints/sdk/v2.ts
  • src/entrypoints/sdk/query.ts
  • src/entrypoints/sdk/agentDefinitions.ts
🔇 Additional comments (7)
src/components/agents/agentFileUtils.ts (1)

113-115: LGTM!

Also applies to: 150-152

src/components/agents/types.ts (1)

16-16: LGTM!

src/components/agents/AgentsMenu.test.tsx (1)

383-455: LGTM!

Also applies to: 457-496

src/components/agents/AgentsMenu.tsx (1)

138-138: LGTM!

Also applies to: 206-206, 324-324

src/entrypoints/sdk/v2.ts (1)

115-116: LGTM!

Also applies to: 279-338, 351-351, 365-365

src/tools/AgentTool/loadAgentsDir.ts (1)

151-155: LGTM!

Also applies to: 168-168, 181-185, 210-218

tests/sdk/sdk-v2-lifecycle.test.ts (1)

351-353: 🎯 Functional Correctness

No issue here The cast is only line-wrapped; there isn’t a duplicated expression.

			> Likely an incorrect or invalid review comment.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 29, 2026
@chioarub
chioarub requested a review from jatmn June 29, 2026 20:25

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Summary

CodeRabbit has a still-valid requested change on this PR, and the contribution guide asks authors to address automated review findings before waiting for maintainer review. Please complete that item as part of the next update.

Findings

  • [P2] Complete CodeRabbit's request to report invalid SDK step limits
    src/entrypoints/sdk/agentDefinitions.ts:78
    CodeRabbit's SDK validation request is still valid: buildSdkUserAgents normalizes maxSteps/maxTurns by deleting invalid provided values before AgentDefinitionSchema().safeParse() runs, so SDK agents with values like maxSteps: 0, -1, 1.5, or '2' are still injected as uncapped agents instead of emitting the agent_load_failure path wired in query.ts and v2.ts. That leaves SDK callers with no signal that their configured cap was ignored, while the PR claims SDK definitions get positive-integer validation. Please keep the offending values visible to schema validation or explicitly report them via reportInvalidAgent before injecting the agent.

@jatmn jatmn left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the update. I rechecked the previously discussed paths and do not see any remaining actionable issues from my side.

@kevincodex1 LGTM

@kevincodex1 kevincodex1 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lgtm

@kevincodex1
kevincodex1 merged commit 1827d84 into Twigpine:main Jun 30, 2026
4 checks passed
@chioarub
chioarub deleted the feat/agent-step-limits branch June 30, 2026 05:45
hotmanxp added a commit to hotmanxp/openclaude that referenced this pull request Jul 1, 2026
… limits

Port the upstream commit 1827d84 (Twigpine#1815) to OpenCC's architecture by
functional sync instead of direct cherry-pick (the cherry-pick conflicts
4 modify/delete on OpenCC-deleted SDK entrypoints + 4 content conflicts).

This commit covers parsing, types, helper wiring, and the constants file
out of upstream's ~2700-line patch. The core enforcement loop in
src/tools/AgentTool/runAgent.ts (caller-side agentStepLimit injection)
and the regression test src/query/agentStepLimit.test.ts remain — they
need a follow-up commit to land.

Ported:
- src/query/agentStepLimit.ts: AGENT_STEP_LIMIT_TOOL_RESULT_PREFIX constant
- src/query.ts: agentStepLimit QueryParams field, State field, normalize,
  counter increment, transition carry-through, toolsForModel gating when
  summaryRequested
- src/query/toolFailureLoopGuard.ts: interaction with step-limit nudges
- src/services/api/claude.ts: agent_step_limit terminal reason recording
- src/tools/AgentTool/agentToolUtils.ts: countToolUses helper
- src/tools/AgentTool/loadAgentsDir.ts: markdown agent maxSteps parse
- src/types/message.ts: isAgentStepLimitToolResult + sourceToolAssistantUUID
- src/utils/frontmatterParser.ts: maxSteps frontmatter extraction
- src/utils/messages.ts: createAssistantMessage helper
- src/utils/plugins/loadPluginAgents.ts: plugin agent maxSteps parse

Deliberately skipped (OpenCC has different SDK architecture):
- src/entrypoints/sdk/{query.ts, v2.ts, agentDefinitions.ts}*
- tests/sdk/*.{test.ts}

Co-Authored-By: Claude <noreply@anthropic.com>
hotmanxp added a commit to hotmanxp/openclaude that referenced this pull request Jul 1, 2026
…et transitions

Carry the agentStepLimit state through the stop_hook_blocking and
token_budget_continuation transitions in queryLoop, matching upstream's
pattern of forwarding step-limit state on every State-restart path so
the counter survives. Continues the partial sync of Twigpine#1815.

Co-Authored-By: Claude <noreply@anthropic.com>
hotmanxp added a commit to hotmanxp/openclaude that referenced this pull request Jul 1, 2026
Closes the remaining 30% of the upstream 1827d84 functional sync:

- src/tools/AgentTool/runAgent.ts: caller-side agentStepLimit injection
  into QueryParams at subagent invocation. Resolve configuredMaxSteps
  from the agent definition, pass `{ maxSteps, agentType }` only when
  the agent has an explicit positive maxSteps. Logs agent_step_limit
  terminal-reason outcomes.
- src/query/agentStepLimit.test.ts (NEW, 693 lines): full port of
  upstream's 8 regression cases — default behavior, invalid values,
  multi-turn accumulation, plugin parsing, failure-loop interaction,
  summary-tool blocking. Adapted to OpenCC's bun:test runner and
  user-message shape via @ts-nocheck + targeted any-casts (mirroring
  toolFailureLoopGuard.test.ts convention).
- src/query/transitions.ts (NEW): Terminal + Continue union types with
  the agent_step_limit variant. Replaces ad-hoc inline return shapes.
- src/query.ts: increments agentStepLimit state-stamp on remaining
  state-restart paths (image_error, prompt_too_long, hard_max_query).

Skipped (no-op for OpenCC, phantom SDK variants):
- src/utils/settings/constants.ts: upstream adds 'sdk' to SettingSource;
  OpenCC has no SDK entrypoint, so the variant is never produced.
- src/utils/analyzeContext.ts: same reason — upstream's 'sdk' source
  variant never appears in OpenCC analyzeContext output.

Closes the functional-sync port of Twigpine#1815. Without runAgent.ts injection
the agent_step_limit machinery parsed in 3ed0b83 was inert; this commit
wires it end-to-end.

Co-Authored-By: Claude <noreply@anthropic.com>
hotmanxp added a commit to hotmanxp/openclaude that referenced this pull request Jul 5, 2026
@coderabbitai coderabbitai Bot mentioned this pull request Jul 5, 2026
6 of 7 tasks
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.

3 participants