project-athena 0.2.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +61 -12
  3. package/dist/activity-BKW7G4I5.js +77 -0
  4. package/dist/agents-DFSNEOP5.js +69 -0
  5. package/dist/ai-ASL4FFQ7.js +96 -0
  6. package/dist/analyze-ZY3MXBOI.js +50 -0
  7. package/dist/chunk-2DY4PUR4.js +465 -0
  8. package/dist/chunk-2R6PXY6Z.js +33 -0
  9. package/dist/chunk-3IS2X2Z7.js +89 -0
  10. package/dist/chunk-3XSDI5WF.js +179 -0
  11. package/dist/chunk-65TSRDQ3.js +124 -0
  12. package/dist/chunk-673EPYYH.js +105 -0
  13. package/dist/chunk-7DZK6WSQ.js +65 -0
  14. package/dist/chunk-AD4OZCU2.js +34 -0
  15. package/dist/chunk-DZDI2HRT.js +169 -0
  16. package/dist/chunk-ELKFRTZT.js +221 -0
  17. package/dist/chunk-EUPETUWA.js +14 -0
  18. package/dist/chunk-FQEGEVLY.js +38 -0
  19. package/dist/chunk-FVCDMQUQ.js +343 -0
  20. package/dist/chunk-GGXPG6OE.js +904 -0
  21. package/dist/chunk-GHFRQAYT.js +112 -0
  22. package/dist/chunk-GR4DL2VM.js +47 -0
  23. package/dist/chunk-INT3IGMQ.js +111 -0
  24. package/dist/chunk-IQQBAWSM.js +90 -0
  25. package/dist/chunk-JCGDR4UV.js +182 -0
  26. package/dist/chunk-KBO7XRBW.js +26 -0
  27. package/dist/chunk-KHMBNT66.js +399 -0
  28. package/dist/chunk-LEMPCNAY.js +209 -0
  29. package/dist/chunk-MPG3IEGB.js +2691 -0
  30. package/dist/chunk-OLPSEQS5.js +264 -0
  31. package/dist/chunk-PVCIGUIT.js +64 -0
  32. package/dist/chunk-QCC4VJUH.js +217 -0
  33. package/dist/chunk-QLW657NT.js +95 -0
  34. package/dist/chunk-RVTNSNGK.js +182 -0
  35. package/dist/chunk-RXNRMIZP.js +390 -0
  36. package/dist/chunk-SHKXELUX.js +295 -0
  37. package/dist/chunk-SJ4DQFIJ.js +379 -0
  38. package/dist/chunk-SVTEJYMS.js +227 -0
  39. package/dist/chunk-TDNZ2RYA.js +702 -0
  40. package/dist/chunk-UAZLPNVC.js +108 -0
  41. package/dist/chunk-VSYBC3VY.js +28 -0
  42. package/dist/chunk-WVQC2EGO.js +166 -0
  43. package/dist/chunk-XDCKZ5TV.js +436 -0
  44. package/dist/chunk-XFN7UZCS.js +35 -0
  45. package/dist/chunk-XW3MLHI2.js +32 -0
  46. package/dist/chunk-YRIS7ZS6.js +919 -0
  47. package/dist/chunk-Z6QWMJLK.js +124 -0
  48. package/dist/chunk-ZB7LC6FP.js +221 -0
  49. package/dist/clean-MDBYH62P.js +23 -0
  50. package/dist/cli.js +18 -10716
  51. package/dist/context-PLPCAPCO.js +161 -0
  52. package/dist/doctor-BX677KRE.js +69 -0
  53. package/dist/event-TNT6CQZR.js +101 -0
  54. package/dist/git-hook-YZNZGAAP.js +252 -0
  55. package/dist/init-WQCAOJ2R.js +38 -0
  56. package/dist/mcp-U7EPH43L.js +393 -0
  57. package/dist/memory-VSVNLEJC.js +393 -0
  58. package/dist/open-UJZRYF4E.js +1450 -0
  59. package/dist/program-CWJNGCTZ.js +165 -0
  60. package/dist/review-OOKXSYMP.js +117 -0
  61. package/dist/rules-4FXJUCXB.js +83 -0
  62. package/dist/security-LME3XFL3.js +177 -0
  63. package/dist/staged-check-X24C3YRD.js +502 -0
  64. package/dist/status-RR57ZNGI.js +81 -0
  65. package/dist/sync-KFJANRXF.js +218 -0
  66. package/dist/watch-CY7QHIYN.js +123 -0
  67. package/dist/web/assets/{Editor-DAXvniWB.js → Editor-Bnilgch0.js} +1 -1
  68. package/dist/web/assets/{abnfDiagram-O67JEVCF-Az7EW1BC.js → abnfDiagram-O67JEVCF-DW9LWr8f.js} +1 -1
  69. package/dist/web/assets/architecture-7GRP2DOG-BWDZV2yn.js +1 -0
  70. package/dist/web/assets/{architectureDiagram-NJMV4G6O-BxeXqSTn.js → architectureDiagram-NJMV4G6O-0eKeQRhj.js} +1 -1
  71. package/dist/web/assets/{blockDiagram-BEXU5L5S-aeKZl9lJ.js → blockDiagram-BEXU5L5S-D5i3-ogI.js} +1 -1
  72. package/dist/web/assets/{c4Diagram-YGBWAQC7-CgmntYsG.js → c4Diagram-YGBWAQC7-BAWQZrEu.js} +1 -1
  73. package/dist/web/assets/channel-Bkh05NKd.js +1 -0
  74. package/dist/web/assets/{chunk-3FUC2YCW-BpmRD2yo.js → chunk-3FUC2YCW-fKRGOZF3.js} +1 -1
  75. package/dist/web/assets/{chunk-5DYCD2WN-CRIFDwod.js → chunk-5DYCD2WN-C5jOlx42.js} +1 -1
  76. package/dist/web/assets/{chunk-742MDFTN-hRW9VeNV.js → chunk-742MDFTN-urY4RP_A.js} +1 -1
  77. package/dist/web/assets/{chunk-7INBJB4K-C6VEpT0Y.js → chunk-7INBJB4K-nk48sKqZ.js} +1 -1
  78. package/dist/web/assets/{chunk-7M6MHVWA-Dnajov2w.js → chunk-7M6MHVWA-BfBD9X0F.js} +1 -1
  79. package/dist/web/assets/{chunk-7PRAP22T-DSAc0_CZ.js → chunk-7PRAP22T-jYf59QlI.js} +1 -1
  80. package/dist/web/assets/{chunk-GTNCS2PH-CefpYUjb.js → chunk-GTNCS2PH-BOCxryKf.js} +1 -1
  81. package/dist/web/assets/{chunk-GWA4HPMP-MLNflMmF.js → chunk-GWA4HPMP-CFpaW0ru.js} +1 -1
  82. package/dist/web/assets/{chunk-MBY4JIJT-D3GmmEiU.js → chunk-MBY4JIJT-BIB8HctN.js} +1 -1
  83. package/dist/web/assets/{chunk-NETBCI7D-DzTj6xVk.js → chunk-NETBCI7D-CpUUK6rh.js} +1 -1
  84. package/dist/web/assets/{chunk-O7XYJQB3-D1d0hCko.js → chunk-O7XYJQB3-BNx_V4Oi.js} +1 -1
  85. package/dist/web/assets/{chunk-UA2S7LBM-C9hIFeWR.js → chunk-UA2S7LBM-D3tMiIOY.js} +1 -1
  86. package/dist/web/assets/{chunk-WEXAMYUT-BFGtcjsi.js → chunk-WEXAMYUT-CC-3C32l.js} +1 -1
  87. package/dist/web/assets/{chunk-Z7XXMR3K-BRZ8_wtE.js → chunk-Z7XXMR3K-BzhxKQUc.js} +1 -1
  88. package/dist/web/assets/{chunk-ZIGJFQKS-CTKOioal.js → chunk-ZIGJFQKS-D4tBHzxg.js} +1 -1
  89. package/dist/web/assets/{classDiagram-v2-NBCMYWYE-DJGKtWJv.js → classDiagram-v2-NBCMYWYE-BbtyanXR.js} +1 -1
  90. package/dist/web/assets/{cynefin-OW5HDTMX-hNq1kGmA.js → cynefin-OW5HDTMX-BIArb8W1.js} +1 -1
  91. package/dist/web/assets/{cynefinDiagram-VND7K2PF-sODQM_ZZ.js → cynefinDiagram-VND7K2PF-BrAcfkXL.js} +1 -1
  92. package/dist/web/assets/{dagre-6A5THRUB-DEzTThIf.js → dagre-6A5THRUB-BcHXRl4s.js} +1 -1
  93. package/dist/web/assets/{diagram-22UHCM2B-s_eellsa.js → diagram-22UHCM2B-Dx9tSCdE.js} +1 -1
  94. package/dist/web/assets/{diagram-3UASUU5V-B2onY_Xw.js → diagram-3UASUU5V-CLLDP9yH.js} +1 -1
  95. package/dist/web/assets/{diagram-ATOU4E4O-B8V6s13s.js → diagram-ATOU4E4O-B46H9iPt.js} +1 -1
  96. package/dist/web/assets/{diagram-CDSNMT55-CJxiE6mf.js → diagram-CDSNMT55-CYtvB6aG.js} +1 -1
  97. package/dist/web/assets/{diagram-MLGK6HIB-m5OHPLAp.js → diagram-MLGK6HIB-Dar7ktoX.js} +1 -1
  98. package/dist/web/assets/{diagram-MPIPVDR6-Buvvrk_A.js → diagram-MPIPVDR6-C-DljnYN.js} +1 -1
  99. package/dist/web/assets/{ebnfDiagram-ZINNZB2B-CpL7Wt3R.js → ebnfDiagram-ZINNZB2B-Dv_3jWnh.js} +1 -1
  100. package/dist/web/assets/{elk-276RUBZZ-CwYhbsXa.js → elk-276RUBZZ-DnHciE9k.js} +1 -1
  101. package/dist/web/assets/{erDiagram-OPXOYQCR-DNikci2r.js → erDiagram-OPXOYQCR-Bn46KrHz.js} +1 -1
  102. package/dist/web/assets/eventmodeling-NTZA5JFV-DYwoptMd.js +1 -0
  103. package/dist/web/assets/flowDiagram-KWPJA3E3-y4rS0gIB.js +1 -0
  104. package/dist/web/assets/{ganttDiagram-FUAMR5RP-d-ynDlvJ.js → ganttDiagram-FUAMR5RP-DOjjJtqz.js} +1 -1
  105. package/dist/web/assets/{gitGraph-4MIJSDKK-DwIeBI91.js → gitGraph-4MIJSDKK-BIoMXJRQ.js} +1 -1
  106. package/dist/web/assets/{gitGraphDiagram-X574FWY7-04RZccu6.js → gitGraphDiagram-X574FWY7-BsJ01R0v.js} +1 -1
  107. package/dist/web/assets/{index-C3-8uYXr.js → index-Cen0jOXj.js} +5 -4
  108. package/dist/web/assets/{index-DKE3ojTe.css → index-WwRY6n68.css} +1 -1
  109. package/dist/web/assets/{info-A6RAGUB7-xf4Nzgv-.js → info-A6RAGUB7-BmlXzRWj.js} +1 -1
  110. package/dist/web/assets/{infoDiagram-VRGFBTTK-BYjw0eiK.js → infoDiagram-VRGFBTTK-CYPJPmBP.js} +1 -1
  111. package/dist/web/assets/{ishikawaDiagram-OU5B5YK6-Bx9s4nPM.js → ishikawaDiagram-OU5B5YK6-YN96geky.js} +1 -1
  112. package/dist/web/assets/{journeyDiagram-ZHPQQLJL-DrdHs7B-.js → journeyDiagram-ZHPQQLJL-20juojKY.js} +1 -1
  113. package/dist/web/assets/{kanban-definition-PNTS6WVX-CVd8v2Te.js → kanban-definition-PNTS6WVX-BhCKIEbP.js} +1 -1
  114. package/dist/web/assets/{line-V_WrJ-6y.js → line-BERsMFG6.js} +1 -1
  115. package/dist/web/assets/{mermaid-parser.core-B-ilyEpO.js → mermaid-parser.core-Bis_wTB-.js} +3 -3
  116. package/dist/web/assets/{mermaid.core-Bnyaa0nF.js → mermaid.core-DMsM3ZX7.js} +4 -4
  117. package/dist/web/assets/{mindmap-definition-NLK3R4M7-B3AbvHPR.js → mindmap-definition-NLK3R4M7-BkcGdOfv.js} +1 -1
  118. package/dist/web/assets/{packet-AYTQ26CC-CBAIUXIc.js → packet-AYTQ26CC-Bh30-JJX.js} +1 -1
  119. package/dist/web/assets/{pegDiagram-GJSIUBJH-DIdeELUM.js → pegDiagram-GJSIUBJH-DxnIo9RF.js} +1 -1
  120. package/dist/web/assets/{pie-WAS4IAKB-a1r3tzPR.js → pie-WAS4IAKB-ChaTr-GD.js} +1 -1
  121. package/dist/web/assets/{pieDiagram-5QR66LMP-pQBEio0x.js → pieDiagram-5QR66LMP-CzAp78FM.js} +1 -1
  122. package/dist/web/assets/{quadrantDiagram-O4NWA36T-CkJK5Y03.js → quadrantDiagram-O4NWA36T-BDSE-cfY.js} +1 -1
  123. package/dist/web/assets/{radar-RG4KPBEZ-BZfLYjx5.js → radar-RG4KPBEZ-DgJ-o_dq.js} +1 -1
  124. package/dist/web/assets/{railroad-74A4TZTK-CuIW1ZAU.js → railroad-74A4TZTK-C8MmcBKz.js} +1 -1
  125. package/dist/web/assets/railroad-abnf-HS5TGJTU-CTLXjcdP.js +1 -0
  126. package/dist/web/assets/railroad-ebnf-LZEXJU2U-ggWsTTL0.js +1 -0
  127. package/dist/web/assets/railroad-peg-WCYAUIDC-D1mCX705.js +1 -0
  128. package/dist/web/assets/{railroadDiagram-XR7U4H2S-_BpGE8aJ.js → railroadDiagram-XR7U4H2S-DfbcWRNh.js} +1 -1
  129. package/dist/web/assets/{requirementDiagram-PLB6GJNP-CnzF90GS.js → requirementDiagram-PLB6GJNP-DM3nksxs.js} +1 -1
  130. package/dist/web/assets/{sankeyDiagram-IPEJSGJF-DYeisDj_.js → sankeyDiagram-IPEJSGJF-DthUpiiC.js} +1 -1
  131. package/dist/web/assets/{sequenceDiagram-PO4LG4MO-ll9cBvca.js → sequenceDiagram-PO4LG4MO-DLA3nuvA.js} +1 -1
  132. package/dist/web/assets/{stateDiagram-v2-GCMORJYK-CdKcOIKQ.js → stateDiagram-v2-GCMORJYK-B0X6ihBW.js} +1 -1
  133. package/dist/web/assets/{swimlanes-2SLR337P-y6piTWEW.js → swimlanes-2SLR337P-B4qWe6vE.js} +1 -1
  134. package/dist/web/assets/swimlanesDiagram-TC7HE7FX-ClIk3e7S.js +8 -0
  135. package/dist/web/assets/{timeline-definition-EJHVYXUP-DuC_4xK0.js → timeline-definition-EJHVYXUP-F-cDzYrj.js} +1 -1
  136. package/dist/web/assets/{treeView-Q6P3EWNA-gCQFmND0.js → treeView-Q6P3EWNA-BaI30nLZ.js} +1 -1
  137. package/dist/web/assets/{treemap-WGGIJYW6-BQ2010OY.js → treemap-WGGIJYW6-D2jGGoMl.js} +1 -1
  138. package/dist/web/assets/{usecaseDiagram-POWQR4AR-CCTqzHz6.js → usecaseDiagram-POWQR4AR-B9qoAQCy.js} +1 -1
  139. package/dist/web/assets/{vennDiagram-UO4OBE2U-0_O7guNq.js → vennDiagram-UO4OBE2U-DGVNOaKO.js} +1 -1
  140. package/dist/web/assets/{wardley-WFR3VGLG-SsX7uMDs.js → wardley-WFR3VGLG-DbKqhNAh.js} +1 -1
  141. package/dist/web/assets/{wardleyDiagram-VNRHLVJA-DlqH6Hox.js → wardleyDiagram-VNRHLVJA-BgZ1gprw.js} +1 -1
  142. package/dist/web/assets/{xychartDiagram-PMCCYNJV-nr4UYDtd.js → xychartDiagram-PMCCYNJV-D73RYid1.js} +1 -1
  143. package/dist/web/index.html +2 -2
  144. package/package.json +4 -2
  145. package/dist/web/assets/architecture-7GRP2DOG-blXBarB2.js +0 -1
  146. package/dist/web/assets/channel-f4QzewnN.js +0 -1
  147. package/dist/web/assets/eventmodeling-NTZA5JFV-CA_ZFPZ2.js +0 -1
  148. package/dist/web/assets/flowDiagram-KWPJA3E3-DObsBuWT.js +0 -1
  149. package/dist/web/assets/railroad-abnf-HS5TGJTU-6B4Ffbxn.js +0 -1
  150. package/dist/web/assets/railroad-ebnf-LZEXJU2U-BGL9lIQc.js +0 -1
  151. package/dist/web/assets/railroad-peg-WCYAUIDC-DcqxTem7.js +0 -1
  152. package/dist/web/assets/swimlanesDiagram-TC7HE7FX-DFS8a3jO.js +0 -8
