Commit Graph
7543 Commits
Author SHA1 Message Date
Saoud Rizwan ef9430ffb4 chore(cli): release v3.0.69 cli-v3.0.69 2026-10-06 22:46:37 -07:00
Saoud Rizwan 0a93311c66 chore(sdk): correct v0.0.91 default-model changelog sdk/sdk/v0.0.91 sdk/core/v0.0.91 sdk/agents/v0.0.91 sdk/llms/v0.0.91 sdk/shared/v0.0.91 2026-10-06 22:40:15 -07:00
Saoud Rizwan dad2e2a5d2 chore(sdk): keep dependency resolutions pinned for v0.0.91 2026-10-06 22:36:45 -07:00
Saoud Rizwan 3cb29e7802 chore(sdk): release v0.0.91 2026-10-06 22:33:41 -07:00
Bee e466f25342 fix(agents): recover incomplete responses with unknown finish reasons (#14869)
* fix(agents): continue unknown AI SDK completions once

* fix(agents): add hidden user continuation after unknown finish

* fix(core): preserve active attachments during hidden continuation compaction
2026-10-06 21:54:39 -07:00
5dea21ab89 Remove deprecated Focus Chain plumbing from the VS Code extension (#14861)
* Hide retired Focus Chain messages when loading legacy tasks

* Remove deprecated Focus Chain plumbing from the extension

* docs: remove retired Focus Chain telemetry events

* Remove unused AgentConfigLoader from the VS Code extension (#14881)

* refactor(vscode): remove unused legacy agent config loader

* test(vscode): verify initialized state persists to disk

* test(vscode): avoid contextual inference in storage assertion

---------

Co-authored-by: Cline <noreply@cline.bot>

---------

Co-authored-by: Cline <noreply@cline.bot>
Co-authored-by: cline-cloud[bot] <276134852+cline-cloud[bot]@users.noreply.github.com>
2026-10-07 13:40:20 +09:00
6354d209c8 docs: correct shared paths, log files, commands and tool names (#14884)
* docs: correct shared paths, log files, commands and tool names

Several pages repeat the same facts about where Cline keeps its files,
which commands exist and what the built-in tools are called, and many of
them no longer match the shipped CLI and SDK:

- Workflows live in ~/.cline/workflows/, not ~/.cline/data/workflows/.
  The session index is ~/.cline/data/db/sessions.db, each session has a
  folder of JSON files, and hub locks and logs are under ~/.cline/data/.
- cline start and cline dev log do not exist; the log command is
  cline doctor log, and the CLI log is ~/.cline/data/logs/cline.log.
- The built-in tools are run_commands, search_codebase,
  fetch_web_content and skills, not bash, search, fetch_web and
  use_skill.
- CLINE_HUB_ADDRESS is read only by cline schedule; the hub port is
  CLINE_HUB_PORT.
- No CLI 3 release reads CLINE_COMMAND_PERMISSIONS. The pages that
  offered it, including the PR review sample, now say the CLI has no
  command allow list and point to a PreToolUse hook. The unused
  permissionDeniedError string in the VS Code prompts goes with it.

Part of #14853.

Co-authored-by: Mikołaj Kondratek <19799111+mkondratek@users.noreply.github.com>
Co-authored-by: Manpreet Kaur <26463231+Manpreet2298@users.noreply.github.com>
Co-authored-by: Renee Huang <100229782+reneehuang1@users.noreply.github.com>

* docs: qualify log, tool routing and command-approval advice

- cline doctor log always opens the default log file, so say so where
  CLINE_LOG_PATH is described.
- The editor and apply_patch choice is a default that SDK callers can
  replace with toolRoutingRules.
- The PR review sample now warns that hooks and plugins in the checked-out
  pull request run with the job's environment, and says how to keep them
  from running before relying on a global PreToolUse hook.
- The conditional-approval example no longer auto-approves git diff,
  which runs a configured external diff program, and notes that Git can
  run programs named in a repository's config.

* docs: run the PR review sample with a read-only token

The sample gave an auto-approved Cline run a token that can write pull
requests. Split it into two jobs: `review` runs Cline with read-only
permissions on a checkout of the base branch and writes review.md;
`post` runs no repository or model code and posts the file with
`gh pr review --comment`.

Skip pull requests from forks and Dependabot, which get no secrets,
and warn against `pull_request_target`. Fence the workflow with four
backticks so the code block inside the prompt no longer ends it early.

---------

Co-authored-by: Dominic Cooney <55120+dominiccooney@users.noreply.github.com>
Co-authored-by: Mikołaj Kondratek <19799111+mkondratek@users.noreply.github.com>
Co-authored-by: Manpreet Kaur <26463231+Manpreet2298@users.noreply.github.com>
Co-authored-by: Renee Huang <100229782+reneehuang1@users.noreply.github.com>
2026-10-07 12:10:37 +09:00
Saoud RizwanandSaoud Rizwan 42c20b9681 test(cli): drop MCP description tests that pin hardcoded default timeouts (#14886)
Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-10-06 19:04:19 -07:00
Saoud Rizwan f832e8169d fix(desktop): let keyless configured providers (local models) start sessions (#14879)
* fix(desktop): let keyless configured providers start sessions

The webview's pre-flight credential gate demanded an API key for every
provider that was not OAuth or local-auth, so a local OpenAI-compatible
endpoint (LM Studio, vLLM, Ollama) migrated from VS Code or added via
Settings failed every turn with "Missing API key" even though the
sidecar already reported it as configured via base URL + model.

Carry the catalog's host-computed `configured` readiness into the chat
config and skip the API-key requirement when the host accepts the
provider, matching the runtime's own keyless handling.

* fix(desktop): gate sessions on the shared apiKeyOptional provider fact

Address review: instead of a desktop-only providerConfigured readiness
flag threaded through the chat config, make the credential requirement
explicit in the shared provider contract.

- @cline/shared: GatewayProviderMetadata.apiKeyOptional, mirrored into
  ProviderAuthInfo via resolveProviderApiKeyOptional (same pattern as
  localCliCommand -> localCli).
- @cline/llms: declare it on openai-compatible, ollama, lmstudio, litellm,
  vertex, and bedrock.
- @cline/core: listLocalProviders carries the fact in ProviderListItem.auth;
  user-added endpoints registered from providers.json / models.json declare
  it too (their key is already optional in the desktop form).
- desktop: resolveCredentialError consults auth.apiKeyOptional and no
  longer needs the extra config field.
2026-10-06 18:48:52 -07:00
Dominic CooneyandDominic Cooney e6a3b1cf0a docs: state telemetry defaults and scope accurately (#14860)
* docs: state telemetry defaults and scope accurately

The Enterprise and monitoring pages called Cline telemetry opt-in and
anonymous, and said code never leaves the machine. Telemetry is on by
default in the VS Code and JetBrains extensions, Cline Desktop and the
CLI. It identifies signed-in accounts and organizations, and includes
prompts for requests to the Cline and ClinePass providers.

Rewrite the telemetry page around what is collected and how to turn it
off in each product. Scope the remote-configuration restrictions to the
products that enforce them, add a per-product support table, and tell
admins to ignore the folders Cline writes into workspaces. Align the VS
Code setting description and host-telemetry warning with the docs.

Part of #14853

* docs: drop bold from remote-config support table rows

The bold marked dashboard switch names, but nothing on the page said so,
so the rows looked inconsistent.

* docs: address review of the telemetry and remote-config pages

State only what the telemetry setting enforces in the extensions: the
lock, and that members can't turn telemetry on when the organization
turns it off. Scope the support-table introduction to the controls
marked Yes, since no product enforces YOLO or Kanban. Use recursive
.gitignore patterns and say why: the cached settings can include prompt
storage access keys, and a member may open a subfolder of a repository.
Narrow the indexing card to content: Cline lists file paths to search
them but doesn't index or embed file contents.

* docs: say products support remote-config controls, not enforce them

Organization rules and workflows reach sessions as instructions that a
member can edit, so "enforces" overstated what the CLI does with them.
The section heading already says "support".

---------

Co-authored-by: Dominic Cooney <55120+dominiccooney@users.noreply.github.com>
2026-10-07 09:40:45 +09:00
Saoud Rizwan e5dd38d81a fix(core): give stdio MCP servers a 10s initialize budget (#14877)
The 3s default connect budget silently dropped every npx/uvx-launched
MCP server on Windows, where reaching initialize through cmd.exe
routinely takes 3-6s even with a warm cache. The model never saw the
server's tools and nothing was logged. 10s covers those launchers while
the doubled worst case (newline + framed attempts) still clears the 30s
hub session.create deadline with headroom.
2026-10-06 16:38:05 -07:00
b2c7148cd9 fix(desktop): render Mermaid diagrams inline (#13721)
* feat(desktop): render Mermaid diagrams in chat

Render model-authored Mermaid fences as interactive SVGs in Desktop without depending on model image-input support.

- extract the strict lazy Mermaid DiagramPlugin into @cline/ui
- keep shared defaults diagram-free and add explicit opt-in controls
- enable copy, download, fullscreen, and pan/zoom in Desktop
- preserve initial bundle size through dynamic Mermaid imports
- cover lazy loading, strict security, failures, and streaming fences

Refs #13568

* test(desktop): harden Mermaid rendering coverage

* test(desktop): stub scrollTo for streamdown 2.6 in Markdown interaction tests

streamdown 2.6 (pulled in by main) scrolls streaming code blocks with element.scrollTo, which jsdom does not implement. Stub it the same way chat-messages.test.tsx and channels-view.test.tsx already do.

* fix(ui): stop Mermaid diagram links from bypassing host link policy

Mermaid's `securityLevel: "strict"` blocks script execution and dangerous URL
schemes, but still renders a `click <node> "https://…"` directive as a live
`<a xlink:href>` anchor inside the SVG. Streamdown injects that SVG with
`dangerouslySetInnerHTML`, so those anchors never pass through the `a`
component a product supplies — bypassing the deceptive-link confirmation and
the external-open routing that ordinary Markdown links go through, with no
rel="noreferrer", and letting a click navigate the desktop webview away from
the app itself.

A diagram label is authored independently of its destination, so these links
are deceptive by construction: the desktop app's own isDeceptiveLink rule
would flag every one of them.

- neutralize rendered diagram links in @cline/ui so they cannot navigate on
  their own, preserving an http(s) destination on data-cline-diagram-href
- reattach them in Desktop to the existing confirmation modal, which shows the
  real destination before anything opens
- recover the anchor from pointerdown: Streamdown's pan/zoom surface takes
  pointer capture, so a real click is retargeted away from the anchor; a press
  that moves more than a few pixels is treated as a pan, not a link click
- drop non-http(s) destinations rather than surfacing them, so a renderer
  change cannot widen what the app will open
- assert the packed Mermaid control shape instead of a "not false" check that
  also accepted undefined or an empty object

Verified against real Mermaid 11.16.1 in a browser: script, event-handler,
iframe, foreignObject and javascript:/data:/vbscript:/file: payloads are all
neutralized by strict mode, and `%%{init}%%` / YAML frontmatter cannot
downgrade securityLevel. The http(s) `click` anchor was the one live escape.

Stacked on #13721, which adds the shared lazy Mermaid plugin this hardens.

Refs #13568

Co-authored-by: yiaany <ilyaantonievich@gmail.com>
Co-authored-by: yiheng-kkk <lij921093@gmail.com>

* feat(ui): theme Mermaid diagrams with the Cline design system

Replace Streamdown's built-in Mermaid block in Desktop with an owned
`@cline/ui` block (`createMermaidRenderer` from
`@cline/ui/components/mermaid-block`):

- Mermaid's `base` theme with variables resolved from the live design tokens
  (`--card`, `--foreground`, `--primary`, ...), following light/dark and the
  accent palette and re-rendering when either changes; a diagram's own
  `%%{init}%%`, frontmatter `config:`, `classDef` and `style` still win
- a filename header from the fence title (```mermaid title="my-diagram"),
  frontmatter `title:`, or a name derived from the diagram
- zoom, fullscreen, copy, and PNG / `.mmd` downloads; PNGs are opaque, 2-3x,
  capped at 4096px and kept under the image attachment limit
- renders are serialized through one queue, since Mermaid is a process-wide
  singleton that is not safe to render concurrently

The owned block injects the SVG itself, so diagram link neutralization moves
into the shared render service and covers both this block and the Streamdown
diagram plugin. Desktop keeps routing diagram link clicks through the existing
confirmation modal.

Refs #13568

* fix(ui): avoid polynomial backtracking in Mermaid helpers

* fix(ui): make diagram label extraction linear-time

Replaces the backtracking label-regexes CodeQL flagged (ReDoS, PR #14757) with single-pass scanners and line-column parsing.

* refactor(ui): share the Mermaid render service and drop dead naming helper

createLazyMermaidPlugin now delegates import/retry/queueing/link-neutralization to createMermaidService instead of duplicating that path, keeping only theme-keyed config. Removes deriveMermaidDiagramName, which had no consumer outside its own tests.

---------

Co-authored-by: harrisonofcline <harrison@cline.bot>
Co-authored-by: yiheng-kkk <lij921093@gmail.com>
2026-10-06 10:50:06 -07:00
Mikołaj KondratekandDante cd80a20e96 fix(llms): send Anthropic refusal fallback only to the official Claude API (#14834)
* fix: omit refusal fallbacks for custom Anthropic endpoints (#14816)

* fix(llms): gate Anthropic refusal fallback on the official endpoint

Move the endpoint check into an isOfficialAnthropicEndpoint URL helper and
keep it in the rule's build step so custom endpoints retain the generic
fanout suppression. Add an identity test that a custom endpoint changes
nothing but `fallbacks`, plus an HTTP-boundary test through the real
handler that checks the body and the server-side-fallback beta header.

Co-authored-by: Dante <duanjl.china@gmail.com>

---------

Co-authored-by: Dante <duanjl.china@gmail.com>
2026-10-06 11:02:59 +02:00
Mikołaj Kondratek 6017c502c3 fix(vscode): apply the user's rules when generating commit messages (#14103)
* refactor(core): select and order session rules in one place

The rules section of a session's system prompt was selected in several
places: `listEnabledRulesFromWatcher` (enabled only, sorted by name) for the
single-workspace plugin, and an inline filter without the sort in the
combined user-instruction service. Callers outside a session that need the
same section had nowhere to reach it and would have grown a third copy.

Add `listEnabledRulesFromRecords` / `loadRulesForSystemPromptFromRecords`
next to the watcher variants, make the watcher variants delegate to them,
and use the records variant in the combined service. Export the loader from
`@cline/core`.

Behavior change: the combined service now orders rules by name like the
single-workspace path does, instead of in listing order.

* fix(vscode): apply the user's rules when generating commit messages

"Generate Commit Message with Cline" built its prompt from a hardcoded
system prompt and never loaded `.clinerules`, so commit conventions users
had written down (language, format, ticket references) were honored in
chat and silently dropped by the button.

`Controller.getRulesForSystemPrompt` takes the enabled rules from the
user-instruction watcher the controller already runs for the workspace,
through core's shared `loadRulesForSystemPromptFromRecords`, and the
commit-message system prompt appends them behind a short preamble telling
the model which rules are relevant to a commit message. The button sees the
rule set a chat session in the workspace sees, including a rule that has
`disabled: true` frontmatter being left out of both. If the rules can't be
read, the base prompt is used.

Known limitation: the Rules panel's on/off toggles live in extension state
the SDK doesn't read, so a rule switched off there is still sent to chat
and to the button alike (CLINE-3120).

The new rules load is one more await before the request; the existing
cancel check before `createMessage` covers it, and a test pins that.

Fixes #9410

* fix(vscode): let Stop end a commit generation still waiting for rules

The first generation in a workspace waits for the user-instruction watcher's
initial scan of rules, skills and workflows. Stop was honored after that
await (no request went out), but the generation and its SCM progress
indicator stayed pending until the scan finished, which can take a while on
a slow filesystem.

Race the rules load against the generation's abort signal so Stop ends the
generation at once. The scan carries on in the background and warms the
watcher chat uses; nothing waits on it any more.

* fix(core): render hub client rules through the shared selection

The hub's client user-instruction proxy filtered and formatted rules inline,
in listing order, while the combined service now goes through the shared
`loadRulesForSystemPromptFromRecords`, which sorts by name. runtime-builder
wraps the client proxy in the combined service when host plugin skills are
present, even though the plugin service contributes no rules, so adding a
host plugin reordered the same client rules in the session prompt.

Render the hub snapshot's rules through the shared helper too. Every path
that builds a session's rules section now selects and orders rules the same
way; hub client sessions now get their rules sorted by name. A boundary test
renders reversed names plus a disabled rule through the proxy alone and
through the combined service, and expects the same output from both.
2026-10-06 10:58:43 +02:00
Ken Jo dec80dadfa docs(mcp): correct the CLI MCP config path (#11671) (#11683)
* docs(mcp): correct the CLI mcp config path

* docs(tools): correct the same stale .cline/mcp.json reference

* docs(cli): correct the MCP config entry in the configuration tree

The CLI reference listed `mcp.json` under the project-root `.cline/` tree,
but `resolveMcpSettingsPath()` only ever resolves a global path:
`~/.cline/data/settings/cline_mcp_settings.json` (overridable via
`CLINE_MCP_SETTINGS_PATH`). There is no project-level MCP config reader.

Move the entry to the `~/.cline/data/settings/` tree where the resolver
actually looks, and drop the project-root entry.
2026-10-06 11:33:13 +09:00
lihongyuan99 27bdf27908 docs: fix three stale documentation anchors (#14259)
Three in-site links point at anchors that no longer exist, so they load
the target page without jumping anywhere. Verified against the live docs
DOM by counting the rendered heading ids.
2026-10-06 11:32:03 +09:00
Bee c00bf86595 fix(cli): expose yolo mode (#14724)
* fix(cli): expose yolo mode

Show `-y/--yolo` in CLI help with a clear sandbox warning so unsupervised
benchmark and CI runs can opt in deliberately.

* revert: drop unrelated desktop sidecar hub-reconnect change
2026-10-05 14:34:46 -07:00
Bee b78d91b79b fix(desktop): reconnect chat sessions after Cline Hub loss (#14725)
* fix(desktop): reconnect chat sessions after Cline Hub loss

Retry session rebuild for up to a minute when the hub transport closes or the session is missing, then end the turn as interrupted so the user can resend. Surface reconnect status in the webview instead of treating it as an error.

* fix(desktop): scope hub-loss recovery to lost sessions

- Probe the hub before rebuilding so a session it still holds is left alone
- Cancel the reconnect loop on stop/abort/reset and undo a racing rebuild
- Recover queued sends too, re-queueing once the session is back
- Show the resend notice as an error-role bubble that history sync keeps
- Recognize missing sessions wrapped as generic hub command failures

* fix(desktop): share hub recovery and preserve session ownership

* fix(desktop): isolate replacement recovery and avoid duplicate queued sends

* fix(desktop): serialize recovery across session replacements

* fix(desktop): bound the entire shared recovery lifecycle
2026-10-05 14:33:23 -07:00
Mikołaj Kondratek 4d04fac76a fix(llms): snap portable reasoning effort to the model's advertised levels (#14835)
OpenAI-compatible adapters send the AI SDK's top-level reasoning value to
the endpoint unchanged as reasoning_effort, but the gateway resolved that
value from the raw request. The models.dev effort ladder was only applied
when composing provider options, after portable reasoning had already been
split off, so it never reached the wire. Endpoints with a short ladder
were sent levels they reject: Kimi K3 accepts only low, high and max, yet
received medium for the default thinking level and minimal for minimal.

For the openai-compatible and cline adapters, snap the portable level to
the nearest level the model advertises. When that nearest level is max,
which the portable setting cannot carry yet, keep the requested level
instead of lowering it. Adapters with their own per-model effort maps and
models without catalog facts are unchanged.
2026-10-05 22:13:13 +02:00
Bee 12e3a468f3 fix(llms): Update OpenAI-compatible provider options key (#14784)
* Add GitHub Actions workflow to deploy Storybook

* Update path for Storybook deployment

* Update Storybook deployment workflow for dependencies

* Update Storybook build command in workflow

* Update Storybook deployment path and build command

* fix(llms): stop emitting hyphenated providerOptions keys for openai-compatible providers

`@ai-sdk/openai-compatible` 3.0.30 reads `providerOptions[<name>]` and its
camelCase alias, and logs a deprecation warning on every stream chunk when
the hyphenated raw name is present:

  DeprecationWarning: AI SDK Warning (openai-compatible.chat / ...):
  Deprecated: "providerOptions key 'openai-compatible'". Use
  'openaiCompatible' instead.

Cline wrote its thinking, reasoning and prompt-cache patches under the raw
provider id (`openai-compatible`, `vercel-ai-gateway`, user-defined ids) as
well as the camelCase alias, so every chunk of every stream through the
generic provider spammed the warning to stderr.

Providers whose options target is `openai-compatible` now write only the
camelCase bucket. The SDK reads that alias for every provider name, so no
request-body passthrough is lost. Native and community vendor targets
(`openai-codex`, `claude-code`, ...) keep their raw id and alias as before.

* fix: resolve provider options PR review concerns
2026-10-05 11:31:31 -07:00
Mikołaj KondratekandDante afabc824d8 fix(cli): preserve config --json when delegating to the runtime command (#14833)
The lazy `config` wrapper declares its own `--json` option, so Commander
consumes the flag before the remaining arguments are forwarded to the
real config command. `cline config --json` therefore reached the runtime
command without the flag and launched the interactive view, which fails
without a TTY, while `cline --json config` worked because the inner
command also reads the root option. `cline config --json mcp` silently
printed text for the same reason.

Copy the wrapper's parsed value onto the runtime command before parsing
the forwarded arguments, and add a non-TTY e2e check that both flag
placements produce the same JSON inventory.

Co-authored-by: Dante <duanjl.china@gmail.com>
2026-10-05 09:48:15 -07:00
Harsha Varma 68b24a92b7 fix(core): support windows path separators in hook discovery telemetry (#14767) (#14818) 2026-10-05 09:24:13 +02:00
Xx 2f93c1d6f7 docs: fix two broken README links (vscode contributing, sdk telegram) (#14826)
* docs: fix two broken README links (vscode contributing, sdk telegram)

* docs: fix two broken README links (vscode contributing, sdk telegram)
2026-10-05 09:08:08 +02:00
Bee 39ff2359f7 feat(llms): opt-in Langfuse tracing for BYOK providers plus env tags, metadata and environment (#14787)
* feat(llms): opt-in Langfuse tracing for BYOK providers plus env tags, metadata and environment

Langfuse tracing was limited to the cline and cline-pass providers, so an
operator pointing LANGFUSE_* credentials at their own instance could not trace
OpenRouter or any other BYOK provider. CLINE_LANGFUSE_ALL_PROVIDERS=1 now opts
third-party providers in. They are exported only through the isolated direct
exporter and never through the host OTLP relay, so BYOK prompts cannot reach a
collector the operator did not configure themselves.

Benchmark and isolated-environment runs can label every trace from the
environment: LANGFUSE_TRACING_ENVIRONMENT sets the Langfuse environment on the
direct exporter, CLINE_LANGFUSE_TAGS adds comma-separated trace tags, and
CLINE_LANGFUSE_METADATA adds trace metadata as a JSON object or key=value
pairs. Env values merge under the runtime's own attributes, and env-only
attributes propagate even when a call supplies none of its own.

* docs(llms): state that Langfuse tracing covers streamed language requests only

Dedicated image generation uses the AI SDK's generateImage, which takes no
telemetry option and has no Langfuse integration hook, so it has never been
traced for any provider. Document that scope in the resolver and the runbook
rather than implying the BYOK opt-in covers it.
2026-10-03 00:33:13 +02:00
Saoud Rizwan 476b165b97 chore(desktop): trim v0.0.43 changelog desktop-v0.0.43 2026-10-02 13:17:41 -07:00
Saoud Rizwan 97facdb231 chore(desktop): release v0.0.43 2026-10-02 13:17:19 -07:00
Saoud Rizwan aa47bcc97f desktop: Connectors "What's new" spotlight (#14786)
* desktop: add Connectors 'What's new' catch-up

* desktop: tighten Suggested combos copy to fit two lines

* desktop: give the Connectors catch-up its own spotlight layout with an Open Connectors CTA

* desktop: move connector logos and pitch into the What's new body, make the example clickable

* desktop: let the What's new dialog scroll in short windows
2026-10-02 13:14:12 -07:00
Saoud Rizwan c269dbb7f9 chore(desktop): release v0.0.42 desktop-v0.0.42 2026-10-02 02:43:01 -07:00
Saoud Rizwan 7e7ff84efd Move installed connectors search under its header and show Browse in two columns (#14771) 2026-10-02 02:37:14 -07:00
Saoud RizwanandSaoud Rizwan 4e3eb7ea15 desktop: browse connectors from Customize, make Connectors the default tab (#14764)
* desktop: browse connectors from Customize and make Connectors the default tab

Customize > Connectors gains a Browse section below the suggested recipes
that lists the rest of the Composio catalog with search and infinite
scroll, so nobody has to open the Marketplace just to find a connector.
Connectors is now the first and default Customize tab (falling back to
Tools for accounts without beta access).

Connector rows and cards always show the connector's own brand logo:
ConnectorLogo falls back to Composio's slug-based logo URL, and the
Marketplace connector rows use it instead of the generic type glyph.

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>

* desktop: format connectors view

* desktop: point the empty Connectors state at Browse and in-chat connect

Connectors can now be connected from inside a task (cline/cline#14755),
so the empty state no longer sends people to the Marketplace.

* desktop: render connector logos at full tile size

ConnectorLogo was drawn at size-5 inside size-7/8/10 tiles, leaving a
grey margin around every mark. The image now fills the tile itself
(size and radius come from className) and the wrapper spans are gone;
the lucide/letter fallbacks keep the tile background.

* desktop: always show the Connectors tab with sign-in and beta guidance

The Connectors tab no longer depends on Composio availability, so the
default tab never swaps underneath the user. When connectors are
unavailable the tab explains why: signed out shows a Cline sign-in card
(same device-code OAuth flow as the Account page) plus Create account;
signed in without beta access shows a rollout notice with Check again.
The tab count is hidden while connectors are unavailable.

Also addresses review feedback: the search hint counts only the Browse
entries actually hidden, and a failed logo retries when a different URL
arrives.

* desktop: separate Installed and Browse searches, wait for account before sign-in prompt

Each Connectors list now has its own search field: the top field filters
Installed (and is hidden when nothing is installed), the field under the
Browse header filters the catalog. Suggested is no longer filtered.

AccountProvider exposes accountReady so the unavailable card can show a
spinner until the first identity lookup finishes instead of telling a
signed-in user without beta access to sign in.

---------

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-10-02 02:08:09 -07:00
Saoud Rizwan 63c2f65c24 feat(desktop): add /compact slash command (#14770)
* feat(desktop): add /compact slash command

Suggest /compact in the composer's slash menu and run it in the sidecar
like the CLI's local command: summarize the transcript with a manual core
compaction and persist it as the session's compaction state instead of
sending the literal text to the model.

* fix(desktop): forward session baseUrl and headers to /compact

Build the compaction connection with buildSessionConnectionUpdate so a
session's top-level baseUrl and headers reach the summarizer like they
reach the live session, and cover the successful compaction path.
2026-10-02 01:56:56 -07:00
Saoud Rizwan 4515a410a0 chore(desktop): release v0.0.41 desktop-v0.0.41 2026-10-01 21:48:38 -07:00
Saoud Rizwan 241c1884a7 chore(cli): release v3.0.68 cli-v3.0.68 2026-10-01 21:21:14 -07:00
Saoud Rizwan a7ad50bae3 chore(sdk): release v0.0.90 sdk/sdk/v0.0.90 sdk/core/v0.0.90 sdk/agents/v0.0.90 sdk/llms/v0.0.90 sdk/shared/v0.0.90 2026-10-01 21:14:46 -07:00
Saoud RizwanandSaoud Rizwan e205ac38b5 fix(core): revive team run lastProgressAt when loading persisted state (#14756)
Restored team runs kept lastProgressAt as an ISO string, so team_list_runs
failed with "toISOString is not a function" on any resumed team that had a
run. Revive it alongside the other run dates in all three loaders.

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-10-01 20:41:31 -07:00
Bee 5349bed08f fix(core): stop rewriting full team state on every streamed teammate chunk (#14729)
* fix(core): stop rewriting full team state on every streamed teammate chunk

* fix(core): retry failed team writes and persist retry/eventless state changes

- TeamPersistenceWriter requeues a failed batch and retries it instead of
  dropping it; dispose no longer schedules retries after shutdown.
- Scheduled retries (run_progress with a queued run) are durable and flushed
  immediately so recovery cannot grant an extra attempt.
- AgentTeamsRuntime notifies onStateDirty for eventless changes (mailbox
  read receipts, cleanup) so they are written promptly.
- Telemetry progress throttle sends the latest event at the end of the window.
- drainStateDelta only indexes mailbox/mission log when they changed.
- handleTeamEvent applies the team_events retention cap.
- File history compaction is also bounded by bytes to avoid repeated rewrites.
- Remove unused TeamRunRow interface.

* fix(core): keep team write retries from duplicating history or dropping on logger errors

- Report write errors after requeueing so a throwing logger cannot lose the batch
- File store writes state before history; compaction and SQLite pruning are best-effort post-commit
- Clear queued telemetry progress when a durable event supersedes it

* fix(core): re-import legacy team state_json on every open

v2 builds only write an empty state_json, so a non-empty value means an
older build wrote it (e.g. after an image rollback). Previously it was
only imported during the one-time v2 migration, so writes made by a
rolled-back build were dropped after re-upgrading. Run the import on
every open.

* fix(core): avoid polynomial regex when trimming team names

`/^-+|-+$/` backtracks quadratically on long runs of `-` (CodeQL
js/polynomial-redos). Trim leading/trailing dashes by index instead.

* refactor(core): share a single sanitizeTeamName helper

Four copies existed; one (team-persistence-store) still used the
polynomial `/^-+|-+$/` trim. Move it to a dependency-free module so
storage can import it without pulling in team-tools.
2026-10-01 14:26:26 -07:00
Saoud RizwanandSaoud Rizwan eabcc2a915 desktop: make marketplace rows self-describing by type (#14750)
* desktop: add marketplace design exploration with five layout variations

Exploration-only /design/marketplace route (not linked from the app) that
renders the same unified item list through five candidate directions:
typed rows, storefront, tabs like Customize, one row per service, and a
directory table. Catalog entries are live; connectors are a fixture.

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>

* desktop: make marketplace rows self-describing by type

Every row and the detail header carry the type's glyph on a per-type
tint, section headers explain what each type is, and rows in mixed
search results show a type pill, so same-named entries (Figma the MCP
server vs Figma the connector) read as different things. Category tags
move from a second row of pills into a single dropdown. Removes the
design-exploration route now that direction A is chosen.

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>

* desktop: drop the count from marketplace section headers

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>

---------

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-10-01 13:05:09 -07:00
Saoud RizwanandSaoud Rizwan 227041a79d desktop: highlight sessions started in the app in the sidebar (#14749)
activeHistorySessionId was derived only from thread.historySession, which
is set when a session is opened from history. A session started fresh in
the app only gets thread.sessionId bound via thread-started, so the
sidebar never received an active id for it and its row stayed
unhighlighted (and its own chat events marked it unread).

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-10-01 11:12:35 -07:00
Saoud RizwanandSaoud Rizwan 7118784339 desktop: add suggested Connector recipes (#14730)
* desktop: align Customize > Connectors tab with the other Customize tabs

The Connectors tab rendered a lone 'Browse all connectors in the
Marketplace' button when empty (redundant with the page header's
Marketplace button) and a compact two-column grid when populated,
neither matching Skills / Plugins / MCP.

It now mirrors those tabs: description row with a refresh button,
full-width search, an Installed section with a count and stacked cards,
and the dashed empty-state box. The recommended connectors that are not
yet connected appear in a Suggested section with one-click Install, so
the empty state is never a dead end without linking out.

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>

* desktop: drop Suggested section from Connectors tab, keep Installed only

Matches the Plugins / MCP tabs exactly: the empty state is the dashed
box pointing at the marketplace, and the header Marketplace button is
the single way to browse.

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>

* desktop: address review on Connectors tab refresh and card click target

- A failed manual refresh keeps the installed list and refresh button and
  shows an inline error instead of replacing the whole tab.
- A refresh response that arrives after a newer connect/disconnect write
  is discarded (status version guard), so stale snapshots cannot
  resurrect an uninstalled connector.
- Successful refreshes go through applyStatus so the Customize tab count
  updates too.
- The whole connector card is the click target for the detail dialog,
  matching its hover treatment and MarketplaceEntryCard.
- Tests cover the refresh button and inline refresh error.

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>

* desktop: suggest connector recipes on Customize > Connectors

Adds a Suggested section under Installed with four connector
combinations (incident RCA, spec-to-shipped, launch-and-market,
support-to-PRs), each explaining the use case, an example prompt, and
per-connector install chips. Connected members show a check; a recipe
disappears once all of its connectors are connected. Shown in both the
empty and populated states; search filters recipes too.

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>

* desktop: add 'Organize your day' connector recipe (Gmail + Slack + Google Calendar)

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>

* desktop: drop the GitHub connector recipe (GitHub is not an available connector)

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>

---------

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-10-01 10:40:25 -07:00
Mikołaj Kondratek 0809928ab2 fix(desktop): preserve prompt drafts when switching sessions (#14645)
* fix(desktop): preserve prompt drafts when switching sessions

* fix(desktop): guard draft recovery and reuse session threads
2026-10-01 16:05:22 +02:00
Mikołaj Kondratek ce74ef0914 fix(vscode): send Cline surface headers from commit message generation (#13593)
* fix(vscode): send Cline surface headers from commit message generation

Commit message generation builds a standalone ApiHandler through
`buildApiHandler` instead of going through ClineCore, and that path wired
no request headers at all. The Cline gateway only serves models that are
restricted to Cline product surfaces (the free models) to requests that
identify themselves, so "Generate Commit Message with Cline" failed with
HTTP 403 on a free model while normal chat on the same model worked.

Resolve the headers through the shared `resolveProviderRequestHeaders`
policy — the same one `local-runtime-bootstrap` uses for sessions — so
there stays one source of truth for provider header policy, and attach
them to the provider config the standalone handler is built from. The
caller now resolves the host client identity first, so a request reports
the same client/platform as a task from the same host. Custom provider
headers stored in providers.json are layered in as well; the commit path
dropped those too.

A standalone request is not a task, so no session id is claimed:
`sessionId` becomes optional in the resolver and `X-Task-ID` is omitted
rather than sent empty. The pre-SDK extension sent `X-Task-ID: ""` from
this same code path, so nothing depends on a meaningful id here.

Fixes #13590

* refactor(vscode): share one client-identity mapping between sessions and standalone requests

`resolveClineRequestClientContext` mapped the host identity to the SDK's
client shape, including the extension-identity fallbacks, and
`buildSessionConfig` built the same object inline. A commit-message request
and a task are supposed to report the same client, and two copies of that
mapping stop guaranteeing it the first time one is edited.

Move the resolver into the session factory and have `buildSessionConfig`
call it, so both paths share it by construction. The host-identity and
multi-root helpers go back to private.

* fix(vscode): send the core's own version and session source from standalone requests

The standalone path sent the extension's version as `X-CORE-VERSION` and an
inlined "vscode" source tag, while a task from the same extension sends the
core package's version via `local-runtime-bootstrap`. That made the "same
headers as a session" guarantee untrue for that header, and the reason given
for inlining the tag (avoiding a core import) didn't hold: this module already
sits behind `cline-session-factory`, which imports `@cline/core`.

Import `CORE_BUILD_VERSION` and `SessionSource.VSCODE` from `@cline/core` so
both paths agree by construction. The vitest `@cline/core` stub re-exports the
real values from SDK source.

* fix(vscode): honor a commit-generation cancel issued while the host identity resolves

`performCommitMsgGeneration` flips the SCM button to its stop action and
then awaits `buildApiHandlerWithHostContext()` (two host-bridge lookups)
before it created this generation's `AbortController`. A cancel in that
window aborted the previous controller, if any, and the request the user had
just cancelled was then sent anyway.

Create and install the controller before the first await, check it again
right before `createMessage`, and read it through a local so a later
generation can't swap the signal an earlier one checks. Two small follow-ons
from the same fix: a cancelled generation no longer reports "Failed to
generate commit message: This operation was aborted", and only the current
generation clears the context key, so one that settles late can't flip the
button back while a newer one runs.

* fix(vscode): cancel a running commit generation when a new one starts

Each generation now checks its own controller, but the stop action can only
reach the one stored in the module slot. The Generate keybinding, unlike
the SCM button and palette entry, stays live while a generation runs, so a
second invocation replaced the slot and left the first generation
unstoppable: Stop cancelled the newer request while the older one kept
writing into the commit input. Before the per-generation controller both
read the shared slot, which is why this only surfaced now.

A new generation now aborts the previous one before taking the slot, so at
most one runs and Stop reaches it by construction. The aborted one exits
without an error and leaves the context key to the new generation.

* fix(vscode): let Stop cancel every running commit generation instead of the newest

Having a new generation abort the previous one made Stop reach everything,
but it added a rule `main` never had, and it collided with "Generate for all
repositories": a generation started mid-run aborted the bulk run's current
repository, the bulk loop then moved to the next repository, and that one
aborted the newer request. The latest request was lost and a repository was
skipped.

Track every running generation in a set instead. Each registers its
controller before its first await and removes it when it settles; Stop
aborts all of them, and the context key stays set while any runs. Nothing
but Stop cancels a generation, so concurrent generations (the Generate
keybinding stays live while one runs, the bulk loop starts one per
repository) no longer cancel each other, and Stop still reaches all of them.

* test(llms): assert Cline surface headers on streaming requests too

The wire-level test only drove `doGenerate`, but commit-message generation
calls `createMessage`, which streams. A regression that dropped the surface
headers from streaming requests alone would have kept the test green while
the free-model 403 came back. Run the same assertions through `doStream`
(and check the request really is a streaming one) for both `cline` and
`cline-pass`.
2026-10-01 15:51:02 +02:00
Mikołaj KondratekandDang Zitou 07a8587479 fix(vscode): register the tool-approval resolver before posting state (#14643)
* fix(vscode): time out undisplayed tool approvals (#14065)

* fix(vscode): drop the approval timeout, keep the resolver-ordering fix

The five-minute timer denied every pending approval, including ones the
user could see but had not answered yet. postStateToWebview() resolving
does not mean the ask was displayed (state delivery is fire-and-forget),
so the timer could not tell an undisplayed approval from a slow answer.

Keep registering the resolver before the state post so Approve/Reject
works while the post is in flight, and deny on a failed post only if
that post's approval is still the pending one; a late failure no longer
denies a later, unrelated approval. Log when an approval starts waiting
so stalls can be told apart from provider stream stalls in the output
channel.

---------

Co-authored-by: Dang Zitou <dengzitao888@163.com>
2026-10-01 15:50:43 +02:00
Bee 8eee168b80 fix(desktop): show installed tool count, not catalog total (#14726)
* fix(desktop): show installed tool count, not catalog total

Drop the connector slug and the stale catalog tools total from the detail dialog so the count reflects only tools available in new sessions.

* fix(desktop): show zero installed tools instead of catalog total for empty connectors
2026-09-30 21:56:41 -07:00
John Choi 9fe17595de fix(desktop): match web cloud model catalog choices (#14720)
* fix(desktop): match web cloud model catalogs

* refactor(desktop): reuse existing cloud model picker

* fix(desktop): require a ready cloud model and allow catalog retry

* fix(desktop): load local cloud model capabilities explicitly

* fix(desktop): start cloud model selection without local fallbacks
2026-09-30 16:41:57 -07:00
Saoud Rizwan 50c83047f2 chore(desktop): release v0.0.40 desktop-v0.0.40 2026-09-30 16:37:18 -07:00
Saoud Rizwan 9087191126 chore(cli): release v3.0.67 cli-v3.0.67 2026-09-30 16:18:46 -07:00
Saoud Rizwan 683487408b chore(sdk): release v0.0.89 sdk/sdk/v0.0.89 sdk/core/v0.0.89 sdk/agents/v0.0.89 sdk/llms/v0.0.89 sdk/shared/v0.0.89 2026-09-30 16:18:35 -07:00
8b03864dca fix(core): recover oversized tool results from a session memory cache (#14712)
* fix(core): cache oversized external results without changing history

* fix(core): use volatile tool result URIs with iteration eviction

* docs(core): clarify cached result reads and truncation fallback

* docs(core): update tool result cache miss message

* fix(core): generate cache fallback agent IDs with crypto.randomUUID

* docs(core): keep cache guidance in result notices

* fix(core): preserve result recovery notices after cache eviction

* fix(core): make cached result recovery readable and text-only

* refactor(core): retain existing read_files availability and line limits

* docs(core): clarify exclusive read_files access to cache URIs

* fix(core): serialize structured cached results as multiline YAML

* fix(core): align recovery admission with persisted preview sizing

* fix(vscode): preserve cache URIs in workspace file reader

* fix(core): exclude MCP image blocks from recovery text

* fix(core): wrap long cached result lines so read_files can page single-line payloads

Cache reads go through read_files' MAX_LINE_CHARS cap, so a minified JSON
or other single-line payload was cut at 2,000 chars with no way to reach
the rest by line range. Wrap cached text at 1,000 chars on the read path
only; stored bytes stay verbatim and cache line numbers are a paging view.

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>

* Revert "fix(core): wrap long cached result lines so read_files can page single-line payloads"

This reverts commit 07e166f3a2.

---------

Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-09-30 15:29:46 -07:00
Bee 457be3d2fd fix(ui): scale tool diff font size with the app font size (#14711)
@pierre/diffs defaults to a fixed 13px font and 20px line height, so diffs
ignored the desktop font-size setting. Drive both from the rem-based
--text-xs token instead.
2026-09-30 11:43:46 -07:00
John Choi 2261d13f9b fix(desktop): remember Cloud model and Git selections for new chats (#14619)
* fix(desktop): remember the Cloud/Local pick and cloud model for new threads

Every new thread seeded its config from `getInitialChatConfig()`, which
restored the last provider/model/workspace but never the execution
target, so a user who ran a task on Cloud was silently dropped back to
Local on the next "New chat".

Persist the user's Cloud/Local pick (and the model last chosen while on
Cloud, which the model picker deliberately keeps out of the per-provider
local memory) in localStorage, and seed new threads from it. Only the
user's own selection is written; the flag-off fallback that forces Local
never overwrites it. The cloud-agents flag now starts as "unknown" so a
thread remembered on Cloud is not bounced to Local before the flag has
resolved.

Part of #14492 (desktop half). The web half is cline/core-platform#3395.

* fix(desktop): open Cloud on the remembered cloud model when switching mid-thread

`getInitialChatConfig()` already seeds a new Cloud thread from the
remembered cloud model, but the Local → Cloud switch inside an open
thread still derived the model from the current local one, so the picker
showed a different model than the one the user last chose on Cloud (and
the next new chat would show the remembered one again). Read the
remembered cloud model there too.

Found by e2e; also flagged by Greptile/Codex on #14619.

* fix(desktop): honour an explicit Local pick and keep validated workspace on Cloud → Local

Three review follow-ups on the remembered execution target:

- Picking "Local" in the environment menu from an SSH host now also
  selects the local execution target, so the new local draft does not
  open on Cloud just because Cloud was remembered. Choosing another SSH
  host is not a Cloud/Local decision and leaves the memory alone.
- A thread that opened on Cloud never captured local settings; switching
  it to Local now keeps the workspace that discovery already validated
  instead of re-applying the raw remembered path, which may no longer
  exist.
- While the cloud-agents flag is still unknown, a composer remembered on
  Cloud keeps its cloud controls rather than showing the local folder
  picker; if the flag settles false the existing effect moves it to Local.

* fix(desktop): never leave a Cloud → Local switch with an empty workspace

If a thread that opened on Cloud is switched to Local before workspace
discovery has returned, nothing was captured and the Cloud config's
workspace is still empty, so the Local composer ended up with no
workspace and the persistence effect could record "" as the last
workspace. Fall back to the remembered path in that window; discovery
still validates and overrides it when it completes.

* feat(desktop): remember the cloud repository and branch for new threads

Remembering the Cloud target and model but making the user re-pick the
repository on every new thread was the remaining gap: the desktop never
had repo memory (only reopened sessions carried theirs). Store the last
cloud repo and branch alongside the target/model, seed new Cloud threads
and Local → Cloud switches from them, and write them from the repo and
branch pickers. Changing the repo forgets the branch until one is picked
for it; the composer's existing accessibility check still clears a repo
the current account can no longer reach.

* fix(desktop): keep the remembered cloud repo through composer clears and history

- The composer clears the repo/branch itself when the current account
  cannot reach the repository (GitHub not connected, no access), and
  that clear went through the same handlers that persist a pick, erasing
  the memory. Only non-empty picks are remembered now.
- reset() only re-seeded the repo when the execution target changed, so
  a new chat after viewing another Cloud session kept that session's
  repository. Re-seed the repo and branch from the remembered selection
  regardless of target, matching provider/model.

* fix(desktop): keep the remembered cloud repo through the first setup check

The composer's mount-time cloud setup check invalidated the scope
eagerly, clearing the repo and branch before confirming access. Since
every new thread mounts a fresh composer, the remembered repo was seeded
and then wiped on each launch and each Local → Cloud switch, and nothing
put it back once access was confirmed.

Only a switch to another user invalidates eagerly now; the first check
of a composer keeps the remembered repo and the existing access guard
drops it if the result shows it is no longer reachable. The sidecar's
scope-change broadcast still invalidates as before.

* fix(desktop): judge a re-activated Cloud composer only by fresh access results

When the composer comes back to Cloud (e.g. after reconnecting GitHub
while on Local), the access guard ran in the same render against the
previous activation's cloud setup results and cleared the remembered
repo before the new check had returned; the successful refresh then had
nothing to restore. Track which request the setup state reflects and let
the guard act only once it matches the latest one. Re-activation also
marks the scope as checking again (without clearing the repo), as it did
before a user-switch became the only eager clear.

* fix(desktop): wait for repository access before starting cloud tasks

* fix(desktop): recover from superseding repository check failures

* fix(desktop): retain validated composer on picker refresh errors

* fix(desktop): share concurrent cloud repository checks

* fix(desktop): persist target only after environment switch succeeds

* fix(desktop): coordinate local selection with disconnect events

* refactor(desktop): reuse model preferences and narrow persistence scope

* fix(desktop): remember Cloud repository and branch for new chats

* fix(desktop): expose recovery for Cloud branch restore failures

* fix(desktop): remember explicit Local selection after fallback

* chore(desktop): trim persistence comments

* fix(desktop): resume Cloud restore after picker failure
2026-09-30 11:05:10 -07:00