@honor-claw/yoyo 2026.6.9-beta.1 → 2026.6.9-beta.2

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 (61) hide show
  1. package/dist/apis/claw-cloud.mjs +19 -0
  2. package/dist/capabilities/cloud-invoke/index.mjs +1 -0
  3. package/dist/capabilities/cloud-invoke/invoke.mjs +43 -0
  4. package/dist/capabilities/node/invoke.mjs +1 -1
  5. package/dist/capabilities/routing/model-switch.mjs +1 -1
  6. package/dist/cloud-channel/dispatcher/impl.mjs +4 -7
  7. package/dist/cloud-channel/handlers/context/handler.mjs +1 -1
  8. package/dist/cloud-channel/log-summary.mjs +3 -3
  9. package/dist/core/prompt/builder.mjs +13 -8
  10. package/dist/core/prompt/cloud-tool.mjs +7 -0
  11. package/dist/messaging/dispatchers/command/impl.mjs +25 -33
  12. package/dist/messaging/dispatchers/stream/controller.mjs +18 -25
  13. package/dist/messaging/dispatchers/stream/error.mjs +221 -25
  14. package/dist/messaging/dispatchers/stream/resolvers.mjs +18 -14
  15. package/dist/messaging/dispatchers/stream/session.mjs +57 -79
  16. package/dist/messaging/inbound/agent.mjs +3 -1
  17. package/dist/messaging/inbound/command.mjs +4 -1
  18. package/dist/messaging/inbound/context.mjs +25 -19
  19. package/dist/messaging/inbound/dispatch.mjs +5 -2
  20. package/dist/messaging/inbound/interrupt.mjs +2 -2
  21. package/dist/messaging/inbound/new-session.mjs +2 -2
  22. package/dist/messaging/inbound/user-message.mjs +2 -2
  23. package/dist/messaging/send/frame.mjs +7 -10
  24. package/dist/modules/configs/plugin-init.mjs +5 -1
  25. package/dist/provisioning/toolset/artifacts.mjs +29 -31
  26. package/dist/provisioning/toolset/cleanup.mjs +17 -16
  27. package/dist/provisioning/toolset/consts.mjs +2 -2
  28. package/dist/provisioning/toolset/md5-index.mjs +30 -46
  29. package/dist/provisioning/toolset/normalize.mjs +3 -5
  30. package/dist/provisioning/toolset/persist.mjs +23 -39
  31. package/dist/provisioning/toolset/skill-inject.mjs +1 -1
  32. package/dist/provisioning/toolset/versioned-store.mjs +45 -0
  33. package/dist/tools/cloud-invoke/index.mjs +1 -0
  34. package/dist/tools/cloud-invoke/tool.mjs +48 -0
  35. package/dist/tools/index.mjs +7 -5
  36. package/openclaw.plugin.json +1 -1
  37. package/package.json +1 -1
  38. package/skills/yoyo-phone-control/SKILL.md +12 -8
  39. package/skills/yoyo-phone-control/configs/sub-skills.json +14 -1
  40. package/skills/yoyo-phone-control/references/alarm-create.md +356 -0
  41. package/skills/yoyo-phone-control/references/alarm-delete.md +301 -0
  42. package/skills/yoyo-phone-control/references/alarm-disable.md +309 -0
  43. package/skills/yoyo-phone-control/references/alarm-enable.md +309 -0
  44. package/skills/yoyo-phone-control/references/alarm-query.md +411 -0
  45. package/skills/yoyo-phone-control/references/alarm-update.md +386 -0
  46. package/skills/yoyo-phone-control/references/file-upload.md +0 -3
  47. package/skills/yoyo-phone-control/references/gui-task-create.md +0 -3
  48. package/skills/yoyo-phone-control/references/gui-task-pause.md +0 -3
  49. package/skills/yoyo-phone-control/references/gui-task-terminate.md +0 -3
  50. package/skills/yoyo-phone-control/references/local-search.md +0 -3
  51. package/skills/yoyo-phone-control/references/local_user_data_qa.md +0 -3
  52. package/skills/yoyo-phone-control/references/local_user_file_search.md +0 -3
  53. package/skills/yoyo-phone-control/references/schedule-create.md +483 -0
  54. package/skills/yoyo-phone-control/references/schedule-delete.md +507 -0
  55. package/skills/yoyo-phone-control/references/schedule-search.md +591 -0
  56. package/skills/yoyo-phone-control/references/schedule-update.md +556 -0
  57. package/skills/yoyo-phone-control/references/task-result-query.md +0 -3
  58. package/skills/yoyo-smart-home/SKILL.md +78 -0
  59. package/skills/yoyo-smart-home/mcptools/device_control.json +136 -0
  60. package/skills/yoyo-smart-home/mcptools/device_query.json +114 -0
  61. package/skills/yoyo-smart-home/mcptools/skill_exit.json +6 -0
