* Improve OpenRouter sticky session routing
OpenRouter prompt caching was getting weaker cache hit rates because requests did not include a stable session_id. Without that identifier, OpenRouter can route consecutive turns away from the same upstream cache context even when cache_control is present, causing more fresh input billing.
Propagate explicit runtime sessionId metadata from agents into model requests without synthesizing fallback session or conversation ids. Add provider metadata for sticky sessions so OpenRouter maps metadata.sessionId to the JSON body session_id field, while keeping the mechanism extensible for header-based providers.
Apply sticky-session metadata in the AI SDK provider fetch wrapper, preserving explicit wire values when callers already set them. Move trimNonEmpty and omitUndefinedValues into @cline/shared for reuse, and cover the JSON-body, header, and no-fallback paths with tests.
* Tighten sticky session fetch body handling
Treat init.body null as an explicit no-body override so the sticky-session wrapper does not inspect or parse a Request body that the caller has intentionally overridden.
Model fetch body text by source, which removes the unreachable JSON-body injection branch and makes the Request rewrite path explicit. Also type the provider fetch mocks so sticky-session assertions compile cleanly in editors.
* merges model-handle default metadata with per-request metadata
* feat(hub): add connector configure path and share catalog via @cline/shared
Add connector.channels/configure/delete_config Hub commands that persist
connector settings to disk without starting connector processes or calling
provider auth APIs. This means settings (including tokens) are saved as-is
without verification; callers are responsible for supplying valid values.
Shared catalog and platform definitions:
- Move ConnectorCatalogEntry, CONNECTOR_CATALOG, listConnectorCatalog, and
all ConnectorPlatformDef/FieldDef/SecurityDef types + CONNECTOR_PLATFORMS
into sdk/packages/shared/src/connectors/platforms.ts
- Export everything from @cline/shared index so CLI and Hub use the same
definitions without duplication
- Reduce apps/cli/src/connectors/catalog.ts and
apps/cli/src/wizards/connect/platforms.ts to thin re-export shims that
preserve existing CLI import paths
New Hub connector handlers (sdk/packages/core):
- connector-handlers.ts: handles connector.channels (list available/active/
configured), connector.configure (validate fields and write settings.json
under ~/.cline/data/connectors/), connector.delete_config (remove entry
and clean up empty file)
- Settings are stored as ConnectorSettingsFile (version 1) at
~/.cline/data/connectors/settings.json; reads are lenient/defensive
- Wire handlers into hub-server-transport.ts dispatch switch
- connector-handlers.test.ts: unit tests for configure, channels, and
delete_config covering field validation, conditional fields, security
constraints, and settings round-trips
Hub WebSocket auth helpers (hub-websocket-server.ts):
- Extract isLocalHubHostName / isLocalHubOrigin as named, tested exports
- Allow unauthenticated WebSocket upgrades from local origins (localhost,
127.0.0.1, ::1) so the Hub UI can connect without an auth token
- hub-websocket-server.test.ts: extend tests to cover new local-origin logic
Add connector.channels, connector.configure, connector.delete_config to
HubCommandName union in sdk/packages/shared/src/hub.ts
* apply feedback
* export connector settings json path
* apply feedback from robin
* fix(sdk): resolve Cline Z.ai model metadata aliases
* fix(sdk): preserve Cline model alias overrides
* test(sdk): update Cline provider model list expectation
* fix(sdk): default-on tool result truncation, name fallback, tool_use budget accounting
- Truncate every tool result (MCP/custom tools included), not just an allowlist
- Resolve tool names from tool_result.name when the paired tool_use is gone
- Count tool_use.input strings toward the aggregate provider request budget
- Protect any binary carrier block ({type, data}) from truncation, not just images
- Don't let failSession cleanup errors mask the original turn error
* fix(sdk): tighten MessageBuilder limits with named options and env overrides
Folds #11474 into the default-on truncation branch and addresses review
feedback from both PRs:
- per-result tool cap drops to 8k chars; MessageBuilderOptions constructor
with CLINE_MESSAGE_BUILDER_* env overrides for A/B testing
- env parsing is positive-only so '=0' cannot silently disable a limit
(greptile on #11474)
- aggregate budget stays at 6MB: budget truncation rewrites mid-transcript
bytes and breaks provider prefix caching, so it must stay a rare overflow
valve rather than the steady state (johnwschoi on #11474)
- user file attachments get a dedicated 50k cap instead of inheriting the
aggressive tool-result cap (codex on #11474)
- isBinaryContentLike restricted to known binary block types so textual
{type, data} payloads can no longer dodge every cap (codex/greptile)
- tool_use.input strings become last-resort budget truncation candidates,
making the aggregate budget reclaimable when oversized model-generated
arguments carry the overflow (robinnewhouse/greptile)
* fix(sdk): constrain binary tool result truncation
* style(sdk): remove disallowed comment formatting
* Revert "style(sdk): remove disallowed comment formatting"
This reverts commit 9d8b66726d.
---------
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
* Make sections expandable and add ClinePass
* fix label
* Map clinePass models to clinePass and the rest to cline
* gate the models behind the feature flag
* Do not allow custom model on cline pass
* Do not show the count on the mode list
* fix clinepass model list
* fix focus when expanding a section
* update the model data when the provider doesn't match
* Add ClinePass to the onboarding screen
* Fix the auth flow not starting
* Hide option behind a feature flag
* Update icon
* Remove unrelated changes
* Hide the custom model id
* fix model names
* remove custom model id option
* fix tests
* Fix names
* Display the clinepass models in the onboarding
* Throw a specific error when the user isn't subscribed
* properly render the error message
* fix error detection
* refactor
* Update the ResponseErrorHandler type
* re-add trailing slash
* Make sections expandable and add ClinePass
* fix label
* Map clinePass models to clinePass and the rest to cline
* gate the models behind the feature flag
* Do not allow custom model on cline pass
* Do not show the count on the mode list
* fix clinepass model list
* fix focus when expanding a section
* update the model data when the provider doesn't match
* Add ClinePass to the onboarding screen
* Fix the auth flow not starting
* Hide option behind a feature flag
* Update icon
* Remove unrelated changes
* Hide the custom model id
* fix model names
* remove custom model id option
* fix tests
* Fix names
* Display the clinepass models in the onboarding
* Make sections expandable and add ClinePass
* fix label
* Map clinePass models to clinePass and the rest to cline
* gate the models behind the feature flag
* Do not allow custom model on cline pass
* Do not show the count on the mode list
* fix clinepass model list
* fix focus when expanding a section
* update the model data when the provider doesn't match
* Update sdk/packages/core/src/services/llms/cline-recommended-models.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* style: format Cline recommended models fallback
* Build models
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
* fix(sdk): search output cap + bash executor fixes (follow-up to #11480)
Slimmed from the original revision: the aggregate per-call output budget
is deferred to its own follow-up PR. What remains:
- cap search_codebase output at 48k chars per query with a middle-cut
notice teaching the model to narrow the pattern (robinnewhouse's
finding on #11480 — search was the last uncapped tool)
- rename bash executor maxOutputBytes -> maxOutputChars; the limit was
always enforced in characters. Deprecated alias retained; stale
@default annotation fixed
- flush the rolling collector's StringDecoder at end-of-stream so
trailing incomplete multibyte sequences are not silently dropped
(greptile's finding on #11480)
- decouple output-limits comments from MessageBuilder's specific
backstop value; the durable invariant is that truncation notices live
in the preserved head/tail of an entry
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
🔮 View transcript: https://agentlogs.beatrixwoo.workers.dev/s/ygz2qho62ub6o8v1zhjvdktt
* test(sdk): cover search output cap
---------
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
* Centralize OAuth management to the SDK
* Update mock
* Cleanup TUI cline-account logic
* clean save credentails
* Remove unused code
* Reduce mocks
* use normalizeStoredAccessToken
* Add Cline Pass
* Properly read storageProviderId
* Use the name for the model generation
* Use the model for the capabilities lookup
* Fix capability discovery
* Fix getLastUsedProviderSettings
* remove the provider id from the resolveWithSingleFlight return
* Fix tests
* Remove the entry.name check
* Execute model API calls separetely
* Hide Cline Pass pricing
* Display cline-pass only if the feature flag is enabled
* unselect cline pass when the feature flag is off
* Store and read feature flag cache
* Add comment
* Do not return userId
* fix tests
* Revert unrelated changes
* Centralize OAuth management to the SDK
* Update mock
* Cleanup TUI cline-account logic
* clean save credentails
* Remove unused code
* Reduce mocks
* use normalizeStoredAccessToken
* Add Cline Pass
* Properly read storageProviderId
* Use the name for the model generation
* Use the model for the capabilities lookup
* Fix capability discovery
* Fix getLastUsedProviderSettings
* remove the provider id from the resolveWithSingleFlight return
* Fix tests
* Remove the entry.name check
* Execute model API calls separetely
* Hide Cline Pass pricing
* update model list
* Address PR feedback
* revert unrelated changes
* Update comment
* Update check
Tool outputs previously entered conversation history nearly unbounded
(1MB command output, whole-file reads up to 10MB) and were re-sent on
every subsequent request. Evals showed single observations of 350KB-3.2MB
dominating token spend versus opencode's 50KB-bounded observations.
- run_commands: combined stdout/stderr capped at 48,000 chars with
head+tail sampling (middle elided with a notice reporting total size),
since failures usually live at the end of build/test output. Failing
commands carry the notice in stderr errors too. Streams decode through
StringDecoder so multibyte chars split across chunks stay intact.
- read_files: whole-file and oversized-range reads windowed to 2,000
lines / 48,000 chars with a notice reporting total line count and how
to paginate via start_line/end_line. Per-line cap of 2,000 chars
defangs minified files. In-window ranged reads are byte-for-byte
unchanged; the 10MB stat guard stays.
- Shared constants live in executors/output-limits.ts, sized below
MessageBuilder's 50,000 per-string backstop so source notices survive
provider-request truncation intact. Tool descriptions document the
windowing so the model pages or filters instead of retrying.
Companion to #11463/#11465: those bound provider requests at build time;
this bounds what enters history at the source and gives the model a
recovery path.
* Introduce PostHog as a Feature Flag provider
* Set-up auth after login
* Update the context when something changes in the CLI
* Make the distinctId not be optional
* Dispose of the feature flag service
* Remove the distinctId from the options
* get rid of isSharedClient
* Remove timeoutMs from the posthog options
* Rename functions to not refer cli
* Change the PostHogFeatureFlagsProvider API
* Add the FeatureFlagService to the SDK
* Fix comments
* Dispose of the telemetry service
* Dispose of the feature flag service
* Address PR feedback
* Stop the polling early if a new one is triggered with another user id
* Address PR feedback
* Dispose of the feature flag service
---------
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
* test(sdk): add regression tests for structured ToolOperationResult truncation
MessageBuilder tests only covered string and {type:
🔮 View transcript: https://agentlogs.beatrixwoo.workers.dev/s/mrbt2b39jfn370scr4g0ivzo"text"} tool-result
content, not the structured ToolOperationResult[] shape the default tools
(run_commands, read_files, search_codebase) actually emit. Those entries
are plain {query, result, success} objects with no type discriminator, so
the token-bloat path they create was unprotected by tests.
Adds regression tests using the real structured shape: huge result, huge
query, huge read_files payload, aggregate budget across multiple results,
mutation safety, and provider-formatted AI SDK payload size. Assertions
are on actual serialized payload sizes, not transcript shape.
The new tests fail at this commit by design; the following commit makes
them pass.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(sdk): truncate structured ToolOperationResult strings in MessageBuilder
The runtime stores structured tool outputs (ToolOperationResult[] from
run_commands/read_files/search_codebase) directly as the tool_result
content array (agentPartToContentBlock casts the array straight through).
Those entries have no type discriminator, so MessageBuilder's per-result
truncation, aggregate byte counting, and budget truncation all skipped
them — multi-megabyte command outputs and file reads were JSON-serialized
in full into every subsequent provider request.
MessageBuilder now deep-truncates nested strings inside structured
entries (middle truncation, preserving head and tail), counts them
against the aggregate text budget, collects them as budget-truncation
candidates, and deep-clones them before mutation so the original
conversation history stays untouched. Image blocks are skipped so base64
payloads survive intact.
Real-inference A/B on openrouter:minimax/minimax-m2.7 with realistic
structured payloads: 58.7% overall input-token reduction (82.6% on a
single huge command output) with identical answer correctness.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
🔮 View transcript: https://agentlogs.beatrixwoo.workers.dev/s/mrbt2b39jfn370scr4g0ivzo
* fix(sdk): include fetch_web_content in MessageBuilder truncation targets
Review feedback: fetch_web_content also returns ToolOperationResult[] and
its executor allows responses up to 5MB, but the tool was missing from
TARGET_TOOL_NAMES, so a single web fetch could still bloat every
subsequent provider request. Adds the tool to the truncation target set
with a regression test.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
🔮 View transcript: https://agentlogs.beatrixwoo.workers.dev/s/mrbt2b39jfn370scr4g0ivzo
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
The run_commands tool result's query field repeated the entire executed
command, which already exists verbatim in the assistant tool-call input.
For large generated-file commands (e.g. cat <<EOF heredocs) this
duplicated thousands of chars of source text into every subsequent
provider request.
Bound the provider-facing echo to a 200-char preview plus a truncation
note pointing at the tool call input. Short commands pass through
unchanged. Applies to both createBashTool and createWindowsShellTool,
on success and error paths.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
🔮 View transcript: https://agentlogs.beatrixwoo.workers.dev/s/og840mbjqaog4zita8m0262m
* feat: Enforce a production singleton Cline Hub
This PR changes local Hub startup/discovery so production uses one stable daemon per user machine instead of silently creating additional hubs on random ports.
Replace resolveSharedHubOwnerContext with resolveProductionHubOwnerContext
across doctor and hub server lifecycle management to scope hub discovery
to the production owner.
Additionally:
- Preserve and propagate auth tokens when retiring incompatible hubs
- Throw a clear error when a compatible hub is already running but its
discovery record is missing, guiding users to run 'cline doctor fix'
- Gate port fallback behind an explicit allowPortFallback override
- Update tests to mock the new production hub owner context
* patches
* fix
* hasExplicitPort
* Restored daemon cron startup, made discovery auth tokens required again, and fixed graceful hub stop/restart paths to use the selected production/shared owner context.
* clean up
* patches
* fix Polynomial regular expression
* test
* fix: require explicit hub port fallback in production
* fix(cli): stop pgrep from parsing the hub daemon marker as an option
pgrep treats the "--cline-hub-daemon" pattern as an unknown long option
and exits 2, so doctor never found stale daemons from compiled-binary
installs, which are exactly the processes 'cline doctor fix' is told to
clean up. Pass "--" before the pattern to end option parsing.
* fix(hub): retire legacy shared-owner hubs on production startup
Pre-singleton production builds tracked the local hub under the shared
owner discovery path and spawned daemons on random fallback ports. The
production owner context never reads that path, so upgrades would leave
those daemons running indefinitely with no way to reuse or stop them.
Retire the recorded legacy hub (its record carries the auth token and
pid needed for a graceful stop) and clear the legacy record before
resolving the production hub.
* refactor(hub): simplify stale discovery clearing, share capability list
shouldClearStaleHubDiscovery was only ever called with
discoveredVerified=false (the true assignment sits on a return path),
so the expected-hub probe and compatibility check had no effect and the
condition reduced to "a discovery record exists and was not reused".
Replace it with a plain conditional and drop the tests that exercised
unreachable states.
Also move the hub capability list into a typed HUB_CAPABILITIES
constant in @cline/shared next to HubCapabilityName so the server
cannot drift from the type.
---------
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
* fix(cli): suppress flickering console windows on Windows by setting windowsHide on child processes
On Windows, child_process.spawn/execFile default to windowsHide: false,
so console-subsystem children (powershell, rg, git, node, npm) can
allocate a new visible console window - guaranteed when detached: true
is used. In the CLI this caused constant short-lived window flashes
from run_commands, the git status bar polling, ripgrep searches and
indexing, clipboard helpers, and hook/plugin node subprocesses.
Set windowsHide: true (CREATE_NO_WINDOW; a no-op on non-Windows) on all
remaining spawn/spawnSync/execFile call sites in the SDK core, CLI,
Cline Hub, and example plugins, matching the pattern already used by
the MCP client, checkpoint-hooks, and StandaloneTerminalProcess.
* Update apps/cli/src/commands/kanban.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* fix(llms): avoid disabled reasoning for fable 5
* fix(llms): route fable reasoning by family
* Revert "fix(llms): route fable reasoning by family"
This reverts commit 6dd4e5dcf5.
* fix(llms): match claude fable reasoning workaround broadly
* fix(core): configured agent support as subagent tools
Introduce configured agent config parsing and tool creation for
subagents. Agent configs are defined via YAML frontmatter files
specifying name, description, tools, skills, model, and system prompt.
- Add `configured-agent-config` for loading and parsing agent
definitions from search paths
- Add configured agent tool factory that wraps delegated agents as
named subagent tools with policy and approval support
* patch
* patches
* fixes
* Infinite loop when YAML block is a non-object fix
* apply feedback
Forwarded host requestToolApproval into configured subagents.
Used the resolved workspace config root for configured-agent skills discovery.
Split configured-agent skill loading from root-session skills enablement.
Added host lifecycle/event plumbing for configured subagents via shared subagent callbacks.
Made UserInstructionConfigService.createSkillsExecutor optional and guarded its use.
* threaded
* test(core): cover configured subagent skill isolation (#11396)
---------
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>