Commit Graph
7663 Commits
Author SHA1 Message Date
John Choi d8d4077dfd fix(desktop): reuse recent cloud session listings 2026-10-22 18:57:23 -07:00
MaxandMax Paulus 🥪 590785eff5 feat(telemetry): report per-run stall signals (#15228)
* feat(telemetry): report per-run stall signals

Add task.run_health (one per agent run, every exit path) and task.run_idle
(at most once per run, after 60s with no runtime event) so harness stalls
can be measured from telemetry instead of transcripts.

run_health carries the longest gap between runtime events and what preceded
it, finish reason, final message shape and a text signature of a final
text-only turn. session.input_sent gains agentBusy, msSinceTurnEnd and a
bumpKind label (probe/nudge/greeting) so the user's reaction to a run can be
paired with it; task.cancelled gains msSinceLastEvent. No message text is sent.

* refactor(telemetry): move run stall signals into a core observer

Stall diagnostics now come from a core RunHealthObserver that watches
runtime events, instead of living in the agent loop. Its fields are added
to agent.run-finished / agent.run-failed through a runEndTelemetryProperties
hook, replacing task.run_health and the task.cancelled additions.

Also fixes measurement gaps: tool-argument streaming now emits a
tool-call-delta progress event, the silence before a run ends is counted,
and a turn rejected before reaching history is labelled empty.

* fix(telemetry): tighten run stall signals

Clear finishReason per turn, skip textSignature for media-only replies,
keep stall fields off replayed queued prompts, and document the run
health observer.

* fix(telemetry): identify the run on its run-end stall fields

agent.run-finished / agent.run-failed carry no session, model or provider of
their own, so the stall fields could not be grouped by model or provider,
paired with the user's next message (session.input_sent), or filtered to
root agents. RunHealthObserver now adds sessionId, isSubagent, providerId and
modelId to the run-end properties; undefined values are omitted.

* fix(telemetry): keep stall labels on prompts sent during a queued run

A queued prompt replayed by the drain starts its run unlabelled, but the
session-wide drain flag also stripped the stall fields from new prompts
the user sent while that queued run was busy. Only the replay itself (the
input that starts the run) is unlabelled now.

Tool-argument chunks now report progress at most once a second: each
event copies the whole conversation, and a large file write streams
thousands of chunks.

* fix(telemetry): mark only the replayed queued prompt as a replay

The queue drain now marks the one input it replays, and runTurn consumes
that marker, instead of inferring a replay from the session-wide drain
flag. Fresh user input during a queued run keeps its stall fields
whether the run is busy or just finishing.

---------

Co-authored-by: Max Paulus 🥪 <max@cline.bot>
2026-10-22 12:10:35 -07:00
Saoud Rizwan c441897f11 ci: require PublishNPM approval for every npm publish (#15258)
* ci: require PublishNPM approval for every npm publish and drop CLI/SDK nightly crons

CLI, SDK, and @cline/ui publish jobs now run in the PublishNPM GitHub
environment, so nothing reaches npm until a reviewer approves the run.
The CLI nightly job and both nightly crons are removed: an unattended
scheduled run would sit waiting for approval every day.

* ci: keep the CLI nightly as a manual, PublishNPM-gated publish
2026-10-21 17:47:26 -07:00
Saoud Rizwan f7676802f4 Fix punctuation in project description 2026-10-21 16:52:49 -07:00
c31347a09b fix(cli): correct ACP provider and account config categories (#15160)
* fix(cli): stop the ACP provider option claiming the model category

* fix(cli): cover assembled ACP options and fix account category

Co-authored-by: Codex <noreply@openai.com>

* test(cli): guard assembled ACP category uniqueness

Refs #15158

---------

Co-authored-by: zurrll <243898826+zurrll@users.noreply.github.com>
Co-authored-by: Codex <noreply@openai.com>
2026-10-21 14:55:38 +02:00
Mikołaj Kondratek e9dafbb764 fix(core): reject an empty run_commands list instead of reporting success (#15089)
* fix(core): reject an empty run_commands list instead of reporting success

`{"commands":[]}` validated, ran nothing, and came back as a successful
call with no results. Fail it with a clear tool error so the model sees
that no command was given, whether it emitted the empty list itself or
a repair produced it.

* fix(core): advertise the run_commands list as non-empty

The lenient input union still accepts an empty list so the normalizer
can reject it with one clear message; the advertised schema now also
tells the model up front, as minItems: 1.
2026-10-21 07:17:24 +02:00
Bee 92c1f4e031 fix(desktop): keep schedule status current and show full errors (#15220)
* fix(desktop): refresh schedule failures and show full errors

* fix(desktop): avoid overlapping schedule background refreshes
2026-10-20 20:47:37 -07:00
Saoud Rizwan 627e51e546 fix(vscode): padding in Local/Cloud task target toggle (#15231)
* Fix padding in Local/Cloud task target toggle

* Balance Local/Cloud toggle insets and corner radii
2026-10-20 18:59:09 -07:00
Saoud Rizwan f380cca27a fix(vscode): wrap task header badges instead of clipping the close button (#15234) 2026-10-20 18:20:25 -07:00
Bee f3249a77cf feat(desktop): add hub controls to General settings (#14653)
* feat(desktop): add hub controls to About settings

* fix(desktop): require trusted connection for hub status

* fix(desktop): isolate local hub activity and track restart identity
2026-10-20 18:15:49 -07:00
John Choi 9e2ed4e6b3 feat(core): add conversation summaries and cloud continuation support (#15219)
* feat(core): add conversation summaries and cloud continuation support

* fix(core): isolate summary generation and preserve continuation context

* chore(core): trim summary docs and duplicate test setup

* refactor(core): trim conversation summary checks and tests

* test(core): preserve both model metadata paths in summary coverage

* fix(core): preserve tool results in conversation summaries

* fix(core): preserve cloud titles when dispatch is vetoed

* test(core): trim summary and cloud test scope

* fix(desktop): forward cloud send lifecycle hook
2026-10-20 18:02:25 -07:00
Saoud Rizwan 6bb7f4cf1d fix(cli): hide null args in the skills tool call label (#15236) 2026-10-20 18:01:23 -07:00
Dominic Cooney 2e9571acf0 refactor(cli): simplify dashboard webview asset resolution (#15209)
* refactor(cli): simplify dashboard webview asset resolution

* test(cli): remove obsolete wrapper layout dashboard test
2026-10-20 16:56:44 -07:00
Saoud Rizwan 43a976d931 fix(core): estimate re-compaction against API-safe projected messages (#15193)
* fix(core): estimate re-compaction against API-safe projected messages

Once a compaction sidecar exists, createCompactionStateAwarePrepareTurn
passed the raw projection as apiMessages, so the auto-compaction trigger
counted full-size tool results that MessageBuilder.buildForApi truncates
to 8k chars before the request is sent. The estimate ran ~7x over the
provider's actual input count and compaction re-fired every few tool
calls.

Thread the orchestrator's provider-message transform into the prepareTurn
context as prepareApiMessages and run the projection through it before
the compaction pipeline estimates request size.

Fixes #15159

* fix(core): inject the API-message transform into compaction wiring

Address review: keep the dependency in the compaction wiring instead of
widening AgentPrepareTurnContext. createCompactionStateAwarePrepareTurn
now requires prepareApiMessages, with no raw-projection fallback, and
the local runtime host supplies the session runtime's
prepareProviderMessagesForApi (extension message builders +
MessageBuilder.buildForApi).

* chore(core): trim redundant comments and dead test scaffolding
2026-10-20 16:56:16 -07:00
Saoud Rizwan 49648740e4 Stack the restart button under the text in the desktop update toast (#15230) 2026-10-20 16:54:18 -07:00
9cb0410253 fix(core): run plugin commands in the active session runtime (#14505)
* fix(core): own plugin commands in the runtime and hub

* docs(core): separate session command ownership from resource loading

* style(cli): sort imports after command activity integration

* fix(core): preserve plugin command delivery and catalog recovery

* test(desktop): require non-replaying plugin command dispatch

* fix(core): bound catalog refresh and remove generated test code

* fix(core): rearm plugin watches as discovery directories appear

* fix(core): reconcile sources after watcher registration

* fix(core): expose only plugin commands from resident sessions (#15185)

* fix(core): own plugin commands in the runtime and hub

* fix(core): expose only plugin commands from resident sessions

Session registries also hold the built-in skill and workflow commands. Their
handlers return the instruction text, which pluginCommands.run turned into a
reply, so Desktop and the CLI showed the skill body and never sent it to the
model. Mark commands registered through PluginRegistry and filter on that.

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

---------

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

* fix(core): run workspace plugin commands for sessions the runtime lacks (#15186)

* fix(core): own plugin commands in the runtime and hub

* fix(core): run workspace plugin commands for sessions the runtime lacks

list() already falls back to the workspace catalog when the runtime does not
have the session, but run() threw SessionNotFoundError. Desktop calls run()
before its hub-loss reconnect and connectors call it before their stale
binding recovery, so a lost session failed the whole send.

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

* test(core): place missing-session plugin command test apart from sibling fixes

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

---------

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

* fix(core): treat hubs without plugin command RPCs as having no commands (#15188)

* fix(core): own plugin commands in the runtime and hub

* fix(core): treat hubs without plugin command RPCs as having no commands

A running Hub that predates plugins.commands.* replies unsupported_command, and
replacement defers while it has active work. The client threw on that reply, so
every non-built-in slash command, skills included, failed in Desktop until the
old Hub exited. Return an empty catalog and no command result instead.

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

* fix(core): catch the unsupported_command error the hub client throws

NodeHubClient.command() throws HubCommandError for a non-ok reply, so checking
the reply never saw an older Hub's unsupported_command. Catch the thrown error
instead, and make the regression test reject the way the real client does.

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

---------

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

* fix(desktop): target plugin commands at the session's workspace root (#15189)

* fix(core): own plugin commands in the runtime and hub

* fix(desktop): target plugin commands at the session's workspace root

Core checks a session command's workspace against the session's
workspaceRoot ?? cwd, but Desktop sent cwd first. A session whose cwd is a
subdirectory of its workspace root failed with 'Plugin command workspace does
not match the session'. Resolve the live session's workspace the same way.

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

---------

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

* fix(cli): refresh plugin command autocomplete when the active session changes (#15190)

* fix(core): own plugin commands in the runtime and hub

* fix(cli): refresh plugin command autocomplete when the active session changes

Session commands come from the active session's plugins, but autocomplete only
reloaded on mount or on a workspace catalog event. The first catalog loads
before a session exists, so session-only commands stayed hidden. Notify the
slash command subscription when a session starts or is cleared.

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

---------

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

* fix(core): keep subprocess-loaded plugin commands in resident sessions (#15207)

isPluginCommand only recognized commands wrapped by PluginRegistry, but with
CLINE_PLUGIN_MODE=sandbox sessions load plugins through loadSandboxedPlugins,
which registers commands directly. Resident sessions then listed no plugin
commands and /commands stopped reaching their handlers. Move the marker into
plugin-command-origin.ts and mark commands from both loaders.

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

* fix(desktop): port packaged plugin runtime probe to runtime-owned plugin commands

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

* fix(desktop): keep skills and workflows working when the plugin catalog is unavailable (#15222)

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

* refactor(core): replace plugin catalog push with per-request freshness (#15224)

* refactor(core): replace plugin catalog push with per-request freshness

- Drop pluginCommands.subscribe and the plugins.commands.changed event. Hub
  runtime hosts no longer open a global event stream, so the per-listener
  event ID dedupe in NodeHubClient is removed with it.
- Reduce PluginCommandManager to a per-workspace catalog that fingerprints
  plugin sources and settings on every request, keeps healthy commands
  through a failed load, and retries that load after 30 seconds. File
  watchers, debounced source checks, backoff timers, and per-path recovery
  are removed.
- Release workspace catalogs that have been idle for 10 minutes so the
  long-lived Hub does not keep plugin workers for every workspace it served.
- CLI suggestions reload on mount and active session change; desktop
  composers re-list plugin and instruction commands when the slash menu
  opens. Client retry loops are removed.

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

* fix(core): isolate workspace catalog loads from the shared plugin registry

Catalog loads went through the process PluginRegistry, so a fatal import
failure in a catalog worker blocked the shared entry: live sessions' copies
failed their usability check, and the 30s retry was skipped as blocked until
a source edit. Each catalog load now uses its own registry.

The fingerprint no longer hashes the whole settings file. The resolved entry
list already excludes plugins disabled in settings, so unrelated preference
changes no longer restart workspace catalogs.

* fix(core): require a registered workspace for Hub plugin commands

An unregistered WebSocket connection reaches the plugin command handler
with no authority, which skipped the workspace check and accepted any
caller-chosen workspacePath. Reject it, matching task commands. Every
NodeHubClient registers on connect, so real clients are unaffected.

* fix(desktop): key cached plugin suggestions by session

A resident session's plugin commands can differ from the workspace
catalog. Switching sessions in the same workspace kept showing the
previous session's commands, indefinitely if the new read failed, and a
stale plugin name could hide a skill or workflow of the same name.

---------

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

---------

Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-10-20 16:45:45 -07:00
John Choi f841eee320 test(core): finish prewarm polling before resetting mocks (#15232) 2026-10-20 16:30:57 -07:00
Saoud RizwanandSaoud Rizwan d553858849 docs(readme): point VS Code extension index entry at apps/vscode (#15225)
Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-10-20 14:18:31 -07:00
Bee 05d980df03 fix(llms): Reduce api retries and record failed attempts (#15221)
* fix(llms): reduce retries and trace failed request attempts

* fix(llms): exclude request cancellation from Langfuse errors
2026-10-20 13:50:40 -07:00
Mikołaj Kondratek 0870796e9e fix(llms): send max_completion_tokens to SAP AI Core (#15141)
* fix(llms): send max_completion_tokens to SAP AI Core

Bump @jerome-benoit/sap-ai-provider from 4.8.0 to 5.0.3 and load it
through its /v4 entrypoint, the one built for AI SDK 7.

4.8.0 always sent the output limit as `max_tokens`. OpenAI reasoning
models reject it, and newer SAP AI Core landscapes reject it for every
model family ("Unsupported parameter: 'max_tokens' is not supported with
this model. Use 'max_completion_tokens' instead."). The provider sends
`max_completion_tokens` since 4.9.0, on both the Orchestration and the
Foundation Models APIs.

No saved setting changes meaning: Cline passes the same options to the
provider, and the upstream 4.x to 5.x notes only raise the runtime floor
to Node 22.12 and reject unsupported binary file objects.

The /v4 facade wraps the V3 model, so the tests that inspect the
resolved provider config now read it from the wrapped model. A new wire
test drives the real provider and SAP SDK clients against a local token
and inference server and asserts on the request body in both API modes.

* test(core): read the SAP model config through the /v4 wrapper
2026-10-20 14:01:16 +02:00
Dominic Cooney ca7402c5ab fix(core): resolve configured CLINE_PLUGIN_RUNTIME_DIR to an absolute path (#15208) 2026-10-20 10:56:28 +09:00
Dominic Cooney 82486434b3 fix(cli): make build:platforms:single work on Windows (#15206)
* fix(cli): make build:platforms:single work on Windows

Replace shell rm -rf with rmSync in apps/cli/script/build.ts, retry
temporary smoke-test directory cleanup while the detached hub process
exits on Windows, and use mkdtempSync with non-Windows chmodSync in
apps/cli/script/compile-binary.ts.

* fix(cli): warn if smoke-test directory cleanup fails after retries

Use rmSync maxRetries/retryDelay for post-smoke-test cleanup and log a
warning with the directory path and error if removal still fails.
2026-10-20 08:47:31 +09:00
2377a20973 fix(core): load embedded plugin and dashboard resources (#15080)
* fix(core): load embedded plugin and dashboard resources

* fix(core): isolate subprocess Bun mode and retain system CA trust

* fix(core): load compiled plugin resources directly from bunfs

* test(desktop): compare native paths and tolerate Hub cleanup on Windows

The standalone plugin test compared the child's process.execPath to
realpathSync(cli), which keeps Windows 8.3 short names (RUNNER~1) while the
child reports the long path. Use realpathSync.native. The dashboard test's
cleanup could hit EBUSY while the stopped Hub released its cwd; retry it like
the startup scenario cleanup does.

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

* fix(core): package every declared SDK runtime export

---------

Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-10-19 15:37:08 -07:00
Mikołaj Kondratek d800bf8271 chore: pin the skills CLI release and let Dependabot bump it (#15144)
* chore: pin the skills CLI release and let Dependabot bump it

cline skill, the marketplace skill fallback (desktop, hub, VS Code) and
core's skill uninstall ran npx skills@latest, so a Vercel release could
change behaviour or raise the Node floor under shipped builds without any
change on our side (1.5.16 broke Node 18/20 on 2026-07-10, 1.5.19 raised
the floor to >=22.20 on 2026-07-16, both within days of us adopting it).

The release is now an exact devDependency of @cline/core, exposed as
SKILLS_CLI_PACKAGE, and Dependabot opens a PR for each new version so
bumps go through CI and review. The package's code is never executed by
us; only its package.json version is read at build time.

* test(core): guard the skills CLI pin against tags and ranges
2026-10-19 21:45:38 +02:00
Saoud Rizwan 0caa1b10ab fix(llms): backfill Cline recommended model capabilities from Vercel catalog (#15181)
* fix(llms): backfill Cline recommended model capabilities from Vercel catalog

* fix(llms): consult Vercel catalog only when OpenRouter has no match

* refactor(llms): pass the models.dev catalog to Cline recommended normalization
2026-10-19 12:12:03 -07:00
Lucien 7e8d22c789 fix(vscode): settle pending questions before posting state (#14839) 2026-10-19 21:10:28 +02:00
Mikołaj Kondratekand33modeling 41e75efc53 fix(vscode): honor disabled rule toggles in SDK sessions (#14605)
* fix(vscode): persist rule toggle state for SDK loader

* fix(vscode): confine rule toggle frontmatter writes and preserve authored YAML

- Only write rule documents the SDK loader actually reads (.md, .markdown,
  .txt, or the bare .clinerules file) that resolve, through symlinks, to a
  regular file inside the scope's rules root (global Rules dir or the
  workspace .clinerules). Anything else keeps the extension-state toggle only.
- Edit the top-level `disabled` entry line by line instead of re-dumping the
  YAML block, so comments, key order, quoting, CRLF line endings and a UTF-8
  BOM survive a toggle. Re-parse before writing and leave the file untouched
  if the result would not parse. Skills share the helper and get the same.
- Reconcile extension state with frontmatter on rules refresh: toggles turned
  off before this fix are written to the file so SDK sessions honor them, and
  a file disabled by hand wins over a stale enabled toggle.

* fix(vscode): write rule toggles into every rule root the panel scans

Rebase adjustment: since the rules panel now scans both .clinerules and
.cline/rules plus every global location the shared resolver knows, the
frontmatter write and the state<->frontmatter reconcile take the same
directory lists instead of the two hardcoded roots.

* fix(vscode): make rule files authoritative for toggles after a one-time back-fill

- Match the SDK's disabled precedence: a boolean `disabled` wins, `enabled:
  false` only counts when `disabled` is absent.
- Recognize quoted frontmatter keys when editing the disabled line.
- Return written/skipped/failed from the frontmatter write; on failure the
  toggle handler reverts the state toggle and returns the reverted map so the
  panel keeps showing what the SDK loads.
- Back-fill state toggles into frontmatter once, behind a new global state
  flag; afterwards the file is the source of truth for the panel in both
  directions, so removing `disabled` from a file re-enables the rule.
- Only write files the SDK loader reads: direct children of a rule root, or
  the single legacy .clinerules file.

* fix(vscode): back-fill rule toggles per workspace and accept uppercase YAML booleans

- The one-time back-fill marker is now keyed per scope (global, and one entry
  per workspace path), so a workspace opened after another one was migrated
  still gets its pre-fix off toggles written into its rule files instead of
  having them flipped on by the file-wins reconcile.
- The enabled: false matcher accepts False and FALSE, which both YAML parsers
  in play read as boolean false, so re-enabling removes those lines too.

* fix(vscode): keep the workspace back-fill marker in workspace state

Each window holds its own copy of global state and the last writer wins per
key, so two windows migrating different workspaces could erase each other's
marker in the shared record. The global marker is a plain flag again and the
workspace marker moves to workspace state, keyed by workspace path, which is
per window and never shared.

* fix(vscode): report a rule toggle as failed when the file could not be edited safely

The frontmatter helper returns the document unchanged both when it already
carries the requested state and when it cannot be edited safely (malformed
YAML, or an edit that would not re-parse). The write wrapper treated both as
success, so the toggle handler kept the new state while the SDK kept loading
the old one. An unchanged document now counts as written only if it parses
and already matches the requested state; otherwise the handler reverts.

* fix(vscode): retry a failed rule back-fill and keep comments after inline disabled values

- A back-fill write that fails (read-only file, malformed frontmatter) keeps
  the off toggle and leaves the scope's migration marker unset, so the next
  refresh retries instead of treating the unwritten file as re-enabled.
- An entry with an inline scalar value is a single line, so an indented
  comment after `disabled: true` is no longer removed with it.

* fix(vscode): track the rule back-fill per rule instead of per scope

A scope-wide migration marker forced a choice between two failure modes: mark
the scope done after a failed back-fill (the unwritten rule turns on), or keep
the whole scope pending (a rule the user re-enabled by hand gets back-filled
again). Each rule now records whether its file is authoritative. A rule joins
that set when state and file agree, when the file disables it, when its
back-fill succeeds, or when the toggle handler writes it; only a rule whose
back-fill failed stays pending and is retried on the next refresh. The global
set lives in global state and the workspace set in workspace state, replacing
the unreleased scope markers.

Also handle an inline disabled value that continues on later lines (a flow
collection or a split quoted string) by taking lines until the entry parses.

* fix(vscode): keep global rule authority records in their own settings file

Every window caches global state and persists its whole snapshot, so a window
that started before another one back-filled a global rule kept no record of
it. After the user re-enabled that rule by editing its file, refreshing the
stale window back-filled it again. The global records now live in
settings/cline-rules-frontmatter-authority.json, re-read on every refresh and
merged on every write, so windows only ever add to them. Records for deleted
rule files are dropped on write. Workspace records stay in workspace state,
which is a separate file per workspace.

* fix(vscode): make the rule file the only source of truth for rule toggles

Drop the one-time back-fill of toggles saved before the toggle wrote
frontmatter. Telling such a toggle apart from a rule the user re-enabled by
editing its file needs per-rule history, and every place to keep it
(scope flags, global state, workspace state, a settings file) failed across
multiple windows, crashes, or hand edits. The Rules panel now shows what the
frontmatter says on every refresh, and the toggle writes it. A rule switched
off before this fix shows as on after upgrading, which is what the SDK has
been loading, and is switched off once more.

Removes the per-rule authority records, the authority settings file, and the
localClineRulesFrontmatterAuthoritative workspace key. The multi-layout
refresh test now marks its disabled fixtures in frontmatter.

* fix(vscode): verify the requested state before reporting a toggle write

The rule and skill write paths trusted the frontmatter editor's output. An
edit that left a disabling flag the editor did not recognize (for example a
legacy `enabled: false` whose value is on the next line) was written and
reported as success, so the panel showed the rule or skill as on while the
SDK still excluded it. Both paths now re-parse the edited document and treat
anything not in the requested state as a failure, so the rule toggle handler
reverts and the skill write reports false without writing.

* fix(vscode): edit rule and skill frontmatter by YAML source range

The line-based editor guessed entry boundaries from line shapes. It missed a
legacy `enabled: false` whose value sits on the next line, matched
`disabled:` lines inside multi-line string values (changing unrelated
metadata while still producing valid YAML), and dropped comments on and
around the flag.

The editor now parses the frontmatter with the SDK loader's YAML parser and
splices only the source ranges of the top-level `disabled` and `enabled`
entries. Disabling sets an existing value or appends `disabled: true`.
Enabling removes those entries, or flips the value in place when the entry
carries a comment so the comment survives. Anything the SDK would reject
(invalid YAML, duplicate keys, non-boolean flags) is left untouched, and an
edit is discarded unless every other value is unchanged and the result is in
the requested state. The Rules panel reads state with the same parser.

Declares `yaml` (already a workspace dependency through @cline/core) as a
direct dependency of apps/vscode.

* test(vscode): mock @cline/core before it is loaded in the bun harness

The preload imported the real @cline/core to read its export names and then
mocked it. Mocking an already-loaded module makes bun re-link the graph, and
that re-link leaves a slice of @cline/shared's source-tree exports undefined
(stripUtf8Bom among them) for everything under sdk/packages/core, which
resolves @cline/shared to shared/src through core's tsconfig paths. Any real
SDK function the stub re-exports then threw when called from a test.

The export names now come from a child process, cached on the built package's
mtime, the mock is registered first, and the stub and @cline/llms are imported
after it.

* fix(vscode): let the SDK parser decide a rule's enabled state

The extension kept its own copy of the SDK's rules for reading a rule file's
enabled state, and every review round found a case where the copy and the
SDK disagreed: flag precedence, uppercase booleans, non-boolean values, and
now frontmatter that is not a mapping, which the SDK loads as having no
metadata but the copy treated as unloadable. A rule starting with a markdown
divider line could not be switched off.

The Rules panel, both write paths, and the editor now ask
parseRuleConfigFromMarkdown / parseSkillConfigFromMarkdown from @cline/core,
so they cannot disagree with what the SDK loads, now or after the SDK changes.
The editor still parses the block as a YAML document, but only to locate the
source ranges it edits. A file with non-mapping frontmatter is disabled by
adding a disabled: true block above it, and re-enabling restores it exactly.
A comment-only block gets the flag appended inside it.

A file the SDK does not load at all (unparseable frontmatter, non-boolean
flag, empty body) now shows as off in the panel, since nothing from it
reaches the model; switching it on fails and reverts, with the reason logged.
The bun test stub re-exports the two parsers from the SDK source.

---------

Co-authored-by: 33modeling <33modeling@gmail.com>
2026-10-19 15:08:19 +02:00
Mikołaj Kondratek 9857d19fc4 fix(vscode): keep the session's mode in sync when Plan/Act is toggled during a session start (#15026)
* test(vscode): cover Plan/Act toggles that race a session start

A toggle that lands while a session is being started or replaced sees no
active session, flips only the setting, and leaves the session running with
the other mode's tools. These tests reproduce that and fail on main.

* fix(vscode): keep the session's mode in sync when Plan/Act is toggled during a session start

Starting or replacing a session detaches the outgoing one before the new one
is active. A toggle in that window saw no session, flipped only the setting,
and the session that finished starting kept the other mode's tools, so the UI
showed Act while every write was blocked as plan mode.

- Sessions record the mode they were built for.
- The toggle decides under the rebuild lock, after waiting for session starts
  that run outside it (new task, edited message, checkpoint restore).
- The toggle and the rebuild compare against the session's mode rather than
  the setting, which also fixes the stale mode notice the late rebuild left.

* test(vscode): release session-start waiters when the start fails

Cover a waiter that is already in place when a tracked start rejects. The
previous check only waited after the rejection, so an implementation that
rejected existing waiters would still have passed.
2026-10-19 12:43:41 +02:00
Mikołaj Kondratek 0e4b58c1c9 fix(core): explain PowerShell quote escaping in the run_commands description (#15115)
Models default to bash-style \" escaping, which PowerShell treats as the
end of a double-quoted string. Wrapped in cmd /c, the leftover text becomes
extra arguments, and in one reported case handed rmdir /s /q a bare \,
the root of the current drive.

For PowerShell shells only, tell the model that the backtick is the escape
character, to single-quote literal paths, to prefer cmdlets over cmd /c,
and to confirm recursive or forced deletes before running them.
2026-10-19 19:11:26 +09:00
Saoud Rizwan 3b1ecbb1f3 fix(llms): stop sending native Google Search on the Gemini API (#15194)
Web search became default-on in #13957, so every Gemini API request now
carries the googleSearch grounding tool. Free-tier keys have no grounding
quota on Gemini 3+ models, so each turn fails with 429 'You exceeded your
current quota' (and is retried 6 times). On Gemini 2.x the AI SDK cannot
combine googleSearch with function tools and drops every Cline tool.

Remove the web_search model-tool capability from the gemini provider
manifest. Vertex, which has no free tier, keeps native search.
2026-10-19 01:39:01 -07:00
Mikołaj Kondratek dc3d7a58c9 fix(vscode): keep keyboard focus when revealing the terminal for a command (#15061)
* fix(vscode): keep keyboard focus when revealing the terminal for a command

Every foreground run_commands execution called terminal.show() with no
argument, which makes VS Code move keyboard focus into the terminal. A user
typing in the chat input while Cline starts a command had the rest of their
keystrokes land in the shell, corrupting the running command.

Pass preserveFocus=true at both reveal sites (the per-command reveal in
runCommand and the pre-cd reveal of a reused terminal). The terminal panel
is still revealed, which is all shell-integration initialization needs.

* test(vscode): stub the command process in the reveal-only terminal test

The reveal test fed the process a never-ending stream, so its VS Code shell-execution and terminal-close listeners outlived the test. Stub run() instead; the test only checks the reveal call.
2026-10-19 07:34:47 +02:00
Tomás Barreiro 731f48462b Support MCP Resources [NO-OP] (#15165)
* Support MCP Resources

* Small fixes

* Address PR comments

* remove CreateMcpToolsOptions mcpApps option
2026-10-19 00:10:19 +02:00
Saoud Rizwan a42df8c8d5 chore(desktop): release v0.0.48 desktop-v0.0.48 2026-10-16 20:08:38 -07:00
Saoud Rizwan c718573538 chore(cli): release v3.0.73 cli-v3.0.73 sdk/sdk/v0.0.95 sdk/core/v0.0.95 sdk/agents/v0.0.95 sdk/llms/v0.0.95 sdk/shared/v0.0.95 2026-10-16 19:37:19 -07:00
Saoud Rizwan 36b80d8ce4 chore(sdk): release v0.0.95 2026-10-16 19:37:13 -07:00
Saoud Rizwan 729d6c224e fix(llms): pin OpenCode Go base URL to the shared inference root (#15154)
models.dev now lists https://opencode.ai/inference/go/openai/v1, which
only serves OpenAI routes: /messages returns 404 there, so every
Anthropic-protocol OpenCode Go model would fail after a catalog regen.
Routing appends per-model protocol endpoints to the base URL, so keep
the shared /inference/go/v1 root that serves chat, responses and
messages.
2026-10-16 19:36:11 -07:00
Mikołaj Kondratek b549ceb4bb fix(llms): send max_completion_tokens for gpt-6 ids on OpenAI-compatible endpoints (#15137)
The reasoning-era model-id matcher only covered o1/o3/o4 and gpt-5, so
gpt-6 requests (gpt-6-sol, gpt-6.1-sol, gpt-6-1-sol) kept max_tokens and
OpenAI/Azure rejected them. Widen the gpt pattern to gpt-5 through gpt-9,
keeping the version digit single so Azure's gpt-35-turbo stays out.
2026-10-16 11:14:20 -07:00
Mikołaj Kondratek 44b388b998 chore(vscode): fix integration test runner on macOS (#15088)
* chore(vscode): fix integration test runner on macOS

Bump @vscode/test-electron to 3.1.0, which resolves the macOS executable
from Info.plist. VS Code 1.110+ renamed Contents/MacOS/Electron to Code
and dropped the compatibility symlink, so 2.5.2 failed every run with
`spawn .../Contents/MacOS/Electron ENOENT`.

Also pass a short --user-data-dir on macOS. VS Code puts its IPC socket
in the user data dir, and the default .vscode-test/user-data overflows
the 103-char unix socket limit from deep checkouts such as worktrees
(`listen EINVAL ... 1.14-main.sock`). Linux and Windows keep the default.

* test(vscode): drop the macOS E2E executable fallback

@vscode/test-electron 3.1.0 resolves the macOS executable from the app
bundle's Info.plist for both Stable and Insiders, so downloadAndUnzipVSCode
now returns Contents/MacOS/Code directly and the Code / Code - Insiders
fallback never runs.
2026-10-16 11:13:15 -07:00
Bee f67e933376 fix(desktop): bake the OTLP trace exporter into desktop builds and record who launched the hub (#15135) 2026-10-16 11:11:53 -07:00
Saoud Rizwan 01b8a9724d chore(vscode): release v4.1.25 v4.1.25 2026-10-15 23:21:22 -07:00
Saoud Rizwan 98a53322f9 chore(desktop): release v0.0.47 desktop-v0.0.47 2026-10-15 23:18:46 -07:00
Mikołaj Kondratek 9098d603cc feat(webview): name the host editor in Cloud sessions copy (#15133)
* feat(webview): name the host editor in Cloud sessions copy

The Cloud sessions copy said "your editor". Name the editor the user is
actually in instead: "VS Code", "Cursor", "PyCharm" and so on.

The extension already gets the product name from the host bridge
(getHostVersion's platform); fetch it once and pass it to the webview as
hostName. The webview shortens it the way users say it (drops the
JetBrains edition, "Visual Studio Code" -> "VS Code") and falls back to
"your editor" when the host is unknown.

* fix: read the host name from HostRegistryInfo instead of a bridge call

HostRegistryInfo already holds getHostVersion's platform from startup, so
building webview state no longer waits on the host bridge. The tooltip
test now asserts the visible text instead of reusing the function it tests.

* fix(webview): fall back to "your IDE" when the host is unknown
2026-10-16 08:06:59 +02:00
Saoud Rizwan d9deb814e8 chore(cli): release v3.0.72 cli-v3.0.72 2026-10-15 22:25:46 -07:00
Mikołaj Kondratek 1faa00fa25 fix(webview): use editor-neutral wording in Cloud sessions copy (#15123)
The webview is shared with the JetBrains plugin, where "after you close
VS Code" is wrong. Say "your editor" instead in the onboarding/GitHub
cards, the Run task hint and the cloud auto-approve tooltip.
2026-10-16 07:13:55 +02:00
TheRealSpencer cd01a92faa security: dependency floor lifts for open Dependabot advisories (#15132) 2026-10-15 23:02:38 -05:00
Saoud Rizwan 2bbaa7a8d3 chore(sdk): release v0.0.94 sdk/sdk/v0.0.94 sdk/core/v0.0.94 sdk/agents/v0.0.94 sdk/llms/v0.0.94 sdk/shared/v0.0.94 2026-10-15 20:22:09 -07:00
Saoud Rizwan 5d5d2e90bf test(sdk): route OpenCode Go messages tests through minimax-m3
The model catalog no longer lists minimax-m2.7 for OpenCode Go, so the
anthropic-protocol routing cases fall back to chat/completions. Use
minimax-m3, which the catalog still serves over messages.
2026-10-15 20:22:08 -07:00
Saoud Rizwan 23791b9323 fix(desktop): pass --use-system-ca when launching the backend on the bundled CLI (#15125)
The desktop backend now runs as `BUN_BE_BUN=1 cline-cli run <bundle>`.
In that mode Bun ignores the flags baked into the CLI with
--compile-exec-argv, so the backend lost the --use-system-ca that #14462
added and went back to trusting only Bun's bundled roots on macOS and
Windows. Requests the backend makes itself (model lists from a LiteLLM or
other intranet endpoint, sign-in refresh, marketplace, cloud sessions)
failed with "unable to get local issuer certificate" behind a corporate
CA. Pass the flag on the run command, and mirror it in the startup test.
desktop-nightly-20261016020842
2026-10-15 17:25:25 -07:00
Bee ee7f4f5c66 fix(llms): retry stream errors and report terminal failures to Langfuse (#15100)
* fix: report stream failures as errors in logs and Langfuse

* fix: correlate model failures and distinguish timeout aborts

* fix: enable three stream retries with terminal error reporting

* fix(llms): close failed attempt spans and retain trace call IDs

* docs(llms): clarify request and stream retry ownership

* fix(llms): classify attempt errors before exporting finished spans

* fix(llms): preserve successful model span completion timing

* fix(llms): use camelCase for error context fields
2026-10-15 14:42:30 -07:00
Saoud Rizwan c8f808b51e test(core): expect the OpenCode Go /inference/go/v1 endpoint in routing tests (#15051)
The catalog refresh in #15047 moved OpenCode Go from /zen/go/v1 to
/inference/go/v1 and updated the llms tests, but the core routing test
still asserted the old URL, failing sdk-test on main (and therefore
sdk-publish).
2026-10-15 13:25:30 -07:00