Commit Graph
59 Commits
Author SHA1 Message Date
Turtle d2270eefcd fix(cli): align personal overlay semantics 2026-07-29 23:36:58 +08:00
Turtle 3d3a261793 docs(cli): remove stale composition references 2026-07-29 21:59:44 +08:00
Turtle dfca95e93f fix(tui): remove disposable query index on exit 2026-07-29 21:51:22 +08:00
Turtle ff126751d8 refactor(cli): keep migrate out of scope 2026-07-29 21:41:51 +08:00
Turtle d8e4fd3b75 fix(cli): align meta invocation contract 2026-07-29 21:39:38 +08:00
Turtle 984830c940 fix(tui): isolate each process query index 2026-07-29 21:15:48 +08:00
Turtle d44fce8a39 fix(cli): keep meta as a fresh-session command 2026-07-29 21:15:48 +08:00
Turtle 857a4941be fix(cli): restore shipped surface capabilities 2026-07-29 21:15:48 +08:00
Turtle 030b044350 fix(cli): reject leaked config replacement flags 2026-07-29 21:15:48 +08:00
Turtle c1324ee896 fix(cli): preserve overlays without session registration 2026-07-29 21:15:42 +08:00
Turtle 8f2f6ef0ac refactor(cli): exclude live-session registry surface 2026-07-29 21:15:42 +08:00
Turtle f290a8b851 refactor(cli)!: one shared base config with per-surface overlays
`dsh` shipped two config trees that were 43 rows the same: apps/cli/cordis.yml
composed web as 74 flat rows, while the TUI booted examples/tui-agent/cordis.yml
whose single `@deepseek-ai/dsh-tui-demo` row mounted twelve plugins behind a
twenty-key pass-through Config. Neither file was what its location claimed —
apps/cli hardcoded the "example" as the product default and the "demo" bundle
was the application — and every capability change had to be made twice.

- apps/cli/base.cordis.yml holds the 43 shared rows; tui.cordis.yml and
  web.cordis.yml are patch lists stating only what differs per surface
- overlays apply as SIBLING patch lists at one include level, because include
  patches never cross an include boundary. Precedence: base < surface <
  (--config | personal ~/.dsh/config.yaml) < launcher flag/profile patches
- `--config` now applies an overlay INSTEAD OF the personal one, so a demo or
  test tree never inherits the user's route; new `--config-replace` boots a file
  as the entire tree (the old `--config` behaviour). Both survive /resume
- vendor/include: index each `insert`ed row as it is added so a later patch can
  configure or disable it. Upstream built the id index once before the patch
  loop, leaving every surface-only row — the whole TUI front door — silently
  unpatchable from user config. Logged as local modification 8
- session identity moves to dsh-agent-loop's CONFIGURED_AGENT_IDENTITIES_KEY;
  dsh-tui's MAIN_SESSION_ID_KEY is deleted (only the bundle read it)
- delete examples/tui-agent, examples/cordis-agent, packages/examples/tui-demo;
  TUI tests → apps/cli/tests, cordis e2e → packages/cordis/tool-cordis/tests,
  examples/code-mode survives as an overlay leaf
- `dsh web` gains --config, threaded into AppCLIEntry as an extra overlay

Three latent defects surfaced and are fixed here: the TUI captured the optional
sessionQuery service once at construction and could permanently disable /resume
when it won the mount race; the session-store root silently reverted to a
project-local ./.sessions; --config-replace was dropped by the resume handoff.

Verified by booting each tree through the real Loader (TUI 55 entries, web 75,
zero unsettled) rather than reading YAML. All eight terminal snapshots replay
byte-identically; 14/14 PTY smoke, 112/112 snapshots, 25/25 doc-sync, hygiene
and lint clean.
2026-07-29 21:15:42 +08:00
Turtle e7c0a5b794 Merge origin/master: web permission sandbox, default pi-ai providers 2026-07-29 21:15:34 +08:00
kingwl 2ca6f54c9e Merge remote-tracking branch 'origin/master' into xtr/dsh-source-launch-tsx-esm
# Conflicts:
#	apps/cli/README.i18n.yaml
2026-07-29 13:39:57 +08:00
kingwl aebf9c863b feat(cli): launch dsh source through the tsx ESM hook
Node 26.0.0 removed --experimental-transform-types, so the native
source-launch chain cannot start anywhere on that line, and strip-only
mode rejects the vendored syntax (parameter properties, decorators,
runtime enums/namespaces). Switch bin/dsh, the root dsh/demo:tui/
demo:web scripts, and the Code Mode TUI overlay to node --import
tsx/esm: one launch vector across the whole engines range, ~0.4s faster
than the full tsx default (the CJS hook stays off; the graph is
ESM-only).

