@inkeep/open-knowledge 0.5.0-beta.39 → 0.5.0-beta.40
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/dist/THIRD_PARTY_NOTICES.md +5 -0
- package/dist/assets/skills/open-knowledge/SKILL.md +11 -6
- package/dist/cli.mjs +4 -4
- package/dist/constants-CQfcgXd1.mjs +2 -0
- package/dist/{dist-mC3lFJl0.mjs → dist-DjC84IgZ.mjs} +18 -18
- package/dist/{dist-CQ1CW0Gw.mjs → dist-kgy3NArq.mjs} +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{init-CZQOVWec.mjs → init-BH7ZH8Ug.mjs} +4 -4
- package/dist/init-CBnvLBjl.mjs +1 -0
- package/dist/loader-B87qQn2P.mjs +1 -0
- package/dist/{loader-BthnLVYV.mjs → loader-C2EgX1O-.mjs} +2 -2
- package/dist/preview-CF4spOTa.mjs +1 -0
- package/dist/{preview-Dp1J-57V.mjs → preview-Ctrbhc4r.mjs} +2 -2
- package/dist/public/assets/ActivityModeContent-DXBpRrSl.js +2 -0
- package/dist/public/assets/{ActivityPanelDiffView-DwtPYJgT.js → ActivityPanelDiffView-d4ec9M69.js} +1 -1
- package/dist/public/assets/ConsentDialogBody-CSNo2n5l.js +2 -0
- package/dist/public/assets/DocumentContext-B0sQn39F.css +1 -0
- package/dist/public/assets/DocumentContext-RBKslC5w.js +52 -0
- package/dist/public/assets/{GraphPanel-FXxgmAV7.js → GraphPanel-CCV85m0N.js} +2 -2
- package/dist/public/assets/McpConsentDialogBody-Cp08S9eY.js +1 -0
- package/dist/public/assets/SettingsDialogBody-DsD6fHwY.js +11 -0
- package/dist/public/assets/SourceEditor-13iENPpI.js +2 -0
- package/dist/public/assets/{_baseFor-BQ6FmUXQ.js → _baseFor-B3FCzyNW.js} +1 -1
- package/dist/public/assets/{agent-presence-LoQiwUUV.js → agent-presence-8VSgL2U2.js} +1 -1
- package/dist/public/assets/{arc-BTYHqK6I.js → arc-GOD6SLHR.js} +1 -1
- package/dist/public/assets/architecture-YZFGNWBL-B2pJrg2X.js +1 -0
- package/dist/public/assets/{architectureDiagram-Q4EWVU46-CAw8ZTI6.js → architectureDiagram-Q4EWVU46-CIVh0TLx.js} +1 -1
- package/dist/public/assets/{blockDiagram-DXYQGD6D-D4mfoScz.js → blockDiagram-DXYQGD6D-Cg-UHasz.js} +1 -1
- package/dist/public/assets/{button-BigAOfY9.js → button-DBLnjjvQ.js} +1 -1
- package/dist/public/assets/{c4Diagram-AHTNJAMY-g4PJwhMw.js → c4Diagram-AHTNJAMY-KFeHAAOO.js} +1 -1
- package/dist/public/assets/channel-BqqURnVG.js +1 -0
- package/dist/public/assets/checkbox-kroC1jEP.js +1 -0
- package/dist/public/assets/{chunk-2KRD3SAO-C0VEmSSK.js → chunk-2KRD3SAO-ChBquZUZ.js} +1 -1
- package/dist/public/assets/{chunk-336JU56O-CWe4KlcJ.js → chunk-336JU56O-DHqaXNrn.js} +2 -2
- package/dist/public/assets/chunk-426QAEUC-CuPmuy8t.js +1 -0
- package/dist/public/assets/{chunk-4BX2VUAB-CqFQlA48.js → chunk-4BX2VUAB-Dagml-_v.js} +1 -1
- package/dist/public/assets/{chunk-4TB4RGXK-B9HnNhjS.js → chunk-4TB4RGXK-QLafKs7A.js} +1 -1
- package/dist/public/assets/chunk-55IACEB6-BRPDx2aU.js +1 -0
- package/dist/public/assets/{chunk-5FUZZQ4R-HtBbmyzC.js → chunk-5FUZZQ4R-DoG5zk7O.js} +1 -1
- package/dist/public/assets/{chunk-5PVQY5BW-BsQqu9Pz.js → chunk-5PVQY5BW--zDnbXdQ.js} +1 -1
- package/dist/public/assets/{chunk-67CJDMHE-DaOHFcoK.js → chunk-67CJDMHE-BDDJCVvR.js} +1 -1
- package/dist/public/assets/{chunk-7N4EOEYR-DxJSpCGX.js → chunk-7N4EOEYR-DcM-tXJf.js} +1 -1
- package/dist/public/assets/{chunk-AA7GKIK3-Ck4Wrqot.js → chunk-AA7GKIK3-CIk9DOam.js} +1 -1
- package/dist/public/assets/{chunk-BSJP7CBP-c353z_ln.js → chunk-BSJP7CBP-CC13npHT.js} +1 -1
- package/dist/public/assets/{chunk-CIAEETIT-fgTeYGb2.js → chunk-CIAEETIT-B7rpgB3I.js} +1 -1
- package/dist/public/assets/{chunk-EDXVE4YY-D_b3pVvT.js → chunk-EDXVE4YY-BfT15Ufb.js} +1 -1
- package/dist/public/assets/{chunk-ENJZ2VHE-DVMAmZ6-.js → chunk-ENJZ2VHE-DEtEhITq.js} +1 -1
- package/dist/public/assets/{chunk-FMBD7UC4-c2vVGInH.js → chunk-FMBD7UC4-DXl_nUYs.js} +1 -1
- package/dist/public/assets/{chunk-FOC6F5B3-CH9dNZl0.js → chunk-FOC6F5B3-wEKzMqND.js} +1 -1
- package/dist/public/assets/{chunk-ICPOFSXX-D9mDZSHP.js → chunk-ICPOFSXX-C8AElYY_.js} +1 -1
- package/dist/public/assets/{chunk-K5T4RW27-DPAjYSpe.js → chunk-K5T4RW27-DcJgbIMU.js} +1 -1
- package/dist/public/assets/{chunk-KGLVRYIC-BKUgXOPp.js → chunk-KGLVRYIC-kNC4I9ls.js} +1 -1
- package/dist/public/assets/{chunk-LIHQZDEY-CWn5kZJ_.js → chunk-LIHQZDEY-B0zYcYPV.js} +1 -1
- package/dist/public/assets/{chunk-ORNJ4GCN-BETATk1q.js → chunk-ORNJ4GCN-S_3Y_0FS.js} +1 -1
- package/dist/public/assets/{chunk-OYMX7WX6-B2DjYZXs.js → chunk-OYMX7WX6-CX3nrwxJ.js} +1 -1
- package/dist/public/assets/chunk-QZHKN3VN-CTZ4su3-.js +1 -0
- package/dist/public/assets/{chunk-U2HBQHQK-bod_LD7f.js → chunk-U2HBQHQK-CfAyyLJz.js} +1 -1
- package/dist/public/assets/{chunk-X2U36JSP-fL9reWIe.js → chunk-X2U36JSP-CmACymAN.js} +1 -1
- package/dist/public/assets/{chunk-XPW4576I-BQtjckSw.js → chunk-XPW4576I-D1s3NdKZ.js} +1 -1
- package/dist/public/assets/{chunk-YZCP3GAM-D-UepLeD.js → chunk-YZCP3GAM-CiWxV9XS.js} +1 -1
- package/dist/public/assets/{chunk-ZZ45TVLE-Z9LUwvvb.js → chunk-ZZ45TVLE-B7t5_MqN.js} +1 -1
- package/dist/public/assets/classDiagram-6PBFFD2Q-DrN_pUa5.js +1 -0
- package/dist/public/assets/classDiagram-v2-HSJHXN6E-C1MJ1Ukt.js +1 -0
- package/dist/public/assets/clone-CecJCxEU.js +1 -0
- package/dist/public/assets/collapsible-L2bca9Ur.js +1 -0
- package/dist/public/assets/config-validation-events-C8srGpAi.js +10 -0
- package/dist/public/assets/{cose-bilkent-S5V4N54A-D7YGD8wq.js → cose-bilkent-S5V4N54A-BjJ-OKPr.js} +1 -1
- package/dist/public/assets/{dagre-BZr05USh.js → dagre-BuFRtOcC.js} +1 -1
- package/dist/public/assets/{dagre-KV5264BT-uIcBsxoB.js → dagre-KV5264BT-BpBW6R71.js} +1 -1
- package/dist/public/assets/{diagram-5BDNPKRD-CRnuX3SM.js → diagram-5BDNPKRD-B5phtkJp.js} +1 -1
- package/dist/public/assets/{diagram-G4DWMVQ6-CwcP8j6L.js → diagram-G4DWMVQ6-tjReW6yx.js} +1 -1
- package/dist/public/assets/{diagram-MMDJMWI5-7Eyc42Ou.js → diagram-MMDJMWI5-b4CgKryF.js} +1 -1
- package/dist/public/assets/{diagram-TYMM5635-Bwhd6MAt.js → diagram-TYMM5635-D5B0g2lj.js} +1 -1
- package/dist/public/assets/dialog-DSzqKgdW.js +45 -0
- package/dist/public/assets/{dist-CyhQWHfo.js → dist-By89CQBy.js} +1 -1
- package/dist/public/assets/{dist-BTf6on8c.js → dist-D-oqC0-R.js} +1 -1
- package/dist/public/assets/{dist-CHvMoypJ.js → dist-DQ1oWohr.js} +1 -1
- package/dist/public/assets/{dist-DDFRxG7H.js → dist-DXgyWuz5.js} +1 -1
- package/dist/public/assets/{dist-Duryk2cE.js → dist-DllAuqQQ.js} +1 -1
- package/dist/public/assets/{dist-BOZuiab_.js → dist-DpEGxZ9h.js} +1 -1
- package/dist/public/assets/doc-hash-iXNxzaUU.js +423 -0
- package/dist/public/assets/{erDiagram-SMLLAGMA-DlCYmXsw.js → erDiagram-SMLLAGMA-CRJz10Jv.js} +1 -1
- package/dist/public/assets/{flatten-ptFIxnDZ.js → flatten-BWAerz3O.js} +1 -1
- package/dist/public/assets/{flowDiagram-DWJPFMVM-BaUE7X8U.js → flowDiagram-DWJPFMVM-BDCJTgJ7.js} +1 -1
- package/dist/public/assets/{ganttDiagram-T4ZO3ILL-Q1QCHTKl.js → ganttDiagram-T4ZO3ILL-cPQKlGYc.js} +1 -1
- package/dist/public/assets/gitGraph-7Q5UKJZL-BMann5g7.js +1 -0
- package/dist/public/assets/{gitGraphDiagram-UUTBAWPF-CG07jTjK.js → gitGraphDiagram-UUTBAWPF-BMyjc352.js} +1 -1
- package/dist/public/assets/{graphlib-B9f9FmLr.js → graphlib-BU8FnRz1.js} +1 -1
- package/dist/public/assets/index-BQdYAvoY.js +1918 -0
- package/dist/public/assets/index-CkiIkxux.css +1 -0
- package/dist/public/assets/info-OMHHGYJF-CKMkwFH6.js +1 -0
- package/dist/public/assets/{infoDiagram-42DDH7IO-DNa5xg8m.js → infoDiagram-42DDH7IO-BZ6v5y-j.js} +1 -1
- package/dist/public/assets/{isEmpty-Dff4GQVw.js → isEmpty-Cairwk5V.js} +1 -1
- package/dist/public/assets/isSymbol-BKUBGC2u.js +1 -0
- package/dist/public/assets/{ishikawaDiagram-UXIWVN3A-CCIU9fS9.js → ishikawaDiagram-UXIWVN3A-DA7_P2Up.js} +1 -1
- package/dist/public/assets/{journeyDiagram-VCZTEJTY-BAQyhz-O.js → journeyDiagram-VCZTEJTY-CzZoB161.js} +1 -1
- package/dist/public/assets/{kanban-definition-6JOO6SKY-B7n3dFDX.js → kanban-definition-6JOO6SKY-DKg7pXv1.js} +1 -1
- package/dist/public/assets/{label-Cv_LZFf-.js → label-CdSs0Skc.js} +1 -1
- package/dist/public/assets/{line-CVYKAp-t.js → line-DGc-MCyQ.js} +1 -1
- package/dist/public/assets/{linear-B5hCL-s4.js → linear-D6wzOaQP.js} +1 -1
- package/dist/public/assets/mcp-consent-store-BPw6Zd40.js +1 -0
- package/dist/public/assets/{mermaid-parser.core-DfyX5Z2V.js → mermaid-parser.core-Bm2u0Ges.js} +2 -2
- package/dist/public/assets/{mermaid.core--fhVTWBk.js → mermaid.core-DRx0wZe0.js} +3 -3
- package/dist/public/assets/{mindmap-definition-QFDTVHPH-BLm_6XTS.js → mindmap-definition-QFDTVHPH-C9GRZxO6.js} +1 -1
- package/dist/public/assets/{now-y3Cm704C.js → now-BN_Nj6nz.js} +1 -1
- package/dist/public/assets/{ordinal-CdtiT3iH.js → ordinal-Dk6d5Y-0.js} +1 -1
- package/dist/public/assets/packet-4T2RLAQJ-DXn_0fd3.js +1 -0
- package/dist/public/assets/{panel-CG6xouXb.js → panel-Co559KoC.js} +1 -1
- package/dist/public/assets/pie-ZZUOXDRM-BdZBZPW9.js +1 -0
- package/dist/public/assets/{pieDiagram-DEJITSTG-BvfCwbBk.js → pieDiagram-DEJITSTG-L6I3ft9Z.js} +1 -1
- package/dist/public/assets/{quadrantDiagram-34T5L4WZ-DUtci3Wz.js → quadrantDiagram-34T5L4WZ-Dp2IeEPC.js} +1 -1
- package/dist/public/assets/radar-PYXPWWZC-yUE2OrUV.js +1 -0
- package/dist/public/assets/{reduce-C8tvPXVb.js → reduce-CSWSFqzz.js} +1 -1
- package/dist/public/assets/{requirementDiagram-MS252O5E-DzkgPeTh.js → requirementDiagram-MS252O5E-BxNWyIZg.js} +1 -1
- package/dist/public/assets/{sankeyDiagram-XADWPNL6-BIuEcRVf.js → sankeyDiagram-XADWPNL6-CRn0_xkw.js} +1 -1
- package/dist/public/assets/{sequenceDiagram-FGHM5R23-XhnGy5pc.js → sequenceDiagram-FGHM5R23-Drkjb1j4.js} +1 -1
- package/dist/public/assets/{src-BqeO7p9A.js → src-DZeiyxTL.js} +1 -1
- package/dist/public/assets/{stateDiagram-FHFEXIEX-lEHzf3FW.js → stateDiagram-FHFEXIEX-BBUFKS0u.js} +1 -1
- package/dist/public/assets/stateDiagram-v2-QKLJ7IA2-BtYsWsIg.js +1 -0
- package/dist/public/assets/{target-navigation-intent-BKGZJzfb.js → target-navigation-intent-BZViEm6M.js} +1 -1
- package/dist/public/assets/{telemetry-impl-DQsr_8J4.js → telemetry-impl-DPRMO_b_.js} +2 -2
- package/dist/public/assets/{textarea-DECT2x7b.js → textarea-5ach84qM.js} +1 -1
- package/dist/public/assets/{timeline-definition-GMOUNBTQ-_uHiIDjf.js → timeline-definition-GMOUNBTQ-CLoe9y-z.js} +1 -1
- package/dist/public/assets/{toggle-group-CqR8P1U0.js → toggle-group-9ORKJ4oQ.js} +1 -1
- package/dist/public/assets/treeView-SZITEDCU-BjJ_gnFc.js +1 -0
- package/dist/public/assets/treemap-W4RFUUIX-DiV984fD.js +1 -0
- package/dist/public/assets/{typing-burst-detector-CXhMEzNx.js → typing-burst-detector-K-CfNoXw.js} +2 -2
- package/dist/public/assets/{vennDiagram-DHZGUBPP-BwneE_Sg.js → vennDiagram-DHZGUBPP-q2zdiy4F.js} +1 -1
- package/dist/public/assets/wardley-RL74JXVD-DbPCtCHV.js +1 -0
- package/dist/public/assets/{wardleyDiagram-NUSXRM2D-D1AodqH_.js → wardleyDiagram-NUSXRM2D-Njg6YHso.js} +1 -1
- package/dist/public/assets/{xychartDiagram-5P7HB3ND-9zuC0eMC.js → xychartDiagram-5P7HB3ND-Ct8Wgp45.js} +1 -1
- package/dist/public/index.html +25 -25
- package/dist/{repair-launch-json-BVtL3kCy.mjs → repair-launch-json-DKsMVH1M.mjs} +2 -2
- package/dist/{repair-mcp-configs-pWK5SBr3.mjs → repair-mcp-configs-BQ5B5SEm.mjs} +2 -2
- package/dist/{src-alwyUgEc.mjs → src-p510n6xV.mjs} +2 -2
- package/dist/{start-B_qddCkX.mjs → start--BCdrceO.mjs} +2 -2
- package/dist/start-CbVIel-D.mjs +1 -0
- package/package.json +1 -1
- package/dist/constants-n--3RKP-.mjs +0 -2
- package/dist/init-4KorX6rI.mjs +0 -1
- package/dist/loader-DlqrUrHi.mjs +0 -1
- package/dist/preview-BCWt39BR.mjs +0 -1
- package/dist/public/assets/ActivityModeContent-BqT9RtWA.js +0 -2
- package/dist/public/assets/ConsentDialogBody-Cxq7nXrG.js +0 -2
- package/dist/public/assets/DocumentContext-Cg2pKBP4.js +0 -52
- package/dist/public/assets/McpConsentDialogBody-_DJeXfdC.js +0 -1
- package/dist/public/assets/SettingsDialog-B-j9NFNZ.js +0 -11
- package/dist/public/assets/SourceEditor-CbzSX0iG.js +0 -2
- package/dist/public/assets/architecture-YZFGNWBL-haHjZ-W1.js +0 -1
- package/dist/public/assets/channel-CDgNg08A.js +0 -1
- package/dist/public/assets/chunk-426QAEUC-C43TcIY5.js +0 -1
- package/dist/public/assets/chunk-55IACEB6-mJDPihNE.js +0 -1
- package/dist/public/assets/chunk-QZHKN3VN-B5CMAE_s.js +0 -1
- package/dist/public/assets/classDiagram-6PBFFD2Q-B7OZyD7f.js +0 -1
- package/dist/public/assets/classDiagram-v2-HSJHXN6E-ByLnm7iZ.js +0 -1
- package/dist/public/assets/clone-DomZ2GAK.js +0 -1
- package/dist/public/assets/config-validation-events-BxoHnc7Y.js +0 -10
- package/dist/public/assets/dialog-B6Yo4QtX.js +0 -45
- package/dist/public/assets/dist-DbPwRkgP.js +0 -1
- package/dist/public/assets/dist-Qx1N2jU5.js +0 -1
- package/dist/public/assets/doc-hash-Ca3pPQw7.js +0 -423
- package/dist/public/assets/gitGraph-7Q5UKJZL-EPtzLtdn.js +0 -1
- package/dist/public/assets/index-CTDxIAjs.js +0 -1918
- package/dist/public/assets/index-Dgr6gLuG.css +0 -1
- package/dist/public/assets/info-OMHHGYJF-DhGHQOTJ.js +0 -1
- package/dist/public/assets/input-jeOsxRL6.js +0 -1
- package/dist/public/assets/isSymbol-DIRIUNhN.js +0 -1
- package/dist/public/assets/mcp-consent-store-BlzZxan6.js +0 -1
- package/dist/public/assets/packet-4T2RLAQJ-dOkbaGJi.js +0 -1
- package/dist/public/assets/pie-ZZUOXDRM-7mxWmZMD.js +0 -1
- package/dist/public/assets/radar-PYXPWWZC-CYrvwt0c.js +0 -1
- package/dist/public/assets/stateDiagram-v2-QKLJ7IA2-BsIimsLv.js +0 -1
- package/dist/public/assets/treeView-SZITEDCU-bf7fN5vg.js +0 -1
- package/dist/public/assets/treemap-W4RFUUIX-DeijdxYt.js +0 -1
- package/dist/public/assets/wardley-RL74JXVD-XbGOizT8.js +0 -1
- package/dist/start-CLPQ8L1O.mjs +0 -1
- /package/dist/public/assets/{__vite-browser-external-CCyf2WTU.js → __vite-browser-external-Bet_nOzq.js} +0 -0
- /package/dist/public/assets/{array-B4rubdDx.js → array-DfeqBzds.js} +0 -0
- /package/dist/public/assets/{colors-DTkp5rhC.js → colors-CuFmRbNJ.js} +0 -0
- /package/dist/public/assets/{cytoscape.esm-lL68JtBB.js → cytoscape.esm-C3hcpWGW.js} +0 -0
- /package/dist/public/assets/{defaultLocale-VDKImYxX.js → defaultLocale-CmG7Nywc.js} +0 -0
- /package/dist/public/assets/{dist-8vOhMUNR.js → dist-D3YXABda.js} +0 -0
- /package/dist/public/assets/{dist-Df8SLnPf.js → dist-GFox5lpz.js} +0 -0
- /package/dist/public/assets/{go-D1ad2i41.js → go-BjDSeE19.js} +0 -0
- /package/dist/public/assets/{init-B4uw1rya.js → init-D-V7N9g_.js} +0 -0
- /package/dist/public/assets/{isObjectLike-DkPsJ8ZC.js → isObjectLike-HLvQwJYx.js} +0 -0
- /package/dist/public/assets/{min-DTUJKQNu.js → min-CHzARyU6.js} +0 -0
- /package/dist/public/assets/{path-flVp2dgl.js → path-Bf8MP5yP.js} +0 -0
- /package/dist/public/assets/{pdf-zy6UKR6F.js → pdf-wFLJduM2.js} +0 -0
- /package/dist/public/assets/{pdf.worker-CETvIAHl.js → pdf.worker-CP44mBOj.js} +0 -0
- /package/dist/public/assets/{project-paths-CsGHlmFh.js → project-paths-DKT5BePl.js} +0 -0
- /package/dist/public/assets/{rough.esm-pmFy2cex.js → rough.esm-Di0388iR.js} +0 -0
- /package/dist/public/assets/{shell-FUK9YCOo.js → shell-184Lov7C.js} +0 -0
- /package/dist/public/assets/{src-CdWhPaRj.js → src-Dz70a8sm.js} +0 -0
- /package/dist/public/assets/{stex-BUy0wSq4.js → stex-ChE_gMQ6.js} +0 -0
|
@@ -324,7 +324,7 @@ $2`).split(`
|
|
|
324
324
|
`)].join(`
|
|
325
325
|
`);case`REMOVED_KEY`:{let t=e.path.join(`.`),S=[`${e.source?`Removed key at ${e.source.file}:${e.source.line}:${e.source.column}`:`Removed key in configuration`}: ${t}`,e.redirect];if(e.source?.snippet&&e.source.snippet.length>0)for(let t of e.source.snippet.split(`
|
|
326
326
|
`))S.push(` ${t}`);return S.join(`
|
|
327
|
-
`)}case`WRITE_ERROR`:return`Failed to write config file: ${e.detail}`;case`OKIGNORE_INVALID`:return e.lineNumber===void 0?`.okignore: ${e.detail}`:`.okignore line ${e.lineNumber}: ${e.detail}`;case`UNKNOWN`:return e.message??`Unknown error.`}}const SYSTEM_DOC_NAME=`__system__`,CC1_CONTRACT_VERSION=1,CONFIG_DOC_NAME_PROJECT=`__config__/project`,CONFIG_DOC_NAME_USER=`__user__/config.yml`,CONFIG_DOC_NAME_PROJECT_LOCAL=`__local__/project`,CONFIG_DOC_NAME_OKIGNORE=`__config__/okignore`,CONFIG_DOC_NAMES=Object.freeze([CONFIG_DOC_NAME_PROJECT,CONFIG_DOC_NAME_PROJECT_LOCAL,CONFIG_DOC_NAME_USER,CONFIG_DOC_NAME_OKIGNORE]),ALL_EDITOR_IDS=[`claude`,`claude-desktop`,`cursor`,`codex`],EDITOR_LABELS={claude:`Claude`,"claude-desktop":`Claude Desktop`,cursor:`Cursor`,codex:`Codex`},DEFAULT_GITHUB_OAUTH_CLIENT_ID=`Ov23liqlSd0V1MwR6rhI`,ORPHAN_MODES=[`incoming`,`outgoing`,`both`];function isOrphanMode(e){return ORPHAN_MODES.includes(e)}const DEFAULT_SERVER_HOST=`localhost`,ALLOWED_IMAGE_MIME_TYPES=[`image/jpeg`,`image/png`,`image/gif`,`image/webp`,`image/svg+xml`],ALLOWED_VIDEO_MIME_TYPES=[`video/mp4`,`video/webm`,`video/ogg`],ALLOWED_AUDIO_MIME_TYPES=[`audio/mpeg`,`audio/wav`,`audio/ogg`],ALLOWED_PDF_MIME_TYPES=[`application/pdf`],IMAGE_EXTENSIONS=new Set([`png`,`jpg`,`jpeg`,`gif`,`webp`,`avif`,`svg`]),VIDEO_EXTENSIONS=new Set([`mp4`,`webm`,`mov`,`m4v`,`mkv`]),PDF_EXTENSIONS=new Set([`pdf`]),AUDIO_EXTENSIONS=new Set([`mp3`,`wav`,`ogg`,`m4a`,`flac`,`aac`,`opus`]),FILE_ATTACHMENT_EXTENSIONS=new Set(`pdf.docx.xlsx.pptx.doc.xls.ppt.zip.7z.tar.gz.rar.csv.tsv.rtf.json.yaml.yml.xml.txt.pages.numbers.key.odt.ods.odp.epub.mobi`.split(`.`)),EXECUTABLE_BLOCKLIST_EXTENSIONS=new Set(`exe.bat.cmd.ps1.com.msi.vbs.js.jse.wsf.wsh.hta.sh.command.csh.ksh.bash.zsh.fish.desktop.action.workflow.html.htm.svg.xml.mhtml.svgz.dmg.pkg.mpkg.scpt.applescript.terminal.prefpane.webloc.inetloc.fileloc.jar.appimage.deb.rpm.msix.appx.ipa.apk.pif.scr.lnk.url`.split(`.`)),ASSET_EXTENSIONS=new Set(`png.jpg.jpeg.gif.webp.avif.svg.apng.heic.heif.tiff.bmp.ico.pdf.mp4.webm.mov.m4v.mkv.avi.flv.wmv.mpeg.mpg.mp3.wav.ogg.m4a.flac.aac.opus.zip.woff.woff2.ttf.otf.eot.docx.xlsx.pptx.csv.txt.rtf.json`.split(`.`)),INLINE_RENDERABLE_EXTENSIONS=new Set(`png.jpg.jpeg.gif.webp.avif.apng.heic.heif.tiff.bmp.ico.svg.pdf.mp4.webm.mov.m4v.mkv.mp3.wav.ogg.m4a.flac.aac.opus`.split(`.`)),DEFAULT_DEDUP_MODE=`same-dir`,WIKI_EMBED_EXTENSIONS=new Set(`png.jpg.jpeg.gif.webp.avif.svg.pdf.mp4.webm.mov.m4v.mkv.mp3.wav.ogg.m4a.flac.aac.opus.docx.xlsx.pptx.doc.xls.ppt.zip.7z.tar.gz.rar.csv.tsv.rtf.json.yaml.yml.xml.txt.pages.numbers.key.odt.ods.odp.epub.mobi`.split(`.`)),SIDEBAR_IMAGE_EXTENSIONS=[`png`,`jpg`,`jpeg`,`gif`,`webp`,`avif`],SIDEBAR_VIDEO_EXTENSIONS=[`mp4`,`webm`,`mov`,`m4v`],SIDEBAR_AUDIO_EXTENSIONS=[`mp3`,`wav`,`ogg`,`m4a`,`flac`,`aac`,`opus`],SIDEBAR_PDF_EXTENSIONS=[`pdf`];function assertSubset(e,t,S){for(let w of t)if(!S.has(w))throw Error(`${e}: ${w} is not present in canonical upload constants`)}assertSubset(`SIDEBAR_IMAGE_ASSET_EXTENSIONS`,SIDEBAR_IMAGE_EXTENSIONS,IMAGE_EXTENSIONS),assertSubset(`SIDEBAR_VIDEO_ASSET_EXTENSIONS`,SIDEBAR_VIDEO_EXTENSIONS,VIDEO_EXTENSIONS),assertSubset(`SIDEBAR_AUDIO_ASSET_EXTENSIONS`,SIDEBAR_AUDIO_EXTENSIONS,AUDIO_EXTENSIONS),assertSubset(`SIDEBAR_PDF_ASSET_EXTENSIONS`,SIDEBAR_PDF_EXTENSIONS,PDF_EXTENSIONS),assertSubset(`FILE_ATTACHMENT_EXTENSIONS`,[...FILE_ATTACHMENT_EXTENSIONS],WIKI_EMBED_EXTENSIONS);const SIDEBAR_IMAGE_ASSET_EXTENSIONS=new Set(SIDEBAR_IMAGE_EXTENSIONS),SIDEBAR_VIDEO_ASSET_EXTENSIONS=new Set(SIDEBAR_VIDEO_EXTENSIONS),SIDEBAR_AUDIO_ASSET_EXTENSIONS=new Set(SIDEBAR_AUDIO_EXTENSIONS),SIDEBAR_PDF_ASSET_EXTENSIONS=new Set(SIDEBAR_PDF_EXTENSIONS),SIDEBAR_RENDERABLE_ASSET_EXTENSIONS=new Set([...SIDEBAR_IMAGE_EXTENSIONS,...SIDEBAR_VIDEO_EXTENSIONS,...SIDEBAR_AUDIO_EXTENSIONS,...SIDEBAR_PDF_EXTENSIONS]);assertSubset(`SIDEBAR_RENDERABLE_ASSET_EXTENSIONS`,[...SIDEBAR_RENDERABLE_ASSET_EXTENSIONS],INLINE_RENDERABLE_EXTENSIONS);function mediaKindForSidebarAssetExtension(e){let t=e.toLowerCase().replace(/^\./,``);return SIDEBAR_IMAGE_ASSET_EXTENSIONS.has(t)?`image`:SIDEBAR_VIDEO_ASSET_EXTENSIONS.has(t)?`video`:SIDEBAR_AUDIO_ASSET_EXTENSIONS.has(t)?`audio`:SIDEBAR_PDF_ASSET_EXTENSIONS.has(t)?`pdf`:null}const CodeBlockFidelity=index_default$11.extend({priority:60,addAttributes(){return{...this.parent?.(),fenceDelimiter:{default:"`"},fenceLength:{default:3},meta:{default:null},sourceStyle:{default:`fenced`}}}}),EmphasisFidelity=index_default$9.extend({name:`emphasis`,priority:60,addAttributes(){return{...this.parent?.(),sourceDelimiter:{default:`*`}}},addInputRules(){return[markInputRule({find:starInputRegex,type:this.type,getAttributes:{sourceDelimiter:`*`}}),markInputRule({find:underscoreInputRegex,type:this.type,getAttributes:{sourceDelimiter:`_`}})]}}),StrongFidelity=index_default$10.extend({name:`strong`,priority:60,addAttributes(){return{...this.parent?.(),sourceDelimiter:{default:`**`}}},addInputRules(){return[markInputRule({find:starInputRegex$1,type:this.type,getAttributes:{sourceDelimiter:`**`}}),markInputRule({find:underscoreInputRegex$1,type:this.type,getAttributes:{sourceDelimiter:`__`}})]}}),EscapeMark=Mark.create({name:`escapeMark`,priority:10,excludes:``,inclusive:!1,parseHTML(){return[{tag:`span[data-escape-mark]`}]},renderHTML(){return[`span`,{"data-escape-mark":``},0]}}),HardBreakFidelity=index_default$8.extend({priority:60,addAttributes(){return{...this.parent?.(),hardBreakStyle:{default:`backslash`}}}}),HeadingFidelity=index_default$7.extend({priority:60,addAttributes(){return{...this.parent?.(),headingStyle:{default:`atx`},sourceTrailingHashes:{default:null},sourceUnderlineLength:{default:null},sourceContiguousNext:{default:!1}}}}),HtmlBlockFidelity=Node3.create({name:`htmlBlock`,group:`block`,atom:!0,priority:60,addAttributes(){return{content:{default:``}}},parseHTML(){return[{tag:`div[data-html-block]`}]},renderHTML({node:e}){return[`div`,{"data-html-block":``,class:`html-block`},e.attrs.content]}}),JsxComponent=Node3.create({name:`jsxComponent`,group:`block`,atom:!1,content:`block*`,isolating:!0,selectable:!0,defining:!0,priority:60,addAttributes(){return{componentName:{default:``},kind:{default:`element`},attributes:{default:[]},sourceRaw:{default:``},sourceDirty:{default:!1},props:{default:{}}}},parseHTML(){return[{tag:`div[data-jsx-component]`,getAttrs:e=>typeof e==`string`?!1:{componentName:e.getAttribute(`data-component-name`)||``,sourceRaw:e.getAttribute(`data-source-raw`)||``}}]},renderHTML({HTMLAttributes:e}){return[`div`,{"data-jsx-component":``,"data-component-name":e.componentName,"data-source-raw":e.sourceRaw},0]},addCommands(){return{insertJsxComponent:e=>({commands:t})=>t.insertContent({type:this.name,attrs:{sourceRaw:e}})}}}),JsxInline=Node3.create({name:`jsxInline`,group:`inline`,inline:!0,atom:!1,content:`text*`,isolating:!1,selectable:!0,priority:60,addAttributes(){return{}},parseHTML(){return[{tag:`span[data-jsx-inline]`}]},renderHTML(){return[`span`,{"data-jsx-inline":``},0]}}),SAFE_URL_SCHEMES=[`https`,`http`,`mailto`,`tel`,`ftp`,`sms`],SCHEME_ALT=SAFE_URL_SCHEMES.map(e=>`${e}:`).join(`|`),SAFE_URL_SCHEME_RE=RegExp(`^(?:${SCHEME_ALT}|\\/|#|\\?|\\.\\/|\\.\\.\\/)`,`i`);function isRelativeUrl(e){let t=e.trim();if(t===``)return!0;let S=t.indexOf(`:`);if(S===-1)return!0;let w=t.indexOf(`/`),E=t.indexOf(`?`),D=t.indexOf(`#`);return S>Math.min(w===-1?1/0:w,E===-1?1/0:E,D===-1?1/0:D)}const ALLOWED_LINK_SCHEMES=new Set(SAFE_URL_SCHEMES.map(e=>`${e}:`)),PLACEHOLDER_BASE=`https://placeholder.invalid`;function isAllowedLinkUri(e){try{let t=new URL(e,PLACEHOLDER_BASE);return ALLOWED_LINK_SCHEMES.has(t.protocol.toLowerCase())}catch{return!1}}const LinkFidelity=index_default$6.extend({priority:60,addOptions(){return{openOnClick:!1,enableClickSelection:!1,linkOnPaste:!0,autolink:!0,protocols:[],defaultProtocol:`http`,HTMLAttributes:{target:`_blank`,rel:`noopener noreferrer`},isAllowedUri:isAllowedLinkUri,validate:isAllowedLinkUri,shouldAutoLink:()=>!0}},addAttributes(){return{...this.parent?.(),linkStyle:{default:`inline`,rendered:!1},refLabel:{default:null,rendered:!1},sourceForm:{default:null,rendered:!1},target:{default:null,rendered:!1},anchor:{default:null,rendered:!1},alias:{default:null,rendered:!1},sourceUrlForm:{default:null,rendered:!1},sourceTitleMarker:{default:null,rendered:!1}}}}),LinkRefDefFidelity=Node3.create({name:`linkRefDef`,group:`block`,atom:!0,priority:60,addAttributes(){return{label:{default:``},href:{default:``},title:{default:null},sourceLayout:{default:null},sourceTitleMarker:{default:null}}},parseHTML(){return[{tag:`div[data-link-ref-def]`}]},renderHTML({node:e}){let{label:t,href:S,title:w}=e.attrs,E=w?`[${t}]: ${S} "${w}"`:`[${t}]: ${S}`;return[`div`,{"data-link-ref-def":``,class:`link-ref-def`},E]}});function isBulletList(e){return e.type.name===`list`&&!e.attrs.ordered}function isOrderedList(e){return e.type.name===`list`&&!!e.attrs.ordered}function hasTaskItems(e){let t=!1;return e.forEach(e=>{e.type.name===`listItem`&&e.attrs.checked!==null&&(t=!0)}),t}function toggleListKind(e,t,S,w,E,D,O){let k=findParentNode(e=>e.type.name===`list`)(e.selection);if(k&&E(k.node)){let{$from:S,$to:E}=e.selection;return S.blockRange(E)?liftListItem$1(w)(e,t):!1}if(k){if(!t)return!0;let{tr:S}=e;return S.setNodeMarkup(k.pos,void 0,{...k.node.attrs,...D}),O!==void 0&&k.node.forEach((e,t)=>{if(e.type.name===`listItem`){let w=k.pos+1+t;S.setNodeMarkup(w,void 0,{...e.attrs,...O})}}),t(S),!0}return wrapInList$1(S,D)(e,void 0)?t?wrapInList$1(S,D)(e,S=>{if(O){let t=S.mapping.map(e.selection.$from.pos),w=S.doc.resolve(t);for(let e=w.depth;e>0;e--){let t=w.node(e);if(t.type.name===`listItem`){S.setNodeMarkup(w.before(e),void 0,{...t.attrs,...O});break}}}t(S)}):!0:!1}const ListNode=Node3.create({name:`list`,group:`block list`,content:`listItem+`,priority:60,addAttributes(){return{ordered:{default:!1},start:{default:1},spread:{default:!1},bulletMarker:{default:null},listMarkerDelimiter:{default:null}}},parseHTML(){return[{tag:`ul`,getAttrs:()=>({ordered:!1})},{tag:`ol`,getAttrs:e=>({ordered:!0,start:e.getAttribute(`start`)?Number(e.getAttribute(`start`)):1})}]},renderHTML({node:e,HTMLAttributes:t}){let S=e.attrs.ordered?`ol`:`ul`,w={};return e.attrs.ordered&&e.attrs.start!==1&&(w.start=e.attrs.start),[S,mergeAttributes(t,w),0]},addCommands(){return{toggleBulletList:()=>({state:e,dispatch:t})=>{let S=e.schema.nodes.list,w=e.schema.nodes.listItem;return!S||!w?!1:toggleListKind(e,t,S,w,e=>isBulletList(e)&&!hasTaskItems(e),{ordered:!1},{checked:null})},toggleOrderedList:()=>({state:e,dispatch:t})=>{let S=e.schema.nodes.list,w=e.schema.nodes.listItem;return!S||!w?!1:toggleListKind(e,t,S,w,e=>isOrderedList(e),{ordered:!0},{checked:null})},toggleTaskList:()=>({state:e,dispatch:t})=>{let S=e.schema.nodes.list,w=e.schema.nodes.listItem;return!S||!w?!1:toggleListKind(e,t,S,w,e=>isBulletList(e)&&hasTaskItems(e),{ordered:!1},{checked:!1})}}},addInputRules(){return[wrappingInputRule({find:/^\s*([-+*])(?!\s*\[[ xX]\])\s$/,type:this.type,getAttributes:e=>({ordered:!1,bulletMarker:e[1]})}),wrappingInputRule({find:/^\s*(\d+)([.)])\s$/,type:this.type,getAttributes:e=>({ordered:!0,start:Number(e[1]),listMarkerDelimiter:e[2]})}),new InputRule({find:/^\s*[-*+]\s\[([ xX])\]\s$/,handler:({state:e,range:t,match:S})=>{let w=e.schema.nodes.list;if(!w)return null;let E=S[1]!==` `,D=e.tr.delete(t.from,t.to),O=D.doc.resolve(t.from).blockRange();if(!O)return null;let k=findWrapping(O,w,{ordered:!1});if(!k)return null;D.wrap(O,k);let j=D.doc.resolve(D.mapping.map(t.from));for(let e=j.depth;e>0;e--){let t=j.node(e);if(t.type.name===`listItem`){D.setNodeMarkup(j.before(e),void 0,{...t.attrs,checked:E});break}}}})]},addKeyboardShortcuts(){return{"Mod-Shift-8":()=>this.editor.commands.toggleBulletList(),"Mod-Shift-7":()=>this.editor.commands.toggleOrderedList(),"Mod-Shift-9":()=>this.editor.commands.toggleTaskList()}}}),ListItemNode=Node3.create({name:`listItem`,content:`paragraph block*`,defining:!0,addAttributes(){return{checked:{default:null},spread:{default:!1}}},parseHTML(){return[{tag:`li`,getAttrs:e=>{let t=e.querySelector(`input[type="checkbox"]`);return{checked:t?t.checked:null}}}]},renderHTML({node:e,HTMLAttributes:t}){return e.attrs.checked===null?[`li`,mergeAttributes(t),0]:[`li`,mergeAttributes(t,{"data-type":`taskItem`,"data-checked":e.attrs.checked?`true`:`false`}),[`label`,{contenteditable:`false`},[`input`,{type:`checkbox`,...e.attrs.checked?{checked:`checked`}:{}}]],[`div`,0]]},addNodeView(){return({node:e,getPos:t,editor:S,HTMLAttributes:w})=>{let E=document.createElement(`li`);Object.entries(mergeAttributes(w,e.attrs.checked===null?{}:{"data-type":`taskItem`,"data-checked":String(!!e.attrs.checked)})).forEach(([e,t])=>{t!=null&&E.setAttribute(e,String(t))});let D=null,O=null,k=document.createElement(`div`);return e.attrs.checked!==null&&(D=document.createElement(`label`),D.contentEditable=`false`,O=document.createElement(`input`),O.type=`checkbox`,O.checked=!!e.attrs.checked,S.isEditable||(O.disabled=!0),O.addEventListener(`change`,()=>{let w=t();w===void 0||typeof w!=`number`||S.view.dispatch(S.view.state.tr.setNodeMarkup(w,void 0,{...e.attrs,checked:O?.checked??!1}))}),D.appendChild(O),E.appendChild(D)),E.appendChild(k),{dom:E,contentDOM:k,update(t){return t.type!==e.type||t.attrs.checked!==null!=(e.attrs.checked!==null)?!1:(O&&t.attrs.checked!==null&&(O.checked=!!t.attrs.checked,E.setAttribute(`data-checked`,String(!!t.attrs.checked))),e=t,!0)}}}},addKeyboardShortcuts(){return{Enter:()=>this.editor.commands.splitListItem(this.name),Tab:()=>{let{$from:e}=this.editor.state.selection;for(let t=e.depth;t>0;t--)if(e.node(t).type.name===`listItem`)return this.editor.commands.sinkListItem(this.name);return!1},"Shift-Tab":()=>{let{$from:e}=this.editor.state.selection;for(let t=e.depth;t>0;t--)if(e.node(t).type.name===`listItem`)return this.editor.commands.liftListItem(this.name);return!1}}}}),List=ListNode,ListItem=ListItemNode,MathInline=Node3.create({name:`mathInline`,group:`inline`,inline:!0,atom:!0,selectable:!0,priority:60,addAttributes(){return{formula:{default:``},id:{default:null},language:{default:`latex`}}},parseHTML(){return[{tag:`span[data-math-inline]`,getAttrs:e=>typeof e==`string`?!1:{formula:e.getAttribute(`data-formula`)||``,id:e.getAttribute(`id`)||null,language:e.getAttribute(`data-language`)||`latex`}}]},renderHTML({HTMLAttributes:e}){return[`span`,{"data-math-inline":``,"data-formula":e.formula,"data-language":e.language,...e.id?{id:e.id}:{}}]},addCommands(){return{insertMathInline:e=>({commands:t})=>t.insertContent({type:this.name,attrs:{formula:e}})}}}),RawMdxFallback=Node3.create({name:`rawMdxFallback`,group:`block`,atom:!1,content:`text*`,isolating:!0,selectable:!0,defining:!0,priority:60,addAttributes(){return{reason:{default:``},originalSpan:{default:{start:0,end:0}}}},parseHTML(){let e=e=>typeof e==`string`?!1:{reason:e.getAttribute(`data-reason`)||``};return[{tag:`div[data-raw-mdx-fallback]`,getAttrs:e},{tag:`pre[data-raw-mdx-fallback]`,getAttrs:e}]},renderHTML({HTMLAttributes:e}){return[`div`,{"data-raw-mdx-fallback":``,"data-raw-badge":`raw`,"data-reason":e.reason,contenteditable:`false`,class:`raw-mdx-fallback`},0]},addNodeView(){return({HTMLAttributes:e})=>{let t=document.createElement(`div`);t.setAttribute(`data-raw-mdx-fallback`,``),t.setAttribute(`data-raw-badge`,`raw`),t.setAttribute(`contenteditable`,`false`),t.classList.add(`raw-mdx-fallback`),e.reason&&t.setAttribute(`data-reason`,e.reason);let S=document.createElement(`pre`);return S.classList.add(`raw-mdx-fallback-content`),S.setAttribute(`contenteditable`,`false`),t.appendChild(S),{dom:t,contentDOM:S,ignoreMutation:()=>!0}}}}),BlockquoteFidelity=index_default$4.extend({priority:60,addAttributes(){return{...this.parent?.(),sourceMarkerSpacings:{default:null}}}}),CodeMarkFidelity=index_default$3.extend({excludes:``,addAttributes(){return{...this.parent?.(),sourceFenceChar:{default:"`"},sourceFenceLength:{default:1}}}}),CommentBlock=Node3.create({name:`commentBlock`,group:`block`,content:`block+`,defining:!0,priority:60,addAttributes(){return{sourceForm:{default:`percent`,parseHTML:e=>e.getAttribute(`data-source-form`)===`html`?`html`:`percent`,renderHTML:e=>e.sourceForm===`html`?{"data-source-form":`html`}:{}},sourceLayout:{default:`block`,parseHTML:e=>e.getAttribute(`data-source-layout`)===`inline`?`inline`:`block`,renderHTML:e=>e.sourceLayout===`inline`?{"data-source-layout":`inline`}:{}}}},parseHTML(){return[{tag:`aside[data-comment-block]`},{tag:`aside.comment-block`}]},renderHTML({HTMLAttributes:e}){return[`aside`,{"data-comment-block":``,"data-clipboard-omit":`true`,class:`comment-block`,style:`display: none;`,...e},0]},addCommands(){return{setCommentBlock:()=>({commands:e})=>e.wrapIn(this.name),toggleCommentBlock:()=>({commands:e})=>e.toggleWrap(this.name),unsetCommentBlock:()=>({commands:e})=>e.lift(this.name)}}}),CommentMark=Mark.create({name:`comment`,priority:10,excludes:``,inclusive:!1,addAttributes(){return{sourceForm:{default:`percent`,parseHTML:e=>e.getAttribute(`data-source-form`)===`html`?`html`:`percent`,renderHTML:e=>e.sourceForm===`html`?{"data-source-form":`html`}:{}}}},parseHTML(){return[{tag:`span[data-comment-mark]`}]},renderHTML({HTMLAttributes:e}){return[`span`,{"data-comment-mark":``,"data-clipboard-omit":`true`,class:`comment-mark`,style:`display: none;`,...e},0]},addCommands(){return{setComment:()=>({commands:e})=>e.setMark(this.name),toggleComment:()=>({commands:e})=>e.toggleMark(this.name),unsetComment:()=>({commands:e})=>e.unsetMark(this.name)}}}),FootnoteDefinition=Node3.create({name:`footnoteDefinition`,group:`block`,content:`block+`,defining:!0,priority:60,addAttributes(){return{identifier:{default:``},label:{default:null}}},parseHTML(){let e=e=>{if(typeof e==`string`)return!1;let t=e.getAttribute(`data-footnote-id`)||``;return{identifier:t,label:t||null}};return[{tag:`aside[data-footnote-def]`,getAttrs:e},{tag:`aside.footnote-def`,getAttrs:e}]},renderHTML({node:e,HTMLAttributes:t}){let S=String(e.attrs.identifier??``);return[`aside`,{...t,"data-footnote-def":``,"data-footnote-id":S,id:`fn-${S}`,class:`footnote-def`},[`div`,{class:`footnote-body`},0],[`a`,{href:`#fnref-${S}`,class:`footnote-backref`,contentEditable:`false`,"aria-label":`Back to reference`},`↩`]]},addCommands(){return{insertFootnoteDefinition:e=>({commands:t})=>t.insertContent({type:this.name,attrs:{identifier:e,label:e},content:[{type:`paragraph`}]})}}}),FootnoteReference=Node3.create({name:`footnoteReference`,group:`inline`,inline:!0,atom:!0,selectable:!0,draggable:!1,priority:60,addAttributes(){return{identifier:{default:``},label:{default:null}}},parseHTML(){return[{tag:`sup[data-footnote-ref]`,getAttrs:e=>{if(typeof e==`string`)return!1;let t=e.getAttribute(`data-footnote-id`)||``;return{identifier:t,label:t||null}}}]},renderHTML({node:e}){let t=String(e.attrs.identifier??``);return[`sup`,{id:`fnref-${t}`,"data-footnote-ref":``,"data-footnote-id":t,class:`footnote-ref`},[`a`,{href:`#fn-${t}`,class:`footnote-ref-link`},`[${t}]`]]},addCommands(){return{insertFootnoteReference:e=>({commands:t})=>t.insertContent({type:this.name,attrs:{identifier:e,label:e}})}}}),ImageReferenceFidelity=Node3.create({name:`imageReference`,group:`inline`,inline:!0,atom:!0,priority:60,addAttributes(){return{alt:{default:``},label:{default:``},identifier:{default:``},referenceType:{default:`shortcut`}}},parseHTML(){return[{tag:`img[data-image-reference]`}]},renderHTML({node:e}){let{alt:t,label:S,referenceType:w}=e.attrs,E=t||S;return[`img`,{"data-image-reference":``,"data-reference-type":w,"data-label":S,alt:E}]}});function toDesktopAssetHref(e){if(typeof e!=`string`||!e.startsWith(`/`))return e;let t=globalThis.window?.okDesktop?.config?.apiOrigin;return typeof t==`string`&&t?t+e:e}const ImageSrcFidelity=index_default.extend({priority:60,addAttributes(){return{...this.parent?.(),sourceUrl:{default:null,rendered:!1}}},renderHTML({HTMLAttributes:e}){let t=mergeAttributes(this.options.HTMLAttributes,e);return typeof t.src==`string`&&(t.src=toDesktopAssetHref(t.src)),[`img`,t]}}),SourceLiteralMark=Mark.create({name:`sourceLiteral`,priority:10,excludes:``,inclusive:!1,addAttributes(){return{sourceRaw:{default:``}}},parseHTML(){return[{tag:`span[data-source-literal]`}]},renderHTML({HTMLAttributes:e}){return[`span`,{"data-source-literal":``,...e},0]}});function isValidSourceLiteralRaw(e,t){if(typeof e!=`string`||typeof t!=`string`||/[\x00-\x1F\x7F]/.test(e))return!1;let S=e.replaceAll(`\xA0`,` `),w=t.replaceAll(`\xA0`,` `);return S===w?!0:stripMarkdownBackslashEscapes(S)===w}function stripMarkdownBackslashEscapes(e){return e.replace(/\\([!-/:-@[-`{-~])/g,`$1`)}const TableFidelity=Table.extend({priority:60,addAttributes(){return{...this.parent?.(),sourceDashCounts:{default:null}}}}),TableCellFidelity=TableCell.extend({priority:60,addAttributes(){return{...this.parent?.(),sourcePadding:{default:null}}}}),TableHeaderFidelity=TableHeader.extend({priority:60,addAttributes(){return{...this.parent?.(),sourcePadding:{default:null}}}}),Tag=Node3.create({name:`tag`,group:`inline`,inline:!0,atom:!0,selectable:!0,priority:60,addAttributes(){return{value:{default:``}}},parseHTML(){return[{tag:`a[data-tag]`,getAttrs:e=>typeof e==`string`?!1:{value:e.getAttribute(`data-tag`)||``}}]},renderHTML({node:e,HTMLAttributes:t}){let S=String(e.attrs.value??``);return[`a`,{...t,"data-tag":S,href:`#tag/${S}`,class:`tag`},`#${S}`]},addCommands(){return{insertTag:e=>({chain:t})=>t().insertContent({type:`tag`,attrs:{value:e}}).run()}}}),THEMATIC_BREAK_INPUT_RE=/^(?:---|—-|___\s|\*\*\*\s)$/;function thematicBreakSourceRawFromMatch(e){let t=String(e[0]??``).replace(/\s+$/,``);return t===`—-`?`---`:t}const ThematicBreakFidelity=index_default$2.extend({name:`thematicBreak`,priority:60,addAttributes(){return{...this.parent?.(),sourceRaw:{default:`---`}}},addInputRules(){return[nodeInputRule({find:THEMATIC_BREAK_INPUT_RE,type:this.type,getAttributes:e=>({sourceRaw:thematicBreakSourceRawFromMatch(e)})})]}});function normalizeNullableString(e){if(typeof e!=`string`)return null;let t=e.trim();return t.length>0?t:null}function getWikiLinkText(e){return e.alias?e.alias:e.anchor?`${e.target}#${e.anchor}`:e.target}const WikiLink=Node3.create({name:`wikiLink`,group:`inline`,inline:!0,atom:!0,priority:60,addAttributes(){return{target:{default:``},alias:{default:null},anchor:{default:null},resolved:{default:!1}}},parseHTML(){return[{tag:`span[data-wiki-link]`,getAttrs:e=>typeof e==`string`?!1:{target:e.getAttribute(`data-target`)||``,alias:normalizeNullableString(e.getAttribute(`data-alias`)),anchor:normalizeNullableString(e.getAttribute(`data-anchor`)),resolved:e.getAttribute(`data-resolved`)===`true`}},{tag:`a.wiki-link[data-target]`,priority:100,getAttrs:e=>{if(typeof e==`string`)return!1;let t=e.getAttribute(`data-target`)??``;return t?{target:t,alias:normalizeNullableString(e.getAttribute(`data-alias`)),anchor:normalizeNullableString(e.getAttribute(`data-anchor`)),resolved:!1}:!1}}]},renderHTML({node:e,HTMLAttributes:t}){let S=String(e.attrs.target??``),w=normalizeNullableString(e.attrs.alias),E=normalizeNullableString(e.attrs.anchor),D=e.attrs.resolved===!0;return[`span`,{...t,"data-wiki-link":``,"data-target":S,"data-alias":w??``,"data-anchor":E??``,"data-resolved":D?`true`:`false`},getWikiLinkText({target:S,alias:w,anchor:E})]}});function extensionOf(e){let t=e.split(`/`).pop()??e,S=t.lastIndexOf(`.`);return S<=0||S===t.length-1?``:t.slice(S+1).toLowerCase()}function labelFor(e){return e.alias?e.alias:e.anchor?`${e.target}#${e.anchor}`:e.target}const WikiLinkEmbed=Node3.create({name:`wikiLinkEmbed`,group:`inline`,inline:!0,atom:!0,priority:60,addAttributes(){return{target:{default:``},alias:{default:null},anchor:{default:null},resolvedSrc:{default:null,rendered:!1,parseHTML:()=>null}}},parseHTML(){let e=e=>typeof e==`string`||!e.hasAttribute(`data-wiki-embed`)?!1:{target:e.getAttribute(`data-target`)||``,alias:normalizeNullableString(e.getAttribute(`data-alias`)),anchor:normalizeNullableString(e.getAttribute(`data-anchor`))};return[{tag:`img[data-wiki-embed]`,getAttrs:e,priority:100},{tag:`a[data-wiki-embed]`,getAttrs:e,priority:100}]},renderHTML({node:e,HTMLAttributes:t}){let S=String(e.attrs.target??``),w=normalizeNullableString(e.attrs.alias),E=normalizeNullableString(e.attrs.anchor),D=normalizeNullableString(e.attrs.resolvedSrc),O=extensionOf(S);if(IMAGE_EXTENSIONS.has(O))return[`img`,{...t,"data-wiki-embed":``,"data-target":S,"data-alias":w??``,"data-anchor":E??``,src:D??S,alt:w??S}];let k=D??S;return[`a`,{...t,"data-wiki-embed":``,"data-target":S,"data-alias":w??``,"data-anchor":E??``,href:E?`${k}#${E}`:k,target:`_blank`,rel:`noopener noreferrer`},labelFor({target:S,alias:w,anchor:E})]}}),sharedExtensions=[JsxComponent,RawMdxFallback,JsxInline,MathInline,WikiLink,WikiLinkEmbed,Tag,List,ListItem,EmphasisFidelity,StrongFidelity,CodeMarkFidelity,CodeBlockFidelity,BlockquoteFidelity,HeadingFidelity,ThematicBreakFidelity,LinkFidelity,HtmlBlockFidelity,LinkRefDefFidelity,HardBreakFidelity,EscapeMark,SourceLiteralMark,index_default$1.configure({undoRedo:!1,bulletList:!1,orderedList:!1,listItem:!1,italic:!1,bold:!1,code:!1,codeBlock:!1,heading:!1,horizontalRule:!1,hardBreak:!1,link:!1,blockquote:!1,dropcursor:{color:`color-mix(in oklch, var(--primary) 50%, transparent)`,width:2}}),TableFidelity.configure({resizable:!0}),TableRow,TableHeaderFidelity,TableCellFidelity,ImageSrcFidelity.configure({inline:!0}),ImageReferenceFidelity,index_default$5,CommentMark,CommentBlock,FootnoteReference,FootnoteDefinition],FRONTMATTER_TAG_VALUE_RE=/^[a-zA-Z][\w/-]*$/;function stripLeadingHash(e){return e.startsWith(`#`)?e.slice(1):e}function coerceCandidates(e){return typeof e==`string`?[e]:Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}function extractFrontmatterTags(e){if(!e||e.trim()===``)return[];let{map:t}=parseFrontmatterYaml(e);if(!t)return[];let S=coerceCandidates(t.tags),w=[];for(let e of S){let t=stripLeadingHash(e);FRONTMATTER_TAG_VALUE_RE.test(t)?w.push(t):console.warn(`[frontmatter-tags] dropping invalid tag entry: ${JSON.stringify(e)}`)}return w}const safeDocNameField=string$2().refine(e=>!e.includes(`..`)&&!e.startsWith(`/`)&&!e.includes(`\0`)&&!e.includes(`\\`),{message:`docName contains unsafe path characters`}).optional(),agentIdentityFields={agentId:string$2().optional(),agentName:string$2().optional(),colorSeed:string$2().optional(),clientName:string$2().optional(),clientVersion:string$2().optional(),label:string$2().optional()},summaryField=string$2().optional(),URN_UUID_RE=/^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,ServerInfoSuccessSchema=object$1({serverInstanceId:string$2().min(1),currentBranch:string$2().min(1).optional(),currentDiskAckSVs:record(string$2().min(1),string$2().min(1)).optional()}).loose(),PrincipalSuccessSchema=object$1({id:string$2().min(1),display_name:string$2().min(1),display_email:string$2(),source:_enum([`git-config`,`synthesized`]),created_at:string$2().min(1)}).loose(),ProblemTypeSchema=_enum(`urn:ok:error:malformed-upload.urn:ok:error:collision-exhaustion.urn:ok:error:storage-full.urn:ok:error:storage-readonly.urn:ok:error:storage-error.urn:ok:error:no-file-received.urn:ok:error:path-escape.urn:ok:error:method-not-allowed.urn:ok:error:invalid-request.urn:ok:error:payload-too-large.urn:ok:error:request-timeout.urn:ok:error:internal-server-error.urn:ok:error:loopback-required.urn:ok:error:invalid-origin.urn:ok:error:url-not-allowed.urn:ok:error:dir-outside-home.urn:ok:error:concurrent-operation.urn:ok:error:clone-failed.urn:ok:error:clone-timeout.urn:ok:error:server-start-failed.urn:ok:error:reserved-doc-name.urn:ok:error:target-not-found.urn:ok:error:stale-target.urn:ok:error:frontmatter-edit-not-supported.urn:ok:error:invalid-frontmatter-patch.urn:ok:error:no-active-session.urn:ok:error:too-many-agent-sessions.urn:ok:error:doc-not-found.urn:ok:error:doc-already-exists.urn:ok:error:doc-not-open.urn:ok:error:rollback-not-configured.urn:ok:error:doc-not-available.urn:ok:error:backlink-index-not-configured.urn:ok:error:file-rescan-not-configured.urn:ok:error:shadow-not-configured.urn:ok:error:host-not-allowed.urn:ok:error:principal-not-available.urn:ok:error:not-found.urn:ok:error:auth-failed.urn:ok:error:no-project-dir.urn:ok:error:server-open-failed.urn:ok:error:sync-not-active.urn:ok:error:project-repo-not-configured.urn:ok:error:seed-prerequisite-missing.urn:ok:error:seed-invalid-root.urn:ok:error:tag-index-not-configured.urn:ok:error:template-not-found.urn:ok:error:unsupported-asset-type.urn:ok:error:asset-not-found.urn:ok:error:collab-server-not-running.urn:ok:error:gateway-timeout.urn:ok:error:cursor-not-installed.urn:ok:error:cursor-spawn-timeout.urn:ok:error:cursor-spawn-failed.urn:ok:error:handoff-target-not-installed.urn:ok:error:handoff-spawn-timeout.urn:ok:error:handoff-spawn-failed`.split(`.`));function assertNeverProblemType(e){throw Error(`Unexpected ProblemType variant: ${JSON.stringify(e)}`)}const ProblemDetailsSchema=object$1({type:ProblemTypeSchema,title:string$2().min(1),status:number$1().int().min(400).max(599),instance:string$2().regex(URN_UUID_RE,`instance must be urn:uuid:<uuid>`).optional(),detail:string$2().optional()}).loose(),UploadRequestSchema=object$1({parentDocName:string$2().min(1),agentId:string$2().min(1).optional(),agentName:string$2().min(1).optional()}).loose(),UploadAssetSuccessSchema=object$1({src:string$2().min(1),path:string$2().min(1).optional(),deduped:boolean$1().optional()}).loose(),LocalOpCloneRequestSchema=object$1({url:string$2().min(1),dir:string$2().min(1)}).loose(),StreamingProblemEventSchema=object$1({type:literal(`error`),problem:ProblemDetailsSchema}).loose();function reconstructAttrs(e,t){let S=Array.isArray(e.attrs.attributes)?e.attrs.attributes.filter(e=>typeof e==`object`&&!!e&&`type`in e):[],w=e.attrs.props??{},E=new Map,D=new Set;if(t)for(let e of t)e.omitOnDefault===!0&&`defaultValue`in e&&e.defaultValue!==void 0&&E.set(e.name,e.defaultValue),e.type===`string`&&e.required===!1&&e.defaultValue===void 0&&D.add(e.name);for(let[e,t]of Object.entries(w)){let w=S.findIndex(t=>t.type===`mdxJsxAttribute`&&t.name===e);if(E.has(e)&&Object.is(E.get(e),t)){w>=0&&S.splice(w,1);continue}if(D.has(e)&&t===``){w>=0&&S.splice(w,1);continue}let O=propToMdxJsxAttribute(e,t);w>=0?S[w]=O:S.push(O)}return S}function propToMdxJsxAttribute(e,t){if(t===!0)return{type:`mdxJsxAttribute`,name:e,value:null};if(t===!1)return{type:`mdxJsxAttribute`,name:e,value:{type:`mdxJsxAttributeValueExpression`,value:`false`}};if(t==null)return{type:`mdxJsxAttribute`,name:e,value:null};if(typeof t==`string`)return{type:`mdxJsxAttribute`,name:e,value:t};if(typeof t==`number`)return{type:`mdxJsxAttribute`,name:e,value:{type:`mdxJsxAttributeValueExpression`,value:JSON.stringify(t)}};if(typeof t==`object`){let S;try{S=JSON.stringify(t)}catch{S=String(t)}return{type:`mdxJsxAttribute`,name:e,value:{type:`mdxJsxAttributeValueExpression`,value:S}}}return{type:`mdxJsxAttribute`,name:e,value:String(t)}}function emitMdxJsx(e,t,S,w){return{type:`mdxJsxFlowElement`,name:e,attributes:reconstructAttrs(t,w),children:S.all(t),data:{}}}const calloutProps=[{name:`type`,type:`enum`,enumValues:[`note`,`tip`,`important`,`warning`,`caution`,`abstract`,`info`,`todo`,`success`,`question`,`failure`,`danger`,`bug`,`example`,`quote`],defaultValue:`note`,required:!1,description:`Callout variant`},{name:`title`,type:`string`,required:!1,description:`Optional heading shown above the body`},{name:`icon`,type:`string`,required:!1,advanced:!0,description:"Custom lucide icon override (e.g. `lucide:Lightbulb`)"},{name:`color`,type:`string`,required:!1,advanced:!0,description:"Optional accent color override (hex — e.g. `#F05032`)"},{name:`collapsible`,type:`boolean`,required:!1,defaultValue:!1,advanced:!0,description:"Render as a foldable `<details>` (Obsidian `[!TYPE]+/-`)"},{name:`defaultOpen`,type:`boolean`,required:!1,defaultValue:!0,advanced:!0,description:`When collapsible, start in the open state`},{name:`children`,type:`reactnode`,required:!0,description:`Callout content`}],htmlImgProps=[{name:`src`,type:`string`,required:!0,defaultValue:``,description:`Image source URL`,accept:ALLOWED_IMAGE_MIME_TYPES,autoFocus:!0},{name:`alt`,type:`string`,required:!0,description:`Alt text`},{name:`width`,type:`number`,required:!1,advanced:!0,description:`Image width`},{name:`height`,type:`number`,required:!1,advanced:!0,description:`Image height`},{name:`srcset`,type:`string`,required:!1,advanced:!0,description:`Responsive image candidate set (e.g. "x.png 1x, y.png 2x")`},{name:`sizes`,type:`string`,required:!1,advanced:!0,description:`Responsive image sizes hint paired with srcset`},{name:`loading`,type:`enum`,enumValues:[`eager`,`lazy`],defaultValue:`lazy`,required:!1,advanced:!0,omitOnDefault:!0,description:`Native img loading strategy (defaults to lazy)`},{name:`title`,type:`string`,required:!1,advanced:!0,description:`Native HTML title attribute (tooltip)`},{name:`decoding`,type:`enum`,enumValues:[`sync`,`async`,`auto`],defaultValue:`auto`,required:!1,advanced:!0,omitOnDefault:!0,description:`Hint for how the browser should decode the image`},{name:`fetchpriority`,type:`enum`,enumValues:[`high`,`low`,`auto`],defaultValue:`auto`,required:!1,advanced:!0,omitOnDefault:!0,description:`Resource fetch priority hint`},{name:`crossorigin`,type:`enum`,enumValues:[`anonymous`,`use-credentials`],required:!1,advanced:!0,description:`CORS mode for the image fetch`},{name:`referrerpolicy`,type:`string`,required:!1,advanced:!0,description:`Referrer policy for the image fetch (HTML referrerpolicy values)`},{name:`align`,type:`enum`,enumValues:[`center`,`left`,`right`],defaultValue:`center`,required:!1,omitOnDefault:!0,description:`Alignment within the column`}],embedProps=[{name:`src`,type:`string`,required:!0,defaultValue:``,description:`Embedded page URL (must start with http:// or https://)`,autoFocus:!0},{name:`title`,type:`string`,required:!1,description:`Iframe title (accessible label for screen readers)`},{name:`width`,type:`string`,required:!1,advanced:!0,description:`Embed width as a CSS length (e.g. "100%", "640px")`},{name:`height`,type:`string`,required:!1,advanced:!0,description:`Embed height as a CSS length (e.g. "26rem", "480px")`},{name:`align`,type:`enum`,enumValues:[`center`,`left`,`right`],defaultValue:`center`,required:!1,omitOnDefault:!0,description:`Alignment within the column`}],htmlVideoProps=[{name:`src`,type:`string`,required:!0,defaultValue:``,description:`Video source URL`,accept:ALLOWED_VIDEO_MIME_TYPES,autoFocus:!0},{name:`controls`,type:`boolean`,required:!1,defaultValue:!0,advanced:!0,omitOnDefault:!0,description:`Show native HTML5 video controls (defaults to true)`},{name:`autoplay`,type:`boolean`,required:!1,advanced:!0,description:`Begin playback as soon as possible (usually requires muted)`},{name:`poster`,type:`string`,required:!1,advanced:!0,description:`Poster image URL shown before playback`,accept:ALLOWED_IMAGE_MIME_TYPES},{name:`width`,type:`number`,required:!1,advanced:!0,description:`Video width`},{name:`height`,type:`number`,required:!1,advanced:!0,description:`Video height`},{name:`title`,type:`string`,required:!1,advanced:!0,description:`Native HTML title attribute (tooltip)`},{name:`muted`,type:`boolean`,required:!1,advanced:!0,description:`Mute audio on load`},{name:`loop`,type:`boolean`,required:!1,advanced:!0,description:`Restart from the beginning when playback ends`},{name:`playsinline`,type:`boolean`,required:!1,advanced:!0,description:`Play inline on iOS rather than entering fullscreen`},{name:`preload`,type:`enum`,enumValues:[`none`,`metadata`,`auto`],required:!1,advanced:!0,description:`Hint for how much of the video to preload`}],htmlAudioProps=[{name:`src`,type:`string`,required:!0,defaultValue:``,description:`Audio source URL`,accept:ALLOWED_AUDIO_MIME_TYPES,autoFocus:!0},{name:`controls`,type:`boolean`,required:!1,defaultValue:!0,advanced:!0,omitOnDefault:!0,description:`Show native HTML5 audio controls (defaults to true)`},{name:`autoplay`,type:`boolean`,required:!1,advanced:!0,description:`Begin playback as soon as possible (usually requires muted)`},{name:`title`,type:`string`,required:!1,advanced:!0,description:`Native HTML title attribute (tooltip)`},{name:`muted`,type:`boolean`,required:!1,advanced:!0,description:`Mute audio on load`},{name:`loop`,type:`boolean`,required:!1,advanced:!0,description:`Restart from the beginning when playback ends`},{name:`preload`,type:`enum`,enumValues:[`none`,`metadata`,`auto`],required:!1,advanced:!0,description:`Hint for how much of the audio to preload`}],accordionProps=[{name:`title`,type:`string`,required:!0,description:`Accordion heading shown inside the <summary>`},{name:`defaultOpen`,type:`boolean`,required:!1,defaultValue:!1,description:`When true, the accordion renders expanded on initial load`},{name:`icon`,type:`string`,required:!1,advanced:!0,description:"Custom lucide icon override (e.g. `lucide:Rocket`)"},{name:`description`,type:`string`,required:!1,advanced:!0,description:`Optional subtitle rendered below the title inside <summary>`},{name:`id`,type:`string`,required:!1,advanced:!0,description:"HTML id attribute for deep-linking (e.g. `#advanced-options`)"},{name:`name`,type:`string`,required:!1,advanced:!0,description:`HTML5 <details name=> group — siblings with the same name are mutually exclusive`}],gfmCalloutProps=[calloutProps[0],calloutProps[1],calloutProps[4],calloutProps[5],calloutProps[6]],commonMarkImageProps=[htmlImgProps[0],htmlImgProps[1],htmlImgProps[7]],htmlDetailsAccordionProps=[accordionProps[0],accordionProps[1],accordionProps[4],accordionProps[5]],wikiEmbedImageProps=[{name:`alias`,type:`string`,required:!1,defaultValue:``,description:"Alt text (Obsidian alias syntax: `![[file.png|alt text]]`)"}],wikiEmbedVideoProps=[{name:`alias`,type:`string`,required:!1,defaultValue:``,description:"Title text (Obsidian alias syntax: `![[clip.mp4|title]]`)"}],wikiEmbedAudioProps=[{name:`alias`,type:`string`,required:!1,defaultValue:``,description:"Title text (Obsidian alias syntax: `![[song.mp3|title]]`)"}],tabsProps=[{name:`id`,type:`string`,required:!1,advanced:!0,description:"HTML id attribute for deep-linking (e.g. `#install-tabs`)"}],tabProps=[{name:`label`,type:`string`,required:!0,autoFocus:!0,defaultValue:`Tab`,description:`Tab strip label — shown in the clickable pill at the top`},{name:`id`,type:`string`,required:!1,advanced:!0,description:"HTML id attribute for deep-linking (e.g. `#tab-npm`)"}],mathProps=[{name:`formula`,type:`string`,required:!0,autoFocus:!0,language:`latex`,description:`LaTeX math source (rendered with KaTeX in the browser)`},{name:`id`,type:`string`,required:!1,advanced:!0,description:"HTML id attribute for deep-linking (e.g. `#eq-pythagoras`)"},{name:`language`,type:`string`,required:!1,advanced:!0,description:"Forward-compat hint for the math source language (default `latex`). Reserved for future MathJax / Typst / AsciiMath substrates."}],dollarMathProps=[mathProps[0]],mathFenceProps=[mathProps[0]],mermaidProps=[{name:`chart`,type:`string`,required:!0,autoFocus:!0,language:`mermaid`,description:`Mermaid chart source (graph / flowchart / sequenceDiagram / class / state / etc.)`}],wikiEmbedFileProps=[{name:`alias`,type:`string`,required:!1,defaultValue:``,description:"Display name override (Obsidian alias syntax: `![[file.zip|label]]`)"}],fileProps=[{name:`src`,type:`string`,required:!0,defaultValue:``,description:`File URL`,accept:[`*/*`],autoFocus:!0}],pdfProps=[{name:`src`,type:`string`,required:!0,defaultValue:``,description:`PDF source URL`,accept:ALLOWED_PDF_MIME_TYPES,autoFocus:!0},{name:`title`,type:`string`,required:!1,advanced:!0,description:`Accessible label for the embedded PDF viewer`},{name:`anchor`,type:`string`,required:!1,advanced:!0,description:"PDF viewer parameters as a single URL-fragment string (e.g. `page=3&height=600`)"}],mirrorProps=[{name:`src`,type:`string`,required:!0,description:"Path of the source doc, extension-less (e.g. `api-spec`).",autoFocus:!0},{name:`anchor`,type:`string`,required:!0,description:"Id of the `<MirrorSource>` block within the source doc."}],mirrorSourceProps=[{name:`id`,type:`string`,required:!0,description:"Stable id agents and authors use to reference this block from `<Mirror>` elsewhere.",autoFocus:!0},{name:`children`,type:`reactnode`,required:!0,description:`Block content this MirrorSource owns — paragraphs, callouts, code, nested JSX, anything.`}];function escapeHtmlAttr(e){return e.replace(/&/g,`&`).replace(/"/g,`"`).replace(/</g,`<`).replace(/>/g,`>`)}function escapeHtmlText(e){return e.replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`)}function serializeWikiEmbed(e){let t=e.attrs.props,S=t?.target??``,w=typeof t?.alias==`string`&&t.alias.length>0?t.alias:null,E=typeof t?.anchor==`string`&&t.anchor.length>0?t.anchor:null,D=w??(E?`${S}#${E}`:S);return{type:`wikiLinkEmbed`,value:D,data:{target:S,anchor:E,alias:w},children:[{type:`text`,value:D}]}}const builtInComponents=[{name:`Callout`,surface:`canonical`,hasChildren:!0,props:calloutProps,icon:`MessageSquareWarning`,category:`content`,displayName:`Callout`,description:`Alert / admonition with 15 type variants — 5 GFM (note, tip, important, warning, caution) plus 10 Obsidian-parity (abstract, info, todo, success, question, failure, danger, bug, example, quote)`,searchTerms:[`note`,`tip`,`important`,`warning`,`caution`,`abstract`,`info`,`todo`,`success`,`question`,`failure`,`danger`,`bug`,`example`,`quote`,`alert`,`admonition`,`callout`],serialize:(e,t)=>emitMdxJsx(`Callout`,e,t,calloutProps)},{name:`img`,surface:`canonical`,hasChildren:!1,isSelfClosing:!0,props:htmlImgProps,icon:`Image`,category:`media`,displayName:`Image`,description:`Image with click-to-zoom and HTML-native attributes`,searchTerms:[`image`,`zoom`,`picture`,`photo`],placeholder:{label:`Add an image`},serialize:(e,t)=>emitMdxJsx(`img`,e,t,htmlImgProps)},{name:`video`,surface:`canonical`,hasChildren:!1,isSelfClosing:!0,props:htmlVideoProps,icon:`SquarePlay`,category:`media`,displayName:`Video`,description:`HTML5 video player with native controls`,searchTerms:[`video`,`media`,`player`,`mp4`,`webm`,`movie`],placeholder:{label:`Add a video`},serialize:(e,t)=>emitMdxJsx(`video`,e,t,htmlVideoProps)},{name:`audio`,surface:`canonical`,hasChildren:!1,isSelfClosing:!0,props:htmlAudioProps,icon:`Volume2`,category:`media`,displayName:`Audio`,description:`HTML5 audio player with native controls`,searchTerms:[`audio`,`sound`,`music`,`mp3`,`podcast`,`player`],placeholder:{label:`Add audio`},serialize:(e,t)=>emitMdxJsx(`audio`,e,t,htmlAudioProps)},{name:`Pdf`,surface:`canonical`,hasChildren:!1,isSelfClosing:!0,props:pdfProps,icon:`FileText`,category:`media`,displayName:`PDF`,description:"Embedded PDF viewer (`#page=N` to open at page N, `#height=N` for viewer height)",searchTerms:[`pdf`,`document`,`embed`,`pdfjs`],placeholder:{label:`Add a PDF`},serialize:(e,t)=>emitMdxJsx(`Pdf`,e,t,pdfProps)},{name:`File`,surface:`canonical`,hasChildren:!1,isSelfClosing:!0,props:fileProps,icon:`Paperclip`,category:`media`,displayName:`File`,description:`Downloadable file attachment — inline row with name + size + download link`,searchTerms:[`file`,`attachment`,`download`,`document`,`zip`,`docx`,`doc`],placeholder:{label:`Add a file`},serialize:(e,t)=>emitMdxJsx(`File`,e,t,fileProps)},{name:`Embed`,surface:`canonical`,hasChildren:!1,isSelfClosing:!0,props:embedProps,icon:`AppWindow`,category:`media`,displayName:`Embed`,description:`Inline web embed (iframe) — drop a URL, get a resizable preview pane`,searchTerms:[`embed`,`iframe`,`website`,`page`,`inline`,`frame`,`preview`],placeholder:{label:`Embed a URL`},serialize:(e,t)=>emitMdxJsx(`Embed`,e,t,embedProps)},{name:`Accordion`,surface:`canonical`,hasChildren:!0,props:accordionProps,icon:`ChevronRight`,category:`content`,displayName:`Accordion`,description:"Standalone expand/collapse via native HTML5 <details>/<summary>. Group siblings with the `name` prop for exclusive-accordion UX.",searchTerms:[`toggle`,`accordion`,`expandable`,`details`,`disclosure`,`collapse`,`fold`],exampleBody:`Body content revealed when the accordion is expanded.`,serialize:(e,t)=>emitMdxJsx(`Accordion`,e,t,accordionProps)},{name:`Tabs`,surface:`canonical`,hasChildren:!0,emptyChildName:`Tab`,props:tabsProps,icon:`LayoutPanelTop`,category:`content`,displayName:`Tabs`,description:"Horizontal tab strip + active panel below. Each `<Tab>` child is one panel; clickable pills at the top switch the active one. Active selection is ephemeral (resets on reload).",searchTerms:[`tabs`,`tabbed`,`panels`,`tabgroup`,`switcher`],exampleBody:`<Tab label="One">Body of the first tab panel.</Tab>
|
|
327
|
+
`)}case`WRITE_ERROR`:return`Failed to write config file: ${e.detail}`;case`OKIGNORE_INVALID`:return e.lineNumber===void 0?`.okignore: ${e.detail}`:`.okignore line ${e.lineNumber}: ${e.detail}`;case`UNKNOWN`:return e.message??`Unknown error.`}}const SYSTEM_DOC_NAME=`__system__`,CC1_CONTRACT_VERSION=1,CONFIG_DOC_NAME_PROJECT=`__config__/project`,CONFIG_DOC_NAME_USER=`__user__/config.yml`,CONFIG_DOC_NAME_PROJECT_LOCAL=`__local__/project`,CONFIG_DOC_NAME_OKIGNORE=`__config__/okignore`,CONFIG_DOC_NAMES=Object.freeze([CONFIG_DOC_NAME_PROJECT,CONFIG_DOC_NAME_PROJECT_LOCAL,CONFIG_DOC_NAME_USER,CONFIG_DOC_NAME_OKIGNORE]),ALL_EDITOR_IDS=[`claude`,`claude-desktop`,`cursor`,`codex`],EDITOR_LABELS={claude:`Claude`,"claude-desktop":`Claude Desktop`,cursor:`Cursor`,codex:`Codex`},DEFAULT_GITHUB_OAUTH_CLIENT_ID=`Ov23liqlSd0V1MwR6rhI`,ORPHAN_MODES=[`incoming`,`outgoing`,`both`];function isOrphanMode(e){return ORPHAN_MODES.includes(e)}const DEFAULT_SERVER_HOST=`localhost`,ALLOWED_IMAGE_MIME_TYPES=[`image/jpeg`,`image/png`,`image/gif`,`image/webp`,`image/svg+xml`],ALLOWED_VIDEO_MIME_TYPES=[`video/mp4`,`video/webm`,`video/ogg`],ALLOWED_AUDIO_MIME_TYPES=[`audio/mpeg`,`audio/wav`,`audio/ogg`],ALLOWED_PDF_MIME_TYPES=[`application/pdf`],IMAGE_EXTENSIONS=new Set([`png`,`jpg`,`jpeg`,`gif`,`webp`,`avif`,`svg`]),VIDEO_EXTENSIONS=new Set([`mp4`,`webm`,`mov`,`m4v`,`mkv`]),PDF_EXTENSIONS=new Set([`pdf`]),AUDIO_EXTENSIONS=new Set([`mp3`,`wav`,`ogg`,`m4a`,`flac`,`aac`,`opus`]),FILE_ATTACHMENT_EXTENSIONS=new Set(`pdf.docx.xlsx.pptx.doc.xls.ppt.zip.7z.tar.gz.rar.csv.tsv.rtf.json.yaml.yml.xml.txt.pages.numbers.key.odt.ods.odp.epub.mobi`.split(`.`)),EXECUTABLE_BLOCKLIST_EXTENSIONS=new Set(`exe.bat.cmd.ps1.com.msi.vbs.js.jse.wsf.wsh.hta.sh.command.csh.ksh.bash.zsh.fish.desktop.action.workflow.html.htm.svg.xml.mhtml.svgz.dmg.pkg.mpkg.scpt.applescript.terminal.prefpane.webloc.inetloc.fileloc.jar.appimage.deb.rpm.msix.appx.ipa.apk.pif.scr.lnk.url`.split(`.`)),ASSET_EXTENSIONS=new Set(`png.jpg.jpeg.gif.webp.avif.svg.apng.heic.heif.tiff.bmp.ico.pdf.mp4.webm.mov.m4v.mkv.avi.flv.wmv.mpeg.mpg.mp3.wav.ogg.m4a.flac.aac.opus.zip.woff.woff2.ttf.otf.eot.docx.xlsx.pptx.csv.txt.rtf.json`.split(`.`)),INLINE_RENDERABLE_EXTENSIONS=new Set(`png.jpg.jpeg.gif.webp.avif.apng.heic.heif.tiff.bmp.ico.svg.pdf.mp4.webm.mov.m4v.mkv.mp3.wav.ogg.m4a.flac.aac.opus`.split(`.`)),DEFAULT_DEDUP_MODE=`same-dir`,WIKI_EMBED_EXTENSIONS=new Set(`png.jpg.jpeg.gif.webp.avif.svg.pdf.mp4.webm.mov.m4v.mkv.mp3.wav.ogg.m4a.flac.aac.opus.docx.xlsx.pptx.doc.xls.ppt.zip.7z.tar.gz.rar.csv.tsv.rtf.json.yaml.yml.xml.txt.pages.numbers.key.odt.ods.odp.epub.mobi`.split(`.`)),SIDEBAR_IMAGE_EXTENSIONS=[`png`,`jpg`,`jpeg`,`gif`,`webp`,`avif`],SIDEBAR_VIDEO_EXTENSIONS=[`mp4`,`webm`,`mov`,`m4v`],SIDEBAR_AUDIO_EXTENSIONS=[`mp3`,`wav`,`ogg`,`m4a`,`flac`,`aac`,`opus`],SIDEBAR_PDF_EXTENSIONS=[`pdf`];function assertSubset(e,t,S){for(let w of t)if(!S.has(w))throw Error(`${e}: ${w} is not present in canonical upload constants`)}assertSubset(`SIDEBAR_IMAGE_ASSET_EXTENSIONS`,SIDEBAR_IMAGE_EXTENSIONS,IMAGE_EXTENSIONS),assertSubset(`SIDEBAR_VIDEO_ASSET_EXTENSIONS`,SIDEBAR_VIDEO_EXTENSIONS,VIDEO_EXTENSIONS),assertSubset(`SIDEBAR_AUDIO_ASSET_EXTENSIONS`,SIDEBAR_AUDIO_EXTENSIONS,AUDIO_EXTENSIONS),assertSubset(`SIDEBAR_PDF_ASSET_EXTENSIONS`,SIDEBAR_PDF_EXTENSIONS,PDF_EXTENSIONS),assertSubset(`FILE_ATTACHMENT_EXTENSIONS`,[...FILE_ATTACHMENT_EXTENSIONS],WIKI_EMBED_EXTENSIONS);const SIDEBAR_IMAGE_ASSET_EXTENSIONS=new Set(SIDEBAR_IMAGE_EXTENSIONS),SIDEBAR_VIDEO_ASSET_EXTENSIONS=new Set(SIDEBAR_VIDEO_EXTENSIONS),SIDEBAR_AUDIO_ASSET_EXTENSIONS=new Set(SIDEBAR_AUDIO_EXTENSIONS),SIDEBAR_PDF_ASSET_EXTENSIONS=new Set(SIDEBAR_PDF_EXTENSIONS),SIDEBAR_RENDERABLE_ASSET_EXTENSIONS=new Set([...SIDEBAR_IMAGE_EXTENSIONS,...SIDEBAR_VIDEO_EXTENSIONS,...SIDEBAR_AUDIO_EXTENSIONS,...SIDEBAR_PDF_EXTENSIONS]);assertSubset(`SIDEBAR_RENDERABLE_ASSET_EXTENSIONS`,[...SIDEBAR_RENDERABLE_ASSET_EXTENSIONS],INLINE_RENDERABLE_EXTENSIONS);function mediaKindForSidebarAssetExtension(e){let t=e.toLowerCase().replace(/^\./,``);return SIDEBAR_IMAGE_ASSET_EXTENSIONS.has(t)?`image`:SIDEBAR_VIDEO_ASSET_EXTENSIONS.has(t)?`video`:SIDEBAR_AUDIO_ASSET_EXTENSIONS.has(t)?`audio`:SIDEBAR_PDF_ASSET_EXTENSIONS.has(t)?`pdf`:null}const CodeBlockFidelity=index_default$11.extend({priority:60,addAttributes(){return{...this.parent?.(),fenceDelimiter:{default:"`"},fenceLength:{default:3},meta:{default:null},sourceStyle:{default:`fenced`}}}}),EmphasisFidelity=index_default$9.extend({name:`emphasis`,priority:60,addAttributes(){return{...this.parent?.(),sourceDelimiter:{default:`*`}}},addInputRules(){return[markInputRule({find:starInputRegex,type:this.type,getAttributes:{sourceDelimiter:`*`}}),markInputRule({find:underscoreInputRegex,type:this.type,getAttributes:{sourceDelimiter:`_`}})]}}),StrongFidelity=index_default$10.extend({name:`strong`,priority:60,addAttributes(){return{...this.parent?.(),sourceDelimiter:{default:`**`}}},addInputRules(){return[markInputRule({find:starInputRegex$1,type:this.type,getAttributes:{sourceDelimiter:`**`}}),markInputRule({find:underscoreInputRegex$1,type:this.type,getAttributes:{sourceDelimiter:`__`}})]}}),EscapeMark=Mark.create({name:`escapeMark`,priority:10,excludes:``,inclusive:!1,parseHTML(){return[{tag:`span[data-escape-mark]`}]},renderHTML(){return[`span`,{"data-escape-mark":``},0]}}),HardBreakFidelity=index_default$8.extend({priority:60,addAttributes(){return{...this.parent?.(),hardBreakStyle:{default:`backslash`}}}}),HeadingFidelity=index_default$7.extend({priority:60,addAttributes(){return{...this.parent?.(),headingStyle:{default:`atx`},sourceTrailingHashes:{default:null},sourceUnderlineLength:{default:null},sourceContiguousNext:{default:!1}}}}),HtmlBlockFidelity=Node3.create({name:`htmlBlock`,group:`block`,atom:!0,priority:60,addAttributes(){return{content:{default:``}}},parseHTML(){return[{tag:`div[data-html-block]`}]},renderHTML({node:e}){return[`div`,{"data-html-block":``,class:`html-block`},e.attrs.content]}}),JsxComponent=Node3.create({name:`jsxComponent`,group:`block`,atom:!1,content:`block*`,isolating:!0,selectable:!0,defining:!0,priority:60,addAttributes(){return{componentName:{default:``},kind:{default:`element`},attributes:{default:[]},sourceRaw:{default:``},sourceDirty:{default:!1},props:{default:{}}}},parseHTML(){return[{tag:`div[data-jsx-component]`,getAttrs:e=>typeof e==`string`?!1:{componentName:e.getAttribute(`data-component-name`)||``,sourceRaw:e.getAttribute(`data-source-raw`)||``}}]},renderHTML({HTMLAttributes:e}){return[`div`,{"data-jsx-component":``,"data-component-name":e.componentName,"data-source-raw":e.sourceRaw},0]},addCommands(){return{insertJsxComponent:e=>({commands:t})=>t.insertContent({type:this.name,attrs:{sourceRaw:e}})}}}),JsxInline=Node3.create({name:`jsxInline`,group:`inline`,inline:!0,atom:!1,content:`text*`,isolating:!1,selectable:!0,priority:60,addAttributes(){return{}},parseHTML(){return[{tag:`span[data-jsx-inline]`}]},renderHTML(){return[`span`,{"data-jsx-inline":``},0]}}),SAFE_URL_SCHEMES=[`https`,`http`,`mailto`,`tel`,`ftp`,`sms`],SCHEME_ALT=SAFE_URL_SCHEMES.map(e=>`${e}:`).join(`|`),SAFE_URL_SCHEME_RE=RegExp(`^(?:${SCHEME_ALT}|\\/|#|\\?|\\.\\/|\\.\\.\\/)`,`i`);function isRelativeUrl(e){let t=e.trim();if(t===``)return!0;let S=t.indexOf(`:`);if(S===-1)return!0;let w=t.indexOf(`/`),E=t.indexOf(`?`),D=t.indexOf(`#`);return S>Math.min(w===-1?1/0:w,E===-1?1/0:E,D===-1?1/0:D)}const ALLOWED_LINK_SCHEMES=new Set(SAFE_URL_SCHEMES.map(e=>`${e}:`)),PLACEHOLDER_BASE=`https://placeholder.invalid`;function isAllowedLinkUri(e){try{let t=new URL(e,PLACEHOLDER_BASE);return ALLOWED_LINK_SCHEMES.has(t.protocol.toLowerCase())}catch{return!1}}const LinkFidelity=index_default$6.extend({priority:60,addOptions(){return{openOnClick:!1,enableClickSelection:!1,linkOnPaste:!0,autolink:!0,protocols:[],defaultProtocol:`http`,HTMLAttributes:{target:`_blank`,rel:`noopener noreferrer`},isAllowedUri:isAllowedLinkUri,validate:isAllowedLinkUri,shouldAutoLink:()=>!0}},addAttributes(){return{...this.parent?.(),linkStyle:{default:`inline`,rendered:!1},refLabel:{default:null,rendered:!1},sourceForm:{default:null,rendered:!1},target:{default:null,rendered:!1},anchor:{default:null,rendered:!1},alias:{default:null,rendered:!1},sourceUrlForm:{default:null,rendered:!1},sourceTitleMarker:{default:null,rendered:!1}}}}),LinkRefDefFidelity=Node3.create({name:`linkRefDef`,group:`block`,atom:!0,priority:60,addAttributes(){return{label:{default:``},href:{default:``},title:{default:null},sourceLayout:{default:null},sourceTitleMarker:{default:null}}},parseHTML(){return[{tag:`div[data-link-ref-def]`}]},renderHTML({node:e}){let{label:t,href:S,title:w}=e.attrs,E=w?`[${t}]: ${S} "${w}"`:`[${t}]: ${S}`;return[`div`,{"data-link-ref-def":``,class:`link-ref-def`},E]}});function isBulletList(e){return e.type.name===`list`&&!e.attrs.ordered}function isOrderedList(e){return e.type.name===`list`&&!!e.attrs.ordered}function hasTaskItems(e){let t=!1;return e.forEach(e=>{e.type.name===`listItem`&&e.attrs.checked!==null&&(t=!0)}),t}function toggleListKind(e,t,S,w,E,D,O){let k=findParentNode(e=>e.type.name===`list`)(e.selection);if(k&&E(k.node)){let{$from:S,$to:E}=e.selection;return S.blockRange(E)?liftListItem$1(w)(e,t):!1}if(k){if(!t)return!0;let{tr:S}=e;return S.setNodeMarkup(k.pos,void 0,{...k.node.attrs,...D}),O!==void 0&&k.node.forEach((e,t)=>{if(e.type.name===`listItem`){let w=k.pos+1+t;S.setNodeMarkup(w,void 0,{...e.attrs,...O})}}),t(S),!0}return wrapInList$1(S,D)(e,void 0)?t?wrapInList$1(S,D)(e,S=>{if(O){let t=S.mapping.map(e.selection.$from.pos),w=S.doc.resolve(t);for(let e=w.depth;e>0;e--){let t=w.node(e);if(t.type.name===`listItem`){S.setNodeMarkup(w.before(e),void 0,{...t.attrs,...O});break}}}t(S)}):!0:!1}const ListNode=Node3.create({name:`list`,group:`block list`,content:`listItem+`,priority:60,addAttributes(){return{ordered:{default:!1},start:{default:1},spread:{default:!1},bulletMarker:{default:null},listMarkerDelimiter:{default:null}}},parseHTML(){return[{tag:`ul`,getAttrs:()=>({ordered:!1})},{tag:`ol`,getAttrs:e=>({ordered:!0,start:e.getAttribute(`start`)?Number(e.getAttribute(`start`)):1})}]},renderHTML({node:e,HTMLAttributes:t}){let S=e.attrs.ordered?`ol`:`ul`,w={};return e.attrs.ordered&&e.attrs.start!==1&&(w.start=e.attrs.start),[S,mergeAttributes(t,w),0]},addCommands(){return{toggleBulletList:()=>({state:e,dispatch:t})=>{let S=e.schema.nodes.list,w=e.schema.nodes.listItem;return!S||!w?!1:toggleListKind(e,t,S,w,e=>isBulletList(e)&&!hasTaskItems(e),{ordered:!1},{checked:null})},toggleOrderedList:()=>({state:e,dispatch:t})=>{let S=e.schema.nodes.list,w=e.schema.nodes.listItem;return!S||!w?!1:toggleListKind(e,t,S,w,e=>isOrderedList(e),{ordered:!0},{checked:null})},toggleTaskList:()=>({state:e,dispatch:t})=>{let S=e.schema.nodes.list,w=e.schema.nodes.listItem;return!S||!w?!1:toggleListKind(e,t,S,w,e=>isBulletList(e)&&hasTaskItems(e),{ordered:!1},{checked:!1})}}},addInputRules(){return[wrappingInputRule({find:/^\s*([-+*])(?!\s*\[[ xX]\])\s$/,type:this.type,getAttributes:e=>({ordered:!1,bulletMarker:e[1]})}),wrappingInputRule({find:/^\s*(\d+)([.)])\s$/,type:this.type,getAttributes:e=>({ordered:!0,start:Number(e[1]),listMarkerDelimiter:e[2]})}),new InputRule({find:/^\s*[-*+]\s\[([ xX])\]\s$/,handler:({state:e,range:t,match:S})=>{let w=e.schema.nodes.list;if(!w)return null;let E=S[1]!==` `,D=e.tr.delete(t.from,t.to),O=D.doc.resolve(t.from).blockRange();if(!O)return null;let k=findWrapping(O,w,{ordered:!1});if(!k)return null;D.wrap(O,k);let j=D.doc.resolve(D.mapping.map(t.from));for(let e=j.depth;e>0;e--){let t=j.node(e);if(t.type.name===`listItem`){D.setNodeMarkup(j.before(e),void 0,{...t.attrs,checked:E});break}}}})]},addKeyboardShortcuts(){return{"Mod-Shift-8":()=>this.editor.commands.toggleBulletList(),"Mod-Shift-7":()=>this.editor.commands.toggleOrderedList(),"Mod-Shift-9":()=>this.editor.commands.toggleTaskList()}}}),ListItemNode=Node3.create({name:`listItem`,content:`paragraph block*`,defining:!0,addAttributes(){return{checked:{default:null},spread:{default:!1}}},parseHTML(){return[{tag:`li`,getAttrs:e=>{let t=e.querySelector(`input[type="checkbox"]`);return{checked:t?t.checked:null}}}]},renderHTML({node:e,HTMLAttributes:t}){return e.attrs.checked===null?[`li`,mergeAttributes(t),0]:[`li`,mergeAttributes(t,{"data-type":`taskItem`,"data-checked":e.attrs.checked?`true`:`false`}),[`label`,{contenteditable:`false`},[`input`,{type:`checkbox`,...e.attrs.checked?{checked:`checked`}:{}}]],[`div`,0]]},addNodeView(){return({node:e,getPos:t,editor:S,HTMLAttributes:w})=>{let E=document.createElement(`li`);Object.entries(mergeAttributes(w,e.attrs.checked===null?{}:{"data-type":`taskItem`,"data-checked":String(!!e.attrs.checked)})).forEach(([e,t])=>{t!=null&&E.setAttribute(e,String(t))});let D=null,O=null,k=document.createElement(`div`);return e.attrs.checked!==null&&(D=document.createElement(`label`),D.contentEditable=`false`,O=document.createElement(`input`),O.type=`checkbox`,O.checked=!!e.attrs.checked,S.isEditable||(O.disabled=!0),O.addEventListener(`change`,()=>{let w=t();w===void 0||typeof w!=`number`||S.view.dispatch(S.view.state.tr.setNodeMarkup(w,void 0,{...e.attrs,checked:O?.checked??!1}))}),D.appendChild(O),E.appendChild(D)),E.appendChild(k),{dom:E,contentDOM:k,update(t){return t.type!==e.type||t.attrs.checked!==null!=(e.attrs.checked!==null)?!1:(O&&t.attrs.checked!==null&&(O.checked=!!t.attrs.checked,E.setAttribute(`data-checked`,String(!!t.attrs.checked))),e=t,!0)}}}},addKeyboardShortcuts(){return{Enter:()=>this.editor.commands.splitListItem(this.name),Tab:()=>{let{$from:e}=this.editor.state.selection;for(let t=e.depth;t>0;t--)if(e.node(t).type.name===`listItem`)return this.editor.commands.sinkListItem(this.name);return!1},"Shift-Tab":()=>{let{$from:e}=this.editor.state.selection;for(let t=e.depth;t>0;t--)if(e.node(t).type.name===`listItem`)return this.editor.commands.liftListItem(this.name);return!1}}}}),List=ListNode,ListItem=ListItemNode,MathInline=Node3.create({name:`mathInline`,group:`inline`,inline:!0,atom:!0,selectable:!0,priority:60,addAttributes(){return{formula:{default:``},id:{default:null},language:{default:`latex`}}},parseHTML(){return[{tag:`span[data-math-inline]`,getAttrs:e=>typeof e==`string`?!1:{formula:e.getAttribute(`data-formula`)||``,id:e.getAttribute(`id`)||null,language:e.getAttribute(`data-language`)||`latex`}}]},renderHTML({HTMLAttributes:e}){return[`span`,{"data-math-inline":``,"data-formula":e.formula,"data-language":e.language,...e.id?{id:e.id}:{}}]},addCommands(){return{insertMathInline:e=>({commands:t})=>t.insertContent({type:this.name,attrs:{formula:e}})}}}),RawMdxFallback=Node3.create({name:`rawMdxFallback`,group:`block`,atom:!1,content:`text*`,isolating:!0,selectable:!0,defining:!0,priority:60,addAttributes(){return{reason:{default:``},originalSpan:{default:{start:0,end:0}}}},parseHTML(){let e=e=>typeof e==`string`?!1:{reason:e.getAttribute(`data-reason`)||``};return[{tag:`div[data-raw-mdx-fallback]`,getAttrs:e},{tag:`pre[data-raw-mdx-fallback]`,getAttrs:e}]},renderHTML({HTMLAttributes:e}){return[`div`,{"data-raw-mdx-fallback":``,"data-raw-badge":`raw`,"data-reason":e.reason,contenteditable:`false`,class:`raw-mdx-fallback`},0]},addNodeView(){return({HTMLAttributes:e})=>{let t=document.createElement(`div`);t.setAttribute(`data-raw-mdx-fallback`,``),t.setAttribute(`data-raw-badge`,`raw`),t.setAttribute(`contenteditable`,`false`),t.classList.add(`raw-mdx-fallback`),e.reason&&t.setAttribute(`data-reason`,e.reason);let S=document.createElement(`pre`);return S.classList.add(`raw-mdx-fallback-content`),S.setAttribute(`contenteditable`,`false`),t.appendChild(S),{dom:t,contentDOM:S,ignoreMutation:()=>!0}}}}),BlockquoteFidelity=index_default$4.extend({priority:60,addAttributes(){return{...this.parent?.(),sourceMarkerSpacings:{default:null}}}}),CodeMarkFidelity=index_default$3.extend({excludes:``,addAttributes(){return{...this.parent?.(),sourceFenceChar:{default:"`"},sourceFenceLength:{default:1}}}}),CommentBlock=Node3.create({name:`commentBlock`,group:`block`,content:`block+`,defining:!0,priority:60,addAttributes(){return{sourceForm:{default:`percent`,parseHTML:e=>e.getAttribute(`data-source-form`)===`html`?`html`:`percent`,renderHTML:e=>e.sourceForm===`html`?{"data-source-form":`html`}:{}},sourceLayout:{default:`block`,parseHTML:e=>e.getAttribute(`data-source-layout`)===`inline`?`inline`:`block`,renderHTML:e=>e.sourceLayout===`inline`?{"data-source-layout":`inline`}:{}}}},parseHTML(){return[{tag:`aside[data-comment-block]`},{tag:`aside.comment-block`}]},renderHTML({HTMLAttributes:e}){return[`aside`,{"data-comment-block":``,"data-clipboard-omit":`true`,class:`comment-block`,style:`display: none;`,...e},0]},addCommands(){return{setCommentBlock:()=>({commands:e})=>e.wrapIn(this.name),toggleCommentBlock:()=>({commands:e})=>e.toggleWrap(this.name),unsetCommentBlock:()=>({commands:e})=>e.lift(this.name)}}}),CommentMark=Mark.create({name:`comment`,priority:10,excludes:``,inclusive:!1,addAttributes(){return{sourceForm:{default:`percent`,parseHTML:e=>e.getAttribute(`data-source-form`)===`html`?`html`:`percent`,renderHTML:e=>e.sourceForm===`html`?{"data-source-form":`html`}:{}}}},parseHTML(){return[{tag:`span[data-comment-mark]`}]},renderHTML({HTMLAttributes:e}){return[`span`,{"data-comment-mark":``,"data-clipboard-omit":`true`,class:`comment-mark`,style:`display: none;`,...e},0]},addCommands(){return{setComment:()=>({commands:e})=>e.setMark(this.name),toggleComment:()=>({commands:e})=>e.toggleMark(this.name),unsetComment:()=>({commands:e})=>e.unsetMark(this.name)}}}),FootnoteDefinition=Node3.create({name:`footnoteDefinition`,group:`block`,content:`block+`,defining:!0,priority:60,addAttributes(){return{identifier:{default:``},label:{default:null}}},parseHTML(){let e=e=>{if(typeof e==`string`)return!1;let t=e.getAttribute(`data-footnote-id`)||``;return{identifier:t,label:t||null}};return[{tag:`aside[data-footnote-def]`,getAttrs:e},{tag:`aside.footnote-def`,getAttrs:e}]},renderHTML({node:e,HTMLAttributes:t}){let S=String(e.attrs.identifier??``);return[`aside`,{...t,"data-footnote-def":``,"data-footnote-id":S,id:`fn-${S}`,class:`footnote-def`},[`div`,{class:`footnote-body`},0],[`a`,{href:`#fnref-${S}`,class:`footnote-backref`,contentEditable:`false`,"aria-label":`Back to reference`},`↩`]]},addCommands(){return{insertFootnoteDefinition:e=>({commands:t})=>t.insertContent({type:this.name,attrs:{identifier:e,label:e},content:[{type:`paragraph`}]})}}}),FootnoteReference=Node3.create({name:`footnoteReference`,group:`inline`,inline:!0,atom:!0,selectable:!0,draggable:!1,priority:60,addAttributes(){return{identifier:{default:``},label:{default:null}}},parseHTML(){return[{tag:`sup[data-footnote-ref]`,getAttrs:e=>{if(typeof e==`string`)return!1;let t=e.getAttribute(`data-footnote-id`)||``;return{identifier:t,label:t||null}}}]},renderHTML({node:e}){let t=String(e.attrs.identifier??``);return[`sup`,{id:`fnref-${t}`,"data-footnote-ref":``,"data-footnote-id":t,class:`footnote-ref`},[`a`,{href:`#fn-${t}`,class:`footnote-ref-link`},`[${t}]`]]},addCommands(){return{insertFootnoteReference:e=>({commands:t})=>t.insertContent({type:this.name,attrs:{identifier:e,label:e}})}}}),ImageReferenceFidelity=Node3.create({name:`imageReference`,group:`inline`,inline:!0,atom:!0,priority:60,addAttributes(){return{alt:{default:``},label:{default:``},identifier:{default:``},referenceType:{default:`shortcut`}}},parseHTML(){return[{tag:`img[data-image-reference]`}]},renderHTML({node:e}){let{alt:t,label:S,referenceType:w}=e.attrs,E=t||S;return[`img`,{"data-image-reference":``,"data-reference-type":w,"data-label":S,alt:E}]}});function toDesktopAssetHref(e){if(typeof e!=`string`||!e.startsWith(`/`))return e;let t=globalThis.window?.okDesktop?.config?.apiOrigin;return typeof t==`string`&&t?t+e:e}const ImageSrcFidelity=index_default.extend({priority:60,addAttributes(){return{...this.parent?.(),sourceUrl:{default:null,rendered:!1}}},renderHTML({HTMLAttributes:e}){let t=mergeAttributes(this.options.HTMLAttributes,e);return typeof t.src==`string`&&(t.src=toDesktopAssetHref(t.src)),[`img`,t]}}),SourceLiteralMark=Mark.create({name:`sourceLiteral`,priority:10,excludes:``,inclusive:!1,addAttributes(){return{sourceRaw:{default:``}}},parseHTML(){return[{tag:`span[data-source-literal]`}]},renderHTML({HTMLAttributes:e}){return[`span`,{"data-source-literal":``,...e},0]}});function isValidSourceLiteralRaw(e,t){if(typeof e!=`string`||typeof t!=`string`||/[\x00-\x1F\x7F]/.test(e))return!1;let S=e.replaceAll(`\xA0`,` `),w=t.replaceAll(`\xA0`,` `);return S===w?!0:stripMarkdownBackslashEscapes(S)===w}function stripMarkdownBackslashEscapes(e){return e.replace(/\\([!-/:-@[-`{-~])/g,`$1`)}const TableFidelity=Table.extend({priority:60,addAttributes(){return{...this.parent?.(),sourceDashCounts:{default:null}}}}),TableCellFidelity=TableCell.extend({priority:60,addAttributes(){return{...this.parent?.(),sourcePadding:{default:null}}}}),TableHeaderFidelity=TableHeader.extend({priority:60,addAttributes(){return{...this.parent?.(),sourcePadding:{default:null}}}}),Tag=Node3.create({name:`tag`,group:`inline`,inline:!0,atom:!0,selectable:!0,priority:60,addAttributes(){return{value:{default:``}}},parseHTML(){return[{tag:`a[data-tag]`,getAttrs:e=>typeof e==`string`?!1:{value:e.getAttribute(`data-tag`)||``}}]},renderHTML({node:e,HTMLAttributes:t}){let S=String(e.attrs.value??``);return[`a`,{...t,"data-tag":S,href:`#tag/${S}`,class:`tag`},`#${S}`]},addCommands(){return{insertTag:e=>({chain:t})=>t().insertContent({type:`tag`,attrs:{value:e}}).run()}}}),THEMATIC_BREAK_INPUT_RE=/^(?:---|—-|___\s|\*\*\*\s)$/;function thematicBreakSourceRawFromMatch(e){let t=String(e[0]??``).replace(/\s+$/,``);return t===`—-`?`---`:t}const ThematicBreakFidelity=index_default$2.extend({name:`thematicBreak`,priority:60,addAttributes(){return{...this.parent?.(),sourceRaw:{default:`---`}}},addInputRules(){return[nodeInputRule({find:THEMATIC_BREAK_INPUT_RE,type:this.type,getAttributes:e=>({sourceRaw:thematicBreakSourceRawFromMatch(e)})})]}});function normalizeNullableString(e){if(typeof e!=`string`)return null;let t=e.trim();return t.length>0?t:null}function getWikiLinkText(e){return e.alias?e.alias:e.anchor?`${e.target}#${e.anchor}`:e.target}const WikiLink=Node3.create({name:`wikiLink`,group:`inline`,inline:!0,atom:!0,priority:60,addAttributes(){return{target:{default:``},alias:{default:null},anchor:{default:null},resolved:{default:!1}}},parseHTML(){return[{tag:`span[data-wiki-link]`,getAttrs:e=>typeof e==`string`?!1:{target:e.getAttribute(`data-target`)||``,alias:normalizeNullableString(e.getAttribute(`data-alias`)),anchor:normalizeNullableString(e.getAttribute(`data-anchor`)),resolved:e.getAttribute(`data-resolved`)===`true`}},{tag:`a.wiki-link[data-target]`,priority:100,getAttrs:e=>{if(typeof e==`string`)return!1;let t=e.getAttribute(`data-target`)??``;return t?{target:t,alias:normalizeNullableString(e.getAttribute(`data-alias`)),anchor:normalizeNullableString(e.getAttribute(`data-anchor`)),resolved:!1}:!1}}]},renderHTML({node:e,HTMLAttributes:t}){let S=String(e.attrs.target??``),w=normalizeNullableString(e.attrs.alias),E=normalizeNullableString(e.attrs.anchor),D=e.attrs.resolved===!0;return[`span`,{...t,"data-wiki-link":``,"data-target":S,"data-alias":w??``,"data-anchor":E??``,"data-resolved":D?`true`:`false`},getWikiLinkText({target:S,alias:w,anchor:E})]}});function extensionOf(e){let t=e.split(`/`).pop()??e,S=t.lastIndexOf(`.`);return S<=0||S===t.length-1?``:t.slice(S+1).toLowerCase()}function labelFor(e){return e.alias?e.alias:e.anchor?`${e.target}#${e.anchor}`:e.target}const WikiLinkEmbed=Node3.create({name:`wikiLinkEmbed`,group:`inline`,inline:!0,atom:!0,priority:60,addAttributes(){return{target:{default:``},alias:{default:null},anchor:{default:null},resolvedSrc:{default:null,rendered:!1,parseHTML:()=>null}}},parseHTML(){let e=e=>typeof e==`string`||!e.hasAttribute(`data-wiki-embed`)?!1:{target:e.getAttribute(`data-target`)||``,alias:normalizeNullableString(e.getAttribute(`data-alias`)),anchor:normalizeNullableString(e.getAttribute(`data-anchor`))};return[{tag:`img[data-wiki-embed]`,getAttrs:e,priority:100},{tag:`a[data-wiki-embed]`,getAttrs:e,priority:100}]},renderHTML({node:e,HTMLAttributes:t}){let S=String(e.attrs.target??``),w=normalizeNullableString(e.attrs.alias),E=normalizeNullableString(e.attrs.anchor),D=normalizeNullableString(e.attrs.resolvedSrc),O=extensionOf(S);if(IMAGE_EXTENSIONS.has(O))return[`img`,{...t,"data-wiki-embed":``,"data-target":S,"data-alias":w??``,"data-anchor":E??``,src:D??S,alt:w??S}];let k=D??S;return[`a`,{...t,"data-wiki-embed":``,"data-target":S,"data-alias":w??``,"data-anchor":E??``,href:E?`${k}#${E}`:k,target:`_blank`,rel:`noopener noreferrer`},labelFor({target:S,alias:w,anchor:E})]}}),sharedExtensions=[JsxComponent,RawMdxFallback,JsxInline,MathInline,WikiLink,WikiLinkEmbed,Tag,List,ListItem,EmphasisFidelity,StrongFidelity,CodeMarkFidelity,CodeBlockFidelity,BlockquoteFidelity,HeadingFidelity,ThematicBreakFidelity,LinkFidelity,HtmlBlockFidelity,LinkRefDefFidelity,HardBreakFidelity,EscapeMark,SourceLiteralMark,index_default$1.configure({undoRedo:!1,bulletList:!1,orderedList:!1,listItem:!1,italic:!1,bold:!1,code:!1,codeBlock:!1,heading:!1,horizontalRule:!1,hardBreak:!1,link:!1,blockquote:!1,dropcursor:{color:`color-mix(in oklch, var(--primary) 50%, transparent)`,width:2}}),TableFidelity.configure({resizable:!0}),TableRow,TableHeaderFidelity,TableCellFidelity,ImageSrcFidelity.configure({inline:!0}),ImageReferenceFidelity,index_default$5,CommentMark,CommentBlock,FootnoteReference,FootnoteDefinition],FRONTMATTER_TAG_VALUE_RE=/^[a-zA-Z][\w/-]*$/;function stripLeadingHash(e){return e.startsWith(`#`)?e.slice(1):e}function coerceCandidates(e){return typeof e==`string`?[e]:Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}function extractFrontmatterTags(e){if(!e||e.trim()===``)return[];let{map:t}=parseFrontmatterYaml(e);if(!t)return[];let S=coerceCandidates(t.tags),w=[];for(let e of S){let t=stripLeadingHash(e);FRONTMATTER_TAG_VALUE_RE.test(t)?w.push(t):console.warn(`[frontmatter-tags] dropping invalid tag entry: ${JSON.stringify(e)}`)}return w}const safeDocNameField=string$2().refine(e=>!e.includes(`..`)&&!e.startsWith(`/`)&&!e.includes(`\0`)&&!e.includes(`\\`),{message:`docName contains unsafe path characters`}).optional(),agentIdentityFields={agentId:string$2().optional(),agentName:string$2().optional(),colorSeed:string$2().optional(),clientName:string$2().optional(),clientVersion:string$2().optional(),label:string$2().optional()},summaryField=string$2().optional(),URN_UUID_RE=/^urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,ServerInfoSuccessSchema=object$1({serverInstanceId:string$2().min(1),currentBranch:string$2().min(1).optional(),currentDiskAckSVs:record(string$2().min(1),string$2().min(1)).optional()}).loose(),PrincipalSuccessSchema=object$1({id:string$2().min(1),display_name:string$2().min(1),display_email:string$2(),source:_enum([`git-config`,`synthesized`]),created_at:string$2().min(1)}).loose(),ProblemTypeSchema=_enum(`urn:ok:error:malformed-upload.urn:ok:error:collision-exhaustion.urn:ok:error:storage-full.urn:ok:error:storage-readonly.urn:ok:error:storage-error.urn:ok:error:no-file-received.urn:ok:error:path-escape.urn:ok:error:method-not-allowed.urn:ok:error:invalid-request.urn:ok:error:payload-too-large.urn:ok:error:request-timeout.urn:ok:error:internal-server-error.urn:ok:error:loopback-required.urn:ok:error:invalid-origin.urn:ok:error:url-not-allowed.urn:ok:error:dir-outside-home.urn:ok:error:concurrent-operation.urn:ok:error:clone-failed.urn:ok:error:clone-timeout.urn:ok:error:server-start-failed.urn:ok:error:reserved-doc-name.urn:ok:error:target-not-found.urn:ok:error:stale-target.urn:ok:error:frontmatter-edit-not-supported.urn:ok:error:invalid-frontmatter-patch.urn:ok:error:no-active-session.urn:ok:error:too-many-agent-sessions.urn:ok:error:doc-not-found.urn:ok:error:doc-already-exists.urn:ok:error:doc-not-open.urn:ok:error:rollback-not-configured.urn:ok:error:doc-not-available.urn:ok:error:backlink-index-not-configured.urn:ok:error:file-rescan-not-configured.urn:ok:error:shadow-not-configured.urn:ok:error:host-not-allowed.urn:ok:error:principal-not-available.urn:ok:error:not-found.urn:ok:error:auth-failed.urn:ok:error:no-project-dir.urn:ok:error:server-open-failed.urn:ok:error:sync-not-active.urn:ok:error:project-repo-not-configured.urn:ok:error:seed-prerequisite-missing.urn:ok:error:seed-invalid-root.urn:ok:error:tag-index-not-configured.urn:ok:error:template-not-found.urn:ok:error:unsupported-asset-type.urn:ok:error:asset-not-found.urn:ok:error:collab-server-not-running.urn:ok:error:gateway-timeout.urn:ok:error:cursor-not-installed.urn:ok:error:cursor-spawn-timeout.urn:ok:error:cursor-spawn-failed.urn:ok:error:handoff-target-not-installed.urn:ok:error:handoff-spawn-timeout.urn:ok:error:handoff-spawn-failed`.split(`.`));function assertNeverProblemType(e){throw Error(`Unexpected ProblemType variant: ${JSON.stringify(e)}`)}const ProblemDetailsSchema=object$1({type:ProblemTypeSchema,title:string$2().min(1),status:number$1().int().min(400).max(599),instance:string$2().regex(URN_UUID_RE,`instance must be urn:uuid:<uuid>`).optional(),detail:string$2().optional()}).loose(),UploadRequestSchema=object$1({parentDocName:string$2().min(1),agentId:string$2().min(1).optional(),agentName:string$2().min(1).optional()}).loose(),UploadAssetSuccessSchema=object$1({src:string$2().min(1),path:string$2().min(1).optional(),deduped:boolean$1().optional()}).loose(),LocalOpCloneRequestSchema=object$1({url:string$2().min(1),dir:string$2().min(1)}).loose(),StreamingProblemEventSchema=object$1({type:literal(`error`),problem:ProblemDetailsSchema}).loose();function reconstructAttrs(e,t){let S=Array.isArray(e.attrs.attributes)?e.attrs.attributes.filter(e=>typeof e==`object`&&!!e&&`type`in e):[],w=e.attrs.props??{},E=new Map,D=new Set;if(t)for(let e of t)e.omitOnDefault===!0&&`defaultValue`in e&&e.defaultValue!==void 0&&E.set(e.name,e.defaultValue),e.type===`string`&&e.required===!1&&e.defaultValue===void 0&&D.add(e.name);for(let[e,t]of Object.entries(w)){let w=S.findIndex(t=>t.type===`mdxJsxAttribute`&&t.name===e);if(E.has(e)&&Object.is(E.get(e),t)){w>=0&&S.splice(w,1);continue}if(D.has(e)&&t===``){w>=0&&S.splice(w,1);continue}let O=propToMdxJsxAttribute(e,t);w>=0?S[w]=O:S.push(O)}return S}function propToMdxJsxAttribute(e,t){if(t===!0)return{type:`mdxJsxAttribute`,name:e,value:null};if(t===!1)return{type:`mdxJsxAttribute`,name:e,value:{type:`mdxJsxAttributeValueExpression`,value:`false`}};if(t==null)return{type:`mdxJsxAttribute`,name:e,value:null};if(typeof t==`string`)return{type:`mdxJsxAttribute`,name:e,value:t};if(typeof t==`number`)return{type:`mdxJsxAttribute`,name:e,value:{type:`mdxJsxAttributeValueExpression`,value:JSON.stringify(t)}};if(typeof t==`object`){let S;try{S=JSON.stringify(t)}catch{S=String(t)}return{type:`mdxJsxAttribute`,name:e,value:{type:`mdxJsxAttributeValueExpression`,value:S}}}return{type:`mdxJsxAttribute`,name:e,value:String(t)}}function emitMdxJsx(e,t,S,w){return{type:`mdxJsxFlowElement`,name:e,attributes:reconstructAttrs(t,w),children:S.all(t),data:{}}}const YOUTUBE_VIDEO_ID_RE=/^[A-Za-z0-9_-]{11}$/;function isYouTubeHost(e){let t=e.toLowerCase();return t===`youtube.com`||t===`www.youtube.com`||t===`m.youtube.com`||t===`music.youtube.com`||t===`youtu.be`||t===`youtube-nocookie.com`||t===`www.youtube-nocookie.com`}function parseTimestampToSeconds(e){if(e.length===0)return null;if(/^[0-9]+$/.test(e)){let t=Number.parseInt(e,10);return t>0?t:null}let t=e.match(/^(?:([0-9]+)h)?(?:([0-9]+)m)?(?:([0-9]+)s?)?$/);if(!t)return null;let S=t[1]?Number.parseInt(t[1],10):0,w=t[2]?Number.parseInt(t[2],10):0,E=t[3]?Number.parseInt(t[3],10):0,D=S*3600+w*60+E;return D>0?D:null}function extractVideoId(e){if(e.hostname.toLowerCase()===`youtu.be`){let t=e.pathname.replace(/^\//,``).split(`/`)[0]??``;return YOUTUBE_VIDEO_ID_RE.test(t)?t:null}if(e.pathname===`/watch`){let t=e.searchParams.get(`v`)??``;return YOUTUBE_VIDEO_ID_RE.test(t)?t:null}let t=e.pathname.match(/^\/(?:embed|shorts|v)\/([A-Za-z0-9_-]{11})\/?$/);return t?t[1]??null:null}function parseYouTubeUrl(e){if(typeof e!=`string`||e.length===0)return null;let t;try{t=new URL(e)}catch{return null}if(t.protocol!==`http:`&&t.protocol!==`https:`||!isYouTubeHost(t.hostname))return null;let S=extractVideoId(t);if(!S)return null;let w=t.searchParams.get(`t`)??t.searchParams.get(`start`)??``;return{id:S,startSeconds:w.length>0?parseTimestampToSeconds(w):null,noCookie:t.hostname.toLowerCase().endsWith(`youtube-nocookie.com`)}}const calloutProps=[{name:`type`,type:`enum`,enumValues:[`note`,`tip`,`important`,`warning`,`caution`,`abstract`,`info`,`todo`,`success`,`question`,`failure`,`danger`,`bug`,`example`,`quote`],defaultValue:`note`,required:!1,description:`Callout variant`},{name:`title`,type:`string`,required:!1,description:`Optional heading shown above the body`},{name:`icon`,type:`string`,required:!1,advanced:!0,description:"Custom lucide icon override (e.g. `lucide:Lightbulb`)"},{name:`color`,type:`string`,required:!1,advanced:!0,description:"Optional accent color override (hex — e.g. `#F05032`)"},{name:`collapsible`,type:`boolean`,required:!1,defaultValue:!1,advanced:!0,description:"Render as a foldable `<details>` (Obsidian `[!TYPE]+/-`)"},{name:`defaultOpen`,type:`boolean`,required:!1,defaultValue:!0,advanced:!0,description:`When collapsible, start in the open state`},{name:`children`,type:`reactnode`,required:!0,description:`Callout content`}],htmlImgProps=[{name:`src`,type:`string`,required:!0,defaultValue:``,description:`Image source URL`,accept:ALLOWED_IMAGE_MIME_TYPES,autoFocus:!0},{name:`alt`,type:`string`,required:!0,description:`Alt text`},{name:`width`,type:`number`,required:!1,advanced:!0,description:`Image width`},{name:`height`,type:`number`,required:!1,advanced:!0,description:`Image height`},{name:`srcset`,type:`string`,required:!1,advanced:!0,description:`Responsive image candidate set (e.g. "x.png 1x, y.png 2x")`},{name:`sizes`,type:`string`,required:!1,advanced:!0,description:`Responsive image sizes hint paired with srcset`},{name:`loading`,type:`enum`,enumValues:[`eager`,`lazy`],defaultValue:`lazy`,required:!1,advanced:!0,omitOnDefault:!0,description:`Native img loading strategy (defaults to lazy)`},{name:`title`,type:`string`,required:!1,advanced:!0,description:`Native HTML title attribute (tooltip)`},{name:`decoding`,type:`enum`,enumValues:[`sync`,`async`,`auto`],defaultValue:`auto`,required:!1,advanced:!0,omitOnDefault:!0,description:`Hint for how the browser should decode the image`},{name:`fetchpriority`,type:`enum`,enumValues:[`high`,`low`,`auto`],defaultValue:`auto`,required:!1,advanced:!0,omitOnDefault:!0,description:`Resource fetch priority hint`},{name:`crossorigin`,type:`enum`,enumValues:[`anonymous`,`use-credentials`],required:!1,advanced:!0,description:`CORS mode for the image fetch`},{name:`referrerpolicy`,type:`string`,required:!1,advanced:!0,description:`Referrer policy for the image fetch (HTML referrerpolicy values)`},{name:`align`,type:`enum`,enumValues:[`center`,`left`,`right`],defaultValue:`center`,required:!1,omitOnDefault:!0,description:`Alignment within the column`}],embedProps=[{name:`src`,type:`string`,required:!0,defaultValue:``,description:`Embedded page URL (must start with http:// or https://)`,autoFocus:!0},{name:`title`,type:`string`,required:!1,description:`Iframe title (accessible label for screen readers)`},{name:`width`,type:`string`,required:!1,advanced:!0,description:`Embed width as a CSS length (e.g. "100%", "640px")`},{name:`height`,type:`string`,required:!1,advanced:!0,description:`Embed height as a CSS length (e.g. "26rem", "480px")`},{name:`align`,type:`enum`,enumValues:[`center`,`left`,`right`],defaultValue:`center`,required:!1,omitOnDefault:!0,description:`Alignment within the column`}],htmlVideoProps=[{name:`src`,type:`string`,required:!0,defaultValue:``,description:`Video source URL`,accept:ALLOWED_VIDEO_MIME_TYPES,autoFocus:!0},{name:`controls`,type:`boolean`,required:!1,defaultValue:!0,advanced:!0,omitOnDefault:!0,description:`Show native HTML5 video controls (defaults to true)`},{name:`autoplay`,type:`boolean`,required:!1,advanced:!0,description:`Begin playback as soon as possible (usually requires muted)`},{name:`poster`,type:`string`,required:!1,advanced:!0,description:`Poster image URL shown before playback`,accept:ALLOWED_IMAGE_MIME_TYPES},{name:`width`,type:`number`,required:!1,advanced:!0,description:`Video width`},{name:`height`,type:`number`,required:!1,advanced:!0,description:`Video height`},{name:`title`,type:`string`,required:!1,advanced:!0,description:`Native HTML title attribute (tooltip)`},{name:`muted`,type:`boolean`,required:!1,advanced:!0,description:`Mute audio on load`},{name:`loop`,type:`boolean`,required:!1,advanced:!0,description:`Restart from the beginning when playback ends`},{name:`playsinline`,type:`boolean`,required:!1,advanced:!0,description:`Play inline on iOS rather than entering fullscreen`},{name:`preload`,type:`enum`,enumValues:[`none`,`metadata`,`auto`],required:!1,advanced:!0,description:`Hint for how much of the video to preload`,hideWhen:e=>typeof e.src==`string`&&parseYouTubeUrl(e.src)!==null}],htmlAudioProps=[{name:`src`,type:`string`,required:!0,defaultValue:``,description:`Audio source URL`,accept:ALLOWED_AUDIO_MIME_TYPES,autoFocus:!0},{name:`controls`,type:`boolean`,required:!1,defaultValue:!0,advanced:!0,omitOnDefault:!0,description:`Show native HTML5 audio controls (defaults to true)`},{name:`autoplay`,type:`boolean`,required:!1,advanced:!0,description:`Begin playback as soon as possible (usually requires muted)`},{name:`title`,type:`string`,required:!1,advanced:!0,description:`Native HTML title attribute (tooltip)`},{name:`muted`,type:`boolean`,required:!1,advanced:!0,description:`Mute audio on load`},{name:`loop`,type:`boolean`,required:!1,advanced:!0,description:`Restart from the beginning when playback ends`},{name:`preload`,type:`enum`,enumValues:[`none`,`metadata`,`auto`],required:!1,advanced:!0,description:`Hint for how much of the audio to preload`}],accordionProps=[{name:`title`,type:`string`,required:!0,description:`Accordion heading shown inside the <summary>`},{name:`defaultOpen`,type:`boolean`,required:!1,defaultValue:!1,description:`When true, the accordion renders expanded on initial load`},{name:`icon`,type:`string`,required:!1,advanced:!0,description:"Custom lucide icon override (e.g. `lucide:Rocket`)"},{name:`description`,type:`string`,required:!1,advanced:!0,description:`Optional subtitle rendered below the title inside <summary>`},{name:`id`,type:`string`,required:!1,advanced:!0,description:"HTML id attribute for deep-linking (e.g. `#advanced-options`)"},{name:`name`,type:`string`,required:!1,advanced:!0,description:`HTML5 <details name=> group — siblings with the same name are mutually exclusive`}],gfmCalloutProps=[calloutProps[0],calloutProps[1],calloutProps[4],calloutProps[5],calloutProps[6]],commonMarkImageProps=[htmlImgProps[0],htmlImgProps[1],htmlImgProps[7]],htmlDetailsAccordionProps=[accordionProps[0],accordionProps[1],accordionProps[4],accordionProps[5]],wikiEmbedImageProps=[{name:`alias`,type:`string`,required:!1,defaultValue:``,description:"Alt text (Obsidian alias syntax: `![[file.png|alt text]]`)"}],wikiEmbedVideoProps=[{name:`alias`,type:`string`,required:!1,defaultValue:``,description:"Title text (Obsidian alias syntax: `![[clip.mp4|title]]`)"}],wikiEmbedAudioProps=[{name:`alias`,type:`string`,required:!1,defaultValue:``,description:"Title text (Obsidian alias syntax: `![[song.mp3|title]]`)"}],tabsProps=[{name:`id`,type:`string`,required:!1,advanced:!0,description:"HTML id attribute for deep-linking (e.g. `#install-tabs`)"}],tabProps=[{name:`label`,type:`string`,required:!0,autoFocus:!0,defaultValue:`Tab`,description:`Tab strip label — shown in the clickable pill at the top`},{name:`id`,type:`string`,required:!1,advanced:!0,description:"HTML id attribute for deep-linking (e.g. `#tab-npm`)"}],mathProps=[{name:`formula`,type:`string`,required:!0,autoFocus:!0,language:`latex`,description:`LaTeX math source (rendered with KaTeX in the browser)`},{name:`id`,type:`string`,required:!1,advanced:!0,description:"HTML id attribute for deep-linking (e.g. `#eq-pythagoras`)"},{name:`language`,type:`string`,required:!1,advanced:!0,description:"Forward-compat hint for the math source language (default `latex`). Reserved for future MathJax / Typst / AsciiMath substrates."}],dollarMathProps=[mathProps[0]],mathFenceProps=[mathProps[0]],mermaidProps=[{name:`chart`,type:`string`,required:!0,autoFocus:!0,language:`mermaid`,description:`Mermaid chart source (graph / flowchart / sequenceDiagram / class / state / etc.)`}],wikiEmbedFileProps=[{name:`alias`,type:`string`,required:!1,defaultValue:``,description:"Display name override (Obsidian alias syntax: `![[file.zip|label]]`)"}],fileProps=[{name:`src`,type:`string`,required:!0,defaultValue:``,description:`File URL`,accept:[`*/*`],autoFocus:!0}],pdfProps=[{name:`src`,type:`string`,required:!0,defaultValue:``,description:`PDF source URL`,accept:ALLOWED_PDF_MIME_TYPES,autoFocus:!0},{name:`title`,type:`string`,required:!1,advanced:!0,description:`Accessible label for the embedded PDF viewer`},{name:`anchor`,type:`string`,required:!1,advanced:!0,description:"PDF viewer parameters as a single URL-fragment string (e.g. `page=3&height=600`)"}],mirrorProps=[{name:`src`,type:`string`,required:!0,description:"Path of the source doc, extension-less (e.g. `api-spec`).",autoFocus:!0},{name:`anchor`,type:`string`,required:!0,description:"Id of the `<MirrorSource>` block within the source doc."}],mirrorSourceProps=[{name:`id`,type:`string`,required:!0,description:"Stable id agents and authors use to reference this block from `<Mirror>` elsewhere.",autoFocus:!0},{name:`children`,type:`reactnode`,required:!0,description:`Block content this MirrorSource owns — paragraphs, callouts, code, nested JSX, anything.`}];function escapeHtmlAttr(e){return e.replace(/&/g,`&`).replace(/"/g,`"`).replace(/</g,`<`).replace(/>/g,`>`)}function escapeHtmlText(e){return e.replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`)}function serializeWikiEmbed(e){let t=e.attrs.props,S=t?.target??``,w=typeof t?.alias==`string`&&t.alias.length>0?t.alias:null,E=typeof t?.anchor==`string`&&t.anchor.length>0?t.anchor:null,D=w??(E?`${S}#${E}`:S);return{type:`wikiLinkEmbed`,value:D,data:{target:S,anchor:E,alias:w},children:[{type:`text`,value:D}]}}const builtInComponents=[{name:`Callout`,surface:`canonical`,hasChildren:!0,props:calloutProps,icon:`MessageSquareWarning`,category:`content`,displayName:`Callout`,description:`Alert / admonition with 15 type variants — 5 GFM (note, tip, important, warning, caution) plus 10 Obsidian-parity (abstract, info, todo, success, question, failure, danger, bug, example, quote)`,searchTerms:[`note`,`tip`,`important`,`warning`,`caution`,`abstract`,`info`,`todo`,`success`,`question`,`failure`,`danger`,`bug`,`example`,`quote`,`alert`,`admonition`,`callout`],serialize:(e,t)=>emitMdxJsx(`Callout`,e,t,calloutProps)},{name:`img`,surface:`canonical`,hasChildren:!1,isSelfClosing:!0,props:htmlImgProps,icon:`Image`,category:`media`,displayName:`Image`,description:`Image with click-to-zoom and HTML-native attributes`,searchTerms:[`image`,`zoom`,`picture`,`photo`],placeholder:{label:`Add an image`},serialize:(e,t)=>emitMdxJsx(`img`,e,t,htmlImgProps)},{name:`video`,surface:`canonical`,hasChildren:!1,isSelfClosing:!0,props:htmlVideoProps,icon:`SquarePlay`,category:`media`,displayName:`Video`,description:`HTML5 video player with native controls`,searchTerms:[`video`,`media`,`player`,`mp4`,`webm`,`movie`],placeholder:{label:`Add a video`},serialize:(e,t)=>emitMdxJsx(`video`,e,t,htmlVideoProps)},{name:`audio`,surface:`canonical`,hasChildren:!1,isSelfClosing:!0,props:htmlAudioProps,icon:`Volume2`,category:`media`,displayName:`Audio`,description:`HTML5 audio player with native controls`,searchTerms:[`audio`,`sound`,`music`,`mp3`,`podcast`,`player`],placeholder:{label:`Add audio`},serialize:(e,t)=>emitMdxJsx(`audio`,e,t,htmlAudioProps)},{name:`Pdf`,surface:`canonical`,hasChildren:!1,isSelfClosing:!0,props:pdfProps,icon:`FileText`,category:`media`,displayName:`PDF`,description:"Embedded PDF viewer (`#page=N` to open at page N, `#height=N` for viewer height)",searchTerms:[`pdf`,`document`,`embed`,`pdfjs`],placeholder:{label:`Add a PDF`},serialize:(e,t)=>emitMdxJsx(`Pdf`,e,t,pdfProps)},{name:`File`,surface:`canonical`,hasChildren:!1,isSelfClosing:!0,props:fileProps,icon:`Paperclip`,category:`media`,displayName:`File`,description:`Downloadable file attachment — inline row with name + size + download link`,searchTerms:[`file`,`attachment`,`download`,`document`,`zip`,`docx`,`doc`],placeholder:{label:`Add a file`},serialize:(e,t)=>emitMdxJsx(`File`,e,t,fileProps)},{name:`Embed`,surface:`canonical`,hasChildren:!1,isSelfClosing:!0,props:embedProps,icon:`AppWindow`,category:`media`,displayName:`Embed`,description:`Inline web embed (iframe) — drop a URL, get a resizable preview pane`,searchTerms:[`embed`,`iframe`,`website`,`page`,`inline`,`frame`,`preview`],placeholder:{label:`Embed a URL`},serialize:(e,t)=>emitMdxJsx(`Embed`,e,t,embedProps)},{name:`Accordion`,surface:`canonical`,hasChildren:!0,props:accordionProps,icon:`ChevronRight`,category:`content`,displayName:`Accordion`,description:"Standalone expand/collapse via native HTML5 <details>/<summary>. Group siblings with the `name` prop for exclusive-accordion UX.",searchTerms:[`toggle`,`accordion`,`expandable`,`details`,`disclosure`,`collapse`,`fold`],exampleBody:`Body content revealed when the accordion is expanded.`,serialize:(e,t)=>emitMdxJsx(`Accordion`,e,t,accordionProps)},{name:`Tabs`,surface:`canonical`,hasChildren:!0,emptyChildName:`Tab`,props:tabsProps,icon:`LayoutPanelTop`,category:`content`,displayName:`Tabs`,description:"Horizontal tab strip + active panel below. Each `<Tab>` child is one panel; clickable pills at the top switch the active one. Active selection is ephemeral (resets on reload).",searchTerms:[`tabs`,`tabbed`,`panels`,`tabgroup`,`switcher`],exampleBody:`<Tab label="One">Body of the first tab panel.</Tab>
|
|
328
328
|
<Tab label="Two">Body of the second tab panel.</Tab>`,serialize:(e,t)=>emitMdxJsx(`Tabs`,e,t,tabsProps)},{name:`Tab`,surface:`canonical`,hasChildren:!0,props:tabProps,icon:`PanelTop`,category:`content`,displayName:`Tab`,description:"A single tab panel inside a `<Tabs>` container — carries the strip label and the block-content body.",searchTerms:[`tab`,`panel`],exampleBody:"Panel content — must be nested inside a `<Tabs>` parent.",serialize:(e,t)=>emitMdxJsx(`Tab`,e,t,tabProps)},{name:`Math`,surface:`canonical`,hasChildren:!1,isSelfClosing:!0,props:mathProps,icon:`Sigma`,category:`content`,displayName:`Math`,description:`Block math equation rendered with KaTeX from a LaTeX source string`,searchTerms:[`math`,`latex`,`equation`,`formula`,`katex`,`tex`],serialize:(e,t)=>emitMdxJsx(`Math`,e,t,mathProps)},{name:`MermaidFence`,surface:`canonical`,hasChildren:!1,isSelfClosing:!0,props:mermaidProps,icon:`Workflow`,category:`content`,displayName:`Mermaid`,description:"Diagram rendered from Mermaid source (flowchart, sequence, class, state, ER, gantt, pie). Authored exclusively as ` ```mermaid ` fenced code.",searchTerms:[`mermaid`,`diagram`,`flowchart`,`graph`,`sequence`,`sequencediagram`,`class`,`state`,`er`,`erdiagram`,`gantt`,`pie`,`chart`],serialize:e=>({type:`code`,lang:`mermaid`,meta:null,value:e.attrs.props?.chart??``})},{name:`Mirror`,surface:`canonical`,hasChildren:!1,isSelfClosing:!0,props:mirrorProps,icon:`CopyPlus`,category:`content`,displayName:`Mirror`,description:"Render a read-only copy of a `<MirrorSource>` block from another doc. Use to keep the same content in sync across multiple docs without copy-paste — edits land at the source, every Mirror reflects the change.",searchTerms:[`mirror`,`sync`,`synced`,`transclude`,`embed`,`reference`,`shared block`],serialize:(e,t)=>emitMdxJsx(`Mirror`,e,t,mirrorProps)},{name:`MirrorSource`,surface:`canonical`,hasChildren:!0,props:mirrorSourceProps,icon:`GitBranch`,category:`content`,displayName:`Mirror Source`,description:'Mark a block as the source of truth for content that appears in multiple docs. Wrap any block content; `<Mirror src="…" anchor="<id>">` references render this verbatim read-only at every call-site. Edit here, propagate everywhere.',searchTerms:[`mirror source`,`sync source`,`source block`,`master block`,`shared`],exampleBody:"Authoritative content lives inside this block — edits here propagate to every `<Mirror>` that references this id.",serialize:(e,t)=>emitMdxJsx(`MirrorSource`,e,t,mirrorSourceProps)},{name:`GFMCallout`,surface:`compat`,hasChildren:!0,props:gfmCalloutProps,icon:`MessageSquareWarning`,category:`content`,displayName:`GFM Callout`,description:"GFM blockquote alert (`> [!NOTE]`) — read-only compat. Preserves `> [!NOTE]` syntax on round-trip; insert a fresh Callout block for the full prop surface.",rendersAs:`Callout`,translateProps:e=>e,serialize:(e,t)=>{let S=e.attrs.props,w=new Set([`note`,`tip`,`important`,`warning`,`caution`,`abstract`,`info`,`todo`,`success`,`question`,`failure`,`danger`,`bug`,`example`,`quote`]),E=S?.type??`note`;return{type:`blockquote`,children:[{type:`html`,value:`[!${(w.has(E.toLowerCase())?E:`note`).toUpperCase()}]${S?.collapsible?S.defaultOpen===!1?`-`:`+`:``}${S?.title?` ${S.title}`:``}`},...t.all(e).filter(e=>{if(e.type!==`paragraph`)return!0;let t=e;return Array.isArray(t.children)&&t.children.length>0})]}}},{name:`CommonMarkImage`,surface:`compat`,hasChildren:!1,isSelfClosing:!0,props:commonMarkImageProps,icon:`Image`,category:`media`,displayName:`CommonMark Image`,description:'CommonMark image (``) — read-only compat. Preserves `` syntax on round-trip; insert a fresh Image block for the full HTML-native attribute surface (srcset, sizes, decoding, etc.).',rendersAs:`img`,translateProps:e=>e,serialize:e=>{let t=e.attrs.props;return{type:`paragraph`,children:[{type:`image`,url:t?.sourceUrl??t?.src??``,alt:t?.alt??``,title:t?.title??null}]}}},{name:`WikiEmbedImage`,surface:`compat`,hasChildren:!1,isSelfClosing:!0,props:wikiEmbedImageProps,icon:`ZoomIn`,category:`media`,displayName:`Wiki Embed Image`,description:"Obsidian-style `![[file.png]]` wiki-embed — read-only compat. Edit the alt-text via the alias slot; the embed target / anchor stay on the prop bag and round-trip byte-identical.",rendersAs:`img`,translateProps:e=>{let t=typeof e.alias==`string`&&e.alias.length>0?e.alias:null,S=typeof e.target==`string`?e.target:``;return{src:e.src,alt:t??S}},serialize:serializeWikiEmbed},{name:`WikiEmbedVideo`,surface:`compat`,hasChildren:!1,isSelfClosing:!0,props:wikiEmbedVideoProps,icon:`Film`,category:`media`,displayName:`Wiki Embed Video`,description:"Obsidian-style `![[clip.mp4]]` wiki-embed — read-only compat. Edit the title via the alias slot; the embed target / anchor stay on the prop bag and round-trip byte-identical.",rendersAs:`video`,translateProps:e=>{let t=typeof e.alias==`string`&&e.alias.length>0?e.alias:null,S=typeof e.target==`string`?e.target:``;return{src:e.src,title:t??S}},serialize:serializeWikiEmbed},{name:`WikiEmbedAudio`,surface:`compat`,hasChildren:!1,isSelfClosing:!0,props:wikiEmbedAudioProps,icon:`Volume2`,category:`media`,displayName:`Wiki Embed Audio`,description:"Obsidian-style `![[song.mp3]]` wiki-embed — read-only compat. Edit the title via the alias slot; the embed target / anchor stay on the prop bag and round-trip byte-identical.",rendersAs:`audio`,translateProps:e=>{let t=typeof e.alias==`string`&&e.alias.length>0?e.alias:null,S=typeof e.target==`string`?e.target:``;return{src:e.src,title:t??S}},serialize:serializeWikiEmbed},{name:`WikiEmbedFile`,surface:`compat`,hasChildren:!1,isSelfClosing:!0,props:wikiEmbedFileProps,icon:`Paperclip`,category:`media`,displayName:`Wiki Embed File`,description:"Obsidian-style `![[file.zip]]` wiki-embed — read-only compat for arbitrary downloadable attachments. Renders through the `File` canonical (inline row with file-up icon + bold name + optional dim size). Edit the display name via the alias slot.",rendersAs:`File`,translateProps:e=>{let t=typeof e.alias==`string`&&e.alias.length>0?e.alias:null,S=typeof e.size==`string`&&e.size.length>0?e.size:null;return{src:e.src,name:t??void 0,size:S??void 0}},serialize:serializeWikiEmbed},{name:`HtmlDetailsAccordion`,surface:`compat`,hasChildren:!0,props:htmlDetailsAccordionProps,icon:`ChevronRight`,category:`content`,displayName:`HTML5 Details`,description:"HTML5 `<details><summary>` collapsible — read-only compat. Preserves `<details>` syntax on round-trip; insert a fresh Accordion block for icon / description / group-name props.",rendersAs:`Accordion`,translateProps:e=>e,serialize:(e,t)=>{let S=e.attrs.props,w=S?.defaultOpen?` open`:``,E=S?.name?` name="${escapeHtmlAttr(S.name)}"`:``,D=S?.id?` id="${escapeHtmlAttr(S.id)}"`:``,O=S?.title?.trim(),k=O?`<summary>${escapeHtmlText(O)}</summary>`:``;return{type:`mdxJsxFlowElement`,name:`HtmlDetailsAccordion`,attributes:[],children:t.all(e),data:{htmlBoundary:{opener:`<details${w}${E}${D}>\n${k}`,closer:`</details>`}}}}},{name:`DollarMath`,surface:`compat`,hasChildren:!1,isSelfClosing:!0,props:dollarMathProps,icon:`Sigma`,category:`content`,displayName:`Dollar Math`,description:"Block math via `$$…$$` syntax — read-only compat. Preserves `$$…$$` form on round-trip; insert a fresh Math block for the full prop surface (id, language).",rendersAs:`Math`,translateProps:e=>e,serialize:e=>({type:`math`,value:e.attrs.props?.formula??``})},{name:`MathFence`,surface:`compat`,hasChildren:!1,isSelfClosing:!0,props:mathFenceProps,icon:`Sigma`,category:`content`,displayName:`Math Fence`,description:"Block math via ` ```math ` fenced code syntax — read-only compat. Preserves the fence form on round-trip; insert a fresh Math block for the full prop surface (id, language).",rendersAs:`Math`,translateProps:e=>e,serialize:e=>({type:`code`,lang:`math`,meta:null,value:e.attrs.props?.formula??``})}],wildcardMeta={name:`*`,surface:`canonical`,hasChildren:!0,props:[],description:`Unregistered component — children editable as markdown`,serialize:(e,t)=>emitMdxJsx(e.attrs.componentName||`*`,e,t)};function createRegistry(){let e=new Map;e.set(`*`,wildcardMeta);for(let t of builtInComponents)e.set(t.name,t);return{get(t){return e.get(t)},getOrWildcard(t){return e.get(t)??e.get(`*`)},set(t,S){e.set(t,S)},has(t){return e.has(t)},entries(){return e.entries()}}}function ypsCounters(){let e=globalThis;return e.__okYpsCounters||={block:0,inline:0},e.__okYpsCounters}const metrics={parseFallback:{blockLevel:0,wholeDoc:0},jsxRenderFailure:{},jsxAutoConvertFailed:{},jsxAutoConvertSucceeded:{},jsxPropDropped:{},jsxMoveFailed:{},jsxStuckCopyFailed:{},jsxStuckDeleteFailed:{},jsxPopoverCloseRestoreFailed:{},jsxKeyboardDeleteFailed:{},blockGripClickSelectFailed:{},jsxArrowNodeSelectFailed:{}};function incrementBlockFallback(){metrics.parseFallback.blockLevel++}function incrementWholeDocFallback(){metrics.parseFallback.wholeDoc++}function getParseHealth(){let e=ypsCounters();return{parseFallback:{...metrics.parseFallback},ypsMismatch:{block:e.block,inline:e.inline},jsxRenderFailure:{...metrics.jsxRenderFailure},jsxAutoConvertFailed:{...metrics.jsxAutoConvertFailed},jsxAutoConvertSucceeded:{...metrics.jsxAutoConvertSucceeded},jsxPropDropped:{...metrics.jsxPropDropped},jsxMoveFailed:{...metrics.jsxMoveFailed},jsxStuckCopyFailed:{...metrics.jsxStuckCopyFailed},jsxStuckDeleteFailed:{...metrics.jsxStuckDeleteFailed},jsxPopoverCloseRestoreFailed:{...metrics.jsxPopoverCloseRestoreFailed},jsxKeyboardDeleteFailed:{...metrics.jsxKeyboardDeleteFailed},blockGripClickSelectFailed:{...metrics.blockGripClickSelectFailed},jsxArrowNodeSelectFailed:{...metrics.jsxArrowNodeSelectFailed}}}const FENCE_RE=/^(`{3,}|~{3,})/gm;function findFencedRegions(e){let t=[],S=null;for(let w of e.matchAll(FENCE_RE)){let e=w[1],E=w.index;S?e[0]===S.marker[0]&&e.length>=S.marker.length&&(t.push([S.offset,E+w[0].length]),S=null):S={marker:e,offset:E}}return S&&t.push([S.offset,e.length]),t}function isInsideFence(e,t){return t.some(([t,S])=>e>=t&&e<S)}const REF_DEF_RE=/^[ \t]{0,3}\[([^\]]+)\]:\s*(\S+)(\s+(?:"[^"]*"|'[^']*'|\([^)]*\)))?\s*$/gm;function hoistRefDefs(e){let t=findFencedRegions(e),S=[];for(let w of e.matchAll(REF_DEF_RE))isInsideFence(w.index,t)||S.push(w[0].trimEnd());return S.length>0?`${S.join(`
|
|
329
329
|
`)}\n\n`:``}const MAX_PARSE_WALLCLOCK_MS=500,MAX_TOTAL_PARSE_CALLS=1e3;function parseWithFallback(e,t){let S={startMs:typeof performance<`u`&&typeof performance.now==`function`?performance.now():Date.now(),calls:0};return parseRecursive(e,t.parse,0,S)}function budgetExhausted(e){return e.calls>=MAX_TOTAL_PARSE_CALLS?!0:(typeof performance<`u`&&typeof performance.now==`function`?performance.now():Date.now())-e.startMs>=MAX_PARSE_WALLCLOCK_MS}const MAX_ERROR_MESSAGE_LEN=500;function errorPayload(e){return e instanceof Error?{name:e.name,message:e.message.slice(0,MAX_ERROR_MESSAGE_LEN),stack:e.stack?.split(`
|
|
330
330
|
`).slice(0,4).join(`
|
|
@@ -342,7 +342,7 @@ $2`).split(`
|
|
|
342
342
|
`;)S--;let w=!1;for(let e=S;e<E;e++)if(t[e]===`>`){w=!0;break}let O=t.slice(E,D).split(`
|
|
343
343
|
`),k=[];for(let e=0;e<O.length;e++){let t=O[e];if(t.length===0)continue;if(w&&e>0)break;let S=t.replace(/^ {1,3}/,``);if(S[0]!==`>`||S.slice(1).trimEnd()===``)continue;let E=S[1];E===` `||E===` `?k.push(`single`):k.push(`none`)}k.length>0&&(e.data.sourceMarkerSpacings=k);break}case`list`:{let S=e.children?.[0];if(S?.position?.start?.offset!=null){let w=S.position.start.offset;if(w>=0&&w<t.length){let S=t[w];if(!e.ordered&&(S===`-`||S===`*`||S===`+`))e.data.bulletMarker=S;else if(e.ordered){let S=t.slice(w,Math.min(w+10,t.length)).match(/^\d+([.)])/);S&&(e.data.listMarkerDelimiter=S[1])}}}break}case`code`:{let S=t[E];if(S==="`"||S===`~`){e.data.sourceStyle=`fenced`,e.data.sourceFenceChar=S;let w=0;for(;E+w<t.length&&t[E+w]===S;)w++;w>=3&&(e.data.sourceFenceLength=w)}else e.data.sourceStyle=`indented`;break}case`inlineCode`:{let S=t[E];if(S==="`"||S===`~`){e.data.sourceFenceChar=S;let w=0;for(;E+w<t.length&&t[E+w]===S;)w++;w>=1&&(e.data.sourceFenceLength=w)}break}case`thematicBreak`:e.data.sourceRaw=t.slice(E,D);break;case`table`:{let S=t.slice(E,D),w=S.indexOf(`
|
|
344
344
|
`);if(w===-1)break;let O=S.slice(w+1),k=O.indexOf(`
|
|
345
|
-
`),j=(k===-1?O:O.slice(0,k)).trim().replace(/^\|/,``).replace(/\|$/,``).split(`|`),F=[];for(let e of j){let t=e.match(/-/g);F.push(t?t.length:0)}F.
|
|
345
|
+
`),j=(k===-1?O:O.slice(0,k)).trim().replace(/^\|/,``).replace(/\|$/,``).split(`|`),F=[];for(let e of j){let t=e.match(/-/g);F.push(t?t.length:0)}F.some(e=>e>0)&&(e.data.sourceDashCounts=F);for(let S of e.children??[]){if(S.type!==`tableRow`||!S.position)continue;let e=S.position.start.offset,w=S.position.end.offset;if(typeof e!=`number`||typeof w!=`number`)continue;let E=t.slice(e,w),D=E.indexOf(`
|
|
346
346
|
`);D!==-1&&(E=E.slice(0,D));let O=splitGfmCellSegments(E);O.length>0&&O[0]===``&&E.startsWith(`|`)&&O.shift(),O.length>0&&O[O.length-1]===``&&E.endsWith(`|`)&&O.pop();let k=S.children??[],j=Math.min(k.length,O.length);for(let e=0;e<j;e++){let t=k[e];if(t.type!==`tableCell`)continue;let S=O[e],w=0;for(;w<S.length&&S[w]===` `;)w++;let E=0;for(;E<S.length-w&&S[S.length-1-E]===` `;)E++;t.data||={},t.data.sourcePadding={left:w,right:E}}}break}case`link`:case`linkReference`:if(`children`in e&&e.children.length===0&&(e.data.sourceRaw=t.slice(E,D)),e.type===`link`){let S=t[E];if(S!==`[`&&S!==`<`&&!e.title)e.data.sourceStyle=`gfm-autolink`;else if(S===`[`){let S=t.slice(E,D),w=S.lastIndexOf(`](`);if(w!==-1){let t=w+2;for(;t<S.length&&(S[t]===` `||S[t]===` `);)t++;if(S[t]===`<`&&(e.data.sourceUrlForm=`angle-bracketed`),e.title!==void 0&&e.title!==null&&S[S.length-1]===`)`){let t=S.length-2;for(;t>w+1&&(S[t]===` `||S[t]===` `||S[t]===`
|
|
347
347
|
`);)t--;S[t]===`"`?e.data.sourceTitleMarker=`double`:S[t]===`'`?e.data.sourceTitleMarker=`single`:S[t]===`)`&&(e.data.sourceTitleMarker=`paren`)}}}}break;case`definition`:{let S=t.slice(E,D);if(e.data.sourceLayout=S.includes(`
|
|
348
348
|
`)?`multiline`:`inline`,typeof e.title==`string`&&S.length>0){let t=S[S.length-1];t===`"`?e.data.sourceTitleMarker=`double`:t===`'`?e.data.sourceTitleMarker=`single`:t===`)`&&(e.data.sourceTitleMarker=`paren`)}break}case`mdxJsxFlowElement`:case`mdxJsxTextElement`:case`mdxFlowExpression`:case`mdxTextExpression`:e.data.sourceRaw=t.slice(E,D);break;case`break`:t.slice(E,D).includes(`\\`)?e.data.sourceStyle=`backslash`:e.data.sourceStyle=`spaces`;break}}const TAG_IN_TEXT_PATTERN_SOURCE=`(^|\\s)#([a-zA-Z][\\w/-]*)`;function createTagInTextRegex(){return new RegExp(TAG_IN_TEXT_PATTERN_SOURCE,`g`)}const TAG_IN_TEXT_RE=createTagInTextRegex();function isEscapedHash(e,t){if(t<=0||e[t-1]!==`\\`)return!1;let S=t-1,w=0;for(;S>=0&&e[S]===`\\`;)w++,S--;return w%2==1}function promoteTagsInParent(e,t=``){let S=[],w=!1;for(let E of e.children){if(E.type!==`text`){S.push(E);continue}let e=E.value,D=typeof E.position?.start?.offset==`number`?E.position?.start?.offset??0:0;TAG_IN_TEXT_RE.lastIndex=0;let O=[],k=0;for(;;){let S=TAG_IN_TEXT_RE.exec(e);if(S===null)break;let E=S[1]??``,j=S[2]??``,F=S.index+E.length;if(t&&D>=0){let S=D,w=0,E=-1;for(;w<=F&&S<t.length;){let D=t[S]===`\\`&&S+1<t.length&&e[w]===t[S+1],O=D?S+1:S;if(w===F){E=O;break}S=D?S+2:S+1,w+=1}if(E>=0&&isEscapedHash(t,E))continue}F>k&&O.push({type:`text`,value:e.slice(k,F)});let L={type:`tag`,value:j};O.push(L),k=F+1+j.length,w=!0}O.length===0?S.push(E):(k<e.length&&O.push({type:`text`,value:e.slice(k)}),S.push(...O))}w&&(e.children=S)}const KNOWN_MDAST_TYPES=new Set(`root.paragraph.heading.text.emphasis.strong.blockquote.list.listItem.code.inlineCode.link.image.linkReference.imageReference.definition.html.thematicBreak.break.yaml.toml.table.tableRow.tableCell.delete.footnoteDefinition.footnoteReference.mdxFlowExpression.mdxJsxFlowElement.mdxJsxTextElement.mdxTextExpression.wikiLink.wikiLinkEmbed.tag.math.inlineMath.mark.comment.commentBlock.rawMdxFallbackMdast`.split(`.`));function toRawMdxFallbackMdast(e,t){let S=e.position?.start?.offset??0,w=e.position?.end?.offset??0,E=w>S?t.slice(S,w):``;return{type:`rawMdxFallbackMdast`,originalType:e.type??`unknown`,value:E||(e.type??`unknown`),position:e.position}}function mergedPostParseWalkerPlugin(){return(e,t)=>{let S=typeof t.value==`string`?t.value:``;applyDocStartThematicFix(e,t);let w=typeof process<`u`&&process.env?.OK_DEBUG_POSITION_SLICE===`1`;visit$1(e,(e,t,E)=>{if(E!==void 0&&typeof t==`number`&&typeof e.type==`string`&&!KNOWN_MDAST_TYPES.has(e.type)){let w=toRawMdxFallbackMdast(e,S);return E.children[t]=w,SKIP$1}if(`children`in e&&Array.isArray(e.children)){let t=e;t.children.some(e=>e.type===`text`)&&(promoteInParent(t),promoteTagsInParent(t,S))}if(applyPositionSliceToNode(e,S,w),e.type===`heading`&&E!==void 0&&typeof t==`number`&&e.data?.sourceStyle===`setext`){let S=e.position?.end?.line,w=E.children[t+1],D=w?.position?.start?.line;if(w?.type===`paragraph`&&typeof S==`number`&&typeof D==`number`&&D===S+1){let t=e;t.data??={},t.data.sourceContiguousNext=!0}}})}}function buildMermaidFenceElement(e,t){let S={type:`mdxJsxFlowElement`,name:`MermaidFence`,attributes:[{type:`mdxJsxAttribute`,name:`chart`,value:e}],children:[]};return t&&(S.position=t),S}function mermaidPromoterPlugin(){return e=>{visit$1(e,`code`,(e,t,S)=>{if(!S||t==null||e.lang!==`mermaid`)return;let w=buildMermaidFenceElement(typeof e.value==`string`?e.value:``,e.position);S.children[t]=w})}}function isContiguousSetextWithParagraph(e,t){let S=e,w=t;return S.type===`heading`&&S.data?.sourceContiguousNext===!0&&w.type===`paragraph`}const positionAwareBlankLineJoin=(e,t)=>{if(isContiguousSetextWithParagraph(e,t))return 0;let S=e.position,w=t.position;if(!S||!w)return;let E=w.start.line-S.end.line-1;return E>=1?E:void 0},MICROMARK_EXT$1=mdx(),FROM_MARKDOWN_EXT=mdxFromMarkdown(),TO_MARKDOWN_EXT=mdxToMarkdown();function remarkMdxAgnostic(){let e=this.data();e.micromarkExtensions||=[],e.fromMarkdownExtensions||=[],e.toMarkdownExtensions||=[];let t=e.micromarkExtensions;t.some(e=>e===MICROMARK_EXT$1)||t.push(MICROMARK_EXT$1);let S=e.fromMarkdownExtensions;S.some(e=>e===FROM_MARKDOWN_EXT)||S.push(FROM_MARKDOWN_EXT);let w=e.toMarkdownExtensions;w.some(e=>e===TO_MARKDOWN_EXT)||w.push(TO_MARKDOWN_EXT)}const SINGLE_DOLLAR_MATH_RE=/(?<!\\)\$(?=\S)([^$\n]*?[^\s$])\$(?!\d)/g;function singleDollarMathPromoterPlugin(){return e=>{visit$1(e,`text`,(e,t,S)=>{if(S===void 0||t==null)return;let w=e.value;if(w.indexOf(`$`)===-1)return;SINGLE_DOLLAR_MATH_RE.lastIndex=0;let E=[],D;for(;(D=SINGLE_DOLLAR_MATH_RE.exec(w))!==null;)E.push(D);if(E.length===0)return;let O=[],k=0;for(let e of E){let t=e.index,S=t+e[0].length;if(t>k){let e={type:`text`,value:w.slice(k,t)};O.push(e)}let E={type:`inlineMath`,value:e[1]};O.push(E),k=S}if(k<w.length){let e={type:`text`,value:w.slice(k)};O.push(e)}return S.children.splice(t,1,...O),[SKIP$1,t+O.length]})}}const tagHandler$1=e=>`#${e.value}`,tagToMarkdown={handlers:{tag:tagHandler$1},unsafe:[{character:`#`,inConstruct:[`phrasing`],before:`\\s`,after:`[a-zA-Z]`}]};function remarkTags(){let e=this.data();e.toMarkdownExtensions||=[],e.toMarkdownExtensions.some(e=>e===tagToMarkdown)||e.toMarkdownExtensions.push(tagToMarkdown)}const CODE_BANG=33,CODE_LBRACKET=91,CODE_RBRACKET=93,CODE_PIPE=124,CODE_HASH=35,tokenizeWikiLink=(e,t,S)=>{let w=0,E=0,D=0;return O;function O(t){return t===CODE_LBRACKET?(e.enter(`wikiLink`),e.enter(`wikiLinkMarker`),e.consume(t),k):S(t)}function k(t){return t===CODE_LBRACKET?(e.consume(t),e.exit(`wikiLinkMarker`),e.enter(`wikiLinkTarget`),j):S(t)}function j(t){return t===null||t===-5||t===-4||t===-3||t===CODE_LBRACKET?S(t):t===CODE_RBRACKET?w===0?S(t):(e.exit(`wikiLinkTarget`),B(t)):t===CODE_HASH?w===0?S(t):(e.exit(`wikiLinkTarget`),e.enter(`wikiLinkSeparator`),e.consume(t),e.exit(`wikiLinkSeparator`),e.enter(`wikiLinkAnchor`),F):t===CODE_PIPE?w===0?S(t):(e.exit(`wikiLinkTarget`),e.enter(`wikiLinkSeparator`),e.consume(t),e.exit(`wikiLinkSeparator`),e.enter(`wikiLinkAlias`),L):(e.consume(t),w++,j)}function F(t){return t===null||t===-5||t===-4||t===-3||t===CODE_LBRACKET?S(t):t===CODE_RBRACKET?E===0?S(t):(e.exit(`wikiLinkAnchor`),B(t)):t===CODE_PIPE?E===0?S(t):(e.exit(`wikiLinkAnchor`),e.enter(`wikiLinkSeparator`),e.consume(t),e.exit(`wikiLinkSeparator`),e.enter(`wikiLinkAlias`),L):(e.consume(t),E++,F)}function L(t){return t===null||t===-5||t===-4||t===-3||t===CODE_LBRACKET?S(t):t===CODE_RBRACKET?D===0?S(t):(e.exit(`wikiLinkAlias`),B(t)):(e.consume(t),D++,L)}function B(t){return t===CODE_RBRACKET?(e.enter(`wikiLinkMarker`),e.consume(t),H):S(t)}function H(w){return w===CODE_RBRACKET?(e.consume(w),e.exit(`wikiLinkMarker`),e.exit(`wikiLink`),t):S(w)}},wikiLinkConstruct={name:`wikiLink`,tokenize:tokenizeWikiLink},tokenizeWikiLinkEmbed=(e,t,S)=>{let w=0,E=0,D=0;return O;function O(t){return t===CODE_BANG?(e.enter(`wikiLinkEmbed`),e.enter(`wikiLinkEmbedBang`),e.consume(t),e.exit(`wikiLinkEmbedBang`),k):S(t)}function k(t){return t===CODE_LBRACKET?(e.enter(`wikiLinkMarker`),e.consume(t),j):S(t)}function j(t){return t===CODE_LBRACKET?(e.consume(t),e.exit(`wikiLinkMarker`),e.enter(`wikiLinkTarget`),F):S(t)}function F(t){return t===null||t===-5||t===-4||t===-3||t===CODE_LBRACKET?S(t):t===CODE_RBRACKET?w===0?S(t):(e.exit(`wikiLinkTarget`),H(t)):t===CODE_HASH?w===0?S(t):(e.exit(`wikiLinkTarget`),e.enter(`wikiLinkSeparator`),e.consume(t),e.exit(`wikiLinkSeparator`),e.enter(`wikiLinkAnchor`),L):t===CODE_PIPE?w===0?S(t):(e.exit(`wikiLinkTarget`),e.enter(`wikiLinkSeparator`),e.consume(t),e.exit(`wikiLinkSeparator`),e.enter(`wikiLinkAlias`),B):(e.consume(t),w++,F)}function L(t){return t===null||t===-5||t===-4||t===-3||t===CODE_LBRACKET?S(t):t===CODE_RBRACKET?E===0?S(t):(e.exit(`wikiLinkAnchor`),H(t)):t===CODE_PIPE?E===0?S(t):(e.exit(`wikiLinkAnchor`),e.enter(`wikiLinkSeparator`),e.consume(t),e.exit(`wikiLinkSeparator`),e.enter(`wikiLinkAlias`),B):(e.consume(t),E++,L)}function B(t){return t===null||t===-5||t===-4||t===-3||t===CODE_LBRACKET?S(t):t===CODE_RBRACKET?D===0?S(t):(e.exit(`wikiLinkAlias`),H(t)):(e.consume(t),D++,B)}function H(t){return t===CODE_RBRACKET?(e.enter(`wikiLinkMarker`),e.consume(t),q):S(t)}function q(w){return w===CODE_RBRACKET?(e.consume(w),e.exit(`wikiLinkMarker`),e.exit(`wikiLinkEmbed`),t):S(w)}},wikiLinkEmbedConstruct={name:`wikiLinkEmbed`,tokenize:tokenizeWikiLinkEmbed};function wikiLinkSyntax(){return{text:{[CODE_LBRACKET]:wikiLinkConstruct,[CODE_BANG]:wikiLinkEmbedConstruct}}}function enterWikiLink(e){this.enter({type:`wikiLink`,value:``,data:{target:``,anchor:null,alias:null},children:[]},e)}function enterWikiLinkEmbed(e){this.enter({type:`wikiLinkEmbed`,value:``,data:{target:``,anchor:null,alias:null},children:[]},e)}function topNode(e){return e.stack[e.stack.length-1]}function exitTarget(e){let t=topNode(this);t.data.target=this.sliceSerialize(e).trim()}function exitAnchor(e){let t=topNode(this),S=this.sliceSerialize(e).trim();t.data.anchor=S.length?S:null}function exitAlias(e){let t=topNode(this),S=this.sliceSerialize(e).trim();t.data.alias=S.length?S:null}function finalizeLabel(e){let{target:t,anchor:S,alias:w}=e.data,E=w||(S?`${t}#${S}`:t);e.value=E,e.children=[{type:`text`,value:E}]}function exitWikiLink(e){finalizeLabel(topNode(this)),this.exit(e)}function exitWikiLinkEmbed(e){finalizeLabel(topNode(this)),this.exit(e)}const wikiLinkFromMarkdown={enter:{wikiLink:enterWikiLink,wikiLinkEmbed:enterWikiLinkEmbed},exit:{wikiLinkTarget:exitTarget,wikiLinkAnchor:exitAnchor,wikiLinkAlias:exitAlias,wikiLink:exitWikiLink,wikiLinkEmbed:exitWikiLinkEmbed}},wikiLinkHandler$1=e=>{let t=e,S=t.data?.target??``,w=t.data?.anchor,E=t.data?.alias,D=`[[${S}`;return w&&(D+=`#${w}`),E&&(D+=`|${E}`),`${D}]]`},wikiLinkEmbedHandler$1=e=>{let t=e,S=t.data?.target??``,w=t.data?.anchor,E=t.data?.alias,D=`![[${S}`;return w&&(D+=`#${w}`),E&&(D+=`|${E}`),`${D}]]`},wikiLinkToMarkdown={handlers:{wikiLink:wikiLinkHandler$1,wikiLinkEmbed:wikiLinkEmbedHandler$1},unsafe:[{character:`[`,inConstruct:[`phrasing`]}]},MICROMARK_EXT=wikiLinkSyntax();function remarkWikiLink(){let e=this.data();e.micromarkExtensions||=[],e.micromarkExtensions.some(e=>e===MICROMARK_EXT)||e.micromarkExtensions.push(MICROMARK_EXT),e.fromMarkdownExtensions||=[],e.fromMarkdownExtensions.some(e=>e===wikiLinkFromMarkdown)||e.fromMarkdownExtensions.push(wikiLinkFromMarkdown),e.toMarkdownExtensions||=[],e.toMarkdownExtensions.some(e=>e===wikiLinkToMarkdown)||e.toMarkdownExtensions.push(wikiLinkToMarkdown)}function ensureNonEmptyDoc(e){return e.children.some(e=>{let t=e.type;return t!==`yaml`&&t!==`toml`})?e:{...e,children:[...e.children,{type:`paragraph`,children:[]}]}}const ACTIVE_MDAST_PLUGINS=[{name:`remark-parse`,plugin:remarkParse},{name:`remark-frontmatter`,plugin:remarkFrontmatter,options:[`yaml`]},{name:`remark-mdx-agnostic`,plugin:remarkMdxAgnostic},{name:`remark-gfm`,plugin:remarkGfm},{name:`remark-math`,plugin:remarkMath,options:{singleDollarTextMath:!1}},{name:`remark-wiki-link`,plugin:remarkWikiLink},{name:`remark-github-alerts`,plugin:remarkGithubAlerts,options:REMARK_GITHUB_ALERTS_OPTIONS},{name:`callout-transformer`,plugin:calloutTransformerPlugin},{name:`restore-from-mdx`,plugin:restoreFromMdx},{name:`restore-entity-refs`,plugin:restoreEntityRefsPlugin},{name:`restore-backslash-escapes`,plugin:restoreBackslashEscapesPlugin},{name:`details-accordion-promoter`,plugin:detailsAccordionPromoterPlugin},{name:`image-promoter`,plugin:imagePromoterPlugin},{name:`indented-code-promoter`,plugin:indentedCodePromoterPlugin},{name:`math-promoter`,plugin:mathPromoterPlugin},{name:`single-dollar-math-promoter`,plugin:singleDollarMathPromoterPlugin},{name:`highlight-promoter`,plugin:highlightPromoterPlugin},{name:`mermaid-promoter`,plugin:mermaidPromoterPlugin},{name:`comment-promoter`,plugin:commentPromoterPlugin},{name:`merged-post-parse-walker`,plugin:mergedPostParseWalkerPlugin},{name:`ensure-non-empty-doc`,plugin:()=>ensureNonEmptyDoc}];function createParseProcessor(e){let t=unified();for(let e of ACTIVE_MDAST_PLUGINS)t=`options`in e&&e.options!==void 0?t.use(e.plugin,e.options):t.use(e.plugin);return t=t.use(remarkProseMirror,{schema:e.schema,handlers:e.handlers}),t.freeze(),t}function createSerializeProcessor(e){let t=unified().use(remarkFrontmatter,[`yaml`]).use(remarkGfm,{tablePipeAlign:!1}).use(remarkMath,{singleDollarTextMath:!1}).use(remarkMdxAgnostic).use(remarkWikiLink).use(remarkTags).use(remarkStringify,{bullet:`-`,fences:!0,rule:`-`,join:[positionAwareBlankLineJoin],...e.toMarkdownHandlers?{handlers:e.toMarkdownHandlers}:{}});return t.freeze(),t}function parseMd(e,t){let S=new VFile(encodeEntityRefs(protectFromMdx(encodeBackslashEscapes(e)))),w=t.parse(S);S.value=e;let E=t.runSync(w,S);return t.stringify(E)}function parseMdToMdast(e,t){let S=new VFile(encodeEntityRefs(protectFromMdx(encodeBackslashEscapes(e)))),w=t.parse(S);return S.value=e,t.runSync(w,S)}function serializeMd(e,t,S){let w=fromProseMirror(e,{schema:S.schema,nodeHandlers:S.pmNodeHandlers,markHandlers:S.pmMarkHandlers});return String(t.stringify(w))}function isDevDiagnosticContext(){return typeof process>`u`||!process.env?!1:process.env.NODE_ENV===`development`||process.env.NODE_ENV===`test`}function posixDirname(e){let t=e.lastIndexOf(`/`);return t===-1?``:t===0?`/`:e.slice(0,t)}function posixNormalizeJoin(e,t){let S=e?`${e}/${t}`:t,w=S.startsWith(`/`),E=[];for(let e of S.split(`/`))if(!(e===``||e===`.`)){if(e===`..`){let e=E[E.length-1];E.length>0&&e!==`..`?E.pop():w||E.push(`..`);continue}E.push(e)}let D=E.join(`/`);return w?`/${D}`:D}function normalizeDocRelativeAssetUrl(e,t){if(typeof e!=`string`||e===``||!t||e.startsWith(`/`)||!isRelativeUrl(e))return e;let S=posixNormalizeJoin(posixDirname(t),e);return S===``||S===`..`||S.startsWith(`../`)?(isDevDiagnosticContext()&&console.warn(`[resolve-image-url] doc-relative path escapes contentDir; emitting raw URL: ${e} (from sourcePath ${t})`),e):`/${S}`}const toMarkdownHandlers={text(e,t,S,w){if(typeof e.data?.sourceRaw==`string`&&isValidSourceLiteralRaw(e.data.sourceRaw,e.value??``))return e.data.sourceRaw;if(e.data?.escapedChars?.length){let t=e.value??``,E=e.data.escapedChars,D=``,O=0;for(let{offset:e,char:k}of E)e>O&&(D+=safeText(S,t.slice(O,e),w)),D+=`\\${k}`,O=e+1;return O<t.length&&(D+=safeText(S,t.slice(O),w)),D}return safeText(S,(e.value??``).replaceAll(`\xA0`,` `),w)},emphasis(e,t,S,w){let E=e.data?.sourceDelimiter??`*`,D=S.createTracker(w),O=S.enter(`emphasis`),k=D.move(E);return k+=S.containerPhrasing(e,{before:k,after:E,...D.current()}),k+=D.move(E),O(),k},strong(e,t,S,w){let E=e.data?.sourceDelimiter??`**`,D=S.createTracker(w),O=S.enter(`strong`),k=D.move(E);return k+=S.containerPhrasing(e,{before:k,after:E,...D.current()}),k+=D.move(E),O(),k},link(e,t,S,w){if(e.data?.sourceStyle===`autolink`)return`<${e.url??``}>`;if(e.data?.sourceStyle===`gfm-autolink`){let t=e.children?.length===1?e.children[0]:null;if(t?.type===`text`&&typeof t.value==`string`)return t.value}let E=S.createTracker(w),D=S.enter(`link`),O=S.enter(`label`),k=E.move(`[`);k+=E.move(S.containerPhrasing(e,{before:k,after:`](`,...E.current()})),k+=E.move(`](`),O();let j=S.enter(`destinationRaw`),F=String(e.url??``),L=e.data?.sourceUrlForm===`angle-bracketed`,B=F.startsWith(`<`)&&F.endsWith(`>`),H=L&&!B?`<${F}>`:formatLinkUrl(F);if(k+=E.move(H),j(),e.title){let t=e.data?.sourceTitleMarker??`double`;k+=E.move(emitLinkTitle(e.title,t))}return k+=E.move(`)`),D(),k},image(e,t,S,w){let E=S.createTracker(w),D=S.enter(`image`),O=S.enter(`label`),k=E.move(`})),k+=E.move(`](`),O();let j=S.enter(`destinationRaw`);if(k+=E.move(formatLinkUrl(String(e.url??``))),j(),e.title){let t=S.enter(`titleQuote`);k+=E.move(` "`),k+=E.move(S.safe(e.title,{before:k,after:`"`,...E.current()})),k+=E.move(`"`),t()}return k+=E.move(`)`),D(),k},definition(e,t,S,w){let E=e.data?.sourceLayout??`inline`,D=e.data?.sourceTitleMarker??`double`,O=S.enter(`definition`),k=S.createTracker(w),j=S.enter(`label`),F=k.move(`[`);F+=k.move(S.safe(S.associationId(e),{before:F,after:`]`,...k.current()})),F+=k.move(`]:`),j();let L=E===`multiline`?`
|
|
@@ -1145,7 +1145,7 @@ ${e.terminator}`}function Qa(e){return`(${Ee(e.body)})${ke(e.redirections)}`}fun
|
|
|
1145
1145
|
`).trim()),E=[]):E.push(e)}if(E.length>0){let e=E.join(`
|
|
1146
1146
|
`).trim();e&&w.push(e)}return w}function reconcile(e){if(isSystemDoc(e.docName)||isConfigDoc(e.docName))return{kind:`noop`};let{base:t,ours:S,theirs:w}=e;if(containsConflictMarkers(w))return{kind:`refused`,reason:`conflict-markers`};if(w===t)return{kind:`noop`};if(S===t)return{kind:`clean`,newContent:w};let E=splitMarkdownBlocks(t),D=splitMarkdownBlocks(S),O=splitMarkdownBlocks(w);return(E.length+1)*(D.length+1)>4e6||(E.length+1)*(O.length+1)>4e6?{kind:`refused`,reason:`too-large`}:mergeBlocks(E,D,O)}function mergeBlocks(e,t,S){let w=computeEditOps(e,t),E=computeEditOps(e,S),D=[],O=[];for(let t=0;t<e.length;t++){let S=e[t],k=w.get(t),j=E.get(t),F=k?.insertsBefore??[],L=j?.insertsBefore??[];D.push(...F,...L);let B=k?.action??`keep`,H=j?.action??`keep`;if(B===`keep`&&H===`keep`)D.push(S);else if(B===`keep`&&H!==`keep`)H===`modify`&&j?.newContent!==void 0&&D.push(j.newContent);else if(B!==`keep`&&H===`keep`)B===`modify`&&k?.newContent!==void 0&&D.push(k.newContent);else{let e=B===`modify`?k?.newContent:null,w=H===`modify`?j?.newContent:null;e===w||O.push({blockIndex:t,base:S,ours:e??``,theirs:w??``}),e!=null&&D.push(e)}}let k=w.get(e.length),j=E.get(e.length);k?.insertsBefore&&D.push(...k.insertsBefore),j?.insertsBefore&&D.push(...j.insertsBefore);let F=D.length>0?`${D.join(`
|
|
1147
1147
|
|
|
1148
|
-
`)}\n`:``;return O.length>0?{kind:`conflicts`,newContent:F,conflicts:O}:{kind:`merged`,newContent:F,mergedBlocks:D.length}}function computeEditOps(e,t){let S=new Map,w=longestCommonSubsequence(e,t);for(let t=0;t<=e.length;t++)S.set(t,{action:`keep`,insertsBefore:[]});let E=new Set,D=new Set;for(let[e,t]of w)E.add(e),D.add(t);let O=-1;for(let k=0;k<e.length;k++)if(E.has(k)){let e=w.find(e=>e[0]===k)?.[1]??-1,E=[];for(let S=O+1;S<e;S++)D.has(S)||E.push(t[S]);let j=S.get(k);j&&(j.insertsBefore=E),O=e}else{let e=w.find(e=>e[0]>k),E=e?e[1]:t.length,j=[];for(let e=O+1;e<E;e++)D.has(e)||j.push(e);if(j.length>0){let e=j[0];D.add(e);let w=S.get(k);w&&(w.action=`modify`,w.newContent=t[e])}else{let e=S.get(k);e&&(e.action=`delete`)}}let k=[];for(let e=O+1;e<t.length;e++)D.has(e)||k.push(t[e]);let j=S.get(e.length);return j&&(j.insertsBefore=k),S}function longestCommonSubsequence(e,t){let S=e.length,w=t.length,E=w+1,D=new Uint32Array((S+1)*E);for(let O=1;O<=S;O++){let S=O*E,k=(O-1)*E;for(let E=1;E<=w;E++)if(e[O-1]===t[E-1])D[S+E]=D[k+(E-1)]+1;else{let e=D[k+E],t=D[S+(E-1)];D[S+E]=e>t?e:t}}let O=[],k=S,j=w;for(;k>0&&j>0;)e[k-1]===t[j-1]?(O.push([k-1,j-1]),k--,j--):D[(k-1)*E+j]>=D[k*E+(j-1)]?k--:j--;return O.reverse()}function assertNeverDiskEvent(e){throw Error(`[DiskEvent] unhandled variant: ${JSON.stringify(e)}`)}const writeTracker=new Map,WRITE_TRACKER_TTL_MS=1e4;function registerWrite(e,t){let S=writeTracker.get(e)??[];S.push({hash:t,timestamp:Date.now()}),writeTracker.set(e,S)}function evictStaleTrackerEntries(){let e=Date.now();for(let[t,S]of writeTracker){let w=S.filter(t=>e-t.timestamp<=WRITE_TRACKER_TTL_MS);w.length===0?writeTracker.delete(t):w.length!==S.length&&writeTracker.set(t,w)}}function contentHash(e){return createHash(`sha256`).update(e).digest(`hex`)}function eventEscapesContentDir(e,t){let S;try{S=lstatSync(e)}catch(t){let S=t.code;return S===`ENOENT`?!1:(console.warn(`[file-watcher] lstat failed for escape check on ${e} (${S}), dropping event`),!0)}if(!S.isSymbolicLink())return!1;let w;try{w=realpathSync(e)}catch(t){let S=t.code;return S!==`ENOENT`&&S!==`ELOOP`&&console.warn(`[file-watcher] realpath failed for escape check on ${e} (${S}), dropping event`),!0}return!isWithinContentDir(w,t)}function pathToDocName(e,t){return stripDocExtension(relative(t,e))}function contentRelativePath(e,t){let S=relative(e,t).replaceAll(`\\`,`/`);return!S||S===`.`||S===`..`||S.startsWith(`../`)?null:S}function upsertFolderIndexEntry(e,t,S,w,E=S){let D=contentRelativePath(t,S);return D?(e.set(D,{size:0,modified:w.mtime.toISOString(),canonicalPath:E,inode:Number(w.ino)}),D):null}function removeFolderIndexEntries(e,t){let S=!1;for(let w of[...e.keys()])(w===t||w.startsWith(`${t}/`))&&(e.delete(w),S=!0);return S}function extractDocExtension(e){let t=extname(e);if(t===``)return null;let S=t.toLowerCase();return S===`.mdx`||S===`.md`?t:null}const lastKnownHash=new Map;function updateLastKnownHash(e,t){lastKnownHash.set(e,t)}function removeLastKnownHash(e){let t=lastKnownHash.get(e);return lastKnownHash.delete(e),t}async function classifyEvents(e,t,S,w){let E=[],D=[],O=[];for(let w of e)if(isSupportedDocFile(w.path)){if(S){let e=relative(t,w.path);if(S.isExcluded(e))continue}switch(w.type){case`delete`:E.push(w);break;case`create`:lastKnownHash.has(w.path)?O.push(w):D.push(w);break;case`update`:O.push(w);break}}let k=new Map,j=new Map;for(let e of D)try{k.set(e.path,await readFile$1(e.path,`utf-8`))}catch(t){t.code!==`ENOENT`&&console.warn(`[file-watcher] Failed to read ${e.path}:`,t)}for(let e of O)try{j.set(e.path,await readFile$1(e.path,`utf-8`))}catch(t){t.code!==`ENOENT`&&console.warn(`[file-watcher] Failed to read ${e.path}:`,t)}function F(e){let S=pathToDocName(e,t);if(!w)return S;let E=null;try{E=lstatSync(e)}catch(t){return t.code!==`ENOENT`&&console.warn(`[file-watcher] resolveDocName lstat failed for ${e}:`,t),w.has(S)&&w.delete(S),S}if(!E.isSymbolicLink())return w.has(S)&&w.delete(S),S;let D;try{D=realpathSync(e)}catch(t){let E=t.code;return E!==`ENOENT`&&E!==`ELOOP`&&console.warn(`[file-watcher] resolveDocName realpath failed for ${e}:`,t),w.delete(S),S}if(!isWithinContentDir(D,t))return w.delete(S),S;let O=pathToDocName(D,t);return O===S?S:(w.set(S,O),O)}let L=[],B=new Set,H=new Set;for(let e of E){let t=removeLastKnownHash(e.path);if(t)for(let S of D){if(B.has(S.path))continue;let w=k.get(S.path);if(w===void 0)continue;let E=contentHash(w);if(E===t){B.add(S.path),H.add(e.path),updateLastKnownHash(S.path,E),L.push({kind:`rename`,oldPath:e.path,newPath:S.path,oldDocName:F(e.path),newDocName:F(S.path),content:w});break}}}for(let e of E)H.has(e.path)||(removeLastKnownHash(e.path),L.push({kind:`delete`,path:e.path,docName:F(e.path)}));for(let e of D){if(B.has(e.path))continue;let t=k.get(e.path);if(t===void 0)continue;let S=contentHash(t);updateLastKnownHash(e.path,S),containsConflictMarkers(t)?L.push({kind:`conflict`,path:e.path,docName:F(e.path),content:t}):L.push({kind:`create`,path:e.path,docName:F(e.path),content:t})}for(let e of O){let t=j.get(e.path);if(t===void 0)continue;let S=contentHash(t);updateLastKnownHash(e.path,S),containsConflictMarkers(t)?L.push({kind:`conflict`,path:e.path,docName:F(e.path),content:t}):L.push({kind:`update`,path:e.path,docName:F(e.path),content:t})}return L}function isSelfWrite(e,t){let S=writeTracker.get(e);if(!S)return!1;let w=S.findIndex(e=>e.hash===t);return w<0?!1:(S.splice(w,1),S.length===0&&writeTracker.delete(e),!0)}function seedLastKnownHashes(e,t,S,w,E,D,O){let k=O??new Set;try{let O=readdirSync(e,{withFileTypes:!0});for(let j of O){let O=join(e,j.name),F;try{F=lstatSync(O)}catch(e){e.code!==`ENOENT`&&console.warn(`[file-watcher] Failed to lstat ${O}, skipping:`,e);continue}if(F.isSymbolicLink()){let e;try{e=realpathSync(O)}catch(e){let t=e.code;t===`ENOENT`||t===`ELOOP`?console.warn(`[file-watcher] Broken/cyclic symlink at ${O}, skipping`):console.warn(`[file-watcher] Failed to resolve symlink ${O}:`,e);continue}if(!isWithinContentDir(e,t)){console.warn(`[file-watcher] Symlink escape: ${O} → ${e}, skipping`);continue}try{let F=statSync(e);if(k.has(F.ino)){if(F.isFile()&&isSupportedDocFile(j.name)){let S=pathToDocName(O,t),E=pathToDocName(e,t);D.set(S,E);let k=w.get(E);k&&!k.aliases.includes(S)&&k.aliases.push(S)}continue}if(k.add(F.ino),F.isDirectory()){let j=contentRelativePath(t,O);if(S&&(!j||S.isDirExcluded(j)))continue;upsertFolderIndexEntry(E,t,O,F,e),seedLastKnownHashes(e,t,S,w,E,D,k)}else if(F.isFile()&&isSupportedDocFile(j.name)){if(S){let w=relative(t,e);if(S.isExcluded(w))continue}let E=pathToDocName(O,t),k=pathToDocName(e,t);D.set(E,k);try{let t=contentHash(readFileSync(e,`utf-8`));lastKnownHash.set(e,t);let S=extractDocExtension(e);if(S){let e=registerDocExtension(k,S);if(e.shadowed&&(console.warn(`[file-watcher] docName "${k}" has both "${e.effective}" and "${e.shadowed}" on disk; "${e.effective}" wins (industry convention). Rename or delete one to disambiguate.`),!e.changed))continue}w.set(k,{size:F.size,modified:F.mtime.toISOString(),canonicalPath:e,inode:F.ino,aliases:[E]})}catch(t){t.code!==`ENOENT`&&console.warn(`[file-watcher] Failed to seed hash for ${e}:`,t)}}}catch(t){console.warn(`[file-watcher] Failed to stat symlink target ${e}:`,t)}}else if(F.isDirectory()){let e=contentRelativePath(t,O);if(S&&(!e||S.isDirExcluded(e)))continue;upsertFolderIndexEntry(E,t,O,F),seedLastKnownHashes(O,t,S,w,E,D,k)}else if(F.isFile()&&isSupportedDocFile(j.name)){if(k.has(F.ino))continue;if(k.add(F.ino),S){let e=relative(t,O);if(S.isExcluded(e))continue}try{let e=readFileSync(O,`utf-8`);lastKnownHash.set(O,contentHash(e));let S=pathToDocName(O,t),E=extractDocExtension(O);if(E){let e=registerDocExtension(S,E);if(e.shadowed&&(console.warn(`[file-watcher] docName "${S}" has both "${e.effective}" and "${e.shadowed}" on disk; "${e.effective}" wins (industry convention). Rename or delete one to disambiguate.`),!e.changed))continue}w.set(S,{size:F.size,modified:F.mtime.toISOString(),canonicalPath:O,inode:F.ino,aliases:[]})}catch(e){let t=e.code;t===`EACCES`?console.warn(`[file-watcher] Permission denied reading ${O}, file excluded from index`):t!==`ENOENT`&&console.warn(`[file-watcher] Failed to seed hash for ${O}:`,e)}}}}catch(t){t.code!==`ENOENT`&&console.warn(`[file-watcher] Failed to read directory ${e}:`,t)}}function updateFileIndex(e,t){if(e.kind===`asset-create`||e.kind===`asset-delete`||e.kind===`folder-create`||e.kind===`folder-delete`)return;let S=e.kind===`rename`?e.newDocName:e.docName;if(!(isSystemDoc(S)||isConfigDoc(S)))switch(e.kind){case`create`:case`update`:case`conflict`:{let S=e.docName,w=t.get(S),E=extractDocExtension(e.path);E&®isterDocExtension(S,E),t.set(S,{size:Buffer.byteLength(e.content,`utf-8`),modified:new Date().toISOString(),canonicalPath:w?.canonicalPath??e.path,inode:w?.inode??0,aliases:w?.aliases??[]});break}case`delete`:if(t.has(e.docName))t.delete(e.docName),forgetDocExtension(e.docName);else for(let[,S]of t){let t=S.aliases.indexOf(e.docName);if(t!==-1){S.aliases.splice(t,1);break}}break;case`rename`:{let S=t.get(e.oldDocName);t.delete(e.oldDocName),forgetDocExtension(e.oldDocName);let w=extractDocExtension(e.newPath);w&®isterDocExtension(e.newDocName,w),t.set(e.newDocName,{size:Buffer.byteLength(e.content,`utf-8`),modified:new Date().toISOString(),canonicalPath:S?.canonicalPath??e.newPath,inode:S?.inode??0,aliases:S?.aliases??[]});break}default:assertNeverDiskEvent(e)}}function updateFolderIndexFromRawEvents(e,t,S,w){let E=[];for(let D of e){let e=contentRelativePath(t,D.path);if(!e)continue;if(D.type===`delete`){removeFolderIndexEntries(w,e)&&E.push({kind:`folder-delete`,path:D.path,relativePath:e});continue}let O;try{O=lstatSync(D.path)}catch(e){let t=e.code;t!==`ENOENT`&&console.warn(`[file-watcher] folder lstat failed for ${D.path} (${t})`);continue}let k=null,j=D.path;if(O.isDirectory())k=O;else if(O.isSymbolicLink())try{if(j=realpathSync(D.path),!isWithinContentDir(j,t))continue;let e=statSync(j);e.isDirectory()&&(k=e)}catch(e){let t=e.code;t!==`ENOENT`&&console.warn(`[file-watcher] folder symlink resolve failed for ${D.path} (${t})`),k=null}if(!k||S?.isDirExcluded(e))continue;let F=w.has(e);upsertFolderIndexEntry(w,t,D.path,k,j),F||(E.push({kind:`folder-create`,path:D.path,relativePath:e}),scanForUntrackedSubfolders(j,t,S,w,E))}return E}function scanForUntrackedSubfolders(e,t,S,w,E){let D=[e];for(;D.length>0;){let e=D.shift();if(e===void 0)continue;let O;try{O=readdirSync(e,{withFileTypes:!0})}catch(t){let S=t.code;S!==`ENOENT`&&console.warn(`[file-watcher] folder rescan readdir failed for ${e} (${S})`);continue}for(let k of O){if(!k.isDirectory())continue;let O=join(e,k.name),j=contentRelativePath(t,O);if(!j||S?.isDirExcluded(j))continue;let F;try{F=lstatSync(O)}catch(e){let t=e.code;t!==`ENOENT`&&console.warn(`[file-watcher] folder rescan lstat failed for ${O} (${t})`);continue}F.isDirectory()&&(w.has(j)||(upsertFolderIndexEntry(w,t,O,F),E.push({kind:`folder-create`,path:O,relativePath:j})),D.push(O))}}}async function handleRawEvents(e,t,S,w,E,D,O){let k=e.filter(e=>eventEscapesContentDir(e.path,t)?(console.warn(`[file-watcher] Symlink escape: ${e.path}, dropping ${e.type} event`),!1):!0),j=k.filter(e=>isSupportedDocFile(e.path)),F=k.filter(e=>isSupportedAssetFile(e.path,ASSET_EXTENSIONS)),L=updateFolderIndexFromRawEvents(k,t,S,E);if(j.length===0&&F.length===0&&L.length===0)return;let B=j.length>0?await classifyEvents(j,t,S,O):[];for(let e of B){let t=!1;if(e.kind!==`delete`&&e.kind!==`rename`){let S=contentHash(e.content),w=e.path;try{w=realpathSync(e.path)}catch(t){let S=t.code;S!==`ENOENT`&&console.warn(`[file-watcher] realpathSync failed for self-write check on ${e.path} (${S})`)}t=isSelfWrite(w,S)}else if(e.kind===`rename`){let S=contentHash(e.content),w=e.newPath;try{w=realpathSync(e.newPath)}catch(t){let S=t.code;S!==`ENOENT`&&console.warn(`[file-watcher] realpathSync failed for self-write check on ${e.newPath} (${S})`)}t=isSelfWrite(w,S)}if(updateFileIndex(e,w),S&&!t)switch(e.kind){case`create`:S.incrementMdDir(dirname(e.docName));break;case`delete`:S.decrementMdDir(dirname(e.docName));break;case`rename`:S.decrementMdDir(dirname(e.oldDocName)),S.incrementMdDir(dirname(e.newDocName));break;case`update`:case`conflict`:break;default:assertNeverDiskEvent(e)}if(t){getLogger(`file-watcher`).debug({kind:e.kind,path:e.kind===`rename`?e.newPath:e.path,self:!0},`[file-watcher] Skipped self-write: ${e.kind}`),_fileWatcherEventsCounter().add(1,{"disk.kind":e.kind,self:!0});continue}getLogger(`file-watcher`).debug({kind:e.kind,path:e.kind===`rename`?e.newPath:e.path},`[file-watcher] Dispatching: ${e.kind}`),_fileWatcherEventsCounter().add(1,{"disk.kind":e.kind,self:!1});let E=e.kind===`rename`?e.newPath:e.path;await withSpan(`file_watcher.process_event`,{attributes:{"disk.kind":e.kind,"disk.path":normalizeFsPath(E),"disk.path.role":classifyFsPath(E)}},async()=>D(e))}for(let e of L)getLogger(`file-watcher`).debug({kind:e.kind,path:e.path},`[file-watcher] Dispatching: ${e.kind}`),_fileWatcherEventsCounter().add(1,{"disk.kind":e.kind,self:!1}),await withSpan(`file_watcher.process_event`,{attributes:{"disk.kind":e.kind,"disk.path":normalizeFsPath(e.path),"disk.path.role":classifyFsPath(e.path)}},async()=>D(e));for(let e of F){if(S){let w=relative(t,e.path);if(S.isExcluded(w))continue}let w=relative(t,e.path);await D(e.type===`delete`?{kind:`asset-delete`,path:e.path,relativePath:w}:{kind:`asset-create`,path:e.path,relativePath:w})}}let _fwEventsCounterCache=null;function _fileWatcherEventsCounter(){return _fwEventsCounterCache||=getMeter().createCounter(`ok.file_watcher.events`,{description:`Number of file-watcher events classified by kind`}),_fwEventsCounterCache}async function startParcelWatcher(e,t,S,w,E,D){let O;try{O=await import(`@parcel/watcher`)}catch(e){return console.warn(`[file-watcher] @parcel/watcher import failed:`,e instanceof Error?e.message:e),null}try{let k=t?{ignore:t.getWatcherIgnoreGlobs()}:void 0;return await O.subscribe(e,async(O,k)=>{if(O){console.error(`[file-watcher]`,O);return}try{await handleRawEvents(k.map(e=>({type:e.type,path:e.path})),e,t,S,w,E,D)}catch(e){console.error(`[file-watcher] parcel batch error:`,e)}},k)}catch(e){return console.warn(`[file-watcher] @parcel/watcher subscribe failed, falling back to chokidar:`,e),null}}async function startChokidarWatcher(e,t,S,w,E,D){let{watch:O}=await import(`./chokidar-CxU7f6JW.mjs`);console.warn(`[file-watcher] @parcel/watcher unavailable, using chokidar fallback`);let k=O(e,{ignoreInitial:!0,followSymlinks:!1,ignored:t?(S,w)=>{let E=relative(e,S);return E===``||E===`.`?!1:w?.isDirectory()?t.isDirExcluded(E):t.isExcluded(E)}:void 0});k.on(`error`,e=>console.error(`[file-watcher] chokidar error:`,e));let j=50,F=[],L=null;function B(O,k){F.push({type:O,path:k}),L||=setTimeout(()=>{let O=F;F=[],L=null,handleRawEvents(O,e,t,S,w,E,D).catch(e=>console.error(`[file-watcher] chokidar batch error:`,e))},50)}return k.on(`add`,e=>B(`create`,e)),k.on(`change`,e=>B(`update`,e)),k.on(`unlink`,e=>B(`delete`,e)),k.on(`addDir`,e=>B(`create`,e)),k.on(`unlinkDir`,e=>B(`delete`,e)),{unsubscribe:()=>(L&&(clearTimeout(L),L=null,F=[]),k.close())}}async function startWatcher(e,t,S){let w;try{w=realpathSync(e)}catch{w=e}let E=new Map,D=new Map,O=new Map;seedLastKnownHashes(w,w,S,E,D,O);let k=setInterval(evictStaleTrackerEntries,WRITE_TRACKER_TTL_MS),j,F;try{let e=await startParcelWatcher(w,S,E,D,t,O);e?(j=e,F=`parcel`):(j=await startChokidarWatcher(w,S,E,D,t,O),F=`chokidar`)}catch(e){throw clearInterval(k),e}let L=j.unsubscribe.bind(j);return console.log(`[file-watcher] Watching ${w} for external .md changes (backend: ${F})`),{async unsubscribe(){return clearInterval(k),writeTracker.clear(),lastKnownHash.clear(),L()},getFileIndex(){return E},getFolderIndex(){return D},getAliasMap(){return O},pruneFileIndexNowExcluded(){if(!S)return 0;let e=0;for(let[t,D]of E){let O=relative(w,D.canonicalPath);S.isExcluded(O)&&(E.delete(t),e++)}return e},rescanFromDisk(){seedLastKnownHashes(w,w,S,E,D,O)}}}function normalizeBody(e){let{body:t}=stripFrontmatter(e);return normalizeBridge(t).trim()}function isWhitespace(e){return e===` `||e===`
|
|
1148
|
+
`)}\n`:``;return O.length>0?{kind:`conflicts`,newContent:F,conflicts:O}:{kind:`merged`,newContent:F,mergedBlocks:D.length}}function computeEditOps(e,t){let S=new Map,w=longestCommonSubsequence(e,t);for(let t=0;t<=e.length;t++)S.set(t,{action:`keep`,insertsBefore:[]});let E=new Set,D=new Set;for(let[e,t]of w)E.add(e),D.add(t);let O=-1;for(let k=0;k<e.length;k++)if(E.has(k)){let e=w.find(e=>e[0]===k)?.[1]??-1,E=[];for(let S=O+1;S<e;S++)D.has(S)||E.push(t[S]);let j=S.get(k);j&&(j.insertsBefore=E),O=e}else{let e=w.find(e=>e[0]>k),E=e?e[1]:t.length,j=[];for(let e=O+1;e<E;e++)D.has(e)||j.push(e);if(j.length>0){let e=j[0];D.add(e);let w=S.get(k);w&&(w.action=`modify`,w.newContent=t[e])}else{let e=S.get(k);e&&(e.action=`delete`)}}let k=[];for(let e=O+1;e<t.length;e++)D.has(e)||k.push(t[e]);let j=S.get(e.length);return j&&(j.insertsBefore=k),S}function longestCommonSubsequence(e,t){let S=e.length,w=t.length,E=w+1,D=new Uint32Array((S+1)*E);for(let O=1;O<=S;O++){let S=O*E,k=(O-1)*E;for(let E=1;E<=w;E++)if(e[O-1]===t[E-1])D[S+E]=D[k+(E-1)]+1;else{let e=D[k+E],t=D[S+(E-1)];D[S+E]=e>t?e:t}}let O=[],k=S,j=w;for(;k>0&&j>0;)e[k-1]===t[j-1]?(O.push([k-1,j-1]),k--,j--):D[(k-1)*E+j]>=D[k*E+(j-1)]?k--:j--;return O.reverse()}function assertNeverDiskEvent(e){throw Error(`[DiskEvent] unhandled variant: ${JSON.stringify(e)}`)}const writeTracker=new Map,WRITE_TRACKER_TTL_MS=1e4;function registerWrite(e,t){let S=writeTracker.get(e)??[];S.push({hash:t,timestamp:Date.now()}),writeTracker.set(e,S)}function evictStaleTrackerEntries(){let e=Date.now();for(let[t,S]of writeTracker){let w=S.filter(t=>e-t.timestamp<=WRITE_TRACKER_TTL_MS);w.length===0?writeTracker.delete(t):w.length!==S.length&&writeTracker.set(t,w)}}function contentHash(e){return createHash(`sha256`).update(e).digest(`hex`)}function eventEscapesContentDir(e,t){let S;try{S=lstatSync(e)}catch(t){let S=t.code;return S===`ENOENT`?!1:(console.warn(`[file-watcher] lstat failed for escape check on ${e} (${S}), dropping event`),!0)}if(!S.isSymbolicLink())return!1;let w;try{w=realpathSync(e)}catch(t){let S=t.code;return S!==`ENOENT`&&S!==`ELOOP`&&console.warn(`[file-watcher] realpath failed for escape check on ${e} (${S}), dropping event`),!0}return!isWithinContentDir(w,t)}function pathToDocName(e,t){return stripDocExtension(relative(t,e))}function contentRelativePath(e,t){let S=relative(e,t).replaceAll(`\\`,`/`);return!S||S===`.`||S===`..`||S.startsWith(`../`)?null:S}function upsertFolderIndexEntry(e,t,S,w,E=S){let D=contentRelativePath(t,S);return D?(e.set(D,{size:0,modified:w.mtime.toISOString(),canonicalPath:E,inode:Number(w.ino)}),D):null}function removeFolderIndexEntries(e,t){let S=!1;for(let w of e.keys())(w===t||w.startsWith(`${t}/`))&&(e.delete(w),S=!0);return S}function extractDocExtension(e){let t=extname(e);if(t===``)return null;let S=t.toLowerCase();return S===`.mdx`||S===`.md`?t:null}const lastKnownHash=new Map;function updateLastKnownHash(e,t){lastKnownHash.set(e,t)}function removeLastKnownHash(e){let t=lastKnownHash.get(e);return lastKnownHash.delete(e),t}async function classifyEvents(e,t,S,w){let E=[],D=[],O=[];for(let w of e)if(isSupportedDocFile(w.path)){if(S){let e=relative(t,w.path);if(S.isExcluded(e))continue}switch(w.type){case`delete`:E.push(w);break;case`create`:lastKnownHash.has(w.path)?O.push(w):D.push(w);break;case`update`:O.push(w);break}}let k=new Map,j=new Map;for(let e of D)try{k.set(e.path,await readFile$1(e.path,`utf-8`))}catch(t){t.code!==`ENOENT`&&console.warn(`[file-watcher] Failed to read ${e.path}:`,t)}for(let e of O)try{j.set(e.path,await readFile$1(e.path,`utf-8`))}catch(t){t.code!==`ENOENT`&&console.warn(`[file-watcher] Failed to read ${e.path}:`,t)}function F(e){let S=pathToDocName(e,t);if(!w)return S;let E=null;try{E=lstatSync(e)}catch(t){return t.code!==`ENOENT`&&console.warn(`[file-watcher] resolveDocName lstat failed for ${e}:`,t),w.has(S)&&w.delete(S),S}if(!E.isSymbolicLink())return w.has(S)&&w.delete(S),S;let D;try{D=realpathSync(e)}catch(t){let E=t.code;return E!==`ENOENT`&&E!==`ELOOP`&&console.warn(`[file-watcher] resolveDocName realpath failed for ${e}:`,t),w.delete(S),S}if(!isWithinContentDir(D,t))return w.delete(S),S;let O=pathToDocName(D,t);return O===S?S:(w.set(S,O),O)}let L=[],B=new Set,H=new Set;for(let e of E){let t=removeLastKnownHash(e.path);if(t)for(let S of D){if(B.has(S.path))continue;let w=k.get(S.path);if(w===void 0)continue;let E=contentHash(w);if(E===t){B.add(S.path),H.add(e.path),updateLastKnownHash(S.path,E),L.push({kind:`rename`,oldPath:e.path,newPath:S.path,oldDocName:F(e.path),newDocName:F(S.path),content:w});break}}}for(let e of E)H.has(e.path)||(removeLastKnownHash(e.path),L.push({kind:`delete`,path:e.path,docName:F(e.path)}));for(let e of D){if(B.has(e.path))continue;let t=k.get(e.path);if(t===void 0)continue;let S=contentHash(t);updateLastKnownHash(e.path,S),containsConflictMarkers(t)?L.push({kind:`conflict`,path:e.path,docName:F(e.path),content:t}):L.push({kind:`create`,path:e.path,docName:F(e.path),content:t})}for(let e of O){let t=j.get(e.path);if(t===void 0)continue;let S=contentHash(t);updateLastKnownHash(e.path,S),containsConflictMarkers(t)?L.push({kind:`conflict`,path:e.path,docName:F(e.path),content:t}):L.push({kind:`update`,path:e.path,docName:F(e.path),content:t})}return L}function isSelfWrite(e,t){let S=writeTracker.get(e);if(!S)return!1;let w=S.findIndex(e=>e.hash===t);return w<0?!1:(S.splice(w,1),S.length===0&&writeTracker.delete(e),!0)}function seedLastKnownHashes(e,t,S,w,E,D,O){let k=O??new Set;try{let O=readdirSync(e,{withFileTypes:!0});for(let j of O){let O=join(e,j.name),F;try{F=lstatSync(O)}catch(e){e.code!==`ENOENT`&&console.warn(`[file-watcher] Failed to lstat ${O}, skipping:`,e);continue}if(F.isSymbolicLink()){let e;try{e=realpathSync(O)}catch(e){let t=e.code;t===`ENOENT`||t===`ELOOP`?console.warn(`[file-watcher] Broken/cyclic symlink at ${O}, skipping`):console.warn(`[file-watcher] Failed to resolve symlink ${O}:`,e);continue}if(!isWithinContentDir(e,t)){console.warn(`[file-watcher] Symlink escape: ${O} → ${e}, skipping`);continue}try{let F=statSync(e);if(k.has(F.ino)){if(F.isFile()&&isSupportedDocFile(j.name)){let S=pathToDocName(O,t),E=pathToDocName(e,t);D.set(S,E);let k=w.get(E);k&&!k.aliases.includes(S)&&k.aliases.push(S)}continue}if(k.add(F.ino),F.isDirectory()){let j=contentRelativePath(t,O);if(S&&(!j||S.isDirExcluded(j)))continue;upsertFolderIndexEntry(E,t,O,F,e),seedLastKnownHashes(e,t,S,w,E,D,k)}else if(F.isFile()&&isSupportedDocFile(j.name)){if(S){let w=relative(t,e);if(S.isExcluded(w))continue}let E=pathToDocName(O,t),k=pathToDocName(e,t);D.set(E,k);try{let t=contentHash(readFileSync(e,`utf-8`));lastKnownHash.set(e,t);let S=extractDocExtension(e);if(S){let e=registerDocExtension(k,S);if(e.shadowed&&(console.warn(`[file-watcher] docName "${k}" has both "${e.effective}" and "${e.shadowed}" on disk; "${e.effective}" wins (industry convention). Rename or delete one to disambiguate.`),!e.changed))continue}w.set(k,{size:F.size,modified:F.mtime.toISOString(),canonicalPath:e,inode:F.ino,aliases:[E]})}catch(t){t.code!==`ENOENT`&&console.warn(`[file-watcher] Failed to seed hash for ${e}:`,t)}}}catch(t){console.warn(`[file-watcher] Failed to stat symlink target ${e}:`,t)}}else if(F.isDirectory()){let e=contentRelativePath(t,O);if(S&&(!e||S.isDirExcluded(e)))continue;upsertFolderIndexEntry(E,t,O,F),seedLastKnownHashes(O,t,S,w,E,D,k)}else if(F.isFile()&&isSupportedDocFile(j.name)){if(k.has(F.ino))continue;if(k.add(F.ino),S){let e=relative(t,O);if(S.isExcluded(e))continue}try{let e=readFileSync(O,`utf-8`);lastKnownHash.set(O,contentHash(e));let S=pathToDocName(O,t),E=extractDocExtension(O);if(E){let e=registerDocExtension(S,E);if(e.shadowed&&(console.warn(`[file-watcher] docName "${S}" has both "${e.effective}" and "${e.shadowed}" on disk; "${e.effective}" wins (industry convention). Rename or delete one to disambiguate.`),!e.changed))continue}w.set(S,{size:F.size,modified:F.mtime.toISOString(),canonicalPath:O,inode:F.ino,aliases:[]})}catch(e){let t=e.code;t===`EACCES`?console.warn(`[file-watcher] Permission denied reading ${O}, file excluded from index`):t!==`ENOENT`&&console.warn(`[file-watcher] Failed to seed hash for ${O}:`,e)}}}}catch(t){t.code!==`ENOENT`&&console.warn(`[file-watcher] Failed to read directory ${e}:`,t)}}function updateFileIndex(e,t){if(e.kind===`asset-create`||e.kind===`asset-delete`||e.kind===`folder-create`||e.kind===`folder-delete`)return;let S=e.kind===`rename`?e.newDocName:e.docName;if(!(isSystemDoc(S)||isConfigDoc(S)))switch(e.kind){case`create`:case`update`:case`conflict`:{let S=e.docName,w=t.get(S),E=extractDocExtension(e.path);E&®isterDocExtension(S,E),t.set(S,{size:Buffer.byteLength(e.content,`utf-8`),modified:new Date().toISOString(),canonicalPath:w?.canonicalPath??e.path,inode:w?.inode??0,aliases:w?.aliases??[]});break}case`delete`:if(t.has(e.docName))t.delete(e.docName),forgetDocExtension(e.docName);else for(let[,S]of t){let t=S.aliases.indexOf(e.docName);if(t!==-1){S.aliases.splice(t,1);break}}break;case`rename`:{let S=t.get(e.oldDocName);t.delete(e.oldDocName),forgetDocExtension(e.oldDocName);let w=extractDocExtension(e.newPath);w&®isterDocExtension(e.newDocName,w),t.set(e.newDocName,{size:Buffer.byteLength(e.content,`utf-8`),modified:new Date().toISOString(),canonicalPath:S?.canonicalPath??e.newPath,inode:S?.inode??0,aliases:S?.aliases??[]});break}default:assertNeverDiskEvent(e)}}function updateFolderIndexFromRawEvents(e,t,S,w){let E=[];for(let D of e){let e=contentRelativePath(t,D.path);if(!e)continue;if(D.type===`delete`){removeFolderIndexEntries(w,e)&&E.push({kind:`folder-delete`,path:D.path,relativePath:e});continue}let O;try{O=lstatSync(D.path)}catch(e){let t=e.code;t!==`ENOENT`&&console.warn(`[file-watcher] folder lstat failed for ${D.path} (${t})`);continue}let k=null,j=D.path;if(O.isDirectory())k=O;else if(O.isSymbolicLink())try{if(j=realpathSync(D.path),!isWithinContentDir(j,t))continue;let e=statSync(j);e.isDirectory()&&(k=e)}catch(e){let t=e.code;t!==`ENOENT`&&console.warn(`[file-watcher] folder symlink resolve failed for ${D.path} (${t})`),k=null}if(!k||S?.isDirExcluded(e))continue;let F=w.has(e);upsertFolderIndexEntry(w,t,D.path,k,j),F||(E.push({kind:`folder-create`,path:D.path,relativePath:e}),scanForUntrackedSubfolders(j,t,S,w,E))}return E}function scanForUntrackedSubfolders(e,t,S,w,E){let D=[e];for(;D.length>0;){let e=D.shift();if(e===void 0)continue;let O;try{O=readdirSync(e,{withFileTypes:!0})}catch(t){let S=t.code;S!==`ENOENT`&&console.warn(`[file-watcher] folder rescan readdir failed for ${e} (${S})`);continue}for(let k of O){if(!k.isDirectory())continue;let O=join(e,k.name),j=contentRelativePath(t,O);if(!j||S?.isDirExcluded(j))continue;let F;try{F=lstatSync(O)}catch(e){let t=e.code;t!==`ENOENT`&&console.warn(`[file-watcher] folder rescan lstat failed for ${O} (${t})`);continue}F.isDirectory()&&(w.has(j)||(upsertFolderIndexEntry(w,t,O,F),E.push({kind:`folder-create`,path:O,relativePath:j})),D.push(O))}}}async function handleRawEvents(e,t,S,w,E,D,O){let k=e.filter(e=>eventEscapesContentDir(e.path,t)?(console.warn(`[file-watcher] Symlink escape: ${e.path}, dropping ${e.type} event`),!1):!0),j=k.filter(e=>isSupportedDocFile(e.path)),F=k.filter(e=>isSupportedAssetFile(e.path,ASSET_EXTENSIONS)),L=updateFolderIndexFromRawEvents(k,t,S,E);if(j.length===0&&F.length===0&&L.length===0)return;let B=j.length>0?await classifyEvents(j,t,S,O):[];for(let e of B){let t=!1;if(e.kind!==`delete`&&e.kind!==`rename`){let S=contentHash(e.content),w=e.path;try{w=realpathSync(e.path)}catch(t){let S=t.code;S!==`ENOENT`&&console.warn(`[file-watcher] realpathSync failed for self-write check on ${e.path} (${S})`)}t=isSelfWrite(w,S)}else if(e.kind===`rename`){let S=contentHash(e.content),w=e.newPath;try{w=realpathSync(e.newPath)}catch(t){let S=t.code;S!==`ENOENT`&&console.warn(`[file-watcher] realpathSync failed for self-write check on ${e.newPath} (${S})`)}t=isSelfWrite(w,S)}if(updateFileIndex(e,w),S&&!t)switch(e.kind){case`create`:S.incrementMdDir(dirname(e.docName));break;case`delete`:S.decrementMdDir(dirname(e.docName));break;case`rename`:S.decrementMdDir(dirname(e.oldDocName)),S.incrementMdDir(dirname(e.newDocName));break;case`update`:case`conflict`:break;default:assertNeverDiskEvent(e)}if(t){getLogger(`file-watcher`).debug({kind:e.kind,path:e.kind===`rename`?e.newPath:e.path,self:!0},`[file-watcher] Skipped self-write: ${e.kind}`),_fileWatcherEventsCounter().add(1,{"disk.kind":e.kind,self:!0});continue}getLogger(`file-watcher`).debug({kind:e.kind,path:e.kind===`rename`?e.newPath:e.path},`[file-watcher] Dispatching: ${e.kind}`),_fileWatcherEventsCounter().add(1,{"disk.kind":e.kind,self:!1});let E=e.kind===`rename`?e.newPath:e.path;await withSpan(`file_watcher.process_event`,{attributes:{"disk.kind":e.kind,"disk.path":normalizeFsPath(E),"disk.path.role":classifyFsPath(E)}},async()=>D(e))}for(let e of L)getLogger(`file-watcher`).debug({kind:e.kind,path:e.path},`[file-watcher] Dispatching: ${e.kind}`),_fileWatcherEventsCounter().add(1,{"disk.kind":e.kind,self:!1}),await withSpan(`file_watcher.process_event`,{attributes:{"disk.kind":e.kind,"disk.path":normalizeFsPath(e.path),"disk.path.role":classifyFsPath(e.path)}},async()=>D(e));for(let e of F){if(S){let w=relative(t,e.path);if(S.isExcluded(w))continue}let w=relative(t,e.path);await D(e.type===`delete`?{kind:`asset-delete`,path:e.path,relativePath:w}:{kind:`asset-create`,path:e.path,relativePath:w})}}let _fwEventsCounterCache=null;function _fileWatcherEventsCounter(){return _fwEventsCounterCache||=getMeter().createCounter(`ok.file_watcher.events`,{description:`Number of file-watcher events classified by kind`}),_fwEventsCounterCache}async function startParcelWatcher(e,t,S,w,E,D){let O;try{O=await import(`@parcel/watcher`)}catch(e){return console.warn(`[file-watcher] @parcel/watcher import failed:`,e instanceof Error?e.message:e),null}try{let k=t?{ignore:t.getWatcherIgnoreGlobs()}:void 0;return await O.subscribe(e,async(O,k)=>{if(O){console.error(`[file-watcher]`,O);return}try{await handleRawEvents(k.map(e=>({type:e.type,path:e.path})),e,t,S,w,E,D)}catch(e){console.error(`[file-watcher] parcel batch error:`,e)}},k)}catch(e){return console.warn(`[file-watcher] @parcel/watcher subscribe failed, falling back to chokidar:`,e),null}}async function startChokidarWatcher(e,t,S,w,E,D){let{watch:O}=await import(`./chokidar-CxU7f6JW.mjs`);console.warn(`[file-watcher] @parcel/watcher unavailable, using chokidar fallback`);let k=O(e,{ignoreInitial:!0,followSymlinks:!1,ignored:t?(S,w)=>{let E=relative(e,S);return E===``||E===`.`?!1:w?.isDirectory()?t.isDirExcluded(E):t.isExcluded(E)}:void 0});k.on(`error`,e=>console.error(`[file-watcher] chokidar error:`,e));let j=50,F=[],L=null;function B(O,k){F.push({type:O,path:k}),L||=setTimeout(()=>{let O=F;F=[],L=null,handleRawEvents(O,e,t,S,w,E,D).catch(e=>console.error(`[file-watcher] chokidar batch error:`,e))},50)}return k.on(`add`,e=>B(`create`,e)),k.on(`change`,e=>B(`update`,e)),k.on(`unlink`,e=>B(`delete`,e)),k.on(`addDir`,e=>B(`create`,e)),k.on(`unlinkDir`,e=>B(`delete`,e)),{unsubscribe:()=>(L&&(clearTimeout(L),L=null,F=[]),k.close())}}async function startWatcher(e,t,S){let w;try{w=realpathSync(e)}catch{w=e}let E=new Map,D=new Map,O=new Map;seedLastKnownHashes(w,w,S,E,D,O);let k=setInterval(evictStaleTrackerEntries,WRITE_TRACKER_TTL_MS),j,F;try{let e=await startParcelWatcher(w,S,E,D,t,O);e?(j=e,F=`parcel`):(j=await startChokidarWatcher(w,S,E,D,t,O),F=`chokidar`)}catch(e){throw clearInterval(k),e}let L=j.unsubscribe.bind(j);return console.log(`[file-watcher] Watching ${w} for external .md changes (backend: ${F})`),{async unsubscribe(){return clearInterval(k),writeTracker.clear(),lastKnownHash.clear(),L()},getFileIndex(){return E},getFolderIndex(){return D},getAliasMap(){return O},pruneFileIndexNowExcluded(){if(!S)return 0;let e=0;for(let[t,D]of E){let O=relative(w,D.canonicalPath);S.isExcluded(O)&&(E.delete(t),e++)}return e},rescanFromDisk(){seedLastKnownHashes(w,w,S,E,D,O)}}}function normalizeBody(e){let{body:t}=stripFrontmatter(e);return normalizeBridge(t).trim()}function isWhitespace(e){return e===` `||e===`
|
|
1149
1149
|
`||e===` `||e===`\r`}function classifyDuplication(e,t){let S=normalizeBody(t);if(S.length===0)return{kind:`allow`,reason:`empty-base`};let w=normalizeBody(e);if(w===S)return{kind:`allow`,reason:`identical`};if(w.length<S.length*2)return{kind:`allow`,reason:`too-short`};let E=0,D=0;for(;E<w.length;){if(w.slice(E,E+S.length)!==S)return{kind:`allow`,reason:`not-integer-multiple`};for(E+=S.length,D++;E<w.length&&isWhitespace(w[E]??``);)E++}return D>=2?{kind:`block`,reason:`structural-duplication`,copies:D}:{kind:`allow`,reason:`single-copy`}}let _liveEntriesGauge=null;function liveEntriesGauge(){return _liveEntriesGauge||=getMeter().createUpDownCounter(`rename.log_entries_total`,{description:`Live rename-log entry count after each append / GC pass`}),_liveEntriesGauge}let _gcDroppedCounter=null;function gcDroppedCounter(){return _gcDroppedCounter||=getMeter().createCounter(`rename.log_gc_dropped_total`,{description:`Cumulative count of rename-log entries dropped by reachability GC`}),_gcDroppedCounter}const RENAME_LOG_HARD_CAP_BYTES=5*1024*1024,RENAME_LOG_MAX_LINE_BYTES=4*1024,RENAME_LOG_FILENAME=`renames.jsonl`;function createEmptyIndex(){return{byTo:new Map,byFrom:new Map}}function renameLogPath(e){return resolve(e,RENAME_LOG_FILENAME)}function validateEntry(e){if(typeof e!=`object`||!e)return null;let t=e;if(t.v!==1||typeof t.from!=`string`||t.from.length===0||typeof t.to!=`string`||t.to.length===0||t.from===t.to||typeof t.at!=`string`||t.at.length===0||typeof t.commitSha!=`string`||t.commitSha!==``&&!/^[0-9a-f]{40}$/.test(t.commitSha)||typeof t.branch!=`string`||t.branch.length===0||typeof t.groupId!=`string`||t.groupId.length===0||t.kind!==`file`&&t.kind!==`folder`||t.actor===null||typeof t.actor!=`object`)return null;let S=t.actor;return typeof S.writerId!=`string`||S.writerId.length===0||typeof S.displayName!=`string`?null:{v:1,from:t.from,to:t.to,at:t.at,commitSha:t.commitSha,branch:t.branch,groupId:t.groupId,kind:t.kind,actor:{writerId:S.writerId,displayName:S.displayName}}}function removeFromByFrom(e,t){let S=e.byFrom.get(t.from);if(!S)return;let w=S.filter(e=>e!==t);w.length===0?e.byFrom.delete(t.from):e.byFrom.set(t.from,w)}function indexRemove(e,t){e.byTo.delete(t.to),removeFromByFrom(e,t)}function indexInsert(e,t){let S=e.byTo.get(t.to);S&&removeFromByFrom(e,S),e.byTo.set(t.to,t);let w=e.byFrom.get(t.from);w?w.push(t):e.byFrom.set(t.from,[t])}function loadRenameLogIndex(e){let t=createEmptyIndex(),S=renameLogPath(e);if(!existsSync(S))return t;let w;try{w=readFileSync(S,`utf-8`)}catch(e){return console.warn(`[rename-log] WARN: failed to read ${S}, treating as empty:`,e),t}if(w.length===0)return t;let E=w.split(`
|
|
1150
1150
|
`),D=E[E.length-1];D!==``&&console.warn(`[rename-log] WARN: trailing line missing newline (${D.length} bytes); dropped`);let O=E.slice(0,-1);for(let e=0;e<O.length;e++){let S=O[e];if(S.length===0)continue;let w;try{w=JSON.parse(S)}catch(t){let w=S.slice(0,80),E=t.message;console.warn(`[rename-log] WARN: corrupt entry at line ${e+1} skipped (${E}): ${w}${S.length>80?`…`:``}`);continue}let E=validateEntry(w);if(!E){console.warn(`[rename-log] WARN: corrupt entry at line ${e+1} skipped`);continue}indexInsert(t,E)}return t.byTo.size>0&&liveEntriesGauge().add(t.byTo.size),t}function appendRenameLogEntry(e,t,S,w){let E=validateEntry(t);if(!E)throw Error(`[rename-log] refusing to append malformed entry`);let D=`${JSON.stringify(E)}\n`;if(Buffer.byteLength(D,`utf-8`)>RENAME_LOG_MAX_LINE_BYTES)throw Error(`[rename-log] entry exceeds max line size (${RENAME_LOG_MAX_LINE_BYTES} bytes)`);let O=renameLogPath(e),k=!1;if(existsSync(O))try{let e=statSync(O).size;e>5242880&&(k=!0,console.warn(`[rename-log] WARN: file size ${e} exceeds hard cap ${RENAME_LOG_HARD_CAP_BYTES}; forcing GC sweep`))}catch{}tracedAppendFileSync(O,D,{flag:`a`}),indexInsert(S,E),liveEntriesGauge().add(1),k&&w&&scheduleHardCapGc(w,S)}const gcPending=new Set;function scheduleHardCapGc(e,t){queueMicrotask(()=>{gcRenameLog(e,t).catch(e=>{console.warn(`[rename-log] WARN: hard-cap forced GC failed:`,e)})})}let _moduleIndex=null;function setRenameLogIndex(e,t){_moduleIndex={shadowDir:e,index:t}}function getOrLoadRenameLogIndex(e){if(_moduleIndex&&_moduleIndex.shadowDir===e)return _moduleIndex.index;let t=loadRenameLogIndex(e);return _moduleIndex={shadowDir:e,index:t},t}function serializeIndexToString(e){let t=[];for(let S of e.byTo.values())t.push(JSON.stringify(S));return t.length>0?`${t.join(`
|
|
1151
1151
|
`)}\n`:``}function parseGitTimeoutMs(){let e=process.env.OK_GIT_TIMEOUT_MS;if(!e)return 3e4;let t=Number.parseInt(e,10);return Number.isFinite(t)&&t>0?t:3e4}function expandPredecessors(e,t,S){let w=[],E=new Set,D=e,O=0;for(;;){if(w.length>=100){console.warn(`[rename-log] WARN: predecessor chain depth exceeded 100 while expanding "${e}"; truncating`);break}if(E.has(D)){console.warn(`[rename-log] WARN: cycle detected at "${D}" while expanding predecessors of "${e}"; truncating`);break}E.add(D);let k=S.byTo.get(D);if(!k||k.branch!==t)break;if(k.commitSha===``){O+=1;break}w.push({path:k.from,renameCommit:k.commitSha}),D=k.from}return w.reverse(),w.push({path:e,renameCommit:null}),{chain:w,skipped:O}}function createAncestorShaSetCache(){return new Map}function createSeedsCache(){return new Map}async function buildSeeds(e,t,S,w){return withSpan(`rename.buildSeeds`,void 0,async E=>{if(w){let e=w.get(`${S}:${t}`);if(e)return E.setAttribute(`rename.seeds_count`,e.length),E.setAttribute(`rename.cache_hit`,!0),e}let D=shadowGit(e),O;try{O=(await D.raw(`show`,`-s`,`--format=%aI`,t)).trim()}catch(e){return console.warn(`[rename-log] WARN: buildSeeds: git show failed for rename commit ${t}; falling back to single-seed:`,e),E.setAttribute(`rename.seeds_count`,1),[t]}if(!O)return E.setAttribute(`rename.seeds_count`,1),[t];let k;try{k=await D.raw(`for-each-ref`,`--sort=-creatordate`,`--format=%(creatordate:iso8601-strict) %(objectname)`,`refs/checkpoints/${S}/`)}catch(e){return console.warn(`[rename-log] WARN: buildSeeds: for-each-ref failed for branch ${S}; falling back to single-seed:`,e),E.setAttribute(`rename.seeds_count`,1),[t]}let j=[t];for(let e of k.split(`
|
|
@@ -2099,18 +2099,18 @@ description: When the agent does scheduled work: daily briefings, end-of-day dos
|
|
|
2099
2099
|
`).filter(e=>e.length===40);ne.push(...e)}catch{}let se=[];if(oe)try{se=(await te.raw(`for-each-ref`,`--format=%(objectname)`,`refs/checkpoints/main/`)).trim().split(`
|
|
2100
2100
|
`).filter(e=>e.length===40)}catch{}try{let e=(await te.raw(`for-each-ref`,`--format=%(refname)`,`refs/wip/${E}/`)).trim().split(`
|
|
2101
2101
|
`).filter(Boolean);ae.push(...e)}catch{}if(oe&&ae.length===0)try{let e=(await te.raw(`for-each-ref`,`--format=%(refname)`,`refs/wip/main/`)).trim().split(`
|
|
2102
|
-
`).filter(Boolean);ae.push(...e)}catch{}if(ae.length===0&&ne.length===0&&se.length===0)return EMPTY;let ce=[...ne,...se],ue=[];if(ce.length>0){let t=parseGitLogOutput(await te.raw(`log`,`--no-walk`,`--author-date-order`,`--format=${GIT_LOG_FORMAT}`,...ce)).map(e=>({...e,type:`checkpoint`}));if(H&&(t=await filterEntriesByChain(e,t,L,E,B,ee,Y)),oe&&ne.length>0&&se.length>0){let e=new Set(ne),S=t.filter(t=>e.has(t.sha)),w=t.filter(t=>!e.has(t.sha)),E=S.reduce((e,t)=>{let S=new Date(t.timestamp).getTime();return S<e?S:e},1/0);ue=[...S,...w.filter(e=>new Date(e.timestamp).getTime()<E)]}else ue=t}let de=[...ae];for(let e of ce)de.push(e);let fe=[];if(de.length>0&&(fe=parseGitLogOutput(await te.raw(`log`,`--full-history`,`--author-date-order`,`--format=${GIT_LOG_FORMAT}`,...de,...H?[`--`,H]:[])),J))for(let t=0;t<L.length-1;t++){let S=L[t];if(S.renameCommit!==null)try{let t=await buildSeeds(e,S.renameCommit,E,Y);if(t.length===0)continue;let w=B(S.path),D=await logSeededReachable(e,[`--full-history`,`--author-date-order`,`--format=${GIT_LOG_FORMAT}`],t,w);fe=[...fe,...parseGitLogOutput(D)]}catch(e){console.warn(`[timeline] predecessor walk failed for step ${t} (${S.path}); skipping:`,e)}}let me=[...ue,...fe],ge=new Set,_e=[];for(let e of me)ge.has(e.sha)||(ge.add(e.sha),_e.push(e));let ve=_e;_e.length>0&&L.length>0&&(ve=filterEntriesByOkActorDocs(_e,L,await Promise.all(L.map(async t=>{if(t.renameCommit===null)return null;let S=await buildSeeds(e,t.renameCommit,E,Y);return S.length===0?new Set:buildAncestorShaSet(e,S,E,ee)})))),ve.sort((e,t)=>new Date(t.timestamp).getTime()-new Date(e.timestamp).getTime());let ye=ve;ye=ye.filter(e=>e.type!==`park`),k.length>0&&(ye=ye.filter(e=>k.includes(e.type))),j.length>0&&(ye=ye.filter(e=>matchesAuthor(e,j))),F.length>0&&(ye=ye.filter(e=>!matchesAuthor(e,F)));let Ce=ye.length;return{entries:ye.slice(O,O+D).map(({rawBody:e,...t})=>t),total:Ce,hasMore:O+D<Ce}}catch(e){return console.warn(`[timeline] getDocumentHistory failed, returning empty result:`,e),EMPTY}}let _httpDurationHist=null;function httpDurationHist(){return _httpDurationHist||=getMeter().createHistogram(`http.server.request.duration`,{description:`HTTP server request duration in seconds`,unit:`s`}),_httpDurationHist}let _hintEmittedCounter=null;function hintEmittedCounter(){return _hintEmittedCounter||=getMeter().createCounter(`ok.preview_attach.hint_emitted`,{description:`Count of attach-preview-once hints emitted on write-tool responses when no editor is attached to __system__`}),_hintEmittedCounter}let _agentPatchFmTouchCounter=null;function agentPatchFmTouchCounter(){return _agentPatchFmTouchCounter||=getMeter().createCounter(`ok.frontmatter.agent_patch_fm_touch_total`,{description:`Count of agent-patch calls whose find string targets the frontmatter region. Measures incidence during the soft-deprecation window before agent-patch FM-intersecting calls are enforced as 400. Bounded label: result ∈ {rejected, pre_deprecation_passthrough}.`}),_agentPatchFmTouchCounter}function findLooksLikeFrontmatter(e){return!!(/(^|\n)---(\s|\n|$)/.test(e)||/^\s*[\w-]+:\s+\S/.test(e))}let _renameAttributionCounter=null;function renameAttributionCounter(){return _renameAttributionCounter||=getMeter().createCounter(`ok.rename.attribution_kind`,{description:`Count of rename and rollback handler dispatches by attribution kind (agent | principal | anonymous)`}),_renameAttributionCounter}const ROLLBACK_ORIGIN={source:`local`,skipStoreHooks:!1,context:{origin:`rollback-apply`,paired:!0}},MANAGED_RENAME_ORIGIN={source:`local`,skipStoreHooks:!1,context:{origin:`managed-rename`,paired:!0}},log$2=getLogger(`api`);function safeDocPath(e,t){if(!e||e.includes(`..`)||e.includes(`\0`))return{error:`Invalid document name.`};let S=t===`.`?``:t.replace(/^\.\//,``),w=getDocExtension(e);return{path:S?`${S}/${e}${w}`:`${e}${w}`}}const GENERIC_PASTE_NAMES=/^(image\.(png|jpe?g|gif|webp)|Clipboard.*|Untitled.*)$/i,SAFE_FILENAME_CHARS=/[^\p{L}\p{N}\p{M}\p{Extended_Pictographic}.\-_ ]/gu,STRIP_ON_SIGHT=/[/\\\x00-\x1f\x7f]/g;function sanitizeFilename(e){let t=e.replace(STRIP_ON_SIGHT,``);if(t=t.replace(SAFE_FILENAME_CHARS,`_`),t=t.replace(/_+/g,`_`).replace(/\.{2,}/g,`.`),t=t.replace(/^[._]+/,``),t=t.replace(/\.+$/,``),t===``)return`upload`;let S=255,w=new TextEncoder;if(w.encode(t).length>255){let e=t.lastIndexOf(`.`),S=e>=0?t.slice(e):``,E=e>=0?t.slice(0,e):t;for(;w.encode(E+S).length>255&&E.length>0;)E=E.slice(0,-1);t=(E||`upload`)+S,w.encode(t).length>255&&(t=`upload`)}return t}function resolveUploadDestDir(e,t,S){let w=t.trim();return w===``||w===`./`?resolve(S,dirname(e)):w===`/`?S:w.startsWith(`./`)?resolve(S,dirname(e),w.slice(2)):resolve(S,w)}function readTempFileHead(e,t){let S=openSync(e,`r`);try{let e=Buffer.alloc(t),w=readSync(S,e,0,t,0);return e.subarray(0,w)}finally{closeSync(S)}}const MAX_DEDUP_SCAN_CANDIDATES=1e3;async function streamingHashFile(e){let t=createHash(`sha256`);return await pipeline(createReadStream(e),t),t.digest(`hex`)}async function findDuplicateAsset(e,t,S){let w;try{w=await readdir(e)}catch{return null}let E=getLogger(`upload`),D=0;for(let O of w){let w=extname(O).slice(1).toLowerCase();if(!ASSET_EXTENSIONS.has(w))continue;let k=resolve(e,O),j;try{j=await stat$1(k)}catch{continue}if(!j.isFile()||j.size!==S)continue;if(D++,D>MAX_DEDUP_SCAN_CANDIDATES)return E.warn({event:`upload-dedup-skip`,reason:`scan-cap-exceeded`,destDir:e,scanned:MAX_DEDUP_SCAN_CANDIDATES,expectedSize:S},`[upload-dedup] candidate scan exceeded ${MAX_DEDUP_SCAN_CANDIDATES} same-size siblings — degrading to no-dedup for this upload`),null;let F;try{F=await streamingHashFile(k)}catch(e){let t=e.code;t!==`ENOENT`&&E.warn({event:`upload-dedup-skip`,reason:`read-failed`,code:t,entry:O},`[upload-dedup] skipped candidate — read failed`);continue}if(F===t)return O}return null}function readUploadBody(e,t){return new Promise((S,w)=>{let E;try{E=(0,import_lib.default)({headers:e.headers,limits:{files:1,fields:10,fieldSize:2*1024}})}catch(e){w(new UploadWriteError(`urn:ok:error:malformed-upload`,e));return}let D=!1,O=`upload`,k=``,j=``,F,L,B=!1,H=(e,t)=>{if(!D){if(D=!0,F)try{unlinkSync(F)}catch{}w(t instanceof UploadWriteError?t:new UploadWriteError(e,t))}},q=classifyUploadErrno;E.on(`field`,(e,t)=>{e===`parentDocName`&&(j=t)}),E.on(`file`,(e,w,E)=>{B=!0,O=E.filename||`upload`,k=E.mimeType||``;let J;try{J=mintTempUploadPath(t)}catch(e){H(q(e),e),w.resume();return}F=J;let Y=new HashingPassThrough;pipeline(w,Y,createWriteStream(J)).then(()=>{D||(D=!0,S({filename:O,mimeType:k,parentDocName:j,tempPath:J,sha:Y.digest(),byteLength:Y.byteLength()}))}).catch(e=>{L=e,H(q(e),e)})}),E.on(`error`,e=>{H(`urn:ok:error:malformed-upload`,e)}),E.on(`close`,()=>{D||L||B||(D=!0,S({filename:``,mimeType:``,parentDocName:j,tempPath:``,sha:``,byteLength:0}))}),e.on(`close`,()=>{D||L||e.complete||H(`urn:ok:error:malformed-upload`,Error(`client disconnected`))}),e.pipe(E)})}function safeSubdir(e,t){let S=resolve(e,t);if(S!==e&&!S.startsWith(`${e}/`))throw Error(`Invalid directory: ${t}`);return S}function synthesizeShowAllAssetExt(e){let t=extname(e);return t?t.slice(1).toLowerCase():e.startsWith(`.`)&&e.length>1?e.slice(1).toLowerCase():`file`}async function walkContentDirForShowAll(e){let{contentDir:t,contentFilter:S,dirFilter:w,documents:E,getDocExtension:D}=e,O=e=>w?e===w||e.startsWith(`${w}/`):!0,k;try{k=await realpath(t)}catch{k=t}let j=e=>e===k?!0:e.startsWith(`${k}/`);async function F(e,t){let w;try{w=await readdir(e,{withFileTypes:!0})}catch(t){console.warn(`[document-list][showAll] readdir failed for ${e}:`,t);return}for(let k of w){let w=t?`${t}/${k.name}`:k.name;if(k.isDirectory()){if(S.isDirExcluded(w,{bypassFilters:!0}))continue;let t=`${e}/${k.name}`,D;try{D=await realpath(t)}catch(e){console.warn(`[document-list][showAll] realpath failed for ${t}:`,e);continue}if(!j(D)){console.warn(`[document-list][showAll] refusing symlink-escape ${t} -> ${D}`);continue}if(O(w)){let e=null;try{e=await stat$1(t)}catch(e){console.warn(`[document-list][showAll] stat failed for ${t}:`,e)}E.push({kind:`folder`,path:w,size:0,modified:e?e.mtime.toISOString():``,docExt:`.md`,isSymlink:!1,canonicalDocName:null,targetPath:null})}await F(t,w);continue}if(!k.isFile()||S.isExcluded(w,{bypassFilters:!0})||!O(w))continue;let L=null;try{L=await stat$1(`${e}/${k.name}`)}catch(t){console.warn(`[document-list][showAll] stat failed for ${e}/${k.name}:`,t);continue}if(isSupportedDocFile(k.name)){let e=w.replace(/\.(md|mdx)$/i,``),t=D(e);E.push({kind:`document`,docName:e,docExt:t,size:L.size,modified:L.mtime.toISOString(),isSymlink:!1,canonicalDocName:null,targetPath:null});continue}let B=synthesizeShowAllAssetExt(k.name),H=ASSET_EXTENSIONS.has(B)?mediaKindForSidebarAssetExtension(B):null;E.push({kind:`asset`,docName:w,docExt:B,path:w,assetExt:B,mediaKind:H,referencedBy:[],size:L.size,modified:L.mtime.toISOString(),isSymlink:!1,canonicalDocName:null,targetPath:null})}}await F(w?`${t}/${w}`:t,w??``)}function isValidRelativeContentPath(e){return!e||e.startsWith(`/`)||e.includes(`\\`)||e.includes(`\0`)?!1:e.split(`/`).every(e=>e&&e!==`.`&&e!==`..`)}function listAffectedDocNames(e,t,S){let w=[...e.keys()].filter(e=>t===`file`?e===S:e===S||e.startsWith(`${S}/`));return w.sort((e,t)=>e.localeCompare(t)),w}function remapDocNameForRename(e,t,S,w){return t===`file`||e===S?w:`${w}${e.slice(S.length)}`}function assertNoSymlinkEscape(e,t){let S;try{S=realpathSync(t)}catch(e){throw e.code===`ENOENT`?new SymlinkEscapeError(`content directory does not exist`):e}let w=e;for(;;)try{if(!isWithinContentDir(realpathSync(w),S))throw new SymlinkEscapeError(`path resolves outside content directory`);return}catch(e){let S=e.code;if(S===`ELOOP`)throw new SymlinkEscapeError(`symlink cycle in path`);if(S!==`ENOENT`)throw e;let E=dirname(w);if(E===w||E!==t&&!E.startsWith(`${t}${sep}`))throw e;w=E}}function resolveContentEntryPath(e,t,S){if(!isValidRelativeContentPath(S))throw Error(`path must be a relative content path`);let w=resolve(e),E=resolve(w,t===`file`?isSupportedDocFile(S)?S:`${S}${getDocExtension(S)}`:S);if(E!==w&&!E.startsWith(`${w}${sep}`))throw Error(`path must not escape content directory`);return assertNoSymlinkEscape(E,w),E}function probeAndRegisterSourceFileExtension(e,t){if(!isValidRelativeContentPath(t))return;let S=resolve(e);for(let e of SUPPORTED_DOC_EXTENSIONS){let w=resolve(S,`${t}${e}`);if(!(w!==S&&!w.startsWith(`${S}${sep}`))&&existsSync(w)){registerDocExtension(t,e);return}}}function toGitRelativePath(e,t){let S=resolve(e),w=resolve(t);return w!==S&&!w.startsWith(`${S}${sep}`)?null:relative(S,w).split(sep).join(`/`)}async function renameTrackedPathInGit(e,t,S){if(!e)return!1;let w=toGitRelativePath(e,t),E=toGitRelativePath(e,S);return!w||!E?!1:await withParentLock(async()=>{let t=esm_default({baseDir:e,timeout:{block:15e3}}),D=``;try{D=(await t.raw(`ls-files`,`--`,w)).trim()}catch(e){return console.warn(`[renameTrackedPathInGit] git ls-files failed, falling back to fs rename:`,e),!1}if(!D)return!1;mkdirSync(dirname(S),{recursive:!0});try{return await t.raw(`mv`,`--`,w,E),!0}catch(e){return console.warn(`[renameTrackedPathInGit] git mv failed, falling back to fs rename:`,e),!1}})}const workspaceSearchCaches=new Map;function extractHeadings(e){let t=e;if(e.startsWith(`---
|
|
2102
|
+
`).filter(Boolean);ae.push(...e)}catch{}if(ae.length===0&&ne.length===0&&se.length===0)return EMPTY;let ce=[...ne,...se],ue=[];if(ce.length>0){let t=parseGitLogOutput(await te.raw(`log`,`--no-walk`,`--author-date-order`,`--format=${GIT_LOG_FORMAT}`,...ce)).map(e=>({...e,type:`checkpoint`}));if(H&&(t=await filterEntriesByChain(e,t,L,E,B,ee,Y)),oe&&ne.length>0&&se.length>0){let e=new Set(ne),S=t.filter(t=>e.has(t.sha)),w=t.filter(t=>!e.has(t.sha)),E=S.reduce((e,t)=>{let S=new Date(t.timestamp).getTime();return S<e?S:e},1/0);ue=[...S,...w.filter(e=>new Date(e.timestamp).getTime()<E)]}else ue=t}let de=[...ae];for(let e of ce)de.push(e);let fe=[];if(de.length>0&&(fe=parseGitLogOutput(await te.raw(`log`,`--full-history`,`--author-date-order`,`--format=${GIT_LOG_FORMAT}`,...de,...H?[`--`,H]:[])),J))for(let t=0;t<L.length-1;t++){let S=L[t];if(S.renameCommit!==null)try{let t=await buildSeeds(e,S.renameCommit,E,Y);if(t.length===0)continue;let w=B(S.path),D=await logSeededReachable(e,[`--full-history`,`--author-date-order`,`--format=${GIT_LOG_FORMAT}`],t,w);fe=[...fe,...parseGitLogOutput(D)]}catch(e){console.warn(`[timeline] predecessor walk failed for step ${t} (${S.path}); skipping:`,e)}}let me=[...ue,...fe],ge=new Set,_e=[];for(let e of me)ge.has(e.sha)||(ge.add(e.sha),_e.push(e));let ve=_e;_e.length>0&&L.length>0&&(ve=filterEntriesByOkActorDocs(_e,L,await Promise.all(L.map(async t=>{if(t.renameCommit===null)return null;let S=await buildSeeds(e,t.renameCommit,E,Y);return S.length===0?new Set:buildAncestorShaSet(e,S,E,ee)})))),ve.sort((e,t)=>new Date(t.timestamp).getTime()-new Date(e.timestamp).getTime());let ye=ve;ye=ye.filter(e=>e.type!==`park`),k.length>0&&(ye=ye.filter(e=>k.includes(e.type))),j.length>0&&(ye=ye.filter(e=>matchesAuthor(e,j))),F.length>0&&(ye=ye.filter(e=>!matchesAuthor(e,F)));let Ce=ye.length;return{entries:ye.slice(O,O+D).map(({rawBody:e,...t})=>t),total:Ce,hasMore:O+D<Ce}}catch(e){return console.warn(`[timeline] getDocumentHistory failed, returning empty result:`,e),EMPTY}}let _httpDurationHist=null;function httpDurationHist(){return _httpDurationHist||=getMeter().createHistogram(`http.server.request.duration`,{description:`HTTP server request duration in seconds`,unit:`s`}),_httpDurationHist}let _hintEmittedCounter=null;function hintEmittedCounter(){return _hintEmittedCounter||=getMeter().createCounter(`ok.preview_attach.hint_emitted`,{description:`Count of preview-attach hints emitted on write-tool responses when no editor is attached to __system__. Covers both attach-preview-once (URL exists, no browser) and start-ui (no UI running anywhere) variants — the tool side disambiguates via the warning action; the metric name is retained as-is so existing dashboards keep working.`}),_hintEmittedCounter}let _agentPatchFmTouchCounter=null;function agentPatchFmTouchCounter(){return _agentPatchFmTouchCounter||=getMeter().createCounter(`ok.frontmatter.agent_patch_fm_touch_total`,{description:`Count of agent-patch calls whose find string targets the frontmatter region. Measures incidence during the soft-deprecation window before agent-patch FM-intersecting calls are enforced as 400. Bounded label: result ∈ {rejected, pre_deprecation_passthrough}.`}),_agentPatchFmTouchCounter}function findLooksLikeFrontmatter(e){return!!(/(^|\n)---(\s|\n|$)/.test(e)||/^\s*[\w-]+:\s+\S/.test(e))}let _renameAttributionCounter=null;function renameAttributionCounter(){return _renameAttributionCounter||=getMeter().createCounter(`ok.rename.attribution_kind`,{description:`Count of rename and rollback handler dispatches by attribution kind (agent | principal | anonymous)`}),_renameAttributionCounter}const ROLLBACK_ORIGIN={source:`local`,skipStoreHooks:!1,context:{origin:`rollback-apply`,paired:!0}},MANAGED_RENAME_ORIGIN={source:`local`,skipStoreHooks:!1,context:{origin:`managed-rename`,paired:!0}},log$2=getLogger(`api`);function safeDocPath(e,t){if(!e||e.includes(`..`)||e.includes(`\0`))return{error:`Invalid document name.`};let S=t===`.`?``:t.replace(/^\.\//,``),w=getDocExtension(e);return{path:S?`${S}/${e}${w}`:`${e}${w}`}}const GENERIC_PASTE_NAMES=/^(image\.(png|jpe?g|gif|webp)|Clipboard.*|Untitled.*)$/i,SAFE_FILENAME_CHARS=/[^\p{L}\p{N}\p{M}\p{Extended_Pictographic}.\-_ ]/gu,STRIP_ON_SIGHT=/[/\\\x00-\x1f\x7f]/g;function sanitizeFilename(e){let t=e.replace(STRIP_ON_SIGHT,``);if(t=t.replace(SAFE_FILENAME_CHARS,`_`),t=t.replace(/_+/g,`_`).replace(/\.{2,}/g,`.`),t=t.replace(/^[._]+/,``),t=t.replace(/\.+$/,``),t===``)return`upload`;let S=255,w=new TextEncoder;if(w.encode(t).length>255){let e=t.lastIndexOf(`.`),S=e>=0?t.slice(e):``,E=e>=0?t.slice(0,e):t;for(;w.encode(E+S).length>255&&E.length>0;)E=E.slice(0,-1);t=(E||`upload`)+S,w.encode(t).length>255&&(t=`upload`)}return t}function resolveUploadDestDir(e,t,S){let w=t.trim();return w===``||w===`./`?resolve(S,dirname(e)):w===`/`?S:w.startsWith(`./`)?resolve(S,dirname(e),w.slice(2)):resolve(S,w)}function readTempFileHead(e,t){let S=openSync(e,`r`);try{let e=Buffer.alloc(t),w=readSync(S,e,0,t,0);return e.subarray(0,w)}finally{closeSync(S)}}const MAX_DEDUP_SCAN_CANDIDATES=1e3;async function streamingHashFile(e){let t=createHash(`sha256`);return await pipeline(createReadStream(e),t),t.digest(`hex`)}async function findDuplicateAsset(e,t,S){let w;try{w=await readdir(e)}catch{return null}let E=getLogger(`upload`),D=0;for(let O of w){let w=extname(O).slice(1).toLowerCase();if(!ASSET_EXTENSIONS.has(w))continue;let k=resolve(e,O),j;try{j=await stat$1(k)}catch{continue}if(!j.isFile()||j.size!==S)continue;if(D++,D>MAX_DEDUP_SCAN_CANDIDATES)return E.warn({event:`upload-dedup-skip`,reason:`scan-cap-exceeded`,destDir:e,scanned:MAX_DEDUP_SCAN_CANDIDATES,expectedSize:S},`[upload-dedup] candidate scan exceeded ${MAX_DEDUP_SCAN_CANDIDATES} same-size siblings — degrading to no-dedup for this upload`),null;let F;try{F=await streamingHashFile(k)}catch(e){let t=e.code;t!==`ENOENT`&&E.warn({event:`upload-dedup-skip`,reason:`read-failed`,code:t,entry:O},`[upload-dedup] skipped candidate — read failed`);continue}if(F===t)return O}return null}function readUploadBody(e,t){return new Promise((S,w)=>{let E;try{E=(0,import_lib.default)({headers:e.headers,limits:{files:1,fields:10,fieldSize:2*1024}})}catch(e){w(new UploadWriteError(`urn:ok:error:malformed-upload`,e));return}let D=!1,O=`upload`,k=``,j=``,F,L,B=!1,H=(e,t)=>{if(!D){if(D=!0,F)try{unlinkSync(F)}catch{}w(t instanceof UploadWriteError?t:new UploadWriteError(e,t))}},q=classifyUploadErrno;E.on(`field`,(e,t)=>{e===`parentDocName`&&(j=t)}),E.on(`file`,(e,w,E)=>{B=!0,O=E.filename||`upload`,k=E.mimeType||``;let J;try{J=mintTempUploadPath(t)}catch(e){H(q(e),e),w.resume();return}F=J;let Y=new HashingPassThrough;pipeline(w,Y,createWriteStream(J)).then(()=>{D||(D=!0,S({filename:O,mimeType:k,parentDocName:j,tempPath:J,sha:Y.digest(),byteLength:Y.byteLength()}))}).catch(e=>{L=e,H(q(e),e)})}),E.on(`error`,e=>{H(`urn:ok:error:malformed-upload`,e)}),E.on(`close`,()=>{D||L||B||(D=!0,S({filename:``,mimeType:``,parentDocName:j,tempPath:``,sha:``,byteLength:0}))}),e.on(`close`,()=>{D||L||e.complete||H(`urn:ok:error:malformed-upload`,Error(`client disconnected`))}),e.pipe(E)})}function safeSubdir(e,t){let S=resolve(e,t);if(S!==e&&!S.startsWith(`${e}/`))throw Error(`Invalid directory: ${t}`);return S}function synthesizeShowAllAssetExt(e){let t=extname(e);return t?t.slice(1).toLowerCase():e.startsWith(`.`)&&e.length>1?e.slice(1).toLowerCase():`file`}async function walkContentDirForShowAll(e){let{contentDir:t,contentFilter:S,dirFilter:w,documents:E,getDocExtension:D}=e,O=e=>w?e===w||e.startsWith(`${w}/`):!0,k;try{k=await realpath(t)}catch{k=t}let j=e=>e===k?!0:e.startsWith(`${k}/`);async function F(e,t){let w;try{w=await readdir(e,{withFileTypes:!0})}catch(t){console.warn(`[document-list][showAll] readdir failed for ${e}:`,t);return}for(let k of w){let w=t?`${t}/${k.name}`:k.name;if(k.isDirectory()){if(S.isDirExcluded(w,{bypassFilters:!0}))continue;let t=`${e}/${k.name}`,D;try{D=await realpath(t)}catch(e){console.warn(`[document-list][showAll] realpath failed for ${t}:`,e);continue}if(!j(D)){console.warn(`[document-list][showAll] refusing symlink-escape ${t} -> ${D}`);continue}if(O(w)){let e=null;try{e=await stat$1(t)}catch(e){console.warn(`[document-list][showAll] stat failed for ${t}:`,e)}E.push({kind:`folder`,path:w,size:0,modified:e?e.mtime.toISOString():``,docExt:`.md`,isSymlink:!1,canonicalDocName:null,targetPath:null})}await F(t,w);continue}if(!k.isFile()||S.isExcluded(w,{bypassFilters:!0})||!O(w))continue;let L=null;try{L=await stat$1(`${e}/${k.name}`)}catch(t){console.warn(`[document-list][showAll] stat failed for ${e}/${k.name}:`,t);continue}if(isSupportedDocFile(k.name)){let e=w.replace(/\.(md|mdx)$/i,``),t=D(e);E.push({kind:`document`,docName:e,docExt:t,size:L.size,modified:L.mtime.toISOString(),isSymlink:!1,canonicalDocName:null,targetPath:null});continue}let B=synthesizeShowAllAssetExt(k.name),H=ASSET_EXTENSIONS.has(B)?mediaKindForSidebarAssetExtension(B):null;E.push({kind:`asset`,docName:w,docExt:B,path:w,assetExt:B,mediaKind:H,referencedBy:[],size:L.size,modified:L.mtime.toISOString(),isSymlink:!1,canonicalDocName:null,targetPath:null})}}await F(w?`${t}/${w}`:t,w??``)}function isValidRelativeContentPath(e){return!e||e.startsWith(`/`)||e.includes(`\\`)||e.includes(`\0`)?!1:e.split(`/`).every(e=>e&&e!==`.`&&e!==`..`)}function listAffectedDocNames(e,t,S){let w=[...e.keys()].filter(e=>t===`file`?e===S:e===S||e.startsWith(`${S}/`));return w.sort((e,t)=>e.localeCompare(t)),w}function remapDocNameForRename(e,t,S,w){return t===`file`||e===S?w:`${w}${e.slice(S.length)}`}function assertNoSymlinkEscape(e,t){let S;try{S=realpathSync(t)}catch(e){throw e.code===`ENOENT`?new SymlinkEscapeError(`content directory does not exist`):e}let w=e;for(;;)try{if(!isWithinContentDir(realpathSync(w),S))throw new SymlinkEscapeError(`path resolves outside content directory`);return}catch(e){let S=e.code;if(S===`ELOOP`)throw new SymlinkEscapeError(`symlink cycle in path`);if(S!==`ENOENT`)throw e;let E=dirname(w);if(E===w||E!==t&&!E.startsWith(`${t}${sep}`))throw e;w=E}}function resolveContentEntryPath(e,t,S){if(!isValidRelativeContentPath(S))throw Error(`path must be a relative content path`);let w=resolve(e),E=resolve(w,t===`file`?isSupportedDocFile(S)?S:`${S}${getDocExtension(S)}`:S);if(E!==w&&!E.startsWith(`${w}${sep}`))throw Error(`path must not escape content directory`);return assertNoSymlinkEscape(E,w),E}function probeAndRegisterSourceFileExtension(e,t){if(!isValidRelativeContentPath(t))return;let S=resolve(e);for(let e of SUPPORTED_DOC_EXTENSIONS){let w=resolve(S,`${t}${e}`);if(!(w!==S&&!w.startsWith(`${S}${sep}`))&&existsSync(w)){registerDocExtension(t,e);return}}}function toGitRelativePath(e,t){let S=resolve(e),w=resolve(t);return w!==S&&!w.startsWith(`${S}${sep}`)?null:relative(S,w).split(sep).join(`/`)}async function renameTrackedPathInGit(e,t,S){if(!e)return!1;let w=toGitRelativePath(e,t),E=toGitRelativePath(e,S);return!w||!E?!1:await withParentLock(async()=>{let t=esm_default({baseDir:e,timeout:{block:15e3}}),D=``;try{D=(await t.raw(`ls-files`,`--`,w)).trim()}catch(e){return console.warn(`[renameTrackedPathInGit] git ls-files failed, falling back to fs rename:`,e),!1}if(!D)return!1;mkdirSync(dirname(S),{recursive:!0});try{return await t.raw(`mv`,`--`,w,E),!0}catch(e){return console.warn(`[renameTrackedPathInGit] git mv failed, falling back to fs rename:`,e),!1}})}const workspaceSearchCaches=new Map;function extractHeadings(e){let t=e;if(e.startsWith(`---
|
|
2103
2103
|
`)||e.startsWith(`---\r
|
|
2104
2104
|
`)){let S=e.indexOf(`
|
|
2105
2105
|
---`,3);S!==-1&&(t=e.slice(S+4))}let S=[],w=new Map,E=createCodeFenceTracker();for(let e of t.split(`
|
|
2106
|
-
`)){if(E(e))continue;let t=e.match(/^(#{1,6})\s+(.+)$/);if(t){let e=t[2].trim(),E=getHeadingSlug(e,w);E&&S.push({level:t[1].length,text:e,slug:E})}}return S}function isSafeDocName(e){return!(e.includes(`..`)||e.startsWith(`/`)||e.includes(`\0`)||e.includes(`\\`))}function createApiExtension(e){let{hocuspocus:t,sessionManager:S,contentDir:w,serverInstanceId:E,getFileIndex:D,getFolderIndex:O,getAliasMap:k,rescanFiles:j,enableTestRoutes:F=!1,shadowRef:L,flushGitCommit:B,flushContributors:H,getCurrentBranch:q,getDiskAckSVs:J,contentRoot:Y,backlinkIndex:ee,tagIndex:te,signalChannel:ne,agentFocusBroadcaster:ae,agentPresenceBroadcaster:oe,onAgentWrite:se,getSyncEngine:ce,localOpCliArgs:ue=[`open-knowledge`],projectDir:de,getPrincipal:fe,contentFilter:me,installedAgentsProbe:ge,forceUnloadDocument:_e,ready:ve,recentlyRemovedDocs:ye}=e,Ce=createConcurrencyGuard(),we=null;function Te(){let e=O?.();return e instanceof Map?e:null}function De(e){let t=Te();if(t)try{upsertFolderIndexEntry(t,w,e,statSync(e),e)}catch(t){console.warn(`[api-extension] folder index stat failed for ${e}:`,t)}}function je(e){let t=e.split(`/`).filter(Boolean);for(let e=1;e<=t.length;e+=1)De(resolve(w,t.slice(0,e).join(`/`)))}function Me(e){let t=Te();t&&removeFolderIndexEntries(t,e)}function Pe(e,t){let S=Te();if(!S)return;let E=[];for(let[w,D]of
|
|
2106
|
+
`)){if(E(e))continue;let t=e.match(/^(#{1,6})\s+(.+)$/);if(t){let e=t[2].trim(),E=getHeadingSlug(e,w);E&&S.push({level:t[1].length,text:e,slug:E})}}return S}function isSafeDocName(e){return!(e.includes(`..`)||e.startsWith(`/`)||e.includes(`\0`)||e.includes(`\\`))}function createApiExtension(e){let{hocuspocus:t,sessionManager:S,contentDir:w,serverInstanceId:E,getFileIndex:D,getFolderIndex:O,getAliasMap:k,rescanFiles:j,enableTestRoutes:F=!1,shadowRef:L,flushGitCommit:B,flushContributors:H,getCurrentBranch:q,getDiskAckSVs:J,contentRoot:Y,backlinkIndex:ee,tagIndex:te,signalChannel:ne,agentFocusBroadcaster:ae,agentPresenceBroadcaster:oe,onAgentWrite:se,getSyncEngine:ce,localOpCliArgs:ue=[`open-knowledge`],projectDir:de,getPrincipal:fe,contentFilter:me,installedAgentsProbe:ge,forceUnloadDocument:_e,ready:ve,recentlyRemovedDocs:ye}=e,Ce=createConcurrencyGuard(),we=null;function Te(){let e=O?.();return e instanceof Map?e:null}function De(e){let t=Te();if(t)try{upsertFolderIndexEntry(t,w,e,statSync(e),e)}catch(t){console.warn(`[api-extension] folder index stat failed for ${e}:`,t)}}function je(e){let t=e.split(`/`).filter(Boolean);for(let e=1;e<=t.length;e+=1)De(resolve(w,t.slice(0,e).join(`/`)))}function Me(e){let t=Te();t&&removeFolderIndexEntries(t,e)}function Pe(e,t){let S=Te();if(!S)return;let E=[];for(let[w,D]of S.entries()){if(w!==e&&!w.startsWith(`${e}/`))continue;S.delete(w);let O=w.slice(e.length);E.push([`${t}${O}`,D])}if(E.length===0){let e=resolveContentEntryPath(w,`folder`,t);existsSync(e)&&De(e);return}for(let[e,t]of E)S.set(e,{...t,modified:new Date().toISOString(),canonicalPath:resolve(w,e)})}function Ie(e){return[...e.entries()].map(([e,t])=>`${e}\0${t.canonicalPath}\0${t.size}\0${t.modified}\0${t.aliases.join(`\0`)}`).sort().join(`
|
|
2107
2107
|
`)}let Re=createInstalledAgentsProbe({probe:ge??createOsProbe(process.platform)});function ze(e){if(!isSafeDocName(e))return null;let t=resolve(w),S=resolve(t,`${e}${getDocExtension(e)}`);return!S.startsWith(`${t}/`)&&S!==t?null:S}function Be(e){let t=ze(e);if(!t||!existsSync(t))return e;try{return extractPageTitle(readFileSync(t,`utf-8`),e)}catch{return e}}function Ve(e,t){return t.has(e)?Be(e):e}let Ue={cluster:void 0,category:void 0,tags:void 0};function We(e){try{let S=t.documents.get(e);if(S){let e=readFmMap(S.getText(`source`).toString());if(Object.keys(e).length>0){let t=typeof e.cluster==`string`?e.cluster:void 0,S=typeof e.category==`string`?e.category:void 0,w;return Array.isArray(e.tags)?w=e.tags.length>0?e.tags:void 0:typeof e.tags==`string`&&e.tags&&(w=[e.tags]),{cluster:t,category:S,tags:w}}}}catch{}try{let t=ze(e);if(!t||!existsSync(t))return Ue;let{frontmatter:S}=stripFrontmatter(readFileSync(t,`utf-8`));return S?parseFrontmatterMetadata(S):Ue}catch{return Ue}}function Ge(e,t){return t.has(e)?We(e):Ue}function Ke(e){if(ee)try{if(ee.getBacklinks(e).length>0)return;let t=performance.now(),S=findHubCandidates(e,D()),w=performance.now()-t;return w>5&&log$2.debug({docName:e,elapsedMs:w,candidateCount:S.length},`[orphan-hint] findHubCandidates slow`),S.length===0?void 0:[{type:`orphan`,parentCandidates:S,message:`This doc has no backlinks yet. To make it discoverable, consider linking from a parent hub doc (index/overview files in the folder tree): ${S.map(e=>`[[${e}]]`).join(`, `)}.`}]}catch(e){console.warn(`[orphan-hint] computeOrphanHints failed:`,e);return}}function Xe(e){return k?.().get(e)??e}function $e(e){try{return t.documents.get(e)?.connections.size??0}catch{return 0}}function nt(){try{return t.documents.get(`__system__`)?.connections.size??0}catch{return 0}}function rt(e,S){let w=`onStoreDocument-${e}`;(t.debouncer.isDebounced(w)?t.debouncer.executeNow(w):Promise.resolve()).then(()=>B?.()).catch(e=>{log$2.warn({err:e},`[${S}] post-write flush failed`)})}function it(){let e=new Set;for(let[t,S]of D()){e.add(t);for(let t of S.aliases)e.add(t)}return e}function at(){let e=Promise.resolve();return async function(t){let S=e,w=()=>{};e=new Promise(e=>{w=e}),await S;try{return await t()}finally{w()}}}let st=at(),vt=e=>e.endsWith(`.`)?e:`${e}.`;function Tt(e){return e instanceof Error?e instanceof ManagedRenameSourceNotFoundError?{status:404,type:`urn:ok:error:doc-not-found`,error:vt(e.message)}:e instanceof ManagedRenameDestinationExistsError?{status:409,type:`urn:ok:error:doc-already-exists`,error:vt(e.message)}:e instanceof ManagedRenameSourceTypeMismatchError?{status:400,type:`urn:ok:error:invalid-request`,error:vt(e.message)}:e instanceof ManagedRenameMissingDocumentError||e instanceof ManagedRenameSnapshotMissingError?{status:404,type:`urn:ok:error:doc-not-found`,error:vt(e.message)}:e instanceof SymlinkEscapeError?{status:400,type:`urn:ok:error:path-escape`,error:vt(e.message)}:e instanceof BacklinkIndexRequiredError?{status:503,type:`urn:ok:error:backlink-index-not-configured`,error:vt(e.message)}:{status:500,type:`urn:ok:error:internal-server-error`,error:`Failed to rename document.`}:{status:500,type:`urn:ok:error:internal-server-error`,error:`Failed to rename document.`}}async function Et(e){let w=new Map;for(let S of e){let e=t.documents.get(S);e&&w.set(S,e.getText(`source`).toString())}for(let t of e)await S.closeAllForDoc(t).catch(e=>{console.warn(`[file-ops] Failed to close agent session for ${t}:`,e)});for(let S of e){let e=t.documents.get(S);deleteReconciledBase(S),e&&(t.closeConnections(S),await(_e??t.unloadDocument.bind(t))(e))}return w}function Dt(e,t){for(let{fromDocName:S,toDocName:E}of e){let e=safeContentPath(E,w),D=t.get(S);typeof D==`string`&&tracedWriteFileSync(e,D,`utf-8`);let O=typeof D==`string`?D:existsSync(e)?readFileSync(e,`utf-8`):null;typeof O==`string`&®isterWrite(e,contentHash(O))}}function jt(e,t){return e.map(e=>{let S=t.get(e);if(typeof S==`string`)return{docName:e,content:S};let E=safeContentPath(e,w);if(!existsSync(E))throw new ManagedRenameSnapshotMissingError(e);return{docName:e,content:readFileSync(E,`utf-8`)}})}function Mt(e){let S=t.documents.get(e);if(S)return S.getText(`source`).toString();let E=resolveContentEntryPath(w,`file`,e);return existsSync(E)?readFileSync(E,`utf-8`):null}function Ft(e,t){let S=resolveContentEntryPath(w,`file`,e);tracedMkdirSync(dirname(S),{recursive:!0}),tracedWriteFileSync(S,t,`utf-8`),registerWrite(S,contentHash(t)),setReconciledBase(e,t);let E=D();E instanceof Map&&updateFileIndex({kind:`update`,path:S,docName:e,content:t},E)}function It(e,S){let w=t.documents.get(e);if(!w)throw Error(`Document is not loaded: ${e}`);let E={markdown:``,rewrites:0};return w.transact(()=>{E=applyRenameMap(w.getText(`source`).toString(),e,S),E.rewrites!==0&&composeAndWriteRawBody(w,E.markdown,`managed-rename`,!1)},MANAGED_RENAME_ORIGIN),E}async function Lt(e,S,E,O){return st(async()=>withSpan(`rename.executeRewrites`,{attributes:{"rename.kind":E}},async k=>{if(!ee)throw new BacklinkIndexRequiredError;let j=resolveContentEntryPath(w,E,e),F=resolveContentEntryPath(w,E,S);if(j===F)return{renamed:[],rewrittenDocs:[]};if(!existsSync(j))throw new ManagedRenameSourceNotFoundError(E);if(existsSync(F))throw new ManagedRenameDestinationExistsError;let B=statSync(j);if(E===`file`&&!B.isFile()||E===`folder`&&!B.isDirectory())throw new ManagedRenameSourceTypeMismatchError(E);let H=(E===`file`?[stripDocExtension(e)]:listAffectedDocNames(D(),E,e)).map(t=>({from:t,to:E===`file`?stripDocExtension(S):remapDocNameForRename(t,E,e,S)}));if(k.setAttribute(`rename.affected_docs`,H.length),H.length===0)return E===`folder`&&(await renameTrackedPathInGit(de,j,F)||(tracedMkdirSync(dirname(F),{recursive:!0}),tracedRenameSync(j,F)),Pe(e,S),ne?.(`files`)),{renamed:[],rewrittenDocs:[]};let J=buildRenameMap(H),Y=H.map(({from:e,to:t})=>({fromDocName:e,toDocName:t})),te=new Set;for(let{from:e}of H)for(let t of ee.getBacklinks(e))J.has(t.source)||te.add(t.source);let ae=[...te].sort((e,t)=>e.localeCompare(t)),oe=new Map,se=[],ce=[];for(let e of[...J.keys(),...ae]){if(oe.has(e))continue;if(!J.has(e)&&!existsSync(resolveContentEntryPath(w,`file`,e))){ce.push(e);continue}let t=Mt(e);typeof t==`string`?(oe.set(e,t),J.has(e)||se.push(e)):J.has(e)||ce.push(e)}for(let{from:e}of H)if(typeof oe.get(e)!=`string`)throw new ManagedRenameMissingDocumentError(e);let ue=createManagedRenameRecoveryJournal({fromPath:e,toPath:S,affectedDocs:[...H],snapshots:jt([...oe.keys()],oe)}),fe=[];return await withManagedRenameRecovery(de??w,ue,async()=>{for(let e of ce)ee.deleteDocument(e);for(let e of se){let S=t.documents.get(e)?It(e,J):applyRenameMap(oe.get(e)??``,e,J);S.rewrites>0&&(Ft(e,S.markdown),fe.push({docName:e,rewrites:S.rewrites})),ee.updateDocumentFromMarkdown(e,S.markdown)}if(ye)for(let{from:e,to:t}of H)isSystemDoc(e)||isConfigDoc(e)||(ye.setRenamed(e,t),console.info(JSON.stringify({event:`recently-removed-docs-populate`,from:e,to:t,kind:`renamed`,source:`spine`})));let k=resolveContentEntryPath(w,E,e),j=resolveContentEntryPath(w,E,S);await renameTrackedPathInGit(de,k,j)||(tracedMkdirSync(dirname(j),{recursive:!0}),tracedRenameSync(k,j)),E===`folder`&&Pe(e,S);let F=await Et([...J.keys()]);if(process.env.NODE_ENV===`test`&&process.env.OK_TEST_RENAME_FAULT===`pre-append`)throw Error(`OK_TEST_RENAME_FAULT=pre-append`);if(L?.current){let e=L.current;withSpanSync(`rename.appendLog`,{attributes:{"rename.kind":E}},t=>{let S=randomUUID(),w=new Date().toISOString(),D=q?.()??`main`,k=getOrLoadRenameLogIndex(e.gitDir),j=O?.actor?{writerId:O.actor.writerId,displayName:O.actor.displayName}:{writerId:SERVICE_WRITER.id,displayName:SERVICE_WRITER.name},F=0;for(let{from:t,to:L}of H){let B={v:1,from:t,to:L,at:w,commitSha:``,branch:D,groupId:S,kind:E,actor:j};appendRenameLogEntry(e.gitDir,B,k,e),F+=1,O?.actor?recordContributor(L,O.actor.writerId,O.actor.displayName,O.actor.colorSeed,formatRenameSubject(t,L),O.actor.actorMetadata,void 0,[{from:t,to:L}]):recordContributor(L,SERVICE_WRITER.id,SERVICE_WRITER.name,SERVICE_WRITER.id,formatRenameSubject(t,L),void 0,void 0,[{from:t,to:L}])}t.setAttribute(`rename.entries_appended`,F)})}let B=E===`file`&&isSupportedDocFile(S)?extname(S):null;for(let{from:e,to:t}of H){let S=getDocExtension(e);forgetDocExtension(e),registerDocExtension(t,B??S)}let Y=[...H].sort((e,t)=>e.from.localeCompare(t.from));for(let{from:e,to:t}of Y){let S=resolveContentEntryPath(w,`file`,e),E=resolveContentEntryPath(w,`file`,t),O=applyRenameMap(F.get(e)??oe.get(e)??readFileSync(E,`utf-8`),e,J);Dt([{fromDocName:e,toDocName:t}],new Map([[e,O.markdown]])),setReconciledBase(t,O.markdown);let k=D();k instanceof Map&&updateFileIndex({kind:`rename`,oldPath:S,newPath:E,oldDocName:e,newDocName:t,content:O.markdown},k),ee.renameDocument(e,t,O.markdown),O.rewrites>0&&fe.push({docName:t,rewrites:O.rewrites})}if(process.env.NODE_ENV===`test`&&process.env.OK_TEST_RENAME_FAULT===`pre-journal-clear`)throw Error(`OK_TEST_RENAME_FAULT=pre-journal-clear`)}),ee.saveToDisk().catch(t=>{console.warn(`[backlinks] Failed to persist managed rename cache for ${e} -> ${S}:`,t)}),ne?.(`files`),ne?.(`backlinks`),ne?.(`graph`),fe.sort((e,t)=>e.docName.localeCompare(t.docName)),k.setAttribute(`rename.rewrite_count`,fe.length),{renamed:Y,rewrittenDocs:fe}}))}function Rt(e){let t=parseAgentBodyFields(e),S=t.writerId??`claude-1`;return{rawAgentId:t.rawAgentId,agentId:S,agentName:t.displayName,colorSeed:t.colorSeed??t.rawAgentId??S,clientName:t.clientName,clientVersion:t.clientVersion,label:t.label}}function zt(e){return{principalId:fe?.()?.id,agentType:resolveAgentType(e.clientName),clientName:e.clientName,clientVersion:e.clientVersion,label:e.label}}function Bt(e){return e.kind===`value`?e.truncatedFrom===void 0?{response:{value:e.value},stored:e.value}:{response:{value:e.value,truncatedFrom:e.truncatedFrom,hint:`Summary truncated from ${e.truncatedFrom} chars to 80 (max 80).`},stored:e.value}:{stored:void 0}}function Vt(e){return{value:e.value}}function Ht(e,t=!1){e.kind===`value`&&(incrementSummariesProvided(),e.truncatedFrom!==void 0&&!t&&incrementSummariesTruncated())}let Ut=withValidation(AgentWriteRequestSchema,async(t,w,E)=>{try{let t=Xe(E.docName!==void 0&&E.docName.length>0?E.docName:`test-doc`),{agentId:D,agentName:O,colorSeed:k,clientName:j,clientVersion:F,label:L}=Rt(E);if(isSystemDoc(t)||isConfigDoc(t)){errorResponse(w,400,`urn:ok:error:reserved-doc-name`,`'${t}' is a reserved document name.`,{handler:`agent-write`});return}let B=normalizeSummary(E.summary),H=await S.getSession(t,D,{displayName:O,colorSeed:k,clientName:j}),q=new Date().toISOString(),J=typeof E.content==`string`?E.content:`Hello from the agent! ${q}`,{response:Y,stored:ee}=Bt(B);try{let S=iconFromClientName(j),w=AGENT_ICON_COLORS[S]??colorFromSeed(k??D);oe?.setPresence(D,{displayName:O,icon:S,color:w,currentDoc:t,mode:`writing`,ts:Date.now()}),captureEffect(H.dc.document.getText(`source`),D,k,j),H.dc.document.transact(()=>{applyAgentMarkdownWrite(H.dc.document,`${J}\n`,`append`,e.resolveEmbed?{resolveEmbed:e.resolveEmbed,sourcePath:t}:void 0),H.dc.document.getMap(`agent-flash`).set(D,{agentId:D,timestamp:Date.now(),type:`insert`,description:`Added (${O}): ${J.slice(0,50)}`})},H.origin),recordContributor(t,D,O,k,void 0,zt({clientName:j,clientVersion:F,label:L}),ee),incrementAgentWriteCalls(),Ht(B)}finally{oe?.touchMode(D,`idle`)}rt(t,`agent-write`),se?.(),successResponse(w,200,AgentWriteSuccessSchema,{timestamp:q,...Y?{summary:Y}:{}},{handler:`agent-write`})}catch(e){if(e instanceof AgentSessionCapacityError){errorResponse(w,503,`urn:ok:error:too-many-agent-sessions`,`Too many agent sessions.`,{handler:`agent-write`,cause:e,extraHeaders:{"Retry-After":`10`}});return}log$2.error({err:e},`[agent-write] handler failed`),errorResponse(w,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`agent-write`,cause:e})}},{handler:`agent-write`,method:`POST`}),Wt=withValidation(AgentWriteMdRequestSchema,async(t,w,E)=>{try{let t=E.position??`append`,D=Xe(E.docName!==void 0&&E.docName.length>0?E.docName:`test-doc`),{agentId:O,agentName:k,colorSeed:j,clientName:F,clientVersion:L,label:B}=Rt(E);if(isSystemDoc(D)||isConfigDoc(D)){errorResponse(w,400,`urn:ok:error:reserved-doc-name`,`'${D}' is a reserved document name.`,{handler:`agent-write-md`});return}let H=normalizeSummary(E.summary),{response:q,stored:J}=Bt(H),Y=await S.getSession(D,O,{displayName:k,colorSeed:j,clientName:F}),ee=new Date().toISOString();try{let S=iconFromClientName(F),w=AGENT_ICON_COLORS[S]??colorFromSeed(j??O);oe?.setPresence(O,{displayName:k,icon:S,color:w,currentDoc:D,mode:`writing`,ts:Date.now()}),captureEffect(Y.dc.document.getText(`source`),O,j,F),Y.dc.document.transact(()=>{applyAgentMarkdownWrite(Y.dc.document,E.markdown,t,e.resolveEmbed?{resolveEmbed:e.resolveEmbed,sourcePath:D}:void 0),Y.dc.document.getMap(`agent-flash`).set(O,{agentId:O,timestamp:Date.now(),type:`insert`,description:`Added (${k}): ${E.markdown.trim().slice(0,50)}`})},Y.origin),recordContributor(D,O,k,j,void 0,zt({clientName:F,clientVersion:L,label:B}),J),incrementAgentWriteCalls(),Ht(H)}finally{oe?.touchMode(O,`idle`)}rt(D,`agent-write-md`),ae?.setFocus(O,{agentName:k,currentDoc:D,writeKind:`write`,ts:Date.now()}),se?.();let te=Ke(D),ne=$e(D),ce=nt();ce===0&&hintEmittedCounter().add(1,{"shadow.writer":`agent`,"agent.type":resolveAgentType(F)}),successResponse(w,200,AgentWriteMdSuccessSchema,{timestamp:ee,subscriberCount:ne,systemSubscriberCount:ce,...te?{hints:te}:{},...q?{summary:q}:{}},{handler:`agent-write-md`})}catch(e){if(e instanceof AgentSessionCapacityError){errorResponse(w,503,`urn:ok:error:too-many-agent-sessions`,`Too many agent sessions.`,{handler:`agent-write-md`,cause:e,extraHeaders:{"Retry-After":`10`}});return}log$2.error({err:e},`[agent-write-md] handler failed`),errorResponse(w,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`agent-write-md`,cause:e})}},{handler:`agent-write-md`,method:`POST`}),Kt=withValidation(FrontmatterPatchRequestSchema,async(e,t,w)=>{try{let e=Xe(w.docName!==void 0&&w.docName.length>0?w.docName:`test-doc`),{agentId:E,agentName:D,colorSeed:O,clientName:k,clientVersion:j,label:F}=Rt(w);if(isSystemDoc(e)||isConfigDoc(e)){errorResponse(t,400,`urn:ok:error:reserved-doc-name`,`'${e}' is a reserved document name.`,{handler:`frontmatter-patch`});return}let L=w.patch??{},B=Object.keys(L),H=normalizeSummary(w.summary),{response:q,stored:J}=Bt(H),Y=await S.getSession(e,E,{displayName:D,colorSeed:O,clientName:k}),ee=new Date().toISOString(),te,ne=!1,ce=[];try{let t=iconFromClientName(k),S=AGENT_ICON_COLORS[t]??colorFromSeed(O??E);oe?.setPresence(E,{displayName:D,icon:t,color:S,currentDoc:e,mode:`writing`,ts:Date.now()}),withSpanSync(`ok.frontmatter_patch`,{attributes:{"doc.name":e,"frontmatter_patch.keys":B.length}},()=>{Y.dc.document.transact(()=>{let{fenced:e,body:t}=detectFmRegion(Y.dc.document.getText(`source`).toString()),S=applyPatchToFm(e,L);if(!S.ok){te=S.error;return}for(let e of Object.keys(L))ce.push(e);if(S.nextFenced!==e){let e=S.nextFenced+t;composeAndWriteRawBody(Y.dc.document,e,`agent`),recordFrontmatterEditSurface(`mcp-write`)}ne=!0},Y.origin)})}finally{oe?.touchMode(E,`idle`)}if(te){let e;switch(te.kind){case`invalid_value`:e={[te.key]:te.reason};break;case`reserved_key`:e={[te.key]:`'${te.key}' is reserved`};break;case`unknown_key`:e={[te.key]:`'${te.key}' is not a recognized key`};break;case`duplicate_target`:e={[te.key]:`'${te.key}' appears more than once`};break;case`reorder_mismatch`:e={__region__:`frontmatter reorder mismatch (expected: ${te.expected.join(`, `)}; got: ${te.got.join(`, `)})`};break;case`region_too_large`:e={__region__:`frontmatter region too large (${te.bytes} > ${te.limit} bytes)`};break;case`parse_failed`:e={__region__:`frontmatter region unparseable: ${te.reason}`};break;default:e={__region__:`unhandled frontmatter edit error (${String(te)})`}}errorResponse(t,400,`urn:ok:error:invalid-frontmatter-patch`,`Frontmatter patch rejected: schema validation failed.`,{handler:`frontmatter-patch`,extensions:{fieldErrors:e}});return}ne&&ce.length>0&&(recordContributor(e,E,D,O,void 0,zt({clientName:k,clientVersion:j,label:F}),J),incrementAgentWriteCalls(),Ht(H),rt(e,`frontmatter-patch`)),ae?.setFocus(E,{agentName:D,currentDoc:e,writeKind:`write`,ts:Date.now()}),se?.();let ue=$e(e),de=nt();de===0&&hintEmittedCounter().add(1,{"shadow.writer":`agent`,"agent.type":resolveAgentType(k)}),successResponse(t,200,FrontmatterPatchSuccessSchema,{timestamp:ee,subscriberCount:ue,systemSubscriberCount:de,appliedKeys:ce,...q?{summary:q}:{}},{handler:`frontmatter-patch`})}catch(e){if(e instanceof AgentSessionCapacityError){errorResponse(t,503,`urn:ok:error:too-many-agent-sessions`,`Too many agent sessions.`,{handler:`frontmatter-patch`,cause:e,extraHeaders:{"Retry-After":`10`}});return}log$2.error({err:e},`[frontmatter-patch] handler failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`frontmatter-patch`,cause:e})}},{handler:`frontmatter-patch`,method:`POST`}),$t=withValidation(EmptyRequestSchema,async(e,S)=>{try{let E=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`).searchParams.get(`docName`)||`test-doc`;if(!isSafeDocName(E)){errorResponse(S,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`document-read`});return}let D=Xe(E);if(isSystemDoc(D)||isConfigDoc(D)){errorResponse(S,400,`urn:ok:error:reserved-doc-name`,`'${D}' is a reserved document name.`,{handler:`document-read`});return}let O=t.documents.get(D);if(O){successResponse(S,200,DocumentReadSuccessSchema,{docName:D,content:O.getText(`source`).toString()},{handler:`document-read`});return}if(!existsSync(resolveContentEntryPath(w,`file`,D))){errorResponse(S,404,`urn:ok:error:doc-not-found`,`Document not found: ${D}.`,{handler:`document-read`});return}let k=await t.openDirectConnection(D);try{let e=k.document;if(!e){errorResponse(S,500,`urn:ok:error:doc-not-available`,`Document is not available.`,{handler:`document-read`});return}successResponse(S,200,DocumentReadSuccessSchema,{docName:D,content:e.getText(`source`).toString()},{handler:`document-read`})}finally{await k.disconnect()}}catch(e){errorResponse(S,500,`urn:ok:error:internal-server-error`,`Failed to read document.`,{handler:`document-read`,cause:e})}},{handler:`document-read`,method:`GET`,skipBodyParse:!0}),en=withValidation(EmptyRequestSchema,async(e,t)=>{try{ve&&await ve.catch(e=>{log$2.warn({err:e,handler:`document-list`},`[api] ready gate rejected — responding with partial index`)});let S=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`),E=S.searchParams.get(`dir`),k=S.searchParams.get(`showAll`)===`true`;if(E)try{safeSubdir(w,E)}catch{errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid directory parameter.`,{handler:`document-list`});return}if(k&&me){let e=[];try{await walkContentDirForShowAll({contentDir:w,contentFilter:me,dirFilter:E,documents:e,getDocExtension}),e.sort((e,t)=>{let S=e.kind===`folder`?e.path??``:e.docName??e.path??``,w=t.kind===`folder`?t.path??``:t.docName??t.path??``;return S.localeCompare(w)}),successResponse(t,200,DocumentListSuccessSchema,{documents:e},{handler:`document-list`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to list documents (showAll mode).`,{handler:`document-list`,cause:e})}return}let j=D(),F=O?.()??new Map,L=[];for(let[e,t]of F)E&&!e.startsWith(`${E}/`)&&e!==E||L.push({kind:`folder`,path:e,size:0,modified:t.modified,docExt:`.md`,isSymlink:!1,canonicalDocName:null,targetPath:null});for(let[e,t]of j){if(E&&!e.startsWith(`${E}/`)&&e!==E)continue;let S=getDocExtension(e);L.push({kind:`document`,docName:e,docExt:S,size:t.size,modified:t.modified,isSymlink:!1,canonicalDocName:null,targetPath:null});for(let D of t.aliases){if(E&&!D.startsWith(`${E}/`)&&D!==E)continue;let O=relative(w,t.canonicalPath);L.push({kind:`document`,docName:D,docExt:S,size:t.size,modified:t.modified,isSymlink:!0,canonicalDocName:e,targetPath:O})}}let B=[];try{let e=Ie(j);we?.signature!==e&&(we={signature:e,assets:collectReferencedAssets({contentDir:w,fileIndex:j,readMarkdown:e=>{try{return readFileSync(e,`utf-8`)}catch{return null}},isExcluded:me?e=>me.isPathIgnored(e):void 0})}),B=we?.assets??[]}catch(e){we=null,console.warn(`[document-list] asset collection failed; returning documents only:`,e)}for(let e of B)E&&!e.path.startsWith(`${E}/`)&&e.path!==E||L.push({kind:`asset`,docName:e.path,docExt:e.assetExt,path:e.path,assetExt:e.assetExt,mediaKind:e.mediaKind,referencedBy:e.referencedBy,size:e.size,modified:e.modified,isSymlink:!1,canonicalDocName:null,targetPath:null});L.sort((e,t)=>{let S=e.kind===`folder`?e.path??``:e.docName??e.path??``,w=t.kind===`folder`?t.path??``:t.docName??t.path??``;return S.localeCompare(w)}),successResponse(t,200,DocumentListSuccessSchema,{documents:L},{handler:`document-list`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to list documents.`,{handler:`document-list`,cause:e})}},{handler:`document-list`,method:`GET`,skipBodyParse:!0}),jr=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ee){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`backlinks`});return}try{let S=new URL(e.url??``,`http://localhost`).searchParams.get(`docName`);if(!S){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing docName parameter.`,{handler:`backlinks`});return}if(!isSafeDocName(S)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`backlinks`});return}successResponse(t,200,BacklinksSuccessSchema,{docName:S,backlinks:ee.getBacklinks(S).map(e=>({source:e.source,anchor:e.anchor,title:Be(e.source),snippet:e.snippet}))},{handler:`backlinks`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read backlinks.`,{handler:`backlinks`,cause:e})}},{handler:`backlinks`,method:`GET`,skipBodyParse:!0}),Mr=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ee){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`backlink-counts`});return}try{let S=new URL(e.url??``,`http://localhost`).searchParams.get(`docNames`);if(!S){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing docNames parameter.`,{handler:`backlink-counts`});return}let w={};for(let e of S.split(`,`)){let t=e.trim();!t||!isSafeDocName(t)||(w[t]=ee.getBacklinkCount(t))}successResponse(t,200,BacklinkCountsSuccessSchema,{counts:w},{handler:`backlink-counts`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read backlink counts.`,{handler:`backlink-counts`,cause:e})}},{handler:`backlink-counts`,method:`GET`,skipBodyParse:!0}),Fr=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ee){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`forward-links`});return}try{let S=new URL(e.url??``,`http://localhost`).searchParams.get(`docName`);if(!S){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing docName parameter.`,{handler:`forward-links`});return}if(!isSafeDocName(S)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`forward-links`});return}let w=it();successResponse(t,200,ForwardLinksSuccessSchema,{docName:S,forwardLinks:ee.getForwardLinkEntries(S).map(e=>e.kind===`doc`?{kind:`doc`,docName:e.target,anchor:e.anchor,title:Ve(e.target,w),snippet:e.snippet}:{kind:`external`,url:e.url,title:e.label??e.url,snippet:e.snippet})},{handler:`forward-links`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read forward links.`,{handler:`forward-links`,cause:e})}},{handler:`forward-links`,method:`GET`,skipBodyParse:!0}),Ir=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ee){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`link-graph`});return}try{let S=new URL(e.url??``,`http://localhost`),w=S.searchParams.get(`docName`);if(w&&!isSafeDocName(w)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`link-graph`});return}let E=S.searchParams.get(`degrees`);if(E&&!w){errorResponse(t,400,`urn:ok:error:invalid-request`,`docName is required when degrees is provided.`,{handler:`link-graph`});return}let D,O;if(E&&w){let e=Number.parseInt(E,10);if(!Number.isFinite(e)||e<0){errorResponse(t,400,`urn:ok:error:invalid-request`,`degrees must be a non-negative integer.`,{handler:`link-graph`});return}({nodes:D,links:O}=ee.getLinkGraphNeighborhood(w,e))}else ({nodes:D,links:O}=ee.getLinkGraph());let k=it();successResponse(t,200,LinkGraphSuccessSchema,{nodes:D.map(e=>{if(e.kind===`doc`){let t=Ge(e.docName,k);return{id:e.id,kind:`doc`,docName:e.docName,anchor:e.anchor??null,label:Ve(e.docName,k),cluster:t.cluster??null,category:t.category??null,tags:t.tags??null}}return{id:e.id,kind:`external`,url:e.url,label:e.label??e.url}}),links:O},{handler:`link-graph`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read link graph.`,{handler:`link-graph`,cause:e})}},{handler:`link-graph`,method:`GET`,skipBodyParse:!0}),Lr=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ee){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`orphans`});return}try{let S=new URL(e.url??``,`http://localhost`).searchParams.get(`mode`)??`both`;if(!isOrphanMode(S)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid orphan mode. Allowed values: incoming, outgoing, both.`,{handler:`orphans`});return}successResponse(t,200,OrphansSuccessSchema,{orphans:ee.getOrphans([...D().keys()],S).map(e=>({docName:e,title:Be(e)}))},{handler:`orphans`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read orphan pages.`,{handler:`orphans`,cause:e})}},{handler:`orphans`,method:`GET`,skipBodyParse:!0}),zr=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ee){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`hubs`});return}try{let S=new URL(e.url??``,`http://localhost`).searchParams.get(`limit`),w=S?Number.parseInt(S,10):20,E=Number.isFinite(w)&&w>0?w:20,D=it();successResponse(t,200,HubsSuccessSchema,{hubs:ee.getHubs(E).map(e=>({docName:e.docName,title:Ve(e.docName,D),count:e.count}))},{handler:`hubs`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read hub pages.`,{handler:`hubs`,cause:e})}},{handler:`hubs`,method:`GET`,skipBodyParse:!0}),Br=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ee){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`dead-links`});return}try{let S=new URL(e.url??``,`http://localhost`).searchParams.getAll(`sourceDocName`);if(S.some(e=>e.length===0||!isSafeDocName(e))){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid sourceDocName.`,{handler:`dead-links`});return}let w=S.length?[...new Set(S.map(e=>Xe(e)))]:void 0;successResponse(t,200,DeadLinksSuccessSchema,{deadLinks:ee.getDeadLinks(it(),w).map(e=>({target:e.target,sources:e.sources.map(e=>({source:e.source,title:Be(e.source),snippet:e.snippet}))}))},{handler:`dead-links`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read dead links.`,{handler:`dead-links`,cause:e})}},{handler:`dead-links`,method:`GET`,skipBodyParse:!0}),Vr=withValidation(AgentPatchRequestSchema,async(t,w,E)=>{try{let{find:t,replace:D,offset:O}=E,k=Xe(E.docName!==void 0&&E.docName.length>0?E.docName:`test-doc`),{agentId:j,agentName:F,colorSeed:L,clientName:B,clientVersion:H,label:q}=Rt(E);if(findLooksLikeFrontmatter(t)){agentPatchFmTouchCounter().add(1,{result:`rejected`}),errorResponse(w,400,`urn:ok:error:frontmatter-edit-not-supported`,`Frontmatter edits are not supported via edit_document. Use write_document with position:"replace" to rewrite the document including its YAML block.`,{handler:`agent-patch`});return}if(isSystemDoc(k)||isConfigDoc(k)){errorResponse(w,400,`urn:ok:error:reserved-doc-name`,`'${k}' is a reserved document name.`,{handler:`agent-patch`});return}let J=normalizeSummary(E.summary),Y=await S.getSession(k,j,{displayName:F,colorSeed:L,clientName:B}),ee=new Date().toISOString(),te=!1,ne=!1,ce=!1;try{let S=iconFromClientName(B),w=AGENT_ICON_COLORS[S]??colorFromSeed(L??j);if(oe?.setPresence(j,{displayName:F,icon:S,color:w,currentDoc:k,mode:`writing`,ts:Date.now()}),captureEffect(Y.dc.document.getText(`source`),j,L,B),Y.dc.document.transact(()=>{let{frontmatter:S,body:w}=stripFrontmatter(Y.dc.document.getText(`source`).toString()),E=prependFrontmatter(S,w),L=O==null?E.indexOf(t):E.slice(O,O+t.length)===t?O:-1;if(L===-1){O==null?te=!0:ne=!0,console.warn(JSON.stringify({event:`agent-patch-find-mismatch`,"doc.name":k,findLength:t.length,replaceLength:D.length,hadOffset:O!=null})),incrementAgentPatchFindMismatches();return}if(L<S.length){ce=!0;return}let{body:B}=stripFrontmatter(E.slice(0,L)+D+E.slice(L+t.length));applyAgentMarkdownWrite(Y.dc.document,B,`replace`,e.resolveEmbed?{resolveEmbed:e.resolveEmbed,sourcePath:k}:void 0),Y.dc.document.getMap(`agent-flash`).set(j,{agentId:j,timestamp:Date.now(),type:`insert`,description:`Patched (${F}): ${t.slice(0,50)}`})},Y.origin),!te&&!ne&&!ce){let{stored:e}=Bt(J);recordContributor(k,j,F,L,void 0,zt({clientName:B,clientVersion:H,label:q}),e),incrementAgentWriteCalls(),Ht(J)}}finally{oe?.touchMode(j,`idle`)}if(ne){errorResponse(w,409,`urn:ok:error:stale-target`,`Target text no longer matches at the requested offset.`,{handler:`agent-patch`});return}if(te){errorResponse(w,404,`urn:ok:error:target-not-found`,`Text not found in document.`,{handler:`agent-patch`});return}if(ce){agentPatchFmTouchCounter().add(1,{result:`rejected`}),errorResponse(w,400,`urn:ok:error:frontmatter-edit-not-supported`,`Frontmatter edits are not supported via edit_document. Use write_document with position:"replace" to rewrite the document including its YAML block.`,{handler:`agent-patch`});return}rt(k,`agent-patch`),ae?.setFocus(j,{agentName:F,currentDoc:k,writeKind:`edit`,ts:Date.now()}),se?.();let ue=$e(k),de=nt();de===0&&hintEmittedCounter().add(1,{"shadow.writer":`agent`,"agent.type":resolveAgentType(B)});let{response:fe}=Bt(J);successResponse(w,200,AgentPatchSuccessSchema,{timestamp:ee,subscriberCount:ue,systemSubscriberCount:de,...fe?{summary:fe}:{}},{handler:`agent-patch`})}catch(e){if(e instanceof AgentSessionCapacityError){errorResponse(w,503,`urn:ok:error:too-many-agent-sessions`,`Too many agent sessions.`,{handler:`agent-patch`,cause:e,extraHeaders:{"Retry-After":`10`}});return}log$2.error({err:e},`[agent-patch] handler failed`),errorResponse(w,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`agent-patch`,cause:e})}},{handler:`agent-patch`,method:`POST`}),Hr=withValidation(AgentUndoRequestSchema,async(t,w,E)=>{try{let{agentId:t,agentName:D,colorSeed:O,clientName:k,clientVersion:j,label:F}=Rt(E),L=Xe(E.docName!==void 0&&E.docName.length>0?E.docName:`test-doc`);if(isSystemDoc(L)||isConfigDoc(L)){errorResponse(w,400,`urn:ok:error:reserved-doc-name`,`'${L}' is a reserved document name.`,{handler:`agent-undo`});return}let{connectionId:B}=E,H=E.scope===`session`||E.scope===`file`?`session`:`last`;if(!S.hasSession(L,B)){errorResponse(w,404,`urn:ok:error:no-active-session`,`No active session for this connectionId and docName.`,{handler:`agent-undo`});return}let q=await S.getSession(L,B),J=!1;try{let S=iconFromClientName(k),w=AGENT_ICON_COLORS[S]??colorFromSeed(O??t);oe?.setPresence(t,{displayName:D,icon:S,color:w,currentDoc:L,mode:`writing`,ts:Date.now()}),J=applyAgentUndo(q,H,e.resolveEmbed?{resolveEmbed:e.resolveEmbed,sourcePath:L}:void 0),J&&recordContributor(L,B,D,O,void 0,zt({clientName:k,clientVersion:j,label:F}))}finally{oe?.touchMode(t,`idle`)}J&&rt(L,`agent-undo`),ae?.setFocus(B,{agentName:B,currentDoc:L,writeKind:`undo`,ts:Date.now()}),successResponse(w,200,AgentUndoSuccessSchema,{docName:L,scope:H,undone:J},{handler:`agent-undo`})}catch(e){log$2.error({err:e},`[agent-undo] handler failed`),errorResponse(w,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`agent-undo`,cause:e})}},{handler:`agent-undo`,method:`POST`}),Ur=withValidation(EmptyRequestSchema,async(e,t)=>{try{let w=validateAgentId(new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`).searchParams.get(`agentId`));if(w===null){errorResponse(t,400,`urn:ok:error:invalid-request`,`agentId required (alphanumeric/_/- only).`,{handler:`agent-activity`});return}successResponse(t,200,AgentActivitySuccessSchema,listAgentActivity(S,w),{handler:`agent-activity`})}catch(e){log$2.error({err:e},`[agent-activity] handler failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`agent-activity`,cause:e})}},{handler:`agent-activity`,method:`GET`,skipBodyParse:!0}),Wr=withValidation(EmptyRequestSchema,async(e,t)=>{try{let w=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`),E=validateAgentId(w.searchParams.get(`agentId`)),D=w.searchParams.get(`docName`),O=w.searchParams.get(`stackIndex`);if(E===null){errorResponse(t,400,`urn:ok:error:invalid-request`,`agentId required (alphanumeric/_/- only).`,{handler:`agent-burst-diff`});return}if(!D||D.trim()===``){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing docName parameter.`,{handler:`agent-burst-diff`});return}if(!isSafeDocName(D)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`agent-burst-diff`});return}let k=Xe(D);if(isSystemDoc(k)||isConfigDoc(k)){errorResponse(t,400,`urn:ok:error:reserved-doc-name`,`'${k}' is a reserved document name.`,{handler:`agent-burst-diff`});return}if(!O||Number.isNaN(Number(O))){errorResponse(t,400,`urn:ok:error:invalid-request`,`StackIndex must be a number.`,{handler:`agent-burst-diff`});return}let j=Number(O);if(!Number.isInteger(j)||j<0){errorResponse(t,400,`urn:ok:error:invalid-request`,`stackIndex must be a non-negative integer.`,{handler:`agent-burst-diff`});return}let F=S.getLiveSession(k,E);if(!F){errorResponse(t,404,`urn:ok:error:no-active-session`,`No active session for this agentId and docName.`,{handler:`agent-burst-diff`});return}let L=F.um;if(j>=L.undoStack.length){errorResponse(t,404,`urn:ok:error:not-found`,`stackIndex ${j} out of range (stack has ${L.undoStack.length} items).`,{handler:`agent-burst-diff`});return}let B=L.undoStack[j];successResponse(t,200,AgentBurstDiffSuccessSchema,{diff:synthesizeStackItemDiffText(B,F.dc.document.getText(`source`),k),generatedAt:Date.now()},{handler:`agent-burst-diff`})}catch(e){log$2.error({err:e},`[agent-burst-diff] handler failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`agent-burst-diff`,cause:e})}},{handler:`agent-burst-diff`,method:`GET`,skipBodyParse:!0}),Gr=withValidation(EmptyRequestSchema,async(e,E)=>{try{let D=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`),O=Xe(D.searchParams.get(`docName`)??`test-doc`),k;try{k=safeContentPath(O,w)}catch(e){log$2.error({err:e,docName:O},`[test-reset] safeContentPath rejected docName`),errorResponse(E,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`test-reset`,cause:e});return}await S.closeAll(O),t.closeConnections(O);let j=`onStoreDocument-${O}`;t.debouncer.isDebounced(j)&&await t.debouncer.executeNow(j);let F=t.documents.get(O);if(F&&await(_e??t.unloadDocument.bind(t))(F),writeFileSync(k,``,`utf-8`),ee&&(ee.deleteDocument(O),ee.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist cache after test-reset for ${O}:`,e)}),ne?.(`backlinks`),ne?.(`graph`)),D.searchParams.get(`reset-okignore`)!==`false`)try{let e=resolve(w,`.okignore`),S=t.documents.get(CONFIG_DOC_NAME_OKIGNORE);if(S){let e=S.getText(`source`);e.length>0&&S.transact(()=>{e.delete(0,e.length)},CONFIG_VALIDATION_REVERT_ORIGIN)}existsSync(e)&&writeFileSync(e,``,`utf-8`),me&&await me.rebuildIgnorePatterns()}catch(e){console.warn(`[test-reset] okignore reset partial failure:`,e)}ne?.(`files`),successResponse(E,200,TestResetSuccessSchema,{},{handler:`test-reset`})}catch(e){errorResponse(E,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`test-reset`,cause:e})}},{handler:`test-reset`,method:`POST`,skipBodyParse:!0}),Kr=withValidation(EmptyRequestSchema,async(e,t)=>{try{if(!ee){errorResponse(t,503,`urn:ok:error:backlink-index-not-configured`,`Backlink index is not configured.`,{handler:`test-rescan-backlinks`});return}await ee.rebuildFromDisk(),ee.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist cache after test-rescan-backlinks:`,e)}),ne?.(`backlinks`),ne?.(`graph`),successResponse(t,200,TestRescanBacklinksSuccessSchema,{},{handler:`test-rescan-backlinks`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`test-rescan-backlinks`,cause:e})}},{handler:`test-rescan-backlinks`,method:`POST`,skipBodyParse:!0}),qr=withValidation(EmptyRequestSchema,async(e,t)=>{try{if(!j){errorResponse(t,503,`urn:ok:error:file-rescan-not-configured`,`Watcher rescan capability is not configured.`,{handler:`test-rescan-files`});return}j(),ne?.(`files`),successResponse(t,200,TestRescanFilesSuccessSchema,{},{handler:`test-rescan-files`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`test-rescan-files`,cause:e})}},{handler:`test-rescan-files`,method:`POST`,skipBodyParse:!0}),Jr=withValidation(SaveVersionRequestSchema,async(e,t,S)=>{try{let{rawAgentId:e,agentId:w,agentName:E,clientName:D}=Rt(S),O=L?.current;if(!O){errorResponse(t,503,`urn:ok:error:shadow-not-configured`,`Shadow repo not configured.`,{handler:`save-version`});return}let k=/^[a-zA-Z0-9_-]+$/,j=[],F,B,H;if(typeof S.message==`string`&&S.message.trim()&&(F=S.message.replace(/[\r\n]/g,` `).slice(0,256)),Array.isArray(S.writers))try{j=S.writers.map(e=>{let t=e.id??`unknown`;if(!k.test(t))throw Error(`Invalid writer id: ${t}`);return{id:t,name:(e.name??`unknown`).replace(/[\r\n]/g,``),email:(e.email??`noreply@openknowledge.local`).replace(/[\r\n]/g,``)}})}catch(e){errorResponse(t,400,`urn:ok:error:invalid-request`,e instanceof Error?e.message:`Invalid writer id.`,{handler:`save-version`,cause:e});return}S.principal&&(typeof S.principal.name==`string`&&S.principal.name.trim()&&(B=sanitizeGitIdentity(S.principal.name.trim())),typeof S.principal.email==`string`&&S.principal.email.trim()&&(H=sanitizeGitIdentity(S.principal.email.trim()))),j.length===0&&(j=e===void 0?[SERVICE_WRITER]:[{id:w,name:D?`${E} (${D})`:E,email:`${w}@openknowledge.local`}]);let q=Y??`.`,J=await saveVersion(O,q,j);console.log(`[history] checkpoint ${J.checkpointRef}`);try{await gcRenameLog(O,getOrLoadRenameLogIndex(O.gitDir))}catch(e){console.warn(`[rename-log] post-saveVersion GC failed:`,e)}let ee=swapContributors(),te;if(de){let e=!1;try{await esm_default({baseDir:de,timeout:{block:5e3}}).revparse([`--git-dir`]),e=!0}catch(e){console.warn(`[save-version] parent-git unavailable: ${e instanceof Error?e.message:String(e)}`)}if(e)try{te=await withParentLock(async()=>{let e=esm_default({baseDir:de,timeout:{block:15e3}}),t=(await e.tags([`--list`,`ok/v*`])).all.length+1,S=`ok/v${t}`,w=`openknowledge`,E=`noreply@openknowledge.local`;if(B&&H)w=B,E=H;else try{let e=await resolveGitIdentity(de);e&&(w=e.name,E=e.email)}catch{}let D=[];for(let e of ee.values())if(e.writerId.startsWith(`agent-`)||e.writerId.startsWith(`principal-`)){let t=`${e.writerId}@openknowledge.local`;D.push(`Co-Authored-By: ${e.displayName} <${t}>`)}let O=formatCheckpointSubject(F??`Checkpoint v${t}`),k=D.length>0?`${O}\n\n${D.join(`
|
|
2108
2108
|
`)}`:O,j=q||`.`;return await e.add(j),await e.env({GIT_AUTHOR_NAME:w,GIT_AUTHOR_EMAIL:E,GIT_COMMITTER_NAME:w,GIT_COMMITTER_EMAIL:E}).commit(k,[`--allow-empty`]),await e.addTag(S),console.log(`[checkpoint] parent-git commit + tag ${S}`),S})}catch(e){console.warn(`[checkpoint] parent-git commit failed (non-fatal):`,e)}}successResponse(t,200,SaveVersionSuccessSchema,{checkpointRef:J.checkpointRef,...te?{versionTag:te}:{}},{handler:`save-version`})}catch(e){log$2.error({err:e},`[save-version] handler failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`save-version`,cause:e})}},{handler:`save-version`,method:`POST`}),Yr=withValidation(EmptyRequestSchema,async(e,t)=>{let S=L?.current;if(!S){errorResponse(t,503,`urn:ok:error:shadow-not-configured`,`Shadow repo not configured.`,{handler:`history`});return}let w=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`),E=w.searchParams.get(`docName`)??``,D=w.searchParams.get(`branch`)??q?.()??`main`;if(!E){errorResponse(t,400,`urn:ok:error:invalid-request`,`docName query parameter is required.`,{handler:`history`});return}if(D.includes(`..`)||!/^[a-zA-Z0-9][a-zA-Z0-9._/-]*$/.test(D)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid branch name.`,{handler:`history`});return}let O=Y??`.`,k=safeDocPath(E,O);if(`error`in k){errorResponse(t,400,`urn:ok:error:invalid-request`,k.error,{handler:`history`});return}let j=Number(w.searchParams.get(`limit`)??`50`),F=Number(w.searchParams.get(`offset`)??`0`),B=Math.min(200,Number.isFinite(j)?j:50),H=Number.isFinite(F)?F:0,J=w.searchParams.get(`type`)??void 0,ee=w.searchParams.get(`author`)??void 0,te=w.searchParams.get(`excludeAuthor`)??void 0,ne=Date.now();try{let e=await getDocumentHistory(S,{docName:E,branch:D,limit:B,offset:H,type:J,author:ee,excludeAuthor:te},O),w=Date.now()-ne;console.log(`[timeline] query docName=${E} entries=${e.entries.length} duration=${w}ms`),successResponse(t,200,HistorySuccessSchema,{...e},{handler:`history`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read history.`,{handler:`history`,cause:e})}},{handler:`history`,method:`GET`,skipBodyParse:!0});async function Xr(e,t,S){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`history-version`,extraHeaders:{Allow:`GET`}});return}let w=L?.current;if(!w){errorResponse(t,503,`urn:ok:error:shadow-not-configured`,`Shadow repo not configured.`,{handler:`history-version`});return}let E=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`).searchParams.get(`docName`)??``,D=Y??`.`,O=safeDocPath(E,D);if(`error`in O){errorResponse(t,400,`urn:ok:error:invalid-request`,O.error,{handler:`history-version`});return}let k=shadowGit(w),j=q?.()??`main`;if(!/^[0-9a-f]{40}$/i.test(S)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid commit SHA.`,{handler:`history-version`});return}try{let e=await resolveDocPathAtCommit(w,E,S,j,getOrLoadRenameLogIndex(w.gitDir),e=>{let t=safeDocPath(e,D);return`error`in t?`${e}.md`:t.path},createAncestorShaSetCache());if(e===null){errorResponse(t,404,`urn:ok:error:doc-not-found`,`Document did not exist at this version.`,{handler:`history-version`});return}let O=await k.raw(`show`,`${S}:${e}`),[F=``,L=``]=(await k.raw(`log`,`-1`,`--format=%aI%x00%an`,S)).trim().split(`\0`);successResponse(t,200,HistoryVersionSuccessSchema,{sha:S,content:O,timestamp:F,author:L},{handler:`history-version`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`history-version`,cause:e})}}let Zr=withValidation(EmptyRequestSchema,async(e,S)=>{let w=L?.current;if(!w){errorResponse(S,503,`urn:ok:error:shadow-not-configured`,`Shadow repo not configured.`,{handler:`diff`});return}let E=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`),D=E.searchParams.get(`docName`)??``,O=E.searchParams.get(`from`)??``,k=E.searchParams.get(`to`)??``;if(!k||!/^[0-9a-f]{40}$/i.test(k)){errorResponse(S,400,`urn:ok:error:invalid-request`,`'to' must be a valid 40-char commit SHA.`,{handler:`diff`});return}let j=Y??`.`,F=safeDocPath(D,j);if(`error`in F){errorResponse(S,400,`urn:ok:error:invalid-request`,F.error,{handler:`diff`});return}let B=shadowGit(w),H=q?.()??`main`,J=getOrLoadRenameLogIndex(w.gitDir),ee=createAncestorShaSetCache(),te=e=>{let t=safeDocPath(e,j);return`error`in t?`${e}.md`:t.path};try{let e=await resolveDocPathAtCommit(w,D,k,H,J,te,ee);if(e===null){errorResponse(S,404,`urn:ok:error:doc-not-found`,`Document did not exist at the target version.`,{handler:`diff`});return}let E=await B.raw(`show`,`${k}:${e}`),j;if(O&&/^[0-9a-f]{40}$/i.test(O)){let e=await resolveDocPathAtCommit(w,D,O,H,J,te,ee);if(e===null){errorResponse(S,404,`urn:ok:error:doc-not-found`,`Document did not exist at the source version.`,{handler:`diff`});return}j=await B.raw(`show`,`${O}:${e}`)}else{let e=t.documents.get(D);if(!e){errorResponse(S,409,`urn:ok:error:doc-not-open`,`Document is not currently open — open it in the editor first.`,{handler:`diff`});return}j=e.getText(`source`).toString()}let F=stripFrontmatter(j).body,L=stripFrontmatter(E).body,q=diffLines(F,L),Y=[],ne=0,ae=0;for(let e of q){let t=e.value.replace(/\n$/,``).split(`
|
|
2109
2109
|
`),S=e.added?`added`:e.removed?`removed`:`unchanged`;for(let e of t)Y.push({type:S,text:e});e.added&&(ne+=t.length),e.removed&&(ae+=t.length)}successResponse(S,200,DiffSuccessSchema,{lines:Y,additions:ne,deletions:ae},{handler:`diff`})}catch(e){errorResponse(S,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`diff`,cause:e})}},{handler:`diff`,method:`GET`,skipBodyParse:!0}),Qr=withValidation(RollbackRequestSchema,async(S,w,E)=>{let D=extractActorIdentity(E,fe);if(D.kind===`invalid-summary`){errorResponse(w,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`rollback`});return}let O=L?.current;if(!O){errorResponse(w,503,`urn:ok:error:rollback-not-configured`,`Shadow repo not configured.`,{handler:`rollback`});return}let{docName:k,commitSha:j,versionTag:F}=E,B=Y??`.`,H=safeDocPath(k,B);if(`error`in H){errorResponse(w,400,`urn:ok:error:invalid-request`,H.error,{handler:`rollback`});return}let J=shadowGit(O),ee=Date.now();try{let S=getOrLoadRenameLogIndex(O.gitDir),E=createAncestorShaSetCache(),L=await resolveDocPathAtCommit(O,k,j,q?.()??`main`,S,e=>{let t=safeDocPath(e,B);return`error`in t?`${e}.md`:t.path},E);if(L===null){errorResponse(w,404,`urn:ok:error:doc-not-found`,`Commit ${j.slice(0,7)} does not contain document ${k} at any known historical path.`,{handler:`rollback`});return}let H=await J.raw(`show`,`${j}:${L}`),te=new Date().toISOString();await safetyCheckpoint(O,B,{action:`rollback`,context:{docName:k,targetSha:j}});let ne=t.documents.get(k);if(!ne){errorResponse(w,409,`urn:ok:error:doc-not-open`,`Document is not currently open — open it in the editor first.`,{handler:`rollback`});return}let oe=e.resolveEmbed?{resolveEmbed:e.resolveEmbed,sourcePath:k}:void 0;ne.transact(()=>{replaceRawBody(ne,H,oe)},ROLLBACK_ORIGIN);let se;switch(D.kind){case`agent`:{let e=j.slice(0,8),t=D.summary.kind===`value`,S=t?D.summary:normalizeSummary(`Restored to ${e}`),w=Bt(S);se=t||!w.response?w.response:Vt(w.response),recordContributor(k,D.writerId,D.displayName,D.colorSeed,formatRollbackSubject(k,j),D.actor,w.stored),incrementAgentWriteCalls(),Ht(S,!t);break}case`principal`:{let e=Bt(D.summary);se=e.response,recordContributor(k,D.writerId,D.displayName,D.colorSeed,formatRollbackSubject(k,j),D.actor,e.stored),Ht(D.summary,!1);break}case`anonymous`:log$2.debug({docName:k,commitSha:j.slice(0,8)},`[rollback] anonymous actor — no contributor recorded (no agentId in body and getPrincipal() returned null)`);break;default:throw Error(`Unhandled actor kind in handleRollback: ${String(D.kind)}`)}renameAttributionCounter().add(1,{kind:`rollback`,attribution_kind:D.kind}),rt(k,`rollback`);let ce=Date.now()-ee;if(console.log(`[rollback] docName=${k} from=${j.slice(0,8)} duration=${ce}ms`),de){let e=`Restored to ${F??j.slice(0,8)}: ${k}`,t=Y??`.`;withParentLock(async()=>{let S=esm_default({baseDir:de,timeout:{block:15e3}}),w=t||`.`;await S.add(w),await S.commit(e,{"--allow-empty":null}),console.log(`[rollback] parent-git commit: ${e}`)}).catch(e=>{console.warn(`[rollback] parent-git commit failed (non-fatal):`,e)})}D.kind===`agent`&&ae?.setFocus(D.writerId,{agentName:D.displayName,currentDoc:k,writeKind:`rollback-apply`,ts:Date.now()}),successResponse(w,200,RollbackSuccessSchema,{restoredFrom:j,timestamp:te,...se?{summary:se}:{}},{handler:`rollback`})}catch(e){errorResponse(w,500,`urn:ok:error:internal-server-error`,`Failed to roll back.`,{handler:`rollback`,cause:e})}},{handler:`rollback`,method:`POST`}),ji=withValidation(EmptyRequestSchema,async(e,t)=>{try{successResponse(t,200,MetricsReconciliationSuccessSchema,getMetrics(),{handler:`metrics-reconciliation`})}catch(e){log$2.error({err:e},`[metrics-reconciliation] handler failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`metrics-reconciliation`,cause:e})}},{handler:`metrics-reconciliation`,method:`GET`,skipBodyParse:!0}),Hi=withValidation(EmptyRequestSchema,async(e,t)=>{try{successResponse(t,200,MetricsParseHealthSuccessSchema,getParseHealth(),{handler:`metrics-parse-health`})}catch(e){log$2.error({err:e},`[metrics-parse-health] handler failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`metrics-parse-health`,cause:e})}},{handler:`metrics-parse-health`,method:`GET`,skipBodyParse:!0}),Ui=withValidation(EmptyRequestSchema,async(e,t)=>{try{let e=getActiveBranch(),S=J?.();successResponse(t,200,ServerInfoSuccessSchema,{serverInstanceId:E,currentBranch:e,...S===void 0?{}:{currentDiskAckSVs:S}},{handler:`server-info`,extraHeaders:{"Cache-Control":`no-store`}})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`server-info`,cause:e})}},{handler:`server-info`,method:`GET`,skipBodyParse:!0});async function Gi(e,t){if(!isLoopbackAddress(e.socket.remoteAddress)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback required.`,{handler:`principal`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`principal`});return}if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`principal`,extraHeaders:{Allow:`GET`}});return}let S=fe?.()??null;if(!S){errorResponse(t,404,`urn:ok:error:principal-not-available`,`Principal not available.`,{handler:`principal`});return}successResponse(t,200,PrincipalSuccessSchema,S,{handler:`principal`})}async function Ki(e,t){if(!isLoopbackAddress(e.socket.remoteAddress)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback required.`,{handler:`metrics-agent-presence`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`metrics-agent-presence`});return}if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`metrics-agent-presence`,extraHeaders:{Allow:`GET`}});return}try{let e=oe?.getPresenceMap()??{},S=Date.now(),w={};for(let[t,E]of Object.entries(e))S-E.ts<2e4&&(w[t]=E);successResponse(t,200,MetricsAgentPresenceSuccessSchema,{presence:w},{handler:`metrics-agent-presence`})}catch(e){log$2.error({err:e},`[metrics-agent-presence] handler failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`metrics-agent-presence`,cause:e})}}async function Yi(e,t){if(!isLoopbackAddress(e.socket.remoteAddress)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback required.`,{handler:`workspace`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`workspace`});return}if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`workspace`,extraHeaders:{Allow:`GET`}});return}let S=resolve(w),E=S,D=!0;try{E=realpathSync(S)}catch(e){let w=e?.code;if(w===`ENOENT`)console.warn(`[workspace] contentDir does not exist; returning unresolved path`,{path:S}),D=!1;else{console.warn(`[workspace] realpath failed for contentDir`,{path:S,err:e}),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Workspace realpath failed.`,{handler:`workspace`,detail:w??void 0,cause:e});return}}successResponse(t,200,WorkspaceSuccessSchema,{contentDir:E,pathSeparator:sep,symlinkResolved:D},{handler:`workspace`})}let Xi=withValidation(EmptyRequestSchema,async(e,t)=>{try{let S=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`).searchParams.get(`path`);if(!S||S.includes(`\0`)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing asset path.`,{handler:`asset`});return}let E=assetContentTypeForPath(S),D=extname(S).slice(1).toLowerCase();if(!E||!ASSET_EXTENSIONS.has(D)){errorResponse(t,415,`urn:ok:error:unsupported-asset-type`,`Unsupported asset type.`,{handler:`asset`});return}let O=realpathSync(w),k=resolve(O,S),j;try{j=realpathSync(k)}catch{errorResponse(t,404,`urn:ok:error:asset-not-found`,`Asset not found.`,{handler:`asset`});return}if(!isWithinContentDir(j,O)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid asset path.`,{handler:`asset`});return}let F;try{F=statSync(j)}catch{errorResponse(t,404,`urn:ok:error:asset-not-found`,`Asset not found.`,{handler:`asset`});return}if(!F.isFile()){errorResponse(t,404,`urn:ok:error:asset-not-found`,`Asset not found.`,{handler:`asset`});return}let L=toContentRelativePath(O,j);if(L!==S.split(`\\`).join(`/`)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid asset path.`,{handler:`asset`});return}if(me?.isPathIgnored(L)){errorResponse(t,404,`urn:ok:error:asset-not-found`,`Asset not found.`,{handler:`asset`});return}let B={"Content-Type":E,"Content-Length":String(F.size),"X-Content-Type-Options":`nosniff`,"Content-Disposition":INLINE_RENDERABLE_EXTENSIONS.has(D)?`inline`:`attachment`,"Cache-Control":`no-store`};D===`svg`&&(B[`Content-Security-Policy`]=`sandbox; default-src 'none'; style-src 'unsafe-inline'`),t.writeHead(200,B);try{await pipeline(createReadStream(j),t)}catch(e){log$2.error({event:`api.asset.pipeline-failed`,handler:`asset`,assetPath:S,err:e},`[asset] pipeline failed mid-stream`),t.destroyed||t.destroy(e instanceof Error?e:void 0)}}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`asset`,cause:e})}},{handler:`asset`,method:`GET`,skipBodyParse:!0}),Zi=1440*60*1e3,ka=withValidation(EmptyRequestSchema,async(e,t)=>{try{if(!L?.current){successResponse(t,200,RescueListSuccessSchema,[],{handler:`rescue-list`});return}let e=Date.now(),S=[],w=resolve(L.current.gitDir,`rescue`);if(existsSync(w))try{let t=readdirSync(w).filter(e=>isSupportedDocFile(e));for(let E of t){let t=resolve(w,E),D=statSync(t);if(e-D.mtimeMs>Zi){try{unlinkSync(t)}catch(e){console.debug(`[rescue] cleanup failed (non-critical):`,e)}continue}S.push({docName:stripDocExtension(E),timestamp:D.mtime.toISOString(),size:D.size,source:`flat`})}}catch(e){log$2.error({err:e},`[rescue] Failed to list flat-file rescue buffers`)}try{let e=q?.()??`main`,t=await listRescueCheckpoints(L.current,e);for(let e of t)S.push({...e,source:`timeline`})}catch(e){log$2.error({err:e},`[rescue] Failed to list timeline-ref rescue checkpoints`)}successResponse(t,200,RescueListSuccessSchema,S,{handler:`rescue-list`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`rescue-list`,cause:e})}},{handler:`rescue-list`,method:`GET`,skipBodyParse:!0});async function _s(e,t,S){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`rescue-get`,extraHeaders:{Allow:`GET`}});return}if(!L?.current){errorResponse(t,503,`urn:ok:error:shadow-not-configured`,`Shadow repo not configured.`,{handler:`rescue-get`});return}let w=resolve(L.current.gitDir,`rescue`),E=resolve(w,`${S}${getDocExtension(S)}`);if(!E.startsWith(`${w}/`)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid document name.`,{handler:`rescue-get`});return}if(existsSync(E)){let e=statSync(E);if(Date.now()-e.mtimeMs>Zi)try{unlinkSync(E)}catch{}else{let e=readFileSync(E,`utf-8`);t.writeHead(200,{"Content-Type":`text/markdown`,"X-Content-Type-Options":`nosniff`}),t.end(e);return}}try{let e=q?.()??`main`,w=(await listRescueCheckpoints(L.current,e)).filter(e=>e.docName===S).sort((e,t)=>t.timestamp.localeCompare(e.timestamp))[0];if(w){let e=shadowGit(L.current),S=((await e.raw(`ls-tree`,`-r`,w.sha)).trim().split(`
|
|
2110
|
-
`)[0]??``).split(/\s+/)[2];if(S){let w=await e.raw(`cat-file`,`-p`,S);t.writeHead(200,{"Content-Type":`text/markdown`,"X-Content-Type-Options":`nosniff`}),t.end(w);return}}}catch(e){console.warn(`[rescue] timeline-ref fallback failed:`,e)}errorResponse(t,404,`urn:ok:error:not-found`,`Not found.`,{handler:`rescue-get`})}let xs=withValidation(CreatePageRequestSchema,async(e,t,S)=>{try{let e=extractActorIdentity(S,fe);if(e.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`create-page`});return}let E=S.path;if(!isSupportedDocFile(E)){errorResponse(t,400,`urn:ok:error:invalid-request`,`path must end with .md or .mdx.`,{handler:`create-page`});return}if(E.includes(`..`)||E.startsWith(`/`)||E.includes(`\0`)||E.includes(`\\`)){errorResponse(t,400,`urn:ok:error:path-escape`,`Invalid path.`,{handler:`create-page`,detail:`path must not contain .. or start with /`});return}let O=resolve(w),k=resolve(O,E);if(!k.startsWith(`${O}/`)&&k!==O){errorResponse(t,400,`urn:ok:error:path-escape`,`path must not escape content directory.`,{handler:`create-page`});return}let j=stripDocExtension(E);if(isSystemDoc(j)||isConfigDoc(j)){errorResponse(t,400,`urn:ok:error:reserved-doc-name`,`'${j}' is a reserved document name.`,{handler:`create-page`});return}let F=typeof S.template==`string`?S.template.trim():``,L=``,B;if(F.length>0){if(!/^[A-Za-z0-9_-]+$/.test(F)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Template name must match [A-Za-z0-9_-]+.`,{handler:`create-page`});return}let S=E.includes(`/`)?E.slice(0,E.lastIndexOf(`/`)):``,w=resolveTemplatesAvailable(O,S),D=w.find(e=>e.name===F);if(!D){let e=w.length===0?`(none)`:w.map(e=>`"${e.name}" (${e.scope})`).join(`, `);errorResponse(t,400,`urn:ok:error:invalid-request`,`Template "${F}" does not resolve for folder "${S||`(root)`}". Available: ${e}`,{handler:`create-page`});return}let k=resolve(O,D.path),j;try{j=readFileSync(k,`utf-8`)}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read template at ${D.path}.`,{handler:`create-page`,cause:e});return}let{body:H}=stripFrontmatter(j),q=e.kind===`agent`||e.kind===`principal`?e.displayName??``:``;L=applySubstitution(H,{date:todayIsoUtc(),user:q}),B=D.scope}mkdirSync(dirname(k),{recursive:!0});try{writeFileSync(k,L,{encoding:`utf-8`,flag:`wx`})}catch(e){if(e.code===`EEXIST`){errorResponse(t,409,`urn:ok:error:doc-already-exists`,`File already exists.`,{handler:`create-page`,cause:e});return}throw e}let H=stripDocExtension(E);switch(ye?.delete(H),me&&me.incrementMdDir(dirname(H)),registerWrite(k,contentHash(L)),e.kind){case`agent`:case`principal`:recordContributor(H,e.writerId,e.displayName,e.colorSeed,void 0,e.actor);break;case`anonymous`:break;default:throw Error(`Unhandled actor kind in handleCreatePage: ${String(e.kind)}`)}let q=typeof D==`function`?D():null;q instanceof Map&&updateFileIndex({kind:`create`,path:k,docName:H,content:L},q),ee&&(ee.updateDocumentFromMarkdown(H,L),ee.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist create-page cache for ${H}:`,e)}),ne?.(`backlinks`),ne?.(`graph`)),ne?.(`files`),B!==void 0&&console.warn(JSON.stringify({event:`template-instantiate`,templateName:F,templateScope:B,docName:H})),successResponse(t,200,CreatePageSuccessSchema,{docName:H},{handler:`create-page`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to create page.`,{handler:`create-page`,cause:e})}},{handler:`create-page`,method:`POST`}),Cs=withValidation(CreateFolderRequestSchema,async(e,t,S)=>{try{if(extractActorIdentity(S,fe).kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`create-folder`});return}let e=S.path;if(!isValidRelativeContentPath(e)){errorResponse(t,400,`urn:ok:error:invalid-request`,`path must be a relative content path.`,{handler:`create-folder`});return}if(e===`.ok`||e.startsWith(`.ok/`)){errorResponse(t,400,`urn:ok:error:reserved-doc-name`,`'.ok' is a reserved directory.`,{handler:`create-folder`});return}if(me?.isDirExcluded(e)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Destination folder is excluded by the workspace content config.`,{handler:`create-folder`});return}let E=resolveContentEntryPath(w,`folder`,e);if(existsSync(E)){errorResponse(t,409,`urn:ok:error:doc-already-exists`,`Folder already exists.`,{handler:`create-folder`});return}tracedMkdirSync(E,{recursive:!0}),je(e),ne?.(`files`),successResponse(t,200,CreateFolderSuccessSchema,{path:e},{handler:`create-folder`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to create folder.`,{handler:`create-folder`,cause:e})}},{handler:`create-folder`,method:`POST`}),Ts=withValidation(EmptyRequestSchema,async(e,t)=>{try{let S=new URL(e.url??``,`http://localhost`).searchParams.get(`docName`);if(!S||S.length===0){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing docName query parameter.`,{handler:`page-headings`});return}if(!isSafeDocName(S)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`page-headings`});return}let w=ze(S);if(!w){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`page-headings`});return}if(!existsSync(w)){errorResponse(t,404,`urn:ok:error:doc-not-found`,`Page not found.`,{handler:`page-headings`});return}successResponse(t,200,PageHeadingsSuccessSchema,{docName:S,headings:extractHeadings(readFileSync(w,`utf-8`))},{handler:`page-headings`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read headings.`,{handler:`page-headings`,cause:e})}},{handler:`page-headings`,method:`GET`,skipBodyParse:!0}),Ds=withValidation(RenamePathRequestSchema,async(e,t,S)=>{try{let e=extractActorIdentity(S,fe);if(e.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`rename-path`});return}let{kind:E,fromPath:D,toPath:O}=S;if(!isValidRelativeContentPath(D)||!isValidRelativeContentPath(O)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Paths must be relative content paths.`,{handler:`rename-path`});return}if(E===`file`&&(isSystemDoc(D)||isSystemDoc(O)||isConfigDoc(D)||isConfigDoc(O))){errorResponse(t,400,`urn:ok:error:reserved-doc-name`,`Reserved document names cannot be renamed.`,{handler:`rename-path`});return}if(D===`.ok`||D.startsWith(`.ok/`)||O===`.ok`||O.startsWith(`.ok/`)){errorResponse(t,400,`urn:ok:error:reserved-doc-name`,`.ok is a reserved directory.`,{handler:`rename-path`});return}if(D===O){successResponse(t,200,RenamePathSuccessSchema,{renamed:[],rewrittenDocs:[]},{handler:`rename-path`});return}if(D.toLowerCase()===O.toLowerCase()){errorResponse(t,400,`urn:ok:error:invalid-request`,`Case-only renames are not supported.`,{handler:`rename-path`});return}if(E===`file`&&probeAndRegisterSourceFileExtension(w,D),me&&(E===`file`?me.isExcluded(isSupportedDocFile(O)?O:`${O}${getDocExtension(D)}`):me.isDirExcluded(O))){errorResponse(t,400,`urn:ok:error:invalid-request`,`Destination ${E===`file`?`document`:`folder`} is excluded by the project content config.`,{handler:`rename-path`});return}let k=e.kind===`agent`||e.kind===`principal`?{writerId:e.writerId,displayName:e.displayName,colorSeed:e.colorSeed,actorMetadata:e.actor}:void 0,j;try{j=await Lt(D,O,E,{...k?{actor:k}:{}})}catch(e){if(e instanceof ManagedRenameCollisionError){errorResponse(t,409,`urn:ok:error:doc-already-exists`,vt(e.message),{handler:`rename-path`,extensions:{colliding:e.colliding},cause:e});return}throw e}if(j.renamed.length===0){successResponse(t,200,RenamePathSuccessSchema,{renamed:[],rewrittenDocs:[]},{handler:`rename-path`});return}let F;switch(e.kind){case`agent`:{let t=e.summary.kind===`value`,S=t?e.summary:normalizeSummary(`Renamed ${D} → ${O}`),w=Bt(S);F=t||!w.response?w.response:Vt(w.response);for(let t=0;t<j.renamed.length;t++){let{fromDocName:S,toDocName:E}=j.renamed[t];recordContributor(E,e.writerId,e.displayName,e.colorSeed,formatRenameSubject(S,E),e.actor,t===0?w.stored:void 0)}incrementAgentWriteCalls(),Ht(S,!t);for(let{toDocName:e}of j.renamed)rt(e,`rename-path`);break}case`principal`:{let t=Bt(e.summary);F=t.response;for(let S=0;S<j.renamed.length;S++){let{fromDocName:w,toDocName:E}=j.renamed[S];recordContributor(E,e.writerId,e.displayName,e.colorSeed,formatRenameSubject(w,E),e.actor,S===0?t.stored:void 0)}Ht(e.summary,!1);for(let{toDocName:e}of j.renamed)rt(e,`rename-path`);break}case`anonymous`:log$2.debug({kind:E,fromPath:D,toPath:O,affectedDocs:j.renamed.length},`[rename-path] anonymous actor — no contributor recorded (no agentId in body and getPrincipal() returned null)`);break;default:throw Error(`Unhandled actor kind in handleRenamePath: ${String(e.kind)}`)}if(renameAttributionCounter().add(1,{kind:`rename-${E}`,attribution_kind:e.kind}),H)try{await H()}catch(e){console.warn(`[rename-path] flushContributors failed (commitSha backfill may be deferred):`,e)}successResponse(t,200,RenamePathSuccessSchema,{renamed:j.renamed,rewrittenDocs:j.rewrittenDocs,...F?{summary:F}:{}},{handler:`rename-path`})}catch(e){let{status:S,type:w,error:E}=Tt(e);errorResponse(t,S,w,E,{handler:`rename-path`,cause:e})}},{handler:`rename-path`,method:`POST`}),Os=withValidation(DeletePathRequestSchema,async(e,t,S)=>{try{Rt(S);let{kind:e,path:E}=S;if(!isValidRelativeContentPath(E)){errorResponse(t,400,`urn:ok:error:invalid-request`,`path must be a relative content path.`,{handler:`delete-path`});return}let O=resolveContentEntryPath(w,e,E);if(!existsSync(O)){errorResponse(t,404,`urn:ok:error:doc-not-found`,`${e} does not exist.`,{handler:`delete-path`});return}let k=statSync(O);if(e===`file`&&!k.isFile()||e===`folder`&&!k.isDirectory()){errorResponse(t,400,`urn:ok:error:invalid-request`,`Target path is not a ${e}.`,{handler:`delete-path`});return}let j=e===`file`?[E]:listAffectedDocNames(D(),e,E);if(await Et(j),ye)for(let e of j)isSystemDoc(e)||isConfigDoc(e)||(ye.setDeleted(e),console.info(JSON.stringify({event:`recently-removed-docs-populate`,docName:e,kind:`deleted`,source:`handleDeletePath`})));e===`file`?unlinkSync(O):(rmSync(O,{recursive:!0,force:!1}),Me(E));let F=D();if(F instanceof Map)for(let e of j)updateFileIndex({kind:`delete`,path:resolve(w,`${e}${getDocExtension(e)}`),docName:e},F);successResponse(t,200,DeletePathSuccessSchema,{deletedDocNames:j},{handler:`delete-path`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to delete path.`,{handler:`delete-path`,cause:e})}},{handler:`delete-path`,method:`POST`}),ks=withValidation(TrashCleanupRequestSchema,async(e,t,S)=>withSpan(`ok.fs.trash_cleanup`,{attributes:{"ok.cleanup.kind":S.kind,"ok.cleanup.path":normalizeFsPath(S.path),"ok.cleanup.path.role":classifyFsPath(S.path)}},async()=>{try{if(extractActorIdentity(S,fe).kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`trash-cleanup`});return}let{kind:e,path:E}=S;if(!isValidRelativeContentPath(E)){errorResponse(t,400,`urn:ok:error:invalid-request`,`path must be a relative content path.`,{handler:`trash-cleanup`});return}let O=e===`folder`&&(E===`__system__`||E===`__config__`||E===`__user__`||E===`__local__`||E.startsWith(`__system__/`)||E.startsWith(`__config__/`)||E.startsWith(`__user__/`)||E.startsWith(`__local__/`));if(e===`file`&&(isSystemDoc(E)||isConfigDoc(E))||O){errorResponse(t,400,`urn:ok:error:reserved-doc-name`,`'${E}' is a reserved document name.`,{handler:`trash-cleanup`});return}let k=D(),j=e===`file`?k.has(E)?[E]:[]:listAffectedDocNames(k,e,E);if(j.length===0){successResponse(t,200,TrashCleanupSuccessSchema,{deletedDocNames:[]},{handler:`trash-cleanup`});return}if(await Et(j),ye)for(let e of j)isSystemDoc(e)||isConfigDoc(e)||(ye.setDeleted(e),console.info(JSON.stringify({event:`recently-removed-docs-populate`,docName:e,kind:`deleted`,source:`handleTrashCleanup`})));let F=D();if(F instanceof Map)for(let e of j)updateFileIndex({kind:`delete`,path:resolve(w,`${e}${getDocExtension(e)}`),docName:e},F);e===`folder`&&Me(E),ne?.(`files`),successResponse(t,200,TrashCleanupSuccessSchema,{deletedDocNames:j},{handler:`trash-cleanup`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to clean up after trash.`,{handler:`trash-cleanup`,cause:e})}}),{handler:`trash-cleanup`,method:`POST`}),As=withValidation(EmptyRequestSchema,async(e,t)=>{try{let e=D(),S=[];for(let[t,E]of e){let e=t,D=getDocExtension(t);try{e=extractPageTitle(readFileSync(resolve(w,`${t}${D}`),`utf-8`),t)}catch(e){console.warn(`[pages] Failed to read title for ${t}:`,e)}S.push({docName:t,title:e,docExt:D,size:E.size,modified:E.modified})}S.sort((e,t)=>e.docName.localeCompare(t.docName)),successResponse(t,200,PagesSuccessSchema,{pages:S},{handler:`pages`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to list pages.`,{handler:`pages`,cause:e})}},{handler:`pages`,method:`GET`,skipBodyParse:!0}),Ns=withValidation(EmptyRequestSchema,async(e,S)=>{try{let w=new URL(e.url??``,`http://localhost`).searchParams.get(`docName`);if(!w){errorResponse(S,400,`urn:ok:error:invalid-request`,`Missing docName parameter.`,{handler:`suggest-links`});return}if(!isSafeDocName(w)){errorResponse(S,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`suggest-links`});return}if(isSystemDoc(w)||isConfigDoc(w)){errorResponse(S,400,`urn:ok:error:reserved-doc-name`,`'${w}' is a reserved document name.`,{handler:`suggest-links`});return}successResponse(S,200,SuggestLinksSuccessSchema,await suggestLinks({hocuspocus:t,fileIndex:D(),docName:w}),{handler:`suggest-links`})}catch(e){if(e instanceof SuggestLinksTargetNotFoundError){errorResponse(S,404,`urn:ok:error:doc-not-found`,`Page not found.`,{handler:`suggest-links`,cause:e});return}errorResponse(S,500,`urn:ok:error:internal-server-error`,`Failed to suggest links.`,{handler:`suggest-links`,cause:e})}},{handler:`suggest-links`,method:`GET`,skipBodyParse:!0});async function Ps(e,t){if(e.method!==`POST`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`upload-asset`,extraHeaders:{Allow:`POST`}});return}let S;try{S=await readUploadBody(e,de??w)}catch(e){if(e instanceof UploadWriteError){errorResponse(t,uploadStatusFor(e.reason),e.reason,uploadTitleFor(e.reason),{handler:`upload-asset`,cause:e});return}errorResponse(t,400,`urn:ok:error:malformed-upload`,`Failed to parse upload.`,{handler:`upload-asset`,cause:e});return}let{filename:E,tempPath:D,sha:O,byteLength:k,parentDocName:j}=S,F=()=>{if(existsSync(D))try{unlinkSync(D)}catch{}},L=validateBody(UploadRequestSchema,{parentDocName:j},t,{handler:`upload-asset`});if(!L.ok){F();return}let{parentDocName:B}=L.value,{agentId:H,agentName:q}=Rt(Object.fromEntries(new URL(e.url??``,`http://localhost`).searchParams.entries()));if(k===0){F(),errorResponse(t,400,`urn:ok:error:no-file-received`,`No file received.`,{handler:`upload-asset`});return}if(B.includes(`\0`)||B.includes(`..`)||B.startsWith(`/`)){F(),errorResponse(t,400,`urn:ok:error:path-escape`,`Path escape detected.`,{handler:`upload-asset`});return}let J=resolve(w),Y=resolveUploadDestDir(B,`./`,J);if(!isWithinContentDir(Y,J)){F(),errorResponse(t,400,`urn:ok:error:path-escape`,`Path escape detected.`,{handler:`upload-asset`});return}try{assertNoSymlinkEscape(Y,J)}catch(e){if(F(),(e instanceof Error?e.message:String(e)).startsWith(`symlink-escape:`)){errorResponse(t,400,`urn:ok:error:path-escape`,`Path escape detected.`,{handler:`upload-asset`});return}log$2.error({err:e,destDir:Y},`[upload] failed to validate destination directory`),errorResponse(t,500,`urn:ok:error:storage-error`,`Storage error.`,{handler:`upload-asset`,cause:e});return}try{mkdirSync(Y,{recursive:!0})}catch(e){if(e.code!==`EEXIST`){F();let S=classifyUploadErrno(e);errorResponse(t,uploadStatusFor(S),S,uploadTitleFor(S),{handler:`upload-asset`,cause:e,detail:`failed to create attachment directory`});return}}try{let e=realpathSync(Y),S;try{S=realpathSync(J)}catch{S=J}if(!isWithinContentDir(e,S)){F(),errorResponse(t,400,`urn:ok:error:path-escape`,`Path escape detected.`,{handler:`upload-asset`});return}}catch(e){if(e.code!==`ENOENT`){F(),errorResponse(t,400,`urn:ok:error:path-escape`,`Path escape detected.`,{handler:`upload-asset`,cause:e});return}}let ee=await fileTypeFromFile(D),te=ee?.mime,ne=ee?.ext;if(!te){let e=readTempFileHead(D,256).toString(`utf-8`).replace(/^/,``).trimStart();(e.startsWith(`<svg`)||e.startsWith(`<?xml`)&&e.includes(`<svg`))&&(te=`image/svg+xml`,ne=`svg`)}{let S=await findDuplicateAsset(Y,O,k);if(S){F();let E=relative(w,resolve(Y,S));log$2.info({event:`upload`,endpoint:e.url??`/api/upload`,agentId:H,agentName:q,dedup:!0,mime:te??null,size:k,destPath:E,httpStatus:200},`[upload] dedup hit`),successResponse(t,200,UploadAssetSuccessSchema,{src:S,path:E,deduped:!0},{handler:`upload-asset`});return}}let ae;if(!E||E===`upload`||GENERIC_PASTE_NAMES.test(E)){let e=new Date().toISOString().replace(/[-:T]/g,``).slice(0,14).replace(/(\d{8})(\d{6})/,`$1-$2`),t=E?extname(E).slice(1):``,S=ne??t??``;ae=S===``?`pasted-${e}`:`pasted-${e}.${S}`}else ae=sanitizeFilename(E);try{let S=linkTempToFinalWithCollisionRetry(D,Y,ae),E=relative(w,resolve(Y,S));log$2.info({event:`upload`,endpoint:e.url??`/api/upload`,agentId:H,agentName:q,dedup:!1,mime:te??null,size:k,destPath:E,httpStatus:200},`[upload] write ok`),successResponse(t,200,UploadAssetSuccessSchema,{src:S,path:E,deduped:!1},{handler:`upload-asset`})}catch(S){let w=S instanceof UploadWriteError?S.reason:`urn:ok:error:storage-error`;log$2.error({event:`upload`,endpoint:e.url??`/api/upload`,agentId:H,agentName:q,filename:ae,size:k,reason:w,httpStatus:uploadStatusFor(w),err:S},`[upload] write failed`),errorResponse(t,uploadStatusFor(w),w,uploadTitleFor(w),{handler:`upload-asset`,cause:S})}}let Is=`/api/local-op/clone`,Rs=`/api/local-op/open`,$s=600*1e3,ec=45e3,tc=`local-op-clone`,nc=withValidation(LocalOpCloneRequestSchema,rc,{handler:tc,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:tc})});async function rc(e,t,S){let{url:w,dir:E}=S;if(!isAllowedGitUrl(w)){errorResponse(t,400,`urn:ok:error:url-not-allowed`,`URL protocol is not allowed for clone.`,{handler:tc,cause:Error(`url=${w}`)});return}if(!isSafeLocalPath(E)){errorResponse(t,400,`urn:ok:error:dir-outside-home`,`Clone destination must be within the user home directory.`,{handler:tc,cause:Error(`dir=${E}`)});return}if(!Ce.tryAcquire(Is)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A clone operation is already in progress.`,{handler:tc,extraHeaders:{"Retry-After":`30`}});return}t.writeHead(200,{"Content-Type":`application/x-ndjson`,"Transfer-Encoding":`chunked`,"X-Content-Type-Options":`nosniff`,"Cache-Control":`no-cache`});let D=createStreamingErrorWriter(t,tc),O=null,k=runCloneSubprocess({cliArgs:ue,url:w,dir:E,timeoutMs:$s,onEvent:e=>{if(e.type===`complete`){O=e.dir;return}if(e.type===`error`){e.message&&log$2.warn({stderr:e.message,url:w,dir:E},`[local-op/clone] clone failed`),D(500,`urn:ok:error:clone-failed`,`Clone subprocess reported an error.`,{cause:e.message?Error(e.message):void 0});return}if(!t.writableEnded&&!t.destroyed)try{t.write(`${JSON.stringify(e)}\n`)}catch{}}});(async()=>{try{if(await k.done,O&&!t.writableEnded&&!t.destroyed){let e=await ic(O);!t.writableEnded&&!t.destroyed&&(`port`in e?t.write(`${JSON.stringify({type:`complete`,port:e.port,dir:O})}\n`):D(500,`urn:ok:error:server-start-failed`,`Cloned successfully but failed to start the project server.`,{cause:Error(e.error)}))}}catch(e){!t.writableEnded&&!t.destroyed?D(500,`urn:ok:error:internal-server-error`,`Unexpected error during clone post-processing.`,{cause:e}):log$2.error({err:e,handler:tc},`clone IIFE rejected after stream ended`)}finally{t.writableEnded||t.end(),Ce.release(Is)}})(),t.on(`close`,()=>{k.cancel()})}async function ic(e){let t=resolve(expandTilde(e)),S=getLocalDir(t),w=readUiLock(S);if(w&&w.port>0)return{port:w.port};let E=readServerLock(S),[D,...O]=ue,k=E&&E.port>0?`ui`:`start`,j=spawn(D,[...O,k],{cwd:t,detached:!0,stdio:[`ignore`,`ignore`,`pipe`],env:{...process.env,OK_LOCK_KIND:`interactive`}}),F=[];j.stderr?.on(`data`,e=>{F.push(e),log$2.warn({cwd:t,cliCmd:k,msg:e.toString(`utf-8`).trim()},`[local-op/open] child stderr`)});let L=null;j.on(`exit`,e=>{L=e??-1}),j.unref();let B=Date.now()+45e3;for(;Date.now()<B;){await setTimeout$1(500);let e=readUiLock(S);if(e&&e.port>0)return{port:e.port};if(L!==null){let e=Buffer.concat(F).toString(`utf-8`).trim();return{error:`\`ok ${k}\` exited (code ${L})${e?` — ${e}`:``}`}}}let H=Buffer.concat(F).toString(`utf-8`).trim();return{error:`UI did not start within the expected time${H?` — ${H}`:``}`}}let ac=`local-op-open`,oc=withValidation(LocalOpOpenRequestSchema,async(e,t,S)=>{let{dir:w}=S;if(!isSafeLocalPath(w)){errorResponse(t,400,`urn:ok:error:dir-outside-home`,`dir must be within the user home directory.`,{handler:ac,cause:Error(`dir=${w}`)});return}if(!Ce.tryAcquire(Rs)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A server-open operation is already in progress.`,{handler:ac,extraHeaders:{"Retry-After":`5`}});return}try{let e=await ic(w);`port`in e?successResponse(t,200,LocalOpOpenSuccessSchema,{port:e.port},{handler:ac}):errorResponse(t,504,`urn:ok:error:server-open-failed`,`Failed to open project server.`,{handler:ac,cause:Error(e.error)})}finally{Ce.release(Rs)}},{handler:ac,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:ac})}),sc=`/api/local-op/auth/login`,cc=`/api/local-op/auth/status`,lc=`/api/local-op/auth/repos`,uc=`/api/local-op/auth/signout`,dc=`/api/local-op/auth/pat`,fc=`local-op-auth-login`,pc=withValidation(LocalOpAuthHostRequestSchema,mc,{handler:fc,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:fc})});async function mc(e,t,S){let w=S.host??`github.com`;if(!Ce.tryAcquire(sc)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`An auth login operation is already in progress.`,{handler:fc,extraHeaders:{"Retry-After":`5`}});return}t.writeHead(200,{"Content-Type":`application/x-ndjson`,"Transfer-Encoding":`chunked`,"X-Content-Type-Options":`nosniff`,"Cache-Control":`no-cache`});let E=createStreamingErrorWriter(t,fc),D=runDeviceFlowSubprocess({cliArgs:ue,host:w,timeoutMs:$s,onEvent:e=>{if(e.type===`error`){E(500,`urn:ok:error:auth-failed`,`Auth subprocess reported an error.`,{cause:e.message?Error(e.message):void 0});return}if(!t.writableEnded&&!t.destroyed)try{t.write(`${JSON.stringify(e)}\n`)}catch{}}}),O=()=>{D.cancel()};t.on(`close`,O),D.done.finally(()=>{t.off(`close`,O),t.writableEnded||t.end(),Ce.release(sc)})}let hc=`local-op-auth-status`,gc=withValidation(LocalOpAuthHostRequestSchema,async(e,t,S)=>{let w=S.host??`github.com`;if(!Ce.tryAcquire(cc)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`An auth status operation is already in progress.`,{handler:hc,extraHeaders:{"Retry-After":`5`}});return}try{let[e,...S]=ue,E=[...S,`auth`,`status`,`--json`,`--host`,w],D=(await new Promise((t,S)=>{let w=spawn(e,E,{stdio:[`ignore`,`pipe`,`pipe`],env:{...process.env}}),D=!1,O=setTimeout(()=>{D=!0,w.kill(`SIGTERM`)},3e4),k=[];w.stdout.on(`data`,e=>k.push(e)),w.on(`close`,()=>{if(clearTimeout(O),D){S(Error(`auth status subprocess timed out after 30s`));return}t(Buffer.concat(k).toString(`utf-8`))}),w.on(`error`,e=>{clearTimeout(O),S(e)})})).split(`
|
|
2110
|
+
`)[0]??``).split(/\s+/)[2];if(S){let w=await e.raw(`cat-file`,`-p`,S);t.writeHead(200,{"Content-Type":`text/markdown`,"X-Content-Type-Options":`nosniff`}),t.end(w);return}}}catch(e){console.warn(`[rescue] timeline-ref fallback failed:`,e)}errorResponse(t,404,`urn:ok:error:not-found`,`Not found.`,{handler:`rescue-get`})}let xs=withValidation(CreatePageRequestSchema,async(e,t,S)=>{try{let e=extractActorIdentity(S,fe);if(e.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`create-page`});return}let E=S.path;if(!isSupportedDocFile(E)){errorResponse(t,400,`urn:ok:error:invalid-request`,`path must end with .md or .mdx.`,{handler:`create-page`});return}if(E.includes(`..`)||E.startsWith(`/`)||E.includes(`\0`)||E.includes(`\\`)){errorResponse(t,400,`urn:ok:error:path-escape`,`Invalid path.`,{handler:`create-page`,detail:`path must not contain .. or start with /`});return}let O=resolve(w),k=resolve(O,E);if(!k.startsWith(`${O}/`)&&k!==O){errorResponse(t,400,`urn:ok:error:path-escape`,`path must not escape content directory.`,{handler:`create-page`});return}let j=stripDocExtension(E);if(isSystemDoc(j)||isConfigDoc(j)){errorResponse(t,400,`urn:ok:error:reserved-doc-name`,`'${j}' is a reserved document name.`,{handler:`create-page`});return}let F=typeof S.template==`string`?S.template.trim():``,L=``,B;if(F.length>0){if(!/^[A-Za-z0-9_-]+$/.test(F)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Template name must match [A-Za-z0-9_-]+.`,{handler:`create-page`});return}let S=E.includes(`/`)?E.slice(0,E.lastIndexOf(`/`)):``,w=resolveTemplatesAvailable(O,S),D=w.find(e=>e.name===F);if(!D){let e=w.length===0?`(none)`:w.map(e=>`"${e.name}" (${e.scope})`).join(`, `);errorResponse(t,400,`urn:ok:error:invalid-request`,`Template "${F}" does not resolve for folder "${S||`(root)`}". Available: ${e}`,{handler:`create-page`});return}let k=resolve(O,D.path),j;try{j=readFileSync(k,`utf-8`)}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read template at ${D.path}.`,{handler:`create-page`,cause:e});return}let{body:H}=stripFrontmatter(j),q=e.kind===`agent`||e.kind===`principal`?e.displayName??``:``;L=applySubstitution(H,{date:todayIsoUtc(),user:q}),B=D.scope}mkdirSync(dirname(k),{recursive:!0});try{writeFileSync(k,L,{encoding:`utf-8`,flag:`wx`})}catch(e){if(e.code===`EEXIST`){errorResponse(t,409,`urn:ok:error:doc-already-exists`,`File already exists.`,{handler:`create-page`,cause:e});return}throw e}let H=stripDocExtension(E);switch(ye?.delete(H),me&&me.incrementMdDir(dirname(H)),registerWrite(k,contentHash(L)),e.kind){case`agent`:case`principal`:recordContributor(H,e.writerId,e.displayName,e.colorSeed,void 0,e.actor);break;case`anonymous`:break;default:throw Error(`Unhandled actor kind in handleCreatePage: ${String(e.kind)}`)}let q=typeof D==`function`?D():null;q instanceof Map&&updateFileIndex({kind:`create`,path:k,docName:H,content:L},q),ee&&(ee.updateDocumentFromMarkdown(H,L),ee.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist create-page cache for ${H}:`,e)}),ne?.(`backlinks`),ne?.(`graph`)),ne?.(`files`),B!==void 0&&console.warn(JSON.stringify({event:`template-instantiate`,templateName:F,templateScope:B,docName:H})),successResponse(t,200,CreatePageSuccessSchema,{docName:H},{handler:`create-page`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to create page.`,{handler:`create-page`,cause:e})}},{handler:`create-page`,method:`POST`}),Cs=withValidation(CreateFolderRequestSchema,async(e,t,S)=>{try{if(extractActorIdentity(S,fe).kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`create-folder`});return}let e=S.path;if(!isValidRelativeContentPath(e)){errorResponse(t,400,`urn:ok:error:invalid-request`,`path must be a relative content path.`,{handler:`create-folder`});return}if(e===`.ok`||e.startsWith(`.ok/`)){errorResponse(t,400,`urn:ok:error:reserved-doc-name`,`'.ok' is a reserved directory.`,{handler:`create-folder`});return}if(me?.isDirExcluded(e)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Destination folder is excluded by the workspace content config.`,{handler:`create-folder`});return}let E=resolveContentEntryPath(w,`folder`,e);if(existsSync(E)){errorResponse(t,409,`urn:ok:error:doc-already-exists`,`Folder already exists.`,{handler:`create-folder`});return}tracedMkdirSync(E,{recursive:!0}),je(e),ne?.(`files`),successResponse(t,200,CreateFolderSuccessSchema,{path:e},{handler:`create-folder`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to create folder.`,{handler:`create-folder`,cause:e})}},{handler:`create-folder`,method:`POST`}),Ts=withValidation(EmptyRequestSchema,async(e,t)=>{try{let S=new URL(e.url??``,`http://localhost`).searchParams.get(`docName`);if(!S||S.length===0){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing docName query parameter.`,{handler:`page-headings`});return}if(!isSafeDocName(S)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`page-headings`});return}let w=ze(S);if(!w){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`page-headings`});return}if(!existsSync(w)){errorResponse(t,404,`urn:ok:error:doc-not-found`,`Page not found.`,{handler:`page-headings`});return}successResponse(t,200,PageHeadingsSuccessSchema,{docName:S,headings:extractHeadings(readFileSync(w,`utf-8`))},{handler:`page-headings`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read headings.`,{handler:`page-headings`,cause:e})}},{handler:`page-headings`,method:`GET`,skipBodyParse:!0}),Ds=withValidation(RenamePathRequestSchema,async(e,t,S)=>{try{let e=extractActorIdentity(S,fe);if(e.kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`rename-path`});return}let{kind:E,fromPath:D,toPath:O}=S;if(!isValidRelativeContentPath(D)||!isValidRelativeContentPath(O)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Paths must be relative content paths.`,{handler:`rename-path`});return}if(E===`file`&&(isSystemDoc(D)||isSystemDoc(O)||isConfigDoc(D)||isConfigDoc(O))){errorResponse(t,400,`urn:ok:error:reserved-doc-name`,`Reserved document names cannot be renamed.`,{handler:`rename-path`});return}if(D===`.ok`||D.startsWith(`.ok/`)||O===`.ok`||O.startsWith(`.ok/`)){errorResponse(t,400,`urn:ok:error:reserved-doc-name`,`.ok is a reserved directory.`,{handler:`rename-path`});return}if(D===O){successResponse(t,200,RenamePathSuccessSchema,{renamed:[],rewrittenDocs:[]},{handler:`rename-path`});return}if(D.toLowerCase()===O.toLowerCase()){errorResponse(t,400,`urn:ok:error:invalid-request`,`Case-only renames are not supported.`,{handler:`rename-path`});return}if(E===`file`&&probeAndRegisterSourceFileExtension(w,D),me&&(E===`file`?me.isExcluded(isSupportedDocFile(O)?O:`${O}${getDocExtension(D)}`):me.isDirExcluded(O))){errorResponse(t,400,`urn:ok:error:invalid-request`,`Destination ${E===`file`?`document`:`folder`} is excluded by the project content config.`,{handler:`rename-path`});return}let k=e.kind===`agent`||e.kind===`principal`?{writerId:e.writerId,displayName:e.displayName,colorSeed:e.colorSeed,actorMetadata:e.actor}:void 0,j;try{j=await Lt(D,O,E,k?{actor:k}:{})}catch(e){if(e instanceof ManagedRenameCollisionError){errorResponse(t,409,`urn:ok:error:doc-already-exists`,vt(e.message),{handler:`rename-path`,extensions:{colliding:e.colliding},cause:e});return}throw e}if(j.renamed.length===0){successResponse(t,200,RenamePathSuccessSchema,{renamed:[],rewrittenDocs:[]},{handler:`rename-path`});return}let F;switch(e.kind){case`agent`:{let t=e.summary.kind===`value`,S=t?e.summary:normalizeSummary(`Renamed ${D} → ${O}`),w=Bt(S);F=t||!w.response?w.response:Vt(w.response);for(let t=0;t<j.renamed.length;t++){let{fromDocName:S,toDocName:E}=j.renamed[t];recordContributor(E,e.writerId,e.displayName,e.colorSeed,formatRenameSubject(S,E),e.actor,t===0?w.stored:void 0)}incrementAgentWriteCalls(),Ht(S,!t);for(let{toDocName:e}of j.renamed)rt(e,`rename-path`);break}case`principal`:{let t=Bt(e.summary);F=t.response;for(let S=0;S<j.renamed.length;S++){let{fromDocName:w,toDocName:E}=j.renamed[S];recordContributor(E,e.writerId,e.displayName,e.colorSeed,formatRenameSubject(w,E),e.actor,S===0?t.stored:void 0)}Ht(e.summary,!1);for(let{toDocName:e}of j.renamed)rt(e,`rename-path`);break}case`anonymous`:log$2.debug({kind:E,fromPath:D,toPath:O,affectedDocs:j.renamed.length},`[rename-path] anonymous actor — no contributor recorded (no agentId in body and getPrincipal() returned null)`);break;default:throw Error(`Unhandled actor kind in handleRenamePath: ${String(e.kind)}`)}if(renameAttributionCounter().add(1,{kind:`rename-${E}`,attribution_kind:e.kind}),H)try{await H()}catch(e){console.warn(`[rename-path] flushContributors failed (commitSha backfill may be deferred):`,e)}successResponse(t,200,RenamePathSuccessSchema,{renamed:j.renamed,rewrittenDocs:j.rewrittenDocs,...F?{summary:F}:{}},{handler:`rename-path`})}catch(e){let{status:S,type:w,error:E}=Tt(e);errorResponse(t,S,w,E,{handler:`rename-path`,cause:e})}},{handler:`rename-path`,method:`POST`}),Os=withValidation(DeletePathRequestSchema,async(e,t,S)=>{try{Rt(S);let{kind:e,path:E}=S;if(!isValidRelativeContentPath(E)){errorResponse(t,400,`urn:ok:error:invalid-request`,`path must be a relative content path.`,{handler:`delete-path`});return}let O=resolveContentEntryPath(w,e,E);if(!existsSync(O)){errorResponse(t,404,`urn:ok:error:doc-not-found`,`${e} does not exist.`,{handler:`delete-path`});return}let k=statSync(O);if(e===`file`&&!k.isFile()||e===`folder`&&!k.isDirectory()){errorResponse(t,400,`urn:ok:error:invalid-request`,`Target path is not a ${e}.`,{handler:`delete-path`});return}let j=e===`file`?[E]:listAffectedDocNames(D(),e,E);if(await Et(j),ye)for(let e of j)isSystemDoc(e)||isConfigDoc(e)||(ye.setDeleted(e),console.info(JSON.stringify({event:`recently-removed-docs-populate`,docName:e,kind:`deleted`,source:`handleDeletePath`})));e===`file`?unlinkSync(O):(rmSync(O,{recursive:!0,force:!1}),Me(E));let F=D();if(F instanceof Map)for(let e of j)updateFileIndex({kind:`delete`,path:resolve(w,`${e}${getDocExtension(e)}`),docName:e},F);successResponse(t,200,DeletePathSuccessSchema,{deletedDocNames:j},{handler:`delete-path`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to delete path.`,{handler:`delete-path`,cause:e})}},{handler:`delete-path`,method:`POST`}),ks=withValidation(TrashCleanupRequestSchema,async(e,t,S)=>withSpan(`ok.fs.trash_cleanup`,{attributes:{"ok.cleanup.kind":S.kind,"ok.cleanup.path":normalizeFsPath(S.path),"ok.cleanup.path.role":classifyFsPath(S.path)}},async()=>{try{if(extractActorIdentity(S,fe).kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:`trash-cleanup`});return}let{kind:e,path:E}=S;if(!isValidRelativeContentPath(E)){errorResponse(t,400,`urn:ok:error:invalid-request`,`path must be a relative content path.`,{handler:`trash-cleanup`});return}let O=e===`folder`&&(E===`__system__`||E===`__config__`||E===`__user__`||E===`__local__`||E.startsWith(`__system__/`)||E.startsWith(`__config__/`)||E.startsWith(`__user__/`)||E.startsWith(`__local__/`));if(e===`file`&&(isSystemDoc(E)||isConfigDoc(E))||O){errorResponse(t,400,`urn:ok:error:reserved-doc-name`,`'${E}' is a reserved document name.`,{handler:`trash-cleanup`});return}let k=D(),j=e===`file`?k.has(E)?[E]:[]:listAffectedDocNames(k,e,E);if(j.length===0){successResponse(t,200,TrashCleanupSuccessSchema,{deletedDocNames:[]},{handler:`trash-cleanup`});return}if(await Et(j),ye)for(let e of j)isSystemDoc(e)||isConfigDoc(e)||(ye.setDeleted(e),console.info(JSON.stringify({event:`recently-removed-docs-populate`,docName:e,kind:`deleted`,source:`handleTrashCleanup`})));let F=D();if(F instanceof Map)for(let e of j)updateFileIndex({kind:`delete`,path:resolve(w,`${e}${getDocExtension(e)}`),docName:e},F);e===`folder`&&Me(E),ne?.(`files`),successResponse(t,200,TrashCleanupSuccessSchema,{deletedDocNames:j},{handler:`trash-cleanup`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to clean up after trash.`,{handler:`trash-cleanup`,cause:e})}}),{handler:`trash-cleanup`,method:`POST`}),As=withValidation(EmptyRequestSchema,async(e,t)=>{try{let e=D(),S=[];for(let[t,E]of e){let e=t,D=getDocExtension(t);try{e=extractPageTitle(readFileSync(resolve(w,`${t}${D}`),`utf-8`),t)}catch(e){console.warn(`[pages] Failed to read title for ${t}:`,e)}S.push({docName:t,title:e,docExt:D,size:E.size,modified:E.modified})}S.sort((e,t)=>e.docName.localeCompare(t.docName)),successResponse(t,200,PagesSuccessSchema,{pages:S},{handler:`pages`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to list pages.`,{handler:`pages`,cause:e})}},{handler:`pages`,method:`GET`,skipBodyParse:!0}),Ns=withValidation(EmptyRequestSchema,async(e,S)=>{try{let w=new URL(e.url??``,`http://localhost`).searchParams.get(`docName`);if(!w){errorResponse(S,400,`urn:ok:error:invalid-request`,`Missing docName parameter.`,{handler:`suggest-links`});return}if(!isSafeDocName(w)){errorResponse(S,400,`urn:ok:error:invalid-request`,`Invalid docName.`,{handler:`suggest-links`});return}if(isSystemDoc(w)||isConfigDoc(w)){errorResponse(S,400,`urn:ok:error:reserved-doc-name`,`'${w}' is a reserved document name.`,{handler:`suggest-links`});return}successResponse(S,200,SuggestLinksSuccessSchema,await suggestLinks({hocuspocus:t,fileIndex:D(),docName:w}),{handler:`suggest-links`})}catch(e){if(e instanceof SuggestLinksTargetNotFoundError){errorResponse(S,404,`urn:ok:error:doc-not-found`,`Page not found.`,{handler:`suggest-links`,cause:e});return}errorResponse(S,500,`urn:ok:error:internal-server-error`,`Failed to suggest links.`,{handler:`suggest-links`,cause:e})}},{handler:`suggest-links`,method:`GET`,skipBodyParse:!0});async function Ps(e,t){if(e.method!==`POST`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`upload-asset`,extraHeaders:{Allow:`POST`}});return}let S;try{S=await readUploadBody(e,de??w)}catch(e){if(e instanceof UploadWriteError){errorResponse(t,uploadStatusFor(e.reason),e.reason,uploadTitleFor(e.reason),{handler:`upload-asset`,cause:e});return}errorResponse(t,400,`urn:ok:error:malformed-upload`,`Failed to parse upload.`,{handler:`upload-asset`,cause:e});return}let{filename:E,tempPath:D,sha:O,byteLength:k,parentDocName:j}=S,F=()=>{if(existsSync(D))try{unlinkSync(D)}catch{}},L=validateBody(UploadRequestSchema,{parentDocName:j},t,{handler:`upload-asset`});if(!L.ok){F();return}let{parentDocName:B}=L.value,{agentId:H,agentName:q}=Rt(Object.fromEntries(new URL(e.url??``,`http://localhost`).searchParams.entries()));if(k===0){F(),errorResponse(t,400,`urn:ok:error:no-file-received`,`No file received.`,{handler:`upload-asset`});return}if(B.includes(`\0`)||B.includes(`..`)||B.startsWith(`/`)){F(),errorResponse(t,400,`urn:ok:error:path-escape`,`Path escape detected.`,{handler:`upload-asset`});return}let J=resolve(w),Y=resolveUploadDestDir(B,`./`,J);if(!isWithinContentDir(Y,J)){F(),errorResponse(t,400,`urn:ok:error:path-escape`,`Path escape detected.`,{handler:`upload-asset`});return}try{assertNoSymlinkEscape(Y,J)}catch(e){if(F(),(e instanceof Error?e.message:String(e)).startsWith(`symlink-escape:`)){errorResponse(t,400,`urn:ok:error:path-escape`,`Path escape detected.`,{handler:`upload-asset`});return}log$2.error({err:e,destDir:Y},`[upload] failed to validate destination directory`),errorResponse(t,500,`urn:ok:error:storage-error`,`Storage error.`,{handler:`upload-asset`,cause:e});return}try{mkdirSync(Y,{recursive:!0})}catch(e){if(e.code!==`EEXIST`){F();let S=classifyUploadErrno(e);errorResponse(t,uploadStatusFor(S),S,uploadTitleFor(S),{handler:`upload-asset`,cause:e,detail:`failed to create attachment directory`});return}}try{let e=realpathSync(Y),S;try{S=realpathSync(J)}catch{S=J}if(!isWithinContentDir(e,S)){F(),errorResponse(t,400,`urn:ok:error:path-escape`,`Path escape detected.`,{handler:`upload-asset`});return}}catch(e){if(e.code!==`ENOENT`){F(),errorResponse(t,400,`urn:ok:error:path-escape`,`Path escape detected.`,{handler:`upload-asset`,cause:e});return}}let ee=await fileTypeFromFile(D),te=ee?.mime,ne=ee?.ext;if(!te){let e=readTempFileHead(D,256).toString(`utf-8`).replace(/^/,``).trimStart();(e.startsWith(`<svg`)||e.startsWith(`<?xml`)&&e.includes(`<svg`))&&(te=`image/svg+xml`,ne=`svg`)}{let S=await findDuplicateAsset(Y,O,k);if(S){F();let E=relative(w,resolve(Y,S));log$2.info({event:`upload`,endpoint:e.url??`/api/upload`,agentId:H,agentName:q,dedup:!0,mime:te??null,size:k,destPath:E,httpStatus:200},`[upload] dedup hit`),successResponse(t,200,UploadAssetSuccessSchema,{src:S,path:E,deduped:!0},{handler:`upload-asset`});return}}let ae;if(!E||E===`upload`||GENERIC_PASTE_NAMES.test(E)){let e=new Date().toISOString().replace(/[-:T]/g,``).slice(0,14).replace(/(\d{8})(\d{6})/,`$1-$2`),t=E?extname(E).slice(1):``,S=ne??t??``;ae=S===``?`pasted-${e}`:`pasted-${e}.${S}`}else ae=sanitizeFilename(E);try{let S=linkTempToFinalWithCollisionRetry(D,Y,ae),E=relative(w,resolve(Y,S));log$2.info({event:`upload`,endpoint:e.url??`/api/upload`,agentId:H,agentName:q,dedup:!1,mime:te??null,size:k,destPath:E,httpStatus:200},`[upload] write ok`),successResponse(t,200,UploadAssetSuccessSchema,{src:S,path:E,deduped:!1},{handler:`upload-asset`})}catch(S){let w=S instanceof UploadWriteError?S.reason:`urn:ok:error:storage-error`;log$2.error({event:`upload`,endpoint:e.url??`/api/upload`,agentId:H,agentName:q,filename:ae,size:k,reason:w,httpStatus:uploadStatusFor(w),err:S},`[upload] write failed`),errorResponse(t,uploadStatusFor(w),w,uploadTitleFor(w),{handler:`upload-asset`,cause:S})}}let Is=`/api/local-op/clone`,Rs=`/api/local-op/open`,$s=600*1e3,ec=45e3,tc=`local-op-clone`,nc=withValidation(LocalOpCloneRequestSchema,rc,{handler:tc,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:tc})});async function rc(e,t,S){let{url:w,dir:E}=S;if(!isAllowedGitUrl(w)){errorResponse(t,400,`urn:ok:error:url-not-allowed`,`URL protocol is not allowed for clone.`,{handler:tc,cause:Error(`url=${w}`)});return}if(!isSafeLocalPath(E)){errorResponse(t,400,`urn:ok:error:dir-outside-home`,`Clone destination must be within the user home directory.`,{handler:tc,cause:Error(`dir=${E}`)});return}if(!Ce.tryAcquire(Is)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A clone operation is already in progress.`,{handler:tc,extraHeaders:{"Retry-After":`30`}});return}t.writeHead(200,{"Content-Type":`application/x-ndjson`,"Transfer-Encoding":`chunked`,"X-Content-Type-Options":`nosniff`,"Cache-Control":`no-cache`});let D=createStreamingErrorWriter(t,tc),O=null,k=runCloneSubprocess({cliArgs:ue,url:w,dir:E,timeoutMs:$s,onEvent:e=>{if(e.type===`complete`){O=e.dir;return}if(e.type===`error`){e.message&&log$2.warn({stderr:e.message,url:w,dir:E},`[local-op/clone] clone failed`),D(500,`urn:ok:error:clone-failed`,`Clone subprocess reported an error.`,{cause:e.message?Error(e.message):void 0});return}if(!t.writableEnded&&!t.destroyed)try{t.write(`${JSON.stringify(e)}\n`)}catch{}}});(async()=>{try{if(await k.done,O&&!t.writableEnded&&!t.destroyed){let e=await ic(O);!t.writableEnded&&!t.destroyed&&(`port`in e?t.write(`${JSON.stringify({type:`complete`,port:e.port,dir:O})}\n`):D(500,`urn:ok:error:server-start-failed`,`Cloned successfully but failed to start the project server.`,{cause:Error(e.error)}))}}catch(e){!t.writableEnded&&!t.destroyed?D(500,`urn:ok:error:internal-server-error`,`Unexpected error during clone post-processing.`,{cause:e}):log$2.error({err:e,handler:tc},`clone IIFE rejected after stream ended`)}finally{t.writableEnded||t.end(),Ce.release(Is)}})(),t.on(`close`,()=>{k.cancel()})}async function ic(e){let t=resolve(expandTilde(e)),S=getLocalDir(t),w=readUiLock(S);if(w&&w.port>0)return{port:w.port};let E=readServerLock(S),[D,...O]=ue,k=E&&E.port>0?`ui`:`start`,j=spawn(D,[...O,k],{cwd:t,detached:!0,stdio:[`ignore`,`ignore`,`pipe`],env:{...process.env,OK_LOCK_KIND:`interactive`}}),F=[];j.stderr?.on(`data`,e=>{F.push(e),log$2.warn({cwd:t,cliCmd:k,msg:e.toString(`utf-8`).trim()},`[local-op/open] child stderr`)});let L=null;j.on(`exit`,e=>{L=e??-1}),j.unref();let B=Date.now()+45e3;for(;Date.now()<B;){await setTimeout$1(500);let e=readUiLock(S);if(e&&e.port>0)return{port:e.port};if(L!==null){let e=Buffer.concat(F).toString(`utf-8`).trim();return{error:`\`ok ${k}\` exited (code ${L})${e?` — ${e}`:``}`}}}let H=Buffer.concat(F).toString(`utf-8`).trim();return{error:`UI did not start within the expected time${H?` — ${H}`:``}`}}let ac=`local-op-open`,oc=withValidation(LocalOpOpenRequestSchema,async(e,t,S)=>{let{dir:w}=S;if(!isSafeLocalPath(w)){errorResponse(t,400,`urn:ok:error:dir-outside-home`,`dir must be within the user home directory.`,{handler:ac,cause:Error(`dir=${w}`)});return}if(!Ce.tryAcquire(Rs)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A server-open operation is already in progress.`,{handler:ac,extraHeaders:{"Retry-After":`5`}});return}try{let e=await ic(w);`port`in e?successResponse(t,200,LocalOpOpenSuccessSchema,{port:e.port},{handler:ac}):errorResponse(t,504,`urn:ok:error:server-open-failed`,`Failed to open project server.`,{handler:ac,cause:Error(e.error)})}finally{Ce.release(Rs)}},{handler:ac,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:ac})}),sc=`/api/local-op/auth/login`,cc=`/api/local-op/auth/status`,lc=`/api/local-op/auth/repos`,uc=`/api/local-op/auth/signout`,dc=`/api/local-op/auth/pat`,fc=`local-op-auth-login`,pc=withValidation(LocalOpAuthHostRequestSchema,mc,{handler:fc,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:fc})});async function mc(e,t,S){let w=S.host??`github.com`;if(!Ce.tryAcquire(sc)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`An auth login operation is already in progress.`,{handler:fc,extraHeaders:{"Retry-After":`5`}});return}t.writeHead(200,{"Content-Type":`application/x-ndjson`,"Transfer-Encoding":`chunked`,"X-Content-Type-Options":`nosniff`,"Cache-Control":`no-cache`});let E=createStreamingErrorWriter(t,fc),D=runDeviceFlowSubprocess({cliArgs:ue,host:w,timeoutMs:$s,onEvent:e=>{if(e.type===`error`){E(500,`urn:ok:error:auth-failed`,`Auth subprocess reported an error.`,{cause:e.message?Error(e.message):void 0});return}if(!t.writableEnded&&!t.destroyed)try{t.write(`${JSON.stringify(e)}\n`)}catch{}}}),O=()=>{D.cancel()};t.on(`close`,O),D.done.finally(()=>{t.off(`close`,O),t.writableEnded||t.end(),Ce.release(sc)})}let hc=`local-op-auth-status`,gc=withValidation(LocalOpAuthHostRequestSchema,async(e,t,S)=>{let w=S.host??`github.com`;if(!Ce.tryAcquire(cc)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`An auth status operation is already in progress.`,{handler:hc,extraHeaders:{"Retry-After":`5`}});return}try{let[e,...S]=ue,E=[...S,`auth`,`status`,`--json`,`--host`,w],D=(await new Promise((t,S)=>{let w=spawn(e,E,{stdio:[`ignore`,`pipe`,`pipe`],env:{...process.env}}),D=!1,O=setTimeout(()=>{D=!0,w.kill(`SIGTERM`)},3e4),k=[];w.stdout.on(`data`,e=>k.push(e)),w.on(`close`,()=>{if(clearTimeout(O),D){S(Error(`auth status subprocess timed out after 30s`));return}t(Buffer.concat(k).toString(`utf-8`))}),w.on(`error`,e=>{clearTimeout(O),S(e)})})).split(`
|
|
2111
2111
|
`).map(e=>e.trim()).filter(Boolean),O=null;for(let e=D.length-1;e>=0;e--)try{O=JSON.parse(D[e]);break}catch{}O===null?successResponse(t,200,LocalOpAuthStatusSuccessSchema,{authenticated:!1},{handler:hc}):successResponse(t,200,LocalOpAuthStatusSuccessSchema,O,{handler:hc})}catch(e){errorResponse(t,500,`urn:ok:error:auth-failed`,`Auth status check failed.`,{handler:hc,cause:e})}finally{Ce.release(cc)}},{handler:hc,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:hc})}),_c=`local-op-auth-repos`,vc=withValidation(LocalOpAuthHostRequestSchema,yc,{handler:_c,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:_c})});async function yc(e,t,S){let w=S.host??`github.com`;if(!Ce.tryAcquire(lc)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`An auth repos operation is already in progress.`,{handler:_c,extraHeaders:{"Retry-After":`5`}});return}t.writeHead(200,{"Content-Type":`application/x-ndjson`,"Transfer-Encoding":`chunked`,"X-Content-Type-Options":`nosniff`,"Cache-Control":`no-cache`});let E=createStreamingErrorWriter(t,_c),[D,...O]=ue,k=[...O,`auth`,`repos`,`--json`,`--host`,w],j=!1,F=``,L=spawn(D,k,{stdio:[`ignore`,`pipe`,`pipe`],env:{...process.env}}),B=setTimeout(()=>{L.kill(`SIGTERM`)},$s);L.stdout.on(`data`,e=>{F+=e.toString(`utf-8`);let S=F.split(`
|
|
2112
2112
|
`);F=S.pop()??``;for(let e of S){if(!e.trim())continue;let S=null;try{S=JSON.parse(e)}catch{}if(S&&S.type===`error`){E(500,`urn:ok:error:auth-failed`,`Auth repos subprocess reported an error.`,{detail:typeof S.message==`string`?S.message:void 0});continue}if(!t.writableEnded&&!t.destroyed)try{t.write(`${e}\n`)}catch{}}}),L.stderr.on(`data`,e=>{log$2.debug({msg:e.toString(`utf-8`).trim()},`[local-op/auth/repos] stderr`)}),L.on(`close`,e=>{clearTimeout(B),j||(j=!0,e!==0&&!t.writableEnded&&E(500,`urn:ok:error:auth-failed`,`Auth repos subprocess exited with code ${e}.`),t.end(),Ce.release(lc))}),L.on(`error`,e=>{clearTimeout(B),j||(j=!0,t.writableEnded||(E(500,`urn:ok:error:auth-failed`,`Failed to spawn the auth repos subprocess.`,{cause:e}),t.end()),Ce.release(lc))}),t.on(`close`,()=>{j||(j=!0,clearTimeout(B),L.kill(`SIGTERM`),Ce.release(lc))})}let bc=`local-op-auth-signout`,xc=withValidation(LocalOpAuthHostRequestSchema,async(e,t,S)=>{let w=S.host??`github.com`;if(!Ce.tryAcquire(uc)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`An auth signout operation is already in progress.`,{handler:bc,extraHeaders:{"Retry-After":`5`}});return}try{let[e,...S]=ue,E=[...S,`auth`,`signout`,`--host`,w];await new Promise((t,S)=>{let w=spawn(e,E,{stdio:`ignore`,env:{...process.env}}),D=setTimeout(()=>{w.kill(`SIGTERM`)},3e4);w.on(`close`,()=>{clearTimeout(D),t()}),w.on(`error`,e=>{clearTimeout(D),S(e)})}),successResponse(t,200,LocalOpAuthEmptySuccessSchema,{},{handler:bc})}catch(e){errorResponse(t,500,`urn:ok:error:auth-failed`,`Auth signout failed.`,{handler:bc,cause:e})}finally{Ce.release(uc)}},{handler:bc,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:bc})}),Sc=`local-op-auth-pat`,Cc=withValidation(LocalOpAuthPatRequestSchema,async(e,t,S)=>{let{pat:w,host:E}=S,D=E??`github.com`;if(!Ce.tryAcquire(dc)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`An auth pat operation is already in progress.`,{handler:Sc,extraHeaders:{"Retry-After":`5`}});return}try{let[e,...S]=ue,E=[...S,`auth`,`pat`,`--json`,`--host`,D],O=(await new Promise((t,S)=>{let D=spawn(e,E,{stdio:[`pipe`,`pipe`,`pipe`],env:{...process.env}}),O=setTimeout(()=>{D.kill(`SIGTERM`)},3e4);D.stdin.write(`${w}\n`),D.stdin.end();let k=[];D.stdout.on(`data`,e=>k.push(e)),D.on(`close`,e=>{clearTimeout(O),e===0?t(Buffer.concat(k).toString(`utf-8`)):S(Error(`auth pat exited with code ${e}`))}),D.on(`error`,e=>{clearTimeout(O),S(e)})})).split(`
|
|
2113
|
-
`).map(e=>e.trim()).filter(Boolean),k=null;for(let e=O.length-1;e>=0;e--)try{k=JSON.parse(O[e]);break}catch{}k===null?successResponse(t,200,LocalOpAuthPatSuccessSchema,{},{handler:Sc}):successResponse(t,200,LocalOpAuthPatSuccessSchema,k,{handler:Sc})}catch(e){errorResponse(t,500,`urn:ok:error:auth-failed`,`Auth pat failed.`,{handler:Sc,cause:e})}finally{Ce.release(dc)}},{handler:Sc,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:Sc})}),wc=`local-op-auth-identity`;async function Tc(e,t){if(checkLocalOpSecurity(e,t,{handler:wc})){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:wc,extraHeaders:{Allow:`GET`}});return}if(!de){errorResponse(t,503,`urn:ok:error:no-project-dir`,`No project directory configured.`,{handler:wc});return}try{successResponse(t,200,LocalOpAuthIdentitySuccessSchema,{identity:await resolveGitIdentity(de)},{handler:wc})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Identity resolution failed.`,{handler:wc,cause:e})}}}let Ec=`/api/local-op/auth/set-identity`,Dc=`local-op-auth-set-identity`,Oc=withValidation(LocalOpAuthSetIdentityRequestSchema,async(e,t,S)=>{let w=S.name.trim(),E=S.email.trim();if(!de){errorResponse(t,503,`urn:ok:error:no-project-dir`,`No project directory configured.`,{handler:Dc});return}if(!Ce.tryAcquire(Ec)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A set-identity operation is already in progress.`,{handler:Dc,extraHeaders:{"Retry-After":`5`}});return}try{writeGitIdentity(de,w,E),ce?.()?.refreshIdentity().catch(()=>{}),successResponse(t,200,LocalOpAuthEmptySuccessSchema,{},{handler:Dc})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Set-identity failed.`,{handler:Dc,cause:e})}finally{Ce.release(Ec)}},{handler:Dc,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:Dc})});async function kc(e,t){if(checkLocalOpSecurity(e,t,{handler:`sync-status`})){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`sync-status`,extraHeaders:{Allow:`GET`}});return}try{let e=ce?.();if(!e){successResponse(t,200,SyncStatusSchema,{state:`dormant`,lastSyncUtc:null,lastFetchUtc:null,lastPushedSha:null,ahead:0,behind:0,consecutiveFailures:0,conflictCount:0,hasRemote:!1,syncEnabled:!1,identityUnresolved:!1},{handler:`sync-status`});return}await e.refreshRemote(),successResponse(t,200,SyncStatusSchema,e.getStatus(),{handler:`sync-status`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`sync-status`,cause:e})}}}let Ac=withValidation(SyncTriggerRequestSchema,async(e,t,S)=>{let w=ce?.();if(!w){errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-trigger`});return}let E=S.op??`sync`;successResponse(t,202,SyncTriggerSuccessSchema,{op:E},{handler:`sync-trigger`}),w.trigger(E)},{handler:`sync-trigger`,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`sync-trigger`})?ce?.()?!0:(errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-trigger`}),!1):!1});async function jc(e,t){if(checkLocalOpSecurity(e,t,{handler:`sync-conflicts`})){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`sync-conflicts`,extraHeaders:{Allow:`GET`}});return}try{let e=ce?.();successResponse(t,200,SyncConflictsSuccessSchema,{conflicts:e?e.getConflicts():[]},{handler:`sync-conflicts`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`sync-conflicts`,cause:e})}}}let Mc=withValidation(SyncResolveConflictRequestSchema,async(e,t,S)=>{let w=ce?.();if(!w){errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-resolve-conflict`});return}let{file:E,strategy:D,content:O}=S;try{await w.resolveConflict(E,D,O),successResponse(t,200,SyncResolveConflictSuccessSchema,{},{handler:`sync-resolve-conflict`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to resolve conflict.`,{handler:`sync-resolve-conflict`,cause:e})}},{handler:`sync-resolve-conflict`,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`sync-resolve-conflict`})?ce?.()?!0:(errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-resolve-conflict`}),!1):!1});async function Nc(e,t){if(!checkLocalOpSecurity(e,t,{handler:`sync-conflict-content`}))return;if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`sync-conflict-content`,extraHeaders:{Allow:`GET`}});return}if(!de){errorResponse(t,503,`urn:ok:error:project-repo-not-configured`,`Project repo not configured.`,{handler:`sync-conflict-content`});return}let S=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`).searchParams.get(`file`);if(!S){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing required query param: file.`,{handler:`sync-conflict-content`});return}if(S.includes(`..`)||S.startsWith(`/`)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid file path.`,{handler:`sync-conflict-content`});return}let w=esm_default({baseDir:de,timeout:{block:15e3}});async function E(e){try{return await w.raw([`show`,`:${e}:${S}`])}catch{return``}}try{let[e,w,D]=await Promise.all([E(1),E(2),E(3)]);successResponse(t,200,SyncConflictContentSuccessSchema,{file:S,base:e,ours:w,theirs:D},{handler:`sync-conflict-content`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read conflict content.`,{handler:`sync-conflict-content`,cause:e})}}async function Pc(e,t){if(!checkLocalOpSecurity(e,t,{handler:`seed-plan`}))return;if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`seed-plan`,extraHeaders:{Allow:`GET`}});return}let S=new URL(e.url??`/`,`http://localhost`),E=S.searchParams.get(`rootDir`)??void 0,D=S.searchParams.get(`packId`),O=coercePackId(D);if(D!==null&&D!==``&&O===void 0){errorResponse(t,400,`urn:ok:error:invalid-request`,`Unknown packId.`,{handler:`seed-plan`,detail:`Pack id "${D}" is not registered.`});return}try{successResponse(t,200,SeedPlanSuccessSchema,{plan:await planSeed({projectDir:w,rootDir:E,packId:O})},{handler:`seed-plan`})}catch(e){if(e instanceof SeedPrerequisiteError){errorResponse(t,422,`urn:ok:error:seed-prerequisite-missing`,`Seed prerequisite missing.`,{handler:`seed-plan`,cause:e});return}if(e instanceof SeedRootDirError){errorResponse(t,400,`urn:ok:error:seed-invalid-root`,`Invalid seed root directory.`,{handler:`seed-plan`,detail:`The provided root directory is not within the workspace content directory.`,cause:e});return}errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`seed-plan`,cause:e})}}let Fc=withValidation(SeedApplyRequestSchema,async(e,t,S)=>{let E=S.plan;if(!E||typeof E!=`object`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid plan payload.`,{handler:`seed-apply`});return}let D=E,O=S.packId,k=coercePackId(O);if(typeof O==`string`&&O.length>0&&k===void 0){errorResponse(t,400,`urn:ok:error:invalid-request`,`Unknown packId.`,{handler:`seed-apply`,detail:`Pack id "${O}" is not registered.`});return}try{successResponse(t,200,SeedApplySuccessSchema,{result:await applySeed(D,{projectDir:w,packId:k})},{handler:`seed-apply`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to apply seed plan.`,{handler:`seed-apply`,cause:e})}},{handler:`seed-apply`,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`seed-apply`})});async function Ic(e,t){if(checkLocalOpSecurity(e,t,{handler:`seed-packs`})){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`seed-packs`,extraHeaders:{Allow:`GET`}});return}successResponse(t,200,SeedListPacksSuccessSchema,{packs:listStarterPacks()},{handler:`seed-packs`})}}let Lc=withValidation(InstallSkillRequestSchema,async(e,t,S)=>{if(S.out!==void 0&&!isSafeLocalPath(S.out)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Output path must be within home directory.`,{handler:`install-skill`});return}try{successResponse(t,200,InstallSkillSuccessSchema,await buildAndOpenSkill({...S.noOpen===void 0?{}:{noOpen:S.noOpen},...S.out===void 0?{}:{out:S.out}}),{handler:`install-skill`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to install skill.`,{handler:`install-skill`,cause:e})}},{handler:`install-skill`,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`install-skill`})});async function Rc(e,t){if(checkLocalOpSecurity(e,t,{handler:`installed-agents`}))try{await handleInstalledAgents(e,t,Re.probeAll)}catch(e){t.headersSent||(log$2.error({err:e},`[installed-agents] route wrapper failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`installed-agents`,cause:e}))}}async function zc(e,t){if(!checkLocalOpSecurity(e,t,{handler:`sync-abort-merge`}))return;if(e.method!==`POST`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`sync-abort-merge`,extraHeaders:{Allow:`POST`}});return}let S=ce?.();if(!S){errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-abort-merge`});return}try{await S.abortMerge(),successResponse(t,200,SyncAbortMergeSuccessSchema,{},{handler:`sync-abort-merge`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to abort merge.`,{handler:`sync-abort-merge`,cause:e})}}let Bc=withValidation(EmptyRequestSchema,async(e,t)=>{if(!te){errorResponse(t,503,`urn:ok:error:tag-index-not-configured`,`Tag index not configured.`,{handler:`tags-list`});return}try{successResponse(t,200,TagsListSuccessSchema,{tags:te.getAllTags()},{handler:`tags-list`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read tags.`,{handler:`tags-list`,cause:e})}},{handler:`tags-list`,method:`GET`,skipBodyParse:!0});async function Vc(e,t,S){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`tags-for-name`,extraHeaders:{Allow:`GET`}});return}if(!te){errorResponse(t,503,`urn:ok:error:tag-index-not-configured`,`Tag index not configured.`,{handler:`tags-for-name`});return}let w;try{w=decodeURIComponent(S)}catch{errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid tag name encoding.`,{handler:`tags-for-name`});return}if(!w){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing tag name.`,{handler:`tags-for-name`});return}try{let e=te.getDocsForTagWithMatches(w).map(({docName:e,matchingTags:t})=>({docName:e,title:Be(e),matchingTags:t,snippet:null}));successResponse(t,200,TagsForNameSuccessSchema,{name:w,docs:e},{handler:`tags-for-name`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read tag membership.`,{handler:`tags-for-name`,cause:e})}}function Hc(e,t,S=`path`,E=`folder-config`){let D=e.replace(/^\.\//,``).replace(/^\/+/,``).replace(/\/+$/,``);if(D.split(`/`).some(e=>e===`..`)||e.startsWith(`/`))return errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid ${S}: must be project-root-relative.`,{handler:E}),null;let O=resolve(w),k=D===``?O:resolve(O,D);return k!==O&&!k.startsWith(`${O}${sep}`)?(errorResponse(t,400,`urn:ok:error:invalid-request`,`Path escapes content directory.`,{handler:E}),null):{folderRel:D,resolvedContentDir:O}}let Uc=/^[A-Za-z0-9_-]+$/;function Wc(e,t,S=`template`){return!e||!Uc.test(e)?(errorResponse(t,400,`urn:ok:error:invalid-request`,"Invalid name: must be letters / digits / `_` / `-` only (no `.md` extension).",{handler:S}),!1):!0}function Gc(e){let t={};if(!e||typeof e!=`object`||Array.isArray(e))return t;for(let[S,w]of Object.entries(e))w!==void 0&&(t[S]=w);return t}async function Kc(e,t){if(e.method===`GET`)return qc(e,t);if(e.method===`PUT`)return Jc(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`folder-config`,extraHeaders:{Allow:`GET, PUT`}})}let qc=withValidation(EmptyRequestSchema,async(e,t)=>{try{let S=Hc(new URL(e.url??``,`http://localhost`).searchParams.get(`path`)??``,t,`path`,`folder-config-get`);if(!S)return;let w=await enrichDirectory(S.folderRel,{projectDir:S.resolvedContentDir}),E=resolve(S.resolvedContentDir,S.folderRel,`.ok`,`frontmatter.yml`),D=null;if(existsSync(E))try{let e=(0,import_dist$1.parse)(await readFile$1(E,`utf-8`));D=e&&typeof e==`object`&&!Array.isArray(e)?e:{}}catch(e){let t=e instanceof Error?e.message:String(e);console.warn(`[folder-config:get] malformed YAML in ${E}: ${t}`),D=null}successResponse(t,200,FolderConfigGetSuccessSchema,{folder:w,frontmatter_local:D},{handler:`folder-config-get`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read folder config.`,{handler:`folder-config-get`,cause:e})}},{handler:`folder-config-get`,method:`GET`,skipBodyParse:!0}),Jc=withValidation(FolderConfigPutRequestSchema,async(e,t,S)=>{try{let e=Hc(S.path,t,`path`,`folder-config-put`);if(!e)return;let w=e.folderRel===``?`**`:`${e.folderRel}/**`,E=applyNestedFolderRulesUpsert({projectDir:e.resolvedContentDir,rules:[{match:w,frontmatter:Gc(S.frontmatter)}]});if(!E.ok){let e=E.error.code===`WRITE_ERROR`||E.error.code===`BAD_PROJECT_DIR`?500:400;errorResponse(t,e,e===500?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,e===500?`Failed to write folder config.`:`Invalid folder config request.`,{handler:`folder-config-put`,detail:E.error.code,cause:Error(E.error.message)});return}successResponse(t,200,FolderConfigPutSuccessSchema,{applied:E.applied},{handler:`folder-config-put`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to write folder config.`,{handler:`folder-config-put`,cause:e})}},{handler:`folder-config-put`,method:`PUT`});async function Yc(e,t){if(e.method===`GET`)return Qc(e,t);if(e.method===`PUT`)return $c(e,t);if(e.method===`DELETE`)return nl(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`template`,extraHeaders:{Allow:`GET, PUT, DELETE`}})}let Xc=/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/,Zc=e=>{let t=e.match(Xc),S={},w=e;if(t){try{let e=(0,import_dist$1.parse)(t[1]??``);e&&typeof e==`object`&&!Array.isArray(e)&&(S=e)}catch{}w=e.slice(t[0].length)}return{frontmatter:S,body:w}},Qc=withValidation(EmptyRequestSchema,async(e,t)=>{try{let S=new URL(e.url??``,`http://localhost`),w=S.searchParams.get(`name`)??``;if(!Wc(w,t,`template-get`))return;let E=Hc(S.searchParams.get(`folder`)??``,t,`folder`,`template-get`);if(!E)return;let{folderRel:D,resolvedContentDir:O}=E,k=D===``?[]:D.split(`/`),j=null,F=null,L=null;for(let e=k.length;e>=0;e--){let t=e===0?``:k.slice(0,e).join(`/`),S=t===``?O:resolve(O,t);if(S!==O&&!S.startsWith(`${O}${sep}`))continue;let E=resolve(S,`.ok`,`templates`,`${w}.md`);if(existsSync(E)){j=E,F=t,L=e===k.length?`local`:`inherited`;break}}if(!j||F===null||L===null){errorResponse(t,404,`urn:ok:error:template-not-found`,`Template not found.`,{handler:`template-get`,detail:`Template "${w}" not found for folder "${D||`.`}". Walked leaf → root.`});return}let{frontmatter:B,body:H}=Zc(await readFile$1(j,`utf-8`)),q=relative(O,j).split(/[\\/]/).filter(Boolean).join(`/`);successResponse(t,200,TemplateGetSuccessSchema,{template:{name:w,folder:F,scope:L,path:q,frontmatter:B,body:H}},{handler:`template-get`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read template.`,{handler:`template-get`,cause:e})}},{handler:`template-get`,method:`GET`,skipBodyParse:!0}),$c=withValidation(TemplatePutRequestSchema,async(e,t,S)=>{try{let e=S.name;if(!Wc(e,t,`template-put`))return;let w=Hc(S.folder,t,`folder`,`template-put`);if(!w)return;let E=applyTemplateWrite({projectDir:w.resolvedContentDir,folder:w.folderRel,name:e,body:typeof S.body==`string`?S.body:``,frontmatter:Gc(S.frontmatter)});if(!E.ok){let e=E.error.code===`WRITE_ERROR`||E.error.code===`BAD_PROJECT_DIR`?500:400;errorResponse(t,e,e===500?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,e===500?`Failed to write template.`:`Invalid template request.`,{handler:`template-put`,detail:E.error.code,cause:Error(E.error.message)});return}successResponse(t,200,TemplatePutSuccessSchema,{path:E.path,created:E.created,warnings:E.warnings},{handler:`template-put`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to write template.`,{handler:`template-put`,cause:e})}},{handler:`template-put`,method:`PUT`}),nl=withValidation(EmptyRequestSchema,async(e,t)=>{try{let S=new URL(e.url??``,`http://localhost`),w=S.searchParams.get(`name`)??``;if(!Wc(w,t,`template-delete`))return;let E=Hc(S.searchParams.get(`folder`)??``,t,`folder`,`template-delete`);if(!E)return;let D=applyTemplateDelete({projectDir:E.resolvedContentDir,folder:E.folderRel,name:w});if(!D.ok){let e=D.error.code===`WRITE_ERROR`||D.error.code===`UNLINK_FAILED`||D.error.code===`BAD_PROJECT_DIR`?500:400;errorResponse(t,e,e===500?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,e===500?`Failed to delete template.`:`Invalid template request.`,{handler:`template-delete`,detail:D.error.code,cause:Error(D.error.message)});return}successResponse(t,200,TemplateDeleteSuccessSchema,{existed:D.existed,path:D.path},{handler:`template-delete`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to delete template.`,{handler:`template-delete`,cause:e})}},{handler:`template-delete`,method:`DELETE`,skipBodyParse:!0});function il(e){let t=new Map;for(let S of e){let e=S.path.split(`/`).filter(Boolean);e.pop();for(let w=1;w<=e.length;w++){let E=e.slice(0,w).join(`/`);t.set(E,Math.max(t.get(E)??0,S.modifiedTs))}}return[...t.entries()].map(([e,t])=>createWorkspaceSearchDocument({kind:`folder`,path:e,modifiedTs:t}))}function al(e,t){let S=t.trim().toLowerCase();if(!S||!e)return;let w=e.toLowerCase().indexOf(S);if(w<0)return;let E=Math.max(0,w-80),D=Math.min(e.length,w+S.length+120),O=E>0?`…`:``,k=D<e.length?`…`:``;return`${O}${e.slice(E,D).replace(/\s+/g,` `).trim()}${k}`}function cl(e){return e===`autocomplete`||e===`full_text`||e===`omnibar`?e:`omnibar`}function ll(e){let t=typeof e==`string`?e.split(`,`):Array.isArray(e)?e:void 0;if(!t)return;let S=t.filter(e=>e===`page`||e===`folder`||e===`content`);return S.length>0?S:void 0}async function ul(){let e=[];for(let[t,S]of D()){if(isSystemDoc(t)||isConfigDoc(t))continue;let w=``,E=t;try{w=await readFile$1(S.canonicalPath,`utf-8`),E=extractPageTitle(w,t)}catch(e){console.warn(`[search] Failed to index ${t}:`,e)}e.push(createWorkspaceSearchDocument({kind:`page`,path:t,title:E,content:w,modifiedTs:Date.parse(S.modified)}))}return[...e,...il(e)]}function dl(){return[...D()].filter(([e])=>!isSystemDoc(e)&&!isConfigDoc(e)).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>`${e}${t.modified}${t.size}${t.canonicalPath}${t.inode}${t.aliases.join(`,`)}`).join(``)}async function fl(){let e=`${w}${de??``}`,t=dl(),S=workspaceSearchCaches.get(e);if(S?.fingerprint===t&&S.corpus)return S.corpus;if(S?.fingerprint===t&&S.pending)return S.pending;let E=ul().then(e=>createWorkspaceSearchCorpus(e));workspaceSearchCaches.set(e,{fingerprint:t,pending:E});try{let S=await E;return workspaceSearchCaches.get(e)?.pending===E&&workspaceSearchCaches.set(e,{fingerprint:t,corpus:S}),S}catch(t){throw workspaceSearchCaches.get(e)?.pending===E&&workspaceSearchCaches.delete(e),t}}function pl(){if(process.env.NODE_ENV!==`test`)for(let e of[0,1e3,3e3])setTimeout(()=>{fl().catch(e=>{console.warn(`[search] Failed to prewarm workspace search cache:`,e)})},e)}pl();async function ml(e,t){if(e.method===`GET`)return hl(e,t);if(e.method===`POST`)return gl(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`search`,extraHeaders:{Allow:`GET, POST`}})}let hl=withValidation(EmptyRequestSchema,async(e,t)=>{let S=new URL(e.url??``,`http://localhost`),w=S.searchParams.get(`limit`),E=S.searchParams.get(`query`)??``,D=cl(S.searchParams.get(`intent`)),O=ll(S.searchParams.get(`scope`)??S.searchParams.get(`scopes`)),k=w===null?void 0:Number(w);if(E.length>200){errorResponse(t,400,`urn:ok:error:invalid-request`,`Query is too long (max 200 chars).`,{handler:`search-get`});return}try{let e=performance.now();successResponse(t,200,SearchSuccessSchema,{query:E,intent:D,results:searchWorkspaceCorpus(await fl(),E,{intent:D,scopes:O,limit:k}).map(e=>({kind:e.document.kind,path:e.document.path,title:e.document.title,score:e.score,signals:e.signals,snippet:e.document.kind===`page`?al(e.document.content,E):void 0})),elapsedMs:Math.max(0,performance.now()-e)},{handler:`search-get`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to search workspace.`,{handler:`search-get`,cause:e})}},{handler:`search-get`,method:`GET`,skipBodyParse:!0}),gl=withValidation(SearchRequestSchema,async(e,t,S)=>{let w=typeof S.query==`string`?S.query:``,E=cl(S.intent),D=ll(S.scopes??S.scope),O=typeof S.limit==`number`?S.limit:void 0;if(w.length>200){errorResponse(t,400,`urn:ok:error:invalid-request`,`Query is too long (max 200 chars).`,{handler:`search-post`});return}try{let e=performance.now();successResponse(t,200,SearchSuccessSchema,{query:w,intent:E,results:searchWorkspaceCorpus(await fl(),w,{intent:E,scopes:D,limit:O}).map(e=>({kind:e.document.kind,path:e.document.path,title:e.document.title,score:e.score,signals:e.signals,snippet:e.document.kind===`page`?al(e.document.content,w):void 0})),elapsedMs:Math.max(0,performance.now()-e)},{handler:`search-post`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to search workspace.`,{handler:`search-post`,cause:e})}},{handler:`search-post`,method:`POST`}),_l=withValidation(EmptyRequestSchema,async(e,t)=>{try{successResponse(t,200,SkillInstallStateSuccessSchema,{...await readSkillInstallStateSnapshot(homedir())},{handler:`skill-install-state`,extraHeaders:{"Cache-Control":`no-store`}})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read skill install state.`,{handler:`skill-install-state`,cause:e})}},{handler:`skill-install-state`,method:`GET`,skipBodyParse:!0,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`skill-install-state`})});async function vl(e,t){if(checkLocalOpSecurity(e,t,{handler:`handoff`}))try{await handleHandoffDispatch(e,t,{contentDir:w,platform:process.platform})}catch(e){t.headersSent||(log$2.error({err:e},`[handoff] route wrapper failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`handoff`,cause:e}))}}async function yl(e,t){if(checkLocalOpSecurity(e,t,{handler:`spawn-cursor`}))try{await handleSpawnCursor(e,t,{contentDir:w,platform:process.platform})}catch(e){t.headersSent||(log$2.error({err:e},`[spawn-cursor] route wrapper failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`spawn-cursor`,cause:e}))}}let xl=withValidation(ShareConstructUrlRequestSchema,async(e,t,S)=>{try{if(!de){emitShareConstructUrlLog(`no-remote`),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`no-remote`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}if(!isValidShareDocPath(S.docPath)){emitShareConstructUrlLog(`invalid-path`),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`invalid-path`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}let e=readGitHeadBranch(de);if(e===null){if(readOriginGitHubRepo(de).kind===`no-remote`){emitShareConstructUrlLog(`no-remote`),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`no-remote`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}emitShareConstructUrlLog(`detached-head`),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`detached-head`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}let w=readOriginGitHubRepo(de);if(w.kind===`no-remote`){emitShareConstructUrlLog(`no-remote`),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`no-remote`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}if(w.kind===`non-github`){emitShareConstructUrlLog(`non-github-remote`),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`non-github-remote`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}if(!branchExistsOnOrigin(de,e)){emitShareConstructUrlLog(`branch-not-on-origin`,!1),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`branch-not-on-origin`,branch:e},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}let E=buildGitHubBlobUrl(w.owner,w.repo,e,S.docPath),D=`${SHARE_BASE_URL}${encodeShareUrl(E)}`;emitShareConstructUrlLog(`ok`,!0),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!0,shareUrl:D,blobUrl:E,branch:e},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG,cause:e})}},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG})});async function Cl(e){let[t,...S]=ue,w=[...S,...e];return await new Promise((e,S)=>{let E=spawn(t,w,{stdio:[`ignore`,`pipe`,`pipe`],env:{...process.env}}),D=!1,O=setTimeout(()=>{D=!0,E.kill(`SIGTERM`)},SHARE_PUBLISH_TIMEOUT_MS),k=[],j=[];E.stdout.on(`data`,e=>k.push(e)),E.stderr.on(`data`,e=>j.push(e)),E.on(`close`,t=>{if(clearTimeout(O),D){S(Error(`share subprocess timed out after ${SHARE_PUBLISH_TIMEOUT_MS}ms`));return}let w=Buffer.concat(k).toString(`utf-8`);if(t!==0){let e=redactShareSubprocessStderr(Buffer.concat(j).toString(`utf-8`)).slice(0,500);console.warn(`[share] subprocess exited code=${t} stderr=${e}`)}e({stdout:w,code:t})}),E.on(`error`,e=>{clearTimeout(O),S(e)})})}let Tl=withValidation(EmptyRequestSchema,async(e,t)=>{if(!Ce.tryAcquire(`/api/share/publish/owners`)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A share owners operation is already in progress.`,{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG,extraHeaders:{"Retry-After":`5`}});return}try{let{stdout:e}=await Cl([`share`,`owners`,`--json`]),S=parseOwnersEvent(pickTerminalJsonLine(e));emitSharePublishLog(`owners-list`,S.ok?`ok`:S.error,S.ok?{count:S.owners.length}:void 0),successResponse(t,200,SharePublishOwnersResponseSchema,S,{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG,cause:e})}finally{Ce.release(SHARE_PUBLISH_OWNERS_KEY)}},{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG,method:`GET`,skipBodyParse:!0,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG})}),El=withValidation(EmptyRequestSchema,async(e,t)=>{let S=new URL(e.url??``,`http://localhost`),w=S.searchParams.get(`owner`)??``,E=S.searchParams.get(`name`)??``;if(!isValidShareOwnerName(w)||!isValidShareRepoName(E)){errorResponse(t,400,`urn:ok:error:invalid-request`,`owner and name query params must be valid GitHub identifiers.`,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG});return}if(!Ce.tryAcquire(`/api/share/publish/name-check`)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A share name-check operation is already in progress.`,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG,extraHeaders:{"Retry-After":`5`}});return}try{let{stdout:e}=await Cl([`share`,`name-check`,`--owner`,w,`--name`,E,`--json`]),S=parseNameCheckEvent(pickTerminalJsonLine(e));emitSharePublishLog(`name-check`,S.ok?`ok`:S.error,S.ok?{available:S.available}:void 0),successResponse(t,200,SharePublishNameCheckResponseSchema,S,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG,cause:e})}finally{Ce.release(SHARE_PUBLISH_NAME_CHECK_KEY)}},{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG,method:`GET`,skipBodyParse:!0,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG})}),Dl=withValidation(SharePublishRequestSchema,async(e,t,S)=>{if(!de){emitSharePublishLog(`publish-create`,`no-project`),successResponse(t,200,SharePublishResponseSchema,{ok:!1,error:`no-project`},{handler:SHARE_PUBLISH_HANDLER_TAG});return}if(!isValidShareOwnerName(S.owner)||!isValidShareRepoName(S.name)){errorResponse(t,400,`urn:ok:error:invalid-request`,`owner and name must be valid GitHub identifiers.`,{handler:SHARE_PUBLISH_HANDLER_TAG});return}if(!Ce.tryAcquire(`/api/share/publish`)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A share publish operation is already in progress.`,{handler:SHARE_PUBLISH_HANDLER_TAG,extraHeaders:{"Retry-After":`5`}});return}try{let e=[`share`,`publish`,`--owner`,S.owner,`--name`,S.name,`--visibility`,S.visibility,`--project-dir`,de,`--json`];S.description!==void 0&&S.description.length>0&&e.push(`--description`,S.description);let{stdout:w}=await Cl(e),E=parsePublishEvent(pickTerminalJsonLine(w));emitSharePublishLog(`publish-create`,E.ok?`ok`:E.error),successResponse(t,200,SharePublishResponseSchema,E,{handler:SHARE_PUBLISH_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:SHARE_PUBLISH_HANDLER_TAG,cause:e})}finally{Ce.release(SHARE_PUBLISH_KEY)}},{handler:SHARE_PUBLISH_HANDLER_TAG,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:SHARE_PUBLISH_HANDLER_TAG})}),Ol={"/api/asset":Xi,"/api/document":$t,"/api/documents":en,"/api/backlinks":jr,"/api/backlink-counts":Mr,"/api/forward-links":Fr,"/api/link-graph":Ir,"/api/dead-links":Br,"/api/orphans":Lr,"/api/hubs":zr,"/api/tags":Bc,"/api/pages":As,"/api/folder-config":Kc,"/api/template":Yc,"/api/search":ml,"/api/suggest-links":Ns,"/api/page-headings":Ts,"/api/create-page":xs,"/api/create-folder":Cs,"/api/rename-path":Ds,"/api/delete-path":Os,"/api/trash/cleanup":ks,"/api/upload":Ps,"/api/agent-write":Ut,"/api/agent-write-md":Wt,"/api/frontmatter-patch":Kt,"/api/agent-patch":Vr,"/api/agent-undo":Hr,"/api/agent-activity":Ur,"/api/agent-burst-diff":Wr,"/api/save-version":Jr,"/api/history":Yr,"/api/diff":Zr,"/api/rollback":Qr,"/api/metrics/reconciliation":ji,"/api/metrics/parse-health":Hi,"/api/metrics/agent-presence":Ki,"/api/server-info":Ui,"/api/share/construct-url":xl,"/api/share/publish/owners":Tl,"/api/share/publish/name-check":El,"/api/share/publish":Dl,"/api/principal":Gi,"/api/rescue":ka,"/api/workspace":Yi,"/api/sync/status":kc,"/api/sync/trigger":Ac,"/api/sync/conflicts":jc,"/api/sync/conflict-content":Nc,"/api/sync/resolve-conflict":Mc,"/api/sync/abort-merge":zc,"/api/local-op/clone":nc,"/api/local-op/open":oc,"/api/local-op/auth/login":pc,"/api/local-op/auth/status":gc,"/api/local-op/auth/repos":vc,"/api/local-op/auth/signout":xc,"/api/local-op/auth/pat":Cc,"/api/local-op/auth/identity":Tc,"/api/local-op/auth/set-identity":Oc,"/api/installed-agents":Rc,"/api/spawn-cursor":yl,"/api/handoff":vl,"/api/install-skill":Lc,"/api/skill/install-state":_l,"/api/seed/plan":Pc,"/api/seed/apply":Fc,"/api/seed/packs":Ic};F&&(Ol[`/api/test-reset`]=Gr,Ol[`/api/test-rescan-backlinks`]=Kr,Ol[`/api/test-rescan-files`]=qr);let kl=new Set([`/api/upload`,`/api/create-page`,`/api/create-folder`,`/api/rename-path`,`/api/delete-path`,`/api/trash/cleanup`,`/api/agent-write`,`/api/agent-write-md`,`/api/frontmatter-patch`,`/api/agent-patch`,`/api/agent-undo`,`/api/save-version`,`/api/rollback`,`/api/sync/trigger`,`/api/sync/resolve-conflict`,`/api/sync/abort-merge`,`/api/test-reset`,`/api/test-rescan-backlinks`,`/api/test-rescan-files`,`/api/install-skill`,`/api/folder-config`,`/api/template`,`/api/seed/apply`]),jl=[`/api/local-op/`];return{priority:100,async onRequest({request:e,response:t}){let S=e.url?.split(`?`)[0];if(!S)return;if(S.startsWith(`/api/`)){let S=e.headers.origin;if(S!==void 0&&!isAllowedApiOrigin(S)){errorResponse(t,403,`urn:ok:error:invalid-origin`,`Origin not allowed.`,{handler:`api-origin-gate`});return}if(typeof t.setHeader==`function`&&(S!==void 0&&(t.setHeader(`Access-Control-Allow-Origin`,S),t.setHeader(`Vary`,`Origin`)),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization, traceparent, tracestate, baggage`)),e.method===`OPTIONS`){t.writeHead(204),t.end();return}}if(kl.has(S)||jl.some(e=>S.startsWith(e))){let S=e.socket?.remoteAddress;if(S!==void 0&&!isLoopbackAddress(S)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback required.`,{handler:`api-mutating-gate`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`api-mutating-gate`});return}}if(!S.startsWith(`/api/`))return;let w=propagation.extract(context.active(),e.headers),E=e.method??`GET`,D=S;S.startsWith(`/api/rescue/`)?D=`/api/rescue/:docName`:S.startsWith(`/api/history/`)?D=`/api/history/:sha`:S.startsWith(`/api/tags/`)?D=`/api/tags/:name`:Ol[S]||(D=`/api/*`);let O=getTracer(),k=Date.now();await context.with(w,()=>O.startActiveSpan(`HTTP ${E} ${D}`,{kind:SpanKind.SERVER,attributes:{[ATTR_HTTP_REQUEST_METHOD]:E,[ATTR_HTTP_ROUTE]:D,[ATTR_URL_PATH]:S,[ATTR_URL_SCHEME]:`http`,[ATTR_USER_AGENT_ORIGINAL]:e.headers[`user-agent`]??``}},async w=>{try{let D=Ol[S],O=!1;if(D)O=!0,await D(e,t);else if(S.startsWith(`/api/rescue/`)){let w=decodeURIComponent(S.slice(12));w&&(O=!0,await _s(e,t,w))}else if(S.startsWith(`/api/history/`)){let w=decodeURIComponent(S.slice(13));w&&(O=!0,await Xr(e,t,w))}else if(S.startsWith(`/api/tags/`)){let w=S.slice(10);w&&(O=!0,await Vc(e,t,w))}O||errorResponse(t,404,`urn:ok:error:not-found`,`API endpoint not found.`,{handler:`api-dispatch`,detail:`No handler for ${E} ${S}`});let k=t.statusCode;w.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE,k),k>=500&&w.setStatus({code:SpanStatusCode.ERROR,message:`status ${k}`})}catch(e){throw w.recordException(e),w.setStatus({code:SpanStatusCode.ERROR,message:e instanceof Error?e.message:String(e)}),!t.headersSent&&!t.writableEnded&&!t.destroyed&&errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:D,cause:e}),e}finally{w.end();let e=(Date.now()-k)/1e3;httpDurationHist().record(e,{[ATTR_HTTP_REQUEST_METHOD]:E,[ATTR_HTTP_ROUTE]:D,[ATTR_HTTP_RESPONSE_STATUS_CODE]:t.statusCode})}}))}}}function isWithinDir(e,t){return e===t?!0:e.startsWith(`${t}${sep}`)}function errnoCode(e){let t=e?.code;return typeof t==`string`?t:void 0}function seedBasenameIndex(e){let t=e.contentDir,S=new Set;function w(E){let D;try{D=readdirSync(E,{withFileTypes:!0})}catch(t){let S=errnoCode(t);S!==`ENOENT`&&e.onSkip?.(`read-failed`,S,E);return}for(let O of D){let D=join(E,O.name),k=relative(t,D);if(k.startsWith(`..`)||e.contentFilter?.isDirExcluded(k)&&O.isDirectory())continue;let j;try{j=lstatSync(D)}catch(t){let S=errnoCode(t);S!==`ENOENT`&&e.onSkip?.(`lstat-failed`,S,D);continue}if(j.isSymbolicLink()){let E;try{E=realpathSync(D)}catch(t){let S=errnoCode(t);S!==`ENOENT`&&e.onSkip?.(`realpath-failed`,S,D);continue}if(!isWithinDir(E,t)){e.onSkip?.(`symlink-escape`,void 0,D);continue}let O;try{O=statSync(E)}catch(t){let S=errnoCode(t);S!==`ENOENT`&&e.onSkip?.(`symlink-stat-failed`,S,E);continue}if(S.has(O.ino))continue;S.add(O.ino),O.isDirectory()?w(E):O.isFile()&&isSupportedAssetFile(D,ASSET_EXTENSIONS)&&!e.contentFilter?.isExcluded(k)&&e.basenameIndex.add(k);continue}if(j.isDirectory()){if(S.has(j.ino))continue;S.add(j.ino),w(D);continue}j.isFile()&&isSupportedAssetFile(D,ASSET_EXTENSIONS)&&!e.contentFilter?.isExcluded(k)&&e.basenameIndex.add(k)}}w(t)}const HocuspocusAuthTokenSchema=object$1({principalId:string$2().optional(),tabSessionId:string$2().optional(),expectedServerInstanceId:string$2().optional(),expectedBranch:string$2().optional()}).loose(),HOCUSPOCUS_AUTH_REJECTION_REASONS=[`server-instance-mismatch`,`branch-mismatch`,`rename-redirect`,`doc-deleted`];function isHocuspocusAuthRejectionReason(e){return HOCUSPOCUS_AUTH_REJECTION_REASONS.includes(e)}const WIRE_PAYLOAD_SEPARATOR=`:`;function formatAuthRejectionWire(e,t){return typeof t!=`string`||t.length===0?e:`${e}${WIRE_PAYLOAD_SEPARATOR}${t}`}function parseAuthRejectionWire(e){if(e.length===0)return{kind:null,payload:void 0};let t=e.indexOf(WIRE_PAYLOAD_SEPARATOR),S=t===-1?e:e.slice(0,t);if(!isHocuspocusAuthRejectionReason(S))return{kind:null,payload:void 0};if(t===-1)return{kind:S,payload:void 0};let w=e.slice(t+1);return{kind:S,payload:w.length>0?w:void 0}}var HocuspocusAuthRejection=class extends Error{kind;payload;reason;constructor(e,t,S){super(t),this.name=`HocuspocusAuthRejection`,this.kind=e,this.payload=typeof S==`string`&&S.length>0?S:void 0,this.reason=formatAuthRejectionWire(e,this.payload)}};function parseHocuspocusAuthToken(e){if(typeof e!=`string`||e.length===0)return;let t;try{t=JSON.parse(e)}catch{return}let S=HocuspocusAuthTokenSchema.safeParse(t);return S.success?S.data:void 0}const DEFAULT_WARN_BEFORE_MS=300*1e3;function attachIdleShutdown(e){let t=e.scheduler??defaultScheduler,S=e.warnBeforeMs??DEFAULT_WARN_BEFORE_MS,w=0,E=null,D=null,O=!1,k=!1;function j(){E!==null&&(t.clearTimeout(E),E=null),D!==null&&(t.clearTimeout(D),D=null)}function F(){j(),!(k||O)&&w===0&&(S>0&&S<e.thresholdMs&&(D=t.setTimeout(()=>{D=null,w===0&&!O&&e.log?.warn({msUntilShutdown:S,webSocketClientCount:0},`idle shutdown pending: no WebSocket clients`)},e.thresholdMs-S)),E=t.setTimeout(()=>{if(E=null,!(k||O)&&w===0){O=!0,e.log?.info({webSocketClientCount:0},`idle shutdown firing`);try{let t=e.onShutdown();t&&typeof t.then==`function`&&t.catch(t=>{e.log?.error({err:t},`idle shutdown handler rejected`)})}catch(t){e.log?.error({err:t},`idle shutdown handler threw`)}}},e.thresholdMs))}let L=(e,t)=>{e.url?.startsWith(`/collab`)&&(w++,j(),t.once(`close`,()=>{w--,w<0&&(w=0),w===0&&F()}))};return e.httpServer.on(`upgrade`,L),F(),{detach:()=>{k||(k=!0,e.httpServer.off(`upgrade`,L),j())}}}const MCP_SERVER_NAME=`open-knowledge`,MCP_CONNECTION_ID_HEADER=`x-ok-connection-id`;function sanitizeClientName(e,t){let S=Array.from(e??``).map(e=>{let t=e.charCodeAt(0);return t<=31||t===127?` `:e}).join(``).replace(/\s+/g,` `).trim();return S?S.slice(0,128):t}function buildInstructions(e){return'Open Knowledge is a markdown-CRDT knowledge base exposed via MCP.\n\n## STOP — native tools on in-scope `.md` / `.mdx`\n\nWhen this workspace has Open Knowledge MCP configured, do **not** use your host\'s native file tools on markdown paths inside the content directory. The ban covers every common rationalization:\n\n- **Native `Read` / `Grep` / `Glob` on in-scope `.md` / `.mdx`** — the original case.\n- **`Bash ls` / `Bash find` / `Bash cat` on dirs containing in-scope markdown** — use `exec("ls -A …")` / `exec("find … -name \'*.md\'")` / `exec("cat …")` instead. Native returns bare names; `exec` returns frontmatter, backlink counts, and recent activity per child. `-A` shows hidden entries (`.ok/`, `.okignore`) which OK projects carry; omit `.` and `..` rows that `-a` would add.\n- **Glob patterns that target markdown** (`**/*.md`, any dir known to be markdown-heavy like `specs/**`, `reports/**`, `docs/**`) — use `exec` with `find`, or `list_documents({ dir })`.\n- **Dispatching the Explore / general-purpose subagent for markdown-heavy exploration** — subagents use native `Read` / `Grep` / `Glob` internally and bypass Open Knowledge entirely. Do markdown exploration yourself via `exec` / `search` / `grep`. Subagents remain appropriate for **source-code** exploration.\n- **Native `Read` / `Grep` on any in-scope markdown inside `.ok/`** — the `.ok/` directory is in-scope; if it carries `.md` / `.mdx`, treat those the same as any other knowledge-base file.\n\nWhy: native tools skip frontmatter, backlinks, shadow-repo activity, and project git history that OK\'s tools return for every matched knowledge-base file. `exec` is the primary read surface; it runs read-only bash (`cat`, `ls`, `grep`, `find`, `head`, `tail`, `wc`, `sort`, `uniq`, `cut` — pipes OK) and returns raw stdout plus enriched metadata per file.\n\n**MCP tool visibility — not seeing `exec` is NOT the escape hatch.** MCP wiring varies by client. Claude Code, Cursor, Codex, Windsurf, VS Code — each surfaces MCP differently. Server labels are user-defined; tools may not appear as top-level symbols named `exec` in your specific UI. If Open Knowledge is registered as an MCP server in this workspace, route markdown reads through its `exec` / `search` / `grep` / `read_document` via your client\'s documented MCP invocation (including any generic "call MCP tool" flow). Registration is the test, not top-level-symbol visibility.\n\n**Escape hatch.** Native `Read` / `Grep` / `Glob` on `.md` / `.mdx` is allowed **only** when no Open Knowledge MCP server is registered for this project, **or** immediately after you tried an MCP call and it failed — then begin a user-visible sentence with `Open Knowledge MCP unavailable:`. Never use the hatch because you skipped your client\'s MCP path, didn\'t see `exec` as a top-level tool, or rationalized the skill wasn\'t necessary.\n\n**Source code and non-markdown files** (`.ts`, `.py`, `package.json`, …): native `Read` / `Grep` / `Glob` always.\n\n## Reads — examples\n\n- Read a file: `exec("cat <path>.md")` — contents + full rich enrichment\n- List a directory: `exec("ls -A <dir>")` — per-child frontmatter, recursive markdown counts, most-recently-updated doc per subdir. Prefer `-A` over plain `ls`: OK projects carry dot-prefixed entries (`.ok/`, nested `.ok/`, `.okignore`) that plain `ls` omits. `-A` shows hidden entries without the noisy `.`/`..` rows that `-a` adds, and without the verbose long-format columns that `-la` adds (the per-child enrichment already carries the useful metadata `-l` would surface).\n- Search: `exec("grep -rn <term> <dir> | head -5")` — matches + enrichment on matched files\n- Typed tools (`read_document`, `search`, `grep`, `list_documents`) remain available — prefer them when a structured `structuredContent` shape is useful (e.g., passing results to another tool). For interactive reads, `exec` is lighter. **Pick the right search:** `search` for ranked retrieval (cmd-K parity — title boost + body BM25 + recency); `grep` for every literal-string occurrence grouped by file with frontmatter enrichment.\n\n## Preview — open the browser at session start\n\n**Open the preview browser as your first OK action of the session, if it is not already open.** The user watches edits land live in that pane; if it isn\'t open, your work is invisible and the whole CRDT pipeline is wasted. Treat this as step zero — before your first read, before your first write.\n\n- Claude Code Desktop: `preview_start("open-knowledge-ui")`.\n- Cursor: use the host\'s open-URL tool with a `previewUrl` from any write response.\n- Other hosts: use whatever command opens a URL (macOS: `open <url>`). On hosts with no preview tool (Codex, generic stdio), surface the URL in chat for the user to click.\n\n**How to know if it\'s already open.** You usually can\'t pre-check from the agent side — rely on these signals:\n\n1. You already opened it earlier in this session → don\'t reopen.\n2. A `write_document` / `edit_document` response returns `previewUrl` but NO `warning: { action: "attach-preview-once" }` → a browser is attached somewhere; do nothing.\n3. A response DOES include `warning: { action: "attach-preview-once", previewUrl, message }` → no browser is attached; open immediately, one-shot. The hint fires only when needed (server tracks `__system__` subscribers) and at most once per session in the normal fresh-start case.\n\nIf the server isn\'t running, you\'ll see a `"Hocuspocus server is not running"` error or `previewUrl: null`. Start the UI (`open-knowledge ui` from a terminal, or `preview_start("open-knowledge-ui")` in Claude Code), then retry. NEVER construct preview URLs by hand — always use the `previewUrl` returned in tool responses.\n\n**No screenshots after edits.** Do NOT take `preview_screenshot` after every `edit_document` / `write_document`. Trust the CRDT tool response as confirmation the edit landed. Only screenshot when debugging a visual issue or when explicitly asked.\n\n## Scope recap\n\nOpen Knowledge looks for documents under the resolved `content.dir` (discoverable at runtime via `get_config({ path: [\'content\', \'dir\'] })`). `.gitignore` and `.okignore` (at the project root and at any folder depth) define exclusions. Folder defaults + templates live in nested `<folder>/.ok/frontmatter.yml` + `<folder>/.ok/templates/` files — NOT in `.ok/config.yml`.\n\nDefault mental model (no jargon): **every `.md` and `.mdx` under `content.dir`** not excluded by `.gitignore` or `.okignore` is an Open Knowledge document — including under `specs/`, `reports/`, `docs/`, etc. Read `.okignore` (and any nested `.okignore` files) once per turn to know what\'s excluded.\n\n**First session in this project?** If `frontmatter_defaults` and `templates_available` are empty for substantial folders, the project hasn\'t been onboarded yet — invoke `discover` (Workflow tools table) before writing. Once onboarded, the cascade carries the discipline.\n\n\nFull guidance lives in the bundled `open-knowledge` skill at `~/.ok/skills/open-knowledge/SKILL.md`.\n'}function installPrettyZodErrors(e){let t=e;if(t.__prettyZodErrorsInstalled===!0)return;let S=t.validateToolInput;if(typeof S!=`function`){console.warn(`[pretty-zod-errors] McpServer.validateToolInput not found — SDK internals may have changed. Falling back to default error formatting.`);return}t.validateToolInput=async function(e,t,w){if(!e.inputSchema||!isZodSchema(e.inputSchema))return S.call(this,e,t,w);let E=await e.inputSchema.safeParseAsync(t);if(E.success)return E.data;let D=prettifyError(E.error);throw new McpError(ErrorCode.InvalidParams,`Input validation error: Invalid arguments for tool ${w}:\n${D}`)},t.__prettyZodErrorsInstalled=!0}function isZodSchema(e){return typeof e!=`object`||!e?!1:typeof e.safeParseAsync==`function`}const loggerContext=new AsyncLocalStorage;var McpLogger=class e{sessionId;corrId;component;constructor(e=`mcp`,t){this.sessionId=t??randomUUID().slice(0,12),this.corrId=randomUUID().slice(0,8),this.component=e}info(e,t={}){this.emit(`info`,e,t)}warn(e,t={}){this.emit(`warn`,e,t)}error(e,t,S={}){let w=t?{error:t instanceof Error?t.message:String(t),...S}:S;this.emit(`error`,e,w)}debug(e,t={}){(process.env.MCP_DEBUG===`1`||process.env.DEBUG?.includes(`mcp`))&&this.emit(`debug`,e,t)}child(t){return new e(t??this.component,this.sessionId)}asCallback(){return e=>this.info(e)}emit(e,t,S){let w={ts:new Date().toISOString(),level:e,sessionId:this.sessionId,corrId:this.corrId,component:this.component,msg:t,...S},E=`${JSON.stringify(w)}\n`;process.stderr.write(E);let D=process.env.OK_LOG_FILE;if(D)try{appendFileSync(D,E)}catch(e){console.warn(`[mcp-logger] Failed to write to OK_LOG_FILE: ${e instanceof Error?e.message:e}`)}}};function runWithMcpLogger(e,t){return loggerContext.run(e,t)}function getCurrentMcpLogger(){return loggerContext.getStore()}const REDACTED_STRING_KEYS=new Set([`find`,`markdown`,`replace`]),COMMON_ARRAY_KEYS=[`backlinks`,`deadLinks`,`documents`,`enrichedPaths`,`entries`,`forwardLinks`,`hints`,`hubs`,`orphans`,`results`],COMMON_SCALAR_KEYS=[`checkpointRef`,`cwd`,`fileCount`,`matchCount`,`ok`,`query`,`stdoutTruncated`,`truncated`];function isPlainObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function isToolExtraLike(e){return isPlainObject(e)&&`requestId`in e}function summarizeStringForLog(e,t){if(REDACTED_STRING_KEYS.has(e))return{redacted:!0,type:`string`,length:t.length,lines:t.length===0?0:t.split(`
|
|
2113
|
+
`).map(e=>e.trim()).filter(Boolean),k=null;for(let e=O.length-1;e>=0;e--)try{k=JSON.parse(O[e]);break}catch{}k===null?successResponse(t,200,LocalOpAuthPatSuccessSchema,{},{handler:Sc}):successResponse(t,200,LocalOpAuthPatSuccessSchema,k,{handler:Sc})}catch(e){errorResponse(t,500,`urn:ok:error:auth-failed`,`Auth pat failed.`,{handler:Sc,cause:e})}finally{Ce.release(dc)}},{handler:Sc,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:Sc})}),wc=`local-op-auth-identity`;async function Tc(e,t){if(checkLocalOpSecurity(e,t,{handler:wc})){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:wc,extraHeaders:{Allow:`GET`}});return}if(!de){errorResponse(t,503,`urn:ok:error:no-project-dir`,`No project directory configured.`,{handler:wc});return}try{successResponse(t,200,LocalOpAuthIdentitySuccessSchema,{identity:await resolveGitIdentity(de)},{handler:wc})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Identity resolution failed.`,{handler:wc,cause:e})}}}let Ec=`/api/local-op/auth/set-identity`,Dc=`local-op-auth-set-identity`,Oc=withValidation(LocalOpAuthSetIdentityRequestSchema,async(e,t,S)=>{let w=S.name.trim(),E=S.email.trim();if(!de){errorResponse(t,503,`urn:ok:error:no-project-dir`,`No project directory configured.`,{handler:Dc});return}if(!Ce.tryAcquire(Ec)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A set-identity operation is already in progress.`,{handler:Dc,extraHeaders:{"Retry-After":`5`}});return}try{writeGitIdentity(de,w,E),ce?.()?.refreshIdentity().catch(()=>{}),successResponse(t,200,LocalOpAuthEmptySuccessSchema,{},{handler:Dc})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Set-identity failed.`,{handler:Dc,cause:e})}finally{Ce.release(Ec)}},{handler:Dc,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:Dc})});async function kc(e,t){if(checkLocalOpSecurity(e,t,{handler:`sync-status`})){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`sync-status`,extraHeaders:{Allow:`GET`}});return}try{let e=ce?.();if(!e){successResponse(t,200,SyncStatusSchema,{state:`dormant`,lastSyncUtc:null,lastFetchUtc:null,lastPushedSha:null,ahead:0,behind:0,consecutiveFailures:0,conflictCount:0,hasRemote:!1,syncEnabled:!1,identityUnresolved:!1},{handler:`sync-status`});return}await e.refreshRemote(),successResponse(t,200,SyncStatusSchema,e.getStatus(),{handler:`sync-status`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`sync-status`,cause:e})}}}let Ac=withValidation(SyncTriggerRequestSchema,async(e,t,S)=>{let w=ce?.();if(!w){errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-trigger`});return}let E=S.op??`sync`;successResponse(t,202,SyncTriggerSuccessSchema,{op:E},{handler:`sync-trigger`}),w.trigger(E)},{handler:`sync-trigger`,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`sync-trigger`})?ce?.()?!0:(errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-trigger`}),!1):!1});async function jc(e,t){if(checkLocalOpSecurity(e,t,{handler:`sync-conflicts`})){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`sync-conflicts`,extraHeaders:{Allow:`GET`}});return}try{let e=ce?.();successResponse(t,200,SyncConflictsSuccessSchema,{conflicts:e?e.getConflicts():[]},{handler:`sync-conflicts`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`sync-conflicts`,cause:e})}}}let Mc=withValidation(SyncResolveConflictRequestSchema,async(e,t,S)=>{let w=ce?.();if(!w){errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-resolve-conflict`});return}let{file:E,strategy:D,content:O}=S;try{await w.resolveConflict(E,D,O),successResponse(t,200,SyncResolveConflictSuccessSchema,{},{handler:`sync-resolve-conflict`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to resolve conflict.`,{handler:`sync-resolve-conflict`,cause:e})}},{handler:`sync-resolve-conflict`,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`sync-resolve-conflict`})?ce?.()?!0:(errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-resolve-conflict`}),!1):!1});async function Nc(e,t){if(!checkLocalOpSecurity(e,t,{handler:`sync-conflict-content`}))return;if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`sync-conflict-content`,extraHeaders:{Allow:`GET`}});return}if(!de){errorResponse(t,503,`urn:ok:error:project-repo-not-configured`,`Project repo not configured.`,{handler:`sync-conflict-content`});return}let S=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`).searchParams.get(`file`);if(!S){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing required query param: file.`,{handler:`sync-conflict-content`});return}if(S.includes(`..`)||S.startsWith(`/`)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid file path.`,{handler:`sync-conflict-content`});return}let w=esm_default({baseDir:de,timeout:{block:15e3}});async function E(e){try{return await w.raw([`show`,`:${e}:${S}`])}catch{return``}}try{let[e,w,D]=await Promise.all([E(1),E(2),E(3)]);successResponse(t,200,SyncConflictContentSuccessSchema,{file:S,base:e,ours:w,theirs:D},{handler:`sync-conflict-content`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read conflict content.`,{handler:`sync-conflict-content`,cause:e})}}async function Pc(e,t){if(!checkLocalOpSecurity(e,t,{handler:`seed-plan`}))return;if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`seed-plan`,extraHeaders:{Allow:`GET`}});return}let S=new URL(e.url??`/`,`http://localhost`),E=S.searchParams.get(`rootDir`)??void 0,D=S.searchParams.get(`packId`),O=coercePackId(D);if(D!==null&&D!==``&&O===void 0){errorResponse(t,400,`urn:ok:error:invalid-request`,`Unknown packId.`,{handler:`seed-plan`,detail:`Pack id "${D}" is not registered.`});return}try{successResponse(t,200,SeedPlanSuccessSchema,{plan:await planSeed({projectDir:w,rootDir:E,packId:O})},{handler:`seed-plan`})}catch(e){if(e instanceof SeedPrerequisiteError){errorResponse(t,422,`urn:ok:error:seed-prerequisite-missing`,`Seed prerequisite missing.`,{handler:`seed-plan`,cause:e});return}if(e instanceof SeedRootDirError){errorResponse(t,400,`urn:ok:error:seed-invalid-root`,`Invalid seed root directory.`,{handler:`seed-plan`,detail:`The provided root directory is not within the workspace content directory.`,cause:e});return}errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`seed-plan`,cause:e})}}let Fc=withValidation(SeedApplyRequestSchema,async(e,t,S)=>{let E=S.plan;if(!E||typeof E!=`object`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid plan payload.`,{handler:`seed-apply`});return}let D=E,O=S.packId,k=coercePackId(O);if(typeof O==`string`&&O.length>0&&k===void 0){errorResponse(t,400,`urn:ok:error:invalid-request`,`Unknown packId.`,{handler:`seed-apply`,detail:`Pack id "${O}" is not registered.`});return}try{successResponse(t,200,SeedApplySuccessSchema,{result:await applySeed(D,{projectDir:w,packId:k})},{handler:`seed-apply`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to apply seed plan.`,{handler:`seed-apply`,cause:e})}},{handler:`seed-apply`,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`seed-apply`})});async function Ic(e,t){if(checkLocalOpSecurity(e,t,{handler:`seed-packs`})){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`seed-packs`,extraHeaders:{Allow:`GET`}});return}successResponse(t,200,SeedListPacksSuccessSchema,{packs:listStarterPacks()},{handler:`seed-packs`})}}let Lc=withValidation(InstallSkillRequestSchema,async(e,t,S)=>{if(S.out!==void 0&&!isSafeLocalPath(S.out)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Output path must be within home directory.`,{handler:`install-skill`});return}try{successResponse(t,200,InstallSkillSuccessSchema,await buildAndOpenSkill({...S.noOpen===void 0?{}:{noOpen:S.noOpen},...S.out===void 0?{}:{out:S.out}}),{handler:`install-skill`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to install skill.`,{handler:`install-skill`,cause:e})}},{handler:`install-skill`,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`install-skill`})});async function Rc(e,t){if(checkLocalOpSecurity(e,t,{handler:`installed-agents`}))try{await handleInstalledAgents(e,t,Re.probeAll)}catch(e){t.headersSent||(log$2.error({err:e},`[installed-agents] route wrapper failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`installed-agents`,cause:e}))}}async function zc(e,t){if(!checkLocalOpSecurity(e,t,{handler:`sync-abort-merge`}))return;if(e.method!==`POST`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`sync-abort-merge`,extraHeaders:{Allow:`POST`}});return}let S=ce?.();if(!S){errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-abort-merge`});return}try{await S.abortMerge(),successResponse(t,200,SyncAbortMergeSuccessSchema,{},{handler:`sync-abort-merge`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to abort merge.`,{handler:`sync-abort-merge`,cause:e})}}let Bc=withValidation(EmptyRequestSchema,async(e,t)=>{if(!te){errorResponse(t,503,`urn:ok:error:tag-index-not-configured`,`Tag index not configured.`,{handler:`tags-list`});return}try{successResponse(t,200,TagsListSuccessSchema,{tags:te.getAllTags()},{handler:`tags-list`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read tags.`,{handler:`tags-list`,cause:e})}},{handler:`tags-list`,method:`GET`,skipBodyParse:!0});async function Vc(e,t,S){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`tags-for-name`,extraHeaders:{Allow:`GET`}});return}if(!te){errorResponse(t,503,`urn:ok:error:tag-index-not-configured`,`Tag index not configured.`,{handler:`tags-for-name`});return}let w;try{w=decodeURIComponent(S)}catch{errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid tag name encoding.`,{handler:`tags-for-name`});return}if(!w){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing tag name.`,{handler:`tags-for-name`});return}try{let e=te.getDocsForTagWithMatches(w).map(({docName:e,matchingTags:t})=>({docName:e,title:Be(e),matchingTags:t,snippet:null}));successResponse(t,200,TagsForNameSuccessSchema,{name:w,docs:e},{handler:`tags-for-name`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read tag membership.`,{handler:`tags-for-name`,cause:e})}}function Hc(e,t,S=`path`,E=`folder-config`){let D=e.replace(/^\.\//,``).replace(/^\/+/,``).replace(/\/+$/,``);if(D.split(`/`).some(e=>e===`..`)||e.startsWith(`/`))return errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid ${S}: must be project-root-relative.`,{handler:E}),null;let O=resolve(w),k=D===``?O:resolve(O,D);return k!==O&&!k.startsWith(`${O}${sep}`)?(errorResponse(t,400,`urn:ok:error:invalid-request`,`Path escapes content directory.`,{handler:E}),null):{folderRel:D,resolvedContentDir:O}}let Uc=/^[A-Za-z0-9_-]+$/;function Wc(e,t,S=`template`){return!e||!Uc.test(e)?(errorResponse(t,400,`urn:ok:error:invalid-request`,"Invalid name: must be letters / digits / `_` / `-` only (no `.md` extension).",{handler:S}),!1):!0}function Gc(e){let t={};if(!e||typeof e!=`object`||Array.isArray(e))return t;for(let[S,w]of Object.entries(e))w!==void 0&&(t[S]=w);return t}async function Kc(e,t){if(e.method===`GET`)return qc(e,t);if(e.method===`PUT`)return Jc(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`folder-config`,extraHeaders:{Allow:`GET, PUT`}})}let qc=withValidation(EmptyRequestSchema,async(e,t)=>{try{let S=Hc(new URL(e.url??``,`http://localhost`).searchParams.get(`path`)??``,t,`path`,`folder-config-get`);if(!S)return;let w=await enrichDirectory(S.folderRel,{projectDir:S.resolvedContentDir}),E=resolve(S.resolvedContentDir,S.folderRel,`.ok`,`frontmatter.yml`),D=null;if(existsSync(E))try{let e=(0,import_dist$1.parse)(await readFile$1(E,`utf-8`));D=e&&typeof e==`object`&&!Array.isArray(e)?e:{}}catch(e){let t=e instanceof Error?e.message:String(e);console.warn(`[folder-config:get] malformed YAML in ${E}: ${t}`),D=null}successResponse(t,200,FolderConfigGetSuccessSchema,{folder:w,frontmatter_local:D},{handler:`folder-config-get`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read folder config.`,{handler:`folder-config-get`,cause:e})}},{handler:`folder-config-get`,method:`GET`,skipBodyParse:!0}),Jc=withValidation(FolderConfigPutRequestSchema,async(e,t,S)=>{try{let e=Hc(S.path,t,`path`,`folder-config-put`);if(!e)return;let w=e.folderRel===``?`**`:`${e.folderRel}/**`,E=applyNestedFolderRulesUpsert({projectDir:e.resolvedContentDir,rules:[{match:w,frontmatter:Gc(S.frontmatter)}]});if(!E.ok){let e=E.error.code===`WRITE_ERROR`||E.error.code===`BAD_PROJECT_DIR`?500:400;errorResponse(t,e,e===500?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,e===500?`Failed to write folder config.`:`Invalid folder config request.`,{handler:`folder-config-put`,detail:E.error.code,cause:Error(E.error.message)});return}successResponse(t,200,FolderConfigPutSuccessSchema,{applied:E.applied},{handler:`folder-config-put`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to write folder config.`,{handler:`folder-config-put`,cause:e})}},{handler:`folder-config-put`,method:`PUT`});async function Yc(e,t){if(e.method===`GET`)return Qc(e,t);if(e.method===`PUT`)return $c(e,t);if(e.method===`DELETE`)return nl(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`template`,extraHeaders:{Allow:`GET, PUT, DELETE`}})}let Xc=/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/,Zc=e=>{let t=e.match(Xc),S={},w=e;if(t){try{let e=(0,import_dist$1.parse)(t[1]??``);e&&typeof e==`object`&&!Array.isArray(e)&&(S=e)}catch{}w=e.slice(t[0].length)}return{frontmatter:S,body:w}},Qc=withValidation(EmptyRequestSchema,async(e,t)=>{try{let S=new URL(e.url??``,`http://localhost`),w=S.searchParams.get(`name`)??``;if(!Wc(w,t,`template-get`))return;let E=Hc(S.searchParams.get(`folder`)??``,t,`folder`,`template-get`);if(!E)return;let{folderRel:D,resolvedContentDir:O}=E,k=D===``?[]:D.split(`/`),j=null,F=null,L=null;for(let e=k.length;e>=0;e--){let t=e===0?``:k.slice(0,e).join(`/`),S=t===``?O:resolve(O,t);if(S!==O&&!S.startsWith(`${O}${sep}`))continue;let E=resolve(S,`.ok`,`templates`,`${w}.md`);if(existsSync(E)){j=E,F=t,L=e===k.length?`local`:`inherited`;break}}if(!j||F===null||L===null){errorResponse(t,404,`urn:ok:error:template-not-found`,`Template not found.`,{handler:`template-get`,detail:`Template "${w}" not found for folder "${D||`.`}". Walked leaf → root.`});return}let{frontmatter:B,body:H}=Zc(await readFile$1(j,`utf-8`)),q=relative(O,j).split(/[\\/]/).filter(Boolean).join(`/`);successResponse(t,200,TemplateGetSuccessSchema,{template:{name:w,folder:F,scope:L,path:q,frontmatter:B,body:H}},{handler:`template-get`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read template.`,{handler:`template-get`,cause:e})}},{handler:`template-get`,method:`GET`,skipBodyParse:!0}),$c=withValidation(TemplatePutRequestSchema,async(e,t,S)=>{try{let e=S.name;if(!Wc(e,t,`template-put`))return;let w=Hc(S.folder,t,`folder`,`template-put`);if(!w)return;let E=applyTemplateWrite({projectDir:w.resolvedContentDir,folder:w.folderRel,name:e,body:typeof S.body==`string`?S.body:``,frontmatter:Gc(S.frontmatter)});if(!E.ok){let e=E.error.code===`WRITE_ERROR`||E.error.code===`BAD_PROJECT_DIR`?500:400;errorResponse(t,e,e===500?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,e===500?`Failed to write template.`:`Invalid template request.`,{handler:`template-put`,detail:E.error.code,cause:Error(E.error.message)});return}successResponse(t,200,TemplatePutSuccessSchema,{path:E.path,created:E.created,warnings:E.warnings},{handler:`template-put`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to write template.`,{handler:`template-put`,cause:e})}},{handler:`template-put`,method:`PUT`}),nl=withValidation(EmptyRequestSchema,async(e,t)=>{try{let S=new URL(e.url??``,`http://localhost`),w=S.searchParams.get(`name`)??``;if(!Wc(w,t,`template-delete`))return;let E=Hc(S.searchParams.get(`folder`)??``,t,`folder`,`template-delete`);if(!E)return;let D=applyTemplateDelete({projectDir:E.resolvedContentDir,folder:E.folderRel,name:w});if(!D.ok){let e=D.error.code===`WRITE_ERROR`||D.error.code===`UNLINK_FAILED`||D.error.code===`BAD_PROJECT_DIR`?500:400;errorResponse(t,e,e===500?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,e===500?`Failed to delete template.`:`Invalid template request.`,{handler:`template-delete`,detail:D.error.code,cause:Error(D.error.message)});return}successResponse(t,200,TemplateDeleteSuccessSchema,{existed:D.existed,path:D.path},{handler:`template-delete`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to delete template.`,{handler:`template-delete`,cause:e})}},{handler:`template-delete`,method:`DELETE`,skipBodyParse:!0});function il(e){let t=new Map;for(let S of e){let e=S.path.split(`/`).filter(Boolean);e.pop();for(let w=1;w<=e.length;w++){let E=e.slice(0,w).join(`/`);t.set(E,Math.max(t.get(E)??0,S.modifiedTs))}}return[...t.entries()].map(([e,t])=>createWorkspaceSearchDocument({kind:`folder`,path:e,modifiedTs:t}))}function al(e,t){let S=t.trim().toLowerCase();if(!S||!e)return;let w=e.toLowerCase().indexOf(S);if(w<0)return;let E=Math.max(0,w-80),D=Math.min(e.length,w+S.length+120),O=E>0?`…`:``,k=D<e.length?`…`:``;return`${O}${e.slice(E,D).replace(/\s+/g,` `).trim()}${k}`}function cl(e){return e===`autocomplete`||e===`full_text`||e===`omnibar`?e:`omnibar`}function ll(e){let t=typeof e==`string`?e.split(`,`):Array.isArray(e)?e:void 0;if(!t)return;let S=t.filter(e=>e===`page`||e===`folder`||e===`content`);return S.length>0?S:void 0}async function ul(){let e=[];for(let[t,S]of D()){if(isSystemDoc(t)||isConfigDoc(t))continue;let w=``,E=t;try{w=await readFile$1(S.canonicalPath,`utf-8`),E=extractPageTitle(w,t)}catch(e){console.warn(`[search] Failed to index ${t}:`,e)}e.push(createWorkspaceSearchDocument({kind:`page`,path:t,title:E,content:w,modifiedTs:Date.parse(S.modified)}))}return[...e,...il(e)]}function dl(){return[...D()].filter(([e])=>!isSystemDoc(e)&&!isConfigDoc(e)).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>`${e}${t.modified}${t.size}${t.canonicalPath}${t.inode}${t.aliases.join(`,`)}`).join(``)}async function fl(){let e=`${w}${de??``}`,t=dl(),S=workspaceSearchCaches.get(e);if(S?.fingerprint===t&&S.corpus)return S.corpus;if(S?.fingerprint===t&&S.pending)return S.pending;let E=ul().then(e=>createWorkspaceSearchCorpus(e));workspaceSearchCaches.set(e,{fingerprint:t,pending:E});try{let S=await E;return workspaceSearchCaches.get(e)?.pending===E&&workspaceSearchCaches.set(e,{fingerprint:t,corpus:S}),S}catch(t){throw workspaceSearchCaches.get(e)?.pending===E&&workspaceSearchCaches.delete(e),t}}function pl(){if(process.env.NODE_ENV!==`test`)for(let e of[0,1e3,3e3])setTimeout(()=>{fl().catch(e=>{console.warn(`[search] Failed to prewarm workspace search cache:`,e)})},e)}pl();async function ml(e,t){if(e.method===`GET`)return hl(e,t);if(e.method===`POST`)return gl(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`search`,extraHeaders:{Allow:`GET, POST`}})}let hl=withValidation(EmptyRequestSchema,async(e,t)=>{let S=new URL(e.url??``,`http://localhost`),w=S.searchParams.get(`limit`),E=S.searchParams.get(`query`)??``,D=cl(S.searchParams.get(`intent`)),O=ll(S.searchParams.get(`scope`)??S.searchParams.get(`scopes`)),k=w===null?void 0:Number(w);if(E.length>200){errorResponse(t,400,`urn:ok:error:invalid-request`,`Query is too long (max 200 chars).`,{handler:`search-get`});return}try{let e=performance.now();successResponse(t,200,SearchSuccessSchema,{query:E,intent:D,results:searchWorkspaceCorpus(await fl(),E,{intent:D,scopes:O,limit:k}).map(e=>({kind:e.document.kind,path:e.document.path,title:e.document.title,score:e.score,signals:e.signals,snippet:e.document.kind===`page`?al(e.document.content,E):void 0})),elapsedMs:Math.max(0,performance.now()-e)},{handler:`search-get`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to search workspace.`,{handler:`search-get`,cause:e})}},{handler:`search-get`,method:`GET`,skipBodyParse:!0}),gl=withValidation(SearchRequestSchema,async(e,t,S)=>{let w=typeof S.query==`string`?S.query:``,E=cl(S.intent),D=ll(S.scopes??S.scope),O=typeof S.limit==`number`?S.limit:void 0;if(w.length>200){errorResponse(t,400,`urn:ok:error:invalid-request`,`Query is too long (max 200 chars).`,{handler:`search-post`});return}try{let e=performance.now();successResponse(t,200,SearchSuccessSchema,{query:w,intent:E,results:searchWorkspaceCorpus(await fl(),w,{intent:E,scopes:D,limit:O}).map(e=>({kind:e.document.kind,path:e.document.path,title:e.document.title,score:e.score,signals:e.signals,snippet:e.document.kind===`page`?al(e.document.content,w):void 0})),elapsedMs:Math.max(0,performance.now()-e)},{handler:`search-post`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to search workspace.`,{handler:`search-post`,cause:e})}},{handler:`search-post`,method:`POST`}),_l=withValidation(EmptyRequestSchema,async(e,t)=>{try{successResponse(t,200,SkillInstallStateSuccessSchema,{...await readSkillInstallStateSnapshot(homedir())},{handler:`skill-install-state`,extraHeaders:{"Cache-Control":`no-store`}})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read skill install state.`,{handler:`skill-install-state`,cause:e})}},{handler:`skill-install-state`,method:`GET`,skipBodyParse:!0,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`skill-install-state`})});async function vl(e,t){if(checkLocalOpSecurity(e,t,{handler:`handoff`}))try{await handleHandoffDispatch(e,t,{contentDir:w,platform:process.platform})}catch(e){t.headersSent||(log$2.error({err:e},`[handoff] route wrapper failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`handoff`,cause:e}))}}async function yl(e,t){if(checkLocalOpSecurity(e,t,{handler:`spawn-cursor`}))try{await handleSpawnCursor(e,t,{contentDir:w,platform:process.platform})}catch(e){t.headersSent||(log$2.error({err:e},`[spawn-cursor] route wrapper failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`spawn-cursor`,cause:e}))}}let xl=withValidation(ShareConstructUrlRequestSchema,async(e,t,S)=>{try{if(!de){emitShareConstructUrlLog(`no-remote`),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`no-remote`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}if(!isValidShareDocPath(S.docPath)){emitShareConstructUrlLog(`invalid-path`),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`invalid-path`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}let e=readGitHeadBranch(de);if(e===null){if(readOriginGitHubRepo(de).kind===`no-remote`){emitShareConstructUrlLog(`no-remote`),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`no-remote`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}emitShareConstructUrlLog(`detached-head`),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`detached-head`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}let w=readOriginGitHubRepo(de);if(w.kind===`no-remote`){emitShareConstructUrlLog(`no-remote`),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`no-remote`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}if(w.kind===`non-github`){emitShareConstructUrlLog(`non-github-remote`),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`non-github-remote`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}if(!branchExistsOnOrigin(de,e)){emitShareConstructUrlLog(`branch-not-on-origin`,!1),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`branch-not-on-origin`,branch:e},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}let E=buildGitHubBlobUrl(w.owner,w.repo,e,S.docPath),D=`${SHARE_BASE_URL}${encodeShareUrl(E)}`;emitShareConstructUrlLog(`ok`,!0),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!0,shareUrl:D,blobUrl:E,branch:e},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG,cause:e})}},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG})});async function Cl(e){let[t,...S]=ue,w=[...S,...e];return await new Promise((e,S)=>{let E=spawn(t,w,{stdio:[`ignore`,`pipe`,`pipe`],env:{...process.env}}),D=!1,O=setTimeout(()=>{D=!0,E.kill(`SIGTERM`)},SHARE_PUBLISH_TIMEOUT_MS),k=[],j=[];E.stdout.on(`data`,e=>k.push(e)),E.stderr.on(`data`,e=>j.push(e)),E.on(`close`,t=>{if(clearTimeout(O),D){S(Error(`share subprocess timed out after ${SHARE_PUBLISH_TIMEOUT_MS}ms`));return}let w=Buffer.concat(k).toString(`utf-8`);if(t!==0){let e=redactShareSubprocessStderr(Buffer.concat(j).toString(`utf-8`)).slice(0,500);console.warn(`[share] subprocess exited code=${t} stderr=${e}`)}e({stdout:w,code:t})}),E.on(`error`,e=>{clearTimeout(O),S(e)})})}let Tl=withValidation(EmptyRequestSchema,async(e,t)=>{if(!Ce.tryAcquire(`/api/share/publish/owners`)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A share owners operation is already in progress.`,{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG,extraHeaders:{"Retry-After":`5`}});return}try{let{stdout:e}=await Cl([`share`,`owners`,`--json`]),S=parseOwnersEvent(pickTerminalJsonLine(e));emitSharePublishLog(`owners-list`,S.ok?`ok`:S.error,S.ok?{count:S.owners.length}:void 0),successResponse(t,200,SharePublishOwnersResponseSchema,S,{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG,cause:e})}finally{Ce.release(SHARE_PUBLISH_OWNERS_KEY)}},{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG,method:`GET`,skipBodyParse:!0,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG})}),El=withValidation(EmptyRequestSchema,async(e,t)=>{let S=new URL(e.url??``,`http://localhost`),w=S.searchParams.get(`owner`)??``,E=S.searchParams.get(`name`)??``;if(!isValidShareOwnerName(w)||!isValidShareRepoName(E)){errorResponse(t,400,`urn:ok:error:invalid-request`,`owner and name query params must be valid GitHub identifiers.`,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG});return}if(!Ce.tryAcquire(`/api/share/publish/name-check`)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A share name-check operation is already in progress.`,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG,extraHeaders:{"Retry-After":`5`}});return}try{let{stdout:e}=await Cl([`share`,`name-check`,`--owner`,w,`--name`,E,`--json`]),S=parseNameCheckEvent(pickTerminalJsonLine(e));emitSharePublishLog(`name-check`,S.ok?`ok`:S.error,S.ok?{available:S.available}:void 0),successResponse(t,200,SharePublishNameCheckResponseSchema,S,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG,cause:e})}finally{Ce.release(SHARE_PUBLISH_NAME_CHECK_KEY)}},{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG,method:`GET`,skipBodyParse:!0,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG})}),Dl=withValidation(SharePublishRequestSchema,async(e,t,S)=>{if(!de){emitSharePublishLog(`publish-create`,`no-project`),successResponse(t,200,SharePublishResponseSchema,{ok:!1,error:`no-project`},{handler:SHARE_PUBLISH_HANDLER_TAG});return}if(!isValidShareOwnerName(S.owner)||!isValidShareRepoName(S.name)){errorResponse(t,400,`urn:ok:error:invalid-request`,`owner and name must be valid GitHub identifiers.`,{handler:SHARE_PUBLISH_HANDLER_TAG});return}if(!Ce.tryAcquire(`/api/share/publish`)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A share publish operation is already in progress.`,{handler:SHARE_PUBLISH_HANDLER_TAG,extraHeaders:{"Retry-After":`5`}});return}try{let e=[`share`,`publish`,`--owner`,S.owner,`--name`,S.name,`--visibility`,S.visibility,`--project-dir`,de,`--json`];S.description!==void 0&&S.description.length>0&&e.push(`--description`,S.description);let{stdout:w}=await Cl(e),E=parsePublishEvent(pickTerminalJsonLine(w));emitSharePublishLog(`publish-create`,E.ok?`ok`:E.error),successResponse(t,200,SharePublishResponseSchema,E,{handler:SHARE_PUBLISH_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:SHARE_PUBLISH_HANDLER_TAG,cause:e})}finally{Ce.release(SHARE_PUBLISH_KEY)}},{handler:SHARE_PUBLISH_HANDLER_TAG,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:SHARE_PUBLISH_HANDLER_TAG})}),Ol={"/api/asset":Xi,"/api/document":$t,"/api/documents":en,"/api/backlinks":jr,"/api/backlink-counts":Mr,"/api/forward-links":Fr,"/api/link-graph":Ir,"/api/dead-links":Br,"/api/orphans":Lr,"/api/hubs":zr,"/api/tags":Bc,"/api/pages":As,"/api/folder-config":Kc,"/api/template":Yc,"/api/search":ml,"/api/suggest-links":Ns,"/api/page-headings":Ts,"/api/create-page":xs,"/api/create-folder":Cs,"/api/rename-path":Ds,"/api/delete-path":Os,"/api/trash/cleanup":ks,"/api/upload":Ps,"/api/agent-write":Ut,"/api/agent-write-md":Wt,"/api/frontmatter-patch":Kt,"/api/agent-patch":Vr,"/api/agent-undo":Hr,"/api/agent-activity":Ur,"/api/agent-burst-diff":Wr,"/api/save-version":Jr,"/api/history":Yr,"/api/diff":Zr,"/api/rollback":Qr,"/api/metrics/reconciliation":ji,"/api/metrics/parse-health":Hi,"/api/metrics/agent-presence":Ki,"/api/server-info":Ui,"/api/share/construct-url":xl,"/api/share/publish/owners":Tl,"/api/share/publish/name-check":El,"/api/share/publish":Dl,"/api/principal":Gi,"/api/rescue":ka,"/api/workspace":Yi,"/api/sync/status":kc,"/api/sync/trigger":Ac,"/api/sync/conflicts":jc,"/api/sync/conflict-content":Nc,"/api/sync/resolve-conflict":Mc,"/api/sync/abort-merge":zc,"/api/local-op/clone":nc,"/api/local-op/open":oc,"/api/local-op/auth/login":pc,"/api/local-op/auth/status":gc,"/api/local-op/auth/repos":vc,"/api/local-op/auth/signout":xc,"/api/local-op/auth/pat":Cc,"/api/local-op/auth/identity":Tc,"/api/local-op/auth/set-identity":Oc,"/api/installed-agents":Rc,"/api/spawn-cursor":yl,"/api/handoff":vl,"/api/install-skill":Lc,"/api/skill/install-state":_l,"/api/seed/plan":Pc,"/api/seed/apply":Fc,"/api/seed/packs":Ic};F&&(Ol[`/api/test-reset`]=Gr,Ol[`/api/test-rescan-backlinks`]=Kr,Ol[`/api/test-rescan-files`]=qr);let kl=new Set([`/api/upload`,`/api/create-page`,`/api/create-folder`,`/api/rename-path`,`/api/delete-path`,`/api/trash/cleanup`,`/api/agent-write`,`/api/agent-write-md`,`/api/frontmatter-patch`,`/api/agent-patch`,`/api/agent-undo`,`/api/save-version`,`/api/rollback`,`/api/sync/trigger`,`/api/sync/resolve-conflict`,`/api/sync/abort-merge`,`/api/test-reset`,`/api/test-rescan-backlinks`,`/api/test-rescan-files`,`/api/install-skill`,`/api/folder-config`,`/api/template`,`/api/seed/apply`]),jl=[`/api/local-op/`];return{priority:100,async onRequest({request:e,response:t}){let S=e.url?.split(`?`)[0];if(!S)return;if(S.startsWith(`/api/`)){let S=e.headers.origin;if(S!==void 0&&!isAllowedApiOrigin(S)){errorResponse(t,403,`urn:ok:error:invalid-origin`,`Origin not allowed.`,{handler:`api-origin-gate`});return}if(typeof t.setHeader==`function`&&(S!==void 0&&(t.setHeader(`Access-Control-Allow-Origin`,S),t.setHeader(`Vary`,`Origin`)),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization, traceparent, tracestate, baggage`)),e.method===`OPTIONS`){t.writeHead(204),t.end();return}}if(kl.has(S)||jl.some(e=>S.startsWith(e))){let S=e.socket?.remoteAddress;if(S!==void 0&&!isLoopbackAddress(S)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback required.`,{handler:`api-mutating-gate`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`api-mutating-gate`});return}}if(!S.startsWith(`/api/`))return;let w=propagation.extract(context.active(),e.headers),E=e.method??`GET`,D=S;S.startsWith(`/api/rescue/`)?D=`/api/rescue/:docName`:S.startsWith(`/api/history/`)?D=`/api/history/:sha`:S.startsWith(`/api/tags/`)?D=`/api/tags/:name`:Ol[S]||(D=`/api/*`);let O=getTracer(),k=Date.now();await context.with(w,()=>O.startActiveSpan(`HTTP ${E} ${D}`,{kind:SpanKind.SERVER,attributes:{[ATTR_HTTP_REQUEST_METHOD]:E,[ATTR_HTTP_ROUTE]:D,[ATTR_URL_PATH]:S,[ATTR_URL_SCHEME]:`http`,[ATTR_USER_AGENT_ORIGINAL]:e.headers[`user-agent`]??``}},async w=>{try{let D=Ol[S],O=!1;if(D)O=!0,await D(e,t);else if(S.startsWith(`/api/rescue/`)){let w=decodeURIComponent(S.slice(12));w&&(O=!0,await _s(e,t,w))}else if(S.startsWith(`/api/history/`)){let w=decodeURIComponent(S.slice(13));w&&(O=!0,await Xr(e,t,w))}else if(S.startsWith(`/api/tags/`)){let w=S.slice(10);w&&(O=!0,await Vc(e,t,w))}O||errorResponse(t,404,`urn:ok:error:not-found`,`API endpoint not found.`,{handler:`api-dispatch`,detail:`No handler for ${E} ${S}`});let k=t.statusCode;w.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE,k),k>=500&&w.setStatus({code:SpanStatusCode.ERROR,message:`status ${k}`})}catch(e){throw w.recordException(e),w.setStatus({code:SpanStatusCode.ERROR,message:e instanceof Error?e.message:String(e)}),!t.headersSent&&!t.writableEnded&&!t.destroyed&&errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:D,cause:e}),e}finally{w.end();let e=(Date.now()-k)/1e3;httpDurationHist().record(e,{[ATTR_HTTP_REQUEST_METHOD]:E,[ATTR_HTTP_ROUTE]:D,[ATTR_HTTP_RESPONSE_STATUS_CODE]:t.statusCode})}}))}}}function isWithinDir(e,t){return e===t?!0:e.startsWith(`${t}${sep}`)}function errnoCode(e){let t=e?.code;return typeof t==`string`?t:void 0}function seedBasenameIndex(e){let t=e.contentDir,S=new Set;function w(E){let D;try{D=readdirSync(E,{withFileTypes:!0})}catch(t){let S=errnoCode(t);S!==`ENOENT`&&e.onSkip?.(`read-failed`,S,E);return}for(let O of D){let D=join(E,O.name),k=relative(t,D);if(k.startsWith(`..`)||e.contentFilter?.isDirExcluded(k)&&O.isDirectory())continue;let j;try{j=lstatSync(D)}catch(t){let S=errnoCode(t);S!==`ENOENT`&&e.onSkip?.(`lstat-failed`,S,D);continue}if(j.isSymbolicLink()){let E;try{E=realpathSync(D)}catch(t){let S=errnoCode(t);S!==`ENOENT`&&e.onSkip?.(`realpath-failed`,S,D);continue}if(!isWithinDir(E,t)){e.onSkip?.(`symlink-escape`,void 0,D);continue}let O;try{O=statSync(E)}catch(t){let S=errnoCode(t);S!==`ENOENT`&&e.onSkip?.(`symlink-stat-failed`,S,E);continue}if(S.has(O.ino))continue;S.add(O.ino),O.isDirectory()?w(E):O.isFile()&&isSupportedAssetFile(D,ASSET_EXTENSIONS)&&!e.contentFilter?.isExcluded(k)&&e.basenameIndex.add(k);continue}if(j.isDirectory()){if(S.has(j.ino))continue;S.add(j.ino),w(D);continue}j.isFile()&&isSupportedAssetFile(D,ASSET_EXTENSIONS)&&!e.contentFilter?.isExcluded(k)&&e.basenameIndex.add(k)}}w(t)}const HocuspocusAuthTokenSchema=object$1({principalId:string$2().optional(),tabSessionId:string$2().optional(),expectedServerInstanceId:string$2().optional(),expectedBranch:string$2().optional()}).loose(),HOCUSPOCUS_AUTH_REJECTION_REASONS=[`server-instance-mismatch`,`branch-mismatch`,`rename-redirect`,`doc-deleted`];function isHocuspocusAuthRejectionReason(e){return HOCUSPOCUS_AUTH_REJECTION_REASONS.includes(e)}const WIRE_PAYLOAD_SEPARATOR=`:`;function formatAuthRejectionWire(e,t){return typeof t!=`string`||t.length===0?e:`${e}${WIRE_PAYLOAD_SEPARATOR}${t}`}function parseAuthRejectionWire(e){if(e.length===0)return{kind:null,payload:void 0};let t=e.indexOf(WIRE_PAYLOAD_SEPARATOR),S=t===-1?e:e.slice(0,t);if(!isHocuspocusAuthRejectionReason(S))return{kind:null,payload:void 0};if(t===-1)return{kind:S,payload:void 0};let w=e.slice(t+1);return{kind:S,payload:w.length>0?w:void 0}}var HocuspocusAuthRejection=class extends Error{kind;payload;reason;constructor(e,t,S){super(t),this.name=`HocuspocusAuthRejection`,this.kind=e,this.payload=typeof S==`string`&&S.length>0?S:void 0,this.reason=formatAuthRejectionWire(e,this.payload)}};function parseHocuspocusAuthToken(e){if(typeof e!=`string`||e.length===0)return;let t;try{t=JSON.parse(e)}catch{return}let S=HocuspocusAuthTokenSchema.safeParse(t);return S.success?S.data:void 0}const DEFAULT_WARN_BEFORE_MS=300*1e3;function attachIdleShutdown(e){let t=e.scheduler??defaultScheduler,S=e.warnBeforeMs??DEFAULT_WARN_BEFORE_MS,w=0,E=null,D=null,O=!1,k=!1;function j(){E!==null&&(t.clearTimeout(E),E=null),D!==null&&(t.clearTimeout(D),D=null)}function F(){j(),!(k||O)&&w===0&&(S>0&&S<e.thresholdMs&&(D=t.setTimeout(()=>{D=null,w===0&&!O&&e.log?.warn({msUntilShutdown:S,webSocketClientCount:0},`idle shutdown pending: no WebSocket clients`)},e.thresholdMs-S)),E=t.setTimeout(()=>{if(E=null,!(k||O)&&w===0){O=!0,e.log?.info({webSocketClientCount:0},`idle shutdown firing`);try{let t=e.onShutdown();t&&typeof t.then==`function`&&t.catch(t=>{e.log?.error({err:t},`idle shutdown handler rejected`)})}catch(t){e.log?.error({err:t},`idle shutdown handler threw`)}}},e.thresholdMs))}let L=(e,t)=>{e.url?.startsWith(`/collab`)&&(w++,j(),t.once(`close`,()=>{w--,w<0&&(w=0),w===0&&F()}))};return e.httpServer.on(`upgrade`,L),F(),{detach:()=>{k||(k=!0,e.httpServer.off(`upgrade`,L),j())}}}const MCP_SERVER_NAME=`open-knowledge`,MCP_CONNECTION_ID_HEADER=`x-ok-connection-id`;function sanitizeClientName(e,t){let S=Array.from(e??``).map(e=>{let t=e.charCodeAt(0);return t<=31||t===127?` `:e}).join(``).replace(/\s+/g,` `).trim();return S?S.slice(0,128):t}function buildInstructions(e){return'Open Knowledge is a markdown-CRDT knowledge base exposed via MCP.\n\n## STOP — native tools on in-scope `.md` / `.mdx`\n\nWhen this workspace has Open Knowledge MCP configured, do **not** use your host\'s native file tools on markdown paths inside the content directory. The ban covers every common rationalization:\n\n- **Native `Read` / `Grep` / `Glob` on in-scope `.md` / `.mdx`** — the original case.\n- **`Bash ls` / `Bash find` / `Bash cat` on dirs containing in-scope markdown** — use `exec("ls -A …")` / `exec("find … -name \'*.md\'")` / `exec("cat …")` instead. Native returns bare names; `exec` returns frontmatter, backlink counts, and recent activity per child. `-A` shows hidden entries (`.ok/`, `.okignore`) which OK projects carry; omit `.` and `..` rows that `-a` would add.\n- **Glob patterns that target markdown** (`**/*.md`, any dir known to be markdown-heavy like `specs/**`, `reports/**`, `docs/**`) — use `exec` with `find`, or `list_documents({ dir })`.\n- **Dispatching the Explore / general-purpose subagent for markdown-heavy exploration** — subagents use native `Read` / `Grep` / `Glob` internally and bypass Open Knowledge entirely. Do markdown exploration yourself via `exec` / `search` / `grep`. Subagents remain appropriate for **source-code** exploration.\n- **Native `Read` / `Grep` on any in-scope markdown inside `.ok/`** — the `.ok/` directory is in-scope; if it carries `.md` / `.mdx`, treat those the same as any other knowledge-base file.\n\nWhy: native tools skip frontmatter, backlinks, shadow-repo activity, and project git history that OK\'s tools return for every matched knowledge-base file. `exec` is the primary read surface; it runs read-only bash (`cat`, `ls`, `grep`, `find`, `head`, `tail`, `wc`, `sort`, `uniq`, `cut` — pipes OK) and returns raw stdout plus enriched metadata per file.\n\n**MCP tool visibility — not seeing `exec` is NOT the escape hatch.** MCP wiring varies by client. Claude Code, Cursor, Codex, Windsurf, VS Code — each surfaces MCP differently. Server labels are user-defined; tools may not appear as top-level symbols named `exec` in your specific UI. If Open Knowledge is registered as an MCP server in this workspace, route markdown reads through its `exec` / `search` / `grep` / `read_document` via your client\'s documented MCP invocation (including any generic "call MCP tool" flow). Registration is the test, not top-level-symbol visibility.\n\n**Escape hatch.** Native `Read` / `Grep` / `Glob` on `.md` / `.mdx` is allowed **only** when no Open Knowledge MCP server is registered for this project, **or** immediately after you tried an MCP call and it failed — then begin a user-visible sentence with `Open Knowledge MCP unavailable:`. Never use the hatch because you skipped your client\'s MCP path, didn\'t see `exec` as a top-level tool, or rationalized the skill wasn\'t necessary.\n\n**Source code and non-markdown files** (`.ts`, `.py`, `package.json`, …): native `Read` / `Grep` / `Glob` always.\n\n## Reads — examples\n\n- Read a file: `exec("cat <path>.md")` — contents + full rich enrichment\n- List a directory: `exec("ls -A <dir>")` — per-child frontmatter, recursive markdown counts, most-recently-updated doc per subdir. Prefer `-A` over plain `ls`: OK projects carry dot-prefixed entries (`.ok/`, nested `.ok/`, `.okignore`) that plain `ls` omits. `-A` shows hidden entries without the noisy `.`/`..` rows that `-a` adds, and without the verbose long-format columns that `-la` adds (the per-child enrichment already carries the useful metadata `-l` would surface).\n- Search: `exec("grep -rn <term> <dir> | head -5")` — matches + enrichment on matched files\n- Typed tools (`read_document`, `search`, `grep`, `list_documents`) remain available — prefer them when a structured `structuredContent` shape is useful (e.g., passing results to another tool). For interactive reads, `exec` is lighter. **Pick the right search:** `search` for ranked retrieval (cmd-K parity — title boost + body BM25 + recency); `grep` for every literal-string occurrence grouped by file with frontmatter enrichment.\n\n## Preview — open the browser at session start\n\n**Open the preview browser as your first OK action of the session, if it is not already open.** The user watches edits land live in that pane; if it isn\'t open, your work is invisible and the whole CRDT pipeline is wasted. Treat this as step zero — before your first read, before your first write.\n\n- Claude Code Desktop: `preview_start("open-knowledge-ui")`.\n- Cursor: use the host\'s open-URL tool with a `previewUrl` from any write response.\n- Other hosts: use whatever command opens a URL (macOS: `open <url>`). On hosts with no preview tool (Codex, generic stdio), surface the URL in chat for the user to click.\n\n**How to know if it\'s already open.** You usually can\'t pre-check from the agent side — rely on these signals:\n\n1. You already opened it earlier in this session → don\'t reopen.\n2. A `write_document` / `edit_document` response returns `previewUrl` but NO `warning` → a browser is attached somewhere; do nothing.\n3. A response DOES include `warning: { action: "attach-preview-once", previewUrl, message }` → a UI server is reachable but no browser is attached; open the URL immediately, one-shot.\n4. A response includes `warning: { action: "start-ui", previewUrl: null, message }` → no UI is running anywhere for this project. Surface the message to the user (the in-band copy names the recovery options: `open-knowledge ui` in a terminal, `preview_start("open-knowledge-ui")` in Claude Code Desktop, or opening the project in OK Electron). Don\'t loop on retries — the user has to act.\n\nBoth warning shapes fire only when needed (server tracks `__system__` subscribers) and at most once per session in the normal fresh-start case.\n\nIf the server isn\'t running, you\'ll see a `"Hocuspocus server is not running"` error. If `previewUrl` is `null` in a tool response, no UI is reachable for this project — neither a CLI `open-knowledge ui` process nor an OK Electron window. Start one (`open-knowledge ui` from a terminal, `preview_start("open-knowledge-ui")` in Claude Code, or just open the project in OK Electron), then retry. NEVER construct preview URLs by hand — always use the `previewUrl` returned in tool responses.\n\nOK Electron and the CLI\'s `ok ui` cannot serve the same project at the same time — they both hold the same `ui.lock`. If `ok ui` errors with a UI-lock collision, an OK Electron window is open for that project (use that window, or quit it and re-run `ok ui`). The reverse holds for the user-facing case: opening a project in OK Electron while a standalone `ok ui` is running for the same project will fail the lock acquire.\n\n**No screenshots after edits.** Do NOT take `preview_screenshot` after every `edit_document` / `write_document`. Trust the CRDT tool response as confirmation the edit landed. Only screenshot when debugging a visual issue or when explicitly asked.\n\n## Scope recap\n\nOpen Knowledge looks for documents under the resolved `content.dir` (discoverable at runtime via `get_config({ path: [\'content\', \'dir\'] })`). `.gitignore` and `.okignore` (at the project root and at any folder depth) define exclusions. Folder defaults + templates live in nested `<folder>/.ok/frontmatter.yml` + `<folder>/.ok/templates/` files — NOT in `.ok/config.yml`.\n\nDefault mental model (no jargon): **every `.md` and `.mdx` under `content.dir`** not excluded by `.gitignore` or `.okignore` is an Open Knowledge document — including under `specs/`, `reports/`, `docs/`, etc. Read `.okignore` (and any nested `.okignore` files) once per turn to know what\'s excluded.\n\n**First session in this project?** If `frontmatter_defaults` and `templates_available` are empty for substantial folders, the project hasn\'t been onboarded yet — invoke `discover` (Workflow tools table) before writing. Once onboarded, the cascade carries the discipline.\n\n\nFull guidance lives in the bundled `open-knowledge` skill at `~/.ok/skills/open-knowledge/SKILL.md`.\n'}function installPrettyZodErrors(e){let t=e;if(t.__prettyZodErrorsInstalled===!0)return;let S=t.validateToolInput;if(typeof S!=`function`){console.warn(`[pretty-zod-errors] McpServer.validateToolInput not found — SDK internals may have changed. Falling back to default error formatting.`);return}t.validateToolInput=async function(e,t,w){if(!e.inputSchema||!isZodSchema(e.inputSchema))return S.call(this,e,t,w);let E=await e.inputSchema.safeParseAsync(t);if(E.success)return E.data;let D=prettifyError(E.error);throw new McpError(ErrorCode.InvalidParams,`Input validation error: Invalid arguments for tool ${w}:\n${D}`)},t.__prettyZodErrorsInstalled=!0}function isZodSchema(e){return typeof e!=`object`||!e?!1:typeof e.safeParseAsync==`function`}const loggerContext=new AsyncLocalStorage;var McpLogger=class e{sessionId;corrId;component;constructor(e=`mcp`,t){this.sessionId=t??randomUUID().slice(0,12),this.corrId=randomUUID().slice(0,8),this.component=e}info(e,t={}){this.emit(`info`,e,t)}warn(e,t={}){this.emit(`warn`,e,t)}error(e,t,S={}){let w=t?{error:t instanceof Error?t.message:String(t),...S}:S;this.emit(`error`,e,w)}debug(e,t={}){(process.env.MCP_DEBUG===`1`||process.env.DEBUG?.includes(`mcp`))&&this.emit(`debug`,e,t)}child(t){return new e(t??this.component,this.sessionId)}asCallback(){return e=>this.info(e)}emit(e,t,S){let w={ts:new Date().toISOString(),level:e,sessionId:this.sessionId,corrId:this.corrId,component:this.component,msg:t,...S},E=`${JSON.stringify(w)}\n`;process.stderr.write(E);let D=process.env.OK_LOG_FILE;if(D)try{appendFileSync(D,E)}catch(e){console.warn(`[mcp-logger] Failed to write to OK_LOG_FILE: ${e instanceof Error?e.message:e}`)}}};function runWithMcpLogger(e,t){return loggerContext.run(e,t)}function getCurrentMcpLogger(){return loggerContext.getStore()}const REDACTED_STRING_KEYS=new Set([`find`,`markdown`,`replace`]),COMMON_ARRAY_KEYS=[`backlinks`,`deadLinks`,`documents`,`enrichedPaths`,`entries`,`forwardLinks`,`hints`,`hubs`,`orphans`,`results`],COMMON_SCALAR_KEYS=[`checkpointRef`,`cwd`,`fileCount`,`matchCount`,`ok`,`query`,`stdoutTruncated`,`truncated`];function isPlainObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function isToolExtraLike(e){return isPlainObject(e)&&`requestId`in e}function summarizeStringForLog(e,t){if(REDACTED_STRING_KEYS.has(e))return{redacted:!0,type:`string`,length:t.length,lines:t.length===0?0:t.split(`
|
|
2114
2114
|
`).length};let S=e===`command`?240:120;return t.length<=S?t:{type:`string`,length:t.length,preview:`${t.slice(0,S)}...`}}function summarizeArgValue(e,t){if(t===null)return null;if(typeof t==`string`)return summarizeStringForLog(e,t);if(typeof t==`number`||typeof t==`boolean`)return t;if(Array.isArray(t))return{type:`array`,length:t.length};if(isPlainObject(t)){let e=Object.keys(t).sort();return{type:`object`,keyCount:e.length,keys:e.slice(0,12)}}if(t!==void 0)return{type:typeof t}}function summarizeArgsForLog(e,t){return isPlainObject(t)?Object.fromEntries(Object.entries(t).map(([e,t])=>[e,summarizeArgValue(e,t)])):summarizeArgValue(e,t)}function summarizeStructuredContentForLog(e){let t={structuredKeys:Object.keys(e).sort()};for(let S of COMMON_SCALAR_KEYS)S in e&&(t[S]=e[S]);for(let S of COMMON_ARRAY_KEYS){let w=e[S];Array.isArray(w)&&(t[`${S}Count`]=w.length)}return`previewUrl`in e&&(t.previewUrl=e.previewUrl??null),`previewUrlSource`in e&&(t.previewUrlSource=e.previewUrlSource),typeof e.stdout==`string`&&(t.stdoutChars=e.stdout.length),Array.isArray(e.warnings)&&(t.warningsCount=e.warnings.length),isPlainObject(e.warning)&&(t.warning=!0,`previewUrl`in e.warning&&(t.warningPreviewUrl=e.warning.previewUrl??null)),isPlainObject(e.ui)&&(t.uiBaseUrl=typeof e.ui.baseUrl==`string`||e.ui.baseUrl===null?e.ui.baseUrl:void 0,t.uiPort=typeof e.ui.port==`number`||e.ui.port===null?e.ui.port:void 0),t}function summarizeToolResultForLog(e){if(!isPlainObject(e))return{resultType:typeof e};let t={isError:e.isError===!0};return Array.isArray(e.content)&&(t.contentItems=e.content.length,t.contentTextChars=e.content.reduce((e,t)=>isPlainObject(t)&&typeof t.text==`string`?e+t.text.length:e,0)),isPlainObject(e.structuredContent)&&Object.assign(t,summarizeStructuredContentForLog(e.structuredContent)),t}function summarizeIdentityForLog(e){return{connectionId:e.connectionId.slice(0,8),displayName:e.displayName,...e.clientInfo?.name?{clientName:e.clientInfo.name}:{}}}function splitInvocationArgs(e){let t=e.at(-1);return isToolExtraLike(t)?{toolArgs:e.length>1?e[0]:void 0,extra:t}:{toolArgs:e[0],extra:void 0}}function wrapToolHandlerForLogging(e,t,S){let w=S.logger;return w?async(...E)=>{let D=w.child(),O=Date.now(),{toolArgs:k,extra:j}=splitInvocationArgs(E);D.info(`tool start`,{tool:e,...j?.requestId===void 0?{}:{requestId:j.requestId},...j?.sessionId?{transportSessionId:j.sessionId}:{},...S.identityRef?.current?{agent:summarizeIdentityForLog(S.identityRef.current)}:{},...k===void 0?{}:{args:summarizeArgsForLog(e,k)}});try{let S=await runWithMcpLogger(D,async()=>await t(...E));return D.info(`tool finish`,{tool:e,...j?.requestId===void 0?{}:{requestId:j.requestId},durationMs:Date.now()-O,result:summarizeToolResultForLog(S)}),S}catch(t){throw D.error(`tool error`,t,{tool:e,...j?.requestId===void 0?{}:{requestId:j.requestId},durationMs:Date.now()-O}),t}}:t}function createLoggedServer(e,t){if(!t.logger)return e;let S=e.tool.bind(e),w=e.registerTool,E=typeof w==`function`?w.bind(e):void 0,D=Object.create(e);return D.tool=((...e)=>{let w=String(e[0]),E=e.at(-1);if(typeof E!=`function`)return S(...e);let D=[...e];return D[D.length-1]=wrapToolHandlerForLogging(w,E,t),S(...D)}),E&&(D.registerTool=((e,S,w)=>typeof w==`function`?E(e,S,wrapToolHandlerForLogging(e,w,t)):E(e,S,w))),D}function buildBody$2(e,t){return`Promote existing research on this topic into a canonical article inside the project content directory. **Canonical, not provisional** — the output is the source of truth for future agents.
|
|
2115
2115
|
|
|
2116
2116
|
Topic: ${e}
|
|
@@ -2259,7 +2259,7 @@ superseded_by: <path-to-new-canonical-article>.md
|
|
|
2259
2259
|
- **Don't rewrite research prose verbatim** — canonical articles have a different voice (direct, decided) than research (exploratory, provisional)
|
|
2260
2260
|
- **Don't skip the supersedes / superseded_by links** — the audit trail matters for future readers
|
|
2261
2261
|
`}const DESCRIPTION$28=[`Returns a multi-step plan for promoting research findings into a canonical article. Does NOT write the article — you execute the plan after the STOP gate confirms the decision.`,``,`**Use when:**`,`- A team has made a decision after research and wants the outcome committed as canonical knowledge`,`- Compacting several provisional research notes into one authoritative article`,`- A developer asks to "consolidate" or "finalize" knowledge on a topic`,``,`**Triggers on:**`,`- "consolidate", "finalize", "promote to canonical", "make this official"`,`- User says the team has decided and wants the outcome written as canonical`,`- Research has stabilized and a destination article is needed`].join(`
|
|
2262
|
-
`);function register$28(e,t){e.registerTool(`consolidate`,{description:DESCRIPTION$28,inputSchema:{topic:string$2().describe(`The topic to consolidate into a canonical article`),cwd:string$2().optional().describe(ROUTED_CWD_DESCRIPTION)}},buildWorkflowHandler(`consolidate`,t,`topic`,buildBody$2))}const PREVIEW_URL_SOURCES=[`lock`];function encodeDocName(e){return e.split(`/`).map(encodeURIComponent).join(`/`)}async function resolvePreviewUrlForTool(e,t,S){return resolvePreviewUrl(e,{lockDir:resolveLockDir(S??await t.resolveCwd())})}function resolveUiInfo(e){try{let t=readUiLock(e.lockDir);if(t&&t.port>0)return{baseUrl:`http://localhost:${t.port}`,port:t.port}}catch(t){process.stderr.write(`[preview-url] readUiLock failed at ${e.lockDir} while building ui block: ${t instanceof Error?t.message:String(t)}\n`)}return{baseUrl:null,port:null}}async function buildListResolver(e,t){let S={lockDir:resolveLockDir(t??await e.resolveCwd())};return{resolve:e=>resolvePreviewUrl(e,S),ui:resolveUiInfo(S)}}function docNameFromPath(e){let t=e.toLowerCase();return t.endsWith(`.md`)?e.slice(0,-3):t.endsWith(`.mdx`)?e.slice(0,-4):e}function resolvePreviewUrl(e,t){let S=`/#/${encodeDocName(e)}`;try{let e=readUiLock(t.lockDir);if(e&&e.port>0)return{url:`http://localhost:${e.port}${S}`,source:`lock`}}catch(e){process.stderr.write(`[preview-url] readUiLock failed at ${t.lockDir}: ${e instanceof Error?e.message:String(e)}\n`)}return null}const DESCRIPTION$27=["[Requires: Hocuspocus server] Delete a document through the managed delete flow at `POST /api/delete-path` (kind: file).",`Closes all open agent sessions for the doc, unloads it from Hocuspocus, and removes the file from disk.`,``,`**Parameters:**`,"- `docName` — Document name, typically without extension. A trailing `.md` or `.mdx` is stripped automatically.",``,`**Notes:**`,'- Inbound wiki-links to the deleted doc become dead links (redlinks) — they are NOT rewritten. Call `get_backlinks({ docName: "your-doc" })` BEFORE deleting to see which docs link here, then update or remove those references first.',"- Deletion is irreversible from this tool. Use `save_version` beforehand if you may need to roll back.","- The structured response includes `previousPreviewUrl` (when a preview source resolves) so agents can close any stale preview tab pointing at the deleted doc.",``,`**Errors:**`,"- 400 — `docName` is not a valid relative content path.",`- 404 — document does not exist.`].join(`
|
|
2262
|
+
`);function register$28(e,t){e.registerTool(`consolidate`,{description:DESCRIPTION$28,inputSchema:{topic:string$2().describe(`The topic to consolidate into a canonical article`),cwd:string$2().optional().describe(ROUTED_CWD_DESCRIPTION)}},buildWorkflowHandler(`consolidate`,t,`topic`,buildBody$2))}const PREVIEW_URL_SOURCES=[`lock`];function encodeDocName(e){return e.split(`/`).map(encodeURIComponent).join(`/`)}const START_UI_MESSAGE='No UI is running for this project. Start one to see the preview: `open-knowledge ui` (terminal), `preview_start("open-knowledge-ui")` (Claude Code Desktop), or open the project in OK Electron.',ATTACH_PREVIEW_ONCE_MESSAGE=`Open the previewUrl in your preview browser.`;function buildPreviewAttachWarning(e){return e?{action:`attach-preview-once`,previewUrl:e.url,message:ATTACH_PREVIEW_ONCE_MESSAGE}:{action:`start-ui`,previewUrl:null,message:START_UI_MESSAGE}}const START_UI_TEXT_HINT=START_UI_MESSAGE;async function resolvePreviewUrlForTool(e,t,S){return resolvePreviewUrl(e,{lockDir:resolveLockDir(S??await t.resolveCwd())})}function resolveUiInfo(e){try{let t=readUiLock(e.lockDir);if(t&&t.port>0)return{baseUrl:`http://localhost:${t.port}`,port:t.port}}catch(t){process.stderr.write(`[preview-url] readUiLock failed at ${e.lockDir} while building ui block: ${t instanceof Error?t.message:String(t)}\n`)}return{baseUrl:null,port:null}}async function buildListResolver(e,t){let S={lockDir:resolveLockDir(t??await e.resolveCwd())};return{resolve:e=>resolvePreviewUrl(e,S),ui:resolveUiInfo(S)}}function docNameFromPath(e){let t=e.toLowerCase();return t.endsWith(`.md`)?e.slice(0,-3):t.endsWith(`.mdx`)?e.slice(0,-4):e}function resolvePreviewUrl(e,t){let S=`/#/${encodeDocName(e)}`;try{let e=readUiLock(t.lockDir);if(e&&e.port>0)return{url:`http://localhost:${e.port}${S}`,source:`lock`}}catch(e){process.stderr.write(`[preview-url] readUiLock failed at ${t.lockDir}: ${e instanceof Error?e.message:String(e)}\n`)}return null}const DESCRIPTION$27=["[Requires: Hocuspocus server] Delete a document through the managed delete flow at `POST /api/delete-path` (kind: file).",`Closes all open agent sessions for the doc, unloads it from Hocuspocus, and removes the file from disk.`,``,`**Parameters:**`,"- `docName` — Document name, typically without extension. A trailing `.md` or `.mdx` is stripped automatically.",``,`**Notes:**`,'- Inbound wiki-links to the deleted doc become dead links (redlinks) — they are NOT rewritten. Call `get_backlinks({ docName: "your-doc" })` BEFORE deleting to see which docs link here, then update or remove those references first.',"- Deletion is irreversible from this tool. Use `save_version` beforehand if you may need to roll back.","- The structured response includes `previousPreviewUrl` (when a preview source resolves) so agents can close any stale preview tab pointing at the deleted doc.",``,`**Errors:**`,"- 400 — `docName` is not a valid relative content path.",`- 404 — document does not exist.`].join(`
|
|
2263
2263
|
`);function parseDeletedDocNames(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}function register$27(e,t){e.registerTool(`delete_document`,{description:DESCRIPTION$27,inputSchema:{docName:string$2().describe(`Document name to delete`),cwd:string$2().optional().describe(ROUTED_CWD_DESCRIPTION)}},async e=>{let S=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!S.ok)return textResult(`Error: ${S.error}`,!0);let{cwd:w,url:E}=S;if(!E)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let D=normalizeDocName(e.docName);if(!D.ok)return textResult(D.error,!0);let O=t.identityRef?.current,k=await httpPost(E,`/api/delete-path`,{kind:`file`,path:D.docName,...O?{agentId:O.connectionId,agentName:O.displayName,clientName:O.clientInfo?.name,colorSeed:O.colorSeed}:{}});if(!k.ok){let e=k.error,t={ok:!1,error:e};return textPlusStructured(`Error: ${e}`,t,!0)}let j=parseDeletedDocNames(k.deletedDocNames),F=await resolvePreviewUrlForTool(D.docName,{config:t.config,resolveCwd:t.resolveCwd},w),L={ok:!0,deletedDocNames:j.length>0?j:[D.docName],...F?{previousPreviewUrl:F.url}:{}};return textPlusStructured(L.deletedDocNames.length===1?`Deleted ${L.deletedDocNames[0]}.`:`Deleted ${L.deletedDocNames.length} documents: ${L.deletedDocNames.join(`, `)}.`,L)})}const DESCRIPTION$26=[`[Operates on disk; no running OK server required] Delete a template.`,``,"Deletes `<folder>/.ok/templates/<name>.md` from the current project. Idempotent: deleting a template that does not exist returns success with `existed: false`. Auto-cleans empty `<folder>/.ok/templates/` and `<folder>/.ok/` directories.",``,`**Parameters:**`,"- `folder` — Project-root-relative folder. Empty / `.` means project root.","- `name` — Template filename without `.md` extension."].join(`
|
|
2264
2264
|
`),InputSchema$7={folder:string$2().describe("Project-root-relative folder. Empty / `.` means project root."),name:string$2().min(1).regex(/^[A-Za-z0-9_-]+$/,"Template name must use letters, digits, `_`, or `-` only.").describe("Template filename without `.md` extension."),cwd:string$2().optional().describe(ROUTED_CWD_DESCRIPTION)},OutputSchema$7=outputSchemaWithText({result:union([object$1({ok:literal(!0),path:string$2(),existed:boolean$1(),cleanedEmpty:object$1({templatesDir:boolean$1(),okDir:boolean$1()})}),object$1({ok:literal(!1),error:object$1({code:string$2(),message:string$2()})})])});function register$26(e,t){e.registerTool(`delete_template`,{description:DESCRIPTION$26,inputSchema:object$1(InputSchema$7).strict(),outputSchema:OutputSchema$7,annotations:{readOnlyHint:!1,idempotentHint:!0,destructiveHint:!0}},async e=>{let S=await resolveProjectConfigContext(t.resolveCwd,t.config,e.cwd);if(!S.ok)return{isError:!0,content:[{type:`text`,text:`Error: ${S.error}`}]};let{cwd:w}=S,E=applyTemplateDelete({projectDir:w,folder:e.folder,name:e.name});if(!E.ok)return{isError:!0,structuredContent:{result:E},content:[{type:`text`,text:`${E.error.code}: ${E.error.message}`}]};let D=[E.existed?`Deleted template at ${E.path}`:`Template at ${E.path} did not exist (no-op)`];return E.cleanedEmpty.templatesDir&&D.push(`Removed empty .ok/templates/ directory`),E.cleanedEmpty.okDir&&D.push(`Removed empty .ok/ directory`),textPlusStructured(D.join(`
|
|
2265
2265
|
`),{result:E})})}function buildDiscoverBody(e){return`# Discover — Project Convention Extraction + Link Graph Activation
|
|
@@ -2579,8 +2579,8 @@ Link-graph activation:
|
|
|
2579
2579
|
- **Validation failure** (Phase 6) → don't pretend to succeed; surface the failed step to the user.
|
|
2580
2580
|
`}const DESCRIPTION$25=[`Returns a multi-step plan for setting up an existing repo (extract conventions, set folder frontmatter, write templates, activate link graph). Does NOT execute the plan — you do, with per-phase user confirmation.`,``,`**Use when:**`,`- First arrival at a repo that has existing markdown content AND no folder frontmatter / templates configured`,"- `list_documents` returns empty `frontmatter_defaults` + empty `templates_available` for substantial folders",`- User explicitly asks to onboard / set up / configure an existing repo`,``,`**Do NOT invoke when:**`,"- The repo is empty (< 5 .md files) — use `ok seed` instead",`- The repo is already fully configured (every substantial folder has folder frontmatter + templates)`,``,'One-shot per project. Idempotent on re-run — detects prior configuration and switches to "extend mode" (proposes additions only, never re-proposes existing artifacts). **Requires the OK Hocuspocus server running** — most primitives the body composes (`list_documents`, `read_document`, link-graph) hit the server. Phase 1 step 0 enforces this; if the server is down, the tool exits cleanly with a "run `open-knowledge start`" instruction. Only `exec`, `set_folder_rule`, `write_template`, and the `.okignore` write are fs-direct.',``,"**Composes existing primitives only** — no new MCP tools, no schema changes. Uses `exec`, `list_documents`, `read_document`, `search`, `set_folder_rule`, `write_template`, `get_orphans`, `get_hubs`, `get_dead_links`, `get_backlinks`, `get_forward_links`, `suggest_links`, `edit_document`."].join(`
|
|
2581
2581
|
`),InputSchema$6={cwd:string$2().optional().describe(ROUTED_CWD_DESCRIPTION)},OutputSchema$6=outputSchemaWithText({previewUrl:_null()});function register$25(e,t){e.registerTool(`discover`,{description:DESCRIPTION$25,inputSchema:InputSchema$6,outputSchema:OutputSchema$6,annotations:{readOnlyHint:!1,idempotentHint:!0,destructiveHint:!1}},async e=>{let S=await resolveProjectConfigContext(t.resolveCwd,t.config,e.cwd);return S.ok?textPlusStructured(buildDiscoverBody(S.config.content.dir),{previewUrl:null}):textResult(`Error: ${S.error}`,!0)})}const DESCRIPTION$24=`${[`[Requires: Hocuspocus server] Find-and-replace on a live document via the CRDT layer.`,`The patch is applied through Hocuspocus and propagated to all connected editors in real-time.`,"Use `offset` when you need to patch an exact occurrence; omit it to preserve first-match behavior.",``,'**Body-only.** Frontmatter-intersecting find/replace calls are rejected with HTTP 400. Frontmatter editing via MCP is currently unavailable — to change frontmatter, use `write_document` with `position: "replace"` and a payload that includes the new YAML block.',``,"**When rewriting prose, add `[[wiki-links]]` aggressively.** If the replacement mentions other documents or entities that should have their own page, link them as `[[Page Name]]`. Over-linking is the goal; underlinked documents lose their value in backlink-driven navigation.",``,`**Parameters:**`,"- `docName` — Document name, typically without extension. A trailing `.md` or `.mdx` is stripped automatically.","- `find` — Text to find (exact match)","- `replace` — Replacement text","- `offset` (optional) — Exact occurrence to patch, as a JavaScript string offset in the current markdown. If the document changed and the text no longer matches there, the server returns a stale-target error; re-run `suggest_links` to get fresh offsets.",'- `summary` — Optional one-line user-outcome description of this edit (≤80 chars). Appears as a bullet in the document timeline so readers can scan intent without opening every diff. Prefer outcome phrasing ("Fixed token-refresh race") over structural ("Changed 1 line"). Avoid including secrets or PII — summaries are persisted to git history.'].join(`
|
|
2582
|
-
`)}\n${renderInventoryFooter()}`;function register$24(e,t){e.registerTool(`edit_document`,{description:DESCRIPTION$24,inputSchema:{docName:string$2().describe(`Document name to edit`),find:string$2().describe(`Text to find (exact match)`),replace:string$2().describe(`Replacement text`),offset:number$1().int().min(0).optional().describe(`Exact occurrence to patch, as a JavaScript string offset in the current markdown`),summary:summaryArgSchema,cwd:string$2().optional().describe(ROUTED_CWD_DESCRIPTION)}},async e=>{let S=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!S.ok)return textResult(`Error: ${S.error}`,!0);let{cwd:w,url:E}=S;if(!E)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let D=normalizeDocName(e.docName);if(!D.ok)return textResult(D.error,!0);let O=t.identityRef?.current,k=await httpPost(E,`/api/agent-patch`,{docName:D.docName,find:e.find,replace:e.replace,offset:e.offset,...e.summary===void 0?{}:{summary:e.summary},...O?{agentId:O.connectionId,agentName:O.displayName,clientName:O.clientInfo?.name,colorSeed:O.colorSeed}:{}});if(!k.ok)return textResult(`Error: ${k.error}`,!0);let j=resolveLockDir(w),F=resolvePreviewUrl(D.docName,{lockDir:j}),L=typeof k.subscriberCount==`number`?k.subscriberCount:void 0,B=(typeof k.systemSubscriberCount==`number`?k.systemSubscriberCount:void 0)===0,H=L===0,q=k.summary&&typeof k.summary==`object`?k.summary:void 0,J=typeof q?.hint==`string`?q.hint:void 0,Y=[`Edit applied successfully.`];F&&Y.push(`Preview: ${F.url}`),B&&Y.push(F?`Open ${F.url} in your preview browser
|
|
2583
|
-
`);if(!F&&!B&&!H&&!q)return textResult(ee);let te={};return F&&(te.previewUrl=F.url,te.previewUrlSource=F.source),B&&(te.warning=
|
|
2582
|
+
`)}\n${renderInventoryFooter()}`;function register$24(e,t){e.registerTool(`edit_document`,{description:DESCRIPTION$24,inputSchema:{docName:string$2().describe(`Document name to edit`),find:string$2().describe(`Text to find (exact match)`),replace:string$2().describe(`Replacement text`),offset:number$1().int().min(0).optional().describe(`Exact occurrence to patch, as a JavaScript string offset in the current markdown`),summary:summaryArgSchema,cwd:string$2().optional().describe(ROUTED_CWD_DESCRIPTION)}},async e=>{let S=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!S.ok)return textResult(`Error: ${S.error}`,!0);let{cwd:w,url:E}=S;if(!E)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let D=normalizeDocName(e.docName);if(!D.ok)return textResult(D.error,!0);let O=t.identityRef?.current,k=await httpPost(E,`/api/agent-patch`,{docName:D.docName,find:e.find,replace:e.replace,offset:e.offset,...e.summary===void 0?{}:{summary:e.summary},...O?{agentId:O.connectionId,agentName:O.displayName,clientName:O.clientInfo?.name,colorSeed:O.colorSeed}:{}});if(!k.ok)return textResult(`Error: ${k.error}`,!0);let j=resolveLockDir(w),F=resolvePreviewUrl(D.docName,{lockDir:j}),L=typeof k.subscriberCount==`number`?k.subscriberCount:void 0,B=(typeof k.systemSubscriberCount==`number`?k.systemSubscriberCount:void 0)===0,H=L===0,q=k.summary&&typeof k.summary==`object`?k.summary:void 0,J=typeof q?.hint==`string`?q.hint:void 0,Y=[`Edit applied successfully.`];F&&Y.push(`Preview: ${F.url}`),B&&Y.push(F?`Open ${F.url} in your preview browser.`:START_UI_TEXT_HINT),J&&Y.push(J);let ee=Y.join(`
|
|
2583
|
+
`);if(!F&&!B&&!H&&!q)return textResult(ee);let te={};return F&&(te.previewUrl=F.url,te.previewUrlSource=F.source),B&&(te.warning=buildPreviewAttachWarning(F)),q&&(te.summary=q),textPlusStructured(ee,te)})}const PRODUCER_COMMANDS=new Set([`cat`,`ls`,`grep`,`find`]),PATH_FALLBACK_RE=/\b[\w./-]+\.(md|mdx)\b/g;function isWikiPath(e){return/\.(md|mdx)$/.test(e)}function normalize$1(e){let t=e.trim();return t?(t=t.replace(/\/+/g,`/`),t.startsWith(`./`)&&(t=t.slice(2)),t.endsWith(`/`)&&(t=t.slice(0,-1)),t):``}function argsOf(e){return e.args.slice(1)}function nonFlagArgs(e){return e.filter(e=>!e.startsWith(`-`))}function extractFromCat(e){return nonFlagArgs(argsOf(e)).filter(isWikiPath)}function extractFromLs(e,t){let S=nonFlagArgs(argsOf(t)),w=S.length>0?S[S.length-1]:``,E=w&&w!==`.`?normalize$1(w):``,D=[];E&&D.push(E);for(let t of e.split(`
|
|
2584
2584
|
`)){let e=t.trim();if(!e||/\.[a-z0-9]+$/i.test(e)&&!isWikiPath(e))continue;let S=E?`${E}/${e}`:e;D.push(S)}return D}function extractFromGrep(e){let t=[];for(let S of e.split(`
|
|
2585
2585
|
`)){if(!S)continue;let e=S.indexOf(`:`);if(e<0)continue;let w=normalize$1(S.slice(0,e));isWikiPath(w)&&t.push(w)}return t}function extractFromFind(e){let t=[];for(let S of e.split(`
|
|
2586
2586
|
`)){let e=normalize$1(S);e&&isWikiPath(e)&&t.push(e)}return t}function extractFromHeadTail(e){return nonFlagArgs(argsOf(e)).filter(isWikiPath)}function headTailActsAsProducer(e){return nonFlagArgs(argsOf(e)).length>0}function fallback(e){let t=[],S=e.matchAll(PATH_FALLBACK_RE);for(let e of S)t.push(normalize$1(e[0]));return t}function extractReferencedPaths(e,t){let S=null;for(let e=t.length-1;e>=0;e--){let w=t[e];if(PRODUCER_COMMANDS.has(w.command)){S=w;break}if((w.command===`head`||w.command===`tail`)&&headTailActsAsProducer(w)){S=w;break}}let w;if(!S)w=fallback(e);else{switch(S.command){case`cat`:w=extractFromCat(S);break;case`ls`:w=extractFromLs(e,S);break;case`grep`:w=extractFromGrep(e);break;case`find`:w=extractFromFind(e);break;case`head`:case`tail`:w=extractFromHeadTail(S);break;default:w=fallback(e)}w.length===0&&(w=fallback(e))}let E=new Set,D=[];for(let e of w){let t=normalize$1(e);!t||E.has(t)||(E.add(t),D.push(t))}return D}function shellEscape(e){return e===``?`''`:/^[\w.\-/]+$/.test(e)?e:`'${e.replace(/'/g,`'\\''`)}'`}const MAX_STDOUT_BYTES=16*1024*1024;var StdoutOverflowError=class extends Error{limitBytes;actualBytes;partial;constructor(e,t,S){super(`Output exceeded ${e} byte buffer (got ${t}); narrow the command`),this.name=`StdoutOverflowError`,this.limitBytes=e,this.actualBytes=t,this.partial=S}};function createBashInstance(e){if(!isAbsolute(e))throw Error(`createBashInstance: cwd must be absolute (got: ${e})`);return new xt({cwd:`/`,fs:new Ss({root:resolve(e),allowSymlinks:!1})})}async function execBash(e,t){let S=await e.exec(t);if(S.stdout.length>MAX_STDOUT_BYTES)throw new StdoutOverflowError(MAX_STDOUT_BYTES,S.stdout.length,{stdout:S.stdout.slice(0,MAX_STDOUT_BYTES),stderr:S.stderr,exitCode:S.exitCode});return{stdout:S.stdout,stderr:S.stderr,exitCode:S.exitCode}}function normalizeGrepGlob(e){return e.startsWith(`**/`)?e.slice(3):e}async function grep(e,t,S={}){let w=createBashInstance(t),E=[`-rn`,`-F`];(S.caseInsensitive??!0)&&E.push(`-i`);for(let e of S.include??[])E.push(`--include=${shellEscape(normalizeGrepGlob(e))}`);for(let e of S.exclude??[])E.push(`--exclude=${shellEscape(normalizeGrepGlob(e))}`),E.push(`--exclude-dir=${shellEscape(normalizeGrepGlob(e))}`);let D=S.paths?.length?S.paths.map(shellEscape):[`.`],O=`grep ${E.join(` `)} ${shellEscape(e)} ${D.join(` `)}`,k;try{k=await execBash(w,O)}catch(e){if(e instanceof StdoutOverflowError)k=e.partial;else throw e}if(k.exitCode===1&&!k.stdout)return[];if(k.exitCode!==0&&k.exitCode!==1&&!k.stdout)throw Error(`grep exited ${k.exitCode}: ${k.stderr}`);let j=[],F=S.maxResults??1/0;for(let e of k.stdout.split(`
|
|
@@ -2592,8 +2592,8 @@ Link-graph activation:
|
|
|
2592
2592
|
`)}async function classifyPaths(e,t){let S=[],w=[];return await Promise.all(t.map(async t=>{try{let E=await stat$1(resolve(e,t));E.isDirectory()?w.push(t):E.isFile()&&S.push(t)}catch{/\.(md|mdx)$/i.test(t)&&S.push(t)}})),{files:S,dirs:w}}function errorCategoryResult(e,t){return textPlusStructured(t,{enrichedPaths:[],error:{category:e,message:t}},!0)}function withPreviewUrls(e,t){return e.map(e=>{let S=t(docNameFromPath(e.path));return{...e,previewUrl:S?.url??null,...S?{previewUrlSource:S.source}:{}}})}async function buildExecResult(e,t){let S=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!S.ok)return errorCategoryResult(`shell_construct_blocked`,`exec failed: ${S.error}`);let{cwd:w,config:E,url:D}=S,O=parseCommand(e.command);if(`error`in O)return errorCategoryResult(O.error.category,O.error.message);let k=augmentStagesWithExcludes(O.stages),j=serializeStages(k),F=await snapshotMtimes(w),L=createBashInstance(w),B=``,H=``;try{let e=await execBash(L,j);B=e.stdout,H=e.stderr}catch(e){return e instanceof StdoutOverflowError?errorCategoryResult(`output_overflow`,`Output exceeded 16 MB buffer. Narrow the command (e.g., add a more specific grep pattern, use head, restrict the path).`):errorCategoryResult(`shell_construct_blocked`,`exec failed: ${e instanceof Error?e.message:String(e)}`)}let q=await snapshotMtimes(w),J=diffMtimes(F.snapshot,q.snapshot);if(J.changed.length>0)return errorCategoryResult(`security_invariant_violation`,`Security invariant violated: file(s) in the content directory were modified during a read-only exec call: ${J.changed.join(`, `)}. This indicates a parser bug; the command has been logged.`);let Y=applySoftCap(B),ee=extractReferencedPaths(B,k).filter(e=>resolveWithinRoot(w,e).ok),{files:te,dirs:ne}=await classifyPaths(w,ee),ae=k.length===1&&k[0].command===`cat`&&te.length===1,oe=await Promise.all(te.map(e=>enrichPath(e,{projectDir:w,serverUrl:D},{includeRichFields:ae}).catch(()=>({path:e,tags:[],frontmatter:{},backlinkCount:null,backlinks:null,forwardLinkCount:null,forwardLinks:null,history:null,historySource:null,projectHistory:null,projectHistorySource:null})))),se=await Promise.all(ne.map(e=>enrichDirectory(e,{projectDir:w}).catch(()=>({path:e,type:`directory`,directMdCount:0,recursiveMdCount:0,childDirCount:0,truncated:!1}))));if(!ae&&D&&oe.length>0){let e=await fetchBacklinkCountsBatch(D,oe.map(e=>pathToDocName$1(e.path))).catch(()=>null);if(e)for(let t of oe){let S=e.get(pathToDocName$1(t.path));typeof S==`number`&&(t.backlinkCount=S)}}let ce=new Map(oe.map(e=>[e.path,e])),ue=new Map(se.map(e=>[e.path,e])),de=[];for(let e of ee){let t=ce.get(e);if(t){de.push(t);continue}let S=ue.get(e);S&&de.push(S)}let fe=detectBinaryArgs(k),me=[];fe.length>0&&me.push(`File${fe.length>1?`s`:``} ${fe.join(`, `)} appear${fe.length===1?`s`:``} to be binary (image/PDF/etc.) — exec returns text only (NG8). For binary retrieval, use native Read.`);let ge=detectHeadTailTruncation(k,B);ge&&me.push(ge.banner),H&&me.push(`stderr: ${H.trim()}`);let _e=me.length>0?`${me.join(`
|
|
2593
2593
|
`)}\n\n`:``,ve=buildStdoutProvenance(k,ue,ce)+Y.text,ye=`${_e}${ve}${formatEnrichedBlock(de)}`,{resolve:Ce,ui:we}=await buildListResolver({config:E,resolveCwd:async()=>w}),Te=withPreviewUrls(de,Ce),De=we;return textPlusStructured(ye,{enrichedPaths:Te,stdout:ve,stdoutTruncated:Y.truncated,cwd:w,...De?{ui:De}:{},...me.length>0?{warnings:me}:{}})}function register$23(e,t){e.registerTool(`exec`,{description:DESCRIPTION$23,inputSchema:{command:string$2().describe(`Read-only bash command (allowlist: cat, ls, grep, find, head, tail, wc, sort, uniq, cut; pipes OK)`),cwd:string$2().optional().describe("Absolute host path to run the command from. Defaults only when the MCP client advertises exactly one root; otherwise pass `cwd` explicitly.")}},async e=>{try{return await buildExecResult(e,t)}catch(e){return errorCategoryResult(`shell_construct_blocked`,`exec handler error: ${e instanceof Error?e.message:String(e)}`)}})}const DESCRIPTION$22=[`[Requires: Hocuspocus server] Set, create, or delete frontmatter properties via JSON Merge Patch (RFC 7396).`,``,`Field-level CRDT merge: concurrent patches to different keys (human form + this tool, or two agents) merge cleanly. Same-key concurrent writes resolve last-writer-wins per key.`,``,'**Use this tool — not `edit_document` — for any frontmatter change.** `edit_document` (agent-patch) targets body content; FM-intersecting `edit_document` calls return HTTP 400. For full-document rewrites (≥3-5 frontmatter keys changing), `write_document({ position: "replace" })` remains the canonical pathway.',``,`**Parameters:**`,"- `docName` — Document name. A trailing `.md` or `.mdx` is stripped automatically.","- `patch` — Object whose keys are property names. Each value is the new value (string, number, boolean, or array of strings) to **set or create** the key, or `null` to **delete** the key. Keys not present in `patch` are unchanged.","- `types` (optional) — **Currently ignored.** Shape-validated for forward-compat but not persisted server-side; type is inferred from value shape on read. Reserved for a future per-key widget-type override (`text | number | boolean | date | list`) once persistence ships.",'- `summary` — Optional one-line user-outcome description (≤80 chars). Prefer outcome phrasing ("Marked spec as approved") over structural ("Set status field"). Avoid secrets / PII — summaries persist to git history.',``,`**Atomicity:** any value failing schema validation rejects the WHOLE patch (HTTP 400 with per-key error report). Either every change commits or none do.`].join(`
|
|
2594
2594
|
`),PatchValueSchema=union([FrontmatterValueSchema,_null()]).describe("Property value (string|number|boolean|string[]) — `null` deletes the key");function register$22(e,t){e.registerTool(`frontmatter_patch`,{description:DESCRIPTION$22,inputSchema:{docName:string$2().describe(`Document name`),patch:record(string$2(),PatchValueSchema).describe("JSON Merge Patch — `{key: value}` sets, `{key: null}` deletes"),types:record(string$2(),_enum(FRONTMATTER_TYPES)).optional().describe(`Currently ignored (shape-validated for forward-compat but not persisted). Type is inferred from value shape on read. Will become a real per-key widget-type override (text|number|boolean|date|list) once persistence lands.`),summary:summaryArgSchema,cwd:string$2().optional().describe(ROUTED_CWD_DESCRIPTION)}},async e=>{let S=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!S.ok)return textResult(`Error: ${S.error}`,!0);let{cwd:w,url:E}=S;if(!E)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let D=normalizeDocName(e.docName);if(!D.ok)return textResult(D.error,!0);let O=t.identityRef?.current,k=await httpPost(E,`/api/frontmatter-patch`,{docName:D.docName,patch:e.patch,...e.types?{types:e.types}:{},...e.summary===void 0?{}:{summary:e.summary},...O?{agentId:O.connectionId,agentName:O.displayName,clientName:O.clientInfo?.name,colorSeed:O.colorSeed}:{}});if(!k.ok){let e=k.error,t=k.fieldErrors&&typeof k.fieldErrors==`object`?k.fieldErrors:void 0;return textResult(t?`Error: ${e}\n${Object.entries(t).map(([e,t])=>` ${e}: ${t}`).join(`
|
|
2595
|
-
`)}`:`Error: ${e}`,!0)}let j=resolveLockDir(w),F=resolvePreviewUrl(D.docName,{lockDir:j}),L=typeof k.subscriberCount==`number`?k.subscriberCount:void 0,B=(typeof k.systemSubscriberCount==`number`?k.systemSubscriberCount:void 0)===0,H=L===0,q=k.summary&&typeof k.summary==`object`?k.summary:void 0,J=typeof q?.hint==`string`?q.hint:void 0,Y=[],ee=[];for(let[t,S]of Object.entries(e.patch))S===null?ee.push(t):Y.push(t);let te=[`Frontmatter patched (${[Y.length?`${Y.length} set`:``,ee.length?`${ee.length} deleted`:``].filter(Boolean).join(`, `)||`${Object.keys(e.patch).length} key(s)`}).`];F&&te.push(`Preview: ${F.url}`),B&&te.push(F?`Open ${F.url} in your preview browser
|
|
2596
|
-
`);if(!F&&!B&&!H&&!q)return textResult(ne);let ae={};return F&&(ae.previewUrl=F.url,ae.previewUrlSource=F.source),B&&(ae.warning=
|
|
2595
|
+
`)}`:`Error: ${e}`,!0)}let j=resolveLockDir(w),F=resolvePreviewUrl(D.docName,{lockDir:j}),L=typeof k.subscriberCount==`number`?k.subscriberCount:void 0,B=(typeof k.systemSubscriberCount==`number`?k.systemSubscriberCount:void 0)===0,H=L===0,q=k.summary&&typeof k.summary==`object`?k.summary:void 0,J=typeof q?.hint==`string`?q.hint:void 0,Y=[],ee=[];for(let[t,S]of Object.entries(e.patch))S===null?ee.push(t):Y.push(t);let te=[`Frontmatter patched (${[Y.length?`${Y.length} set`:``,ee.length?`${ee.length} deleted`:``].filter(Boolean).join(`, `)||`${Object.keys(e.patch).length} key(s)`}).`];F&&te.push(`Preview: ${F.url}`),B&&te.push(F?`Open ${F.url} in your preview browser.`:START_UI_TEXT_HINT),J&&te.push(J);let ne=te.join(`
|
|
2596
|
+
`);if(!F&&!B&&!H&&!q)return textResult(ne);let ae={};return F&&(ae.previewUrl=F.url,ae.previewUrlSource=F.source),B&&(ae.warning=buildPreviewAttachWarning(F)),q&&(ae.summary=q),textPlusStructured(ne,ae)})}const DESCRIPTION$21=[`[Requires: Hocuspocus server] Find all pages that link to a given page.`,`Returns source page names, resolved titles, and context snippets as JSON.`,``,`**Parameters:**`,'- `docName` — Target page docName, typically without extension (for example, "articles/project-alpha"). A trailing `.md` or `.mdx` is stripped automatically.'].join(`
|
|
2597
2597
|
`);function register$21(e,t){e.registerTool(`get_backlinks`,{description:DESCRIPTION$21,inputSchema:{docName:string$2().describe(`Target page docName`),cwd:string$2().optional().describe(ROUTED_CWD_DESCRIPTION)}},async e=>{let S=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!S.ok)return textResult(`Error: ${S.error}`,!0);let{cwd:w,url:E}=S;if(!E)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let D=normalizeDocName(e.docName);if(!D.ok)return textResult(D.error,!0);let O=await httpGet(E,`/api/backlinks?docName=${encodeURIComponent(D.docName)}`);if(!O.ok)return textResult(`Error: ${O.error}`,!0);let{ok:k,...j}=O,F=j,{resolve:L,ui:B}=await buildListResolver(t,w),H=(F.backlinks??[]).map(e=>{let t=typeof e.source==`string`?e.source:null,S=t?L(t):null;return{...e,previewUrl:S?.url??null,...S?{previewUrlSource:S.source}:{}}}),q={...F,backlinks:H,ui:B,cwd:w};return textPlusStructured(JSON.stringify(q,null,2),q)})}const ID_CARDINALITY_CAP=32,DESCRIPTION$20=["[Operates on registry data; no running OK server required] Return full per-entry details for the canonical components an agent picked from the inventory rendered in the `write_document` / `edit_document` tool descriptions.",``,"Each entry carries: literal source-form `example` (copy-pasteable) + form-aware `params` (every prop, with `type` / `values?` / `required` / `defaultValue?` / `description`). Unmatched ids surface in `notFound` rather than failing the call.",``,`**Parameters:**`,`- \`ids\` — Array of canonical ids picked from the write-tool inventory (e.g. \`["Callout", "Tabs"]\`). Max ${ID_CARDINALITY_CAP} ids per call. Case-sensitive — must match the inventory exactly (\`Callout\` not \`callout\`; \`img\` not \`Image\`).`,"- `cwd` (optional) — Project root (see `cwd` description below)."].join(`
|
|
2598
2598
|
`),InputSchema$5={ids:array(string$2().min(1)).max(ID_CARDINALITY_CAP).describe(`Array of canonical ids to fetch. Max ${ID_CARDINALITY_CAP} ids per call. Empty array returns an empty components list.`),cwd:string$2().optional().describe(ROUTED_CWD_DESCRIPTION)},ParamSchema=object$1({name:string$2(),type:_enum([`string`,`boolean`,`number`,`enum`,`reactnode`]),values:array(string$2()).optional(),required:boolean$1(),defaultValue:union([string$2(),boolean$1(),number$1()]).optional(),description:string$2().optional(),omitOnDefault:literal(!0).optional(),advanced:literal(!0).optional(),language:_enum([`mermaid`,`latex`,`html`,`json`,`yaml`,`javascript`,`markdown`]).optional(),accept:array(string$2()).optional()}),ComponentEntrySchema=object$1({id:string$2(),displayName:string$2(),description:string$2(),kind:_enum([`jsx-block`,`jsx-void`]),example:string$2(),params:array(ParamSchema)}),OutputSchema$5=outputSchemaWithText({version:literal(1).describe(`Schema version stamp — bump for breaking shape changes.`),components:array(ComponentEntrySchema).describe(`Full per-entry details for ids that matched.`),notFound:array(string$2()).describe(`Ids that did not match any canonical descriptor.`)});function register$20(e,t){e.registerTool(`get_components`,{description:DESCRIPTION$20,inputSchema:InputSchema$5,outputSchema:OutputSchema$5,annotations:{readOnlyHint:!0,idempotentHint:!0}},async e=>{e.cwd;let t=getAgentCanonicalDescriptors(),S=new Map(t.map(e=>[e.name,e])),w=[],E=[],D=new Set;for(let t of e.ids){if(D.has(t))continue;D.add(t);let e=S.get(t);if(e===void 0){E.push(t);continue}w.push(projectFull(e))}let O={version:1,components:w,notFound:E};return textPlusStructured(JSON.stringify(O,null,2),O)})}const DESCRIPTION$19=[`[Operates on disk; no running OK server required] Read the effective merged Open Knowledge config (defaults → user → project).`,``,`Use this when you need to inspect the config mid-session — e.g., after a write that may have changed disk state, or to re-confirm the value of a field before reading it again.`,``,"Read returns the FULL merged config or a sub-tree when `path` is provided. There is no allowlist on reads — every field is readable.",``,"Note: the `server.*`, `mcp.*`, `github.*`, and `preview.*` config sub-trees were removed; their values are now built-in constants in `@inkeep/open-knowledge-core` (or hardcoded behavior, in the case of `preview.*`). Reading those paths returns `exists: false`.",``,`**Parameters:**`,'- `path` (optional) — Dotted-segments array. `["content"]` returns the content sub-tree; `["appearance", "theme"]` returns just that leaf. Omit for full config.',"- `cwd` (optional) — Project root (see `cwd` description below)."].join(`
|
|
2599
2599
|
`),InputSchema$4={path:array(string$2()).optional().describe(`Dotted path as array of segments (e.g. ["appearance","theme"]). Omit to return the full merged config.`),cwd:string$2().optional().describe(ROUTED_CWD_DESCRIPTION)},OutputSchema$4=outputSchemaWithText({value:unknown$2().describe(`Resolved config value at the requested path (or full config).`),exists:boolean$1().optional().describe('Whether the requested path resolved to a value. `false` distinguishes "path absent" from "path explicitly set to null"; absent on full-config reads.'),path:array(string$2()).optional().describe(`Echo of the requested dotted path (empty when reading the full config).`)});function readConfigPath(e,t){let S=e;for(let e of t){if(typeof S!=`object`||!S)return;S=S[e]}return S}function register$19(e,t){e.registerTool(`get_config`,{description:DESCRIPTION$19,inputSchema:InputSchema$4,outputSchema:OutputSchema$4,annotations:{readOnlyHint:!0,idempotentHint:!0}},async e=>{let S=await resolveProjectConfigContext(t.resolveCwd,t.config,e.cwd);if(!S.ok)return{isError:!0,content:[{type:`text`,text:`Error: ${S.error}`}]};let w=e.path??[],E=w.length>0?readConfigPath(S.config,w):S.config;return w.length>0&&E===void 0?textPlusStructured(`(no value at ${w.join(`.`)})`,{value:null,exists:!1,path:w}):textPlusStructured(JSON.stringify(E,null,2),{value:E,exists:!0,path:w})})}const DESCRIPTION$18=[`[Requires: Hocuspocus server] Find missing internal page targets across the corpus.`,`Returns grouped dead links keyed by missing target with source-doc rows as JSON.`,``,`**Parameters:**`,"- `sourceDocNames` (optional) — Referring source docs to narrow the audit with OR semantics"].join(`
|
|
@@ -3051,15 +3051,15 @@ In headless mode, write the recap into the research article's "Further reading"
|
|
|
3051
3051
|
`);function register$7(e,t){e.registerTool(`research`,{description:DESCRIPTION$7,inputSchema:{topic:string$2().describe(`The topic, question, or anchor URL to research`),cwd:string$2().optional().describe(ROUTED_CWD_DESCRIPTION)}},buildWorkflowHandler(`research`,t,`topic`,buildBody))}const DESCRIPTION$6=[`[Requires: Hocuspocus server] Restore a document to a historical version via the CRDT layer.`,`The restore is append-only — it creates a new version with the old content,`,`preserving all history. All connected editors see the change in real-time.`,``,`**Parameters:**`,"- `docName` — Document name to restore, typically without extension. A trailing `.md` or `.mdx` is stripped automatically.","- `commitSha` — The 40-character SHA of the shadow repo commit to restore to."," Use `get_history` to find available versions.",'- `summary` — Optional one-line user-outcome description (≤80 chars). Appears as a bullet in the timeline. If omitted, a default like "Restored to <sha-short>" is generated. Provide your own summary to explain the why. Avoid including secrets or PII — summaries are persisted to git history.'].join(`
|
|
3052
3052
|
`);function register$6(e,t){e.registerTool(`rollback_to_version`,{description:DESCRIPTION$6,inputSchema:{docName:string$2().describe(`Document name to restore`),commitSha:string$2().length(40).regex(/^[0-9a-f]+$/i).describe(`40-character commit SHA from the shadow repo timeline`),summary:summaryArgSchema.describe(`Optional one-line user-outcome description (≤80 chars). Defaults to "Restored to <sha-short>" when omitted. Appears as a bullet in the timeline.`),cwd:string$2().optional().describe(ROUTED_CWD_DESCRIPTION)}},async e=>{let S=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!S.ok)return textResult(`Error: ${S.error}`,!0);let{cwd:w,url:E}=S;if(!E)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let D=normalizeDocName(e.docName);if(!D.ok)return textResult(D.error,!0);let O=D.docName,k=await httpGet(E,`/api/history/${e.commitSha}?docName=${encodeURIComponent(O)}`);if(!k.ok)return textResult(`Error: ${k.error??`Version not found`}`,!0);let j=t.identityRef?.current,F=await httpPost(E,`/api/rollback`,{docName:O,commitSha:e.commitSha,...e.summary===void 0?{}:{summary:e.summary},...j?{agentId:j.connectionId,agentName:j.displayName,clientName:j.clientInfo?.name,colorSeed:j.colorSeed}:{}});if(!F.ok)return textResult(`Error: ${F.error}`,!0);let L=F.summary&&typeof F.summary==`object`?F.summary:void 0,B=typeof L?.hint==`string`?L.hint:void 0,H=[`Restored "${O}" to version ${e.commitSha.slice(0,8)} (${k.author}, ${k.timestamp}). The change has been applied to all connected editors.`];B&&H.push(B);let q=await resolvePreviewUrlForTool(O,{config:t.config,resolveCwd:t.resolveCwd},w);return textPlusStructured(H.join(`
|
|
3053
3053
|
`),{previewUrl:q?.url??null,...q?{previewUrlSource:q.source}:{},...L?{summary:L}:{}})})}const DESCRIPTION$5=[`[Requires: Hocuspocus server] Save a version checkpoint of all documents.`,`Creates a checkpoint commit in the shadow repo and project repo,`,`preserving the current state of all documents. The checkpoint can later`,"be found via `get_history` and restored via `rollback_to_version`."].join(`
|
|
3054
|
-
`);function register$5(e,t,S,w,E){e.registerTool(`save_version`,{description:DESCRIPTION$5,inputSchema:{cwd:string$2().optional().describe(ROUTED_CWD_DESCRIPTION)}},async(e={})=>{let D=await resolveProjectServerContext(w,t,S,e.cwd);if(!D.ok)return textResult(`Error: ${D.error}`,!0);if(!D.url)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let{url:O}=D,k=E?.current,j=await httpPost(O,`/api/save-version`,
|
|
3054
|
+
`);function register$5(e,t,S,w,E){e.registerTool(`save_version`,{description:DESCRIPTION$5,inputSchema:{cwd:string$2().optional().describe(ROUTED_CWD_DESCRIPTION)}},async(e={})=>{let D=await resolveProjectServerContext(w,t,S,e.cwd);if(!D.ok)return textResult(`Error: ${D.error}`,!0);if(!D.url)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let{url:O}=D,k=E?.current,j=await httpPost(O,`/api/save-version`,k?{writers:[{id:`agent-${k.connectionId}`,name:k.displayName,email:`agent-${k.connectionId}@openknowledge.local`}]}:{});return j.ok?textPlusStructured(`Checkpoint saved. Checkpoint ref: ${j.checkpointRef}`,{checkpointRef:j.checkpointRef,previewUrl:null}):textResult(`Error: ${j.error}`,!0)})}const DESCRIPTION$4=["Find the most relevant pages for a query (ranked: title boost + body BM25 + recency). For literal-string matching across every line, use `grep`.",``,"Same engine and ranking the cmd-K palette uses. Returns a sorted list of page (and folder, with `omnibar` intent) hits with score signals plus a body snippet per page.",``,`**Use when:**`,`- Hunting for the canonical page on a topic`,`- Locating a doc by partial title or path segments`,`- Picking the best entry point before reading`,``,`**Parameters:**`,"- `query` — Search query (free-form; tokenized across title, name, path segments, and optionally body content).","- `intent` (optional) — `'omnibar'` searches title/path/folders only (fast); `'full_text'` includes body content. Default `'full_text'`.","- `scopes` (optional) — Override the result scope. Members: `'page'`, `'folder'`, `'content'`. Defaults derive from `intent`.","- `limit` (optional) — Max rows; default 20, max 100.","- `cwd` (optional) — Project root the query runs against.",``,"**Server requirement:** the Hocuspocus server must be running (`open-knowledge start`). If not, this tool returns a recovery hint; use `grep` as a server-free fallback."].join(`
|
|
3055
3055
|
`),InputSchema$2={query:string$2().describe(`Search query — title, path, or body terms.`),intent:_enum([`omnibar`,`full_text`]).optional().describe(`'omnibar' for title/path/folder only (fast); 'full_text' includes body content. Default 'full_text'.`),scopes:array(_enum([`page`,`folder`,`content`])).optional().describe(`Override the default scope set. Members: 'page', 'folder', 'content'. Defaults derive from intent.`),limit:number$1().int().min(1).max(100).optional().describe(`Max rows; default 20, max 100.`),cwd:string$2().optional().describe(ROUTED_CWD_DESCRIPTION)},SearchResultRowSchema=object$1({kind:_enum([`page`,`folder`]),path:string$2(),docName:string$2(),title:string$2().nullable(),score:number$1(),signals:object$1({lexical:number$1(),fullText:number$1(),recency:number$1()}),snippet:string$2().optional(),previewUrl:string$2().nullable(),previewUrlSource:_enum(PREVIEW_URL_SOURCES).optional()}),OutputSchema$2=outputSchemaWithText({cwd:string$2(),query:string$2(),intent:string$2(),resultCount:number$1().int(),results:array(SearchResultRowSchema),elapsedMs:number$1().nullable(),ui:object$1({baseUrl:string$2().nullable(),port:number$1().nullable()})});function isSearchKind(e){return e===`page`||e===`folder`}function normalizeSignals(e){return{lexical:typeof e?.lexical==`number`?e.lexical:0,fullText:typeof e?.fullText==`number`?e.fullText:0,recency:typeof e?.recency==`number`?e.recency:0}}function formatResultsBlock(e){if(e.length===0)return``;let t=[];for(let S of e){let e=S.title?.trim()||S.path;t.push(`### ${e} (${S.path})`),t.push(`Score ${S.score.toFixed(2)} — kind: ${S.kind}`),S.snippet&&t.push(S.snippet),t.push(``)}return t.join(`
|
|
3056
3056
|
`)}function register$4(e,t){e.registerTool(`search`,{description:DESCRIPTION$4,inputSchema:InputSchema$2,outputSchema:OutputSchema$2,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0}},async e=>{try{let S=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!S.ok)return textResult(`Error: ${S.error}`,!0);let{cwd:w,config:E,url:D}=S;if(!D)return textResult(`${HOCUSPOCUS_NOT_RUNNING_ERROR}\nFor server-free literal-string search, use \`grep\` instead — it walks the filesystem and does not need Hocuspocus.`,!0);let O=e.intent??`full_text`,k=e.limit??20,j={query:e.query,intent:O,limit:k};e.scopes&&(j.scopes=e.scopes);let F=await httpPost(D,`/api/search`,j);if(!F.ok)return textResult(`Error: ${F.error}`,!0);let{resolve:L,ui:B}=await buildListResolver({config:E,resolveCwd:async()=>w},w),H=(F.results??[]).flatMap(e=>{if(!isSearchKind(e.kind)||typeof e.path!=`string`)return[];let t=docNameFromPath(e.path),S=L(t);return[{kind:e.kind,path:e.path,docName:t,title:e.title??null,score:typeof e.score==`number`?e.score:0,signals:normalizeSignals(e.signals),...e.snippet?{snippet:e.snippet}:{},previewUrl:S?.url??null,...S?{previewUrlSource:S.source}:{}}]}),q={cwd:w,query:e.query,intent:O,resultCount:H.length,results:H,elapsedMs:typeof F.elapsedMs==`number`?F.elapsedMs:null,ui:B},J=`## Search results for "${e.query}" (${H.length} hit${H.length===1?``:`s`}, intent: ${O})`;return textPlusStructured(H.length===0?`No matches for "${e.query}".`:`${J}\n\n${formatResultsBlock(H)}`,q)}catch(e){return textResult(`Error: ${e instanceof Error?e.message:String(e)}`,!0)}})}const DESCRIPTION$3=["[Operates on disk; no running OK server required] Upsert one or more folder rules — writes nested `<folder>/.ok/frontmatter.yml` files.",``,"Folder rules apply default frontmatter to every doc inside `<folder>/` (and its descendants via cascade). Open shape — any YAML-representable key is accepted. Common keys: `title`, `description`, `tags` (the well-known three) plus arbitrary additions like `status`, `team`, `owners`, `review_cycle`. Use this tool to add a new rule, replace an existing one keyed by `match`, or rename via `new_match`.",``,`**Cascade merge semantics (D6 generalized):** scalars (string / number / boolean / null) replace last-wins along the leaf → root walk; arrays union-and-dedup with first-occurrence preserved; objects replace last-wins.`,``,'Each `match` glob must resolve to a SINGLE target folder by walking leading literal segments — `"specs/**"` writes `specs/.ok/frontmatter.yml`. Multi-folder globs (e.g. `"specs/*/evidence/**"`, where the literal `evidence` follows `*`) are rejected with `MULTI_FOLDER_GLOB`; split into per-folder rules instead.',``,"Always pass an array — even for a single rule. Validation runs against every rule first; if any fails (e.g. `MULTI_FOLDER_GLOB`, `PATH_ESCAPE`), NO rules are applied to disk. Filesystem-level errors during the write phase (disk full, permissions) may leave a partial result — the error response includes `partiallyApplied` listing which rules already landed.",``,'**To remove a rule**, pass an empty `frontmatter: {}` — the merge collapses, the file is deleted, and `<folder>/.ok/` is auto-cleaned if no other tenant remains. To clear a SPECIFIC key while keeping others, set that key to `null` / `""` / `[]` in the patch.',``,`**Parameters:**`,"- `rules` — Array of `{match, frontmatter, new_match?}`.",' - `match` — Glob pattern that identifies the target folder (e.g. `"specs/**"`, `"meetings/prep-notes/**"`). Required.'," - `frontmatter` — Open `Record<string, unknown>` of key/value defaults. Common: `{title?, description?, tags?: string[]}`. Any other key persists too (`status`, `team`, etc.)."," - `new_match` — If set, move the rule from `match` to this new glob (deletes the old folder's frontmatter.yml + auto-cleans).","- `cwd` (optional) — Project root."].join(`
|
|
3057
3057
|
`),FolderRuleUpsertInputSchema=object$1({match:string$2().min(1).describe(`Glob pattern (e.g. "specs/**", "meetings/prep-notes/**") that identifies the target folder.`),frontmatter:record(string$2(),unknown$2()).refine(e=>!(`title`in e&&e.title!==null&&typeof e.title!=`string`||`description`in e&&e.description!==null&&typeof e.description!=`string`||`tags`in e&&e.tags!==null&&!Array.isArray(e.tags)),{message:"Well-known keys must match expected types when present: `title` (string|null), `description` (string|null), `tags` (string[]|null)."}).describe('Default frontmatter to apply to matched docs. Open shape — any YAML-representable key. Common: `{title?, description?, tags?: string[]}`; arbitrary keys (`status`, `team`, `owners`, `review_cycle`, …) also persist. Pass `{}` to remove the rule (auto-cleans `.ok/` if empty). Pass `key: null | "" | []` to clear that specific key while keeping others.'),new_match:string$2().min(1).optional().describe("If set, move the rule from `match` to this new folder (deletes the old folder's frontmatter.yml + auto-cleans).")}),InputSchema$1={rules:array(FolderRuleUpsertInputSchema).min(1).describe("One or more folder rules to upsert. Always an array — pass `[{...}]` for a single rule."),cwd:string$2().optional().describe(ROUTED_CWD_DESCRIPTION)},AppliedEntrySchema=object$1({match:string$2(),path:string$2(),action:_enum([`written`,`deleted`])}),SuccessOutputSchema=object$1({ok:literal(!0),applied:array(AppliedEntrySchema)}),ErrorOutputSchema=object$1({ok:literal(!1),error:object$1({code:_enum([`MULTI_FOLDER_GLOB`,`PATH_ESCAPE`,`BAD_PROJECT_DIR`,`WRITE_ERROR`]),message:string$2(),rule:string$2().optional()}),partiallyApplied:array(AppliedEntrySchema).optional()}),OutputSchema$1=outputSchemaWithText({result:union([SuccessOutputSchema,ErrorOutputSchema])});function register$3(e,t){e.registerTool(`set_folder_rule`,{description:DESCRIPTION$3,inputSchema:InputSchema$1,outputSchema:OutputSchema$1,annotations:{readOnlyHint:!1,idempotentHint:!0,destructiveHint:!1}},async e=>{let S=await resolveProjectConfigContext(t.resolveCwd,t.config,e.cwd);if(!S.ok)return{isError:!0,content:[{type:`text`,text:`Error: ${S.error}`}]};let{cwd:w}=S,E=applyNestedFolderRulesUpsert({projectDir:w,rules:e.rules.map(e=>({match:e.match,frontmatter:e.frontmatter??{},...e.new_match===void 0?{}:{new_match:e.new_match}}))});return E.ok?textPlusStructured(JSON.stringify(E,null,2),{result:E}):{isError:!0,structuredContent:{result:E},content:[{type:`text`,text:`${E.error.code}: ${E.error.message}`}]}})}const DESCRIPTION$2=[`[Requires: Hocuspocus server] Find missing link candidates for a target page.`,"Returns JSON with structure: `{ target: { docName, title, aliases }, mentions: [{ source, excerpt, offset }], truncated }`.","Each mention includes an `offset` you can pass to `edit_document` for precision patching.","When `truncated` is true, the scan hit its time budget before reading every admitted document.",``,`**Parameters:**`,'- `docName` — Target page docName, typically without extension (for example, "articles/project-alpha"). A trailing `.md` or `.mdx` is stripped automatically.'].join(`
|
|
3058
3058
|
`);function register$2(e,t){e.registerTool(`suggest_links`,{description:DESCRIPTION$2,inputSchema:{docName:string$2().describe(`Target page docName`),cwd:string$2().optional().describe(ROUTED_CWD_DESCRIPTION)}},async e=>{let S=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!S.ok)return textResult(`Error: ${S.error}`,!0);let{cwd:w,url:E}=S;if(!E)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let D=normalizeDocName(e.docName);if(!D.ok)return textResult(D.error,!0);let O=await httpGet(E,`/api/suggest-links?docName=${encodeURIComponent(D.docName)}`);if(!O.ok)return textResult(`Error: ${O.error}`,!0);let{ok:k,...j}=O,F=await resolvePreviewUrlForTool(D.docName,{config:t.config,resolveCwd:t.resolveCwd},w);return textPlusStructured(JSON.stringify(j,null,2),{...j,previewUrl:F?.url??null,...F?{previewUrlSource:F.source}:{}})})}const DESCRIPTION$1=`${[`[Requires: Hocuspocus server] Write markdown content to a document via the CRDT layer.`,`Content is applied through Hocuspocus and propagated to all connected editors in real-time.`,``,'**Frontmatter.** The markdown payload may include a YAML frontmatter block (`---`-fenced). To change frontmatter, call this tool with `position: "replace"` and a payload that includes the new YAML block — per-property MCP editing is currently unavailable. `edit_document` rejects frontmatter-intersecting find/replace calls.',``,'**Link liberally.** Every noun-phrase that names another document in this knowledge base should be a `[[wiki-link]]`, not plain prose. Backlinks are the primary navigation surface — underlinked documents become islands. Redlinks (links to pages that don\'t exist yet) are fine; they signal "this should exist." Prefer `[[Page Name]]` over Markdown `[text](./page.md)` — only wiki-links participate in the backlinks index.',``,"**Templates.** When creating a new doc, pass `template: \"<name>\"` to instantiate from a folder-scoped template. The name resolves against `templates_available` for the doc's parent folder (leaf → root walk-up; check `list_documents({ dir, depth: 1 })` to see the menu). The template's body + frontmatter become the doc's starting content; folder cascade merges naturally at read time. Templates scoped to a descendant subfolder are rejected for parent-folder targets. **`template` and `markdown` are mutually exclusive** — pass exactly one. To start from the template body and then customize, instantiate via `template` first, then call `edit_document` to fill placeholders.",``,`**Parameters:**`,'- `docName` — Document name, typically without extension (e.g., "my-doc" or "notes/meeting"). A trailing `.md` or `.mdx` is stripped automatically. New documents are created as `.md` by default; to create a `.mdx` file, first place it on disk, then use this tool for edits.',"- `markdown` — Markdown content to write. Required unless `template` is set (mutually exclusive — pass exactly one).","- `template` (optional) — Template name resolved against the parent folder's `templates_available`. The template body becomes the new doc verbatim. Cannot be combined with `markdown`.",'- `position` — Where to insert: "append", "prepend", or "replace". When `template` is set, `position` is forced to "replace".','- `summary` — Optional one-line user-outcome description of this edit (≤80 chars). Appears as a bullet in the document timeline so readers can scan intent without opening every diff. Prefer outcome phrasing ("Fixed token-refresh race") over structural ("Added 3 lines"). Avoid including secrets or PII — summaries are persisted to git history.'].join(`
|
|
3059
|
-
`)}\n${renderInventoryFooter()}`;function register$1(e,t){e.registerTool(`write_document`,{description:DESCRIPTION$1,inputSchema:{docName:string$2().describe(`Document name to write to`),markdown:string$2().optional().describe("Markdown content to write. Optional when `template` is set — the template body is used."),template:string$2().min(1).optional().describe(`Template name resolved against parent folder's templates_available (leaf → root walk-up; closest-wins on collision). See list_documents({ dir, depth: 1 }) to inspect the menu.`),position:_enum([`append`,`prepend`,`replace`]).describe(`Where to insert the content`),summary:summaryArgSchema,cwd:string$2().optional().describe(ROUTED_CWD_DESCRIPTION)}},async e=>{let S=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!S.ok)return textResult(`Error: ${S.error}`,!0);let{cwd:w,url:E}=S;if(!E)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let D=normalizeDocName(e.docName);if(!D.ok)return textResult(D.error,!0);let O=t.identityRef?.current;if(e.template===void 0&&e.markdown===void 0)return textResult("Error: either `markdown` or `template` must be provided. Omitting both would write empty content.",!0);if(e.template!==void 0&&e.markdown!==void 0)return textResult("Error: TEMPLATE_AND_MARKDOWN_BOTH_SET — `template` and `markdown` are mutually exclusive. Pass one. The template body becomes the new doc verbatim; fill placeholders via subsequent `edit_document` calls.",!0);let k=e.markdown??``,j=e.position;if(e.template!==void 0){let t=parentFolderOf(D.docName),S=resolveTemplatesAvailable(w,t,{depth:1}),E=S.find(t=>t.name===e.template);if(!E)return textResult(`Error: template "${e.template}" not found for folder "${t||`.`}". Available: ${S.length===0?`(none)`:S.map(e=>`${e.name} [${e.scope}]`).join(`, `)}. Templates are resolved by walk-up; check list_documents({ dir, depth: 1 }) at the parent folder to see the menu.`,!0);let F;try{F=readFileSync(resolve(w,E.path),`utf-8`)}catch(e){return textResult(`Error: failed to read template at ${E.path}: ${e.message}`,!0)}k=applySubstitution(F,{date:todayIsoUtc(),user:O?.displayName??``}),j=`replace`}let F=await httpPost(E,`/api/agent-write-md`,{docName:D.docName,markdown:k,position:j,...e.summary===void 0?{}:{summary:e.summary},...O?{agentId:O.connectionId,agentName:O.displayName,clientName:O.clientInfo?.name,colorSeed:O.colorSeed}:{}});if(!F.ok)return textResult(`Error: ${F.error}`,!0);let L=resolveLockDir(w),B=resolvePreviewUrl(D.docName,{lockDir:L}),H=typeof F.subscriberCount==`number`?F.subscriberCount:void 0,q=(typeof F.systemSubscriberCount==`number`?F.systemSubscriberCount:void 0)===0,J=H===0,Y=Array.isArray(F.hints)?F.hints:void 0,ee=F.summary&&typeof F.summary==`object`?F.summary:void 0,te=typeof ee?.hint==`string`?ee.hint:void 0,ne=[e.template===void 0?`Written successfully (${j}).`:`Written successfully (instantiated from template "${e.template}").`];if(B&&ne.push(`Preview: ${B.url}`),q&&ne.push(B?`Open ${B.url} in your preview browser
|
|
3060
|
-
`);if(!B&&!q&&!J&&!Y&&!ee)return textResult(ae);let oe={};return B&&(oe.previewUrl=B.url,oe.previewUrlSource=B.source),q&&(oe.warning=
|
|
3059
|
+
`)}\n${renderInventoryFooter()}`;function register$1(e,t){e.registerTool(`write_document`,{description:DESCRIPTION$1,inputSchema:{docName:string$2().describe(`Document name to write to`),markdown:string$2().optional().describe("Markdown content to write. Optional when `template` is set — the template body is used."),template:string$2().min(1).optional().describe(`Template name resolved against parent folder's templates_available (leaf → root walk-up; closest-wins on collision). See list_documents({ dir, depth: 1 }) to inspect the menu.`),position:_enum([`append`,`prepend`,`replace`]).describe(`Where to insert the content`),summary:summaryArgSchema,cwd:string$2().optional().describe(ROUTED_CWD_DESCRIPTION)}},async e=>{let S=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!S.ok)return textResult(`Error: ${S.error}`,!0);let{cwd:w,url:E}=S;if(!E)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let D=normalizeDocName(e.docName);if(!D.ok)return textResult(D.error,!0);let O=t.identityRef?.current;if(e.template===void 0&&e.markdown===void 0)return textResult("Error: either `markdown` or `template` must be provided. Omitting both would write empty content.",!0);if(e.template!==void 0&&e.markdown!==void 0)return textResult("Error: TEMPLATE_AND_MARKDOWN_BOTH_SET — `template` and `markdown` are mutually exclusive. Pass one. The template body becomes the new doc verbatim; fill placeholders via subsequent `edit_document` calls.",!0);let k=e.markdown??``,j=e.position;if(e.template!==void 0){let t=parentFolderOf(D.docName),S=resolveTemplatesAvailable(w,t,{depth:1}),E=S.find(t=>t.name===e.template);if(!E)return textResult(`Error: template "${e.template}" not found for folder "${t||`.`}". Available: ${S.length===0?`(none)`:S.map(e=>`${e.name} [${e.scope}]`).join(`, `)}. Templates are resolved by walk-up; check list_documents({ dir, depth: 1 }) at the parent folder to see the menu.`,!0);let F;try{F=readFileSync(resolve(w,E.path),`utf-8`)}catch(e){return textResult(`Error: failed to read template at ${E.path}: ${e.message}`,!0)}k=applySubstitution(F,{date:todayIsoUtc(),user:O?.displayName??``}),j=`replace`}let F=await httpPost(E,`/api/agent-write-md`,{docName:D.docName,markdown:k,position:j,...e.summary===void 0?{}:{summary:e.summary},...O?{agentId:O.connectionId,agentName:O.displayName,clientName:O.clientInfo?.name,colorSeed:O.colorSeed}:{}});if(!F.ok)return textResult(`Error: ${F.error}`,!0);let L=resolveLockDir(w),B=resolvePreviewUrl(D.docName,{lockDir:L}),H=typeof F.subscriberCount==`number`?F.subscriberCount:void 0,q=(typeof F.systemSubscriberCount==`number`?F.systemSubscriberCount:void 0)===0,J=H===0,Y=Array.isArray(F.hints)?F.hints:void 0,ee=F.summary&&typeof F.summary==`object`?F.summary:void 0,te=typeof ee?.hint==`string`?ee.hint:void 0,ne=[e.template===void 0?`Written successfully (${j}).`:`Written successfully (instantiated from template "${e.template}").`];if(B&&ne.push(`Preview: ${B.url}`),q&&ne.push(B?`Open ${B.url} in your preview browser.`:START_UI_TEXT_HINT),te&&ne.push(te),Y)for(let e of Y)e.message&&ne.push(e.message);let ae=ne.join(`
|
|
3060
|
+
`);if(!B&&!q&&!J&&!Y&&!ee)return textResult(ae);let oe={};return B&&(oe.previewUrl=B.url,oe.previewUrlSource=B.source),q&&(oe.warning=buildPreviewAttachWarning(B)),Y&&(oe.hints=Y),ee&&(oe.summary=ee),textPlusStructured(ae,oe)})}const DESCRIPTION=[`[Operates on disk; no running OK server required] Create or update a template.`,``,"Templates are markdown starter shapes that agents pick from when creating a new doc — `write_document({ template: <name> })` resolves the name against the folder cascade and instantiates the body + frontmatter.",``,'Templates live at `<folder>/.ok/templates/<name>.md`. The `folder` argument selects which project folder owns it (project-wide via `folder: ""`, or scoped to a subfolder).',``,"**`title` is required** in the frontmatter — it is the menu surface agents pick from. Missing or empty title returns `TEMPLATE_TITLE_REQUIRED`. `description` is recommended (soft warning when absent) — it disambiguates similarly-named templates.",``,"**Substitution allowlist.** The body MAY contain `{{date}}` (today, ISO-8601) and `{{user}}` (calling principal display name). Any other `{{...}}` token is rejected at write time with `TEMPLATE_UNKNOWN_VARIABLE`. Substitution happens at instantiation time (when `write_document({ template })` materializes the doc), not at template-write time — templates on disk show the raw `{{date}}` token.",``,`**Parameters:**`,'- `folder` — Project-root-relative folder (e.g. `"meetings"`, `"meetings/prep-notes"`). Empty / `.` means project root.',"- `name` — Template filename without `.md`. Letters, digits, `_`, `-` only.","- `body` — Markdown body. May use `{{date}}` / `{{user}}` substitution tokens. Other placeholder text in `{shape}` form (e.g. `{Meeting Title}`) is LITERAL — agents fill it in via subsequent `edit_document` calls.","- `frontmatter` — `{title (required), description?, tags?: string[]}` for the template menu."].join(`
|
|
3061
3061
|
`),InputSchema={folder:string$2().describe("Project-root-relative folder. Empty / `.` means project root."),name:string$2().min(1).regex(/^[A-Za-z0-9_-]+$/,"Template name must use letters, digits, `_`, or `-` only (no slashes, dots, or spaces).").describe("Template filename without `.md` extension."),body:string$2().describe(`Markdown body for the template.`),frontmatter:object$1({title:string$2().min(1,"Template `title` is required — it is the menu surface agents pick from.").describe(`Required. The menu surface agents pick from. Empty / missing returns TEMPLATE_TITLE_REQUIRED.`),description:string$2().optional().describe(`Recommended. Disambiguates similarly-named templates. Soft warning when absent.`),tags:array(string$2()).optional().describe(`Optional. Concatenated with cascade tags at instantiation time.`)}).describe("Template menu metadata. `title` MUST be present (hard error if missing). `description` SHOULD be present (warning)."),cwd:string$2().optional().describe(ROUTED_CWD_DESCRIPTION)},OutputSchema=outputSchemaWithText({result:union([object$1({ok:literal(!0),path:string$2(),created:boolean$1(),warnings:array(string$2())}),object$1({ok:literal(!1),error:object$1({code:string$2(),message:string$2()})})])});function register(e,t){e.registerTool(`write_template`,{description:DESCRIPTION,inputSchema:object$1(InputSchema).strict(),outputSchema:OutputSchema,annotations:{readOnlyHint:!1,idempotentHint:!0,destructiveHint:!1}},async e=>{let S=await resolveProjectConfigContext(t.resolveCwd,t.config,e.cwd);if(!S.ok)return{isError:!0,content:[{type:`text`,text:`Error: ${S.error}`}]};let{cwd:w}=S,E=applyTemplateWrite({projectDir:w,folder:e.folder,name:e.name,body:e.body,frontmatter:e.frontmatter});if(!E.ok)return{isError:!0,structuredContent:{result:E},content:[{type:`text`,text:`${E.error.code}: ${E.error.message}`}]};let D=[`${E.created?`Created`:`Updated`} template at ${E.path}`];if(E.warnings.length>0){D.push(``,`Warnings:`);for(let e of E.warnings)D.push(` - ${e}`)}return textPlusStructured(D.join(`
|
|
3062
|
-
`),{result:E})})}function registerAllTools(e,t){let S=t.logger,w=createLoggedServer(e,{logger:t.logger,identityRef:t.identityRef}),E=e=>async w=>{try{let E=await t.resolveCwd(w);return(getCurrentMcpLogger()??S)?.debug(`tool cwd resolved`,{tool:e,cwd:E,...w?{explicit:w}:{}}),E}catch(t){throw(getCurrentMcpLogger()??S)?.warn(`tool call failed`,{tool:e,error:t instanceof Error?t.message:String(t),...w?{explicit:w}:{}}),t}};register$23(w,{resolveCwd:E(`exec`),serverUrl:t.serverUrl,config:t.config}),register$12(w,{config:t.config,resolveCwd:E(`ingest`)}),register$7(w,{config:t.config,resolveCwd:E(`research`)}),register$28(w,{config:t.config,resolveCwd:E(`consolidate`)}),register$25(w,{config:t.config,resolveCwd:E(`discover`)}),register$10(w,{resolveCwd:E(`read_document`),config:t.config,serverUrl:t.serverUrl}),register$4(w,{resolveCwd:E(`search`),config:t.config,serverUrl:t.serverUrl}),register$13(w,{resolveCwd:E(`grep`),config:t.config,serverUrl:t.serverUrl}),register$2(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`suggest_links`)}),register$1(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`write_document`),identityRef:t.identityRef}),register$24(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`edit_document`),identityRef:t.identityRef}),register$27(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`delete_document`),identityRef:t.identityRef}),register$22(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`frontmatter_patch`),identityRef:t.identityRef}),register$9(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`rename_document`),identityRef:t.identityRef}),register$8(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`rename_folder`),identityRef:t.identityRef}),register$16(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`get_history`)}),register$5(w,t.config,t.serverUrl,E(`save_version`),t.identityRef),register$6(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`rollback_to_version`),identityRef:t.identityRef}),register$11(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`list_documents`)}),register$21(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`get_backlinks`)}),register$20(w,{resolveCwd:E(`get_components`),config:t.config}),register$17(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`get_forward_links`)}),register$14(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`get_orphans`)}),register$15(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`get_hubs`)}),register$18(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`get_dead_links`)}),register$19(w,{config:t.config,resolveCwd:E(`get_config`)}),register$3(w,{config:t.config,resolveCwd:E(`set_folder_rule`)}),register(w,{config:t.config,resolveCwd:E(`write_template`)}),register$26(w,{config:t.config,resolveCwd:E(`delete_template`)})}function firstHeader(e){return Array.isArray(e)?e[0]:e}function writePlain(e,t,S){e.writableEnded||(e.statusCode=t,e.setHeader(`Content-Type`,`text/plain; charset=utf-8`),e.end(S))}function createSessionServer(e,t,S){let w=e.config,E=new McpServer({name:MCP_SERVER_NAME,version:RUNTIME_VERSION},{instructions:buildInstructions(w.content)});installPrettyZodErrors(E);let D=S??randomUUID(),O={current:{connectionId:D,displayName:D,colorSeed:D}};E.server.oninitialized=()=>{let e=E.server.getClientVersion(),t=sanitizeClientName(e?.name,D);O.current={connectionId:D,clientInfo:e?{name:t,version:e.version}:void 0,displayName:t,colorSeed:t}};let k=e.projectDir??e.contentDir;return registerAllTools(E,{serverUrl:async()=>e.getServerUrl(),resolveCwd:async e=>{if(e===void 0)return k;let t=resolveWithinRoot(k,e);if(!t.ok)throw Error(`cwd "${e}" is not within the configured project root: ${t.reason}`);return t.abs},config:w,identityRef:O}),{server:E,transport:t}}function createMcpHttpHandler(e){let t=new Map,S=e.sessionTtlMs??1800*1e3,w=e.maxSessions??100;async function E(S,w){let E=t.get(S);if(!E)return;t.delete(S),E.ttlTimer!==void 0&&clearTimeout(E.ttlTimer);let D=await Promise.allSettled([E.server.close(),E.transport.close()]);for(let t of D)t.status===`rejected`&&e.log?.warn?.({err:t.reason,sessionId:S,reason:w},`MCP HTTP session close failed`);e.log?.info?.({sessionId:S,reason:w},`MCP HTTP session closed`)}function D(t,w){w.ttlTimer!==void 0&&clearTimeout(w.ttlTimer),w.ttlTimer=setTimeout(()=>{E(t,`ttl-expired`).catch(S=>{e.log?.warn?.({err:S,sessionId:t},`MCP HTTP session TTL cleanup failed`)})},S),w.ttlTimer.unref?.()}return{async handle(S,O){let k=firstHeader(S.headers[`mcp-session-id`]);if(k){let e=t.get(k);if(!e){writePlain(O,404,`MCP session not found`);return}D(k,e),await e.transport.handleRequest(S,O);return}if(S.method!==`POST`){writePlain(O,400,`Missing MCP session. Initialize with POST /mcp first.`);return}if(t.size>=w){e.log?.warn?.({activeSessions:t.size,maxSessions:w},`MCP HTTP session cap reached`),writePlain(O,503,`Too many active MCP sessions`);return}let j=firstHeader(S.headers[MCP_CONNECTION_ID_HEADER]),F=validateAgentId(j)??void 0;j!==void 0&&F===void 0&&e.log?.warn?.({headerLength:j.length},`MCP HTTP forwarded connectionId header failed validation; falling back to randomUUID`);let L=new StreamableHTTPServerTransport({sessionIdGenerator:()=>randomUUID(),enableJsonResponse:!0,onsessioninitialized:async S=>{try{let w=createSessionServer(e,L,F);await w.server.connect(L),t.set(S,w),D(S,w),e.log?.info?.({sessionId:S},`MCP HTTP session initialized`)}catch(w){throw t.delete(S),e.log?.error?.({err:w,sessionId:S},`MCP HTTP session initialization failed`),w}}});L.onerror=t=>{e.log?.warn?.({err:t},`MCP HTTP transport error`)},L.onclose=()=>{let t=L.sessionId;if(!t){e.log?.info?.({sessionId:t,reason:`transport-closed`},`MCP HTTP session closed`);return}E(t,`transport-closed`).catch(S=>{e.log?.warn?.({err:S,sessionId:t},`MCP HTTP transport-close cleanup failed`)})},await L.handleRequest(S,O)},async close(){let e=[...t.entries()];await Promise.allSettled(e.map(([e])=>E(e,`handler-close`)))}}}const DEFAULT_KEEPALIVE_GRACE_MS=1e4,MAX_COLLAB_MESSAGE_BYTES=1024*1024,MCP_CORS_HEADERS={"Access-Control-Allow-Methods":`GET, POST, DELETE, OPTIONS`,"Access-Control-Allow-Headers":`Content-Type, Authorization, traceparent, tracestate, baggage, mcp-session-id, mcp-protocol-version`,"Access-Control-Max-Age":`86400`};function mountMcpAndApi(e){let{httpServer:t,hocuspocus:S,mcpHttpHandler:w,log:E,sessionManager:D,agentFocusBroadcaster:O,agentPresenceBroadcaster:k,contentAssetMiddleware:j}=e,F=e.keepaliveGraceMs??DEFAULT_KEEPALIVE_GRACE_MS,L=new import_websocket_server$1.default({noServer:!0,maxPayload:MAX_COLLAB_MESSAGE_BYTES});L.on(`error`,e=>{E.error({err:e},`WebSocketServer error`)});let B=new Map,H=new Set,q=!1;return t.on(`request`,(e,t)=>{let D=e.url?.split(`?`)[0];if(w!==void 0&&D===`/mcp`){let S=e.headers.origin,D=Array.isArray(e.headers[`mcp-session-id`])?e.headers[`mcp-session-id`][0]:e.headers[`mcp-session-id`];if(!isLoopbackAddress(e.socket.remoteAddress)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback access required.`,{handler:`mcp`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`mcp`});return}if(S!==void 0&&!isAllowedApiOrigin(S)){errorResponse(t,403,`urn:ok:error:invalid-origin`,`Origin not allowed.`,{handler:`mcp`});return}S!==void 0&&(t.setHeader(`Access-Control-Allow-Origin`,S),t.setHeader(`Vary`,`Origin`));for(let[e,S]of Object.entries(MCP_CORS_HEADERS))t.setHeader(e,S);if(e.method===`OPTIONS`){t.writeHead(204),t.end();return}w.handle(e,t).catch(e=>{E.error({err:e,sessionId:D},`Unhandled MCP HTTP error`),!t.writableEnded&&!t.headersSent?errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`mcp`,cause:e}):t.writableEnded||t.end()});return}if(D?.startsWith(`/api/`)){S.hooks(`onRequest`,{request:e,response:t}).then(()=>{t.writableEnded||t.headersSent||errorResponse(t,404,`urn:ok:error:not-found`,`API endpoint not found.`,{handler:`mcp-mount`,detail:`No handler for ${e.method??`GET`} ${D}`})}).catch(e=>{E.error({err:e},`Unhandled onRequest error`),!t.writableEnded&&!t.headersSent?errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`mcp-mount`,cause:e}):t.writableEnded||t.end()});return}if(j!==void 0){try{j(e,t,()=>{t.writableEnded||t.headersSent||errorResponse(t,404,`urn:ok:error:not-found`,`Not found.`,{handler:`mcp-mount`,detail:`No handler for ${D??`/`}`})})}catch(e){E.error({err:e},`Unhandled content-asset middleware error`),!t.writableEnded&&!t.headersSent?errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`mcp-mount`,cause:e}):t.writableEnded||t.end()}return}errorResponse(t,404,`urn:ok:error:not-found`,`Not found.`,{handler:`mcp-mount`,detail:`The React UI is served by \`ok ui\` (run \`ok ui\` and check \`ui.lock.port\`). No handler for ${D??`/`}`})}),t.on(`upgrade`,(e,t,w)=>{if(e.url?.startsWith(`/collab/keepalive`)){if(!isLoopbackAddress(e.socket.remoteAddress)||!isAllowedWorkspaceHostHeader(e.headers.host)){t.destroy();return}t.on(`error`,e=>{handleCollabSocketError(e)||E.error({err:e},`MCP keepalive socket error`)}),L.handleUpgrade(e,t,w,t=>{let S=parseKeepaliveConnectionId(e.url);if(S){let e=B.get(S);e!==void 0&&(clearTimeout(e),B.delete(S),E.info({connectionId:S},`[keepalive] reconnect during grace — timer cancelled`))}if(S&&k){let t=parseKeepaliveIdentity(e.url);if(t)try{let e=iconFromClientName(t.clientName),w=AGENT_ICON_COLORS[e]??colorFromSeed(t.colorSeed);k.setPresence(toBroadcasterKey(S),{displayName:t.displayName,icon:e,color:w,currentDoc:`(connected)`,mode:`idle`,ts:Date.now()})}catch(e){E.error({err:e,connectionId:S},`[keepalive] presence bootstrap failed`)}}let w=setInterval(()=>{try{t.ping()}catch{}},3e4);w.unref?.();let j=S?setInterval(()=>{k?.bumpPresenceTs(toBroadcasterKey(S))},3e3):null;j?.unref?.(),t.on(`close`,()=>{if(clearInterval(w),j!==null&&clearInterval(j),!S)return;let e=setTimeout(()=>{if(B.delete(S),q)return;let e=(async()=>{E.info({connectionId:S},`[keepalive] grace expired — cleaning up sessions`);try{await D?.closeAllForAgent(S)}catch(e){E.error({err:e,connectionId:S},`[keepalive] closeAllForAgent failed`)}try{O?.clearFocus(S)}catch(e){E.error({err:e,connectionId:S},`[keepalive] clearFocus failed`)}try{k?.clearPresence(toBroadcasterKey(S))}catch(e){E.error({err:e,connectionId:S},`[keepalive] clearPresence failed`)}})();H.add(e),e.finally(()=>H.delete(e))},F);e.unref?.(),B.set(S,e),E.info({connectionId:S,graceMs:F},`[keepalive] disconnected — grace timer started`)}),t.on(`error`,e=>{handleCollabSocketError(e)||E.error({err:e},`MCP keepalive WS error`),t.terminate()})});return}if(e.url?.startsWith(`/collab`)){t.on(`error`,e=>{handleCollabSocketError(e)||E.error({err:e},`Upgrade socket error`)}),L.handleUpgrade(e,t,w,t=>{let w=S.handleConnection(t,e),D=!1;t.on(`message`,e=>{if(D)return;let S=e.byteLength;if(S>MAX_COLLAB_MESSAGE_BYTES){D=!0,incrementCollabMessageTooLarge(),E.warn({event:`collab-message-too-large`,bytes:S,limit:MAX_COLLAB_MESSAGE_BYTES},`Collab WebSocket message rejected before Yjs processing`),t.close(1009,`Message Too Big`);return}w.handleMessage(new Uint8Array(e))}),t.on(`close`,(e,t)=>{w.handleClose({code:e,reason:t.toString()})}),t.on(`error`,e=>{if(e.code===`WS_ERR_UNSUPPORTED_MESSAGE_LENGTH`){incrementCollabMessageTooLarge(),E.warn({event:`collab-message-too-large`,limit:MAX_COLLAB_MESSAGE_BYTES},`Collab WebSocket frame rejected by ws maxPayload before Yjs processing`),t.terminate();return}handleCollabSocketError(e)||E.error({err:e},`WebSocket error`),t.terminate()})});return}t.destroy()}),{wss:L,shutdown:async()=>{if(!q){q=!0;for(let e of B.values())clearTimeout(e);B.clear(),H.size>0&&await Promise.allSettled([...H])}}}}function parseKeepaliveConnectionId(e){if(!e)return null;try{return validateAgentId(new URL(e,`http://localhost`).searchParams.get(`connectionId`))}catch{return null}}const MAX_KEEPALIVE_IDENTITY_LEN=256;function sanitizeIdentityField(e){return e===null||e.length===0||e.length>MAX_KEEPALIVE_IDENTITY_LEN||/[-]/.test(e)?null:e}function parseKeepaliveIdentity(e){if(!e)return null;try{let t=new URL(e,`http://localhost`),S=sanitizeIdentityField(t.searchParams.get(`displayName`)),w=sanitizeIdentityField(t.searchParams.get(`clientName`)),E=sanitizeIdentityField(t.searchParams.get(`colorSeed`));return S===null||w===null||E===null?null:{displayName:S,clientName:w,colorSeed:E}}catch{return null}}const MISSING_OK_CONFIG_MESSAGE=`Open Knowledge config not found at .ok/config.yml. Run ok init to scaffold OK in this directory.`;var MissingOkConfigError=class extends Error{kind;projectDir;constructor(e,t,S){super(MISSING_OK_CONFIG_MESSAGE,S),this.name=`MissingOkConfigError`,this.kind=e,this.projectDir=t}};async function startConfigFileWatcher(e,t){let S=getLogger(`config-file-watcher`),{watch:w}=await import(`./chokidar-CxU7f6JW.mjs`),E=dirname(e);try{tracedMkdirSync(E,{recursive:!0})}catch(e){e.code!==`EEXIST`&&S.warn({err:e,watchDir:E},`failed to create watch directory; watcher may be inert`)}let D=w(E,{ignoreInitial:!0,depth:0,usePolling:!0,interval:200,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50},ignored:t=>t!==E&&t!==e});await new Promise(e=>{D.once(`ready`,e)});let O=null;try{O=readFileSync(e,`utf-8`)}catch{}let k=(w,E=!0)=>{if(w!==e)return;let D;try{D=readFileSync(w,`utf-8`)}catch(e){if(e.code===`ENOENT`){E&&S.debug({path:w},`config file disappeared between event and read; dropping`);return}S.warn({err:e,path:w},`config file read failed; dropping event`);return}if(D!==O){O=D;try{t(D)}catch(e){S.warn({err:e,path:w},`config file change handler threw`)}}},j=e=>k(e);D.on(`add`,j),D.on(`change`,j),D.on(`unlink`,t=>{t===e&&S.debug({path:t},`config file unlinked; Y.Text retained at current state`)}),D.on(`error`,t=>{S.warn({err:t,watchDir:E,absPath:e},`[config-file-watcher] chokidar error while watching ${e}`)});let F=0,L=setInterval(()=>{F++,k(e,!1),F>=20&&clearInterval(L)},500);L.unref?.();let B=!1;return async()=>{B||(B=!0,clearInterval(L),await D.close())}}async function startMultiPathConfigFileWatcher(e,t){if(e.length===0)throw Error(`startMultiPathConfigFileWatcher requires at least one absolute path`);let S=getLogger(`config-file-watcher`),{watch:w}=await import(`./chokidar-CxU7f6JW.mjs`),E=new Set(e),D=Array.from(new Set(Array.from(E,e=>dirname(e))));for(let e of D)try{tracedMkdirSync(e,{recursive:!0})}catch(t){t.code!==`EEXIST`&&S.warn({err:t,dir:e},`failed to create watch directory; watcher may be inert`)}let O=w(D,{ignoreInitial:!0,depth:0,usePolling:!0,interval:200,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50},ignored:e=>!E.has(e)&&!D.includes(e)});await new Promise(e=>{O.once(`ready`,e)});let k=new Map;for(let e of E)try{k.set(e,readFileSync(e,`utf-8`))}catch{k.set(e,null)}let j=(e,w=!0)=>{if(!E.has(e))return;let D;try{D=readFileSync(e,`utf-8`)}catch(t){if(t.code===`ENOENT`){w&&S.debug({path:e},`config file disappeared between event and read; dropping`);return}S.warn({err:t,path:e},`config file read failed; dropping event`);return}if(D!==k.get(e)){k.set(e,D);try{t(e,D)}catch(t){S.warn({err:t,path:e},`config file change handler threw`)}}},F=e=>j(e);O.on(`add`,F),O.on(`change`,F),O.on(`unlink`,e=>{E.has(e)&&S.debug({path:e},`config file unlinked; downstream state retained`)}),O.on(`error`,e=>{S.warn({err:e,watchDirs:D,paths:Array.from(E)},`[config-file-watcher] chokidar error in multi-path watcher`)});let L=0,B=setInterval(()=>{L++;for(let e of E)j(e,!1);L>=20&&clearInterval(B)},500);B.unref?.();let H=!1;return async()=>{H||(H=!0,clearInterval(B),await O.close())}}const QUIET_WINDOW_MS=100,BATCH_TIMEOUT_MS=3e4,WATCHED_FILES=new Set([`HEAD`,`MERGE_HEAD`,`ORIG_HEAD`,`index.lock`]);function readHeadSha(e){try{let t=readFileSync(resolve(e,`HEAD`),`utf-8`).trim();if(t.startsWith(`ref: `)){let S=resolve(e,t.slice(5));try{return readFileSync(S,`utf-8`).trim()}catch{try{let S=readFileSync(resolve(e,`packed-refs`),`utf-8`),w=t.slice(5),E=S.split(`
|
|
3062
|
+
`),{result:E})})}function registerAllTools(e,t){let S=t.logger,w=createLoggedServer(e,{logger:t.logger,identityRef:t.identityRef}),E=e=>async w=>{try{let E=await t.resolveCwd(w);return(getCurrentMcpLogger()??S)?.debug(`tool cwd resolved`,{tool:e,cwd:E,...w?{explicit:w}:{}}),E}catch(t){throw(getCurrentMcpLogger()??S)?.warn(`tool call failed`,{tool:e,error:t instanceof Error?t.message:String(t),...w?{explicit:w}:{}}),t}};register$23(w,{resolveCwd:E(`exec`),serverUrl:t.serverUrl,config:t.config}),register$12(w,{config:t.config,resolveCwd:E(`ingest`)}),register$7(w,{config:t.config,resolveCwd:E(`research`)}),register$28(w,{config:t.config,resolveCwd:E(`consolidate`)}),register$25(w,{config:t.config,resolveCwd:E(`discover`)}),register$10(w,{resolveCwd:E(`read_document`),config:t.config,serverUrl:t.serverUrl}),register$4(w,{resolveCwd:E(`search`),config:t.config,serverUrl:t.serverUrl}),register$13(w,{resolveCwd:E(`grep`),config:t.config,serverUrl:t.serverUrl}),register$2(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`suggest_links`)}),register$1(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`write_document`),identityRef:t.identityRef}),register$24(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`edit_document`),identityRef:t.identityRef}),register$27(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`delete_document`),identityRef:t.identityRef}),register$22(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`frontmatter_patch`),identityRef:t.identityRef}),register$9(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`rename_document`),identityRef:t.identityRef}),register$8(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`rename_folder`),identityRef:t.identityRef}),register$16(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`get_history`)}),register$5(w,t.config,t.serverUrl,E(`save_version`),t.identityRef),register$6(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`rollback_to_version`),identityRef:t.identityRef}),register$11(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`list_documents`)}),register$21(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`get_backlinks`)}),register$20(w,{resolveCwd:E(`get_components`),config:t.config}),register$17(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`get_forward_links`)}),register$14(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`get_orphans`)}),register$15(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`get_hubs`)}),register$18(w,{serverUrl:t.serverUrl,config:t.config,resolveCwd:E(`get_dead_links`)}),register$19(w,{config:t.config,resolveCwd:E(`get_config`)}),register$3(w,{config:t.config,resolveCwd:E(`set_folder_rule`)}),register(w,{config:t.config,resolveCwd:E(`write_template`)}),register$26(w,{config:t.config,resolveCwd:E(`delete_template`)})}function firstHeader(e){return Array.isArray(e)?e[0]:e}function writePlain(e,t,S){e.writableEnded||(e.statusCode=t,e.setHeader(`Content-Type`,`text/plain; charset=utf-8`),e.end(S))}function createSessionServer(e,t,S){let w=e.config,E=new McpServer({name:MCP_SERVER_NAME,version:RUNTIME_VERSION},{instructions:buildInstructions(w.content)});installPrettyZodErrors(E);let D=S??randomUUID(),O={current:{connectionId:D,displayName:D,colorSeed:D}};E.server.oninitialized=()=>{let e=E.server.getClientVersion(),t=sanitizeClientName(e?.name,D);O.current={connectionId:D,clientInfo:e?{name:t,version:e.version}:void 0,displayName:t,colorSeed:t}};let k=e.projectDir??e.contentDir;return registerAllTools(E,{serverUrl:async()=>e.getServerUrl(),resolveCwd:async e=>{if(e===void 0)return k;let t=resolveWithinRoot(k,e);if(!t.ok)throw Error(`cwd "${e}" is not within the configured project root: ${t.reason}`);return t.abs},config:w,identityRef:O}),{server:E,transport:t}}function createMcpHttpHandler(e){let t=new Map,S=e.sessionTtlMs??1800*1e3,w=e.maxSessions??100;async function E(S,w){let E=t.get(S);if(!E)return;t.delete(S),E.ttlTimer!==void 0&&clearTimeout(E.ttlTimer);let D=await Promise.allSettled([E.server.close(),E.transport.close()]);for(let t of D)t.status===`rejected`&&e.log?.warn?.({err:t.reason,sessionId:S,reason:w},`MCP HTTP session close failed`);e.log?.info?.({sessionId:S,reason:w},`MCP HTTP session closed`)}function D(t,w){w.ttlTimer!==void 0&&clearTimeout(w.ttlTimer),w.ttlTimer=setTimeout(()=>{E(t,`ttl-expired`).catch(S=>{e.log?.warn?.({err:S,sessionId:t},`MCP HTTP session TTL cleanup failed`)})},S),w.ttlTimer.unref?.()}return{async handle(S,O){let k=firstHeader(S.headers[`mcp-session-id`]);if(k){let e=t.get(k);if(!e){writePlain(O,404,`MCP session not found`);return}D(k,e),await e.transport.handleRequest(S,O);return}if(S.method!==`POST`){writePlain(O,400,`Missing MCP session. Initialize with POST /mcp first.`);return}if(t.size>=w){e.log?.warn?.({activeSessions:t.size,maxSessions:w},`MCP HTTP session cap reached`),writePlain(O,503,`Too many active MCP sessions`);return}let j=firstHeader(S.headers[MCP_CONNECTION_ID_HEADER]),F=validateAgentId(j)??void 0;j!==void 0&&F===void 0&&e.log?.warn?.({headerLength:j.length},`MCP HTTP forwarded connectionId header failed validation; falling back to randomUUID`);let L=new StreamableHTTPServerTransport({sessionIdGenerator:()=>randomUUID(),enableJsonResponse:!0,onsessioninitialized:async S=>{try{let w=createSessionServer(e,L,F);await w.server.connect(L),t.set(S,w),D(S,w),e.log?.info?.({sessionId:S},`MCP HTTP session initialized`)}catch(w){throw t.delete(S),e.log?.error?.({err:w,sessionId:S},`MCP HTTP session initialization failed`),w}}});L.onerror=t=>{e.log?.warn?.({err:t},`MCP HTTP transport error`)},L.onclose=()=>{let t=L.sessionId;if(!t){e.log?.info?.({sessionId:t,reason:`transport-closed`},`MCP HTTP session closed`);return}E(t,`transport-closed`).catch(S=>{e.log?.warn?.({err:S,sessionId:t},`MCP HTTP transport-close cleanup failed`)})},await L.handleRequest(S,O)},async close(){let e=[...t.entries()];await Promise.allSettled(e.map(([e])=>E(e,`handler-close`)))}}}const DEFAULT_KEEPALIVE_GRACE_MS=1e4,MAX_COLLAB_MESSAGE_BYTES=1024*1024,MCP_CORS_HEADERS={"Access-Control-Allow-Methods":`GET, POST, DELETE, OPTIONS`,"Access-Control-Allow-Headers":`Content-Type, Authorization, traceparent, tracestate, baggage, mcp-session-id, mcp-protocol-version`,"Access-Control-Max-Age":`86400`};function mountMcpAndApi(e){let{httpServer:t,hocuspocus:S,mcpHttpHandler:w,log:E,sessionManager:D,agentFocusBroadcaster:O,agentPresenceBroadcaster:k,contentAssetMiddleware:j,reactShellMiddleware:F}=e,L=e.keepaliveGraceMs??DEFAULT_KEEPALIVE_GRACE_MS,B=new import_websocket_server$1.default({noServer:!0,maxPayload:MAX_COLLAB_MESSAGE_BYTES});B.on(`error`,e=>{E.error({err:e},`WebSocketServer error`)});let H=new Map,q=new Set,J=!1;return t.on(`request`,(e,t)=>{let D=e.url?.split(`?`)[0];if(w!==void 0&&D===`/mcp`){let S=e.headers.origin,D=Array.isArray(e.headers[`mcp-session-id`])?e.headers[`mcp-session-id`][0]:e.headers[`mcp-session-id`];if(!isLoopbackAddress(e.socket.remoteAddress)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback access required.`,{handler:`mcp`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`mcp`});return}if(S!==void 0&&!isAllowedApiOrigin(S)){errorResponse(t,403,`urn:ok:error:invalid-origin`,`Origin not allowed.`,{handler:`mcp`});return}S!==void 0&&(t.setHeader(`Access-Control-Allow-Origin`,S),t.setHeader(`Vary`,`Origin`));for(let[e,S]of Object.entries(MCP_CORS_HEADERS))t.setHeader(e,S);if(e.method===`OPTIONS`){t.writeHead(204),t.end();return}w.handle(e,t).catch(e=>{E.error({err:e,sessionId:D},`Unhandled MCP HTTP error`),!t.writableEnded&&!t.headersSent?errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`mcp`,cause:e}):t.writableEnded||t.end()});return}if(D?.startsWith(`/api/`)){S.hooks(`onRequest`,{request:e,response:t}).then(()=>{t.writableEnded||t.headersSent||errorResponse(t,404,`urn:ok:error:not-found`,`API endpoint not found.`,{handler:`mcp-mount`,detail:`No handler for ${e.method??`GET`} ${D}`})}).catch(e=>{E.error({err:e},`Unhandled onRequest error`),!t.writableEnded&&!t.headersSent?errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`mcp-mount`,cause:e}):t.writableEnded||t.end()});return}let O=(e,t)=>{if(!(t.writableEnded||t.headersSent)){if(F!==void 0){try{F(e,t,()=>{t.writableEnded||t.headersSent||errorResponse(t,404,`urn:ok:error:not-found`,`Not found.`,{handler:`mcp-mount`,detail:`No handler for ${D??`/`}`})})}catch(e){E.error({err:e},`Unhandled react-shell middleware error`),!t.writableEnded&&!t.headersSent?errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`mcp-mount`,cause:e}):t.writableEnded||t.end()}return}errorResponse(t,404,`urn:ok:error:not-found`,`Not found.`,{handler:`mcp-mount`,detail:`No handler for ${D??`/`}`})}};if(j!==void 0){try{j(e,t,()=>O(e,t))}catch(e){E.error({err:e},`Unhandled content-asset middleware error`),!t.writableEnded&&!t.headersSent?errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`mcp-mount`,cause:e}):t.writableEnded||t.end()}return}if(F!==void 0){O(e,t);return}errorResponse(t,404,`urn:ok:error:not-found`,`Not found.`,{handler:`mcp-mount`,detail:`The React UI is served by \`ok ui\` (run \`ok ui\` and check \`ui.lock.port\`). No handler for ${D??`/`}`})}),t.on(`upgrade`,(e,t,w)=>{if(e.url?.startsWith(`/collab/keepalive`)){if(!isLoopbackAddress(e.socket.remoteAddress)||!isAllowedWorkspaceHostHeader(e.headers.host)){t.destroy();return}t.on(`error`,e=>{handleCollabSocketError(e)||E.error({err:e},`MCP keepalive socket error`)}),B.handleUpgrade(e,t,w,t=>{let S=parseKeepaliveConnectionId(e.url);if(S){let e=H.get(S);e!==void 0&&(clearTimeout(e),H.delete(S),E.info({connectionId:S},`[keepalive] reconnect during grace — timer cancelled`))}if(S&&k){let t=parseKeepaliveIdentity(e.url);if(t)try{let e=iconFromClientName(t.clientName),w=AGENT_ICON_COLORS[e]??colorFromSeed(t.colorSeed);k.setPresence(toBroadcasterKey(S),{displayName:t.displayName,icon:e,color:w,currentDoc:`(connected)`,mode:`idle`,ts:Date.now()})}catch(e){E.error({err:e,connectionId:S},`[keepalive] presence bootstrap failed`)}}let w=setInterval(()=>{try{t.ping()}catch{}},3e4);w.unref?.();let j=S?setInterval(()=>{k?.bumpPresenceTs(toBroadcasterKey(S))},3e3):null;j?.unref?.(),t.on(`close`,()=>{if(clearInterval(w),j!==null&&clearInterval(j),!S)return;let e=setTimeout(()=>{if(H.delete(S),J)return;let e=(async()=>{E.info({connectionId:S},`[keepalive] grace expired — cleaning up sessions`);try{await D?.closeAllForAgent(S)}catch(e){E.error({err:e,connectionId:S},`[keepalive] closeAllForAgent failed`)}try{O?.clearFocus(S)}catch(e){E.error({err:e,connectionId:S},`[keepalive] clearFocus failed`)}try{k?.clearPresence(toBroadcasterKey(S))}catch(e){E.error({err:e,connectionId:S},`[keepalive] clearPresence failed`)}})();q.add(e),e.finally(()=>q.delete(e))},L);e.unref?.(),H.set(S,e),E.info({connectionId:S,graceMs:L},`[keepalive] disconnected — grace timer started`)}),t.on(`error`,e=>{handleCollabSocketError(e)||E.error({err:e},`MCP keepalive WS error`),t.terminate()})});return}if(e.url?.startsWith(`/collab`)){t.on(`error`,e=>{handleCollabSocketError(e)||E.error({err:e},`Upgrade socket error`)}),B.handleUpgrade(e,t,w,t=>{let w=S.handleConnection(t,e),D=!1;t.on(`message`,e=>{if(D)return;let S=e.byteLength;if(S>MAX_COLLAB_MESSAGE_BYTES){D=!0,incrementCollabMessageTooLarge(),E.warn({event:`collab-message-too-large`,bytes:S,limit:MAX_COLLAB_MESSAGE_BYTES},`Collab WebSocket message rejected before Yjs processing`),t.close(1009,`Message Too Big`);return}w.handleMessage(new Uint8Array(e))}),t.on(`close`,(e,t)=>{w.handleClose({code:e,reason:t.toString()})}),t.on(`error`,e=>{if(e.code===`WS_ERR_UNSUPPORTED_MESSAGE_LENGTH`){incrementCollabMessageTooLarge(),E.warn({event:`collab-message-too-large`,limit:MAX_COLLAB_MESSAGE_BYTES},`Collab WebSocket frame rejected by ws maxPayload before Yjs processing`),t.terminate();return}handleCollabSocketError(e)||E.error({err:e},`WebSocket error`),t.terminate()})});return}t.destroy()}),{wss:B,shutdown:async()=>{if(!J){J=!0;for(let e of H.values())clearTimeout(e);H.clear(),q.size>0&&await Promise.allSettled(q)}}}}function parseKeepaliveConnectionId(e){if(!e)return null;try{return validateAgentId(new URL(e,`http://localhost`).searchParams.get(`connectionId`))}catch{return null}}const MAX_KEEPALIVE_IDENTITY_LEN=256;function sanitizeIdentityField(e){return e===null||e.length===0||e.length>MAX_KEEPALIVE_IDENTITY_LEN||/[-]/.test(e)?null:e}function parseKeepaliveIdentity(e){if(!e)return null;try{let t=new URL(e,`http://localhost`),S=sanitizeIdentityField(t.searchParams.get(`displayName`)),w=sanitizeIdentityField(t.searchParams.get(`clientName`)),E=sanitizeIdentityField(t.searchParams.get(`colorSeed`));return S===null||w===null||E===null?null:{displayName:S,clientName:w,colorSeed:E}}catch{return null}}const MISSING_OK_CONFIG_MESSAGE=`Open Knowledge config not found at .ok/config.yml. Run ok init to scaffold OK in this directory.`;var MissingOkConfigError=class extends Error{kind;projectDir;constructor(e,t,S){super(MISSING_OK_CONFIG_MESSAGE,S),this.name=`MissingOkConfigError`,this.kind=e,this.projectDir=t}};async function startConfigFileWatcher(e,t){let S=getLogger(`config-file-watcher`),{watch:w}=await import(`./chokidar-CxU7f6JW.mjs`),E=dirname(e);try{tracedMkdirSync(E,{recursive:!0})}catch(e){e.code!==`EEXIST`&&S.warn({err:e,watchDir:E},`failed to create watch directory; watcher may be inert`)}let D=w(E,{ignoreInitial:!0,depth:0,usePolling:!0,interval:200,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50},ignored:t=>t!==E&&t!==e});await new Promise(e=>{D.once(`ready`,e)});let O=null;try{O=readFileSync(e,`utf-8`)}catch{}let k=(w,E=!0)=>{if(w!==e)return;let D;try{D=readFileSync(w,`utf-8`)}catch(e){if(e.code===`ENOENT`){E&&S.debug({path:w},`config file disappeared between event and read; dropping`);return}S.warn({err:e,path:w},`config file read failed; dropping event`);return}if(D!==O){O=D;try{t(D)}catch(e){S.warn({err:e,path:w},`config file change handler threw`)}}},j=e=>k(e);D.on(`add`,j),D.on(`change`,j),D.on(`unlink`,t=>{t===e&&S.debug({path:t},`config file unlinked; Y.Text retained at current state`)}),D.on(`error`,t=>{S.warn({err:t,watchDir:E,absPath:e},`[config-file-watcher] chokidar error while watching ${e}`)});let F=0,L=setInterval(()=>{F++,k(e,!1),F>=20&&clearInterval(L)},500);L.unref?.();let B=!1;return async()=>{B||(B=!0,clearInterval(L),await D.close())}}async function startMultiPathConfigFileWatcher(e,t){if(e.length===0)throw Error(`startMultiPathConfigFileWatcher requires at least one absolute path`);let S=getLogger(`config-file-watcher`),{watch:w}=await import(`./chokidar-CxU7f6JW.mjs`),E=new Set(e),D=Array.from(new Set(Array.from(E,e=>dirname(e))));for(let e of D)try{tracedMkdirSync(e,{recursive:!0})}catch(t){t.code!==`EEXIST`&&S.warn({err:t,dir:e},`failed to create watch directory; watcher may be inert`)}let O=w(D,{ignoreInitial:!0,depth:0,usePolling:!0,interval:200,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50},ignored:e=>!E.has(e)&&!D.includes(e)});await new Promise(e=>{O.once(`ready`,e)});let k=new Map;for(let e of E)try{k.set(e,readFileSync(e,`utf-8`))}catch{k.set(e,null)}let j=(e,w=!0)=>{if(!E.has(e))return;let D;try{D=readFileSync(e,`utf-8`)}catch(t){if(t.code===`ENOENT`){w&&S.debug({path:e},`config file disappeared between event and read; dropping`);return}S.warn({err:t,path:e},`config file read failed; dropping event`);return}if(D!==k.get(e)){k.set(e,D);try{t(e,D)}catch(t){S.warn({err:t,path:e},`config file change handler threw`)}}},F=e=>j(e);O.on(`add`,F),O.on(`change`,F),O.on(`unlink`,e=>{E.has(e)&&S.debug({path:e},`config file unlinked; downstream state retained`)}),O.on(`error`,e=>{S.warn({err:e,watchDirs:D,paths:Array.from(E)},`[config-file-watcher] chokidar error in multi-path watcher`)});let L=0,B=setInterval(()=>{L++;for(let e of E)j(e,!1);L>=20&&clearInterval(B)},500);B.unref?.();let H=!1;return async()=>{H||(H=!0,clearInterval(B),await O.close())}}const QUIET_WINDOW_MS=100,BATCH_TIMEOUT_MS=3e4,WATCHED_FILES=new Set([`HEAD`,`MERGE_HEAD`,`ORIG_HEAD`,`index.lock`]);function readHeadSha(e){try{let t=readFileSync(resolve(e,`HEAD`),`utf-8`).trim();if(t.startsWith(`ref: `)){let S=resolve(e,t.slice(5));try{return readFileSync(S,`utf-8`).trim()}catch{try{let S=readFileSync(resolve(e,`packed-refs`),`utf-8`),w=t.slice(5),E=S.split(`
|
|
3063
3063
|
`).find(e=>e.endsWith(` ${w}`));if(E)return E.split(` `)[0]}catch{}return null}}return t.length>=40?t.slice(0,40):null}catch{return null}}function readBranchFromHead(e){try{let t=readFileSync(resolve(e,`HEAD`),`utf-8`).trim();return t.startsWith(`ref: refs/heads/`)?t.slice(16):t.length>=40?`detached-${t.slice(0,12)}`:null}catch{return null}}async function startHeadWatcher(e,t,S){let w=resolveGitDir(e);if(!w)return{unsubscribe:async()=>{},getLastKnownBranch:()=>null};let E=w,D=!1,O=null,k=null,j=null,F=null;async function L(e){if(H&&await H,!D)return;O&&=(clearTimeout(O),null),k&&=(clearTimeout(k),null);let t=readHeadSha(E),w=j!==t,L=readBranchFromHead(E),B;B=L?.startsWith(`detached-`)?`detached-head`:F===L?`within-branch`:`cross-branch`;let q=F;try{await S({headMoved:w,oldHead:j,newHead:t,timeout:e,batchKind:B,oldBranch:q,newBranch:L})}catch(e){console.error(`[head-watcher] onBatchEnd callback failed:`,e)}finally{D=!1,j=t,F=L}}function B(){O&&clearTimeout(O),O=setTimeout(()=>{O=null,L(!1)},QUIET_WINDOW_MS)}let H=null;async function q(e){if(!D){D=!0,j=readHeadSha(E);let S=(async()=>{try{await t({trigger:e})}catch(e){console.error(`[head-watcher] onBatchBegin callback failed:`,e)}})();H=S,await S,H=null,k=setTimeout(()=>{k=null,L(!0)},BATCH_TIMEOUT_MS)}B()}let J,Y;try{Y=await import(`@parcel/watcher`)}catch(e){throw Error(`@parcel/watcher unavailable for HEAD watching: ${e instanceof Error?e.message:e}`)}try{let e=await Y.subscribe(E,(e,t)=>{if(e){console.error(`[head-watcher]`,e);return}for(let e of t){let t=e.path.split(`/`).pop()??``;if(WATCHED_FILES.has(t)){q(t);break}}});J=()=>e.unsubscribe()}catch(e){throw Error(`@parcel/watcher subscribe failed for HEAD watching: ${e instanceof Error?e.message:e}`)}return j=readHeadSha(E),F=readBranchFromHead(E),console.log(`[head-watcher] Watching ${E} for HEAD changes`),{unsubscribe:async()=>{D&&await L(!1),O&&clearTimeout(O),k&&clearTimeout(k),await J()},getLastKnownBranch:()=>F}}const LIVE_DERIVED_INDEX_DEBOUNCE_MS=100;function isLocalOriginLike(e){return typeof e!=`object`||!e?!1:e.source===`local`}function serializeLiveDocument(e){return e.getText(`source`).toString()}function createLiveDerivedIndexExtension(e){let{backlinkIndex:t,tagIndex:S,signalChannel:w,debounceMs:E=100}=e,D=new Map;function O(e){let t=D.get(e);t&&(clearTimeout(t),D.delete(e))}function k(e,k){O(e),D.set(e,setTimeout(()=>{D.delete(e);try{let E=serializeLiveDocument(k);t.updateDocumentFromMarkdown(e,E),w?.(`backlinks`),w?.(`graph`),S&&(S.updateDocumentFromMarkdown(e,E),w?.(`tags`))}catch(t){console.error(`[live-derived-index] Failed to update derived views for ${e}:`,t)}},E))}return{async onChange({documentName:e,document:t,transactionOrigin:S}){isSystemDoc(e)||isConfigDoc(e)||isLocalOriginLike(S)&&S.context?.origin===`file-watcher`||k(e,t)},async beforeUnloadDocument({documentName:e}){O(e)},async onDestroy(){for(let e of D.values())clearTimeout(e);D.clear()}}}const PRINCIPAL_FILE=`principal.json`,GIT_TIMEOUT_MS=3e3;async function readGitConfig(e){try{let t=esm_default({baseDir:e,timeout:{block:GIT_TIMEOUT_MS}});return{name:(await t.raw(`config`,`--get`,`user.name`)).trim()||null,email:(await t.raw(`config`,`--get`,`user.email`)).trim()||null}}catch{return{name:null,email:null}}}async function loadPrincipal(e){let t=getLocalDir(e),S=resolve(t,PRINCIPAL_FILE),{name:w,email:E}=await readGitConfig(e);if(existsSync(S)){let e;try{e=JSON.parse(readFileSync(S,`utf-8`))}catch{e={}}let t=typeof e.id==`string`&&e.id.startsWith(`principal-`)?e.id:`principal-${randomUUID()}`,D=typeof e.created_at==`string`?e.created_at:new Date().toISOString(),O=t.slice(10,18),k={id:t,display_name:w?sanitizeGitIdentity(w):typeof e.display_name==`string`?e.display_name:`Local User`,display_email:E?sanitizeGitIdentity(E):typeof e.display_email==`string`?e.display_email:`principal-${O}@openknowledge.local`,source:w||E?`git-config`:`synthesized`,created_at:D};return writeFileSync(S,JSON.stringify(k,null,2),`utf-8`),k}mkdirSync(t,{recursive:!0});let D=`principal-${randomUUID()}`,O=D.slice(10,18),k={id:D,display_name:w?sanitizeGitIdentity(w):`Local User`,display_email:E?sanitizeGitIdentity(E):`principal-${O}@openknowledge.local`,source:w||E?`git-config`:`synthesized`,created_at:new Date().toISOString()};return writeFileSync(S,JSON.stringify(k,null,2),`utf-8`),k}const DEFAULT_CAPACITY=1e4;var RecentlyRemovedDocs=class{map=new Map;capacity;onEviction;onSizeChange;now;constructor(e=DEFAULT_CAPACITY,t={}){this.capacity=Math.max(0,Math.floor(e)),this.onEviction=t.onEviction,this.onSizeChange=t.onSizeChange,this.now=t.now??Date.now}setRenamed(e,t){this.put(e,{kind:`renamed`,newDocName:t,addedAt:this.now()})}setDeleted(e){this.put(e,{kind:`deleted`,addedAt:this.now()})}get(e){let t=this.map.get(e);if(t!==void 0)return this.map.delete(e),this.map.set(e,t),t}has(e){return this.map.has(e)}peek(e){return this.map.get(e)}delete(e){this.map.delete(e)&&this.onSizeChange?.(this.map.size)}get size(){return this.map.size}put(e,t){if(this.capacity===0){this.onSizeChange?.(0);return}for(this.map.delete(e),this.map.set(e,t);this.map.size>this.capacity;){let e=this.map.keys().next().value;if(e===void 0)break;this.map.delete(e),this.onEviction?.()}this.onSizeChange?.(this.map.size)}};function fileExistsForDocName(e,t){let S=e.resolveFilePath(t);return S!==null&&e.fileExists(S)}async function runRemovalRedirectGuard(e,t){try{if(isSystemDoc(e)||isConfigDoc(e))return;let S=t.recentlyRemovedDocs.get(e);if(S===void 0)return;if(S.kind===`deleted`){if(fileExistsForDocName(t,e)){t.recentlyRemovedDocs.delete(e);return}throw incrementAuthDocDeleted(),setActiveSpanAttributes({"auth.reason":`doc-deleted`}),new HocuspocusAuthRejection(`doc-deleted`,`removed-doc rejection for deleted ${e}`)}let w=new Set([e]),E=S.newDocName;for(;;){if(w.has(E)){incrementRemovalRedirectChainCycle(),console.warn(JSON.stringify({event:`removal-redirect-chain-cycle`,documentName:e,target:E}));return}w.add(E);let S=t.recentlyRemovedDocs.get(E);if(S===void 0)throw incrementAuthRenameRedirect(),setActiveSpanAttributes({"auth.reason":`rename-redirect`}),new HocuspocusAuthRejection(`rename-redirect`,`removed-doc redirect for ${e} → ${E}`,E);if(S.kind===`deleted`)throw fileExistsForDocName(t,E)?(t.recentlyRemovedDocs.delete(E),incrementAuthRenameRedirect(),setActiveSpanAttributes({"auth.reason":`rename-redirect`}),new HocuspocusAuthRejection(`rename-redirect`,`removed-doc redirect for ${e} → ${E}`,E)):(incrementAuthDocDeleted(),setActiveSpanAttributes({"auth.reason":`doc-deleted`}),new HocuspocusAuthRejection(`doc-deleted`,`removed-doc rejection for deleted ${e}`));E=S.newDocName}}catch(t){if(t instanceof HocuspocusAuthRejection)throw t;incrementAuthRemovalGuardError(),console.warn(JSON.stringify({event:`removal-redirect-extension-error`,documentName:e,message:t instanceof Error?t.message:String(t)}))}}function createServerObserverExtension(e){let t=new Map,S=new Map;return{async afterLoadDocument({documentName:w,document:E}){if(isSystemDoc(w)||isConfigDoc(w)||t.has(w))return;let D=E,O=D.getXmlFragment(`default`),k=D.getText(`source`),j=()=>{try{let S=setupServerObservers({doc:D,xmlFragment:O,ytext:k,mdManager:e.mdManager,schema:e.schema,docName:w,shadow:e.shadowRef?()=>e.shadowRef?.current:void 0,getBranch:e.getCurrentBranch?()=>e.getCurrentBranch?.()??`main`:void 0,contentRoot:e.contentRoot,resolveEmbed:e.resolveEmbed,resolveSize:e.resolveSize});return t.set(w,S),!0}catch(e){return console.error(`[ServerObserverExtension] Failed to attach observers for '${w}':`,e),incrementServerObserverError(`a`),incrementServerObserverError(`b`),!1}};if(!j()){let e=setTimeout(()=>{S.delete(w),!t.has(w)&&(console.warn(`[ServerObserverExtension] Retrying observer attachment for '${w}'`),j())},5e3);S.set(w,e)}},async afterUnloadDocument({documentName:e}){let w=S.get(e);w&&(clearTimeout(w),S.delete(e));let E=t.get(e);E&&(E(),t.delete(e))},async onDestroy(){for(let e of S.values())clearTimeout(e);S.clear();for(let[e,S]of t.entries())try{S()}catch(t){console.error(`[ServerObserverExtension] Cleanup failed for '${e}':`,t)}t.clear()}}}const STATE_MANIFEST_FILENAME=`state.json`;function detectProjectShape(e){return e.lockDir,existsSync(e.shadowRepoDir)?`adopt`:`fresh`}function manifestPath(e){return resolve(e,STATE_MANIFEST_FILENAME)}function isCompatibleSchema(e,t){return e===t||e===0&&t===1}var StateManifestError=class extends Error{kind;path;constructor(e){super(e.message),this.name=`StateManifestError`,this.kind=e.kind,this.path=e.path}};function isStateManifestRecord(e){if(!e||typeof e!=`object`)return!1;let t=e;if(typeof t.stateSchemaVersion!=`number`||typeof t.createdAt!=`string`||!t.createdBy||typeof t.createdBy!=`object`)return!1;let S=t.createdBy;return!(typeof S.runtimeVersion!=`string`||S.protocolVersion!==void 0&&typeof S.protocolVersion!=`number`)}function readStateManifest(e){let t=manifestPath(e);if(!existsSync(t))return{status:`absent`};let S;try{S=readFileSync(t,`utf-8`)}catch(e){throw new StateManifestError({kind:`corrupt`,path:t,message:`Failed to read state manifest at ${t}: ${e instanceof Error?e.message:String(e)}`})}let w;try{w=JSON.parse(S)}catch(e){throw new StateManifestError({kind:`corrupt`,path:t,message:`State manifest at ${t} is not valid JSON: ${e instanceof Error?e.message:String(e)}`})}if(!isStateManifestRecord(w))throw new StateManifestError({kind:`corrupt`,path:t,message:`State manifest at ${t} has invalid shape (missing or wrong-typed required fields)`});return{status:`present`,manifest:w}}function writeStateManifest(e,t){let S=manifestPath(e);mkdirSync(dirname(S),{recursive:!0}),writeFileSync(S,JSON.stringify(t,null,2),{encoding:`utf-8`,mode:384})}function assertCompatibleStateManifest(e){let t=getLogger(`state-manifest`),S=e.currentStateSchemaVersion??1,w=e.currentRuntimeVersion??RUNTIME_VERSION,E=e.currentProtocolVersion??1,D=(e.now??(()=>new Date))().toISOString(),O=manifestPath(e.lockDir),k=readStateManifest(e.lockDir);if(k.status===`present`){let j=k.manifest;if(!isCompatibleSchema(j.stateSchemaVersion,S))throw new StateManifestError({kind:`incompatible`,path:O,message:`State manifest at ${O} declares stateSchemaVersion=${j.stateSchemaVersion} but this binary supports ${S}. Refusing to boot — on-the-fly migration is out of scope. (Manifest written by runtime ${j.createdBy.runtimeVersion}, protocol ${j.createdBy.protocolVersion}.)`});try{let t={...j,lastWriteBy:{runtimeVersion:w,protocolVersion:E,at:D}};return writeStateManifest(e.lockDir,t),t}catch(e){return t.warn({err:e},`[state-manifest] failed to update lastWriteBy — proceeding`),j}}if(detectProjectShape({lockDir:e.lockDir,shadowRepoDir:e.shadowRepoDir})===`fresh`){let k={stateSchemaVersion:S,createdAt:D,createdBy:{runtimeVersion:w,protocolVersion:E}};return writeStateManifest(e.lockDir,k),t.info({path:O,stateSchemaVersion:S},`[state-manifest] fresh project — wrote manifest`),k}let j={stateSchemaVersion:0,createdAt:D,createdBy:{runtimeVersion:w,protocolVersion:E,adoptedAt:D}};return writeStateManifest(e.lockDir,j),t.warn({path:O,runtimeVersion:w},`[state-manifest] adopting pre-versioned project — wrote schema-0 manifest. Future binaries with STATE_SCHEMA_VERSION>=2 may refuse if they cannot read schema-0 state.`),j}const log$1=getLogger(`conflict-storage`);var ConflictStore=class{storePath;projectDir;branch;conflicts=[];constructor(e,t=`main`){this.storePath=join(getLocalDir(e),`conflicts.json`),this.projectDir=e,this.branch=t,this.load()}load(){if(!existsSync(this.storePath)){this.conflicts=[];return}try{let e=readFileSync(this.storePath,`utf-8`),t=JSON.parse(e);if(t.version!==1){log$1.warn({path:this.storePath},`[conflicts] unknown schema version — resetting`),this.conflicts=[];return}this.branch=t.branch??this.branch,this.conflicts=t.conflicts??[]}catch(e){log$1.warn({err:e},`[conflicts] failed to load conflicts.json — starting empty`),this.conflicts=[]}}save(){try{let e=dirname(this.storePath);existsSync(e)||mkdirSync(e,{recursive:!0});let t={version:1,branch:this.branch,conflicts:this.conflicts};writeFileSync(this.storePath,JSON.stringify(t,null,2),`utf-8`)}catch(e){log$1.warn({err:e},`[conflicts] failed to save conflicts.json`)}}addConflict(e){let t=this.conflicts.findIndex(t=>t.file===e.file);t===-1?this.conflicts.push(e):this.conflicts[t]=e,this.save()}removeConflict(e){this.conflicts=this.conflicts.filter(t=>t.file!==e),this.save()}clear(){this.conflicts=[],this.save()}count(){return this.conflicts.length}list(){return[...this.conflicts]}hasConflicts(){return this.conflicts.length>0}setBranch(e){this.branch=e}async resolveConflict(e,t,S,w=[]){if(!this.conflicts.find(t=>t.file===e))throw Error(`[conflicts] no conflict tracked for file: ${e}`);if(t===`content`&&S===void 0)throw Error(`[conflicts] strategy 'content' requires content parameter`);let{createGitInstance:E}=await import(`./git-handle-DwfYp_z--DreW3fNC.mjs`).then(e=>e.n),D=E(this.projectDir,{credentialArgs:w});switch(t){case`mine`:await D.git.raw([`checkout`,`--ours`,`--`,e]),await D.git.raw([`add`,`--`,e]);break;case`theirs`:await D.git.raw([`checkout`,`--theirs`,`--`,e]),await D.git.raw([`add`,`--`,e]);break;case`content`:{if(!S)throw Error(`[conflicts] strategy 'content' requires content parameter`);let t=resolve(this.projectDir),w=resolve(t,e);if(w!==t&&!w.startsWith(`${t}/`))throw Error(`[conflicts] file path escapes project directory: ${e}`);writeFileSync(w,S,`utf-8`),await D.git.raw([`add`,`--`,e]);break}default:throw Error(`[conflicts] unknown resolve strategy: ${t}`)}if(this.removeConflict(e),!this.hasConflicts())try{await D.git.raw([`commit`,`--no-edit`]),log$1.info({file:e},`[conflicts] all conflicts resolved — merge commit created`)}catch(t){let S=new Date().toISOString(),w=!1;try{let e=(await D.git.raw([`diff`,`--name-only`,`--diff-filter=U`])).split(`
|
|
3064
3064
|
`).map(e=>e.trim()).filter(Boolean);for(let t of e)this.addConflict({file:t,detectedAt:S});w=e.length>0}catch(e){log$1.warn({err:e},`[conflicts] commit failed and re-scan of unmerged files failed — falling back to single-file re-add`)}w||this.addConflict({file:e,detectedAt:S}),log$1.warn({err:t},`[conflicts] failed to commit merge after all conflicts resolved — unmerged files re-added`)}}};function extractStderr(e){return e.git?.toString()??e.message??``}function matchesAny(e,t){return t.some(t=>t.test(e))}const AUTH_PATTERNS=[/\b(401|403)\b/,/authentication failed/i,/authorization failed/i,/invalid credentials/i,/credential helper/i,/bad credentials/i,/token.*expired/i,/expired.*token/i,/permission denied.*\(publickey\)/i,/host key verification failed/i,/fatal:.*repository.*not found/i],SCOPE_MISMATCH_PATTERNS=[/insufficient scopes/i,/missing.*scope/i,/required scope/i],NON_FAST_FORWARD_PATTERNS=[/non-fast-forward/i,/rejected.*non-fast-forward/i,/would overwrite.*commits/i,/\[rejected\]/,/fetch first/i,/updates were rejected/i],PROTECTED_BRANCH_PATTERNS=[/protected branch/i,/refusing to allow/i,/at least \d+ approving review/i,/required status check/i,/branch policy/i,/GH001/i,/GH002/i,/GH003/i,/GH004/i,/push declined due to repository rule/i,/cannot push to a protected branch/i],MERGE_CONFLICT_PATTERNS=[/\bmerge conflict\b/i,/automatic merge failed/i,/CONFLICT \(/,/\bconflict\b.*\bmerge\b/i,/(?:^|\n)CONFLICTS:\s/i],LFS_PATTERNS=[/lfs.*quota/i,/exceeded.*bandwidth/i,/lfs storage/i],LARGE_FILE_PATTERNS=[/file.*too large/i,/exceeded.*file size/i,/push file size limit/i],PRE_RECEIVE_PATTERNS=[/pre-receive hook/i,/remote:.*rejected/i,/hook declined/i],SECRET_DETECTED_PATTERNS=[/secret.*detected/i,/push.*secret/i,/secret scanning/i,/leaking.*credentials/i,/token.*detected/i],INDEX_LOCK_PATTERNS=[/\.git\/index\.lock/i,/another git process/i,/unable to create.*\.lock/i],DIRTY_TREE_PATTERNS=[/dirty.*working tree/i,/working tree.*not clean/i,/untracked.*files.*would be overwritten/i,/local changes.*would be overwritten/i,/uncommitted changes/i,/changes.*not staged/i,/please.*commit.*changes/i,/please.*stash/i,/commit your changes or stash/i],DISK_FULL_PATTERNS=[/no space left on device/i,/disk quota exceeded/i,/ENOSPC/],NETWORK_PATTERNS=[/could not resolve host/i,/name.*resolution/i,/connection.*timed out/i,/operation timed out/i,/connection refused/i,/network.*unreachable/i,/ssl.*handshake/i,/unable to connect/i,/getaddrinfo/i,/econnrefused/i,/enotfound/i,/etimedout/i,/ehostunreach/i],HTTP_5XX_PATTERNS=[/\bHTTP[\s/]*5[0-9]{2}\b/i,/\bstatus:?\s*5[0-9]{2}\b/i,/\berror\s*5[0-9]{2}\b/i,/\bresponse.*?\b5[0-9]{2}\b/i],HTTP_429_PATTERNS=[/\bHTTP[\s/]*429\b/i,/\bstatus:?\s*429\b/i,/\berror\s*429\b/i,/rate.?limit/i,/too many requests/i];function classifyGitError(e){let t=e instanceof Error?e:Error(String(e)),S=extractStderr(t),w=`${t.message}\n${S}`.toLowerCase();return matchesAny(w,INDEX_LOCK_PATTERNS)?{class:`local`,subclass:`index-lock`,retryable:!0,message:`Git index locked by another process`,rawStderr:S}:matchesAny(w,DIRTY_TREE_PATTERNS)?{class:`local`,subclass:`dirty-tree`,retryable:!0,message:`Working tree has uncommitted changes`,rawStderr:S}:matchesAny(w,DISK_FULL_PATTERNS)?{class:`local`,subclass:`disk-full`,retryable:!0,message:`Disk full or quota exceeded`,rawStderr:S}:matchesAny(w,SCOPE_MISMATCH_PATTERNS)?{class:`auth`,subclass:`scope-mismatch`,retryable:!1,message:`GitHub token missing required scopes`,rawStderr:S}:matchesAny(w,AUTH_PATTERNS)?/\b401\b/.test(w)||/token.*expired/i.test(w)?{class:`auth`,subclass:`401`,retryable:!1,message:`Authentication failed — token may be expired`,rawStderr:S}:/\b403\b/.test(w)?matchesAny(w,PROTECTED_BRANCH_PATTERNS)?{class:`semantic`,subclass:`protected-branch`,retryable:!1,message:`Push rejected — branch is protected`,rawStderr:S}:{class:`auth`,subclass:`403`,retryable:!1,message:`Access denied (403)`,rawStderr:S}:{class:`auth`,subclass:`unknown-auth`,retryable:!1,message:`Authentication failed`,rawStderr:S}:matchesAny(w,PROTECTED_BRANCH_PATTERNS)?{class:`semantic`,subclass:`protected-branch`,retryable:!1,message:`Push rejected — branch is protected`,rawStderr:S}:matchesAny(w,NON_FAST_FORWARD_PATTERNS)?{class:`semantic`,subclass:`non-fast-forward`,retryable:!1,message:`Push rejected — remote has diverged (non-fast-forward)`,rawStderr:S}:matchesAny(w,MERGE_CONFLICT_PATTERNS)?{class:`semantic`,subclass:`merge-conflict`,retryable:!1,message:`Merge conflict — manual resolution required`,rawStderr:S}:matchesAny(w,LFS_PATTERNS)?{class:`structural`,subclass:`lfs-quota`,retryable:!1,message:`Git LFS quota exceeded`,rawStderr:S}:matchesAny(w,LARGE_FILE_PATTERNS)?{class:`structural`,subclass:`large-file`,retryable:!1,message:`File exceeds size limit`,rawStderr:S}:matchesAny(w,SECRET_DETECTED_PATTERNS)?{class:`structural`,subclass:`secret-detected`,retryable:!1,message:`Push blocked — secret or credential detected in content`,rawStderr:S}:matchesAny(w,PRE_RECEIVE_PATTERNS)?{class:`structural`,subclass:`pre-receive-hook`,retryable:!1,message:`Push rejected by server pre-receive hook`,rawStderr:S}:matchesAny(w,HTTP_429_PATTERNS)?{class:`network`,subclass:`429`,retryable:!0,message:`Rate limited — too many requests`,rawStderr:S}:matchesAny(w,HTTP_5XX_PATTERNS)?{class:`network`,subclass:`5xx`,retryable:!0,message:`Server error (5xx)`,rawStderr:S}:matchesAny(w,NETWORK_PATTERNS)?/timed? out/i.test(w)?{class:`network`,subclass:`timeout`,retryable:!0,message:`Connection timed out`,rawStderr:S}:/refused/i.test(w)||/econnrefused/i.test(w)?{class:`network`,subclass:`connection-refused`,retryable:!0,message:`Connection refused`,rawStderr:S}:/resolve.*host/i.test(w)||/enotfound/i.test(w)||/getaddrinfo/i.test(w)?{class:`network`,subclass:`dns`,retryable:!0,message:`DNS resolution failed`,rawStderr:S}:{class:`network`,subclass:`unknown-network`,retryable:!0,message:`Network error`,rawStderr:S}:{class:`local`,subclass:`unknown-local`,retryable:!0,message:t.message||`Unknown git error`,rawStderr:S}}function computeRemainingMs(e,t,S=Date.now()){if(!e)return 0;let w=new Date(e).getTime();if(Number.isNaN(w))return 0;let E=w+t*1e3;return Math.max(0,E-S)}const log=getLogger(`sync-engine`),SHA_HEX_40=/^[0-9a-f]{40}$/i;function jitteredMs(e){let t=e*1e3,S=t*.15*(2*Math.random()-1);return Math.round(t+S)}function isUnbornHead(e){try{let t=join(e,`.git`,`HEAD`);if(!existsSync(t))return!1;let S=readFileSync(t,`utf-8`).trim(),w=/^ref:\s+(refs\/.+)$/.exec(S);if(!w)return!1;let E=w[1];if(existsSync(join(e,`.git`,E)))return!1;let D=join(e,`.git`,`packed-refs`);if(existsSync(D)){let e=readFileSync(D,`utf-8`);if(RegExp(`^[0-9a-f]+\\s+${E}$`,`m`).test(e))return!1}return!0}catch{return!1}}function backoffMs(e){return e>=8?3600*1e3:e>=5?900*1e3:e>=3?300*1e3:0}var SyncEngine=class{state=`dormant`;projectDir;contentDir;contentFilter;contentRoot;pullIntervalSeconds;pushIntervalSeconds;syncEnabled;credentialArgs;cc1Broadcaster;onStateChange;setBatchInProgress;onAutoDisable;pullTimer=null;pushTimer=null;stateSaveTimer=null;lastSyncUtc=null;lastFetchUtc=null;lastPushedSha=null;consecutiveFailures=0;ahead=0;behind=0;conflictCount=0;error;pausedReason;currentBranch=`main`;pullInFlight=!1;pushInFlight=!1;hasRemote=!1;identityUnresolved=!1;statePath;conflictStore;constructor(e){this.projectDir=e.projectDir,this.contentDir=e.contentDir,this.contentFilter=e.contentFilter,this.contentRoot=e.contentRoot??``,this.pullIntervalSeconds=e.pullIntervalSeconds??30,this.pushIntervalSeconds=e.pushIntervalSeconds??60,this.syncEnabled=e.syncEnabled,this.credentialArgs=e.credentialArgs??[],this.cc1Broadcaster=e.cc1Broadcaster??null,this.onStateChange=e.onStateChange,this.setBatchInProgress=e.setBatchInProgress,this.onAutoDisable=e.onAutoDisable,this.statePath=resolve(getLocalDir(this.projectDir),`sync-state.json`),this.conflictStore=new ConflictStore(this.projectDir,this.currentBranch)}async start(){if(this.state!==`dormant`)return;this.loadState();let e=!1;try{let t=createGitInstance(this.projectDir,{credentialArgs:this.credentialArgs});e=(await t.git.raw(`remote`,`-v`)).trim().length>0,this.hasRemote=e;try{let e=(await t.git.raw(`rev-parse`,`--abbrev-ref`,`HEAD`)).trim();e&&e!==`HEAD`&&(this.currentBranch=e,this.conflictStore.setBranch(e))}catch{}}catch(e){log.warn({err:e},`[sync] remote detection failed`)}if(this.syncEnabled!==!0){e&&this.transitionTo(`disabled`),log.info({hasRemote:e,syncEnabled:this.syncEnabled},`[sync] sync not enabled — staying inactive`);return}if(!e){log.info({},`[sync] no remote detected — staying dormant`);return}this.transitionTo(`idle`);let t=existsSync(join(this.projectDir,`.git`,`MERGE_HEAD`));if(this.conflictCount>0&&!t)log.warn({count:this.conflictCount},`[sync] persisted conflicts but no MERGE_HEAD — clearing stale state`),this.conflictStore.clear(),this.conflictCount=0;else if(this.conflictCount>0&&t)try{let e=(await createGitInstance(this.projectDir,{credentialArgs:this.credentialArgs}).git.raw([`diff`,`--name-only`,`--diff-filter=U`])).trim(),t=new Set(e?e.split(`
|
|
3065
3065
|
`).map(e=>e.trim()).filter(Boolean):[]),S=this.conflictCount;for(let e of this.conflictStore.list())t.has(e.file)||this.conflictStore.removeConflict(e.file);this.conflictCount=this.conflictStore.count(),this.conflictCount<S&&log.info({cleared:S-this.conflictCount,remaining:this.conflictCount},`[sync] reconciled conflicts.json against git unmerged index`)}catch(e){log.warn({err:e},`[sync] failed to reconcile conflicts with git index`)}if(t&&this.conflictCount===0){log.warn({},`[sync] stale MERGE_HEAD detected with no tracked conflicts — aborting merge`);try{await createGitInstance(this.projectDir,{credentialArgs:this.credentialArgs}).git.raw([`merge`,`--abort`])}catch(e){log.warn({err:e},`[sync] git merge --abort for stale MERGE_HEAD failed`)}}if(this.conflictCount>0){this.transitionTo(`conflict`),log.warn({count:this.conflictCount},`[sync] restarted with active conflicts — sync paused`);return}let S=computeRemainingMs(this.lastFetchUtc,this.pullIntervalSeconds),w=computeRemainingMs(this.lastSyncUtc,this.pushIntervalSeconds);this.schedulePull(S>0?S:void 0),this.schedulePush(w>0?w:void 0),log.info({branch:this.currentBranch,pullDelayMs:S,pushDelayMs:w},`[sync] started`)}stop(){this.pullTimer!==null&&(clearTimeout(this.pullTimer),this.pullTimer=null),this.pushTimer!==null&&(clearTimeout(this.pushTimer),this.pushTimer=null),this.stateSaveTimer!==null&&(clearTimeout(this.stateSaveTimer),this.stateSaveTimer=null),this.state!==`dormant`&&this.transitionTo(`dormant`)}async destroy(){this.stop(),this.saveStateNow()}async setEnabled(e){if(this.syncEnabled!==e){if(this.syncEnabled=e,!e){this.pullTimer!==null&&(clearTimeout(this.pullTimer),this.pullTimer=null),this.pushTimer!==null&&(clearTimeout(this.pushTimer),this.pushTimer=null);let e=3e4,t=Date.now();for(;this.pullInFlight||this.pushInFlight;){if(Date.now()-t>3e4){log.warn({pullInFlight:this.pullInFlight,pushInFlight:this.pushInFlight},`[sync] setEnabled(false): timed out waiting for in-flight cycle to drain`);break}await setTimeout$1(50)}this.pausedReason=void 0,this.error=void 0,this.transitionTo(this.hasRemote?`disabled`:`dormant`),this.saveStateNow();return}if(this.hasRemote=await this.probeRemote(),this.pausedReason=void 0,this.error=void 0,this.consecutiveFailures=0,!this.hasRemote){this.transitionTo(`dormant`),this.saveStateNow();return}this.transitionTo(`idle`),this.schedulePull(0),this.schedulePush(),this.saveStateNow()}}async trigger(e=`sync`){this.consecutiveFailures=0,(this.pausedReason===`dirty-tree`||this.pausedReason===`external-changes-pending`)&&(this.pausedReason=void 0,this.error=void 0),this.state===`dormant`||this.state===`disabled`||this.state===`conflict`||this.state===`auth-error`?log.warn({op:e,state:this.state,syncEnabled:this.syncEnabled,hasRemote:this.hasRemote,pausedReason:this.pausedReason,conflictCount:this.conflictCount},`[sync] trigger(${e}) ignored — state=${this.state}`):log.info({op:e,state:this.state},`[sync] trigger(${e}) running`),e===`push`?await this.runPushCycle():(e===`pull`||await this.runPushCycle(),await this.runPullCycle())}getStatus(){return{state:this.state,lastSyncUtc:this.lastSyncUtc,lastFetchUtc:this.lastFetchUtc,lastPushedSha:this.lastPushedSha,ahead:this.ahead,behind:this.behind,consecutiveFailures:this.consecutiveFailures,conflictCount:this.conflictCount,hasRemote:this.hasRemote,syncEnabled:this.syncEnabled===!0,identityUnresolved:this.identityUnresolved,error:this.error,pausedReason:this.pausedReason}}async refreshIdentity(){let e=await resolveGitIdentity(this.projectDir)===null;this.identityUnresolved!==e&&(this.identityUnresolved=e,this.cc1Broadcaster?.signal(`sync-status`))}async refreshRemote(){this.hasRemote||await this.probeRemote()&&(this.hasRemote=!0,log.info({syncEnabled:this.syncEnabled},`[sync] remote detected post-boot — re-evaluating state`),this.syncEnabled===!0?(this.transitionTo(`idle`),this.schedulePull(0),this.schedulePush()):this.transitionTo(`disabled`))}async probeRemote(){if(!existsSync(join(this.projectDir,`.git`)))return!1;try{return(await createGitInstance(this.projectDir,{credentialArgs:this.credentialArgs}).git.raw(`remote`,`-v`)).trim().length>0}catch(e){return log.warn({err:e},`[sync] remote detection failed`),!1}}getConflicts(){return this.conflictStore.list()}async resolveConflict(e,t,S){await this.conflictStore.resolveConflict(e,t,S),this.conflictCount=this.conflictStore.count(),this.conflictCount===0&&this.state===`conflict`&&(this.transitionTo(`idle`),this.pausedReason=void 0,this.schedulePull(),this.schedulePush()),this.scheduleSaveState()}updateCurrentBranch(e){e===null?this.state!==`dormant`&&this.state!==`disabled`&&(this.transitionTo(`disabled`),this.pausedReason=`detached-head`,this.scheduleSaveState()):this.currentBranch!==e&&(this.currentBranch=e,this.conflictStore.setBranch(e),this.state===`disabled`&&this.pausedReason===`detached-head`&&(this.pausedReason=void 0,this.transitionTo(`idle`),this.schedulePull(),this.schedulePush()))}schedulePull(e){this.pullTimer!==null&&clearTimeout(this.pullTimer);let t=e??this.effectivePullDelayMs();this.pullTimer=setTimeout(()=>{this.pullTimer=null,this.runPullCycle().catch(e=>{log.error({err:e},`[sync] pull cycle uncaught error`)})},t)}schedulePush(e){this.pushTimer!==null&&clearTimeout(this.pushTimer);let t=e??jitteredMs(this.pushIntervalSeconds);this.pushTimer=setTimeout(()=>{this.pushTimer=null,this.runPushCycle().catch(e=>{log.error({err:e},`[sync] push cycle uncaught error`)})},t)}effectivePullDelayMs(){let e=this.consecutiveFailures,t=backoffMs(e);return t>0?t:jitteredMs(this.pullIntervalSeconds)}async runPullCycle(){if(!this.pullInFlight&&!(this.state===`dormant`||this.state===`disabled`)){if(this.state===`conflict`){this.schedulePull();return}if(isUnbornHead(this.projectDir)){this.schedulePull();return}this.pullInFlight=!0;try{await this.doPullCycle()}finally{this.pullInFlight=!1,this.schedulePull()}}}async doPullCycle(){let e=createGitInstance(this.projectDir,{credentialArgs:this.credentialArgs}),t;try{let S=(await e.git.raw(`rev-parse`,`--abbrev-ref`,`HEAD`)).trim();if(!S||S===`HEAD`){this.transitionTo(`disabled`),this.pausedReason=`detached-head`,log.warn({},`[sync] detached HEAD — pausing sync`);return}t=S,this.currentBranch=t}catch(e){this.handleError(classifyGitError(e instanceof Error?e:Error(String(e))));return}this.transitionTo(`fetching`);try{await e.git.fetch(`origin`),this.lastFetchUtc=new Date().toISOString(),this.consecutiveFailures=0,this.error=void 0}catch(e){let t=classifyGitError(e instanceof Error?e:Error(String(e)));this.handleError(t);return}try{let t=await e.git.status();this.ahead=t.ahead,this.behind=t.behind}catch{}if(this.behind>0&&this.conflictCount===0){this.transitionTo(`pulling`),this.setBatchInProgress?.(!0);try{if(await this.commitDirtyContentFilesToHead(e),!await this.pauseIfNonContentDirty(e))return;await e.git.merge([`origin/${t}`]),this.lastSyncUtc=new Date().toISOString(),this.behind=0,this.transitionTo(`idle`)}catch(e){let t=classifyGitError(e instanceof Error?e:Error(String(e)));t.class===`semantic`&&t.subclass===`merge-conflict`?await this.handleMergeConflict():this.handleError(t);return}finally{this.setBatchInProgress?.(!1)}}else this.transitionTo(`idle`);this.scheduleSaveState()}async runPushCycle(){if(!this.pushInFlight&&!(this.state===`dormant`||this.state===`disabled`)&&!(this.state===`conflict`||this.state===`auth-error`)){if(isUnbornHead(this.projectDir)){this.schedulePush();return}this.pushInFlight=!0;try{await this.doPushCycle(1)}finally{this.pushInFlight=!1,this.schedulePush()}}}async doPushCycle(e=0){let t=this.gatherContentFilesSync(),S=join(tmpdir(),`ok-sync-idx-${process.pid}-${Date.now()}.idx`),w=null;this.transitionTo(`pushing`);try{await withParentLock(async()=>{let e=createGitInstance(this.projectDir,{credentialArgs:this.credentialArgs,gitIndexFile:S});if(isUnbornHead(this.projectDir)){log.info({},`[sync] repo has no commits yet — skipping push cycle`),this.transitionTo(`idle`);return}let E;try{E=(await e.git.revparse(`HEAD`)).trim()}catch(e){let t=e instanceof Error?e.message:String(e),S=`${t}\n${e.git?.toString()??t}`;if(/unknown revision or path not in the working tree/i.test(S)||/ambiguous argument 'HEAD'/i.test(S)||/does not have any commits yet/i.test(S)){log.info({},`[sync] repo has no commits yet — skipping push cycle`),this.transitionTo(`idle`);return}this.handleError(classifyGitError(e instanceof Error?e:Error(String(e))));return}await e.git.raw([`read-tree`,E]);let D=new Set;try{let t=(await e.git.raw([`ls-tree`,`-r`,`--name-only`,E])).trim();for(let e of t?t.split(`
|
|
@@ -3070,5 +3070,5 @@ In headless mode, write the recap into the research article's "Further reading"
|
|
|
3070
3070
|
`,`
|
|
3071
3071
|
`).split(`
|
|
3072
3072
|
`),S=[],w=!1,E=``;for(let e of t){let t=/^\s{0,3}([`~]{3,})/.exec(e);if(t){w?RegExp(`^\\s{0,3}${E[0]==="`"?"`":`~`}{${E.length},}\\s*$`).test(e)&&(w=!1,E=``):(w=!0,E=t[1]);continue}if(w)continue;let D=stripInlineCodeSpans(e);for(TAG_VALUE_RE.lastIndex=0;;){let e=TAG_VALUE_RE.exec(D);if(e===null)break;let t=e[2];t&&S.push(t)}}return S}var TagIndex=class{contentDir;contentFilter;state=createEmptyState();constructor(e){this.contentDir=e.contentDir,this.contentFilter=e.contentFilter}updateDocumentFromMarkdown(e,t){if(!(isSystemDoc(e)||isConfigDoc(e)))try{let{frontmatter:S,body:w}=stripFrontmatter(t),E=extractFrontmatterTags(S?unwrapFrontmatterFences(S):``),D=extractInlineTagsFromBody(w),O=new Set([...E,...D]),k=new Set;for(let e of O)for(let t of expandTagToHierarchy(e))k.add(t);this.applyDocSnapshot(e,O,k)}catch(t){console.warn(`[tag-index] Failed to scan ${e} for tag extraction:`,t),this.deleteDocument(e)}}deleteDocument(e){if(isSystemDoc(e)||isConfigDoc(e))return;let t=this.state.byDoc.get(e);if(t){for(let S of t){let t=this.state.byTag.get(S);t&&(t.delete(e),t.size===0&&this.state.byTag.delete(S))}this.state.byDoc.delete(e),this.state.byDocLiteral.delete(e)}}renameDocument(e,t,S){this.deleteDocument(e),this.updateDocumentFromMarkdown(t,S)}getDocsForTag(e){let t=this.state.byTag.get(e);return t?[...t].sort((e,t)=>e.localeCompare(t)):[]}getDocsForTagWithMatches(e){let t=this.state.byTag.get(e);if(!t)return[];let S=[];for(let w of t){let t=this.state.byDocLiteral.get(w);if(!t)continue;let E=tagsMatchingPrefix(t,e);S.push({docName:w,matchingTags:[...E].sort((e,t)=>e.localeCompare(t))})}return S.sort((e,t)=>e.docName.localeCompare(t.docName))}getAllTags(){let e=[...this.state.byTag.entries()],t=e.map(([e])=>e),S=new Set;for(let e of t){let t=e.indexOf(`/`);t>0&&S.add(e.slice(0,t));let w=t;for(;w>0;)S.add(e.slice(0,w)),w=e.indexOf(`/`,w+1)}return e.map(([e,t])=>({name:e,count:t.size,isLeaf:!S.has(e)})).sort((e,t)=>e.name.localeCompare(t.name))}init(){if(this.state=createEmptyState(),!existsSync(this.contentDir))return;let e=this.listDocsWithPaths();for(let{docName:t,filePath:S}of e)try{let e=readFileSync(S,`utf-8`);this.updateDocumentFromMarkdown(t,e)}catch(e){console.warn(`[tag-index] Failed to read ${t} during init:`,e)}}applyDocSnapshot(e,t,S){let w=this.state.byDoc.get(e)??new Set;for(let t of w){if(S.has(t))continue;let w=this.state.byTag.get(t);w&&(w.delete(e),w.size===0&&this.state.byTag.delete(t))}for(let t of S){let S=this.state.byTag.get(t);S||(S=new Set,this.state.byTag.set(t,S)),S.add(e)}S.size===0?(this.state.byDoc.delete(e),this.state.byDocLiteral.delete(e)):(this.state.byDoc.set(e,S),this.state.byDocLiteral.set(e,t))}listDocsWithPaths(){let e=[];this.walkContentDir(this.contentDir,e),e.sort((e,t)=>e.docName===t.docName?t.filePath.localeCompare(e.filePath):e.docName.localeCompare(t.docName));let t=new Set;return e.filter(({docName:e})=>t.has(e)?!1:(t.add(e),!0))}walkContentDir(e,t){let S;try{S=readdirSync(e,{withFileTypes:!0})}catch(t){console.warn(`[tag-index] Failed to read directory ${e}:`,t);return}for(let w of S){let S=join(e,w.name);if(w.isDirectory()){let e=relative(this.contentDir,S);if(this.contentFilter&&e&&this.contentFilter.isDirExcluded(e))continue;this.walkContentDir(S,t);continue}if(!w.isFile()||!isSupportedDocFile(w.name))continue;let E=relative(this.contentDir,S);this.contentFilter?.isExcluded(E)||t.push({docName:stripDocExtension(E),filePath:S})}}};const PARK_SNAPSHOT_ORIGIN=(()=>{let e=Object.freeze({origin:`park-snapshot`,paired:!0});return Object.freeze({source:`local`,skipStoreHooks:!1,context:e})})();function createServer$1(e){let{contentDir:t,projectDir:S=t,quiet:w=!0,debounce:E=2e3,maxDebounce:D=1e4,gitEnabled:O=!0,commitDebounceMs:k=3e4,wipRef:j=`refs/wip/main`,configHomedirOverride:F,enableTestRoutes:L=!1,shadowRepo:B,contentRoot:H,destroyTimeoutMs:q=1e4,localOpCliArgs:J,skipStateManifestCheck:Y=!1}=e,ee=getLogger(`server`);function te(){let e=readConfigSafely({absPath:resolveConfigPath(`project-local`,S),sideline:!1,warn:e=>ee.warn({message:e},`[config] could not read project-local config`)}),t=e.value.autoSync?.enabled;return t==null?(e.valid||ee.warn({},`[config] project-local autoSync.enabled unavailable (config invalid) — falling back to project config`),readConfigSafely({absPath:resolveConfigPath(`project`,S),sideline:!1,warn:e=>ee.warn({message:e},`[config] could not read project config`)}).value.autoSync?.enabled===!0):t===!0}initTelemetry();let ne=randomUUID(),ae=getLocalDir(S);if(acquireServerLock(ae,{port:e.port??0,worktreeRoot:S,kind:e.lockKind??`interactive`,capabilities:[`http`,`ws`]}),!Y)try{assertCompatibleStateManifest({lockDir:ae,shadowRepoDir:resolveShadowDir(S)})}catch(e){throw releaseServerLock(ae),e}let oe=createBasenameIndex(),se=(e,t)=>oe.resolveEmbed(e,t),ce=(e,S)=>{let w=oe.resolveEmbed(e,S);if(!w&&e.includes(`/`)&&(w=e.replace(/^\.?\//,``)),!w)return null;let E=resolve(t,w),D=resolve(t);if(E!==D&&!E.startsWith(`${D}/`))return null;try{let e=statSync(E);return e.isFile()?e.size:null}catch{return null}},ue,de,fe,me,ge,_e,ve,ye=null,Ce=null,we=null,Te=null,De=new Set,je=!1,Me,Pe,Ie,Re=new Promise((e,t)=>{Pe=e,Ie=t});function ze(e){ye?.signal(e)}let Be=2e3,Ve=null;function Ue(){Ve!==null&&clearTimeout(Ve),Ve=setTimeout(()=>{Ve=null,de.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist debounced cache:`,e)})},2e3)}let We=new RecentlyRemovedDocs(void 0,{onEviction:()=>incrementRecentlyRemovedDocsEviction(),onSizeChange:e=>setRecentlyRemovedDocsSize(e)}),Ge=(e,t)=>{isSystemDoc(e)||isConfigDoc(e)||We.setRenamed(e,t)},Ke=e=>{if(!(isSystemDoc(e)||isConfigDoc(e))){if(We.peek(e)?.kind===`renamed`){console.info(JSON.stringify({event:`recently-removed-docs-unpaired-delete-suppressed`,docName:e,source:`watcher-delete`}));return}We.setDeleted(e)}},Xe=e=>{isSystemDoc(e)||isConfigDoc(e)||We.delete(e)};try{ue=createContentFilter({projectDir:S,contentDir:t,onAfterRebuild:()=>{de.rebuildFromDisk(getActiveBranch()).catch(e=>{getLogger(`server-factory`).warn({err:e},`[content-filter] backlink-index rebuild failed after onAfterRebuild`)});try{fe.init()}catch(e){getLogger(`server-factory`).warn({err:e},`[content-filter] tag-index rebuild failed after onAfterRebuild`)}try{let e=Lt?.pruneFileIndexNowExcluded()??0;e>0&&getLogger(`server-factory`).info({pruned:e},`[content-filter] pruned now-excluded entries from fileIndex`)}catch(e){getLogger(`server-factory`).warn({err:e},`[content-filter] fileIndex prune failed after onAfterRebuild`)}}}),de=new BacklinkIndex({projectDir:S,contentDir:t,contentFilter:ue}),fe=new TagIndex({contentDir:t,contentFilter:ue});try{fe.init()}catch(e){console.warn(`[server-factory] tag-index init failed; continuing with empty index:`,e)}me={current:B},ge=createPersistenceExtension({contentDir:t,projectDir:S,gitEnabled:O,commitDebounceMs:k,wipRef:j,shadowRef:me,contentRoot:H,backlinkIndex:de,configHomedirOverride:F,getCurrentBranch:()=>Rt?.getLastKnownBranch()??null,resolveEmbed:se,resolveSize:ce,getPrincipal:()=>Te,onAgentCommit:()=>ye?.signal(`session-activity`),onDiskFlush:(e,t)=>ye?.emitDiskAck(e,t),onConfigRejected:(e,t)=>ye?.emitConfigValidationRejected(e,t),mdManager:e.mdManager}),_e=new Hocuspocus({quiet:w,debounce:E,maxDebounce:D,extensions:[ge.extension]});let q=_e.shouldUnloadDocument.bind(_e);_e.shouldUnloadDocument=e=>{if(De.has(e)||je&&q(e))return!0;let t=e.name;return isSystemDoc(t)||isConfigDoc(t)||getReconciledBase(t)!==void 0||e.getXmlFragment(`default`).length!==0||e.getText(`source`).length!==0?!1:q(e)},Me=async e=>{De.add(e);try{await _e.unloadDocument(e)}finally{De.delete(e)}},ye=new CC1Broadcaster(_e),Ce=new AgentFocusBroadcaster(_e),we=new AgentPresenceBroadcaster(_e),ve=new AgentSessionManager(_e);let Y=createLiveDerivedIndexExtension({backlinkIndex:de,tagIndex:fe,signalChannel:ze});_e.configuration.extensions.push(Y),_e.configuration.extensions.push({__kind:`principal-auth`,async onAuthenticate(e){let t=e.token,S=parseHocuspocusAuthToken(t),w=S?.expectedServerInstanceId;if(typeof w==`string`&&w.length>0&&w!==ne)throw new HocuspocusAuthRejection(`server-instance-mismatch`,`server instance mismatch: client claimed ${w}, this server is ${ne}`);let E=S?.expectedBranch,D=getActiveBranch();if(typeof E==`string`&&E.length>0&&E!==D)throw new HocuspocusAuthRejection(`branch-mismatch`,`branch mismatch: client claimed ${E}, server is on ${D}`);if(!S)return;let O=e.context;typeof S.principalId==`string`&&(Te&&S.principalId===Te.id?O.principalId=Te.id:Te?console.warn(JSON.stringify({event:`principal-token-mismatch`,claimed:S.principalId,loaded:Te.id})):O.principalId=S.principalId),typeof S.tabSessionId==`string`&&(O.tabSessionId=S.tabSessionId),O.kind=`human`}}),_e.configuration.extensions.push({__kind:`config-doc-admission-guard`,async onAuthenticate(e){if(!isConfigDoc(e.documentName))return;let t=e.request,S=t.socket?.remoteAddress;if(S!==void 0&&!isLoopbackAddress(S))throw Error(`config-doc admission requires loopback peer (peer=${S}, doc=${e.documentName})`);let w=e.requestHeaders,E=(w&&typeof w.get==`function`?w.get(`host`):null)??t.headers?.host??void 0;if(!isAllowedWorkspaceHostHeader(E))throw Error(`config-doc admission requires loopback Host header (host=${E??`<absent>`}, doc=${e.documentName})`)}});let ee=resolve(t);function te(e){if(!isSafeDocName(e))return null;let t=resolve(ee,`${e}${getDocExtension(e)}`);return!t.startsWith(`${ee}/`)&&t!==ee?null:t}_e.configuration.extensions.push({__kind:`removal-redirect-guard`,async onAuthenticate(e){await runRemovalRedirectGuard(e.documentName,{recentlyRemovedDocs:We,resolveFilePath:te,fileExists:existsSync})}}),_e.configuration.extensions.push({__kind:`system-doc-broadcast-guard`,async beforeHandleMessage(e){if(e.documentName!==`__system__`)return;let t=new IncomingMessage(e.update);if(t.readVarString(),t.readVarUint()===MessageType.BroadcastStateless)throw Error(`inbound BroadcastStateless on ${SYSTEM_DOC_NAME} rejected — server-only channel`)}});let ae=createApiExtension({hocuspocus:_e,sessionManager:ve,contentDir:t,contentFilter:ue,serverInstanceId:ne,getFileIndex:()=>Lt?Lt.getFileIndex():new Map,getFolderIndex:()=>Lt?Lt.getFolderIndex():new Map,getAliasMap:()=>Lt?Lt.getAliasMap():new Map,rescanFiles:()=>Lt?.rescanFromDisk(),enableTestRoutes:L,shadowRef:me,flushGitCommit:()=>ge.flushPendingGitCommit(),flushContributors:()=>ge.flushContributors(),getCurrentBranch:()=>Rt?.getLastKnownBranch()??null,getDiskAckSVs:()=>ye?.getLatestDiskAckSVsAsBase64()??{},contentRoot:H,backlinkIndex:de,tagIndex:fe,signalChannel:ze,agentFocusBroadcaster:Ce,agentPresenceBroadcaster:we,onAgentWrite:e.onAgentWrite,getSyncEngine:()=>zt,localOpCliArgs:J,projectDir:S,resolveEmbed:se,getPrincipal:()=>Te,forceUnloadDocument:Me,ready:Re,recentlyRemovedDocs:We});_e.configuration.extensions.push(ae),_e.configuration.extensions.push(createServerObserverExtension({mdManager,schema,shadowRef:me,contentRoot:H,getCurrentBranch:()=>Rt?.getLastKnownBranch()??null,resolveEmbed:se,resolveSize:ce})),_e.configuration.extensions.push(createSyncHandshakeSpanExtension())}catch(e){throw releaseServerLock(ae),e}let $e=null,nt=new Map,rt=[];function it(e,t){let S=resolve(e,`rescue`),w=resolve(S,`${t}${getDocExtension(t)}`);return w.startsWith(`${S}/`)?w:null}function at(e){let t=_e.documents.get(e);if(!t)return null;let{frontmatter:S,body:w}=stripFrontmatter(t.getText(`source`).toString());return prependFrontmatter(S,w)}let st=(e,t)=>applyExternalChange(_e,e,t,se,ce),vt=e=>{if(!e)return;let t=`[[${e}]]`;for(let[S]of _e.documents){if(isSystemDoc(S)||isConfigDoc(S))continue;let w=_e.documents.get(S);if(!w)continue;let E=w.getText(`source`).toString();if(E.includes(t))try{w.transact(()=>{applyDiskContentToDoc(w,E,se,S)},FILE_WATCHER_ORIGIN)}catch(t){ee.error({err:t,docName:S,assetBasename:e},`[asset-event] failed to re-render ${S} for asset basename ${e}`)}}},Tt=null,Et=e=>{e&&(Tt===null&&(Tt=new Set,setImmediate(()=>{let e=Tt;if(Tt=null,e)try{for(let t of e)vt(t)}catch(t){ee.error({err:t,basenames:[...e]},`[asset-event] dedup rerender pass crashed`)}})),Tt.add(e))};function Dt(e){switch(e.kind){case`rename`:return e.newDocName;case`asset-create`:case`asset-delete`:case`folder-create`:case`folder-delete`:return e.relativePath;case`create`:case`update`:case`delete`:case`conflict`:return e.docName;default:return assertNeverDiskEvent(e)}}async function jt(e){try{switch(e.kind){case`create`:ee.info({docName:e.docName},`[reconcile] create: ${e.docName}`),de.updateDocumentFromMarkdown(e.docName,e.content),Ue(),fe.updateDocumentFromMarkdown(e.docName,e.content),ze(`files`),ze(`backlinks`),ze(`graph`),ze(`tags`),Xe(e.docName);break;case`update`:{let{docName:t,content:S}=e,w=_e.documents.get(t);if(!w){de.updateDocumentFromMarkdown(t,S),Ue(),fe.updateDocumentFromMarkdown(t,S),ze(`backlinks`),ze(`graph`),ze(`tags`);return}let E=getReconciledBase(t)??``,D=at(t)??E,O=reconcile({docName:t,base:E,ours:D,theirs:S}),k=contentHash(E).slice(0,6),j=contentHash(D).slice(0,6),F=contentHash(S).slice(0,6);switch(ee.info({docName:t,base:k,ours:j,theirs:F,result:O.kind},`[reconcile] ${t} base=${k} ours=${j} theirs=${F} result=${O.kind}`),O.kind){case`noop`:de.updateDocumentFromMarkdown(t,S),Ue(),fe.updateDocumentFromMarkdown(t,S),ze(`backlinks`),ze(`graph`),ze(`tags`);break;case`clean`:try{st(t,O.newContent),setReconciledBase(t,O.newContent),incrementReconcile(),de.updateDocumentFromMarkdown(t,S),Ue(),fe.updateDocumentFromMarkdown(t,S),ze(`backlinks`),ze(`graph`),ze(`tags`)}catch(e){ee.error({err:e,docName:t},`[reconcile] failed to apply clean content to Y.Doc for ${t}`),setReconciledBase(t,S)}break;case`merged`:try{st(t,O.newContent),setReconciledBase(t,O.newContent),incrementReconcile(),de.updateDocumentFromMarkdown(t,S),Ue(),fe.updateDocumentFromMarkdown(t,S),ze(`backlinks`),ze(`graph`),ze(`tags`)}catch(e){ee.error({err:e,docName:t},`[reconcile] failed to apply merged content to Y.Doc for ${t}`),setReconciledBase(t,S)}break;case`conflicts`:try{st(t,O.newContent),setReconciledBase(t,O.newContent),incrementReconcile(),incrementConflict(),de.updateDocumentFromMarkdown(t,S),Ue(),fe.updateDocumentFromMarkdown(t,S),ze(`backlinks`),ze(`graph`),ze(`tags`)}catch(e){ee.error({err:e,docName:t},`[reconcile] failed to apply conflict content to Y.Doc for ${t}`),setReconciledBase(t,S)}break;case`refused`:{incrementConflict();let e=w.getMap(`lifecycle`);e.set(`status`,`conflict`),e.set(`reason`,O.reason);break}}break}case`delete`:{let{docName:t}=e,S=_e.documents.get(t);if(!S){de.deleteDocument(t),Ue(),fe.deleteDocument(t),ze(`files`),ze(`backlinks`),ze(`graph`),ze(`tags`),Ke(t),console.info(JSON.stringify({event:`recently-removed-docs-populate`,docName:t,kind:`deleted`,source:`watcher-delete`}));return}let w=getReconciledBase(t)??``,E=at(t)??``,D=E!==w;if(D&&me.current){let e=me.current,S=Rt?.getLastKnownBranch()??`main`;queueMicrotask(()=>{saveInMemoryCheckpoint(e,H??``,{kind:`external-change-rescue`,docName:t,contents:E,label:`External change recovered @ ${new Date().toISOString()}`,branch:S,metadata:{incomingDiskSha:``}}).then(()=>{incrementRescueBuffer(),ee.info({docName:t},`[reconcile] rescue checkpoint saved (delete): ${t}`)}).catch(e=>{ee.error({docName:t,err:e},`[reconcile] rescue checkpoint write failed: ${t}`)})})}S.getMap(`lifecycle`).set(`status`,`deleted-upstream`),deleteReconciledBase(t),de.deleteDocument(t),Ue(),fe.deleteDocument(t),ee.info({docName:t,isDirty:D},`[reconcile] delete: ${t} (dirty=${D})`),_e.closeConnections(t),await Me(S),ze(`files`),ze(`backlinks`),ze(`graph`),ze(`tags`),Ke(t),console.info(JSON.stringify({event:`recently-removed-docs-populate`,docName:t,kind:`deleted`,source:`watcher-delete`}));break}case`rename`:{let{oldDocName:t,newDocName:S,content:w}=e,E=_e.documents.get(t);if(deleteReconciledBase(t),setReconciledBase(S,w),de.renameDocument(t,S,w),Ue(),fe.renameDocument(t,S,w),E){let e=E.getMap(`lifecycle`);e.set(`status`,`renamed`),e.set(`newPath`,S)}ee.info({oldDocName:t,newDocName:S},`[reconcile] rename: ${t} → ${S}`),ze(`files`),ze(`backlinks`),ze(`graph`),ze(`tags`),Ge(t,S),console.info(JSON.stringify({event:`recently-removed-docs-populate`,from:t,to:S,kind:`renamed`,source:`watcher-rename`}));break}case`conflict`:{let{docName:t}=e,S=_e.documents.get(t);if(!S)return;let w=S.getMap(`lifecycle`);w.set(`status`,`conflict`),w.set(`reason`,`conflict-markers`),ee.info({docName:t},`[reconcile] conflict markers detected: ${t}`);break}case`asset-create`:oe.add(e.relativePath),ze(`files`),Et(basename(e.relativePath));break;case`asset-delete`:oe.remove(e.relativePath),ze(`files`),Et(basename(e.relativePath));break;case`folder-create`:case`folder-delete`:ze(`files`);break;default:assertNeverDiskEvent(e)}}catch(t){let S=Dt(e);ee.error({err:t,kind:e.kind,label:S},`[reconcile] failed to handle ${e.kind} for ${S}`)}}let Mt=[];async function Ft(e){if(isBatchInProgress()){Mt.push(e);return}await jt(e)}async function It(){let e=Mt.splice(0,Mt.length);for(let t of e)await jt(t)}let Lt=null,Rt=null,zt=null,Bt=null;async function Vt(e){if(_e.documents.size===0)return;let t=!1,S=new Promise(e=>{_e.configuration.extensions.push({async afterUnloadDocument({instance:S}){!t&&S.getDocumentsCount()===0&&(t=!0,e())}})}),w=Array.from(_e.documents.keys());_e.closeConnections(),_e.flushPendingStores();for(let e of _e.documents.values())e.getConnectionsCount()===0&&_e.unloadDocument(e).catch(t=>{console.warn(JSON.stringify({event:`ok-shutdown-unload-document-failed`,docName:e.name,reason:t instanceof Error?t.message:String(t)}))});let E,D=new Promise((S,D)=>{E=setTimeout(()=>{t=!0;let S=Array.from(_e.documents.keys()),E=[],O=[];if(me.current){for(let e of S)if(!(isSystemDoc(e)||isConfigDoc(e)))try{let t=at(e);if(t===null){ee.warn({docName:e},`[rescue] skipping ${e} — document dropped from map mid-rescue`),O.push(e);continue}let S=it(me.current.gitDir,e);if(!S){ee.warn({docName:e,gitDir:me.current.gitDir},`[rescue] path-traversal guard rejected docName: ${e}`),O.push(e);continue}mkdirSync(dirname(S),{recursive:!0}),writeFileSync(S,t,`utf-8`),incrementRescueBuffer(),E.push(e),ee.info({docName:e},`[rescue] rescue buffer saved on flush timeout: ${e}`)}catch(t){O.push(e),ee.error({err:t,docName:e},`[rescue] failed to write rescue buffer for ${e}`)}}else ee.warn({stillLoadedCount:S.length},`[rescue] shadow repo unavailable at flush timeout — ${S.length} doc(s) will be lost: [${S.join(`, `)}]`),O.push(...S);let k=E.length>0||O.length>0?` — rescued [${E.join(`, `)}]${O.length>0?`, lost [${O.join(`, `)}]`:``}`:``;D(Error(`flushAllStoresAndWait timeout after ${e}ms — ${S.length}/${w.length} docs did not unload: [${S.join(`, `)}]${k}`))},e)});try{await Promise.race([S,D])}finally{E!==void 0&&clearTimeout(E)}}async function Ht(){return Bt||(Bt=(async()=>{let e=Date.now(),t=[];je=!0,Ve!==null&&(clearTimeout(Ve),Ve=null);let w,E=await Promise.race([Re.then(()=>`completed`,e=>(ee.debug({err:e},`[server] init incomplete during shutdown`),`failed`)),new Promise(e=>{w=setTimeout(()=>e(`timeout`),5e3)})]);w!==void 0&&clearTimeout(w),E===`timeout`&&ee.warn({},`[server] init did not complete within 5s during shutdown`);let D=_e.documents.size;try{try{try{Rt&&=(await Rt.unsubscribe(),null),Lt&&=(await Lt.unsubscribe(),null);for(let{docName:e,cleanup:t}of rt)try{await t()}catch(t){ee.warn({err:t,docName:e},`[server] failed to stop config-file-watcher for ${e}`)}rt.length=0}catch(e){t.push({phase:`watcher-unsubscribe`,error:e instanceof Error?e.message:String(e)}),ee.error({err:e},`[server] shutdown phase-1 watcher unsubscribe failed`)}try{ye?.destroy(),we?.destroy(),$e&&=(await $e.disconnect(),null);for(let[e,t]of nt)try{await t.disconnect()}catch(t){ee.warn({err:t,docName:e},`[server] failed to disconnect ${e} during shutdown`)}nt.clear()}catch(e){t.push({phase:`cc1-teardown`,error:e instanceof Error?e.message:String(e)}),ee.error({err:e},`[server] shutdown phase-1b CC1 teardown failed`)}try{await ve.closeAll()}catch(e){t.push({phase:`agent-session-drain`,error:e instanceof Error?e.message:String(e)}),ee.error({err:e},`[server] shutdown phase-2 agent session drain failed`)}try{await Vt(q)}catch(e){t.push({phase:`flush-all-stores`,error:e instanceof Error?e.message:String(e)}),ee.error({err:e},`[server] shutdown phase-3 flush failed`)}let e;try{await Promise.race([(async()=>{await ge.flushPendingGitCommit(),await ge.waitForPendingCommits()})(),new Promise((t,S)=>{e=setTimeout(()=>S(Error(`L2 git flush timeout`)),q)})])}catch(e){t.push({phase:`git-commit-flush`,error:e instanceof Error?e.message:String(e)}),ee.error({err:e},`[server] shutdown phase-4 git commit flush failed`)}finally{e!==void 0&&clearTimeout(e)}try{zt&&=(await zt.destroy(),null)}catch(e){t.push({phase:`sync-engine-stop`,error:e instanceof Error?e.message:String(e)}),ee.error({err:e},`[server] shutdown sync-engine-stop failed`)}}finally{if(me.current){try{let e=(await esm_default({baseDir:S,timeout:{block:5e3}}).revparse(`HEAD`)).trim();e&&writeFileSync(resolve(me.current.gitDir,`last-known-head`),e,`utf-8`)}catch{}try{destroyShadowRepo(me.current)}catch(e){t.push({phase:`shadow-repo-release`,error:e instanceof Error?e.message:String(e)}),ee.error({err:e},`[server] shutdown phase-5 destroyShadowRepo failed`)}}let w=Date.now()-e;t.length===0?ee.info({documentCount:D,durationMs:w},`[server] shutdown flushed ${D} documents in ${w}ms`):ee.warn({documentCount:D,durationMs:w,phaseErrors:t},`[server] shutdown flushed ${D} documents in ${w}ms with ${t.length} phase error(s)`)}}finally{try{releaseServerLock(ae)}catch(e){t.push({phase:`server-lock-release`,error:e instanceof Error?e.message:String(e)}),ee.error({err:e},`[server] shutdown phase-6 releaseServerLock failed`)}try{await shutdownTelemetry()}catch(e){t.push({phase:`telemetry-shutdown`,error:e instanceof Error?e.message:String(e)})}}})(),Bt)}let Ut=[];async function Wt(){try{Te=await loadPrincipal(S),ee.info({principalId:Te.id},`[server] principal loaded`)}catch(e){ee.warn({err:e},`[server] principal load failed — browser writes will use SERVICE_WRITER`)}if(!me.current)try{me.current=await initShadowRepo(S),ee.info({gitDir:me.current.gitDir},`[server] history repo initialized at ${me.current.gitDir}`)}catch(e){ee.error({err:e},`[server] history repo init failed`),Ut.push(`shadow-repo`)}if(me.current){let e=null;try{e=loadRenameLogIndex(me.current.gitDir),sweepLazyPopOrphans(me.current.gitDir,e),setRenameLogIndex(me.current.gitDir,e),ee.info({entries:e.byTo.size},`[server] rename log loaded (${e.byTo.size} entries)`)}catch(e){ee.warn({err:e},`[rename-log] boot-time load/sweep failed; rename history unavailable`)}if(e){let t=1e4;try{await Promise.race([gcRenameLog(me.current,e,{rebuild:!0}),new Promise((e,S)=>setTimeout(()=>S(Error(`boot-time GC exceeded ${t}ms`)),t))])}catch(e){ee.warn({err:e},`[rename-log] boot-time GC/rebuild failed; index loaded without GC`)}}}if(me.current)try{await shadowGit(me.current).raw(`rev-parse`,`--git-dir`)}catch(e){let t=e instanceof Error?e.message:String(e);if(t.includes(`not a git repository`)||t.includes(`invalid object`)){ee.warn({},`[server] history repo appears corrupted — reinitializing`);try{me.current=await initShadowRepo(S)}catch(e){ee.error({err:e},`[server] history repo reinit failed`),me.current=void 0,Ut.includes(`shadow-repo`)||Ut.push(`shadow-repo`)}}else ee.error({err:e},`[server] history repo check failed (transient?)`)}if(me.current)try{let e=resolve(me.current.gitDir,`last-known-head`),t=null;try{t=readFileSync(e,`utf-8`).trim()||null}catch{}let w=null;try{w=(await esm_default({baseDir:S,timeout:{block:1e4}}).revparse(`HEAD`)).trim()||null}catch{}if(w!==null){if(w!==t){let e=`main`;try{let t=(await esm_default({baseDir:S,timeout:{block:1e4}}).raw(`rev-parse`,`--abbrev-ref`,`HEAD`)).trim();t&&t!==`HEAD`&&(e=t)}catch{}ee.info({lastKnownHead:t,currentHead:w,branch:e},`[head-drift] lastKnownHead=${t??`null`}, currentHead=${w}, action=import`);try{await commitUpstreamImport(me.current,H??``,t,w,e),incrementUpstreamImport()}catch(e){ee.warn({err:e},`[head-drift] commitUpstreamImport failed — continuing`)}}else ee.info({currentHead:w},`[head-drift] lastKnownHead=${t??`null`}, currentHead=${w}, action=noop`);try{writeFileSync(e,w,`utf-8`)}catch(e){ee.warn({err:e},`[head-drift] failed to write last-known-head`)}}}catch(e){ee.warn({err:e},`[head-drift] check failed — continuing`)}try{let e=recoverPendingManagedRename(t,S);if(e.recovered&&e.journal){let t=e.journal.version===2?e.journal.fromPath:e.journal.sourceDocName,S=e.journal.version===2?e.journal.toPath:e.journal.destinationDocName;ee.warn({journalVersion:e.journal.version,fromPath:t,toPath:S,restoredDocNames:e.restoredDocNames},`[managed-rename] recovered pending rename ${t} -> ${S}`)}}catch(e){ee.error({err:e},`[server] managed rename recovery failed`),Ut.push(`managed-rename-recovery`)}try{let e=cleanupOrphanUploadTempfiles(S);(e.deleted>0||e.errors>0)&&ee.info({scanned:e.scanned,deleted:e.deleted,errors:e.errors},`[upload-tempfile-sweep] swept ${e.deleted} orphan tempfile(s)`)}catch(e){ee.error({err:e},`[server] upload-tempfile sweep failed`),Ut.push(`upload-tempfile-sweep`)}try{$e=await _e.openDirectConnection(SYSTEM_DOC_NAME),ye?.emitServerInfo(ne,getActiveBranch())}catch(e){ee.error({err:e},`[server] failed to open __system__ direct connection — CC1 push disabled`),Ut.push(`cc1-push`)}for(let e of CONFIG_DOC_NAMES)try{let t=await _e.openDirectConnection(e);nt.set(e,t)}catch(t){ee.error({err:t,docName:e},`[server] failed to open ${e} direct connection — config bind degraded`),Ut.push(`config-doc:${e}`)}let e=new Map([[CONFIG_DOC_NAME_PROJECT,resolveConfigPath(`project`,S)],[CONFIG_DOC_NAME_PROJECT_LOCAL,resolveConfigPath(`project-local`,S)],[CONFIG_DOC_NAME_USER,resolveConfigPath(`user`,S,F)]]);for(let t of CONFIG_DOC_NAMES){let S=e.get(t);if(S)try{ee.info({docName:t,path:S},`[config-file-watcher] starting`);let e=await startConfigFileWatcher(S,e=>{let S=_e.documents.get(t);ee.info({docName:t,hasDocument:S!==void 0,contentLength:e.length},`[config-file-watcher] file changed`);let w=applyExternalConfigChange(S??null,t,e,ge.configPersistenceCtx);if(ee.info({docName:t,outcome:w},`[config-file-watcher] applyExternalConfigChange outcome`),t===`__config__/project`||t===`__local__/project`){let e=te();zt?.setEnabled(e).catch(t=>{ee.warn({err:t,enabled:e},`[sync] failed to apply autoSync.enabled from config`)})}});rt.push({docName:t,cleanup:e}),ee.info({docName:t,path:S},`[config-file-watcher] started`)}catch(e){ee.warn({err:e,docName:t,path:S},`[config-file-watcher] failed to start for ${t}`),Ut.push(`config-file-watcher:${t}`)}}try{let e=resolve(t,`.okignore`),w=resolve(S,`.gitignore`),E=ee;E.info({okignorePath:e,gitignorePath:w},`[ignore-watcher] starting multi-path watcher for .okignore + .gitignore`);let D=await startMultiPathConfigFileWatcher([e,w],(t,w)=>{(async()=>{if(t===e)try{let e=applyExternalConfigChange(_e.documents.get(`__config__/okignore`)??null,CONFIG_DOC_NAME_OKIGNORE,w,ge.configPersistenceCtx);E.info({docName:CONFIG_DOC_NAME_OKIGNORE,outcome:e},`[ignore-watcher] applyExternalConfigChange outcome`)}catch(e){E.error({err:e,changedPath:relative(S,t)},`[ignore-watcher] applyExternalConfigChange failed; rebuild proceeds independently`)}let D=await ue.rebuildIgnorePatterns();if(D.ok)E.info({changedPath:relative(S,t),patternCount:D.patternCount,nestedFileCount:D.nestedFileCount,durationMs:D.durationMs},`[ignore-watcher] rebuild succeeded — broadcasting files channel`),ye?.signal(`files`);else{let e=relative(S,t)||`.`;E.warn({changedPath:e,error:D.error.message},`[ignore-watcher] rebuild failed — emitting config-ignore-nested-error`),ye?.emitConfigIgnoreNestedError(e,D.error.message)}})().catch(e=>{E.error({err:e,changedPath:relative(S,t)||`.`},`[ignore-watcher] handler threw`)})});rt.push({docName:`__ignore-files__`,cleanup:D}),E.info({okignorePath:e,gitignorePath:w},`[ignore-watcher] multi-path watcher started`)}catch(e){ee.warn({err:e,projectDir:S,contentDir:t},`[ignore-watcher] failed to start multi-path watcher`),Ut.push(`ignore-files-watcher`)}let w=resolveGitDir(S),E=w?readBranchFromHead(w)??`main`:`main`;switchReconciledBaseScope(E),de.switchBranch(E);try{{let e=getActiveBranch();try{if(await de.loadFromDisk(e)){let t=await de.reconcileWithDisk(e);(t.added>0||t.updated>0||t.deleted>0)&&ee.info(t,`[backlinks] startup reconcile: offline changes applied`)}else await de.rebuildFromDisk(e);de.saveToDisk().catch(t=>{console.warn(`[backlinks] Failed to persist startup cache for ${e}:`,t)})}catch(t){ee.error({err:t,branch:e},`[backlinks] startup init failed; index will populate incrementally via watcher`)}}Lt=await startWatcher(t,Ft,ue),fe.init();let e=0;try{seedBasenameIndex({contentDir:t,contentFilter:ue,basenameIndex:oe,onSkip:(t,S,w)=>{e++,ee.warn({reason:t,code:S,path:w},`[basename-index] skipped entry during seed (${t}${S?` ${S}`:``})`)}}),e>0&&(ee.warn({count:e},`[basename-index] startup seed completed with ${e} skipped entries — embeds under inaccessible subtrees will not resolve`),Ut.push(`basename-index-partial`))}catch(e){ee.error({err:e},`[basename-index] startup seed failed`),Ut.push(`basename-index`)}}catch(e){ee.error({err:e},`[server] disk bridge watcher failed to start`),Ut.push(`file-watcher`)}try{Rt=await startHeadWatcher(S,async({trigger:e})=>{if(ee.info({trigger:e},`[batch] begin trigger=${e}`),incrementBatch(),_e.flushPendingStores(),await ge.flushPendingGitCommit(),setBatchInProgress(!0),me.current){let e=getActiveBranch(),t=resolveGitDir(S),w=t?readBranchFromHead(t)??e:e,E=[];for(let[e,t]of _e.documents){if(isSystemDoc(e)||isConfigDoc(e))continue;let S=null;if(t.transact(()=>{S=at(e)},PARK_SNAPSHOT_ORIGIN),S===null)continue;let w=getReconciledBase(e)??S;E.push({docName:e,markdown:S,diskSnapshot:w})}if(E.length>0)try{let t=await parkBranch(me.current,e,SERVICE_WRITER.id,E,w);t&&(incrementPark(),ee.info({count:E.length,branch:e,sha:t.slice(0,8)},`[history] parked ${E.length} docs on ${e} → ${t.slice(0,8)}`))}catch(e){ee.error({err:e},`[shadow] park failed`)}}},async e=>{let S=Mt.length,w=e.newBranch??`main`;if(ee.info({kind:e.batchKind,headMoved:e.headMoved,docs:S,timeout:!!e.timeout},`[batch] end kind=${e.batchKind} headMoved=${e.headMoved} docs=${S}${e.timeout?` timeout`:``}`),e.batchKind===`within-branch`)setBatchInProgress(!1),await It(),await ge.flushDeferredStores(`within-branch`);else{incrementBranchSwitch(),Mt.splice(0,Mt.length),switchReconciledBaseScope(w),Ve!==null&&(clearTimeout(Ve),Ve=null),de.switchBranch(w),ue.rebuildDirCount();try{let e=0;oe.clear(),seedBasenameIndex({contentDir:t,contentFilter:ue,basenameIndex:oe,onSkip:(t,S,E)=>{e++,ee.warn({reason:t,code:S,path:E,branch:w},`[basename-index] skipped entry during branch-switch reseed (${t}${S?` ${S}`:``})`)}}),e>0&&(ee.warn({count:e,branch:w},`[basename-index] branch-switch reseed completed with ${e} skipped entries — embeds under inaccessible subtrees will not resolve on this branch`),Ut.includes(`basename-index-partial`)||Ut.push(`basename-index-partial`))}catch(e){ee.error({err:e,branch:w},`[basename-index] branch-switch reseed failed`)}for(let[e,S]of _e.documents)if(!(isSystemDoc(e)||isConfigDoc(e)))try{let E=safeContentPath(e,t);if(!existsSync(E)){let t=getReconciledBase(e)??``,E=at(e)??``;if(E!==t&&me.current){let t=me.current;queueMicrotask(()=>{saveInMemoryCheckpoint(t,H??``,{kind:`external-change-rescue`,docName:e,contents:E,label:`External change recovered @ ${new Date().toISOString()}`,branch:w,metadata:{incomingDiskSha:``}}).then(()=>{incrementRescueBuffer(),ee.info({docName:e},`[reconcile] rescue checkpoint saved on branch switch: ${e}`)}).catch(t=>{ee.error({docName:e,err:t},`[reconcile] rescue checkpoint write failed: ${e}`)})})}S.getMap(`lifecycle`).set(`status`,`deleted-upstream`),ee.info({docName:e,branch:w},`[branch-switch] tombstone: ${e} (not on ${w})`);continue}let D=readFileSync(E,`utf-8`);st(e,D),setReconciledBase(e,D),ee.info({docName:e},`[branch-switch] reset: ${e}`)}catch(t){ee.error({err:t,docName:e},`[branch-switch] failed to reset ${e}`)}ee.info({branch:w,docCount:_e.documents.size},`[branch-switch] loaded branch ${w} (${_e.documents.size} docs)`);try{if(await de.loadFromDisk(w)){let e=await de.reconcileWithDisk(w);(e.added>0||e.updated>0||e.deleted>0)&&ee.info(e,`[backlinks] branch-switch reconcile for ${w}`)}else await de.rebuildFromDisk(w);de.saveToDisk(w).catch(e=>{console.warn(`[backlinks] Failed to persist branch cache for ${w}:`,e)})}catch(e){ee.error({err:e,branch:w},`[backlinks] branch-switch rebuild failed; backlinks may be stale`)}if(fe.init(),me.current&&e.batchKind===`cross-branch`){let e=0;for(let[t]of _e.documents)if(!(isSystemDoc(t)||isConfigDoc(t)))try{let S=await readParkedState(me.current,w,SERVICE_WRITER.id,t);if(!S||S.markdown===S.diskSnapshot)continue;let E=getReconciledBase(t);if(!E)continue;let D=reconcile({docName:t,base:S.diskSnapshot,ours:S.markdown,theirs:E});switch(D.kind){case`merged`:case`clean`:st(t,D.newContent),setReconciledBase(t,D.newContent),e++;break;case`conflicts`:st(t,D.newContent),setReconciledBase(t,D.newContent),incrementConflict(),e++;break;case`noop`:case`refused`:break}}catch(e){ee.error({err:e,docName:t},`[branch-switch] restore WIP failed for ${t}`)}e>0&&ee.info({count:e,branch:w},`[branch-switch] restored ${e} parked docs on ${w}`)}if(e.oldBranch?.startsWith(`detached-`)&&me.current)try{let t=shadowGit(me.current),S=(await t.raw(`for-each-ref`,`refs/wip/${e.oldBranch}/`,`--format=%(refname)`)).trim();if(S){for(let e of S.split(`
|
|
3073
|
-
`))e&&await t.raw(`update-ref`,`-d`,e);ee.info({context:e.oldBranch},`[branch-switch] cleaned up detached context ${e.oldBranch}`)}}catch(e){ee.error({err:e},`[branch-switch] detached cleanup failed`)}setBatchInProgress(!1),await ge.flushDeferredStores(`discard-stale`),ye?.emitBranchSwitched(w)}if(e.headMoved&&e.newHead&&me.current&&S>0){let t=H??`.`;try{let S=await commitUpstreamImport(me.current,t,e.oldHead,e.newHead,w);incrementUpstreamImport(),ee.info({oldHead:e.oldHead?.slice(0,8)??`null`,newHead:e.newHead.slice(0,8),sha:S.slice(0,8)},`[history] upstream-import from ${e.oldHead?.slice(0,8)??`null`}..${e.newHead.slice(0,8)} → ${S.slice(0,8)}`)}catch(e){ee.error({err:e},`[shadow] upstream-import failed`)}}})}catch(e){ee.error({err:e},`[server] HEAD watcher failed to start`),Ut.push(`head-watcher`)}let D=J?.[0]??`open-knowledge`,O=[`-c`,`credential.helper=!${J&&J.length>1?J.join(` `):D} auth git-credential`];try{zt=new SyncEngine({projectDir:S,contentDir:t,contentFilter:ue,contentRoot:H,syncEnabled:te(),credentialArgs:O,cc1Broadcaster:ye,setBatchInProgress:e=>{setBatchInProgress(e),e||ge.flushDeferredStores(`within-branch`).catch(e=>{ee.error({err:e},`[persistence] deferred store drain failed after sync batch`)})},onStateChange:e=>{ee.info({state:e},`[sync] state → ${e}`)},onAutoDisable:async e=>{ee.warn({reason:e},`[sync] auto-disabled — persisting to project-local config`);let t=await writeConfigPatch({cwd:S,scope:`project-local`,patch:{autoSync:{enabled:!1}}});t.ok||ee.error({result:t,reason:e,humanError:humanFormat(t.error),configPath:resolveConfigPath(`project-local`,S)},`[sync] failed to persist auto-disable — next restart WILL re-enable sync and re-trigger the same failure. Check permissions on the config path.`)}}),await zt.start()}catch(e){ee.warn({err:e},`[server] SyncEngine failed to start — sync disabled`),zt=null}ze(`files`),ze(`backlinks`),ze(`graph`),ze(`tags`)}return Wt().then(Pe,Ie),{hocuspocus:_e,sessionManager:ve,cc1Broadcaster:ye,agentFocusBroadcaster:Ce,agentPresenceBroadcaster:we,contentFilter:ue,basenameIndex:oe,serverInstanceId:ne,destroy:Ht,ready:Re,degraded:Ut,lockDir:ae,get syncEngine(){return zt}}}const LEGACY_RUNTIME_FILENAMES=[`server.lock`,`ui.lock`,`state.json`,`principal.json`,`sync-state.json`,`conflicts.json`,`last-spawn-error.log`],LEGACY_RUNTIME_DIRNAMES=[`cache`,`tmp`];function findLegacyRuntimeFiles(e){let t=resolve(e,LOCAL_DIR);if(!(()=>{if(!existsSync(t))return!0;try{return readdirSync(t).length===0}catch{return!0}})())return[];let S=[];for(let t of LEGACY_RUNTIME_FILENAMES)existsSync(resolve(e,t))&&S.push(t);for(let t of LEGACY_RUNTIME_DIRNAMES){let w=resolve(e,t);try{existsSync(w)&&statSync(w).isDirectory()&&S.push(`${t}/`)}catch{}}return S}function computeWorktreeAttributes(e){let t=resolveGitDirDetailed(e);switch(t.kind){case`directory`:return{kind:`main`,gitdir:t.path};case`linked`:return{kind:`linked`,gitdir:t.path};case`malformed-pointer`:return{kind:`linked`,gitdir:null};case`inaccessible`:case`absent`:return{kind:`main`,gitdir:null}}}const DEFAULT_IDLE_THRESHOLD_MS=1800*1e3,DESTROY_STEP_TIMEOUT_MS=5e3;async function bootServer(e){initTelemetry();let{kind:t,gitdir:S}=computeWorktreeAttributes(e.projectDir??e.contentDir),w={"ok.worktree.kind":t};return S!==null&&(w[`ok.worktree.gitdir`]=normalizeFsPath(S)),withSpan(`ok.boot`,{attributes:w},async()=>bootServerInner(e))}async function bootServerInner(e){let t=e.skipAutoInit??!1,S=e.attachUiSibling??!0,w=e.idleShutdownMs,E=e.log??getLogger(`boot`),D=process.env.OK_LOCK_KIND===`mcp-spawned`||process.env.OK_LOCK_KIND===`interactive`?process.env.OK_LOCK_KIND:void 0,O=e.lockKind??D??`interactive`,{createServer:k}=await import(`node:http`),{updateServerLockPort:j}=await import(`./server-lock-D7DXNVql-B5nINglj.mjs`).then(e=>e.a),F=!1;if(!t&&e.autoInitFn)try{F=!!await e.autoInitFn()}catch(e){E.warn({err:e},`autoInitFn failed`)}let L=e.projectDir??e.contentDir,B=resolve(L,`.ok`);if(!existsSync(resolve(B,`config.yml`)))throw new MissingOkConfigError(existsSync(B)?`config`:`okdir`,L);existsSync(resolve(B,`.gitignore`))||console.warn("[boot] Note: .ok/.gitignore is missing — per-machine state files in .ok/ may show up as untracked changes. Run `ok init` to add the recommended ignore entries.");let H=findLegacyRuntimeFiles(B);H.length>0&&console.warn(`[boot] Found legacy runtime files at .ok/${H.join(`, `)}. Delete .ok/ and re-init — these files moved to .ok/${LOCAL_DIR}/.`);let q=createServer$1({contentDir:e.contentDir,projectDir:e.projectDir,contentRoot:e.contentRoot,port:e.port,host:e.host,quiet:e.quiet??!1,debounce:e.debounce,maxDebounce:e.maxDebounce,gitEnabled:e.gitEnabled,commitDebounceMs:e.commitDebounceMs,wipRef:e.wipRef,enableTestRoutes:e.enableTestRoutes,shadowRepo:e.shadowRepo,destroyTimeoutMs:e.destroyTimeoutMs,localOpCliArgs:e.localOpCliArgs,onAgentWrite:e.onAgentWrite,lockKind:O,skipStateManifestCheck:e.skipStateManifestCheck}),{hocuspocus:J,destroy:Y,ready:ee,degraded:te,lockDir:ne,sessionManager:ae,agentFocusBroadcaster:oe,agentPresenceBroadcaster:se}=q,ce=(()=>{let t=e.host??`localhost`;return t===`0.0.0.0`||t===`::`?`localhost`:t.includes(`:`)&&!t.startsWith(`[`)?`[${t}]`:t})(),ue=e.port??0,de=createMcpHttpHandler({contentDir:e.contentDir,projectDir:e.projectDir??e.contentDir,config:e.config,getServerUrl:()=>`http://${ce}:${ue}`,log:E}),fe=k();fe.headersTimeout=3e4,fe.requestTimeout=6e4;let me=e.serveContentAssets?createAssetServeMiddleware({contentFilter:q.contentFilter,contentSirv:build_default(e.contentDir,{dev:!0,dotfiles:!1}),inlineExtensions:INLINE_RENDERABLE_EXTENSIONS,assetExtensions:ASSET_EXTENSIONS,blocklistExtensions:EXECUTABLE_BLOCKLIST_EXTENSIONS}):void 0,ge=mountMcpAndApi({httpServer:fe,hocuspocus:J,mcpHttpHandler:de,log:E,sessionManager:ae,agentFocusBroadcaster:oe,agentPresenceBroadcaster:se,keepaliveGraceMs:e.keepaliveGraceMs,contentAssetMiddleware:me}),_e=async()=>{throw Error(`bootServer: destroy() invoked before initialization — boot did not complete`)},ve=null;w!==null&&(ve=attachIdleShutdown({httpServer:fe,thresholdMs:w??DEFAULT_IDLE_THRESHOLD_MS,log:E,onShutdown:(e.idleShutdownHandler??(e=>async()=>{await e()}))(async()=>{await _e()})})),await new Promise((t,S)=>{let w=e=>S(e);fe.once(`error`,w),fe.listen(e.port,e.host,()=>{fe.removeListener(`error`,w),t()})});let ye=fe.address(),Ce=typeof ye==`object`&&ye?ye.port:e.port??0;if(ue=Ce,j(ne,Ce),S&&e.spawnUiSiblingFn)try{await e.spawnUiSiblingFn({lockDir:ne,log:E})}catch(e){E.warn({err:e},`spawnUiSiblingFn failed`)}let we=!1,Te=async(e,t)=>{let S;try{await Promise.race([t(),new Promise((t,w)=>{S=setTimeout(()=>{w(Error(`${e} timed out after ${DESTROY_STEP_TIMEOUT_MS}ms`))},DESTROY_STEP_TIMEOUT_MS),S.unref?.()})])}finally{S!==void 0&&clearTimeout(S)}};return _e=async()=>{if(we)return;we=!0;let e=[],t=async(t,S)=>{try{await Te(t,S)}catch(S){e.push(S),E.warn({err:S,step:t},`bootServer destroy step failed`)}};try{ve?.detach()}catch(t){e.push(t),E.warn({err:t,step:`idleHandle.detach`},`bootServer destroy step failed`)}if(await t(`mount.shutdown`,()=>ge.shutdown()),await t(`mcpHttpHandler.close`,()=>de.close()),await t(`mount.wss.close`,()=>new Promise((e,t)=>{ge.wss.close(S=>S?t(S):e())})),await t(`httpServer.closeAllConnections`,async()=>{fe.closeAllConnections?.()}),await t(`httpServer.close`,()=>new Promise((e,t)=>{fe.close(S=>S&&S.code!==`ERR_SERVER_NOT_RUNNING`?t(S):e())})),await t(`destroyHocuspocus`,()=>Y()),await t(`shutdownTelemetry`,()=>shutdownTelemetry()),e.length>0)throw AggregateError(e,`bootServer destroy completed with errors`)},{httpServer:fe,destroy:_e,lockDir:ne,contentDir:e.contentDir,port:Ce,ready:ee,degraded:te,didAutoInit:F,serverInstance:q}}const ConfigSchema=ConfigSchema$1;function detectClaudeDesktopPresence(e={}){let t=e.home??homedir(),S=e.platformName??process.platform,w=e.env??process.env;return S===`darwin`?existsSync(join(t,`Library`,`Application Support`,`Claude`)):S===`win32`?existsSync(join(w.APPDATA??join(t,`AppData`,`Roaming`),`Claude`)):!1}const ANCESTOR_WALK_DEPTH_LIMIT=30,GIT_MARKER=`.git`;function findEnclosingGitRoot(e){let t=resolve(e),S=0;for(;S<ANCESTOR_WALK_DEPTH_LIMIT;){let e=!1;try{e=existsSync(resolve(t,GIT_MARKER))}catch{e=!1}if(e)return{gitRoot:t,distance:S};let w=dirname(t);if(w===t)return null;t=w,S+=1}return null}const execFileAsync=promisify(execFile);var ProjectGitInitError=class extends Error{stderr;constructor(e,t=``,S){super(e,S),this.name=`ProjectGitInitError`,this.stderr=t}};async function isInsideExistingWorkTree(e){try{let{stdout:t}=await execFileAsync(`git`,[`rev-parse`,`--is-inside-work-tree`],{cwd:e});return t.trim()===`true`}catch{return!1}}async function ensureProjectGit(e){let t=resolve(e),S=resolve(t,`.git`),w=resolve(S,`HEAD`),E=!1;if(existsSync(S)){if(!statSync(S).isDirectory()||existsSync(w))return{didInit:!1};console.log(`[project-git] detected partial .git/ — running git init to repair`),E=!0}else if(await isInsideExistingWorkTree(t))return{didInit:!1};let D=``;try{D=(await execFileAsync(`git`,[`init`,`--initial-branch=main`,t])).stderr??``}catch(e){let S=typeof e==`object`&&e&&`stderr`in e?String(e.stderr??``):``;throw new ProjectGitInitError(`git init failed at ${t}: ${e instanceof Error?e.message:String(e)}`,S,{cause:e})}if(!existsSync(w))throw new ProjectGitInitError(`git init reported success but ${S}/HEAD is missing (partial init detected)`,D);return E?(console.log(`[project-git] backfilled missing .git/HEAD at ${t}`),{didInit:!0,repaired:!0}):(console.log(`[project-git] initialized .git/ at ${t} (branch: main)`),{didInit:!0})}async function resolvePackageVersion(e,t){let S;try{S=createRequire(t).resolve(e)}catch(e){if(e?.code===`MODULE_NOT_FOUND`)return;throw e}for(let t=dirname(S),w=0;w<32;w+=1){let S=join(t,`package.json`);if(existsSync(S))try{let t=JSON.parse(await readFile$1(S,`utf-8`));if(t.name===e&&typeof t.version==`string`)return t.version}catch{}let w=dirname(t);if(w===t)return;t=w}}export{assertNeverDiskEvent as $,rewriteWikiLinksForDocumentRename as $n,ALL_EDITOR_IDS as $r,incrementServerObserverFire as $t,MissingOkConfigError as A,_coercedNumber as Ai,readServerPackageVersion as An,tracedWriteFile as Ar,createStreamingErrorWriter as At,STARTER_PACK_IDS as B,registerWrite as Bn,writeTargetVersion as Br,formatAuthRejectionWire as Bt,LOG_MD_TEMPLATE as C,boolean$1 as Ci,parseAuthRejectionWire as Cn,tracedMkdir as Cr,createExternalChangeHandler as Ct,MCP_SERVER_NAME as D,object$1 as Di,planSeed as Dn,tracedRmSync as Dr,createPersistenceExtension as Dt,MCP_CONNECTION_ID_HEADER as E,number$1 as Ei,pathToDocName as En,tracedRenameSync as Er,createOsProbe as Et,SERVICE_WRITER as F,readUiLock as Fn,validateCloneInputs as Fr,errorResponse as Ft,StateManifestError as G,resolveContentDir as Gn,isInitializedNotification as Gr,getLocalDir as Gt,STATE_MANIFEST_FILENAME as H,removeLastKnownHash as Hn,McpServer as Hr,formatContributorsFrom as Ht,SKILL_INSTALL_EVENTS_FILE_REL as I,reconcile as In,validateSkillZip as Ir,evictStaleTrackerEntries as It,acquireUiLock as J,resolveLockDir as Jn,readConfigSafely as Jr,getMetrics as Jt,TagIndex as K,resolveCursorBinaryDefault as Kn,isJSONRPCRequest as Kr,getLogger as Kt,STARTER_FOLDERS as L,recordContributor as Ln,withSpan as Lr,extractWikiLinksFromMarkdown as Lt,PinoLogger as M,require_dist$2 as Mi,readStateManifest as Mn,updateLastKnownHash as Mr,detectClaudeDesktopPresence as Mt,ProjectGitInitError as N,readTargetRecordedAt as Nn,updateUiLockPort as Nr,detectProjectShape as Nt,MISSING_OK_CONFIG_MESSAGE as O,string$2 as Oi,readAllTargets as On,tracedRmdirSync as Or,createServer$1 as Ot,ROLLBACK_ORIGIN as P,readTargetVersion as Pn,validateAgentId as Pr,ensureProjectGit as Pt,assertCompatibleStateManifest as Q,rewriteMarkdownLinksForDocumentRename as Qn,MalformedGitPointerError as Qr,incrementCollabSocketFilteredError as Qt,STARTER_FOLDER_FRONTMATTER_FILENAME as R,recordSkillInstallEvent as Rn,withSpanSync as Rr,findEnclosingGitRoot as Rt,LIVE_DERIVED_INDEX_DEBOUNCE_MS as S,array as Si,normalizeFsPath as Sn,tracedLinkSync as Sr,createContentFilterAsync as St,MAX_AGENT_SESSIONS as T,looseObject as Ti,parseKeepaliveConnectionId as Tn,tracedRename as Tr,createMcpHttpHandler as Tt,SeedPrerequisiteError as U,resetMetrics as Un,JSONRPCMessageSchema as Ur,gcCheckpointRefs as Ut,STARTER_TEMPLATES as V,releaseUiLock as Vn,writeTracker as Vr,formatContributors as Vt,SeedRootDirError as W,resolveBundledSkillDir as Wn,LATEST_PROTOCOL_VERSION as Wr,getCurrentMcpLogger as Wt,applyExternalChange as X,resolvePackageVersion as Xn,writeConfigPatch as Xr,handleCollabSocketError as Xt,applyAgentMarkdownWrite as Y,resolvePack as Yn,resolveConfigPath as Yr,getTracer as Yt,applySeed as Z,restoreContributors as Zn,GitDirAccessError as Zr,handleSpawnCursor as Zt,GIT_UPSTREAM_WRITER as _,LOCAL_DIR as _i,listRescueCheckpoints as _n,startWatcher as _r,contentHash as _t,AgentPresenceBroadcaster as a,EXECUTABLE_BLOCKLIST_EXTENSIONS as ai,isAllowedApiOrigin as an,safeContentPath as ar,buildReadResult as at,HocuspocusAuthTokenSchema as b,ZodNumber$1 as bi,loggerFactory as bn,toBroadcasterKey as br,createAssetServeMiddleware as bt,BacklinkIndex as c,ProblemDetailsSchema as ci,isHocuspocusAuthRejectionReason as cn,sanitizeClientName as cr,buildWipTree as ct,CURSOR_BUNDLE_PATHS_BY_PLATFORM as d,colorFromSeed as di,isPairedWriteOrigin as dn,seedBasenameIndex as dr,clearContributors as dt,ASSET_EXTENSIONS as ei,initShadowRepo as en,runAuthReposSubprocess as er,attachIdleShutdown as et,ConfigSchema as f,defaultScheduler as fi,isPathWithinDir as fn,setActiveSpanAttributes as fr,coercePackId as ft,FILE_WATCHER_ORIGIN as g,CONFIG_SCHEMA_MAJOR_PATH as gi,lastKnownHash as gn,splitMarkdownBlocks as gr,containsConflictMarkers as gt,FILE_SYSTEM_WRITER as h,isOrphanMode as hi,isSystemDoc as hn,spawnDetached as hr,commitWipFromTree as ht,AgentFocusBroadcaster as i,EDITOR_LABELS as ii,installUserSkill as in,runWithMcpLogger as ir,buildInstructions as it,OBSERVER_SYNC_ORIGIN as j,NEVER as ji,readSkillInstallStateSnapshot as jn,tracedWriteFileSync as jr,createTestLogger as jt,McpLogger as k,url as ki,readBranchFromHead as kn,tracedUnlinkSync as kr,createServerObserverExtension as kt,CC1Broadcaster as l,SKILL_STATE_TARGETS as li,isKnownPackId as ln,saveInMemoryCheckpoint as lr,classifyEvents as lt,DEFAULT_PACK_ID as m,iconFromClientName as mi,isSelfWrite as mn,shutdownTelemetry as mr,commitWip as mt,AGENT_ID_RE as n,DEFAULT_GITHUB_OAUTH_CLIENT_ID as ni,installPrettyZodErrors as nn,runCloneSubprocess as nr,buildAndOpenSkill as nt,AgentSessionCapacityError as o,INLINE_RENDERABLE_EXTENSIONS as oi,isAllowedWorkspaceHostHeader as on,safeSubdir as or,buildSkillZip as ot,DEFAULT_CHECKPOINT_RETENTION as p,humanFormat as pi,isProjectRoot as pn,shadowGit as pr,commitUpstreamImport as pt,UiLockCollisionError as q,resolveCursorSpawnInvocation as qn,isJSONRPCResultResponse as qr,getMeter as qt,AGENT_WRITE_ORIGIN as r,DEFAULT_SERVER_HOST as ri,installTestLoggers as rn,runDeviceFlowSubprocess as rr,buildExecResult as rt,AgentSessionManager as s,ORPHAN_MODES as si,isConfigDoc as sn,safetyCheckpoint as sr,buildStarterFolderFrontmatterYaml as st,AGENT_ID_MAX_LEN as t,CC1_CONTRACT_VERSION as ti,initTelemetry as tn,runAuthStatusSubprocess as tr,bootServer as tt,CONFLICT_MARKER_RE as u,SYSTEM_DOC_NAME as ui,isLoopbackAddress as un,saveVersion as ur,classifyFsPath as ut,HOCUSPOCUS_AUTH_REJECTION_REASONS as v,OK_PROJECT_MARKER as vi,listStarterPacks as vn,streamingProblemEvent as vr,contributorCount as vt,MANAGED_RENAME_ORIGIN as w,literal as wi,parseHocuspocusAuthToken as wn,tracedMkdirSync as wr,createLiveDerivedIndexExtension as wt,INSTALLED_AGENTS_SCHEMES as x,any$1 as xi,mountMcpAndApi as xn,tracedAppendFileSync as xr,createContentFilter as xt,HocuspocusAuthRejection as y,locateIssue as yi,loadPrincipal as yn,swapContributors as yr,createApiExtension as yt,STARTER_PACKS as z,registerAllTools as zn,writeStateManifest as zr,findEnclosingProjectRoot as zt};
|
|
3074
|
-
//# sourceMappingURL=dist-
|
|
3073
|
+
`))e&&await t.raw(`update-ref`,`-d`,e);ee.info({context:e.oldBranch},`[branch-switch] cleaned up detached context ${e.oldBranch}`)}}catch(e){ee.error({err:e},`[branch-switch] detached cleanup failed`)}setBatchInProgress(!1),await ge.flushDeferredStores(`discard-stale`),ye?.emitBranchSwitched(w)}if(e.headMoved&&e.newHead&&me.current&&S>0){let t=H??`.`;try{let S=await commitUpstreamImport(me.current,t,e.oldHead,e.newHead,w);incrementUpstreamImport(),ee.info({oldHead:e.oldHead?.slice(0,8)??`null`,newHead:e.newHead.slice(0,8),sha:S.slice(0,8)},`[history] upstream-import from ${e.oldHead?.slice(0,8)??`null`}..${e.newHead.slice(0,8)} → ${S.slice(0,8)}`)}catch(e){ee.error({err:e},`[shadow] upstream-import failed`)}}})}catch(e){ee.error({err:e},`[server] HEAD watcher failed to start`),Ut.push(`head-watcher`)}let D=J?.[0]??`open-knowledge`,O=[`-c`,`credential.helper=!${J&&J.length>1?J.join(` `):D} auth git-credential`];try{zt=new SyncEngine({projectDir:S,contentDir:t,contentFilter:ue,contentRoot:H,syncEnabled:te(),credentialArgs:O,cc1Broadcaster:ye,setBatchInProgress:e=>{setBatchInProgress(e),e||ge.flushDeferredStores(`within-branch`).catch(e=>{ee.error({err:e},`[persistence] deferred store drain failed after sync batch`)})},onStateChange:e=>{ee.info({state:e},`[sync] state → ${e}`)},onAutoDisable:async e=>{ee.warn({reason:e},`[sync] auto-disabled — persisting to project-local config`);let t=await writeConfigPatch({cwd:S,scope:`project-local`,patch:{autoSync:{enabled:!1}}});t.ok||ee.error({result:t,reason:e,humanError:humanFormat(t.error),configPath:resolveConfigPath(`project-local`,S)},`[sync] failed to persist auto-disable — next restart WILL re-enable sync and re-trigger the same failure. Check permissions on the config path.`)}}),await zt.start()}catch(e){ee.warn({err:e},`[server] SyncEngine failed to start — sync disabled`),zt=null}ze(`files`),ze(`backlinks`),ze(`graph`),ze(`tags`)}return Wt().then(Pe,Ie),{hocuspocus:_e,sessionManager:ve,cc1Broadcaster:ye,agentFocusBroadcaster:Ce,agentPresenceBroadcaster:we,contentFilter:ue,basenameIndex:oe,serverInstanceId:ne,destroy:Ht,ready:Re,degraded:Ut,lockDir:ae,get syncEngine(){return zt}}}const LEGACY_RUNTIME_FILENAMES=[`server.lock`,`ui.lock`,`state.json`,`principal.json`,`sync-state.json`,`conflicts.json`,`last-spawn-error.log`],LEGACY_RUNTIME_DIRNAMES=[`cache`,`tmp`];function findLegacyRuntimeFiles(e){let t=resolve(e,LOCAL_DIR);if(!(()=>{if(!existsSync(t))return!0;try{return readdirSync(t).length===0}catch{return!0}})())return[];let S=[];for(let t of LEGACY_RUNTIME_FILENAMES)existsSync(resolve(e,t))&&S.push(t);for(let t of LEGACY_RUNTIME_DIRNAMES){let w=resolve(e,t);try{existsSync(w)&&statSync(w).isDirectory()&&S.push(`${t}/`)}catch{}}return S}function computeWorktreeAttributes(e){let t=resolveGitDirDetailed(e);switch(t.kind){case`directory`:return{kind:`main`,gitdir:t.path};case`linked`:return{kind:`linked`,gitdir:t.path};case`malformed-pointer`:return{kind:`linked`,gitdir:null};case`inaccessible`:case`absent`:return{kind:`main`,gitdir:null}}}const DEFAULT_IDLE_THRESHOLD_MS=1800*1e3,DESTROY_STEP_TIMEOUT_MS=5e3;async function bootServer(e){initTelemetry();let{kind:t,gitdir:S}=computeWorktreeAttributes(e.projectDir??e.contentDir),w={"ok.worktree.kind":t};return S!==null&&(w[`ok.worktree.gitdir`]=normalizeFsPath(S)),withSpan(`ok.boot`,{attributes:w},async()=>bootServerInner(e))}async function bootServerInner(e){let t=e.skipAutoInit??!1,S=e.attachUiSibling??!0,w=e.idleShutdownMs,E=e.log??getLogger(`boot`),D=process.env.OK_LOCK_KIND===`mcp-spawned`||process.env.OK_LOCK_KIND===`interactive`?process.env.OK_LOCK_KIND:void 0,O=e.lockKind??D??`interactive`,{createServer:k}=await import(`node:http`),{updateServerLockPort:j}=await import(`./server-lock-D7DXNVql-B5nINglj.mjs`).then(e=>e.a),F=!1;if(!t&&e.autoInitFn)try{F=!!await e.autoInitFn()}catch(e){E.warn({err:e},`autoInitFn failed`)}let L=e.projectDir??e.contentDir,B=resolve(L,`.ok`);if(!existsSync(resolve(B,`config.yml`)))throw new MissingOkConfigError(existsSync(B)?`config`:`okdir`,L);existsSync(resolve(B,`.gitignore`))||console.warn("[boot] Note: .ok/.gitignore is missing — per-machine state files in .ok/ may show up as untracked changes. Run `ok init` to add the recommended ignore entries.");let H=findLegacyRuntimeFiles(B);H.length>0&&console.warn(`[boot] Found legacy runtime files at .ok/${H.join(`, `)}. Delete .ok/ and re-init — these files moved to .ok/${LOCAL_DIR}/.`);let q=createServer$1({contentDir:e.contentDir,projectDir:e.projectDir,contentRoot:e.contentRoot,port:e.port,host:e.host,quiet:e.quiet??!1,debounce:e.debounce,maxDebounce:e.maxDebounce,gitEnabled:e.gitEnabled,commitDebounceMs:e.commitDebounceMs,wipRef:e.wipRef,enableTestRoutes:e.enableTestRoutes,shadowRepo:e.shadowRepo,destroyTimeoutMs:e.destroyTimeoutMs,localOpCliArgs:e.localOpCliArgs,onAgentWrite:e.onAgentWrite,lockKind:O,skipStateManifestCheck:e.skipStateManifestCheck}),{hocuspocus:J,destroy:Y,ready:ee,degraded:te,lockDir:ne,sessionManager:ae,agentFocusBroadcaster:oe,agentPresenceBroadcaster:se}=q,ce=(()=>{let t=e.host??`localhost`;return t===`0.0.0.0`||t===`::`?`localhost`:t.includes(`:`)&&!t.startsWith(`[`)?`[${t}]`:t})(),ue=e.port??0,de=createMcpHttpHandler({contentDir:e.contentDir,projectDir:e.projectDir??e.contentDir,config:e.config,getServerUrl:()=>`http://${ce}:${ue}`,log:E}),fe=k();fe.headersTimeout=3e4,fe.requestTimeout=6e4;let me=e.serveContentAssets?createAssetServeMiddleware({contentFilter:q.contentFilter,contentSirv:build_default(e.contentDir,{dev:!0,dotfiles:!1}),inlineExtensions:INLINE_RENDERABLE_EXTENSIONS,assetExtensions:ASSET_EXTENSIONS,blocklistExtensions:EXECUTABLE_BLOCKLIST_EXTENSIONS}):void 0;if(e.reactShellDistDir)try{acquireUiLock(ne,{port:0,worktreeRoot:e.projectDir??e.contentDir})}catch(e){throw await Y().catch(()=>{}),e}let ge=e.reactShellDistDir?build_default(e.reactShellDistDir,{single:!0,gzip:!0,immutable:!0}):void 0,_e=mountMcpAndApi({httpServer:fe,hocuspocus:J,mcpHttpHandler:de,log:E,sessionManager:ae,agentFocusBroadcaster:oe,agentPresenceBroadcaster:se,keepaliveGraceMs:e.keepaliveGraceMs,contentAssetMiddleware:me,reactShellMiddleware:ge}),ve=async()=>{throw Error(`bootServer: destroy() invoked before initialization — boot did not complete`)},ye=null;w!==null&&(ye=attachIdleShutdown({httpServer:fe,thresholdMs:w??DEFAULT_IDLE_THRESHOLD_MS,log:E,onShutdown:(e.idleShutdownHandler??(e=>async()=>{await e()}))(async()=>{await ve()})}));try{await new Promise((t,S)=>{let w=e=>S(e);fe.once(`error`,w),fe.listen(e.port,e.host,()=>{fe.removeListener(`error`,w),t()})})}catch(t){if(e.reactShellDistDir)try{releaseUiLock(ne)}catch(e){E.warn({err:e},`releaseUiLock failed during listen-error cleanup`)}throw await Y().catch(()=>{}),t}let Ce=fe.address(),we=typeof Ce==`object`&&Ce?Ce.port:e.port??0;if(ue=we,j(ne,we),e.reactShellDistDir&&updateUiLockPort(ne,we),S&&e.spawnUiSiblingFn)try{await e.spawnUiSiblingFn({lockDir:ne,log:E})}catch(e){E.warn({err:e},`spawnUiSiblingFn failed`)}let Te=!1,De=async(e,t)=>{let S;try{await Promise.race([t(),new Promise((t,w)=>{S=setTimeout(()=>{w(Error(`${e} timed out after ${DESTROY_STEP_TIMEOUT_MS}ms`))},DESTROY_STEP_TIMEOUT_MS),S.unref?.()})])}finally{S!==void 0&&clearTimeout(S)}};return ve=async()=>{if(Te)return;Te=!0;let t=[],S=async(e,S)=>{try{await De(e,S)}catch(S){t.push(S),E.warn({err:S,step:e},`bootServer destroy step failed`)}};try{ye?.detach()}catch(e){t.push(e),E.warn({err:e,step:`idleHandle.detach`},`bootServer destroy step failed`)}if(await S(`mount.shutdown`,()=>_e.shutdown()),await S(`mcpHttpHandler.close`,()=>de.close()),await S(`mount.wss.close`,()=>new Promise((e,t)=>{_e.wss.close(S=>S?t(S):e())})),await S(`httpServer.closeAllConnections`,async()=>{fe.closeAllConnections?.()}),await S(`httpServer.close`,()=>new Promise((e,t)=>{fe.close(S=>S&&S.code!==`ERR_SERVER_NOT_RUNNING`?t(S):e())})),await S(`destroyHocuspocus`,()=>Y()),e.reactShellDistDir&&await S(`releaseUiLock`,async()=>releaseUiLock(ne)),await S(`shutdownTelemetry`,()=>shutdownTelemetry()),t.length>0)throw AggregateError(t,`bootServer destroy completed with errors`)},{httpServer:fe,destroy:ve,lockDir:ne,contentDir:e.contentDir,port:we,ready:ee,degraded:te,didAutoInit:F,serverInstance:q}}const ConfigSchema=ConfigSchema$1;function detectClaudeDesktopPresence(e={}){let t=e.home??homedir(),S=e.platformName??process.platform,w=e.env??process.env;return S===`darwin`?existsSync(join(t,`Library`,`Application Support`,`Claude`)):S===`win32`?existsSync(join(w.APPDATA??join(t,`AppData`,`Roaming`),`Claude`)):!1}const ANCESTOR_WALK_DEPTH_LIMIT=30,GIT_MARKER=`.git`;function findEnclosingGitRoot(e){let t=resolve(e),S=0;for(;S<ANCESTOR_WALK_DEPTH_LIMIT;){let e=!1;try{e=existsSync(resolve(t,GIT_MARKER))}catch{e=!1}if(e)return{gitRoot:t,distance:S};let w=dirname(t);if(w===t)return null;t=w,S+=1}return null}const execFileAsync=promisify(execFile);var ProjectGitInitError=class extends Error{stderr;constructor(e,t=``,S){super(e,S),this.name=`ProjectGitInitError`,this.stderr=t}};async function isInsideExistingWorkTree(e){try{let{stdout:t}=await execFileAsync(`git`,[`rev-parse`,`--is-inside-work-tree`],{cwd:e});return t.trim()===`true`}catch{return!1}}async function ensureProjectGit(e){let t=resolve(e),S=resolve(t,`.git`),w=resolve(S,`HEAD`),E=!1;if(existsSync(S)){if(!statSync(S).isDirectory()||existsSync(w))return{didInit:!1};console.log(`[project-git] detected partial .git/ — running git init to repair`),E=!0}else if(await isInsideExistingWorkTree(t))return{didInit:!1};let D=``;try{D=(await execFileAsync(`git`,[`init`,`--initial-branch=main`,t])).stderr??``}catch(e){let S=typeof e==`object`&&e&&`stderr`in e?String(e.stderr??``):``;throw new ProjectGitInitError(`git init failed at ${t}: ${e instanceof Error?e.message:String(e)}`,S,{cause:e})}if(!existsSync(w))throw new ProjectGitInitError(`git init reported success but ${S}/HEAD is missing (partial init detected)`,D);return E?(console.log(`[project-git] backfilled missing .git/HEAD at ${t}`),{didInit:!0,repaired:!0}):(console.log(`[project-git] initialized .git/ at ${t} (branch: main)`),{didInit:!0})}async function resolvePackageVersion(e,t){let S;try{S=createRequire(t).resolve(e)}catch(e){if(e?.code===`MODULE_NOT_FOUND`)return;throw e}for(let t=dirname(S),w=0;w<32;w+=1){let S=join(t,`package.json`);if(existsSync(S))try{let t=JSON.parse(await readFile$1(S,`utf-8`));if(t.name===e&&typeof t.version==`string`)return t.version}catch{}let w=dirname(t);if(w===t)return;t=w}}export{assertNeverDiskEvent as $,rewriteWikiLinksForDocumentRename as $n,ALL_EDITOR_IDS as $r,incrementServerObserverFire as $t,MissingOkConfigError as A,_coercedNumber as Ai,readServerPackageVersion as An,tracedWriteFile as Ar,createStreamingErrorWriter as At,STARTER_PACK_IDS as B,registerWrite as Bn,writeTargetVersion as Br,formatAuthRejectionWire as Bt,LOG_MD_TEMPLATE as C,boolean$1 as Ci,parseAuthRejectionWire as Cn,tracedMkdir as Cr,createExternalChangeHandler as Ct,MCP_SERVER_NAME as D,object$1 as Di,planSeed as Dn,tracedRmSync as Dr,createPersistenceExtension as Dt,MCP_CONNECTION_ID_HEADER as E,number$1 as Ei,pathToDocName as En,tracedRenameSync as Er,createOsProbe as Et,SERVICE_WRITER as F,readUiLock as Fn,validateCloneInputs as Fr,errorResponse as Ft,StateManifestError as G,resolveContentDir as Gn,isInitializedNotification as Gr,getLocalDir as Gt,STATE_MANIFEST_FILENAME as H,removeLastKnownHash as Hn,McpServer as Hr,formatContributorsFrom as Ht,SKILL_INSTALL_EVENTS_FILE_REL as I,reconcile as In,validateSkillZip as Ir,evictStaleTrackerEntries as It,acquireUiLock as J,resolveLockDir as Jn,readConfigSafely as Jr,getMetrics as Jt,TagIndex as K,resolveCursorBinaryDefault as Kn,isJSONRPCRequest as Kr,getLogger as Kt,STARTER_FOLDERS as L,recordContributor as Ln,withSpan as Lr,extractWikiLinksFromMarkdown as Lt,PinoLogger as M,require_dist$2 as Mi,readStateManifest as Mn,updateLastKnownHash as Mr,detectClaudeDesktopPresence as Mt,ProjectGitInitError as N,readTargetRecordedAt as Nn,updateUiLockPort as Nr,detectProjectShape as Nt,MISSING_OK_CONFIG_MESSAGE as O,string$2 as Oi,readAllTargets as On,tracedRmdirSync as Or,createServer$1 as Ot,ROLLBACK_ORIGIN as P,readTargetVersion as Pn,validateAgentId as Pr,ensureProjectGit as Pt,assertCompatibleStateManifest as Q,rewriteMarkdownLinksForDocumentRename as Qn,MalformedGitPointerError as Qr,incrementCollabSocketFilteredError as Qt,STARTER_FOLDER_FRONTMATTER_FILENAME as R,recordSkillInstallEvent as Rn,withSpanSync as Rr,findEnclosingGitRoot as Rt,LIVE_DERIVED_INDEX_DEBOUNCE_MS as S,array as Si,normalizeFsPath as Sn,tracedLinkSync as Sr,createContentFilterAsync as St,MAX_AGENT_SESSIONS as T,looseObject as Ti,parseKeepaliveConnectionId as Tn,tracedRename as Tr,createMcpHttpHandler as Tt,SeedPrerequisiteError as U,resetMetrics as Un,JSONRPCMessageSchema as Ur,gcCheckpointRefs as Ut,STARTER_TEMPLATES as V,releaseUiLock as Vn,writeTracker as Vr,formatContributors as Vt,SeedRootDirError as W,resolveBundledSkillDir as Wn,LATEST_PROTOCOL_VERSION as Wr,getCurrentMcpLogger as Wt,applyExternalChange as X,resolvePackageVersion as Xn,writeConfigPatch as Xr,handleCollabSocketError as Xt,applyAgentMarkdownWrite as Y,resolvePack as Yn,resolveConfigPath as Yr,getTracer as Yt,applySeed as Z,restoreContributors as Zn,GitDirAccessError as Zr,handleSpawnCursor as Zt,GIT_UPSTREAM_WRITER as _,LOCAL_DIR as _i,listRescueCheckpoints as _n,startWatcher as _r,contentHash as _t,AgentPresenceBroadcaster as a,EXECUTABLE_BLOCKLIST_EXTENSIONS as ai,isAllowedApiOrigin as an,safeContentPath as ar,buildReadResult as at,HocuspocusAuthTokenSchema as b,ZodNumber$1 as bi,loggerFactory as bn,toBroadcasterKey as br,createAssetServeMiddleware as bt,BacklinkIndex as c,ProblemDetailsSchema as ci,isHocuspocusAuthRejectionReason as cn,sanitizeClientName as cr,buildWipTree as ct,CURSOR_BUNDLE_PATHS_BY_PLATFORM as d,colorFromSeed as di,isPairedWriteOrigin as dn,seedBasenameIndex as dr,clearContributors as dt,ASSET_EXTENSIONS as ei,initShadowRepo as en,runAuthReposSubprocess as er,attachIdleShutdown as et,ConfigSchema as f,defaultScheduler as fi,isPathWithinDir as fn,setActiveSpanAttributes as fr,coercePackId as ft,FILE_WATCHER_ORIGIN as g,CONFIG_SCHEMA_MAJOR_PATH as gi,lastKnownHash as gn,splitMarkdownBlocks as gr,containsConflictMarkers as gt,FILE_SYSTEM_WRITER as h,isOrphanMode as hi,isSystemDoc as hn,spawnDetached as hr,commitWipFromTree as ht,AgentFocusBroadcaster as i,EDITOR_LABELS as ii,installUserSkill as in,runWithMcpLogger as ir,buildInstructions as it,OBSERVER_SYNC_ORIGIN as j,NEVER as ji,readSkillInstallStateSnapshot as jn,tracedWriteFileSync as jr,createTestLogger as jt,McpLogger as k,url as ki,readBranchFromHead as kn,tracedUnlinkSync as kr,createServerObserverExtension as kt,CC1Broadcaster as l,SKILL_STATE_TARGETS as li,isKnownPackId as ln,saveInMemoryCheckpoint as lr,classifyEvents as lt,DEFAULT_PACK_ID as m,iconFromClientName as mi,isSelfWrite as mn,shutdownTelemetry as mr,commitWip as mt,AGENT_ID_RE as n,DEFAULT_GITHUB_OAUTH_CLIENT_ID as ni,installPrettyZodErrors as nn,runCloneSubprocess as nr,buildAndOpenSkill as nt,AgentSessionCapacityError as o,INLINE_RENDERABLE_EXTENSIONS as oi,isAllowedWorkspaceHostHeader as on,safeSubdir as or,buildSkillZip as ot,DEFAULT_CHECKPOINT_RETENTION as p,humanFormat as pi,isProjectRoot as pn,shadowGit as pr,commitUpstreamImport as pt,UiLockCollisionError as q,resolveCursorSpawnInvocation as qn,isJSONRPCResultResponse as qr,getMeter as qt,AGENT_WRITE_ORIGIN as r,DEFAULT_SERVER_HOST as ri,installTestLoggers as rn,runDeviceFlowSubprocess as rr,buildExecResult as rt,AgentSessionManager as s,ORPHAN_MODES as si,isConfigDoc as sn,safetyCheckpoint as sr,buildStarterFolderFrontmatterYaml as st,AGENT_ID_MAX_LEN as t,CC1_CONTRACT_VERSION as ti,initTelemetry as tn,runAuthStatusSubprocess as tr,bootServer as tt,CONFLICT_MARKER_RE as u,SYSTEM_DOC_NAME as ui,isLoopbackAddress as un,saveVersion as ur,classifyFsPath as ut,HOCUSPOCUS_AUTH_REJECTION_REASONS as v,OK_PROJECT_MARKER as vi,listStarterPacks as vn,streamingProblemEvent as vr,contributorCount as vt,MANAGED_RENAME_ORIGIN as w,literal as wi,parseHocuspocusAuthToken as wn,tracedMkdirSync as wr,createLiveDerivedIndexExtension as wt,INSTALLED_AGENTS_SCHEMES as x,any$1 as xi,mountMcpAndApi as xn,tracedAppendFileSync as xr,createContentFilter as xt,HocuspocusAuthRejection as y,locateIssue as yi,loadPrincipal as yn,swapContributors as yr,createApiExtension as yt,STARTER_PACKS as z,registerAllTools as zn,writeStateManifest as zr,findEnclosingProjectRoot as zt};
|
|
3074
|
+
//# sourceMappingURL=dist-DjC84IgZ.mjs.map
|