Commit Graph

7107 Commits

Author SHA1 Message Date
Saoud Rizwan 4f5f238407 Desktop app: organize sidebar sessions into Pinned, Scheduled, and Tasks sections (#13528)
* Add Pinned/Scheduled/Tasks categories to desktop app sidebar

Replace the Schedules and Favorites filter-menu options with visible
collapsible category sections in the session sidebar, and rename the
Favorite action to Pin across the sidebar and sessions view.

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

* Grow full history window when Tasks show-more outpaces loaded tasks

loadMoreSessions treats its argument as a limit on all sessions, but the
Tasks show-more count only tracks Task rows, so once pinned/scheduled
rows pushed the loaded total past the requested count the call no-oped
and clicks went dead. Grow the whole history window via
loadOlderSessions instead, and only when the loaded tasks cannot fill
the next page. Addresses Greptile review on #13528.

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

* Auto-fill the Tasks page instead of fetching once per show-more click

A single 50-session window growth can consist entirely of pinned or
scheduled sessions, leaving a show-more click with no visible Tasks
progress. Replace the one-shot fetch with a page-fill effect that keeps
growing the history window until the requested Tasks page fills or
history runs out. Addresses the follow-up Greptile review on #13528.

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

* Halt page-fill retries after a failed history fetch

A failed fetch leaves the task count and has-more state unchanged,
which are exactly the conditions the page-fill effect fires on, so one
failing request would retry and re-toast forever. Halt the effect after
a failure and let the next explicit show-more click retry. Addresses
the third Greptile review on #13528.

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

---------

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-08-24 22:51:00 -07:00
Saoud Rizwan 8f69880ac4 Hide Channels and Agents sections from desktop app sidebar (#13527)
Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-08-24 21:54:59 -07:00
Saoud Rizwan a0c341e93c desktop: sidebar navigation cleanup with New/Schedule/Customize rows and dialog-based search (#13533)
* desktop: clean up sidebar navigation chrome

- Give New Task its own full-width labeled row below the logo row
  instead of an ambiguous icon next to the agenda toggle
- Wire the New Task row to the home action so starting a new task
  clearly takes you home (the logo still works as a fallback)
- Swap back/forward chevrons for browser-style arrow icons and
  bump their size

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

* desktop: sidebar New/Schedule/Customize rows and always-visible search

- Stack New (plus icon), Schedule, and Customize as full-width labeled
  rows below the logo; whole row highlights on hover via sidebarItem
- New starts a fresh task (home), Schedule opens Settings > Schedules,
  Customize opens the Customizations sections (Plugins first)
- Show the session search bar permanently above the sessions list
  instead of hiding it behind a search icon toggle

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

* desktop: move session search into a dialog behind a logo-row icon

- Replace the inline sidebar search bar with a search icon in the
  logo row that opens a cmdk command dialog listing sessions
- Selecting a result opens that session and closes the dialog
- Remove the agenda/tasks toggle the icon replaces, along with the
  now-unreachable sidebar Agenda panel (the welcome screen still
  surfaces agenda tasks)

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

* desktop: load full session history when the search dialog opens

Addresses Greptile review on #13533: the dialog only searched the
currently loaded history batch, so older unloaded sessions could not
be found. Opening search now kicks off loadAllSessions() (the hook's
purpose-built global-search loader), and the empty state reads
'Searching older sessions...' while more history is streaming in.

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

---------

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-08-24 21:53:47 -07:00
Saoud Rizwan f91af30401 Add Desktop App and Cloud Platform to bug report issue template (#13532)
* Add Desktop App and Cloud Platform to bug report surfaces

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

* Rename Surface Diagnostics field to Diagnostics

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

---------

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-08-24 19:49:47 -07:00
Saoud Rizwan 83b2588c9c Disable the agent todo tool and hide the Agenda UI in the desktop app (#13530)
* remove todo tool and Agenda UI, keep schedule-only tasks tool

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

* chore: biome formatting fixes

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

* restore agenda backend; disable todo kind behind a flag instead of deleting

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

* keep agenda automation pump idle while the todo tool is disabled

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

* remove todo tool and Agenda UI altogether (revert the disable-flag hybrid)

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

* restore all agenda code to main state

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

* disable agent todo tool and hide Agenda UI behind flags

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

---------

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-08-24 19:35:51 -07:00
Saoud Rizwan 6e09e81a79 Add suggested schedule templates to the desktop Schedules page (#13529)
* Add suggested schedule templates to desktop Schedules page

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

* Fix unreadable selected text in inputs caused by selection utility conflict

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

* Restyle Suggested section label as small gray uppercase

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

* Hide suggested schedule cards that match an existing schedule name

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

---------

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-08-24 18:14:01 -07:00
Saoud Rizwan dc43a57fd7 fix(tools): create new files with the platform-native line ending (#13521)
* fix(tools): use platform-native EOL for new files and preserve CRLF in apply_patch updates

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

* simplify to the minimal new-file EOL fix

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

* extract shared normalizeNewFileLineEndings helper

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

---------

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-08-24 17:54:54 -07:00
Saoud Rizwan 833cc891b5 chore(vscode): hide per-tool MCP auto-approve checkboxes behind a flag (#13522)
* chore(vscode): remove per-tool MCP auto-approve checkboxes from webview

MCP auto-approval is now governed solely by the global 'Use MCP servers'
toggle; the SDK approval path (shared with the CLI and desktop app) has no
per-tool granularity, so the per-tool and 'Auto-approve all tools'
checkboxes were no-ops that implied control that no longer exists. Remove
them from the MCP settings view and chat tool rows. The autoApprove arrays
in cline_mcp_settings.json and the toggleToolAutoApprove RPC are left
intact for the legacy extension.

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

* chore(vscode): hide per-tool MCP auto-approve checkboxes behind a flag

Keep the checkbox components, handlers, and RPC plumbing intact but gate
rendering behind SHOW_MCP_PER_TOOL_AUTO_APPROVE=false: the SDK approval
path (shared with the CLI and desktop app) is all-or-nothing via the
global 'Use MCP servers' toggle, so the per-tool checkboxes were no-ops.
Flip the flag back on if the SDK gains per-tool approval granularity.

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

---------

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-08-24 17:47:15 -07:00
Saoud Rizwan a2fb1d15ca fix(core): prevent search_codebase from crashing the process on giant single-line files (#13525)
* fix(core): prevent search_codebase from crashing the process on giant single-line files

searchWithRipgrep buffered all of rg's --json stdout into one string. Each
JSON event embeds the full text of the matched line (--max-columns is
ignored in JSON mode), so searching a directory of serialized trace dumps
(single-line multi-hundred-MB JSON files) accumulated gigabytes of stdout
until string concatenation threw RangeError: Out of memory inside the
stream data handler. That throw is outside the tool's try/catch, so it
escalated to an uncaughtException and killed the CLI/hub daemon.

Parse rg's JSON events incrementally line by line, drop events larger
than 256KB, truncate matched/context lines to MAX_LINE_CHARS, and stop
reading once maxResults is reached. The fallback regex scan now skips
files larger than 10MB (reporting the skip count) and truncates its
context lines the same way.

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

* simplify search_codebase crash fix to a minimal diff

Replace the incremental JSON-event parser with three small guards: stop
buffering rg stdout past 10MB, drop the trailing partial event before
parsing, and slice fallback context lines to MAX_LINE_CHARS. Drops the
fallback file-size skip and skip-count reporting.

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

---------

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-08-24 17:45:59 -07:00
Saoud Rizwan 8e7a55498b chore(cli): release v3.0.58 cli-v3.0.58 2026-08-24 15:44:16 -07:00
Saoud Rizwan 0cfc901589 fix(hub): flush the /shutdown 202 before daemon teardown
The /shutdown handler queued teardown on a microtask, which runs before
the event loop's write phase, so the daemon could process.exit() before
the accepted 202 was handed to the socket. Unix masked it (uv_try_write
lands small loopback writes synchronously); Windows has no such fast
path and lost the race regularly — the recurring shutdown.e2e.test.ts
'socket hang up' failures on windows-latest. Start teardown from the
response's write callback instead, with an idempotent 1s fallback so a
client that vanishes mid-write cannot strand the daemon, and send
Connection: close so the client gets a FIN rather than an abort.

Since the flakiness this compensated for is fixed at the source, restore
maxWorkers: 2 for the Windows core suite (serializing it cost ~3 min of
CI per run), and raise the e2e daemon discovery hang guard 10s→30s —
it guards against hangs, not runner speed.
sdk/sdk/v0.0.79 sdk/core/v0.0.79 sdk/agents/v0.0.79 sdk/llms/v0.0.79 sdk/shared/v0.0.79
2026-08-24 15:43:44 -07:00
Saoud Rizwan a5c3181b78 fix(vscode): don't steal last-used provider from ClinePass on credential refresh (#13520)
Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-08-24 15:18:04 -07:00
Saoud Rizwan 8cb60caf0c chore(sdk): release v0.0.79 2026-08-24 14:55:30 -07:00
Mikołaj Kondratek c03e452315 fix(sdk): carry root overrides into the Node smoke-test sandbox (#13517)
ci-node-smoke.ts installs the packed SDK tarballs with a plain npm
install in a fresh temp dir, where the repo root package.json overrides
do not apply. When @sap-cloud-sdk 4.9.0 shipped (2026-08-24) it broke
@sap-ai-sdk/ai-api 2.14.0 (via @jerome-benoit/sap-ai-provider in
@cline/llms) with ERR_PACKAGE_PATH_NOT_EXPORTED, failing the smoke step
on every PR even though the root already pins @sap-cloud-sdk/* to 4.6.0.

Copy the root overrides block into the generated sandbox package.json
so the smoke install resolves the same pinned versions as the repo and
future third-party releases cannot break it independently.
2026-08-24 23:49:52 +02:00
Saoud Rizwan 83ff8fd2f5 fix(hub): cap hub-events db size so it can't fill the disk (#13516)
* fix(hub): cap hub-events db size so it can't fill the disk

Row/time retention alone didn't bound disk usage: envelopes carrying
full session snapshots reach hundreds of KB each, so retained rows
could total tens of GB, sweeps only ran hourly, and DELETE never
shrinks a SQLite file. Enforce a 64 MiB size budget in prune() (oldest
rows first, VACUUM to return the space), and also prune after every
16 MiB appended so bursts can't outrun the hourly timer.

Fixes #13505

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

* fix(hub): tolerate VACUUM failure on a full disk

VACUUM needs scratch space and can fail in exactly the state a
ballooned event log causes. The byte-budget deletes already bound live
data, so swallow the error and let the next sweep retry the reclaim
instead of aborting startup pruning and disabling the durable log.

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

* fix(hub): count the size budget in UTF-8 bytes, not characters

envelopeJson.length (UTF-16 units) and SQLite LENGTH() (characters)
undercount multibyte text by up to 3x, which could leave a CJK-heavy
log settled above budget and re-running VACUUM every sweep. Use
Buffer.byteLength and LENGTH(CAST(... AS BLOB)) instead.

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

---------

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-08-24 14:47:26 -07:00
Mikołaj Kondratek 397a6a3341 fix(vscode): resolve hook workspace identity from the window, not shared global state (#13352)
* fix(vscode): resolve hook workspace identity from the window, not shared global state

Hook discovery, hook cwd selection, and the workspaceRoots metadata passed
to hook scripts all read the workspaceRoots/primaryRootIndex global state
keys. Global state lives in ~/.cline and is shared by every Cline instance
(all VS Code windows, the CLI, the JetBrains plugin), and nothing writes
these keys anymore, so hooks resolved against whatever project some other
or older instance last recorded. With a second window open on another
project, a workspace's .clinerules/hooks scripts were never discovered.

Resolve workspace roots via a single guarded helper backed by
HostProvider.workspace.getWorkspacePaths() (in-process, window-scoped,
same as refreshHooks): blank paths are filtered, a host-bridge failure
degrades to no workspace roots instead of silently disabling global hooks
or skipping blocking PreToolUse guards, and one resolution is threaded
through hooks-dir discovery, cache misses, cwd selection, and hook input
metadata so they can't disagree (previously up to four host lookups per
hook execution — real gRPC round trips in the standalone host). Roots and
hooks dirs are matched on whole path segments with the longest root
winning, so prefix-sharing or nested workspace roots resolve to the right
project. The adapter creates the runner once per event and skips no-op
runners, making creation the single resolution point; the separate
hasHook/getHookInfo checks are removed. The dead workspaceRoots and
primaryRootIndex state keys are dropped, and the four hand-rolled
HostProvider.workspace test stubs are consolidated into one shared
helper.

* test(vscode): add e2e coverage for workspace-scoped hook discovery

Boots real VS Code with the packaged extension against the workspace
fixture, sends a prompt, and asserts the fixture's UserPromptSubmit hook
was discovered from the open window's workspace, executed with that
workspace root as its cwd, and received the same root in its
workspaceRoots input — the end-to-end contract the hook workspace
identity fix establishes.

* test(vscode): isolate the e2e hook fixture from the shared workspace

The UserPromptSubmit fixture hook lived in the shared e2e workspace, so
every prompt-sending spec executed it (hooksEnabled defaults to true) —
and its cold PowerShell spawn on Windows pushed chat.test.ts past the
5s expect timeout. hooks.test.ts now overrides workspaceDir to a
dedicated workspace-hooks fixture, so only the hooks spec pays the hook
spawn.
2026-08-24 23:28:11 +02:00
Saoud Rizwan c9b75155ea fix(cli): remove the $4.99 ClinePass promo copy (#13514)
The $4.99 first-month promo is ending, so the CLI's first-launch "Try ClinePass" dialog should no longer advertise it. Also drops the leftover CLI_PROMO_CODE plumbing, which has been an empty string since the promo-code flow was removed.
2026-08-24 13:09:42 -07:00
Saoud Rizwan 09ee902639 chore(vscode): release v4.1.15 v4.1.15 2026-08-23 12:33:23 -07:00
Saoud Rizwan 2b7b01328a fix(vscode): auto-approve all MCP tool calls when the MCP toggle is on (#13498)
* fix(vscode): honor MCP auto-approve settings for SDK tool calls

The SDK extension required both the global 'Use MCP servers' auto-approve
toggle AND each tool's per-tool autoApprove flag before silently approving
an MCP call, while the legacy extension treated them as either/or. Restore
the legacy OR semantics so toggling MCP auto-approve works again.

Also key toolPolicies by the registered SDK tool name (via
defaultMcpToolNameTransform, now exported from @cline/core) instead of raw
server__tool. Servers whose names contain sanitized characters (e.g.
marketplace names like github.com/user/repo) or exceed 64 chars produced
policy keys that never matched the registered tool, so those MCP tools ran
without any approval gate; the live auto-approve lookup now re-applies the
transform instead of string-splitting the name.

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

* Revert "fix(vscode): honor MCP auto-approve settings for SDK tool calls"

This reverts commit 86c568fbba.

* fix(vscode): auto-approve all MCP tool calls when the MCP toggle is on

The SDK extension only auto-approved an MCP call when the global 'Use MCP
servers' auto-approve toggle AND that tool's per-tool autoApprove flag were
both set, so toggling MCP auto-approve appeared to do nothing and users had
to opt in each tool individually. The toggle alone now governs all MCP
tools; the per-tool flag is no longer consulted.

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

---------

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-08-23 12:12:32 -07:00
Saoud Rizwan be8b984d10 chore(vscode): release v4.1.14 v4.1.14 2026-08-23 02:41:04 -07:00
Saoud Rizwan c870116d1d fix(telemetry): emit task.completed from every session teardown path (#13489)
The task.completed fallback lived only inside shutdownSession, but
stopSession/dispose route interactive sessions with a terminal reported
status through releaseSessionRuntime, which never emitted. Truthful
session-status reporting (shipped in 4.1.11) re-routed a large share of
interactive stops onto that branch and silently dropped the event.

Route the emission through a single choke point,
emitTaskCompletedOnTeardown, called from both shutdownSession and
releaseSessionRuntime. The completion criterion no longer reads
session.status: interactive sessions use the recorded final-turn
outcome (lastInteractiveTurnFinishReason), non-interactive sessions
keep the existing input.status === "completed" logic. A new
taskCompletedEmitted flag (also set by the submit_and_exit observer)
enforces exactly one task.completed per session. failSession now
records the errored final turn so a stale "completed" from an earlier
turn can never leak into the teardown emission. Telemetry only; no
user-facing behavior changes.
2026-08-23 02:34:26 -07:00
Saoud Rizwan 4f836ae7d0 test(sdk): give windows-sensitive suites realistic timeouts
Four consecutive SDK publish runs failed on windows-latest, each on a
different test, all of them plain timeouts: two @cline/shared SQLite
tests at the 5s vitest default, core's bash executor at 10s, and the hub
singleton endpoint test at 10s. The 2-core Windows runner spawns forks
and takes SQLite locks slowly enough to blow those budgets under load.

These timeouts guard against hangs; they are not timing assertions (the
one suite that does assert elapsed time, shutdown.e2e, was fixed by
removing file-level parallelism instead). Raise core to 20s and give
@cline/shared an explicit 15s in place of the inherited 5s default.
sdk/sdk/v0.0.78 sdk/core/v0.0.78 sdk/agents/v0.0.78 sdk/llms/v0.0.78 sdk/shared/v0.0.78
2026-08-22 16:39:19 -07:00
Saoud Rizwan 6cb653a362 chore(desktop): release v0.0.16 desktop-v0.0.16 2026-08-22 16:34:23 -07:00
Saoud Rizwan 5077fe8697 fix(core): run hub e2e files serially so daemon timing budgets survive CI contention
singleton.e2e.test.ts (added in #13468) spawns real daemons and runs for
~15s. Vitest's default file parallelism let it run alongside
shutdown.e2e.test.ts, whose assertions are wall-clock bound: discovery
within 10s, exit within 5s, and a 2s shutdown watchdog. On the 2-core
windows-latest runner that contention alone broke those budgets, failing
the shutdown test two different ways across runs — once never observing
discovery, once with the daemon forced to exit before its HTTP 202
flushed (socket hang up). The test passed on Windows before #13468 and
has failed every SDK publish run since.
2026-08-22 15:18:04 -07:00
Saoud Rizwan 2266fe8cf4 chore(cli): release v3.0.57 cli-v3.0.57 2026-08-22 13:25:40 -07:00
Saoud Rizwan 21cb8d2525 chore(sdk): release v0.0.78 2026-08-22 13:03:18 -07:00
Saoud Rizwan 68ad354b52 chore(vscode): prepare 4.1.13 release v4.1.13 2026-08-22 12:50:54 -07:00
Saoud Rizwan e098a8ed0d fix(core): stop stored capability lists from silently revoking tool calling for custom models (#13476)
* fix(core): seed tools capability when custom model capabilities are synthesized from boolean flags

For a models.json entry with no explicit capabilities list, toStoredModelInfo
synthesized a capability array purely from boolean convenience flags (e.g.
supportsReasoning: true -> ["reasoning"]). modelSupportsToolCalling fails open
only for a missing or empty list, so the synthesized non-empty list read as an
authoritative denial and silently stripped every tool definition from requests
to custom OpenAI-compatible models (#13463).

Seed "tools" whenever the list was not explicitly authored and the boolean
projections made it non-empty, preserving the fail-open contract. Explicitly
authored capability lists remain authoritative and can still disable tools.

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

* test(core): cover stale catalog capability overrides

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

* fix: treat stored capability lists as non-authoritative for tool calling

The hasExplicitCapabilities guard still let two producers of tool-less
lists through:

- The VS Code legacy-override migration (legacyModelInfoToOverrides)
  persists explicit partial lists like ["prompt-cache"] into models.json
  for custom OpenAI-compatible models, which then read as an authoritative
  "cannot call tools" and drop every tool - same symptom as #13463.
- Any hand- or UI-authored partial list on a non-catalog model.

Stored entries and user-authored provider metadata have no way to declare
"cannot call tools" (there is no supportsTools field, and every writer
that authors a full list includes "tools"), so seed "tools" into any
non-empty list for a language model. Only generated catalog capabilities
remain authoritative - a genuine no-tools catalog model stays that way -
and non-language models (e.g. image generation) never gain a tools claim.

Also make legacyModelInfoToOverrides write "tools" into the arrays it
fabricates, matching the providers.json migration, so models.json stops
being poisoned for older readers.

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

---------

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-08-22 12:42:09 -07:00
Bee 1de61b178a feat(hub): add drain and upgrade commands with replay support (#13468)
* feat(hub): add drain and upgrade commands with replay support

* handles disconnection

* feat(hub): wire bot profiles, drain, and durable event/run-queue into the live transport

Completes the wiring the previous commits' primitives needed:
HubServerTransport gains isDraining(), hub.drain/hub.status/profile.get
command handling, and replayEventsAfter() (backed by the durable event
log), plus the sequence/sinceSequence wire types they depend on in
shared/hub.ts. run-queue-handlers.ts reads the active bot profile's
plugin roots when executing durable runs.

Also adds hub/profiles/: profile.json (identity/rules/plugins) ->
system prompt composition, --profile / CLINE_HUB_BOT_PROFILE
resolution, and the bundled cline-dad profile with its
cline_hub_support read-only diagnostics tool.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* Revert "feat(hub): wire bot profiles, drain, and durable event/run-queue into the live transport"

This reverts commit 6696d5d202.

* fix(hub): dedupe replayed events by eventId, not just sequence

HubEventLogStore.append() returns a new envelope stamped with a
sequence rather than mutating the input, so a pending approval
re-issued sequence-less by subscribe() (it predates any durable-log
append) and its later sequence-stamped copy from the durable log are
two different objects carrying the same eventId. The replay-then-live
buffer in browser-websocket.ts only deduped by sequence, so the
sequence-less copy's guard never tripped and it was delivered a second
time when the buffer flushed after replay.

Track delivered eventIds alongside the sequence cursor; eventId
survives the append/stamp round-trip unchanged, so this dedupes the
exact-same logical event regardless of which copy arrives first.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(hub): wire drain, durable event log, and run queue into the live transport

CI on this branch failed bun run build:sdk: browser-websocket.ts,
client/index.ts, and hub-websocket-server.ts (already on this branch)
reference sequence/sinceSequence, HubServerTransport.isDraining(), and
the "hub.drain" command — but the commit that reverted bot profiles
out of this branch also reverted this wiring, since it shared a commit
with the profiles work. That wiring is a hub concern, not a
bot-profiles one; split it back out.

- shared/hub.ts: sequence/sinceSequence types, run.enqueue/run.list/
  hub.drain/hub.status/stream.replay capability, command, and event
  names. profile.get intentionally excluded — stays bot-profiles-only.
- context.ts: isDraining() on HubTransportContext. botProfile field
  intentionally excluded.
- hub-server-transport.ts: eventLog/runQueue fields and start/stop
  lifecycle, publish() appends to the durable log, handleCommand cases
  for run.enqueue/run.list/hub.drain/hub.status, drain-refusal check,
  replayEventsAfter()/lastEventSequence(). startBotProfile()/
  startHubSupportTool() and the profile.get case intentionally
  excluded.
- run-queue-handlers.ts: added without handleProfileGet (needs
  ctx.botProfile, which doesn't exist here).
- hub-upgrades.test.ts: added without its two bot-profile-injection
  tests (they need a resolved bot profile to assert against).

Verified bun run build:sdk exits 0 (the exact CI command) and
bunx vitest run src/hub passes (311/312; the one failure is the
same pre-existing environment-timing flake already present before
this change).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(hub): export instance-lock, event-log, and run-queue from the hub barrel

These landed as internal modules only; hub-server-transport.ts and
hub-websocket-server.ts import them by direct path, but nothing
re-exported them from the public @cline/core/hub surface the way
sibling discovery/server modules already are.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(hub): wire the instance lock into the daemon entry point

The singleton lock (discovery/instance-lock.ts) and its consumption in
startHubWebSocketServer/ensureHubWebSocketServer were already on this
branch, but the daemon entry point's own half was not: retrying a bind
when a retiring predecessor still holds the lock, and exiting with a
distinct code (3) instead of the generic fatal path when a live Hub
already owns the data directory. Without this, a daemon racing a
retiring predecessor could fail outright instead of waiting the lock
out, and losing the singleton race looked identical to a crash.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(hub): address drain/upgrade review findings (#13478)

- cline hub upgrade: check idleness at least once (--wait 0 works), reject
  non-numeric --wait, and un-drain on every abort path so an aborted
  upgrade can never leave the hub refusing new work
- add cline hub drain --off and the off query param to requestHubDrain so
  POST /drain?off is reachable from shipped code
- HubEventLogStore/HubRunQueue: WAL journal mode + busy_timeout, and stamp
  sequences from lastInsertRowid instead of SELECT MAX(sequence)
- HubInstanceLock.acquire: degrade to an unheld lock when SQLite is
  unavailable instead of refusing hub startup; only BUSY/LOCKED still
  raises HubLockHeldError
- ensureHubWebSocketServer: retire an unusable discovered hub through the
  shared retireDiscoveredHub (busy hubs are attached to, drain precedes
  shutdown, discovery cleared only when the hub actually retired)
- replay adapter: advance the cursor past eventId-deduped events, cap
  replay pages, stop when the cursor stalls, and drop the dedupe set after
  the buffered flush so it cannot grow for the socket lifetime

Co-authored-by: Cursor Agent <cursoragent@cursor.com>

* fix(hub): derive the singleton e2e challenger cwd portably

The challenger's working directory was derived by round-tripping the
discovery path through a file: URL and stripping the last pathname
segment. On Windows that yields a POSIX-style '/C:/...' path, which is
not a valid spawn cwd, so the spawn fails ENOENT before the singleton
lock is ever contested and the Windows SDK test job goes red.

The data dir is simply the discovery file's parent: use dirname().

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

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com>
Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-08-21 21:49:21 -07:00
Saoud Rizwan e7ed29109b ci(vscode): make combined nightly manual-dispatch only
The PublishNightly environment gained required reviewers, so each cron
run parked on approval, held the workflow's concurrency group, and
silently cancelled every scheduled run queued behind it. 20 consecutive
scheduled nightlies died this way between 2026-07-31 and 2026-08-21;
the only nightlies that shipped in that window were manual dispatches.

Drop the cron rather than leave a trigger that cannot succeed unattended.
2026-08-21 17:01:56 -07:00
Bee 9316de6bb5 fix: propagate Langfuse session telemetry (#13473)
* fix telemetry session propagation

* feat telemetry client version metadata

* fix(core): address Langfuse review feedback — hub client identity + delegated agent session grouping (#13475)

* fix(core): rebuild hub session client identity from request headers

Hub-backed sessions do not transport extensionContext (it is local-only),
so the daemon's runtime built traces without the clientName/clientVersion
metadata even though the hub client bakes X-CLIENT-TYPE / X-CLIENT-VERSION
into the session's provider headers. Reconstruct extensionContext.client
from those headers during local runtime bootstrap so hub-backed Langfuse
traces carry the same client identity as local runtimes, and the daemon's
header re-resolution stops clobbering the original X-CLIENT-TYPE.

* fix(core): propagate parent distinctId/sessionId to delegated agents

Delegated agents (spawned sub-agents, configured agents, teammates) were
built without distinctId and sessionId, so their Langfuse traces had no
userId or sessionId and did not group with the parent user or session.
Thread the host-resolved distinctId through RuntimeBuilderInput and the
root sessionId through the delegated-agent config provider, and copy both
onto the delegated AgentConfig.

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-08-21 16:34:21 -07:00
Tomás Barreiro fb58e340a2 Add feature flags to the desktop app (#13289)
* Add feature flags to the app

* React to account updates

* Address comments

* use a per-app file
2026-08-22 00:25:30 +02:00
Saoud Rizwan db6d18a98a chore(vscode): prepare 4.1.12 release v4.1.12 2026-08-21 13:53:56 -07:00
yzxcj797 2ea460fa46 Treat an empty preserved capability list as unspecified when seeding tools (#13465)
* Treat an empty preserved capability list as unspecified when seeding tools

toSdkModelInfo guarded the tools seeding with a strict
preservedCapabilities === undefined check, but modelHasCapability —
the runtime's own reader — treats undefined AND length === 0 as
"unspecified". A custom OpenAI-Compatible model whose stored
capabilities field is a defined-but-empty array (a config carried over
from before the field existed, or one round-tripped through a boundary
that defaults it to []) skipped the seeding; the first boolean
projection to run afterwards (e.g. supportsReasoning) then populated
the array, the runtime gate read the non-empty, tool-less list as
authoritative, and every tool definition was silently dropped from the
session (#13463).

The guard now covers the empty array too, matching the reader's
unspecified semantics.

* test: satisfy the store's isModelInfo gate so the empty-capabilities case actually reaches knownModels

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

---------

Co-authored-by: yzxcj797 <yzxcj797@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-08-21 13:42:01 -07:00
Saoud Rizwan 7d366ce7d4 fix(vscode): remote config MCP settings (#13466)
* fix(vscode): enforce enterprise MCP controls on the Customize marketplace

The unified Customize marketplace replaced the old MCP marketplace
without carrying over enterprise remote-config enforcement: the catalog
RPC returned every MCP entry and installs were never policy-checked,
so orgs with mcpMarketplaceEnabled=false or an allowedMCPServers
allowlist saw (and could install) all marketplace MCP servers.

- Filter MCP entries out of getMarketplaceCatalog when the marketplace
  is disabled, and restrict entries to the allowlist when configured
  (matching entry id, display name, installed server name, or source
  repo URL, mirroring legacy GitHub-URL allowlist ids)
- Reject installMarketplaceEntry requests that violate the policy
- Map the published catalog's repo/homepage fields onto
  sourceUrl/homepageUrl so URL-based allowlists can match
- Update the enterprise MCP server controls docs

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

* refactor: simplify MCP marketplace policy enforcement

Fold the policy check into marketplace-helpers, drop the dedicated
test suite, and trim the docs edit to the strictly necessary line.

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

---------

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-08-21 12:40:01 -07:00
Saoud Rizwan fb60f9e5fd chore(desktop): release v0.0.15 desktop-v0.0.15 2026-08-20 22:42:08 -07:00
Saoud Rizwan 9e0015b78b chore(vscode): prepare 4.1.11 release v4.1.11 2026-08-20 22:07:44 -07:00
Saoud Rizwan 4a128d5f76 docs(cli): drop the tasks tool from the v3.0.56 notes, it is desktop-only sdk/sdk/v0.0.77 sdk/core/v0.0.77 sdk/agents/v0.0.77 sdk/llms/v0.0.77 sdk/shared/v0.0.77 cli-v3.0.56 2026-08-20 21:38:16 -07:00
Saoud Rizwan b5cfe88846 chore(sdk): release v0.0.77 2026-08-20 21:38:02 -07:00
Bee 355ce11ae2 refactor: centralize client tool availability (#13451) 2026-08-20 21:34:38 -07:00
Haley Park 05da55857a feat(desktop): reskin first-run onboarding (#13441) 2026-08-20 20:48:34 -07:00
Haley Park 35583ee8bb feat(desktop): interactive welcome hero graphic (#13399)
* feat(desktop): add interactive welcome hero

* feat(desktop): support composable welcome hero variants
2026-08-20 20:47:52 -07:00
Saoud Rizwan a8d260f1bd docs(cli): scope the v3.0.56 release notes to CLI-visible changes 2026-08-20 19:52:20 -07:00
Saoud Rizwan 59ee1ea80e chore(cli): release v3.0.56 2026-08-20 19:39:45 -07:00
Saoud Rizwan bd218aa7bb chore(sdk): release v0.0.76 sdk/sdk/v0.0.76 sdk/core/v0.0.76 sdk/agents/v0.0.76 sdk/llms/v0.0.76 sdk/shared/v0.0.76 2026-08-20 19:23:35 -07:00
cline-cloud[bot] 80b3b0348e docs: remove duplicate GLM-5.3 rows in ClinePass tables (#13449)
Co-authored-by: cline-cloud[bot] <276134852+cline-cloud[bot]@users.noreply.github.com>
2026-08-20 19:13:56 -07:00
Renee Huang 401cf5e12a docs: simplify Open Cline step in installing guide (#13405) 2026-08-20 18:32:58 -07:00
Bee 48feb02ae9 chore(deps): update Langfuse packages and bump app versions (#13443)
* chore(deps): update Langfuse packages and bump app versions

Update @langfuse/otel to v5.10.1 and add @langfuse/vercel-ai-sdk v5.9.1 for improved observability with Vercel AI SDK.

Bump versions for @cline/code to 0.0.14 and @cline/ui to 0.2.0-next.6, updated via bun.lock.

Other Changes:
Added optional userId to AgentRuntimeConfig.
Propagated userId, sessionId, conversationId, runId, iteration, provider, and model context into AI SDK telemetry.
Added AI SDK 7 runtimeContext with explicit includeRuntimeContext.
Added stable OTEL_SERVICE_NAME=cline-sdk.
Added runtime metadata assertions in agent tests.

* add taskId

* Revert "add taskId"

This reverts commit f20d31d96d.
2026-08-20 18:17:33 -07:00
Saoud Rizwan eef7958cad fix(core): report truthful session status so desktop checkpoint restore stops wedging (#13418)
* fix(core): keep hub session status truthful across queue-drained turns

Queue-drained turns settle only through the event stream, but the hub
runtime host mistranslated their lifecycle in two ways:

- session.updated events carrying only a snapshot (persistence updates)
  defaulted the projected status to "running". When one trailed the
  final idle update after a turn, clients that track busy state from
  status events (the desktop sidecar's workspace restore gate) stayed
  busy forever. Use the snapshot's real status and emit nothing when
  neither source reports one.
- the per-run agent.done dedup was only reset by run.started, which the
  daemon-side queue drain never publishes, so a drained turn's done was
  swallowed as a duplicate of the previous turn's. Reset the dedup on
  session.pending_prompt_submitted, and suppress stale run.completed
  events that land inside a drained turn's window so they can neither
  emit a phantom done nor consume the drained turn's dedup slot.

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

* test(desktop): cover restore unlock after an event-settled queued turn

Exports the sidecar's core-session event handler so the queued-turn
lifecycle (busy via status events, cleared by the done agent event,
restore allowed afterwards) is testable end-to-end.

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

* fix(core): start interactive sessions without a prompt as idle

The runtime host reported every new session as "running" until its
first turn ended. Interactive hosts (the desktop app) start sessions
with no prompt and dispatch turns through separate send calls, so a
created-but-never-prompted session stayed "running" forever — wedging
clients that gate workspace operations (checkpoint restore, message
edit) on active turns.

Interactive no-prompt starts now begin idle, start emits the session's
actual status (resumed sessions no longer masquerade as running), and
markTurn* transitions keep tracking in-memory status for lazily
persisted sessions so the first turn still reports running -> idle.

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

* style: format hub-runtime-host test filter

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

* refactor: drop the drained-turn done bookkeeping, keep the minimal fix

The stuck restore is fully explained by the two status defects (fabricated
"running" from snapshot-only session.updated events, and never-prompted
interactive sessions reporting "running"). The done-dedup machinery for
queue-drained turns addressed a separate cosmetic gap (queued turns emit no
chat_done, pre-existing) and required fragile run-window heuristics, so it
is removed to keep this change reviewable. Sidecar test now settles the
queued turn through the status event, matching the shipped mechanism.

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

* docs(sdk): document the truthful session-status contract

---------

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-08-20 18:17:19 -07:00
Saoud Rizwan 04e08187f3 fix(vscode): show the diff edit view for multi-line edits in CRLF files (#13417)
The edit preview computed proposed content with an exact old_text match, but
the SDK executor normalizes old/new text to the file's own line endings before
matching (#12305) - reads strip CR, so models emit LF-only text even for CRLF
files. Any multi-line old_text in a CRLF file therefore failed the preview's
match: the diff edit view silently never opened while the executor applied the
edit. Single-line edits (no line break in old_text) were unaffected, which is
why the diff view appeared to trigger inconsistently.

Mirror the executor's EOL normalization (and its literal $-sequence insertion)
in the preview computation.

Fixes #13296

Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com>
2026-08-20 14:55:19 -07:00