Delete scripts/tspath-loader.ts and apps/cli/src/tsconfig-paths-loader.ts:
tsx owns both transformation and tsconfig paths projection. Add
dsh-source-launch-smoke to the node-compat gates so the 22.19/26 matrix
executes the real launch vector; no CI job did, which is how the Node 26
breakage shipped silently.

Supersedes the native-TypeScript-source-launch Agent Note (new note
records the profiling evidence and rejected alternatives).
2026-07-29 13:15:24 +08:00
imccyu fa64ad39cb Merge branch 'master' into doc/host-client-group-readmes 2026-07-29 10:42:00 +08:00
Turtle c7e6cb5753 fix(tui): complete launcher integration and rationale 2026-07-29 10:25:07 +08:00
creatixchu 51b70f5864 Merge remote-tracking branch 'origin/master' into doc/host-client-group-readmes
# Conflicts:
#	apps/cli/README.i18n.yaml
2026-07-29 01:08:17 +08:00
imccyu 431c2180c1 fix(cli): harden native source resolution 2026-07-28 23:42:54 +08:00
imccyu db3b12a0f7 feat: launch dsh source with native TypeScript 2026-07-28 23:06:27 +08:00
creatixchu 012b5eb466 fix(cli): stop exporting the internal all-interfaces bind literal
knip (unused exports) flags ALL_INTERFACES_HOST: both consumers live in
apps/cli source, so the constant needs no export surface.
2026-07-28 21:54:02 +08:00
creatixchu 302dfca4d5 Merge remote-tracking branch 'origin/master' into doc/host-client-group-readmes
# Conflicts:
#	packages/README.i18n.yaml
#	packages/README.md
#	packages/README.zh.md
#	packages/client/connection/src/index.ts
#	packages/client/connection/src/native-dialog-request.ts
#	packages/client/connection/tests/node-half.spec.ts
#	packages/host/apiproxy/README.i18n.yaml
2026-07-28 21:01:20 +08:00
creatixchu f43cfb2406 fix(cli): sample LAN addresses once — trust and the printed LAN URL share the snapshot
web.ts re-sampled interfaces after boot, so an address change during
entry.run() could advertise a LAN URL absent from the trustedHosts snapshot
composePatches captured, answering 403 on arrival. resolveLanTrust now
returns the single sample and AppCLIEntry exposes it for display.
2026-07-28 17:47:56 +08:00
creatixchu 01eea07bab fix(connection): keep LAN serving working under the /api browser-trust fence
Markerless requests pass on any Host (a non-browser sender is the principal
and forges headers anyway); browser Host matching gains port-less entries and
WHATWG normalization; dsh derives LAN IP-literal authorities for an
all-interfaces bind and web grows --trusted-host for named ones.
2026-07-28 15:40:02 +08:00
_Kerman fbf87e660c refactor: identify and freeze messages at creation 2026-07-28 13:55:59 +08:00
Turtle 2fda7c1da5 feat(cli): default session store to global ~/.dsh/sessions 2026-07-27 19:08:26 +08:00
Turtle 4c5f92e0fd feat(tui): personal TUI rework, integrating upstream model reasoning-effort selection
Consolidates the personal dsh-tui customizations (module split into
components/session/extension, prompt template + running-glyph indicator,
copyable transcript, tool-card headers, timing placement, XML tool output,
status/footer rework) and ports upstream's model reasoning-effort selector
(Shift+Tab effort cycling, effort-aware /model, footer, and /status) onto
the personal module layout.
2026-07-27 18:55:13 +08:00
Turtle e996aabf47 Merge branch 'master' into worktree/dsh-arg-parser
Integrate the Commander adapter with master's `dsh web --workspace-root`
(workspace-aware session flow).

