Commit Graph
244 Commits
Author SHA1 Message Date
Bohdan Triapitsyn eb6f7b0904 fix(terminal): update ghostty-web to a build that clears recycled rows
ghostty-web 0.4.0 hands rows that scroll into view out of recycled WASM
page memory without clearing them, so after a tab or project switch the
new emulator showed the previous terminal's text (upstream #138). The fix
landed only in prereleases, so pin 0.4.0-next.20 and carry the local
block-glyph rendering patch over to the new dist file.

Verified in a production build: creating an emulator after disposing a
full one no longer exposes its rows, and switching between two projects
with live output in each keeps every terminal's content to itself.
2026-09-06 22:57:43 +03:00
Bohdan Triapitsyn 7b42208b8c release v1.22.2 2026-09-05 21:39:04 +03:00
Bohdan Triapitsyn 0b39efb0ae chore: bump @opencode-ai/sdk to 1.18.29 2026-09-05 12:11:20 +03:00
Bohdan Triapitsyn 05e2903815 release v1.22.1 2026-09-04 23:51:03 +03:00
Bohdan Triapitsyn f42988c9bf chore: bump @opencode-ai/sdk to 1.18.28 2026-09-04 23:43:54 +03:00
Bohdan Triapitsyn bdda3c36bc release v1.22.0 2026-08-30 19:24:09 +03:00
Bohdan Triapitsyn 9963e6e3b7 release v1.21.1 2026-08-29 13:20:21 +03:00
Bohdan Triapitsyn 5871c36875 chore: bump @opencode-ai/sdk to 1.18.25 2026-08-28 16:01:07 +03:00
Bohdan Triapitsyn c3f3c5aeb7 Merge pull request #3040 from gaojunran/fix/cjk-markdown-links
fix(markdown): keep CJK/fullwidth punctuation out of bare-URL autolinks
2026-08-28 01:22:11 +03:00
Bohdan Triapitsyn 8598f3a37c release v1.21.0 2026-08-26 23:15:55 +03:00
Bohdan Triapitsyn cb18f8c9af chore: bump @opencode-ai/sdk to 1.18.23 2026-08-26 19:46:23 +03:00
Bohdan Triapitsyn ac880e8e62 Merge main (anchored-turn chat scrolling) into perf/switch-and-scroll
Main replaced the chat timeline scroll engine while this branch was in
flight, which obsoletes two of its subareas and reshapes a third:

- Chat timeline: main's LegendList-based MessageList/ChatContainer win;
  the activation-overscan staircase targeted the removed tanstack path
  (LegendList provides adaptive rendering natively) and is dropped along
  with its test.
- Scroll shadows: main's hook-based masks stay (the virtualized list owns
  its scroll element — there is no wrapper to hand the styling to); the
  viewport-wrapper ScrollShadow rewrite, its index.css replacement, its
  test, and the call-site viewportClassName adaptations are reverted to
  main. The chat OverlayScrollbar keeps this branch's disableHorizontal.
- OverlayScrollbar: the direct-DOM rewrite lands, but binding now follows
  the live container node instead of binding once per ref object — the
  chat scroller remounts on every session switch, and a bind-once
  contract left the scrollbar attached to a dead element.
- Markdown renderer: the detached-DOM cache and warm-block fast path
  merge with main's block-commit reveal (enter cascade), streaming code
  highlighting, and gutter reservation; the per-block reconcile keeps
  both the decoration-refresh path and the reveal cascade.
2026-08-26 00:59:45 +03:00
c_w_xiaohei 1c3c26f2bf perf(ui): batch Mermaid viewer initialization 2026-08-26 00:42:36 +08:00
Bohdan Triapitsyn 04f338cc49 feat(chat): upgrade @legendapp/list to 3.3.8 and let it own end following
3.3.x makes maintainScrollAtEnd follow content growth on its own — a
tail row growing in place included — which is exactly what the manual
totalSize correction existed for. Delete that correction (the totalSize
listener now only drives the anchored-turn glide) and pick up 3.3.x's
measurement batching, prepend-flash fixes, and web programmatic-scroll
fixes. Opt the explicit maintainScrollAtEnd config into footerLayout per
the 3.1.1 guidance.

