@iowarp/clio-coder 0.3.0 → 0.3.2
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 +123 -2
- package/CONTRIBUTING.md +23 -23
- package/README.md +295 -627
- package/dist/acp-BIYHVZIM.js +128 -0
- package/dist/{agents-Q4MYPMUW.js → agents-YT6SSRIT.js} +52 -27
- package/dist/assets/codewiki.json +1 -0
- package/dist/assets/grammars/notices/@vscode__tree-sitter-wasm/LICENSE +21 -0
- package/dist/assets/grammars/notices/@vscode__tree-sitter-wasm/cgmanifest.json +16 -0
- package/dist/assets/grammars/notices/tree-sitter-wasms/LICENSE +24 -0
- package/dist/assets/grammars/tree-sitter-c-sharp.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-c.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-cpp.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-go.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-java.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-javascript.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-python.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-ruby.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-rust.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-tsx.wasm +0 -0
- package/dist/assets/grammars/tree-sitter-typescript.wasm +0 -0
- package/dist/assets/grammars/tree-sitter.wasm +0 -0
- package/dist/{auth-O6HYIJ6J.js → auth-5TWEIYDN.js} +30 -15
- package/dist/chunk-2EHAIA3X.js +481 -0
- package/dist/{chunk-ME6DNWIU.js → chunk-2IR2NMPA.js} +12 -4
- package/dist/chunk-2SFS6XQE.js +122 -0
- package/dist/{chunk-KKKPTZLM.js → chunk-2STGEDFV.js} +8 -1
- package/dist/chunk-2VTFPG5O.js +48 -0
- package/dist/chunk-3I7MS7N2.js +40 -0
- package/dist/chunk-3R73A4XB.js +69 -0
- package/dist/{chunk-JPOWPFCU.js → chunk-3ZXDFGR5.js} +52 -23
- package/dist/chunk-4BJ5BYCE.js +61 -0
- package/dist/{chunk-26BZQOAD.js → chunk-4BPJXDWC.js} +161 -260
- package/dist/chunk-4KLWL3UC.js +18 -0
- package/dist/{chunk-5LDRNKX2.js → chunk-4VP4KH3K.js} +161 -262
- package/dist/chunk-4ZG3XFUR.js +77 -0
- package/dist/chunk-5B2AEOW5.js +5407 -0
- package/dist/chunk-5TSRNF4G.js +510 -0
- package/dist/{chunk-WD6AJM35.js → chunk-5UUP6MWO.js} +48 -69
- package/dist/{chunk-X3BR7HWV.js → chunk-5WIGXA4T.js} +7 -1
- package/dist/chunk-65DEGPJ6.js +52 -0
- package/dist/chunk-6EJMN2Y3.js +17 -0
- package/dist/chunk-6EJV5X2W.js +16405 -0
- package/dist/chunk-6N5PTWMY.js +136 -0
- package/dist/chunk-6XLNIQDB.js +27 -0
- package/dist/{chunk-XNISANGE.js → chunk-77VKQEHF.js} +171 -74
- package/dist/chunk-7CR24IG7.js +242 -0
- package/dist/{chunk-UWIJNAOB.js → chunk-7EYHLWU7.js} +907 -638
- package/dist/chunk-7MNJORFF.js +22 -0
- package/dist/{chunk-JWHCJDCI.js → chunk-A3CYT5EX.js} +257 -79
- package/dist/chunk-AGYYIBLL.js +1069 -0
- package/dist/chunk-AO4RKG4M.js +277 -0
- package/dist/chunk-APJ265NV.js +7410 -0
- package/dist/chunk-ARBGF5F7.js +174 -0
- package/dist/{chunk-TFSSEXL6.js → chunk-BMEMKKIT.js} +14 -4
- package/dist/{chunk-X3NE4WVW.js → chunk-BNAZZHFG.js} +7 -1
- package/dist/chunk-CBCAPZAA.js +229 -0
- package/dist/{chunk-QV47YRF4.js → chunk-CGKSTWHD.js} +7 -1
- package/dist/chunk-CMZWFGD2.js +352 -0
- package/dist/chunk-ECH6PKUQ.js +39 -0
- package/dist/{chunk-67MTHP2E.js → chunk-ED4KHGC3.js} +13 -5
- package/dist/chunk-EKMEHE4H.js +340 -0
- package/dist/{chunk-O4EJEDHO.js → chunk-EPVUXGXG.js} +50 -35
- package/dist/chunk-FCSXB6T2.js +338 -0
- package/dist/chunk-FJ3H4MN5.js +48 -0
- package/dist/chunk-FQ4SKYE4.js +29 -0
- package/dist/chunk-G2DE3C7R.js +644 -0
- package/dist/chunk-G4BMMOKF.js +182 -0
- package/dist/{chunk-7BHLZB3A.js → chunk-GGXXDWE4.js} +190 -1218
- package/dist/chunk-HC4CLZ2Y.js +68 -0
- package/dist/{chunk-E3NYWENM.js → chunk-HFSBBKSQ.js} +55 -61
- package/dist/chunk-HKIYEGME.js +30 -0
- package/dist/chunk-I4HZDVNP.js +73 -0
- package/dist/chunk-IGLFWIYI.js +161 -0
- package/dist/chunk-IHXBNWMM.js +137 -0
- package/dist/chunk-IKCO5N3L.js +162 -0
- package/dist/chunk-IR4CFBFN.js +56 -0
- package/dist/{chunk-DXQNI4PC.js → chunk-IWHMRKLL.js} +8 -1
- package/dist/{chunk-VOO7NYPP.js → chunk-J5HN4RYU.js} +27 -9
- package/dist/{chunk-4UQA7NCT.js → chunk-J5Q24KAG.js} +7 -2
- package/dist/{chunk-KBR4MZZR.js → chunk-JVCV3ICN.js} +7 -1
- package/dist/chunk-KJ5LWLOE.js +1077 -0
- package/dist/chunk-LBMZMYH2.js +285 -0
- package/dist/{chunk-3DANZDGR.js → chunk-LBNRH5WM.js} +100 -161
- package/dist/{chunk-TKHQ4DGZ.js → chunk-LZSJBIVT.js} +7358 -7414
- package/dist/{chunk-UGYAX5YI.js → chunk-M6SHUN7Q.js} +13 -8
- package/dist/chunk-MAW544W2.js +1882 -0
- package/dist/chunk-MBS4V7ZP.js +217 -0
- package/dist/{chunk-2J63S4SF.js → chunk-MFFY33HR.js} +167 -140
- package/dist/chunk-MNA4JGU4.js +255 -0
- package/dist/chunk-MQSRRFWA.js +3428 -0
- package/dist/{chunk-RQDWMVRB.js → chunk-MVVUPGPW.js} +138 -137
- package/dist/chunk-OAO4GE4M.js +619 -0
- package/dist/chunk-OHHN2SO4.js +5135 -0
- package/dist/chunk-OKGUZO2U.js +34 -0
- package/dist/{chunk-BBUH4VAA.js → chunk-OOJYHWRB.js} +60 -361
- package/dist/{chunk-D5YD55AR.js → chunk-OQ33BKR3.js} +12 -1
- package/dist/chunk-OQE5J4C6.js +73 -0
- package/dist/{chunk-AMFR5YA3.js → chunk-ORBHGJC5.js} +26 -12
- package/dist/chunk-POHLU5DW.js +1186 -0
- package/dist/chunk-QKMUKYO7.js +4961 -0
- package/dist/{chunk-7RBKDI66.js → chunk-QTYWRVRA.js} +104 -12
- package/dist/{chunk-5N2FG33Q.js → chunk-R346GLFC.js} +7 -1
- package/dist/chunk-SRF2PJNW.js +184 -0
- package/dist/chunk-SST6Z5JA.js +80 -0
- package/dist/{chunk-XV4ZJ6ZM.js → chunk-STBPMHSX.js} +473 -1194
- package/dist/{chunk-HBU5MTAM.js → chunk-SVNXH4L2.js} +7 -1
- package/dist/chunk-T6YILFSB.js +80 -0
- package/dist/chunk-TXOTCRLG.js +15 -0
- package/dist/chunk-TZTZS7QK.js +227 -0
- package/dist/chunk-UOV2BYIW.js +107 -0
- package/dist/{chunk-527KG6XR.js → chunk-V4RXGQ5Q.js} +72 -185
- package/dist/chunk-VAKQQHWR.js +434 -0
- package/dist/chunk-VG7TBQIY.js +128 -0
- package/dist/chunk-VJWL6YS5.js +244 -0
- package/dist/chunk-WEH5XRJQ.js +32 -0
- package/dist/{chunk-VPAWTYLY.js → chunk-WEPFGWHJ.js} +7 -1
- package/dist/chunk-WMSVI4G2.js +2095 -0
- package/dist/chunk-WVO7V2QY.js +797 -0
- package/dist/chunk-X4RCMKVQ.js +641 -0
- package/dist/chunk-X75S7HFS.js +374 -0
- package/dist/chunk-XN3L4EYL.js +46 -0
- package/dist/{chunk-HMYNFFY4.js → chunk-XPLRXC72.js} +7 -2
- package/dist/{chunk-PIDUD6M2.js → chunk-YCWGATWI.js} +12 -5
- package/dist/chunk-YHZX5GEU.js +193 -0
- package/dist/chunk-YXLYO42X.js +91 -0
- package/dist/{chunk-UHTSULZS.js → chunk-ZDOOVTXZ.js} +38 -73
- package/dist/chunk-ZI647VB5.js +37 -0
- package/dist/{chunk-CLJ5HLUD.js → chunk-ZWLZP4ZT.js} +25 -6
- package/dist/cli/index.js +70 -56
- package/dist/clio-4LY5K2AC.js +25 -0
- package/dist/code-nav-7AX6FYE6.js +600 -0
- package/dist/codewiki/build-worker.js +66 -0
- package/dist/compile-cache-CVJMMODC.js +18 -0
- package/dist/{components-JVHMUBEB.js → components-KELWS457.js} +31 -9
- package/dist/{config-ZFCDBMDC.js → config-GTLUW2PR.js} +104 -56
- package/dist/configure-R6A64DHX.js +42 -0
- package/dist/context-5VKGUVJJ.js +866 -0
- package/dist/{context-CDXTP2MP.js → context-JFZEJ7W5.js} +21 -13
- package/dist/{context-E3KIFVXI.js → context-RW5HC47S.js} +77 -36
- package/dist/{context-clear-3F4PLXOS.js → context-clear-6ZHBAZZT.js} +64 -30
- package/dist/{context-index-Q7YSYTR3.js → context-index-BZ4UYMTC.js} +36 -24
- package/dist/dispatch-runner-VKBRCWQC.js +1997 -0
- package/dist/{docs-YIETIWZI.js → docs-2C2LTVT2.js} +32 -13
- package/dist/doctor-KI767GSN.js +87 -0
- package/dist/{eval-B3KZZESM.js → eval-XSSNATB4.js} +93 -27
- package/dist/{evidence-V67CHM35.js → evidence-UA6AWDQQ.js} +55 -27
- package/dist/{evolve-YDZSUQYA.js → evolve-QNTFGV6Z.js} +59 -26
- package/dist/{extensions-SRG7XCAH.js → extensions-QVDOHDGJ.js} +23 -8
- package/dist/{fleet-CA2CRTVG.js → fleet-Q7UOMUSG.js} +173 -56
- package/dist/fleet-preflight-DDN536IT.js +26 -0
- package/dist/{init-2OZDJE2D.js → init-WBB65ZHQ.js} +79 -34
- package/dist/{memory-3PIQQAKX.js → memory-MD3O64RI.js} +57 -28
- package/dist/{models-DY35XI7Y.js → models-BZU34YWD.js} +49 -24
- package/dist/monitor-MEQA5C3I.js +661 -0
- package/dist/{chunk-PS4PFJQP.js → orchestrator-CGFKEP27.js} +22837 -18564
- package/dist/{paths-5OMXW7Z4.js → paths-UXLN5YYZ.js} +17 -6
- package/dist/preload-P6DGH2PZ.js +13 -0
- package/dist/{reset-PIFYNOS3.js → reset-L2FQEE3E.js} +25 -13
- package/dist/{run-3VSPP24F.js → run-IV4Q6RLN.js} +115 -63
- package/dist/{share-D36RQCXM.js → share-S5BZQC5I.js} +23 -10
- package/dist/{skills-F2MRLELY.js → skills-LQEKRDTN.js} +42 -15
- package/dist/{skills-eval-E2ZTW4PL.js → skills-eval-3DC4HEWS.js} +90 -45
- package/dist/steer-GGWFUJUD.js +77 -0
- package/dist/{targets-DZMEZAH4.js → targets-C4SSGQOB.js} +78 -60
- package/dist/terminal-lease-IT5JW2NR.js +395 -0
- package/dist/{trace-7NYCUI2J.js → trace-PNCASAXC.js} +48 -17
- package/dist/tree-sitter-HGKH6LG4.js +4673 -0
- package/dist/{uninstall-AD3JWHBB.js → uninstall-FZCQCDKC.js} +19 -8
- package/dist/{upgrade-WYYBKGDY.js → upgrade-7TT7SQ3G.js} +66 -24
- package/dist/{usage-ULIDAGFF.js → usage-GV4PKT3M.js} +71 -32
- package/dist/verify-G6V4D2G7.js +716 -0
- package/dist/version-KGEG7EPO.js +21 -0
- package/dist/web-fetch-2YHJ3KTG.js +638 -0
- package/dist/{wiki-generate-PKFIX6OB.js → wiki-generate-DQF6Z66B.js} +98 -48
- package/dist/worker/entry.js +297 -54
- package/dist/workspace-G4ZWUIPR.js +22 -0
- package/docs/README.md +29 -21
- package/docs/acp.md +191 -16
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +157 -7
- package/docs/artifact-placement.md +101 -0
- package/docs/artifact-versions.md +1 -1
- package/docs/built-in-agents.md +4 -2
- package/docs/capacity-and-scheduling.md +1 -1
- package/docs/commands-and-modes.md +224 -97
- package/docs/config-knobs-audit.md +1 -3
- package/docs/configuration-and-targets.md +236 -38
- package/docs/context-engine.md +34 -7
- package/docs/development-pipeline.md +102 -0
- package/docs/dispatch-architecture-rationale.md +1 -1
- package/docs/documentation-coverage.md +4 -4
- package/docs/documentation-guide.md +3 -3
- package/docs/environment-variables.md +15 -6
- package/docs/eval-runner.md +3 -3
- package/docs/evals-internal.md +2 -2
- package/docs/evidence-and-memory.md +10 -2
- package/docs/evolution.md +2 -2
- package/docs/exit-codes-and-output.md +15 -9
- package/docs/extensions-and-sharing.md +25 -18
- package/docs/fleet-demo-runbook.md +22 -23
- package/docs/fleet-dispatch.md +117 -16
- package/docs/git-commit-provenance.md +120 -0
- package/docs/glossary.md +107 -15
- package/docs/installation-and-lifecycle.md +75 -17
- package/docs/middleware-and-components.md +1 -1
- package/docs/model-catalog.md +46 -15
- package/docs/observability.md +8 -5
- package/docs/performance-methodology.md +491 -0
- package/docs/pi-boundary.md +72 -0
- package/docs/proactive-memory.md +14 -14
- package/docs/prompt-envelope-and-tools.md +25 -4
- package/docs/provider-adapter-cookbook.md +57 -4
- package/docs/release-cut-checklist.md +129 -111
- package/docs/safety-model.md +28 -8
- package/docs/scientific-validation.md +3 -3
- package/docs/session-lifecycle.md +55 -12
- package/docs/skills-marketplace.md +12 -8
- package/docs/time-conventions.md +101 -0
- package/docs/tool-usage.md +6 -5
- package/docs/trace-store.md +1 -1
- package/docs/troubleshooting.md +10 -7
- package/docs/tui-design.md +121 -28
- package/docs/worker-dispatch-mechanics.md +3 -3
- package/package.json +33 -36
- package/skills/README.md +5 -6
- package/skills/coding/ast-grep/SKILL.md +136 -0
- package/skills/coding/ast-grep/evals.md +56 -0
- package/skills/coding/ast-grep/references/rule_reference.md +297 -0
- package/skills/coding/coding-standards/SKILL.md +113 -0
- package/skills/coding/coding-standards/evals.md +34 -0
- package/skills/coding/prototype/SKILL.md +86 -0
- package/skills/coding/prototype/evals.md +42 -0
- package/skills/coding/prototype/references/LOGIC.md +67 -0
- package/skills/coding/prototype/references/UI.md +112 -0
- package/skills/coding/tdd/SKILL.md +101 -0
- package/skills/coding/tdd/evals.md +41 -0
- package/skills/coding/tdd/references/mocking.md +59 -0
- package/skills/coding/tdd/references/tests.md +77 -0
- package/skills/context/context-handoff/SKILL.md +126 -0
- package/skills/context/context-handoff/evals.md +57 -0
- package/skills/context/context-handoff/scripts/new-handoff.sh +26 -0
- package/skills/context/context-prime/SKILL.md +95 -0
- package/skills/context/context-prime/evals.md +54 -0
- package/skills/git/file-ticket/SKILL.md +107 -0
- package/skills/git/file-ticket/evals.md +54 -0
- package/skills/git/fix-issue/SKILL.md +106 -0
- package/skills/git/fix-issue/evals.md +71 -0
- package/skills/git/ship/SKILL.md +92 -0
- package/skills/git/ship/evals.md +72 -0
- package/skills/meta/clio-dev/SKILL.md +91 -0
- package/skills/meta/clio-dev/evals.md +45 -0
- package/skills/meta/clio-test/SKILL.md +130 -0
- package/skills/meta/clio-test/evals.md +43 -0
- package/skills/meta/clio-test/references/harness.md +97 -0
- package/skills/meta/clio-test/references/test-map.md +59 -0
- package/skills/meta/credentials/SKILL.md +125 -0
- package/skills/meta/credentials/evals.md +104 -0
- package/skills/meta/find-skills/SKILL.md +72 -0
- package/skills/meta/find-skills/evals.md +47 -0
- package/skills/meta/herdr/SKILL.md +127 -0
- package/skills/meta/herdr/evals.md +38 -0
- package/skills/meta/skill-craft/SKILL.md +102 -0
- package/skills/meta/skill-craft/evals.md +41 -0
- package/skills/planning/architecture/SKILL.md +129 -0
- package/skills/planning/architecture/evals.md +36 -0
- package/skills/planning/backlog/SKILL.md +90 -0
- package/skills/planning/backlog/evals.md +43 -0
- package/skills/planning/prd/SKILL.md +82 -0
- package/skills/planning/prd/evals.md +49 -0
- package/skills/planning/product-intent/SKILL.md +112 -0
- package/skills/planning/product-intent/evals.md +36 -0
- package/skills/planning/tech-spec/SKILL.md +115 -0
- package/skills/planning/tech-spec/evals.md +47 -0
- package/skills/registry.yaml +136 -0
- package/skills/research/arxiv-literature/SKILL.md +104 -0
- package/skills/research/arxiv-literature/evals.md +58 -0
- package/skills/research/experiment-protocol/SKILL.md +122 -0
- package/skills/research/experiment-protocol/evals.md +91 -0
- package/skills/research/scientific-debugging/SKILL.md +119 -0
- package/skills/research/scientific-debugging/evals.md +138 -0
- package/skills/research/scientific-modernization/SKILL.md +138 -0
- package/skills/research/scientific-modernization/evals.md +84 -0
- package/skills/skill-marketplace.json +12 -20
- package/skills/workflow/design-council/SKILL.md +139 -0
- package/skills/workflow/design-council/evals.md +97 -0
- package/skills/workflow/grill-me/SKILL.md +186 -0
- package/skills/workflow/grill-me/evals.md +78 -0
- package/skills/workflow/workflow-distiller/SKILL.md +136 -0
- package/skills/workflow/workflow-distiller/evals.md +107 -0
- package/src/cli/acp.ts +115 -0
- package/src/cli/agents.ts +60 -0
- package/src/cli/args.ts +280 -0
- package/src/cli/argv.ts +170 -0
- package/src/cli/ask.ts +34 -0
- package/src/cli/auth.ts +468 -0
- package/src/cli/bootstrap-generate.ts +498 -0
- package/src/cli/clio.ts +96 -0
- package/src/cli/components.ts +195 -0
- package/src/cli/config-inspect.ts +336 -0
- package/src/cli/config.ts +72 -0
- package/src/cli/configure-interop.ts +67 -0
- package/src/cli/configure-layout.ts +172 -0
- package/src/cli/configure.ts +1525 -0
- package/src/cli/context-clear.ts +76 -0
- package/src/cli/context-index.ts +100 -0
- package/src/cli/context.ts +321 -0
- package/src/cli/default-target.ts +55 -0
- package/src/cli/docs.ts +346 -0
- package/src/cli/doctor.ts +54 -0
- package/src/cli/eval.ts +315 -0
- package/src/cli/evidence.ts +225 -0
- package/src/cli/evolve.ts +219 -0
- package/src/cli/extensions.ts +214 -0
- package/src/cli/fleet.ts +868 -0
- package/src/cli/index.ts +338 -0
- package/src/cli/init.ts +219 -0
- package/src/cli/initial-message.ts +47 -0
- package/src/cli/internal-dispatch.ts +55 -0
- package/src/cli/memory.ts +182 -0
- package/src/cli/models.ts +257 -0
- package/src/cli/modes/json-stream.ts +121 -0
- package/src/cli/modes/jsonl.ts +9 -0
- package/src/cli/modes/print.ts +604 -0
- package/src/cli/oauth-manual-input.ts +72 -0
- package/src/cli/oauth-select.ts +36 -0
- package/src/cli/output-guard.ts +48 -0
- package/src/cli/paths.ts +44 -0
- package/src/cli/provider-target.ts +113 -0
- package/src/cli/removal.ts +72 -0
- package/src/cli/reset.ts +253 -0
- package/src/cli/run.ts +497 -0
- package/src/cli/share.ts +243 -0
- package/src/cli/shared.ts +60 -0
- package/src/cli/skills-eval.ts +1240 -0
- package/src/cli/skills.ts +485 -0
- package/src/cli/steer-channel.ts +86 -0
- package/src/cli/targets.ts +1154 -0
- package/src/cli/text-layout.ts +112 -0
- package/src/cli/trace.ts +322 -0
- package/src/cli/uninstall.ts +405 -0
- package/src/cli/upgrade.ts +286 -0
- package/src/cli/usage.ts +876 -0
- package/src/cli/validate-model.ts +28 -0
- package/src/cli/version.ts +7 -0
- package/src/cli/wiki-generate.ts +510 -0
- package/src/core/agent-environment.ts +7 -0
- package/src/core/artifact-paths.ts +43 -0
- package/src/core/bash-exec.ts +313 -0
- package/src/core/boot-trace.ts +42 -0
- package/src/core/bus-events.ts +744 -0
- package/src/core/bus-trace.ts +53 -0
- package/src/core/c-header-language.ts +265 -0
- package/src/core/clio-repo.ts +78 -0
- package/src/core/commit-attribution.ts +157 -0
- package/src/core/compile-cache.ts +159 -0
- package/src/core/config.ts +1722 -0
- package/src/core/context-floor.ts +33 -0
- package/src/core/defaults.ts +659 -0
- package/src/core/domain-loader.ts +177 -0
- package/src/core/event-bus.ts +94 -0
- package/src/core/file-references.ts +282 -0
- package/src/core/git-commit-attribution.ts +362 -0
- package/src/core/guardrails.ts +185 -0
- package/src/core/headless-permission.ts +21 -0
- package/src/core/incomplete-installation.ts +45 -0
- package/src/core/init.ts +223 -0
- package/src/core/json-payload.ts +58 -0
- package/src/core/package-root.ts +54 -0
- package/src/core/path-canonical.ts +37 -0
- package/src/core/process-identity.ts +41 -0
- package/src/core/recent-models.ts +91 -0
- package/src/core/residency-protection.ts +56 -0
- package/src/core/resolve-config-value.ts +88 -0
- package/src/core/response-schema.ts +279 -0
- package/src/core/run-overrides.ts +77 -0
- package/src/core/safe-exec.ts +205 -0
- package/src/core/safe-id.ts +37 -0
- package/src/core/safe-resource-write.ts +162 -0
- package/src/core/session-routing.ts +339 -0
- package/src/core/settings-layers.ts +354 -0
- package/src/core/shared-bus.ts +8 -0
- package/src/core/shell-quote.ts +26 -0
- package/src/core/skill-activation.ts +190 -0
- package/src/core/startup-timer.ts +37 -0
- package/src/core/state-file-lock.ts +219 -0
- package/src/core/termination.ts +275 -0
- package/src/core/timers.ts +38 -0
- package/src/core/tool-names.ts +65 -0
- package/src/core/verification-scripts.ts +13 -0
- package/src/core/workspace-files.ts +492 -0
- package/src/core/xdg.ts +177 -0
- package/src/domains/agents/builtins/architect.md +4 -4
- package/src/domains/agents/builtins/coder.md +3 -2
- package/src/domains/agents/builtins/debugger.md +1 -1
- package/src/domains/agents/builtins/documenter.md +1 -1
- package/src/domains/agents/builtins/git-master.md +3 -3
- package/src/domains/agents/builtins/provenance.md +1 -1
- package/src/domains/agents/builtins/researcher.md +1 -1
- package/src/domains/agents/builtins/scout.md +1 -1
- package/src/domains/agents/builtins/tester.md +1 -1
- package/src/domains/agents/builtins/verifier.md +1 -1
- package/src/domains/agents/builtins/wiki-writer.md +1 -1
- package/src/domains/agents/catalog.ts +172 -0
- package/src/domains/agents/contract.ts +16 -0
- package/src/domains/agents/extension.ts +110 -0
- package/src/domains/agents/fleet-commands.ts +154 -0
- package/src/domains/agents/fleet-contract.ts +797 -0
- package/src/domains/agents/frontmatter.ts +40 -0
- package/src/domains/agents/index.ts +102 -0
- package/src/domains/agents/manifest.ts +6 -0
- package/src/domains/agents/recipe-schema.ts +202 -0
- package/src/domains/agents/recipe.ts +125 -0
- package/src/domains/agents/registry.ts +111 -0
- package/src/domains/agents/result-contract.ts +1265 -0
- package/src/domains/agents/spec.ts +371 -0
- package/src/domains/agents/write-boundary.ts +109 -0
- package/src/domains/components/diff.ts +99 -0
- package/src/domains/components/hash.ts +21 -0
- package/src/domains/components/index.ts +3 -0
- package/src/domains/components/scan.ts +304 -0
- package/src/domains/components/snapshot.ts +108 -0
- package/src/domains/components/types.ts +82 -0
- package/src/domains/config/agent-namespace.ts +13 -0
- package/src/domains/config/classify.ts +106 -0
- package/src/domains/config/contract.ts +22 -0
- package/src/domains/config/extension.ts +142 -0
- package/src/domains/config/index.ts +23 -0
- package/src/domains/config/keybindings.ts +200 -0
- package/src/domains/config/manifest.ts +6 -0
- package/src/domains/config/watcher.ts +41 -0
- package/src/domains/context/adoption.ts +880 -0
- package/src/domains/context/bootstrap-prompt.ts +273 -0
- package/src/domains/context/bootstrap.ts +1502 -0
- package/src/domains/context/clear.ts +91 -0
- package/src/domains/context/clio-md.ts +429 -0
- package/src/domains/context/codewiki/artifact.ts +400 -0
- package/src/domains/context/codewiki/build-worker-protocol.ts +24 -0
- package/src/domains/context/codewiki/build-worker.ts +54 -0
- package/src/domains/context/codewiki/cmake.ts +356 -0
- package/src/domains/context/codewiki/cooperative.ts +46 -0
- package/src/domains/context/codewiki/coordinator.ts +182 -0
- package/src/domains/context/codewiki/digest.ts +135 -0
- package/src/domains/context/codewiki/grammar-assets.ts +33 -0
- package/src/domains/context/codewiki/indexer.ts +1529 -0
- package/src/domains/context/codewiki/paths.ts +67 -0
- package/src/domains/context/codewiki/schema.ts +80 -0
- package/src/domains/context/codewiki/tree-sitter.ts +771 -0
- package/src/domains/context/contract.ts +68 -0
- package/src/domains/context/excluded-dirs.ts +1 -0
- package/src/domains/context/extension.ts +358 -0
- package/src/domains/context/fingerprint.ts +198 -0
- package/src/domains/context/index.ts +154 -0
- package/src/domains/context/init-options.ts +69 -0
- package/src/domains/context/manifest.ts +6 -0
- package/src/domains/context/operator-profile.ts +157 -0
- package/src/domains/context/project-metadata.ts +529 -0
- package/src/domains/context/project-rules.ts +227 -0
- package/src/domains/context/prompt-context.ts +61 -0
- package/src/domains/context/refresh.ts +178 -0
- package/src/domains/context/runtime.ts +17 -0
- package/src/domains/context/sibling-files.ts +10 -0
- package/src/domains/context/state.ts +237 -0
- package/src/domains/context/wiki/assemble.ts +303 -0
- package/src/domains/context/wiki/frontmatter.ts +210 -0
- package/src/domains/context/wiki/generate.ts +595 -0
- package/src/domains/context/wiki/layout.ts +111 -0
- package/src/domains/context/wiki/meta.ts +221 -0
- package/src/domains/context/wiki/plan-store.ts +217 -0
- package/src/domains/context/wiki/plan.ts +250 -0
- package/src/domains/context/wiki/prompts.ts +283 -0
- package/src/domains/context/wiki/staleness.ts +198 -0
- package/src/domains/dispatch/active-route-planner.ts +168 -0
- package/src/domains/dispatch/admission-queue.ts +150 -0
- package/src/domains/dispatch/admission.ts +334 -0
- package/src/domains/dispatch/agent-candidates.ts +307 -0
- package/src/domains/dispatch/agent-ledger-hub.ts +71 -0
- package/src/domains/dispatch/agent-ledger-store.ts +257 -0
- package/src/domains/dispatch/agent-ledger.ts +212 -0
- package/src/domains/dispatch/agent-plan-adapter.ts +85 -0
- package/src/domains/dispatch/assignment-events.ts +132 -0
- package/src/domains/dispatch/assignment-reconcile.ts +76 -0
- package/src/domains/dispatch/assignment-store.ts +162 -0
- package/src/domains/dispatch/assignment.ts +278 -0
- package/src/domains/dispatch/backoff.ts +59 -0
- package/src/domains/dispatch/batch-store.ts +134 -0
- package/src/domains/dispatch/batch-tracker.ts +66 -0
- package/src/domains/dispatch/capability-match.ts +155 -0
- package/src/domains/dispatch/capacity-lease.ts +413 -0
- package/src/domains/dispatch/code-step-store.ts +52 -0
- package/src/domains/dispatch/code-step.ts +387 -0
- package/src/domains/dispatch/contract.ts +278 -0
- package/src/domains/dispatch/dedup.ts +133 -0
- package/src/domains/dispatch/event-pump.ts +251 -0
- package/src/domains/dispatch/execution-handoff.ts +29 -0
- package/src/domains/dispatch/execution-plan.ts +328 -0
- package/src/domains/dispatch/execution-role.ts +277 -0
- package/src/domains/dispatch/execution-scheduler.ts +583 -0
- package/src/domains/dispatch/extension.ts +6006 -0
- package/src/domains/dispatch/failure-classification.ts +147 -0
- package/src/domains/dispatch/fleet-commit-attribution.ts +56 -0
- package/src/domains/dispatch/fleet-plan.ts +225 -0
- package/src/domains/dispatch/fleet-preflight.ts +394 -0
- package/src/domains/dispatch/gate-decisions.ts +1040 -0
- package/src/domains/dispatch/gate-role-prompts.ts +58 -0
- package/src/domains/dispatch/heartbeat.ts +27 -0
- package/src/domains/dispatch/index.ts +137 -0
- package/src/domains/dispatch/joint-route-adapter.ts +114 -0
- package/src/domains/dispatch/joint-route-resolver.ts +283 -0
- package/src/domains/dispatch/manifest.ts +6 -0
- package/src/domains/dispatch/orphan-recovery.ts +266 -0
- package/src/domains/dispatch/outcome.ts +109 -0
- package/src/domains/dispatch/phase-timing.ts +47 -0
- package/src/domains/dispatch/placement.ts +202 -0
- package/src/domains/dispatch/receipt-findings.ts +255 -0
- package/src/domains/dispatch/receipt-integrity.ts +383 -0
- package/src/domains/dispatch/recovery-candidates.ts +74 -0
- package/src/domains/dispatch/reproducibility.ts +48 -0
- package/src/domains/dispatch/reservation-store.ts +501 -0
- package/src/domains/dispatch/route-approval.ts +177 -0
- package/src/domains/dispatch/route-candidates.ts +57 -0
- package/src/domains/dispatch/route-decision.ts +1079 -0
- package/src/domains/dispatch/route-facts.ts +187 -0
- package/src/domains/dispatch/route-history.ts +238 -0
- package/src/domains/dispatch/route-observer.ts +488 -0
- package/src/domains/dispatch/route-policy.ts +327 -0
- package/src/domains/dispatch/route-quality.ts +256 -0
- package/src/domains/dispatch/route-readiness.ts +120 -0
- package/src/domains/dispatch/routing-intent.ts +287 -0
- package/src/domains/dispatch/run-identity.ts +56 -0
- package/src/domains/dispatch/scout-transition.ts +130 -0
- package/src/domains/dispatch/state.ts +302 -0
- package/src/domains/dispatch/tool-stats.ts +132 -0
- package/src/domains/dispatch/transport.ts +210 -0
- package/src/domains/dispatch/types.ts +799 -0
- package/src/domains/dispatch/validation-grounding.ts +154 -0
- package/src/domains/dispatch/validation.ts +721 -0
- package/src/domains/dispatch/worker-protocol.ts +275 -0
- package/src/domains/dispatch/worker-spawn.ts +585 -0
- package/src/domains/dispatch/write-boundary-enforcer.ts +97 -0
- package/src/domains/dispatch/write-boundary.ts +426 -0
- package/src/domains/eval/artifacts/redact.ts +42 -0
- package/src/domains/eval/artifacts/store.ts +173 -0
- package/src/domains/eval/compare/compare.ts +33 -0
- package/src/domains/eval/compare/gates.ts +66 -0
- package/src/domains/eval/compare/thresholds.ts +92 -0
- package/src/domains/eval/harness-metrics.ts +62 -0
- package/src/domains/eval/index.ts +66 -0
- package/src/domains/eval/metrics/chaos-stream.ts +93 -0
- package/src/domains/eval/metrics/context.ts +34 -0
- package/src/domains/eval/metrics/coverage.ts +21 -0
- package/src/domains/eval/metrics/evidence.ts +182 -0
- package/src/domains/eval/metrics/fleet-loop-stream.ts +196 -0
- package/src/domains/eval/metrics/invariants.ts +736 -0
- package/src/domains/eval/metrics/latency.ts +4 -0
- package/src/domains/eval/metrics/token-stream.ts +139 -0
- package/src/domains/eval/metrics/tokens.ts +51 -0
- package/src/domains/eval/metrics/tool-calls.ts +7 -0
- package/src/domains/eval/proactive-memory.ts +279 -0
- package/src/domains/eval/provenance.ts +35 -0
- package/src/domains/eval/report.ts +234 -0
- package/src/domains/eval/reports/json.ts +5 -0
- package/src/domains/eval/reports/junit.ts +23 -0
- package/src/domains/eval/reports/markdown.ts +20 -0
- package/src/domains/eval/reports/swe-jsonl.ts +16 -0
- package/src/domains/eval/reports/text.ts +25 -0
- package/src/domains/eval/run-compare.ts +274 -0
- package/src/domains/eval/runner.ts +244 -0
- package/src/domains/eval/runners/clio-run.ts +148 -0
- package/src/domains/eval/runners/context-index.ts +56 -0
- package/src/domains/eval/runners/context-init.ts +203 -0
- package/src/domains/eval/runners/external-command.ts +350 -0
- package/src/domains/eval/runtime-paths.ts +171 -0
- package/src/domains/eval/schema/artifact.ts +75 -0
- package/src/domains/eval/schema/suite.ts +235 -0
- package/src/domains/eval/schema/validate.ts +339 -0
- package/src/domains/eval/store.ts +392 -0
- package/src/domains/eval/suites/load.ts +74 -0
- package/src/domains/eval/suites/matrix.ts +19 -0
- package/src/domains/eval/suites/resolve.ts +44 -0
- package/src/domains/eval/suites/run.ts +325 -0
- package/src/domains/eval/task-file.ts +186 -0
- package/src/domains/eval/types.ts +140 -0
- package/src/domains/eval/verifiers/command.ts +27 -0
- package/src/domains/eval/verifiers/file-exists.ts +6 -0
- package/src/domains/eval/verifiers/patch.ts +22 -0
- package/src/domains/eval/workspaces/git.ts +41 -0
- package/src/domains/eval/workspaces/local.ts +17 -0
- package/src/domains/eval/workspaces/temp-copy.ts +29 -0
- package/src/domains/evidence/build.ts +1754 -0
- package/src/domains/evidence/eval.ts +605 -0
- package/src/domains/evidence/failure-attribution.ts +54 -0
- package/src/domains/evidence/finish-contract-map.ts +42 -0
- package/src/domains/evidence/index.ts +55 -0
- package/src/domains/evidence/provenance.ts +200 -0
- package/src/domains/evidence/redact.ts +81 -0
- package/src/domains/evidence/store.ts +291 -0
- package/src/domains/evidence/types.ts +325 -0
- package/src/domains/evolution/SELF_EDIT_GATE.md +91 -0
- package/src/domains/evolution/index.ts +26 -0
- package/src/domains/evolution/manifest.ts +154 -0
- package/src/domains/evolution/validate.ts +304 -0
- package/src/domains/extensions/contract.ts +22 -0
- package/src/domains/extensions/discovery.ts +193 -0
- package/src/domains/extensions/extension.ts +46 -0
- package/src/domains/extensions/index.ts +34 -0
- package/src/domains/extensions/manager.ts +30 -0
- package/src/domains/extensions/manifest.ts +6 -0
- package/src/domains/extensions/resources.ts +38 -0
- package/src/domains/extensions/state.ts +224 -0
- package/src/domains/extensions/types.ts +83 -0
- package/src/domains/interop/consent.ts +185 -0
- package/src/domains/interop/contract.ts +29 -0
- package/src/domains/interop/detect.ts +173 -0
- package/src/domains/interop/extension.ts +59 -0
- package/src/domains/interop/index.ts +34 -0
- package/src/domains/interop/manifest.ts +6 -0
- package/src/domains/interop/registry.ts +139 -0
- package/src/domains/interop/state.ts +92 -0
- package/src/domains/interop/types.ts +109 -0
- package/src/domains/lifecycle/contract.ts +11 -0
- package/src/domains/lifecycle/doctor.ts +536 -0
- package/src/domains/lifecycle/extension.ts +23 -0
- package/src/domains/lifecycle/index.ts +21 -0
- package/src/domains/lifecycle/install-method.ts +51 -0
- package/src/domains/lifecycle/manifest.ts +6 -0
- package/src/domains/lifecycle/migrations/2026-08-18-lmstudio-runtime-id.ts +52 -0
- package/src/domains/lifecycle/migrations/index.ts +114 -0
- package/src/domains/lifecycle/state.ts +93 -0
- package/src/domains/lifecycle/upgrade-notice.ts +35 -0
- package/src/domains/lifecycle/version.ts +35 -0
- package/src/domains/memory/index.ts +128 -0
- package/src/domains/memory/operations.ts +143 -0
- package/src/domains/memory/prompt-section.ts +86 -0
- package/src/domains/memory/proposal.ts +180 -0
- package/src/domains/memory/store.ts +163 -0
- package/src/domains/memory/task-bank.ts +229 -0
- package/src/domains/memory/task-memory-handoff.ts +222 -0
- package/src/domains/memory/task-memory-policy.ts +602 -0
- package/src/domains/memory/task-memory-status.ts +58 -0
- package/src/domains/memory/task-memory-telemetry.ts +346 -0
- package/src/domains/memory/task-memory-trace.ts +89 -0
- package/src/domains/memory/types.ts +74 -0
- package/src/domains/memory/validate.ts +297 -0
- package/src/domains/middleware/budget.ts +216 -0
- package/src/domains/middleware/contract.ts +35 -0
- package/src/domains/middleware/dispatch-nudge.ts +469 -0
- package/src/domains/middleware/extension.ts +129 -0
- package/src/domains/middleware/hook-receipts.ts +70 -0
- package/src/domains/middleware/hooks-io.ts +186 -0
- package/src/domains/middleware/hooks.ts +432 -0
- package/src/domains/middleware/index.ts +154 -0
- package/src/domains/middleware/manifest.ts +6 -0
- package/src/domains/middleware/memory-intervention.ts +701 -0
- package/src/domains/middleware/rules.ts +42 -0
- package/src/domains/middleware/runtime.ts +333 -0
- package/src/domains/middleware/skills-reminder.ts +202 -0
- package/src/domains/middleware/snapshot.ts +71 -0
- package/src/domains/middleware/stalled-turn.ts +71 -0
- package/src/domains/middleware/task-board-reminder.ts +87 -0
- package/src/domains/middleware/task-nudge.ts +77 -0
- package/src/domains/middleware/tool-choice-control.ts +42 -0
- package/src/domains/middleware/types.ts +131 -0
- package/src/domains/middleware/validate.ts +329 -0
- package/src/domains/observability/accountability.ts +67 -0
- package/src/domains/observability/contract.ts +168 -0
- package/src/domains/observability/cost.ts +206 -0
- package/src/domains/observability/evidence-index.ts +123 -0
- package/src/domains/observability/extension.ts +281 -0
- package/src/domains/observability/index.ts +78 -0
- package/src/domains/observability/manifest.ts +10 -0
- package/src/domains/observability/metrics.ts +37 -0
- package/src/domains/observability/projection.ts +477 -0
- package/src/domains/observability/telemetry.ts +89 -0
- package/src/domains/observability/trace-store.ts +1454 -0
- package/src/domains/prompts/compiler.ts +614 -0
- package/src/domains/prompts/contract.ts +46 -0
- package/src/domains/prompts/extension.ts +336 -0
- package/src/domains/prompts/fragment-loader.ts +138 -0
- package/src/domains/prompts/fragments/identity/clio.md +5 -6
- package/src/domains/prompts/fragments/identity/docs-routing.md +10 -0
- package/src/domains/prompts/fragments/identity/self-awareness.md +19 -0
- package/src/domains/prompts/fragments/operating/contract.md +4 -41
- package/src/domains/prompts/fragments/operating/delegation.md +42 -0
- package/src/domains/prompts/fragments/operating/skills.md +26 -0
- package/src/domains/prompts/fragments/operating/worker.md +16 -0
- package/src/domains/prompts/fragments/safety/auto-edit.md +5 -5
- package/src/domains/prompts/fragments/safety/full-auto.md +3 -3
- package/src/domains/prompts/fragments/safety/read-only.md +4 -4
- package/src/domains/prompts/fragments/safety/suggest.md +2 -2
- package/src/domains/prompts/fragments/wiki/page.md +10 -0
- package/src/domains/prompts/fragments/wiki/plan.md +10 -0
- package/src/domains/prompts/hash.ts +73 -0
- package/src/domains/prompts/index.ts +32 -0
- package/src/domains/prompts/manifest.ts +8 -0
- package/src/domains/prompts/memory-intervention.ts +57 -0
- package/src/domains/prompts/preload.ts +82 -0
- package/src/domains/providers/auth/api-key.ts +47 -0
- package/src/domains/providers/auth/backend-file.ts +79 -0
- package/src/domains/providers/auth/backend-memory.ts +72 -0
- package/src/domains/providers/auth/boot-status.ts +65 -0
- package/src/domains/providers/auth/index.ts +37 -0
- package/src/domains/providers/auth/oauth.ts +37 -0
- package/src/domains/providers/auth/storage.ts +726 -0
- package/src/domains/providers/capabilities.ts +58 -0
- package/src/domains/providers/catalog.ts +162 -0
- package/src/domains/providers/contract.ts +162 -0
- package/src/domains/providers/credentials.ts +20 -0
- package/src/domains/providers/eligibility.ts +24 -0
- package/src/domains/providers/errors.ts +64 -0
- package/src/domains/providers/extension.ts +548 -0
- package/src/domains/providers/index.ts +142 -0
- package/src/domains/providers/knowledge-base-path.ts +102 -0
- package/src/domains/providers/manifest.ts +6 -0
- package/src/domains/providers/model-capabilities.ts +136 -0
- package/src/domains/providers/model-discovery.ts +144 -0
- package/src/domains/providers/model-family.ts +32 -0
- package/src/domains/providers/model-runtime-capabilities.ts +723 -0
- package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +120 -37
- package/src/domains/providers/plugins.ts +61 -0
- package/src/domains/providers/probe/fingerprint.ts +64 -0
- package/src/domains/providers/probe/http.ts +114 -0
- package/src/domains/providers/probe/reasoning.ts +111 -0
- package/src/domains/providers/registry.ts +187 -0
- package/src/domains/providers/resolver.ts +156 -0
- package/src/domains/providers/runtime-resolution.ts +720 -0
- package/src/domains/providers/runtimes/antigravity/antigravity-code.ts +90 -0
- package/src/domains/providers/runtimes/boot-manifest.ts +55 -0
- package/src/domains/providers/runtimes/builtins.ts +78 -0
- package/src/domains/providers/runtimes/claude/claude-code.ts +38 -0
- package/src/domains/providers/runtimes/claude/claude-sdk.ts +38 -0
- package/src/domains/providers/runtimes/claude/common.ts +55 -0
- package/src/domains/providers/runtimes/cloud/alcf.ts +171 -0
- package/src/domains/providers/runtimes/cloud/anthropic-max.ts +71 -0
- package/src/domains/providers/runtimes/cloud/anthropic.ts +43 -0
- package/src/domains/providers/runtimes/cloud/bedrock.ts +35 -0
- package/src/domains/providers/runtimes/cloud/deepseek.ts +50 -0
- package/src/domains/providers/runtimes/cloud/google.ts +41 -0
- package/src/domains/providers/runtimes/cloud/groq.ts +46 -0
- package/src/domains/providers/runtimes/cloud/mistral.ts +46 -0
- package/src/domains/providers/runtimes/cloud/openai-codex.ts +49 -0
- package/src/domains/providers/runtimes/cloud/openai.ts +46 -0
- package/src/domains/providers/runtimes/cloud/openrouter.ts +111 -0
- package/src/domains/providers/runtimes/common/lmstudio-http.ts +423 -0
- package/src/domains/providers/runtimes/common/local-synth.ts +164 -0
- package/src/domains/providers/runtimes/common/probe-helpers.ts +474 -0
- package/src/domains/providers/runtimes/local-native/lemonade-anthropic.ts +27 -0
- package/src/domains/providers/runtimes/local-native/lemonade-openai.ts +26 -0
- package/src/domains/providers/runtimes/local-native/llamacpp-anthropic.ts +88 -0
- package/src/domains/providers/runtimes/local-native/llamacpp-completion.ts +207 -0
- package/src/domains/providers/runtimes/local-native/llamacpp-embed.ts +180 -0
- package/src/domains/providers/runtimes/local-native/llamacpp-rerank.ts +126 -0
- package/src/domains/providers/runtimes/local-native/llamacpp.ts +98 -0
- package/src/domains/providers/runtimes/local-native/lmstudio.ts +241 -0
- package/src/domains/providers/runtimes/local-native/ollama-native.ts +117 -0
- package/src/domains/providers/runtimes/local-native/sglang.ts +26 -0
- package/src/domains/providers/runtimes/local-native/vllm.ts +27 -0
- package/src/domains/providers/runtimes/protocol/anthropic-compat.ts +104 -0
- package/src/domains/providers/runtimes/protocol/anthropic-messages.ts +28 -0
- package/src/domains/providers/runtimes/protocol/bedrock.ts +26 -0
- package/src/domains/providers/runtimes/protocol/google.ts +27 -0
- package/src/domains/providers/runtimes/protocol/openai-compat.ts +145 -0
- package/src/domains/providers/support.ts +241 -0
- package/src/domains/providers/thinking-control-policy.ts +85 -0
- package/src/domains/providers/types/capability-flags.ts +114 -0
- package/src/domains/providers/types/cost-provenance.ts +7 -0
- package/src/domains/providers/types/inference.ts +41 -0
- package/src/domains/providers/types/knowledge-base.ts +156 -0
- package/src/domains/providers/types/local-model-quirks.ts +216 -0
- package/src/domains/providers/types/runtime-descriptor.ts +181 -0
- package/src/domains/providers/types/target-descriptor.ts +60 -0
- package/src/domains/resources/collision.ts +92 -0
- package/src/domains/resources/common-loader.ts +140 -0
- package/src/domains/resources/contract.ts +24 -0
- package/src/domains/resources/extension.ts +59 -0
- package/src/domains/resources/index.ts +74 -0
- package/src/domains/resources/loader.ts +85 -0
- package/src/domains/resources/manifest.ts +6 -0
- package/src/domains/resources/prompts/loader.ts +246 -0
- package/src/domains/resources/prompts/substitute.ts +1 -0
- package/src/domains/resources/skills/content-hash.ts +107 -0
- package/src/domains/resources/skills/evals.ts +175 -0
- package/src/domains/resources/skills/install.ts +427 -0
- package/src/domains/resources/skills/loader.ts +985 -0
- package/src/domains/resources/skills/marketplace.ts +301 -0
- package/src/domains/resources/skills/provenance-pin.ts +115 -0
- package/src/domains/safety/action-classifier.ts +270 -0
- package/src/domains/safety/approval-axis.ts +23 -0
- package/src/domains/safety/audit.ts +493 -0
- package/src/domains/safety/autonomy.ts +174 -0
- package/src/domains/safety/call-target.ts +59 -0
- package/src/domains/safety/contract.ts +65 -0
- package/src/domains/safety/damage-control.ts +44 -0
- package/src/domains/safety/default-path-policy.ts +117 -0
- package/src/domains/safety/extension.ts +383 -0
- package/src/domains/safety/finish-contract-registration.ts +128 -0
- package/src/domains/safety/finish-contract.ts +554 -0
- package/src/domains/safety/index.ts +44 -0
- package/src/domains/safety/loop-detector.ts +143 -0
- package/src/domains/safety/manifest.ts +6 -0
- package/src/domains/safety/path-policy.ts +164 -0
- package/src/domains/safety/policy-engine.ts +994 -0
- package/src/domains/safety/project-policy.ts +391 -0
- package/src/domains/safety/protected-artifacts-registration.ts +189 -0
- package/src/domains/safety/protected-artifacts.ts +993 -0
- package/src/domains/safety/rejection-feedback.ts +102 -0
- package/src/domains/safety/rigor.ts +72 -0
- package/src/domains/safety/rule-compiler.ts +48 -0
- package/src/domains/safety/rule-pack-loader.ts +92 -0
- package/src/domains/safety/run-effects.ts +197 -0
- package/src/domains/safety/scope.ts +61 -0
- package/src/domains/scheduling/budget.ts +35 -0
- package/src/domains/scheduling/cluster.ts +175 -0
- package/src/domains/scheduling/contract.ts +30 -0
- package/src/domains/scheduling/extension.ts +91 -0
- package/src/domains/scheduling/index.ts +12 -0
- package/src/domains/scheduling/manifest.ts +6 -0
- package/src/domains/session/archive-readers.ts +208 -0
- package/src/domains/session/checkpoint.ts +38 -0
- package/src/domains/session/compaction/auto.ts +89 -0
- package/src/domains/session/compaction/branch-summary.ts +187 -0
- package/src/domains/session/compaction/compact.ts +493 -0
- package/src/domains/session/compaction/cut-point.ts +172 -0
- package/src/domains/session/compaction/defaults.ts +34 -0
- package/src/domains/session/compaction/mask-observations.ts +265 -0
- package/src/domains/session/compaction/session-entries.ts +18 -0
- package/src/domains/session/compaction/tokens.ts +148 -0
- package/src/domains/session/context-accounting.ts +583 -0
- package/src/domains/session/context-ledger.ts +362 -0
- package/src/domains/session/contract.ts +159 -0
- package/src/domains/session/cwd-fallback.ts +65 -0
- package/src/domains/session/decision-board.ts +190 -0
- package/src/domains/session/entries.ts +572 -0
- package/src/domains/session/extension.ts +403 -0
- package/src/domains/session/history.ts +172 -0
- package/src/domains/session/index.ts +84 -0
- package/src/domains/session/manager.ts +128 -0
- package/src/domains/session/manifest.ts +6 -0
- package/src/domains/session/migrations/index.ts +27 -0
- package/src/domains/session/prompt-manifest.ts +173 -0
- package/src/domains/session/protected-artifact-journal.ts +241 -0
- package/src/domains/session/protected-artifacts.ts +90 -0
- package/src/domains/session/retry.ts +230 -0
- package/src/domains/session/session-artifacts.ts +107 -0
- package/src/domains/session/task-board.ts +569 -0
- package/src/domains/session/tree/active-path.ts +137 -0
- package/src/domains/session/tree/fork.ts +159 -0
- package/src/domains/session/tree/manager.ts +128 -0
- package/src/domains/session/tree/navigator.ts +177 -0
- package/src/domains/session/tree/preview.ts +259 -0
- package/src/domains/session/usage.ts +148 -0
- package/src/domains/session/workspace/git-probe.ts +167 -0
- package/src/domains/session/workspace/index.ts +4 -0
- package/src/domains/session/workspace/project-type.ts +217 -0
- package/src/domains/session/workspace/snapshot.ts +74 -0
- package/src/domains/share/archive.ts +684 -0
- package/src/domains/share/contract.ts +9 -0
- package/src/domains/share/extension.ts +26 -0
- package/src/domains/share/index.ts +28 -0
- package/src/domains/share/manifest.ts +6 -0
- package/src/domains/user-tasks/store.ts +297 -0
- package/src/engine/acp/adapter.ts +397 -0
- package/src/engine/acp/errors.ts +128 -0
- package/src/engine/acp/event-mapper.ts +154 -0
- package/src/engine/acp/server.ts +2238 -0
- package/src/engine/acp/tool-mediator.ts +686 -0
- package/src/engine/acp/transport.ts +775 -0
- package/src/engine/acp/types.ts +196 -0
- package/src/engine/agent.ts +29 -0
- package/src/engine/ai.ts +207 -0
- package/src/engine/alcf-oauth.ts +205 -0
- package/src/engine/antigravity/subprocess-runtime.ts +205 -0
- package/src/engine/api-registry.ts +223 -0
- package/src/engine/apis/degraded-inference.ts +95 -0
- package/src/engine/apis/index.ts +16 -0
- package/src/engine/apis/llamacpp-residency.ts +292 -0
- package/src/engine/apis/lmstudio-residency.ts +76 -0
- package/src/engine/apis/lmstudio.ts +243 -0
- package/src/engine/apis/ollama-native.ts +528 -0
- package/src/engine/apis/openai-completions.ts +795 -0
- package/src/engine/apis/output-budget.ts +99 -0
- package/src/engine/apis/residency-lock.ts +29 -0
- package/src/engine/apis/residency.ts +776 -0
- package/src/engine/apis/resident-models.ts +42 -0
- package/src/engine/apis/sampling-overrides.ts +38 -0
- package/src/engine/apis/types.ts +16 -0
- package/src/engine/claude/sdk-runtime.ts +685 -0
- package/src/engine/claude/session-id.ts +5 -0
- package/src/engine/claude/subprocess-runtime.ts +316 -0
- package/src/engine/claude/tool-safety.ts +400 -0
- package/src/engine/env-api-keys.ts +98 -0
- package/src/engine/external-subprocess.ts +23 -0
- package/src/engine/gemma-channel-filter.ts +223 -0
- package/src/engine/harmony-response.ts +165 -0
- package/src/engine/instrumented-tui.ts +192 -0
- package/src/engine/loop-guard.ts +1127 -0
- package/src/engine/messages.ts +14 -0
- package/src/engine/models.ts +42 -0
- package/src/engine/oauth.ts +196 -0
- package/src/engine/pi-mono-names.ts +13 -0
- package/src/engine/prompt-templates.ts +1 -0
- package/src/engine/provider-payload.ts +272 -0
- package/src/engine/select-list.ts +53 -0
- package/src/engine/session.ts +834 -0
- package/src/engine/strip-tokenizer-sentinels.ts +125 -0
- package/src/engine/truncate.ts +9 -0
- package/src/engine/tui.ts +111 -0
- package/src/engine/types.ts +63 -0
- package/src/engine/worker-events.ts +100 -0
- package/src/engine/worker-runtime-capabilities.ts +5 -0
- package/src/engine/worker-runtime.ts +1022 -0
- package/src/engine/worker-tools.ts +208 -0
- package/src/entry/boot-options.ts +50 -0
- package/src/entry/orchestrator.ts +2011 -0
- package/src/interactive/application-controller.ts +433 -0
- package/src/interactive/bus-notices.ts +265 -0
- package/src/interactive/chat-loop-messages.ts +626 -0
- package/src/interactive/chat-loop-policy.ts +18 -0
- package/src/interactive/chat-loop.ts +1090 -0
- package/src/interactive/chat-panel.ts +1820 -0
- package/src/interactive/chat-renderer.ts +1228 -0
- package/src/interactive/clio-editor.ts +161 -0
- package/src/interactive/command-fallbacks.ts +23 -0
- package/src/interactive/command-output.ts +85 -0
- package/src/interactive/context-activity.ts +203 -0
- package/src/interactive/context-meter.ts +223 -0
- package/src/interactive/context-overlay.ts +246 -0
- package/src/interactive/cost-overlay.ts +279 -0
- package/src/interactive/dispatch-board.ts +1319 -0
- package/src/interactive/dispatch-steering.ts +86 -0
- package/src/interactive/editor-bash.ts +46 -0
- package/src/interactive/editor-steer.ts +51 -0
- package/src/interactive/editor-submit.ts +507 -0
- package/src/interactive/export-html/ansi-to-html.ts +161 -0
- package/src/interactive/export-html/index.ts +51 -0
- package/src/interactive/export-html/template.ts +45 -0
- package/src/interactive/export-html/tool-renderer.ts +54 -0
- package/src/interactive/external-editor.ts +67 -0
- package/src/interactive/follow-up-queue-panel.ts +75 -0
- package/src/interactive/footer/dashboard.ts +538 -0
- package/src/interactive/footer/notifications.ts +275 -0
- package/src/interactive/footer/widgets.ts +1264 -0
- package/src/interactive/footer-panel.ts +187 -0
- package/src/interactive/format-time.ts +97 -0
- package/src/interactive/index.ts +11 -0
- package/src/interactive/interactive-application.ts +939 -0
- package/src/interactive/interactive-event-projection.ts +385 -0
- package/src/interactive/interactive-input-runtime.ts +307 -0
- package/src/interactive/interactive-presentation.ts +584 -0
- package/src/interactive/interactive-shell.ts +388 -0
- package/src/interactive/interactive-slash-runtime.ts +554 -0
- package/src/interactive/interactive-subscriptions.ts +111 -0
- package/src/interactive/interactive-tickers.ts +183 -0
- package/src/interactive/keybinding-manager.ts +496 -0
- package/src/interactive/layout.ts +57 -0
- package/src/interactive/leader-key.ts +143 -0
- package/src/interactive/loop-guard-interrupt.ts +101 -0
- package/src/interactive/memory-overlay.ts +280 -0
- package/src/interactive/overlay-ask-user-lifecycle.ts +110 -0
- package/src/interactive/overlay-auth-lifecycle.ts +308 -0
- package/src/interactive/overlay-frame.ts +502 -0
- package/src/interactive/overlay-general-openers.ts +274 -0
- package/src/interactive/overlay-key-routing.ts +216 -0
- package/src/interactive/overlay-lifecycle.ts +426 -0
- package/src/interactive/overlay-model-selectors.ts +127 -0
- package/src/interactive/overlay-permission-lifecycle.ts +345 -0
- package/src/interactive/overlay-resource-openers.ts +112 -0
- package/src/interactive/overlay-session-lifecycle.ts +327 -0
- package/src/interactive/overlay-transitions.ts +57 -0
- package/src/interactive/overlays/agents.ts +69 -0
- package/src/interactive/overlays/ask-user.ts +921 -0
- package/src/interactive/overlays/auth-dialog.ts +221 -0
- package/src/interactive/overlays/context-reset.ts +108 -0
- package/src/interactive/overlays/cwd-fallback.ts +141 -0
- package/src/interactive/overlays/decisions.ts +300 -0
- package/src/interactive/overlays/extensions.ts +54 -0
- package/src/interactive/overlays/help-reference.ts +145 -0
- package/src/interactive/overlays/interop.ts +139 -0
- package/src/interactive/overlays/keybinding-detail.ts +90 -0
- package/src/interactive/overlays/list-overlay.ts +606 -0
- package/src/interactive/overlays/message-picker.ts +155 -0
- package/src/interactive/overlays/model-selector.ts +1109 -0
- package/src/interactive/overlays/prompts.ts +72 -0
- package/src/interactive/overlays/session-selector-search.ts +31 -0
- package/src/interactive/overlays/session-selector.ts +284 -0
- package/src/interactive/overlays/settings.ts +3451 -0
- package/src/interactive/overlays/skills-hub.ts +237 -0
- package/src/interactive/overlays/tree-selector.ts +422 -0
- package/src/interactive/permission-overlay.ts +170 -0
- package/src/interactive/render-trace.ts +534 -0
- package/src/interactive/renderers/branch-summary.ts +86 -0
- package/src/interactive/renderers/code-ink.ts +420 -0
- package/src/interactive/renderers/compaction-summary.ts +112 -0
- package/src/interactive/renderers/diff.ts +137 -0
- package/src/interactive/renderers/mermaid.ts +53 -0
- package/src/interactive/renderers/notice.ts +28 -0
- package/src/interactive/renderers/retry-status.ts +31 -0
- package/src/interactive/renderers/structured.ts +89 -0
- package/src/interactive/renderers/tool-execution.ts +1357 -0
- package/src/interactive/renderers/worker-entry.ts +280 -0
- package/src/interactive/session-last-turn.ts +186 -0
- package/src/interactive/session-switch-settlement.ts +10 -0
- package/src/interactive/session-transcript.ts +105 -0
- package/src/interactive/session-usage-reseed.ts +74 -0
- package/src/interactive/slash-autocomplete.ts +256 -0
- package/src/interactive/slash-commands.ts +1407 -0
- package/src/interactive/slash-spec.ts +424 -0
- package/src/interactive/status/controller.ts +260 -0
- package/src/interactive/status/index.ts +23 -0
- package/src/interactive/status/state-machine.ts +530 -0
- package/src/interactive/status/summary.ts +170 -0
- package/src/interactive/status/types.ts +121 -0
- package/src/interactive/status/verbs.ts +163 -0
- package/src/interactive/status/watchdog.ts +24 -0
- package/src/interactive/stdout-backpressure.ts +99 -0
- package/src/interactive/stream-pacer.ts +530 -0
- package/src/interactive/stream-pacing-policy.ts +66 -0
- package/src/interactive/tasks-overlay.ts +540 -0
- package/src/interactive/terminal-lease.ts +485 -0
- package/src/interactive/theme/components.ts +55 -0
- package/src/interactive/theme/glyphs.ts +70 -0
- package/src/interactive/theme/index.ts +15 -0
- package/src/interactive/theme/labels.ts +88 -0
- package/src/interactive/theme/rules.ts +138 -0
- package/src/interactive/theme/segments.ts +88 -0
- package/src/interactive/theme/tokens.ts +121 -0
- package/src/interactive/thinking-level-policy.ts +6 -0
- package/src/interactive/tool-prose-loop.ts +122 -0
- package/src/interactive/tool-prose-registration.ts +48 -0
- package/src/interactive/turn-context.ts +855 -0
- package/src/interactive/turn-middleware.ts +283 -0
- package/src/interactive/turn-persistence.ts +458 -0
- package/src/interactive/turn-queues.ts +181 -0
- package/src/interactive/turn-recovery.ts +323 -0
- package/src/interactive/turn-runtime.ts +869 -0
- package/src/interactive/turn-state.ts +133 -0
- package/src/interactive/view/artifacts.ts +1452 -0
- package/src/interactive/view/view-overlay.ts +735 -0
- package/src/interactive/welcome-dashboard.ts +537 -0
- package/src/interactive/worker-receipts.ts +143 -0
- package/src/interactive/worker-replay.ts +111 -0
- package/src/interactive/worker-share.ts +100 -0
- package/src/interactive/worker-stream.ts +446 -0
- package/src/interactive/workspace-facts.ts +141 -0
- package/src/tools/agent-tools.ts +402 -0
- package/src/tools/artifact.ts +103 -0
- package/src/tools/ask-user.ts +666 -0
- package/src/tools/bash.ts +204 -0
- package/src/tools/bootstrap.ts +77 -0
- package/src/tools/builtin-tool-catalog.ts +265 -0
- package/src/tools/codewiki/code-nav-surface.ts +29 -0
- package/src/tools/codewiki/code-nav.ts +549 -0
- package/src/tools/codewiki/shared.ts +118 -0
- package/src/tools/compete-worktrees.ts +898 -0
- package/src/tools/context/docs-engine.ts +630 -0
- package/src/tools/context/index.ts +514 -0
- package/src/tools/context/surface.ts +19 -0
- package/src/tools/core-bootstrap.ts +168 -0
- package/src/tools/credential-present.ts +151 -0
- package/src/tools/dispatch-admission.ts +533 -0
- package/src/tools/dispatch-arguments.ts +228 -0
- package/src/tools/dispatch-background.ts +54 -0
- package/src/tools/dispatch-event-text.ts +6 -0
- package/src/tools/dispatch-plan.ts +746 -0
- package/src/tools/dispatch-run-events.ts +238 -0
- package/src/tools/dispatch-runner.ts +2370 -0
- package/src/tools/dispatch-scout-admission.ts +295 -0
- package/src/tools/dispatch-scout.ts +461 -0
- package/src/tools/dispatch-types.ts +77 -0
- package/src/tools/dispatch.ts +244 -0
- package/src/tools/edit-diff.ts +534 -0
- package/src/tools/edit.ts +128 -0
- package/src/tools/executables.ts +22 -0
- package/src/tools/file-mutation-queue.ts +35 -0
- package/src/tools/find.ts +294 -0
- package/src/tools/grep.ts +495 -0
- package/src/tools/ignore-policy.ts +169 -0
- package/src/tools/lazy-tool.ts +60 -0
- package/src/tools/ledger.ts +206 -0
- package/src/tools/ls.ts +110 -0
- package/src/tools/monitor-surface.ts +36 -0
- package/src/tools/monitor.ts +767 -0
- package/src/tools/network-policy.ts +29 -0
- package/src/tools/observation.ts +421 -0
- package/src/tools/observers.ts +99 -0
- package/src/tools/path-utils.ts +79 -0
- package/src/tools/policy.ts +154 -0
- package/src/tools/profiles.ts +108 -0
- package/src/tools/read.ts +173 -0
- package/src/tools/registry.ts +1169 -0
- package/src/tools/result-shaping.ts +204 -0
- package/src/tools/safe-exec.ts +128 -0
- package/src/tools/spawn-hygiene.ts +182 -0
- package/src/tools/steer-surface.ts +17 -0
- package/src/tools/steer.ts +77 -0
- package/src/tools/tasks.ts +265 -0
- package/src/tools/truncate-utf8.ts +17 -0
- package/src/tools/truncate.ts +43 -0
- package/src/tools/verify/frontend.ts +687 -0
- package/src/tools/verify/index.ts +31 -0
- package/src/tools/verify/scripts.ts +108 -0
- package/src/tools/verify/surface.ts +46 -0
- package/src/tools/web-fetch-surface.ts +23 -0
- package/src/tools/web-fetch.ts +759 -0
- package/src/tools/worker-evidence.ts +215 -0
- package/src/tools/write.ts +57 -0
- package/src/utils/exif-orientation.ts +192 -0
- package/src/utils/git.ts +24 -0
- package/src/utils/image-resize.ts +148 -0
- package/src/utils/photon.ts +103 -0
- package/src/worker/control-lane.ts +22 -0
- package/src/worker/entry.ts +294 -0
- package/src/worker/event-projection.ts +56 -0
- package/src/worker/heartbeat.ts +24 -0
- package/src/worker/ledger-mirror.ts +95 -0
- package/src/worker/ndjson.ts +40 -0
- package/src/worker/protocol.ts +529 -0
- package/src/worker/resource-facts.ts +79 -0
- package/src/worker/runtime-registry.ts +12 -0
- package/src/worker/spec-contract.ts +675 -0
- package/src/worker/stdin-demux.ts +316 -0
- package/dist/acp-UMLFVA3F.js +0 -92
- package/dist/chunk-262G75JS.js +0 -35
- package/dist/chunk-6CWDTGUC.js +0 -20
- package/dist/chunk-BYEU76JP.js +0 -899
- package/dist/chunk-GNGDQYDU.js +0 -34688
- package/dist/chunk-GOTUR54M.js +0 -9
- package/dist/chunk-NI4DEJMC.js +0 -88
- package/dist/chunk-TPOCL34A.js +0 -2876
- package/dist/chunk-UU3R62TT.js +0 -128
- package/dist/clio-KIQ5SNDS.js +0 -53
- package/dist/configure-G4E3A2PG.js +0 -27
- package/dist/doctor-M5HJJZOL.js +0 -61
- package/dist/domains/agents/builtins/architect.md +0 -33
- package/dist/domains/agents/builtins/coder.md +0 -31
- package/dist/domains/agents/builtins/context-bootstrap.md +0 -38
- package/dist/domains/agents/builtins/debugger.md +0 -30
- package/dist/domains/agents/builtins/documenter.md +0 -31
- package/dist/domains/agents/builtins/git-master.md +0 -30
- package/dist/domains/agents/builtins/provenance.md +0 -30
- package/dist/domains/agents/builtins/researcher.md +0 -71
- package/dist/domains/agents/builtins/scout.md +0 -42
- package/dist/domains/agents/builtins/tester.md +0 -31
- package/dist/domains/agents/builtins/verifier.md +0 -30
- package/dist/domains/agents/builtins/wiki-writer.md +0 -41
- package/dist/fleet-preflight-CLIAX7YR.js +0 -21
- package/dist/preload-KZVHET2B.js +0 -11
- package/dist/version-ROZ6CZKH.js +0 -16
- package/docs/html/agents_blueprint.html +0 -936
- package/docs/html/alcf_blueprint.html +0 -324
- package/docs/html/architecture_blueprint.html +0 -850
- package/docs/html/commands_blueprint.html +0 -794
- package/docs/html/config_knobs_audit_blueprint.html +0 -178
- package/docs/html/configuration_blueprint.html +0 -1080
- package/docs/html/context_blueprint.html +0 -603
- package/docs/html/documentation_blueprint.html +0 -832
- package/docs/html/environment_blueprint.html +0 -404
- package/docs/html/eval_blueprint.html +0 -743
- package/docs/html/evals_internal_blueprint.html +0 -190
- package/docs/html/evolution_blueprint.html +0 -674
- package/docs/html/extensions_blueprint.html +0 -2065
- package/docs/html/fleet_dispatch_blueprint.html +0 -286
- package/docs/html/index.html +0 -919
- package/docs/html/lifecycle_blueprint.html +0 -723
- package/docs/html/memory_blueprint.html +0 -699
- package/docs/html/middleware_blueprint.html +0 -664
- package/docs/html/models_blueprint.html +0 -2366
- package/docs/html/observability_blueprint.html +0 -683
- package/docs/html/provider_adapter_blueprint.html +0 -245
- package/docs/html/safety_blueprint.html +0 -1386
- package/docs/html/shared.css +0 -571
- package/docs/html/shared.js +0 -143
- package/docs/html/skills_blueprint.html +0 -671
- package/docs/html/soak_blueprint.html +0 -182
- package/docs/html/tool_usage_blueprint.html +0 -350
- package/docs/html/tools_blueprint.html +0 -2249
- package/docs/html/trace_blueprint.html +0 -235
- package/docs/html/tui_design_blueprint.html +0 -314
- package/docs/html/validation_blueprint.html +0 -961
- package/docs/html/worker_dispatch_blueprint.html +0 -231
- package/skills/git/commit-crafting/SKILL.md +0 -79
- package/skills/git/commit-crafting/evals.md +0 -92
- package/skills/git/create-pr/SKILL.md +0 -116
- package/skills/git/create-pr/evals.md +0 -114
- package/skills/git/investigate-issue/SKILL.md +0 -139
- package/skills/git/investigate-issue/evals.md +0 -94
- package/skills/git/review-changes/SKILL.md +0 -103
- package/skills/git/review-changes/evals.md +0 -85
|
@@ -0,0 +1,1529 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
3
|
+
import { readFile as readFileAsync } from "node:fs/promises";
|
|
4
|
+
import { dirname, join, relative, resolve } from "node:path";
|
|
5
|
+
import { classifyCHeaderLanguage, isAmbiguousHeaderPath } from "../../../core/c-header-language.js";
|
|
6
|
+
import { safeResourceWrite } from "../../../core/safe-resource-write.js";
|
|
7
|
+
import { enumerateWorkspaceFilesAsync, filterWorkspaceFileCandidates } from "../../../core/workspace-files.js";
|
|
8
|
+
import type { ProjectType } from "../../session/workspace/project-type.js";
|
|
9
|
+
import { EXCLUDED_DIRS } from "../excluded-dirs.js";
|
|
10
|
+
import { extractCMake, isCMakePath } from "./cmake.js";
|
|
11
|
+
import { type CooperativeSlicer, createSlicer } from "./cooperative.js";
|
|
12
|
+
import { isIndexablePath, languageForPath } from "./paths.js";
|
|
13
|
+
import {
|
|
14
|
+
type BuildCodewikiInput,
|
|
15
|
+
CODEWIKI_VERSION,
|
|
16
|
+
type Codewiki,
|
|
17
|
+
type CodewikiEdge,
|
|
18
|
+
type CodewikiEntry,
|
|
19
|
+
type CodewikiExternalEdge,
|
|
20
|
+
type CodewikiFile,
|
|
21
|
+
type CodewikiFileRole,
|
|
22
|
+
type CodewikiInternalEdge,
|
|
23
|
+
type CodewikiLanguage,
|
|
24
|
+
type CodewikiReadFile,
|
|
25
|
+
type CodewikiSymbol,
|
|
26
|
+
type CodewikiSymbolKind,
|
|
27
|
+
type ExtractedSymbol,
|
|
28
|
+
type LanguageExtraction,
|
|
29
|
+
type LanguageExtractor,
|
|
30
|
+
} from "./schema.js";
|
|
31
|
+
import type { TreeSitterExtractor } from "./tree-sitter.js";
|
|
32
|
+
|
|
33
|
+
export {
|
|
34
|
+
type BuildCodewikiInput,
|
|
35
|
+
CODEWIKI_VERSION,
|
|
36
|
+
type Codewiki,
|
|
37
|
+
type CodewikiEdge,
|
|
38
|
+
type CodewikiEntry,
|
|
39
|
+
type CodewikiExternalEdge,
|
|
40
|
+
type CodewikiFile,
|
|
41
|
+
type CodewikiFileRole,
|
|
42
|
+
type CodewikiInternalEdge,
|
|
43
|
+
type CodewikiLanguage,
|
|
44
|
+
type CodewikiReadFile,
|
|
45
|
+
type CodewikiSymbol,
|
|
46
|
+
type CodewikiSymbolKind,
|
|
47
|
+
type ExtractedSymbol,
|
|
48
|
+
type LanguageExtraction,
|
|
49
|
+
type LanguageExtractor,
|
|
50
|
+
} from "./schema.js";
|
|
51
|
+
|
|
52
|
+
const CODEWIKI_SYMBOL_KINDS_WITH_SIG = new Set<CodewikiSymbolKind>(["func", "class", "method", "type"]);
|
|
53
|
+
|
|
54
|
+
export interface CodewikiBuildOptions {
|
|
55
|
+
readFile?: CodewikiReadFile;
|
|
56
|
+
/**
|
|
57
|
+
* Slice budget shared across a whole index run. Callers that chain several
|
|
58
|
+
* phases pass one slicer so the budget applies end to end rather than
|
|
59
|
+
* resetting at each phase boundary. Defaults to a fresh slicer.
|
|
60
|
+
*/
|
|
61
|
+
slicer?: CooperativeSlicer;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let treeSitterExtractorPromise: Promise<TreeSitterExtractor> | null = null;
|
|
65
|
+
|
|
66
|
+
function loadTreeSitterExtractor(): Promise<TreeSitterExtractor> {
|
|
67
|
+
treeSitterExtractorPromise ??= import("./tree-sitter.js").then(({ createTreeSitterExtractor }) =>
|
|
68
|
+
createTreeSitterExtractor(),
|
|
69
|
+
);
|
|
70
|
+
return treeSitterExtractorPromise;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const RESOLUTION_EXTENSIONS = [
|
|
74
|
+
".ts",
|
|
75
|
+
".tsx",
|
|
76
|
+
".mts",
|
|
77
|
+
".cts",
|
|
78
|
+
".js",
|
|
79
|
+
".jsx",
|
|
80
|
+
".mjs",
|
|
81
|
+
".cjs",
|
|
82
|
+
".py",
|
|
83
|
+
".go",
|
|
84
|
+
".rs",
|
|
85
|
+
".c",
|
|
86
|
+
".h",
|
|
87
|
+
".cc",
|
|
88
|
+
".cpp",
|
|
89
|
+
".cxx",
|
|
90
|
+
".hpp",
|
|
91
|
+
".hh",
|
|
92
|
+
".hxx",
|
|
93
|
+
".cu",
|
|
94
|
+
".cuh",
|
|
95
|
+
".java",
|
|
96
|
+
".rb",
|
|
97
|
+
".cs",
|
|
98
|
+
];
|
|
99
|
+
|
|
100
|
+
function compareStrings(a: string, b: string): number {
|
|
101
|
+
return a.localeCompare(b);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function stableFileId(path: string): string {
|
|
105
|
+
return `f_${createHash("sha256").update(path).digest("hex").slice(0, 16)}`;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function contentHash(text: string): string {
|
|
109
|
+
return createHash("sha256").update(text).digest("hex").slice(0, 16);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function defaultReadFile(path: string): string | null {
|
|
113
|
+
try {
|
|
114
|
+
return readFileSync(path, "utf8");
|
|
115
|
+
} catch {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function normalizeRel(cwd: string, filePath: string): string {
|
|
121
|
+
return relative(cwd, filePath).split("\\").join("/");
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function normalizeInputPath(path: string): string {
|
|
125
|
+
return path.split("\\").join("/").replace(/^\.\//, "");
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export { isIndexablePath } from "./paths.js";
|
|
129
|
+
|
|
130
|
+
function lineCount(text: string): number {
|
|
131
|
+
if (text.length === 0) return 0;
|
|
132
|
+
return text.endsWith("\n") ? text.split("\n").length - 1 : text.split("\n").length;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function roleFor(relPath: string, language: CodewikiLanguage): CodewikiFileRole {
|
|
136
|
+
if (language === "config") return "config";
|
|
137
|
+
const lower = relPath.toLowerCase();
|
|
138
|
+
if (
|
|
139
|
+
lower.includes("/test/") ||
|
|
140
|
+
lower.includes("/tests/") ||
|
|
141
|
+
/\.(test|spec)\.[cm]?[jt]sx?$/.test(lower) ||
|
|
142
|
+
/(^|\/)test_.*\.py$/.test(lower) ||
|
|
143
|
+
/(^|\/).*_test\.(go|rs|rb)$/.test(lower)
|
|
144
|
+
) {
|
|
145
|
+
return "test";
|
|
146
|
+
}
|
|
147
|
+
if (/(^|\/)(index|main|server|cli|orchestrator|bootstrap)\.[^.]+$/.test(lower) || lower.endsWith("/__main__.py")) {
|
|
148
|
+
return "entry";
|
|
149
|
+
}
|
|
150
|
+
return "module";
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function firstDocSummary(text: string): string | null {
|
|
154
|
+
const jsDoc = /\/\*\*([\s\S]*?)\*\//.exec(text)?.[1];
|
|
155
|
+
const pythonDoc = /^\s*(?:"""([\s\S]*?)"""|'''([\s\S]*?)''')/.exec(text);
|
|
156
|
+
const raw = jsDoc ?? pythonDoc?.[1] ?? pythonDoc?.[2];
|
|
157
|
+
if (!raw) return null;
|
|
158
|
+
const cleaned = raw
|
|
159
|
+
.split("\n")
|
|
160
|
+
.map((line) => line.replace(/^\s*\*\s?/, "").trim())
|
|
161
|
+
.filter((line) => line.length > 0 && !line.startsWith("@"))
|
|
162
|
+
.join(" ")
|
|
163
|
+
.replace(/\s+/g, " ")
|
|
164
|
+
.trim();
|
|
165
|
+
return cleaned.length > 0 ? cleaned.slice(0, 160) : null;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function sanitizeSymbolName(value: string): string {
|
|
169
|
+
return value
|
|
170
|
+
.trim()
|
|
171
|
+
.replace(/^self\./, "")
|
|
172
|
+
.replace(/^this\./, "")
|
|
173
|
+
.slice(0, 160);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function addSymbol(
|
|
177
|
+
target: ExtractedSymbol[],
|
|
178
|
+
seen: Set<string>,
|
|
179
|
+
name: string | undefined,
|
|
180
|
+
kind: CodewikiSymbolKind,
|
|
181
|
+
line: number,
|
|
182
|
+
sig?: string,
|
|
183
|
+
): void {
|
|
184
|
+
if (!name) return;
|
|
185
|
+
const clean = sanitizeSymbolName(name);
|
|
186
|
+
if (clean.length === 0) return;
|
|
187
|
+
const key = `${clean}\0${kind}\0${line}`;
|
|
188
|
+
if (seen.has(key)) return;
|
|
189
|
+
seen.add(key);
|
|
190
|
+
target.push({
|
|
191
|
+
name: clean,
|
|
192
|
+
kind,
|
|
193
|
+
line,
|
|
194
|
+
...(sig && sig.trim().length > 0 ? { sig: sig.trim().slice(0, 240) } : {}),
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function uniqueSorted(values: Iterable<string>): string[] {
|
|
199
|
+
return [...new Set([...values].filter((item) => item.length > 0))].sort(compareStrings);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function extractWithLineRegex(
|
|
203
|
+
text: string,
|
|
204
|
+
patterns: ReadonlyArray<{ regex: RegExp; kind: CodewikiSymbolKind; nameIndex?: number }>,
|
|
205
|
+
): ExtractedSymbol[] {
|
|
206
|
+
const symbols: ExtractedSymbol[] = [];
|
|
207
|
+
const seen = new Set<string>();
|
|
208
|
+
const lines = text.split(/\r?\n/);
|
|
209
|
+
for (const [index, line] of lines.entries()) {
|
|
210
|
+
for (const pattern of patterns) {
|
|
211
|
+
const match = pattern.regex.exec(line);
|
|
212
|
+
if (!match) continue;
|
|
213
|
+
const name = match[pattern.nameIndex ?? 1];
|
|
214
|
+
addSymbol(symbols, seen, name, pattern.kind, index + 1, line.trim());
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return symbols.sort(compareSymbols);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function compareSymbols(
|
|
221
|
+
a: Pick<CodewikiSymbol, "name" | "kind" | "line">,
|
|
222
|
+
b: Pick<CodewikiSymbol, "name" | "kind" | "line">,
|
|
223
|
+
): number {
|
|
224
|
+
return a.line - b.line || a.name.localeCompare(b.name) || a.kind.localeCompare(b.kind);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function extractMatches(text: string, regex: RegExp, group = 1): string[] {
|
|
228
|
+
const out: string[] = [];
|
|
229
|
+
for (const match of text.matchAll(regex)) {
|
|
230
|
+
const value = match[group];
|
|
231
|
+
if (value) out.push(value);
|
|
232
|
+
}
|
|
233
|
+
return out;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
interface CFamilyAliasStatement {
|
|
237
|
+
text: string;
|
|
238
|
+
masked: string;
|
|
239
|
+
line: number;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function maskCFamilyCommentsAndStrings(text: string): string {
|
|
243
|
+
// split("") preserves UTF-16 offsets so slices of the masked text line up
|
|
244
|
+
// exactly with slices of the original source, including astral characters.
|
|
245
|
+
const chars = text.split("");
|
|
246
|
+
let state: "code" | "line-comment" | "block-comment" | "single-quote" | "double-quote" = "code";
|
|
247
|
+
for (let index = 0; index < chars.length; index += 1) {
|
|
248
|
+
const current = chars[index] ?? "";
|
|
249
|
+
const next = chars[index + 1] ?? "";
|
|
250
|
+
if (state === "code") {
|
|
251
|
+
if (current === "/" && next === "/") {
|
|
252
|
+
chars[index] = " ";
|
|
253
|
+
chars[index + 1] = " ";
|
|
254
|
+
state = "line-comment";
|
|
255
|
+
index += 1;
|
|
256
|
+
} else if (current === "/" && next === "*") {
|
|
257
|
+
chars[index] = " ";
|
|
258
|
+
chars[index + 1] = " ";
|
|
259
|
+
state = "block-comment";
|
|
260
|
+
index += 1;
|
|
261
|
+
} else if (current === "'") {
|
|
262
|
+
chars[index] = " ";
|
|
263
|
+
state = "single-quote";
|
|
264
|
+
} else if (current === '"') {
|
|
265
|
+
chars[index] = " ";
|
|
266
|
+
state = "double-quote";
|
|
267
|
+
}
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
if (current === "\n") {
|
|
271
|
+
if (state === "line-comment") state = "code";
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
chars[index] = " ";
|
|
275
|
+
if (state === "block-comment" && current === "*" && next === "/") {
|
|
276
|
+
chars[index + 1] = " ";
|
|
277
|
+
state = "code";
|
|
278
|
+
index += 1;
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
if ((state === "single-quote" || state === "double-quote") && current === "\\") {
|
|
282
|
+
if (index + 1 < chars.length && chars[index + 1] !== "\n") {
|
|
283
|
+
chars[index + 1] = " ";
|
|
284
|
+
index += 1;
|
|
285
|
+
}
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
if (state === "single-quote" && current === "'") state = "code";
|
|
289
|
+
if (state === "double-quote" && current === '"') state = "code";
|
|
290
|
+
}
|
|
291
|
+
return chars.join("");
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function cFamilyAliasStatements(text: string): CFamilyAliasStatement[] {
|
|
295
|
+
const masked = maskCFamilyCommentsAndStrings(text);
|
|
296
|
+
const statements: CFamilyAliasStatement[] = [];
|
|
297
|
+
const token = /\b(?:typedef|using)\b/g;
|
|
298
|
+
for (let match = token.exec(masked); match; match = token.exec(masked)) {
|
|
299
|
+
const start = match.index;
|
|
300
|
+
const lineStart = masked.lastIndexOf("\n", start - 1) + 1;
|
|
301
|
+
if (masked.slice(lineStart, start).trimStart().startsWith("#")) continue;
|
|
302
|
+
let braces = 0;
|
|
303
|
+
let parentheses = 0;
|
|
304
|
+
let brackets = 0;
|
|
305
|
+
let end = -1;
|
|
306
|
+
for (let index = token.lastIndex; index < masked.length; index += 1) {
|
|
307
|
+
const current = masked[index];
|
|
308
|
+
if (current === "{") braces += 1;
|
|
309
|
+
else if (current === "}") braces = Math.max(0, braces - 1);
|
|
310
|
+
else if (current === "(") parentheses += 1;
|
|
311
|
+
else if (current === ")") parentheses = Math.max(0, parentheses - 1);
|
|
312
|
+
else if (current === "[") brackets += 1;
|
|
313
|
+
else if (current === "]") brackets = Math.max(0, brackets - 1);
|
|
314
|
+
else if (current === ";" && braces === 0 && parentheses === 0 && brackets === 0) {
|
|
315
|
+
end = index + 1;
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
if (end === -1) continue;
|
|
320
|
+
statements.push({
|
|
321
|
+
text: text.slice(start, end),
|
|
322
|
+
masked: masked.slice(start, end),
|
|
323
|
+
line: 1 + Array.from(masked.slice(0, start).matchAll(/\n/g)).length,
|
|
324
|
+
});
|
|
325
|
+
token.lastIndex = end;
|
|
326
|
+
}
|
|
327
|
+
return statements;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function stripCFamilyBraceBodies(statement: string): string {
|
|
331
|
+
let depth = 0;
|
|
332
|
+
let result = "";
|
|
333
|
+
for (const current of statement) {
|
|
334
|
+
if (current === "{") {
|
|
335
|
+
depth += 1;
|
|
336
|
+
result += " ";
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
if (current === "}") {
|
|
340
|
+
depth = Math.max(0, depth - 1);
|
|
341
|
+
result += " ";
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
result += depth === 0 || current === "\n" ? current : " ";
|
|
345
|
+
}
|
|
346
|
+
return result;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function splitCFamilyDeclarators(value: string): string[] {
|
|
350
|
+
const parts: string[] = [];
|
|
351
|
+
let start = 0;
|
|
352
|
+
let parentheses = 0;
|
|
353
|
+
let brackets = 0;
|
|
354
|
+
let angles = 0;
|
|
355
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
356
|
+
const current = value[index];
|
|
357
|
+
if (current === "(") parentheses += 1;
|
|
358
|
+
else if (current === ")") parentheses = Math.max(0, parentheses - 1);
|
|
359
|
+
else if (current === "[") brackets += 1;
|
|
360
|
+
else if (current === "]") brackets = Math.max(0, brackets - 1);
|
|
361
|
+
else if (current === "<") angles += 1;
|
|
362
|
+
else if (current === ">") angles = Math.max(0, angles - 1);
|
|
363
|
+
else if (current === "," && parentheses === 0 && brackets === 0 && angles === 0) {
|
|
364
|
+
parts.push(value.slice(start, index));
|
|
365
|
+
start = index + 1;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
parts.push(value.slice(start));
|
|
369
|
+
return parts;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
const C_FAMILY_TYPE_WORDS = new Set([
|
|
373
|
+
"typedef",
|
|
374
|
+
"const",
|
|
375
|
+
"volatile",
|
|
376
|
+
"restrict",
|
|
377
|
+
"signed",
|
|
378
|
+
"unsigned",
|
|
379
|
+
"short",
|
|
380
|
+
"long",
|
|
381
|
+
"void",
|
|
382
|
+
"char",
|
|
383
|
+
"int",
|
|
384
|
+
"float",
|
|
385
|
+
"double",
|
|
386
|
+
"struct",
|
|
387
|
+
"union",
|
|
388
|
+
"enum",
|
|
389
|
+
"class",
|
|
390
|
+
"typename",
|
|
391
|
+
"auto",
|
|
392
|
+
]);
|
|
393
|
+
|
|
394
|
+
function stripTrailingCFamilyDeclaratorSuffixes(value: string): string {
|
|
395
|
+
let end = value.length;
|
|
396
|
+
while (end > 0) {
|
|
397
|
+
while (end > 0 && /\s/.test(value[end - 1] ?? "")) end -= 1;
|
|
398
|
+
const close = value[end - 1];
|
|
399
|
+
if (close !== ")" && close !== "]") break;
|
|
400
|
+
const open = close === ")" ? "(" : "[";
|
|
401
|
+
let depth = 1;
|
|
402
|
+
let start = end - 1;
|
|
403
|
+
for (start -= 1; start >= 0; start -= 1) {
|
|
404
|
+
const current = value[start];
|
|
405
|
+
if (current === close) depth += 1;
|
|
406
|
+
else if (current === open) {
|
|
407
|
+
depth -= 1;
|
|
408
|
+
if (depth === 0) break;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
if (start < 0) break;
|
|
412
|
+
// A suffix follows an identifier, another completed declarator group, or
|
|
413
|
+
// an array. A standalone `(Alias)` is a wrapper around the name itself and
|
|
414
|
+
// must remain available to the identifier search below. Requiring direct
|
|
415
|
+
// adjacency is what distinguishes `callable_t(...)` from `int (Wrapped)`.
|
|
416
|
+
if (start === 0 || !/[A-Za-z_0-9)\]]/.test(value[start - 1] ?? "")) break;
|
|
417
|
+
end = start;
|
|
418
|
+
}
|
|
419
|
+
return value.slice(0, end);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
function cFamilyTypedefNames(maskedStatement: string): string[] {
|
|
423
|
+
const withoutBodies = stripCFamilyBraceBodies(maskedStatement)
|
|
424
|
+
.replace(/^\s*typedef\b/, "")
|
|
425
|
+
.replace(/;\s*$/, "");
|
|
426
|
+
const names: string[] = [];
|
|
427
|
+
for (const declarator of splitCFamilyDeclarators(withoutBodies)) {
|
|
428
|
+
const functionPointerNames = Array.from(
|
|
429
|
+
declarator.matchAll(
|
|
430
|
+
/\(\s*(?:[A-Za-z_]\w*\s+)*[*&]+\s*(?:(?:const|volatile|restrict)\s+)*([A-Za-z_]\w*)\s*(?:\[[^\]]*\]\s*)*\)(?=\s*\()/g,
|
|
431
|
+
),
|
|
432
|
+
(match) => match[1] ?? "",
|
|
433
|
+
).filter((name) => name.length > 0);
|
|
434
|
+
if (functionPointerNames.length > 0) {
|
|
435
|
+
names.push(...functionPointerNames);
|
|
436
|
+
continue;
|
|
437
|
+
}
|
|
438
|
+
const declaratorWithoutSuffixes = stripTrailingCFamilyDeclaratorSuffixes(declarator);
|
|
439
|
+
const identifiers = Array.from(declaratorWithoutSuffixes.matchAll(/\b[A-Za-z_]\w*\b/g), (match) => match[0]).filter(
|
|
440
|
+
(name) => !C_FAMILY_TYPE_WORDS.has(name),
|
|
441
|
+
);
|
|
442
|
+
const name = identifiers.at(-1);
|
|
443
|
+
if (name) names.push(name);
|
|
444
|
+
}
|
|
445
|
+
return uniqueSorted(names);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function extractCFamilyAliasSymbols(text: string): ExtractedSymbol[] {
|
|
449
|
+
const symbols: ExtractedSymbol[] = [];
|
|
450
|
+
const seen = new Set<string>();
|
|
451
|
+
for (const statement of cFamilyAliasStatements(text)) {
|
|
452
|
+
const usingName = /^\s*using\s+([A-Za-z_]\w*)\s*=/.exec(statement.masked)?.[1];
|
|
453
|
+
const names = usingName
|
|
454
|
+
? [usingName]
|
|
455
|
+
: /^\s*typedef\b/.test(statement.masked)
|
|
456
|
+
? cFamilyTypedefNames(statement.masked)
|
|
457
|
+
: [];
|
|
458
|
+
const signature = statement.text.replace(/\s+/g, " ").trim();
|
|
459
|
+
for (const name of names) addSymbol(symbols, seen, name, "type", statement.line, signature);
|
|
460
|
+
}
|
|
461
|
+
return symbols;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
const tsJsExtractor: LanguageExtractor = {
|
|
465
|
+
langs: ["typescript", "javascript"],
|
|
466
|
+
extractImports(_path, text) {
|
|
467
|
+
return uniqueSorted([
|
|
468
|
+
...extractMatches(text, /\bimport\s+(?:type\s+)?(?:[^'"]*?\s+from\s+)?["']([^"']+)["']/g),
|
|
469
|
+
...extractMatches(text, /\bexport\s+[^'"]*?\s+from\s+["']([^"']+)["']/g),
|
|
470
|
+
...extractMatches(text, /\brequire\s*\(\s*["']([^"']+)["']\s*\)/g),
|
|
471
|
+
...extractMatches(text, /\bimport\s*\(\s*["']([^"']+)["']\s*\)/g),
|
|
472
|
+
]);
|
|
473
|
+
},
|
|
474
|
+
extract(_path, text) {
|
|
475
|
+
const symbols = extractWithLineRegex(text, [
|
|
476
|
+
{ regex: /^\s*export\s+default\s+(?:async\s+)?function\s+([A-Za-z_$][\w$]*)?/, kind: "func" },
|
|
477
|
+
{ regex: /^\s*(?:export\s+)?(?:async\s+)?function\s+([A-Za-z_$][\w$]*)\s*\(/, kind: "func" },
|
|
478
|
+
{ regex: /^\s*(?:export\s+)?class\s+([A-Za-z_$][\w$]*)\b/, kind: "class" },
|
|
479
|
+
{ regex: /^\s*(?:export\s+)?interface\s+([A-Za-z_$][\w$]*)\b/, kind: "iface" },
|
|
480
|
+
{ regex: /^\s*(?:export\s+)?type\s+([A-Za-z_$][\w$]*)\b/, kind: "type" },
|
|
481
|
+
{ regex: /^\s*(?:export\s+)?enum\s+([A-Za-z_$][\w$]*)\b/, kind: "type" },
|
|
482
|
+
{ regex: /^(?:\s*export\s+)?const\s+([A-Za-z_$][\w$]*)\b/, kind: "const" },
|
|
483
|
+
{ regex: /^(?:\s*export\s+)?(?:let|var)\s+([A-Za-z_$][\w$]*)\b/, kind: "var" },
|
|
484
|
+
{
|
|
485
|
+
regex:
|
|
486
|
+
/^(?: {2,}|\t+)(?:public\s+|private\s+|protected\s+|static\s+|override\s+|abstract\s+|async\s+|get\s+|set\s+)*(?!(?:if|for|while|switch|catch|return|typeof|else|do|new|await|yield)\b)([A-Za-z_$][\w$]*)\s*\([^)]*\)\s*\{?$/,
|
|
487
|
+
kind: "method",
|
|
488
|
+
},
|
|
489
|
+
]);
|
|
490
|
+
return { symbols, imports: tsJsExtractor.extractImports?.(_path, text) ?? [] };
|
|
491
|
+
},
|
|
492
|
+
};
|
|
493
|
+
|
|
494
|
+
const pythonExtractor: LanguageExtractor = {
|
|
495
|
+
langs: ["python"],
|
|
496
|
+
extractImports(_path, text) {
|
|
497
|
+
return uniqueSorted([
|
|
498
|
+
...extractMatches(text, /^\s*import\s+([A-Za-z_][\w.]*)(?:\s+as\s+\w+)?/gm),
|
|
499
|
+
...extractMatches(text, /^\s*from\s+([.\w]+)\s+import\s+/gm),
|
|
500
|
+
]);
|
|
501
|
+
},
|
|
502
|
+
extract(_path, text) {
|
|
503
|
+
const rawSymbols = extractWithLineRegex(text, [
|
|
504
|
+
{ regex: /^(\s*)def\s+([A-Za-z_]\w*)\s*\(/, kind: "func", nameIndex: 2 },
|
|
505
|
+
{ regex: /^(\s*)async\s+def\s+([A-Za-z_]\w*)\s*\(/, kind: "func", nameIndex: 2 },
|
|
506
|
+
{ regex: /^\s*class\s+([A-Za-z_]\w*)\b/, kind: "class" },
|
|
507
|
+
{ regex: /^([A-Z][A-Z0-9_]*)\s*=/, kind: "const" },
|
|
508
|
+
{ regex: /^([A-Za-z_]\w*)\s*=/, kind: "var" },
|
|
509
|
+
]);
|
|
510
|
+
const symbols: ExtractedSymbol[] = rawSymbols.map((symbol) => {
|
|
511
|
+
if ((symbol.kind === "func" || symbol.kind === "var") && /^\s+/.test(symbol.sig ?? "")) {
|
|
512
|
+
return { ...symbol, kind: symbol.kind === "func" ? "method" : symbol.kind };
|
|
513
|
+
}
|
|
514
|
+
return symbol;
|
|
515
|
+
});
|
|
516
|
+
return { symbols: symbols.sort(compareSymbols), imports: pythonExtractor.extractImports?.(_path, text) ?? [] };
|
|
517
|
+
},
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
const goExtractor: LanguageExtractor = {
|
|
521
|
+
langs: ["go"],
|
|
522
|
+
extractImports(_path, text) {
|
|
523
|
+
return uniqueSorted([
|
|
524
|
+
...extractMatches(text, /^\s*import\s+"([^"]+)"/gm),
|
|
525
|
+
...extractMatches(text, /^\s*"([^"]+)"\s*$/gm),
|
|
526
|
+
]);
|
|
527
|
+
},
|
|
528
|
+
extract(_path, text) {
|
|
529
|
+
const rawSymbols = extractWithLineRegex(text, [
|
|
530
|
+
{ regex: /^\s*func\s+(?:\([^)]*\)\s*)?([A-Za-z_]\w*)\s*\(/, kind: "func" },
|
|
531
|
+
{ regex: /^\s*type\s+([A-Za-z_]\w*)\s+interface\b/, kind: "iface" },
|
|
532
|
+
{ regex: /^\s*type\s+([A-Za-z_]\w*)\s+struct\b/, kind: "type" },
|
|
533
|
+
{ regex: /^\s*type\s+([A-Za-z_]\w*)\b/, kind: "type" },
|
|
534
|
+
{ regex: /^const\s+([A-Za-z_]\w*)\b/, kind: "const" },
|
|
535
|
+
{ regex: /^var\s+([A-Za-z_]\w*)\b/, kind: "var" },
|
|
536
|
+
]);
|
|
537
|
+
const symbols: ExtractedSymbol[] = rawSymbols.map((symbol) => {
|
|
538
|
+
if (symbol.kind === "func" && /^\s*func\s+\(/.test(symbol.sig ?? "")) return { ...symbol, kind: "method" };
|
|
539
|
+
return symbol;
|
|
540
|
+
});
|
|
541
|
+
return { symbols: symbols.sort(compareSymbols), imports: goExtractor.extractImports?.(_path, text) ?? [] };
|
|
542
|
+
},
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
const rustExtractor: LanguageExtractor = {
|
|
546
|
+
langs: ["rust"],
|
|
547
|
+
extractImports(_path, text) {
|
|
548
|
+
return uniqueSorted([
|
|
549
|
+
...extractMatches(text, /^\s*use\s+([^;]+);/gm).map((item) => item.trim()),
|
|
550
|
+
...extractMatches(text, /^\s*extern\s+crate\s+([A-Za-z_]\w*)/gm),
|
|
551
|
+
]);
|
|
552
|
+
},
|
|
553
|
+
extract(_path, text) {
|
|
554
|
+
const symbols = extractWithLineRegex(text, [
|
|
555
|
+
{ regex: /^\s*(?:pub(?:\([^)]*\))?\s+)?fn\s+([A-Za-z_]\w*)\s*[<(]/, kind: "func" },
|
|
556
|
+
{ regex: /^\s*(?:pub(?:\([^)]*\))?\s+)?struct\s+([A-Za-z_]\w*)\b/, kind: "type" },
|
|
557
|
+
{ regex: /^\s*(?:pub(?:\([^)]*\))?\s+)?enum\s+([A-Za-z_]\w*)\b/, kind: "type" },
|
|
558
|
+
{ regex: /^\s*(?:pub(?:\([^)]*\))?\s+)?trait\s+([A-Za-z_]\w*)\b/, kind: "trait" },
|
|
559
|
+
{ regex: /^\s*(?:pub(?:\([^)]*\))?\s+)?type\s+([A-Za-z_]\w*)\b/, kind: "type" },
|
|
560
|
+
{ regex: /^(?:\s*pub(?:\([^)]*\))?\s+)?const\s+([A-Za-z_]\w*)\b/, kind: "const" },
|
|
561
|
+
{ regex: /^(?:\s*pub(?:\([^)]*\))?\s+)?static\s+([A-Za-z_]\w*)\b/, kind: "var" },
|
|
562
|
+
]);
|
|
563
|
+
return { symbols, imports: rustExtractor.extractImports?.(_path, text) ?? [] };
|
|
564
|
+
},
|
|
565
|
+
};
|
|
566
|
+
|
|
567
|
+
const cFamilyExtractor: LanguageExtractor = {
|
|
568
|
+
langs: ["c", "c++"],
|
|
569
|
+
extractImports(_path, text) {
|
|
570
|
+
const imports: string[] = [];
|
|
571
|
+
for (const match of text.matchAll(/^\s*#\s*include\s*(?:"([^"]+)"|<([^>]+)>)/gm)) {
|
|
572
|
+
const quoted = match[1];
|
|
573
|
+
const system = match[2];
|
|
574
|
+
if (quoted) imports.push(quoted.startsWith(".") || quoted.startsWith("/") ? quoted : `./${quoted}`);
|
|
575
|
+
else if (system) imports.push(system);
|
|
576
|
+
}
|
|
577
|
+
return uniqueSorted(imports);
|
|
578
|
+
},
|
|
579
|
+
extract(_path, text) {
|
|
580
|
+
const regexSymbols = extractWithLineRegex(text, [
|
|
581
|
+
{ regex: /^\s*class\s+([A-Za-z_]\w*)\b/, kind: "class" },
|
|
582
|
+
{
|
|
583
|
+
regex: /^\s*(?:typedef\s+)?(?:struct\s+|union\s+|enum\s+(?:(?:class|struct)\s+)?)([A-Za-z_]\w*)\b/,
|
|
584
|
+
kind: "type",
|
|
585
|
+
},
|
|
586
|
+
{
|
|
587
|
+
regex:
|
|
588
|
+
/^\s*(?!(?:typedef|using)\b)(?:template\s*<[^>]+>\s*)?(?:[A-Za-z_][\w:<>,*&\s]+\s+)+(?:(?:[A-Za-z_]\w*)::)*([~A-Za-z_]\w*)\s*\([^;]*\)\s*(?:const\s*)?(?:noexcept\s*)?(?:;|\{)?$/,
|
|
589
|
+
kind: "func",
|
|
590
|
+
},
|
|
591
|
+
{ regex: /^(?:const\s+)?[A-Za-z_][\w:<>,*&\s]+\s+([A-Z][A-Z0-9_]*)\s*=/, kind: "const" },
|
|
592
|
+
]);
|
|
593
|
+
const symbolsByKey = new Map<string, ExtractedSymbol>();
|
|
594
|
+
for (const symbol of [...regexSymbols, ...extractCFamilyAliasSymbols(text)]) {
|
|
595
|
+
const key = `${symbol.name}\0${symbol.kind}\0${symbol.line}`;
|
|
596
|
+
if (!symbolsByKey.has(key)) symbolsByKey.set(key, symbol);
|
|
597
|
+
}
|
|
598
|
+
const symbols = [...symbolsByKey.values()].sort(compareSymbols);
|
|
599
|
+
return { symbols, imports: cFamilyExtractor.extractImports?.(_path, text) ?? [] };
|
|
600
|
+
},
|
|
601
|
+
};
|
|
602
|
+
|
|
603
|
+
const javaExtractor: LanguageExtractor = {
|
|
604
|
+
langs: ["java"],
|
|
605
|
+
extractImports(_path, text) {
|
|
606
|
+
return uniqueSorted(extractMatches(text, /^\s*import\s+(?:static\s+)?([A-Za-z_][\w.*]*);/gm));
|
|
607
|
+
},
|
|
608
|
+
extract(_path, text) {
|
|
609
|
+
const symbols = extractWithLineRegex(text, [
|
|
610
|
+
{ regex: /^\s*(?:public\s+|private\s+|protected\s+|abstract\s+|final\s+)*class\s+([A-Za-z_]\w*)\b/, kind: "class" },
|
|
611
|
+
{
|
|
612
|
+
regex: /^\s*(?:public\s+|private\s+|protected\s+|abstract\s+|final\s+)*interface\s+([A-Za-z_]\w*)\b/,
|
|
613
|
+
kind: "iface",
|
|
614
|
+
},
|
|
615
|
+
{ regex: /^\s*(?:public\s+|private\s+|protected\s+|abstract\s+|final\s+)*enum\s+([A-Za-z_]\w*)\b/, kind: "type" },
|
|
616
|
+
{
|
|
617
|
+
regex:
|
|
618
|
+
/^\s*(?:public\s+|private\s+|protected\s+|static\s+|final\s+|synchronized\s+)*[A-Za-z_][\w<>,[\]\s]*\s+([A-Za-z_]\w*)\s*\([^)]*\)\s*\{?$/,
|
|
619
|
+
kind: "method",
|
|
620
|
+
},
|
|
621
|
+
{
|
|
622
|
+
regex: /^\s*public\s+(?:static\s+|final\s+)*[A-Za-z_][\w<>,[\]\s]*\s+([A-Z][A-Z0-9_]*)\s*=/,
|
|
623
|
+
kind: "const",
|
|
624
|
+
},
|
|
625
|
+
]);
|
|
626
|
+
return { symbols, imports: javaExtractor.extractImports?.(_path, text) ?? [] };
|
|
627
|
+
},
|
|
628
|
+
};
|
|
629
|
+
|
|
630
|
+
const rubyExtractor: LanguageExtractor = {
|
|
631
|
+
langs: ["ruby"],
|
|
632
|
+
extractImports(_path, text) {
|
|
633
|
+
return uniqueSorted([
|
|
634
|
+
...extractMatches(text, /^\s*require\s+["']([^"']+)["']/gm),
|
|
635
|
+
...extractMatches(text, /^\s*require_relative\s+["']([^"']+)["']/gm).map((item) => `./${item}`),
|
|
636
|
+
]);
|
|
637
|
+
},
|
|
638
|
+
extract(_path, text) {
|
|
639
|
+
const symbols = extractWithLineRegex(text, [
|
|
640
|
+
{ regex: /^\s*class\s+([A-Z]\w*(?:::[A-Z]\w*)*)\b/, kind: "class" },
|
|
641
|
+
{ regex: /^\s*module\s+([A-Z]\w*(?:::[A-Z]\w*)*)\b/, kind: "type" },
|
|
642
|
+
{ regex: /^\s*def\s+(?:self\.)?([A-Za-z_]\w*[!?=]?)\b/, kind: "func" },
|
|
643
|
+
{ regex: /^([A-Z][A-Z0-9_]*)\s*=/, kind: "const" },
|
|
644
|
+
]);
|
|
645
|
+
return { symbols, imports: rubyExtractor.extractImports?.(_path, text) ?? [] };
|
|
646
|
+
},
|
|
647
|
+
};
|
|
648
|
+
|
|
649
|
+
const csharpExtractor: LanguageExtractor = {
|
|
650
|
+
langs: ["c#"],
|
|
651
|
+
extractImports(_path, text) {
|
|
652
|
+
// Mirrors the tree-sitter using-directive handling: static prefixes are
|
|
653
|
+
// stripped and alias directives resolve to their right-hand side.
|
|
654
|
+
return uniqueSorted(
|
|
655
|
+
extractMatches(text, /^\s*using\s+(?:static\s+)?(?:[A-Za-z_]\w*\s*=\s*)?([A-Za-z_][\w.]*)\s*;/gm),
|
|
656
|
+
);
|
|
657
|
+
},
|
|
658
|
+
extract(_path, text) {
|
|
659
|
+
const symbols = extractWithLineRegex(text, [
|
|
660
|
+
{
|
|
661
|
+
regex:
|
|
662
|
+
/^\s*(?:public\s+|private\s+|protected\s+|internal\s+|static\s+|sealed\s+|abstract\s+|partial\s+)*class\s+([A-Za-z_]\w*)\b/,
|
|
663
|
+
kind: "class",
|
|
664
|
+
},
|
|
665
|
+
{
|
|
666
|
+
regex: /^\s*(?:public\s+|private\s+|protected\s+|internal\s+|partial\s+)*interface\s+([A-Za-z_]\w*)\b/,
|
|
667
|
+
kind: "iface",
|
|
668
|
+
},
|
|
669
|
+
{
|
|
670
|
+
regex:
|
|
671
|
+
/^\s*(?:public\s+|private\s+|protected\s+|internal\s+|readonly\s+|partial\s+)*(?:enum|struct|record)\s+([A-Za-z_]\w*)\b/,
|
|
672
|
+
kind: "type",
|
|
673
|
+
},
|
|
674
|
+
{
|
|
675
|
+
regex:
|
|
676
|
+
/^\s*(?:public\s+|private\s+|protected\s+|internal\s+|static\s+|virtual\s+|override\s+|abstract\s+|sealed\s+|async\s+|partial\s+|new\s+)*(?!(?:if|for|foreach|while|switch|catch|return|using|else|do|new|class|interface|enum|struct|record|namespace|lock|throw)\b)[A-Za-z_][\w<>,[\].?\s]*\s+([A-Za-z_]\w*)\s*\([^)]*\)\s*\{?$/,
|
|
677
|
+
kind: "method",
|
|
678
|
+
},
|
|
679
|
+
{
|
|
680
|
+
regex:
|
|
681
|
+
/^\s*(?:public\s+|private\s+|protected\s+|internal\s+|static\s+)*const\s+[A-Za-z_][\w<>,[\]\s]*\s+([A-Za-z_]\w*)\s*=/,
|
|
682
|
+
kind: "const",
|
|
683
|
+
},
|
|
684
|
+
]);
|
|
685
|
+
return { symbols, imports: csharpExtractor.extractImports?.(_path, text) ?? [] };
|
|
686
|
+
},
|
|
687
|
+
};
|
|
688
|
+
|
|
689
|
+
const fallbackExtractors: ReadonlyArray<LanguageExtractor> = [
|
|
690
|
+
tsJsExtractor,
|
|
691
|
+
pythonExtractor,
|
|
692
|
+
goExtractor,
|
|
693
|
+
rustExtractor,
|
|
694
|
+
cFamilyExtractor,
|
|
695
|
+
javaExtractor,
|
|
696
|
+
rubyExtractor,
|
|
697
|
+
csharpExtractor,
|
|
698
|
+
];
|
|
699
|
+
|
|
700
|
+
function extractWithExtractors(
|
|
701
|
+
extractors: ReadonlyArray<LanguageExtractor>,
|
|
702
|
+
language: CodewikiLanguage,
|
|
703
|
+
relPath: string,
|
|
704
|
+
text: string,
|
|
705
|
+
): LanguageExtraction {
|
|
706
|
+
const symbols = new Map<string, ExtractedSymbol>();
|
|
707
|
+
const imports: string[] = [];
|
|
708
|
+
for (const extractor of extractors) {
|
|
709
|
+
if (!extractor.langs.includes(language)) continue;
|
|
710
|
+
const extracted = extractor.extract(relPath, text);
|
|
711
|
+
for (const symbol of extracted.symbols) {
|
|
712
|
+
const key = `${symbol.name}\0${symbol.kind}\0${symbol.line}`;
|
|
713
|
+
if (!symbols.has(key)) symbols.set(key, symbol);
|
|
714
|
+
}
|
|
715
|
+
imports.push(...extracted.imports);
|
|
716
|
+
}
|
|
717
|
+
return {
|
|
718
|
+
symbols: [...symbols.values()].sort(compareSymbols),
|
|
719
|
+
imports: uniqueSorted(imports),
|
|
720
|
+
};
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
function extractImportsWithExtractors(
|
|
724
|
+
extractors: ReadonlyArray<LanguageExtractor>,
|
|
725
|
+
language: CodewikiLanguage,
|
|
726
|
+
relPath: string,
|
|
727
|
+
text: string,
|
|
728
|
+
): string[] {
|
|
729
|
+
const imports: string[] = [];
|
|
730
|
+
for (const extractor of extractors) {
|
|
731
|
+
if (!extractor.langs.includes(language) || !extractor.extractImports) continue;
|
|
732
|
+
imports.push(...extractor.extractImports(relPath, text));
|
|
733
|
+
}
|
|
734
|
+
return uniqueSorted(imports);
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
interface BuiltFile {
|
|
738
|
+
file: CodewikiFile;
|
|
739
|
+
symbols: CodewikiSymbol[];
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
function mergeTreeSitterWithRegexImports(
|
|
743
|
+
language: CodewikiLanguage,
|
|
744
|
+
relPath: string,
|
|
745
|
+
text: string,
|
|
746
|
+
extracted: LanguageExtraction,
|
|
747
|
+
): LanguageExtraction {
|
|
748
|
+
const regexImports = extractImportsWithExtractors(fallbackExtractors, language, relPath, text);
|
|
749
|
+
return {
|
|
750
|
+
symbols: extracted.symbols.sort(compareSymbols),
|
|
751
|
+
imports: uniqueSorted([...extracted.imports, ...regexImports]),
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
export function fallbackExtraction(language: CodewikiLanguage, relPath: string, text: string): LanguageExtraction {
|
|
756
|
+
return extractWithExtractors(fallbackExtractors, language, relPath, text);
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
/**
|
|
760
|
+
* Largest source text handed to tree-sitter. The cooperative slicer yields
|
|
761
|
+
* between files, never inside one, so a single parse is the longest stretch the
|
|
762
|
+
* event loop can be held for; measured on this machine that is roughly 0.5 ms
|
|
763
|
+
* per KiB of ordinary source and 2 to 3 ms per KiB of a minified bundle, which
|
|
764
|
+
* made one 9 MiB vendored bundle a 25 s freeze that no shutdown budget could
|
|
765
|
+
* interrupt (issue #99). Nothing hand-written is this big; anything above the
|
|
766
|
+
* cap is generated or vendored, and the regex extractor covers it in tens of
|
|
767
|
+
* milliseconds. Under the cap one parse of ordinary source is a few hundred
|
|
768
|
+
* milliseconds at most; a minified file right at the cap can still take about a
|
|
769
|
+
* second, which is bounded, and the loop gets its turn at the next file.
|
|
770
|
+
*/
|
|
771
|
+
export const MAX_TREE_SITTER_SOURCE_CHARS = 512 * 1024;
|
|
772
|
+
|
|
773
|
+
function extractSourceFile(
|
|
774
|
+
language: CodewikiLanguage,
|
|
775
|
+
relPath: string,
|
|
776
|
+
text: string,
|
|
777
|
+
treeSitterExtractor: LanguageExtractor,
|
|
778
|
+
): LanguageExtraction {
|
|
779
|
+
if (!treeSitterExtractor.langs.includes(language)) return fallbackExtraction(language, relPath, text);
|
|
780
|
+
if (text.length > MAX_TREE_SITTER_SOURCE_CHARS) return fallbackExtraction(language, relPath, text);
|
|
781
|
+
try {
|
|
782
|
+
return mergeTreeSitterWithRegexImports(language, relPath, text, treeSitterExtractor.extract(relPath, text));
|
|
783
|
+
} catch {
|
|
784
|
+
return fallbackExtraction(language, relPath, text);
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
function buildFile(
|
|
789
|
+
cwd: string,
|
|
790
|
+
relPath: string,
|
|
791
|
+
treeSitterExtractor: LanguageExtractor,
|
|
792
|
+
readFile: CodewikiReadFile,
|
|
793
|
+
): BuiltFile | null {
|
|
794
|
+
const pathLanguage = languageForPath(relPath);
|
|
795
|
+
if (!pathLanguage) return null;
|
|
796
|
+
let text: string | null;
|
|
797
|
+
try {
|
|
798
|
+
text = readFile(join(cwd, relPath));
|
|
799
|
+
} catch {
|
|
800
|
+
return null;
|
|
801
|
+
}
|
|
802
|
+
if (text === null) return null;
|
|
803
|
+
// Ambiguous `.h` headers classify from content so both full builds and
|
|
804
|
+
// incremental updates land on the same C/C++ decision.
|
|
805
|
+
const language = pathLanguage === "c" && isAmbiguousHeaderPath(relPath) ? classifyCHeaderLanguage(text) : pathLanguage;
|
|
806
|
+
const file: CodewikiFile = {
|
|
807
|
+
id: stableFileId(relPath),
|
|
808
|
+
path: relPath,
|
|
809
|
+
lang: language,
|
|
810
|
+
loc: lineCount(text),
|
|
811
|
+
role: roleFor(relPath, language),
|
|
812
|
+
hash: contentHash(text),
|
|
813
|
+
imports: [],
|
|
814
|
+
};
|
|
815
|
+
if (text.trim().length === 0) return { file, symbols: [] };
|
|
816
|
+
const extracted = isCMakePath(relPath)
|
|
817
|
+
? extractCMake(text)
|
|
818
|
+
: language !== "config"
|
|
819
|
+
? extractSourceFile(language, relPath, text, treeSitterExtractor)
|
|
820
|
+
: null;
|
|
821
|
+
if (!extracted) return { file, symbols: [] };
|
|
822
|
+
const summary = firstDocSummary(text);
|
|
823
|
+
const sourceFile: CodewikiFile = {
|
|
824
|
+
...file,
|
|
825
|
+
imports: extracted.imports,
|
|
826
|
+
...(summary ? { summary } : {}),
|
|
827
|
+
};
|
|
828
|
+
const symbols = extracted.symbols.map((symbol) => ({
|
|
829
|
+
name: symbol.name,
|
|
830
|
+
kind: symbol.kind,
|
|
831
|
+
fileId: sourceFile.id,
|
|
832
|
+
line: symbol.line,
|
|
833
|
+
...symbolSigFields(symbol.kind, symbol.sig),
|
|
834
|
+
}));
|
|
835
|
+
return {
|
|
836
|
+
file: sourceFile,
|
|
837
|
+
symbols,
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
function candidatePathsForImport(cwd: string, fromRel: string, specifier: string): string[] {
|
|
842
|
+
const fromDir = dirname(join(cwd, fromRel));
|
|
843
|
+
const cleaned = specifier.replace(/\\/g, "/");
|
|
844
|
+
const base = cleaned.startsWith(".") || cleaned.startsWith("/") ? resolve(fromDir, cleaned) : "";
|
|
845
|
+
if (!base) return [];
|
|
846
|
+
const candidates = [base];
|
|
847
|
+
for (const ext of RESOLUTION_EXTENSIONS) candidates.push(`${base}${ext}`);
|
|
848
|
+
for (const ext of RESOLUTION_EXTENSIONS) candidates.push(join(base, `index${ext}`));
|
|
849
|
+
if (cleaned.endsWith(".js")) {
|
|
850
|
+
const stripped = base.replace(/\.js$/, "");
|
|
851
|
+
for (const ext of [".ts", ".tsx", ".mts", ".cts"]) candidates.push(`${stripped}${ext}`);
|
|
852
|
+
}
|
|
853
|
+
if (/^[.]+[A-Za-z_]/.test(cleaned)) {
|
|
854
|
+
const pythonModule = cleaned.replace(/^\.+/, "").replace(/\./g, "/");
|
|
855
|
+
const pythonBase = resolve(fromDir, pythonModule);
|
|
856
|
+
candidates.push(`${pythonBase}.py`, join(pythonBase, "__init__.py"));
|
|
857
|
+
}
|
|
858
|
+
return uniqueSorted(
|
|
859
|
+
candidates.map((candidate) => normalizeRel(cwd, candidate)).filter((candidate) => !candidate.startsWith("..")),
|
|
860
|
+
);
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
/**
|
|
864
|
+
* Per-run memo for import resolution.
|
|
865
|
+
*
|
|
866
|
+
* A candidate list depends only on the importing file's directory and the
|
|
867
|
+
* specifier, and a candidate's on-disk status cannot change while a single edge
|
|
868
|
+
* rebuild is in flight, so both collapse to a map lookup after the first miss.
|
|
869
|
+
* Uncached, one rebuild of a 1100-file TypeScript repo issued roughly 80 000
|
|
870
|
+
* `statSync` calls, most of them for paths that do not exist, and spent about
|
|
871
|
+
* four seconds doing it.
|
|
872
|
+
*/
|
|
873
|
+
function createImportResolver(cwd: string): {
|
|
874
|
+
resolve(fromRel: string, specifier: string, pathToId: ReadonlyMap<string, string>): string | null;
|
|
875
|
+
} {
|
|
876
|
+
const candidatesByOrigin = new Map<string, string[]>();
|
|
877
|
+
const onDisk = new Map<string, boolean>();
|
|
878
|
+
const candidatesFor = (fromRel: string, specifier: string): string[] => {
|
|
879
|
+
// The candidate set is a function of the directory, not the file: every
|
|
880
|
+
// sibling importing the same specifier resolves through the same list.
|
|
881
|
+
const key = `${dirname(fromRel)}\0${specifier}`;
|
|
882
|
+
let candidates = candidatesByOrigin.get(key);
|
|
883
|
+
if (!candidates) {
|
|
884
|
+
candidates = candidatePathsForImport(cwd, fromRel, specifier);
|
|
885
|
+
candidatesByOrigin.set(key, candidates);
|
|
886
|
+
}
|
|
887
|
+
return candidates;
|
|
888
|
+
};
|
|
889
|
+
const isFile = (candidate: string): boolean => {
|
|
890
|
+
const cached = onDisk.get(candidate);
|
|
891
|
+
if (cached !== undefined) return cached;
|
|
892
|
+
let exists: boolean;
|
|
893
|
+
try {
|
|
894
|
+
exists = statSync(join(cwd, candidate)).isFile();
|
|
895
|
+
} catch {
|
|
896
|
+
exists = false;
|
|
897
|
+
}
|
|
898
|
+
onDisk.set(candidate, exists);
|
|
899
|
+
return exists;
|
|
900
|
+
};
|
|
901
|
+
return {
|
|
902
|
+
resolve(fromRel, specifier, pathToId): string | null {
|
|
903
|
+
for (const candidate of candidatesFor(fromRel, specifier)) {
|
|
904
|
+
if (pathToId.has(candidate)) return pathToId.get(candidate) ?? null;
|
|
905
|
+
// An unindexed file that exists still claims the specifier: it shadows
|
|
906
|
+
// any later candidate, and having no id makes the edge external.
|
|
907
|
+
if (isFile(candidate)) return null;
|
|
908
|
+
}
|
|
909
|
+
return null;
|
|
910
|
+
},
|
|
911
|
+
};
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
async function buildEdges(
|
|
915
|
+
cwd: string,
|
|
916
|
+
files: ReadonlyArray<CodewikiFile>,
|
|
917
|
+
slicer: CooperativeSlicer,
|
|
918
|
+
): Promise<CodewikiEdge[]> {
|
|
919
|
+
const pathToId = new Map(files.map((file) => [file.path, file.id] as const));
|
|
920
|
+
const resolver = createImportResolver(cwd);
|
|
921
|
+
const edges: CodewikiEdge[] = [];
|
|
922
|
+
const seen = new Set<string>();
|
|
923
|
+
for (const file of files) {
|
|
924
|
+
for (const specifier of file.imports) {
|
|
925
|
+
await slicer.tick();
|
|
926
|
+
const target = resolver.resolve(file.path, specifier, pathToId);
|
|
927
|
+
const edge = target
|
|
928
|
+
? ({ fileId: file.id, toFileId: target } satisfies CodewikiInternalEdge)
|
|
929
|
+
: ({ fileId: file.id, externalModule: specifier } satisfies CodewikiExternalEdge);
|
|
930
|
+
const key = "toFileId" in edge ? `${edge.fileId}\0${edge.toFileId}` : `${edge.fileId}\0${edge.externalModule}`;
|
|
931
|
+
if (seen.has(key)) continue;
|
|
932
|
+
seen.add(key);
|
|
933
|
+
edges.push(edge);
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
return edges.sort(compareEdges);
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
function compareFiles(a: CodewikiFile, b: CodewikiFile): number {
|
|
940
|
+
return a.path.localeCompare(b.path);
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
function compareCodewikiSymbols(a: CodewikiSymbol, b: CodewikiSymbol): number {
|
|
944
|
+
const pathCmp = a.fileId.localeCompare(b.fileId);
|
|
945
|
+
return pathCmp || a.line - b.line || a.name.localeCompare(b.name) || a.kind.localeCompare(b.kind);
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
function compareEdges(a: CodewikiEdge, b: CodewikiEdge): number {
|
|
949
|
+
const fileCmp = a.fileId.localeCompare(b.fileId);
|
|
950
|
+
if (fileCmp !== 0) return fileCmp;
|
|
951
|
+
const aTarget = "toFileId" in a ? a.toFileId : `~${a.externalModule}`;
|
|
952
|
+
const bTarget = "toFileId" in b ? b.toFileId : `~${b.externalModule}`;
|
|
953
|
+
return aTarget.localeCompare(bTarget);
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
function promoteSingleSourceEntry(files: CodewikiFile[]): CodewikiFile[] {
|
|
957
|
+
const sourceFiles = files.filter((file) => file.lang !== "config");
|
|
958
|
+
if (sourceFiles.length !== 1) return files;
|
|
959
|
+
const only = sourceFiles[0];
|
|
960
|
+
if (only?.role !== "module") return files;
|
|
961
|
+
return files.map((file) => (file.id === only.id ? { ...file, role: "entry" } : file));
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
async function codewikiFromBuiltFiles(
|
|
965
|
+
cwd: string,
|
|
966
|
+
language: ProjectType,
|
|
967
|
+
builtFiles: ReadonlyArray<BuiltFile>,
|
|
968
|
+
slicer: CooperativeSlicer,
|
|
969
|
+
): Promise<Codewiki> {
|
|
970
|
+
const baseBuiltFiles = builtFiles.map((item) => ({
|
|
971
|
+
...item,
|
|
972
|
+
file: { ...item.file, role: roleFor(item.file.path, item.file.lang) },
|
|
973
|
+
}));
|
|
974
|
+
const files = promoteSingleSourceEntry(baseBuiltFiles.map((item) => item.file).sort(compareFiles));
|
|
975
|
+
const roleById = new Map(files.map((file) => [file.id, file.role] as const));
|
|
976
|
+
const normalizedBuilt = baseBuiltFiles.map((item) => {
|
|
977
|
+
const role = roleById.get(item.file.id);
|
|
978
|
+
return role && role !== item.file.role ? { ...item, file: { ...item.file, role } } : item;
|
|
979
|
+
});
|
|
980
|
+
const normalizedFiles = normalizedBuilt.map((item) => item.file).sort(compareFiles);
|
|
981
|
+
return {
|
|
982
|
+
version: CODEWIKI_VERSION,
|
|
983
|
+
language,
|
|
984
|
+
files: normalizedFiles,
|
|
985
|
+
symbols: normalizedBuilt.flatMap((item) => item.symbols).sort(compareCodewikiSymbols),
|
|
986
|
+
edges: await buildEdges(cwd, normalizedFiles, slicer),
|
|
987
|
+
};
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
async function buildFromPaths(
|
|
991
|
+
cwd: string,
|
|
992
|
+
language: ProjectType,
|
|
993
|
+
relPaths: ReadonlyArray<string>,
|
|
994
|
+
options: CodewikiBuildOptions = {},
|
|
995
|
+
): Promise<Codewiki> {
|
|
996
|
+
const slicer = options.slicer ?? createSlicer();
|
|
997
|
+
const sortedPaths = [...relPaths].sort(compareStrings);
|
|
998
|
+
const treeSitterExtractor = await loadTreeSitterExtractor();
|
|
999
|
+
await treeSitterExtractor.ensureGrammarsForPaths(sortedPaths);
|
|
1000
|
+
const readFile = options.readFile ?? defaultReadFile;
|
|
1001
|
+
const builtFiles: BuiltFile[] = [];
|
|
1002
|
+
for (const relPath of sortedPaths) {
|
|
1003
|
+
// One read plus one tree-sitter parse per file; a full build of a large
|
|
1004
|
+
// repo is thousands of them and must not land as a single turn.
|
|
1005
|
+
await slicer.tick();
|
|
1006
|
+
const built = buildFile(cwd, relPath, treeSitterExtractor, readFile);
|
|
1007
|
+
if (built) builtFiles.push(built);
|
|
1008
|
+
}
|
|
1009
|
+
return codewikiFromBuiltFiles(cwd, language, builtFiles, slicer);
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
export async function buildCodewiki(input: BuildCodewikiInput, options: CodewikiBuildOptions = {}): Promise<Codewiki> {
|
|
1013
|
+
const slicer = options.slicer ?? createSlicer();
|
|
1014
|
+
const files = (await enumerateWorkspaceFilesAsync(input.cwd, EXCLUDED_DIRS, undefined, slicer)).filter(
|
|
1015
|
+
isIndexablePath,
|
|
1016
|
+
);
|
|
1017
|
+
return buildFromPaths(input.cwd, input.language, files, { ...options, slicer });
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
/**
|
|
1021
|
+
* Apply an incremental update for a set of changed paths. The changed file
|
|
1022
|
+
* records and symbols are replaced in-place, and edges are rebuilt from stored
|
|
1023
|
+
* imports across the merged file set.
|
|
1024
|
+
*/
|
|
1025
|
+
export async function updateCodewikiPaths(
|
|
1026
|
+
cwd: string,
|
|
1027
|
+
codewiki: Codewiki,
|
|
1028
|
+
paths: ReadonlyArray<string>,
|
|
1029
|
+
options: CodewikiBuildOptions = {},
|
|
1030
|
+
): Promise<Codewiki> {
|
|
1031
|
+
const normalizedPaths = uniqueSorted(
|
|
1032
|
+
paths.map(normalizeInputPath).filter((path) => path.length > 0 && !path.startsWith("..")),
|
|
1033
|
+
);
|
|
1034
|
+
if (normalizedPaths.length === 0) return codewiki;
|
|
1035
|
+
if (
|
|
1036
|
+
normalizedPaths.some(
|
|
1037
|
+
(path) =>
|
|
1038
|
+
path === ".gitignore" ||
|
|
1039
|
+
path.endsWith("/.gitignore") ||
|
|
1040
|
+
path === ".git/info/exclude" ||
|
|
1041
|
+
path === ".git/index" ||
|
|
1042
|
+
path === ".gitmodules",
|
|
1043
|
+
)
|
|
1044
|
+
) {
|
|
1045
|
+
// Ignore and index metadata can add or remove paths that are not present in
|
|
1046
|
+
// the mutation batch itself. Re-enumerate once so incremental visibility
|
|
1047
|
+
// remains byte-equivalent to a full build.
|
|
1048
|
+
return buildCodewiki({ cwd, language: codewiki.language }, options);
|
|
1049
|
+
}
|
|
1050
|
+
const slicer = options.slicer ?? createSlicer();
|
|
1051
|
+
const existingPaths = new Set(codewiki.files.map((file) => file.path));
|
|
1052
|
+
const visiblePaths = new Set(filterWorkspaceFileCandidates(cwd, normalizedPaths, EXCLUDED_DIRS));
|
|
1053
|
+
const readFile = options.readFile ?? defaultReadFile;
|
|
1054
|
+
const changedPathSet = new Set(normalizedPaths);
|
|
1055
|
+
const rebuildPaths: string[] = [];
|
|
1056
|
+
let hasIndexChange = false;
|
|
1057
|
+
for (const relPath of normalizedPaths) {
|
|
1058
|
+
const wasIndexed = existingPaths.has(relPath);
|
|
1059
|
+
const isCurrentIndexableFile = isIndexablePath(relPath) && visiblePaths.has(relPath);
|
|
1060
|
+
if (!wasIndexed && !isCurrentIndexableFile) continue;
|
|
1061
|
+
hasIndexChange = true;
|
|
1062
|
+
if (isCurrentIndexableFile) rebuildPaths.push(relPath);
|
|
1063
|
+
}
|
|
1064
|
+
if (!hasIndexChange) return codewiki;
|
|
1065
|
+
const rebuiltFiles: BuiltFile[] = [];
|
|
1066
|
+
if (rebuildPaths.length > 0) {
|
|
1067
|
+
const treeSitterExtractor = await loadTreeSitterExtractor();
|
|
1068
|
+
await treeSitterExtractor.ensureGrammarsForPaths(rebuildPaths);
|
|
1069
|
+
for (const relPath of rebuildPaths) {
|
|
1070
|
+
await slicer.tick();
|
|
1071
|
+
const built = buildFile(cwd, relPath, treeSitterExtractor, readFile);
|
|
1072
|
+
if (built) rebuiltFiles.push(built);
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
const removedFileIds = new Set(codewiki.files.filter((file) => changedPathSet.has(file.path)).map((file) => file.id));
|
|
1076
|
+
const symbolsByFileId = new Map<string, CodewikiSymbol[]>();
|
|
1077
|
+
for (const symbol of codewiki.symbols) {
|
|
1078
|
+
if (removedFileIds.has(symbol.fileId)) continue;
|
|
1079
|
+
const symbols = symbolsByFileId.get(symbol.fileId) ?? [];
|
|
1080
|
+
symbols.push(symbol);
|
|
1081
|
+
symbolsByFileId.set(symbol.fileId, symbols);
|
|
1082
|
+
}
|
|
1083
|
+
const keptFiles: BuiltFile[] = codewiki.files
|
|
1084
|
+
.filter((file) => !changedPathSet.has(file.path))
|
|
1085
|
+
.map((file) => ({ file, symbols: symbolsByFileId.get(file.id) ?? [] }));
|
|
1086
|
+
return codewikiFromBuiltFiles(cwd, codewiki.language, [...keptFiles, ...rebuiltFiles], slicer);
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
/**
|
|
1090
|
+
* Reconcile an existing index with the current workspace without parsing
|
|
1091
|
+
* unchanged files. The scan reads and hashes candidate files, then delegates
|
|
1092
|
+
* extraction to the incremental updater only for additions, removals, and
|
|
1093
|
+
* content changes. Callers can still use buildCodewiki when the artifact is
|
|
1094
|
+
* missing or structurally incompatible.
|
|
1095
|
+
*/
|
|
1096
|
+
export async function syncCodewiki(
|
|
1097
|
+
cwd: string,
|
|
1098
|
+
codewiki: Codewiki,
|
|
1099
|
+
options: CodewikiBuildOptions = {},
|
|
1100
|
+
): Promise<Codewiki> {
|
|
1101
|
+
const slicer = options.slicer ?? createSlicer();
|
|
1102
|
+
const readFile = options.readFile ?? defaultReadFile;
|
|
1103
|
+
const currentPaths = (await enumerateWorkspaceFilesAsync(cwd, EXCLUDED_DIRS, undefined, slicer)).filter(
|
|
1104
|
+
isIndexablePath,
|
|
1105
|
+
);
|
|
1106
|
+
const currentFiles = new Map<string, string>();
|
|
1107
|
+
const currentTexts = new Map<string, string>();
|
|
1108
|
+
for (const relPath of currentPaths) {
|
|
1109
|
+
// Reads and hashes every visible file in the workspace. Cheap per file,
|
|
1110
|
+
// seconds in aggregate on a large repo.
|
|
1111
|
+
await slicer.tick();
|
|
1112
|
+
const text = readFile(join(cwd, relPath));
|
|
1113
|
+
if (text !== null) {
|
|
1114
|
+
currentFiles.set(relPath, contentHash(text));
|
|
1115
|
+
currentTexts.set(relPath, text);
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
const indexedFiles = new Map(codewiki.files.map((file) => [file.path, file] as const));
|
|
1119
|
+
const changedPaths = new Set<string>();
|
|
1120
|
+
for (const [relPath, hash] of currentFiles) {
|
|
1121
|
+
if (indexedFiles.get(relPath)?.hash !== hash) changedPaths.add(relPath);
|
|
1122
|
+
}
|
|
1123
|
+
for (const relPath of indexedFiles.keys()) {
|
|
1124
|
+
if (!currentFiles.has(relPath)) changedPaths.add(relPath);
|
|
1125
|
+
}
|
|
1126
|
+
if (changedPaths.size === 0) return codewiki;
|
|
1127
|
+
const syncOptions: CodewikiBuildOptions = {
|
|
1128
|
+
...options,
|
|
1129
|
+
slicer,
|
|
1130
|
+
readFile: (path) => currentTexts.get(normalizeRel(cwd, path)) ?? readFile(path),
|
|
1131
|
+
};
|
|
1132
|
+
return updateCodewikiPaths(cwd, codewiki, [...changedPaths], syncOptions);
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
export function codewikiPath(cwd: string): string {
|
|
1136
|
+
return join(cwd, ".clio-coder", "codewiki.json");
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
export function serializeCodewiki(codewiki: Codewiki): string {
|
|
1140
|
+
return `${JSON.stringify(normalizeCodewiki(codewiki))}\n`;
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
export function writeCodewiki(cwd: string, codewiki: Codewiki): string {
|
|
1144
|
+
const serialized = serializeCodewiki(codewiki);
|
|
1145
|
+
safeResourceWrite(codewikiPath(cwd), serialized, {
|
|
1146
|
+
encoding: "utf8",
|
|
1147
|
+
});
|
|
1148
|
+
return serialized;
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
export function parseCodewikiRaw(raw: string): Codewiki | null {
|
|
1152
|
+
let parsed: unknown;
|
|
1153
|
+
try {
|
|
1154
|
+
parsed = JSON.parse(raw);
|
|
1155
|
+
} catch {
|
|
1156
|
+
return null;
|
|
1157
|
+
}
|
|
1158
|
+
return upgradeCodewiki(parsed);
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
function readCodewikiRaw(cwd: string): { raw: string; codewiki: Codewiki } | null {
|
|
1162
|
+
const filePath = codewikiPath(cwd);
|
|
1163
|
+
if (!existsSync(filePath)) return null;
|
|
1164
|
+
let raw: string;
|
|
1165
|
+
try {
|
|
1166
|
+
raw = readFileSync(filePath, "utf8");
|
|
1167
|
+
} catch {
|
|
1168
|
+
return null;
|
|
1169
|
+
}
|
|
1170
|
+
const codewiki = parseCodewikiRaw(raw);
|
|
1171
|
+
return codewiki ? { raw, codewiki } : null;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
export function readCodewiki(cwd: string): Codewiki | null {
|
|
1175
|
+
return readCodewikiRaw(cwd)?.codewiki ?? null;
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
/**
|
|
1179
|
+
* Read and parse the artifact without blocking on the file read. The parse
|
|
1180
|
+
* itself still runs as one turn, which is what a JSON artifact costs; the read
|
|
1181
|
+
* is the part that scales with repository size and it now happens off the loop.
|
|
1182
|
+
* For status surfaces that poll, prefer this over `readCodewiki`.
|
|
1183
|
+
*/
|
|
1184
|
+
export async function readCodewikiAsync(cwd: string): Promise<Codewiki | null> {
|
|
1185
|
+
let raw: string;
|
|
1186
|
+
try {
|
|
1187
|
+
raw = await readFileAsync(codewikiPath(cwd), "utf8");
|
|
1188
|
+
} catch {
|
|
1189
|
+
return null;
|
|
1190
|
+
}
|
|
1191
|
+
return parseCodewikiRaw(raw);
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
export function codewikiEntries(codewiki: Codewiki): CodewikiEntry[] {
|
|
1195
|
+
const fileById = new Map(codewiki.files.map((file) => [file.id, file] as const));
|
|
1196
|
+
const exportsByFile = new Map<string, string[]>();
|
|
1197
|
+
for (const symbol of codewiki.symbols) {
|
|
1198
|
+
const list = exportsByFile.get(symbol.fileId) ?? [];
|
|
1199
|
+
list.push(symbol.name);
|
|
1200
|
+
exportsByFile.set(symbol.fileId, list);
|
|
1201
|
+
}
|
|
1202
|
+
const importsByFile = new Map<string, string[]>();
|
|
1203
|
+
for (const edge of codewiki.edges) {
|
|
1204
|
+
const list = importsByFile.get(edge.fileId) ?? [];
|
|
1205
|
+
if ("toFileId" in edge) {
|
|
1206
|
+
const target = fileById.get(edge.toFileId);
|
|
1207
|
+
if (target) list.push(target.path);
|
|
1208
|
+
} else {
|
|
1209
|
+
list.push(edge.externalModule);
|
|
1210
|
+
}
|
|
1211
|
+
importsByFile.set(edge.fileId, list);
|
|
1212
|
+
}
|
|
1213
|
+
return codewiki.files
|
|
1214
|
+
.filter((file) => file.lang !== "config")
|
|
1215
|
+
.map<CodewikiEntry>((file) => ({
|
|
1216
|
+
path: file.path,
|
|
1217
|
+
exports: uniqueSorted(exportsByFile.get(file.id) ?? []),
|
|
1218
|
+
imports: uniqueSorted(importsByFile.get(file.id) ?? []),
|
|
1219
|
+
kind: file.role === "entry" ? "entry-point" : file.role === "test" ? "test" : "module",
|
|
1220
|
+
...(file.summary ? { summary: file.summary } : {}),
|
|
1221
|
+
}))
|
|
1222
|
+
.sort((a, b) => a.path.localeCompare(b.path));
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
export function codewikiNeedsBackfill(codewiki: Codewiki): boolean {
|
|
1226
|
+
return codewiki.files.some((file) => file.lang !== "config" && file.hash.length === 0);
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
export function structuralCodewikiHash(codewiki: Codewiki): string {
|
|
1230
|
+
return createHash("sha256")
|
|
1231
|
+
.update(JSON.stringify(normalizeCodewiki(codewiki)))
|
|
1232
|
+
.digest("hex");
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
function normalizeCodewikiFile(file: CodewikiFile): CodewikiFile {
|
|
1236
|
+
return {
|
|
1237
|
+
id: file.id,
|
|
1238
|
+
path: file.path,
|
|
1239
|
+
lang: file.lang,
|
|
1240
|
+
loc: file.loc,
|
|
1241
|
+
role: file.role,
|
|
1242
|
+
hash: file.hash,
|
|
1243
|
+
imports: uniqueSorted(file.imports),
|
|
1244
|
+
...(file.summary ? { summary: file.summary } : {}),
|
|
1245
|
+
};
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
function symbolSigFields(kind: CodewikiSymbolKind, sig: string | undefined): Pick<CodewikiSymbol, "sig"> {
|
|
1249
|
+
if (!CODEWIKI_SYMBOL_KINDS_WITH_SIG.has(kind)) return {};
|
|
1250
|
+
const clean = sig?.trim().slice(0, 240);
|
|
1251
|
+
return clean && clean.length > 0 ? { sig: clean } : {};
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
function normalizeCodewikiSymbol(symbol: CodewikiSymbol): CodewikiSymbol {
|
|
1255
|
+
return {
|
|
1256
|
+
name: symbol.name,
|
|
1257
|
+
kind: symbol.kind,
|
|
1258
|
+
fileId: symbol.fileId,
|
|
1259
|
+
line: symbol.line,
|
|
1260
|
+
...symbolSigFields(symbol.kind, symbol.sig),
|
|
1261
|
+
};
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
function normalizeCodewiki(codewiki: Codewiki): Codewiki {
|
|
1265
|
+
return {
|
|
1266
|
+
version: CODEWIKI_VERSION,
|
|
1267
|
+
language: codewiki.language,
|
|
1268
|
+
files: codewiki.files.map(normalizeCodewikiFile).sort(compareFiles),
|
|
1269
|
+
symbols: codewiki.symbols.map(normalizeCodewikiSymbol).sort(compareCodewikiSymbols),
|
|
1270
|
+
edges: [...codewiki.edges].sort(compareEdges),
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
function upgradeCodewiki(value: unknown): Codewiki | null {
|
|
1275
|
+
if (isCodewikiV5(value)) return normalizeCodewiki(value);
|
|
1276
|
+
if (isCodewikiV4(value)) return upgradeV4Codewiki(value);
|
|
1277
|
+
if (isCodewikiV3(value)) return upgradeV3Codewiki(value);
|
|
1278
|
+
if (isCodewikiV2(value)) return upgradeV2Codewiki(value);
|
|
1279
|
+
return null;
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
interface CodewikiFileV3 {
|
|
1283
|
+
id: string;
|
|
1284
|
+
path: string;
|
|
1285
|
+
lang: CodewikiLanguage;
|
|
1286
|
+
loc: number;
|
|
1287
|
+
role: CodewikiFileRole;
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
interface CodewikiV3 {
|
|
1291
|
+
version: 3;
|
|
1292
|
+
language: ProjectType;
|
|
1293
|
+
files: CodewikiFileV3[];
|
|
1294
|
+
symbols: CodewikiSymbol[];
|
|
1295
|
+
edges: CodewikiEdge[];
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
interface CodewikiV4 {
|
|
1299
|
+
version: 4;
|
|
1300
|
+
language: ProjectType;
|
|
1301
|
+
files: CodewikiFile[];
|
|
1302
|
+
symbols: CodewikiSymbol[];
|
|
1303
|
+
edges: CodewikiEdge[];
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
interface CodewikiV2 {
|
|
1307
|
+
version: 2;
|
|
1308
|
+
generatedAt: string;
|
|
1309
|
+
language: ProjectType;
|
|
1310
|
+
entries: CodewikiEntry[];
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
function upgradeV3Codewiki(value: CodewikiV3): Codewiki {
|
|
1314
|
+
return normalizeCodewiki({
|
|
1315
|
+
version: CODEWIKI_VERSION,
|
|
1316
|
+
language: value.language,
|
|
1317
|
+
files: value.files.map((file) => ({
|
|
1318
|
+
...file,
|
|
1319
|
+
hash: "",
|
|
1320
|
+
imports: [],
|
|
1321
|
+
})),
|
|
1322
|
+
symbols: value.symbols,
|
|
1323
|
+
edges: value.edges,
|
|
1324
|
+
});
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
function upgradeV4Codewiki(value: CodewikiV4): Codewiki {
|
|
1328
|
+
return normalizeCodewiki({
|
|
1329
|
+
version: CODEWIKI_VERSION,
|
|
1330
|
+
language: value.language,
|
|
1331
|
+
// v5 changes C-family extraction and adds CUDA paths. Blank hashes force
|
|
1332
|
+
// one complete rebuild instead of treating a structurally obsolete v4
|
|
1333
|
+
// artifact as fresh.
|
|
1334
|
+
files: value.files.map((file) => ({ ...file, hash: "" })),
|
|
1335
|
+
symbols: value.symbols,
|
|
1336
|
+
edges: value.edges,
|
|
1337
|
+
});
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1340
|
+
function upgradeV2Codewiki(value: CodewikiV2): Codewiki {
|
|
1341
|
+
const files: CodewikiFileV3[] = value.entries.map((entry) => {
|
|
1342
|
+
const lang =
|
|
1343
|
+
languageForPath(entry.path) ??
|
|
1344
|
+
(value.language === "unknown" || value.language === "polyglot" || value.language === "dotfiles"
|
|
1345
|
+
? "config"
|
|
1346
|
+
: value.language);
|
|
1347
|
+
return {
|
|
1348
|
+
id: stableFileId(entry.path),
|
|
1349
|
+
path: entry.path,
|
|
1350
|
+
lang,
|
|
1351
|
+
loc: 0,
|
|
1352
|
+
role: entry.kind === "entry-point" ? "entry" : entry.kind === "test" ? "test" : "module",
|
|
1353
|
+
};
|
|
1354
|
+
});
|
|
1355
|
+
const pathToId = new Map(files.map((file) => [file.path, file.id] as const));
|
|
1356
|
+
const symbols: CodewikiSymbol[] = [];
|
|
1357
|
+
for (const entry of value.entries) {
|
|
1358
|
+
const fileId = pathToId.get(entry.path);
|
|
1359
|
+
if (!fileId) continue;
|
|
1360
|
+
for (const name of entry.exports) symbols.push({ name, kind: "const", fileId, line: 1 });
|
|
1361
|
+
}
|
|
1362
|
+
const edges: CodewikiEdge[] = [];
|
|
1363
|
+
for (const entry of value.entries) {
|
|
1364
|
+
const fileId = pathToId.get(entry.path);
|
|
1365
|
+
if (!fileId) continue;
|
|
1366
|
+
for (const item of entry.imports) {
|
|
1367
|
+
const toFileId = pathToId.get(item);
|
|
1368
|
+
edges.push(toFileId ? { fileId, toFileId } : { fileId, externalModule: item });
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
return upgradeV3Codewiki({
|
|
1372
|
+
version: 3,
|
|
1373
|
+
language: value.language,
|
|
1374
|
+
files,
|
|
1375
|
+
symbols,
|
|
1376
|
+
edges,
|
|
1377
|
+
});
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
function isNormalizedRelativeCodewikiPath(path: string): boolean {
|
|
1381
|
+
if (path.length === 0 || path.includes("\0") || path.includes("\\") || path.startsWith("/")) return false;
|
|
1382
|
+
if (/^[A-Za-z]:\//.test(path)) return false;
|
|
1383
|
+
const segments = path.split("/");
|
|
1384
|
+
return segments.every((segment) => segment.length > 0 && segment !== "." && segment !== "..");
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
function hasValidNativeV5Semantics(value: Codewiki): boolean {
|
|
1388
|
+
const fileIds = new Set<string>();
|
|
1389
|
+
const filePaths = new Set<string>();
|
|
1390
|
+
const locByFileId = new Map<string, number>();
|
|
1391
|
+
for (const file of value.files) {
|
|
1392
|
+
if (fileIds.has(file.id) || filePaths.has(file.path)) return false;
|
|
1393
|
+
if (!isNormalizedRelativeCodewikiPath(file.path) || !/^[0-9a-f]{16}$/.test(file.hash)) return false;
|
|
1394
|
+
fileIds.add(file.id);
|
|
1395
|
+
filePaths.add(file.path);
|
|
1396
|
+
locByFileId.set(file.id, file.loc);
|
|
1397
|
+
}
|
|
1398
|
+
for (const symbol of value.symbols) {
|
|
1399
|
+
const loc = locByFileId.get(symbol.fileId);
|
|
1400
|
+
if (loc === undefined || symbol.line > loc) return false;
|
|
1401
|
+
}
|
|
1402
|
+
for (const edge of value.edges) {
|
|
1403
|
+
if (!fileIds.has(edge.fileId)) return false;
|
|
1404
|
+
if ("toFileId" in edge && !fileIds.has(edge.toFileId)) return false;
|
|
1405
|
+
}
|
|
1406
|
+
return true;
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
function isCodewikiV5(value: unknown): value is Codewiki {
|
|
1410
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
1411
|
+
const obj = value as Record<string, unknown>;
|
|
1412
|
+
if (obj.version !== CODEWIKI_VERSION || typeof obj.language !== "string") return false;
|
|
1413
|
+
if (!Array.isArray(obj.files) || !Array.isArray(obj.symbols) || !Array.isArray(obj.edges)) return false;
|
|
1414
|
+
if (!obj.files.every(isCodewikiFile) || !obj.symbols.every(isCodewikiSymbol) || !obj.edges.every(isCodewikiEdge)) {
|
|
1415
|
+
return false;
|
|
1416
|
+
}
|
|
1417
|
+
return hasValidNativeV5Semantics(obj as unknown as Codewiki);
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
function isCodewikiV4(value: unknown): value is CodewikiV4 {
|
|
1421
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
1422
|
+
const obj = value as Record<string, unknown>;
|
|
1423
|
+
if (obj.version !== 4 || typeof obj.language !== "string") return false;
|
|
1424
|
+
if (!Array.isArray(obj.files) || !Array.isArray(obj.symbols) || !Array.isArray(obj.edges)) return false;
|
|
1425
|
+
return obj.files.every(isCodewikiFile) && obj.symbols.every(isCodewikiSymbol) && obj.edges.every(isCodewikiEdge);
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
function isCodewikiV3(value: unknown): value is CodewikiV3 {
|
|
1429
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
1430
|
+
const obj = value as Record<string, unknown>;
|
|
1431
|
+
if (obj.version !== 3 || typeof obj.language !== "string") return false;
|
|
1432
|
+
if (!Array.isArray(obj.files) || !Array.isArray(obj.symbols) || !Array.isArray(obj.edges)) return false;
|
|
1433
|
+
return obj.files.every(isCodewikiFileV3) && obj.symbols.every(isCodewikiSymbol) && obj.edges.every(isCodewikiEdge);
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
function isCodewikiV2(value: unknown): value is CodewikiV2 {
|
|
1437
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
1438
|
+
const obj = value as Record<string, unknown>;
|
|
1439
|
+
if (obj.version !== 2 || typeof obj.generatedAt !== "string" || typeof obj.language !== "string") return false;
|
|
1440
|
+
if (!Array.isArray(obj.entries)) return false;
|
|
1441
|
+
return obj.entries.every(isCodewikiEntry);
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
const CODEWIKI_LANGUAGES = new Set<CodewikiLanguage>([
|
|
1445
|
+
"typescript",
|
|
1446
|
+
"javascript",
|
|
1447
|
+
"python",
|
|
1448
|
+
"rust",
|
|
1449
|
+
"go",
|
|
1450
|
+
"c",
|
|
1451
|
+
"c++",
|
|
1452
|
+
"java",
|
|
1453
|
+
"ruby",
|
|
1454
|
+
"c#",
|
|
1455
|
+
"config",
|
|
1456
|
+
]);
|
|
1457
|
+
const FILE_ROLES = new Set<CodewikiFileRole>(["entry", "test", "module", "config"]);
|
|
1458
|
+
const SYMBOL_KINDS = new Set<CodewikiSymbolKind>(["func", "class", "method", "type", "const", "var", "trait", "iface"]);
|
|
1459
|
+
|
|
1460
|
+
function isCodewikiFile(value: unknown): value is CodewikiFile {
|
|
1461
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
1462
|
+
const obj = value as Record<string, unknown>;
|
|
1463
|
+
return (
|
|
1464
|
+
typeof obj.id === "string" &&
|
|
1465
|
+
typeof obj.path === "string" &&
|
|
1466
|
+
typeof obj.lang === "string" &&
|
|
1467
|
+
CODEWIKI_LANGUAGES.has(obj.lang as CodewikiLanguage) &&
|
|
1468
|
+
typeof obj.loc === "number" &&
|
|
1469
|
+
Number.isInteger(obj.loc) &&
|
|
1470
|
+
obj.loc >= 0 &&
|
|
1471
|
+
typeof obj.role === "string" &&
|
|
1472
|
+
FILE_ROLES.has(obj.role as CodewikiFileRole) &&
|
|
1473
|
+
typeof obj.hash === "string" &&
|
|
1474
|
+
Array.isArray(obj.imports) &&
|
|
1475
|
+
obj.imports.every((item) => typeof item === "string") &&
|
|
1476
|
+
(!("summary" in obj) || typeof obj.summary === "string")
|
|
1477
|
+
);
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
function isCodewikiFileV3(value: unknown): value is CodewikiFileV3 {
|
|
1481
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
1482
|
+
const obj = value as Record<string, unknown>;
|
|
1483
|
+
return (
|
|
1484
|
+
typeof obj.id === "string" &&
|
|
1485
|
+
typeof obj.path === "string" &&
|
|
1486
|
+
typeof obj.lang === "string" &&
|
|
1487
|
+
CODEWIKI_LANGUAGES.has(obj.lang as CodewikiLanguage) &&
|
|
1488
|
+
typeof obj.loc === "number" &&
|
|
1489
|
+
Number.isInteger(obj.loc) &&
|
|
1490
|
+
obj.loc >= 0 &&
|
|
1491
|
+
typeof obj.role === "string" &&
|
|
1492
|
+
FILE_ROLES.has(obj.role as CodewikiFileRole)
|
|
1493
|
+
);
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
function isCodewikiSymbol(value: unknown): value is CodewikiSymbol {
|
|
1497
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
1498
|
+
const obj = value as Record<string, unknown>;
|
|
1499
|
+
return (
|
|
1500
|
+
typeof obj.name === "string" &&
|
|
1501
|
+
typeof obj.kind === "string" &&
|
|
1502
|
+
SYMBOL_KINDS.has(obj.kind as CodewikiSymbolKind) &&
|
|
1503
|
+
typeof obj.fileId === "string" &&
|
|
1504
|
+
typeof obj.line === "number" &&
|
|
1505
|
+
Number.isInteger(obj.line) &&
|
|
1506
|
+
obj.line >= 1 &&
|
|
1507
|
+
(!("sig" in obj) || typeof obj.sig === "string")
|
|
1508
|
+
);
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
function isCodewikiEdge(value: unknown): value is CodewikiEdge {
|
|
1512
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
1513
|
+
const obj = value as Record<string, unknown>;
|
|
1514
|
+
if (typeof obj.fileId !== "string") return false;
|
|
1515
|
+
const hasToFile = typeof obj.toFileId === "string";
|
|
1516
|
+
const hasExternal = typeof obj.externalModule === "string";
|
|
1517
|
+
return hasToFile !== hasExternal;
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
function isCodewikiEntry(value: unknown): value is CodewikiEntry {
|
|
1521
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
1522
|
+
const obj = value as Record<string, unknown>;
|
|
1523
|
+
if (typeof obj.path !== "string") return false;
|
|
1524
|
+
if (!Array.isArray(obj.exports) || obj.exports.some((item) => typeof item !== "string")) return false;
|
|
1525
|
+
if (!Array.isArray(obj.imports) || obj.imports.some((item) => typeof item !== "string")) return false;
|
|
1526
|
+
if (obj.kind !== "entry-point" && obj.kind !== "test" && obj.kind !== "module") return false;
|
|
1527
|
+
if ("summary" in obj && typeof obj.summary !== "string") return false;
|
|
1528
|
+
return true;
|
|
1529
|
+
}
|