web-skill 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { ZodTypeAny } from \"zod\";\n\nimport type {\n AddWebSkillFunctionOptions,\n NewWebSkillOptions,\n ResolvedWebSkillDefinition,\n ResolvedWebSkillFunctionDefinition,\n WebSkillBuilder,\n WebSkillFunctionDefinition,\n WebSkillFunctionHandler,\n WebSkillGenerator,\n WebSkillMetadata,\n WebSkillsWindowShape,\n WebSkillWindowEntry,\n WebSkillWindowFunction,\n} from \"./types.ts\";\nimport { ensureUniqueString, slugifySkillSegment, titleFromName, toSkillKey } from \"./utils.ts\";\n\ninterface MutableWebSkillDefinition {\n description: string | null;\n functions: WebSkillFunctionDefinition<any, any>[];\n key: string;\n name: string;\n slug: string;\n title: string;\n}\n\nclass WebSkillBuilderImpl implements WebSkillBuilder {\n constructor(private readonly skill: MutableWebSkillDefinition) {}\n\n addFunction<TInput, TOutput>(\n func: WebSkillFunctionHandler<TInput, TOutput>,\n name: string,\n options: AddWebSkillFunctionOptions<TInput, TOutput> = {},\n ): WebSkillBuilder {\n if (typeof func !== \"function\") {\n throw new TypeError(`web-skill function \"${name}\" must be a function.`);\n }\n\n const normalizedName = name.trim();\n if (!normalizedName) {\n throw new TypeError(\"web-skill function name must not be empty.\");\n }\n if (normalizedName === \"_meta\") {\n throw new TypeError('web-skill function name \"_meta\" is reserved.');\n }\n\n const existing = this.skill.functions.find((definition) => definition.name === normalizedName);\n if (existing) {\n throw new Error(\n `web-skill \"${this.skill.key}\" already contains a function named \"${normalizedName}\".`,\n );\n }\n\n this.skill.functions.push({\n func,\n name: normalizedName,\n description: options.description?.trim() || undefined,\n inputSchema: options.inputSchema,\n outputSchema: options.outputSchema,\n });\n\n return this;\n }\n}\n\nclass WebSkillGeneratorImpl implements WebSkillGenerator {\n private readonly skills: MutableWebSkillDefinition[] = [];\n private readonly usedKeys = new Set<string>();\n private readonly usedNames = new Set<string>();\n private readonly usedSlugs = new Set<string>();\n\n newSkill(options: NewWebSkillOptions = {}): WebSkillBuilder {\n const skillIndex = this.skills.length + 1;\n const fallbackName = `web-skill-${skillIndex}`;\n const requestedName = options.name?.trim();\n const requestedTitle = options.title?.trim();\n const requestedIdentifier = requestedName || requestedTitle || fallbackName;\n const requestedKeyBase = requestedName || requestedTitle || `webSkill${skillIndex}`;\n const requestedTitleBase = requestedTitle || requestedName || fallbackName;\n\n const slug = ensureUniqueString(slugifySkillSegment(requestedIdentifier), this.usedSlugs);\n const keyBase = toSkillKey(requestedKeyBase);\n const key = ensureUniqueString(keyBase, this.usedKeys, (index) => `${keyBase}${index + 1}`);\n const nameBase = requestedName || slug;\n const name = ensureUniqueString(nameBase, this.usedNames);\n const title = requestedTitle || titleFromName(requestedTitleBase);\n\n const skill: MutableWebSkillDefinition = {\n description: options.description?.trim() || null,\n functions: [],\n key,\n name,\n slug,\n title,\n };\n\n this.skills.push(skill);\n return new WebSkillBuilderImpl(skill);\n }\n\n getSkills(): ResolvedWebSkillDefinition[] {\n return this.skills.map((skill) => ({\n description: skill.description,\n key: skill.key,\n name: skill.name,\n slug: skill.slug,\n title: skill.title,\n functions: skill.functions.map<ResolvedWebSkillFunctionDefinition>((definition) => ({\n name: definition.name,\n description: definition.description ?? undefined,\n inputSchema: definition.inputSchema,\n outputSchema: definition.outputSchema,\n })),\n }));\n }\n\n install(target?: Window): WebSkillsWindowShape {\n const windowTarget = target ?? resolveWindowTarget();\n const registry = (windowTarget._web_skills ??= {});\n\n for (const skill of this.skills) {\n const entry: Partial<WebSkillWindowEntry> = {};\n const metadata: WebSkillMetadata = {\n description: skill.description,\n functions: skill.functions.map((definition) => ({\n description: definition.description ?? null,\n hasInputSchema: Boolean(definition.inputSchema),\n hasOutputSchema: Boolean(definition.outputSchema),\n name: definition.name,\n })),\n key: skill.key,\n name: skill.name,\n title: skill.title,\n };\n\n entry._meta = metadata;\n\n for (const definition of skill.functions) {\n entry[definition.name] = wrapFunction(skill.key, definition);\n }\n\n registry[skill.key] = entry as WebSkillWindowEntry;\n }\n\n return registry;\n }\n}\n\nfunction resolveWindowTarget(): Window {\n if (typeof window === \"undefined\") {\n throw new Error(\"web-skill install() requires a browser window target.\");\n }\n\n return window;\n}\n\nfunction wrapFunction(\n skillKey: string,\n definition: WebSkillFunctionDefinition<any, any>,\n): WebSkillWindowFunction {\n return async (input: unknown) => {\n const parsedInput = parseWithSchema(definition.inputSchema, input);\n const result = await definition.func(parsedInput);\n return parseWithSchema(definition.outputSchema, result);\n };\n}\n\nfunction parseWithSchema(schema: ZodTypeAny | undefined, value: unknown): unknown {\n if (!schema) {\n return value;\n }\n\n return schema.parse(value);\n}\n\nexport function createWebSkillGenerator(): WebSkillGenerator {\n return new WebSkillGeneratorImpl();\n}\n\ndeclare global {\n interface Window {\n _web_skills?: WebSkillsWindowShape;\n }\n}\n"]}
@@ -0,0 +1,71 @@
1
+ import { Plugin } from 'vite';
2
+ import { ZodType } from 'zod';
3
+
4
+ type MaybePromise<T> = T | Promise<T>;
5
+ type WebSkillFunctionHandler<TInput = unknown, TOutput = unknown> = (input: TInput) => MaybePromise<TOutput>;
6
+ interface AddWebSkillFunctionOptions<TInput = unknown, TOutput = unknown> {
7
+ description?: string;
8
+ inputSchema?: ZodType<TInput>;
9
+ outputSchema?: ZodType<TOutput>;
10
+ }
11
+ interface WebSkillFunctionDefinition<TInput = unknown, TOutput = unknown> extends AddWebSkillFunctionOptions<TInput, TOutput> {
12
+ func: WebSkillFunctionHandler<TInput, TOutput>;
13
+ name: string;
14
+ }
15
+ interface NewWebSkillOptions {
16
+ description?: string;
17
+ name?: string;
18
+ title?: string;
19
+ }
20
+ interface ResolvedWebSkillFunctionDefinition<TInput = unknown, TOutput = unknown> extends AddWebSkillFunctionOptions<TInput, TOutput> {
21
+ name: string;
22
+ }
23
+ interface ResolvedWebSkillDefinition {
24
+ description: string | null;
25
+ functions: ResolvedWebSkillFunctionDefinition<any, any>[];
26
+ key: string;
27
+ name: string;
28
+ slug: string;
29
+ title: string;
30
+ }
31
+ interface WebSkillFunctionMetadata {
32
+ description: string | null;
33
+ hasInputSchema: boolean;
34
+ hasOutputSchema: boolean;
35
+ name: string;
36
+ }
37
+ interface WebSkillMetadata {
38
+ description: string | null;
39
+ functions: WebSkillFunctionMetadata[];
40
+ key: string;
41
+ name: string;
42
+ title: string;
43
+ }
44
+ type WebSkillWindowFunction = (input: unknown) => Promise<unknown>;
45
+ type WebSkillWindowEntry = Record<string, WebSkillWindowFunction | WebSkillMetadata> & {
46
+ _meta: WebSkillMetadata;
47
+ };
48
+ interface WebSkillsWindowShape {
49
+ [skillKey: string]: WebSkillWindowEntry;
50
+ }
51
+ interface WebSkillLinkTag {
52
+ href: string;
53
+ title: string;
54
+ type: "text/markdown";
55
+ }
56
+ interface WebSkillVitePluginOptions {
57
+ generator: WebSkillGenerator;
58
+ publicBasePath?: string;
59
+ }
60
+ interface WebSkillGenerator {
61
+ getSkills(): ResolvedWebSkillDefinition[];
62
+ install(target?: Window): WebSkillsWindowShape;
63
+ newSkill(options?: NewWebSkillOptions): WebSkillBuilder;
64
+ }
65
+ interface WebSkillBuilder {
66
+ addFunction<TInput, TOutput>(func: WebSkillFunctionHandler<TInput, TOutput>, name: string, options?: AddWebSkillFunctionOptions<TInput, TOutput>): WebSkillBuilder;
67
+ }
68
+
69
+ declare function webSkillVitePlugin(options: WebSkillVitePluginOptions): Plugin;
70
+
71
+ export { type AddWebSkillFunctionOptions as A, type NewWebSkillOptions as N, type ResolvedWebSkillDefinition as R, type WebSkillsWindowShape as W, type WebSkillGenerator as a, type WebSkillLinkTag as b, type ResolvedWebSkillFunctionDefinition as c, type WebSkillBuilder as d, type WebSkillFunctionDefinition as e, type WebSkillFunctionHandler as f, type WebSkillMetadata as g, type WebSkillVitePluginOptions as h, type WebSkillWindowEntry as i, type WebSkillWindowFunction as j, webSkillVitePlugin as w };
@@ -0,0 +1,3 @@
1
+ import 'vite';
2
+ export { w as webSkillVitePlugin } from './vite-plugin-5xZLBPsq.js';
3
+ import 'zod';
@@ -0,0 +1,3 @@
1
+ export { webSkillVitePlugin } from './chunk-YVQDAY47.js';
2
+ //# sourceMappingURL=vite-plugin.js.map
3
+ //# sourceMappingURL=vite-plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"vite-plugin.js"}
package/docs/api.md ADDED
@@ -0,0 +1,121 @@
1
+ # API Reference
2
+
3
+ `web-skill` exposes a small public API surface on purpose. The package is designed to let an app define task-level browser actions once, then reuse that definition for runtime registration, generated markdown, and HTML discovery tags.
4
+
5
+ ## `createWebSkillGenerator()`
6
+
7
+ Creates a generator instance that owns one or more skills.
8
+
9
+ Returned methods:
10
+
11
+ - `newSkill(options?)`
12
+ - `getSkills()`
13
+ - `install(target?)`
14
+
15
+ ## `newSkill(options?)`
16
+
17
+ Creates one logical skill definition.
18
+
19
+ Options:
20
+
21
+ - `name?: string`
22
+ - `title?: string`
23
+ - `description?: string`
24
+
25
+ Behavior:
26
+
27
+ - `name` is the stable identifier when supplied
28
+ - `title` is the human-facing label shown to agents
29
+ - duplicate names, keys, and slugs are automatically disambiguated
30
+ - omitted values fall back to generated names such as `web-skill-1`
31
+
32
+ ## `skill.addFunction(func, name, options?)`
33
+
34
+ Registers one task-level function under the current skill.
35
+
36
+ Arguments:
37
+
38
+ - `func`: `(input) => output | Promise<output>`
39
+ - `name`: string
40
+ - `options?.description`
41
+ - `options?.inputSchema`
42
+ - `options?.outputSchema`
43
+
44
+ Runtime guarantees:
45
+
46
+ - empty names are rejected
47
+ - `_meta` is reserved
48
+ - duplicate function names within a skill are rejected
49
+ - `inputSchema` and `outputSchema` are enforced with Zod when provided
50
+
51
+ ## `generator.install(target?)`
52
+
53
+ Registers all configured skills under `window._web_skills`, or under the provided `target` object.
54
+
55
+ Generated shape:
56
+
57
+ ```ts
58
+ window._web_skills.<skillKey>.<functionName>(input)
59
+ window._web_skills.<skillKey>._meta
60
+ ```
61
+
62
+ If `target` is omitted outside a browser environment, `install()` throws.
63
+
64
+ ## `generator.getSkills()`
65
+
66
+ Returns the normalized skill metadata used by both the runtime and markdown generation helpers.
67
+
68
+ Each skill includes:
69
+
70
+ - `key`
71
+ - `name`
72
+ - `slug`
73
+ - `title`
74
+ - `description`
75
+ - `functions`
76
+
77
+ ## `generateSkillMarkdown(skill)`
78
+
79
+ Renders one normalized skill definition into a `SKILL.md` document suitable for serving or emitting as a build asset.
80
+
81
+ ## `renderZodSchema(schema)`
82
+
83
+ Converts a Zod schema into a compact TypeScript-like summary string for documentation output.
84
+
85
+ ## `buildWebSkillLinkTags(skills, basePath?)`
86
+
87
+ Creates the `<link rel="web-skill" ...>` metadata records used by the Vite plugin and any custom integrations.
88
+
89
+ Return shape:
90
+
91
+ ```ts
92
+ {
93
+ href: string;
94
+ title: string;
95
+ type: "text/markdown";
96
+ }
97
+ ```
98
+
99
+ ## `webSkillVitePlugin(options)`
100
+
101
+ Vite integration that:
102
+
103
+ - serves generated `SKILL.md` files during local development
104
+ - emits `skills/<slug>/SKILL.md` assets during build
105
+ - injects `<link rel="web-skill">` tags into transformed HTML
106
+
107
+ Options:
108
+
109
+ - `generator: WebSkillGenerator`
110
+ - `publicBasePath?: string`
111
+
112
+ ## Error behavior
113
+
114
+ Common synchronous errors:
115
+
116
+ - `web-skill function name must not be empty.`
117
+ - `web-skill function name "_meta" is reserved.`
118
+ - `web-skill "<key>" already contains a function named "<name>".`
119
+ - `web-skill install() requires a browser window target.`
120
+
121
+ Schema validation errors are surfaced directly from Zod.
package/package.json CHANGED
@@ -1,17 +1,28 @@
1
1
  {
2
2
  "name": "web-skill",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Generate browser-advertised skills, runtime registries, and Vite head tags for agent-friendly web apps.",
5
+ "author": "Dillion Kum <dillion@dimbreak.com>",
5
6
  "license": "MIT",
6
7
  "type": "module",
7
- "main": "./src/index.ts",
8
+ "main": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
8
10
  "exports": {
9
- ".": "./src/index.ts",
10
- "./vite": "./src/vite-plugin.ts"
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "./vite": {
17
+ "types": "./dist/vite-plugin.d.ts",
18
+ "import": "./dist/vite-plugin.js",
19
+ "default": "./dist/vite-plugin.js"
20
+ }
11
21
  },
12
22
  "files": [
13
- "src",
23
+ "dist",
14
24
  "skills",
25
+ "docs",
15
26
  "README.md",
16
27
  "LICENSE"
17
28
  ],
@@ -20,8 +31,17 @@
20
31
  "node": ">=20"
21
32
  },
