@smthrs/core 1.0.0-rc.7 → 1.0.0-rc.9
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/README.md +3 -1
- package/dist/cjs/Markdown.d.ts +2 -0
- package/dist/cjs/Markdown.d.ts.map +1 -1
- package/dist/cjs/Markdown.js +8 -3
- package/dist/cjs/Markdown.js.map +2 -2
- package/dist/esm/Markdown.d.ts +2 -0
- package/dist/esm/Markdown.d.ts.map +1 -1
- package/dist/esm/Markdown.js +12 -6
- package/dist/esm/Markdown.js.map +1 -1
- package/docs/README.md +3 -1
- package/docs/installation.md +5 -1
- package/docs/quickstart.md +1 -1
- package/package.json +7 -7
- package/src/Markdown.ts +10 -7
package/README.md
CHANGED
|
@@ -14,7 +14,9 @@ JavaScript and TypeScript declarations and all planning callbacks must be truste
|
|
|
14
14
|
|
|
15
15
|
For agent-generated declarations, use a constrained data-only ingestion boundary that trusted code validates and translates into nodes, or load and plan untrusted code in an externally isolated environment with restricted permissions and resources. See [Plan time](https://core.smithers.sh/concepts/plan-time/#planning-requires-trusted-declarations).
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
```bash
|
|
18
|
+
npm install @smthrs/core@next effect
|
|
19
|
+
```
|
|
18
20
|
|
|
19
21
|
The full API reference lives at [core.smithers.sh/reference/api](https://core.smithers.sh/reference/api/).
|
|
20
22
|
|
package/dist/cjs/Markdown.d.ts
CHANGED
|
@@ -123,6 +123,8 @@ export declare class MarkdownError extends MarkdownError_base {
|
|
|
123
123
|
* the implementation for; the collaborators it names stay declarations, and no
|
|
124
124
|
* flow implementation is resolved while lowering. The `smart` model seat is
|
|
125
125
|
* the explicit fallback when frontmatter declares no `model`.
|
|
126
|
+
* Model-seat and collaborator arrays are copied, so later changes to the
|
|
127
|
+
* supplied frontmatter arrays do not change the lowered flow or its decorators.
|
|
126
128
|
*
|
|
127
129
|
* @category constructors
|
|
128
130
|
* @since 0.0.0
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../src/Markdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AAKjC;;;;GAIG;AACH,OAAO,EAAE,KAAK,IAAI,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AAE1E,QAAA,MAAM,KAAK;;EAAyC,CAAA;AACpD,QAAA,MAAM,MAAM,eAAgB,CAAA;AAE5B;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACzC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,SAAS,CAAA;IACzE,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;IAClD,QAAQ,CAAC,YAAY,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;IACzD,QAAQ,CAAC,OAAO,CAAC,EAAE;QACjB,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;QAClD,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;QACnD,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;QACvD,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,GAAG,SAAS,CAAA;QACnE,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;KAC5C,GAAG,SAAS,CAAA;IACb,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAA;CAC3E;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,YAAY,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACxC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,aAAc,SAAQ,gBAAgB;IACrD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,6SAW5B,CAAA;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG,OAAO,iBAAiB,CAAC,IAAI,CAAA;;;;;AAE7D;;;;;;GAMG;AACH,qBAAa,aAAc,SAAQ,kBAGjC;CAAG;AAEL
|
|
1
|
+
{"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../src/Markdown.ts"],"names":[],"mappings":"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"}
|
package/dist/cjs/Markdown.js
CHANGED
|
@@ -86,8 +86,8 @@ const lowerMarkdown = (frontmatter, body) => {
|
|
|
86
86
|
tier: frontmatter.effects.tier
|
|
87
87
|
})
|
|
88
88
|
},
|
|
89
|
-
model: frontmatter.model ?? "smart",
|
|
90
|
-
flows: frontmatter.flows ?? [],
|
|
89
|
+
model: typeof frontmatter.model === "object" ? [...frontmatter.model] : frontmatter.model ?? "smart",
|
|
90
|
+
flows: [...frontmatter.flows ?? []],
|
|
91
91
|
prompt: body
|
|
92
92
|
});
|
|
93
93
|
switch (frontmatter.placement) {
|
|
@@ -108,7 +108,12 @@ const skillNamePattern = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
|
108
108
|
const isSkillName = (name) => name.length <= 64 && skillNamePattern.test(name);
|
|
109
109
|
const codePoints = (value) => [...value].length;
|
|
110
110
|
const isBlank = (value) => value.trim() === "";
|
|
111
|
-
const isScalarMapping = (value) =>
|
|
111
|
+
const isScalarMapping = (value) => {
|
|
112
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
113
|
+
const prototype = Object.getPrototypeOf(value);
|
|
114
|
+
if (prototype !== null && prototype !== Object.prototype) return false;
|
|
115
|
+
return Object.values(value).every((member) => typeof member === "string");
|
|
116
|
+
};
|
|
112
117
|
const validateSkillFrontmatter = (fields) => {
|
|
113
118
|
const name = fields.name;
|
|
114
119
|
if (name === void 0 || typeof name === "string" && isBlank(name)) {
|
package/dist/cjs/Markdown.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/Markdown.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Parses Agent Skills documents and lowers markdown prompts into ordinary\n * flows.\n *\n * General markdown discovery belongs to `/registry`. Agent Skills\n * frontmatter is parsed with the complete failsafe YAML schema, then checked\n * against the intrinsic rules of the Agent Skills specification\n * (https://agentskills.io/specification), before this module lowers the\n * document to the ordinary flow shape. The one rule that needs the file\n * system, that `name` equals the skill directory name, stays with the\n * registry.\n *\n * Governing contract: `packages/smithers/flows/core/docs/api.md`, published as\n * https://smithers.sh/docs/reference/api/core.\n *\n * @since 0.0.0\n */\n\nimport * as Result from \"effect/Result\"\nimport * as Schema from \"effect/Schema\"\nimport * as Annotations from \"./Annotations.ts\"\nimport * as Effects from \"./Effects.ts\"\nimport * as Flow from \"./Flow.ts\"\nimport { build } from \"./internal/Signature.ts\"\nimport * as skillFrontmatter from \"./internal/skillFrontmatter.ts\"\nimport * as Placement from \"./Placement.ts\"\n\n/**\n * Separates leading YAML frontmatter from the markdown body without parsing it.\n * @category parsing\n * @since 1.0.0\n */\nexport { split as splitFrontmatter } from \"./internal/skillFrontmatter.ts\"\n\nconst input = Schema.Struct({ args: Schema.String })\nconst output = Schema.String\n\n/**\n * Already-parsed metadata accepted by the markdown flow loader.\n *\n * @category models\n * @since 0.0.0\n * @slop\n */\nexport interface MarkdownFrontmatter {\n /**\n * The flow's name, which becomes its tag.\n *\n * It is required because the tag is what a host binds an implementation to\n * and what a plan records; a registry derives it from the frontmatter or\n * from the document's path before lowering.\n */\n readonly name: string\n readonly description?: string | undefined\n readonly model?: string | readonly [string, ...Array<string>] | undefined\n readonly flows?: ReadonlyArray<string> | undefined\n readonly capabilities?: ReadonlyArray<string> | undefined\n readonly effects?: {\n readonly reads?: ReadonlyArray<string> | undefined\n readonly writes?: ReadonlyArray<string> | undefined\n readonly mode?: Effects.Declaration[\"mode\"] | undefined\n readonly onConflict?: Effects.Declaration[\"onConflict\"] | undefined\n readonly tier?: Effects.Declaration[\"tier\"]\n } | undefined\n readonly placement?: \"sandbox\" | \"remote\" | \"client\" | \"local\" | undefined\n}\n\n/**\n * Agent Skills frontmatter that passed {@link validateSkillFrontmatter}.\n *\n * `allowedTools` is the specification's space-separated `allowed-tools`\n * scalar, split into tool names. `extra` holds every other field, including\n * the validated optional `license`, `compatibility`, and `metadata`, as a\n * frozen null-prototype record.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport interface SkillFrontmatter {\n readonly name: string\n readonly description: string\n readonly allowedTools: ReadonlyArray<string>\n readonly extra: Record<string, unknown>\n}\n\n/**\n * Parsed Agent Skills document.\n *\n * @category models\n * @since 0.0.0\n * @slop\n */\nexport interface SkillDocument extends SkillFrontmatter {\n readonly body: string\n}\n\n/**\n * Stable code emitted by markdown loader failures.\n *\n * @category models\n * @since 0.0.0\n * @slop\n */\nexport const MarkdownErrorCode = Schema.Literals([\n \"skill_missing_frontmatter\",\n \"skill_invalid_frontmatter\",\n \"skill_missing_name\",\n \"skill_invalid_name\",\n \"skill_missing_description\",\n \"skill_invalid_description\",\n \"skill_invalid_allowed_tools\",\n \"skill_invalid_compatibility\",\n \"skill_invalid_metadata\",\n \"skill_invalid_license\"\n])\n\n/**\n * Stable code emitted by markdown loader failures.\n *\n * @category models\n * @since 0.0.0\n * @slop\n */\nexport type MarkdownErrorCode = typeof MarkdownErrorCode.Type\n\n/**\n * A typed markdown loader failure.\n *\n * @category errors\n * @since 0.0.0\n * @slop\n */\nexport class MarkdownError extends Schema.TaggedError<MarkdownError>()(\"flows/core/MarkdownError\", {\n code: MarkdownErrorCode,\n message: Schema.String\n}) {}\n\n/**\n * Lowers parsed markdown metadata and a markdown body to an ordinary flow.\n *\n * The prompt is the markdown body. Harnesses append non-empty runtime `args`\n * when rendering that prompt, preserving the markdown-flow calling convention.\n * The lowered flow declares no body, so it carries the action a host supplies\n * the implementation for; the collaborators it names stay declarations, and no\n * flow implementation is resolved while lowering. The `smart` model seat is\n * the explicit fallback when frontmatter declares no `model`.\n *\n * @category constructors\n * @since 0.0.0\n * @slop\n */\nexport const lowerMarkdown = (\n frontmatter: MarkdownFrontmatter,\n body: string\n): Flow.Flow<typeof input, typeof output> => {\n const flow = build({\n error: Schema.Never,\n annotations: Annotations.empty,\n body: undefined,\n name: frontmatter.name,\n description: frontmatter.description,\n input,\n output,\n capabilities: [...new Set(frontmatter.capabilities ?? [])].sort(),\n effects: undefined,\n ...(frontmatter.effects === undefined\n ? {}\n : {\n effects: Effects.make({\n reads: frontmatter.effects.reads ?? [],\n writes: frontmatter.effects.writes ?? [],\n mode: frontmatter.effects.mode ?? \"hermetic\",\n onConflict: frontmatter.effects.onConflict ?? \"serialize\",\n tier: frontmatter.effects.tier\n })\n }),\n model: frontmatter.model ?? \"smart\",\n flows: frontmatter.flows ?? [],\n prompt: body\n })\n\n switch (frontmatter.placement) {\n case \"sandbox\":\n return Flow.within(flow, Placement.sandbox())\n case \"remote\":\n return Flow.within(flow, Placement.remote())\n case \"client\":\n return Flow.within(flow, Placement.client())\n case \"local\":\n return Flow.within(flow, Placement.local())\n default:\n return flow\n }\n}\n\nconst fail = (code: MarkdownErrorCode, message: string): Result.Result<never, MarkdownError> =>\n Result.fail(new MarkdownError({ code, message }))\n\n// The specification's name grammar: lowercase ASCII letters and digits joined\n// by single hyphens, so a leading, trailing, or doubled hyphen fails here.\nconst skillNamePattern = /^[a-z0-9]+(?:-[a-z0-9]+)*$/\n\n/**\n * Whether `name` is a valid Agent Skills name: 1 to 64 lowercase ASCII\n * letters, digits, or single hyphens, not starting or ending with a hyphen.\n *\n * {@link validateSkillFrontmatter} applies this rule, and `@smthrs/registry`\n * reads the same predicate when it warns about a discovered skill's name, so\n * the rule has one definition.\n *\n * @category validation\n * @since 1.0.0-rc.1\n */\nexport const isSkillName = (name: string): boolean => name.length <= 64 && skillNamePattern.test(name)\n\n// The specification measures a field in characters. Counting UTF-16 units\n// would reject a 600-emoji description the specification accepts, so the\n// count walks code points.\nconst codePoints = (value: string): number => [...value].length\n\nconst isBlank = (value: string): boolean => value.trim() === \"\"\n\nconst isScalarMapping = (value: unknown): boolean =>\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n Object.values(value).every((member) => typeof member === \"string\")\n\n/**\n * Checks already-parsed Agent Skills frontmatter against the specification's\n * intrinsic rules and lowers the fields this package reads.\n *\n * `name` is 1 to 64 lowercase ASCII letters, digits, or single hyphens and\n * cannot start or end with a hyphen. `description` is 1 to 1024 characters.\n * `allowed-tools`, when present, is one space-separated scalar. `license` is\n * a scalar, `compatibility` is 1 to 500 characters, and `metadata` maps\n * string keys to scalar values. A field that is absent reports a `missing`\n * code; a field that is present but malformed reports its own `invalid` code\n * without echoing the offending value. The registry keeps the one rule that\n * needs the file system: `name` must equal the skill directory name.\n *\n * @category validation\n * @since 1.0.0-rc.0\n */\nexport const validateSkillFrontmatter = (\n fields: Record<string, unknown>\n): Result.Result<SkillFrontmatter, MarkdownError> => {\n const name = fields.name\n if (name === undefined || (typeof name === \"string\" && isBlank(name))) {\n return fail(\"skill_missing_name\", \"SKILL.md requires a non-empty frontmatter name\")\n }\n if (typeof name !== \"string\" || !isSkillName(name)) {\n return fail(\n \"skill_invalid_name\",\n \"SKILL.md name must be 1 to 64 lowercase ASCII letters, digits, or single hyphens, and cannot start or end with a hyphen\"\n )\n }\n\n const description = fields.description\n if (description === undefined || (typeof description === \"string\" && isBlank(description))) {\n return fail(\"skill_missing_description\", \"SKILL.md requires a non-empty frontmatter description\")\n }\n if (typeof description !== \"string\" || codePoints(description) > 1024) {\n return fail(\"skill_invalid_description\", \"SKILL.md description must be a scalar of 1 to 1024 characters\")\n }\n\n const allowedToolsValue = fields[\"allowed-tools\"]\n if (allowedToolsValue !== undefined && typeof allowedToolsValue !== \"string\") {\n return fail(\"skill_invalid_allowed_tools\", \"SKILL.md allowed-tools must be a space-separated scalar\")\n }\n const allowedTools = allowedToolsValue === undefined\n ? []\n : allowedToolsValue.split(/\\s+/).filter((tool) => tool.length > 0)\n\n const license = fields.license\n if (license !== undefined && typeof license !== \"string\") {\n return fail(\"skill_invalid_license\", \"SKILL.md license must be a scalar\")\n }\n\n const compatibility = fields.compatibility\n if (\n compatibility !== undefined &&\n (typeof compatibility !== \"string\" || codePoints(compatibility) < 1 || codePoints(compatibility) > 500)\n ) {\n return fail(\"skill_invalid_compatibility\", \"SKILL.md compatibility must be a scalar of 1 to 500 characters\")\n }\n\n const metadata = fields.metadata\n if (metadata !== undefined && !isScalarMapping(metadata)) {\n return fail(\"skill_invalid_metadata\", \"SKILL.md metadata must be a mapping from string keys to scalar values\")\n }\n\n const extra = Object.create(null) as Record<string, unknown>\n for (const [key, value] of Object.entries(fields)) {\n if (key !== \"name\" && key !== \"description\" && key !== \"allowed-tools\") {\n Object.defineProperty(extra, key, {\n value,\n enumerable: true,\n writable: false,\n configurable: false\n })\n }\n }\n Object.freeze(extra)\n\n return Result.succeed({ name, description, allowedTools, extra })\n}\n\n/**\n * Parses an Agent Skills document with failsafe-schema YAML semantics and\n * validates its frontmatter with {@link validateSkillFrontmatter}.\n *\n * @category constructors\n * @since 0.0.0\n * @slop\n */\nexport const parseSkill = (text: string): Result.Result<SkillDocument, MarkdownError> => {\n const split = skillFrontmatter.split(text)\n if (split.frontmatter === undefined) {\n return fail(\"skill_missing_frontmatter\", \"SKILL.md requires leading frontmatter\")\n }\n\n const parsed = skillFrontmatter.parse(split.frontmatter)\n if (Result.isFailure(parsed)) {\n return fail(\"skill_invalid_frontmatter\", parsed.failure)\n }\n\n return Result.map(validateSkillFrontmatter(parsed.success), (frontmatter) => ({\n ...frontmatter,\n body: split.body\n }))\n}\n\n/**\n * Parses and lowers an Agent Skills document to an ordinary flow.\n *\n * Only `name`, `description`, and `allowed-tools` are lowered. Every other\n * frontmatter field remains in {@link parseSkill}'s `extra` record for the\n * caller to interpret. Agent Skills frontmatter is untyped failsafe YAML;\n * coercing extra fields such as `model` or `placement` here would duplicate\n * the flow-level frontmatter typing owned by `@smthrs/registry`.\n *\n * @category constructors\n * @since 0.0.0\n * @slop\n */\nexport const lowerSkill = (\n text: string\n): Result.Result<Flow.Flow<typeof input, typeof output>, MarkdownError> =>\n Result.map(parseSkill(text), (skill) =>\n lowerMarkdown({\n name: skill.name,\n description: skill.description,\n flows: skill.allowedTools\n }, skill.body))\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkBA,aAAwB;AACxB,aAAwB;AACxB,kBAA6B;AAC7B,cAAyB;AACzB,WAAsB;AACtB,uBAAsB;AACtB,uBAAkC;AAClC,gBAA2B;AAO3B,8BAA0C;AAE1C,MAAM,QAAQ,OAAO,OAAO,EAAE,MAAM,OAAO,OAAO,CAAC;AACnD,MAAM,SAAS,OAAO;AAoEf,MAAM,oBAAoB,OAAO,SAAS;AAAA,EAC/C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAkBM,MAAM,sBAAsB,OAAO,YAA2B,EAAE,4BAA4B;AAAA,EACjG,MAAM;AAAA,EACN,SAAS,OAAO;AAClB,CAAC,EAAE;AAAC;
|
|
4
|
+
"sourcesContent": ["/**\n * Parses Agent Skills documents and lowers markdown prompts into ordinary\n * flows.\n *\n * General markdown discovery belongs to `/registry`. Agent Skills\n * frontmatter is parsed with the complete failsafe YAML schema, then checked\n * against the intrinsic rules of the Agent Skills specification\n * (https://agentskills.io/specification), before this module lowers the\n * document to the ordinary flow shape. The one rule that needs the file\n * system, that `name` equals the skill directory name, stays with the\n * registry.\n *\n * Governing contract: `packages/smithers/flows/core/docs/api.md`, published as\n * https://smithers.sh/docs/reference/api/core.\n *\n * @since 0.0.0\n */\n\nimport * as Result from \"effect/Result\"\nimport * as Schema from \"effect/Schema\"\nimport * as Annotations from \"./Annotations.ts\"\nimport * as Effects from \"./Effects.ts\"\nimport * as Flow from \"./Flow.ts\"\nimport { build } from \"./internal/Signature.ts\"\nimport * as skillFrontmatter from \"./internal/skillFrontmatter.ts\"\nimport * as Placement from \"./Placement.ts\"\n\n/**\n * Separates leading YAML frontmatter from the markdown body without parsing it.\n * @category parsing\n * @since 1.0.0\n */\nexport { split as splitFrontmatter } from \"./internal/skillFrontmatter.ts\"\n\nconst input = Schema.Struct({ args: Schema.String })\nconst output = Schema.String\n\n/**\n * Already-parsed metadata accepted by the markdown flow loader.\n *\n * @category models\n * @since 0.0.0\n * @slop\n */\nexport interface MarkdownFrontmatter {\n /**\n * The flow's name, which becomes its tag.\n *\n * It is required because the tag is what a host binds an implementation to\n * and what a plan records; a registry derives it from the frontmatter or\n * from the document's path before lowering.\n */\n readonly name: string\n readonly description?: string | undefined\n readonly model?: string | readonly [string, ...Array<string>] | undefined\n readonly flows?: ReadonlyArray<string> | undefined\n readonly capabilities?: ReadonlyArray<string> | undefined\n readonly effects?: {\n readonly reads?: ReadonlyArray<string> | undefined\n readonly writes?: ReadonlyArray<string> | undefined\n readonly mode?: Effects.Declaration[\"mode\"] | undefined\n readonly onConflict?: Effects.Declaration[\"onConflict\"] | undefined\n readonly tier?: Effects.Declaration[\"tier\"]\n } | undefined\n readonly placement?: \"sandbox\" | \"remote\" | \"client\" | \"local\" | undefined\n}\n\n/**\n * Agent Skills frontmatter that passed {@link validateSkillFrontmatter}.\n *\n * `allowedTools` is the specification's space-separated `allowed-tools`\n * scalar, split into tool names. `extra` holds every other field, including\n * the validated optional `license`, `compatibility`, and `metadata`, as a\n * frozen null-prototype record.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport interface SkillFrontmatter {\n readonly name: string\n readonly description: string\n readonly allowedTools: ReadonlyArray<string>\n readonly extra: Record<string, unknown>\n}\n\n/**\n * Parsed Agent Skills document.\n *\n * @category models\n * @since 0.0.0\n * @slop\n */\nexport interface SkillDocument extends SkillFrontmatter {\n readonly body: string\n}\n\n/**\n * Stable code emitted by markdown loader failures.\n *\n * @category models\n * @since 0.0.0\n * @slop\n */\nexport const MarkdownErrorCode = Schema.Literals([\n \"skill_missing_frontmatter\",\n \"skill_invalid_frontmatter\",\n \"skill_missing_name\",\n \"skill_invalid_name\",\n \"skill_missing_description\",\n \"skill_invalid_description\",\n \"skill_invalid_allowed_tools\",\n \"skill_invalid_compatibility\",\n \"skill_invalid_metadata\",\n \"skill_invalid_license\"\n])\n\n/**\n * Stable code emitted by markdown loader failures.\n *\n * @category models\n * @since 0.0.0\n * @slop\n */\nexport type MarkdownErrorCode = typeof MarkdownErrorCode.Type\n\n/**\n * A typed markdown loader failure.\n *\n * @category errors\n * @since 0.0.0\n * @slop\n */\nexport class MarkdownError extends Schema.TaggedError<MarkdownError>()(\"flows/core/MarkdownError\", {\n code: MarkdownErrorCode,\n message: Schema.String\n}) {}\n\n/**\n * Lowers parsed markdown metadata and a markdown body to an ordinary flow.\n *\n * The prompt is the markdown body. Harnesses append non-empty runtime `args`\n * when rendering that prompt, preserving the markdown-flow calling convention.\n * The lowered flow declares no body, so it carries the action a host supplies\n * the implementation for; the collaborators it names stay declarations, and no\n * flow implementation is resolved while lowering. The `smart` model seat is\n * the explicit fallback when frontmatter declares no `model`.\n * Model-seat and collaborator arrays are copied, so later changes to the\n * supplied frontmatter arrays do not change the lowered flow or its decorators.\n *\n * @category constructors\n * @since 0.0.0\n * @slop\n */\nexport const lowerMarkdown = (\n frontmatter: MarkdownFrontmatter,\n body: string\n): Flow.Flow<typeof input, typeof output> => {\n const flow = build({\n error: Schema.Never,\n annotations: Annotations.empty,\n body: undefined,\n name: frontmatter.name,\n description: frontmatter.description,\n input,\n output,\n capabilities: [...new Set(frontmatter.capabilities ?? [])].sort(),\n effects: undefined,\n ...(frontmatter.effects === undefined\n ? {}\n : {\n effects: Effects.make({\n reads: frontmatter.effects.reads ?? [],\n writes: frontmatter.effects.writes ?? [],\n mode: frontmatter.effects.mode ?? \"hermetic\",\n onConflict: frontmatter.effects.onConflict ?? \"serialize\",\n tier: frontmatter.effects.tier\n })\n }),\n model: typeof frontmatter.model === \"object\" ? [...frontmatter.model] : frontmatter.model ?? \"smart\",\n flows: [...frontmatter.flows ?? []],\n prompt: body\n })\n\n switch (frontmatter.placement) {\n case \"sandbox\":\n return Flow.within(flow, Placement.sandbox())\n case \"remote\":\n return Flow.within(flow, Placement.remote())\n case \"client\":\n return Flow.within(flow, Placement.client())\n case \"local\":\n return Flow.within(flow, Placement.local())\n default:\n return flow\n }\n}\n\nconst fail = (code: MarkdownErrorCode, message: string): Result.Result<never, MarkdownError> =>\n Result.fail(new MarkdownError({ code, message }))\n\n// The specification's name grammar: lowercase ASCII letters and digits joined\n// by single hyphens, so a leading, trailing, or doubled hyphen fails here.\nconst skillNamePattern = /^[a-z0-9]+(?:-[a-z0-9]+)*$/\n\n/**\n * Whether `name` is a valid Agent Skills name: 1 to 64 lowercase ASCII\n * letters, digits, or single hyphens, not starting or ending with a hyphen.\n *\n * {@link validateSkillFrontmatter} applies this rule, and `@smthrs/registry`\n * reads the same predicate when it warns about a discovered skill's name, so\n * the rule has one definition.\n *\n * @category validation\n * @since 1.0.0-rc.1\n */\nexport const isSkillName = (name: string): boolean => name.length <= 64 && skillNamePattern.test(name)\n\n// The specification measures a field in characters. Counting UTF-16 units\n// would reject a 600-emoji description the specification accepts, so the\n// count walks code points.\nconst codePoints = (value: string): number => [...value].length\n\nconst isBlank = (value: string): boolean => value.trim() === \"\"\n\nconst isScalarMapping = (value: unknown): boolean => {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return false\n const prototype = Object.getPrototypeOf(value)\n if (prototype !== null && prototype !== Object.prototype) return false\n return Object.values(value).every((member) => typeof member === \"string\")\n}\n\n/**\n * Checks already-parsed Agent Skills frontmatter against the specification's\n * intrinsic rules and lowers the fields this package reads.\n *\n * `name` is 1 to 64 lowercase ASCII letters, digits, or single hyphens and\n * cannot start or end with a hyphen. `description` is 1 to 1024 characters.\n * `allowed-tools`, when present, is one space-separated scalar. `license` is\n * a scalar, `compatibility` is 1 to 500 characters, and `metadata` maps\n * string keys to scalar values. A field that is absent reports a `missing`\n * code; a field that is present but malformed reports its own `invalid` code\n * without echoing the offending value. The registry keeps the one rule that\n * needs the file system: `name` must equal the skill directory name.\n *\n * @category validation\n * @since 1.0.0-rc.0\n */\nexport const validateSkillFrontmatter = (\n fields: Record<string, unknown>\n): Result.Result<SkillFrontmatter, MarkdownError> => {\n const name = fields.name\n if (name === undefined || (typeof name === \"string\" && isBlank(name))) {\n return fail(\"skill_missing_name\", \"SKILL.md requires a non-empty frontmatter name\")\n }\n if (typeof name !== \"string\" || !isSkillName(name)) {\n return fail(\n \"skill_invalid_name\",\n \"SKILL.md name must be 1 to 64 lowercase ASCII letters, digits, or single hyphens, and cannot start or end with a hyphen\"\n )\n }\n\n const description = fields.description\n if (description === undefined || (typeof description === \"string\" && isBlank(description))) {\n return fail(\"skill_missing_description\", \"SKILL.md requires a non-empty frontmatter description\")\n }\n if (typeof description !== \"string\" || codePoints(description) > 1024) {\n return fail(\"skill_invalid_description\", \"SKILL.md description must be a scalar of 1 to 1024 characters\")\n }\n\n const allowedToolsValue = fields[\"allowed-tools\"]\n if (allowedToolsValue !== undefined && typeof allowedToolsValue !== \"string\") {\n return fail(\"skill_invalid_allowed_tools\", \"SKILL.md allowed-tools must be a space-separated scalar\")\n }\n const allowedTools = allowedToolsValue === undefined\n ? []\n : allowedToolsValue.split(/\\s+/).filter((tool) => tool.length > 0)\n\n const license = fields.license\n if (license !== undefined && typeof license !== \"string\") {\n return fail(\"skill_invalid_license\", \"SKILL.md license must be a scalar\")\n }\n\n const compatibility = fields.compatibility\n if (\n compatibility !== undefined &&\n (typeof compatibility !== \"string\" || codePoints(compatibility) < 1 || codePoints(compatibility) > 500)\n ) {\n return fail(\"skill_invalid_compatibility\", \"SKILL.md compatibility must be a scalar of 1 to 500 characters\")\n }\n\n const metadata = fields.metadata\n if (metadata !== undefined && !isScalarMapping(metadata)) {\n return fail(\"skill_invalid_metadata\", \"SKILL.md metadata must be a mapping from string keys to scalar values\")\n }\n\n const extra = Object.create(null) as Record<string, unknown>\n for (const [key, value] of Object.entries(fields)) {\n if (key !== \"name\" && key !== \"description\" && key !== \"allowed-tools\") {\n Object.defineProperty(extra, key, {\n value,\n enumerable: true,\n writable: false,\n configurable: false\n })\n }\n }\n Object.freeze(extra)\n\n return Result.succeed({ name, description, allowedTools, extra })\n}\n\n/**\n * Parses an Agent Skills document with failsafe-schema YAML semantics and\n * validates its frontmatter with {@link validateSkillFrontmatter}.\n *\n * @category constructors\n * @since 0.0.0\n * @slop\n */\nexport const parseSkill = (text: string): Result.Result<SkillDocument, MarkdownError> => {\n const split = skillFrontmatter.split(text)\n if (split.frontmatter === undefined) {\n return fail(\"skill_missing_frontmatter\", \"SKILL.md requires leading frontmatter\")\n }\n\n const parsed = skillFrontmatter.parse(split.frontmatter)\n if (Result.isFailure(parsed)) {\n return fail(\"skill_invalid_frontmatter\", parsed.failure)\n }\n\n return Result.map(validateSkillFrontmatter(parsed.success), (frontmatter) => ({\n ...frontmatter,\n body: split.body\n }))\n}\n\n/**\n * Parses and lowers an Agent Skills document to an ordinary flow.\n *\n * Only `name`, `description`, and `allowed-tools` are lowered. Every other\n * frontmatter field remains in {@link parseSkill}'s `extra` record for the\n * caller to interpret. Agent Skills frontmatter is untyped failsafe YAML;\n * coercing extra fields such as `model` or `placement` here would duplicate\n * the flow-level frontmatter typing owned by `@smthrs/registry`.\n *\n * @category constructors\n * @since 0.0.0\n * @slop\n */\nexport const lowerSkill = (\n text: string\n): Result.Result<Flow.Flow<typeof input, typeof output>, MarkdownError> =>\n Result.map(parseSkill(text), (skill) =>\n lowerMarkdown({\n name: skill.name,\n description: skill.description,\n flows: skill.allowedTools\n }, skill.body))\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["split"]
|
|
7
7
|
}
|
package/dist/esm/Markdown.d.ts
CHANGED
|
@@ -123,6 +123,8 @@ export declare class MarkdownError extends MarkdownError_base {
|
|
|
123
123
|
* the implementation for; the collaborators it names stay declarations, and no
|
|
124
124
|
* flow implementation is resolved while lowering. The `smart` model seat is
|
|
125
125
|
* the explicit fallback when frontmatter declares no `model`.
|
|
126
|
+
* Model-seat and collaborator arrays are copied, so later changes to the
|
|
127
|
+
* supplied frontmatter arrays do not change the lowered flow or its decorators.
|
|
126
128
|
*
|
|
127
129
|
* @category constructors
|
|
128
130
|
* @since 0.0.0
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../src/Markdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AAKjC;;;;GAIG;AACH,OAAO,EAAE,KAAK,IAAI,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AAE1E,QAAA,MAAM,KAAK;;EAAyC,CAAA;AACpD,QAAA,MAAM,MAAM,eAAgB,CAAA;AAE5B;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACzC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,SAAS,CAAA;IACzE,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;IAClD,QAAQ,CAAC,YAAY,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;IACzD,QAAQ,CAAC,OAAO,CAAC,EAAE;QACjB,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;QAClD,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;QACnD,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS,CAAA;QACvD,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,GAAG,SAAS,CAAA;QACnE,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;KAC5C,GAAG,SAAS,CAAA;IACb,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAA;CAC3E;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,YAAY,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACxC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,aAAc,SAAQ,gBAAgB;IACrD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,6SAW5B,CAAA;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG,OAAO,iBAAiB,CAAC,IAAI,CAAA;;;;;AAE7D;;;;;;GAMG;AACH,qBAAa,aAAc,SAAQ,kBAGjC;CAAG;AAEL
|
|
1
|
+
{"version":3,"file":"Markdown.d.ts","sourceRoot":"","sources":["../../src/Markdown.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/Markdown.js
CHANGED
|
@@ -71,6 +71,8 @@ export class MarkdownError extends Schema.TaggedError()("flows/core/MarkdownErro
|
|
|
71
71
|
* the implementation for; the collaborators it names stay declarations, and no
|
|
72
72
|
* flow implementation is resolved while lowering. The `smart` model seat is
|
|
73
73
|
* the explicit fallback when frontmatter declares no `model`.
|
|
74
|
+
* Model-seat and collaborator arrays are copied, so later changes to the
|
|
75
|
+
* supplied frontmatter arrays do not change the lowered flow or its decorators.
|
|
74
76
|
*
|
|
75
77
|
* @category constructors
|
|
76
78
|
* @since 0.0.0
|
|
@@ -98,8 +100,8 @@ export const lowerMarkdown = (frontmatter, body) => {
|
|
|
98
100
|
tier: frontmatter.effects.tier
|
|
99
101
|
})
|
|
100
102
|
}),
|
|
101
|
-
model: frontmatter.model ?? "smart",
|
|
102
|
-
flows: frontmatter.flows ?? [],
|
|
103
|
+
model: typeof frontmatter.model === "object" ? [...frontmatter.model] : frontmatter.model ?? "smart",
|
|
104
|
+
flows: [...frontmatter.flows ?? []],
|
|
103
105
|
prompt: body
|
|
104
106
|
});
|
|
105
107
|
switch (frontmatter.placement) {
|
|
@@ -136,10 +138,14 @@ export const isSkillName = (name) => name.length <= 64 && skillNamePattern.test(
|
|
|
136
138
|
// count walks code points.
|
|
137
139
|
const codePoints = (value) => [...value].length;
|
|
138
140
|
const isBlank = (value) => value.trim() === "";
|
|
139
|
-
const isScalarMapping = (value) =>
|
|
140
|
-
value !== null
|
|
141
|
-
|
|
142
|
-
Object.
|
|
141
|
+
const isScalarMapping = (value) => {
|
|
142
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
143
|
+
return false;
|
|
144
|
+
const prototype = Object.getPrototypeOf(value);
|
|
145
|
+
if (prototype !== null && prototype !== Object.prototype)
|
|
146
|
+
return false;
|
|
147
|
+
return Object.values(value).every((member) => typeof member === "string");
|
|
148
|
+
};
|
|
143
149
|
/**
|
|
144
150
|
* Checks already-parsed Agent Skills frontmatter against the specification's
|
|
145
151
|
* intrinsic rules and lowers the fields this package reads.
|
package/dist/esm/Markdown.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Markdown.js","sourceRoot":"","sources":["../../src/Markdown.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Parses Agent Skills documents and lowers markdown prompts into ordinary\n * flows.\n *\n * General markdown discovery belongs to `/registry`. Agent Skills\n * frontmatter is parsed with the complete failsafe YAML schema, then checked\n * against the intrinsic rules of the Agent Skills specification\n * (https://agentskills.io/specification), before this module lowers the\n * document to the ordinary flow shape. The one rule that needs the file\n * system, that `name` equals the skill directory name, stays with the\n * registry.\n *\n * Governing contract: `packages/smithers/flows/core/docs/api.md`, published as\n * https://smithers.sh/docs/reference/api/core.\n *\n * @since 0.0.0\n */\n\nimport * as Result from \"effect/Result\"\nimport * as Schema from \"effect/Schema\"\nimport * as Annotations from \"./Annotations.ts\"\nimport * as Effects from \"./Effects.ts\"\nimport * as Flow from \"./Flow.ts\"\nimport { build } from \"./internal/Signature.ts\"\nimport * as skillFrontmatter from \"./internal/skillFrontmatter.ts\"\nimport * as Placement from \"./Placement.ts\"\n\n/**\n * Separates leading YAML frontmatter from the markdown body without parsing it.\n * @category parsing\n * @since 1.0.0\n */\nexport { split as splitFrontmatter } from \"./internal/skillFrontmatter.ts\"\n\nconst input = Schema.Struct({ args: Schema.String })\nconst output = Schema.String\n\n/**\n * Already-parsed metadata accepted by the markdown flow loader.\n *\n * @category models\n * @since 0.0.0\n * @slop\n */\nexport interface MarkdownFrontmatter {\n /**\n * The flow's name, which becomes its tag.\n *\n * It is required because the tag is what a host binds an implementation to\n * and what a plan records; a registry derives it from the frontmatter or\n * from the document's path before lowering.\n */\n readonly name: string\n readonly description?: string | undefined\n readonly model?: string | readonly [string, ...Array<string>] | undefined\n readonly flows?: ReadonlyArray<string> | undefined\n readonly capabilities?: ReadonlyArray<string> | undefined\n readonly effects?: {\n readonly reads?: ReadonlyArray<string> | undefined\n readonly writes?: ReadonlyArray<string> | undefined\n readonly mode?: Effects.Declaration[\"mode\"] | undefined\n readonly onConflict?: Effects.Declaration[\"onConflict\"] | undefined\n readonly tier?: Effects.Declaration[\"tier\"]\n } | undefined\n readonly placement?: \"sandbox\" | \"remote\" | \"client\" | \"local\" | undefined\n}\n\n/**\n * Agent Skills frontmatter that passed {@link validateSkillFrontmatter}.\n *\n * `allowedTools` is the specification's space-separated `allowed-tools`\n * scalar, split into tool names. `extra` holds every other field, including\n * the validated optional `license`, `compatibility`, and `metadata`, as a\n * frozen null-prototype record.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport interface SkillFrontmatter {\n readonly name: string\n readonly description: string\n readonly allowedTools: ReadonlyArray<string>\n readonly extra: Record<string, unknown>\n}\n\n/**\n * Parsed Agent Skills document.\n *\n * @category models\n * @since 0.0.0\n * @slop\n */\nexport interface SkillDocument extends SkillFrontmatter {\n readonly body: string\n}\n\n/**\n * Stable code emitted by markdown loader failures.\n *\n * @category models\n * @since 0.0.0\n * @slop\n */\nexport const MarkdownErrorCode = Schema.Literals([\n \"skill_missing_frontmatter\",\n \"skill_invalid_frontmatter\",\n \"skill_missing_name\",\n \"skill_invalid_name\",\n \"skill_missing_description\",\n \"skill_invalid_description\",\n \"skill_invalid_allowed_tools\",\n \"skill_invalid_compatibility\",\n \"skill_invalid_metadata\",\n \"skill_invalid_license\"\n])\n\n/**\n * Stable code emitted by markdown loader failures.\n *\n * @category models\n * @since 0.0.0\n * @slop\n */\nexport type MarkdownErrorCode = typeof MarkdownErrorCode.Type\n\n/**\n * A typed markdown loader failure.\n *\n * @category errors\n * @since 0.0.0\n * @slop\n */\nexport class MarkdownError extends Schema.TaggedError<MarkdownError>()(\"flows/core/MarkdownError\", {\n code: MarkdownErrorCode,\n message: Schema.String\n}) {}\n\n/**\n * Lowers parsed markdown metadata and a markdown body to an ordinary flow.\n *\n * The prompt is the markdown body. Harnesses append non-empty runtime `args`\n * when rendering that prompt, preserving the markdown-flow calling convention.\n * The lowered flow declares no body, so it carries the action a host supplies\n * the implementation for; the collaborators it names stay declarations, and no\n * flow implementation is resolved while lowering. The `smart` model seat is\n * the explicit fallback when frontmatter declares no `model`.\n *\n * @category constructors\n * @since 0.0.0\n * @slop\n */\nexport const lowerMarkdown = (\n frontmatter: MarkdownFrontmatter,\n body: string\n): Flow.Flow<typeof input, typeof output> => {\n const flow = build({\n error: Schema.Never,\n annotations: Annotations.empty,\n body: undefined,\n name: frontmatter.name,\n description: frontmatter.description,\n input,\n output,\n capabilities: [...new Set(frontmatter.capabilities ?? [])].sort(),\n effects: undefined,\n ...(frontmatter.effects === undefined\n ? {}\n : {\n effects: Effects.make({\n reads: frontmatter.effects.reads ?? [],\n writes: frontmatter.effects.writes ?? [],\n mode: frontmatter.effects.mode ?? \"hermetic\",\n onConflict: frontmatter.effects.onConflict ?? \"serialize\",\n tier: frontmatter.effects.tier\n })\n }),\n model: frontmatter.model ?? \"smart\",\n flows: frontmatter.flows ?? [],\n prompt: body\n })\n\n switch (frontmatter.placement) {\n case \"sandbox\":\n return Flow.within(flow, Placement.sandbox())\n case \"remote\":\n return Flow.within(flow, Placement.remote())\n case \"client\":\n return Flow.within(flow, Placement.client())\n case \"local\":\n return Flow.within(flow, Placement.local())\n default:\n return flow\n }\n}\n\nconst fail = (code: MarkdownErrorCode, message: string): Result.Result<never, MarkdownError> =>\n Result.fail(new MarkdownError({ code, message }))\n\n// The specification's name grammar: lowercase ASCII letters and digits joined\n// by single hyphens, so a leading, trailing, or doubled hyphen fails here.\nconst skillNamePattern = /^[a-z0-9]+(?:-[a-z0-9]+)*$/\n\n/**\n * Whether `name` is a valid Agent Skills name: 1 to 64 lowercase ASCII\n * letters, digits, or single hyphens, not starting or ending with a hyphen.\n *\n * {@link validateSkillFrontmatter} applies this rule, and `@smthrs/registry`\n * reads the same predicate when it warns about a discovered skill's name, so\n * the rule has one definition.\n *\n * @category validation\n * @since 1.0.0-rc.1\n */\nexport const isSkillName = (name: string): boolean => name.length <= 64 && skillNamePattern.test(name)\n\n// The specification measures a field in characters. Counting UTF-16 units\n// would reject a 600-emoji description the specification accepts, so the\n// count walks code points.\nconst codePoints = (value: string): number => [...value].length\n\nconst isBlank = (value: string): boolean => value.trim() === \"\"\n\nconst isScalarMapping = (value: unknown): boolean =>\n typeof value === \"object\" &&\n value !== null &&\n !Array.isArray(value) &&\n Object.values(value).every((member) => typeof member === \"string\")\n\n/**\n * Checks already-parsed Agent Skills frontmatter against the specification's\n * intrinsic rules and lowers the fields this package reads.\n *\n * `name` is 1 to 64 lowercase ASCII letters, digits, or single hyphens and\n * cannot start or end with a hyphen. `description` is 1 to 1024 characters.\n * `allowed-tools`, when present, is one space-separated scalar. `license` is\n * a scalar, `compatibility` is 1 to 500 characters, and `metadata` maps\n * string keys to scalar values. A field that is absent reports a `missing`\n * code; a field that is present but malformed reports its own `invalid` code\n * without echoing the offending value. The registry keeps the one rule that\n * needs the file system: `name` must equal the skill directory name.\n *\n * @category validation\n * @since 1.0.0-rc.0\n */\nexport const validateSkillFrontmatter = (\n fields: Record<string, unknown>\n): Result.Result<SkillFrontmatter, MarkdownError> => {\n const name = fields.name\n if (name === undefined || (typeof name === \"string\" && isBlank(name))) {\n return fail(\"skill_missing_name\", \"SKILL.md requires a non-empty frontmatter name\")\n }\n if (typeof name !== \"string\" || !isSkillName(name)) {\n return fail(\n \"skill_invalid_name\",\n \"SKILL.md name must be 1 to 64 lowercase ASCII letters, digits, or single hyphens, and cannot start or end with a hyphen\"\n )\n }\n\n const description = fields.description\n if (description === undefined || (typeof description === \"string\" && isBlank(description))) {\n return fail(\"skill_missing_description\", \"SKILL.md requires a non-empty frontmatter description\")\n }\n if (typeof description !== \"string\" || codePoints(description) > 1024) {\n return fail(\"skill_invalid_description\", \"SKILL.md description must be a scalar of 1 to 1024 characters\")\n }\n\n const allowedToolsValue = fields[\"allowed-tools\"]\n if (allowedToolsValue !== undefined && typeof allowedToolsValue !== \"string\") {\n return fail(\"skill_invalid_allowed_tools\", \"SKILL.md allowed-tools must be a space-separated scalar\")\n }\n const allowedTools = allowedToolsValue === undefined\n ? []\n : allowedToolsValue.split(/\\s+/).filter((tool) => tool.length > 0)\n\n const license = fields.license\n if (license !== undefined && typeof license !== \"string\") {\n return fail(\"skill_invalid_license\", \"SKILL.md license must be a scalar\")\n }\n\n const compatibility = fields.compatibility\n if (\n compatibility !== undefined &&\n (typeof compatibility !== \"string\" || codePoints(compatibility) < 1 || codePoints(compatibility) > 500)\n ) {\n return fail(\"skill_invalid_compatibility\", \"SKILL.md compatibility must be a scalar of 1 to 500 characters\")\n }\n\n const metadata = fields.metadata\n if (metadata !== undefined && !isScalarMapping(metadata)) {\n return fail(\"skill_invalid_metadata\", \"SKILL.md metadata must be a mapping from string keys to scalar values\")\n }\n\n const extra = Object.create(null) as Record<string, unknown>\n for (const [key, value] of Object.entries(fields)) {\n if (key !== \"name\" && key !== \"description\" && key !== \"allowed-tools\") {\n Object.defineProperty(extra, key, {\n value,\n enumerable: true,\n writable: false,\n configurable: false\n })\n }\n }\n Object.freeze(extra)\n\n return Result.succeed({ name, description, allowedTools, extra })\n}\n\n/**\n * Parses an Agent Skills document with failsafe-schema YAML semantics and\n * validates its frontmatter with {@link validateSkillFrontmatter}.\n *\n * @category constructors\n * @since 0.0.0\n * @slop\n */\nexport const parseSkill = (text: string): Result.Result<SkillDocument, MarkdownError> => {\n const split = skillFrontmatter.split(text)\n if (split.frontmatter === undefined) {\n return fail(\"skill_missing_frontmatter\", \"SKILL.md requires leading frontmatter\")\n }\n\n const parsed = skillFrontmatter.parse(split.frontmatter)\n if (Result.isFailure(parsed)) {\n return fail(\"skill_invalid_frontmatter\", parsed.failure)\n }\n\n return Result.map(validateSkillFrontmatter(parsed.success), (frontmatter) => ({\n ...frontmatter,\n body: split.body\n }))\n}\n\n/**\n * Parses and lowers an Agent Skills document to an ordinary flow.\n *\n * Only `name`, `description`, and `allowed-tools` are lowered. Every other\n * frontmatter field remains in {@link parseSkill}'s `extra` record for the\n * caller to interpret. Agent Skills frontmatter is untyped failsafe YAML;\n * coercing extra fields such as `model` or `placement` here would duplicate\n * the flow-level frontmatter typing owned by `@smthrs/registry`.\n *\n * @category constructors\n * @since 0.0.0\n * @slop\n */\nexport const lowerSkill = (\n text: string\n): Result.Result<Flow.Flow<typeof input, typeof output>, MarkdownError> =>\n Result.map(parseSkill(text), (skill) =>\n lowerMarkdown({\n name: skill.name,\n description: skill.description,\n flows: skill.allowedTools\n }, skill.body))\n"]}
|
|
1
|
+
{"version":3,"file":"Markdown.js","sourceRoot":"","sources":["../../src/Markdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAC/C,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AACjC,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;AAC/C,OAAO,KAAK,gBAAgB,MAAM,gCAAgC,CAAA;AAClE,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAA;AAE3C;;;;GAIG;AACH,OAAO,EAAE,KAAK,IAAI,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AAE1E,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAA;AACpD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAA;AA6D5B;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC,QAAQ,CAAC;IAC/C,2BAA2B;IAC3B,2BAA2B;IAC3B,oBAAoB;IACpB,oBAAoB;IACpB,2BAA2B;IAC3B,2BAA2B;IAC3B,6BAA6B;IAC7B,6BAA6B;IAC7B,wBAAwB;IACxB,uBAAuB;CACxB,CAAC,CAAA;AAWF;;;;;;GAMG;AACH,MAAM,OAAO,aAAc,SAAQ,MAAM,CAAC,WAAW,EAAiB,CAAC,0BAA0B,EAAE;IACjG,IAAI,EAAE,iBAAiB;IACvB,OAAO,EAAE,MAAM,CAAC,MAAM;CACvB,CAAC;CAAG;AAEL;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,WAAgC,EAChC,IAAY,EAC4B,EAAE;IAC1C,MAAM,IAAI,GAAG,KAAK,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,WAAW,EAAE,WAAW,CAAC,KAAK;QAC9B,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,WAAW,CAAC,IAAI;QACtB,WAAW,EAAE,WAAW,CAAC,WAAW;QACpC,KAAK;QACL,MAAM;QACN,YAAY,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE;QACjE,OAAO,EAAE,SAAS;QAClB,GAAG,CAAC,WAAW,CAAC,OAAO,KAAK,SAAS;YACnC,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC;gBACA,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC;oBACpB,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE;oBACtC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE;oBACxC,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,IAAI,UAAU;oBAC5C,UAAU,EAAE,WAAW,CAAC,OAAO,CAAC,UAAU,IAAI,WAAW;oBACzD,IAAI,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI;iBAC/B,CAAC;aACH,CAAC;QACJ,KAAK,EAAE,OAAO,WAAW,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,IAAI,OAAO;QACpG,KAAK,EAAE,CAAC,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE,CAAC;QACnC,MAAM,EAAE,IAAI;KACb,CAAC,CAAA;IAEF,QAAQ,WAAW,CAAC,SAAS,EAAE,CAAC;QAC9B,KAAK,SAAS;YACZ,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC,CAAA;QAC/C,KAAK,QAAQ;YACX,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC,CAAA;QAC9C,KAAK,QAAQ;YACX,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC,CAAA;QAC9C,KAAK,OAAO;YACV,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC,CAAA;QAC7C;YACE,OAAO,IAAI,CAAA;IACf,CAAC;AACH,CAAC,CAAA;AAED,MAAM,IAAI,GAAG,CAAC,IAAuB,EAAE,OAAe,EAAuC,EAAE,CAC7F,MAAM,CAAC,IAAI,CAAC,IAAI,aAAa,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAA;AAEnD,8EAA8E;AAC9E,2EAA2E;AAC3E,MAAM,gBAAgB,GAAG,4BAA4B,CAAA;AAErD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAY,EAAW,EAAE,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAEtG,0EAA0E;AAC1E,yEAAyE;AACzE,2BAA2B;AAC3B,MAAM,UAAU,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,MAAM,CAAA;AAE/D,MAAM,OAAO,GAAG,CAAC,KAAa,EAAW,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,CAAA;AAE/D,MAAM,eAAe,GAAG,CAAC,KAAc,EAAW,EAAE;IAClD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IACrF,MAAM,SAAS,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAA;IAC9C,IAAI,SAAS,KAAK,IAAI,IAAI,SAAS,KAAK,MAAM,CAAC,SAAS;QAAE,OAAO,KAAK,CAAA;IACtE,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAA;AAC3E,CAAC,CAAA;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACtC,MAA+B,EACiB,EAAE;IAClD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAA;IACxB,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QACtE,OAAO,IAAI,CAAC,oBAAoB,EAAE,gDAAgD,CAAC,CAAA;IACrF,CAAC;IACD,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QACnD,OAAO,IAAI,CACT,oBAAoB,EACpB,yHAAyH,CAC1H,CAAA;IACH,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAA;IACtC,IAAI,WAAW,KAAK,SAAS,IAAI,CAAC,OAAO,WAAW,KAAK,QAAQ,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;QAC3F,OAAO,IAAI,CAAC,2BAA2B,EAAE,uDAAuD,CAAC,CAAA;IACnG,CAAC;IACD,IAAI,OAAO,WAAW,KAAK,QAAQ,IAAI,UAAU,CAAC,WAAW,CAAC,GAAG,IAAI,EAAE,CAAC;QACtE,OAAO,IAAI,CAAC,2BAA2B,EAAE,+DAA+D,CAAC,CAAA;IAC3G,CAAC;IAED,MAAM,iBAAiB,GAAG,MAAM,CAAC,eAAe,CAAC,CAAA;IACjD,IAAI,iBAAiB,KAAK,SAAS,IAAI,OAAO,iBAAiB,KAAK,QAAQ,EAAE,CAAC;QAC7E,OAAO,IAAI,CAAC,6BAA6B,EAAE,yDAAyD,CAAC,CAAA;IACvG,CAAC;IACD,MAAM,YAAY,GAAG,iBAAiB,KAAK,SAAS;QAClD,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAEpE,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAA;IAC9B,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QACzD,OAAO,IAAI,CAAC,uBAAuB,EAAE,mCAAmC,CAAC,CAAA;IAC3E,CAAC;IAED,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,CAAA;IAC1C,IACE,aAAa,KAAK,SAAS;QAC3B,CAAC,OAAO,aAAa,KAAK,QAAQ,IAAI,UAAU,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,aAAa,CAAC,GAAG,GAAG,CAAC,EACvG,CAAC;QACD,OAAO,IAAI,CAAC,6BAA6B,EAAE,gEAAgE,CAAC,CAAA;IAC9G,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAA;IAChC,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzD,OAAO,IAAI,CAAC,wBAAwB,EAAE,uEAAuE,CAAC,CAAA;IAChH,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAA4B,CAAA;IAC5D,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,aAAa,IAAI,GAAG,KAAK,eAAe,EAAE,CAAC;YACvE,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,GAAG,EAAE;gBAChC,KAAK;gBACL,UAAU,EAAE,IAAI;gBAChB,QAAQ,EAAE,KAAK;gBACf,YAAY,EAAE,KAAK;aACpB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IACD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IAEpB,OAAO,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAA;AACnE,CAAC,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,IAAY,EAA+C,EAAE;IACtF,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAC1C,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC,2BAA2B,EAAE,uCAAuC,CAAC,CAAA;IACnF,CAAC;IAED,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAA;IACxD,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC,2BAA2B,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;IAC1D,CAAC;IAED,OAAO,MAAM,CAAC,GAAG,CAAC,wBAAwB,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAC5E,GAAG,WAAW;QACd,IAAI,EAAE,KAAK,CAAC,IAAI;KACjB,CAAC,CAAC,CAAA;AACL,CAAC,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,IAAY,EAC0D,EAAE,CACxE,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CACrC,aAAa,CAAC;IACZ,IAAI,EAAE,KAAK,CAAC,IAAI;IAChB,WAAW,EAAE,KAAK,CAAC,WAAW;IAC9B,KAAK,EAAE,KAAK,CAAC,YAAY;CAC1B,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA","sourcesContent":["/**\n * Parses Agent Skills documents and lowers markdown prompts into ordinary\n * flows.\n *\n * General markdown discovery belongs to `/registry`. Agent Skills\n * frontmatter is parsed with the complete failsafe YAML schema, then checked\n * against the intrinsic rules of the Agent Skills specification\n * (https://agentskills.io/specification), before this module lowers the\n * document to the ordinary flow shape. The one rule that needs the file\n * system, that `name` equals the skill directory name, stays with the\n * registry.\n *\n * Governing contract: `packages/smithers/flows/core/docs/api.md`, published as\n * https://smithers.sh/docs/reference/api/core.\n *\n * @since 0.0.0\n */\n\nimport * as Result from \"effect/Result\"\nimport * as Schema from \"effect/Schema\"\nimport * as Annotations from \"./Annotations.ts\"\nimport * as Effects from \"./Effects.ts\"\nimport * as Flow from \"./Flow.ts\"\nimport { build } from \"./internal/Signature.ts\"\nimport * as skillFrontmatter from \"./internal/skillFrontmatter.ts\"\nimport * as Placement from \"./Placement.ts\"\n\n/**\n * Separates leading YAML frontmatter from the markdown body without parsing it.\n * @category parsing\n * @since 1.0.0\n */\nexport { split as splitFrontmatter } from \"./internal/skillFrontmatter.ts\"\n\nconst input = Schema.Struct({ args: Schema.String })\nconst output = Schema.String\n\n/**\n * Already-parsed metadata accepted by the markdown flow loader.\n *\n * @category models\n * @since 0.0.0\n * @slop\n */\nexport interface MarkdownFrontmatter {\n /**\n * The flow's name, which becomes its tag.\n *\n * It is required because the tag is what a host binds an implementation to\n * and what a plan records; a registry derives it from the frontmatter or\n * from the document's path before lowering.\n */\n readonly name: string\n readonly description?: string | undefined\n readonly model?: string | readonly [string, ...Array<string>] | undefined\n readonly flows?: ReadonlyArray<string> | undefined\n readonly capabilities?: ReadonlyArray<string> | undefined\n readonly effects?: {\n readonly reads?: ReadonlyArray<string> | undefined\n readonly writes?: ReadonlyArray<string> | undefined\n readonly mode?: Effects.Declaration[\"mode\"] | undefined\n readonly onConflict?: Effects.Declaration[\"onConflict\"] | undefined\n readonly tier?: Effects.Declaration[\"tier\"]\n } | undefined\n readonly placement?: \"sandbox\" | \"remote\" | \"client\" | \"local\" | undefined\n}\n\n/**\n * Agent Skills frontmatter that passed {@link validateSkillFrontmatter}.\n *\n * `allowedTools` is the specification's space-separated `allowed-tools`\n * scalar, split into tool names. `extra` holds every other field, including\n * the validated optional `license`, `compatibility`, and `metadata`, as a\n * frozen null-prototype record.\n *\n * @category models\n * @since 1.0.0-rc.0\n */\nexport interface SkillFrontmatter {\n readonly name: string\n readonly description: string\n readonly allowedTools: ReadonlyArray<string>\n readonly extra: Record<string, unknown>\n}\n\n/**\n * Parsed Agent Skills document.\n *\n * @category models\n * @since 0.0.0\n * @slop\n */\nexport interface SkillDocument extends SkillFrontmatter {\n readonly body: string\n}\n\n/**\n * Stable code emitted by markdown loader failures.\n *\n * @category models\n * @since 0.0.0\n * @slop\n */\nexport const MarkdownErrorCode = Schema.Literals([\n \"skill_missing_frontmatter\",\n \"skill_invalid_frontmatter\",\n \"skill_missing_name\",\n \"skill_invalid_name\",\n \"skill_missing_description\",\n \"skill_invalid_description\",\n \"skill_invalid_allowed_tools\",\n \"skill_invalid_compatibility\",\n \"skill_invalid_metadata\",\n \"skill_invalid_license\"\n])\n\n/**\n * Stable code emitted by markdown loader failures.\n *\n * @category models\n * @since 0.0.0\n * @slop\n */\nexport type MarkdownErrorCode = typeof MarkdownErrorCode.Type\n\n/**\n * A typed markdown loader failure.\n *\n * @category errors\n * @since 0.0.0\n * @slop\n */\nexport class MarkdownError extends Schema.TaggedError<MarkdownError>()(\"flows/core/MarkdownError\", {\n code: MarkdownErrorCode,\n message: Schema.String\n}) {}\n\n/**\n * Lowers parsed markdown metadata and a markdown body to an ordinary flow.\n *\n * The prompt is the markdown body. Harnesses append non-empty runtime `args`\n * when rendering that prompt, preserving the markdown-flow calling convention.\n * The lowered flow declares no body, so it carries the action a host supplies\n * the implementation for; the collaborators it names stay declarations, and no\n * flow implementation is resolved while lowering. The `smart` model seat is\n * the explicit fallback when frontmatter declares no `model`.\n * Model-seat and collaborator arrays are copied, so later changes to the\n * supplied frontmatter arrays do not change the lowered flow or its decorators.\n *\n * @category constructors\n * @since 0.0.0\n * @slop\n */\nexport const lowerMarkdown = (\n frontmatter: MarkdownFrontmatter,\n body: string\n): Flow.Flow<typeof input, typeof output> => {\n const flow = build({\n error: Schema.Never,\n annotations: Annotations.empty,\n body: undefined,\n name: frontmatter.name,\n description: frontmatter.description,\n input,\n output,\n capabilities: [...new Set(frontmatter.capabilities ?? [])].sort(),\n effects: undefined,\n ...(frontmatter.effects === undefined\n ? {}\n : {\n effects: Effects.make({\n reads: frontmatter.effects.reads ?? [],\n writes: frontmatter.effects.writes ?? [],\n mode: frontmatter.effects.mode ?? \"hermetic\",\n onConflict: frontmatter.effects.onConflict ?? \"serialize\",\n tier: frontmatter.effects.tier\n })\n }),\n model: typeof frontmatter.model === \"object\" ? [...frontmatter.model] : frontmatter.model ?? \"smart\",\n flows: [...frontmatter.flows ?? []],\n prompt: body\n })\n\n switch (frontmatter.placement) {\n case \"sandbox\":\n return Flow.within(flow, Placement.sandbox())\n case \"remote\":\n return Flow.within(flow, Placement.remote())\n case \"client\":\n return Flow.within(flow, Placement.client())\n case \"local\":\n return Flow.within(flow, Placement.local())\n default:\n return flow\n }\n}\n\nconst fail = (code: MarkdownErrorCode, message: string): Result.Result<never, MarkdownError> =>\n Result.fail(new MarkdownError({ code, message }))\n\n// The specification's name grammar: lowercase ASCII letters and digits joined\n// by single hyphens, so a leading, trailing, or doubled hyphen fails here.\nconst skillNamePattern = /^[a-z0-9]+(?:-[a-z0-9]+)*$/\n\n/**\n * Whether `name` is a valid Agent Skills name: 1 to 64 lowercase ASCII\n * letters, digits, or single hyphens, not starting or ending with a hyphen.\n *\n * {@link validateSkillFrontmatter} applies this rule, and `@smthrs/registry`\n * reads the same predicate when it warns about a discovered skill's name, so\n * the rule has one definition.\n *\n * @category validation\n * @since 1.0.0-rc.1\n */\nexport const isSkillName = (name: string): boolean => name.length <= 64 && skillNamePattern.test(name)\n\n// The specification measures a field in characters. Counting UTF-16 units\n// would reject a 600-emoji description the specification accepts, so the\n// count walks code points.\nconst codePoints = (value: string): number => [...value].length\n\nconst isBlank = (value: string): boolean => value.trim() === \"\"\n\nconst isScalarMapping = (value: unknown): boolean => {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return false\n const prototype = Object.getPrototypeOf(value)\n if (prototype !== null && prototype !== Object.prototype) return false\n return Object.values(value).every((member) => typeof member === \"string\")\n}\n\n/**\n * Checks already-parsed Agent Skills frontmatter against the specification's\n * intrinsic rules and lowers the fields this package reads.\n *\n * `name` is 1 to 64 lowercase ASCII letters, digits, or single hyphens and\n * cannot start or end with a hyphen. `description` is 1 to 1024 characters.\n * `allowed-tools`, when present, is one space-separated scalar. `license` is\n * a scalar, `compatibility` is 1 to 500 characters, and `metadata` maps\n * string keys to scalar values. A field that is absent reports a `missing`\n * code; a field that is present but malformed reports its own `invalid` code\n * without echoing the offending value. The registry keeps the one rule that\n * needs the file system: `name` must equal the skill directory name.\n *\n * @category validation\n * @since 1.0.0-rc.0\n */\nexport const validateSkillFrontmatter = (\n fields: Record<string, unknown>\n): Result.Result<SkillFrontmatter, MarkdownError> => {\n const name = fields.name\n if (name === undefined || (typeof name === \"string\" && isBlank(name))) {\n return fail(\"skill_missing_name\", \"SKILL.md requires a non-empty frontmatter name\")\n }\n if (typeof name !== \"string\" || !isSkillName(name)) {\n return fail(\n \"skill_invalid_name\",\n \"SKILL.md name must be 1 to 64 lowercase ASCII letters, digits, or single hyphens, and cannot start or end with a hyphen\"\n )\n }\n\n const description = fields.description\n if (description === undefined || (typeof description === \"string\" && isBlank(description))) {\n return fail(\"skill_missing_description\", \"SKILL.md requires a non-empty frontmatter description\")\n }\n if (typeof description !== \"string\" || codePoints(description) > 1024) {\n return fail(\"skill_invalid_description\", \"SKILL.md description must be a scalar of 1 to 1024 characters\")\n }\n\n const allowedToolsValue = fields[\"allowed-tools\"]\n if (allowedToolsValue !== undefined && typeof allowedToolsValue !== \"string\") {\n return fail(\"skill_invalid_allowed_tools\", \"SKILL.md allowed-tools must be a space-separated scalar\")\n }\n const allowedTools = allowedToolsValue === undefined\n ? []\n : allowedToolsValue.split(/\\s+/).filter((tool) => tool.length > 0)\n\n const license = fields.license\n if (license !== undefined && typeof license !== \"string\") {\n return fail(\"skill_invalid_license\", \"SKILL.md license must be a scalar\")\n }\n\n const compatibility = fields.compatibility\n if (\n compatibility !== undefined &&\n (typeof compatibility !== \"string\" || codePoints(compatibility) < 1 || codePoints(compatibility) > 500)\n ) {\n return fail(\"skill_invalid_compatibility\", \"SKILL.md compatibility must be a scalar of 1 to 500 characters\")\n }\n\n const metadata = fields.metadata\n if (metadata !== undefined && !isScalarMapping(metadata)) {\n return fail(\"skill_invalid_metadata\", \"SKILL.md metadata must be a mapping from string keys to scalar values\")\n }\n\n const extra = Object.create(null) as Record<string, unknown>\n for (const [key, value] of Object.entries(fields)) {\n if (key !== \"name\" && key !== \"description\" && key !== \"allowed-tools\") {\n Object.defineProperty(extra, key, {\n value,\n enumerable: true,\n writable: false,\n configurable: false\n })\n }\n }\n Object.freeze(extra)\n\n return Result.succeed({ name, description, allowedTools, extra })\n}\n\n/**\n * Parses an Agent Skills document with failsafe-schema YAML semantics and\n * validates its frontmatter with {@link validateSkillFrontmatter}.\n *\n * @category constructors\n * @since 0.0.0\n * @slop\n */\nexport const parseSkill = (text: string): Result.Result<SkillDocument, MarkdownError> => {\n const split = skillFrontmatter.split(text)\n if (split.frontmatter === undefined) {\n return fail(\"skill_missing_frontmatter\", \"SKILL.md requires leading frontmatter\")\n }\n\n const parsed = skillFrontmatter.parse(split.frontmatter)\n if (Result.isFailure(parsed)) {\n return fail(\"skill_invalid_frontmatter\", parsed.failure)\n }\n\n return Result.map(validateSkillFrontmatter(parsed.success), (frontmatter) => ({\n ...frontmatter,\n body: split.body\n }))\n}\n\n/**\n * Parses and lowers an Agent Skills document to an ordinary flow.\n *\n * Only `name`, `description`, and `allowed-tools` are lowered. Every other\n * frontmatter field remains in {@link parseSkill}'s `extra` record for the\n * caller to interpret. Agent Skills frontmatter is untyped failsafe YAML;\n * coercing extra fields such as `model` or `placement` here would duplicate\n * the flow-level frontmatter typing owned by `@smthrs/registry`.\n *\n * @category constructors\n * @since 0.0.0\n * @slop\n */\nexport const lowerSkill = (\n text: string\n): Result.Result<Flow.Flow<typeof input, typeof output>, MarkdownError> =>\n Result.map(parseSkill(text), (skill) =>\n lowerMarkdown({\n name: skill.name,\n description: skill.description,\n flows: skill.allowedTools\n }, skill.body))\n"]}
|
package/docs/README.md
CHANGED
|
@@ -37,7 +37,9 @@ diagram, or a test.
|
|
|
37
37
|
|
|
38
38
|
## Install
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
```bash
|
|
41
|
+
npm install @smthrs/core@next effect
|
|
42
|
+
```
|
|
41
43
|
|
|
42
44
|
The package needs Node.js 26.4.0 or later. It has no platform bindings, so the
|
|
43
45
|
same build runs in Node, in Bun, in a browser, and in a Cloudflare Worker.
|
package/docs/installation.md
CHANGED
|
@@ -7,7 +7,11 @@ sidebar:
|
|
|
7
7
|
|
|
8
8
|
## Install the package
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
```bash
|
|
11
|
+
npm install @smthrs/core@next effect
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
The `next` tag carries the 1.0 release candidates.
|
|
11
15
|
|
|
12
16
|
The package requires Node.js 26.4.0 or later and ships as both ESM and
|
|
13
17
|
CommonJS with TypeScript declarations. It has no platform bindings: it reads no
|
package/docs/quickstart.md
CHANGED
|
@@ -13,7 +13,7 @@ with no engine, no model, and no file system.
|
|
|
13
13
|
## Prerequisites
|
|
14
14
|
|
|
15
15
|
- Node.js 26.4.0 or later.
|
|
16
|
-
- A
|
|
16
|
+
- A project with the packages installed: `npm install @smthrs/core@next @smthrs/flow@next effect`.
|
|
17
17
|
|
|
18
18
|
## Declare two signatures
|
|
19
19
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smthrs/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.0-rc.
|
|
4
|
+
"version": "1.0.0-rc.9",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"smthrs": {
|
|
7
7
|
"group": "agent"
|
|
@@ -165,10 +165,10 @@
|
|
|
165
165
|
"tag": "next"
|
|
166
166
|
},
|
|
167
167
|
"dependencies": {
|
|
168
|
-
"@smthrs/canonical": "1.0.0-rc.
|
|
169
|
-
"@smthrs/crypto": "1.0.0-rc.
|
|
170
|
-
"@smthrs/flow": "1.0.0-rc.
|
|
171
|
-
"@smthrs/plan": "1.0.0-rc.
|
|
168
|
+
"@smthrs/canonical": "1.0.0-rc.9",
|
|
169
|
+
"@smthrs/crypto": "1.0.0-rc.9",
|
|
170
|
+
"@smthrs/flow": "1.0.0-rc.9",
|
|
171
|
+
"@smthrs/plan": "1.0.0-rc.9",
|
|
172
172
|
"yaml": "2.9.0"
|
|
173
173
|
},
|
|
174
174
|
"devDependencies": {
|
|
@@ -176,7 +176,7 @@
|
|
|
176
176
|
"@effect/platform-node": "4.0.4",
|
|
177
177
|
"@effect/vitest": "4.0.4",
|
|
178
178
|
"@eslint/js": "9.39.5",
|
|
179
|
-
"@smthrs/engine": "1.0.0-rc.
|
|
179
|
+
"@smthrs/engine": "1.0.0-rc.9",
|
|
180
180
|
"@types/node": "26.4.1",
|
|
181
181
|
"@vitest/coverage-v8": "5.0.0",
|
|
182
182
|
"dprint": "0.57.1",
|
|
@@ -196,7 +196,7 @@
|
|
|
196
196
|
"effect": "^4.0.4"
|
|
197
197
|
},
|
|
198
198
|
"scripts": {
|
|
199
|
-
"lint": "eslint src --max-warnings=0 && dprint check",
|
|
199
|
+
"lint": "eslint src examples --max-warnings=0 && dprint check",
|
|
200
200
|
"format": "dprint fmt",
|
|
201
201
|
"build": "node scripts/build.mjs",
|
|
202
202
|
"check": "tsc -b tsconfig.json && tsc -p tsconfig.test.json --noEmit",
|
package/src/Markdown.ts
CHANGED
|
@@ -144,6 +144,8 @@ export class MarkdownError extends Schema.TaggedError<MarkdownError>()("flows/co
|
|
|
144
144
|
* the implementation for; the collaborators it names stay declarations, and no
|
|
145
145
|
* flow implementation is resolved while lowering. The `smart` model seat is
|
|
146
146
|
* the explicit fallback when frontmatter declares no `model`.
|
|
147
|
+
* Model-seat and collaborator arrays are copied, so later changes to the
|
|
148
|
+
* supplied frontmatter arrays do not change the lowered flow or its decorators.
|
|
147
149
|
*
|
|
148
150
|
* @category constructors
|
|
149
151
|
* @since 0.0.0
|
|
@@ -174,8 +176,8 @@ export const lowerMarkdown = (
|
|
|
174
176
|
tier: frontmatter.effects.tier
|
|
175
177
|
})
|
|
176
178
|
}),
|
|
177
|
-
model: frontmatter.model ?? "smart",
|
|
178
|
-
flows: frontmatter.flows ?? [],
|
|
179
|
+
model: typeof frontmatter.model === "object" ? [...frontmatter.model] : frontmatter.model ?? "smart",
|
|
180
|
+
flows: [...frontmatter.flows ?? []],
|
|
179
181
|
prompt: body
|
|
180
182
|
})
|
|
181
183
|
|
|
@@ -220,11 +222,12 @@ const codePoints = (value: string): number => [...value].length
|
|
|
220
222
|
|
|
221
223
|
const isBlank = (value: string): boolean => value.trim() === ""
|
|
222
224
|
|
|
223
|
-
const isScalarMapping = (value: unknown): boolean =>
|
|
224
|
-
typeof value
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
Object.values(value).every((member) => typeof member === "string")
|
|
225
|
+
const isScalarMapping = (value: unknown): boolean => {
|
|
226
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false
|
|
227
|
+
const prototype = Object.getPrototypeOf(value)
|
|
228
|
+
if (prototype !== null && prototype !== Object.prototype) return false
|
|
229
|
+
return Object.values(value).every((member) => typeof member === "string")
|
|
230
|
+
}
|
|
228
231
|
|
|
229
232
|
/**
|
|
230
233
|
* Checks already-parsed Agent Skills frontmatter against the specification's
|