Commit Graph

33 Commits

Author SHA1 Message Date
creatixchu
3135639867 Merge remote-tracking branch 'origin/master' into worktree/web-multimodal-image-input 2026-07-31 10:47:25 +08:00
imccyu
296cb1c35f fix: app-boot report plugin error detail 2026-07-31 03:02:45 +08:00
creatixchu
a975eda638 Merge remote-tracking branch 'origin/master' into worktree/web-multimodal-image-input
# Conflicts:
#	docs/architecture.i18n.yaml
#	docs/architecture.md
#	docs/architecture.zh.md
#	docs/cordis-catalog/events.md
#	docs/cordis-catalog/services.md
#	docs/core-data-structures/core.i18n.yaml
#	docs/core-data-structures/llm-streaming.i18n.yaml
#	docs/event-producer-consumer.md
#	docs/module-graph.md
#	examples/acp-agent/tests/snapshots/cordis-inspect-jsdoc/session.jsonl
#	packages/client/connection/README.i18n.yaml
#	packages/client/connection/README.md
#	packages/client/connection/README.zh.md
#	packages/client/connection/src/client/fixture.ts
#	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/AssistantMarkdown.tsx
#	packages/client/ui-conversation/src/client/chat/ChatView.tsx
#	packages/host/apiproxy/README.i18n.yaml
#	packages/host/apiproxy/src/api-proxy.ts
#	packages/llm/llm-deepseek/tests/adapter.spec.ts
#	packages/llm/llm-pi-ai/README.i18n.yaml
#	packages/llm/llm-pi-ai/src/index.ts
#	packages/llm/llm/README.i18n.yaml
#	packages/llm/llm/README.md
#	packages/llm/llm/README.zh.md
#	packages/llm/llm/src/index.ts
#	packages/llm/llm/src/types.ts
2026-07-31 02:14:07 +08:00
imccyu
d802364651 feat(cli): move the telemetry row into the shared base — every surface reports
The row moves from web.cordis.yml to base.cordis.yml, so the TUI reports
too (its exit paths already drain: disposeRootAndExit on normal exit, root
dispose before the /resume execve). The TUI launcher applies the same
resolveTelemetryPatch opt-out, judged against the tree actually booting via
configHasTelemetryRow so a --config-replace tree without the row is not
failed by a switch with nothing to disable. The TUI keyless smoke disables
telemetry in its child env; README (en/zh) and the Agent Note pair updated
to the every-surface stance.
2026-07-31 01:34:43 +08:00
imccyu
bd1c69149d fix(web): review round 1 — loud opt-out, headless drain, scaffold isolation, docs
- resolveTelemetryPatch: extracted pure switch resolution (unit-tested);
  fails loud when DSH_TELEMETRY_DISABLED is set but the row is absent, and
  documents that ANY non-empty value (including '0'/'false') disables.
- runHeadless: SIGINT/SIGTERM now dispose the tree before exit so the
  telemetry tail and shutdown marker drain (Node's default signal exit
  skips disposal).
- web.cordis.yml: explicit maxQueueSize beside maxExportBatchSize (the
  single-batch drain invariant no longer leans on an SDK default), comment
  covers exportTimeoutMillis's role and links the Agent Note.
- apps/web scaffold: disable telemetry-otel — fixture sessions must never
  leave the process.
- apps/cli README (en/zh + pairing): document the default endpoint, both
  env seams, and the no-redaction disclosure.
2026-07-31 01:34:42 +08:00
imccyu
91478443c2 feat(web): wire session-telemetry-otel into the dsh web composition
Mount the existing telemetry seam + OTel logs backend in the web/headless
config tree so every session-log event streams to an OTLP/HTTP collector:

- telemetry-otel row: url defaults to the standard local OTLP endpoint,
  DSH_TELEMETRY_OTLP_URL overrides; 10s batch cadence; exporter/processor
  values bound the shutdown drain to ~1s against an unreachable collector
  (timeoutMillis doubles as the retry deadline, single-batch drain).
- DSH_TELEMETRY_DISABLED opt-out: AppCLIEntry patches the row disabled
  before boot (config alone cannot disable a row, and exporter.url
  validation is load-time fail-loud).
