@desplega.ai/agent-swarm 1.166.0 → 1.167.0

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 (194) hide show
  1. package/dist/acp-adapter-zpvy6321.js +34 -0
  2. package/dist/{actions-qz3m692w.js → actions-fq2zrwtf.js} +25 -25
  3. package/dist/{amp-adapter-j1xbmsqz.js → amp-adapter-5gbk7501.js} +4 -4
  4. package/dist/{anthropic-messages-hst62ws9.js → anthropic-messages-13yn502s.js} +4 -4
  5. package/dist/{app-43vrdmv8.js → app-nctetn1e.js} +10 -9
  6. package/dist/{assistant-ertffmka.js → assistant-0aq8gjvj.js} +26 -26
  7. package/dist/{azure-openai-responses-mh8tvf78.js → azure-openai-responses-9st34pfz.js} +5 -5
  8. package/dist/{boot-reembed-998jtpdg.js → boot-reembed-1ze5853n.js} +9 -8
  9. package/dist/{boot-reembed-s7k7c6v2.js → boot-reembed-fmp5ww69.js} +9 -8
  10. package/dist/{boot-scrub-sweep-nepsk4t1.js → boot-scrub-sweep-cbp8xd4e.js} +10 -9
  11. package/dist/{boot-seeds-vvzs1zhk.js → boot-seeds-22tx8a53.js} +12 -11
  12. package/dist/{claude-adapter-2zvmekrp.js → claude-adapter-0jhgeh1d.js} +24 -22
  13. package/dist/{claude-managed-adapter-s49wbk8t.js → claude-managed-adapter-tzwxy803.js} +4 -4
  14. package/dist/{claude-managed-setup-cvhqq8qn.js → claude-managed-setup-nrhfx5b0.js} +3 -3
  15. package/dist/{claude-sdk-session-kkbxtw5q.js → claude-sdk-session-wh77rh83.js} +22 -22
  16. package/dist/{cli-zsh093hk.js → cli-014vns2y.js} +63 -1
  17. package/dist/{cli-qvfk83fy.js → cli-13xwcqvj.js} +2 -2
  18. package/dist/{cli-dw2q9f7g.js → cli-1yrcfa5s.js} +4 -4
  19. package/dist/{cli-jvj6a0cv.js → cli-577bxkf6.js} +27 -17
  20. package/dist/{cli-zy7vwsne.js → cli-5qkcdv8c.js} +16 -9
  21. package/dist/{cli-cwxhbf43.js → cli-5t5my0h8.js} +85 -2
  22. package/dist/{cli-y59h2pk9.js → cli-69egj654.js} +1 -1
  23. package/dist/{cli-68r1j4sg.js → cli-6bpvv8h4.js} +3 -3
  24. package/dist/{cli-cpfmqz3n.js → cli-6qxmjpem.js} +5 -5
  25. package/dist/{cli-aqcey741.js → cli-6vfz44sr.js} +1 -1
  26. package/dist/{cli-32bca7nr.js → cli-7avy4v8w.js} +1 -1
  27. package/dist/{cli-f2n17zhp.js → cli-7mhy3ths.js} +21 -18
  28. package/dist/{cli-q38n4bq0.js → cli-95zs84qw.js} +3 -3
  29. package/dist/cli-a35hzdve.js +33 -0
  30. package/dist/{cli-x3x0qwky.js → cli-bxqez1p0.js} +51 -23
  31. package/dist/{cli-gt8azyet.js → cli-c2tpw9ck.js} +1 -1
  32. package/dist/{cli-ecknp7p1.js → cli-c8r99akr.js} +10 -10
  33. package/dist/{cli-3qn4r334.js → cli-cexctgn5.js} +20 -14
  34. package/dist/{cli-vzc73wet.js → cli-cf2vgn9d.js} +87 -69
  35. package/dist/{cli-ng97fjq7.js → cli-cmxkbzzs.js} +33 -7
  36. package/dist/{cli-nexwh8zg.js → cli-g7k7zbcz.js} +12 -5
  37. package/dist/{cli-nvvfd8bq.js → cli-jbzbr36n.js} +4091 -3793
  38. package/dist/{cli-3ddybbbx.js → cli-jvmtxqtc.js} +26 -14
  39. package/dist/{cli-pkke6geq.js → cli-km4x66j0.js} +83 -65
  40. package/dist/{cli-j2jbr8af.js → cli-kw0jcfje.js} +1 -1
  41. package/dist/{cli-8t229cmr.js → cli-m7vmeepg.js} +30 -17
  42. package/dist/{cli-yshaazs1.js → cli-mkdsy1nq.js} +62 -20
  43. package/dist/{cli-b0f70z24.js → cli-mn8qkd8v.js} +1 -1
  44. package/dist/{cli-0qjcsxgz.js → cli-mxry91sa.js} +30 -9
  45. package/dist/cli-nkqjj42q.js +104 -0
  46. package/dist/{cli-rggdq8wq.js → cli-p8rt8spp.js} +3 -3
  47. package/dist/{cli-v2a8x45d.js → cli-pkj1w46r.js} +10 -5
  48. package/dist/cli-q1vnz8wv.js +96 -0
  49. package/dist/{cli-fj86xr3c.js → cli-qd97v6z2.js} +2 -2
  50. package/dist/{cli-66zh26sp.js → cli-qzmzwegq.js} +57 -17
  51. package/dist/{cli-p4ztb80h.js → cli-r7eeddkq.js} +13 -8
  52. package/dist/{cli-8ssjez7e.js → cli-rhy7z1rp.js} +22 -11
  53. package/dist/{cli-4mevd1hf.js → cli-s9y81s7j.js} +5 -5
  54. package/dist/{cli-h3x613ze.js → cli-tc5zec7v.js} +6 -6
  55. package/dist/{cli-ttbsse3f.js → cli-tmhsxhb8.js} +1 -1
  56. package/dist/{cli-0nhdwxd5.js → cli-tx2zvn23.js} +3 -3
  57. package/dist/{cli-mwegs4af.js → cli-ty4bzkqr.js} +3 -3
  58. package/dist/{cli-ysnyhws9.js → cli-v1pwxreq.js} +54 -51
  59. package/dist/{cli-feh3dkah.js → cli-v1w7pbd8.js} +2 -1
  60. package/dist/{cli-10zmp1p7.js → cli-vr5avem2.js} +27 -32
  61. package/dist/{cli-bzr0ftht.js → cli-wnb9b2g3.js} +19 -0
  62. package/dist/{cli-df56tqdw.js → cli-wydz3feg.js} +108 -57
  63. package/dist/{cli-krqm5f11.js → cli-xezn9nkh.js} +16 -13
  64. package/dist/{cli-8kt0bmgx.js → cli-xf713zz0.js} +2 -2
  65. package/dist/{cli-x7kpr72a.js → cli-y0kjpfm9.js} +2 -2
  66. package/dist/{cli-6zcfw0x7.js → cli-y195hv1a.js} +1 -1
  67. package/dist/{cli-fn697bnt.js → cli-ykt8f7va.js} +21 -8
  68. package/dist/{cli-4r1sjfc4.js → cli-ymmc1zxg.js} +8 -8
  69. package/dist/{cli-8kgvmkak.js → cli-ypgba1a8.js} +1 -1
  70. package/dist/{cli-rsy933yz.js → cli-z1dqhc9y.js} +30 -19
  71. package/dist/{cli-qbksc292.js → cli-zy39d433.js} +2 -0
  72. package/dist/cli.js +26 -26
  73. package/dist/{cloudflare-workers-ai-system-one-tt484t61.js → cloudflare-workers-ai-system-one-sta45jf9.js} +7 -5
  74. package/dist/{codex-adapter-dw1wxqt8.js → codex-adapter-cgesnjkr.js} +18 -18
  75. package/dist/{codex-login-terbdsqq.js → codex-login-g1cyt5zm.js} +1 -1
  76. package/dist/{codex-session-runner-3cgb8y1g.js → codex-session-runner-8kd7ddhr.js} +18 -18
  77. package/dist/{commands-mhxam6z2.js → commands-h6zaaxym.js} +9 -8
  78. package/dist/{cursor-adapter-2qda3st7.js → cursor-adapter-v8mm6bp5.js} +5 -5
  79. package/dist/{db-sjks418k.js → db-qg3myn53.js} +9 -8
  80. package/dist/{dispatcher-1es759rn.js → dispatcher-7vnwj9qw.js} +24 -24
  81. package/dist/{dsh-adapter-bek4cyw9.js → dsh-adapter-tz6hfp5r.js} +5 -5
  82. package/dist/{easter-egg-3d-mtpnw06s.js → easter-egg-3d-66zxervv.js} +2 -2
  83. package/dist/{execute-s4ccjq3n.js → execute-h4jgevyw.js} +61 -11
  84. package/dist/{google-generative-ai-d6nphg3q.js → google-generative-ai-b8zxrpax.js} +5 -5
  85. package/dist/{google-vertex-cpshkref.js → google-vertex-nrdd697t.js} +5 -5
  86. package/dist/{grok-adapter-ar9cw9jg.js → grok-adapter-jdt2dz2s.js} +18 -8
  87. package/dist/{handlers-1gkbhktr.js → handlers-2qtkpncr.js} +27 -27
  88. package/dist/{hook-ds2zxq9v.js → hook-51yfcgsv.js} +42 -31
  89. package/dist/{hook-vxa3tcsy.js → hook-qnbdgwvd.js} +14 -14
  90. package/dist/{http-3h21z9md.js → http-jsmtag08.js} +320 -98
  91. package/dist/{index-9b65j1m5.js → index-2t9kesn1.js} +9 -8
  92. package/dist/{index-dkfxpkmm.js → index-bt8wkv1w.js} +25 -25
  93. package/dist/{index-f8xnqrye.js → index-cx1sb9bq.js} +33 -24
  94. package/dist/{index-bn6cy8ps.js → index-ekywyv2v.js} +24 -24
  95. package/dist/{index-n99fycq7.js → index-t4g06w93.js} +24 -24
  96. package/dist/{keepalive-3xspa9jw.js → keepalive-4aezx4bj.js} +11 -10
  97. package/dist/{lead-6qphc124.js → lead-r44bkpm5.js} +47 -47
  98. package/dist/{llama-cpp-classify-tgj35k8d.js → llama-cpp-classify-6erb7wwv.js} +3 -1
  99. package/dist/{maintenance-0teem1bb.js → maintenance-grz5jrzh.js} +9 -8
  100. package/dist/{mistral-conversations-8445ddjn.js → mistral-conversations-059y51zt.js} +4 -4
  101. package/dist/{node-9sg7ajby.js → node-qm9eb6z0.js} +1 -1
  102. package/dist/{oauth-refresh-sweep-sh9q25xp.js → oauth-refresh-sweep-wm4ctjfj.js} +10 -9
  103. package/dist/{onboard-54qmnqxe.js → onboard-v60zgqf0.js} +2 -2
  104. package/dist/{openai-codex-responses-9ynm88zy.js → openai-codex-responses-jzxkta9b.js} +8 -7
  105. package/dist/{openai-completions-nhqwjmaw.js → openai-completions-663yncfq.js} +4 -4
  106. package/dist/openai-decisions-vj9nkpf8.js +162 -0
  107. package/dist/{openai-responses-xx1c4kgm.js → openai-responses-m3g43rrt.js} +5 -5
  108. package/dist/{opencode-adapter-wjfa2wvd.js → opencode-adapter-yjyqynzf.js} +7 -7
  109. package/dist/{openrouter-images-8yx3487g.js → openrouter-images-kr60n6b9.js} +1 -1
  110. package/dist/{otel-impl-ycqzp2a1.js → otel-impl-ghh4dyf8.js} +1 -1
  111. package/dist/{pi-messages-vxdt8v7j.js → pi-messages-xszk613n.js} +1 -1
  112. package/dist/{pi-mono-adapter-e77e9zst.js → pi-mono-adapter-0eg8kw2c.js} +68 -51
  113. package/dist/{pricing-refresh-atnkngqs.js → pricing-refresh-mjrqvnvw.js} +11 -10
  114. package/dist/{rbac-roles-j78wdksm.js → rbac-roles-axv4d74x.js} +10 -9
  115. package/dist/{rbac-roles-9pjphh9q.js → rbac-roles-fd5tskj9.js} +9 -8
  116. package/dist/{render-v2-pxjs49fx.js → render-v2-k50j33qd.js} +10 -9
  117. package/dist/{runtime-v2t1r79e.js → runtime-h9ha1mq6.js} +4 -4
  118. package/dist/{setup-ymej0xtx.js → setup-4syh0pd2.js} +2 -2
  119. package/dist/{typesafe-system-one-datfr82p.js → typesafe-system-one-e988vty7.js} +7 -5
  120. package/dist/{virtual-modules-wm8mxdxx.js → virtual-modules-ftr9kwe8.js} +11 -11
  121. package/dist/{work-objects-3nh4ymzb.js → work-objects-jcdbg8rr.js} +27 -27
  122. package/dist/{worker-qa9fkz5s.js → worker-x8j8c9sx.js} +47 -47
  123. package/openapi.json +1 -1
  124. package/package.json +8 -8
  125. package/src/be/memory/providers/openai-embedding.ts +7 -2
  126. package/src/be/memory/raters/llm-summarizer.ts +7 -2
  127. package/src/be/modelsdev-cache.json +61 -0
  128. package/src/be/seed-pricing.ts +84 -53
  129. package/src/be/swarm-config-guard.ts +13 -0
  130. package/src/commands/provider-credentials.ts +28 -5
  131. package/src/commands/runner.ts +7 -12
  132. package/src/heartbeat/heartbeat.ts +91 -19
  133. package/src/hooks/hook.ts +72 -27
  134. package/src/http/mcp.ts +5 -0
  135. package/src/http/onboarding.ts +2 -0
  136. package/src/providers/acp-targets.ts +9 -4
  137. package/src/providers/amp-adapter.ts +1 -1
  138. package/src/providers/claude-adapter.ts +26 -0
  139. package/src/providers/codex-adapter.ts +30 -3
  140. package/src/providers/codex-oauth/auth-json.ts +21 -4
  141. package/src/providers/codex-oauth/types.ts +2 -0
  142. package/src/providers/dsh-adapter.ts +10 -1
  143. package/src/providers/grok-adapter.ts +18 -2
  144. package/src/providers/opencode-adapter.ts +21 -5
  145. package/src/providers/pi-mono-extension.ts +56 -25
  146. package/src/providers/pricing-sources.md +2 -0
  147. package/src/server.ts +63 -3
  148. package/src/tests/acp-adapter.test.ts +152 -12
  149. package/src/tests/ci-unit-test-report.test.ts +73 -0
  150. package/src/tests/claude-default-route.test.ts +75 -0
  151. package/src/tests/claude-hook-output.test.ts +233 -0
  152. package/src/tests/codex-adapter-pool-auth-revalidate.test.ts +4 -2
  153. package/src/tests/codex-adapter.test.ts +166 -26
  154. package/src/tests/codex-oauth-auth-timestamps.test.ts +76 -0
  155. package/src/tests/codex-oauth.test.ts +4 -1
  156. package/src/tests/context-window.test.ts +2 -2
  157. package/src/tests/credential-check.test.ts +51 -1
  158. package/src/tests/dsh-adapter.test.ts +23 -1
  159. package/src/tests/enabled-tools.test.ts +269 -0
  160. package/src/tests/entrypoint-codex-oauth-seed.test.ts +12 -0
  161. package/src/tests/grok-adapter.test.ts +13 -0
  162. package/src/tests/haiku-5-5-pricing.test.ts +38 -0
  163. package/src/tests/heartbeat-checklist.test.ts +158 -1
  164. package/src/tests/onboarding.test.ts +44 -0
  165. package/src/tests/opencode-adapter.test.ts +66 -3
  166. package/src/tests/opencode-plugin.test.ts +37 -0
  167. package/src/tests/openrouter-attribution-call-sites.test.ts +204 -0
  168. package/src/tests/openrouter-base-url.test.ts +30 -39
  169. package/src/tests/pi-mono-extension.test.ts +161 -2
  170. package/src/tests/pricing-refresh.test.ts +70 -1
  171. package/src/tests/reasoning-effort.test.ts +3 -1
  172. package/src/tests/telemetry-trigger.test.ts +12 -1
  173. package/src/tests/workflow-llm.test.ts +14 -0
  174. package/src/tests/workflow-system-one-decision-providers.test.ts +33 -0
  175. package/src/tools/request-human-input.ts +7 -2
  176. package/src/utils/enabled-tools.ts +27 -0
  177. package/src/utils/internal-ai/complete-structured.ts +11 -3
  178. package/src/utils/openrouter-base-url.ts +23 -0
  179. package/src/workflows/executors/raw-llm.ts +1 -0
  180. package/src/workflows/executors/system-one-decision.ts +2 -0
  181. package/src/workflows/executors/validate.ts +1 -0
  182. package/src/workflows/executors/workflow-llm.ts +9 -2
  183. package/templates/skills/agent-browser/SKILL.md +2 -0
  184. package/templates/skills/agent-browser/content.md +2 -0
  185. package/templates/skills/code-quality/content.md +1 -0
  186. package/templates/skills/heartbeat-runbook/content.md +1 -1
  187. package/templates/skills/work-on-task/SKILL.md +4 -0
  188. package/templates/skills/work-on-task/content.md +4 -0
  189. package/templates/skills/workflow-iterate/content.md +9 -0
  190. package/dist/acp-adapter-yzfxn8vj.js +0 -23
  191. package/dist/cli-3dpj7atn.js +0 -11
  192. package/dist/cli-gvcgmx69.js +0 -183
  193. package/dist/{cli-jhm6hzjn.js → cli-mxvnnv5q.js} +7 -7
  194. package/dist/{codex-hook-d2rkvf39.js → codex-hook-15dgc4cb.js} +1 -1