@@ -0,0 +1,227 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ athenaDir
4
+ } from "./chunk-2DY4PUR4.js";
5
+ import {
6
+ readTextIfExists,
7
+ writeFileAtomic
8
+ } from "./chunk-IQQBAWSM.js";
9
+ import {
10
+ toPosix
11
+ } from "./chunk-XW3MLHI2.js";
12
+
13
+ // src/core/graph/graph.ts
14
+ import { z } from "zod";
15
+ import path from "path";
16
+ var NodeKind = z.enum(["package", "file", "route", "entity", "framework", "command", "infra", "doc"]);
17
+ var EdgeKind = z.enum(["contains", "imports", "handles", "defines", "depends_on", "documents", "runs"]);
18
+ var GraphNode = z.object({
19
+ id: z.string(),
20
+ kind: NodeKind,
21
+ name: z.string(),
22
+ path: z.string().optional(),
23
+ meta: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).default({})
24
+ });
25
+ var GraphEdge = z.object({ from: z.string(), to: z.string(), kind: EdgeKind });
26
+ var ProjectGraph = z.object({
27
+ schemaVersion: z.literal(1),
28
+ builtAt: z.string(),
29
+ nodes: z.array(GraphNode),
30
+ edges: z.array(GraphEdge),
31
+ stats: z.object({ nodes: z.number(), edges: z.number(), byKind: z.record(z.string(), z.number()) })
32
+ });
33
+ var GRAPH_FILE = "graph.json";
34
+ var nodeId = (kind, key) => `${kind}:${key}`;
35
+ var IMPORT_RE = /^\s*(?:import\s[^'"]*from\s*['"]([^'"]+)['"]|import\s*['"]([^'"]+)['"]|export\s[^'"]*from\s*['"]([^'"]+)['"]|(?:const|let|var)\s[^=]*=\s*require\(\s*['"]([^'"]+)['"]\s*\))/gm;
36
+ var PY_IMPORT_RE = /^\s*(?:from\s+([.\w]+)\s+import|import\s+([.\w]+))/gm;
37
+ var RESOLVE_EXTS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".py", ".vue", ".svelte"];
38
+ function resolveImport(fromFile, spec, fileSet) {
39
+ if (!spec.startsWith(".")) return null;
40
+ const base = toPosix(path.posix.normalize(path.posix.join(path.posix.dirname(fromFile), spec)));
41
+ if (fileSet.has(base)) return base;
42
+ for (const ext of RESOLVE_EXTS) {
43
+ for (const c of [`${base}${ext}`, `${base}/index${ext}`, `${base}/__init__${ext}`]) if (fileSet.has(c)) return c;
44
+ }
45
+ return null;
46
+ }
47
+ var compare = new Intl.Collator().compare;
48
+ async function buildGraph(model, opts) {
49
+ const nodes = /* @__PURE__ */ new Map();
50
+ const edges = [];
51
+ const edgeKeys = /* @__PURE__ */ new Set();
52
+ const fileSet = new Set(opts.files);
53
+ const addNode = (n) => {
54
+ if (!nodes.has(n.id)) nodes.set(n.id, n);
55
+ return n.id;
56
+ };
57
+ const addEdge = (from, to, kind) => {
58
+ if (from === to || !nodes.has(from) || !nodes.has(to)) return;
59
+ const key = `${from}\0${to}\0${kind}`;
60
+ if (edgeKeys.has(key)) return;
61
+ edgeKeys.add(key);
62
+ edges.push({ from, to, kind });
63
+ };
64
+ const fileNode = (p) => addNode({ id: nodeId("file", p), kind: "file", name: path.posix.basename(p), path: p, meta: {} });
65
+ for (const pkg of model.workspace.packages) {
66
+ addNode({ id: nodeId("package", pkg.name), kind: "package", name: pkg.name, path: pkg.path, meta: { kind: pkg.kind, ecosystem: pkg.ecosystem } });
67
+ }
68
+ for (const pkg of model.workspace.packages) {
69
+ for (const dep of pkg.internalDependencies) addEdge(nodeId("package", pkg.name), nodeId("package", dep), "depends_on");
70
+ }
71
+ const packageAtPath = /* @__PURE__ */ new Map();
72
+ for (const pkg of model.workspace.packages) if (!packageAtPath.has(pkg.path)) packageAtPath.set(pkg.path, pkg);
73
+ for (const f of model.frameworks) {
74
+ const id = addNode({ id: nodeId("framework", `${f.name}@${f.root}`), kind: "framework", name: f.name, path: f.root, meta: { category: f.category, status: f.provenance.status, confidence: f.provenance.confidence } });
75
+ const owner = packageAtPath.get(f.root);
76
+ if (owner) addEdge(nodeId("package", owner.name), id, "contains");
77
+ }
78
+ for (const r of model.routes) {
79
+ const id = addNode({ id: nodeId("route", `${r.method} ${r.path} ${r.file}`), kind: "route", name: `${r.method} ${r.path}`, path: r.file, meta: { method: r.method, framework: r.framework, ...r.line ? { line: r.line } : {} } });
80
+ addEdge(id, fileNode(r.file), "handles");
81
+ }
82
+ const entityByName = /* @__PURE__ */ new Map();
83
+ for (const x of model.dbEntities) {
84
+ const k = x.name.toLowerCase();
85
+ if (!entityByName.has(k)) entityByName.set(k, x);
86
+ }
87
+ for (const e of model.dbEntities) {
88
+ const id = addNode({ id: nodeId("entity", `${e.name}@${e.file}`), kind: "entity", name: e.name, path: e.file, meta: { kind: e.kind, fields: e.fields.length, indexes: e.indexes.length } });
89
+ addEdge(id, fileNode(e.file), "defines");
90
+ for (const rel of e.relations) {
91
+ const target = rel.split("\u2192")[1]?.trim();
92
+ const other = target ? entityByName.get(target.toLowerCase()) : void 0;
93
+ if (other) addEdge(id, nodeId("entity", `${other.name}@${other.file}`), "depends_on");
94
+ }
95
+ }
96
+ for (const e of model.entryPoints) fileNode(e.path);
97
+ for (const c of model.commands) {
98
+ const id = addNode({ id: nodeId("command", `${c.source}:${c.name}`), kind: "command", name: c.name, path: c.source, meta: { purpose: c.purpose, command: c.command.slice(0, 120) } });
99
+ addEdge(id, fileNode(c.source), "runs");
100
+ }
101
+ for (const i of model.infrastructure) addNode({ id: nodeId("infra", `${i.name}@${i.file}`), kind: "infra", name: i.name, path: i.file, meta: { kind: i.kind } });
102
+ for (const d of model.containers.dockerfiles) addNode({ id: nodeId("infra", `Dockerfile@${d.path}`), kind: "infra", name: "Dockerfile", path: d.path, meta: { kind: "container" } });
103
+ for (const s of model.containers.services) addNode({ id: nodeId("infra", `service:${s.name}@${s.file}`), kind: "infra", name: s.name, path: s.file, meta: { kind: "service", image: s.image ?? "" } });
104
+ for (const n of [...nodes.values()].filter((x) => x.kind === "file" && x.path)) {
105
+ const p = n.path;
106
+ let owner;
107
+ for (let i = p.lastIndexOf("/"); i >= 0 && !owner; i = i > 0 ? p.lastIndexOf("/", i - 1) : -1) {
108
+ const prefix = p.slice(0, i);
109
+ if (prefix !== ".") owner = packageAtPath.get(prefix);
110
+ }
111
+ if (owner) addEdge(nodeId("package", owner.name), n.id, "contains");
112
+ }
113
+ const maxImportFiles = opts.maxImportFiles ?? 2e3;
114
+ const queue = [...nodes.values()].filter((n) => n.kind === "file").map((n) => n.path);
115
+ const parsed = /* @__PURE__ */ new Set();
116
+ let head = 0;
117
+ while (head < queue.length && parsed.size < maxImportFiles) {
118
+ opts.signal?.throwIfAborted();
119
+ const p = queue[head++];
120
+ if (parsed.has(p)) continue;
121
+ parsed.add(p);
122
+ const n = { id: nodeId("file", p) };
123
+ if (!/\.(m|c)?(t|j)sx?$|\.py$/.test(p)) continue;
124
+ const text = await opts.read(p);
125
+ if (!text) continue;
126
+ const specs = [];
127
+ for (const m of text.matchAll(IMPORT_RE)) specs.push(m[1] ?? m[2] ?? m[3] ?? m[4]);
128
+ if (p.endsWith(".py")) for (const m of text.matchAll(PY_IMPORT_RE)) specs.push((m[1] ?? m[2]).replace(/\./g, "/"));
129
+ for (const spec of specs.slice(0, 200)) {
130
+ const target = resolveImport(p, spec, fileSet);
131
+ if (!target) continue;
132
+ addEdge(n.id, fileNode(target), "imports");
133
+ if (!parsed.has(target)) queue.push(target);
134
+ }
135
+ }
136
+ const byKind = {};
137
+ for (const n of nodes.values()) byKind[n.kind] = (byKind[n.kind] ?? 0) + 1;
138
+ return {
139
+ schemaVersion: 1,
140
+ builtAt: (/* @__PURE__ */ new Date()).toISOString(),
141
+ nodes: [...nodes.values()].sort((a, b) => compare(a.id, b.id)),
142
+ edges: edges.sort((a, b) => compare(a.from, b.from) || compare(a.to, b.to)),
143
+ stats: { nodes: nodes.size, edges: edges.length, byKind }
144
+ };
145
+ }
146
+ async function saveGraph(root, graph) {
147
+ await writeFileAtomic(path.join(athenaDir(root), GRAPH_FILE), `${JSON.stringify(graph, null, 2)}
148
+ `);
149
+ }
150
+ async function loadGraph(root) {
151
+ const raw = await readTextIfExists(path.join(athenaDir(root), GRAPH_FILE));
152
+ if (!raw) return null;
153
+ try {
154
+ const parsed = ProjectGraph.safeParse(JSON.parse(raw));
155
+ return parsed.success ? parsed.data : null;
156
+ } catch {
157
+ return null;
158
+ }
159
+ }
160
+ var indexes = /* @__PURE__ */ new WeakMap();
161
+ function graphIndex(graph) {
162
+ let idx = indexes.get(graph);
163
+ if (idx && idx.nodeCount === graph.nodes.length && idx.edgeCount === graph.edges.length) return idx;
164
+ const byId = /* @__PURE__ */ new Map();
165
+ for (const n of graph.nodes) byId.set(n.id, n);
166
+ const incident = /* @__PURE__ */ new Map();
167
+ const add = (id, i) => {
168
+ const list = incident.get(id);
169
+ if (!list) incident.set(id, [i]);
170
+ else if (list[list.length - 1] !== i) list.push(i);
171
+ };
172
+ graph.edges.forEach((e, i) => {
173
+ add(e.from, i);
174
+ add(e.to, i);
175
+ });
176
+ idx = { byId, incident, nodeCount: graph.nodes.length, edgeCount: graph.edges.length };
177
+ indexes.set(graph, idx);
178
+ return idx;
179
+ }
180
+ function neighbors(graph, id) {
181
+ const node = graph.nodes.find((n) => n.id === id);
182
+ if (!node) return null;
183
+ const { byId, incident } = graphIndex(graph);
184
+ const out = [];
185
+ for (const i of incident.get(id) ?? []) {
186
+ const e = graph.edges[i];
187
+ if (e.from === id && byId.has(e.to)) out.push({ edge: e, other: byId.get(e.to), direction: "out" });
188
+ else if (e.to === id && byId.has(e.from)) out.push({ edge: e, other: byId.get(e.from), direction: "in" });
189
+ }
190
+ return { node, edges: out };
191
+ }
192
+ function expandFromFiles(graph, files, depth = 1, limit = 40) {
193
+ const { byId, incident } = graphIndex(graph);
194
+ const fileSet = new Set(files);
195
+ const seed = graph.nodes.filter((n) => n.path && fileSet.has(n.path));
196
+ const seen = new Set(seed.map((n) => n.id));
197
+ let frontier = new Set(seen);
198
+ for (let d = 0; d < depth; d++) {
199
+ const touched = /* @__PURE__ */ new Set();
200
+ for (const id of frontier) for (const i of incident.get(id) ?? []) touched.add(i);
201
+ const next = /* @__PURE__ */ new Set();
202
+ for (const i of [...touched].sort((a, b) => a - b)) {
203
+ const e = graph.edges[i];
204
+ if (frontier.has(e.from) && !seen.has(e.to)) {
205
+ seen.add(e.to);
206
+ next.add(e.to);
207
+ } else if (frontier.has(e.to) && !seen.has(e.from)) {
208
+ seen.add(e.from);
209
+ next.add(e.from);
210
+ }
211
+ }
212
+ frontier = next;
213
+ if (!frontier.size) break;
214
+ }
215
+ return [...seen].map((id) => byId.get(id)).filter((n) => Boolean(n)).slice(0, limit);
216
+ }
217
+
218
+ export {
219
+ ProjectGraph,
220
+ GRAPH_FILE,
221
+ buildGraph,
222
+ saveGraph,
223
+ loadGraph,
224
+ neighbors,
225
+ expandFromFiles
226
+ };
227
+ //# sourceMappingURL=chunk-SVTEJYMS.js.map