Commit Graph

1331 Commits

Author SHA1 Message Date
Yichen Jiang
f56c7d6638 Merge branch 'stack/agent-profiles-7-docs' into stack/agent-profiles-8-authoring 2026-08-07 01:01:51 +08:00
Yichen Jiang
2b7d50642c Merge branch 'stack/agent-profiles-2-configs' into stack/agent-profiles-3-wire 2026-08-07 01:01:49 +08:00
Jiaying Ding
67bd84b207 Merge branch 'master' into fix/update-explore-unknown-copy 2026-08-07 00:45:44 +08:00
Yichen Jiang
9eaa9d22a5 feat(tools): let one agent choose its tool presentation, and ship code
Code Mode was a deployment-wide field on the host `tools` row: a
deployment ran every session that way or none. The obvious product
shape — 代码模式 beside 标准/极简/创造 in the preset picker — had
nothing to hang on.

The registry itself cannot move into a preset; the agent loop's
scheduler, the api-proxy's presenters, and every tool plugin are its
consumers. So split the registry from its projection: `presentAs(mode)`
writes one cell on the calling agent's scope layer, exactly as
`restrict()` does, and the three reads that decided presentation take
that scope's mode instead of the service's. The config `mode` becomes
the default agents shadow rather than a process-wide fact.

Two consequences are load-bearing. `run_code` now enters a view only
for scopes whose own mode presents it — a native agent must not find it
dispatchable because another agent in the process does — and the
reserved name holds whatever the configured mode, since any agent may
select a code mode later.

`dsh-agent-tool-mode` is the row a preset carries to declare this. A
code mode waits for the host's `codeRuntime` rather than assuming it,
so a runtime-less deployment fails the preset at mount, naming the
row, instead of at the session's first request.

The shipped `code` preset is `standard` plus that row, ordered second.
2026-08-07 00:44:49 +08:00
Yichen Jiang
d247c50c6f fix(web): return every service a host row injects, and run the browser lane
The browser e2e lane had been failing wholesale since this stack moved the
agent plane into presets, and nothing caught it: 34 of 48 files. Two of the
causes are product defects, not test breakage.

`bashEnv` goes back to the host plane. `apps/cli/src/web.ts` injects it to
publish `DSH_WEB_URL`/`DSH_WEB_MODE`, so the earlier note that "nothing outside
the agent plane injects bashEnv" was simply wrong — behind a preset's `shell`
realm those variables reached no shell at all, and a `dsh web` agent could not
find the address of its own interface. This is the same criterion that returned
`subagents`: a host row that injects a service resolves before any session
exists and has no agent to key by, so the service is host-plane. `tool-bash`
consumes the host registry from inside the preset, which works because an
agent context chains to the host; only the reverse is invisible.

`tool-subagent-report` goes back with it. It is not a tool this agent calls: it
registers a continuable SETUP on the host `subagents` singleton, and that list
is not scope-aware. One copy per mounted preset meant every child was handed
`report` once per live session, so the second registration threw and a cold
subagent resume failed with `subagent-not-resumable` — a diagnostic three
layers removed from the cause.

The lane's own composition facts follow. Skill roots resolve inside a preset
now, a subtree include patches cannot reach, so the scaffold pins the roots'
documented environment fallback for its whole lifetime rather than for the boot
— presets mount per session. Without it the developer's real `~/.dsh/skills`
enters replay requests and goldens while CI sees none. The `apps/cli`
composition test pins `storage-json` for the same reason: unpinned it wrote,
and then read back, the developer's own `~/.dsh/storages/`.

Three tests now address through an agent what they used to read off the root
context, because that is where the thing lives: the tool catalog, the skill
registry, and the token meter. The seeded-history projection baseline asserts
the opposite of what it did — a detached session yields a preset-plane
projection only from a durable checkpoint written while it was live, and this
seed was written straight to persistence and never ran.