- args.ts: add `--workspace-root <path>` to the web subcommand; WebInvocation
  carries workspaceRoot.
- web.ts: keep the adapter-parsed signature, take (host, port, dev,
  workspaceRoot) and pass workspaceRoot through to AppCLIEntry (drop master's
  re-added parseArgs and CLI host/port validation — the schema owns those).
- bin.ts forwards invocation.workspaceRoot; args.spec + the Agent Note pair note
  the flag.
2026-07-25 18:05:39 +08:00
Turtle 2243023575 Merge branch 'master' into worktree/dsh-arg-parser
Integrate the Commander adapter with master's headless rework (dsh -p now boots
through AppCLIEntry — the same cordis.yml composition as dsh web, web-observable
while it runs — via toFetchHandler(ctx.apiProxy)).

- headless.ts: keep master's AppCLIEntry-based body but take the adapter's
  pre-parsed `task` (drop the re-added parseArgs). Old startHost path and the
  now-deleted packages/host/runtime dependency are gone.
- remove the stale packages/host/runtime dir left on disk by master's deletion
  (mirrors the earlier packages/ui/acp cleanup).
2026-07-25 17:48:21 +08:00
imccyu 9eb9c70a8a feat(web): add workspace-aware session flow 2026-07-25 17:45:26 +08:00
Turtle 5a06b9e926 fix(cli): reject default-surface flags leaked onto the web subcommand
ds-review-bot: `dsh web -p task`, `dsh web --resume s`, and `dsh --config c.yml
web` reached the web action with those values in program.opts() but the action
ignored them and served — silently dropping mode-specific inputs. The web
action now reads the parent opts and fails loud (exit 1) on a leaked
--config/-p/--resume, matching the root mode's mixing guard. Covered in
args.spec.ts.

