@webskill/sdk 0.9.0 → 0.10.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.
Files changed (33) hide show
  1. package/dist/agent.d.ts +2 -2
  2. package/dist/agent.js +5 -1
  3. package/dist/browser.d.ts +5 -3
  4. package/dist/browser.js +15 -7
  5. package/dist/{catalogComponents-DfxxfUvn-T7Ic8QFV.js → catalogComponents-DTcYfpLQ-CcoOaz-Z.js} +1354 -415
  6. package/dist/{dist-BQe1uglQ.js → dist-1OFC-zax.js} +6 -4
  7. package/dist/{dist-CFmkV45C.js → dist-BViUeszk.js} +349 -32
  8. package/dist/{eventTypes-DbOpAECr-BjcjZVms.js → eventTypes-s2uwAcLG-Go3l_dUe.js} +5 -2
  9. package/dist/governance.d.ts +29 -6
  10. package/dist/governance.js +45 -7
  11. package/dist/{index-DXNTIa-6.d.ts → index-B0QPLWPZ.d.ts} +6 -2
  12. package/dist/{index-lLcCpHE-.d.ts → index-BF4E1a9j.d.ts} +10 -3
  13. package/dist/{index-znZjobkr.d.ts → index-DtFdMKBX.d.ts} +63 -6
  14. package/dist/index.d.ts +4 -4
  15. package/dist/index.js +3 -3
  16. package/dist/mcp.d.ts +18 -3
  17. package/dist/mcp.js +62 -21
  18. package/dist/node.d.ts +3 -3
  19. package/dist/node.js +2 -2
  20. package/dist/{openUiLibrary-DURlAxjk-Do_yqg3u.js → openUiLibrary-CIrV--Ad-B8zG_91e.js} +3 -3
  21. package/dist/{skillVersionStore-Bl-ElD45-dMJ8Ybhb.d.ts → skillVersionStore-D-qHk9ZE-DBsYYCWn.d.ts} +13 -5
  22. package/dist/{testing-Csg5ljNm.js → testing-WPTyXQYt.js} +26 -3
  23. package/dist/testing.d.ts +1 -1
  24. package/dist/testing.js +1 -1
  25. package/dist/{types-B3n0cMZu-BDhheIhX.d.ts → types-CrRcT-LM-DZAp8sWv.d.ts} +36 -3
  26. package/dist/ui-react.d.ts +11 -2
  27. package/dist/ui-react.js +119 -38
  28. package/dist/ui-vue.d.ts +1 -1
  29. package/dist/ui-vue.js +1 -1
  30. package/dist/ui.d.ts +3 -3
  31. package/dist/ui.js +2 -2
  32. package/dist/{webskillLitCatalog-DwTwSBFt-BG7kL-Es.js → webskillLitCatalog-BJrphK0y-SGmRXaaO.js} +2 -2
  33. package/package.json +1 -1
@@ -103,11 +103,11 @@ const SCHEMA_KEYS = /* @__PURE__ */ new Set([
103
103
  "then",
104
104
  "else"
105
105
  ]);