@@ -69,6 +69,25 @@ var o = class {
69
69
  timeout: r?.timeoutMs ?? 3e4
70
70
  });
71
71
  }
72
+ async invokeCloudTool(e, n, r) {
73
+ let i = {
74
+ "x-trace-id": t(),
75
+ "x-jwt-token": n.token
76
+ }, a = {
77
+ pluginService: { serviceId: r.serviceId },
78
+ pluginParams: r.pluginParams,
79
+ device: {
80
+ deviceId: e.deviceId,
81
+ role: "yoyoclaw",
82
+ port: e.port
83
+ }
84
+ };
85
+ return this.httpClient.post("/icsplugin/execute", {
86
+ headers: i,
87
+ body: a,
88
+ timeout: r?.timeoutMs ?? 3e4
89
+ });
90
+ }
72
91
  async exchangeToken(e, r) {
73
92
  let i = t(), o = {
74
93
  "Content-Type": "application/json",
@@ -0,0 +1 @@
1
+ import "./invoke.mjs";
@@ -0,0 +1,43 @@
1
+ import { toErrorMessage as e } from "../../utils/error.mjs";
2
+ import { clawLogger as t } from "../../utils/claw-logger.mjs";
3
+ import { HonorAccount as n } from "../../honor-auth/vault/impl.mjs";
4
+ import { createClawCloudClient as r } from "../../apis/claw-cloud.mjs";
5
+ import { loadDeviceInfo as i } from "../../modules/device/device-info.mjs";
6
+ import "../../modules/device/index.mjs";
7
+ import "../../honor-auth/vault/index.mjs";
8
+ import "../../apis/index.mjs";
9
+ import { ToolError as a } from "../../tools/error.mjs";
10
+ //#region src/capabilities/cloud-invoke/invoke.ts
11
+ var o = t("capabilities");
12
+ async function s(t) {
13
+ let s = await n.fromUser().current();
14
+ if (!s?.token || !s.userId) throw o.error("cloud invoke skipped: no current user"), new a("unauthorized", "missing current user token");
15
+ let c;
16
+ try {
17
+ c = await i();
18
+ } catch (e) {
19
+ throw o.error("cloud invoke failed to get device info", e), new a("ctx missing", "failed to get device info", { cause: e });
20
+ }
21
+ try {
22
+ let e = await r().invokeCloudTool(c, s, {
23
+ serviceId: t.toolId,
24
+ pluginParams: t.params ?? {},
25
+ ...t.timeoutMs === void 0 ? {} : { timeoutMs: t.timeoutMs }
26
+ }), n = e.data, i = e.status >= 200 && e.status < 300, l = n?.code === "0", u = n?.code === "ICS-500";
27
+ if (!i || !l && !u) throw o.error("cloud invoke response not ok", null, {
28
+ status: e.status,
29
+ code: n?.code,
30
+ cnMessage: n?.cnMessage,
31
+ cpErrorCode: n?.data?.cpErrorCode
32
+ }), new a("api_failed", `code=${n?.code ?? "-"} cpErrorCode=${n?.data?.cpErrorCode ?? "-"} message=${n?.cnMessage ?? "-"}`);
33
+ return {
34
+ ...n.data === void 0 ? {} : { pluginResponse: n.data },
35
+ code: e.data.code,
36
+ cnMessage: e.data.cnMessage
37
+ };
38
+ } catch (t) {
39
+ throw t instanceof a ? t : (o.error("cloud invoke failed", t), new a("network_error", e(t), { cause: t }));
40
+ }
41
+ }
42
+ //#endregion
43
+ export { s as invokeCloudToolService };
@@ -12,7 +12,7 @@ async function a(e) {
12
12
  toolCallId: e.toolCallId,
13
13
  nodeId: e.nodeId,
14
14
  name: e.name,
15
- params: e.params
15
+ ...e.params ? { params: { arguments: JSON.stringify(e.params) } } : {}
16
16
  } }
17
17
  }, a = n();
