Commit Graph
1549 Commits
Author SHA1 Message Date
John Choi 6926a8c086 refactor(cloud): remove unused handoff plumbing 2026-10-23 17:47:11 -07:00
John Choi 304c4234c8 refactor(cloud): include initial messages in session creation 2026-10-23 17:32:05 -07:00
John Choi 92e8979d8f refactor(cloud): reuse request failure code for lost replies 2026-10-23 17:12:23 -07:00
John Choi 882c456753 fix(cloud): send initial handoff prompt before follow-ups 2026-10-23 17:08:00 -07:00
John Choi e0ca19614c fix(cloud): keep initial task dispatch owned by the Hub 2026-10-23 15:44:12 -07:00
John Choi 56a028ed51 Merge main keybindings changes into desktop cloud handoff 2026-10-23 14:00:19 -07:00
BeeandSaoud Rizwan b11ad3abc0 feat(desktop): configurable keybindings setting (#15097)
* feat(desktop): configurable keybindings with hold-to-quit

Add a keybindings.json (settings/clients/desktop) that maps desktop app
shortcuts, a Keybindings settings view to record them, and Keybindings
menu items in the app and Help menus. Quit can require holding the keys
(default 1s on macOS) to avoid quitting by accident. Add Kbd/KbdGroup to
@cline/ui for rendering shortcuts.

* fix(desktop): harden keybinding capture and hold-to-quit

- Handle a custom quit shortcut with no hold time in the webview instead of
  only restoring native Cmd+Q, which never fired the custom key.
- Quit only from a key-repeat event at or past the hold threshold so time
  after the key was released never counts.
- Suspend all shortcuts while one is being recorded so re-recording the quit
  keys cannot quit the app.
- Enforce Shift for named keys (Mod+Enter no longer matches Mod+Shift+Enter).
- Compare platform-resolved shortcuts for conflict warnings so aliases such
  as Cmd+N and Mod+N are flagged.
- Ignore stale save broadcasts while a newer save is in flight.
- Normalize the released key (Space) when ending a hold.
- Never rewrite an existing keybindings.json when opening it, so a malformed
  file can be fixed by hand.
- Fix the documented file path and two a11y lint errors.

* fix(desktop): restart quit hold on each fresh key press

* fix(desktop): validate shortcuts and restore native quit when unfocused

* fix(desktop): consume app shortcuts before input key handlers

* fix(desktop): stop the quit shortcut from reaching input handlers

---------

Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
2026-10-23 13:55:43 -07:00
John Choi 396e692084 Merge main into desktop cloud handoff 2026-10-23 13:46:49 -07:00
5a5e5acb7d refactor(core): move desktop cloud session orchestration into the hub (#15205)
* refactor(core): move desktop cloud session orchestration into the hub

* fix(core): compare cloud account scope without hashing credentials

* fix(core): address hub cloud session review concerns

* fix(desktop): preserve successful account switches when cloud refresh fails

* fix(core): treat in-flight cloud commands as busy when replacing the hub

Hub replacement decided busy-ness from session.list, which never reported
cloud work, so a newer install could retire the hub mid-provisioning and
fail the pending create. session.list now reports activeCloudCommands, and
the automatic retirement, explicit upgrade, and recovery checks count it.

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

* fix(core): scope cloud discovery fallbacks to their organization

* fix(core): include organization lookup in cloud discovery deadline

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-10-23 13:41:53 -07:00
John Choi 554d965f16 Merge Hub cloud discovery deadline fix 2026-10-23 12:59:57 -07:00
John Choi e57b0572db Merge Hub organization-scoped discovery fix 2026-10-23 12:33:20 -07:00
abeatrix 90ce357074 fix(core): include organization lookup in cloud discovery deadline 2026-10-23 12:30:13 -07:00
abeatrix 69e564efc8 fix(core): scope cloud discovery fallbacks to their organization 2026-10-23 11:05:13 -07:00
Saoud Rizwan 1619168bde fix(llms): keep tests green after the release catalog regen (#15240)
* fix(llms): keep Bedrock Sonnet 4.5 through models.dev deprecation

models.dev now marks Claude Sonnet 4.5 on Bedrock (bare id and all geo
profiles) and Z.AI Coding Plan's glm-5.2 as deprecated, and catalog
normalization drops deprecated models. The next `bun run version` regen
would therefore:

- remove Sonnet 4.5 from the Bedrock catalog, so resolveBedrockModelId
  can no longer confirm a geo profile and sends the bare id, which AWS
  rejects for on-demand use
- leave zai-coding-plan's default model missing from its catalog

Retain the deprecated Sonnet 4.5 Bedrock entries in normalization (used
by both generation and the live catalog refresh) until AWS retires the
model, and move the Z.AI Coding Plan default to glm-5.3.

Also stop pinning ClinePass fallback tests to a specific model the Cline
backend no longer lists; they now check against the generated catalog.

* test(desktop): give the compiled plugin startup test a generous import timeout

Cold Windows runners intermittently take longer than the 4s default to start
the sandbox child, failing sdk-test. The test covers resource loading, not
startup time.

* revert(llms): drop the deprecated Bedrock Sonnet 4.5 retention

Let models.dev deprecations flow through the catalog as before. Point the
Bedrock geo-prefix test at Claude Haiku 4.5, which models.dev still lists, so
it passes after the release catalog regen.
2026-10-22 16:55:24 -07:00
John Choi 714685f2fa fix(desktop): integrate cloud handoff with hub ownership 2026-10-22 16:13:28 -07:00
Cursor AgentandSaoud Rizwan f00ea3ec32 fix(core): treat in-flight cloud commands as busy when replacing the hub
Hub replacement decided busy-ness from session.list, which never reported
cloud work, so a newer install could retire the hub mid-provisioning and
fail the pending create. session.list now reports activeCloudCommands, and
the automatic retirement, explicit upgrade, and recovery checks count it.

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-10-22 21:34:26 +00: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
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
abeatrix 234cb7b0f6 fix(desktop): preserve successful account switches when cloud refresh fails 2026-10-20 19:26:39 -07:00
abeatrix d12f57fe1e fix(core): address hub cloud session review concerns 2026-10-20 18:54:16 -07:00
abeatrix 4acf2c25ea Merge main and resolve hub cloud orchestration conflicts 2026-10-20 18:31:43 -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 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
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
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
abeatrix 0abc68fbfd fix(core): compare cloud account scope without hashing credentials 2026-10-19 16:09:47 -07:00
abeatrix 5fcc892f6d refactor(core): move desktop cloud session orchestration into the hub 2026-10-19 16:01:05 -07: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
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
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 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
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 2bbaa7a8d3 chore(sdk): release 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
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 90f9ba059e feat(desktop): remove the Cloud sessions settings toggle (#15110)
* 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).
2026-10-15 13:23:49 -07:00
Tomás Barreiro 48594e5a7c Log request ids (#15044)
* Log request ids on failure logs

* refactor

* Capture only the base error message

* address review comments
2026-10-15 14:13:09 +02:00
Dominic Cooney 789f79e46d feat(core): run plugins only in workers; drop the in-process mode (#15069)
Plugin code never runs on a host's main thread. The in_process execution
mode is removed along with the fallback to it when a host shipped no
worker bootstrap: that fallback turned a loud "plugins do not load" into
a silent "plugins run inside the hub", which is the failure class behind

CLINE_PLUGIN_MODE is now `worker` (default) or `sandbox`; `in_process` is
no longer honoured.

A host that ships no bootstrap for the requested mode fails every plugin
load with PluginBootstrapMissingError, which names
CLINE_PLUGIN_BOOTSTRAP_PATH, so the cause shows in `cline config tools`,
`cline hub plugins`, and session-start warnings instead of plugins
silently dropping. The SSH remote helper is such a host today: it is
uploaded as a single file with no bootstrap beside it, so plugin tools
are reported missing there instead of running inside the remote hub.

With no plugin code in the host, the registry loses the jiti import
path, per-session module copies, AsyncLocalStorage call scoping, the
__clinePluginHost shim, and stack attribution of uncaught errors. The
daemon's uncaughtException / unhandledRejection handlers are fatal
again. The in-process registry tests that cover retained behaviour
(hook timeouts and error modes, multi-session notices, capability
checks, discovery and settings issues, command/rule/builder timeouts,
host-rejected registrations, timeout overrides, reload) move to the
worker suite.

How each host obtains the bootstrap and the SDK packages plugins
import, and embedding them in compiled binaries, is left to follow-ups.
2026-10-14 16:42:19 +09:00
Saoud Rizwan adc7b15535 fix(vscode): include attachments in ask_question answers (#15059)
* fix(vscode): include attachments in ask_question answers

Answer a pending ask_question with the user's images and attached files
in the tool result itself, as the pre-SDK extension did, instead of
dropping them. The SDK's AskQuestionExecutor may now return text and
image blocks (the same shape read_file returns), and the answer bubble
shows the attachments.

* fix(vscode): let cancel settle an ask_question answer while attachments load

Cancelling the task while an answer's attached files were still being
extracted could not release the question, so the old run (and anything
waiting for it to stop) stalled until extraction finished. Keep the
claimed resolver reachable so clearPending settles it immediately.
2026-10-14 00:17:19 -07:00
BeeandSaoud Rizwan 83ea9a41d1 refactor: Start the desktop and SSH remote hubs through the bundled Cline CLI (#14792)
* Let hosts choose the hub daemon launcher and defer spawn-only setup

Adds setHubDaemonLauncher so an embedding process can start the hub
daemon through a bundled Cline CLI instead of its own executable, and a
beforeSpawn hook on ensureDetachedHubServer that only runs when a new
daemon is actually started.

* Add programmatic options to cline hub ensure

hub ensure/start gain --json (URL + auth token), --allow-port-fallback,
--no-connectors and --login-shell-path, and the hub command accepts
--discovery-path for a dedicated discovery record. These let the desktop
app and SSH remotes start or reuse a hub through the CLI.

Also extracts the standalone binary compile step into
script/compile-binary.ts so other packages can build the CLI binary.

* Run SSH remote hubs through the Cline CLI

SSH remotes now upload the Cline CLI binary and start or reuse the remote
hub with 'cline hub ensure --json --discovery-path ...', stopping it with
'cline hub stop'. The dedicated remote helper entrypoint is removed;
cleanup records from older releases still stop through the old flag.

* Run the desktop backend on the bundled Cline CLI

The desktop app no longer compiles its own executable. It bundles the
self-contained Cline CLI (externalBin cline-cli) plus the backend as a JS
bundle that runs on the CLI's embedded runtime. At startup the backend has
the CLI run 'hub ensure', which reuses a compatible healthy Hub or starts
one, and any Hub it starts later also goes through the CLI binary. Linux
CLI copies are bundled for SSH remotes.

* Launch the desktop backend through the bundled Cline CLI

The Tauri shell resolves the bundled cline-cli and the backend bundle
(per-platform resource layouts) and starts 'cline-cli run' on it. The
Windows installer stops users of cline-cli.exe, and also stops and removes
the backend executable of earlier releases on upgrade.

* Recognize the CLI-hosted desktop backend in cline doctor --fix

* Update desktop publish workflow and docs for the bundled Cline CLI

Telemetry selfchecks and smoke tests run the backend bundle on the
bundled CLI, and the Windows signature gate verifies cline-cli.exe.

* fix(desktop): address runtime packaging review findings

* fix(desktop): preserve failed hub cleanup and handle exited daemons

* fix(hub): distinguish missing discovery records from read failures

* fix(hub): preserve discovery recovery while enforcing strict shutdown reads

* fix(cli): do not count hub commands as CLI activations (#14870)

* fix(cli): do not count hub commands as CLI activations

The desktop app runs `cline-cli hub ensure` on every launch and the SSH
remote flow runs `cline hub ensure` on every connect. Both went through
runCli(), which captured user.extension_activated unconditionally, so each
desktop launch was double-counted as a CLI activation and every SSH remote
host (with its own distinct id) showed up as a new CLI user.

Skip the activation capture for the hub subcommand; it is plumbing other
clients invoke, not a user activation. Hub-owned task telemetry is
unaffected since the daemon path never enters runCli().

* test(cli): clear the hub command mock between main.test.ts cases

* test(cli): stop stubbing the hub command module in main.test.ts

The module-wide vi.mock("./commands/hub") replaced createHubCommand with
a no-op, so `cline hub dashboard` (routed through createHubCommand) never
reached the dashboard mock and three dashboard tests failed. Drop the
module mock and assert the activation exclusion through
`hub dashboard --no-open`, which is already mocked.

---------

Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
2026-10-13 21:58:41 -07:00