@inkeep/open-knowledge 0.0.0-dev-20260430114143 → 0.0.0-dev-20260430143017
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/cli.mjs +5 -5
- package/dist/constants-CxQqeafL.mjs +2 -0
- package/dist/{dist-4R_64RM-.mjs → dist-DIvHbLlg.mjs} +6 -5
- package/dist/{dist-B_F7lvhy.mjs → dist-EY8HptxY.mjs} +1 -1
- package/dist/index.mjs +1 -1
- package/dist/init-B3uGrxky.mjs +1 -0
- package/dist/init-Bjf0qJPH.mjs +1 -0
- package/dist/{init-DNr_9OgR.mjs → init-DUoMa9vS.mjs} +3 -3
- package/dist/{init-Dqz7_zO5.mjs → init-M_iZj3b4.mjs} +2 -2
- package/dist/loader-CDwZoOZT.mjs +1 -0
- package/dist/{loader-BKFiCMIa.mjs → loader-DtQHwYLI.mjs} +2 -2
- package/dist/paths-BDTDW9fv.mjs +1 -0
- package/dist/paths-D6PiyuBM.mjs +2 -0
- package/dist/{preview-Cult7sjc.mjs → preview-BdpgALxC.mjs} +2 -2
- package/dist/preview-Bik03UEr.mjs +1 -0
- package/dist/public/assets/{ActivityModeContent-DfUTOBgs.js → ActivityModeContent-BTaFD1U9.js} +1 -1
- package/dist/public/assets/{DocumentContext-DoCfv7j-.js → DocumentContext-DAIo0tO4.js} +2 -2
- package/dist/public/assets/{SettingsPane-DpquQmsN.js → SettingsPane-DI69uSJ8.js} +1 -1
- package/dist/public/assets/{SourceEditor-DxXLr-rH.js → SourceEditor-DETsdSVD.js} +1 -1
- package/dist/public/assets/{clipboard-gmuzGuGs.js → clipboard-u6JJjR6P.js} +1 -1
- package/dist/public/assets/{config-validation-events-D-_GEtc8.js → config-validation-events-DVkEzAED.js} +1 -1
- package/dist/public/assets/{index-CtKJP5vb.js → index-Cw2rGin_.js} +3 -3
- package/dist/public/index.html +4 -4
- package/dist/src-K3thD12M.mjs +1 -0
- package/dist/start-CRIGht80.mjs +1 -0
- package/dist/{start-BqL97CT_.mjs → start-CaJ1XX6a.mjs} +2 -2
- package/package.json +1 -1
- package/dist/constants-Dsup7g7b.mjs +0 -2
- package/dist/init-B7SPU1sB.mjs +0 -1
- package/dist/init-CfK5d723.mjs +0 -1
- package/dist/loader-Cvkobp0h.mjs +0 -1
- package/dist/paths-CPeHdYhU.mjs +0 -1
- package/dist/paths-biVIwieT.mjs +0 -2
- package/dist/preview-B85r4s7v.mjs +0 -1
- package/dist/src-BrLmEjU2.mjs +0 -1
- package/dist/start-CPQfPn2E.mjs +0 -1
|
@@ -69,7 +69,8 @@ To resolve the conflict:`,(0,r.getConflictResolutionRecipe)(i,e))),a=o):n.diag.w
|
|
|
69
69
|
`).filter(e=>e.length>0)}catch{return 0}let r=[],i={server:0,"human-":0,upstream:0};for(let e of n){let t=e.split(`/`);if(t.length<4)continue;let n=t.slice(3).join(`/`);parseWriterId(n).classification===`unknown`&&(n===`server`?(r.push(e),i.server++):n.startsWith(`human-`)?(r.push(e),i[`human-`]++):n===`upstream`&&(r.push(e),i.upstream++))}if(r.length===0)return 0;for(let e of r)try{await t.raw(`update-ref`,`-d`,e)}catch(t){console.warn(`[shadow-migration] failed to delete legacy ref ${e}:`,t)}let a=r.length;return incrementShadowMigrationLegacyRefsDeleted(a),console.warn(`[shadow-migration] deleted ${a} legacy refs: server=${i.server} human-=${i[`human-`]} upstream=${i.upstream}`),a}async function commitWip(e,t,n,r,i=`main`){return withSpan(`shadow.commitWip`,{attributes:{"shadow.writer":t.id,"shadow.branch":i}},async()=>commitWipInner(e,t,n,r,i))}async function commitWipInner(e,t,n,r,i=`main`){let a=resolve(e.gitDir,`index-wip-${t.id}`),o=`refs/wip/${i}/${t.id}`,s=shadowGit(e),c=n||`.`;try{try{let t=(await s.raw(`rev-parse`,`${o}^{tree}`)).trim();await s.env({GIT_DIR:e.gitDir,GIT_INDEX_FILE:a}).raw(`read-tree`,t)}catch(e){let t=e instanceof Error?e.message:String(e);if(!(t.includes(`unknown revision`)||t.includes(`bad revision`)))throw console.error(`[shadow-repo] Unexpected error seeding index for ${o}:`,e),e}await s.env({GIT_DIR:e.gitDir,GIT_WORK_TREE:e.workTree,GIT_INDEX_FILE:a}).raw(`add`,c);let n=(await s.env({GIT_DIR:e.gitDir,GIT_INDEX_FILE:a}).raw(`write-tree`)).trim(),i=null;try{i=(await s.raw(`rev-parse`,o)).trim()}catch(e){let t=e instanceof Error?e.message:String(e);if(!t.includes(`unknown revision`)&&!t.includes(`bad revision`))throw console.error(`[shadow-repo] Unexpected error resolving ${o}:`,e),e}let l=[`commit-tree`,n,`-m`,r];i&&l.push(`-p`,i);let u=(await s.env({GIT_DIR:e.gitDir,GIT_AUTHOR_NAME:t.name,GIT_AUTHOR_EMAIL:t.email,GIT_COMMITTER_NAME:`openknowledge`,GIT_COMMITTER_EMAIL:`noreply@openknowledge.local`}).raw(...l)).trim();return await s.raw(`update-ref`,o,u),u}finally{try{rmSync(a)}catch{}}}function sweepOrphanedTmpIndexFiles(e){let t=0;try{for(let n of readdirSync(e.gitDir))if(n.startsWith(`index-wip-fanout-`))try{rmSync(resolve(e.gitDir,n)),t++}catch{}}catch{}return t}async function buildWipTree(e,t){let n=resolve(e.gitDir,`index-wip-fanout-${randomUUID()}`),r=shadowGit(e),i=t||`.`;try{return await r.env({GIT_DIR:e.gitDir,GIT_WORK_TREE:e.workTree,GIT_INDEX_FILE:n}).raw(`add`,i),(await r.env({GIT_DIR:e.gitDir,GIT_INDEX_FILE:n}).raw(`write-tree`)).trim()}finally{try{rmSync(n)}catch{}}}async function commitWipFromTree(e,t,n,r,i=`main`){return withSpan(`shadow.commitWipFromTree`,{attributes:{"shadow.writer":t.id,"shadow.branch":i,"shadow.tree":n.slice(0,8)}},async()=>commitWipFromTreeInner(e,t,n,r,i))}async function commitWipFromTreeInner(e,t,n,r,i=`main`){let a=`refs/wip/${i}/${t.id}`,o=shadowGit(e),s=null;try{s=(await o.raw(`rev-parse`,a)).trim()}catch(e){let t=e instanceof Error?e.message:String(e);if(!t.includes(`unknown revision`)&&!t.includes(`bad revision`))throw console.error(`[shadow-repo] Unexpected error resolving ${a}:`,e),e}let c=[`commit-tree`,n,`-m`,r];s&&c.push(`-p`,s);let l=(await o.env({GIT_DIR:e.gitDir,GIT_AUTHOR_NAME:t.name,GIT_AUTHOR_EMAIL:t.email,GIT_COMMITTER_NAME:`openknowledge`,GIT_COMMITTER_EMAIL:`noreply@openknowledge.local`}).raw(...c)).trim();return await o.raw(`update-ref`,a,l),l}const FILE_SYSTEM_WRITER={id:`file-system`,name:`File System`,email:`file-system@openknowledge.local`},GIT_UPSTREAM_WRITER={id:`git-upstream`,name:`Git (upstream)`,email:`git@openknowledge.local`},SERVICE_WRITER={id:`openknowledge-service`,name:`Open Knowledge (service)`,email:`service@openknowledge.local`},UPSTREAM_WRITER=GIT_UPSTREAM_WRITER;async function commitUpstreamImport(e,t,n,r,i=`main`){return withSpan(`shadow.commitUpstreamImport`,{attributes:{"shadow.branch":i,"shadow.new_head":r.slice(0,8)}},async()=>commitUpstreamImportInner(e,t,n,r,i))}async function commitUpstreamImportInner(e,t,n,r,i=`main`){return commitWip(e,UPSTREAM_WRITER,t,`${formatImportSubject(n,r)}\n\n${formatOkActor({v:1,writer_id:UPSTREAM_WRITER.id,principal:null,agent_session:null,agent_type:null,client_name:null,client_version:null,label:null,display_name:UPSTREAM_WRITER.name,color_seed:UPSTREAM_WRITER.id,docs:[]})}`,i)}const SAFETY_WRITER=SERVICE_WRITER;async function safetyCheckpoint(e,t,n,r=`main`){return commitWip(e,SAFETY_WRITER,t,`${formatCheckpointSubject(`pre-${n.action}`)}\n\n${formatOkActor({v:1,writer_id:SAFETY_WRITER.id,principal:null,agent_session:null,agent_type:null,client_name:null,client_version:null,label:null,display_name:SAFETY_WRITER.name,color_seed:SAFETY_WRITER.id,docs:[]})}`,r)}async function saveInMemoryCheckpoint(e,t,n){let r=n.branch??`main`,i=shadowGit(e),a=randomUUID(),o=resolve(e.gitDir,`index-checkpoint-${a}`),s=resolve(e.gitDir,`tmp-checkpoint-blob-${a}`),c=t?`${t.replace(/\/$/,``)}/${n.docName}`:n.docName,l=Buffer.byteLength(n.contents,`utf-8`),u=formatCheckpointBodyLine(n.kind===`bridge-merge-loss`?{kind:`bridge-merge-loss`,docName:n.docName,size:l,metadata:n.metadata}:{kind:`external-change-rescue`,docName:n.docName,size:l,metadata:n.metadata}),d=`checkpoint: ${n.label}\n\n${u}`;try{tracedWriteFileSync(s,n.contents,`utf-8`);let t=(await i.env({GIT_DIR:e.gitDir,GIT_INDEX_FILE:o}).raw(`hash-object`,`-w`,s)).trim();await i.env({GIT_DIR:e.gitDir,GIT_INDEX_FILE:o}).raw(`update-index`,`--add`,`--cacheinfo`,`100644,${t},${c}`);let a=(await i.env({GIT_DIR:e.gitDir,GIT_INDEX_FILE:o}).raw(`write-tree`)).trim(),l=(await i.env({GIT_DIR:e.gitDir,GIT_AUTHOR_NAME:`openknowledge`,GIT_AUTHOR_EMAIL:`noreply@openknowledge.local`,GIT_COMMITTER_NAME:`openknowledge`,GIT_COMMITTER_EMAIL:`noreply@openknowledge.local`}).raw(`commit-tree`,a,`-m`,d)).trim();return await i.raw(`update-ref`,`refs/checkpoints/${r}/${l}`,l),l}finally{try{rmSync(o)}catch{}try{rmSync(s)}catch{}}}async function listRescueCheckpoints(e,t=`main`){let n=shadowGit(e),r;try{r=await n.raw(`for-each-ref`,`--format=%(objectname)`,`refs/checkpoints/${t}/`)}catch{return[]}let i=r.trim().split(`
|
|
70
70
|
`).filter(e=>e.length===40);if(i.length===0)return[];let a;try{a=await n.raw(`log`,`--no-walk`,`--author-date-order`,`--format=%H%x00%aI%x00%s%x00%B%x1e`,...i)}catch{return[]}let o=[];for(let e of a.split(``)){let t=e.trimStart();if(!t)continue;let[r=``,i=``,a=``,s=``]=t.split(`\0`),c=parseCheckpoint(s);if(c?.kind!==`external-change-rescue`)continue;let l=c.docName??``,u=c.size??0;if(!l)try{let e=(await n.raw(`ls-tree`,`-r`,`--long`,r)).trim().split(`
|
|
71
71
|
`)[0];if(e){let t=e.split(/\s+/),n=4,r=3;u===0&&(u=Number(t[3]??`0`)),l=(t[4]??``).replace(/\.mdx?$/,``).split(`/`).slice(-1)[0]??``}}catch{}l&&o.push({docName:l,timestamp:i,size:u,sha:r,label:a.replace(/^checkpoint:\s*/,``),incomingDiskSha:c.metadata.incomingDiskSha})}return o}async function parkBranch(e,t,n,r,i){return r.length===0?null:withSpan(`shadow.parkBranch`,{attributes:{"shadow.branch":t,"shadow.new_branch":i??``,"shadow.doc_count":r.length}},async()=>parkBranchInner(e,t,n,r,i))}async function parkBranchInner(e,t,n,r,i){let a=shadowGit(e),o=resolve(e.gitDir,`index-park-${t.replace(/\//g,`-`)}`),s=`refs/wip/${t}/${n}`,c=resolve(e.gitDir,`tmp-park-blob`);try{for(let t of r){tracedWriteFileSync(c,t.markdown,`utf-8`);let n=(await a.env({GIT_DIR:e.gitDir,GIT_INDEX_FILE:o}).raw(`hash-object`,`-w`,c)).trim();await a.env({GIT_DIR:e.gitDir,GIT_INDEX_FILE:o}).raw(`update-index`,`--add`,`--cacheinfo`,`100644,${n},${t.docName}`),tracedWriteFileSync(c,t.diskSnapshot,`utf-8`);let r=(await a.env({GIT_DIR:e.gitDir,GIT_INDEX_FILE:o}).raw(`hash-object`,`-w`,c)).trim();await a.env({GIT_DIR:e.gitDir,GIT_INDEX_FILE:o}).raw(`update-index`,`--add`,`--cacheinfo`,`100644,${r},.park-base/${t.docName}`)}let n=(await a.env({GIT_DIR:e.gitDir,GIT_INDEX_FILE:o}).raw(`write-tree`)).trim(),l=null;try{l=(await a.raw(`rev-parse`,s)).trim()}catch{}let u={v:1,writer_id:SERVICE_WRITER.id,principal:null,agent_session:null,agent_type:null,client_name:null,client_version:null,label:null,display_name:SERVICE_WRITER.name,color_seed:SERVICE_WRITER.id,docs:r.map(e=>e.docName)},d=[`commit-tree`,n,`-m`,`${formatParkSubject(t,i??t)}\n\n${formatOkActor(u)}`];l&&d.push(`-p`,l);let f=(await a.env({GIT_DIR:e.gitDir,GIT_AUTHOR_NAME:`openknowledge`,GIT_AUTHOR_EMAIL:`noreply@openknowledge.local`,GIT_COMMITTER_NAME:`openknowledge`,GIT_COMMITTER_EMAIL:`noreply@openknowledge.local`}).raw(...d)).trim();return await a.raw(`update-ref`,s,f),f}finally{try{rmSync(o)}catch{}try{rmSync(c)}catch{}}}async function readParkedState(e,t,n,r){let i=shadowGit(e),a=`refs/wip/${t}/${n}`,o;try{o=(await i.raw(`rev-parse`,a)).trim()}catch{return null}try{return(await i.raw(`log`,`-1`,`--format=%s`,o)).trim().startsWith(`park:`)?{markdown:(await i.raw(`show`,`${o}:${r}`)).trim(),diskSnapshot:(await i.raw(`show`,`${o}:.park-base/${r}`)).trim()}:null}catch(e){throw console.error(`[shadow] Failed to read parked state for ${r} from ${a}:`,e),e}}async function saveVersion(e,t,n,r=`main`){return withSpan(`shadow.saveVersion`,{attributes:{"shadow.branch":r,"shadow.writer_count":n.length}},async()=>saveVersionInner(e,t,n,r))}async function saveVersionInner(e,t,n,r=`main`){let i=shadowGit(e),a=t||`.`,o=resolve(e.gitDir,`index-checkpoint`);try{await i.env({GIT_DIR:e.gitDir,GIT_WORK_TREE:e.workTree,GIT_INDEX_FILE:o}).raw(`add`,a);let t=(await i.env({GIT_DIR:e.gitDir,GIT_INDEX_FILE:o}).raw(`write-tree`)).trim(),s=[];for(let e of[...n,GIT_UPSTREAM_WRITER])try{let t=(await i.raw(`rev-parse`,`refs/wip/${r}/${e.id}`)).trim();s.push(t)}catch{}let c=[...new Set(s)];if(c.length===0)try{let e=(await i.raw(`for-each-ref`,`--sort=-creatordate`,`--format=%(objectname)`,`refs/checkpoints/${r}/`)).trim().split(`
|
|
72
|
-
`).filter(Boolean);e[0]&&c.push(e[0])}catch{}let l={v:1,writer_id:SERVICE_WRITER.id,principal:null,agent_session:null,agent_type:null,client_name:null,client_version:null,label:null,display_name:SERVICE_WRITER.name,color_seed:SERVICE_WRITER.id,docs:[]},u=[`commit-tree`,t,`-m`,`${formatCheckpointSubject(`Checkpoint version`)}\n\n${formatOkActor(l)}`];for(let e of c)u.push(`-p`,e);let d=(await i.env({GIT_DIR:e.gitDir,GIT_AUTHOR_NAME:`openknowledge`,GIT_AUTHOR_EMAIL:`noreply@openknowledge.local`,GIT_COMMITTER_NAME:`openknowledge`,GIT_COMMITTER_EMAIL:`noreply@openknowledge.local`}).raw(...u)).trim(),f=`refs/checkpoints/${r}/${d}`;await i.raw(`update-ref`,f,d);for(let e of n)try{await i.raw(`update-ref`,`-d`,`refs/wip/${r}/${e.id}`)}catch{}try{await i.raw(`update-ref`,`-d`,`refs/wip/${r}/${GIT_UPSTREAM_WRITER.id}`)}catch{}return{checkpointRef:f}}finally{try{rmSync(o)}catch{}}}const log$4=getLogger(`persistence`);function resolveWriterFromOrigin(e,t){if(!e||typeof e!=`object`)return null;let n=e;if(n.source===`local`){let e=n.context;if(!e)return null;if(typeof e.session_id==`string`){let t=e.session_id;return{id:`agent-${t}`,name:`Agent (${t.slice(0,8)})`,email:`agent-${t}@openknowledge.local`}}return e.origin===`file-watcher`?FILE_SYSTEM_WRITER:e.origin===`upstream-import`||e.origin===`git-upstream`?GIT_UPSTREAM_WRITER:SERVICE_WRITER}if(n.source===`connection`){let e=n.connection?.context;if(typeof e?.principalId==`string`){let n=e.principalId,r=t?.();return r&&r.id===n&&r.display_name&&r.display_email?{id:r.id,name:r.display_name,email:r.display_email}:{id:n,name:`Local User`,email:`${n}@openknowledge.local`}}return SERVICE_WRITER}return null}function captureDocSnapshotForPersistence(e){return{sv:encodeStateVector(e),json:yXmlFragmentToProseMirrorRootNode(e.getXmlFragment(`default`),schema).toJSON()}}function safeContentPath(e,t){if(e.includes(`\0`))throw Error(`Invalid document name: ${e}`);let n=resolve(t,`${e}${getDocExtension(e)}`);if(!n.startsWith(`${t}/`))throw Error(`Invalid document name: ${e}`);return n}function isWithinContentDir(e,t){return e===t||e.startsWith(t+sep)}const reconciledBaseByBranch=new Map;let activeBranch=`main`;function switchReconciledBaseScope(e){activeBranch=e,reconciledBaseByBranch.has(e)||reconciledBaseByBranch.set(e,new Map)}function getActiveBranch(){return activeBranch}function getReconciledBase(e){return reconciledBaseByBranch.get(activeBranch)?.get(e)}function setReconciledBase(e,t){reconciledBaseByBranch.has(activeBranch)||reconciledBaseByBranch.set(activeBranch,new Map),reconciledBaseByBranch.get(activeBranch)?.set(e,t)}function deleteReconciledBase(e){reconciledBaseByBranch.get(activeBranch)?.delete(e)}let batchInProgress=!1;function setBatchInProgress(e){batchInProgress=e}function isBatchInProgress(){return batchInProgress}function createPersistenceExtension(e){let t=e?.contentDir??process.cwd(),n;try{n=realpathSync(t)}catch{n=t}let r=e?.projectDir??process.cwd(),i=e?.shadowRef,a=e?.contentRoot??(relative(r,n)||`.`),o=e?.backlinkIndex,s=e?.getPrincipal,c=e?.onAgentCommit,l=e?.onDiskFlush,u={projectDir:r,lkgCache:new Map,homedirOverride:e?.configHomedirOverride,onConfigRejected:e?.onConfigRejected},d=new Map,f=e?.gitEnabled??!0,p=e?.commitDebounceMs??15e3,m=e?.wipRef??`refs/wip/main`,h=e?.getCurrentBranch,g=null,_=0,v=null,y=!1;async function b(){O();let e=Date.now();return withSpan(`persistence.commitToWipRef`,void 0,async()=>await x()).finally(()=>{D?.record((Date.now()-e)/1e3)})}async function x(){let e=i?.current;if(e){let t=swapContributors(),n=h?.()??`main`;if(t.size===0){let t={v:1,writer_id:SERVICE_WRITER.id,principal:null,agent_session:null,agent_type:null,client_name:null,client_version:null,label:null,display_name:SERVICE_WRITER.name,color_seed:SERVICE_WRITER.id,docs:[]},r=`${formatWipSubject([])}\n\n${formatOkActor(t)}`;try{let t=await commitWip(e,SERVICE_WRITER,a,r,n);_=0,log$4.info({sha:t.slice(0,8),writer:SERVICE_WRITER.id},`[persistence] Shadow WIP commit: ${t.slice(0,8)} on refs/wip/${SERVICE_WRITER.id}`)}catch(e){_++,incrementGitAutoSaveFailure(),log$4.error({err:e,attempt:_},`[persistence] Shadow commit failed (attempt ${_})`),_>=3&&log$4.error({attempt:_},`[persistence] CRITICAL: Git auto-save has failed 3+ times. Version history is NOT being recorded.`)}return}let r;try{r=await buildWipTree(e,a)}catch(e){restoreContributors(t),_++,incrementGitAutoSaveFailure(),log$4.error({err:e,attempt:_},`[persistence] Shadow WIP tree build failed (attempt ${_})`);return}let i=!1;for(let[a,o]of t){let t={id:a,name:o.displayName,email:`${a}@openknowledge.local`},s=[...o.docs],l=o.actor,u=[...o.summaries],d={v:1,writer_id:a,principal:l?.principalId??null,agent_session:a.startsWith(`agent-`)?a.slice(6):null,agent_type:l?.agentType??null,client_name:l?.clientName??null,client_version:l?.clientVersion??null,label:l?.label??null,display_name:o.displayName,color_seed:o.colorSeed,docs:s,...u.length>0?{summaries:u}:{}},f=`${composeCommitSubject(o.subjectOverride??formatWipSubject(s),u)}\n\n${formatOkActor(d)}`;try{let o=await commitWipFromTree(e,t,r,f,n);i=!0,log$4.info({sha:o.slice(0,8),writer:a,tree:r.slice(0,8)},`[persistence] Shadow WIP commit: ${o.slice(0,8)} on refs/wip/${a}`),a.startsWith(`agent-`)&&c?.()}catch(e){restoreContributorEntry(a,o),incrementGitWriterCommitFailure(),log$4.error({err:e,writer:a},`[persistence] Per-writer shadow commit failed for ${a}`)}}i?_=0:(_++,incrementGitAutoSaveFailure(),_>=3&&log$4.error({attempt:_},`[persistence] CRITICAL: Git auto-save has failed 3+ times. Version history is NOT being recorded.`));return}let t=shadowGit({gitDir:resolve(r,`.git`),workTree:r}),n=resolve(r,`.git/index-wip`),o={GIT_INDEX_FILE:n};try{try{let e=(await t.raw(`rev-parse`,`HEAD^{tree}`)).trim();await t.env(o).raw(`read-tree`,e)}catch(e){let t=e instanceof Error?e.message:String(e);t.includes(`unknown revision`)||t.includes(`bad revision`)?log$4.info({},`[persistence] Empty repo — starting with empty index`):log$4.error({err:e},`[persistence] Failed to read HEAD tree, falling back to empty index`)}await t.env(o).raw(`add`,a);let e=(await t.env(o).raw(`write-tree`)).trim(),n=null;try{n=(await t.raw(`rev-parse`,m)).trim()}catch(e){let t=e instanceof Error?e.message:String(e);if(!t.includes(`unknown revision`)&&!t.includes(`bad revision`))throw e}let r=[`commit-tree`,e,`-m`,`WIP auto-save ${new Date().toISOString()}`];n&&r.push(`-p`,n);let i=(await t.raw(...r)).trim();await t.raw(`update-ref`,m,i),_=0,log$4.info({sha:i.slice(0,8),wipRef:m},`[persistence] Git commit: ${i.slice(0,8)} on ${m}`)}catch(e){_++,incrementGitAutoSaveFailure(),log$4.error({err:e,attempt:_},`[persistence] Git commit failed (attempt ${_})`),_>=3&&log$4.error({attempt:_},`[persistence] CRITICAL: Git auto-save has failed 3+ times. Version history is NOT being recorded.`)}finally{try{tracedUnlinkSync(n)}catch{}}}function S(e){if(e<=0)return p;let t=2**Math.min(e,5),n=Math.random()*.25*p;return p*t+n}function C(){f&&(isBatchInProgress()||(g&&clearTimeout(g),g=setTimeout(()=>{if(g=null,v){y=!0;return}v=b().finally(()=>{v=null,y&&(y=!1,C())})},S(_))))}async function w(){g&&(clearTimeout(g),g=null,v||=b().finally(()=>{v=null,y&&(y=!1,C())})),v&&await v}let T=null,E=null,D=null;function O(){if(T)return;let e=getMeter();T=e.createHistogram(`ok.persistence.load.duration`,{description:`Duration of persistence.onLoadDocument in seconds`,unit:`s`}),E=e.createHistogram(`ok.persistence.store.duration`,{description:`Duration of persistence.onStoreDocument in seconds`,unit:`s`}),D=e.createHistogram(`ok.persistence.git_commit.duration`,{description:`Duration of commitToWipRef drain in seconds`,unit:`s`})}let k={async onLoadDocument({document:t,documentName:r,context:i}){if(isSystemDoc(r))return;if(isConfigDoc(r)){loadConfigDoc(t,r,u);return}O();let a=Date.now();return withSpan(`persistence.onLoadDocument`,{attributes:{"doc.name":r}},async()=>{log$4.info({documentName:r,connections:t.getConnectionsCount?.()??`?`},`[persistence] onLoadDocument called for ${r} (connections: ${t.getConnectionsCount?.()??`?`})`);let i=safeContentPath(r,n);if(!existsSync(i))return;try{let e=realpathSync(i);if(!isWithinContentDir(e,n)){console.warn(`[persistence] symlink-escape on load: ${i} → ${e}, refusing`);return}}catch(e){if(e.code===`ELOOP`){console.warn(`[persistence] Symlink cycle on load: ${i}, refusing`);return}}let{frontmatter:a,body:o}=stripFrontmatter(readFileSync(i,`utf-8`));a&&(d.set(r,a),t.getMap(`metadata`).set(`frontmatter`,a));let s=t.getXmlFragment(`default`);log$4.info({documentName:r,fragmentLength:s.length},`[persistence] onLoadDocument ${r}: fragment.length=${s.length} before update`);let c=e?.resolveEmbed?{resolveEmbed:e.resolveEmbed,sourcePath:r}:void 0,l=mdManager.parseWithFallback(o,c);s.length===0?(updateYFragment(t,s,schema.nodeFromJSON(l),{mapping:new Map,isOMark:new Map}),log$4.info({filePath:i,children:s.length},`[persistence] Loaded ${i} into Y.Doc (${s.length} children)`),s.observeDeep(()=>{log$4.info({documentName:r,fragmentLength:s.length},`[persistence] MUTATION on ${r}: fragment.length=${s.length}`)})):log$4.info({documentName:r,children:s.length},`[persistence] Skipped load for ${r} — fragment already has ${s.length} children`),setReconciledBase(r,prependFrontmatter(a,mdManager.serialize(yXmlFragmentToProseMirrorRootNode(s,schema).toJSON())))}).finally(()=>{T?.record((Date.now()-a)/1e3)})},async onStoreDocument({document:e,documentName:t,lastTransactionOrigin:r,lastContext:i}){if(isSystemDoc(t))return;if(isConfigDoc(t)){await storeConfigDoc(e,t,r,u);return}if(isBatchInProgress())return;O();let a=Date.now();return withSpan(`persistence.onStoreDocument`,{attributes:{"doc.name":t}},async()=>{let{sv:i,json:a}=captureDocSnapshotForPersistence(e),c=mdManager.serialize(a),u=e.getMap(`metadata`).get(`frontmatter`),f=prependFrontmatter(typeof u==`string`?u:d.get(t)||``,c),p=getReconciledBase(t);if(p!==void 0&&normalizeBridge(f)===normalizeBridge(p)){contributorCount()>0&&C();return}if(p===void 0&&normalizeBridge(f)===``){log$4.warn({documentName:t},`[persistence] Skipped phantom write for ${t}: empty Y.Doc with no reconciled base`);return}let m=resolveWriterFromOrigin(r,s);m&&m.id!==SERVICE_WRITER.id&&(hasContributor(m.id)||recordContributor(t,m.id,m.name,m.id)),p&&f.length>p.length*1.5&&(log$4.warn({documentName:t,markdownLength:f.length,baseLength:p.length},`[persistence] WARNING: serialized content is ${f.length} bytes vs base ${p.length} bytes for ${t} — possible duplication`),log$4.warn({documentName:t,children:e.getXmlFragment(`default`).length},`[persistence] Fragment children: ${e.getXmlFragment(`default`).length}`));let h=safeContentPath(t,n);await tracedMkdir(dirname(h),{recursive:!0});let g;try{g=await realpath(h)}catch(e){let n=e.code;if(n===`ENOENT`){let e=!1;try{e=lstatSync(h).isSymbolicLink()}catch(e){e.code!==`ENOENT`&&log$4.warn({err:e,path:h},`[persistence] lstat failed during broken-symlink check`)}e&&console.warn(`[persistence] broken-symlink fallback`,{docName:t,reason:`broken-symlink`}),g=h}else if(n===`ELOOP`)throw console.error(`[persistence] Symlink cycle at ${h}`),Error(`Symlink cycle detected at ${h}`);else throw e}if(!isWithinContentDir(g,n)){let e=`symlink-escape: ${h} resolves to ${g} outside ${n}`;throw console.error(`[persistence] ${e}`,{docName:t,originalPath:h,canonical:g,contentDir:n}),Error(e)}let _=`${g}.tmp.${crypto.randomUUID()}`;try{await tracedWriteFile(_,f,`utf-8`),await tracedRename(_,g),registerWrite(g,contentHash(f)),incrementPersistenceDiskWrite(),l?.(t,i)}catch(e){try{tracedUnlinkSync(_)}catch{}throw log$4.error({err:e,documentName:t},`[persistence] Failed to save ${t}`),e}log$4.info({filePath:g,bytes:f.length},`[persistence] Wrote ${g} (${f.length} bytes)`),setReconciledBase(t,f),o&&(o.updateDocumentFromMarkdown(t,f),o.saveToDisk().catch(e=>{log$4.warn({err:e,documentName:t},`[backlinks] Failed to persist cache for ${t}`)})),setActiveSpanAttributes({"persistence.bytes":f.length}),C()}).finally(()=>{E?.record((Date.now()-a)/1e3)})}};async function A(){v&&await v}return{extension:k,flushPendingGitCommit:w,waitForPendingCommits:A,configPersistenceCtx:u}}const CONFLICT_MARKER_RE=/^(<{7} |={7}$|>{7} |\|{7} )/m;function containsConflictMarkers(e){return CONFLICT_MARKER_RE.test(e)}function splitMarkdownBlocks(e){let t=e.replace(/\n+$/,``);if(!t)return[];let n=t.split(`
|
|
72
|
+
`).filter(Boolean);e[0]&&c.push(e[0])}catch{}let l={v:1,writer_id:SERVICE_WRITER.id,principal:null,agent_session:null,agent_type:null,client_name:null,client_version:null,label:null,display_name:SERVICE_WRITER.name,color_seed:SERVICE_WRITER.id,docs:[]},u=[`commit-tree`,t,`-m`,`${formatCheckpointSubject(`Checkpoint version`)}\n\n${formatOkActor(l)}`];for(let e of c)u.push(`-p`,e);let d=(await i.env({GIT_DIR:e.gitDir,GIT_AUTHOR_NAME:`openknowledge`,GIT_AUTHOR_EMAIL:`noreply@openknowledge.local`,GIT_COMMITTER_NAME:`openknowledge`,GIT_COMMITTER_EMAIL:`noreply@openknowledge.local`}).raw(...u)).trim(),f=`refs/checkpoints/${r}/${d}`;await i.raw(`update-ref`,f,d);for(let e of n)try{await i.raw(`update-ref`,`-d`,`refs/wip/${r}/${e.id}`)}catch{}try{await i.raw(`update-ref`,`-d`,`refs/wip/${r}/${GIT_UPSTREAM_WRITER.id}`)}catch{}return{checkpointRef:f}}finally{try{rmSync(o)}catch{}}}const FILE_WATCHER_ORIGIN={source:`local`,skipStoreHooks:!0,context:{origin:`file-watcher`,paired:!0}};function applyDiskContentToDoc(e,t,n,r){let{frontmatter:i,body:a}=stripFrontmatter(t),o=n&&r?{resolveEmbed:n,sourcePath:r}:void 0,s=mdManager.parseWithFallback(a,o),c=schema.nodeFromJSON(s),l=e.getXmlFragment(`default`);e.transact(()=>{updateYFragment(e,l,c,{mapping:new Map,isOMark:new Map}),e.getMap(`metadata`).set(`frontmatter`,i);let n=e.getText(`source`),r=n.toString();r!==t&&applyFastDiff(n,r,t)},FILE_WATCHER_ORIGIN)}function applyExternalChange(e,t,n,r){if(isSystemDoc(t)||isConfigDoc(t))return;let i=e.documents.get(t);i&&(applyDiskContentToDoc(i,n,r,t),recordContributor(t,FILE_SYSTEM_WRITER.id,FILE_SYSTEM_WRITER.name,FILE_SYSTEM_WRITER.id,formatReconcileSubject(t)),setReconciledBase(t,n))}function normalizeBody(e){let{body:t}=stripFrontmatter(e);return normalizeBridge(t).trim()}function isWhitespace(e){return e===` `||e===`
|
|
73
|
+
`||e===` `||e===`\r`}function classifyDuplication(e,t){let n=normalizeBody(t);if(n.length===0)return{kind:`allow`,reason:`empty-base`};let r=normalizeBody(e);if(r===n)return{kind:`allow`,reason:`identical`};if(r.length<n.length*2)return{kind:`allow`,reason:`too-short`};let i=0,a=0;for(;i<r.length;){if(r.slice(i,i+n.length)!==n)return{kind:`allow`,reason:`not-integer-multiple`};for(i+=n.length,a++;i<r.length&&isWhitespace(r[i]??``);)i++}return a>=2?{kind:`block`,reason:`structural-duplication`,copies:a}:{kind:`allow`,reason:`single-copy`}}const log$4=getLogger(`persistence`);function resolveWriterFromOrigin(e,t){if(!e||typeof e!=`object`)return null;let n=e;if(n.source===`local`){let e=n.context;if(!e)return null;if(typeof e.session_id==`string`){let t=e.session_id;return{id:`agent-${t}`,name:`Agent (${t.slice(0,8)})`,email:`agent-${t}@openknowledge.local`}}return e.origin===`file-watcher`?FILE_SYSTEM_WRITER:e.origin===`upstream-import`||e.origin===`git-upstream`?GIT_UPSTREAM_WRITER:SERVICE_WRITER}if(n.source===`connection`){let e=n.connection?.context;if(typeof e?.principalId==`string`){let n=e.principalId,r=t?.();return r&&r.id===n&&r.display_name&&r.display_email?{id:r.id,name:r.display_name,email:r.display_email}:{id:n,name:`Local User`,email:`${n}@openknowledge.local`}}return SERVICE_WRITER}return null}function captureDocSnapshotForPersistence(e){return{sv:encodeStateVector(e),json:yXmlFragmentToProseMirrorRootNode(e.getXmlFragment(`default`),schema).toJSON()}}function safeContentPath(e,t){if(e.includes(`\0`))throw Error(`Invalid document name: ${e}`);let n=resolve(t,`${e}${getDocExtension(e)}`);if(!n.startsWith(`${t}/`))throw Error(`Invalid document name: ${e}`);return n}function isWithinContentDir(e,t){return e===t||e.startsWith(t+sep)}const reconciledBaseByBranch=new Map;let activeBranch=`main`;function switchReconciledBaseScope(e){activeBranch=e,reconciledBaseByBranch.has(e)||reconciledBaseByBranch.set(e,new Map)}function getActiveBranch(){return activeBranch}function getReconciledBase(e){return reconciledBaseByBranch.get(activeBranch)?.get(e)}function setReconciledBase(e,t){reconciledBaseByBranch.has(activeBranch)||reconciledBaseByBranch.set(activeBranch,new Map),reconciledBaseByBranch.get(activeBranch)?.set(e,t)}function deleteReconciledBase(e){reconciledBaseByBranch.get(activeBranch)?.delete(e)}let batchInProgress=!1;function setBatchInProgress(e){batchInProgress=e}function isBatchInProgress(){return batchInProgress}function createPersistenceExtension(e){let t=e?.contentDir??process.cwd(),n;try{n=realpathSync(t)}catch{n=t}let r=e?.projectDir??process.cwd(),i=e?.shadowRef,a=e?.contentRoot??(relative(r,n)||`.`),o=e?.backlinkIndex,s=e?.getPrincipal,c=e?.onAgentCommit,l=e?.onDiskFlush,u={projectDir:r,lkgCache:new Map,homedirOverride:e?.configHomedirOverride,onConfigRejected:e?.onConfigRejected},d=new Map,f=new Set,p=e?.applyDiskContentToDoc??applyDiskContentToDoc,m=null,h=e?.gitEnabled??!0,g=e?.commitDebounceMs??15e3,_=e?.wipRef??`refs/wip/main`,v=e?.getCurrentBranch,y=null,b=0,x=null,S=!1,C=null,w=new Map;async function T(){N();let e=Date.now();return withSpan(`persistence.commitToWipRef`,void 0,async()=>await E()).finally(()=>{M?.record((Date.now()-e)/1e3)})}async function E(){let e=i?.current;if(e){let t=swapContributors(),n=v?.()??`main`;if(t.size===0){let t={v:1,writer_id:SERVICE_WRITER.id,principal:null,agent_session:null,agent_type:null,client_name:null,client_version:null,label:null,display_name:SERVICE_WRITER.name,color_seed:SERVICE_WRITER.id,docs:[]},r=`${formatWipSubject([])}\n\n${formatOkActor(t)}`;try{let t=await commitWip(e,SERVICE_WRITER,a,r,n);b=0,log$4.info({sha:t.slice(0,8),writer:SERVICE_WRITER.id},`[persistence] Shadow WIP commit: ${t.slice(0,8)} on refs/wip/${SERVICE_WRITER.id}`)}catch(e){b++,incrementGitAutoSaveFailure(),log$4.error({err:e,attempt:b},`[persistence] Shadow commit failed (attempt ${b})`),b>=3&&log$4.error({attempt:b},`[persistence] CRITICAL: Git auto-save has failed 3+ times. Version history is NOT being recorded.`)}return}let r;try{r=await buildWipTree(e,a)}catch(e){restoreContributors(t),b++,incrementGitAutoSaveFailure(),log$4.error({err:e,attempt:b},`[persistence] Shadow WIP tree build failed (attempt ${b})`);return}let i=!1;for(let[a,o]of t){let t={id:a,name:o.displayName,email:`${a}@openknowledge.local`},s=[...o.docs],l=o.actor,u=[...o.summaries],d={v:1,writer_id:a,principal:l?.principalId??null,agent_session:a.startsWith(`agent-`)?a.slice(6):null,agent_type:l?.agentType??null,client_name:l?.clientName??null,client_version:l?.clientVersion??null,label:l?.label??null,display_name:o.displayName,color_seed:o.colorSeed,docs:s,...u.length>0?{summaries:u}:{}},f=`${composeCommitSubject(o.subjectOverride??formatWipSubject(s),u)}\n\n${formatOkActor(d)}`;try{let o=await commitWipFromTree(e,t,r,f,n);i=!0,log$4.info({sha:o.slice(0,8),writer:a,tree:r.slice(0,8)},`[persistence] Shadow WIP commit: ${o.slice(0,8)} on refs/wip/${a}`),a.startsWith(`agent-`)&&c?.()}catch(e){restoreContributorEntry(a,o),incrementGitWriterCommitFailure(),log$4.error({err:e,writer:a},`[persistence] Per-writer shadow commit failed for ${a}`)}}i?b=0:(b++,incrementGitAutoSaveFailure(),b>=3&&log$4.error({attempt:b},`[persistence] CRITICAL: Git auto-save has failed 3+ times. Version history is NOT being recorded.`));return}let t=shadowGit({gitDir:resolve(r,`.git`),workTree:r}),n=resolve(r,`.git/index-wip`),o={GIT_INDEX_FILE:n};try{try{let e=(await t.raw(`rev-parse`,`HEAD^{tree}`)).trim();await t.env(o).raw(`read-tree`,e)}catch(e){let t=e instanceof Error?e.message:String(e);t.includes(`unknown revision`)||t.includes(`bad revision`)?log$4.info({},`[persistence] Empty repo — starting with empty index`):log$4.error({err:e},`[persistence] Failed to read HEAD tree, falling back to empty index`)}await t.env(o).raw(`add`,a);let e=(await t.env(o).raw(`write-tree`)).trim(),n=null;try{n=(await t.raw(`rev-parse`,_)).trim()}catch(e){let t=e instanceof Error?e.message:String(e);if(!t.includes(`unknown revision`)&&!t.includes(`bad revision`))throw e}let r=[`commit-tree`,e,`-m`,`WIP auto-save ${new Date().toISOString()}`];n&&r.push(`-p`,n);let i=(await t.raw(...r)).trim();await t.raw(`update-ref`,_,i),b=0,log$4.info({sha:i.slice(0,8),wipRef:_},`[persistence] Git commit: ${i.slice(0,8)} on ${_}`)}catch(e){b++,incrementGitAutoSaveFailure(),log$4.error({err:e,attempt:b},`[persistence] Git commit failed (attempt ${b})`),b>=3&&log$4.error({attempt:b},`[persistence] CRITICAL: Git auto-save has failed 3+ times. Version history is NOT being recorded.`)}finally{try{tracedUnlinkSync(n)}catch{}}}function D(e){if(e<=0)return g;let t=2**Math.min(e,5),n=Math.random()*.25*g;return g*t+n}function O(){h&&(isBatchInProgress()||(y&&clearTimeout(y),y=setTimeout(()=>{if(y=null,x){S=!0;return}x=T().finally(()=>{x=null,S&&(S=!1,O())})},D(b))))}async function k(){y&&(clearTimeout(y),y=null,x||=T().finally(()=>{x=null,S&&(S=!1,O())})),x&&await x}let A=null,j=null,M=null;function N(){if(A)return;let e=getMeter();A=e.createHistogram(`ok.persistence.load.duration`,{description:`Duration of persistence.onLoadDocument in seconds`,unit:`s`}),j=e.createHistogram(`ok.persistence.store.duration`,{description:`Duration of persistence.onStoreDocument in seconds`,unit:`s`}),M=e.createHistogram(`ok.persistence.git_commit.duration`,{description:`Duration of commitToWipRef drain in seconds`,unit:`s`})}async function P({document:e,documentName:t,lastTransactionOrigin:r}){N();let i=Date.now();return withSpan(`persistence.onStoreDocument`,{attributes:{"doc.name":t}},async()=>{let{sv:i,json:a}=captureDocSnapshotForPersistence(e),c=mdManager.serialize(a),u=e.getMap(`metadata`).get(`frontmatter`),m=prependFrontmatter(typeof u==`string`?u:d.get(t)||``,c),h=getReconciledBase(t);if(h!==void 0&&normalizeBridge(m)===normalizeBridge(h)){contributorCount()>0&&O();return}if(h===void 0&&normalizeBridge(m)===``){log$4.warn({documentName:t},`[persistence] Skipped phantom write for ${t}: empty Y.Doc with no reconciled base`);return}let g=resolveWriterFromOrigin(r,s);if(g&&g.id!==SERVICE_WRITER.id&&(hasContributor(g.id)||recordContributor(t,g.id,g.name,g.id)),h!==void 0){let r=classifyDuplication(m,h);if(r.kind===`block`){if(f.has(t)){log$4.warn({documentName:t},`[persistence] Tripwire breaker active — skipping duplicate store for ${t}`);return}let i=e.getXmlFragment(`default`).length;console.warn(JSON.stringify({event:`ok-persistence-duplication-blocked`,"doc.name":t,candidateBytes:m.length,baseBytes:h.length,fragmentChildren:i,copies:r.copies,reason:r.reason}));try{let r=safeContentPath(t,n);p(e,existsSync(r)?readFileSync(r,`utf-8`):h),f.delete(t)}catch(e){f.add(t),log$4.error({err:e,documentName:t},`[persistence] Tripwire reset failed for ${t}`)}return}}let _=safeContentPath(t,n);await tracedMkdir(dirname(_),{recursive:!0});let v;try{v=await realpath(_)}catch(e){let n=e.code;if(n===`ENOENT`){let e=!1;try{e=lstatSync(_).isSymbolicLink()}catch(e){e.code!==`ENOENT`&&log$4.warn({err:e,path:_},`[persistence] lstat failed during broken-symlink check`)}e&&console.warn(`[persistence] broken-symlink fallback`,{docName:t,reason:`broken-symlink`}),v=_}else if(n===`ELOOP`)throw console.error(`[persistence] Symlink cycle at ${_}`),Error(`Symlink cycle detected at ${_}`);else throw e}if(!isWithinContentDir(v,n)){let e=`symlink-escape: ${_} resolves to ${v} outside ${n}`;throw console.error(`[persistence] ${e}`,{docName:t,originalPath:_,canonical:v,contentDir:n}),Error(e)}let y=`${v}.tmp.${crypto.randomUUID()}`;try{await tracedWriteFile(y,m,`utf-8`),await tracedRename(y,v),registerWrite(v,contentHash(m)),incrementPersistenceDiskWrite(),l?.(t,i)}catch(e){try{tracedUnlinkSync(y)}catch{}throw log$4.error({err:e,documentName:t},`[persistence] Failed to save ${t}`),e}log$4.info({filePath:v,bytes:m.length},`[persistence] Wrote ${v} (${m.length} bytes)`),setReconciledBase(t,m),f.delete(t),o&&(o.updateDocumentFromMarkdown(t,m),o.saveToDisk().catch(e=>{log$4.warn({err:e,documentName:t},`[backlinks] Failed to persist cache for ${t}`)})),setActiveSpanAttributes({"persistence.bytes":m.length}),O()}).finally(()=>{j?.record((Date.now()-i)/1e3)})}function F({document:e,documentName:t,lastTransactionOrigin:n}){w.set(t,{branch:getActiveBranch(),document:e,lastTransactionOrigin:n})}async function I(e=`within-branch`){return C?(m=m===`discard-stale`||e===`discard-stale`?`discard-stale`:`within-branch`,C):(C=(async()=>{let t=e;for(;;){let e=[...w.entries()];if(w.clear(),t!==`discard-stale`){for(let[t,n]of e)if(n.branch===getActiveBranch())try{await P({document:n.document,documentName:t,lastTransactionOrigin:n.lastTransactionOrigin})}catch(e){log$4.error({err:e,documentName:t},`[persistence] Deferred store failed for ${t}`)}}let n=m;if(m=null,w.size===0&&n===null)break;t=n??`within-branch`}})().finally(()=>{C=null}),C)}let L={async onLoadDocument({document:t,documentName:r,context:i}){if(isSystemDoc(r))return;if(isConfigDoc(r)){loadConfigDoc(t,r,u);return}N();let a=Date.now();return withSpan(`persistence.onLoadDocument`,{attributes:{"doc.name":r}},async()=>{log$4.info({documentName:r,connections:t.getConnectionsCount?.()??`?`},`[persistence] onLoadDocument called for ${r} (connections: ${t.getConnectionsCount?.()??`?`})`);let i=safeContentPath(r,n);if(!existsSync(i))return;try{let e=realpathSync(i);if(!isWithinContentDir(e,n)){console.warn(`[persistence] symlink-escape on load: ${i} → ${e}, refusing`);return}}catch(e){if(e.code===`ELOOP`){console.warn(`[persistence] Symlink cycle on load: ${i}, refusing`);return}}let{frontmatter:a,body:o}=stripFrontmatter(readFileSync(i,`utf-8`));a&&(d.set(r,a),t.getMap(`metadata`).set(`frontmatter`,a));let s=t.getXmlFragment(`default`);log$4.info({documentName:r,fragmentLength:s.length},`[persistence] onLoadDocument ${r}: fragment.length=${s.length} before update`);let c=e?.resolveEmbed?{resolveEmbed:e.resolveEmbed,sourcePath:r}:void 0,l=mdManager.parseWithFallback(o,c);s.length===0?(updateYFragment(t,s,schema.nodeFromJSON(l),{mapping:new Map,isOMark:new Map}),log$4.info({filePath:i,children:s.length},`[persistence] Loaded ${i} into Y.Doc (${s.length} children)`),s.observeDeep(()=>{log$4.info({documentName:r,fragmentLength:s.length},`[persistence] MUTATION on ${r}: fragment.length=${s.length}`)})):log$4.info({documentName:r,children:s.length},`[persistence] Skipped load for ${r} — fragment already has ${s.length} children`),setReconciledBase(r,prependFrontmatter(a,mdManager.serialize(yXmlFragmentToProseMirrorRootNode(s,schema).toJSON())))}).finally(()=>{A?.record((Date.now()-a)/1e3)})},async onStoreDocument({document:e,documentName:t,lastTransactionOrigin:n,lastContext:r}){if(!isSystemDoc(t)){if(isConfigDoc(t)){await storeConfigDoc(e,t,n,u);return}if(isBatchInProgress()){F({document:e,documentName:t,lastTransactionOrigin:n});return}return P({document:e,documentName:t,lastTransactionOrigin:n})}}};async function R(){x&&await x}return{extension:L,flushDeferredStores:I,flushPendingGitCommit:k,waitForPendingCommits:R,configPersistenceCtx:u}}const CONFLICT_MARKER_RE=/^(<{7} |={7}$|>{7} |\|{7} )/m;function containsConflictMarkers(e){return CONFLICT_MARKER_RE.test(e)}function splitMarkdownBlocks(e){let t=e.replace(/\n+$/,``);if(!t)return[];let n=t.split(`
|
|
73
74
|
`),r=[],i=[],a=null;for(let e of n){let t=e.match(/^(`{3,}|~{3,})/);if(t){let e=t[1][0];a?e===a&&(a=null):a=e}a===null&&e.trim()===``&&i.length>0?(r.push(i.join(`
|
|
74
75
|
`).trim()),i=[]):i.push(e)}if(i.length>0){let e=i.join(`
|
|
75
76
|
`).trim();e&&r.push(e)}return r}function reconcile(e){if(isSystemDoc(e.docName)||isConfigDoc(e.docName))return{kind:`noop`};let{base:t,ours:n,theirs:r}=e;return containsConflictMarkers(r)?{kind:`refused`,reason:`conflict-markers`}:r===t?{kind:`noop`}:n===t?{kind:`clean`,newContent:r}:mergeBlocks(splitMarkdownBlocks(t),splitMarkdownBlocks(n),splitMarkdownBlocks(r))}function mergeBlocks(e,t,n){let r=computeEditOps(e,t),i=computeEditOps(e,n),a=[],o=[];for(let t=0;t<e.length;t++){let n=e[t],s=r.get(t),c=i.get(t),l=s?.insertsBefore??[],u=c?.insertsBefore??[];a.push(...l,...u);let d=s?.action??`keep`,f=c?.action??`keep`;if(d===`keep`&&f===`keep`)a.push(n);else if(d===`keep`&&f!==`keep`)f===`modify`&&c?.newContent!==void 0&&a.push(c.newContent);else if(d!==`keep`&&f===`keep`)d===`modify`&&s?.newContent!==void 0&&a.push(s.newContent);else{let e=d===`modify`?s?.newContent:null,r=f===`modify`?c?.newContent:null;e===r||o.push({blockIndex:t,base:n,ours:e??``,theirs:r??``}),e!=null&&a.push(e)}}let s=r.get(e.length),c=i.get(e.length);s?.insertsBefore&&a.push(...s.insertsBefore),c?.insertsBefore&&a.push(...c.insertsBefore);let l=a.length>0?`${a.join(`
|
|
@@ -125,7 +126,7 @@ What to log:
|
|
|
125
126
|
`);c=n.pop()??``;for(let e of n)if(e.trim())try{let t=JSON.parse(e);(t.type===`complete`||t.type===`error`)&&(s=!0)}catch{}}),l.stderr.on(`data`,e=>{log$2.debug({msg:e.toString(`utf-8`).trim()},`[local-op/auth/login] stderr`)}),l.on(`close`,e=>{clearTimeout(u),t.off(`close`,d),o||(o=!0,t.writableEnded||(e===0&&!s?t.write(`${JSON.stringify({type:`complete`,host:n,login:``})}\n`):e!==0&&t.write(`${JSON.stringify({type:`error`,message:`auth login exited with code ${e}`})}\n`)),t.end()),T.release(qe)}),l.on(`error`,e=>{clearTimeout(u),t.off(`close`,d),o||(o=!0,t.writableEnded||(t.write(`${JSON.stringify({type:`error`,message:e.message})}\n`),t.end())),T.release(qe)})}async function $e(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let n=`github.com`;try{let t=(await readBody(e)).toString().trim();if(t.length>0){let e=JSON.parse(t);typeof e.host==`string`&&e.host&&(n=e.host)}}catch{json(t,400,{ok:!1,error:`Invalid JSON body`});return}if(!T.tryAcquire(Je)){json(t,429,{ok:!1,error:`An auth status operation is already in progress`});return}try{let[e,...r]=y,i=[...r,`auth`,`status`,`--json`,`--host`,n],a=(await new Promise((t,n)=>{let r=spawn(e,i,{stdio:[`ignore`,`pipe`,`pipe`],env:{...process.env}}),a=setTimeout(()=>{r.kill(`SIGTERM`)},3e4),o=[];r.stdout.on(`data`,e=>o.push(e)),r.on(`close`,()=>{clearTimeout(a),t(Buffer.concat(o).toString(`utf-8`))}),r.on(`error`,e=>{clearTimeout(a),n(e)})})).split(`
|
|
126
127
|
`).map(e=>e.trim()).filter(Boolean),o=null;for(let e=a.length-1;e>=0;e--)try{o=JSON.parse(a[e]);break}catch{}o===null?json(t,200,{authenticated:!1}):json(t,200,o)}catch(e){json(t,500,{ok:!1,error:e instanceof Error?e.message:`auth status failed`})}finally{T.release(Je)}}async function et(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let n=`github.com`;try{let t=(await readBody(e)).toString().trim();if(t.length>0){let e=JSON.parse(t);typeof e.host==`string`&&e.host&&(n=e.host)}}catch{json(t,400,{ok:!1,error:`Invalid JSON body`});return}if(!T.tryAcquire(Ye)){json(t,429,{ok:!1,error:`An auth repos operation is already in progress`});return}t.writeHead(200,{"Content-Type":`application/x-ndjson`,"Transfer-Encoding":`chunked`,"X-Content-Type-Options":`nosniff`,"Cache-Control":`no-cache`});let[r,...i]=y,a=[...i,`auth`,`repos`,`--json`,`--host`,n],o=!1,s=spawn(r,a,{stdio:[`ignore`,`pipe`,`pipe`],env:{...process.env}}),c=setTimeout(()=>{s.kill(`SIGTERM`)},He);s.stdout.on(`data`,e=>{t.writableEnded||t.write(e)}),s.stderr.on(`data`,e=>{log$2.debug({msg:e.toString(`utf-8`).trim()},`[local-op/auth/repos] stderr`)}),s.on(`close`,e=>{clearTimeout(c),o||(o=!0,e!==0&&!t.writableEnded&&t.write(`${JSON.stringify({type:`error`,message:`auth repos exited with code ${e}`})}\n`),t.end()),T.release(Ye)}),s.on(`error`,e=>{clearTimeout(c),o||(o=!0,t.writableEnded||(t.write(`${JSON.stringify({type:`error`,message:e.message})}\n`),t.end())),T.release(Ye)})}async function tt(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let n=`github.com`;try{let t=await readBody(e),r=JSON.parse(t.toString());typeof r.host==`string`&&r.host&&(n=r.host)}catch{json(t,400,{ok:!1,error:`Invalid JSON body`});return}if(!T.tryAcquire(Xe)){json(t,429,{ok:!1,error:`An auth signout operation is already in progress`});return}try{let[e,...r]=y,i=[...r,`auth`,`signout`,`--host`,n];await new Promise((t,n)=>{let r=spawn(e,i,{stdio:`ignore`,env:{...process.env}}),a=setTimeout(()=>{r.kill(`SIGTERM`)},3e4);r.on(`close`,()=>{clearTimeout(a),t()}),r.on(`error`,e=>{clearTimeout(a),n(e)})}),json(t,200,{ok:!0})}catch(e){json(t,500,{ok:!1,error:e instanceof Error?e.message:`auth signout failed`})}finally{T.release(Xe)}}async function nt(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let n=`github.com`,r;try{let i=await readBody(e),a=JSON.parse(i.toString());if(typeof a.pat!=`string`||!a.pat){json(t,400,{ok:!1,error:`Missing or invalid pat`});return}r=a.pat,typeof a.host==`string`&&a.host&&(n=a.host)}catch{json(t,400,{ok:!1,error:`Invalid JSON body`});return}if(!T.tryAcquire(Ze)){json(t,429,{ok:!1,error:`An auth pat operation is already in progress`});return}try{let[e,...i]=y,a=[...i,`auth`,`pat`,`--json`,`--host`,n],o=(await new Promise((t,n)=>{let i=spawn(e,a,{stdio:[`pipe`,`pipe`,`pipe`],env:{...process.env}}),o=setTimeout(()=>{i.kill(`SIGTERM`)},3e4);i.stdin.write(`${r}\n`),i.stdin.end();let s=[];i.stdout.on(`data`,e=>s.push(e)),i.on(`close`,e=>{clearTimeout(o),e===0?t(Buffer.concat(s).toString(`utf-8`)):n(Error(`auth pat exited with code ${e}`))}),i.on(`error`,e=>{clearTimeout(o),n(e)})})).split(`
|
|
127
128
|
`).map(e=>e.trim()).filter(Boolean),s=null;for(let e=o.length-1;e>=0;e--)try{s=JSON.parse(o[e]);break}catch{}s===null?json(t,200,{ok:!0}):json(t,200,s)}catch(e){json(t,500,{ok:!1,error:e instanceof Error?e.message:`auth pat failed`})}finally{T.release(Ze)}}async function rt(e,t){if(checkLocalOpSecurity(e,t,json)){if(e.method!==`GET`){json(t,405,{ok:!1,error:`Method not allowed`});return}if(!b){json(t,400,{ok:!1,error:`No project directory configured`});return}try{json(t,200,{ok:!0,identity:await resolveGitIdentity(b)})}catch(e){json(t,500,{ok:!1,error:e instanceof Error?e.message:`identity resolution failed`})}}}let it=`/api/local-op/auth/set-identity`;async function at(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let n,r;try{let i=await readBody(e),a=JSON.parse(i.toString());if(typeof a.name!=`string`||!a.name.trim()){json(t,400,{ok:!1,error:`Missing or invalid name`});return}if(typeof a.email!=`string`||!a.email.trim()){json(t,400,{ok:!1,error:`Missing or invalid email`});return}n=a.name.trim(),r=a.email.trim()}catch{json(t,400,{ok:!1,error:`Invalid JSON body`});return}if(!b){json(t,400,{ok:!1,error:`No project directory configured`});return}if(!T.tryAcquire(it)){json(t,429,{ok:!1,error:`A set-identity operation is already in progress`});return}try{writeGitIdentity(b,n,r),v?.()?.refreshIdentity().catch(()=>{}),json(t,200,{ok:!0})}catch(e){json(t,500,{ok:!1,error:e instanceof Error?e.message:`set-identity failed`})}finally{T.release(it)}}async function ot(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`GET`){json(t,405,{ok:!1,error:`Method not allowed`});return}let n=v?.();if(!n){json(t,200,{state:`dormant`,lastSyncUtc:null,lastFetchUtc:null,lastPushedSha:null,ahead:0,behind:0,consecutiveFailures:0,conflictCount:0,hasRemote:!1,syncEnabled:!1,identityUnresolved:!1});return}json(t,200,n.getStatus())}async function st(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let n=v?.();if(!n){json(t,503,{ok:!1,error:`Sync engine not active`});return}let r=`sync`;try{let t=await readBody(e);if(t.length>0){let e=JSON.parse(t.toString());(e.op===`push`||e.op===`pull`||e.op===`sync`)&&(r=e.op)}}catch{}json(t,202,{ok:!0,op:r}),n.trigger(r)}async function ct(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let n=v?.();if(!n){json(t,503,{ok:!1,error:`Sync engine not active`});return}let r;try{let n=await readBody(e),i=JSON.parse(n.toString());if(typeof i.enabled!=`boolean`){json(t,400,{ok:!1,error:`enabled must be a boolean`});return}r=i.enabled}catch{json(t,400,{ok:!1,error:`Invalid JSON body`});return}await n.setEnabled(r),json(t,200,{ok:!0,status:n.getStatus()})}async function lt(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`GET`){json(t,405,{ok:!1,error:`Method not allowed`});return}let n=v?.();json(t,200,{conflicts:n?n.getConflicts():[]})}async function ut(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let n=v?.();if(!n){json(t,503,{ok:!1,error:`Sync engine not active`});return}let r;try{let t=await readBody(e);r=JSON.parse(t.toString())}catch{json(t,400,{ok:!1,error:`Invalid JSON body`});return}let{file:i,strategy:a,content:o}=r;if(!i||typeof i!=`string`){json(t,400,{ok:!1,error:`Missing required field: file`});return}if(a!==`mine`&&a!==`theirs`&&a!==`content`){json(t,400,{ok:!1,error:`Invalid strategy: must be 'mine', 'theirs', or 'content'`});return}try{await n.resolveConflict(i,a,o),json(t,200,{ok:!0})}catch(e){json(t,500,{ok:!1,error:e instanceof Error?e.message:String(e)})}}async function dt(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`GET`){json(t,405,{ok:!1,error:`Method not allowed`});return}if(!b){json(t,503,{ok:!1,error:`Project repo not configured`});return}let n=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`).searchParams.get(`file`);if(!n){json(t,400,{ok:!1,error:`Missing required query param: file`});return}if(n.includes(`..`)||n.startsWith(`/`)){json(t,400,{ok:!1,error:`Invalid file path`});return}let r=esm_default({baseDir:b,timeout:{block:15e3}});async function i(e){try{return await r.raw([`show`,`:${e}:${n}`])}catch{return``}}try{let[e,r,a]=await Promise.all([i(1),i(2),i(3)]);json(t,200,{ok:!0,file:n,base:e,ours:r,theirs:a})}catch(e){json(t,500,{ok:!1,error:e instanceof Error?e.message:String(e)})}}async function ft(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`GET`){json(t,405,{ok:!1,error:`Method not allowed`});return}let n=new URL(e.url??`/`,`http://localhost`).searchParams.get(`rootDir`)??void 0;try{json(t,200,{ok:!0,plan:await planSeed({projectDir:r,rootDir:n})})}catch(e){if(e instanceof SeedPrerequisiteError){json(t,200,{ok:!1,error:{kind:`prerequisite-missing`,message:e.message}});return}if(e instanceof SeedRootDirError){json(t,200,{ok:!1,error:{kind:`invalid-root`,message:e.message}});return}json(t,500,{ok:!1,error:{kind:`internal`,message:e instanceof Error?e.message:String(e)}})}}async function pt(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let n;try{let r=await readBody(e),i=JSON.parse(r.toString());if(!i.plan||typeof i.plan!=`object`){json(t,400,{ok:!1,error:`Missing or invalid plan`});return}n=i.plan}catch{json(t,400,{ok:!1,error:`Invalid JSON body`});return}try{json(t,200,{ok:!0,result:await applySeed(n,{projectDir:r})})}catch(e){json(t,500,{ok:!1,error:{kind:`internal`,message:e instanceof Error?e.message:String(e)}})}}async function mt(e,t){if(checkLocalOpSecurity(e,t,json))return handleInstalledAgents(e,t,E.probeAll)}async function ht(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let n=v?.();if(!n){json(t,503,{ok:!1,error:`Sync engine not active`});return}try{await n.abortMerge(),json(t,200,{ok:!0})}catch(e){json(t,500,{ok:!1,error:e instanceof Error?e.message:String(e)})}}let gt={"/api/document":re,"/api/documents":ie,"/api/backlinks":ae,"/api/backlink-counts":oe,"/api/forward-links":se,"/api/link-graph":ce,"/api/dead-links":de,"/api/orphans":le,"/api/hubs":ue,"/api/pages":Le,"/api/suggest-links":Re,"/api/page-headings":Ne,"/api/create-page":Me,"/api/rename":Pe,"/api/rename-path":Fe,"/api/delete-path":Ie,"/api/upload":ze,"/api/agent-write":Q,"/api/agent-write-md":ne,"/api/agent-patch":fe,"/api/agent-undo":pe,"/api/agent-activity":me,"/api/agent-burst-diff":he,"/api/save-version":ve,"/api/history":ye,"/api/diff":xe,"/api/rollback":Se,"/api/metrics/reconciliation":Ce,"/api/metrics/parse-health":we,"/api/metrics/agent-presence":De,"/api/server-info":Te,"/api/principal":Ee,"/api/rescue":Ae,"/api/workspace":Oe,"/api/sync/status":ot,"/api/sync/trigger":st,"/api/sync/set-enabled":ct,"/api/sync/conflicts":lt,"/api/sync/conflict-content":dt,"/api/sync/resolve-conflict":ut,"/api/sync/abort-merge":ht,"/api/local-op/clone":We,"/api/local-op/open":Ke,"/api/local-op/auth/login":Qe,"/api/local-op/auth/status":$e,"/api/local-op/auth/repos":et,"/api/local-op/auth/signout":tt,"/api/local-op/auth/pat":nt,"/api/local-op/auth/identity":rt,"/api/local-op/auth/set-identity":at,"/api/installed-agents":mt,"/api/seed/plan":ft,"/api/seed/apply":pt};s&&(gt[`/api/test-reset`]=ge,gt[`/api/test-rescan-backlinks`]=_e);let _t=new Set([`/api/upload`,`/api/create-page`,`/api/rename`,`/api/rename-path`,`/api/delete-path`,`/api/agent-write`,`/api/agent-write-md`,`/api/agent-patch`,`/api/save-version`,`/api/rollback`,`/api/sync/trigger`,`/api/sync/set-enabled`,`/api/sync/resolve-conflict`,`/api/sync/abort-merge`,`/api/test-reset`,`/api/test-rescan-backlinks`]),vt=[`/api/local-op/`];return{priority:100,async onRequest({request:e,response:t}){let n=e.url?.split(`?`)[0];if(!n)return;if(n.startsWith(`/api/`)){let n=e.headers.origin;if(n!==void 0&&!isAllowedApiOrigin(n)){typeof t.setHeader==`function`&&t.setHeader(`Content-Type`,`application/json`),t.writeHead(403),t.end(JSON.stringify({ok:!1,error:`origin-not-allowed`}));return}if(typeof t.setHeader==`function`&&(n!==void 0&&(t.setHeader(`Access-Control-Allow-Origin`,n),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(_t.has(n)||vt.some(e=>n.startsWith(e))){let n=e.socket?.remoteAddress;if(n!==void 0&&!isLoopbackAddress(n)){json(t,403,{ok:!1,error:`loopback-required`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){json(t,403,{ok:!1,error:`host-header-not-allowed`});return}}if(!n.startsWith(`/api/`))return;let r=propagation.extract(context.active(),e.headers),i=e.method??`GET`,a=n;n.startsWith(`/api/rescue/`)?a=`/api/rescue/:docName`:n.startsWith(`/api/history/`)&&(a=`/api/history/:sha`);let o=getTracer(),s=Date.now();await context.with(r,()=>o.startActiveSpan(`HTTP ${i} ${a}`,{kind:SpanKind.SERVER,attributes:{[ATTR_HTTP_REQUEST_METHOD]:i,[ATTR_HTTP_ROUTE]:a,[ATTR_URL_PATH]:n,[ATTR_URL_SCHEME]:`http`,[ATTR_USER_AGENT_ORIGINAL]:e.headers[`user-agent`]??``}},async r=>{try{let i=gt[n];if(i)await i(e,t);else if(n.startsWith(`/api/rescue/`)){let r=decodeURIComponent(n.slice(12));r&&await je(e,t,r)}else if(n.startsWith(`/api/history/`)){let r=decodeURIComponent(n.slice(13));r&&await be(e,t,r)}let a=t.statusCode;r.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE,a),a>=500&&r.setStatus({code:SpanStatusCode.ERROR,message:`status ${a}`})}catch(e){throw r.recordException(e),r.setStatus({code:SpanStatusCode.ERROR,message:e instanceof Error?e.message:String(e)}),e}finally{r.end();let e=(Date.now()-s)/1e3;httpDurationHist().record(e,{[ATTR_HTTP_REQUEST_METHOD]:i,[ATTR_HTTP_ROUTE]:a,[ATTR_HTTP_RESPONSE_STATUS_CODE]:t.statusCode})}}))}}}Object.assign(mimes,{m4v:`video/mp4`,mkv:`video/x-matroska`,flac:`audio/flac`});function createAssetServeMiddleware(e){let{contentFilter:t,contentSirv:n,inlineExtensions:r,assetExtensions:i,blocklistExtensions:a}=e;return(e,o,s)=>{let c;try{c=decodeURIComponent(e.url?.split(`?`)[0]?.replace(/^\//,``)??``)}catch{return s()}if(!c||t.isExcluded(c))return s();o.setHeader(`X-Content-Type-Options`,`nosniff`);let l=extname(c).slice(1).toLowerCase();l===`md`||l===`mdx`||(r.has(l)?o.setHeader(`Content-Disposition`,`inline`):o.setHeader(`Content-Disposition`,`attachment`)),n(e,o,()=>{if(!o.headersSent){if(i.has(l)||a.has(l)){o.statusCode=404,o.end();return}s()}})}}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,n=new Set;function r(i){let a;try{a=readdirSync(i,{withFileTypes:!0})}catch(t){let n=errnoCode(t);n!==`ENOENT`&&e.onSkip?.(`read-failed`,n,i);return}for(let o of a){let a=join(i,o.name),s=relative(t,a);if(s.startsWith(`..`)||e.contentFilter?.isDirExcluded(s)&&o.isDirectory())continue;let c;try{c=lstatSync(a)}catch(t){let n=errnoCode(t);n!==`ENOENT`&&e.onSkip?.(`lstat-failed`,n,a);continue}if(c.isSymbolicLink()){let i;try{i=realpathSync(a)}catch(t){let n=errnoCode(t);n!==`ENOENT`&&e.onSkip?.(`realpath-failed`,n,a);continue}if(!isWithinDir(i,t)){e.onSkip?.(`symlink-escape`,void 0,a);continue}let o;try{o=statSync(i)}catch(t){let n=errnoCode(t);n!==`ENOENT`&&e.onSkip?.(`symlink-stat-failed`,n,i);continue}if(n.has(o.ino))continue;n.add(o.ino),o.isDirectory()?r(i):o.isFile()&&isSupportedAssetFile(a,ASSET_EXTENSIONS)&&!e.contentFilter?.isExcluded(s)&&e.basenameIndex.add(s);continue}if(c.isDirectory()){if(n.has(c.ino))continue;n.add(c.ino),r(a);continue}c.isFile()&&isSupportedAssetFile(a,ASSET_EXTENSIONS)&&!e.contentFilter?.isExcluded(s)&&e.basenameIndex.add(s)}}r(t)}const HocuspocusAuthTokenSchema=object({principalId:string().optional(),tabSessionId:string().optional(),expectedServerInstanceId:string().optional(),expectedBranch:string().optional()}).loose();var HocuspocusAuthRejection=class extends Error{reason;constructor(e,t){super(t),this.name=`HocuspocusAuthRejection`,this.reason=e}};function parseHocuspocusAuthToken(e){if(typeof e!=`string`||e.length===0)return;let t;try{t=JSON.parse(e)}catch{return}let n=HocuspocusAuthTokenSchema.safeParse(t);return n.success?n.data:void 0}const DEFAULT_WARN_BEFORE_MS=300*1e3;function attachIdleShutdown(e){let t=e.scheduler??defaultScheduler,n=e.warnBeforeMs??DEFAULT_WARN_BEFORE_MS,r=0,i=null,a=null,o=!1,s=!1;function c(){i!==null&&(t.clearTimeout(i),i=null),a!==null&&(t.clearTimeout(a),a=null)}function l(){c(),!(s||o)&&r===0&&(n>0&&n<e.thresholdMs&&(a=t.setTimeout(()=>{a=null,r===0&&!o&&e.log?.warn({msUntilShutdown:n,webSocketClientCount:0},`idle shutdown pending: no WebSocket clients`)},e.thresholdMs-n)),i=t.setTimeout(()=>{if(i=null,!(s||o)&&r===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 u=(e,t)=>{e.url?.startsWith(`/collab`)&&(r++,c(),t.once(`close`,()=>{r--,r<0&&(r=0),r===0&&l()}))};return e.httpServer.on(`upgrade`,u),l(),{detach:()=>{s||(s=!0,e.httpServer.off(`upgrade`,u),c())}}}async function startConfigFileWatcher(e,t){let n=getLogger(`config-file-watcher`),{watch:r}=await import(`./chokidar-DjlCoHHX.mjs`),i=dirname(e);try{tracedMkdirSync(i,{recursive:!0})}catch(e){e.code!==`EEXIST`&&n.warn({err:e,watchDir:i},`failed to create watch directory; watcher may be inert`)}let a=r(i,{ignoreInitial:!0,depth:0,usePolling:!0,interval:200,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50},ignored:t=>t!==i&&t!==e});await new Promise(e=>{a.once(`ready`,()=>e())});let o=r=>{if(r!==e)return;let i;try{i=readFileSync(r,`utf-8`)}catch(e){if(e.code===`ENOENT`){n.debug({path:r},`config file disappeared between event and read; dropping`);return}n.warn({err:e,path:r},`config file read failed; dropping event`);return}try{t(i)}catch(e){n.warn({err:e,path:r},`config file change handler threw`)}};a.on(`add`,o),a.on(`change`,o),a.on(`unlink`,t=>{t===e&&n.debug({path:t},`config file unlinked; Y.Text retained at current state`)}),a.on(`error`,t=>{n.warn({err:t,watchDir:i,absPath:e},`[config-file-watcher] chokidar error while watching ${e}`)});let s=!1;return async()=>{s||(s=!0,await a.close())}}const BUILTIN_SKIP_DIRS=new Set([`node_modules`,`.venv`,`venv`,`env`,`__pycache__`,`vendor`,`dist`,`build`,`out`,`output`,`.next`,`.nuxt`,`.svelte-kit`,`.astro`,`.turbo`,`.cache`,`.parcel-cache`,`coverage`,`.git`]);function createContentFilter(e){let{projectDir:t,contentDir:n,includePatterns:r,excludePatterns:i}=e,a=(0,import_picomatch.default)(r,{dot:!0}),o=(0,import_ignore.default)();o.add(`.git`);let s=join(t,`.gitignore`),c=[];if(existsSync(s))try{let e=parseGitignorePatterns(readFileSync(s,`utf-8`));c.push(...e),o.add(e)}catch(e){console.warn(`[content-filter] Failed to read .gitignore at ${s}:`,e)}let l=relative(t,n),u=l.startsWith(`..`);if(i.length>0&&(l?o.add(i.map(e=>`${l}/${e}`)):o.add(i)),l){let e=join(n,`.gitignore`);if(existsSync(e))try{let t=parseGitignorePatterns(readFileSync(e,`utf-8`)).map(e=>e.startsWith(`!`)?`!${l}/${e.slice(1)}`:`${l}/${e}`);o.add(t)}catch(t){console.warn(`[content-filter] Failed to read .gitignore at ${e}:`,t)}}loadNestedGitignores(n,t,o);let d=[...c,...i].filter(e=>e.length>0&&!e.startsWith(`!`)&&!e.startsWith(`#`)),f=new Map;function p(e){if(u)return!1;let t=l?`${l}/${e}`:e;return o.ignores(t)}return populateDirCount(n,``,a,p,f),{isExcluded(e){let t=stripDocExtension(e);if(isSystemDoc(t)||isConfigDoc(t)||!u&&p(e))return!0;if(a(e))return!1;let n=extname(e).slice(1).toLowerCase();if(ASSET_EXTENSIONS.has(n)){let t=dirname(e),n=t===`.`?``:t;if((f.get(n)??0)>0)return!1}return!0},isDirExcluded(e){let t=e.split(`/`)[0];if(BUILTIN_SKIP_DIRS.has(t))return!0;if(u)return!1;let n=l?`${l}/${e}`:e;return o.ignores(n)||o.ignores(`${n}/`)},getWatcherIgnoreGlobs(){return d},incrementMdDir(e){let t=e===`.`?``:e;f.set(t,(f.get(t)??0)+1)},decrementMdDir(e){let t=e===`.`?``:e,n=f.get(t)??0;n<=1?f.delete(t):f.set(t,n-1)},rebuildDirCount(){f.clear(),populateDirCount(n,``,a,p,f)}}}function populateDirCount(e,t,n,r,i){let a;try{a=readdirSync(e,{withFileTypes:!0})}catch{return}for(let o of a){let a=t?`${t}/${o.name}`:o.name;if(o.isDirectory()){if(BUILTIN_SKIP_DIRS.has(o.name)||r(a)||r(`${a}/`))continue;populateDirCount(join(e,o.name),a,n,r,i)}else if(o.isFile()&&isSupportedDocFile(o.name)&&n(a)&&!r(a)){let e=t===``?``:t;i.set(e,(i.get(e)??0)+1)}}}function parseGitignorePatterns(e){return e.split(`
|
|
128
|
-
`).map(e=>e.trim()).filter(e=>e.length>0&&!e.startsWith(`#`))}function loadNestedGitignores(e,t,n){let r;try{r=readdirSync(e,{withFileTypes:!0})}catch(t){console.warn(`[content-filter] Failed to read directory ${e}:`,t);return}for(let i of r){if(!i.isDirectory()||BUILTIN_SKIP_DIRS.has(i.name))continue;let r=join(e,i.name),a=relative(t,r);if(a.startsWith(`..`)||n.ignores(a)||n.ignores(`${a}/`))continue;let o=join(r,`.gitignore`);if(existsSync(o))try{let e=parseGitignorePatterns(readFileSync(o,`utf-8`)).map(e=>e.startsWith(`!`)?`!${a}/${e.slice(1)}`:`${a}/${e}`);n.add(e)}catch(e){console.warn(`[content-filter] Failed to read nested .gitignore at ${o}:`,e)}loadNestedGitignores(r,t,n)}}const
|
|
129
|
+
`).map(e=>e.trim()).filter(e=>e.length>0&&!e.startsWith(`#`))}function loadNestedGitignores(e,t,n){let r;try{r=readdirSync(e,{withFileTypes:!0})}catch(t){console.warn(`[content-filter] Failed to read directory ${e}:`,t);return}for(let i of r){if(!i.isDirectory()||BUILTIN_SKIP_DIRS.has(i.name))continue;let r=join(e,i.name),a=relative(t,r);if(a.startsWith(`..`)||n.ignores(a)||n.ignores(`${a}/`))continue;let o=join(r,`.gitignore`);if(existsSync(o))try{let e=parseGitignorePatterns(readFileSync(o,`utf-8`)).map(e=>e.startsWith(`!`)?`!${a}/${e.slice(1)}`:`${a}/${e}`);n.add(e)}catch(e){console.warn(`[content-filter] Failed to read nested .gitignore at ${o}:`,e)}loadNestedGitignores(r,t,n)}}const QUIET_WINDOW_MS=100,BATCH_TIMEOUT_MS=3e4,WATCHED_FILES=new Set([`HEAD`,`MERGE_HEAD`,`ORIG_HEAD`,`index.lock`]);function resolveGitDir(e){let t=resolve(e,`.git`);try{let n=statSync(t);if(n.isDirectory())return t;if(n.isFile()){let n=readFileSync(t,`utf-8`).trim().match(/^gitdir:\s*(.+)$/);if(n)return resolve(e,n[1])}}catch{}return null}function readHeadSha(e){try{let t=readFileSync(resolve(e,`HEAD`),`utf-8`).trim();if(t.startsWith(`ref: `)){let n=resolve(e,t.slice(5));try{return readFileSync(n,`utf-8`).trim()}catch{try{let n=readFileSync(resolve(e,`packed-refs`),`utf-8`),r=t.slice(5),i=n.split(`
|
|
129
130
|
`).find(e=>e.endsWith(` ${r}`));if(i)return i.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,n){let r=resolveGitDir(e);if(!r)return{unsubscribe:async()=>{},getLastKnownBranch:()=>null};let i=r,a=!1,o=null,s=null,c=null,l=null;async function u(e){if(f&&await f,!a)return;o&&=(clearTimeout(o),null),s&&=(clearTimeout(s),null);let t=readHeadSha(i),r=c!==t,u=readBranchFromHead(i),d;d=u?.startsWith(`detached-`)?`detached-head`:l===u?`within-branch`:`cross-branch`;let p=l;try{await n({headMoved:r,oldHead:c,newHead:t,timeout:e,batchKind:d,oldBranch:p,newBranch:u})}catch(e){console.error(`[head-watcher] onBatchEnd callback failed:`,e)}finally{a=!1,c=t,l=u}}function d(){o&&clearTimeout(o),o=setTimeout(()=>{o=null,u(!1)},QUIET_WINDOW_MS)}let f=null;async function p(e){if(!a){a=!0,c=readHeadSha(i);let n=(async()=>{try{await t({trigger:e})}catch(e){console.error(`[head-watcher] onBatchBegin callback failed:`,e)}})();f=n,await n,f=null,s=setTimeout(()=>{s=null,u(!0)},BATCH_TIMEOUT_MS)}d()}let m,h;try{h=await import(`@parcel/watcher`)}catch(e){throw Error(`@parcel/watcher unavailable for HEAD watching: ${e instanceof Error?e.message:e}`)}try{let e=await h.subscribe(i,(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)){p(t);break}}});m=()=>e.unsubscribe()}catch(e){throw Error(`@parcel/watcher subscribe failed for HEAD watching: ${e instanceof Error?e.message:e}`)}return c=readHeadSha(i),l=readBranchFromHead(i),console.log(`[head-watcher] Watching ${i} for HEAD changes`),{unsubscribe:async()=>{a&&await u(!1),o&&clearTimeout(o),s&&clearTimeout(s),await m()},getLastKnownBranch:()=>l}}function isLocalOriginLike(e){return typeof e!=`object`||!e?!1:e.source===`local`}function serializeLiveDocument(e){let t=e.getXmlFragment(`default`),n=mdManager.serialize(yXmlFragmentToProseMirrorRootNode(t,schema).toJSON()),r=e.getMap(`metadata`).get(`frontmatter`);return prependFrontmatter(typeof r==`string`?r:``,n)}function createLiveDerivedIndexExtension(e){let{backlinkIndex:t,signalChannel:n,debounceMs:r=100}=e,i=new Map;function a(e){let t=i.get(e);t&&(clearTimeout(t),i.delete(e))}function o(e,o){a(e),i.set(e,setTimeout(()=>{i.delete(e);try{t.updateDocumentFromMarkdown(e,serializeLiveDocument(o)),n?.(`backlinks`),n?.(`graph`)}catch(t){console.error(`[live-derived-index] Failed to update backlinks for ${e}:`,t)}},r))}return{async onChange({documentName:e,document:t,transactionOrigin:n}){isSystemDoc(e)||isConfigDoc(e)||isLocalOriginLike(n)&&n.context?.origin===`file-watcher`||o(e,t)},async beforeUnloadDocument({documentName:e}){a(e)},async onDestroy(){for(let e of i.values())clearTimeout(e);i.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=resolve(e,OK_DIR),n=resolve(t,PRINCIPAL_FILE),{name:r,email:i}=await readGitConfig(e);if(existsSync(n)){let e;try{e=JSON.parse(readFileSync(n,`utf-8`))}catch{e={}}let t=typeof e.id==`string`&&e.id.startsWith(`principal-`)?e.id:`principal-${randomUUID()}`,a=typeof e.created_at==`string`?e.created_at:new Date().toISOString(),o=t.slice(10,18),s={id:t,display_name:r?sanitizeGitIdentity(r):typeof e.display_name==`string`?e.display_name:`Local User`,display_email:i?sanitizeGitIdentity(i):typeof e.display_email==`string`?e.display_email:`principal-${o}@openknowledge.local`,source:r||i?`git-config`:`synthesized`,created_at:a};return writeFileSync(n,JSON.stringify(s,null,2),`utf-8`),s}mkdirSync(t,{recursive:!0});let a=`principal-${randomUUID()}`,o=a.slice(10,18),s={id:a,display_name:r?sanitizeGitIdentity(r):`Local User`,display_email:i?sanitizeGitIdentity(i):`principal-${o}@openknowledge.local`,source:r||i?`git-config`:`synthesized`,created_at:new Date().toISOString()};return writeFileSync(n,JSON.stringify(s,null,2),`utf-8`),s}const OBSERVER_SYNC_ORIGIN={source:`local`,skipStoreHooks:!0,context:{origin:`observer-sync`}},isPairedWriteOrigin=e=>typeof e!=`object`||!e?!1:e.context?.paired===!0;function shouldRethrowBridgeMergeLoss(e=process.env){return e.NODE_ENV===`test`||e.OK_RETHROW_BRIDGE_LOSS===`1`}function setupServerObservers(e){let{doc:t,xmlFragment:n,ytext:r,mdManager:i,schema:a}=e,o=(t,n)=>{let r=process.env.OK_TELEMETRY_VERBOSE===`1`;console.warn(JSON.stringify({...t.toLog({verbose:r}),docName:e.docName??null,timestamp:new Date().toISOString()})),incrementBridgeMergeContentLoss();let i=e.shadow?.();if(!i||!e.docName)return;let a=e.getBranch?.()??`main`,o=e.contentRoot??``;queueMicrotask(()=>{saveInMemoryCheckpoint(i,o,{kind:`bridge-merge-loss`,docName:e.docName,contents:n,label:`Before concurrent merge @ ${new Date().toISOString()}`,branch:a,metadata:{lostSubstrings:t.info.lostSubstrings}}).then(t=>{incrementBridgeMergeCheckpointCreated(),console.warn(JSON.stringify({event:`bridge-merge-checkpoint-created`,docName:e.docName,sha:t,kind:`bridge-merge-loss`,timestamp:new Date().toISOString()}))}).catch(e=>{let t=e instanceof Error?e:Error(String(e));console.warn(`[Server Observer A] Silent checkpoint write failed:`,{name:t.name,message:t.message,stack:t.stack?.split(`
|
|
130
131
|
`).slice(0,4).join(`
|
|
131
132
|
`)})})})},s=``,c=!1,l=!1;try{let e=yXmlFragmentToProseMirrorRootNode(n,a).toJSON(),r=i.serialize(e);s=prependFrontmatter(getFrontmatter(t),r)}catch(e){incrementServerObserverError(`a`),console.warn(`[Server Observer A] Baseline init failed — starting from empty snapshot:`,e instanceof Error?e.message:String(e)),s=``}let u=()=>{try{let e=yXmlFragmentToProseMirrorRootNode(n,a).toJSON(),c=i.serialize(e),l=prependFrontmatter(getFrontmatter(t),c);if(s===l)return;let u=r.toString();if(normalizeBridge(u)===normalizeBridge(l)){s=l;return}let d=s;t.transact(()=>{if(u===s)applyIncrementalDiff(r,u,l);else try{applyFastDiff(r,u,mergeThreeWay(s,l,u))}catch(e){if(!(e instanceof BridgeMergeContentLossError)||(o(e,d),shouldRethrowBridgeMergeLoss()))throw e;applyFastDiff(r,u,e.info.result)}},OBSERVER_SYNC_ORIGIN),incrementServerObserverFire(`a`),s=r.toString()}catch(e){incrementServerObserverError(`a`),console.error(`[Server Observer A] Failed to sync tree→text:`,e);try{s=r.toString()}catch(e){console.warn(`[Server Observer A] Baseline recovery also failed:`,e)}}},d=(e,r)=>{if(r.origin!==OBSERVER_SYNC_ORIGIN){if(isPairedWriteOrigin(r.origin)){try{let e=yXmlFragmentToProseMirrorRootNode(n,a).toJSON(),r=i.serialize(e);s=prependFrontmatter(getFrontmatter(t),r)}catch(e){incrementServerObserverError(`a`),console.warn(`[Server Observer A] Paired-write baseline refresh failed — falling through to settlement:`,e instanceof Error?e.message:String(e)),c=!0}return}c=!0}};if(n.length>0&&r.length===0)try{let e=yXmlFragmentToProseMirrorRootNode(n,a).toJSON(),o=i.serialize(e),c=prependFrontmatter(getFrontmatter(t),o);t.transact(()=>{r.insert(0,c)},OBSERVER_SYNC_ORIGIN),s=c}catch(e){incrementServerObserverError(`a`),console.error(`[Server Observer A] Failed initial sync:`,e),s=``}let f=()=>{try{let a=r.toString(),{frontmatter:o,body:c}=stripFrontmatter(a);if(normalizeBridge(s)===normalizeBridge(a)){let e=t.getMap(`metadata`);(e.get(`frontmatter`)??``)!==o&&t.transact(()=>{e.set(`frontmatter`,o)},OBSERVER_SYNC_ORIGIN);return}let l=e.resolveEmbed&&e.docName?{resolveEmbed:e.resolveEmbed,sourcePath:e.docName}:void 0,u=i.parseWithFallback(c,l),d=e.schema.nodeFromJSON(u);t.transact(()=>{updateYFragment(t,n,d,{mapping:new Map,isOMark:new Map}),t.getMap(`metadata`).set(`frontmatter`,o)},OBSERVER_SYNC_ORIGIN),incrementServerObserverFire(`b`);try{let e=i.serialize(u);if(e===c)s=prependFrontmatter(o,c);else{let n=prependFrontmatter(o,e),i=r.toString();i!==n&&t.transact(()=>{applyFastDiff(r,i,n)},OBSERVER_SYNC_ORIGIN),s=n}}catch(e){console.warn(`[Server Observer B] Post-sync re-serialization failed — using input body as baseline:`,e),s=prependFrontmatter(o,c)}}catch(e){incrementServerObserverError(`b`),console.error(`[Server Observer B] Failed to sync text→tree:`,e);try{let e=yXmlFragmentToProseMirrorRootNode(n,a).toJSON(),r=i.serialize(e);s=prependFrontmatter(getFrontmatter(t),r)}catch(e){console.warn(`[Server Observer B] Baseline recovery also failed:`,e)}}},p=(e,r)=>{if(r.origin!==OBSERVER_SYNC_ORIGIN){if(isPairedWriteOrigin(r.origin)){try{let e=yXmlFragmentToProseMirrorRootNode(n,a).toJSON(),r=i.serialize(e);s=prependFrontmatter(getFrontmatter(t),r)}catch(e){incrementServerObserverError(`b`),console.warn(`[Server Observer B] Paired-write baseline refresh failed — falling through to settlement:`,e instanceof Error?e.message:String(e)),l=!0}return}l=!0}},m=(t,n)=>{if(!c&&!l){e.onDispatch?.(`none`);return}if(n.every(e=>e.origin===OBSERVER_SYNC_ORIGIN)){c=!1,l=!1,e.onDispatch?.(`none`);return}c&&(c=!1,e.onDispatch?.(`a`),u()),l&&(l=!1,e.onDispatch?.(`b`),f())};return n.observeDeep(d),r.observe(p),t.on(`afterAllTransactions`,m),()=>{t.off(`afterAllTransactions`,m),n.unobserveDeep(d),r.unobserve(p)}}function createServerObserverExtension(e){let t=new Map,n=new Map;return{async afterLoadDocument({documentName:r,document:i}){if(isSystemDoc(r)||isConfigDoc(r)||t.has(r))return;let a=i,o=a.getXmlFragment(`default`),s=a.getText(`source`),c=()=>{try{let n=setupServerObservers({doc:a,xmlFragment:o,ytext:s,mdManager:e.mdManager,schema:e.schema,docName:r,shadow:e.shadowRef?()=>e.shadowRef?.current:void 0,getBranch:e.getCurrentBranch?()=>e.getCurrentBranch?.()??`main`:void 0,contentRoot:e.contentRoot,resolveEmbed:e.resolveEmbed});return t.set(r,n),!0}catch(e){return console.error(`[ServerObserverExtension] Failed to attach observers for '${r}':`,e),incrementServerObserverError(`a`),incrementServerObserverError(`b`),!1}};if(!c()){let e=setTimeout(()=>{n.delete(r),!t.has(r)&&(console.warn(`[ServerObserverExtension] Retrying observer attachment for '${r}'`),c())},5e3);n.set(r,e)}},async afterUnloadDocument({documentName:e}){let r=n.get(e);r&&(clearTimeout(r),n.delete(e));let i=t.get(e);i&&(i(),t.delete(e))},async onDestroy(){for(let e of n.values())clearTimeout(e);n.clear();for(let[e,n]of t.entries())try{n()}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 n=t.createdBy;return!(typeof n.runtimeVersion!=`string`||typeof n.protocolVersion!=`number`)}function readStateManifest(e){let t=manifestPath(e);if(!existsSync(t))return{status:`absent`};let n;try{n=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 r;try{r=JSON.parse(n)}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(r))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:r}}function writeStateManifest(e,t){let n=manifestPath(e);mkdirSync(dirname(n),{recursive:!0}),writeFileSync(n,JSON.stringify(t,null,2),{encoding:`utf-8`,mode:384})}function assertCompatibleStateManifest(e){let t=getLogger(`state-manifest`),n=e.currentStateSchemaVersion??1,r=e.currentRuntimeVersion??RUNTIME_VERSION,i=e.currentProtocolVersion??1,a=(e.now??(()=>new Date))().toISOString(),o=manifestPath(e.lockDir),s=readStateManifest(e.lockDir);if(s.status===`present`){let c=s.manifest;if(!isCompatibleSchema(c.stateSchemaVersion,n))throw new StateManifestError({kind:`incompatible`,path:o,message:`State manifest at ${o} declares stateSchemaVersion=${c.stateSchemaVersion} but this binary supports ${n}. Refusing to boot — on-the-fly migration is out of scope. (Manifest written by runtime ${c.createdBy.runtimeVersion}, protocol ${c.createdBy.protocolVersion}.)`});try{let t={...c,lastWriteBy:{runtimeVersion:r,protocolVersion:i,at:a}};return writeStateManifest(e.lockDir,t),t}catch(e){return t.warn({err:e},`[state-manifest] failed to update lastWriteBy — proceeding`),c}}if(detectProjectShape({lockDir:e.lockDir,shadowRepoDir:e.shadowRepoDir})===`fresh`){let s={stateSchemaVersion:n,createdAt:a,createdBy:{runtimeVersion:r,protocolVersion:i}};return writeStateManifest(e.lockDir,s),t.info({path:o,stateSchemaVersion:n},`[state-manifest] fresh project — wrote manifest`),s}let c={stateSchemaVersion:0,createdAt:a,createdBy:{runtimeVersion:r,protocolVersion:i,adoptedAt:a}};return writeStateManifest(e.lockDir,c),t.warn({path:o,runtimeVersion:r},`[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.`),c}const log$1=getLogger(`conflict-storage`);var ConflictStore=class{storePath;projectDir;branch;conflicts=[];constructor(e,t,n=`main`){this.storePath=join(e,`.open-knowledge`,`conflicts.json`),this.projectDir=t,this.branch=n,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,n,r=[]){if(!this.conflicts.find(t=>t.file===e))throw Error(`[conflicts] no conflict tracked for file: ${e}`);if(t===`content`&&n===void 0)throw Error(`[conflicts] strategy 'content' requires content parameter`);let{createGitInstance:i}=await import(`./git-handle-BhGnmvTB-Di8EsrYa.mjs`).then(e=>e.n),a=i(this.projectDir,{credentialArgs:r});switch(t){case`mine`:await a.git.raw([`checkout`,`--ours`,`--`,e]),await a.git.raw([`add`,`--`,e]);break;case`theirs`:await a.git.raw([`checkout`,`--theirs`,`--`,e]),await a.git.raw([`add`,`--`,e]);break;case`content`:{if(!n)throw Error(`[conflicts] strategy 'content' requires content parameter`);let t=resolve(this.projectDir),r=resolve(t,e);if(r!==t&&!r.startsWith(`${t}/`))throw Error(`[conflicts] file path escapes project directory: ${e}`);writeFileSync(r,n,`utf-8`),await a.git.raw([`add`,`--`,e]);break}default:throw Error(`[conflicts] unknown resolve strategy: ${t}`)}if(this.removeConflict(e),!this.hasConflicts())try{await a.git.raw([`commit`,`--no-edit`]),log$1.info({file:e},`[conflicts] all conflicts resolved — merge commit created`)}catch(t){let n=new Date().toISOString(),r=!1;try{let e=(await a.git.raw([`diff`,`--name-only`,`--diff-filter=U`])).split(`
|
|
@@ -134,9 +135,9 @@ What to log:
|
|
|
134
135
|
`):[]){let t=e.trim();if(!t)continue;let n=join(this.projectDir,t),r=relative(this.contentDir,n);!r.startsWith(`..`)&&!this.contentFilter.isExcluded(r)&&a.add(t)}}catch{}if(t.length>0){let n=100;for(let n=0;n<t.length;n+=100){let r=t.slice(n,n+100).map(e=>e.projectRelPath);await e.git.raw([`add`,`--`,...r])}}let o=new Set(t.map(e=>e.projectRelPath)),s=[...a].filter(e=>!o.has(e));s.length>0&&await e.git.raw([`rm`,`--cached`,`--`,...s]);let c=(await e.git.raw([`write-tree`])).trim(),l=``;try{l=(await e.git.raw([`rev-parse`,`${i}^{tree}`])).trim()}catch{}if(l&&l===c){let n=null;try{n=(await e.git.raw([`rev-parse`,`origin/${this.currentBranch}`])).trim()}catch{}if(n===i){log.info({contentFileCount:t.length,headSha:i},`[sync] push cycle: nothing to commit (tree unchanged, origin matches HEAD)`),this.lastPushedSha=i,this.transitionTo(`idle`);return}log.info({headSha:i,upstreamSha:n},`[sync] push cycle: tree unchanged but local ahead of origin — pushing existing commits`);let a=!1;try{await e.git.raw([`rev-parse`,`--abbrev-ref`,`${this.currentBranch}@{u}`]),a=!0}catch{}a?await e.git.raw([`push`,`origin`,this.currentBranch]):await e.git.raw([`push`,`--set-upstream`,`origin`,this.currentBranch]),r=i;return}let u=[];try{let n=(await e.git.raw([`diff-tree`,`--name-only`,`-r`,i,c])).trim();if(n){let e=new Map(t.map(e=>[e.projectRelPath,e.contentRelPath]));for(let t of n.split(`
|
|
135
136
|
`)){let n=t.trim();if(!n)continue;let r=e.get(n)??relative(this.contentDir,join(this.projectDir,n));r&&!r.startsWith(`..`)&&u.push(r)}}}catch{u=t.map(e=>e.contentRelPath)}let d=this.buildCommitMessage(u),f=await resolveGitIdentity(this.projectDir),p=f===null;this.identityUnresolved!==p&&(this.identityUnresolved=p,this.cc1Broadcaster?.signal(`sync-status`));let m=f?.name??`Open Knowledge`,h=f?.email??`sync@open-knowledge.local`;e.git.env({GIT_AUTHOR_NAME:m,GIT_AUTHOR_EMAIL:h,GIT_COMMITTER_NAME:m,GIT_COMMITTER_EMAIL:h});let g=(await e.git.raw([`commit-tree`,c,`-p`,i,`-m`,d])).trim();if(!g||!SHA_HEX_40.test(g)){log.warn({raw:g},`[sync] commit-tree returned invalid SHA — aborting push`),this.transitionTo(`idle`);return}if(await e.git.raw([`update-ref`,`refs/heads/${this.currentBranch}`,g,i]),t.length>0){let e=createGitInstance(this.projectDir,{credentialArgs:this.credentialArgs}),n=100;for(let n=0;n<t.length;n+=100){let r=t.slice(n,n+100).map(e=>e.projectRelPath);try{await e.git.raw([`reset`,`HEAD`,`--`,...r])}catch{}}}let _=!1;try{await e.git.raw([`rev-parse`,`--abbrev-ref`,`${this.currentBranch}@{u}`]),_=!0}catch{}_?await e.git.raw([`push`,`origin`,this.currentBranch]):await e.git.raw([`push`,`--set-upstream`,`origin`,this.currentBranch]),r=g}),r&&(this.lastPushedSha=r,this.lastSyncUtc=new Date().toISOString(),this.ahead=0,this.state===`pushing`&&this.transitionTo(`idle`),this.pausedReason===`dirty-tree`&&(this.pausedReason=void 0,this.error=void 0,this.schedulePull(0)))}catch(t){let n=classifyGitError(t instanceof Error?t:Error(String(t)));if(n.class===`semantic`&&n.subclass===`non-fast-forward`){if(e>0){log.info({},`[sync] push rejected (non-fast-forward) — fetching, merging, retrying`);let e=createGitInstance(this.projectDir,{credentialArgs:this.credentialArgs});this.setBatchInProgress?.(!0);try{if(await e.git.fetch(`origin`),await this.commitDirtyContentFilesToHead(e),!await this.pauseIfNonContentDirty(e)){this.setBatchInProgress?.(!1);return}await e.git.merge([`origin/${this.currentBranch}`])}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),this.scheduleSaveState();return}finally{this.setBatchInProgress?.(!1)}await this.doPushCycle(0);return}log.info({},`[sync] push still rejected after retry — waiting for next pull cycle`),this.consecutiveFailures++,this.state===`pushing`&&this.transitionTo(`idle`)}else this.handleError(n)}finally{try{unlinkSync(n)}catch{}}this.scheduleSaveState()}async commitDirtyContentFilesToHead(e){if((await e.git.status()).files.length===0)return null;let t=(await e.git.revparse(`HEAD`)).trim(),n=this.gatherContentFilesSync();if(n.length===0)return null;let r=join(tmpdir(),`ok-sync-retry-idx-${process.pid}-${Date.now()}.idx`),i=createGitInstance(this.projectDir,{credentialArgs:this.credentialArgs,gitIndexFile:r});try{await i.git.raw([`read-tree`,t]);let r=100;for(let e=0;e<n.length;e+=100){let t=n.slice(e,e+100).map(e=>e.projectRelPath);await i.git.raw([`add`,`--`,...t])}let a=(await i.git.raw([`write-tree`])).trim();if(a===(await i.git.raw([`rev-parse`,`${t}^{tree}`])).trim())return null;let o=await resolveGitIdentity(this.projectDir),s=o?.name??`Open Knowledge`,c=o?.email??`sync@open-knowledge.local`;i.git.env({GIT_AUTHOR_NAME:s,GIT_AUTHOR_EMAIL:c,GIT_COMMITTER_NAME:s,GIT_COMMITTER_EMAIL:c});let l=(await i.git.raw([`commit-tree`,a,`-p`,t,`-m`,`Auto-save: interim before merge`])).trim();if(!l||!SHA_HEX_40.test(l))return log.warn({raw:l},`[sync] commit-tree returned invalid SHA in commitDirtyContentFilesToHead`),null;await e.git.raw([`update-ref`,`refs/heads/${this.currentBranch}`,l,t]);for(let t=0;t<n.length;t+=100){let r=n.slice(t,t+100).map(e=>e.projectRelPath);try{await e.git.raw([`reset`,`HEAD`,`--`,...r])}catch{}}return l}finally{try{unlinkSync(r)}catch{}}}async pauseIfNonContentDirty(e){let t=``;try{t=(await e.git.raw([`diff-index`,`--name-only`,`HEAD`])).trim()}catch{return!0}if(!t)return!0;let n=t.split(`
|
|
136
137
|
`).map(e=>e.trim()).filter(Boolean);return n.length===0?!0:(this.error=`External changes pending: ${n.slice(0,3).join(`, `)}${n.length>3?`, +${n.length-3} more`:``}`,this.pausedReason=`external-changes-pending`,this.consecutiveFailures=0,this.transitionTo(`idle`),this.scheduleSaveState(),log.warn({files:n},`[sync] paused — non-content tracked files dirty`),!1)}gatherContentFilesSync(){let e=[],t=n=>{let r;try{r=readdirSync(n,{withFileTypes:!0})}catch{return}for(let i of r){let r=join(n,i.name);if(i.isDirectory()){if(i.name===`node_modules`||i.name===`.git`||i.name.startsWith(`.`)&&i.name!==`.open-knowledge`)continue;t(r)}else if(i.isFile()){let t=relative(this.contentDir,r);if(!t.startsWith(`..`)&&!this.contentFilter.isExcluded(t)){let n=relative(this.projectDir,r);e.push({contentRelPath:t,projectRelPath:n})}}}};return existsSync(this.contentDir)&&t(this.contentDir),e}buildCommitMessage(e){return e.length===0?`Auto-save: changes saved`:e.length<=3?`Auto-save: Updated ${e.join(`, `)}`:`Auto-save: ${e.length} files changed`}async handleMergeConflict(){let e=createGitInstance(this.projectDir,{credentialArgs:this.credentialArgs}),t=[];try{let n=(await e.git.raw([`diff`,`--name-only`,`--diff-filter=U`])).trim();t=n?n.split(`
|
|
137
|
-
`).map(e=>e.trim()).filter(Boolean):[]}catch(t){log.error({err:t},`[sync] failed to list conflicted files — aborting merge to avoid committing unresolved state`);try{await e.git.raw([`merge`,`--abort`])}catch(e){log.warn({err:e},`[sync] git merge --abort failed during cleanup`)}this.error=`Failed to detect conflict files — merge aborted`,this.pausedReason=void 0,this.transitionTo(`idle`);return}let n=[],r=[];for(let e of t){let t=join(this.projectDir,e),i=relative(this.contentDir,t);!i.startsWith(`..`)&&!this.contentFilter.isExcluded(i)?n.push(e):r.push(e)}for(let t of r)try{await e.git.raw([`checkout`,`--theirs`,`--`,t]),await e.git.raw([`add`,`--`,t]),log.info({file:t},`[sync] auto-resolved non-content conflict with theirs`)}catch(e){log.warn({err:e,file:t},`[sync] auto-resolve failed — escalating to content conflict`),n.push(t)}if(n.length>0){for(let e of n)this.conflictStore.addConflict({file:e,detectedAt:new Date().toISOString()});this.conflictCount=this.conflictStore.count(),this.pullTimer!==null&&(clearTimeout(this.pullTimer),this.pullTimer=null),this.pushTimer!==null&&(clearTimeout(this.pushTimer),this.pushTimer=null),this.transitionTo(`conflict`),log.warn({files:n},`[sync] content conflicts — sync paused until resolved`)}else try{await e.git.raw([`commit`,`--no-edit`]),this.lastSyncUtc=new Date().toISOString(),this.behind=0,this.transitionTo(`idle`),log.info({},`[sync] all conflicts auto-resolved — merge committed`)}catch(t){log.warn({err:t},`[sync] failed to commit after auto-resolving conflicts — aborting merge`);try{await e.git.raw([`merge`,`--abort`])}catch(e){log.warn({err:e},`[sync] git merge --abort failed during cleanup`)}this.transitionTo(`idle`)}}async abortMerge(){let e=createGitInstance(this.projectDir,{credentialArgs:this.credentialArgs});try{await e.git.raw([`merge`,`--abort`]),log.info({},`[sync] merge aborted`)}catch(e){log.warn({err:e},`[sync] git merge --abort failed — conflicts.json still cleared`)}this.conflictStore.clear(),this.conflictCount=0,this.transitionTo(`idle`),this.scheduleSaveState()}handleError(e){this.error=e.message,log.warn({class:e.class,subclass:e.subclass,retryable:e.retryable,rawStderr:e.rawStderr},`[sync-error] ${e.message}`),e.class===`auth`?(this.transitionTo(`auth-error`),this.pausedReason=`auth-error`):e.class===`semantic`&&e.subclass===`protected-branch`?(this.syncEnabled=!1,this.transitionTo(`disabled`),this.pausedReason=`protected-branch`):e.class===`local`&&e.subclass===`dirty-tree`?(this.consecutiveFailures++,this.transitionTo(`idle`),this.pausedReason=`dirty-tree`,this.schedulePush(0)):e.retryable?(this.consecutiveFailures++,this.transitionTo(`offline`)):(this.consecutiveFailures++,this.transitionTo(`idle`))}transitionTo(e){if(this.state===e)return;let t=this.state;this.state=e,log.info({from:t,to:e},`[sync] state: ${t} → ${e}`),this.onStateChange?.(e),this.cc1Broadcaster?.signal(`sync-status`)}scheduleSaveState(){this.stateSaveTimer===null&&(this.stateSaveTimer=setTimeout(()=>{this.stateSaveTimer=null,this.saveStateNow()},5e3))}saveStateNow(){try{let e={version:1,lastSyncUtc:this.lastSyncUtc,lastFetchUtc:this.lastFetchUtc,lastPushedSha:this.lastPushedSha,consecutiveFailures:this.consecutiveFailures,pausedReason:this.pausedReason,pausedSinceUtc:this.pausedReason?new Date().toISOString():void 0,inflightConflicts:this.conflictStore.list().map(e=>e.file),syncEnabled:this.syncEnabled};writeFileSync(this.statePath,JSON.stringify(e,null,2),`utf-8`)}catch(e){log.warn({err:e},`[sync] failed to persist sync state`)}}loadState(){if(existsSync(this.statePath))try{let e=readFileSync(this.statePath,`utf-8`),t=JSON.parse(e);if(t.version!==1)return;this.lastSyncUtc=t.lastSyncUtc??null,this.lastFetchUtc=t.lastFetchUtc??null,this.lastPushedSha=t.lastPushedSha??null,this.consecutiveFailures=t.consecutiveFailures??0,this.pausedReason=t.pausedReason,t.syncEnabled!==void 0&&(this.syncEnabled=t.syncEnabled);let n=t.inflightConflicts??[];if(n.length>0){for(let e of n)this.conflictStore.list().some(t=>t.file===e)||this.conflictStore.addConflict({file:e,detectedAt:new Date().toISOString()});this.conflictCount=this.conflictStore.count()}}catch(e){log.warn({err:e},`[sync] failed to load sync state`)}}};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:n=t,quiet:r=!0,debounce:i=2e3,maxDebounce:a=1e4,gitEnabled:o=!0,commitDebounceMs:s=3e4,wipRef:c=`refs/wip/main`,configHomedirOverride:l,enableTestRoutes:u=!1,shadowRepo:d,contentRoot:f,includePatterns:p=[`**/*.md`,`**/*.mdx`],excludePatterns:m=[],destroyTimeoutMs:h=1e4,localOpCliArgs:g,skipStateManifestCheck:_=!1}=e,v=getLogger(`server`);initTelemetry();let y=randomUUID(),b=resolve(t,`.open-knowledge`);if(acquireServerLock(b,{port:e.port??0,worktreeRoot:n,kind:e.lockKind??`interactive`,...e.parentPid!==void 0&&{parentPid:e.parentPid},capabilities:[`http`,`ws`]}),!_)try{assertCompatibleStateManifest({lockDir:b,shadowRepoDir:resolveShadowDir(n)})}catch(e){throw releaseServerLock(b),e}let x=createBasenameIndex(),S=(e,t)=>x.resolveEmbed(e,t),C,w,T,E,D,O,k=null,A=null,j=null,M=null,N=new Set,P=!1,F;function I(e){k?.signal(e)}try{C=createContentFilter({projectDir:n,contentDir:t,includePatterns:p,excludePatterns:m}),w=new BacklinkIndex({projectDir:n,contentDir:t,contentFilter:C}),T={current:d},E=createPersistenceExtension({contentDir:t,projectDir:n,gitEnabled:o,commitDebounceMs:s,wipRef:c,shadowRef:T,contentRoot:f,backlinkIndex:w,configHomedirOverride:l,getCurrentBranch:()=>ee?.getLastKnownBranch()??null,resolveEmbed:S,getPrincipal:()=>M,onAgentCommit:()=>k?.signal(`session-activity`),onDiskFlush:(e,t)=>k?.emitDiskAck(e,t),onConfigRejected:(e,t)=>k?.emitConfigValidationRejected(e,t)}),D=new Hocuspocus({quiet:r,debounce:i,maxDebounce:a,extensions:[E.extension]});let h=D.shouldUnloadDocument.bind(D);D.shouldUnloadDocument=e=>(P||N.has(e))&&h(e),F=async e=>{N.add(e);try{await D.unloadDocument(e)}finally{N.delete(e)}},k=new CC1Broadcaster(D),A=new AgentFocusBroadcaster(D),j=new AgentPresenceBroadcaster(D),O=new AgentSessionManager(D);let _=createLiveDerivedIndexExtension({backlinkIndex:w,signalChannel:I});D.configuration.extensions.push(_),D.configuration.extensions.push({__kind:`principal-auth`,async onAuthenticate(e){let t=e.token,n=parseHocuspocusAuthToken(t),r=n?.expectedServerInstanceId;if(typeof r==`string`&&r.length>0&&r!==y)throw new HocuspocusAuthRejection(`server-instance-mismatch`,`server instance mismatch: client claimed ${r}, this server is ${y}`);let i=n?.expectedBranch,a=getActiveBranch();if(typeof i==`string`&&i.length>0&&i!==a)throw new HocuspocusAuthRejection(`branch-mismatch`,`branch mismatch: client claimed ${i}, server is on ${a}`);if(!n)return;let o=e.context;typeof n.principalId==`string`&&(M&&n.principalId===M.id?o.principalId=M.id:M?console.warn(JSON.stringify({event:`principal-token-mismatch`,claimed:n.principalId,loaded:M.id})):o.principalId=n.principalId),typeof n.tabSessionId==`string`&&(o.tabSessionId=n.tabSessionId),o.kind=`human`}}),D.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 v=createApiExtension({hocuspocus:D,sessionManager:O,contentDir:t,contentFilter:C,serverInstanceId:y,getFileIndex:()=>J?J.getFileIndex():new Map,getAliasMap:()=>J?J.getAliasMap():new Map,enableTestRoutes:u,shadowRef:T,flushGitCommit:()=>E.flushPendingGitCommit(),getCurrentBranch:()=>ee?.getLastKnownBranch()??null,getDiskAckSVs:()=>k?.getLatestDiskAckSVsAsBase64()??{},contentRoot:f,backlinkIndex:w,signalChannel:I,agentFocusBroadcaster:A,agentPresenceBroadcaster:j,onAgentWrite:e.onAgentWrite,getSyncEngine:()=>Y,localOpCliArgs:g,projectDir:n,resolveEmbed:S,getPrincipal:()=>M,forceUnloadDocument:F});D.configuration.extensions.push(v),D.configuration.extensions.push(createServerObserverExtension({mdManager,schema,shadowRef:T,contentRoot:f,getCurrentBranch:()=>ee?.getLastKnownBranch()??null,resolveEmbed:S}))}catch(e){throw releaseServerLock(b),e}let L=null,R=new Map,z=[];function B(e,t){let n=resolve(e,`rescue`),r=resolve(n,`${t}${getDocExtension(t)}`);return r.startsWith(`${n}/`)?r:null}function V(e){let t=D.documents.get(e);if(!t)return null;let n=yXmlFragmentToProseMirrorRootNode(t.getXmlFragment(`default`),schema).toJSON(),r=mdManager.serialize(n),i=t.getMap(`metadata`).get(`frontmatter`);return prependFrontmatter(typeof i==`string`?i:``,r)}let H=(e,t)=>applyExternalChange(D,e,t,S);function U(e){switch(e.kind){case`rename`:return e.newDocName;case`asset-create`:case`asset-delete`:return e.relativePath;default:return e.docName}}async function W(e){try{switch(e.kind){case`create`:v.info({docName:e.docName},`[reconcile] create: ${e.docName}`),w.updateDocumentFromMarkdown(e.docName,e.content),w.saveToDisk().catch(t=>{console.warn(`[backlinks] Failed to persist create for ${e.docName}:`,t)}),I(`files`),I(`backlinks`),I(`graph`);break;case`update`:{let{docName:t,content:n}=e,r=D.documents.get(t);if(!r){w.updateDocumentFromMarkdown(t,n),w.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist closed-doc update for ${t}:`,e)}),I(`backlinks`),I(`graph`);return}let i=getReconciledBase(t)??``,a=V(t)??i,o=reconcile({docName:t,base:i,ours:a,theirs:n}),s=contentHash(i).slice(0,6),c=contentHash(a).slice(0,6),l=contentHash(n).slice(0,6);switch(v.info({docName:t,base:s,ours:c,theirs:l,result:o.kind},`[reconcile] ${t} base=${s} ours=${c} theirs=${l} result=${o.kind}`),o.kind){case`noop`:w.updateDocumentFromMarkdown(t,n),w.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist noop update for ${t}:`,e)}),I(`backlinks`),I(`graph`);break;case`clean`:try{H(t,o.newContent),setReconciledBase(t,o.newContent),incrementReconcile(),w.updateDocumentFromMarkdown(t,n),w.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist clean update for ${t}:`,e)}),I(`backlinks`),I(`graph`)}catch(e){v.error({err:e,docName:t},`[reconcile] failed to apply clean content to Y.Doc for ${t}`),setReconciledBase(t,n)}break;case`merged`:try{H(t,o.newContent),setReconciledBase(t,o.newContent),incrementReconcile(),w.updateDocumentFromMarkdown(t,n),w.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist merged update for ${t}:`,e)}),I(`backlinks`),I(`graph`)}catch(e){v.error({err:e,docName:t},`[reconcile] failed to apply merged content to Y.Doc for ${t}`),setReconciledBase(t,n)}break;case`conflicts`:try{H(t,o.newContent),setReconciledBase(t,o.newContent),incrementReconcile(),incrementConflict(),w.updateDocumentFromMarkdown(t,n),w.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist conflict update for ${t}:`,e)}),I(`backlinks`),I(`graph`)}catch(e){v.error({err:e,docName:t},`[reconcile] failed to apply conflict content to Y.Doc for ${t}`),setReconciledBase(t,n)}break;case`refused`:{incrementConflict();let e=r.getMap(`lifecycle`);e.set(`status`,`conflict`),e.set(`reason`,o.reason);break}}break}case`delete`:{let{docName:t}=e,n=D.documents.get(t);if(!n){w.deleteDocument(t),w.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist closed-doc delete for ${t}:`,e)}),I(`files`),I(`backlinks`),I(`graph`);return}let r=getReconciledBase(t)??``,i=V(t)??``,a=i!==r;if(a&&T.current){let e=T.current,n=ee?.getLastKnownBranch()??`main`;queueMicrotask(()=>{saveInMemoryCheckpoint(e,f??``,{kind:`external-change-rescue`,docName:t,contents:i,label:`External change recovered @ ${new Date().toISOString()}`,branch:n,metadata:{incomingDiskSha:``}}).then(()=>{incrementRescueBuffer(),v.info({docName:t},`[reconcile] rescue checkpoint saved (delete): ${t}`)}).catch(e=>{v.error({docName:t,err:e},`[reconcile] rescue checkpoint write failed: ${t}`)})})}n.getMap(`lifecycle`).set(`status`,`deleted-upstream`),deleteReconciledBase(t),w.deleteDocument(t),w.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist delete for ${t}:`,e)}),v.info({docName:t,isDirty:a},`[reconcile] delete: ${t} (dirty=${a})`),D.closeConnections(t),await F(n),I(`files`),I(`backlinks`),I(`graph`);break}case`rename`:{let{oldDocName:t,newDocName:n,content:r}=e,i=D.documents.get(t);if(deleteReconciledBase(t),setReconciledBase(n,r),w.renameDocument(t,n,r),w.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist rename for ${t} -> ${n}:`,e)}),i){let e=i.getMap(`lifecycle`);e.set(`status`,`renamed`),e.set(`newPath`,n)}v.info({oldDocName:t,newDocName:n},`[reconcile] rename: ${t} → ${n}`),I(`files`),I(`backlinks`),I(`graph`);break}case`conflict`:{let{docName:t}=e,n=D.documents.get(t);if(!n)return;let r=n.getMap(`lifecycle`);r.set(`status`,`conflict`),r.set(`reason`,`conflict-markers`),v.info({docName:t},`[reconcile] conflict markers detected: ${t}`);break}case`asset-create`:x.add(e.relativePath),I(`files`);break;case`asset-delete`:x.remove(e.relativePath),I(`files`);break;default:assertNeverDiskEvent(e)}}catch(t){let n=U(e);v.error({err:t,kind:e.kind,label:n},`[reconcile] failed to handle ${e.kind} for ${n}`)}}let G=[];async function K(e){if(isBatchInProgress()){G.push(e);return}await W(e)}async function q(){let e=G.splice(0,G.length);for(let t of e)await W(t)}let J=null,ee=null,Y=null,X=null;async function Z(e){if(D.documents.size===0)return;let t=!1,n=new Promise(e=>{D.configuration.extensions.push({async afterUnloadDocument({instance:n}){!t&&n.getDocumentsCount()===0&&(t=!0,e())}})}),r=Array.from(D.documents.keys());D.closeConnections(),D.flushPendingStores();for(let e of D.documents.values())e.getConnectionsCount()===0&&D.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 i,a=new Promise((n,a)=>{i=setTimeout(()=>{t=!0;let n=Array.from(D.documents.keys()),i=[],o=[];if(T.current){for(let e of n)if(!(isSystemDoc(e)||isConfigDoc(e)))try{let t=V(e);if(t===null){v.warn({docName:e},`[rescue] skipping ${e} — document dropped from map mid-rescue`),o.push(e);continue}let n=B(T.current.gitDir,e);if(!n){v.warn({docName:e,gitDir:T.current.gitDir},`[rescue] path-traversal guard rejected docName: ${e}`),o.push(e);continue}mkdirSync(dirname(n),{recursive:!0}),writeFileSync(n,t,`utf-8`),incrementRescueBuffer(),i.push(e),v.info({docName:e},`[rescue] rescue buffer saved on flush timeout: ${e}`)}catch(t){o.push(e),v.error({err:t,docName:e},`[rescue] failed to write rescue buffer for ${e}`)}}else v.warn({stillLoadedCount:n.length},`[rescue] shadow repo unavailable at flush timeout — ${n.length} doc(s) will be lost: [${n.join(`, `)}]`),o.push(...n);let s=i.length>0||o.length>0?` — rescued [${i.join(`, `)}]${o.length>0?`, lost [${o.join(`, `)}]`:``}`:``;a(Error(`flushAllStoresAndWait timeout after ${e}ms — ${n.length}/${r.length} docs did not unload: [${n.join(`, `)}]${s}`))},e)});try{await Promise.race([n,a])}finally{i!==void 0&&clearTimeout(i)}}async function te(){return X||(X=(async()=>{let e=Date.now(),t=[];P=!0;let r,i=await Promise.race([re.then(()=>`completed`,e=>(v.debug({err:e},`[server] init incomplete during shutdown`),`failed`)),new Promise(e=>{r=setTimeout(()=>e(`timeout`),5e3)})]);r!==void 0&&clearTimeout(r),i===`timeout`&&v.warn({},`[server] init did not complete within 5s during shutdown`);let a=D.documents.size;try{try{try{ee&&=(await ee.unsubscribe(),null),J&&=(await J.unsubscribe(),null);for(let{docName:e,cleanup:t}of z)try{await t()}catch(t){v.warn({err:t,docName:e},`[server] failed to stop config-file-watcher for ${e}`)}z.length=0}catch(e){t.push({phase:`watcher-unsubscribe`,error:e instanceof Error?e.message:String(e)}),v.error({err:e},`[server] shutdown phase-1 watcher unsubscribe failed`)}try{k?.destroy(),j?.destroy(),L&&=(await L.disconnect(),null);for(let[e,t]of R)try{await t.disconnect()}catch(t){v.warn({err:t,docName:e},`[server] failed to disconnect ${e} during shutdown`)}R.clear()}catch(e){t.push({phase:`cc1-teardown`,error:e instanceof Error?e.message:String(e)}),v.error({err:e},`[server] shutdown phase-1b CC1 teardown failed`)}try{await O.closeAll()}catch(e){t.push({phase:`agent-session-drain`,error:e instanceof Error?e.message:String(e)}),v.error({err:e},`[server] shutdown phase-2 agent session drain failed`)}try{await Z(h)}catch(e){t.push({phase:`flush-all-stores`,error:e instanceof Error?e.message:String(e)}),v.error({err:e},`[server] shutdown phase-3 flush failed`)}let e;try{await Promise.race([(async()=>{await E.flushPendingGitCommit(),await E.waitForPendingCommits()})(),new Promise((t,n)=>{e=setTimeout(()=>n(Error(`L2 git flush timeout`)),h)})])}catch(e){t.push({phase:`git-commit-flush`,error:e instanceof Error?e.message:String(e)}),v.error({err:e},`[server] shutdown phase-4 git commit flush failed`)}finally{e!==void 0&&clearTimeout(e)}try{Y&&=(await Y.destroy(),null)}catch(e){t.push({phase:`sync-engine-stop`,error:e instanceof Error?e.message:String(e)}),v.error({err:e},`[server] shutdown sync-engine-stop failed`)}}finally{if(T.current){try{let e=(await esm_default({baseDir:n,timeout:{block:5e3}}).revparse(`HEAD`)).trim();e&&writeFileSync(resolve(T.current.gitDir,`last-known-head`),e,`utf-8`)}catch{}try{destroyShadowRepo(T.current)}catch(e){t.push({phase:`shadow-repo-release`,error:e instanceof Error?e.message:String(e)}),v.error({err:e},`[server] shutdown phase-5 destroyShadowRepo failed`)}}let r=Date.now()-e;t.length===0?v.info({documentCount:a,durationMs:r},`[server] shutdown flushed ${a} documents in ${r}ms`):v.warn({documentCount:a,durationMs:r,phaseErrors:t},`[server] shutdown flushed ${a} documents in ${r}ms with ${t.length} phase error(s)`)}}finally{try{releaseServerLock(b)}catch(e){t.push({phase:`server-lock-release`,error:e instanceof Error?e.message:String(e)}),v.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)})}}})(),X)}let Q=[];async function ne(){try{M=await loadPrincipal(t),v.info({principalId:M.id},`[server] principal loaded`)}catch(e){v.warn({err:e},`[server] principal load failed — browser writes will use SERVICE_WRITER`)}if(!T.current)try{T.current=await initShadowRepo(n),v.info({gitDir:T.current.gitDir},`[server] history repo initialized at ${T.current.gitDir}`)}catch(e){v.error({err:e},`[server] history repo init failed`),Q.push(`shadow-repo`)}if(T.current)try{await shadowGit(T.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`)){v.warn({},`[server] history repo appears corrupted — reinitializing`);try{T.current=await initShadowRepo(n)}catch(e){v.error({err:e},`[server] history repo reinit failed`),T.current=void 0,Q.includes(`shadow-repo`)||Q.push(`shadow-repo`)}}else v.error({err:e},`[server] history repo check failed (transient?)`)}if(T.current)try{let e=resolve(T.current.gitDir,`last-known-head`),t=null;try{t=readFileSync(e,`utf-8`).trim()||null}catch{}let r=null;try{r=(await esm_default({baseDir:n,timeout:{block:1e4}}).revparse(`HEAD`)).trim()||null}catch{}if(r!==null){if(r!==t){let e=`main`;try{let t=(await esm_default({baseDir:n,timeout:{block:1e4}}).raw(`rev-parse`,`--abbrev-ref`,`HEAD`)).trim();t&&t!==`HEAD`&&(e=t)}catch{}v.info({lastKnownHead:t,currentHead:r,branch:e},`[head-drift] lastKnownHead=${t??`null`}, currentHead=${r}, action=import`);try{await commitUpstreamImport(T.current,f??``,t,r,e),incrementUpstreamImport()}catch(e){v.warn({err:e},`[head-drift] commitUpstreamImport failed — continuing`)}}else v.info({currentHead:r},`[head-drift] lastKnownHead=${t??`null`}, currentHead=${r}, action=noop`);try{writeFileSync(e,r,`utf-8`)}catch(e){v.warn({err:e},`[head-drift] failed to write last-known-head`)}}}catch(e){v.warn({err:e},`[head-drift] check failed — continuing`)}try{let e=recoverPendingManagedRename(t);e.recovered&&e.journal&&v.warn({sourceDocName:e.journal.sourceDocName,destinationDocName:e.journal.destinationDocName,restoredDocNames:e.restoredDocNames},`[managed-rename] recovered pending rename ${e.journal.sourceDocName} -> ${e.journal.destinationDocName}`)}catch(e){v.error({err:e},`[server] managed rename recovery failed`),Q.push(`managed-rename-recovery`)}try{let e=cleanupOrphanUploadTempfiles(t);(e.deleted>0||e.errors>0)&&v.info({scanned:e.scanned,deleted:e.deleted,errors:e.errors},`[upload-tempfile-sweep] swept ${e.deleted} orphan tempfile(s)`)}catch(e){v.error({err:e},`[server] upload-tempfile sweep failed`),Q.push(`upload-tempfile-sweep`)}try{L=await D.openDirectConnection(SYSTEM_DOC_NAME),k?.emitServerInfo(y,getActiveBranch())}catch(e){v.error({err:e},`[server] failed to open __system__ direct connection — CC1 push disabled`),Q.push(`cc1-push`)}for(let e of CONFIG_DOC_NAMES)try{let t=await D.openDirectConnection(e);R.set(e,t)}catch(t){v.error({err:t,docName:e},`[server] failed to open ${e} direct connection — config bind degraded`),Q.push(`config-doc:${e}`)}let e=new Map([[CONFIG_DOC_NAME_WORKSPACE,resolveConfigPath(`workspace`,n)],[CONFIG_DOC_NAME_USER,resolveConfigPath(`user`,n,l)]]);for(let t of CONFIG_DOC_NAMES){let n=e.get(t);if(n)try{v.info({docName:t,path:n},`[config-file-watcher] starting`);let e=await startConfigFileWatcher(n,e=>{let n=D.documents.get(t);v.info({docName:t,hasDocument:n!==void 0,contentLength:e.length},`[config-file-watcher] file changed`);let r=applyExternalConfigChange(n??null,t,e,E.configPersistenceCtx);v.info({docName:t,outcome:r},`[config-file-watcher] applyExternalConfigChange outcome`)});z.push({docName:t,cleanup:e}),v.info({docName:t,path:n},`[config-file-watcher] started`)}catch(e){v.warn({err:e,docName:t,path:n},`[config-file-watcher] failed to start for ${t}`),Q.push(`config-file-watcher:${t}`)}}let r=resolveGitDir(n),i=r?readBranchFromHead(r)??`main`:`main`;switchReconciledBaseScope(i),w.switchBranch(i);try{J=await startWatcher(t,K,C),w.rebuildFromDisk(getActiveBranch()),w.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist startup cache for ${getActiveBranch()}:`,e)});let e=0;try{seedBasenameIndex({contentDir:t,contentFilter:C,basenameIndex:x,onSkip:(t,n,r)=>{e++,v.warn({reason:t,code:n,path:r},`[basename-index] skipped entry during seed (${t}${n?` ${n}`:``})`)}}),e>0&&(v.warn({count:e},`[basename-index] startup seed completed with ${e} skipped entries — embeds under inaccessible subtrees will not resolve`),Q.push(`basename-index-partial`))}catch(e){v.error({err:e},`[basename-index] startup seed failed`),Q.push(`basename-index`)}}catch(e){v.error({err:e},`[server] disk bridge watcher failed to start`),Q.push(`file-watcher`)}try{ee=await startHeadWatcher(n,async({trigger:e})=>{if(v.info({trigger:e},`[batch] begin trigger=${e}`),incrementBatch(),D.flushPendingStores(),await E.flushPendingGitCommit(),setBatchInProgress(!0),T.current){let e=getActiveBranch(),t=resolveGitDir(n),r=t?readBranchFromHead(t)??e:e,i=[];for(let[e,t]of D.documents){if(isSystemDoc(e)||isConfigDoc(e))continue;let n=null;if(t.transact(()=>{n=V(e)},PARK_SNAPSHOT_ORIGIN),n===null)continue;let r=getReconciledBase(e)??n;i.push({docName:e,markdown:n,diskSnapshot:r})}if(i.length>0)try{let t=await parkBranch(T.current,e,SERVICE_WRITER.id,i,r);t&&(incrementPark(),v.info({count:i.length,branch:e,sha:t.slice(0,8)},`[history] parked ${i.length} docs on ${e} → ${t.slice(0,8)}`))}catch(e){v.error({err:e},`[shadow] park failed`)}}},async e=>{let n=G.length,r=e.newBranch??`main`;if(setBatchInProgress(!1),v.info({kind:e.batchKind,headMoved:e.headMoved,docs:n,timeout:!!e.timeout},`[batch] end kind=${e.batchKind} headMoved=${e.headMoved} docs=${n}${e.timeout?` timeout`:``}`),e.batchKind===`within-branch`)await q();else{incrementBranchSwitch(),G.splice(0,G.length),switchReconciledBaseScope(r),w.switchBranch(r),C.rebuildDirCount();try{let e=0;x.clear(),seedBasenameIndex({contentDir:t,contentFilter:C,basenameIndex:x,onSkip:(t,n,i)=>{e++,v.warn({reason:t,code:n,path:i,branch:r},`[basename-index] skipped entry during branch-switch reseed (${t}${n?` ${n}`:``})`)}}),e>0&&(v.warn({count:e,branch:r},`[basename-index] branch-switch reseed completed with ${e} skipped entries — embeds under inaccessible subtrees will not resolve on this branch`),Q.includes(`basename-index-partial`)||Q.push(`basename-index-partial`))}catch(e){v.error({err:e,branch:r},`[basename-index] branch-switch reseed failed`)}for(let[e,n]of D.documents)if(!(isSystemDoc(e)||isConfigDoc(e)))try{let i=safeContentPath(e,t);if(!existsSync(i)){let t=getReconciledBase(e)??``,i=V(e)??``;if(i!==t&&T.current){let t=T.current;queueMicrotask(()=>{saveInMemoryCheckpoint(t,f??``,{kind:`external-change-rescue`,docName:e,contents:i,label:`External change recovered @ ${new Date().toISOString()}`,branch:r,metadata:{incomingDiskSha:``}}).then(()=>{incrementRescueBuffer(),v.info({docName:e},`[reconcile] rescue checkpoint saved on branch switch: ${e}`)}).catch(t=>{v.error({docName:e,err:t},`[reconcile] rescue checkpoint write failed: ${e}`)})})}n.getMap(`lifecycle`).set(`status`,`deleted-upstream`),v.info({docName:e,branch:r},`[branch-switch] tombstone: ${e} (not on ${r})`);continue}let a=readFileSync(i,`utf-8`);H(e,a),setReconciledBase(e,a),v.info({docName:e},`[branch-switch] reset: ${e}`)}catch(t){v.error({err:t,docName:e},`[branch-switch] failed to reset ${e}`)}if(v.info({branch:r,docCount:D.documents.size},`[branch-switch] loaded branch ${r} (${D.documents.size} docs)`),w.rebuildFromDisk(r),w.saveToDisk(r).catch(e=>{console.warn(`[backlinks] Failed to persist branch cache for ${r}:`,e)}),T.current&&e.batchKind===`cross-branch`){let e=0;for(let[t]of D.documents)if(!(isSystemDoc(t)||isConfigDoc(t)))try{let n=await readParkedState(T.current,r,SERVICE_WRITER.id,t);if(!n||n.markdown===n.diskSnapshot)continue;let i=getReconciledBase(t);if(!i)continue;let a=reconcile({docName:t,base:n.diskSnapshot,ours:n.markdown,theirs:i});switch(a.kind){case`merged`:case`clean`:H(t,a.newContent),setReconciledBase(t,a.newContent),e++;break;case`conflicts`:H(t,a.newContent),setReconciledBase(t,a.newContent),incrementConflict(),e++;break;case`noop`:case`refused`:break}}catch(e){v.error({err:e,docName:t},`[branch-switch] restore WIP failed for ${t}`)}e>0&&v.info({count:e,branch:r},`[branch-switch] restored ${e} parked docs on ${r}`)}if(e.oldBranch?.startsWith(`detached-`)&&T.current)try{let t=shadowGit(T.current),n=(await t.raw(`for-each-ref`,`refs/wip/${e.oldBranch}/`,`--format=%(refname)`)).trim();if(n){for(let e of n.split(`
|
|
138
|
-
`))e&&await t.raw(`update-ref`,`-d`,e);v.info({context:e.oldBranch},`[branch-switch] cleaned up detached context ${e.oldBranch}`)}}catch(e){v.error({err:e},`[branch-switch] detached cleanup failed`)}k?.emitBranchSwitched(r)}if(e.headMoved&&e.newHead&&T.current&&n>0){let t=f??`.`;try{let n=await commitUpstreamImport(T.current,t,e.oldHead,e.newHead,r);incrementUpstreamImport(),v.info({oldHead:e.oldHead?.slice(0,8)??`null`,newHead:e.newHead.slice(0,8),sha:n.slice(0,8)},`[history] upstream-import from ${e.oldHead?.slice(0,8)??`null`}..${e.newHead.slice(0,8)} → ${n.slice(0,8)}`)}catch(e){v.error({err:e},`[shadow] upstream-import failed`)}}})}catch(e){v.error({err:e},`[server] HEAD watcher failed to start`),Q.push(`head-watcher`)}let a=g?.[0]??`open-knowledge`,o=[`-c`,`credential.helper=!${g&&g.length>1?g.join(` `):a} auth git-credential`];try{Y=new SyncEngine({projectDir:n,contentDir:t,contentFilter:C,contentRoot:f,credentialArgs:o,cc1Broadcaster:k,setBatchInProgress,onStateChange:e=>{v.info({state:e},`[sync] state → ${e}`)}}),await Y.start()}catch(e){v.warn({err:e},`[server] SyncEngine failed to start — sync disabled`),Y=null}}let re=ne();return{hocuspocus:D,sessionManager:O,cc1Broadcaster:k,agentFocusBroadcaster:A,agentPresenceBroadcaster:j,contentFilter:C,basenameIndex:x,serverInstanceId:y,destroy:te,ready:re,degraded:Q,lockDir:b,get syncEngine(){return Y}}}const DEFAULT_PARENT_DEATH_POLL_MS=5e3,DEFAULT_IDLE_THRESHOLD_MS=1800*1e3;async function bootServer(e){let t=e.skipAutoInit??!1,n=e.attachUiSibling??!0,r=e.idleShutdownMs,i=e.log??getLogger(`boot`),a=process.env.OK_LOCK_KIND===`mcp-spawned`||process.env.OK_LOCK_KIND===`interactive`?process.env.OK_LOCK_KIND:void 0,o=process.env.OK_PARENT_PID,s=typeof o==`string`&&/^[0-9]+$/.test(o)?Number.parseInt(o,10):void 0,c=e.lockKind??a??`interactive`,l=e.parentPid??s;initTelemetry();let{createServer:u}=await import(`node:http`),{WebSocketServer:d}=await import(`./wrapper-DYxqFKGF.mjs`),{updateServerLockPort:f}=await import(`./server-lock-n3Y5JWNv-DXpg9_eU.mjs`).then(e=>e.a),p=!1;!t&&e.ensureProjectGitFn&&(p=!!(await e.ensureProjectGitFn()).didInit);let m=!1;if(!t&&e.autoInitFn)try{m=!!await e.autoInitFn()}catch(e){i.warn({err:e},`autoInitFn failed`)}let h=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,includePatterns:e.includePatterns,excludePatterns:e.excludePatterns,destroyTimeoutMs:e.destroyTimeoutMs,localOpCliArgs:e.localOpCliArgs,onAgentWrite:e.onAgentWrite,lockKind:c,parentPid:l,skipStateManifestCheck:e.skipStateManifestCheck}),{hocuspocus:g,destroy:_,ready:v,degraded:y,lockDir:b,agentPresenceBroadcaster:x}=h,S=u((e,t)=>{let n=e.url?.split(`?`)[0];if(n?.startsWith(`/api/`)){g.hooks(`onRequest`,{request:e,response:t}).then(()=>{t.writableEnded||t.headersSent||(t.statusCode=404,t.setHeader(`Content-Type`,`application/json`),t.end(JSON.stringify({error:`API route not found`,path:n})))}).catch(e=>{i.error({err:e},`Unhandled onRequest error`),!t.writableEnded&&!t.headersSent?(t.writeHead(500),t.end(`Internal server error`)):t.writableEnded||t.end()});return}t.writeHead(404,{"Content-Type":`application/json`}),t.end(JSON.stringify({error:"Not found. The React UI is served by `ok ui` (default port 3000).",path:n??`/`}))}),C=new d({noServer:!0});C.on(`error`,e=>{i.error({err:e},`WebSocketServer error`)});let w=e.keepaliveGraceMs??1e4,T=new Map,E=new Set,D=!1;S.on(`upgrade`,(e,t,n)=>{if(e.url?.startsWith(`/collab/keepalive`)){t.on(`error`,e=>{handleCollabSocketError(e)||i.error({err:e},`MCP keepalive socket error`)}),C.handleUpgrade(e,t,n,t=>{let n=parseKeepaliveConnectionId(e.url);if(n){let e=T.get(n);e!==void 0&&(clearTimeout(e),T.delete(n),i.info({connectionId:n},`[keepalive] reconnect during grace — timer cancelled`))}let r=setInterval(()=>{try{t.ping()}catch{}},3e4);r.unref?.();let a=n?setInterval(()=>{x?.bumpPresenceTs(toBroadcasterKey(n))},3e3):null;a?.unref?.(),t.on(`close`,()=>{if(clearInterval(r),a!==null&&clearInterval(a),!n)return;let e=setTimeout(()=>{if(T.delete(n),D)return;let e=(async()=>{i.info({connectionId:n},`[keepalive] grace expired — cleaning up sessions`);try{await h.sessionManager.closeAllForAgent(n)}catch(e){i.error({err:e,connectionId:n},`[keepalive] closeAllForAgent failed`)}try{h.agentFocusBroadcaster?.clearFocus(n)}catch(e){i.error({err:e,connectionId:n},`[keepalive] clearFocus failed`)}try{x?.clearPresence(toBroadcasterKey(n))}catch(e){i.error({err:e,connectionId:n},`[keepalive] clearPresence failed`)}})();E.add(e),e.finally(()=>E.delete(e))},w);e.unref?.(),T.set(n,e),i.info({connectionId:n,graceMs:w},`[keepalive] disconnected — grace timer started`)}),t.on(`error`,e=>{handleCollabSocketError(e)||i.error({err:e},`MCP keepalive WS error`),t.terminate()})});return}e.url?.startsWith(`/collab`)&&(t.on(`error`,e=>{handleCollabSocketError(e)||i.error({err:e},`Upgrade socket error`)}),C.handleUpgrade(e,t,n,t=>{let n=g.handleConnection(t,e);t.on(`message`,e=>{n.handleMessage((e instanceof ArrayBuffer,new Uint8Array(e)))}),t.on(`close`,(e,t)=>{n.handleClose({code:e,reason:t.toString()})}),t.on(`error`,e=>{handleCollabSocketError(e)||i.error({err:e},`WebSocket error`),t.terminate()})}))});let O=null;r!==null&&(O=attachIdleShutdown({httpServer:S,thresholdMs:r??DEFAULT_IDLE_THRESHOLD_MS,log:i,onShutdown:(e.idleShutdownHandler??(e=>async()=>{await e()}))(async()=>{await _()})})),await new Promise((t,n)=>{let r=e=>n(e);S.once(`error`,r),S.listen(e.port,e.host,()=>{S.removeListener(`error`,r),t()})});let k=S.address(),A=typeof k==`object`&&k?k.port:e.port??0;if(f(b,A),n&&e.spawnUiSiblingFn)try{await e.spawnUiSiblingFn({lockDir:b,log:i})}catch(e){i.warn({err:e},`spawnUiSiblingFn failed`)}let j=!1,M=null,N=async()=>{if(!j){j=!0,D=!0,M!==null&&(clearInterval(M),M=null);try{O?.detach()}catch(e){i.warn({err:e},`[bootServer.destroy] idleHandle.detach failed`)}for(let e of T.values())clearTimeout(e);T.clear(),E.size>0&&await Promise.allSettled([...E]);try{try{S.closeAllConnections?.()}catch(e){i.warn({err:e},`[bootServer.destroy] closeAllConnections failed`)}let e;try{await Promise.race([new Promise(e=>S.close(()=>e())),new Promise((t,n)=>{e=setTimeout(()=>n(Error(`httpServer.close timeout after 10s`)),1e4)})]).catch(e=>{i.warn({err:e},`[bootServer.destroy] httpServer.close did not complete within timeout`)})}finally{e!==void 0&&clearTimeout(e)}}finally{await _(),await shutdownTelemetry()}}};if(l!==void 0){let t=e.parentDeathPollMs??DEFAULT_PARENT_DEATH_POLL_MS,n=e.parentAliveCheck??isProcessAlive;M=setInterval(()=>{j||n(l)||(i.warn({parentPid:l,lockKind:c},`[boot] parent process gone — initiating graceful shutdown`),N().catch(e=>{i.error({err:e,parentPid:l},`[boot] parent-death shutdown failed`)}))},t),M.unref?.()}return{httpServer:S,destroy:N,lockDir:b,contentDir:e.contentDir,port:A,ready:v,degraded:y,didAutoInit:m,didGitInit:p,serverInstance:h}}function parseKeepaliveConnectionId(e){if(!e)return null;try{return validateAgentId(new URL(e,`http://localhost`).searchParams.get(`connectionId`))}catch{return null}}const MAX_ZIP_BYTES=102400;function resolveBundledSkillDir(){let e=[`../assets/skills/open-knowledge`,`./assets/skills/open-knowledge`],t=[];for(let n of e){let e=fileURLToPath(new URL(n,import.meta.url));if(existsSync(e))return e;t.push(e)}throw Error(`Bundled skill asset directory not found. Tried: ${t.join(`, `)}. This usually means the CLI build did not copy packages/server/assets into dist/assets. Run \`cd packages/cli && bun run build\` before publishing.`)}async function readCliVersion(){for(let e of[`../../cli/package.json`,`../package.json`]){let t=fileURLToPath(new URL(e,import.meta.url));if(!existsSync(t))continue;let n=await readFile(t,`utf-8`),r=JSON.parse(n);if(r.name===`@inkeep/open-knowledge`&&typeof r.version==`string`)return r.version}throw Error(`Could not resolve @inkeep/open-knowledge CLI version — no package.json with matching name found in candidate paths.`)}async function*walkFiles(e,t=e){let n=await readdir(e,{withFileTypes:!0});for(let r of n){let n=join(e,r.name);r.isDirectory()?yield*walkFiles(n,t):r.isFile()&&(yield relative(t,n))}}async function zipDirectory(e,t){let n=e.split(`/`).pop()??`open-knowledge`,r=new import_yazl.ZipFile;r.addEmptyDirectory(`${n}/`);let i=[];for await(let t of walkFiles(e))i.push(t);i.sort();for(let t of i){let i=join(e,t),a=`${n}/${t}`;r.addFile(i,a)}r.end(),await new Promise((e,n)=>{let i=createWriteStream(t);r.outputStream.pipe(i),i.on(`close`,()=>e()),i.on(`error`,n),r.outputStream.on(`error`,n)})}async function sha256OfFile(e){return new Promise((t,n)=>{let r=createHash(`sha256`),i=createReadStream(e);i.on(`data`,e=>r.update(e)),i.on(`end`,()=>t(r.digest(`hex`))),i.on(`error`,n)})}function extractMetadataVersion(e){let t=e.indexOf(`
|
|
138
|
+
`).map(e=>e.trim()).filter(Boolean):[]}catch(t){log.error({err:t},`[sync] failed to list conflicted files — aborting merge to avoid committing unresolved state`);try{await e.git.raw([`merge`,`--abort`])}catch(e){log.warn({err:e},`[sync] git merge --abort failed during cleanup`)}this.error=`Failed to detect conflict files — merge aborted`,this.pausedReason=void 0,this.transitionTo(`idle`);return}let n=[],r=[];for(let e of t){let t=join(this.projectDir,e),i=relative(this.contentDir,t);!i.startsWith(`..`)&&!this.contentFilter.isExcluded(i)?n.push(e):r.push(e)}for(let t of r)try{await e.git.raw([`checkout`,`--theirs`,`--`,t]),await e.git.raw([`add`,`--`,t]),log.info({file:t},`[sync] auto-resolved non-content conflict with theirs`)}catch(e){log.warn({err:e,file:t},`[sync] auto-resolve failed — escalating to content conflict`),n.push(t)}if(n.length>0){for(let e of n)this.conflictStore.addConflict({file:e,detectedAt:new Date().toISOString()});this.conflictCount=this.conflictStore.count(),this.pullTimer!==null&&(clearTimeout(this.pullTimer),this.pullTimer=null),this.pushTimer!==null&&(clearTimeout(this.pushTimer),this.pushTimer=null),this.transitionTo(`conflict`),log.warn({files:n},`[sync] content conflicts — sync paused until resolved`)}else try{await e.git.raw([`commit`,`--no-edit`]),this.lastSyncUtc=new Date().toISOString(),this.behind=0,this.transitionTo(`idle`),log.info({},`[sync] all conflicts auto-resolved — merge committed`)}catch(t){log.warn({err:t},`[sync] failed to commit after auto-resolving conflicts — aborting merge`);try{await e.git.raw([`merge`,`--abort`])}catch(e){log.warn({err:e},`[sync] git merge --abort failed during cleanup`)}this.transitionTo(`idle`)}}async abortMerge(){let e=createGitInstance(this.projectDir,{credentialArgs:this.credentialArgs});try{await e.git.raw([`merge`,`--abort`]),log.info({},`[sync] merge aborted`)}catch(e){log.warn({err:e},`[sync] git merge --abort failed — conflicts.json still cleared`)}this.conflictStore.clear(),this.conflictCount=0,this.transitionTo(`idle`),this.scheduleSaveState()}handleError(e){this.error=e.message,log.warn({class:e.class,subclass:e.subclass,retryable:e.retryable,rawStderr:e.rawStderr},`[sync-error] ${e.message}`),e.class===`auth`?(this.transitionTo(`auth-error`),this.pausedReason=`auth-error`):e.class===`semantic`&&e.subclass===`protected-branch`?(this.syncEnabled=!1,this.transitionTo(`disabled`),this.pausedReason=`protected-branch`):e.class===`local`&&e.subclass===`dirty-tree`?(this.consecutiveFailures++,this.transitionTo(`idle`),this.pausedReason=`dirty-tree`,this.schedulePush(0)):e.retryable?(this.consecutiveFailures++,this.transitionTo(`offline`)):(this.consecutiveFailures++,this.transitionTo(`idle`))}transitionTo(e){if(this.state===e)return;let t=this.state;this.state=e,log.info({from:t,to:e},`[sync] state: ${t} → ${e}`),this.onStateChange?.(e),this.cc1Broadcaster?.signal(`sync-status`)}scheduleSaveState(){this.stateSaveTimer===null&&(this.stateSaveTimer=setTimeout(()=>{this.stateSaveTimer=null,this.saveStateNow()},5e3))}saveStateNow(){try{let e={version:1,lastSyncUtc:this.lastSyncUtc,lastFetchUtc:this.lastFetchUtc,lastPushedSha:this.lastPushedSha,consecutiveFailures:this.consecutiveFailures,pausedReason:this.pausedReason,pausedSinceUtc:this.pausedReason?new Date().toISOString():void 0,inflightConflicts:this.conflictStore.list().map(e=>e.file),syncEnabled:this.syncEnabled};writeFileSync(this.statePath,JSON.stringify(e,null,2),`utf-8`)}catch(e){log.warn({err:e},`[sync] failed to persist sync state`)}}loadState(){if(existsSync(this.statePath))try{let e=readFileSync(this.statePath,`utf-8`),t=JSON.parse(e);if(t.version!==1)return;this.lastSyncUtc=t.lastSyncUtc??null,this.lastFetchUtc=t.lastFetchUtc??null,this.lastPushedSha=t.lastPushedSha??null,this.consecutiveFailures=t.consecutiveFailures??0,this.pausedReason=t.pausedReason,t.syncEnabled!==void 0&&(this.syncEnabled=t.syncEnabled);let n=t.inflightConflicts??[];if(n.length>0){for(let e of n)this.conflictStore.list().some(t=>t.file===e)||this.conflictStore.addConflict({file:e,detectedAt:new Date().toISOString()});this.conflictCount=this.conflictStore.count()}}catch(e){log.warn({err:e},`[sync] failed to load sync state`)}}};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:n=t,quiet:r=!0,debounce:i=2e3,maxDebounce:a=1e4,gitEnabled:o=!0,commitDebounceMs:s=3e4,wipRef:c=`refs/wip/main`,configHomedirOverride:l,enableTestRoutes:u=!1,shadowRepo:d,contentRoot:f,includePatterns:p=[`**/*.md`,`**/*.mdx`],excludePatterns:m=[],destroyTimeoutMs:h=1e4,localOpCliArgs:g,skipStateManifestCheck:_=!1}=e,v=getLogger(`server`);initTelemetry();let y=randomUUID(),b=resolve(t,`.open-knowledge`);if(acquireServerLock(b,{port:e.port??0,worktreeRoot:n,kind:e.lockKind??`interactive`,...e.parentPid!==void 0&&{parentPid:e.parentPid},capabilities:[`http`,`ws`]}),!_)try{assertCompatibleStateManifest({lockDir:b,shadowRepoDir:resolveShadowDir(n)})}catch(e){throw releaseServerLock(b),e}let x=createBasenameIndex(),S=(e,t)=>x.resolveEmbed(e,t),C,w,T,E,D,O,k=null,A=null,j=null,M=null,N=new Set,P=!1,F;function I(e){k?.signal(e)}try{C=createContentFilter({projectDir:n,contentDir:t,includePatterns:p,excludePatterns:m}),w=new BacklinkIndex({projectDir:n,contentDir:t,contentFilter:C}),T={current:d},E=createPersistenceExtension({contentDir:t,projectDir:n,gitEnabled:o,commitDebounceMs:s,wipRef:c,shadowRef:T,contentRoot:f,backlinkIndex:w,configHomedirOverride:l,getCurrentBranch:()=>ee?.getLastKnownBranch()??null,resolveEmbed:S,getPrincipal:()=>M,onAgentCommit:()=>k?.signal(`session-activity`),onDiskFlush:(e,t)=>k?.emitDiskAck(e,t),onConfigRejected:(e,t)=>k?.emitConfigValidationRejected(e,t)}),D=new Hocuspocus({quiet:r,debounce:i,maxDebounce:a,extensions:[E.extension]});let h=D.shouldUnloadDocument.bind(D);D.shouldUnloadDocument=e=>(P||N.has(e))&&h(e),F=async e=>{N.add(e);try{await D.unloadDocument(e)}finally{N.delete(e)}},k=new CC1Broadcaster(D),A=new AgentFocusBroadcaster(D),j=new AgentPresenceBroadcaster(D),O=new AgentSessionManager(D);let _=createLiveDerivedIndexExtension({backlinkIndex:w,signalChannel:I});D.configuration.extensions.push(_),D.configuration.extensions.push({__kind:`principal-auth`,async onAuthenticate(e){let t=e.token,n=parseHocuspocusAuthToken(t),r=n?.expectedServerInstanceId;if(typeof r==`string`&&r.length>0&&r!==y)throw new HocuspocusAuthRejection(`server-instance-mismatch`,`server instance mismatch: client claimed ${r}, this server is ${y}`);let i=n?.expectedBranch,a=getActiveBranch();if(typeof i==`string`&&i.length>0&&i!==a)throw new HocuspocusAuthRejection(`branch-mismatch`,`branch mismatch: client claimed ${i}, server is on ${a}`);if(!n)return;let o=e.context;typeof n.principalId==`string`&&(M&&n.principalId===M.id?o.principalId=M.id:M?console.warn(JSON.stringify({event:`principal-token-mismatch`,claimed:n.principalId,loaded:M.id})):o.principalId=n.principalId),typeof n.tabSessionId==`string`&&(o.tabSessionId=n.tabSessionId),o.kind=`human`}}),D.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 v=createApiExtension({hocuspocus:D,sessionManager:O,contentDir:t,contentFilter:C,serverInstanceId:y,getFileIndex:()=>J?J.getFileIndex():new Map,getAliasMap:()=>J?J.getAliasMap():new Map,enableTestRoutes:u,shadowRef:T,flushGitCommit:()=>E.flushPendingGitCommit(),getCurrentBranch:()=>ee?.getLastKnownBranch()??null,getDiskAckSVs:()=>k?.getLatestDiskAckSVsAsBase64()??{},contentRoot:f,backlinkIndex:w,signalChannel:I,agentFocusBroadcaster:A,agentPresenceBroadcaster:j,onAgentWrite:e.onAgentWrite,getSyncEngine:()=>Y,localOpCliArgs:g,projectDir:n,resolveEmbed:S,getPrincipal:()=>M,forceUnloadDocument:F});D.configuration.extensions.push(v),D.configuration.extensions.push(createServerObserverExtension({mdManager,schema,shadowRef:T,contentRoot:f,getCurrentBranch:()=>ee?.getLastKnownBranch()??null,resolveEmbed:S}))}catch(e){throw releaseServerLock(b),e}let L=null,R=new Map,z=[];function B(e,t){let n=resolve(e,`rescue`),r=resolve(n,`${t}${getDocExtension(t)}`);return r.startsWith(`${n}/`)?r:null}function V(e){let t=D.documents.get(e);if(!t)return null;let n=yXmlFragmentToProseMirrorRootNode(t.getXmlFragment(`default`),schema).toJSON(),r=mdManager.serialize(n),i=t.getMap(`metadata`).get(`frontmatter`);return prependFrontmatter(typeof i==`string`?i:``,r)}let H=(e,t)=>applyExternalChange(D,e,t,S);function U(e){switch(e.kind){case`rename`:return e.newDocName;case`asset-create`:case`asset-delete`:return e.relativePath;default:return e.docName}}async function W(e){try{switch(e.kind){case`create`:v.info({docName:e.docName},`[reconcile] create: ${e.docName}`),w.updateDocumentFromMarkdown(e.docName,e.content),w.saveToDisk().catch(t=>{console.warn(`[backlinks] Failed to persist create for ${e.docName}:`,t)}),I(`files`),I(`backlinks`),I(`graph`);break;case`update`:{let{docName:t,content:n}=e,r=D.documents.get(t);if(!r){w.updateDocumentFromMarkdown(t,n),w.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist closed-doc update for ${t}:`,e)}),I(`backlinks`),I(`graph`);return}let i=getReconciledBase(t)??``,a=V(t)??i,o=reconcile({docName:t,base:i,ours:a,theirs:n}),s=contentHash(i).slice(0,6),c=contentHash(a).slice(0,6),l=contentHash(n).slice(0,6);switch(v.info({docName:t,base:s,ours:c,theirs:l,result:o.kind},`[reconcile] ${t} base=${s} ours=${c} theirs=${l} result=${o.kind}`),o.kind){case`noop`:w.updateDocumentFromMarkdown(t,n),w.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist noop update for ${t}:`,e)}),I(`backlinks`),I(`graph`);break;case`clean`:try{H(t,o.newContent),setReconciledBase(t,o.newContent),incrementReconcile(),w.updateDocumentFromMarkdown(t,n),w.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist clean update for ${t}:`,e)}),I(`backlinks`),I(`graph`)}catch(e){v.error({err:e,docName:t},`[reconcile] failed to apply clean content to Y.Doc for ${t}`),setReconciledBase(t,n)}break;case`merged`:try{H(t,o.newContent),setReconciledBase(t,o.newContent),incrementReconcile(),w.updateDocumentFromMarkdown(t,n),w.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist merged update for ${t}:`,e)}),I(`backlinks`),I(`graph`)}catch(e){v.error({err:e,docName:t},`[reconcile] failed to apply merged content to Y.Doc for ${t}`),setReconciledBase(t,n)}break;case`conflicts`:try{H(t,o.newContent),setReconciledBase(t,o.newContent),incrementReconcile(),incrementConflict(),w.updateDocumentFromMarkdown(t,n),w.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist conflict update for ${t}:`,e)}),I(`backlinks`),I(`graph`)}catch(e){v.error({err:e,docName:t},`[reconcile] failed to apply conflict content to Y.Doc for ${t}`),setReconciledBase(t,n)}break;case`refused`:{incrementConflict();let e=r.getMap(`lifecycle`);e.set(`status`,`conflict`),e.set(`reason`,o.reason);break}}break}case`delete`:{let{docName:t}=e,n=D.documents.get(t);if(!n){w.deleteDocument(t),w.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist closed-doc delete for ${t}:`,e)}),I(`files`),I(`backlinks`),I(`graph`);return}let r=getReconciledBase(t)??``,i=V(t)??``,a=i!==r;if(a&&T.current){let e=T.current,n=ee?.getLastKnownBranch()??`main`;queueMicrotask(()=>{saveInMemoryCheckpoint(e,f??``,{kind:`external-change-rescue`,docName:t,contents:i,label:`External change recovered @ ${new Date().toISOString()}`,branch:n,metadata:{incomingDiskSha:``}}).then(()=>{incrementRescueBuffer(),v.info({docName:t},`[reconcile] rescue checkpoint saved (delete): ${t}`)}).catch(e=>{v.error({docName:t,err:e},`[reconcile] rescue checkpoint write failed: ${t}`)})})}n.getMap(`lifecycle`).set(`status`,`deleted-upstream`),deleteReconciledBase(t),w.deleteDocument(t),w.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist delete for ${t}:`,e)}),v.info({docName:t,isDirty:a},`[reconcile] delete: ${t} (dirty=${a})`),D.closeConnections(t),await F(n),I(`files`),I(`backlinks`),I(`graph`);break}case`rename`:{let{oldDocName:t,newDocName:n,content:r}=e,i=D.documents.get(t);if(deleteReconciledBase(t),setReconciledBase(n,r),w.renameDocument(t,n,r),w.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist rename for ${t} -> ${n}:`,e)}),i){let e=i.getMap(`lifecycle`);e.set(`status`,`renamed`),e.set(`newPath`,n)}v.info({oldDocName:t,newDocName:n},`[reconcile] rename: ${t} → ${n}`),I(`files`),I(`backlinks`),I(`graph`);break}case`conflict`:{let{docName:t}=e,n=D.documents.get(t);if(!n)return;let r=n.getMap(`lifecycle`);r.set(`status`,`conflict`),r.set(`reason`,`conflict-markers`),v.info({docName:t},`[reconcile] conflict markers detected: ${t}`);break}case`asset-create`:x.add(e.relativePath),I(`files`);break;case`asset-delete`:x.remove(e.relativePath),I(`files`);break;default:assertNeverDiskEvent(e)}}catch(t){let n=U(e);v.error({err:t,kind:e.kind,label:n},`[reconcile] failed to handle ${e.kind} for ${n}`)}}let G=[];async function K(e){if(isBatchInProgress()){G.push(e);return}await W(e)}async function q(){let e=G.splice(0,G.length);for(let t of e)await W(t)}let J=null,ee=null,Y=null,X=null;async function Z(e){if(D.documents.size===0)return;let t=!1,n=new Promise(e=>{D.configuration.extensions.push({async afterUnloadDocument({instance:n}){!t&&n.getDocumentsCount()===0&&(t=!0,e())}})}),r=Array.from(D.documents.keys());D.closeConnections(),D.flushPendingStores();for(let e of D.documents.values())e.getConnectionsCount()===0&&D.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 i,a=new Promise((n,a)=>{i=setTimeout(()=>{t=!0;let n=Array.from(D.documents.keys()),i=[],o=[];if(T.current){for(let e of n)if(!(isSystemDoc(e)||isConfigDoc(e)))try{let t=V(e);if(t===null){v.warn({docName:e},`[rescue] skipping ${e} — document dropped from map mid-rescue`),o.push(e);continue}let n=B(T.current.gitDir,e);if(!n){v.warn({docName:e,gitDir:T.current.gitDir},`[rescue] path-traversal guard rejected docName: ${e}`),o.push(e);continue}mkdirSync(dirname(n),{recursive:!0}),writeFileSync(n,t,`utf-8`),incrementRescueBuffer(),i.push(e),v.info({docName:e},`[rescue] rescue buffer saved on flush timeout: ${e}`)}catch(t){o.push(e),v.error({err:t,docName:e},`[rescue] failed to write rescue buffer for ${e}`)}}else v.warn({stillLoadedCount:n.length},`[rescue] shadow repo unavailable at flush timeout — ${n.length} doc(s) will be lost: [${n.join(`, `)}]`),o.push(...n);let s=i.length>0||o.length>0?` — rescued [${i.join(`, `)}]${o.length>0?`, lost [${o.join(`, `)}]`:``}`:``;a(Error(`flushAllStoresAndWait timeout after ${e}ms — ${n.length}/${r.length} docs did not unload: [${n.join(`, `)}]${s}`))},e)});try{await Promise.race([n,a])}finally{i!==void 0&&clearTimeout(i)}}async function te(){return X||(X=(async()=>{let e=Date.now(),t=[];P=!0;let r,i=await Promise.race([re.then(()=>`completed`,e=>(v.debug({err:e},`[server] init incomplete during shutdown`),`failed`)),new Promise(e=>{r=setTimeout(()=>e(`timeout`),5e3)})]);r!==void 0&&clearTimeout(r),i===`timeout`&&v.warn({},`[server] init did not complete within 5s during shutdown`);let a=D.documents.size;try{try{try{ee&&=(await ee.unsubscribe(),null),J&&=(await J.unsubscribe(),null);for(let{docName:e,cleanup:t}of z)try{await t()}catch(t){v.warn({err:t,docName:e},`[server] failed to stop config-file-watcher for ${e}`)}z.length=0}catch(e){t.push({phase:`watcher-unsubscribe`,error:e instanceof Error?e.message:String(e)}),v.error({err:e},`[server] shutdown phase-1 watcher unsubscribe failed`)}try{k?.destroy(),j?.destroy(),L&&=(await L.disconnect(),null);for(let[e,t]of R)try{await t.disconnect()}catch(t){v.warn({err:t,docName:e},`[server] failed to disconnect ${e} during shutdown`)}R.clear()}catch(e){t.push({phase:`cc1-teardown`,error:e instanceof Error?e.message:String(e)}),v.error({err:e},`[server] shutdown phase-1b CC1 teardown failed`)}try{await O.closeAll()}catch(e){t.push({phase:`agent-session-drain`,error:e instanceof Error?e.message:String(e)}),v.error({err:e},`[server] shutdown phase-2 agent session drain failed`)}try{await Z(h)}catch(e){t.push({phase:`flush-all-stores`,error:e instanceof Error?e.message:String(e)}),v.error({err:e},`[server] shutdown phase-3 flush failed`)}let e;try{await Promise.race([(async()=>{await E.flushPendingGitCommit(),await E.waitForPendingCommits()})(),new Promise((t,n)=>{e=setTimeout(()=>n(Error(`L2 git flush timeout`)),h)})])}catch(e){t.push({phase:`git-commit-flush`,error:e instanceof Error?e.message:String(e)}),v.error({err:e},`[server] shutdown phase-4 git commit flush failed`)}finally{e!==void 0&&clearTimeout(e)}try{Y&&=(await Y.destroy(),null)}catch(e){t.push({phase:`sync-engine-stop`,error:e instanceof Error?e.message:String(e)}),v.error({err:e},`[server] shutdown sync-engine-stop failed`)}}finally{if(T.current){try{let e=(await esm_default({baseDir:n,timeout:{block:5e3}}).revparse(`HEAD`)).trim();e&&writeFileSync(resolve(T.current.gitDir,`last-known-head`),e,`utf-8`)}catch{}try{destroyShadowRepo(T.current)}catch(e){t.push({phase:`shadow-repo-release`,error:e instanceof Error?e.message:String(e)}),v.error({err:e},`[server] shutdown phase-5 destroyShadowRepo failed`)}}let r=Date.now()-e;t.length===0?v.info({documentCount:a,durationMs:r},`[server] shutdown flushed ${a} documents in ${r}ms`):v.warn({documentCount:a,durationMs:r,phaseErrors:t},`[server] shutdown flushed ${a} documents in ${r}ms with ${t.length} phase error(s)`)}}finally{try{releaseServerLock(b)}catch(e){t.push({phase:`server-lock-release`,error:e instanceof Error?e.message:String(e)}),v.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)})}}})(),X)}let Q=[];async function ne(){try{M=await loadPrincipal(t),v.info({principalId:M.id},`[server] principal loaded`)}catch(e){v.warn({err:e},`[server] principal load failed — browser writes will use SERVICE_WRITER`)}if(!T.current)try{T.current=await initShadowRepo(n),v.info({gitDir:T.current.gitDir},`[server] history repo initialized at ${T.current.gitDir}`)}catch(e){v.error({err:e},`[server] history repo init failed`),Q.push(`shadow-repo`)}if(T.current)try{await shadowGit(T.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`)){v.warn({},`[server] history repo appears corrupted — reinitializing`);try{T.current=await initShadowRepo(n)}catch(e){v.error({err:e},`[server] history repo reinit failed`),T.current=void 0,Q.includes(`shadow-repo`)||Q.push(`shadow-repo`)}}else v.error({err:e},`[server] history repo check failed (transient?)`)}if(T.current)try{let e=resolve(T.current.gitDir,`last-known-head`),t=null;try{t=readFileSync(e,`utf-8`).trim()||null}catch{}let r=null;try{r=(await esm_default({baseDir:n,timeout:{block:1e4}}).revparse(`HEAD`)).trim()||null}catch{}if(r!==null){if(r!==t){let e=`main`;try{let t=(await esm_default({baseDir:n,timeout:{block:1e4}}).raw(`rev-parse`,`--abbrev-ref`,`HEAD`)).trim();t&&t!==`HEAD`&&(e=t)}catch{}v.info({lastKnownHead:t,currentHead:r,branch:e},`[head-drift] lastKnownHead=${t??`null`}, currentHead=${r}, action=import`);try{await commitUpstreamImport(T.current,f??``,t,r,e),incrementUpstreamImport()}catch(e){v.warn({err:e},`[head-drift] commitUpstreamImport failed — continuing`)}}else v.info({currentHead:r},`[head-drift] lastKnownHead=${t??`null`}, currentHead=${r}, action=noop`);try{writeFileSync(e,r,`utf-8`)}catch(e){v.warn({err:e},`[head-drift] failed to write last-known-head`)}}}catch(e){v.warn({err:e},`[head-drift] check failed — continuing`)}try{let e=recoverPendingManagedRename(t);e.recovered&&e.journal&&v.warn({sourceDocName:e.journal.sourceDocName,destinationDocName:e.journal.destinationDocName,restoredDocNames:e.restoredDocNames},`[managed-rename] recovered pending rename ${e.journal.sourceDocName} -> ${e.journal.destinationDocName}`)}catch(e){v.error({err:e},`[server] managed rename recovery failed`),Q.push(`managed-rename-recovery`)}try{let e=cleanupOrphanUploadTempfiles(t);(e.deleted>0||e.errors>0)&&v.info({scanned:e.scanned,deleted:e.deleted,errors:e.errors},`[upload-tempfile-sweep] swept ${e.deleted} orphan tempfile(s)`)}catch(e){v.error({err:e},`[server] upload-tempfile sweep failed`),Q.push(`upload-tempfile-sweep`)}try{L=await D.openDirectConnection(SYSTEM_DOC_NAME),k?.emitServerInfo(y,getActiveBranch())}catch(e){v.error({err:e},`[server] failed to open __system__ direct connection — CC1 push disabled`),Q.push(`cc1-push`)}for(let e of CONFIG_DOC_NAMES)try{let t=await D.openDirectConnection(e);R.set(e,t)}catch(t){v.error({err:t,docName:e},`[server] failed to open ${e} direct connection — config bind degraded`),Q.push(`config-doc:${e}`)}let e=new Map([[CONFIG_DOC_NAME_WORKSPACE,resolveConfigPath(`workspace`,n)],[CONFIG_DOC_NAME_USER,resolveConfigPath(`user`,n,l)]]);for(let t of CONFIG_DOC_NAMES){let n=e.get(t);if(n)try{v.info({docName:t,path:n},`[config-file-watcher] starting`);let e=await startConfigFileWatcher(n,e=>{let n=D.documents.get(t);v.info({docName:t,hasDocument:n!==void 0,contentLength:e.length},`[config-file-watcher] file changed`);let r=applyExternalConfigChange(n??null,t,e,E.configPersistenceCtx);v.info({docName:t,outcome:r},`[config-file-watcher] applyExternalConfigChange outcome`)});z.push({docName:t,cleanup:e}),v.info({docName:t,path:n},`[config-file-watcher] started`)}catch(e){v.warn({err:e,docName:t,path:n},`[config-file-watcher] failed to start for ${t}`),Q.push(`config-file-watcher:${t}`)}}let r=resolveGitDir(n),i=r?readBranchFromHead(r)??`main`:`main`;switchReconciledBaseScope(i),w.switchBranch(i);try{J=await startWatcher(t,K,C),w.rebuildFromDisk(getActiveBranch()),w.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist startup cache for ${getActiveBranch()}:`,e)});let e=0;try{seedBasenameIndex({contentDir:t,contentFilter:C,basenameIndex:x,onSkip:(t,n,r)=>{e++,v.warn({reason:t,code:n,path:r},`[basename-index] skipped entry during seed (${t}${n?` ${n}`:``})`)}}),e>0&&(v.warn({count:e},`[basename-index] startup seed completed with ${e} skipped entries — embeds under inaccessible subtrees will not resolve`),Q.push(`basename-index-partial`))}catch(e){v.error({err:e},`[basename-index] startup seed failed`),Q.push(`basename-index`)}}catch(e){v.error({err:e},`[server] disk bridge watcher failed to start`),Q.push(`file-watcher`)}try{ee=await startHeadWatcher(n,async({trigger:e})=>{if(v.info({trigger:e},`[batch] begin trigger=${e}`),incrementBatch(),D.flushPendingStores(),await E.flushPendingGitCommit(),setBatchInProgress(!0),T.current){let e=getActiveBranch(),t=resolveGitDir(n),r=t?readBranchFromHead(t)??e:e,i=[];for(let[e,t]of D.documents){if(isSystemDoc(e)||isConfigDoc(e))continue;let n=null;if(t.transact(()=>{n=V(e)},PARK_SNAPSHOT_ORIGIN),n===null)continue;let r=getReconciledBase(e)??n;i.push({docName:e,markdown:n,diskSnapshot:r})}if(i.length>0)try{let t=await parkBranch(T.current,e,SERVICE_WRITER.id,i,r);t&&(incrementPark(),v.info({count:i.length,branch:e,sha:t.slice(0,8)},`[history] parked ${i.length} docs on ${e} → ${t.slice(0,8)}`))}catch(e){v.error({err:e},`[shadow] park failed`)}}},async e=>{let n=G.length,r=e.newBranch??`main`;if(v.info({kind:e.batchKind,headMoved:e.headMoved,docs:n,timeout:!!e.timeout},`[batch] end kind=${e.batchKind} headMoved=${e.headMoved} docs=${n}${e.timeout?` timeout`:``}`),e.batchKind===`within-branch`)setBatchInProgress(!1),await q(),await E.flushDeferredStores(`within-branch`);else{incrementBranchSwitch(),G.splice(0,G.length),switchReconciledBaseScope(r),w.switchBranch(r),C.rebuildDirCount();try{let e=0;x.clear(),seedBasenameIndex({contentDir:t,contentFilter:C,basenameIndex:x,onSkip:(t,n,i)=>{e++,v.warn({reason:t,code:n,path:i,branch:r},`[basename-index] skipped entry during branch-switch reseed (${t}${n?` ${n}`:``})`)}}),e>0&&(v.warn({count:e,branch:r},`[basename-index] branch-switch reseed completed with ${e} skipped entries — embeds under inaccessible subtrees will not resolve on this branch`),Q.includes(`basename-index-partial`)||Q.push(`basename-index-partial`))}catch(e){v.error({err:e,branch:r},`[basename-index] branch-switch reseed failed`)}for(let[e,n]of D.documents)if(!(isSystemDoc(e)||isConfigDoc(e)))try{let i=safeContentPath(e,t);if(!existsSync(i)){let t=getReconciledBase(e)??``,i=V(e)??``;if(i!==t&&T.current){let t=T.current;queueMicrotask(()=>{saveInMemoryCheckpoint(t,f??``,{kind:`external-change-rescue`,docName:e,contents:i,label:`External change recovered @ ${new Date().toISOString()}`,branch:r,metadata:{incomingDiskSha:``}}).then(()=>{incrementRescueBuffer(),v.info({docName:e},`[reconcile] rescue checkpoint saved on branch switch: ${e}`)}).catch(t=>{v.error({docName:e,err:t},`[reconcile] rescue checkpoint write failed: ${e}`)})})}n.getMap(`lifecycle`).set(`status`,`deleted-upstream`),v.info({docName:e,branch:r},`[branch-switch] tombstone: ${e} (not on ${r})`);continue}let a=readFileSync(i,`utf-8`);H(e,a),setReconciledBase(e,a),v.info({docName:e},`[branch-switch] reset: ${e}`)}catch(t){v.error({err:t,docName:e},`[branch-switch] failed to reset ${e}`)}if(v.info({branch:r,docCount:D.documents.size},`[branch-switch] loaded branch ${r} (${D.documents.size} docs)`),w.rebuildFromDisk(r),w.saveToDisk(r).catch(e=>{console.warn(`[backlinks] Failed to persist branch cache for ${r}:`,e)}),T.current&&e.batchKind===`cross-branch`){let e=0;for(let[t]of D.documents)if(!(isSystemDoc(t)||isConfigDoc(t)))try{let n=await readParkedState(T.current,r,SERVICE_WRITER.id,t);if(!n||n.markdown===n.diskSnapshot)continue;let i=getReconciledBase(t);if(!i)continue;let a=reconcile({docName:t,base:n.diskSnapshot,ours:n.markdown,theirs:i});switch(a.kind){case`merged`:case`clean`:H(t,a.newContent),setReconciledBase(t,a.newContent),e++;break;case`conflicts`:H(t,a.newContent),setReconciledBase(t,a.newContent),incrementConflict(),e++;break;case`noop`:case`refused`:break}}catch(e){v.error({err:e,docName:t},`[branch-switch] restore WIP failed for ${t}`)}e>0&&v.info({count:e,branch:r},`[branch-switch] restored ${e} parked docs on ${r}`)}if(e.oldBranch?.startsWith(`detached-`)&&T.current)try{let t=shadowGit(T.current),n=(await t.raw(`for-each-ref`,`refs/wip/${e.oldBranch}/`,`--format=%(refname)`)).trim();if(n){for(let e of n.split(`
|
|
139
|
+
`))e&&await t.raw(`update-ref`,`-d`,e);v.info({context:e.oldBranch},`[branch-switch] cleaned up detached context ${e.oldBranch}`)}}catch(e){v.error({err:e},`[branch-switch] detached cleanup failed`)}setBatchInProgress(!1),await E.flushDeferredStores(`discard-stale`),k?.emitBranchSwitched(r)}if(e.headMoved&&e.newHead&&T.current&&n>0){let t=f??`.`;try{let n=await commitUpstreamImport(T.current,t,e.oldHead,e.newHead,r);incrementUpstreamImport(),v.info({oldHead:e.oldHead?.slice(0,8)??`null`,newHead:e.newHead.slice(0,8),sha:n.slice(0,8)},`[history] upstream-import from ${e.oldHead?.slice(0,8)??`null`}..${e.newHead.slice(0,8)} → ${n.slice(0,8)}`)}catch(e){v.error({err:e},`[shadow] upstream-import failed`)}}})}catch(e){v.error({err:e},`[server] HEAD watcher failed to start`),Q.push(`head-watcher`)}let a=g?.[0]??`open-knowledge`,o=[`-c`,`credential.helper=!${g&&g.length>1?g.join(` `):a} auth git-credential`];try{Y=new SyncEngine({projectDir:n,contentDir:t,contentFilter:C,contentRoot:f,credentialArgs:o,cc1Broadcaster:k,setBatchInProgress:e=>{setBatchInProgress(e),e||E.flushDeferredStores(`within-branch`).catch(e=>{v.error({err:e},`[persistence] deferred store drain failed after sync batch`)})},onStateChange:e=>{v.info({state:e},`[sync] state → ${e}`)}}),await Y.start()}catch(e){v.warn({err:e},`[server] SyncEngine failed to start — sync disabled`),Y=null}}let re=ne();return{hocuspocus:D,sessionManager:O,cc1Broadcaster:k,agentFocusBroadcaster:A,agentPresenceBroadcaster:j,contentFilter:C,basenameIndex:x,serverInstanceId:y,destroy:te,ready:re,degraded:Q,lockDir:b,get syncEngine(){return Y}}}const DEFAULT_PARENT_DEATH_POLL_MS=5e3,DEFAULT_IDLE_THRESHOLD_MS=1800*1e3;async function bootServer(e){let t=e.skipAutoInit??!1,n=e.attachUiSibling??!0,r=e.idleShutdownMs,i=e.log??getLogger(`boot`),a=process.env.OK_LOCK_KIND===`mcp-spawned`||process.env.OK_LOCK_KIND===`interactive`?process.env.OK_LOCK_KIND:void 0,o=process.env.OK_PARENT_PID,s=typeof o==`string`&&/^[0-9]+$/.test(o)?Number.parseInt(o,10):void 0,c=e.lockKind??a??`interactive`,l=e.parentPid??s;initTelemetry();let{createServer:u}=await import(`node:http`),{WebSocketServer:d}=await import(`./wrapper-DYxqFKGF.mjs`),{updateServerLockPort:f}=await import(`./server-lock-n3Y5JWNv-DXpg9_eU.mjs`).then(e=>e.a),p=!1;!t&&e.ensureProjectGitFn&&(p=!!(await e.ensureProjectGitFn()).didInit);let m=!1;if(!t&&e.autoInitFn)try{m=!!await e.autoInitFn()}catch(e){i.warn({err:e},`autoInitFn failed`)}let h=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,includePatterns:e.includePatterns,excludePatterns:e.excludePatterns,destroyTimeoutMs:e.destroyTimeoutMs,localOpCliArgs:e.localOpCliArgs,onAgentWrite:e.onAgentWrite,lockKind:c,parentPid:l,skipStateManifestCheck:e.skipStateManifestCheck}),{hocuspocus:g,destroy:_,ready:v,degraded:y,lockDir:b,agentPresenceBroadcaster:x}=h,S=u((e,t)=>{let n=e.url?.split(`?`)[0];if(n?.startsWith(`/api/`)){g.hooks(`onRequest`,{request:e,response:t}).then(()=>{t.writableEnded||t.headersSent||(t.statusCode=404,t.setHeader(`Content-Type`,`application/json`),t.end(JSON.stringify({error:`API route not found`,path:n})))}).catch(e=>{i.error({err:e},`Unhandled onRequest error`),!t.writableEnded&&!t.headersSent?(t.writeHead(500),t.end(`Internal server error`)):t.writableEnded||t.end()});return}t.writeHead(404,{"Content-Type":`application/json`}),t.end(JSON.stringify({error:"Not found. The React UI is served by `ok ui` (default port 3000).",path:n??`/`}))}),C=new d({noServer:!0});C.on(`error`,e=>{i.error({err:e},`WebSocketServer error`)});let w=e.keepaliveGraceMs??1e4,T=new Map,E=new Set,D=!1;S.on(`upgrade`,(e,t,n)=>{if(e.url?.startsWith(`/collab/keepalive`)){t.on(`error`,e=>{handleCollabSocketError(e)||i.error({err:e},`MCP keepalive socket error`)}),C.handleUpgrade(e,t,n,t=>{let n=parseKeepaliveConnectionId(e.url);if(n){let e=T.get(n);e!==void 0&&(clearTimeout(e),T.delete(n),i.info({connectionId:n},`[keepalive] reconnect during grace — timer cancelled`))}let r=setInterval(()=>{try{t.ping()}catch{}},3e4);r.unref?.();let a=n?setInterval(()=>{x?.bumpPresenceTs(toBroadcasterKey(n))},3e3):null;a?.unref?.(),t.on(`close`,()=>{if(clearInterval(r),a!==null&&clearInterval(a),!n)return;let e=setTimeout(()=>{if(T.delete(n),D)return;let e=(async()=>{i.info({connectionId:n},`[keepalive] grace expired — cleaning up sessions`);try{await h.sessionManager.closeAllForAgent(n)}catch(e){i.error({err:e,connectionId:n},`[keepalive] closeAllForAgent failed`)}try{h.agentFocusBroadcaster?.clearFocus(n)}catch(e){i.error({err:e,connectionId:n},`[keepalive] clearFocus failed`)}try{x?.clearPresence(toBroadcasterKey(n))}catch(e){i.error({err:e,connectionId:n},`[keepalive] clearPresence failed`)}})();E.add(e),e.finally(()=>E.delete(e))},w);e.unref?.(),T.set(n,e),i.info({connectionId:n,graceMs:w},`[keepalive] disconnected — grace timer started`)}),t.on(`error`,e=>{handleCollabSocketError(e)||i.error({err:e},`MCP keepalive WS error`),t.terminate()})});return}e.url?.startsWith(`/collab`)&&(t.on(`error`,e=>{handleCollabSocketError(e)||i.error({err:e},`Upgrade socket error`)}),C.handleUpgrade(e,t,n,t=>{let n=g.handleConnection(t,e);t.on(`message`,e=>{n.handleMessage((e instanceof ArrayBuffer,new Uint8Array(e)))}),t.on(`close`,(e,t)=>{n.handleClose({code:e,reason:t.toString()})}),t.on(`error`,e=>{handleCollabSocketError(e)||i.error({err:e},`WebSocket error`),t.terminate()})}))});let O=null;r!==null&&(O=attachIdleShutdown({httpServer:S,thresholdMs:r??DEFAULT_IDLE_THRESHOLD_MS,log:i,onShutdown:(e.idleShutdownHandler??(e=>async()=>{await e()}))(async()=>{await _()})})),await new Promise((t,n)=>{let r=e=>n(e);S.once(`error`,r),S.listen(e.port,e.host,()=>{S.removeListener(`error`,r),t()})});let k=S.address(),A=typeof k==`object`&&k?k.port:e.port??0;if(f(b,A),n&&e.spawnUiSiblingFn)try{await e.spawnUiSiblingFn({lockDir:b,log:i})}catch(e){i.warn({err:e},`spawnUiSiblingFn failed`)}let j=!1,M=null,N=async()=>{if(!j){j=!0,D=!0,M!==null&&(clearInterval(M),M=null);try{O?.detach()}catch(e){i.warn({err:e},`[bootServer.destroy] idleHandle.detach failed`)}for(let e of T.values())clearTimeout(e);T.clear(),E.size>0&&await Promise.allSettled([...E]);try{try{S.closeAllConnections?.()}catch(e){i.warn({err:e},`[bootServer.destroy] closeAllConnections failed`)}let e;try{await Promise.race([new Promise(e=>S.close(()=>e())),new Promise((t,n)=>{e=setTimeout(()=>n(Error(`httpServer.close timeout after 10s`)),1e4)})]).catch(e=>{i.warn({err:e},`[bootServer.destroy] httpServer.close did not complete within timeout`)})}finally{e!==void 0&&clearTimeout(e)}}finally{await _(),await shutdownTelemetry()}}};if(l!==void 0){let t=e.parentDeathPollMs??DEFAULT_PARENT_DEATH_POLL_MS,n=e.parentAliveCheck??isProcessAlive;M=setInterval(()=>{j||n(l)||(i.warn({parentPid:l,lockKind:c},`[boot] parent process gone — initiating graceful shutdown`),N().catch(e=>{i.error({err:e,parentPid:l},`[boot] parent-death shutdown failed`)}))},t),M.unref?.()}return{httpServer:S,destroy:N,lockDir:b,contentDir:e.contentDir,port:A,ready:v,degraded:y,didAutoInit:m,didGitInit:p,serverInstance:h}}function parseKeepaliveConnectionId(e){if(!e)return null;try{return validateAgentId(new URL(e,`http://localhost`).searchParams.get(`connectionId`))}catch{return null}}const MAX_ZIP_BYTES=102400;function resolveBundledSkillDir(){let e=[`../assets/skills/open-knowledge`,`./assets/skills/open-knowledge`],t=[];for(let n of e){let e=fileURLToPath(new URL(n,import.meta.url));if(existsSync(e))return e;t.push(e)}throw Error(`Bundled skill asset directory not found. Tried: ${t.join(`, `)}. This usually means the CLI build did not copy packages/server/assets into dist/assets. Run \`cd packages/cli && bun run build\` before publishing.`)}async function readCliVersion(){for(let e of[`../../cli/package.json`,`../package.json`]){let t=fileURLToPath(new URL(e,import.meta.url));if(!existsSync(t))continue;let n=await readFile(t,`utf-8`),r=JSON.parse(n);if(r.name===`@inkeep/open-knowledge`&&typeof r.version==`string`)return r.version}throw Error(`Could not resolve @inkeep/open-knowledge CLI version — no package.json with matching name found in candidate paths.`)}async function*walkFiles(e,t=e){let n=await readdir(e,{withFileTypes:!0});for(let r of n){let n=join(e,r.name);r.isDirectory()?yield*walkFiles(n,t):r.isFile()&&(yield relative(t,n))}}async function zipDirectory(e,t){let n=e.split(`/`).pop()??`open-knowledge`,r=new import_yazl.ZipFile;r.addEmptyDirectory(`${n}/`);let i=[];for await(let t of walkFiles(e))i.push(t);i.sort();for(let t of i){let i=join(e,t),a=`${n}/${t}`;r.addFile(i,a)}r.end(),await new Promise((e,n)=>{let i=createWriteStream(t);r.outputStream.pipe(i),i.on(`close`,()=>e()),i.on(`error`,n),r.outputStream.on(`error`,n)})}async function sha256OfFile(e){return new Promise((t,n)=>{let r=createHash(`sha256`),i=createReadStream(e);i.on(`data`,e=>r.update(e)),i.on(`end`,()=>t(r.digest(`hex`))),i.on(`error`,n)})}function extractMetadataVersion(e){let t=e.indexOf(`
|
|
139
140
|
---`,4);if(!e.startsWith(`---
|
|
140
141
|
`)||t<0)return;let n=e.slice(4,t),r=n.search(/^metadata:/m);if(r<0)return;let i=n.slice(r).split(`
|
|
141
142
|
`).slice(1);for(let e of i){if(/^[^\s]/.test(e))break;let t=e.match(/^\s+version:\s*["']?([^"'\s]+)["']?$/);if(t)return t[1]}}async function validateSkillZip(e,t,n={}){let r=statSync(e).size;if(r>MAX_ZIP_BYTES)throw Error(`Built ${e} is ${r} bytes, exceeds ${MAX_ZIP_BYTES}-byte ceiling`);let i=await sha256OfFile(e),a=await readFile(join(resolveBundledSkillDir(),`SKILL.md`),`utf-8`);if(!/^name:\s+open-knowledge$/m.test(a.slice(0,1e3)))throw Error("SKILL.md frontmatter `name:` does not match 'open-knowledge'. Check packages/server/assets/skills/open-knowledge/SKILL.md frontmatter.");let o=extractMetadataVersion(a);if(!n.skipVersionCheck){if(!o)throw Error("SKILL.md metadata.version missing. Add it to packages/server/assets/skills/open-knowledge/SKILL.md or run `bash scripts/sync-skill-version.sh`.");if(o!==t)throw Error(`SKILL.md metadata.version (${o}) does not match CLI version (${t}). Run \`bash scripts/sync-skill-version.sh\` after bumping package versions.`)}return{size:r,sha256:i,skillVersion:o}}async function buildSkillZip(e={}){let t=e.sourceDir??resolveBundledSkillDir(),n=e.outputPath??join(process.cwd(),`openknowledge.skill`),r=await readCliVersion();await zipDirectory(t,n);let{size:i,sha256:a,skillVersion:o}=await validateSkillZip(n,r,{skipVersionCheck:e.skipVersionCheck});return{outputPath:n,size:i,sha256:a,cliVersion:r,skillVersion:o}}function detectClaudeDesktopPresence(e={}){let t=e.home??homedir(),n=e.platformName??process.platform,r=e.env??process.env;return n===`darwin`?existsSync(join(t,`Library`,`Application Support`,`Claude`)):n===`win32`?existsSync(join(r.APPDATA??join(t,`AppData`,`Roaming`),`Claude`)):!1}const execFileAsync=promisify(execFile);var ProjectGitInitError=class extends Error{stderr;constructor(e,t=``,n){super(e,n),this.name=`ProjectGitInitError`,this.stderr=t}};async function ensureProjectGit(e){let t=resolve(e),n=resolve(t,`.git`);if(existsSync(n))return{didInit:!1};let r=``;try{r=(await execFileAsync(`git`,[`init`,`--initial-branch=main`,t])).stderr??``}catch(e){let n=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)}`,n,{cause:e})}if(!existsSync(resolve(n,`HEAD`)))throw new ProjectGitInitError(`git init reported success but ${n}/HEAD is missing (partial init detected)`,r);return console.log(`[project-git] initialized .git/ at ${t} (branch: main)`),{didInit:!0}}const SIDECAR_FILENAME=`skill-installed-version`,SKILLS_CLI_SPEC=`skills@~1.5.0`,DEFAULT_TIMEOUT_MS=6e4,VERSION_RE=/^\d+\.\d+\.\d+(?:[-+][\w.-]+)?$/;async function readServerPackageVersion(){let e=await readFile(fileURLToPath(new URL(`../package.json`,import.meta.url)),`utf-8`),t=JSON.parse(e);if(typeof t.version!=`string`||t.version.length===0)throw Error(`@inkeep/open-knowledge-server/package.json missing version field`);return t.version}function sidecarPath(e){return join(e,`.open-knowledge`,SIDECAR_FILENAME)}async function readSidecarVersion(e){try{let t=(await readFile(sidecarPath(e),`utf-8`)).trim();return t.length===0||!VERSION_RE.test(t)?null:t}catch(e){if(e.code===`ENOENT`)return null;throw e}}async function writeSidecarVersion(e,t){let n=sidecarPath(e);await mkdir(dirname(n),{recursive:!0}),await writeFile(n,`${t}\n`,`utf-8`)}function runSpawn(e,t,n,r,i){return new Promise(a=>{let o;try{o=e(t,n,{env:r,stdio:[`ignore`,`pipe`,`pipe`]})}catch(e){a({kind:`spawn-error`,stderr:``,error:e});return}let s=``,c=!1,l=e=>{c||(c=!0,clearTimeout(u),a(e))};o.stderr?.on(`data`,e=>{s+=typeof e==`string`?e:e.toString(`utf-8`)}),o.on(`error`,e=>{l({kind:`spawn-error`,stderr:s,error:e})}),o.on(`exit`,e=>{l(e===0?{kind:`ok`,exitCode:e,stderr:s}:{kind:`nonzero`,exitCode:e,stderr:s})});let u=setTimeout(()=>{try{o.kill(`SIGTERM`)}catch{}l({kind:`timeout`,stderr:s})},i)})}async function installUserSkill(e={}){let t=e.home??homedir(),n=e.logger??{warn:(e,t)=>console.warn(t,e),info:(e,t)=>console.info(t,e)},r=e.spawn??spawn,i=e.timeoutMs??DEFAULT_TIMEOUT_MS,a;try{a=await readServerPackageVersion()}catch(e){return n.warn({event:`skill-install.failed`,reason:`version-read-failed`,error:String(e)},`Skill install aborted — could not read @inkeep/open-knowledge-server version.`),`failed`}let o=await readSidecarVersion(t).catch(()=>null);if(o!==null&&o===a)return n.info?.({event:`skill-install.skip-current`,version:a},`Open Knowledge skill already installed at current version; skipping.`),`skip-current`;let s;try{s=resolveBundledSkillDir()}catch(e){return n.warn({event:`skill-install.failed`,reason:`bundled-asset-missing`,error:String(e)},`Skill install aborted — bundled SKILL.md asset not found.`),`failed`}let c=await runSpawn(r,`npx`,[`-y`,SKILLS_CLI_SPEC,`add`,s,`--agent`,`*`,`-g`,`-y`,`--copy`],{...process.env,HOME:t},i);if(c.kind===`ok`){try{await writeSidecarVersion(t,a)}catch(e){return n.warn({event:`skill-install.failed`,reason:`sidecar-write-failed`,error:String(e)},`Skill install succeeded but sidecar write failed.`),`failed`}return n.info?.({event:`skill-install.installed`,version:a},`Open Knowledge skill installed to detected agent hosts.`),`installed`}return c.kind===`timeout`?(n.warn({event:`skill-install.failed`,reason:`timeout`,timeoutMs:i,stderr:c.stderr},`Skill install subprocess timed out. Run manually: npx ${SKILLS_CLI_SPEC} add ${s} --agent '*' -g -y --copy`),`failed`):c.kind===`spawn-error`?(n.warn({event:`skill-install.failed`,reason:`spawn-error`,error:String(c.error),stderr:c.stderr},`Skill install failed — \`npx\` unavailable or spawn errored. Run manually: npx ${SKILLS_CLI_SPEC} add ${s} --agent '*' -g -y --copy`),`failed`):(n.warn({event:`skill-install.failed`,reason:`nonzero-exit`,exitCode:c.exitCode,stderr:c.stderr},`Skill install subprocess exited non-zero. Run manually: npx ${SKILLS_CLI_SPEC} add ${s} --agent '*' -g -y --copy`),`failed`)}export{ensureProjectGit as $,withSpanSync as $t,applySeed as A,releaseUiLock as At,commitWipFromTree as B,seedBasenameIndex as Bt,SeedPrerequisiteError as C,planSeed as Ct,acquireUiLock as D,reconcile as Dt,UiLockCollisionError as E,readUiLock as Et,buildSkillZip as F,safeContentPath as Ft,createAssetServeMiddleware as G,startWatcher as Gt,contentHash as H,shadowGit as Ht,buildWipTree as I,safeSubdir as It,createPersistenceExtension as J,updateLastKnownHash as Jt,createContentFilter as K,starterFolderRule as Kt,classifyEvents as L,safetyCheckpoint as Lt,assertNeverDiskEvent as M,resolveBundledSkillDir as Mt,attachIdleShutdown as N,rewriteMarkdownLinksForDocumentRename as Nt,applyAgentMarkdownWrite as O,recordContributor as Ot,bootServer as P,rewriteWikiLinksForDocumentRename as Pt,detectProjectShape as Q,withSpan as Qt,commitUpstreamImport as R,saveInMemoryCheckpoint as Rt,STATE_MANIFEST_FILENAME as S,pathToDocName as St,StateManifestError as T,readStateManifest as Tt,contributorCount as U,shutdownTelemetry as Ut,containsConflictMarkers as V,setActiveSpanAttributes as Vt,createApiExtension as W,splitMarkdownBlocks as Wt,createServerObserverExtension as X,validateAgentId as Xt,createServer$1 as Y,updateUiLockPort as Yt,detectClaudeDesktopPresence as Z,validateSkillZip as Zt,ProjectGitInitError as _,listRescueCheckpoints as _t,BacklinkIndex as a,parseWriterId as an,getTracer as at,SERVICE_WRITER as b,parseHocuspocusAuthToken as bt,FILE_SYSTEM_WRITER as c,incrementServerObserverFire as ct,HocuspocusAuthRejection as d,installUserSkill as dt,writeStateManifest as en,evictStaleTrackerEntries as et,HocuspocusAuthTokenSchema as f,isConfigDoc as ft,PinoLogger as g,lastKnownHash as gt,OBSERVER_SYNC_ORIGIN as h,isSystemDoc as ht,AgentSessionManager as i,getWipRefPattern as in,getMetrics as it,assertCompatibleStateManifest as j,removeLastKnownHash as jt,applyExternalChange as k,registerWrite as kt,FILE_WATCHER_ORIGIN as l,initShadowRepo as lt,MANAGED_RENAME_ORIGIN as m,isSelfWrite as mt,AgentFocusBroadcaster as n,require_picomatch as nn,getLogger as nt,CC1Broadcaster as o,readContributors as on,handleCollabSocketError as ot,LOG_MD_TEMPLATE as p,isPairedWriteOrigin as pt,createLiveDerivedIndexExtension as q,toBroadcasterKey as qt,AgentPresenceBroadcaster as r,getShadowRepoPath as rn,getMeter as rt,CONFLICT_MARKER_RE as s,incrementCollabSocketFilteredError as st,AGENT_ID_RE as t,writeTracker as tn,extractWikiLinksFromMarkdown as tt,GIT_UPSTREAM_WRITER as u,initTelemetry as ut,ROLLBACK_ORIGIN as v,loadPrincipal as vt,SeedRootDirError as w,readBranchFromHead as wt,STARTER_FOLDERS as x,parseKeepaliveConnectionId as xt,SEED_CONFIG_FILENAME as y,loggerFactory as yt,commitWip as z,saveVersion as zt};
|
|
142
|
-
//# sourceMappingURL=dist-
|
|
143
|
+
//# sourceMappingURL=dist-DIvHbLlg.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./dist-CgDgVcCw.mjs";import{l as e,o as t}from"./server-lock-n3Y5JWNv-3o7br8XE.mjs";import{$ as n,At as r,D as i,E as a,Et as o,G as s,K as c,P as l,Yt as u,_ as d,nt as f}from"./dist-
|
|
1
|
+
import"./dist-CgDgVcCw.mjs";import{l as e,o as t}from"./server-lock-n3Y5JWNv-3o7br8XE.mjs";import{$ as n,At as r,D as i,E as a,Et as o,G as s,K as c,P as l,Yt as u,_ as d,nt as f}from"./dist-DIvHbLlg.mjs";export{d as ProjectGitInitError,a as UiLockCollisionError,i as acquireUiLock,l as bootServer,s as createAssetServeMiddleware,c as createContentFilter,n as ensureProjectGit,f as getLogger,t as isProcessAlive,e as readServerLock,o as readUiLock,r as releaseUiLock,u as updateUiLockPort};
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as e,r as t}from"./loader-
|
|
1
|
+
import{n as e,r as t}from"./loader-DtQHwYLI.mjs";import{c as n,i as r,l as i,s as a,t as o,u as s}from"./init-DUoMa9vS.mjs";import"./src-K3thD12M.mjs";export{i as ALL_EDITOR_IDS,t as ConfigSchema,s as EDITOR_TARGETS,o as detectInstalledEditors,e as loadConfig,r as readExistingMcpEntry,a as writeEditorMcpConfig,n as writeUserMcpConfigs};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{n as e}from"./init-M_iZj3b4.mjs";export{e as initContent};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{o as e}from"./init-DUoMa9vS.mjs";export{e as runInit};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{n as e,t}from"./esm-wByiX8MO.mjs";import{$ as n}from"./dist-CgDgVcCw.mjs";import{r}from"./constants-
|
|
1
|
+
import{n as e,t}from"./esm-wByiX8MO.mjs";import{$ as n}from"./dist-CgDgVcCw.mjs";import{r}from"./constants-CxQqeafL.mjs";import{$ as i,Z as a,_ as o,dt as s}from"./dist-DIvHbLlg.mjs";import{t as c}from"./is-object-CEU0BgQ5.mjs";import{n as l}from"./init-M_iZj3b4.mjs";import{t as u}from"./preview-BdpgALxC.mjs";import{s as d,t as f}from"./colors-BdAXRiXe.mjs";import{basename as p,dirname as m,join as h,posix as g,relative as _,resolve as v,sep as y,win32 as b}from"node:path";import{existsSync as x,mkdirSync as S,readFileSync as C,writeFileSync as w}from"node:fs";import{homedir as T}from"node:os";import E from"@inquirer/checkbox";
|
|
2
2
|
/*!
|
|
3
3
|
* Copyright (c) Squirrel Chat et al., All rights reserved.
|
|
4
4
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
@@ -251,5 +251,5 @@ let F=/^[a-z0-9-_]+$/i;function I(e){let t=typeof e;if(t===`object`){if(Array.is
|
|
|
251
251
|
`)?n:`${n}\n`,`utf-8`)}const Re=e=>e!==`project`,Y=e=>e!==`user`;async function ze(){let e=await E({message:`Where should the MCP server be configured?
|
|
252
252
|
`,required:!1,theme:{icon:{checked:`[x]`,unchecked:`[ ]`}},choices:[{name:`User-level (~/.claude.json, ~/.cursor/mcp.json, …)`,value:`user`,checked:!0},{name:`Project-level (.mcp.json, .cursor/mcp.json, …)`,value:`project`,checked:!0}]});return e.includes(`user`)&&e.includes(`project`)?`both`:e.includes(`user`)?`user`:e.includes(`project`)?`project`:null}async function Be(e){return e.mcp===!1?null:e.scope?e.scope:e.isTTY??process.stdout.isTTY?(e.promptFn??ze)():`both`}const Ve=`0.0.1`,X=`open-knowledge-ui`;function He(e,t={}){let n=h(e,`.claude`,`launch.json`),r=t.mode===`dev`?{name:X,runtimeExecutable:`node`,runtimeArgs:[V(t.cliEntryPath),`ui`],port:3e3}:{name:X,runtimeExecutable:`npx`,runtimeArgs:[`@inkeep/open-knowledge`,`ui`],port:3e3};try{if(!x(n))return S(m(n),{recursive:!0}),w(n,`${JSON.stringify({version:Ve,configurations:[r]},null,2)}\n`,`utf-8`),{action:`created`,configPath:n};let e=C(n,`utf-8`).trim(),t=e?JSON.parse(e):{};if(!c(t))return{action:`failed`,configPath:n,error:`launch.json root is not an object`};let i=Array.isArray(t.configurations)?t.configurations:[],a=i.findIndex(e=>c(e)&&e.name===X);a>=0?i[a]=r:i.push(r);let o={...t,version:t.version??Ve,configurations:i};return w(n,`${JSON.stringify(o,null,2)}\n`,`utf-8`),{action:a>=0?`merged`:`created`,configPath:n}}catch(e){return{action:`failed`,configPath:n,error:e instanceof Error?e.message:String(e)}}}function Z(e,t,n){try{return x(e.detectPath?.(t,n)??m(e.configPath(t,n)))}catch{return!1}}function Q(e,t,n,r,i){let a=e.serverName(t),o;try{o=i??e.configPath(t,r)}catch(t){return{editorId:e.id,label:e.label,action:`failed`,configPath:``,serverName:a,error:t instanceof Error?t.message:String(t)}}if(!i&&!n.skipAvailabilityCheck&&!Z(e,t,r))return{editorId:e.id,label:e.label,action:`skipped-missing`,configPath:o,serverName:a};let s;try{s=e.format===`toml`?Fe(o):Pe(o)}catch(t){return{editorId:e.id,label:e.label,action:`failed`,configPath:o,serverName:a,error:t instanceof Error?t.message:String(t)}}let c=s[e.topLevelKey]??{},l=c[a],u;try{u=e.buildEntry(t,n)}catch(t){return{editorId:e.id,label:e.label,action:`failed`,configPath:o,serverName:a,error:t instanceof Error?t.message:String(t)}}let d={...s,[e.topLevelKey]:{...c,[a]:u}};try{e.format===`toml`?Le(o,d):Ie(o,d)}catch(t){return{editorId:e.id,label:e.label,action:`failed`,configPath:o,serverName:a,error:t instanceof Error?t.message:String(t)}}return{editorId:e.id,label:e.label,action:l===void 0?`written`:`overwritten`,configPath:o,serverName:a,...i===void 0?{}:{configScope:`project`}}}function Ue(e,t){let n=e.projectConfigPath?.(t);if(!(!n||!x(n)))return{editorId:e.id,label:e.label,path:n}}async function We(e){let t=J(e.editors),n={mode:`published`,cliPath:e.cliPath,skipAvailabilityCheck:!0};return t.map(t=>Q(t,``,n,e.home))}function Ge(e,t,n){let r;try{r=e.configPath(t,n)}catch{return null}let i;try{i=e.format===`toml`?Fe(r):Pe(r)}catch{return null}let a=i[e.topLevelKey];if(!c(a))return null;let o=a[e.serverName(t)];return c(o)?o:null}async function Ke(e={}){let t=v(e.cwd??process.cwd()),n={mode:e.pin?`pinned`:e.devMcp?`dev`:`published`,cliEntryPath:e.cliEntryPath},r=await i(t),o;try{o=l(t)}catch(n){let i=q.claude.configPath(t,e.home);return{contentCreated:[],contentUpdated:[],contentSkipped:[],editors:[],legacyProjectConfigs:[],didGitInit:r.didInit,claudeDesktopDetected:!1,mcpAction:`failed`,mcpPath:i,mcpError:`Content scaffolding failed: ${n instanceof Error?n.message:String(n)}`}}let c=await Be({scope:e.scope,mcp:e.mcp,isTTY:e.isTTY,promptFn:e.promptFn}),u=e.editors??$(t,e.home),d=e.editors??B.filter(e=>q[e].projectConfigPath!==void 0),f=J(u),p=J(d),m=e.mcp===!1||c===null,h=Array.from(new Map([...f,...m?[]:p].map(e=>[e.id,e])).values()),g=f.filter(n=>Z(n,t,e.home)),_=[],y=new Set;for(let r of h){if(m){let n=``;try{n=r.configPath(t,e.home)}catch{}_.push({editorId:r.id,label:r.label,action:`skipped-flag`,configPath:n,serverName:r.serverName(t)});continue}if(Re(c)&&f.includes(r)&&_.push(Q(r,t,n,e.home)),Y(c)&&p.includes(r)&&r.projectConfigPath){let i=r.projectConfigPath(t),a=Q(r,t,n,e.home,i);_.push(a),(a.action===`written`||a.action===`overwritten`)&&y.add(i)}}let b=!m&&c!==null&&Y(c)?p.filter(e=>!e.projectConfigPath).map(e=>e.label):void 0,x=m?[]:g.map(e=>Ue(e,t)).filter(e=>e!==void 0).filter(e=>!y.has(e.path)),S=g.some(e=>e.id===`claude`)&&!m?He(t,n):void 0,C=await(e.installUserSkill??s)({home:e.home}),w=a({home:e.home}),T=m?`skipped-flag`:`skipped-missing`,E=_.find(e=>e.editorId===`claude`)??_[0]??{action:T,configPath:q.claude.configPath(t,e.home)};return{contentCreated:o.created,contentUpdated:o.updated,contentSkipped:o.skipped,editors:_,legacyProjectConfigs:x,launchJson:S,skillInstall:C,didGitInit:r.didInit,claudeDesktopDetected:w,mcpAction:E.action,mcpPath:E.configPath,mcpError:`error`in E?E.error:void 0,projectScopeUnsupportedLabels:b}}function qe(e,t){let r=[],i=e.editors.some(e=>e.action===`written`||e.action===`overwritten`),a=e.editors.some(e=>e.action===`failed`),o=e.editors.length>0&&e.editors.every(e=>e.action===`skipped-flag`),s=e.editors.length>0&&e.editors.every(e=>e.action===`skipped-missing`),c=e=>{let n=e.configPath.startsWith(t)?_(t,e.configPath):e.configPath;switch(e.action){case`created`:return` app preview server ${n} configured for Claude Code Desktop embedded browser`;case`merged`:return` app preview server ${n} updated for Claude Code Desktop embedded browser`;case`failed`:return` app preview server ${n} FAILED: ${e.error}`}};e.didGitInit&&r.push(`Initialized git repo at ${t}/.git/ (default branch: main)`);let l=h(t,n);if(e.contentCreated.length>0||e.contentUpdated.length>0?(r.push(`Content scaffolded at ${l}/`),e.contentCreated.length>0&&r.push(` Created: ${e.contentCreated.join(`, `)}`),e.contentUpdated.length>0&&r.push(` Updated: ${e.contentUpdated.join(`, `)}`)):r.push(`Content already present at ${l}/`),e.contentSkipped.length>0&&r.push(` Skipped (already exist): ${e.contentSkipped.join(`, `)}`),r.push(``),e.mcpError&&e.editors.length===0)r.push(`Warning: ${e.mcpError}`);else if(e.editors.length===0)if(r.push(`MCP server configuration:`),e.mcpAction===`skipped-flag`)r.push(` MCP config not written — use without --no-mcp to configure editors`);else if(e.projectScopeUnsupportedLabels&&e.projectScopeUnsupportedLabels.length>0){let t=e.projectScopeUnsupportedLabels.join(`, `),n=e.projectScopeUnsupportedLabels.length===1?`does`:`do`;r.push(` ${t} ${n} not support project-level config; skipped`)}else r.push(` No supported editor config directories detected; skipped MCP registration`);else if(o)r.push(`MCP config not written — use without --no-mcp to configure editors`);else if(s)r.push(`MCP server configuration:`),r.push(` No supported editor config directories detected; skipped MCP registration`);else{r.push(`MCP server configuration:`);for(let n of e.editors){let i=n.configPath.startsWith(t)?_(t,n.configPath):n.configPath.replace(/^\/Users\/[^/]+/,`~`),a=n.serverName===`open-knowledge`?``:` (${n.serverName})`,o=n.configScope===`project`?` (project)`:``,s=`${n.label}${o}`,l=` `.repeat(Math.max(1,20-s.length)),u=n.editorId===`claude-desktop`&&(n.action===`written`||n.action===`overwritten`)?` — quit and relaunch Claude Desktop to activate`:``;switch(n.action){case`written`:r.push(` ${s}${l}${i} registered${a}${u}`);break;case`overwritten`:r.push(` ${s}${l}${i} updated${a}${u}`);break;case`skipped-missing`:r.push(` ${s}${l}${i} config root missing; skipped`);break;case`failed`:r.push(` ${s}${l}${i} FAILED: ${n.error}`);break;case`skipped-flag`:break}n.editorId===`claude`&&e.launchJson&&r.push(c(e.launchJson))}if(e.projectScopeUnsupportedLabels&&e.projectScopeUnsupportedLabels.length>0){let t=e.projectScopeUnsupportedLabels.join(`, `),n=e.projectScopeUnsupportedLabels.length===1?`does`:`do`;r.push(` ${t} ${n} not support project-level config; skipped`)}}if(a&&(r.push(``),r.push(`For failed editors, add the MCP server entry manually. See:`),r.push(` https://github.com/inkeep/open-knowledge#mcp-setup`)),e.legacyProjectConfigs.length>0){r.push(``),r.push(`Project MCP configs found:`);for(let n of e.legacyProjectConfigs)r.push(` ${n.label} ${_(t,n.path)}`);r.push(` These project-local files may override the global config. Remove them if you want fully user-scoped MCP setup in this project.`)}if(e.skillInstall)switch(r.push(``),r.push(`User-global skill:`),e.skillInstall){case`installed`:r.push(" open-knowledge installed to detected agent hosts via `npx skills`");break;case`skip-current`:r.push(` open-knowledge already installed at current version`);break;case`failed`:r.push(` ${d(`open-knowledge install failed — MCP still configured; run manually:`)}`),r.push(` ${d(` npx skills@~1.5.0 add <bundled-path> --agent '*' -g -y --copy`)}`);break}if(e.claudeDesktopDetected&&(r.push(``),r.push(`Claude Desktop App detected. To enable in Claude Chat & Cowork, run: ${f(`ok install-skill`)}`)),e.preview?(r.push(``),r.push(u(e.preview,t))):e.previewWarning&&(r.push(``),r.push(`Content preview unavailable: ${e.previewWarning}`)),i){let t=new Set,n=e.editors.filter(e=>e.action===`written`||e.action===`overwritten`).filter(e=>!t.has(e.editorId)&&t.add(e.editorId)).map(e=>e.label);r.push(``),r.push(`Next steps:`),r.push(` 1. Open your editor (${n.join(` / `)})`),r.push(` 2. Approve the MCP server when prompted`),r.push(` 3. (Optional) scaffold the starter knowledge-base structure:`),r.push(` - ok seed`),r.push(` 4. Use the three MCP workflow tools as you build the wiki:`),r.push(` - mcp__open-knowledge__ingest — capture an external source`),r.push(` - mcp__open-knowledge__research — gather sources and write findings`),r.push(` - mcp__open-knowledge__consolidate — promote research to canonical articles`)}return r.join(`
|
|
253
253
|
`)}function $(e,t){let n=[];for(let r of B)Z(q[r],e,t)&&n.push(r);return n}function Je(){return new t(`init`).description(`Scaffold ${n}/ in the current directory and register the MCP server for your editor(s)`).option(`--mcp`,`Register the MCP server for selected editors (default: true)`,!0).option(`--no-mcp`,`Scaffold the ${n}/ directory but do not touch MCP config`).option(`--dev-mcp`,`Register a local dev MCP entry using node + packages/cli/dist/cli.mjs with debug logging`).addOption(new e(`--scope <scope>`,`Write MCP config at user level, project level, or both`).choices([`user`,`project`,`both`])).option(`--pin`,"Pin the MCP entry to the absolute path of the current CLI binary instead of `npx`. Use a stable shim like /usr/local/bin/ok for upgrade-safe pinning; npx-cache or worktree paths will go stale on reinstall.").option(`--no-pin`,"Use the default unpinned `npx @inkeep/open-knowledge mcp` MCP entry").action(async e=>{let t=process.cwd(),n;try{n=await Ke({cwd:t,mcp:e.mcp,devMcp:e.devMcp,scope:e.scope,pin:e.pin})}catch(e){if(e instanceof o){process.stderr.write(`open-knowledge requires git to initialize a parent repo. Install git or run 'git init' yourself, then re-run.
|
|
254
|
-
`),e.stderr&&process.stderr.write(`${e.stderr.trim()}\n`),process.exitCode=1;return}throw e}try{let{previewContent:e}=await import(`./preview-
|
|
255
|
-
//# sourceMappingURL=init-
|
|
254
|
+
`),e.stderr&&process.stderr.write(`${e.stderr.trim()}\n`),process.exitCode=1;return}throw e}try{let{previewContent:e}=await import(`./preview-Bik03UEr.mjs`),{loadConfig:r}=await import(`./loader-CDwZoOZT.mjs`),{resolveContentDir:i}=await import(`./paths-BDTDW9fv.mjs`),{config:a}=r(t),o=i(a,t);n.preview=e({projectDir:t,contentDir:o,include:a.content.include,exclude:a.content.exclude})}catch(e){n.previewWarning=e instanceof Error?e.message:String(e)}process.stdout.write(`${qe(n,t)}\n`),(n.editors.some(e=>e.action===`failed`)||n.mcpAction===`failed`)&&(process.exitCode=1)})}export{Be as a,We as c,Ge as i,B as l,qe as n,Ke as o,Je as r,Q as s,$ as t,q as u};
|
|
255
|
+
//# sourceMappingURL=init-DUoMa9vS.mjs.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{$ as e,X as t}from"./dist-CgDgVcCw.mjs";import{i as n,n as r,t as i}from"./constants-
|
|
1
|
+
import{$ as e,X as t}from"./dist-CgDgVcCw.mjs";import{i as n,n as r,t as i}from"./constants-CxQqeafL.mjs";import{join as a,resolve as o}from"node:path";import{existsSync as s,mkdirSync as c,readFileSync as l,writeFileSync as u}from"node:fs";function d(n){return`# yaml-language-server: $schema=https://unpkg.com/@inkeep/open-knowledge@latest/dist/schemas/${t}/config.workspace.schema.json
|
|
2
2
|
# Open Knowledge — workspace configuration
|
|
3
3
|
#
|
|
4
4
|
# This file overrides built-in defaults for this workspace. Every key below
|
|
@@ -141,4 +141,4 @@ state.json
|
|
|
141
141
|
# MCP spawn diagnostics
|
|
142
142
|
last-spawn-error.log
|
|
143
143
|
`;function h(t){let s=o(t,e),l=[],u=[],h=[];c(s,{recursive:!0}),c(a(s,i),{recursive:!0});let g=p(a(s,`.gitignore`),m);return g===`created`?l.push(`.gitignore`):g===`updated`?u.push(`.gitignore`):h.push(`.gitignore`),f(a(s,`config.yml`),d(n))?l.push(r):h.push(r),{created:l,updated:u,skipped:h}}export{h as n,d as t};
|
|
144
|
-
//# sourceMappingURL=init-
|
|
144
|
+
//# sourceMappingURL=init-M_iZj3b4.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{n as e}from"./loader-DtQHwYLI.mjs";export{e as loadConfig};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{$ as e,I as t,Rt as n,Z as r,nt as i}from"./dist-CgDgVcCw.mjs";import{n as a}from"./constants-
|
|
2
|
-
//# sourceMappingURL=loader-
|
|
1
|
+
import{$ as e,I as t,Rt as n,Z as r,nt as i}from"./dist-CgDgVcCw.mjs";import{n as a}from"./constants-CxQqeafL.mjs";import{r as o}from"./server-CTsFrqmD.mjs";import{t as s}from"./is-object-CEU0BgQ5.mjs";import{resolve as c}from"node:path";import{existsSync as l,readFileSync as u}from"node:fs";import{homedir as d}from"node:os";import{realpath as f}from"node:fs/promises";async function p(e){let t=c(e);try{return await f(t)}catch(e){if(e.code!==`ENOENT`){let n=e instanceof Error?e.message:String(e);console.warn(`[normalize-cwd] realpath failed for ${t}: ${n}`)}return t}}const m=r;var h=n();function g(e,t){let n={...e};for(let r of Object.keys(t)){let i=e[r],a=t[r];s(a)&&s(i)?n[r]=g(i,a):a!==void 0&&(n[r]=a)}return n}function _(e){if(!l(e))return{value:null,path:e,source:null,doc:null};let t;try{t=u(e,`utf-8`)}catch(t){return console.warn(`[config] Failed to read ${e}: ${t instanceof Error?t.message:t}`),{value:null,path:e,source:null,doc:null}}let n=(0,h.parseDocument)(t);if(n.errors.length>0)return console.warn(`[config] Failed to parse ${e}: ${n.errors.map(e=>e.message).join(`; `)}`),{value:null,path:e,source:t,doc:null};let r=n.toJSON();return s(r)?{value:r,path:e,source:t,doc:n}:{value:null,path:e,source:t,doc:n}}function v(e,t){return e.map(e=>{let n=e.path.map(e=>typeof e==`symbol`?String(e):e),r={path:n,message:e.message,issueCode:e.code};if(t.doc!==null&&t.source!==null){let e=i({file:t.path,source:t.source,doc:t.doc,path:n});if(e!==void 0)return{...r,source:e}}return r})}function y(n){let r=n??process.cwd(),i=[],l=c(d(),e,a),u=o({absPath:l}),f={};u.valid&&u.source!==void 0?(f=g(f,u.value),i.push(l)):u.valid;let p=c(r,e,a),h=_(p);h.value!==null&&(f=g(f,h.value),i.push(p));let y=f.upload;s(y)&&y.maxBytes!==void 0&&console.warn(`[config] upload.maxBytes is deprecated and ignored — streaming uploads have no user-facing cap. Remove the key to silence this warning.`);let b=m.safeParse(f);if(!b.success){let e={code:`SCHEMA_INVALID`,issues:v(b.error.issues,h)};throw Error(t(e))}return{config:b.data,sources:i}}function b(e,t=process.env){let n=e;return t.HOST&&(n={...n,server:{...n.server,host:t.HOST}}),n}function x(e){let t=e.env??process.env,n=e.cacheMs??1e3,r=e.loadConfigFn??y,i=new Map,a=new Map,o=p(e.startupCwd);return async s=>{let c=await p(s??e.startupCwd),l=Date.now(),u=i.get(c);if(u&&u.expiresAt>l)return u.config;let d=a.get(c);if(d)return await d;let f=(async()=>{if(c===await o){let r=b(e.startupConfig,t);return i.set(c,{config:r,expiresAt:Date.now()+n}),r}let a=b(r(c).config,t);return i.set(c,{config:a,expiresAt:Date.now()+n}),a})();a.set(c,f);try{return await f}finally{a.delete(c)}}}export{p as i,y as n,m as r,x as t};
|
|
2
|
+
//# sourceMappingURL=loader-DtQHwYLI.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{n as e,t}from"./paths-D6PiyuBM.mjs";export{t as resolveContentDir,e as resolveLockDir};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{$ as e}from"./dist-CgDgVcCw.mjs";import"./constants-
|
|
1
|
+
import{$ as e}from"./dist-CgDgVcCw.mjs";import"./constants-CxQqeafL.mjs";import{K as t}from"./dist-DIvHbLlg.mjs";import{join as n,relative as r}from"node:path";import{existsSync as i,lstatSync as a,readdirSync as o,realpathSync as s,statSync as c}from"node:fs";function l(e){let{projectDir:i,contentDir:l,include:u,exclude:d,sampleCap:f=5}=e,p=[],m=[];try{a(l)}catch(e){return{totalCount:0,sample:[],contentDir:l,include:u,exclude:d,warnings:[`cannot access content directory ${l}: ${e instanceof Error?e.message:String(e)}`]}}let h;try{h=t({projectDir:i,contentDir:l,includePatterns:u,excludePatterns:d})}catch(e){return{totalCount:0,sample:[],contentDir:l,include:u,exclude:d,warnings:[e instanceof Error?e.message:String(e)]}}function g(e){let t;try{t=o(e,{withFileTypes:!0})}catch(t){let n=t instanceof Error?t.message:String(t);p.push(`could not read directory ${r(l,e)||`.`}: ${n}`);return}for(let i of t){let t=n(e,i.name);if(i.isSymbolicLink()){let e;try{e=s(t)}catch(e){let n=e.code;n===`ENOENT`||n===`ELOOP`?p.push(`broken or cyclic symlink: ${r(l,t)}`):p.push(`cannot resolve symlink ${r(l,t)}: ${n??`unknown error`}`);continue}let n;try{n=c(e)}catch{continue}if(n.isDirectory()){let e=r(l,t);if(h.isDirExcluded(e))continue;g(t)}else if(n.isFile()){let e=r(l,t);if(h.isExcluded(e))continue;m.push(e)}}else if(i.isDirectory()){let e=r(l,t);if(h.isDirExcluded(e))continue;g(t)}else if(i.isFile()){let e=r(l,t);if(h.isExcluded(e))continue;m.push(e)}}}return g(l),{totalCount:m.length,sample:m.slice(0,f),contentDir:l,include:u,exclude:d,warnings:p}}function u(t,a){let o=[],s=r(a,t.contentDir),c=s===``?`./`:`./${s}`;o.push(`Content:`),o.push(` Found ${t.totalCount} markdown files in ${c}`);let l=t.include.join(`, `),u=t.exclude.length>0?t.exclude.join(`, `):`(none)`;if(o.push(` Scope: include=${l} exclude=${u}`),t.sample.length>0){let e=t.sample.join(`, `),n=t.totalCount>t.sample.length?`, …`:``;o.push(` Sample: ${e}${n}`)}if(t.warnings.length>0)for(let e of t.warnings)o.push(` Warning: ${e}`);return o.push(``),i(n(a,`.open-knowledge`,`config.yml`))?(o.push(` To adjust, edit ${e}/config.yml:`),o.push(` content:`),o.push(` include: ${JSON.stringify(t.include)}`),o.push(` exclude: ${JSON.stringify(t.exclude)}`)):(o.push(" Run `open-knowledge init` to scaffold config, then adjust:"),o.push(` ${e}/config.yml → content.include / content.exclude`)),o.push(``),o.push(` Re-check anytime: open-knowledge preview`),o.join(`
|
|
2
2
|
`)}export{l as n,u as t};
|
|
3
|
-
//# sourceMappingURL=preview-
|
|
3
|
+
//# sourceMappingURL=preview-BdpgALxC.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{n as e,t}from"./preview-BdpgALxC.mjs";export{t as formatPreviewBlock,e as previewContent};
|