Commit Graph

513 Commits

Author SHA1 Message Date
imccyu
5c432955ed Merge remote-tracking branch 'origin/master' into web-permission-sandbox-merge-master 2026-07-29 11:16:49 +08:00
_Kerman
69aa58d31b Merge remote-tracking branch 'github/master' into xtr/trajectory-inspection-ui 2026-07-29 11:14:05 +08:00
Yichen Jiang
602f594c4b Merge remote-tracking branch 'origin/master' into worktree/web-model-request-retry
# Conflicts:
#	apps/cli/README.i18n.yaml
#	packages/client/connection/tests/fixture.spec.ts
#	packages/client/runtime/README.i18n.yaml
#	packages/client/runtime/src/client/index.ts
#	packages/client/runtime/src/client/sessions/session.ts
#	packages/client/ui-conversation/README.i18n.yaml
#	packages/client/ui-conversation/README.md
#	packages/client/ui-conversation/README.zh.md
#	packages/client/ui-conversation/src/client/chat/ChatView.tsx
#	packages/client/ui-conversation/tests/chat-view.spec.tsx
#	tsconfig.base.json
2026-07-29 10:14:02 +08:00
creatixchu
459128dfb6 fix(web): root USERPROFILE for the browser golden; re-record it against fresh bundles
- homedir() reads USERPROFILE on Windows: the golden's home collapse now
  sets and restores both variables, keeping the artifact machine-independent
  on every platform (ds-review-bot).
- The committed golden is re-recorded against freshly built bundles: the
  earlier recording ran with a stale dist that predated the navigation
  landmark and the button-in-listitem markup, which is why refreshes had
  looked byte-identical.
2026-07-29 01:57:19 +08:00
imccyu
667b0aff87 test(web): answer the fixture approval takeover; refresh aria goldens
The assembled fixture app now takes over the composer while fx-alpha's
resident approval is pending — the feature under test, not chrome noise —
so the session-title snapshot answers it (允许一次) before asserting the
model seat, mirroring what a user sees. The eleven keyless ui.expected.md
goldens re-record (DSH_SNAPSHOT=refresh, no key) for the Access placeholder
→ projection chip swap (Danger Full Access under the roster default) plus
the master-side chrome drift the goldens had accumulated (copy/branch/edit
buttons, tab rows) since their last refresh.
2026-07-29 01:15:31 +08:00
creatixchu
6cd63f741c fix(host): address review — Escape scoping, relist gating, crumb overflow, aria golden
- Escape (and the mask) now reaches only the topmost dialog: while the
  nested New-folder dialog is up the browser ignores its own Modal close,
  and the nested dialog's in-flight fence keeps both open during creation.
- New folder disables while any listing loads, so a slow post-create
  relist/select sequence cannot host a second create against a target the
  pending listing is about to change.
- Deep ancestry scrolls inside a dedicated crumb trail whose tail is pinned
  into view; the path-edit zone keeps its reserved width instead of being
  clipped by the card, preserving cross-drive path entry.
- The workspace-management e2e records a directory-browser aria golden at a
  staged tree (host HOME pointed at the scaffold cwd collapses ancestry into
  the Home crumb, keeping the artifact machine-independent), and the keyless
  snapshot's row targeting goes through visible label text — listitem
  accessible-name computation differs across dom-accessibility-api
  environments (the CI-only miss).
