github-router 0.3.313 → 0.3.315

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 (102) hide show
  1. package/dist/aic-ledger-BS47yb_C.js +298 -0
  2. package/dist/aic-ledger-BS47yb_C.js.map +1 -0
  3. package/dist/{attribution-settings-Dnt04Iyn.js → attribution-settings-DXmmyuEE.js} +8 -8
  4. package/dist/{attribution-settings-Dnt04Iyn.js.map → attribution-settings-DXmmyuEE.js.map} +1 -1
  5. package/dist/{auth-O_UG1ABO.js → auth-D8t41c5D.js} +3 -3
  6. package/dist/{auth-O_UG1ABO.js.map → auth-D8t41c5D.js.map} +1 -1
  7. package/dist/browser-ext/manifest.json +1 -1
  8. package/dist/{check-usage-dicJOWML.js → check-usage-BpBKOjGZ.js} +4 -4
  9. package/dist/{check-usage-dicJOWML.js.map → check-usage-BpBKOjGZ.js.map} +1 -1
  10. package/dist/{claude-D_Me80Yi.js → claude-Cmmu3-cL.js} +140 -20
  11. package/dist/claude-Cmmu3-cL.js.map +1 -0
  12. package/dist/{codex-CE7zZm-M.js → codex-DqTKKoEx.js} +5 -5
  13. package/dist/{codex-CE7zZm-M.js.map → codex-DqTKKoEx.js.map} +1 -1
  14. package/dist/copilot-discount-IbXR5A28.js +220 -0
  15. package/dist/copilot-discount-IbXR5A28.js.map +1 -0
  16. package/dist/{debug-2PgImRnr.js → debug-CA7pg8V9.js} +2 -2
  17. package/dist/{debug-2PgImRnr.js.map → debug-CA7pg8V9.js.map} +1 -1
  18. package/dist/engine-b9XaKLp0.js +2 -0
  19. package/dist/{exec-y8C_MU8A.js → exec-COUT4QsS.js} +2 -2
  20. package/dist/{exec-y8C_MU8A.js.map → exec-COUT4QsS.js.map} +1 -1
  21. package/dist/{gate-discovery-_flEdhYo.js → gate-discovery-CPk6Z8yc.js} +6 -6
  22. package/dist/{gate-discovery-_flEdhYo.js.map → gate-discovery-CPk6Z8yc.js.map} +1 -1
  23. package/dist/{get-copilot-usage-Cjy8TiFf.js → get-copilot-usage-FSQE8szQ.js} +2 -2
  24. package/dist/{get-copilot-usage-Cjy8TiFf.js.map → get-copilot-usage-FSQE8szQ.js.map} +1 -1
  25. package/dist/hooks.mjs +615 -15
  26. package/dist/hooks.sha256 +1 -1
  27. package/dist/internal-aic-status-BN0xRLSF.js +432 -0
  28. package/dist/internal-aic-status-BN0xRLSF.js.map +1 -0
  29. package/dist/{internal-artifact-open-CxeIfsW_.js → internal-artifact-open-B3stUu74.js} +2 -2
  30. package/dist/{internal-artifact-open-CxeIfsW_.js.map → internal-artifact-open-B3stUu74.js.map} +1 -1
  31. package/dist/{internal-fast-dispatch-guard-D8YNlnuQ.js → internal-fast-dispatch-guard-2QjUlhqO.js} +1 -1
  32. package/dist/{internal-fast-dispatch-guard-19xQEouu.js → internal-fast-dispatch-guard-CAwYj_Yz.js} +2 -2
  33. package/dist/{internal-fast-dispatch-guard-19xQEouu.js.map → internal-fast-dispatch-guard-CAwYj_Yz.js.map} +1 -1
  34. package/dist/{internal-first-mate-guard-BuweUgjb.js → internal-first-mate-guard-B0rbLb0L.js} +3 -3
  35. package/dist/{internal-first-mate-guard-BuweUgjb.js.map → internal-first-mate-guard-B0rbLb0L.js.map} +1 -1
  36. package/dist/{internal-first-mate-guard-Nf1H0mCK.js → internal-first-mate-guard-VgnHBp0s.js} +1 -1
  37. package/dist/{internal-max-dispatch-guard-_Pp4LltM.js → internal-max-dispatch-guard-BzKsY9ze.js} +1 -1
  38. package/dist/{internal-max-dispatch-guard-DZ7KLWxP.js → internal-max-dispatch-guard-l1NGYHtF.js} +2 -2
  39. package/dist/{internal-max-dispatch-guard-DZ7KLWxP.js.map → internal-max-dispatch-guard-l1NGYHtF.js.map} +1 -1
  40. package/dist/{internal-plan-review-DLduDz41.js → internal-plan-review-QUvNZmMR.js} +3 -3
  41. package/dist/{internal-plan-review-DLduDz41.js.map → internal-plan-review-QUvNZmMR.js.map} +1 -1
  42. package/dist/{internal-prompt-submit-DG94f8E-.js → internal-prompt-submit-fj5ccft_.js} +5 -5
  43. package/dist/{internal-prompt-submit-DG94f8E-.js.map → internal-prompt-submit-fj5ccft_.js.map} +1 -1
  44. package/dist/{internal-session-bind-D6Hpl-84.js → internal-session-bind-0Hmak8PR.js} +2 -2
  45. package/dist/{internal-session-bind-D6Hpl-84.js.map → internal-session-bind-0Hmak8PR.js.map} +1 -1
  46. package/dist/{internal-stop-hook-BJ3o61-L.js → internal-stop-hook-BKiKYeda.js} +6 -6
  47. package/dist/{internal-stop-hook-BJ3o61-L.js.map → internal-stop-hook-BKiKYeda.js.map} +1 -1
  48. package/dist/{internal-stop-review-DlKzZgFm.js → internal-stop-review-8v2llYDB.js} +2 -2
  49. package/dist/{internal-stop-review-DlKzZgFm.js.map → internal-stop-review-8v2llYDB.js.map} +1 -1
  50. package/dist/{internal-worker-guard-D7sfByyo.js → internal-worker-guard-BI4Pl0Ew.js} +2 -2
  51. package/dist/{internal-worker-guard-D7sfByyo.js.map → internal-worker-guard-BI4Pl0Ew.js.map} +1 -1
  52. package/dist/{internal-workspace-header-CU5OjLCB.js → internal-workspace-header-kg9FoNXK.js} +2 -2
  53. package/dist/{internal-workspace-header-CU5OjLCB.js.map → internal-workspace-header-kg9FoNXK.js.map} +1 -1
  54. package/dist/lifecycle-BpqAyaAj.js +2 -0
  55. package/dist/lifecycle-CL2WiyeQ.js +2 -0
  56. package/dist/{lifecycle-CtRA3Y7p.js → lifecycle-Cx1wVrLb.js} +3 -3
  57. package/dist/{lifecycle-CtRA3Y7p.js.map → lifecycle-Cx1wVrLb.js.map} +1 -1
  58. package/dist/{lifecycle-BCnarXJV.js → lifecycle-IwotwedG.js} +2 -2
  59. package/dist/{lifecycle-BCnarXJV.js.map → lifecycle-IwotwedG.js.map} +1 -1
  60. package/dist/main.js +21 -20
  61. package/dist/main.js.map +1 -1
  62. package/dist/{mcp-workspace-header-B60WSR1Y.js → mcp-workspace-header-BYgWioLH.js} +2 -2
  63. package/dist/{mcp-workspace-header-B60WSR1Y.js.map → mcp-workspace-header-BYgWioLH.js.map} +1 -1
  64. package/dist/{models-COuMOfM6.js → models-DgLeb-Dv.js} +3 -3
  65. package/dist/{models-COuMOfM6.js.map → models-DgLeb-Dv.js.map} +1 -1
  66. package/dist/{orchestration-DjLA-lxB.js → orchestration-Dc3mO0G3.js} +3 -3
  67. package/dist/{orchestration-DjLA-lxB.js.map → orchestration-Dc3mO0G3.js.map} +1 -1
  68. package/dist/paths-BXXCVFvA.js +2 -0
  69. package/dist/{paths-De1Qh9Q9.js → paths-CMxlQEfQ.js} +3 -3
  70. package/dist/{paths-De1Qh9Q9.js.map → paths-CMxlQEfQ.js.map} +1 -1
  71. package/dist/{peer-mcp-personas-DklYru_1.js → peer-mcp-personas-CYWJSxPK.js} +40 -13
  72. package/dist/{peer-mcp-personas-DklYru_1.js.map → peer-mcp-personas-CYWJSxPK.js.map} +1 -1
  73. package/dist/{plan-review-hook-vL6BYmA8.js → plan-review-hook-BIMwWkh6.js} +4 -4
  74. package/dist/{plan-review-hook-vL6BYmA8.js.map → plan-review-hook-BIMwWkh6.js.map} +1 -1
  75. package/dist/{prompt-submit-hook-DfqufWC1.js → prompt-submit-hook-BcFpjHXg.js} +3 -3
  76. package/dist/{prompt-submit-hook-DfqufWC1.js.map → prompt-submit-hook-BcFpjHXg.js.map} +1 -1
  77. package/dist/{provision-BYdIsKcp.js → provision-AwSjt-vR.js} +9 -5
  78. package/dist/provision-AwSjt-vR.js.map +1 -0
  79. package/dist/{self-invocation-B84JCHps.js → self-invocation-cRl4RqfW.js} +2 -2
  80. package/dist/{self-invocation-B84JCHps.js.map → self-invocation-cRl4RqfW.js.map} +1 -1
  81. package/dist/{serve-DI4QgSSB.js → serve-BG2O6Slz.js} +13 -13
  82. package/dist/{serve-DI4QgSSB.js.map → serve-BG2O6Slz.js.map} +1 -1
  83. package/dist/{server-setup-s2Os8RfG.js → server-setup-D7ABbEs1.js} +109 -10
  84. package/dist/server-setup-D7ABbEs1.js.map +1 -0
  85. package/dist/{start-DV5iDhbP.js → start-Dpwpnq99.js} +3 -3
  86. package/dist/{start-DV5iDhbP.js.map → start-Dpwpnq99.js.map} +1 -1
  87. package/dist/{stop-gate-hook-BEU8qQrC.js → stop-gate-hook-BUCxa5Kc.js} +4 -4
  88. package/dist/{stop-gate-hook-BEU8qQrC.js.map → stop-gate-hook-BUCxa5Kc.js.map} +1 -1
  89. package/dist/{stop-gate-policy-qzqXfRxE.js → stop-gate-policy--bpyxxXU.js} +3 -3
  90. package/dist/{stop-gate-policy-qzqXfRxE.js.map → stop-gate-policy--bpyxxXU.js.map} +1 -1
  91. package/dist/{token-CCg-Ov5q.js → token-ClzS23Y2.js} +2 -2
  92. package/dist/{token-CCg-Ov5q.js.map → token-ClzS23Y2.js.map} +1 -1
  93. package/dist/{worker-dispatch-CH-NN5FW.js → worker-dispatch-DMIdrlsF.js} +2 -2
  94. package/dist/{worker-dispatch-CH-NN5FW.js.map → worker-dispatch-DMIdrlsF.js.map} +1 -1
  95. package/package.json +1 -1
  96. package/dist/claude-D_Me80Yi.js.map +0 -1
  97. package/dist/engine-DyzGsCUb.js +0 -2
  98. package/dist/lifecycle-B0USSJvd.js +0 -2
  99. package/dist/lifecycle-CQFjaQc0.js +0 -2
  100. package/dist/paths-DyX6SEnd.js +0 -2
  101. package/dist/provision-BYdIsKcp.js.map +0 -1
  102. package/dist/server-setup-s2Os8RfG.js.map +0 -1
