project-athena 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +56 -0
- package/README.md +56 -4
- package/dist/{activity-P4UUFHWV.js → activity-XCHKBZTG.js} +6 -6
- package/dist/{agents-3HTSQGL2.js → agents-HUJ4JXIB.js} +6 -6
- package/dist/{ai-ASL4FFQ7.js → ai-LGTLQKL4.js} +3 -3
- package/dist/{analyze-F3YOILNL.js → analyze-AP4XJT7D.js} +10 -9
- package/dist/{chunk-ZB7LC6FP.js → chunk-3KFOI2X4.js} +2 -2
- package/dist/{chunk-PANVPNYF.js → chunk-44EGCEB2.js} +59 -251
- package/dist/{chunk-SJOOXO34.js → chunk-4FETKOY3.js} +9 -8
- package/dist/chunk-4IIBVTBS.js +76 -0
- package/dist/{chunk-LEMPCNAY.js → chunk-56EXAGTM.js} +3 -3
- package/dist/{chunk-32PRS2MG.js → chunk-6OSQMXUP.js} +5 -5
- package/dist/{chunk-OLPSEQS5.js → chunk-AKOI4VTD.js} +10 -1
- package/dist/{chunk-EF6GHOIN.js → chunk-C25FDXOO.js} +133 -23
- package/dist/{chunk-S7T6VX56.js → chunk-DH5AGULY.js} +8 -4
- package/dist/chunk-F65QINMR.js +702 -0
- package/dist/chunk-GU3ZX2J7.js +166 -0
- package/dist/chunk-GYQG4Q2N.js +108 -0
- package/dist/chunk-IDODPGTX.js +595 -0
- package/dist/chunk-KJYSNZXS.js +934 -0
- package/dist/{chunk-PR53DT7I.js → chunk-L2EHJCH4.js} +8 -8
- package/dist/{chunk-65TSRDQ3.js → chunk-P4TRQMES.js} +2 -2
- package/dist/{chunk-TGJUUB44.js → chunk-PZPMWCXS.js} +5 -5
- package/dist/chunk-QCC4VJUH.js +217 -0
- package/dist/{chunk-DOQMAZL5.js → chunk-R5AX7VST.js} +3 -3
- package/dist/{chunk-JY6BFIJJ.js → chunk-RQKGT2EK.js} +3 -3
- package/dist/{chunk-PDFQ5BFG.js → chunk-SVTEJYMS.js} +4 -155
- package/dist/{chunk-VSYBC3VY.js → chunk-UMWX4UTK.js} +2 -2
- package/dist/{chunk-RXNRMIZP.js → chunk-WUIC65QO.js} +2 -2
- package/dist/{chunk-JCGDR4UV.js → chunk-WWQ5NKEC.js} +3 -1
- package/dist/{chunk-XB66PZ6Z.js → chunk-X7EYOAEX.js} +2 -2
- package/dist/chunk-Y6SDMZET.js +278 -0
- package/dist/{chunk-2RS6TA3D.js → chunk-YRIS7ZS6.js} +28 -17
- package/dist/{clean-S7PKCOLM.js → clean-LQOG56AM.js} +4 -4
- package/dist/cli.js +2 -2
- package/dist/{context-AH5MFHRG.js → context-G5YHY3L2.js} +24 -10
- package/dist/{doctor-RSJMLE2P.js → doctor-L34QJ7WR.js} +17 -10
- package/dist/{event-TNT6CQZR.js → event-6YW6TGFI.js} +3 -3
- package/dist/{git-hook-YZNZGAAP.js → git-hook-Y7Y262F7.js} +2 -2
- package/dist/{init-2V34DVRQ.js → init-427QR5AS.js} +10 -9
- package/dist/{mcp-T2GRTEX5.js → mcp-DWNWRGJW.js} +196 -21
- package/dist/memory-XBZCYQLW.js +393 -0
- package/dist/{open-2QSZKKUG.js → open-LJMOB6U2.js} +262 -69
- package/dist/{program-V2USHGXN.js → program-DCP526LU.js} +63 -32
- package/dist/{review-R3R2J5BJ.js → review-VEJBPACX.js} +14 -11
- package/dist/{rules-4FXJUCXB.js → rules-M4DLLXBL.js} +4 -4
- package/dist/scan-JVKCVHPD.js +939 -0
- package/dist/{security-PI4LXCOB.js → security-JTJN3E7K.js} +15 -11
- package/dist/{staged-check-HHIBKKMR.js → staged-check-PQSLGQBW.js} +15 -13
- package/dist/{status-6M73WX5I.js → status-PO27BSOZ.js} +10 -4
- package/dist/{sync-3ZNJDSSU.js → sync-GVO2VHPI.js} +14 -12
- package/dist/{watch-USN5CQIV.js → watch-TEHFO47V.js} +14 -12
- package/dist/web/assets/{Editor-BI56-HX5.js → Editor-Bnilgch0.js} +1 -1
- package/dist/web/assets/{abnfDiagram-O67JEVCF-y_9px2ob.js → abnfDiagram-O67JEVCF-DW9LWr8f.js} +1 -1
- package/dist/web/assets/architecture-7GRP2DOG-BWDZV2yn.js +1 -0
- package/dist/web/assets/{architectureDiagram-NJMV4G6O-lB6fcVzU.js → architectureDiagram-NJMV4G6O-0eKeQRhj.js} +1 -1
- package/dist/web/assets/{blockDiagram-BEXU5L5S-DcM5pEjM.js → blockDiagram-BEXU5L5S-D5i3-ogI.js} +1 -1
- package/dist/web/assets/{c4Diagram-YGBWAQC7-CJgqxTY2.js → c4Diagram-YGBWAQC7-BAWQZrEu.js} +1 -1
- package/dist/web/assets/channel-Bkh05NKd.js +1 -0
- package/dist/web/assets/{chunk-3FUC2YCW-B8l_VuWR.js → chunk-3FUC2YCW-fKRGOZF3.js} +1 -1
- package/dist/web/assets/{chunk-5DYCD2WN-CZecgNhf.js → chunk-5DYCD2WN-C5jOlx42.js} +1 -1
- package/dist/web/assets/{chunk-742MDFTN-BeZ7P5jB.js → chunk-742MDFTN-urY4RP_A.js} +1 -1
- package/dist/web/assets/{chunk-7INBJB4K-IKy0pr5m.js → chunk-7INBJB4K-nk48sKqZ.js} +1 -1
- package/dist/web/assets/{chunk-7M6MHVWA-Dg_QqJEX.js → chunk-7M6MHVWA-BfBD9X0F.js} +1 -1
- package/dist/web/assets/{chunk-7PRAP22T-DqQNS8oq.js → chunk-7PRAP22T-jYf59QlI.js} +1 -1
- package/dist/web/assets/{chunk-GTNCS2PH-x4sM51nJ.js → chunk-GTNCS2PH-BOCxryKf.js} +1 -1
- package/dist/web/assets/{chunk-GWA4HPMP-CE5GcwVN.js → chunk-GWA4HPMP-CFpaW0ru.js} +1 -1
- package/dist/web/assets/{chunk-MBY4JIJT-DA_D1hjF.js → chunk-MBY4JIJT-BIB8HctN.js} +1 -1
- package/dist/web/assets/{chunk-NETBCI7D-CeJ3XBZ2.js → chunk-NETBCI7D-CpUUK6rh.js} +1 -1
- package/dist/web/assets/{chunk-O7XYJQB3-BH2gESvO.js → chunk-O7XYJQB3-BNx_V4Oi.js} +1 -1
- package/dist/web/assets/{chunk-UA2S7LBM-BWr0xCux.js → chunk-UA2S7LBM-D3tMiIOY.js} +1 -1
- package/dist/web/assets/{chunk-WEXAMYUT-B4QwUZPM.js → chunk-WEXAMYUT-CC-3C32l.js} +1 -1
- package/dist/web/assets/{chunk-Z7XXMR3K-BxcA-y5B.js → chunk-Z7XXMR3K-BzhxKQUc.js} +1 -1
- package/dist/web/assets/{chunk-ZIGJFQKS-BZYvP63G.js → chunk-ZIGJFQKS-D4tBHzxg.js} +1 -1
- package/dist/web/assets/{classDiagram-v2-NBCMYWYE-BS3P_NXb.js → classDiagram-v2-NBCMYWYE-BbtyanXR.js} +1 -1
- package/dist/web/assets/{cynefin-OW5HDTMX-BALD4Pve.js → cynefin-OW5HDTMX-BIArb8W1.js} +1 -1
- package/dist/web/assets/{cynefinDiagram-VND7K2PF-BM2y4W6d.js → cynefinDiagram-VND7K2PF-BrAcfkXL.js} +1 -1
- package/dist/web/assets/{dagre-6A5THRUB-PTfOrIdF.js → dagre-6A5THRUB-BcHXRl4s.js} +1 -1
- package/dist/web/assets/{diagram-22UHCM2B-CpXEHhUl.js → diagram-22UHCM2B-Dx9tSCdE.js} +1 -1
- package/dist/web/assets/{diagram-3UASUU5V-DPHfXzr6.js → diagram-3UASUU5V-CLLDP9yH.js} +1 -1
- package/dist/web/assets/{diagram-ATOU4E4O-DMBNXvAC.js → diagram-ATOU4E4O-B46H9iPt.js} +1 -1
- package/dist/web/assets/{diagram-CDSNMT55-CDLe1M7G.js → diagram-CDSNMT55-CYtvB6aG.js} +1 -1
- package/dist/web/assets/{diagram-MLGK6HIB-D6L8oE7j.js → diagram-MLGK6HIB-Dar7ktoX.js} +1 -1
- package/dist/web/assets/{diagram-MPIPVDR6-CP-S7rrQ.js → diagram-MPIPVDR6-C-DljnYN.js} +1 -1
- package/dist/web/assets/{ebnfDiagram-ZINNZB2B-CkUc63TK.js → ebnfDiagram-ZINNZB2B-Dv_3jWnh.js} +1 -1
- package/dist/web/assets/{elk-276RUBZZ-C1CAJLH_.js → elk-276RUBZZ-DnHciE9k.js} +1 -1
- package/dist/web/assets/{erDiagram-OPXOYQCR-DXBnaTHm.js → erDiagram-OPXOYQCR-Bn46KrHz.js} +1 -1
- package/dist/web/assets/eventmodeling-NTZA5JFV-DYwoptMd.js +1 -0
- package/dist/web/assets/flowDiagram-KWPJA3E3-y4rS0gIB.js +1 -0
- package/dist/web/assets/{ganttDiagram-FUAMR5RP-BVm8SiGg.js → ganttDiagram-FUAMR5RP-DOjjJtqz.js} +1 -1
- package/dist/web/assets/{gitGraph-4MIJSDKK-Dm7xBrW0.js → gitGraph-4MIJSDKK-BIoMXJRQ.js} +1 -1
- package/dist/web/assets/{gitGraphDiagram-X574FWY7-D_PIKKhx.js → gitGraphDiagram-X574FWY7-BsJ01R0v.js} +1 -1
- package/dist/web/assets/{index-CeOIBpu2.js → index-Cen0jOXj.js} +5 -4
- package/dist/web/assets/{index-DKE3ojTe.css → index-WwRY6n68.css} +1 -1
- package/dist/web/assets/{info-A6RAGUB7-CLGrx8pn.js → info-A6RAGUB7-BmlXzRWj.js} +1 -1
- package/dist/web/assets/{infoDiagram-VRGFBTTK-BlBjaKm7.js → infoDiagram-VRGFBTTK-CYPJPmBP.js} +1 -1
- package/dist/web/assets/{ishikawaDiagram-OU5B5YK6-Kxe7GGS3.js → ishikawaDiagram-OU5B5YK6-YN96geky.js} +1 -1
- package/dist/web/assets/{journeyDiagram-ZHPQQLJL-wCMoHK4M.js → journeyDiagram-ZHPQQLJL-20juojKY.js} +1 -1
- package/dist/web/assets/{kanban-definition-PNTS6WVX-BxdCz9Ko.js → kanban-definition-PNTS6WVX-BhCKIEbP.js} +1 -1
- package/dist/web/assets/{line-Zf11FnWF.js → line-BERsMFG6.js} +1 -1
- package/dist/web/assets/{mermaid-parser.core-BvFFklev.js → mermaid-parser.core-Bis_wTB-.js} +3 -3
- package/dist/web/assets/{mermaid.core-Cd_Ssti9.js → mermaid.core-DMsM3ZX7.js} +4 -4
- package/dist/web/assets/{mindmap-definition-NLK3R4M7-BGPQl-GY.js → mindmap-definition-NLK3R4M7-BkcGdOfv.js} +1 -1
- package/dist/web/assets/{packet-AYTQ26CC-6lI3cEX_.js → packet-AYTQ26CC-Bh30-JJX.js} +1 -1
- package/dist/web/assets/{pegDiagram-GJSIUBJH-BPIjlSAj.js → pegDiagram-GJSIUBJH-DxnIo9RF.js} +1 -1
- package/dist/web/assets/{pie-WAS4IAKB-D6Dzj3Ja.js → pie-WAS4IAKB-ChaTr-GD.js} +1 -1
- package/dist/web/assets/{pieDiagram-5QR66LMP-DtA-vZmv.js → pieDiagram-5QR66LMP-CzAp78FM.js} +1 -1
- package/dist/web/assets/{quadrantDiagram-O4NWA36T-EettyqQn.js → quadrantDiagram-O4NWA36T-BDSE-cfY.js} +1 -1
- package/dist/web/assets/{radar-RG4KPBEZ-xmRc3Dl8.js → radar-RG4KPBEZ-DgJ-o_dq.js} +1 -1
- package/dist/web/assets/{railroad-74A4TZTK-BLB7dhOn.js → railroad-74A4TZTK-C8MmcBKz.js} +1 -1
- package/dist/web/assets/railroad-abnf-HS5TGJTU-CTLXjcdP.js +1 -0
- package/dist/web/assets/railroad-ebnf-LZEXJU2U-ggWsTTL0.js +1 -0
- package/dist/web/assets/railroad-peg-WCYAUIDC-D1mCX705.js +1 -0
- package/dist/web/assets/{railroadDiagram-XR7U4H2S-PBw4We6b.js → railroadDiagram-XR7U4H2S-DfbcWRNh.js} +1 -1
- package/dist/web/assets/{requirementDiagram-PLB6GJNP-DjQpaUFA.js → requirementDiagram-PLB6GJNP-DM3nksxs.js} +1 -1
- package/dist/web/assets/{sankeyDiagram-IPEJSGJF-CBW-_AoF.js → sankeyDiagram-IPEJSGJF-DthUpiiC.js} +1 -1
- package/dist/web/assets/{sequenceDiagram-PO4LG4MO-DEoPYqY9.js → sequenceDiagram-PO4LG4MO-DLA3nuvA.js} +1 -1
- package/dist/web/assets/{stateDiagram-v2-GCMORJYK-UZq5rPud.js → stateDiagram-v2-GCMORJYK-B0X6ihBW.js} +1 -1
- package/dist/web/assets/{swimlanes-2SLR337P-CACfuXJR.js → swimlanes-2SLR337P-B4qWe6vE.js} +1 -1
- package/dist/web/assets/swimlanesDiagram-TC7HE7FX-ClIk3e7S.js +8 -0
- package/dist/web/assets/{timeline-definition-EJHVYXUP-CYJl7mP-.js → timeline-definition-EJHVYXUP-F-cDzYrj.js} +1 -1
- package/dist/web/assets/{treeView-Q6P3EWNA-DtZ5nkPQ.js → treeView-Q6P3EWNA-BaI30nLZ.js} +1 -1
- package/dist/web/assets/{treemap-WGGIJYW6-m49GDM-M.js → treemap-WGGIJYW6-D2jGGoMl.js} +1 -1
- package/dist/web/assets/{usecaseDiagram-POWQR4AR-C2Vg20UK.js → usecaseDiagram-POWQR4AR-B9qoAQCy.js} +1 -1
- package/dist/web/assets/{vennDiagram-UO4OBE2U-C07v5OGI.js → vennDiagram-UO4OBE2U-DGVNOaKO.js} +1 -1
- package/dist/web/assets/{wardley-WFR3VGLG-C9Z7EZtz.js → wardley-WFR3VGLG-DbKqhNAh.js} +1 -1
- package/dist/web/assets/{wardleyDiagram-VNRHLVJA-DdA8CcSC.js → wardleyDiagram-VNRHLVJA-BgZ1gprw.js} +1 -1
- package/dist/web/assets/{xychartDiagram-PMCCYNJV-C9EZw07b.js → xychartDiagram-PMCCYNJV-D73RYid1.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +3 -1
- package/dist/chunk-CXUTYCZX.js +0 -238
- package/dist/chunk-LMOFZNTQ.js +0 -379
- package/dist/web/assets/architecture-7GRP2DOG-DyxkwYiW.js +0 -1
- package/dist/web/assets/channel-BvDD7AMO.js +0 -1
- package/dist/web/assets/eventmodeling-NTZA5JFV-cLIzvgDp.js +0 -1
- package/dist/web/assets/flowDiagram-KWPJA3E3-D7Zq63VQ.js +0 -1
- package/dist/web/assets/railroad-abnf-HS5TGJTU-DBFym6g8.js +0 -1
- package/dist/web/assets/railroad-ebnf-LZEXJU2U-CkG28ig8.js +0 -1
- package/dist/web/assets/railroad-peg-WCYAUIDC-Df_Ifaad.js +0 -1
- package/dist/web/assets/swimlanesDiagram-TC7HE7FX-CDSrqdgx.js +0 -8
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
SCAN_FILE,
|
|
4
|
+
SecurityScan
|
|
5
|
+
} from "./chunk-44EGCEB2.js";
|
|
6
|
+
import {
|
|
7
|
+
GRAPH_FILE,
|
|
8
|
+
ProjectGraph
|
|
9
|
+
} from "./chunk-SVTEJYMS.js";
|
|
10
|
+
import {
|
|
11
|
+
ProjectModel
|
|
12
|
+
} from "./chunk-QCC4VJUH.js";
|
|
13
|
+
import {
|
|
14
|
+
athenaDir,
|
|
15
|
+
readState
|
|
16
|
+
} from "./chunk-2DY4PUR4.js";
|
|
17
|
+
import {
|
|
18
|
+
AthenaError
|
|
19
|
+
} from "./chunk-AD4OZCU2.js";
|
|
20
|
+
|
|
21
|
+
// src/services/project-session.ts
|
|
22
|
+
import { promises as fs } from "fs";
|
|
23
|
+
import path from "path";
|
|
24
|
+
var fileKey = (st) => `${st.ino}:${st.size}:${st.mtimeNs}`;
|
|
25
|
+
var ProjectSession = class {
|
|
26
|
+
constructor(root) {
|
|
27
|
+
this.root = root;
|
|
28
|
+
}
|
|
29
|
+
root;
|
|
30
|
+
cache = /* @__PURE__ */ new Map();
|
|
31
|
+
inflight = /* @__PURE__ */ new Map();
|
|
32
|
+
stateEntry = null;
|
|
33
|
+
get dir() {
|
|
34
|
+
return athenaDir(this.root);
|
|
35
|
+
}
|
|
36
|
+
/** model.json, or why it can't be used. */
|
|
37
|
+
readModel() {
|
|
38
|
+
return this.read("model.json", ProjectModel);
|
|
39
|
+
}
|
|
40
|
+
/** The parsed model, or null when missing or unusable. */
|
|
41
|
+
async model() {
|
|
42
|
+
const r = await this.readModel();
|
|
43
|
+
return r.kind === "ok" ? r.value : null;
|
|
44
|
+
}
|
|
45
|
+
/** The parsed model; throws an AthenaError with a hint when it is missing or corrupted. */
|
|
46
|
+
async requireModel() {
|
|
47
|
+
const r = await this.readModel();
|
|
48
|
+
if (r.kind === "ok") return r.value;
|
|
49
|
+
if (r.kind === "missing") throw new AthenaError("model.json is missing.", "Run `athena analyze` (or re-analyze from the overview) first.");
|
|
50
|
+
throw new AthenaError(`model.json is corrupted (${r.reason}).`, "Run `athena analyze` to rebuild it.");
|
|
51
|
+
}
|
|
52
|
+
/** Cheap existence check (a stat, no parsing). */
|
|
53
|
+
async hasModel() {
|
|
54
|
+
return this.exists("model.json");
|
|
55
|
+
}
|
|
56
|
+
readGraph() {
|
|
57
|
+
return this.read(GRAPH_FILE, ProjectGraph);
|
|
58
|
+
}
|
|
59
|
+
async graph() {
|
|
60
|
+
const r = await this.readGraph();
|
|
61
|
+
return r.kind === "ok" ? r.value : null;
|
|
62
|
+
}
|
|
63
|
+
readScan() {
|
|
64
|
+
return this.read(SCAN_FILE, SecurityScan);
|
|
65
|
+
}
|
|
66
|
+
async scan() {
|
|
67
|
+
const r = await this.readScan();
|
|
68
|
+
return r.kind === "ok" ? r.value : null;
|
|
69
|
+
}
|
|
70
|
+
/** state.json via `readState`, memoized like the other artifacts. */
|
|
71
|
+
async state() {
|
|
72
|
+
const file = path.join(this.dir, "state.json");
|
|
73
|
+
const st = await fs.stat(file, { bigint: true }).catch(() => null);
|
|
74
|
+
if (!st) return readState(this.dir);
|
|
75
|
+
const key = fileKey(st);
|
|
76
|
+
if (this.stateEntry?.key === key) return this.stateEntry.state;
|
|
77
|
+
const state = await readState(this.dir);
|
|
78
|
+
const after = await fs.stat(file, { bigint: true }).catch(() => null);
|
|
79
|
+
if (after && fileKey(after) === key) this.stateEntry = { key, state };
|
|
80
|
+
return state;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Record a value this process just wrote to `.athena/<name>`, so the next
|
|
84
|
+
* read doesn't parse it again. The file must already be on disk.
|
|
85
|
+
*/
|
|
86
|
+
async remember(name, value) {
|
|
87
|
+
const st = await fs.stat(path.join(this.dir, name), { bigint: true }).catch(() => null);
|
|
88
|
+
if (st) this.cache.set(name, { key: fileKey(st), result: { kind: "ok", value } });
|
|
89
|
+
else this.cache.delete(name);
|
|
90
|
+
}
|
|
91
|
+
/** Drop memoized results (all, or one file). */
|
|
92
|
+
invalidate(name) {
|
|
93
|
+
if (!name || name === "state.json") this.stateEntry = null;
|
|
94
|
+
if (name) this.cache.delete(name);
|
|
95
|
+
else this.cache.clear();
|
|
96
|
+
}
|
|
97
|
+
async exists(name) {
|
|
98
|
+
const st = await fs.stat(path.join(this.dir, name)).catch(() => null);
|
|
99
|
+
return Boolean(st?.isFile());
|
|
100
|
+
}
|
|
101
|
+
read(name, schema) {
|
|
102
|
+
const running = this.inflight.get(name);
|
|
103
|
+
if (running) return running;
|
|
104
|
+
const p = this.load(name, schema).finally(() => this.inflight.delete(name));
|
|
105
|
+
this.inflight.set(name, p);
|
|
106
|
+
return p;
|
|
107
|
+
}
|
|
108
|
+
async load(name, schema) {
|
|
109
|
+
const file = path.join(this.dir, name);
|
|
110
|
+
let st;
|
|
111
|
+
try {
|
|
112
|
+
st = await fs.stat(file, { bigint: true });
|
|
113
|
+
} catch (err) {
|
|
114
|
+
const code = err.code;
|
|
115
|
+
this.cache.delete(name);
|
|
116
|
+
if (code === "ENOENT" || code === "ENOTDIR") return { kind: "missing" };
|
|
117
|
+
return { kind: "corrupted", reason: `unreadable (${code})` };
|
|
118
|
+
}
|
|
119
|
+
const key = fileKey(st);
|
|
120
|
+
const hit = this.cache.get(name);
|
|
121
|
+
if (hit?.key === key) return hit.result;
|
|
122
|
+
let raw;
|
|
123
|
+
try {
|
|
124
|
+
raw = await fs.readFile(file, "utf8");
|
|
125
|
+
} catch (err) {
|
|
126
|
+
const code = err.code;
|
|
127
|
+
if (code === "ENOENT") return { kind: "missing" };
|
|
128
|
+
return { kind: "corrupted", reason: `unreadable (${code})` };
|
|
129
|
+
}
|
|
130
|
+
const result = parseArtifact(raw, schema);
|
|
131
|
+
const after = await fs.stat(file, { bigint: true }).catch(() => null);
|
|
132
|
+
if (after && fileKey(after) === key) this.cache.set(name, { key, result });
|
|
133
|
+
return result;
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
function parseArtifact(raw, schema) {
|
|
137
|
+
let json;
|
|
138
|
+
try {
|
|
139
|
+
json = JSON.parse(raw);
|
|
140
|
+
} catch {
|
|
141
|
+
return { kind: "corrupted", reason: "invalid JSON" };
|
|
142
|
+
}
|
|
143
|
+
const parsed = schema.safeParse(json);
|
|
144
|
+
if (parsed.success) return { kind: "ok", value: parsed.data };
|
|
145
|
+
const issue = parsed.error.issues[0];
|
|
146
|
+
return { kind: "corrupted", reason: `schema mismatch at ${issue?.path.map(String).join(".") || "(root)"}: ${issue?.message}` };
|
|
147
|
+
}
|
|
148
|
+
var sessions = /* @__PURE__ */ new Map();
|
|
149
|
+
function projectSession(root) {
|
|
150
|
+
const key = path.resolve(root);
|
|
151
|
+
let s = sessions.get(key);
|
|
152
|
+
if (!s) {
|
|
153
|
+
s = new ProjectSession(key);
|
|
154
|
+
sessions.set(key, s);
|
|
155
|
+
}
|
|
156
|
+
return s;
|
|
157
|
+
}
|
|
158
|
+
function releaseProjectSession(root) {
|
|
159
|
+
sessions.delete(path.resolve(root));
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export {
|
|
163
|
+
projectSession,
|
|
164
|
+
releaseProjectSession
|
|
165
|
+
};
|
|
166
|
+
//# sourceMappingURL=chunk-GU3ZX2J7.js.map
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
CONTEXT_MEMORY_LIMIT,
|
|
4
|
+
documentSections,
|
|
5
|
+
listMemory,
|
|
6
|
+
recall,
|
|
7
|
+
selectContext
|
|
8
|
+
} from "./chunk-F65QINMR.js";
|
|
9
|
+
import {
|
|
10
|
+
projectSession
|
|
11
|
+
} from "./chunk-GU3ZX2J7.js";
|
|
12
|
+
import {
|
|
13
|
+
analyzeProject
|
|
14
|
+
} from "./chunk-44EGCEB2.js";
|
|
15
|
+
import {
|
|
16
|
+
GRAPH_FILE,
|
|
17
|
+
buildGraph,
|
|
18
|
+
saveGraph
|
|
19
|
+
} from "./chunk-SVTEJYMS.js";
|
|
20
|
+
import {
|
|
21
|
+
KNOWLEDGE_DOCS
|
|
22
|
+
} from "./chunk-FQEGEVLY.js";
|
|
23
|
+
import {
|
|
24
|
+
athenaDir
|
|
25
|
+
} from "./chunk-2DY4PUR4.js";
|
|
26
|
+
import {
|
|
27
|
+
readTextIfExists
|
|
28
|
+
} from "./chunk-IQQBAWSM.js";
|
|
29
|
+
import {
|
|
30
|
+
AthenaError
|
|
31
|
+
} from "./chunk-AD4OZCU2.js";
|
|
32
|
+
|
|
33
|
+
// src/services/context.ts
|
|
34
|
+
import path from "path";
|
|
35
|
+
async function refreshGraph(root, opts = {}) {
|
|
36
|
+
const session = projectSession(root);
|
|
37
|
+
const st = await session.state();
|
|
38
|
+
const analysis = await analyzeProject(root, { signal: opts.signal });
|
|
39
|
+
const files = analysis.files.map((f) => f.path);
|
|
40
|
+
const graph = await buildGraph(analysis.model, {
|
|
41
|
+
files,
|
|
42
|
+
signal: opts.signal,
|
|
43
|
+
read: async (rel) => readTextIfExists(path.join(root, rel)).catch(() => null)
|
|
44
|
+
});
|
|
45
|
+
await saveGraph(root, graph);
|
|
46
|
+
await session.remember(GRAPH_FILE, graph);
|
|
47
|
+
return graph;
|
|
48
|
+
}
|
|
49
|
+
async function getGraph(root, opts = {}) {
|
|
50
|
+
const existing = await projectSession(root).graph();
|
|
51
|
+
if (existing) return existing;
|
|
52
|
+
return opts.build ? refreshGraph(root, { signal: opts.signal }) : null;
|
|
53
|
+
}
|
|
54
|
+
async function getRelevantContext(root, task, opts = {}) {
|
|
55
|
+
if (!task.trim()) throw new AthenaError("Describe the task to get relevant context.", 'For example: athena context "add refunds to the payments API"');
|
|
56
|
+
const dir = athenaDir(root);
|
|
57
|
+
const documents = [];
|
|
58
|
+
for (const d of KNOWLEDGE_DOCS) {
|
|
59
|
+
if (d.id === "rules") continue;
|
|
60
|
+
const text = await readTextIfExists(path.join(dir, d.file));
|
|
61
|
+
if (text) documents.push({ id: d.id, file: d.file, sections: documentSections(text) });
|
|
62
|
+
}
|
|
63
|
+
if (!documents.length) throw new AthenaError("No knowledge documents found.", "Run `athena init` first.", 3);
|
|
64
|
+
return selectContext({
|
|
65
|
+
task,
|
|
66
|
+
documents,
|
|
67
|
+
rulesMarkdown: await readTextIfExists(path.join(dir, "rules.md")),
|
|
68
|
+
graph: await getGraph(root, { build: opts.buildGraph, signal: opts.signal }),
|
|
69
|
+
maxChars: opts.maxChars,
|
|
70
|
+
memories: await memoriesFor(root, task)
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
async function memoriesFor(root, task, files = []) {
|
|
74
|
+
let hits;
|
|
75
|
+
try {
|
|
76
|
+
hits = recall(await listMemory(root), { task, files, limit: CONTEXT_MEMORY_LIMIT * 2 });
|
|
77
|
+
} catch {
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
const rank = (s) => s === "confirmed" ? 0 : 1;
|
|
81
|
+
return hits.map((h, i) => ({ h, i })).sort((a, b) => rank(a.h.entry.status) - rank(b.h.entry.status) || a.i - b.i).slice(0, CONTEXT_MEMORY_LIMIT).map(({ h: { entry: e, why } }) => ({
|
|
82
|
+
id: e.id,
|
|
83
|
+
kind: e.kind,
|
|
84
|
+
status: e.status === "confirmed" ? "confirmed" : "unreviewed",
|
|
85
|
+
label: e.label,
|
|
86
|
+
stale: e.stale,
|
|
87
|
+
changedFiles: e.changedFiles,
|
|
88
|
+
source: e.source,
|
|
89
|
+
title: e.title,
|
|
90
|
+
details: e.details,
|
|
91
|
+
files: e.files,
|
|
92
|
+
evidence: e.evidence,
|
|
93
|
+
why
|
|
94
|
+
}));
|
|
95
|
+
}
|
|
96
|
+
async function graphSummary(root) {
|
|
97
|
+
const session = projectSession(root);
|
|
98
|
+
const [graph, hasModel] = await Promise.all([session.graph(), session.hasModel()]);
|
|
99
|
+
return { built: Boolean(graph), builtAt: graph?.builtAt ?? null, stats: graph?.stats ?? null, model: { hasModel } };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export {
|
|
103
|
+
refreshGraph,
|
|
104
|
+
getGraph,
|
|
105
|
+
getRelevantContext,
|
|
106
|
+
graphSummary
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=chunk-GYQG4Q2N.js.map
|