2026-07-28 23:21:27 +08:00
_Kerman
62dd2ab38e Merge remote-tracking branch 'github/master' into xtr/trajectory-inspection-ui
# Conflicts:
#	packages/client/runtime/src/client/sessions/fold-adapter.ts
#	packages/compact/compact-basic/src/summarizer.ts
2026-07-28 21:56:02 +08:00
Chinesezjc
1c8188ce2b Merge remote-tracking branch 'origin/master' into feat/web-terminal-card
# Conflicts:
#	packages/client/ui-conversation/README.i18n.yaml
2026-07-28 21:03:26 +08:00
Hypatia May
e466c66ee3 Merge remote-tracking branch 'origin/master' into codex/status-bar-token-metrics
# Conflicts:
#	docs/cordis-catalog/events.md
#	docs/event-producer-consumer.md
#	packages/client/runtime/src/client/sessions/conversation.ts
#	packages/client/runtime/src/client/sessions/session.ts
#	packages/client/runtime/tests/fake-api.ts
#	packages/client/runtime/tests/session.spec.ts
#	packages/client/ui-conversation/tests/chat-stats-bash-sample.spec.tsx
#	packages/client/ui-conversation/tests/chat-toolview-slot.spec.tsx
#	packages/client/ui-conversation/tests/chat-view.spec.tsx
#	packages/client/ui-conversation/tests/gate-branch-tails.spec.tsx
#	packages/client/ui-conversation/tests/queue-dock.spec.tsx
#	packages/core/agent-loop/README.i18n.yaml
#	packages/core/agent/README.i18n.yaml
#	packages/host/apiproxy/README.i18n.yaml
#	packages/host/apiproxy/src/api-proxy.ts
#	packages/host/apiproxy/src/api/events.schema.ts
#	packages/host/apiproxy/src/api/events.ts
#	packages/host/apiproxy/src/api/index.ts
#	packages/host/apiproxy/src/api/sessions.schema.ts
#	packages/host/apiproxy/src/api/sessions.ts
#	packages/host/apiproxy/tests/rpc-schemas.spec.ts
2026-07-28 19:34:30 +08:00
Chinesezjc
dbe7ac8234 Merge remote-tracking branch 'origin/master' into feat/web-terminal-card
# Conflicts:
#	apps/web/tests/navigation-panes.e2e.ts
#	apps/web/tests/snapshots/navigation-panes/details-open.expected.md
#	packages/client/ui-conversation/README.i18n.yaml
#	packages/client/ui-conversation/README.md
#	packages/client/ui-conversation/README.zh.md
#	packages/client/ui-conversation/src/client/chat/GenericToolCard.tsx
#	packages/client/ui-conversation/src/client/chat/ToolRow.tsx
#	packages/client/ui-conversation/src/client/toolviews/bash-sample.tsx
#	packages/client/ui-conversation/tests/chat-tool-row.spec.tsx
2026-07-28 19:03:03 +08:00
Chinesezjc
60248e99d1 Merge remote-tracking branch 'origin/master' into feat/scrollbar-tokens 2026-07-28 18:15:00 +08:00
_Kerman
0e1e594314 Merge remote-tracking branch 'origin/master' into xtr/trajectory-timeline
# Conflicts:
#	apps/web/tests/code-mode-fixture.snapshot.ts
#	apps/web/tests/navigation-panes.e2e.ts
#	apps/web/tests/snapshots/navigation-panes/details-open.expected.md
#	packages/client/runtime/src/client/index.ts
#	packages/client/runtime/src/client/sessions/fold-adapter.ts
#	packages/client/ui-trajectory/tests/views.spec.tsx
2026-07-28 18:06:04 +08:00
NI0317
544d543ad1 fix(web): close the GUI update feedback loop 2026-07-28 18:04:21 +08:00
_Kerman
bbd9949d31 feat(client): refine trajectory timeline interaction 2026-07-28 18:02:19 +08:00
Hypatia May
3f0ba77bfa Merge remote-tracking branch 'origin/master' into codex/status-bar-token-metrics
# Conflicts:
#	packages/client/ui-conversation/README.i18n.yaml
#	packages/host/apiproxy/README.i18n.yaml
#	packages/host/apiproxy/README.md
#	packages/host/apiproxy/README.zh.md
#	packages/host/apiproxy/src/api-proxy.ts
2026-07-28 17:55:01 +08:00
Chinesezjc
4265ac876c fix(client): rebind the scrollbar indirection on three missed elevated surfaces
Review found three scroll containers sitting on surfaces the rebinding
contract covers, none of which rebound: ui-primitives' shared Menu card
on --dsw-specific-menu (the surface PopupSelectView already rebinds for),
and the composer input and question composer cards, both on
--dsw-specific-input-major. Each rendered the l1 thumb, which differs
from l2 only in the dark palette and only on that surface, so a
light-palette screenshot and a code read both look correct.

Adds the mechanical check that would have caught them instead of leaving
it to inspection: a sheet that scrolls somewhere and paints a known
elevated surface somewhere must rebind. The elevated set is derived from
the sheets that already rebind, since a rebinding rule paints the surface
whose elevation it declares, so a new elevated surface joins the set by
rebinding rather than by anyone updating a list. Surface-level rather than
element-level because the card and the descendant that scrolls are
separate rules and CSS text does not say which contains which. Verified by
reverting each of the three fixes in turn: the check names the sheet and
the surface every time.

