/** * User-facing permission presets over the independent sandbox-mode and * approval-policy knobs. A switch records the selected preset, then writes * changed knobs through their canonical setters. Execution, prompt narration, * and replay keep reading their knob folds. The preset event preserves user * intent when two presets share a bundle. The read side ships as the * `permissions` session projection; the write side ships as the * `/permission` command — both optional children over the same service. * * @module dsh-permission-presets */ import { Context, Service } from '@deepseek-ai/cordis'; import z from '@deepseek-ai/schemastery'; import type { Session, SessionEvent } from '@deepseek-ai/dsh-session'; import type { SandboxMode } from '@deepseek-ai/dsh-sandbox'; import type { ApprovalPolicy } from '@deepseek-ai/dsh-user-approval'; import type { PermissionSelect, PresetOption } from './types.ts'; export type * from './types.ts'; declare module '@deepseek-ai/cordis' { interface Context { permissionPresets: PermissionPresetService; } } declare module '@deepseek-ai/dsh-session/types' { interface SessionEventMap { /** * Records the selected preset as durable, log-only user intent. The knob * events follow in the same turn and control execution; this event stays * out of the model transcript and lets {@link effectivePermissionPreset} * preserve a selection when bundles match. */ 'permission/preset': { preset: string; }; } } /** One preset's sandbox/approval bundle and optional client presentation. */ export interface PresetSpec { /** The `sandbox/mode` value the preset writes through. */ sandbox: SandboxMode; /** The `approval/policy` value the preset writes through. */ approval: ApprovalPolicy; /** The display label a client shows for this preset; the raw table key when omitted. */ name?: string; /** One user-facing sentence on what the preset means; omitted when not configured. */ description?: string; } /** * Returned when effective knob values match no table entry. Clients may show * it as the current value, but it is never a switch target or event payload. */ export declare const CUSTOM_PRESET = "custom"; /** Settings namespace carrying the default for future sessions. */ export declare const PERMISSION_SETTINGS_NAMESPACE: import("@deepseek-ai/dsh-settings").SettingsNamespace; /** * Fold the last selected preset from the durable log; replay needs no catch-up * state. * @param events - session events in log order; other event types are ignored. * @returns the last selected preset, or undefined when none was recorded. */ export declare function effectivePermissionPreset(events: readonly SessionEvent[]): string | undefined; /** * The projection unit's state: the last seen value of each knob event, null * before an override (composition defaults apply at view time). Plain JSON * (persisted-cache precondition). */ export interface KnobState { /** Last `permission/preset` payload, or null. */ preset: string | null; /** Last `sandbox/mode` payload, or null. */ sandbox: SandboxMode | null; /** Last `approval/policy` payload, or null. */ approval: ApprovalPolicy | null; } /** * One-event knob transition (the projection unit's `apply`). Uninterested * events return the same reference — the registry's change gate. * @param state - the folded knob state before `event`. * @param event - one committed session event. * @returns the next state; the same reference when the event is not a knob. */ export declare function applyKnobEvent(state: KnobState, event: SessionEvent): KnobState; /** User setting resolved when a new session receives its initial permission. */ export interface PermissionSettings { /** Preset pinned into a newly created session. */ defaultPreset: string; } /** The {@link PermissionPresetService} config: preset table and composition default. */ export interface Config { /** * The preset table: name → knob bundle. Defaults to `workspace-write` * (workspace-write + ask) and `danger-full-access` (danger-full-access + * never). The name `custom` is reserved for the derived not-a-preset state. */ presets?: Record; /** * Default for new sessions. When omitted, the preset matching the composed * sandbox and approval defaults is used. */ defaultPreset?: string; } /** * Owns the deployment's permission presets and their write path. Requires a * confining `ctx.shell` executor and `ctx.approval`; unmatched knob values are * reported as {@link CUSTOM_PRESET}, not an error. */ export declare class PermissionPresetService extends Service { static Config: z; static inject: string[]; private readonly presets; private defaultSettings; constructor(ctx: Context, config: Config); /** * The advertised preset names, in the preset table's declaration order. * @returns every switchable preset name. */ get names(): readonly string[]; /** * The preset currently selected as the default for future sessions. * @returns the resolved settings value, or the composition default without * a mounted settings provider. */ get defaultPreset(): string; /** * Resolve the preset matching the effective knob values. A still-matching * last selection wins shared-bundle ties; otherwise the first table match * wins, or {@link CUSTOM_PRESET} when no entry matches. * @param events - the session's events in log order. * @returns the effective preset name, or `custom` when nothing matches. */ current(events: readonly SessionEvent[]): string; /** Resolve the preset for one folded knob state (the shared mathematics of `current` and the projection unit). */ private derive; /** * Build the whole select value for one folded knob state: every table * option in declaration order, `custom` appended exactly while derived. * @param state - the folded knob overrides. * @returns the `permissions` projection payload. */ selectFor(state: KnobState): PermissionSelect; /** * Resolve a preset's knob bundle. * @param name - the preset name to resolve. * @returns the configured bundle. * @throws when `name` is not in the table. */ resolve(name: string): PresetSpec; /** * Build the client option for a table entry or {@link CUSTOM_PRESET}. A * missing label falls back to the table key. * @param name - a table key, or `custom`. * @returns the option a client renders. * @throws when `name` is neither a table key nor `custom`. */ optionOf(name: string): PresetOption; /** * Record a changed preset, then update each changed knob through its own * setter. Selecting the effective preset again appends nothing. * @param session - the session the switch belongs to. * @param name - the preset to switch to; unknown names throw. */ set(session: Session, name: string): void; /** Apply one preset with the caller-selected live or initialization policy writer. */ private apply; /** * Fill every missing permission fact before a session is published. A * genuinely fresh session uses the current user default; seeded or partially * initialized sessions preserve their effective knob values and only gain * the missing durable facts. */ private pinInitialPermission; } export default PermissionPresetService; //# sourceMappingURL=index.d.ts.map