2026-07-31 01:34:40 +08:00
creatixchu
c814cea183 Merge remote-tracking branch 'origin/master' into worktree/web-multimodal-image-input
# Conflicts:
#	docs/architecture.i18n.yaml
#	docs/cordis-catalog/services.md
#	docs/core-data-structures/core.i18n.yaml
#	docs/module-graph.md
#	examples/acp-agent/tests/snapshots/cordis-inspect-jsdoc/session.jsonl
#	packages/README.i18n.yaml
#	packages/llm/llm-pi-ai/README.i18n.yaml
#	packages/llm/llm-pi-ai/package.json
#	packages/llm/llm-pi-ai/src/adapter.ts
#	packages/llm/llm-pi-ai/src/index.ts
#	packages/llm/llm-pi-ai/tests/adapter.spec.ts
#	packages/llm/llm-pi-ai/tsconfig.json
#	packages/llm/llm/README.i18n.yaml
#	pnpm-lock.yaml
#	tsconfig.host.json
2026-07-31 01:11:50 +08:00
creatixchu
98ed9d8d4b Merge remote-tracking branch 'origin/master' into worktree/web-multimodal-image-input
# Conflicts:
#	apps/cli/cordis.yml
#	apps/cli/package.json
#	apps/cli/src/bin.ts
#	apps/cli/tests/args.spec.ts
#	packages/client/ui-conversation/README.i18n.yaml
#	packages/host/apiproxy/README.i18n.yaml
#	packages/ui/tui/README.i18n.yaml
#	pnpm-lock.yaml
2026-07-30 20:04:22 +08:00
Yichen Jiang
eae4219e04 Merge branch 'worktree-config-settings-seam' into worktree-llm-dynamic-config
# Conflicts:
#	apps/cli/README.i18n.yaml
#	apps/cli/composition.md
#	apps/cli/config/base.cordis.yml
#	apps/cli/src/app-cli-entry.ts
#	apps/cli/src/tui.ts
#	apps/cli/tests/tui-keyless-smoke.e2e.ts
#	examples/package.json
#	packages/ui/app-boot/README.i18n.yaml
#	packages/ui/app-boot/README.md
#	packages/ui/app-boot/README.zh.md
#	pnpm-lock.yaml
#	python/sdk-runtime/package.json
2026-07-30 19:46:04 +08:00
Yichen Jiang
8f045bfdbd fix(cli)!: stop hoisting $DSH_HOME/.env into process.env
The shipped surfaces loaded the harness home's .env into the process
environment before cordis booted. credentials-local then saw every stored
key as an ambient launch override: describe reported source 'env' with
writable false, and set/unset rejected as shadowed — so a key the web page
or TUI stored was unrotatable and undeletable from the next run onward,
and the adapter kept using the value captured at launch.

The home's .env is now the credential provider's own store, read by that
provider alone and hot-reloaded by it. The genuine launch environment and
the invoking directory's .env (loaded by the bin) remain the read-only
ambient layer, so a plain composition without the provider still resolves
keys exactly as before.

Proven by a real restart in the loader composition: store a key through
the seam, dispose the tree, re-boot over the same harness home, and the
entry is still file-sourced and writable — rotating it lands on the very
next request.
2026-07-30 15:44:32 +08:00
Turtle
a51143bded fix(cli): close shared config review gaps 2026-07-30 14:56:39 +08:00
Turtle
83360c3dca fix(cli): default session root in shipped config 2026-07-30 10:24:04 +08:00
Tianyi Cui
d6c82001b3 Merge remote-tracking branch 'refs/remotes/origin/worktree/web-multimodal-image-input' into worktree/pr555-simplify
# Conflicts:
#	.agents/notes/implemented/feature/2026-07-22-web-multimodal-image-input-and-durable-attachments.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-22-web-multimodal-image-input-and-durable-attachments.md
#	.agents/notes/implemented/feature/2026-07-22-web-multimodal-image-input-and-durable-attachments.zh.md
#	apps/cli/README.i18n.yaml
#	apps/cli/README.md
#	apps/cli/README.zh.md
#	apps/cli/src/app-cli-entry.ts
#	packages/client/connection/src/client/fixture.ts
#	packages/client/ui-conversation/src/client/service.ts
#	packages/host/apiproxy/src/api-proxy.ts
#	packages/host/apiproxy/src/api/host.schema.ts
#	packages/host/apiproxy/src/api/host.ts
#	packages/host/apiproxy/tests/fetch-carrier.spec.ts
2026-07-30 01:16:58 +08:00
Yichen Jiang
3733bd1374 fix(gui): remove temporary multimodal routing state 2026-07-30 00:30:58 +08:00
Turtle
c19facf9db refactor(cli): share app boot driver 2026-07-29 23:39:09 +08:00
Turtle
d2270eefcd fix(cli): align personal overlay semantics 2026-07-29 23:36:58 +08:00
Tianyi Cui
3a4c436d83 refactor: narrow web image input v1 2026-07-29 23:18:57 +08:00
Turtle
3d3a261793 docs(cli): remove stale composition references 2026-07-29 21:59:44 +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
creatixchu
f73bf425ec fix: address ds-review-bot v8 findings
- llm-deepseek: the uncatalogued resolveModel fallback declares text-only
  modalities — the wire route is text-only regardless of catalog
  membership, so "unknown" must not let the host persist-then-fail images.
