Files
deepseek-harness/examples/desktop/docs/default-profile-real-probe
ZiyaZhang e8f5c0b51b feat(desktop): DSH Electron desktop shell — harness internals visualized
Minimal Electron shell over the DSH JSON-RPC runtime — a first-look at
what a ChatGPT.app-style host on top of the DeepSeek Harness looks
like, with the harness's normally-invisible internals (trace timeline,
context surface, subagent tree, compaction, plugin registry, rubrics)
brought forward as first-class UI surfaces so plugin authors and
researchers can see what the agent is actually doing.

Runs against three keyless-to-live profiles (stdio-echo works on
master out of the box; daemon-echo / daemon-vibe-echo activate once
the daemon-demo lands; stdio-deepseek and daemon-vibe hit the real
DeepSeek API when you supply a key). HARNESS_DEV auto-resolves to the
in-repo runtime when this shell ships under examples/desktop/, so a
fresh clone launches without config; env DSH_DEV_ROOT overrides for
custom layouts, and a sibling deepseek-harness-dev/ checkout is the
original dev workflow.

Cold-clone gate (P0 fixes for first-time-clone usability):
- HARNESS_DEV: 3-candidate resolver (env → walk-up in-repo marker →
  sibling), unit-tested via mock fs so ordering is locked without
  needing either real layout on disk.
- config yml leaves rewritten at assemble time so the sibling-clone
  paths (../../deepseek-harness-dev/examples/echo-agent/…) become
  the in-repo paths (../../echo-agent/…) in the released tree —
  source yml stays usable for local dev, released tree ships a
  working shape.
- pnpm-workspace.yaml allowBuilds.electron = true (was placeholder).
- missing-key card in stdio-deepseek offers a one-click switch to
  stdio-echo (the keyless profile that works on master) rather than
  daemon-echo (blocked on the not-yet-shipped daemon-demo).
- assemble-oss-release.sh rewrites the source-side breadcrumb name
  'dsh-desktop-demo' → 'dsh-desktop' for the released package.json.

FOUC guard on the onboarding gate (41fc5df carried) keeps the
first-launch splash from flashing before the runtime probe finishes.

Test suite (1634 tests in source, 3990 in the runtime repo) covers
resolver ordering, renderer classifiers, trace timeline shape,
compaction diff rendering, rubric parity, and the missing-key
onboarding paths.
2026-07-18 12:59:34 -07:00
..

default-profile-real probe (2026-07-18)

Isolated real-machine verification for fix/default-profile-real (default profile → stdio-deepseek + missing-key guided-switch card).

Isolation (mandatory)

--user-data-dir=/tmp/dsh-probe-default-real/user-data (Electron caches + Local Storage) AND DSH_DESKTOP_HOME=/tmp/dsh-probe-default-real/dsh-home (shell overlay + config.json + .onboarded sentinel). Team-lead flagged that a prior probe wrote through to the user's real ~/.dsh-desktop/user- overlay.cordis.yml because DSH_DESKTOP_HOME wasn't isolated; this probe respects both.

Driver: /tmp/dsh-probe-default-real/run.sh {with-key|no-key} [port].

Scenarios

01 · no-key boot (01-no-key-boot.png)

Boots stdio-deepseek with DEEPSEEK_API_KEY unset. Confirms:

  • Bottom-right chip: stdio-deepseek · deepseek-v4-flash (NEW DEFAULT correctly landed — was daemon-echo · mock-echo before this change)
  • Composer model chip: deepseek-v4-flash (matches profile default)
  • Status bar: crashed (expected — the deepseek runtime dies during plugin load because this dev-clone snapshot has a workspaceContext schema drift; NOT the api-key error we designed against)
  • Banner: generic "Runtime warning" — the raw message reaching the classifier is runtime not writable (from transport.js:53 write() throws when stdin isn't writable), which correctly falls through to the generic bucket. My missing-api-key regex would ONLY match if the deepseek plugin actually got to throw its api-key error, which requires the config schema to pass first.

02 · guided-switch card (synthetic inject, 02-guided-card-injected.png)

Fires showRuntimeErrorBanner('llm-deepseek: an API key is required (Config.apiKey or $DEEPSEEK_API_KEY)') via the __dshRenderer test seam so we can see the classifier + banner logic end-to-end without needing the real llm-deepseek error to surface. Confirms:

  • Banner title: "! DEEPSEEK_API_KEY needed for real-model profile"
  • Hint: full two-option copy (set env in .env/shell, or try keyless demo)
  • Switch button: "Switch to keyless demo (daemon-echo)" (ghost small, under hint, wired to window.dsh.startRuntime('daemon-echo'))
  • Layout: amber-tinted banner sits above the welcome cards, NO red wall, full-width row (respects density spec)

03 · with-key boot (03-with-key-boot.png)

Boots stdio-deepseek with the dev-clone .env key loaded. Same shape as #01 in this environment because the config schema drift dies before the key check — the WITH-key scenario would surface status=ready + no banner only after the dev clone is bumped past the workspaceContext requirement. Documenting for reproducibility.

Known limits (dev-clone drift)

deepseek-harness-dev currently requires workspaceContext in the agent-spine-demo entry (packages/examples/agent-spine-demo/src/index.ts:94). The demo repo's config/deepseek-jsonrpc.yml predates that requirement, so the runtime dies at config validation before either the key check or the actual daemon handshake. This is orthogonal to the default-profile change and does NOT block:

  • The default profile stdio-deepseek IS observably active (screenshots and CDP eval of #profile.value confirm)
  • The guided-switch card renders correctly when the api-key error DOES reach the classifier (screenshot #02 proves this via the test seam)
  • The static test suite (test/default-profile-real.test.js + test/renderer-runtime-banner-classify.test.js) locks every step of the wire path (currentProfileName, cfg.profile persistence, stderr accumulator, classification bucket, banner switch button)

Follow-up

  • Dev-clone bump: separate ticket. When agent-spine-demo becomes optional or the yml gains workspaceContext, re-run this probe in full to see the api-key error surface organically. Current 1554 test suite locks the code paths that would fire when it does.
  • README quick-start — team-lead owns this batch, keeping just the minimum quote-of-fact edits to README in this commit (default is stdio-deepseek, keyless demo callout).