@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.
- package/dist/env/agent/agent-component.d.ts +33 -0
- package/dist/env/agent/agent-component.js +4 -3
- package/dist/env/agent/index.js +4 -3
- package/dist/env/agent/types.d.ts +17 -0
- package/dist/env/error-reply.d.ts +53 -1
- package/dist/env/error-reply.js +8 -1
- package/dist/env/event-source/event-source-handlers.js +3 -2
- package/dist/env/event-source/index.js +4 -3
- package/dist/env/index.js +14 -13
- package/dist/env/llm/adapter-pi-ai.d.ts +47 -0
- package/dist/env/llm/index.js +3 -2
- package/dist/env/llm/model-fallback.d.ts +54 -0
- package/dist/env/llm/redact.d.ts +39 -0
- package/dist/env/llm/types.d.ts +13 -0
- package/dist/env/session/index.js +5 -4
- package/dist/env/session/storage/index.js +4 -3
- package/dist/env/task/delegate/delegate-tool.d.ts +27 -1
- package/dist/env/task/delegate/delegate-tool.js +1 -1
- package/dist/env/task/delegate/index.js +1 -1
- package/dist/env/task/index.js +2 -2
- package/dist/env/tool/types.d.ts +13 -0
- package/dist/env/workflow/index.js +7 -6
- package/dist/env/workflow/tools/index.js +6 -5
- package/dist/index.js +15 -14
- package/dist/shared/@ai-setting/{roy-agent-core-9qgrc9dy.js → roy-agent-core-03k5drfp.js} +54 -14
- package/dist/shared/@ai-setting/{roy-agent-core-2veqhrxa.js → roy-agent-core-1dnsk6ht.js} +2 -2
- package/dist/shared/@ai-setting/{roy-agent-core-vvb4cyyy.js → roy-agent-core-2cw72f16.js} +7 -2
- package/dist/shared/@ai-setting/{roy-agent-core-cqpd41gf.js → roy-agent-core-5hq4v41q.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-fr296a53.js → roy-agent-core-60f7h284.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-gz2jnaan.js → roy-agent-core-b4zdm2n4.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-48h4zh60.js → roy-agent-core-bm3gav5d.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-h3fwjbhp.js → roy-agent-core-ebws32tv.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-5bj0xfjk.js → roy-agent-core-g23yp3t1.js} +298 -34
- package/dist/shared/@ai-setting/{roy-agent-core-w2h6xt6k.js → roy-agent-core-g6pw4esq.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-fqandv0a.js → roy-agent-core-gnt23yx0.js} +21 -11
- package/dist/shared/@ai-setting/roy-agent-core-ntn32q7j.js +72 -0
- package/dist/shared/@ai-setting/{roy-agent-core-x1d6edkh.js → roy-agent-core-rfhxj8v2.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-nmn853z0.js → roy-agent-core-t6nx0rsz.js} +1 -1
- package/dist/shared/@ai-setting/{roy-agent-core-9nvyffxg.js → roy-agent-core-va4m04e8.js} +117 -7
- 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
|
-
|
|
218
|
-
|
|
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 };
|