@@ -0,0 +1,96 @@
1
+ import {
2
+ retryProviderRequest
3
+ } from "./cli-zy39d433.js";
4
+ import {
5
+ headersToRecord,
6
+ providerHeadersToRecord
7
+ } from "./cli-7kyk9jr3.js";
8
+ import {
9
+ calculateCost
10
+ } from "./cli-g7k7zbcz.js";
11
+
12
+ // node_modules/@earendil-works/pi-ai/dist/api/classifier-shared.js
13
+ function httpError(label, response, body) {
14
+ const error = new Error(`${label} returned ${response.status}`);
15
+ error.status = response.status;
16
+ error.headers = response.headers;
17
+ error.body = body;
18
+ return error;
19
+ }
20
+ function timeoutError(timeoutMs) {
21
+ const error = new Error(`Request timed out after ${timeoutMs}ms`);
22
+ error.name = "TimeoutError";
23
+ error.status = undefined;
24
+ error.headers = undefined;
25
+ error.body = "";
26
+ return error;
27
+ }
28
+ function isRecord(value) {
29
+ return typeof value === "object" && value !== null && !Array.isArray(value);
30
+ }
31
+ function requiredNumber(label, value, field) {
32
+ if (typeof value !== "number" || !Number.isFinite(value)) {
33
+ throw new Error(`${label} returned an invalid ${field}`);
34
+ }
35
+ return value;
36
+ }
37
+ function requestHeaders(model, apiKey, optionsHeaders) {
38
+ return providerHeadersToRecord({ authorization: `Bearer ${apiKey}`, "content-type": "application/json" }, model.headers, optionsHeaders) ?? {};
39
+ }
40
+ async function postClassifierRequest(label, url, model, body, options, noRetryStatuses) {
41
+ if (!options?.apiKey)
42
+ throw new Error(`No API key for provider: ${model.provider}`);
43
+ const apiKey = options.apiKey;
44
+ let payload = body;
45
+ const transformed = await options.onPayload?.(payload, model);
46
+ if (transformed !== undefined)
47
+ payload = transformed;
48
+ const requestFetch = options.fetch ?? globalThis.fetch;
49
+ const { response, json } = await retryProviderRequest(async () => {
50
+ const timeoutSignal = options.timeoutMs !== undefined ? AbortSignal.timeout(options.timeoutMs) : undefined;
51
+ const signal = options.signal && timeoutSignal ? AbortSignal.any([options.signal, timeoutSignal]) : options.signal ?? timeoutSignal;
52
+ try {
53
+ const next = await requestFetch(url, {
54
+ method: "POST",
55
+ headers: requestHeaders(model, apiKey, options.headers),
56
+ body: JSON.stringify(payload),
57
+ signal
58
+ });
59
+ if (!next.ok)
60
+ throw httpError(label, next, await next.text());
61
+ return { response: next, json: await next.json() };
62
+ } catch (error) {
63
+ if (timeoutSignal?.aborted && !options.signal?.aborted)
64
+ throw timeoutError(options.timeoutMs);
65
+ throw error;
66
+ }
67
+ }, {
68
+ maxRetries: options.maxRetries ?? 2,
69
+ maxRetryDelayMs: options.maxRetryDelayMs,
70
+ signal: options.signal,
71
+ noRetryStatuses
72
+ });
73
+ await options.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);
74
+ return json;
75
+ }
76
+ function tokenCount(value) {
77
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
78
+ }
79
+ function parseClassifierUsage(value, model) {
80
+ if (!isRecord(value) || value.input_tokens === undefined && value.output_tokens === undefined)
81
+ return;
82
+ const input = tokenCount(value.input_tokens);
83
+ const output = tokenCount(value.output_tokens);
84
+ const usage = {
85
+ input,
86
+ output,
87
+ cacheRead: 0,
88
+ cacheWrite: 0,
89
+ totalTokens: input + output,
90
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
91
+ };
92
+ calculateCost(model, usage);
93
+ return usage;
94
+ }
95
+
96
+ export { isRecord, requiredNumber, postClassifierRequest, parseClassifierUsage };
@@ -8,7 +8,7 @@ import {
8
8
  resolveGrammarConstrainedSampling,
9
9
  resolveJsonSchemaStrictSampling,
10
10
  transformMessages
11
- } from "./cli-8kt0bmgx.js";
11
+ } from "./cli-xf713zz0.js";
12
12
  import {
13
13
  sanitizeSurrogates
14
14
  } from "./cli-y2apkfe2.js";