22
33
  "scripts": {
23
- "check": "npm run typecheck",
24
- "typecheck": "tsc --noEmit -p tsconfig.json"
34
+ "clean": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
35
+ "build": "npm run clean && tsup src/index.ts src/vite-plugin.ts --format esm --dts --sourcemap --target es2022 --out-dir dist --clean --treeshake",
36
+ "check": "npm run verify",
37
+ "prepack": "npm run build",
38
+ "test": "npm run build && node --import tsx --test tests/**/*.test.ts",
39
+ "typecheck": "tsc --noEmit -p tsconfig.json",
40
+ "verify": "npm run typecheck && npm run test",
41
+ "prepublishOnly": "npm run verify"
42
+ },
43
+ "publishConfig": {
44
+ "access": "public"
25
45
  },
26
46
  "repository": {
27
47
  "type": "git",
@@ -30,7 +50,7 @@
30
50
  "bugs": {
31
51
  "url": "https://github.com/dimbreak/webskill/issues"
32
52
  },
33
- "homepage": "https://github.com/dimbreak/webskill#readme",
53
+ "homepage": "https://www.npmjs.com/package/web-skill",
34
54
  "keywords": [
35
55
  "agent",
36
56
  "automation",
@@ -47,6 +67,8 @@
47
67
  },
48
68
  "devDependencies": {
49
69
  "@types/node": "^24.3.3",
70
+ "tsx": "^4.20.6",
71
+ "tsup": "^8.5.0",
50
72
  "typescript": "^5.7.3",
51
73
  "vite": "^7.0.0"
52
74
  }
package/src/index.ts DELETED
@@ -1,20 +0,0 @@
1
- export { generateSkillMarkdown, renderZodSchema } from "./markdown.ts";
2
- export { createWebSkillGenerator } from "./runtime.ts";
3
- export { webSkillVitePlugin } from "./vite-plugin.ts";
4
- export type {
5
- AddWebSkillFunctionOptions,
6
- NewWebSkillOptions,
7
- ResolvedWebSkillDefinition,
8
- ResolvedWebSkillFunctionDefinition,
9
- WebSkillBuilder,
10
- WebSkillFunctionDefinition,
11
- WebSkillFunctionHandler,
12
- WebSkillGenerator,
13
- WebSkillLinkTag,
14
- WebSkillMetadata,
15
- WebSkillsWindowShape,
16
- WebSkillVitePluginOptions,
17
- WebSkillWindowEntry,
18
- WebSkillWindowFunction,
19
- } from "./types.ts";
20
- export { buildWebSkillLinkTags } from "./utils.ts";
package/src/markdown.ts DELETED
@@ -1,230 +0,0 @@
1
- import type { ZodTypeAny } from "zod";
2
-
3
- import type { ResolvedWebSkillDefinition, ResolvedWebSkillFunctionDefinition } from "./types.ts";
4
-
5
- const INDENT = " ";
6
-
7
- interface LooseZodDefinition {
8
- typeName?: string;
9
- [key: string]: unknown;
10
- }
11
-
12
- export function generateSkillMarkdown(skill: ResolvedWebSkillDefinition): string {
13
- const description =
14
- skill.description
15
- ?? `Expose browser-callable functions under \`window._web_skills.${skill.key}\`.`;
16
-
17
- const lines: string[] = [
18
- "---",
19
- `name: ${skill.slug}`,
20
- `description: ${escapeFrontmatterValue(description)}`,
21
- "---",
22
- "",
23
- `# ${skill.title}`,
24
- "",
25
- "Use the browser console entrypoint:",
26
- "",
27
- "```js",
28
- `window._web_skills.${skill.key}`,
29
- "```",
30
- "",
31
- "Available functions:",
32
- "",
33
- ];
34
-
35
- for (const definition of skill.functions) {
36
- lines.push(...renderFunctionSection(skill, definition), "");
37
- }
38
-
39
- return `${lines.join("\n").trimEnd()}\n`;
40
- }
41
-
42
- function renderFunctionSection(
43
- skill: ResolvedWebSkillDefinition,
44
- definition: ResolvedWebSkillFunctionDefinition,
45
- ): string[] {
46
- const inputSchema = definition.inputSchema ? renderZodSchema(definition.inputSchema) : "unknown";
47
- const outputSchema = definition.outputSchema ? renderZodSchema(definition.outputSchema) : "unknown";
48
-
49
- return [
50
- `## \`${definition.name}(input)\``,
51
- "",
52
- `Purpose: ${definition.description ?? `Invoke \`window._web_skills.${skill.key}.${definition.name}(input)\`.`}`,
53
- "",
54
- "Input:",
55
- "",
56
- "```ts",
57
- inputSchema,
58
- "```",
59
- "",
60
- "Output:",
61
- "",
62
- "```ts",
63
- outputSchema,
64
- "```",
65
- ];
66
- }
67
-
68
- export function renderZodSchema(schema: ZodTypeAny): string {
69
- return renderSchema(schema, 0);
70
- }
71
-
72
- function renderSchema(schema: ZodTypeAny, depth: number): string {
73
- const definition = getDefinition(schema);
74
- const typeName = definition?.typeName;
75
-
76
- switch (typeName) {
77
- case "ZodString":
78
- return "string";
79
- case "ZodNumber":
80
- return "number";
81
- case "ZodBoolean":
82
- return "boolean";
83
- case "ZodBigInt":
84
- return "bigint";
85
- case "ZodDate":
86
- return "Date";
87
- case "ZodUndefined":
88
- return "undefined";
89
- case "ZodNull":
90
- return "null";
91
- case "ZodVoid":
92
- return "void";
93
- case "ZodAny":
94
- return "any";
95
- case "ZodUnknown":
96
- return "unknown";
97
- case "ZodNever":
98
- return "never";
99
- case "ZodLiteral":
100
- return JSON.stringify(definition?.value);
101
- case "ZodEnum":
102
- return Array.isArray(definition?.values)
103
- ? definition.values.map((value) => JSON.stringify(value)).join(" | ")
104
- : "string";
105
- case "ZodNativeEnum":
106
- return renderNativeEnum(
107
- definition?.values && typeof definition.values === "object"
108
- ? (definition.values as Record<string, string | number>)
109
- : undefined,
110
- );
111
- case "ZodArray":
112
- return `${wrapType(renderSchema(definition?.type as ZodTypeAny, depth))}[]`;
113
- case "ZodOptional":
114
- return `${renderSchema(definition?.innerType as ZodTypeAny, depth)} | undefined`;
115
- case "ZodNullable":
116
- return `${renderSchema(definition?.innerType as ZodTypeAny, depth)} | null`;
117
- case "ZodDefault":
118
- case "ZodCatch":
119
- return renderSchema(definition?.innerType as ZodTypeAny, depth);
120
- case "ZodEffects":
121
- return renderSchema(definition?.schema as ZodTypeAny, depth);
122
- case "ZodBranded":
123
- return renderSchema(definition?.type as ZodTypeAny, depth);
124
- case "ZodUnion":
125
- return Array.isArray(definition?.options)
126
- ? definition.options.map((option) => wrapType(renderSchema(option as ZodTypeAny, depth))).join(" | ")
127
- : "unknown";
128
- case "ZodDiscriminatedUnion":
129
- return Array.from(
130
- definition?.options instanceof Map ? definition.options.values() : [],
131
- )
132
- .map((option) => wrapType(renderSchema(option as ZodTypeAny, depth)))
133
- .join(" | ");
134
- case "ZodIntersection":
135
- return `${wrapType(renderSchema(definition?.left as ZodTypeAny, depth))} & ${wrapType(renderSchema(definition?.right as ZodTypeAny, depth))}`;
136
- case "ZodTuple":
137
- return `[${Array.isArray(definition?.items)
138
- ? definition.items.map((item) => renderSchema(item as ZodTypeAny, depth)).join(", ")
139
- : ""}]`;
140
- case "ZodRecord":
141
- return `Record<${renderRecordKey(definition?.keyType as ZodTypeAny | undefined)}, ${renderSchema(definition?.valueType as ZodTypeAny, depth)}>`;
142
- case "ZodObject":
143
- return renderObjectSchema(schema, depth);
144
- case "ZodLazy":
145
- return typeof definition?.getter === "function"
146
- ? renderSchema(definition.getter() as ZodTypeAny, depth)
147
- : "unknown";
148
- default:
149
- return "unknown";
150
- }
151
- }
152
-
153
- function renderObjectSchema(schema: ZodTypeAny, depth: number): string {
154
- const definition = getDefinition(schema);
155
- const shapeSource = definition?.shape;
156
- const shape =
157
- typeof shapeSource === "function"
158
- ? (shapeSource() as Record<string, ZodTypeAny>)
159
- : ((shapeSource ?? {}) as Record<string, ZodTypeAny>);
160
- const entries = Object.entries(shape);
161
-
162
- if (entries.length === 0) {
163
- return "{}";
164
- }
165
-
166
- const propertyLines = entries.map(([key, propertySchema]) => {
167
- const optional = isOptionalSchema(propertySchema);
168
- const renderedType = renderSchema(optional ? unwrapOptionalSchema(propertySchema) : propertySchema, depth + 1);
169
- return `${indent(depth + 1)}${quotePropertyKey(key)}${optional ? "?" : ""}: ${renderedType};`;
170
- });
171
-
172
- return ["{", ...propertyLines, `${indent(depth)}}`].join("\n");
173
- }
174
-
175
- function renderNativeEnum(values: Record<string, string | number> | undefined): string {
176
- if (!values) {
177
- return "string | number";
178
- }
179
-
180
- const rendered = Array.from(
181
- new Set(
182
- Object.values(values).filter(
183
- (value): value is string | number => typeof value === "string" || typeof value === "number",
184
- ),
185
- ),
186
- );
187
-
188
- return rendered.map((value) => JSON.stringify(value)).join(" | ") || "string | number";
189
- }
190
-
191
- function renderRecordKey(keyType: ZodTypeAny | undefined): string {
192
- if (!keyType) {
193
- return "string";
194
- }
195
-
196
- return renderSchema(keyType, 0);
197
- }
198
-
199
- function isOptionalSchema(schema: ZodTypeAny): boolean {
200
- return typeof schema.isOptional === "function" ? schema.isOptional() : getDefinition(schema)?.typeName === "ZodOptional";
201
- }
202
-
203
- function unwrapOptionalSchema(schema: ZodTypeAny): ZodTypeAny {
204
- const definition = getDefinition(schema);
205
- if (definition?.typeName === "ZodOptional") {
206
- return definition.innerType as ZodTypeAny;
207
- }
208
-
209
- return schema;
210
- }
211
-
212
- function wrapType(value: string): string {
213
- return /[|&\n]/u.test(value) ? `(${value})` : value;
214
- }
215
-
216
- function quotePropertyKey(value: string): string {
217
- return /^[A-Za-z_$][A-Za-z0-9_$]*$/u.test(value) ? value : JSON.stringify(value);
218
- }
219
-
220
- function indent(depth: number): string {
221
- return INDENT.repeat(depth);
222
- }
223
-
224
- function getDefinition(schema: ZodTypeAny): LooseZodDefinition | undefined {
225
- return (schema as unknown as { _def?: LooseZodDefinition })._def;
226
- }
227
-
228
- function escapeFrontmatterValue(value: string): string {
229
- return JSON.stringify(value);
230
- }
package/src/types.ts DELETED
@@ -1,89 +0,0 @@
1
- import type { ZodType, ZodTypeAny } from "zod";
2
-
3
- export type MaybePromise<T> = T | Promise<T>;
4
-
5
- export type WebSkillFunctionHandler<TInput = unknown, TOutput = unknown> = (
6
- input: TInput,
7
- ) => MaybePromise<TOutput>;
8
-
9
- export interface AddWebSkillFunctionOptions<TInput = unknown, TOutput = unknown> {
10
- description?: string;
11
- inputSchema?: ZodType<TInput>;
12
- outputSchema?: ZodType<TOutput>;
13
- }
14
-
15
- export interface WebSkillFunctionDefinition<TInput = unknown, TOutput = unknown>
16
- extends AddWebSkillFunctionOptions<TInput, TOutput> {
17
- func: WebSkillFunctionHandler<TInput, TOutput>;
18
- name: string;
19
- }
20
-
21
- export interface NewWebSkillOptions {
22
- description?: string;
23
- name?: string;
24
- title?: string;
25
- }
26
-
27
- export interface ResolvedWebSkillFunctionDefinition<TInput = unknown, TOutput = unknown>
28
- extends AddWebSkillFunctionOptions<TInput, TOutput> {
29
- name: string;
30
- }
31
-
32
- export interface ResolvedWebSkillDefinition {
33
- description: string | null;
34
- functions: ResolvedWebSkillFunctionDefinition<any, any>[];
35
- key: string;
36
- name: string;
37
- slug: string;
38
- title: string;
39
- }
40
-
41
- export interface WebSkillFunctionMetadata {
42
- description: string | null;
43
- hasInputSchema: boolean;
44
- hasOutputSchema: boolean;
45
- name: string;
46
- }
47
-
48
- export interface WebSkillMetadata {
49
- description: string | null;
50
- functions: WebSkillFunctionMetadata[];
51
- key: string;
52
- name: string;
53
- title: string;
54
- }
55
-
56
- export type WebSkillWindowFunction = (input: unknown) => Promise<unknown>;
57
-
58
- export type WebSkillWindowEntry = Record<string, WebSkillWindowFunction | WebSkillMetadata> & {
59
- _meta: WebSkillMetadata;
60
- };
61
-
62
- export interface WebSkillsWindowShape {
63
- [skillKey: string]: WebSkillWindowEntry;
64
- }
65
-
66
- export interface WebSkillLinkTag {
67
- href: string;
68
- title: string;
69
- type: "text/markdown";
70
- }
71
-
72
- export interface WebSkillVitePluginOptions {
73
- generator: WebSkillGenerator;
74
- publicBasePath?: string;
75
- }
76
-
77
- export interface WebSkillGenerator {
78
- getSkills(): ResolvedWebSkillDefinition[];
79
- install(target?: Window): WebSkillsWindowShape;
80
- newSkill(options?: NewWebSkillOptions): WebSkillBuilder;
81
- }
82
-
83
- export interface WebSkillBuilder {
84
- addFunction<TInput, TOutput>(
85
- func: WebSkillFunctionHandler<TInput, TOutput>,
86
- name: string,
87
- options?: AddWebSkillFunctionOptions<TInput, TOutput>,
88
- ): WebSkillBuilder;
89
- }