Commit Graph

621 Commits

Author SHA1 Message Date
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
_Kerman
57d90c343d Merge remote-tracking branch 'origin/master' into xtr/agent-loop-message-machine
# Conflicts:
#	.agents/notes/implemented/feature/2026-06-14-acp-agent-client-protocol.md
#	.agents/notes/implemented/feature/2026-06-14-acp-agent-client-protocol.zh.md
#	.agents/notes/implemented/feature/2026-06-30-hook-bridges.i18n.yaml
#	.agents/notes/implemented/feature/2026-06-30-interception-seams.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-06-sandbox.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-06-sandbox.md
#	.agents/notes/implemented/feature/2026-07-06-sandbox.zh.md
#	.agents/notes/implemented/feature/2026-07-19-model-facing-goal-tools.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-19-same-session-goal-round-driver.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-25-workspace-ui-product-flow.i18n.yaml
#	.agents/notes/implemented/simplification/2026-07-02-remove-stream-chunk-mirror.i18n.yaml
#	docs/architecture.i18n.yaml
#	docs/cookbook/adding-a-tool.i18n.yaml
#	docs/cookbook/extension-cookbook.i18n.yaml
#	docs/core-data-structures/llm-streaming.i18n.yaml
#	docs/core-data-structures/session.i18n.yaml
#	docs/core-data-structures/tools.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/persistence-catalog.md
#	examples/acp-agent/tests/snapshots/cordis-inspect-jsdoc/stdout.expected.jsonl
#	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/permission-switching/session.jsonl
#	examples/acp-agent/tests/snapshots/plan-mode-reject/session.jsonl
#	examples/acp-agent/tests/snapshots/plan-mode/session.jsonl
#	examples/acp-agent/tests/snapshots/session-sandbox-root/session.jsonl
#	packages/context/session-reference/README.md
#	packages/core/agent-loop/tests/agent.spec.ts
#	packages/hooks/hooks-claude/tests/coverage-cases.ts
#	packages/host/runtime/tests/host-runtime.spec.ts
#	packages/llm/llm-retry/tests/retry.spec.ts
#	packages/session-persistence/session-persistence/src/coordinator.ts
#	packages/support/acp-snapshot/README.md
#	packages/support/acp-snapshot/src/normalize.ts
#	packages/ui/acp/acp-feature-support.md
#	packages/ui/acp/src/codec.ts
#	packages/ui/acp/src/index.ts
#	packages/ui/acp/tests/bridge.spec.ts
#	packages/ui/acp/tests/codec.spec.ts
#	packages/ui/acp/tests/config-options.spec.ts
#	packages/ui/acp/tests/dispose.spec.ts
#	packages/ui/acp/tests/edges.spec.ts
#	packages/ui/acp/tests/stream-update.spec.ts
#	packages/ui/acp/tests/turns.spec.ts
2026-07-26 14:05:33 +08:00
Yichen Jiang
cba0948604 Merge remote-tracking branch 'origin/master' into worktree/web-session-model-selector
# Conflicts:
#	.agents/notes/implemented/architecture/2026-07-15-llm-model-catalog-and-acp-selection.i18n.yaml
#	.agents/notes/implemented/architecture/2026-07-23-client-plugin-loading-model.i18n.yaml
#	apps/cli/src/web.ts
#	apps/web/tests/session-title.snapshot.ts
#	apps/web/tests/smoke-fixture.e2e.ts
#	packages/client/connection/src/client/api.ts
#	packages/client/connection/src/client/fixture.ts
#	packages/client/connection/src/client/index.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/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.module.css
#	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/skeleton-branches.spec.tsx
#	packages/client/ui-conversation/tests/skeleton.spec.tsx
#	packages/host/apiproxy/README.md
#	packages/host/apiproxy/src/api-proxy.ts
#	packages/host/apiproxy/src/api/rpc.schema.ts
#	packages/host/apiproxy/src/api/rpc.ts
#	packages/host/apiproxy/tests/api-proxy-models.spec.ts
#	packages/host/apiproxy/tests/rpc-schemas.spec.ts
#	packages/host/runtime/README.md
#	packages/llm/llm-deepseek/README.md
#	scripts/translation-pairing.manifest.json
#	tsconfig.client.json
2026-07-26 13:13:53 +08:00
Tianyi Cui
202ef2fc89 Merge branch 'code-mode-ui/dispatch-spill' into code-mode-ui/shiki 2026-07-26 12:30:26 +08:00
Tianyi Cui
6333b51f2f Merge branch 'code-mode-ui/web-ui-v1' into code-mode-ui/live-parallel 2026-07-26 12:30:03 +08:00
Tianyi Cui
104e83109f fix: address review — plain fences while streaming
ds-review-bot finding: a growing fence retokenized on every chunk
(quadratic main-thread work). MarkdownText gains a streaming flag —
the streaming partial renders fences through the plain arm and the
finalize swap highlights once; AssistantMarkdown threads its existing
flag. (The zh Agent Note pair the review also flagged landed earlier
on this branch.) New spec pins plain-while-streaming and
highlighted-after-finalize.
2026-07-26 10:43:52 +08:00
Tianyi Cui
a786911293 fix: address review — non-vacuous error assertion, package contracts
ds-review-bot findings: the browser e2e's error-state check now requires
at least one error sub-row (was >= 0); the runtime README documents the
codeDispatches snapshot contract and the ui-conversation README the code
variant + nested sub-row semantics.
2026-07-26 10:36:35 +08:00
Tianyi Cui
bb3dc50a4b feat(web): shiki syntax highlighting for code surfaces
One highlighter for the client: a synchronous fine-grained shiki core
(JS regex engine, no WASM) in ui-primitives with an explicit grammar
allowlist (typescript, shellscript, json — aliases resolve, unknown
languages take a geometry-identical plain arm). The shared CodeBlock
component owns both arms; markdown fences, the run_code expanded
program body (typescript), and the details panel Input (json) all
route through it. Token colors live in a new ui-theme shiki.css sheet
as --shiki-* custom properties (light/dark blocks), wired through the
shell's base.css chain — tokens-only styling holds; shiki's generated
span tree is the sanctioned innerHTML path (static output, no user
HTML). jsdom specs pin token spans, aliases, both fallbacks, and the
fence route; the built-bundle snapshot asserts the highlighted program
under the code row.
2026-07-26 09:52:37 +08:00
Tianyi Cui
8a79679489 feat(tools): live dispatch lifecycle + native-contract parallel sub-calls in Code Mode
The bridge replaces its serialization queue with a pool that reuses the
native concurrency contract: submissions classify through
registry.executionMode (fail-closed isConcurrencySafe), start strictly in
submission order, overlap up to the validated maxParallelSubCalls config
(default 10; 1 restores serial), and exclusive calls drain the pool, run
alone, and bar later calls. Each started sub-call logs a
tool/code-dispatch-start event at pool entry; the existing
tool/code-dispatch settles the pair (started ⇔ settles exactly once;
abandoned queued calls log neither). SDK prompt guidance now states the
true Promise.all contract — re-recorded across every code/both-mode
snapshot (plus the stale cordis-dynamic-toolchain fixture gaining the
required description arg).