Also (ds-review-bot): tui-demo/README documented the removed `dsh
[path-to-cordis.yml]` positional form; corrected to bare `dsh` / `dsh --config
<path>`. Agent Note + Chinese pair note the web-leak guard.
2026-07-25 17:24:39 +08:00
Turtle 9f6dbde7f6 refactor(cli): let the webserver schema own web --host/--port validation
The adapter no longer validates --host/--port or declares the allowed set:
LOOPBACK_HOST/ALL_INTERFACES_HOST leave args.ts. --host/--port are now
unvalidated pass-through overrides — the adapter only Number-coerces the port
string (the dsh-host-webserver schema wants a number). That schema
(host a 127.0.0.1/0.0.0.0 literal union, port a natural <= 65535) is the single
source of both the default (the shipped cordis.yml webserver row) and validity;
AppCLIEntry patches an explicit flag into that row, so a bad host/port fails
loud at the schema on boot (verified: `dsh web --host 9.9.9.9` and `--port abc`
both exit 1 with the schema's ValidationError).

web.ts keeps two display-only literals (the printed loopback URL, the
all-interfaces LAN-detection check), commented as mirrors of the schema, not a
source of truth. Agent Note + Chinese pair and README updated; the args spec
drops the host/port exit-code cases (now the schema's job, covered by the web
smoke on boot).
2026-07-25 16:19:02 +08:00
Turtle 6a8049879e docs(cli): trim bin.ts module comment to the non-obvious contract
Review (turtle1999): the opening narrated control flow. Drop the argv-parse/
switch narration; keep only the two non-obvious facts (per-mode dynamic imports,
and that the adapter exits so only a valid mode reaches the switch).
2026-07-25 15:50:10 +08:00
Turtle fca2dda37d refactor(cli): unify the arg grammar — one program, --config flag, real web subcommand
Drop the bare `dsh <config>` positional in favor of a `--config <path>` flag.
Without a root positional, `web` can be a real Commander subcommand in one
program instead of the reserved-first-token dispatch to a second parser, so
`dsh --help` lists every mode natively (no hand-pasted command text) and the
second parser + reserved-token machinery are gone.

Grammar:
  dsh                       TUI (shipped tree + ~/.dsh overlay)
  dsh --config <path>       TUI, alternate tree (demos/tests only)
  dsh --resume <id>         TUI, resume a session
  dsh -p "task"             headless one-shot
  dsh web [--host --port --dev]

`dsh` is the product front door with no positional; `--config` exists only so
demo:cordis, demo:code-mode, and the keyless PTY smokes can point the shipped
bin at an example tree. Those three sites and the /resume re-exec argv move to
`--config <path>`. The `-p` + `--config`/`--resume` mode-mixing guard and the
cordis.yml-owns-host/port-default fix are preserved.

Agent Note + Chinese pair, README, tui.ts docs updated. All 13 PTY smokes
(including code-mode via --config and the exec-replace resume handoff) green.
2026-07-25 15:47:55 +08:00
Turtle 91d86f9b21 fix(cli): let cordis.yml own the web host/port default (single source)
The merge's "always pass adapter-resolved host/port to AppCLIEntry" made the
adapter's 127.0.0.1/3080 shadow apps/cli/cordis.yml's webserver row — editing
the yml port would have had no effect, a duplicated default.

The adapter now assigns no host/port default: an absent --host/--port leaves the
field undefined (WebInvocation.host?/port?), runWeb forwards each to AppCLIEntry
only when present, and AppCLIEntry patches the webserver row only for an
explicit flag. cordis.yml is the single source of the host/port default; the
adapter still validates a flag when given. Removes the now-unused
DEFAULT_WEB_PORT; LOOPBACK_HOST/ALL_INTERFACES_HOST stay as the allowed-value
vocabulary (validation + the printed URL/LAN line).
2026-07-25 15:03:17 +08:00
imccyu 4a27da44cf test(web): real-composition webserver spec
Boots a test-only cordis.yml through the real Loader and asserts the route
service's behavior surface: exact/longest-prefix matching, tapIndex
transform order and unsubscription, traversal 403, non-GET 405, SPA-200
fallback, malformed-request 400 without process exit, duplicate-pattern
throw, dispose closing held connections with register/disposer symmetry,
and a listen-failure fail-loud case (EADDRINUSE -> FAILED fiber + late
rejection). Replaces the retired factory-era specs.
2026-07-25 14:40:45 +08:00
Turtle 2dfd8635e8 Merge branch 'master' into worktree/dsh-arg-parser
Integrate the Commander argument adapter and dsh-front-door work with master's
config-tree `dsh web` (#601: AppCLIEntry + apps/cli/cordis.yml) and the
packages/ui/acp → packages/acp/acp relocation.

- web.ts: keep master's AppCLIEntry-based boot, but take the adapter's parsed
  (host, port, dev) instead of an internal parseArgs. The adapter's host/port
  defaults (127.0.0.1/3080) match cordis.yml, so always passing them is
  behavior-equivalent to master's "undefined keeps the yml default".
- apps/cli/package.json: master's expanded config-tree dep set + commander.
- retire-readline Agent Note: point the TUI refusal proof at
  apps/cli/tests/built-bin.e2e.ts (both languages), re-record the pair.
- READMEs reconciled (demo-bin removal + master's ACP/channel rewording).
2026-07-25 14:37:57 +08:00
Turtle 007e8fd92f refactor(cli): bail early in the arg adapter instead of returning errors as data
Address review and cut ceremony: the adapter no longer models help/version/
errors as DshInvocation members. Commander owns those under exitOverride — it
prints usage or the diagnostic and one try/catch in parseDshArgs turns the
thrown CommanderError into process.exit with the intended code. bin.ts drops its
help/version/error cases; the union is the three real modes.

Domain checks bail via command.error(print + exit 1): --prompt rejects an empty
task or a stray config/--resume, empty --resume= fails loud, and --host/--port
are validated. A repeated --resume or a flag captured as a value is Commander's
standard behavior, left alone (a bad id fails loud downstream). dsh --help
discloses web via addHelpText. Net: args.ts 185 -> 112 lines.

Also fixes review nits: built-bin e2e resolves on `close`; the /resume handoff
uses `dsh --resume=<id> -- <config>` so a config named `web` stays a positional;
and stale prose (cordis.yml comment, app-boot module doc + duplicate JSDoc,
ui/README, two feature notes, an agent-loop test name) tracks the shipped state.
Removes tui-demo's now-dead plugin-include dep and vendor/loader + app-boot
tsconfig references.
2026-07-25 14:15:25 +08:00
Turtle 0901140b3f test(cli): cover the dsh built-bin non-TTY refusal
Removing the dsh-tui-demo bin dropped the only test of the TUI's piped-launch
refusal. Add apps/cli/tests/built-bin.e2e.ts (apps/*/tests added to the e2e
vitest include) running the built lib/bin.js under plain Node with piped stdio,
and point the refusal message at `dsh -p "task"` for automation.
2026-07-25 13:01:45 +08:00
Turtle 870fb1cafa refactor(cli): make dsh the sole terminal front door, drop RESUME_SESSION_ID
Remove the redundant dsh-tui-demo bin and the RESUME_SESSION_ID environment
variable, leaving dsh as the one terminal entrypoint.

The dsh-tui-demo package was a plugin (the TUI app bundle mounted by dsh's
config) plus a bin that booted a leaf cordis.yml — the same job `dsh [config]`
does. The bin, its ./bin export, its built-bin.e2e.ts, the tsdown bin entry,
and the now-unused dsh-app-boot dependency are removed; the package keeps its
plugin and invariant. demo:cordis, demo:code-mode, and the tui-agent and
cordis-agent keyless PTY smokes now launch through apps/cli/src/bin.ts with the
config as the positional argument. cli-demo/acp-demo/jsonrpc-demo keep their
bins (distinct surfaces).

RESUME_SESSION_ID was the only bridge from --resume into the shipped config;
--resume now provides the id on the boot context via ctx.provide(
RESUME_SESSION_ID_KEY, id), and the four configs read it as a bare identifier
through a quoted typeof-guarded !!js expression. The TUI resumeCommand fixtures
and docs move to `dsh --resume {session}`.

Agent Note and its Chinese pair updated; config-catalog regenerated.
2026-07-25 12:43:59 +08:00
Turtle 6cd139a25b Merge branch 'master' into worktree/dsh-arg-parser
Integrate the Commander argument adapter with master's safe session-resume
feature and dsh web --dev flag.

- args.ts: add --dev to the web parser.
- tui.ts: keep master's process.execve in-place resume handoff, but take the
  adapter's parsed (config, resume); inject the resume id through boot's
  prepare(ctx) hook via ctx.provide(RESUME_SESSION_ID_KEY, id) instead of the
  RESUME_SESSION_ID env var; rebuild the re-exec argv as `dsh --resume <id>`.
- app-boot: drop master's replaceResumeArg (no longer needed) alongside the
  already-removed parseResumeArg; add RESUME_SESSION_ID_KEY.
- the four tui-agent/cordis configs read the ctx-provided resumeSessionId via a
  typeof-guarded !!js expression, so resume needs no env var.
- web.ts: keep master's client roster and --dev watch, take parsed host/port/dev.
2026-07-25 12:04:37 +08:00
imccyu 2e27b8aeef chore(web): gate repairs for the config-tree boot round
Lint (bridge JSDoc params, service-class export shape, async invariant
listener form), regenerated doc catalogs/graphs with role classifications
for httpServer and clientModuleHost, catalog type-link exemptions for the
route/graph contracts, knip alignment (apps/cli composes via cordis.yml so
its yml-named deps are runtime edges knip cannot see; webserver's deleted
test dir), the zh side of the loading-model note brought along with its
pairing records, and coverage exclusions for the new web-transport halves
under the GUI test-lane TODO (real-composition harnesses land with that
lane).
2026-07-25 10:38:54 +08:00
imccyu 5466a81474 feat(web): boot dsh web from a config tree via AppCLIEntry
apps/cli/cordis.yml holds the whole composition flat — the host runtime
rows, the api-gateway row, the webserver row, and the ten dshClient rows.
AppCLIEntry is the pre-cordis glue: layered env (ambient > cwd .env >
$DSH_HOME/.env, fixing DSH_HOME=... dsh web not finding its key), patch
composition from the three non-yml sources (profile json through the static
PROFILE_MAPPINGS table, CLI flags, the resolved frontend distIndex), the
Loader include boot (--dev appends the hmr row before the settle), and the
fail-loud triple (assertEntriesLoaded + installFailLoud + an all-ACTIVE
sweep for PENDING fibers). web.ts shrinks to argv parsing + the URL line.
2026-07-25 10:25:02 +08:00
Turtle ee5132c1e1 refactor(cli): dispatch web as a reserved token, drop parse machinery
Simplify the Commander adapter now that behavior can change: dispatch a leading
`web` token to its own parser instead of a subcommand of the root program, and
read opts()/processedArgs after parse() instead of action closures with a
mutable holder.

This removes enablePositionalOptions(), the parent-option leak guard, both
action closures, and the --resume/--prompt argParser threading. Behavior
changes: `dsh -p x web` is a headless prompt (extra positional dropped),
`dsh web -p x` fails loud (web has no -p), and a repeated --resume is natural
last-wins. The two real fail-loud invariants stay as post-parse checks: an empty
--resume= id (agent-loop treats '' as no-resume) and an empty -p task.

Trims args.spec.ts to the routing/fail-loud/help behavior that matters; the
tui-agent keyless PTY smoke still covers bin.ts dispatch end to end. Net ~114
fewer lines across adapter and tests.
2026-07-24 20:01:38 +08:00
Turtle 800bafda3b refactor(cli): parse dsh argv through one Commander adapter
Replace the dsh CLI's three hand-rolled parsing idioms (raw argv[0]/includes
dispatch in bin.ts, per-mode node:util parseArgs in headless.ts/web.ts, and the
bespoke parseResumeArg scanner in dsh-app-boot) with a single Commander adapter
in apps/cli/src/args.ts. parseDshArgs resolves argv into a discriminated
DshInvocation union; bin.ts switches on the mode and dynamic-imports the chosen
module, which now consumes already-parsed values.

- web is a real subcommand; --host uses choices and --port an argParser range
  check, moving validation into the parser.
- --resume rejects empty and repeated forms; --prompt rejects empty; a config
  positional after --prompt and a root flag placed before web fail loud.
- adds --help/--version; removes parseResumeArg from dsh-app-boot.
- new apps/cli/tests/args.spec.ts (apps/*/tests added to vitest include,
  apps/cli/tests to tsconfig.host.json); the tui-agent keyless PTY smoke covers
  bin.ts dispatch end to end unchanged.
2026-07-24 19:43:59 +08:00
NI0317 2ae9f4fdf3 feat(tui): add safe session resume flow 2026-07-24 01:29:35 -07: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 fb47f61a83 refactor(gui): host graph from dshClient discovery; webserver self-watches bundles for HMR
The registry scans mounted Loader entries' dshClient declarations and
composes __DSH_BOOT__ {rev, entries} — inject edges and the immediately
mark come from manifests, never hand-copied; malformed fields fail loud
at load. The composing app owns one flat roster plus the --dev switch
(hmr row and bundle watching are dev-graph decisions).

The rebuild signal is the webserver's own observation: in dev mode the
registry stat-polls each scanned bundle (fs.watchFile; polling because
network mounts deliver no inotify), re-hashes on change, and broadcasts
a rebuilt frame on the /plugins/events SSE channel only when the rev
actually changed. Watch membership follows the table across rescans;
dispose drops all watches; a torn read self-heals on the next tick.
The POST /plugins/rebuilt endpoint is gone — builders and the host
share zero protocol. dsh web --dev logs the watched bundle list and
each rebuilt id with its rev transition.
2026-07-24 02:09:42 +08:00
Tianyi Cui 29f293675a fix(host): opt in to model titles from web 2026-07-23 20:08:33 +08:00
Dudu-0223 1ba00bf80c feat(web): inject workspace instructions 2026-07-23 14:11:25 +08:00