Repository navigation
Replies: 2 comments
|
四条主诉我逐条核了,三条成立、一条的机制需要修正。另外你引的那两处「反向文档错误」在最新代码上仍然存在,是最容易落地的一处修正。 1. home patch 让整行在 Settings 里存不下去 —— 成立
if (!isDeepStrictEqual(effective?.config ?? {}, next)) {
throw new Error(`Configuration for "${entry.options.id}" is overridden by a home patch or command-line overlay`)
}你引的代码与报错文本逐字正确。层序在 判据是「组合后整行深比较」 ⇒ 所以"home patch 只改了一个键"也会让整行在 UI 里变只读 —— 你观察到的 llm-pi-ai 现象成立。 2.
|
|
Adding a case for point 1, with one more consequence: such a row is not only un-editable, it is also un-resettable. Both write paths the settings form can take are refused, so once a home row sets Environment: DSH Desktop 0.2.1-rc.3 (bundled Why both paths fail: the editor uses two different layer sets
So Matrix, using this install's real layer data
The third row matters: narrowing the home row does not restore editability, because a patch replaces Repro with the shipped modules only (no app, no UI)import { applyEntryPatches } from '@deepseek-ai/cordis-plugin-include'
const ID = 'agent-preset-registry'
const NAME = '@deepseek-ai/dsh-agent-preset-registry'
const bundle = [{ id: ID, name: NAME, config: { default: 'standard' } }]
const home = [{ id: ID, name: NAME, config: { default: 'standard', selectedDefault: 'standard' } }]
// (A) user edits selectedDefault -> redteam
const A = [{ id: ID, name: NAME, config: { default: 'standard', selectedDefault: 'redteam' } }]
applyEntryPatches(bundle, [...A, ...home]).find(r => r.id === ID).config
// => { default: 'standard', selectedDefault: 'standard' } != next -> throws
// (B) user clicks "restore default": next === inherited() === { default: 'standard' }, row config deleted
const B = [{ id: ID, name: NAME }]
applyEntryPatches(bundle, [...B, ...home]).find(r => r.id === ID).config
// => { default: 'standard', selectedDefault: 'standard' } != { default: 'standard' } -> throwsSmallest change that would unstick it (no layer-model change)Make Optionally, in addition: refuse earlier with a distinct |
Uh oh!
There was an error while loading. Please reload this page.
I run the desktop app and the CLI
dsh webagainst the same$DSH_HOME, and I want the same custom model setup in both (one pi-ai gateway, nine models). Trying to stop maintaining two copies of that config turned into three separate traps, so I'm writing them up together instead of filing three reports.1. The shared layer disables the Settings page for every row it sets
$DSH_HOME/cordis.patch.ymlis documented as the machine-local layer shared by every profile, and it is applied after the profile patch, so it wins. That sounds like exactly the right home for shared config.But a row that lives there can no longer be saved from Settings. The configuration editor validates a write by composing every layer and comparing the composed row against the intended config — the
isDeepStrictEqual(effective?.config ?? {}, next)check inpackages/boot/config-editor/src/index.ts. Once the home patch wins that comparison, the write is refused with:I confirmed the mechanism outside the UI by composing the profile layers twice, once with a home patch on the row and once without: without it the same write passes, with it the guard rejects.
The practical result: the layer that exists to share configuration is also the layer that makes that configuration uneditable in the GUI. For
llm-pi-ai, the Models page still renders the provider and API keys still save (they go to~/.dsh/.credentials.yaml, which is shared), but adding or editing a model is refused. So "share it" and "manage it in the UI" are mutually exclusive, and nothing in the UI says so.2. A patch row replaces the target row's whole
config, silentlyThe rule is written in the bundle headers — a patch replaces the targeted row's whole
configrather than merging into it — and that is fine as a rule, but nothing warns you when a write drops inherited keys. I added this to set a default permission preset:and it removed the
presetstable the base bundle had set. I caught it by composing the layers: the row came back as just{defaultPreset: ...}, with nopresetsat all, so "Read Only" was gone from the composition (the composer picker is rendered from that table). To keep it correct I now have to restate the entire table — in every profile that overrides the row.Same shape for the default model: pointing
agent-default-modelat my gateway means restating every key the base layer set, and repeating that in each profile.3. Settings don't travel between profiles, but the desktop README says they do
apps/desktop/README.mdsays the desktop shell "shares sessions, settings, credentials, workspaces, and storage under$DSH_HOMEwith CLI dsh". Sessions, credentials, workspaces and storage do share. Settings do not — they are each profile's owncordis.patch.yml. A model I add in the desktop app simply does not exist inprofiles/web, and no UI anywhere tells you that.Two client package READMEs make the inverse mistake, documenting preferences as persisting to the home patch when they actually land in the profile patch (see #8407).
4. The fallback — hand-editing the file — is worse
Because the GUI can't be used for rows the home patch owns, the obvious workaround is to edit the file. That path is also broken: changing
cordis.patch.ymlwhile DSH is running aborts running sessions mid-turn, and editing a profile patch strips tools from live sessions with nothing in the transcript to explain it (see #8857 and #8635).What I'd like
configwould drop inherited keys — "you set 1 key and this removes 3 set by the base layer" would have caught #2 for me.To be clear, I'm not asking for a redesign of the layer model — the ordering is documented and I can work with it. I'm asking for these failure modes to be visible at the moment they happen instead of turning into silent config loss.
Related
--patchsilently overridden,--dump-configreports the wrong effective value.default()leaves a merged row config unresolvedllm-pi-airoutes while the chat dropdown shows them(Drafted with an AI assistant from my session logs and the discussions linked above.)
All reactions