@@ -18,7 +18,7 @@ import {
18
18
  renderSystemMessageUpdate,
19
19
  resolveTranscript,
20
20
  resolveTranscriptTools
21
- } from "./cli-nexwh8zg.js";
21
+ } from "./cli-g7k7zbcz.js";
22
22
  import {
23
23
  parseStreamingJson
24
24
  } from "./cli-1m2e086m.js";
@@ -18,13 +18,13 @@ import {
18
18
  recoverIncompleteRuns,
19
19
  repointTrackerSyncBySwarmId,
20
20
  resolveLeadOnlyRecoveryAssignment
21
- } from "./cli-df56tqdw.js";
21
+ } from "./cli-wydz3feg.js";
22
22
  import {
23
23
  isMultiRuntimeEnabled
24
24
  } from "./cli-re8z5p8p.js";
25
25
  import {
26
26
  createApprovalFollowUpTask
27
- } from "./cli-jvj6a0cv.js";
27
+ } from "./cli-577bxkf6.js";
28
28
  import {
29
29
  MAX_EMPTY_POLLS,
30
30
  assignUnassignedTaskPending,
@@ -75,7 +75,7 @@ import {
75
75
  settleSupersededTaskDependents,
76
76
  supersedeTask,
77
77
  updateAgentStatus
78
- } from "./cli-yshaazs1.js";
78
+ } from "./cli-mkdsy1nq.js";
79
79
  import {
80
80
  TERMINAL_TASK_STATUSES,
81
81
  init_types
@@ -90,11 +90,18 @@ import {
90
90
  init_env_flag,
91
91
  isEnvFlagEnabled
92
92
  } from "./cli-ej6gbxfb.js";
93
+ import {
94
+ init_package,
95
+ package_default
96
+ } from "./cli-ymmc1zxg.js";
93
97
  import {
94
98
  init_secret_scrubber,
95
99
  scrubSecrets
96
100
  } from "./cli-wt7ccy4r.js";
97
101
 
102
+ // src/heartbeat/heartbeat.ts
103
+ init_package();
104
+
98
105
  // src/be/approval-sweeps.ts
99
106
  init_db();
100
107
  var DEFAULT_APPROVAL_REQUEST_AUTO_CANCELLATION_DAYS = 7;
@@ -356,6 +363,9 @@ function heartbeatChecklistIntervalMs() {
356
363
  function isHeartbeatChecklistDisabled() {
357
364
  return isEnvFlagEnabled("HEARTBEAT_CHECKLIST_DISABLE", false);
358
365
  }
366
+ function isBootTriageAlways() {
367
+ return isEnvFlagEnabled("HEARTBEAT_BOOT_TRIAGE_ALWAYS", false);
368
+ }
359
369
  var heartbeatInterval = null;
360
370
  var checklistInterval = null;
361
371
  var bootTriageTimeout = null;
@@ -1130,19 +1140,7 @@ async function gatherSystemStatus(options) {
1130
1140
  sections.push("- If the retry failed or the work is no longer needed, cancel it");
1131
1141
  sections.push("- Do NOT mark this boot triage as complete until all items are triaged");
1132
1142
  }
1133
- const orphanedTasks = [];
1134
- for (const status of ["pending", "offered"]) {
1135
- const tasks = await getTasksByStatus(status);
1136
- for (const task of tasks) {
1137
- const holderId = status === "offered" ? task.offeredTo : task.agentId;
1138
- if (!holderId)
1139
- continue;
1140
- const agent = agents.find((a) => a.id === holderId);
1141
- if (!agent || agent.status === "offline") {
1142
- orphanedTasks.push(task);
1143
- }
1144
- }
1145
- }
1143
+ const orphanedTasks = await getOrphanedPendingOrOfferedTasks(agents);
1146
1144
  if (orphanedTasks.length > 0) {
1147
1145
  sections.push("");
1148
1146
  sections.push("## Orphaned Tasks [auto-generated, NEEDS ATTENTION]");
@@ -1160,6 +1158,32 @@ async function gatherSystemStatus(options) {
1160
1158
  return sections.join(`
1161
1159
  `);
1162
1160
  }
1161
+ async function getOrphanedPendingOrOfferedTasks(agents) {
1162
+ const orphanedTasks = [];
1163
+ for (const status of ["pending", "offered"]) {
1164
+ const tasks = await getTasksByStatus(status);
1165
+ for (const task of tasks) {
1166
+ const holderId = status === "offered" ? task.offeredTo : task.agentId;
1167
+ if (!holderId)
1168
+ continue;
1169
+ const agent = agents.find((a) => a.id === holderId);
1170
+ if (!agent || agent.status === "offline") {
1171
+ orphanedTasks.push(task);
1172
+ }
1173
+ }
1174
+ }
1175
+ return orphanedTasks;
1176
+ }
1177
+ async function getBootTriageFindings() {
1178
+ const now = Date.now();
1179
+ const agents = await getAllAgents();
1180
+ return {
1181
+ rebootInterrupted: getRebootAffectedTasks().length,
1182
+ stalled: (await getStalledInProgressTasks(stallThresholdMinutes())).length,
1183
+ orphaned: (await getOrphanedPendingOrOfferedTasks(agents)).length,
1184
+ supersededWithoutResume: (await getSupersededTasksWithoutResume(new Date(now - ORPHAN_SUPERSEDE_MIN_AGE_MS).toISOString(), new Date(now - ORPHAN_SUPERSEDE_MAX_AGE_MS).toISOString())).length
1185
+ };
1186
+ }
1163
1187
  async function checkHeartbeatChecklist() {
1164
1188
  const lead = await getLeadAgent();
1165
1189
  if (!lead)
@@ -1323,7 +1347,23 @@ async function createBootTriageTask() {
1323
1347
  LIMIT 1`, [lead.id, ...TERMINAL_TASK_STATUSES]);
1324
1348
  if (existing)
1325
1349
  return;
1326
- const systemStatus = await gatherSystemStatus({ isBootTriage: true });
1350
+ if (!isBootTriageAlways()) {
1351
+ const findings = await getBootTriageFindings().catch((err) => {
1352
+ console.error("[Heartbeat] Boot triage findings failed, creating Lead task:", scrubSecrets(err instanceof Error ? err.message : String(err)));
1353
+ return null;
1354
+ });
1355
+ if (findings && Object.values(findings).every((count) => count === 0)) {
1356
+ console.log(`[Heartbeat] Clean boot (v${package_default.version}): 0 interrupted, stalled, orphaned, or resume-less superseded tasks; no boot-triage task for lead ${lead.name}`);
1357
+ return;
1358
+ }
1359
+ }
1360
+ const systemStatus = await gatherSystemStatus({ isBootTriage: true }).catch((err) => {
1361
+ const reason = scrubSecrets(err instanceof Error ? err.message : String(err));
1362
+ console.error("[Heartbeat] Boot triage status gathering failed:", reason);
1363
+ return `## System status unavailable
1364
+
1365
+ Status gathering failed after this boot (${reason}). Investigate the task, agent, and DB state directly.`;
1366
+ });
1327
1367
  const result = resolveTemplate("heartbeat.boot-triage", {
1328
1368
  system_status: systemStatus,
1329
1369
  heartbeat_content: isEffectivelyEmpty(heartbeatMd) ? "_No standing orders configured._" : heartbeatMd
@@ -6,18 +6,20 @@ import {
6
6
  import {
7
7
  parseModelStr,
8
8
  resolveCredential
9
- } from "./cli-f2n17zhp.js";
10
- import {
11
- DEFAULT_OPENROUTER_BASE_URL,
12
- getOpenRouterBaseUrl
13
- } from "./cli-3dpj7atn.js";
9
+ } from "./cli-7mhy3ths.js";
14
10
  import {
15
11
  complete,
16
12
  getBuiltinModel
17
- } from "./cli-pkke6geq.js";
13
+ } from "./cli-km4x66j0.js";
18
14
  import {
19
15
  exports_typebox
20
16
  } from "./cli-rb9m6rpe.js";
17
+ import {
18
+ DEFAULT_OPENROUTER_BASE_URL,
19
+ getOpenRouterAttributionHeaders,
20
+ getOpenRouterBaseUrl,
21
+ init_openrouter_base_url
22
+ } from "./cli-a35hzdve.js";
21
23
  import {
22
24
  init_zod
23
25
  } from "./cli-sd0mxa3c.js";
@@ -31,6 +33,7 @@ import {
31
33
 
32
34
  // src/utils/internal-ai/complete-structured.ts
33
35
  init_zod();
36
+ init_openrouter_base_url();
34
37
  init_secret_scrubber();
35
38
  var CLAUDE_CLI_TIMEOUT_MS = 30000;
36
39
  function stripJsonFences(raw) {
@@ -169,10 +172,12 @@ ${claudeUserPrompt}`, cred.modelDefault, opts.signal, jsonSchema);
169
172
  console.error(scrubSecrets(`internal-ai: unknown model ${provider}/${modelId} (callerTag=${callerTag})`));
170
173
  return null;
171
174
  }
172
- const openRouterBaseUrl = getOpenRouterBaseUrl(opts.env ?? process.env);
175
+ const env = opts.env ?? process.env;
176
+ const openRouterBaseUrl = getOpenRouterBaseUrl(env);
173
177
  if (provider === "openrouter" && openRouterBaseUrl !== DEFAULT_OPENROUTER_BASE_URL) {
174
178
  model = { ...model, baseUrl: openRouterBaseUrl };
175
179
  }
180
+ const headers = provider === "openrouter" ? getOpenRouterAttributionHeaders(model.baseUrl, env) : {};
176
181
  const completeFn = opts._complete ?? complete;
177
182
  const toolChoice = model.api === "anthropic-messages" ? { type: "tool", name: opts.toolName } : "required";
178
183
  let userPrompt = opts.userPrompt;
@@ -189,7 +194,7 @@ ${claudeUserPrompt}`, cred.modelDefault, opts.signal, jsonSchema);
189
194
  parameters: opts.toolSchema
190
195
  }
191
196
  ]
192
- }, { apiKey: cred.apiKey, signal: opts.signal, toolChoice });
197
+ }, { apiKey: cred.apiKey, signal: opts.signal, toolChoice, headers });
193
198
  const toolCall = msg.content.find((c) => c.type === "toolCall" && c.name === opts.toolName);
194
199
  if (!toolCall) {
195
200
  const assistantText = msg.content.filter((content) => content.type === "text").map((content) => content.text).join(`
@@ -7,7 +7,7 @@ import {
7
7
  imageFallback,
8
8
  resolvePath,
9
9
  truncateToWidth
10
- } from "./cli-cwxhbf43.js";
10
+ } from "./cli-5t5my0h8.js";
11
11
 
12
12
  // node_modules/@earendil-works/pi-coding-agent/dist/utils/output-files.js
13
13
  import { randomBytes } from "node:crypto";
@@ -414,14 +414,25 @@ class VisualLinePreview {
414
414
  }
415
415
 
416
416
  // node_modules/@earendil-works/pi-coding-agent/dist/utils/ansi.js
417
- function ansiRegex({ onlyFirst = false } = {}) {
418
- const ST = "(?:\\u0007|\\u001B\\u005C|\\u009C)";
419
- const osc = `(?:\\u001B\\][\\s\\S]*?${ST})`;
420
- const csi = "[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]";
421
- const pattern = `${osc}|${csi}`;
422
- return new RegExp(pattern, onlyFirst ? undefined : "g");
423
- }
424
- var regex = ansiRegex();
417
+ var ST = "(?:\\u0007|\\u001B\\u005C|\\u009C)";
418
+ var OSC_START = "\\u001B\\]";
419
+ var CSI_START = "[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?";
420
+ var CSI_FINAL = "[\\dA-PR-TZcf-nq-uy=><~]";
421
+ var ansiRegex = new RegExp(`(?:${OSC_START}[\\s\\S]*?${ST})|${CSI_START}${CSI_FINAL}`, "g");
422
+ var unfinishedAnsiAtEndRegex = new RegExp(`(?:${OSC_START}(?:[^\\u0007\\u009C\\u001B]|\\u001B(?!\\\\))*|${CSI_START})$`);
423
+ var MAX_PENDING_ANSI_LENGTH = 256;
424
+ function splitIncompleteAnsiSuffix(value) {
425
+ if (!value.includes("\x1B") && !value.includes("›")) {
426
+ return { complete: value, pending: "" };
427
+ }
428
+ const windowStart = Math.max(0, value.length - MAX_PENDING_ANSI_LENGTH);
429
+ const match = unfinishedAnsiAtEndRegex.exec(value.slice(windowStart));
430
+ if (!match) {
431
+ return { complete: value, pending: "" };
432
+ }
433
+ const splitAt = windowStart + match.index;
434
+ return { complete: value.slice(0, splitAt), pending: value.slice(splitAt) };
435
+ }
425
436
  function stripAnsi(value) {
426
437
  if (typeof value !== "string") {
427
438
  throw new TypeError(`Expected a \`string\`, got \`${typeof value}\``);
@@ -429,7 +440,7 @@ function stripAnsi(value) {
429
440
  if (!value.includes("\x1B") && !value.includes("›")) {
430
441
  return value;
431
442
  }
432
- return value.replace(regex, "");
443
+ return value.replace(ansiRegex, "");
433
444
  }
434
445
 
435
446
  // node_modules/@earendil-works/pi-coding-agent/dist/core/tools/render-utils.js
@@ -518,4 +529,4 @@ function renderToolPath(rawPath, theme, cwd, options) {
518
529
  return linkPath(theme.fg("accent", shortenPath(value)), value, cwd);
519
530
  }
520
531
 
521
- export { stripAnsi, writeOutputFile, createOutputFileStream, getShellConfig, getPowerShellConfig, getShellEnv, sanitizeBinaryOutput, trackDetachedChildPid, untrackDetachedChildPid, killTrackedDetachedChildren, killProcessTree, DEFAULT_MAX_LINES, DEFAULT_MAX_BYTES, GREP_MAX_LINE_LENGTH, formatSize, truncateHead, truncateTail, truncateLine, truncateMiddle, truncateToVisualLines, VisualLinePreview, shortenPath, str, replaceTabs, normalizeDisplayText, getTextOutput, formatToolCallWithArgs, invalidArgText, renderToolPath };
532
+ export { splitIncompleteAnsiSuffix, stripAnsi, writeOutputFile, createOutputFileStream, getShellConfig, getPowerShellConfig, getShellEnv, sanitizeBinaryOutput, trackDetachedChildPid, untrackDetachedChildPid, killTrackedDetachedChildren, killProcessTree, DEFAULT_MAX_LINES, DEFAULT_MAX_BYTES, GREP_MAX_LINE_LENGTH, formatSize, truncateHead, truncateTail, truncateLine, truncateMiddle, truncateToVisualLines, VisualLinePreview, shortenPath, str, replaceTabs, normalizeDisplayText, getTextOutput, formatToolCallWithArgs, invalidArgText, renderToolPath };
@@ -3,7 +3,7 @@ import {
3
3
  getTextOutput,
4
4
  replaceTabs,
5
5
  str
6
- } from "./cli-8ssjez7e.js";
6
+ } from "./cli-rhy7z1rp.js";
7
7
  import {
8
8
  Container,
9
9
  Spacer,
@@ -11,7 +11,7 @@ import {
11
11
  getDocsPath,
12
12
  highlightCode,
13
13
  keyHint
14
- } from "./cli-cwxhbf43.js";
14
+ } from "./cli-5t5my0h8.js";
15
15
  import {
16
16
  exports_typebox
17
17
  } from "./cli-rb9m6rpe.js";
@@ -613,7 +613,7 @@ function createToolDefinitionFromAgentTool(tool) {
613
613
  }
614
614
 
615
615
  // node_modules/@earendil-works/pi-coding-agent/dist/extensions/codemode/execute.lazy.js
616
- var loadCodemodeExecutor = () => import("./execute-s4ccjq3n.js");
616
+ var loadCodemodeExecutor = () => import("./execute-h4jgevyw.js");
617
617
 
618
618
  // node_modules/@earendil-works/pi-coding-agent/dist/extensions/codemode/renderer.js
619
619
  var CODE_PREVIEW_LINES = 10;
@@ -755,9 +755,9 @@ var DESCRIPTION_INTRO = `Run JavaScript that calls other tools. The input is raw
755
755
  function describeGlobals(models) {
756
756
  const lines = [
757
757
  "Globals:",
758
- "- `text(value)`, `image(dataUrlOrImageBlock)`, `console.log(...)`, and top-level `return` add output; `exit()` ends the script. `image()` also saves the image to a temp file and the result names its path.",
758
+ "- `text(value)`, `image(dataUrlOrImageBlock)`, `console.log(...)`, and top-level `return` add output; `exit()` ends the script. With several text items, each starts with a `==> text N/M <==` line, and `console` lines follow the other output in one `<console_output>` block. `image()` also saves the image to a temp file and the result names its path.",
759
759
  "- `store(key, value)` and `load(key)` keep JSON values across codemode calls.",
760
- "- `ALL_TOOLS`, `searchTools(query, { limit?, namespace? })`, `describeTool(name)`, `describeNamespace(name)`: find unlisted tools, such as MCP tools."
760
+ "- `ALL_TOOLS`, `await searchTools(query, { limit?, namespace? })`, `await describeTool(name)`, `await describeNamespace(name)`: find unlisted tools, such as MCP tools."
761
761
  ];
762
762
  if (models) {
763
763
  lines.push(`- \`models\`: classifiers and image generation. Read ${CODEMODE_DOCS_PATH} first.`);
@@ -4,23 +4,23 @@ import {
4
4
  import {
5
5
  readPkgVersion
6
6
  } from "./cli-gt4hxb8p.js";
7
+ import {
8
+ checkToolLoop
9
+ } from "./cli-hp1n6zq3.js";
7
10
  import {
8
11
  CONTEXT_FORMULA,
9
12
  clampContextPercent,
10
13
  computeContextUsedUnified,
11
14
  getContextWindowSize
12
- } from "./cli-32bca7nr.js";
13
- import {
14
- checkToolLoop
15
- } from "./cli-hp1n6zq3.js";
15
+ } from "./cli-7avy4v8w.js";
16
16
  import {
17
17
  Anthropic
18
- } from "./cli-zy7vwsne.js";
18
+ } from "./cli-5qkcdv8c.js";
19
19
  import {
20
20
  init_runtime_model_catalog,
21
21
  init_src,
22
22
  runtimeCatalogModel
23
- } from "./cli-zsh093hk.js";
23
+ } from "./cli-014vns2y.js";
24
24
  import {
25
25
  init_secret_scrubber,
26
26
  scrubSecrets
@@ -8,7 +8,7 @@ import {
8
8
  reasoningLevelsFor,
9
9
  runtimeCatalogModel,
10
10
  runtimeCatalogSection
11
- } from "./cli-zsh093hk.js";
11
+ } from "./cli-014vns2y.js";
12
12
 