Goldens re-recorded for the hero's preset chip and the settings nav entry.
2026-08-07 00:42:25 +08:00
Yichen Jiang
2b8a0a8cff feat(web): choose the agent preset on the new-session screen
The composer seat spent nearly all its life disabled: a session's
composition is fixed once a turn has run. Move the choice to the
new-session screen beside the workspace picker, where it still works,
and let the session header report what a running session runs.

The hero pick is staged rather than applied — that screen precedes the
session it belongs to. It lands when a session becomes current and is
still blank, which covers both the session a workspace connect creates
and the blank one it reuses; riding `sessions.create` would miss the
second. It is spent on first use, matching the workspace picker.

Fix the durability the header field claimed but never had: `agentPreset`
was declared on `SessionHeader` and dropped by the JSONL header line, the
SQLite sessions row, the derived query index, and the cold list
projection, so every resumed session came back composed from nothing.

Add the web e2e lane that would have caught it — the one lane that mounts
the shipped roster, which needed `cordis:group` in the scaffold's Loader
builtins, as `mountRootInclude` already registers.
2026-08-07 00:41:50 +08:00
Yichen Jiang
3d68185480 feat(web): move the agent plane behind per-session presets
The Web overlay disables base's 32 agent-plane rows and mounts the preset
roster instead, so each session composes its own tools and prompt rather than
sharing one process-wide set. The TUI keeps base unchanged: it is single-session
and composing its agent process-wide is correct there.

`roots` is patched in by AppCLIEntry, like `distIndex`: the shipped presets sit
beside the composition that names them and the user's live under the Harness
home, neither of which a config author chooses.

A session's preset is fixed at creation. Naming a different one for an existing
identity is `agent-preset-conflict` rather than a switch, because that
session's history was produced under the first preset's tools. The guard sits
after `await creation`, beside the cwd check, so it covers every path that
yields a live agent — freshly created, adopted live, resumed, or recovered by
the concurrent-creation catch. A request naming no preset adopts the session as
it is, keeping reconnect and retry ordinary.

Two bugs the real-composition test caught, both invisible to unit tests:

`PresetTree` now refuses to write. The Loader persists a tree whose plugin
self-disposed, and tearing an agent down disposes its whole subtree — inherited,
that rewrote the shipped composition, truncating a 241-line preset to `[]` the
first time a session ended.

`dsh-tool-skill` compared against a lookup of its own name in the global layer,
so it threw inside any preset: `register()` files into the calling context's
scope. It now compares against the definition it registered, which is what the
identity check meant all along.

The `standard` catalog is asserted exactly, not spot-checked: a row that
registers into the wrong layer mounts cleanly and simply contributes nothing, so
an omission is this design's quietest failure. It matches the shipped TUI
catalog plus `glob`/`grep`, the pair that composition documents as
ripgrep-dependent.

Re-records `cordis-inspect-jsdoc`, whose rendered `SessionHeader` gains the
`agentPreset` field. `fs-glob-sampling` fails identically on pristine master
and is untouched here.

The browser e2e scaffold gains the roster fact AppCLIEntry supplies. `roots` is
resolved and patched in by the CLI entry, like `distIndex` on the webserver row,
and this lane boots the shipped tree without that entry — so it has to supply
the same fact or the roster resolves nothing and every session in the lane
composes an agent with no tools, no persona, and no token meter. Only the
shipped root: a developer's own `~/.dsh/.agent-presets` must not decide a golden. The
`cordis:group` builtin comes with it, exactly as `boot()` registers it, because
a preset resolving package names from its own directory cannot reach
`@cordisjs/plugin-group` by name.

