| 1 | /** Agent-preset vocabulary shared by discovery, mounting, and consumers. */ |
| 2 | |
| 3 | /** |
| 4 | * Where a preset's composition came from. A `system` preset ships with the |
| 5 | * deployment; a `user` preset was authored locally, by a person or by an |
| 6 | * agent, and therefore carries the same trust as shell access. |
| 7 | */ |
| 8 | export type PresetTrust = 'system' | 'user' |
| 9 | |
| 10 | /** |
| 11 | * Ids a preset directory may use. |
| 12 | * |
| 13 | * The id becomes a path segment, so this is a containment boundary rather than |
| 14 | * a style rule: `..`, a separator, or an absolute-looking name would place the |
| 15 | * composition outside the root the deployment authorised. Discovery shares it: |
| 16 | * a directory whose name no copy could ever claim is not a preset slot. |
| 17 | */ |
| 18 | export const PRESET_ID = /^[a-z0-9][a-z0-9-]*$/ |
| 19 | |
| 20 | /** One preset directory that carries a mountable agent composition. */ |
| 21 | export interface AgentPreset { |
| 22 | /** Stable identifier; the preset directory's name. */ |
| 23 | readonly id: string |
| 24 | /** Trust recorded from the root this preset was discovered under. */ |
| 25 | readonly trust: PresetTrust |
| 26 | /** Absolute path of the preset's agent composition file. */ |
| 27 | readonly path: string |
| 28 | /** Display name from the preset's own metadata; absent falls back to {@link id}. */ |
| 29 | readonly name?: string |
| 30 | /** One sentence on what this preset is for, when it published one. */ |
| 31 | readonly description?: string |
| 32 | /** Declared position within its group; absent sorts after those that declare one. */ |
| 33 | readonly order?: number |
| 34 | /** |
| 35 | * Why this preset cannot compose a session, absent when it can. A broken |
| 36 | * preset stays on the roster — hiding it would leave its directory blocking |
| 37 | * the id with nothing to see or delete — but every mounting path refuses it |
| 38 | * up front with this reason instead of failing deep inside the loader. |
| 39 | */ |
| 40 | readonly broken?: string |
| 41 | } |
| 42 | |
| 43 | /** One directory scanned for preset subdirectories. */ |
| 44 | export interface PresetRoot { |
| 45 | /** Directory holding one subdirectory per preset; a leading `~` expands. */ |
| 46 | path: string |
| 47 | /** Trust recorded on every preset discovered under this root. */ |
| 48 | trust: PresetTrust |
| 49 | } |
| 50 | |
| 51 | /** Plugin config: which preset is the default, and where presets live. */ |
| 52 | export interface Config { |
| 53 | /** Preset id mounted when a caller names none. Missing at mount time fails loud. */ |
| 54 | default: string |
| 55 | /** Scanned roots in precedence order; an earlier root wins a duplicate id. */ |
| 56 | roots: PresetRoot[] |
| 57 | /** |
| 58 | * Prepend this package's bundled shipped presets as a `system` root, before |
| 59 | * every configured root, so the shipped set always mounts and wins a |
| 60 | * duplicate id. The default survives a whole-`config` patch replacement; |
| 61 | * only an explicit `false` — a deployment supplying purely its own presets, |
| 62 | * or an embedder using the roster as bare machinery — drops the set. |
| 63 | */ |
| 64 | includeShippedRoot: boolean |
| 65 | /** |
| 66 | * Append the harness home's `USER_PRESET_DIR` as a `user` root, after every |
| 67 | * configured root. False mounts a roster without the derived writable root. |
| 68 | */ |
| 69 | includeUserRoot: boolean |
| 70 | } |
| 71 |