Commit Graph
3312 Commits
Author SHA1 Message Date
Tom Rochette ecc70fa15d feat(debug): add fetch requests-in-flight tracker with age percentiles
Adds a 'Requests' tab to the debug panel (Ctrl/Cmd+Shift+D) that wraps
window.fetch while the panel is open to track every request as in-flight
from call to promise settle, sampled once per second over a 5-minute
rolling window.

Charts:
- in-flight request count over time (current + peak)
- p50/p90/p99/max age distribution of currently in-flight requests,
  with the legend below the chart and a y-axis max label for scale

Tracking is fully gated behind the panel: closing it stops the sampling
interval, unwraps window.fetch, and drops all state (zero overhead when
not debugging). i18n keys added to all 9 locales.
2026-06-24 05:24:48 +00:00
Bohdan Triapitsyn 604bb97258 refactor(files): use runtime fetch query options 2026-06-24 00:43:27 +03:00
Bohdan Triapitsyn 7f8e04d22f fix(session): prefer current directory for implicit drafts 2026-06-24 00:43:19 +03:00
Bohdan Triapitsyn 08b866136e fix(server): normalize encoded directory headers 2026-06-24 00:43:11 +03:00
Bohdan Triapitsyn c3cf914fda fix(runtime): avoid encoding latin1 directory headers 2026-06-24 00:43:03 +03:00
Bohdan Triapitsyn 37aec95f37 chore: bump opencode sdk 2026-06-24 00:42:56 +03:00
bashrusakhandLeonid Skorobogatyy e44efa97d6 feat(agents): expose thinking variant configuration in agent settings (#1715)
* feat(agents): expose thinking variant configuration in agent settings

Fix #1425: add variant field to agent config UI so users can configure
thinking/reasoning depth per agent without editing opencode.json.

Changes:
- Added variant to AgentConfig and AgentDraft types in useAgentsStore
- Pass variant in createAgent and updateAgent API calls
- Support null for temperature, top_p, and variant to clear overrides
- Added variant input field in AgentsPage 'Model & Parameters' section
- Added variant to settings search registry
- Added i18n strings for variant field in all 8 non-English locales

The variant field maps to provider-specific parameters (e.g. Anthropic
high/max variant, OpenAI reasoning effort). Users can enter any string
value; the SDK passes it through to the model provider.

Clearing temperature/topP/variant now sends null to the server instead
of omitting the field, which properly removes the override in
opencode.json.

* fix(sync): preserve tool state.time in materialization merge

* chore: trigger re-review

* fix(agents): use thinking variant selector in settings

* fix(agents): preserve thinking variant values

---------

Co-authored-by: Leonid Skorobogatyy <bash@opencode.itc.local>
2026-06-23 23:22:59 +03:00
Bohdan Triapitsyn 3d3674d4dd fix: restore arrow-up message history navigation
Lets ArrowUp recall previous messages when the cursor is at the start
Keeps autocomplete guards for history navigation
Restores prior chat input behavior
2026-06-23 23:21:09 +03:00
Bohdan Triapitsyn d47a892376 fix: sync before pushing git commits
Makes Commit & Sync fetch and pull before push when needed
Prevents stale git status from showing already up to date
Adds regression coverage for git status cache invalidation
2026-06-23 23:16:06 +03:00
Bohdan Triapitsyn efdfbf3ce2 fix: improve PR review UX guidance
Adds behavioral contract checks for user-facing changes
Discourages raw schema-driven UI defaults in reviews
Applies guidance to automated review workflow prompts
2026-06-23 23:16:06 +03:00
bashrusakhandLeonid Skorobogatyy 3db91721cb fix(providers): use correct endpoint for provider disconnect (#1714)
Fix #1462: handleDisconnectProvider called the SDK auth.remove() which
only clears auth credentials from auth.json. Cloud providers configured
in user/project/custom config files were not removed and reappeared
after reload. Now calls DELETE /api/provider/:id/auth?scope=all which
removes the provider from all config sources.

Co-authored-by: Leonid Skorobogatyy <bash@opencode.itc.local>
2026-06-23 22:38:49 +03:00
bashrusakhandLeonid Skorobogatyy 6e68015389 fix(agents): use isPrimaryMode consistently across all agent pickers (#1713)
* fix(agents): use isPrimaryMode filter for agent picker

Fix #1527: agent picker filtered by mode !== 'subagent' which missed
agents with unexpected mode values. Now uses isPrimaryMode() which
only includes 'primary', 'all', undefined, and null — the semantically
correct set of agents that should appear in the picker.

* fix(agents): use isPrimaryMode consistently across all agent pickers

Updated AgentSelector.tsx to use isPrimaryMode instead of mode !== 'subagent'.
Removed duplicate isPrimaryMode definition from useConfigStore.ts and
imported the shared helper from mobileControlsUtils.

---------

Co-authored-by: Leonid Skorobogatyy <bash@opencode.itc.local>
2026-06-23 22:34:51 +03:00
bashrusakhandLeonid Skorobogatyy ac0f173655 fix(chat): preserve tool duration across session switches (#1712)
* fix(chat): preserve tool duration across session switches

Fix #1636: ToolPart.tsx reset pinnedTime to empty on unmount/remount,
causing LiveDuration to not render on first paint. Now initializes
pinnedTime from server-provided time?.start/time?.end in the useState
initializer, eliminating the one-frame gap.

* fix(sync): preserve tool state.time in materialization merge

---------

Co-authored-by: Leonid Skorobogatyy <bash@opencode.itc.local>
2026-06-23 22:30:04 +03:00
bashrusakhandLeonid Skorobogatyy 57cef1b278 fix(sidebar): correct expansion-key format for virtualizer buffer (#1711)
* fix(sidebar): increase virtualizer buffer for expanded parents

Fix #1530: archive sub-session layout broken because the virtualizer
used a fixed 28px height estimate per row. Expanded parents with inline
children are much taller. Now dynamically increases bufferSize when
expanded parents are present.

* fix(sidebar): correct expansion-key format for virtualizer buffer

The expansion key was using raw sessionId instead of the scoped format
'project:{archived|active}:{sessionId}'. This made hasExpandedParent
always false, so bufferSize never increased. Also removed dead
hasSessionSearchQuery branch.

---------

Co-authored-by: Leonid Skorobogatyy <bash@opencode.itc.local>
2026-06-23 22:24:11 +03:00
bashrusakhandLeonid Skorobogatyy a25fc4c25a fix(sync): reflect share status from global store after cancel (#1709)
* fix(sync): reflect share status from global store after cancel

Fix #1551: unshareSession() called updateLiveSession() which silently
fails when the child store doesn't exist. The sidebar rendered from the
child store first, showing stale share data. Now overlays the global
session's share field at merge points.

* fix(sync): extract shared mergeLiveSessionWithGlobalSession helper

Extracted the share-field overlay into a single shared helper in
useGlobalSessionsStore.ts. All 3 merge sites now use the helper
instead of duplicating the overlay logic.

* test(sync): add unit tests for mergeLiveSessionWithGlobalSession helper

---------

Co-authored-by: Leonid Skorobogatyy <bash@opencode.itc.local>
2026-06-23 22:18:44 +03:00
5f3ef320d2 fix(session): bind new sessions to selected project (#1708)
* fix(session): bind new sessions to selected project

Fix #1521: openNewSessionDraft() always used currentDirectory even when
the user selected a different project. Now prefers the selected project's
path when no explicit directory is provided.

* test(session): add unit test for openNewSessionDraft project binding

---------

Co-authored-by: Leonid Skorobogatyy <bash@opencode.itc.local>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-06-23 22:14:33 +03:00
bashrusakhandLeonid Skorobogatyy 83256ba924 fix(sidebar): preserve pinned sessions and folder refs on empty session list (#1706)
Added sessions.length === 0 guard to useSidebarPersistence.ts and
sessions.length === 0 && archivedSessions.length === 0 guard to
useSessionFolderCleanup.ts. Prevents data loss when server returns
empty list during transient failures.

Co-authored-by: Leonid Skorobogatyy <bash@opencode.itc.local>
2026-06-23 22:01:24 +03:00
Bohdan Triapitsyn 2fd86db6a7 fix(auth): trim opencode server username 2026-06-23 21:52:51 +03:00
bashrusakhandLeonid Skorobogatyy 4feddfa810 fix(auth): honor OPENCODE_SERVER_USERNAME env var for basic auth (#1705)
Fix #1685: the Basic auth header for the OpenCode server was hardcoded
to use the username 'opencode', ignoring OPENCODE_SERVER_USERNAME. Users
who set a custom username got 401 errors because the server expected a
different credential.

Both call sites (web server auth-state-runtime.js and VS Code
extension opencode.ts) now read process.env.OPENCODE_SERVER_USERNAME
with a fallback to 'opencode' to preserve prior behavior.

Co-authored-by: Leonid Skorobogatyy <bash@opencode.itc.local>
2026-06-23 21:50:14 +03:00
Szasz AttilaandBohdan Triapitsyn eae09d4576 fix(settings): persist per-model visibility and sibling selector state (#1700)
* fix(settings): persist per-model visibility and sibling selector state

The server-side settings sanitizer only allowlisted favoriteModels and
recentModels, so hiddenModels, collapsedModelProviders, recentAgents, and
recentEfforts were stripped on every write to settings.json — per-model
visibility and collapsed-provider state silently reset on every container
redeploy or settings reload.

Add the four missing fields to sanitizeSettingsUpdate:
- hiddenModels: sanitizeModelRefs(..., 1024) — same shape as favoriteModels;
  1024 covers dense multi-provider setups while bounding persistence/memory.
- collapsedModelProviders: normalizeStringArray with Array.isArray gate
  (matches usageDropdownProviders).
- recentAgents: normalizeStringArray (Array<string> per ui-store).
- recentEfforts: new sanitizeRecentEfforts validating Record<string, string[]>
  (shape confirmed in ui-store + addRecentEffort action); trims/dedupes keys
  and variants, caps at 128 keys x 5 variants/key (5 matches client slice).

No ui-store version bump or migration: zustand's default merge spreads
persisted state over defaults, so missing fields fall back to [] / {} until
the next toggle. favoriteModels and recentModels are untouched.

Tests: 8 new cases in settings-helpers.test.js using the real
sanitizeModelRefs / normalizeStringArray — round-trips, empty-[] parity with
favoriteModels, garbage rejection, and a full-payload regression test.

* fix: sync model selector settings

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-06-23 21:46:23 +03:00
307808bec2 fix(mobile): use exact directory matching for session grouping (#1687)
* fix(mobile): use exact directory matching for session grouping

The new mobile sessions sheet used startsWith prefix matching to
assign sessions to projects, which caused child-directory sessions
(e.g. /root/repos/opencode) to be grouped into parent projects
(e.g. /root/repos). Switch to exact directory matching (project root
or registered worktree paths only) to match the desktop sidebar
behavior.

Also exclude sub-agent sessions (those with parentID) from the
totalSessions badge count so the displayed number reflects only
top-level sessions.

* fix: align mobile session project matching

---------

Co-authored-by: lilyzhaun <lilyzhaun@users.noreply.github.com>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-06-23 21:27:54 +03:00
Gokul GK 12835c7646 fix: refresh skills catalog after settings updates (#1681) 2026-06-23 21:10:22 +03:00
Leonid Skorobogatyy 20f2a2635b chore(worktree): drop dead otherBranches labels after search guard
The mobile and desktop (cmdk) pickers in NewWorktreeDialog now hide
non-matching branches during search via a !hasExistingBranchQuery /
!hasSourceBranchQuery outer guard. That makes the inner heading
ternaries (which switched between 'localBranches' and
'otherLocalBranches' depending on the search state) unreachable: they
always resolve to the non-query label, and the
'hasExistingBranchQuery && <CommandSeparator />' lines were dead code.

This commit:

- Replaces 8 heading ternaries with static non-query labels
  (mobile and desktop, existing/source, local/remote).
- Drops the two unreachable <CommandSeparator /> renders in the
  otherLocal blocks.
- Simplifies the otherRemote separator conditions by removing the
  always-false '|| hasExistingBranchQuery' / '|| hasSourceBranchQuery'
  terms.
- Removes the now-unused 'session.newWorktree.otherLocalBranches' and
  'session.newWorktree.otherRemoteBranches' keys from all 9 locales.

Behavior is unchanged; this is dead-branch cleanup only.
2026-06-24 03:51:56 +11:00
FanFan4204andBohdan Triapitsyn efd621b087 fix: handle non-ISO-8859-1 characters in fetch headers and Content-Disposition (#1673)
* fix: handle non-ISO-8859-1 characters in fetch headers and Content-Disposition

Browser Headers API rejects characters above U+00FF. The x-opencode-directory header carries raw filesystem paths, which breaks when paths contain Chinese/CJK characters. Also fixes Content-Disposition for non-ASCII filenames per RFC 5987.

* refactor: export header sanitization helpers, deduplicate, add tests

Export isLatin1Safe and sanitizeHeadersForBrowser from runtime-fetch.ts so VS Code webview can import them instead of duplicating the logic. Add tests: isLatin1Safe boundary checks, sanitizeHeadersForBrowser encoding/deduplication, runtimeFetch round-trip encode/decode, and Content-Disposition RFC 5987 output for both ASCII and non-ASCII filenames.

* fix: mark encoded directory headers

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-06-23 19:49:44 +03:00
Leonid Skorobogatyy 1ad470cead fix(worktree): hide non-matching branches during search 2026-06-24 03:26:26 +11:00
Nicolas Charpentier 43f677d56d ci: skip stale workflow on forks (#1663) 2026-06-23 14:32:31 +03:00
Nicolas CharpentierandBohdan Triapitsyn b87de3c5b2 fix: ignore pasted @ for file mentions (#1649)
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-06-23 14:07:09 +03:00
renovate[bot] 18744bf723 chore(deps): update development dependencies (#1643) 2026-06-23 13:36:23 +03:00
weixiang1862andBohdan Triapitsyn 3f4ad2a3e8 fix: preserve settings default thinking variant when switching agents (#1639)
* fix: preserve settings default thinking variant when switching agents

When a user sets a default thinking variant (e.g. 'high') in settings and
switches between plan and build agents in a session, the variant was reset
to 'default' (undefined) instead of respecting the settings default.

Root cause: two code paths failed to fall back to settingsDefaultVariant:

1. ModelControls variant sync effect: when no per-session+agent+model
   variant was saved, the effect set currentVariant to undefined instead
   of falling back to settingsDefaultVariant.

2. setAgent in useConfigStore: when the target agent had a configured
   model, the variant was always passed as undefined to
   applyResolvedModelSelection, ignoring both the saved per-session
   variant and the settings default.

Fix both paths to resolve variants in priority order:
saved variant > settingsDefaultVariant > undefined.

* fix: preserve agent variant fallback order

* fix: apply historical session variant on restore

---------

Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-06-23 13:35:36 +03:00
Ibrahim KhanandIbrahim Khan b863a4a83a test(git): assert relative URLs in gitApiHttp stage/unstage tests (#1615)
The runtime URL refactor in #1228 switched gitApiHttp's buildUrl from
absolute window-origin URLs to the relative URLs returned by the default
runtime URL resolver, but gitApiHttp.test.ts kept asserting the old
absolute URLs. The two index-mutation tests have failed ever since
(no CI step runs the test suite, so it went unnoticed). Update the
expectations to the relative URLs the helper now produces.

Co-authored-by: Ibrahim Khan <ibrakhxn@amazon.com>
2026-06-23 12:10:50 +03:00
f1c9776fde fix: invoke skills selected from the slash command menu (#1607)
Selecting a user-installed skill from the slash menu inserted "/name" as a
plain text message instead of running the skill (#1605). routeMessage only
dispatched a "/name" via session.command when the name was found in the synced
command list (hydrated once at bootstrap) or the commands store (which filters
skills out), so skills installed after startup fell through to a plain prompt.

Consult the live skills store when classifying a slash token. OpenCode registers
every skill as a command (source: "skill"), so a known skill is dispatched via
session.command and its content is injected, matching the existing behavior of
skills that happened to be in the bootstrap snapshot.

Signed-off-by: Bohdan Triapitsyn <artmore@protonmail.com>
Co-authored-by: Ibrahim Khan <ibrakhxn@amazon.com>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-06-23 11:51:05 +03:00
renovate[bot] ec69dcc28b fix(deps): update dependency katex to ^0.17.0 (#1603) 2026-06-23 11:34:26 +03:00
renovate[bot] 36579be4ee fix(deps): update dependency @simplewebauthn/server to v13.3.1 (#1600) 2026-06-23 11:33:45 +03:00
Sin991114 6c1e41c5f9 Fix font-size/padding not applying in VS Code (#1261) (#1595)
The VS Code webview was misdetected as a mobile device when the panel
was narrow on touch-capable machines, because device detection only
exempted the Electron shell. That added the `mobile-pointer` class,
letting mobile.css override the typography vars with `!important`, which
beats the inline styles from applyTypography/applyPadding — so font-size
and padding settings had no effect.

Treat the VS Code runtime like the desktop shell, as Electron already is.
2026-06-23 11:32:30 +03:00
Baruch Vitorino eab8862268 fix(quota): handle MiniMax M3/Token Plan API changes (#1589)
Extract shared MiniMax provider logic into minimax-shared.js factory
module used by both minimax-coding-plan and minimax-cn-coding-plan
as thin wrappers.

Endpoint fallback:
- Try /v1/token_plan/remains (M3/Token Plan) first
- Fall back to legacy /v1/api/openplatform/coding_plan/remains
- fetchEndpoint wrapped in try/catch so network/parse errors
  return null instead of throwing, ensuring fallback always runs

Model selection (pickChatModel):
- Prefer MiniMax-M* entries with non-zero total_count (Token Plan M3)
- Fall back to general/chat/text model names (legacy Coding Plan)
- Fall back to any entry with current_interval_remaining_percent
- Ultimate fallback to model_remains[0]

Usage calculation:
- token_plan endpoint: usage_count = remaining, so used = total - remaining
- coding_plan endpoint: usage_count = consumed (legacy behavior)
- Prefer current_interval_remaining_percent when count fields are zero
  (legacy Coding Plan accounts with percentage-based quotas)
- remains_time used as fallback for window duration (in milliseconds,
  confirmed via live API: 9664502ms = 2.68h in 5h window)

Window status:
- Respect current_weekly_status field: status 3 means the window is
  not applicable for the current plan tier (e.g. legacy plans without
  weekly limits). These windows are omitted from the result.
- Default to active when status field is absent (backward compatible).

Fixes #759 (percentage showing empty/null for legacy Coding Plan
accounts and incorrect percentages for M3/Token Plan accounts).
2026-06-23 11:31:17 +03:00
weixiang1862 56ca5bcf74 fix(mobile): subagent chevron overlaps session title on mobile (#1582)
`mobile.css` applies `min-width: 36px; min-height: 36px` to all `[role="button]` elements on mobile devices for touch targets, enlarging the subagent chevron from `14×14px to 36×36px`. This extends the chevron box 20px past the content edge, visually overlapping the session title. Add inline `minWidth/minHeight: 14` to pin the chevron size.
2026-06-23 11:30:02 +03:00
Mayuresh Kadu 474ec6c037 gitignore: exclude internal planning docs from upstream 2026-06-20 09:35:59 +01:00
Mayuresh Kadu 2cbbf3ab15 review fixes: align reproduction script timeout, tighten comments 2026-06-20 09:35:11 +01:00
Mayuresh Kadu df669a4ded changelog: document brew opencode detection fix 2026-06-20 09:35:11 +01:00
Mayuresh Kadu 390a7d0a66 scripts: update reproduction script with fix documentation 2026-06-20 09:35:11 +01:00
Mayuresh Kadu d781c302e2 server+vsce: fix brew path coverage (TOOLCHAIN_SEGMENTS, fallback order) 2026-06-20 09:35:11 +01:00
Mayuresh Kadu 3d436d88e8 server: add fast command -v path before login shell probing 2026-06-20 09:35:10 +01:00
Mayuresh Kadu 13caa698f3 server: add 5s timeout to all shell probes in env-runtime.js 2026-06-20 09:33:35 +01:00
Bohdan Triapitsyn 4d63278efd feat: add SSH commit signing to git identities
Configure commit signing per Git identity
Apply SSH signing settings automatically
Support signing in web and VS Code
2026-06-18 23:51:40 +03:00
Issue Reproducer 1439f5e838 reproduce(issue-1720): add reproduction script for brew opencode detection on macOS 2026-06-18 15:00:44 +00:00
Bohdan Triapitsyn 07e6935a3e docs: add vacation notice to README
Added vacation notice for Jun 18-28
2026-06-18 02:26:40 +03:00
Bohdan Triapitsyn 68cebd09a6 release v1.13.2 2026-06-18 02:20:56 +03:00
Bohdan Triapitsyn e4cfb628fe fix(diff): keep header controls and horizontal scroll within the panel when line wrap is off
In the changes/diff view, an unwrapped diff's intrinsic width leaked up the
flex chain: the flex-1 column holding the scroll area lacked min-width:0, so its
min-content (the widest line) stretched it — and every nested w-full element,
including the .pierre-diff-wrapper (overflow-x-auto) and the file header — grew
to the content width. That pushed the header's action controls past the narrow
viewport and left overflow-x-auto with nothing to scroll.

Add min-w-0 to the diff layout's flex items so the chain stays at viewport
width: long lines now scroll horizontally inside the diff, and the file header
controls stay visible.
2026-06-18 02:17:44 +03:00
Bohdan Triapitsyn 57c5808ef2 fix(files): refresh URL auth token proactively for asset previews
The oc_url_token has a ~50s effective lifetime and was only fetched once at
preview mount, so HTML/image/PDF previews cycled to 'authentication required'
when it expired and nothing forced a re-render with a fresh token.

Add a consumer-gated proactive refresh in runtime-auth: while at least one
url-token consumer is active, a single scheduler mints a fresh token just
before the skew window and swaps it in atomically (the previous token stays
valid until the new one lands — no empty-token window for other consumers).
acquire/release manage the consumer count; subscribe fires only on a real
token replacement.

FilesView consumes this via a shared useAssetAuthRefresh hook (replacing three
near-duplicate effects) and remounts the iframe/img only when the token
actually changes, not on a blind interval.
2026-06-18 01:24:37 +03:00
Ibrahim KhanandIbrahim Khan fbc108f6ba fix(sync): treat part snapshot as a delta coalescing barrier (#1693)
A `message.part.updated` snapshot did not invalidate the pending delta
coalescing key for its message/part. A delta arriving after an intervening
snapshot merged into a delta queued before it, and the snapshot then
overwrote that slot, dropping the later delta's text (e.g. `abc` rendered
as `ab`). Enqueueing a part snapshot now drops that part's pending delta
coalescing keys, while leaving already-queued delta events in place, so
post-snapshot deltas start a fresh entry.

Closes #1647.

Co-authored-by: Ibrahim Khan <ibrakhxn@amazon.com>
2026-06-18 01:09:24 +03:00