@webskill/sdk 0.2.8 → 0.3.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 +42 -0
- package/dist/browser.d.ts +2 -2
- package/dist/browser.js +4 -5
- package/dist/client-BCM6Z3yq-qUQNkKrK.js +7787 -0
- package/dist/{dist-BQzncxXg.js → dist-8oQRa8Xz.js} +212 -13
- package/dist/{dist-CtBLBbEz.js → dist-ZKaM8j06.js} +2 -2
- package/dist/{dist-B9VLwOME.js → dist-rorEJsNi.js} +530 -44
- package/dist/governance.d.ts +4 -4
- package/dist/governance.js +1 -1
- package/dist/{index-QrHtAudz.d.ts → index-8d-oEDww.d.ts} +201 -2
- package/dist/{index-7DVaZJU7.d.ts → index-wiV5X8Rz.d.ts} +2 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/{jsonRenderRegistry-9GrWP_hE-CQY8bT9w.js → jsonRenderRegistry-9GrWP_hE-U6Do3Kid.js} +1 -1
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +2 -2
- package/dist/node.d.ts +293 -4
- package/dist/node.js +281 -7
- package/dist/{openUiLibrary-B8-Cvou9-D3RsU2EB.js → openUiLibrary-B8-Cvou9-BbpNTXS3.js} +1 -1
- package/dist/skillVersionStore-DOEI9ptb-BxbYL70B.d.ts +127 -0
- package/dist/stdio-CFMoANJJ-BxrTeXh7.js +31 -0
- package/dist/{testing-BUoXvm1u.js → testing-CsrG3XLz.js} +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +1 -1
- package/dist/{types-AmKCKJn_-BogJPQHU.d.ts → types-AmKCKJn_-VGabeXK4.d.ts} +137 -2
- package/dist/types-WovEf4ED-CZSDiiBU.js +6215 -0
- package/dist/ui-react.d.ts +2 -2
- package/dist/ui-react.js +5 -5
- package/dist/ui-vue.d.ts +1 -1
- package/dist/ui-vue.js +1 -1
- package/dist/ui.d.ts +2 -2
- package/dist/ui.js +2 -2
- package/dist/{webskillLitCatalog-CNaUpasU-CfSRvqCZ.js → webskillLitCatalog-CNaUpasU-BslMcxRZ.js} +1 -1
- package/package.json +4 -7
- package/dist/skillVersionStore-B7rGjtMi-BgnQho9v.d.ts +0 -365
package/dist/node.d.ts
CHANGED
|
@@ -1,7 +1,296 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { $ as SkillInstallSource, H as SKILL_MANIFEST_FILE, I as JsonSchema, N as FileStat, O as ArchiveLimits, P as FileSystemProvider, V as SKILLS_LOCKFILE, _ as RenderResultRequest, dt as TrustedKeyStore, ft as UnsignedPolicy, lt as SkillsLockfile, mt as VerifyResult, nt as SkillManagerPort, o as InteractionRequest, q as SignatureAuditSink, rt as SkillManifest, s as InteractionResponse, v as UiBridge } from "./types-AmKCKJn_-VGabeXK4.js";
|
|
2
|
+
import { F as NetworkPolicy, Ot as createScriptContext, Tt as WebSkillRuntimeDeps, _t as ToolResult, b as FsArtifactStore, ct as ScriptExecutor, d as BridgeCapabilities, ht as ToolDefinition, ot as SchemaInferer, st as ScriptExecutionContext, u as ApprovalScope, wt as WebSkillRuntime, x as FsMemoryStore } from "./index-8d-oEDww.js";
|
|
3
|
+
import { a as AuditLog, c as CandidateSkill, d as CandidateStore, h as SkillVersionStore, r as ApprovalPolicy } from "./skillVersionStore-DOEI9ptb-BxbYL70B.js";
|
|
3
4
|
import { n as LlmEnvConfig, s as probeLlmCapabilities, t as LlmCapabilities } from "./env-BPUBZCwJ-4jat_SVG.js";
|
|
4
|
-
import {
|
|
5
|
+
import { Readable, Writable } from "node:stream";
|
|
6
|
+
//#region ../node/dist/index.d.ts
|
|
7
|
+
//#region src/fs/nodeFs.d.ts
|
|
8
|
+
/**
|
|
9
|
+
* 基于 node:fs/promises 的 FileSystemProvider;接受 `/` 风格路径,写入自动创建父目录。
|
|
10
|
+
* 可选 root 模式:构造传入 root 后,read/write 操作先做 realpath 包含校验
|
|
11
|
+
* (root 与目标都 realpath 后前缀比对),经符号链接逃逸 root → FS_PATH_OUTSIDE_ROOT。
|
|
12
|
+
*/
|
|
13
|
+
declare class NodeFS implements FileSystemProvider {
|
|
14
|
+
#private;
|
|
15
|
+
readonly kind = "node";
|
|
16
|
+
constructor(deps?: {
|
|
17
|
+
root?: string;
|
|
18
|
+
});
|
|
19
|
+
/** root 模式:全部方法(read/write/exists/stat/list/mkdir/remove/rename)目标 realpath 必须落在 root realpath 前缀内 */
|
|
20
|
+
withRoot(root: string): NodeFS;
|
|
21
|
+
readText(p: string): Promise<string>;
|
|
22
|
+
writeText(p: string, content: string): Promise<void>;
|
|
23
|
+
appendText(p: string, content: string): Promise<void>;
|
|
24
|
+
readBinary(p: string): Promise<Uint8Array>;
|
|
25
|
+
writeBinary(p: string, content: Uint8Array): Promise<void>;
|
|
26
|
+
exists(p: string): Promise<boolean>;
|
|
27
|
+
stat(p: string): Promise<FileStat>;
|
|
28
|
+
list(p: string): Promise<FileStat[]>;
|
|
29
|
+
mkdir(p: string): Promise<void>;
|
|
30
|
+
remove(p: string, options?: {
|
|
31
|
+
recursive?: boolean;
|
|
32
|
+
}): Promise<void>;
|
|
33
|
+
rename(from: string, to: string): Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/executor/nodeScriptExecutor.d.ts
|
|
37
|
+
/**
|
|
38
|
+
* 进程内脚本执行器。接口按沙箱语义设计(context 无隐式宿主访问),
|
|
39
|
+
* worker_threads 沙箱见 deferred-items D1。
|
|
40
|
+
*/
|
|
41
|
+
declare class NodeScriptExecutor implements ScriptExecutor {
|
|
42
|
+
#private;
|
|
43
|
+
constructor(fs: FileSystemProvider);
|
|
44
|
+
loadDefinition(skillRoot: string, scriptName: string): Promise<ToolDefinition>;
|
|
45
|
+
execute(input: {
|
|
46
|
+
skillRoot: string;
|
|
47
|
+
scriptName: string;
|
|
48
|
+
args: Record<string, unknown>;
|
|
49
|
+
context: Parameters<ScriptExecutor['execute']>[0]['context'];
|
|
50
|
+
timeoutMs: number;
|
|
51
|
+
}): Promise<ToolResult>;
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
//#region src/executor/sandboxedScriptExecutor.d.ts
|
|
55
|
+
interface SandboxOptions {
|
|
56
|
+
/** 默认 { maxOldGenerationSizeMb: 64, maxYoungGenerationSizeMb: 16 } */
|
|
57
|
+
resourceLimits?: {
|
|
58
|
+
maxOldGenerationSizeMb?: number;
|
|
59
|
+
maxYoungGenerationSizeMb?: number;
|
|
60
|
+
};
|
|
61
|
+
/** env 白名单(仅这些变量传入 Worker;默认空) */
|
|
62
|
+
envWhitelist?: string[];
|
|
63
|
+
capabilities?: BridgeCapabilities;
|
|
64
|
+
/** 网络策略:默认 'deny-all'(白名单见 runtime/sandbox/networkPolicy) */
|
|
65
|
+
networkPolicy?: NetworkPolicy;
|
|
66
|
+
/** 裸模块 allowlist(默认 []:一切 node: 内置模块全禁;按需放行如 ['node:path']) */
|
|
67
|
+
allowedModules?: string[];
|
|
68
|
+
/** require-approval 模式的授权询问出口(缺失时 require-approval 一律拒绝) */
|
|
69
|
+
uiBridge?: UiBridge;
|
|
70
|
+
/** 授权粒度:默认 'once-per-run' */
|
|
71
|
+
approvalScope?: ApprovalScope;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* D1:worker_threads 沙箱脚本执行器。
|
|
75
|
+
* 每次执行独立 Worker(resourceLimits + env 白名单),loadDefinition 同样在
|
|
76
|
+
* Worker 内完成(禁止主进程 import 不可信脚本);超时 terminate(可杀同步死循环)。
|
|
77
|
+
* 能力桥协议与浏览器同一来源(runtime/sandbox/bridgeProtocol)。
|
|
78
|
+
*
|
|
79
|
+
* 诚实标注:本执行器做的是**能力面收敛**(网络策略、模块 allowlist、资源限额、
|
|
80
|
+
* 超时强杀),**不是安全边界**——Worker 内脚本与宿主共享进程;
|
|
81
|
+
* 已知主动逃逸面(process.binding/_linkedBinding/dlopen/openStdin/reallyExit/abort)
|
|
82
|
+
* 已在入口删除(0.2.3),常规 import 拦截之外不承诺防御其它宿主共享面;
|
|
83
|
+
* 禁止假定其可隔离不可信脚本(隔离级需求用 ProcessSandboxExecutor)。
|
|
84
|
+
*/
|
|
85
|
+
declare class SandboxedScriptExecutor implements ScriptExecutor {
|
|
86
|
+
#private;
|
|
87
|
+
constructor(fs: FileSystemProvider, options?: SandboxOptions);
|
|
88
|
+
loadDefinition(skillRoot: string, scriptName: string): Promise<ToolDefinition>;
|
|
89
|
+
execute(input: {
|
|
90
|
+
skillRoot: string;
|
|
91
|
+
scriptName: string;
|
|
92
|
+
args: Record<string, unknown>;
|
|
93
|
+
context: ScriptExecutionContext;
|
|
94
|
+
timeoutMs: number;
|
|
95
|
+
}): Promise<ToolResult>;
|
|
96
|
+
}
|
|
97
|
+
//#endregion
|
|
98
|
+
//#region src/executor/processSandboxExecutor.d.ts
|
|
99
|
+
interface ProcessSandboxOptions {
|
|
100
|
+
/** 温池大小(并发上限;执行后 kill 并补位重生),默认 2 */
|
|
101
|
+
poolSize?: number;
|
|
102
|
+
/** 透传给子进程的环境变量白名单(默认 []:子进程 env 为空,防密钥泄露) */
|
|
103
|
+
envWhitelist?: string[];
|
|
104
|
+
capabilities?: BridgeCapabilities;
|
|
105
|
+
/** 网络策略:默认 'deny-all'(权限模型无网络维度,补丁兜底;node:net 裸模块为已知残余面) */
|
|
106
|
+
networkPolicy?: NetworkPolicy;
|
|
107
|
+
/** require-approval 模式的授权询问出口 */
|
|
108
|
+
uiBridge?: UiBridge;
|
|
109
|
+
/** 授权粒度:默认 'once-per-run' */
|
|
110
|
+
approvalScope?: ApprovalScope;
|
|
111
|
+
/** 池维护告警出口(recycle 重生失败等;默认 console.warn) */
|
|
112
|
+
onWarning?: (message: string) => void;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* child_process.fork + --permission 进程沙箱(真实进程隔离)。
|
|
116
|
+
* 每个子进程以 `--permission --allow-fs-read=<入口目录> --allow-fs-read=<skillRoot>
|
|
117
|
+
* --allow-fs-write=<artifactDir>` 启动:fs 维度由权限模型管控(experimental),
|
|
118
|
+
* 子进程/Worker/addons 默认禁;网络无权限维度仍靠 fetch/WebSocket patch。
|
|
119
|
+
* 能力桥协议与 worker_threads 沙箱同一形态(readReference/writeArtifact/confirm + 授权)。
|
|
120
|
+
* 温池(默认 2):同 skillRoot 复用子进程;执行后 kill 并补位重生;并发上限即池大小。
|
|
121
|
+
* 超时 kill(同步死循环可杀);非零退出码 → TOOL_EXECUTION_FAILED。
|
|
122
|
+
*/
|
|
123
|
+
declare class ProcessSandboxExecutor implements ScriptExecutor {
|
|
124
|
+
#private;
|
|
125
|
+
constructor(fs: FileSystemProvider, options?: ProcessSandboxOptions);
|
|
126
|
+
get poolSize(): number;
|
|
127
|
+
/** 池全部子进程销毁(测试收尾/进程退出前调用);排队中的 acquire 一律 reject(不悬挂) */
|
|
128
|
+
dispose(): Promise<void>;
|
|
129
|
+
loadDefinition(skillRoot: string, scriptName: string): Promise<ToolDefinition>;
|
|
130
|
+
execute(input: {
|
|
131
|
+
skillRoot: string;
|
|
132
|
+
scriptName: string;
|
|
133
|
+
args: Record<string, unknown>;
|
|
134
|
+
context: ScriptExecutionContext;
|
|
135
|
+
timeoutMs: number;
|
|
136
|
+
}): Promise<ToolResult>;
|
|
137
|
+
}
|
|
138
|
+
//#endregion
|
|
139
|
+
//#region src/schema/oxcSchemaInferer.d.ts
|
|
140
|
+
/**
|
|
141
|
+
* D2 Schema 推导(OXC 静态文本分析,宿主侧执行,不进沙箱)。
|
|
142
|
+
* TS 类型标注为主路径,JSDoc @param 为辅路径;不支持类型降级 string 并标 'x-inferred'。
|
|
143
|
+
*/
|
|
144
|
+
declare class OxcSchemaInferer implements SchemaInferer {
|
|
145
|
+
inferSchemaFromSource(source: string, options?: {
|
|
146
|
+
fileName?: string;
|
|
147
|
+
}): JsonSchema | undefined;
|
|
148
|
+
}
|
|
149
|
+
//#endregion
|
|
150
|
+
//#region src/artifacts/fileArtifactStore.d.ts
|
|
151
|
+
/**
|
|
152
|
+
* FileArtifactStore:兼容别名,语义同阶段 2-4。
|
|
153
|
+
* 实现已上移到 runtime 的 FsArtifactStore;node 侧保留 NodeFS 默认值。
|
|
154
|
+
*/
|
|
155
|
+
declare class FileArtifactStore extends FsArtifactStore {
|
|
156
|
+
constructor(deps: {
|
|
157
|
+
root: string;
|
|
158
|
+
fs?: FileSystemProvider;
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
//#endregion
|
|
162
|
+
//#region src/memory/fileMemoryStore.d.ts
|
|
163
|
+
/**
|
|
164
|
+
* FileMemoryStore:兼容别名,语义同阶段 3。
|
|
165
|
+
* 实现已上移到 runtime 的 FsMemoryStore;node 侧保留 NodeFS 默认值。
|
|
166
|
+
*/
|
|
167
|
+
declare class FileMemoryStore extends FsMemoryStore {
|
|
168
|
+
constructor(deps: {
|
|
169
|
+
root: string;
|
|
170
|
+
fs?: FileSystemProvider;
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
//#endregion
|
|
174
|
+
//#region src/ui/cliUiBridge.d.ts
|
|
175
|
+
/**
|
|
176
|
+
* 命令行 UiBridge:ask→问答,confirm→y/n(带默认值),
|
|
177
|
+
* form→逐字段提示(显示默认值与必填标记),select→编号列表,
|
|
178
|
+
* authorize→授权询问(默认拒绝,仅显式 y/yes 批准)。
|
|
179
|
+
* 输入/输出流可注入(测试用 PassThrough)。
|
|
180
|
+
*/
|
|
181
|
+
declare class CliUiBridge implements UiBridge {
|
|
182
|
+
#private;
|
|
183
|
+
constructor(deps?: {
|
|
184
|
+
input?: Readable;
|
|
185
|
+
output?: Writable;
|
|
186
|
+
});
|
|
187
|
+
request(input: InteractionRequest): Promise<InteractionResponse>;
|
|
188
|
+
progress(input: {
|
|
189
|
+
runId: string;
|
|
190
|
+
message: string;
|
|
191
|
+
value?: number;
|
|
192
|
+
}): Promise<void>;
|
|
193
|
+
renderResult(input: RenderResultRequest): Promise<void>;
|
|
194
|
+
}
|
|
195
|
+
//#endregion
|
|
196
|
+
//#region src/skillManagement/skillManager.d.ts
|
|
197
|
+
/**
|
|
198
|
+
* 技能管理门面:统一安装管线(staging → 解析 name → 校验 → 拷贝 → manifest → lockfile),
|
|
199
|
+
* 任何失败清理现场抛 INSTALL_FAILED。
|
|
200
|
+
* @stable
|
|
201
|
+
*/
|
|
202
|
+
declare class SkillManager implements SkillManagerPort {
|
|
203
|
+
#private;
|
|
204
|
+
constructor(deps: {
|
|
205
|
+
managedRoot: string;
|
|
206
|
+
fs?: FileSystemProvider;
|
|
207
|
+
fetchImpl?: typeof fetch;
|
|
208
|
+
/** D2 安装期 schema 预推导(默认 true,可关) */
|
|
209
|
+
schemaInference?: boolean;
|
|
210
|
+
/** 归档体积三重上限(缺省 DEFAULT_ARCHIVE_LIMITS) */
|
|
211
|
+
archiveLimits?: ArchiveLimits;
|
|
212
|
+
/** install/uninstall 成功后的变更回调(宿主接线缓存失效,如 WebSkillRuntime.invalidate) */
|
|
213
|
+
onChanged?: () => void;
|
|
214
|
+
/**
|
|
215
|
+
* 供应链信任(design 03 §5.1)。未注入时仍会验签,只是信任库为空——
|
|
216
|
+
* 未签名的包不受影响(默认策略 warn),带着不受信公钥的包则装不上。
|
|
217
|
+
*/
|
|
218
|
+
signature?: {
|
|
219
|
+
trustedKeys?: TrustedKeyStore;
|
|
220
|
+
/** 未签名包的处置,默认 warn */
|
|
221
|
+
unsigned?: UnsignedPolicy;
|
|
222
|
+
/** 验签结论落审计(governance 的 FsAuditLog 结构上兼容) */
|
|
223
|
+
audit?: SignatureAuditSink;
|
|
224
|
+
};
|
|
225
|
+
/** 安装期告警(当前仅未签名放行);宿主接线日志/UI */
|
|
226
|
+
onWarning?: (warning: {
|
|
227
|
+
skill: string;
|
|
228
|
+
message: string;
|
|
229
|
+
}) => void;
|
|
230
|
+
});
|
|
231
|
+
/** 托管根目录(治理发布归档捕获等只读场景) */
|
|
232
|
+
get managedRoot(): string;
|
|
233
|
+
install(source: SkillInstallSource, options?: {
|
|
234
|
+
expectedSha256?: string;
|
|
235
|
+
}): Promise<SkillManifest>;
|
|
236
|
+
uninstall(name: string): Promise<void>;
|
|
237
|
+
verifyIntegrity(name: string): Promise<VerifyResult>;
|
|
238
|
+
listInstalled(): Promise<SkillsLockfile>;
|
|
239
|
+
exportArchive(name: string, options: {
|
|
240
|
+
format: 'zip' | 'tar';
|
|
241
|
+
outPath: string;
|
|
242
|
+
}): Promise<string>;
|
|
243
|
+
/** 多技能包集导出(webskill.skill-pack.json + 各技能目录含 manifest),写 outPath 并返回 */
|
|
244
|
+
exportPack(names: string[], options: {
|
|
245
|
+
outPath: string;
|
|
246
|
+
}): Promise<string>;
|
|
247
|
+
}
|
|
248
|
+
//#endregion
|
|
249
|
+
//#region src/mcp/connectStdioEndpoint.d.ts
|
|
250
|
+
interface StdioEndpointConfig {
|
|
251
|
+
/** registry 中的名字(endpoint:tool 引用) */
|
|
252
|
+
endpoint: string;
|
|
253
|
+
/**
|
|
254
|
+
* 可执行文件。**只能来自宿主配置**:从技能 frontmatter / manifest 到这里没有任何代码路径。
|
|
255
|
+
* 因为 env 不继承父进程,PATH 默认为空——请传绝对路径,或在 env 里显式给出 PATH。
|
|
256
|
+
*/
|
|
257
|
+
command: string;
|
|
258
|
+
args?: readonly string[];
|
|
259
|
+
cwd?: string;
|
|
260
|
+
/** 子进程环境变量。**不默认继承 process.env**:MCP server 是宿主机上的任意程序 */
|
|
261
|
+
env?: Record<string, string>;
|
|
262
|
+
/** 连接与调用超时;0/缺省 = 不超时 */
|
|
263
|
+
timeoutMs?: number;
|
|
264
|
+
/** 子进程 stderr 观测(默认丢弃,仅保留尾部用于错误消息) */
|
|
265
|
+
onStderr?: (chunk: string) => void;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* stdio MCP endpoint 装配:spawn 宿主配置的可执行程序,经 stdin/stdout 说 MCP,
|
|
269
|
+
* 注册进 EndpointRegistry——endpoint:tool 解析、TTL+版本缓存、临时技能消费自动生效。
|
|
270
|
+
* 返回 close 句柄:断开后 unregister 并确保子进程真的退出(不留僵尸)。
|
|
271
|
+
*
|
|
272
|
+
* registry 参数写成结构型而非 `EndpointRegistry<McpClientLike>`:只要从 `@webskill/mcp`
|
|
273
|
+
* `import type`,tsdown 就会把整个 mcp 的 d.ts chunk 拖进 `@webskill/sdk/node`,
|
|
274
|
+
* 把 optional peer `@modelcontextprotocol/sdk` 变成 node 子路径的类型硬依赖
|
|
275
|
+
* (install-smoke 的消费方 typecheck 探针会因此变红)。结构类型保证真实的
|
|
276
|
+
* `EndpointRegistry<McpClientLike>` 仍可直接传入。
|
|
277
|
+
*/
|
|
278
|
+
declare function connectStdioEndpoint<TClient>(registry: {
|
|
279
|
+
register(endpoint: string, client: TClient): void;
|
|
280
|
+
unregister(endpoint: string): void;
|
|
281
|
+
}, config: StdioEndpointConfig): Promise<{
|
|
282
|
+
close(): Promise<void>;
|
|
283
|
+
}>;
|
|
284
|
+
//#endregion
|
|
285
|
+
//#region src/skillManagement/export/archiveExporter.d.ts
|
|
286
|
+
/** 导出技能目录全部文件(含 manifest)为 zip/tar 归档,返回 outPath */
|
|
287
|
+
declare function exportArchive(fs: FileSystemProvider, skillRoot: string, options: {
|
|
288
|
+
format: 'zip' | 'tar';
|
|
289
|
+
outPath: string;
|
|
290
|
+
}): Promise<string>;
|
|
291
|
+
/** 只解出归档中的 webskill.skill-manifest.json 条目(安装前预览) */
|
|
292
|
+
declare function readArchiveManifest(fs: FileSystemProvider, archivePath: string): Promise<SkillManifest>;
|
|
293
|
+
//#endregion
|
|
5
294
|
//#region ../governance/dist/node.d.ts
|
|
6
295
|
//#region src/approval/approvalWorkflow.d.ts
|
|
7
296
|
/** 审批工作流:review(UiBridge confirm 真实接线)/ publish(校验→安装→版本→审计) */
|
|
@@ -47,4 +336,4 @@ declare function createEvaluationRuntime(deps: WebSkillRuntimeDeps & {
|
|
|
47
336
|
executor?: ScriptExecutor;
|
|
48
337
|
}): WebSkillRuntime;
|
|
49
338
|
//#endregion
|
|
50
|
-
export { ApprovalWorkflow, CliUiBridge, FileArtifactStore, FileMemoryStore, type LlmCapabilities, type LlmEnvConfig, NodeFS, NodeScriptExecutor, OxcSchemaInferer, ProcessSandboxExecutor, type ProcessSandboxOptions, SKILLS_LOCKFILE, SKILL_MANIFEST_FILE, type SandboxOptions, SandboxedScriptExecutor, type SkillInstallSource, SkillManager, type SkillManifest, type SkillsLockfile, type VerifyResult, createEvaluationRuntime, createScriptContext, exportArchive, probeLlmCapabilities, readArchiveManifest };
|
|
339
|
+
export { ApprovalWorkflow, CliUiBridge, FileArtifactStore, FileMemoryStore, type LlmCapabilities, type LlmEnvConfig, NodeFS, NodeScriptExecutor, OxcSchemaInferer, ProcessSandboxExecutor, type ProcessSandboxOptions, SKILLS_LOCKFILE, SKILL_MANIFEST_FILE, type SandboxOptions, SandboxedScriptExecutor, type SkillInstallSource, SkillManager, type SkillManifest, type SkillsLockfile, type StdioEndpointConfig, type VerifyResult, connectStdioEndpoint, createEvaluationRuntime, createScriptContext, exportArchive, probeLlmCapabilities, readArchiveManifest };
|
package/dist/node.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as
|
|
2
|
-
import {
|
|
1
|
+
import { A as parseSkillMarkdown, B as unzipWithLimits, H as verifyManifest, I as resolveArchiveLimits, L as resolveInsideRoot, M as readResponseWithLimit, N as readSkillSignature, O as messageOf, T as isValidSkillName, U as verifySkillSignature, V as validateSkills, _ as atomicWriteText, g as assertSafePathSegment, h as assertRemoteUrlAllowed, j as parseSkillPackManifest, m as WebSkillError, o as SKILLS_LOCKFILE, r as MANIFEST_EXCLUDED_FILES, s as SKILL_MANIFEST_FILE, u as SKILL_PACK_FILE, w as exportSkills, y as buildManifest } from "./dist-8oQRa8Xz.js";
|
|
2
|
+
import { B as normalizeToolContent, D as bridgeError, E as WebSkillRuntime, H as parseBridgeRequest, L as networkPolicyLibSource, V as normalizeToolError, c as FsArtifactStore, k as createScriptContext, l as FsMemoryStore, o as CapabilityApproval } from "./dist-rorEJsNi.js";
|
|
3
3
|
import { i as probeLlmCapabilities } from "./env--jJB-TSX-04klhTYi.js";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import { unzipSync, zipSync } from "fflate";
|
|
@@ -10,7 +10,7 @@ import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
10
10
|
import { format, promisify } from "node:util";
|
|
11
11
|
import { Worker } from "node:worker_threads";
|
|
12
12
|
import { mkdtemp, rm } from "node:fs/promises";
|
|
13
|
-
import { execFile, fork } from "node:child_process";
|
|
13
|
+
import { execFile, fork, spawn } from "node:child_process";
|
|
14
14
|
import { createInterface } from "node:readline/promises";
|
|
15
15
|
import { createHash } from "node:crypto";
|
|
16
16
|
|
|
@@ -1597,7 +1597,6 @@ async function removeLockEntry(fs, managedRoot, name) {
|
|
|
1597
1597
|
async function writeLockfileAtomic(fs, managedRoot, lockfile) {
|
|
1598
1598
|
await atomicWriteText(fs, `${managedRoot}/${SKILLS_LOCKFILE}`, JSON.stringify(lockfile, null, 2));
|
|
1599
1599
|
}
|
|
1600
|
-
const EXCLUDED_FILES = /* @__PURE__ */ new Set([SKILL_MANIFEST_FILE, SKILLS_LOCKFILE]);
|
|
1601
1600
|
/** 递归收集技能目录内的文件(相对路径,posix 分隔) */
|
|
1602
1601
|
async function walkFiles(fs, root, prefix = "") {
|
|
1603
1602
|
const out = [];
|
|
@@ -1605,7 +1604,7 @@ async function walkFiles(fs, root, prefix = "") {
|
|
|
1605
1604
|
const name = entry.path.split("/").pop() ?? "";
|
|
1606
1605
|
const rel = prefix === "" ? name : `${prefix}/${name}`;
|
|
1607
1606
|
if (entry.type === "directory") out.push(...await walkFiles(fs, entry.path, rel));
|
|
1608
|
-
else if (!
|
|
1607
|
+
else if (!MANIFEST_EXCLUDED_FILES.has(name)) out.push(rel);
|
|
1609
1608
|
}
|
|
1610
1609
|
return out;
|
|
1611
1610
|
}
|
|
@@ -1649,7 +1648,29 @@ async function verifyIntegrity(fs, skillRoot) {
|
|
|
1649
1648
|
for (const rel of actualFiles) actualHashes.set(rel, sha256Hex(await fs.readBinary(`${skillRoot}/${rel}`)));
|
|
1650
1649
|
return verifyManifest(manifest, actualHashes, actualFiles);
|
|
1651
1650
|
}
|
|
1652
|
-
|
|
1651
|
+
/**
|
|
1652
|
+
* 验签失败不能被折叠成 INSTALL_FAILED:四种失败的宿主处置完全不同
|
|
1653
|
+
* (引导选策略 / 提示重下 / 引导添加密钥 / 安全事件),见 design 03 §3.1。
|
|
1654
|
+
*/
|
|
1655
|
+
const PRESERVED_INSTALL_CODES = /* @__PURE__ */ new Set([
|
|
1656
|
+
"SIGNATURE_MISSING",
|
|
1657
|
+
"SIGNATURE_MALFORMED",
|
|
1658
|
+
"SIGNATURE_UNTRUSTED_KEY",
|
|
1659
|
+
"SIGNATURE_MISMATCH",
|
|
1660
|
+
"SIGNATURE_UNSUPPORTED"
|
|
1661
|
+
]);
|
|
1662
|
+
const asInstallFailed = (e) => e instanceof WebSkillError && (e.code === "INSTALL_FAILED" || PRESERVED_INSTALL_CODES.has(e.code)) ? e : new WebSkillError("INSTALL_FAILED", `Install failed: ${messageOf(e)}`, e);
|
|
1663
|
+
/** 未注入信任库时的空库:任何签名都不受信,比「验不了就放行」安全 */
|
|
1664
|
+
const EMPTY_TRUSTED_KEYS = {
|
|
1665
|
+
list: async () => [],
|
|
1666
|
+
get: async () => void 0,
|
|
1667
|
+
add: async () => {
|
|
1668
|
+
throw new WebSkillError("SIGNATURE_UNTRUSTED_KEY", "This SkillManager has no trusted key store configured");
|
|
1669
|
+
},
|
|
1670
|
+
remove: async () => {
|
|
1671
|
+
throw new WebSkillError("SIGNATURE_UNTRUSTED_KEY", "This SkillManager has no trusted key store configured");
|
|
1672
|
+
}
|
|
1673
|
+
};
|
|
1653
1674
|
/**
|
|
1654
1675
|
* 技能管理门面:统一安装管线(staging → 解析 name → 校验 → 拷贝 → manifest → lockfile),
|
|
1655
1676
|
* 任何失败清理现场抛 INSTALL_FAILED。
|
|
@@ -1662,6 +1683,10 @@ var SkillManager = class {
|
|
|
1662
1683
|
#schemaInference;
|
|
1663
1684
|
#archiveLimits;
|
|
1664
1685
|
#onChanged;
|
|
1686
|
+
#trustedKeys;
|
|
1687
|
+
#unsignedPolicy;
|
|
1688
|
+
#signatureAudit;
|
|
1689
|
+
#onWarning;
|
|
1665
1690
|
#schemaInferer = new OxcSchemaInferer();
|
|
1666
1691
|
constructor(deps) {
|
|
1667
1692
|
this.#managedRoot = deps.managedRoot.replace(/\/+$/, "");
|
|
@@ -1670,6 +1695,10 @@ var SkillManager = class {
|
|
|
1670
1695
|
this.#schemaInference = deps.schemaInference ?? true;
|
|
1671
1696
|
this.#archiveLimits = deps.archiveLimits;
|
|
1672
1697
|
this.#onChanged = deps.onChanged;
|
|
1698
|
+
this.#trustedKeys = deps.signature?.trustedKeys ?? EMPTY_TRUSTED_KEYS;
|
|
1699
|
+
this.#unsignedPolicy = deps.signature?.unsigned ?? "warn";
|
|
1700
|
+
this.#signatureAudit = deps.signature?.audit;
|
|
1701
|
+
this.#onWarning = deps.onWarning;
|
|
1673
1702
|
}
|
|
1674
1703
|
/** 托管根目录(治理发布归档捕获等只读场景) */
|
|
1675
1704
|
get managedRoot() {
|
|
@@ -1728,6 +1757,7 @@ var SkillManager = class {
|
|
|
1728
1757
|
...version ? { version } : {},
|
|
1729
1758
|
source: staged.source
|
|
1730
1759
|
});
|
|
1760
|
+
await this.#verifySignature(finalDir, manifest);
|
|
1731
1761
|
targetDir = `${this.#managedRoot}/${name}`;
|
|
1732
1762
|
const backupDir = `${stagingRoot}/backup`;
|
|
1733
1763
|
const hadPrevious = await fs.exists(targetDir);
|
|
@@ -1797,6 +1827,7 @@ var SkillManager = class {
|
|
|
1797
1827
|
source
|
|
1798
1828
|
});
|
|
1799
1829
|
if (manifest.integrity.digest !== entry.digest) throw new WebSkillError("INSTALL_FAILED", `Skill "${entry.name}" digest mismatch: expected ${entry.digest}, got ${manifest.integrity.digest}`);
|
|
1830
|
+
await this.#verifySignature(`${finalRoot}/${entry.name}`, manifest);
|
|
1800
1831
|
manifests.push(manifest);
|
|
1801
1832
|
}
|
|
1802
1833
|
const swapped = [];
|
|
@@ -1836,6 +1867,33 @@ var SkillManager = class {
|
|
|
1836
1867
|
}
|
|
1837
1868
|
}
|
|
1838
1869
|
/**
|
|
1870
|
+
* 安装期验签(design 03 §5.1):manifest 生成之后、lockfile 提交之前。
|
|
1871
|
+
* 失败直接抛出,暂存目录由 install 的 finally 清理,不落盘。
|
|
1872
|
+
* 未签名且策略放行时也记一条审计——「当时是 warn 放过去的」事后必须查得到。
|
|
1873
|
+
*/
|
|
1874
|
+
async #verifySignature(skillDir, manifest) {
|
|
1875
|
+
const verdict = await verifySkillSignature({
|
|
1876
|
+
manifest,
|
|
1877
|
+
signature: await readSkillSignature(this.#fs, skillDir),
|
|
1878
|
+
trustedKeys: this.#trustedKeys,
|
|
1879
|
+
policy: { unsigned: this.#unsignedPolicy }
|
|
1880
|
+
});
|
|
1881
|
+
if (verdict.warning !== void 0) this.#onWarning?.({
|
|
1882
|
+
skill: manifest.name,
|
|
1883
|
+
message: verdict.warning
|
|
1884
|
+
});
|
|
1885
|
+
await this.#signatureAudit?.append({
|
|
1886
|
+
type: "skill.signature-verified",
|
|
1887
|
+
target: manifest.name,
|
|
1888
|
+
data: {
|
|
1889
|
+
...verdict.keyId !== void 0 ? { keyId: verdict.keyId } : {},
|
|
1890
|
+
verdict: verdict.unsigned ? "unsigned-allowed" : "signed",
|
|
1891
|
+
policy: this.#unsignedPolicy,
|
|
1892
|
+
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
1893
|
+
}
|
|
1894
|
+
});
|
|
1895
|
+
}
|
|
1896
|
+
/**
|
|
1839
1897
|
* D2 安装期预推导:scripts/ 下无显式 inputSchema 导出且无 sidecar 的脚本,
|
|
1840
1898
|
* 经 OXC 推导写 sidecar(计入 manifest.files;重装重新生成)
|
|
1841
1899
|
*/
|
|
@@ -1898,6 +1956,222 @@ var SkillManager = class {
|
|
|
1898
1956
|
return options.outPath;
|
|
1899
1957
|
}
|
|
1900
1958
|
};
|
|
1959
|
+
async function loadMcpSdk() {
|
|
1960
|
+
try {
|
|
1961
|
+
const [client, stdio] = await Promise.all([import("./client-BCM6Z3yq-qUQNkKrK.js"), import("./stdio-CFMoANJJ-BxrTeXh7.js")]);
|
|
1962
|
+
return {
|
|
1963
|
+
Client: client.Client,
|
|
1964
|
+
ReadBuffer: stdio.ReadBuffer,
|
|
1965
|
+
serializeMessage: stdio.serializeMessage
|
|
1966
|
+
};
|
|
1967
|
+
} catch (e) {
|
|
1968
|
+
throw new WebSkillError("MCP_ENDPOINT_UNAVAILABLE", "The \"@modelcontextprotocol/sdk\" package is required for stdio MCP endpoints; install it first (npm i @modelcontextprotocol/sdk)", e);
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
/** SIGTERM 后等待自行退出的宽限期,超时改 SIGKILL */
|
|
1972
|
+
const KILL_GRACE_MS = 2e3;
|
|
1973
|
+
function describeExit(exit) {
|
|
1974
|
+
return exit.signal !== null ? `signal ${exit.signal}` : `exit code ${exit.code}`;
|
|
1975
|
+
}
|
|
1976
|
+
async function spawnServer(config) {
|
|
1977
|
+
const child = spawn(config.command, [...config.args ?? []], {
|
|
1978
|
+
...config.cwd !== void 0 ? { cwd: config.cwd } : {},
|
|
1979
|
+
env: { ...config.env },
|
|
1980
|
+
stdio: [
|
|
1981
|
+
"pipe",
|
|
1982
|
+
"pipe",
|
|
1983
|
+
"pipe"
|
|
1984
|
+
],
|
|
1985
|
+
shell: false,
|
|
1986
|
+
windowsHide: true
|
|
1987
|
+
});
|
|
1988
|
+
let tail = "";
|
|
1989
|
+
child.stderr?.on("data", (chunk) => {
|
|
1990
|
+
const text = chunk.toString("utf8");
|
|
1991
|
+
config.onStderr?.(text);
|
|
1992
|
+
tail = (tail + text).slice(-4096);
|
|
1993
|
+
});
|
|
1994
|
+
child.stdin?.on("error", () => {});
|
|
1995
|
+
child.stderr?.on("error", () => {});
|
|
1996
|
+
let exit;
|
|
1997
|
+
const exited = new Promise((resolve) => {
|
|
1998
|
+
child.once("exit", (code, signal) => {
|
|
1999
|
+
exit = {
|
|
2000
|
+
code,
|
|
2001
|
+
signal
|
|
2002
|
+
};
|
|
2003
|
+
resolve();
|
|
2004
|
+
});
|
|
2005
|
+
});
|
|
2006
|
+
try {
|
|
2007
|
+
await new Promise((resolve, reject) => {
|
|
2008
|
+
child.once("spawn", resolve);
|
|
2009
|
+
child.once("error", reject);
|
|
2010
|
+
});
|
|
2011
|
+
} catch (e) {
|
|
2012
|
+
throw new WebSkillError("MCP_STDIO_SPAWN_FAILED", `Failed to spawn stdio MCP endpoint "${config.endpoint}" (${config.command}): ${messageOf(e)}`, e);
|
|
2013
|
+
}
|
|
2014
|
+
child.on("error", () => {});
|
|
2015
|
+
return {
|
|
2016
|
+
child,
|
|
2017
|
+
stderrTail: () => tail,
|
|
2018
|
+
exit: () => exit,
|
|
2019
|
+
terminate: async () => {
|
|
2020
|
+
if (exit !== void 0) return;
|
|
2021
|
+
child.kill("SIGTERM");
|
|
2022
|
+
const killer = setTimeout(() => child.kill("SIGKILL"), KILL_GRACE_MS);
|
|
2023
|
+
try {
|
|
2024
|
+
await exited;
|
|
2025
|
+
} finally {
|
|
2026
|
+
clearTimeout(killer);
|
|
2027
|
+
}
|
|
2028
|
+
}
|
|
2029
|
+
};
|
|
2030
|
+
}
|
|
2031
|
+
/**
|
|
2032
|
+
* 子进程 stdio 上的 MCP transport。帧解析复用 SDK 的 ReadBuffer / serializeMessage,
|
|
2033
|
+
* 不自己写协议解析;进程由 connectStdioEndpoint 先行 spawn,
|
|
2034
|
+
* 好把「命令起不来」和「起来后立刻退出」分成两个错误码。
|
|
2035
|
+
*/
|
|
2036
|
+
var ChildStdioTransport = class {
|
|
2037
|
+
onclose;
|
|
2038
|
+
onerror;
|
|
2039
|
+
onmessage;
|
|
2040
|
+
#child;
|
|
2041
|
+
#sdk;
|
|
2042
|
+
#readBuffer;
|
|
2043
|
+
constructor(child, sdk) {
|
|
2044
|
+
this.#child = child;
|
|
2045
|
+
this.#sdk = sdk;
|
|
2046
|
+
this.#readBuffer = new sdk.ReadBuffer();
|
|
2047
|
+
}
|
|
2048
|
+
async start() {
|
|
2049
|
+
if (this.#child.exitCode !== null || this.#child.signalCode !== null) {
|
|
2050
|
+
this.onclose?.();
|
|
2051
|
+
return;
|
|
2052
|
+
}
|
|
2053
|
+
this.#child.stdout?.on("data", (chunk) => {
|
|
2054
|
+
this.#readBuffer.append(chunk);
|
|
2055
|
+
for (;;) {
|
|
2056
|
+
let message;
|
|
2057
|
+
try {
|
|
2058
|
+
message = this.#readBuffer.readMessage();
|
|
2059
|
+
} catch (e) {
|
|
2060
|
+
this.onerror?.(e instanceof Error ? e : new Error(String(e)));
|
|
2061
|
+
return;
|
|
2062
|
+
}
|
|
2063
|
+
if (message === null) return;
|
|
2064
|
+
this.onmessage?.(message);
|
|
2065
|
+
}
|
|
2066
|
+
});
|
|
2067
|
+
this.#child.stdout?.on("error", (e) => this.onerror?.(e));
|
|
2068
|
+
this.#child.once("exit", () => this.onclose?.());
|
|
2069
|
+
}
|
|
2070
|
+
async send(message) {
|
|
2071
|
+
const stdin = this.#child.stdin;
|
|
2072
|
+
if (!stdin || stdin.destroyed) throw new WebSkillError("MCP_STDIO_EXITED", "The stdio MCP server process is no longer writable");
|
|
2073
|
+
await new Promise((resolve, reject) => {
|
|
2074
|
+
stdin.write(this.#sdk.serializeMessage(message), (e) => e ? reject(e) : resolve());
|
|
2075
|
+
});
|
|
2076
|
+
}
|
|
2077
|
+
async close() {
|
|
2078
|
+
this.#child.stdin?.end();
|
|
2079
|
+
this.#readBuffer.clear();
|
|
2080
|
+
}
|
|
2081
|
+
};
|
|
2082
|
+
function withTimeout(work, timeoutMs, onTimeout) {
|
|
2083
|
+
if (timeoutMs <= 0) return work;
|
|
2084
|
+
let timer;
|
|
2085
|
+
const timeout = new Promise((_resolve, reject) => {
|
|
2086
|
+
timer = setTimeout(() => reject(onTimeout()), timeoutMs);
|
|
2087
|
+
});
|
|
2088
|
+
return Promise.race([work, timeout]).finally(() => clearTimeout(timer));
|
|
2089
|
+
}
|
|
2090
|
+
const CLIENT_METHODS = [
|
|
2091
|
+
"listTools",
|
|
2092
|
+
"callTool",
|
|
2093
|
+
"listPrompts",
|
|
2094
|
+
"getPrompt",
|
|
2095
|
+
"listResources",
|
|
2096
|
+
"readResource"
|
|
2097
|
+
];
|
|
2098
|
+
/**
|
|
2099
|
+
* 给每次调用套上 timeoutMs。超时按「server 挂住了」处理:先终止进程再上抛,
|
|
2100
|
+
* 免得留下一个谁都不再理会的子进程。
|
|
2101
|
+
*/
|
|
2102
|
+
function guardCalls(client, config, abort) {
|
|
2103
|
+
const timeoutMs = config.timeoutMs ?? 0;
|
|
2104
|
+
if (timeoutMs <= 0) return client;
|
|
2105
|
+
const source = client;
|
|
2106
|
+
const guarded = {};
|
|
2107
|
+
for (const method of CLIENT_METHODS) guarded[method] = async (input) => {
|
|
2108
|
+
try {
|
|
2109
|
+
return await withTimeout(source[method](input), timeoutMs, () => new WebSkillError("MCP_STDIO_TIMEOUT", `Call "${method}" on stdio MCP endpoint "${config.endpoint}" timed out after ${timeoutMs}ms`));
|
|
2110
|
+
} catch (e) {
|
|
2111
|
+
if (e instanceof WebSkillError && e.code === "MCP_STDIO_TIMEOUT") await abort();
|
|
2112
|
+
throw e;
|
|
2113
|
+
}
|
|
2114
|
+
};
|
|
2115
|
+
return guarded;
|
|
2116
|
+
}
|
|
2117
|
+
/**
|
|
2118
|
+
* stdio MCP endpoint 装配:spawn 宿主配置的可执行程序,经 stdin/stdout 说 MCP,
|
|
2119
|
+
* 注册进 EndpointRegistry——endpoint:tool 解析、TTL+版本缓存、临时技能消费自动生效。
|
|
2120
|
+
* 返回 close 句柄:断开后 unregister 并确保子进程真的退出(不留僵尸)。
|
|
2121
|
+
*
|
|
2122
|
+
* registry 参数写成结构型而非 `EndpointRegistry<McpClientLike>`:只要从 `@webskill/mcp`
|
|
2123
|
+
* `import type`,tsdown 就会把整个 mcp 的 d.ts chunk 拖进 `@webskill/sdk/node`,
|
|
2124
|
+
* 把 optional peer `@modelcontextprotocol/sdk` 变成 node 子路径的类型硬依赖
|
|
2125
|
+
* (install-smoke 的消费方 typecheck 探针会因此变红)。结构类型保证真实的
|
|
2126
|
+
* `EndpointRegistry<McpClientLike>` 仍可直接传入。
|
|
2127
|
+
*/
|
|
2128
|
+
async function connectStdioEndpoint(registry, config) {
|
|
2129
|
+
const sdk = await loadMcpSdk();
|
|
2130
|
+
const proc = await spawnServer(config);
|
|
2131
|
+
const transport = new ChildStdioTransport(proc.child, sdk);
|
|
2132
|
+
const client = new sdk.Client({
|
|
2133
|
+
name: "webskill-stdio-client",
|
|
2134
|
+
version: "0.1.0"
|
|
2135
|
+
});
|
|
2136
|
+
let timedOut = false;
|
|
2137
|
+
try {
|
|
2138
|
+
await withTimeout(client.connect(transport), config.timeoutMs ?? 0, () => {
|
|
2139
|
+
timedOut = true;
|
|
2140
|
+
return new WebSkillError("MCP_STDIO_TIMEOUT", `Timed out after ${config.timeoutMs}ms connecting stdio MCP endpoint "${config.endpoint}"`);
|
|
2141
|
+
});
|
|
2142
|
+
} catch (e) {
|
|
2143
|
+
await proc.terminate();
|
|
2144
|
+
if (timedOut) throw e;
|
|
2145
|
+
const exit = proc.exit();
|
|
2146
|
+
if (exit !== void 0) {
|
|
2147
|
+
const tail = proc.stderrTail().trim();
|
|
2148
|
+
throw new WebSkillError("MCP_STDIO_EXITED", `Stdio MCP endpoint "${config.endpoint}" exited before it was ready (${describeExit(exit)})` + (tail === "" ? "" : `; stderr: ${tail}`), e);
|
|
2149
|
+
}
|
|
2150
|
+
throw new WebSkillError("MCP_ENDPOINT_UNAVAILABLE", `Failed to connect stdio MCP endpoint "${config.endpoint}": ${messageOf(e)}`, e);
|
|
2151
|
+
}
|
|
2152
|
+
let closed = false;
|
|
2153
|
+
const close = async () => {
|
|
2154
|
+
if (closed) return;
|
|
2155
|
+
closed = true;
|
|
2156
|
+
registry.unregister(config.endpoint);
|
|
2157
|
+
try {
|
|
2158
|
+
await client.close();
|
|
2159
|
+
} finally {
|
|
2160
|
+
await proc.terminate();
|
|
2161
|
+
}
|
|
2162
|
+
};
|
|
2163
|
+
try {
|
|
2164
|
+
registry.register(config.endpoint, guardCalls(client, config, close));
|
|
2165
|
+
} catch (e) {
|
|
2166
|
+
try {
|
|
2167
|
+
await client.close();
|
|
2168
|
+
} finally {
|
|
2169
|
+
await proc.terminate();
|
|
2170
|
+
}
|
|
2171
|
+
throw new WebSkillError("MCP_ENDPOINT_UNAVAILABLE", `Failed to register stdio MCP endpoint "${config.endpoint}": ${messageOf(e)}`, e);
|
|
2172
|
+
}
|
|
2173
|
+
return { close };
|
|
2174
|
+
}
|
|
1901
2175
|
|
|
1902
2176
|
//#endregion
|
|
1903
2177
|
//#region ../governance/dist/node.js
|
|
@@ -2063,4 +2337,4 @@ function createEvaluationRuntime(deps) {
|
|
|
2063
2337
|
}
|
|
2064
2338
|
|
|
2065
2339
|
//#endregion
|
|
2066
|
-
export { ApprovalWorkflow, CliUiBridge, FileArtifactStore, FileMemoryStore, NodeFS, NodeScriptExecutor, OxcSchemaInferer, ProcessSandboxExecutor, SKILLS_LOCKFILE, SKILL_MANIFEST_FILE, SandboxedScriptExecutor, SkillManager, createEvaluationRuntime, createScriptContext, exportArchive, probeLlmCapabilities, readArchiveManifest };
|
|
2340
|
+
export { ApprovalWorkflow, CliUiBridge, FileArtifactStore, FileMemoryStore, NodeFS, NodeScriptExecutor, OxcSchemaInferer, ProcessSandboxExecutor, SKILLS_LOCKFILE, SKILL_MANIFEST_FILE, SandboxedScriptExecutor, SkillManager, connectStdioEndpoint, createEvaluationRuntime, createScriptContext, exportArchive, probeLlmCapabilities, readArchiveManifest };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ft as uiCatalog } from "./dist-
|
|
1
|
+
import { ft as uiCatalog } from "./dist-ZKaM8j06.js";
|
|
2
2
|
import { n as catalogComponentImpls } from "./catalogComponents-C_V39rbF-BOHveMWa.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { Component, Fragment, createContext, useCallback, useContext, useEffect, useInsertionEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|