@@ -0,0 +1,298 @@
1
+ import { t as PATHS } from "./paths-CMxlQEfQ.js";
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import fs$1 from "node:fs/promises";
5
+ //#region src/lib/aic-usage.ts
6
+ /** Nano-AIU per AI credit (SI prefix, per Copilot SDK docs). */
7
+ const NANO_AIU_PER_CREDIT = 1e9;
8
+ function nonNegativeNumber(value) {
9
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0) return 0;
10
+ return value;
11
+ }
12
+ function parseTokenDetail(value) {
13
+ if (!value || typeof value !== "object" || Array.isArray(value)) return;
14
+ const record = value;
15
+ const batchSize = nonNegativeNumber(record.batch_size);
16
+ if (batchSize <= 0) return void 0;
17
+ return {
18
+ ...typeof record.model === "string" && record.model.length > 0 ? { model: record.model } : {},
19
+ ...typeof record.token_type === "string" && record.token_type.length > 0 ? { tokenType: record.token_type } : {},
20
+ tokenCount: Math.floor(nonNegativeNumber(record.token_count)),
21
+ batchSize: Math.floor(batchSize),
22
+ costPerBatch: nonNegativeNumber(record.cost_per_batch)
23
+ };
24
+ }
25
+ /**
26
+ * Extract a validated `CopilotUsage` from an unknown value (typically
27
+ * `responseBody.copilot_usage` or an SSE event's `copilot_usage`).
28
+ * Returns `undefined` when absent or invalid — never throws.
29
+ */
30
+ function extractCopilotUsage(value) {
31
+ if (!value || typeof value !== "object" || Array.isArray(value)) return;
32
+ const record = value;
33
+ if (typeof record.total_nano_aiu !== "number" || !Number.isFinite(record.total_nano_aiu) || record.total_nano_aiu < 0) return;
34
+ const details = [];
35
+ if (Array.isArray(record.token_details)) for (const entry of record.token_details) {
36
+ const parsed = parseTokenDetail(entry);
37
+ if (parsed) details.push(parsed);
38
+ }
39
+ return {
40
+ totalNanoAiu: Math.floor(record.total_nano_aiu),
41
+ tokenDetails: details
42
+ };
43
+ }
44
+ /** Convert nano-AIU to AI credits. */
45
+ function nanoAiuToCredits(nanoAiu) {
46
+ if (!Number.isFinite(nanoAiu) || nanoAiu <= 0) return 0;
47
+ return nanoAiu / NANO_AIU_PER_CREDIT;
48
+ }
49
+ /**
50
+ * Compact display: `12.42` for totals ≥ 0.01, more precision below.
51
+ * Always a plain number string — callers add units/context.
52
+ */
53
+ function formatAic(credits) {
54
+ if (!Number.isFinite(credits) || credits <= 0) return "0";
55
+ if (credits >= 100) return credits.toFixed(1);
56
+ if (credits >= 1) return credits.toFixed(2);
57
+ if (credits >= .01) return credits.toFixed(3);
58
+ return credits.toPrecision(2);
59
+ }
60
+ //#endregion
61
+ //#region src/lib/aic-ledger.ts
62
+ /**
63
+ * Per-launch AIC (AI Credits) ledger.
64
+ *
65
+ * Every route handler records upstream `copilot_usage` here as a side effect
66
+ * (bytes pass through untouched). The totals feed two consumers:
67
+ *
68
+ * 1. `internal-aic-status` — runs as a SEPARATE process on every status-line
69
+ * tick, so it cannot read in-process memory. Each `record()` therefore
70
+ * also persists an atomic snapshot file; the ledger path is handed to the
71
+ * spawned child via `GH_ROUTER_AIC_LEDGER` and baked into the statusLine
72
+ * command.
73
+ * 2. The `claude` exit summary — reads the in-process snapshot.
74
+ *
75
+ * Keyed per proxy process (one file per PID under `<APP_DIR>/aic-ledger/`),
76
+ * so concurrent launches never mix. Snapshot writes are best-effort and never
77
+ * throw into the request path. Stale files (dead PID, >24h) are swept at
78
+ * startup of the next record and on shutdown.
79
+ */
80
+ function emptyModelTokens() {
81
+ return {
82
+ input: 0,
83
+ cache_read: 0,
84
+ cache_write: 0,
85
+ output: 0,
86
+ other: 0
87
+ };
88
+ }
89
+ function emptySnapshot() {
90
+ return {
91
+ totalNanoAiu: 0,
92
+ requests: 0,
93
+ perModel: {},
94
+ perTokenType: {},
95
+ tokensByModel: {}
96
+ };
97
+ }
98
+ let ledger = emptySnapshot();
99
+ function ledgerDir() {
100
+ return process.env.GH_ROUTER_AIC_LEDGER_DIR ?? path.join(PATHS.APP_DIR, "aic-ledger");
101
+ }
102
+ /**
103
+ * Snapshot file for this proxy process. Overridable via `GH_ROUTER_AIC_LEDGER`
104
+ * (used by tests and by the spawned child's env).
105
+ */
106
+ function aicLedgerPath() {
107
+ const override = process.env.GH_ROUTER_AIC_LEDGER;
108
+ if (override && override.length > 0) return override;
109
+ return path.join(ledgerDir(), `${process.pid}.json`);
110
+ }
111
+ /** Best-effort persist; never throws. */
112
+ function persistBestEffort() {
113
+ try {
114
+ const file = aicLedgerPath();
115
+ fs.mkdirSync(path.dirname(file), { recursive: true });
116
+ const tmp = `${file}.${process.pid}.tmp`;
117
+ fs.writeFileSync(tmp, `${JSON.stringify(ledger)}\n`, { mode: 384 });
118
+ fs.renameSync(tmp, file);
119
+ } catch {}
120
+ }
121
+ /**
122
+ * Record one upstream `copilot_usage` reading. No-op on undefined.
123
+ * `model` is the resolved (Copilot-side) model id when known.
124
+ */
125
+ function recordAic(model, usage) {
126
+ if (!usage) return;
127
+ ledger.totalNanoAiu += usage.totalNanoAiu;
128
+ ledger.requests += 1;
129
+ const key = model && model.length > 0 ? model : "unknown";
130
+ const entry = ledger.perModel[key] ?? {
131
+ nanoAiu: 0,
132
+ requests: 0
133
+ };
134
+ entry.nanoAiu += usage.totalNanoAiu;
135
+ entry.requests += 1;
136
+ ledger.perModel[key] = entry;
137
+ ledger.tokensByModel[key] ??= emptyModelTokens();
138
+ for (const detail of usage.tokenDetails) {
139
+ const type = detail.tokenType ?? "unknown";
140
+ const nano = Math.round(detail.tokenCount * detail.costPerBatch / detail.batchSize);
141
+ ledger.perTokenType[type] = (ledger.perTokenType[type] ?? 0) + nano;
142
+ const counts = ledger.tokensByModel[key] ?? emptyModelTokens();
143
+ const bucket = tokenBucket(type);
144
+ counts[bucket] += detail.tokenCount;
145
+ ledger.tokensByModel[key] = counts;
146
+ }
147
+ persistBestEffort();
148
+ }
149
+ /**
150
+ * Map an upstream `token_type` to its count bucket. Unknown/missing types
151
+ * land in `other` (priced at the model's input factor downstream) rather
152
+ * than being dropped — the observed universe is the four known types, this
153
+ * is the just-in-case bucket.
154
+ */
155
+ function tokenBucket(type) {
156
+ switch (type) {
157
+ case "input": return "input";
158
+ case "cache_read": return "cache_read";
159
+ case "cache_write": return "cache_write";
160
+ case "output": return "output";
161
+ default: return "other";
162
+ }
163
+ }
164
+ /**
165
+ * Extract `copilot_usage` from a response object or SSE event-data object,
166
+ * record it under `model`, and return its nano-AIU for `logRequest`.
167
+ * Returns `undefined` when absent/invalid. Never throws.
168
+ */
169
+ function extractAndRecordAic(model, container) {
170
+ if (!container || typeof container !== "object" || Array.isArray(container)) return;
171
+ const usage = extractCopilotUsage(container.copilot_usage);
172
+ if (!usage) return void 0;
173
+ recordAic(model, usage);
174
+ return usage.totalNanoAiu;
175
+ }
176
+ /** In-process snapshot (defensive copy). */
177
+ function aicSnapshot() {
178
+ return {
179
+ totalNanoAiu: ledger.totalNanoAiu,
180
+ requests: ledger.requests,
181
+ perModel: Object.fromEntries(Object.entries(ledger.perModel).map(([k, v]) => [k, { ...v }])),
182
+ perTokenType: { ...ledger.perTokenType },
183
+ tokensByModel: Object.fromEntries(Object.entries(ledger.tokensByModel).map(([k, v]) => [k, { ...v }]))
184
+ };
185
+ }
186
+ /**
187
+ * Read a persisted snapshot file (the status-hook path). Returns undefined
188
+ * when missing/unreadable — the hook then prints nothing.
189
+ */
190
+ function readAicSnapshotFile(file) {
191
+ try {
192
+ const raw = fs.readFileSync(file, "utf8");
193
+ const parsed = JSON.parse(raw);
194
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return;
195
+ const record = parsed;
196
+ if (typeof record.totalNanoAiu !== "number" || typeof record.requests !== "number") return;
197
+ return {
198
+ totalNanoAiu: Math.max(0, Math.floor(record.totalNanoAiu)),
199
+ requests: Math.max(0, Math.floor(record.requests)),
200
+ perModel: record.perModel && typeof record.perModel === "object" ? record.perModel : {},
201
+ perTokenType: record.perTokenType && typeof record.perTokenType === "object" ? record.perTokenType : {},
202
+ tokensByModel: sanitizeModelTokens(record.tokensByModel)
203
+ };
204
+ } catch {
205
+ return;
206
+ }
207
+ }
208
+ /** Best-effort sanitize of persisted per-model token counts; `{}` when absent. */
209
+ function sanitizeModelTokens(value) {
210
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
211
+ const out = {};
212
+ for (const [model, counts] of Object.entries(value)) {
213
+ if (!counts || typeof counts !== "object" || Array.isArray(counts)) continue;
214
+ const entry = counts;
215
+ const clean = emptyModelTokens();
216
+ let ok = true;
217
+ for (const field of [
218
+ "input",
219
+ "cache_read",
220
+ "cache_write",
221
+ "output",
222
+ "other"
223
+ ]) {
224
+ const n = entry[field];
225
+ if (n === void 0) continue;
226
+ if (typeof n !== "number" || !Number.isFinite(n) || n < 0) {
227
+ ok = false;
228
+ break;
229
+ }
230
+ clean[field] = Math.floor(n);
231
+ }
232
+ if (ok) out[model] = clean;
233
+ }
234
+ return out;
235
+ }
236
+ /** Total credits for a snapshot. */
237
+ function aicTotalCredits(snapshot) {
238
+ return nanoAiuToCredits(snapshot.totalNanoAiu);
239
+ }
240
+ /** One-line status fragment: `[AIC 12.42]`. Empty string when nothing recorded. */
241
+ function formatAicStatus(snapshot) {
242
+ if (snapshot.requests === 0 || snapshot.totalNanoAiu <= 0) return "";
243
+ return `[AIC ${formatAic(aicTotalCredits(snapshot))}]`;
244
+ }
245
+ /**
246
+ * Multi-line exit summary. `verbose` adds per-model and per-type breakdowns
247
+ * (only from upstream-measured values — never estimates).
248
+ */
249
+ function formatAicExitSummary(snapshot, opts = {}) {
250
+ const total = aicTotalCredits(snapshot);
251
+ const reqWord = snapshot.requests === 1 ? "request" : "requests";
252
+ const lines = [`AIC consumed this session: ${formatAic(total)} credits (~$${(total / 100).toFixed(2)}) across ${snapshot.requests} ${reqWord}`];
253
+ if (opts.verbose) {
254
+ const models = Object.entries(snapshot.perModel).sort((a, b) => b[1].nanoAiu - a[1].nanoAiu);
255
+ for (const [model, entry] of models) {
256
+ const rWord = entry.requests === 1 ? "request" : "requests";
257
+ lines.push(` ${model}: ${formatAic(nanoAiuToCredits(entry.nanoAiu))} credits across ${entry.requests} ${rWord}`);
258
+ }
259
+ const types = Object.entries(snapshot.perTokenType).sort((a, b) => b[1] - a[1]);
260
+ if (types.length > 0) lines.push(` by type: ${types.map(([t, n]) => `${t}=${formatAic(nanoAiuToCredits(n))}`).join(" ")}`);
261
+ }
262
+ return lines.join("\n");
263
+ }
264
+ /** Remove this process's snapshot file; never throws. */
265
+ async function removeAicLedgerFile() {
266
+ try {
267
+ await fs$1.rm(aicLedgerPath(), { force: true });
268
+ } catch {}
269
+ }
270
+ /** Sweep stale ledger files (dead PID or >24h old); never throws. */
271
+ async function sweepStaleAicLedgerFiles() {
272
+ try {
273
+ const dir = ledgerDir();
274
+ const entries = await fs$1.readdir(dir).catch(() => []);
275
+ const now = Date.now();
276
+ await Promise.all(entries.map(async (entry) => {
277
+ if (!/^\d+\.json$/.test(entry)) return;
278
+ const file = path.join(dir, entry);
279
+ try {
280
+ const stat = await fs$1.stat(file);
281
+ if (!await isPidAlive(Number(entry.slice(0, -5))) || now - stat.mtimeMs > 864e5) await fs$1.rm(file, { force: true });
282
+ } catch {}
283
+ }));
284
+ } catch {}
285
+ }
286
+ async function isPidAlive(pid) {
287
+ if (!Number.isInteger(pid) || pid <= 0) return false;
288
+ try {
289
+ process.kill(pid, 0);
290
+ return true;
291
+ } catch {
292
+ return false;
293
+ }
294
+ }
295
+ //#endregion
296
+ export { formatAicExitSummary as a, recordAic as c, extractCopilotUsage as d, formatAic as f, extractAndRecordAic as i, removeAicLedgerFile as l, aicSnapshot as n, formatAicStatus as o, nanoAiuToCredits as p, aicTotalCredits as r, readAicSnapshotFile as s, aicLedgerPath as t, sweepStaleAicLedgerFiles as u };
297
+
298
+ //# sourceMappingURL=aic-ledger-BS47yb_C.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aic-ledger-BS47yb_C.js","names":["fsp"],"sources":["../src/lib/aic-usage.ts","../src/lib/aic-ledger.ts"],"sourcesContent":["/**\n * AIC (AI Credits) extraction from upstream Copilot `copilot_usage` fields.\n *\n * Verified live (2026-09-14) on all three native endpoints: `/responses`\n * (non-stream top-level + terminal `response.completed` event), `/chat/completions`\n * (non-stream top-level), and `/v1/messages` (non-stream top-level + terminal\n * `message_delta` event). No special request header is required — the field\n * arrives with the proxy's stock headers.\n *\n * Shape:\n * ```json\n * \"copilot_usage\": {\n * \"token_details\": [\n * {\"batch_size\":1000000,\"cost_per_batch\":20000000000,\n * \"model\":\"gpt-5.6-luna\",\"token_count\":11,\"token_type\":\"input\"},\n * ...\n * ],\n * \"total_nano_aiu\": 820000\n * }\n * ```\n * Credits = `total_nano_aiu / 1e9` (SI nano prefix — the same convention the\n * Copilot SDK docs use; treat GitHub billing docs as source of truth before\n * surfacing currency equivalents). Per-type cost reconstructs as\n * `token_count × cost_per_batch / batch_size / 1e9` (verified arithmetically\n * against `total_nano_aiu` on live captures).\n *\n * All parsing is total and never throws: malformed entries are skipped, and a\n * missing/invalid field yields `undefined` so callers fall back cleanly.\n */\n\n/** One entry of `copilot_usage.token_details`. */\nexport interface CopilotTokenDetail {\n model?: string\n tokenType?: string\n tokenCount: number\n batchSize: number\n costPerBatch: number\n}\n\n/** Parsed `copilot_usage` object. */\nexport interface CopilotUsage {\n totalNanoAiu: number\n tokenDetails: Array<CopilotTokenDetail>\n}\n\n/** Nano-AIU per AI credit (SI prefix, per Copilot SDK docs). */\nexport const NANO_AIU_PER_CREDIT = 1_000_000_000\n\nfunction nonNegativeNumber(value: unknown): number {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) {\n return 0\n }\n return value\n}\n\nfunction parseTokenDetail(value: unknown): CopilotTokenDetail | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return undefined\n }\n const record = value as Record<string, unknown>\n const batchSize = nonNegativeNumber(record.batch_size)\n if (batchSize <= 0) return undefined\n return {\n ...(typeof record.model === \"string\" && record.model.length > 0\n ? { model: record.model }\n : {}),\n ...(typeof record.token_type === \"string\" && record.token_type.length > 0\n ? { tokenType: record.token_type }\n : {}),\n tokenCount: Math.floor(nonNegativeNumber(record.token_count)),\n batchSize: Math.floor(batchSize),\n costPerBatch: nonNegativeNumber(record.cost_per_batch),\n }\n}\n\n/**\n * Extract a validated `CopilotUsage` from an unknown value (typically\n * `responseBody.copilot_usage` or an SSE event's `copilot_usage`).\n * Returns `undefined` when absent or invalid — never throws.\n */\nexport function extractCopilotUsage(value: unknown): CopilotUsage | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return undefined\n }\n const record = value as Record<string, unknown>\n if (\n typeof record.total_nano_aiu !== \"number\"\n || !Number.isFinite(record.total_nano_aiu)\n || record.total_nano_aiu < 0\n ) {\n return undefined\n }\n const details: Array<CopilotTokenDetail> = []\n if (Array.isArray(record.token_details)) {\n for (const entry of record.token_details) {\n const parsed = parseTokenDetail(entry)\n if (parsed) details.push(parsed)\n }\n }\n return {\n totalNanoAiu: Math.floor(record.total_nano_aiu),\n tokenDetails: details,\n }\n}\n\n/** Convert nano-AIU to AI credits. */\nexport function nanoAiuToCredits(nanoAiu: number): number {\n if (!Number.isFinite(nanoAiu) || nanoAiu <= 0) return 0\n return nanoAiu / NANO_AIU_PER_CREDIT\n}\n\n/** Credits for one token-detail entry. */\nexport function creditsForDetail(detail: CopilotTokenDetail): number {\n return nanoAiuToCredits(\n (detail.tokenCount * detail.costPerBatch) / detail.batchSize,\n )\n}\n\n/**\n * Compact display: `12.42` for totals ≥ 0.01, more precision below.\n * Always a plain number string — callers add units/context.\n */\nexport function formatAic(credits: number): string {\n if (!Number.isFinite(credits) || credits <= 0) return \"0\"\n if (credits >= 100) return credits.toFixed(1)\n if (credits >= 1) return credits.toFixed(2)\n if (credits >= 0.01) return credits.toFixed(3)\n return credits.toPrecision(2)\n}\n","/**\n * Per-launch AIC (AI Credits) ledger.\n *\n * Every route handler records upstream `copilot_usage` here as a side effect\n * (bytes pass through untouched). The totals feed two consumers:\n *\n * 1. `internal-aic-status` — runs as a SEPARATE process on every status-line\n * tick, so it cannot read in-process memory. Each `record()` therefore\n * also persists an atomic snapshot file; the ledger path is handed to the\n * spawned child via `GH_ROUTER_AIC_LEDGER` and baked into the statusLine\n * command.\n * 2. The `claude` exit summary — reads the in-process snapshot.\n *\n * Keyed per proxy process (one file per PID under `<APP_DIR>/aic-ledger/`),\n * so concurrent launches never mix. Snapshot writes are best-effort and never\n * throw into the request path. Stale files (dead PID, >24h) are swept at\n * startup of the next record and on shutdown.\n */\n\nimport fs from \"node:fs\"\nimport fsp from \"node:fs/promises\"\nimport path from \"node:path\"\n\nimport { PATHS } from \"~/lib/paths\"\n\nimport {\n extractCopilotUsage,\n formatAic,\n nanoAiuToCredits,\n type CopilotUsage,\n} from \"./aic-usage\"\n\nexport interface AicModelEntry {\n nanoAiu: number\n requests: number\n}\n\n/** Token counts per model per upstream `token_type`, for the cost table. */\nexport interface AicModelTokens {\n /** Upstream `input` type: fresh (uncached) input tokens. */\n input: number\n /** Upstream `cache_read` type. */\n cache_read: number\n /** Upstream `cache_write` type. */\n cache_write: number\n /** Upstream `output` type. */\n output: number\n /** Any other/missing `token_type`: never dropped silently, priced at input. */\n other: number\n}\n\nexport interface AicSnapshot {\n totalNanoAiu: number\n requests: number\n perModel: Record<string, AicModelEntry>\n /** Reconstructed nano-AIU per token_type (input/cache_read/cache_write/output). */\n perTokenType: Record<string, number>\n /** Raw token counts per model per type (exit cost table + rate math). */\n tokensByModel: Record<string, AicModelTokens>\n}\n\nfunction emptyModelTokens(): AicModelTokens {\n return { input: 0, cache_read: 0, cache_write: 0, output: 0, other: 0 }\n}\n\nfunction emptySnapshot(): AicSnapshot {\n return {\n totalNanoAiu: 0,\n requests: 0,\n perModel: {},\n perTokenType: {},\n tokensByModel: {},\n }\n}\n\nlet ledger: AicSnapshot = emptySnapshot()\n\n/** @internal — reset module state between test cases. */\nexport function __resetAicLedgerForTests(): void {\n ledger = emptySnapshot()\n}\n\nfunction ledgerDir(): string {\n return (\n process.env.GH_ROUTER_AIC_LEDGER_DIR ?? path.join(PATHS.APP_DIR, \"aic-ledger\")\n )\n}\n\n/**\n * Snapshot file for this proxy process. Overridable via `GH_ROUTER_AIC_LEDGER`\n * (used by tests and by the spawned child's env).\n */\nexport function aicLedgerPath(): string {\n const override = process.env.GH_ROUTER_AIC_LEDGER\n if (override && override.length > 0) return override\n return path.join(ledgerDir(), `${process.pid}.json`)\n}\n\n/** Best-effort persist; never throws. */\nfunction persistBestEffort(): void {\n try {\n const file = aicLedgerPath()\n fs.mkdirSync(path.dirname(file), { recursive: true })\n const tmp = `${file}.${process.pid}.tmp`\n fs.writeFileSync(tmp, `${JSON.stringify(ledger)}\\n`, { mode: 0o600 })\n fs.renameSync(tmp, file)\n } catch {\n // Telemetry must never break a request.\n }\n}\n\n/**\n * Record one upstream `copilot_usage` reading. No-op on undefined.\n * `model` is the resolved (Copilot-side) model id when known.\n */\nexport function recordAic(\n model: string | undefined,\n usage: CopilotUsage | undefined,\n): void {\n if (!usage) return\n ledger.totalNanoAiu += usage.totalNanoAiu\n ledger.requests += 1\n const key = model && model.length > 0 ? model : \"unknown\"\n const entry = ledger.perModel[key] ?? { nanoAiu: 0, requests: 0 }\n entry.nanoAiu += usage.totalNanoAiu\n entry.requests += 1\n ledger.perModel[key] = entry\n ledger.tokensByModel[key] ??= emptyModelTokens()\n for (const detail of usage.tokenDetails) {\n const type = detail.tokenType ?? \"unknown\"\n // Reconstruct nano-AIU per token type from the priced detail.\n const nano = Math.round(\n (detail.tokenCount * detail.costPerBatch) / detail.batchSize,\n )\n ledger.perTokenType[type] = (ledger.perTokenType[type] ?? 0) + nano\n // Retain raw counts per model per type for the exit cost table. The\n // hook only reads them; pricing still flows exclusively through nano.\n const counts = ledger.tokensByModel[key] ?? emptyModelTokens()\n const bucket = tokenBucket(type)\n counts[bucket] += detail.tokenCount\n ledger.tokensByModel[key] = counts\n }\n persistBestEffort()\n}\n\n/**\n * Map an upstream `token_type` to its count bucket. Unknown/missing types\n * land in `other` (priced at the model's input factor downstream) rather\n * than being dropped — the observed universe is the four known types, this\n * is the just-in-case bucket.\n */\nfunction tokenBucket(type: string): keyof AicModelTokens {\n switch (type) {\n case \"input\":\n return \"input\"\n case \"cache_read\":\n return \"cache_read\"\n case \"cache_write\":\n return \"cache_write\"\n case \"output\":\n return \"output\"\n default:\n return \"other\"\n }\n}\n\n/**\n * Extract `copilot_usage` from a response object or SSE event-data object,\n * record it under `model`, and return its nano-AIU for `logRequest`.\n * Returns `undefined` when absent/invalid. Never throws.\n */\nexport function extractAndRecordAic(\n model: string | undefined,\n container: unknown,\n): number | undefined {\n if (!container || typeof container !== \"object\" || Array.isArray(container)) {\n return undefined\n }\n const usage = extractCopilotUsage(\n (container as Record<string, unknown>).copilot_usage,\n )\n if (!usage) return undefined\n recordAic(model, usage)\n return usage.totalNanoAiu\n}\n\n/** In-process snapshot (defensive copy). */\nexport function aicSnapshot(): AicSnapshot {\n return {\n totalNanoAiu: ledger.totalNanoAiu,\n requests: ledger.requests,\n perModel: Object.fromEntries(\n Object.entries(ledger.perModel).map(([k, v]) => [k, { ...v }]),\n ),\n perTokenType: { ...ledger.perTokenType },\n tokensByModel: Object.fromEntries(\n Object.entries(ledger.tokensByModel).map(([k, v]) => [k, { ...v }]),\n ),\n }\n}\n\n/**\n * Read a persisted snapshot file (the status-hook path). Returns undefined\n * when missing/unreadable — the hook then prints nothing.\n */\nexport function readAicSnapshotFile(file: string): AicSnapshot | undefined {\n try {\n const raw = fs.readFileSync(file, \"utf8\")\n const parsed: unknown = JSON.parse(raw)\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n return undefined\n }\n const record = parsed as Record<string, unknown>\n if (\n typeof record.totalNanoAiu !== \"number\"\n || typeof record.requests !== \"number\"\n ) {\n return undefined\n }\n return {\n totalNanoAiu: Math.max(0, Math.floor(record.totalNanoAiu)),\n requests: Math.max(0, Math.floor(record.requests)),\n perModel:\n record.perModel && typeof record.perModel === \"object\"\n ? (record.perModel as AicSnapshot[\"perModel\"])\n : {},\n perTokenType:\n record.perTokenType && typeof record.perTokenType === \"object\"\n ? (record.perTokenType as AicSnapshot[\"perTokenType\"])\n : {},\n // Pre-tokens files (written before this field existed) read as empty\n // rather than failing the hook.\n tokensByModel: sanitizeModelTokens(record.tokensByModel),\n }\n } catch {\n return undefined\n }\n}\n\n/** Best-effort sanitize of persisted per-model token counts; `{}` when absent. */\nfunction sanitizeModelTokens(value: unknown): Record<string, AicModelTokens> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return {}\n const out: Record<string, AicModelTokens> = {}\n for (const [model, counts] of Object.entries(value as Record<string, unknown>)) {\n if (!counts || typeof counts !== \"object\" || Array.isArray(counts)) continue\n const entry = counts as Record<string, unknown>\n const clean = emptyModelTokens()\n let ok = true\n for (const field of [\"input\", \"cache_read\", \"cache_write\", \"output\", \"other\"] as const) {\n const n = entry[field]\n if (n === undefined) continue\n if (typeof n !== \"number\" || !Number.isFinite(n) || n < 0) {\n ok = false\n break\n }\n clean[field] = Math.floor(n)\n }\n if (ok) out[model] = clean\n }\n return out\n}\n\n/** Total credits for a snapshot. */\nexport function aicTotalCredits(snapshot: AicSnapshot): number {\n return nanoAiuToCredits(snapshot.totalNanoAiu)\n}\n\n/** One-line status fragment: `[AIC 12.42]`. Empty string when nothing recorded. */\nexport function formatAicStatus(snapshot: AicSnapshot): string {\n if (snapshot.requests === 0 || snapshot.totalNanoAiu <= 0) return \"\"\n return `[AIC ${formatAic(aicTotalCredits(snapshot))}]`\n}\n\n/**\n * Multi-line exit summary. `verbose` adds per-model and per-type breakdowns\n * (only from upstream-measured values — never estimates).\n */\nexport function formatAicExitSummary(\n snapshot: AicSnapshot,\n opts: { verbose?: boolean } = {},\n): string {\n const total = aicTotalCredits(snapshot)\n const reqWord = snapshot.requests === 1 ? \"request\" : \"requests\"\n const lines = [\n `AIC consumed this session: ${formatAic(total)} credits (~$${(total / 100).toFixed(2)}) across ${snapshot.requests} ${reqWord}`,\n ]\n if (opts.verbose) {\n const models = Object.entries(snapshot.perModel).sort(\n (a, b) => b[1].nanoAiu - a[1].nanoAiu,\n )\n for (const [model, entry] of models) {\n const rWord = entry.requests === 1 ? \"request\" : \"requests\"\n lines.push(\n ` ${model}: ${formatAic(nanoAiuToCredits(entry.nanoAiu))} credits across ${entry.requests} ${rWord}`,\n )\n }\n const types = Object.entries(snapshot.perTokenType).sort(\n (a, b) => b[1] - a[1],\n )\n if (types.length > 0) {\n lines.push(\n ` by type: ${types.map(([t, n]) => `${t}=${formatAic(nanoAiuToCredits(n))}`).join(\" \")}`,\n )\n }\n }\n return lines.join(\"\\n\")\n}\n\n/** Remove this process's snapshot file; never throws. */\nexport async function removeAicLedgerFile(): Promise<void> {\n try {\n await fsp.rm(aicLedgerPath(), { force: true })\n } catch {\n // Best-effort cleanup.\n }\n}\n\n/** Sweep stale ledger files (dead PID or >24h old); never throws. */\nexport async function sweepStaleAicLedgerFiles(): Promise<void> {\n try {\n const dir = ledgerDir()\n const entries = await fsp.readdir(dir).catch(() => [] as Array<string>)\n const now = Date.now()\n await Promise.all(\n entries.map(async (entry) => {\n if (!/^\\d+\\.json$/.test(entry)) return\n const file = path.join(dir, entry)\n try {\n const stat = await fsp.stat(file)\n const pid = Number(entry.slice(0, -\".json\".length))\n const alive = await isPidAlive(pid)\n if (!alive || now - stat.mtimeMs > 24 * 60 * 60 * 1000) {\n await fsp.rm(file, { force: true })\n }\n } catch {\n // Best-effort per file.\n }\n }),\n )\n } catch {\n // Best-effort sweep.\n }\n}\n\nasync function isPidAlive(pid: number): Promise<boolean> {\n if (!Number.isInteger(pid) || pid <= 0) return false\n try {\n process.kill(pid, 0)\n return true\n } catch {\n return false\n }\n}\n"],"mappings":";;;;;;AA8CA,MAAa,sBAAsB;AAEnC,SAAS,kBAAkB,OAAwB;CACjD,IAAI,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,KAAK,KAAK,QAAQ,GAClE,OAAO;CAET,OAAO;AACT;AAEA,SAAS,iBAAiB,OAAgD;CACxE,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAC5D;CAEF,MAAM,SAAS;CACf,MAAM,YAAY,kBAAkB,OAAO,UAAU;CACrD,IAAI,aAAa,GAAG,OAAO,KAAA;CAC3B,OAAO;EACL,GAAI,OAAO,OAAO,UAAU,YAAY,OAAO,MAAM,SAAS,IAC1D,EAAE,OAAO,OAAO,MAAM,IACtB,CAAC;EACL,GAAI,OAAO,OAAO,eAAe,YAAY,OAAO,WAAW,SAAS,IACpE,EAAE,WAAW,OAAO,WAAW,IAC/B,CAAC;EACL,YAAY,KAAK,MAAM,kBAAkB,OAAO,WAAW,CAAC;EAC5D,WAAW,KAAK,MAAM,SAAS;EAC/B,cAAc,kBAAkB,OAAO,cAAc;CACvD;AACF;;;;;;AAOA,SAAgB,oBAAoB,OAA0C;CAC5E,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAC5D;CAEF,MAAM,SAAS;CACf,IACE,OAAO,OAAO,mBAAmB,YAC9B,CAAC,OAAO,SAAS,OAAO,cAAc,KACtC,OAAO,iBAAiB,GAE3B;CAEF,MAAM,UAAqC,CAAC;CAC5C,IAAI,MAAM,QAAQ,OAAO,aAAa,GACpC,KAAK,MAAM,SAAS,OAAO,eAAe;EACxC,MAAM,SAAS,iBAAiB,KAAK;EACrC,IAAI,QAAQ,QAAQ,KAAK,MAAM;CACjC;CAEF,OAAO;EACL,cAAc,KAAK,MAAM,OAAO,cAAc;EAC9C,cAAc;CAChB;AACF;;AAGA,SAAgB,iBAAiB,SAAyB;CACxD,IAAI,CAAC,OAAO,SAAS,OAAO,KAAK,WAAW,GAAG,OAAO;CACtD,OAAO,UAAU;AACnB;;;;;AAaA,SAAgB,UAAU,SAAyB;CACjD,IAAI,CAAC,OAAO,SAAS,OAAO,KAAK,WAAW,GAAG,OAAO;CACtD,IAAI,WAAW,KAAK,OAAO,QAAQ,QAAQ,CAAC;CAC5C,IAAI,WAAW,GAAG,OAAO,QAAQ,QAAQ,CAAC;CAC1C,IAAI,WAAW,KAAM,OAAO,QAAQ,QAAQ,CAAC;CAC7C,OAAO,QAAQ,YAAY,CAAC;AAC9B;;;;;;;;;;;;;;;;;;;;;ACnEA,SAAS,mBAAmC;CAC1C,OAAO;EAAE,OAAO;EAAG,YAAY;EAAG,aAAa;EAAG,QAAQ;EAAG,OAAO;CAAE;AACxE;AAEA,SAAS,gBAA6B;CACpC,OAAO;EACL,cAAc;EACd,UAAU;EACV,UAAU,CAAC;EACX,cAAc,CAAC;EACf,eAAe,CAAC;CAClB;AACF;AAEA,IAAI,SAAsB,cAAc;AAOxC,SAAS,YAAoB;CAC3B,OACE,QAAQ,IAAI,4BAA4B,KAAK,KAAK,MAAM,SAAS,YAAY;AAEjF;;;;;AAMA,SAAgB,gBAAwB;CACtC,MAAM,WAAW,QAAQ,IAAI;CAC7B,IAAI,YAAY,SAAS,SAAS,GAAG,OAAO;CAC5C,OAAO,KAAK,KAAK,UAAU,GAAG,GAAG,QAAQ,IAAI,MAAM;AACrD;;AAGA,SAAS,oBAA0B;CACjC,IAAI;EACF,MAAM,OAAO,cAAc;EAC3B,GAAG,UAAU,KAAK,QAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;EACpD,MAAM,MAAM,GAAG,KAAK,GAAG,QAAQ,IAAI;EACnC,GAAG,cAAc,KAAK,GAAG,KAAK,UAAU,MAAM,EAAE,KAAK,EAAE,MAAM,IAAM,CAAC;EACpE,GAAG,WAAW,KAAK,IAAI;CACzB,QAAQ,CAER;AACF;;;;;AAMA,SAAgB,UACd,OACA,OACM;CACN,IAAI,CAAC,OAAO;CACZ,OAAO,gBAAgB,MAAM;CAC7B,OAAO,YAAY;CACnB,MAAM,MAAM,SAAS,MAAM,SAAS,IAAI,QAAQ;CAChD,MAAM,QAAQ,OAAO,SAAS,QAAQ;EAAE,SAAS;EAAG,UAAU;CAAE;CAChE,MAAM,WAAW,MAAM;CACvB,MAAM,YAAY;CAClB,OAAO,SAAS,OAAO;CACvB,OAAO,cAAc,SAAS,iBAAiB;CAC/C,KAAK,MAAM,UAAU,MAAM,cAAc;EACvC,MAAM,OAAO,OAAO,aAAa;EAEjC,MAAM,OAAO,KAAK,MACf,OAAO,aAAa,OAAO,eAAgB,OAAO,SACrD;EACA,OAAO,aAAa,SAAS,OAAO,aAAa,SAAS,KAAK;EAG/D,MAAM,SAAS,OAAO,cAAc,QAAQ,iBAAiB;EAC7D,MAAM,SAAS,YAAY,IAAI;EAC/B,OAAO,WAAW,OAAO;EACzB,OAAO,cAAc,OAAO;CAC9B;CACA,kBAAkB;AACpB;;;;;;;AAQA,SAAS,YAAY,MAAoC;CACvD,QAAQ,MAAR;EACE,KAAK,SACH,OAAO;EACT,KAAK,cACH,OAAO;EACT,KAAK,eACH,OAAO;EACT,KAAK,UACH,OAAO;EACT,SACE,OAAO;CACX;AACF;;;;;;AAOA,SAAgB,oBACd,OACA,WACoB;CACpB,IAAI,CAAC,aAAa,OAAO,cAAc,YAAY,MAAM,QAAQ,SAAS,GACxE;CAEF,MAAM,QAAQ,oBACX,UAAsC,aACzC;CACA,IAAI,CAAC,OAAO,OAAO,KAAA;CACnB,UAAU,OAAO,KAAK;CACtB,OAAO,MAAM;AACf;;AAGA,SAAgB,cAA2B;CACzC,OAAO;EACL,cAAc,OAAO;EACrB,UAAU,OAAO;EACjB,UAAU,OAAO,YACf,OAAO,QAAQ,OAAO,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAC/D;EACA,cAAc,EAAE,GAAG,OAAO,aAAa;EACvC,eAAe,OAAO,YACpB,OAAO,QAAQ,OAAO,aAAa,CAAC,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CACpE;CACF;AACF;;;;;AAMA,SAAgB,oBAAoB,MAAuC;CACzE,IAAI;EACF,MAAM,MAAM,GAAG,aAAa,MAAM,MAAM;EACxC,MAAM,SAAkB,KAAK,MAAM,GAAG;EACtC,IAAI,CAAC,UAAU,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,GAC/D;EAEF,MAAM,SAAS;EACf,IACE,OAAO,OAAO,iBAAiB,YAC5B,OAAO,OAAO,aAAa,UAE9B;EAEF,OAAO;GACL,cAAc,KAAK,IAAI,GAAG,KAAK,MAAM,OAAO,YAAY,CAAC;GACzD,UAAU,KAAK,IAAI,GAAG,KAAK,MAAM,OAAO,QAAQ,CAAC;GACjD,UACE,OAAO,YAAY,OAAO,OAAO,aAAa,WACzC,OAAO,WACR,CAAC;GACP,cACE,OAAO,gBAAgB,OAAO,OAAO,iBAAiB,WACjD,OAAO,eACR,CAAC;GAGP,eAAe,oBAAoB,OAAO,aAAa;EACzD;CACF,QAAQ;EACN;CACF;AACF;;AAGA,SAAS,oBAAoB,OAAgD;CAC3E,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG,OAAO,CAAC;CACzE,MAAM,MAAsC,CAAC;CAC7C,KAAK,MAAM,CAAC,OAAO,WAAW,OAAO,QAAQ,KAAgC,GAAG;EAC9E,IAAI,CAAC,UAAU,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,GAAG;EACpE,MAAM,QAAQ;EACd,MAAM,QAAQ,iBAAiB;EAC/B,IAAI,KAAK;EACT,KAAK,MAAM,SAAS;GAAC;GAAS;GAAc;GAAe;GAAU;EAAO,GAAY;GACtF,MAAM,IAAI,MAAM;GAChB,IAAI,MAAM,KAAA,GAAW;GACrB,IAAI,OAAO,MAAM,YAAY,CAAC,OAAO,SAAS,CAAC,KAAK,IAAI,GAAG;IACzD,KAAK;IACL;GACF;GACA,MAAM,SAAS,KAAK,MAAM,CAAC;EAC7B;EACA,IAAI,IAAI,IAAI,SAAS;CACvB;CACA,OAAO;AACT;;AAGA,SAAgB,gBAAgB,UAA+B;CAC7D,OAAO,iBAAiB,SAAS,YAAY;AAC/C;;AAGA,SAAgB,gBAAgB,UAA+B;CAC7D,IAAI,SAAS,aAAa,KAAK,SAAS,gBAAgB,GAAG,OAAO;CAClE,OAAO,QAAQ,UAAU,gBAAgB,QAAQ,CAAC,EAAE;AACtD;;;;;AAMA,SAAgB,qBACd,UACA,OAA8B,CAAC,GACvB;CACR,MAAM,QAAQ,gBAAgB,QAAQ;CACtC,MAAM,UAAU,SAAS,aAAa,IAAI,YAAY;CACtD,MAAM,QAAQ,CACZ,8BAA8B,UAAU,KAAK,EAAE,eAAe,QAAQ,IAAA,CAAK,QAAQ,CAAC,EAAE,WAAW,SAAS,SAAS,GAAG,SACxH;CACA,IAAI,KAAK,SAAS;EAChB,MAAM,SAAS,OAAO,QAAQ,SAAS,QAAQ,CAAC,CAAC,MAC9C,GAAG,MAAM,EAAE,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,OAChC;EACA,KAAK,MAAM,CAAC,OAAO,UAAU,QAAQ;GACnC,MAAM,QAAQ,MAAM,aAAa,IAAI,YAAY;GACjD,MAAM,KACJ,KAAK,MAAM,IAAI,UAAU,iBAAiB,MAAM,OAAO,CAAC,EAAE,kBAAkB,MAAM,SAAS,GAAG,OAChG;EACF;EACA,MAAM,QAAQ,OAAO,QAAQ,SAAS,YAAY,CAAC,CAAC,MACjD,GAAG,MAAM,EAAE,KAAK,EAAE,EACrB;EACA,IAAI,MAAM,SAAS,GACjB,MAAM,KACJ,cAAc,MAAM,KAAK,CAAC,GAAG,OAAO,GAAG,EAAE,GAAG,UAAU,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,GACxF;CAEJ;CACA,OAAO,MAAM,KAAK,IAAI;AACxB;;AAGA,eAAsB,sBAAqC;CACzD,IAAI;EACF,MAAMA,KAAI,GAAG,cAAc,GAAG,EAAE,OAAO,KAAK,CAAC;CAC/C,QAAQ,CAER;AACF;;AAGA,eAAsB,2BAA0C;CAC9D,IAAI;EACF,MAAM,MAAM,UAAU;EACtB,MAAM,UAAU,MAAMA,KAAI,QAAQ,GAAG,CAAC,CAAC,YAAY,CAAC,CAAkB;EACtE,MAAM,MAAM,KAAK,IAAI;EACrB,MAAM,QAAQ,IACZ,QAAQ,IAAI,OAAO,UAAU;GAC3B,IAAI,CAAC,cAAc,KAAK,KAAK,GAAG;GAChC,MAAM,OAAO,KAAK,KAAK,KAAK,KAAK;GACjC,IAAI;IACF,MAAM,OAAO,MAAMA,KAAI,KAAK,IAAI;IAGhC,IAAI,CAAC,MADe,WADR,OAAO,MAAM,MAAM,GAAG,EAAe,CAChB,CAAC,KACpB,MAAM,KAAK,UAAU,OACjC,MAAMA,KAAI,GAAG,MAAM,EAAE,OAAO,KAAK,CAAC;GAEtC,QAAQ,CAER;EACF,CAAC,CACH;CACF,QAAQ,CAER;AACF;AAEA,eAAe,WAAW,KAA+B;CACvD,IAAI,CAAC,OAAO,UAAU,GAAG,KAAK,OAAO,GAAG,OAAO;CAC/C,IAAI;EACF,QAAQ,KAAK,KAAK,CAAC;EACnB,OAAO;CACT,QAAQ;EACN,OAAO;CACT;AACF"}
@@ -1,12 +1,12 @@
1
- import { An as CHEAP_PROFILE_MODELS, Dn as withOneMSuffix, En as oneMContextDisabled, Mn as CHEAP_PROFILE_NATIVE_EFFORTS, Nn as CHEAP_PROFILE_NATIVE_MODELS, a as buildAgentPrompt, an as CONDENSED_OPERATING_SEQUENCE, jn as CHEAP_PROFILE_NATIVE_AGENT_NAMES, l as maxPersonasFor, n as MCP_GROUPS, on as DEFINITION_OF_GREATNESS, t as GROUP_META, u as personasFor } from "./peer-mcp-personas-DklYru_1.js";
2
- import { a as isUnderClaudeConfigMirror, d as writeRuntimeFileSecure, t as PATHS } from "./paths-De1Qh9Q9.js";
3
- import { f as LUNA_SCOUT_ALIAS_ID } from "./server-setup-s2Os8RfG.js";
1
+ import { An as CHEAP_PROFILE_MODELS, Dn as withOneMSuffix, En as oneMContextDisabled, Mn as CHEAP_PROFILE_NATIVE_EFFORTS, Nn as CHEAP_PROFILE_NATIVE_MODELS, a as buildAgentPrompt, an as CONDENSED_OPERATING_SEQUENCE, jn as CHEAP_PROFILE_NATIVE_AGENT_NAMES, l as maxPersonasFor, n as MCP_GROUPS, on as DEFINITION_OF_GREATNESS, t as GROUP_META, u as personasFor } from "./peer-mcp-personas-CYWJSxPK.js";
2
+ import { a as isUnderClaudeConfigMirror, d as writeRuntimeFileSecure, t as PATHS } from "./paths-CMxlQEfQ.js";
3
+ import { f as LUNA_SCOUT_ALIAS_ID } from "./server-setup-D7ABbEs1.js";
4
4
  import { c as FAST_PROFILE_MODELS, d as FAST_PROFILE_NATIVE_MODELS, l as FAST_PROFILE_NATIVE_AGENT_NAMES, u as FAST_PROFILE_NATIVE_EFFORTS } from "./fast-profile-contract-_DhIWank.js";
