* 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.
* 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
* 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
* 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
* 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>
* 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
* 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.
* 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>
* 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
* 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
* 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>
* 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.
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.
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.
* 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.
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.
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.
* 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.
* 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
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.
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.
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.
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).
* feat(desktop): enable cloud sessions for everyone
Remove the Cloud sessions preview toggle from Settings and the
code-cloud-agents rollout flag that revealed it. Cloud sessions are now
on by default; CLINE_CODE_CLOUD_AGENTS=0 still turns them off for
development and tests.
* fix(desktop): keep the code-cloud-agents rollout flag as the cloud gate
Only the Settings opt-in should go away. Cloud sessions are enabled
wherever the code-cloud-agents PostHog flag is on (or the
CLINE_CODE_CLOUD_AGENTS env override forces them).