@webskill/sdk 0.0.6 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +180 -46
- package/dist/browser.d.ts +5 -1
- package/dist/browser.js +7 -2
- package/dist/{dist-nXiR40hi.js → dist-CiYRkm71.js} +16 -746
- package/dist/{dist-33_zuOCm.js → dist-DfKKj86A.js} +3 -1
- package/dist/{dist-BQruQ9Hv.js → dist-Dv4a1Jkm.js} +15 -3
- package/dist/governance.d.ts +3 -2
- package/dist/governance.js +2 -2
- package/dist/{index-vi7GPemR.d.ts → index-DuodMfQw.d.ts} +3 -1
- package/dist/{index-DCifjtJx.d.ts → index-S8uza3ld.d.ts} +19 -595
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/mcp.d.ts +3 -1
- package/dist/mcp.js +3 -1
- package/dist/memoryArtifactStore-C9lFVqPF-U8nXvqL9.js +637 -0
- package/dist/node.d.ts +4 -3
- package/dist/node.js +3 -2
- package/dist/testing-pn3NhXSV.js +117 -0
- package/dist/testing.d.ts +73 -0
- package/dist/testing.js +4 -0
- package/dist/types-CgNC-oQu-DCklnS0h.d.ts +539 -0
- package/dist/ui-react.d.ts +1 -1
- package/dist/ui-react.js +1 -1
- package/dist/ui-vue.d.ts +1 -1
- package/dist/ui-vue.js +1 -1
- package/dist/ui.d.ts +17 -4
- package/dist/ui.js +2 -2
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -9,22 +9,25 @@ governance.
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
11
11
|
- **Skill protocol** — Agent Skills compatible discovery, validation, cataloging
|
|
12
|
-
(JSON / XML), and
|
|
12
|
+
(JSON / XML), declarative `dependencies` and `allowed-tools`, skill packs
|
|
13
|
+
(multi-skill zip export/import with integrity digests).
|
|
13
14
|
- **Agent loop** — multi-turn tool calling with structured errors fed back to
|
|
14
|
-
the LLM, guardrails, lifecycle events, memory,
|
|
15
|
-
(missing-parameter forms, confirmations,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
the LLM, guardrails, lifecycle events, memory, human interaction
|
|
16
|
+
(missing-parameter forms, confirmations, authorization prompts), and
|
|
17
|
+
resumable interrupted runs.
|
|
18
|
+
- **Script sandbox** — `worker_threads` sandbox for Node, Web Worker sandbox for
|
|
19
|
+
the browser. Deny-by-default network policy, per-capability forced approval,
|
|
20
|
+
timeouts kill runaway scripts.
|
|
21
|
+
- **`navigator.webskill`** — a browser facade (`discover` / `read` / `validate` /
|
|
22
|
+
`run` / `install` / `uninstall`) assembled explicitly in one call.
|
|
20
23
|
- **MCP** — call page-provided tools and consume page-declared dynamic skills
|
|
21
24
|
over standard MCP transports (MessageChannel).
|
|
22
25
|
- **Governance** — LLM-generated skill candidates with mandatory review,
|
|
23
26
|
approval workflows, audit log, versioning/rollback, quarantine, evaluation,
|
|
24
27
|
and scoring.
|
|
25
|
-
- **UI** — framework-agnostic
|
|
26
|
-
adapters (Vercel AI SDK, OpenUI, A2UI), plus React and
|
|
27
|
-
primitives.
|
|
28
|
+
- **UI** — framework-agnostic forms, result rendering (markdown, tables, SVG
|
|
29
|
+
charts), generative UI adapters (Vercel AI SDK, OpenUI, A2UI), plus React and
|
|
30
|
+
Vue component primitives.
|
|
28
31
|
|
|
29
32
|
## Installation
|
|
30
33
|
|
|
@@ -35,53 +38,184 @@ npm install @webskill/sdk
|
|
|
35
38
|
React/Vue integrations require their respective peer dependencies
|
|
36
39
|
(`react` + `react-dom`, or `vue`), which are optional.
|
|
37
40
|
|
|
41
|
+
## Requirements
|
|
42
|
+
|
|
43
|
+
- Node.js >= 22.18 (native type stripping for `.ts` skill scripts)
|
|
44
|
+
- Modern browsers for the browser host (OPFS, Web Workers, ES modules)
|
|
45
|
+
|
|
38
46
|
## Quick start (Node)
|
|
39
47
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
});
|
|
48
|
+
Runs as-is with the bundled mock LLM — see
|
|
49
|
+
[`examples/quickstart-node`](../examples/quickstart-node) for the full project.
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
import { WebSkillRuntime } from '@webskill/sdk';
|
|
53
|
+
import { NodeFS, SandboxedScriptExecutor } from '@webskill/sdk/node';
|
|
54
|
+
import { MockLlmClient } from '@webskill/sdk/testing';
|
|
55
|
+
|
|
56
|
+
const fs = new NodeFS();
|
|
57
|
+
const llm = new MockLlmClient([
|
|
58
|
+
{ toolCalls: [{ id: 'c1', name: 'read_skill_file', arguments: { skillName: 'greeter' } }] },
|
|
59
|
+
{ toolCalls: [{ id: 'c2', name: 'greeter__greet', arguments: { text: 'world' } }] },
|
|
60
|
+
{ content: 'Greeted the world.' }
|
|
61
|
+
]);
|
|
55
62
|
|
|
56
|
-
|
|
57
|
-
const { entries, issues } = await runtime.discover();
|
|
58
|
-
console.log(
|
|
59
|
-
entries.map((e) => e.name),
|
|
60
|
-
issues
|
|
61
|
-
);
|
|
63
|
+
const runtime = new WebSkillRuntime({ fs, roots: ['./skills'], llm, executor: new SandboxedScriptExecutor(fs) });
|
|
62
64
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
const catalog = await runtime.discover();
|
|
66
|
+
console.log(catalog.entries.map((e) => e.name));
|
|
67
|
+
|
|
68
|
+
const { output, run } = await runtime.run('Greet the world.');
|
|
65
69
|
console.log(output, run.status, run.trace.length);
|
|
66
70
|
```
|
|
67
71
|
|
|
72
|
+
For a real LLM, replace the mock with `OpenAiCompatibleClient`:
|
|
73
|
+
|
|
74
|
+
```js
|
|
75
|
+
import { OpenAiCompatibleClient } from '@webskill/sdk';
|
|
76
|
+
|
|
77
|
+
const llm = new OpenAiCompatibleClient({
|
|
78
|
+
baseUrl: 'https://your-llm-endpoint/v1',
|
|
79
|
+
apiKey: process.env.LLM_API_KEY,
|
|
80
|
+
model: 'your-model'
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
68
84
|
## Subpath exports
|
|
69
85
|
|
|
70
|
-
|
|
71
|
-
| -------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
72
|
-
| `@webskill/sdk` | Core protocol + runtime engine (discovery, agent loop, LLM clients, routing, interaction, memory, artifacts, trace) |
|
|
73
|
-
| `@webskill/sdk/node` | Node host: NodeFS, script executors (in-process + sandboxed), file stores, skill manager, CLI UI bridge, env helpers |
|
|
74
|
-
| `@webskill/sdk/browser` | Browser host: OPFS provider, Web Worker script sandbox, worker runtime host/client |
|
|
75
|
-
| `@webskill/sdk/mcp` | MCP transports, endpoint registry, tool resolver, temporary skills, WebMCP adapter, runtime plugin |
|
|
76
|
-
| `@webskill/sdk/ui` | Framework-agnostic forms, result rendering, mini markdown, Vercel/OpenUI/A2UI adapters, A2UI Lit runtime |
|
|
77
|
-
| `@webskill/sdk/ui-react` | React bridge state + InteractionForm/ResultBlocks/StreamingText components |
|
|
78
|
-
| `@webskill/sdk/ui-vue` | Vue bridge state + equivalent components |
|
|
79
|
-
| `@webskill/sdk/governance` | Candidates, approval, audit, versioning, state policy, evaluation, scoring, documents |
|
|
86
|
+
### `@webskill/sdk` (main entry)
|
|
80
87
|
|
|
81
|
-
|
|
88
|
+
Core protocol + runtime engine: discovery, catalog, validation, agent loop, LLM
|
|
89
|
+
clients, routing, interaction types, memory, artifacts, tracing, network policy,
|
|
90
|
+
capability approval, and the environment-agnostic `createWebSkillApi` facade.
|
|
82
91
|
|
|
83
|
-
|
|
84
|
-
|
|
92
|
+
```js
|
|
93
|
+
import { SkillDiscovery, validateSkills, createWebSkillApi } from '@webskill/sdk';
|
|
94
|
+
|
|
95
|
+
const api = createWebSkillApi({ fs, roots: ['./skills'], llm, skillManager });
|
|
96
|
+
const report = await api.validate('./skills');
|
|
97
|
+
const run = await api.run('Summarize the references of skill greeter.');
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### `@webskill/sdk/node`
|
|
101
|
+
|
|
102
|
+
Node host: `NodeFS`, script executors (in-process + `worker_threads` sandbox),
|
|
103
|
+
file-backed stores, `SkillManager` (install/export incl. multi-skill packs),
|
|
104
|
+
CLI UI bridge, schema inference.
|
|
105
|
+
|
|
106
|
+
```js
|
|
107
|
+
import { NodeFS, SkillManager } from '@webskill/sdk/node';
|
|
108
|
+
|
|
109
|
+
const manager = new SkillManager({ managedRoot: './.webskill/skills' });
|
|
110
|
+
await manager.install({ type: 'http', url: 'https://example.com/greeter.zip' });
|
|
111
|
+
await manager.exportPack(['greeter', 'calculator'], { outPath: './pack.zip' });
|
|
112
|
+
console.log((await manager.verifyIntegrity('greeter')).ok);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### `@webskill/sdk/browser`
|
|
116
|
+
|
|
117
|
+
Browser host: OPFS provider, Web Worker script sandbox (deny-by-default network
|
|
118
|
+
policy), worker runtime host/client, `BrowserSkillManager`, and the
|
|
119
|
+
`navigator.webskill` assembler. See
|
|
120
|
+
[`examples/quickstart-browser`](../examples/quickstart-browser).
|
|
121
|
+
|
|
122
|
+
```js
|
|
123
|
+
import { installWebSkillNavigator } from '@webskill/browser';
|
|
124
|
+
|
|
125
|
+
const api = installWebSkillNavigator({ roots: ['/skills'], llm });
|
|
126
|
+
const catalog = await navigator.webskill.discover('/skills');
|
|
127
|
+
const run = await navigator.webskill.run('Greet the world.');
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### `@webskill/sdk/mcp`
|
|
131
|
+
|
|
132
|
+
MCP integration: MessageChannel transport, endpoint registry, tool resolver,
|
|
133
|
+
temporary (page-declared) skills, WebMCP adapter, runtime plugin.
|
|
134
|
+
|
|
135
|
+
```js
|
|
136
|
+
import { MessageChannelTransport, serveSkillAsMcp } from '@webskill/sdk/mcp';
|
|
137
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
138
|
+
|
|
139
|
+
const server = new McpServer({ name: 'page', version: '0.1.0' });
|
|
140
|
+
serveSkillAsMcp(server, { name: 'greeter', description: 'Greet someone', body: '# Greeter' });
|
|
141
|
+
await server.connect(new MessageChannelTransport(port));
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### `@webskill/sdk/ui`
|
|
145
|
+
|
|
146
|
+
Framework-agnostic UI: form models + `WebFormBridge`, result rendering
|
|
147
|
+
(markdown / table / mini-chart SVG), mini markdown, generative UI adapters
|
|
148
|
+
(Vercel AI SDK, OpenUI, A2UI).
|
|
149
|
+
|
|
150
|
+
```js
|
|
151
|
+
import { WebFormBridge } from '@webskill/sdk/ui';
|
|
152
|
+
|
|
153
|
+
const bridge = new WebFormBridge({ mount: document.querySelector('#ui') });
|
|
154
|
+
// pass as uiBridge to the runtime: forms, confirmations, and authorization
|
|
155
|
+
// prompts render as real DOM, results (incl. charts) render on completion.
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### `@webskill/sdk/ui-react`
|
|
159
|
+
|
|
160
|
+
React bridge state + `InteractionForm` / `ResultBlocks` / `StreamingText`
|
|
161
|
+
components (requires `react` + `react-dom`).
|
|
162
|
+
|
|
163
|
+
```jsx
|
|
164
|
+
import { ReactBridgeState, InteractionForm, ResultBlocks } from '@webskill/sdk/ui-react';
|
|
165
|
+
|
|
166
|
+
const bridge = new ReactBridgeState();
|
|
167
|
+
// <InteractionForm bridge={bridge} /> <ResultBlocks bridge={bridge} />
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### `@webskill/sdk/ui-vue`
|
|
171
|
+
|
|
172
|
+
Vue bridge state + equivalent components (requires `vue`).
|
|
173
|
+
|
|
174
|
+
```js
|
|
175
|
+
import { VueBridgeState, InteractionForm, ResultBlocks } from '@webskill/sdk/ui-vue';
|
|
176
|
+
|
|
177
|
+
const bridge = new VueBridgeState();
|
|
178
|
+
// <InteractionForm :bridge="bridge" /> <ResultBlocks :bridge="bridge" />
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### `@webskill/sdk/governance`
|
|
182
|
+
|
|
183
|
+
Governance: skill candidates with mandatory review, approval workflows, audit
|
|
184
|
+
log, versioning/rollback, quarantine, evaluation, scoring, dependency graph.
|
|
185
|
+
|
|
186
|
+
```js
|
|
187
|
+
import { DependencyGraph } from '@webskill/sdk/governance';
|
|
188
|
+
|
|
189
|
+
const graph = DependencyGraph.buildFromCatalog(catalog.entries, documents);
|
|
190
|
+
console.log(graph.dependenciesOf('greeter'));
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### `@webskill/sdk/testing`
|
|
194
|
+
|
|
195
|
+
Test facilities (moved out of the main entry in 0.1.0): `MockLlmClient`,
|
|
196
|
+
`MockUiBridge`, `InMemoryStore`, `MemoryArtifactStore`.
|
|
197
|
+
|
|
198
|
+
```js
|
|
199
|
+
import { MockLlmClient, MockUiBridge, InMemoryStore, MemoryArtifactStore } from '@webskill/sdk/testing';
|
|
200
|
+
|
|
201
|
+
const llm = new MockLlmClient([{ content: 'deterministic answer' }]);
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Stability
|
|
205
|
+
|
|
206
|
+
This package follows semver starting at 0.1.0. Public symbols carry JSDoc
|
|
207
|
+
stability tags:
|
|
208
|
+
|
|
209
|
+
- **`@stable`** — covered by the semver contract: bug fixes ship in patch,
|
|
210
|
+
backwards-compatible capabilities in minor, breaking changes only in major
|
|
211
|
+
(with release notes).
|
|
212
|
+
- **`@experimental`** — may change in minor/patch releases. Currently:
|
|
213
|
+
`ExperimentalWebMcpAdapter`, `resumeRun` and the `RunSnapshot` format,
|
|
214
|
+
the A2UI/OpenUI adapters, and the `authorize` interaction type.
|
|
215
|
+
|
|
216
|
+
The public API surface of every subpath is pinned by checked-in `.d.ts`
|
|
217
|
+
snapshots (`api-snapshots/`); any intentional change requires
|
|
218
|
+
`pnpm api:update` and is reviewable in the diff.
|
|
85
219
|
|
|
86
220
|
## License
|
|
87
221
|
|
package/dist/browser.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { H as SkillsLockfile, L as SkillManifest, P as SkillInstallSource, S as FileSystemProvider, W as VerifyResult, _ as RenderResultRequest, a as InteractionPolicy, c as LlmClient, d as LlmResponse, f as LlmStreamEvent, o as InteractionRequest, s as InteractionResponse, v as UiBridge, x as FileStat } from "./types-CgNC-oQu-DCklnS0h.js";
|
|
2
|
+
import { K as ScriptExecutionContext, Y as ToolDefinition, Z as ToolResult, _ as ExternalToolSource, _t as parseBridgeRequest, c as ApprovalScope, d as BridgeRequest, f as BridgeResponse, g as ExternalSkillProvider, k as NetworkPolicy, l as BridgeCapabilities, ot as bridgeError, q as ScriptExecutor, rt as WebSkillApi } from "./index-S8uza3ld.js";
|
|
2
3
|
//#region ../browser/dist/index.d.ts
|
|
3
4
|
//#region src/fs/featureDetection.d.ts
|
|
4
5
|
/** 检测当前环境是否可用 OPFS(navigator.storage.getDirectory) */
|
|
@@ -74,6 +75,7 @@ declare class TsTranspiler {
|
|
|
74
75
|
* D5:浏览器技能安装(http(s) zip / ArrayBuffer;tar/git/npm → TOOL_UNSUPPORTED)。
|
|
75
76
|
* 流程与 Node 对齐:staging → 解析 name → validateSkills(失败零残留)→ managed root →
|
|
76
77
|
* manifest(WebCrypto sha256)→ skills.lock.json;zip-slip 防护;manifest/lockfile 与 Node 同格式。
|
|
78
|
+
* @stable
|
|
77
79
|
*/
|
|
78
80
|
declare class BrowserSkillManager {
|
|
79
81
|
#private;
|
|
@@ -119,6 +121,7 @@ type WorkerFactory = () => WorkerLike;
|
|
|
119
121
|
/**
|
|
120
122
|
* Web Worker 脚本沙箱执行器:loadDefinition 与 execute 都在 Worker 内完成,
|
|
121
123
|
* 主线程从不 import 技能脚本;每次执行独立 Worker;超时 terminate 强杀。
|
|
124
|
+
* @stable
|
|
122
125
|
*/
|
|
123
126
|
declare class BrowserWorkerScriptExecutor implements ScriptExecutor {
|
|
124
127
|
#private;
|
|
@@ -157,6 +160,7 @@ declare global {
|
|
|
157
160
|
* BrowserSkillManager → createWebSkillApi;target 提供时挂 target.navigator
|
|
158
161
|
* (缺失则补空对象),否则挂真实 navigator.webskill。
|
|
159
162
|
* target 可注入(测试);返回值即门面本体(挂载只是副作用)。
|
|
163
|
+
* @stable
|
|
160
164
|
*/
|
|
161
165
|
declare function installWebSkillNavigator(config: {
|
|
162
166
|
roots?: string[];
|
package/dist/browser.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { D as
|
|
1
|
+
import { D as verifyManifest, E as validateSkills, S as parseSkillPackManifest, T as resolveInsideRoot, _ as exportSkills, c as SkillDiscovery, d as buildCatalog, f as buildManifest, i as SKILL_MANIFEST_FILE, r as SKILLS_LOCKFILE, s as SKILL_PACK_FILE, u as WebSkillError, v as isValidSkillName, x as parseSkillMarkdown } from "./memoryArtifactStore-C9lFVqPF-U8nXvqL9.js";
|
|
2
|
+
import { A as normalizeToolContent, C as createWebSkillApi, D as isNetworkAllowed, O as mergeCatalogEntries, _ as RUN_SNAPSHOT_SCHEMA_VERSION, a as CapabilityApproval, b as bridgeError, c as FsMemoryStore, f as OpenAiCompatibleClient, i as AgentLoop, j as parseBridgeRequest, k as networkUrlHost, l as FsRunSnapshotStore, p as ProgressiveRouter, s as FsArtifactStore } from "./dist-CiYRkm71.js";
|
|
3
|
+
import { n as MockLlmClient } from "./testing-pn3NhXSV.js";
|
|
2
4
|
import { unzipSync } from "fflate";
|
|
3
5
|
|
|
4
6
|
//#region ../browser/dist/index.js
|
|
@@ -442,6 +444,7 @@ const lockfilePath = (root) => `${root}/${SKILLS_LOCKFILE}`;
|
|
|
442
444
|
* D5:浏览器技能安装(http(s) zip / ArrayBuffer;tar/git/npm → TOOL_UNSUPPORTED)。
|
|
443
445
|
* 流程与 Node 对齐:staging → 解析 name → validateSkills(失败零残留)→ managed root →
|
|
444
446
|
* manifest(WebCrypto sha256)→ skills.lock.json;zip-slip 防护;manifest/lockfile 与 Node 同格式。
|
|
447
|
+
* @stable
|
|
445
448
|
*/
|
|
446
449
|
var BrowserSkillManager = class {
|
|
447
450
|
#fs;
|
|
@@ -685,6 +688,7 @@ const messageOf = (e) => e instanceof Error ? e.message : String(e);
|
|
|
685
688
|
/**
|
|
686
689
|
* Web Worker 脚本沙箱执行器:loadDefinition 与 execute 都在 Worker 内完成,
|
|
687
690
|
* 主线程从不 import 技能脚本;每次执行独立 Worker;超时 terminate 强杀。
|
|
691
|
+
* @stable
|
|
688
692
|
*/
|
|
689
693
|
var BrowserWorkerScriptExecutor = class {
|
|
690
694
|
#fs;
|
|
@@ -910,6 +914,7 @@ var BrowserWorkerScriptExecutor = class {
|
|
|
910
914
|
* BrowserSkillManager → createWebSkillApi;target 提供时挂 target.navigator
|
|
911
915
|
* (缺失则补空对象),否则挂真实 navigator.webskill。
|
|
912
916
|
* target 可注入(测试);返回值即门面本体(挂载只是副作用)。
|
|
917
|
+
* @stable
|
|
913
918
|
*/
|
|
914
919
|
function installWebSkillNavigator(config) {
|
|
915
920
|
const roots = config.roots ?? ["/skills"];
|
|
@@ -1132,7 +1137,7 @@ function startWorkerRuntimeHost(scope, overrides = {}) {
|
|
|
1132
1137
|
return [];
|
|
1133
1138
|
}
|
|
1134
1139
|
}))).flat();
|
|
1135
|
-
const catalog = providerEntries.length > 0 ? {
|
|
1140
|
+
const catalog = providerEntries.length > 0 ? { entries: mergeCatalogEntries(buildCatalog(entries).entries, providerEntries) } : buildCatalog(entries);
|
|
1136
1141
|
const route = await new ProgressiveRouter().route(catalog);
|
|
1137
1142
|
const uiBridge = new WorkerUiBridge(scope);
|
|
1138
1143
|
activeUiBridge = uiBridge;
|