The library's own released-on-user-scroll heuristic proved unreliable
one run in three against synthetic touch, so the gesture state machine
stays authoritative: while a real gesture owns the scroll, the list's
end pinning is switched off through a threaded endPinningReleased prop
and re-engages when the user returns to the end.

Validated with the CDP battery on a production build: stream follow
stays at distance 0, mobile drag releases with the pill shown in three
of three runs, resize oscillation stays at the reduced level, the rail
reaches the last turn, and profiled streaming cost per rendered
character matches the tuned 3.2.0 numbers.
2026-08-25 16:49:22 +03:00
Bohdan Triapitsyn d2d8669564 refactor(chat): replace timeline scroll engine with anchored-turn LegendList
Sending a message now parks that message near the top of the viewport
and streams the reply into reserved end space below it, instead of
jumping to the bottom and chasing it.

- swap @tanstack/react-virtual for @legendapp/list in the chat timeline; the
  streaming tail becomes a normal list row rather than a separately rendered
  block, so one component owns the scroll position
- add timelineScrollAnchoring: pure anchored-turn geometry plus the three
  scroll modes (following-end / anchoring-new-turn / free-scrolling)
- replace useChatAutoFollow with useChatTimelineScroll, which opts out of
  automatic movement on real gestures via a generation counter instead of the
  timer windows the old implementation needed to recognise its own writes
- move the load-older button, question/permission cards, recap, status row and
  bottom spacer into the list header/footer, since the list owns its container
- extract useScrollShadow so the shadows can attach to that container

maintainScrollAtEnd and maintainVisibleContentPosition replace the manual
prepend anchor-hold and the mobile quiet-window prepend deferral.