Client: CodeSubCall widens to RunningToolCall | ToolResultNode — starts
land the running shape (rows wear the native running ring), settles
replace in place preserving start order, callTime pairs to the start
time. Fixture emits start/settle pairs; jsdom pins the running sub-row;
runtime specs pin in-place settlement and out-of-order completion.
2026-07-26 06:02:36 +08:00
Tianyi Cui
226dc7a249 docs: translate remaining READMEs 2026-07-26 05:06:39 +08:00
Chinesezjc
99805b6340 fix(gui): merge adaptations to master's apiproxy defaults and deleted test hook
The origin/master merge introduced a required workspaceRoot on
ApiProxyDefaults and deleted the ui-conversation test hook.ts helper.
Add workspaceRoot to the new todo-projection api-proxy test and bind
the todo-panel spec's selector hook via bindSnapshotSelector directly,
matching the sibling specs.
2026-07-26 04:30:58 +08:00
Tianyi Cui
13f7c62318 feat(web): render Code Mode sub-calls as native rows nested under the run_code row
The client indexes tool/code-dispatch events into
ConversationSnapshot.codeDispatches (parent callId -> ToolResultNode-shaped
sub-calls; live mux and history replay build the identical index). ChatView
renders each run_code parent as the new code variant (description summary,
program as the expanded monospace body) with its sub-dispatches as
always-visible indented rows — every sub-row dispatches through the SAME
keyed conversation.chat.toolview hole with the same GenericToolCard
fallback, so custom registrations (bash sample) take over sub-rows exactly
as top-level rows. The details panel resolves sub-callIds to full logged
args and complete output through the native path.