5
5
  import { C as MAX_PARALLELISM_RULE, S as MAX_COORDINATOR_PROMPT, T as maxNativePrompt, a as MAX_PROFILE_NATIVE_AGENT_NAMES, i as MAX_PROFILE_MODELS, o as MAX_PROFILE_NATIVE_EFFORTS, s as MAX_PROFILE_NATIVE_MODELS, w as maxNativeDescription, x as MAX_COORDINATOR_DESCRIPTION } from "./max-profile-contract-BcrMlrmo.js";
6
- import "./self-invocation-B84JCHps.js";
7
- import { a as STRIPPED_AUTH_ROUTING_ENV_KEYS, n as buildCodexProviderConfigFlags } from "./provision-BYdIsKcp.js";
8
- import { n as buildWorkspaceHeaderHelperCommand } from "./mcp-workspace-header-B60WSR1Y.js";
9
- import { a as dispatcherAgentName, c as dispatcherTools, n as activeDispatchModes, o as dispatcherDescription, s as dispatcherPrompt } from "./worker-dispatch-CH-NN5FW.js";
6
+ import "./self-invocation-cRl4RqfW.js";
7
+ import { a as STRIPPED_AUTH_ROUTING_ENV_KEYS, n as buildCodexProviderConfigFlags } from "./provision-AwSjt-vR.js";
8
+ import { n as buildWorkspaceHeaderHelperCommand } from "./mcp-workspace-header-BYgWioLH.js";
9
+ import { a as dispatcherAgentName, c as dispatcherTools, n as activeDispatchModes, o as dispatcherDescription, s as dispatcherPrompt } from "./worker-dispatch-DMIdrlsF.js";
10
10
  import consola from "consola";
