@webskill/sdk 0.11.0 → 0.12.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/dist/agent.d.ts +3 -3
- package/dist/agent.js +2 -2
- package/dist/browser.d.ts +3 -3
- package/dist/browser.js +7 -3
- package/dist/{catalogComponents-BFoqpT1v-CjUBZ3bc.js → catalogComponents-BgAJN0p8-C3K8klJd.js} +260 -914
- package/dist/{dist-qnlI2Iup.js → dist-DU9KDAuR.js} +194 -6
- package/dist/{dist-DTHZS2k1.js → dist-DqcL6jKO.js} +155 -39
- package/dist/{dist-B-cOu08W.js → dist-sdKFgERo.js} +431 -40
- package/dist/{echarts-DhNm2ene.js → echarts-De78wXqV.js} +599 -61
- package/dist/governance.d.ts +3 -3
- package/dist/{index-DACk2_XZ.d.ts → index-3fCHc1mQ.d.ts} +92 -8
- package/dist/{index-D3mONFHD.d.ts → index-C9pzXLKy.d.ts} +148 -4
- package/dist/{index-DWbs58LF.d.ts → index-DFhU1uks.d.ts} +64 -10
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/mcp.d.ts +26 -3
- package/dist/mcp.js +37 -1
- package/dist/node.d.ts +3 -3
- package/dist/node.js +9 -3
- package/dist/{openUiLibrary-D5u8oIvx-BLOAQCho.js → openUiLibrary-BKXW7Iwx-DaymVubt.js} +3 -3
- package/dist/processSandboxEntry.js +2 -1
- package/dist/sandboxWorkerEntry.js +2 -1
- package/dist/{skillVersionStore-D-qHk9ZE-BcmFLykd.d.ts → skillVersionStore-D-qHk9ZE-DheTIwAB.d.ts} +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/{types-C26b05fW-CdrRCRDb.d.ts → types-DLctJep_-B5G4uk2u.d.ts} +3 -2
- package/dist/ui-react.d.ts +13 -4
- package/dist/ui-react.js +69 -253
- package/dist/ui-vue.d.ts +1 -1
- package/dist/ui-vue.js +1 -1
- package/dist/ui.d.ts +4 -4
- package/dist/ui.js +3 -3
- package/dist/{webskillLitCatalog-DME6PBkV-CmYNLlIT.js → webskillLitCatalog-D_zCqeQF-C9lrvvMr.js} +2 -2
- package/package.json +1 -1
|
@@ -210,16 +210,89 @@ function uniqueName(base, taken) {
|
|
|
210
210
|
while (taken.has(`${prefixed}_${index}`)) index += 1;
|
|
211
211
|
return `${prefixed}_${index}`;
|
|
212
212
|
}
|
|
213
|
+
function renameDefRefs(node, renames) {
|
|
214
|
+
if (Array.isArray(node)) return node.map((child) => renameDefRefs(child, renames));
|
|
215
|
+
if (!isRecord$7(node)) return node;
|
|
216
|
+
const out = {};
|
|
217
|
+
const prefix = `#/${DEFS_KEY}/`;
|
|
218
|
+
for (const [key, value] of Object.entries(node)) {
|
|
219
|
+
if (key === "$ref" && typeof value === "string" && value.startsWith(prefix)) {
|
|
220
|
+
const [head, ...tail] = value.slice(prefix.length).split("/");
|
|
221
|
+
const mapped = head === void 0 ? void 0 : renames.get(head);
|
|
222
|
+
out[key] = mapped === void 0 ? value : [`${prefix}${mapped}`, ...tail].join("/");
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
out[key] = renameDefRefs(value, renames);
|
|
226
|
+
}
|
|
227
|
+
return out;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* 把非根位置的 `$defs` 搬到根。zod 每次 `toJSONSchema()` 各自产出 `$defs.__schemaN`,
|
|
231
|
+
* 嵌进大 schema 后其 `#/$defs/...` 从大根解析不到——提升即修复。重名时避让并改写引用。
|
|
232
|
+
*/
|
|
233
|
+
function hoistNestedDefs(schema) {
|
|
234
|
+
const rootDefs = isRecord$7(schema[DEFS_KEY]) ? { ...schema[DEFS_KEY] } : {};
|
|
235
|
+
const taken = new Set(Object.keys(rootDefs));
|
|
236
|
+
let hoisted = false;
|
|
237
|
+
function visit(node, isRoot) {
|
|
238
|
+
if (Array.isArray(node)) return node.map((child) => visit(child, false));
|
|
239
|
+
if (!isRecord$7(node)) return node;
|
|
240
|
+
const nested = !isRoot && isRecord$7(node[DEFS_KEY]) ? node[DEFS_KEY] : void 0;
|
|
241
|
+
const body = {};
|
|
242
|
+
for (const [key, value] of Object.entries(node)) {
|
|
243
|
+
if (key === DEFS_KEY && nested !== void 0) continue;
|
|
244
|
+
if (key === DEFS_KEY) {
|
|
245
|
+
body[key] = value;
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
if (SCHEMA_MAP_KEYS.has(key) && isRecord$7(value)) {
|
|
249
|
+
const mapped = {};
|
|
250
|
+
for (const [name, child] of Object.entries(value)) mapped[name] = visit(child, false);
|
|
251
|
+
body[key] = mapped;
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
if (SCHEMA_LIST_KEYS.has(key) && Array.isArray(value)) {
|
|
255
|
+
body[key] = value.map((child) => visit(child, false));
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
if (SCHEMA_KEYS.has(key)) {
|
|
259
|
+
body[key] = visit(value, false);
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
body[key] = value;
|
|
263
|
+
}
|
|
264
|
+
if (nested === void 0) return body;
|
|
265
|
+
hoisted = true;
|
|
266
|
+
const renames = /* @__PURE__ */ new Map();
|
|
267
|
+
for (const name of Object.keys(nested)) {
|
|
268
|
+
const target = uniqueName(name, taken);
|
|
269
|
+
taken.add(target);
|
|
270
|
+
if (target !== name) renames.set(name, target);
|
|
271
|
+
}
|
|
272
|
+
for (const [name, def] of Object.entries(nested)) {
|
|
273
|
+
const moved = visit(def, false);
|
|
274
|
+
rootDefs[renames.get(name) ?? name] = renames.size > 0 ? renameDefRefs(moved, renames) : moved;
|
|
275
|
+
}
|
|
276
|
+
return renames.size > 0 ? renameDefRefs(body, renames) : body;
|
|
277
|
+
}
|
|
278
|
+
const out = visit(schema, true);
|
|
279
|
+
return hoisted ? {
|
|
280
|
+
...out,
|
|
281
|
+
[DEFS_KEY]: rootDefs
|
|
282
|
+
} : schema;
|
|
283
|
+
}
|
|
213
284
|
/**
|
|
214
285
|
* 把工具 inputSchema 重写为严格解析器可接受的 JSON Schema 2020-12 形态:
|
|
215
|
-
*
|
|
286
|
+
* 非根 `$defs` 提到根,自引用的 schema resource 提到根 `$defs`,
|
|
287
|
+
* 所有 `$ref: '#'` 改写为 `$ref: '#/$defs/<Node>'`。
|
|
216
288
|
*
|
|
217
|
-
*
|
|
289
|
+
* 幂等:不含自引用也不含嵌套 `$defs` 的 schema 原样返回。
|
|
218
290
|
*
|
|
219
291
|
* 这是**传输层适配**,只应在出站请求体上调用;不要下沉到 AgentLoop,
|
|
220
292
|
* 否则 trace / eventBus 观测到的 schema 会与技能作者写的不一致。
|
|
221
293
|
*/
|
|
222
|
-
function toPortableToolSchema(
|
|
294
|
+
function toPortableToolSchema(input) {
|
|
295
|
+
const schema = hoistNestedDefs(input);
|
|
223
296
|
const roots = /* @__PURE__ */ new Map();
|
|
224
297
|
collectSelfRefRoots(schema, [], [], roots);
|
|
225
298
|
if (roots.size === 0) return schema;
|
|
@@ -382,6 +455,10 @@ const ANTHROPIC_SCHEMA_PROFILE = {
|
|
|
382
455
|
/**
|
|
383
456
|
* Google Gen AI 的 `FunctionDeclaration.parameters` 收到 `additionalProperties`
|
|
384
457
|
* 直接回 400 `Unknown name "additionalProperties"`,且不解析 `$ref` / `$defs`。
|
|
458
|
+
*
|
|
459
|
+
* 本 profile 描述的是 **`parameters` 这一字段**的能力,不是 Google 的能力上限:
|
|
460
|
+
* 完整 JSON Schema(含 `$ref` / `$defs`)走另一个字段 `parametersJsonSchema`。
|
|
461
|
+
* 把 `supportsRefs: false` 读成「Google 不支持引用」是错的,分流见 `googleGenAiClient.toGenAiTools`。
|
|
385
462
|
*/
|
|
386
463
|
const GOOGLE_SCHEMA_PROFILE = {
|
|
387
464
|
id: "google",
|
|
@@ -445,6 +522,46 @@ function sanitizeForVendor(schema, profile, toolName) {
|
|
|
445
522
|
if (!profile.supportsRefs && containsRef(schema)) throw new WebSkillError("TOOL_SCHEMA_UNAVAILABLE", `Tool "${toolName}" requires $ref support that provider "${profile.id}" does not accept`);
|
|
446
523
|
return sanitizeNode(schema, profile);
|
|
447
524
|
}
|
|
525
|
+
/**
|
|
526
|
+
* schema 能否走 profile 描述的受限通道。与 `sanitizeForVendor` 同判据,但不抛错——
|
|
527
|
+
* 调用方需要的是「选哪条通道」而不是「失败」。
|
|
528
|
+
*/
|
|
529
|
+
function isExpressibleForVendor(schema, profile) {
|
|
530
|
+
return profile.supportsRefs || !containsRef(schema);
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* 放宽不可终止的递归环:Gemini 只接受「可选 / 可为 null / 可零长数组」的引用环。
|
|
534
|
+
* 对 `items` 直接是 `$ref` 的数组节点删去 `minItems`。
|
|
535
|
+
*
|
|
536
|
+
* **只作用于出站副本**:catalog 本体的校验判据不变。
|
|
537
|
+
*/
|
|
538
|
+
function relaxRefLoops(schema) {
|
|
539
|
+
return relaxNode(schema);
|
|
540
|
+
}
|
|
541
|
+
function relaxNode(node) {
|
|
542
|
+
if (Array.isArray(node)) return node.map(relaxNode);
|
|
543
|
+
if (!isRecord$5(node)) return node;
|
|
544
|
+
const out = {};
|
|
545
|
+
for (const [key, value] of Object.entries(node)) {
|
|
546
|
+
if (key === "minItems" && isRecord$5(node["items"]) && typeof node["items"]["$ref"] === "string") continue;
|
|
547
|
+
if (SCHEMA_MAP_KEYS.has(key) && isRecord$5(value)) {
|
|
548
|
+
const mapped = {};
|
|
549
|
+
for (const [name, child] of Object.entries(value)) mapped[name] = relaxNode(child);
|
|
550
|
+
out[key] = mapped;
|
|
551
|
+
continue;
|
|
552
|
+
}
|
|
553
|
+
if (SCHEMA_LIST_KEYS.has(key) && Array.isArray(value)) {
|
|
554
|
+
out[key] = value.map(relaxNode);
|
|
555
|
+
continue;
|
|
556
|
+
}
|
|
557
|
+
if (SCHEMA_KEYS.has(key)) {
|
|
558
|
+
out[key] = relaxNode(value);
|
|
559
|
+
continue;
|
|
560
|
+
}
|
|
561
|
+
out[key] = value;
|
|
562
|
+
}
|
|
563
|
+
return out;
|
|
564
|
+
}
|
|
448
565
|
function createSseFrameReader() {
|
|
449
566
|
let buffer = "";
|
|
450
567
|
let data = [];
|
|
@@ -1151,11 +1268,14 @@ function toGenAiContents(messages) {
|
|
|
1151
1268
|
contents: out
|
|
1152
1269
|
};
|
|
1153
1270
|
}
|
|
1154
|
-
const toGenAiTools = (tools) => [{ functionDeclarations: tools.map((tool) =>
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
}
|
|
1271
|
+
const toGenAiTools = (tools) => [{ functionDeclarations: tools.map((tool) => {
|
|
1272
|
+
const portable = toPortableToolSchema(stripModelUnfillableParams(tool.inputSchema));
|
|
1273
|
+
return {
|
|
1274
|
+
name: tool.name,
|
|
1275
|
+
...tool.description ? { description: tool.description } : {},
|
|
1276
|
+
...isExpressibleForVendor(portable, GOOGLE_SCHEMA_PROFILE) ? { parameters: sanitizeForVendor(portable, GOOGLE_SCHEMA_PROFILE, tool.name) } : { parametersJsonSchema: relaxRefLoops(portable) }
|
|
1277
|
+
};
|
|
1278
|
+
}) }];
|
|
1159
1279
|
/** Google GenAI(generateContent / streamGenerateContent)客户端(零依赖 fetch) */
|
|
1160
1280
|
var GoogleGenAiClient = class {
|
|
1161
1281
|
#config;
|
|
@@ -1682,6 +1802,7 @@ const ASK_USER_INPUT_SCHEMA = {
|
|
|
1682
1802
|
type: "string",
|
|
1683
1803
|
description: "Help text shown under the input."
|
|
1684
1804
|
},
|
|
1805
|
+
defaultValue: { description: "A value the user already stated in this conversation; it is filled into the input for them. Only pass it when the user actually said it — do not guess." },
|
|
1685
1806
|
options: {
|
|
1686
1807
|
type: "array",
|
|
1687
1808
|
items: {
|
|
@@ -1725,6 +1846,78 @@ const ASK_USER_TOOL = {
|
|
|
1725
1846
|
source: "builtin"
|
|
1726
1847
|
};
|
|
1727
1848
|
/**
|
|
1849
|
+
* 产物 metadata 的准入与判读(分册 18)。
|
|
1850
|
+
*
|
|
1851
|
+
* metadata 是能力桥上第一个**开放结构**的入参,且来自沙箱内的技能脚本。
|
|
1852
|
+
* 校验落在 `createScriptContext.writeArtifact`——它是 in-process 与三个沙箱执行器
|
|
1853
|
+
* 唯一的汇聚点,在此抛错才能带上正确的桥请求 id 回给脚本(DV-10)。
|
|
1854
|
+
*/
|
|
1855
|
+
/** 序列化后的字节上限;`index.json` 是整覆盖原子写,无上限等于廉价的放大面 */
|
|
1856
|
+
const ARTIFACT_METADATA_MAX_BYTES = 4096;
|
|
1857
|
+
/** 原型污染键;JSON 解析产生的同名键是**自有键**,可被 getOwnPropertyNames 查出 */
|
|
1858
|
+
const FORBIDDEN_KEYS = /* @__PURE__ */ new Set([
|
|
1859
|
+
"__proto__",
|
|
1860
|
+
"constructor",
|
|
1861
|
+
"prototype"
|
|
1862
|
+
]);
|
|
1863
|
+
function isPlainObject$1(value) {
|
|
1864
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
1865
|
+
const proto = Object.getPrototypeOf(value);
|
|
1866
|
+
return proto === Object.prototype || proto === null;
|
|
1867
|
+
}
|
|
1868
|
+
/** 函数声明而非箭头函数赋值:只有前者能让 TS 的控制流分析认到 never 终止 */
|
|
1869
|
+
function reject$1(message) {
|
|
1870
|
+
throw new WebSkillError("VALIDATION_FAILED", message);
|
|
1871
|
+
}
|
|
1872
|
+
/**
|
|
1873
|
+
* 递归拒绝原型污染键与不可序列化值。
|
|
1874
|
+
* `JSON.stringify` 会**静默丢弃**函数与 symbol,而静默正是本需求明令禁止的形态,
|
|
1875
|
+
* 所以必须在序列化之前显式查一遍。
|
|
1876
|
+
*/
|
|
1877
|
+
function assertSerializableShape(value, path, seen) {
|
|
1878
|
+
const kind = typeof value;
|
|
1879
|
+
if (kind === "function" || kind === "symbol" || kind === "bigint") reject$1(`Artifact metadata value at "${path}" is not JSON-serializable (${kind})`);
|
|
1880
|
+
if (kind !== "object" || value === null) return;
|
|
1881
|
+
const container = value;
|
|
1882
|
+
if (seen.has(container)) reject$1(`Artifact metadata contains a circular reference at "${path}"`);
|
|
1883
|
+
seen.add(container);
|
|
1884
|
+
if (Array.isArray(value)) value.forEach((item, index) => assertSerializableShape(item, `${path}[${index}]`, seen));
|
|
1885
|
+
else {
|
|
1886
|
+
if (!isPlainObject$1(value)) reject$1(`Artifact metadata value at "${path}" must be a plain object or array`);
|
|
1887
|
+
for (const key of Object.getOwnPropertyNames(value)) {
|
|
1888
|
+
if (FORBIDDEN_KEYS.has(key)) reject$1(`Artifact metadata must not contain the reserved key "${key}" (at "${path}")`);
|
|
1889
|
+
assertSerializableShape(value[key], `${path}.${key}`, seen);
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1892
|
+
seen.delete(container);
|
|
1893
|
+
}
|
|
1894
|
+
/**
|
|
1895
|
+
* 准入校验。通过后返回 `JSON.parse(JSON.stringify(...))` 的副本:
|
|
1896
|
+
* in-process 路径由此获得与 JSON stdio 沙箱路径完全相同的语义,
|
|
1897
|
+
* 而不是依赖某条传输链路碰巧做了序列化。
|
|
1898
|
+
*/
|
|
1899
|
+
function admitArtifactMetadata(value) {
|
|
1900
|
+
if (!isPlainObject$1(value)) reject$1("Artifact metadata must be a plain object");
|
|
1901
|
+
assertSerializableShape(value, "metadata", /* @__PURE__ */ new Set());
|
|
1902
|
+
let json;
|
|
1903
|
+
try {
|
|
1904
|
+
json = JSON.stringify(value);
|
|
1905
|
+
} catch (error) {
|
|
1906
|
+
reject$1(`Artifact metadata is not JSON-serializable: ${error.message}`);
|
|
1907
|
+
}
|
|
1908
|
+
const bytes = new TextEncoder().encode(json).length;
|
|
1909
|
+
if (bytes > 4096) reject$1(`Artifact metadata is too large: ${bytes} bytes exceeds the ${ARTIFACT_METADATA_MAX_BYTES} byte limit`);
|
|
1910
|
+
return JSON.parse(json);
|
|
1911
|
+
}
|
|
1912
|
+
/**
|
|
1913
|
+
* 「这份产物不出自动下载卡」的判读。**严格 `=== false`**:
|
|
1914
|
+
* 隐式真值转换会让写错的键值静默生效,而隐藏是不可见的失败。
|
|
1915
|
+
* `buildRenderResult` 与 agentLoop 的去重集合共用本函数,两处判据不得分叉。
|
|
1916
|
+
*/
|
|
1917
|
+
function isArtifactCardHidden(artifact) {
|
|
1918
|
+
return artifact.metadata?.["resultCard"] === false;
|
|
1919
|
+
}
|
|
1920
|
+
/**
|
|
1728
1921
|
* 越权 / 绝对路径 / 父级遍历的技能目录读取:策略拒绝(FS_PERMISSION_DENIED,
|
|
1729
1922
|
* 计入 POLICY_DENIAL_CODES → 不计入隔离失败计数),
|
|
1730
1923
|
* 与「目录内路径确实不存在 → FS_NOT_FOUND」区分(0.9.0 分册 14,UX-04)。
|
|
@@ -1762,16 +1955,19 @@ function createScriptContext(deps) {
|
|
|
1762
1955
|
return readFs.readBinary(resolveSkillDir(skillRoot, "assets", relativePath));
|
|
1763
1956
|
},
|
|
1764
1957
|
async writeArtifact(path, content, options) {
|
|
1958
|
+
const metadata = options?.metadata === void 0 ? void 0 : admitArtifactMetadata(options.metadata);
|
|
1765
1959
|
const artifact = typeof content === "string" ? await artifactStore.createTextArtifact({
|
|
1766
1960
|
runId,
|
|
1767
1961
|
path,
|
|
1768
1962
|
content,
|
|
1769
|
-
mimeType: options?.mimeType
|
|
1963
|
+
mimeType: options?.mimeType,
|
|
1964
|
+
...metadata === void 0 ? {} : { metadata }
|
|
1770
1965
|
}) : await artifactStore.createBinaryArtifact({
|
|
1771
1966
|
runId,
|
|
1772
1967
|
path,
|
|
1773
1968
|
content,
|
|
1774
|
-
mimeType: options?.mimeType
|
|
1969
|
+
mimeType: options?.mimeType,
|
|
1970
|
+
...metadata === void 0 ? {} : { metadata }
|
|
1775
1971
|
});
|
|
1776
1972
|
onArtifactCreated?.(artifact);
|
|
1777
1973
|
return artifact;
|
|
@@ -1826,12 +2022,15 @@ function buildRenderResult(run, output, renderBlocks = []) {
|
|
|
1826
2022
|
text: output
|
|
1827
2023
|
});
|
|
1828
2024
|
}
|
|
1829
|
-
for (const artifact of run.artifacts)
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
2025
|
+
for (const artifact of run.artifacts) {
|
|
2026
|
+
if (isArtifactCardHidden(artifact)) continue;
|
|
2027
|
+
blocks.push({
|
|
2028
|
+
type: "file",
|
|
2029
|
+
path: artifact.path,
|
|
2030
|
+
...artifact.mimeType ? { mimeType: artifact.mimeType } : {},
|
|
2031
|
+
size: artifact.size
|
|
2032
|
+
});
|
|
2033
|
+
}
|
|
1835
2034
|
return {
|
|
1836
2035
|
runId: run.id,
|
|
1837
2036
|
summary: run.terminationReason,
|
|
@@ -2391,10 +2590,18 @@ function extractSkillCandidate(data) {
|
|
|
2391
2590
|
* @stable
|
|
2392
2591
|
*/
|
|
2393
2592
|
const DEFAULT_LOOP_LIMITS = {
|
|
2394
|
-
maxTurns:
|
|
2593
|
+
maxTurns: 1e3,
|
|
2395
2594
|
totalTimeoutMs: 36e5,
|
|
2396
|
-
toolTimeoutMs: 6e5
|
|
2595
|
+
toolTimeoutMs: 6e5,
|
|
2596
|
+
maxHistoryMessages: 1e3
|
|
2397
2597
|
};
|
|
2598
|
+
/**
|
|
2599
|
+
* 工具参数留存的单次体积上限(分册 30 / FR-30.2)。**全仓唯一来源**(S8)。
|
|
2600
|
+
*
|
|
2601
|
+
* 超限时不留半截参数,整条标记为 `truncated`。
|
|
2602
|
+
* @stable
|
|
2603
|
+
*/
|
|
2604
|
+
const MAX_TOOL_STEP_ARG_BYTES = 32768;
|
|
2398
2605
|
const RUN_SNAPSHOT_SCHEMA_VERSION = 3;
|
|
2399
2606
|
/** @experimental */
|
|
2400
2607
|
function isUnsupportedRunSnapshot(entry) {
|
|
@@ -2537,6 +2744,69 @@ function evaluateToolAccess(state, llmToolName) {
|
|
|
2537
2744
|
reason: denialReason(state, canonical)
|
|
2538
2745
|
};
|
|
2539
2746
|
}
|
|
2747
|
+
/**
|
|
2748
|
+
* 参数敏感标注关键字(分册 30 / FR-30.3)。
|
|
2749
|
+
*
|
|
2750
|
+
* 不用 `format: 'password'`:`format` 是 JSON Schema 的规范关键字,provider 侧
|
|
2751
|
+
* 可能据其做转换或校验,而且它只对 `type: 'string'` 有意义,对象型凭据标不了。
|
|
2752
|
+
* `x-` 前缀走 `JsonSchema` 的索引签名,不与任何规范语义抢占。
|
|
2753
|
+
*/
|
|
2754
|
+
const SENSITIVE_ANNOTATION = "x-webskill-sensitive";
|
|
2755
|
+
const isSensitive = (schema) => schema?.[SENSITIVE_ANNOTATION] === true;
|
|
2756
|
+
const isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2757
|
+
const join = (prefix, key) => prefix === "" ? key : `${prefix}.${key}`;
|
|
2758
|
+
/**
|
|
2759
|
+
* 按 schema 标注逐字段脱敏。
|
|
2760
|
+
*
|
|
2761
|
+
* 脱敏值取 `null` 而不是删键,也不是 `'***'`:删键会让生成器以为这个步骤
|
|
2762
|
+
* 本来就没有这个参数,从而写出漏参的技能;掩码则仍然泄露长度与存在性。
|
|
2763
|
+
*/
|
|
2764
|
+
function redactAnnotated(value, schema, path, redacted) {
|
|
2765
|
+
if (isSensitive(schema)) {
|
|
2766
|
+
redacted.push(path);
|
|
2767
|
+
return null;
|
|
2768
|
+
}
|
|
2769
|
+
if (Array.isArray(value)) return value.map((item, i) => redactAnnotated(item, schema?.items, `${path}[${i}]`, redacted));
|
|
2770
|
+
if (isPlainObject(value)) {
|
|
2771
|
+
const out = {};
|
|
2772
|
+
for (const [key, entry] of Object.entries(value)) out[key] = redactAnnotated(entry, schema?.properties?.[key], join(path, key), redacted);
|
|
2773
|
+
return out;
|
|
2774
|
+
}
|
|
2775
|
+
return value;
|
|
2776
|
+
}
|
|
2777
|
+
/** 不可信来源:所有叶子脱敏,键与结构保留 */
|
|
2778
|
+
function redactAll(value, path, redacted) {
|
|
2779
|
+
if (Array.isArray(value)) return value.map((item, i) => redactAll(item, `${path}[${i}]`, redacted));
|
|
2780
|
+
if (isPlainObject(value)) {
|
|
2781
|
+
const out = {};
|
|
2782
|
+
for (const [key, entry] of Object.entries(value)) out[key] = redactAll(entry, join(path, key), redacted);
|
|
2783
|
+
return out;
|
|
2784
|
+
}
|
|
2785
|
+
redacted.push(path);
|
|
2786
|
+
return null;
|
|
2787
|
+
}
|
|
2788
|
+
/**
|
|
2789
|
+
* 分层脱敏(FR-30.3)——**全仓唯一实现**。
|
|
2790
|
+
*
|
|
2791
|
+
* 1. `untrusted` → 所有字段脱敏;
|
|
2792
|
+
* 2. `reviewed` / `host-trusted` → 逐字段走 schema,标注为敏感的脱敏。
|
|
2793
|
+
*
|
|
2794
|
+
* 标注为敏感的字段在**任何**层级都脱敏:信任声明说的是「未标注的可以留」,
|
|
2795
|
+
* 不是「标注了也能留」。
|
|
2796
|
+
*/
|
|
2797
|
+
function redactToolStepArgs(args, schema, trust) {
|
|
2798
|
+
const redacted = [];
|
|
2799
|
+
const redactedArgs = trust.tier === "untrusted" ? redactAll(args, "", redacted) : redactAnnotated(args, schema, "", redacted);
|
|
2800
|
+
if (JSON.stringify(redactedArgs).length > 32768) return {
|
|
2801
|
+
args: {},
|
|
2802
|
+
redacted: [],
|
|
2803
|
+
truncated: true
|
|
2804
|
+
};
|
|
2805
|
+
return {
|
|
2806
|
+
args: redactedArgs,
|
|
2807
|
+
redacted
|
|
2808
|
+
};
|
|
2809
|
+
}
|
|
2540
2810
|
const MAX_SURFACE_PATCHES_PER_SECOND = 240;
|
|
2541
2811
|
/**
|
|
2542
2812
|
* 一轮 LLM 调用可能抛出、且**值得原样上报**的结构化码。
|
|
@@ -2572,6 +2842,11 @@ const summarizeArgs = (args) => {
|
|
|
2572
2842
|
const json = JSON.stringify(args);
|
|
2573
2843
|
return json.length > 100 ? `${json.slice(0, 100)}…` : json;
|
|
2574
2844
|
};
|
|
2845
|
+
/** 外部工具的 inputSchema 索引(分册 30);run 开始与 resume 各重建一次 */
|
|
2846
|
+
function indexExternalToolSchemas(state, specs) {
|
|
2847
|
+
state.externalToolSchemas.clear();
|
|
2848
|
+
for (const spec of specs) state.externalToolSchemas.set(spec.name, spec.inputSchema);
|
|
2849
|
+
}
|
|
2575
2850
|
/**
|
|
2576
2851
|
* file-pick 的回填值带整个文件的 base64,落进 `paramHistory` 会把用户选的文件
|
|
2577
2852
|
* 原样长期留在记忆里(体积与隐私都不可接受)。只留可辨识的描述,正文不留。
|
|
@@ -2717,6 +2992,7 @@ var AgentLoop = class {
|
|
|
2717
2992
|
pausedMs: 0,
|
|
2718
2993
|
maxTurns: this.#config.maxTurns,
|
|
2719
2994
|
totalTimeoutMs: this.#config.totalTimeoutMs,
|
|
2995
|
+
externalToolSchemas: /* @__PURE__ */ new Map(),
|
|
2720
2996
|
controller: new AbortController()
|
|
2721
2997
|
};
|
|
2722
2998
|
this.#controllers.set(runId, state.controller);
|
|
@@ -2736,14 +3012,8 @@ var AgentLoop = class {
|
|
|
2736
3012
|
candidates: route.catalog.entries.map((e) => e.name)
|
|
2737
3013
|
}
|
|
2738
3014
|
}, state);
|
|
2739
|
-
const externalSpecs = this.#config.toolCallingDisabled ? [] :
|
|
2740
|
-
|
|
2741
|
-
return await source.listToolSpecs();
|
|
2742
|
-
} catch (e) {
|
|
2743
|
-
trace.record("run.warning", { message: `External tool source "${source.kind}" failed to list specs: ${messageOf(e)}` });
|
|
2744
|
-
return [];
|
|
2745
|
-
}
|
|
2746
|
-
}))).flat();
|
|
3015
|
+
const externalSpecs = this.#config.toolCallingDisabled ? [] : await this.#collectExternalSpecs(state);
|
|
3016
|
+
indexExternalToolSchemas(state, externalSpecs);
|
|
2747
3017
|
const externalSystemPrompts = [];
|
|
2748
3018
|
if (!this.#config.toolCallingDisabled) for (const source of this.#deps.externalTools ?? []) {
|
|
2749
3019
|
if (source.systemPrompt === void 0) continue;
|
|
@@ -3113,6 +3383,7 @@ var AgentLoop = class {
|
|
|
3113
3383
|
pausedMs: snapshot.pausedMs ?? 0,
|
|
3114
3384
|
maxTurns: snapshot.config.maxTurns,
|
|
3115
3385
|
totalTimeoutMs: snapshot.config.totalTimeoutMs,
|
|
3386
|
+
externalToolSchemas: /* @__PURE__ */ new Map(),
|
|
3116
3387
|
controller: new AbortController()
|
|
3117
3388
|
};
|
|
3118
3389
|
this.#controllers.set(runId, state.controller);
|
|
@@ -3126,6 +3397,8 @@ var AgentLoop = class {
|
|
|
3126
3397
|
} });
|
|
3127
3398
|
const pending = pendingInteraction;
|
|
3128
3399
|
const pendingCall = this.#findPendingToolCall(state.messages);
|
|
3400
|
+
const externalSpecs = await this.#collectExternalSpecs(state);
|
|
3401
|
+
indexExternalToolSchemas(state, externalSpecs);
|
|
3129
3402
|
const carried = [];
|
|
3130
3403
|
try {
|
|
3131
3404
|
await this.#replaySurfaceEvents(state);
|
|
@@ -3183,14 +3456,6 @@ var AgentLoop = class {
|
|
|
3183
3456
|
if (e instanceof RunTerminated) return this.#finish(state, e.outcome.status, e.outcome.reason, e.outcome.message, e.outcome.code);
|
|
3184
3457
|
throw e;
|
|
3185
3458
|
}
|
|
3186
|
-
const externalSpecs = (await Promise.all((this.#deps.externalTools ?? []).map(async (source) => {
|
|
3187
|
-
try {
|
|
3188
|
-
return await source.listToolSpecs();
|
|
3189
|
-
} catch (e) {
|
|
3190
|
-
trace.record("run.warning", { message: `External tool source "${source.kind}" failed to list specs: ${messageOf(e)}` });
|
|
3191
|
-
return [];
|
|
3192
|
-
}
|
|
3193
|
-
}))).flat();
|
|
3194
3459
|
try {
|
|
3195
3460
|
return await this.#turnLoop(state, snapshot.turn + 1, externalSpecs);
|
|
3196
3461
|
} catch (e) {
|
|
@@ -3419,6 +3684,81 @@ var AgentLoop = class {
|
|
|
3419
3684
|
});
|
|
3420
3685
|
});
|
|
3421
3686
|
}
|
|
3687
|
+
/** 外部工具 specs:单个来源失败跳过并记 warning(run 开始与 resume 共用) */
|
|
3688
|
+
async #collectExternalSpecs(state) {
|
|
3689
|
+
return (await Promise.all((this.#deps.externalTools ?? []).map(async (source) => {
|
|
3690
|
+
try {
|
|
3691
|
+
return await source.listToolSpecs();
|
|
3692
|
+
} catch (e) {
|
|
3693
|
+
state.trace.record("run.warning", { message: `External tool source "${source.kind}" failed to list specs: ${messageOf(e)}` });
|
|
3694
|
+
return [];
|
|
3695
|
+
}
|
|
3696
|
+
}))).flat();
|
|
3697
|
+
}
|
|
3698
|
+
/**
|
|
3699
|
+
* 一次工具调用的信任层级与 inputSchema(分册 30)。
|
|
3700
|
+
*
|
|
3701
|
+
* 技能脚本工具按 `untrusted`:它们的 schema 来自各技能的 frontmatter,
|
|
3702
|
+
* 是第三方内容,不是本仓审查过的。
|
|
3703
|
+
*/
|
|
3704
|
+
#toolCaptureContext(call, state) {
|
|
3705
|
+
if (call.name === "read_skill_file") return {
|
|
3706
|
+
trust: { tier: "reviewed" },
|
|
3707
|
+
schema: READ_SKILL_FILE_TOOL.inputSchema,
|
|
3708
|
+
args: call.arguments
|
|
3709
|
+
};
|
|
3710
|
+
if (call.name === "ask_user") return {
|
|
3711
|
+
trust: { tier: "reviewed" },
|
|
3712
|
+
schema: ASK_USER_TOOL.inputSchema,
|
|
3713
|
+
args: call.arguments
|
|
3714
|
+
};
|
|
3715
|
+
if (call.name === "read_linked_document") return {
|
|
3716
|
+
trust: { tier: "reviewed" },
|
|
3717
|
+
schema: READ_LINKED_DOCUMENT_TOOL.inputSchema,
|
|
3718
|
+
args: call.arguments
|
|
3719
|
+
};
|
|
3720
|
+
const source = (this.#deps.externalTools ?? []).find((s) => s.canHandle(call.name));
|
|
3721
|
+
if (source === void 0) return {
|
|
3722
|
+
trust: { tier: "untrusted" },
|
|
3723
|
+
args: call.arguments
|
|
3724
|
+
};
|
|
3725
|
+
const schema = state.externalToolSchemas.get(call.name);
|
|
3726
|
+
const trust = source.argCaptureTrust?.(call.name, call.arguments) ?? { tier: "untrusted" };
|
|
3727
|
+
const args = source.captureArgs?.(call.name, call.arguments) ?? call.arguments;
|
|
3728
|
+
return schema === void 0 ? {
|
|
3729
|
+
trust,
|
|
3730
|
+
args
|
|
3731
|
+
} : {
|
|
3732
|
+
trust,
|
|
3733
|
+
schema,
|
|
3734
|
+
args
|
|
3735
|
+
};
|
|
3736
|
+
}
|
|
3737
|
+
/**
|
|
3738
|
+
* 成功调用的完整参数留存(FR-30.2)。失败的调用不留存:它什么也没做成,
|
|
3739
|
+
* 让模型引用它只会生成一个跑不通的步骤。
|
|
3740
|
+
*/
|
|
3741
|
+
async #captureToolStep(call, state) {
|
|
3742
|
+
const store = this.#deps.toolSteps;
|
|
3743
|
+
if (store === void 0) return;
|
|
3744
|
+
const { trust, schema, args: captured } = this.#toolCaptureContext(call, state);
|
|
3745
|
+
const { args, redacted, truncated } = redactToolStepArgs(captured, schema, trust);
|
|
3746
|
+
try {
|
|
3747
|
+
await store.append({
|
|
3748
|
+
runId: state.runId,
|
|
3749
|
+
sessionId: state.run.sessionId,
|
|
3750
|
+
callId: call.id,
|
|
3751
|
+
tool: call.name,
|
|
3752
|
+
at: state.now(),
|
|
3753
|
+
args,
|
|
3754
|
+
redacted,
|
|
3755
|
+
...truncated !== void 0 ? { truncated } : {},
|
|
3756
|
+
trust
|
|
3757
|
+
});
|
|
3758
|
+
} catch (e) {
|
|
3759
|
+
state.trace.record("run.warning", { message: `Failed to capture tool step arguments: ${messageOf(e)}` });
|
|
3760
|
+
}
|
|
3761
|
+
}
|
|
3422
3762
|
async #executeCall(call, state) {
|
|
3423
3763
|
const argsSummary = summarizeArgs(call.arguments);
|
|
3424
3764
|
const owner = this.#skillOf(call, state);
|
|
@@ -3458,6 +3798,7 @@ var AgentLoop = class {
|
|
|
3458
3798
|
durationMs,
|
|
3459
3799
|
...attribution
|
|
3460
3800
|
} });
|
|
3801
|
+
await this.#captureToolStep(call, state);
|
|
3461
3802
|
this.#emitTool(state, "completed", call);
|
|
3462
3803
|
for (const item of result.content) {
|
|
3463
3804
|
if (item.type !== "json") continue;
|
|
@@ -3497,7 +3838,7 @@ var AgentLoop = class {
|
|
|
3497
3838
|
this.#emitTool(state, "failed", call, result.error?.code);
|
|
3498
3839
|
}
|
|
3499
3840
|
for (const artifact of result.artifacts ?? []) {
|
|
3500
|
-
state.artifactPaths.add(artifact.path);
|
|
3841
|
+
if (!isArtifactCardHidden(artifact)) state.artifactPaths.add(artifact.path);
|
|
3501
3842
|
state.trace.record("artifact.created", { data: {
|
|
3502
3843
|
artifactId: artifact.id,
|
|
3503
3844
|
path: artifact.path
|
|
@@ -3575,7 +3916,7 @@ var AgentLoop = class {
|
|
|
3575
3916
|
async #stripDuplicateFileLinks(state, event) {
|
|
3576
3917
|
if (state.artifactPaths.size === 0) {
|
|
3577
3918
|
const listed = await this.#deps.artifactStore.listArtifacts(state.runId).catch(() => []);
|
|
3578
|
-
for (const artifact of listed) state.artifactPaths.add(artifact.path);
|
|
3919
|
+
for (const artifact of listed) if (!isArtifactCardHidden(artifact)) state.artifactPaths.add(artifact.path);
|
|
3579
3920
|
}
|
|
3580
3921
|
if (state.artifactPaths.size === 0) return event;
|
|
3581
3922
|
const paths = state.artifactPaths;
|
|
@@ -3956,6 +4297,7 @@ var AgentLoop = class {
|
|
|
3956
4297
|
type,
|
|
3957
4298
|
...field["required"] === true ? { required: true } : {},
|
|
3958
4299
|
...typeof field["description"] === "string" ? { description: field["description"] } : {},
|
|
4300
|
+
...field["defaultValue"] !== void 0 ? { defaultValue: field["defaultValue"] } : {},
|
|
3959
4301
|
...Array.isArray(options) ? { options: options.filter((o) => typeof o === "object" && o !== null).map((o) => ({
|
|
3960
4302
|
label: String(o["label"] ?? o["value"]),
|
|
3961
4303
|
value: o["value"]
|
|
@@ -4719,12 +5061,12 @@ var WebSkillRuntime = class {
|
|
|
4719
5061
|
* 多会话:session 对象的 run(prompt) 跨 run 延续消息历史(同一 session 对话上下文连续)。
|
|
4720
5062
|
* 既有 runtime.run(prompt) 保持无状态单次语义不变。
|
|
4721
5063
|
* 同 handle 并发 run 经 per-handle 队列串行化(防历史 last-writer-wins 丢轮次);
|
|
4722
|
-
* maxHistoryMessages
|
|
5064
|
+
* maxHistoryMessages(默认取 `DEFAULT_LOOP_LIMITS`)超出时滚动裁剪中段(保留首尾;边界对齐 tool 契约)。
|
|
4723
5065
|
*/
|
|
4724
5066
|
createSession(options = {}) {
|
|
4725
5067
|
const sessionId = options.sessionId ?? `session-${Math.random().toString(36).slice(2, 10)}`;
|
|
4726
5068
|
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4727
|
-
const maxHistory = options.maxHistoryMessages ??
|
|
5069
|
+
const maxHistory = options.maxHistoryMessages ?? DEFAULT_LOOP_LIMITS.maxHistoryMessages;
|
|
4728
5070
|
let history = [];
|
|
4729
5071
|
let queue = Promise.resolve();
|
|
4730
5072
|
return {
|
|
@@ -4791,6 +5133,7 @@ var WebSkillRuntime = class {
|
|
|
4791
5133
|
skillProviders: this.#deps.skillProviders,
|
|
4792
5134
|
catalogFilter: this.#deps.catalogFilter,
|
|
4793
5135
|
snapshotStore: this.#deps.snapshotStore,
|
|
5136
|
+
toolSteps: this.#deps.toolSteps,
|
|
4794
5137
|
skillStateGuard: this.#deps.skillStateGuard,
|
|
4795
5138
|
skillIntegrityGuard: this.#deps.skillIntegrityGuard,
|
|
4796
5139
|
skillOutcomeReporter: this.#deps.skillOutcomeReporter,
|
|
@@ -4916,6 +5259,7 @@ var WebSkillRuntime = class {
|
|
|
4916
5259
|
skillProviders: this.#deps.skillProviders,
|
|
4917
5260
|
catalogFilter: this.#deps.catalogFilter,
|
|
4918
5261
|
snapshotStore: store,
|
|
5262
|
+
toolSteps: this.#deps.toolSteps,
|
|
4919
5263
|
skillStateGuard: this.#deps.skillStateGuard,
|
|
4920
5264
|
skillIntegrityGuard: this.#deps.skillIntegrityGuard,
|
|
4921
5265
|
skillOutcomeReporter: this.#deps.skillOutcomeReporter,
|
|
@@ -5449,7 +5793,8 @@ function parseBridgeRequest(data) {
|
|
|
5449
5793
|
id,
|
|
5450
5794
|
path,
|
|
5451
5795
|
content,
|
|
5452
|
-
...isNonEmptyString(mimeType) ? { mimeType } : {}
|
|
5796
|
+
...isNonEmptyString(mimeType) ? { mimeType } : {},
|
|
5797
|
+
..."metadata" in data ? { metadata: data["metadata"] } : {}
|
|
5453
5798
|
};
|
|
5454
5799
|
}
|
|
5455
5800
|
case "confirm": return isNonEmptyString(data["message"]) ? {
|
|
@@ -5892,6 +6237,7 @@ function sortByStartedAtDesc(summaries) {
|
|
|
5892
6237
|
function applyFilter(summaries, filter) {
|
|
5893
6238
|
let runs = summaries;
|
|
5894
6239
|
if (filter.status !== void 0 && filter.status !== "") runs = runs.filter((r) => r.status === filter.status);
|
|
6240
|
+
if (filter.sessionId !== void 0 && filter.sessionId !== "") runs = runs.filter((r) => r.sessionId === filter.sessionId);
|
|
5895
6241
|
const q = filter.search?.trim().toLowerCase();
|
|
5896
6242
|
if (q !== void 0 && q !== "") runs = runs.filter((r) => r.runId.toLowerCase().includes(q) || r.activeSkills.some((s) => s.toLowerCase().includes(q)));
|
|
5897
6243
|
return runs;
|
|
@@ -6151,6 +6497,51 @@ var FsSessionStore = class {
|
|
|
6151
6497
|
});
|
|
6152
6498
|
}
|
|
6153
6499
|
};
|
|
6500
|
+
/**
|
|
6501
|
+
* 按会话分文件的 append-only JSONL 留存。
|
|
6502
|
+
*
|
|
6503
|
+
* 分文件维度取会话而非 run:读取侧唯一的查询就是「这个会话的全部步骤」,
|
|
6504
|
+
* 按 run 分会让一次生成要开 N 个文件。
|
|
6505
|
+
*/
|
|
6506
|
+
var FsToolStepStore = class {
|
|
6507
|
+
#root;
|
|
6508
|
+
#fs;
|
|
6509
|
+
#onError;
|
|
6510
|
+
constructor(deps) {
|
|
6511
|
+
this.#root = deps.root.replace(/\/+$/, "");
|
|
6512
|
+
this.#fs = deps.fs;
|
|
6513
|
+
this.#onError = deps.onError ?? ((error, record) => {
|
|
6514
|
+
console.warn(`Failed to persist tool step for call "${record.callId}": ${messageOf(error)}`);
|
|
6515
|
+
});
|
|
6516
|
+
}
|
|
6517
|
+
#path(sessionId) {
|
|
6518
|
+
assertSafePathSegment(sessionId, "session id");
|
|
6519
|
+
return resolveInsideRoot(this.#root, `${sessionId}.jsonl`);
|
|
6520
|
+
}
|
|
6521
|
+
async append(record) {
|
|
6522
|
+
const path = this.#path(record.sessionId);
|
|
6523
|
+
try {
|
|
6524
|
+
await this.#fs.appendText(path, `${JSON.stringify(record)}\n`);
|
|
6525
|
+
} catch (e) {
|
|
6526
|
+
this.#onError(e, record);
|
|
6527
|
+
}
|
|
6528
|
+
}
|
|
6529
|
+
async listBySession(sessionId) {
|
|
6530
|
+
const path = this.#path(sessionId);
|
|
6531
|
+
if (!await this.#fs.exists(path)) return [];
|
|
6532
|
+
const raw = await this.#fs.readText(path);
|
|
6533
|
+
const records = [];
|
|
6534
|
+
for (const line of raw.split("\n")) {
|
|
6535
|
+
if (line.trim() === "") continue;
|
|
6536
|
+
try {
|
|
6537
|
+
records.push(JSON.parse(line));
|
|
6538
|
+
} catch {
|
|
6539
|
+
continue;
|
|
6540
|
+
}
|
|
6541
|
+
}
|
|
6542
|
+
return records;
|
|
6543
|
+
}
|
|
6544
|
+
};
|
|
6154
6545
|
|
|
6155
6546
|
//#endregion
|
|
6156
|
-
export {
|
|
6547
|
+
export { bridgeError as $, ProgressiveRouter as A, refineUserProfile as At, SUPPORTED_DOCUMENT_MIME as B, toLlmToolSpec as Bt, FsSessionStore as C, normalizeToolError as Ct, HookRunner as D, readProfileEntries as Dt, GoogleGenAiClient as E, readBehaviorRecords as Et, READ_SKILL_FILE_TOOL_NAME as F, schemaToForm as Ft, USER_PROFILE_EXPORT_VERSION as G, TEXT_BUDGETED_CONTENT_TYPES as H, toVercelToolSpecs as Ht, RUN_SNAPSHOT_SCHEMA_VERSION as I, scriptToolName as It, USER_PROFILE_PROMPT_HEADER as J, USER_PROFILE_KEY as K, RUN_TRACE_SCHEMA_VERSION as L, sealToolCallPairs as Lt, READ_LINKED_DOCUMENT_TOOL_NAME as M, resolveToolName as Mt, READ_SKILL_FILE_INPUT_SCHEMA as N, sampleBehaviorRecords as Nt, MAX_TOOL_STEP_ARG_BYTES as O, readUserProfile as Ot, READ_SKILL_FILE_TOOL as P, schemaSourceLabel as Pt, applyUserProfileImport as Q, SENSITIVE_ANNOTATION as R, summarizeRunUsage as Rt, FsRunTraceStore as S, normalizeToolContent as St, FullDisclosureRouter as T, parseUserProfileExport as Tt, TraceRecorder as U, validateUiSpecEvent as Ut, SerializingMemoryStore as V, toRecordDigests as Vt, UNSUPPORTED_DOCUMENT_MESSAGE as W, validateUiSpecNode as Wt, WebSkillRuntime as X, USER_PROFILE_REFINE_PROMPT as Y, appendBehaviorRecords as Z, EventBus as _, mergeCatalogEntries as _t, ASK_USER_TOOL as a, extractChartSpec as at, FsMemoryStore as b, networkUrlHost as bt, AnthropicClient as c, extractUiSpecEvents as ct, DEFAULT_LOOP_LIMITS as d, fromVercelResult as dt, buildRenderResult as et, DEFAULT_MAX_DATA_SOURCE_BYTES as f, fromVercelStreamPart as ft, EMPTY_USER_PROFILE as g, listSkillScripts as gt, DEFAULT_USER_PROFILE_LIMITS as h, isUnsupportedRunSnapshot as ht, ASK_USER_MAX_FIELDS as i, exportUserProfile as it, READ_LINKED_DOCUMENT_TOOL as j, renderUserProfileContext as jt, OpenAiCompatibleClient as k, redactToolStepArgs as kt, BEHAVIOR_RECORDS_KEY as l, findUnpairedToolCalls as lt, DEFAULT_MAX_DOCUMENT_TEXT_BYTES as m, isNetworkAllowed as mt, ASK_USER_FIELD_TYPES as n, createWebSkillApi as nt, ASK_USER_TOOL_NAME as o, extractSkillCandidate as ot, DEFAULT_MAX_DOCUMENT_BYTES as p, interruptedToolResult as pt, USER_PROFILE_NO_INVENTION_RULE as q, ASK_USER_INPUT_SCHEMA as r, diffUserProfile as rt, AgentLoop as s, extractTodoTraceEvents as st, ALLOWED_TOOLS_EXCLUSION_REASON as t, createScriptContext as tt, CapabilityApproval as u, formatSkillScriptManifest as ut, FS_SESSION_PAGE_SIZE as v, mergeProfileEntries as vt, FsToolStepStore as w, parseBridgeRequest as wt, FsRunSnapshotStore as x, normalizeErrorCode as xt, FsArtifactStore as y, networkPolicyLibSource as yt, SESSION_SCHEMA_VERSION as z, summarizeToolCalls as zt };
|