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.
Files changed (158) hide show
  1. package/README.md +3 -3
  2. package/{_executeModel-OPTKYHJA.js → _executeModel-R26QYY66.js} +50 -46
  3. package/{action-ORXWW2ZG.js → action-76JX3JX3.js} +7 -6
  4. package/{addContentAction-53BZ34AE.js → addContentAction-V3NAZRTJ.js} +6 -5
  5. package/{addDialogAgentAction-JRYUS54Y.js → addDialogAgentAction-RZOAF46K.js} +5 -4
  6. package/{agentDeleteCommand-FJIWU2BS.js → agentDeleteCommand-6GNQA4J4.js} +30 -27
  7. package/{agentEmailCommands-CE32L43B.js → agentEmailCommands-HH67CYKD.js} +61 -57
  8. package/{agentGrantCommands-2LEZDADN.js → agentGrantCommands-R3VQEZJR.js} +1 -1
  9. package/{agentListCommands-VJNKULIK.js → agentListCommands-23XW3OPZ.js} +61 -31
  10. package/{agentMachineCommands-HCJ3WQXL.js → agentMachineCommands-HXHASEWO.js} +31 -28
  11. package/{agentPullCommand-M552CYSI.js → agentPullCommand-N7L2CT7L.js} +2 -2
  12. package/{agentRecordCommands-QFWERED4.js → agentRecordCommands-UHTQJVGC.js} +59 -55
  13. package/{agentRunCommand-G3GQMUNN.js → agentRunCommand-OAMT77EX.js} +63 -59
  14. package/{agentRunControl-INKFDXDA.js → agentRunControl-WECMOO6O.js} +11 -6
  15. package/{agentRuntimeLocal-K327ELSL.js → agentRuntimeLocal-QBK4H3T2.js} +26 -23
  16. package/{agentSlice-ODKF4J6M.js → agentSlice-7XJH5WQF.js} +8 -7
  17. package/{appDeleteCommands-XUXMFDI4.js → appDeleteCommands-AX2O6VDV.js} +30 -27
  18. package/{appDeployCommands-37F4GPCU.js → appDeployCommands-L5ZR26CB.js} +30 -27
  19. package/{appDeployStatusCommands-WSPU7TUK.js → appDeployStatusCommands-5HQHELRA.js} +30 -27
  20. package/{appGetCommands-YLOBA3EM.js → appGetCommands-HVSYOS57.js} +30 -27
  21. package/{appListCommands-UD62R5ME.js → appListCommands-XV2FPTWX.js} +30 -27
  22. package/{authCommand-OK6HLHGS.js → authCommand-WOTWLJNF.js} +35 -29
  23. package/{authCommands-2DUIUEMT.js → authCommands-ILTBI6JV.js} +7 -5
  24. package/{chatQueueReduxAdapter-TV2TUOQS.js → chatQueueReduxAdapter-F3R253JE.js} +20 -18
  25. package/{chunk-HPW5MNDQ.js → chunk-22BTGNSP.js} +113 -57
  26. package/{chunk-UNZDCI3O.js → chunk-2KDR4CWE.js} +35 -4
  27. package/{chunk-3ZTR7ZO4.js → chunk-2PGGC63K.js} +1 -1
  28. package/{chunk-EA5OYZVD.js → chunk-37XDGCY7.js} +1 -1
  29. package/chunk-3BLB7QKO.js +433 -0
  30. package/{chunk-CS6TCJ7E.js → chunk-3JQ2NRYU.js} +30 -7
  31. package/{chunk-3LKZRP7E.js → chunk-3QGUVVX5.js} +2 -2
  32. package/{chunk-SSXTSPSG.js → chunk-45YO6H7P.js} +71 -30
  33. package/{chunk-YLCUU3WM.js → chunk-4NJEIGBQ.js} +5 -5
  34. package/{chunk-K4NISKOR.js → chunk-5ZYA4JJ3.js} +47 -17
  35. package/{chunk-6HIGYUBQ.js → chunk-6XIE5ZGI.js} +1 -1
  36. package/{chunk-3Y2K5O2R.js → chunk-7A3RRUCQ.js} +125 -40
  37. package/{chunk-6COJEAYH.js → chunk-7KELZLC2.js} +44 -37
  38. package/chunk-AETZ7AD6.js +274 -0
  39. package/chunk-BFU6C242.js +66 -0
  40. package/{chunk-IA3A5373.js → chunk-C3FZR5EC.js} +1 -1
  41. package/{chunk-IWUMSAQF.js → chunk-CJCJF5XB.js} +26 -3
  42. package/{chunk-UGBHDMHI.js → chunk-CP7VIDZ7.js} +1 -1
  43. package/{chunk-TR4DXUYX.js → chunk-CQ2OZMLQ.js} +1181 -737
  44. package/{chunk-JON2PHYT.js → chunk-CTCW7U7N.js} +1 -1
  45. package/{chunk-7NYDJAQ7.js → chunk-DNNSCSA2.js} +5 -5
  46. package/{chunk-NI2BS6UD.js → chunk-DWUCB2A3.js} +1 -1
  47. package/{chunk-FJHMLRDQ.js → chunk-DWYSDNOH.js} +22 -28
  48. package/{chunk-AA564GBL.js → chunk-E3YVTQWT.js} +2 -2
  49. package/chunk-E4MARS3Q.js +114 -0
  50. package/{chunk-75MSWWUE.js → chunk-E6RGHPDR.js} +5 -3
  51. package/chunk-EDKF7RX4.js +30 -0
  52. package/{chunk-TC6P4NDR.js → chunk-F44FAXP2.js} +6 -6
  53. package/{chunk-SYYUU7EV.js → chunk-FHAGENAS.js} +2 -3
  54. package/{chunk-NJUQBYFJ.js → chunk-FKFMIBTT.js} +3 -1
  55. package/{chunk-INZZJSQF.js → chunk-FZGV4FGK.js} +24 -12
  56. package/{chunk-6HDYSFLO.js → chunk-GSXDRMDO.js} +3 -3
  57. package/{chunk-AUVFJGPC.js → chunk-JX5PJCWS.js} +7 -5
  58. package/{chunk-LYGNQHUW.js → chunk-JYYZCK2Z.js} +2 -4
  59. package/{chunk-EY7V7REW.js → chunk-KHCLMKZZ.js} +6 -280
  60. package/{chunk-EJE33XNR.js → chunk-KSCXMC6U.js} +1521 -565
  61. package/{chunk-XOJRZUPF.js → chunk-KWSQR2KK.js} +14 -29
  62. package/{chunk-2WBFJHQA.js → chunk-L7B47JXR.js} +34 -39
  63. package/{chunk-EICIFHVS.js → chunk-LAFC3B2I.js} +1 -1
  64. package/{chunk-N4JKMCY3.js → chunk-LJKICKVC.js} +2 -2
  65. package/chunk-M3JEW6N6.js +193 -0
  66. package/{chunk-LRGKOI5Y.js → chunk-MBOEV4L2.js} +7 -3
  67. package/{chunk-SVDMVX4G.js → chunk-MMZ6ZTVO.js} +112 -73
  68. package/{chunk-JDSUTNYY.js → chunk-MP64VFGD.js} +2 -2
  69. package/{chunk-NFLA6GSU.js → chunk-MXUDQZXQ.js} +44 -5
  70. package/chunk-N4G4PKQ6.js +23 -0
  71. package/{chunk-WQHGJHAL.js → chunk-N6HLMLKE.js} +732 -726
  72. package/{chunk-YQBXOHE6.js → chunk-NO42UD73.js} +1 -1
  73. package/{chunk-MLEZPE3U.js → chunk-NRRPKMM7.js} +4 -4
  74. package/{chunk-KXKQO4Q6.js → chunk-NTW5GWDM.js} +58 -1
  75. package/chunk-ONXOABJR.js +215 -0
  76. package/{chunk-TY3ADTX5.js → chunk-OZX2IPKM.js} +7 -2
  77. package/{chunk-Q4XZVZPN.js → chunk-P7OOB7QP.js} +1 -1
  78. package/{chunk-XIJZOCSP.js → chunk-PEZJEQAO.js} +1 -1
  79. package/{chunk-SWJGJMTW.js → chunk-PQDIDWGX.js} +1 -1
  80. package/chunk-PSCNXBYA.js +11 -0
  81. package/{chunk-BY2FF2C4.js → chunk-QEFJJS2I.js} +55 -73
  82. package/{chunk-BG7J6Y5X.js → chunk-QEW2MFDQ.js} +1 -1
  83. package/{chunk-KLIBF3BY.js → chunk-RDBARW6T.js} +8 -3
  84. package/{chunk-ZVOHVJI3.js → chunk-RJ2SAFB5.js} +82 -35
  85. package/{chunk-MYMBBB6Q.js → chunk-RVWRKFUB.js} +5 -3
  86. package/{chunk-43CXXVJD.js → chunk-RXX4GDIH.js} +1 -1
  87. package/chunk-SEJ5OS6F.js +49 -0
  88. package/{chunk-JXIP6ZWH.js → chunk-SKIRVYEI.js} +18 -5
  89. package/{chunk-SAJSBPI2.js → chunk-SOJM57FX.js} +5 -2
  90. package/{chunk-EKLRRZIN.js → chunk-SPAQ4PVV.js} +0 -5
  91. package/{chunk-RHMDMTDK.js → chunk-SYNKICCB.js} +2 -2
  92. package/{chunk-YBFJQC2M.js → chunk-TBHAHL33.js} +65 -42
  93. package/{chunk-L7NG2M6H.js → chunk-TRV2MIDW.js} +89 -74
  94. package/{chunk-5UAYZEXO.js → chunk-UZPQSVM6.js} +1 -1
  95. package/{chunk-7FAS3NEF.js → chunk-VAKVNHK5.js} +19 -15
  96. package/{chunk-UOWXD4VN.js → chunk-VHO3TMQZ.js} +336 -244
  97. package/{chunk-SVC3GGUA.js → chunk-VMWYBIXG.js} +7 -5
  98. package/{chunk-ZHXJ6M7T.js → chunk-W7XHHYWM.js} +4 -0
  99. package/{chunk-UR66XPVF.js → chunk-XAVSS3KE.js} +21 -3
  100. package/{chunk-A65UV3M5.js → chunk-XOKOSO35.js} +10 -19
  101. package/{chunk-VZMUOPYG.js → chunk-XTJTN3RW.js} +46 -3
  102. package/{chunk-T5HJEUQN.js → chunk-YCDWJX45.js} +1 -1
  103. package/{chunk-BBTN4NQD.js → chunk-Z4QSJILV.js} +85 -13
  104. package/{chunk-5FCIPEKT.js → chunk-Z5MHFBJZ.js} +1051 -926
  105. package/{chunk-O5FLGN2L.js → chunk-ZRSJ3JEH.js} +6 -2
  106. package/{cliExecutor-BBUVQU4L.js → cliExecutor-HG3S345O.js} +1 -1
  107. package/{codingSkills-BCQXRZOI.js → codingSkills-TKROLCBA.js} +4 -3
  108. package/{contentThunks-KNI6VXLT.js → contentThunks-OZPK5B4Z.js} +21 -19
  109. package/{cooldownCommands-GI5NNWGL.js → cooldownCommands-BSCH2W7P.js} +2 -2
  110. package/{createAgentAutomationAction-OK4L33KF.js → createAgentAutomationAction-LCIBGE5T.js} +23 -21
  111. package/{createDialogAction-JDSMY4AY.js → createDialogAction-JPJZMHJE.js} +25 -22
  112. package/{createPageAction-T7RA3HCG.js → createPageAction-6P2WLNHO.js} +26 -23
  113. package/{dbSlice-TVX6SN2T.js → dbSlice-IBVOBVMS.js} +5 -4
  114. package/{deleteFile-JYKRT7C3.js → deleteFile-FWP2PSBG.js} +3 -2
  115. package/{dialogCommands-UQZYWOOV.js → dialogCommands-WAFKC3KK.js} +30 -27
  116. package/{dialogSlice-TYW2G7IL.js → dialogSlice-R5RZHFTU.js} +20 -18
  117. package/{docCreateCommands-OA6HZBWO.js → docCreateCommands-GHGB42S7.js} +32 -28
  118. package/{docDeleteCommands-KBB3YQI2.js → docDeleteCommands-Y5I7ZEX4.js} +33 -29
  119. package/{docReadCommands-ZLMFVC67.js → docReadCommands-BMXM6J7T.js} +32 -28
  120. package/{docStore-2URPBVCS.js → docStore-DKWZ6XJ5.js} +6 -5
  121. package/{docUpdateCommands-HMH5KUON.js → docUpdateCommands-QNABH3M2.js} +32 -28
  122. package/{getPricing-RFOPUWHY.js → getPricing-NM3NUTAS.js} +4 -4
  123. package/handleSendMessageAction-UQGKM4UX.js +675 -0
  124. package/index.js +79 -88
  125. package/{lib-2ZTNRXR4.js → lib-FRRS27KN.js} +63 -28
  126. package/{localRuntimeAuthority-KQDAE64E.js → localRuntimeAuthority-R5UBODT3.js} +6 -4
  127. package/{localRuntimeDb-PF7CFKDL.js → localRuntimeDb-P37ZTX55.js} +1 -1
  128. package/{machineCommands-RK6L7ZWL.js → machineCommands-YDAIPYU5.js} +298 -80
  129. package/{machineWsRunDispatch-3X64DW2Z.js → machineWsRunDispatch-O6RM2ECT.js} +57 -53
  130. package/{memberThunks-THZYZFSN.js → memberThunks-VZI6G7YZ.js} +10 -8
  131. package/{models-JVKUEER5.js → models-FAMINFZ7.js} +2 -2
  132. package/package.json +3 -2
  133. package/{read-K4JU4MQC.js → read-2BYWW7AA.js} +3 -2
  134. package/{readDocTool-LQGR6FUN.js → readDocTool-LC3A7QTB.js} +1 -1
  135. package/{readlineWorkspace-XUFJV3RS.js → readlineWorkspace-5DP3AJWN.js} +4367 -2796
  136. package/{removeDialogAgentAction-ECHCFB7N.js → removeDialogAgentAction-SFYZXHNK.js} +8 -7
  137. package/{runAgentClientLoop-24GQ2AW6.js → runAgentClientLoop-Y6HWP2PT.js} +51 -46
  138. package/{runtimeDoctorCommands-JKTTN723.js → runtimeDoctorCommands-CROTMULY.js} +7 -5
  139. package/{setDialogExtraReferencesAction-KCVJNGMB.js → setDialogExtraReferencesAction-Q32RGFTA.js} +6 -5
  140. package/{setPrimaryDialogAgentAction-VDOBOMKC.js → setPrimaryDialogAgentAction-BFYJHUJS.js} +8 -7
  141. package/{settingSlice-VR2IJSXC.js → settingSlice-IRUU4VFB.js} +6 -5
  142. package/{skillDiscovery-2QTZINON.js → skillDiscovery-CYUCJMAG.js} +2 -1
  143. package/{spaceCommands-S5YJJXL7.js → spaceCommands-CLN45IE3.js} +33 -215
  144. package/{streamAgentChatTurn-QHKP3ABO.js → streamAgentChatTurn-6WFQJ4DY.js} +107 -74
  145. package/{switchDialogAgentAction-5L4UP7VI.js → switchDialogAgentAction-L2KOKCGG.js} +5 -4
  146. package/{tableCommands-R6WFRDYF.js → tableCommands-SUNTHAYX.js} +1 -1
  147. package/{toolApiClient-53U4UDFF.js → toolApiClient-VGYUB4P5.js} +2 -1
  148. package/{tools-SSXSTC3O.js → tools-RR53D65Q.js} +39 -35
  149. package/{tuiSummaryLlmCaller-URFJHFC5.js → tuiSummaryLlmCaller-F3DPFFZM.js} +15 -13
  150. package/{updateCommands-IYKLF3JX.js → updateCommands-AJYSD73Y.js} +2 -2
  151. package/{updateDialogTitleAction-YFYAEW3T.js → updateDialogTitleAction-WXS3AKOL.js} +23 -21
  152. package/agentSuperviseCommands-5AR3DKNN.js +0 -640
  153. package/chunk-6IGD47IC.js +0 -19
  154. package/chunk-FD36SCCD.js +0 -105
  155. package/chunk-GRFK2XP4.js +0 -230
  156. package/chunk-HJTAGT3W.js +0 -370
  157. package/chunk-SUEIAK5N.js +0 -2574
  158. 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
