fix: show the settings card, and make an edit actually take effect
`mode` and `extraRoots` carried no `volatile()` marker, so the framework's
form projection dropped the whole entry from `settings.describe` and the plugin
had no card under Plugins at all. The marker is what creates the card.
It is also what turns each field into a reference rather than a value: the
resolved config hands `apply` a `{get(), [write]}` per volatile field, which is
how a settings write lands in a running plugin without re-applying it. So the
policy and the guard now read both fields at the point of use instead of
snapshotting them at mount, and `sectionOrder`/`contextOrder` stay unmarked
because a prompt section cannot be re-ordered without a remount.
A section is also registered once as a plain string, so the rule could not
follow a live `mode` without freezing at load. The mode-specific sentence moved
into the binding, which is a callback.
This commit is contained in:
1 parent
c41c555400
commit
28f20a8aac
8 files changed
+283
-59
No files matched your search
@@ -16,10 +16,12 @@
|
||||
* published once here and consumed there, which is also why the preset can be
|
||||
* swapped without touching any of this.
|
||||
*
|
||||
* There is deliberately no `settings` namespace. A facet grant is a statement
|
||||
* about one conversation, so the only thing worth persisting is the deployment's
|
||||
* standing grants, and those belong in the profile patch — the layer where this
|
||||
* machine's facts already live.
|
||||
* There is deliberately no `settings` *namespace* of our own: a facet grant is a
|
||||
* statement about one conversation, so the only thing worth persisting is the
|
||||
* deployment's standing grants, and those belong in the profile patch — the
|
||||
* layer where this machine's facts already live. What the framework projects
|
||||
* onto this row is the {@link Config} schema below, which is the same patch
|
||||
* layer reached through the Web UI rather than a second place to store things.
|
||||
*/
|
||||
|
||||
import Schema from '@deepseek-ai/schemastery'
|
||||
@@ -28,21 +30,42 @@ import { createFacetPolicy } from './lib/policy.js'
|
||||
|
||||
export const name = 'dsh-facet'
|
||||
|
||||
/** Every configuration field this plugin exposes. */
|
||||
/**
|
||||
* Every configuration field this plugin exposes.
|
||||
*
|
||||
* `mode` and `extraRoots` are marked `volatile()`, and that marker is doing two
|
||||
* jobs rather than one. It is what puts them on the settings page at all — the
|
||||
* framework's form projection keeps only fields under a volatile ancestor, and
|
||||
* drops an entry with no such field from `settings.describe` entirely, so
|
||||
* without it this row has no card. It is also what makes an edit *live*: a
|
||||
* volatile field is handed to {@link apply} as a reference rather than a value,
|
||||
* and the framework commits an edit into that reference without re-applying the
|
||||
* plugin.
|
||||
*
|
||||
* The second job is why every reader of these two fields goes through
|
||||
* `configValue()` in `./lib/policy.js` and reads at the point of use. A plugin
|
||||
* that takes the reference for a string gets a settings card that appears to
|
||||
* work and changes nothing.
|
||||
*
|
||||
* `sectionOrder` and `contextOrder` are deliberately NOT volatile. They place
|
||||
* the rule and the binding among the other prompt sections, which is settled
|
||||
* once at load; making them volatile would put two knobs nobody should touch on
|
||||
* the card, and a section cannot be re-ordered without a remount anyway.
|
||||
*/
|
||||
export const Config = Schema.object({
|
||||
/**
|
||||
* How a call outside the facet is handled. `ask` questions the user, `deny`
|
||||
* refuses outright, `off` disables enforcement while leaving the preset in
|
||||
* place — useful for telling a scoping problem from an unrelated one.
|
||||
*/
|
||||
mode: Schema.union(['ask', 'deny', 'off']).default('ask'),
|
||||
mode: Schema.union(['ask', 'deny', 'off']).default('ask').volatile(),
|
||||
|
||||
/**
|
||||
* Paths always in scope, for code a module legitimately depends on — shared
|
||||
* types, a common test harness. Relative paths resolve against each session's
|
||||
* own directory, so the same list is meaningful in every workspace.
|
||||
*/
|
||||
extraRoots: Schema.array(String).default([]),
|
||||
extraRoots: Schema.array(String).default([]).volatile(),
|
||||
|
||||
/** Placement of the invariant rule in the system prompt. */
|
||||
sectionOrder: Schema.number().default(100),
|
||||
|
||||
Reference in new issue
Block a user