Evidence: fixture turn 64 + built-bundle jsdom snapshot, real-machinery
jsdom suites (nesting, error state, details, running parent, reference
stability), and a recorded code-mode browser e2e round (keyless replay +
aria golden). Scaffold gains a toolsMode patch knob.
2026-07-26 04:02:38 +08:00
Chinesezjc
012b712820 Merge remote-tracking branch 'origin/master' into web2-todo
# Conflicts:
#	.agents/notes/implemented/feature/2026-06-29-todo-write-tool.i18n.yaml
#	.agents/notes/implemented/feature/2026-06-29-todo-write-tool.md
#	.agents/notes/implemented/feature/2026-06-29-todo-write-tool.zh.md
#	apps/web/tests/smoke-fixture.e2e.ts
#	examples/acp-agent/tests/snapshots/model-switching/tool-schemas.expected.json
#	examples/acp-agent/tests/snapshots/permission-switching/tool-schemas.expected.json
#	examples/acp-agent/tests/snapshots/plan-mode/tool-schemas.expected.json
#	packages/client/runtime/README.md
#	packages/client/runtime/src/client/index.ts
#	packages/client/runtime/src/client/sessions/conversation.ts
#	packages/client/ui-conversation/src/client/skeleton/ConversationRoot.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/skeleton-branches.spec.tsx
#	packages/client/ui-conversation/tests/skeleton.spec.tsx
#	packages/todo/tool-todo/README.md
2026-07-26 03:33:57 +08:00
imccyu
6e721b9fdd feat(gui): settings panel with locale and theme preferences
Add the browser Settings surface as slot-composed plugins over new
preference services:

- Rename dsh-client-i18n to dsh-client-locale (locale is the domain
  name); LocaleService adds getLocale()/setLocale(id), immutable
  snapshots, a locale/change event, and dsh.locale persistence.
- ThemeService owns the light/dark/system preference (default system),
  resolves system via prefers-color-scheme, publishes theme/change
  snapshots, persists dsh.theme, and no longer touches the DOM;
  ui-layout's ThemePresenter applies resolved snapshots
  (body[data-ds-dark-theme] + alias tokens) and cleans up on dispose.
- ui-sidebar drops the phase-1 settings dropdown/modal; the foot renders
  the new sidebar.settings slot with the column state.
- New ui-settings shell occupies sidebar.settings: foot trigger row and
  the centered 1080x700 panel (figma 501:29947) with 24% mask, close
  button / mask click / Escape all closing, and a 188px nav projected
  from the settings.section list slot it declares. Nav labels are
  registrant-localized; sections re-register on locale change, so the
  ledger version is the shell's only subscription.
- ui-settings-general registers the General section: Permission and
  Tool Call skeletons, live Language (locale menu) and Appearance
  (Light/Dark/System cubes following the persisted preference); its
  slot store mirrors both service snapshots via apply-side listeners.
- ui-settings-models registers the Models nav entry with an empty
  content column.
- Portaled menus pin z-index above modal overlays (a menu anchored
  inside the settings dialog rendered underneath it and was
  unclickable).
- theme/data/list-pen icons in ui-primitives; settings copy ships as
  zh/en dictionaries; fixture manifests gain the settings rows.