Also commits snapshots/sidebar-scrollbar/geometry.expected.md, the
resolved scrollbar style and geometry in both palettes. The aria goldens
the other web scenarios commit cannot carry a CSS-only change, since it
alters no DOM and no accessible name and leaves their trees
byte-identical. Absolute coordinates stay out: they track font metrics and
the laid-out sidebar width, so committing them would document the platform
and force a per-platform re-record.
2026-07-28 17:42:57 +08:00
NI0317
568866d5a8 fix(web): orient agents to the running GUI 2026-07-28 17:20:20 +08:00
Chinesezjc
f4c243c75f feat(web): state the run state on the terminal card's prompt line
The terminal card showed no run state: a running command and a settled
command that produced no output rendered the same prompt line, so whether
a command was still running had to be inferred from the absence of output.

Lead the prompt line with a StateDot in three of its states — the spinning
ring while running, red for the same exit status that renders the status
pill, green for a clean settle. That is the same indicator a tool row's
leading icon carries, so a row and its own card cannot disagree about one
command; the row/card agreement is pinned in the ui-conversation spec.
StateDot is aria-hidden, so a visually hidden text label rides beside it,
which is what the refreshed aria goldens now record.

The e2e adds what jsdom cannot compute: the dot's color resolves to the
green success token through the real theme stylesheet, and the dot precedes
the prompt label in document order.
2026-07-28 16:41:04 +08:00
_Kerman
1d4a6149cc feat(client): add trajectory timing overview 2026-07-28 16:28:57 +08:00
07akioni
c30c891628 fix: ci 2026-07-28 15:21:34 +08:00
Chinesezjc
5081697aaf feat(web): render bash tool output as a terminal card
The bash tool already declares the `card: 'terminal'` render intent for
both its call and its result, and host/connection/runtime already deliver
it to the browser as callView/resultView. The Web client ignored it:
rows derived from raw args, and the details panel flattened every tool's
content into one soft-wrapping `<pre>`. Column-aligned output folded into
a paragraph and a long listing stretched the panel without bound.

`TerminalBlock` (ui-primitives) renders a command as a terminal surface:
a shortened-cwd prompt line, output at `white-space: pre` in a
horizontally scrolling box, a head/tail height cap with an expand
control, an exit-code/signal status pill, and a copy control for the raw
output. ANSI SGR runs are parsed with `anser` and resolved onto `--dsw-*`
theme tokens, with literal rgb kept for values the design system has no
token for. Geometry and fonts mirror CodeBlock; the clipboard write both
need moved into a package-internal `clipboard.ts`.

Both Web render sites for a bash call consume the intent through one
derivation (`terminal-card-model.ts`), so they cannot disagree about a
command, its cwd, or its exit status: the keyed BashRow carries the card
resident below its summary row, and the render-site fallback row keeps it
behind its existing expand control. Rows cap at 8 lines against the
panel's 16.

Inline output in the chat row reverses this package's stated
no-inline-output convention, on the owner's explicit decision; the Agent
Note records the reversal and its bound.