The lane stays red through this layer and the next four for the reason stated
above — the api-proxy injects `subagents`, `workspace`, and `tools`, so
`api-gateway` cannot activate and the browser has no `/api` at all. It goes
green again in the layer that returns those registries to the host plane; this
change is what makes that layer's fix sufficient rather than partial.
2026-08-07 00:35:30 +08:00
Yichen Jiang
6b75bb0425 fix(web): say the API key format is wrong rather than naming the characters 2026-08-06 23:15:08 +08:00
Tianyi Cui
8f2168303b feat(web): add install metadata 2026-08-06 23:00:01 +08:00
Yichen Jiang
a89c26b611 test(web): pin the API key field refusal end to end 2026-08-06 22:42:56 +08:00
Yichen Jiang
fe31cd7609 Merge remote-tracking branch 'origin/master' into claude/unified-environment-credentials-c8841a
# Conflicts:
#	apps/cli/src/profile-boot.ts
#	apps/cli/src/web.ts
2026-08-06 22:34:46 +08:00
Yichen Jiang
fe8a88c96a Merge pull request #1803 from deepseek-harness/worktree/align-core-web-rl-prompt
fix(web): align core profile with RL prompt
2026-08-06 21:57:28 +08:00
Yichen Jiang
5e139ac64e Merge remote-tracking branch 'origin/master' into claude/unified-environment-credentials-c8841a
# Conflicts:
#	.agents/notes/implemented/feature/2026-07-20-dsh-cli-personal-config.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-20-dsh-cli-personal-config.md
#	.agents/notes/implemented/feature/2026-07-20-dsh-cli-personal-config.zh.md
#	apps/cli/config/base.cordis.yml
#	apps/cli/package.json
#	apps/cli/reference/README.i18n.yaml
#	apps/cli/reference/README.md
#	apps/cli/reference/README.zh.md
#	apps/cli/src/app-cli-entry.ts
#	apps/cli/src/args.ts
#	apps/cli/src/bin.ts
#	apps/cli/src/config.ts
#	apps/cli/src/dump-config.ts
#	apps/cli/src/headless.ts
#	apps/cli/src/web.ts
#	apps/cli/tests/args.spec.ts
#	apps/cli/tests/built-bin.e2e.ts
#	apps/cli/tests/headless-shutdown.e2e.ts
#	apps/cli/tsconfig.json
#	docs/user/guide/config.i18n.yaml
#	docs/user/guide/config.md
#	docs/user/guide/config.zh.md
#	examples/mcp-memory/README.i18n.yaml
#	examples/mcp-memory/README.md
#	examples/mcp-memory/README.zh.md
#	packages/bundle/web-app/cordis.patch.yml
#	packages/cordis/repository-plugin/README.i18n.yaml
#	packages/cordis/repository-plugin/README.md
#	packages/cordis/repository-plugin/README.zh.md
#	packages/credentials/credentials-local/README.i18n.yaml
#	packages/credentials/credentials-local/README.md
#	packages/credentials/credentials-local/README.zh.md
#	packages/ui/app-boot/README.i18n.yaml
#	packages/ui/app-boot/README.md
#	packages/ui/app-boot/README.zh.md
#	packages/ui/app-boot/src/index.ts
#	packages/ui/app-boot/tests/config-reload.spec.ts
#	packages/ui/app-boot/tests/user-patches.spec.ts
#	pnpm-lock.yaml
2026-08-06 21:34:45 +08:00
ZiyaZhang
4767285694 Merge remote-tracking branch 'upstream/master' into feat/web-workspace-file-links
# Conflicts:
#	apps/cli/package.json
#	pnpm-lock.yaml
2026-08-06 06:24:53 -07:00
imccyu
8d4164452a fix(ui): drop stale react-dom deps and address onboarding review
knip: ui-settings no longer imports react-dom (the portal moved into
OnboardingSurface), so the react-dom peer/dev dependencies and
@types/react-dom go away with the usage.

