@graphorin/skills 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,338 @@
1
+ /**
2
+ * Public types for `@graphorin/skills`.
3
+ *
4
+ * The skills loader exposes a small, stable surface that mirrors the
5
+ * `SKILL.md` packaging format and layers Graphorin-specific
6
+ * extensions on top through the `graphorin-*` namespace.
7
+ *
8
+ * @packageDocumentation
9
+ */
10
+
11
+ import type { ResolvedTool, Tool } from '@graphorin/core';
12
+ import type {
13
+ ResolvedSkillTrustPolicy,
14
+ SkillSignatureVerificationResult,
15
+ SkillTrustLevel,
16
+ SkillSource as SupplyChainSkillSource,
17
+ } from '@graphorin/security/supply-chain';
18
+
19
+ /**
20
+ * Trust level recognised by the skills loader. Extends the
21
+ * supply-chain trust ladder with a third `'unknown'` value the
22
+ * loader uses for skills that have no explicit declaration. The
23
+ * sandbox tier resolver treats `'unknown'` like `'untrusted'`
24
+ * (mandatory `worker-threads + no-net + no-fs`); the supply-chain
25
+ * installer treats it as untrusted EXCEPT that the signature
26
+ * requirement is downgraded from mandatory to optional - signature
27
+ * is a trust upgrade, not a gate (Phase 08 § Risks & mitigations).
28
+ *
29
+ * @stable
30
+ */
31
+ export type SkillsTrustLevel = SkillTrustLevel | 'unknown';
32
+
33
+ /**
34
+ * Conflict-resolution policy used by the frontmatter validator when an
35
+ * Anthropic-base field and the equivalent `graphorin-*` field are both
36
+ * declared.
37
+ *
38
+ * @stable
39
+ */
40
+ export type FrontmatterValidatorPolicy = 'warn' | 'error' | 'silent';
41
+
42
+ /**
43
+ * Policy applied to frontmatter fields that are present but recognised
44
+ * neither by the bundled spec snapshot nor by the `graphorin-*`
45
+ * extension catalogue.
46
+ *
47
+ * @stable
48
+ */
49
+ export type UnknownFieldPolicy = 'preserve' | 'reject' | 'warn';
50
+
51
+ /**
52
+ * Trust level applied to a loaded skill. Mirrors the supply-chain
53
+ * trust ladder + the loader's `'unknown'` extension so callers do
54
+ * not have to bridge two enums.
55
+ *
56
+ * @stable
57
+ */
58
+ export type SkillTrustLevelValue = SkillsTrustLevel;
59
+
60
+ /**
61
+ * Source descriptor for a {@link loadSkills} request.
62
+ *
63
+ * - `'folder'` - load from a directory on disk.
64
+ * - `'npm-package'` - install via the supply-chain installer + load.
65
+ * - `'git-repo'` - shallow-clone via the supply-chain installer +
66
+ * load.
67
+ * - `'inline'` - the caller supplies a parsed skill structure;
68
+ * useful for tests and embedded fixtures.
69
+ *
70
+ * @stable
71
+ */
72
+ export type SkillSource =
73
+ | {
74
+ readonly kind: 'folder';
75
+ readonly path: string;
76
+ /**
77
+ * Operator-supplied trust level. When present it overrides the
78
+ * skill's self-declared `graphorin-trust-level`. Without it, a
79
+ * folder's self-declared `trusted` / `trusted-with-scripts` is
80
+ * capped at `'unknown'` - a downloaded directory cannot promote
81
+ * itself; trust is granted by the integrator, never the artifact.
82
+ */
83
+ readonly trustLevel?: SkillTrustLevel;
84
+ }
85
+ | {
86
+ readonly kind: 'npm-package';
87
+ readonly packageName: string;
88
+ readonly version?: string;
89
+ readonly trustLevel?: SkillTrustLevel;
90
+ }
91
+ | {
92
+ readonly kind: 'git-repo';
93
+ readonly url: string;
94
+ readonly ref?: string;
95
+ readonly trustLevel?: SkillTrustLevel;
96
+ }
97
+ | { readonly kind: 'inline'; readonly skill: InlineSkill };
98
+
99
+ /**
100
+ * Pre-built tool record accepted by the inline source. The loader
101
+ * does not parse the tool - it forwards the record to the agent
102
+ * runtime which feeds it through `stampSkillTool(...)` before
103
+ * registering with `@graphorin/tools`.
104
+ *
105
+ * @stable
106
+ */
107
+ export type InlineSkillTool = Tool;
108
+
109
+ /**
110
+ * Pre-built skill payload accepted by `{ kind: 'inline' }`. Bypasses
111
+ * the file-system loader; useful for tests and bundled defaults.
112
+ *
113
+ * @stable
114
+ */
115
+ export interface InlineSkill {
116
+ readonly skillMd: string;
117
+ readonly basePath?: string;
118
+ readonly resources?: ReadonlyArray<{ readonly path: string; readonly content: string }>;
119
+ /**
120
+ * Pre-built `Tool[]` payload. When supplied, the loader exposes
121
+ * these via {@link Skill.tools} so {@link SkillRegistry.tools}
122
+ * returns them deduplicated by `tool.name`.
123
+ *
124
+ * Folder / npm / git sources do not carry tool implementations -
125
+ * the agent runtime (Phase 12) materialises them from the skill's
126
+ * `tools/` directory. The inline source is the only path through
127
+ * which tests + bundled defaults can ship pre-built tools.
128
+ */
129
+ readonly tools?: ReadonlyArray<InlineSkillTool>;
130
+ }
131
+
132
+ /**
133
+ * Resolution outcome of a single field on a `SKILL.md` frontmatter.
134
+ *
135
+ * @stable
136
+ */
137
+ export interface FieldResolution<T = unknown> {
138
+ readonly value: T | undefined;
139
+ readonly source: 'anthropic-base' | 'metadata-graphorin' | 'graphorin-prefix' | 'fallback';
140
+ readonly conflicting: boolean;
141
+ readonly conflictingSources: ReadonlyArray<string>;
142
+ }
143
+
144
+ /**
145
+ * Diagnostic record produced by the frontmatter validator. Carries a
146
+ * structured `kind` so the loader can surface the diagnostic on a
147
+ * trace span / audit emitter without re-parsing the human message.
148
+ *
149
+ * @stable
150
+ */
151
+ export interface FrontmatterDiagnostic {
152
+ readonly kind:
153
+ | 'conflict'
154
+ | 'experimental-field'
155
+ | 'unknown-field'
156
+ | 'spec-newer-than-loader'
157
+ | 'spec-older-than-loader'
158
+ | 'unsupported-frontmatter'
159
+ | 'invalid-field-type'
160
+ | 'missing-required-field'
161
+ | 'untrusted-handoff-filter-required'
162
+ | 'invalid-runtime-compat';
163
+ readonly field: string;
164
+ readonly severity: 'info' | 'warn' | 'error';
165
+ readonly message: string;
166
+ readonly hint?: string;
167
+ }
168
+
169
+ /**
170
+ * Validated skill metadata. Always available on the registry without
171
+ * loading the body - this is the always-present **Tier 1** payload
172
+ * that the system prompt advertises.
173
+ *
174
+ * @stable
175
+ */
176
+ export interface SkillMetadata {
177
+ readonly name: string;
178
+ readonly description: string;
179
+ readonly license?: string;
180
+ readonly compatibility?: string;
181
+ readonly metadata?: Readonly<Record<string, unknown>>;
182
+ readonly allowedTools?: ReadonlyArray<string>;
183
+ readonly disableModelInvocation: boolean;
184
+ readonly graphorinTrustLevel: SkillsTrustLevel;
185
+ readonly graphorinRuntimeCompat?: string;
186
+ readonly graphorinSensitivity?: string;
187
+ readonly graphorinSensitivityDefaults?: Readonly<Record<string, string>>;
188
+ readonly graphorinSandbox?: Readonly<Record<string, unknown>>;
189
+ readonly graphorinHandoffInputFilter?: HandoffInputFilterDeclaration;
190
+ readonly graphorinSignaturePresent: boolean;
191
+ readonly graphorinAnthropicSpec?: string;
192
+ /** Author-declared graphorin runtime / extension version. */
193
+ readonly graphorinVersion?: string;
194
+ /** Raw frontmatter (read-only) for power users - every loader user can re-derive bespoke fields. */
195
+ readonly raw: Readonly<Record<string, unknown>>;
196
+ }
197
+
198
+ /**
199
+ * `graphorin-handoff-input-filter` declaration recognised by the
200
+ * loader. The runtime resolves the declaration into the actual filter
201
+ * implementation in Phase 12; the loader only validates the shape.
202
+ *
203
+ * @stable
204
+ */
205
+ export type HandoffInputFilterDeclaration =
206
+ | { readonly kind: 'lastUser' }
207
+ | { readonly kind: 'lastN'; readonly n: number }
208
+ | { readonly kind: 'summary' }
209
+ | { readonly kind: 'full' }
210
+ | {
211
+ readonly kind: 'compose';
212
+ readonly steps: ReadonlyArray<HandoffInputFilterStep>;
213
+ };
214
+
215
+ /**
216
+ * Composable step recognised inside `graphorin-handoff-input-filter:
217
+ * { compose: [...] }`. The runtime resolves named steps into actual
218
+ * filter implementations in Phase 12.
219
+ *
220
+ * @stable
221
+ */
222
+ export type HandoffInputFilterStep =
223
+ | { readonly kind: 'lastUser' }
224
+ | { readonly kind: 'lastN'; readonly n: number }
225
+ | { readonly kind: 'summary' }
226
+ | {
227
+ readonly kind: 'stripSensitiveOutputs';
228
+ readonly keepTier?: string;
229
+ }
230
+ | { readonly kind: 'stripReasoning' };
231
+
232
+ /**
233
+ * Tool declaration found inside `graphorin-tools:`. The loader only
234
+ * captures the declarations; the actual `Tool[]` is produced by the
235
+ * skill author's `tools/*.ts` modules and bridged into the
236
+ * `@graphorin/tools` registry by the agent runtime in Phase 12.
237
+ *
238
+ * @stable
239
+ */
240
+ export interface SkillToolDeclaration {
241
+ readonly name: string;
242
+ readonly module?: string;
243
+ readonly description?: string;
244
+ readonly tags?: ReadonlyArray<string>;
245
+ }
246
+
247
+ /**
248
+ * Lazy resource accessor returned by {@link Skill.resources}. The
249
+ * loader does not read the file off disk until `.read()` is invoked.
250
+ *
251
+ * @stable
252
+ */
253
+ export interface SkillResource {
254
+ readonly path: string;
255
+ readonly relativePath: string;
256
+ readonly mediaType?: string;
257
+ read(signal?: AbortSignal): Promise<Uint8Array>;
258
+ readText(signal?: AbortSignal): Promise<string>;
259
+ }
260
+
261
+ /**
262
+ * Loaded skill record returned by {@link SkillRegistry.getSkill} and
263
+ * {@link loadSkills}. Three-tier semantics:
264
+ *
265
+ * - {@link Skill.metadata} - always available (parsed at load time).
266
+ * - {@link Skill.body} - lazy; resolved on first call. Cached for
267
+ * subsequent calls.
268
+ * - {@link Skill.resources} - lazy listing; resource bytes are only
269
+ * read when {@link SkillResource.read} is invoked.
270
+ * - {@link Skill.tools} - derived from the `graphorin-tools`
271
+ * declarations; the actual `Tool[]` is materialised by the agent
272
+ * runtime through the `@graphorin/tools` registry.
273
+ *
274
+ * @stable
275
+ */
276
+ export interface Skill {
277
+ readonly metadata: SkillMetadata;
278
+ readonly source: SkillSource;
279
+ readonly basePath?: string;
280
+ readonly trustPolicy: ResolvedSkillTrustPolicy;
281
+ readonly signature?: SkillSignatureVerificationResult;
282
+ body(signal?: AbortSignal): Promise<string>;
283
+ resources(signal?: AbortSignal): Promise<ReadonlyArray<SkillResource>>;
284
+ /**
285
+ * Pre-built tools shipped with the skill. The inline source is the
286
+ * only path through which the loader carries actual `Tool[]`
287
+ * records; folder / npm / git sources return `[]` here and the
288
+ * agent runtime (Phase 12) materialises tools from the
289
+ * `graphorin-tools` declarations + the skill's `tools/` directory.
290
+ */
291
+ tools(): ReadonlyArray<InlineSkillTool>;
292
+ toolDeclarations(): ReadonlyArray<SkillToolDeclaration>;
293
+ diagnostics(): ReadonlyArray<FrontmatterDiagnostic>;
294
+ }
295
+
296
+ /**
297
+ * Activated skill - what the agent runtime sees after the model (or a
298
+ * slash command) elects a skill. Carries the loaded body + declared
299
+ * tools so the runtime can inject them into the conversation.
300
+ *
301
+ * @stable
302
+ */
303
+ export interface ActivatedSkill {
304
+ readonly skill: Skill;
305
+ readonly body: string;
306
+ readonly resources: ReadonlyArray<SkillResource>;
307
+ /**
308
+ * Tools made available to the model while the skill is active.
309
+ * The agent runtime (Phase 12) is the canonical producer - it
310
+ * resolves the skill's `tools/` directory or the inline-supplied
311
+ * `Tool[]` and feeds each entry through `stampSkillTool(...)` so
312
+ * the resulting `ResolvedTool` carries the right trust class +
313
+ * sandbox tier.
314
+ */
315
+ readonly tools: ReadonlyArray<ResolvedTool>;
316
+ readonly activationKind: 'auto' | 'slash-command' | 'explicit';
317
+ readonly activatedAt: number;
318
+ }
319
+
320
+ /**
321
+ * Result of {@link parseSlashCommand}. The loader parses
322
+ * `/skill:<name>` and `/skill:<name> <free-form-args>` into a
323
+ * structured payload the agent runtime consumes.
324
+ *
325
+ * @stable
326
+ */
327
+ export interface SlashCommandActivation {
328
+ readonly name: string;
329
+ readonly args: string;
330
+ readonly raw: string;
331
+ }
332
+
333
+ export type {
334
+ ResolvedSkillTrustPolicy,
335
+ SkillSignatureVerificationResult,
336
+ SkillTrustLevel,
337
+ SupplyChainSkillSource,
338
+ };