Commit Graph
22410 Commits
Author SHA1 Message Date
imccyu 504a01a957 release(dsh): 0.2.1-rc.4 dsh-v0.2.1-rc.4 2026-10-26 16:15:51 +08:00
imccyu 199ffe37ba fix(ui): keep the more views tooltip fixed (#7342) 2026-10-26 16:12:05 +08:00
imccyu f425304f7b Merge pull request #7179 from deepseek-harness/fix/release-acp-account-stdout
fix(acp): keep account catalog diagnostics off stdout
2026-10-25 12:56:33 +08:00
Tianyi Cui 940aafcadb test(acp): use shared cleanup for the stdout regression 2026-10-25 12:09:34 +08:00
Tianyi Cui 41736cdec5 fix(acp): keep account catalog diagnostics off stdout 2026-10-25 12:09:00 +08:00
imccyu cb7f0878e4 Merge pull request #7168 from deepseek-harness/worktree/acp-stdout-logging-audit-f95a78
fix(mcp): keep resource-listing diagnostics off ACP stdout
2026-10-25 12:05:36 +08:00
imccyu 72624bae95 fix(ui): show view tab tooltip only for overflowing labels (#7183)
Conversation view tabs added a tooltip to every label in 0.2.1-rc.3, including short labels that fit the 88px cell. Estimate the glyph width and only enable the tooltip when the label is expected to overflow; keep the More trigger tooltip.

Refs #7181
2026-10-25 12:05:02 +08:00
imccyu c38265a00e fix(ui): show view tab tooltip only for overflowing labels
Conversation view tabs added a tooltip to every label in 0.2.1-rc.3, including short labels that fit the 88px cell. Estimate the glyph width and only enable the tooltip when the label is expected to overflow; keep the More trigger tooltip.

Refs #7181
2026-10-25 02:48:52 +08:00
Yichen Jiang cc4446eecc fix(mcp): keep resource-listing diagnostics off ACP stdout
The MCP SDK answers resources/list and resources/templates/list for a
server without the resources capability with an empty page, but first
writes a console.debug line to stdout. Under the ACP profile that line
lands in the JSON-RPC stream whenever the model lists resources of a
client-supplied, tools-only MCP server. Return the same empty pages
before calling the SDK, and cover it with a unit assertion and an ACP
stdout regression test.
2026-10-24 22:25:48 +08:00
imccyu 1f81c047fc Merge pull request #6999 from deepseek-harness/worktree/release-dsh-0.2.1-rc.3
release: next version [email protected]
dsh-v0.2.1-rc.3
2026-10-23 11:29:36 +08:00
imccyu d02ea370ee release(dsh): 0.2.1-rc.3 2026-10-23 01:11:35 +08:00
Yichen Jiang c48f8523f2 feat(llm): follow the official /models listing on the DeepSeek API-key route (#6944)
* 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.

* test(llm-deepseek): compose the malformed-key turn without the native executor

release/dsh-0.2.1 predates @deepseek-ai/dsh-tool-executor-native; its tool
runtime executes tools itself. Compose the official-route turn the way
account-routing.spec.ts does on this branch.

* fix(llm-deepseek-api-key): gate nothing when the credential lookup fails

The listing cache switches scope only after it reads a credential, so a
failed lookup left `connect` serving the previous credential's listing.
After a key whose listing refuses a model was replaced by a malformed one,
`admit` refused that model with CLIENT_UPGRADE_REQUIRED before the turn
recorded the prompt, instead of `resolveAuth` reporting the credential
error on the request. Serve the built-in catalog without listing gates
when the lookup fails.

* test(llm-deepseek-api-key): pin the once-per-listing diagnostic across request preparation

The hidden-entry diagnostic test repeated the same discovery assertion to
prove a second pass reports nothing new, which read as a duplicate. Assert
the single warning after the request preparations instead; they resolve
the same listing, so dropping the per-listing deduplication still fails
the test.

* docs(llm-deepseek-api-key): note that a list matching an earlier built-in catalog counts as customized

Customization is judged against the running version's built-in catalog,
so a saved `models` list equal to an earlier version's catalog stops
following the listing once the built-in catalog changes, until Restore
defaults. Record the consequence in the Agent Note and the README's known
limitations.
2026-10-22 20:42:19 +08:00
imccyu 39d2903841 fix(ui): separate navigation pins from selection and show menu icons (#6883)
* fix(ui): separate navigation pins from selection and show menu icons

* fix(ui): simplify More menus and fold conversation views on resize

* test(ui): fix navigation CI regressions and refresh catalogs

* refactor(ui): render sidebar panel icons directly

* fix(ui): keep Chat visible and stop persisting navigation pins

* refactor(ui): drop unreachable pin validation from in-memory stores
2026-10-22 20:05:33 +08:00
675164957a feat(analytics): track navigation entries and preset selections (#6600)
* feat(analytics): track navigation entry clicks, preset switches, and new-session sends

Rebuilds the click events of #6600 on the region-owned More menus in
release/dsh-0.2.1. Exposure events, creator_mode_enter, and the
ui-workspace onOpened observer are not included.

- sidebar_menu_click gains position plus the new_session and more entries:
  New Session (sidebar button, brand, titlebar), Plugins and Automation
  rows, the left sidebar More button, and entries opened from its menu.
- more_menu_item_click records Browse other plugins and Create your plugin
  per region.
- agent_preset_switch reports applied or unbound staged picks; the seat
  controller now returns an explicit apply outcome.
- code_work_view_toggle reports a successful change of the setting.
- send_button_click adds is_new_session and the Session's preset category.

Co-authored-by: imccyu <[email protected]>

* test(analytics): cover navigation, preset switch, toggle, and send analytics

Co-authored-by: imccyu <[email protected]>

* docs(analytics): document click events and regenerate catalogs

Co-authored-by: imccyu <[email protected]>

* test(ui): reuse the developer tools row accessor without a new unknown cast

Co-authored-by: imccyu <[email protected]>

* fix(analytics): classify preset switches by preset id only

agent_preset_switch now maps the preset id the same way send_button_click does: cordis is creator, ptc, minimal and standard keep their ids, and any other id is other; a published preset name no longer changes the category.

Co-authored-by: imccyu <[email protected]>

---------

Co-authored-by: dingyifan <[email protected]>
Co-authored-by: imccyu <[email protected]>
2026-10-21 11:17:55 +08:00
5ff29190ed feat(ui): add navigation entry customization (#6247)
* fix(ui): avoid tooltip trigger overlap when a side fits

* feat(ui): add navigation entry customization

* fix(test): keep tooltip geometry independent of JSX types

* fix(ui): align customization catalogs and integration fixtures

* test(ui): complete customization lifecycle and release integration coverage

* fix(ui): return entry discovery to the installed plugin list

* docs: refresh module graph for entry customization

* build: refresh workspace links for the moved entry customization package

* docs: regenerate catalogs and pairing hashes for the moved entry customization package

* test(web): cover default-loaded entry customization in the Web e2e

* test(ui): describe entry customization as a browser plugin in the host entry spec

* build: order entry customization publication files as workspace constraints require

* test(release): drop the moved entry customization package from the experimental family list

* style(ui): use the shared focus ring color on entry customization triggers

* test(web): re-record goldens for the default-loaded More navigation menus

* test(web): add the More conversation views trigger to the remaining CI-reported goldens

* docs: record region-owned pins for plugin entry customization

* refactor(ui): rebuild entry customization on region-owned pins and More menus

- Each navigation region (left sidebar, Conversation header, right sidebar
  guide) persists its own unpinned list under
  dsh.slot.manual-order.<list slot key>.v1, filters its own launchers, and
  draws its own More button and Menu around its actions slot.
- ui-entry-customization only registers the shared menu rows (entries with
  pin buttons, Browse other plugins, Create your plugin) into the three
  actions slots and keeps no state.
- Remove ctx.layout.entryVisibility, the plugin store, left-sidebar drag
  reordering, and agentPresetNavigation; ui-layout and ui-agent-preset match
  release/dsh-0.2.1 again.
- Keep the release <nav> and Conversation tab-bar visibility conditions.
- Move the More glyph into ui-primitives as IconAppsAddOutline{Regular,Medium}.

* docs: compile the entry customization owner props example

* docs(ui): describe the wrapping Conversation tab row in the header comment

* fix(ui): return New Session to the Workspace blank and its unsent draft

- New Session (startSession without options) takes the blank-reuse path
  again instead of creating a fresh Session on every call, which hid the
  previous blank and its unsent draft since a5c9c2aaeef (#5775).
- A request that names an Agent preset skips blanks listing a different
  preset, so Creator entries no longer take over an ordinary draft.
- Record the change in a v0.2.1-rc.2 upgrade guide; the Host refresh of a
  stale loaded blank stays deferred (see the Agent Note).

* docs: regenerate the Cordis inspect catalog for New Session blank reuse

* fix(ui): keep the selected entry visible while unpinned

- Left-sidebar rows and View tabs keep the selected entry, with aria-current or aria-selected, until another entry is selected.
- Entry menu Creator action takes no region argument; the registration's region selects the prompt.
- Document the 2px panel-row and 32px View-tab gaps; drop commit hashes from the New Session Agent Note.

* fix(ui): leave a blank of another preset unstaged when starting Creator

startCreatorDraft stages cordis only when the main blank lists no preset or already lists cordis; navigation opens a separate Creator blank otherwise, so a Standard draft blank keeps its preset.

* feat(ui): choose whether a draft prompt replaces, appends to, or keeps an existing draft

- DraftInitializationOptions gains whenDraftExists ('replace' | 'append' | 'keep', default 'keep'); clearPreviousDraft stays and maps to 'replace' only when whenDraftExists is omitted.
- Append adds the prompt as new paragraphs after the existing text and references; attachments stay in every mode.
- The three Create your plugin entries append their regional prompt.

* test(web): align e2e with New Session blank reuse and the visible selected entry

* refactor(ui): share the draft paragraph writer between setDraft and appendDraft

---------

Co-authored-by: Yif <[email protected]>
Co-authored-by: imccyu <[email protected]>
2026-10-20 15:17:13 +08:00
imccyu 687f282e86 Merge pull request #6408 from deepseek-harness/worktree/release-dsh-0.2.1-rc.2
release: next version [email protected]
dsh-v0.2.1-rc.2
2026-10-17 15:22:43 +08:00
imccyu d1b9c04067 release(dsh): 0.2.1-rc.2 2026-10-17 15:10:31 +08:00
Yudong HanandLegGasai fda98dadd2 feat(web): add DeepSeek Search and Fetch APIs behind a settings switch (#6103)
* fix(web-search-deepseek): disable thinking for auxiliary search requests

The provider discards the generated text of the auxiliary Messages turn,
so reasoning tokens have no consumer. DeepSeek enables thinking by default,
which adds latency and output tokens to every search.

Fixes #6099.

* feat(web): add opt-in traditional Search and Fetch APIs

* test(web): verify API settings persistence and refresh Session evidence

* fix(web): require an explicit Search API base with its route prefix

* docs(web): document direct Search and Fetch API decisions

* fix(web): keep Messages search default behind the new Web Search API switch

- Rename useTraditionalApi/traditionalBaseURL to useSearchApi/searchApiBaseURL and
  label the switch "Use the new Web Search API"; Messages search stays the default.
- Default the Search / Fetch API base to https://api.deepseek.com/v1/tools.
- Authenticate the Search API with an API key only: DeepSeek Account tokens
  returned an empty HTTP 404 on /v1/tools/* when probed on 2026-10-16.
- Remove the count setting, which tool-web's maxResults always overrides, and
  the undocumented DeepSeek-API-Version header.
- Name the active API's base URL field and the current settings path in
  endpoint guidance; re-record the endpoint guidance Session.
- Keep WebFetchResult.statusCode required: DeepSeek Fetch reports HTTP 200 and
  drops the page title, so the fetch-metadata widening and its upgrade guide
  are removed.

* fix(web): accept account sign-in on the live Search API

The public Search and Fetch routes went live on 2026-10-16 and accept the
DeepSeek Account token, so account-route Sessions send it to the Search API
as they do for Messages search, and the settings copy no longer says account
sign-in does not apply.

Record the live behavior in the README and Agent Note: summaries of
1,000-2,300 characters, an HTTP 500 for an unresolvable Fetch target, and
migration notes for gateways without /v1/tools routes. Test doubles now use
the live response fields and RFC 3339 offsets.

* feat(web): configure Search API result count and send the triggering question

- Add web-search-deepseek.count (1-50, default 10, the service default) and
  show it as "Results per search" in Search API mode, where "Max searches per
  request" applies only to Messages; a smaller request maxResults still wins.
- Send the initiating Session's latest human prompt as ori_question, with
  whitespace collapsed and cut to the API's 128-character limit; blank or
  absent prompts omit it, and sendOriginalQuestion: false disables it. The
  settings hint states that the question is sent.
- Match the web search double on the request's query field, since
  ori_question now carries every query in the prompt.

* fix(client): unify web search endpoint override controls

* feat(web): configure registered search and fetch providers through shared settings

* feat(web): include Exa and Perplexity in provider settings

* test(web): cover provider settings branches and refresh plugin snapshots

* revert(web): drop the provider dropdown, schema-driven form, and Exa/Perplexity settings

Revert aed8c5cb609, d88c47dcd80, and 036a5a337d3. The Web search settings
page returns to the DeepSeek toggle; the DeepSeek Search and Fetch API split
is reintroduced as one plugin in the following commit.

* feat(web): move the DeepSeek Search and Fetch APIs into web-deepseek-api

The new web-deepseek-api plugin registers deepseek-search-api and
deepseek-fetch-api over one credential and API base, and exports the
authentication and redirect-rejecting transport that web-search-deepseek now
reuses for Messages search only. The web service reads searchProvider and
fetchProvider for each operation, so the Web search settings switch selects
both APIs together on save and restores Messages search with local HTTP fetch
when turned off. The switch hint links to the DeepSeek search and fetch guide.

* refactor(client): keep the web search endpoint fields on the shared override controls

Drop the always-visible reset and the inherited-address placeholder from the
Web search page, restoring ui-primitives to its base. Each endpoint field shows
the selected section's effective value and offers Reset to default only for an
override, like every other settings field.

* refactor(web): keep Messages search independent of web-deepseek-api

Restore dsh-web-search-deepseek to its own credential and transport code,
keeping only the disabled-thinking request and the current settings guidance,
so the Messages plugin no longer depends on the Search and Fetch API package.
dsh-web-deepseek-api keeps its transport internal; the regions that repeat the
Messages helpers carry jscpd:ignore markers, with the rationale recorded in the
Search and Fetch API Agent Note.

* refactor(web): keep the web-deepseek-api request type module-private

---------

Co-authored-by: LegGasai <[email protected]>
2026-10-17 15:08:08 +08:00
Yichen Jiang ca15fe4f17 Merge pull request #6417 from deepseek-harness/worktree/deepseek-flash-1017-badge
feat(web): replace the DeepSeek Flash suffix with a temporary badge
2026-10-17 13:54:15 +08:00
Yichen Jiang 3c937cd0ba feat(web): display a temporary 1017 badge for DeepSeek Flash 2026-10-17 13:33:35 +08:00
Yichen Jiang 32efe36a4e revert: restore the bundled DeepSeek Flash display name 2026-10-17 13:23:06 +08:00
Yichen Jiang c6acc07232 Merge pull request #6406 from deepseek-harness/worktree/deepseek-flash-1017
fix(llm): append 1017 to the bundled DeepSeek Flash display name
2026-10-17 09:23:32 +08:00
Yichen Jiang 9404cd1790 Merge branch 'master' into worktree/deepseek-flash-1017 2026-10-17 09:13:01 +08:00
Yichen Jiang 7d844abc87 fix(llm): append 1017 to the bundled DeepSeek Flash display name 2026-10-17 09:06:36 +08:00
imccyu 1600d8a1e1 Merge pull request #6387 from deepseek-harness/worktree/release-dsh-0.2.1-rc.1
release: next version [email protected]
dsh-v0.2.1-rc.1
2026-10-16 21:46:57 +08:00
imccyu c6e89e6755 release(dsh): 0.2.1-rc.1 2026-10-16 21:39:18 +08:00
imccyu ca912356fb Merge pull request #6388 from deepseek-harness/worktree/release-vendor-4.0.5
release(vendor): prepare cordis 4.0.5 stable packages
2026-10-16 21:19:31 +08:00
imccyu d9c04d6cc6 release(vendor): cordis 4.0.5, cosmokit 1.8.6, group 1.0.5, hmr 1.0.20, include 1.0.10, loader 1.0.6, logger-console 1.0.5, schemastery 3.18.5, timer 1.1.7 2026-10-16 20:53:44 +08:00
imccyu 1517a4dbca Merge pull request #6327 from deepseek-harness/worktree/release-dsh-0.2.1-alpha.5
release: next version [email protected]
dsh-v0.2.1-alpha.5
2026-10-16 19:02:34 +08:00
imccyu a5e553a5ee Merge branch 'master' into worktree/release-dsh-0.2.1-alpha.5 2026-10-16 18:44:50 +08:00
lsdsjy 5ee0f50811 Merge pull request #6384 from deepseek-harness/feat/account-notice-stack
feat(account): 支持通用通知字段和多通知层叠展示
2026-10-16 18:40:03 +08:00
lsdsjy 00a1155f5a test(account): 修复通知动画测试的类型感知 lint 2026-10-16 18:26:26 +08:00
lsdsjy da6c16747e fix(account): 平滑过渡不同高度的通知卡片 2026-10-16 18:21:04 +08:00
Yichen Jiang 29a497ee5c Merge pull request #6357 from deepseek-harness/worktree/model-label-slot
feat(web): add provider-aware model label slot
2026-10-16 18:12:40 +08:00
lsdsjy 474d7b7989 docs(account): 同步通知元数据类型依赖图 2026-10-16 18:04:16 +08:00
lsdsjy 1f312b6282 fix(account): 保留未校验的通知元数据 2026-10-16 17:58:20 +08:00
lsdsjy 6ac5c103db fix(account): 修复通知空标题和过期队首处理 2026-10-16 17:52:44 +08:00
lsdsjy 2dcd031a8e feat(account): 支持通用通知字段和多通知层叠展示 2026-10-16 17:14:42 +08:00
Yichen Jiang f87c08950a fix(web): memoize model label providers 2026-10-16 16:34:19 +08:00
imccyu 0a49d91bb2 release: setup next release version for [email protected] 2026-10-16 16:17:09 +08:00
Yichen Jiang 1b385d6e2a fix(web): keep model menu positioning local 2026-10-16 16:01:04 +08:00
imccyu e28419f15b Merge pull request #6353 from deepseek-harness/fix/sidebar-pageup-shift
fix(web): clip the collapsed right sidebar so PageUp cannot shift the frame
2026-10-16 15:49:54 +08:00
fz d614ae2769 Merge pull request #6348 from deepseek-harness/fix/ptc-prompt-alignment
fix(prompts): restore compatible PTC guidance and SDK persona
2026-10-16 15:48:04 +08:00
fz 839bd5131d refactor(tools): compose PTC instructions without prose replacement
Pass execution-specific phrases directly to the run_code flavor factory and render SDK instructions from explicit program-format branches. Keep all emitted text byte-identical while removing coupling to exact shared prose. Validate the owning tests with full scoped coverage, focused session/SDK replays, and a complete build.
2026-10-16 15:30:12 +08:00
fz c34a107428 test(sdk): apply cache E2E retry settings and expose provider failures
Set the required normal retry mode so the Loader accepts the full provider patch, and type-check the policy before JSON serialization. Assert the effective request settings and successful warm-up turns, report failed attempt causes immediately, and inherit suite retries for transient external API failures.
2026-10-16 15:16:35 +08:00
Yichen Jiang c78f3fd33d fix(web): keep model label menus inside the viewport 2026-10-16 15:16:21 +08:00
Yichen Jiang 919aa5f400 feat(web): add provider-aware model label slot 2026-10-16 14:24:47 +08:00
Shigma 1a33461f2b Merge pull request #6182 from deepseek-harness/docs/cordis-rc11-plan
docs(cordis): Cordis rc.11 vendor upgrade plan
2026-10-16 14:23:05 +08:00
imccyu 8953554b5e fix(web): clip the collapsed right sidebar so PageUp cannot shift the frame
While the right sidebar is collapsed, its docked hosts are translated past
the frame's right edge and widen the frame's scrollable overflow. Outside
macOS, PageUp in a text field moves the caret and reveals it against the
start edge of every scrollable ancestor, so the `overflow: hidden` frame
scrolled sideways and the whole UI shifted left.

Clip the panel's overflow. `overflow: clip` does not make the panel a scroll
container and does not clip the fixed-position floating panels, whose
containing block is the viewport; the DockLayout ancestor contract now says so.

Fixes #6341
2026-10-16 14:21:08 +08:00
fz d6adc5d9b9 fix(prompts): restore compatible PTC guidance and SDK persona 2026-10-16 13:14:24 +08:00