heor-agent-mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +152 -0
- package/dist/audit/builder.d.ts +8 -0
- package/dist/audit/builder.d.ts.map +1 -0
- package/dist/audit/builder.js +37 -0
- package/dist/audit/builder.js.map +1 -0
- package/dist/audit/types.d.ts +30 -0
- package/dist/audit/types.d.ts.map +1 -0
- package/dist/audit/types.js +2 -0
- package/dist/audit/types.js.map +1 -0
- package/dist/formatters/docx.d.ts +5 -0
- package/dist/formatters/docx.d.ts.map +1 -0
- package/dist/formatters/docx.js +207 -0
- package/dist/formatters/docx.js.map +1 -0
- package/dist/formatters/json.d.ts +4 -0
- package/dist/formatters/json.d.ts.map +1 -0
- package/dist/formatters/json.js +4 -0
- package/dist/formatters/json.js.map +1 -0
- package/dist/formatters/markdown.d.ts +5 -0
- package/dist/formatters/markdown.d.ts.map +1 -0
- package/dist/formatters/markdown.js +50 -0
- package/dist/formatters/markdown.js.map +1 -0
- package/dist/knowledge/index.d.ts +8 -0
- package/dist/knowledge/index.d.ts.map +1 -0
- package/dist/knowledge/index.js +8 -0
- package/dist/knowledge/index.js.map +1 -0
- package/dist/knowledge/paths.d.ts +9 -0
- package/dist/knowledge/paths.d.ts.map +1 -0
- package/dist/knowledge/paths.js +35 -0
- package/dist/knowledge/paths.js.map +1 -0
- package/dist/knowledge/projectStore.d.ts +37 -0
- package/dist/knowledge/projectStore.d.ts.map +1 -0
- package/dist/knowledge/projectStore.js +112 -0
- package/dist/knowledge/projectStore.js.map +1 -0
- package/dist/knowledge/rawStore.d.ts +18 -0
- package/dist/knowledge/rawStore.d.ts.map +1 -0
- package/dist/knowledge/rawStore.js +103 -0
- package/dist/knowledge/rawStore.js.map +1 -0
- package/dist/knowledge/search.d.ts +19 -0
- package/dist/knowledge/search.d.ts.map +1 -0
- package/dist/knowledge/search.js +105 -0
- package/dist/knowledge/search.js.map +1 -0
- package/dist/knowledge/types.d.ts +6 -0
- package/dist/knowledge/types.d.ts.map +1 -0
- package/dist/knowledge/types.js +2 -0
- package/dist/knowledge/types.js.map +1 -0
- package/dist/knowledge/wikiStore.d.ts +18 -0
- package/dist/knowledge/wikiStore.d.ts.map +1 -0
- package/dist/knowledge/wikiStore.js +77 -0
- package/dist/knowledge/wikiStore.js.map +1 -0
- package/dist/knowledge/yaml.d.ts +17 -0
- package/dist/knowledge/yaml.d.ts.map +1 -0
- package/dist/knowledge/yaml.js +131 -0
- package/dist/knowledge/yaml.js.map +1 -0
- package/dist/models/distributions.d.ts +28 -0
- package/dist/models/distributions.d.ts.map +1 -0
- package/dist/models/distributions.js +99 -0
- package/dist/models/distributions.js.map +1 -0
- package/dist/models/index.d.ts +11 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +7 -0
- package/dist/models/index.js.map +1 -0
- package/dist/models/markov.d.ts +42 -0
- package/dist/models/markov.d.ts.map +1 -0
- package/dist/models/markov.js +82 -0
- package/dist/models/markov.js.map +1 -0
- package/dist/models/modelUtils.d.ts +29 -0
- package/dist/models/modelUtils.d.ts.map +1 -0
- package/dist/models/modelUtils.js +139 -0
- package/dist/models/modelUtils.js.map +1 -0
- package/dist/models/owsa.d.ts +31 -0
- package/dist/models/owsa.d.ts.map +1 -0
- package/dist/models/owsa.js +103 -0
- package/dist/models/owsa.js.map +1 -0
- package/dist/models/partsa.d.ts +40 -0
- package/dist/models/partsa.d.ts.map +1 -0
- package/dist/models/partsa.js +65 -0
- package/dist/models/partsa.js.map +1 -0
- package/dist/models/psa.d.ts +33 -0
- package/dist/models/psa.d.ts.map +1 -0
- package/dist/models/psa.js +118 -0
- package/dist/models/psa.js.map +1 -0
- package/dist/providers/direct/aifa.d.ts +3 -0
- package/dist/providers/direct/aifa.d.ts.map +1 -0
- package/dist/providers/direct/aifa.js +30 -0
- package/dist/providers/direct/aifa.js.map +1 -0
- package/dist/providers/direct/allOfUs.d.ts +3 -0
- package/dist/providers/direct/allOfUs.d.ts.map +1 -0
- package/dist/providers/direct/allOfUs.js +37 -0
- package/dist/providers/direct/allOfUs.js.map +1 -0
- package/dist/providers/direct/anvisa.d.ts +3 -0
- package/dist/providers/direct/anvisa.d.ts.map +1 -0
- package/dist/providers/direct/anvisa.js +25 -0
- package/dist/providers/direct/anvisa.js.map +1 -0
- package/dist/providers/direct/biorxiv.d.ts +3 -0
- package/dist/providers/direct/biorxiv.d.ts.map +1 -0
- package/dist/providers/direct/biorxiv.js +33 -0
- package/dist/providers/direct/biorxiv.js.map +1 -0
- package/dist/providers/direct/bnf.d.ts +3 -0
- package/dist/providers/direct/bnf.d.ts.map +1 -0
- package/dist/providers/direct/bnf.js +30 -0
- package/dist/providers/direct/bnf.js.map +1 -0
- package/dist/providers/direct/cadthReviews.d.ts +3 -0
- package/dist/providers/direct/cadthReviews.d.ts.map +1 -0
- package/dist/providers/direct/cadthReviews.js +30 -0
- package/dist/providers/direct/cadthReviews.js.map +1 -0
- package/dist/providers/direct/chembl.d.ts +3 -0
- package/dist/providers/direct/chembl.d.ts.map +1 -0
- package/dist/providers/direct/chembl.js +24 -0
- package/dist/providers/direct/chembl.js.map +1 -0
- package/dist/providers/direct/citeline.d.ts +3 -0
- package/dist/providers/direct/citeline.d.ts.map +1 -0
- package/dist/providers/direct/citeline.js +50 -0
- package/dist/providers/direct/citeline.js.map +1 -0
- package/dist/providers/direct/clinicalTrials.d.ts +3 -0
- package/dist/providers/direct/clinicalTrials.d.ts.map +1 -0
- package/dist/providers/direct/clinicalTrials.js +29 -0
- package/dist/providers/direct/clinicalTrials.js.map +1 -0
- package/dist/providers/direct/cmsNadac.d.ts +3 -0
- package/dist/providers/direct/cmsNadac.d.ts.map +1 -0
- package/dist/providers/direct/cmsNadac.js +52 -0
- package/dist/providers/direct/cmsNadac.js.map +1 -0
- package/dist/providers/direct/cochrane.d.ts +3 -0
- package/dist/providers/direct/cochrane.d.ts.map +1 -0
- package/dist/providers/direct/cochrane.js +46 -0
- package/dist/providers/direct/cochrane.js.map +1 -0
- package/dist/providers/direct/conitec.d.ts +3 -0
- package/dist/providers/direct/conitec.d.ts.map +1 -0
- package/dist/providers/direct/conitec.js +25 -0
- package/dist/providers/direct/conitec.js.map +1 -0
- package/dist/providers/direct/cortellis.d.ts +3 -0
- package/dist/providers/direct/cortellis.d.ts.map +1 -0
- package/dist/providers/direct/cortellis.js +52 -0
- package/dist/providers/direct/cortellis.js.map +1 -0
- package/dist/providers/direct/datasus.d.ts +3 -0
- package/dist/providers/direct/datasus.d.ts.map +1 -0
- package/dist/providers/direct/datasus.js +30 -0
- package/dist/providers/direct/datasus.js.map +1 -0
- package/dist/providers/direct/embase.d.ts +3 -0
- package/dist/providers/direct/embase.d.ts.map +1 -0
- package/dist/providers/direct/embase.js +54 -0
- package/dist/providers/direct/embase.js.map +1 -0
- package/dist/providers/direct/fonasa.d.ts +3 -0
- package/dist/providers/direct/fonasa.d.ts.map +1 -0
- package/dist/providers/direct/fonasa.js +25 -0
- package/dist/providers/direct/fonasa.js.map +1 -0
- package/dist/providers/direct/gbaDecisions.d.ts +3 -0
- package/dist/providers/direct/gbaDecisions.d.ts.map +1 -0
- package/dist/providers/direct/gbaDecisions.js +30 -0
- package/dist/providers/direct/gbaDecisions.js.map +1 -0
- package/dist/providers/direct/googleScholar.d.ts +3 -0
- package/dist/providers/direct/googleScholar.d.ts.map +1 -0
- package/dist/providers/direct/googleScholar.js +39 -0
- package/dist/providers/direct/googleScholar.js.map +1 -0
- package/dist/providers/direct/hasTc.d.ts +3 -0
- package/dist/providers/direct/hasTc.d.ts.map +1 -0
- package/dist/providers/direct/hasTc.js +30 -0
- package/dist/providers/direct/hasTc.js.map +1 -0
- package/dist/providers/direct/hitap.d.ts +3 -0
- package/dist/providers/direct/hitap.d.ts.map +1 -0
- package/dist/providers/direct/hitap.js +30 -0
- package/dist/providers/direct/hitap.js.map +1 -0
- package/dist/providers/direct/icerReports.d.ts +3 -0
- package/dist/providers/direct/icerReports.d.ts.map +1 -0
- package/dist/providers/direct/icerReports.js +30 -0
- package/dist/providers/direct/icerReports.js.map +1 -0
- package/dist/providers/direct/iets.d.ts +3 -0
- package/dist/providers/direct/iets.d.ts.map +1 -0
- package/dist/providers/direct/iets.js +25 -0
- package/dist/providers/direct/iets.js.map +1 -0
- package/dist/providers/direct/ihmeGbd.d.ts +3 -0
- package/dist/providers/direct/ihmeGbd.d.ts.map +1 -0
- package/dist/providers/direct/ihmeGbd.js +74 -0
- package/dist/providers/direct/ihmeGbd.js.map +1 -0
- package/dist/providers/direct/index.d.ts +7 -0
- package/dist/providers/direct/index.d.ts.map +1 -0
- package/dist/providers/direct/index.js +186 -0
- package/dist/providers/direct/index.js.map +1 -0
- package/dist/providers/direct/inesss.d.ts +3 -0
- package/dist/providers/direct/inesss.d.ts.map +1 -0
- package/dist/providers/direct/inesss.js +30 -0
- package/dist/providers/direct/inesss.js.map +1 -0
- package/dist/providers/direct/iqwig.d.ts +3 -0
- package/dist/providers/direct/iqwig.d.ts.map +1 -0
- package/dist/providers/direct/iqwig.js +30 -0
- package/dist/providers/direct/iqwig.js.map +1 -0
- package/dist/providers/direct/ispor.d.ts +3 -0
- package/dist/providers/direct/ispor.d.ts.map +1 -0
- package/dist/providers/direct/ispor.js +35 -0
- package/dist/providers/direct/ispor.js.map +1 -0
- package/dist/providers/direct/nhsCosts.d.ts +3 -0
- package/dist/providers/direct/nhsCosts.d.ts.map +1 -0
- package/dist/providers/direct/nhsCosts.js +32 -0
- package/dist/providers/direct/nhsCosts.js.map +1 -0
- package/dist/providers/direct/niceTa.d.ts +3 -0
- package/dist/providers/direct/niceTa.d.ts.map +1 -0
- package/dist/providers/direct/niceTa.js +30 -0
- package/dist/providers/direct/niceTa.js.map +1 -0
- package/dist/providers/direct/oecd.d.ts +3 -0
- package/dist/providers/direct/oecd.d.ts.map +1 -0
- package/dist/providers/direct/oecd.js +102 -0
- package/dist/providers/direct/oecd.js.map +1 -0
- package/dist/providers/direct/orangeBook.d.ts +3 -0
- package/dist/providers/direct/orangeBook.d.ts.map +1 -0
- package/dist/providers/direct/orangeBook.js +48 -0
- package/dist/providers/direct/orangeBook.js.map +1 -0
- package/dist/providers/direct/paho.d.ts +3 -0
- package/dist/providers/direct/paho.d.ts.map +1 -0
- package/dist/providers/direct/paho.js +30 -0
- package/dist/providers/direct/paho.js.map +1 -0
- package/dist/providers/direct/pbacPsd.d.ts +3 -0
- package/dist/providers/direct/pbacPsd.d.ts.map +1 -0
- package/dist/providers/direct/pbacPsd.js +30 -0
- package/dist/providers/direct/pbacPsd.js.map +1 -0
- package/dist/providers/direct/pbsSchedule.d.ts +3 -0
- package/dist/providers/direct/pbsSchedule.d.ts.map +1 -0
- package/dist/providers/direct/pbsSchedule.js +37 -0
- package/dist/providers/direct/pbsSchedule.js.map +1 -0
- package/dist/providers/direct/pharmapendium.d.ts +3 -0
- package/dist/providers/direct/pharmapendium.d.ts.map +1 -0
- package/dist/providers/direct/pharmapendium.js +39 -0
- package/dist/providers/direct/pharmapendium.js.map +1 -0
- package/dist/providers/direct/proxyClient.d.ts +15 -0
- package/dist/providers/direct/proxyClient.d.ts.map +1 -0
- package/dist/providers/direct/proxyClient.js +76 -0
- package/dist/providers/direct/proxyClient.js.map +1 -0
- package/dist/providers/direct/pssru.d.ts +3 -0
- package/dist/providers/direct/pssru.d.ts.map +1 -0
- package/dist/providers/direct/pssru.js +33 -0
- package/dist/providers/direct/pssru.js.map +1 -0
- package/dist/providers/direct/pubmed.d.ts +3 -0
- package/dist/providers/direct/pubmed.d.ts.map +1 -0
- package/dist/providers/direct/pubmed.js +73 -0
- package/dist/providers/direct/pubmed.js.map +1 -0
- package/dist/providers/direct/purpleBook.d.ts +3 -0
- package/dist/providers/direct/purpleBook.d.ts.map +1 -0
- package/dist/providers/direct/purpleBook.js +52 -0
- package/dist/providers/direct/purpleBook.js.map +1 -0
- package/dist/providers/direct/tlv.d.ts +3 -0
- package/dist/providers/direct/tlv.d.ts.map +1 -0
- package/dist/providers/direct/tlv.js +30 -0
- package/dist/providers/direct/tlv.js.map +1 -0
- package/dist/providers/direct/whoGho.d.ts +3 -0
- package/dist/providers/direct/whoGho.d.ts.map +1 -0
- package/dist/providers/direct/whoGho.js +51 -0
- package/dist/providers/direct/whoGho.js.map +1 -0
- package/dist/providers/direct/worldBank.d.ts +3 -0
- package/dist/providers/direct/worldBank.d.ts.map +1 -0
- package/dist/providers/direct/worldBank.js +54 -0
- package/dist/providers/direct/worldBank.js.map +1 -0
- package/dist/providers/factory.d.ts +3 -0
- package/dist/providers/factory.d.ts.map +1 -0
- package/dist/providers/factory.js +8 -0
- package/dist/providers/factory.js.map +1 -0
- package/dist/providers/hosted/index.d.ts +9 -0
- package/dist/providers/hosted/index.d.ts.map +1 -0
- package/dist/providers/hosted/index.js +16 -0
- package/dist/providers/hosted/index.js.map +1 -0
- package/dist/providers/types.d.ts +176 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +2 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +80 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/costEffectivenessModel.d.ts +98 -0
- package/dist/tools/costEffectivenessModel.d.ts.map +1 -0
- package/dist/tools/costEffectivenessModel.js +404 -0
- package/dist/tools/costEffectivenessModel.js.map +1 -0
- package/dist/tools/htaDossierPrep.d.ts +69 -0
- package/dist/tools/htaDossierPrep.d.ts.map +1 -0
- package/dist/tools/htaDossierPrep.js +399 -0
- package/dist/tools/htaDossierPrep.js.map +1 -0
- package/dist/tools/knowledgeRead.d.ts +21 -0
- package/dist/tools/knowledgeRead.d.ts.map +1 -0
- package/dist/tools/knowledgeRead.js +38 -0
- package/dist/tools/knowledgeRead.js.map +1 -0
- package/dist/tools/knowledgeSearch.d.ts +37 -0
- package/dist/tools/knowledgeSearch.d.ts.map +1 -0
- package/dist/tools/knowledgeSearch.js +51 -0
- package/dist/tools/knowledgeSearch.js.map +1 -0
- package/dist/tools/knowledgeWrite.d.ts +25 -0
- package/dist/tools/knowledgeWrite.d.ts.map +1 -0
- package/dist/tools/knowledgeWrite.js +40 -0
- package/dist/tools/knowledgeWrite.js.map +1 -0
- package/dist/tools/literatureSearch.d.ts +42 -0
- package/dist/tools/literatureSearch.d.ts.map +1 -0
- package/dist/tools/literatureSearch.js +142 -0
- package/dist/tools/literatureSearch.js.map +1 -0
- package/dist/tools/metabolicProfile.d.ts +19 -0
- package/dist/tools/metabolicProfile.d.ts.map +1 -0
- package/dist/tools/metabolicProfile.js +150 -0
- package/dist/tools/metabolicProfile.js.map +1 -0
- package/dist/tools/projectCreate.d.ts +37 -0
- package/dist/tools/projectCreate.d.ts.map +1 -0
- package/dist/tools/projectCreate.js +61 -0
- package/dist/tools/projectCreate.js.map +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { homedir } from "node:os";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
export function getKbRoot() {
|
|
4
|
+
return process.env.HEOR_KB_ROOT ?? join(homedir(), ".heor-agent");
|
|
5
|
+
}
|
|
6
|
+
export function getProjectRoot(projectId) {
|
|
7
|
+
return join(getKbRoot(), "projects", sanitizeProjectId(projectId));
|
|
8
|
+
}
|
|
9
|
+
export function getRawLiteratureDir(projectId) {
|
|
10
|
+
return join(getProjectRoot(projectId), "raw", "literature");
|
|
11
|
+
}
|
|
12
|
+
export function getRawModelsDir(projectId) {
|
|
13
|
+
return join(getProjectRoot(projectId), "raw", "models");
|
|
14
|
+
}
|
|
15
|
+
export function getRawDossiersDir(projectId) {
|
|
16
|
+
return join(getProjectRoot(projectId), "raw", "dossiers");
|
|
17
|
+
}
|
|
18
|
+
export function getWikiDir(projectId) {
|
|
19
|
+
return join(getProjectRoot(projectId), "wiki");
|
|
20
|
+
}
|
|
21
|
+
// Sanitize project ID to prevent path traversal and filesystem issues
|
|
22
|
+
export function sanitizeProjectId(id) {
|
|
23
|
+
// Allow alphanumeric, hyphens, underscores. Replace all else with hyphen.
|
|
24
|
+
const clean = id.replace(/[^a-zA-Z0-9_-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
25
|
+
if (clean.length === 0)
|
|
26
|
+
throw new Error("Invalid project ID: must contain alphanumeric characters");
|
|
27
|
+
if (clean.length > 64)
|
|
28
|
+
return clean.slice(0, 64).toLowerCase();
|
|
29
|
+
return clean.toLowerCase();
|
|
30
|
+
}
|
|
31
|
+
// Sanitize filename (for file IDs like "pubmed_12345")
|
|
32
|
+
export function sanitizeFilename(name) {
|
|
33
|
+
return name.replace(/[^a-zA-Z0-9_.-]/g, "_").slice(0, 200);
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/knowledge/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,UAAU,SAAS;IACvB,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,aAAa,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,SAAiB;IAC9C,OAAO,IAAI,CAAC,SAAS,EAAE,EAAE,UAAU,EAAE,iBAAiB,CAAC,SAAS,CAAC,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,SAAiB;IACnD,OAAO,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,OAAO,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,SAAiB;IACjD,OAAO,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,SAAiB;IAC1C,OAAO,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC;AACjD,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,iBAAiB,CAAC,EAAU;IAC1C,0EAA0E;IAC1E,MAAM,KAAK,GAAG,EAAE,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC3F,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IACpG,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAC/D,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC;AAC7B,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC7D,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface ProjectConfig {
|
|
2
|
+
project_id: string;
|
|
3
|
+
drug: string;
|
|
4
|
+
indication: string;
|
|
5
|
+
hta_targets?: string[];
|
|
6
|
+
picos?: Array<{
|
|
7
|
+
id: string;
|
|
8
|
+
population: string;
|
|
9
|
+
comparator: string;
|
|
10
|
+
outcomes: string[];
|
|
11
|
+
}>;
|
|
12
|
+
created_at: string;
|
|
13
|
+
notes?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ProjectCreateParams {
|
|
16
|
+
project_id: string;
|
|
17
|
+
drug: string;
|
|
18
|
+
indication: string;
|
|
19
|
+
hta_targets?: string[];
|
|
20
|
+
notes?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function projectExists(projectId: string): Promise<boolean>;
|
|
23
|
+
/**
|
|
24
|
+
* Create a new project with directory skeleton and project.yaml.
|
|
25
|
+
* Idempotent: if project exists, returns existing config without overwriting.
|
|
26
|
+
*/
|
|
27
|
+
export declare function createProject(params: ProjectCreateParams): Promise<{
|
|
28
|
+
config: ProjectConfig;
|
|
29
|
+
created: boolean;
|
|
30
|
+
path: string;
|
|
31
|
+
}>;
|
|
32
|
+
export declare function readProjectConfig(projectId: string): Promise<ProjectConfig>;
|
|
33
|
+
/**
|
|
34
|
+
* List all projects in the KB root.
|
|
35
|
+
*/
|
|
36
|
+
export declare function listProjects(): Promise<string[]>;
|
|
37
|
+
//# sourceMappingURL=projectStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projectStore.d.ts","sourceRoot":"","sources":["../../src/knowledge/projectStore.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAC1F,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQvE;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAsDpE;AAED,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAcjF;AAiBD;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAWtD"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { writeFile, readFile, mkdir, access, readdir } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { getProjectRoot, getWikiDir, getRawLiteratureDir, getRawModelsDir, getRawDossiersDir, getKbRoot, sanitizeProjectId, } from "./paths.js";
|
|
4
|
+
import { stringifyFrontmatter, parseFrontmatter } from "./yaml.js";
|
|
5
|
+
export async function projectExists(projectId) {
|
|
6
|
+
try {
|
|
7
|
+
const yamlPath = join(getProjectRoot(projectId), "project.yaml");
|
|
8
|
+
await access(yamlPath);
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Create a new project with directory skeleton and project.yaml.
|
|
17
|
+
* Idempotent: if project exists, returns existing config without overwriting.
|
|
18
|
+
*/
|
|
19
|
+
export async function createProject(params) {
|
|
20
|
+
const projectId = sanitizeProjectId(params.project_id);
|
|
21
|
+
const projectRoot = getProjectRoot(projectId);
|
|
22
|
+
if (await projectExists(projectId)) {
|
|
23
|
+
const existing = await readProjectConfig(projectId);
|
|
24
|
+
return { config: existing, created: false, path: projectRoot };
|
|
25
|
+
}
|
|
26
|
+
// Create directory skeleton
|
|
27
|
+
await mkdir(getRawLiteratureDir(projectId), { recursive: true });
|
|
28
|
+
await mkdir(getRawModelsDir(projectId), { recursive: true });
|
|
29
|
+
await mkdir(getRawDossiersDir(projectId), { recursive: true });
|
|
30
|
+
await mkdir(getWikiDir(projectId), { recursive: true });
|
|
31
|
+
const config = {
|
|
32
|
+
project_id: projectId,
|
|
33
|
+
drug: params.drug,
|
|
34
|
+
indication: params.indication,
|
|
35
|
+
hta_targets: params.hta_targets ?? [],
|
|
36
|
+
picos: [],
|
|
37
|
+
created_at: new Date().toISOString(),
|
|
38
|
+
notes: params.notes,
|
|
39
|
+
};
|
|
40
|
+
await writeProjectConfig(projectId, config);
|
|
41
|
+
// Create starter wiki index.md
|
|
42
|
+
const indexContent = `---
|
|
43
|
+
project: ${projectId}
|
|
44
|
+
drug: ${params.drug}
|
|
45
|
+
indication: ${params.indication}
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
# ${params.drug} — ${params.indication}
|
|
49
|
+
|
|
50
|
+
Project knowledge base index.
|
|
51
|
+
|
|
52
|
+
## Structure
|
|
53
|
+
- [[trials/]] — clinical trials and evidence
|
|
54
|
+
- [[comparators/]] — comparator drugs and standards of care
|
|
55
|
+
- [[outcomes/]] — outcome measures and endpoints
|
|
56
|
+
- [[picos/]] — PICO definitions per scoping decision
|
|
57
|
+
- [[models/]] — CE model runs and PSA results
|
|
58
|
+
|
|
59
|
+
## Data Sources
|
|
60
|
+
Raw search results are auto-saved to \`raw/literature/\`, \`raw/models/\`, and \`raw/dossiers/\`.
|
|
61
|
+
|
|
62
|
+
*Created: ${config.created_at}*
|
|
63
|
+
`;
|
|
64
|
+
await writeFile(join(getWikiDir(projectId), "index.md"), indexContent, "utf-8");
|
|
65
|
+
return { config, created: true, path: projectRoot };
|
|
66
|
+
}
|
|
67
|
+
export async function readProjectConfig(projectId) {
|
|
68
|
+
const yamlPath = join(getProjectRoot(projectId), "project.yaml");
|
|
69
|
+
const raw = await readFile(yamlPath, "utf-8");
|
|
70
|
+
const { frontmatter } = parseFrontmatter(raw);
|
|
71
|
+
return {
|
|
72
|
+
project_id: String(frontmatter.project_id ?? projectId),
|
|
73
|
+
drug: String(frontmatter.drug ?? ""),
|
|
74
|
+
indication: String(frontmatter.indication ?? ""),
|
|
75
|
+
hta_targets: Array.isArray(frontmatter.hta_targets) ? frontmatter.hta_targets : [],
|
|
76
|
+
picos: [], // picos are complex; skip for v1
|
|
77
|
+
created_at: String(frontmatter.created_at ?? ""),
|
|
78
|
+
notes: frontmatter.notes ? String(frontmatter.notes) : undefined,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
async function writeProjectConfig(projectId, config) {
|
|
82
|
+
const yamlPath = join(getProjectRoot(projectId), "project.yaml");
|
|
83
|
+
// project.yaml uses frontmatter format (--- delimiters) for consistency with other .md files
|
|
84
|
+
const fm = {
|
|
85
|
+
project_id: config.project_id,
|
|
86
|
+
drug: config.drug,
|
|
87
|
+
indication: config.indication,
|
|
88
|
+
hta_targets: config.hta_targets ?? [],
|
|
89
|
+
created_at: config.created_at,
|
|
90
|
+
};
|
|
91
|
+
if (config.notes)
|
|
92
|
+
fm.notes = config.notes;
|
|
93
|
+
const body = "# Project metadata\nManaged by heor-agent-mcp. Edit with care.";
|
|
94
|
+
await writeFile(yamlPath, stringifyFrontmatter(fm, body), "utf-8");
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* List all projects in the KB root.
|
|
98
|
+
*/
|
|
99
|
+
export async function listProjects() {
|
|
100
|
+
try {
|
|
101
|
+
const projectsRoot = join(getKbRoot(), "projects");
|
|
102
|
+
const entries = await readdir(projectsRoot, { withFileTypes: true });
|
|
103
|
+
return entries
|
|
104
|
+
.filter(e => e.isDirectory())
|
|
105
|
+
.map(e => e.name)
|
|
106
|
+
.sort();
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return [];
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=projectStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projectStore.js","sourceRoot":"","sources":["../../src/knowledge/projectStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { LiteratureResult } from "../providers/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Save a literature result to the project's raw/literature/ directory.
|
|
4
|
+
* If a file with the same ID exists, merges: keeps original metadata,
|
|
5
|
+
* appends current timestamp to retrieved_at array, appends query to query_history.
|
|
6
|
+
*/
|
|
7
|
+
export declare function saveLiteratureResult(projectId: string, result: LiteratureResult, query: string): Promise<string>;
|
|
8
|
+
/**
|
|
9
|
+
* Save a CE model run to raw/models/.
|
|
10
|
+
* Filename: {iso-date}_{model_type}.md
|
|
11
|
+
*/
|
|
12
|
+
export declare function saveModelRun(projectId: string, metadata: Record<string, unknown>, textContent: string): Promise<string>;
|
|
13
|
+
/**
|
|
14
|
+
* Save an HTA dossier draft to raw/dossiers/.
|
|
15
|
+
* Filename: {hta_body}_{submission_type}_{iso-date}.md
|
|
16
|
+
*/
|
|
17
|
+
export declare function saveDossier(projectId: string, htaBody: string, submissionType: string, metadata: Record<string, unknown>, textContent: string): Promise<string>;
|
|
18
|
+
//# sourceMappingURL=rawStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rawStore.d.ts","sourceRoot":"","sources":["../../src/knowledge/rawStore.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,gBAAgB,EACxB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,CA2CjB;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CAoBjB;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,CAAC,CAqBjB"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile, access } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { parseFrontmatter, stringifyFrontmatter } from "./yaml.js";
|
|
4
|
+
import { sanitizeFilename, getRawLiteratureDir, getRawModelsDir, getRawDossiersDir } from "./paths.js";
|
|
5
|
+
/**
|
|
6
|
+
* Save a literature result to the project's raw/literature/ directory.
|
|
7
|
+
* If a file with the same ID exists, merges: keeps original metadata,
|
|
8
|
+
* appends current timestamp to retrieved_at array, appends query to query_history.
|
|
9
|
+
*/
|
|
10
|
+
export async function saveLiteratureResult(projectId, result, query) {
|
|
11
|
+
const dir = getRawLiteratureDir(projectId);
|
|
12
|
+
await mkdir(dir, { recursive: true });
|
|
13
|
+
const filename = `${sanitizeFilename(result.id)}.md`;
|
|
14
|
+
const filepath = join(dir, filename);
|
|
15
|
+
const nowIso = new Date().toISOString();
|
|
16
|
+
let frontmatter;
|
|
17
|
+
let body;
|
|
18
|
+
if (await fileExists(filepath)) {
|
|
19
|
+
// Merge: read existing, append retrieval
|
|
20
|
+
const existing = await readFile(filepath, "utf-8");
|
|
21
|
+
const parsed = parseFrontmatter(existing);
|
|
22
|
+
frontmatter = parsed.frontmatter;
|
|
23
|
+
body = parsed.body;
|
|
24
|
+
const retrievedAt = Array.isArray(frontmatter.retrieved_at) ? frontmatter.retrieved_at : [];
|
|
25
|
+
const queryHistory = Array.isArray(frontmatter.query_history) ? frontmatter.query_history : [];
|
|
26
|
+
frontmatter.retrieved_at = [...retrievedAt, nowIso];
|
|
27
|
+
if (!queryHistory.includes(query)) {
|
|
28
|
+
frontmatter.query_history = [...queryHistory, query];
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
// Create new
|
|
33
|
+
frontmatter = {
|
|
34
|
+
id: result.id,
|
|
35
|
+
source: result.source,
|
|
36
|
+
title: result.title,
|
|
37
|
+
authors: result.authors,
|
|
38
|
+
date: result.date,
|
|
39
|
+
study_type: result.study_type,
|
|
40
|
+
url: result.url,
|
|
41
|
+
project: projectId,
|
|
42
|
+
retrieved_at: [nowIso],
|
|
43
|
+
query_history: [query],
|
|
44
|
+
};
|
|
45
|
+
body = `# ${result.title}\n\n${result.abstract || "*No abstract available*"}\n\n**URL:** ${result.url}`;
|
|
46
|
+
}
|
|
47
|
+
const content = stringifyFrontmatter(frontmatter, body);
|
|
48
|
+
await writeFile(filepath, content, "utf-8");
|
|
49
|
+
return filepath;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Save a CE model run to raw/models/.
|
|
53
|
+
* Filename: {iso-date}_{model_type}.md
|
|
54
|
+
*/
|
|
55
|
+
export async function saveModelRun(projectId, metadata, textContent) {
|
|
56
|
+
const dir = getRawModelsDir(projectId);
|
|
57
|
+
await mkdir(dir, { recursive: true });
|
|
58
|
+
const nowIso = new Date().toISOString().replace(/[:.]/g, "-");
|
|
59
|
+
const modelType = String(metadata.model_type ?? "markov");
|
|
60
|
+
const filename = `${nowIso}_${sanitizeFilename(modelType)}.md`;
|
|
61
|
+
const filepath = join(dir, filename);
|
|
62
|
+
const frontmatter = {
|
|
63
|
+
tool: "cost_effectiveness_model",
|
|
64
|
+
generated_at: new Date().toISOString(),
|
|
65
|
+
project: projectId,
|
|
66
|
+
...Object.fromEntries(Object.entries(metadata).map(([k, v]) => [k, v])),
|
|
67
|
+
};
|
|
68
|
+
const content = stringifyFrontmatter(frontmatter, textContent);
|
|
69
|
+
await writeFile(filepath, content, "utf-8");
|
|
70
|
+
return filepath;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Save an HTA dossier draft to raw/dossiers/.
|
|
74
|
+
* Filename: {hta_body}_{submission_type}_{iso-date}.md
|
|
75
|
+
*/
|
|
76
|
+
export async function saveDossier(projectId, htaBody, submissionType, metadata, textContent) {
|
|
77
|
+
const dir = getRawDossiersDir(projectId);
|
|
78
|
+
await mkdir(dir, { recursive: true });
|
|
79
|
+
const nowIso = new Date().toISOString().replace(/[:.]/g, "-");
|
|
80
|
+
const filename = `${sanitizeFilename(htaBody)}_${sanitizeFilename(submissionType)}_${nowIso}.md`;
|
|
81
|
+
const filepath = join(dir, filename);
|
|
82
|
+
const frontmatter = {
|
|
83
|
+
tool: "hta_dossier_prep",
|
|
84
|
+
hta_body: htaBody,
|
|
85
|
+
submission_type: submissionType,
|
|
86
|
+
generated_at: new Date().toISOString(),
|
|
87
|
+
project: projectId,
|
|
88
|
+
...Object.fromEntries(Object.entries(metadata).map(([k, v]) => [k, v])),
|
|
89
|
+
};
|
|
90
|
+
const content = stringifyFrontmatter(frontmatter, textContent);
|
|
91
|
+
await writeFile(filepath, content, "utf-8");
|
|
92
|
+
return filepath;
|
|
93
|
+
}
|
|
94
|
+
async function fileExists(path) {
|
|
95
|
+
try {
|
|
96
|
+
await access(path);
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=rawStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rawStore.js","sourceRoot":"","sources":["../../src/knowledge/rawStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAoB,MAAM,WAAW,CAAC;AACrF,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAGvG;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,SAAiB,EACjB,MAAwB,EACxB,KAAa;IAEb,MAAM,GAAG,GAAG,mBAAmB,CAAC,SAAS,CAAC,CAAC;IAC3C,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEtC,MAAM,QAAQ,GAAG,GAAG,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC;IACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAExC,IAAI,WAAwB,CAAC;IAC7B,IAAI,IAAY,CAAC;IAEjB,IAAI,MAAM,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/B,yCAAyC;QACzC,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAC1C,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;QACjC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACnB,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5F,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/F,WAAW,CAAC,YAAY,GAAG,CAAC,GAAG,WAAW,EAAE,MAAM,CAAC,CAAC;QACpD,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAClC,WAAW,CAAC,aAAa,GAAG,CAAC,GAAG,YAAY,EAAE,KAAK,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;SAAM,CAAC;QACN,aAAa;QACb,WAAW,GAAG;YACZ,EAAE,EAAE,MAAM,CAAC,EAAE;YACb,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,GAAG,EAAE,MAAM,CAAC,GAAG;YACf,OAAO,EAAE,SAAS;YAClB,YAAY,EAAE,CAAC,MAAM,CAAC;YACtB,aAAa,EAAE,CAAC,KAAK,CAAC;SACvB,CAAC;QACF,IAAI,GAAG,KAAK,MAAM,CAAC,KAAK,OAAO,MAAM,CAAC,QAAQ,IAAI,yBAAyB,gBAAgB,MAAM,CAAC,GAAG,EAAE,CAAC;IAC1G,CAAC;IAED,MAAM,OAAO,GAAG,oBAAoB,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IACxD,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,SAAiB,EACjB,QAAiC,EACjC,WAAmB;IAEnB,MAAM,GAAG,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IACvC,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC9D,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,UAAU,IAAI,QAAQ,CAAC,CAAC;IAC1D,MAAM,QAAQ,GAAG,GAAG,MAAM,IAAI,gBAAgB,CAAC,SAAS,CAAC,KAAK,CAAC;IAC/D,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAErC,MAAM,WAAW,GAAgB;QAC/B,IAAI,EAAE,0BAA0B;QAChC,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACtC,OAAO,EAAE,SAAS;QAClB,GAAG,MAAM,CAAC,WAAW,CACnB,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAyC,CAAC,CAAC,CACzF;KACF,CAAC;IAEF,MAAM,OAAO,GAAG,oBAAoB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IAC/D,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,SAAiB,EACjB,OAAe,EACf,cAAsB,EACtB,QAAiC,EACjC,WAAmB;IAEnB,MAAM,GAAG,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC9D,MAAM,QAAQ,GAAG,GAAG,gBAAgB,CAAC,OAAO,CAAC,IAAI,gBAAgB,CAAC,cAAc,CAAC,IAAI,MAAM,KAAK,CAAC;IACjG,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAErC,MAAM,WAAW,GAAgB;QAC/B,IAAI,EAAE,kBAAkB;QACxB,QAAQ,EAAE,OAAO;QACjB,eAAe,EAAE,cAAc;QAC/B,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACtC,OAAO,EAAE,SAAS;QAClB,GAAG,MAAM,CAAC,WAAW,CACnB,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAyC,CAAC,CAAC,CACzF;KACF,CAAC;IAEF,MAAM,OAAO,GAAG,oBAAoB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IAC/D,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,IAAY;IACpC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface SearchMatch {
|
|
2
|
+
file: string;
|
|
3
|
+
line_number: number;
|
|
4
|
+
snippet: string;
|
|
5
|
+
score: number;
|
|
6
|
+
title?: string;
|
|
7
|
+
source?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface SearchOptions {
|
|
10
|
+
paths?: Array<"raw" | "wiki">;
|
|
11
|
+
max_results?: number;
|
|
12
|
+
case_sensitive?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Search project files for a query. Returns matches with snippets.
|
|
16
|
+
* Case-insensitive by default. Multi-term queries match any term (OR).
|
|
17
|
+
*/
|
|
18
|
+
export declare function searchProject(projectId: string, query: string, options?: SearchOptions): Promise<SearchMatch[]>;
|
|
19
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/knowledge/search.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,WAAW,EAAE,CAAC,CA0BxB"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
2
|
+
import { join, relative } from "node:path";
|
|
3
|
+
import { getProjectRoot } from "./paths.js";
|
|
4
|
+
/**
|
|
5
|
+
* Search project files for a query. Returns matches with snippets.
|
|
6
|
+
* Case-insensitive by default. Multi-term queries match any term (OR).
|
|
7
|
+
*/
|
|
8
|
+
export async function searchProject(projectId, query, options = {}) {
|
|
9
|
+
const { paths = ["raw", "wiki"], max_results = 20, case_sensitive = false } = options;
|
|
10
|
+
const projectRoot = getProjectRoot(projectId);
|
|
11
|
+
// Tokenize query into terms
|
|
12
|
+
const terms = query.trim().split(/\s+/).filter(Boolean);
|
|
13
|
+
if (terms.length === 0)
|
|
14
|
+
return [];
|
|
15
|
+
const matches = [];
|
|
16
|
+
for (const subtree of paths) {
|
|
17
|
+
const dirPath = join(projectRoot, subtree);
|
|
18
|
+
try {
|
|
19
|
+
const files = await walkMarkdownFiles(dirPath);
|
|
20
|
+
for (const filePath of files) {
|
|
21
|
+
const fileMatches = await searchFile(filePath, projectRoot, terms, case_sensitive);
|
|
22
|
+
matches.push(...fileMatches);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
// Directory doesn't exist yet — skip
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// Sort by score desc, then file path asc for stability
|
|
30
|
+
matches.sort((a, b) => b.score - a.score || a.file.localeCompare(b.file));
|
|
31
|
+
return matches.slice(0, max_results);
|
|
32
|
+
}
|
|
33
|
+
async function walkMarkdownFiles(dir) {
|
|
34
|
+
const out = [];
|
|
35
|
+
try {
|
|
36
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
37
|
+
for (const entry of entries) {
|
|
38
|
+
const full = join(dir, entry.name);
|
|
39
|
+
if (entry.isDirectory()) {
|
|
40
|
+
const nested = await walkMarkdownFiles(full);
|
|
41
|
+
out.push(...nested);
|
|
42
|
+
}
|
|
43
|
+
else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
44
|
+
out.push(full);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// directory not accessible — return empty
|
|
50
|
+
}
|
|
51
|
+
return out;
|
|
52
|
+
}
|
|
53
|
+
async function searchFile(filePath, projectRoot, terms, caseSensitive) {
|
|
54
|
+
let content;
|
|
55
|
+
try {
|
|
56
|
+
content = await readFile(filePath, "utf-8");
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
const lines = content.split("\n");
|
|
62
|
+
const haystackTerms = caseSensitive ? terms : terms.map(t => t.toLowerCase());
|
|
63
|
+
const matches = [];
|
|
64
|
+
const relFile = relative(projectRoot, filePath);
|
|
65
|
+
// Extract title and source from frontmatter (simple regex, no full parse)
|
|
66
|
+
let title;
|
|
67
|
+
let source;
|
|
68
|
+
for (let i = 0; i < Math.min(lines.length, 30); i++) {
|
|
69
|
+
const line = lines[i];
|
|
70
|
+
if (line.startsWith("title:"))
|
|
71
|
+
title = line.slice(6).trim().replace(/^["']|["']$/g, "");
|
|
72
|
+
if (line.startsWith("source:"))
|
|
73
|
+
source = line.slice(7).trim().replace(/^["']|["']$/g, "");
|
|
74
|
+
}
|
|
75
|
+
for (let i = 0; i < lines.length; i++) {
|
|
76
|
+
const line = lines[i];
|
|
77
|
+
const haystack = caseSensitive ? line : line.toLowerCase();
|
|
78
|
+
let matchCount = 0;
|
|
79
|
+
for (const term of haystackTerms) {
|
|
80
|
+
if (haystack.includes(term))
|
|
81
|
+
matchCount++;
|
|
82
|
+
}
|
|
83
|
+
if (matchCount > 0) {
|
|
84
|
+
// Snippet: trim line to ~200 chars, centered around first match if possible
|
|
85
|
+
const firstTerm = haystackTerms.find(t => haystack.includes(t));
|
|
86
|
+
let snippet = line;
|
|
87
|
+
if (line.length > 200 && firstTerm) {
|
|
88
|
+
const idx = haystack.indexOf(firstTerm);
|
|
89
|
+
const start = Math.max(0, idx - 80);
|
|
90
|
+
const end = Math.min(line.length, idx + firstTerm.length + 80);
|
|
91
|
+
snippet = (start > 0 ? "..." : "") + line.slice(start, end) + (end < line.length ? "..." : "");
|
|
92
|
+
}
|
|
93
|
+
matches.push({
|
|
94
|
+
file: relFile,
|
|
95
|
+
line_number: i + 1,
|
|
96
|
+
snippet: snippet.trim(),
|
|
97
|
+
score: matchCount,
|
|
98
|
+
title,
|
|
99
|
+
source,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return matches;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/knowledge/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/knowledge/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/knowledge/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read a file from anywhere in the project's raw/ or wiki/ tree.
|
|
3
|
+
* Path is relative to project root.
|
|
4
|
+
* Allowed prefixes: "raw/", "wiki/"
|
|
5
|
+
*/
|
|
6
|
+
export declare function readKnowledgeFile(projectId: string, path: string): Promise<string>;
|
|
7
|
+
/**
|
|
8
|
+
* Write a file to the project's wiki/ tree.
|
|
9
|
+
* Path is relative to project root, MUST start with "wiki/".
|
|
10
|
+
* Creates parent directories as needed.
|
|
11
|
+
* Raw files can NOT be written via this tool — they come only from tool auto-save.
|
|
12
|
+
*/
|
|
13
|
+
export declare function writeWikiFile(projectId: string, path: string, content: string): Promise<string>;
|
|
14
|
+
/**
|
|
15
|
+
* Check if a file exists in the project tree (raw/ or wiki/).
|
|
16
|
+
*/
|
|
17
|
+
export declare function knowledgeFileExists(projectId: string, path: string): Promise<boolean>;
|
|
18
|
+
//# sourceMappingURL=wikiStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wikiStore.d.ts","sourceRoot":"","sources":["../../src/knowledge/wikiStore.ts"],"names":[],"mappings":"AA0BA;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAaxF;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBrG;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAS3F"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { readFile, writeFile, mkdir, access } from "node:fs/promises";
|
|
2
|
+
import { dirname, join, normalize, relative, isAbsolute, sep } from "node:path";
|
|
3
|
+
import { getProjectRoot } from "./paths.js";
|
|
4
|
+
/**
|
|
5
|
+
* Validate that a requested path stays inside the allowed directory.
|
|
6
|
+
* Prevents path traversal (../../etc/passwd).
|
|
7
|
+
* Returns the resolved absolute path if safe, or throws.
|
|
8
|
+
*/
|
|
9
|
+
function validatePath(allowedRoot, requestedPath) {
|
|
10
|
+
if (isAbsolute(requestedPath)) {
|
|
11
|
+
throw new Error(`Path must be relative: ${requestedPath}`);
|
|
12
|
+
}
|
|
13
|
+
// Normalize removes ../ etc.
|
|
14
|
+
const normalized = normalize(requestedPath);
|
|
15
|
+
if (normalized.startsWith("..") || normalized.includes(`${sep}..`) || normalized.includes(`..${sep}`)) {
|
|
16
|
+
throw new Error(`Path traversal not allowed: ${requestedPath}`);
|
|
17
|
+
}
|
|
18
|
+
const resolved = join(allowedRoot, normalized);
|
|
19
|
+
const rel = relative(allowedRoot, resolved);
|
|
20
|
+
if (rel.startsWith("..") || isAbsolute(rel)) {
|
|
21
|
+
throw new Error(`Path escapes allowed root: ${requestedPath}`);
|
|
22
|
+
}
|
|
23
|
+
return resolved;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Read a file from anywhere in the project's raw/ or wiki/ tree.
|
|
27
|
+
* Path is relative to project root.
|
|
28
|
+
* Allowed prefixes: "raw/", "wiki/"
|
|
29
|
+
*/
|
|
30
|
+
export async function readKnowledgeFile(projectId, path) {
|
|
31
|
+
const projectRoot = getProjectRoot(projectId);
|
|
32
|
+
const fullPath = validatePath(projectRoot, path);
|
|
33
|
+
// Only allow reading from raw/ or wiki/ subtrees
|
|
34
|
+
const rel = relative(projectRoot, fullPath);
|
|
35
|
+
const inRaw = rel.startsWith("raw/") || rel.startsWith("raw" + sep);
|
|
36
|
+
const inWiki = rel.startsWith("wiki/") || rel.startsWith("wiki" + sep);
|
|
37
|
+
if (!inRaw && !inWiki) {
|
|
38
|
+
throw new Error(`Read only allowed in raw/ or wiki/ subtrees: ${path}`);
|
|
39
|
+
}
|
|
40
|
+
return readFile(fullPath, "utf-8");
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Write a file to the project's wiki/ tree.
|
|
44
|
+
* Path is relative to project root, MUST start with "wiki/".
|
|
45
|
+
* Creates parent directories as needed.
|
|
46
|
+
* Raw files can NOT be written via this tool — they come only from tool auto-save.
|
|
47
|
+
*/
|
|
48
|
+
export async function writeWikiFile(projectId, path, content) {
|
|
49
|
+
const projectRoot = getProjectRoot(projectId);
|
|
50
|
+
const fullPath = validatePath(projectRoot, path);
|
|
51
|
+
// Must be inside wiki/
|
|
52
|
+
const rel = relative(projectRoot, fullPath);
|
|
53
|
+
if (!rel.startsWith("wiki/") && !rel.startsWith("wiki" + sep)) {
|
|
54
|
+
throw new Error(`Writes only allowed in wiki/ subtree. Got: ${path}`);
|
|
55
|
+
}
|
|
56
|
+
if (!fullPath.endsWith(".md")) {
|
|
57
|
+
throw new Error(`Wiki files must have .md extension: ${path}`);
|
|
58
|
+
}
|
|
59
|
+
await mkdir(dirname(fullPath), { recursive: true });
|
|
60
|
+
await writeFile(fullPath, content, "utf-8");
|
|
61
|
+
return fullPath;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Check if a file exists in the project tree (raw/ or wiki/).
|
|
65
|
+
*/
|
|
66
|
+
export async function knowledgeFileExists(projectId, path) {
|
|
67
|
+
try {
|
|
68
|
+
const projectRoot = getProjectRoot(projectId);
|
|
69
|
+
const fullPath = validatePath(projectRoot, path);
|
|
70
|
+
await access(fullPath);
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=wikiStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wikiStore.js","sourceRoot":"","sources":["../../src/knowledge/wikiStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChF,OAAO,EAAc,cAAc,EAAE,MAAM,YAAY,CAAC;AAExD;;;;GAIG;AACH,SAAS,YAAY,CAAC,WAAmB,EAAE,aAAqB;IAC9D,IAAI,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,0BAA0B,aAAa,EAAE,CAAC,CAAC;IAC7D,CAAC;IACD,6BAA6B;IAC7B,MAAM,UAAU,GAAG,SAAS,CAAC,aAAa,CAAC,CAAC;IAC5C,IAAI,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG,GAAG,IAAI,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,GAAG,EAAE,CAAC,EAAE,CAAC;QACtG,MAAM,IAAI,KAAK,CAAC,+BAA+B,aAAa,EAAE,CAAC,CAAC;IAClE,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IAC/C,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC5C,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,8BAA8B,aAAa,EAAE,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,SAAiB,EAAE,IAAY;IACrE,MAAM,WAAW,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,YAAY,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAEjD,iDAAiD;IACjD,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC;IACpE,MAAM,MAAM,GAAG,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;IACvE,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,gDAAgD,IAAI,EAAE,CAAC,CAAC;IAC1E,CAAC;IAED,OAAO,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,SAAiB,EAAE,IAAY,EAAE,OAAe;IAClF,MAAM,WAAW,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,YAAY,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAEjD,uBAAuB;IACvB,MAAM,GAAG,GAAG,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC5C,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,GAAG,GAAG,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,KAAK,CAAC,8CAA8C,IAAI,EAAE,CAAC,CAAC;IACxE,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,uCAAuC,IAAI,EAAE,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC5C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,SAAiB,EAAE,IAAY;IACvE,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;QAC9C,MAAM,QAAQ,GAAG,YAAY,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QACjD,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface Frontmatter {
|
|
2
|
+
[key: string]: string | number | boolean | string[] | Date | Record<string, unknown> | null | undefined;
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Parse YAML frontmatter from a markdown string.
|
|
6
|
+
* Returns { frontmatter, body } where body is the content after the frontmatter.
|
|
7
|
+
* If no frontmatter present, returns { frontmatter: {}, body: content }.
|
|
8
|
+
*/
|
|
9
|
+
export declare function parseFrontmatter(content: string): {
|
|
10
|
+
frontmatter: Frontmatter;
|
|
11
|
+
body: string;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Serialize a Frontmatter object + body into a markdown string with YAML frontmatter.
|
|
15
|
+
*/
|
|
16
|
+
export declare function stringifyFrontmatter(frontmatter: Frontmatter, body: string): string;
|
|
17
|
+
//# sourceMappingURL=yaml.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yaml.d.ts","sourceRoot":"","sources":["../../src/knowledge/yaml.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,CAAC,GAAG,EAAE,MAAM,GACR,MAAM,GACN,MAAM,GACN,OAAO,GACP,MAAM,EAAE,GACR,IAAI,GACJ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACvB,IAAI,GACJ,SAAS,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG;IACjD,WAAW,EAAE,WAAW,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;CACd,CAqBA;AA6DD;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE,MAAM,GACX,MAAM,CAuBR"}
|