Tests: TerminalBlock/ansi/clipboard unit specs, ui-conversation wiring
specs at every render site, a built-client-graph snapshot covering both
chat-row shapes, and a real-browser e2e asserting the no-wrap layout and
the page's own Clipboard API.
2026-07-28 14:58:06 +08:00
Hypatia May
9ca0241d5d feat(web): add durable session metrics (round 1) 2026-07-28 12:10:48 +08:00
Yichen Jiang
1dede11506 Merge remote-tracking branch 'origin/master' into worktree/web-model-request-retry
# Conflicts:
#	.agents/notes/implemented/architecture/2026-06-21-bounded-llm-request-recovery.i18n.yaml
#	.agents/notes/implemented/architecture/2026-06-21-bounded-llm-request-recovery.md
#	.agents/notes/implemented/architecture/2026-06-21-bounded-llm-request-recovery.zh.md
#	apps/web/tests/session-title.snapshot.ts
#	docs/config-catalog.md
#	packages/client/runtime/README.i18n.yaml
#	packages/client/runtime/README.md
#	packages/client/runtime/README.zh.md
#	packages/client/ui-conversation/README.i18n.yaml
#	packages/client/ui-conversation/src/client/chat/ChatView.tsx
#	packages/client/ui-conversation/tests/chat-view.spec.tsx
#	packages/llm/llm-retry/README.i18n.yaml
#	packages/llm/llm-retry/README.md
#	packages/llm/llm-retry/README.zh.md
2026-07-28 11:39:42 +08:00
_Kerman
92081094ae fix(ui): reconcile trajectory ledger with current client contracts 2026-07-28 10:23:44 +08:00
_Kerman
a4f4751600 Merge remote-tracking branch 'github/master' into xtr/trajectory-inspection-ui
# Conflicts:
#	packages/client/ui-primitives/src/Menu.tsx
#	packages/client/ui-trajectory/src/client/TrajectoryCell.tsx
#	packages/client/ui-trajectory/src/client/TrajectoryView.tsx
#	packages/client/ui-trajectory/tests/layout.spec.tsx
#	pnpm-lock.yaml
#	pnpm-workspace.yaml
2026-07-28 10:12:29 +08:00
Hypatia May
05d4c19085 Merge remote-tracking branch 'origin/master' into codex/basic-session-search
# Conflicts:
#	apps/web/tests/snapshots/question-composer/answered.expected.md
#	packages/client/connection/tests/fake-api.ts
#	packages/client/runtime/README.i18n.yaml
#	packages/client/runtime/tests/fake-api.ts
#	packages/client/ui-workspace/README.i18n.yaml
#	packages/client/ui-workspace/README.md
#	packages/client/ui-workspace/README.zh.md
#	packages/client/ui-workspace/src/client/WorkspaceBrowser.tsx
#	packages/client/ui-workspace/tests/apply.spec.ts
#	packages/host/apiproxy/README.i18n.yaml
#	packages/host/apiproxy/README.md
#	packages/host/apiproxy/README.zh.md
#	packages/host/apiproxy/src/api-proxy.ts
#	packages/host/apiproxy/src/api/index.ts
#	packages/host/apiproxy/src/api/sessions.schema.ts
#	packages/host/apiproxy/src/fetch/client.ts
#	packages/host/apiproxy/src/fetch/handler.ts
#	packages/host/apiproxy/tests/fetch-carrier.spec.ts
#	packages/host/apiproxy/tests/rpc-schemas.spec.ts
#	packages/session-query/session-query/tests/search-helpers.spec.ts
2026-07-28 09:27:28 +08:00
imccyu
af70af4020 Merge remote-tracking branch 'origin/master' into worktree/web-session-model-selector 2026-07-28 00:39:24 +08:00
Tianyi Cui
064cea4ebe Merge remote-tracking branch 'origin/master' into worktree/pr743-merge-20260727
# Conflicts:
#	examples/acp-agent/tests/snapshots/escalation-approved/session.jsonl
#	examples/acp-agent/tests/snapshots/escalation-rejected/session.jsonl
#	examples/acp-agent/tests/snapshots/fs-escalation-approved/session.jsonl
#	examples/acp-agent/tests/snapshots/hook-cc-pretool-ask/session.jsonl
#	examples/acp-agent/tests/snapshots/session-query-spill/session.jsonl
#	examples/cordis-agent/tests/cordis-tools.e2e.ts
#	examples/headless-agent/tests/snapshots/advanced-toolchain/session.1.jsonl
#	examples/headless-agent/tests/snapshots/advanced-toolchain/session.2.jsonl
#	examples/headless-agent/tests/snapshots/advanced-toolchain/session.jsonl
2026-07-27 23:59:33 +08:00
Tianyi Cui
7a60a523f9 Merge branch 'master' into feature/cordis-temporary-tools 2026-07-27 22:26:49 +08:00
NI0317
1ef285d038 Restore Cordis mount and unmount names
Keep temporary lifecycle descriptions and UI labels explicit.
2026-07-27 21:20:06 +08:00
Chinesezjc
f11dc28f1f test(web): record the user-bubble action row in the answered golden
The answered golden omitted the `复制` / `在新对话中分支` / `编辑` buttons
that `MessageItem`'s `UserActions` renders under every user bubble, so the
scenario failed against the built client. They are unconditional in the
accessibility tree — the `@media (hover: hover)` rule only sets `opacity`,
which does not remove a node from an aria snapshot — so there is no
message-row state to stabilize before capture; the golden was simply
recorded against a stale `lib/`. A partially failed `pnpm run build` had
left the client bundles from before its failure current and the rest not.

