@ai-setting/roy-agent-core 1.7.62 → 1.7.63

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 (40) hide show
  1. package/dist/env/agent/agent-component.d.ts +33 -0
  2. package/dist/env/agent/agent-component.js +4 -3
  3. package/dist/env/agent/index.js +4 -3
  4. package/dist/env/agent/types.d.ts +17 -0
  5. package/dist/env/error-reply.d.ts +53 -1
  6. package/dist/env/error-reply.js +8 -1
  7. package/dist/env/event-source/event-source-handlers.js +3 -2
  8. package/dist/env/event-source/index.js +4 -3
  9. package/dist/env/index.js +14 -13
  10. package/dist/env/llm/adapter-pi-ai.d.ts +47 -0
  11. package/dist/env/llm/index.js +3 -2
  12. package/dist/env/llm/model-fallback.d.ts +54 -0
  13. package/dist/env/llm/redact.d.ts +39 -0
  14. package/dist/env/llm/types.d.ts +13 -0
  15. package/dist/env/session/index.js +5 -4
  16. package/dist/env/session/storage/index.js +4 -3
  17. package/dist/env/task/delegate/delegate-tool.d.ts +27 -1
  18. package/dist/env/task/delegate/delegate-tool.js +1 -1
  19. package/dist/env/task/delegate/index.js +1 -1
  20. package/dist/env/task/index.js +2 -2
  21. package/dist/env/tool/types.d.ts +13 -0
  22. package/dist/env/workflow/index.js +7 -6
  23. package/dist/env/workflow/tools/index.js +6 -5
  24. package/dist/index.js +15 -14
  25. package/dist/shared/@ai-setting/{roy-agent-core-9qgrc9dy.js → roy-agent-core-03k5drfp.js} +54 -14
  26. package/dist/shared/@ai-setting/{roy-agent-core-2veqhrxa.js → roy-agent-core-1dnsk6ht.js} +2 -2
  27. package/dist/shared/@ai-setting/{roy-agent-core-vvb4cyyy.js → roy-agent-core-2cw72f16.js} +7 -2
  28. package/dist/shared/@ai-setting/{roy-agent-core-cqpd41gf.js → roy-agent-core-5hq4v41q.js} +1 -1
  29. package/dist/shared/@ai-setting/{roy-agent-core-fr296a53.js → roy-agent-core-60f7h284.js} +1 -1
  30. package/dist/shared/@ai-setting/{roy-agent-core-gz2jnaan.js → roy-agent-core-b4zdm2n4.js} +1 -1
  31. package/dist/shared/@ai-setting/{roy-agent-core-48h4zh60.js → roy-agent-core-bm3gav5d.js} +1 -1
  32. package/dist/shared/@ai-setting/{roy-agent-core-h3fwjbhp.js → roy-agent-core-ebws32tv.js} +1 -1
  33. package/dist/shared/@ai-setting/{roy-agent-core-5bj0xfjk.js → roy-agent-core-g23yp3t1.js} +298 -34
  34. package/dist/shared/@ai-setting/{roy-agent-core-w2h6xt6k.js → roy-agent-core-g6pw4esq.js} +1 -1
  35. package/dist/shared/@ai-setting/{roy-agent-core-fqandv0a.js → roy-agent-core-gnt23yx0.js} +21 -11
  36. package/dist/shared/@ai-setting/roy-agent-core-ntn32q7j.js +72 -0
  37. package/dist/shared/@ai-setting/{roy-agent-core-x1d6edkh.js → roy-agent-core-rfhxj8v2.js} +1 -1
  38. package/dist/shared/@ai-setting/{roy-agent-core-nmn853z0.js → roy-agent-core-t6nx0rsz.js} +1 -1
  39. package/dist/shared/@ai-setting/{roy-agent-core-9nvyffxg.js → roy-agent-core-va4m04e8.js} +117 -7
  40. package/package.json +1 -1
@@ -1,3 +1,6 @@
1
+ import {
2
+ redactSecrets
3
+ } from "./roy-agent-core-ntn32q7j.js";
1
4
  import {
2
5
  normalizeLarkAtMentions
3
6
  } from "./roy-agent-core-m880qz3y.js";
@@ -24,6 +27,15 @@ var UPSTREAM_RETRY_PATTERNS = [
24
27
  /network error/i,
25
28
  /overloaded/i
26
29
  ];