Review follow-ups: the Agent Note's Testing section now records the
held-join reload regression scenario this PR adds (both languages,
pairing re-recorded); the e2e hold gates EVERY settings.describe issued
before release instead of only the first, so a future boot-time join
consumer cannot silently collapse the widened window; the sampler's
persistence across later navigations is documented and the vacuity
wording softened to what the hold actually buys (timing independence).
2026-08-06 21:08:20 +08:00
imccyu
63b80956f2 fix(ui): move the onboarding takeover chrome into the step
The settings shell painted the onboarding overlay (opaque stage, mask,
#root inert) the moment a step was registered and not locally completed,
while every step still had to load its private join before deciding
whether to show — rendering null could not suppress the shell-owned
chrome. Every reload on the hero therefore flashed a full-screen opaque
layer (white in the light palette) for one settings/credential RPC
round-trip after the session list turned ready.

The chrome now belongs to the step: a new zero-cordis OnboardingSurface
primitive (ui-primitives) renders the body-portaled overlay/mask/stage
verbatim from the former SettingsRoot stylesheet and holds #root inert
for exactly its own lifetime. WelcomeNotice and DeepSeekOnboardingDialog
wrap only their visible branch in it, so their existing null branches
paint and block nothing by construction. SettingsRoot keeps the
coordinator unchanged but renders the elected step bare, and the
settings.onboarding contract now names the surface wrap as the
registrant's obligation.

The onboarding e2e gains a held-join reload scenario pinning that a
configured world never mounts the takeover chrome or inerts the app.
2026-08-06 20:44:31 +08:00
Yichen Jiang
266629f1c3 test(web): cover core profile request header 2026-08-06 20:41:19 +08:00
Yichen Jiang
c16cad7c03 Merge remote-tracking branch 'origin/master' into worktree/web-skill-tool-row
# Conflicts:
#	packages/host/apiproxy/README.i18n.yaml
2026-08-06 20:41:13 +08:00
Yichen Jiang
b5600e9376 Merge remote-tracking branch 'origin/master' into worktree/align-core-web-rl-prompt
# Conflicts:
#	apps/cli/reference/README.i18n.yaml
#	apps/cli/reference/README.md
#	apps/cli/reference/README.zh.md
#	apps/cli/src/app-cli-entry.ts
#	apps/cli/src/dump-config.ts
#	apps/cli/src/web.ts
#	apps/cli/tests/built-bin.e2e.ts
#	apps/cli/tests/web-prompt-context.spec.ts
#	apps/web/tests/scaffold.ts
2026-08-06 20:34:57 +08:00
Yichen Jiang
dd473870dd fix(web): persist theme preference in settings 2026-08-06 20:28:15 +08:00
Yichen Jiang
50c46be948 fix(cli): isolate Web runtime context from headless 2026-08-06 20:11:44 +08:00
Turtle
a51b88d2aa Merge remote-tracking branch 'origin/master' into feat/profile-plugin-management
# Conflicts:
#	apps/cli/src/headless.ts
#	docs/event-producer-consumer.md
#	packages/host/apiproxy/README.i18n.yaml
2026-08-06 20:03:22 +08:00
Yichen Jiang
0cf1ba7f87 fix(web): align core profile with RL prompt 2026-08-06 19:52:16 +08:00
creatixchu
59c1b9c5ac Merge master into fix/conversation-column-one-axis-scroll 2026-08-06 19:49:11 +08:00
creatixchu
7c338cc3b9 Merge remote-tracking branch 'origin/master' into worktree/turn-tail-actions 2026-08-06 19:47:08 +08:00
ZiyaZhang
3742214226 Merge remote-tracking branch 'upstream/master' into feat/web-workspace-file-links
# Conflicts:
#	apps/web/tsconfig.json
#	packages/client/connection/README.i18n.yaml
#	packages/client/connection/README.zh.md
#	packages/client/ui-conversation/README.i18n.yaml
#	packages/client/ui-conversation/src/client/chat/AssistantMarkdown.tsx
#	packages/client/ui-conversation/src/client/chat/ChatView.tsx
#	packages/client/ui-conversation/src/client/chat/ToolRow.module.css
#	packages/client/ui-conversation/src/client/chat/chat-flow.ts
#	packages/client/ui-conversation/tests/chat-view.spec.tsx
#	packages/host/apiproxy/src/native-path-opener.ts
#	tsconfig.host.json
2026-08-06 04:44:13 -07:00
Turtle
4d241d37e4 Merge pull request #1599 from deepseek-harness/codex/web-slash-fuzzy-search
feat(web): add fuzzy slash command discovery
2026-08-06 19:21:47 +08:00
Turtle
da732cad72 Merge remote-tracking branch 'origin/master' into task/command-feedback-master 2026-08-06 18:38:35 +08:00
Jiaying Ding
2e943a1643 Update details-session-lifecycle.e2e.ts 2026-08-06 18:31:44 +08:00
creatixchu
e116b34d08 Merge remote-tracking branch 'origin/master' into worktree/turn-tail-actions
# Conflicts:
#	packages/client/ui-conversation/README.i18n.yaml
2026-08-06 18:11:05 +08:00
Jiaying Ding
342229dc14 Update plan-active.expected.md 2026-08-06 18:02:23 +08:00
imccyu
f9f72e2f09 fix(ui): preserve Hero tree when selecting a Workspace 2026-08-06 18:01:11 +08:00
Jiaying Ding
c22337a71e Update hero.expected.md 2026-08-06 17:59:42 +08:00
Jiaying Ding
9a9bfbf306 Update lifecycle-chrome.e2e.ts 2026-08-06 17:51:23 +08:00
creatixchu
84a6bae1c7 fix(web): drop the branch action from user and steering bubbles
The branch control on user and consumed-steering bubbles could enable
only when a completed turn ended with no node after the message at all,
so readers saw a permanently unavailable control whose tooltip promised
a state it could not reach. An enabled one would mislead anyway: a fork
at a message seq cuts at the containing turn/end and takes the answer
along, the opposite of the branch-to-re-ask reading a control on one's
own bubble suggests.

MessageItem loses its fork props, PendingSteeringBubble loses the
showBranch special case, and messageBranchSeqs narrows to
assistantBranchSeqs: only a completed turn's transcript tail that is
the turn's own content-text assistant may fork. A steered turn keeps
its fork point under the settled answer, because fork is a log-prefix
cut and the steer is model-visible history the child inherits.

Web aria goldens drop the user-bubble disabled-branch row and its
hidden explanation text; the nested-subagent golden also loses the one
enabled user-tail fork handle, a loss the decision note accepts.
2026-08-06 17:46:18 +08:00
Jiaying Ding
9bb0aecb92 Update hmr-live.e2e.ts 2026-08-06 17:41:54 +08:00
Jiaying Ding
6515988ec7 Update startup-auto-selection.e2e.ts 2026-08-06 17:40:48 +08:00
Turtle
ef30572e63 fix: retire leftovers of the removed $DSH_HOME/config.yaml personal overlay
The profile rework left references to the old entry modes behind. Renames
the user patch-layer API and its spec file (watchPersonalPatches ->
watchUserPatches, personal-config.spec.ts -> user-patches.spec.ts) and
retargets the prose that still named `config.yaml`, `--config`, raw-config
mode, and surface overlays: repository-plugin and mcp-memory READMEs, the
credentials-local anchor into app-boot, vendor manifest items 12-13, the
vendored include/hmr comments, and install.sh.

Restores the boot-failure guard the rework dropped with raw mode: the
built-bin case now boots `--profile web --patch <invalid>` and asserts the
settled diagnostic and exit 1, so the HMR initial-scan deadlock stays
covered; its orphaned raw fixture is renamed and the unused one deleted.
The superseded personal-config Agent Note and its superseding profile note
are now cross-linked.
2026-08-06 17:28:58 +08:00
Turtle
62d0f26fd6 refactor(cli)!: namespace the profile and bundle manifests under dsh.profile and dsh.bundle
A profile manifest and a bundle manifest are different kinds and shared one
flat `dsh` section: `dsh.plugins` listed bundles (not plugins) and `dsh.patch`
declared a bundle's layer. Each kind now names its role — a bundle declares
`dsh.bundle.patch`, a profile declares `dsh.profile.bundles` — so a
package.json states which role it plays and the list name matches its contents.

`DEFAULT_PROFILE_PLUGINS` becomes `DEFAULT_PROFILE_BUNDLES`, and
`DshManifestSection` splits into `DshBundleManifest`/`DshProfileManifest`.
Pre-release: no compatibility shim; turtle-ui moved with it (bd5ff10).
2026-08-06 17:28:30 +08:00
Yichen Jiang
66b136e6e3 Merge remote-tracking branch 'origin/master' into worktree/provider-credential-lifecycle
# Conflicts:
#	packages/client/ui-models/README.i18n.yaml
#	packages/client/ui-models/README.md
#	packages/client/ui-models/README.zh.md
#	packages/client/ui-models/src/client/ModelsSection.tsx
#	packages/client/ui-models/src/client/ProviderEditor.tsx
2026-08-06 16:54:33 +08:00
Yichen Jiang
bce4a038c9 Merge remote-tracking branch 'origin/master' into claude/unified-environment-credentials-c8841a
# Conflicts:
#	docs/config-catalog.md
#	packages/llm/llm-pi-ai/src/config.ts
#	packages/llm/llm-pi-ai/src/index.ts
#	packages/llm/llm-pi-ai/tests/sdk-options.spec.ts
2026-08-06 16:52:19 +08:00
Yichen Jiang
f2050bfd1e fix(web): surface provider credential status 2026-08-06 16:44:04 +08:00
creatixchu
6902b51fea fix(web): address review on the turn-tail actions gate
Correct the Agent Note's consequence: a running turn withholds the footer
below its own trigger bubble, while every earlier completed turn keeps its
seat — which the package test already asserts.

Give the running-phase barrier an explicit budget: it is armed before the
park and awaited after the stop click, so the 30s replay default left no
headroom for the marker poll, the UI polls, and two aria captures.

Number the running-turn test's boundary seqs like the log does, with each
turn/end strictly after its own nodes.
2026-08-06 16:42:41 +08:00
creatixchu
53e210348d fix(web): grant turn-tail IconActions only after the turn ends
`assistantActionsSeqs` picked the last content-text assistant of each turn
from the finalized transcript alone. That quantity is stable only once the
turn closes: while a turn is still producing steps, the narration written
before a tool call is the last content assistant so far, so copy, branch,
and the clock appeared under an intermediate sentence for as long as the
tool ran and then moved down to the next step's text.

Pass `ConversationSnapshot.turnEnds` into the derivation and grant the row
only inside a turn that has a durable `turn/end`. This is the same
completion fact the branch control and the `Ran for` label already read, so
the three parts of one row now agree; mid-turn narration owns nothing, and
the seat appears once under the settled answer.

`hasContentText` moves to chat-flow.ts so the ownership gate and
AssistantMarkdown's mount gate cannot drift apart.

apps/web/tests/turn-tail-actions.e2e.ts pins both states through the
assembled application: a hang sidecar on the second model call parks a turn
whose first step narrated before calling bash, and the two goldens hold the
parked flow and the flow after stopping.
2026-08-06 16:42:41 +08:00
Yichen Jiang
690f7ae035 Merge remote-tracking branch 'origin/master' into worktree/web-skill-tool-row 2026-08-06 16:41:57 +08:00
creatixchu
12e5fe0330 Merge master into fix/conversation-column-one-axis-scroll 2026-08-06 16:39:59 +08:00
imccyu
90f738a4c7 build(web): react-free vendor list for the incremental markdown pipeline, npmPackageOf scoped guard, chunk audit script 2026-08-06 16:38:25 +08:00
imccyu
021074c0ee build(web): split the shell dist into index and vendor chunks with langs/ and fonts/ dirs 2026-08-06 16:38:25 +08:00
Turtle
4f595311f7 test: include feedback in Web command catalog snapshot 2026-08-06 16:32:46 +08:00
Yichen Jiang
8eebf7dd40 test(web): pin the remaining markdown fixture's event times
Master stabilized two of the three hand-built markdown fixtures by spacing
their event times, so the stats line's LLM segment stops depending on how fast
the replay ran. `markdown-images` was left on the old shape and kept failing
for exactly that reason — a different test each run, always the same one-line
difference.

Pin it the same way and record the segment its golden now always shows. This
supersedes the normalizer that dropped those segments outright, reverted here:
pinning the fixture keeps a real part of the page in the goldens instead of
hiding it from every one of them, and master's two goldens already record it.
2026-08-06 16:24:20 +08:00