- session.selectModel also consults the pending-inbox mirror: a queued
  image prompt enters the log only when claimed, after a switch would land.
- attachment store: ensureDurableDirectory syncs every ancestor entry up to
  a caller-vouched boundary regardless of what mkdir reports — a raced
  "already existed" is not "already durable".
- One image walker (imageBlockIn/imageInEvent) now serves both attachment
  authorization and the selection gate; referencedImage therefore also
  authorizes references inside wrapped message content.
- InputHub: the scope disposer resolves the conversation service optionally
  (teardown/HMR must reach quiescence), and a send failing after its scope
  died releases the in-flight drafts instead of restoring them onto a
  disposed shell.
- http-bridge destroys declared-oversize requests with connection: close
  instead of draining a body the client can trickle indefinitely.
- LlmService validates AND detaches modality arrays identically on the
  advisory and exact routes; READMEs record the fourth INVALID_MODEL_INFO
  rejection reason.
- CLI provider docs (JSDoc, README pair, Agent Note pair) describe the
  reuse behavior; llm-route.spec now parses the SHIPPED cordis.yml through
  the production extraction, pinning the row coupling.
- image-display lane pins gallery/rail shape in inline snapshots and the
  object-URL scheme this environment must take; stale host.schema comment
  dropped.
2026-07-29 19:40:17 +08:00
creatixchu
adce3b833d fix: address ds-review-bot v6/v7 findings on the image-input assembly
- resolveLlmRoute: reuse the yml pi-ai row for providers it already routes
  (DUPLICATE_ADAPTER boot failure) and detect an unset model by origin, not
  by comparison against one deployment default; covered by a new spec.
- LlmService.resolveModelInfoFor preserves (and validates) modality
  metadata, arming the host image preflight for exact-route resolution.
- session.selectModel refuses a text-only target once the session log
  carries an image on any replayed route; an accepted switch would strand
  every later turn with no in-product recovery.
- The composer no longer gates image intake on the handshake activeModel
  snapshot (wrong authority for a per-session decision); the host preflight
  plus the error strip own capability, deployment limits stay client-side.
- InputHub shell teardown releases the scope's draft images (File objects
  and object URLs leaked for the page lifetime).
- session.prompt image parts carry optional alt into the durable block;
  ImageBlock documents assistant-side rendering as forward compatibility.
- Assembled built-client lane apps/web/tests/image-display.snapshot.ts pins
  the history galleries over the authorized attachment route, the lightbox,
  and the composer paste rail; the attachment rail is an accessible group.
- Docs: validateImage on the seam page, fixture byte metadata matches its
  PNG, and the Agent Note claims now match the shipped coverage.