2026-07-26 00:28:43 +08:00
imccyu
468c64a078 fix(web): keep composer add action attachment-only 2026-07-25 17:46:05 +08:00
imccyu
08ce02da2b docs(web): finalize workspace UI product flow 2026-07-25 17:46:04 +08:00
imccyu
9eb9c70a8a feat(web): add workspace-aware session flow 2026-07-25 17:45:26 +08:00
Turtle
fac6c35e9a Trim redundant source comments 2026-07-25 13:02:37 +08:00
Chinesezjc
1f094ae076 fix(gui): todo row keeps running/stopped execution states visible
The row rendered a status only for error, so a call cancelled before
tool/result read as a completed plan update even though no todo/write
occurred. Non-ok states now ride the generic row's StateDot semantics
(ongoing dot while running, warning dot + 已中断 marker when interrupted);
the ok badge stays for settled successful updates.
2026-07-25 00:42:40 +08:00
Chinesezjc
62bfc6b4fb docs(gui): bring the todo tool note's Chinese side along
master gave 2026-06-29-todo-write-tool a Chinese counterpart; the English
side's web-consumer sentences now translate across (in-body links keep
their .md targets per the pairing contract) and the pair is re-recorded.
The todo-panel fake gains the time/callTime fields ToolResultNode now
requires.
2026-07-24 23:10:19 +08:00
Chinesezjc
02abe3c821 fix(gui): todo-row guards valid-JSON invalid-shape args before dereferencing
null roots, non-object roots, and null array items (retained verbatim on a
rejected tool/call) now take the documented generic-summary fallback instead
of throwing into the row error boundary.
2026-07-24 22:56:12 +08:00
Chinesezjc
63109dab66 feat(gui): todo display — TodoPanel plan strip + todo_write toolview row
TodoPanel pins above the composer (776px card axis), hidden while empty,
collapsible with the active item as the collapsed hint; status glyphs
mirror the TUI plan panel. todo_write rows render a plan-flavored summary
(counts + active item) via the toolview registry, generic fallback on
malformed args. Existing fake snapshots gain the required todos field.
2026-07-24 22:56:12 +08:00
Chinesezjc
a0c269b0fb feat(gui): fold todo/write into ConversationSnapshot.todos
Session consumes the todo/write session event as a per-event side effect
(last write wins), rebuilds it on window replay/paging/resync, and exposes
snapshot.todos. TodoItem re-exported through the runtime surface.
2026-07-24 22:55:17 +08:00
Turtle
f0410d592d feat(web): permission presets and approval answering for the web UI
The web host now composes the sandboxed product path (sandbox-local +
sandbox-policy behind bash-sandbox/fs-sandbox, with user-approval and
permission on top); BootHostOptions.sandbox carries the deployment
defaults (workspace-write + ask).

createApiProxy owns the approval pending registry: a ctx.approval ask
becomes an answerable approval/requested mux frame with a stable rpcId,
replayed verbatim on every mux open until settled; respond routes by the
echoed rpcId, validates the ApprovalResponsePayload audit correlation,
and broadcasts approval/resolved; the ask's abort signal withdraws the
question as cancelled.

session.permissions / session.setPermission project ctx.permission into
a protocol-owned PermissionOption select; idle switches are held
last-write-wins and
flushed into the next prompted turn (the ACP bridge's anchoring
pattern). The shared hasOpenTurn fold moved to dsh-session,
deduplicating the private copies in user-approval, the ACP bridge, and
the proxy.