18
18
  return r.forAccount(a).request(i, {
@@ -14,7 +14,7 @@ async function s(e) {
14
14
  senderId: e.deviceId,
15
15
  chatId: s,
16
16
  accountId: e.accountId,
17
- traceId: e.traceId,
17
+ traceInfo: e.traceInfo,
18
18
  content: `/model ${e.provider}/${e.model}`,
19
19
  resources: [],
20
20
  silent: !0
@@ -11,10 +11,10 @@ function s(e) {
11
11
  let a = e.replyTo, l = !!a, u = l && a ? a.from : e.to;
12
12
  if (!u) return o.warn("missing 'to' and no replyTo", { msgType: e.msgType }), !1;
13
13
  if (l && a && !a.payload.traceInfo) return o.warn("replyTo missing traceInfo", { msgType: e.msgType }), !1;
14
- let d = e.traceInfo ?? (l && a ? a.payload.traceInfo : {
15
- traceId: n(),
14
+ let d = {
15
+ ...e.traceInfo ?? (l && a ? a.payload.traceInfo : { traceId: n() }),
16
16
  timestamp: Date.now()
17
- }), { deviceId: f, port: p } = await r(), m = i(t("yoyoclaw", f, p), u, e.msgType, d, e.data, e.bizExtInfo);
17
+ }, { deviceId: f, port: p } = await r(), m = i(t("yoyoclaw", f, p), u, e.msgType, d, e.data, e.bizExtInfo);
18
18
  return c.send(s.serialize(m), e.silent);
19
19
  };
20
20
  return {
@@ -23,10 +23,7 @@ function s(e) {
23
23
  let { matchResult: r, timeoutMs: i } = t, s = n();
24
24
  if (!await u({
25
25
  ...e,
26
- traceInfo: {
27
- traceId: s,
28
- timestamp: Date.now()
29
- }
26
+ traceInfo: { traceId: s }
30
27
  })) throw Error("send failed");
31
28
  return new Promise((e, t) => {
32
29
  let n = setTimeout(() => {
@@ -42,7 +42,7 @@ async function f(e, n) {
42
42
  deviceId: n.from.deviceId,
43
43
  provider: r,
44
44
  model: a,
45
- traceId: n.payload.traceInfo.traceId
45
+ traceInfo: n.payload.traceInfo
46
46
  });
47
47
  return {
48
48
  ok: !0,
@@ -2,13 +2,13 @@
2
2
  function e(e) {
3
3
  let { payload: t, data: n, from: r } = e, i = {
4
4
  msgType: t.msgType,
5
- traceId: t.traceInfo.traceId,
6
- from: r.role
5
+ from: r.role,
6
+ ...t.traceInfo
7
7
  };
8
8
  switch (t.msgType) {
9
9
  case "agentReply": {
10
10
  let e = n?.agentMessage;
11
- e && (i.period = e.period, i.messageId = e.id, e.turnId && (i.turnId = e.turnId), e.isFinish && (i.isFinish = e.isFinish));
11
+ e && (i.period = e.period, i.messageId = e.id, e.isFinish && (i.isFinish = e.isFinish));
12
12
  break;
13
13
  }
14
14
  case "nodeInvokeRequest": {
@@ -1,19 +1,24 @@
1
1
  import { resolveAgentPromptContribution as e } from "./agent.mjs";
2
- import { resolveSkillPromptContribution as t } from "./skill.mjs";
2
+ import { resolveCloudToolPromptContribution as t } from "./cloud-tool.mjs";
3
+ import { resolveSkillPromptContribution as n } from "./skill.mjs";
3
4
  //#region src/core/prompt/builder.ts
4
- function n(e) {
5
+ function r(e) {
5
6
  let t = e.filter((e) => !!e);
6
7
  return t.length > 0 ? t.join("\n\n") : void 0;
7
8
  }
8
- function r(e) {
9
- let t = n(e.map((e) => e.prependSystemContext)), r = n(e.map((e) => e.prependContext));
9
+ function i(e) {
10
+ let t = r(e.map((e) => e.prependSystemContext)), n = r(e.map((e) => e.prependContext));
10
11
  return {
11
12
  ...t ? { prependSystemContext: t } : {},
12
- ...r ? { prependContext: r } : {}
13
+ ...n ? { prependContext: n } : {}
13
14
  };
14
15
  }
15
- async function i() {
16
- return r([e(), await t()]);
16
+ async function a() {
17
+ return i([
18
+ e(),
19
+ t(),
20
+ await n()
21
+ ]);
17
22
  }
18
23
  //#endregion
19
- export { i as resolvePromptBuildContribution };
24
+ export { a as resolvePromptBuildContribution };
@@ -0,0 +1,7 @@
1
+ //#region src/core/prompt/cloud-tool.ts
2
+ var e = "## Skill 使用云工具调用规则\n\n当已读取的 SKILL.md frontmatter 包含 allowed-tools 声明时:\n\n1. 根据用户意图从 allowed-tools 选择工具。\n2. 调用前必须读取当前 skill 目录下对应的 mcptools/<name>.json。\n3. 从 JSON 的 id 获取 toolId,按 inputSchema 提取 params。\n4. 调用 cloud_invoke,传入 { toolId, params }。\n\n不得猜测 toolId,不得使用未在 allowed-tools 中声明的工具。\n明确属于 yoyo-phone-control 等设备控制 Skill(走 node_invoke 通道)的工具,不得通过 cloud_invoke 调用。";
3
+ function t() {
4
+ return { prependSystemContext: e };
5
+ }
6
+ //#endregion
7
+ export { t as resolveCloudToolPromptContribution };
@@ -1,54 +1,46 @@
1
1
  import { clawLogger as e } from "../../../utils/claw-logger.mjs";
2
- import { classifyAndFormatModelError as t } from "../stream/error.mjs";
3
- import { createStreamSession as n, finishStreamSession as r, pushFinalVisibleText as i, pushStreamDelta as a } from "../stream/session.mjs";
2
+ import { captureErrorPayload as t } from "../stream/error.mjs";
3
+ import { createStreamSession as n, finishStreamSession as r, pushStreamDelta as i } from "../stream/session.mjs";
4
4
  //#region src/messaging/dispatchers/command/impl.ts
5
- var o = e("dispatcher");
6
- function s(e) {
7
- let s = n(e);
5
+ var a = e("dispatcher");
6
+ function o(e) {
7
+ let o = n(e), s = !1;
8
8
  return {
9
9
  dispatcherOptions: {
10
10
  deliver: async (e, n) => {
11
- let r = t(e);
12
- if (r) {
13
- o.warn("model api error", {
14
- sender: s.target.deviceId,
15
- turnId: s.turnId,
16
- kind: r.kind,
17
- rawTextLength: r.rawText.length
18
- }), await a(s, r.userMessage);
19
- return;
20
- }
21
- let c = e.text ?? "";
22
- if (c) {
23
- if (n.kind === "final") {
24
- await i(s, c);
25
- return;
26
- }
27
- s.hasPushedAnswerText || await i(s, c);
28
- }
11
+ if (a.info("command reply deliver received", {
12
+ sender: o.target.deviceId,
13
+ turnId: o.traceInfo.turnId,
14
+ payload: e,
15
+ info: n
16
+ }), t(o, e)) return;
17
+ let r = e.text ?? "";
18
+ if (!r) return;
19
+ let c = s ? `\n${r}` : r;
20
+ s = !0, await i(o, c);
29
21
  },
30
22
  onSkip: (e, t) => {
31
- t.reason !== "silent" && o.debug("command reply skipped", {
32
- sender: s.target.deviceId,
33
- turnId: s.turnId,
23
+ t.reason !== "silent" && a.debug("command reply skipped", {
24
+ sender: o.target.deviceId,
25
+ turnId: o.traceInfo.turnId,
34
26
  reason: t.reason
35
27
  });
36
28
  },
37
29
  onError: (e, t) => {
38
- o.warn("command reply dispatcher error", {
39
- sender: s.target.deviceId,
40
- turnId: s.turnId,
30
+ a.warn("command reply dispatcher error", {
31
+ sender: o.target.deviceId,
32
+ turnId: o.traceInfo.turnId,
41
33
  kind: t.kind,
42
34
  error: e
43
35
  });
44
36
  },
45
37
  onIdle: async () => {
46
- await r(s);
38
+ await r(o);
47
39
  }
48
40
  },
49
- replyOptions: { abortSignal: s.abortController.signal },
50
- session: s
41
+ replyOptions: { abortSignal: o.abortController.signal },
42
+ session: o
51
43
  };
52
44
  }
53
45
  //#endregion
54
- export { s as createCommandDispatcher };
46
+ export { o as createCommandDispatcher };
@@ -1,16 +1,16 @@
1
1
  import { clawLogger as e } from "../../../utils/claw-logger.mjs";
2
- import { classifyAndFormatModelError as t } from "./error.mjs";
2
+ import { captureErrorPayload as t } from "./error.mjs";
3
3
  import { resolveAnswerPartialDelta as n, resolveThinkingDelta as r } from "./resolvers.mjs";
4
4
  import { getToolUseTraceSteps as i } from "./tool/trace-store.mjs";
5
- import { finishStreamSession as a, finishThinking as o, pushFinalVisibleText as s, pushStreamDelta as c, pushThinkingDelta as l, pushToolEvent as u, resetAnswerSnapshot as d } from "./session.mjs";
6
- import { buildToolResultEvent as f, buildToolStartEvent as p } from "./tool/event-builder.mjs";
5
+ import { finishStreamSession as a, finishThinking as o, pushFinalVisibleText as s, pushStreamDelta as c, pushThinkingDelta as l, pushToolEvent as u } from "./session.mjs";
6
+ import { buildToolResultEvent as d, buildToolStartEvent as f } from "./tool/event-builder.mjs";
7
7
  import "./tool/index.mjs";
8
8
  //#region src/messaging/dispatchers/stream/controller.ts
9
- var m = e("dispatcher");
10
- function h(e, t) {
9
+ var p = e("dispatcher");
10
+ function m(e, t) {
11
11
  return e ?? `no-id:${t}`;
12
12
  }
13
- var g = class {
13
+ var h = class {
14
14
  session;
15
15
  includeThinking;
16
16
  includeToolCalls;
@@ -25,8 +25,8 @@ var g = class {
25
25
  }
26
26
  emitToolStart(e) {
27
27
  if (!this.includeToolCalls || !e.name) return;
28
- let t = h(e.toolCallId, e.name);
29
- this.emittedToolStartKeys.has(t) || (this.emittedToolStartKeys.add(t), u(this.session, p(e)), this.pendingToolKeys.add(t), m.debug("tool start emitted", {
28
+ let t = m(e.toolCallId, e.name);
29
+ this.emittedToolStartKeys.has(t) || (this.emittedToolStartKeys.add(t), u(this.session, f(e)), this.pendingToolKeys.add(t), p.debug("tool start emitted", {
30
30
  sessionKey: this.session.sessionKey,
31
31
  toolName: e.name,
32
32
  hasToolCallId: !!e.toolCallId,
@@ -34,7 +34,7 @@ var g = class {
34
34
  }));
35
35
  }
36
36
  emitToolResult(e) {
37
- this.includeToolCalls && (u(this.session, f(e)), this.pendingToolKeys.delete(h(e.toolCallId, e.toolName)), this.pendingToolKeys.size === 0 && (d(this.session), this.flushPendingReplyPayloads()));
37
+ this.includeToolCalls && (u(this.session, d(e)), this.pendingToolKeys.delete(m(e.toolCallId, e.toolName)), this.pendingToolKeys.size === 0 && this.flushPendingReplyPayloads());
38
38
  }
39
39
  onToolStart = (e) => {
40
40
  e.phase && e.phase !== "start" || e.name && this.emitToolStart({
@@ -87,24 +87,17 @@ var g = class {
87
87
  this.includeThinking && o(this.session);
88
88
  };
89
89
  deliver = async (e, n) => {
90
- if (n.kind === "tool") return;
91
- let r = t(e);
92
- if (r) {
93
- m.warn("model api error", {
94
- sender: this.session.target.deviceId,
95
- turnId: this.session.turnId,
96
- kind: r.kind,
97
- rawTextLength: r.rawText.length
98
- }), await c(this.session, r.userMessage);
99
- return;
100
- }
101
- let i = e.text ?? "";
102
- (n.kind === "final" || !this.session.hasPushedAnswerText) && await s(this.session, i);
90
+ p.info("user message reply deliver received", {
91
+ sender: this.session.target.deviceId,
92
+ turnId: this.session.traceInfo.turnId,
93
+ payload: e,
94
+ info: n
95
+ }), n.kind !== "tool" && (t(this.session, e) || n.kind === "final" && await s(this.session, e.text ?? ""));
103
96
  };
104
97
  onError = (e) => {
105
- m.warn("reply dispatcher error", {
98
+ p.warn("reply dispatcher error", {
106
99
  sender: this.session.target.deviceId,
107
- turnId: this.session.turnId,
100
+ turnId: this.session.traceInfo.turnId,
108
101
  error: e instanceof Error ? e.message : String(e)
109
102
  });
110
103
  };
@@ -132,4 +125,4 @@ var g = class {
132
125
  }
133
126
  };
134
127
  //#endregion
135
- export { g as StreamingController };
128
+ export { h as StreamingController };
@@ -1,56 +1,252 @@
1
+ import { clawLogger as e } from "../../../utils/claw-logger.mjs";
2
+ import { isReplyPayloadNonTerminalToolErrorWarning as t } from "openclaw/plugin-sdk/reply-payload";
1
3
  //#region src/messaging/dispatchers/stream/error.ts
2
- var e = {
3
- context_overflow: "当前会话内容过长,请使用 /new 开启新会话。",
4
- auth: "模型 API 凭证失效,请联系管理员。",
4
+ var n = e("dispatcher"), r = new Set([
5
+ "delivery_error",
6
+ "tool_error",
7
+ "no_visible_reply",
8
+ "runtime_error"
9
+ ]), i = {
10
+ context_overflow: "当前会话内容过长,请使用 /reset 开启新会话。",
11
+ auth: "模型服务认证失败,请检查模型凭证配置。",
5
12
  model_not_found: "当前模型不可用,请切换模型后重试。",
6
- billing: "模型服务余额不足,请处理后重试。",
13
+ billing: "模型服务额度不足,请检查账户状态。",
7
14
  rate_limit: "请求过于频繁,请稍候再试。",
8
15
  overloaded: "模型服务繁忙,请稍候再试。",
16
+ network: "模型服务连接异常,请检查网络后重试。",
9
17
  timeout: "模型响应超时,请稍候重试。",
10
- unknown: "模型响应失败,请稍候重试。"
11
- }, t = [
18
+ server_error: "模型服务暂时异常,请稍候重试。",
19
+ format: "模型服务无法处理当前请求,请调整请求或切换模型后重试。",
20
+ conversation_state: "当前会话状态异常,请重试或使用 /reset 重置会话。",
21
+ tool_error: "工具执行失败,请调整操作后重试。",
22
+ delivery_error: "回复已生成,但消息发送失败,请重试。",
23
+ no_visible_reply: "任务已完成,但没有生成可展示的回复,请重试。",
24
+ runtime_error: "请求处理异常,请稍候重试。"
25
+ }, a = [
12
26
  {
13
- kind: "context_overflow",
14
- test: /context (length|window)|too (many tokens|large|long)/i
27
+ kind: "delivery_error",
28
+ patterns: [/generated a reply but could not deliver it/i, /could not deliver .* to this chat/i]
15
29
  },
16
30
  {
17
- kind: "auth",
18
- test: /unauthori[sz]ed|forbidden|invalid api key|authentication/i
31
+ kind: "no_visible_reply",
32
+ patterns: [
33
+ /did not produce a visible reply/i,
34
+ /produced no visible reply/i,
35
+ /completion agent did not produce a visible reply/i
36
+ ]
37
+ },
38
+ {
39
+ kind: "conversation_state",
40
+ patterns: [
41
+ /provider rejected the conversation state/i,
42
+ /roles must alternate/i,
43
+ /incorrect role information/i,
44
+ /invalid_replay_transcript/i,
45
+ /session history looks corrupted/i,
46
+ /message ordering conflict/i
47
+ ]
48
+ },
49
+ {
50
+ kind: "context_overflow",
51
+ patterns: [
52
+ /context (?:length|window).*(?:exceed|overflow|limit|too (?:large|long))/i,
53
+ /maximum context length/i,
54
+ /context[_ ]window[_ ]exceeded/i,
55
+ /context overflow/i,
56
+ /prompt (?:is )?too long/i,
57
+ /request_too_large/i,
58
+ /request (?:size )?exceeds?.*(?:context|maximum size)/i,
59
+ /exceeds? (?:the )?model(?:'s)? maximum context/i,
60
+ /model token limit/i,
61
+ /上下文(?:过长|超出|长度超)/,
62
+ /超出最大上下文/
63
+ ]
19
64
  },
20
65
  {
21
66
  kind: "model_not_found",
22
- test: /model (not found|does not exist|unavailable)/i
67
+ patterns: [
68
+ /model .* not found/i,
69
+ /model .* does not exist/i,
70
+ /no such model/i,
71
+ /configured model is unavailable/i,
72
+ /model .* (?:renamed|retired)/i
73
+ ]
23
74
  },
24
75
  {
25
76
  kind: "billing",
26
- test: /billing|payment|required quota|insufficient quota|credits?/i
77
+ patterns: [
78
+ /\b402\b/,
79
+ /payment required/i,
80
+ /billing error/i,
81
+ /insufficient (?:credits?|balance|quota)/i,
82
+ /credit balance/i,
83
+ /spend(?:ing)? limit/i,
84
+ /run out of credits/i
85
+ ]
27
86
  },
28
87
  {
29
88
  kind: "rate_limit",
30
- test: /rate limit|too many requests|quota exceeded|tpm|rpm/i
89
+ patterns: [
90
+ /\b429\b/,
91
+ /rate[_ -]?limit/i,
92
+ /too many (?:concurrent )?requests/i,
93
+ /quota exceeded/i,
94
+ /resource[_ ]exhausted/i,
95
+ /throttl/i,
96
+ /\b(?:tpm|rpm)\b/i,
97
+ /tokens per minute/i
98
+ ]
31
99
  },
32
100
  {
33
101
  kind: "overloaded",
34
- test: /overloaded|high demand|capacity|temporarily unavailable/i
102
+ patterns: [
103
+ /overloaded(?:_error)?/i,
104
+ /model .* at capacity/i,
105
+ /high demand/i,
106
+ /high load/i
107
+ ]
108
+ },
109
+ {
110
+ kind: "auth",
111
+ patterns: [
112
+ /\b401\b/,
113
+ /\b403\b/,
114
+ /unauthori[sz]ed/i,
115
+ /forbidden/i,
116
+ /incorrect api key/i,
117
+ /invalid[_ ]?api[_ ]?key/i,
118
+ /invalid token/i,
119
+ /authentication failed/i,
120
+ /authentication refresh failed/i,
121
+ /token has expired/i,
122
+ /oauth .* (?:expired|failed)/i,
123
+ /missing api key/i,
124
+ /no api key found/i,
125
+ /missing the required .* scopes/i
126
+ ]
127
+ },
128
+ {
129
+ kind: "runtime_error",
130
+ patterns: [
131
+ /cli .* timed out/i,
132
+ /app-server .* closed/i,
133
+ /auto-compaction could not recover/i,
134
+ /something went wrong while processing your request/i,
135
+ /authentication refresh is already in progress/i,
136
+ /browser oauth did not complete/i,
137
+ /no space left on device/i,
138
+ /disk (?:is )?full/i,
139
+ /\benospc\b/i,
140
+ /^llm request failed\.?$/i,
141
+ /llm request failed with an unknown error/i
142
+ ]
143
+ },
144
+ {
145
+ kind: "network",
146
+ patterns: [
147
+ /network(?: connection)? error/i,
148
+ /network connection was interrupted/i,
149
+ /network request failed/i,
150
+ /connection refused/i,
151
+ /connection reset/i,
152
+ /connection aborted/i,
153
+ /socket hang up/i,
154
+ /fetch failed/i,
155
+ /dns lookup/i,
156
+ /provider endpoint is unreachable/i,
157
+ /proxy or tunnel configuration blocked/i,
158
+ /\beconn(?:refused|reset|aborted)\b/i,
159
+ /\benet(?:unreach|reset)\b/i,
160
+ /\behost(?:unreach|down)\b/i,
161
+ /\benotfound\b/i,
162
+ /\beai_again\b/i,
163
+ /\bepipe\b/i,
164
+ /\bund_err_/i
165
+ ]
35
166
  },
36
167
  {
37
168
  kind: "timeout",
38
- test: /timeout|timed out|etimedout|econnreset|socket hang up/i
169
+ patterns: [
170
+ /timed out/i,
171
+ /\btimeout\b/i,
172
+ /deadline exceeded/i,
173
+ /\betimedout\b/i,
174
+ /\besockettimedout\b/i
175
+ ]
176
+ },
177
+ {
178
+ kind: "server_error",
179
+ patterns: [
180
+ /internal server error/i,
181
+ /provider returned .* internal error/i,
182
+ /ai service returned an internal error/i,
183
+ /\bserver_error\b/i,
184
+ /\binternal_error\b/i,
185
+ /bad gateway/i,
186
+ /upstream error/i,
187
+ /service temporarily unavailable/i,
188
+ /provider returned an html error page/i,
189
+ /\b50[0234]\b/
190
+ ]
191
+ },
192
+ {
193
+ kind: "format",
194
+ patterns: [
195
+ /provider rejected the request schema or tool payload/i,
196
+ /invalid request format/i,
197
+ /invalid_request/i,
198
+ /tool call id .* must be/i,
199
+ /tool_use\.id/i,
200
+ /conversation must end with a user message/i,
201
+ /does not support assistant message prefill/i,
202
+ /invalid streaming response/i,
203
+ /unexpected event order/i,
204
+ /malformed streaming fragment/i
205
+ ]
206
+ },
207
+ {
208
+ kind: "tool_error",
209
+ patterns: [
210
+ /^\s*⚠️\s*(?:🛠️\s*)?.*\b(?:tool|exec|command)\b.*\b(?:failed|error)\b/i,
211
+ /\btool (?:execution )?(?:failed|error)\b/i,
212
+ /\b(?:exec|command) failed\b/i
213
+ ]
39
214
  }
40
215
  ];
41
- function n(t, n) {
216
+ function o(e, t) {
42
217
  return {
43
- kind: t,
44
- rawText: n,
45
- userMessage: e[t]
218
+ kind: e,
219
+ rawText: t,
220
+ userMessage: e === "unknown" ? t : i[e]
46
221
  };
47
222
  }
48
- function r(e) {
223
+ function s(e) {
224
+ for (let { kind: t, patterns: n } of a) if (n.some((t) => t.test(e))) return t;
225
+ return "unknown";
226
+ }
227
+ function c(e) {
49
228
  if (e.isError !== !0) return null;
50
- let r = (e.text ?? "").trim();
51
- if (!r) return n("unknown", r);
52
- for (let { kind: e, test: i } of t) if (i.test(r)) return n(e, r);
53
- return n("unknown", r);
229
+ if (t(e)) return n.warn("error payload discarded", {
230
+ kind: "tool_error",
231
+ payload: e
232
+ }), null;
233
+ let i = e.text?.trim();
234
+ if (!i) return n.warn("error payload without text discarded", { payload: e }), null;
235
+ let a = s(i);
236
+ if (r.has(a)) return n.warn("error payload discarded", {
237
+ kind: a,
238
+ payload: e
239
+ }), null;
240
+ let c = o(a, i);
241
+ return n.error("reply error payload detected", i, {
242
+ kind: a,
243
+ payload: e
244
+ }), c;
245
+ }
246
+ function l(e, t) {
247
+ if (t.isError !== !0) return !1;
248
+ let n = c(t);
249
+ return n && (e.error = n), !0;
54
250
  }
55
251
  //#endregion
56
- export { r as classifyAndFormatModelError };
252
+ export { l as captureErrorPayload };
@@ -1,20 +1,24 @@
1
1
  //#region src/messaging/dispatchers/stream/resolvers.ts
2
2
  function e(e, t) {
3
- if (t.delta) return typeof t.text == "string" ? (e.answerSnapshot = t.text, e.latestAnswerSnapshot = t.text) : (e.answerSnapshot += t.delta, e.latestAnswerSnapshot = e.answerSnapshot), t.delta;
4
- if (typeof t.text != "string" || t.text.length === 0) return "";
5
- if (t.replace || !t.text.startsWith(e.answerSnapshot)) return e.latestAnswerSnapshot = t.text, "";
6
- let n = t.text.slice(e.answerSnapshot.length);
7
- return e.answerSnapshot = t.text, e.latestAnswerSnapshot = t.text, n;
3
+ return t.length < e.length || !t.startsWith(e);
8
4
  }
9
- function t(e, t) {
10
- let n = t.text ?? "";
11
- if (!n) return "";
12
- if (t.isReasoningSnapshot) {
13
- if (!n.startsWith(e.thinkingSnapshot)) return e.thinkingSnapshot = n, "";
14
- let t = n.slice(e.thinkingSnapshot.length);
15
- return e.thinkingSnapshot = n, t;
5
+ function t(t, n) {
6
+ if (n.delta) return typeof n.text == "string" ? t.answerSnapshot = n.text : t.answerSnapshot += n.delta, n.delta;
7
+ if (typeof n.text != "string" || n.text.length === 0) return "";
8
+ if (n.replace) return t.answerSnapshot = n.text, "";
9
+ if (e(t.answerSnapshot, n.text)) return t.answerSnapshot = n.text, n.text;
10
+ let r = n.text.slice(t.answerSnapshot.length);
11
+ return t.answerSnapshot = n.text, r;
12
+ }
13
+ function n(t, n) {
14
+ let r = n.text ?? "";
15
+ if (!r) return "";
16
+ if (n.isReasoningSnapshot) {
17
+ if (e(t.thinkingSnapshot, r)) return t.thinkingSnapshot = r, r;
18
+ let n = r.slice(t.thinkingSnapshot.length);
19
+ return t.thinkingSnapshot = r, n;
16
20
  }
17
- return e.thinkingSnapshot += n, n;
21
+ return t.thinkingSnapshot += r, r;
18
22
  }
19
23
  //#endregion
20
- export { e as resolveAnswerPartialDelta, t as resolveThinkingDelta };
24
+ export { t as resolveAnswerPartialDelta, n as resolveThinkingDelta };