13
13
  // src/providers/reasoning-effort.ts
14
14
  init_src();
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  seedPricingFromModelsDev
3
- } from "./cli-ysnyhws9.js";
3
+ } from "./cli-v1pwxreq.js";
4
4
  import {
5
5
  ensureRbacSeedsSynced,
6
6
  init_rbac_roles
7
- } from "./cli-8kgvmkak.js";
7
+ } from "./cli-ypgba1a8.js";
8
8
  import {
9
9
  getDb,
10
10
  init_db1 as init_db
11
- } from "./cli-yshaazs1.js";
11
+ } from "./cli-mkdsy1nq.js";
12
12
 
13
13
  // src/be/boot-seeds.ts
14
14
  init_db();
@@ -5,10 +5,10 @@ import {
5
5
  CONTEXT_FORMULA,
6
6
  clampContextPercent,
7
7
  computeContextUsedUnified
8
- } from "./cli-32bca7nr.js";
8
+ } from "./cli-7avy4v8w.js";
9
9
  import {
10
10
  applyReasoningEffort
11
- } from "./cli-ttbsse3f.js";
11
+ } from "./cli-tmhsxhb8.js";
12
12
  import {
13
13
  ampBillsCacheWrites,
14
14
  resolveAmpModel
@@ -36,7 +36,7 @@ import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
36
36
  import { tmpdir } from "node:os";
37
37
  import { join } from "node:path";
38
38
  init_secret_scrubber();
39
- var AMP_PACKAGE = "@ampcode/cli@0.0.1791403257-g05ffa9";
39
+ var AMP_PACKAGE = "@ampcode/cli@0.0.1791460855-g1f688c";
40
40
  var AMP_MCP_SERVER_NAME = "agent-swarm";
41
41
  var AMP_PLUGIN_MODE_KEY = "agent-swarm";
42
42
  var AMP_LIVE_TEST_TIMEOUT_MS = 5000;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  getDb,
3
3
  init_db1 as init_db
4
- } from "./cli-yshaazs1.js";
4
+ } from "./cli-mkdsy1nq.js";
5
5
 
