@vibgrate/cli 2026.803.4 → 2026.804.1
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/agent-YDRDDKPE.js +24 -0
- package/dist/{agent-WYBWUBCC.js.map → agent-YDRDDKPE.js.map} +1 -1
- package/dist/{baseline-3HECX4Q6.js → baseline-IALIGR4A.js} +3 -3
- package/dist/{baseline-3HECX4Q6.js.map → baseline-IALIGR4A.js.map} +1 -1
- package/dist/{chunk-QUI3E3TQ.js → chunk-2U4SXS5U.js} +26 -3
- package/dist/chunk-2U4SXS5U.js.map +1 -0
- package/dist/{chunk-5TS7N7J2.js → chunk-4TPTVRVI.js} +5 -5
- package/dist/{chunk-5TS7N7J2.js.map → chunk-4TPTVRVI.js.map} +1 -1
- package/dist/{chunk-HBQC4XQJ.js → chunk-A4CGGQJ7.js} +5 -6
- package/dist/chunk-A4CGGQJ7.js.map +1 -0
- package/dist/chunk-B2Y45PCA.js +6 -0
- package/dist/{chunk-FZ5Y4KEI.js.map → chunk-B2Y45PCA.js.map} +1 -1
- package/dist/{chunk-2A7XCANX.js → chunk-B6IBSQHG.js} +218 -24
- package/dist/chunk-B6IBSQHG.js.map +1 -0
- package/dist/{chunk-JZGVUH57.js → chunk-CM6OYYBW.js} +4 -4
- package/dist/{chunk-JZGVUH57.js.map → chunk-CM6OYYBW.js.map} +1 -1
- package/dist/{chunk-23UPIFRU.js → chunk-D56WBMAM.js} +7 -8
- package/dist/chunk-D56WBMAM.js.map +1 -0
- package/dist/{chunk-66B4ZQA3.js → chunk-FJ2ARY3S.js} +6 -7
- package/dist/chunk-FJ2ARY3S.js.map +1 -0
- package/dist/{chunk-7TOIESUT.js → chunk-K5GPEWPI.js} +458 -6
- package/dist/chunk-K5GPEWPI.js.map +1 -0
- package/dist/{chunk-5WMFX7TY.js → chunk-KSFYHT5G.js} +4 -4
- package/dist/{chunk-5WMFX7TY.js.map → chunk-KSFYHT5G.js.map} +1 -1
- package/dist/{chunk-4ZMJKR74.js → chunk-L4CYXVW2.js} +4 -4
- package/dist/{chunk-4ZMJKR74.js.map → chunk-L4CYXVW2.js.map} +1 -1
- package/dist/{chunk-BRUMBQV7.js → chunk-L7GGEXZG.js} +4 -4
- package/dist/{chunk-BRUMBQV7.js.map → chunk-L7GGEXZG.js.map} +1 -1
- package/dist/{chunk-KFK7KCAH.js → chunk-NAZLPO63.js} +3 -3
- package/dist/{chunk-KFK7KCAH.js.map → chunk-NAZLPO63.js.map} +1 -1
- package/dist/{chunk-TVRM57CE.js → chunk-NGMVIAKI.js} +4 -4
- package/dist/{chunk-TVRM57CE.js.map → chunk-NGMVIAKI.js.map} +1 -1
- package/dist/{chunk-HVHCXM2E.js → chunk-P63H3DXY.js} +7 -8
- package/dist/chunk-P63H3DXY.js.map +1 -0
- package/dist/{chunk-7BU7CWXC.js → chunk-TASMCKLD.js} +8 -8
- package/dist/{chunk-7BU7CWXC.js.map → chunk-TASMCKLD.js.map} +1 -1
- package/dist/{chunk-UWVFLVZX.js → chunk-UHLFD7EO.js} +4 -4
- package/dist/{chunk-UWVFLVZX.js.map → chunk-UHLFD7EO.js.map} +1 -1
- package/dist/{chunk-OVDL76LB.js → chunk-UZO2T3J2.js} +3 -3
- package/dist/{chunk-OVDL76LB.js.map → chunk-UZO2T3J2.js.map} +1 -1
- package/dist/{chunk-FAA7RBIG.js → chunk-WGIX4S5A.js} +8 -9
- package/dist/chunk-WGIX4S5A.js.map +1 -0
- package/dist/{chunk-BUCNKYTW.js → chunk-XVZMDDU4.js} +5 -5
- package/dist/{chunk-BUCNKYTW.js.map → chunk-XVZMDDU4.js.map} +1 -1
- package/dist/{chunk-537JBQVB.js → chunk-ZZNNXZYB.js} +3 -4
- package/dist/chunk-ZZNNXZYB.js.map +1 -0
- package/dist/cli.js +101 -49
- package/dist/cli.js.map +1 -1
- package/dist/embed-worker-main.js +5 -2
- package/dist/embed-worker-main.js.map +1 -1
- package/dist/{ensure-map-DZ53QXRT.js → ensure-map-DNLGAQRQ.js} +12 -14
- package/dist/{ensure-map-DZ53QXRT.js.map → ensure-map-DNLGAQRQ.js.map} +1 -1
- package/dist/graph-backend-L7PIG7CS.js +13 -0
- package/dist/{graph-backend-3A2M22QN.js.map → graph-backend-L7PIG7CS.js.map} +1 -1
- package/dist/index.d.ts +25 -6
- package/dist/index.js +11 -13
- package/dist/index.js.map +1 -1
- package/dist/{interactive-DB7IC3BL.js → interactive-GQ3O7FKE.js} +22 -24
- package/dist/interactive-GQ3O7FKE.js.map +1 -0
- package/dist/load-VOSNNCOZ.js +9 -0
- package/dist/{load-6KVGUQMU.js.map → load-VOSNNCOZ.js.map} +1 -1
- package/dist/{run-outcome-YOYRC32U.js → run-outcome-I4T5GDQZ.js} +5 -7
- package/dist/run-outcome-I4T5GDQZ.js.map +1 -0
- package/dist/runtime-session-45HT7NZA.js +20 -0
- package/dist/{runtime-session-XEP7IPGP.js.map → runtime-session-45HT7NZA.js.map} +1 -1
- package/dist/session-QUONHFJN.js +15 -0
- package/dist/{session-5WKEACIF.js.map → session-QUONHFJN.js.map} +1 -1
- package/dist/{stream-json-3OJCPBWY.js → stream-json-WEWVI3DW.js} +11 -13
- package/dist/stream-json-WEWVI3DW.js.map +1 -0
- package/dist/{vg-mcp-bridge-PM3C4FQL.js → vg-mcp-bridge-NOG3D6TL.js} +8 -10
- package/dist/vg-mcp-bridge-NOG3D6TL.js.map +1 -0
- package/dist/{vgd-UTLMMPIZ.js → vgd-URRPZ7OD.js} +8 -10
- package/dist/{vgd-UTLMMPIZ.js.map → vgd-URRPZ7OD.js.map} +1 -1
- package/package.json +1 -1
- package/dist/agent-WYBWUBCC.js +0 -26
- package/dist/chunk-23UPIFRU.js.map +0 -1
- package/dist/chunk-2A7XCANX.js.map +0 -1
- package/dist/chunk-4LGDQBYK.js +0 -358
- package/dist/chunk-4LGDQBYK.js.map +0 -1
- package/dist/chunk-537JBQVB.js.map +0 -1
- package/dist/chunk-66B4ZQA3.js.map +0 -1
- package/dist/chunk-7TOIESUT.js.map +0 -1
- package/dist/chunk-FAA7RBIG.js.map +0 -1
- package/dist/chunk-FZ5Y4KEI.js +0 -6
- package/dist/chunk-HBQC4XQJ.js.map +0 -1
- package/dist/chunk-HVHCXM2E.js.map +0 -1
- package/dist/chunk-QUI3E3TQ.js.map +0 -1
- package/dist/chunk-RBMKBYGV.js +0 -102
- package/dist/chunk-RBMKBYGV.js.map +0 -1
- package/dist/graph-backend-3A2M22QN.js +0 -13
- package/dist/interactive-DB7IC3BL.js.map +0 -1
- package/dist/load-6KVGUQMU.js +0 -11
- package/dist/run-outcome-YOYRC32U.js.map +0 -1
- package/dist/runtime-session-XEP7IPGP.js +0 -22
- package/dist/session-5WKEACIF.js +0 -17
- package/dist/stream-json-3OJCPBWY.js.map +0 -1
- package/dist/vg-mcp-bridge-PM3C4FQL.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { resolveIngestHost } from './chunk-HTLDXEHW.js';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { cacheDir } from './chunk-K5GPEWPI.js';
|
|
3
|
+
import { VERSION } from './chunk-B2Y45PCA.js';
|
|
4
4
|
import * as fs from 'fs';
|
|
5
5
|
import * as os from 'os';
|
|
6
6
|
import * as path from 'path';
|
|
@@ -212,5 +212,5 @@ var StatsSharer = class {
|
|
|
212
212
|
};
|
|
213
213
|
|
|
214
214
|
export { StatsSharer, installId, isCI, statsEndpoint, telemetryOptOut };
|
|
215
|
-
//# sourceMappingURL=chunk-
|
|
216
|
-
//# sourceMappingURL=chunk-
|
|
215
|
+
//# sourceMappingURL=chunk-UHLFD7EO.js.map
|
|
216
|
+
//# sourceMappingURL=chunk-UHLFD7EO.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/engine/stats-share.ts"],"names":[],"mappings":";;;;;;;;AAiCA,IAAM,cAAA,GAAiB,GAAA;AAEvB,IAAM,WAAA,GAAc,kBAAA;AAEpB,IAAM,cAAA,GAAsB,IAAA,CAAA,IAAA,CAAQ,EAAA,CAAA,OAAA,EAAQ,EAAG,WAAW,CAAA;AAC1D,IAAM,eAAA,GAAuB,IAAA,CAAA,IAAA,CAAK,cAAA,EAAgB,YAAY,CAAA;AAE9D,IAAM,eAAA,GAAkB,GAAA;AAgCjB,SAAS,eAAA,CAAgB,GAAA,GAAyB,OAAA,CAAQ,GAAA,EAAoB;AACnF,EAAA,MAAM,OAAO,GAAA,CAAI,YAAA,IAAgB,EAAA,EAAI,IAAA,GAAO,WAAA,EAAY;AACxD,EAAA,IAAI,QAAQ,EAAA,IAAM,GAAA,KAAQ,GAAA,IAAO,GAAA,KAAQ,SAAS,OAAO,cAAA;AACzD,EAAA,MAAM,MAAM,GAAA,CAAI,kBAAA,IAAsB,EAAA,EAAI,IAAA,GAAO,WAAA,EAAY;AAC7D,EAAA,IAAI,OAAO,GAAA,IAAO,EAAA,KAAO,OAAA,IAAW,EAAA,KAAO,OAAO,OAAO,oBAAA;AACzD,EAAA,OAAO,IAAA;AACT;AAGA,IAAM,WAAA,GAAc;AAAA,EAClB,IAAA;AAAA,EACA,gBAAA;AAAA,EACA,WAAA;AAAA,EACA,UAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA;AAAA,EACA,aAAA;AAAA,EACA;AACF,CAAA;AAGO,SAAS,IAAA,CAAK,GAAA,GAAyB,OAAA,CAAQ,GAAA,EAAc;AAClE,EAAA,OAAO,WAAA,CAAY,IAAA,CAAK,CAAC,CAAA,KAAM;AAC7B,IAAA,MAAM,OAAO,GAAA,CAAI,CAAC,KAAK,EAAA,EAAI,IAAA,GAAO,WAAA,EAAY;AAC9C,IAAA,OAAO,GAAA,KAAQ,EAAA,IAAM,GAAA,KAAQ,GAAA,IAAO,GAAA,KAAQ,OAAA;AAAA,EAC9C,CAAC,CAAA;AACH;AAcO,SAAS,SAAA,CAAU,GAAA,GAAyB,OAAA,CAAQ,GAAA,EAAa;AACtE,EAAA,IAAI,eAAA,CAAgB,GAAG,CAAA,KAAM,IAAA,IAAQ,KAAK,GAAG,CAAA,SAAU,UAAA,EAAW;AAClE,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,GAAc,EAAA,CAAA,YAAA,CAAa,eAAA,EAAiB,MAAM,EAAE,IAAA,EAAK;AAC/D,IAAA,IAAI,MAAA,CAAO,QAAQ,CAAA,EAAG,OAAO,QAAA;AAAA,EAC/B,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,MAAM,KAAK,UAAA,EAAW;AACtB,EAAA,IAAI;AACF,IAAG,EAAA,CAAA,SAAA,CAAU,cAAA,EAAgB,EAAE,SAAA,EAAW,MAAM,CAAA;AAChD,IAAG,iBAAc,eAAA,EAAiB,EAAA,GAAK,MAAM,EAAE,IAAA,EAAM,KAAO,CAAA;AAAA,EAC9D,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,OAAO,EAAA;AACT;AAEA,SAAS,OAAO,CAAA,EAAoB;AAClC,EAAA,OAAO,iEAAA,CAAkE,KAAK,CAAC,CAAA;AACjF;AAEA,SAAS,UAAA,GAAqB;AAC5B,EAAA,OAAO,UAAA,EAAW;AACpB;AAGO,SAAS,aAAA,GAAwB;AACtC,EAAA,MAAM,QAAA,GAAW,QAAQ,GAAA,CAAI,uBAAA;AAC7B,EAAA,IAAI,QAAA,IAAY,cAAA,CAAe,IAAA,CAAK,QAAQ,GAAG,OAAO,QAAA;AACtD,EAAA,OAAO,CAAA,QAAA,EAAW,mBAAmB,CAAA,wBAAA,CAAA;AACvC;AAEA,SAAS,WAAW,IAAA,EAAsB;AACxC,EAAA,OAAY,IAAA,CAAA,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,EAAG,WAAW,CAAA;AAC9C;AAEA,SAAS,eAAe,IAAA,EAAsB;AAC5C,EAAA,OAAY,IAAA,CAAA,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,EAAG,eAAe,CAAA;AAClD;AAEA,SAAS,WAAW,IAAA,EAAsB;AACxC,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,KAAK,KAAA,CAAS,EAAA,CAAA,YAAA,CAAa,WAAW,IAAI,CAAA,EAAG,MAAM,CAAC,CAAA;AAChE,IAAA,OAAO,OAAO,IAAI,MAAA,KAAW,QAAA,IAAY,IAAI,MAAA,IAAU,CAAA,GAAI,IAAI,MAAA,GAAS,CAAA;AAAA,EAC1E,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,CAAA;AAAA,EACT;AACF;AAEA,SAAS,WAAA,CAAY,MAAc,MAAA,EAAsB;AACvD,EAAA,IAAI;AACF,IAAG,aAAU,QAAA,CAAS,IAAI,GAAG,EAAE,SAAA,EAAW,MAAM,CAAA;AAChD,IAAG,EAAA,CAAA,aAAA,CAAc,UAAA,CAAW,IAAI,CAAA,EAAG,IAAA,CAAK,UAAU,EAAE,MAAA,EAAQ,CAAA,GAAI,IAAI,CAAA;AAAA,EACtE,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAOO,SAAS,UAAA,CACd,IAAA,EACA,UAAA,EACA,EAAA,GAAK,WAAU,EACkC;AACjD,EAAA,MAAM,IAAA,GAAO,eAAe,IAAI,CAAA;AAChC,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,IAAI;AACF,IAAA,IAAA,GAAU,EAAA,CAAA,QAAA,CAAS,IAAI,CAAA,CAAE,IAAA;AAAA,EAC3B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,KAAA,EAAO,IAAA,EAAM,SAAA,EAAW,CAAA,EAAE;AAAA,EACrC;AAEA,EAAA,MAAM,KAAA,GAAQ,UAAA,GAAa,IAAA,GAAO,CAAA,GAAI,UAAA;AACtC,EAAA,IAAI,SAAS,IAAA,EAAM,OAAO,EAAE,KAAA,EAAO,IAAA,EAAM,WAAW,IAAA,EAAK;AAEzD,EAAA,IAAI,IAAA,GAAO,EAAA;AACX,EAAA,IAAI;AACF,IAAA,MAAM,EAAA,GAAQ,EAAA,CAAA,QAAA,CAAS,IAAA,EAAM,GAAG,CAAA;AAChC,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,MAAA,CAAO,KAAA,CAAM,IAAA,GAAO,KAAK,CAAA;AACrC,MAAG,YAAS,EAAA,EAAI,GAAA,EAAK,CAAA,EAAG,GAAA,CAAI,QAAQ,KAAK,CAAA;AACzC,MAAA,IAAA,GAAO,GAAA,CAAI,SAAS,MAAM,CAAA;AAAA,IAC5B,CAAA,SAAE;AACA,MAAG,aAAU,EAAE,CAAA;AAAA,IACjB;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,KAAA,EAAO,IAAA,EAAM,SAAA,EAAW,UAAA,EAAW;AAAA,EAC9C;AAIA,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,WAAA,CAAY,IAAI,CAAA;AACpC,EAAA,IAAI,SAAS,CAAA,EAAG,OAAO,EAAE,KAAA,EAAO,IAAA,EAAM,WAAW,KAAA,EAAM;AACvD,EAAA,MAAM,QAAA,GAAW,QAAQ,MAAA,GAAS,CAAA;AAClC,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAsB;AACvC,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,IAAI,KAAA,GAAQ,QAAA;AACZ,EAAA,IAAI,KAAA,GAAQ,CAAA,QAAA;AACZ,EAAA,KAAA,MAAW,IAAA,IAAQ,KAAK,KAAA,CAAM,CAAA,EAAG,MAAM,CAAA,CAAE,KAAA,CAAM,IAAI,CAAA,EAAG;AACpD,IAAA,IAAI,CAAC,IAAA,CAAK,IAAA,EAAK,EAAG;AAClB,IAAA,IAAI,CAAA;AACJ,IAAA,IAAI;AACF,MAAA,CAAA,GAAI,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,IACrB,CAAA,CAAA,MAAQ;AACN,MAAA;AAAA,IACF;AACA,IAAA,MAAM,MAAA,GAAiB,EAAE,MAAA,IAAU,KAAA;AACnC,IAAA,MAAM,MAAA,GAAS,EAAE,MAAA,IAAU,SAAA;AAC3B,IAAA,MAAM,OAAA,GAAmB,EAAE,OAAA,IAAW,UAAA;AACtC,IAAA,MAAM,GAAA,GAAM,GAAG,MAAM,CAAA,CAAA,EAAI,MAAM,CAAA,CAAA,EAAI,CAAA,CAAE,IAAI,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA;AACpD,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA,IAAK;AAAA,MAC3B,MAAA;AAAA,MACA,MAAA;AAAA,MACA,MAAM,CAAA,CAAE,IAAA;AAAA,MACR,OAAA;AAAA,MACA,KAAA,EAAO,CAAA;AAAA,MACP,QAAA,EAAU,CAAA;AAAA,MACV,cAAA,EAAgB;AAAA,KAClB;AACA,IAAA,GAAA,CAAI,KAAA,EAAA;AACJ,IAAA,GAAA,CAAI,QAAA,IAAY,EAAE,QAAA,IAAY,CAAA;AAC9B,IAAA,GAAA,CAAI,cAAA,IAAkB,EAAE,cAAA,IAAkB,CAAA;AAC1C,IAAA,IAAA,CAAK,GAAA,CAAI,KAAK,GAAG,CAAA;AACjB,IAAA,KAAA,EAAA;AACA,IAAA,IAAI,OAAO,CAAA,CAAE,EAAA,KAAO,QAAA,EAAU;AAC5B,MAAA,IAAI,CAAA,CAAE,EAAA,GAAK,KAAA,EAAO,KAAA,GAAQ,CAAA,CAAE,EAAA;AAC5B,MAAA,IAAI,CAAA,CAAE,EAAA,GAAK,KAAA,EAAO,KAAA,GAAQ,CAAA,CAAE,EAAA;AAAA,IAC9B;AAAA,EACF;AACA,EAAA,IAAI,KAAA,KAAU,CAAA,IAAK,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,EAAG,OAAO,EAAE,KAAA,EAAO,IAAA,EAAM,SAAA,EAAW,QAAA,EAAS;AACtF,EAAA,MAAM,KAAA,GAAoB;AAAA,IACxB,aAAA,EAAe,cAAA;AAAA,IACf,SAAA,EAAW,EAAA;AAAA,IACX,SAAA,EAAW,OAAA;AAAA,IACX,IAAI,OAAA,CAAQ,QAAA;AAAA,IACZ,MAAM,OAAA,CAAQ,IAAA;AAAA,IACd,WAAA,EAAa,IAAI,IAAA,CAAK,KAAK,EAAE,WAAA,EAAY;AAAA,IACzC,SAAA,EAAW,IAAI,IAAA,CAAK,KAAK,EAAE,WAAA,EAAY;AAAA,IACvC,UAAA,EAAY,KAAA;AAAA,IACZ,IAAA,EAAM,CAAC,GAAG,IAAA,CAAK,QAAQ;AAAA,GACzB;AACA,EAAA,OAAO,EAAE,KAAA,EAAO,SAAA,EAAW,QAAA,EAAS;AACtC;AAMA,eAAe,UAAU,KAAA,EAAqC;AAC5D,EAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,EAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,UAAA,CAAW,KAAA,IAAS,eAAe,CAAA;AAClE,EAAA,KAAA,CAAM,KAAA,IAAQ;AACd,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,aAAA,EAAc,EAAG;AAAA,MACvC,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAoB,YAAY,OAAA,EAAQ;AAAA,MACnE,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,KAAK,CAAA;AAAA,MAC1B,QAAQ,UAAA,CAAW;AAAA,KACpB,CAAA;AACD,IAAA,OAAO,GAAA,CAAI,EAAA;AAAA,EACb,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT,CAAA,SAAE;AACA,IAAA,YAAA,CAAa,KAAK,CAAA;AAAA,EACpB;AACF;AAOO,IAAM,cAAN,MAAkB;AAAA,EAKvB,YAA6B,IAAA,EAAc;AAAd,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAC3B,IAAA,IAAA,CAAK,MAAA,GAAS,WAAW,IAAI,CAAA;AAAA,EAC/B;AAAA,EAF6B,IAAA;AAAA,EAJZ,KAAK,SAAA,EAAU;AAAA,EACxB,MAAA;AAAA,EACA,QAAA,GAAW,KAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUnB,MAAM,KAAA,GAAuB;AAC3B,IAAA,IAAI,KAAK,QAAA,EAAU;AACnB,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAChB,IAAA,IAAI;AACF,MAAA,MAAM,EAAE,KAAA,EAAO,SAAA,EAAU,GAAI,UAAA,CAAW,KAAK,IAAA,EAAM,IAAA,CAAK,MAAA,EAAQ,IAAA,CAAK,EAAE,CAAA;AACvE,MAAA,IAAI,CAAC,KAAA,EAAO;AAEV,QAAA,IAAI,SAAA,GAAY,KAAK,MAAA,EAAQ;AAC3B,UAAA,IAAA,CAAK,MAAA,GAAS,SAAA;AACd,UAAA,WAAA,CAAY,IAAA,CAAK,MAAM,SAAS,CAAA;AAAA,QAClC;AACA,QAAA;AAAA,MACF;AACA,MAAA,MAAM,EAAA,GAAK,MAAM,SAAA,CAAU,KAAK,CAAA;AAChC,MAAA,IAAI,EAAA,EAAI;AACN,QAAA,IAAA,CAAK,MAAA,GAAS,SAAA;AACd,QAAA,WAAA,CAAY,IAAA,CAAK,MAAM,SAAS,CAAA;AAAA,MAClC;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAER,CAAA,SAAE;AACA,MAAA,IAAA,CAAK,QAAA,GAAW,KAAA;AAAA,IAClB;AAAA,EACF;AACF","file":"chunk-UWVFLVZX.js","sourcesContent":["import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport { cacheDir } from './cache.js';\nimport { VERSION } from '../version.js';\nimport { resolveIngestHost } from '../reporting/regions.js';\nimport type { SavingEntry, Source, Outcome } from './savings.js';\n\n/**\n * Opt-in usage-stats sharing for `vg serve --share-stats`.\n *\n * This is the ONLY path in `vg serve` that sends anything off the machine, and\n * it is off unless the operator explicitly asks for it. What we send is the\n * same counts-only ledger `vg savings` reports locally — per (source, client,\n * tool, outcome): how many calls and the vg-vs-grep token figures — plus the vg\n * version, OS/arch, and a random per-install id. We never send code, file paths,\n * question text, repo identity, or any credential. See GUARDRAILS §3.4.\n *\n * Even when the flag is passed, the universal `DO_NOT_TRACK` opt-out (or\n * `VIBGRATE_TELEMETRY=0`) wins: nothing is uploaded and no install id is ever\n * minted or persisted (see `telemetryOptOut` / `installId`).\n *\n * Design:\n * - The local ledger (savings.jsonl) is the single source of truth; the flusher\n * reads only the tail past a persisted byte offset, so a batch is sent once.\n * - Fire-and-forget with a short timeout. A network problem never blocks a tool\n * call and never throws — the offset only advances on a confirmed 2xx, so a\n * failed batch is retried on the next flush.\n * - Fully offline-safe: under `--local` the sharer is never constructed.\n */\n\n/** Payload schema version — must match the server's `mcpUsageStatsSchema`. */\nconst SCHEMA_VERSION = '1';\n/** Where the offset (and cached install id) live, per repo, beside the ledger. */\nconst OFFSET_FILE = 'stats-share.json';\n/** The machine-global anonymous install id lives here (stable across repos). */\nconst INSTALL_ID_DIR = path.join(os.homedir(), '.vibgrate');\nconst INSTALL_ID_FILE = path.join(INSTALL_ID_DIR, 'install-id');\n/** Give a flush POST a hard ceiling so a hung endpoint never stalls shutdown. */\nconst SEND_TIMEOUT_MS = 4000;\n\n/** One aggregated row of the shared batch — counts only. */\nexport interface StatsRow {\n source: Source;\n client: string;\n tool: string;\n outcome: Outcome;\n calls: number;\n vgTokens: number;\n baselineTokens: number;\n}\n\n/** The counts-only batch POSTed to the ingest endpoint. */\nexport interface StatsBatch {\n schemaVersion: string;\n installId: string;\n vgVersion: string;\n os: string;\n arch: string;\n windowStart: string;\n windowEnd: string;\n totalCalls: number;\n rows: StatsRow[];\n}\n\n/**\n * The universal opt-out (https://consoledonottrack.com) plus a tool-specific\n * alias, honoured even when `--share-stats` is passed explicitly. Pure function\n * of the environment for testability. Returns the name of the variable that\n * opted out (for the disclosure message), or null when sharing may proceed.\n */\nexport function telemetryOptOut(env: NodeJS.ProcessEnv = process.env): string | null {\n const dnt = (env.DO_NOT_TRACK ?? '').trim().toLowerCase();\n if (dnt !== '' && dnt !== '0' && dnt !== 'false') return 'DO_NOT_TRACK';\n const vt = (env.VIBGRATE_TELEMETRY ?? '').trim().toLowerCase();\n if (vt === '0' || vt === 'false' || vt === 'off') return 'VIBGRATE_TELEMETRY';\n return null;\n}\n\n/** Common CI environment markers — a CI runner is never an interactive session. */\nconst CI_ENV_VARS = [\n 'CI',\n 'GITHUB_ACTIONS',\n 'GITLAB_CI',\n 'CIRCLECI',\n 'TRAVIS',\n 'BUILDKITE',\n 'JENKINS_URL',\n 'TF_BUILD',\n] as const;\n\n/** True when running under a recognised CI system. Pure function of the env. */\nexport function isCI(env: NodeJS.ProcessEnv = process.env): boolean {\n return CI_ENV_VARS.some((v) => {\n const val = (env[v] ?? '').trim().toLowerCase();\n return val !== '' && val !== '0' && val !== 'false';\n });\n}\n\n/**\n * Read (or lazily create) the anonymous per-install id — a random UUID stored in\n * `~/.vibgrate/install-id`. It is *not* tied to the user, the repo, or any\n * account; it only lets us de-duplicate batches from the same install when\n * aggregating. If the home dir isn't writable we fall back to an ephemeral id\n * so sharing still works (it just can't be de-duplicated across restarts).\n *\n * Under an env opt-out no id is ever read or persisted (the sharing path isn't\n * reached then either — this is defence in depth), and on CI runners the id is\n * ephemeral: a persisted id on a shared/throwaway runner would be meaningless\n * for de-duplication and would leave state behind on machines we don't own.\n */\nexport function installId(env: NodeJS.ProcessEnv = process.env): string {\n if (telemetryOptOut(env) !== null || isCI(env)) return randomUuid();\n try {\n const existing = fs.readFileSync(INSTALL_ID_FILE, 'utf8').trim();\n if (isUuid(existing)) return existing;\n } catch {\n /* not created yet */\n }\n const id = randomUuid();\n try {\n fs.mkdirSync(INSTALL_ID_DIR, { recursive: true });\n fs.writeFileSync(INSTALL_ID_FILE, id + '\\n', { mode: 0o600 });\n } catch {\n /* home dir read-only — use the ephemeral id for this process */\n }\n return id;\n}\n\nfunction isUuid(s: string): boolean {\n return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(s);\n}\n\nfunction randomUuid(): string {\n return randomUUID();\n}\n\n/** Resolve the ingest endpoint: env override wins, else the default region host. */\nexport function statsEndpoint(): string {\n const override = process.env.VIBGRATE_STATS_ENDPOINT;\n if (override && /^https?:\\/\\//.test(override)) return override;\n return `https://${resolveIngestHost()}/v1/ingest/cli-mcp-usage`;\n}\n\nfunction offsetPath(root: string): string {\n return path.join(cacheDir(root), OFFSET_FILE);\n}\n\nfunction ledgerFilePath(root: string): string {\n return path.join(cacheDir(root), 'savings.jsonl');\n}\n\nfunction readOffset(root: string): number {\n try {\n const raw = JSON.parse(fs.readFileSync(offsetPath(root), 'utf8')) as { offset?: number };\n return typeof raw.offset === 'number' && raw.offset >= 0 ? raw.offset : 0;\n } catch {\n return 0;\n }\n}\n\nfunction writeOffset(root: string, offset: number): void {\n try {\n fs.mkdirSync(cacheDir(root), { recursive: true });\n fs.writeFileSync(offsetPath(root), JSON.stringify({ offset }) + '\\n');\n } catch {\n /* best-effort; a lost offset just means one batch may re-send */\n }\n}\n\n/**\n * Aggregate the ledger entries after `fromOffset` into a counts-only batch.\n * Returns the batch (or null if there's nothing new) and the new byte offset to\n * persist once the batch is confirmed sent.\n */\nexport function buildBatch(\n root: string,\n fromOffset: number,\n id = installId(),\n): { batch: StatsBatch | null; newOffset: number } {\n const file = ledgerFilePath(root);\n let size = 0;\n try {\n size = fs.statSync(file).size;\n } catch {\n return { batch: null, newOffset: 0 };\n }\n // The ledger was truncated/recreated under us — re-read from the top.\n const start = fromOffset > size ? 0 : fromOffset;\n if (start >= size) return { batch: null, newOffset: size };\n\n let text = '';\n try {\n const fd = fs.openSync(file, 'r');\n try {\n const buf = Buffer.alloc(size - start);\n fs.readSync(fd, buf, 0, buf.length, start);\n text = buf.toString('utf8');\n } finally {\n fs.closeSync(fd);\n }\n } catch {\n return { batch: null, newOffset: fromOffset };\n }\n\n // Only whole lines are complete; a trailing partial line (mid-append) is left\n // for the next flush by rewinding the offset to the last newline.\n const lastNl = text.lastIndexOf('\\n');\n if (lastNl < 0) return { batch: null, newOffset: start };\n const consumed = start + lastNl + 1;\n const rows = new Map<string, StatsRow>();\n let total = 0;\n let minTs = Infinity;\n let maxTs = -Infinity;\n for (const line of text.slice(0, lastNl).split('\\n')) {\n if (!line.trim()) continue;\n let e: SavingEntry;\n try {\n e = JSON.parse(line) as SavingEntry;\n } catch {\n continue;\n }\n const source: Source = e.source ?? 'mcp';\n const client = e.client ?? 'unknown';\n const outcome: Outcome = e.outcome ?? 'complete';\n const key = `${source}|${client}|${e.tool}|${outcome}`;\n const row = rows.get(key) ?? {\n source,\n client,\n tool: e.tool,\n outcome,\n calls: 0,\n vgTokens: 0,\n baselineTokens: 0,\n };\n row.calls++;\n row.vgTokens += e.vgTokens ?? 0;\n row.baselineTokens += e.baselineTokens ?? 0;\n rows.set(key, row);\n total++;\n if (typeof e.ts === 'number') {\n if (e.ts < minTs) minTs = e.ts;\n if (e.ts > maxTs) maxTs = e.ts;\n }\n }\n if (total === 0 || !Number.isFinite(minTs)) return { batch: null, newOffset: consumed };\n const batch: StatsBatch = {\n schemaVersion: SCHEMA_VERSION,\n installId: id,\n vgVersion: VERSION,\n os: process.platform,\n arch: process.arch,\n windowStart: new Date(minTs).toISOString(),\n windowEnd: new Date(maxTs).toISOString(),\n totalCalls: total,\n rows: [...rows.values()],\n };\n return { batch, newOffset: consumed };\n}\n\n/**\n * POST a batch to the endpoint. Never throws; returns whether it was accepted.\n * A short timeout keeps a hung endpoint from stalling the caller (e.g. shutdown).\n */\nasync function postBatch(batch: StatsBatch): Promise<boolean> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), SEND_TIMEOUT_MS);\n timer.unref?.();\n try {\n const res = await fetch(statsEndpoint(), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', Connection: 'close' },\n body: JSON.stringify(batch),\n signal: controller.signal,\n });\n return res.ok;\n } catch {\n return false;\n } finally {\n clearTimeout(timer);\n }\n}\n\n/**\n * Periodic + on-shutdown flusher for one serve session. Holds the install id and\n * the persisted offset so each flush reads only new ledger lines and advances the\n * offset only when the batch is confirmed sent.\n */\nexport class StatsSharer {\n private readonly id = installId();\n private offset: number;\n private flushing = false;\n\n constructor(private readonly root: string) {\n this.offset = readOffset(root);\n }\n\n /**\n * Flush any new ledger entries. Single-flight (a slow POST won't overlap the\n * next tick). Best-effort: any failure is swallowed and retried next time.\n */\n async flush(): Promise<void> {\n if (this.flushing) return;\n this.flushing = true;\n try {\n const { batch, newOffset } = buildBatch(this.root, this.offset, this.id);\n if (!batch) {\n // Nothing to send, but still advance past consumed blank/partial space.\n if (newOffset > this.offset) {\n this.offset = newOffset;\n writeOffset(this.root, newOffset);\n }\n return;\n }\n const ok = await postBatch(batch);\n if (ok) {\n this.offset = newOffset;\n writeOffset(this.root, newOffset);\n }\n } catch {\n /* never let sharing break serving */\n } finally {\n this.flushing = false;\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/engine/stats-share.ts"],"names":[],"mappings":"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","file":"chunk-UHLFD7EO.js","sourcesContent":["import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { randomUUID } from 'node:crypto';\nimport { cacheDir } from './cache.js';\nimport { VERSION } from '../version.js';\nimport { resolveIngestHost } from '../reporting/regions.js';\nimport type { SavingEntry, Source, Outcome } from './savings.js';\n\n/**\n * Opt-in usage-stats sharing for `vg serve --share-stats`.\n *\n * This is the ONLY path in `vg serve` that sends anything off the machine, and\n * it is off unless the operator explicitly asks for it. What we send is the\n * same counts-only ledger `vg savings` reports locally — per (source, client,\n * tool, outcome): how many calls and the vg-vs-grep token figures — plus the vg\n * version, OS/arch, and a random per-install id. We never send code, file paths,\n * question text, repo identity, or any credential. See GUARDRAILS §3.4.\n *\n * Even when the flag is passed, the universal `DO_NOT_TRACK` opt-out (or\n * `VIBGRATE_TELEMETRY=0`) wins: nothing is uploaded and no install id is ever\n * minted or persisted (see `telemetryOptOut` / `installId`).\n *\n * Design:\n * - The local ledger (savings.jsonl) is the single source of truth; the flusher\n * reads only the tail past a persisted byte offset, so a batch is sent once.\n * - Fire-and-forget with a short timeout. A network problem never blocks a tool\n * call and never throws — the offset only advances on a confirmed 2xx, so a\n * failed batch is retried on the next flush.\n * - Fully offline-safe: under `--local` the sharer is never constructed.\n */\n\n/** Payload schema version — must match the server's `mcpUsageStatsSchema`. */\nconst SCHEMA_VERSION = '1';\n/** Where the offset (and cached install id) live, per repo, beside the ledger. */\nconst OFFSET_FILE = 'stats-share.json';\n/** The machine-global anonymous install id lives here (stable across repos). */\nconst INSTALL_ID_DIR = path.join(os.homedir(), '.vibgrate');\nconst INSTALL_ID_FILE = path.join(INSTALL_ID_DIR, 'install-id');\n/** Give a flush POST a hard ceiling so a hung endpoint never stalls shutdown. */\nconst SEND_TIMEOUT_MS = 4000;\n\n/** One aggregated row of the shared batch — counts only. */\nexport interface StatsRow {\n source: Source;\n client: string;\n tool: string;\n outcome: Outcome;\n calls: number;\n vgTokens: number;\n baselineTokens: number;\n}\n\n/** The counts-only batch POSTed to the ingest endpoint. */\nexport interface StatsBatch {\n schemaVersion: string;\n installId: string;\n vgVersion: string;\n os: string;\n arch: string;\n windowStart: string;\n windowEnd: string;\n totalCalls: number;\n rows: StatsRow[];\n}\n\n/**\n * The universal opt-out (https://consoledonottrack.com) plus a tool-specific\n * alias, honoured even when `--share-stats` is passed explicitly. Pure function\n * of the environment for testability. Returns the name of the variable that\n * opted out (for the disclosure message), or null when sharing may proceed.\n */\nexport function telemetryOptOut(env: NodeJS.ProcessEnv = process.env): string | null {\n const dnt = (env.DO_NOT_TRACK ?? '').trim().toLowerCase();\n if (dnt !== '' && dnt !== '0' && dnt !== 'false') return 'DO_NOT_TRACK';\n const vt = (env.VIBGRATE_TELEMETRY ?? '').trim().toLowerCase();\n if (vt === '0' || vt === 'false' || vt === 'off') return 'VIBGRATE_TELEMETRY';\n return null;\n}\n\n/** Common CI environment markers — a CI runner is never an interactive session. */\nconst CI_ENV_VARS = [\n 'CI',\n 'GITHUB_ACTIONS',\n 'GITLAB_CI',\n 'CIRCLECI',\n 'TRAVIS',\n 'BUILDKITE',\n 'JENKINS_URL',\n 'TF_BUILD',\n] as const;\n\n/** True when running under a recognised CI system. Pure function of the env. */\nexport function isCI(env: NodeJS.ProcessEnv = process.env): boolean {\n return CI_ENV_VARS.some((v) => {\n const val = (env[v] ?? '').trim().toLowerCase();\n return val !== '' && val !== '0' && val !== 'false';\n });\n}\n\n/**\n * Read (or lazily create) the anonymous per-install id — a random UUID stored in\n * `~/.vibgrate/install-id`. It is *not* tied to the user, the repo, or any\n * account; it only lets us de-duplicate batches from the same install when\n * aggregating. If the home dir isn't writable we fall back to an ephemeral id\n * so sharing still works (it just can't be de-duplicated across restarts).\n *\n * Under an env opt-out no id is ever read or persisted (the sharing path isn't\n * reached then either — this is defence in depth), and on CI runners the id is\n * ephemeral: a persisted id on a shared/throwaway runner would be meaningless\n * for de-duplication and would leave state behind on machines we don't own.\n */\nexport function installId(env: NodeJS.ProcessEnv = process.env): string {\n if (telemetryOptOut(env) !== null || isCI(env)) return randomUuid();\n try {\n const existing = fs.readFileSync(INSTALL_ID_FILE, 'utf8').trim();\n if (isUuid(existing)) return existing;\n } catch {\n /* not created yet */\n }\n const id = randomUuid();\n try {\n fs.mkdirSync(INSTALL_ID_DIR, { recursive: true });\n fs.writeFileSync(INSTALL_ID_FILE, id + '\\n', { mode: 0o600 });\n } catch {\n /* home dir read-only — use the ephemeral id for this process */\n }\n return id;\n}\n\nfunction isUuid(s: string): boolean {\n return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(s);\n}\n\nfunction randomUuid(): string {\n return randomUUID();\n}\n\n/** Resolve the ingest endpoint: env override wins, else the default region host. */\nexport function statsEndpoint(): string {\n const override = process.env.VIBGRATE_STATS_ENDPOINT;\n if (override && /^https?:\\/\\//.test(override)) return override;\n return `https://${resolveIngestHost()}/v1/ingest/cli-mcp-usage`;\n}\n\nfunction offsetPath(root: string): string {\n return path.join(cacheDir(root), OFFSET_FILE);\n}\n\nfunction ledgerFilePath(root: string): string {\n return path.join(cacheDir(root), 'savings.jsonl');\n}\n\nfunction readOffset(root: string): number {\n try {\n const raw = JSON.parse(fs.readFileSync(offsetPath(root), 'utf8')) as { offset?: number };\n return typeof raw.offset === 'number' && raw.offset >= 0 ? raw.offset : 0;\n } catch {\n return 0;\n }\n}\n\nfunction writeOffset(root: string, offset: number): void {\n try {\n fs.mkdirSync(cacheDir(root), { recursive: true });\n fs.writeFileSync(offsetPath(root), JSON.stringify({ offset }) + '\\n');\n } catch {\n /* best-effort; a lost offset just means one batch may re-send */\n }\n}\n\n/**\n * Aggregate the ledger entries after `fromOffset` into a counts-only batch.\n * Returns the batch (or null if there's nothing new) and the new byte offset to\n * persist once the batch is confirmed sent.\n */\nexport function buildBatch(\n root: string,\n fromOffset: number,\n id = installId(),\n): { batch: StatsBatch | null; newOffset: number } {\n const file = ledgerFilePath(root);\n let size = 0;\n try {\n size = fs.statSync(file).size;\n } catch {\n return { batch: null, newOffset: 0 };\n }\n // The ledger was truncated/recreated under us — re-read from the top.\n const start = fromOffset > size ? 0 : fromOffset;\n if (start >= size) return { batch: null, newOffset: size };\n\n let text = '';\n try {\n const fd = fs.openSync(file, 'r');\n try {\n const buf = Buffer.alloc(size - start);\n fs.readSync(fd, buf, 0, buf.length, start);\n text = buf.toString('utf8');\n } finally {\n fs.closeSync(fd);\n }\n } catch {\n return { batch: null, newOffset: fromOffset };\n }\n\n // Only whole lines are complete; a trailing partial line (mid-append) is left\n // for the next flush by rewinding the offset to the last newline.\n const lastNl = text.lastIndexOf('\\n');\n if (lastNl < 0) return { batch: null, newOffset: start };\n const consumed = start + lastNl + 1;\n const rows = new Map<string, StatsRow>();\n let total = 0;\n let minTs = Infinity;\n let maxTs = -Infinity;\n for (const line of text.slice(0, lastNl).split('\\n')) {\n if (!line.trim()) continue;\n let e: SavingEntry;\n try {\n e = JSON.parse(line) as SavingEntry;\n } catch {\n continue;\n }\n const source: Source = e.source ?? 'mcp';\n const client = e.client ?? 'unknown';\n const outcome: Outcome = e.outcome ?? 'complete';\n const key = `${source}|${client}|${e.tool}|${outcome}`;\n const row = rows.get(key) ?? {\n source,\n client,\n tool: e.tool,\n outcome,\n calls: 0,\n vgTokens: 0,\n baselineTokens: 0,\n };\n row.calls++;\n row.vgTokens += e.vgTokens ?? 0;\n row.baselineTokens += e.baselineTokens ?? 0;\n rows.set(key, row);\n total++;\n if (typeof e.ts === 'number') {\n if (e.ts < minTs) minTs = e.ts;\n if (e.ts > maxTs) maxTs = e.ts;\n }\n }\n if (total === 0 || !Number.isFinite(minTs)) return { batch: null, newOffset: consumed };\n const batch: StatsBatch = {\n schemaVersion: SCHEMA_VERSION,\n installId: id,\n vgVersion: VERSION,\n os: process.platform,\n arch: process.arch,\n windowStart: new Date(minTs).toISOString(),\n windowEnd: new Date(maxTs).toISOString(),\n totalCalls: total,\n rows: [...rows.values()],\n };\n return { batch, newOffset: consumed };\n}\n\n/**\n * POST a batch to the endpoint. Never throws; returns whether it was accepted.\n * A short timeout keeps a hung endpoint from stalling the caller (e.g. shutdown).\n */\nasync function postBatch(batch: StatsBatch): Promise<boolean> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), SEND_TIMEOUT_MS);\n timer.unref?.();\n try {\n const res = await fetch(statsEndpoint(), {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', Connection: 'close' },\n body: JSON.stringify(batch),\n signal: controller.signal,\n });\n return res.ok;\n } catch {\n return false;\n } finally {\n clearTimeout(timer);\n }\n}\n\n/**\n * Periodic + on-shutdown flusher for one serve session. Holds the install id and\n * the persisted offset so each flush reads only new ledger lines and advances the\n * offset only when the batch is confirmed sent.\n */\nexport class StatsSharer {\n private readonly id = installId();\n private offset: number;\n private flushing = false;\n\n constructor(private readonly root: string) {\n this.offset = readOffset(root);\n }\n\n /**\n * Flush any new ledger entries. Single-flight (a slow POST won't overlap the\n * next tick). Best-effort: any failure is swallowed and retried next time.\n */\n async flush(): Promise<void> {\n if (this.flushing) return;\n this.flushing = true;\n try {\n const { batch, newOffset } = buildBatch(this.root, this.offset, this.id);\n if (!batch) {\n // Nothing to send, but still advance past consumed blank/partial space.\n if (newOffset > this.offset) {\n this.offset = newOffset;\n writeOffset(this.root, newOffset);\n }\n return;\n }\n const ok = await postBatch(batch);\n if (ok) {\n this.offset = newOffset;\n writeOffset(this.root, newOffset);\n }\n } catch {\n /* never let sharing break serving */\n } finally {\n this.flushing = false;\n }\n }\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { startVgdServer } from './chunk-
|
|
1
|
+
import { startVgdServer } from './chunk-L4CYXVW2.js';
|
|
2
2
|
import { vgdIsRunning, vgdRequest } from './chunk-RBIRXQR6.js';
|
|
3
3
|
|
|
4
4
|
// src/code/runtime-session.ts
|
|
@@ -78,5 +78,5 @@ function noneSession() {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
export { startCodeRuntimeSession };
|
|
81
|
-
//# sourceMappingURL=chunk-
|
|
82
|
-
//# sourceMappingURL=chunk-
|
|
81
|
+
//# sourceMappingURL=chunk-UZO2T3J2.js.map
|
|
82
|
+
//# sourceMappingURL=chunk-UZO2T3J2.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/code/runtime-session.ts"],"names":[],"mappings":"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","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../src/code/runtime-session.ts"],"names":[],"mappings":"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","file":"chunk-UZO2T3J2.js","sourcesContent":["/**\n * Session boundary between VG Code and the Fusion Runtime daemon (`vgd`).\n *\n * Replaces the old {@link GraphProcess} (`vg serve` child) for the interactive\n * coding REPL. Behaviour:\n *\n * 1. If a local vgd is already running — register this workspace and leave the\n * daemon running when the session ends (unregister only).\n * 2. Otherwise — start an **in-process** vgd for the life of the session and\n * tear it down on dispose. No second OS process, no `vg serve` spawn.\n *\n * Never throws: a failure to attach degrades to “no runtime session” and the\n * agent continues with the in-process graph only (same safety as GraphProcess).\n */\n\nimport { startVgdServer, vgdIsRunning, vgdRequest, type VgdServer } from '../runtime/vgd/index.js';\nimport type { WorkspaceRecord } from '../runtime/vgd/protocol.js';\n\nexport type RuntimeSessionKind = 'attached' | 'owned' | 'none';\n\nexport interface RuntimeSessionOptions {\n root: string;\n /** Override socket path (tests). */\n socketPath?: string;\n /** Injectable connect/start hooks (tests). */\n isRunning?: (socketPath?: string) => Promise<boolean>;\n request?: typeof vgdRequest;\n startServer?: (opts: { socketPath?: string }) => Promise<VgdServer>;\n}\n\nexport interface CodeRuntimeSession {\n readonly kind: RuntimeSessionKind;\n /** Daemon pid when known (attached status or owned process). */\n readonly pid: number | undefined;\n readonly workspace: WorkspaceRecord | undefined;\n readonly socketPath: string | undefined;\n /** Human label for the REPL intro line. */\n readonly label: string;\n dispose(): Promise<void>;\n}\n\n/**\n * Attach VG Code to vgd for one coding session. Always resolves (never throws).\n */\nexport async function startCodeRuntimeSession(options: RuntimeSessionOptions): Promise<CodeRuntimeSession> {\n const socketPath = options.socketPath;\n const isRunning = options.isRunning ?? ((sp?: string) => vgdIsRunning({ socketPath: sp }));\n const request = options.request ?? vgdRequest;\n const startServer = options.startServer ?? ((opts: { socketPath?: string }) => startVgdServer(opts));\n\n try {\n if (await isRunning(socketPath)) {\n return await attachExisting(options.root, socketPath, request);\n }\n return await startOwned(options.root, socketPath, startServer, request);\n } catch {\n return noneSession();\n }\n}\n\nasync function attachExisting(\n root: string,\n socketPath: string | undefined,\n request: typeof vgdRequest,\n): Promise<CodeRuntimeSession> {\n const clientOpts = { socketPath };\n const reg = await request({ op: 'register', root }, clientOpts);\n if (!reg.ok || !('workspace' in reg)) return noneSession();\n const status = await request({ op: 'status' }, clientOpts).catch(() => null);\n const pid = status && status.ok && 'pid' in status ? status.pid : undefined;\n let disposed = false;\n return {\n kind: 'attached',\n pid,\n workspace: reg.workspace,\n socketPath: status && status.ok && 'socketPath' in status ? status.socketPath : socketPath,\n label: pid != null ? `vgd ${pid}` : 'vgd',\n async dispose() {\n if (disposed) return;\n disposed = true;\n try {\n await request({ op: 'unregister', root }, clientOpts);\n } catch {\n /* best-effort */\n }\n },\n };\n}\n\nasync function startOwned(\n root: string,\n socketPath: string | undefined,\n startServer: (opts: { socketPath?: string }) => Promise<VgdServer>,\n request: typeof vgdRequest,\n): Promise<CodeRuntimeSession> {\n const server = await startServer({ socketPath });\n const clientOpts = { socketPath: server.socketPath };\n let workspace: WorkspaceRecord | undefined;\n try {\n const reg = await request({ op: 'register', root }, clientOpts);\n if (reg.ok && 'workspace' in reg) workspace = reg.workspace;\n } catch {\n /* registry optional for an empty session */\n }\n let disposed = false;\n return {\n kind: 'owned',\n pid: process.pid,\n workspace,\n socketPath: server.socketPath,\n label: `vgd (session)`,\n async dispose() {\n if (disposed) return;\n disposed = true;\n try {\n await server.close();\n } catch {\n /* best-effort */\n }\n },\n };\n}\n\nfunction noneSession(): CodeRuntimeSession {\n return {\n kind: 'none',\n pid: undefined,\n workspace: undefined,\n socketPath: undefined,\n label: '',\n async dispose() {\n /* no-op */\n },\n };\n}\n"]}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { refreshIfStale } from './chunk-
|
|
2
|
-
import { sanitizeClient, recordSaving, SAVINGS_TOOLS, PER_FILE_TOKENS } from './chunk-
|
|
3
|
-
import { listedToolNames, budgetSuffix, TOOLS, renderToolResult, warmEmbedderInBackground, countTokens } from './chunk-
|
|
4
|
-
import { loadGraphPreferIndex } from './chunk-
|
|
5
|
-
import { mapFileStat, renderHtml, renderReport } from './chunk-
|
|
6
|
-
import { VERSION } from './chunk-
|
|
7
|
-
import { parseGraph, slimGraphForExport, serializeGraph } from './chunk-RBMKBYGV.js';
|
|
1
|
+
import { refreshIfStale } from './chunk-A4CGGQJ7.js';
|
|
2
|
+
import { sanitizeClient, recordSaving, SAVINGS_TOOLS, PER_FILE_TOKENS } from './chunk-CM6OYYBW.js';
|
|
3
|
+
import { listedToolNames, budgetSuffix, TOOLS, renderToolResult, warmEmbedderInBackground, countTokens } from './chunk-FJ2ARY3S.js';
|
|
4
|
+
import { loadGraphPreferIndex } from './chunk-ZZNNXZYB.js';
|
|
5
|
+
import { mapFileStat, parseGraph, slimGraphForExport, renderHtml, renderReport, serializeGraph } from './chunk-K5GPEWPI.js';
|
|
6
|
+
import { VERSION } from './chunk-B2Y45PCA.js';
|
|
8
7
|
import * as fs from 'fs';
|
|
9
8
|
import * as path from 'path';
|
|
10
9
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
@@ -531,5 +530,5 @@ function spdx(ctx) {
|
|
|
531
530
|
}
|
|
532
531
|
|
|
533
532
|
export { GraphSource, createServer, exportGraph, formatForExt, isRelevantChange, serveStdio };
|
|
534
|
-
//# sourceMappingURL=chunk-
|
|
535
|
-
//# sourceMappingURL=chunk-
|
|
533
|
+
//# sourceMappingURL=chunk-WGIX4S5A.js.map
|
|
534
|
+
//# sourceMappingURL=chunk-WGIX4S5A.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/engine/watch-filter.ts","../src/mcp/server.ts","../src/engine/export.ts"],"names":["path2"],"mappings":";;;;;;;;;;;;AASO,IAAM,gBAAA,uBAAuB,GAAA,CAAI;AAAA,EACtC,MAAA;AAAA,EACA,cAAA;AAAA,EACA,WAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA;AAAA,EACA,UAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,aAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAC,CAAA;AAGM,SAAS,iBAAiB,QAAA,EAA2B;AAC1D,EAAA,IAAI,QAAA,CAAS,KAAA,CAAW,IAAA,CAAA,GAAG,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,KAAM,gBAAA,CAAiB,GAAA,CAAI,CAAC,CAAC,CAAA,EAAG,OAAO,KAAA;AAC1E,EAAA,IAAI,QAAA,CAAS,QAAA,CAAS,CAAA,EAAQ,IAAA,CAAA,GAAG,CAAA,SAAA,EAAiB,IAAA,CAAA,GAAG,CAAA,CAAE,CAAA,IAAK,QAAA,CAAS,UAAA,CAAW,WAAW,CAAA,EAAG,OAAO,KAAA;AACrG,EAAA,OAAO,IAAA;AACT;;;ACUA,IAAM,iBAAA,GAAoB,GAAA;AAE1B,IAAM,qBAAA,GAAwB,GAAA;AAE9B,IAAM,iBAAA,GAAoB,EAAA;AAUnB,IAAM,iBAAA,GAAoB,GAAA;AAEjC,IAAM,mBAAA,GAAsB,GAAA;AAE5B,IAAM,iBAAA,GAAoB,GAAA;AA2DnB,IAAM,cAAN,MAAkB;AAAA,EAsBvB,YACW,SAAA,EACQ,OAAA,GAAU,KAAA,EAEV,MAAA,GAA4B,EAAC,EAC9C;AAJS,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AACQ,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAEA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAIjB,IAAA,IAAA,CAAK,OAAO,MAAA,CAAO,IAAA,IAAaA,IAAA,CAAA,OAAA,CAAaA,IAAA,CAAA,OAAA,CAAQ,SAAS,CAAC,CAAA;AAC/D,IAAA,IAAA,CAAK,WAAA,GAAc,OAAO,WAAA,IAAe,cAAA;AAAA,EAC3C;AAAA,EATW,SAAA;AAAA,EACQ,OAAA;AAAA,EAEA,MAAA;AAAA,EAzBX,aAAA,GAAgB,EAAA;AAAA,EAChB,MAAA,GAAyB,IAAA;AAAA;AAAA,EAExB,IAAA;AAAA,EACD,WAAA,GAAc,CAAA;AAAA,EACd,WAAA,GAAc,CAAA;AAAA,EACd,QAAA,GAAiC,IAAA;AAAA;AAAA,EAEjC,eAAA,GAAkB,iBAAA;AAAA,EACT,WAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,cAAA,uBAAqB,GAAA,EAAoB;AAAA,EAClD,OAAA,GAA+B,IAAA;AAAA,EAC/B,UAAA,GAAmD,IAAA;AAAA;AAAA,EAe3D,MAAM,GAAA,GAAwB;AAC5B,IAAA,IAAI,IAAA,CAAK,OAAA,EAAS,MAAM,IAAA,CAAK,YAAA,EAAa;AAG1C,IAAA,MAAM,IAAA,GAAO,WAAA,CAAY,IAAA,CAAK,SAAS,CAAA;AACvC,IAAA,IAAI,KAAK,OAAA,KAAY,IAAA,CAAK,aAAA,IAAiB,CAAC,KAAK,MAAA,EAAQ;AAEvD,MAAA,MAAM,SAAA,GAAY,oBAAA,CAAqB,IAAA,CAAK,IAAA,EAAM,KAAK,SAAS,CAAA;AAChE,MAAA,IAAA,CAAK,MAAA,GAAS,YACV,SAAA,CAAU,KAAA,GACV,WAAc,EAAA,CAAA,YAAA,CAAa,IAAA,CAAK,SAAA,EAAW,MAAM,CAAC,CAAA;AACtD,MAAA,IAAA,CAAK,gBAAgB,IAAA,CAAK,OAAA;AAAA,IAC5B;AACA,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,YAAA,GAA8B;AAC1C,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,IAAI,CAAC,KAAK,QAAA,EAAU;AAClB,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,MAAA,CAAO,eAAA,IAAmB,IAAA,CAAK,eAAA;AACrD,MAAA,IAAI,MAAM,IAAA,CAAK,WAAA,IAAe,GAAA,GAAM,IAAA,CAAK,cAAc,QAAA,EAAU;AACjE,MAAA,IAAA,CAAK,WAAA,GAAc,GAAA;AACnB,MAAA,MAAM,SAAA,GAAY,GAAA;AAClB,MAAA,IAAA,CAAK,QAAA,GAAW,IAAA,CAAK,WAAA,CAAY,IAAA,CAAK,IAAA,EAAM,EAAE,SAAA,EAAW,IAAA,CAAK,SAAA,EAAW,CAAA,CACtE,IAAA,CAAK,CAAC,CAAA,KAAM;AACX,QAAA,IAAI,EAAE,MAAA,KAAW,OAAA,OAAc,WAAA,GAAc,IAAA,CAAK,KAAI,GAAI,mBAAA;AAK1D,QAAA,IAAI,CAAA,CAAE,MAAA,KAAW,OAAA,IAAW,CAAA,CAAE,WAAW,WAAA,EAAa;AACpD,UAAA,KAAA,MAAW,CAAC,IAAA,EAAM,MAAM,CAAA,IAAK,KAAK,cAAA,EAAgB;AAChD,YAAA,IAAI,MAAA,IAAU,SAAA,EAAW,IAAA,CAAK,cAAA,CAAe,OAAO,IAAI,CAAA;AAAA,UAC1D;AAAA,QACF;AAMA,QAAA,MAAM,OACJ,CAAA,CAAE,MAAA,KAAW,eAAe,OAAO,CAAA,CAAE,OAAO,QAAA,GAAW,IAAA,CAAK,IAAI,CAAA,CAAE,EAAA,EAAI,KAAK,GAAA,EAAI,GAAI,GAAG,CAAA,GAAI,IAAA,CAAK,KAAI,GAAI,GAAA;AACzG,QAAA,IAAA,CAAK,kBAAkB,IAAA,CAAK,GAAA;AAAA,UAC1B,qBAAA;AAAA,UACA,IAAA,CAAK,GAAA,CAAI,iBAAA,EAAmB,IAAA,GAAO,iBAAiB;AAAA,SACtD;AAAA,MACF,CAAC,CAAA,CACA,KAAA,CAAM,MAAM;AACX,QAAA,IAAA,CAAK,WAAA,GAAc,IAAA,CAAK,GAAA,EAAI,GAAI,mBAAA;AAAA,MAClC,CAAC,CAAA,CACA,OAAA,CAAQ,MAAM;AACb,QAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAAA,MAClB,CAAC,CAAA;AAAA,IACL;AACA,IAAA,MAAM,OAAA,CAAQ,IAAA,CAAK,CAAC,IAAA,CAAK,QAAA,EAAU,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,eAAA,IAAmB,iBAAiB,CAAC,CAAC,CAAA;AAAA,EAC7F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,kBAAkB,QAAA,EAAwB;AACxC,IAAA,IAAA,CAAK,cAAA,CAAe,GAAA,CAAI,QAAA,EAAU,IAAA,CAAK,KAAK,CAAA;AAC5C,IAAA,IAAA,CAAK,WAAA,GAAc,CAAA;AACnB,IAAA,IAAA,CAAK,WAAA,GAAc,CAAA;AACnB,IAAA,IAAI,CAAC,KAAK,OAAA,EAAS;AACnB,IAAA,IAAI,IAAA,CAAK,UAAA,EAAY,YAAA,CAAa,IAAA,CAAK,UAAU,CAAA;AACjD,IAAA,IAAA,CAAK,UAAA,GAAa,WAAW,MAAM;AACjC,MAAA,IAAA,CAAK,UAAA,GAAa,IAAA;AAClB,MAAA,KAAK,KAAK,YAAA,EAAa;AAAA,IACzB,GAAG,iBAAiB,CAAA;AACpB,IAAA,IAAA,CAAK,WAAW,KAAA,IAAQ;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,aAAA,GAAyB;AACvB,IAAA,IAAI,IAAA,CAAK,SAAS,OAAO,IAAA;AACzB,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,OAAA,GAAa,EAAA,CAAA,KAAA,CAAM,IAAA,CAAK,IAAA,EAAM,EAAE,WAAW,IAAA,EAAK,EAAG,CAAC,MAAA,EAAQ,QAAA,KAAa;AAC5E,QAAA,IAAI,CAAC,QAAA,EAAU;AACf,QAAA,IAAI,CAAC,gBAAA,CAAiB,QAAQ,CAAA,EAAG;AACjC,QAAA,IAAA,CAAK,kBAAkB,QAAQ,CAAA;AAAA,MACjC,CAAC,CAAA;AACD,MAAA,IAAA,CAAK,QAAQ,KAAA,IAAQ;AACrB,MAAA,OAAO,IAAA;AAAA,IACT,CAAA,CAAA,MAAQ;AACN,MAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AAAA,EAEA,YAAA,GAAqB;AACnB,IAAA,IAAA,CAAK,SAAS,KAAA,EAAM;AACpB,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AACf,IAAA,IAAI,IAAA,CAAK,UAAA,EAAY,YAAA,CAAa,IAAA,CAAK,UAAU,CAAA;AACjD,IAAA,IAAA,CAAK,UAAA,GAAa,IAAA;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAA,GAA+B;AAC7B,IAAA,MAAM,CAAA,GAAI,KAAK,cAAA,CAAe,IAAA;AAC9B,IAAA,IAAI,CAAA,KAAM,GAAG,OAAO,IAAA;AACpB,IAAA,MAAM,KAAA,GAAQ,CAAC,GAAG,IAAA,CAAK,cAAA,CAAe,IAAA,EAAM,CAAA,CAAE,IAAA,EAAK,CAAE,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA;AAC/D,IAAA,MAAM,IAAA,GAAO,IAAI,KAAA,CAAM,MAAA,GAAS,MAAM,CAAA,GAAI,KAAA,CAAM,MAAM,CAAA,KAAA,CAAA,GAAU,EAAA;AAChE,IAAA,OAAO,CAAA,eAAA,EAAkB,CAAC,CAAA,yCAAA,EAA4C,KAAA,CAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAA,gEAAA,CAAA;AAAA,EAC/F;AACF;AAEO,SAAS,YAAA,CAAa,MAAA,EAAqB,IAAA,GAAqB,EAAC,EAAW;AACjF,EAAA,MAAM,EAAE,OAAA,GAAU,KAAA,EAAO,UAAA,GAAa,KAAA,EAAO,QAAQ,KAAA,EAAO,KAAA,GAAQ,KAAA,EAAO,KAAA,EAAM,GAAI,IAAA;AAGrF,EAAA,MAAM,SAAS,OAAA,IAAW,UAAA;AAE1B,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,IAAQ,MAAA,CAAO,IAAA;AAMjC,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,MAAM,SAAS,IAAI,MAAA;AAAA,IACjB,EAAE,IAAA,EAAM,IAAA,EAAM,OAAA,EAAS,OAAA,EAAQ;AAAA,IAC/B;AAAA,MACE,YAAA,EAAc,EAAE,KAAA,EAAO,EAAC,EAAE;AAAA;AAAA;AAAA;AAAA,MAI1B,YAAA,EACE;AAAA;AAoBJ,GACF;AAEA,EAAA,MAAA,CAAO,iBAAA,CAAkB,wBAAwB,YAAY;AAC3D,IAAA,MAAM,SAAS,IAAI,GAAA,CAAI,eAAA,CAAgB,IAAA,CAAK,WAAW,CAAC,CAAA;AAIxD,IAAA,IAAI,MAAA,GAAS,EAAA;AACb,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,GAAQ,MAAM,MAAA,CAAO,GAAA,EAAI;AAC/B,MAAA,MAAA,GAAS,YAAA,CAAa,IAAI,GAAA,CAAI,KAAA,CAAM,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAC,CAAA,CAAE,IAAI,CAAA;AAAA,IACpE,CAAA,CAAA,MAAQ;AAAA,IAER;AACA,IAAA,OAAO;AAAA,MACL,KAAA,EAAO,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,KAAM,MAAA,CAAO,GAAA,CAAI,CAAA,CAAE,IAAI,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,QACzD,MAAM,CAAA,CAAE,IAAA;AAAA,QACR,WAAA,EAAa,CAAA,CAAE,IAAA,KAAS,QAAA,IAAY,MAAA,GAAS,CAAA,EAAG,CAAA,CAAE,WAAW,CAAA,EAAG,MAAM,CAAA,CAAA,GAAK,CAAA,CAAE,WAAA;AAAA,QAC7E,aAAa,CAAA,CAAE,WAAA;AAAA,QACf,WAAA,EAAa,EAAE,YAAA,EAAc,IAAA,EAAM,eAAe,KAAA;AAAM,OAC1D,CAAE;AAAA,KACJ;AAAA,EACF,CAAC,CAAA;AAED,EAAA,MAAA,CAAO,iBAAA,CAAkB,qBAAA,EAAuB,OAAO,OAAA,KAAY;AACjE,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,IAAA,KAAS,OAAA,CAAQ,MAAA,CAAO,IAAI,CAAA;AAC7D,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,OAAO,WAAA,CAAY,CAAA,cAAA,EAAiB,OAAA,CAAQ,MAAA,CAAO,IAAI,CAAA,CAAA,CAAG,CAAA;AAAA,IAC5D;AACA,IAAA,IAAI,KAAA;AACJ,IAAA,IAAI;AACF,MAAA,KAAA,GAAQ,MAAM,OAAO,GAAA,EAAI;AAAA,IAC3B,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,WAAA;AAAA,QACL;AAAA,OACF;AAAA,IACF;AACA,IAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAC3B,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAQ,OAAA,CAAQ,MAAA,CAAO,SAAA,IAAa,EAAC;AAC3C,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,OAAA,CAAQ,OAAO,IAAA,EAAM,EAAE,IAAA,EAAM,KAAA,EAAO,KAAA,EAAO,IAAA,EAAM,SAAA,EAAW,MAAA,CAAO,WAAW,CAAA;AACxG,MAAA,MAAM,EAAA,GAAK,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAGxB,MAAA,KAAA,EAAO,MAAA,CAAO,EAAE,GAAG,WAAA,CAAY,KAAK,IAAA,EAAM,MAAM,CAAA,EAAG,MAAA,EAAQ,eAAe,YAAA,CAAa,MAAM,CAAC,CAAA,EAAG,IAAI,CAAA;AAKrG,MAAA,IAAI,MAAA,cAAoB,IAAA,EAAM,IAAA,CAAK,MAAM,MAAA,EAAQ,YAAA,CAAa,MAAM,CAAA,EAAG,EAAE,CAAA;AAEzE,MAAA,MAAM,QAAA,GAAW,iBAAiB,MAAM,CAAA;AAKxC,MAAA,MAAM,SAAA,GAAY,OAAO,aAAA,EAAc;AACvC,MAAA,IAAI,WAAW,QAAA,CAAS,OAAA,GAAU,CAAC,GAAI,SAAS,OAAA,IAAW,EAAC,EAAI,EAAE,MAAM,MAAA,EAAQ,IAAA,EAAM,CAAA,CAAA,EAAI,SAAS,KAAK,CAAA;AACxG,MAAA,OAAO,QAAA;AAAA,IACT,SAAS,GAAA,EAAK;AAGZ,MAAA,KAAA,EAAO,MAAA,CAAO;AAAA,QACZ,MAAM,IAAA,CAAK,IAAA;AAAA,QACX,MAAA,EAAQ,cAAA,CAAe,YAAA,CAAa,MAAM,CAAC,CAAA;AAAA,QAC3C,OAAA,EAAS,MAAA;AAAA,QACT,EAAA,EAAI,IAAA,CAAK,GAAA,EAAI,GAAI,SAAA;AAAA,QACjB,QAAA,EAAU,CAAA;AAAA,QACV,cAAA,EAAgB;AAAA,OACjB,CAAA;AACD,MAAA,OAAO,YAAY,CAAA,MAAA,EAAS,IAAA,CAAK,IAAI,CAAA,UAAA,EAAc,GAAA,CAAc,OAAO,CAAA,CAAE,CAAA;AAAA,IAC5E;AAAA,EACF,CAAC,CAAA;AAED,EAAA,OAAO,MAAA;AACT;AAEA,eAAsB,UAAA,CAAW,SAAA,EAAmB,IAAA,GAAqB,EAAC,EAAkB;AAC1F,EAAA,MAAM,MAAA,GAAS,IAAI,WAAA,CAAY,SAAA,EAAW,IAAA,CAAK,OAAA,KAAY,KAAA,EAAO,EAAE,IAAA,EAAM,IAAA,CAAK,IAAA,EAAM,CAAA;AACrF,EAAA,IAAI,KAAK,OAAA,KAAY,KAAA,IAAS,KAAK,KAAA,KAAU,KAAA,SAAc,aAAA,EAAc;AACzE,EAAA,MAAM,MAAA,GAAS,YAAA,CAAa,MAAA,EAAQ,IAAI,CAAA;AAIxC,EAAA,wBAAA,CAAyB,KAAK,KAAK,CAAA;AACnC,EAAA,MAAM,MAAA,CAAO,OAAA,CAAQ,IAAI,oBAAA,EAAsB,CAAA;AACjD;AAEA,SAAS,MAAM,EAAA,EAA2B;AACxC,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,KAAY;AAC9B,IAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,OAAA,EAAS,EAAE,CAAA;AACpC,IAAA,KAAA,CAAM,KAAA,IAAQ;AAAA,EAChB,CAAC,CAAA;AACH;AAcO,SAAS,WAAA,CAAY,IAAA,EAAc,IAAA,EAAc,MAAA,EAAiB,QAAiB,EAAA,EAAmB;AAC3G,EAAA,YAAA;AAAA,IACE,IAAA;AAAA,IACA,EAAE,GAAG,WAAA,CAAY,MAAM,MAAM,CAAA,EAAG,QAAQ,KAAA,EAAO,MAAA,EAAQ,eAAe,MAAM,CAAA,EAAG,GAAI,EAAA,KAAO,MAAA,GAAY,EAAE,EAAA,EAAG,GAAI,EAAC,EAAG;AAAA,IACnH,KAAK,GAAA;AAAI,GACX;AACF;AAOA,SAAS,WAAA,CAAY,MAAc,MAAA,EAA+F;AAChI,EAAA,MAAM,OAAA,GAAU,gBAAgB,MAAM,CAAA;AACtC,EAAA,IAAI,QAAA,GAAW,CAAA;AACf,EAAA,IAAI,cAAA,GAAiB,CAAA;AACrB,EAAA,IAAI,cAAc,GAAA,CAAI,IAAI,KAAK,MAAA,IAAU,OAAO,WAAW,QAAA,EAAU;AACnE,IAAA,QAAA,GAAW,WAAA,CAAY,YAAA,CAAa,gBAAA,CAAiB,MAAM,CAAC,CAAC,CAAA;AAK7D,IAAA,cAAA,GAAiB,eAAA,CAAgB,MAAM,CAAA,CAAE,IAAA,GAAO,eAAA;AAAA,EAClD;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,OAAA,EAAS,QAAA,EAAU,cAAA,EAAe;AACnD;AAQA,SAAS,aAAa,MAAA,EAAoC;AACxD,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAQ,OAAsE,gBAAA,IAAmB;AACvG,IAAA,OAAO,OAAO,IAAA,EAAM,IAAA,KAAS,QAAA,GAAW,KAAK,IAAA,GAAO,KAAA,CAAA;AAAA,EACtD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAUA,SAAS,gBAAgB,MAAA,EAA0B;AACjD,EAAA,IAAI,KAAA,CAAM,QAAQ,MAAM,CAAA,SAAU,MAAA,CAAO,MAAA,KAAW,IAAI,MAAA,GAAS,UAAA;AACjE,EAAA,IAAI,CAAC,MAAA,IAAU,OAAO,MAAA,KAAW,UAAU,OAAO,MAAA;AAClD,EAAA,MAAM,CAAA,GAAI,MAAA;AACV,EAAA,IAAI,OAAO,CAAA,CAAE,KAAA,KAAU,QAAA,IAAY,CAAA,CAAE,OAAO,OAAO,MAAA;AACnD,EAAA,IAAI,CAAA,CAAE,SAAA,KAAc,KAAA,EAAO,OAAO,MAAA;AAClC,EAAA,IAAI,KAAA,CAAM,QAAQ,CAAA,CAAE,OAAO,KAAK,CAAA,CAAE,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG,OAAO,MAAA;AAC/D,EAAA,OAAO,SAAA,CAAU,CAAC,CAAA,GAAI,SAAA,GAAY,UAAA;AACpC;AAGA,SAAS,UAAU,CAAA,EAAqC;AACtD,EAAA,IAAI,CAAA,CAAE,aAAA,KAAkB,IAAA,EAAM,OAAO,IAAA;AACrC,EAAA,IAAI,EAAE,UAAA,IAAc,OAAO,CAAA,CAAE,UAAA,KAAe,UAAU,OAAO,IAAA;AAG7D,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,CAAC,CAAA,EAAG;AAC5C,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,GAAA,CAAI,QAAA,CAAS,OAAO,CAAA,EAAG;AACzD,IAAA,MAAM,OAAO,GAAA,CAAI,KAAA,CAAM,CAAA,EAAG,CAAC,QAAQ,MAAM,CAAA;AACzC,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,IAAI,CAAC,CAAA,GAAK,CAAA,CAAE,IAAI,CAAA,CAAgB,MAAA,GAAS,CAAA;AACvE,IAAA,IAAI,KAAA,GAAQ,OAAO,OAAO,IAAA;AAAA,EAC5B;AACA,EAAA,OAAO,KAAA;AACT;AAGA,SAAS,aAAa,QAAA,EAAkC;AACtD,EAAA,MAAM,KAAA,GAAQ,SAAS,OAAA,EAAS,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,MAAM,CAAA;AAC7D,EAAA,OAAO,KAAA,IAAS,UAAU,KAAA,IAAS,OAAO,MAAM,IAAA,KAAS,QAAA,GAAW,MAAM,IAAA,GAAO,EAAA;AACnF;AAGA,SAAS,gBAAgB,MAAA,EAA8B;AACrD,EAAA,MAAM,CAAA,GAAI,MAAA;AACV,EAAA,MAAM,KAAA,uBAAY,GAAA,EAAY;AAC9B,EAAA,IAAI,OAAO,EAAE,IAAA,KAAS,QAAA,IAAY,EAAE,IAAA,EAAM,KAAA,CAAM,GAAA,CAAI,CAAA,CAAE,IAAI,CAAA;AAC1D,EAAA,KAAA,MAAW,CAAA,IAAK,OAAA,CAAQ,CAAA,CAAE,OAAO,CAAA,EAAG;AAClC,IAAA,MAAM,IAAK,CAAA,CAAyB,IAAA;AACpC,IAAA,IAAI,OAAO,CAAA,KAAM,QAAA,IAAY,CAAA,EAAG,KAAA,CAAM,IAAI,CAAC,CAAA;AAAA,EAC7C;AAGA,EAAA,KAAA,MAAW,IAAA,IAAQ,CAAC,GAAG,OAAA,CAAQ,CAAA,CAAE,KAAK,CAAA,EAAG,GAAG,OAAA,CAAQ,CAAA,CAAE,QAAQ,CAAC,CAAA,EAAG;AAChE,IAAA,IAAI,OAAO,SAAS,QAAA,EAAU;AAC9B,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,OAAA,CAAQ,GAAG,CAAA;AAC1B,IAAA,IAAI,CAAA,GAAI,GAAG,KAAA,CAAM,GAAA,CAAI,KAAK,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA;AAAA,EACvC;AACA,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,QAAQ,CAAA,EAAuB;AACtC,EAAA,OAAO,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA,GAAI,IAAI,EAAC;AACjC;AAEA,SAAS,YAAY,OAAA,EAAiB;AACpC,EAAA,OAAO,EAAE,OAAA,EAAS,CAAC,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,OAAA,EAAS,CAAA,EAAG,OAAA,EAAS,IAAA,EAAK;AACrE;;;AC3gBO,IAAM,kBAAA,GAAqB,GAAA;AAqB3B,SAAS,aAAa,GAAA,EAAkC;AAC7D,EAAA,QAAQ,GAAA,CAAI,aAAY;AAAG,IACzB,KAAK,OAAA;AACH,MAAA,OAAO,MAAA;AAAA,IACT,KAAK,SAAA;AACH,MAAA,OAAO,QAAA;AAAA,IACT,KAAK,UAAA;AACH,MAAA,OAAO,SAAA;AAAA,IACT,KAAK,MAAA;AAAA,IACL,KAAK,KAAA;AACH,MAAA,OAAO,KAAA;AAAA,IACT,KAAK,SAAA;AACH,MAAA,OAAO,QAAA;AAAA,IACT,KAAK,MAAA;AACH,MAAA,OAAO,KAAA;AAAA,IACT,KAAK,KAAA;AACH,MAAA,OAAO,IAAA;AAAA,IACT,KAAK,OAAA;AACH,MAAA,OAAO,MAAA;AAAA,IACT;AACE,MAAA,OAAO,IAAA;AAAA;AAEb;AAaO,SAAS,WAAA,CAAY,QAAsB,GAAA,EAA4B;AAC5E,EAAA,MAAM,QAAQ,GAAA,CAAI,IAAA,GAAO,mBAAmB,GAAA,CAAI,KAAK,IAAI,GAAA,CAAI,KAAA;AAC7D,EAAA,MAAM,OAAA,GACJ,GAAA,CAAI,OAAA,KAAY,IAAA,IACf,GAAA,CAAI,OAAA,KAAY,KAAA,IAAS,MAAA,KAAW,MAAA,IAAU,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,KAAA,GAAQ,kBAAA;AAE3E,EAAA,QAAQ,MAAA;AAAQ,IACd,KAAK,MAAA;AACH,MAAA,OAAO,cAAA,CAAe,KAAA,EAAO,EAAE,OAAA,EAAS,CAAA;AAAA,IAC1C,KAAK,IAAA;AACH,MAAA,OAAO,aAAa,KAAK,CAAA;AAAA,IAC3B,KAAK,MAAA;AACH,MAAA,OAAO,WAAW,KAAK,CAAA;AAAA,IACzB,KAAK,QAAA;AACH,MAAA,OAAO,OAAO,KAAK,CAAA;AAAA,IACrB,KAAK,SAAA;AACH,MAAA,OAAO,QAAQ,KAAK,CAAA;AAAA,IACtB,KAAK,KAAA;AACH,MAAA,OAAO,IAAI,KAAK,CAAA;AAAA,IAClB,KAAK,QAAA;AACH,MAAA,OAAO,OAAO,KAAK,CAAA;AAAA,IACrB,KAAK,KAAA;AACH,MAAA,OAAO,GAAA,CAAI,EAAE,GAAG,GAAA,EAAK,OAAO,CAAA;AAAA,IAC9B,KAAK,WAAA;AACH,MAAA,OAAO,SAAA,CAAU,EAAE,GAAG,GAAA,EAAK,OAAO,CAAA;AAAA,IACpC,KAAK,MAAA;AACH,MAAA,OAAO,IAAA,CAAK,EAAE,GAAG,GAAA,EAAK,OAAO,CAAA;AAAA;AAEnC;AAEA,SAAS,OAAO,KAAA,EAAwB;AAEtC,EAAA,MAAM,IAAA,GAAO,MAAM,KAAA,IAAS,KAAA,CAAM,MAAM,MAAA,GAAS,KAAA,CAAM,QAAQ,KAAA,CAAM,KAAA;AACrE,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAM,IAAA,CAAK,SAAA,CAAU,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA,GAAI,IAAA;AACzD;AAEA,SAAS,IAAI,CAAA,EAAmB;AAC9B,EAAA,OAAO,CAAA,CAAE,OAAA,CAAQ,IAAA,EAAM,OAAO,EAAE,OAAA,CAAQ,IAAA,EAAM,MAAM,CAAA,CAAE,QAAQ,IAAA,EAAM,MAAM,CAAA,CAAE,OAAA,CAAQ,MAAM,QAAQ,CAAA;AACpG;AAEA,SAAS,QAAQ,KAAA,EAAwB;AACvC,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,CAAM,KAAK,wCAAwC,CAAA;AACnD,EAAA,KAAA,CAAM,KAAK,yDAAyD,CAAA;AACpE,EAAA,KAAA,CAAM,KAAK,mEAAmE,CAAA;AAC9E,EAAA,KAAA,CAAM,KAAK,mEAAmE,CAAA;AAC9E,EAAA,KAAA,CAAM,KAAK,mEAAmE,CAAA;AAC9E,EAAA,KAAA,CAAM,KAAK,oEAAoE,CAAA;AAC/E,EAAA,KAAA,CAAM,KAAK,kCAAkC,CAAA;AAC7C,EAAA,KAAA,MAAW,CAAA,IAAK,MAAM,KAAA,EAAO;AAC3B,IAAA,KAAA,CAAM,IAAA,CAAK,iBAAiB,GAAA,CAAI,CAAA,CAAE,EAAE,CAAC,CAAA,mBAAA,EAAsB,IAAI,CAAA,CAAE,aAAa,CAAC,CAAA,wBAAA,EAA2B,GAAA,CAAI,EAAE,IAAI,CAAC,2BAA2B,GAAA,CAAI,CAAA,CAAE,IAAI,CAAC,CAAA,cAAA,CAAgB,CAAA;AAAA,EAC7K;AACA,EAAA,KAAA,MAAW,CAAA,IAAK,MAAM,KAAA,EAAO;AAC3B,IAAA,KAAA,CAAM,KAAK,CAAA,kBAAA,EAAqB,GAAA,CAAI,CAAA,CAAE,GAAG,CAAC,CAAA,UAAA,EAAa,GAAA,CAAI,CAAA,CAAE,GAAG,CAAC,CAAA,oBAAA,EAAuB,GAAA,CAAI,CAAA,CAAE,IAAI,CAAC,CAAA,cAAA,CAAgB,CAAA;AAAA,EACrH;AACA,EAAA,KAAA,CAAM,KAAK,YAAY,CAAA;AACvB,EAAA,KAAA,CAAM,KAAK,YAAY,CAAA;AACvB,EAAA,OAAO,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA,GAAI,IAAA;AAC5B;AAEA,SAAS,IAAI,KAAA,EAAwB;AACnC,EAAA,MAAM,KAAA,GAAkB,CAAC,cAAc,CAAA;AACvC,EAAA,KAAA,MAAW,CAAA,IAAK,KAAA,CAAM,KAAA,EAAO,KAAA,CAAM,IAAA,CAAK,CAAA,GAAA,EAAM,CAAA,CAAE,EAAE,CAAA,UAAA,EAAa,MAAA,CAAO,CAAA,CAAE,aAAa,CAAC,CAAA,GAAA,CAAK,CAAA;AAC3F,EAAA,KAAA,MAAW,CAAA,IAAK,KAAA,CAAM,KAAA,EAAO,KAAA,CAAM,KAAK,CAAA,GAAA,EAAM,CAAA,CAAE,GAAG,CAAA,MAAA,EAAS,CAAA,CAAE,GAAG,CAAA,UAAA,EAAa,CAAA,CAAE,IAAI,CAAA,GAAA,CAAK,CAAA;AACzF,EAAA,KAAA,CAAM,KAAK,GAAG,CAAA;AACd,EAAA,OAAO,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA,GAAI,IAAA;AAC5B;AACA,SAAS,OAAO,CAAA,EAAmB;AACjC,EAAA,OAAO,CAAA,CAAE,OAAA,CAAQ,IAAA,EAAM,KAAK,CAAA;AAC9B;AAEA,SAAS,OAAO,KAAA,EAAwB;AACtC,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,MAAW,CAAA,IAAK,MAAM,KAAA,EAAO;AAC3B,IAAA,KAAA,CAAM,IAAA;AAAA,MACJ,cAAc,WAAA,CAAY,CAAA,CAAE,IAAI,CAAC,CAAA,OAAA,EAAU,EAAE,CAAA,CAAE,EAAE,CAAC,CAAA,OAAA,EAAU,CAAA,CAAE,EAAE,aAAa,CAAC,UAAU,CAAA,CAAE,CAAA,CAAE,IAAI,CAAC,CAAA,GAAA;AAAA,KACnG;AAAA,EACF;AACA,EAAA,KAAA,MAAW,CAAA,IAAK,MAAM,KAAA,EAAO;AAC3B,IAAA,KAAA,CAAM,IAAA;AAAA,MACJ,CAAA,aAAA,EAAgB,CAAA,CAAE,CAAA,CAAE,GAAG,CAAC,CAAA,UAAA,EAAa,CAAA,CAAE,CAAA,CAAE,GAAG,CAAC,CAAA,kBAAA,EAAqB,WAAA,CAAY,CAAA,CAAE,IAAI,CAAC,CAAA,SAAA;AAAA,KACvF;AAAA,EACF;AACA,EAAA,OAAO,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA,GAAI,IAAA;AAC5B;AACA,SAAS,YAAY,CAAA,EAAmB;AACtC,EAAA,OAAO,CAAA,CAAE,OAAA,CAAQ,gBAAA,EAAkB,GAAG,CAAA;AACxC;AACA,SAAS,EAAE,CAAA,EAAmB;AAC5B,EAAA,OAAO,IAAA,CAAK,UAAU,CAAC,CAAA;AACzB;AAaA,SAAS,IAAI,GAAA,EAA4B;AACvC,EAAA,MAAM,QAAQ,GAAA,CAAI,KAAA;AAClB,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,KAAA,CAAM,KAAK,QAAQ,CAAA;AAGnB,EAAA,KAAA,CAAM,KAAK,qEAAqE,CAAA;AAChF,EAAA,MAAM,IAAA,GAAkC;AAAA,IACtC,CAAC,eAAA,EAAiB,KAAA,CAAM,aAAa,CAAA;AAAA,IACrC,CAAC,aAAA,EAAe,GAAA,CAAI,WAAW,CAAA;AAAA,IAC/B,CAAC,YAAA,EAAc,KAAA,CAAM,UAAA,CAAW,UAAU,CAAA;AAAA,IAC1C,CAAC,MAAA,EAAQ,KAAA,CAAM,UAAA,CAAW,IAAI,CAAA;AAAA,IAC9B,CAAC,aAAA,EAAe,KAAA,CAAM,UAAA,CAAW,OAAO,CAAA;AAAA,IACxC,CAAC,UAAA,EAAY,KAAA,CAAM,WAAW,QAAA,CAAS,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,IAChD,CAAC,aAAA,EAAe,KAAA,CAAM,UAAA,CAAW,SAAA,EAAW,eAAe,IAAI;AAAA,GACjE;AACA,EAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,CAAA,IAAK,MAAM,KAAA,CAAM,IAAA,CAAK,CAAA,yBAAA,EAA4B,MAAA,CAAO,CAAC,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,CAAC,CAAC,CAAA,EAAA,CAAI,CAAA;AAG7F,EAAA,KAAA,CAAM,IAAA;AAAA,IACJ;AAAA,GACF;AACA,EAAA,KAAA,MAAW,CAAA,IAAK,MAAM,KAAA,EAAO;AAC3B,IAAA,KAAA,CAAM,IAAA;AAAA,MACJ,6BAA6B,MAAA,CAAO,CAAA,CAAE,EAAE,CAAC,KAAK,MAAA,CAAO,CAAA,CAAE,IAAI,CAAC,KAAK,MAAA,CAAO,CAAA,CAAE,IAAI,CAAC,KAAK,MAAA,CAAO,CAAA,CAAE,aAAa,CAAC,KAAK,MAAA,CAAO,CAAA,CAAE,IAAI,CAAC,KAAK,MAAA,CAAO,CAAA,CAAE,IAAA,CAAK,KAAK,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,CAAA,CAAE,IAAA,CAAK,GAAG,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,CAAA,CAAE,IAAI,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,CAAA,CAAE,UAAU,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,CAAA,CAAE,SAAS,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,CAAA,CAAE,UAAU,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,CAAA,CAAE,IAAI,CAAC,CAAA,EAAA,EAAK,OAAA,CAAQ,CAAA,CAAE,KAAK,CAAC,CAAA,EAAA,EAAK,OAAA,CAAQ,CAAA,CAAE,MAAM,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,CAAA,CAAE,QAAQ,CAAC,CAAA,EAAA;AAAA,KAClW;AAAA,EACF;AAGA,EAAA,KAAA,CAAM,IAAA;AAAA,IACJ;AAAA,GACF;AACA,EAAA,KAAA,MAAW,CAAA,IAAK,MAAM,KAAA,EAAO;AAC3B,IAAA,KAAA,CAAM,IAAA;AAAA,MACJ,CAAA,0BAAA,EAA6B,OAAO,CAAA,CAAE,EAAE,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,EAAE,IAAI,CAAC,KAAK,MAAA,CAAO,CAAA,CAAE,GAAG,CAAC,CAAA,EAAA,EAAK,OAAO,CAAA,CAAE,GAAG,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,EAAE,UAAU,CAAC,KAAK,MAAA,CAAO,CAAA,CAAE,UAAU,CAAC,CAAA,EAAA,EAAK,OAAO,CAAA,CAAE,SAAS,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,EAAE,QAAQ,CAAC,KAAK,MAAA,CAAO,CAAA,CAAE,KAAK,CAAC,CAAA,EAAA;AAAA,KACvN;AAAA,EACF;AAGA,EAAA,KAAA,CAAM,KAAK,6HAA6H,CAAA;AACxI,EAAA,KAAA,CAAM,KAAK,0EAA0E,CAAA;AACrF,EAAA,KAAA,MAAW,CAAA,IAAK,MAAM,KAAA,EAAO;AAC3B,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,0BAAA,EAA6B,MAAA,CAAO,CAAA,CAAE,EAAE,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,CAAA,CAAE,KAAK,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,EAAE,IAAI,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,CAAA,CAAE,QAAQ,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,CAAA,CAAE,aAAa,CAAC,CAAA,EAAA,CAAI,CAAA;AAClJ,IAAA,KAAA,MAAW,CAAA,IAAK,CAAA,CAAE,OAAA,EAAS,KAAA,CAAM,KAAK,CAAA,iCAAA,EAAoC,MAAA,CAAO,CAAA,CAAE,EAAE,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,CAAC,CAAC,CAAA,EAAA,CAAI,CAAA;AAAA,EAC1G;AAGA,EAAA,IAAI,KAAA,CAAM,KAAA,IAAS,KAAA,CAAM,KAAA,CAAM,MAAA,EAAQ;AACrC,IAAA,KAAA,CAAM,KAAK,2HAA2H,CAAA;AACtI,IAAA,KAAA,CAAM,KAAK,wEAAwE,CAAA;AACnF,IAAA,KAAA,CAAM,KAAK,2GAA2G,CAAA;AACtH,IAAA,KAAA,MAAW,CAAA,IAAK,MAAM,KAAA,EAAO;AAC3B,MAAA,KAAA,CAAM,IAAA,CAAK,CAAA,0BAAA,EAA6B,MAAA,CAAO,CAAA,CAAE,EAAE,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,CAAA,CAAE,IAAI,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,IAAA,CAAK,SAAA,CAAU,CAAA,CAAE,SAAS,CAAC,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,CAAA,CAAE,SAAS,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,CAAA,CAAE,UAAU,CAAC,CAAA,EAAA,CAAI,CAAA;AACpK,MAAA,KAAA,MAAW,CAAA,IAAK,CAAA,CAAE,UAAA,EAAY,KAAA,CAAM,KAAK,CAAA,kCAAA,EAAqC,MAAA,CAAO,CAAA,CAAE,EAAE,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,CAAC,CAAC,CAAA,EAAA,CAAI,CAAA;AAC5G,MAAA,KAAA,MAAW,EAAA,IAAM,CAAA,CAAE,QAAA,EAAU,KAAA,CAAM,IAAA,CAAK,CAAA,kCAAA,EAAqC,MAAA,CAAO,CAAA,CAAE,EAAE,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,EAAA,CAAG,IAAI,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,EAAA,CAAG,IAAA,CAAK,KAAK,CAAC,CAAA,EAAA,EAAK,MAAA,CAAO,EAAA,CAAG,IAAA,CAAK,GAAG,CAAC,CAAA,EAAA,CAAI,CAAA;AAAA,IACrK;AAAA,EACF;AAEA,EAAA,KAAA,CAAM,KAAK,SAAS,CAAA;AACpB,EAAA,OAAO,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA,GAAI,IAAA;AAC5B;AAGA,SAAS,OAAO,CAAA,EAAsC;AACpD,EAAA,IAAI,CAAA,IAAK,MAAM,OAAO,MAAA;AACtB,EAAA,OAAO,CAAA,CAAA,EAAI,CAAA,CAAE,OAAA,CAAQ,IAAA,EAAM,IAAI,CAAC,CAAA,CAAA,CAAA;AAClC;AAEA,SAAS,OAAO,CAAA,EAAsC;AACpD,EAAA,OAAO,CAAA,IAAK,QAAQ,CAAC,MAAA,CAAO,SAAS,CAAC,CAAA,GAAI,MAAA,GAAS,MAAA,CAAO,CAAC,CAAA;AAC7D;AAEA,SAAS,QAAQ,CAAA,EAAuC;AACtD,EAAA,OAAO,CAAA,IAAK,IAAA,GAAO,MAAA,GAAS,CAAA,GAAI,GAAA,GAAM,GAAA;AACxC;AAEA,SAAS,UAAU,GAAA,EAA4B;AAI7C,EAAA,MAAM,aAAwB,EAAC;AAC/B,EAAA,KAAA,MAAW,CAAA,IAAK,GAAA,CAAI,IAAA,IAAQ,EAAC,EAAG;AAC9B,IAAA,UAAA,CAAW,IAAA,CAAK;AAAA,MACd,IAAA,EAAM,SAAA;AAAA,MACN,MAAM,CAAA,CAAE,IAAA;AAAA,MACR,OAAA,EAAS,CAAA,CAAE,SAAA,IAAa,CAAA,CAAE,QAAA;AAAA,MAC1B,IAAA,EAAM,CAAA,CAAE,SAAA,KAAc,KAAA,GAAQ,CAAA,QAAA,EAAW,CAAA,CAAE,IAAI,CAAA,CAAA,EAAI,CAAA,CAAE,SAAA,IAAa,EAAE,CAAA,CAAA,GAAK;AAAA,KAC1E,CAAA;AAAA,EACH;AACA,EAAA,KAAA,MAAW,CAAA,IAAK,GAAA,CAAI,MAAA,IAAU,EAAC,EAAG;AAChC,IAAA,UAAA,CAAW,KAAK,EAAE,IAAA,EAAM,wBAAA,EAA0B,IAAA,EAAM,EAAE,IAAA,EAAM,UAAA,EAAY,CAAC,EAAE,MAAM,YAAA,EAAc,KAAA,EAAO,EAAE,OAAA,EAAS,GAAG,CAAA;AAAA,EAC1H;AACA,EAAA,MAAM,GAAA,GAAM;AAAA,IACV,SAAA,EAAW,WAAA;AAAA,IACX,WAAA,EAAa,KAAA;AAAA,IACb,UAAU,EAAE,SAAA,EAAW,GAAA,CAAI,WAAA,EAAa,OAAO,CAAC,EAAE,IAAA,EAAM,IAAA,EAAM,SAAS,GAAA,CAAI,KAAA,CAAM,UAAA,CAAW,OAAA,EAAS,CAAA,EAAE;AAAA,IACvG;AAAA,GACF;AACA,EAAA,OAAO,IAAA,CAAK,SAAA,CAAU,GAAA,EAAK,IAAA,EAAM,CAAC,CAAA,GAAI,IAAA;AACxC;AAEA,SAAS,KAAK,GAAA,EAA4B;AACxC,EAAA,MAAM,YAAY,GAAA,CAAI,IAAA,IAAQ,EAAC,EAAG,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,IAC5C,MAAA,EAAQ,CAAA,gBAAA,EAAmB,WAAA,CAAY,CAAA,CAAE,IAAI,CAAC,CAAA,CAAA;AAAA,IAC9C,MAAM,CAAA,CAAE,IAAA;AAAA,IACR,WAAA,EAAa,CAAA,CAAE,SAAA,IAAa,CAAA,CAAE,QAAA;AAAA,IAC9B,gBAAA,EAAkB;AAAA,GACpB,CAAE,CAAA;AACF,EAAA,MAAM,GAAA,GAAM;AAAA,IACV,WAAA,EAAa,UAAA;AAAA,IACb,WAAA,EAAa,SAAA;AAAA,IACb,MAAA,EAAQ,kBAAA;AAAA,IACR,IAAA,EAAM,SAAA;AAAA,IACN,YAAA,EAAc,EAAE,OAAA,EAAS,GAAA,CAAI,WAAA,EAAa,QAAA,EAAU,CAAC,CAAA,SAAA,EAAY,GAAA,CAAI,KAAA,CAAM,UAAA,CAAW,OAAO,EAAE,CAAA,EAAE;AAAA,IACjG;AAAA,GACF;AACA,EAAA,OAAO,IAAA,CAAK,SAAA,CAAU,GAAA,EAAK,IAAA,EAAM,CAAC,CAAA,GAAI,IAAA;AACxC","file":"chunk-WGIX4S5A.js","sourcesContent":["import * as path from 'node:path';\n\n/**\n * Shared change-event filter for the two file watchers (`vg watch` and the\n * serve-loop watcher in mcp/server.ts): which filesystem events are real\n * source changes, and which are dependency/artifact/VCS noise that must never\n * trigger a rebuild — including vg's own artifacts, or every build would\n * re-trigger itself.\n */\nexport const WATCH_SKIP_NAMES = new Set([\n '.git',\n 'node_modules',\n '.vibgrate',\n 'dist',\n 'build',\n 'out',\n 'coverage',\n '.next',\n 'target',\n '__pycache__',\n '.venv',\n 'venv',\n]);\n\n/** True when a watch event's filename is a change worth rebuilding for. */\nexport function isRelevantChange(filename: string): boolean {\n if (filename.split(path.sep).some((p) => WATCH_SKIP_NAMES.has(p))) return false;\n if (filename.includes(`${path.sep}.vibgrate${path.sep}`) || filename.startsWith('.vibgrate')) return false;\n return true;\n}\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { parseGraph } from '../engine/serialize.js';\nimport { mapFileStat } from '../engine/snapshot.js';\nimport { loadGraphPreferIndex } from '../engine/index-db.js';\nimport { refreshIfStale } from '../engine/refresh.js';\nimport { TOOLS, budgetSuffix, listedToolNames, warmEmbedderInBackground, type ToolSurface } from './tools.js';\nimport { isRelevantChange } from '../engine/watch-filter.js';\nimport { renderToolResult } from './response.js';\nimport { recordSaving, sanitizeClient, PER_FILE_TOKENS, SAVINGS_TOOLS, type Outcome } from '../engine/savings.js';\nimport type { SessionStats } from './serve-stats.js';\nimport { countTokens } from '../engine/tokens.js';\nimport { VERSION } from '../version.js';\nimport type { VgGraph } from '../schema.js';\n\n/**\n * The local `vg serve` MCP server. Self-contained and offline. Freshness is\n * two-layered, with no filesystem watcher (freshness only matters at the\n * moment of a query, so we check on read instead of watching):\n *\n * 1. **Hot reload** — `graph.json` is re-read whenever its mtime changes, so a\n * rebuild from ANY source (a foreground `vg`, another serve process, CI)\n * is picked up on the next tool call.\n * 2. **Auto-refresh** (default on) — each tool call runs a debounced, stat-only\n * freshness probe against the last build's snapshot; if the working tree\n * drifted, an incremental rebuild runs in-process (cross-process locked,\n * single-flight). The call waits only a **micro-budget** so a warm probe can\n * land without stalling MCP tools — otherwise it answers from the current\n * map while the rebuild finishes for a later call (hot-reload picks it up).\n *\n * Every tool remains read-only and auto-approvable; the refresh only rewrites\n * vg's own artifacts under `.vibgrate/`, never user code.\n */\n\n/** Min gap between freshness probes — bounds stat-walk cost under bursty tool calls. */\nconst PROBE_INTERVAL_MS = 2000;\n/** Ceiling for the self-tuned probe interval on very large repos. */\nconst MAX_PROBE_INTERVAL_MS = 30_000;\n/** Probe/rebuild may consume at most ~1/PROBE_DUTY_FACTOR of serve wall-time (20 → ≤5%). */\nconst PROBE_DUTY_FACTOR = 20;\n/**\n * How long a tool call waits for an in-flight refresh before answering from\n * the current map. Kept deliberately small: MCP tool latency is sub-10ms on\n * warm maps, and a multi-second budget (the previous 5s ceiling matched\n * `git rev-parse`'s spawn timeout) turned every sequential tool call during a\n * large-repo rebuild into a multi-second stall — measured as TypeScript p50\n * ~5.2s on the release benchmark for the `vg-cli-public` corpus entry.\n * Warm probes still finish inside this window; heavy rebuilds never should.\n */\nexport const REFRESH_BUDGET_MS = 100;\n/** After a refresh failure (e.g. read-only checkout), don't retry for this long. */\nconst FAILURE_COOLDOWN_MS = 60_000;\n/** Settle time between a watcher event and the background refresh it triggers. */\nconst WATCH_DEBOUNCE_MS = 400;\n\nexport type RefreshImpl = typeof refreshIfStale;\n\nexport interface GraphSourceTuning {\n probeIntervalMs?: number;\n refreshBudgetMs?: number;\n /**\n * Workspace root for freshness probes. Prefer passing this explicitly —\n * deriving it from `graphPath` via `dirname` twice only works for the legacy\n * `root/.vibgrate/graph.json` layout, not the global branch-keyed store.\n */\n root?: string;\n /** Tests only: inject a slow/fake refresh to assert the micro-budget. */\n refreshImpl?: RefreshImpl;\n}\n\nexport interface ServeOptions {\n /** Record local, counts-only usage savings (opt-in). */\n savings?: boolean;\n /**\n * Periodically upload the counts-only ledger to Vibgrate (opt-in; off by\n * default). Implies recording. The upload itself is driven by the serve\n * command (see commands/serve.ts + engine/stats-share.ts); here it just also\n * turns recording on so there's something to send.\n */\n shareStats?: boolean;\n /** Air-gapped mode (no model downloads). */\n local?: boolean;\n /** Collapse repeat heavy relation lists within a session (opt-in). */\n dedup?: boolean;\n /** Auto-refresh the map when the working tree drifts (default true). */\n refresh?: boolean;\n /**\n * Event-driven refresh: recursive fs.watch on the workspace so a save\n * rebuilds in ~400 ms instead of waiting out the freshness poll (default\n * true when refresh is on; `--no-watch` opts out). Where recursive watch is\n * unavailable the poll silently remains the only mechanism.\n */\n watch?: boolean;\n /**\n * Workspace root (project directory). When set, freshness probes and tools\n * use this instead of inferring root from the graph path.\n */\n root?: string;\n /**\n * In-memory session stats behind the live `vg serve` status display. Always\n * safe to pass: nothing recorded here is persisted or uploaded — it dies with\n * the process (the opt-in ledger above is a separate concern).\n */\n stats?: SessionStats;\n /**\n * Listing surface (`--surface hot` / `--tools a,b`). Filters ONLY what\n * `tools/list` advertises; every tool stays callable so behaviour is\n * byte-identical across surfaces. See `listedToolNames` in ./tools.ts.\n */\n toolSurface?: ToolSurface;\n}\n\nexport class GraphSource {\n private cachedMtimeMs = -1;\n private cached: VgGraph | null = null;\n /** Project root used for freshness probes and rebuilds. */\n readonly root: string;\n private lastProbeAt = 0;\n private failedUntil = 0;\n private inflight: Promise<void> | null = null;\n /** Self-tuned: grows with measured probe/rebuild cost so huge repos aren't penalized. */\n private probeIntervalMs = PROBE_INTERVAL_MS;\n private readonly refreshImpl: RefreshImpl;\n /**\n * Files seen changing since the last COMMITTED refresh (watcher events,\n * filename → last-seen ms). Entries are cleared only after a refresh that\n * started at-or-after their last event completes with 'fresh'/'refreshed' —\n * a change landing mid-refresh stays pending, so the staleness signal can\n * be a false positive but never a false negative.\n */\n private readonly pendingChanges = new Map<string, number>();\n private watcher: fs.FSWatcher | null = null;\n private watchTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor(\n readonly graphPath: string,\n private readonly refresh = false,\n /** Timing / root overrides (production passes `root`; tests may pass more). */\n private readonly tuning: GraphSourceTuning = {},\n ) {\n // Prefer an explicit root. Fallback assumes legacy `root/.vibgrate/graph.json`\n // (dirname twice); wrong for the global store — callers should pass `root`.\n this.root = tuning.root ?? path.dirname(path.dirname(graphPath));\n this.refreshImpl = tuning.refreshImpl ?? refreshIfStale;\n }\n\n /** Current graph: auto-refreshed if the tree drifted, reloaded if the file changed. */\n async get(): Promise<VgGraph> {\n if (this.refresh) await this.maybeRefresh();\n // JSON when present, else the standalone snapshot (global-store mode);\n // throws if neither exists → surfaced as tool error.\n const stat = mapFileStat(this.graphPath);\n if (stat.mtimeMs !== this.cachedMtimeMs || !this.cached) {\n // Prefer SQLite reconstruct when corpusHash matches (scale past JSON parse).\n const preferred = loadGraphPreferIndex(this.root, this.graphPath);\n this.cached = preferred\n ? preferred.graph\n : parseGraph(fs.readFileSync(this.graphPath, 'utf8'));\n this.cachedMtimeMs = stat.mtimeMs;\n }\n return this.cached;\n }\n\n /**\n * Debounced, single-flight refresh. Never throws — a refresh problem must\n * degrade to \"answer from the current map\", not break the tool call.\n */\n private async maybeRefresh(): Promise<void> {\n const now = Date.now();\n if (!this.inflight) {\n const interval = this.tuning.probeIntervalMs ?? this.probeIntervalMs;\n if (now < this.failedUntil || now - this.lastProbeAt < interval) return;\n this.lastProbeAt = now;\n const startedAt = now;\n this.inflight = this.refreshImpl(this.root, { graphPath: this.graphPath })\n .then((r) => {\n if (r.status === 'error') this.failedUntil = Date.now() + FAILURE_COOLDOWN_MS;\n // A COMMITTED outcome (map verified fresh, or rebuilt) clears the\n // pending set — but only entries whose last event predates the\n // refresh start. 'locked'/'error'/'no-snapshot' clear nothing:\n // the map may still be behind those changes.\n if (r.status === 'fresh' || r.status === 'refreshed') {\n for (const [file, seenAt] of this.pendingChanges) {\n if (seenAt <= startedAt) this.pendingChanges.delete(file);\n }\n }\n // Self-tune off the full wall cost of *every* outcome — including a\n // multi-second incremental rebuild. Previously only probe-only\n // outcomes (fresh/no-snapshot/locked) backed off, so a 20s rebuild\n // of a large repo re-armed after the 2s floor and every sequential\n // tool call blocked on the refresh budget for the whole suite.\n const cost =\n r.status === 'refreshed' && typeof r.ms === 'number' ? Math.max(r.ms, Date.now() - now) : Date.now() - now;\n this.probeIntervalMs = Math.min(\n MAX_PROBE_INTERVAL_MS,\n Math.max(PROBE_INTERVAL_MS, cost * PROBE_DUTY_FACTOR),\n );\n })\n .catch(() => {\n this.failedUntil = Date.now() + FAILURE_COOLDOWN_MS;\n })\n .finally(() => {\n this.inflight = null;\n });\n }\n await Promise.race([this.inflight, sleep(this.tuning.refreshBudgetMs ?? REFRESH_BUDGET_MS)]);\n }\n\n /**\n * Record a source change (watcher event, or a test). Arms the next probe to\n * run immediately (bypassing the self-tuned interval — a real event is not a\n * poll) and schedules a debounced background refresh so the rebuild happens\n * BETWEEN tool calls instead of on the next call's 100 ms budget.\n */\n notePendingChange(filename: string): void {\n this.pendingChanges.set(filename, Date.now());\n this.lastProbeAt = 0;\n this.failedUntil = 0;\n if (!this.refresh) return;\n if (this.watchTimer) clearTimeout(this.watchTimer);\n this.watchTimer = setTimeout(() => {\n this.watchTimer = null;\n void this.maybeRefresh();\n }, WATCH_DEBOUNCE_MS);\n this.watchTimer.unref?.();\n }\n\n /**\n * Event-driven freshness (the serve-loop watcher): a recursive `fs.watch`\n * on the workspace feeds `notePendingChange`, so a save triggers a rebuild\n * in ~WATCH_DEBOUNCE_MS instead of waiting out the 2–30 s poll. The poll\n * stays armed as the fallback — on filesystems where recursive watch fails\n * (some containers/NFS) this returns false and behaviour is unchanged.\n */\n startWatching(): boolean {\n if (this.watcher) return true;\n try {\n this.watcher = fs.watch(this.root, { recursive: true }, (_event, filename) => {\n if (!filename) return;\n if (!isRelevantChange(filename)) return;\n this.notePendingChange(filename);\n });\n this.watcher.unref?.();\n return true;\n } catch {\n this.watcher = null;\n return false;\n }\n }\n\n stopWatching(): void {\n this.watcher?.close();\n this.watcher = null;\n if (this.watchTimer) clearTimeout(this.watchTimer);\n this.watchTimer = null;\n }\n\n /**\n * In-band staleness signal for tool responses: what has changed since the\n * last committed refresh. Null when the map is current (the common case —\n * responses carry zero overhead then).\n */\n stalenessNote(): string | null {\n const n = this.pendingChanges.size;\n if (n === 0) return null;\n const names = [...this.pendingChanges.keys()].sort().slice(0, 3);\n const more = n > names.length ? `, +${n - names.length} more` : '';\n return `map freshness: ${n} file(s) changed since the last rebuild (${names.join(', ')}${more}) — auto-refresh pending; symbol locations may have shifted`;\n }\n}\n\nexport function createServer(source: GraphSource, opts: ServeOptions = {}): Server {\n const { savings = false, shareStats = false, local = false, dedup = false, stats } = opts;\n // Recording feeds both the local `vg savings` report and the opt-in upload, so\n // enabling either turns it on. Absent both, `vg serve` records nothing.\n const record = savings || shareStats;\n // Prefer GraphSource's explicit root (set by serve from the project cwd).\n const root = opts.root ?? source.root;\n // Per-session memory of node ids whose full detail was already returned — the\n // basis for opt-in cross-call dedup (`--dedup`). Scoped to this server\n // instance so it never leaks across sessions. Node ids are content-addressed\n // (blake3 of content), so an edited node gets a new id and is never falsely\n // treated as already-seen — dedup is stale-safe by construction.\n const seen = new Set<string>();\n const server = new Server(\n { name: 'vg', version: VERSION },\n {\n capabilities: { tools: {} },\n // Routing guidance once at the server level (hosts that surface\n // `instructions` get it at zero per-step schema cost): the flashlight\n // vs the map.\n instructions:\n 'vg is a code map. Use search_symbols to find a known name or literal string fast — ' +\n 'a multi-word/quoted phrase runs a complete literal sweep and reports totalTextMatches, ' +\n 'so reach for it instead of grep even for plain-string \"find every occurrence\" lookups. ' +\n 'Use orient/query_graph for meaning: symptoms, relationships, and what-breaks-if. ' +\n 'Responses are concise by default; pass response_format:\"detailed\" only when a node proves load-bearing. ' +\n // Stop-discipline: the failure mode on a focused task is over-navigation\n // — one more query, one more get_node — which re-bills the whole context\n // every step. One good navigation call usually locates the code.\n 'Navigate as little as possible: one good search/query usually locates the code. ' +\n 'As soon as you have the file and line, read that file and make the edit — ' +\n 'do not call further graph tools unless the edit fails or the match was wrong. ' +\n // Library docs: position against web search (version-correct beats\n // SEO results), and give a stopping rule so a thin doc doesn't turn\n // into an open-ended search loop.\n 'For how-do-I-use-this-library questions call resolve_library once, then library_docs ' +\n 'with the returned targetId and a focused query: the docs are official and matched to ' +\n 'the version THIS project has installed (drift-annotated) — prefer them over web search ' +\n 'or training-data recall when they conflict. Skip them for language built-ins or APIs ' +\n 'already shown in context. If two library_docs calls have not surfaced the section you ' +\n 'need, read the package source under node_modules instead of searching again.',\n },\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n const listed = new Set(listedToolNames(opts.toolSurface));\n // Repo-size call budget on orient's listed description: the stop-discipline\n // where the model decides, priced once per list, not per step. Best-effort —\n // when no map is loadable yet the description ships without the line.\n let budget = '';\n try {\n const graph = await source.get();\n budget = budgetSuffix(new Set(graph.nodes.map((n) => n.file)).size);\n } catch {\n /* no map yet — plain description */\n }\n return {\n tools: TOOLS.filter((t) => listed.has(t.name)).map((t) => ({\n name: t.name,\n description: t.name === 'orient' && budget ? `${t.description}${budget}` : t.description,\n inputSchema: t.inputSchema,\n annotations: { readOnlyHint: true, openWorldHint: false },\n })),\n };\n });\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const tool = TOOLS.find((t) => t.name === request.params.name);\n if (!tool) {\n return errorResult(`unknown tool \"${request.params.name}\"`);\n }\n let graph: VgGraph;\n try {\n graph = await source.get();\n } catch {\n return errorResult(\n 'no code map found. Run `vg` in the project to build .vibgrate/graph.json, then retry.',\n );\n }\n const startedAt = Date.now();\n try {\n const args = (request.params.arguments ?? {}) as Record<string, unknown>;\n const result = await tool.handler(graph, args, { root, local, dedup, seen, graphPath: source.graphPath });\n const ms = Date.now() - startedAt;\n // Live, in-memory session stats for the serve status display — always on\n // when a serve process passed them (nothing leaves the process).\n stats?.record({ ...measureCall(tool.name, result), client: sanitizeClient(detectClient(server)), ms });\n // Opt-in, counts-only usage ledger: one entry per navigation call, with its\n // outcome, the grep-baseline token counts, and — so `vg savings` can show\n // the command-vs-MCP split and which AI is calling — the source (`mcp`) and\n // the client detected from the initialize handshake.\n if (record) recordUsage(root, tool.name, result, detectClient(server), ms);\n // Compact → clamp to the token ceiling → compact-serialise. See ./response.ts.\n const rendered = renderToolResult(result);\n // In-band staleness (serve-loop watcher): when the working tree has\n // drifted past the served map, say so ON the response — the agent is the\n // one acting on possibly-moved symbols, and stderr never reaches it.\n // Zero overhead when the map is current (the overwhelmingly common case).\n const staleness = source.stalenessNote();\n if (staleness) rendered.content = [...(rendered.content ?? []), { type: 'text', text: `[${staleness}]` }];\n return rendered;\n } catch (err) {\n // A failed call still counts in the live display — as a miss, so the\n // operator sees trouble instead of a silently frozen dashboard.\n stats?.record({\n tool: tool.name,\n client: sanitizeClient(detectClient(server)),\n outcome: 'miss',\n ms: Date.now() - startedAt,\n vgTokens: 0,\n baselineTokens: 0,\n });\n return errorResult(`tool \"${tool.name}\" failed: ${(err as Error).message}`);\n }\n });\n\n return server;\n}\n\nexport async function serveStdio(graphPath: string, opts: ServeOptions = {}): Promise<void> {\n const source = new GraphSource(graphPath, opts.refresh !== false, { root: opts.root });\n if (opts.refresh !== false && opts.watch !== false) source.startWatching();\n const server = createServer(source, opts);\n // Start the semantic-model warm-up as soon as the server boots, so the first\n // orient/query_graph doesn't pay a cold download. Non-blocking: navigation\n // answers lexically until the model is ready, then upgrades to semantic.\n warmEmbedderInBackground(opts.local);\n await server.connect(new StdioServerTransport());\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n const timer = setTimeout(resolve, ms);\n timer.unref?.(); // never keep the server process alive just for the budget timer\n });\n}\n\n/**\n * Append a counts-only usage entry for a navigation call: which tool, how it\n * resolved (complete/partial/miss), and — for the grep-baseline tools — the\n * tokens vg spent vs the grep/read baseline it replaced.\n *\n * `vgTokens` is the size of the payload vg ACTUALLY returned — the rendered text\n * block the model receives and re-pays on every subsequent turn — measured with\n * the same token counter the budget uses. It is deliberately NOT read from a\n * `tokensEstimate` field: only query_graph's rarely-used *detailed* mode ever\n * set that (get_node never did), so the old code recorded nothing under normal\n * concise usage and `vg savings` always reported \"recording is off\".\n */\nexport function recordUsage(root: string, tool: string, result: unknown, client?: string, ms?: number): void {\n recordSaving(\n root,\n { ...measureCall(tool, result), source: 'mcp', client: sanitizeClient(client), ...(ms !== undefined ? { ms } : {}) },\n Date.now(),\n );\n}\n\n/**\n * Measure one tool call for the ledger and the live session stats: its outcome\n * plus — for the grep-baseline tools only — the context tokens vg returned and\n * the baseline they replaced (other tools report zeros, meaning \"no baseline\").\n */\nfunction measureCall(tool: string, result: unknown): { tool: string; outcome: Outcome; vgTokens: number; baselineTokens: number } {\n const outcome = classifyOutcome(result);\n let vgTokens = 0;\n let baselineTokens = 0;\n if (SAVINGS_TOOLS.has(tool) && result && typeof result === 'object') {\n vgTokens = countTokens(renderedText(renderToolResult(result)));\n // Grep/read baseline: ~PER_FILE_TOKENS per distinct file the answer points\n // at — the files a grep/read agent would have had to open to learn the same\n // thing. query_graph surfaces them as `matches[].file`; get_node as its own\n // `file` plus the files of the callers/callees it returned in one call.\n baselineTokens = referencedFiles(result).size * PER_FILE_TOKENS;\n }\n return { tool, outcome, vgTokens, baselineTokens };\n}\n\n/**\n * The coarse client label from the MCP `initialize` handshake, if the host sent\n * `clientInfo`. Read defensively — `getClientVersion()` exists on the SDK Server\n * once initialized, but we never want telemetry bookkeeping to throw. Returns\n * undefined when unknown (then sanitized to `'unknown'`).\n */\nfunction detectClient(server: Server): string | undefined {\n try {\n const info = (server as { getClientVersion?: () => { name?: string } | undefined }).getClientVersion?.();\n return typeof info?.name === 'string' ? info.name : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Bucket a tool result into complete / partial / miss. A `miss` is an answer\n * that found nothing (no match, not-found, not-connected, or an empty listing);\n * a `partial` found results but capped or paginated some of them; everything\n * else is `complete`. Note that a legitimately empty `affected`/`covers` (e.g.\n * \"nothing depends on this\") is a successful answer, not a miss — only the\n * primary discovery signals below mark a miss.\n */\nfunction classifyOutcome(result: unknown): Outcome {\n if (Array.isArray(result)) return result.length === 0 ? 'miss' : 'complete';\n if (!result || typeof result !== 'object') return 'miss';\n const r = result as Record<string, unknown>;\n if (typeof r.error === 'string' && r.error) return 'miss'; // not_found / ambiguous / unresolved\n if (r.connected === false) return 'miss'; // find_path\n if (Array.isArray(r.matches) && r.matches.length === 0) return 'miss'; // query_graph / search_symbols\n return isPartial(r) ? 'partial' : 'complete';\n}\n\n/** True when a hit left results on the table: paginated, or a capped relation list. */\nfunction isPartial(r: Record<string, unknown>): boolean {\n if (r.moreAvailable === true) return true;\n if (r._truncated && typeof r._truncated === 'object') return true;\n // A `<name>Total` greater than the length of its sibling `<name>` array means\n // the array was capped (e.g. get_node's callsTotal vs the shown calls).\n for (const [key, value] of Object.entries(r)) {\n if (typeof value !== 'number' || !key.endsWith('Total')) continue;\n const base = key.slice(0, -'Total'.length);\n const shown = Array.isArray(r[base]) ? (r[base] as unknown[]).length : 0;\n if (value > shown) return true;\n }\n return false;\n}\n\n/** The text block of a rendered tool result — what the model is billed for. */\nfunction renderedText(rendered: CallToolResult): string {\n const block = rendered.content?.find((b) => b.type === 'text');\n return block && 'text' in block && typeof block.text === 'string' ? block.text : '';\n}\n\n/** Distinct files a navigation result points at (its grep/read baseline set). */\nfunction referencedFiles(result: unknown): Set<string> {\n const r = result as { file?: unknown; matches?: unknown; calls?: unknown; calledBy?: unknown };\n const files = new Set<string>();\n if (typeof r.file === 'string' && r.file) files.add(r.file);\n for (const m of asArray(r.matches)) {\n const f = (m as { file?: unknown }).file;\n if (typeof f === 'string' && f) files.add(f);\n }\n // get_node's calls/calledBy are qualified names of the form `path:symbol`; the\n // path prefix is the file a grep/read agent would open to inspect that edge.\n for (const name of [...asArray(r.calls), ...asArray(r.calledBy)]) {\n if (typeof name !== 'string') continue;\n const i = name.indexOf(':');\n if (i > 0) files.add(name.slice(0, i));\n }\n return files;\n}\n\nfunction asArray(v: unknown): unknown[] {\n return Array.isArray(v) ? v : [];\n}\n\nfunction errorResult(message: string) {\n return { content: [{ type: 'text', text: message }], isError: true };\n}\n","import { serializeGraph, slimGraphForExport } from './serialize.js';\nimport { renderReport } from './report.js';\nimport { renderHtml } from './html.js';\nimport type { DepRecord } from './drift.js';\nimport type { LocalModel } from './models.js';\nimport type { VgGraph } from '../schema.js';\n\n/** Above this node count, JSON export defaults to compact (no pretty-print). */\nexport const COMPACT_JSON_NODES = 5_000;\n\n/**\n * Deterministic exporters (VG-CLI-SPEC §4.2). One `vg export <file>` verb, format\n * inferred from the extension. Live graph-DB push is deliberately out (a file\n * import covers the same need offline). CycloneDX/SPDX power the SBOM/AI-BOM seam\n * (VG-LOCAL-MODELS §9.4).\n */\n\nexport type ExportFormat =\n | 'json'\n | 'ndjson'\n | 'graphml'\n | 'dot'\n | 'cypher'\n | 'sql'\n | 'md'\n | 'html'\n | 'cyclonedx'\n | 'spdx';\n\nexport function formatForExt(ext: string): ExportFormat | null {\n switch (ext.toLowerCase()) {\n case '.json':\n return 'json';\n case '.ndjson':\n return 'ndjson';\n case '.graphml':\n return 'graphml';\n case '.dot':\n case '.gv':\n return 'dot';\n case '.cypher':\n return 'cypher';\n case '.sql':\n return 'sql';\n case '.md':\n return 'md';\n case '.html':\n return 'html';\n default:\n return null;\n }\n}\n\nexport interface ExportContext {\n graph: VgGraph;\n deps?: DepRecord[];\n models?: LocalModel[];\n generatedAt: string;\n /** Force compact JSON (no indent). Default: auto when nodes > COMPACT_JSON_NODES. */\n compact?: boolean;\n /** Drop area members + grounding for smaller artifacts. */\n slim?: boolean;\n}\n\nexport function exportGraph(format: ExportFormat, ctx: ExportContext): string {\n const graph = ctx.slim ? slimGraphForExport(ctx.graph) : ctx.graph;\n const compact =\n ctx.compact === true ||\n (ctx.compact !== false && format === 'json' && graph.meta.counts.nodes > COMPACT_JSON_NODES);\n\n switch (format) {\n case 'json':\n return serializeGraph(graph, { compact });\n case 'md':\n return renderReport(graph);\n case 'html':\n return renderHtml(graph);\n case 'ndjson':\n return ndjson(graph);\n case 'graphml':\n return graphml(graph);\n case 'dot':\n return dot(graph);\n case 'cypher':\n return cypher(graph);\n case 'sql':\n return sql({ ...ctx, graph });\n case 'cyclonedx':\n return cyclonedx({ ...ctx, graph });\n case 'spdx':\n return spdx({ ...ctx, graph });\n }\n}\n\nfunction ndjson(graph: VgGraph): string {\n // Facts stream if present, else the node stream — one JSON object per line.\n const rows = graph.facts && graph.facts.length ? graph.facts : graph.nodes;\n return rows.map((r) => JSON.stringify(r)).join('\\n') + '\\n';\n}\n\nfunction esc(s: string): string {\n return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"');\n}\n\nfunction graphml(graph: VgGraph): string {\n const lines: string[] = [];\n lines.push('<?xml version=\"1.0\" encoding=\"UTF-8\"?>');\n lines.push('<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\">');\n lines.push(' <key id=\"name\" for=\"node\" attr.name=\"name\" attr.type=\"string\"/>');\n lines.push(' <key id=\"kind\" for=\"node\" attr.name=\"kind\" attr.type=\"string\"/>');\n lines.push(' <key id=\"file\" for=\"node\" attr.name=\"file\" attr.type=\"string\"/>');\n lines.push(' <key id=\"ekind\" for=\"edge\" attr.name=\"kind\" attr.type=\"string\"/>');\n lines.push(' <graph edgedefault=\"directed\">');\n for (const n of graph.nodes) {\n lines.push(` <node id=\"${esc(n.id)}\"><data key=\"name\">${esc(n.qualifiedName)}</data><data key=\"kind\">${esc(n.kind)}</data><data key=\"file\">${esc(n.file)}</data></node>`);\n }\n for (const e of graph.edges) {\n lines.push(` <edge source=\"${esc(e.src)}\" target=\"${esc(e.dst)}\"><data key=\"ekind\">${esc(e.kind)}</data></edge>`);\n }\n lines.push(' </graph>');\n lines.push('</graphml>');\n return lines.join('\\n') + '\\n';\n}\n\nfunction dot(graph: VgGraph): string {\n const lines: string[] = ['digraph vg {'];\n for (const n of graph.nodes) lines.push(` \"${n.id}\" [label=\"${dotEsc(n.qualifiedName)}\"];`);\n for (const e of graph.edges) lines.push(` \"${e.src}\" -> \"${e.dst}\" [label=\"${e.kind}\"];`);\n lines.push('}');\n return lines.join('\\n') + '\\n';\n}\nfunction dotEsc(s: string): string {\n return s.replace(/\"/g, '\\\\\"');\n}\n\nfunction cypher(graph: VgGraph): string {\n const lines: string[] = [];\n for (const n of graph.nodes) {\n lines.push(\n `CREATE (:\\`${cypherLabel(n.kind)}\\` {id:${q(n.id)}, name:${q(n.qualifiedName)}, file:${q(n.file)}});`,\n );\n }\n for (const e of graph.edges) {\n lines.push(\n `MATCH (a {id:${q(e.src)}}),(b {id:${q(e.dst)}}) CREATE (a)-[:\\`${cypherLabel(e.kind)}\\`]->(b);`,\n );\n }\n return lines.join('\\n') + '\\n';\n}\nfunction cypherLabel(s: string): string {\n return s.replace(/[^A-Za-z0-9_]/g, '_');\n}\nfunction q(s: string): string {\n return JSON.stringify(s);\n}\n\n/**\n * Portable SQL fact-DB (VG-CLI-SPEC §4.2, agent-consumption). Emits deterministic\n * DDL + INSERT text — NOT a native driver — that loads identically into BOTH\n * sqlite3 and duckdb (`sqlite3 map.db < map.sql` / `duckdb map.db < map.sql`).\n * Text keeps the CLI dependency-free, offline, and byte-diffable; an identical\n * graph yields identical bytes. An agent can then run e.g.\n * SELECT src, dst FROM edges WHERE epistemic = 'observed' AND confidence >= 0.9;\n * Determinism: single transaction, `CREATE TABLE IF NOT EXISTS`, rows emitted in\n * the graph's own (already-sorted) array order, single quotes doubled, NULL for\n * absent optionals, booleans as 0/1, and no timestamp but the graph's generatedAt.\n */\nfunction sql(ctx: ExportContext): string {\n const graph = ctx.graph;\n const lines: string[] = [];\n lines.push('BEGIN;');\n\n // meta — provenance / toolchain fingerprint (key/value; agent can read the corpus hash).\n lines.push('CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value TEXT);');\n const meta: [string, string | null][] = [\n ['schemaVersion', graph.schemaVersion],\n ['generatedAt', ctx.generatedAt],\n ['corpusHash', graph.provenance.corpusHash],\n ['tool', graph.provenance.tool],\n ['toolVersion', graph.provenance.version],\n ['resolver', graph.provenance.resolver.join(',')],\n ['fingerprint', graph.provenance.toolchain?.fingerprint ?? null],\n ];\n for (const [k, v] of meta) lines.push(`INSERT INTO meta VALUES (${sqlStr(k)}, ${sqlStr(v)});`);\n\n // nodes\n lines.push(\n 'CREATE TABLE IF NOT EXISTS nodes (id TEXT PRIMARY KEY, kind TEXT, name TEXT, qualified_name TEXT, file TEXT, span_start INTEGER, span_end INTEGER, lang TEXT, visibility TEXT, signature TEXT, importance REAL, area INTEGER, is_hub INTEGER, tested INTEGER, coverage REAL);',\n );\n for (const n of graph.nodes) {\n lines.push(\n `INSERT INTO nodes VALUES (${sqlStr(n.id)}, ${sqlStr(n.kind)}, ${sqlStr(n.name)}, ${sqlStr(n.qualifiedName)}, ${sqlStr(n.file)}, ${sqlNum(n.span.start)}, ${sqlNum(n.span.end)}, ${sqlStr(n.lang)}, ${sqlStr(n.visibility)}, ${sqlStr(n.signature)}, ${sqlNum(n.importance)}, ${sqlNum(n.area)}, ${sqlBool(n.isHub)}, ${sqlBool(n.tested)}, ${sqlNum(n.coverage)});`,\n );\n }\n\n // edges — the epistemic column is the point: SELECT ... WHERE epistemic='observed'.\n lines.push(\n 'CREATE TABLE IF NOT EXISTS edges (id TEXT PRIMARY KEY, kind TEXT, src TEXT, dst TEXT, resolution TEXT, confidence REAL, epistemic TEXT, surprise REAL, \"count\" INTEGER);',\n );\n for (const e of graph.edges) {\n lines.push(\n `INSERT INTO edges VALUES (${sqlStr(e.id)}, ${sqlStr(e.kind)}, ${sqlStr(e.src)}, ${sqlStr(e.dst)}, ${sqlStr(e.resolution)}, ${sqlNum(e.confidence)}, ${sqlStr(e.epistemic)}, ${sqlNum(e.surprise)}, ${sqlNum(e.count)});`,\n );\n }\n\n // areas (+ members)\n lines.push('CREATE TABLE IF NOT EXISTS areas (id INTEGER PRIMARY KEY, label TEXT, size INTEGER, cohesion REAL, external_edges INTEGER);');\n lines.push('CREATE TABLE IF NOT EXISTS area_members (area_id INTEGER, node_id TEXT);');\n for (const a of graph.areas) {\n lines.push(`INSERT INTO areas VALUES (${sqlNum(a.id)}, ${sqlStr(a.label)}, ${sqlNum(a.size)}, ${sqlNum(a.cohesion)}, ${sqlNum(a.externalEdges)});`);\n for (const m of a.members) lines.push(`INSERT INTO area_members VALUES (${sqlNum(a.id)}, ${sqlStr(m)});`);\n }\n\n // facts (+ subjects, evidence) when the graph carried them.\n if (graph.facts && graph.facts.length) {\n lines.push('CREATE TABLE IF NOT EXISTS facts (id TEXT PRIMARY KEY, kind TEXT, predicate_json TEXT, derived_by TEXT, confidence TEXT);');\n lines.push('CREATE TABLE IF NOT EXISTS fact_subjects (fact_id TEXT, node_id TEXT);');\n lines.push('CREATE TABLE IF NOT EXISTS fact_evidence (fact_id TEXT, file TEXT, span_start INTEGER, span_end INTEGER);');\n for (const f of graph.facts) {\n lines.push(`INSERT INTO facts VALUES (${sqlStr(f.id)}, ${sqlStr(f.kind)}, ${sqlStr(JSON.stringify(f.predicate))}, ${sqlStr(f.derivedBy)}, ${sqlStr(f.confidence)});`);\n for (const s of f.subjectIds) lines.push(`INSERT INTO fact_subjects VALUES (${sqlStr(f.id)}, ${sqlStr(s)});`);\n for (const ev of f.evidence) lines.push(`INSERT INTO fact_evidence VALUES (${sqlStr(f.id)}, ${sqlStr(ev.file)}, ${sqlNum(ev.span.start)}, ${sqlNum(ev.span.end)});`);\n }\n }\n\n lines.push('COMMIT;');\n return lines.join('\\n') + '\\n';\n}\n\n/** SQL string literal (single quotes doubled) or NULL for absent values. */\nfunction sqlStr(v: string | null | undefined): string {\n if (v == null) return 'NULL';\n return `'${v.replace(/'/g, \"''\")}'`;\n}\n/** Numeric literal or NULL for absent values. */\nfunction sqlNum(v: number | null | undefined): string {\n return v == null || !Number.isFinite(v) ? 'NULL' : String(v);\n}\n/** Boolean as 0/1, NULL when unknown (e.g. an unanalyzable node's `tested`). */\nfunction sqlBool(v: boolean | null | undefined): string {\n return v == null ? 'NULL' : v ? '1' : '0';\n}\n\nfunction cyclonedx(ctx: ExportContext): string {\n // CycloneDX 1.6 JSON — dependencies as library components + local models as\n // machine-learning-model components (AI-BOM). Deterministic ordering; no\n // timestamps beyond the pinned generatedAt.\n const components: unknown[] = [];\n for (const d of ctx.deps ?? []) {\n components.push({\n type: 'library',\n name: d.name,\n version: d.installed ?? d.declared,\n purl: d.ecosystem === 'npm' ? `pkg:npm/${d.name}@${d.installed ?? ''}` : undefined,\n });\n }\n for (const m of ctx.models ?? []) {\n components.push({ type: 'machine-learning-model', name: m.name, properties: [{ name: 'vg:runtime', value: m.runtime }] });\n }\n const bom = {\n bomFormat: 'CycloneDX',\n specVersion: '1.6',\n metadata: { timestamp: ctx.generatedAt, tools: [{ name: 'vg', version: ctx.graph.provenance.version }] },\n components,\n };\n return JSON.stringify(bom, null, 2) + '\\n';\n}\n\nfunction spdx(ctx: ExportContext): string {\n const packages = (ctx.deps ?? []).map((d) => ({\n SPDXID: `SPDXRef-Package-${cypherLabel(d.name)}`,\n name: d.name,\n versionInfo: d.installed ?? d.declared,\n downloadLocation: 'NOASSERTION',\n }));\n const doc = {\n spdxVersion: 'SPDX-2.3',\n dataLicense: 'CC0-1.0',\n SPDXID: 'SPDXRef-DOCUMENT',\n name: 'vg-sbom',\n creationInfo: { created: ctx.generatedAt, creators: [`Tool: vg-${ctx.graph.provenance.version}`] },\n packages,\n };\n return JSON.stringify(doc, null, 2) + '\\n';\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { buildMessages, parseEdits, applyEdits, unifiedDiff, redactSecrets } from './chunk-
|
|
2
|
-
import { recordCliCall, CLI_TOOL_ALIASES, buildCodeContext, buildTaskCapsule, capsuleToCodeContext } from './chunk-
|
|
3
|
-
import { analyzeQuestion, loadTopicTags } from './chunk-
|
|
1
|
+
import { buildMessages, parseEdits, applyEdits, unifiedDiff, redactSecrets } from './chunk-2U4SXS5U.js';
|
|
2
|
+
import { recordCliCall, CLI_TOOL_ALIASES, buildCodeContext, buildTaskCapsule, capsuleToCodeContext } from './chunk-CM6OYYBW.js';
|
|
3
|
+
import { analyzeQuestion, loadTopicTags } from './chunk-K5GPEWPI.js';
|
|
4
4
|
import { repositoryIdFromRoot } from './chunk-BWPBB45M.js';
|
|
5
5
|
import * as fs from 'fs';
|
|
6
6
|
import * as path from 'path';
|
|
@@ -258,5 +258,5 @@ function shortId() {
|
|
|
258
258
|
}
|
|
259
259
|
|
|
260
260
|
export { commitChanges, nodeCodeFs, runCodeSession, undoChanges };
|
|
261
|
-
//# sourceMappingURL=chunk-
|
|
262
|
-
//# sourceMappingURL=chunk-
|
|
261
|
+
//# sourceMappingURL=chunk-XVZMDDU4.js.map
|
|
262
|
+
//# sourceMappingURL=chunk-XVZMDDU4.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/code/session.ts"],"names":["resolve"],"mappings":"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","file":"chunk-BUCNKYTW.js","sourcesContent":["/**\n * The `vg code` governance session (VG-CLI-CODE §7).\n *\n * This is the load-bearing rule the whole platform is built on, applied to code\n * edits: a state-altering change goes **through** the lifecycle, never around it\n * (GUARDRAILS §5). One run walks inspect → assess → dry-run → approve → execute\n * → verify → log:\n *\n * inspect build the graph-grounded context for the instruction\n * assess ask the routed model for a terse edit; apply it deterministically\n * (in memory); compute the diff and the blast radius\n * dry-run the DEFAULT terminal state — propose the change, write nothing\n * approve writing requires explicit consent; without it we stop at dry-run\n * execute write the approved changes to disk\n * verify confirm the files on disk match what was approved (+ optional cmd)\n * log append an immutable, secret-free audit record with a correlation id\n *\n * Everything is deterministic except the single model call, which is isolated\n * behind the provider list (tried in order, falling back on transport failure).\n * The filesystem and clock are injectable so the whole session is testable\n * offline with no writes escaping a temp dir.\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { buildCodeContext } from './context.js';\nimport { analyzeQuestion, type RelevanceAnalysis } from '../engine/relevance-provider.js';\nimport { loadTopicTags } from '../engine/relevance-enrich.js';\nimport { buildTaskCapsule, capsuleToCodeContext } from './capsule.js';\nimport { recordCliCall, CLI_TOOL_ALIASES } from '../engine/savings.js';\nimport { repositoryIdFromRoot } from '../runtime/paths.js';\nimport { parseEdits, applyEdits, type SymbolSpan } from './apply.js';\nimport { unifiedDiff } from './diff.js';\nimport { buildMessages } from './prompt.js';\nimport { redactSecrets } from './providers.js';\nimport type { ChatOptions, CodeContext, CodeSessionResult, FileChange, LifecyclePhase, Provider, ProviderResult } from './types.js';\nimport type { VgGraph } from '../schema.js';\n\n/** Minimal filesystem seam so the session is testable without touching real disk. */\nexport interface CodeFs {\n read(file: string): string | null;\n write(file: string, content: string): void;\n remove(file: string): void;\n appendAudit(line: string): void;\n}\n\nexport interface RunSessionOptions {\n graph: VgGraph;\n root: string;\n instruction: string;\n /** Providers to try in order (from the router); the first that answers wins. */\n providers: Provider[];\n /** Write to disk? Default false — dry-run is the safe default (GUARDRAILS §3.2). */\n apply?: boolean;\n /** Explicit consent for the write (`--yes`); without it, a requested apply stops at dry-run. */\n consent?: boolean;\n /** Restrict the edit surface to these files. */\n files?: string[];\n /** Context token budget. */\n budget?: number;\n chatOptions?: ChatOptions;\n /** Injectable filesystem (defaults to a real, root-scoped fs). */\n fsImpl?: CodeFs;\n /** Injectable clock (ms) for the audit timestamp. */\n now?: () => number;\n /** Injectable correlation id (defaults to a random short id). */\n correlationId?: string;\n /** Progress callback per phase. */\n onPhase?: (phase: LifecyclePhase, detail: string) => void;\n /** Skip appending to the audit log (used by tests/dry programmatic calls). */\n noAudit?: boolean;\n /**\n * Who is making the graph-backed call, for per-model savings auditing. When\n * `client` is set, the context-assembly step (a `query_graph`-equivalent) is\n * recorded to the local savings ledger tagged with the provider + model, so\n * `vg savings` can break usage down per model. VG Code always sets this.\n */\n attribution?: { client: string; provider?: string; model?: string };\n /**\n * Use a source-bearing Task Capsule for the inspect context (Fusion Runtime\n * Phase 0 A/B). Default false keeps the metadata-only path.\n */\n capsule?: boolean;\n}\n\nexport async function runCodeSession(options: RunSessionOptions): Promise<CodeSessionResult> {\n const {\n graph,\n root,\n instruction,\n providers,\n apply = false,\n consent = false,\n files,\n budget,\n chatOptions,\n now = () => 0,\n onPhase = () => {},\n } = options;\n const fsImpl = options.fsImpl ?? nodeCodeFs(root);\n const correlationId = options.correlationId ?? shortId();\n const phasesRun: LifecyclePhase[] = [];\n const phase = (p: LifecyclePhase, detail: string): void => {\n phasesRun.push(p);\n onPhase(p, detail);\n };\n\n // ── inspect ──────────────────────────────────────────────────────────────\n phase('inspect', options.capsule ? 'building source-bearing task capsule' : 'building graph-grounded context');\n // Optional relevance provider: widens capsule seed vocabulary when\n // installed; null (the default) changes nothing.\n const relevance = await analyzeQuestion(instruction);\n const topicTags = relevance ? await loadTopicTags(graph, root) : null;\n const context = buildSessionContext(graph, instruction, {\n budget,\n files,\n capsule: options.capsule,\n root,\n fsImpl,\n relevance,\n topicTags,\n });\n\n // Per-model savings: the context build is VG Code's `query_graph`-equivalent.\n // Record it (counts only — never code or the instruction) tagged with the\n // model, so `vg savings` audits usage per model. Local-only, best-effort.\n if (options.attribution?.client) {\n const seedFiles = new Set(context.seeds.map((s) => s.node.file).filter(Boolean));\n recordCliCall(\n root,\n {\n tool: CLI_TOOL_ALIASES.ask,\n client: options.attribution.client,\n provider: options.attribution.provider,\n model: options.attribution.model,\n outcome: context.seeds.length ? 'complete' : 'miss',\n vgTokens: context.tokensEstimate,\n baselineFiles: seedFiles.size,\n },\n now(),\n );\n }\n\n // ── assess ──────────────────────────────────────────────────────────────\n phase('assess', 'asking the routed model for a minimal edit');\n const messages = buildMessages(context);\n const { result, provider, fellBack } = await complete(providers, messages, chatOptions, correlationId);\n\n const edits = parseEdits(result.text);\n const spans = spanIndex(graph);\n const applied = applyEdits(\n edits,\n (file) => fsImpl.read(file),\n (file) => spans.get(normalize(file)) ?? [],\n );\n\n const changes: FileChange[] = [];\n for (const [file, entry] of [...applied.entries()].sort((a, b) => a[0].localeCompare(b[0]))) {\n changes.push({\n file,\n before: entry.before,\n after: entry.after,\n outcomes: entry.outcomes,\n diff: unifiedDiff(entry.before, entry.after, file),\n });\n }\n\n // ── dry-run (always produced) ─────────────────────────────────────────────\n phase('dry-run', `${changes.length} file(s) would change`);\n\n const anyApplicable = changes.some((c) => c.diff !== '' && c.outcomes.some((o) => o.status === 'applied'));\n const base: CodeSessionResult = {\n instruction,\n provider: { id: provider.id, model: provider.model, local: provider.local, fellBack },\n phasesRun,\n changes,\n applied: false,\n verification: { ran: false, ok: false, detail: 'dry-run — no changes written' },\n correlationId,\n };\n\n // ── approve ───────────────────────────────────────────────────────────────\n // Writing is opt-in AND consent-gated. A requested apply without consent is\n // not an error — it degrades to a dry-run so the caller can review, then\n // re-run with --yes. This is the \"never destructive-by-default\" guardrail.\n if (!apply) {\n if (!options.noAudit) writeAudit(fsImpl, base, now());\n return base;\n }\n if (!consent) {\n const stopped = { ...base, verification: { ran: false, ok: false, detail: 'apply requested without consent — re-run with --yes to write these changes' } };\n if (!options.noAudit) writeAudit(fsImpl, stopped, now());\n return stopped;\n }\n if (!anyApplicable) {\n const nothing = { ...base, verification: { ran: false, ok: false, detail: 'nothing to write — no edit applied cleanly' } };\n if (!options.noAudit) writeAudit(fsImpl, nothing, now());\n return nothing;\n }\n phase('approve', 'consent given (--yes)');\n\n // ── execute ───────────────────────────────────────────────────────────────\n phase('execute', 'writing approved changes');\n for (const change of changes) {\n if (change.diff === '') continue; // no-op file\n if (!change.outcomes.some((o) => o.status === 'applied')) continue; // nothing applied cleanly here\n if (change.after === null) fsImpl.remove(change.file);\n else fsImpl.write(change.file, change.after);\n }\n\n // ── verify ────────────────────────────────────────────────────────────────\n phase('verify', 'confirming on-disk content matches the approved change');\n const verification = verifyWrites(fsImpl, changes);\n\n // ── log ───────────────────────────────────────────────────────────────────\n phase('log', 'recording an audit entry');\n const final: CodeSessionResult = { ...base, applied: true, verification };\n if (!options.noAudit) writeAudit(fsImpl, final, now());\n return final;\n}\n\n/**\n * Commit an already-computed dry-run result: write the cleanly-applied changes,\n * verify them on disk, and append the audit record — the \"approve → execute →\n * verify → log\" tail of the lifecycle, run against a proposal the caller has\n * already shown and had approved (the interactive REPL uses this so it never\n * calls the model twice or writes something different from what was reviewed).\n */\nexport function commitChanges(result: CodeSessionResult, fsImpl: CodeFs, now: () => number = () => 0): CodeSessionResult {\n const anyApplicable = result.changes.some((c) => c.diff !== '' && c.outcomes.some((o) => o.status === 'applied'));\n if (!anyApplicable) {\n return { ...result, applied: false, verification: { ran: false, ok: false, detail: 'nothing to write — no edit applied cleanly' } };\n }\n for (const change of result.changes) {\n if (change.diff === '' || !change.outcomes.some((o) => o.status === 'applied')) continue;\n if (change.after === null) fsImpl.remove(change.file);\n else fsImpl.write(change.file, change.after);\n }\n const verification = verifyWrites(fsImpl, result.changes);\n const final: CodeSessionResult = { ...result, applied: true, verification, phasesRun: [...result.phasesRun, 'approve', 'execute', 'verify', 'log'] };\n writeAudit(fsImpl, final, now());\n return final;\n}\n\n/**\n * Undo a set of applied changes by restoring each file's prior content — the\n * `/undo` command. A created file (before === null) is removed; an edited or\n * deleted file is restored to its `before`. Only cleanly-applied changes are\n * reverted. Returns the files it restored.\n */\nexport function undoChanges(changes: FileChange[], fsImpl: CodeFs): string[] {\n const restored: string[] = [];\n for (const ch of changes) {\n if (!ch.outcomes.some((o) => o.status === 'applied')) continue;\n if (ch.before === null) fsImpl.remove(ch.file);\n else fsImpl.write(ch.file, ch.before);\n restored.push(ch.file);\n }\n return restored;\n}\n\nfunction buildSessionContext(\n graph: VgGraph,\n instruction: string,\n opts: { budget?: number; files?: string[]; capsule?: boolean; root: string; fsImpl: CodeFs; relevance?: RelevanceAnalysis | null; topicTags?: Map<string, readonly string[]> | null },\n): CodeContext {\n const budget = opts.budget;\n const files = opts.files;\n if (!opts.capsule) {\n return buildCodeContext(graph, instruction, { budget, files, relevance: opts.relevance, topicTags: opts.topicTags });\n }\n const capsule = buildTaskCapsule(graph, instruction, {\n budget,\n files,\n readFile: (rel) => opts.fsImpl.read(rel),\n repositoryId: repositoryIdFromRoot(opts.root),\n relevance: opts.relevance,\n topicTags: opts.topicTags,\n });\n return capsuleToCodeContext(capsule);\n}\n\n/** Try each provider in order; fall back on transport failure. Throws the last actionable error. */\nasync function complete(\n providers: Provider[],\n messages: ReturnType<typeof buildMessages>,\n chatOptions: ChatOptions | undefined,\n correlationId: string,\n): Promise<{ result: ProviderResult; provider: Provider; fellBack: boolean }> {\n if (providers.length === 0) throw new Error(`no model provider available (ref ${correlationId})`);\n let lastErr: unknown;\n for (let i = 0; i < providers.length; i++) {\n const provider = providers[i];\n try {\n const result = await provider.chat(messages, { temperature: 0, ...chatOptions });\n return { result, provider, fellBack: i > 0 };\n } catch (e) {\n lastErr = e;\n }\n }\n const message = lastErr instanceof Error ? redactSecrets(lastErr.message) : String(lastErr);\n throw new Error(`${message} (ref ${correlationId})`);\n}\n\n/** Confirm each written file's on-disk content equals what we approved. */\nfunction verifyWrites(fsImpl: CodeFs, changes: FileChange[]): { ran: boolean; ok: boolean; detail: string } {\n let checked = 0;\n const mismatches: string[] = [];\n for (const change of changes) {\n if (change.diff === '' || !change.outcomes.some((o) => o.status === 'applied')) continue;\n checked++;\n const onDisk = fsImpl.read(change.file);\n if (onDisk !== change.after) mismatches.push(change.file);\n }\n if (mismatches.length) return { ran: true, ok: false, detail: `on-disk content differs for: ${mismatches.join(', ')}` };\n return { ran: true, ok: true, detail: `wrote and verified ${checked} file(s)` };\n}\n\n/** An append-only, secret-free audit record (GUARDRAILS §2.6 / §5). No file contents, no keys. */\nfunction writeAudit(fsImpl: CodeFs, r: CodeSessionResult, ts: number): void {\n const record = {\n ts,\n correlationId: r.correlationId,\n instruction: r.instruction.slice(0, 500),\n provider: r.provider.id,\n model: r.provider.model,\n local: r.provider.local,\n applied: r.applied,\n files: r.changes.map((c) => ({ file: c.file, statuses: c.outcomes.map((o) => o.status) })),\n verification: r.verification,\n phases: r.phasesRun,\n };\n try {\n fsImpl.appendAudit(JSON.stringify(record));\n } catch {\n /* audit is best-effort; never fail the run on a logging problem */\n }\n}\n\n/** Build a per-file map of symbol spans for graph-scoped edit disambiguation. */\nfunction spanIndex(graph: VgGraph): Map<string, SymbolSpan[]> {\n const map = new Map<string, SymbolSpan[]>();\n for (const n of graph.nodes) {\n if (n.kind === 'file' || n.kind === 'external') continue;\n const file = normalize(n.file);\n const list = map.get(file) ?? [];\n list.push({ qualifiedName: n.qualifiedName, file, start: n.span.start, end: n.span.end });\n map.set(file, list);\n }\n return map;\n}\n\nfunction normalize(file: string): string {\n return file.replace(/\\\\/g, '/').replace(/^\\.\\//, '');\n}\n\n/** Default filesystem impl, scoped to `root`. Refuses paths that escape the root. */\nexport function nodeCodeFs(root: string): CodeFs {\n const resolve = (file: string): string => {\n const abs = path.resolve(root, file);\n const rel = path.relative(root, abs);\n if (rel.startsWith('..') || path.isAbsolute(rel)) {\n throw new Error(`edit path escapes the project root: ${file} — refusing to touch files outside ${root}`);\n }\n return abs;\n };\n return {\n read(file) {\n try {\n return fs.readFileSync(resolve(file), 'utf8');\n } catch {\n return null;\n }\n },\n write(file, content) {\n const abs = resolve(file);\n fs.mkdirSync(path.dirname(abs), { recursive: true });\n fs.writeFileSync(abs, content);\n },\n remove(file) {\n try {\n fs.rmSync(resolve(file));\n } catch {\n /* already gone */\n }\n },\n appendAudit(line) {\n const dir = path.join(root, '.vibgrate');\n fs.mkdirSync(dir, { recursive: true });\n fs.appendFileSync(path.join(dir, 'code-audit.jsonl'), line + '\\n');\n },\n };\n}\n\n/** Short, URL-safe correlation id. Not a graph artifact, so runtime randomness is fine here. */\nfunction shortId(): string {\n let s = '';\n const alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789';\n for (let i = 0; i < 8; i++) s += alphabet[Math.floor(Math.random() * alphabet.length)];\n return s;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/code/session.ts"],"names":["resolve"],"mappings":"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","file":"chunk-XVZMDDU4.js","sourcesContent":["/**\n * The `vg code` governance session (VG-CLI-CODE §7).\n *\n * This is the load-bearing rule the whole platform is built on, applied to code\n * edits: a state-altering change goes **through** the lifecycle, never around it\n * (GUARDRAILS §5). One run walks inspect → assess → dry-run → approve → execute\n * → verify → log:\n *\n * inspect build the graph-grounded context for the instruction\n * assess ask the routed model for a terse edit; apply it deterministically\n * (in memory); compute the diff and the blast radius\n * dry-run the DEFAULT terminal state — propose the change, write nothing\n * approve writing requires explicit consent; without it we stop at dry-run\n * execute write the approved changes to disk\n * verify confirm the files on disk match what was approved (+ optional cmd)\n * log append an immutable, secret-free audit record with a correlation id\n *\n * Everything is deterministic except the single model call, which is isolated\n * behind the provider list (tried in order, falling back on transport failure).\n * The filesystem and clock are injectable so the whole session is testable\n * offline with no writes escaping a temp dir.\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { buildCodeContext } from './context.js';\nimport { analyzeQuestion, type RelevanceAnalysis } from '../engine/relevance-provider.js';\nimport { loadTopicTags } from '../engine/relevance-enrich.js';\nimport { buildTaskCapsule, capsuleToCodeContext } from './capsule.js';\nimport { recordCliCall, CLI_TOOL_ALIASES } from '../engine/savings.js';\nimport { repositoryIdFromRoot } from '../runtime/paths.js';\nimport { parseEdits, applyEdits, type SymbolSpan } from './apply.js';\nimport { unifiedDiff } from './diff.js';\nimport { buildMessages } from './prompt.js';\nimport { redactSecrets } from './providers.js';\nimport type { ChatOptions, CodeContext, CodeSessionResult, FileChange, LifecyclePhase, Provider, ProviderResult } from './types.js';\nimport type { VgGraph } from '../schema.js';\n\n/** Minimal filesystem seam so the session is testable without touching real disk. */\nexport interface CodeFs {\n read(file: string): string | null;\n write(file: string, content: string): void;\n remove(file: string): void;\n appendAudit(line: string): void;\n}\n\nexport interface RunSessionOptions {\n graph: VgGraph;\n root: string;\n instruction: string;\n /** Providers to try in order (from the router); the first that answers wins. */\n providers: Provider[];\n /** Write to disk? Default false — dry-run is the safe default (GUARDRAILS §3.2). */\n apply?: boolean;\n /** Explicit consent for the write (`--yes`); without it, a requested apply stops at dry-run. */\n consent?: boolean;\n /** Restrict the edit surface to these files. */\n files?: string[];\n /** Context token budget. */\n budget?: number;\n chatOptions?: ChatOptions;\n /** Injectable filesystem (defaults to a real, root-scoped fs). */\n fsImpl?: CodeFs;\n /** Injectable clock (ms) for the audit timestamp. */\n now?: () => number;\n /** Injectable correlation id (defaults to a random short id). */\n correlationId?: string;\n /** Progress callback per phase. */\n onPhase?: (phase: LifecyclePhase, detail: string) => void;\n /** Skip appending to the audit log (used by tests/dry programmatic calls). */\n noAudit?: boolean;\n /**\n * Who is making the graph-backed call, for per-model savings auditing. When\n * `client` is set, the context-assembly step (a `query_graph`-equivalent) is\n * recorded to the local savings ledger tagged with the provider + model, so\n * `vg savings` can break usage down per model. VG Code always sets this.\n */\n attribution?: { client: string; provider?: string; model?: string };\n /**\n * Use a source-bearing Task Capsule for the inspect context (Fusion Runtime\n * Phase 0 A/B). Default false keeps the metadata-only path.\n */\n capsule?: boolean;\n}\n\nexport async function runCodeSession(options: RunSessionOptions): Promise<CodeSessionResult> {\n const {\n graph,\n root,\n instruction,\n providers,\n apply = false,\n consent = false,\n files,\n budget,\n chatOptions,\n now = () => 0,\n onPhase = () => {},\n } = options;\n const fsImpl = options.fsImpl ?? nodeCodeFs(root);\n const correlationId = options.correlationId ?? shortId();\n const phasesRun: LifecyclePhase[] = [];\n const phase = (p: LifecyclePhase, detail: string): void => {\n phasesRun.push(p);\n onPhase(p, detail);\n };\n\n // ── inspect ──────────────────────────────────────────────────────────────\n phase('inspect', options.capsule ? 'building source-bearing task capsule' : 'building graph-grounded context');\n // Optional relevance provider: widens capsule seed vocabulary when\n // installed; null (the default) changes nothing.\n const relevance = await analyzeQuestion(instruction);\n const topicTags = relevance ? await loadTopicTags(graph, root) : null;\n const context = buildSessionContext(graph, instruction, {\n budget,\n files,\n capsule: options.capsule,\n root,\n fsImpl,\n relevance,\n topicTags,\n });\n\n // Per-model savings: the context build is VG Code's `query_graph`-equivalent.\n // Record it (counts only — never code or the instruction) tagged with the\n // model, so `vg savings` audits usage per model. Local-only, best-effort.\n if (options.attribution?.client) {\n const seedFiles = new Set(context.seeds.map((s) => s.node.file).filter(Boolean));\n recordCliCall(\n root,\n {\n tool: CLI_TOOL_ALIASES.ask,\n client: options.attribution.client,\n provider: options.attribution.provider,\n model: options.attribution.model,\n outcome: context.seeds.length ? 'complete' : 'miss',\n vgTokens: context.tokensEstimate,\n baselineFiles: seedFiles.size,\n },\n now(),\n );\n }\n\n // ── assess ──────────────────────────────────────────────────────────────\n phase('assess', 'asking the routed model for a minimal edit');\n const messages = buildMessages(context);\n const { result, provider, fellBack } = await complete(providers, messages, chatOptions, correlationId);\n\n const edits = parseEdits(result.text);\n const spans = spanIndex(graph);\n const applied = applyEdits(\n edits,\n (file) => fsImpl.read(file),\n (file) => spans.get(normalize(file)) ?? [],\n );\n\n const changes: FileChange[] = [];\n for (const [file, entry] of [...applied.entries()].sort((a, b) => a[0].localeCompare(b[0]))) {\n changes.push({\n file,\n before: entry.before,\n after: entry.after,\n outcomes: entry.outcomes,\n diff: unifiedDiff(entry.before, entry.after, file),\n });\n }\n\n // ── dry-run (always produced) ─────────────────────────────────────────────\n phase('dry-run', `${changes.length} file(s) would change`);\n\n const anyApplicable = changes.some((c) => c.diff !== '' && c.outcomes.some((o) => o.status === 'applied'));\n const base: CodeSessionResult = {\n instruction,\n provider: { id: provider.id, model: provider.model, local: provider.local, fellBack },\n phasesRun,\n changes,\n applied: false,\n verification: { ran: false, ok: false, detail: 'dry-run — no changes written' },\n correlationId,\n };\n\n // ── approve ───────────────────────────────────────────────────────────────\n // Writing is opt-in AND consent-gated. A requested apply without consent is\n // not an error — it degrades to a dry-run so the caller can review, then\n // re-run with --yes. This is the \"never destructive-by-default\" guardrail.\n if (!apply) {\n if (!options.noAudit) writeAudit(fsImpl, base, now());\n return base;\n }\n if (!consent) {\n const stopped = { ...base, verification: { ran: false, ok: false, detail: 'apply requested without consent — re-run with --yes to write these changes' } };\n if (!options.noAudit) writeAudit(fsImpl, stopped, now());\n return stopped;\n }\n if (!anyApplicable) {\n const nothing = { ...base, verification: { ran: false, ok: false, detail: 'nothing to write — no edit applied cleanly' } };\n if (!options.noAudit) writeAudit(fsImpl, nothing, now());\n return nothing;\n }\n phase('approve', 'consent given (--yes)');\n\n // ── execute ───────────────────────────────────────────────────────────────\n phase('execute', 'writing approved changes');\n for (const change of changes) {\n if (change.diff === '') continue; // no-op file\n if (!change.outcomes.some((o) => o.status === 'applied')) continue; // nothing applied cleanly here\n if (change.after === null) fsImpl.remove(change.file);\n else fsImpl.write(change.file, change.after);\n }\n\n // ── verify ────────────────────────────────────────────────────────────────\n phase('verify', 'confirming on-disk content matches the approved change');\n const verification = verifyWrites(fsImpl, changes);\n\n // ── log ───────────────────────────────────────────────────────────────────\n phase('log', 'recording an audit entry');\n const final: CodeSessionResult = { ...base, applied: true, verification };\n if (!options.noAudit) writeAudit(fsImpl, final, now());\n return final;\n}\n\n/**\n * Commit an already-computed dry-run result: write the cleanly-applied changes,\n * verify them on disk, and append the audit record — the \"approve → execute →\n * verify → log\" tail of the lifecycle, run against a proposal the caller has\n * already shown and had approved (the interactive REPL uses this so it never\n * calls the model twice or writes something different from what was reviewed).\n */\nexport function commitChanges(result: CodeSessionResult, fsImpl: CodeFs, now: () => number = () => 0): CodeSessionResult {\n const anyApplicable = result.changes.some((c) => c.diff !== '' && c.outcomes.some((o) => o.status === 'applied'));\n if (!anyApplicable) {\n return { ...result, applied: false, verification: { ran: false, ok: false, detail: 'nothing to write — no edit applied cleanly' } };\n }\n for (const change of result.changes) {\n if (change.diff === '' || !change.outcomes.some((o) => o.status === 'applied')) continue;\n if (change.after === null) fsImpl.remove(change.file);\n else fsImpl.write(change.file, change.after);\n }\n const verification = verifyWrites(fsImpl, result.changes);\n const final: CodeSessionResult = { ...result, applied: true, verification, phasesRun: [...result.phasesRun, 'approve', 'execute', 'verify', 'log'] };\n writeAudit(fsImpl, final, now());\n return final;\n}\n\n/**\n * Undo a set of applied changes by restoring each file's prior content — the\n * `/undo` command. A created file (before === null) is removed; an edited or\n * deleted file is restored to its `before`. Only cleanly-applied changes are\n * reverted. Returns the files it restored.\n */\nexport function undoChanges(changes: FileChange[], fsImpl: CodeFs): string[] {\n const restored: string[] = [];\n for (const ch of changes) {\n if (!ch.outcomes.some((o) => o.status === 'applied')) continue;\n if (ch.before === null) fsImpl.remove(ch.file);\n else fsImpl.write(ch.file, ch.before);\n restored.push(ch.file);\n }\n return restored;\n}\n\nfunction buildSessionContext(\n graph: VgGraph,\n instruction: string,\n opts: { budget?: number; files?: string[]; capsule?: boolean; root: string; fsImpl: CodeFs; relevance?: RelevanceAnalysis | null; topicTags?: Map<string, readonly string[]> | null },\n): CodeContext {\n const budget = opts.budget;\n const files = opts.files;\n if (!opts.capsule) {\n return buildCodeContext(graph, instruction, { budget, files, relevance: opts.relevance, topicTags: opts.topicTags });\n }\n const capsule = buildTaskCapsule(graph, instruction, {\n budget,\n files,\n readFile: (rel) => opts.fsImpl.read(rel),\n repositoryId: repositoryIdFromRoot(opts.root),\n relevance: opts.relevance,\n topicTags: opts.topicTags,\n });\n return capsuleToCodeContext(capsule);\n}\n\n/** Try each provider in order; fall back on transport failure. Throws the last actionable error. */\nasync function complete(\n providers: Provider[],\n messages: ReturnType<typeof buildMessages>,\n chatOptions: ChatOptions | undefined,\n correlationId: string,\n): Promise<{ result: ProviderResult; provider: Provider; fellBack: boolean }> {\n if (providers.length === 0) throw new Error(`no model provider available (ref ${correlationId})`);\n let lastErr: unknown;\n for (let i = 0; i < providers.length; i++) {\n const provider = providers[i];\n try {\n const result = await provider.chat(messages, { temperature: 0, ...chatOptions });\n return { result, provider, fellBack: i > 0 };\n } catch (e) {\n lastErr = e;\n }\n }\n const message = lastErr instanceof Error ? redactSecrets(lastErr.message) : String(lastErr);\n throw new Error(`${message} (ref ${correlationId})`);\n}\n\n/** Confirm each written file's on-disk content equals what we approved. */\nfunction verifyWrites(fsImpl: CodeFs, changes: FileChange[]): { ran: boolean; ok: boolean; detail: string } {\n let checked = 0;\n const mismatches: string[] = [];\n for (const change of changes) {\n if (change.diff === '' || !change.outcomes.some((o) => o.status === 'applied')) continue;\n checked++;\n const onDisk = fsImpl.read(change.file);\n if (onDisk !== change.after) mismatches.push(change.file);\n }\n if (mismatches.length) return { ran: true, ok: false, detail: `on-disk content differs for: ${mismatches.join(', ')}` };\n return { ran: true, ok: true, detail: `wrote and verified ${checked} file(s)` };\n}\n\n/** An append-only, secret-free audit record (GUARDRAILS §2.6 / §5). No file contents, no keys. */\nfunction writeAudit(fsImpl: CodeFs, r: CodeSessionResult, ts: number): void {\n const record = {\n ts,\n correlationId: r.correlationId,\n instruction: r.instruction.slice(0, 500),\n provider: r.provider.id,\n model: r.provider.model,\n local: r.provider.local,\n applied: r.applied,\n files: r.changes.map((c) => ({ file: c.file, statuses: c.outcomes.map((o) => o.status) })),\n verification: r.verification,\n phases: r.phasesRun,\n };\n try {\n fsImpl.appendAudit(JSON.stringify(record));\n } catch {\n /* audit is best-effort; never fail the run on a logging problem */\n }\n}\n\n/** Build a per-file map of symbol spans for graph-scoped edit disambiguation. */\nfunction spanIndex(graph: VgGraph): Map<string, SymbolSpan[]> {\n const map = new Map<string, SymbolSpan[]>();\n for (const n of graph.nodes) {\n if (n.kind === 'file' || n.kind === 'external') continue;\n const file = normalize(n.file);\n const list = map.get(file) ?? [];\n list.push({ qualifiedName: n.qualifiedName, file, start: n.span.start, end: n.span.end });\n map.set(file, list);\n }\n return map;\n}\n\nfunction normalize(file: string): string {\n return file.replace(/\\\\/g, '/').replace(/^\\.\\//, '');\n}\n\n/** Default filesystem impl, scoped to `root`. Refuses paths that escape the root. */\nexport function nodeCodeFs(root: string): CodeFs {\n const resolve = (file: string): string => {\n const abs = path.resolve(root, file);\n const rel = path.relative(root, abs);\n if (rel.startsWith('..') || path.isAbsolute(rel)) {\n throw new Error(`edit path escapes the project root: ${file} — refusing to touch files outside ${root}`);\n }\n return abs;\n };\n return {\n read(file) {\n try {\n return fs.readFileSync(resolve(file), 'utf8');\n } catch {\n return null;\n }\n },\n write(file, content) {\n const abs = resolve(file);\n fs.mkdirSync(path.dirname(abs), { recursive: true });\n fs.writeFileSync(abs, content);\n },\n remove(file) {\n try {\n fs.rmSync(resolve(file));\n } catch {\n /* already gone */\n }\n },\n appendAudit(line) {\n const dir = path.join(root, '.vibgrate');\n fs.mkdirSync(dir, { recursive: true });\n fs.appendFileSync(path.join(dir, 'code-audit.jsonl'), line + '\\n');\n },\n };\n}\n\n/** Short, URL-safe correlation id. Not a graph artifact, so runtime randomness is fine here. */\nfunction shortId(): string {\n let s = '';\n const alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789';\n for (let i = 0; i < 8; i++) s += alphabet[Math.floor(Math.random() * alphabet.length)];\n return s;\n}\n"]}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { loadGraphFileWithSnapshot, resolveGraphPath } from './chunk-
|
|
2
|
-
import { cacheDir } from './chunk-RBMKBYGV.js';
|
|
1
|
+
import { loadGraphFileWithSnapshot, resolveGraphPath, cacheDir } from './chunk-K5GPEWPI.js';
|
|
3
2
|
import { __require } from './chunk-Z6ZWNWWR.js';
|
|
4
3
|
import * as fs from 'fs';
|
|
5
4
|
import * as path from 'path';
|
|
@@ -199,5 +198,5 @@ function loadGraph(root, graphPath) {
|
|
|
199
198
|
}
|
|
200
199
|
|
|
201
200
|
export { SCHEMA_VERSION, loadGraph, loadGraphPreferIndex, writeGraphIndex };
|
|
202
|
-
//# sourceMappingURL=chunk-
|
|
203
|
-
//# sourceMappingURL=chunk-
|
|
201
|
+
//# sourceMappingURL=chunk-ZZNNXZYB.js.map
|
|
202
|
+
//# sourceMappingURL=chunk-ZZNNXZYB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/schema.ts","../src/engine/index-db.ts","../src/engine/load.ts"],"names":[],"mappings":"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","file":"chunk-ZZNNXZYB.js","sourcesContent":["/**\n * The `vg-graph/1.0` on-disk schema.\n *\n * This is vg's own open schema (VG-PACKAGE-AND-SCHEMA.md §4) — informed by good\n * ideas (content-hashed ids, epistemic typing of facts) but standalone and\n * self-contained. Every collection is deterministically serialized\n * (sorted keys, stable element order). These TypeScript shapes are normative.\n */\n\nexport const SCHEMA_VERSION = 'vg-graph/1.0' as const;\n\nexport type ResolverKind = 'scip' | 'stackgraph' | 'tsc' | 'heuristic';\n\n/** Coarse, honest resolution tier for an edge (see engine/epistemic.ts). */\nexport type EpistemicTier = 'observed' | 'name-matched' | 'declared';\n\n/**\n * The toolchain that produced this graph — the reproducibility fingerprint.\n * Everything here deterministically affects graph *content* (parse trees change\n * between grammar releases; resolvers change which edges resolve), so a CI run\n * and a laptop run that disagree can be caught by comparing `fingerprint`.\n * Deliberately excludes the Node/OS version so the graph stays byte-stable\n * across host runtimes; `fingerprint` pins the parse/resolve toolchain only.\n */\nexport interface Toolchain {\n schema: string; // SCHEMA_VERSION\n tool: string; // vg calendar version\n grammars: string; // tree-sitter grammar set version string\n resolvers: ResolverKind[]; // resolver kinds available, sorted\n fingerprint: string; // shortId over the fields above — the value `vg attest` signs\n}\n\nexport interface Provenance {\n tool: 'vg';\n version: string; // calendar version\n grammars: Record<string, string>; // lang → grammar version (determinism input)\n resolver: ResolverKind[];\n deep: boolean; // did the heavier open passes run\n semanticModel?: string; // embedding model id+version if --deep semantic links\n corpusHash: string; // blake3 over the included file set + hashes\n toolchain?: Toolchain; // reproducibility fingerprint (checked by `vg verify`)\n}\n\n/** Analysis cost tier — auto-selected by node count (or forced). Reported honestly. */\nexport type AnalysisTier = 'full' | 'large' | 'xl';\n\nexport interface GraphMeta {\n root: string; // relative; portable across machines\n languages: string[];\n counts: {\n nodes: number;\n edges: number;\n areas: number;\n tests: number;\n untested: number;\n };\n cluster: 'leiden' | 'louvain' | 'none';\n /** Auto-selected (or forced) analysis tier for large maps. */\n analysisTier?: AnalysisTier;\n edgeKinds: EdgeKind[];\n}\n\nexport type NodeKind =\n | 'file'\n | 'module'\n | 'package'\n | 'class'\n | 'interface'\n | 'function'\n | 'method'\n | 'property'\n | 'test'\n | 'route'\n | 'component'\n /** Documentation / config text ingested for semantic ask (markdown, txt, env examples). */\n | 'document'\n | 'external';\n\nexport interface Span {\n start: number; // 1-based start line\n end: number; // 1-based end line\n}\n\nexport interface Centrality {\n degree: number;\n pagerank: number;\n betweenness: number;\n eigenvector: number;\n}\n\nexport interface GraphNode {\n id: string; // blake3(canonical(kind, qualifiedName, file, signature))\n kind: NodeKind;\n name: string; // short name\n qualifiedName: string;\n file: string; // relative path\n span: Span; // line range (excluded from id hash)\n lang: string;\n visibility?: 'public' | 'private' | 'protected' | 'internal';\n signature?: string;\n doc?: string; // short leading doc-comment / docstring summary (deterministic; not a full body)\n importance: number; // 0..1 blended centrality\n centrality: Centrality;\n area: number; // area id (the node's community); -1 = unassigned (cluster \"none\")\n isHub: boolean; // centrality outlier — surfaced by `vg hubs`\n tested: boolean | null; // null = not analyzable (e.g. external)\n coverage?: number; // 0..1 line coverage if a coverage report was ingested\n changeCoupling?: string[]; // node ids that historically change together\n}\n\nexport type EdgeKind =\n | 'call'\n | 'import'\n | 'contains'\n | 'extends'\n | 'implements'\n | 'references'\n | 'test'\n | 'coverage';\n\nexport interface GraphEdge {\n id: string; // blake3(canonical(kind, src, dst))\n kind: EdgeKind;\n src: string; // node id\n dst: string; // node id\n resolution: ResolverKind; // how the edge was resolved\n confidence: number; // 0..1 (1.0 for scip/declared; lower for heuristic/dynamic)\n epistemic?: EpistemicTier; // coarse honesty tier derived from resolution+kind\n surprise?: number; // 0..1 improbability under the area model (`vg oddities`)\n count?: number; // call-site multiplicity\n}\n\nexport interface Area {\n id: number; // stable across runs (remapped to previous committed map)\n label: string; // most-central member's name (editable via `vg label`)\n size: number;\n members: string[]; // node ids, sorted\n cohesion: number; // 0..1\n externalEdges: number; // cross-area edge count\n}\n\nexport type FactKind = 'contract' | 'invariant' | 'characterization';\nexport type DerivedBy = 'declared' | 'static';\nexport type FactConfidence = 'Observed' | 'Derived';\n\nexport interface Fact {\n id: string; // blake3(canonical(kind, subjectIds, predicate))\n kind: FactKind;\n subjectIds: string[]; // node ids this fact constrains\n predicate: unknown; // the constraint\n derivedBy: DerivedBy;\n confidence: FactConfidence;\n evidence: { file: string; span: Span }[];\n}\n\n/**\n * A reference the graph could not resolve — surfaced by `vg unknowns`. Reporting\n * what it *cannot* connect (ranked by blast radius) is the honest inverse of a\n * scanner that hides its unknowns. Only unknowns the precise rungs (tsc/scip)\n * did not supersede are recorded, so a compiler-resolved file never shows here.\n */\nexport interface Unknown {\n from: string; // node id where the unresolved reference occurs\n name: string; // the callee/type name that could not be resolved\n kind: 'call' | 'extends' | 'implements';\n count: number; // occurrences at this site\n}\n\nexport type GroundingKind = 'should_follow' | 'smells_like' | 'relevant_to';\n\nexport interface GroundingEdge {\n src: string; // node id\n packEntryId: string;\n kind: GroundingKind;\n confidence: number; // 0..1\n rationale: 'recommended' | 'conjectured';\n citation: { title: string; url: string };\n}\n\n/** Precomputed hub blast-radius counts for fast agent answers (optional). */\nexport interface HubBlastSummary {\n id: string;\n name: string;\n kind: string;\n file: string;\n importance: number;\n direct: number;\n depth2: number;\n files: number;\n tested: boolean | null;\n}\n\nexport interface GraphSummaries {\n hubs: HubBlastSummary[];\n}\n\nexport interface VgGraph {\n schemaVersion: typeof SCHEMA_VERSION;\n generatedAt: string; // ISO; the ONLY nondeterministic field (pinned by --generated-at)\n provenance: Provenance;\n meta: GraphMeta;\n nodes: GraphNode[]; // sorted by id\n edges: GraphEdge[]; // sorted by (kind, src, dst)\n areas: Area[]; // sorted by id\n facts?: Fact[]; // open facts (contract/invariant/characterization); sorted by id\n grounding?: GroundingEdge[]; // free-pack grounding (default on; omit with --no-ground)\n unknowns?: Unknown[]; // heuristic references left unresolved; sorted by (from, kind, name)\n /** Build-time hub blast-radius summaries (always on; tiny). */\n summaries?: GraphSummaries;\n}\n","/**\n * SQLite serve index for large maps (scale past flat-JSON-only serve).\n *\n * The canonical artifact remains `graph.json` (determinism / git). The index\n * at `.vibgrate/cache/graph.db` is a derived, gitignored structure built after\n * every successful build:\n * - denormalized name/edge columns for O(log n) lookup\n * - full node/edge/area JSON for reconstructing a `VgGraph` without parsing\n * the pretty-printed graph.json (faster cold serve on XL maps)\n *\n * Uses Node's built-in `node:sqlite` (Node ≥22) — no native npm dependency.\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { cacheDir } from './cache.js';\nimport { loadGraphFileWithSnapshot } from './snapshot.js';\nimport type {\n Area,\n EpistemicTier,\n GraphEdge,\n GraphNode,\n ResolverKind,\n VgGraph,\n} from '../schema.js';\nimport { SCHEMA_VERSION } from '../schema.js';\n\nexport interface IndexWriteResult {\n path: string;\n nodes: number;\n edges: number;\n /** False when node:sqlite is unavailable — callers should not fail the build. */\n ok: boolean;\n reason?: string;\n}\n\nexport function indexDbPath(root: string): string {\n return path.join(cacheDir(root), 'graph.db');\n}\n\n/** Write (replace) the SQLite index from a built graph. Never throws to callers. */\nexport function writeGraphIndex(root: string, graph: VgGraph): IndexWriteResult {\n const file = indexDbPath(root);\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { DatabaseSync } = require('node:sqlite') as typeof import('node:sqlite');\n fs.mkdirSync(path.dirname(file), { recursive: true });\n const tmp = `${file}.${process.pid}.tmp`;\n try {\n if (fs.existsSync(tmp)) fs.unlinkSync(tmp);\n } catch {\n /* ignore */\n }\n\n const db = new DatabaseSync(tmp);\n db.exec(`\n PRAGMA journal_mode = OFF;\n PRAGMA synchronous = OFF;\n CREATE TABLE meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n CREATE TABLE nodes (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n qualified_name TEXT NOT NULL,\n kind TEXT NOT NULL,\n file TEXT NOT NULL,\n line INTEGER NOT NULL,\n importance REAL NOT NULL,\n area INTEGER NOT NULL,\n is_hub INTEGER NOT NULL,\n lang TEXT NOT NULL,\n json TEXT NOT NULL\n );\n CREATE TABLE edges (\n id TEXT PRIMARY KEY,\n kind TEXT NOT NULL,\n src TEXT NOT NULL,\n dst TEXT NOT NULL,\n resolution TEXT NOT NULL,\n confidence REAL NOT NULL,\n epistemic TEXT NOT NULL,\n json TEXT NOT NULL\n );\n CREATE TABLE areas (\n id INTEGER PRIMARY KEY,\n json TEXT NOT NULL\n );\n CREATE INDEX idx_nodes_name ON nodes(name);\n CREATE INDEX idx_nodes_qn ON nodes(qualified_name);\n CREATE INDEX idx_nodes_file ON nodes(file);\n CREATE INDEX idx_edges_src ON edges(src);\n CREATE INDEX idx_edges_dst ON edges(dst);\n CREATE INDEX idx_edges_kind ON edges(kind);\n `);\n\n const insMeta = db.prepare('INSERT INTO meta(key, value) VALUES (?, ?)');\n insMeta.run('corpusHash', graph.provenance.corpusHash);\n insMeta.run('schemaVersion', graph.schemaVersion);\n insMeta.run('generatedAt', graph.generatedAt);\n insMeta.run('nodeCount', String(graph.nodes.length));\n insMeta.run('edgeCount', String(graph.edges.length));\n insMeta.run('analysisTier', graph.meta.analysisTier ?? 'full');\n insMeta.run('indexVersion', 'vg-graph-index/2');\n // Full meta + provenance for reconstruct without graph.json parse.\n insMeta.run('graphMeta', JSON.stringify(graph.meta));\n insMeta.run('graphProvenance', JSON.stringify(graph.provenance));\n if (graph.facts) insMeta.run('factsJson', JSON.stringify(graph.facts));\n if (graph.grounding) insMeta.run('groundingJson', JSON.stringify(graph.grounding));\n if (graph.summaries) insMeta.run('summariesJson', JSON.stringify(graph.summaries));\n if (graph.unknowns) insMeta.run('unknownsJson', JSON.stringify(graph.unknowns));\n\n const insNode = db.prepare(\n `INSERT INTO nodes(id, name, qualified_name, kind, file, line, importance, area, is_hub, lang, json)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,\n );\n for (const n of graph.nodes) {\n insNode.run(\n n.id,\n n.name,\n n.qualifiedName,\n n.kind,\n n.file,\n n.span.start,\n n.importance,\n n.area,\n n.isHub ? 1 : 0,\n n.lang,\n JSON.stringify(n),\n );\n }\n\n const insEdge = db.prepare(\n `INSERT INTO edges(id, kind, src, dst, resolution, confidence, epistemic, json)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,\n );\n for (const e of graph.edges) {\n insEdge.run(\n e.id,\n e.kind,\n e.src,\n e.dst,\n e.resolution,\n e.confidence,\n e.epistemic ?? 'observed',\n JSON.stringify(e),\n );\n }\n\n const insArea = db.prepare('INSERT INTO areas(id, json) VALUES (?, ?)');\n for (const a of graph.areas) {\n insArea.run(a.id, JSON.stringify(a));\n }\n\n db.close();\n fs.renameSync(tmp, file);\n return { path: file, nodes: graph.nodes.length, edges: graph.edges.length, ok: true };\n } catch (err) {\n return {\n path: file,\n nodes: 0,\n edges: 0,\n ok: false,\n reason: (err as Error).message,\n };\n }\n}\n\nexport interface NameHit {\n id: string;\n name: string;\n qualifiedName: string;\n kind: string;\n file: string;\n line: number;\n importance: number;\n}\n\n/** Fast name / prefix lookup against the index. Empty if index missing. */\nexport function lookupNameIndex(root: string, query: string, limit = 20): NameHit[] {\n const file = indexDbPath(root);\n if (!fs.existsSync(file) || !query.trim()) return [];\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { DatabaseSync } = require('node:sqlite') as typeof import('node:sqlite');\n const db = new DatabaseSync(file, { readOnly: true });\n const q = query.trim();\n const rows = db\n .prepare(\n `SELECT id, name, qualified_name, kind, file, line, importance\n FROM nodes\n WHERE name = ? OR qualified_name = ? OR name LIKE ? OR qualified_name LIKE ?\n ORDER BY\n CASE WHEN name = ? OR qualified_name = ? THEN 0\n WHEN name LIKE ? THEN 1\n ELSE 2 END,\n importance DESC\n LIMIT ?`,\n )\n .all(q, q, `${q}%`, `%${q}%`, q, q, `${q}%`, limit) as Record<string, unknown>[];\n db.close();\n return rows.map((r) => ({\n id: String(r.id),\n name: String(r.name),\n qualifiedName: String(r.qualified_name),\n kind: String(r.kind),\n file: String(r.file),\n line: Number(r.line),\n importance: Number(r.importance),\n }));\n } catch {\n return [];\n }\n}\n\n/** Neighbor edges for a node id (src or dst). Empty if index missing. */\nexport function lookupNeighbors(\n root: string,\n nodeId: string,\n direction: 'out' | 'in' | 'both' = 'both',\n limit = 50,\n): GraphEdge[] {\n const file = indexDbPath(root);\n if (!fs.existsSync(file) || !nodeId) return [];\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { DatabaseSync } = require('node:sqlite') as typeof import('node:sqlite');\n const db = new DatabaseSync(file, { readOnly: true });\n let rows: Record<string, unknown>[] = [];\n if (direction === 'out' || direction === 'both') {\n rows = rows.concat(\n db\n .prepare(`SELECT json FROM edges WHERE src = ? LIMIT ?`)\n .all(nodeId, limit) as Record<string, unknown>[],\n );\n }\n if (direction === 'in' || direction === 'both') {\n rows = rows.concat(\n db\n .prepare(`SELECT json FROM edges WHERE dst = ? LIMIT ?`)\n .all(nodeId, limit) as Record<string, unknown>[],\n );\n }\n db.close();\n const byId = new Map<string, GraphEdge>();\n for (const r of rows) {\n try {\n const e = JSON.parse(String(r.json)) as GraphEdge;\n byId.set(e.id, e);\n } catch {\n /* skip bad row */\n }\n }\n return [...byId.values()];\n } catch {\n return [];\n }\n}\n\n/** Read index meta (corpusHash etc.) or null if missing. */\nexport function readIndexMeta(root: string): Record<string, string> | null {\n const file = indexDbPath(root);\n if (!fs.existsSync(file)) return null;\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { DatabaseSync } = require('node:sqlite') as typeof import('node:sqlite');\n const db = new DatabaseSync(file, { readOnly: true });\n const rows = db.prepare('SELECT key, value FROM meta').all() as { key: string; value: string }[];\n db.close();\n const out: Record<string, string> = {};\n for (const r of rows) out[r.key] = r.value;\n return out;\n } catch {\n return null;\n }\n}\n\n/**\n * Reconstruct a full `VgGraph` from the SQLite index (indexVersion ≥ 2).\n * Returns null if the index is missing, stale schema, or incomplete.\n * Prefer this over JSON.parse of pretty graph.json for cold serve on large maps.\n */\nexport function loadGraphFromIndex(root: string): VgGraph | null {\n const file = indexDbPath(root);\n if (!fs.existsSync(file)) return null;\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { DatabaseSync } = require('node:sqlite') as typeof import('node:sqlite');\n const db = new DatabaseSync(file, { readOnly: true });\n const metaRows = db.prepare('SELECT key, value FROM meta').all() as {\n key: string;\n value: string;\n }[];\n const meta: Record<string, string> = {};\n for (const r of metaRows) meta[r.key] = r.value;\n\n if (meta.indexVersion !== 'vg-graph-index/2' || !meta.graphMeta || !meta.graphProvenance) {\n db.close();\n return null;\n }\n\n const nodeRows = db.prepare('SELECT json FROM nodes ORDER BY id').all() as {\n json: string;\n }[];\n const edgeRows = db.prepare('SELECT json FROM edges ORDER BY id').all() as {\n json: string;\n }[];\n const areaRows = db.prepare('SELECT json FROM areas ORDER BY id').all() as {\n json: string;\n }[];\n db.close();\n\n const nodes = nodeRows.map((r) => JSON.parse(r.json) as GraphNode);\n const edges = edgeRows.map((r) => JSON.parse(r.json) as GraphEdge);\n const areas = areaRows.map((r) => JSON.parse(r.json) as Area);\n\n // Stable sorts match serialize contract (ids already ordered by SQL, re-sort for safety).\n nodes.sort((a, b) => a.id.localeCompare(b.id));\n edges.sort(\n (a, b) =>\n a.kind.localeCompare(b.kind) || a.src.localeCompare(b.src) || a.dst.localeCompare(b.dst),\n );\n areas.sort((a, b) => a.id - b.id);\n\n const graph: VgGraph = {\n schemaVersion: (meta.schemaVersion as typeof SCHEMA_VERSION) || SCHEMA_VERSION,\n generatedAt: meta.generatedAt ?? new Date(0).toISOString(),\n provenance: JSON.parse(meta.graphProvenance),\n meta: JSON.parse(meta.graphMeta),\n nodes,\n edges,\n areas,\n };\n if (meta.factsJson) graph.facts = JSON.parse(meta.factsJson);\n if (meta.groundingJson) graph.grounding = JSON.parse(meta.groundingJson);\n if (meta.summariesJson) graph.summaries = JSON.parse(meta.summariesJson);\n if (meta.unknownsJson) graph.unknowns = JSON.parse(meta.unknownsJson);\n\n // Lightweight integrity: edge resolution types stay valid.\n for (const e of edges) {\n if (!e.resolution) e.resolution = 'heuristic' as ResolverKind;\n if (!e.epistemic) e.epistemic = 'observed' as EpistemicTier;\n }\n return graph;\n } catch {\n return null;\n }\n}\n\n/**\n * Load the graph preferring the SQLite index when its corpusHash matches the\n * committed graph.json provenance (or when only the index exists). Falls back\n * to graph.json. Returns null if neither is usable.\n */\nexport function loadGraphPreferIndex(\n root: string,\n graphJsonPath: string,\n): { graph: VgGraph; source: 'index' | 'json' } | null {\n // Snapshot-first: skips the large-string JSON.parse when a fresh binary\n // snapshot exists (sidecar or store-mode standalone), and self-heals the\n // sidecar when not (see engine/snapshot.ts).\n const jsonGraph: VgGraph | null = loadGraphFileWithSnapshot(graphJsonPath);\n\n const fromIndex = loadGraphFromIndex(root);\n if (fromIndex) {\n if (!jsonGraph || fromIndex.provenance.corpusHash === jsonGraph.provenance.corpusHash) {\n return { graph: fromIndex, source: 'index' };\n }\n // Index stale vs graph.json — prefer canonical JSON and let next build refresh.\n }\n if (jsonGraph) return { graph: jsonGraph, source: 'json' };\n return null;\n}\n","import * as fs from 'node:fs';\nimport { resolveGraphPath } from './artifacts.js';\nimport { loadGraphFileWithSnapshot } from './snapshot.js';\nimport { loadGraphPreferIndex } from './index-db.js';\nimport type { VgGraph } from '../schema.js';\n\n/**\n * Load the code map for a repository.\n *\n * When `graphPath` is omitted, prefers an existing global-store snapshot, then\n * the legacy `.vibgrate/graph.json`, matching {@link resolveGraphPath}.\n * Prefers the SQLite index when its corpusHash matches the committed map\n * (faster cold serve on large repos). Returns null if none exists.\n */\nexport function loadGraph(root: string, graphPath?: string): VgGraph | null {\n const file = resolveGraphPath(root, graphPath);\n // Index is always rooted at the project root; only use it when loading the\n // default map for that root (not an arbitrary --graph path).\n if (!graphPath) {\n const preferred = loadGraphPreferIndex(root, file);\n if (preferred) return preferred.graph;\n }\n return loadGraphFileWithSnapshot(file);\n}\n"]}
|