11
11
  import path from "node:path";
12
12
  import { randomBytes } from "node:crypto";
@@ -2854,4 +2854,4 @@ async function injectAttributionSuppressionIntoSettingsFile(settingsPath) {
2854
2854
  //#endregion
2855
2855
  export { writePeerMcpRuntimeFiles as C, workersKeyOf as S, sanitizeServeSettingsEnv as _, appendPeerAwarenessToMirroredClaudeMd as a, resolveCodexCliBackend as b, buildOperatingDefaultsDirective as c, prependStyleDirectiveToMirroredClaudeMd as d, buildArtifactReviewSkill as f, planModeAllowRules as g, injectAllowRules as h, writeInjectedSkill as i, prependArtifactPanelDirectiveToMirroredClaudeMd as l, configureServeDefaultPermissionMode as m, INJECTED_SKILLS as n, appendToolbeltAwarenessToMirroredClaudeMd as o, SEAMLESS_BUILTIN_TOOLS as p, injectedSkillsForLaunch as r, buildOperatingDefaultsDigest as s, injectAttributionSuppressionIntoSettingsFile as t, prependOperatingDefaultsToMirroredClaudeMd as u, BUILTIN_SUBAGENT_DEFINITIONS as v, resolveGroupKeysFromMirror as x, injectPeerMcpIntoMirror as y };
2856
2856
 
2857
- //# sourceMappingURL=attribution-settings-Dnt04Iyn.js.map
2857
+ //# sourceMappingURL=attribution-settings-DXmmyuEE.js.map