mirror of
https://github.com/cline/cline.git
synced 2026-10-13 17:16:30 +08:00
main
1149
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
c96fb0992a | chore(cli): release v3.0.71 | ||
|
|
df56169ed5 |
fix(cli): let the compiled binary resolve plugin SDK imports natively (#15048)
* fix(cli): let the compiled binary resolve plugin SDK imports natively
Plugins import @cline/core from the wrapper's node_modules. Bun standalone
executables skip package.json loading at runtime by default, so every bare
import from those files failed to resolve natively and jiti fell back to
babel-transpiling the whole SDK graph (~440 files, ~8s cold). That blew the
8s plugin load timeout after an upgrade or reboot and left the plugin
failed for the life of the hub. With autoloadPackageJson the cold load
takes ~1.4s, matching the 3.0.70 subprocess sandbox.
* fix(cli): show the resumed transcript when startup posts a notice
Resuming a session hydrates the transcript after the session starts. A
plugin load failure posts a status notice during that start, and the
hydration guard treated any existing entry as user activity and skipped
the transcript, so the resumed session looked empty. Skip only once the
user has submitted, and keep startup notices after the transcript.
* Revert "fix(cli): show the resumed transcript when startup posts a notice"
This reverts commit
|
||
|
|
12a4c6bfe2 |
feat(core): load plugins in the hub process and surface plugin errors (#14957)
* feat(core): load plugins in the hub process and surface plugin errors
Plugins now load in-process through one registry per process instead of a
node/bun subprocess. The compiled CLI and the hub it starts no longer need a
runtime on PATH, and plugins can use the Bun global under the Bun-built hub.
The subprocess sandbox stays available with CLINE_PLUGIN_MODE=sandbox.
The registry wraps import, setup, every hook, tool, and command call with
timeouts and error capture, and tracks loading/ready/degraded/failed/disabled
per plugin with the last error's phase, message, stack, and counts. A failing
plugin no longer silently drops its tools:
- session.create takes a `plugins` policy shaped like toolPolicies, and its
reply and session.created event carry `pluginIssues`
- failures after start (setup and hooks run on the first turn) reach each
affected session as a status notice
- the hub answers plugins.list/status/reload and broadcasts
plugin.status_changed; `cline hub plugins [--reload]` wraps them
- the daemon marks a plugin failed instead of shutting down when an uncaught
error's stack points into it
- the CLI prints a warning naming the plugin and error, and
`cline config tools --json` lists failed plugins as plugin_failure entries
Setup and tool contexts gain cwd and emitEvent; __clinePluginHost keeps
working as a shim. Compiled binaries fall back to jiti/static when babel is
not on disk next to them.
* fix(core): give each session its own copy of every plugin module
Plugins written for the per-session sandbox keep state at module level. The
cline-monitor plugin, for example, builds one plugin object per import and
throws "Create a separate monitor plugin handle for each session" on a second
setup(). Sharing one imported copy across hub sessions broke it on the
second session.
The registry now hands each session its own copy: the first session claims
the copy imported at startup, and later ones re-evaluate the module while
reusing jiti's transform cache (about 180ms for cline-monitor instead of
2.8s with no cache).
A setup() failure now costs only the session it happened in: other sessions
keep their copies, the next session tries again, and a successful setup
returns the status to ready. Import failures, attributed uncaught errors, and
repeated hook/tool failures still turn the plugin off for every session.
* docs(sdk): document the plugin hooks that exist and how hook failures behave
The Hook Stages list (snake_case stages such as tool_call_before) and the
Hook Policies table (mode, retries, queueLimit, maxConcurrency) described no
code: plugin hooks are the seven runtime hooks, and there is no per-hook
policy object. Replace both with the real hooks, what each can return, and
how hookErrorMode and the 3-second hook timeout apply.
* fix(core): report failed plugins as failed in settings
Settings marked a plugin "failed" only when the plugin tool report had no
entry for it. The report now lists failed plugins with their state, so they
showed as "available" (desktop Extensions page and other core settings
hosts). Use the reported state, and fill loadError with the failing phase
and message so the reason is visible.
Also tell only the calling session about a per-session setup failure;
other sessions' copies still work. Keep the hub log line's own message
instead of letting the plugin error text overwrite it.
* fix(core): address plugin registry review findings
Reload and generations: each session copy records the generation (import)
it came from. A reload starts a new generation without invalidating older
copies, so running sessions keep working. Failures and blocking are counted
per generation, so a broken reload cannot turn off copies that still work,
and an old copy's failures cannot change the current status. A stray error
attributed by stack turns off every live generation, since a stack cannot
tell copies of one file apart.
Sandbox mode: the hub daemon no longer preloads plugins in sandbox mode,
and tool listing and MCP settings sync inspect plugins through the sandbox.
The session plugin policy now applies in sandbox mode: paths whose file
name the policy turns off never reach the sandbox, and plugins matched only
by their exported name are dropped after import.
Calls: commands, rule content, and message builders go through the same
guarded path as hooks and tools (timeout, error capture, failure count), and
calls into a copy that is turned off, failed setup, or whose session ended
are refused. A failing rule contributes no text and a failing message
builder leaves messages unchanged.
Cleanup: ctx.onDispose registers per-session cleanup. Timers a copy creates
while its own code runs, including at import, are tracked and cleared when
the session releases the copy; host callbacks given to plugins run outside
that scope so host timers are never cleared with them. Release runs on
session stop and dispose, and now also when building the session runtime
fails. The automation-events example uses ctx.onDispose.
Registrations: automation event types are validated while setup runs. If
the host still rejects a registration on commit, the copy's setup is
recorded as failed and the error is rethrown so the partial registrations
are discarded.
Also: forward importTimeoutMs, hookTimeoutMs, and contributionTimeoutMs to
the in-process registry per session; key the plugin tool inspection cache on
registry status; keep the module copy imported by preload for the first
session; report settings-disabled plugins a session would use as issues
with reason "settings".
* fix(core): keep this bindings and route import-time plugin events
- Timer tracking forwards the runtime's this (the timer handle in Node and
Bun) to plugin callbacks.
- Plugin methods keep their receiver: rule content, message builders,
command handlers, and setup() are called on their own objects, including
setup() in the existing in-process loader.
- Each plugin copy owns one async scope from import onward. Claiming the
copy for a session fills in that scope's session id and event callback,
so events emitted by work the module started at import reach the session.
- Each generation tracks its own health, so an older copy's first failure
after a reload is reported to its sessions even though the status shows
the reloaded generation.
* fix(core): bind plugin changes to sessions started afterwards
Plugins are bound to a session when it starts; added, edited, or reloaded
plugins reach only sessions started afterwards. Change detection used the
entry file's mtime and size, which missed edits to files the entry imports
(common for package plugins) and same-size edits within one clock tick, so
the next new session could claim a stale preloaded copy.
Detect changes with a content fingerprint of the entry file and every file
it reaches through relative static imports, for the registry, the plugin
tool inspection cache, and the plugin command service. Add a bootstrap test
that a session started before a plugin is added or changed keeps its
original tools even when its setup runs afterwards, and a registry test for
a change outside the entry file.
* fix(core): include side-effect imports in plugin change fingerprints
The fingerprint only followed `from`, `import()`, and `require()`
specifiers, so a fix to a file the entry imports only for side effects
(`import "./setup.js"`) left the fingerprint unchanged and new sessions kept
getting the failed entry.
Scan statement-level side-effect imports for the fingerprint only. They are
kept out of the dependency preflight, where a loose match on text inside a
string (`'run import "x" first'`) would reject a valid plugin.
* fix(core): retry failed plugin imports on a backoff
Change detection follows static and side-effect relative imports, but a
broken import can also be fixed where no fingerprint sees it: a dynamically
imported file, a file behind a block comment, or a dependency installed in
node_modules. Such plugins stayed failed until an explicit reload.
Retry a plugin whose import failed when a session starts, at most every 30
seconds, even if no change was detected. A broken plugin costs at most one
extra import attempt per 30 seconds, bounded by the import timeout.
Replace the SHA-1 fingerprint with a non-cryptographic checksum; it only has
to notice edits to plugin source.
* feat(desktop): show plugin failures in the chat
Plugin failures reached the desktop webview only as core logs written to the
devtools console. Show them as status lines in the chat:
- session start returns `pluginWarnings` for plugins the session asked for
but could not load, and the webview adds one status line per warning
- plugin notices that arrive later on the session stream (setup and hooks
run on the first turn) carry `metadata.pluginIssue`; the webview adds
those as status lines too, while other core logs stay out of the
transcript
* fix(desktop): keep plugin warnings when saved history reloads
Finishing a turn replaces the live transcript with saved history, which
never contains plugin warnings (they come from the start reply and stream
notices), so the explanation of a missing plugin disappeared after the first
turn. Carry the session's live plugin-warning lines into canonical history
at their original position by time.
* refactor(core): simplify the in-process plugin registry (#14999)
* refactor(core): simplify the plugin registry
Drop the pieces added in review rounds that cost more than they buy:
- Global timer tracking. It monkeypatched setTimeout/setInterval/
setImmediate and their clear* counterparts on globalThis for the whole
host process (the hub, the CLI, and the shared VS Code extension host),
and attributed timers by async scope, so a host callback invoked from
inside a plugin call had its timers cancelled when the session released
its plugin copy. Plugins stop what they start in ctx.onDispose, which
stays.
- Plugin generations and per-generation health. Blocking and consecutive
failures are counted per plugin again; a re-import (reload or source
change) resets them. Running sessions keep their copies callable unless
the plugin is turned off, so a broken reload fails closed for them.
- Automatic retry of failed imports on a 30 s backoff, and the side-effect
import scan in the change fingerprint. plugins.reload covers changes the
fingerprint cannot see.
- The duplicated registerAutomationEventType validation; the commit
try/catch already records a host-rejected registration as a setup
failure.
* refactor(core): do not apply the session plugin policy in sandbox mode
The sandbox is an opt-in escape hatch and the per-session policy is new;
filtering sandbox results by file-derived and exported names added two
passes nobody needs yet. The policy is documented as in-process only.
* revert(desktop): drop the live plugin-warning merge into saved history
Reverts
|
||
|
|
79341eb295 | fix(desktop): retain catalog counts on installed connectors (#15042) | ||
|
|
d2cbeea6ff | fix(composio): discover connector tools through meta search (#15041) | ||
|
|
cbe3a4d4f0 | fix(desktop): drain copy feedback timer in chat test (#15040) | ||
|
|
55d32c22ab |
fix(desktop): allow cancelling cloud account sign-in (#14943)
* fix(desktop): allow cancelling cloud account sign-in * fix(desktop): keep cancel label stable during sign-in cancellation * fix(desktop): swap account creation for cancel during sign-in * fix(desktop): keep sign-in controls visible during account refresh * fix(desktop): keep sign-in retry responsive during account refresh * fix(desktop): ignore stale account reloads after sign-in retry * fix(desktop): limit sign-in changes to cancellation and stop polling * fix(desktop): keep sign-in cancellation in existing screen handlers * refactor(desktop): share sign-in cancellation mechanics * refactor(desktop): remove redundant sign-in error callback * fix(desktop): preserve sign-in cancellation across screens * test(desktop): simplify sign-in cancellation coverage |
||
|
|
ff255c08a9 |
feat(vscode): show dedicated ai& provider settings (#14611)
* feat(vscode): show dedicated ai& provider settings Selecting ai& in the extension showed the generic OpenAI-compatible form (base URL, model ID, custom headers, Azure options). Register aiand as a known provider so it gets the standard API key + model picker form, backed by the SDK builtin (fixed base URL https://api.aiand.com/v1, catalog models, default zai-org/glm-5.3). * chore: drop unused changeset file |
||
|
|
a48408909b |
fix(desktop): keep Cloud setup cards visible (#14954)
* fix(desktop): compact signed-out cloud welcome spacing * fix(desktop): keep cloud sign-in card near window bottom * fix(desktop): tighten signed-out cloud onboarding spacing * fix(desktop): use existing setup card for welcome spacing |
||
|
|
62f690d6ca |
fix: load and watch symlinked rule files (#14912)
* fix: load symlinked rule files from config directories
* fix(core): automatically reload symlinked instruction targets
* fix(core): drop symlink target watching, keep link-path loading
Review feedback on #14912: reading rules through the link path already
fixes the reported bug, and each new session re-reads the rules. Watching
wherever links point is a larger change than the bug needs and carried
loose ends (directory links in the target path, a readlink per file on
every refresh).
- revert the target-directory watching, chain walk and broken-link
retention from
|
||
|
|
8eba11b270 |
fix(schedules): stuck pending runs, silent model failures, stale editor models (#14998)
* fix(schedules): claim queued runs under bun:sqlite claimDueRuns bound unprefixed named parameters, which bun:sqlite binds as NULL, so the desktop hub never claimed a queued run and every scheduled run stayed pending with no error. Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * fix(schedules): fail runs whose agent turn ends with an error Provider failures such as a retired model id resolve the turn with finishReason 'error' instead of throwing, so these runs were recorded as successful with no error message. Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * fix(desktop): load live models in the schedule editor The editor only used the bundled provider catalog, so it kept offering retired models (e.g. space-bunny) that the live list no longer has. Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * fix(schedules): skip superseded queued cron occurrences Once queued runs are claimable again, the backlog that piled up while claiming was broken would replay every missed slot back to back. Cancel queued cron occurrences that a newer queued occurrence of the same schedule supersedes so only the latest runs. Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * fix(schedules): keep usage and tool calls in error-finish run reports Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * test(schedules): cover claimDueRuns under bun:sqlite Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> --------- Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> |
||
|
|
bf71bf7cd9 |
Default to the first Cline recommended model (Sonnet 5.5 fallback) across CLI, extension, and desktop (#14959)
* Default to the first Cline recommended model (Sonnet 5.5 fallback) across CLI, extension, and desktop - @cline/shared: CLINE_DEFAULT_MODEL_ID is now the anthropic/claude-sonnet-5.5 fallback - @cline/llms: the cline provider's defaultModelId prefers GENERATED_CLINE_RECOMMENDED_MODELS.recommended[0] - CLI: resolve the provider's SDK default before falling back to the first catalog entry; drop the hardcoded sonnet-4.6 fallback - VS Code: openRouterDefaultModelId -> anthropic/claude-sonnet-5.5; cline provider falls through to the SDK default Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * Default the SDK openrouter provider to anthropic/claude-sonnet-5.5 The VS Code extension's OpenRouter model field is populated from this SDK default via resolveModelInfo, so the extension-side openRouterDefaultModelId constant alone did not change the fresh-install selection. Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * Desktop: adopt the provider catalog default model once the catalog loads A fresh install booted on CLINE_DEFAULT_MODEL_ID and kept it when the user skipped onboarding, so the chat bar never picked up the Cline provider's recommended-list default. Swap the bootstrap fallback for the catalog default unless a model was already remembered for that provider. Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * Scope the recommended-model default to the Cline providers Only cline/cline-pass declare a curated default; other manifests may expose a placeholder like "default" (ollama, lmstudio), so the CLI keeps falling back to the first catalog entry for them. The desktop bootstrap swap now also applies only to new Cline chats, never to hydrated sessions. Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * Test both branches of the cline default model selection Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * Simplify: drop the desktop bootstrap swap and connector catalog lookup The desktop app keeps CLINE_DEFAULT_MODEL_ID as its pre-onboarding default (onboarding already stores the provider's recommended default), and the connector only swaps its hardcoded literal for the shared constant. Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * CLI: only the cline provider uses the SDK default before the catalog cline-pass's manifest default is just the first bundled model, not a curated pick, so it keeps the live catalog's own ordering. Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * Connectors: prefer the provider's declared default over the Cline fallback Non-Cline connector sessions with no saved model were handed a Claude id. Use the provider manifest default when it is a real model, skipping the "default" placeholder that catalog-less local providers expose. Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> --------- Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> |
||
|
|
d20b337eb5 |
feat(desktop): add transcript outline with shared shadcn message scroller (#14948)
* feat(desktop): add transcript outline with shared message scroller * fix(desktop): avoid repeated outline work during streaming * fix(ui): preserve transcript position when replacing rows * fix(ui): respect reduced motion in MessageScrollerButton The shared scroll-to-end button always passed shadcn's default smooth behavior. Resolve it from prefers-reduced-motion like the outline does, keeping an explicit behavior prop as an override. * test(desktop): cover saved-session row swap and streaming growth Add a regression test for continuing a saved session: history hydrates after the provider mounts, a new prompt pins near the top, then the activity row is swapped for the first answer row in one commit and the viewport must stay on the new prompt. Make the streaming test grow the transcript and deliver the resize notification instead of only changing answer text. * chore(ui): tidy message-scroller check in smoke-package --------- Co-authored-by: Saoud Rizwan <7799382+saoudrizwan@users.noreply.github.com> |
||
|
|
8d35dbbc5f | fix(desktop): explain missing Git during skill install (#14663) (#14670) | ||
|
|
e6ad24c43a | fix(cli): apply --thinking in ACP mode (#14894) | ||
|
|
2f4e36e86f | fix(vscode): preserve prose spacing when deleting slash commands (#14883) | ||
|
|
93e5e455e6 |
chore: remove the dead subscribeToRelinquishControl stream (#14974)
Its only sender, sendRelinquishControlEvent, was removed as unused in
|
||
|
|
75111f347f |
fix(cli): accept agent_error hook events in the hook command (#14945)
The `hook` command's dispatcher had no case for `agent_error`, which the
shared hook schema accepts and the CLI runtime emits when a run fails. A
valid `agent_error` payload fell through to the default branch, so the
command exited 1 without a JSON response. It now returns `{}` like the other
agent events. Adds the first unit tests for the command.
Fixes #14808
|
||
|
|
fa840c741c |
fix(desktop): sync session titles changed on the web (#14935)
* fix(desktop): sync session titles changed on the web * fix(desktop): preserve unopened session renames during discovery * fix(desktop): keep title refreshes ahead of React commits * fix(desktop): limit refreshed title reconciliation to cloud sessions * fix(desktop): keep every renamed title ahead of refresh completion * refactor(desktop): reuse session history lookup for chat header |
||
|
|
95e54e4a02 |
fix(cli): treat a provider API key from the environment as configured (#14926)
The TUI's startup check now accepts a provider API key from the environment (e.g. OPENROUTER_API_KEY) when the provider declares exactly one environment variable, as the runtime does when no key is saved. The key is checked through isProviderSettingsUsable, so the provider's other requirements still apply. Providers with several environment variables (Bedrock, Vertex, ...) are unchanged, and nothing is persisted. Related to #14923 |
||
|
|
3453880297 |
fix(vscode): keep error details in production logs (#14693)
* fix(vscode): keep error details in production logs
Logger dropped every extra argument unless IS_DEV was true, and production
bundles build IS_DEV as false, so lines like 'Cline OAuth login failed:' lost
the error. Production now appends error messages (with cause chain), numbers
and booleans; strings and objects stay dropped because call sites pass OAuth
URLs, terminal and file contents and settings. Verbose mode now serializes
Errors as stacks instead of {} and survives circular arguments. The
'Opening browser' line logs only origin and path.
* fix(vscode): reduce URLs in production log output to their origin
Error messages printed in production can embed URLs with credentials in
the query, path or userinfo, such as the expanded MCP server URL in the
invalid-URL error or Bun's URL parse error echoing its input. Reduce
every URL in a production error message to its origin, log only the
origin when opening a browser, and echo the MCP server URL as entered
rather than with environment variables expanded.
* fix(vscode): redact whole URLs in log text and keep the matcher linear
Parentheses and brackets are valid URL characters, so ending a match at
them left the rest of a credential-bearing URL in the log. Match up to
whitespace, quotes or angle brackets instead, trim only trailing
sentence punctuation and unbalanced closing brackets, and bound the
scheme length so scanning stays linear on adversarial input.
* fix(vscode): move the URL redaction helper into shared
Logger lives in src/shared, which the webview build compiles too, and
there `@/` resolves to webview-ui/src, so importing `@/utils/redact-url`
broke the webview typecheck.
* refactor(vscode): drop free-text URL scrubbing from the Logger
Scrubbing URLs out of arbitrary error messages is a blocklist that can
never be complete. Give error messages the same trust as the log message
itself instead, and keep the deterministic fixes: the MCP invalid-URL
error no longer embeds expanded environment variables, and the browser
URL is logged as its origin at the one call site that logs it.
* fix(vscode): omit JSON parse error messages from production logs
V8 and Bun quote the parsed input in JSON.parse errors, and the parsed
input is often a settings file or an API response carrying credentials,
such as the remote-config provider API keys. Log only the error name.
* fix(vscode): keep the entered MCP URL out of the invalid-URL error
A URL typed with userinfo or query credentials failed validation and
was echoed in the error, which is logged in production. Omit the URL
and keep the guidance; the user just typed it and can see it in the
form. Also drop the changeset: the repo no longer uses them.
* feat(vscode): fingerprint redacted URLs in the browser-open log line
Append three hex digits of a SHA-256 over the full URL to the redacted
origin, so a log shows whether two lines with the same origin were the
same URL without revealing it.
|
||
|
|
417526f19c | chore(desktop): release v0.0.45 | ||
|
|
0322bc5d51 | chore(cli): note removed schedule and history options in v3.0.70 changelog | ||
|
|
9c4de34543 | chore(cli): release v3.0.70 | ||
|
|
d630fa8f24 |
fix(cli): reject schedule and history options that do nothing (#14931)
* fix(cli): reject schedule and history options that do nothing
Several options were accepted and saved, but nothing ever read them, so
scripts that used them succeeded and silently did nothing:
- `cline schedule create|update --autonomous`, `--no-autonomous`,
`--idle-timeout` and `--poll-interval` wrote `metadata.autonomous`.
Its only reader was the scheduler package, removed in
|
||
|
|
3debb849a7 |
fix(desktop): let the composer model name use the available row width (#14936)
Drop the fixed max width on the composer's model picker so long model names show in full when the settings row has room, truncating only when it runs out. Keep the settings row on one line instead of wrapping, reserve room for the model and thinking controls so a long branch name can't squeeze the model name out, and give the conversation layout a shrinkable grid column so the composer row truncates instead of being clipped at narrow widths. Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> |
||
|
|
49276bcf99 |
fix(desktop): cut SSH logins from the git branch label poll (#14934)
get_git_branch only needs the current branch, but it ran listGitBranches, which also executes git for-each-ref. Over an SSH environment each command is its own ssh login, so the 5s branch label poll opened two fresh SSH sessions every 5 seconds against the remote host for as long as it was connected. Run only git branch --show-current for the label, and poll it every 30s for SSH environments (5s stays for local). Branch switches made through the picker still refresh immediately, as do focus and visibility changes. Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> |
||
|
|
faf05ef067 |
fix(desktop): stop UPX-packing the Linux SSH remote helpers (#14928)
* fix(desktop): stop UPX-packing the Linux SSH remote helpers Since the Bun 1.4.2 upgrade (#14631) the compiled helper lazily reads its embedded module payload back from its own executable at runtime. On a UPX-packed binary those reads return NUL padding, so the helper starts but every --remote-hub-ensure fails with "SyntaxError: Invalid character: '\0'" and SSH remotes cannot start (desktop 0.0.38 through 0.0.44). Ship the helpers uncompressed again and drop the upx installs from the publish workflow. Bundles grow by roughly 175 MB until the CLI-managed Hub replaces the helper binary. Fixes #14815 Fixes #14781 Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> * ci(desktop): smoke-test the bundled SSH remote helper before publishing Run each Linux job's native remote helper through --remote-hub-ensure and --remote-hub-stop against an isolated CLINE_DIR and discovery record. The UPX regression started the helper fine but failed on exactly this path, and nothing in the publish workflow exercised it. Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> --------- Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> |
||
|
|
ab4c1136a8 |
fix(vscode): stop labelling every HTTP 401-428 as an auth failure (#14919)
* fix(vscode): stop labelling every HTTP 401-428 as an auth failure ClineError.getErrorType treated any status in 401-428 as ClineErrorType.Auth, so a 404 from an OpenAI-compatible server with a stale model id, or from Gemini for a retired model, was shown as an authentication problem: for the cline provider the webview replaced the real message with the logged-out card or "(Click Retry below)". Only 401/403/407 are Auth now. 402 maps to Balance, 404/405/410 to a new NotFound class, and other 4xx fall through to the generic row, which shows the real status and message. The axios ERR_BAD_REQUEST code (set on every 4xx) only stands in for an auth failure when no status is available. ErrorRow adds model-id/base-URL guidance to a status-based NotFound, and the host's text-matched model-not-found rewrite shares the same guidance text so a message is never told twice. * fix(vscode): keep 407 off the auth row and pin message-based detection A 407 is the proxy rejecting credentials, not the provider, so the sign-in card would point at the wrong account; it now stays on the generic row, matching the SDK classifier's 401/403. Also pin that a status outside the dedicated sets still reaches the wording checks: Gemini answers an invalid key with a 400 and only the message says so. |
||
|
|
5b67631981 |
fix: child-stdin EPIPE and the SAP SDK's winston handler no longer kill the host process (#13762)
* fix: stop child-stdin EPIPE and the SAP SDK's winston handler from killing the host process
Two stacked bugs made cline-core exit with code 1 about 3s after a hook
(or MCP server) exited before draining its stdin:
- HookProcess and the SDK stdio MCP client wrote to a child's stdin with
no "error" listener. When the child dies while part of the write is
still queued (input larger than the pipe buffer), Node fails it
asynchronously with EPIPE and, unhandled, raises it as an uncaught
exception on the host process. Both writers now absorb the error and
let the existing exit handling report how the child ended.
- @sap-cloud-sdk/util (a dependency of the SAP AI Core provider) builds a
winston logger with exceptionHandlers at module load, installing a
process-wide uncaughtException listener that calls process.exit(1)
three seconds later -- overriding cline-core's own "log but survive"
handler. @jerome-benoit/sap-ai-provider bundles a second private copy
of that module, so disableExceptionLogger() cannot reach it; the
community vendor module now strips winston's process catchers by name
after the import and again after building the provider.
Regression tests cover both halves: a hook and an MCP server that exit
mid-write must fail the single operation without an uncaught exception,
and importing the community module must leave no winston catcher on the
process.
* fix(hooks): explain an undelivered input in hook failure messages
Review follow-up: the stdin "error" listener only logged. It still must
not settle the run -- a hook may legitimately ignore its input and exit
0, and the shell wrapper keeps the pipe open while the script lives, so
"close" stays the single source of truth -- but the failure is now
recorded and appended to the timeout / non-zero-exit errors so a hook
that never read its input is diagnosable from the error alone. Adds a
test that a hook ignoring a large input and exiting 0 still succeeds.
* test: type the uncaughtException probes so apps/vscode check-types passes
bun-types merges extra process listener overloads into `process`, which
made `process.off("uncaughtException", ...)` fail overload resolution
under the apps/vscode tsconfig (and with it the e2e package step). Type
the probe listeners and remove them through the plain EventEmitter type.
* fix(mcp): report the server's exit, not the broken pipe, when it dies mid-write
Review follow-up: the stdin "error" listener failed every pending request
with the EPIPE message, and it fires before "exit", so the exit handler
(which carries the exit code and stderr) never got to report. It now only
records the failure; the exit and request-timeout errors append a note
that the server stopped reading its input. The test server crashes with
exit code 3 and the test asserts the exit is what gets reported.
Also drops the changeset: changesets are no longer used in this repo.
* fix(mcp): kill a server whose stdin write failed instead of waiting out the timeout
A stdin write only fails once nothing holds the pipe's read end, so the
connection is dead either way. Killing the child lets the "exit" handler
fail pending requests immediately. A server that already exited keeps
its real exit status (the kill is a no-op); one that closed stdin but
stayed alive no longer stalls the request for the full timeout.
* fix: strip only the SAP SDK's own process catchers; give a dying MCP server its graceful window
Review follow-ups:
- community.ts removed every winston `uncaughtException`/`unhandledRejection`
listener by name, which would also take out an embedding host's own
winston exception handlers. The SAP provider is now imported lazily
(literal specifier, so bundlers still include it) inside the same
snapshot-and-diff wrapper the opencode provider already uses, so only
the listeners that import and construction added are removed. The
hygiene test installs a host listener with winston's name and asserts
it survives.
- The MCP client killed the server as soon as a stdin write failed, so a
server that closed stdin and was about to exit with its own code was
reported as SIGTERM instead. The kill now waits the existing graceful
shutdown window (250ms) and is skipped if the server exits first; a
test covers a server that exits 7 shortly after closing stdin.
* test(mcp): keep the stays-alive fixture alive and assert the client killed it
Number("") is 0, so with FAKE_MCP_EXIT_AFTER_CLOSE_MS unset the fixture
exited with code 7 at once and the stays-alive test passed without
exercising the kill. Use Number(undefined) (NaN) for the unset case and
require signal=SIGTERM so a fixture that exits on its own fails the test.
* fix(mcp): bound request failure and shutdown when a server outlives a failed stdin write
Sending a single SIGTERM and waiting for "exit" left a server that handles
SIGTERM alive, with the pending request stalled until its normal timeout.
If the server is still the current child when the graceful window ends,
the pending requests now fail with the stdin-failure message and the child
goes through disconnect()'s SIGTERM -> SIGKILL escalation. A server that
exits within the window is still reported by its own exit code.
Tests cover a stdin-closing server that honors and one that ignores
SIGTERM: the request fails within seconds and the process is gone.
* fix(llms): remove only the exit handlers the SAP import registers
The previous wrapper diffed process listeners across the async import and
construction, so it also removed host listeners registered in that
window (e.g. the CLI's abort-time unhandledRejection swap), and it had no
finally, so a rejected first construction left winston's handlers armed.
The SAP provider now loads through a small helper that attributes
"uncaughtException" registrations to the import by async context
(AsyncLocalStorage + a temporary "newListener" listener) and removes
exactly those in a finally. Construction runs after cleanup.
unhandledRejection is no longer touched: SAP never registers one.
On Bun, async context does not reach module evaluation, so nothing is
attributed; the Bun-run CLI and hub already treat uncaught exceptions as
fatal. The opencode signal-handler helper is back to exactly main's.
Tests run in fresh processes (one per file) and prove the SAP import
armed a handler: host listeners registered after loading starts survive
and SAP's are removed, on both a successful and a rejected first
construction.
|
||
|
|
0adccbdb70 |
docs, fix(cli): match the CLI reference and --help to what the CLI does (#14895)
* docs: match the CLI reference to CLI 3.0.68 The CLI reference and the pages that repeat it had drifted from the CLI. They named a `dev` command that no longer exists, swapped the --config and --data-dir defaults, described `connect` as an IDE adapter, said --thinking defaults to medium, and showed a JSON output shape (say/ask messages) that the CLI never prints. The documented `jq -r .text` example prints only nulls. Replace the pasted help with the 3.0.68 output and document what it lists: --compaction, --worktree, --update, --kanban, `skill`, `dashboard`, the `auth` options, `config <target>`, `connect --stop` and `--restart`, `mcp add`/`remove`, the `history` subcommands and options, and the `hub` subcommands including `drain` and `upgrade`. Rewrite the JSON section around the agent_event and run_result lines, with a jq filter that prints the final answer. Note that -k also saves the key, drop the `-i` image example (-i opens the TUI), and use the Cline provider's model id in the API auth example. Co-authored-by: Harshil Mistry <125483347+harshil-mistry@users.noreply.github.com> Co-authored-by: MarMar Labs <marmar9615@icloud.com> * docs: correct CLI defaults and JSON notes from review --retries defaults to 3, not the 6 that `cline --help` prints; note the discrepancy under the pasted help. Without --thinking, Cline uses the reasoning level saved from the TUI before the provider's default. Drop --page, which the CLI accepts but ignores. Say that a --timeout stops the run without a run_aborted line, and that scripts should skip line types they don't use. Use Claude Sonnet 5.5 in the auth examples, and say "in your terminal" where the pages described commands that need one. * fix(cli): make --help match what the CLI does `cline --help` said --retries defaults to 6, but runs use 3. The help now reads the same CLI_DEFAULT_MAX_CONSECUTIVE_MISTAKES constant that main.ts passes to the session, and a test ties the two together. --thinking now says that, without the flag, the CLI uses the level saved in the TUI before the provider default. -k says the key is also saved as the provider's key. `history --page` is hidden from help: the CLI never reads it, but it stays accepted so existing scripts keep working. The CLI reference shows the corrected help and no longer notes the wrong --retries default. The CLI README's -k and --thinking rows match. * fix(cli): name /model in the --thinking help Readers don't know what "the TUI" is. The level --thinking falls back to is the one chosen in the model picker, which users open with /model, so the help, the CLI reference, the overview and the README now say that. * fix(cli): warn that cline history --page is ignored cline history lists the newest sessions up to --limit and has never read --page. The option stays accepted so existing scripts keep working, but it now prints a deprecation notice to stderr. The terminal tests that expected --page in help, or ran it as if it selected a page, are removed. * fix(cli): say hub upgrade does not wait for --zen tasks cline hub upgrade waits only until no client is attached. A --zen run detaches once the hub accepts it, and scheduled runs never attach, so the upgrade can stop both mid-run. The help text and the hub command lists in the docs now say so. * docs: drop dashboard from the root help listing cline --help no longer lists dashboard; it is cline hub dashboard. * fix(cli): require a count for --retries; fix connect --restart example --retries was declared with an optional value, so a bare --retries set it to true and the CLI crashed calling .trim() on it. The option now requires a count, and a bare --retries fails with commander's "argument missing" error. cline connect passes options after the channel to the channel's connector, so "cline connect telegram --restart" never reached connect. The examples now put --stop and --restart before the channel, and the reference says why. * docs: scope the JSON line format to agent runs The JSON section read as the format of every --json, but only agent runs print typed lines. cline history --json prints one array, and each cline config target prints its own shape. The heading and both pages now say the line format is for tasks, and name the others. --------- Co-authored-by: Dominic Cooney <55120+dominiccooney@users.noreply.github.com> Co-authored-by: Harshil Mistry <125483347+harshil-mistry@users.noreply.github.com> Co-authored-by: MarMar Labs <marmar9615@icloud.com> |
||
|
|
a7fa147e91 |
fix(cli): keep --header values when cline mcp add opens the wizard (#14901)
* fix(cli): keep --header values when cline mcp add opens the wizard Without --yes, cline mcp add opens the add wizard with the name, transport and URL filled in, but dropped every --header value. A user who accepted the prefilled answers saved a remote server without its Authorization header. The wizard now selects "Static headers" and fills in the header field. If the user leaves that field unchanged, the headers are saved exactly as given on the command line, including values that contain commas, which the comma-separated field cannot represent. * fix(cli): parse wizard headers the way --yes does The add wizard read every header from one comma-separated field and split it with its own rules: it split on commas, dropped malformed headers without a word, and accepted names and empty values that cline mcp add --yes rejects. Its earlier fix kept unedited prefilled headers by comparing text, so one edit sent them all back through the comma split. The wizard now asks for one header per prompt, prefilled from --header, and checks each with parseMcpHeaders, the parser --yes uses. A malformed header is rejected at the prompt with the --yes error message, and placeholder warnings appear in both paths. The test restores CLINE_MCP_SETTINGS_PATH with vi.unstubAllEnvs, so an unset variable is removed instead of being set to "undefined". * fix(cli): warn about placeholder headers before their wizard prompt The add wizard warned about a placeholder header such as "Bearer <token>" only after every header had been entered, too late to fix it there. It now warns just before the prompt that shows a prefilled placeholder, and again only if the user types a new one. Clearing a prefilled header now drops that header alone. Before, an empty answer ended the list, so clearing the first of two prefilled headers also dropped the second. --------- Co-authored-by: Dominic Cooney <55120+dominiccooney@users.noreply.github.com> |
||
|
|
c747d494a2 |
chore(llms): align the AI SDK on one release line (ai 7.0.120, provider-utils 5.0.50) (#14862)
`ai` had stayed at 7.0.79 while single `@ai-sdk/*` packages were bumped on their own. Each such bump brought its own `@ai-sdk/provider` / `provider-utils`, whose types no longer unify with the ones `ai` pins, so the hand-off to `ai` needed casts. Bumping `@ai-sdk/openai` alone for #14649 would have added two more. Move `ai` and every `@ai-sdk/*` package to the releases built on `@ai-sdk/provider-utils` 5.0.50 (all published 2026-09-28): ai 7.0.120, gateway 4.0.98, anthropic 4.0.67, google 4.0.84, google-vertex 5.0.97, mistral 4.0.53, openai 4.0.79, openai-compatible 3.0.58, otel 1.0.120, react 4.0.123, provider 4.0.19. Bedrock 5.0.98 is already on this line and stays. One copy of each is left in the lockfile; the only other `ai` is Langfuse's own nested copy, as before. No casts are added. This also fixes #14649: `@ai-sdk/openai` 4.0.79 knows which GPT-6 models can turn reasoning off and drops the setting for the rest, so commit message generation (which always turns reasoning off) and tasks with reasoning set to "none" stop getting a 400 from GPT-6 Astra and 6.1 Sol. GPT-5.x and GPT-6 Sol/Luna still get "none". It fixes #13203 the same way: `@ai-sdk/anthropic` 4.0.67 leaves `thinking` out for Claude models that can't turn thinking off (Fable 5, Opus 5.5) instead of sending `thinking: {type: "disabled"}`, which they reject. Other Claude models still get `disabled`. |
||
|
|
55a133b751 |
feat(cli): move dashboard under hub (#14900)
* refactor(cli): scope hub options to their subcommands * feat(cli): move dashboard under hub and document its usage --------- Co-authored-by: Cline <cline@users.noreply.github.com> |
||
|
|
e49de78175 | fix(cli): show help for bare hub command (#14897) | ||
|
|
afaf4f2457 | chore(vscode): release v4.1.23 | ||
|
|
66ff3731cf | chore(desktop): release v0.0.44 | ||
|
|
c995be480a |
fix(cli): make cline doctor log honour CLINE_LOG_PATH (#14893)
The CLI logger wrote to CLINE_LOG_PATH when it was set, but cline doctor built the default path itself, so `cline doctor log` opened the wrong file and `doctor --verbose`/`--json` read recently spawned processes from it. Move the path into resolveCliLogPath() in logging/log-path.ts and call it from the logger and from both doctor readers. The module is separate from the logger so cline doctor doesn't load pino. The config page, the CLI reference, the proxy troubleshooting page and the CLI README now say that `cline doctor log` opens the CLINE_LOG_PATH file. Co-authored-by: Dominic Cooney <55120+dominiccooney@users.noreply.github.com> |
||
|
|
ef9430ffb4 | chore(cli): release v3.0.69 | ||
|
|
5dea21ab89 |
Remove deprecated Focus Chain plumbing from the VS Code extension (#14861)
* Hide retired Focus Chain messages when loading legacy tasks * Remove deprecated Focus Chain plumbing from the extension * docs: remove retired Focus Chain telemetry events * Remove unused AgentConfigLoader from the VS Code extension (#14881) * refactor(vscode): remove unused legacy agent config loader * test(vscode): verify initialized state persists to disk * test(vscode): avoid contextual inference in storage assertion --------- Co-authored-by: Cline <noreply@cline.bot> --------- Co-authored-by: Cline <noreply@cline.bot> Co-authored-by: cline-cloud[bot] <276134852+cline-cloud[bot]@users.noreply.github.com> |
||
|
|
6354d209c8 |
docs: correct shared paths, log files, commands and tool names (#14884)
* docs: correct shared paths, log files, commands and tool names Several pages repeat the same facts about where Cline keeps its files, which commands exist and what the built-in tools are called, and many of them no longer match the shipped CLI and SDK: - Workflows live in ~/.cline/workflows/, not ~/.cline/data/workflows/. The session index is ~/.cline/data/db/sessions.db, each session has a folder of JSON files, and hub locks and logs are under ~/.cline/data/. - cline start and cline dev log do not exist; the log command is cline doctor log, and the CLI log is ~/.cline/data/logs/cline.log. - The built-in tools are run_commands, search_codebase, fetch_web_content and skills, not bash, search, fetch_web and use_skill. - CLINE_HUB_ADDRESS is read only by cline schedule; the hub port is CLINE_HUB_PORT. - No CLI 3 release reads CLINE_COMMAND_PERMISSIONS. The pages that offered it, including the PR review sample, now say the CLI has no command allow list and point to a PreToolUse hook. The unused permissionDeniedError string in the VS Code prompts goes with it. Part of #14853. Co-authored-by: Mikołaj Kondratek <19799111+mkondratek@users.noreply.github.com> Co-authored-by: Manpreet Kaur <26463231+Manpreet2298@users.noreply.github.com> Co-authored-by: Renee Huang <100229782+reneehuang1@users.noreply.github.com> * docs: qualify log, tool routing and command-approval advice - cline doctor log always opens the default log file, so say so where CLINE_LOG_PATH is described. - The editor and apply_patch choice is a default that SDK callers can replace with toolRoutingRules. - The PR review sample now warns that hooks and plugins in the checked-out pull request run with the job's environment, and says how to keep them from running before relying on a global PreToolUse hook. - The conditional-approval example no longer auto-approves git diff, which runs a configured external diff program, and notes that Git can run programs named in a repository's config. * docs: run the PR review sample with a read-only token The sample gave an auto-approved Cline run a token that can write pull requests. Split it into two jobs: `review` runs Cline with read-only permissions on a checkout of the base branch and writes review.md; `post` runs no repository or model code and posts the file with `gh pr review --comment`. Skip pull requests from forks and Dependabot, which get no secrets, and warn against `pull_request_target`. Fence the workflow with four backticks so the code block inside the prompt no longer ends it early. --------- Co-authored-by: Dominic Cooney <55120+dominiccooney@users.noreply.github.com> Co-authored-by: Mikołaj Kondratek <19799111+mkondratek@users.noreply.github.com> Co-authored-by: Manpreet Kaur <26463231+Manpreet2298@users.noreply.github.com> Co-authored-by: Renee Huang <100229782+reneehuang1@users.noreply.github.com> |
||
|
|
42c20b9681 |
test(cli): drop MCP description tests that pin hardcoded default timeouts (#14886)
Co-authored-by: Saoud Rizwan <saoudrizwan@users.noreply.github.com> |
||
|
|
f832e8169d |
fix(desktop): let keyless configured providers (local models) start sessions (#14879)
* fix(desktop): let keyless configured providers start sessions The webview's pre-flight credential gate demanded an API key for every provider that was not OAuth or local-auth, so a local OpenAI-compatible endpoint (LM Studio, vLLM, Ollama) migrated from VS Code or added via Settings failed every turn with "Missing API key" even though the sidecar already reported it as configured via base URL + model. Carry the catalog's host-computed `configured` readiness into the chat config and skip the API-key requirement when the host accepts the provider, matching the runtime's own keyless handling. * fix(desktop): gate sessions on the shared apiKeyOptional provider fact Address review: instead of a desktop-only providerConfigured readiness flag threaded through the chat config, make the credential requirement explicit in the shared provider contract. - @cline/shared: GatewayProviderMetadata.apiKeyOptional, mirrored into ProviderAuthInfo via resolveProviderApiKeyOptional (same pattern as localCliCommand -> localCli). - @cline/llms: declare it on openai-compatible, ollama, lmstudio, litellm, vertex, and bedrock. - @cline/core: listLocalProviders carries the fact in ProviderListItem.auth; user-added endpoints registered from providers.json / models.json declare it too (their key is already optional in the desktop form). - desktop: resolveCredentialError consults auth.apiKeyOptional and no longer needs the extra config field. |
||
|
|
e6a3b1cf0a |
docs: state telemetry defaults and scope accurately (#14860)
* docs: state telemetry defaults and scope accurately The Enterprise and monitoring pages called Cline telemetry opt-in and anonymous, and said code never leaves the machine. Telemetry is on by default in the VS Code and JetBrains extensions, Cline Desktop and the CLI. It identifies signed-in accounts and organizations, and includes prompts for requests to the Cline and ClinePass providers. Rewrite the telemetry page around what is collected and how to turn it off in each product. Scope the remote-configuration restrictions to the products that enforce them, add a per-product support table, and tell admins to ignore the folders Cline writes into workspaces. Align the VS Code setting description and host-telemetry warning with the docs. Part of #14853 * docs: drop bold from remote-config support table rows The bold marked dashboard switch names, but nothing on the page said so, so the rows looked inconsistent. * docs: address review of the telemetry and remote-config pages State only what the telemetry setting enforces in the extensions: the lock, and that members can't turn telemetry on when the organization turns it off. Scope the support-table introduction to the controls marked Yes, since no product enforces YOLO or Kanban. Use recursive .gitignore patterns and say why: the cached settings can include prompt storage access keys, and a member may open a subfolder of a repository. Narrow the indexing card to content: Cline lists file paths to search them but doesn't index or embed file contents. * docs: say products support remote-config controls, not enforce them Organization rules and workflows reach sessions as instructions that a member can edit, so "enforces" overstated what the CLI does with them. The section heading already says "support". --------- Co-authored-by: Dominic Cooney <55120+dominiccooney@users.noreply.github.com> |
||
|
|
b2c7148cd9 |
fix(desktop): render Mermaid diagrams inline (#13721)
* feat(desktop): render Mermaid diagrams in chat Render model-authored Mermaid fences as interactive SVGs in Desktop without depending on model image-input support. - extract the strict lazy Mermaid DiagramPlugin into @cline/ui - keep shared defaults diagram-free and add explicit opt-in controls - enable copy, download, fullscreen, and pan/zoom in Desktop - preserve initial bundle size through dynamic Mermaid imports - cover lazy loading, strict security, failures, and streaming fences Refs #13568 * test(desktop): harden Mermaid rendering coverage * test(desktop): stub scrollTo for streamdown 2.6 in Markdown interaction tests streamdown 2.6 (pulled in by main) scrolls streaming code blocks with element.scrollTo, which jsdom does not implement. Stub it the same way chat-messages.test.tsx and channels-view.test.tsx already do. * fix(ui): stop Mermaid diagram links from bypassing host link policy Mermaid's `securityLevel: "strict"` blocks script execution and dangerous URL schemes, but still renders a `click <node> "https://…"` directive as a live `<a xlink:href>` anchor inside the SVG. Streamdown injects that SVG with `dangerouslySetInnerHTML`, so those anchors never pass through the `a` component a product supplies — bypassing the deceptive-link confirmation and the external-open routing that ordinary Markdown links go through, with no rel="noreferrer", and letting a click navigate the desktop webview away from the app itself. A diagram label is authored independently of its destination, so these links are deceptive by construction: the desktop app's own isDeceptiveLink rule would flag every one of them. - neutralize rendered diagram links in @cline/ui so they cannot navigate on their own, preserving an http(s) destination on data-cline-diagram-href - reattach them in Desktop to the existing confirmation modal, which shows the real destination before anything opens - recover the anchor from pointerdown: Streamdown's pan/zoom surface takes pointer capture, so a real click is retargeted away from the anchor; a press that moves more than a few pixels is treated as a pan, not a link click - drop non-http(s) destinations rather than surfacing them, so a renderer change cannot widen what the app will open - assert the packed Mermaid control shape instead of a "not false" check that also accepted undefined or an empty object Verified against real Mermaid 11.16.1 in a browser: script, event-handler, iframe, foreignObject and javascript:/data:/vbscript:/file: payloads are all neutralized by strict mode, and `%%{init}%%` / YAML frontmatter cannot downgrade securityLevel. The http(s) `click` anchor was the one live escape. Stacked on #13721, which adds the shared lazy Mermaid plugin this hardens. Refs #13568 Co-authored-by: yiaany <ilyaantonievich@gmail.com> Co-authored-by: yiheng-kkk <lij921093@gmail.com> * feat(ui): theme Mermaid diagrams with the Cline design system Replace Streamdown's built-in Mermaid block in Desktop with an owned `@cline/ui` block (`createMermaidRenderer` from `@cline/ui/components/mermaid-block`): - Mermaid's `base` theme with variables resolved from the live design tokens (`--card`, `--foreground`, `--primary`, ...), following light/dark and the accent palette and re-rendering when either changes; a diagram's own `%%{init}%%`, frontmatter `config:`, `classDef` and `style` still win - a filename header from the fence title (```mermaid title="my-diagram"), frontmatter `title:`, or a name derived from the diagram - zoom, fullscreen, copy, and PNG / `.mmd` downloads; PNGs are opaque, 2-3x, capped at 4096px and kept under the image attachment limit - renders are serialized through one queue, since Mermaid is a process-wide singleton that is not safe to render concurrently The owned block injects the SVG itself, so diagram link neutralization moves into the shared render service and covers both this block and the Streamdown diagram plugin. Desktop keeps routing diagram link clicks through the existing confirmation modal. Refs #13568 * fix(ui): avoid polynomial backtracking in Mermaid helpers * fix(ui): make diagram label extraction linear-time Replaces the backtracking label-regexes CodeQL flagged (ReDoS, PR #14757) with single-pass scanners and line-column parsing. * refactor(ui): share the Mermaid render service and drop dead naming helper createLazyMermaidPlugin now delegates import/retry/queueing/link-neutralization to createMermaidService instead of duplicating that path, keeping only theme-keyed config. Removes deriveMermaidDiagramName, which had no consumer outside its own tests. --------- Co-authored-by: harrisonofcline <harrison@cline.bot> Co-authored-by: yiheng-kkk <lij921093@gmail.com> |
||
|
|
6017c502c3 |
fix(vscode): apply the user's rules when generating commit messages (#14103)
* refactor(core): select and order session rules in one place The rules section of a session's system prompt was selected in several places: `listEnabledRulesFromWatcher` (enabled only, sorted by name) for the single-workspace plugin, and an inline filter without the sort in the combined user-instruction service. Callers outside a session that need the same section had nowhere to reach it and would have grown a third copy. Add `listEnabledRulesFromRecords` / `loadRulesForSystemPromptFromRecords` next to the watcher variants, make the watcher variants delegate to them, and use the records variant in the combined service. Export the loader from `@cline/core`. Behavior change: the combined service now orders rules by name like the single-workspace path does, instead of in listing order. * fix(vscode): apply the user's rules when generating commit messages "Generate Commit Message with Cline" built its prompt from a hardcoded system prompt and never loaded `.clinerules`, so commit conventions users had written down (language, format, ticket references) were honored in chat and silently dropped by the button. `Controller.getRulesForSystemPrompt` takes the enabled rules from the user-instruction watcher the controller already runs for the workspace, through core's shared `loadRulesForSystemPromptFromRecords`, and the commit-message system prompt appends them behind a short preamble telling the model which rules are relevant to a commit message. The button sees the rule set a chat session in the workspace sees, including a rule that has `disabled: true` frontmatter being left out of both. If the rules can't be read, the base prompt is used. Known limitation: the Rules panel's on/off toggles live in extension state the SDK doesn't read, so a rule switched off there is still sent to chat and to the button alike (CLINE-3120). The new rules load is one more await before the request; the existing cancel check before `createMessage` covers it, and a test pins that. Fixes #9410 * fix(vscode): let Stop end a commit generation still waiting for rules The first generation in a workspace waits for the user-instruction watcher's initial scan of rules, skills and workflows. Stop was honored after that await (no request went out), but the generation and its SCM progress indicator stayed pending until the scan finished, which can take a while on a slow filesystem. Race the rules load against the generation's abort signal so Stop ends the generation at once. The scan carries on in the background and warms the watcher chat uses; nothing waits on it any more. * fix(core): render hub client rules through the shared selection The hub's client user-instruction proxy filtered and formatted rules inline, in listing order, while the combined service now goes through the shared `loadRulesForSystemPromptFromRecords`, which sorts by name. runtime-builder wraps the client proxy in the combined service when host plugin skills are present, even though the plugin service contributes no rules, so adding a host plugin reordered the same client rules in the session prompt. Render the hub snapshot's rules through the shared helper too. Every path that builds a session's rules section now selects and orders rules the same way; hub client sessions now get their rules sorted by name. A boundary test renders reversed names plus a disabled rule through the proxy alone and through the combined service, and expects the same output from both. |
||
|
|
c00bf86595 |
fix(cli): expose yolo mode (#14724)
* fix(cli): expose yolo mode Show `-y/--yolo` in CLI help with a clear sandbox warning so unsupervised benchmark and CI runs can opt in deliberately. * revert: drop unrelated desktop sidecar hub-reconnect change |
||
|
|
b78d91b79b |
fix(desktop): reconnect chat sessions after Cline Hub loss (#14725)
* fix(desktop): reconnect chat sessions after Cline Hub loss Retry session rebuild for up to a minute when the hub transport closes or the session is missing, then end the turn as interrupted so the user can resend. Surface reconnect status in the webview instead of treating it as an error. * fix(desktop): scope hub-loss recovery to lost sessions - Probe the hub before rebuilding so a session it still holds is left alone - Cancel the reconnect loop on stop/abort/reset and undo a racing rebuild - Recover queued sends too, re-queueing once the session is back - Show the resend notice as an error-role bubble that history sync keeps - Recognize missing sessions wrapped as generic hub command failures * fix(desktop): share hub recovery and preserve session ownership * fix(desktop): isolate replacement recovery and avoid duplicate queued sends * fix(desktop): serialize recovery across session replacements * fix(desktop): bound the entire shared recovery lifecycle |
||
|
|
afabc824d8 |
fix(cli): preserve config --json when delegating to the runtime command (#14833)
The lazy `config` wrapper declares its own `--json` option, so Commander consumes the flag before the remaining arguments are forwarded to the real config command. `cline config --json` therefore reached the runtime command without the flag and launched the interactive view, which fails without a TTY, while `cline --json config` worked because the inner command also reads the root option. `cline config --json mcp` silently printed text for the same reason. Copy the wrapper's parsed value onto the runtime command before parsing the forwarded arguments, and add a non-TTY e2e check that both flag placements produce the same JSON inventory. Co-authored-by: Dante <duanjl.china@gmail.com> |
||
|
|
2f93c1d6f7 |
docs: fix two broken README links (vscode contributing, sdk telegram) (#14826)
* docs: fix two broken README links (vscode contributing, sdk telegram) * docs: fix two broken README links (vscode contributing, sdk telegram) |