github-router 0.3.314 → 0.3.316
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{aic-ledger-Cx_Ubon3.js → aic-ledger-BS47yb_C.js} +66 -6
- package/dist/aic-ledger-BS47yb_C.js.map +1 -0
- package/dist/{attribution-settings-Btc5EZTj.js → attribution-settings-jcsSeVur.js} +120 -21
- package/dist/attribution-settings-jcsSeVur.js.map +1 -0
- package/dist/{auth-O_UG1ABO.js → auth-JfxL9q7z.js} +4 -4
- package/dist/{auth-O_UG1ABO.js.map → auth-JfxL9q7z.js.map} +1 -1
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/{check-usage-dicJOWML.js → check-usage-DXUEQzt_.js} +4 -4
- package/dist/{check-usage-dicJOWML.js.map → check-usage-DXUEQzt_.js.map} +1 -1
- package/dist/{claude-D0vuAqTV.js → claude-CJ4Nd2_3.js} +116 -45
- package/dist/claude-CJ4Nd2_3.js.map +1 -0
- package/dist/{codex-BNm9D0iJ.js → codex-CwuLqNZF.js} +6 -6
- package/dist/codex-CwuLqNZF.js.map +1 -0
- package/dist/copilot-discount-IbXR5A28.js +220 -0
- package/dist/copilot-discount-IbXR5A28.js.map +1 -0
- package/dist/{debug-2PgImRnr.js → debug-CA7pg8V9.js} +2 -2
- package/dist/{debug-2PgImRnr.js.map → debug-CA7pg8V9.js.map} +1 -1
- package/dist/engine-DwrxceOS.js +2 -0
- package/dist/{exec-y8C_MU8A.js → exec-COUT4QsS.js} +2 -2
- package/dist/{exec-y8C_MU8A.js.map → exec-COUT4QsS.js.map} +1 -1
- package/dist/{gate-discovery-CO2njGBB.js → gate-discovery-z04ywOzB.js} +6 -6
- package/dist/{gate-discovery-CO2njGBB.js.map → gate-discovery-z04ywOzB.js.map} +1 -1
- package/dist/{get-copilot-usage-Cjy8TiFf.js → get-copilot-usage-BMD_cJNT.js} +3 -3
- package/dist/{get-copilot-usage-Cjy8TiFf.js.map → get-copilot-usage-BMD_cJNT.js.map} +1 -1
- package/dist/hooks.mjs +490 -28
- package/dist/hooks.sha256 +1 -1
- package/dist/internal-aic-status-BN0xRLSF.js +432 -0
- package/dist/internal-aic-status-BN0xRLSF.js.map +1 -0
- package/dist/{internal-artifact-open-CxeIfsW_.js → internal-artifact-open-B3stUu74.js} +2 -2
- package/dist/{internal-artifact-open-CxeIfsW_.js.map → internal-artifact-open-B3stUu74.js.map} +1 -1
- package/dist/{internal-fast-dispatch-guard-D8YNlnuQ.js → internal-fast-dispatch-guard-2QjUlhqO.js} +1 -1
- package/dist/{internal-fast-dispatch-guard-19xQEouu.js → internal-fast-dispatch-guard-CAwYj_Yz.js} +2 -2
- package/dist/{internal-fast-dispatch-guard-19xQEouu.js.map → internal-fast-dispatch-guard-CAwYj_Yz.js.map} +1 -1
- package/dist/{internal-first-mate-guard-BuweUgjb.js → internal-first-mate-guard-B0rbLb0L.js} +3 -3
- package/dist/{internal-first-mate-guard-BuweUgjb.js.map → internal-first-mate-guard-B0rbLb0L.js.map} +1 -1
- package/dist/{internal-first-mate-guard-Nf1H0mCK.js → internal-first-mate-guard-VgnHBp0s.js} +1 -1
- package/dist/{internal-max-dispatch-guard-DZ7KLWxP.js → internal-max-dispatch-guard-BNqQ2wMc.js} +3 -3
- package/dist/{internal-max-dispatch-guard-DZ7KLWxP.js.map → internal-max-dispatch-guard-BNqQ2wMc.js.map} +1 -1
- package/dist/{internal-max-dispatch-guard-_Pp4LltM.js → internal-max-dispatch-guard-Bz7a2Ntf.js} +1 -1
- package/dist/{internal-plan-review-DLduDz41.js → internal-plan-review-QUvNZmMR.js} +3 -3
- package/dist/{internal-plan-review-DLduDz41.js.map → internal-plan-review-QUvNZmMR.js.map} +1 -1
- package/dist/{internal-prompt-submit-DG94f8E-.js → internal-prompt-submit-fj5ccft_.js} +5 -5
- package/dist/{internal-prompt-submit-DG94f8E-.js.map → internal-prompt-submit-fj5ccft_.js.map} +1 -1
- package/dist/{internal-session-bind-D6Hpl-84.js → internal-session-bind-0Hmak8PR.js} +2 -2
- package/dist/{internal-session-bind-D6Hpl-84.js.map → internal-session-bind-0Hmak8PR.js.map} +1 -1
- package/dist/{internal-stop-hook-D56b6iVj.js → internal-stop-hook-UN1JHtjj.js} +6 -6
- package/dist/{internal-stop-hook-D56b6iVj.js.map → internal-stop-hook-UN1JHtjj.js.map} +1 -1
- package/dist/{internal-stop-review-DlKzZgFm.js → internal-stop-review-8v2llYDB.js} +2 -2
- package/dist/{internal-stop-review-DlKzZgFm.js.map → internal-stop-review-8v2llYDB.js.map} +1 -1
- package/dist/{internal-worker-guard-D7sfByyo.js → internal-worker-guard-BI4Pl0Ew.js} +2 -2
- package/dist/{internal-worker-guard-D7sfByyo.js.map → internal-worker-guard-BI4Pl0Ew.js.map} +1 -1
- package/dist/{internal-workspace-header-CU5OjLCB.js → internal-workspace-header-kg9FoNXK.js} +2 -2
- package/dist/{internal-workspace-header-CU5OjLCB.js.map → internal-workspace-header-kg9FoNXK.js.map} +1 -1
- package/dist/lifecycle-BpqAyaAj.js +2 -0
- package/dist/lifecycle-CL2WiyeQ.js +2 -0
- package/dist/{lifecycle-CtRA3Y7p.js → lifecycle-Cx1wVrLb.js} +3 -3
- package/dist/{lifecycle-CtRA3Y7p.js.map → lifecycle-Cx1wVrLb.js.map} +1 -1
- package/dist/{lifecycle-BCnarXJV.js → lifecycle-IwotwedG.js} +2 -2
- package/dist/{lifecycle-BCnarXJV.js.map → lifecycle-IwotwedG.js.map} +1 -1
- package/dist/main.js +20 -20
- package/dist/{max-profile-contract-BcrMlrmo.js → max-profile-contract-Bl7I_EOC.js} +2 -2
- package/dist/{max-profile-contract-BcrMlrmo.js.map → max-profile-contract-Bl7I_EOC.js.map} +1 -1
- package/dist/{mcp-workspace-header-B60WSR1Y.js → mcp-workspace-header-BYgWioLH.js} +2 -2
- package/dist/{mcp-workspace-header-B60WSR1Y.js.map → mcp-workspace-header-BYgWioLH.js.map} +1 -1
- package/dist/{models-COuMOfM6.js → models-CVzyU5mJ.js} +3 -3
- package/dist/{models-COuMOfM6.js.map → models-CVzyU5mJ.js.map} +1 -1
- package/dist/{orchestration-DjLA-lxB.js → orchestration-Dc3mO0G3.js} +3 -3
- package/dist/{orchestration-DjLA-lxB.js.map → orchestration-Dc3mO0G3.js.map} +1 -1
- package/dist/paths-BXXCVFvA.js +2 -0
- package/dist/{paths-De1Qh9Q9.js → paths-CMxlQEfQ.js} +3 -3
- package/dist/{paths-De1Qh9Q9.js.map → paths-CMxlQEfQ.js.map} +1 -1
- package/dist/{peer-mcp-personas-0_XU6nm9.js → peer-mcp-personas-CQ-0Piyr.js} +175 -54
- package/dist/peer-mcp-personas-CQ-0Piyr.js.map +1 -0
- package/dist/{plan-review-hook-vL6BYmA8.js → plan-review-hook-BIMwWkh6.js} +4 -4
- package/dist/{plan-review-hook-vL6BYmA8.js.map → plan-review-hook-BIMwWkh6.js.map} +1 -1
- package/dist/{prompt-submit-hook-DfqufWC1.js → prompt-submit-hook-BcFpjHXg.js} +3 -3
- package/dist/{prompt-submit-hook-DfqufWC1.js.map → prompt-submit-hook-BcFpjHXg.js.map} +1 -1
- package/dist/{provision-DuCnZJj_.js → provision-_R7ZMygj.js} +5 -5
- package/dist/{provision-DuCnZJj_.js.map → provision-_R7ZMygj.js.map} +1 -1
- package/dist/{self-invocation-B84JCHps.js → self-invocation-cRl4RqfW.js} +2 -2
- package/dist/{self-invocation-B84JCHps.js.map → self-invocation-cRl4RqfW.js.map} +1 -1
- package/dist/{serve-DXFVR6A0.js → serve-DU66K5kv.js} +14 -14
- package/dist/{serve-DXFVR6A0.js.map → serve-DU66K5kv.js.map} +1 -1
- package/dist/{server-setup-CP8nGop3.js → server-setup-iLG8LrfL.js} +168 -30
- package/dist/server-setup-iLG8LrfL.js.map +1 -0
- package/dist/{start-BHEjESCB.js → start-DQTcm0o_.js} +3 -3
- package/dist/{start-BHEjESCB.js.map → start-DQTcm0o_.js.map} +1 -1
- package/dist/{state-B8adscCv.js → state-BlMpEFAt.js} +2 -1
- package/dist/{state-B8adscCv.js.map → state-BlMpEFAt.js.map} +1 -1
- package/dist/{stop-gate-hook-BEU8qQrC.js → stop-gate-hook-BUCxa5Kc.js} +4 -4
- package/dist/{stop-gate-hook-BEU8qQrC.js.map → stop-gate-hook-BUCxa5Kc.js.map} +1 -1
- package/dist/{stop-gate-policy-qzqXfRxE.js → stop-gate-policy--bpyxxXU.js} +3 -3
- package/dist/{stop-gate-policy-qzqXfRxE.js.map → stop-gate-policy--bpyxxXU.js.map} +1 -1
- package/dist/{token-CCg-Ov5q.js → token-C1gthnbV.js} +3 -3
- package/dist/{token-CCg-Ov5q.js.map → token-C1gthnbV.js.map} +1 -1
- package/dist/{worker-dispatch-CH-NN5FW.js → worker-dispatch-DMIdrlsF.js} +2 -2
- package/dist/{worker-dispatch-CH-NN5FW.js.map → worker-dispatch-DMIdrlsF.js.map} +1 -1
- package/package.json +1 -1
- package/dist/aic-ledger-Cx_Ubon3.js.map +0 -1
- package/dist/attribution-settings-Btc5EZTj.js.map +0 -1
- package/dist/claude-D0vuAqTV.js.map +0 -1
- package/dist/codex-BNm9D0iJ.js.map +0 -1
- package/dist/engine-DsVZuCrD.js +0 -2
- package/dist/internal-aic-status-C_swX3_7.js +0 -95
- package/dist/internal-aic-status-C_swX3_7.js.map +0 -1
- package/dist/lifecycle-B0USSJvd.js +0 -2
- package/dist/lifecycle-CQFjaQc0.js +0 -2
- package/dist/paths-DyX6SEnd.js +0 -2
- package/dist/peer-mcp-personas-0_XU6nm9.js.map +0 -1
- package/dist/server-setup-CP8nGop3.js.map +0 -1
package/dist/hooks.mjs
CHANGED
|
@@ -10936,6 +10936,7 @@ var init_state = __esmMin((() => {
|
|
|
10936
10936
|
fleetEnabled: false,
|
|
10937
10937
|
agentsEnabled: false,
|
|
10938
10938
|
powerBrowseEnabled: false,
|
|
10939
|
+
searchEnabled: false,
|
|
10939
10940
|
humanlikeForce: "auto",
|
|
10940
10941
|
sessionId: randomUUID(),
|
|
10941
10942
|
machineId: randomBytes(32).toString("hex"),
|
|
@@ -34642,6 +34643,35 @@ var NANO_AIU_PER_CREDIT;
|
|
|
34642
34643
|
var init_aic_usage = __esmMin((() => {
|
|
34643
34644
|
NANO_AIU_PER_CREDIT = 1e9;
|
|
34644
34645
|
}));
|
|
34646
|
+
//#endregion
|
|
34647
|
+
//#region src/lib/aic-ledger.ts
|
|
34648
|
+
/**
|
|
34649
|
+
* Per-launch AIC (AI Credits) ledger.
|
|
34650
|
+
*
|
|
34651
|
+
* Every route handler records upstream `copilot_usage` here as a side effect
|
|
34652
|
+
* (bytes pass through untouched). The totals feed two consumers:
|
|
34653
|
+
*
|
|
34654
|
+
* 1. `internal-aic-status` — runs as a SEPARATE process on every status-line
|
|
34655
|
+
* tick, so it cannot read in-process memory. Each `record()` therefore
|
|
34656
|
+
* also persists an atomic snapshot file; the ledger path is handed to the
|
|
34657
|
+
* spawned child via `GH_ROUTER_AIC_LEDGER` and baked into the statusLine
|
|
34658
|
+
* command.
|
|
34659
|
+
* 2. The `claude` exit summary — reads the in-process snapshot.
|
|
34660
|
+
*
|
|
34661
|
+
* Keyed per proxy process (one file per PID under `<APP_DIR>/aic-ledger/`),
|
|
34662
|
+
* so concurrent launches never mix. Snapshot writes are best-effort and never
|
|
34663
|
+
* throw into the request path. Stale files (dead PID, >24h) are swept at
|
|
34664
|
+
* startup of the next record and on shutdown.
|
|
34665
|
+
*/
|
|
34666
|
+
function emptyModelTokens() {
|
|
34667
|
+
return {
|
|
34668
|
+
input: 0,
|
|
34669
|
+
cache_read: 0,
|
|
34670
|
+
cache_write: 0,
|
|
34671
|
+
output: 0,
|
|
34672
|
+
other: 0
|
|
34673
|
+
};
|
|
34674
|
+
}
|
|
34645
34675
|
/**
|
|
34646
34676
|
* Read a persisted snapshot file (the status-hook path). Returns undefined
|
|
34647
34677
|
* when missing/unreadable — the hook then prints nothing.
|
|
@@ -34657,12 +34687,41 @@ function readAicSnapshotFile(file) {
|
|
|
34657
34687
|
totalNanoAiu: Math.max(0, Math.floor(record.totalNanoAiu)),
|
|
34658
34688
|
requests: Math.max(0, Math.floor(record.requests)),
|
|
34659
34689
|
perModel: record.perModel && typeof record.perModel === "object" ? record.perModel : {},
|
|
34660
|
-
perTokenType: record.perTokenType && typeof record.perTokenType === "object" ? record.perTokenType : {}
|
|
34690
|
+
perTokenType: record.perTokenType && typeof record.perTokenType === "object" ? record.perTokenType : {},
|
|
34691
|
+
tokensByModel: sanitizeModelTokens(record.tokensByModel)
|
|
34661
34692
|
};
|
|
34662
34693
|
} catch {
|
|
34663
34694
|
return;
|
|
34664
34695
|
}
|
|
34665
34696
|
}
|
|
34697
|
+
/** Best-effort sanitize of persisted per-model token counts; `{}` when absent. */
|
|
34698
|
+
function sanitizeModelTokens(value) {
|
|
34699
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
34700
|
+
const out = {};
|
|
34701
|
+
for (const [model, counts] of Object.entries(value)) {
|
|
34702
|
+
if (!counts || typeof counts !== "object" || Array.isArray(counts)) continue;
|
|
34703
|
+
const entry = counts;
|
|
34704
|
+
const clean = emptyModelTokens();
|
|
34705
|
+
let ok = true;
|
|
34706
|
+
for (const field of [
|
|
34707
|
+
"input",
|
|
34708
|
+
"cache_read",
|
|
34709
|
+
"cache_write",
|
|
34710
|
+
"output",
|
|
34711
|
+
"other"
|
|
34712
|
+
]) {
|
|
34713
|
+
const n = entry[field];
|
|
34714
|
+
if (n === void 0) continue;
|
|
34715
|
+
if (typeof n !== "number" || !Number.isFinite(n) || n < 0) {
|
|
34716
|
+
ok = false;
|
|
34717
|
+
break;
|
|
34718
|
+
}
|
|
34719
|
+
clean[field] = Math.floor(n);
|
|
34720
|
+
}
|
|
34721
|
+
if (ok) out[model] = clean;
|
|
34722
|
+
}
|
|
34723
|
+
return out;
|
|
34724
|
+
}
|
|
34666
34725
|
/** Total credits for a snapshot. */
|
|
34667
34726
|
function aicTotalCredits(snapshot) {
|
|
34668
34727
|
return nanoAiuToCredits(snapshot.totalNanoAiu);
|
|
@@ -34968,7 +35027,7 @@ var internal_stop_hook_exports = /* @__PURE__ */ __exportAll({
|
|
|
34968
35027
|
* no such handle. Hooks always receive piped/redirected stdin, so this never
|
|
34969
35028
|
* blocks (guarded against an interactive TTY, and any error -> "").
|
|
34970
35029
|
*/
|
|
34971
|
-
function readStdin$
|
|
35030
|
+
function readStdin$6() {
|
|
34972
35031
|
try {
|
|
34973
35032
|
if (process.stdin.isTTY) return "";
|
|
34974
35033
|
return readFileSync(0, "utf8");
|
|
@@ -35155,7 +35214,7 @@ var init_internal_stop_hook = __esmMin((() => {
|
|
|
35155
35214
|
description: "Internal: the structural-gate Stop hook. Reads the Claude Code hook payload on stdin, runs the sealed gate, exits 2 (blocks the stop) on a red gate or gate-weakening diff."
|
|
35156
35215
|
},
|
|
35157
35216
|
async run() {
|
|
35158
|
-
const stdin = readStdin$
|
|
35217
|
+
const stdin = readStdin$6();
|
|
35159
35218
|
const reviewEnabled = stopReviewEnabled() && hookMcpRuntimeFromEnv() !== void 0;
|
|
35160
35219
|
let transcriptPath = "";
|
|
35161
35220
|
let userPrompt = "";
|
|
@@ -35323,7 +35382,7 @@ var internal_prompt_submit_exports = /* @__PURE__ */ __exportAll({ internalPromp
|
|
|
35323
35382
|
* no such handle. Hooks always receive piped/redirected stdin, so this never
|
|
35324
35383
|
* blocks (guarded against an interactive TTY, and any error -> "").
|
|
35325
35384
|
*/
|
|
35326
|
-
function readStdin$
|
|
35385
|
+
function readStdin$5() {
|
|
35327
35386
|
try {
|
|
35328
35387
|
if (process.stdin.isTTY) return "";
|
|
35329
35388
|
return readFileSync(0, "utf8");
|
|
@@ -35360,7 +35419,7 @@ var init_internal_prompt_submit = __esmMin((() => {
|
|
|
35360
35419
|
},
|
|
35361
35420
|
async run() {
|
|
35362
35421
|
try {
|
|
35363
|
-
const stdin = readStdin$
|
|
35422
|
+
const stdin = readStdin$5();
|
|
35364
35423
|
const steerEnabled = parseBoolEnv(process.env.GH_ROUTER_DISABLE_PROMPT_STEER) !== true;
|
|
35365
35424
|
const runtime = hookMcpRuntimeFromEnv();
|
|
35366
35425
|
let decision;
|
|
@@ -35655,7 +35714,7 @@ var init_plan_review_hook = __esmMin((() => {
|
|
|
35655
35714
|
//#endregion
|
|
35656
35715
|
//#region src/internal-plan-review.ts
|
|
35657
35716
|
var internal_plan_review_exports = /* @__PURE__ */ __exportAll({ internalPlanReview: () => internalPlanReview });
|
|
35658
|
-
function readStdin$
|
|
35717
|
+
function readStdin$4() {
|
|
35659
35718
|
try {
|
|
35660
35719
|
if (process.stdin.isTTY) return "";
|
|
35661
35720
|
return readFileSync(0, "utf8");
|
|
@@ -35748,7 +35807,7 @@ var init_internal_plan_review = __esmMin((() => {
|
|
|
35748
35807
|
return;
|
|
35749
35808
|
}
|
|
35750
35809
|
const decision = await decidePlanReviewHook({
|
|
35751
|
-
stdin: readStdin$
|
|
35810
|
+
stdin: readStdin$4(),
|
|
35752
35811
|
runtimeAvailable: true,
|
|
35753
35812
|
debounce: filePlanReviewDebounce(stopReviewStateDir()),
|
|
35754
35813
|
fallbackCwd: process.cwd()
|
|
@@ -35771,7 +35830,7 @@ var internal_session_bind_exports = /* @__PURE__ */ __exportAll({
|
|
|
35771
35830
|
* teardown and trips a `uv_async_send` assertion; a synchronous read has no such
|
|
35772
35831
|
* handle. Hooks always receive piped stdin (guarded against a TTY; any error -> "").
|
|
35773
35832
|
*/
|
|
35774
|
-
function readStdin$
|
|
35833
|
+
function readStdin$3() {
|
|
35775
35834
|
try {
|
|
35776
35835
|
if (process.stdin.isTTY) return "";
|
|
35777
35836
|
return readFileSync(0, "utf8");
|
|
@@ -35865,7 +35924,7 @@ var init_internal_session_bind = __esmMin((() => {
|
|
|
35865
35924
|
try {
|
|
35866
35925
|
const out = typeof args.out === "string" ? args.out.trim() : "";
|
|
35867
35926
|
if (!out) return;
|
|
35868
|
-
const record = decodeSessionBind(readStdin$
|
|
35927
|
+
const record = decodeSessionBind(readStdin$3());
|
|
35869
35928
|
if (record) writeSidecar(out, record);
|
|
35870
35929
|
} catch {}
|
|
35871
35930
|
process.exitCode = 0;
|
|
@@ -37678,7 +37737,7 @@ var internal_artifact_open_exports = /* @__PURE__ */ __exportAll({
|
|
|
37678
37737
|
internalArtifactOpen: () => internalArtifactOpen,
|
|
37679
37738
|
parseExitPlanPayload: () => parseExitPlanPayload
|
|
37680
37739
|
});
|
|
37681
|
-
function readStdin$
|
|
37740
|
+
function readStdin$2() {
|
|
37682
37741
|
try {
|
|
37683
37742
|
if (process.stdin.isTTY) return "";
|
|
37684
37743
|
return readFileSync(0, "utf8");
|
|
@@ -37778,7 +37837,7 @@ var init_internal_artifact_open = __esmMin((() => {
|
|
|
37778
37837
|
},
|
|
37779
37838
|
async run() {
|
|
37780
37839
|
try {
|
|
37781
|
-
const raw = readStdin$
|
|
37840
|
+
const raw = readStdin$2();
|
|
37782
37841
|
let payload;
|
|
37783
37842
|
try {
|
|
37784
37843
|
payload = JSON.parse(raw);
|
|
@@ -37997,7 +38056,7 @@ var internal_worker_guard_exports = /* @__PURE__ */ __exportAll({ internalWorker
|
|
|
37997
38056
|
* libuv FS request that races Windows process teardown. Hooks always receive
|
|
37998
38057
|
* piped stdin (guarded against an interactive TTY; any error → "").
|
|
37999
38058
|
*/
|
|
38000
|
-
function readStdin() {
|
|
38059
|
+
function readStdin$1() {
|
|
38001
38060
|
try {
|
|
38002
38061
|
if (process.stdin.isTTY) return "";
|
|
38003
38062
|
return readFileSync(0, "utf8");
|
|
@@ -38028,7 +38087,7 @@ var init_internal_worker_guard = __esmMin((() => {
|
|
|
38028
38087
|
},
|
|
38029
38088
|
run(ctx) {
|
|
38030
38089
|
try {
|
|
38031
|
-
const stdin = readStdin();
|
|
38090
|
+
const stdin = readStdin$1();
|
|
38032
38091
|
const workersKey = String(ctx.args["workers-key"] ?? "").trim();
|
|
38033
38092
|
if (workersKey.length > 0) {
|
|
38034
38093
|
const { output } = decideWorkerGuard({
|
|
@@ -38485,6 +38544,388 @@ var init_internal_max_dispatch_guard = __esmMin((() => {
|
|
|
38485
38544
|
});
|
|
38486
38545
|
}));
|
|
38487
38546
|
//#endregion
|
|
38547
|
+
//#region src/lib/copilot-discount.ts
|
|
38548
|
+
function row(factor, source) {
|
|
38549
|
+
return {
|
|
38550
|
+
factor,
|
|
38551
|
+
source
|
|
38552
|
+
};
|
|
38553
|
+
}
|
|
38554
|
+
/**
|
|
38555
|
+
* Clamp a factor to usable range. Non-finite or negative factors (corrupt
|
|
38556
|
+
* table edit, bad injection) degrade to 1.0 — unfactored but never NaN,
|
|
38557
|
+
* never negative on screen.
|
|
38558
|
+
*/
|
|
38559
|
+
function sanitizeFactor(raw) {
|
|
38560
|
+
return typeof raw === "number" && Number.isFinite(raw) && raw >= 0 ? raw : 1;
|
|
38561
|
+
}
|
|
38562
|
+
/**
|
|
38563
|
+
* Session discounted USD from a ledger snapshot. Total function: never
|
|
38564
|
+
* throws (guards non-finite/negative ledger values defensively — a corrupt
|
|
38565
|
+
* snapshot must degrade the status line, not crash the hook).
|
|
38566
|
+
*/
|
|
38567
|
+
function discountedUsdForSnapshot(snapshot) {
|
|
38568
|
+
return discountedUsdWithFactors(snapshot, DISCOUNT_FACTORS);
|
|
38569
|
+
}
|
|
38570
|
+
/**
|
|
38571
|
+
* Factor-injectable core (exported for unit tests — e.g. proving a
|
|
38572
|
+
* fat-finger factor can never overstate spend). `factors` falls back to
|
|
38573
|
+
* 1.0 per model exactly like the table lookup.
|
|
38574
|
+
*/
|
|
38575
|
+
function discountedUsdWithFactors(snapshot, factors) {
|
|
38576
|
+
const byModel = {};
|
|
38577
|
+
let sum = 0;
|
|
38578
|
+
for (const [model, entry] of Object.entries(snapshot.perModel)) {
|
|
38579
|
+
const nano = typeof entry.nanoAiu === "number" && Number.isFinite(entry.nanoAiu) ? Math.max(0, entry.nanoAiu) : 0;
|
|
38580
|
+
const factor = sanitizeFactor(factors[model]?.factor);
|
|
38581
|
+
const usd = nano / 1e9 * USD_PER_AIC_CREDIT * factor;
|
|
38582
|
+
byModel[model] = usd;
|
|
38583
|
+
sum += usd;
|
|
38584
|
+
}
|
|
38585
|
+
const cap = aicTotalCredits(snapshot) * USD_PER_AIC_CREDIT;
|
|
38586
|
+
if (!(sum > cap * (1 + 1e-9)) || sum <= 0) return {
|
|
38587
|
+
total: sum,
|
|
38588
|
+
byModel,
|
|
38589
|
+
capped: false
|
|
38590
|
+
};
|
|
38591
|
+
const scale = cap / sum;
|
|
38592
|
+
const scaled = {};
|
|
38593
|
+
for (const [model, usd] of Object.entries(byModel)) scaled[model] = usd * scale;
|
|
38594
|
+
return {
|
|
38595
|
+
total: cap,
|
|
38596
|
+
byModel: scaled,
|
|
38597
|
+
capped: true
|
|
38598
|
+
};
|
|
38599
|
+
}
|
|
38600
|
+
var USD_PER_AIC_CREDIT, DISCOUNT_FACTORS;
|
|
38601
|
+
var init_copilot_discount = __esmMin((() => {
|
|
38602
|
+
init_aic_ledger();
|
|
38603
|
+
USD_PER_AIC_CREDIT = .01;
|
|
38604
|
+
DISCOUNT_FACTORS = Object.freeze({
|
|
38605
|
+
"gpt-5.6-sol": row(.28, "0.27-0.29 across 28d/MTD/7d/pre/9-9; write-mix refuted"),
|
|
38606
|
+
"claude-opus-5": row(.62, "0.61-0.64 across windows; 9/7 1.02 excluded as single-day artifact"),
|
|
38607
|
+
"claude-sonnet-5": row(.66, "0.62-0.71 across windows"),
|
|
38608
|
+
"gpt-5.3-codex": row(.6, "0.59-0.62 across windows"),
|
|
38609
|
+
"gpt-5.4": row(.6, "single snapshot 0.598"),
|
|
38610
|
+
"gemini-3.7-flash": row(.29, "September regime; pre-Sep 1.00x — volatile"),
|
|
38611
|
+
"gpt-5.6-luna": row(1, "long-tier portal + writes, no discount"),
|
|
38612
|
+
"grok-4.6": row(1, "portal default, six windows"),
|
|
38613
|
+
"gemini-3.8-flash": row(1, "portal exact, six windows to the dollar")
|
|
38614
|
+
});
|
|
38615
|
+
}));
|
|
38616
|
+
//#endregion
|
|
38617
|
+
//#region src/lib/default-statusline.ts
|
|
38618
|
+
/**
|
|
38619
|
+
* Rich default status line for `github-router claude` sessions.
|
|
38620
|
+
*
|
|
38621
|
+
* Replaces the need for users to maintain their own PowerShell/bash status
|
|
38622
|
+
* script: `internal-aic-status` renders these segments natively from the
|
|
38623
|
+
* Claude Code stdin JSON, then pins the `[AIC x.xx]` ledger fragment ahead
|
|
38624
|
+
* of them. Zero dependencies, cross-platform (Windows 11 is the primary
|
|
38625
|
+
* target — no `powershell`/`bash`/`jq` required), and fast (no shell
|
|
38626
|
+
* startup; one bounded `git rev-parse` at most).
|
|
38627
|
+
*
|
|
38628
|
+
* Segment order (left = highest priority; narrow terminals drop from the
|
|
38629
|
+
* right, `AIC` is never dropped):
|
|
38630
|
+
*
|
|
38631
|
+
* `[AIC] | [ctx bar] % | model | dir (branch) | ~$actual | in/out | dur | +a -r`
|
|
38632
|
+
*
|
|
38633
|
+
* The `$` segment is the DISCOUNTED actual (`~$` = factor-discounted
|
|
38634
|
+
* session total from `copilot-discount.ts`, capped at AIC × $0.01) — NOT
|
|
38635
|
+
* Claude's `cost.total_cost_usd`, which prices at Anthropic list rates and
|
|
38636
|
+
* reads ~10-100x high against Copilot billing (a 28-day sample: 41.1B tokens
|
|
38637
|
+
* for $5,142 ≈ $0.13/1M blended vs $15-75/1M list). Rendering list price
|
|
38638
|
+
* next to the real `[AIC]` billing unit would show two contradictory
|
|
38639
|
+
* numbers, so list price is deliberately not rendered at all.
|
|
38640
|
+
*
|
|
38641
|
+
* Width comes from `COLUMNS` (set by Claude Code for status scripts since
|
|
38642
|
+
* v2.1.153); fallback is 120 when unset/unparseable so a missing `COLUMNS`
|
|
38643
|
+
* never needlessly drops segments.
|
|
38644
|
+
*/
|
|
38645
|
+
function asRecord(value) {
|
|
38646
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
38647
|
+
return value;
|
|
38648
|
+
}
|
|
38649
|
+
function finiteNumber(value) {
|
|
38650
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
38651
|
+
}
|
|
38652
|
+
function nonEmptyString(value) {
|
|
38653
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
38654
|
+
}
|
|
38655
|
+
/**
|
|
38656
|
+
* Parse Claude Code's status-line stdin JSON into the fields we render.
|
|
38657
|
+
* Total function: malformed JSON or unexpected shapes yield `{}` (every
|
|
38658
|
+
* segment then renders its `--` placeholder or is omitted) — never throws.
|
|
38659
|
+
*/
|
|
38660
|
+
function parseStatusInput(raw) {
|
|
38661
|
+
if (!raw.trim()) return {};
|
|
38662
|
+
let parsed;
|
|
38663
|
+
try {
|
|
38664
|
+
parsed = JSON.parse(raw);
|
|
38665
|
+
} catch {
|
|
38666
|
+
return {};
|
|
38667
|
+
}
|
|
38668
|
+
const root = asRecord(parsed);
|
|
38669
|
+
if (!root) return {};
|
|
38670
|
+
const out = {};
|
|
38671
|
+
const ctx = asRecord(root.context_window);
|
|
38672
|
+
if (ctx) {
|
|
38673
|
+
const pct = finiteNumber(ctx.used_percentage);
|
|
38674
|
+
if (pct !== void 0) out.usedPct = pct;
|
|
38675
|
+
const tIn = finiteNumber(ctx.total_input_tokens);
|
|
38676
|
+
if (tIn !== void 0 && tIn >= 0) out.totalInputTokens = Math.floor(tIn);
|
|
38677
|
+
const tOut = finiteNumber(ctx.total_output_tokens);
|
|
38678
|
+
if (tOut !== void 0 && tOut >= 0) out.totalOutputTokens = Math.floor(tOut);
|
|
38679
|
+
}
|
|
38680
|
+
const cost = asRecord(root.cost);
|
|
38681
|
+
if (cost) {
|
|
38682
|
+
const dur = finiteNumber(cost.total_duration_ms);
|
|
38683
|
+
if (dur !== void 0 && dur >= 0) out.totalDurationMs = dur;
|
|
38684
|
+
const la = finiteNumber(cost.total_lines_added);
|
|
38685
|
+
if (la !== void 0 && la >= 0) out.linesAdded = Math.floor(la);
|
|
38686
|
+
const lr = finiteNumber(cost.total_lines_removed);
|
|
38687
|
+
if (lr !== void 0 && lr >= 0) out.linesRemoved = Math.floor(lr);
|
|
38688
|
+
}
|
|
38689
|
+
const workspace = asRecord(root.workspace);
|
|
38690
|
+
const cwd = (workspace ? nonEmptyString(workspace.current_dir) : void 0) ?? nonEmptyString(root.cwd);
|
|
38691
|
+
if (cwd) out.cwd = cwd;
|
|
38692
|
+
const model = asRecord(root.model);
|
|
38693
|
+
if (model) {
|
|
38694
|
+
const name = nonEmptyString(model.display_name) ?? nonEmptyString(model.id);
|
|
38695
|
+
if (name) out.modelName = name;
|
|
38696
|
+
}
|
|
38697
|
+
return out;
|
|
38698
|
+
}
|
|
38699
|
+
/** Compact token count: `999` → `999`, `15234` → `15.2k`, `2.1M`. */
|
|
38700
|
+
function compactTokens(n) {
|
|
38701
|
+
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
38702
|
+
if (n >= 1e3) return `${(n / 1e3).toFixed(1)}k`;
|
|
38703
|
+
return `${n}`;
|
|
38704
|
+
}
|
|
38705
|
+
/** `45000` → `0m45s`, `198000` → `3m18s`, `3720000` → `1h02m`. */
|
|
38706
|
+
function formatDurationMs(ms) {
|
|
38707
|
+
const totalSeconds = Math.floor(ms / 1e3);
|
|
38708
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
38709
|
+
const minutes = Math.floor(totalSeconds % 3600 / 60);
|
|
38710
|
+
const seconds = totalSeconds % 60;
|
|
38711
|
+
if (hours >= 1) return `${hours}h${String(minutes).padStart(2, "0")}m`;
|
|
38712
|
+
return `${minutes}m${String(seconds).padStart(2, "0")}s`;
|
|
38713
|
+
}
|
|
38714
|
+
/** Basename of a cwd, tolerant of `/` and `\` separators + trailing slash. */
|
|
38715
|
+
function dirLeaf(cwd) {
|
|
38716
|
+
const trimmed = cwd.replace(/[/\\]+$/, "");
|
|
38717
|
+
const parts = trimmed.split(/[/\\]/);
|
|
38718
|
+
return parts[parts.length - 1] ?? trimmed;
|
|
38719
|
+
}
|
|
38720
|
+
function buildCtxSegment(usedPct) {
|
|
38721
|
+
if (usedPct === void 0 || !Number.isFinite(usedPct)) return {
|
|
38722
|
+
text: `${DIM}[----------] --%${RESET}`,
|
|
38723
|
+
plain: "[----------] --%"
|
|
38724
|
+
};
|
|
38725
|
+
const u = Math.max(0, Math.min(100, Math.round(usedPct)));
|
|
38726
|
+
let filled = Math.round(u / 100 * CTX_BAR_LEN);
|
|
38727
|
+
if (filled > CTX_BAR_LEN) filled = CTX_BAR_LEN;
|
|
38728
|
+
if (filled < 0) filled = 0;
|
|
38729
|
+
const bar = `#`.repeat(filled) + `-`.repeat(CTX_BAR_LEN - filled);
|
|
38730
|
+
return {
|
|
38731
|
+
text: `${u < 50 ? GREEN : u < 75 ? YELLOW : RED}[${bar}] ${u}%${RESET}`,
|
|
38732
|
+
plain: `[${bar}] ${u}%`
|
|
38733
|
+
};
|
|
38734
|
+
}
|
|
38735
|
+
/**
|
|
38736
|
+
* Discounted-actual `$` segment. Callers pass the capped total from
|
|
38737
|
+
* `discountedUsdForSnapshot` — this function only formats. Placeholder
|
|
38738
|
+
* `~$--` until the first priced upstream response lands in the ledger.
|
|
38739
|
+
* Thresholds are tuned for ACTUALS scale (a session runs ~$0.10-2.00) —
|
|
38740
|
+
* not the old list-price scale.
|
|
38741
|
+
*/
|
|
38742
|
+
function buildUsdSegment(actualUsd) {
|
|
38743
|
+
if (actualUsd === void 0 || !Number.isFinite(actualUsd) || actualUsd < 0) return {
|
|
38744
|
+
text: `${DIM}~$--${RESET}`,
|
|
38745
|
+
plain: "~$--"
|
|
38746
|
+
};
|
|
38747
|
+
const c = actualUsd;
|
|
38748
|
+
const color = c < 1 ? GREEN : c < 5 ? YELLOW : c < 20 ? ORANGE : RED;
|
|
38749
|
+
const formatted = c < 10 ? c.toFixed(2) : c.toFixed(1);
|
|
38750
|
+
return {
|
|
38751
|
+
text: `${color}~$${formatted}${RESET}`,
|
|
38752
|
+
plain: `~$${formatted}`
|
|
38753
|
+
};
|
|
38754
|
+
}
|
|
38755
|
+
function buildToksSegment(tIn, tOut) {
|
|
38756
|
+
if (tIn === void 0 || tOut === void 0) return {
|
|
38757
|
+
text: `${DIM}--/--${RESET}`,
|
|
38758
|
+
plain: "--/--"
|
|
38759
|
+
};
|
|
38760
|
+
const cin = compactTokens(tIn);
|
|
38761
|
+
const cout = compactTokens(tOut);
|
|
38762
|
+
return {
|
|
38763
|
+
text: `${CYAN}${cin}${RESET}${DIM}/${RESET}${MAGENTA}${cout}${RESET}`,
|
|
38764
|
+
plain: `${cin}/${cout}`
|
|
38765
|
+
};
|
|
38766
|
+
}
|
|
38767
|
+
function buildDurSegment(durMs) {
|
|
38768
|
+
if (durMs === void 0 || !Number.isFinite(durMs) || durMs < 0) return {
|
|
38769
|
+
text: `${DIM}--${RESET}`,
|
|
38770
|
+
plain: "--"
|
|
38771
|
+
};
|
|
38772
|
+
const formatted = formatDurationMs(durMs);
|
|
38773
|
+
return {
|
|
38774
|
+
text: `${DIM}${formatted}${RESET}`,
|
|
38775
|
+
plain: formatted
|
|
38776
|
+
};
|
|
38777
|
+
}
|
|
38778
|
+
function buildLinesSegment(added, removed) {
|
|
38779
|
+
const a = added ?? 0;
|
|
38780
|
+
const r = removed ?? 0;
|
|
38781
|
+
return {
|
|
38782
|
+
text: `${GREEN}+${a}${RESET} ${RED}-${r}${RESET}`,
|
|
38783
|
+
plain: `+${a} -${r}`
|
|
38784
|
+
};
|
|
38785
|
+
}
|
|
38786
|
+
function buildModelSegment(modelName) {
|
|
38787
|
+
if (!modelName || modelName === "--") return void 0;
|
|
38788
|
+
return {
|
|
38789
|
+
text: `${MAGENTA}${modelName}${RESET}`,
|
|
38790
|
+
plain: modelName
|
|
38791
|
+
};
|
|
38792
|
+
}
|
|
38793
|
+
function buildDirGitSegment(cwd, branch) {
|
|
38794
|
+
const leaf = cwd ? dirLeaf(cwd) : "";
|
|
38795
|
+
const br = branch && branch !== "HEAD" ? branch : "";
|
|
38796
|
+
if (!leaf && !br) return void 0;
|
|
38797
|
+
if (leaf && br) return {
|
|
38798
|
+
text: `${BLUE}${leaf}${RESET} ${CYAN}(${br})${RESET}`,
|
|
38799
|
+
plain: `${leaf} (${br})`
|
|
38800
|
+
};
|
|
38801
|
+
if (leaf) return {
|
|
38802
|
+
text: `${BLUE}${leaf}${RESET}`,
|
|
38803
|
+
plain: leaf
|
|
38804
|
+
};
|
|
38805
|
+
return {
|
|
38806
|
+
text: `${CYAN}${br}${RESET}`,
|
|
38807
|
+
plain: br
|
|
38808
|
+
};
|
|
38809
|
+
}
|
|
38810
|
+
/**
|
|
38811
|
+
* Resolve the current git branch for `cwd`. Bounded (`GIT_TIMEOUT_MS`) and
|
|
38812
|
+
* total: any failure (no git binary, not a repo, detached `HEAD`, timeout,
|
|
38813
|
+
* `%` in a Windows path that cmd.exe cannot safely quote) yields `""`
|
|
38814
|
+
* (caller omits the branch) — never throws.
|
|
38815
|
+
*/
|
|
38816
|
+
function resolveGitBranch(cwd) {
|
|
38817
|
+
try {
|
|
38818
|
+
if (!cwd) return "";
|
|
38819
|
+
const gitPath = resolveExecutable("git");
|
|
38820
|
+
if (!gitPath) return "";
|
|
38821
|
+
const { command, args, shell } = buildExecInvocation([
|
|
38822
|
+
gitPath,
|
|
38823
|
+
"-C",
|
|
38824
|
+
cwd,
|
|
38825
|
+
"rev-parse",
|
|
38826
|
+
"--abbrev-ref",
|
|
38827
|
+
"HEAD"
|
|
38828
|
+
]);
|
|
38829
|
+
const result = spawnSync(command, args, {
|
|
38830
|
+
shell,
|
|
38831
|
+
timeout: GIT_TIMEOUT_MS,
|
|
38832
|
+
encoding: "utf8",
|
|
38833
|
+
stdio: [
|
|
38834
|
+
"ignore",
|
|
38835
|
+
"pipe",
|
|
38836
|
+
"ignore"
|
|
38837
|
+
]
|
|
38838
|
+
});
|
|
38839
|
+
if (result.error) return "";
|
|
38840
|
+
const out = typeof result.stdout === "string" ? result.stdout.trim() : "";
|
|
38841
|
+
if (!out || out === "HEAD") return "";
|
|
38842
|
+
return out.split("\n")[0]?.trim() ?? "";
|
|
38843
|
+
} catch {
|
|
38844
|
+
return "";
|
|
38845
|
+
}
|
|
38846
|
+
}
|
|
38847
|
+
/** Terminal width for the drop-right-to-left assembly. */
|
|
38848
|
+
function terminalWidth(env = process.env) {
|
|
38849
|
+
const raw = env.COLUMNS;
|
|
38850
|
+
if (raw !== void 0) {
|
|
38851
|
+
const n = Number(raw);
|
|
38852
|
+
if (Number.isInteger(n) && n > 0) return n;
|
|
38853
|
+
}
|
|
38854
|
+
return WIDTH_FALLBACK;
|
|
38855
|
+
}
|
|
38856
|
+
/**
|
|
38857
|
+
* Assemble the full status line. `aicFragment` (e.g. `[AIC 12.42]`) is
|
|
38858
|
+
* PINNED — it renders even when nothing else fits. `actualUsd` feeds the
|
|
38859
|
+
* `~$` segment (the capped factor-discounted total from
|
|
38860
|
+
* `discountedUsdForSnapshot`, same snapshot the fragment came from).
|
|
38861
|
+
* Droppable segments in priority order: ctx, model, dir/git, ~$, toks,
|
|
38862
|
+
* dur, lines.
|
|
38863
|
+
*/
|
|
38864
|
+
function assembleStatusLine(aicFragment, input, opts = {}) {
|
|
38865
|
+
const aic = aicFragment.trim();
|
|
38866
|
+
const aicText = aic ? `${AIC_COLOR}${aic}${RESET}` : "";
|
|
38867
|
+
const droppable = [buildCtxSegment(input.usedPct)];
|
|
38868
|
+
const model = buildModelSegment(input.modelName);
|
|
38869
|
+
if (model) droppable.push(model);
|
|
38870
|
+
const dirGit = buildDirGitSegment(input.cwd, opts.branch);
|
|
38871
|
+
if (dirGit) droppable.push(dirGit);
|
|
38872
|
+
droppable.push(buildUsdSegment(opts.actualUsd), buildToksSegment(input.totalInputTokens, input.totalOutputTokens), buildDurSegment(input.totalDurationMs), buildLinesSegment(input.linesAdded, input.linesRemoved));
|
|
38873
|
+
const width = opts.width ?? terminalWidth();
|
|
38874
|
+
const sepLen = 3;
|
|
38875
|
+
let count = droppable.length;
|
|
38876
|
+
while (count > 0) {
|
|
38877
|
+
let total = aic ? aic.length : 0;
|
|
38878
|
+
for (let i = 0; i < count; i++) {
|
|
38879
|
+
if (aic || i > 0) total += sepLen;
|
|
38880
|
+
total += droppable[i].plain.length;
|
|
38881
|
+
}
|
|
38882
|
+
if (total <= width) break;
|
|
38883
|
+
if (count === 1 && !aic) break;
|
|
38884
|
+
count--;
|
|
38885
|
+
}
|
|
38886
|
+
const parts = [];
|
|
38887
|
+
if (aic) parts.push(aicText);
|
|
38888
|
+
for (let i = 0; i < count; i++) parts.push(droppable[i].text);
|
|
38889
|
+
if (parts.length === 0) return "";
|
|
38890
|
+
return parts.join(SEP_TEXT);
|
|
38891
|
+
}
|
|
38892
|
+
/**
|
|
38893
|
+
* Convenience: parse stdin JSON + assemble with branch resolution.
|
|
38894
|
+
* `branchOverride` skips the `git` spawn (used by tests). `actualUsd`
|
|
38895
|
+
* comes from `discountedUsdForSnapshot` on the same ledger snapshot as
|
|
38896
|
+
* `aicFragment` (read by the caller — this module never touches the
|
|
38897
|
+
* ledger file).
|
|
38898
|
+
*/
|
|
38899
|
+
function buildRichStatusLine(stdinRaw, aicFragment, opts = {}) {
|
|
38900
|
+
const input = parseStatusInput(stdinRaw);
|
|
38901
|
+
const branch = opts.branchOverride !== void 0 ? opts.branchOverride : resolveGitBranch(input.cwd);
|
|
38902
|
+
return assembleStatusLine(aicFragment, input, {
|
|
38903
|
+
...opts.width !== void 0 ? { width: opts.width } : {},
|
|
38904
|
+
...branch ? { branch } : {},
|
|
38905
|
+
...opts.actualUsd !== void 0 ? { actualUsd: opts.actualUsd } : {}
|
|
38906
|
+
});
|
|
38907
|
+
}
|
|
38908
|
+
var ESC, RESET, DIM, GREEN, YELLOW, RED, ORANGE, CYAN, MAGENTA, BLUE, AIC_COLOR, CTX_BAR_LEN, GIT_TIMEOUT_MS, WIDTH_FALLBACK, SEP_TEXT;
|
|
38909
|
+
var init_default_statusline = __esmMin((() => {
|
|
38910
|
+
init_copilot_discount();
|
|
38911
|
+
init_exec();
|
|
38912
|
+
ESC = "\x1B";
|
|
38913
|
+
RESET = `${ESC}[0m`;
|
|
38914
|
+
DIM = `${ESC}[90m`;
|
|
38915
|
+
GREEN = `${ESC}[32m`;
|
|
38916
|
+
YELLOW = `${ESC}[33m`;
|
|
38917
|
+
RED = `${ESC}[31m`;
|
|
38918
|
+
ORANGE = `${ESC}[38;5;208m`;
|
|
38919
|
+
CYAN = `${ESC}[36m`;
|
|
38920
|
+
MAGENTA = `${ESC}[35m`;
|
|
38921
|
+
BLUE = `${ESC}[34m`;
|
|
38922
|
+
AIC_COLOR = `${ESC}[1;33m`;
|
|
38923
|
+
CTX_BAR_LEN = 10;
|
|
38924
|
+
GIT_TIMEOUT_MS = 300;
|
|
38925
|
+
WIDTH_FALLBACK = 120;
|
|
38926
|
+
SEP_TEXT = `${DIM} | ${RESET}`;
|
|
38927
|
+
}));
|
|
38928
|
+
//#endregion
|
|
38488
38929
|
//#region src/internal-aic-status.ts
|
|
38489
38930
|
var internal_aic_status_exports = /* @__PURE__ */ __exportAll({
|
|
38490
38931
|
composeAicStatusLine: () => composeAicStatusLine,
|
|
@@ -38492,14 +38933,18 @@ var internal_aic_status_exports = /* @__PURE__ */ __exportAll({
|
|
|
38492
38933
|
runUserStatusLine: () => runUserStatusLine
|
|
38493
38934
|
});
|
|
38494
38935
|
/**
|
|
38495
|
-
* Read stdin synchronously
|
|
38496
|
-
* statusLine command; an unread pipe can SIGPIPE the writer on some
|
|
38936
|
+
* Read stdin synchronously. Claude Code pipes session JSON to the
|
|
38937
|
+
* statusLine command; an unread pipe can SIGPIPE the writer on some
|
|
38938
|
+
* platforms. Returns "" when stdin is a TTY or unreadable — callers render
|
|
38939
|
+
* placeholders/omit segments rather than failing.
|
|
38497
38940
|
*/
|
|
38498
|
-
function
|
|
38941
|
+
function readStdin() {
|
|
38499
38942
|
try {
|
|
38500
|
-
if (process.stdin.isTTY) return;
|
|
38501
|
-
readFileSync(0, "utf8");
|
|
38502
|
-
} catch {
|
|
38943
|
+
if (process.stdin.isTTY) return "";
|
|
38944
|
+
return readFileSync(0, "utf8");
|
|
38945
|
+
} catch {
|
|
38946
|
+
return "";
|
|
38947
|
+
}
|
|
38503
38948
|
}
|
|
38504
38949
|
/**
|
|
38505
38950
|
* Pure core: compose the status line from an AIC fragment and a user line.
|
|
@@ -38536,31 +38981,48 @@ function runUserStatusLine(command, timeoutMs = 5e3) {
|
|
|
38536
38981
|
return "";
|
|
38537
38982
|
}
|
|
38538
38983
|
}
|
|
38539
|
-
function
|
|
38984
|
+
function readAicSnapshot() {
|
|
38540
38985
|
try {
|
|
38541
38986
|
const ledgerPath = process.env.GH_ROUTER_AIC_LEDGER;
|
|
38542
|
-
if (!ledgerPath) return "";
|
|
38987
|
+
if (!ledgerPath) return { fragment: "" };
|
|
38543
38988
|
const snapshot = readAicSnapshotFile(ledgerPath);
|
|
38544
|
-
if (!snapshot) return "";
|
|
38545
|
-
|
|
38989
|
+
if (!snapshot) return { fragment: "" };
|
|
38990
|
+
if (snapshot.requests === 0 || snapshot.totalNanoAiu <= 0) return { fragment: "" };
|
|
38991
|
+
return {
|
|
38992
|
+
fragment: formatAicStatus(snapshot),
|
|
38993
|
+
actualUsd: discountedUsdForSnapshot(snapshot).total
|
|
38994
|
+
};
|
|
38546
38995
|
} catch {
|
|
38547
|
-
return "";
|
|
38996
|
+
return { fragment: "" };
|
|
38548
38997
|
}
|
|
38549
38998
|
}
|
|
38550
38999
|
var internalAicStatus;
|
|
38551
39000
|
var init_internal_aic_status = __esmMin((() => {
|
|
38552
39001
|
init_dist$1();
|
|
38553
39002
|
init_aic_ledger();
|
|
39003
|
+
init_copilot_discount();
|
|
39004
|
+
init_default_statusline();
|
|
38554
39005
|
internalAicStatus = defineCommand({
|
|
38555
39006
|
meta: {
|
|
38556
39007
|
name: "internal-aic-status",
|
|
38557
|
-
description: "Internal: Claude Code statusLine handler printing
|
|
39008
|
+
description: "Internal: Claude Code statusLine handler printing AIC total + rich session line."
|
|
38558
39009
|
},
|
|
38559
39010
|
async run() {
|
|
38560
|
-
|
|
38561
|
-
const aic =
|
|
39011
|
+
const stdinRaw = readStdin();
|
|
39012
|
+
const { fragment: aic, actualUsd } = readAicSnapshot();
|
|
38562
39013
|
const userCommand = process.env.GH_ROUTER_AIC_USER_STATUSLINE ?? "";
|
|
38563
|
-
|
|
39014
|
+
if (userCommand.trim()) {
|
|
39015
|
+
const line = composeAicStatusLine(aic, runUserStatusLine(userCommand));
|
|
39016
|
+
if (line) process.stdout.write(`${line}\n`);
|
|
39017
|
+
process.exitCode = 0;
|
|
39018
|
+
return;
|
|
39019
|
+
}
|
|
39020
|
+
let line;
|
|
39021
|
+
try {
|
|
39022
|
+
line = buildRichStatusLine(stdinRaw, aic, { ...actualUsd !== void 0 ? { actualUsd } : {} });
|
|
39023
|
+
} catch {
|
|
39024
|
+
line = aic.trim();
|
|
39025
|
+
}
|
|
38564
39026
|
if (line) process.stdout.write(`${line}\n`);
|
|
38565
39027
|
process.exitCode = 0;
|
|
38566
39028
|
}
|
package/dist/hooks.sha256
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
ae0a2c903c8ec87019aeddd7bb25ae9d2739cf807659e26bbf07952babce45db
|