nolo-cli 0.54.0 → 0.61.0-alpha.3
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/README.md +3 -3
- package/{_executeModel-OPTKYHJA.js → _executeModel-R26QYY66.js} +50 -46
- package/{action-ORXWW2ZG.js → action-76JX3JX3.js} +7 -6
- package/{addContentAction-53BZ34AE.js → addContentAction-V3NAZRTJ.js} +6 -5
- package/{addDialogAgentAction-JRYUS54Y.js → addDialogAgentAction-RZOAF46K.js} +5 -4
- package/{agentDeleteCommand-FJIWU2BS.js → agentDeleteCommand-6GNQA4J4.js} +30 -27
- package/{agentEmailCommands-CE32L43B.js → agentEmailCommands-HH67CYKD.js} +61 -57
- package/{agentGrantCommands-2LEZDADN.js → agentGrantCommands-R3VQEZJR.js} +1 -1
- package/{agentListCommands-VJNKULIK.js → agentListCommands-23XW3OPZ.js} +61 -31
- package/{agentMachineCommands-HCJ3WQXL.js → agentMachineCommands-HXHASEWO.js} +31 -28
- package/{agentPullCommand-M552CYSI.js → agentPullCommand-N7L2CT7L.js} +2 -2
- package/{agentRecordCommands-QFWERED4.js → agentRecordCommands-UHTQJVGC.js} +59 -55
- package/{agentRunCommand-G3GQMUNN.js → agentRunCommand-OAMT77EX.js} +63 -59
- package/{agentRunControl-INKFDXDA.js → agentRunControl-WECMOO6O.js} +11 -6
- package/{agentRuntimeLocal-K327ELSL.js → agentRuntimeLocal-QBK4H3T2.js} +26 -23
- package/{agentSlice-ODKF4J6M.js → agentSlice-7XJH5WQF.js} +8 -7
- package/{appDeleteCommands-XUXMFDI4.js → appDeleteCommands-AX2O6VDV.js} +30 -27
- package/{appDeployCommands-37F4GPCU.js → appDeployCommands-L5ZR26CB.js} +30 -27
- package/{appDeployStatusCommands-WSPU7TUK.js → appDeployStatusCommands-5HQHELRA.js} +30 -27
- package/{appGetCommands-YLOBA3EM.js → appGetCommands-HVSYOS57.js} +30 -27
- package/{appListCommands-UD62R5ME.js → appListCommands-XV2FPTWX.js} +30 -27
- package/{authCommand-OK6HLHGS.js → authCommand-WOTWLJNF.js} +35 -29
- package/{authCommands-2DUIUEMT.js → authCommands-ILTBI6JV.js} +7 -5
- package/{chatQueueReduxAdapter-TV2TUOQS.js → chatQueueReduxAdapter-F3R253JE.js} +20 -18
- package/{chunk-HPW5MNDQ.js → chunk-22BTGNSP.js} +113 -57
- package/{chunk-UNZDCI3O.js → chunk-2KDR4CWE.js} +35 -4
- package/{chunk-3ZTR7ZO4.js → chunk-2PGGC63K.js} +1 -1
- package/{chunk-EA5OYZVD.js → chunk-37XDGCY7.js} +1 -1
- package/chunk-3BLB7QKO.js +433 -0
- package/{chunk-CS6TCJ7E.js → chunk-3JQ2NRYU.js} +30 -7
- package/{chunk-3LKZRP7E.js → chunk-3QGUVVX5.js} +2 -2
- package/{chunk-SSXTSPSG.js → chunk-45YO6H7P.js} +71 -30
- package/{chunk-YLCUU3WM.js → chunk-4NJEIGBQ.js} +5 -5
- package/{chunk-K4NISKOR.js → chunk-5ZYA4JJ3.js} +47 -17
- package/{chunk-6HIGYUBQ.js → chunk-6XIE5ZGI.js} +1 -1
- package/{chunk-3Y2K5O2R.js → chunk-7A3RRUCQ.js} +125 -40
- package/{chunk-6COJEAYH.js → chunk-7KELZLC2.js} +44 -37
- package/chunk-AETZ7AD6.js +274 -0
- package/chunk-BFU6C242.js +66 -0
- package/{chunk-IA3A5373.js → chunk-C3FZR5EC.js} +1 -1
- package/{chunk-IWUMSAQF.js → chunk-CJCJF5XB.js} +26 -3
- package/{chunk-UGBHDMHI.js → chunk-CP7VIDZ7.js} +1 -1
- package/{chunk-TR4DXUYX.js → chunk-CQ2OZMLQ.js} +1181 -737
- package/{chunk-JON2PHYT.js → chunk-CTCW7U7N.js} +1 -1
- package/{chunk-7NYDJAQ7.js → chunk-DNNSCSA2.js} +5 -5
- package/{chunk-NI2BS6UD.js → chunk-DWUCB2A3.js} +1 -1
- package/{chunk-FJHMLRDQ.js → chunk-DWYSDNOH.js} +22 -28
- package/{chunk-AA564GBL.js → chunk-E3YVTQWT.js} +2 -2
- package/chunk-E4MARS3Q.js +114 -0
- package/{chunk-75MSWWUE.js → chunk-E6RGHPDR.js} +5 -3
- package/chunk-EDKF7RX4.js +30 -0
- package/{chunk-TC6P4NDR.js → chunk-F44FAXP2.js} +6 -6
- package/{chunk-SYYUU7EV.js → chunk-FHAGENAS.js} +2 -3
- package/{chunk-NJUQBYFJ.js → chunk-FKFMIBTT.js} +3 -1
- package/{chunk-INZZJSQF.js → chunk-FZGV4FGK.js} +24 -12
- package/{chunk-6HDYSFLO.js → chunk-GSXDRMDO.js} +3 -3
- package/{chunk-AUVFJGPC.js → chunk-JX5PJCWS.js} +7 -5
- package/{chunk-LYGNQHUW.js → chunk-JYYZCK2Z.js} +2 -4
- package/{chunk-EY7V7REW.js → chunk-KHCLMKZZ.js} +6 -280
- package/{chunk-EJE33XNR.js → chunk-KSCXMC6U.js} +1521 -565
- package/{chunk-XOJRZUPF.js → chunk-KWSQR2KK.js} +14 -29
- package/{chunk-2WBFJHQA.js → chunk-L7B47JXR.js} +34 -39
- package/{chunk-EICIFHVS.js → chunk-LAFC3B2I.js} +1 -1
- package/{chunk-N4JKMCY3.js → chunk-LJKICKVC.js} +2 -2
- package/chunk-M3JEW6N6.js +193 -0
- package/{chunk-LRGKOI5Y.js → chunk-MBOEV4L2.js} +7 -3
- package/{chunk-SVDMVX4G.js → chunk-MMZ6ZTVO.js} +112 -73
- package/{chunk-JDSUTNYY.js → chunk-MP64VFGD.js} +2 -2
- package/{chunk-NFLA6GSU.js → chunk-MXUDQZXQ.js} +44 -5
- package/chunk-N4G4PKQ6.js +23 -0
- package/{chunk-WQHGJHAL.js → chunk-N6HLMLKE.js} +732 -726
- package/{chunk-YQBXOHE6.js → chunk-NO42UD73.js} +1 -1
- package/{chunk-MLEZPE3U.js → chunk-NRRPKMM7.js} +4 -4
- package/{chunk-KXKQO4Q6.js → chunk-NTW5GWDM.js} +58 -1
- package/chunk-ONXOABJR.js +215 -0
- package/{chunk-TY3ADTX5.js → chunk-OZX2IPKM.js} +7 -2
- package/{chunk-Q4XZVZPN.js → chunk-P7OOB7QP.js} +1 -1
- package/{chunk-XIJZOCSP.js → chunk-PEZJEQAO.js} +1 -1
- package/{chunk-SWJGJMTW.js → chunk-PQDIDWGX.js} +1 -1
- package/chunk-PSCNXBYA.js +11 -0
- package/{chunk-BY2FF2C4.js → chunk-QEFJJS2I.js} +55 -73
- package/{chunk-BG7J6Y5X.js → chunk-QEW2MFDQ.js} +1 -1
- package/{chunk-KLIBF3BY.js → chunk-RDBARW6T.js} +8 -3
- package/{chunk-ZVOHVJI3.js → chunk-RJ2SAFB5.js} +82 -35
- package/{chunk-MYMBBB6Q.js → chunk-RVWRKFUB.js} +5 -3
- package/{chunk-43CXXVJD.js → chunk-RXX4GDIH.js} +1 -1
- package/chunk-SEJ5OS6F.js +49 -0
- package/{chunk-JXIP6ZWH.js → chunk-SKIRVYEI.js} +18 -5
- package/{chunk-SAJSBPI2.js → chunk-SOJM57FX.js} +5 -2
- package/{chunk-EKLRRZIN.js → chunk-SPAQ4PVV.js} +0 -5
- package/{chunk-RHMDMTDK.js → chunk-SYNKICCB.js} +2 -2
- package/{chunk-YBFJQC2M.js → chunk-TBHAHL33.js} +65 -42
- package/{chunk-L7NG2M6H.js → chunk-TRV2MIDW.js} +89 -74
- package/{chunk-5UAYZEXO.js → chunk-UZPQSVM6.js} +1 -1
- package/{chunk-7FAS3NEF.js → chunk-VAKVNHK5.js} +19 -15
- package/{chunk-UOWXD4VN.js → chunk-VHO3TMQZ.js} +336 -244
- package/{chunk-SVC3GGUA.js → chunk-VMWYBIXG.js} +7 -5
- package/{chunk-ZHXJ6M7T.js → chunk-W7XHHYWM.js} +4 -0
- package/{chunk-UR66XPVF.js → chunk-XAVSS3KE.js} +21 -3
- package/{chunk-A65UV3M5.js → chunk-XOKOSO35.js} +10 -19
- package/{chunk-VZMUOPYG.js → chunk-XTJTN3RW.js} +46 -3
- package/{chunk-T5HJEUQN.js → chunk-YCDWJX45.js} +1 -1
- package/{chunk-BBTN4NQD.js → chunk-Z4QSJILV.js} +85 -13
- package/{chunk-5FCIPEKT.js → chunk-Z5MHFBJZ.js} +1051 -926
- package/{chunk-O5FLGN2L.js → chunk-ZRSJ3JEH.js} +6 -2
- package/{cliExecutor-BBUVQU4L.js → cliExecutor-HG3S345O.js} +1 -1
- package/{codingSkills-BCQXRZOI.js → codingSkills-TKROLCBA.js} +4 -3
- package/{contentThunks-KNI6VXLT.js → contentThunks-OZPK5B4Z.js} +21 -19
- package/{cooldownCommands-GI5NNWGL.js → cooldownCommands-BSCH2W7P.js} +2 -2
- package/{createAgentAutomationAction-OK4L33KF.js → createAgentAutomationAction-LCIBGE5T.js} +23 -21
- package/{createDialogAction-JDSMY4AY.js → createDialogAction-JPJZMHJE.js} +25 -22
- package/{createPageAction-T7RA3HCG.js → createPageAction-6P2WLNHO.js} +26 -23
- package/{dbSlice-TVX6SN2T.js → dbSlice-IBVOBVMS.js} +5 -4
- package/{deleteFile-JYKRT7C3.js → deleteFile-FWP2PSBG.js} +3 -2
- package/{dialogCommands-UQZYWOOV.js → dialogCommands-WAFKC3KK.js} +30 -27
- package/{dialogSlice-TYW2G7IL.js → dialogSlice-R5RZHFTU.js} +20 -18
- package/{docCreateCommands-OA6HZBWO.js → docCreateCommands-GHGB42S7.js} +32 -28
- package/{docDeleteCommands-KBB3YQI2.js → docDeleteCommands-Y5I7ZEX4.js} +33 -29
- package/{docReadCommands-ZLMFVC67.js → docReadCommands-BMXM6J7T.js} +32 -28
- package/{docStore-2URPBVCS.js → docStore-DKWZ6XJ5.js} +6 -5
- package/{docUpdateCommands-HMH5KUON.js → docUpdateCommands-QNABH3M2.js} +32 -28
- package/{getPricing-RFOPUWHY.js → getPricing-NM3NUTAS.js} +4 -4
- package/handleSendMessageAction-UQGKM4UX.js +675 -0
- package/index.js +79 -88
- package/{lib-2ZTNRXR4.js → lib-FRRS27KN.js} +63 -28
- package/{localRuntimeAuthority-KQDAE64E.js → localRuntimeAuthority-R5UBODT3.js} +6 -4
- package/{localRuntimeDb-PF7CFKDL.js → localRuntimeDb-P37ZTX55.js} +1 -1
- package/{machineCommands-RK6L7ZWL.js → machineCommands-YDAIPYU5.js} +298 -80
- package/{machineWsRunDispatch-3X64DW2Z.js → machineWsRunDispatch-O6RM2ECT.js} +57 -53
- package/{memberThunks-THZYZFSN.js → memberThunks-VZI6G7YZ.js} +10 -8
- package/{models-JVKUEER5.js → models-FAMINFZ7.js} +2 -2
- package/package.json +3 -2
- package/{read-K4JU4MQC.js → read-2BYWW7AA.js} +3 -2
- package/{readDocTool-LQGR6FUN.js → readDocTool-LC3A7QTB.js} +1 -1
- package/{readlineWorkspace-XUFJV3RS.js → readlineWorkspace-5DP3AJWN.js} +4367 -2796
- package/{removeDialogAgentAction-ECHCFB7N.js → removeDialogAgentAction-SFYZXHNK.js} +8 -7
- package/{runAgentClientLoop-24GQ2AW6.js → runAgentClientLoop-Y6HWP2PT.js} +51 -46
- package/{runtimeDoctorCommands-JKTTN723.js → runtimeDoctorCommands-CROTMULY.js} +7 -5
- package/{setDialogExtraReferencesAction-KCVJNGMB.js → setDialogExtraReferencesAction-Q32RGFTA.js} +6 -5
- package/{setPrimaryDialogAgentAction-VDOBOMKC.js → setPrimaryDialogAgentAction-BFYJHUJS.js} +8 -7
- package/{settingSlice-VR2IJSXC.js → settingSlice-IRUU4VFB.js} +6 -5
- package/{skillDiscovery-2QTZINON.js → skillDiscovery-CYUCJMAG.js} +2 -1
- package/{spaceCommands-S5YJJXL7.js → spaceCommands-CLN45IE3.js} +33 -215
- package/{streamAgentChatTurn-QHKP3ABO.js → streamAgentChatTurn-6WFQJ4DY.js} +107 -74
- package/{switchDialogAgentAction-5L4UP7VI.js → switchDialogAgentAction-L2KOKCGG.js} +5 -4
- package/{tableCommands-R6WFRDYF.js → tableCommands-SUNTHAYX.js} +1 -1
- package/{toolApiClient-53U4UDFF.js → toolApiClient-VGYUB4P5.js} +2 -1
- package/{tools-SSXSTC3O.js → tools-RR53D65Q.js} +39 -35
- package/{tuiSummaryLlmCaller-URFJHFC5.js → tuiSummaryLlmCaller-F3DPFFZM.js} +15 -13
- package/{updateCommands-IYKLF3JX.js → updateCommands-AJYSD73Y.js} +2 -2
- package/{updateDialogTitleAction-YFYAEW3T.js → updateDialogTitleAction-WXS3AKOL.js} +23 -21
- package/agentSuperviseCommands-5AR3DKNN.js +0 -640
- package/chunk-6IGD47IC.js +0 -19
- package/chunk-FD36SCCD.js +0 -105
- package/chunk-GRFK2XP4.js +0 -230
- package/chunk-HJTAGT3W.js +0 -370
- package/chunk-SUEIAK5N.js +0 -2574
- package/handleSendMessageAction-GO53TY7U.js +0 -409
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isOAuthApiKeyRef
|
|
3
|
+
} from "./chunk-YYLHWIW6.js";
|
|
4
|
+
import {
|
|
5
|
+
compareAgentSelection
|
|
6
|
+
} from "./chunk-RJ2SAFB5.js";
|
|
7
|
+
import {
|
|
8
|
+
getModelAbility
|
|
9
|
+
} from "./chunk-FKFMIBTT.js";
|
|
10
|
+
import {
|
|
11
|
+
isOwnedAgentKey,
|
|
12
|
+
ownedAgentKey,
|
|
13
|
+
publicAgentKey
|
|
14
|
+
} from "./chunk-BJIRLHJR.js";
|
|
15
|
+
|
|
16
|
+
// packages/ai/agent/agentBilling.ts
|
|
17
|
+
function resolveBillingSource(candidate) {
|
|
18
|
+
if (candidate?.local === true || candidate?.isLocal === true || candidate?.cliProvider === "local" || candidate?.apiSource === "local" || candidate?.provider === "local" || candidate?.billingSource === "local") return "local";
|
|
19
|
+
if (candidate?.isOwned !== true) return "platform_credits";
|
|
20
|
+
if (candidate?.isOAuth === true || candidate?.billingSource === "user_subscription" || candidate?.apiSource === "oauth" || isOAuthApiKeyRef(candidate?.apiKeyRef)) return "user_subscription";
|
|
21
|
+
if (candidate?.apiSource === "custom" || candidate?.billingSource === "user_api") {
|
|
22
|
+
return "user_api";
|
|
23
|
+
}
|
|
24
|
+
return "platform_credits";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// packages/ai/economics/economicsPolicy.ts
|
|
28
|
+
var DEEPSEEK_PRICING_DOC = "https://api-docs.deepseek.com/quick_start/pricing";
|
|
29
|
+
var BIGMODEL_CODING_PLAN_USAGE_NOTES = "https://docs.bigmodel.cn/cn/coding-plan/usage-notes";
|
|
30
|
+
var WEEKDAYS_MON_FRI = [1, 2, 3, 4, 5];
|
|
31
|
+
var DEEPSEEK_API_POLICY = {
|
|
32
|
+
id: "deepseek_api",
|
|
33
|
+
version: "2026-09-weekday-utc-peak-2x",
|
|
34
|
+
windows: [
|
|
35
|
+
{ timezone: "UTC", weekdays: WEEKDAYS_MON_FRI, startMinute: 60, endMinute: 240 },
|
|
36
|
+
{ timezone: "UTC", weekdays: WEEKDAYS_MON_FRI, startMinute: 360, endMinute: 600 }
|
|
37
|
+
],
|
|
38
|
+
effectiveFrom: Date.UTC(2026, 7, 16, 16, 0, 0),
|
|
39
|
+
peakPriceMultiplier: 2,
|
|
40
|
+
offPeakPriceMultiplier: 1,
|
|
41
|
+
sourceUrl: DEEPSEEK_PRICING_DOC
|
|
42
|
+
};
|
|
43
|
+
var BIGMODEL_GLM_CODING_PLAN_POLICY = {
|
|
44
|
+
id: "bigmodel_glm_coding_plan",
|
|
45
|
+
version: "2026-09-coding-plan-sh-peak-14-18",
|
|
46
|
+
windows: [
|
|
47
|
+
{ timezone: "Asia/Shanghai", weekdays: WEEKDAYS_MON_FRI, startMinute: 840, endMinute: 1080 }
|
|
48
|
+
],
|
|
49
|
+
peakQuotaMultiplier: 1,
|
|
50
|
+
offPeakQuotaMultiplier: 0.5,
|
|
51
|
+
sourceUrl: BIGMODEL_CODING_PLAN_USAGE_NOTES
|
|
52
|
+
};
|
|
53
|
+
var ECONOMICS_POLICIES = [
|
|
54
|
+
DEEPSEEK_API_POLICY,
|
|
55
|
+
BIGMODEL_GLM_CODING_PLAN_POLICY
|
|
56
|
+
];
|
|
57
|
+
function resolveEconomicsSourceId(input) {
|
|
58
|
+
const provider = typeof input?.provider === "string" ? input.provider.trim().toLowerCase() : "";
|
|
59
|
+
if (input?.apiSource?.trim().toLowerCase() === "platform") return null;
|
|
60
|
+
const rawUrl = typeof input?.customProviderUrl === "string" ? input.customProviderUrl.trim() : "";
|
|
61
|
+
let hostname = "";
|
|
62
|
+
let pathname = "";
|
|
63
|
+
if (rawUrl) {
|
|
64
|
+
try {
|
|
65
|
+
const parsed = new URL(rawUrl);
|
|
66
|
+
hostname = parsed.hostname.toLowerCase();
|
|
67
|
+
pathname = parsed.pathname;
|
|
68
|
+
} catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (provider === "deepseek") {
|
|
73
|
+
if (rawUrl && hostname !== "api.deepseek.com") return null;
|
|
74
|
+
return rawUrl ? "deepseek_api" : null;
|
|
75
|
+
}
|
|
76
|
+
if (provider === "bigmodel") {
|
|
77
|
+
if (hostname === "open.bigmodel.cn" && pathname.startsWith("/api/coding/")) {
|
|
78
|
+
return "bigmodel_glm_coding_plan";
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// packages/ai/economics/economicsSnapshot.ts
|
|
86
|
+
var wallClockFormatterCache = /* @__PURE__ */ new Map();
|
|
87
|
+
function getWallClockFormatter(timezone) {
|
|
88
|
+
let formatter = wallClockFormatterCache.get(timezone);
|
|
89
|
+
if (!formatter) {
|
|
90
|
+
formatter = new Intl.DateTimeFormat("en-US", {
|
|
91
|
+
timeZone: timezone,
|
|
92
|
+
hourCycle: "h23",
|
|
93
|
+
year: "numeric",
|
|
94
|
+
month: "2-digit",
|
|
95
|
+
day: "2-digit",
|
|
96
|
+
hour: "2-digit",
|
|
97
|
+
minute: "2-digit",
|
|
98
|
+
second: "2-digit"
|
|
99
|
+
});
|
|
100
|
+
wallClockFormatterCache.set(timezone, formatter);
|
|
101
|
+
}
|
|
102
|
+
return formatter;
|
|
103
|
+
}
|
|
104
|
+
function getZonedWallClock(timezone, at) {
|
|
105
|
+
const parts = getWallClockFormatter(timezone).formatToParts(new Date(at));
|
|
106
|
+
const values = {};
|
|
107
|
+
for (const part of parts) {
|
|
108
|
+
if (part.type !== "literal") values[part.type] = Number(part.value);
|
|
109
|
+
}
|
|
110
|
+
const year = values.year;
|
|
111
|
+
const month = values.month;
|
|
112
|
+
const day = values.day;
|
|
113
|
+
const hour = values.hour;
|
|
114
|
+
const minute = values.minute;
|
|
115
|
+
const second = values.second;
|
|
116
|
+
const weekday = new Date(Date.UTC(year, month - 1, day)).getUTCDay();
|
|
117
|
+
return { year, month, day, hour, minute, second, weekday, minutesOfDay: hour * 60 + minute };
|
|
118
|
+
}
|
|
119
|
+
function getTimeZoneOffsetMs(timezone, at) {
|
|
120
|
+
const atSecond = Math.floor(at / 1e3) * 1e3;
|
|
121
|
+
const clock = getZonedWallClock(timezone, atSecond);
|
|
122
|
+
return Date.UTC(clock.year, clock.month - 1, clock.day, clock.hour, clock.minute, clock.second) - atSecond;
|
|
123
|
+
}
|
|
124
|
+
function zonedWallClockToEpochMs(timezone, year, month, day, minutesOfDay) {
|
|
125
|
+
const guess = Date.UTC(year, month - 1, day, Math.floor(minutesOfDay / 60), minutesOfDay % 60);
|
|
126
|
+
let instant = guess - getTimeZoneOffsetMs(timezone, guess);
|
|
127
|
+
instant = guess - getTimeZoneOffsetMs(timezone, instant);
|
|
128
|
+
return instant;
|
|
129
|
+
}
|
|
130
|
+
function resolveEconomicsPeriod(policy, at) {
|
|
131
|
+
for (const window of policy.windows) {
|
|
132
|
+
const clock = getZonedWallClock(window.timezone, at);
|
|
133
|
+
if (!window.weekdays.includes(clock.weekday)) continue;
|
|
134
|
+
if (clock.minutesOfDay >= window.startMinute && clock.minutesOfDay < window.endMinute) {
|
|
135
|
+
return "peak";
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return "off_peak";
|
|
139
|
+
}
|
|
140
|
+
function findNextEconomicsBoundary(policy, at) {
|
|
141
|
+
let best;
|
|
142
|
+
for (const window of policy.windows) {
|
|
143
|
+
const anchor = getZonedWallClock(window.timezone, at);
|
|
144
|
+
for (let dayOffset = 0; dayOffset <= 7; dayOffset++) {
|
|
145
|
+
const dayUtc = new Date(Date.UTC(anchor.year, anchor.month - 1, anchor.day + dayOffset));
|
|
146
|
+
const weekday = dayUtc.getUTCDay();
|
|
147
|
+
if (!window.weekdays.includes(weekday)) continue;
|
|
148
|
+
const year = dayUtc.getUTCFullYear();
|
|
149
|
+
const month = dayUtc.getUTCMonth() + 1;
|
|
150
|
+
const day = dayUtc.getUTCDate();
|
|
151
|
+
for (const edge of [window.startMinute, window.endMinute]) {
|
|
152
|
+
const instant = zonedWallClockToEpochMs(window.timezone, year, month, day, edge);
|
|
153
|
+
if (instant > at && (best === void 0 || instant < best)) best = instant;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return best;
|
|
158
|
+
}
|
|
159
|
+
function selectEconomicsPolicyVersion(policies, sourceId, at) {
|
|
160
|
+
const applicable = policies.filter(
|
|
161
|
+
(policy) => policy.id === sourceId && (policy.effectiveFrom === void 0 || policy.effectiveFrom <= at) && (policy.effectiveUntil === void 0 || at < policy.effectiveUntil)
|
|
162
|
+
);
|
|
163
|
+
if (applicable.length === 0) return null;
|
|
164
|
+
return applicable.reduce(
|
|
165
|
+
(latest, candidate) => (candidate.effectiveFrom ?? -Infinity) >= (latest.effectiveFrom ?? -Infinity) ? candidate : latest
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
function findNextPolicyBoundary(policy, at, policies) {
|
|
169
|
+
const boundaries = [
|
|
170
|
+
policy.effectiveUntil,
|
|
171
|
+
...policies.filter((candidate) => candidate.id === policy.id).map((candidate) => candidate.effectiveFrom).filter((value) => value !== void 0 && value > at)
|
|
172
|
+
].filter((value) => value !== void 0 && value > at);
|
|
173
|
+
return boundaries.length > 0 ? Math.min(...boundaries) : void 0;
|
|
174
|
+
}
|
|
175
|
+
function resolveEconomicsSnapshot(input, at, policies = ECONOMICS_POLICIES) {
|
|
176
|
+
const sourceId = resolveEconomicsSourceId(input);
|
|
177
|
+
if (!sourceId) return null;
|
|
178
|
+
const policy = selectEconomicsPolicyVersion(policies, sourceId, at);
|
|
179
|
+
if (!policy) return null;
|
|
180
|
+
const period = resolveEconomicsPeriod(policy, at);
|
|
181
|
+
const priceMultiplier = period === "peak" ? policy.peakPriceMultiplier : policy.offPeakPriceMultiplier;
|
|
182
|
+
const quotaMultiplier = period === "peak" ? policy.peakQuotaMultiplier : policy.offPeakQuotaMultiplier;
|
|
183
|
+
const windowBoundary = findNextEconomicsBoundary(policy, at);
|
|
184
|
+
const policyBoundary = findNextPolicyBoundary(policy, at, policies);
|
|
185
|
+
const changesAt = [windowBoundary, policyBoundary].filter((value) => value !== void 0).sort((a, b) => a - b)[0];
|
|
186
|
+
return {
|
|
187
|
+
source: sourceId,
|
|
188
|
+
policyVersion: policy.version,
|
|
189
|
+
period,
|
|
190
|
+
...priceMultiplier !== void 0 ? { priceMultiplier } : {},
|
|
191
|
+
...quotaMultiplier !== void 0 ? { quotaMultiplier } : {},
|
|
192
|
+
...changesAt !== void 0 ? { changesAt } : {}
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// packages/ai/agent/safeAgentSummary.ts
|
|
197
|
+
function parseTimestamp(val) {
|
|
198
|
+
if (typeof val === "number" && Number.isFinite(val)) return val;
|
|
199
|
+
if (typeof val === "string") return Date.parse(val) || 0;
|
|
200
|
+
return 0;
|
|
201
|
+
}
|
|
202
|
+
function safeTimestamp(val) {
|
|
203
|
+
if (typeof val === "number" && Number.isFinite(val)) return val;
|
|
204
|
+
if (typeof val === "string") return val;
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
function parseAgentRecordId(privateKey, explicitId) {
|
|
208
|
+
if (explicitId && typeof explicitId === "string" && explicitId.trim()) {
|
|
209
|
+
return explicitId.trim();
|
|
210
|
+
}
|
|
211
|
+
if (privateKey && typeof privateKey === "string") {
|
|
212
|
+
const match = privateKey.match(/^agent-[^-]+-(.+)$/i);
|
|
213
|
+
if (match?.[1]) return match[1];
|
|
214
|
+
}
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
function resolveFavoriteStatus(record, options) {
|
|
218
|
+
if (options?.isFavorite !== void 0) {
|
|
219
|
+
return {
|
|
220
|
+
isFavorite: !!options.isFavorite,
|
|
221
|
+
favoritedAt: safeTimestamp(options.favoritedAt)
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
if (record?.isFavorite === true) {
|
|
225
|
+
return {
|
|
226
|
+
isFavorite: true,
|
|
227
|
+
favoritedAt: safeTimestamp(record?.favoritedAt)
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
const favoritesMap = options?.favoritesMap;
|
|
231
|
+
if (!favoritesMap) {
|
|
232
|
+
return { isFavorite: false, favoritedAt: null };
|
|
233
|
+
}
|
|
234
|
+
const candidateKeys = [];
|
|
235
|
+
if (typeof record?.dbKey === "string" && record.dbKey) candidateKeys.push(record.dbKey);
|
|
236
|
+
if (typeof record?.privateKey === "string" && record.privateKey) candidateKeys.push(record.privateKey);
|
|
237
|
+
if (typeof record?.publicKey === "string" && record.publicKey) candidateKeys.push(record.publicKey);
|
|
238
|
+
if (typeof record?.id === "string" && record.id) {
|
|
239
|
+
candidateKeys.push(record.id);
|
|
240
|
+
candidateKeys.push(publicAgentKey(record.id));
|
|
241
|
+
if (options?.userId) {
|
|
242
|
+
candidateKeys.push(ownedAgentKey(options.userId, record.id));
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
let matched = false;
|
|
246
|
+
let highestFavAt = null;
|
|
247
|
+
let highestFavTime = -1;
|
|
248
|
+
for (const key of candidateKeys) {
|
|
249
|
+
const val = favoritesMap instanceof Map ? favoritesMap.get(key) : favoritesMap[key];
|
|
250
|
+
if (val !== void 0 && val !== false && val !== null) {
|
|
251
|
+
const favAt = val === true ? 1 : safeTimestamp(val);
|
|
252
|
+
if (favAt === null) continue;
|
|
253
|
+
matched = true;
|
|
254
|
+
const time = parseTimestamp(favAt);
|
|
255
|
+
if (time > highestFavTime) {
|
|
256
|
+
highestFavTime = time;
|
|
257
|
+
highestFavAt = favAt;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (matched) {
|
|
262
|
+
return {
|
|
263
|
+
isFavorite: true,
|
|
264
|
+
favoritedAt: highestFavAt ?? 1
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
return { isFavorite: false, favoritedAt: null };
|
|
268
|
+
}
|
|
269
|
+
function toSafeAgentSummary(record, options) {
|
|
270
|
+
const rawId = parseAgentRecordId(
|
|
271
|
+
typeof record?.privateKey === "string" ? record.privateKey : record?.dbKey,
|
|
272
|
+
typeof record?.id === "string" ? record.id : void 0
|
|
273
|
+
);
|
|
274
|
+
const id = rawId ?? (typeof record?.id === "string" ? record.id : null);
|
|
275
|
+
const publicRecordDenied = record?.publicRecordExists === false || options?.publicRecordExists === false;
|
|
276
|
+
const publicRecordConfirmed = record?.publicRecordExists === true || options?.publicRecordExists === true;
|
|
277
|
+
let publicKey;
|
|
278
|
+
if (typeof record?.publicKey === "string" && record.publicKey && !publicRecordDenied) {
|
|
279
|
+
publicKey = record.publicKey;
|
|
280
|
+
} else if (publicRecordConfirmed && id) {
|
|
281
|
+
publicKey = publicAgentKey(id);
|
|
282
|
+
}
|
|
283
|
+
const name = typeof record?.name === "string" && record.name ? record.name : "(unnamed)";
|
|
284
|
+
const handle = typeof record?.handle === "string" && record.handle ? record.handle : null;
|
|
285
|
+
const introduction = typeof record?.introduction === "string" && record.introduction ? record.introduction : typeof record?.description === "string" && record.description ? record.description : null;
|
|
286
|
+
const model = typeof record?.model === "string" && record.model ? record.model : null;
|
|
287
|
+
const provider = typeof record?.provider === "string" && record.provider ? record.provider : typeof record?.apiSource === "string" && record.apiSource ? record.apiSource : null;
|
|
288
|
+
const apiSource = typeof record?.apiSource === "string" && record.apiSource ? record.apiSource : null;
|
|
289
|
+
const cliProvider = typeof record?.cliProvider === "string" && record.cliProvider ? record.cliProvider : null;
|
|
290
|
+
const tools = Array.isArray(record?.tools) ? record.tools.filter((t) => typeof t === "string") : [];
|
|
291
|
+
const inputPrice = typeof record?.inputPrice === "number" && Number.isFinite(record.inputPrice) ? record.inputPrice : null;
|
|
292
|
+
const outputPrice = typeof record?.outputPrice === "number" && Number.isFinite(record.outputPrice) ? record.outputPrice : null;
|
|
293
|
+
const modelAbility = model ? getModelAbility(model) ?? null : null;
|
|
294
|
+
const favStatus = resolveFavoriteStatus(record, options);
|
|
295
|
+
const isPublic = record?.isPublic === true || record?.isPublicFlag === true || record?.publicRecordExists === true;
|
|
296
|
+
const updatedAt = safeTimestamp(record?.updatedAt ?? record?.createdAt ?? record?.created);
|
|
297
|
+
const nextAvailableAt = typeof record?.nextAvailableAt === "number" && Number.isFinite(record.nextAvailableAt) ? record.nextAvailableAt : void 0;
|
|
298
|
+
const currentUserId = options?.userId;
|
|
299
|
+
const isOwnedByRecord = Boolean(currentUserId) && (typeof record?.userId === "string" && record.userId === currentUserId || typeof record?.ownerId === "string" && record.ownerId === currentUserId);
|
|
300
|
+
const ownedKey = currentUserId ? [record?.dbKey, record?.privateKey].find(
|
|
301
|
+
(key) => isOwnedAgentKey(key, currentUserId)
|
|
302
|
+
) : void 0;
|
|
303
|
+
const isOwned = isOwnedByRecord || Boolean(ownedKey);
|
|
304
|
+
const isOAuth = isOAuthApiKeyRef(record?.apiKeyRef);
|
|
305
|
+
const billingSource = resolveBillingSource({
|
|
306
|
+
...record,
|
|
307
|
+
isOAuth,
|
|
308
|
+
isOwned,
|
|
309
|
+
apiSource,
|
|
310
|
+
cliProvider,
|
|
311
|
+
provider,
|
|
312
|
+
isPublic
|
|
313
|
+
});
|
|
314
|
+
const economics = resolveEconomicsSnapshot(
|
|
315
|
+
{
|
|
316
|
+
provider,
|
|
317
|
+
apiSource,
|
|
318
|
+
customProviderUrl: typeof record?.customProviderUrl === "string" ? record.customProviderUrl : null
|
|
319
|
+
},
|
|
320
|
+
options?.now ?? Date.now()
|
|
321
|
+
);
|
|
322
|
+
let agentKey;
|
|
323
|
+
if (currentUserId) {
|
|
324
|
+
if (isOwned) {
|
|
325
|
+
agentKey = ownedKey ?? (id ? ownedAgentKey(currentUserId, id) : void 0);
|
|
326
|
+
} else if (publicKey) {
|
|
327
|
+
agentKey = publicKey;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return {
|
|
331
|
+
id,
|
|
332
|
+
...agentKey !== void 0 ? { agentKey } : {},
|
|
333
|
+
...publicKey !== void 0 ? { publicKey } : {},
|
|
334
|
+
name,
|
|
335
|
+
handle,
|
|
336
|
+
introduction,
|
|
337
|
+
model,
|
|
338
|
+
provider,
|
|
339
|
+
apiSource,
|
|
340
|
+
cliProvider,
|
|
341
|
+
billingSource,
|
|
342
|
+
tools,
|
|
343
|
+
inputPrice,
|
|
344
|
+
outputPrice,
|
|
345
|
+
modelAbility,
|
|
346
|
+
isFavorite: favStatus.isFavorite,
|
|
347
|
+
favoritedAt: favStatus.favoritedAt,
|
|
348
|
+
isPublic,
|
|
349
|
+
...economics ? { economics } : {},
|
|
350
|
+
isOwned,
|
|
351
|
+
isOAuth,
|
|
352
|
+
...nextAvailableAt !== void 0 ? { nextAvailableAt } : {},
|
|
353
|
+
updatedAt
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
function sortSafeAgentSummaries(agents) {
|
|
357
|
+
return [...agents].sort(compareAgentSelection);
|
|
358
|
+
}
|
|
359
|
+
var COMPACT_AGENT_SUMMARY_FIELDS = [
|
|
360
|
+
"agentKey",
|
|
361
|
+
"name",
|
|
362
|
+
"model",
|
|
363
|
+
"provider",
|
|
364
|
+
"apiSource",
|
|
365
|
+
"billingSource",
|
|
366
|
+
"isFavorite",
|
|
367
|
+
"isOAuth",
|
|
368
|
+
"isOwned",
|
|
369
|
+
"isPublic",
|
|
370
|
+
"tools",
|
|
371
|
+
// Phase 2A economics 快照(period/multipliers/changesAt 等小对象)。
|
|
372
|
+
// 只对 DeepSeek API / BigModel GLM Coding Plan 存在;不含完整 policy/windows。
|
|
373
|
+
"economics",
|
|
374
|
+
// 仅限流中的 agent 才会带(可用 agent 上不存在)。对"现在能不能选它"是
|
|
375
|
+
// 决策信息(CLI --show-unavailable 场景);默认列表已把这类 agent 过滤掉,
|
|
376
|
+
// 所以通常根本不占字节。
|
|
377
|
+
"nextAvailableAt"
|
|
378
|
+
];
|
|
379
|
+
function omitNullishAgentSummaryFields(summary) {
|
|
380
|
+
const result = {};
|
|
381
|
+
for (const [key, value] of Object.entries(summary)) {
|
|
382
|
+
if (value !== null && value !== void 0) {
|
|
383
|
+
result[key] = value;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
return result;
|
|
387
|
+
}
|
|
388
|
+
function toCompactAgentSummary(summary) {
|
|
389
|
+
const compact = {};
|
|
390
|
+
for (const field of COMPACT_AGENT_SUMMARY_FIELDS) {
|
|
391
|
+
const value = summary[field];
|
|
392
|
+
if (value !== null && value !== void 0) {
|
|
393
|
+
compact[field] = value;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
return compact;
|
|
397
|
+
}
|
|
398
|
+
var UNAVAILABLE_AGENT_SUMMARY_FIELDS = [
|
|
399
|
+
"agentKey",
|
|
400
|
+
"name",
|
|
401
|
+
"model",
|
|
402
|
+
"provider",
|
|
403
|
+
"apiSource",
|
|
404
|
+
"isFavorite",
|
|
405
|
+
"isOAuth",
|
|
406
|
+
"isOwned",
|
|
407
|
+
"nextAvailableAt",
|
|
408
|
+
"favoritedAt",
|
|
409
|
+
"updatedAt"
|
|
410
|
+
];
|
|
411
|
+
function toUnavailableAgentSummary(summary) {
|
|
412
|
+
const item = {
|
|
413
|
+
name: summary.name,
|
|
414
|
+
isFavorite: summary.isFavorite,
|
|
415
|
+
isOAuth: summary.isOAuth,
|
|
416
|
+
isOwned: summary.isOwned
|
|
417
|
+
};
|
|
418
|
+
for (const field of UNAVAILABLE_AGENT_SUMMARY_FIELDS) {
|
|
419
|
+
const value = summary[field];
|
|
420
|
+
if (value !== null && value !== void 0) {
|
|
421
|
+
item[field] = value;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
return item;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
export {
|
|
428
|
+
toSafeAgentSummary,
|
|
429
|
+
sortSafeAgentSummaries,
|
|
430
|
+
omitNullishAgentSummaryFields,
|
|
431
|
+
toCompactAgentSummary,
|
|
432
|
+
toUnavailableAgentSummary
|
|
433
|
+
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
-
getCredentialsDir
|
|
3
|
-
|
|
2
|
+
getCredentialsDir,
|
|
3
|
+
getLegacyCredentialPath,
|
|
4
|
+
migrateLegacyCredentialFile
|
|
5
|
+
} from "./chunk-ONXOABJR.js";
|
|
4
6
|
import {
|
|
5
7
|
asNonEmptyStringArray
|
|
6
8
|
} from "./chunk-I42VC5KR.js";
|
|
@@ -23,6 +25,7 @@ import {
|
|
|
23
25
|
unlinkSync,
|
|
24
26
|
writeFileSync
|
|
25
27
|
} from "node:fs";
|
|
28
|
+
import { homedir } from "node:os";
|
|
26
29
|
import { join } from "node:path";
|
|
27
30
|
|
|
28
31
|
// packages/agent-runtime/credentialBroker.ts
|
|
@@ -65,7 +68,26 @@ function writePrivateFile(path, body) {
|
|
|
65
68
|
} catch {
|
|
66
69
|
}
|
|
67
70
|
}
|
|
68
|
-
function
|
|
71
|
+
function migrateApiKeyCredentialIfNeeded(ref, homeDir, migration) {
|
|
72
|
+
if (homeDir !== void 0 || !migration?.enableLegacyMigration) return;
|
|
73
|
+
const legacyHomeDir = migration.legacyHomeDir ?? homedir();
|
|
74
|
+
const relativePath = join("keys", credentialRefToFileName(ref));
|
|
75
|
+
migrateLegacyCredentialFile({
|
|
76
|
+
canonicalPath: getApiKeyCredentialPath(ref),
|
|
77
|
+
legacyPath: getLegacyCredentialPath(relativePath, legacyHomeDir),
|
|
78
|
+
mode: migration.mode ?? (migration.legacyHomeDir ? "test" : "production"),
|
|
79
|
+
isValid: (raw) => {
|
|
80
|
+
try {
|
|
81
|
+
const parsed = JSON.parse(raw);
|
|
82
|
+
return typeof parsed?.secret === "string" && Boolean(parsed.secret);
|
|
83
|
+
} catch {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
function readApiKeyCredential(ref, homeDir, migration) {
|
|
90
|
+
migrateApiKeyCredentialIfNeeded(ref, homeDir, migration);
|
|
69
91
|
const path = getApiKeyCredentialPath(ref, homeDir);
|
|
70
92
|
if (!existsSync(path)) return null;
|
|
71
93
|
try {
|
|
@@ -99,15 +121,16 @@ function removeApiKeyCredential(ref, homeDir) {
|
|
|
99
121
|
if (!existsSync(path)) return;
|
|
100
122
|
unlinkSync(path);
|
|
101
123
|
}
|
|
102
|
-
function hasApiKeyCredential(ref, homeDir) {
|
|
103
|
-
return readApiKeyCredential(ref, homeDir) !== null;
|
|
124
|
+
function hasApiKeyCredential(ref, homeDir, migration) {
|
|
125
|
+
return readApiKeyCredential(ref, homeDir, migration) !== null;
|
|
104
126
|
}
|
|
105
127
|
function createFileCredentialBroker(options = {}) {
|
|
106
128
|
const homeDir = options.homeDir;
|
|
129
|
+
const migration = options.migration;
|
|
107
130
|
const now = options.now ?? Date.now;
|
|
108
131
|
return {
|
|
109
132
|
get(ref) {
|
|
110
|
-
return readApiKeyCredential(ref, homeDir);
|
|
133
|
+
return readApiKeyCredential(ref, homeDir, migration);
|
|
111
134
|
},
|
|
112
135
|
put(ref, secret) {
|
|
113
136
|
writeApiKeyCredential(ref, secret, homeDir, now());
|
|
@@ -116,7 +139,7 @@ function createFileCredentialBroker(options = {}) {
|
|
|
116
139
|
removeApiKeyCredential(ref, homeDir);
|
|
117
140
|
},
|
|
118
141
|
has(ref) {
|
|
119
|
-
return hasApiKeyCredential(ref, homeDir);
|
|
142
|
+
return hasApiKeyCredential(ref, homeDir, migration);
|
|
120
143
|
}
|
|
121
144
|
};
|
|
122
145
|
}
|
|
@@ -6,10 +6,10 @@ import {
|
|
|
6
6
|
} from "./chunk-AGGIDPCZ.js";
|
|
7
7
|
import {
|
|
8
8
|
getModelConfig
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-MMZ6ZTVO.js";
|
|
10
10
|
import {
|
|
11
11
|
isPlatformHostedImageModel
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-22BTGNSP.js";
|
|
13
13
|
import {
|
|
14
14
|
asOptionalFiniteNumber
|
|
15
15
|
} from "./chunk-WWC7I6TA.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isAgentRunTerminalStatus
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-NTW5GWDM.js";
|
|
4
4
|
import {
|
|
5
5
|
isCompiledBinary,
|
|
6
6
|
resolveCliEntrypointPath
|
|
@@ -335,12 +335,6 @@ async function popQueueMessages(queuePath, depsOrFs = {}) {
|
|
|
335
335
|
const entries = await popAllQueueEntries(queuePath, depsOrFs);
|
|
336
336
|
return entries.map((e) => e.text);
|
|
337
337
|
}
|
|
338
|
-
function resolveRunReportPath(runId, env, homedir = nodeHomedir) {
|
|
339
|
-
return join(resolveRunsDir(env, homedir), `${runId}.report.md`);
|
|
340
|
-
}
|
|
341
|
-
function resolveRunReportJsonPath(runId, env, homedir = nodeHomedir) {
|
|
342
|
-
return join(resolveRunsDir(env, homedir), `${runId}.report.json`);
|
|
343
|
-
}
|
|
344
338
|
function defaultGenerateRunId() {
|
|
345
339
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
346
340
|
const random = Math.random().toString(36).slice(2, 8);
|
|
@@ -602,8 +596,6 @@ async function gcRunRecords(deps = {}, options = {}) {
|
|
|
602
596
|
const jsonPath = resolveRunRecordPath(record.runId, deps.env, deps.homedir);
|
|
603
597
|
const logPath = resolveRunLogPath(record.runId, deps.env, deps.homedir);
|
|
604
598
|
const queuePath = record.queuePath ?? resolveRunQueuePath(record.runId, deps.env, deps.homedir);
|
|
605
|
-
const reportPath = resolveRunReportPath(record.runId, deps.env, deps.homedir);
|
|
606
|
-
const reportJsonPath = resolveRunReportJsonPath(record.runId, deps.env, deps.homedir);
|
|
607
599
|
const msgPath = record.msgFile ?? join(resolveRunsDir(deps.env, deps.homedir), `${record.runId}.msg.md`);
|
|
608
600
|
const logOk = tryUnlinkFile(fs, logPath);
|
|
609
601
|
const msgOk = tryUnlinkFile(fs, msgPath);
|
|
@@ -617,8 +609,9 @@ async function gcRunRecords(deps = {}, options = {}) {
|
|
|
617
609
|
queueOk = false;
|
|
618
610
|
}
|
|
619
611
|
}
|
|
620
|
-
|
|
621
|
-
tryUnlinkFile(fs,
|
|
612
|
+
const runsDirForLegacy = resolveRunsDir(deps.env, deps.homedir);
|
|
613
|
+
tryUnlinkFile(fs, join(runsDirForLegacy, `${record.runId}.report.md`));
|
|
614
|
+
tryUnlinkFile(fs, join(runsDirForLegacy, `${record.runId}.report.json`));
|
|
622
615
|
if (!logOk || !msgOk || !queueOk) {
|
|
623
616
|
failedIds.push(record.runId);
|
|
624
617
|
continue;
|
|
@@ -897,21 +890,60 @@ function releaseRunRecordAck(runId, token, deps = {}) {
|
|
|
897
890
|
writeRunRecord(record, deps);
|
|
898
891
|
});
|
|
899
892
|
}
|
|
900
|
-
function
|
|
901
|
-
withRunRecordLock(runId, deps, () => {
|
|
902
|
-
const
|
|
903
|
-
if (!
|
|
893
|
+
function transitionRunToTerminal(runId, update, deps = {}, options = {}) {
|
|
894
|
+
const settled = withRunRecordLock(runId, deps, () => {
|
|
895
|
+
const record2 = readRunRecord(runId, deps);
|
|
896
|
+
if (!record2) return { kind: "not_found" };
|
|
897
|
+
const orphanCorrection = options.allowOverOrphaned === true && record2.status === "orphaned" && (update.status === "done" || update.status === "failed");
|
|
898
|
+
if (isAgentRunTerminalStatus(record2.status) && !orphanCorrection) {
|
|
899
|
+
return { kind: "kept", record: record2 };
|
|
900
|
+
}
|
|
904
901
|
const now = deps.now ?? (() => /* @__PURE__ */ new Date());
|
|
905
|
-
|
|
906
|
-
if (typeof update.exitCode === "number")
|
|
907
|
-
if (update.dialogId)
|
|
902
|
+
record2.status = update.status;
|
|
903
|
+
if (typeof update.exitCode === "number") record2.exitCode = update.exitCode;
|
|
904
|
+
if (update.dialogId) record2.dialogId = update.dialogId;
|
|
908
905
|
if (typeof update.credits === "number" && Number.isFinite(update.credits)) {
|
|
909
|
-
|
|
906
|
+
record2.credits = update.credits;
|
|
910
907
|
}
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
908
|
+
if (update.dodResults && update.dodResults.length > 0) {
|
|
909
|
+
record2.dodResults = update.dodResults;
|
|
910
|
+
}
|
|
911
|
+
record2.endedAt = now().toISOString();
|
|
912
|
+
if (typeof update.note === "string" && update.note.trim()) {
|
|
913
|
+
record2.note = update.note.trim();
|
|
914
|
+
}
|
|
915
|
+
if (record2.note?.startsWith("orphaned:")) record2.note = void 0;
|
|
916
|
+
writeRunRecord(record2, deps);
|
|
917
|
+
return { kind: "transitioned", record: record2 };
|
|
918
|
+
}, { strict: true });
|
|
919
|
+
if (settled !== void 0) return settled;
|
|
920
|
+
const record = readRunRecord(runId, deps);
|
|
921
|
+
if (!record) return { kind: "not_found" };
|
|
922
|
+
if (isAgentRunTerminalStatus(record.status)) return { kind: "kept", record };
|
|
923
|
+
return { kind: "contended", record };
|
|
924
|
+
}
|
|
925
|
+
var AUTHORITATIVE_SETTLE_MAX_ATTEMPTS = 4;
|
|
926
|
+
var AUTHORITATIVE_SETTLE_RETRY_DELAY_MS = 15;
|
|
927
|
+
async function settleRunTerminalAuthoritatively(runId, update, deps = {}, transition = transitionRunToTerminal) {
|
|
928
|
+
const attempt = () => transition(runId, update, deps, { allowOverOrphaned: true });
|
|
929
|
+
let result = attempt();
|
|
930
|
+
for (let attemptNo = 1; result?.kind === "contended" && attemptNo < AUTHORITATIVE_SETTLE_MAX_ATTEMPTS; attemptNo += 1) {
|
|
931
|
+
await (deps.sleep ?? defaultSleep)(AUTHORITATIVE_SETTLE_RETRY_DELAY_MS);
|
|
932
|
+
result = attempt();
|
|
933
|
+
}
|
|
934
|
+
if (result?.kind === "contended") {
|
|
935
|
+
console.error(
|
|
936
|
+
`[nolo] authoritative settlement for run ${runId} lost the record lock ${AUTHORITATIVE_SETTLE_MAX_ATTEMPTS} times; durable record still ${result.record.status} \u2014 terminal status pending reconcile, child outcome (exitCode/dialogId/credits/DoD) may be lost`
|
|
937
|
+
);
|
|
938
|
+
} else if (result?.kind === "kept" && result.record.status !== update.status) {
|
|
939
|
+
console.warn(
|
|
940
|
+
`[nolo] run ${runId} already terminal (${result.record.status}); keeping the durable outcome over intended ${update.status}`
|
|
941
|
+
);
|
|
942
|
+
}
|
|
943
|
+
return result ?? { kind: "not_found" };
|
|
944
|
+
}
|
|
945
|
+
function finalizeRunRecord(runId, update, deps = {}) {
|
|
946
|
+
transitionRunToTerminal(runId, update, deps);
|
|
915
947
|
}
|
|
916
948
|
function isPidGone(pid, deps = {}) {
|
|
917
949
|
const kill = deps.kill ?? ((p, s) => process.kill(p, s));
|
|
@@ -1349,12 +1381,18 @@ async function runSignalCommand(args, signal, verb, deps) {
|
|
|
1349
1381
|
`);
|
|
1350
1382
|
return 1;
|
|
1351
1383
|
}
|
|
1352
|
-
|
|
1353
|
-
|
|
1384
|
+
const reconciled = checkStaleRun(record.runId, deps) ?? record;
|
|
1385
|
+
if (isAgentRunTerminalStatus(reconciled.status)) {
|
|
1386
|
+
deps.output.write(`Run ${reconciled.runId} is already ${reconciled.status}.
|
|
1387
|
+
`);
|
|
1388
|
+
return 0;
|
|
1389
|
+
}
|
|
1390
|
+
if (typeof reconciled.pid !== "number") {
|
|
1391
|
+
deps.output.write(`Run has no pid: ${reconciled.runId}
|
|
1354
1392
|
`);
|
|
1355
1393
|
return 1;
|
|
1356
1394
|
}
|
|
1357
|
-
const confirmed = await terminateRunProcess(
|
|
1395
|
+
const confirmed = await terminateRunProcess(reconciled, signal, deps);
|
|
1358
1396
|
if (!confirmed) {
|
|
1359
1397
|
deps.output.write(
|
|
1360
1398
|
`Failed to ${verb} ${record.runId} (pid ${record.pid}): process still alive after SIGKILL.
|
|
@@ -1362,9 +1400,10 @@ async function runSignalCommand(args, signal, verb, deps) {
|
|
|
1362
1400
|
);
|
|
1363
1401
|
return 1;
|
|
1364
1402
|
}
|
|
1365
|
-
|
|
1403
|
+
const transition = transitionRunToTerminal(reconciled.runId, { status: "killed" }, deps);
|
|
1366
1404
|
deps.output.write(
|
|
1367
|
-
`Stopped ${
|
|
1405
|
+
transition.kind === "contended" ? `Stopped ${reconciled.runId} (pid ${reconciled.pid}): process group confirmed gone; terminal status pending reconcile.
|
|
1406
|
+
` : `Stopped ${reconciled.runId} (pid ${reconciled.pid}): process group confirmed gone.
|
|
1368
1407
|
`
|
|
1369
1408
|
);
|
|
1370
1409
|
return 0;
|
|
@@ -1404,8 +1443,6 @@ export {
|
|
|
1404
1443
|
popAllQueueEntries,
|
|
1405
1444
|
popSingleQueueMessage,
|
|
1406
1445
|
popQueueMessages,
|
|
1407
|
-
resolveRunReportPath,
|
|
1408
|
-
resolveRunReportJsonPath,
|
|
1409
1446
|
defaultGenerateRunId,
|
|
1410
1447
|
defaultGenerateBatchId,
|
|
1411
1448
|
writeRunRecord,
|
|
@@ -1432,6 +1469,10 @@ export {
|
|
|
1432
1469
|
claimRunRecord,
|
|
1433
1470
|
commitRunRecordClaim,
|
|
1434
1471
|
releaseRunRecordAck,
|
|
1472
|
+
transitionRunToTerminal,
|
|
1473
|
+
AUTHORITATIVE_SETTLE_MAX_ATTEMPTS,
|
|
1474
|
+
AUTHORITATIVE_SETTLE_RETRY_DELAY_MS,
|
|
1475
|
+
settleRunTerminalAuthoritatively,
|
|
1435
1476
|
finalizeRunRecord,
|
|
1436
1477
|
isPidGone,
|
|
1437
1478
|
defaultGetProcessStartTime,
|