Validated: workspace type-check, lint, web build, ui tests per file.
Scroll behaviour itself is unverified and needs manual testing on web, desktop
and iOS.
2026-08-25 01:10:00 +03:00
Bohdan Triapitsyn fe80d246ea release v1.20.0 2026-08-23 02:10:48 +03:00
Bohdan Triapitsyn 90f150bd0c chore: bump @opencode-ai/sdk to 1.18.21 2026-08-22 12:13:54 +03:00
gaojunran 19c5cc1f1e fix(markdown): keep CJK punctuation out of bare-URL autolinks
marked's GFM url tokenizer swallows any non-space text after a bare URL,
including fullwidth punctuation and Chinese annotations written directly
after it ("https://x.com/docs(说明)了解更多"). Switch the autolink
tokenizer to marked-linkify-it, which treats Unicode punctuation as a URL
boundary, so fullwidth parens and CJK punctuation are trimmed naturally.
2026-08-21 13:10:42 +08:00
Bohdan Triapitsyn ef2afdc759 release v1.19.0 2026-08-19 01:18:56 +03:00
Bohdan Triapitsyn 584b9304fd fix(ui): use CodeMirror selection handles on iOS 2026-08-18 21:37:57 +03:00
Bohdan Triapitsyn 3f266232f9 release v1.18.4 2026-08-14 17:48:03 +03:00
Bohdan Triapitsyn b5c9da4ff0 release v1.18.3 2026-08-14 00:55:17 +03:00
Bohdan Triapitsyn 7c5fcb535e chore: bump @opencode-ai/sdk to 1.18.18 2026-08-14 00:26:07 +03:00
Bohdan Triapitsyn a5aa32446d feat(browser): replace the preview proxy with a real browser panel and an agent web tool (#2883)
The preview panel worked by proxying a dev server through OpenChamber's own
origin and rewriting the HTML that came back. Anything the rewriter did not
anticipate broke, and pages that refuse to be embedded never loaded at all.
This deletes the proxy (-1604 lines and its tests) and merges the preview and
browser panels into one surface backed by a real Chromium view.

What the panel is now

- A `<webview>` in its own session partition: logins and cookies persist, hot
  reload works because nothing is rewritten, DevTools are one click away.
- Annotation: pick one element, drag a region, or draw freehand, write a note,
  and it reaches chat with a screenshot of the visible page with the marks on it.
- Toolbar: hard reload, page zoom, device sizes, a light/dark switch that
  applies to the page rather than the app, and cookie/cache clearing scoped to
  the panel alone.
- Several pages at once, each tab showing the page's own favicon, and an address
  bar that suggests pages already visited in this project.
- Dev servers are listed from what is actually listening on the machine, checked
  against what a project announced, so a server is offered no matter how it was
  started. One that is still starting is waited for instead of failing.

Remote dev servers

The desktop app binds a local port and pipes raw bytes to the OpenChamber host
over the existing authenticated connection, so the page keeps its own origin at
the root of its own host. The reachable set is exactly what discovery reports
and is re-checked per connection, so an authenticated client cannot dial
arbitrary local services on the host. Links and redirects to another loopback
port stay on the machine that served the page. A tunnel that cannot be opened is
reported; it is never replaced by the plain loopback URL, which would answer
from the user's own machine under a remote address.

Agent control

Browser actions are a separate `openchamber_web` tool: open, snapshot, click,
type, scroll, inspect computed styles, resize between mobile/tablet/desktop, and
capture a screenshot into `.openchamber/screenshots/` in the project. The
existing `openchamber` tool keeps sessions, worktrees and scheduled tasks. Each
has its own setting in the new Settings -> General -> OpenChamber Tools section,
and the plugin is not injected at all when both are off.

Capability belongs to the connected client, not to configuration: a client
declares on its event stream that it can drive a page, which only a Chromium
host does. Exactly one client performs each request — it claims the request
before acting, and the first claim wins — because deciding by whose result
arrives first would be too late for a click that already happened. No client
listening is answered immediately with an explanation rather than a timeout.

Runtime boundaries

Web tabs get a plain iframe that can display a page but not inspect one. The
VS Code extension no longer offers the surface at all, since nothing that makes
the panel worth having works there. Mobile is unaffected.

Native boundary

Camera, microphone, location and device-picker requests from panel pages are
denied — Electron grants them by default when no handler is set, and the panel
loads whatever address the user types. Page capture, appearance emulation and
storage clearing verify that their target belongs to the panel's own session
instead of trusting a web-contents id from the renderer.

Persisted state

Stored `preview` tabs migrate to `browser` (v13 -> v14). Context panel tab
limits are now per surface, so filling one surface no longer evicts another's
tabs. Address history is stored per project and per runtime.

Documentation

`preview.mdx` and `desktop-browser.mdx` rewritten across all locales, the agent
tool settings path corrected, new `DOCUMENTATION.md` for the browser-control
broker and the dev tunnel, and the `ui-api-decoupling` skill updated where it
still described the deleted proxy.
2026-08-13 22:44:13 +03:00
Serhii DziupinandSerhii Dziupin 86e6a2ae76 Remove verified dead declarations (#2714)
* chore: remove verified dead declarations

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* chore: narrow unused internal exports

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* chore: remove newly exposed dead helpers

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* chore: remove unused deep-link serializer

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* test: drop two tests that assert on copies of the code

mainLayoutMobileSidebarMount read MainLayout.tsx and SessionSidebar.tsx as
strings and asserted on source substrings down to exact indentation, so it
failed on formatting rather than behaviour. useProjectSessionSelection.test
reimplemented the hook's visitNodes logic inside the test file and asserted
against that copy, so it could not observe the hook at all.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* test: repair sync suites that had rotted while unrunnable

No runner executed packages/ui, so these drifted from the source unnoticed:
two imported helpers that are no longer exported, one directory-store stub
predated the session field routeMessage reads, and the WebSocket fake missed
the mandatory url-token mint plus the close event the socket wrapper reads.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* test: stop the web suite failing on timeouts and a hand-copied mock

The Git suites drive a real git binary, so the 5s default made a valid suite
fail differently per run. The gitApiHttp mock listed ~70 export names by hand
and fell behind the source; it now derives every stub from the real module,
which the added shared-UI aliases make resolvable.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* test: run every suite from one command and in CI

packages/ui (232 files) and packages/vscode (22) had no test script at all, CI
ran neither, and 9 vscode files could never run because Node cannot resolve
their extensionless TypeScript imports. Three electron files sat outside every
script list, one of them importing vitest, which that package does not depend
on. A runner gives each file its own process, since these suites keep
module-level singletons and fail by load order when sharing one.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* chore: delete a superseded repro harness and a completed plan

The issue-2638 harness needed lsof, overrode process.platform and spawned real
servers, and nothing referenced it; event-stream/rebind.test.js now covers the
same hub-pinned-to-the-old-port behaviour. The pairing v2 plan described relay
and the pairing UI as out of scope, both of which shipped.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* docs: point at the theme tools and record the github barrel invariant

convert-vscode-theme and harmonize-theme were referenced nowhere, so the
theme-authoring reference now names them. The github barrel is loaded through
await import('./index.js') and destructured per route, which no static report
can see; documenting that is what stops the next cleanup from deleting it.

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>

* test: repair merge drift in bridge and route-registry mocks

upstream/main gained upsertProviderConfig on bridge-system-runtime and a
PATCH scheduled-task route after this branch forked. Their test doubles
were never updated to match:
- bridge-system-runtime.test.js: add upsertProviderConfig to the
  opencodeConfig mock so the import resolves.
- sse-routes.test.js: add app.patch to the route registry stub.

---------

Co-authored-by: Serhii Dziupin <makeittech@users.noreply.github.com>
2026-08-13 15:30:54 +03:00
Bohdan Triapitsyn 59d988deda release v1.18.2 2026-08-10 20:57:44 +03:00
Bohdan Triapitsyn f8b33be5eb chore: bump @opencode-ai/sdk to 1.18.15 2026-08-09 20:03:06 +03:00
Bohdan Triapitsyn 67965ced2f release v1.18.1 2026-08-04 19:39:40 +03:00
Bohdan Triapitsyn f28d36a23f release v1.18.0 2026-08-04 02:29:53 +03:00
Bohdan Triapitsyn 134d055ee6 fix(git): support secure SSH config 2026-08-02 23:02:14 +03:00
Bohdan Triapitsyn 37ff3a8164 release v1.17.2 2026-08-01 23:17:28 +03:00
Bohdan Triapitsyn 4c7b87bb21 release v1.17.1 2026-07-29 20:18:11 +03:00
Bohdan Triapitsyn 0716797efb chore: bump @opencode-ai/sdk to 1.18.9 2026-07-29 20:16:58 +03:00
Bohdan Triapitsyn c4c5087715 release v1.17.0 2026-07-28 19:39:32 +03:00
Bohdan Triapitsyn 3a5c399298 chore: bump @opencode-ai/sdk to 1.18.8 2026-07-28 12:26:20 +03:00
Bohdan Triapitsyn 3fa0c5be57 chore: bump @opencode-ai/sdk to 1.18.7 2026-07-27 23:13:21 +03:00
Bohdan Triapitsyn b6cdf7b6a7 chore: update opencode sdk version to 1.18.5 2026-07-26 18:53:58 +03:00
Bohdan Triapitsyn 5f4ad9d824 release v1.16.3 2026-07-22 18:14:11 +03:00
Bohdan Triapitsyn fd0f6a6bac feat: support Office documents in chat attachments
Users can now attach Microsoft Office documents (.docx, .pptx, and .xlsx) and OpenDocument files (.odt, .odp, and .ods) from the shared web, desktop, mobile, and VS Code chat surfaces.

Document text is extracted locally and sent as a text/plain file part with the original filename, keeping the visible user message clean. Supported embedded PNG, JPEG, GIF, and WebP images are sent as separate image parts, with matching [filename] citations preserved near their source paragraph, slide object, spreadsheet cell anchor, or OpenDocument position. Presentation notes, spreadsheet values, headers, and footers are included where available.

Document expansion is metadata-validated and bounded against oversized entries, excessive uncompressed data, unsafe paths, invalid image signatures, attachment-name races, and dangling citations after truncation. Generated document parts are published to the composer atomically.

Add fflate for worker-backed ZIP extraction and narrowly allow blob workers in the VS Code webview CSP without permitting blob scripts. Include focused fixtures for every supported format, extraction limits, positional citations, collision recovery, atomic attachment state, and CSP behavior.
2026-07-22 13:11:42 +03:00
Bohdan Triapitsyn 55013ecb25 chore: update opencode sdk version 2026-07-22 11:44:47 +03:00
Bohdan Triapitsyn 27e1775126 release v1.16.2 2026-07-18 10:05:06 +03:00
Bohdan Triapitsyn 66f3969273 chore: bump @opencode-ai/sdk to 1.18.3
Updates the SDK dependency across web, UI, and VS Code packages.
Refreshes the lockfile and package versions to match the release.
Adds unreleased changelog notes for the current set of user-facing changes.
2026-07-18 01:19:15 +03:00
Bohdan Triapitsyn 5a80638fba release v1.16.1 2026-07-14 01:51:00 +03:00
Bohdan Triapitsyn 3362ebbfa3 release v1.16.0 2026-07-13 02:30:40 +03:00
Bohdan Triapitsyn e9102df5f7 release v1.15.0 2026-07-10 19:41:49 +03:00
Bohdan Triapitsyn 6c2e657511 chore: draft unreleased changelog, bump opencode sdk to 1.17.18
Changelog leads with the private relay and the native mobile apps (TestFlight
beta + Android APK links), followed by pairing v2 and the device management,
desktop multi-transport, and chat items; VS Code changelog gets the shared
chat-render entries.
2026-07-10 13:42:52 +03:00
Bohdan Triapitsyn 624be556f6 release v1.14.1 2026-07-07 01:56:59 +03:00
Bohdan Triapitsyn e5b03493da release v1.14.0 2026-07-05 12:58:59 +03:00
Bohdan Triapitsyn 2bce38cfbb feat(chat): migrate history list to @tanstack/react-virtual with deterministic mobile history loading
- Replace virtua with @tanstack/react-virtual for chat history on all
  surfaces: bottom anchoring (anchorTo: end), key-stable prepend
  preservation, and native iOS touch/momentum deferral live in the core
- Patch virtual-core to clamp the render range to real scroll bounds
  during transient adjustments
- Rows render in normal flow inside a translated wrapper so sticky user
  headers keep working; measurement snapshots cached per session
- Pre-write container height in scrollToFn so the browser cannot clamp
  anchor corrections to the stale height; hold the prepend anchor for up
  to 180 frames on mobile while fresh rows settle (cancelled by user
  input; desktop relies on core anchoring alone)
- Adaptive row-size estimate from per-session measured averages; disable
  reveal fade-in for virtualized history rows
- Mobile loads older history only through an explicit localized top
  button: no scroll-position trigger and no post-mount background
  prepend, so every insert happens from a resting state; a quiet-window
  hold defers any stray prepend commit while a touch gesture is active
- Desktop/VS Code keep the seamless scroll-up trigger and progressive
  background prepend
2026-07-03 18:43:40 +03:00
Bohdan Triapitsyn be9911fac0 release v1.13.9 2026-07-02 19:00:58 +03:00