Commit Graph
100 Commits
Author SHA1 Message Date
Yichen Jiang e47ca1b174 Merge pull request #2116 from deepseek-harness/worktree/fix-1844-docs-site-chinese-projection
fix(docs): project existing Chinese translations
2026-08-09 21:58:23 +08:00
Yichen Jiang 5096db61b2 fix(docs): project existing Chinese translations 2026-08-09 21:48:41 +08:00
Yichen Jiang e75a5c6651 Merge pull request #2040 from deepseek-harness/worktree/sidebar-subagent-activity
feat(web): surface subagent activity in sidebar
2026-08-08 16:47:06 +08:00
Yichen Jiang 3b10120d60 Merge remote-tracking branch 'origin/master' into worktree/sidebar-subagent-activity
# Conflicts:
#	packages/client/runtime/README.i18n.yaml
2026-08-08 16:37:29 +08:00
Yichen Jiang d174edf9eb Merge pull request #2034 from deepseek-harness/worktree/merge-compact-card
feat(web): merge compact status and summary cards
2026-08-08 16:23:00 +08:00
Yichen Jiang fb1d230518 test(web): avoid replay timing assertions 2026-08-08 15:56:36 +08:00
Yichen Jiang 81d32bf52c test(web): isolate sidebar subagent activity snapshot 2026-08-08 15:46:08 +08:00
Yichen Jiang ebd3a87834 fix(web): stabilize compact card snapshots 2026-08-08 15:24:50 +08:00
Yichen Jiang b3a53c1e51 fix(client): address sidebar activity review 2026-08-08 15:14:29 +08:00
Yichen Jiang 7aca4c6b94 Merge branch 'master' into worktree/merge-compact-card 2026-08-08 14:45:55 +08:00
Yichen Jiang e9103ad5ee Merge branch 'master' into worktree/sidebar-subagent-activity 2026-08-08 14:44:48 +08:00
Yichen Jiang 04e6a98064 feat(client): surface subagent activity in sidebar 2026-08-08 14:42:14 +08:00
Yichen Jiang 63f88997bb fix(web): preserve compact icon until hover 2026-08-08 14:36:03 +08:00
Yichen Jiang 915a56208d Merge pull request #1977 from deepseek-harness/worktree/pi-ai-per-model-reasoning
feat(llm-pi-ai): per-model reasoning efforts, dialect switches, and modelOverrides in settings.yaml
2026-08-08 14:23:07 +08:00
Yichen Jiang f50521ac4c Merge pull request #2002 from deepseek-harness/feature/issue-1470-skill-invoke
feat(skill): deterministic user-explicit skill invocation at the pre-step gesture boundary
2026-08-08 14:17:52 +08:00
Yichen Jiang 1db327ea6c feat(web): merge compact status and summary cards 2026-08-08 14:11:26 +08:00
Yichen Jiang 18dee248a6 Merge remote-tracking branch 'origin/master' into feature/issue-1470-skill-invoke
# Conflicts:
#	docs/module-graph.md
2026-08-08 14:03:29 +08:00
Yichen Jiang ed492077a5 test(tool-skill): cover reject passthrough and non-text block scanning 2026-08-08 14:03:03 +08:00
Yichen Jiang 7f138f3f5c test(examples): re-record catalog stitch sentence in agent-spine inline snapshot 2026-08-08 13:52:47 +08:00
Yichen Jiang 2b6836a6fe fix(vendor): widen include's writeTask for exactOptionalPropertyTypes
The debounced writer assigns undefined on flush, which a plain optional
NodeJS.Timeout rejects under exactOptionalPropertyTypes; the error had
been masked by stale build state until a residue cleanup invalidated it.
Logged as local modification 14 in the vendor manifest.
2026-08-08 13:16:27 +08:00
Yichen Jiang 0d53752c49 refactor(host)!: retire the skill.invoke RPC for the gesture boundary
Invocation is an ordinary session.prompt again: the pre-step gesture
boundary makes it deterministic host-side for every front end, so the
dedicated RPC (handler, wire schema, error codes, client face, fixtures)
and ui-skill's claim machinery are net deletions. The menu keeps decision
21 exactly — a pick lands literal /name text — plus the user-only marker
from skill.list's modelInvocable flag.
2026-08-08 13:15:52 +08:00
Yichen Jiang c08fa27e5c feat(tool-skill): inject user-invoked skills at the pre-step gesture boundary
A whitespace-bounded /name token anywhere in a claimed user message,
naming a user-invocable skill in the workspace directory, now injects that
skill's renderSkillContent as instructions context appended after every
other injection of the step — the same agent/pre-step seam the catalog,
workspace instructions, and the runtime snapshot ride. Closed-set matching
mirrors the command registry (a miss stays plain prose), only user-source
messages are scanned, the policy check runs on the loaded definition, and
this is the sole entry point for disable-model-invocation skills. The
catalog's no-reload sentence now names the gesture boundary.
2026-08-08 13:14:49 +08:00
Yichen Jiang 7750789c8e docs: regenerate the module graph for the dsh-skill llm dependency 2026-08-08 11:32:28 +08:00
Yichen Jiang 31ed85900d fix(client): review fixes for invocation rendering and turn boundaries
The user-turn predicate (opensUserTurn) unifies the three parallel
consumers a new node kind silently missed — produced-files turn reset,
retry liveness, own-words force-scroll — so a skill invocation behaves as
the turn opener it is. The menu marker resolves through ctx.locale.bind
instead of a hand-rolled snapshot lookup; the dead legacy <skill> render
arm goes with the removal cut; command-over-skill name precedence is now
documented at the matchEnter seam; and the emptied replacement catalog
keeps the no-reload sentence, with the never-published residual recorded
in the Agent Note.
2026-08-08 11:30:16 +08:00
Yichen Jiang c4c2355b50 fix(host): harden skill.invoke at the enforcement boundary
Review fixes: recheck isUserInvocable on the loaded definition (list and
get collect independently, so a provider change between them could swap in
a user-disabled body — the skill-tool execute template's second check);
thread the carrier signal through the lookup and refuse an abandoned
caller's turn as cancelled; fold lookup/loader failures into the
structured internal error the list face already uses; refuse cwd-less
sessions with the skill.list stance; and reject blank trailing text at the
wire schema instead of relying on client trimming.
2026-08-08 11:30:14 +08:00
Yichen Jiang c480796db4 docs(llm-pi-ai): state the composition-base assumption for the dict-merge limitation
Maintainer ruling on the review's merge-semantics warning: per-model
reasoning fields belong to the settings document, not cordis.yml entry
config (the shipped composition mounts the adapter dormant), so the
recursive-merge delete gap is a documented posture rather than a tracked
fix; the Known Limitations entry now states the assumption instead of
pointing at the closed #2003.
2026-08-08 11:06:29 +08:00
Yichen Jiang e5d0089d5b cleanup(llm-pi-ai): share the model-entry field schemas between models and modelOverrides
The duplication gate caught the two schema literals diverging only by
the id field; the shared dict is now the single home, with the id added
where it lives (the entry) and omitted where the dict key carries it.
2026-08-08 10:55:11 +08:00
Yichen Jiang ae9d31d098 review: pin off-value wire contract, scope compat inheritance to the entry's api, update the superseded note
Review findings on #1977, each verified before acting: the 2026-08-03
declared-provider-catalog note is updated in place and cross-linked both
ways now that reasoningEfforts/compat reopened half of its rejected
alternative; resolveModelCompat inherits the catalog entry's compat only
while the resolved api still is the entry's own, so a route-level api
repoint no longer merges another protocol's shape as a completions base;
the off-with-value promise gains a request-boundary test proving pi-ai
reads thinkingLevelMap.off when the reasoning option is absent (and the
catalog-level test name stops overclaiming); the cannot-stop-thinking
wording narrows to what is actually enforced (no Off offered, explicit
Off refused — an effortless request goes out bare); the z.const(null)
comment attributes null passthrough to schemastery's nullable
short-circuit; the baseten drift-gate claim names its verification
source; and the layered-merge delete gap for dict keys is documented
under Known Limitations with the atomic-leaf follow-up in #2003.
2026-08-08 10:46:58 +08:00
Yichen Jiang 86fbc5fc15 Merge remote-tracking branch 'origin/master' into worktree/pi-ai-per-model-reasoning
# Conflicts:
#	docs/config-catalog.md
#	docs/user/guide/providers.i18n.yaml
#	packages/llm/llm-pi-ai/README.i18n.yaml
#	packages/llm/llm-pi-ai/README.md
#	packages/llm/llm-pi-ai/README.zh.md
#	packages/llm/llm-pi-ai/tests/config.spec.ts
2026-08-08 10:32:22 +08:00
Yichen Jiang 69bd00ae76 chore(web): register the skill-user-invoke scenario in both typecheck planes
The web app project excludes every e2e file (they are host-plane programs)
and tsconfig.host.json includes them one by one; the new scenario joins
both lists so it keeps typecheck coverage without dragging host sources
into the client project.
2026-08-08 10:28:30 +08:00
Yichen Jiang 3584d8e088 docs(skill): document the user-explicit invocation path
Bilingual README updates for the four touched packages (ui-skill's claim
flow and deterministic-injection model experience, the apiproxy skills
domain, the shared renderSkillContent seam export, the catalog stitch
sentence), the implemented Agent Note triplet recording the decision and
its peer-product evidence, and the regenerated catalogs/graphs.
2026-08-08 01:52:43 +08:00
Yichen Jiang db146f0eba refactor(host): share the turn-start route refusal between prompt and skill.invoke
turnAgentFor owns the addressed-agent resolution and the model-unavailable
refusal both turn-starting methods repeat; the duplication gate flagged the
copied block.
2026-08-08 01:52:42 +08:00
Yichen Jiang 74ba0b532e chore: sync the lockfile for the dsh-skill llm dependency 2026-08-08 01:33:56 +08:00
Yichen Jiang 0fb474f672 test(web): cover user-only skill invocation end to end
The policy scenario now expects the user-only quadrant in the menu with
its marker (riding the description — the hint field is claim-state ghost
text, which the menu never renders), and a new skill-user-invoke scenario
drives /name args through the composer against the real host: the claim
lands skill.invoke, the transcript shows the dedicated card with the
collapsed <skill_content> body, and a paced replay answers the injected
turn deterministically.
2026-08-08 01:27:25 +08:00
Yichen Jiang 8ccb176905 docs: per-model reasoning guide, config catalog, and the feature's Agent Note
The user guide's model-catalog section teaches the three new knobs at
task altitude — declare levels per model, pick the reasoning dialect,
reshape catalog models with modelOverrides — with the settings.yaml
example exercising all of them, plus an UNSUPPORTED_REASONING_EFFORT
troubleshooting row. The generated plugin config catalog picks up the
new Config fields, and the bilingual Agent Note records the decision,
the alternatives considered, and the schemastery materialization
constraint that chose false over {} as the disable spelling.
2026-08-08 01:17:10 +08:00
Yichen Jiang 011e3e4e63 feat(client): render user skill invocations as dedicated transcript cards
A user/message carrying the skill-invocation source materializes as its
own conversation node (name/args lifted off the source metadata, never
re-parsed from the body) and renders as a right-aligned bubble: the /name
chip plus the user's trailing text, with the injected <skill_content>
collapsed behind a disclosure. A record with an unreadable name degrades
to the injected-context row.
2026-08-08 01:05:08 +08:00
Yichen Jiang 56e9e61749 feat(ui-skill): claim slash skill references into skill.invoke
A menu pick or an entered /name line now claims the composer into an
args-tolerant skill.invoke transaction instead of shipping the literal
text and hoping the model loads the skill. This gives every user-invocable
skill a deterministic entry point — including disable-model-invocation
skills the catalog never shows the model (issue #1470). Candidates carry
a user-only hint, and the unreached legacy <skill> reference codec is
removed (decision 21 removal cut).
2026-08-08 00:59:55 +08:00
Yichen Jiang 756304322a feat(llm-pi-ai): modelOverrides reshapes catalog models without replacing the catalog
A route's modelOverrides dict customizes individual installed-catalog
models — key = catalog model id, value = the same fields a models entry
takes — while the rest of the catalog keeps serving, which a models list
cannot express because declaring one replaces the served set. An
override becomes the catalog entry's configuration and resolves through
the existing entry path, so capacities, reasoningEfforts, compat, and
request-default semantics are identical to a models entry's. Unlike
Pi's config layer, which ignores unknown ids, every override that lands
nowhere is refused at the write that produced it: beside a models list,
on a hand-declared route, naming a model the catalog does not describe,
or smuggling an id through the schema's unknown-key tolerance.
2026-08-08 00:57:41 +08:00
Yichen Jiang cc0f6e11b9 feat(tool-skill): teach the catalog about user-explicit skill injection
Both catalog renderings now tell the model that a directly invoked skill
arrives as an inline <skill_content> block to follow without re-loading it
through the skill tool — the seam rule that keeps the user-explicit path
and the model-autonomous path from double-injecting one skill.
2026-08-08 00:55:37 +08:00
Yichen Jiang 0490f8bb06 feat(llm-pi-ai): per-model reasoningEfforts and reasoning-dispatch compat switches
A model entry's reasoningEfforts dict declares its selectable thinking
levels — key = offered level, value = the wire spelling dispatch sends;
only off may leave the value empty (supported, send nothing). false
strips reasoning from a catalog model; every level is materialized
explicitly into pi-ai's thinkingLevelMap so nobody has to know pi-ai's
asymmetric absent-key defaulting. compat.thinkingFormat and
compat.supportsReasoningEffort become configurable on the route and per
model (model > route > catalog entry > pi-ai's URL-derived guess),
openai-completions only, so a private gateway speaking the DeepSeek
reasoning dialect no longer depends on its URL being recognizable.
Record-typed drift gates pin both enums to pi-ai's, and an unserviceable
declaration is refused at the write that produced it, naming route,
model, and level.
2026-08-08 00:51:54 +08:00
Yichen Jiang 85422f44dc feat(host): user-invocable skill listing and skill.invoke injection RPC
skill.list now serves every user-invocable skill and carries modelInvocable
so menus can mark user-only entries; the old model-and-user intersection
hid disable-model-invocation skills from their only legitimate entry point
(issue #1470). skill.invoke enforces user-invocation policy at the host
boundary, renders the canonical <skill_content> body, and injects it as a
user-role message carrying the skill-invocation source before starting a
turn. The connection fixture mirrors both faces for client tests.
2026-08-08 00:51:24 +08:00
Yichen Jiang 62c308f415 feat(skill): share renderSkillContent and declare the skill-invocation message source
The model-facing <skill_content> rendering moves from dsh-tool-skill to the
dsh-skill seam so the skill tool result and the upcoming user-explicit
invocation injection share one canonical shape. The seam also declares the
skill-invocation MessageSource kind that injection will stamp on its
user-role messages.
2026-08-08 00:40:06 +08:00
Yichen Jiang b1074e60ab test(web): re-record the skill-tool-row golden for the resolved seat label
Master added this scenario while this branch was open, so its golden froze
the composer seat's "Select model" fallback. The scaffold's route-only
adapter (added here for fixture-less scenarios) makes the seat resolve the
model those scenarios actually route to, which is what the other eight
goldens on this branch already show. Only the two seat lines move.
2026-08-07 18:54:50 +08:00
Yichen Jiang 209fb4d355 Merge remote-tracking branch 'origin/master' into worktree/default-model-persistence
# Conflicts:
#	packages/client/ui-conversation/README.i18n.yaml
#	packages/host/apiproxy/README.i18n.yaml
2026-08-07 18:18:40 +08:00
Yichen Jiang f3049e5663 fix(llm-pi-ai): describing a model must not fail on a bad profile level
`resolveModel` validated the profile's reasoning level against the exact
model and threw when it did not fit. That call builds the model catalog,
and the catalog build catches per PROVIDER — so one mis-set field took the
whole provider out of every picker behind a single error row, hiding even
the models that do support the level. Measured: `anthropic` set to `max`
threw for six of its eight models.

Describing what a model can do now reports an unusable profile level as no
default rather than throwing; the request path still refuses it, which is
where a bad configuration belongs. The existing spec asserted the old
throw and now asserts both halves of that split.

Known gap, left deliberately: a model that cannot take the route's level
still fails its first request while the picker shows 「Default」 for it,
because the request path keeps using the profile level as the fallback.
Reaching that needs a hand-written `settings.yaml` — the Models page no
longer writes the field — and the error names the model and the level, so
selecting a supported level is a way out. Closing it properly means giving
`AgentOptions` a `reasoningEffort` so compositions without a model picker
keep an entry point, then dropping the provider-scoped field altogether;
that is its own change.
2026-08-07 18:07:15 +08:00
Yichen Jiang 2dc1406dfd feat(ui-models): drop the provider-scoped reasoning effort, and red-flag a bad route id
**Reasoning effort leaves the provider cards entirely.** It is a per-MODEL
capability and the models under one provider disagree about which levels
they accept: setting `anthropic` to `max` made six of its eight models
throw UNSUPPORTED_REASONING_EFFORT, and because the catalog build catches
per provider, the whole provider vanished from the picker behind one error
row. A provider-scoped control can only ever be set to a value some of its
models reject.

The composer's model picker already offers each model its own levels, and
a switch there now records provider, model, and effort together as the
next session's default — so the setting has a better home at the right
granularity. The profile field stays in `settings.yaml` for a deployment
that knows its route; only the control is gone, from both cards and both
adapter families. Two `components.spec` cases used the control as the
vehicle for their op assertions and now use `baseURL`, which is what they
were actually testing.

**A rejected Provider ID now reads as a fault.** It shared the neutral
hint paragraph with the field's guidance, so the copy telling the user
what they got wrong looked like advice. Reuses the existing `.error`
style, matching the split the key field already makes.
2026-08-07 17:36:08 +08:00
Yichen Jiang 135064c831 fix(ui-models): stop the shared hint contradicting a filled-in field
The line under the create form names the one blocked gate worth naming,
and its fallback arm reads "no models yet". An unmet Provider ID gate fell
through to that arm, so a card with two models listed right above it was
told it needed one. The key gate was already excluded for this reason; the
route gate was assumed excluded because its field explains itself, and was
not.

Tightening the route rule in the previous commit is what made this easy to
hit — a digit-leading id now fails the gate — but the fallthrough predates
it and fires for an empty or taken id just the same.
2026-08-07 17:02:05 +08:00
Yichen Jiang 5a90eb41fb fix(ui-models): three faults the running app surfaced
**A hand-declared route must not offer a reasoning effort.** The earlier
commit read the create card's missing control as drift and added one. It
is the other way round: such a model has no reasoning capability — pi-ai's
installed catalog is what supplies one, and it ships nothing under the
route — so `resolveModel` throws UNSUPPORTED_REASONING_EFFORT for every
model on it and the whole provider drops out of the picker. Verified
against the adapter, not inferred. The create card no longer offers it and
the editor withholds it on the directory's `declared` bit, which is the
real bug: that control has always been wrong for these routes.

**A blocked composer locked the way out of the block.** Reusing the
no-workspace inert posture disabled the model seat along with everything
else, so the bar asked for a model while preventing the one control that
picks one. A block now rides its own `blocked` owner prop: the textarea,
send, commands, plan seat, and access chip all lock, and the model seat
alone stays live.

**A Provider ID could derive an illegal credential reference.** The card
accepted a digit-leading id, whose derived `123_API_KEY` then failed at
the credential seam with a raw regular expression the user cannot act on.
The id must now start with a letter, and a test pins the relation between
the two rules rather than the regex.
2026-08-07 16:45:50 +08:00
Yichen Jiang 210b6fec5c Merge pull request #1879 from deepseek-harness/worktree/web-skill-icon-14
fix(web): render Skill icon at 14px
2026-08-07 16:25:34 +08:00
Yichen Jiang 8e57dd1dac fix(web): render Skill icon at 14px 2026-08-07 16:15:17 +08:00
Yichen Jiang dfaf3c288e Merge remote-tracking branch 'origin/master' into claude/unified-environment-credentials-c8841a
# Conflicts:
#	apps/web/tests/models-settings.e2e.ts
#	docs/config-catalog.md
#	packages/llm/llm-deepseek/README.i18n.yaml
#	packages/llm/llm-deepseek/README.md
#	packages/llm/llm-deepseek/README.zh.md
#	packages/llm/llm-deepseek/src/index.ts
#	packages/llm/llm-pi-ai/src/config.ts
#	packages/llm/llm-pi-ai/src/index.ts
2026-08-07 15:54:13 +08:00
Yichen Jiang 53bd0a90a6 Merge pull request #1754 from deepseek-harness/worktree/web-skill-tool-row
feat(web): add dedicated skill tool row
2026-08-07 15:45:24 +08:00
Yichen Jiang d03d3ab70b Merge remote-tracking branch 'origin/master' into worktree/default-model-persistence
Carries two edits beyond conflict resolution, both forced by what master
brought in:

- `CustomProviderCard`: master added front-end key validation and a
  component-level `keyValue` (already trimmed) while still writing
  `apiKeyEnv` unconditionally. Kept this branch's blank-key rule and its
  committed-profile retry gate, and adopted master's single `keyValue` so
  the component has one spelling of the key rather than two.
- `docs/user/guide/providers`: master merged #1810, whose default-model
  section still taught overriding the `api-gateway` row in
  `$DSH_HOME/config.yaml` — the behavior this branch replaced. Rewritten
  for the settings section the picker now writes, plus the review fix from
  #1810 replacing the colloquial 挂着 in the opener.
2026-08-07 15:44:57 +08:00
Yichen Jiang bb43ff4f37 feat(ui): make a session that cannot send refuse to accept one
A default naming a route the Models page has since removed left the
composer saying 选择模型 while the input still accepted a message, which
then failed inside the adapter mid-turn.

`session.prompt` now refuses with `model-unavailable` before opening a
turn. That is the enforcement boundary: the method stays callable no
matter what a client disables. `session.models` reports the same fact as
`routable`, and ui-model pushes a block through the new
`ctx.conversation.blocks` registry so the bar renders the disabled
textarea it already renders without a workspace, carrying the blocker's
own reason. The push direction is forced — ui-model already depends on
ui-conversation, so ui-conversation cannot read it back.

The gate is `routable`, not "matches no advertised group": catalog
membership is advisory, so a route serving a model it stopped advertising
is missing from the groups yet perfectly usable, and `null` before the
first load never blocks so a slow Host cannot lock a working composer.

The scaffold gains a route-only adapter for fixture-less keyless
scenarios. Registering zero providers is a test artifact — every product
composition mounts one — and the goldens that froze the seat's fallback
label now show the model those scenarios actually route to.
2026-08-07 15:26:42 +08:00
Yichen Jiang 7ce9c244ae Merge pull request #1810 from deepseek-harness/claude/docs-model-providers
docs(user): 新增「配置模型」入门文档,并让文档站点自带图片
2026-08-07 15:15:27 +08:00
Yichen Jiang a45beb1292 Merge branch 'master' into worktree/web-skill-tool-row 2026-08-07 15:06:42 +08:00
Yichen Jiang 23a4c0a51e Merge pull request #1827 from deepseek-harness/worktree/charming-swartz-83bf33
fix(llm,web): validate API key format before it reaches an HTTP header
2026-08-07 14:36:04 +08:00
Yichen Jiang d5c5e7f2e9 Merge remote-tracking branch 'origin/master' into worktree/charming-swartz-83bf33
# Conflicts:
#	apps/web/tests/models-settings.e2e.ts
#	docs/config-catalog.md
#	packages/client/ui-models/README.i18n.yaml
#	packages/client/ui-models/README.md
#	packages/client/ui-models/README.zh.md
#	packages/client/ui-models/src/client/ProviderEditor.tsx
#	packages/client/ui-models/tests/provider-form.spec.tsx
#	packages/llm/llm-deepseek/README.i18n.yaml
#	packages/llm/llm-deepseek/README.md
#	packages/llm/llm-deepseek/README.zh.md
#	packages/llm/llm-deepseek/src/index.ts
2026-08-07 14:12:17 +08:00
Yichen Jiang 63724ed5f9 Merge pull request #1856 from deepseek-harness/worktree/fix-wsl-open-config
fix(apiproxy): open config files through Windows on WSL
2026-08-07 14:11:30 +08:00
Yichen Jiang 0823a3484a fix(web): report a wrapped paste as the same API key format failure 2026-08-07 14:03:11 +08:00
Yichen Jiang 72618f29b5 fix(ui-models): stop the create card pinning a reference on a blank key
Master's credential-lifecycle work taught the editor card that a pi-ai
profile names `apiKeyEnv` only when a key is actually stored, so a route
left blank keeps its provider-native auth path. The create card kept
writing the derived reference unconditionally, so a route declared for a
credential chain or ADC was born pointing at a reference nothing sets —
and now rendered a red missing-key dot for it.

Both cards apply one rule. The obsolete assertion moves with the behavior
(the with-key case is covered by the neighbouring test), and the merged
Models e2e golden shows the declared route unmarked rather than flagged.
2026-08-07 13:57:52 +08:00
Yichen Jiang 768e2e866f fix(web): keep skill row pairing client-local 2026-08-07 13:56:42 +08:00
Yichen Jiang d63c70bcf1 Merge remote-tracking branch 'origin/master' into worktree/default-model-persistence
# Conflicts:
#	apps/web/tests/models-settings.e2e.ts
#	packages/client/ui-models/README.i18n.yaml
#	packages/client/ui-models/README.md
#	packages/client/ui-models/README.zh.md
#	packages/client/ui-models/src/client/ModelsSection.module.css
#	packages/client/ui-models/src/client/ModelsSection.tsx
2026-08-07 13:54:15 +08:00
Yichen Jiang 9679597204 feat(ui-models): tag the provider rows this deployment declared
A row's stored profile could not tell a hand-declared gateway from a
shipped provider whose models someone narrowed — both look identical from
outside the adapter — so the Models page had no way to mark the routes a
deployment added itself.

The directory entry now carries `declared`, answered by the owning adapter
against its own installed catalog, and the page renders a Custom tag from
it. Absence stays "this adapter draws no such distinction" rather than
"shipped", so a route no adapter claims is labelled neither way.

Also records the default-route work's Agent Note and the e2e evidence for
all three changes: the composer switch writing the section, and the Models
page declaring a route with its own reasoning effort.
2026-08-07 13:49:47 +08:00
Yichen Jiang 0cb922199d fix(apiproxy): open config files through Windows on WSL 2026-08-07 13:30:05 +08:00
Yichen Jiang ddacc8de45 Merge pull request #1735 from deepseek-harness/worktree/provider-credential-lifecycle
fix(web): recover provider credential lifecycle
2026-08-07 13:27:18 +08:00
Yichen Jiang e0f9f7a6e6 fix(ui-models): let a hand-declared route set its reasoning effort
The create card omitted the provider-level effort the editor card offers
for the same namespace, so a route declared through 添加自定义提供方 gained
a setting the moment it was reopened for editing — one the creating user
was never shown.

Both cards now render one shared control. The field, its vocabulary, and
the inherit-means-absent rule live with the control rather than in the
editor, which is what stops the two from drifting apart again.
2026-08-07 13:25:46 +08:00
Yichen Jiang f2d1a29636 feat(apiproxy): make the default model a user setting the picker writes
The route a new session starts from was frozen into the gateway's
composition entry, so switching models in a conversation reached only that
conversation and every later session went back to the shipped default.

The gateway now owns an `api-gateway` settings section: the entry is the
base layer and the user document layers over it, so `session.selectModel`
records an accepted switch as the default for the next session. The write
is wholesale rather than a merge — switching to a model with no reasoning
effort has to clear a stored one — and a storage failure is reported
without undoing the switch, which already applies to its own session.

`targetFor` now resolves its tiers on every read instead of seeding once:
an explicit selection, else the session's own logged request header, else
the live default. That is what keeps a session that has run a turn deriving
its route from its log forever after, while a session still blank — New
Session reuses one rather than minting another — starts from a default
saved after it was created.
2026-08-07 13:23:19 +08:00
Yichen Jiang 09d1b0d27f test(web): align skill snapshot with turn actions 2026-08-07 12:50:23 +08:00
Yichen Jiang 9264f383e6 Merge remote-tracking branch 'origin/master' into worktree/web-skill-tool-row
# Conflicts:
#	apps/web/tsconfig.json
#	tsconfig.host.json
2026-08-07 12:48:08 +08:00
Yichen Jiang 545080105f Merge branch 'master' into worktree/charming-swartz-83bf33 2026-08-07 11:37:57 +08:00
Yichen Jiang abd2e2973b Merge branch 'master' into worktree/provider-credential-lifecycle 2026-08-07 11:37:41 +08:00
Yichen Jiang 3aa3212fd7 Merge branch 'master' into worktree/web-skill-tool-row 2026-08-07 11:37:34 +08:00
Yichen Jiang 5a422337f8 fix(web): silence the stale gate hint, clear whitespace fields, narrow the paste heuristic 2026-08-07 11:36:01 +08:00
Yichen Jiang df5790919c Merge branch 'master' into worktree/web-skill-tool-row 2026-08-07 11:31:49 +08:00
Yichen Jiang 6edd98e2b2 Merge branch 'master' into worktree/provider-credential-lifecycle 2026-08-07 11:28:22 +08:00
Yichen Jiang 91e9d5afa2 Merge branch 'master' into worktree/charming-swartz-83bf33 2026-08-07 11:28:05 +08:00
Yichen Jiang a7d3744268 test(web): cover the create card's blank-key copy substitution 2026-08-07 11:16:20 +08:00
Yichen Jiang ec1111f18e docs: keep the API key Agent Note current with the review fixes 2026-08-07 11:04:02 +08:00
Yichen Jiang 1019f149c4 fix(web,llm): address review — document the card contract, pin the host diagnosis, gate the probe 2026-08-07 11:02:38 +08:00
Yichen Jiang 6b75bb0425 fix(web): say the API key format is wrong rather than naming the characters 2026-08-06 23:15:08 +08:00
Yichen Jiang a89c26b611 test(web): pin the API key field refusal end to end 2026-08-06 22:42:56 +08:00
Yichen Jiang fe31cd7609 Merge remote-tracking branch 'origin/master' into claude/unified-environment-credentials-c8841a
# Conflicts:
#	apps/cli/src/profile-boot.ts
#	apps/cli/src/web.ts
2026-08-06 22:34:46 +08:00
Yichen Jiang cf9eade39d feat(web): refuse an unusable API key on the field that holds it 2026-08-06 22:30:43 +08:00
Yichen Jiang 665b5697bb docs(llm-pi-ai): document the invalid-credential refusal 2026-08-06 22:13:02 +08:00
Yichen Jiang 45d78c9272 fix(llm-pi-ai): refuse an unusable API key before the header is built 2026-08-06 22:12:50 +08:00
Yichen Jiang fe8a88c96a Merge pull request #1803 from deepseek-harness/worktree/align-core-web-rl-prompt
fix(web): align core profile with RL prompt
2026-08-06 21:57:28 +08:00
Yichen Jiang 48fd9b70ea docs: drop the notes for changes master now owns
The profile-json entry and the personal composition layer were both
settled on master by its profile restructure — the first removed with
`app-cli-entry.ts`, the second deliberately restored as
`$DSH_HOME/cordis.patch.yml`. Neither is this branch's change any more,
so the notes claiming them go, and the prose they edited returns to
master's.
2026-08-06 21:43:40 +08:00
Yichen Jiang b1660ab8a4 docs(llm-deepseek): document the invalid-credential refusal 2026-08-06 21:40:06 +08:00
Yichen Jiang 5514dd2bd6 fix(llm-deepseek): refuse an API key no header can carry 2026-08-06 21:39:57 +08:00
Yichen Jiang 5e139ac64e Merge remote-tracking branch 'origin/master' into claude/unified-environment-credentials-c8841a
# Conflicts:
#	.agents/notes/implemented/feature/2026-07-20-dsh-cli-personal-config.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-20-dsh-cli-personal-config.md
#	.agents/notes/implemented/feature/2026-07-20-dsh-cli-personal-config.zh.md
#	apps/cli/config/base.cordis.yml
#	apps/cli/package.json
#	apps/cli/reference/README.i18n.yaml
#	apps/cli/reference/README.md
#	apps/cli/reference/README.zh.md
#	apps/cli/src/app-cli-entry.ts
#	apps/cli/src/args.ts
#	apps/cli/src/bin.ts
#	apps/cli/src/config.ts
#	apps/cli/src/dump-config.ts
#	apps/cli/src/headless.ts
#	apps/cli/src/web.ts
#	apps/cli/tests/args.spec.ts
#	apps/cli/tests/built-bin.e2e.ts
#	apps/cli/tests/headless-shutdown.e2e.ts
#	apps/cli/tsconfig.json
#	docs/user/guide/config.i18n.yaml
#	docs/user/guide/config.md
#	docs/user/guide/config.zh.md
#	examples/mcp-memory/README.i18n.yaml
#	examples/mcp-memory/README.md
#	examples/mcp-memory/README.zh.md
#	packages/bundle/web-app/cordis.patch.yml
#	packages/cordis/repository-plugin/README.i18n.yaml
#	packages/cordis/repository-plugin/README.md
#	packages/cordis/repository-plugin/README.zh.md
#	packages/credentials/credentials-local/README.i18n.yaml
#	packages/credentials/credentials-local/README.md
#	packages/credentials/credentials-local/README.zh.md
#	packages/ui/app-boot/README.i18n.yaml
#	packages/ui/app-boot/README.md
#	packages/ui/app-boot/README.zh.md
#	packages/ui/app-boot/src/index.ts
#	packages/ui/app-boot/tests/config-reload.spec.ts
#	packages/ui/app-boot/tests/user-patches.spec.ts
#	pnpm-lock.yaml
2026-08-06 21:34:45 +08:00
Yichen Jiang a48b84c001 fix(scripts): only publish images the repository owns, and keep their suffix
Review found four real gaps in the image placement this PR introduced.

Link rewriting only needs a target to exist, but publication copies its bytes
onto the site: a reference reaching out of the tree through `../..` or a
symlink would put a build-machine file on a published page. Only a regular
file whose real path stays inside the repository is copied now, and anything
else fails the projection naming the page and the target.

A placed reference kept none of its `?query` or `#fragment`, which the GitHub
branch has always carried and which decides what an SVG view fragment or a
Vite query means. The suffix rides along again, and the file name is
percent-encoded because the destination is a Markdown inline target.

Page outputs and placed images now claim projected paths from one map, so the
"fail loud rather than overwrite" invariant covers a page and an image landing
on one path, not only two images. `docsSourceFiles()` reports placed images, so
replacing a screenshot re-projects under `docs:dev` instead of serving the
previous copy until something touches the page.

The guide said to set `agent-loop`'s `agents` to change the default model,
which does nothing for `dsh web`: that default is `api-gateway`'s, and the
shipped composition leaves `agents` empty. It also promised that a catalog
provider needs only an API key, which is false for Bedrock, Vertex, Azure, and
Codex. Both are corrected.

The projection note and the doc-site skill carried the superseded "a
repository image becomes a raw GitHub URL" rule; both now describe what ships.
2026-08-06 21:14:39 +08:00
Yichen Jiang b6b57ceda3 docs(llm): document the invalid-credential code 2026-08-06 20:57:43 +08:00
Yichen Jiang 88f5de5755 docs: regenerate cordis catalog and event graph for shifted index.ts lines 2026-08-06 20:57:30 +08:00
Yichen Jiang 53d47a8f86 docs(cli): clarify core prompt environment semantics 2026-08-06 20:45:57 +08:00
Yichen Jiang 5b842895a8 feat(llm): define the legal API key shape in the seam 2026-08-06 20:43:50 +08:00
Yichen Jiang c826966181 Merge remote-tracking branch 'origin/master' into claude/docs-model-providers
# Conflicts:
#	docs/user/guide/quickstart.i18n.yaml
2026-08-06 20:41:55 +08:00
Yichen Jiang 266629f1c3 test(web): cover core profile request header 2026-08-06 20:41:19 +08:00
Yichen Jiang c16cad7c03 Merge remote-tracking branch 'origin/master' into worktree/web-skill-tool-row
# Conflicts:
#	packages/host/apiproxy/README.i18n.yaml
2026-08-06 20:41:13 +08:00
Yichen Jiang 9ff7eb84f0 docs: propose API key format validation 2026-08-06 20:35:02 +08:00