Commit Graph
1011 Commits
Author SHA1 Message Date
Shigma 1aead808e2 chore(cordis): merge master into cordis-core-rc11 2026-10-28 17:27:40 +08:00
imccyu 00d541438b release(dsh): 0.2.2-alpha.2 2026-10-28 02:03:15 +08:00
imccyu 69c389ae11 release(dsh): 0.2.2-alpha.1 2026-10-28 00:00:58 +08:00
imccyu 873c68c15b feat(models): show model selector badges from the /models listing (#7027)
* refactor(llm-deepseek): share the /models listing machinery

Move the account route's `/models` request and decoding, its
credential-scoped listing cache, and listed-catalog resolution with the
version gate into the shared DeepSeek Messages library, so a second
route can follow the same listing. Names drop the account prefix, the
cache takes each access's endpoint settings with the call, and it gains
`invalidate()` for a forced reload. `isBuiltInCatalog()` recognizes the
catalog an uncustomized `models` setting resolves to.

The account route keeps its behavior; only its imports and the
override diagnostic wording ("model listing") change.

* feat(llm-deepseek-api-key): follow the official /models listing

While `models` equals the built-in catalog and the Messages origin is
https://api.deepseek.com, `deepseek-official` serves the official
`GET /models` listing, authenticated with the API key in `x-api-key`.
Loading, refresh, fallback, merging, and the client-version gate match
the account route: the first access waits up to `modelsTimeoutMs`, a
listing older than `modelsMaxAgeMs` refreshes in the background on the
next access, a failure keeps the last good listing or the built-in
catalog, and listed models this build cannot serve are refused before
network I/O.

A customized `models` list replaces the catalog and requests nothing.
Switching between a customized catalog and the listing discards the
cached listing, so Restore defaults reloads it on the next access.

Suites that boot the route on the official endpoint now answer the
listing themselves instead of reaching the network.

* docs: describe the official route model listing

Document when `deepseek-official` follows the official `/models`
listing, its timing fields, customization precedence, and the forced
reload after Restore defaults in the API-key README, the shared
transport README, and the provider guide. Record the decision in a new
Agent Note, keep the account note's statement of where the shared
listing code lives current, and regenerate the configuration catalog.

* test(llm-deepseek-api-key): pin the once-per-listing hidden-entry diagnostic

* docs: regenerate module and event graphs for the shared listing

* fix(llm-deepseek-api-key): report credential failures on the model request

On the official endpoint, `connect` waited for the listing view, whose
credential lookup rethrew a malformed key or a credential-store failure
before the agent loop recorded the prompt. A failed lookup now resolves
the connection from the current listing view, so `resolveAuth` reports
the failure on the model request and the turn keeps the prompt and the
failed attempt. A caller abort still rejects.

* docs(llm-deepseek-api-key): name which hidden listing entries are logged

* test: keep unit suites off the official model listing

Suites that boot the DeepSeek routes with a dummy or inherited key now
request `GET https://api.deepseek.com/models` on the official endpoint.
A unit-lane setup file rejects that request at once, so such a suite
serves the built-in catalog instead of reaching production or waiting
out the listing deadline on a network that never answers; suites that
exercise the listing answer `fetch` themselves. Other requests pass
through unchanged.

* feat(llm-deepseek): read tool_update from the model listing

Both DeepSeek routes now take a listed model's Messages tool update mode
from `api_capabilities.anthropic_messages.tool_update`, alongside the
system prompt mode. `in-history` and `addition-only` replace the
bundled mode; any other value reads as `leading-only` and removes it.
An absent or `null` mode keeps the bundled one, so a listing that does
not declare the field leaves `deepseek-flash` on `addition-only`.

`system_prompt_update: null` likewise keeps the bundled mode now; it
previously read as `leading-only`, which a serializer writing empty
values as null would have turned into a cache-unfriendly downgrade.

* fix(llm-deepseek): sync the built-in context window with the official listing

The official `/models` listing declares a 1,048,576-token context window
for `deepseek-flash` and `deepseek-v4-pro`; the built-in catalog said
1,000,000, a decimal-versus-binary mismatch. Both built-in entries now
carry the listed value, so offline starts and listing failures size the
context the same way the listing does. The Models page shows the exact
count for these rows, since 1,048,576 has no decimal K/M spelling.

`defaultContextWindow`, the fallback for model ids the catalog does not
describe, stays 1,000,000.

* test(llm-deepseek-api-key): reject the stubbed listing request with an Error

* test(cli): keep the built SDK smoke off the official model listing

The SDK profile's initialize now resolves the deepseek-official catalog,
which requests GET https://api.deepseek.com/models on the official
endpoint. With the smoke's fixture key that request answers 401 and the
route warns on stderr, so the test's empty-stderr assertion failed in the
e2e and snapshots lanes. Point the run at a loopback mock and assert it
received no model call.

* feat(llm): carry /models badges into the model catalog

The shared DeepSeek listing decoder reads an optional per-entry
`badge: { text, tone }`. Text is one literal or translations keyed by
lowercase language id with a required English entry, each trimmed to 1
to 12 characters on one line; tone is neutral, info, success, or
warning, and an absent or unrecognized tone reads as neutral. An absent
or null badge declares none; an unreadable one is dropped with a listing
problem and never hides its model.

resolveListedCatalog keeps the badges of offered models, both DeepSeek
routes attach them through catalogModelInfo, LlmRuntime.listModels
detaches them, and the Host model catalog forwards them as
ModelCatalogModel.badge. resolveModelInfo omits the badge, so no model
request, Session event, or model-facing tool carries it.

* feat(client): render catalog badges in the model selector

The composer model seat shows a catalog model's badge after its name in
the trigger, the root-menu value, and each option: a Tag in the badge's
tone whose text is resolved for the active locale through
ctx.locale.resolveText. A conversation.input.model.label contribution
replaces the name and badge together and receives the badge in its
owner props.

Remove ui-deepseek-model-label-1017, which hard-coded `1017` beside
DeepSeek-V4.1-Flash for two providers, and its Web bundle row. The badge
now comes only from the model listing, so the build ships none of its
own; the upgrade guide covers profile patches that still target the
removed row. The Web e2e replaces the fixed-badge case with replay
catalogs that declare literal and translated badges, and the replay
adapter validates and advertises a configured badge.

* feat(llm-deepseek): read model badges from client_metadata

Each /models entry now declares its selector badge under
client_metadata["deepseek-harness"].badge, keyed by the User-Agent product
token like client_requirements, so the public model fields stay unchanged
and later DeepSeek Harness fields join the same object. Every field under
client_metadata is ignorable: null at any level shows no badge, and a level
that is not an object drops only the badge with a diagnostic naming it.

* docs: record why the listing badge container is client_metadata

* fix(models): refresh listed badges in open selectors

* refactor(models): share listing cache lifecycle wiring

* docs(models): refresh listing event producer catalog

* fix(models): retain badges when listing refresh fails

* fix(models): validate badge text and preserve tags beside long names

* test(models): cover account listing automatic badge removal
2026-10-27 23:18:07 +08:00
imccyu 2de3029cc6 Merge pull request #7427 from deepseek-harness/fix/chat-landing
fix(chat): keep the transcript steady at Turn end and when steering lands
2026-10-27 22:16:47 +08:00
imccyu a1659120a3 fix(session-controller): retire a queued echo when its Inbox row is canceled
A queued echo now records its Inbox position like transcript and steering
echoes. Later splices move that position, so a canceled splice that removes
the row retires the echo even when no Inbox projection ever showed it, for
example when the Turn is stopped right after queueing. A claimed row still
waits for its admitted message, and the queue dock still hands the echo over
to the Host row it renders.

The fold-room e2e no longer samples the running status slide or the
`data-chat-tail-pinned` mark that this branch removed. It asserts that fold
room below a short answer takes the new Turn's growth without scrolling
through Turn end, that the room never grows back, and that the running
status only moves down.
2026-10-27 21:36:10 +08:00
imccyu ae07093132 fix(chat): keep the transcript steady at Turn end and when steering lands
Measured against 0.2.1-rc.4 and master with the frame-sampled motion matrix,
the transcript moved back and forth at Turn end and around input landing.
This keeps rc.4's landing behavior, master's steering layout, and fixes the
reversals that remain.

- Completion-time folding keeps the first visible surviving row still when
  work rows close at once, filling the gap with bottom space capped at half
  the scrollport, instead of letting the browser clamp the position.
- After the Session stops running, the running status keeps its tail slot
  hidden and silent until the Turn's actions row replaces it, so the tail
  does not shrink and grow back.
- A Turn's duration control takes its gap in one frame instead of sliding.
- A fold batch that takes over following for a content change absorbs
  growth outside the batch before its first frame.
- Steering lands at once under either fold timing: the running Turn keeps
  streaming above its echo, which a native animation would push down.
- The running status no longer slides below a Step's first output, and the
  column no longer carries `data-chat-tail-pinned`; the steering entrance
  keeps its animation.
- A queued prompt is accepted by its Inbox row as well as by its receipt,
  so the composer clears the draft in the frame the queue dock shows it.
- A queued echo waits for the Inbox projection instead of retiring on the
  durable splice, so the queue dock does not empty for a frame.
2026-10-27 20:44:52 +08:00
Yichen Jiang 8394a200b9 fix(models): refresh listed badges in open selectors 2026-10-27 14:53:23 +08:00
Yichen Jiang af086ad377 Merge remote-tracking branch 'origin/master' into worktree/pr-7027-badge-refresh
# Conflicts:
#	docs/event-producer-consumer.md
#	docs/event-producer-consumer.zh.md
#	docs/persistence-catalog.i18n.yaml
#	docs/persistence-catalog.md
#	docs/persistence-catalog.zh.md
#	docs/persistence-schema.json
#	packages/client/ui-deepseek-model-label-1017/package.json
2026-10-27 14:38:36 +08:00
_Kerman 89c5ea4d83 Merge latest master into xtr/trajectory-result-mode 2026-10-27 11:16:45 +08:00
imccyu 6a19d120c9 Merge master into DSH 0.2.1-rc.4 synchronization branch 2026-10-26 16:18:13 +08:00
Yichen Jiang b0e41f74ad Merge remote-tracking branch 'origin/master' into worktree/composer-host-confirmed-echo
# Conflicts:
#	packages/api/session-controller/README.i18n.yaml
#	packages/api/session-controller/src/client/sessions/session.ts
#	packages/client/ui-conversation/README.i18n.yaml
2026-10-26 13:29:33 +08:00
_Kerman 5626ae2391 refactor(trajectory): own live result inspection in the feature plugin 2026-10-26 11:16:36 +08:00
imccyu 3014b0af0f Merge master into DSH 0.2.1-rc.4 synchronization branch 2026-10-26 01:29:12 +08:00
imccyu 341beb33c0 release(dsh): 0.2.1-rc.4 2026-10-26 00:57:37 +08:00
imccyu 8b8d1a4942 test(session): call the renamed events read 2026-10-25 19:55:32 +08:00
imccyu e032fdc2a8 refactor(session): rename the history controller read to events 2026-10-25 19:54:41 +08:00
imccyu 12a8c3adf7 docs(session): correct the events page and activation wording 2026-10-25 19:36:04 +08:00
imccyu 7c7b021766 docs(session): document events, deprecated page and activation order
Sync the Session README, implementation notes and follow upgrade guide,
then regenerate the API, subsystem, persistence and event-graph catalogs.
2026-10-25 18:14:32 +08:00
imccyu 99a6c14527 test(session): cover the split controllers and passive follow
Move the facade, listener, state, wait and history tests onto the new
controllers, and cover passive activation, omitted cursors and the
event subscription frames.
2026-10-25 18:14:28 +08:00
imccyu 2f2caf88b3 feat(session): split history, state and web controllers
History, State and Web become ordinary classes sharing the Session scope.
Subscribe-before-read removes the tail repair, events and page expose the
cursor-bearing history read, observeEvent keeps a pure event subscription,
and follow stays passive unless activate is requested.
2026-10-25 18:14:18 +08:00
imccyu a1473ddec6 feat(gateway): expose pending remote events
Session state reads sample Gateway pending events; the Gateway contract now
provides getPendingRemoteEvents() for that read.
2026-10-25 18:14:17 +08:00
CreatixChu 7bc30c4cba fix(attachments): 复用完整图片引用,取消 Session 历史扫描 (#7021)
* test(api): measure historical image read costs

* fix(test): resolve image benchmark paths from its config

* fix(attachments): read stored images without scanning sessions

* test(attachments): complete by-id fixtures and access assertions

* fix(docs): implement image-id read on catalog fixture

* docs(attachments): refresh generated read contracts

* test(web): verify stored images across history and forks

* docs(api): clarify image read metadata and permission scope

* test(api): type benchmark instrumentation without unsafe returns

* test(api): retire unknown-cast allowances with removed history fixtures

* test(attachments): isolate browser cases and document store-wide access

* test(web): intercept the by-id thumbnail read path

* docs(perf): run generated diagnostic from its owning package

* refactor(attachments): reuse reference reads for conversation images

* docs(api): refresh complete image reference client contract

* test(ui-chat): assert complete image reference forwarding

* test(perf): measure image reads against current Session observations
2026-10-25 09:40:53 +00:00
Yichen Jiang 3764b60205 Merge commit '3dd445fe163' into worktree/composer-host-confirmed-echo
The session-controller README pairing is recorded again for the merged
sections.
2026-10-24 21:39:51 +08:00
_Kerman e1e3f3a2c2 fix(trajectory): retain raw tool results only for live Sessions 2026-10-24 14:01:59 +08:00
imccyu 048845f841 fix(typert): harden default resource declarations and sync contracts 2026-10-23 17:39:35 +08:00
imccyu 3c4a79cc1b chore(session): remove stray blank lines 2026-10-23 16:22:07 +08:00
imccyu b2b3bf4568 fix(typert): reject ambiguous and multiple default resource identities 2026-10-23 16:13:38 +08:00
imccyu 9d7cd67a51 test(session): cover cold attachment without workspace 2026-10-23 16:01:29 +08:00
imccyu 05f94de1f9 fix(typert): preserve parameter metadata in resource resolvers 2026-10-23 16:01:28 +08:00
imccyu 94464e2214 chore(session): sync baseline docs and test lint 2026-10-23 16:01:28 +08:00
imccyu fea3bcdbf4 feat(typert): support default resource resolvers 2026-10-23 16:01:28 +08:00
imccyu 0c23ad233d refactor(session-controller): remove unused inspection facade 2026-10-23 16:01:27 +08:00
Dudu-0223 6c4560253d docs(session): explain historical ordinary fork parents 2026-10-23 15:07:41 +08:00
Dudu-0223 b096659245 fix(session): make ordinary forks independent of source lineage 2026-10-23 14:48:07 +08:00
Yichen Jiang 89538fb115 Merge remote-tracking branch 'origin/master' into worktree/composer-host-confirmed-echo
- The composer's primary button keeps master's rule that hides a denied
  action and draws the sending state inside it; a sending prompt stays
  interruptible through master's stopAction.
- The ui-conversation README pairing is recorded again for the merged
  sections.
2026-10-23 14:31:30 +08:00
Yichen Jiang c92c81727c Merge remote-tracking branch 'origin/master' into worktree/model-badge-schema-fb132b 2026-10-23 13:23:05 +08:00
imccyu 37faa05ffa Merge master into DSH 0.2.1-rc.3 synchronization branch 2026-10-23 12:55:47 +08:00
Turtle 2d130c7e61 Merge pull request #5610 from deepseek-harness/turtle/image-cache-stale-0a243f674e12
fix(client): reload overwritten local Markdown images in new renders
2026-10-23 12:44:17 +08:00
imccyu 14f0b2aafe Merge master into DSH 0.2.1-rc.3 synchronization branch 2026-10-23 11:56:34 +08:00
imccyu d02ea370ee release(dsh): 0.2.1-rc.3 2026-10-23 01:11:35 +08:00
Shigma 21e19d3639 chore(cordis): merge master into cordis-core-rc11 2026-10-22 21:20:45 +08:00
07akioni 84edeadc2b feat(i18n): add Spanish French German Russian and Portuguese 2026-10-22 19:53:52 +08:00
Yichen Jiang 663aa618c5 feat(llm): carry /models badges into the model catalog
The shared DeepSeek listing decoder reads an optional per-entry
`badge: { text, tone }`. Text is one literal or translations keyed by
lowercase language id with a required English entry, each trimmed to 1
to 12 characters on one line; tone is neutral, info, success, or
warning, and an absent or unrecognized tone reads as neutral. An absent
or null badge declares none; an unreadable one is dropped with a listing
problem and never hides its model.

resolveListedCatalog keeps the badges of offered models, both DeepSeek
routes attach them through catalogModelInfo, LlmRuntime.listModels
detaches them, and the Host model catalog forwards them as
ModelCatalogModel.badge. resolveModelInfo omits the badge, so no model
request, Session event, or model-facing tool carries it.
2026-10-22 18:47:30 +08:00
imccyu f185b5fa6d Revert "fix(session-controller): 在 Web 操作中等待本地 Agent 初始化" 2026-10-22 18:18:01 +08:00
_Kerman a3d5e4f9e3 Merge pull request #6959 from deepseek-harness/xtr/fix-web-agent-initialization
fix(session-controller): 在 Web 操作中等待本地 Agent 初始化
2026-10-22 18:12:26 +08:00
_Kerman d3972b1af5 fix(session-controller): handle initialization join failures 2026-10-22 17:44:40 +08:00
_Kerman e5b68798b9 fix(session-controller): wait for initializing local agents 2026-10-22 17:04:51 +08:00
Turtle b908e13271 Merge remote-tracking branch 'origin/master' into turtle/image-cache-stale-0a243f674e12
# Conflicts:
#	packages/api/session-controller/README.i18n.yaml
#	packages/api/session-controller/README.md
#	packages/api/session-controller/README.zh.md
#	packages/client/ui-primitives/README.i18n.yaml
2026-10-22 14:57:42 +08:00
imccyu 73931626be feat(webserver): add resource routes and in-process readResource (#6901)
* feat(webserver): add resource routes and in-process readResource

A webserver route or the fallback seat may now answer through a resource,
a function from a Fetch Request to a Response, besides the existing
node:http handler. register accepts either route form and registerFallback
accepts a handler or { resource }; existing handler callers are unchanged.
HTTP GET and HEAD requests reach a resource; webServer.readResource(request,
peer) follows the same match order and reaches only resources, so handler
routes stay unreachable to in-process readers.

client-modules registers /plugins as the fetchBundle resource, and
frontend-static claims the fallback seat with a resource that renders the
index for a supplied Peer, or runs Connection's existing authorizeIndex for
an HTTP request and renders for the browser Peer.

* fix(webserver): flush resource headers and keep one drain listener per response

Resource responses send their status and headers before the first body
chunk, register one drain/close listener pair per response so the gzip
middleware's zlib stream does not accumulate listeners across backpressure
waits, and readResource drops the body of a HEAD read as HTTP does. HTTP
requests and readResource share one responder lookup.

* chore(scripts): prune the retired client-modules unknown-cast baseline entry

* feat(frontend-static): let browsers revalidate dist files except the index

Every dist file other than the rendered index now carries
cache-control: no-cache and a weak ETag from a SHA-1 of its bytes; a
request whose If-None-Match equals that ETag receives an empty 304. The
index keeps sending no cache headers. In-process reads through
webServer.readResource revalidate the same way.

* fix(webserver): stop reading Host for resource URLs and copy no held body

A resource request's URL is the request target resolved against the same
placeholder origin the route match uses, so a missing or unparsable Host no
longer turns a dist or /plugins request into 400. The webserver ends a
resource response itself and treats any earlier close as an abort, which
also covers the Web Worker tunnel marking an aborted response ended first.
client-modules bundle bodies and frontend-static file bodies are the held
bytes themselves instead of copies, and frontend-static no longer exports
its internal serveStatic helper.

* docs(webserver): document resource route types and the handler-or-resource fallback

Paste WebResource and WebResourceRoute beside WebRoute on the web-server
subsystem page and link the catalog signatures to it, replace the remaining
'fallback handler' wording now that the seat takes a handler or a resource,
and note why the drain listener removal is a no-op under gzip.
2026-10-22 13:41:18 +08:00