The Agent Note records that trap: confirm the build exited zero before
refreshing a golden, and note that untracked directories under `packages/`
are compiled too, so a leftover from another branch fails the build for
reasons the diff does not explain.

The same omission is present in the other 15 committed web goldens on
master, where 9 tests across 7 files fail for this reason on a pristine
tree. That is pre-existing and belongs to whoever landed `UserActions`;
this commit fixes only the golden this PR already touches.
2026-07-27 19:54:55 +08:00
Chinesezjc
9dd57a25c5 fix(ui-question): stop option rows absorbing the capped card's shortfall
The question composer card is capped against the viewport and scrolls its
option list. `.options` is a flex column whose children defaulted to
`flex-shrink: 1`, so a short seat shrank the rows before overflowing the
scroll container: a row collapsed to its 42px minimum while `.optionCopy`
kept the taller height its wrapped copy needs, and `align-items: center`
then painted that copy outside the row's border box — over the question
title above and the next row below. Measured 6.5px of spill at 900x440 on
the shipped client, 10px at 380px tall, with `.options` reporting
scrollHeight === clientHeight and therefore offering no scrollbar.

`.option` and `.custom` now declare `flex-shrink: 0`, so the shortfall
reaches the scroll container that already owns `overflow-y: auto` — the
behavior the cap was designed for. Only rows whose copy wraps could
reproduce this, which is why the recorded scenario now asks a question
with long option descriptions; the web e2e asserts at three squeezed seat
heights that every row's children stay inside its border box, guarded
against holding vacuously by requiring a wrapped row and a scrolling list.
2026-07-27 19:20:33 +08:00
Hypatia May
4727d742db fix(web): align session search contracts 2026-07-27 18:38:00 +08:00
fz
826c6fd243 feat(web): present Cordis lifecycle tools 2026-07-27 17:57:59 +08:00
Hypatia May
8f9262edc3 test(web): refresh snapshots after master merge 2026-07-27 17:09:49 +08:00
_Kerman
628c1bffe0 feat(ui): add trajectory inspection ledger 2026-07-27 15:47:44 +08:00
Hypatia May
0aa7f8c5cf fix(web): converge session search boundaries (round 9) 2026-07-27 14:46:08 +08:00
Hypatia May
222096e3cf fix(web): validate search hit provenance (round 2) 2026-07-27 12:27:11 +08:00
Yichen Jiang
bde5e26a96 Merge remote-tracking branch 'origin/master' into worktree/web-session-model-selector
# Conflicts:
#	apps/cli/package.json
#	apps/web/tests/smoke-real.e2e.ts
#	apps/web/tests/snapshots/fresh-round-trip/ui.expected.md
#	apps/web/tests/snapshots/seeded-history/ui.expected.md
#	docs/config-catalog.md
#	packages/client/connection/tests/fake-api.ts
#	packages/client/runtime/src/client/index.ts
#	packages/client/runtime/src/client/sessions/conversation.ts
#	packages/client/runtime/src/client/sessions/session.ts
#	packages/client/runtime/tests/fake-api.ts
#	packages/client/ui-conversation/src/client/apply.ts
#	packages/client/ui-conversation/src/client/contract/slots.ts
#	packages/client/ui-conversation/src/client/index.ts
#	packages/client/ui-conversation/src/client/skeleton/ConversationRoot.tsx
#	packages/client/ui-conversation/src/client/skeleton/InputBar.tsx
#	packages/client/ui-conversation/tests/chat-stats-bash-sample.spec.tsx
#	packages/client/ui-conversation/tests/chat-toolview-slot.spec.tsx
#	packages/client/ui-conversation/tests/chat-view.spec.tsx
#	packages/client/ui-conversation/tests/gate-branch-tails.spec.tsx
#	packages/client/ui-conversation/tests/input-bar.spec.tsx
#	packages/client/ui-conversation/tests/skeleton.spec.tsx
#	packages/host/apiproxy/README.md
#	packages/host/apiproxy/src/api-proxy.ts
#	pnpm-lock.yaml
#	scripts/verify-package-readme-model-experience.ts
#	tsconfig.base.json
2026-07-27 12:17:38 +08:00
Hypatia May
891e9035e7 feat(web): add basic past-session search (round 1) 2026-07-27 12:15:06 +08:00
Yichen Jiang
cd5c1f88a1 Merge remote-tracking branch 'origin/master' into worktree/web-model-request-retry
# Conflicts:
#	apps/web/tests/smoke-real.e2e.ts
#	packages/client/runtime/src/client/index.ts
#	packages/client/runtime/src/client/sessions/session.ts
#	packages/client/ui-conversation/src/client/chat/ChatView.tsx
#	packages/client/ui-conversation/src/client/chat/MessageItem.module.css
#	packages/client/ui-conversation/src/client/chat/MessageItem.tsx
2026-07-27 12:14:23 +08:00
imccyu
1b49666cd5 Merge branch 'master' into worktree-slash-split 2026-07-27 08:54:56 +08:00
imccyu
ecdaf0dc24 test(web): connect a Workspace in the e2e boot path and refresh goldens
The startup-selection flow leaves a fresh world (no Workspace) in the
locked view state, so every e2e scenario that types into the composer
now connects one first via the shared connectFreshWorkspace helper
(hero picker create-by-name dialog; the default 'workspace' name keeps
the session-header cwd assertions intact).