- } from "./chunk-FD36SCCD.js";
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 readApiKeyCredential(ref, homeDir) {
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-SVDMVX4G.js";
9
+ } from "./chunk-MMZ6ZTVO.js";
10
10
  import {
11
11
  isPlatformHostedImageModel
12
- } from "./chunk-HPW5MNDQ.js";
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-KXKQO4Q6.js";
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
- tryUnlinkFile(fs, reportPath);
621
- tryUnlinkFile(fs, reportJsonPath);
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 finalizeRunRecord(runId, update, deps = {}) {
901
- withRunRecordLock(runId, deps, () => {
902
- const record = readRunRecord(runId, deps);
903
- if (!record) return;
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
- record.status = update.status;
906
- if (typeof update.exitCode === "number") record.exitCode = update.exitCode;
907
- if (update.dialogId) record.dialogId = 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
- record.credits = update.credits;
906
+ record2.credits = update.credits;
910
907
  }
911
- record.endedAt = now().toISOString();
912
- if (record.note?.startsWith("orphaned:")) record.note = void 0;
913
- writeRunRecord(record, deps);
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
- if (typeof record.pid !== "number") {
1353
- deps.output.write(`Run has no pid: ${record.runId}
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(record, signal, deps);
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
- finalizeRunRecord(record.runId, { status: "killed" }, deps);
1403
+ const transition = transitionRunToTerminal(reconciled.runId, { status: "killed" }, deps);
1366
1404
  deps.output.write(
1367
- `Stopped ${record.runId} (pid ${record.pid}): process group confirmed gone.
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,