106
- function isRecord$6(value) {
106
+ function isRecord$7(value) {
107
107
  return typeof value === "object" && value !== null && !Array.isArray(value);
108
108
  }
109
109
  function isSelfRef(value) {
110
- return isRecord$6(value) && value["$ref"] === SELF_REF;
110
+ return isRecord$7(value) && value["$ref"] === SELF_REF;
111
111
  }
112
112
  /**
113
113
  * 按 JSON Schema 关键字下降到子 schema。
@@ -117,7 +117,7 @@ function isSelfRef(value) {
117
117
  function forEachSubSchema(node, visit) {
118
118
  for (const [key, value] of Object.entries(node)) {
119
119
  if (SCHEMA_MAP_KEYS.has(key)) {
120
- if (isRecord$6(value)) for (const name of Object.keys(value)) visit(value[name], [key, name]);
120
+ if (isRecord$7(value)) for (const name of Object.keys(value)) visit(value[name], [key, name]);
121
121
  continue;
122
122
  }
123
123
  if (SCHEMA_LIST_KEYS.has(key)) {
@@ -136,7 +136,7 @@ function pathKey(path) {
136
136
  * `#` 解析到最近的带 `$id` 的祖先;没有则是文档根。
137
137
  */
138
138
  function collectSelfRefRoots(node, path, resourceRoot, out) {
139
- if (!isRecord$6(node)) return;
139
+ if (!isRecord$7(node)) return;
140
140
  if (isSelfRef(node)) {
141
141
  out.set(pathKey(resourceRoot), resourceRoot);
142
142
  return;
@@ -149,7 +149,7 @@ function collectSelfRefRoots(node, path, resourceRoot, out) {
149
149
  function getAt(schema, path) {
150
150
  let current = schema;
151
151
  for (const segment of path) if (Array.isArray(current) && typeof segment === "number") current = current[segment];
152
- else if (isRecord$6(current) && typeof segment === "string") current = current[segment];
152
+ else if (isRecord$7(current) && typeof segment === "string") current = current[segment];
153
153
  else return void 0;
154
154
  return current;
155
155
  }
@@ -175,7 +175,7 @@ function setAt(schema, path, replacement) {
175
175
  * 正是严格解析器无法解析 `#` 的直接原因。
176
176
  */
177
177
  function rewriteSelfRefs(node, target, depth) {
178
- if (!isRecord$6(node)) return node;
178
+ if (!isRecord$7(node)) return node;
179
179
  if (depth > 8) throw new WebSkillError("TOOL_SCHEMA_UNAVAILABLE", `Tool schema nesting exceeds 8 levels; cannot produce a portable form`);
180
180
  if (isSelfRef(node)) {
181
181
  const rest = {};
@@ -188,7 +188,7 @@ function rewriteSelfRefs(node, target, depth) {
188
188
  const result = {};
189
189
  for (const [key, value] of Object.entries(node)) {
190
190
  if (key === "$id" || key === "$schema") continue;
191
- if (SCHEMA_MAP_KEYS.has(key) && isRecord$6(value)) {
191
+ if (SCHEMA_MAP_KEYS.has(key) && isRecord$7(value)) {
192
192
  const mapped = {};
193
193
  for (const [name, child] of Object.entries(value)) mapped[name] = rewriteSelfRefs(child, target, depth + 1);
194
194
  result[key] = mapped;
@@ -226,8 +226,8 @@ function toPortableToolSchema(schema) {
226
226
  if (roots.size > 1) throw new WebSkillError("TOOL_SCHEMA_UNAVAILABLE", "Tool schema contains self references in more than one schema resource; cannot produce a portable form");
227
227
  const rootPath = [...roots.values()][0] ?? [];
228
228
  const resource = getAt(schema, rootPath);
229
- if (!isRecord$6(resource)) return schema;
230
- const existingDefs = isRecord$6(schema[DEFS_KEY]) ? schema[DEFS_KEY] : void 0;
229
+ if (!isRecord$7(resource)) return schema;
230
+ const existingDefs = isRecord$7(schema[DEFS_KEY]) ? schema[DEFS_KEY] : void 0;
231
231
  const taken = new Set(Object.keys(existingDefs ?? {}));
232
232
  const nodeName = uniqueName(NODE_NAME, taken);
233
233
  taken.add(nodeName);
@@ -258,6 +258,63 @@ function toPortableToolSchema(schema) {
258
258
  }
259
259
  };
260
260
  }
261
+ function isRecord$6(value) {
262
+ return typeof value === "object" && value !== null && !Array.isArray(value);
263
+ }
264
+ /**
265
+ * 与 `interaction/schemaToForm` 的 file 判定保持一致:JSON Schema 里二进制内容的
266
+ * 两种标准写法(`format: binary` / `contentEncoding: base64`)。
267
+ */
268
+ function isModelUnfillable(node) {
269
+ return isRecord$6(node) && node["type"] === "string" && (node["format"] === "binary" || node["contentEncoding"] === "base64");
270
+ }
271
+ function stripNode(node) {
272
+ if (Array.isArray(node)) return node.map(stripNode);
273
+ if (!isRecord$6(node)) return node;
274
+ const out = {};
275
+ for (const [key, value] of Object.entries(node)) {
276
+ if (SCHEMA_MAP_KEYS.has(key) && isRecord$6(value)) {
277
+ const mapped = {};
278
+ for (const [name, child] of Object.entries(value)) {
279
+ if (key === "properties" && isModelUnfillable(child)) continue;
280
+ mapped[name] = stripNode(child);
281
+ }
282
+ out[key] = mapped;
283
+ continue;
284
+ }
285
+ if (SCHEMA_LIST_KEYS.has(key) && Array.isArray(value)) {
286
+ out[key] = value.map(stripNode);
287
+ continue;
288
+ }
289
+ if (SCHEMA_KEYS.has(key)) {
290
+ out[key] = stripNode(value);
291
+ continue;
292
+ }
293
+ out[key] = value;
294
+ }
295
+ const required = out["required"];
296
+ const properties = out["properties"];
297
+ if (Array.isArray(required) && isRecord$6(properties)) out["required"] = required.filter((name) => typeof name !== "string" || name in properties);
298
+ return out;
299
+ }
300
+ /**
301
+ * 把模型不可能自己产出的字段(本地文件二进制)从**出站**工具 schema 里剥离。
302
+ *
303
+ * 模型拿不到用户磁盘上的文件,留着这个字段只有两种下场:模型拒绝调用工具
304
+ * (实测 DeepSeek 直接回文本「请上传文件」,file-pick 永远触发不了),或编造一个
305
+ * 占位字符串把技能跑挂。剥掉后模型以缺参形式调用,引擎的 missing-params 链路
306
+ * 会弹 file-pick 让用户用系统文件选择器补这个字段。
307
+ *
308
+ * 这是**传输层适配**,只应在出站请求体上调用;不要下沉到 AgentLoop——
309
+ * 引擎侧的 missing 校验看的必须是技能作者写的完整 inputSchema。
310
+ *
311
+ * 已知边界(0.10.0 复核注记):只剥 `properties` 里的 inline 二进制字段;
312
+ * 通过 `$ref` 指向 `$defs` 中二进制定义的字段仍会下发(剥掉会留悬空 $ref),
313
+ * 这类技能依旧可能拿不到 file-pick——需要完整修复时再补「剥 $def + 剥指向它的 $ref」。
314
+ */
315
+ function stripModelUnfillableParams(schema) {
316
+ return stripNode(schema);
317
+ }
261
318
  /** 各家都认的基础关键字。Google `FunctionDeclaration.parameters` 是其中最窄的一家。 */
262
319
  const BASE_KEYWORDS = /* @__PURE__ */ new Set([
263
320
  "type",
@@ -499,7 +556,7 @@ const toOpenAiTools = (tools) => tools.map((tool) => ({
499
556
  function: {
500
557
  name: tool.name,
501
558
  ...tool.description ? { description: tool.description } : {},
502
- parameters: sanitizeForVendor(toPortableToolSchema(tool.inputSchema), OPENAI_SCHEMA_PROFILE, tool.name)
559
+ parameters: sanitizeForVendor(toPortableToolSchema(stripModelUnfillableParams(tool.inputSchema)), OPENAI_SCHEMA_PROFILE, tool.name)
503
560
  }
504
561
  }));
505
562
  const errorMessage$2 = (e) => e instanceof Error ? e.message : String(e);
@@ -539,6 +596,7 @@ var OpenAiCompatibleClient = class {
539
596
  const reader = res.body.getReader();
540
597
  const frames = createSseFrameReader();
541
598
  let done = false;
599
+ let usage;
542
600
  const handleFrame = function* (data) {
543
601
  if (data === "[DONE]") {
544
602
  done = true;
@@ -550,8 +608,17 @@ var OpenAiCompatibleClient = class {
550
608
  } catch (e) {
551
609
  throw new WebSkillError("LLM_REQUEST_FAILED", `Failed to parse LLM stream frame: ${errorMessage$2(e)}`, data);
552
610
  }
611
+ const usageRaw = chunk.usage;
612
+ if (usageRaw && (typeof usageRaw["prompt_tokens"] === "number" || typeof usageRaw["completion_tokens"] === "number")) usage = {
613
+ inputTokens: typeof usageRaw["prompt_tokens"] === "number" ? usageRaw["prompt_tokens"] : 0,
614
+ outputTokens: typeof usageRaw["completion_tokens"] === "number" ? usageRaw["completion_tokens"] : 0
615
+ };
553
616
  const delta = chunk.choices?.[0]?.delta;
554
617
  if (!delta) return;
618
+ if (typeof delta["reasoning_content"] === "string" && delta["reasoning_content"] !== "") yield {
619
+ type: "thinking-delta",
620
+ delta: delta["reasoning_content"]
621
+ };
555
622
  if (typeof delta["content"] === "string" && delta["content"] !== "") yield {
556
623
  type: "text-delta",
557
624
  delta: delta["content"]
@@ -601,7 +668,10 @@ var OpenAiCompatibleClient = class {
601
668
  };
602
669
  })
603
670
  };
604
- yield { type: "done" };
671
+ yield {
672
+ type: "done",
673
+ ...usage ? { usage } : {}
674
+ };
605
675
  }
606
676
  async #postChat(input, stream) {
607
677
  const { baseUrl, apiKey, model } = this.#requireConfig();
@@ -615,7 +685,10 @@ var OpenAiCompatibleClient = class {
615
685
  body["tool_choice"] = "auto";
616
686
  }
617
687
  if (input.temperature !== void 0) body["temperature"] = input.temperature;
618
- if (stream) body["stream"] = true;
688
+ if (stream) {
689
+ body["stream"] = true;
690
+ body["stream_options"] = { include_usage: true };
691
+ }
619
692
  let res;
620
693
  try {
621
694
  res = await this.#fetch(`${baseUrl}/chat/completions`, {
@@ -665,9 +738,17 @@ var OpenAiCompatibleClient = class {
665
738
  };
666
739
  });
667
740
  const content = choice["content"];
741
+ const thinking = choice["reasoning_content"];
742
+ const usageRaw = data.usage;
743
+ const usage = usageRaw && (typeof usageRaw["prompt_tokens"] === "number" || typeof usageRaw["completion_tokens"] === "number") ? {
744
+ inputTokens: typeof usageRaw["prompt_tokens"] === "number" ? usageRaw["prompt_tokens"] : 0,
745
+ outputTokens: typeof usageRaw["completion_tokens"] === "number" ? usageRaw["completion_tokens"] : 0
746
+ } : void 0;
668
747
  return {
669
748
  content: typeof content === "string" && content !== "" ? textParts(content) : void 0,
670
749
  toolCalls: toolCalls?.length ? toolCalls : void 0,
750
+ ...typeof thinking === "string" && thinking !== "" ? { thinking } : {},
751
+ ...usage ? { usage } : {},
671
752
  raw: data
672
753
  };
673
754
  } catch (e) {
@@ -756,7 +837,7 @@ function toAnthropicMessages(messages) {
756
837
  const toAnthropicTools = (tools) => tools.map((tool) => ({
757
838
  name: tool.name,
758
839
  ...tool.description ? { description: tool.description } : {},
759
- input_schema: sanitizeForVendor(toPortableToolSchema(tool.inputSchema), ANTHROPIC_SCHEMA_PROFILE, tool.name)
840
+ input_schema: sanitizeForVendor(toPortableToolSchema(stripModelUnfillableParams(tool.inputSchema)), ANTHROPIC_SCHEMA_PROFILE, tool.name)
760
841
  }));
761
842
  /** Anthropic Messages API 客户端(零依赖 fetch;Node/浏览器通用) */
762
843
  var AnthropicClient = class {
@@ -795,6 +876,8 @@ var AnthropicClient = class {
795
876
  const decoder = new TextDecoder();
796
877
  const reader = res.body.getReader();
797
878
  const frames = createSseFrameReader();
879
+ let inputTokens;
880
+ let outputTokens;
798
881
  const handleFrame = function* (data) {
799
882
  let chunk;
800
883
  try {
@@ -804,6 +887,17 @@ var AnthropicClient = class {
804
887
  }
805
888
  const type = chunk["type"];
806
889
  if (type === "error") throw new WebSkillError("LLM_REQUEST_FAILED", `LLM stream error: ${chunk["error"]?.message ?? data}`);
890
+ if (type === "message_start") {
891
+ const usage = chunk["message"]?.["usage"];
892
+ if (typeof usage?.["input_tokens"] === "number") inputTokens = usage["input_tokens"];
893
+ if (typeof usage?.["output_tokens"] === "number") outputTokens = usage["output_tokens"];
894
+ return;
895
+ }
896
+ if (type === "message_delta") {
897
+ const usage = chunk["usage"];
898
+ if (typeof usage?.["output_tokens"] === "number") outputTokens = usage["output_tokens"];
899
+ return;
900
+ }
807
901
  if (type === "content_block_start") {
808
902
  const block = chunk["content_block"];
809
903
  if (block?.["type"] === "tool_use") {
@@ -826,6 +920,13 @@ var AnthropicClient = class {
826
920
  };
827
921
  return;
828
922
  }
923
+ if (delta?.["type"] === "thinking_delta" && typeof delta["thinking"] === "string" && delta["thinking"] !== "") {
924
+ yield {
925
+ type: "thinking-delta",
926
+ delta: delta["thinking"]
927
+ };
928
+ return;
929
+ }
829
930
  if (delta?.["type"] === "input_json_delta" && typeof delta["partial_json"] === "string") {
830
931
  const acc = toolCallsByIndex.get(index) ?? {
831
932
  id: "",
@@ -866,7 +967,14 @@ var AnthropicClient = class {
866
967
  };
867
968
  })
868
969
  };
869
- yield { type: "done" };
970
+ const usage = inputTokens !== void 0 || outputTokens !== void 0 ? {
971
+ inputTokens: inputTokens ?? 0,
972
+ outputTokens: outputTokens ?? 0
973
+ } : void 0;
974
+ yield {
975
+ type: "done",
976
+ ...usage ? { usage } : {}
977
+ };
870
978
  }
871
979
  async #post(input, stream) {
872
980
  validateLlmMessages(input.messages);
@@ -878,7 +986,12 @@ var AnthropicClient = class {
878
986
  };
879
987
  if (system !== void 0) body["system"] = system;
880
988
  if (input.tools?.length) body["tools"] = toAnthropicTools(input.tools);
881
- if (input.temperature !== void 0) body["temperature"] = input.temperature;
989
+ const thinkingBudget = this.#config.thinkingBudgetTokens;
990
+ if (thinkingBudget !== void 0 && Number.isInteger(thinkingBudget) && thinkingBudget > 0) body["thinking"] = {
991
+ type: "enabled",
992
+ budget_tokens: thinkingBudget
993
+ };
994
+ else if (input.temperature !== void 0) body["temperature"] = input.temperature;
882
995
  if (stream) body["stream"] = true;
883
996
  let res;
884
997
  try {
@@ -926,14 +1039,22 @@ var AnthropicClient = class {
926
1039
  const blocks = data.content;
927
1040
  if (!Array.isArray(blocks)) throw new Error("response has no content blocks");
928
1041
  const text = blocks.filter((b) => b["type"] === "text").map((b) => String(b["text"] ?? "")).join("");
1042
+ const thinking = blocks.filter((b) => b["type"] === "thinking").map((b) => String(b["thinking"] ?? "")).join("");
929
1043
  const toolCalls = blocks.filter((b) => b["type"] === "tool_use").map((b) => ({
930
1044
  id: typeof b["id"] === "string" ? b["id"] : "",
931
1045
  name: typeof b["name"] === "string" ? b["name"] : "",
932
1046
  arguments: typeof b["input"] === "object" && b["input"] !== null ? b["input"] : {}
933
1047
  }));
1048
+ const usageRaw = data.usage;
1049
+ const usage = typeof usageRaw?.["input_tokens"] === "number" || typeof usageRaw?.["output_tokens"] === "number" ? {
1050
+ inputTokens: typeof usageRaw["input_tokens"] === "number" ? usageRaw["input_tokens"] : 0,
1051
+ outputTokens: typeof usageRaw["output_tokens"] === "number" ? usageRaw["output_tokens"] : 0
1052
+ } : void 0;
934
1053
  return {
935
1054
  content: text === "" ? void 0 : textParts(text),
936
1055
  toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
1056
+ ...thinking === "" ? {} : { thinking },
1057
+ ...usage ? { usage } : {},
937
1058
  raw: data
938
1059
  };
939
1060
  } catch (e) {
@@ -942,6 +1063,18 @@ var AnthropicClient = class {
942
1063
  }
943
1064
  };
944
1065
  const errorMessage = (e) => e instanceof Error ? e.message : String(e);
1066
+ /** usageMetadata → LlmTokenUsage(promptTokenCount / candidatesTokenCount;无字段返回 undefined) */
1067
+ function parseGenAiUsage(data) {
1068
+ const usage = data?.usageMetadata;
1069
+ if (!usage) return void 0;
1070
+ const input = usage["promptTokenCount"];
1071
+ const output = usage["candidatesTokenCount"];
1072
+ if (typeof input !== "number" && typeof output !== "number") return void 0;
1073
+ return {
1074
+ inputTokens: typeof input === "number" ? input : 0,
1075
+ outputTokens: typeof output === "number" ? output : 0
1076
+ };
1077
+ }
945
1078
  /** parts → GenAI parts(二进制统一走 inlineData) */
946
1079
  const toGenAiParts = (parts, where) => parts.map((part) => {
947
1080
  switch (part.type) {
@@ -1015,7 +1148,7 @@ function toGenAiContents(messages) {
1015
1148
  const toGenAiTools = (tools) => [{ functionDeclarations: tools.map((tool) => ({
1016
1149
  name: tool.name,
1017
1150
  ...tool.description ? { description: tool.description } : {},
1018
- parameters: sanitizeForVendor(toPortableToolSchema(tool.inputSchema), GOOGLE_SCHEMA_PROFILE, tool.name)
1151
+ parameters: sanitizeForVendor(toPortableToolSchema(stripModelUnfillableParams(tool.inputSchema)), GOOGLE_SCHEMA_PROFILE, tool.name)
1019
1152
  })) }];
1020
1153
  /** Google GenAI(generateContent / streamGenerateContent)客户端(零依赖 fetch) */
1021
1154
  var GoogleGenAiClient = class {
@@ -1039,9 +1172,11 @@ var GoogleGenAiClient = class {
1039
1172
  const parts = this.#responseParts(data);
1040
1173
  const text = parts.filter((p) => typeof p["text"] === "string").map((p) => String(p["text"])).join("");
1041
1174
  const toolCalls = this.#functionCalls(parts);
1175
+ const usage = parseGenAiUsage(data);
1042
1176
  return {
1043
1177
  content: text === "" ? void 0 : textParts(text),
1044
1178
  toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
1179
+ ...usage ? { usage } : {},
1045
1180
  raw: data
1046
1181
  };
1047
1182
  }
@@ -1053,6 +1188,7 @@ var GoogleGenAiClient = class {
1053
1188
  const decoder = new TextDecoder();
1054
1189
  const reader = res.body.getReader();
1055
1190
  const frames = createSseFrameReader();
1191
+ let usage;
1056
1192
  const handleFrame = function* (data) {
1057
1193
  let chunk;
1058
1194
  try {
@@ -1060,6 +1196,7 @@ var GoogleGenAiClient = class {
1060
1196
  } catch (e) {
1061
1197
  throw new WebSkillError("LLM_REQUEST_FAILED", `Failed to parse LLM stream frame: ${errorMessage(e)}`, data);
1062
1198
  }
1199
+ usage = parseGenAiUsage(chunk) ?? usage;
1063
1200
  const parts = chunk.candidates?.[0]?.content?.parts;
1064
1201
  for (const part of parts ?? []) {
1065
1202
  if (typeof part["text"] === "string" && part["text"] !== "") {
@@ -1091,7 +1228,10 @@ var GoogleGenAiClient = class {
1091
1228
  type: "tool-calls",
1092
1229
  toolCalls
1093
1230
  };
1094
- yield { type: "done" };
1231
+ yield {
1232
+ type: "done",
1233
+ ...usage ? { usage } : {}
1234
+ };
1095
1235
  }
1096
1236
  async #post(input, stream) {
1097
1237
  const model = input.model ?? this.#config.model;
@@ -1152,6 +1292,17 @@ var GoogleGenAiClient = class {
1152
1292
  return out;
1153
1293
  }
1154
1294
  };
1295
+ /** v5 { inputTokens, outputTokens } 与 v4 { promptTokens, completionTokens } 两种形状都接 */
1296
+ function fromVercelUsage(raw) {
1297
+ const u = raw ?? {};
1298
+ const input = u["inputTokens"] ?? u["promptTokens"];
1299
+ const output = u["outputTokens"] ?? u["completionTokens"];
1300
+ if (typeof input !== "number" && typeof output !== "number") return void 0;
1301
+ return {
1302
+ inputTokens: typeof input === "number" ? input : 0,
1303
+ outputTokens: typeof output === "number" ? output : 0
1304
+ };
1305
+ }
1155
1306
  function toVercelToolSpecs(tools) {
1156
1307
  const out = {};
1157
1308
  for (const tool of tools) out[tool.name] = {
@@ -1160,6 +1311,16 @@ function toVercelToolSpecs(tools) {
1160
1311
  };
1161
1312
  return out;
1162
1313
  }
1314
+ /**
1315
+ * 归一化供应商思考内容:v5 的 `reasoningText`(字符串)与 v4 的 `reasoning`
1316
+ * (Array<{ text; type }>)都能落到同一条 `LlmResponse.thinking`。
1317
+ */
1318
+ function normalizeThinking(value) {
1319
+ if (typeof value === "string") return value !== "" ? value : void 0;
1320
+ if (!Array.isArray(value)) return void 0;
1321
+ const text = value.map((part) => typeof part?.text === "string" ? part.text : "").join("");
1322
+ return text !== "" ? text : void 0;
1323
+ }
1163
1324
  /** 接受 generateText 的返回值形状:{ text?, toolCalls?: [{ toolCallId, toolName, input|args }] } */
1164
1325
  function fromVercelResult(result) {
1165
1326
  const r = result;
@@ -1171,9 +1332,13 @@ function fromVercelResult(result) {
1171
1332
  arguments: typeof args === "object" && args !== null ? args : {}
1172
1333
  };
1173
1334
  });
1335
+ const thinking = normalizeThinking(r.reasoningText ?? r.reasoning);
1336
+ const usage = fromVercelUsage(r.usage);
1174
1337
  return {
1175
1338
  content: typeof r.text === "string" && r.text !== "" ? textParts(r.text) : void 0,
1176
1339
  toolCalls: toolCalls.length ? toolCalls : void 0,
1340
+ ...thinking !== void 0 ? { thinking } : {},
1341
+ ...usage ? { usage } : {},
1177
1342
  raw: result
1178
1343
  };
1179
1344
  }
@@ -1191,6 +1356,13 @@ function fromVercelStreamPart(part) {
1191
1356
  delta
1192
1357
  } : void 0;
1193
1358
  }
1359
+ case "reasoning-delta": {
1360
+ const delta = p["text"] ?? p["delta"];
1361
+ return typeof delta === "string" && delta !== "" ? {
1362
+ type: "thinking-delta",
1363
+ delta
1364
+ } : void 0;
1365
+ }
1194
1366
  case "tool-call": return {
1195
1367
  type: "tool-calls",
1196
1368
  toolCalls: [{
@@ -1199,7 +1371,13 @@ function fromVercelStreamPart(part) {
1199
1371
  arguments: typeof p["input"] === "object" && p["input"] !== null ? p["input"] : {}
1200
1372
  }]
1201
1373
  };
1202
- case "finish": return { type: "done" };
1374
+ case "finish": {
1375
+ const usage = fromVercelUsage(p["totalUsage"] ?? p["usage"]);
1376
+ return {
1377
+ type: "done",
1378
+ ...usage ? { usage } : {}
1379
+ };
1380
+ }
1203
1381
  default: return;
1204
1382
  }
1205
1383
  }
@@ -1803,7 +1981,7 @@ const DEFAULT_USER_PROFILE_LIMITS = {
1803
1981
  recordLimit: 500,
1804
1982
  valueMaxChars: 2e3,
1805
1983
  sampleLimit: 80,
1806
- injectMaxBytes: 2e3,
1984
+ injectMaxBytes: 4e3,
1807
1985
  entryLimit: 40
1808
1986
  };
1809
1987
  /** @experimental */
@@ -2053,8 +2231,8 @@ function extractSkillCandidate(data) {
2053
2231
  */
2054
2232
  const DEFAULT_LOOP_LIMITS = {
2055
2233
  maxTurns: 10,
2056
- totalTimeoutMs: 12e4,
2057
- toolTimeoutMs: 3e4
2234
+ totalTimeoutMs: 36e5,
2235
+ toolTimeoutMs: 6e5
2058
2236
  };
2059
2237
  const RUN_SNAPSHOT_SCHEMA_VERSION = 3;
2060
2238
  /** @experimental */
@@ -2294,7 +2472,7 @@ var AgentLoop = class {
2294
2472
  maxTurns: config.maxTurns ?? DEFAULT_LOOP_LIMITS.maxTurns,
2295
2473
  totalTimeoutMs: config.totalTimeoutMs ?? DEFAULT_LOOP_LIMITS.totalTimeoutMs,
2296
2474
  toolTimeoutMs: config.toolTimeoutMs ?? DEFAULT_LOOP_LIMITS.toolTimeoutMs,
2297
- toolResultMaxBytes: config.toolResultMaxBytes ?? 1e5,
2475
+ toolResultMaxBytes: config.toolResultMaxBytes ?? 256e3,
2298
2476
  paramHistoryLimit: config.paramHistoryLimit ?? 50,
2299
2477
  toolCallingDisabled: config.toolCallingDisabled ?? false,
2300
2478
  maxUnknownToolRetries: config.maxUnknownToolRetries ?? 2,
@@ -2357,6 +2535,7 @@ var AgentLoop = class {
2357
2535
  surfacePatchCount: 0,
2358
2536
  processedSurfaceActionNonces: /* @__PURE__ */ new Set(),
2359
2537
  emittedToolEvents: /* @__PURE__ */ new Set(),
2538
+ artifactPaths: /* @__PURE__ */ new Set(),
2360
2539
  unknownToolCalls: 0,
2361
2540
  startMs,
2362
2541
  pausedMs: 0,
@@ -2507,6 +2686,23 @@ var AgentLoop = class {
2507
2686
  const code = e instanceof WebSkillError && (e.code === "LLM_UNAVAILABLE" || e.code === "LLM_REQUEST_FAILED") ? e.code : "LLM_REQUEST_FAILED";
2508
2687
  return finish("failed", "llm-error", messageOf(e), code);
2509
2688
  }
2689
+ if (response.thinking !== void 0 && response.thinking !== "") {
2690
+ state.trace.record("llm.thinking", { data: {
2691
+ turn,
2692
+ text: response.thinking
2693
+ } });
2694
+ const bus = this.#deps.eventBus;
2695
+ if (!llm.stream && bus && bus.listenerCount() > 0) bus.emit({
2696
+ phase: "execute",
2697
+ runId: state.runId,
2698
+ sessionId: state.run.sessionId,
2699
+ ts: state.now(),
2700
+ data: {
2701
+ kind: "thinking-delta",
2702
+ delta: response.thinking
2703
+ }
2704
+ });
2705
+ }
2510
2706
  const responseText = partsToText(response.content);
2511
2707
  if (!llm.stream && responseText !== "") await this.#deps.uiBridge?.onTextDelta?.(state.runId, responseText);
2512
2708
  trace.record("llm.response", { data: {
@@ -2514,6 +2710,11 @@ var AgentLoop = class {
2514
2710
  hasToolCalls: Boolean(response.toolCalls?.length),
2515
2711
  contentLength: responseText.length
2516
2712
  } });
2713
+ if (response.usage) trace.record("llm.usage", { data: {
2714
+ turn,
2715
+ inputTokens: response.usage.inputTokens,
2716
+ outputTokens: response.usage.outputTokens
2717
+ } });
2517
2718
  if (!response.toolCalls?.length) {
2518
2719
  messages.push({
2519
2720
  role: "assistant",
@@ -2723,6 +2924,7 @@ var AgentLoop = class {
2723
2924
  surfacePatchCount: 0,
2724
2925
  processedSurfaceActionNonces: new Set(snapshot.processedSurfaceActionNonces ?? []),
2725
2926
  emittedToolEvents: /* @__PURE__ */ new Set(),
2927
+ artifactPaths: /* @__PURE__ */ new Set(),
2726
2928
  unknownToolCalls: 0,
2727
2929
  startMs,
2728
2930
  pausedMs: snapshot.pausedMs ?? 0,
@@ -2843,6 +3045,7 @@ var AgentLoop = class {
2843
3045
  /**
2844
3046
  * 流式 LLM 调用:text-delta 仅在 EventBus 有订阅者时发射 llm.delta 事件,
2845
3047
  * 并同步转发 uiBridge.onTextDelta;tool-calls/done 组装为 LlmResponse 走原有分支。
3048
+ * thinking-delta 同理累积成 `response.thinking`(每轮一段,UI-UX5 #32)。
2846
3049
  */
2847
3050
  async #completeStreaming(llm, state, input) {
2848
3051
  const emitDelta = (delta) => {
@@ -2859,18 +3062,41 @@ var AgentLoop = class {
2859
3062
  });
2860
3063
  this.#deps.uiBridge?.onTextDelta?.(state.runId, delta);
2861
3064
  };
3065
+ const emitThinkingDelta = (delta) => {
3066
+ const bus = this.#deps.eventBus;
3067
+ if (bus && bus.listenerCount() > 0) bus.emit({
3068
+ phase: "execute",
3069
+ runId: state.runId,
3070
+ sessionId: state.run.sessionId,
3071
+ ts: state.now(),
3072
+ data: {
3073
+ kind: "thinking-delta",
3074
+ delta
3075
+ }
3076
+ });
3077
+ };
2862
3078
  let content = "";
3079
+ let thinking = "";
2863
3080
  let doneContent;
3081
+ let usage;
2864
3082
  const toolCalls = [];
2865
3083
  for await (const event of llm.stream(input)) if (event.type === "text-delta") {
2866
3084
  content += event.delta;
2867
3085
  emitDelta(event.delta);
3086
+ } else if (event.type === "thinking-delta") {
3087
+ thinking += event.delta;
3088
+ emitThinkingDelta(event.delta);
2868
3089
  } else if (event.type === "tool-calls") toolCalls.push(...event.toolCalls);
2869
- else if (event.type === "done") doneContent = event.content;
3090
+ else if (event.type === "done") {
3091
+ doneContent = event.content;
3092
+ usage = event.usage ?? usage;
3093
+ }
2870
3094
  const text = doneContent ?? content;
2871
3095
  return {
2872
3096
  content: text === "" ? void 0 : textParts(text),
2873
- toolCalls: toolCalls.length > 0 ? toolCalls : void 0
3097
+ toolCalls: toolCalls.length > 0 ? toolCalls : void 0,
3098
+ ...thinking === "" ? {} : { thinking },
3099
+ ...usage ? { usage } : {}
2874
3100
  };
2875
3101
  }
2876
3102
  /** 生命周期接线:更新 phase、发事件、跑钩子 */
@@ -3097,10 +3323,13 @@ var AgentLoop = class {
3097
3323
  });
3098
3324
  this.#emitTool(state, "failed", call, result.error?.code);
3099
3325
  }
3100
- for (const artifact of result.artifacts ?? []) state.trace.record("artifact.created", { data: {
3101
- artifactId: artifact.id,
3102
- path: artifact.path
3103
- } });
3326
+ for (const artifact of result.artifacts ?? []) {
3327
+ state.artifactPaths.add(artifact.path);
3328
+ state.trace.record("artifact.created", { data: {
3329
+ artifactId: artifact.id,
3330
+ path: artifact.path
3331
+ } });
3332
+ }
3104
3333
  if (state.unknownToolCalls > this.#config.maxUnknownToolRetries) throw new RunTerminated({
3105
3334
  status: "failed",
3106
3335
  reason: "tool-resolution-exhausted",
@@ -3116,7 +3345,12 @@ var AgentLoop = class {
3116
3345
  state.trace.record("run.warning", { message: "UiBridge does not support renderSurface; UI surface was not rendered" });
3117
3346
  return;
3118
3347
  }
3119
- const attributed = this.#attributeSurfaceEvent(state, event);
3348
+ let attributed = this.#attributeSurfaceEvent(state, event);
3349
+ if (attributed.type === "open") {
3350
+ const kept = await this.#stripDuplicateFileLinks(state, attributed);
3351
+ if (kept === void 0) return;
3352
+ attributed = kept;
3353
+ }
3120
3354
  if (attributed.type === "patch") this.#consumeSurfacePatchBudget(state);
3121
3355
  await bridge.renderSurface(attributed);
3122
3356
  state.surfaceEvents.push(structuredClone(attributed));
@@ -3159,6 +3393,44 @@ var AgentLoop = class {
3159
3393
  }))
3160
3394
  };
3161
3395
  }
3396
+ /**
3397
+ * 剥掉指向「本 run 已写出 artifact」的 FileLink 节点(UI-UX5 #5):
3398
+ * 宿主在 run 完成时会把每个 artifact 自动渲染成下载卡(`buildRenderResult`),
3399
+ * 模型/技能再建一张就是重复。整棵树剥空返回 undefined(放弃这次 open);
3400
+ * 有剥离就记一条 run.warning,让「少了一张卡」在轨迹里可查。
3401
+ */
3402
+ async #stripDuplicateFileLinks(state, event) {
3403
+ if (state.artifactPaths.size === 0) {
3404
+ const listed = await this.#deps.artifactStore.listArtifacts(state.runId).catch(() => []);
3405
+ for (const artifact of listed) state.artifactPaths.add(artifact.path);
3406
+ }
3407
+ if (state.artifactPaths.size === 0) return event;
3408
+ const paths = state.artifactPaths;
3409
+ let stripped = 0;
3410
+ const walk = (node) => {
3411
+ if (node.component === "FileLink") {
3412
+ const path = node.props?.["path"];
3413
+ if (typeof path === "string" && paths.has(path)) {
3414
+ stripped += 1;
3415
+ return;
3416
+ }
3417
+ }
3418
+ if (!node.children || node.children.length === 0) return node;
3419
+ const children = node.children.map(walk).filter((child) => child !== void 0);
3420
+ if (children.length === node.children.length) return node;
3421
+ return {
3422
+ ...node,
3423
+ children
3424
+ };
3425
+ };
3426
+ const node = walk(event.node);
3427
+ if (stripped === 0) return event;
3428
+ state.trace.record("run.warning", { message: `Dropped ${stripped} FileLink node(s) duplicating auto-rendered artifact download card(s)` });
3429
+ return node === void 0 ? void 0 : {
3430
+ ...event,
3431
+ node
3432
+ };
3433
+ }
3162
3434
  /** Awaits the single action emitted with the most recently persisted tool result. */
3163
3435
  async #drainSurfaceAction(state) {
3164
3436
  const request = state.pendingSurfaceAction;
@@ -3437,7 +3709,7 @@ var AgentLoop = class {
3437
3709
  }))];
3438
3710
  }
3439
3711
  /**
3440
- * 工具结果回喂序列化:超过 toolResultMaxBytes(默认 100KB)时头尾保留截断,
3712
+ * 工具结果回喂序列化:超过 toolResultMaxBytes(默认 256KB)时头尾保留截断,
3441
3713
  * 完整内容经 artifactStore 落 artifact,回喂摘要含 artifact id。
3442
3714
  */
3443
3715
  async #serializeToolResult(call, result, state) {
@@ -4930,6 +5202,38 @@ var CapabilityApproval = class CapabilityApproval {
4930
5202
  return "allowed";
4931
5203
  }
4932
5204
  };
5205
+ /**
5206
+ * 从 run 的 trace 聚合大模型用量(请求次数 + 输入/输出 token)。
5207
+ * 与 `summarizeToolCalls` 同型:消费方不再各自遍历 trace。
5208
+ * @stable
5209
+ */
5210
+ function summarizeRunUsage(trace) {
5211
+ let llmCalls = 0;
5212
+ let inputTokens = 0;
5213
+ let outputTokens = 0;
5214
+ let hasUsage = false;
5215
+ for (const event of trace) {
5216
+ if (event.type === "llm.request") {
5217
+ llmCalls += 1;
5218
+ continue;
5219
+ }
5220
+ if (event.type !== "llm.usage") continue;
5221
+ const input = event.data?.["inputTokens"];
5222
+ const output = event.data?.["outputTokens"];
5223
+ const hasInput = typeof input === "number" && Number.isFinite(input);
5224
+ const hasOutput = typeof output === "number" && Number.isFinite(output);
5225
+ if (hasInput) inputTokens += input;
5226
+ if (hasOutput) outputTokens += output;
5227
+ if (hasInput || hasOutput) hasUsage = true;
5228
+ }
5229
+ return {
5230
+ llmCalls,
5231
+ ...hasUsage ? {
5232
+ inputTokens,
5233
+ outputTokens
5234
+ } : {}
5235
+ };
5236
+ }
4933
5237
  const RUN_TRACE_SCHEMA_VERSION = 1;
4934
5238
  /** 终止原因:取最后一条 run.completed/cancelled/failed 事件的 data.reason */
4935
5239
  function extractEndReason(events) {
@@ -4944,6 +5248,7 @@ function extractEndReason(events) {
4944
5248
  function summarize(trace) {
4945
5249
  const endReason = extractEndReason(trace.events);
4946
5250
  const durationMs = trace.endedAt === void 0 ? void 0 : Date.parse(trace.endedAt) - Date.parse(trace.startedAt);
5251
+ const runUsage = summarizeRunUsage(trace.events);
4947
5252
  return {
4948
5253
  runId: trace.runId,
4949
5254
  startedAt: trace.startedAt,
@@ -4954,7 +5259,11 @@ function summarize(trace) {
4954
5259
  ...trace.sessionId !== void 0 ? { sessionId: trace.sessionId } : {},
4955
5260
  ...trace.endedAt !== void 0 ? { endedAt: trace.endedAt } : {},
4956
5261
  ...endReason !== void 0 ? { endReason } : {},
4957
- ...durationMs !== void 0 && Number.isFinite(durationMs) && durationMs >= 0 ? { durationMs } : {}
5262
+ ...durationMs !== void 0 && Number.isFinite(durationMs) && durationMs >= 0 ? { durationMs } : {},
5263
+ ...runUsage.inputTokens !== void 0 ? { usage: {
5264
+ inputTokens: runUsage.inputTokens,
5265
+ outputTokens: runUsage.outputTokens ?? 0
5266
+ } } : {}
4958
5267
  };
4959
5268
  }
4960
5269
  function parseTraceFile(raw, path) {
@@ -5147,6 +5456,12 @@ function applyFilter(summaries, filter) {
5147
5456
  * @stable
5148
5457
  */
5149
5458
  function summarizeToolCalls(run) {
5459
+ const startedAtByCallId = /* @__PURE__ */ new Map();
5460
+ for (const event of run.trace) {
5461
+ if (event.type !== "tool.started") continue;
5462
+ const callId = event.data?.["callId"];
5463
+ if (typeof callId === "string" && !startedAtByCallId.has(callId)) startedAtByCallId.set(callId, event.ts);
5464
+ }
5150
5465
  const calls = [];
5151
5466
  for (const event of run.trace) {
5152
5467
  if (event.type !== "tool.completed" && event.type !== "tool.failed") continue;
@@ -5156,6 +5471,7 @@ function summarizeToolCalls(run) {
5156
5471
  const args = event.data?.["args"];
5157
5472
  const durationMs = event.data?.["durationMs"];
5158
5473
  const errorCode = event.data?.["code"];
5474
+ const startedAt = startedAtByCallId.get(callId);
5159
5475
  calls.push({
5160
5476
  callId,
5161
5477
  name,
@@ -5163,6 +5479,7 @@ function summarizeToolCalls(run) {
5163
5479
  ...typeof args === "string" ? { args } : {},
5164
5480
  ...typeof durationMs === "number" ? { durationMs } : {},
5165
5481
  ...typeof errorCode === "string" ? { errorCode } : {},
5482
+ ...startedAt !== void 0 ? { startedAt } : {},
5166
5483
  ...event.type === "tool.failed" && typeof event.message === "string" ? { errorMessage: event.message } : {}
5167
5484
  });
5168
5485
  }
@@ -5386,4 +5703,4 @@ var FsSessionStore = class {
5386
5703
  };
5387
5704
 
5388
5705
  //#endregion
5389
- export { fromVercelStreamPart as $, SerializingMemoryStore as A, bridgeError as B, ProgressiveRouter as C, sealToolCallPairs as Ct, RUN_SNAPSHOT_SCHEMA_VERSION as D, toVercelToolSpecs as Dt, READ_SKILL_FILE_TOOL_NAME as E, toRecordDigests as Et, USER_PROFILE_PROMPT_HEADER as F, exportUserProfile as G, createScriptContext as H, USER_PROFILE_REFINE_PROMPT as I, extractTodoTraceEvents as J, extractChartSpec as K, WebSkillRuntime as L, USER_PROFILE_EXPORT_VERSION as M, USER_PROFILE_KEY as N, RUN_TRACE_SCHEMA_VERSION as O, validateUiSpecEvent as Ot, USER_PROFILE_NO_INVENTION_RULE as P, fromVercelResult as Q, appendBehaviorRecords as R, OpenAiCompatibleClient as S, scriptToolName as St, READ_SKILL_FILE_TOOL as T, toLlmToolSpec as Tt, createWebSkillApi as U, buildRenderResult as V, diffUserProfile as W, findUnpairedToolCalls as X, extractUiSpecEvents as Y, formatSkillScriptManifest as Z, FsRunTraceStore as _, renderUserProfileContext as _t, AgentLoop as a, mergeProfileEntries as at, GoogleGenAiClient as b, schemaSourceLabel as bt, CapabilityApproval as c, normalizeErrorCode as ct, EMPTY_USER_PROFILE as d, parseBridgeRequest as dt, interruptedToolResult as et, EventBus as f, parseUserProfileExport as ft, FsRunSnapshotStore as g, refineUserProfile as gt, FsMemoryStore as h, readUserProfile as ht, ASK_USER_TOOL_NAME as i, mergeCatalogEntries as it, TraceRecorder as j, SESSION_SCHEMA_VERSION as k, validateUiSpecNode as kt, DEFAULT_LOOP_LIMITS as l, normalizeToolContent as lt, FsArtifactStore as m, readProfileEntries as mt, ASK_USER_INPUT_SCHEMA as n, isUnsupportedRunSnapshot as nt, AnthropicClient as o, networkPolicyLibSource as ot, FS_SESSION_PAGE_SIZE as p, readBehaviorRecords as pt, extractSkillCandidate as q, ASK_USER_TOOL as r, listSkillScripts as rt, BEHAVIOR_RECORDS_KEY as s, networkUrlHost as st, ALLOWED_TOOLS_EXCLUSION_REASON as t, isNetworkAllowed as tt, DEFAULT_USER_PROFILE_LIMITS as u, normalizeToolError as ut, FsSessionStore as v, resolveToolName as vt, READ_SKILL_FILE_INPUT_SCHEMA as w, summarizeToolCalls as wt, HookRunner as x, schemaToForm as xt, FullDisclosureRouter as y, sampleBehaviorRecords as yt, applyUserProfileImport as z };
5706
+ export { fromVercelStreamPart as $, SerializingMemoryStore as A, validateUiSpecNode as At, bridgeError as B, ProgressiveRouter as C, sealToolCallPairs as Ct, RUN_SNAPSHOT_SCHEMA_VERSION as D, toRecordDigests as Dt, READ_SKILL_FILE_TOOL_NAME as E, toLlmToolSpec as Et, USER_PROFILE_PROMPT_HEADER as F, exportUserProfile as G, createScriptContext as H, USER_PROFILE_REFINE_PROMPT as I, extractTodoTraceEvents as J, extractChartSpec as K, WebSkillRuntime as L, USER_PROFILE_EXPORT_VERSION as M, USER_PROFILE_KEY as N, RUN_TRACE_SCHEMA_VERSION as O, toVercelToolSpecs as Ot, USER_PROFILE_NO_INVENTION_RULE as P, fromVercelResult as Q, appendBehaviorRecords as R, OpenAiCompatibleClient as S, scriptToolName as St, READ_SKILL_FILE_TOOL as T, summarizeToolCalls as Tt, createWebSkillApi as U, buildRenderResult as V, diffUserProfile as W, findUnpairedToolCalls as X, extractUiSpecEvents as Y, formatSkillScriptManifest as Z, FsRunTraceStore as _, renderUserProfileContext as _t, AgentLoop as a, mergeProfileEntries as at, GoogleGenAiClient as b, schemaSourceLabel as bt, CapabilityApproval as c, normalizeErrorCode as ct, EMPTY_USER_PROFILE as d, parseBridgeRequest as dt, interruptedToolResult as et, EventBus as f, parseUserProfileExport as ft, FsRunSnapshotStore as g, refineUserProfile as gt, FsMemoryStore as h, readUserProfile as ht, ASK_USER_TOOL_NAME as i, mergeCatalogEntries as it, TraceRecorder as j, SESSION_SCHEMA_VERSION as k, validateUiSpecEvent as kt, DEFAULT_LOOP_LIMITS as l, normalizeToolContent as lt, FsArtifactStore as m, readProfileEntries as mt, ASK_USER_INPUT_SCHEMA as n, isUnsupportedRunSnapshot as nt, AnthropicClient as o, networkPolicyLibSource as ot, FS_SESSION_PAGE_SIZE as p, readBehaviorRecords as pt, extractSkillCandidate as q, ASK_USER_TOOL as r, listSkillScripts as rt, BEHAVIOR_RECORDS_KEY as s, networkUrlHost as st, ALLOWED_TOOLS_EXCLUSION_REASON as t, isNetworkAllowed as tt, DEFAULT_USER_PROFILE_LIMITS as u, normalizeToolError as ut, FsSessionStore as v, resolveToolName as vt, READ_SKILL_FILE_INPUT_SCHEMA as w, summarizeRunUsage as wt, HookRunner as x, schemaToForm as xt, FullDisclosureRouter as y, sampleBehaviorRecords as yt, applyUserProfileImport as z };