nolo-cli 0.16.0-alpha.12 → 0.16.0-alpha.14
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/{_executeModel-LGHYA5XS.js → _executeModel-UU2JO5OB.js} +16 -15
- package/{agentDeleteCommand-PBIUC4FT.js → agentDeleteCommand-L6JRXPYK.js} +10 -10
- package/{agentEmailCommands-KC2QCPQV.js → agentEmailCommands-FE3GY3T5.js} +19 -18
- package/{agentListCommands-N64PHBXM.js → agentListCommands-ZWSAIC4W.js} +11 -11
- package/{agentMachineCommands-P7S5WAVA.js → agentMachineCommands-VWQ2GZBY.js} +10 -10
- package/{agentRecordCommands-JKZR2TZJ.js → agentRecordCommands-PYVZMRZM.js} +19 -18
- package/{agentRunCommand-2ELKCBWR.js → agentRunCommand-3ADJ2J5U.js} +24 -20
- package/{agentRunControl-6ADXVYMR.js → agentRunControl-YVLQ4BW5.js} +24 -1
- package/{agentRuntimeLocal-T6YECTNF.js → agentRuntimeLocal-LXTR6SAU.js} +7 -7
- package/{agentSlice-NXLMDKR7.js → agentSlice-TI6ECUGN.js} +1 -1
- package/{appDeleteCommands-D6B6Z4ZQ.js → appDeleteCommands-QIS37SXE.js} +11 -11
- package/{appDeployCommands-YMO5FK4T.js → appDeployCommands-WBHB7T5B.js} +11 -11
- package/{appDeployStatusCommands-EO5DWWPQ.js → appDeployStatusCommands-A3OUV6GO.js} +11 -11
- package/{appGetCommands-6SMZ3URQ.js → appGetCommands-LCVYIH63.js} +11 -11
- package/{appListCommands-RZXSWR2G.js → appListCommands-PC7QOBUO.js} +11 -11
- package/{chunk-4LXOVZ4W.js → chunk-2OK7P5XF.js} +54 -13
- package/{chunk-MSA4JAOZ.js → chunk-2ZLEOGS5.js} +1 -1
- package/{chunk-KKY4B2Q2.js → chunk-4PWB7JRR.js} +4 -1
- package/{chunk-VHXXRWNL.js → chunk-5QJFYG2N.js} +15 -5
- package/{chunk-F3UOACU4.js → chunk-64IEIMN4.js} +1 -1
- package/{chunk-XEWUC53Z.js → chunk-6IGLIDDE.js} +21 -9
- package/{chunk-AS3ZQ3O2.js → chunk-7OBMZCRD.js} +1 -1
- package/{chunk-QLUFR47U.js → chunk-AL2V7U3E.js} +1 -1
- package/{chunk-22NGXGN3.js → chunk-BOBNE3XT.js} +2 -2
- package/{chunk-MYMMNKYL.js → chunk-E5CLOOG5.js} +153 -6
- package/{chunk-ZXQ52OY2.js → chunk-ECGTEOC2.js} +3 -3
- package/chunk-FKXFCYVO.js +221 -0
- package/{chunk-6KBBMW4D.js → chunk-FTNTMGXT.js} +1 -1
- package/{chunk-6CRACQXW.js → chunk-GFPESFS6.js} +2 -2
- package/{chunk-47QUPRHO.js → chunk-GM37ZF7R.js} +2 -2
- package/{chunk-A7O4KKLZ.js → chunk-HGDFFA6T.js} +2 -2
- package/{chunk-C4MMO7W4.js → chunk-NZBK3ZET.js} +1 -1
- package/{chunk-JTMNCCWF.js → chunk-OSIJVBXP.js} +2 -2
- package/{chunk-OVBVEXZ7.js → chunk-PFW2ZEON.js} +53 -1
- package/{chunk-BXXECNBU.js → chunk-Q6B6XJBG.js} +15 -6
- package/{chunk-GPELDE6I.js → chunk-SOW2GCA5.js} +1 -1
- package/{chunk-HSASSW4L.js → chunk-TUWPYUVR.js} +7 -7
- package/{chunk-EQTZPEID.js → chunk-U3DCTSPN.js} +31 -49
- package/{chunk-D4NCEGGR.js → chunk-URVWRKFU.js} +166 -242
- package/{chunk-WBA6SIBB.js → chunk-UUDRNDC7.js} +1 -1
- package/{chunk-2WXMU64E.js → chunk-W63ZTRQU.js} +3 -3
- package/{chunk-ZH62XNZE.js → chunk-W6OKITU6.js} +678 -39
- package/{chunk-PU4LXVAC.js → chunk-XG7CSGP3.js} +1 -1
- package/{chunk-XRSPI6CP.js → chunk-YZXEEGKV.js} +1 -1
- package/{chunk-RIF3XLXK.js → chunk-ZDDHKIWB.js} +8 -4
- package/{createAgentAutomationAction-RKWIMKHW.js → createAgentAutomationAction-N4ZB7VX2.js} +3 -3
- package/{createDialogAction-VN7MEBS3.js → createDialogAction-KF6HXCCZ.js} +4 -4
- package/{createPageAction-JBUWBHHC.js → createPageAction-FXWSJONZ.js} +3 -3
- package/{dialogCommands-DFY5HJ6M.js → dialogCommands-ULS6HV5V.js} +11 -11
- package/{dialogSlice-NNYBU35K.js → dialogSlice-K32QLYS7.js} +3 -3
- package/{docCreateCommands-5L76YTI2.js → docCreateCommands-RZTRTRU4.js} +10 -10
- package/{docDeleteCommands-3GASP3VR.js → docDeleteCommands-FU36A663.js} +11 -11
- package/{docReadCommands-ALA77AZM.js → docReadCommands-IX4JXD4X.js} +10 -10
- package/{docStore-DR22GGF3.js → docStore-L6HBNJ3R.js} +4 -4
- package/{docUpdateCommands-6AZGXE5M.js → docUpdateCommands-W4OCR55Z.js} +10 -10
- package/{handleSendMessageAction-FHITDM7H.js → handleSendMessageAction-MFKKZXV7.js} +3 -3
- package/index.js +45 -45
- package/{machineCommands-3B4IHHVK.js → machineCommands-4MFLZERH.js} +18 -17
- package/{machineWsRunDispatch-AXZ6OL3V.js → machineWsRunDispatch-AAHRNKIR.js} +18 -17
- package/package.json +1 -1
- package/{readlineWorkspace-DBZCXS7Y.js → readlineWorkspace-7OPITHTN.js} +38 -29
- package/{runAgentClientLoop-AB7PQ3TB.js → runAgentClientLoop-HRWV7KE2.js} +12 -11
- package/{setPrimaryDialogAgentAction-IIVDCY5C.js → setPrimaryDialogAgentAction-57GRIGX5.js} +16 -8
- package/{skillDiscovery-6M2BZUFN.js → skillDiscovery-KJWT7JBU.js} +3 -3
- package/{spaceCommands-AB2D7A2R.js → spaceCommands-GMMQTMHK.js} +10 -10
- package/{spaceSlice-TEJDCU6A.js → spaceSlice-V2P5TTQU.js} +3 -3
- package/{streamAgentChatTurn-NZ3HLAXS.js → streamAgentChatTurn-ZANOYOUR.js} +64 -43
- package/{tools-M4USUF3R.js → tools-YHZP6NXU.js} +8 -7
- package/{updateDialogTitleAction-SMPQVKWT.js → updateDialogTitleAction-IKTPGPPE.js} +3 -3
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
buildLocalAgentLookupKeys,
|
|
9
9
|
normalizeAgentHandle,
|
|
10
10
|
shouldReadAgentKeyRemotely
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-XG7CSGP3.js";
|
|
12
12
|
import {
|
|
13
13
|
LOCAL_CODEX_AGENT_ID,
|
|
14
14
|
LOCAL_CODEX_AGENT_KEY,
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
import {
|
|
22
22
|
inlineImageUrlsForCustomProvider,
|
|
23
23
|
prepareTools
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-GM37ZF7R.js";
|
|
25
25
|
import {
|
|
26
26
|
getAntigravityUserAgent,
|
|
27
27
|
isAntigravityOAuthAgent,
|
|
@@ -30,27 +30,19 @@ import {
|
|
|
30
30
|
} from "./chunk-L6NVTGI7.js";
|
|
31
31
|
import {
|
|
32
32
|
FORCED_TOOLS,
|
|
33
|
-
TASK_PREVIEW_MAX,
|
|
34
33
|
addDefaultLightWebToolsForConfiguredAgents,
|
|
35
34
|
addDefaultSystemCapabilityTools,
|
|
36
35
|
appendEnabledPackPromptPatches,
|
|
37
36
|
applyDisabledTools,
|
|
38
37
|
applySystemBuiltinSkillFilter,
|
|
39
38
|
expandEnabledPacks,
|
|
40
|
-
formatListRunsCard,
|
|
41
|
-
formatNotFoundRunCard,
|
|
42
|
-
formatStartRunCard,
|
|
43
|
-
formatStatusRunCard,
|
|
44
|
-
formatStopRunCard,
|
|
45
|
-
isAgentNameFallback,
|
|
46
39
|
readXPostFunc,
|
|
47
40
|
readXPostFunctionSchema,
|
|
48
41
|
readXhsProfileFunc,
|
|
49
42
|
readXhsProfileFunctionSchema,
|
|
50
43
|
rememberMemoryFunctionSchema,
|
|
51
|
-
resolveEffectiveEnabledPacks
|
|
52
|
-
|
|
53
|
-
} from "./chunk-D4NCEGGR.js";
|
|
44
|
+
resolveEffectiveEnabledPacks
|
|
45
|
+
} from "./chunk-URVWRKFU.js";
|
|
54
46
|
import {
|
|
55
47
|
createDrainExhaustedResponse,
|
|
56
48
|
isCoreDrainingBody,
|
|
@@ -62,13 +54,13 @@ import {
|
|
|
62
54
|
} from "./chunk-OWOHNGCN.js";
|
|
63
55
|
import {
|
|
64
56
|
prepareTokenUsageData
|
|
65
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-2OK7P5XF.js";
|
|
66
58
|
import {
|
|
67
59
|
BUILTIN_TITLE_LLM_CONFIG
|
|
68
60
|
} from "./chunk-XOIF2TNF.js";
|
|
69
61
|
import {
|
|
70
62
|
fetchServerSyncedCredential
|
|
71
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-ECGTEOC2.js";
|
|
72
64
|
import {
|
|
73
65
|
buildAgentRuntimeDialogWritePlan,
|
|
74
66
|
buildLocalWorkspaceOpenAiTools,
|
|
@@ -82,7 +74,7 @@ import {
|
|
|
82
74
|
parseSseDataLineObject,
|
|
83
75
|
readOpenAiCompatibleSseCompletion,
|
|
84
76
|
resolveOpenAiCompatibleProviderConfig
|
|
85
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-5QJFYG2N.js";
|
|
86
78
|
import {
|
|
87
79
|
buildPlatformChatCompletionRequest,
|
|
88
80
|
canUsePlatformChatProvider,
|
|
@@ -97,7 +89,7 @@ import {
|
|
|
97
89
|
} from "./chunk-OIQPORYI.js";
|
|
98
90
|
import {
|
|
99
91
|
summarizeToolArguments
|
|
100
|
-
} from "./chunk-
|
|
92
|
+
} from "./chunk-ZDDHKIWB.js";
|
|
101
93
|
import {
|
|
102
94
|
convertMessagesToResponsesInput,
|
|
103
95
|
toResponsesTools
|
|
@@ -112,7 +104,7 @@ import {
|
|
|
112
104
|
canonicalizeToolNames,
|
|
113
105
|
parseNoloWorkspaceToolArguments,
|
|
114
106
|
resolveRuntimeToolSurfaceForAgent
|
|
115
|
-
} from "./chunk-
|
|
107
|
+
} from "./chunk-OSIJVBXP.js";
|
|
116
108
|
import {
|
|
117
109
|
clipCompactText
|
|
118
110
|
} from "./chunk-5MMAK75Q.js";
|
|
@@ -138,9 +130,22 @@ import {
|
|
|
138
130
|
checkStaleRun,
|
|
139
131
|
finalizeRunRecord,
|
|
140
132
|
findRunRecord,
|
|
141
|
-
|
|
133
|
+
gcRunRecords,
|
|
134
|
+
queryRunRecords,
|
|
142
135
|
spawnLocalBackgroundRun
|
|
143
|
-
} from "./chunk-
|
|
136
|
+
} from "./chunk-E5CLOOG5.js";
|
|
137
|
+
import {
|
|
138
|
+
TASK_PREVIEW_MAX,
|
|
139
|
+
formatListRunsCard,
|
|
140
|
+
formatNotFoundRunCard,
|
|
141
|
+
formatStartRunCard,
|
|
142
|
+
formatStatusRunCard,
|
|
143
|
+
formatStopRunCard,
|
|
144
|
+
isAgentNameFallback,
|
|
145
|
+
isAgentRunTerminalStatus,
|
|
146
|
+
resolveRunLabel,
|
|
147
|
+
shortRunId
|
|
148
|
+
} from "./chunk-FKXFCYVO.js";
|
|
144
149
|
import {
|
|
145
150
|
CliProviderQuotaError,
|
|
146
151
|
executeCli
|
|
@@ -950,6 +955,185 @@ function agentRunCardLabels() {
|
|
|
950
955
|
};
|
|
951
956
|
}
|
|
952
957
|
|
|
958
|
+
// packages/ai/tools/agent/quotaCircuitBreaker.ts
|
|
959
|
+
var QUOTA_ERROR_PATTERNS = [
|
|
960
|
+
/429/,
|
|
961
|
+
/quota/i,
|
|
962
|
+
/rate\s*limit/i,
|
|
963
|
+
/too\s*many\s*requests/i,
|
|
964
|
+
/额度/,
|
|
965
|
+
/上限/,
|
|
966
|
+
/用尽/,
|
|
967
|
+
/CliProviderQuotaError/i
|
|
968
|
+
];
|
|
969
|
+
var AGENT_NOT_FOUND_PATTERNS = [
|
|
970
|
+
/agent[^\n]{0,80}not\s+found/i,
|
|
971
|
+
/agent[^\n]{0,80}not\s+exist/i,
|
|
972
|
+
/agent[^\n]{0,80}不存在/i,
|
|
973
|
+
/agent[^\n]{0,80}未找到/i,
|
|
974
|
+
/AGENT_NOT_FOUND/
|
|
975
|
+
];
|
|
976
|
+
var AUTH_ERROR_PATTERNS = [
|
|
977
|
+
/401/,
|
|
978
|
+
/403/,
|
|
979
|
+
/unauthori[sz]ed/i,
|
|
980
|
+
/authentication\s+failed/i,
|
|
981
|
+
/invalid\s+(api[-\s]?key|token|credential)/i,
|
|
982
|
+
/api[-\s]?key\s+(invalid|missing|not\s+found)/i,
|
|
983
|
+
/token\s*(invalid|expired|失效|过期)/i,
|
|
984
|
+
/未授权/,
|
|
985
|
+
/认证失败/,
|
|
986
|
+
/凭证/
|
|
987
|
+
];
|
|
988
|
+
var NETWORK_ERROR_PATTERNS = [
|
|
989
|
+
/ECONNREFUSED|ECONNRESET|ETIMEDOUT|ENOTFOUND|EHOSTUNREACH|EPIPE/i,
|
|
990
|
+
/getaddrinfo|DNS\s+(error|fail)/i,
|
|
991
|
+
/fetch\s+failed/i,
|
|
992
|
+
/network\s+(error|unreachable|down|disconnected)/i,
|
|
993
|
+
/socket\s+(hang|closed|error)/i,
|
|
994
|
+
/连接失败/,
|
|
995
|
+
/网络错误|网络异常|无法连接/
|
|
996
|
+
];
|
|
997
|
+
function findActiveBreaker(now, table, target) {
|
|
998
|
+
if (!Number.isFinite(now)) return void 0;
|
|
999
|
+
for (const entry of table) {
|
|
1000
|
+
if (entry.target !== target) continue;
|
|
1001
|
+
if (typeof entry.until === "number" && entry.until > now) return entry;
|
|
1002
|
+
}
|
|
1003
|
+
return void 0;
|
|
1004
|
+
}
|
|
1005
|
+
function isCliProviderQuotaErrorShape(error) {
|
|
1006
|
+
if (!error || typeof error !== "object") return false;
|
|
1007
|
+
const e = error;
|
|
1008
|
+
return e.name === "CliProviderQuotaError" || typeof e.message === "string" && e.message.startsWith("[QUOTA_LIMITED:");
|
|
1009
|
+
}
|
|
1010
|
+
function isQuotaExhaustedError(error) {
|
|
1011
|
+
if (!error) return false;
|
|
1012
|
+
if (isCliProviderQuotaErrorShape(error)) return true;
|
|
1013
|
+
if (error instanceof Error) {
|
|
1014
|
+
return QUOTA_ERROR_PATTERNS.some((pattern) => pattern.test(error.message));
|
|
1015
|
+
}
|
|
1016
|
+
if (typeof error === "string") {
|
|
1017
|
+
return QUOTA_ERROR_PATTERNS.some((pattern) => pattern.test(error));
|
|
1018
|
+
}
|
|
1019
|
+
const maybeStatus = error.status;
|
|
1020
|
+
if (typeof maybeStatus === "number" && maybeStatus === 429) return true;
|
|
1021
|
+
const maybeStatusCode = error.statusCode;
|
|
1022
|
+
if (typeof maybeStatusCode === "number" && maybeStatusCode === 429) return true;
|
|
1023
|
+
return false;
|
|
1024
|
+
}
|
|
1025
|
+
function isAgentNotFoundError(error) {
|
|
1026
|
+
if (!error) return false;
|
|
1027
|
+
const e = error;
|
|
1028
|
+
if (e.code === "AGENT_NOT_FOUND") return true;
|
|
1029
|
+
const message = typeof e.message === "string" ? e.message : typeof error === "string" ? error : "";
|
|
1030
|
+
if (AGENT_NOT_FOUND_PATTERNS.some((pattern) => pattern.test(message))) return true;
|
|
1031
|
+
if ((e.status === 404 || e.statusCode === 404) && /agent|不存在|未找到/i.test(message)) {
|
|
1032
|
+
return true;
|
|
1033
|
+
}
|
|
1034
|
+
return false;
|
|
1035
|
+
}
|
|
1036
|
+
function extractMessage(error) {
|
|
1037
|
+
if (typeof error === "string") return error;
|
|
1038
|
+
if (error instanceof Error) return error.message;
|
|
1039
|
+
if (error && typeof error === "object") {
|
|
1040
|
+
const m = error.message;
|
|
1041
|
+
return typeof m === "string" ? m : "";
|
|
1042
|
+
}
|
|
1043
|
+
return "";
|
|
1044
|
+
}
|
|
1045
|
+
function extractStatus(error) {
|
|
1046
|
+
if (!error || typeof error !== "object") return void 0;
|
|
1047
|
+
const e = error;
|
|
1048
|
+
const s = typeof e.status === "number" ? e.status : void 0;
|
|
1049
|
+
const sc = typeof e.statusCode === "number" ? e.statusCode : void 0;
|
|
1050
|
+
return s ?? sc;
|
|
1051
|
+
}
|
|
1052
|
+
function parseResetsInMs(text) {
|
|
1053
|
+
if (!text) return void 0;
|
|
1054
|
+
const unitMs = (n, unit) => {
|
|
1055
|
+
if (/^d/.test(unit)) return n * 24 * 3600 * 1e3;
|
|
1056
|
+
if (/^h/.test(unit)) return n * 3600 * 1e3;
|
|
1057
|
+
if (/^m/.test(unit)) return n * 60 * 1e3;
|
|
1058
|
+
if (/^s/.test(unit)) return n * 1e3;
|
|
1059
|
+
return NaN;
|
|
1060
|
+
};
|
|
1061
|
+
const re = /(\d+)\s*(d(?:ay|ays)?|h(?:r|rs|our|ours)?|m(?:in|ins|inute|inutes)?|s(?:ec|ecs|econd|econds)?)/gi;
|
|
1062
|
+
let totalMs = 0;
|
|
1063
|
+
let matched = false;
|
|
1064
|
+
let m;
|
|
1065
|
+
while ((m = re.exec(text)) !== null) {
|
|
1066
|
+
const ms = unitMs(Number(m[1]), m[2]);
|
|
1067
|
+
if (!Number.isFinite(ms)) continue;
|
|
1068
|
+
totalMs += ms;
|
|
1069
|
+
matched = true;
|
|
1070
|
+
}
|
|
1071
|
+
return matched ? totalMs : void 0;
|
|
1072
|
+
}
|
|
1073
|
+
function extractProvider(error) {
|
|
1074
|
+
if (!error || typeof error !== "object") return void 0;
|
|
1075
|
+
const p = error.provider;
|
|
1076
|
+
if (typeof p === "string" && p.length > 0) return p;
|
|
1077
|
+
const message = extractMessage(error);
|
|
1078
|
+
const tag = /\[QUOTA_LIMITED:([^\]]+)\]/i.exec(message);
|
|
1079
|
+
if (tag?.[1]) return tag[1];
|
|
1080
|
+
return void 0;
|
|
1081
|
+
}
|
|
1082
|
+
function extractRetryAfterHeader(error) {
|
|
1083
|
+
if (!error || typeof error !== "object") return void 0;
|
|
1084
|
+
const headers = error.headers;
|
|
1085
|
+
if (!headers || typeof headers !== "object") return void 0;
|
|
1086
|
+
const raw = headers["retry-after"];
|
|
1087
|
+
if (typeof raw !== "string" && typeof raw !== "number") return void 0;
|
|
1088
|
+
const secs = Number(raw);
|
|
1089
|
+
return Number.isFinite(secs) && secs > 0 ? secs * 1e3 : void 0;
|
|
1090
|
+
}
|
|
1091
|
+
function classifyRunFailure(error) {
|
|
1092
|
+
const message = extractMessage(error);
|
|
1093
|
+
const status = extractStatus(error);
|
|
1094
|
+
const retryAfterMs = extractRetryAfterHeader(error) ?? parseResetsInMs(message);
|
|
1095
|
+
if (isQuotaExhaustedError(error)) {
|
|
1096
|
+
return {
|
|
1097
|
+
reason: "quota",
|
|
1098
|
+
provider: extractProvider(error),
|
|
1099
|
+
// 纯函数不取时钟:resetsAt 由调用方用 now + retryAfterMs 计算后补齐
|
|
1100
|
+
retryAfterMs,
|
|
1101
|
+
message
|
|
1102
|
+
};
|
|
1103
|
+
}
|
|
1104
|
+
if (isAgentNotFoundError(error)) {
|
|
1105
|
+
return { reason: "agent-not-found", message };
|
|
1106
|
+
}
|
|
1107
|
+
if (isAuthError(error)) {
|
|
1108
|
+
return { reason: "auth", message };
|
|
1109
|
+
}
|
|
1110
|
+
if (isNetworkError(error)) {
|
|
1111
|
+
return { reason: "network", message };
|
|
1112
|
+
}
|
|
1113
|
+
return { reason: "other", message };
|
|
1114
|
+
}
|
|
1115
|
+
function isAuthError(error) {
|
|
1116
|
+
const message = extractMessage(error);
|
|
1117
|
+
const status = extractStatus(error);
|
|
1118
|
+
if (status === 401 || status === 403) return true;
|
|
1119
|
+
return AUTH_ERROR_PATTERNS.some((pattern) => pattern.test(message));
|
|
1120
|
+
}
|
|
1121
|
+
function isNetworkError(error) {
|
|
1122
|
+
const message = extractMessage(error);
|
|
1123
|
+
return NETWORK_ERROR_PATTERNS.some((pattern) => pattern.test(message));
|
|
1124
|
+
}
|
|
1125
|
+
var DEFAULT_QUOTA_BREAKER_MS = 6 * 3600 * 1e3;
|
|
1126
|
+
var DEFAULT_AGENT_NOT_FOUND_BREAKER_MS = 15 * 60 * 1e3;
|
|
1127
|
+
function buildBreakerEntry(now, target, kind, retryAfterMs) {
|
|
1128
|
+
const ttl = kind === "quota" ? typeof retryAfterMs === "number" && retryAfterMs > 0 ? retryAfterMs : DEFAULT_QUOTA_BREAKER_MS : DEFAULT_AGENT_NOT_FOUND_BREAKER_MS;
|
|
1129
|
+
return {
|
|
1130
|
+
target,
|
|
1131
|
+
kind,
|
|
1132
|
+
until: now + ttl,
|
|
1133
|
+
...kind === "quota" && typeof retryAfterMs === "number" ? { resetsAt: now + retryAfterMs } : {}
|
|
1134
|
+
};
|
|
1135
|
+
}
|
|
1136
|
+
|
|
953
1137
|
// packages/cli/client/localRuntimeDiagnostics.ts
|
|
954
1138
|
import { ulid } from "ulid";
|
|
955
1139
|
var preparedAgentRuntimeCache = /* @__PURE__ */ new Map();
|
|
@@ -989,7 +1173,7 @@ function summarizeOpenAiToolNames(tools) {
|
|
|
989
1173
|
}
|
|
990
1174
|
|
|
991
1175
|
// packages/cli/client/localRuntimeAdapter.ts
|
|
992
|
-
import { dirname, extname, join } from "node:path";
|
|
1176
|
+
import { dirname as dirname2, extname, join as join2 } from "node:path";
|
|
993
1177
|
import { fileURLToPath } from "node:url";
|
|
994
1178
|
|
|
995
1179
|
// packages/core/summarizeEndpoint.ts
|
|
@@ -1786,7 +1970,10 @@ var LOCAL_SERVER_WEB_TOOL_NAMES = ["fetchWebpage", "exa_search"];
|
|
|
1786
1970
|
var LOCAL_SERVER_WEB_TOOL_NAME_SET = new Set(
|
|
1787
1971
|
LOCAL_SERVER_WEB_TOOL_NAMES
|
|
1788
1972
|
);
|
|
1789
|
-
var LOCAL_SERVER_MEMORY_TOOL_NAMES = [
|
|
1973
|
+
var LOCAL_SERVER_MEMORY_TOOL_NAMES = [
|
|
1974
|
+
"queryMemory",
|
|
1975
|
+
"rememberMemory"
|
|
1976
|
+
];
|
|
1790
1977
|
var LOCAL_SERVER_MEMORY_TOOL_NAME_SET = new Set(
|
|
1791
1978
|
LOCAL_SERVER_MEMORY_TOOL_NAMES
|
|
1792
1979
|
);
|
|
@@ -2018,6 +2205,27 @@ function buildServerPlatformToolExecutors(args) {
|
|
|
2018
2205
|
}
|
|
2019
2206
|
])
|
|
2020
2207
|
);
|
|
2208
|
+
const queryMemory = async (call) => {
|
|
2209
|
+
const parsed = parseNoloWorkspaceToolArguments(call.arguments);
|
|
2210
|
+
const query = typeof parsed.query === "string" ? parsed.query.trim() : "";
|
|
2211
|
+
if (!query) {
|
|
2212
|
+
return {
|
|
2213
|
+
content: JSON.stringify({ error: "queryMemory \u9700\u8981\u975E\u7A7A query\u3002" }),
|
|
2214
|
+
metadata: { serverPlatformTool: true, memoryRead: false }
|
|
2215
|
+
};
|
|
2216
|
+
}
|
|
2217
|
+
const body = { userInput: query };
|
|
2218
|
+
if (args.agentKey) body.agentKey = args.agentKey;
|
|
2219
|
+
const memorySubjectId = typeof call.runtimeContext?.memorySubjectId === "string" ? call.runtimeContext.memorySubjectId.trim() : args.memorySubjectId?.trim();
|
|
2220
|
+
if (memorySubjectId) body.memorySubjectId = memorySubjectId;
|
|
2221
|
+
const raw = await postServer("/api/memory/query", body, {
|
|
2222
|
+
retryTransient: true
|
|
2223
|
+
});
|
|
2224
|
+
return {
|
|
2225
|
+
content: raw,
|
|
2226
|
+
metadata: { serverPlatformTool: true, memoryRead: true }
|
|
2227
|
+
};
|
|
2228
|
+
};
|
|
2021
2229
|
const rememberMemory = async (call) => {
|
|
2022
2230
|
const parsed = parseNoloWorkspaceToolArguments(call.arguments);
|
|
2023
2231
|
const content = typeof parsed.content === "string" ? parsed.content.trim() : "";
|
|
@@ -2036,6 +2244,8 @@ function buildServerPlatformToolExecutors(args) {
|
|
|
2036
2244
|
source: "agent-inferred"
|
|
2037
2245
|
};
|
|
2038
2246
|
if (args.agentKey) body.agentKey = args.agentKey;
|
|
2247
|
+
const memorySubjectId = typeof call.runtimeContext?.memorySubjectId === "string" ? call.runtimeContext.memorySubjectId.trim() : args.memorySubjectId?.trim();
|
|
2248
|
+
if (memorySubjectId) body.memorySubjectId = memorySubjectId;
|
|
2039
2249
|
const raw = await postServer("/api/memory/remember", body, {
|
|
2040
2250
|
retryTransient: true
|
|
2041
2251
|
});
|
|
@@ -2044,11 +2254,11 @@ function buildServerPlatformToolExecutors(args) {
|
|
|
2044
2254
|
metadata: { serverPlatformTool: true, memoryWrite: true }
|
|
2045
2255
|
};
|
|
2046
2256
|
};
|
|
2047
|
-
return { ...tableExecutors, ...webExecutors, rememberMemory };
|
|
2257
|
+
return { ...tableExecutors, ...webExecutors, queryMemory, rememberMemory };
|
|
2048
2258
|
}
|
|
2049
2259
|
|
|
2050
2260
|
// packages/cli/client/cliAgentRunToolExecutors.ts
|
|
2051
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
2261
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
2052
2262
|
|
|
2053
2263
|
// packages/cli/client/agentRunSnapshot.ts
|
|
2054
2264
|
function readString(value) {
|
|
@@ -2135,6 +2345,276 @@ function parseAgentRunEvent(event) {
|
|
|
2135
2345
|
return { kind: "status", snapshot };
|
|
2136
2346
|
}
|
|
2137
2347
|
|
|
2348
|
+
// packages/ai/tools/agent/batchAggregation.ts
|
|
2349
|
+
var DEFAULT_BATCH_TIMEOUT_MS = 30 * 60 * 1e3;
|
|
2350
|
+
var MAX_ERROR_SUMMARY_CHARS = 120;
|
|
2351
|
+
var MAX_FAILURE_LINES = 10;
|
|
2352
|
+
function isFailureStatus(status) {
|
|
2353
|
+
return isAgentRunTerminalStatus(status) && status !== "done";
|
|
2354
|
+
}
|
|
2355
|
+
function isOrphanedStatus(status) {
|
|
2356
|
+
return status === "orphaned";
|
|
2357
|
+
}
|
|
2358
|
+
function toEpochMs(iso) {
|
|
2359
|
+
if (!iso) return void 0;
|
|
2360
|
+
const ms = Date.parse(iso);
|
|
2361
|
+
return Number.isFinite(ms) ? ms : void 0;
|
|
2362
|
+
}
|
|
2363
|
+
function isOverTimeout(run, nowMs, timeoutMs) {
|
|
2364
|
+
const startedMs = toEpochMs(run.startedAt);
|
|
2365
|
+
if (startedMs === void 0) return false;
|
|
2366
|
+
return nowMs - startedMs >= timeoutMs;
|
|
2367
|
+
}
|
|
2368
|
+
function truncateErrorSummary(text, max = MAX_ERROR_SUMMARY_CHARS) {
|
|
2369
|
+
if (!text) return "";
|
|
2370
|
+
const collapsed = text.replace(/\s+/g, " ").trim();
|
|
2371
|
+
if (collapsed.length <= max) return collapsed;
|
|
2372
|
+
return `${collapsed.slice(0, max - 1)}\u2026`;
|
|
2373
|
+
}
|
|
2374
|
+
function formatFailureLine(run) {
|
|
2375
|
+
const label = shortRunId(run.runId);
|
|
2376
|
+
const agent = run.agentName ? ` (${run.agentName})` : "";
|
|
2377
|
+
const error = truncateErrorSummary(run.errorSummary);
|
|
2378
|
+
return error ? `\u5931\u8D25: ${label}${agent} \u2014 ${error}` : `\u5931\u8D25: ${label}${agent}`;
|
|
2379
|
+
}
|
|
2380
|
+
function formatBatchSummary(batchId, counts, runs, reason) {
|
|
2381
|
+
const failures = runs.filter((r) => isFailureStatus(r.status));
|
|
2382
|
+
const unfinished = runs.filter((r) => !isAgentRunTerminalStatus(r.status));
|
|
2383
|
+
if (reason === "timeout") {
|
|
2384
|
+
const lines2 = [
|
|
2385
|
+
`\u6279\u6B21 ${batchId}: \u8D85\u65F6\u672A\u6536\u655B \u2014 ${counts.running} \u4E2A\u672A\u5B8C\u6210`
|
|
2386
|
+
];
|
|
2387
|
+
for (const run of unfinished.slice(0, MAX_FAILURE_LINES)) {
|
|
2388
|
+
const agent = run.agentName ? ` (${run.agentName})` : "";
|
|
2389
|
+
lines2.push(`\u672A\u5B8C\u6210: ${shortRunId(run.runId)}${agent}`);
|
|
2390
|
+
}
|
|
2391
|
+
const rest2 = unfinished.length - MAX_FAILURE_LINES;
|
|
2392
|
+
if (rest2 > 0) lines2.push(`\u2026 \u53CA\u53E6\u5916 ${rest2} \u4E2A\u672A\u5B8C\u6210`);
|
|
2393
|
+
return lines2.join("\n");
|
|
2394
|
+
}
|
|
2395
|
+
const tail = counts.running > 0 ? `, ${counts.running} \u4ECD\u5728\u8DD1` : "";
|
|
2396
|
+
const lines = [
|
|
2397
|
+
`\u6279\u6B21 ${batchId}: ${counts.success + counts.failed}/${counts.total} \u5B8C\u6210 \u2014 ${counts.success} \u6210\u529F, ${counts.failed} \u5931\u8D25${tail}`
|
|
2398
|
+
];
|
|
2399
|
+
for (const run of failures.slice(0, MAX_FAILURE_LINES)) {
|
|
2400
|
+
lines.push(formatFailureLine(run));
|
|
2401
|
+
}
|
|
2402
|
+
const rest = failures.length - MAX_FAILURE_LINES;
|
|
2403
|
+
if (rest > 0) lines.push(`\u2026 \u53CA\u53E6\u5916 ${rest} \u4E2A\u5931\u8D25`);
|
|
2404
|
+
return lines.join("\n");
|
|
2405
|
+
}
|
|
2406
|
+
function aggregateBatch(input) {
|
|
2407
|
+
const { batchId, runs, now } = input;
|
|
2408
|
+
const timeoutMs = input.timeoutMs ?? DEFAULT_BATCH_TIMEOUT_MS;
|
|
2409
|
+
const notified = new Set(input.notifiedReasons ?? []);
|
|
2410
|
+
const nowMs = toEpochMs(now) ?? 0;
|
|
2411
|
+
let success = 0;
|
|
2412
|
+
let failed = 0;
|
|
2413
|
+
let orphaned = 0;
|
|
2414
|
+
let running = 0;
|
|
2415
|
+
const unfinished = [];
|
|
2416
|
+
let timedOut = false;
|
|
2417
|
+
for (const run of runs) {
|
|
2418
|
+
if (isAgentRunTerminalStatus(run.status)) {
|
|
2419
|
+
if (run.status === "done") success += 1;
|
|
2420
|
+
else {
|
|
2421
|
+
failed += 1;
|
|
2422
|
+
if (isOrphanedStatus(run.status)) orphaned += 1;
|
|
2423
|
+
}
|
|
2424
|
+
} else {
|
|
2425
|
+
running += 1;
|
|
2426
|
+
unfinished.push(run.runId);
|
|
2427
|
+
if (isOverTimeout(run, nowMs, timeoutMs)) timedOut = true;
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
const converged = running === 0;
|
|
2431
|
+
let newWakeReasons = [];
|
|
2432
|
+
if (failed > 0 && !notified.has("failure")) {
|
|
2433
|
+
newWakeReasons = ["failure"];
|
|
2434
|
+
} else if (converged && !notified.has("converged")) {
|
|
2435
|
+
newWakeReasons = ["converged"];
|
|
2436
|
+
} else if (timedOut && !notified.has("timeout")) {
|
|
2437
|
+
newWakeReasons = ["timeout"];
|
|
2438
|
+
}
|
|
2439
|
+
const counts = {
|
|
2440
|
+
total: runs.length,
|
|
2441
|
+
success,
|
|
2442
|
+
failed,
|
|
2443
|
+
orphaned,
|
|
2444
|
+
running
|
|
2445
|
+
};
|
|
2446
|
+
const summary = newWakeReasons.length > 0 ? formatBatchSummary(batchId, counts, runs, newWakeReasons[0]) : "";
|
|
2447
|
+
return {
|
|
2448
|
+
batchId,
|
|
2449
|
+
converged,
|
|
2450
|
+
timedOut,
|
|
2451
|
+
counts,
|
|
2452
|
+
newWakeReasons,
|
|
2453
|
+
unfinished,
|
|
2454
|
+
summary
|
|
2455
|
+
};
|
|
2456
|
+
}
|
|
2457
|
+
|
|
2458
|
+
// packages/ai/tools/agent/runtimeTodo.ts
|
|
2459
|
+
var TODO_REVIEW_BLOCK = "BLOCK";
|
|
2460
|
+
function deriveTodoStatus(input) {
|
|
2461
|
+
const { todo, runs } = input;
|
|
2462
|
+
if (todo.status === "abandoned") {
|
|
2463
|
+
return { status: "abandoned" };
|
|
2464
|
+
}
|
|
2465
|
+
if (runs.length === 0) {
|
|
2466
|
+
return { status: todo.status };
|
|
2467
|
+
}
|
|
2468
|
+
if (runs.some((r) => !isAgentRunTerminalStatus(r.status))) {
|
|
2469
|
+
return { status: "running", latestRun: latestRun(runs) };
|
|
2470
|
+
}
|
|
2471
|
+
const latest = latestRun(runs);
|
|
2472
|
+
if (latest?.reviewVerdict === TODO_REVIEW_BLOCK) {
|
|
2473
|
+
return {
|
|
2474
|
+
status: "blocked",
|
|
2475
|
+
latestRun: latest,
|
|
2476
|
+
blockedReason: clipSummary(latest.reviewReason, MAX_ERROR_SUMMARY_CHARS)
|
|
2477
|
+
};
|
|
2478
|
+
}
|
|
2479
|
+
if (latest?.status === "done") {
|
|
2480
|
+
return { status: "done", latestRun: latest };
|
|
2481
|
+
}
|
|
2482
|
+
return { status: "pending", latestRun: latest };
|
|
2483
|
+
}
|
|
2484
|
+
function toEpochMs2(iso) {
|
|
2485
|
+
if (!iso) return void 0;
|
|
2486
|
+
const ms = Date.parse(iso);
|
|
2487
|
+
return Number.isFinite(ms) ? ms : void 0;
|
|
2488
|
+
}
|
|
2489
|
+
function latestRun(runs) {
|
|
2490
|
+
let latest;
|
|
2491
|
+
let latestScore = -1;
|
|
2492
|
+
for (const run of runs) {
|
|
2493
|
+
const score = toEpochMs2(run.finishedAt) ?? toEpochMs2(run.startedAt) ?? -1;
|
|
2494
|
+
if (latest === void 0 || score >= latestScore) {
|
|
2495
|
+
latest = run;
|
|
2496
|
+
latestScore = score;
|
|
2497
|
+
}
|
|
2498
|
+
}
|
|
2499
|
+
return latest;
|
|
2500
|
+
}
|
|
2501
|
+
function clipSummary(text, max) {
|
|
2502
|
+
if (!text) return void 0;
|
|
2503
|
+
const folded = text.replace(/\s+/g, " ").trim();
|
|
2504
|
+
if (folded.length === 0) return void 0;
|
|
2505
|
+
return folded.length > max ? `${folded.slice(0, max - 1)}\u2026` : folded;
|
|
2506
|
+
}
|
|
2507
|
+
|
|
2508
|
+
// packages/cli/client/fileSystemStores.ts
|
|
2509
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2510
|
+
import { homedir as nodeHomedir } from "node:os";
|
|
2511
|
+
import { dirname, join } from "node:path";
|
|
2512
|
+
var nodeFs = {
|
|
2513
|
+
mkdirSync,
|
|
2514
|
+
writeFileSync,
|
|
2515
|
+
readFileSync,
|
|
2516
|
+
existsSync
|
|
2517
|
+
};
|
|
2518
|
+
function resolveNoloHome(env, homedir) {
|
|
2519
|
+
const custom = env?.NOLO_HOME;
|
|
2520
|
+
if (custom && custom.trim()) return custom.trim();
|
|
2521
|
+
return join(homedir(), ".nolo");
|
|
2522
|
+
}
|
|
2523
|
+
function ensureDir(dir, fs) {
|
|
2524
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
2525
|
+
}
|
|
2526
|
+
function readJson(path, fs) {
|
|
2527
|
+
if (!fs.existsSync(path)) return void 0;
|
|
2528
|
+
try {
|
|
2529
|
+
const raw = fs.readFileSync(path, "utf8");
|
|
2530
|
+
return JSON.parse(String(raw));
|
|
2531
|
+
} catch {
|
|
2532
|
+
return void 0;
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
function writeJson(path, data, fs) {
|
|
2536
|
+
fs.writeFileSync(path, JSON.stringify(data, null, 2));
|
|
2537
|
+
}
|
|
2538
|
+
function createFileSystemCircuitBreakerStore(opts = {}) {
|
|
2539
|
+
const env = opts.env ?? process.env;
|
|
2540
|
+
const homedir = opts.homedir ?? nodeHomedir;
|
|
2541
|
+
const fs = opts.fs ?? nodeFs;
|
|
2542
|
+
const filePath = opts.filePath ?? join(resolveNoloHome(env, homedir), "breakers.json");
|
|
2543
|
+
const loadMap = () => {
|
|
2544
|
+
const data = readJson(filePath, fs);
|
|
2545
|
+
const map = /* @__PURE__ */ new Map();
|
|
2546
|
+
if (data?.entries) {
|
|
2547
|
+
for (const entry of data.entries) {
|
|
2548
|
+
if (entry && typeof entry.target === "string") map.set(entry.target, entry);
|
|
2549
|
+
}
|
|
2550
|
+
}
|
|
2551
|
+
return map;
|
|
2552
|
+
};
|
|
2553
|
+
const persist = (map) => {
|
|
2554
|
+
ensureDir(dirname(filePath), fs);
|
|
2555
|
+
writeJson(filePath, { entries: [...map.values()] }, fs);
|
|
2556
|
+
};
|
|
2557
|
+
return {
|
|
2558
|
+
get(target) {
|
|
2559
|
+
return loadMap().get(target);
|
|
2560
|
+
},
|
|
2561
|
+
set(entry) {
|
|
2562
|
+
const map = loadMap();
|
|
2563
|
+
map.set(entry.target, entry);
|
|
2564
|
+
persist(map);
|
|
2565
|
+
},
|
|
2566
|
+
clear(target) {
|
|
2567
|
+
const map = loadMap();
|
|
2568
|
+
map.delete(target);
|
|
2569
|
+
persist(map);
|
|
2570
|
+
},
|
|
2571
|
+
clearAll() {
|
|
2572
|
+
persist(/* @__PURE__ */ new Map());
|
|
2573
|
+
}
|
|
2574
|
+
};
|
|
2575
|
+
}
|
|
2576
|
+
function createFileSystemTodoStore(opts = {}) {
|
|
2577
|
+
const env = opts.env ?? process.env;
|
|
2578
|
+
const homedir = opts.homedir ?? nodeHomedir;
|
|
2579
|
+
const fs = opts.fs ?? nodeFs;
|
|
2580
|
+
const filePath = opts.filePath ?? join(resolveNoloHome(env, homedir), "todos.json");
|
|
2581
|
+
const loadMap = () => {
|
|
2582
|
+
const data = readJson(filePath, fs);
|
|
2583
|
+
const map = /* @__PURE__ */ new Map();
|
|
2584
|
+
if (data?.todos) {
|
|
2585
|
+
for (const todo of data.todos) {
|
|
2586
|
+
if (todo && typeof todo.id === "string") map.set(todo.id, todo);
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
return map;
|
|
2590
|
+
};
|
|
2591
|
+
const persist = (map) => {
|
|
2592
|
+
ensureDir(dirname(filePath), fs);
|
|
2593
|
+
writeJson(filePath, { todos: [...map.values()] }, fs);
|
|
2594
|
+
};
|
|
2595
|
+
return {
|
|
2596
|
+
async getTodo(id) {
|
|
2597
|
+
return loadMap().get(id);
|
|
2598
|
+
},
|
|
2599
|
+
async listTodos(filter) {
|
|
2600
|
+
const all = [...loadMap().values()];
|
|
2601
|
+
if (!filter?.statuses || filter.statuses.length === 0) return all;
|
|
2602
|
+
const wanted = new Set(filter.statuses);
|
|
2603
|
+
return all.filter((t2) => wanted.has(t2.status));
|
|
2604
|
+
},
|
|
2605
|
+
async putTodo(todo) {
|
|
2606
|
+
const map = loadMap();
|
|
2607
|
+
map.set(todo.id, todo);
|
|
2608
|
+
persist(map);
|
|
2609
|
+
},
|
|
2610
|
+
async deleteTodo(id) {
|
|
2611
|
+
const map = loadMap();
|
|
2612
|
+
map.delete(id);
|
|
2613
|
+
persist(map);
|
|
2614
|
+
}
|
|
2615
|
+
};
|
|
2616
|
+
}
|
|
2617
|
+
|
|
2138
2618
|
// packages/cli/client/cliAgentRunToolExecutors.ts
|
|
2139
2619
|
var noopOutput = { write: () => {
|
|
2140
2620
|
} };
|
|
@@ -2145,7 +2625,7 @@ var parseCallArgs = (call) => {
|
|
|
2145
2625
|
return {};
|
|
2146
2626
|
}
|
|
2147
2627
|
};
|
|
2148
|
-
var resolveFs = (deps) => deps.fs ?? { existsSync, readFileSync };
|
|
2628
|
+
var resolveFs = (deps) => deps.fs ?? { existsSync: existsSync2, readFileSync: readFileSync2 };
|
|
2149
2629
|
var tailFile = (logPath, tailLines, fs) => {
|
|
2150
2630
|
if (!fs.existsSync(logPath)) return void 0;
|
|
2151
2631
|
try {
|
|
@@ -2157,6 +2637,10 @@ var tailFile = (logPath, tailLines, fs) => {
|
|
|
2157
2637
|
return void 0;
|
|
2158
2638
|
}
|
|
2159
2639
|
};
|
|
2640
|
+
var resolveBreakerStore = (deps) => deps.breakerStore ?? createFileSystemCircuitBreakerStore({ env: deps.env, homedir: deps.homedir, fs: deps.fs });
|
|
2641
|
+
var resolveTodoStore = (deps) => deps.todoStore ?? createFileSystemTodoStore({ env: deps.env, homedir: deps.homedir, fs: deps.fs });
|
|
2642
|
+
var resolveNowMs = (deps) => typeof deps.nowMs === "function" ? deps.nowMs() : Date.now();
|
|
2643
|
+
var resolveTarget = (deps, agentKey) => typeof deps.resolveProviderTarget === "function" ? deps.resolveProviderTarget(agentKey) : agentKey;
|
|
2160
2644
|
function createCliStartAgentRunExecutor(deps = {}) {
|
|
2161
2645
|
return async (call) => {
|
|
2162
2646
|
const args = parseCallArgs(call);
|
|
@@ -2164,6 +2648,29 @@ function createCliStartAgentRunExecutor(deps = {}) {
|
|
|
2164
2648
|
const task = typeof args.task === "string" ? args.task.trim() : "";
|
|
2165
2649
|
if (!agentKey) throw new Error("startAgentRun: \u7F3A\u5C11 agentKey \u53C2\u6570\u3002");
|
|
2166
2650
|
if (!task) throw new Error("startAgentRun: \u7F3A\u5C11\u6709\u6548\u7684 task \u6587\u672C\u63CF\u8FF0\u3002");
|
|
2651
|
+
const breakerStore = resolveBreakerStore(deps);
|
|
2652
|
+
const target = resolveTarget(deps, agentKey);
|
|
2653
|
+
const nowMs = resolveNowMs(deps);
|
|
2654
|
+
const activeBreaker = findActiveBreaker(
|
|
2655
|
+
nowMs,
|
|
2656
|
+
[breakerStore.get(target)].filter(Boolean),
|
|
2657
|
+
target
|
|
2658
|
+
);
|
|
2659
|
+
if (activeBreaker) {
|
|
2660
|
+
const resetsAt = activeBreaker.resetsAt;
|
|
2661
|
+
return {
|
|
2662
|
+
content: JSON.stringify({
|
|
2663
|
+
rejected: true,
|
|
2664
|
+
reason: "quota",
|
|
2665
|
+
provider: target,
|
|
2666
|
+
...resetsAt !== void 0 ? { resetsAt } : {},
|
|
2667
|
+
message: `provider ${target} \u5904\u4E8E\u7194\u65AD\u671F\uFF08\u914D\u989D\u8017\u5C3D\uFF09\uFF0C\u5EFA\u8BAE\u6539\u6D3E\u5176\u5B83 provider\u3002`
|
|
2668
|
+
}),
|
|
2669
|
+
metadata: {
|
|
2670
|
+
displayData: `Run rejected \xB7 quota breaker active on ${target}`
|
|
2671
|
+
}
|
|
2672
|
+
};
|
|
2673
|
+
}
|
|
2167
2674
|
const message = typeof args.input === "undefined" ? task : `${task}
|
|
2168
2675
|
|
|
2169
2676
|
--- \u9644\u52A0\u8F93\u5165 ---
|
|
@@ -2179,13 +2686,16 @@ ${JSON.stringify(args.input)}`;
|
|
|
2179
2686
|
...args.ephemeral === true ? ["--ephemeral"] : []
|
|
2180
2687
|
];
|
|
2181
2688
|
const agentName = typeof args.agentName === "string" && args.agentName.trim() ? args.agentName.trim() : typeof args.name === "string" && args.name.trim() ? args.name.trim() : void 0;
|
|
2182
|
-
const
|
|
2689
|
+
const batchId = typeof args.batchId === "string" && args.batchId.trim() ? args.batchId.trim() : void 0;
|
|
2690
|
+
const { runId, batchId: resolvedBatchId } = await spawnLocalBackgroundRun(
|
|
2183
2691
|
{
|
|
2184
2692
|
rawArgs,
|
|
2185
2693
|
commandPath: ["agent", "run"],
|
|
2186
2694
|
cliEntrypointPath: deps.cliEntrypoint,
|
|
2187
2695
|
agentKey,
|
|
2188
2696
|
...agentName ? { agentName } : {},
|
|
2697
|
+
...batchId ? { batchId } : {},
|
|
2698
|
+
...typeof args.parentDialogId === "string" && args.parentDialogId.trim() ? { parentDialogId: args.parentDialogId.trim() } : {},
|
|
2189
2699
|
cwd: deps.cwd ?? process.cwd(),
|
|
2190
2700
|
message,
|
|
2191
2701
|
output: noopOutput
|
|
@@ -2195,10 +2705,39 @@ ${JSON.stringify(args.input)}`;
|
|
|
2195
2705
|
const displayName = resolveRunLabel({ agentName, agentKey, runId });
|
|
2196
2706
|
const labels = agentRunCardLabels();
|
|
2197
2707
|
const taskPreview = typeof args.task === "string" ? args.task.replace(/\s+/g, " ").trim().slice(0, TASK_PREVIEW_MAX) : "";
|
|
2708
|
+
const trackTodo = typeof args.trackTodo === "boolean" ? args.trackTodo : Boolean(resolvedBatchId);
|
|
2709
|
+
if (trackTodo) {
|
|
2710
|
+
try {
|
|
2711
|
+
const todoStore = resolveTodoStore(deps);
|
|
2712
|
+
const todoId = `todo-${resolvedBatchId}`;
|
|
2713
|
+
const existing = await todoStore.getTodo(todoId);
|
|
2714
|
+
const nowIso = new Date(nowMs).toISOString();
|
|
2715
|
+
const runIds = existing?.runIds ?? [];
|
|
2716
|
+
if (!runIds.includes(runId)) runIds.push(runId);
|
|
2717
|
+
const todo = {
|
|
2718
|
+
id: todoId,
|
|
2719
|
+
title: taskPreview || task.slice(0, 100),
|
|
2720
|
+
status: existing?.status ?? "pending",
|
|
2721
|
+
...existing?.specPath ? { specPath: existing.specPath } : {},
|
|
2722
|
+
...existing?.worktree ? { worktree: existing.worktree } : {},
|
|
2723
|
+
...existing?.branch ? { branch: existing.branch } : {},
|
|
2724
|
+
...deps.cwd ? { worktree: deps.cwd } : {},
|
|
2725
|
+
runIds,
|
|
2726
|
+
deps: existing?.deps ?? [],
|
|
2727
|
+
createdAt: existing?.createdAt ?? nowIso,
|
|
2728
|
+
updatedAt: nowIso
|
|
2729
|
+
};
|
|
2730
|
+
await todoStore.putTodo(todo);
|
|
2731
|
+
} catch {
|
|
2732
|
+
}
|
|
2733
|
+
}
|
|
2198
2734
|
return {
|
|
2199
2735
|
content: JSON.stringify({
|
|
2200
2736
|
runId,
|
|
2201
2737
|
status: "running",
|
|
2738
|
+
// batchId is always returned so the caller can later filter by it —
|
|
2739
|
+
// even when the caller didn't supply one, a fresh id was generated.
|
|
2740
|
+
batchId: resolvedBatchId,
|
|
2202
2741
|
...agentName ? { agentName } : {},
|
|
2203
2742
|
...taskPreview ? { taskPreview } : {}
|
|
2204
2743
|
}),
|
|
@@ -2218,26 +2757,103 @@ function createCliControlAgentRunExecutor(deps = {}) {
|
|
|
2218
2757
|
const action = typeof args.action === "string" ? args.action : "";
|
|
2219
2758
|
const tailLines = typeof args.tailLines === "number" ? args.tailLines : 0;
|
|
2220
2759
|
if (action === "list") {
|
|
2221
|
-
|
|
2760
|
+
gcRunRecords(deps);
|
|
2761
|
+
const { runs: records, total, hasMore } = queryRunRecords(
|
|
2762
|
+
{
|
|
2763
|
+
...typeof args.batchId === "string" && args.batchId.trim() ? { batchId: args.batchId.trim() } : {},
|
|
2764
|
+
...typeof args.status === "string" && args.status.trim() ? { status: args.status.trim() } : typeof args.statusFilter === "string" && args.statusFilter.trim() ? { status: args.statusFilter.trim() } : {},
|
|
2765
|
+
...typeof args.limit === "number" ? { limit: args.limit } : {},
|
|
2766
|
+
...typeof args.offset === "number" ? { offset: args.offset } : {}
|
|
2767
|
+
},
|
|
2768
|
+
deps
|
|
2769
|
+
);
|
|
2222
2770
|
const runs = records.map((record2) => {
|
|
2223
|
-
const reconciled = checkStaleRun(record2.runId, deps) ?? record2;
|
|
2224
2771
|
return {
|
|
2225
|
-
runId:
|
|
2226
|
-
status:
|
|
2227
|
-
agentKey:
|
|
2228
|
-
...
|
|
2229
|
-
|
|
2230
|
-
|
|
2772
|
+
runId: record2.runId,
|
|
2773
|
+
status: record2.status,
|
|
2774
|
+
agentKey: record2.agentKey,
|
|
2775
|
+
...record2.agentName ? { agentName: record2.agentName } : {},
|
|
2776
|
+
...record2.batchId ? { batchId: record2.batchId } : {},
|
|
2777
|
+
pid: record2.pid ?? null,
|
|
2778
|
+
startedAt: record2.startedAt
|
|
2231
2779
|
};
|
|
2232
2780
|
});
|
|
2233
2781
|
const labels2 = agentRunCardLabels();
|
|
2782
|
+
const batchIdArg = typeof args.batchId === "string" && args.batchId.trim() ? args.batchId.trim() : void 0;
|
|
2783
|
+
let batchSummary;
|
|
2784
|
+
if (batchIdArg && records.length > 0) {
|
|
2785
|
+
const batchRuns = records.map((r) => ({
|
|
2786
|
+
runId: r.runId,
|
|
2787
|
+
status: r.status,
|
|
2788
|
+
startedAt: r.startedAt,
|
|
2789
|
+
...r.agentName ? { agentName: r.agentName } : {}
|
|
2790
|
+
}));
|
|
2791
|
+
batchSummary = aggregateBatch({
|
|
2792
|
+
batchId: batchIdArg,
|
|
2793
|
+
runs: batchRuns,
|
|
2794
|
+
now: new Date(resolveNowMs(deps)).toISOString()
|
|
2795
|
+
});
|
|
2796
|
+
}
|
|
2234
2797
|
return {
|
|
2235
|
-
content: JSON.stringify({
|
|
2798
|
+
content: JSON.stringify({
|
|
2799
|
+
runs,
|
|
2800
|
+
count: runs.length,
|
|
2801
|
+
total,
|
|
2802
|
+
hasMore,
|
|
2803
|
+
...batchSummary?.summary ? { batchSummary: batchSummary.summary } : {}
|
|
2804
|
+
}),
|
|
2236
2805
|
metadata: {
|
|
2237
2806
|
displayData: formatListRunsCard(runs, labels2)
|
|
2238
2807
|
}
|
|
2239
2808
|
};
|
|
2240
2809
|
}
|
|
2810
|
+
if (action === "todo") {
|
|
2811
|
+
const todoStore = resolveTodoStore(deps);
|
|
2812
|
+
const statusesRaw = typeof args.status === "string" ? args.status.trim() : void 0;
|
|
2813
|
+
const filter = statusesRaw && statusesRaw !== "all" ? { statuses: statusesRaw.split(",").map((s) => s.trim()).filter(Boolean) } : void 0;
|
|
2814
|
+
const todos = await todoStore.listTodos(filter);
|
|
2815
|
+
const enriched = await Promise.all(
|
|
2816
|
+
todos.map(async (todo) => {
|
|
2817
|
+
const runSummaries = [];
|
|
2818
|
+
for (const rid of todo.runIds) {
|
|
2819
|
+
const rec = findRunRecord(rid, deps);
|
|
2820
|
+
if (!rec) continue;
|
|
2821
|
+
runSummaries.push({
|
|
2822
|
+
runId: rec.runId,
|
|
2823
|
+
status: rec.status,
|
|
2824
|
+
startedAt: rec.startedAt,
|
|
2825
|
+
...rec.agentName ? { agentName: rec.agentName } : {}
|
|
2826
|
+
});
|
|
2827
|
+
}
|
|
2828
|
+
const derived = deriveTodoStatus({
|
|
2829
|
+
todo: { id: todo.id, status: todo.status },
|
|
2830
|
+
runs: runSummaries,
|
|
2831
|
+
now: new Date(resolveNowMs(deps)).toISOString()
|
|
2832
|
+
});
|
|
2833
|
+
return {
|
|
2834
|
+
id: todo.id,
|
|
2835
|
+
title: todo.title,
|
|
2836
|
+
status: derived.status,
|
|
2837
|
+
runIds: todo.runIds,
|
|
2838
|
+
...derived.blockedReason ? { blockedReason: derived.blockedReason } : {},
|
|
2839
|
+
...derived.latestRun ? { latestRunId: derived.latestRun.runId, latestRunStatus: derived.latestRun.status } : {},
|
|
2840
|
+
updatedAt: todo.updatedAt
|
|
2841
|
+
};
|
|
2842
|
+
})
|
|
2843
|
+
);
|
|
2844
|
+
return {
|
|
2845
|
+
content: JSON.stringify({ todos: enriched, count: enriched.length }),
|
|
2846
|
+
metadata: {
|
|
2847
|
+
displayData: formatListRunsCard(
|
|
2848
|
+
enriched.map((t2) => ({
|
|
2849
|
+
agentName: t2.title,
|
|
2850
|
+
status: t2.status
|
|
2851
|
+
})),
|
|
2852
|
+
agentRunCardLabels()
|
|
2853
|
+
)
|
|
2854
|
+
}
|
|
2855
|
+
};
|
|
2856
|
+
}
|
|
2241
2857
|
if (action !== "status" && action !== "stop") {
|
|
2242
2858
|
throw new Error(`controlAgentRun: \u672A\u77E5 action "${action}"\u3002`);
|
|
2243
2859
|
}
|
|
@@ -2256,6 +2872,25 @@ function createCliControlAgentRunExecutor(deps = {}) {
|
|
|
2256
2872
|
const name = resolveRunLabel(reconciled);
|
|
2257
2873
|
const logLines = logTail ? logTail.split("\n") : void 0;
|
|
2258
2874
|
const labels2 = agentRunCardLabels();
|
|
2875
|
+
if (reconciled.status === "failed" || reconciled.status === "orphaned") {
|
|
2876
|
+
try {
|
|
2877
|
+
const failureSource = logTail ?? reconciled.note ?? "";
|
|
2878
|
+
const failureInfo = classifyRunFailure(
|
|
2879
|
+
failureSource || reconciled.status
|
|
2880
|
+
);
|
|
2881
|
+
if (failureInfo.reason === "quota") {
|
|
2882
|
+
const t2 = resolveTarget(deps, reconciled.agentKey);
|
|
2883
|
+
const entry = buildBreakerEntry(
|
|
2884
|
+
resolveNowMs(deps),
|
|
2885
|
+
t2,
|
|
2886
|
+
"quota",
|
|
2887
|
+
failureInfo.retryAfterMs
|
|
2888
|
+
);
|
|
2889
|
+
resolveBreakerStore(deps).set(entry);
|
|
2890
|
+
}
|
|
2891
|
+
} catch {
|
|
2892
|
+
}
|
|
2893
|
+
}
|
|
2259
2894
|
return {
|
|
2260
2895
|
content: JSON.stringify({
|
|
2261
2896
|
runId: reconciled.runId,
|
|
@@ -2379,7 +3014,8 @@ function buildLocalToolExecutors(args) {
|
|
|
2379
3014
|
...buildServerPlatformToolExecutors({
|
|
2380
3015
|
env: args.env,
|
|
2381
3016
|
fetchImpl: args.fetchImpl,
|
|
2382
|
-
agentKey: args.agentKey
|
|
3017
|
+
agentKey: args.agentKey,
|
|
3018
|
+
memorySubjectId: args.memorySubjectId
|
|
2383
3019
|
}),
|
|
2384
3020
|
...buildCliWorkspaceToolExecutors({
|
|
2385
3021
|
env: args.env,
|
|
@@ -10420,9 +11056,9 @@ function createCliCallAgentToolExecutor(deps, ctx) {
|
|
|
10420
11056
|
// packages/cli/client/localRuntimeAdapter.ts
|
|
10421
11057
|
var currentMetaFile = fileURLToPath(import.meta.url);
|
|
10422
11058
|
var isJsBundle = extname(currentMetaFile) === ".js";
|
|
10423
|
-
var SOURCE_CLI_DIR = isJsBundle ?
|
|
10424
|
-
var CLI_DIR = isCompiledBinary() ?
|
|
10425
|
-
var CLI_ENTRYPOINT = isCompiledBinary() ? process.execPath : isJsBundle ? currentMetaFile :
|
|
11059
|
+
var SOURCE_CLI_DIR = isJsBundle ? dirname2(currentMetaFile) : dirname2(dirname2(currentMetaFile));
|
|
11060
|
+
var CLI_DIR = isCompiledBinary() ? dirname2(process.execPath) : SOURCE_CLI_DIR;
|
|
11061
|
+
var CLI_ENTRYPOINT = isCompiledBinary() ? process.execPath : isJsBundle ? currentMetaFile : join2(SOURCE_CLI_DIR, "index.ts");
|
|
10426
11062
|
function createCliLocalRuntimeAdapter(deps) {
|
|
10427
11063
|
const now = deps.now ?? Date.now;
|
|
10428
11064
|
const createId = deps.createId ?? createFallbackId;
|
|
@@ -11225,6 +11861,7 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
11225
11861
|
};
|
|
11226
11862
|
},
|
|
11227
11863
|
executeTool: async (call, opts) => {
|
|
11864
|
+
const contextualCall = opts?.runtimeContext ? { ...call, runtimeContext: opts.runtimeContext } : call;
|
|
11228
11865
|
assertWithinLocalToolBudget({
|
|
11229
11866
|
toolName: call.name,
|
|
11230
11867
|
budgets: localToolBudgets,
|
|
@@ -11233,7 +11870,7 @@ function createCliLocalRuntimeAdapter(deps) {
|
|
|
11233
11870
|
const result = await executeLocalToolWithPolicy({
|
|
11234
11871
|
env: deps.env,
|
|
11235
11872
|
agentToolNames: activeAgentToolNames,
|
|
11236
|
-
call,
|
|
11873
|
+
call: contextualCall,
|
|
11237
11874
|
executors: localToolExecutors,
|
|
11238
11875
|
abortSignal: opts?.abortSignal,
|
|
11239
11876
|
detachMs: resolveExecShellDetachMs(deps.env),
|
|
@@ -11262,6 +11899,8 @@ export {
|
|
|
11262
11899
|
t,
|
|
11263
11900
|
toolLabel,
|
|
11264
11901
|
agentRunCardLabels,
|
|
11902
|
+
QUOTA_ERROR_PATTERNS,
|
|
11903
|
+
isQuotaExhaustedError,
|
|
11265
11904
|
clearCliLocalRuntimePreparedAgentCache,
|
|
11266
11905
|
createCliCallAgentToolExecutor,
|
|
11267
11906
|
createCliLocalRuntimeAdapter
|