init
This commit is contained in:
commit
0858862cda
17 files changed
+2189
No files matched your search
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* dsh-facet — the host half.
|
||||
*
|
||||
* A facet session is confined to one module of a multi-faceted system: the
|
||||
* folder the conversation was started in, plus whatever the user has explicitly
|
||||
* granted. This row owns the *policy* — the enforcement mode, the standing
|
||||
* grants, and the live per-session grants — and publishes it as `ctx.facetPolicy`.
|
||||
*
|
||||
* **Why the policy is a host row and the enforcement is not.** The rule that
|
||||
* confines an agent has to hold per agent, so it is mounted inside the `facet`
|
||||
* agent preset; a guard registered on the host plane would confine every session
|
||||
* in the profile, including the ones deliberately working across the whole
|
||||
* system. The *configuration*, though, is a fact about this deployment — one
|
||||
* mode, one set of standing grants — and duplicating it into the preset would
|
||||
* mean two places to edit and two answers to the same question. So the policy is
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import Schema from '@deepseek-ai/schemastery'
|
||||
|
||||
import { createFacetPolicy } from './lib/policy.js'
|
||||
|
||||
export const name = 'dsh-facet'
|
||||
|
||||
/** Every configuration field this plugin exposes. */
|
||||
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'),
|
||||
|
||||
/**
|
||||
* 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([]),
|
||||
|
||||
/** Placement of the invariant rule in the system prompt. */
|
||||
sectionOrder: Schema.number().default(100),
|
||||
|
||||
/** Placement of the per-session binding in the runtime-context snapshot. */
|
||||
contextOrder: Schema.number().default(105),
|
||||
})
|
||||
|
||||
/**
|
||||
* Publish the deployment's facet policy.
|
||||
*
|
||||
* @param {import('@deepseek-ai/cordis').Context} ctx - host context.
|
||||
* @param {object} config - validated {@link Config}.
|
||||
*/
|
||||
export function apply(ctx, config) {
|
||||
const policy = createFacetPolicy(config)
|
||||
|
||||
// A grant belongs to the conversation that asked for it. Without this the map
|
||||
// would grow for the life of the process, and a resumed session id would
|
||||
// inherit a grant nobody remembers making.
|
||||
ctx.on('session/disposed', (session) => {
|
||||
policy.forget(session.id)
|
||||
})
|
||||
|
||||
ctx.provide('facetPolicy', policy)
|
||||
}
|
||||
Reference in new issue
Block a user