@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.
- package/CHANGELOG.md +31 -0
- package/README.md +3 -3
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/package.js +6 -0
- package/dist/package.js.map +1 -0
- 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
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# @graphorin/skills
|
|
2
2
|
|
|
3
|
+
## 0.7.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#154](https://github.com/o-stepper/graphorin/pull/154) [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04) Thanks [@o-stepper](https://github.com/o-stepper)! - W-072: every export map's `import` condition becomes `default`, and the Node floor rises to `>=22.12.0`.
|
|
8
|
+
|
|
9
|
+
CJS consumers previously hit a bewildering `ERR_PACKAGE_PATH_NOT_EXPORTED` instead of a clear ESM-only signal. With the `default` condition, plain `require('@graphorin/core')` works via Node's stable `require(esm)` - which shipped in 22.12, hence the engines bump across every workspace manifest (packages, examples, benchmarks, docs; enforced by the widened mvp-readiness sweep). No dual-instance hazard: there is no CJS build, `require()` returns the same ESM module instance. ESM consumers are unaffected (`default` serves both paths; `types` stays first). The pack gate now runs attw under the full `node16` profile (was `esm-only`) and adds a runtime `require(esm)` smoke against the packed tarballs. Installs on Node 22.0-22.11 with `engine-strict` will refuse - upgrade Node (see the migration guide).
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [#162](https://github.com/o-stepper/graphorin/pull/162) [`73b19ca`](https://github.com/o-stepper/graphorin/commit/73b19caeda388bda628a48138cb7d70b1db839a3) Thanks [@o-stepper](https://github.com/o-stepper)! - Remove phantom workspace dependencies that no source file imports: agent no longer depends on provider and observability, mcp/workflow/server no longer depend on observability, sessions no longer depends on security (and its memory edge moves to devDependencies where the single test import lives), skills no longer depends on tools. Dead tsdown `external` entries for the removed edges are gone too, so a future import can no longer build as external without a declared dependency. Consumer install graphs shrink accordingly; a new repo-wide `check-phantom-deps` CI gate keeps the manifest graph honest from here on.
|
|
14
|
+
|
|
15
|
+
- [#164](https://github.com/o-stepper/graphorin/pull/164) [`764239b`](https://github.com/o-stepper/graphorin/commit/764239b97e0e0202442e91272583f13adeb12d00) Thanks [@o-stepper](https://github.com/o-stepper)! - Tarballs now ship `src/` so the published `dist/**/*.d.ts.map` files actually work (W-136): the maps referenced `../src/*.ts` that the `files` whitelist excluded, so go-to-definition fell back into `.d.ts` and the shipped maps were dead weight. The pack gate gains a `map-integrity` leg: every source referenced by a shipped map must resolve inside the tarball (or be embedded via `sourcesContent`), with an anti-vacuous guard - a package whose tsdown config emits declaration maps must contain a non-zero number of `.d.ts.map` files, so a cache-restored dist that silently dropped maps fails the gate instead of passing vacuously. `mvp-readiness` now requires `src` in every publishable `files` array.
|
|
16
|
+
|
|
17
|
+
- [#164](https://github.com/o-stepper/graphorin/pull/164) [`764239b`](https://github.com/o-stepper/graphorin/commit/764239b97e0e0202442e91272583f13adeb12d00) Thanks [@o-stepper](https://github.com/o-stepper)! - Every published package now declares its tree-shaking contract via `sideEffects` (W-137): 18 packages audited to a pure module scope get `false`, the CLI declares its bin entry (`["./dist/bin/*"]`), and `@graphorin/security` gets an explicit `true` - its secrets subsystem registers built-in resolvers and the SecretValue caller-context provider at import time, so marking it pure would let bundlers drop those registrations. `mvp-readiness` now fails any publishable manifest without a declared `sideEffects`, closing the drift for future packages.
|
|
18
|
+
|
|
19
|
+
- Updated dependencies [[`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04), [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04), [`832f22e`](https://github.com/o-stepper/graphorin/commit/832f22e570b8c3175c1adeb4c150070cbd131534), [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04), [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04), [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04), [`832f22e`](https://github.com/o-stepper/graphorin/commit/832f22e570b8c3175c1adeb4c150070cbd131534), [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04), [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04), [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04), [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04), [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04), [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04), [`32bbd03`](https://github.com/o-stepper/graphorin/commit/32bbd03b588136a355e4b5ad6ac5e19b36b4d8ab), [`32bbd03`](https://github.com/o-stepper/graphorin/commit/32bbd03b588136a355e4b5ad6ac5e19b36b4d8ab), [`32bbd03`](https://github.com/o-stepper/graphorin/commit/32bbd03b588136a355e4b5ad6ac5e19b36b4d8ab), [`4ee256e`](https://github.com/o-stepper/graphorin/commit/4ee256e30fe9190cef6c48dc6785464757707156), [`4ee256e`](https://github.com/o-stepper/graphorin/commit/4ee256e30fe9190cef6c48dc6785464757707156), [`4ee256e`](https://github.com/o-stepper/graphorin/commit/4ee256e30fe9190cef6c48dc6785464757707156), [`4ee256e`](https://github.com/o-stepper/graphorin/commit/4ee256e30fe9190cef6c48dc6785464757707156), [`32bbd03`](https://github.com/o-stepper/graphorin/commit/32bbd03b588136a355e4b5ad6ac5e19b36b4d8ab), [`32bbd03`](https://github.com/o-stepper/graphorin/commit/32bbd03b588136a355e4b5ad6ac5e19b36b4d8ab), [`764239b`](https://github.com/o-stepper/graphorin/commit/764239b97e0e0202442e91272583f13adeb12d00), [`764239b`](https://github.com/o-stepper/graphorin/commit/764239b97e0e0202442e91272583f13adeb12d00), [`764239b`](https://github.com/o-stepper/graphorin/commit/764239b97e0e0202442e91272583f13adeb12d00), [`764239b`](https://github.com/o-stepper/graphorin/commit/764239b97e0e0202442e91272583f13adeb12d00), [`764239b`](https://github.com/o-stepper/graphorin/commit/764239b97e0e0202442e91272583f13adeb12d00), [`764239b`](https://github.com/o-stepper/graphorin/commit/764239b97e0e0202442e91272583f13adeb12d00), [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04), [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04), [`fe98522`](https://github.com/o-stepper/graphorin/commit/fe98522ce2477c9a7dc09029f9dcfdb1f7c9aa04)]:
|
|
20
|
+
- @graphorin/core@0.7.0
|
|
21
|
+
- @graphorin/security@0.7.0
|
|
22
|
+
|
|
23
|
+
## 0.6.1
|
|
24
|
+
|
|
25
|
+
### Patch Changes
|
|
26
|
+
|
|
27
|
+
- [#142](https://github.com/o-stepper/graphorin/pull/142) [`436d6ca`](https://github.com/o-stepper/graphorin/commit/436d6ca5ebbd16df094e915682d3915c279a8430) Thanks [@o-stepper](https://github.com/o-stepper)! - Version constants and version-bearing strings now derive from each package's manifest at build time (`VERSION = pkg.version`; writer ids, client/server info, OTLP framework attributes, build-info metrics interpolate it). No behavioral change at the current version: the rendered strings are byte-identical. A release bump no longer edits source; the new `check-version-consistency` gate fails any reintroduced hardcoded framework version.
|
|
28
|
+
|
|
29
|
+
- Updated dependencies [[`436d6ca`](https://github.com/o-stepper/graphorin/commit/436d6ca5ebbd16df094e915682d3915c279a8430)]:
|
|
30
|
+
- @graphorin/core@0.6.1
|
|
31
|
+
- @graphorin/security@0.6.1
|
|
32
|
+
- @graphorin/tools@0.6.1
|
|
33
|
+
|
|
3
34
|
## 0.6.0
|
|
4
35
|
|
|
5
36
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -82,7 +82,7 @@ import { loadSkillFromSource, createSkillRegistry } from '@graphorin/skills';
|
|
|
82
82
|
|
|
83
83
|
const skill = await loadSkillFromSource(
|
|
84
84
|
{ kind: 'folder', path: './skills/finance-helper' },
|
|
85
|
-
{ conflictPolicy: 'warn', runtimeVersion: '0.
|
|
85
|
+
{ conflictPolicy: 'warn', runtimeVersion: '0.7.0' },
|
|
86
86
|
);
|
|
87
87
|
|
|
88
88
|
const registry = createSkillRegistry();
|
|
@@ -111,7 +111,7 @@ license: MIT
|
|
|
111
111
|
disable-model-invocation: false
|
|
112
112
|
|
|
113
113
|
# === Graphorin extensions (namespaced) ===
|
|
114
|
-
graphorin-runtime-compat: ^0.
|
|
114
|
+
graphorin-runtime-compat: ^0.7.0
|
|
115
115
|
graphorin-trust-level: trusted
|
|
116
116
|
graphorin-sensitivity: internal
|
|
117
117
|
graphorin-handoff-input-filter: lastUser
|
|
@@ -168,4 +168,4 @@ MIT. Copyright © 2026 Oleksiy Stepurenko.
|
|
|
168
168
|
|
|
169
169
|
---
|
|
170
170
|
|
|
171
|
-
**Project Graphorin** · v0.
|
|
171
|
+
**Project Graphorin** · v0.7.0 · MIT License · © 2026 Oleksiy Stepurenko · <https://github.com/o-stepper/graphorin>
|
package/dist/index.d.ts
CHANGED
|
@@ -45,8 +45,7 @@ import { FieldStability, GraphorinFieldPolicy, GraphorinMappingEntry, KnownField
|
|
|
45
45
|
*
|
|
46
46
|
* @packageDocumentation
|
|
47
47
|
*/
|
|
48
|
-
|
|
49
|
-
declare const VERSION = "0.6.0";
|
|
48
|
+
declare const VERSION: string;
|
|
50
49
|
//#endregion
|
|
51
50
|
export { ActivatedSkill, ActivationRequest, FieldResolution, FieldStability, FrontmatterDiagnostic, FrontmatterValidatorPolicy, GraphorinFieldPolicy, GraphorinMappingEntry, GraphorinSkillsError, GraphorinSkillsErrorKind, HandoffInputFilterDeclaration, HandoffInputFilterStep, InlineSkill, InlineSkillTool, InputFilterRequiredError, KnownFieldEntry, LoadSkillOptions, LoadSkillsOptions, MigrateFrontmatterOptions, MigrationResult, MigrationRewrite, ParsedActivationTrigger, RegisteredToolDeclaration, ResolvedSkillTrustPolicy, Skill, SkillFrontmatterConflictError, SkillLoadError, SkillManifestParseError, SkillMetadata, SkillNameCollisionError, SkillRegistry, SkillRegistryOptions, SkillRequiredFieldMissingError, SkillResource, SkillRuntimeCompatError, SkillSignatureVerificationResult, SkillSource, SkillToolDeclaration, SkillToolStamper, SkillTrustLevel, SkillTrustLevelValue, SkillsTrustLevel, SlashCommandActivation, SlashCommandParseError, SpecSnapshot, SplitSkillMd, StampedSkillTool, SupplyChainSkillSource, UnknownFieldPolicy, VERSION, ValidateFrontmatterOptions, ValidatedFrontmatter, _setSpecSnapshotForTesting, compareAuthorSpecHint, createSkillRegistry, getGraphorinMapping, getKnownField, getSpecSnapshot, isRuntimeCompatSatisfied, isSlashCommand, loadSkillFromSource, loadSkills, migrateFrontmatter, parseActivationTrigger, parseAllowedToolsValue, parseFrontmatterYaml, parseHandoffInputFilter, parseSlashCommand, parseToolsField, requireHandoffInputFilter, resolveSkillField, sortKeysAnthropicFirst, splitSkillMd, stampSkillTool, stampSkillToolFromMetadata, validateFrontmatter };
|
|
52
51
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAuCA;;;;;;;;;;;;;;;;;;;;;;;;cAAa"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { version } from "./package.js";
|
|
1
2
|
import { GraphorinSkillsError, InputFilterRequiredError, SkillFrontmatterConflictError, SkillLoadError, SkillManifestParseError, SkillNameCollisionError, SkillRequiredFieldMissingError, SkillRuntimeCompatError, SlashCommandParseError } from "./errors/index.js";
|
|
2
3
|
import { isSlashCommand, parseSlashCommand } from "./activation/index.js";
|
|
3
4
|
import { _setSpecSnapshotForTesting, compareAuthorSpecHint, getGraphorinMapping, getKnownField, getSpecSnapshot } from "./spec/index.js";
|
|
@@ -43,8 +44,8 @@ import { createSkillRegistry, parseActivationTrigger } from "./registry/index.js
|
|
|
43
44
|
*
|
|
44
45
|
* @packageDocumentation
|
|
45
46
|
*/
|
|
46
|
-
/** Canonical version constant
|
|
47
|
-
const VERSION =
|
|
47
|
+
/** Canonical version constant, derived from `package.json` at build time. */
|
|
48
|
+
const VERSION = version;
|
|
48
49
|
|
|
49
50
|
//#endregion
|
|
50
51
|
export { GraphorinSkillsError, InputFilterRequiredError, SkillFrontmatterConflictError, SkillLoadError, SkillManifestParseError, SkillNameCollisionError, SkillRequiredFieldMissingError, SkillRuntimeCompatError, SlashCommandParseError, VERSION, _setSpecSnapshotForTesting, compareAuthorSpecHint, createSkillRegistry, getGraphorinMapping, getKnownField, getSpecSnapshot, isRuntimeCompatSatisfied, isSlashCommand, loadSkillFromSource, loadSkills, migrateFrontmatter, parseActivationTrigger, parseAllowedToolsValue, parseFrontmatterYaml, parseHandoffInputFilter, parseSlashCommand, parseToolsField, requireHandoffInputFilter, resolveSkillField, sortKeysAnthropicFirst, splitSkillMd, stampSkillTool, stampSkillToolFromMetadata, validateFrontmatter };
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * `@graphorin/skills` - skills surface for the Graphorin framework.\n *\n * The package owns:\n *\n * - `SKILL.md` loader with three-tier progressive disclosure\n * (metadata always available; body and resources lazy-loaded).\n * - Frontmatter validator implementing the field-resolution\n * algorithm and conflict policy from ADR-043.\n * - Bundled snapshot of the publicly published `SKILL.md` packaging-\n * format specification + the framework-specific extension\n * catalogue.\n * - Slash-command parser (`/skill:<name>`) + auto-activation\n * metadata generator.\n * - `SkillRegistry` with name-collision detection, activation\n * resolution, and a typed tool-declaration surface the agent\n * runtime bridges into the `@graphorin/tools` registry.\n * - Idempotent `migrateFrontmatter` library that rewrites legacy\n * `graphorin-*` fields onto their upstream equivalents per the\n * bundled mapping table.\n *\n * Stable sub-paths:\n *\n * ```ts\n * import { loadSkills, loadSkillFromSource } from '@graphorin/skills/loader';\n * import { createSkillRegistry } from '@graphorin/skills/registry';\n * import { validateFrontmatter, resolveSkillField } from '@graphorin/skills/frontmatter';\n * import { migrateFrontmatter } from '@graphorin/skills/migration';\n * import { parseSlashCommand } from '@graphorin/skills/activation';\n * import { getSpecSnapshot, getKnownField } from '@graphorin/skills/spec';\n * import { SkillFrontmatterConflictError } from '@graphorin/skills/errors';\n * ```\n *\n * @packageDocumentation\n */\n\n/** Canonical version constant
|
|
1
|
+
{"version":3,"file":"index.js","names":["VERSION: string","pkg.version"],"sources":["../src/index.ts"],"sourcesContent":["/**\n * `@graphorin/skills` - skills surface for the Graphorin framework.\n *\n * The package owns:\n *\n * - `SKILL.md` loader with three-tier progressive disclosure\n * (metadata always available; body and resources lazy-loaded).\n * - Frontmatter validator implementing the field-resolution\n * algorithm and conflict policy from ADR-043.\n * - Bundled snapshot of the publicly published `SKILL.md` packaging-\n * format specification + the framework-specific extension\n * catalogue.\n * - Slash-command parser (`/skill:<name>`) + auto-activation\n * metadata generator.\n * - `SkillRegistry` with name-collision detection, activation\n * resolution, and a typed tool-declaration surface the agent\n * runtime bridges into the `@graphorin/tools` registry.\n * - Idempotent `migrateFrontmatter` library that rewrites legacy\n * `graphorin-*` fields onto their upstream equivalents per the\n * bundled mapping table.\n *\n * Stable sub-paths:\n *\n * ```ts\n * import { loadSkills, loadSkillFromSource } from '@graphorin/skills/loader';\n * import { createSkillRegistry } from '@graphorin/skills/registry';\n * import { validateFrontmatter, resolveSkillField } from '@graphorin/skills/frontmatter';\n * import { migrateFrontmatter } from '@graphorin/skills/migration';\n * import { parseSlashCommand } from '@graphorin/skills/activation';\n * import { getSpecSnapshot, getKnownField } from '@graphorin/skills/spec';\n * import { SkillFrontmatterConflictError } from '@graphorin/skills/errors';\n * ```\n *\n * @packageDocumentation\n */\n\n/** Canonical version constant, derived from `package.json` at build time. */\nimport pkg from '../package.json' with { type: 'json' };\n\nexport const VERSION: string = pkg.version;\n\nexport * from './activation/index.js';\nexport * from './errors/index.js';\nexport * from './frontmatter/index.js';\nexport * from './loader/index.js';\nexport * from './migration/index.js';\nexport * from './registry/index.js';\nexport * from './spec/index.js';\nexport * from './types/index.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCA,MAAaA,UAAkBC"}
|
package/dist/package.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package.js","names":[],"sources":["../package.json"],"sourcesContent":["{\n \"name\": \"@graphorin/skills\",\n \"version\": \"0.7.0\",\n \"description\": \"Skills surface for the Graphorin framework: loader for the SKILL.md packaging format with three-tier progressive disclosure (metadata / body / resources), frontmatter validator implementing the field-resolution algorithm and conflict policy from ADR-043, registry with auto-activation + slash-command activation, supply-chain hardening (signature verification + `--ignore-scripts` enforcement via @graphorin/security), sandbox-tier propagation for untrusted skills, handoff input-filter declaration recognition, and idempotent migrate-frontmatter library.\",\n \"license\": \"MIT\",\n \"author\": \"Oleksiy Stepurenko\",\n \"homepage\": \"https://github.com/o-stepper/graphorin/tree/main/packages/skills\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/o-stepper/graphorin.git\",\n \"directory\": \"packages/skills\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/o-stepper/graphorin/issues\"\n },\n \"keywords\": [\n \"graphorin\",\n \"ai\",\n \"agents\",\n \"framework\",\n \"skills\",\n \"skill-loader\",\n \"skill-registry\",\n \"frontmatter\",\n \"yaml\",\n \"progressive-disclosure\",\n \"supply-chain\",\n \"sandbox\",\n \"ed25519\",\n \"signature-verification\",\n \"migration\"\n ],\n \"type\": \"module\",\n \"sideEffects\": false,\n \"engines\": {\n \"node\": \">=22.12.0\"\n },\n \"main\": \"./dist/index.js\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n },\n \"./loader\": {\n \"types\": \"./dist/loader/index.d.ts\",\n \"default\": \"./dist/loader/index.js\"\n },\n \"./registry\": {\n \"types\": \"./dist/registry/index.d.ts\",\n \"default\": \"./dist/registry/index.js\"\n },\n \"./frontmatter\": {\n \"types\": \"./dist/frontmatter/index.d.ts\",\n \"default\": \"./dist/frontmatter/index.js\"\n },\n \"./migration\": {\n \"types\": \"./dist/migration/index.d.ts\",\n \"default\": \"./dist/migration/index.js\"\n },\n \"./spec\": {\n \"types\": \"./dist/spec/index.d.ts\",\n \"default\": \"./dist/spec/index.js\"\n },\n \"./activation\": {\n \"types\": \"./dist/activation/index.d.ts\",\n \"default\": \"./dist/activation/index.js\"\n },\n \"./errors\": {\n \"types\": \"./dist/errors/index.d.ts\",\n \"default\": \"./dist/errors/index.js\"\n },\n \"./anthropic-spec-snapshot.json\": \"./anthropic-spec-snapshot.json\",\n \"./package.json\": \"./package.json\"\n },\n \"files\": [\n \"dist\",\n \"src\",\n \"anthropic-spec-snapshot.json\",\n \"README.md\",\n \"CHANGELOG.md\",\n \"LICENSE\"\n ],\n \"scripts\": {\n \"build\": \"tsdown\",\n \"typecheck\": \"tsc --noEmit && tsc -p tsconfig.tests.json\",\n \"test\": \"vitest run\",\n \"lint\": \"biome check .\",\n \"clean\": \"rimraf dist .turbo *.tsbuildinfo\"\n },\n \"dependencies\": {\n \"@graphorin/core\": \"workspace:*\",\n \"@graphorin/security\": \"workspace:*\",\n \"yaml\": \"^2.8.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\",\n \"provenance\": true\n },\n \"devDependencies\": {\n \"fast-check\": \"^3.23.0\",\n \"zod\": \"^3.25.0\"\n }\n}\n"],"mappings":";cAEa"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphorin/skills",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Skills surface for the Graphorin framework: loader for the SKILL.md packaging format with three-tier progressive disclosure (metadata / body / resources), frontmatter validator implementing the field-resolution algorithm and conflict policy from ADR-043, registry with auto-activation + slash-command activation, supply-chain hardening (signature verification + `--ignore-scripts` enforcement via @graphorin/security), sandbox-tier propagation for untrusted skills, handoff input-filter declaration recognition, and idempotent migrate-frontmatter library.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Oleksiy Stepurenko",
|
|
@@ -31,8 +31,9 @@
|
|
|
31
31
|
"migration"
|
|
32
32
|
],
|
|
33
33
|
"type": "module",
|
|
34
|
+
"sideEffects": false,
|
|
34
35
|
"engines": {
|
|
35
|
-
"node": ">=22.
|
|
36
|
+
"node": ">=22.12.0"
|
|
36
37
|
},
|
|
37
38
|
"main": "./dist/index.js",
|
|
38
39
|
"module": "./dist/index.js",
|
|
@@ -40,41 +41,42 @@
|
|
|
40
41
|
"exports": {
|
|
41
42
|
".": {
|
|
42
43
|
"types": "./dist/index.d.ts",
|
|
43
|
-
"
|
|
44
|
+
"default": "./dist/index.js"
|
|
44
45
|
},
|
|
45
46
|
"./loader": {
|
|
46
47
|
"types": "./dist/loader/index.d.ts",
|
|
47
|
-
"
|
|
48
|
+
"default": "./dist/loader/index.js"
|
|
48
49
|
},
|
|
49
50
|
"./registry": {
|
|
50
51
|
"types": "./dist/registry/index.d.ts",
|
|
51
|
-
"
|
|
52
|
+
"default": "./dist/registry/index.js"
|
|
52
53
|
},
|
|
53
54
|
"./frontmatter": {
|
|
54
55
|
"types": "./dist/frontmatter/index.d.ts",
|
|
55
|
-
"
|
|
56
|
+
"default": "./dist/frontmatter/index.js"
|
|
56
57
|
},
|
|
57
58
|
"./migration": {
|
|
58
59
|
"types": "./dist/migration/index.d.ts",
|
|
59
|
-
"
|
|
60
|
+
"default": "./dist/migration/index.js"
|
|
60
61
|
},
|
|
61
62
|
"./spec": {
|
|
62
63
|
"types": "./dist/spec/index.d.ts",
|
|
63
|
-
"
|
|
64
|
+
"default": "./dist/spec/index.js"
|
|
64
65
|
},
|
|
65
66
|
"./activation": {
|
|
66
67
|
"types": "./dist/activation/index.d.ts",
|
|
67
|
-
"
|
|
68
|
+
"default": "./dist/activation/index.js"
|
|
68
69
|
},
|
|
69
70
|
"./errors": {
|
|
70
71
|
"types": "./dist/errors/index.d.ts",
|
|
71
|
-
"
|
|
72
|
+
"default": "./dist/errors/index.js"
|
|
72
73
|
},
|
|
73
74
|
"./anthropic-spec-snapshot.json": "./anthropic-spec-snapshot.json",
|
|
74
75
|
"./package.json": "./package.json"
|
|
75
76
|
},
|
|
76
77
|
"files": [
|
|
77
78
|
"dist",
|
|
79
|
+
"src",
|
|
78
80
|
"anthropic-spec-snapshot.json",
|
|
79
81
|
"README.md",
|
|
80
82
|
"CHANGELOG.md",
|
|
@@ -82,9 +84,8 @@
|
|
|
82
84
|
],
|
|
83
85
|
"dependencies": {
|
|
84
86
|
"yaml": "^2.8.0",
|
|
85
|
-
"@graphorin/core": "0.
|
|
86
|
-
"@graphorin/security": "0.
|
|
87
|
-
"@graphorin/tools": "0.6.0"
|
|
87
|
+
"@graphorin/core": "0.7.0",
|
|
88
|
+
"@graphorin/security": "0.7.0"
|
|
88
89
|
},
|
|
89
90
|
"publishConfig": {
|
|
90
91
|
"access": "public",
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Activation surface for `@graphorin/skills`.
|
|
3
|
+
*
|
|
4
|
+
* Two activation paths are supported per DEC-206:
|
|
5
|
+
*
|
|
6
|
+
* 1. **Auto** - every step the agent runtime injects the metadata of
|
|
7
|
+
* every registered skill into the system prompt; the model elects
|
|
8
|
+
* a skill by invoking the synthetic `activate_skill(name)` tool.
|
|
9
|
+
* Skills with `disable-model-invocation: true` are excluded from
|
|
10
|
+
* the metadata advertisement so the model never sees them.
|
|
11
|
+
* 2. **Slash command** - the user types `/skill:<name>` (optionally
|
|
12
|
+
* followed by free-form arguments) and the agent runtime activates
|
|
13
|
+
* the matched skill regardless of `disable-model-invocation`.
|
|
14
|
+
*
|
|
15
|
+
* The runtime owns the actual activation; this module only parses the
|
|
16
|
+
* inputs into a structured payload.
|
|
17
|
+
*
|
|
18
|
+
* @packageDocumentation
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { SlashCommandParseError } from '../errors/index.js';
|
|
22
|
+
import type { SlashCommandActivation } from '../types/index.js';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Parse a single message body for a `/skill:<name>` invocation. The
|
|
26
|
+
* grammar accepts:
|
|
27
|
+
*
|
|
28
|
+
* ```
|
|
29
|
+
* /skill:<name>
|
|
30
|
+
* /skill:<name> <free-form-args>
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* `<name>` must match `^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$` (kebab-case
|
|
34
|
+
* conventional). Whitespace before the leading `/` is tolerated; any
|
|
35
|
+
* other prefix triggers a {@link SlashCommandParseError}.
|
|
36
|
+
*
|
|
37
|
+
* @stable
|
|
38
|
+
*/
|
|
39
|
+
export function parseSlashCommand(raw: string): SlashCommandActivation {
|
|
40
|
+
if (typeof raw !== 'string' || raw.length === 0) {
|
|
41
|
+
throw new SlashCommandParseError(raw ?? '', 'message body must be a non-empty string.');
|
|
42
|
+
}
|
|
43
|
+
const trimmed = raw.replace(/^\s+/u, '');
|
|
44
|
+
if (!trimmed.startsWith('/skill:')) {
|
|
45
|
+
throw new SlashCommandParseError(raw, "message must begin with '/skill:'.");
|
|
46
|
+
}
|
|
47
|
+
const remainder = trimmed.slice('/skill:'.length);
|
|
48
|
+
if (remainder.length === 0) {
|
|
49
|
+
throw new SlashCommandParseError(raw, "missing skill name after '/skill:'.");
|
|
50
|
+
}
|
|
51
|
+
const match = /^([A-Za-z0-9][A-Za-z0-9_.-]{0,127})(?:\s+([\s\S]*))?$/u.exec(remainder);
|
|
52
|
+
if (match === null) {
|
|
53
|
+
throw new SlashCommandParseError(
|
|
54
|
+
raw,
|
|
55
|
+
'skill name must match /^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$/.',
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
const name = match[1] ?? '';
|
|
59
|
+
const args = (match[2] ?? '').trim();
|
|
60
|
+
return Object.freeze({ name, args, raw });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Convenience predicate. Returns `true` when {@link parseSlashCommand}
|
|
65
|
+
* would succeed against the supplied body.
|
|
66
|
+
*
|
|
67
|
+
* @stable
|
|
68
|
+
*/
|
|
69
|
+
export function isSlashCommand(raw: string): boolean {
|
|
70
|
+
try {
|
|
71
|
+
parseSlashCommand(raw);
|
|
72
|
+
return true;
|
|
73
|
+
} catch {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed error hierarchy for `@graphorin/skills`.
|
|
3
|
+
*
|
|
4
|
+
* Every error carries a stable lowercase `kind` discriminator so the
|
|
5
|
+
* agent runtime, the CLI, and the audit emitter can branch without
|
|
6
|
+
* resorting to `instanceof` chains, plus an optional `hint` field with
|
|
7
|
+
* an actionable remediation step (a CLI command or a documentation
|
|
8
|
+
* link).
|
|
9
|
+
*
|
|
10
|
+
* @packageDocumentation
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** Base class for every error thrown by `@graphorin/skills`. */
|
|
14
|
+
export abstract class GraphorinSkillsError extends Error {
|
|
15
|
+
abstract readonly kind: string;
|
|
16
|
+
readonly hint?: string;
|
|
17
|
+
override readonly cause?: unknown;
|
|
18
|
+
constructor(message: string, options?: { hint?: string; cause?: unknown }) {
|
|
19
|
+
super(message);
|
|
20
|
+
this.name = new.target.name;
|
|
21
|
+
if (options?.hint !== undefined) this.hint = options.hint;
|
|
22
|
+
if (options?.cause !== undefined) this.cause = options.cause;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The frontmatter validator detected an Anthropic-base / `graphorin-*`
|
|
28
|
+
* collision and the operator-resolved policy is `'error'`.
|
|
29
|
+
*/
|
|
30
|
+
export class SkillFrontmatterConflictError extends GraphorinSkillsError {
|
|
31
|
+
readonly kind = 'frontmatter:conflict' as const;
|
|
32
|
+
readonly skillName: string;
|
|
33
|
+
readonly field: string;
|
|
34
|
+
readonly conflictingFields: ReadonlyArray<string>;
|
|
35
|
+
constructor(
|
|
36
|
+
skillName: string,
|
|
37
|
+
field: string,
|
|
38
|
+
conflictingFields: ReadonlyArray<string>,
|
|
39
|
+
options?: { hint?: string },
|
|
40
|
+
) {
|
|
41
|
+
super(
|
|
42
|
+
`Skill '${skillName}' frontmatter conflict on '${field}' (also set: ${conflictingFields
|
|
43
|
+
.filter((f) => f !== field)
|
|
44
|
+
.join(', ')}). Validator policy: 'error'.`,
|
|
45
|
+
options,
|
|
46
|
+
);
|
|
47
|
+
this.skillName = skillName;
|
|
48
|
+
this.field = field;
|
|
49
|
+
this.conflictingFields = conflictingFields;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** A skill manifest could not be parsed (missing frontmatter / invalid YAML). */
|
|
54
|
+
export class SkillManifestParseError extends GraphorinSkillsError {
|
|
55
|
+
readonly kind = 'manifest:parse' as const;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The runtime-compat declaration on a skill does not satisfy the
|
|
60
|
+
* loader's installed runtime version.
|
|
61
|
+
*/
|
|
62
|
+
export class SkillRuntimeCompatError extends GraphorinSkillsError {
|
|
63
|
+
readonly kind = 'runtime-compat:mismatch' as const;
|
|
64
|
+
readonly skillName: string;
|
|
65
|
+
readonly declared: string;
|
|
66
|
+
readonly installed: string;
|
|
67
|
+
constructor(skillName: string, declared: string, installed: string, options?: { hint?: string }) {
|
|
68
|
+
super(
|
|
69
|
+
`Skill '${skillName}' declares runtime-compat '${declared}' which does not match installed Graphorin '${installed}'.`,
|
|
70
|
+
options,
|
|
71
|
+
);
|
|
72
|
+
this.skillName = skillName;
|
|
73
|
+
this.declared = declared;
|
|
74
|
+
this.installed = installed;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** A required Anthropic-base field is missing from the frontmatter. */
|
|
79
|
+
export class SkillRequiredFieldMissingError extends GraphorinSkillsError {
|
|
80
|
+
readonly kind = 'frontmatter:missing-required' as const;
|
|
81
|
+
readonly field: string;
|
|
82
|
+
constructor(field: string, options?: { hint?: string }) {
|
|
83
|
+
super(`Skill frontmatter is missing required field '${field}'.`, options);
|
|
84
|
+
this.field = field;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* `Agent.toTool()` / `handoff(...)` would be invoked inside an
|
|
90
|
+
* untrusted skill, but the skill did not declare
|
|
91
|
+
* `graphorin-handoff-input-filter`. Throwing the error at activation
|
|
92
|
+
* time prevents the runtime from materialising a sub-agent without an
|
|
93
|
+
* explicit filter.
|
|
94
|
+
*/
|
|
95
|
+
export class InputFilterRequiredError extends GraphorinSkillsError {
|
|
96
|
+
readonly kind = 'handoff:input-filter-required' as const;
|
|
97
|
+
readonly skillName: string;
|
|
98
|
+
constructor(skillName: string, options?: { hint?: string; cause?: unknown }) {
|
|
99
|
+
super(
|
|
100
|
+
`Untrusted skill '${skillName}' uses Agent.toTool()/handoff() but did not declare 'graphorin-handoff-input-filter'.`,
|
|
101
|
+
{
|
|
102
|
+
hint:
|
|
103
|
+
options?.hint ??
|
|
104
|
+
"Add 'graphorin-handoff-input-filter: lastUser' (or another supported value) to the SKILL.md frontmatter.",
|
|
105
|
+
...(options?.cause === undefined ? {} : { cause: options.cause }),
|
|
106
|
+
},
|
|
107
|
+
);
|
|
108
|
+
this.skillName = skillName;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** A skill source could not be loaded from disk. */
|
|
113
|
+
export class SkillLoadError extends GraphorinSkillsError {
|
|
114
|
+
readonly kind = 'load:failed' as const;
|
|
115
|
+
readonly source: string;
|
|
116
|
+
constructor(source: string, message: string, options?: { hint?: string; cause?: unknown }) {
|
|
117
|
+
super(`Skill load failed (source='${source}'): ${message}`, options);
|
|
118
|
+
this.source = source;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** A skill name in a registry registration collided with another already-loaded skill. */
|
|
123
|
+
export class SkillNameCollisionError extends GraphorinSkillsError {
|
|
124
|
+
readonly kind = 'registry:name-collision' as const;
|
|
125
|
+
readonly skillName: string;
|
|
126
|
+
constructor(skillName: string, options?: { hint?: string; cause?: unknown }) {
|
|
127
|
+
super(`Skill '${skillName}' is already registered.`, {
|
|
128
|
+
hint:
|
|
129
|
+
options?.hint ??
|
|
130
|
+
'Either rename one of the colliding skills or call `registry.unregister(name)` before re-registering.',
|
|
131
|
+
...(options?.cause === undefined ? {} : { cause: options.cause }),
|
|
132
|
+
});
|
|
133
|
+
this.skillName = skillName;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* The slash-command parser received a string that did not match the
|
|
139
|
+
* `/skill:<name>` grammar.
|
|
140
|
+
*/
|
|
141
|
+
export class SlashCommandParseError extends GraphorinSkillsError {
|
|
142
|
+
readonly kind = 'slash:parse' as const;
|
|
143
|
+
readonly raw: string;
|
|
144
|
+
constructor(raw: string, message: string, options?: { hint?: string; cause?: unknown }) {
|
|
145
|
+
super(`Slash command '${raw}': ${message}`, {
|
|
146
|
+
hint: options?.hint ?? 'Use `/skill:<name>` to activate a registered skill.',
|
|
147
|
+
...(options?.cause === undefined ? {} : { cause: options.cause }),
|
|
148
|
+
});
|
|
149
|
+
this.raw = raw;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** Convenience union - every `kind` discriminator the package may emit. */
|
|
154
|
+
export type GraphorinSkillsErrorKind =
|
|
155
|
+
| 'frontmatter:conflict'
|
|
156
|
+
| 'manifest:parse'
|
|
157
|
+
| 'runtime-compat:mismatch'
|
|
158
|
+
| 'frontmatter:missing-required'
|
|
159
|
+
| 'handoff:input-filter-required'
|
|
160
|
+
| 'load:failed'
|
|
161
|
+
| 'registry:name-collision'
|
|
162
|
+
| 'slash:parse';
|