@plebeiantech/lat.md 0.12.3-fork.13 → 0.12.3-fork.14
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/README.md +24 -0
- package/dist/src/cli/check-context.d.ts +56 -0
- package/dist/src/cli/check-context.js +215 -0
- package/dist/src/cli/check-coverage.js +9 -5
- package/dist/src/cli/check-frontmatter.js +1 -1
- package/dist/src/cli/check-mode.js +1 -1
- package/dist/src/cli/check-status.js +1 -1
- package/dist/src/cli/check.d.ts +19 -12
- package/dist/src/cli/check.js +259 -206
- package/dist/src/cli/context.js +1 -1
- package/dist/src/cli/expand.d.ts +1 -2
- package/dist/src/cli/expand.js +52 -5
- package/dist/src/cli/external.d.ts +11 -0
- package/dist/src/cli/external.js +185 -0
- package/dist/src/cli/fork-instructions.d.ts +1 -0
- package/dist/src/cli/fork-instructions.js +3 -2
- package/dist/src/cli/hook.d.ts +26 -0
- package/dist/src/cli/hook.js +112 -40
- package/dist/src/cli/index.js +55 -3
- package/dist/src/cli/init.d.ts +1 -0
- package/dist/src/cli/init.js +40 -2
- package/dist/src/cli/locate.js +4 -3
- package/dist/src/cli/refs.d.ts +2 -1
- package/dist/src/cli/refs.js +88 -43
- package/dist/src/cli/reindex.js +2 -1
- package/dist/src/cli/search.d.ts +12 -3
- package/dist/src/cli/search.js +45 -49
- package/dist/src/cli/section.d.ts +3 -1
- package/dist/src/cli/section.js +114 -38
- package/dist/src/code-refs.d.ts +17 -5
- package/dist/src/code-refs.js +246 -65
- package/dist/src/context.d.ts +3 -0
- package/dist/src/document-formats.d.ts +7 -0
- package/dist/src/document-formats.js +39 -0
- package/dist/src/extensions/alert-marker.d.ts +25 -0
- package/dist/src/extensions/alert-marker.js +55 -0
- package/dist/src/external-documents.d.ts +56 -0
- package/dist/src/external-documents.js +404 -0
- package/dist/src/external-sources.d.ts +136 -0
- package/dist/src/external-sources.js +1098 -0
- package/dist/src/fork/antigravity-hook.d.ts +47 -0
- package/dist/src/fork/antigravity-hook.js +424 -0
- package/dist/src/fork/antigravity-init.d.ts +17 -0
- package/dist/src/fork/antigravity-init.js +124 -0
- package/dist/src/fork/frontmatter-fields.d.ts +36 -0
- package/dist/src/fork/frontmatter-fields.js +23 -0
- package/dist/src/format.d.ts +5 -2
- package/dist/src/format.js +8 -3
- package/dist/src/graph-export.js +1 -1
- package/dist/src/lattice-model.d.ts +77 -0
- package/dist/src/lattice-model.js +464 -0
- package/dist/src/lattice.d.ts +9 -104
- package/dist/src/lattice.js +69 -516
- package/dist/src/markdown-analysis-cache.d.ts +20 -0
- package/dist/src/markdown-analysis-cache.js +139 -0
- package/dist/src/markdown-analysis-worker.d.ts +16 -0
- package/dist/src/markdown-analysis-worker.js +33 -0
- package/dist/src/markdown-analysis.d.ts +50 -0
- package/dist/src/markdown-analysis.js +139 -0
- package/dist/src/markdown-analyzer-loader.d.ts +4 -0
- package/dist/src/markdown-analyzer-loader.js +13 -0
- package/dist/src/markdown-validation.d.ts +25 -0
- package/dist/src/markdown-validation.js +104 -0
- package/dist/src/mcp/server.js +27 -11
- package/dist/src/parser-cache.d.ts +17 -0
- package/dist/src/parser-cache.js +65 -0
- package/dist/src/parser-import.d.ts +8 -0
- package/dist/src/parser-import.js +1 -0
- package/dist/src/parser.js +80 -5
- package/dist/src/path.d.ts +2 -0
- package/dist/src/path.js +4 -0
- package/dist/src/profiler.d.ts +16 -0
- package/dist/src/profiler.js +81 -0
- package/dist/src/project-analysis.d.ts +59 -0
- package/dist/src/project-analysis.js +233 -0
- package/dist/src/project-discovery.d.ts +6 -0
- package/dist/src/project-discovery.js +30 -0
- package/dist/src/repository-path.d.ts +11 -0
- package/dist/src/repository-path.js +52 -0
- package/dist/src/search/db.d.ts +1 -1
- package/dist/src/search/db.js +2 -2
- package/dist/src/search/embedder.d.ts +2 -1
- package/dist/src/search/embedder.js +6 -5
- package/dist/src/search/index.d.ts +2 -1
- package/dist/src/search/index.js +10 -8
- package/dist/src/search/query.d.ts +20 -0
- package/dist/src/search/query.js +67 -0
- package/dist/src/search/search.d.ts +3 -1
- package/dist/src/search/search.js +5 -2
- package/dist/src/source-formats.d.ts +7 -0
- package/dist/src/source-formats.js +26 -0
- package/dist/src/source-parser.d.ts +44 -4
- package/dist/src/source-parser.js +494 -57
- package/dist/src/view/client/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/dist/src/view/client/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/dist/src/view/client/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/dist/src/view/client/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/dist/src/view/client/assets/MarkdownEditor-B7quqPb8.js +28 -0
- package/dist/src/view/client/assets/OrbitControls-DwcpQNja.js +1 -0
- package/dist/src/view/client/assets/STLLoader-CLWTKt5i.js +1 -0
- package/dist/src/view/client/assets/abnfDiagram-VCTEODGH-V7-T6qsl.js +1 -0
- package/dist/src/view/client/assets/arc-BnwR8Bu7.js +1 -0
- package/dist/src/view/client/assets/architectureDiagram-5GKGNRK7-u97vDna9.js +36 -0
- package/dist/src/view/client/assets/blockDiagram-I7D4REHJ-DETl8e_H.js +129 -0
- package/dist/src/view/client/assets/c4Diagram-7LVT6UL2-DJRAT1Ve.js +38 -0
- package/dist/src/view/client/assets/channel-BwQbnWCN.js +1 -0
- package/dist/src/view/client/assets/chunk-2Q5K7J3B-C0TmOC1Q.js +1 -0
- package/dist/src/view/client/assets/chunk-5VM5RSS4-dfBOrYE6.js +15 -0
- package/dist/src/view/client/assets/chunk-F27PBJKO-DAnks99K.js +1 -0
- package/dist/src/view/client/assets/chunk-IMKFNOWR-CPjB07if.js +231 -0
- package/dist/src/view/client/assets/chunk-JWPE2WC7-VvU_gZI6.js +1 -0
- package/dist/src/view/client/assets/chunk-POPQ4Y6H-DDUbVF55.js +1 -0
- package/dist/src/view/client/assets/chunk-SVP7TREG-BHROkr6D.js +88 -0
- package/dist/src/view/client/assets/chunk-TICWLB2K-95PzGIOg.js +206 -0
- package/dist/src/view/client/assets/chunk-XXDRQBXY-MdmuLhIs.js +1 -0
- package/dist/src/view/client/assets/classDiagram-ZZMXUADV-HvQKkIS-.js +1 -0
- package/dist/src/view/client/assets/classDiagram-v2-VYDZK3BY-HvQKkIS-.js +1 -0
- package/dist/src/view/client/assets/cose-bilkent-JH36ORCC-CauUf_rN.js +1 -0
- package/dist/src/view/client/assets/cynefin-OW5HDTMX-CeA8IKWo.js +166 -0
- package/dist/src/view/client/assets/cynefinDiagram-5FMLGOSQ-L1rtcT8l.js +62 -0
- package/dist/src/view/client/assets/cytoscape.esm-DzSz-X2X.js +321 -0
- package/dist/src/view/client/assets/dagre-GXQ25YYZ-DLQwTa3H.js +4 -0
- package/dist/src/view/client/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/dist/src/view/client/assets/diagram-S7CK7UJ4-kbKdIyXG.js +30 -0
- package/dist/src/view/client/assets/diagram-UQ7AKVKN-kmzp92RC.js +41 -0
- package/dist/src/view/client/assets/diagram-VSXAHHWV-EXJTU8qq.js +3 -0
- package/dist/src/view/client/assets/diagram-VX7I27RA-DAiIyMCG.js +24 -0
- package/dist/src/view/client/assets/diagram-Z3DM3KII-G9wz50ZV.js +24 -0
- package/dist/src/view/client/assets/ebnfDiagram-PWID7BFC-D2tVRCNA.js +1 -0
- package/dist/src/view/client/assets/erDiagram-RLTQ6QDP-C925J5A3.js +99 -0
- package/dist/src/view/client/assets/flowDiagram-HODETNUW-DzoCa-Nq.js +168 -0
- package/dist/src/view/client/assets/ganttDiagram-EL5Y4UJY-D2ebbg4p.js +292 -0
- package/dist/src/view/client/assets/gitGraphDiagram-WWUBYQGX-B4QratYy.js +106 -0
- package/dist/src/view/client/assets/index-BnENo9bV.js +1 -0
- package/dist/src/view/client/assets/index-D0ajr_Ja.css +1 -0
- package/dist/src/view/client/assets/index-KZcnpXJH.js +321 -0
- package/dist/src/view/client/assets/infoDiagram-27XIBGKW-DL4mtHkt.js +2 -0
- package/dist/src/view/client/assets/init-Gi6I4Gst.js +1 -0
- package/dist/src/view/client/assets/ishikawaDiagram-5VMMS53U-CW4mto2d.js +70 -0
- package/dist/src/view/client/assets/journeyDiagram-3NMN7TZE-8R4eacFW.js +139 -0
- package/dist/src/view/client/assets/kanban-definition-UXKFOSKX-Cy9ioXEJ.js +89 -0
- package/dist/src/view/client/assets/katex-HP8lGamR.js +257 -0
- package/dist/src/view/client/assets/layout-C0MFuhth.js +1 -0
- package/dist/src/view/client/assets/linear-Dv3N4dQR.js +1 -0
- package/dist/src/view/client/assets/logo-small-RR_KBOAT.svg +149 -0
- package/dist/src/view/client/assets/maplibre-gl-DnqZgfUS.js +800 -0
- package/dist/src/view/client/assets/mermaid.core-bds9A7e2.js +310 -0
- package/dist/src/view/client/assets/mindmap-definition-YA3MSWOX-DjmGW355.js +96 -0
- package/dist/src/view/client/assets/ordinal-Cboi1Yqb.js +1 -0
- package/dist/src/view/client/assets/pegDiagram-XKGWAZYB-BWsZp0ab.js +1 -0
- package/dist/src/view/client/assets/pieDiagram-E7YTZNPT-CCH2gGR-.js +39 -0
- package/dist/src/view/client/assets/quadrantDiagram-AXDQQJYC-CjocPJFz.js +7 -0
- package/dist/src/view/client/assets/railroadDiagram-O6MQD6OU-BjLeb2KF.js +1 -0
- package/dist/src/view/client/assets/requirementDiagram-BXWQKSXE-Ct6AoXRr.js +84 -0
- package/dist/src/view/client/assets/sankeyDiagram-P5KCCOFB-CIpgGN_w.js +40 -0
- package/dist/src/view/client/assets/sequenceDiagram-WJ2MYXX4-DrmLFj6w.js +162 -0
- package/dist/src/view/client/assets/sizeCapture-INFHLROL-BdFMe2Lr.js +1 -0
- package/dist/src/view/client/assets/stateDiagram-D77RDMKH-Zd9F1goW.js +1 -0
- package/dist/src/view/client/assets/stateDiagram-v2-MP3YSRHH-ByIKCftl.js +1 -0
- package/dist/src/view/client/assets/swimlanes-42K2YHIH-a7VFwi00.js +1 -0
- package/dist/src/view/client/assets/swimlanesDiagram-VR7AAH4N-CzxaUHB-.js +8 -0
- package/dist/src/view/client/assets/three.module-PDSP0dbZ.js +4108 -0
- package/dist/src/view/client/assets/timeline-definition-24CTP7MA-BExPu6X5.js +120 -0
- package/dist/src/view/client/assets/vennDiagram-4TSXK5OY-PC1MU3si.js +34 -0
- package/dist/src/view/client/assets/wardleyDiagram-VM6X3IG4-DNWqU3fa.js +78 -0
- package/dist/src/view/client/assets/xychartDiagram-S5SC5T6Z-E1uA28_D.js +7 -0
- package/dist/src/view/client/index.html +2 -2
- package/dist/src/view/client-shell.d.ts +2 -0
- package/dist/src/view/client-shell.js +5 -0
- package/dist/src/view/diagnostics.d.ts +3 -2
- package/dist/src/view/diagnostics.js +49 -58
- package/dist/src/view/document-edit.d.ts +8 -0
- package/dist/src/view/document-edit.js +25 -0
- package/dist/src/view/document-route.d.ts +12 -0
- package/dist/src/view/document-route.js +93 -0
- package/dist/src/view/document-tree.d.ts +18 -0
- package/dist/src/view/document-tree.js +139 -0
- package/dist/src/view/external-document-tree.d.ts +3 -0
- package/dist/src/view/external-document-tree.js +674 -0
- package/dist/src/view/git-diff.js +187 -0
- package/dist/src/view/git.js +1 -1
- package/dist/src/view/graph.d.ts +3 -2
- package/dist/src/view/graph.js +94 -7
- package/dist/src/view/highlight.d.ts +10 -2
- package/dist/src/view/highlight.js +4540 -1360
- package/dist/src/view/markdown.d.ts +3 -2
- package/dist/src/view/markdown.js +214 -53
- package/dist/src/view/protocol.d.ts +59 -6
- package/dist/src/view/references.d.ts +10 -25
- package/dist/src/view/references.js +117 -107
- package/dist/src/view/repository.d.ts +13 -3
- package/dist/src/view/repository.js +234 -15
- package/dist/src/view/search.d.ts +1 -1
- package/dist/src/view/search.js +3 -7
- package/dist/src/view/server.d.ts +11 -2
- package/dist/src/view/server.js +212 -70
- package/dist/src/view/source-target.js +5 -8
- package/dist/src/view/static-build.d.ts +1 -0
- package/dist/src/view/static-build.js +245 -42
- package/dist/src/view/static-protocol.d.ts +19 -2
- package/dist/src/view/store.d.ts +16 -3
- package/dist/src/view/store.js +228 -36
- package/dist/src/view/table-of-contents.d.ts +2 -2
- package/dist/src/view/table-of-contents.js +2 -22
- package/dist/src/walk.d.ts +5 -3
- package/dist/src/walk.js +102 -8
- package/package.json +46 -8
- package/plugins/lat-md/README.md +61 -0
- package/plugins/lat-md/hooks.json +38 -0
- package/plugins/lat-md/plugin.json +9 -0
- package/plugins/lat-md/rules/AGENTS.md +118 -0
- package/plugins/lat-md/skills/lat-md/SKILL.md +178 -0
- package/plugins/lat-md/skills/lat-md-conventions/SKILL.md +182 -0
- package/templates/AGENTS.md +15 -3
- package/templates/cursor-rules.md +12 -3
- package/templates/skill/SKILL.md +22 -1
- package/dist/src/view/client/assets/index-C3iaZyYT.css +0 -1
- package/dist/src/view/client/assets/index-KWi67IMz.js +0 -334
- package/dist/src/view/client/assets/logo-CNF8zs47.svg +0 -182
package/dist/src/cli/index.js
CHANGED
|
@@ -8,6 +8,7 @@ import { dirname, join } from 'node:path';
|
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
9
9
|
import { Command, InvalidArgumentError } from 'commander';
|
|
10
10
|
import { resolveCheckContext, resolveContext } from './context.js';
|
|
11
|
+
import { DEFAULT_SEARCH_LIMIT, DEFAULT_SEARCH_THRESHOLD, } from '../search/search.js';
|
|
11
12
|
function parsePort(value) {
|
|
12
13
|
if (!/^\d+$/.test(value)) {
|
|
13
14
|
throw new InvalidArgumentError('port must be an integer from 1 to 65535');
|
|
@@ -18,6 +19,13 @@ function parsePort(value) {
|
|
|
18
19
|
}
|
|
19
20
|
return port;
|
|
20
21
|
}
|
|
22
|
+
function parseSimilarityThreshold(value) {
|
|
23
|
+
const threshold = Number(value);
|
|
24
|
+
if (!Number.isFinite(threshold) || threshold < 0 || threshold > 1) {
|
|
25
|
+
throw new InvalidArgumentError('threshold must be a number from 0 to 1');
|
|
26
|
+
}
|
|
27
|
+
return threshold;
|
|
28
|
+
}
|
|
21
29
|
/** Reserve `-- <directory>` for an explicit check target. */
|
|
22
30
|
function splitCheckTarget(args) {
|
|
23
31
|
let commandIndex = -1;
|
|
@@ -138,15 +146,53 @@ program
|
|
|
138
146
|
const { refsCommand } = await import('./refs.js');
|
|
139
147
|
handleResult(await refsCommand(ctx, query, scope));
|
|
140
148
|
});
|
|
149
|
+
const external = program
|
|
150
|
+
.command('external')
|
|
151
|
+
.description('Manage pinned external source repositories');
|
|
152
|
+
external
|
|
153
|
+
.command('add')
|
|
154
|
+
.argument('[handle]', 'stable external source handle')
|
|
155
|
+
.argument('[repo]', 'canonical HTTPS Git repository')
|
|
156
|
+
.option('--commit <commit-or-ref>', 'commit, branch, or tag to pin')
|
|
157
|
+
.option('--prefix <path>', 'repository path prefix')
|
|
158
|
+
.option('--default-file-extension <extension>', 'extension for external paths that omit one')
|
|
159
|
+
.option('--strategy <strategy>', 'retrieval strategy: fetch or checkout')
|
|
160
|
+
.option('--fetch-url <template>', 'raw-file URL template')
|
|
161
|
+
.action(async (handle, repo, opts) => {
|
|
162
|
+
const ctx = resolveContext(program.opts());
|
|
163
|
+
const { externalAddCommand } = await import('./external.js');
|
|
164
|
+
handleResult(await externalAddCommand(ctx, handle, repo, opts));
|
|
165
|
+
});
|
|
166
|
+
external
|
|
167
|
+
.command('show')
|
|
168
|
+
.argument('<source>', 'handle or exact external target')
|
|
169
|
+
.option('--json', 'emit structured JSON')
|
|
170
|
+
.action(async (source, opts) => {
|
|
171
|
+
const ctx = resolveContext(program.opts());
|
|
172
|
+
const { externalShowCommand } = await import('./external.js');
|
|
173
|
+
handleResult(await externalShowCommand(ctx, source, !!opts.json));
|
|
174
|
+
});
|
|
175
|
+
external
|
|
176
|
+
.command('list')
|
|
177
|
+
.option('--json', 'emit structured JSON')
|
|
178
|
+
.action(async (opts) => {
|
|
179
|
+
const ctx = resolveContext(program.opts());
|
|
180
|
+
const { externalListCommand } = await import('./external.js');
|
|
181
|
+
handleResult(await externalListCommand(ctx, !!opts.json));
|
|
182
|
+
});
|
|
141
183
|
const check = program
|
|
142
184
|
.command('check')
|
|
143
185
|
.usage('[subcommand] [-- <directory>]')
|
|
144
186
|
.description('Validate markdown, links, code references, and structure')
|
|
145
187
|
.option('--fix', 'generate/update directory index files from frontmatter')
|
|
188
|
+
.option('--profile', 'show detailed validation timing')
|
|
146
189
|
.action(async (opts) => {
|
|
147
190
|
const ctx = resolveCheckContext(program.opts(), checkTargetArgs.target);
|
|
148
191
|
const { checkAllCommand } = await import('./check.js');
|
|
149
|
-
handleResult(await checkAllCommand(ctx, {
|
|
192
|
+
handleResult(await checkAllCommand(ctx, {
|
|
193
|
+
fix: opts.fix,
|
|
194
|
+
profile: !!opts.profile,
|
|
195
|
+
}));
|
|
150
196
|
});
|
|
151
197
|
check
|
|
152
198
|
.command('md')
|
|
@@ -258,12 +304,18 @@ program
|
|
|
258
304
|
.command('search')
|
|
259
305
|
.description('Semantic search across lat.md sections')
|
|
260
306
|
.argument('[query]', 'search query in plain English')
|
|
261
|
-
.option('--limit <n>',
|
|
307
|
+
.option('--limit <n>', `max results (default: ${DEFAULT_SEARCH_LIMIT})`, String(DEFAULT_SEARCH_LIMIT))
|
|
308
|
+
.option('--debug', 'show result similarity scores')
|
|
309
|
+
.option('--threshold <score>', `minimum cosine similarity score (default: ${DEFAULT_SEARCH_THRESHOLD})`, parseSimilarityThreshold)
|
|
262
310
|
.action(async (query, opts) => {
|
|
263
311
|
const ctx = resolveContext(program.opts());
|
|
264
312
|
const { searchCommand, cliProgress } = await import('./search.js');
|
|
265
313
|
const progress = cliProgress(ctx.styler);
|
|
266
|
-
const result = await searchCommand(ctx, query, {
|
|
314
|
+
const result = await searchCommand(ctx, query, {
|
|
315
|
+
limit: parseInt(opts.limit),
|
|
316
|
+
debug: opts.debug,
|
|
317
|
+
threshold: opts.threshold,
|
|
318
|
+
}, progress);
|
|
267
319
|
handleResult(result);
|
|
268
320
|
});
|
|
269
321
|
program
|
package/dist/src/cli/init.d.ts
CHANGED
|
@@ -5,5 +5,6 @@ type LatCommandStyle = 'global' | 'local' | 'npx';
|
|
|
5
5
|
*/
|
|
6
6
|
export declare function syncLatHooks(settingsPath: string, style: LatCommandStyle, agent?: 'claude' | 'codex'): void;
|
|
7
7
|
export declare function readLogo(): string;
|
|
8
|
+
export declare function ensureLatLocalConfigIgnored(latDir: string): void;
|
|
8
9
|
export declare function initCmd(targetDir?: string): Promise<void>;
|
|
9
10
|
export {};
|
package/dist/src/cli/init.js
CHANGED
|
@@ -17,6 +17,7 @@ import { selectMenu } from './select-menu.js';
|
|
|
17
17
|
import { checklistMenu } from './checklist-menu.js';
|
|
18
18
|
import { writeForkInstructions } from './fork-instructions.js';
|
|
19
19
|
import { offerRequireMode, writeForkScaffold } from './fork-scaffold.js';
|
|
20
|
+
import { setupAntigravity } from '../fork/antigravity-init.js';
|
|
20
21
|
async function confirm(rl, message) {
|
|
21
22
|
while (true) {
|
|
22
23
|
let answer;
|
|
@@ -819,6 +820,7 @@ function printNextSteps(selectedAgents) {
|
|
|
819
820
|
pi: 'Pi',
|
|
820
821
|
opencode: 'OpenCode',
|
|
821
822
|
codex: 'Codex',
|
|
823
|
+
antigravity: 'Antigravity',
|
|
822
824
|
};
|
|
823
825
|
if (!hasClaudeCode && ideAgents.length === 0)
|
|
824
826
|
return;
|
|
@@ -841,6 +843,15 @@ function printNextSteps(selectedAgents) {
|
|
|
841
843
|
export function readLogo() {
|
|
842
844
|
return readFileSync(join(findTemplatesDir(), 'logo.txt'), 'utf-8');
|
|
843
845
|
}
|
|
846
|
+
export function ensureLatLocalConfigIgnored(latDir) {
|
|
847
|
+
const path = join(latDir, '.gitignore');
|
|
848
|
+
const entry = 'config.local.yaml';
|
|
849
|
+
const current = existsSync(path) ? readFileSync(path, 'utf8') : '';
|
|
850
|
+
if (current.split(/\r?\n/).includes(entry))
|
|
851
|
+
return;
|
|
852
|
+
const prefix = current && !current.endsWith('\n') ? `${current}\n` : current;
|
|
853
|
+
writeFileSync(path, `${prefix}${entry}\n`);
|
|
854
|
+
}
|
|
844
855
|
export async function initCmd(targetDir) {
|
|
845
856
|
console.log(styleText('cyan', readLogo()));
|
|
846
857
|
// Upfront version check — let the user upgrade before proceeding
|
|
@@ -904,6 +915,7 @@ export async function initCmd(targetDir) {
|
|
|
904
915
|
console.log(styleText('green', 'Created lat.md/'));
|
|
905
916
|
writeForkScaffold(latDir);
|
|
906
917
|
}
|
|
918
|
+
ensureLatLocalConfigIgnored(latDir);
|
|
907
919
|
// Step 2: Configure fresh/outdated setups, ask interactive users about an
|
|
908
920
|
// available key, and offer to rebuild an index whose backend differs. This
|
|
909
921
|
// happens before agent selection so "no agents" still completes it.
|
|
@@ -917,6 +929,7 @@ export async function initCmd(targetDir) {
|
|
|
917
929
|
{ label: 'VS Code Copilot', value: 'copilot' },
|
|
918
930
|
{ label: 'OpenCode', value: 'opencode' },
|
|
919
931
|
{ label: 'Codex', value: 'codex' },
|
|
932
|
+
{ label: 'Antigravity / Gemini', value: 'antigravity' },
|
|
920
933
|
];
|
|
921
934
|
const selectedAgents = await checklistMenu(allAgents, 'Which coding agents do you use?');
|
|
922
935
|
const useClaudeCode = selectedAgents.includes('claude');
|
|
@@ -925,13 +938,15 @@ export async function initCmd(targetDir) {
|
|
|
925
938
|
const useCopilot = selectedAgents.includes('copilot');
|
|
926
939
|
const useOpenCode = selectedAgents.includes('opencode');
|
|
927
940
|
const useCodex = selectedAgents.includes('codex');
|
|
941
|
+
const useAntigravity = selectedAgents.includes('antigravity');
|
|
928
942
|
const anySelected = selectedAgents.length > 0;
|
|
929
943
|
const needsLatCommand = useClaudeCode ||
|
|
930
944
|
usePi ||
|
|
931
945
|
useCursor ||
|
|
932
946
|
useCopilot ||
|
|
933
947
|
useOpenCode ||
|
|
934
|
-
useCodex
|
|
948
|
+
useCodex ||
|
|
949
|
+
useAntigravity;
|
|
935
950
|
// Step 4: How should agents run lat?
|
|
936
951
|
let commandStyle = 'local';
|
|
937
952
|
if (anySelected && needsLatCommand && interactive) {
|
|
@@ -973,7 +988,12 @@ export async function initCmd(targetDir) {
|
|
|
973
988
|
const template = readAgentsTemplate();
|
|
974
989
|
const fileHashes = {};
|
|
975
990
|
// Step 5: AGENTS.md (shared by non-Claude agents)
|
|
976
|
-
const needsAgentsMd = usePi ||
|
|
991
|
+
const needsAgentsMd = usePi ||
|
|
992
|
+
useCursor ||
|
|
993
|
+
useCopilot ||
|
|
994
|
+
useOpenCode ||
|
|
995
|
+
useCodex ||
|
|
996
|
+
useAntigravity;
|
|
977
997
|
if (needsAgentsMd) {
|
|
978
998
|
await setupAgentsMd(root, latDir, template, fileHashes, ask);
|
|
979
999
|
}
|
|
@@ -1008,6 +1028,24 @@ export async function initCmd(targetDir) {
|
|
|
1008
1028
|
console.log(styleText('bold', 'Setting up Codex...'));
|
|
1009
1029
|
await setupCodex(root, latDir, fileHashes, ask, commandStyle);
|
|
1010
1030
|
}
|
|
1031
|
+
if (useAntigravity) {
|
|
1032
|
+
console.log('');
|
|
1033
|
+
console.log(styleText('bold', 'Setting up Antigravity / Gemini...'));
|
|
1034
|
+
await setupAntigravity({
|
|
1035
|
+
root,
|
|
1036
|
+
latDir,
|
|
1037
|
+
template,
|
|
1038
|
+
hashes: fileHashes,
|
|
1039
|
+
ask,
|
|
1040
|
+
style: commandStyle,
|
|
1041
|
+
latBin: latBinString(commandStyle),
|
|
1042
|
+
appendTemplateSection,
|
|
1043
|
+
writeTemplateFile,
|
|
1044
|
+
ensureGitignored,
|
|
1045
|
+
hasMcpServer,
|
|
1046
|
+
addMcpServer,
|
|
1047
|
+
});
|
|
1048
|
+
}
|
|
1011
1049
|
await writeForkInstructions(root, latDir, fileHashes, ask);
|
|
1012
1050
|
// Record init version and file hashes so `lat check` can detect stale setups
|
|
1013
1051
|
writeInitMeta(latDir, fileHashes);
|
package/dist/src/cli/locate.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { findSections } from '../lattice-model.js';
|
|
2
2
|
import { formatResultList } from '../format.js';
|
|
3
|
+
import { commandProjectAnalysis } from '../project-analysis.js';
|
|
3
4
|
export async function locateCommand(ctx, query) {
|
|
4
5
|
const stripped = query.replace(/^\[\[|\]\]$/g, '');
|
|
5
|
-
const
|
|
6
|
-
const matches = findSections(
|
|
6
|
+
const project = await commandProjectAnalysis(ctx);
|
|
7
|
+
const matches = findSections(project.allSections, stripped);
|
|
7
8
|
if (matches.length === 0) {
|
|
8
9
|
const s = ctx.styler;
|
|
9
10
|
return {
|
package/dist/src/cli/refs.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Section, type SectionMatch } from '../lattice.js';
|
|
1
|
+
import { type Section, type SectionMatch } from '../lattice-model.js';
|
|
2
2
|
import type { CmdContext, CmdResult } from '../context.js';
|
|
3
3
|
export type Scope = 'md' | 'code' | 'md+code';
|
|
4
4
|
export type RefsFound = {
|
|
@@ -10,6 +10,7 @@ export type RefsFound = {
|
|
|
10
10
|
export type RefsError = {
|
|
11
11
|
kind: 'no-match';
|
|
12
12
|
suggestions: SectionMatch[];
|
|
13
|
+
message?: string;
|
|
13
14
|
};
|
|
14
15
|
export type RefsResult = RefsFound | RefsError;
|
|
15
16
|
/**
|
package/dist/src/cli/refs.js
CHANGED
|
@@ -1,21 +1,9 @@
|
|
|
1
|
-
import { readFile } from 'node:fs/promises';
|
|
2
1
|
import { existsSync } from 'node:fs';
|
|
3
2
|
import { extname, join, relative } from 'node:path';
|
|
4
|
-
import {
|
|
3
|
+
import { findSections, resolveRef, } from '../lattice-model.js';
|
|
5
4
|
import { formatResultList } from '../format.js';
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
const SOURCE_EXTS = new Set([
|
|
9
|
-
'.ts',
|
|
10
|
-
'.tsx',
|
|
11
|
-
'.js',
|
|
12
|
-
'.jsx',
|
|
13
|
-
'.py',
|
|
14
|
-
'.rs',
|
|
15
|
-
'.go',
|
|
16
|
-
'.c',
|
|
17
|
-
'.h',
|
|
18
|
-
]);
|
|
5
|
+
import { commandProjectAnalysis, commandProjectSession, } from '../project-analysis.js';
|
|
6
|
+
import { isSourceFileExtension } from '../source-formats.js';
|
|
19
7
|
/**
|
|
20
8
|
* Check if a query looks like a source file path (has a recognized extension
|
|
21
9
|
* and the file exists on disk).
|
|
@@ -25,7 +13,7 @@ function isSourceQuery(query, projectRoot) {
|
|
|
25
13
|
const filePart = hashIdx === -1 ? query : query.slice(0, hashIdx);
|
|
26
14
|
const symbolPart = hashIdx === -1 ? '' : query.slice(hashIdx + 1);
|
|
27
15
|
const ext = extname(filePart);
|
|
28
|
-
if (!
|
|
16
|
+
if (!isSourceFileExtension(ext))
|
|
29
17
|
return null;
|
|
30
18
|
if (!existsSync(join(projectRoot, filePart)))
|
|
31
19
|
return null;
|
|
@@ -36,7 +24,8 @@ function isSourceQuery(query, projectRoot) {
|
|
|
36
24
|
* For file-level queries (no #symbol), matches all wiki links targeting
|
|
37
25
|
* that file or any symbol in it.
|
|
38
26
|
*/
|
|
39
|
-
async function findSourceRefs(
|
|
27
|
+
async function findSourceRefs(ctx, query, scope) {
|
|
28
|
+
const { projectRoot } = ctx;
|
|
40
29
|
const hashIdx = query.indexOf('#');
|
|
41
30
|
const filePart = hashIdx === -1 ? query : query.slice(0, hashIdx);
|
|
42
31
|
const isFileLevel = hashIdx === -1;
|
|
@@ -59,7 +48,7 @@ async function findSourceRefs(latDir, projectRoot, query, scope) {
|
|
|
59
48
|
const { resolveSourceSymbol } = await import('../source-parser.js');
|
|
60
49
|
if (hashIdx !== -1) {
|
|
61
50
|
const symbolPart = query.slice(hashIdx + 1);
|
|
62
|
-
const { found, symbols } = await resolveSourceSymbol(filePart, symbolPart, projectRoot);
|
|
51
|
+
const { found, symbols } = await resolveSourceSymbol(filePart, symbolPart, projectRoot, commandProjectSession(ctx).sourceSymbolOptions());
|
|
63
52
|
if (found) {
|
|
64
53
|
const parts = symbolPart.split('#');
|
|
65
54
|
const sym = symbols.find((s) => parts.length === 1
|
|
@@ -76,17 +65,14 @@ async function findSourceRefs(latDir, projectRoot, query, scope) {
|
|
|
76
65
|
catch {
|
|
77
66
|
// source parser unavailable — proceed without line info
|
|
78
67
|
}
|
|
79
|
-
const
|
|
80
|
-
const flat =
|
|
68
|
+
const project = await commandProjectAnalysis(ctx);
|
|
69
|
+
const flat = project.sections;
|
|
81
70
|
const mdRefs = [];
|
|
82
71
|
const codeRefs = [];
|
|
83
72
|
if (scope === 'md' || scope === 'md+code') {
|
|
84
|
-
const files = await listLatticeFiles(latDir);
|
|
85
73
|
const matchingFromSections = new Set();
|
|
86
|
-
for (const file of files) {
|
|
87
|
-
const
|
|
88
|
-
const fileRefs = extractRefs(file, content, projectRoot);
|
|
89
|
-
for (const ref of fileRefs) {
|
|
74
|
+
for (const file of project.files.values()) {
|
|
75
|
+
for (const ref of file.wikiRefs) {
|
|
90
76
|
const targetLower = ref.target.toLowerCase();
|
|
91
77
|
const matches = isFileLevel
|
|
92
78
|
? targetLower === fileLower || targetLower.startsWith(fileLower + '#')
|
|
@@ -104,7 +90,7 @@ async function findSourceRefs(latDir, projectRoot, query, scope) {
|
|
|
104
90
|
}
|
|
105
91
|
}
|
|
106
92
|
if (scope === 'code' || scope === 'md+code') {
|
|
107
|
-
const { refs: scannedRefs } = await
|
|
93
|
+
const { refs: scannedRefs } = await commandProjectSession(ctx).codeRefs();
|
|
108
94
|
for (const ref of scannedRefs) {
|
|
109
95
|
const targetLower = ref.target.toLowerCase();
|
|
110
96
|
const matches = isFileLevel
|
|
@@ -118,6 +104,56 @@ async function findSourceRefs(latDir, projectRoot, query, scope) {
|
|
|
118
104
|
}
|
|
119
105
|
return { kind: 'found', target, mdRefs, codeRefs };
|
|
120
106
|
}
|
|
107
|
+
async function findExternalRefs(ctx, query, scope) {
|
|
108
|
+
const external = await commandProjectSession(ctx).external();
|
|
109
|
+
const parsed = external.parse(query);
|
|
110
|
+
const target = {
|
|
111
|
+
id: parsed.identity,
|
|
112
|
+
heading: parsed.fragment || parsed.authoredPath,
|
|
113
|
+
depth: 0,
|
|
114
|
+
file: parsed.identity,
|
|
115
|
+
filePath: parsed.identity,
|
|
116
|
+
children: [],
|
|
117
|
+
startLine: 0,
|
|
118
|
+
endLine: 0,
|
|
119
|
+
firstParagraph: '',
|
|
120
|
+
};
|
|
121
|
+
const project = await commandProjectAnalysis(ctx);
|
|
122
|
+
const flat = project.sections;
|
|
123
|
+
const matchingSections = new Set();
|
|
124
|
+
const codeRefs = [];
|
|
125
|
+
const matchesTarget = (candidate) => {
|
|
126
|
+
try {
|
|
127
|
+
return external.parse(candidate)?.identity === parsed.identity;
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
if (scope !== 'code') {
|
|
134
|
+
for (const file of project.files.values()) {
|
|
135
|
+
for (const ref of file.wikiRefs) {
|
|
136
|
+
if (matchesTarget(ref.target))
|
|
137
|
+
matchingSections.add(ref.fromSection.toLowerCase());
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (scope !== 'md') {
|
|
142
|
+
for (const ref of (await commandProjectSession(ctx).codeRefs()).refs) {
|
|
143
|
+
if (matchesTarget(ref.target)) {
|
|
144
|
+
codeRefs.push(`${relative(process.cwd(), join(ctx.projectRoot, ref.file))}:${ref.line}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
kind: 'found',
|
|
150
|
+
target,
|
|
151
|
+
mdRefs: flat
|
|
152
|
+
.filter((section) => matchingSections.has(section.id.toLowerCase()))
|
|
153
|
+
.map((section) => ({ section, reason: 'wiki link' })),
|
|
154
|
+
codeRefs,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
121
157
|
/**
|
|
122
158
|
* Find all sections and code locations that reference a given section or
|
|
123
159
|
* source file. Accepts section ids (full-path, short-form) and source file
|
|
@@ -126,15 +162,29 @@ async function findSourceRefs(latDir, projectRoot, query, scope) {
|
|
|
126
162
|
*/
|
|
127
163
|
export async function findRefs(ctx, query, scope) {
|
|
128
164
|
query = query.replace(/^\[\[|\]\]$/g, '');
|
|
165
|
+
const external = await commandProjectSession(ctx).external();
|
|
166
|
+
try {
|
|
167
|
+
if (external.parse(query))
|
|
168
|
+
return findExternalRefs(ctx, query, scope);
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
return {
|
|
172
|
+
kind: 'no-match',
|
|
173
|
+
suggestions: [],
|
|
174
|
+
message: error.message,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
const unknownExternal = external.unknownTargetMessage(query);
|
|
178
|
+
if (unknownExternal) {
|
|
179
|
+
return { kind: 'no-match', suggestions: [], message: unknownExternal };
|
|
180
|
+
}
|
|
129
181
|
// Source file queries bypass section resolution
|
|
130
182
|
if (isSourceQuery(query, ctx.projectRoot)) {
|
|
131
|
-
return findSourceRefs(ctx
|
|
183
|
+
return findSourceRefs(ctx, query, scope);
|
|
132
184
|
}
|
|
133
|
-
const
|
|
134
|
-
const flat =
|
|
135
|
-
const sectionIds = new Set(
|
|
136
|
-
const fileIndex = buildFileIndex(allSections);
|
|
137
|
-
const slugIndex = buildSectionSlugIndex(allSections);
|
|
185
|
+
const project = await commandProjectAnalysis(ctx);
|
|
186
|
+
const { allSections, sections: flat, fileIndex, slugIndex } = project;
|
|
187
|
+
const sectionIds = new Set(project.sectionIds);
|
|
138
188
|
const { resolved } = resolveRef(query, sectionIds, fileIndex, slugIndex);
|
|
139
189
|
const q = resolved.toLowerCase();
|
|
140
190
|
let exactMatch = flat.find((s) => s.id.toLowerCase() === q);
|
|
@@ -157,17 +207,9 @@ export async function findRefs(ctx, query, scope) {
|
|
|
157
207
|
const mdRefs = [];
|
|
158
208
|
const codeRefs = [];
|
|
159
209
|
if (scope === 'md' || scope === 'md+code') {
|
|
160
|
-
const files = await listLatticeFiles(ctx.latDir);
|
|
161
210
|
const matchingFromSections = new Set();
|
|
162
|
-
for (const
|
|
163
|
-
|
|
164
|
-
const fileRefs = extractRefs(file, content, ctx.projectRoot);
|
|
165
|
-
for (const ref of fileRefs) {
|
|
166
|
-
const { resolved: refResolved } = resolveRef(ref.target, sectionIds, fileIndex, slugIndex);
|
|
167
|
-
if (refResolved.toLowerCase() === targetId) {
|
|
168
|
-
matchingFromSections.add(ref.fromSection.toLowerCase());
|
|
169
|
-
}
|
|
170
|
-
}
|
|
211
|
+
for (const ref of project.incomingRefsBySection.get(targetId) ?? []) {
|
|
212
|
+
matchingFromSections.add(ref.fromSection.toLowerCase());
|
|
171
213
|
}
|
|
172
214
|
if (matchingFromSections.size > 0) {
|
|
173
215
|
const referrers = flat.filter((s) => matchingFromSections.has(s.id.toLowerCase()));
|
|
@@ -177,7 +219,7 @@ export async function findRefs(ctx, query, scope) {
|
|
|
177
219
|
}
|
|
178
220
|
}
|
|
179
221
|
if (scope === 'code' || scope === 'md+code') {
|
|
180
|
-
const { refs: scannedRefs } = await
|
|
222
|
+
const { refs: scannedRefs } = await commandProjectSession(ctx).codeRefs();
|
|
181
223
|
for (const ref of scannedRefs) {
|
|
182
224
|
const { resolved: codeResolved } = resolveRef(ref.target, sectionIds, fileIndex, slugIndex);
|
|
183
225
|
if (codeResolved.toLowerCase() === targetId) {
|
|
@@ -192,6 +234,9 @@ export async function refsCommand(ctx, query, scope) {
|
|
|
192
234
|
const result = await findRefs(ctx, query, scope);
|
|
193
235
|
if (result.kind === 'no-match') {
|
|
194
236
|
const s = ctx.styler;
|
|
237
|
+
if (result.message) {
|
|
238
|
+
return { output: s.red(result.message), isError: true };
|
|
239
|
+
}
|
|
195
240
|
if (result.suggestions.length > 0) {
|
|
196
241
|
const suggestions = result.suggestions
|
|
197
242
|
.map((m) => ` ${s.dim('*')} ${s.white(m.section.id)} ${s.dim(`(${m.reason})`)}`)
|
package/dist/src/cli/reindex.js
CHANGED
|
@@ -3,6 +3,7 @@ import { openDb, ensureMeta, setStoredModel, ensureSectionsSchema, dropSections,
|
|
|
3
3
|
import { embedderFromEnv, localEmbedder, modelKey, EmbeddingAuthError, } from '../search/embedder.js';
|
|
4
4
|
import { getLlmKey, getRepoEmbedding, setRepoEmbedding } from '../config.js';
|
|
5
5
|
import { indexSections } from '../search/index.js';
|
|
6
|
+
import { commandProjectAnalysis } from '../project-analysis.js';
|
|
6
7
|
const SPINNER = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
7
8
|
async function confirmUseLocal(ctx, status, assumeYes) {
|
|
8
9
|
const s = ctx.styler;
|
|
@@ -106,7 +107,7 @@ export async function reindexCommand(ctx, opts) {
|
|
|
106
107
|
process.stderr.write(s.dim(label + '…\n'));
|
|
107
108
|
let stats;
|
|
108
109
|
try {
|
|
109
|
-
stats = await indexSections(ctx.latDir, db, embedder, onProgress);
|
|
110
|
+
stats = await indexSections(ctx.latDir, db, embedder, onProgress, await commandProjectAnalysis(ctx));
|
|
110
111
|
// Pin the backend only after a successful build, so a failed reindex never
|
|
111
112
|
// records a model that doesn't match a completed index.
|
|
112
113
|
await setStoredModel(db, modelKey(embedder));
|
package/dist/src/cli/search.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { CmdContext, CmdResult, Styler } from '../context.js';
|
|
2
2
|
import { type IndexStats } from '../search/index.js';
|
|
3
|
-
import
|
|
3
|
+
import type { SectionMatch } from '../lattice-model.js';
|
|
4
|
+
import type { Section } from '../lattice-model.js';
|
|
5
|
+
import { type MarkdownProjectAnalysis } from '../project-analysis.js';
|
|
4
6
|
export type SearchResult = {
|
|
5
7
|
query: string;
|
|
6
8
|
matches: SectionMatch[];
|
|
@@ -23,14 +25,21 @@ export type IndexProgress = {
|
|
|
23
25
|
*/
|
|
24
26
|
export declare function runSearch(latDir: string, query: string, limit: number, progress?: IndexProgress, opts?: {
|
|
25
27
|
buildIndex?: boolean;
|
|
26
|
-
|
|
28
|
+
project?: MarkdownProjectAnalysis;
|
|
29
|
+
sectionById?: ReadonlyMap<string, Section>;
|
|
30
|
+
threshold?: number;
|
|
31
|
+
cacheDir?: string;
|
|
27
32
|
}): Promise<SearchResult>;
|
|
28
33
|
/**
|
|
29
34
|
* Index-only mode (no query) — builds the index on first use. Rebuilding is
|
|
30
35
|
* `lat reindex`, not a flag here.
|
|
31
36
|
*/
|
|
32
|
-
export declare function runIndex(latDir: string, progress?: IndexProgress
|
|
37
|
+
export declare function runIndex(latDir: string, progress?: IndexProgress, analyzedProject?: MarkdownProjectAnalysis, options?: {
|
|
38
|
+
cacheDir?: string;
|
|
39
|
+
}): Promise<void>;
|
|
33
40
|
export declare function cliProgress(s: Styler): IndexProgress;
|
|
34
41
|
export declare function searchCommand(ctx: CmdContext, query: string | undefined, opts: {
|
|
35
42
|
limit: number;
|
|
43
|
+
debug?: boolean;
|
|
44
|
+
threshold?: number;
|
|
36
45
|
}, progress?: IndexProgress): Promise<CmdResult>;
|
package/dist/src/cli/search.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
|
-
import { join } from 'node:path';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
3
|
import { openDb, ensureMeta, getStoredModel, setStoredModel, ensureSectionsSchema, dropSections, closeDb, } from '../search/db.js';
|
|
4
4
|
import { getLlmKey } from '../config.js';
|
|
5
5
|
import { embedderForIndex, modelKey, ReindexRequiredError, EmbeddingAuthError, } from '../search/embedder.js';
|
|
6
6
|
import { indexSections } from '../search/index.js';
|
|
7
7
|
import { searchSections } from '../search/search.js';
|
|
8
|
-
import {
|
|
8
|
+
import { searchIndexedSections } from '../search/query.js';
|
|
9
|
+
import { analyzeMarkdownProject, commandProjectAnalysis, } from '../project-analysis.js';
|
|
9
10
|
import { formatSectionPreview, formatNavHints } from '../format.js';
|
|
10
11
|
import { provenanceNote, formatProvenanceNote } from './check-status.js';
|
|
11
|
-
async function withDb(latDir, progress, fn) {
|
|
12
|
-
const db = openDb(latDir);
|
|
12
|
+
async function withDb(latDir, progress, project, cacheDir, fn) {
|
|
13
|
+
const db = openDb(latDir, cacheDir);
|
|
13
14
|
try {
|
|
14
15
|
await ensureMeta(db);
|
|
15
16
|
const stored = await getStoredModel(db);
|
|
@@ -46,7 +47,7 @@ async function withDb(latDir, progress, fn) {
|
|
|
46
47
|
}
|
|
47
48
|
progress?.beforeIndex?.(isEmpty);
|
|
48
49
|
try {
|
|
49
|
-
const stats = await indexSections(latDir, db, embedder);
|
|
50
|
+
const stats = await indexSections(latDir, db, embedder, undefined, project);
|
|
50
51
|
// Pin the backend only after a successful index, so a failed build never
|
|
51
52
|
// leaves the repo wrongly pinned to an empty index.
|
|
52
53
|
if (!stored)
|
|
@@ -60,26 +61,12 @@ async function withDb(latDir, progress, fn) {
|
|
|
60
61
|
await dropSections(db);
|
|
61
62
|
throw err;
|
|
62
63
|
}
|
|
63
|
-
return await fn(db, embedder);
|
|
64
|
+
return await fn(db, embedder, project);
|
|
64
65
|
}
|
|
65
66
|
finally {
|
|
66
67
|
await closeDb(db);
|
|
67
68
|
}
|
|
68
69
|
}
|
|
69
|
-
/** Resolve raw search hits (by id) to full section matches. */
|
|
70
|
-
async function resolveMatches(latDir, results, preloadedSections) {
|
|
71
|
-
if (results.length === 0)
|
|
72
|
-
return [];
|
|
73
|
-
const allSections = preloadedSections ?? (await loadAllSections(latDir));
|
|
74
|
-
const flat = flattenSections(allSections);
|
|
75
|
-
const byId = new Map(flat.map((s) => [s.id, s]));
|
|
76
|
-
return results.flatMap((result) => {
|
|
77
|
-
const section = byId.get(result.id);
|
|
78
|
-
return section
|
|
79
|
-
? [{ section, reason: 'semantic match', score: result.score }]
|
|
80
|
-
: [];
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
70
|
/**
|
|
84
71
|
* Run a semantic search across lat.md sections.
|
|
85
72
|
* Handles indexing (with optional progress callback). Returns matched sections.
|
|
@@ -92,31 +79,30 @@ async function resolveMatches(latDir, results, preloadedSections) {
|
|
|
92
79
|
*/
|
|
93
80
|
export async function runSearch(latDir, query, limit, progress, opts) {
|
|
94
81
|
if (opts?.buildIndex === false) {
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
await
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
await ensureSectionsSchema(db, embedder.dimensions);
|
|
105
|
-
const results = await searchSections(db, query, embedder, limit);
|
|
106
|
-
return {
|
|
107
|
-
query,
|
|
108
|
-
matches: await resolveMatches(latDir, results, opts?.preloadedSections),
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
finally {
|
|
112
|
-
await closeDb(db);
|
|
113
|
-
}
|
|
82
|
+
const sectionById = opts.sectionById ??
|
|
83
|
+
opts.project?.sectionById ??
|
|
84
|
+
(await analyzeMarkdownProject(latDir, dirname(latDir), {
|
|
85
|
+
executor: 'auto',
|
|
86
|
+
})).sectionById;
|
|
87
|
+
return searchIndexedSections(latDir, query, limit, sectionById, {
|
|
88
|
+
cacheDir: opts.cacheDir,
|
|
89
|
+
threshold: opts.threshold,
|
|
90
|
+
});
|
|
114
91
|
}
|
|
115
|
-
|
|
116
|
-
|
|
92
|
+
const project = opts?.project ??
|
|
93
|
+
(await analyzeMarkdownProject(latDir, dirname(latDir), {
|
|
94
|
+
executor: 'auto',
|
|
95
|
+
}));
|
|
96
|
+
return withDb(latDir, progress, project, opts?.cacheDir, async (db, embedder, analyzed) => {
|
|
97
|
+
const results = await searchSections(db, query, embedder, limit, opts?.threshold);
|
|
117
98
|
return {
|
|
118
99
|
query,
|
|
119
|
-
matches:
|
|
100
|
+
matches: results.flatMap((result) => {
|
|
101
|
+
const section = analyzed.sectionById.get(result.id.toLowerCase());
|
|
102
|
+
return section
|
|
103
|
+
? [{ section, reason: 'semantic match', score: result.score }]
|
|
104
|
+
: [];
|
|
105
|
+
}),
|
|
120
106
|
};
|
|
121
107
|
});
|
|
122
108
|
}
|
|
@@ -124,8 +110,12 @@ export async function runSearch(latDir, query, limit, progress, opts) {
|
|
|
124
110
|
* Index-only mode (no query) — builds the index on first use. Rebuilding is
|
|
125
111
|
* `lat reindex`, not a flag here.
|
|
126
112
|
*/
|
|
127
|
-
export async function runIndex(latDir, progress) {
|
|
128
|
-
|
|
113
|
+
export async function runIndex(latDir, progress, analyzedProject, options = {}) {
|
|
114
|
+
const project = analyzedProject ??
|
|
115
|
+
(await analyzeMarkdownProject(latDir, dirname(latDir), {
|
|
116
|
+
executor: 'auto',
|
|
117
|
+
}));
|
|
118
|
+
await withDb(latDir, progress, project, options.cacheDir, async () => { });
|
|
129
119
|
}
|
|
130
120
|
export function cliProgress(s) {
|
|
131
121
|
return {
|
|
@@ -153,7 +143,7 @@ export function cliProgress(s) {
|
|
|
153
143
|
* say whether a person ever checked that claim. Frontmatter is read once per
|
|
154
144
|
* file rather than once per match, since several matches routinely share one.
|
|
155
145
|
*/
|
|
156
|
-
async function formatSearchMatches(ctx, query, matches) {
|
|
146
|
+
async function formatSearchMatches(ctx, query, matches, opts) {
|
|
157
147
|
const notes = new Map();
|
|
158
148
|
for (const match of matches) {
|
|
159
149
|
const filePath = match.section.filePath;
|
|
@@ -173,6 +163,7 @@ async function formatSearchMatches(ctx, query, matches) {
|
|
|
173
163
|
lines.push('');
|
|
174
164
|
lines.push(formatSectionPreview(ctx, matches[i].section, {
|
|
175
165
|
reason: matches[i].reason,
|
|
166
|
+
score: opts?.showScores ? matches[i].score : undefined,
|
|
176
167
|
}));
|
|
177
168
|
const note = notes.get(matches[i].section.filePath);
|
|
178
169
|
if (note)
|
|
@@ -185,16 +176,21 @@ export async function searchCommand(ctx, query, opts, progress) {
|
|
|
185
176
|
const s = ctx.styler;
|
|
186
177
|
try {
|
|
187
178
|
if (!query) {
|
|
188
|
-
await runIndex(ctx.latDir, progress);
|
|
179
|
+
await runIndex(ctx.latDir, progress, await commandProjectAnalysis(ctx));
|
|
189
180
|
return { output: '' };
|
|
190
181
|
}
|
|
191
|
-
const
|
|
182
|
+
const project = await commandProjectAnalysis(ctx);
|
|
183
|
+
const result = await runSearch(ctx.latDir, query, opts.limit, progress, {
|
|
184
|
+
project,
|
|
185
|
+
threshold: opts.threshold,
|
|
186
|
+
});
|
|
192
187
|
if (result.matches.length === 0) {
|
|
193
188
|
return { output: 'No results found.' };
|
|
194
189
|
}
|
|
195
190
|
return {
|
|
196
|
-
output: (await formatSearchMatches(ctx, query, result.matches
|
|
197
|
-
|
|
191
|
+
output: (await formatSearchMatches(ctx, query, result.matches, {
|
|
192
|
+
showScores: opts.debug,
|
|
193
|
+
})) + formatNavHints(ctx),
|
|
198
194
|
};
|
|
199
195
|
}
|
|
200
196
|
catch (err) {
|