Golden refreshes carry the current composer chrome: the plan/model
control seats are empty until their owning plugins register (the seats
shipped without occupants on this branch), the sidebar shows the
connected workspace group pre-send, and the bash details material
renders Input/code/Output as separate nodes. The cancel scenario polls
the frozen-partial swap instead of counting synchronously — the abort
frame reaches the browser over SSE after the host settles.
2026-07-27 08:25:00 +08:00
Tianyi Cui
a20cf88928 test(session): canonicalize fixtures as packed rows 2026-07-26 23:45:14 +08:00
Tianyi Cui
709ac6b531 Merge branch 'master' into web-e2e-interactions 2026-07-26 21:29:34 +08:00
Tianyi Cui
0ba1e8320e Merge branch 'master' into web-e2e-interactions 2026-07-26 21:23:10 +08:00
Tianyi Cui
f8342b0a8e test(web): cover the settings surface and workspace management
Two new keyless scenarios for the functionality master gained since this
lane's base (#644 websettings, #643 workspace browser rework), both zero
model calls:

- settings-chrome: the modal shell (sidebar-foot trigger aria states,
  role=dialog, aria-current section switch to the deliberately empty
  Models, Escape + close-button paths, dialog aria golden); the Appearance
  row as the REAL theme gesture — retiring lifecycle-chrome's
  TODO(web-theme-gesture): clicking 深色 runs aria-pressed -> persisted
  dsh.theme -> body[data-ds-dark-theme] -> alias-token flip, survives
  reload, and 'system' follows the emulated OS scheme both ways; the
  Language row switches the settings-scoped copy to English (dsh.locale
  persisted, survives reload) and restores zh. Intentional reloads tear
  the SSE stream, so the spec drains exactly its own reconnect warnings —
  the tripwire still fails on unexpected connection loss.
- workspace-management: create-by-name twice through the region-header
  dialog (host-durable via ctx.workspace.list()); rename end to end —
  hover-revealed row menu (the button is display:none until the row
  hovers), duplicate-name pre-check (inline role=alert + disabled primary
  before any wire call), then workspace.rename through the real RPC,
  row update, host durability, reload survival; the flat 'In one list'
  view (section label flips, group headers drop, dsh.workspace.view
  persists across reload, grouped restored); the session hover card
  (dwell to open, closes on pointer leave). The one session row reuses
  seeded-history's committed seed — no new recording. Deliberately not
  driven: the inert menu rows and drag reorder (deferred in the note
  with re-entry triggers).

Agent Note gains scenarios 8-9 and the drag-reorder deferred item in both
languages; llm-replay README's zh side catches up with the { patches }
paragraph; pairings re-recorded.
2026-07-26 20:38:36 +08:00
Tianyi Cui
1998915630 test(web): refresh the hero golden for the localized settings label
The websettings merge (#644) localized the sidebar foot to 设置; the
lifecycle-chrome hero golden pinned the old English label. Keyless
DSH_SNAPSHOT=refresh rewrite; full lane green twice after.
2026-07-26 14:40:54 +08:00
Yichen Jiang
8c77ba6420 Merge remote-tracking branch 'origin/master' into worktree/web-model-request-retry 2026-07-26 14:09:43 +08:00
Yichen Jiang
a430207427 feat(web): retry transient model requests 2026-07-26 14:09:31 +08:00