30
+ var QUOTA_EXHAUSTED_PATTERNS = [
31
+ /free usage limit (reached|exceeded)/i,
32
+ /free (model )?(usage|quota).{0,20}(limit|exhaust)/i,
33
+ /usage limit (reached|exceeded)/i,
34
+ /quota (exceeded|exhausted|reached)/i,
35
+ /insufficient[_ ]?(quota|balance|credit)/i,
36
+ /(credit|balance) (is )?(exhausted|insufficient)/i,
37
+ /billing (hard )?limit/i
38
+ ];
27
39
  var TIMEOUT_PATTERNS = [
28
40
  /timeout/i,
29
41
  /timed out/i,
@@ -98,6 +110,69 @@ function collectErrorText(error, depth = 0) {
98
110
  return parts.join(`
99
111
  `);
100
112
  }
113
+ function extractRetryAfterSeconds(error, depth = 0) {
114
+ if (!error || typeof error !== "object" || depth > 6)
115
+ return;
116
+ const e = error;
117
+ const candidates = [
118
+ e.retryAfter,
119
+ e.retry_after,
120
+ e.retryAfterSeconds,
121
+ e.headers?.["retry-after"],
122
+ e.headers?.["Retry-After"],
123
+ e.responseHeaders?.["retry-after"],
124
+ e.responseHeaders?.["Retry-After"],
125
+ e.headers?.get?.("retry-after"),
126
+ e.data?.error?.retry_after,
127
+ e.data?.error?.retryAfter
128
+ ];
129
+ for (const raw of candidates) {
130
+ const seconds = toSeconds(raw);
131
+ if (seconds !== undefined)
132
+ return seconds;
133
+ }
134
+ const nested = [e.lastError, e.cause];
135
+ if (Array.isArray(e.errors))
136
+ nested.push(...e.errors.slice(-2));
137
+ for (const inner of nested) {
138
+ const seconds = extractRetryAfterSeconds(inner, depth + 1);
139
+ if (seconds !== undefined)
140
+ return seconds;
141
+ }
142
+ return;
143
+ }
144
+ function toSeconds(raw) {
145
+ if (typeof raw === "number" && Number.isFinite(raw) && raw >= 0)
146
+ return raw;
147
+ if (typeof raw !== "string")
148
+ return;
149
+ const trimmed = raw.trim();
150
+ if (!trimmed)
151
+ return;
152
+ const asNumber = Number(trimmed);
153
+ if (Number.isFinite(asNumber) && asNumber >= 0)
154
+ return asNumber;
155
+ const asDate = Date.parse(trimmed);
156
+ if (!Number.isNaN(asDate)) {
157
+ const delta = Math.max(0, asDate - Date.now());
158
+ return Math.round(delta / 1000);
159
+ }
160
+ return;
161
+ }
162
+ function humanizeRetryAfter(seconds) {
163
+ if (seconds === undefined || !Number.isFinite(seconds) || seconds < 0)
164
+ return;
165
+ if (seconds < 90)
166
+ return "约 1 分钟内";
167
+ const minutes = seconds / 60;
168
+ if (minutes < 90)
169
+ return `约 ${Math.round(minutes)} 分钟后`;
170
+ const hours = minutes / 60;
171
+ if (hours < 36)
172
+ return `约 ${Math.round(hours)} 小时后`;
173
+ const days = hours / 24;
174
+ return `约 ${Math.round(days)} 天后`;
175
+ }
101
176
  function truncate(text, max) {
102
177
  if (text.length <= max)
103
178
  return text;
@@ -134,6 +209,17 @@ var FAILURE_RULES = [
134
209
  reason: "本次执行等待响应超时(上游长时间未返回或网络卡住)。建议稍后重试,或把任务拆小一些。",
135
210
  retryable: true
136
211
  },
212
+ {
213
+ id: "quota_exhausted",
214
+ kind: "quota_exhausted",
215
+ names: ["FreeUsageLimitError"],
216
+ patterns: QUOTA_EXHAUSTED_PATTERNS,
217
+ notify: true,
218
+ title: "模型额度已用尽",
219
+ reason: "本次调用被上游拒绝:该模型的额度(或免费额度)已经用完。这不是你的操作问题," + "也不是仓库代码的问题 —— 重发同一个模型不会恢复,需要换模型或等额度重置。",
220
+ retryable: false,
221
+ suggestion: "换一个模型(例如 `--model <provider>/<付费模型>`),或等额度重置后再试。"
222
+ },
137
223
  {
138
224
  id: "upstream_retry",
139
225
  kind: "upstream_retry",
@@ -191,16 +277,20 @@ function getFailureRuleIds() {
191
277
  function classifyReactFailure(error) {
192
278
  const text = collectErrorText(error);
193
279
  const name = error && typeof error === "object" ? String(error.name ?? "") : "";
194
- const technical = text ? truncate(text.replace(/\s*\n\s*/g, " | "), 400) : undefined;
280
+ const technical = text ? truncate(redactSecrets(text.replace(/\s*\n\s*/g, " | ")), 400) : undefined;
195
281
  const rule = FAILURE_RULES.find((r) => ruleMatches(r, name, text)) ?? UNKNOWN_RULE;
282
+ const retryAfterSeconds = rule.kind === "quota_exhausted" ? extractRetryAfterSeconds(error) : undefined;
283
+ const window = humanizeRetryAfter(retryAfterSeconds);
196
284
  return {
197
285
  kind: rule.kind,
198
286
  ruleId: rule.id,
199
287
  title: rule.title,
200
- reason: rule.reason,
288
+ reason: window ? `${rule.reason}上游提示:额度${window}恢复。` : rule.reason,
201
289
  retryable: rule.retryable,
202
290
  notify: rule.notify,
203
- technical
291
+ technical,
292
+ ...retryAfterSeconds !== undefined ? { retryAfterSeconds } : {},
293
+ ...rule.suggestion ? { suggestion: rule.suggestion } : {}
204
294
  };
205
295
  }
206
296
  var MAX_QUERY_PREVIEW = 200;
@@ -214,11 +304,12 @@ function buildFailureReplyMarkdown(info, opts) {
214
304
  lines.push("");
215
305
  lines.push(`> 原始请求:${truncate(query.replace(/\s+/g, " "), MAX_QUERY_PREVIEW)}`);
216
306
  }
217
- if (info.retryable) {
218
- lines.push("");
307
+ lines.push("");
308
+ if (info.suggestion) {
309
+ lines.push(`**你可以:** ${info.suggestion}`);
310
+ } else if (info.retryable) {
219
311
  lines.push("**你可以:** 直接再发一次(重发即可,无需额外操作)。");
220
312
  } else {
221
- lines.push("");
222
313
  lines.push("**你可以:** 新开一个会话,或先让我压缩当前会话。");
223
314
  }
224
315
  const technical = info.technical;
@@ -229,6 +320,25 @@ function buildFailureReplyMarkdown(info, opts) {
229
320
  return lines.join(`
230
321
  `);
231
322
  }
323
+ function errorName(error) {
324
+ if (!error || typeof error !== "object")
325
+ return "";
326
+ const n = error.name;
327
+ return typeof n === "string" ? n : "";
328
+ }
329
+ function formatCliFailureLine(error) {
330
+ const info = classifyReactFailure(error);
331
+ if (info.kind === "quota_exhausted") {
332
+ const window = humanizeRetryAfter(info.retryAfterSeconds);
333
+ const head = `${info.title}(${window ? window.replace(/^约 /, "约 ") + "恢复" : "恢复时间未知"})`;
334
+ const advice = info.suggestion ? ` 建议:${info.suggestion}` : "";
335
+ return `${head} —— 重发同一模型无效。${advice}`.trim();
336
+ }
337
+ const segments = (info.technical ?? "").split("|").map((seg) => seg.trim()).filter((seg) => seg.length > 0 && seg.toLowerCase() !== (errorName(error) || "").toLowerCase());
338
+ const informative = segments.find((seg) => /\d/.test(seg)) ?? [...segments].sort((a, b) => b.length - a.length)[0] ?? "";
339
+ const summary = informative.slice(0, 200);
340
+ return summary ? `${info.title}:${summary}` : info.title;
341
+ }
232
342
  function extractReplyChannelFromEvent(envEvent) {
233
343
  if (!envEvent || typeof envEvent !== "object")
234
344
  return;
@@ -411,4 +521,4 @@ async function notifyReactFailure(options) {
411
521
  }
412
522
  }
413
523
 
414
- export { getFailureRuleIds, classifyReactFailure, buildFailureReplyMarkdown, __resetFailureReplyDedupForTest, notifyReactFailure };
524
+ export { extractRetryAfterSeconds, humanizeRetryAfter, getFailureRuleIds, classifyReactFailure, buildFailureReplyMarkdown, formatCliFailureLine, __resetFailureReplyDedupForTest, notifyReactFailure };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-setting/roy-agent-core",
3
- "version": "1.7.62",
3
+ "version": "1.7.63",
4
4
  "type": "module",
5
5
  "description": "Core SDK for roy-agent - Environment, Components, Tools, Sessions, Tasks",
6
6
  "main": "./dist/index.js",