2026-07-29 18:56:40 +08:00
creatixchu
666fd721b5 Merge remote-tracking branch 'origin/master' into worktree/web-multimodal-image-input
# Conflicts:
#	apps/cli/README.i18n.yaml
#	apps/cli/package.json
#	apps/cli/src/app-cli-entry.ts
#	apps/cli/src/args.ts
#	apps/cli/src/bin.ts
#	apps/cli/src/web.ts
#	apps/cli/tests/args.spec.ts
#	docs/architecture.i18n.yaml
#	docs/config-catalog.md
#	docs/module-graph.md
#	packages/README.i18n.yaml
#	packages/client/connection/README.i18n.yaml
#	packages/client/connection/src/client/api.ts
#	packages/client/connection/src/client/fixture.ts
#	packages/client/connection/src/index.ts
#	packages/client/connection/tests/node-half.spec.ts
#	packages/client/ui-conversation/README.i18n.yaml
#	packages/client/ui-conversation/src/client/chat/ChatView.tsx
#	packages/client/ui-conversation/src/client/skeleton/InputBar.tsx
#	packages/host/apiproxy/src/api/host.schema.ts
#	packages/host/apiproxy/src/index.ts
#	packages/ui/tui/README.i18n.yaml
#	pnpm-lock.yaml
2026-07-29 14:38:34 +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
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
Yichen Jiang
004f598917 Merge remote-tracking branch 'origin/master' into worktree/web-multimodal-image-input
# Conflicts:
#	docs/architecture.i18n.yaml
#	docs/architecture.md
#	docs/architecture.zh.md
#	docs/config-catalog.md
#	docs/core-data-structures/core.i18n.yaml
#	docs/core-data-structures/llm-streaming.i18n.yaml
#	docs/module-graph.md
#	examples/acp-agent/tests/snapshots/cordis-inspect-jsdoc/session.jsonl
#	packages/README.i18n.yaml
#	packages/client/connection/src/client/fixture.ts
#	packages/client/connection/src/index.ts
#	packages/client/runtime/README.i18n.yaml
#	packages/client/runtime/README.md
#	packages/client/runtime/README.zh.md
#	packages/client/runtime/src/client/sessions/conversation.ts
#	packages/client/ui-conversation/README.i18n.yaml
#	packages/client/ui-conversation/src/client/apply.ts
#	packages/client/ui-conversation/src/client/chat/ChatView.tsx
#	packages/client/ui-conversation/src/client/chat/MessageItem.tsx
#	packages/client/ui-conversation/src/client/contract/slots.ts
#	packages/client/ui-trajectory/tests/views.spec.tsx
#	packages/compact/compact-basic/README.i18n.yaml
#	packages/cordis/tool-cordis/src/api-catalog.ts
#	packages/host/apiproxy/src/api-proxy.ts
#	packages/host/apiproxy/src/api/index.ts
#	packages/host/apiproxy/src/api/sessions.ts
#	packages/host/apiproxy/src/index.ts
#	packages/host/apiproxy/tests/fetch-carrier.spec.ts
#	packages/llm/llm-deepseek/src/adapter.ts
#	packages/llm/llm-deepseek/tests/adapter.spec.ts
#	packages/llm/llm-deepseek/tests/serialize.spec.ts
#	packages/llm/llm-pi-ai/README.i18n.yaml
#	packages/llm/llm-pi-ai/src/adapter.ts
#	packages/llm/llm-pi-ai/src/index.ts
#	packages/llm/llm-pi-ai/tests/adapter.spec.ts
#	packages/llm/llm/src/types.ts
#	packages/ui/tui/README.i18n.yaml
#	packages/ui/tui/src/index.ts
#	packages/ui/tui/tests/tui.spec.ts
2026-07-28 11:41:40 +08:00
Turtle
2fda7c1da5 feat(cli): default session store to global ~/.dsh/sessions 2026-07-27 19:08:26 +08:00
Yichen Jiang
c981f18921 Merge remote-tracking branch 'origin/master' into worktree/web-multimodal-image-input
# Conflicts:
#	apps/cli/README.md
#	apps/cli/src/web.ts
#	apps/web/tests/smoke-fixture.e2e.ts
#	docs/architecture.i18n.yaml
#	docs/module-graph.md
#	examples/acp-agent/tests/snapshots/cordis-inspect-jsdoc/stdout.expected.jsonl
#	packages/client/connection/src/client/api.ts
#	packages/client/connection/src/client/fixture.ts
#	packages/client/runtime/README.md
#	packages/client/runtime/src/client/index.ts
#	packages/client/runtime/src/client/sessions/conversation.ts
#	packages/client/runtime/src/client/sessions/service.ts
#	packages/client/runtime/src/client/sessions/session.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/service.ts
#	packages/client/ui-conversation/src/client/skeleton/ConversationRoot.tsx
#	packages/client/ui-conversation/src/client/skeleton/EmptyState.tsx
#	packages/client/ui-conversation/src/client/skeleton/InputBar.tsx
#	packages/client/ui-conversation/src/client/stores.ts
#	packages/client/ui-conversation/tests/apply-inject.spec.tsx
#	packages/client/ui-conversation/tests/service-orchestration.spec.ts
#	packages/client/ui-conversation/tests/skeleton-branches.spec.tsx
#	packages/client/ui-conversation/tests/skeleton.spec.tsx
#	packages/cordis/tool-cordis/src/api-catalog.ts
#	packages/host/apiproxy/package.json
#	packages/host/apiproxy/src/api-proxy.ts
#	packages/host/apiproxy/src/api/sessions.schema.ts
#	packages/host/runtime/package.json
#	packages/host/runtime/src/boot.ts
#	packages/host/runtime/tests/host-runtime.spec.ts
#	packages/host/runtime/tsconfig.json
#	packages/host/webserver/README.md
#	packages/host/webserver/src/index.ts
#	packages/host/webserver/tests/webserver.spec.ts
#	packages/llm/llm-pi-ai/tests/convert.spec.ts
#	packages/ui/acp/src/codec.ts
#	packages/ui/acp/tests/codec.spec.ts
#	pnpm-lock.yaml
2026-07-25 22:35:22 +08:00
imccyu
9eb9c70a8a feat(web): add workspace-aware session flow 2026-07-25 17:45:26 +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
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