@graphorin/skills 0.6.1 → 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.
- package/CHANGELOG.md +20 -0
- package/README.md +3 -3
- package/dist/package.js +1 -1
- package/dist/package.js.map +1 -1
- package/package.json +14 -13
- package/src/activation/index.ts +76 -0
- package/src/errors/index.ts +162 -0
- package/src/frontmatter/index.ts +646 -0
- package/src/index.ts +49 -0
- package/src/loader/index.ts +813 -0
- package/src/migration/index.ts +192 -0
- package/src/registry/bridge.ts +169 -0
- package/src/registry/index.ts +414 -0
- package/src/spec/index.ts +158 -0
- package/src/types/index.ts +338 -0
|
@@ -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
|
+
};
|