@inkeep/open-knowledge 0.4.0-beta.17 → 0.4.0-beta.19
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/assets/skills/open-knowledge/SKILL.md +1 -1
- package/dist/cli.mjs +38 -38
- package/dist/constants-3O7IbmRt.mjs +2 -0
- package/dist/dist-CeydCXIY.mjs +1 -0
- package/dist/{dist-dNO-Udm_.mjs → dist-RAy2NfOX.mjs} +4 -4
- package/dist/index.mjs +1 -1
- package/dist/init-Bf3i3xIz.mjs +1 -0
- package/dist/{init-BO8sWy5q.mjs → init-qh1HubtR.mjs} +3 -3
- package/dist/loader-CTQL6JBJ.mjs +1 -0
- package/dist/{loader-fktLkWoO.mjs → loader-DMES5Z4K.mjs} +3 -3
- package/dist/{preview-DOErzjxx.mjs → preview-CZdt-b-O.mjs} +2 -2
- package/dist/preview-Dy00IGYn.mjs +1 -0
- package/dist/src-D0mZ2vS1.mjs +1 -0
- package/dist/start-CMpdhTp5.mjs +1 -0
- package/dist/{start-jeIuSBq5.mjs → start-Dxso0_dy.mjs} +2 -2
- package/package.json +1 -1
- package/dist/constants-lybG5gQZ.mjs +0 -2
- package/dist/dist-D0H-ut9y.mjs +0 -1
- package/dist/init-Dlm__eWd.mjs +0 -1
- package/dist/loader-od_FoBBq.mjs +0 -1
- package/dist/preview-ByeyxmgX.mjs +0 -1
- package/dist/src-Brc8KpdH.mjs +0 -1
- package/dist/start-H8MzEZdm.mjs +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{$ as e,A as t,M as n,O as r,R as i,g as a,tt as o}from"./dist-DfIz2LcA.mjs";import{_ as s,a as c,c as l,d as u,f as d,g as f,i as p,l as m,m as h,n as g,o as _,p as v,r as y,s as b,t as x,u as S}from"./server-lock-D7DXNVql-BRVVzA6T.mjs";import{$ as C,$n as w,$t as T,A as E,An as D,At as O,B as k,Bn as A,Bt as j,C as M,Cn as N,Ct as P,D as F,Dn as I,Dt as L,E as R,En as z,Et as B,F as V,Fn as H,Ft as U,G as W,Gn as G,Gt as K,H as q,Hn as J,Ht as Y,I as X,In as Z,It as Q,J as $,Jn as ee,Jt as te,K as ne,Kn as re,Kt as ie,L as ae,Ln as oe,Lt as se,M as ce,Mn as le,Mt as ue,N as de,Nn as fe,Nt as pe,O as me,On as he,Ot as ge,P as _e,Pn as ve,Pt as ye,Q as be,Qn as xe,Qt as Se,R as Ce,Rn as we,Rt as Te,S as Ee,Sn as De,St as Oe,T as ke,Tn as Ae,Tt as je,U as Me,Un as Ne,Ut as Pe,V as Fe,Vn as Ie,Vt as Le,W as Re,Wn as ze,Wt as Be,X as Ve,Xn as He,Xt as Ue,Y as We,Yn as Ge,Yt as Ke,Z as qe,Zn as Je,Zt as Ye,_ as Xe,_n as Ze,_t as Qe,a as $e,an as et,ar as tt,at as nt,b as rt,bn as it,bt as at,c as ot,cn as st,ct,d as lt,dn as ut,dt,en as ft,er as pt,et as mt,f as ht,fn as gt,ft as _t,g as vt,gn as yt,gt as bt,h as xt,hn as St,hr as Ct,ht as wt,i as Tt,in as Et,ir as Dt,it as Ot,j as kt,jn as At,jt,k as Mt,kn as Nt,kt as Pt,l as Ft,ln as It,lt as Lt,m as Rt,mn as zt,mr as Bt,mt as Vt,n as Ht,nn as Ut,nr as Wt,nt as Gt,o as Kt,on as qt,ot as Jt,p as Yt,pn as Xt,pt as Zt,q as Qt,qn as $t,qt as en,r as tn,rn as nn,rr as rn,rt as an,s as on,sn,st as cn,t as ln,tn as un,tr as dn,tt as fn,u as pn,un as mn,ut as hn,v as gn,vn as _n,vt as vn,w as yn,wn as bn,wt as xn,x as Sn,xn as Cn,xt as wn,y as Tn,yn as En,yt as Dn,z as On,zn as kn,zt as An}from"./dist-RAy2NfOX.mjs";export{ln as AGENT_ID_MAX_LEN,Ht as AGENT_ID_RE,tn as AGENT_WRITE_ORIGIN,Tt as AgentFocusBroadcaster,$e as AgentPresenceBroadcaster,Kt as AgentSessionCapacityError,on as AgentSessionManager,ot as BacklinkIndex,Ft as CC1Broadcaster,a as CC1_CONTRACT_VERSION,pn as CONFLICT_MARKER_RE,lt as CURSOR_BUNDLE_PATHS_BY_PLATFORM,ht as ConfigSchema,Yt as DEFAULT_CHECKPOINT_RETENTION,Rt as FILE_SYSTEM_WRITER,xt as FILE_WATCHER_ORIGIN,vt as GIT_UPSTREAM_WRITER,Bt as GitDirAccessError,Xe as HOCUSPOCUS_AUTH_REJECTION_REASONS,gn as HocuspocusAuthRejection,Tn as HocuspocusAuthTokenSchema,rt as INSTALLED_AGENTS_SCHEMES,Sn as LIVE_DERIVED_INDEX_DEBOUNCE_MS,Ee as LOG_MD_TEMPLATE,M as MANAGED_RENAME_ORIGIN,yn as MAX_AGENT_SESSIONS,ke as MCP_CONNECTION_ID_HEADER,R as MCP_SERVER_NAME,F as MISSING_OK_CONFIG_MESSAGE,Ct as MalformedGitPointerError,me as McpLogger,Mt as MissingOkConfigError,E as OBSERVER_SYNC_ORIGIN,r as ORPHAN_MODES,kt as PinoLogger,x as ProcessLockCollisionError,ce as ProjectGitInitError,de as ROLLBACK_ORIGIN,g as RUNTIME_VERSION,_e as SERVICE_WRITER,V as SKILL_INSTALL_EVENTS_FILE_REL,t as SKILL_STATE_TARGETS,X as STARTER_FOLDERS,ae as STARTER_FOLDER_FRONTMATTER_FILENAME,Ce as STARTER_TEMPLATES,On as STATE_MANIFEST_FILENAME,y as STATE_SCHEMA_VERSION,n as SYSTEM_DOC_NAME,k as SeedPrerequisiteError,Fe as SeedRootDirError,p as ServerLockCollisionError,q as StateManifestError,Me as TagIndex,Re as UiLockCollisionError,c as acquireProcessLock,_ as acquireServerLock,W as acquireUiLock,ne as applyAgentMarkdownWrite,Qt as applyExternalChange,$ as applySeed,We as assertCompatibleStateManifest,Ve as assertNeverDiskEvent,qe as attachIdleShutdown,be as bootServer,C as buildAndOpenSkill,mt as buildExecResult,fn as buildReadResult,Gt as buildSkillZip,an as buildStarterFolderFrontmatterYaml,Ot as buildWipTree,nt as classifyEvents,Jt as clearContributors,i as colorFromSeed,cn as commitUpstreamImport,ct as commitWip,Lt as commitWipFromTree,hn as containsConflictMarkers,dt as contentHash,_t as contributorCount,Zt as createApiExtension,Vt as createAssetServeMiddleware,wt as createContentFilter,bt as createContentFilterAsync,Qe as createExternalChangeHandler,vn as createLiveDerivedIndexExtension,Dn as createMcpHttpHandler,at as createOsProbe,wn as createPersistenceExtension,Oe as createServer,P as createServerObserverExtension,xn as createTestLogger,je as detectClaudeDesktopPresence,B as detectProjectShape,L as ensureProjectGit,ge as evictStaleTrackerEntries,Pt as extractWikiLinksFromMarkdown,O as formatContributors,jt as gcCheckpointRefs,ue as getCurrentMcpLogger,pe as getLocalDir,ye as getLogger,U as getMeter,Q as getMetrics,se as getTracer,Te as handleCollabSocketError,An as handleSpawnCursor,e as iconFromClientName,j as incrementCollabSocketFilteredError,Le as incrementServerObserverFire,Y as initShadowRepo,Pe as initTelemetry,Be as installTestLoggers,K as installUserSkill,ie as isAllowedApiOrigin,en as isAllowedWorkspaceHostHeader,te as isConfigDoc,Ke as isHocuspocusAuthRejectionReason,Ue as isLoopbackAddress,o as isOrphanMode,Ye as isPairedWriteOrigin,Se as isPathWithinDir,b as isProcessAlive,T as isSelfWrite,ft as isSystemDoc,l as isValidLockPid,un as lastKnownHash,Ut as listRescueCheckpoints,nn as loadPrincipal,m as lockFilePath,Et as loggerFactory,et as mountMcpAndApi,qt as parseHocuspocusAuthToken,sn as parseKeepaliveConnectionId,st as pathToDocName,It as planSeed,mn as readAllTargets,ut as readBranchFromHead,S as readProcessLock,u as readProcessLockDetailed,d as readServerLock,gt as readServerPackageVersion,Xt as readSkillInstallStateSnapshot,zt as readStateManifest,St as readTargetRecordedAt,yt as readTargetVersion,Ze as readUiLock,_n as reconcile,En as recordContributor,it as recordSkillInstallEvent,Cn as registerWrite,v as releaseProcessLock,h as releaseServerLock,De as releaseUiLock,N as removeLastKnownHash,bn as resetMetrics,Ae as resolveBundledSkillDir,z as resolveContentDir,I as resolveCursorBinaryDefault,he as resolveCursorSpawnInvocation,Nt as resolveLockDir,D as resolvePackageVersion,At as rewriteMarkdownLinksForDocumentRename,le as rewriteWikiLinksForDocumentRename,fe as runAuthReposSubprocess,ve as runAuthStatusSubprocess,H as runCloneSubprocess,Z as runDeviceFlowSubprocess,oe as runWithMcpLogger,we as safeContentPath,kn as safeSubdir,A as safetyCheckpoint,Ie as saveInMemoryCheckpoint,J as saveVersion,Ne as seedBasenameIndex,ze as setActiveSpanAttributes,G as shadowGit,re as shutdownTelemetry,$t as splitMarkdownBlocks,ee as startWatcher,Ge as toBroadcasterKey,He as updateLastKnownHash,f as updateProcessLockPort,s as updateServerLockPort,Je as updateUiLockPort,xe as validateAgentId,w as validateCloneInputs,pt as validateSkillZip,dn as withSpan,Wt as withSpanSync,rn as writeStateManifest,Dt as writeTargetVersion,tt as writeTracker};
|
|
@@ -956,7 +956,7 @@ tags: [article, canonical]
|
|
|
956
956
|
`),s=e.added?`added`:e.removed?`removed`:`unchanged`;for(let e of t)B.push({type:s,text:e});e.added&&(ee+=t.length),e.removed&&(te+=t.length)}json(s,200,{ok:!0,lines:B,additions:ee,deletions:te})}catch(e){console.error(`[diff]`,e),json(s,500,{ok:!1,error:`Internal server error`})}}async function Br(s,g){if(s.method!==`POST`){g.writeHead(405),g.end(`Method not allowed`);return}let S=O?.current;if(!S){json(g,400,{ok:!1,error:`Shadow repo not configured`});return}let w;try{w=await readBody(s)}catch{json(g,413,{ok:!1,error:`Payload too large`});return}let E;try{E=w.length>0?JSON.parse(w.toString()):{}}catch{json(g,400,{ok:!1,error:`Invalid JSON`});return}if(!E||typeof E!=`object`||Array.isArray(E)){json(g,400,{ok:!1,error:`Body must be a JSON object`});return}let D=E,k=extractActorIdentity(D,se);if(k.kind===`invalid-summary`){json(g,400,{ok:!1,error:`summary must be a string`});return}let{docName:j,commitSha:L,versionTag:H}=D,q=typeof j==`string`?j:``,J=typeof L==`string`?L:``,ee=typeof H==`string`?H:void 0;if(!q){json(g,400,{ok:!1,error:`docName required`});return}if(!J||!/^[0-9a-f]{40}$/i.test(J)){json(g,400,{ok:!1,error:`commitSha must be a valid 40-char commit SHA`});return}let te=B??`.`,ne=safeDocPath(q,te);if(`error`in ne){json(g,400,{ok:!1,error:ne.error});return}let ae=shadowGit(S),ce=Date.now();try{let s=getOrLoadRenameLogIndex(S.gitDir),w=createAncestorShaSetCache(),E=await resolveDocPathAtCommit(S,q,J,F?.()??`main`,s,e=>{let t=safeDocPath(e,te);return`error`in t?`${e}.md`:t.path},w);if(E===null){json(g,404,{ok:!1,error:`Commit ${J.slice(0,7)} does not contain document ${q} at any known historical path.`});return}let D=await ae.raw(`show`,`${J}:${E}`),O=new Date().toISOString();await safetyCheckpoint(S,te,{action:`rollback`,context:{docName:q,targetSha:J}});let j=t.documents.get(q);if(!j){json(g,409,{ok:!1,error:`Document is not currently open — open it in the editor first`});return}let{body:L}=stripFrontmatter(D),H=e.resolveEmbed?{resolveEmbed:e.resolveEmbed,sourcePath:q}:void 0,ne=mdManager.parseWithFallback(L,H),se=schema.nodeFromJSON(ne),ue=j.getXmlFragment(`default`);j.transact(()=>{updateYFragment(j,ue,se,{mapping:new Map,isOMark:new Map});let e=j.getText(`source`),t=e.toString();t!==D&&(e.delete(0,t.length),e.insert(0,D))},ROLLBACK_ORIGIN);let de;switch(k.kind){case`agent`:{let e=J.slice(0,8),t=k.summary.kind===`value`,s=t?k.summary:normalizeSummary(`Restored to ${e}`),g=st(s);de=t||!g.response?g.response:vt(g.response),recordContributor(q,k.writerId,k.displayName,k.colorSeed,formatRollbackSubject(q,J),k.actor,g.stored),incrementAgentWriteCalls(),Tt(s,!t);break}case`principal`:{let e=st(k.summary);de=e.response,recordContributor(q,k.writerId,k.displayName,k.colorSeed,formatRollbackSubject(q,J),k.actor,e.stored),Tt(k.summary,!1);break}case`anonymous`:log$2.debug({docName:q,commitSha:J.slice(0,8)},`[rollback] anonymous actor — no contributor recorded (no agentId in body and getPrincipal() returned null)`);break;default:throw Error(`Unhandled actor kind in handleRollback: ${String(k.kind)}`)}renameAttributionCounter().add(1,{kind:`rollback`,attribution_kind:k.kind}),Re(q,`rollback`);let fe=Date.now()-ce;if(console.log(`[rollback] docName=${q} from=${J.slice(0,8)} duration=${fe}ms`),oe){let e=`Restored to ${ee??J.slice(0,8)}: ${q}`,t=B??`.`;withParentLock(async()=>{let s=esm_default({baseDir:oe,timeout:{block:15e3}}),g=t||`.`;await s.add(g),await s.commit(e,{"--allow-empty":null}),console.log(`[rollback] parent-git commit: ${e}`)}).catch(e=>{console.warn(`[rollback] parent-git commit failed (non-fatal):`,e)})}k.kind===`agent`&&Y?.setFocus(k.writerId,{agentName:k.displayName,currentDoc:q,writeKind:`rollback-apply`,ts:Date.now()}),json(g,200,{ok:!0,restoredFrom:J,timestamp:O,...de?{summary:de}:{}})}catch(e){console.error(`[rollback]`,e),json(g,500,{ok:!1,error:e instanceof Error?e.message:`Failed to roll back document`})}}async function Vr(e,t){if(e.method!==`GET`){t.writeHead(405),t.end(`Method not allowed`);return}json(t,200,getMetrics())}async function Hr(e,t){if(e.method!==`GET`){t.writeHead(405),t.end(`Method not allowed`);return}json(t,200,getParseHealth())}async function Ur(e,t){if(e.method!==`GET`){t.writeHead(405),t.end(`Method not allowed`);return}let s=getActiveBranch(),g=L?.();json(t,200,{ok:!0,serverInstanceId:S,currentBranch:s,...g===void 0?{}:{currentDiskAckSVs:g}},{"Cache-Control":`no-store`})}async function Wr(e,t){if(!isLoopbackAddress(e.socket.remoteAddress)){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(e.method!==`GET`){t.writeHead(405),t.end(`Method not allowed`);return}let s=se?.()??null;if(!s){json(t,404,{error:`Principal not available`});return}json(t,200,s)}async function Gr(e,t){if(!isLoopbackAddress(e.socket.remoteAddress)){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(e.method!==`GET`){t.writeHead(405),t.end(`Method not allowed`);return}let s=ee?.getPresenceMap()??{},g=Date.now(),S={};for(let[e,t]of Object.entries(s))g-t.ts<2e4&&(S[e]=t);json(t,200,{presence:S})}async function Kr(e,t){if(!isLoopbackAddress(e.socket.remoteAddress)){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(e.method!==`GET`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s=resolve(g),S=s,w=!0;try{S=realpathSync(s)}catch(e){let g=e?.code;if(g===`ENOENT`)console.warn(`[workspace] contentDir does not exist; returning unresolved path`,{path:s}),w=!1;else{console.warn(`[workspace] realpath failed for contentDir`,{path:s,err:e}),json(t,500,{ok:!1,error:`workspace-realpath-failed`,code:g??null});return}}json(t,200,{ok:!0,contentDir:S,pathSeparator:sep,symlinkResolved:w})}async function qr(e,t){if(e.method!==`GET`){json(t,405,{ok:!1,error:`Method not allowed`});return}try{let s=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`).searchParams.get(`path`);if(!s||s.includes(`\0`)){json(t,400,{ok:!1,error:`Missing asset path`});return}let S=assetContentTypeForPath(s),w=extname(s).slice(1).toLowerCase();if(!S||!ASSET_EXTENSIONS.has(w)){json(t,415,{ok:!1,error:`Unsupported asset type`});return}let E=realpathSync(g),D=resolve(E,s),O;try{O=realpathSync(D)}catch{json(t,404,{ok:!1,error:`Asset not found`});return}if(!isWithinContentDir(O,E)){json(t,400,{ok:!1,error:`Invalid asset path`});return}let k;try{k=statSync(O)}catch{json(t,404,{ok:!1,error:`Asset not found`});return}if(!k.isFile()){json(t,404,{ok:!1,error:`Asset not found`});return}let j=toContentRelativePath(E,O);if(j!==s.split(`\\`).join(`/`)){json(t,400,{ok:!1,error:`Invalid asset path`});return}if(ce?.isPathIgnored(j)){json(t,404,{ok:!1,error:`Asset not found`});return}let F={"Content-Type":S,"Content-Length":String(k.size),"X-Content-Type-Options":`nosniff`,"Content-Disposition":INLINE_RENDERABLE_EXTENSIONS.has(w)?`inline`:`attachment`,"Cache-Control":`no-store`};w===`svg`&&(F[`Content-Security-Policy`]=`sandbox; default-src 'none'; style-src 'unsafe-inline'`),t.writeHead(200,F);try{await pipeline(createReadStream(O),t)}catch(e){console.error(`[asset]`,e),t.headersSent?t.destroyed||t.destroy(e instanceof Error?e:void 0):json(t,500,{ok:!1,error:`Failed to read asset`})}}catch(e){console.error(`[asset]`,e),json(t,500,{ok:!1,error:`Internal server error`})}}let Jr=1440*60*1e3;async function Yr(e,t){if(e.method!==`GET`){t.writeHead(405),t.end(`Method not allowed`);return}if(!O?.current){json(t,200,[]);return}let s=Date.now(),g=[],S=resolve(O.current.gitDir,`rescue`);if(existsSync(S))try{let e=readdirSync(S).filter(e=>isSupportedDocFile(e));for(let t of e){let e=resolve(S,t),w=statSync(e);if(s-w.mtimeMs>Jr){try{unlinkSync(e)}catch(e){console.debug(`[rescue] cleanup failed (non-critical):`,e)}continue}g.push({docName:stripDocExtension(t),timestamp:w.mtime.toISOString(),size:w.size,source:`flat`})}}catch(e){console.error(`[rescue] Failed to list flat-file rescue buffers:`,e)}try{let e=F?.()??`main`,t=await listRescueCheckpoints(O.current,e);for(let e of t)g.push({...e,source:`timeline`})}catch(e){console.error(`[rescue] Failed to list timeline-ref rescue checkpoints:`,e)}json(t,200,g)}async function Xr(e,t,s){if(e.method!==`GET`){t.writeHead(405),t.end(`Method not allowed`);return}if(!O?.current){t.writeHead(404),t.end(`Not found`);return}let g=resolve(O.current.gitDir,`rescue`),S=resolve(g,`${s}${getDocExtension(s)}`);if(!S.startsWith(`${g}/`)){t.writeHead(400),t.end(`Invalid document name`);return}if(existsSync(S)){let e=statSync(S);if(Date.now()-e.mtimeMs>Jr)try{unlinkSync(S)}catch{}else{let e=readFileSync(S,`utf-8`);t.writeHead(200,{"Content-Type":`text/markdown`,"X-Content-Type-Options":`nosniff`}),t.end(e);return}}try{let e=F?.()??`main`,g=(await listRescueCheckpoints(O.current,e)).filter(e=>e.docName===s).sort((e,t)=>t.timestamp.localeCompare(e.timestamp))[0];if(g){let e=shadowGit(O.current),s=((await e.raw(`ls-tree`,`-r`,g.sha)).trim().split(`
|
|
957
957
|
`)[0]??``).split(/\s+/)[2];if(s){let g=await e.raw(`cat-file`,`-p`,s);t.writeHead(200,{"Content-Type":`text/markdown`,"X-Content-Type-Options":`nosniff`}),t.end(g);return}}}catch(e){console.warn(`[rescue] timeline-ref fallback failed:`,e)}t.writeHead(404),t.end(`Not found`)}async function Zr(e,t){if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}try{let s;try{s=await readBody(e)}catch{json(t,413,{ok:!1,error:`Payload too large`});return}let S;try{S=JSON.parse(s.toString())}catch{json(t,400,{ok:!1,error:`Invalid JSON`});return}if(!S||typeof S!=`object`||Array.isArray(S)){json(t,400,{ok:!1,error:`Body must be a JSON object`});return}let E=extractActorIdentity(S,se);if(E.kind===`invalid-summary`){json(t,400,{ok:!1,error:`summary must be a string`});return}let{path:D}=S;if(!D||typeof D!=`string`||D.length===0){json(t,400,{ok:!1,error:`path is required`});return}if(!isSupportedDocFile(D)){json(t,400,{ok:!1,error:`path must end with .md or .mdx`});return}if(D.includes(`..`)||D.startsWith(`/`)||D.includes(`\0`)||D.includes(`\\`)){json(t,400,{ok:!1,error:`path must not contain .. or start with /`});return}let O=resolve(g),k=resolve(O,D);if(!k.startsWith(`${O}/`)&&k!==O){json(t,400,{ok:!1,error:`path must not escape content directory`});return}let j=stripDocExtension(D);if(isSystemDoc(j)||isConfigDoc(j)){json(t,400,{ok:!1,error:`'${j}' is a reserved document name`});return}mkdirSync(dirname(k),{recursive:!0});let F=``;try{writeFileSync(k,``,{encoding:`utf-8`,flag:`wx`})}catch(e){if(e.code===`EEXIST`){json(t,409,{ok:!1,error:`File already exists`});return}throw e}let L=stripDocExtension(D);switch(ce&&ce.incrementMdDir(dirname(L)),registerWrite(k,contentHash(``)),E.kind){case`agent`:case`principal`:recordContributor(L,E.writerId,E.displayName,E.colorSeed,void 0,E.actor);break;case`anonymous`:break;default:throw Error(`Unhandled actor kind in handleCreatePage: ${String(E.kind)}`)}let B=typeof w==`function`?w():null;B instanceof Map&&updateFileIndex({kind:`create`,path:k,docName:L,content:``},B),H&&(H.updateDocumentFromMarkdown(L,``),H.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist create-page cache for ${L}:`,e)}),J?.(`backlinks`),J?.(`graph`)),J?.(`files`),json(t,200,{ok:!0,docName:L})}catch(e){console.error(`[create-page]`,e),json(t,500,{ok:!1,error:`Failed to create page`})}}async function Qr(e,t){if(e.method!==`GET`){json(t,405,{ok:!1,error:`Method not allowed`});return}try{let s=new URL(e.url??``,`http://localhost`).searchParams.get(`docName`);if(!s||typeof s!=`string`||s.length===0){json(t,400,{ok:!1,error:`Missing docName parameter`});return}if(!isSafeDocName(s)){json(t,400,{ok:!1,error:`Invalid docName`});return}let g=ve(s);if(!g){json(t,400,{ok:!1,error:`Invalid docName`});return}if(!existsSync(g)){json(t,404,{ok:!1,error:`Page not found`});return}json(t,200,{ok:!0,docName:s,headings:extractHeadings(readFileSync(g,`utf-8`))})}catch(e){console.error(`[page-headings]`,e),json(t,500,{ok:!1,error:`Failed to read headings`})}}async function ji(e,t){if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}try{let s;try{s=await readBody(e)}catch{json(t,413,{ok:!1,error:`Payload too large`});return}let S;try{S=JSON.parse(s.toString())}catch{json(t,400,{ok:!1,error:`Invalid JSON`});return}if(!S||typeof S!=`object`||Array.isArray(S)){json(t,400,{ok:!1,error:`Body must be a JSON object`});return}let w=S,E=extractActorIdentity(w,se);if(E.kind===`invalid-summary`){json(t,400,{ok:!1,error:`summary must be a string`});return}let{kind:D,fromPath:O,toPath:k}=w;if(D!==`file`&&D!==`folder`){json(t,400,{ok:!1,error:`kind must be "file" or "folder"`});return}if(typeof O!=`string`||typeof k!=`string`){json(t,400,{ok:!1,error:`fromPath and toPath are required`});return}if(!isValidRelativeContentPath(O)||!isValidRelativeContentPath(k)){json(t,400,{ok:!1,error:`Paths must be relative content paths`});return}if(D===`file`&&(isSystemDoc(O)||isSystemDoc(k)||isConfigDoc(O)||isConfigDoc(k))){json(t,400,{ok:!1,error:`Reserved document names cannot be renamed`});return}if(O===`.ok`||O.startsWith(`.ok/`)||k===`.ok`||k.startsWith(`.ok/`)){json(t,400,{ok:!1,error:`.ok is a reserved directory`});return}if(O===k){json(t,200,{ok:!0,renamed:[],rewrittenDocs:[]});return}if(O.toLowerCase()===k.toLowerCase()){json(t,400,{ok:!1,error:`Case-only renames are not supported`});return}if(D===`file`&&probeAndRegisterSourceFileExtension(g,O),ce&&(D===`file`?ce.isExcluded(isSupportedDocFile(k)?k:`${k}${getDocExtension(O)}`):ce.isDirExcluded(k))){json(t,400,{ok:!1,error:`Destination ${D===`file`?`document`:`folder`} is excluded by the workspace content config`});return}let F;try{let e=E.kind===`agent`||E.kind===`principal`?{writerId:E.writerId,displayName:E.displayName,colorSeed:E.colorSeed,actorMetadata:E.actor}:void 0;F=await rt(O,k,D,{...e?{actor:e}:{}})}catch(e){if(e instanceof ManagedRenameCollisionError){json(t,409,{ok:!1,error:e.message,colliding:e.colliding});return}throw e}if(F.renamed.length===0){json(t,200,{ok:!0,renamed:[],rewrittenDocs:[]});return}let L;switch(E.kind){case`agent`:{let e=E.summary.kind===`value`,t=e?E.summary:normalizeSummary(`Renamed ${O} → ${k}`),s=st(t);L=e||!s.response?s.response:vt(s.response);for(let e=0;e<F.renamed.length;e++){let{fromDocName:t,toDocName:g}=F.renamed[e];recordContributor(g,E.writerId,E.displayName,E.colorSeed,formatRenameSubject(t,g),E.actor,e===0?s.stored:void 0)}incrementAgentWriteCalls(),Tt(t,!e);for(let{toDocName:e}of F.renamed)Re(e,`rename-path`);break}case`principal`:{let e=st(E.summary);L=e.response;for(let t=0;t<F.renamed.length;t++){let{fromDocName:s,toDocName:g}=F.renamed[t];recordContributor(g,E.writerId,E.displayName,E.colorSeed,formatRenameSubject(s,g),E.actor,t===0?e.stored:void 0)}Tt(E.summary,!1);for(let{toDocName:e}of F.renamed)Re(e,`rename-path`);break}case`anonymous`:log$2.debug({kind:D,fromPath:O,toPath:k,affectedDocs:F.renamed.length},`[rename-path] anonymous actor — no contributor recorded (no agentId in body and getPrincipal() returned null)`);break;default:throw Error(`Unhandled actor kind in handleRenamePath: ${String(E.kind)}`)}if(renameAttributionCounter().add(1,{kind:`rename-${D}`,attribution_kind:E.kind}),j)try{await j()}catch(e){console.warn(`[rename-log] WARN: post-rename drain failed:`,e)}json(t,200,{ok:!0,renamed:F.renamed,rewrittenDocs:F.rewrittenDocs,...L?{summary:L}:{}})}catch(e){console.error(`[rename-path]`,e);let{status:s,error:g}=Ue(e);json(t,s,{ok:!1,error:g})}}async function Hi(e,t){if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}try{let s;try{s=await readBody(e)}catch{json(t,413,{ok:!1,error:`Payload too large`});return}let S;try{S=JSON.parse(s.toString())}catch{json(t,400,{ok:!1,error:`Invalid JSON`});return}if(!S||typeof S!=`object`||Array.isArray(S)){json(t,400,{ok:!1,error:`Body must be a JSON object`});return}it(S);let{kind:E,path:D}=S;if(E!==`file`&&E!==`folder`){json(t,400,{ok:!1,error:`kind must be "file" or "folder"`});return}if(typeof D!=`string`||!isValidRelativeContentPath(D)){json(t,400,{ok:!1,error:`path must be a relative content path`});return}let O=resolveContentEntryPath(g,E,D);if(!existsSync(O)){json(t,404,{ok:!1,error:`${E} does not exist`});return}let k=statSync(O);if(E===`file`&&!k.isFile()||E===`folder`&&!k.isDirectory()){json(t,400,{ok:!1,error:`Target path is not a ${E}`});return}let j=E===`file`?[D]:listAffectedDocNames(w(),E,D);await We(j),E===`file`?unlinkSync(O):rmSync(O,{recursive:!0,force:!1}),json(t,200,{ok:!0,deletedDocNames:j})}catch(e){console.error(`[delete-path]`,e),json(t,500,{ok:!1,error:`Failed to delete path`})}}async function Ui(e,t){if(e.method!==`GET`){json(t,405,{ok:!1,error:`Method not allowed`});return}try{let e=w(),s=[];for(let[t,S]of e){let e=t,w=getDocExtension(t);try{e=extractPageTitle(readFileSync(resolve(g,`${t}${w}`),`utf-8`),t)}catch(e){console.warn(`[pages] Failed to read title for ${t}:`,e)}s.push({docName:t,title:e,docExt:w,size:S.size,modified:S.modified})}s.sort((e,t)=>e.docName.localeCompare(t.docName)),json(t,200,{ok:!0,pages:s})}catch(e){console.error(`[pages]`,e),json(t,500,{ok:!1,error:`Failed to list pages`})}}function Gi(e,t,s=`path`){let S=e.replace(/^\.\//,``).replace(/^\/+/,``).replace(/\/+$/,``);if(S.split(`/`).some(e=>e===`..`)||e.startsWith(`/`))return json(t,400,{ok:!1,error:`Invalid ${s}: must be project-root-relative`}),null;let w=resolve(g),E=S===``?w:resolve(w,S);return E!==w&&!E.startsWith(`${w}${sep}`)?(json(t,400,{ok:!1,error:`Path escapes content directory`}),null):{folderRel:S,resolvedContentDir:w}}let Ki=/^[A-Za-z0-9_-]+$/;function Yi(e,t){return!e||!Ki.test(e)?(json(t,400,{ok:!1,error:"Invalid name: must be letters / digits / `_` / `-` only (no `.md` extension)."}),!1):!0}function Xi(e){let t={};if(!e||typeof e!=`object`||Array.isArray(e))return t;for(let[s,g]of Object.entries(e))g!==void 0&&(t[s]=g);return t}async function Zi(e,t){if(e.method===`GET`)return ka(e,t);if(e.method===`PUT`)return _s(e,t);json(t,405,{ok:!1,error:`Method not allowed`})}async function ka(e,t){try{let s=Gi(new URL(e.url??``,`http://localhost`).searchParams.get(`path`)??``,t);if(!s)return;let g=await enrichDirectory(s.folderRel,{projectDir:s.resolvedContentDir}),{sources:S}=resolveNestedFrontmatterWithSources(s.resolvedContentDir,s.folderRel),w=resolve(s.resolvedContentDir,s.folderRel,`.ok`,`frontmatter.yml`),E=null;if(existsSync(w))try{let e=(0,import_dist$1.parse)(await readFile$1(w,`utf-8`));E=e&&typeof e==`object`&&!Array.isArray(e)?e:{}}catch(e){let t=e instanceof Error?e.message:String(e);console.warn(`[folder-config:get] malformed YAML in ${w}: ${t}`),E=null}json(t,200,{ok:!0,folder:g,frontmatter_local:E,frontmatter_sources:S})}catch(e){console.error(`[folder-config:get]`,e),json(t,500,{ok:!1,error:e instanceof Error?e.message:`internal error`})}}async function _s(e,t){try{let s=(await readBody(e)).toString(`utf-8`),g=JSON.parse(s),S=Gi(typeof g.path==`string`?g.path:``,t);if(!S)return;let w=S.folderRel===``?`**`:`${S.folderRel}/**`,E=applyNestedFolderRulesUpsert({projectDir:S.resolvedContentDir,rules:[{match:w,frontmatter:Xi(g.frontmatter)}]});if(!E.ok){json(t,E.error.code===`WRITE_ERROR`||E.error.code===`BAD_PROJECT_DIR`?500:400,{ok:!1,error:{code:E.error.code,message:E.error.message}});return}json(t,200,{ok:!0,applied:E.applied})}catch(e){console.error(`[folder-config:put]`,e),json(t,e instanceof SyntaxError?400:500,{ok:!1,error:e instanceof Error?e.message:`internal error`})}}async function xs(e,t){if(e.method===`GET`)return Cs(e,t);if(e.method===`PUT`)return Ts(e,t);if(e.method===`DELETE`)return Ds(e,t);json(t,405,{ok:!1,error:`Method not allowed`})}async function Cs(e,t){try{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`name`)??``;if(!Yi(g,t))return;let S=Gi(s.searchParams.get(`folder`)??``,t,`folder`);if(!S)return;let{folderRel:w,resolvedContentDir:E}=S,D=w===``?[]:w.split(`/`),O=null,k=null,j=null;for(let e=D.length;e>=0;e--){let t=e===0?``:D.slice(0,e).join(`/`),s=t===``?E:resolve(E,t);if(s!==E&&!s.startsWith(`${E}${sep}`))continue;let S=resolve(s,`.ok`,`templates`,`${g}.md`);if(existsSync(S)){O=S,k=t,j=e===D.length?`local`:`inherited`;break}}if(!O||k===null||j===null){json(t,404,{ok:!1,error:`Template "${g}" not found for folder "${w||`.`}". Walked leaf → root.`});return}let F=await readFile$1(O,`utf-8`),L=F.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/),B={},H=F;if(L){try{let e=(0,import_dist$1.parse)(L[1]);e&&typeof e==`object`&&!Array.isArray(e)&&(B=e)}catch{}H=F.slice(L[0].length)}let q=relative(E,O).split(/[\\/]/).filter(Boolean).join(`/`);json(t,200,{ok:!0,template:{name:g,folder:k,scope:j,path:q,frontmatter:B,body:H}})}catch(e){console.error(`[template:get]`,e),json(t,500,{ok:!1,error:e instanceof Error?e.message:`internal error`})}}async function Ts(e,t){try{let s=(await readBody(e)).toString(`utf-8`),g=JSON.parse(s),S=typeof g.name==`string`?g.name:``;if(!Yi(S,t))return;let w=Gi(typeof g.folder==`string`?g.folder:``,t,`folder`);if(!w)return;let E=applyTemplateWrite({projectDir:w.resolvedContentDir,folder:w.folderRel,name:S,body:typeof g.body==`string`?g.body:``,frontmatter:Xi(g.frontmatter)});if(!E.ok){json(t,E.error.code===`WRITE_ERROR`||E.error.code===`BAD_PROJECT_DIR`?500:400,{ok:!1,error:{code:E.error.code,message:E.error.message}});return}json(t,200,{ok:!0,path:E.path,created:E.created,warnings:E.warnings})}catch(e){console.error(`[template:put]`,e),json(t,e instanceof SyntaxError?400:500,{ok:!1,error:e instanceof Error?e.message:`internal error`})}}async function Ds(e,t){try{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`name`)??``;if(!Yi(g,t))return;let S=Gi(s.searchParams.get(`folder`)??``,t,`folder`);if(!S)return;let w=applyTemplateDelete({projectDir:S.resolvedContentDir,folder:S.folderRel,name:g});if(!w.ok){json(t,w.error.code===`WRITE_ERROR`||w.error.code===`BAD_PROJECT_DIR`?500:400,{ok:!1,error:{code:w.error.code,message:w.error.message}});return}json(t,200,{ok:!0,existed:w.existed,path:w.path})}catch(e){console.error(`[template:delete]`,e),json(t,500,{ok:!1,error:e instanceof Error?e.message:`internal error`})}}function Os(e){let t=new Map;for(let s of e){let e=s.path.split(`/`).filter(Boolean);e.pop();for(let g=1;g<=e.length;g++){let S=e.slice(0,g).join(`/`);t.set(S,Math.max(t.get(S)??0,s.modifiedTs))}}return[...t.entries()].map(([e,t])=>createWorkspaceSearchDocument({kind:`folder`,path:e,modifiedTs:t}))}function ks(e,t){let s=t.trim().toLowerCase();if(!s||!e)return;let g=e.toLowerCase().indexOf(s);if(g<0)return;let S=Math.max(0,g-80),w=Math.min(e.length,g+s.length+120),E=S>0?`...`:``,D=w<e.length?`...`:``;return`${E}${e.slice(S,w).replace(/\s+/g,` `).trim()}${D}`}function As(e){return e===`autocomplete`||e===`full_text`||e===`omnibar`?e:`omnibar`}function Ns(e){let t=typeof e==`string`?e.split(`,`):Array.isArray(e)?e:void 0;if(!t)return;let s=t.filter(e=>e===`page`||e===`folder`||e===`content`);return s.length>0?s:void 0}class Ps extends Error{constructor(e,t){super(t),this.status=e}}async function Is(e){if(e.method===`GET`){let t=new URL(e.url??``,`http://localhost`),s=t.searchParams.get(`limit`);return{query:t.searchParams.get(`query`)??``,intent:As(t.searchParams.get(`intent`)),scopes:Ns(t.searchParams.get(`scope`)??t.searchParams.get(`scopes`)),limit:s===null?void 0:Number(s)}}let t;try{t=await readBody(e)}catch{throw new Ps(413,`Payload too large`)}let s;try{let e=JSON.parse(t.toString());if(!e||typeof e!=`object`||Array.isArray(e))throw new Ps(400,`Invalid JSON body`);s=e}catch(e){throw e instanceof Ps?e:new Ps(400,`Invalid JSON body`)}return{query:typeof s.query==`string`?s.query:``,intent:As(s.intent),scopes:Ns(s.scopes??s.scope),limit:typeof s.limit==`number`?s.limit:Number(s.limit)}}async function Rs(){let e=[];for(let[t,s]of w()){if(isSystemDoc(t)||isConfigDoc(t))continue;let g=``,S=t;try{g=await readFile$1(s.canonicalPath,`utf-8`),S=extractPageTitle(g,t)}catch(e){console.warn(`[search] Failed to index ${t}:`,e)}e.push(createWorkspaceSearchDocument({kind:`page`,path:t,title:S,content:g,modifiedTs:Date.parse(s.modified)}))}return[...e,...Os(e)]}function $s(){return[...w()].filter(([e])=>!isSystemDoc(e)&&!isConfigDoc(e)).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>`${e}\u0000${t.modified}\u0000${t.size}\u0000${t.canonicalPath}\u0000${t.inode}\u0000${t.aliases.join(`,`)}`).join(``)}async function ec(){let e=`${g}\u0000${oe??``}`,t=$s(),s=workspaceSearchCaches.get(e);if(s?.fingerprint===t&&s.corpus)return s.corpus;if(s?.fingerprint===t&&s.pending)return s.pending;let S=Rs().then(e=>createWorkspaceSearchCorpus(e));workspaceSearchCaches.set(e,{fingerprint:t,pending:S});try{let s=await S;return workspaceSearchCaches.get(e)?.pending===S&&workspaceSearchCaches.set(e,{fingerprint:t,corpus:s}),s}catch(t){throw workspaceSearchCaches.get(e)?.pending===S&&workspaceSearchCaches.delete(e),t}}function tc(){if(process.env.NODE_ENV!==`test`)for(let e of[0,1e3,3e3])setTimeout(()=>{ec().catch(e=>{console.warn(`[search] Failed to prewarm workspace search cache:`,e)})},e)}tc();async function nc(e,t){if(e.method!==`GET`&&e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}try{let s=performance$1.now(),g=await Is(e);if(g.query.length>200){json(t,400,{ok:!1,error:`Query is too long`});return}let S=searchWorkspaceCorpus(await ec(),g.query,{intent:g.intent,scopes:g.scopes,limit:g.limit});json(t,200,{ok:!0,query:g.query,intent:g.intent,results:S.map(e=>({kind:e.document.kind,path:e.document.path,title:e.document.title,score:e.score,signals:e.signals,snippet:e.document.kind===`page`?ks(e.document.content,g.query):void 0})),elapsedMs:Math.max(0,performance$1.now()-s)})}catch(e){if(e instanceof Ps){json(t,e.status,{ok:!1,error:e.message});return}console.error(`[search]`,e),json(t,500,{ok:!1,error:`Failed to search workspace`})}}async function rc(e,s){if(e.method!==`GET`){json(s,405,{ok:!1,error:`Method not allowed`});return}try{let g=new URL(e.url??``,`http://localhost`).searchParams.get(`docName`);if(!g){json(s,400,{ok:!1,error:`Missing docName parameter`});return}if(!isSafeDocName(g)){json(s,400,{ok:!1,error:`Invalid docName`});return}if(isSystemDoc(g)||isConfigDoc(g)){json(s,400,{ok:!1,error:`'${g}' is a reserved document name`});return}json(s,200,{ok:!0,...await suggestLinks({hocuspocus:t,fileIndex:w(),docName:g})})}catch(e){if(e instanceof SuggestLinksTargetNotFoundError){json(s,404,{ok:!1,error:`Page not found`});return}console.error(`[suggest-links]`,e),json(s,500,{ok:!1,error:`Failed to suggest links`})}}async function ic(e,t){if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s;try{s=await readUploadBody(e,g)}catch(e){if(e instanceof UploadWriteError){if(e.reason===`malformed-upload`){json(t,400,{ok:!1,error:`malformed-upload`});return}if(e.reason===`storage-full`){json(t,507,{ok:!1,error:`storage-full`});return}if(e.reason===`storage-readonly`){json(t,500,{ok:!1,error:`storage-readonly`});return}json(t,500,{ok:!1,error:`storage-error`});return}json(t,400,{ok:!1,error:`Failed to parse upload: ${e instanceof Error?e.message:String(e)}`});return}let{filename:S,tempPath:w,sha:E,byteLength:D,parentDocName:O}=s,{agentId:k,agentName:j}=it(Object.fromEntries(new URL(e.url??``,`http://localhost`).searchParams.entries())),F=()=>{if(existsSync(w))try{unlinkSync(w)}catch{}};if(D===0){F(),json(t,400,{ok:!1,error:`No file received`});return}if(!O){F(),json(t,400,{ok:!1,error:`parentDocName is required`});return}if(O.includes(`\0`)||O.includes(`..`)||O.startsWith(`/`)){F(),json(t,400,{ok:!1,error:`path-escape`});return}let L=resolve(g),B=resolveUploadDestDir(O,`./`,L);if(!isWithinContentDir(B,L)){F(),json(t,400,{ok:!1,error:`path-escape`});return}try{assertNoSymlinkEscape(B,L)}catch(e){if(F(),(e instanceof Error?e.message:String(e)).startsWith(`symlink-escape:`)){json(t,400,{ok:!1,error:`path-escape`});return}log$2.error({err:e,destDir:B},`[upload] failed to validate destination directory`),json(t,500,{ok:!1,error:`storage-error`});return}try{mkdirSync(B,{recursive:!0})}catch(e){if(e.code!==`EEXIST`){F(),log$2.error({err:e,destDir:B},`[upload] failed to create attachment directory`),json(t,500,{ok:!1,error:`storage-error`});return}}try{let e=realpathSync(B),s;try{s=realpathSync(L)}catch{s=L}if(!isWithinContentDir(e,s)){F(),json(t,400,{ok:!1,error:`path-escape`});return}}catch{F(),json(t,400,{ok:!1,error:`path-escape`});return}let H=await fileTypeFromFile(w),q=H?.mime,J=H?.ext;if(!q){let e=readTempFileHead(w,256).toString(`utf-8`).replace(/^/,``).trimStart();(e.startsWith(`<svg`)||e.startsWith(`<?xml`)&&e.includes(`<svg`))&&(q=`image/svg+xml`,J=`svg`)}{let s=await findDuplicateAsset(B,E,D);if(s){F();let S=relative(g,resolve(B,s));log$2.info({event:`upload`,endpoint:e.url??`/api/upload`,agentId:k,agentName:j,dedup:!0,mime:q??null,size:D,destPath:S,httpStatus:200},`[upload] dedup hit`),json(t,200,{ok:!0,src:s,path:S,deduped:!0});return}}let Y;if(!S||S===`upload`||GENERIC_PASTE_NAMES.test(S)){let e=new Date().toISOString().replace(/[-:T]/g,``).slice(0,14).replace(/(\d{8})(\d{6})/,`$1-$2`),t=S?extname(S).slice(1):``,s=J??t??``;Y=s===``?`pasted-${e}`:`pasted-${e}.${s}`}else Y=sanitizeFilename(S);try{let s=linkTempToFinalWithCollisionRetry(w,B,Y),S=relative(g,resolve(B,s));log$2.info({event:`upload`,endpoint:e.url??`/api/upload`,agentId:k,agentName:j,dedup:!1,mime:q??null,size:D,destPath:S,httpStatus:200},`[upload] write ok`),json(t,200,{ok:!0,src:s,path:S,deduped:!1})}catch(s){let g=s instanceof Error?s.message:String(s),S=s instanceof UploadWriteError?s.reason:`unknown`;if(log$2.error({event:`upload`,endpoint:e.url??`/api/upload`,agentId:k,agentName:j,filename:Y,size:D,reason:S,message:g,httpStatus:s instanceof UploadWriteError&&s.reason===`storage-full`?507:500},`[upload] write failed`),s instanceof UploadWriteError){if(s.reason===`storage-full`){json(t,507,{ok:!1,error:`storage-full`});return}if(s.reason===`storage-readonly`){json(t,500,{ok:!1,error:`storage-readonly`});return}if(s.reason===`collision-exhaustion`){json(t,500,{ok:!1,error:`collision-exhaustion`});return}json(t,500,{ok:!1,error:`storage-error`});return}json(t,500,{ok:!1,error:`storage-error`})}}let ac=`/api/local-op/clone`,oc=`/api/local-op/open`,sc=600*1e3,cc=45e3;async function lc(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s,g;try{let S=await readBody(e),w=JSON.parse(S.toString());if(typeof w.url!=`string`||!w.url){json(t,400,{ok:!1,error:`Missing or invalid url`});return}if(typeof w.dir!=`string`||!w.dir){json(t,400,{ok:!1,error:`Missing or invalid dir`});return}s=w.url,g=w.dir}catch{json(t,400,{ok:!1,error:`Invalid JSON body`});return}if(!isAllowedGitUrl(s)){json(t,400,{ok:!1,error:`URL protocol not allowed`});return}if(!isSafeLocalPath(g)){json(t,400,{ok:!1,error:`dir must be within the user home directory`});return}if(!fe.tryAcquire(ac)){json(t,429,{ok:!1,error:`A clone 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 S=null,w=runCloneSubprocess({cliArgs:ae,url:s,dir:g,timeoutMs:sc,onEvent:e=>{if(e.type===`complete`){S=e.dir;return}e.type===`error`&&e.message&&log$2.warn({stderr:e.message,url:s,dir:g},`[local-op/clone] clone failed`),t.writableEnded||t.write(`${JSON.stringify(e)}\n`)}});(async()=>{try{if(await w.done,S&&!t.writableEnded){let e=await uc(S);t.writableEnded||(`port`in e?t.write(`${JSON.stringify({type:`complete`,port:e.port,dir:S})}\n`):t.write(`${JSON.stringify({type:`error`,message:e.error})}\n`))}}finally{t.writableEnded||t.end(),fe.release(ac)}})(),t.on(`close`,()=>{w.cancel()})}async function uc(e){let t=resolve(expandTilde(e)),s=getLocalDir(t),g=readUiLock(s);if(g&&g.port>0)return{port:g.port};let S=readServerLock(s),[w,...E]=ae,D=S&&S.port>0?`ui`:`start`,O=spawn(w,[...E,D],{cwd:t,detached:!0,stdio:[`ignore`,`ignore`,`pipe`],env:{...process.env,OK_LOCK_KIND:`interactive`,OK_PARENT_PID:String(process.pid)}}),k=[];O.stderr?.on(`data`,e=>{k.push(e),log$2.warn({cwd:t,cliCmd:D,msg:e.toString(`utf-8`).trim()},`[local-op/open] child stderr`)});let j=null;O.on(`exit`,e=>{j=e??-1}),O.unref();let F=Date.now()+45e3;for(;Date.now()<F;){await setTimeout$1(500);let e=readUiLock(s);if(e&&e.port>0)return{port:e.port};if(j!==null){let e=Buffer.concat(k).toString(`utf-8`).trim();return{error:`\`ok ${D}\` exited (code ${j})${e?` — ${e}`:``}`}}}let L=Buffer.concat(k).toString(`utf-8`).trim();return{error:`UI did not start within the expected time${L?` — ${L}`:``}`}}async function dc(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s;try{let g=await readBody(e),S=JSON.parse(g.toString());if(typeof S.dir!=`string`||!S.dir){json(t,400,{ok:!1,error:`Missing or invalid dir`});return}s=S.dir}catch{json(t,400,{ok:!1,error:`Invalid JSON body`});return}if(!isSafeLocalPath(s)){json(t,400,{ok:!1,error:`dir must be within the user home directory`});return}if(!fe.tryAcquire(oc)){json(t,429,{ok:!1,error:`A server-open operation is already in progress`});return}try{let e=await uc(s);`port`in e?json(t,200,{port:e.port}):json(t,504,{ok:!1,error:e.error})}finally{fe.release(oc)}}let fc=`/api/local-op/auth/login`,pc=`/api/local-op/auth/status`,mc=`/api/local-op/auth/repos`,hc=`/api/local-op/auth/signout`,gc=`/api/local-op/auth/pat`;async function _c(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s=`github.com`;try{let t=await readBody(e),g=JSON.parse(t.toString());typeof g.host==`string`&&g.host&&(s=g.host)}catch{json(t,400,{ok:!1,error:`Invalid JSON body`});return}if(!fe.tryAcquire(fc)){json(t,429,{ok:!1,error:`An auth login 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 g=runDeviceFlowSubprocess({cliArgs:ae,host:s,timeoutMs:sc,onEvent:e=>{t.writableEnded||t.write(`${JSON.stringify(e)}\n`)}}),S=()=>{g.cancel()};t.on(`close`,S),g.done.finally(()=>{t.off(`close`,S),t.writableEnded||t.end(),fe.release(fc)})}async function vc(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s=`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&&(s=e.host)}}catch{json(t,400,{ok:!1,error:`Invalid JSON body`});return}if(!fe.tryAcquire(pc)){json(t,429,{ok:!1,error:`An auth status operation is already in progress`});return}try{let[e,...g]=ae,S=[...g,`auth`,`status`,`--json`,`--host`,s],w=(await new Promise((t,s)=>{let g=spawn(e,S,{stdio:[`ignore`,`pipe`,`pipe`],env:{...process.env}}),w=setTimeout(()=>{g.kill(`SIGTERM`)},3e4),E=[];g.stdout.on(`data`,e=>E.push(e)),g.on(`close`,()=>{clearTimeout(w),t(Buffer.concat(E).toString(`utf-8`))}),g.on(`error`,e=>{clearTimeout(w),s(e)})})).split(`
|
|
958
958
|
`).map(e=>e.trim()).filter(Boolean),E=null;for(let e=w.length-1;e>=0;e--)try{E=JSON.parse(w[e]);break}catch{}E===null?json(t,200,{authenticated:!1}):json(t,200,E)}catch(e){json(t,500,{ok:!1,error:e instanceof Error?e.message:`auth status failed`})}finally{fe.release(pc)}}async function yc(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s=`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&&(s=e.host)}}catch{json(t,400,{ok:!1,error:`Invalid JSON body`});return}if(!fe.tryAcquire(mc)){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[g,...S]=ae,w=[...S,`auth`,`repos`,`--json`,`--host`,s],E=!1,D=spawn(g,w,{stdio:[`ignore`,`pipe`,`pipe`],env:{...process.env}}),O=setTimeout(()=>{D.kill(`SIGTERM`)},sc);D.stdout.on(`data`,e=>{t.writableEnded||t.write(e)}),D.stderr.on(`data`,e=>{log$2.debug({msg:e.toString(`utf-8`).trim()},`[local-op/auth/repos] stderr`)}),D.on(`close`,e=>{clearTimeout(O),E||(E=!0,e!==0&&!t.writableEnded&&t.write(`${JSON.stringify({type:`error`,message:`auth repos exited with code ${e}`})}\n`),t.end()),fe.release(mc)}),D.on(`error`,e=>{clearTimeout(O),E||(E=!0,t.writableEnded||(t.write(`${JSON.stringify({type:`error`,message:e.message})}\n`),t.end())),fe.release(mc)})}async function bc(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s=`github.com`;try{let t=await readBody(e),g=JSON.parse(t.toString());typeof g.host==`string`&&g.host&&(s=g.host)}catch{json(t,400,{ok:!1,error:`Invalid JSON body`});return}if(!fe.tryAcquire(hc)){json(t,429,{ok:!1,error:`An auth signout operation is already in progress`});return}try{let[e,...g]=ae,S=[...g,`auth`,`signout`,`--host`,s];await new Promise((t,s)=>{let g=spawn(e,S,{stdio:`ignore`,env:{...process.env}}),w=setTimeout(()=>{g.kill(`SIGTERM`)},3e4);g.on(`close`,()=>{clearTimeout(w),t()}),g.on(`error`,e=>{clearTimeout(w),s(e)})}),json(t,200,{ok:!0})}catch(e){json(t,500,{ok:!1,error:e instanceof Error?e.message:`auth signout failed`})}finally{fe.release(hc)}}async function xc(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s=`github.com`,g;try{let S=await readBody(e),w=JSON.parse(S.toString());if(typeof w.pat!=`string`||!w.pat){json(t,400,{ok:!1,error:`Missing or invalid pat`});return}g=w.pat,typeof w.host==`string`&&w.host&&(s=w.host)}catch{json(t,400,{ok:!1,error:`Invalid JSON body`});return}if(!fe.tryAcquire(gc)){json(t,429,{ok:!1,error:`An auth pat operation is already in progress`});return}try{let[e,...S]=ae,w=[...S,`auth`,`pat`,`--json`,`--host`,s],E=(await new Promise((t,s)=>{let S=spawn(e,w,{stdio:[`pipe`,`pipe`,`pipe`],env:{...process.env}}),E=setTimeout(()=>{S.kill(`SIGTERM`)},3e4);S.stdin.write(`${g}\n`),S.stdin.end();let D=[];S.stdout.on(`data`,e=>D.push(e)),S.on(`close`,e=>{clearTimeout(E),e===0?t(Buffer.concat(D).toString(`utf-8`)):s(Error(`auth pat exited with code ${e}`))}),S.on(`error`,e=>{clearTimeout(E),s(e)})})).split(`
|
|
959
|
-
`).map(e=>e.trim()).filter(Boolean),D=null;for(let e=E.length-1;e>=0;e--)try{D=JSON.parse(E[e]);break}catch{}D===null?json(t,200,{ok:!0}):json(t,200,D)}catch(e){json(t,500,{ok:!1,error:e instanceof Error?e.message:`auth pat failed`})}finally{fe.release(gc)}}async function Sc(e,t){if(checkLocalOpSecurity(e,t,json)){if(e.method!==`GET`){json(t,405,{ok:!1,error:`Method not allowed`});return}if(!oe){json(t,400,{ok:!1,error:`No project directory configured`});return}try{json(t,200,{ok:!0,identity:await resolveGitIdentity(oe)})}catch(e){json(t,500,{ok:!1,error:e instanceof Error?e.message:`identity resolution failed`})}}}let Cc=`/api/local-op/auth/set-identity`;async function wc(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s,g;try{let S=await readBody(e),w=JSON.parse(S.toString());if(typeof w.name!=`string`||!w.name.trim()){json(t,400,{ok:!1,error:`Missing or invalid name`});return}if(typeof w.email!=`string`||!w.email.trim()){json(t,400,{ok:!1,error:`Missing or invalid email`});return}s=w.name.trim(),g=w.email.trim()}catch{json(t,400,{ok:!1,error:`Invalid JSON body`});return}if(!oe){json(t,400,{ok:!1,error:`No project directory configured`});return}if(!fe.tryAcquire(Cc)){json(t,429,{ok:!1,error:`A set-identity operation is already in progress`});return}try{writeGitIdentity(oe,s,g),ne?.()?.refreshIdentity().catch(()=>{}),json(t,200,{ok:!0})}catch(e){json(t,500,{ok:!1,error:e instanceof Error?e.message:`set-identity failed`})}finally{fe.release(Cc)}}async function Tc(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`GET`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s=ne?.();if(!s){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,s.getStatus())}async function Ec(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s=ne?.();if(!s){json(t,503,{ok:!1,error:`Sync engine not active`});return}let g=`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`)&&(g=e.op)}}catch{}json(t,202,{ok:!0,op:g}),s.trigger(g)}async function Dc(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`GET`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s=ne?.();json(t,200,{conflicts:s?s.getConflicts():[]})}async function Oc(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s=ne?.();if(!s){json(t,503,{ok:!1,error:`Sync engine not active`});return}let g;try{let t=await readBody(e);g=JSON.parse(t.toString())}catch{json(t,400,{ok:!1,error:`Invalid JSON body`});return}let{file:S,strategy:w,content:E}=g;if(!S||typeof S!=`string`){json(t,400,{ok:!1,error:`Missing required field: file`});return}if(w!==`mine`&&w!==`theirs`&&w!==`content`){json(t,400,{ok:!1,error:`Invalid strategy: must be 'mine', 'theirs', or 'content'`});return}try{await s.resolveConflict(S,w,E),json(t,200,{ok:!0})}catch(e){json(t,500,{ok:!1,error:e instanceof Error?e.message:String(e)})}}async function kc(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`GET`){json(t,405,{ok:!1,error:`Method not allowed`});return}if(!oe){json(t,503,{ok:!1,error:`Project repo not configured`});return}let s=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`).searchParams.get(`file`);if(!s){json(t,400,{ok:!1,error:`Missing required query param: file`});return}if(s.includes(`..`)||s.startsWith(`/`)){json(t,400,{ok:!1,error:`Invalid file path`});return}let g=esm_default({baseDir:oe,timeout:{block:15e3}});async function S(e){try{return await g.raw([`show`,`:${e}:${s}`])}catch{return``}}try{let[e,g,w]=await Promise.all([S(1),S(2),S(3)]);json(t,200,{ok:!0,file:s,base:e,ours:g,theirs:w})}catch(e){json(t,500,{ok:!1,error:e instanceof Error?e.message:String(e)})}}async function Ac(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`GET`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s=new URL(e.url??`/`,`http://localhost`).searchParams.get(`rootDir`)??void 0;try{json(t,200,{ok:!0,plan:await planSeed({projectDir:g,rootDir:s})})}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 jc(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s;try{let g=await readBody(e),S=JSON.parse(g.toString());if(!S.plan||typeof S.plan!=`object`){json(t,400,{ok:!1,error:`Missing or invalid plan`});return}s=S.plan}catch{json(t,400,{ok:!1,error:`Invalid JSON body`});return}try{json(t,200,{ok:!0,result:await applySeed(s,{projectDir:g})})}catch(e){json(t,500,{ok:!1,error:{kind:`internal`,message:e instanceof Error?e.message:String(e)}})}}async function Mc(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s={};try{let g=await readBody(e);if(g.length>0){let e=JSON.parse(g.toString());if(typeof e.noOpen==`boolean`&&(s.noOpen=e.noOpen),typeof e.force==`boolean`&&(s.force=e.force),typeof e.out==`string`){if(!isSafeLocalPath(e.out)){json(t,400,{ok:!1,error:`Output path must be within home directory`});return}s.out=e.out}}}catch{json(t,400,{ok:!1,error:`Invalid JSON body`});return}try{json(t,200,await buildAndOpenSkill(s))}catch(e){json(t,500,{ok:!1,error:{kind:`internal`,message:e instanceof Error?e.message:String(e)}})}}async function Nc(e,t){if(checkLocalOpSecurity(e,t,json)){if(e.method!==`GET`){json(t,405,{ok:!1,error:`Method not allowed`});return}try{json(t,200,{ok:!0,...await readSkillInstallStateSnapshot(homedir())},{"Cache-Control":`no-store`})}catch(e){json(t,500,{ok:!1,error:{kind:`internal`,message:e instanceof Error?e.message:String(e)}})}}}async function Pc(e,t){if(checkLocalOpSecurity(e,t,json))return handleInstalledAgents(e,t,_e.probeAll)}async function Fc(e,t){if(checkLocalOpSecurity(e,t,json))return handleSpawnCursor(e,t,{contentDir:g,platform:process.platform})}async function Ic(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s=ne?.();if(!s){json(t,503,{ok:!1,error:`Sync engine not active`});return}try{await s.abortMerge(),json(t,200,{ok:!0})}catch(e){json(t,500,{ok:!1,error:e instanceof Error?e.message:String(e)})}}let Lc={"/api/document":jt,"/api/documents":Mt,"/api/backlinks":Ft,"/api/backlink-counts":It,"/api/forward-links":Lt,"/api/link-graph":Rt,"/api/dead-links":Vt,"/api/orphans":zt,"/api/hubs":Bt,"/api/tags":Ht,"/api/pages":Ui,"/api/folder-config":Zi,"/api/template":xs,"/api/search":nc,"/api/suggest-links":rc,"/api/page-headings":Qr,"/api/create-page":Zr,"/api/rename-path":ji,"/api/delete-path":Hi,"/api/upload":ic,"/api/agent-write":Et,"/api/agent-write-md":Dt,"/api/agent-patch":Wt,"/api/agent-undo":Kt,"/api/agent-activity":$t,"/api/agent-burst-diff":en,"/api/save-version":Fr,"/api/history":Ir,"/api/diff":zr,"/api/rollback":Br,"/api/metrics/reconciliation":Vr,"/api/metrics/parse-health":Hr,"/api/metrics/agent-presence":Gr,"/api/server-info":Ur,"/api/principal":Wr,"/api/rescue":Yr,"/api/asset":qr,"/api/workspace":Kr,"/api/sync/status":Tc,"/api/sync/trigger":Ec,"/api/sync/conflicts":Dc,"/api/sync/conflict-content":kc,"/api/sync/resolve-conflict":Oc,"/api/sync/abort-merge":Ic,"/api/local-op/clone":lc,"/api/local-op/open":dc,"/api/local-op/auth/login":_c,"/api/local-op/auth/status":vc,"/api/local-op/auth/repos":yc,"/api/local-op/auth/signout":bc,"/api/local-op/auth/pat":xc,"/api/local-op/auth/identity":Sc,"/api/local-op/auth/set-identity":wc,"/api/installed-agents":Pc,"/api/spawn-cursor":Fc,"/api/install-skill":Mc,"/api/skill/install-state":Nc,"/api/seed/plan":Ac,"/api/seed/apply":jc};D&&(Lc[`/api/test-reset`]=jr,Lc[`/api/test-rescan-backlinks`]=Mr);let Rc=new Set([`/api/upload`,`/api/create-page`,`/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/resolve-conflict`,`/api/sync/abort-merge`,`/api/test-reset`,`/api/test-rescan-backlinks`,`/api/install-skill`,`/api/folder-config`,`/api/template`]),zc=[`/api/local-op/`];return{priority:100,async onRequest({request:e,response:t}){let s=e.url?.split(`?`)[0];if(!s)return;if(s.startsWith(`/api/`)){let s=e.headers.origin;if(s!==void 0&&!isAllowedApiOrigin(s)){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`&&(s!==void 0&&(t.setHeader(`Access-Control-Allow-Origin`,s),t.setHeader(`Vary`,`Origin`)),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization, traceparent, tracestate, baggage`)),e.method===`OPTIONS`){t.writeHead(204),t.end();return}}if(Rc.has(s)||zc.some(e=>s.startsWith(e))){let s=e.socket?.remoteAddress;if(s!==void 0&&!isLoopbackAddress(s)){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(!s.startsWith(`/api/`))return;let g=propagation.extract(context.active(),e.headers),S=e.method??`GET`,w=s;s.startsWith(`/api/rescue/`)?w=`/api/rescue/:docName`:s.startsWith(`/api/history/`)?w=`/api/history/:sha`:s.startsWith(`/api/tags/`)&&(w=`/api/tags/:name`);let E=getTracer(),D=Date.now();await context.with(g,()=>E.startActiveSpan(`HTTP ${S} ${w}`,{kind:SpanKind.SERVER,attributes:{[ATTR_HTTP_REQUEST_METHOD]:S,[ATTR_HTTP_ROUTE]:w,[ATTR_URL_PATH]:s,[ATTR_URL_SCHEME]:`http`,[ATTR_USER_AGENT_ORIGINAL]:e.headers[`user-agent`]??``}},async g=>{try{let S=Lc[s];if(S)await S(e,t);else if(s.startsWith(`/api/rescue/`)){let g=decodeURIComponent(s.slice(12));g&&await Xr(e,t,g)}else if(s.startsWith(`/api/history/`)){let g=decodeURIComponent(s.slice(13));g&&await Lr(e,t,g)}else if(s.startsWith(`/api/tags/`)){let g=s.slice(10);g&&await Ut(e,t,g)}let w=t.statusCode;g.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE,w),w>=500&&g.setStatus({code:SpanStatusCode.ERROR,message:`status ${w}`})}catch(e){throw g.recordException(e),g.setStatus({code:SpanStatusCode.ERROR,message:e instanceof Error?e.message:String(e)}),e}finally{g.end();let e=(Date.now()-D)/1e3;httpDurationHist().record(e,{[ATTR_HTTP_REQUEST_METHOD]:S,[ATTR_HTTP_ROUTE]:w,[ATTR_HTTP_RESPONSE_STATUS_CODE]:t.statusCode})}}))}}}function isWithinDir(e,t){return e===t?!0:e.startsWith(`${t}${sep}`)}function errnoCode(e){let t=e?.code;return typeof t==`string`?t:void 0}function seedBasenameIndex(e){let t=e.contentDir,s=new Set;function g(S){let w;try{w=readdirSync(S,{withFileTypes:!0})}catch(t){let s=errnoCode(t);s!==`ENOENT`&&e.onSkip?.(`read-failed`,s,S);return}for(let E of w){let w=join(S,E.name),D=relative(t,w);if(D.startsWith(`..`)||e.contentFilter?.isDirExcluded(D)&&E.isDirectory())continue;let O;try{O=lstatSync(w)}catch(t){let s=errnoCode(t);s!==`ENOENT`&&e.onSkip?.(`lstat-failed`,s,w);continue}if(O.isSymbolicLink()){let S;try{S=realpathSync(w)}catch(t){let s=errnoCode(t);s!==`ENOENT`&&e.onSkip?.(`realpath-failed`,s,w);continue}if(!isWithinDir(S,t)){e.onSkip?.(`symlink-escape`,void 0,w);continue}let E;try{E=statSync(S)}catch(t){let s=errnoCode(t);s!==`ENOENT`&&e.onSkip?.(`symlink-stat-failed`,s,S);continue}if(s.has(E.ino))continue;s.add(E.ino),E.isDirectory()?g(S):E.isFile()&&isSupportedAssetFile(w,ASSET_EXTENSIONS)&&!e.contentFilter?.isExcluded(D)&&e.basenameIndex.add(D);continue}if(O.isDirectory()){if(s.has(O.ino))continue;s.add(O.ino),g(w);continue}O.isFile()&&isSupportedAssetFile(w,ASSET_EXTENSIONS)&&!e.contentFilter?.isExcluded(D)&&e.basenameIndex.add(D)}}g(t)}const HocuspocusAuthTokenSchema=object$1({principalId:string().optional(),tabSessionId:string().optional(),expectedServerInstanceId:string().optional(),expectedBranch:string().optional()}).loose(),HOCUSPOCUS_AUTH_REJECTION_REASONS=[`server-instance-mismatch`,`branch-mismatch`];function isHocuspocusAuthRejectionReason(e){return HOCUSPOCUS_AUTH_REJECTION_REASONS.includes(e)}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 s=HocuspocusAuthTokenSchema.safeParse(t);return s.success?s.data:void 0}const DEFAULT_WARN_BEFORE_MS=300*1e3;function attachIdleShutdown(e){let t=e.scheduler??defaultScheduler,s=e.warnBeforeMs??DEFAULT_WARN_BEFORE_MS,g=0,S=null,w=null,E=!1,D=!1;function O(){S!==null&&(t.clearTimeout(S),S=null),w!==null&&(t.clearTimeout(w),w=null)}function k(){O(),!(D||E)&&g===0&&(s>0&&s<e.thresholdMs&&(w=t.setTimeout(()=>{w=null,g===0&&!E&&e.log?.warn({msUntilShutdown:s,webSocketClientCount:0},`idle shutdown pending: no WebSocket clients`)},e.thresholdMs-s)),S=t.setTimeout(()=>{if(S=null,!(D||E)&&g===0){E=!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 j=(e,t)=>{e.url?.startsWith(`/collab`)&&(g++,O(),t.once(`close`,()=>{g--,g<0&&(g=0),g===0&&k()}))};return e.httpServer.on(`upgrade`,j),k(),{detach:()=>{D||(D=!0,e.httpServer.off(`upgrade`,j),O())}}}const MCP_SERVER_NAME=`open-knowledge`;function buildInstructions(e){return`# Open Knowledge (OK) — collaborative markdown via MCP
|
|
959
|
+
`).map(e=>e.trim()).filter(Boolean),D=null;for(let e=E.length-1;e>=0;e--)try{D=JSON.parse(E[e]);break}catch{}D===null?json(t,200,{ok:!0}):json(t,200,D)}catch(e){json(t,500,{ok:!1,error:e instanceof Error?e.message:`auth pat failed`})}finally{fe.release(gc)}}async function Sc(e,t){if(checkLocalOpSecurity(e,t,json)){if(e.method!==`GET`){json(t,405,{ok:!1,error:`Method not allowed`});return}if(!oe){json(t,400,{ok:!1,error:`No project directory configured`});return}try{json(t,200,{ok:!0,identity:await resolveGitIdentity(oe)})}catch(e){json(t,500,{ok:!1,error:e instanceof Error?e.message:`identity resolution failed`})}}}let Cc=`/api/local-op/auth/set-identity`;async function wc(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s,g;try{let S=await readBody(e),w=JSON.parse(S.toString());if(typeof w.name!=`string`||!w.name.trim()){json(t,400,{ok:!1,error:`Missing or invalid name`});return}if(typeof w.email!=`string`||!w.email.trim()){json(t,400,{ok:!1,error:`Missing or invalid email`});return}s=w.name.trim(),g=w.email.trim()}catch{json(t,400,{ok:!1,error:`Invalid JSON body`});return}if(!oe){json(t,400,{ok:!1,error:`No project directory configured`});return}if(!fe.tryAcquire(Cc)){json(t,429,{ok:!1,error:`A set-identity operation is already in progress`});return}try{writeGitIdentity(oe,s,g),ne?.()?.refreshIdentity().catch(()=>{}),json(t,200,{ok:!0})}catch(e){json(t,500,{ok:!1,error:e instanceof Error?e.message:`set-identity failed`})}finally{fe.release(Cc)}}async function Tc(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`GET`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s=ne?.();if(!s){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,s.getStatus())}async function Ec(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s=ne?.();if(!s){json(t,503,{ok:!1,error:`Sync engine not active`});return}let g=`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`)&&(g=e.op)}}catch{}json(t,202,{ok:!0,op:g}),s.trigger(g)}async function Dc(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`GET`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s=ne?.();json(t,200,{conflicts:s?s.getConflicts():[]})}async function Oc(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s=ne?.();if(!s){json(t,503,{ok:!1,error:`Sync engine not active`});return}let g;try{let t=await readBody(e);g=JSON.parse(t.toString())}catch{json(t,400,{ok:!1,error:`Invalid JSON body`});return}let{file:S,strategy:w,content:E}=g;if(!S||typeof S!=`string`){json(t,400,{ok:!1,error:`Missing required field: file`});return}if(w!==`mine`&&w!==`theirs`&&w!==`content`){json(t,400,{ok:!1,error:`Invalid strategy: must be 'mine', 'theirs', or 'content'`});return}try{await s.resolveConflict(S,w,E),json(t,200,{ok:!0})}catch(e){json(t,500,{ok:!1,error:e instanceof Error?e.message:String(e)})}}async function kc(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`GET`){json(t,405,{ok:!1,error:`Method not allowed`});return}if(!oe){json(t,503,{ok:!1,error:`Project repo not configured`});return}let s=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`).searchParams.get(`file`);if(!s){json(t,400,{ok:!1,error:`Missing required query param: file`});return}if(s.includes(`..`)||s.startsWith(`/`)){json(t,400,{ok:!1,error:`Invalid file path`});return}let g=esm_default({baseDir:oe,timeout:{block:15e3}});async function S(e){try{return await g.raw([`show`,`:${e}:${s}`])}catch{return``}}try{let[e,g,w]=await Promise.all([S(1),S(2),S(3)]);json(t,200,{ok:!0,file:s,base:e,ours:g,theirs:w})}catch(e){json(t,500,{ok:!1,error:e instanceof Error?e.message:String(e)})}}async function Ac(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`GET`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s=new URL(e.url??`/`,`http://localhost`).searchParams.get(`rootDir`)??void 0;try{json(t,200,{ok:!0,plan:await planSeed({projectDir:g,rootDir:s})})}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 jc(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s;try{let g=await readBody(e),S=JSON.parse(g.toString());if(!S.plan||typeof S.plan!=`object`){json(t,400,{ok:!1,error:`Missing or invalid plan`});return}s=S.plan}catch{json(t,400,{ok:!1,error:`Invalid JSON body`});return}try{json(t,200,{ok:!0,result:await applySeed(s,{projectDir:g})})}catch(e){json(t,500,{ok:!1,error:{kind:`internal`,message:e instanceof Error?e.message:String(e)}})}}async function Mc(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s={};try{let g=await readBody(e);if(g.length>0){let e=JSON.parse(g.toString());if(typeof e.noOpen==`boolean`&&(s.noOpen=e.noOpen),typeof e.force==`boolean`&&(s.force=e.force),typeof e.out==`string`){if(!isSafeLocalPath(e.out)){json(t,400,{ok:!1,error:`Output path must be within home directory`});return}s.out=e.out}}}catch{json(t,400,{ok:!1,error:`Invalid JSON body`});return}try{json(t,200,await buildAndOpenSkill(s))}catch(e){json(t,500,{ok:!1,error:{kind:`internal`,message:e instanceof Error?e.message:String(e)}})}}async function Nc(e,t){if(checkLocalOpSecurity(e,t,json)){if(e.method!==`GET`){json(t,405,{ok:!1,error:`Method not allowed`});return}try{json(t,200,{ok:!0,...await readSkillInstallStateSnapshot(homedir())},{"Cache-Control":`no-store`})}catch(e){json(t,500,{ok:!1,error:{kind:`internal`,message:e instanceof Error?e.message:String(e)}})}}}async function Pc(e,t){if(checkLocalOpSecurity(e,t,json))return handleInstalledAgents(e,t,_e.probeAll)}async function Fc(e,t){if(checkLocalOpSecurity(e,t,json))return handleSpawnCursor(e,t,{contentDir:g,platform:process.platform})}async function Ic(e,t){if(!checkLocalOpSecurity(e,t,json))return;if(e.method!==`POST`){json(t,405,{ok:!1,error:`Method not allowed`});return}let s=ne?.();if(!s){json(t,503,{ok:!1,error:`Sync engine not active`});return}try{await s.abortMerge(),json(t,200,{ok:!0})}catch(e){json(t,500,{ok:!1,error:e instanceof Error?e.message:String(e)})}}let Lc={"/api/document":jt,"/api/documents":Mt,"/api/backlinks":Ft,"/api/backlink-counts":It,"/api/forward-links":Lt,"/api/link-graph":Rt,"/api/dead-links":Vt,"/api/orphans":zt,"/api/hubs":Bt,"/api/tags":Ht,"/api/pages":Ui,"/api/folder-config":Zi,"/api/template":xs,"/api/search":nc,"/api/suggest-links":rc,"/api/page-headings":Qr,"/api/create-page":Zr,"/api/rename-path":ji,"/api/delete-path":Hi,"/api/upload":ic,"/api/agent-write":Et,"/api/agent-write-md":Dt,"/api/agent-patch":Wt,"/api/agent-undo":Kt,"/api/agent-activity":$t,"/api/agent-burst-diff":en,"/api/save-version":Fr,"/api/history":Ir,"/api/diff":zr,"/api/rollback":Br,"/api/metrics/reconciliation":Vr,"/api/metrics/parse-health":Hr,"/api/metrics/agent-presence":Gr,"/api/server-info":Ur,"/api/principal":Wr,"/api/rescue":Yr,"/api/asset":qr,"/api/workspace":Kr,"/api/sync/status":Tc,"/api/sync/trigger":Ec,"/api/sync/conflicts":Dc,"/api/sync/conflict-content":kc,"/api/sync/resolve-conflict":Oc,"/api/sync/abort-merge":Ic,"/api/local-op/clone":lc,"/api/local-op/open":dc,"/api/local-op/auth/login":_c,"/api/local-op/auth/status":vc,"/api/local-op/auth/repos":yc,"/api/local-op/auth/signout":bc,"/api/local-op/auth/pat":xc,"/api/local-op/auth/identity":Sc,"/api/local-op/auth/set-identity":wc,"/api/installed-agents":Pc,"/api/spawn-cursor":Fc,"/api/install-skill":Mc,"/api/skill/install-state":Nc,"/api/seed/plan":Ac,"/api/seed/apply":jc};D&&(Lc[`/api/test-reset`]=jr,Lc[`/api/test-rescan-backlinks`]=Mr);let Rc=new Set([`/api/upload`,`/api/create-page`,`/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/resolve-conflict`,`/api/sync/abort-merge`,`/api/test-reset`,`/api/test-rescan-backlinks`,`/api/install-skill`,`/api/folder-config`,`/api/template`]),zc=[`/api/local-op/`];return{priority:100,async onRequest({request:e,response:t}){let s=e.url?.split(`?`)[0];if(!s)return;if(s.startsWith(`/api/`)){let s=e.headers.origin;if(s!==void 0&&!isAllowedApiOrigin(s)){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`&&(s!==void 0&&(t.setHeader(`Access-Control-Allow-Origin`,s),t.setHeader(`Vary`,`Origin`)),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization, traceparent, tracestate, baggage`)),e.method===`OPTIONS`){t.writeHead(204),t.end();return}}if(Rc.has(s)||zc.some(e=>s.startsWith(e))){let s=e.socket?.remoteAddress;if(s!==void 0&&!isLoopbackAddress(s)){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(!s.startsWith(`/api/`))return;let g=propagation.extract(context.active(),e.headers),S=e.method??`GET`,w=s;s.startsWith(`/api/rescue/`)?w=`/api/rescue/:docName`:s.startsWith(`/api/history/`)?w=`/api/history/:sha`:s.startsWith(`/api/tags/`)&&(w=`/api/tags/:name`);let E=getTracer(),D=Date.now();await context.with(g,()=>E.startActiveSpan(`HTTP ${S} ${w}`,{kind:SpanKind.SERVER,attributes:{[ATTR_HTTP_REQUEST_METHOD]:S,[ATTR_HTTP_ROUTE]:w,[ATTR_URL_PATH]:s,[ATTR_URL_SCHEME]:`http`,[ATTR_USER_AGENT_ORIGINAL]:e.headers[`user-agent`]??``}},async g=>{try{let S=Lc[s];if(S)await S(e,t);else if(s.startsWith(`/api/rescue/`)){let g=decodeURIComponent(s.slice(12));g&&await Xr(e,t,g)}else if(s.startsWith(`/api/history/`)){let g=decodeURIComponent(s.slice(13));g&&await Lr(e,t,g)}else if(s.startsWith(`/api/tags/`)){let g=s.slice(10);g&&await Ut(e,t,g)}let w=t.statusCode;g.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE,w),w>=500&&g.setStatus({code:SpanStatusCode.ERROR,message:`status ${w}`})}catch(e){throw g.recordException(e),g.setStatus({code:SpanStatusCode.ERROR,message:e instanceof Error?e.message:String(e)}),e}finally{g.end();let e=(Date.now()-D)/1e3;httpDurationHist().record(e,{[ATTR_HTTP_REQUEST_METHOD]:S,[ATTR_HTTP_ROUTE]:w,[ATTR_HTTP_RESPONSE_STATUS_CODE]:t.statusCode})}}))}}}function isWithinDir(e,t){return e===t?!0:e.startsWith(`${t}${sep}`)}function errnoCode(e){let t=e?.code;return typeof t==`string`?t:void 0}function seedBasenameIndex(e){let t=e.contentDir,s=new Set;function g(S){let w;try{w=readdirSync(S,{withFileTypes:!0})}catch(t){let s=errnoCode(t);s!==`ENOENT`&&e.onSkip?.(`read-failed`,s,S);return}for(let E of w){let w=join(S,E.name),D=relative(t,w);if(D.startsWith(`..`)||e.contentFilter?.isDirExcluded(D)&&E.isDirectory())continue;let O;try{O=lstatSync(w)}catch(t){let s=errnoCode(t);s!==`ENOENT`&&e.onSkip?.(`lstat-failed`,s,w);continue}if(O.isSymbolicLink()){let S;try{S=realpathSync(w)}catch(t){let s=errnoCode(t);s!==`ENOENT`&&e.onSkip?.(`realpath-failed`,s,w);continue}if(!isWithinDir(S,t)){e.onSkip?.(`symlink-escape`,void 0,w);continue}let E;try{E=statSync(S)}catch(t){let s=errnoCode(t);s!==`ENOENT`&&e.onSkip?.(`symlink-stat-failed`,s,S);continue}if(s.has(E.ino))continue;s.add(E.ino),E.isDirectory()?g(S):E.isFile()&&isSupportedAssetFile(w,ASSET_EXTENSIONS)&&!e.contentFilter?.isExcluded(D)&&e.basenameIndex.add(D);continue}if(O.isDirectory()){if(s.has(O.ino))continue;s.add(O.ino),g(w);continue}O.isFile()&&isSupportedAssetFile(w,ASSET_EXTENSIONS)&&!e.contentFilter?.isExcluded(D)&&e.basenameIndex.add(D)}}g(t)}const HocuspocusAuthTokenSchema=object$1({principalId:string().optional(),tabSessionId:string().optional(),expectedServerInstanceId:string().optional(),expectedBranch:string().optional()}).loose(),HOCUSPOCUS_AUTH_REJECTION_REASONS=[`server-instance-mismatch`,`branch-mismatch`];function isHocuspocusAuthRejectionReason(e){return HOCUSPOCUS_AUTH_REJECTION_REASONS.includes(e)}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 s=HocuspocusAuthTokenSchema.safeParse(t);return s.success?s.data:void 0}const DEFAULT_WARN_BEFORE_MS=300*1e3;function attachIdleShutdown(e){let t=e.scheduler??defaultScheduler,s=e.warnBeforeMs??DEFAULT_WARN_BEFORE_MS,g=0,S=null,w=null,E=!1,D=!1;function O(){S!==null&&(t.clearTimeout(S),S=null),w!==null&&(t.clearTimeout(w),w=null)}function k(){O(),!(D||E)&&g===0&&(s>0&&s<e.thresholdMs&&(w=t.setTimeout(()=>{w=null,g===0&&!E&&e.log?.warn({msUntilShutdown:s,webSocketClientCount:0},`idle shutdown pending: no WebSocket clients`)},e.thresholdMs-s)),S=t.setTimeout(()=>{if(S=null,!(D||E)&&g===0){E=!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 j=(e,t)=>{e.url?.startsWith(`/collab`)&&(g++,O(),t.once(`close`,()=>{g--,g<0&&(g=0),g===0&&k()}))};return e.httpServer.on(`upgrade`,j),k(),{detach:()=>{D||(D=!0,e.httpServer.off(`upgrade`,j),O())}}}const MCP_SERVER_NAME=`open-knowledge`,MCP_CONNECTION_ID_HEADER=`x-ok-connection-id`;function buildInstructions(e){return`# Open Knowledge (OK) — collaborative markdown via MCP
|
|
960
960
|
|
|
961
961
|
**STOP** *(when \`.ok/\` exists)* — do NOT use native \`Read\`, \`Grep\`, \`Glob\`, \`Edit\`, \`Write\` on in-scope \`.md\` / \`.mdx\`. Reads: \`exec\` / \`read_document\` / \`search\` / \`grep\`. Writes: \`write_document\` / \`edit_document\` ONLY.
|
|
962
962
|
|
|
@@ -1606,7 +1606,7 @@ In headless mode, write the recap into the research article's "Further reading"
|
|
|
1606
1606
|
`);function register$1(e,t){e.tool(`write_document`,DESCRIPTION$1,{docName:string().describe(`Document name to write to`),markdown:string().optional().describe("Markdown content to write. Optional when `template` is set — the template body is used."),template:string().min(1).optional().describe(`Template name resolved against parent folder's templates_available (leaf → root walk-up; closest-wins on collision). See list_documents({ dir, depth: 1 }) to inspect the menu.`),position:_enum([`append`,`prepend`,`replace`]).describe(`Where to insert the content`),summary:summaryArgSchema,cwd:string().optional().describe(ROUTED_CWD_DESCRIPTION)},async e=>{let s=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!s.ok)return textResult(`Error: ${s.error}`,!0);let{cwd:g,config:S,url:w}=s;if(!w)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let E=normalizeDocName(e.docName);if(!E.ok)return textResult(E.error,!0);let D=t.identityRef?.current;if(e.template===void 0&&e.markdown===void 0)return textResult("Error: either `markdown` or `template` must be provided. Omitting both would write empty content.",!0);if(e.template!==void 0&&e.markdown!==void 0)return textResult("Error: TEMPLATE_AND_MARKDOWN_BOTH_SET — `template` and `markdown` are mutually exclusive. Pass one. The template body becomes the new doc verbatim; fill placeholders via subsequent `edit_document` calls.",!0);let O=e.markdown??``,k=e.position;if(e.template!==void 0){let t=parentFolderOf(E.docName),s=resolveTemplatesAvailable(g,t,{depth:1}),S=s.find(t=>t.name===e.template);if(!S)return textResult(`Error: template "${e.template}" not found for folder "${t||`.`}". Available: ${s.length===0?`(none)`:s.map(e=>`${e.name} [${e.scope}]`).join(`, `)}. Templates are resolved by walk-up (D7); check list_documents({ dir, depth: 1 }) at the parent folder to see the menu.`,!0);let w;try{w=readFileSync(resolve(g,S.path),`utf-8`)}catch(e){return textResult(`Error: failed to read template at ${S.path}: ${e.message}`,!0)}O=applySubstitution(w,{date:todayIsoUtc(),user:D?.displayName??``}),k=`replace`}let j=await httpPost(w,`/api/agent-write-md`,{docName:E.docName,markdown:O,position:k,...e.summary===void 0?{}:{summary:e.summary},...D?{agentId:D.connectionId,agentName:D.displayName,clientName:D.clientInfo?.name,colorSeed:D.colorSeed}:{}});if(!j.ok)return textResult(`Error: ${j.error}`,!0);let F=resolveLockDir(resolveContentDir(S,g)),L=resolvePreviewUrl(E.docName,{config:S,lockDir:F}),B=typeof j.subscriberCount==`number`?j.subscriberCount:void 0,H=(typeof j.systemSubscriberCount==`number`?j.systemSubscriberCount:void 0)===0,q=B===0,J=Array.isArray(j.hints)?j.hints:void 0,Y=j.summary&&typeof j.summary==`object`?j.summary:void 0,ee=typeof Y?.hint==`string`?Y.hint:void 0,te=[e.template===void 0?`Written successfully (${k}).`:`Written successfully (instantiated from template "${e.template}").`];if(L&&te.push(`Preview: ${L.url}`),H&&te.push(L?`Open ${L.url} in your preview browser.`:`No preview attached. Start the UI.`),ee&&te.push(ee),J)for(let e of J)e.message&&te.push(e.message);let ne=te.join(`
|
|
1607
1607
|
`);if(!L&&!H&&!q&&!J&&!Y)return textResult(ne);let ae={};return L&&(ae.previewUrl=L.url,ae.previewUrlSource=L.source),H&&(ae.warning={message:`Open the previewUrl in your preview browser.`,action:`attach-preview-once`,previewUrl:L?.url??null}),J&&(ae.hints=J),Y&&(ae.summary=Y),textPlusStructured(ne,ae)})}const DESCRIPTION=["[Operates on disk; no running OK server required] Create or update a folder-scoped template at `<folder>/.ok/templates/<name>.md`.",``,"Templates are markdown starter shapes that agents pick from when creating a new doc — `write_document({ template: <name> })` resolves the name against the folder cascade and instantiates the body + frontmatter.",``,"**`title` is required** in the frontmatter (D14) — it is the menu surface agents pick from. Missing or empty title returns `TEMPLATE_TITLE_REQUIRED`. `description` is recommended (soft warning when absent) — it disambiguates similarly-named templates.",``,"**Substitution allowlist (D5 / FR17).** The body MAY contain `{{date}}` (today, ISO-8601) and `{{user}}` (calling principal display name). Any other `{{...}}` token is rejected at write time with `TEMPLATE_UNKNOWN_VARIABLE`. Substitution happens at instantiation time (when `write_document({ template })` materializes the doc), not at template-write time — templates on disk show the raw `{{date}}` token.",``,`**Parameters:**`,'- `folder` — Project-root-relative folder where the template lives (e.g. `"meetings"`, `"meetings/prep-notes"`). Empty / `.` means the project root.',"- `name` — Template filename without `.md`. Letters, digits, `_`, `-` only.","- `body` — Markdown body. May use `{{date}}` / `{{user}}` substitution tokens. Other placeholder text in `{shape}` form (e.g. `{Meeting Title}`) is LITERAL — agents fill it in via subsequent `edit_document` calls.","- `frontmatter` — `{title (required), description?, tags?: string[]}` for the template menu."].join(`
|
|
1608
1608
|
`),InputSchema={folder:string().describe("Project-root-relative folder. Empty / `.` means project root."),name:string().min(1).regex(/^[A-Za-z0-9_-]+$/,"Template name must use letters, digits, `_`, or `-` only (no slashes, dots, or spaces).").describe("Template filename without `.md` extension."),body:string().describe(`Markdown body for the template.`),frontmatter:object$1({title:string().min(1,"Template `title` is required (D14) — it is the menu surface agents pick from.").describe(`Required. The menu surface agents pick from. Empty / missing returns TEMPLATE_TITLE_REQUIRED.`),description:string().optional().describe(`Recommended. Disambiguates similarly-named templates. Soft warning when absent.`),tags:array(string()).optional().describe(`Optional. Concatenated with cascade tags at instantiation time.`)}).describe("Template menu metadata. `title` MUST be present (D14 — hard error if missing). `description` SHOULD be present (warning)."),cwd:string().optional().describe(ROUTED_CWD_DESCRIPTION)},OutputSchema={result:union([object$1({ok:literal(!0),path:string(),created:boolean(),warnings:array(string())}),object$1({ok:literal(!1),error:object$1({code:string(),message:string()})})])};function register(e,t){e.registerTool(`write_template`,{description:DESCRIPTION,inputSchema:InputSchema,outputSchema:OutputSchema,annotations:{readOnlyHint:!1,idempotentHint:!0,destructiveHint:!1}},async e=>{let s=await resolveProjectConfigContext(t.resolveCwd,t.config,e.cwd);if(!s.ok)return{isError:!0,content:[{type:`text`,text:`Error: ${s.error}`}]};let{cwd:g}=s,S=applyTemplateWrite({projectDir:g,folder:e.folder,name:e.name,body:e.body,frontmatter:e.frontmatter});if(!S.ok)return{isError:!0,structuredContent:{result:S},content:[{type:`text`,text:`${S.error.code}: ${S.error.message}`}]};let w=[`${S.created?`Created`:`Updated`} template at ${S.path}`];if(S.warnings.length>0){w.push(``,`Warnings:`);for(let e of S.warnings)w.push(` - ${e}`)}return textPlusStructured(w.join(`
|
|
1609
|
-
`),{result:S})})}function registerAllTools(e,t){let s=t.logger,g=createLoggedServer(e,{logger:t.logger,identityRef:t.identityRef}),S=e=>async g=>{try{let S=await t.resolveCwd(g);return(getCurrentMcpLogger()??s)?.debug(`tool cwd resolved`,{tool:e,cwd:S,...g?{explicit:g}:{}}),S}catch(t){throw(getCurrentMcpLogger()??s)?.warn(`tool call failed`,{tool:e,error:t instanceof Error?t.message:String(t),...g?{explicit:g}:{}}),t}};register$21(g,{resolveCwd:S(`exec`),serverUrl:t.serverUrl,config:t.config}),register$12(g,{config:t.config,resolveCwd:S(`ingest`)}),register$7(g,{config:t.config,resolveCwd:S(`research`)}),register$25(g,{config:t.config,resolveCwd:S(`consolidate`)}),register$10(g,{resolveCwd:S(`read_document`),config:t.config,serverUrl:t.serverUrl}),register$4(g,{resolveCwd:S(`search`),config:t.config,serverUrl:t.serverUrl}),register$13(g,{resolveCwd:S(`grep`),config:t.config,serverUrl:t.serverUrl}),register$2(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`suggest_links`)}),register$1(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`write_document`),identityRef:t.identityRef}),register$22(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`edit_document`),identityRef:t.identityRef}),register$24(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`delete_document`),identityRef:t.identityRef}),register$9(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`rename_document`),identityRef:t.identityRef}),register$8(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`rename_folder`),identityRef:t.identityRef}),register$16(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`get_history`)}),register$5(g,t.config,t.serverUrl,S(`save_version`),t.identityRef),register$6(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`rollback_to_version`),identityRef:t.identityRef}),register$11(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`list_documents`)}),register$20(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`get_backlinks`)}),register$17(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`get_forward_links`)}),register$14(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`get_orphans`)}),register$15(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`get_hubs`)}),register$18(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`get_dead_links`)}),register$19(g,{config:t.config,resolveCwd:S(`get_config`)}),register$3(g,{config:t.config,resolveCwd:S(`set_folder_rule`)}),register(g,{config:t.config,resolveCwd:S(`write_template`)}),register$23(g,{config:t.config,resolveCwd:S(`delete_template`)})}function firstHeader(e){return Array.isArray(e)?e[0]:e}function writePlain(e,t,s){e.writableEnded||(e.statusCode=t,e.setHeader(`Content-Type`,`text/plain; charset=utf-8`),e.end(s))}function sanitizeClientName(e,t){let s=Array.from(e??``).map(e=>{let t=e.charCodeAt(0);return t<=31||t===127?` `:e}).join(``).replace(/\s+/g,` `).trim();return s?s.slice(0,128):t}function createSessionServer(e,t){let s=e.config,g=new McpServer({name:MCP_SERVER_NAME,version:RUNTIME_VERSION},{instructions:buildInstructions(s.content)}),S=randomUUID(),w={current:{connectionId:S,displayName:S,colorSeed:S}};g.server.oninitialized=()=>{let e=g.server.getClientVersion(),t=sanitizeClientName(e?.name,S);w.current={connectionId:S,clientInfo:e?{name:t,version:e.version}:void 0,displayName:t,colorSeed:t}};let E=e.projectDir??e.contentDir;return registerAllTools(g,{serverUrl:async()=>e.getServerUrl(),resolveCwd:async e=>{if(e===void 0)return E;let t=resolveWithinRoot(E,e);if(!t.ok)throw Error(`cwd "${e}" is not within the configured project root: ${t.reason}`);return t.abs},config:s,identityRef:w}),{server:g,transport:t}}function createMcpHttpHandler(e){let t=new Map,s=e.sessionTtlMs??1800*1e3,g=e.maxSessions??100;async function S(s,g){let S=t.get(s);if(!S)return;t.delete(s),S.ttlTimer!==void 0&&clearTimeout(S.ttlTimer);let w=await Promise.allSettled([S.server.close(),S.transport.close()]);for(let t of w)t.status===`rejected`&&e.log?.warn?.({err:t.reason,sessionId:s,reason:g},`MCP HTTP session close failed`);e.log?.info?.({sessionId:s,reason:g},`MCP HTTP session closed`)}function w(t,g){g.ttlTimer!==void 0&&clearTimeout(g.ttlTimer),g.ttlTimer=setTimeout(()=>{S(t,`ttl-expired`).catch(s=>{e.log?.warn?.({err:s,sessionId:t},`MCP HTTP session TTL cleanup failed`)})},s),g.ttlTimer.unref?.()}return{async handle(s,E){let D=firstHeader(s.headers[`mcp-session-id`]);if(D){let e=t.get(D);if(!e){writePlain(E,404,`MCP session not found`);return}w(D,e),await e.transport.handleRequest(s,E);return}if(s.method!==`POST`){writePlain(E,400,`Missing MCP session. Initialize with POST /mcp first.`);return}if(t.size>=g){e.log?.warn?.({activeSessions:t.size,maxSessions:g},`MCP HTTP session cap reached`),writePlain(E,503,`Too many active MCP sessions`);return}let O=new StreamableHTTPServerTransport({sessionIdGenerator:()=>randomUUID(),enableJsonResponse:!0,onsessioninitialized:async s=>{try{let g=createSessionServer(e,O);await g.server.connect(O),t.set(s,g),w(s,g),e.log?.info?.({sessionId:s},`MCP HTTP session initialized`)}catch(g){throw t.delete(s),e.log?.error?.({err:g,sessionId:s},`MCP HTTP session initialization failed`),g}}});O.onerror=t=>{e.log?.warn?.({err:t},`MCP HTTP transport error`)},O.onclose=()=>{let t=O.sessionId;if(!t){e.log?.info?.({sessionId:t,reason:`transport-closed`},`MCP HTTP session closed`);return}S(t,`transport-closed`).catch(s=>{e.log?.warn?.({err:s,sessionId:t},`MCP HTTP transport-close cleanup failed`)})},await O.handleRequest(s,E)},async close(){let e=[...t.entries()];await Promise.allSettled(e.map(([e])=>S(e,`handler-close`)))}}}const DEFAULT_KEEPALIVE_GRACE_MS=1e4,MAX_COLLAB_MESSAGE_BYTES=1024*1024,MCP_CORS_HEADERS={"Access-Control-Allow-Methods":`GET, POST, DELETE, OPTIONS`,"Access-Control-Allow-Headers":`Content-Type, Authorization, traceparent, tracestate, baggage, mcp-session-id, mcp-protocol-version`,"Access-Control-Max-Age":`86400`};function mountMcpAndApi(e){let{httpServer:t,hocuspocus:s,mcpHttpHandler:g,log:S,sessionManager:w,agentFocusBroadcaster:E,agentPresenceBroadcaster:D}=e,O=e.keepaliveGraceMs??DEFAULT_KEEPALIVE_GRACE_MS,k=new import_websocket_server$1.default({noServer:!0,maxPayload:MAX_COLLAB_MESSAGE_BYTES});k.on(`error`,e=>{S.error({err:e},`WebSocketServer error`)});let j=new Map,F=new Set,L=!1;return t.on(`request`,(e,t)=>{let w=e.url?.split(`?`)[0];if(g!==void 0&&w===`/mcp`){let s=e.headers.origin,w=Array.isArray(e.headers[`mcp-session-id`])?e.headers[`mcp-session-id`][0]:e.headers[`mcp-session-id`];if(!isLoopbackAddress(e.socket.remoteAddress)){t.writeHead(403,{"Content-Type":`application/json`}),t.end(JSON.stringify({ok:!1,error:`loopback-required`}));return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){t.writeHead(403,{"Content-Type":`application/json`}),t.end(JSON.stringify({ok:!1,error:`host-header-not-allowed`}));return}if(s!==void 0&&!isAllowedApiOrigin(s)){t.writeHead(403,{"Content-Type":`application/json`}),t.end(JSON.stringify({ok:!1,error:`origin-not-allowed`}));return}s!==void 0&&(t.setHeader(`Access-Control-Allow-Origin`,s),t.setHeader(`Vary`,`Origin`));for(let[e,s]of Object.entries(MCP_CORS_HEADERS))t.setHeader(e,s);if(e.method===`OPTIONS`){t.writeHead(204),t.end();return}g.handle(e,t).catch(e=>{S.error({err:e,sessionId:w},`Unhandled MCP HTTP error`),!t.writableEnded&&!t.headersSent?(t.writeHead(500),t.end(`Internal server error`)):t.writableEnded||t.end()});return}if(w?.startsWith(`/api/`)){s.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:w})))}).catch(e=>{S.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:w??`/`}))}),t.on(`upgrade`,(e,t,g)=>{if(e.url?.startsWith(`/collab/keepalive`)){if(!isLoopbackAddress(e.socket.remoteAddress)||!isAllowedWorkspaceHostHeader(e.headers.host)){t.destroy();return}t.on(`error`,e=>{handleCollabSocketError(e)||S.error({err:e},`MCP keepalive socket error`)}),k.handleUpgrade(e,t,g,t=>{let s=parseKeepaliveConnectionId(e.url);if(s){let e=j.get(s);e!==void 0&&(clearTimeout(e),j.delete(s),S.info({connectionId:s},`[keepalive] reconnect during grace — timer cancelled`))}let g=setInterval(()=>{try{t.ping()}catch{}},3e4);g.unref?.();let k=s?setInterval(()=>{D?.bumpPresenceTs(toBroadcasterKey(s))},3e3):null;k?.unref?.(),t.on(`close`,()=>{if(clearInterval(g),k!==null&&clearInterval(k),!s)return;let e=setTimeout(()=>{if(j.delete(s),L)return;let e=(async()=>{S.info({connectionId:s},`[keepalive] grace expired — cleaning up sessions`);try{await w?.closeAllForAgent(s)}catch(e){S.error({err:e,connectionId:s},`[keepalive] closeAllForAgent failed`)}try{E?.clearFocus(s)}catch(e){S.error({err:e,connectionId:s},`[keepalive] clearFocus failed`)}try{D?.clearPresence(toBroadcasterKey(s))}catch(e){S.error({err:e,connectionId:s},`[keepalive] clearPresence failed`)}})();F.add(e),e.finally(()=>F.delete(e))},O);e.unref?.(),j.set(s,e),S.info({connectionId:s,graceMs:O},`[keepalive] disconnected — grace timer started`)}),t.on(`error`,e=>{handleCollabSocketError(e)||S.error({err:e},`MCP keepalive WS error`),t.terminate()})});return}if(e.url?.startsWith(`/collab`)){t.on(`error`,e=>{handleCollabSocketError(e)||S.error({err:e},`Upgrade socket error`)}),k.handleUpgrade(e,t,g,t=>{let g=s.handleConnection(t,e),w=!1;t.on(`message`,e=>{if(w)return;let s=e.byteLength;if(s>MAX_COLLAB_MESSAGE_BYTES){w=!0,incrementCollabMessageTooLarge(),S.warn({event:`collab-message-too-large`,bytes:s,limit:MAX_COLLAB_MESSAGE_BYTES},`Collab WebSocket message rejected before Yjs processing`),t.close(1009,`Message Too Big`);return}g.handleMessage(new Uint8Array(e))}),t.on(`close`,(e,t)=>{g.handleClose({code:e,reason:t.toString()})}),t.on(`error`,e=>{if(e.code===`WS_ERR_UNSUPPORTED_MESSAGE_LENGTH`){incrementCollabMessageTooLarge(),S.warn({event:`collab-message-too-large`,limit:MAX_COLLAB_MESSAGE_BYTES},`Collab WebSocket frame rejected by ws maxPayload before Yjs processing`),t.terminate();return}handleCollabSocketError(e)||S.error({err:e},`WebSocket error`),t.terminate()})});return}t.destroy()}),{wss:k,shutdown:async()=>{if(!L){L=!0;for(let e of j.values())clearTimeout(e);j.clear(),F.size>0&&await Promise.allSettled([...F])}}}}function parseKeepaliveConnectionId(e){if(!e)return null;try{return validateAgentId(new URL(e,`http://localhost`).searchParams.get(`connectionId`))}catch{return null}}const MISSING_OK_CONFIG_MESSAGE=`Open Knowledge config not found at .ok/config.yml. Run ok init to scaffold OK in this directory.`;var MissingOkConfigError=class extends Error{kind;projectDir;constructor(e,t,s){super(MISSING_OK_CONFIG_MESSAGE,s),this.name=`MissingOkConfigError`,this.kind=e,this.projectDir=t}};async function startConfigFileWatcher(e,t){let s=getLogger(`config-file-watcher`),{watch:g}=await import(`./chokidar-CxU7f6JW.mjs`),S=dirname(e);try{tracedMkdirSync(S,{recursive:!0})}catch(e){e.code!==`EEXIST`&&s.warn({err:e,watchDir:S},`failed to create watch directory; watcher may be inert`)}let w=g(S,{ignoreInitial:!0,depth:0,usePolling:!0,interval:200,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50},ignored:t=>t!==S&&t!==e});await new Promise(e=>{w.once(`ready`,e)});let E=null;try{E=readFileSync(e,`utf-8`)}catch{}let D=(g,S=!0)=>{if(g!==e)return;let w;try{w=readFileSync(g,`utf-8`)}catch(e){if(e.code===`ENOENT`){S&&s.debug({path:g},`config file disappeared between event and read; dropping`);return}s.warn({err:e,path:g},`config file read failed; dropping event`);return}if(w!==E){E=w;try{t(w)}catch(e){s.warn({err:e,path:g},`config file change handler threw`)}}},O=e=>D(e);w.on(`add`,O),w.on(`change`,O),w.on(`unlink`,t=>{t===e&&s.debug({path:t},`config file unlinked; Y.Text retained at current state`)}),w.on(`error`,t=>{s.warn({err:t,watchDir:S,absPath:e},`[config-file-watcher] chokidar error while watching ${e}`)});let k=0,j=setInterval(()=>{k++,D(e,!1),k>=20&&clearInterval(j)},500);j.unref?.();let F=!1;return async()=>{F||(F=!0,clearInterval(j),await w.close())}}async function startMultiPathConfigFileWatcher(e,t){if(e.length===0)throw Error(`startMultiPathConfigFileWatcher requires at least one absolute path`);let s=getLogger(`config-file-watcher`),{watch:g}=await import(`./chokidar-CxU7f6JW.mjs`),S=new Set(e),w=Array.from(new Set(Array.from(S,e=>dirname(e))));for(let e of w)try{tracedMkdirSync(e,{recursive:!0})}catch(t){t.code!==`EEXIST`&&s.warn({err:t,dir:e},`failed to create watch directory; watcher may be inert`)}let E=g(w,{ignoreInitial:!0,depth:0,usePolling:!0,interval:200,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50},ignored:e=>!S.has(e)&&!w.includes(e)});await new Promise(e=>{E.once(`ready`,e)});let D=new Map;for(let e of S)try{D.set(e,readFileSync(e,`utf-8`))}catch{D.set(e,null)}let O=(e,g=!0)=>{if(!S.has(e))return;let w;try{w=readFileSync(e,`utf-8`)}catch(t){if(t.code===`ENOENT`){g&&s.debug({path:e},`config file disappeared between event and read; dropping`);return}s.warn({err:t,path:e},`config file read failed; dropping event`);return}if(w!==D.get(e)){D.set(e,w);try{t(e,w)}catch(t){s.warn({err:t,path:e},`config file change handler threw`)}}},k=e=>O(e);E.on(`add`,k),E.on(`change`,k),E.on(`unlink`,e=>{S.has(e)&&s.debug({path:e},`config file unlinked; downstream state retained`)}),E.on(`error`,e=>{s.warn({err:e,watchDirs:w,paths:Array.from(S)},`[config-file-watcher] chokidar error in multi-path watcher`)});let j=0,F=setInterval(()=>{j++;for(let e of S)O(e,!1);j>=20&&clearInterval(F)},500);F.unref?.();let L=!1;return async()=>{L||(L=!0,clearInterval(F),await E.close())}}const QUIET_WINDOW_MS=100,BATCH_TIMEOUT_MS=3e4,WATCHED_FILES=new Set([`HEAD`,`MERGE_HEAD`,`ORIG_HEAD`,`index.lock`]);function readHeadSha(e){try{let t=readFileSync(resolve(e,`HEAD`),`utf-8`).trim();if(t.startsWith(`ref: `)){let s=resolve(e,t.slice(5));try{return readFileSync(s,`utf-8`).trim()}catch{try{let s=readFileSync(resolve(e,`packed-refs`),`utf-8`),g=t.slice(5),S=s.split(`
|
|
1609
|
+
`),{result:S})})}function registerAllTools(e,t){let s=t.logger,g=createLoggedServer(e,{logger:t.logger,identityRef:t.identityRef}),S=e=>async g=>{try{let S=await t.resolveCwd(g);return(getCurrentMcpLogger()??s)?.debug(`tool cwd resolved`,{tool:e,cwd:S,...g?{explicit:g}:{}}),S}catch(t){throw(getCurrentMcpLogger()??s)?.warn(`tool call failed`,{tool:e,error:t instanceof Error?t.message:String(t),...g?{explicit:g}:{}}),t}};register$21(g,{resolveCwd:S(`exec`),serverUrl:t.serverUrl,config:t.config}),register$12(g,{config:t.config,resolveCwd:S(`ingest`)}),register$7(g,{config:t.config,resolveCwd:S(`research`)}),register$25(g,{config:t.config,resolveCwd:S(`consolidate`)}),register$10(g,{resolveCwd:S(`read_document`),config:t.config,serverUrl:t.serverUrl}),register$4(g,{resolveCwd:S(`search`),config:t.config,serverUrl:t.serverUrl}),register$13(g,{resolveCwd:S(`grep`),config:t.config,serverUrl:t.serverUrl}),register$2(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`suggest_links`)}),register$1(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`write_document`),identityRef:t.identityRef}),register$22(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`edit_document`),identityRef:t.identityRef}),register$24(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`delete_document`),identityRef:t.identityRef}),register$9(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`rename_document`),identityRef:t.identityRef}),register$8(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`rename_folder`),identityRef:t.identityRef}),register$16(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`get_history`)}),register$5(g,t.config,t.serverUrl,S(`save_version`),t.identityRef),register$6(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`rollback_to_version`),identityRef:t.identityRef}),register$11(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`list_documents`)}),register$20(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`get_backlinks`)}),register$17(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`get_forward_links`)}),register$14(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`get_orphans`)}),register$15(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`get_hubs`)}),register$18(g,{serverUrl:t.serverUrl,config:t.config,resolveCwd:S(`get_dead_links`)}),register$19(g,{config:t.config,resolveCwd:S(`get_config`)}),register$3(g,{config:t.config,resolveCwd:S(`set_folder_rule`)}),register(g,{config:t.config,resolveCwd:S(`write_template`)}),register$23(g,{config:t.config,resolveCwd:S(`delete_template`)})}function firstHeader(e){return Array.isArray(e)?e[0]:e}function writePlain(e,t,s){e.writableEnded||(e.statusCode=t,e.setHeader(`Content-Type`,`text/plain; charset=utf-8`),e.end(s))}function sanitizeClientName(e,t){let s=Array.from(e??``).map(e=>{let t=e.charCodeAt(0);return t<=31||t===127?` `:e}).join(``).replace(/\s+/g,` `).trim();return s?s.slice(0,128):t}function createSessionServer(e,t,s){let g=e.config,S=new McpServer({name:MCP_SERVER_NAME,version:RUNTIME_VERSION},{instructions:buildInstructions(g.content)}),w=s??randomUUID(),E={current:{connectionId:w,displayName:w,colorSeed:w}};S.server.oninitialized=()=>{let e=S.server.getClientVersion(),t=sanitizeClientName(e?.name,w);E.current={connectionId:w,clientInfo:e?{name:t,version:e.version}:void 0,displayName:t,colorSeed:t}};let D=e.projectDir??e.contentDir;return registerAllTools(S,{serverUrl:async()=>e.getServerUrl(),resolveCwd:async e=>{if(e===void 0)return D;let t=resolveWithinRoot(D,e);if(!t.ok)throw Error(`cwd "${e}" is not within the configured project root: ${t.reason}`);return t.abs},config:g,identityRef:E}),{server:S,transport:t}}function createMcpHttpHandler(e){let t=new Map,s=e.sessionTtlMs??1800*1e3,g=e.maxSessions??100;async function S(s,g){let S=t.get(s);if(!S)return;t.delete(s),S.ttlTimer!==void 0&&clearTimeout(S.ttlTimer);let w=await Promise.allSettled([S.server.close(),S.transport.close()]);for(let t of w)t.status===`rejected`&&e.log?.warn?.({err:t.reason,sessionId:s,reason:g},`MCP HTTP session close failed`);e.log?.info?.({sessionId:s,reason:g},`MCP HTTP session closed`)}function w(t,g){g.ttlTimer!==void 0&&clearTimeout(g.ttlTimer),g.ttlTimer=setTimeout(()=>{S(t,`ttl-expired`).catch(s=>{e.log?.warn?.({err:s,sessionId:t},`MCP HTTP session TTL cleanup failed`)})},s),g.ttlTimer.unref?.()}return{async handle(s,E){let D=firstHeader(s.headers[`mcp-session-id`]);if(D){let e=t.get(D);if(!e){writePlain(E,404,`MCP session not found`);return}w(D,e),await e.transport.handleRequest(s,E);return}if(s.method!==`POST`){writePlain(E,400,`Missing MCP session. Initialize with POST /mcp first.`);return}if(t.size>=g){e.log?.warn?.({activeSessions:t.size,maxSessions:g},`MCP HTTP session cap reached`),writePlain(E,503,`Too many active MCP sessions`);return}let O=firstHeader(s.headers[MCP_CONNECTION_ID_HEADER]),k=validateAgentId(O)??void 0;O!==void 0&&k===void 0&&e.log?.warn?.({headerLength:O.length},`MCP HTTP forwarded connectionId header failed validation; falling back to randomUUID`);let j=new StreamableHTTPServerTransport({sessionIdGenerator:()=>randomUUID(),enableJsonResponse:!0,onsessioninitialized:async s=>{try{let g=createSessionServer(e,j,k);await g.server.connect(j),t.set(s,g),w(s,g),e.log?.info?.({sessionId:s},`MCP HTTP session initialized`)}catch(g){throw t.delete(s),e.log?.error?.({err:g,sessionId:s},`MCP HTTP session initialization failed`),g}}});j.onerror=t=>{e.log?.warn?.({err:t},`MCP HTTP transport error`)},j.onclose=()=>{let t=j.sessionId;if(!t){e.log?.info?.({sessionId:t,reason:`transport-closed`},`MCP HTTP session closed`);return}S(t,`transport-closed`).catch(s=>{e.log?.warn?.({err:s,sessionId:t},`MCP HTTP transport-close cleanup failed`)})},await j.handleRequest(s,E)},async close(){let e=[...t.entries()];await Promise.allSettled(e.map(([e])=>S(e,`handler-close`)))}}}const DEFAULT_KEEPALIVE_GRACE_MS=1e4,MAX_COLLAB_MESSAGE_BYTES=1024*1024,MCP_CORS_HEADERS={"Access-Control-Allow-Methods":`GET, POST, DELETE, OPTIONS`,"Access-Control-Allow-Headers":`Content-Type, Authorization, traceparent, tracestate, baggage, mcp-session-id, mcp-protocol-version`,"Access-Control-Max-Age":`86400`};function mountMcpAndApi(e){let{httpServer:t,hocuspocus:s,mcpHttpHandler:g,log:S,sessionManager:w,agentFocusBroadcaster:E,agentPresenceBroadcaster:D}=e,O=e.keepaliveGraceMs??DEFAULT_KEEPALIVE_GRACE_MS,k=new import_websocket_server$1.default({noServer:!0,maxPayload:MAX_COLLAB_MESSAGE_BYTES});k.on(`error`,e=>{S.error({err:e},`WebSocketServer error`)});let j=new Map,F=new Set,L=!1;return t.on(`request`,(e,t)=>{let w=e.url?.split(`?`)[0];if(g!==void 0&&w===`/mcp`){let s=e.headers.origin,w=Array.isArray(e.headers[`mcp-session-id`])?e.headers[`mcp-session-id`][0]:e.headers[`mcp-session-id`];if(!isLoopbackAddress(e.socket.remoteAddress)){t.writeHead(403,{"Content-Type":`application/json`}),t.end(JSON.stringify({ok:!1,error:`loopback-required`}));return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){t.writeHead(403,{"Content-Type":`application/json`}),t.end(JSON.stringify({ok:!1,error:`host-header-not-allowed`}));return}if(s!==void 0&&!isAllowedApiOrigin(s)){t.writeHead(403,{"Content-Type":`application/json`}),t.end(JSON.stringify({ok:!1,error:`origin-not-allowed`}));return}s!==void 0&&(t.setHeader(`Access-Control-Allow-Origin`,s),t.setHeader(`Vary`,`Origin`));for(let[e,s]of Object.entries(MCP_CORS_HEADERS))t.setHeader(e,s);if(e.method===`OPTIONS`){t.writeHead(204),t.end();return}g.handle(e,t).catch(e=>{S.error({err:e,sessionId:w},`Unhandled MCP HTTP error`),!t.writableEnded&&!t.headersSent?(t.writeHead(500),t.end(`Internal server error`)):t.writableEnded||t.end()});return}if(w?.startsWith(`/api/`)){s.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:w})))}).catch(e=>{S.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:w??`/`}))}),t.on(`upgrade`,(e,t,g)=>{if(e.url?.startsWith(`/collab/keepalive`)){if(!isLoopbackAddress(e.socket.remoteAddress)||!isAllowedWorkspaceHostHeader(e.headers.host)){t.destroy();return}t.on(`error`,e=>{handleCollabSocketError(e)||S.error({err:e},`MCP keepalive socket error`)}),k.handleUpgrade(e,t,g,t=>{let s=parseKeepaliveConnectionId(e.url);if(s){let e=j.get(s);e!==void 0&&(clearTimeout(e),j.delete(s),S.info({connectionId:s},`[keepalive] reconnect during grace — timer cancelled`))}let g=setInterval(()=>{try{t.ping()}catch{}},3e4);g.unref?.();let k=s?setInterval(()=>{D?.bumpPresenceTs(toBroadcasterKey(s))},3e3):null;k?.unref?.(),t.on(`close`,()=>{if(clearInterval(g),k!==null&&clearInterval(k),!s)return;let e=setTimeout(()=>{if(j.delete(s),L)return;let e=(async()=>{S.info({connectionId:s},`[keepalive] grace expired — cleaning up sessions`);try{await w?.closeAllForAgent(s)}catch(e){S.error({err:e,connectionId:s},`[keepalive] closeAllForAgent failed`)}try{E?.clearFocus(s)}catch(e){S.error({err:e,connectionId:s},`[keepalive] clearFocus failed`)}try{D?.clearPresence(toBroadcasterKey(s))}catch(e){S.error({err:e,connectionId:s},`[keepalive] clearPresence failed`)}})();F.add(e),e.finally(()=>F.delete(e))},O);e.unref?.(),j.set(s,e),S.info({connectionId:s,graceMs:O},`[keepalive] disconnected — grace timer started`)}),t.on(`error`,e=>{handleCollabSocketError(e)||S.error({err:e},`MCP keepalive WS error`),t.terminate()})});return}if(e.url?.startsWith(`/collab`)){t.on(`error`,e=>{handleCollabSocketError(e)||S.error({err:e},`Upgrade socket error`)}),k.handleUpgrade(e,t,g,t=>{let g=s.handleConnection(t,e),w=!1;t.on(`message`,e=>{if(w)return;let s=e.byteLength;if(s>MAX_COLLAB_MESSAGE_BYTES){w=!0,incrementCollabMessageTooLarge(),S.warn({event:`collab-message-too-large`,bytes:s,limit:MAX_COLLAB_MESSAGE_BYTES},`Collab WebSocket message rejected before Yjs processing`),t.close(1009,`Message Too Big`);return}g.handleMessage(new Uint8Array(e))}),t.on(`close`,(e,t)=>{g.handleClose({code:e,reason:t.toString()})}),t.on(`error`,e=>{if(e.code===`WS_ERR_UNSUPPORTED_MESSAGE_LENGTH`){incrementCollabMessageTooLarge(),S.warn({event:`collab-message-too-large`,limit:MAX_COLLAB_MESSAGE_BYTES},`Collab WebSocket frame rejected by ws maxPayload before Yjs processing`),t.terminate();return}handleCollabSocketError(e)||S.error({err:e},`WebSocket error`),t.terminate()})});return}t.destroy()}),{wss:k,shutdown:async()=>{if(!L){L=!0;for(let e of j.values())clearTimeout(e);j.clear(),F.size>0&&await Promise.allSettled([...F])}}}}function parseKeepaliveConnectionId(e){if(!e)return null;try{return validateAgentId(new URL(e,`http://localhost`).searchParams.get(`connectionId`))}catch{return null}}const MISSING_OK_CONFIG_MESSAGE=`Open Knowledge config not found at .ok/config.yml. Run ok init to scaffold OK in this directory.`;var MissingOkConfigError=class extends Error{kind;projectDir;constructor(e,t,s){super(MISSING_OK_CONFIG_MESSAGE,s),this.name=`MissingOkConfigError`,this.kind=e,this.projectDir=t}};async function startConfigFileWatcher(e,t){let s=getLogger(`config-file-watcher`),{watch:g}=await import(`./chokidar-CxU7f6JW.mjs`),S=dirname(e);try{tracedMkdirSync(S,{recursive:!0})}catch(e){e.code!==`EEXIST`&&s.warn({err:e,watchDir:S},`failed to create watch directory; watcher may be inert`)}let w=g(S,{ignoreInitial:!0,depth:0,usePolling:!0,interval:200,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50},ignored:t=>t!==S&&t!==e});await new Promise(e=>{w.once(`ready`,e)});let E=null;try{E=readFileSync(e,`utf-8`)}catch{}let D=(g,S=!0)=>{if(g!==e)return;let w;try{w=readFileSync(g,`utf-8`)}catch(e){if(e.code===`ENOENT`){S&&s.debug({path:g},`config file disappeared between event and read; dropping`);return}s.warn({err:e,path:g},`config file read failed; dropping event`);return}if(w!==E){E=w;try{t(w)}catch(e){s.warn({err:e,path:g},`config file change handler threw`)}}},O=e=>D(e);w.on(`add`,O),w.on(`change`,O),w.on(`unlink`,t=>{t===e&&s.debug({path:t},`config file unlinked; Y.Text retained at current state`)}),w.on(`error`,t=>{s.warn({err:t,watchDir:S,absPath:e},`[config-file-watcher] chokidar error while watching ${e}`)});let k=0,j=setInterval(()=>{k++,D(e,!1),k>=20&&clearInterval(j)},500);j.unref?.();let F=!1;return async()=>{F||(F=!0,clearInterval(j),await w.close())}}async function startMultiPathConfigFileWatcher(e,t){if(e.length===0)throw Error(`startMultiPathConfigFileWatcher requires at least one absolute path`);let s=getLogger(`config-file-watcher`),{watch:g}=await import(`./chokidar-CxU7f6JW.mjs`),S=new Set(e),w=Array.from(new Set(Array.from(S,e=>dirname(e))));for(let e of w)try{tracedMkdirSync(e,{recursive:!0})}catch(t){t.code!==`EEXIST`&&s.warn({err:t,dir:e},`failed to create watch directory; watcher may be inert`)}let E=g(w,{ignoreInitial:!0,depth:0,usePolling:!0,interval:200,awaitWriteFinish:{stabilityThreshold:100,pollInterval:50},ignored:e=>!S.has(e)&&!w.includes(e)});await new Promise(e=>{E.once(`ready`,e)});let D=new Map;for(let e of S)try{D.set(e,readFileSync(e,`utf-8`))}catch{D.set(e,null)}let O=(e,g=!0)=>{if(!S.has(e))return;let w;try{w=readFileSync(e,`utf-8`)}catch(t){if(t.code===`ENOENT`){g&&s.debug({path:e},`config file disappeared between event and read; dropping`);return}s.warn({err:t,path:e},`config file read failed; dropping event`);return}if(w!==D.get(e)){D.set(e,w);try{t(e,w)}catch(t){s.warn({err:t,path:e},`config file change handler threw`)}}},k=e=>O(e);E.on(`add`,k),E.on(`change`,k),E.on(`unlink`,e=>{S.has(e)&&s.debug({path:e},`config file unlinked; downstream state retained`)}),E.on(`error`,e=>{s.warn({err:e,watchDirs:w,paths:Array.from(S)},`[config-file-watcher] chokidar error in multi-path watcher`)});let j=0,F=setInterval(()=>{j++;for(let e of S)O(e,!1);j>=20&&clearInterval(F)},500);F.unref?.();let L=!1;return async()=>{L||(L=!0,clearInterval(F),await E.close())}}const QUIET_WINDOW_MS=100,BATCH_TIMEOUT_MS=3e4,WATCHED_FILES=new Set([`HEAD`,`MERGE_HEAD`,`ORIG_HEAD`,`index.lock`]);function readHeadSha(e){try{let t=readFileSync(resolve(e,`HEAD`),`utf-8`).trim();if(t.startsWith(`ref: `)){let s=resolve(e,t.slice(5));try{return readFileSync(s,`utf-8`).trim()}catch{try{let s=readFileSync(resolve(e,`packed-refs`),`utf-8`),g=t.slice(5),S=s.split(`
|
|
1610
1610
|
`).find(e=>e.endsWith(` ${g}`));if(S)return S.split(` `)[0]}catch{}return null}}return t.length>=40?t.slice(0,40):null}catch{return null}}function readBranchFromHead(e){try{let t=readFileSync(resolve(e,`HEAD`),`utf-8`).trim();return t.startsWith(`ref: refs/heads/`)?t.slice(16):t.length>=40?`detached-${t.slice(0,12)}`:null}catch{return null}}async function startHeadWatcher(e,t,s){let g=resolveGitDir(e);if(!g)return{unsubscribe:async()=>{},getLastKnownBranch:()=>null};let S=g,w=!1,E=null,D=null,O=null,k=null;async function j(e){if(L&&await L,!w)return;E&&=(clearTimeout(E),null),D&&=(clearTimeout(D),null);let t=readHeadSha(S),g=O!==t,j=readBranchFromHead(S),F;F=j?.startsWith(`detached-`)?`detached-head`:k===j?`within-branch`:`cross-branch`;let B=k;try{await s({headMoved:g,oldHead:O,newHead:t,timeout:e,batchKind:F,oldBranch:B,newBranch:j})}catch(e){console.error(`[head-watcher] onBatchEnd callback failed:`,e)}finally{w=!1,O=t,k=j}}function F(){E&&clearTimeout(E),E=setTimeout(()=>{E=null,j(!1)},QUIET_WINDOW_MS)}let L=null;async function B(e){if(!w){w=!0,O=readHeadSha(S);let s=(async()=>{try{await t({trigger:e})}catch(e){console.error(`[head-watcher] onBatchBegin callback failed:`,e)}})();L=s,await s,L=null,D=setTimeout(()=>{D=null,j(!0)},BATCH_TIMEOUT_MS)}F()}let H,q;try{q=await import(`@parcel/watcher`)}catch(e){throw Error(`@parcel/watcher unavailable for HEAD watching: ${e instanceof Error?e.message:e}`)}try{let e=await q.subscribe(S,(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)){B(t);break}}});H=()=>e.unsubscribe()}catch(e){throw Error(`@parcel/watcher subscribe failed for HEAD watching: ${e instanceof Error?e.message:e}`)}return O=readHeadSha(S),k=readBranchFromHead(S),console.log(`[head-watcher] Watching ${S} for HEAD changes`),{unsubscribe:async()=>{w&&await j(!1),E&&clearTimeout(E),D&&clearTimeout(D),await H()},getLastKnownBranch:()=>k}}const LIVE_DERIVED_INDEX_DEBOUNCE_MS=100;function isLocalOriginLike(e){return typeof e!=`object`||!e?!1:e.source===`local`}function serializeLiveDocument(e){return e.getText(`source`).toString()}function createLiveDerivedIndexExtension(e){let{backlinkIndex:t,tagIndex:s,signalChannel:g,debounceMs:S=100}=e,w=new Map;function E(e){let t=w.get(e);t&&(clearTimeout(t),w.delete(e))}function D(e,D){E(e),w.set(e,setTimeout(()=>{w.delete(e);try{let S=serializeLiveDocument(D);t.updateDocumentFromMarkdown(e,S),g?.(`backlinks`),g?.(`graph`),s&&(s.updateDocumentFromMarkdown(e,S),g?.(`tags`))}catch(t){console.error(`[live-derived-index] Failed to update derived views for ${e}:`,t)}},S))}return{async onChange({documentName:e,document:t,transactionOrigin:s}){isSystemDoc(e)||isConfigDoc(e)||isLocalOriginLike(s)&&s.context?.origin===`file-watcher`||D(e,t)},async beforeUnloadDocument({documentName:e}){E(e)},async onDestroy(){for(let e of w.values())clearTimeout(e);w.clear()}}}const PRINCIPAL_FILE=`principal.json`,GIT_TIMEOUT_MS=3e3;async function readGitConfig(e){try{let t=esm_default({baseDir:e,timeout:{block:GIT_TIMEOUT_MS}});return{name:(await t.raw(`config`,`--get`,`user.name`)).trim()||null,email:(await t.raw(`config`,`--get`,`user.email`)).trim()||null}}catch{return{name:null,email:null}}}async function loadPrincipal(e){let t=getLocalDir(e),s=resolve(t,PRINCIPAL_FILE),{name:g,email:S}=await readGitConfig(e);if(existsSync(s)){let e;try{e=JSON.parse(readFileSync(s,`utf-8`))}catch{e={}}let t=typeof e.id==`string`&&e.id.startsWith(`principal-`)?e.id:`principal-${randomUUID()}`,w=typeof e.created_at==`string`?e.created_at:new Date().toISOString(),E=t.slice(10,18),D={id:t,display_name:g?sanitizeGitIdentity(g):typeof e.display_name==`string`?e.display_name:`Local User`,display_email:S?sanitizeGitIdentity(S):typeof e.display_email==`string`?e.display_email:`principal-${E}@openknowledge.local`,source:g||S?`git-config`:`synthesized`,created_at:w};return writeFileSync(s,JSON.stringify(D,null,2),`utf-8`),D}mkdirSync(t,{recursive:!0});let w=`principal-${randomUUID()}`,E=w.slice(10,18),D={id:w,display_name:g?sanitizeGitIdentity(g):`Local User`,display_email:S?sanitizeGitIdentity(S):`principal-${E}@openknowledge.local`,source:g||S?`git-config`:`synthesized`,created_at:new Date().toISOString()};return writeFileSync(s,JSON.stringify(D,null,2),`utf-8`),D}function createServerObserverExtension(e){let t=new Map,s=new Map;return{async afterLoadDocument({documentName:g,document:S}){if(isSystemDoc(g)||isConfigDoc(g)||t.has(g))return;let w=S,E=w.getXmlFragment(`default`),D=w.getText(`source`),O=()=>{try{let s=setupServerObservers({doc:w,xmlFragment:E,ytext:D,mdManager:e.mdManager,schema:e.schema,docName:g,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(g,s),!0}catch(e){return console.error(`[ServerObserverExtension] Failed to attach observers for '${g}':`,e),incrementServerObserverError(`a`),incrementServerObserverError(`b`),!1}};if(!O()){let e=setTimeout(()=>{s.delete(g),!t.has(g)&&(console.warn(`[ServerObserverExtension] Retrying observer attachment for '${g}'`),O())},5e3);s.set(g,e)}},async afterUnloadDocument({documentName:e}){let g=s.get(e);g&&(clearTimeout(g),s.delete(e));let S=t.get(e);S&&(S(),t.delete(e))},async onDestroy(){for(let e of s.values())clearTimeout(e);s.clear();for(let[e,s]of t.entries())try{s()}catch(t){console.error(`[ServerObserverExtension] Cleanup failed for '${e}':`,t)}t.clear()}}}const STATE_MANIFEST_FILENAME=`state.json`;function detectProjectShape(e){return e.lockDir,existsSync(e.shadowRepoDir)?`adopt`:`fresh`}function manifestPath(e){return resolve(e,STATE_MANIFEST_FILENAME)}function isCompatibleSchema(e,t){return e===t||e===0&&t===1}var StateManifestError=class extends Error{kind;path;constructor(e){super(e.message),this.name=`StateManifestError`,this.kind=e.kind,this.path=e.path}};function isStateManifestRecord(e){if(!e||typeof e!=`object`)return!1;let t=e;if(typeof t.stateSchemaVersion!=`number`||typeof t.createdAt!=`string`||!t.createdBy||typeof t.createdBy!=`object`)return!1;let s=t.createdBy;return!(typeof s.runtimeVersion!=`string`||s.protocolVersion!==void 0&&typeof s.protocolVersion!=`number`)}function readStateManifest(e){let t=manifestPath(e);if(!existsSync(t))return{status:`absent`};let s;try{s=readFileSync(t,`utf-8`)}catch(e){throw new StateManifestError({kind:`corrupt`,path:t,message:`Failed to read state manifest at ${t}: ${e instanceof Error?e.message:String(e)}`})}let g;try{g=JSON.parse(s)}catch(e){throw new StateManifestError({kind:`corrupt`,path:t,message:`State manifest at ${t} is not valid JSON: ${e instanceof Error?e.message:String(e)}`})}if(!isStateManifestRecord(g))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:g}}function writeStateManifest(e,t){let s=manifestPath(e);mkdirSync(dirname(s),{recursive:!0}),writeFileSync(s,JSON.stringify(t,null,2),{encoding:`utf-8`,mode:384})}function assertCompatibleStateManifest(e){let t=getLogger(`state-manifest`),s=e.currentStateSchemaVersion??1,g=e.currentRuntimeVersion??RUNTIME_VERSION,S=e.currentProtocolVersion??1,w=(e.now??(()=>new Date))().toISOString(),E=manifestPath(e.lockDir),D=readStateManifest(e.lockDir);if(D.status===`present`){let O=D.manifest;if(!isCompatibleSchema(O.stateSchemaVersion,s))throw new StateManifestError({kind:`incompatible`,path:E,message:`State manifest at ${E} declares stateSchemaVersion=${O.stateSchemaVersion} but this binary supports ${s}. Refusing to boot — on-the-fly migration is out of scope. (Manifest written by runtime ${O.createdBy.runtimeVersion}, protocol ${O.createdBy.protocolVersion}.)`});try{let t={...O,lastWriteBy:{runtimeVersion:g,protocolVersion:S,at:w}};return writeStateManifest(e.lockDir,t),t}catch(e){return t.warn({err:e},`[state-manifest] failed to update lastWriteBy — proceeding`),O}}if(detectProjectShape({lockDir:e.lockDir,shadowRepoDir:e.shadowRepoDir})===`fresh`){let D={stateSchemaVersion:s,createdAt:w,createdBy:{runtimeVersion:g,protocolVersion:S}};return writeStateManifest(e.lockDir,D),t.info({path:E,stateSchemaVersion:s},`[state-manifest] fresh project — wrote manifest`),D}let O={stateSchemaVersion:0,createdAt:w,createdBy:{runtimeVersion:g,protocolVersion:S,adoptedAt:w}};return writeStateManifest(e.lockDir,O),t.warn({path:E,runtimeVersion:g},`[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.`),O}const log$1=getLogger(`conflict-storage`);var ConflictStore=class{storePath;projectDir;branch;conflicts=[];constructor(e,t,s=`main`){this.storePath=join(getLocalDir(e),`conflicts.json`),this.projectDir=t,this.branch=s,this.load()}load(){if(!existsSync(this.storePath)){this.conflicts=[];return}try{let e=readFileSync(this.storePath,`utf-8`),t=JSON.parse(e);if(t.version!==1){log$1.warn({path:this.storePath},`[conflicts] unknown schema version — resetting`),this.conflicts=[];return}this.branch=t.branch??this.branch,this.conflicts=t.conflicts??[]}catch(e){log$1.warn({err:e},`[conflicts] failed to load conflicts.json — starting empty`),this.conflicts=[]}}save(){try{let e=dirname(this.storePath);existsSync(e)||mkdirSync(e,{recursive:!0});let t={version:1,branch:this.branch,conflicts:this.conflicts};writeFileSync(this.storePath,JSON.stringify(t,null,2),`utf-8`)}catch(e){log$1.warn({err:e},`[conflicts] failed to save conflicts.json`)}}addConflict(e){let t=this.conflicts.findIndex(t=>t.file===e.file);t===-1?this.conflicts.push(e):this.conflicts[t]=e,this.save()}removeConflict(e){this.conflicts=this.conflicts.filter(t=>t.file!==e),this.save()}clear(){this.conflicts=[],this.save()}count(){return this.conflicts.length}list(){return[...this.conflicts]}hasConflicts(){return this.conflicts.length>0}setBranch(e){this.branch=e}async resolveConflict(e,t,s,g=[]){if(!this.conflicts.find(t=>t.file===e))throw Error(`[conflicts] no conflict tracked for file: ${e}`);if(t===`content`&&s===void 0)throw Error(`[conflicts] strategy 'content' requires content parameter`);let{createGitInstance:S}=await import(`./git-handle-DwfYp_z--DreW3fNC.mjs`).then(e=>e.n),w=S(this.projectDir,{credentialArgs:g});switch(t){case`mine`:await w.git.raw([`checkout`,`--ours`,`--`,e]),await w.git.raw([`add`,`--`,e]);break;case`theirs`:await w.git.raw([`checkout`,`--theirs`,`--`,e]),await w.git.raw([`add`,`--`,e]);break;case`content`:{if(!s)throw Error(`[conflicts] strategy 'content' requires content parameter`);let t=resolve(this.projectDir),g=resolve(t,e);if(g!==t&&!g.startsWith(`${t}/`))throw Error(`[conflicts] file path escapes project directory: ${e}`);writeFileSync(g,s,`utf-8`),await w.git.raw([`add`,`--`,e]);break}default:throw Error(`[conflicts] unknown resolve strategy: ${t}`)}if(this.removeConflict(e),!this.hasConflicts())try{await w.git.raw([`commit`,`--no-edit`]),log$1.info({file:e},`[conflicts] all conflicts resolved — merge commit created`)}catch(t){let s=new Date().toISOString(),g=!1;try{let e=(await w.git.raw([`diff`,`--name-only`,`--diff-filter=U`])).split(`
|
|
1611
1611
|
`).map(e=>e.trim()).filter(Boolean);for(let t of e)this.addConflict({file:t,detectedAt:s});g=e.length>0}catch(e){log$1.warn({err:e},`[conflicts] commit failed and re-scan of unmerged files failed — falling back to single-file re-add`)}g||this.addConflict({file:e,detectedAt:s}),log$1.warn({err:t},`[conflicts] failed to commit merge after all conflicts resolved — unmerged files re-added`)}}};function extractStderr(e){return e.git?.toString()??e.message??``}function matchesAny(e,t){return t.some(t=>t.test(e))}const AUTH_PATTERNS=[/\b(401|403)\b/,/authentication failed/i,/authorization failed/i,/invalid credentials/i,/credential helper/i,/bad credentials/i,/token.*expired/i,/expired.*token/i,/permission denied.*\(publickey\)/i,/host key verification failed/i,/fatal:.*repository.*not found/i],SCOPE_MISMATCH_PATTERNS=[/insufficient scopes/i,/missing.*scope/i,/required scope/i],NON_FAST_FORWARD_PATTERNS=[/non-fast-forward/i,/rejected.*non-fast-forward/i,/would overwrite.*commits/i,/\[rejected\]/,/fetch first/i,/updates were rejected/i],PROTECTED_BRANCH_PATTERNS=[/protected branch/i,/refusing to allow/i,/at least \d+ approving review/i,/required status check/i,/branch policy/i,/GH001/i,/GH002/i,/GH003/i,/GH004/i,/push declined due to repository rule/i,/cannot push to a protected branch/i],MERGE_CONFLICT_PATTERNS=[/\bmerge conflict\b/i,/automatic merge failed/i,/CONFLICT \(/,/\bconflict\b.*\bmerge\b/i,/(?:^|\n)CONFLICTS:\s/i],LFS_PATTERNS=[/lfs.*quota/i,/exceeded.*bandwidth/i,/lfs storage/i],LARGE_FILE_PATTERNS=[/file.*too large/i,/exceeded.*file size/i,/push file size limit/i],PRE_RECEIVE_PATTERNS=[/pre-receive hook/i,/remote:.*rejected/i,/hook declined/i],SECRET_DETECTED_PATTERNS=[/secret.*detected/i,/push.*secret/i,/secret scanning/i,/leaking.*credentials/i,/token.*detected/i],INDEX_LOCK_PATTERNS=[/\.git\/index\.lock/i,/another git process/i,/unable to create.*\.lock/i],DIRTY_TREE_PATTERNS=[/dirty.*working tree/i,/working tree.*not clean/i,/untracked.*files.*would be overwritten/i,/local changes.*would be overwritten/i,/uncommitted changes/i,/changes.*not staged/i,/please.*commit.*changes/i,/please.*stash/i,/commit your changes or stash/i],DISK_FULL_PATTERNS=[/no space left on device/i,/disk quota exceeded/i,/ENOSPC/],NETWORK_PATTERNS=[/could not resolve host/i,/name.*resolution/i,/connection.*timed out/i,/operation timed out/i,/connection refused/i,/network.*unreachable/i,/ssl.*handshake/i,/unable to connect/i,/getaddrinfo/i,/econnrefused/i,/enotfound/i,/etimedout/i,/ehostunreach/i],HTTP_5XX_PATTERNS=[/\bHTTP[\s/]*5[0-9]{2}\b/i,/\bstatus:?\s*5[0-9]{2}\b/i,/\berror\s*5[0-9]{2}\b/i,/\bresponse.*?\b5[0-9]{2}\b/i],HTTP_429_PATTERNS=[/\bHTTP[\s/]*429\b/i,/\bstatus:?\s*429\b/i,/\berror\s*429\b/i,/rate.?limit/i,/too many requests/i];function classifyGitError(e){let t=e instanceof Error?e:Error(String(e)),s=extractStderr(t),g=`${t.message}\n${s}`.toLowerCase();return matchesAny(g,INDEX_LOCK_PATTERNS)?{class:`local`,subclass:`index-lock`,retryable:!0,message:`Git index locked by another process`,rawStderr:s}:matchesAny(g,DIRTY_TREE_PATTERNS)?{class:`local`,subclass:`dirty-tree`,retryable:!0,message:`Working tree has uncommitted changes`,rawStderr:s}:matchesAny(g,DISK_FULL_PATTERNS)?{class:`local`,subclass:`disk-full`,retryable:!0,message:`Disk full or quota exceeded`,rawStderr:s}:matchesAny(g,SCOPE_MISMATCH_PATTERNS)?{class:`auth`,subclass:`scope-mismatch`,retryable:!1,message:`GitHub token missing required scopes`,rawStderr:s}:matchesAny(g,AUTH_PATTERNS)?/\b401\b/.test(g)||/token.*expired/i.test(g)?{class:`auth`,subclass:`401`,retryable:!1,message:`Authentication failed — token may be expired`,rawStderr:s}:/\b403\b/.test(g)?matchesAny(g,PROTECTED_BRANCH_PATTERNS)?{class:`semantic`,subclass:`protected-branch`,retryable:!1,message:`Push rejected — branch is protected`,rawStderr:s}:{class:`auth`,subclass:`403`,retryable:!1,message:`Access denied (403)`,rawStderr:s}:{class:`auth`,subclass:`unknown-auth`,retryable:!1,message:`Authentication failed`,rawStderr:s}:matchesAny(g,PROTECTED_BRANCH_PATTERNS)?{class:`semantic`,subclass:`protected-branch`,retryable:!1,message:`Push rejected — branch is protected`,rawStderr:s}:matchesAny(g,NON_FAST_FORWARD_PATTERNS)?{class:`semantic`,subclass:`non-fast-forward`,retryable:!1,message:`Push rejected — remote has diverged (non-fast-forward)`,rawStderr:s}:matchesAny(g,MERGE_CONFLICT_PATTERNS)?{class:`semantic`,subclass:`merge-conflict`,retryable:!1,message:`Merge conflict — manual resolution required`,rawStderr:s}:matchesAny(g,LFS_PATTERNS)?{class:`structural`,subclass:`lfs-quota`,retryable:!1,message:`Git LFS quota exceeded`,rawStderr:s}:matchesAny(g,LARGE_FILE_PATTERNS)?{class:`structural`,subclass:`large-file`,retryable:!1,message:`File exceeds size limit`,rawStderr:s}:matchesAny(g,SECRET_DETECTED_PATTERNS)?{class:`structural`,subclass:`secret-detected`,retryable:!1,message:`Push blocked — secret or credential detected in content`,rawStderr:s}:matchesAny(g,PRE_RECEIVE_PATTERNS)?{class:`structural`,subclass:`pre-receive-hook`,retryable:!1,message:`Push rejected by server pre-receive hook`,rawStderr:s}:matchesAny(g,HTTP_429_PATTERNS)?{class:`network`,subclass:`429`,retryable:!0,message:`Rate limited — too many requests`,rawStderr:s}:matchesAny(g,HTTP_5XX_PATTERNS)?{class:`network`,subclass:`5xx`,retryable:!0,message:`Server error (5xx)`,rawStderr:s}:matchesAny(g,NETWORK_PATTERNS)?/timed? out/i.test(g)?{class:`network`,subclass:`timeout`,retryable:!0,message:`Connection timed out`,rawStderr:s}:/refused/i.test(g)||/econnrefused/i.test(g)?{class:`network`,subclass:`connection-refused`,retryable:!0,message:`Connection refused`,rawStderr:s}:/resolve.*host/i.test(g)||/enotfound/i.test(g)||/getaddrinfo/i.test(g)?{class:`network`,subclass:`dns`,retryable:!0,message:`DNS resolution failed`,rawStderr:s}:{class:`network`,subclass:`unknown-network`,retryable:!0,message:`Network error`,rawStderr:s}:{class:`local`,subclass:`unknown-local`,retryable:!0,message:t.message||`Unknown git error`,rawStderr:s}}function computeRemainingMs(e,t,s=Date.now()){if(!e)return 0;let g=new Date(e).getTime();if(Number.isNaN(g))return 0;let S=g+t*1e3;return Math.max(0,S-s)}const log=getLogger(`sync-engine`),SHA_HEX_40=/^[0-9a-f]{40}$/i;function jitteredMs(e){let t=e*1e3,s=t*.15*(2*Math.random()-1);return Math.round(t+s)}function isUnbornHead(e){try{let t=join(e,`.git`,`HEAD`);if(!existsSync(t))return!1;let s=readFileSync(t,`utf-8`).trim(),g=/^ref:\s+(refs\/.+)$/.exec(s);if(!g)return!1;let S=g[1];if(existsSync(join(e,`.git`,S)))return!1;let w=join(e,`.git`,`packed-refs`);if(existsSync(w)){let e=readFileSync(w,`utf-8`);if(RegExp(`^[0-9a-f]+\\s+${S}$`,`m`).test(e))return!1}return!0}catch{return!1}}function backoffMs(e){return e>=8?3600*1e3:e>=5?900*1e3:e>=3?300*1e3:0}var SyncEngine=class{state=`dormant`;projectDir;contentDir;contentFilter;contentRoot;pullIntervalSeconds;pushIntervalSeconds;syncEnabled;credentialArgs;cc1Broadcaster;onStateChange;setBatchInProgress;onAutoDisable;pullTimer=null;pushTimer=null;stateSaveTimer=null;lastSyncUtc=null;lastFetchUtc=null;lastPushedSha=null;consecutiveFailures=0;ahead=0;behind=0;conflictCount=0;error;pausedReason;currentBranch=`main`;pullInFlight=!1;pushInFlight=!1;hasRemote=!1;identityUnresolved=!1;statePath;conflictStore;constructor(e){this.projectDir=e.projectDir,this.contentDir=e.contentDir,this.contentFilter=e.contentFilter,this.contentRoot=e.contentRoot??``,this.pullIntervalSeconds=e.pullIntervalSeconds??30,this.pushIntervalSeconds=e.pushIntervalSeconds??60,this.syncEnabled=e.syncEnabled,this.credentialArgs=e.credentialArgs??[],this.cc1Broadcaster=e.cc1Broadcaster??null,this.onStateChange=e.onStateChange,this.setBatchInProgress=e.setBatchInProgress,this.onAutoDisable=e.onAutoDisable,this.statePath=resolve(getLocalDir(this.contentDir),`sync-state.json`),this.conflictStore=new ConflictStore(this.contentDir,this.projectDir,this.currentBranch)}async start(){if(this.state!==`dormant`)return;this.loadState();let e=!1;try{let t=createGitInstance(this.projectDir,{credentialArgs:this.credentialArgs});e=(await t.git.raw(`remote`,`-v`)).trim().length>0,this.hasRemote=e;try{let e=(await t.git.raw(`rev-parse`,`--abbrev-ref`,`HEAD`)).trim();e&&e!==`HEAD`&&(this.currentBranch=e,this.conflictStore.setBranch(e))}catch{}}catch(e){log.warn({err:e},`[sync] remote detection failed`)}if(this.syncEnabled!==!0){e&&this.transitionTo(`disabled`),log.info({hasRemote:e,syncEnabled:this.syncEnabled},`[sync] sync not enabled — staying inactive`);return}if(!e){log.info({},`[sync] no remote detected — staying dormant`);return}this.transitionTo(`idle`);let t=existsSync(join(this.projectDir,`.git`,`MERGE_HEAD`));if(this.conflictCount>0&&!t)log.warn({count:this.conflictCount},`[sync] persisted conflicts but no MERGE_HEAD — clearing stale state`),this.conflictStore.clear(),this.conflictCount=0;else if(this.conflictCount>0&&t)try{let e=(await createGitInstance(this.projectDir,{credentialArgs:this.credentialArgs}).git.raw([`diff`,`--name-only`,`--diff-filter=U`])).trim(),t=new Set(e?e.split(`
|
|
1612
1612
|
`).map(e=>e.trim()).filter(Boolean):[]),s=this.conflictCount;for(let e of this.conflictStore.list())t.has(e.file)||this.conflictStore.removeConflict(e.file);this.conflictCount=this.conflictStore.count(),this.conflictCount<s&&log.info({cleared:s-this.conflictCount,remaining:this.conflictCount},`[sync] reconciled conflicts.json against git unmerged index`)}catch(e){log.warn({err:e},`[sync] failed to reconcile conflicts with git index`)}if(t&&this.conflictCount===0){log.warn({},`[sync] stale MERGE_HEAD detected with no tracked conflicts — aborting merge`);try{await createGitInstance(this.projectDir,{credentialArgs:this.credentialArgs}).git.raw([`merge`,`--abort`])}catch(e){log.warn({err:e},`[sync] git merge --abort for stale MERGE_HEAD failed`)}}if(this.conflictCount>0){this.transitionTo(`conflict`),log.warn({count:this.conflictCount},`[sync] restarted with active conflicts — sync paused`);return}let s=computeRemainingMs(this.lastFetchUtc,this.pullIntervalSeconds),g=computeRemainingMs(this.lastSyncUtc,this.pushIntervalSeconds);this.schedulePull(s>0?s:void 0),this.schedulePush(g>0?g:void 0),log.info({branch:this.currentBranch,pullDelayMs:s,pushDelayMs:g},`[sync] started`)}stop(){this.pullTimer!==null&&(clearTimeout(this.pullTimer),this.pullTimer=null),this.pushTimer!==null&&(clearTimeout(this.pushTimer),this.pushTimer=null),this.stateSaveTimer!==null&&(clearTimeout(this.stateSaveTimer),this.stateSaveTimer=null),this.state!==`dormant`&&this.transitionTo(`dormant`)}async destroy(){this.stop(),this.saveStateNow()}async setEnabled(e){if(this.syncEnabled!==e){if(this.syncEnabled=e,!e){this.pullTimer!==null&&(clearTimeout(this.pullTimer),this.pullTimer=null),this.pushTimer!==null&&(clearTimeout(this.pushTimer),this.pushTimer=null);let e=3e4,t=Date.now();for(;this.pullInFlight||this.pushInFlight;){if(Date.now()-t>3e4){log.warn({pullInFlight:this.pullInFlight,pushInFlight:this.pushInFlight},`[sync] setEnabled(false): timed out waiting for in-flight cycle to drain`);break}await setTimeout$1(50)}this.pausedReason=void 0,this.error=void 0,this.transitionTo(this.hasRemote?`disabled`:`dormant`),this.saveStateNow();return}try{this.hasRemote=(await createGitInstance(this.projectDir,{credentialArgs:this.credentialArgs}).git.raw(`remote`,`-v`)).trim().length>0}catch(e){log.warn({err:e},`[sync] remote detection failed during enable`)}if(this.pausedReason=void 0,this.error=void 0,this.consecutiveFailures=0,!this.hasRemote){this.transitionTo(`dormant`),this.saveStateNow();return}this.transitionTo(`idle`),this.schedulePull(0),this.schedulePush(),this.saveStateNow()}}async trigger(e=`sync`){this.consecutiveFailures=0,(this.pausedReason===`dirty-tree`||this.pausedReason===`external-changes-pending`)&&(this.pausedReason=void 0,this.error=void 0),this.state===`dormant`||this.state===`disabled`||this.state===`conflict`||this.state===`auth-error`?log.warn({op:e,state:this.state,syncEnabled:this.syncEnabled,hasRemote:this.hasRemote,pausedReason:this.pausedReason,conflictCount:this.conflictCount},`[sync] trigger(${e}) ignored — state=${this.state}`):log.info({op:e,state:this.state},`[sync] trigger(${e}) running`),e===`push`?await this.runPushCycle():(e===`pull`||await this.runPushCycle(),await this.runPullCycle())}getStatus(){return{state:this.state,lastSyncUtc:this.lastSyncUtc,lastFetchUtc:this.lastFetchUtc,lastPushedSha:this.lastPushedSha,ahead:this.ahead,behind:this.behind,consecutiveFailures:this.consecutiveFailures,conflictCount:this.conflictCount,hasRemote:this.hasRemote,syncEnabled:this.syncEnabled===!0,identityUnresolved:this.identityUnresolved,error:this.error,pausedReason:this.pausedReason}}async refreshIdentity(){let e=await resolveGitIdentity(this.projectDir)===null;this.identityUnresolved!==e&&(this.identityUnresolved=e,this.cc1Broadcaster?.signal(`sync-status`))}getConflicts(){return this.conflictStore.list()}async resolveConflict(e,t,s){await this.conflictStore.resolveConflict(e,t,s),this.conflictCount=this.conflictStore.count(),this.conflictCount===0&&this.state===`conflict`&&(this.transitionTo(`idle`),this.pausedReason=void 0,this.schedulePull(),this.schedulePush()),this.scheduleSaveState()}updateCurrentBranch(e){e===null?this.state!==`dormant`&&this.state!==`disabled`&&(this.transitionTo(`disabled`),this.pausedReason=`detached-head`,this.scheduleSaveState()):this.currentBranch!==e&&(this.currentBranch=e,this.conflictStore.setBranch(e),this.state===`disabled`&&this.pausedReason===`detached-head`&&(this.pausedReason=void 0,this.transitionTo(`idle`),this.schedulePull(),this.schedulePush()))}schedulePull(e){this.pullTimer!==null&&clearTimeout(this.pullTimer);let t=e??this.effectivePullDelayMs();this.pullTimer=setTimeout(()=>{this.pullTimer=null,this.runPullCycle().catch(e=>{log.error({err:e},`[sync] pull cycle uncaught error`)})},t)}schedulePush(e){this.pushTimer!==null&&clearTimeout(this.pushTimer);let t=e??jitteredMs(this.pushIntervalSeconds);this.pushTimer=setTimeout(()=>{this.pushTimer=null,this.runPushCycle().catch(e=>{log.error({err:e},`[sync] push cycle uncaught error`)})},t)}effectivePullDelayMs(){let e=this.consecutiveFailures,t=backoffMs(e);return t>0?t:jitteredMs(this.pullIntervalSeconds)}async runPullCycle(){if(!this.pullInFlight&&!(this.state===`dormant`||this.state===`disabled`)){if(this.state===`conflict`){this.schedulePull();return}if(isUnbornHead(this.projectDir)){this.schedulePull();return}this.pullInFlight=!0;try{await this.doPullCycle()}finally{this.pullInFlight=!1,this.schedulePull()}}}async doPullCycle(){let e=createGitInstance(this.projectDir,{credentialArgs:this.credentialArgs}),t;try{let s=(await e.git.raw(`rev-parse`,`--abbrev-ref`,`HEAD`)).trim();if(!s||s===`HEAD`){this.transitionTo(`disabled`),this.pausedReason=`detached-head`,log.warn({},`[sync] detached HEAD — pausing sync`);return}t=s,this.currentBranch=t}catch(e){this.handleError(classifyGitError(e instanceof Error?e:Error(String(e))));return}this.transitionTo(`fetching`);try{await e.git.fetch(`origin`),this.lastFetchUtc=new Date().toISOString(),this.consecutiveFailures=0,this.error=void 0}catch(e){let t=classifyGitError(e instanceof Error?e:Error(String(e)));this.handleError(t);return}try{let t=await e.git.status();this.ahead=t.ahead,this.behind=t.behind}catch{}if(this.behind>0&&this.conflictCount===0){this.transitionTo(`pulling`),this.setBatchInProgress?.(!0);try{if(await this.commitDirtyContentFilesToHead(e),!await this.pauseIfNonContentDirty(e))return;await e.git.merge([`origin/${t}`]),this.lastSyncUtc=new Date().toISOString(),this.behind=0,this.transitionTo(`idle`)}catch(e){let t=classifyGitError(e instanceof Error?e:Error(String(e)));t.class===`semantic`&&t.subclass===`merge-conflict`?await this.handleMergeConflict():this.handleError(t);return}finally{this.setBatchInProgress?.(!1)}}else this.transitionTo(`idle`);this.scheduleSaveState()}async runPushCycle(){if(!this.pushInFlight&&!(this.state===`dormant`||this.state===`disabled`)&&!(this.state===`conflict`||this.state===`auth-error`)){if(isUnbornHead(this.projectDir)){this.schedulePush();return}this.pushInFlight=!0;try{await this.doPushCycle(1)}finally{this.pushInFlight=!1,this.schedulePush()}}}async doPushCycle(e=0){let t=this.gatherContentFilesSync(),s=join(tmpdir(),`ok-sync-idx-${process.pid}-${Date.now()}.idx`),g=null;this.transitionTo(`pushing`);try{await withParentLock(async()=>{let e=createGitInstance(this.projectDir,{credentialArgs:this.credentialArgs,gitIndexFile:s});if(isUnbornHead(this.projectDir)){log.info({},`[sync] repo has no commits yet — skipping push cycle`),this.transitionTo(`idle`);return}let S;try{S=(await e.git.revparse(`HEAD`)).trim()}catch(e){let t=e instanceof Error?e.message:String(e),s=`${t}\n${e.git?.toString()??t}`;if(/unknown revision or path not in the working tree/i.test(s)||/ambiguous argument 'HEAD'/i.test(s)||/does not have any commits yet/i.test(s)){log.info({},`[sync] repo has no commits yet — skipping push cycle`),this.transitionTo(`idle`);return}this.handleError(classifyGitError(e instanceof Error?e:Error(String(e))));return}await e.git.raw([`read-tree`,S]);let w=new Set;try{let t=(await e.git.raw([`ls-tree`,`-r`,`--name-only`,S])).trim();for(let e of t?t.split(`
|
|
@@ -1617,5 +1617,5 @@ In headless mode, write the recap into the research article's "Further reading"
|
|
|
1617
1617
|
`,`
|
|
1618
1618
|
`).split(`
|
|
1619
1619
|
`),s=[],g=!1,S=``;for(let e of t){let t=/^\s{0,3}([`~]{3,})/.exec(e);if(t){g?RegExp(`^\\s{0,3}${S[0]==="`"?"`":`~`}{${S.length},}\\s*$`).test(e)&&(g=!1,S=``):(g=!0,S=t[1]);continue}if(g)continue;let w=stripInlineCodeSpans(e);for(TAG_VALUE_RE.lastIndex=0;;){let e=TAG_VALUE_RE.exec(w);if(e===null)break;let t=e[2];t&&s.push(t)}}return s}var TagIndex=class{contentDir;contentFilter;state=createEmptyState();constructor(e){this.contentDir=e.contentDir,this.contentFilter=e.contentFilter}updateDocumentFromMarkdown(e,t){if(!(isSystemDoc(e)||isConfigDoc(e)))try{let{frontmatter:s,body:g}=stripFrontmatter(t),S=extractFrontmatterTags(s?unwrapFrontmatterFences(s):``),w=extractInlineTagsFromBody(g),E=new Set([...S,...w]),D=new Set;for(let e of E)for(let t of expandTagToHierarchy(e))D.add(t);this.applyDocSnapshot(e,E,D)}catch(t){console.warn(`[tag-index] Failed to scan ${e} for tag extraction:`,t),this.deleteDocument(e)}}deleteDocument(e){if(isSystemDoc(e)||isConfigDoc(e))return;let t=this.state.byDoc.get(e);if(t){for(let s of t){let t=this.state.byTag.get(s);t&&(t.delete(e),t.size===0&&this.state.byTag.delete(s))}this.state.byDoc.delete(e),this.state.byDocLiteral.delete(e)}}renameDocument(e,t,s){this.deleteDocument(e),this.updateDocumentFromMarkdown(t,s)}getDocsForTag(e){let t=this.state.byTag.get(e);return t?[...t].sort((e,t)=>e.localeCompare(t)):[]}getDocsForTagWithMatches(e){let t=this.state.byTag.get(e);if(!t)return[];let s=[];for(let g of t){let t=this.state.byDocLiteral.get(g);if(!t)continue;let S=tagsMatchingPrefix(t,e);s.push({docName:g,matchingTags:[...S].sort((e,t)=>e.localeCompare(t))})}return s.sort((e,t)=>e.docName.localeCompare(t.docName))}getAllTags(){let e=[...this.state.byTag.entries()],t=e.map(([e])=>e),s=new Set;for(let e of t){let t=e.indexOf(`/`);t>0&&s.add(e.slice(0,t));let g=t;for(;g>0;)s.add(e.slice(0,g)),g=e.indexOf(`/`,g+1)}return e.map(([e,t])=>({name:e,count:t.size,isLeaf:!s.has(e)})).sort((e,t)=>e.name.localeCompare(t.name))}init(){if(this.state=createEmptyState(),!existsSync(this.contentDir))return;let e=this.listDocsWithPaths();for(let{docName:t,filePath:s}of e)try{let e=readFileSync(s,`utf-8`);this.updateDocumentFromMarkdown(t,e)}catch(e){console.warn(`[tag-index] Failed to read ${t} during init:`,e)}}applyDocSnapshot(e,t,s){let g=this.state.byDoc.get(e)??new Set;for(let t of g){if(s.has(t))continue;let g=this.state.byTag.get(t);g&&(g.delete(e),g.size===0&&this.state.byTag.delete(t))}for(let t of s){let s=this.state.byTag.get(t);s||(s=new Set,this.state.byTag.set(t,s)),s.add(e)}s.size===0?(this.state.byDoc.delete(e),this.state.byDocLiteral.delete(e)):(this.state.byDoc.set(e,s),this.state.byDocLiteral.set(e,t))}listDocsWithPaths(){let e=[];this.walkContentDir(this.contentDir,e),e.sort((e,t)=>e.docName===t.docName?t.filePath.localeCompare(e.filePath):e.docName.localeCompare(t.docName));let t=new Set;return e.filter(({docName:e})=>t.has(e)?!1:(t.add(e),!0))}walkContentDir(e,t){let s;try{s=readdirSync(e,{withFileTypes:!0})}catch(t){console.warn(`[tag-index] Failed to read directory ${e}:`,t);return}for(let g of s){let s=join(e,g.name);if(g.isDirectory()){let e=relative(this.contentDir,s);if(this.contentFilter&&e&&this.contentFilter.isDirExcluded(e))continue;this.walkContentDir(s,t);continue}if(!g.isFile()||!isSupportedDocFile(g.name))continue;let S=relative(this.contentDir,s);this.contentFilter?.isExcluded(S)||t.push({docName:stripDocExtension(S),filePath:s})}}};const PARK_SNAPSHOT_ORIGIN=(()=>{let e=Object.freeze({origin:`park-snapshot`,paired:!0});return Object.freeze({source:`local`,skipStoreHooks:!1,context:e})})();function createServer$1(e){let{contentDir:t,projectDir:s=t,quiet:g=!0,debounce:S=2e3,maxDebounce:w=1e4,gitEnabled:E=!0,commitDebounceMs:D=3e4,wipRef:O=`refs/wip/main`,configHomedirOverride:k,enableTestRoutes:j=!1,shadowRepo:F,contentRoot:L,destroyTimeoutMs:B=1e4,localOpCliArgs:H,skipStateManifestCheck:q=!1}=e,J=getLogger(`server`);function Y(){let e=readConfigSafely({absPath:resolveConfigPath(`project-local`,s),sideline:!1,warn:e=>J.warn({message:e},`[config] could not read project-local config`)}),t=e.value.autoSync?.enabled;return t==null?(e.valid||J.warn({},`[config] project-local autoSync.enabled unavailable (config invalid) — falling back to project config`),readConfigSafely({absPath:resolveConfigPath(`project`,s),sideline:!1,warn:e=>J.warn({message:e},`[config] could not read project config`)}).value.autoSync?.enabled===!0):t===!0}initTelemetry();let ee=randomUUID(),te=getLocalDir(t);if(acquireServerLock(te,{port:e.port??0,worktreeRoot:s,kind:e.lockKind??`interactive`,capabilities:[`http`,`ws`]}),!q)try{assertCompatibleStateManifest({lockDir:te,shadowRepoDir:resolveShadowDir(s)})}catch(e){throw releaseServerLock(te),e}let ne=createBasenameIndex(),ae=(e,t)=>ne.resolveEmbed(e,t),oe,se,ce,ue,de,fe,me,ge=null,_e=null,ve=null,ye=null,Ce=new Set,we=!1,Te;function De(e){ge?.signal(e)}let je=2e3,Me=null;function Pe(){Me!==null&&clearTimeout(Me),Me=setTimeout(()=>{Me=null,se.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist debounced cache:`,e)})},2e3)}try{oe=createContentFilter({projectDir:s,contentDir:t,onAfterRebuild:()=>{se.rebuildFromDisk(getActiveBranch()).catch(e=>{getLogger(`server-factory`).warn({err:e},`[content-filter] backlink-index rebuild failed after onAfterRebuild`)});try{ce.init()}catch(e){getLogger(`server-factory`).warn({err:e},`[content-filter] tag-index rebuild failed after onAfterRebuild`)}try{let e=at?.pruneFileIndexNowExcluded()??0;e>0&&getLogger(`server-factory`).info({pruned:e},`[content-filter] pruned now-excluded entries from fileIndex`)}catch(e){getLogger(`server-factory`).warn({err:e},`[content-filter] fileIndex prune failed after onAfterRebuild`)}}}),se=new BacklinkIndex({projectDir:s,contentDir:t,contentFilter:oe}),ce=new TagIndex({contentDir:t,contentFilter:oe});try{ce.init()}catch(e){console.warn(`[server-factory] tag-index init failed; continuing with empty index:`,e)}ue={current:F},de=createPersistenceExtension({contentDir:t,projectDir:s,gitEnabled:E,commitDebounceMs:D,wipRef:O,shadowRef:ue,contentRoot:L,backlinkIndex:se,configHomedirOverride:k,getCurrentBranch:()=>st?.getLastKnownBranch()??null,resolveEmbed:ae,getPrincipal:()=>ye,onAgentCommit:()=>ge?.signal(`session-activity`),onDiskFlush:(e,t)=>ge?.emitDiskAck(e,t),onConfigRejected:(e,t)=>ge?.emitConfigValidationRejected(e,t)}),fe=new Hocuspocus({quiet:g,debounce:S,maxDebounce:w,extensions:[de.extension]});let B=fe.shouldUnloadDocument.bind(fe);fe.shouldUnloadDocument=e=>{if((we||Ce.has(e))&&B(e))return!0;let t=e.name;return isSystemDoc(t)||isConfigDoc(t)||getReconciledBase(t)!==void 0||e.getXmlFragment(`default`).length!==0||e.getText(`source`).length!==0?!1:B(e)},Te=async e=>{Ce.add(e);try{await fe.unloadDocument(e)}finally{Ce.delete(e)}},ge=new CC1Broadcaster(fe),_e=new AgentFocusBroadcaster(fe),ve=new AgentPresenceBroadcaster(fe),me=new AgentSessionManager(fe);let q=createLiveDerivedIndexExtension({backlinkIndex:se,tagIndex:ce,signalChannel:De});fe.configuration.extensions.push(q),fe.configuration.extensions.push({__kind:`principal-auth`,async onAuthenticate(e){let t=e.token,s=parseHocuspocusAuthToken(t),g=s?.expectedServerInstanceId;if(typeof g==`string`&&g.length>0&&g!==ee)throw new HocuspocusAuthRejection(`server-instance-mismatch`,`server instance mismatch: client claimed ${g}, this server is ${ee}`);let S=s?.expectedBranch,w=getActiveBranch();if(typeof S==`string`&&S.length>0&&S!==w)throw new HocuspocusAuthRejection(`branch-mismatch`,`branch mismatch: client claimed ${S}, server is on ${w}`);if(!s)return;let E=e.context;typeof s.principalId==`string`&&(ye&&s.principalId===ye.id?E.principalId=ye.id:ye?console.warn(JSON.stringify({event:`principal-token-mismatch`,claimed:s.principalId,loaded:ye.id})):E.principalId=s.principalId),typeof s.tabSessionId==`string`&&(E.tabSessionId=s.tabSessionId),E.kind=`human`}}),fe.configuration.extensions.push({__kind:`config-doc-admission-guard`,async onAuthenticate(e){if(!isConfigDoc(e.documentName))return;let t=e.request,s=t.socket?.remoteAddress;if(s!==void 0&&!isLoopbackAddress(s))throw Error(`config-doc admission requires loopback peer (peer=${s}, doc=${e.documentName})`);let g=e.requestHeaders,S=(g&&typeof g.get==`function`?g.get(`host`):null)??t.headers?.host??void 0;if(!isAllowedWorkspaceHostHeader(S))throw Error(`config-doc admission requires loopback Host header (host=${S??`<absent>`}, doc=${e.documentName})`)}}),fe.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 J=createApiExtension({hocuspocus:fe,sessionManager:me,contentDir:t,contentFilter:oe,serverInstanceId:ee,getFileIndex:()=>at?at.getFileIndex():new Map,getAliasMap:()=>at?at.getAliasMap():new Map,enableTestRoutes:j,shadowRef:ue,flushGitCommit:()=>de.flushPendingGitCommit(),flushContributors:()=>de.flushContributors(),getCurrentBranch:()=>st?.getLastKnownBranch()??null,getDiskAckSVs:()=>ge?.getLatestDiskAckSVsAsBase64()??{},contentRoot:L,backlinkIndex:se,tagIndex:ce,signalChannel:De,agentFocusBroadcaster:_e,agentPresenceBroadcaster:ve,onAgentWrite:e.onAgentWrite,getSyncEngine:()=>vt,localOpCliArgs:H,projectDir:s,resolveEmbed:ae,getPrincipal:()=>ye,forceUnloadDocument:Te});fe.configuration.extensions.push(J),fe.configuration.extensions.push(createServerObserverExtension({mdManager,schema,shadowRef:ue,contentRoot:L,getCurrentBranch:()=>st?.getLastKnownBranch()??null,resolveEmbed:ae}))}catch(e){throw releaseServerLock(te),e}let Ie=null,Re=new Map,ze=[];function Be(e,t){let s=resolve(e,`rescue`),g=resolve(s,`${t}${getDocExtension(t)}`);return g.startsWith(`${s}/`)?g:null}function Ve(e){let t=fe.documents.get(e);if(!t)return null;let{frontmatter:s,body:g}=stripFrontmatter(t.getText(`source`).toString());return prependFrontmatter(s,g)}let Ue=(e,t)=>applyExternalChange(fe,e,t,ae),We=e=>{if(!e)return;let t=`[[${e}]]`;for(let[s]of fe.documents){if(isSystemDoc(s)||isConfigDoc(s))continue;let g=fe.documents.get(s);if(!g)continue;let S=g.getText(`source`).toString();if(S.includes(t))try{g.transact(()=>{applyDiskContentToDoc(g,S,ae,s)},FILE_WATCHER_ORIGIN)}catch(t){J.error({err:t,docName:s,assetBasename:e},`[asset-event] failed to re-render ${s} for asset basename ${e}`)}}},Ge=null,Ke=e=>{e&&(Ge===null&&(Ge=new Set,setImmediate(()=>{let e=Ge;if(Ge=null,e)try{for(let t of e)We(t)}catch(t){J.error({err:t,basenames:[...e]},`[asset-event] dedup rerender pass crashed`)}})),Ge.add(e))};function Xe(e){switch(e.kind){case`rename`:return e.newDocName;case`asset-create`:case`asset-delete`:return e.relativePath;default:return e.docName}}async function $e(e){try{switch(e.kind){case`create`:J.info({docName:e.docName},`[reconcile] create: ${e.docName}`),se.updateDocumentFromMarkdown(e.docName,e.content),Pe(),ce.updateDocumentFromMarkdown(e.docName,e.content),De(`files`),De(`backlinks`),De(`graph`),De(`tags`);break;case`update`:{let{docName:t,content:s}=e,g=fe.documents.get(t);if(!g){se.updateDocumentFromMarkdown(t,s),Pe(),ce.updateDocumentFromMarkdown(t,s),De(`backlinks`),De(`graph`),De(`tags`);return}let S=getReconciledBase(t)??``,w=Ve(t)??S,E=reconcile({docName:t,base:S,ours:w,theirs:s}),D=contentHash(S).slice(0,6),O=contentHash(w).slice(0,6),k=contentHash(s).slice(0,6);switch(J.info({docName:t,base:D,ours:O,theirs:k,result:E.kind},`[reconcile] ${t} base=${D} ours=${O} theirs=${k} result=${E.kind}`),E.kind){case`noop`:se.updateDocumentFromMarkdown(t,s),Pe(),ce.updateDocumentFromMarkdown(t,s),De(`backlinks`),De(`graph`),De(`tags`);break;case`clean`:try{Ue(t,E.newContent),setReconciledBase(t,E.newContent),incrementReconcile(),se.updateDocumentFromMarkdown(t,s),Pe(),ce.updateDocumentFromMarkdown(t,s),De(`backlinks`),De(`graph`),De(`tags`)}catch(e){J.error({err:e,docName:t},`[reconcile] failed to apply clean content to Y.Doc for ${t}`),setReconciledBase(t,s)}break;case`merged`:try{Ue(t,E.newContent),setReconciledBase(t,E.newContent),incrementReconcile(),se.updateDocumentFromMarkdown(t,s),Pe(),ce.updateDocumentFromMarkdown(t,s),De(`backlinks`),De(`graph`),De(`tags`)}catch(e){J.error({err:e,docName:t},`[reconcile] failed to apply merged content to Y.Doc for ${t}`),setReconciledBase(t,s)}break;case`conflicts`:try{Ue(t,E.newContent),setReconciledBase(t,E.newContent),incrementReconcile(),incrementConflict(),se.updateDocumentFromMarkdown(t,s),Pe(),ce.updateDocumentFromMarkdown(t,s),De(`backlinks`),De(`graph`),De(`tags`)}catch(e){J.error({err:e,docName:t},`[reconcile] failed to apply conflict content to Y.Doc for ${t}`),setReconciledBase(t,s)}break;case`refused`:{incrementConflict();let e=g.getMap(`lifecycle`);e.set(`status`,`conflict`),e.set(`reason`,E.reason);break}}break}case`delete`:{let{docName:t}=e,s=fe.documents.get(t);if(!s){se.deleteDocument(t),Pe(),ce.deleteDocument(t),De(`files`),De(`backlinks`),De(`graph`),De(`tags`);return}let g=getReconciledBase(t)??``,S=Ve(t)??``,w=S!==g;if(w&&ue.current){let e=ue.current,s=st?.getLastKnownBranch()??`main`;queueMicrotask(()=>{saveInMemoryCheckpoint(e,L??``,{kind:`external-change-rescue`,docName:t,contents:S,label:`External change recovered @ ${new Date().toISOString()}`,branch:s,metadata:{incomingDiskSha:``}}).then(()=>{incrementRescueBuffer(),J.info({docName:t},`[reconcile] rescue checkpoint saved (delete): ${t}`)}).catch(e=>{J.error({docName:t,err:e},`[reconcile] rescue checkpoint write failed: ${t}`)})})}s.getMap(`lifecycle`).set(`status`,`deleted-upstream`),deleteReconciledBase(t),se.deleteDocument(t),Pe(),ce.deleteDocument(t),J.info({docName:t,isDirty:w},`[reconcile] delete: ${t} (dirty=${w})`),fe.closeConnections(t),await Te(s),De(`files`),De(`backlinks`),De(`graph`),De(`tags`);break}case`rename`:{let{oldDocName:t,newDocName:s,content:g}=e,S=fe.documents.get(t);if(deleteReconciledBase(t),setReconciledBase(s,g),se.renameDocument(t,s,g),Pe(),ce.renameDocument(t,s,g),S){let e=S.getMap(`lifecycle`);e.set(`status`,`renamed`),e.set(`newPath`,s)}J.info({oldDocName:t,newDocName:s},`[reconcile] rename: ${t} → ${s}`),De(`files`),De(`backlinks`),De(`graph`),De(`tags`);break}case`conflict`:{let{docName:t}=e,s=fe.documents.get(t);if(!s)return;let g=s.getMap(`lifecycle`);g.set(`status`,`conflict`),g.set(`reason`,`conflict-markers`),J.info({docName:t},`[reconcile] conflict markers detected: ${t}`);break}case`asset-create`:ne.add(e.relativePath),De(`files`),Ke(basename(e.relativePath));break;case`asset-delete`:ne.remove(e.relativePath),De(`files`),Ke(basename(e.relativePath));break;default:assertNeverDiskEvent(e)}}catch(t){let s=Xe(e);J.error({err:t,kind:e.kind,label:s},`[reconcile] failed to handle ${e.kind} for ${s}`)}}let nt=[];async function rt(e){if(isBatchInProgress()){nt.push(e);return}await $e(e)}async function it(){let e=nt.splice(0,nt.length);for(let t of e)await $e(t)}let at=null,st=null,vt=null,Tt=null;async function Et(e){if(fe.documents.size===0)return;let t=!1,s=new Promise(e=>{fe.configuration.extensions.push({async afterUnloadDocument({instance:s}){!t&&s.getDocumentsCount()===0&&(t=!0,e())}})}),g=Array.from(fe.documents.keys());fe.closeConnections(),fe.flushPendingStores();for(let e of fe.documents.values())e.getConnectionsCount()===0&&fe.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 S,w=new Promise((s,w)=>{S=setTimeout(()=>{t=!0;let s=Array.from(fe.documents.keys()),S=[],E=[];if(ue.current){for(let e of s)if(!(isSystemDoc(e)||isConfigDoc(e)))try{let t=Ve(e);if(t===null){J.warn({docName:e},`[rescue] skipping ${e} — document dropped from map mid-rescue`),E.push(e);continue}let s=Be(ue.current.gitDir,e);if(!s){J.warn({docName:e,gitDir:ue.current.gitDir},`[rescue] path-traversal guard rejected docName: ${e}`),E.push(e);continue}mkdirSync(dirname(s),{recursive:!0}),writeFileSync(s,t,`utf-8`),incrementRescueBuffer(),S.push(e),J.info({docName:e},`[rescue] rescue buffer saved on flush timeout: ${e}`)}catch(t){E.push(e),J.error({err:t,docName:e},`[rescue] failed to write rescue buffer for ${e}`)}}else J.warn({stillLoadedCount:s.length},`[rescue] shadow repo unavailable at flush timeout — ${s.length} doc(s) will be lost: [${s.join(`, `)}]`),E.push(...s);let D=S.length>0||E.length>0?` — rescued [${S.join(`, `)}]${E.length>0?`, lost [${E.join(`, `)}]`:``}`:``;w(Error(`flushAllStoresAndWait timeout after ${e}ms — ${s.length}/${g.length} docs did not unload: [${s.join(`, `)}]${D}`))},e)});try{await Promise.race([s,w])}finally{S!==void 0&&clearTimeout(S)}}async function Dt(){return Tt||(Tt=(async()=>{let e=Date.now(),t=[];we=!0,Me!==null&&(clearTimeout(Me),Me=null);let g,S=await Promise.race([Ft.then(()=>`completed`,e=>(J.debug({err:e},`[server] init incomplete during shutdown`),`failed`)),new Promise(e=>{g=setTimeout(()=>e(`timeout`),5e3)})]);g!==void 0&&clearTimeout(g),S===`timeout`&&J.warn({},`[server] init did not complete within 5s during shutdown`);let w=fe.documents.size;try{try{try{st&&=(await st.unsubscribe(),null),at&&=(await at.unsubscribe(),null);for(let{docName:e,cleanup:t}of ze)try{await t()}catch(t){J.warn({err:t,docName:e},`[server] failed to stop config-file-watcher for ${e}`)}ze.length=0}catch(e){t.push({phase:`watcher-unsubscribe`,error:e instanceof Error?e.message:String(e)}),J.error({err:e},`[server] shutdown phase-1 watcher unsubscribe failed`)}try{ge?.destroy(),ve?.destroy(),Ie&&=(await Ie.disconnect(),null);for(let[e,t]of Re)try{await t.disconnect()}catch(t){J.warn({err:t,docName:e},`[server] failed to disconnect ${e} during shutdown`)}Re.clear()}catch(e){t.push({phase:`cc1-teardown`,error:e instanceof Error?e.message:String(e)}),J.error({err:e},`[server] shutdown phase-1b CC1 teardown failed`)}try{await me.closeAll()}catch(e){t.push({phase:`agent-session-drain`,error:e instanceof Error?e.message:String(e)}),J.error({err:e},`[server] shutdown phase-2 agent session drain failed`)}try{await Et(B)}catch(e){t.push({phase:`flush-all-stores`,error:e instanceof Error?e.message:String(e)}),J.error({err:e},`[server] shutdown phase-3 flush failed`)}let e;try{await Promise.race([(async()=>{await de.flushPendingGitCommit(),await de.waitForPendingCommits()})(),new Promise((t,s)=>{e=setTimeout(()=>s(Error(`L2 git flush timeout`)),B)})])}catch(e){t.push({phase:`git-commit-flush`,error:e instanceof Error?e.message:String(e)}),J.error({err:e},`[server] shutdown phase-4 git commit flush failed`)}finally{e!==void 0&&clearTimeout(e)}try{vt&&=(await vt.destroy(),null)}catch(e){t.push({phase:`sync-engine-stop`,error:e instanceof Error?e.message:String(e)}),J.error({err:e},`[server] shutdown sync-engine-stop failed`)}}finally{if(ue.current){try{let e=(await esm_default({baseDir:s,timeout:{block:5e3}}).revparse(`HEAD`)).trim();e&&writeFileSync(resolve(ue.current.gitDir,`last-known-head`),e,`utf-8`)}catch{}try{destroyShadowRepo(ue.current)}catch(e){t.push({phase:`shadow-repo-release`,error:e instanceof Error?e.message:String(e)}),J.error({err:e},`[server] shutdown phase-5 destroyShadowRepo failed`)}}let g=Date.now()-e;t.length===0?J.info({documentCount:w,durationMs:g},`[server] shutdown flushed ${w} documents in ${g}ms`):J.warn({documentCount:w,durationMs:g,phaseErrors:t},`[server] shutdown flushed ${w} documents in ${g}ms with ${t.length} phase error(s)`)}}finally{try{releaseServerLock(te)}catch(e){t.push({phase:`server-lock-release`,error:e instanceof Error?e.message:String(e)}),J.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)})}}})(),Tt)}let jt=[];async function Mt(){try{ye=await loadPrincipal(t),J.info({principalId:ye.id},`[server] principal loaded`)}catch(e){J.warn({err:e},`[server] principal load failed — browser writes will use SERVICE_WRITER`)}if(!ue.current)try{ue.current=await initShadowRepo(s),J.info({gitDir:ue.current.gitDir},`[server] history repo initialized at ${ue.current.gitDir}`)}catch(e){J.error({err:e},`[server] history repo init failed`),jt.push(`shadow-repo`)}if(ue.current){let e=null;try{e=loadRenameLogIndex(ue.current.gitDir),sweepLazyPopOrphans(ue.current.gitDir,e),setRenameLogIndex(ue.current.gitDir,e),J.info({entries:e.byTo.size},`[server] rename log loaded (${e.byTo.size} entries)`)}catch(e){J.warn({err:e},`[rename-log] boot-time load/sweep failed; rename history unavailable`)}if(e){let t=1e4;try{await Promise.race([gcRenameLog(ue.current,e,{rebuild:!0}),new Promise((e,s)=>setTimeout(()=>s(Error(`boot-time GC exceeded ${t}ms`)),t))])}catch(e){J.warn({err:e},`[rename-log] boot-time GC/rebuild failed; index loaded without GC`)}}}if(ue.current)try{await shadowGit(ue.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`)){J.warn({},`[server] history repo appears corrupted — reinitializing`);try{ue.current=await initShadowRepo(s)}catch(e){J.error({err:e},`[server] history repo reinit failed`),ue.current=void 0,jt.includes(`shadow-repo`)||jt.push(`shadow-repo`)}}else J.error({err:e},`[server] history repo check failed (transient?)`)}if(ue.current)try{let e=resolve(ue.current.gitDir,`last-known-head`),t=null;try{t=readFileSync(e,`utf-8`).trim()||null}catch{}let g=null;try{g=(await esm_default({baseDir:s,timeout:{block:1e4}}).revparse(`HEAD`)).trim()||null}catch{}if(g!==null){if(g!==t){let e=`main`;try{let t=(await esm_default({baseDir:s,timeout:{block:1e4}}).raw(`rev-parse`,`--abbrev-ref`,`HEAD`)).trim();t&&t!==`HEAD`&&(e=t)}catch{}J.info({lastKnownHead:t,currentHead:g,branch:e},`[head-drift] lastKnownHead=${t??`null`}, currentHead=${g}, action=import`);try{await commitUpstreamImport(ue.current,L??``,t,g,e),incrementUpstreamImport()}catch(e){J.warn({err:e},`[head-drift] commitUpstreamImport failed — continuing`)}}else J.info({currentHead:g},`[head-drift] lastKnownHead=${t??`null`}, currentHead=${g}, action=noop`);try{writeFileSync(e,g,`utf-8`)}catch(e){J.warn({err:e},`[head-drift] failed to write last-known-head`)}}}catch(e){J.warn({err:e},`[head-drift] check failed — continuing`)}try{let e=recoverPendingManagedRename(t);if(e.recovered&&e.journal){let t=e.journal.version===2?e.journal.fromPath:e.journal.sourceDocName,s=e.journal.version===2?e.journal.toPath:e.journal.destinationDocName;J.warn({journalVersion:e.journal.version,fromPath:t,toPath:s,restoredDocNames:e.restoredDocNames},`[managed-rename] recovered pending rename ${t} -> ${s}`)}}catch(e){J.error({err:e},`[server] managed rename recovery failed`),jt.push(`managed-rename-recovery`)}try{let e=cleanupOrphanUploadTempfiles(t);(e.deleted>0||e.errors>0)&&J.info({scanned:e.scanned,deleted:e.deleted,errors:e.errors},`[upload-tempfile-sweep] swept ${e.deleted} orphan tempfile(s)`)}catch(e){J.error({err:e},`[server] upload-tempfile sweep failed`),jt.push(`upload-tempfile-sweep`)}try{Ie=await fe.openDirectConnection(SYSTEM_DOC_NAME),ge?.emitServerInfo(ee,getActiveBranch())}catch(e){J.error({err:e},`[server] failed to open __system__ direct connection — CC1 push disabled`),jt.push(`cc1-push`)}for(let e of CONFIG_DOC_NAMES)try{let t=await fe.openDirectConnection(e);Re.set(e,t)}catch(t){J.error({err:t,docName:e},`[server] failed to open ${e} direct connection — config bind degraded`),jt.push(`config-doc:${e}`)}let e=new Map([[CONFIG_DOC_NAME_PROJECT,resolveConfigPath(`project`,s)],[CONFIG_DOC_NAME_PROJECT_LOCAL,resolveConfigPath(`project-local`,s)],[CONFIG_DOC_NAME_USER,resolveConfigPath(`user`,s,k)]]);for(let t of CONFIG_DOC_NAMES){let s=e.get(t);if(s)try{J.info({docName:t,path:s},`[config-file-watcher] starting`);let e=await startConfigFileWatcher(s,e=>{let s=fe.documents.get(t);J.info({docName:t,hasDocument:s!==void 0,contentLength:e.length},`[config-file-watcher] file changed`);let g=applyExternalConfigChange(s??null,t,e,de.configPersistenceCtx);if(J.info({docName:t,outcome:g},`[config-file-watcher] applyExternalConfigChange outcome`),t===`__config__/project`||t===`__local__/project`){let e=Y();vt?.setEnabled(e).catch(t=>{J.warn({err:t,enabled:e},`[sync] failed to apply autoSync.enabled from config`)})}});ze.push({docName:t,cleanup:e}),J.info({docName:t,path:s},`[config-file-watcher] started`)}catch(e){J.warn({err:e,docName:t,path:s},`[config-file-watcher] failed to start for ${t}`),jt.push(`config-file-watcher:${t}`)}}try{let e=resolve(t,`.okignore`),g=resolve(s,`.gitignore`),S=J;S.info({okignorePath:e,gitignorePath:g},`[ignore-watcher] starting multi-path watcher for .okignore + .gitignore`);let w=await startMultiPathConfigFileWatcher([e,g],(t,g)=>{(async()=>{if(t===e)try{let e=applyExternalConfigChange(fe.documents.get(`__config__/okignore`)??null,CONFIG_DOC_NAME_OKIGNORE,g,de.configPersistenceCtx);S.info({docName:CONFIG_DOC_NAME_OKIGNORE,outcome:e},`[ignore-watcher] applyExternalConfigChange outcome`)}catch(e){S.error({err:e,changedPath:relative(s,t)},`[ignore-watcher] applyExternalConfigChange failed; rebuild proceeds independently`)}let w=await oe.rebuildIgnorePatterns();if(w.ok)S.info({changedPath:relative(s,t),patternCount:w.patternCount,nestedFileCount:w.nestedFileCount,durationMs:w.durationMs},`[ignore-watcher] rebuild succeeded — broadcasting files channel`),ge?.signal(`files`);else{let e=relative(s,t)||`.`;S.warn({changedPath:e,error:w.error.message},`[ignore-watcher] rebuild failed — emitting config-ignore-nested-error`),ge?.emitConfigIgnoreNestedError(e,w.error.message)}})().catch(e=>{S.error({err:e,changedPath:relative(s,t)||`.`},`[ignore-watcher] handler threw`)})});ze.push({docName:`__ignore-files__`,cleanup:w}),S.info({okignorePath:e,gitignorePath:g},`[ignore-watcher] multi-path watcher started`)}catch(e){J.warn({err:e,projectDir:s,contentDir:t},`[ignore-watcher] failed to start multi-path watcher`),jt.push(`ignore-files-watcher`)}let g=resolveGitDir(s),S=g?readBranchFromHead(g)??`main`:`main`;switchReconciledBaseScope(S),se.switchBranch(S);try{{let e=getActiveBranch();try{if(await se.loadFromDisk(e)){let t=await se.reconcileWithDisk(e);(t.added>0||t.updated>0||t.deleted>0)&&J.info(t,`[backlinks] startup reconcile: offline changes applied`)}else await se.rebuildFromDisk(e);se.saveToDisk().catch(t=>{console.warn(`[backlinks] Failed to persist startup cache for ${e}:`,t)})}catch(t){J.error({err:t,branch:e},`[backlinks] startup init failed; index will populate incrementally via watcher`)}}at=await startWatcher(t,rt,oe),ce.init();let e=0;try{seedBasenameIndex({contentDir:t,contentFilter:oe,basenameIndex:ne,onSkip:(t,s,g)=>{e++,J.warn({reason:t,code:s,path:g},`[basename-index] skipped entry during seed (${t}${s?` ${s}`:``})`)}}),e>0&&(J.warn({count:e},`[basename-index] startup seed completed with ${e} skipped entries — embeds under inaccessible subtrees will not resolve`),jt.push(`basename-index-partial`))}catch(e){J.error({err:e},`[basename-index] startup seed failed`),jt.push(`basename-index`)}}catch(e){J.error({err:e},`[server] disk bridge watcher failed to start`),jt.push(`file-watcher`)}try{st=await startHeadWatcher(s,async({trigger:e})=>{if(J.info({trigger:e},`[batch] begin trigger=${e}`),incrementBatch(),fe.flushPendingStores(),await de.flushPendingGitCommit(),setBatchInProgress(!0),ue.current){let e=getActiveBranch(),t=resolveGitDir(s),g=t?readBranchFromHead(t)??e:e,S=[];for(let[e,t]of fe.documents){if(isSystemDoc(e)||isConfigDoc(e))continue;let s=null;if(t.transact(()=>{s=Ve(e)},PARK_SNAPSHOT_ORIGIN),s===null)continue;let g=getReconciledBase(e)??s;S.push({docName:e,markdown:s,diskSnapshot:g})}if(S.length>0)try{let t=await parkBranch(ue.current,e,SERVICE_WRITER.id,S,g);t&&(incrementPark(),J.info({count:S.length,branch:e,sha:t.slice(0,8)},`[history] parked ${S.length} docs on ${e} → ${t.slice(0,8)}`))}catch(e){J.error({err:e},`[shadow] park failed`)}}},async e=>{let s=nt.length,g=e.newBranch??`main`;if(J.info({kind:e.batchKind,headMoved:e.headMoved,docs:s,timeout:!!e.timeout},`[batch] end kind=${e.batchKind} headMoved=${e.headMoved} docs=${s}${e.timeout?` timeout`:``}`),e.batchKind===`within-branch`)setBatchInProgress(!1),await it(),await de.flushDeferredStores(`within-branch`);else{incrementBranchSwitch(),nt.splice(0,nt.length),switchReconciledBaseScope(g),Me!==null&&(clearTimeout(Me),Me=null),se.switchBranch(g),oe.rebuildDirCount();try{let e=0;ne.clear(),seedBasenameIndex({contentDir:t,contentFilter:oe,basenameIndex:ne,onSkip:(t,s,S)=>{e++,J.warn({reason:t,code:s,path:S,branch:g},`[basename-index] skipped entry during branch-switch reseed (${t}${s?` ${s}`:``})`)}}),e>0&&(J.warn({count:e,branch:g},`[basename-index] branch-switch reseed completed with ${e} skipped entries — embeds under inaccessible subtrees will not resolve on this branch`),jt.includes(`basename-index-partial`)||jt.push(`basename-index-partial`))}catch(e){J.error({err:e,branch:g},`[basename-index] branch-switch reseed failed`)}for(let[e,s]of fe.documents)if(!(isSystemDoc(e)||isConfigDoc(e)))try{let S=safeContentPath(e,t);if(!existsSync(S)){let t=getReconciledBase(e)??``,S=Ve(e)??``;if(S!==t&&ue.current){let t=ue.current;queueMicrotask(()=>{saveInMemoryCheckpoint(t,L??``,{kind:`external-change-rescue`,docName:e,contents:S,label:`External change recovered @ ${new Date().toISOString()}`,branch:g,metadata:{incomingDiskSha:``}}).then(()=>{incrementRescueBuffer(),J.info({docName:e},`[reconcile] rescue checkpoint saved on branch switch: ${e}`)}).catch(t=>{J.error({docName:e,err:t},`[reconcile] rescue checkpoint write failed: ${e}`)})})}s.getMap(`lifecycle`).set(`status`,`deleted-upstream`),J.info({docName:e,branch:g},`[branch-switch] tombstone: ${e} (not on ${g})`);continue}let w=readFileSync(S,`utf-8`);Ue(e,w),setReconciledBase(e,w),J.info({docName:e},`[branch-switch] reset: ${e}`)}catch(t){J.error({err:t,docName:e},`[branch-switch] failed to reset ${e}`)}J.info({branch:g,docCount:fe.documents.size},`[branch-switch] loaded branch ${g} (${fe.documents.size} docs)`);try{if(await se.loadFromDisk(g)){let e=await se.reconcileWithDisk(g);(e.added>0||e.updated>0||e.deleted>0)&&J.info(e,`[backlinks] branch-switch reconcile for ${g}`)}else await se.rebuildFromDisk(g);se.saveToDisk(g).catch(e=>{console.warn(`[backlinks] Failed to persist branch cache for ${g}:`,e)})}catch(e){J.error({err:e,branch:g},`[backlinks] branch-switch rebuild failed; backlinks may be stale`)}if(ce.init(),ue.current&&e.batchKind===`cross-branch`){let e=0;for(let[t]of fe.documents)if(!(isSystemDoc(t)||isConfigDoc(t)))try{let s=await readParkedState(ue.current,g,SERVICE_WRITER.id,t);if(!s||s.markdown===s.diskSnapshot)continue;let S=getReconciledBase(t);if(!S)continue;let w=reconcile({docName:t,base:s.diskSnapshot,ours:s.markdown,theirs:S});switch(w.kind){case`merged`:case`clean`:Ue(t,w.newContent),setReconciledBase(t,w.newContent),e++;break;case`conflicts`:Ue(t,w.newContent),setReconciledBase(t,w.newContent),incrementConflict(),e++;break;case`noop`:case`refused`:break}}catch(e){J.error({err:e,docName:t},`[branch-switch] restore WIP failed for ${t}`)}e>0&&J.info({count:e,branch:g},`[branch-switch] restored ${e} parked docs on ${g}`)}if(e.oldBranch?.startsWith(`detached-`)&&ue.current)try{let t=shadowGit(ue.current),s=(await t.raw(`for-each-ref`,`refs/wip/${e.oldBranch}/`,`--format=%(refname)`)).trim();if(s){for(let e of s.split(`
|
|
1620
|
-
`))e&&await t.raw(`update-ref`,`-d`,e);J.info({context:e.oldBranch},`[branch-switch] cleaned up detached context ${e.oldBranch}`)}}catch(e){J.error({err:e},`[branch-switch] detached cleanup failed`)}setBatchInProgress(!1),await de.flushDeferredStores(`discard-stale`),ge?.emitBranchSwitched(g)}if(e.headMoved&&e.newHead&&ue.current&&s>0){let t=L??`.`;try{let s=await commitUpstreamImport(ue.current,t,e.oldHead,e.newHead,g);incrementUpstreamImport(),J.info({oldHead:e.oldHead?.slice(0,8)??`null`,newHead:e.newHead.slice(0,8),sha:s.slice(0,8)},`[history] upstream-import from ${e.oldHead?.slice(0,8)??`null`}..${e.newHead.slice(0,8)} → ${s.slice(0,8)}`)}catch(e){J.error({err:e},`[shadow] upstream-import failed`)}}})}catch(e){J.error({err:e},`[server] HEAD watcher failed to start`),jt.push(`head-watcher`)}let w=H?.[0]??`open-knowledge`,E=[`-c`,`credential.helper=!${H&&H.length>1?H.join(` `):w} auth git-credential`];try{vt=new SyncEngine({projectDir:s,contentDir:t,contentFilter:oe,contentRoot:L,syncEnabled:Y(),credentialArgs:E,cc1Broadcaster:ge,setBatchInProgress:e=>{setBatchInProgress(e),e||de.flushDeferredStores(`within-branch`).catch(e=>{J.error({err:e},`[persistence] deferred store drain failed after sync batch`)})},onStateChange:e=>{J.info({state:e},`[sync] state → ${e}`)},onAutoDisable:async e=>{J.warn({reason:e},`[sync] auto-disabled — persisting to project-local config`);let t=await writeConfigPatch({cwd:s,scope:`project-local`,patch:{autoSync:{enabled:!1}}});t.ok||J.error({result:t,reason:e,humanError:humanFormat(t.error),configPath:resolveConfigPath(`project-local`,s)},`[sync] failed to persist auto-disable — next restart WILL re-enable sync and re-trigger the same failure. Check permissions on the config path.`)}}),await vt.start()}catch(e){J.warn({err:e},`[server] SyncEngine failed to start — sync disabled`),vt=null}}let Ft=Mt();return{hocuspocus:fe,sessionManager:me,cc1Broadcaster:ge,agentFocusBroadcaster:_e,agentPresenceBroadcaster:ve,contentFilter:oe,basenameIndex:ne,serverInstanceId:ee,destroy:Dt,ready:Ft,degraded:jt,lockDir:te,get syncEngine(){return vt}}}const LEGACY_RUNTIME_FILENAMES=[`server.lock`,`ui.lock`,`state.json`,`principal.json`,`sync-state.json`,`conflicts.json`,`last-spawn-error.log`],LEGACY_RUNTIME_DIRNAMES=[`cache`,`tmp`];function findLegacyRuntimeFiles(e){let t=resolve(e,LOCAL_DIR);if(!(()=>{if(!existsSync(t))return!0;try{return readdirSync(t).length===0}catch{return!0}})())return[];let s=[];for(let t of LEGACY_RUNTIME_FILENAMES)existsSync(resolve(e,t))&&s.push(t);for(let t of LEGACY_RUNTIME_DIRNAMES){let g=resolve(e,t);try{existsSync(g)&&statSync(g).isDirectory()&&s.push(`${t}/`)}catch{}}return s}function computeWorktreeAttributes(e){let t=resolveGitDirDetailed(e);switch(t.kind){case`directory`:return{kind:`main`,gitdir:t.path};case`linked`:return{kind:`linked`,gitdir:t.path};case`malformed-pointer`:return{kind:`linked`,gitdir:null};case`inaccessible`:case`absent`:return{kind:`main`,gitdir:null}}}const DEFAULT_IDLE_THRESHOLD_MS=1800*1e3,DESTROY_STEP_TIMEOUT_MS=5e3;async function bootServer(e){initTelemetry();let{kind:t,gitdir:s}=computeWorktreeAttributes(e.projectDir??e.contentDir),g={"ok.worktree.kind":t};return s!==null&&(g[`ok.worktree.gitdir`]=normalizeFsPath(s)),withSpan(`ok.boot`,{attributes:g},async()=>bootServerInner(e))}async function bootServerInner(e){let t=e.skipAutoInit??!1,s=e.attachUiSibling??!0,g=e.idleShutdownMs,S=e.log??getLogger(`boot`),w=process.env.OK_LOCK_KIND===`mcp-spawned`||process.env.OK_LOCK_KIND===`interactive`?process.env.OK_LOCK_KIND:void 0,E=e.lockKind??w??`interactive`,{createServer:D}=await import(`node:http`),{updateServerLockPort:O}=await import(`./server-lock-D7DXNVql-B5nINglj.mjs`).then(e=>e.a),k=!1;if(!t&&e.autoInitFn)try{k=!!await e.autoInitFn()}catch(e){S.warn({err:e},`autoInitFn failed`)}let j=e.projectDir??e.contentDir,F=resolve(j,`.ok`);if(!existsSync(resolve(F,`config.yml`)))throw new MissingOkConfigError(existsSync(F)?`config`:`okdir`,j);existsSync(resolve(F,`.gitignore`))||console.warn("[boot] Note: .ok/.gitignore is missing — per-machine state files in .ok/ may show up as untracked changes. Run `ok init` to add the recommended ignore entries.");let L=findLegacyRuntimeFiles(F);L.length>0&&console.warn(`[boot] Found legacy runtime files at .ok/${L.join(`, `)}. Delete .ok/ and re-init — these files moved to .ok/${LOCAL_DIR}/.`);let B=createServer$1({contentDir:e.contentDir,projectDir:e.projectDir,contentRoot:e.contentRoot,port:e.port,host:e.host,quiet:e.quiet??!1,debounce:e.debounce,maxDebounce:e.maxDebounce,gitEnabled:e.gitEnabled,commitDebounceMs:e.commitDebounceMs,wipRef:e.wipRef,enableTestRoutes:e.enableTestRoutes,shadowRepo:e.shadowRepo,destroyTimeoutMs:e.destroyTimeoutMs,localOpCliArgs:e.localOpCliArgs,onAgentWrite:e.onAgentWrite,lockKind:E,skipStateManifestCheck:e.skipStateManifestCheck}),{hocuspocus:H,destroy:q,ready:J,degraded:Y,lockDir:ee,sessionManager:te,agentFocusBroadcaster:ne,agentPresenceBroadcaster:ae}=B,oe=(()=>{let t=e.host??`localhost`;return t===`0.0.0.0`||t===`::`?`localhost`:t.includes(`:`)&&!t.startsWith(`[`)?`[${t}]`:t})(),se=e.port??0,ce=createMcpHttpHandler({contentDir:e.contentDir,projectDir:e.projectDir??e.contentDir,config:e.config,getServerUrl:()=>`http://${oe}:${se}`,log:S}),ue=D(),de=mountMcpAndApi({httpServer:ue,hocuspocus:H,mcpHttpHandler:ce,log:S,sessionManager:te,agentFocusBroadcaster:ne,agentPresenceBroadcaster:ae,keepaliveGraceMs:e.keepaliveGraceMs}),fe=null;g!==null&&(fe=attachIdleShutdown({httpServer:ue,thresholdMs:g??DEFAULT_IDLE_THRESHOLD_MS,log:S,onShutdown:(e.idleShutdownHandler??(e=>async()=>{await e()}))(async()=>{await q()})})),await new Promise((t,s)=>{let g=e=>s(e);ue.once(`error`,g),ue.listen(e.port,e.host,()=>{ue.removeListener(`error`,g),t()})});let me=ue.address(),ge=typeof me==`object`&&me?me.port:e.port??0;if(se=ge,O(ee,ge),s&&e.spawnUiSiblingFn)try{await e.spawnUiSiblingFn({lockDir:ee,log:S})}catch(e){S.warn({err:e},`spawnUiSiblingFn failed`)}let _e=!1,ve=async(e,t)=>{let s;try{await Promise.race([t(),new Promise((t,g)=>{s=setTimeout(()=>{g(Error(`${e} timed out after ${DESTROY_STEP_TIMEOUT_MS}ms`))},DESTROY_STEP_TIMEOUT_MS),s.unref?.()})])}finally{s!==void 0&&clearTimeout(s)}};return{httpServer:ue,destroy:async()=>{if(_e)return;_e=!0;let e=[],t=async(t,s)=>{try{await ve(t,s)}catch(s){e.push(s),S.warn({err:s,step:t},`bootServer destroy step failed`)}};try{fe?.detach()}catch(t){e.push(t),S.warn({err:t,step:`idleHandle.detach`},`bootServer destroy step failed`)}if(await t(`mount.shutdown`,()=>de.shutdown()),await t(`mcpHttpHandler.close`,()=>ce.close()),await t(`mount.wss.close`,()=>new Promise((e,t)=>{de.wss.close(s=>s?t(s):e())})),await t(`httpServer.closeAllConnections`,async()=>{ue.closeAllConnections?.()}),await t(`httpServer.close`,()=>new Promise((e,t)=>{ue.close(s=>s&&s.code!==`ERR_SERVER_NOT_RUNNING`?t(s):e())})),await t(`destroyHocuspocus`,()=>q()),await t(`shutdownTelemetry`,()=>shutdownTelemetry()),e.length>0)throw AggregateError(e,`bootServer destroy completed with errors`)},lockDir:ee,contentDir:e.contentDir,port:ge,ready:J,degraded:Y,didAutoInit:k,serverInstance:B}}const ConfigSchema=ConfigSchema$1;function detectClaudeDesktopPresence(e={}){let t=e.home??homedir(),s=e.platformName??process.platform,g=e.env??process.env;return s===`darwin`?existsSync(join(t,`Library`,`Application Support`,`Claude`)):s===`win32`?existsSync(join(g.APPDATA??join(t,`AppData`,`Roaming`),`Claude`)):!1}const execFileAsync=promisify(execFile);var ProjectGitInitError=class extends Error{stderr;constructor(e,t=``,s){super(e,s),this.name=`ProjectGitInitError`,this.stderr=t}};async function isInsideExistingWorkTree(e){try{let{stdout:t}=await execFileAsync(`git`,[`rev-parse`,`--is-inside-work-tree`],{cwd:e});return t.trim()===`true`}catch{return!1}}async function ensureProjectGit(e){let t=resolve(e),s=resolve(t,`.git`);if(existsSync(s)||await isInsideExistingWorkTree(t))return{didInit:!1};let g=``;try{g=(await execFileAsync(`git`,[`init`,`--initial-branch=main`,t])).stderr??``}catch(e){let s=typeof e==`object`&&e&&`stderr`in e?String(e.stderr??``):``;throw new ProjectGitInitError(`git init failed at ${t}: ${e instanceof Error?e.message:String(e)}`,s,{cause:e})}if(!existsSync(resolve(s,`HEAD`)))throw new ProjectGitInitError(`git init reported success but ${s}/HEAD is missing (partial init detected)`,g);return console.log(`[project-git] initialized .git/ at ${t} (branch: main)`),{didInit:!0}}async function resolvePackageVersion(e,t){let s;try{s=createRequire(t).resolve(e)}catch(e){if(e?.code===`MODULE_NOT_FOUND`)return;throw e}for(let t=dirname(s),g=0;g<32;g+=1){let s=join(t,`package.json`);if(existsSync(s))try{let t=JSON.parse(await readFile$1(s,`utf-8`));if(t.name===e&&typeof t.version==`string`)return t.version}catch{}let g=dirname(t);if(g===t)return;t=g}}export{buildExecResult as $,validateSkillZip as $n,isSystemDoc as $t,PinoLogger as A,rewriteMarkdownLinksForDocumentRename as An,gcCheckpointRefs as At,SeedRootDirError as B,saveInMemoryCheckpoint as Bn,incrementServerObserverFire as Bt,MANAGED_RENAME_ORIGIN as C,resetMetrics as Cn,createTestLogger as Ct,McpLogger as D,resolveCursorSpawnInvocation as Dn,evictStaleTrackerEntries as Dt,MISSING_OK_CONFIG_MESSAGE as E,resolveCursorBinaryDefault as En,ensureProjectGit as Et,STARTER_FOLDERS as F,runDeviceFlowSubprocess as Fn,getMetrics as Ft,applyAgentMarkdownWrite as G,shutdownTelemetry as Gn,isAllowedApiOrigin as Gt,TagIndex as H,seedBasenameIndex as Hn,initTelemetry as Ht,STARTER_FOLDER_FRONTMATTER_FILENAME as I,runWithMcpLogger as In,getTracer as It,assertCompatibleStateManifest as J,toBroadcasterKey as Jn,isHocuspocusAuthRejectionReason as Jt,applyExternalChange as K,splitMarkdownBlocks as Kn,isAllowedWorkspaceHostHeader as Kt,STARTER_TEMPLATES as L,safeContentPath as Ln,handleCollabSocketError as Lt,ROLLBACK_ORIGIN as M,runAuthReposSubprocess as Mn,getLocalDir as Mt,SERVICE_WRITER as N,runAuthStatusSubprocess as Nn,getLogger as Nt,MissingOkConfigError as O,resolveLockDir as On,extractWikiLinksFromMarkdown as Ot,SKILL_INSTALL_EVENTS_FILE_REL as P,runCloneSubprocess as Pn,getMeter as Pt,buildAndOpenSkill as Q,validateCloneInputs as Qn,isSelfWrite as Qt,STATE_MANIFEST_FILENAME as R,safeSubdir as Rn,handleSpawnCursor as Rt,LOG_MD_TEMPLATE as S,removeLastKnownHash as Sn,createServerObserverExtension as St,MCP_SERVER_NAME as T,resolveContentDir as Tn,detectProjectShape as Tt,UiLockCollisionError as U,setActiveSpanAttributes as Un,installTestLoggers as Ut,StateManifestError as V,saveVersion as Vn,initShadowRepo as Vt,acquireUiLock as W,shadowGit as Wn,installUserSkill as Wt,attachIdleShutdown as X,updateUiLockPort as Xn,isPairedWriteOrigin as Xt,assertNeverDiskEvent as Y,updateLastKnownHash as Yn,isLoopbackAddress as Yt,bootServer as Z,validateAgentId as Zn,isPathWithinDir as Zt,HOCUSPOCUS_AUTH_REJECTION_REASONS as _,reconcile as _n,createLiveDerivedIndexExtension as _t,AgentPresenceBroadcaster as a,parseHocuspocusAuthToken as an,JSONRPCMessageSchema as ar,clearContributors as at,INSTALLED_AGENTS_SCHEMES as b,registerWrite as bn,createPersistenceExtension as bt,BacklinkIndex as c,planSeed as cn,isJSONRPCRequest as cr,commitWipFromTree as ct,CURSOR_BUNDLE_PATHS_BY_PLATFORM as d,readServerPackageVersion as dn,resolveConfigPath as dr,contributorCount as dt,lastKnownHash as en,withSpan as er,buildReadResult as et,ConfigSchema as f,readSkillInstallStateSnapshot as fn,writeConfigPatch as fr,createApiExtension as ft,GIT_UPSTREAM_WRITER as g,readUiLock as gn,createExternalChangeHandler as gt,FILE_WATCHER_ORIGIN as h,readTargetVersion as hn,createContentFilterAsync as ht,AgentFocusBroadcaster as i,mountMcpAndApi as in,writeTracker as ir,classifyEvents as it,ProjectGitInitError as j,rewriteWikiLinksForDocumentRename as jn,getCurrentMcpLogger as jt,OBSERVER_SYNC_ORIGIN as k,resolvePackageVersion as kn,formatContributors as kt,CC1Broadcaster as l,readAllTargets as ln,isJSONRPCResultResponse as lr,containsConflictMarkers as lt,FILE_SYSTEM_WRITER as m,readTargetRecordedAt as mn,MalformedGitPointerError as mr,createContentFilter as mt,AGENT_ID_RE as n,loadPrincipal as nn,writeStateManifest as nr,buildStarterFolderFrontmatterYaml as nt,AgentSessionCapacityError as o,parseKeepaliveConnectionId as on,LATEST_PROTOCOL_VERSION as or,commitUpstreamImport as ot,DEFAULT_CHECKPOINT_RETENTION as p,readStateManifest as pn,GitDirAccessError as pr,createAssetServeMiddleware as pt,applySeed as q,startWatcher as qn,isConfigDoc as qt,AGENT_WRITE_ORIGIN as r,loggerFactory as rn,writeTargetVersion as rr,buildWipTree as rt,AgentSessionManager as s,pathToDocName as sn,isInitializedNotification as sr,commitWip as st,AGENT_ID_MAX_LEN as t,listRescueCheckpoints as tn,withSpanSync as tr,buildSkillZip as tt,CONFLICT_MARKER_RE as u,readBranchFromHead as un,readConfigSafely as ur,contentHash as ut,HocuspocusAuthRejection as v,recordContributor as vn,createMcpHttpHandler as vt,MAX_AGENT_SESSIONS as w,resolveBundledSkillDir as wn,detectClaudeDesktopPresence as wt,LIVE_DERIVED_INDEX_DEBOUNCE_MS as x,releaseUiLock as xn,createServer$1 as xt,HocuspocusAuthTokenSchema as y,recordSkillInstallEvent as yn,createOsProbe as yt,SeedPrerequisiteError as z,safetyCheckpoint as zn,incrementCollabSocketFilteredError as zt};
|
|
1621
|
-
//# sourceMappingURL=dist-
|
|
1620
|
+
`))e&&await t.raw(`update-ref`,`-d`,e);J.info({context:e.oldBranch},`[branch-switch] cleaned up detached context ${e.oldBranch}`)}}catch(e){J.error({err:e},`[branch-switch] detached cleanup failed`)}setBatchInProgress(!1),await de.flushDeferredStores(`discard-stale`),ge?.emitBranchSwitched(g)}if(e.headMoved&&e.newHead&&ue.current&&s>0){let t=L??`.`;try{let s=await commitUpstreamImport(ue.current,t,e.oldHead,e.newHead,g);incrementUpstreamImport(),J.info({oldHead:e.oldHead?.slice(0,8)??`null`,newHead:e.newHead.slice(0,8),sha:s.slice(0,8)},`[history] upstream-import from ${e.oldHead?.slice(0,8)??`null`}..${e.newHead.slice(0,8)} → ${s.slice(0,8)}`)}catch(e){J.error({err:e},`[shadow] upstream-import failed`)}}})}catch(e){J.error({err:e},`[server] HEAD watcher failed to start`),jt.push(`head-watcher`)}let w=H?.[0]??`open-knowledge`,E=[`-c`,`credential.helper=!${H&&H.length>1?H.join(` `):w} auth git-credential`];try{vt=new SyncEngine({projectDir:s,contentDir:t,contentFilter:oe,contentRoot:L,syncEnabled:Y(),credentialArgs:E,cc1Broadcaster:ge,setBatchInProgress:e=>{setBatchInProgress(e),e||de.flushDeferredStores(`within-branch`).catch(e=>{J.error({err:e},`[persistence] deferred store drain failed after sync batch`)})},onStateChange:e=>{J.info({state:e},`[sync] state → ${e}`)},onAutoDisable:async e=>{J.warn({reason:e},`[sync] auto-disabled — persisting to project-local config`);let t=await writeConfigPatch({cwd:s,scope:`project-local`,patch:{autoSync:{enabled:!1}}});t.ok||J.error({result:t,reason:e,humanError:humanFormat(t.error),configPath:resolveConfigPath(`project-local`,s)},`[sync] failed to persist auto-disable — next restart WILL re-enable sync and re-trigger the same failure. Check permissions on the config path.`)}}),await vt.start()}catch(e){J.warn({err:e},`[server] SyncEngine failed to start — sync disabled`),vt=null}}let Ft=Mt();return{hocuspocus:fe,sessionManager:me,cc1Broadcaster:ge,agentFocusBroadcaster:_e,agentPresenceBroadcaster:ve,contentFilter:oe,basenameIndex:ne,serverInstanceId:ee,destroy:Dt,ready:Ft,degraded:jt,lockDir:te,get syncEngine(){return vt}}}const LEGACY_RUNTIME_FILENAMES=[`server.lock`,`ui.lock`,`state.json`,`principal.json`,`sync-state.json`,`conflicts.json`,`last-spawn-error.log`],LEGACY_RUNTIME_DIRNAMES=[`cache`,`tmp`];function findLegacyRuntimeFiles(e){let t=resolve(e,LOCAL_DIR);if(!(()=>{if(!existsSync(t))return!0;try{return readdirSync(t).length===0}catch{return!0}})())return[];let s=[];for(let t of LEGACY_RUNTIME_FILENAMES)existsSync(resolve(e,t))&&s.push(t);for(let t of LEGACY_RUNTIME_DIRNAMES){let g=resolve(e,t);try{existsSync(g)&&statSync(g).isDirectory()&&s.push(`${t}/`)}catch{}}return s}function computeWorktreeAttributes(e){let t=resolveGitDirDetailed(e);switch(t.kind){case`directory`:return{kind:`main`,gitdir:t.path};case`linked`:return{kind:`linked`,gitdir:t.path};case`malformed-pointer`:return{kind:`linked`,gitdir:null};case`inaccessible`:case`absent`:return{kind:`main`,gitdir:null}}}const DEFAULT_IDLE_THRESHOLD_MS=1800*1e3,DESTROY_STEP_TIMEOUT_MS=5e3;async function bootServer(e){initTelemetry();let{kind:t,gitdir:s}=computeWorktreeAttributes(e.projectDir??e.contentDir),g={"ok.worktree.kind":t};return s!==null&&(g[`ok.worktree.gitdir`]=normalizeFsPath(s)),withSpan(`ok.boot`,{attributes:g},async()=>bootServerInner(e))}async function bootServerInner(e){let t=e.skipAutoInit??!1,s=e.attachUiSibling??!0,g=e.idleShutdownMs,S=e.log??getLogger(`boot`),w=process.env.OK_LOCK_KIND===`mcp-spawned`||process.env.OK_LOCK_KIND===`interactive`?process.env.OK_LOCK_KIND:void 0,E=e.lockKind??w??`interactive`,{createServer:D}=await import(`node:http`),{updateServerLockPort:O}=await import(`./server-lock-D7DXNVql-B5nINglj.mjs`).then(e=>e.a),k=!1;if(!t&&e.autoInitFn)try{k=!!await e.autoInitFn()}catch(e){S.warn({err:e},`autoInitFn failed`)}let j=e.projectDir??e.contentDir,F=resolve(j,`.ok`);if(!existsSync(resolve(F,`config.yml`)))throw new MissingOkConfigError(existsSync(F)?`config`:`okdir`,j);existsSync(resolve(F,`.gitignore`))||console.warn("[boot] Note: .ok/.gitignore is missing — per-machine state files in .ok/ may show up as untracked changes. Run `ok init` to add the recommended ignore entries.");let L=findLegacyRuntimeFiles(F);L.length>0&&console.warn(`[boot] Found legacy runtime files at .ok/${L.join(`, `)}. Delete .ok/ and re-init — these files moved to .ok/${LOCAL_DIR}/.`);let B=createServer$1({contentDir:e.contentDir,projectDir:e.projectDir,contentRoot:e.contentRoot,port:e.port,host:e.host,quiet:e.quiet??!1,debounce:e.debounce,maxDebounce:e.maxDebounce,gitEnabled:e.gitEnabled,commitDebounceMs:e.commitDebounceMs,wipRef:e.wipRef,enableTestRoutes:e.enableTestRoutes,shadowRepo:e.shadowRepo,destroyTimeoutMs:e.destroyTimeoutMs,localOpCliArgs:e.localOpCliArgs,onAgentWrite:e.onAgentWrite,lockKind:E,skipStateManifestCheck:e.skipStateManifestCheck}),{hocuspocus:H,destroy:q,ready:J,degraded:Y,lockDir:ee,sessionManager:te,agentFocusBroadcaster:ne,agentPresenceBroadcaster:ae}=B,oe=(()=>{let t=e.host??`localhost`;return t===`0.0.0.0`||t===`::`?`localhost`:t.includes(`:`)&&!t.startsWith(`[`)?`[${t}]`:t})(),se=e.port??0,ce=createMcpHttpHandler({contentDir:e.contentDir,projectDir:e.projectDir??e.contentDir,config:e.config,getServerUrl:()=>`http://${oe}:${se}`,log:S}),ue=D(),de=mountMcpAndApi({httpServer:ue,hocuspocus:H,mcpHttpHandler:ce,log:S,sessionManager:te,agentFocusBroadcaster:ne,agentPresenceBroadcaster:ae,keepaliveGraceMs:e.keepaliveGraceMs}),fe=null;g!==null&&(fe=attachIdleShutdown({httpServer:ue,thresholdMs:g??DEFAULT_IDLE_THRESHOLD_MS,log:S,onShutdown:(e.idleShutdownHandler??(e=>async()=>{await e()}))(async()=>{await q()})})),await new Promise((t,s)=>{let g=e=>s(e);ue.once(`error`,g),ue.listen(e.port,e.host,()=>{ue.removeListener(`error`,g),t()})});let me=ue.address(),ge=typeof me==`object`&&me?me.port:e.port??0;if(se=ge,O(ee,ge),s&&e.spawnUiSiblingFn)try{await e.spawnUiSiblingFn({lockDir:ee,log:S})}catch(e){S.warn({err:e},`spawnUiSiblingFn failed`)}let _e=!1,ve=async(e,t)=>{let s;try{await Promise.race([t(),new Promise((t,g)=>{s=setTimeout(()=>{g(Error(`${e} timed out after ${DESTROY_STEP_TIMEOUT_MS}ms`))},DESTROY_STEP_TIMEOUT_MS),s.unref?.()})])}finally{s!==void 0&&clearTimeout(s)}};return{httpServer:ue,destroy:async()=>{if(_e)return;_e=!0;let e=[],t=async(t,s)=>{try{await ve(t,s)}catch(s){e.push(s),S.warn({err:s,step:t},`bootServer destroy step failed`)}};try{fe?.detach()}catch(t){e.push(t),S.warn({err:t,step:`idleHandle.detach`},`bootServer destroy step failed`)}if(await t(`mount.shutdown`,()=>de.shutdown()),await t(`mcpHttpHandler.close`,()=>ce.close()),await t(`mount.wss.close`,()=>new Promise((e,t)=>{de.wss.close(s=>s?t(s):e())})),await t(`httpServer.closeAllConnections`,async()=>{ue.closeAllConnections?.()}),await t(`httpServer.close`,()=>new Promise((e,t)=>{ue.close(s=>s&&s.code!==`ERR_SERVER_NOT_RUNNING`?t(s):e())})),await t(`destroyHocuspocus`,()=>q()),await t(`shutdownTelemetry`,()=>shutdownTelemetry()),e.length>0)throw AggregateError(e,`bootServer destroy completed with errors`)},lockDir:ee,contentDir:e.contentDir,port:ge,ready:J,degraded:Y,didAutoInit:k,serverInstance:B}}const ConfigSchema=ConfigSchema$1;function detectClaudeDesktopPresence(e={}){let t=e.home??homedir(),s=e.platformName??process.platform,g=e.env??process.env;return s===`darwin`?existsSync(join(t,`Library`,`Application Support`,`Claude`)):s===`win32`?existsSync(join(g.APPDATA??join(t,`AppData`,`Roaming`),`Claude`)):!1}const execFileAsync=promisify(execFile);var ProjectGitInitError=class extends Error{stderr;constructor(e,t=``,s){super(e,s),this.name=`ProjectGitInitError`,this.stderr=t}};async function isInsideExistingWorkTree(e){try{let{stdout:t}=await execFileAsync(`git`,[`rev-parse`,`--is-inside-work-tree`],{cwd:e});return t.trim()===`true`}catch{return!1}}async function ensureProjectGit(e){let t=resolve(e),s=resolve(t,`.git`);if(existsSync(s)||await isInsideExistingWorkTree(t))return{didInit:!1};let g=``;try{g=(await execFileAsync(`git`,[`init`,`--initial-branch=main`,t])).stderr??``}catch(e){let s=typeof e==`object`&&e&&`stderr`in e?String(e.stderr??``):``;throw new ProjectGitInitError(`git init failed at ${t}: ${e instanceof Error?e.message:String(e)}`,s,{cause:e})}if(!existsSync(resolve(s,`HEAD`)))throw new ProjectGitInitError(`git init reported success but ${s}/HEAD is missing (partial init detected)`,g);return console.log(`[project-git] initialized .git/ at ${t} (branch: main)`),{didInit:!0}}async function resolvePackageVersion(e,t){let s;try{s=createRequire(t).resolve(e)}catch(e){if(e?.code===`MODULE_NOT_FOUND`)return;throw e}for(let t=dirname(s),g=0;g<32;g+=1){let s=join(t,`package.json`);if(existsSync(s))try{let t=JSON.parse(await readFile$1(s,`utf-8`));if(t.name===e&&typeof t.version==`string`)return t.version}catch{}let g=dirname(t);if(g===t)return;t=g}}export{buildAndOpenSkill as $,validateCloneInputs as $n,isSelfWrite as $t,OBSERVER_SYNC_ORIGIN as A,resolvePackageVersion as An,formatContributors as At,SeedPrerequisiteError as B,safetyCheckpoint as Bn,incrementCollabSocketFilteredError as Bt,MANAGED_RENAME_ORIGIN as C,removeLastKnownHash as Cn,createServerObserverExtension as Ct,MISSING_OK_CONFIG_MESSAGE as D,resolveCursorBinaryDefault as Dn,ensureProjectGit as Dt,MCP_SERVER_NAME as E,resolveContentDir as En,detectProjectShape as Et,SKILL_INSTALL_EVENTS_FILE_REL as F,runCloneSubprocess as Fn,getMeter as Ft,acquireUiLock as G,shadowGit as Gn,installUserSkill as Gt,StateManifestError as H,saveVersion as Hn,initShadowRepo as Ht,STARTER_FOLDERS as I,runDeviceFlowSubprocess as In,getMetrics as It,applySeed as J,startWatcher as Jn,isConfigDoc as Jt,applyAgentMarkdownWrite as K,shutdownTelemetry as Kn,isAllowedApiOrigin as Kt,STARTER_FOLDER_FRONTMATTER_FILENAME as L,runWithMcpLogger as Ln,getTracer as Lt,ProjectGitInitError as M,rewriteWikiLinksForDocumentRename as Mn,getCurrentMcpLogger as Mt,ROLLBACK_ORIGIN as N,runAuthReposSubprocess as Nn,getLocalDir as Nt,McpLogger as O,resolveCursorSpawnInvocation as On,evictStaleTrackerEntries as Ot,SERVICE_WRITER as P,runAuthStatusSubprocess as Pn,getLogger as Pt,bootServer as Q,validateAgentId as Qn,isPathWithinDir as Qt,STARTER_TEMPLATES as R,safeContentPath as Rn,handleCollabSocketError as Rt,LOG_MD_TEMPLATE as S,releaseUiLock as Sn,createServer$1 as St,MCP_CONNECTION_ID_HEADER as T,resolveBundledSkillDir as Tn,detectClaudeDesktopPresence as Tt,TagIndex as U,seedBasenameIndex as Un,initTelemetry as Ut,SeedRootDirError as V,saveInMemoryCheckpoint as Vn,incrementServerObserverFire as Vt,UiLockCollisionError as W,setActiveSpanAttributes as Wn,installTestLoggers as Wt,assertNeverDiskEvent as X,updateLastKnownHash as Xn,isLoopbackAddress as Xt,assertCompatibleStateManifest as Y,toBroadcasterKey as Yn,isHocuspocusAuthRejectionReason as Yt,attachIdleShutdown as Z,updateUiLockPort as Zn,isPairedWriteOrigin as Zt,HOCUSPOCUS_AUTH_REJECTION_REASONS as _,readUiLock as _n,createExternalChangeHandler as _t,AgentPresenceBroadcaster as a,mountMcpAndApi as an,writeTracker as ar,classifyEvents as at,INSTALLED_AGENTS_SCHEMES as b,recordSkillInstallEvent as bn,createOsProbe as bt,BacklinkIndex as c,pathToDocName as cn,isInitializedNotification as cr,commitWip as ct,CURSOR_BUNDLE_PATHS_BY_PLATFORM as d,readBranchFromHead as dn,readConfigSafely as dr,contentHash as dt,isSystemDoc as en,validateSkillZip as er,buildExecResult as et,ConfigSchema as f,readServerPackageVersion as fn,resolveConfigPath as fr,contributorCount as ft,GIT_UPSTREAM_WRITER as g,readTargetVersion as gn,createContentFilterAsync as gt,FILE_WATCHER_ORIGIN as h,readTargetRecordedAt as hn,MalformedGitPointerError as hr,createContentFilter as ht,AgentFocusBroadcaster as i,loggerFactory as in,writeTargetVersion as ir,buildWipTree as it,PinoLogger as j,rewriteMarkdownLinksForDocumentRename as jn,gcCheckpointRefs as jt,MissingOkConfigError as k,resolveLockDir as kn,extractWikiLinksFromMarkdown as kt,CC1Broadcaster as l,planSeed as ln,isJSONRPCRequest as lr,commitWipFromTree as lt,FILE_SYSTEM_WRITER as m,readStateManifest as mn,GitDirAccessError as mr,createAssetServeMiddleware as mt,AGENT_ID_RE as n,listRescueCheckpoints as nn,withSpanSync as nr,buildSkillZip as nt,AgentSessionCapacityError as o,parseHocuspocusAuthToken as on,JSONRPCMessageSchema as or,clearContributors as ot,DEFAULT_CHECKPOINT_RETENTION as p,readSkillInstallStateSnapshot as pn,writeConfigPatch as pr,createApiExtension as pt,applyExternalChange as q,splitMarkdownBlocks as qn,isAllowedWorkspaceHostHeader as qt,AGENT_WRITE_ORIGIN as r,loadPrincipal as rn,writeStateManifest as rr,buildStarterFolderFrontmatterYaml as rt,AgentSessionManager as s,parseKeepaliveConnectionId as sn,LATEST_PROTOCOL_VERSION as sr,commitUpstreamImport as st,AGENT_ID_MAX_LEN as t,lastKnownHash as tn,withSpan as tr,buildReadResult as tt,CONFLICT_MARKER_RE as u,readAllTargets as un,isJSONRPCResultResponse as ur,containsConflictMarkers as ut,HocuspocusAuthRejection as v,reconcile as vn,createLiveDerivedIndexExtension as vt,MAX_AGENT_SESSIONS as w,resetMetrics as wn,createTestLogger as wt,LIVE_DERIVED_INDEX_DEBOUNCE_MS as x,registerWrite as xn,createPersistenceExtension as xt,HocuspocusAuthTokenSchema as y,recordContributor as yn,createMcpHttpHandler as yt,STATE_MANIFEST_FILENAME as z,safeSubdir as zn,handleSpawnCursor as zt};
|
|
1621
|
+
//# sourceMappingURL=dist-RAy2NfOX.mjs.map
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as e,d as t,i as n,l as r,s as i,t as a,u as o}from"./init-
|
|
1
|
+
import{c as e,d as t,i as n,l as r,s as i,t as a,u as o}from"./init-qh1HubtR.mjs";import{t as s}from"./loader-DMES5Z4K.mjs";import"./src-D0mZ2vS1.mjs";export{r as ALL_EDITOR_IDS,o as EDITOR_TARGETS,a as detectInstalledEditors,t as initContent,s as loadConfig,n as readExistingMcpEntry,i as writeEditorMcpConfig,e as writeUserMcpConfigs};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{o as e}from"./init-qh1HubtR.mjs";export{e as runInit};
|