Client, per the designer draft: a pending approval takes over the
composer (ApprovalPanel replaces the InputBar — amber strip,
justification headline, paired command, one-shot refuse/allow, keyed by
rpcId so a queued second approval remounts live; the resolved frame
restores the composer); the sidebar session row shows an amber
waiting-approval dot that outranks the running ring (manager-tracked
approvalId set, idempotent under mux-open replays, cleared per
connection generation, lit for uninstantiated sessions too); the
permission selector is a composer bottom-row chip over an invisible
native select, with a presentation-only title-case transform
(workspace-write renders as Workspace Write; wire names untouched). Question placeholders stay in the message flow. The
connection fixture mirrors the host behavior for keyless browser
acceptance.
2026-07-24 19:15:04 +08:00
_Kerman
fb0ef82aa6 Merge remote-tracking branch 'origin/feat/send-unify' into xtr/agent-loop-message-machine
# Conflicts:
#	packages/client/runtime/src/client/sessions/fold-adapter.ts
2026-07-24 18:24:28 +08:00
fz
e90b3bc5a2 fix(web): make plan transitions admission-safe 2026-07-24 16:55:04 +08:00
07akioni
6fc92bbb16 fix: ci 2026-07-24 16:32:35 +08:00
_Kerman
6945a2c37d Merge remote-tracking branch 'origin/feat/send-unify' into xtr/agent-loop-message-machine 2026-07-24 16:31:49 +08:00
07akioni
6f5321cb37 feat: workspace select menu 2026-07-24 16:09:58 +08:00
fz
4cd4c11871 fix(web): deduplicate plan review rendering 2026-07-24 15:05:18 +08:00
Yichen Jiang
208a44a7ec feat(web): add session model selector 2026-07-24 14:55:54 +08:00
07akioni
aeb8b1f486 feat: implement new session behavior to clear selection and show empty state
- Added bilingual notes for the new session feature, detailing the transition to an empty state upon session creation.
- Updated `SessionsService` to include a `clear()` method that resets the current selection and persists the empty state.
- Enhanced the `EmptyState` component to reflect the new design, including workspace selection and input handling.
- Modified CSS styles for improved layout and visual consistency in the empty state.
- Updated tests to cover the new session clearing functionality and its effects on the UI.
2026-07-24 14:09:00 +08:00
_Kerman
5c7505b208 refactor(agent): remove message metadata channel 2026-07-24 14:05:33 +08:00
07akioni
a4b4a4c53d fix: type check 2026-07-24 13:36:27 +08:00
07akioni
3babb2cd42 feat(trajectory): implement trajectory step cell and layout with bilingual support
- Added TrajectoryCell, TrajectoryGroupHeader, and TrajectoryTurn components for rendering trajectory steps and groups.
- Introduced bilingual support with English and Chinese translations for trajectory notes.
- Updated conversation session models to include timestamps for various message types.
- Enhanced layout logic to handle expanded assistant blocks and tool results with duration metrics.
- Added CSS styles for new components to ensure proper display and alignment.
2026-07-24 13:33:35 +08:00
fz
9a69feeec0 feat(web): add plan mode controls 2026-07-24 12:55:23 +08:00
fz
bc63b5fe00 feat(web): project plan mode through host API 2026-07-24 12:09:04 +08:00
imccyu
a7699cdeb1 ci: coverage/knip 2026-07-24 02:09:43 +08:00
imccyu
76b25f6c65 pkg: fix dep 2026-07-24 02:09:42 +08:00
imccyu
e903a864f7 fix(gui): reconcile the rebase — ui-question joins the client roster
ui-question landed on master as a full dshClient plugin package (composer
question flow); it enters the flat roster, apps/cli deps/refs, and the
smoke graph. Restore the workspace-context and user-interaction host deps
the conflict resolution had dropped.
2026-07-24 02:09:42 +08:00
imccyu
c2e0c16d6a refactor(gui): one plugin-package shape — dshClient manifests, clientBundle preset, purity gate over all nine
Every client plugin package carries dshClient ({platform, inject,
immediately?}) and emits lib/client.js through the shared clientBundle
preset; exports["./client"] points at the bundle. The infrastructure
tier (connection, runtime, ui-theme, i18n, hmr) declares immediately: true
in its manifest — absent means lazy. The bundle purity gate covers all
nine packages: platform modules stay external, INLINE_SAFE wire layers
inline, any other cross-plugin value import is a build error. Migrations
that rule forced: scopeOf became a SessionsService method and
transportError moved into dsh-host-apiproxy's wire layer; the store
engine stays in runtime under a documented temporary exemption
(TODO(webload/store-rehome)).
2026-07-24 02:09:42 +08:00
Tianyi Cui
404da65595 Merge branch 'master' into worktree/web-session-titles
# Conflicts:
#	apps/web/tests/smoke-real.e2e.ts
#	packages/client/connection/tests/fixture.spec.ts
#	packages/host/runtime/README.md
#	packages/host/runtime/src/api-proxy.ts
2026-07-23 22:00:17 +08:00
Tianyi Cui
ea019beae9 Merge branch 'master' into worktree/web-session-titles 2026-07-23 20:51:17 +08:00
Tianyi Cui
d7c4822f95 Merge origin/master into worktree/web-session-titles
# Conflicts:
#	packages/client/connection/src/client/fixture.ts
2026-07-23 20:12:40 +08:00
imccyu
0f63666522 Merge branch 'worktree/web-carrier-chain' into worktree/web-ask-user-question 2026-07-23 20:09:11 +08:00
imccyu
3f6158f2c6 Merge branch 'master' into worktree/web-carrier-chain 2026-07-23 19:46:13 +08:00
Yichen Jiang
6f624c67c4 feat(web): render assistant Markdown 2026-07-23 19:18:05 +08:00
imccyu
34f0536cfe Merge branch 'worktree/web-carrier-chain' into worktree/web-ask-user-question 2026-07-23 18:56:20 +08:00
imccyu
2b06aa0102 Merge branch 'worktree/web-carrier-chain' into worktree/web-ask-user-question
Restack the ask-user domain layer onto the carrier-chain architecture
branch. Conflict policy: runtime and ui-conversation take the
carrier-chain side (master sessions shape, dual-kind PendingCard,
'internal' envelope shell tests); the 'cancelled' wire code and its
semantics tests stay in apiproxy + ui-question (domain layer); the
smoke fixture keeps the nine-bundle success pass with the resident
question round over the carrier-chain first-describe shape.
2026-07-23 18:50:30 +08:00