6
6
  // src/be/seed-pricing.ts
7
7
  init_db();
@@ -152,16 +152,47 @@ function projectCostBlock(provider, model, cost, opts = {}) {
152
152
  }
153
153
  return rows;
154
154
  }
155
- function buildModelsDevSeedRows(cache) {
155
+ function outranksSource(candidate, current, key) {
156
+ const a = candidate.toLowerCase();
157
+ const b = current.toLowerCase();
158
+ if (a === key !== (b === key))
159
+ return a === key;
160
+ return a > b;
161
+ }
162
+ function collapseNormalizedIds(sourced) {
163
+ const modelKey = (row) => `${row.provider}\x00${row.model}`;
164
+ const winners = new Map;
165
+ for (const { sourceId, row } of sourced) {
166
+ const current = winners.get(modelKey(row));
167
+ if (current === undefined || outranksSource(sourceId, current, row.model)) {
168
+ winners.set(modelKey(row), sourceId);
169
+ }
170
+ }
171
+ const seen = new Set;
156
172
  const rows = [];
173
+ for (const { sourceId, row } of sourced) {
174
+ if (winners.get(modelKey(row)) !== sourceId)
175
+ continue;
176
+ const rowKey = `${modelKey(row)}\x00${row.tokenClass}`;
177
+ if (seen.has(rowKey))
178
+ continue;
179
+ seen.add(rowKey);
180
+ rows.push(row);
181
+ }
182
+ return rows;
183
+ }
184
+ function buildModelsDevSeedRows(cache) {
185
+ const sourced = [];
186
+ const add = (sourceId, projected) => {
187
+ for (const row of projected)
188
+ sourced.push({ sourceId, row });
189
+ };
157
190
  const anthropic = cache.anthropic?.models ?? {};
158
191
  for (const [id, model] of Object.entries(anthropic)) {
159
192
  if (!model?.cost)
160
193
  continue;
161
194
  for (const provider of ["claude", "claude-managed"]) {
162
- for (const row of projectCostBlock(provider, id, model.cost)) {
163
- rows.push(row);
164
- }
195
+ add(id, projectCostBlock(provider, id, model.cost));
165
196
  }
166
197
  }
167
198
  for (const [shortname, fullId] of Object.entries(ANTHROPIC_SHORTNAME_TO_MODELSDEV)) {
@@ -169,96 +200,68 @@ function buildModelsDevSeedRows(cache) {
169
200
  if (!cost)
170
201
  continue;
171
202
  for (const provider of ["claude", "claude-managed"]) {
172
- for (const row of projectCostBlock(provider, shortname, cost)) {
173
- rows.push(row);
174
- }
203
+ add(shortname, projectCostBlock(provider, shortname, cost));
175
204
  }
176
205
  }
177
206
  for (const [shortname, fullId] of Object.entries(ANTHROPIC_SHORTNAME_TO_MODELSDEV)) {
178
207
  const cost = anthropic[fullId]?.cost ?? (cache.anthropic ? ANTHROPIC_SHORTNAME_PRICING_FALLBACKS[fullId] : undefined);
179
208
  if (!cost)
180
209
  continue;
181
- for (const row of projectCostBlock("pi", shortname, cost, { anthropicBilled: true })) {
182
- rows.push(row);
183
- }
210
+ add(shortname, projectCostBlock("pi", shortname, cost, { anthropicBilled: true }));
184
211
  }
185
212
  for (const section of ["anthropic", "openai", "google", "fireworks-ai"]) {
186
213
  for (const [id, model] of Object.entries(cache[section]?.models ?? {})) {
187
214
  if (!model?.cost)
188
215
  continue;
189
- for (const row of projectCostBlock("amp", id, model.cost)) {
190
- rows.push(row);
191
- }
216
+ add(id, projectCostBlock("amp", id, model.cost));
192
217
  }
193
218
  }
194
219
  const openai = cache.openai?.models ?? {};
195
220
  for (const [id, model] of Object.entries(openai)) {
196
221
  if (!model?.cost)
197
222
  continue;
198
- for (const row of projectCostBlock("codex", id, model.cost)) {
199
- rows.push(row);
200
- }
201
- for (const row of projectCostBlock("pi", id, model.cost)) {
202
- rows.push(row);
203
- }
223
+ add(id, projectCostBlock("codex", id, model.cost));
224
+ add(id, projectCostBlock("pi", id, model.cost));
204
225
  }
205
226
  for (const vendor of ["openai", "anthropic", "google", "xai"]) {
206
227
  for (const [id, model] of Object.entries(cache[vendor]?.models ?? {})) {
207
228
  if (!model?.cost)
208
229
  continue;
209
- for (const row of projectCostBlock("cursor", id, model.cost, { anthropicBilled: false })) {
210
- rows.push(row);
211
- }
230
+ add(id, projectCostBlock("cursor", id, model.cost, { anthropicBilled: false }));
212
231
  }
213
232
  }
214
233
  for (const [id, model] of Object.entries(cache.xai?.models ?? {})) {
215
234
  if (!model?.cost)
216
235
  continue;
217
- for (const row of projectCostBlock("grok", id, model.cost, { anthropicBilled: false })) {
218
- rows.push(row);
219
- }
236
+ add(id, projectCostBlock("grok", id, model.cost, { anthropicBilled: false }));
220
237
  }
221
238
  const deepseek = cache.deepseek?.models ?? {};
222
239
  for (const [id, model] of Object.entries(deepseek)) {
223
240
  if (!model?.cost)
224
241
  continue;
225
- for (const row of projectCostBlock("dsh", id, model.cost)) {
226
- rows.push(row);
227
- }
242
+ add(id, projectCostBlock("dsh", id, model.cost));
228
243
  }
229
244
  const openrouter = cache.openrouter?.models ?? {};
230
245
  for (const [id, model] of Object.entries(openrouter)) {
231
246
  if (!model?.cost)
232
247
  continue;
233
- for (const row of projectCostBlock("opencode", id, model.cost)) {
234
- rows.push(row);
235
- }
236
- for (const row of projectCostBlock("pi", id, model.cost, {
248
+ add(id, projectCostBlock("opencode", id, model.cost));
249
+ add(id, projectCostBlock("pi", id, model.cost, {
237
250
  anthropicBilled: id.startsWith("anthropic/")
238
- })) {
239
- rows.push(row);
240
- }
241
- for (const row of projectCostBlock("dsh", id, model.cost, {
251
+ }));
252
+ add(id, projectCostBlock("dsh", id, model.cost, {
242
253
  anthropicBilled: id.startsWith("anthropic/")
243
- })) {
244
- rows.push(row);
245
- }
246
- for (const row of projectCostBlock("grok", id, model.cost, {
254
+ }));
255
+ add(id, projectCostBlock("grok", id, model.cost, {
247
256
  anthropicBilled: id.startsWith("anthropic/")
248
- })) {
249
- rows.push(row);
250
- }
257
+ }));
251
258
  if (id.startsWith("google/")) {
252
259
  const geminiKey = id.replace(/^google\//, "");
253
- for (const row of projectCostBlock("gemini", geminiKey, model.cost)) {
254
- rows.push(row);
255
- }
256
- for (const row of projectCostBlock("gemini", id, model.cost)) {
257
- rows.push(row);
258
- }
260
+ add(geminiKey, projectCostBlock("gemini", geminiKey, model.cost));
261
+ add(id, projectCostBlock("gemini", id, model.cost));
259
262
  }
260
263
  }
261
- return rows;
264
+ return collapseNormalizedIds(sourced);
262
265
  }
263
266
  function buildPricingSeedRows(cache) {
264
267
  const modelsdevRows = cache ? buildModelsDevSeedRows(cache) : [];
@@ -366,7 +366,8 @@ function credentialsToAuthJson(creds, opts = {}) {
366
366
  refresh_token: includeRefreshToken ? creds.refresh : "",
367
367
  account_id: creds.accountId
368
368
  },
369
- last_refresh: new Date(creds.expires).toISOString()
369
+ last_refresh: new Date().toISOString(),
370
+ expires: creds.expires
370
371
  };
371
372
  }
372
373