Truncation was measured once on mount and watched through a ResizeObserver
on the clamped element, whose own height stops changing under line-clamp.
A message measured before its content settled never regained the expand
affordance, and a just-sent one measured before its turn finished laying
out could not be expanded at all.
Measure at click time so expanding depends on whether the text is clipped
right now, re-read once on the next frame after mount, and observe the
children (which keep their natural height) plus subtree swaps.
Preserve layout with invisible placeholders while worker highlighting loads
Reuse cached highlighted lines on first render when available
Differentiate loading from failed highlighting results for better fallback behavior
The additional context and pull request template blocks ran into the file
list without a blank line, and the template's markdown headings blended into
the surrounding instructions. Each block now starts on its own, and template
content is fenced with explicit markers labelled as structure to reuse rather
than instructions to follow.
Claude-Session: https://claude.ai/code/session_01NzK8hD1hFHHHwv2FgZJwC2
The server echo of an optimistic user message carries different part
ids, so the reducer dropped the optimistic part and appended the server
one at the end, and MessageBody keyed user parts by part id. The key
change remounted the text subtree (blank frame, markdown re-parse,
truncation state reset) and the append reordered text against file
parts.
Replace the optimistic part in place and key user parts positionally.
Commit generation now samples the last 10 commit subjects and instructs the
model to match their language, prefix convention, and length, falling back to
Conventional Commits only when the history shows no consistent style.
PR generation probes the conventional pull request template locations and
reuses the repository's own sections and checklists as the body structure when
one is found.
Claude-Session: https://claude.ai/code/session_01NzK8hD1hFHHHwv2FgZJwC2
Prevent managed Chat drafts and sessions from inheriting an active project's repository context in the Work Status panel while retaining directory-independent status sections.
Parakeet is an offline model trained on whole utterances, so re-decoding
the growing buffer to animate a live transcript cost O(n^2) work for a
result the final decode replaced. Sessions now decode once per committed
segment, and the composer shows a scrolling waveform of the mic level
instead of running text.
Long dictations split at a pause once past 60s (hard cap 90s) instead of
on a blind 15s timer, so cuts no longer land mid-word. Committed segments
decode while the user is still speaking: a 185s dictation returns 4.1s
after stop instead of 11.0s, with identical text (816 vs 817 words).
Also fixes two ways the stream manager could silently drop transcribed
audio. It now counts the commits it issued instead of trusting the
session's echoed events, so a commit still in flight when the client
finishes can no longer be left out of the final text. And segment
byte/peak accounting is reset where the commit is issued rather than when
the event arrives, which could mistake the tail of a dictation for
silence and clear it.
Remove retired Command Code, Discord, and Telegram integration entries, search targets, and documentation. Keep Command Code provider usage and logo support available through normalized provider ID aliases.
Show every change on the current branch relative to its base in the
Changed/Staged/Last turn dropdown. The base comes from the branch's
reflog record or an explicit per-branch user choice (persisted), never
a main/master guess; when git has no record the user picks a base once
from a searchable branch list.
- server: GET /api/git/branch-base (reflog-derived base),
GET /api/git/range-files (name-status -z with rename/copy
destination paths and -C copy detection)
- shared UI: optional getBranchBase/getGitRangeFiles runtime APIs
with boundary parsing; persisted per-branch overrides keyed by
runtime+directory+branch
- DiffView: branch scope with confirmed-unavailability coercion of
persisted tabs (detached HEAD, default-branch checkout, metadata
settled without a default), range-invalidated diff cache guarded
against stale completions, bounded branch-metadata retry, read-only
diff actions in branch scope; hidden in VS Code
- helper module branchDiffScope.ts with tests for coercion,
availability, race conditions, and retry exhaustion
* feat(ui): show externally-created sessions in sidebar and Recent view (#1441)
Sessions created by external OpenCode processes (CLI, other server
instances) share the same database but don't broadcast SSE events to
OpenChamber's connected server. The existing 45s global polling via
experimental.session.list() already discovers these sessions, but the
isKnownActiveSessionDirectory filter in SessionSidebar.tsx removes
them when their directory isn't a registered project.
Add effectiveKnownDirectories that extends knownSessionDirectories
with directories derived from globalActiveSessions themselves, so
external sessions pass the filter and appear in the sidebar and Recent
view.
Validated with two live OpenCode server processes sharing the same
database: global experimental.session.list() returns external sessions
immediately, while per-directory APIs do not.
* Revert "feat(ui): show externally-created sessions in sidebar and Recent view (#1441)"
This reverts commit 94acda43ad3049e7674d8eb3f24b1f74acb0d1c3.
* fix(ui): make sidebar reactive to global session store updates (#1441)
Replace non-reactive useGlobalSessionsStore.getState() with direct
reactive subscriptions for activeSessions and archivedSessions. The
previous getState() pattern relied on proxy subscriptions
(activeSessionStructure, hasAuthoritativeGlobalSessions) to trigger
re-renders, which created a fragility gap where store updates could
go unnoticed by the sidebar.
Add a 45s periodic refreshGlobalSessions() interval in the sidebar,
independent of the tray sync hook. The tray sync's polling is gated
behind isTrayPlatform() and isTrayEnabled(), so on runtimes where
the tray is unavailable, there was no periodic refresh of global
sessions at all. External sessions (created by CLI or other server
processes) were only discovered on initial mount or page refresh.
* test: add regression test for stat directory scoping (#3019)
* fix: scope file-reference stat probes to the session directory (#3019)
The /api/fs/stat probe sent by the markdown renderer carried no
directory hint, so the server resolved the workspace from
settings.lastDirectory. When the browsed directory differs from the
session directory the stat returns 400 and the renderer treats it as
file-does-not-exist, silently disabling file-reference links.
Send effectiveDirectory as x-opencode-directory on the probe and
qualify the stat cache key by directory so a rejection under one
directory cannot leak into another. The probe logic moves from
MarkdownRendererImpl into fileReferenceStat with unit coverage.
Opens the chat tab when a new inline comment is submitted
Automatically focuses the chat composer for quicker follow-up
Leaves draft updates unchanged when editing an existing comment
Render managed Chats through the shared folder-aware session group and keep folder ownership at the Chats root, including new drafts and older per-directory scopes.
Hide worktree actions for Chats, make worktree shortcuts inert on Chat drafts, and let new-session shortcuts inherit an active session directory while explicit Chats controls still create managed Chat drafts.
Track Chats and Recent section sentinels so the desktop sticky overlay changes identity only when the corresponding section reaches the top of the sidebar.
Create projectless chat sessions under a managed, date-scoped Chats directory and clean abandoned or deleted session folders.
Add Chats to sidebar state, startup cache, shared context, and Electron Mini Chat while keeping VS Code project-only. Resolve managed chat directories to one server-side memory owner and document the runtime contracts.
Adds a mandatory early load step for the communication-style skill.
Removes the blanket always-on trigger from the skills table.
Clarifies that the guidance applies to all task output.
Adds a new communication-style skill for rewriting text in a more human voice
Replaces the old unslop skill with the new name and guidance
Updates agent instructions to apply the communication-style skill to every task
* feat(skills): remove ClawHub catalog integration
Drop the ClawHub registry as a skills catalog source across web server,
shared UI, VS Code, docs, and locales. The catalog now serves git-based
sources only: the curated Anthropic repo and user-defined repositories.
Also removes the now-unused adm-zip dependency.
* feat(skills): redesign catalog around curated GitHub repositories
Replace the single-source dropdown with a card grid of curated GitHub
repositories (Anthropic, OpenAI, Cursor pstack/skills, Matt Pocock) plus
user-defined sources. Source cards show skill counts, GitHub stars, and
last-updated time; a global search covers all loaded sources.
Server: curated sources gain GitHub repo metadata (stars, pushed_at)
fetched best-effort with a 3-hour in-memory and on-disk cache; scans
run through a concurrency-limited, deduplicated cache with 3-hour TTL
persisted across restarts. Refresh still bypasses the cache.
Shared UI: source cards, global search with clear button, per-skill
GitHub links, install/installed states. VS Code curated list updated
to match. All new copy translated across 12 locales.
* fix(skills): address catalog review findings
- GitHub metadata fetch timeout drops to 1.5s (under the catalog
client's 3s deadline) and failed lookups cache briefly (5 min) so
repeated catalog loads do not re-hit a failing API.
- Disk cache files are written with owner-only permissions (0o600);
rename preserves the mode.
- loadSource deduplicates concurrent in-flight requests per source and
the shared isLoadingSource flag now clears only when the last active
source load finishes.
Defines a process for rewriting text to sound more human
Lists patterns to remove, including AI-style phrasing and overused punctuation
Adds practical guidance for clearer, more direct prose
Plugin providers are registered from a plugin's `config` hook and credentialed
from its `auth` loader, both inside the running OpenCode process. Nothing about
them reaches `opencode.json` or `auth.json`, so resolution that only reads files
could not see them: selecting such a model failed with "has no known API base
URL" while the same model worked in chat (#2666).
`GET /provider` is where that state is visible. A new `runtime-providers`
module keeps one cached snapshot of it and reports, per provider, the
credential and endpoint OpenCode itself resolved. Credential resolution becomes
config -> runtime -> auth.json, and endpoint resolution config -> openai default
-> runtime -> models.dev catalog.
Providers with a dedicated wire format (Copilot, ChatGPT-plan OpenAI, Anthropic,
Google) are excluded from the runtime credential: for them OpenCode reports an
OAuth access token that their real transport does not accept.
opencode zen is excluded when the user has no zen login. OpenCode then reports
the sentinel `apiKey: "public"` and trims its catalog to free models that run on
its own infrastructure; the sentinel is never read as a credential.
Claude Code stays refused for background actions even when a plugin publishes an
OpenAI-compatible endpoint for it, because that endpoint is a facade over the
Claude Agent SDK and spawns the CLI per request.
No capability probe. Asking `GET /models` does identify a plugin whose protocol
lives in its own `fetch`, but measured across the 166 providers with an `api`
URL in the models.dev catalog it also denies six that work and simply have no
`/models` route. A provider that vanishes from the picker explains nothing,
while one that fails on use says why, so availability stops at credential and
endpoint.
The same list drives the Small Model and Changes Walkthrough pickers.
Validated against a real OpenCode with four plugin providers loaded: offered
providers went from 3 to 7, zen and Claude Code stayed out, and a generation
through a plugin-backed model that previously failed now returns.
* fix: reconcile busy sessions after managed OpenCode restart
Forced health-check restarts previously rebound the event stream without
settling in-flight turns, so sessions stayed busy with no terminal state.
Interrupt those sessions, classify health failures, and retain bounded
process diagnostics for post-restart diagnosis.
Fixes#2943
Co-authored-by: serkraser <serkraser@gmail.com>
* fix: surface interrupted chats after OpenCode restart
Complete unfinished assistant turns as aborted once the session is
authoritatively idle, and show a persistent toast so users can continue
instead of remaining silently stranded.
Fixes#2943
Co-authored-by: serkraser <serkraser@gmail.com>
* fix: redact Basic auth credentials in restart diagnostics
The key/value sanitizer stopped at whitespace, so Authorization: Basic
credentials survived in stderr tails and health snapshots. Redact the
scheme token before that rule runs.
Co-authored-by: serkraser <serkraser@gmail.com>
Shows the auth panel only when provider credentials are actually required
Keeps custom providers defined in config from being treated as incomplete
Adds coverage for the new provider auth check
Adds new integrations docs for Claude Code, Command Code, and Cursor
Links the Providers pages to the new integrations guide
Updates the docs sidebar with localized integrations navigation
Share the desktop session-card currency formatter (lib/money.ts) and surface
the current session's cost in the extension chat-header context usage tooltip.