@inkeep/open-knowledge 0.9.0-beta.15 → 0.9.0-beta.16

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.
Files changed (39) hide show
  1. package/dist/assets/skills/discovery/SKILL.md +1 -1
  2. package/dist/assets/skills/project/SKILL.md +3 -3
  3. package/dist/cli.mjs +21 -21
  4. package/dist/constants-BrsDfgAF.mjs +2 -0
  5. package/dist/dist-BO9a8zPl.mjs +1 -0
  6. package/dist/{dist-DKgq69uI.mjs → dist-eWWovL1R.mjs} +5 -5
  7. package/dist/index.mjs +1 -1
  8. package/dist/init-Bv86j4qK.mjs +1 -0
  9. package/dist/init-C65xzxs_.mjs +281 -0
  10. package/dist/{loader-Kl4WTX1f.mjs → loader-CYrZw2xs.mjs} +2 -2
  11. package/dist/loader-Cc6X8AiE.mjs +1 -0
  12. package/dist/preview-D1L8os3m.mjs +1 -0
  13. package/dist/{preview-BeyH-UEE.mjs → preview-DrBr_hFy.mjs} +2 -2
  14. package/dist/public/assets/{ActivityModeContent-BTXnBQZu.js → ActivityModeContent-DZuWquln.js} +1 -1
  15. package/dist/public/assets/{DocumentContext-Dc7iRIl7.js → DocumentContext-Dxan0ulz.js} +2 -2
  16. package/dist/public/assets/{SettingsDialogBody-D_TZUnbh.js → SettingsDialogBody-D6_VytdC.js} +2 -2
  17. package/dist/public/assets/{SourceEditor-CY0-BmEV.js → SourceEditor-BurQPyPf.js} +2 -2
  18. package/dist/public/assets/{config-validation-events-tCaPOuUE.js → config-validation-events-D1a8eR7j.js} +5 -5
  19. package/dist/public/assets/index-nTUe-U2N.js +1914 -0
  20. package/dist/public/assets/{typing-burst-detector-Couz3KO5.js → typing-burst-detector-BY1B6_tL.js} +2 -2
  21. package/dist/public/index.html +4 -4
  22. package/dist/{repair-launch-json-CFr8rkTn.mjs → repair-launch-json-CrR6leuM.mjs} +2 -2
  23. package/dist/{repair-mcp-configs-B5ZX9sla.mjs → repair-mcp-configs-Bw1jWfGY.mjs} +2 -2
  24. package/dist/repair-skills-DjdnsgMp.mjs +1 -0
  25. package/dist/{repair-skills-D2S7rOZx.mjs → repair-skills-PmgRAebo.mjs} +2 -2
  26. package/dist/{src-CqKV9RHO.mjs → src-DXQs_Tkb.mjs} +2 -2
  27. package/dist/start-3dXByph1.mjs +1 -0
  28. package/dist/{start-0hrhk1O7.mjs → start-CCU7nFR1.mjs} +2 -2
  29. package/dist/{write-project-skill-BQGm1G4f.mjs → write-project-skill-B5IcYKkU.mjs} +2 -2
  30. package/package.json +1 -1
  31. package/dist/constants-0K-IjaEA.mjs +0 -2
  32. package/dist/dist-D-rWIekL.mjs +0 -1
  33. package/dist/init-DoNyAjRX.mjs +0 -1
  34. package/dist/init-htUcoMvf.mjs +0 -281
  35. package/dist/loader-zqrX35Oi.mjs +0 -1
  36. package/dist/preview-CcFDoic9.mjs +0 -1
  37. package/dist/public/assets/index-Da6BYW3D.js +0 -1914
  38. package/dist/repair-skills-BimjofqV.mjs +0 -1
  39. package/dist/start-CRDIbOn9.mjs +0 -1
@@ -0,0 +1 @@
1
+ import{Br as e,Cn as t,K as n,Wr as r,a as i,an as a,bn as o,c as s,d as c,f as l,g as u,h as d,i as f,l as p,ln 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,yr as C}from"./server-lock-BpjJj3OD-B9uBbH7Z.mjs";import{$ as w,$n as T,$r as E,$t as D,A as O,An as k,Ar as A,At as j,B as M,Bn as N,Br as P,Bt as F,C as I,Cn as L,Cr as R,Ct as z,D as B,Dn as V,Dr as H,Dt as U,E as W,En as G,Er as K,Et as q,F as J,Fn as Y,Fr as X,Ft as Z,G as Q,Gn as $,Gr as ee,Gt as te,H as ne,Hn as re,Hr as ie,Ht as ae,I as oe,In as se,Ir as ce,It as le,J as ue,Jn as de,Jr as fe,Jt as pe,K as me,Kn as he,Kr as ge,Kt as _e,L as ve,Ln as ye,Lr as be,Lt as xe,M as Se,Mn as Ce,Mr as we,Mt as Te,N as Ee,Nn as De,Nr as Oe,Nt as ke,O as Ae,Oi as je,On as Me,Or as Ne,Ot as Pe,P as Fe,Pn as Ie,Pr as Le,Pt as Re,Q as ze,Qn as Be,Qr as Ve,Qt as He,R as Ue,Rn as We,Rr as Ge,Rt as Ke,S as qe,Sn as Je,Sr as Ye,St as Xe,T as Ze,Tn as Qe,Tr as $e,Tt as et,U as tt,Un as nt,Ur as rt,Ut as it,V as at,Vn as ot,Vr as st,Vt as ct,W as lt,Wn as ut,Wr as dt,Wt as ft,X as pt,Xn as mt,Xr as ht,Xt as gt,Y as _t,Yn as vt,Yr as yt,Yt as bt,Z as xt,Zn as St,Zr as Ct,Zt as wt,_ as Tt,_n as Et,_r as Dt,_t as Ot,a as kt,ai as At,an as jt,ar as Mt,at as Nt,b as Pt,bn as Ft,br as It,bt as Lt,c as Rt,ci as zt,cn as Bt,cr as Vt,ct as Ht,d as Ut,di as Wt,dn as Gt,dr as Kt,dt as qt,ei as Jt,en as Yt,er as Xt,et as Zt,f as Qt,fi as $t,fn as en,fr as tn,ft as nn,g as rn,gi as an,gn as on,gr as sn,gt as cn,h as ln,hi as un,hn as dn,hr as fn,ht as pn,i as mn,ii as hn,in as gn,ir as _n,it as vn,j as yn,jn as bn,jr as xn,jt as Sn,k as Cn,ki as wn,kn as Tn,kr as En,kt as Dn,l as On,li as kn,ln as An,lr as jn,lt as Mn,m as Nn,mi as Pn,mn as Fn,mr as In,mt as Ln,n as Rn,ni as zn,nn as Bn,nr as Vn,nt as Hn,o as Un,oi as Wn,on as Gn,or as Kn,ot as qn,p as Jn,pi as Yn,pn as Xn,pr as Zn,pt as Qn,q as $n,qn as er,qr as tr,qt as nr,r as rr,ri as ir,rn as ar,rr as or,rt as sr,s as cr,si as lr,sn as ur,sr as dr,st as fr,t as pr,ti as mr,tn as hr,tr as gr,tt as _r,u as vr,ui as yr,un as br,ur as xr,ut as Sr,v as Cr,vn as wr,vr as Tr,vt as Er,w as Dr,wn as Or,wr as kr,wt as Ar,x as jr,xn as Mr,xr as Nr,xt as Pr,y as Fr,yn as Ir,yr as Lr,yt as Rr,z as zr,zn as Br,zr as Vr,zt as Hr}from"./dist-eWWovL1R.mjs";export{pr as AGENT_ID_MAX_LEN,Rn as AGENT_ID_RE,rr as AGENT_WRITE_ORIGIN,mn as AgentFocusBroadcaster,kt as AgentPresenceBroadcaster,Un as AgentSessionCapacityError,cr as AgentSessionManager,Rt as BacklinkIndex,On as CC1Broadcaster,n as CC1_CONTRACT_VERSION,vr as CONFIG_FILENAME,Ut as CONFLICT_MARKER_RE,Qt as CURSOR_BUNDLE_PATHS_BY_PLATFORM,Jn as ConfigSchema,Nn as DEFAULT_CHECKPOINT_RETENTION,ln as DEFAULT_PACK_ID,rn as FILE_SYSTEM_WRITER,Tt as FILE_WATCHER_ORIGIN,Cr as GIT_PREFLIGHT_FAIL_SPAN_NAME,Fr as GIT_UPSTREAM_WRITER,je as GitDirAccessError,Pt as GitNotAvailableError,jr as GitTooOldError,qe as HOCUSPOCUS_AUTH_REJECTION_REASONS,I as HocuspocusAuthRejection,Dr as HocuspocusAuthTokenSchema,Ze as INSTALLED_AGENTS_SCHEMES,W as LIVE_DERIVED_INDEX_DEBOUNCE_MS,B as LOG_MD_TEMPLATE,Ae as MANAGED_RENAME_ORIGIN,Cn as MAX_AGENT_SESSIONS,O as MCP_CONNECTION_ID_HEADER,yn as MCP_SERVER_NAME,Se as MIN_GIT_VERSION,Ee as MISSING_OK_CONFIG_MESSAGE,wn as MalformedGitPointerError,Fe as McpLogger,J as MissingOkConfigError,oe as OBSERVER_SYNC_ORIGIN,ve as OK_OKIGNORE_TEMPLATE,a as ORPHAN_MODES,Ue as PANE_TARGET_TTL_MS,m as PROTOCOL_VERSION,zr as PinoLogger,x as ProcessLockCollisionError,M as ProjectGitInitError,at as ROLLBACK_ORIGIN,ne as ROOT_GITIGNORE_TEMPLATE,g as RUNTIME_VERSION,tt as SERVICE_WRITER,lt as SKILL_INSTALL_EVENTS_FILE_REL,o as SKILL_STATE_TARGETS,Q as STARTER_FOLDERS,me as STARTER_FOLDER_FRONTMATTER_FILENAME,$n as STARTER_PACKS,ue as STARTER_PACK_IDS,_t as STARTER_TEMPLATES,pt as STATE_MANIFEST_FILENAME,y as STATE_SCHEMA_VERSION,t as SYSTEM_DOC_NAME,xt as SeedPrerequisiteError,ze as SeedRootDirError,f as ServerLockCollisionError,w as StateManifestError,Zt as TagIndex,_r as UiLockCollisionError,i as acquireProcessLock,_ as acquireServerLock,Hn as acquireUiLock,sr as applyAgentMarkdownWrite,vn as applyExternalChange,Nt as applySeed,qn as armPaneTarget,fr as assertCompatibleStateManifest,Ht as assertGitAvailable,Mn as assertNeverDiskEvent,Sr as attachIdleShutdown,qt as bootServer,nn as buildAndOpenSkill,Qn as buildConfigYmlContent,Ln as buildExecResult,pn as buildInstructions,cn as buildSkillZip,Ot as buildStarterFolderFrontmatterYaml,Er as buildWipTree,Rr as classifyEvents,Lt as classifyFsPath,Pr as clearArmedPaneTarget,Xe as clearContributors,z as coercePackId,C as colorFromSeed,Ar as commitUpstreamImport,et as commitWip,q as commitWipFromTree,U as compareSemver,Pe as containsConflictMarkers,Dn as contentHash,j as contributorCount,Sn as createApiExtension,Te as createAssetServeMiddleware,ke as createContentFilter,Re as createContentFilterAsync,Z as createExternalChangeHandler,le as createFileLogger,xe as createLiveDerivedIndexExtension,Ke as createMcpHttpHandler,Hr as createOsProbe,F as createPersistenceExtension,ct as createServer,ae as createServerObserverExtension,it as createStreamingErrorWriter,ft as createTestLogger,te as detectClaudeDesktopPresence,_e as detectGit,nr as detectProjectShape,pe as emitPreflightFailureSpan,bt as ensureProjectGit,gt as errorResponse,wt as evictStaleTrackerEntries,He as extractWikiLinksFromMarkdown,D as fallbackPaths,Yt as findEnclosingGitRoot,hr as findEnclosingProjectRoot,Bn as formatAuthRejectionWire,ar as formatContributors,gn as formatContributorsFrom,jt as gcCheckpointRefs,Gn as getCurrentMcpLogger,ur as getLocalDir,Bt as getLogFilePath,An as getLogger,br as getLogsDir,Gt as getMeter,en as getMetrics,Xn as getTracer,Fn as handleCollabSocketError,dn as handleSpawnCursor,e as iconFromClientName,on as incrementCollabSocketFilteredError,Et as incrementServerObserverFire,wr as initContent,Ir as initShadowRepo,Ft as initTelemetry,Mr as installPrettyZodErrors,Je as installTestLoggers,L as installUserSkill,Or as isAllowedApiOrigin,Qe as isAllowedWorkspaceHostHeader,G as isConfigDoc,V as isHocuspocusAuthRejectionReason,Me as isKnownPackId,Tn as isLoopbackAddress,r as isOrphanMode,k as isPairedWriteOrigin,bn as isPathWithinDir,b as isProcessAlive,Ce as isProjectRoot,De as isSelfWrite,Ie as isSystemDoc,s as isValidLockPid,Y as lastKnownHash,se as listRescueCheckpoints,ye as listStarterPacks,We as loadPrincipal,p as lockFilePath,Br as loggerFactory,N as logsCurrentPath,ot as logsPreviousPath,re as mountMcpAndApi,nt as normalizeFsPath,ut as packageVersionMajorMinor,$ as parseAuthRejectionWire,he as parseGitVersion,er as parseHocuspocusAuthToken,de as parseKeepaliveConnectionId,vt as pathToDocName,mt as planSeed,St as readAllTargets,Be as readArmedPaneTarget,T as readBranchFromHead,S as readProcessLock,c as readProcessLockDetailed,l as readServerLock,Xt as readServerPackageVersion,gr as readSkillInstallStateSnapshot,Vn as readStateManifest,or as readTargetRecordedAt,_n as readTargetVersion,Mt as readUiLock,Kn as reconcile,dr as recordContributor,Vt as recordSkillInstallEvent,jn as registerAllTools,xr as registerWrite,v as releaseProcessLock,h as releaseServerLock,Kt as releaseUiLock,tn as removeLastKnownHash,Zn as resetMetrics,In as resolveBundledSkillDir,fn as resolveContentDir,sn as resolveCursorBinaryDefault,Dt as resolveCursorSpawnInvocation,Tr as resolveLockDir,Lr as resolvePack,It as resolvePackageVersion,Nr as restoreContributors,Ye as restoreLifecycleFromConflictsJson,R as rewriteMarkdownLinksForDocumentRename,kr as rewriteWikiLinksForDocumentRename,$e as runAuthReposSubprocess,K as runAuthStatusSubprocess,H as runCloneSubprocess,Ne as runDeviceFlowSubprocess,En as runWithMcpLogger,A as safeContentPath,xn as safeSubdir,we as safetyCheckpoint,Oe as sanitizeClientName,Le as saveInMemoryCheckpoint,X as saveVersion,ce as seedBasenameIndex,be as serializeError,Ge as setActiveSpanAttributes,Vr as shadowGit,P as shutdownTelemetry,st as spansCurrentPath,ie as spansPreviousPath,rt as spawnDetached,dt as splitMarkdownBlocks,ee as startWatcher,ge as streamingProblemEvent,tr as swapContributors,fe as toBroadcasterKey,yt as tracedAppendFileSync,ht as tracedLinkSync,Ct as tracedMkdir,Ve as tracedMkdirSync,E as tracedRename,Jt as tracedRenameSync,mr as tracedRmSync,zn as tracedRmdirSync,ir as tracedUnlinkSync,hn as tracedWriteFile,At as tracedWriteFileSync,Wn as updateLastKnownHash,d as updateProcessLockPort,u as updateServerLockPort,lr as updateUiLockPort,zt as validateAgentId,kn as validateCloneInputs,yr as validateSkillZip,Wt as withSpan,$t as withSpanSync,Yn as writeRootGitignoreForNewRepo,Pn as writeStateManifest,un as writeTargetVersion,an as writeTracker};
@@ -1955,7 +1955,7 @@ description: When the agent does scheduled work: daily briefings, end-of-day dos
1955
1955
  `).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?successResponse(t,200,LocalOpAuthPatSuccessSchema,{},{handler:Vc}):successResponse(t,200,LocalOpAuthPatSuccessSchema,D,{handler:Vc})}catch(e){errorResponse(t,500,`urn:ok:error:auth-failed`,`Auth pat failed.`,{handler:Vc,cause:e})}finally{Ce.release(kc)}},{handler:Vc,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:Vc})}),Uc=`local-op-auth-identity`;async function Wc(e,t){if(checkLocalOpSecurity(e,t,{handler:Uc})){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:Uc,extraHeaders:{Allow:`GET`}});return}if(!ue){errorResponse(t,503,`urn:ok:error:no-project-dir`,`No project directory configured.`,{handler:Uc});return}try{successResponse(t,200,LocalOpAuthIdentitySuccessSchema,{identity:await resolveGitIdentity(ue)},{handler:Uc})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Identity resolution failed.`,{handler:Uc,cause:e})}}}let Gc=`/api/local-op/auth/set-identity`,Kc=`local-op-auth-set-identity`,qc=withValidation(LocalOpAuthSetIdentityRequestSchema,async(e,t,s)=>{let g=s.name.trim(),S=s.email.trim();if(!ue){errorResponse(t,503,`urn:ok:error:no-project-dir`,`No project directory configured.`,{handler:Kc});return}if(!Ce.tryAcquire(Gc)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A set-identity operation is already in progress.`,{handler:Kc,extraHeaders:{"Retry-After":`5`}});return}try{writeGitIdentity(ue,g,S),se?.()?.refreshIdentity().catch(()=>{}),successResponse(t,200,LocalOpAuthEmptySuccessSchema,{},{handler:Kc})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Set-identity failed.`,{handler:Kc,cause:e})}finally{Ce.release(Gc)}},{handler:Kc,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:Kc})});async function Jc(e,t){if(checkLocalOpSecurity(e,t,{handler:`sync-status`})){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`sync-status`,extraHeaders:{Allow:`GET`}});return}try{let e=se?.();if(!e){successResponse(t,200,SyncStatusSchema,{state:`dormant`,lastSyncUtc:null,lastFetchUtc:null,lastPushedSha:null,ahead:0,behind:0,consecutiveFailures:0,conflictCount:0,hasRemote:!1,syncEnabled:!1,identityUnresolved:!1,remote:null},{handler:`sync-status`});return}await e.refreshRemote(),successResponse(t,200,SyncStatusSchema,e.getStatus(),{handler:`sync-status`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`sync-status`,cause:e})}}}let Yc=withValidation(SyncTriggerRequestSchema,async(e,t,s)=>{let g=se?.();if(!g){errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-trigger`});return}let S=s.op??`sync`;successResponse(t,202,SyncTriggerSuccessSchema,{op:S},{handler:`sync-trigger`}),g.trigger(S)},{handler:`sync-trigger`,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`sync-trigger`})?se?.()?!0:(errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-trigger`}),!1):!1});async function Xc(e,t){if(checkLocalOpSecurity(e,t,{handler:`sync-conflicts`})){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`sync-conflicts`,extraHeaders:{Allow:`GET`}});return}try{let e=se?.();successResponse(t,200,SyncConflictsSuccessSchema,{conflicts:e?e.getConflicts():[]},{handler:`sync-conflicts`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`sync-conflicts`,cause:e})}}}let Zc=withValidation(SyncResolveConflictRequestSchema,async(e,t,s)=>{let g=se?.();if(!g){errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-resolve-conflict`});return}let{file:S,strategy:w,content:E}=s;try{await g.resolveConflict(S,w,E),successResponse(t,200,SyncResolveConflictSuccessSchema,{},{handler:`sync-resolve-conflict`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to resolve conflict.`,{handler:`sync-resolve-conflict`,cause:e,detail:e instanceof Error?e.message:void 0})}},{handler:`sync-resolve-conflict`,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`sync-resolve-conflict`})?se?.()?!0:(errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-resolve-conflict`}),!1):!1});async function Qc(e,s){if(!checkLocalOpSecurity(e,s,{handler:`sync-conflict-content`}))return;if(e.method!==`GET`){errorResponse(s,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`sync-conflict-content`,extraHeaders:{Allow:`GET`}});return}if(!ue){errorResponse(s,503,`urn:ok:error:project-repo-not-configured`,`Project repo not configured.`,{handler:`sync-conflict-content`});return}let g=new URL(e.url??`/`,`http://${e.headers.host??`localhost`}`),S=g.searchParams.get(`file`);if(!S){errorResponse(s,400,`urn:ok:error:invalid-request`,`Missing required query param: file.`,{handler:`sync-conflict-content`});return}if(S.includes(`..`)||S.startsWith(`/`)){errorResponse(s,400,`urn:ok:error:invalid-request`,`Invalid file path.`,{handler:`sync-conflict-content`});return}let w=stripDocExtension(S),E=t.documents.get(w)?.getMap(`lifecycle`).get(`status`)===`conflict`,D=se?.(),O=D?D.getConflicts().some(e=>e.file===S):!1;if(!E&&!O){errorResponse(s,404,`urn:ok:error:no-conflict-tracked`,`No conflict is tracked for this path.`,{handler:`sync-conflict-content`,extensions:{file:S}});return}let k=g.searchParams.get(`source`),j=esm_default({baseDir:ue,timeout:{block:15e3}});async function F(e){try{return{present:!0,content:await j.raw([`show`,`:${e}:${S}`])}}catch(t){let s=t instanceof Error?t.message:String(t);if(!/pathspec|did not match|exists on disk, but not in|is in the index, but not at stage/i.test(s))throw console.warn(JSON.stringify({event:`showstage-unexpected-error`,stage:e,file:S,detail:s,handler:`sync-conflict-content`})),t;return{present:!1}}}try{let[e,g,w]=await Promise.all([F(1),F(2),F(3)]),E=e.present?e.content:``,D=w.present?w.content:``,O=g.present&&w.present?`both-modified`:!g.present&&w.present?`delete-modify`:g.present&&!w.present?`modify-delete`:`both-modified`,j=g.present?g.content:``,L=null;if(k===`ytext`){let e=stripDocExtension(S),s=t.documents.get(e);if(s){let t=s.getMap(`lifecycle`).get(`status`);if(L=typeof t==`string`&&t.length>0?t:null,O!==`delete-modify`){let t=ye?ye(e):null;t!==null&&!ytextHasConflictMarkers(t)?j=t:t!==null&&console.warn(JSON.stringify({event:`ytext-conflict-marker-detected`,"doc.name":e,handler:`sync-conflict-content`}))}}else console.warn(`[conflict-content] doc ${e} not loaded; lifecycleStatus unavailable`)}successResponse(s,200,SyncConflictContentSuccessSchema,{file:S,base:E,ours:j,theirs:D,kind:O,lifecycleStatus:L},{handler:`sync-conflict-content`})}catch(e){errorResponse(s,500,`urn:ok:error:internal-server-error`,`Failed to read conflict content.`,{handler:`sync-conflict-content`,cause:e})}}async function $c(e,t){if(!checkLocalOpSecurity(e,t,{handler:`seed-plan`}))return;if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`seed-plan`,extraHeaders:{Allow:`GET`}});return}let s=new URL(e.url??`/`,`http://localhost`),S=s.searchParams.get(`rootDir`)??void 0,w=s.searchParams.get(`packId`),E=coercePackId(w);if(w!==null&&w!==``&&E===void 0){errorResponse(t,400,`urn:ok:error:invalid-request`,`Unknown packId.`,{handler:`seed-plan`,detail:`Pack id "${w}" is not registered.`});return}try{successResponse(t,200,SeedPlanSuccessSchema,{plan:await planSeed({projectDir:g,rootDir:S,packId:E})},{handler:`seed-plan`})}catch(e){if(e instanceof SeedPrerequisiteError){errorResponse(t,422,`urn:ok:error:seed-prerequisite-missing`,`Seed prerequisite missing.`,{handler:`seed-plan`,cause:e});return}if(e instanceof SeedRootDirError){errorResponse(t,400,`urn:ok:error:seed-invalid-root`,`Invalid seed root directory.`,{handler:`seed-plan`,detail:`The provided root directory is not within the workspace content directory.`,cause:e});return}errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`seed-plan`,cause:e})}}let nl=withValidation(SeedApplyRequestSchema,async(e,t,s)=>{let S=s.plan;if(!S||typeof S!=`object`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid plan payload.`,{handler:`seed-apply`});return}let w=S,E=s.packId,D=coercePackId(E);if(typeof E==`string`&&E.length>0&&D===void 0){errorResponse(t,400,`urn:ok:error:invalid-request`,`Unknown packId.`,{handler:`seed-apply`,detail:`Pack id "${E}" is not registered.`});return}try{successResponse(t,200,SeedApplySuccessSchema,{result:await applySeed(w,{projectDir:g,packId:D})},{handler:`seed-apply`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to apply seed plan.`,{handler:`seed-apply`,cause:e})}},{handler:`seed-apply`,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`seed-apply`})});async function il(e,t){if(checkLocalOpSecurity(e,t,{handler:`seed-packs`})){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`seed-packs`,extraHeaders:{Allow:`GET`}});return}successResponse(t,200,SeedListPacksSuccessSchema,{packs:listStarterPacks()},{handler:`seed-packs`})}}let al=withValidation(InstallSkillRequestSchema,async(e,t,s)=>{if(s.out!==void 0&&!isSafeLocalPath(s.out)){errorResponse(t,400,`urn:ok:error:invalid-request`,`Output path must be within home directory.`,{handler:`install-skill`});return}try{successResponse(t,200,InstallSkillSuccessSchema,await buildAndOpenSkill({...s.noOpen===void 0?{}:{noOpen:s.noOpen},...s.out===void 0?{}:{out:s.out}}),{handler:`install-skill`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to install skill.`,{handler:`install-skill`,cause:e})}},{handler:`install-skill`,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`install-skill`})});async function cl(e,t){if(checkLocalOpSecurity(e,t,{handler:`installed-agents`}))try{await handleInstalledAgents(e,t,ze.probeAll)}catch(e){t.headersSent||(log$4.error({err:e},`[installed-agents] route wrapper failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`installed-agents`,cause:e}))}}async function ll(e,t){if(!checkLocalOpSecurity(e,t,{handler:`sync-abort-merge`}))return;if(e.method!==`POST`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`sync-abort-merge`,extraHeaders:{Allow:`POST`}});return}let s=se?.();if(!s){errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-abort-merge`});return}try{await s.abortMerge(),successResponse(t,200,SyncAbortMergeSuccessSchema,{},{handler:`sync-abort-merge`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to abort merge.`,{handler:`sync-abort-merge`,cause:e})}}let ul=withValidation(EmptyRequestSchema,async(e,t)=>{if(!ee){errorResponse(t,503,`urn:ok:error:tag-index-not-configured`,`Tag index not configured.`,{handler:`tags-list`});return}try{successResponse(t,200,TagsListSuccessSchema,{tags:ee.getAllTags()},{handler:`tags-list`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read tags.`,{handler:`tags-list`,cause:e})}},{handler:`tags-list`,method:`GET`,skipBodyParse:!0});async function dl(e,t,s){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`tags-for-name`,extraHeaders:{Allow:`GET`}});return}if(!ee){errorResponse(t,503,`urn:ok:error:tag-index-not-configured`,`Tag index not configured.`,{handler:`tags-for-name`});return}let g;try{g=decodeURIComponent(s)}catch{errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid tag name encoding.`,{handler:`tags-for-name`});return}if(!g){errorResponse(t,400,`urn:ok:error:invalid-request`,`Missing tag name.`,{handler:`tags-for-name`});return}try{let e=ee.getDocsForTagWithMatches(g).map(({docName:e,matchingTags:t})=>({docName:e,title:Ve(e),matchingTags:t,snippet:null}));successResponse(t,200,TagsForNameSuccessSchema,{name:g,docs:e},{handler:`tags-for-name`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read tag membership.`,{handler:`tags-for-name`,cause:e})}}function fl(e,t,s=`path`,S=`folder-config`){let w=e.replace(/^\.\//,``).replace(/^\/+/,``).replace(/\/+$/,``);if(w.split(`/`).some(e=>e===`..`)||e.startsWith(`/`))return errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid ${s}: must be project-root-relative.`,{handler:S}),null;let E=resolve(g),D=w===``?E:resolve(E,w);return D!==E&&!D.startsWith(`${E}${sep}`)?(errorResponse(t,400,`urn:ok:error:invalid-request`,`Path escapes content directory.`,{handler:S}),null):{folderRel:w,resolvedContentDir:E}}let pl=/^[A-Za-z0-9_-]+$/;function ml(e,t,s=`template`){return!e||!pl.test(e)?(errorResponse(t,400,`urn:ok:error:invalid-request`,"Invalid name: must be letters / digits / `_` / `-` only (no `.md` extension).",{handler:s}),!1):!0}function hl(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}function gl(e){let t={};if(!e||typeof e!=`object`||Array.isArray(e))return{patch:t,badField:null};for(let[s,g]of Object.entries(e)){if(g===void 0)continue;if(g===null){t[s]=null;continue}let e=DeclarationSchema.safeParse(g);if(!e.success)return{patch:null,badField:s};t[s]=e.data}return{patch:t,badField:null}}async function _l(e,t){if(e.method===`GET`)return vl(e,t);if(e.method===`PUT`)return yl(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`folder-config`,extraHeaders:{Allow:`GET, PUT`}})}let vl=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=fl(new URL(e.url??``,`http://localhost`).searchParams.get(`path`)??``,t,`path`,`folder-config-get`);if(!s)return;let g=await enrichDirectory(s.folderRel,{projectDir:s.resolvedContentDir}),S=resolve(s.resolvedContentDir,s.folderRel,`.ok`),w=resolve(S,`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}let D=resolveNestedFrontmatterWithSources(s.resolvedContentDir,s.folderRel),O=resolve(S,`schema.yml`),k=null;if(existsSync(O))try{let e=(0,import_dist$1.parse)(await readFile$1(O,`utf-8`)),t=FolderSchemaSchema.safeParse(e);t.success?k=t.data.declarations:(console.warn(`[ok-folder-schema] invalid shape at ${O}: ${t.error.message}`),k=null)}catch(e){let t=e instanceof Error?e.message:String(e);console.warn(`[ok-folder-schema] malformed YAML in ${O}: ${t}`),k=null}let j=Object.keys(D.declarations).length>0;successResponse(t,200,FolderConfigGetSuccessSchema,{folder:g,frontmatter_local:E,...Object.keys(D.sources).length>0?{frontmatter_sources:D.sources}:{},...j?{schema_declarations:D.declarations,schema_sources:D.declarationSources}:{},schema_local:k},{handler:`folder-config-get`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read folder config.`,{handler:`folder-config-get`,cause:e})}},{handler:`folder-config-get`,method:`GET`,skipBodyParse:!0}),yl=withValidation(FolderConfigPutRequestSchema,async(e,t,s)=>{try{let e=fl(s.path,t,`path`,`folder-config-put`);if(!e)return;let g=e.folderRel===``?`**`:`${e.folderRel}/**`,S;if(s.declarations!==void 0){let e=gl(s.declarations);if(e.patch===null){errorResponse(t,400,`urn:ok:error:invalid-request`,`Invalid declaration for field "${e.badField}": must be { type: text|number|boolean|date|list } or null.`,{handler:`folder-config-put`,detail:`INVALID_DECLARATION`});return}S=e.patch}let w=[];if(s.frontmatter!==void 0){let S=applyNestedFolderRulesUpsert({projectDir:e.resolvedContentDir,rules:[{match:g,frontmatter:hl(s.frontmatter)}]});if(!S.ok){let e=S.error.code===`WRITE_ERROR`||S.error.code===`BAD_PROJECT_DIR`?500:400;errorResponse(t,e,e===500?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,e===500?`Failed to write folder config.`:`Invalid folder config request.`,{handler:`folder-config-put`,detail:S.error.code,cause:Error(S.error.message)});return}w.push(...S.applied)}if(S!==void 0&&Object.keys(S).length>0){let s=applyNestedFolderSchemaUpsert({projectDir:e.resolvedContentDir,rules:[{match:g,declarations:S}]});if(!s.ok){let e=s.error.code===`WRITE_ERROR`||s.error.code===`BAD_PROJECT_DIR`?500:400,g=e===500?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,S=e===500?`Failed to write folder schema.`:`Invalid folder schema request.`,E=w.length>0?{partiallyApplied:w}:void 0;errorResponse(t,e,g,S,{handler:`folder-config-put`,detail:s.error.code,cause:Error(s.error.message),...E?{extensions:E}:{}});return}w.push(...s.applied)}successResponse(t,200,FolderConfigPutSuccessSchema,{applied:w},{handler:`folder-config-put`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to write folder config.`,{handler:`folder-config-put`,cause:e})}},{handler:`folder-config-put`,method:`PUT`});function xl(e,s,g,S){if(!s)return!1;let w=e===``?`.ok/templates/${s}`:`${e.replace(/\/$/,``)}/.ok/templates/${s}`,E=t.documents.get(w);return E&&isDocInConflict(E)?(respondDocInConflict(S,new DocInConflictError({file:`${w}.md`}),g),!0):!1}async function Cl(e,t){if(e.method===`GET`)return Dl(e,t);if(e.method===`PUT`)return Ol(e,t);if(e.method===`DELETE`)return kl(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`template`,extraHeaders:{Allow:`GET, PUT, DELETE`}})}let Tl=/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/,El=e=>{let t=e.match(Tl),s={},g=e;if(t){try{let e=(0,import_dist$1.parse)(t[1]??``);e&&typeof e==`object`&&!Array.isArray(e)&&(s=e)}catch{}g=e.slice(t[0].length)}return{frontmatter:s,body:g}},Dl=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`name`)??``;if(!ml(g,t,`template-get`))return;let S=fl(s.searchParams.get(`folder`)??``,t,`folder`,`template-get`);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){errorResponse(t,404,`urn:ok:error:template-not-found`,`Template not found.`,{handler:`template-get`,detail:`Template "${g}" not found for folder "${w||`.`}". Walked leaf → root.`});return}let{frontmatter:F,body:L}=El(await readFile$1(O,`utf-8`)),B=relative(E,O).split(/[\\/]/).filter(Boolean).join(`/`);successResponse(t,200,TemplateGetSuccessSchema,{template:{name:g,folder:k,scope:j,path:B,frontmatter:F,body:L}},{handler:`template-get`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read template.`,{handler:`template-get`,cause:e})}},{handler:`template-get`,method:`GET`,skipBodyParse:!0}),Ol=withValidation(TemplatePutRequestSchema,async(e,t,s)=>{try{let e=s.name;if(!ml(e,t,`template-put`))return;let g=fl(s.folder,t,`folder`,`template-put`);if(!g||xl(g.folderRel,e,`template-put`,t))return;let S=applyTemplateWrite({projectDir:g.resolvedContentDir,folder:g.folderRel,name:e,body:typeof s.body==`string`?s.body:``,frontmatter:hl(s.frontmatter)});if(!S.ok){let e=S.error.code===`WRITE_ERROR`||S.error.code===`BAD_PROJECT_DIR`?500:400;errorResponse(t,e,e===500?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,e===500?`Failed to write template.`:`Invalid template request.`,{handler:`template-put`,detail:S.error.code,cause:Error(S.error.message)});return}successResponse(t,200,TemplatePutSuccessSchema,{path:S.path,created:S.created,warnings:S.warnings},{handler:`template-put`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to write template.`,{handler:`template-put`,cause:e})}},{handler:`template-put`,method:`PUT`}),kl=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`name`)??``;if(!ml(g,t,`template-delete`))return;let S=fl(s.searchParams.get(`folder`)??``,t,`folder`,`template-delete`);if(!S||xl(S.folderRel,g,`template-delete`,t))return;let w=applyTemplateDelete({projectDir:S.resolvedContentDir,folder:S.folderRel,name:g});if(!w.ok){let e=w.error.code===`WRITE_ERROR`||w.error.code===`UNLINK_FAILED`||w.error.code===`BAD_PROJECT_DIR`?500:400;errorResponse(t,e,e===500?`urn:ok:error:internal-server-error`:`urn:ok:error:invalid-request`,e===500?`Failed to delete template.`:`Invalid template request.`,{handler:`template-delete`,detail:w.error.code,cause:Error(w.error.message)});return}successResponse(t,200,TemplateDeleteSuccessSchema,{existed:w.existed,path:w.path},{handler:`template-delete`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to delete template.`,{handler:`template-delete`,cause:e})}},{handler:`template-delete`,method:`DELETE`,skipBodyParse:!0});function jl(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 Ml(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 Pl(e){return e===`autocomplete`||e===`full_text`||e===`omnibar`?e:`omnibar`}function Fl(e){let t=typeof e==`string`?e.split(`,`):Array.isArray(e)?e:void 0;if(!t)return;let s=t.filter(e=>e===`page`||e===`folder`||e===`content`);return s.length>0?s:void 0}async function Il(){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,...jl(e)]}function Ll(){return[...w()].filter(([e])=>!isSystemDoc(e)&&!isConfigDoc(e)).sort(([e],[t])=>e.localeCompare(t)).map(([e,t])=>`${e}${t.modified}${t.size}${t.canonicalPath}${t.inode}${t.aliases.join(`,`)}`).join(``)}async function Rl(){let e=`${g}${ue??``}`,t=Ll(),s=workspaceSearchCaches.get(e);if(s?.fingerprint===t&&s.corpus)return s.corpus;if(s?.fingerprint===t&&s.pending)return s.pending;let S=Il().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 zl(){if(process.env.NODE_ENV!==`test`)for(let e of[0,1e3,3e3])setTimeout(()=>{Rl().catch(e=>{console.warn(`[search] Failed to prewarm workspace search cache:`,e)})},e)}zl();async function Bl(e,t){if(e.method===`GET`)return Vl(e,t);if(e.method===`POST`)return Hl(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`search`,extraHeaders:{Allow:`GET, POST`}})}let Vl=withValidation(EmptyRequestSchema,async(e,t)=>{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`limit`),S=s.searchParams.get(`query`)??``,w=Pl(s.searchParams.get(`intent`)),E=Fl(s.searchParams.get(`scope`)??s.searchParams.get(`scopes`)),D=g===null?void 0:Number(g);if(S.length>200){errorResponse(t,400,`urn:ok:error:invalid-request`,`Query is too long (max 200 chars).`,{handler:`search-get`});return}try{let e=performance.now();successResponse(t,200,SearchSuccessSchema,{query:S,intent:w,results:searchWorkspaceCorpus(await Rl(),S,{intent:w,scopes:E,limit:D}).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`?Ml(e.document.content,S):void 0})),elapsedMs:Math.max(0,performance.now()-e)},{handler:`search-get`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to search workspace.`,{handler:`search-get`,cause:e})}},{handler:`search-get`,method:`GET`,skipBodyParse:!0}),Hl=withValidation(SearchRequestSchema,async(e,t,s)=>{let g=typeof s.query==`string`?s.query:``,S=Pl(s.intent),w=Fl(s.scopes??s.scope),E=typeof s.limit==`number`?s.limit:void 0;if(g.length>200){errorResponse(t,400,`urn:ok:error:invalid-request`,`Query is too long (max 200 chars).`,{handler:`search-post`});return}try{let e=performance.now();successResponse(t,200,SearchSuccessSchema,{query:g,intent:S,results:searchWorkspaceCorpus(await Rl(),g,{intent:S,scopes:w,limit:E}).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`?Ml(e.document.content,g):void 0})),elapsedMs:Math.max(0,performance.now()-e)},{handler:`search-post`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to search workspace.`,{handler:`search-post`,cause:e})}},{handler:`search-post`,method:`POST`}),Ul=withValidation(EmptyRequestSchema,async(e,t)=>{try{successResponse(t,200,SkillInstallStateSuccessSchema,{...await readSkillInstallStateSnapshot(homedir())},{handler:`skill-install-state`,extraHeaders:{"Cache-Control":`no-store`}})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read skill install state.`,{handler:`skill-install-state`,cause:e})}},{handler:`skill-install-state`,method:`GET`,skipBodyParse:!0,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`skill-install-state`})});async function Wl(e,t){if(checkLocalOpSecurity(e,t,{handler:`handoff`}))try{await handleHandoffDispatch(e,t,{contentDir:g,platform:process.platform})}catch(e){t.headersSent||(log$4.error({err:e},`[handoff] route wrapper failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`handoff`,cause:e}))}}async function Gl(e,t){if(checkLocalOpSecurity(e,t,{handler:`spawn-cursor`}))try{await handleSpawnCursor(e,t,{contentDir:g,platform:process.platform})}catch(e){t.headersSent||(log$4.error({err:e},`[spawn-cursor] route wrapper failed`),errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`spawn-cursor`,cause:e}))}}let Kl=withValidation(ShareConstructUrlRequestSchema,async(e,t,s)=>{try{if(!ue){emitShareConstructUrlLog(`no-remote`),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`no-remote`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}if(!isValidShareDocPath(s.docPath)){emitShareConstructUrlLog(`invalid-path`),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`invalid-path`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}let e=readGitHeadBranch(ue);if(e===null){if(readOriginGitHubRepo(ue).kind===`no-remote`){emitShareConstructUrlLog(`no-remote`),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`no-remote`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}emitShareConstructUrlLog(`detached-head`),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`detached-head`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}let g=readOriginGitHubRepo(ue);if(g.kind===`no-remote`){emitShareConstructUrlLog(`no-remote`),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`no-remote`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}if(g.kind===`non-github`){emitShareConstructUrlLog(`non-github-remote`),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`non-github-remote`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}if(!branchExistsOnOrigin(ue,e)){emitShareConstructUrlLog(`branch-not-on-origin`,!1),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`branch-not-on-origin`,branch:e},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}let S=buildGitHubBlobUrl(g.owner,g.repo,e,s.docPath),w=`${SHARE_BASE_URL}${encodeShareUrl(S)}`;emitShareConstructUrlLog(`ok`,!0),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!0,shareUrl:w,blobUrl:S,branch:e},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG,cause:e})}},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG})}),ql=withValidation(EmptyRequestSchema,async(e,t)=>{try{if(!ue){errorResponse(t,500,`urn:ok:error:internal-server-error`,`projectDir is not configured for this server.`,{handler:BRANCH_INFO_HANDLER_TAG});return}let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`branch`),S=s.searchParams.get(`path`);if(!isValidBranchName(g)){errorResponse(t,400,`urn:ok:error:invalid-request`,`branch query param missing or malformed.`,{handler:BRANCH_INFO_HANDLER_TAG});return}if(!isValidBranchInfoDocPath(S)){errorResponse(t,400,`urn:ok:error:invalid-request`,`path query param missing or malformed.`,{handler:BRANCH_INFO_HANDLER_TAG});return}successResponse(t,200,BranchInfoResponseSchema,await computeBranchInfo(ue,g,S),{handler:BRANCH_INFO_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:BRANCH_INFO_HANDLER_TAG,cause:e})}},{handler:BRANCH_INFO_HANDLER_TAG,method:`GET`,skipBodyParse:!0}),Jl=withValidation(CheckoutRequestSchema,async(e,t,s)=>{if(extractActorIdentity(s,de).kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:CHECKOUT_HANDLER_TAG});return}if(!ue){errorResponse(t,500,`urn:ok:error:internal-server-error`,`projectDir is not configured for this server.`,{handler:CHECKOUT_HANDLER_TAG});return}try{successResponse(t,200,CheckoutResponseSchema,await withParentLock(()=>runCheckoutFlow(ue,s.branch)),{handler:CHECKOUT_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:CHECKOUT_HANDLER_TAG,cause:e})}},{handler:CHECKOUT_HANDLER_TAG,method:`POST`});async function Yl(e){let[t,...s]=ce,g=[...s,...e];return await new Promise((e,s)=>{let S=spawn(t,g,{stdio:[`ignore`,`pipe`,`pipe`],env:{...process.env}}),w=!1,E=setTimeout(()=>{w=!0,S.kill(`SIGTERM`)},SHARE_PUBLISH_TIMEOUT_MS),D=[],O=[];S.stdout.on(`data`,e=>D.push(e)),S.stderr.on(`data`,e=>O.push(e)),S.on(`close`,t=>{if(clearTimeout(E),w){s(Error(`share subprocess timed out after ${SHARE_PUBLISH_TIMEOUT_MS}ms`));return}let g=Buffer.concat(D).toString(`utf-8`);if(t!==0){let e=redactShareSubprocessStderr(Buffer.concat(O).toString(`utf-8`)).slice(0,500);console.warn(`[share] subprocess exited code=${t} stderr=${e}`)}e({stdout:g,code:t})}),S.on(`error`,e=>{clearTimeout(E),s(e)})})}let Xl=withValidation(EmptyRequestSchema,async(e,t)=>{if(!Ce.tryAcquire(`/api/share/publish/owners`)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A share owners operation is already in progress.`,{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG,extraHeaders:{"Retry-After":`5`}});return}try{let{stdout:e}=await Yl([`share`,`owners`,`--json`]),s=parseOwnersEvent(pickTerminalJsonLine(e));emitSharePublishLog(`owners-list`,s.ok?`ok`:s.error,s.ok?{count:s.owners.length}:void 0),successResponse(t,200,SharePublishOwnersResponseSchema,s,{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG,cause:e})}finally{Ce.release(SHARE_PUBLISH_OWNERS_KEY)}},{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG,method:`GET`,skipBodyParse:!0,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:SHARE_PUBLISH_OWNERS_HANDLER_TAG})}),Zl=withValidation(EmptyRequestSchema,async(e,t)=>{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`owner`)??``,S=s.searchParams.get(`name`)??``;if(!isValidShareOwnerName(g)||!isValidShareRepoName(S)){errorResponse(t,400,`urn:ok:error:invalid-request`,`owner and name query params must be valid GitHub identifiers.`,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG});return}if(!Ce.tryAcquire(`/api/share/publish/name-check`)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A share name-check operation is already in progress.`,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG,extraHeaders:{"Retry-After":`5`}});return}try{let{stdout:e}=await Yl([`share`,`name-check`,`--owner`,g,`--name`,S,`--json`]),s=parseNameCheckEvent(pickTerminalJsonLine(e));emitSharePublishLog(`name-check`,s.ok?`ok`:s.error,s.ok?{available:s.available}:void 0),successResponse(t,200,SharePublishNameCheckResponseSchema,s,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG,cause:e})}finally{Ce.release(SHARE_PUBLISH_NAME_CHECK_KEY)}},{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG,method:`GET`,skipBodyParse:!0,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:SHARE_PUBLISH_NAME_CHECK_HANDLER_TAG})}),Ql=withValidation(SharePublishRequestSchema,async(e,t,s)=>{if(!ue){emitSharePublishLog(`publish-create`,`no-project`),successResponse(t,200,SharePublishResponseSchema,{ok:!1,error:`no-project`},{handler:SHARE_PUBLISH_HANDLER_TAG});return}if(!isValidShareOwnerName(s.owner)||!isValidShareRepoName(s.name)){errorResponse(t,400,`urn:ok:error:invalid-request`,`owner and name must be valid GitHub identifiers.`,{handler:SHARE_PUBLISH_HANDLER_TAG});return}if(!Ce.tryAcquire(`/api/share/publish`)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A share publish operation is already in progress.`,{handler:SHARE_PUBLISH_HANDLER_TAG,extraHeaders:{"Retry-After":`5`}});return}try{let e=[`share`,`publish`,`--owner`,s.owner,`--name`,s.name,`--visibility`,s.visibility,`--project-dir`,ue,`--json`];s.description!==void 0&&s.description.length>0&&e.push(`--description`,s.description);let{stdout:g}=await Yl(e),S=parsePublishEvent(pickTerminalJsonLine(g));emitSharePublishLog(`publish-create`,S.ok?`ok`:S.error),successResponse(t,200,SharePublishResponseSchema,S,{handler:SHARE_PUBLISH_HANDLER_TAG})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:SHARE_PUBLISH_HANDLER_TAG,cause:e})}finally{Ce.release(SHARE_PUBLISH_KEY)}},{handler:SHARE_PUBLISH_HANDLER_TAG,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:SHARE_PUBLISH_HANDLER_TAG})}),$l=withValidation(ClientLogsRequestSchema,async(e,t,s)=>{try{let e=getLogger(`renderer`);for(let t of s.entries)try{e[t.level]({...t.fields??{},source:`renderer-console`,transport:`web`,...t.sourceId?{sourceId:t.sourceId}:{},...t.lineNumber===void 0?{}:{lineNumber:t.lineNumber},...t.ts===void 0?{}:{clientTs:t.ts}},t.event??t.message)}catch{}successResponse(t,200,ClientLogsSuccessSchema,{accepted:s.entries.length},{handler:`client-logs`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`client-logs`,cause:e})}},{handler:`client-logs`,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:`client-logs`})}),eu={"/api/asset":Ps,"/api/asset-text":Rs,"/api/document":Wr,"/api/documents":Gr,"/api/backlinks":Kr,"/api/backlink-counts":qr,"/api/forward-links":Jr,"/api/link-graph":Yr,"/api/dead-links":Qr,"/api/orphans":Xr,"/api/hubs":Zr,"/api/tags":ul,"/api/pages":lc,"/api/folder-config":_l,"/api/template":Cl,"/api/search":Bl,"/api/suggest-links":uc,"/api/page-headings":ac,"/api/create-page":nc,"/api/create-folder":rc,"/api/duplicate-path":ic,"/api/rename-path":oc,"/api/delete-path":sc,"/api/trash/cleanup":cc,"/api/upload":dc,"/api/agent-write":Br,"/api/agent-write-md":Vr,"/api/frontmatter-patch":Hr,"/api/agent-patch":ji,"/api/agent-undo":Hi,"/api/agent-activity":Ui,"/api/agent-burst-diff":Gi,"/api/save-version":Zi,"/api/history":ka,"/api/diff":xs,"/api/rollback":Cs,"/api/metrics/reconciliation":Ts,"/api/metrics/parse-health":Ds,"/api/metrics/agent-presence":As,"/api/server-info":Os,"/api/share/construct-url":Kl,"/api/git/branch-info":ql,"/api/git/checkout":Jl,"/api/share/publish/owners":Xl,"/api/share/publish/name-check":Zl,"/api/share/publish":Ql,"/api/principal":ks,"/api/rescue":ec,"/api/workspace":Ns,"/api/sync/status":Jc,"/api/sync/trigger":Yc,"/api/sync/conflicts":Xc,"/api/sync/conflict-content":Qc,"/api/sync/resolve-conflict":Zc,"/api/sync/abort-merge":ll,"/api/local-op/clone":vc,"/api/local-op/open":Sc,"/api/local-op/ok-init":wc,"/api/local-op/auth/login":Mc,"/api/local-op/auth/status":Fc,"/api/local-op/auth/repos":Lc,"/api/local-op/auth/signout":Bc,"/api/local-op/auth/pat":Hc,"/api/local-op/auth/identity":Wc,"/api/local-op/auth/set-identity":qc,"/api/installed-agents":cl,"/api/spawn-cursor":Gl,"/api/handoff":Wl,"/api/install-skill":al,"/api/skill/install-state":Ul,"/api/seed/plan":$c,"/api/seed/apply":nl,"/api/seed/packs":il,"/api/client-logs":$l};j&&(eu[`/api/test-reset`]=Ki,eu[`/api/test-rescan-backlinks`]=Yi,eu[`/api/test-rescan-files`]=Xi);let tu=new Set(`/api/upload./api/create-page./api/create-folder./api/duplicate-path./api/rename-path./api/delete-path./api/trash/cleanup./api/agent-write./api/agent-write-md./api/frontmatter-patch./api/agent-patch./api/agent-undo./api/save-version./api/rollback./api/sync/trigger./api/sync/resolve-conflict./api/sync/abort-merge./api/git/checkout./api/test-reset./api/test-rescan-backlinks./api/test-rescan-files./api/install-skill./api/folder-config./api/template./api/seed/apply./api/client-logs`.split(`.`)),nu=[`/api/local-op/`];return{priority:100,async onRequest({request:e,response:t}){let s=e.url?.split(`?`)[0];if(!s)return;if(s.startsWith(`/api/`)){let s=e.headers.origin;if(s!==void 0&&!isAllowedApiOrigin(s)){errorResponse(t,403,`urn:ok:error:invalid-origin`,`Origin not allowed.`,{handler:`api-origin-gate`});return}if(typeof t.setHeader==`function`&&(s!==void 0&&(t.setHeader(`Access-Control-Allow-Origin`,s),t.setHeader(`Vary`,`Origin`)),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization, traceparent, tracestate, baggage, ${CLIENT_VERSION_HEADER.protocol}, ${CLIENT_VERSION_HEADER.runtime}, ${CLIENT_VERSION_HEADER.kind}`)),e.method===`OPTIONS`){t.writeHead(204),t.end();return}}if(tu.has(s)||nu.some(e=>s.startsWith(e))){let s=e.socket?.remoteAddress;if(s!==void 0&&!isLoopbackAddress(s)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback required.`,{handler:`api-mutating-gate`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`api-mutating-gate`});return}}if(!s.startsWith(`/api/`))return;let 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`:eu[s]||(w=`/api/*`);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 w=eu[s],E=!1;if(w)E=!0,await w(e,t);else if(s.startsWith(`/api/rescue/`)){let g=decodeURIComponent(s.slice(12));g&&(E=!0,await tc(e,t,g))}else if(s.startsWith(`/api/history/`)){let g=decodeURIComponent(s.slice(13));g&&(E=!0,await _s(e,t,g))}else if(s.startsWith(`/api/tags/`)){let g=s.slice(10);g&&(E=!0,await dl(e,t,g))}E||errorResponse(t,404,`urn:ok:error:not-found`,`API endpoint not found.`,{handler:`api-dispatch`,detail:`No handler for ${S} ${s}`});let D=t.statusCode;g.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE,D),D>=500&&g.setStatus({code:SpanStatusCode.ERROR,message:`status ${D}`})}catch(e){throw g.recordException(e),g.setStatus({code:SpanStatusCode.ERROR,message:e instanceof Error?e.message:String(e)}),!t.headersSent&&!t.writableEnded&&!t.destroyed&&errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:w,cause: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(),clientProtocolVersion:number().optional(),clientRuntimeVersion:string().optional(),clientKind:string().optional()}).loose(),HOCUSPOCUS_AUTH_REJECTION_REASONS=[`server-instance-mismatch`,`branch-mismatch`,`rename-redirect`,`doc-deleted`];function isHocuspocusAuthRejectionReason(e){return HOCUSPOCUS_AUTH_REJECTION_REASONS.includes(e)}const WIRE_PAYLOAD_SEPARATOR=`:`;function formatAuthRejectionWire(e,t){return typeof t!=`string`||t.length===0?e:`${e}${WIRE_PAYLOAD_SEPARATOR}${t}`}function parseAuthRejectionWire(e){if(e.length===0)return{kind:null,payload:void 0};let t=e.indexOf(WIRE_PAYLOAD_SEPARATOR),s=t===-1?e:e.slice(0,t);if(!isHocuspocusAuthRejectionReason(s))return{kind:null,payload:void 0};if(t===-1)return{kind:s,payload:void 0};let g=e.slice(t+1);return{kind:s,payload:g.length>0?g:void 0}}var HocuspocusAuthRejection=class extends Error{kind;payload;reason;constructor(e,t,s){super(t),this.name=`HocuspocusAuthRejection`,this.kind=e,this.payload=typeof s==`string`&&s.length>0?s:void 0,this.reason=formatAuthRejectionWire(e,this.payload)}};function parseHocuspocusAuthToken(e){if(typeof e!=`string`||e.length===0)return;let t;try{t=JSON.parse(e)}catch{return}let s=HocuspocusAuthTokenSchema.safeParse(t);return s.success?s.data:void 0}const log$3=getLogger(`conflict-storage`);var ConflictStore=class{storePath;projectDir;branch;conflicts=[];constructor(e,t=`main`){this.storePath=join(getLocalDir(e),`conflicts.json`),this.projectDir=e,this.branch=t,this.load()}load(){if(!existsSync(this.storePath)){this.conflicts=[];return}try{let e=readFileSync(this.storePath,`utf-8`),t=JSON.parse(e);if(t.version!==1){log$3.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$3.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$3.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-BJwB5EBp-DA7Yg-p3.mjs`),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===void 0)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}case`delete`:await w.git.raw([`rm`,`--`,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$3.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(`
1956
1956
  `).map(e=>e.trim()).filter(Boolean);for(let t of e)this.addConflict({file:t,detectedAt:s});g=e.length>0}catch(e){log$3.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$3.warn({err:t},`[conflicts] failed to commit merge after all conflicts resolved — unmerged files re-added`);let S=t instanceof Error?t.message:String(t);throw Error(`Merge commit failed after resolving ${e}; ${g?`unmerged files re-added`:`original file re-added`} — ${S}`,{cause:t})}}};const MIN_GIT_VERSION=`2.31.0`,PROBE_TIMEOUT_MS$1=5e3;var GitNotAvailableError=class extends Error{code=`GIT_NOT_AVAILABLE`;platform;guidance;constructor(e,t,s){super(buildMissingMessage(t),s),this.name=`GitNotAvailableError`,this.platform=e,this.guidance=t}},GitTooOldError=class extends Error{code=`GIT_TOO_OLD`;platform;detected;required;resolvedPath;guidance;constructor(e,t,s,g,S,w){super(buildTooOldMessage(t,s,g,S),w),this.name=`GitTooOldError`,this.platform=e,this.detected=t,this.required=s,this.resolvedPath=g,this.guidance=S}};function detectGit(){let e=probeGit(`git`);if(e.kind===`ok`)return{ok:!0,version:e.version,resolvedPath:e.resolvedPath,source:`PATH`};for(let e of fallbackPaths(process.platform)){if(!existsSync(e))continue;let t=probeGit(e);if(t.kind===`ok`)return{ok:!0,version:t.version,resolvedPath:e,source:`fallback`}}throw new GitNotAvailableError(process.platform,buildGuidance(process.platform))}function assertGitAvailable(){let e=detectGit();if(compareSemver(e.version,`2.31.0`)<0)throw new GitTooOldError(process.platform,e.version,MIN_GIT_VERSION,e.resolvedPath,buildGuidance(process.platform));return e}function probeGit(e){let t=spawnSync(e,[`--version`],{encoding:`utf-8`,timeout:PROBE_TIMEOUT_MS$1,env:{...process.env,LANG:`C`,LC_ALL:`C`}});if(t.error)return`signal`in t&&t.signal===`SIGTERM`?{kind:`fail`,reason:`timeout`}:{kind:`fail`,reason:`enoent`};if(t.status!==0)return{kind:`fail`,reason:`nonzero`};let s=parseGitVersion(typeof t.stdout==`string`?t.stdout:``);return s===null?{kind:`fail`,reason:`unparseable`}:{kind:`ok`,version:s,resolvedPath:e===`git`?resolveOnPath(`git`)??e:e}}function parseGitVersion(e){let t=e.match(/git version (\d+)\.(\d+)\.(\d+)/);return t?`${t[1]}.${t[2]}.${t[3]}`:null}const SAFE_COMMAND_NAME_RE=/^[a-zA-Z0-9_.-]+$/,resolveOnPathCache=new Map;function resolveOnPath(e){if(!SAFE_COMMAND_NAME_RE.test(e))return null;let t=resolveOnPathCache.get(e);if(t!==void 0)return t;let s;if(process.platform===`win32`){let t=spawnSync(`where`,[e],{encoding:`utf-8`,timeout:PROBE_TIMEOUT_MS$1});s=t.status===0&&(typeof t.stdout==`string`?t.stdout:``).trim().split(/\r?\n/)[0]||null}else{let t=spawnSync(`/bin/sh`,[`-c`,`command -v ${e}`],{encoding:`utf-8`,timeout:PROBE_TIMEOUT_MS$1});s=t.status===0&&(typeof t.stdout==`string`?t.stdout:``).trim().split(/\r?\n/)[0]||null}return s!==null&&resolveOnPathCache.set(e,s),s}function fallbackPaths(e){switch(e){case`darwin`:return[`/opt/homebrew/bin/git`,`/usr/local/bin/git`,`/Library/Developer/CommandLineTools/usr/bin/git`,`/usr/bin/git`];case`win32`:return[`C:\\Program Files\\Git\\cmd\\git.exe`,`C:\\Program Files (x86)\\Git\\cmd\\git.exe`,join(homedir(),`scoop`,`apps`,`git`,`current`,`cmd`,`git.exe`)];default:return[`/usr/bin/git`,`/usr/local/bin/git`,join(homedir(),`.local`,`bin`,`git`),`/snap/bin/git`]}}function buildGuidance(e){switch(e){case`darwin`:{let e=[];return hasBrew()&&e.push({label:`Install with Homebrew (recommended; no admin needed)`,command:`brew install git`,requiresAdmin:!1}),e.push({label:`Install Xcode Command Line Tools`,command:`xcode-select --install`,requiresAdmin:!0}),{product:`Git`,url:`https://git-scm.com/download/mac`,options:e}}case`win32`:{let e=[];return hasWinget()&&e.push({label:`Install with winget`,command:`winget install --id Git.Git -e --source winget`,requiresAdmin:!0}),hasScoop()&&e.push({label:`Install with Scoop (no admin)`,command:`scoop install git`,requiresAdmin:!1}),hasChoco()&&e.push({label:`Install with Chocolatey`,command:`choco install git -y`,requiresAdmin:!0}),e.push({label:`Download the official installer`,command:`Open https://gitforwindows.org/ in your browser`,requiresAdmin:!1}),{product:`Git for Windows`,url:`https://gitforwindows.org/`,options:e}}default:return{product:`Git`,url:`https://git-scm.com/download/linux`,options:linuxInstallOptions()}}}function linuxInstallOptions(){switch(detectLinuxFamily()){case`debian`:return[{label:`Install with apt`,command:`sudo apt install git`,requiresAdmin:!0}];case`fedora`:return[{label:`Install with dnf`,command:`sudo dnf install git`,requiresAdmin:!0}];case`arch`:return[{label:`Install with pacman`,command:`sudo pacman -S git`,requiresAdmin:!0}];case`opensuse`:return[{label:`Install with zypper`,command:`sudo zypper install git`,requiresAdmin:!0}];case`alpine`:return[{label:`Install with apk`,command:`sudo apk add git`,requiresAdmin:!0}];default:return[{label:`Use your distribution's package manager`,command:`apt / dnf / pacman / zypper / apk install git (one of these will fit your system)`,requiresAdmin:!0}]}}function detectLinuxFamily(e){let t=e;if(t===void 0)try{t=readFileSync(`/etc/os-release`,`utf-8`)}catch{return`unknown`}let s=[/^ID=(.+)$/m.exec(t)?.[1]?.replace(/["']/g,``),...(/^ID_LIKE=(.+)$/m.exec(t)?.[1]?.replace(/["']/g,``)??``).split(/\s+/)].filter(e=>!!e);return s.some(e=>/^(debian|ubuntu|mint|pop)$/i.test(e))?`debian`:s.some(e=>/^(fedora|rhel|centos|alma|rocky)$/i.test(e))?`fedora`:s.some(e=>/^(arch|manjaro|endeavouros)$/i.test(e))?`arch`:s.some(e=>/^opensuse/i.test(e))||s.includes(`suse`)?`opensuse`:s.some(e=>/^alpine$/i.test(e))?`alpine`:`unknown`}function hasCommand(e){return resolveOnPath(e)!==null}function hasBrew(){return hasCommand(`brew`)}function hasWinget(){return hasCommand(`winget`)}function hasScoop(){return hasCommand(`scoop`)}function hasChoco(){return hasCommand(`choco`)}function buildMissingMessage(e){let t=[];if(t.push(`Open Knowledge needs ${e.product} to track changes to your knowledge base, but it isn't installed (or isn't on PATH).`),t.push(``),e.options.length>0){t.push(`Install ${e.product}:`);for(let s of e.options){let e=s.requiresAdmin?` (admin required)`:``;t.push(` • ${s.label}${e}`),t.push(` ${s.command}`)}t.push(``)}return t.push(`Or download from: ${e.url}`),t.push(``),t.push(`After installing, re-run Open Knowledge.`),t.push("Run `ok diagnose health --check git` to verify your installation."),t.join(`
1957
1957
  `)}function buildTooOldMessage(e,t,s,g){let S=[];if(S.push(`Open Knowledge requires ${g.product} ${t} or newer (detected ${e} at ${s}).`),S.push(``),g.options.length>0){S.push(`Update ${g.product}:`);for(let e of g.options){let t=e.requiresAdmin?` (admin required)`:``;S.push(` • ${e.label}${t}`),S.push(` ${e.command}`)}S.push(``)}return S.push(`Or download from: ${g.url}`),S.push(``),S.push(`After updating, re-run Open Knowledge.`),S.push("Run `ok diagnose health --check git` to verify your installation."),S.join(`
1958
- `)}function compareSemver(e,t){let s=e.split(`.`).map(e=>Number.parseInt(e,10)||0),g=t.split(`.`).map(e=>Number.parseInt(e,10)||0);for(let e=0;e<3;e++){let t=s[e]??0,S=g[e]??0;if(t!==S)return t-S}return 0}const GIT_PREFLIGHT_FAIL_SPAN_NAME=`ok.preflight.git.fail`;function emitPreflightFailureSpan(e){let t=e instanceof GitTooOldError?`too_old`:`not_available`,s=e instanceof GitTooOldError?e.detected:``;withSpanSync(GIT_PREFLIGHT_FAIL_SPAN_NAME,{attributes:{"ok.platform":e.platform,"ok.preflight.git.reason":t,"ok.preflight.git.detected_version":s}},()=>{})}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())}}}function isObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function readRawSinkBlock(e){if(!existsSync(e))return{};let t;try{t=(0,import_dist$1.parse)(readFileSync(e,`utf-8`))}catch(t){return console.warn(`[telemetry.localSink] failed to parse ${e}; falling back to schema defaults — any explicit telemetry.localSink fields in this file are being ignored. Reason: ${t instanceof Error?t.message:String(t)}`),{}}if(!isObject(t))return{};let s=t.telemetry;if(!isObject(s))return{};let g=s.localSink;return isObject(g)?g:{}}function readBoolean(e){return typeof e==`boolean`?e:void 0}function readPositiveNumber(e){return typeof e==`number`&&Number.isFinite(e)&&e>0?e:void 0}function readStringArray(e){if(Array.isArray(e)&&e.every(e=>typeof e==`string`))return e}function readMaxBytes(e){if(isObject(e))return readPositiveNumber(e.maxBytes)}function resolveLocalSinkConfig(e){if(process.env.OK_DISABLE_LOCAL_SINK===`1`||process.env.OK_DISABLE_LOCAL_SINK===`true`)return null;let t=readRawSinkBlock(resolveConfigPath(`project`,e.projectDir)),s=readRawSinkBlock(resolveConfigPath(`project-local`,e.projectDir));if((readBoolean(s.enabled)??readBoolean(t.enabled)??!0)===!1)return null;let g=readMaxBytes(s.spans)??readMaxBytes(t.spans)??52428800,S=readMaxBytes(s.logs)??readMaxBytes(t.logs)??26214400,w=readStringArray(s.attributeDenylist)??readStringArray(t.attributeDenylist)??DEFAULT_TELEMETRY_ATTRIBUTE_DENYLIST;return{telemetry:{contentDir:e.contentDir,spansMaxBytes:g,attributeDenylist:w},logs:{contentDir:e.contentDir,maxBytes:S}}}const MCP_SERVER_NAME=`open-knowledge`,MCP_CONNECTION_ID_HEADER=`x-ok-connection-id`;function sanitizeClientName(e,t){let s=Array.from(e??``).map(e=>{let t=e.charCodeAt(0);return t<=31||t===127?` `:e}).join(``).replace(/\s+/g,` `).trim();return s?s.slice(0,128):t}function buildInstructions(e){return'Open Knowledge is a markdown-CRDT knowledge base exposed via MCP.\n\n## STOP — native tools on in-scope `.md` / `.mdx`\n\nWhen this workspace has Open Knowledge MCP configured, do **not** use your host\'s native file tools on markdown paths inside the content directory. The ban covers every common rationalization:\n\n- **Native `Read` / `Grep` / `Glob` on in-scope `.md` / `.mdx`** — the original case.\n- **`Bash ls` / `Bash find` / `Bash cat` on dirs containing in-scope markdown** — use `exec("ls -A …")` / `exec("find … -name \'*.md\'")` / `exec("cat …")` instead. Native returns bare names; `exec` returns frontmatter, backlink counts, and recent activity per child. `-A` shows hidden entries (`.ok/`, `.okignore`) which OK projects carry; omit `.` and `..` rows that `-a` would add.\n- **Glob patterns that target markdown** (`**/*.md`, any dir known to be markdown-heavy like `specs/**`, `reports/**`, `docs/**`) — use `exec` with `find`, or `exec("ls -A <dir>")`.\n- **Dispatching the Explore / general-purpose subagent for markdown-heavy exploration** — subagents use native `Read` / `Grep` / `Glob` internally and bypass Open Knowledge entirely. Do markdown exploration yourself via `exec` / `search`. Subagents remain appropriate for **source-code** exploration.\n- **Native `Read` / `Grep` on any in-scope markdown inside `.ok/`** — the `.ok/` directory is in-scope; if it carries `.md` / `.mdx`, treat those the same as any other knowledge-base file.\n\nWhy: native tools skip frontmatter, backlinks, shadow-repo activity, and project git history that OK\'s tools return for every matched knowledge-base file. `exec` is the primary read surface; it runs read-only bash (`cat`, `ls`, `grep`, `find`, `head`, `tail`, `wc`, `sort`, `uniq`, `cut` — pipes OK) and returns raw stdout plus enriched metadata per file.\n\n**MCP tool visibility — not seeing `exec` is NOT the escape hatch.** MCP wiring varies by client. Claude Code, Cursor, Codex, Windsurf, VS Code — each surfaces MCP differently. Server labels are user-defined; tools may not appear as top-level symbols named `exec` in your specific UI. If Open Knowledge is registered as an MCP server in this workspace, route markdown reads through its `exec` / `search` via your client\'s documented MCP invocation (including any generic "call MCP tool" flow). Registration is the test, not top-level-symbol visibility.\n\n**Escape hatch.** Native `Read` / `Grep` / `Glob` on `.md` / `.mdx` is allowed **only** when no Open Knowledge MCP server is registered for this project, **or** immediately after you tried an MCP call and it failed — then begin a user-visible sentence with `Open Knowledge MCP unavailable:`. Never use the hatch because you skipped your client\'s MCP path, didn\'t see `exec` as a top-level tool, or rationalized the skill wasn\'t necessary.\n\n**Source code and non-markdown files** (`.ts`, `.py`, `package.json`, …): native `Read` / `Grep` / `Glob` always.\n\n## Reads — examples\n\n- Read a file: `exec("cat <path>.md")` — contents + full rich enrichment.\n- List a directory: `exec("ls -A <dir>")` — per-child frontmatter, recursive markdown counts, most-recently-updated doc per subdir, folder-level `frontmatter_defaults` + `templates_available`. Prefer `-A` over plain `ls` to surface dot-prefixed entries (`.ok/`, `.okignore`) without the noisy `.`/`..` rows that `-a` adds.\n- Literal search: `exec("grep -rn <term> <dir> | head -5")` — matches + enrichment on matched files.\n- Ranked search: `search({ query })` — cmd-K parity (title boost + body BM25 + recency); use when picking the best doc, not when listing every occurrence.\n\n## Preview — open the browser at session start\n\nThe user watches your edits land in a live browser preview. Open it once at session start, then keep working. Re-navigate only when the user asks to open a different doc, or to land them on a finished deliverable (see below) — not to re-check your own edits.\n\n**End a turn on the deliverable, not your scratch space.** Keep the preview steady *during* a multi-doc task — don\'t yank it around to re-check your own edits. But when a turn created or substantially changed user-facing docs, navigate the preview to the primary deliverable before you hand back: the hub / overview / index page when you created several docs, or the changed doc when you changed one. Don\'t step the user through every supporting source card — the user is watching, so leave them on the result.\n\n**`previewUrl` is a route, not a URL to open.** Every read response (per-doc, on `exec` / `search` / `links` rows) and every write response carries a `previewUrl` — a route fragment like `/#/specs/foo/SPEC`, with **no scheme, host, or port**. It identifies *which doc* to preview, not a URL to hand a browser by itself. Never construct or guess preview URLs.\n\n**Pick how to open the preview by tool capability — not by host name.** Look at the tools actually available to you this session. If a tool can navigate to a URL, it counts as an in-app browser — match on the capability, not on what your host is called.\n\n- **You have a `preview_*` tool** (e.g. `preview_start`) → call `preview_start("open-knowledge-ui")` and nothing else. The pane supplies its own origin; you never need a URL. Do NOT also call `get_preview_url`. Do NOT read, diagnose, or edit `.claude/launch.json` — that file is host-managed, and the OK lock-collision proxy handles the UI-already-running case automatically. If `preview_start` fails, report it to the user; do not try to "fix" `launch.json`.\n- **No `preview_*` tool, but you have an in-app / built-in browser tool** — including Codex\'s built-in browser, and any host tool whose contract is "navigate to a URL" (`browser`, `view_url`, `open_url`, `web.browse`, host-specific names, etc.) → call `get_preview_url` once to get the full browser URL (`{ url, baseUrl, running }`), then navigate your **in-app browser** to `url`. Pass a `docName` to `get_preview_url` to jump straight to a doc, or omit it for the UI root.\n- **Truly no browser-capable tool — if you have ANY tool that navigates to a URL, use the in-app branch above** (a pure stdio host with no URL-navigation tool at all) → call `get_preview_url`, then `open <url>` in the system browser as a last resort, and say so plainly to the user ("opening the preview in your system browser — this host has no in-app browser"). The system browser is the fallback, never the default.\n- **Honor `autoOpen`** (on `get_preview_url`, or on `warning` for write tools). If `false`, do not open or refresh any preview UI; surface the URL only if asked.\n\n**Opening or reading a file IS a preview navigation.** On any "open `<file>`" / "read `<file>`" request, navigate the browser to that doc\'s `previewUrl` route from the tool response — not a separate fetch, not a fresh system-browser launch.\n\n**Four signals to check if the preview is already attached** (read these from each write response):\n\n1. You opened/navigated earlier this session → don\'t reopen.\n2. Write response has `previewUrl` (non-null route) and NO `warning` → a browser is attached somewhere; do nothing.\n3. `warning: { action: "attach-preview-once", previewUrl, message }` → UI reachable, no browser attached; navigate one-shot (`preview_start`, or `get_preview_url` → in-app browser).\n4. `warning: { action: "start-ui", previewUrl: null, message }` → no UI running anywhere. Surface the message verbatim — recovery options are in the in-band copy. Don\'t loop on retries.\n\nWarnings fire at most once per session in the fresh-start case.\n\n**`previewUrl: null` only means "no UI reachable" on the three attach-warning tools: `write_document` / `edit_document` / `edit_frontmatter`.** Workflow tools return prose and don\'t carry `previewUrl`. `delete_document` / `rename` emit `previousPreviewUrl` (different field, for closing stale tabs) and don\'t fire attach warnings. `get_preview_url` reports `running: false` + `url: null` when no UI is running.\n\nIf you see `"Hocuspocus server is not running"`, run `ok start` and retry.\n\nOK Electron and `ok ui` share `ui.lock`; when a second UI binds a different port, the OK lock-collision proxy bridges it to the live server transparently. That is exactly why `previewUrl` is route-only — the port behind the proxy is not the agent\'s to use. **Do not nudge the user to quit OK Electron to free a port** — the proxy handles it, and quitting tears down a UI in active use.\n\n**The preview is read-only for the agent — it is the user\'s view, not a surface you read back.** You cannot click or type to drive edits — the CRDT flow is one-way (agent → MCP → CRDT → preview).\n\n**No screenshots to confirm edits, no generic verification loop.** Do NOT take `preview_screenshot` (host tool, not OK MCP) after a write, and do not run a generic snapshot/eval/screenshot verification loop — OK\'s preview is a read-only, one-way mirror, so the CRDT tool response *is* the confirmation that an edit landed. Screenshot only when debugging a visual rendering issue or when the user explicitly asks to see the preview — never to confirm an edit landed.\n\n## Scope recap\n\nOpen Knowledge looks for documents under the resolved `content.dir` (discoverable at runtime via `get_config({ path: [\'content\', \'dir\'] })`). `.gitignore` and `.okignore` (at the project root and at any folder depth) define exclusions. Folder defaults + templates live in nested `<folder>/.ok/frontmatter.yml` + `<folder>/.ok/templates/` files — NOT in `.ok/config.yml`.\n\nDefault mental model (no jargon): **every `.md` and `.mdx` under `content.dir`** not excluded by `.gitignore` or `.okignore` is an Open Knowledge document — including under `specs/`, `reports/`, `docs/`, etc. Read `.okignore` (and any nested `.okignore` files) once per turn to know what\'s excluded.\n\n**First session in this project?** If `frontmatter_defaults` and `templates_available` are empty for substantial folders, the project hasn\'t been onboarded yet — invoke `discover` (Workflow tools table) before writing. Once onboarded, the cascade carries the discipline.\n\n\nFull guidance lives in the bundled `open-knowledge` skill at `~/.ok/skills/open-knowledge/SKILL.md`.\n'}function installPrettyZodErrors(e){let t=e;if(t.__prettyZodErrorsInstalled===!0)return;let s=t.validateToolInput;if(typeof s!=`function`){console.warn(`[pretty-zod-errors] McpServer.validateToolInput not found — SDK internals may have changed. Falling back to default error formatting.`);return}t.validateToolInput=async function(e,t,g){if(!e.inputSchema||!isZodSchema(e.inputSchema))return s.call(this,e,t,g);let S=await e.inputSchema.safeParseAsync(t);if(S.success)return S.data;let w=prettifyError(S.error);throw new McpError(ErrorCode.InvalidParams,`Input validation error: Invalid arguments for tool ${g}:\n${w}`)},t.__prettyZodErrorsInstalled=!0}function isZodSchema(e){return typeof e!=`object`||!e?!1:typeof e.safeParseAsync==`function`}const loggerContext=new AsyncLocalStorage;var McpLogger=class e{sessionId;corrId;component;constructor(e=`mcp`,t){this.sessionId=t??randomUUID().slice(0,12),this.corrId=randomUUID().slice(0,8),this.component=e}info(e,t={}){this.emit(`info`,e,t)}warn(e,t={}){this.emit(`warn`,e,t)}error(e,t,s={}){let g=t?{error:t instanceof Error?t.message:String(t),...s}:s;this.emit(`error`,e,g)}debug(e,t={}){(process.env.MCP_DEBUG===`1`||process.env.DEBUG?.includes(`mcp`))&&this.emit(`debug`,e,t)}child(t){return new e(t??this.component,this.sessionId)}asCallback(){return e=>this.info(e)}emit(e,t,s){let g={ts:new Date().toISOString(),level:e,sessionId:this.sessionId,corrId:this.corrId,component:this.component,msg:t,...s},S=`${JSON.stringify(g)}\n`;process.stderr.write(S);let w=process.env.OK_LOG_FILE;if(w)try{appendFileSync(w,S)}catch(e){console.warn(`[mcp-logger] Failed to write to OK_LOG_FILE: ${e instanceof Error?e.message:e}`)}}};function runWithMcpLogger(e,t){return loggerContext.run(e,t)}function getCurrentMcpLogger(){return loggerContext.getStore()}const REDACTED_STRING_KEYS=new Set([`find`,`markdown`,`replace`]),COMMON_ARRAY_KEYS=[`backlinks`,`deadLinks`,`documents`,`enrichedPaths`,`entries`,`forwardLinks`,`hints`,`hubs`,`orphans`,`results`],COMMON_SCALAR_KEYS=[`checkpointRef`,`cwd`,`fileCount`,`matchCount`,`ok`,`query`,`stdoutTruncated`,`truncated`];function isPlainObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function isToolExtraLike(e){return isPlainObject(e)&&`requestId`in e}function summarizeStringForLog(e,t){if(REDACTED_STRING_KEYS.has(e))return{redacted:!0,type:`string`,length:t.length,lines:t.length===0?0:t.split(`
1958
+ `)}function compareSemver(e,t){let s=e.split(`.`).map(e=>Number.parseInt(e,10)||0),g=t.split(`.`).map(e=>Number.parseInt(e,10)||0);for(let e=0;e<3;e++){let t=s[e]??0,S=g[e]??0;if(t!==S)return t-S}return 0}const GIT_PREFLIGHT_FAIL_SPAN_NAME=`ok.preflight.git.fail`;function emitPreflightFailureSpan(e){let t=e instanceof GitTooOldError?`too_old`:`not_available`,s=e instanceof GitTooOldError?e.detected:``;withSpanSync(GIT_PREFLIGHT_FAIL_SPAN_NAME,{attributes:{"ok.platform":e.platform,"ok.preflight.git.reason":t,"ok.preflight.git.detected_version":s}},()=>{})}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())}}}function isObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function readRawSinkBlock(e){if(!existsSync(e))return{};let t;try{t=(0,import_dist$1.parse)(readFileSync(e,`utf-8`))}catch(t){return console.warn(`[telemetry.localSink] failed to parse ${e}; falling back to schema defaults — any explicit telemetry.localSink fields in this file are being ignored. Reason: ${t instanceof Error?t.message:String(t)}`),{}}if(!isObject(t))return{};let s=t.telemetry;if(!isObject(s))return{};let g=s.localSink;return isObject(g)?g:{}}function readBoolean(e){return typeof e==`boolean`?e:void 0}function readPositiveNumber(e){return typeof e==`number`&&Number.isFinite(e)&&e>0?e:void 0}function readStringArray(e){if(Array.isArray(e)&&e.every(e=>typeof e==`string`))return e}function readMaxBytes(e){if(isObject(e))return readPositiveNumber(e.maxBytes)}function resolveLocalSinkConfig(e){if(process.env.OK_DISABLE_LOCAL_SINK===`1`||process.env.OK_DISABLE_LOCAL_SINK===`true`)return null;let t=readRawSinkBlock(resolveConfigPath(`project`,e.projectDir)),s=readRawSinkBlock(resolveConfigPath(`project-local`,e.projectDir));if((readBoolean(s.enabled)??readBoolean(t.enabled)??!0)===!1)return null;let g=readMaxBytes(s.spans)??readMaxBytes(t.spans)??52428800,S=readMaxBytes(s.logs)??readMaxBytes(t.logs)??26214400,w=readStringArray(s.attributeDenylist)??readStringArray(t.attributeDenylist)??DEFAULT_TELEMETRY_ATTRIBUTE_DENYLIST;return{telemetry:{contentDir:e.contentDir,spansMaxBytes:g,attributeDenylist:w},logs:{contentDir:e.contentDir,maxBytes:S}}}const MCP_SERVER_NAME=`open-knowledge`,MCP_CONNECTION_ID_HEADER=`x-ok-connection-id`;function sanitizeClientName(e,t){let s=Array.from(e??``).map(e=>{let t=e.charCodeAt(0);return t<=31||t===127?` `:e}).join(``).replace(/\s+/g,` `).trim();return s?s.slice(0,128):t}function buildInstructions(e){return'Open Knowledge is a markdown-CRDT knowledge base exposed via MCP.\n\n## STOP — native tools on in-scope `.md` / `.mdx`\n\nWhen this workspace has Open Knowledge MCP configured, do **not** use your host\'s native file tools on markdown paths inside the content directory. The ban covers every common rationalization:\n\n- **Native `Read` / `Grep` / `Glob` on in-scope `.md` / `.mdx`** — the original case.\n- **`Bash ls` / `Bash find` / `Bash cat` on dirs containing in-scope markdown** — use `exec("ls -A …")` / `exec("find … -name \'*.md\'")` / `exec("cat …")` instead. Native returns bare names; `exec` returns frontmatter, backlink counts, and recent activity per child. `-A` shows hidden entries (`.ok/`, `.okignore`) which OK projects carry; omit `.` and `..` rows that `-a` would add.\n- **Glob patterns that target markdown** (`**/*.md`, any dir known to be markdown-heavy like `specs/**`, `reports/**`, `docs/**`) — use `exec` with `find`, or `exec("ls -A <dir>")`.\n- **Dispatching the Explore / general-purpose subagent for markdown-heavy exploration** — subagents use native `Read` / `Grep` / `Glob` internally and bypass Open Knowledge entirely. Do markdown exploration yourself via `exec` / `search`. Subagents remain appropriate for **source-code** exploration.\n- **Native `Read` / `Grep` on any in-scope markdown inside `.ok/`** — the `.ok/` directory is in-scope; if it carries `.md` / `.mdx`, treat those the same as any other knowledge-base file.\n\nWhy: native tools skip frontmatter, backlinks, shadow-repo activity, and project git history that OK\'s tools return for every matched knowledge-base file. `exec` is the primary read surface; it runs read-only bash (`cat`, `ls`, `grep`, `find`, `head`, `tail`, `wc`, `sort`, `uniq`, `cut` — pipes OK) and returns raw stdout plus enriched metadata per file.\n\n**MCP tool visibility — not seeing `exec` is NOT the escape hatch.** MCP wiring varies by client. Claude Code, Cursor, Codex, Windsurf, VS Code — each surfaces MCP differently. Server labels are user-defined; tools may not appear as top-level symbols named `exec` in your specific UI. If Open Knowledge is registered as an MCP server in this workspace, route markdown reads through its `exec` / `search` via your client\'s documented MCP invocation (including any generic "call MCP tool" flow). Registration is the test, not top-level-symbol visibility.\n\n**Escape hatch.** Native `Read` / `Grep` / `Glob` on `.md` / `.mdx` is allowed **only** when no Open Knowledge MCP server is registered for this project, **or** immediately after you tried an MCP call and it failed — then begin a user-visible sentence with `Open Knowledge MCP unavailable:`. Never use the hatch because you skipped your client\'s MCP path, didn\'t see `exec` as a top-level tool, or rationalized the skill wasn\'t necessary.\n\n**Source code and non-markdown files** (`.ts`, `.py`, `package.json`, …): native `Read` / `Grep` / `Glob` always.\n\n## Reads — examples\n\n- Read a file: `exec("cat <path>.md")` — contents + full rich enrichment.\n- List a directory: `exec("ls -A <dir>")` — per-child frontmatter, recursive markdown counts, most-recently-updated doc per subdir, folder-level `frontmatter_defaults` + `templates_available`. Prefer `-A` over plain `ls` to surface dot-prefixed entries (`.ok/`, `.okignore`) without the noisy `.`/`..` rows that `-a` adds.\n- Literal search: `exec("grep -rn <term> <dir> | head -5")` — matches + enrichment on matched files.\n- Ranked search: `search({ query })` — cmd-K parity (title boost + body BM25 + recency); use when picking the best doc, not when listing every occurrence.\n\n## Preview — open the browser at session start\n\nThe user watches your edits land in a live browser preview. Open it once at session start, then keep working. Re-navigate only when the user asks to open a different doc, or to land them on a finished deliverable (see below) — not to re-check your own edits.\n\n**End a turn on the deliverable, not your scratch space.** Keep the preview steady *during* a multi-doc task — don\'t yank it around to re-check your own edits. But when a turn created or substantially changed user-facing docs, navigate the preview to the primary deliverable before you hand back: the hub / overview / index page when you created several docs, or the changed doc when you changed one. Don\'t step the user through every supporting source card — the user is watching, so leave them on the result.\n\n**`previewUrl` is a route, not a URL to open.** Every read response (per-doc, on `exec` / `search` / `links` rows) and every write response carries a `previewUrl` — a route fragment like `/#/specs/foo/SPEC`, with **no scheme, host, or port**. It identifies *which doc* to preview, not a URL to hand a browser by itself. Never construct or guess preview URLs.\n\n**Pick how to open the preview by tool capability — not by host name.** Look at the tools actually available to you this session. If a tool can navigate to a URL, it counts as an in-app browser — match on the capability, not on what your host is called.\n\n- **You have a `preview_*` tool** (e.g. `preview_start`) → call `preview_start("open-knowledge-ui")`; the pane supplies its own origin. To land the pane on a specific target, arm it first: `get_preview_url({ armPaneTarget: true, docName })` (or `folder`) writes a ~30s target so the next base-open lands there. Don\'t read or edit `.claude/launch.json` — host-managed; the OK lock-collision proxy handles the UI-already-running case. If `preview_start` fails, report it; don\'t "fix" `launch.json`.\n- **No `preview_*` tool, but you have an in-app / built-in browser tool** — Codex\'s built-in browser, or any host tool that navigates to a URL (`browser`, `view_url`, `open_url`, `web.browse`, etc.) → call `get_preview_url` once for the **exact** target (`docName` for a doc, `folder` for a folder) and navigate your **in-app browser** straight to the returned `url`. Open that deep URL directly — never the root then navigate. Omit both args only for the root.\n- **Truly no browser-capable tool — if you have ANY tool that navigates to a URL, use the in-app branch above** (a pure stdio host with no URL-navigation tool at all) → call `get_preview_url`, then `open <url>` in the system browser as a last resort, and say so plainly to the user ("opening the preview in your system browser — this host has no in-app browser"). The system browser is the fallback, never the default.\n- **Honor `autoOpen`** (on `get_preview_url`, or on `warning` for write tools). If `false`, do not open or refresh any preview UI; surface the URL only if asked.\n\n**Opening or reading a file IS a preview navigation.** On any "open `<file>`" / "read `<file>`" request, navigate the browser to that doc\'s `previewUrl` route from the tool response — not a separate fetch, not a fresh system-browser launch.\n\n**Four signals to check if the preview is already attached** (read these from each write response):\n\n1. You opened/navigated earlier this session → don\'t reopen.\n2. Write response has `previewUrl` (non-null route) and NO `warning` → a browser is attached somewhere; do nothing.\n3. `warning: { action: "attach-preview-once", previewUrl, message }` → UI reachable, no browser attached; navigate one-shot (`preview_start`, or `get_preview_url` → in-app browser).\n4. `warning: { action: "start-ui", previewUrl: null, message }` → no UI running anywhere. Surface the message verbatim — recovery options are in the in-band copy. Don\'t loop on retries.\n\nWarnings fire at most once per session in the fresh-start case.\n\n**`previewUrl: null` only means "no UI reachable" on the three attach-warning tools: `write_document` / `edit_document` / `edit_frontmatter`.** Workflow tools return prose and don\'t carry `previewUrl`. `delete_document` / `rename` emit `previousPreviewUrl` (different field, for closing stale tabs) and don\'t fire attach warnings. `get_preview_url` reports `running: false` + `url: null` when no UI is running.\n\nIf you see `"Hocuspocus server is not running"`, run `ok start` and retry.\n\nOK Electron and `ok ui` share `ui.lock`; when a second UI binds a different port, the OK lock-collision proxy bridges it to the live server transparently. That is exactly why `previewUrl` is route-only — the port behind the proxy is not the agent\'s to use. **Do not nudge the user to quit OK Electron to free a port** — the proxy handles it, and quitting tears down a UI in active use.\n\n**The preview is read-only for the agent — it is the user\'s view, not a surface you read back.** You cannot click or type to drive edits — the CRDT flow is one-way (agent → MCP → CRDT → preview).\n\n**No screenshots to confirm edits, no generic verification loop.** Do NOT take `preview_screenshot` (host tool, not OK MCP) after a write, and do not run a generic snapshot/eval/screenshot verification loop — OK\'s preview is a read-only, one-way mirror, so the CRDT tool response *is* the confirmation that an edit landed. Screenshot only when debugging a visual rendering issue or when the user explicitly asks to see the preview — never to confirm an edit landed.\n\n## Scope recap\n\nOpen Knowledge looks for documents under the resolved `content.dir` (discoverable at runtime via `get_config({ path: [\'content\', \'dir\'] })`). `.gitignore` and `.okignore` (at the project root and at any folder depth) define exclusions. Folder defaults + templates live in nested `<folder>/.ok/frontmatter.yml` + `<folder>/.ok/templates/` files — NOT in `.ok/config.yml`.\n\nDefault mental model (no jargon): **every `.md` and `.mdx` under `content.dir`** not excluded by `.gitignore` or `.okignore` is an Open Knowledge document — including under `specs/`, `reports/`, `docs/`, etc. Read `.okignore` (and any nested `.okignore` files) once per turn to know what\'s excluded.\n\n**First session in this project?** If `frontmatter_defaults` and `templates_available` are empty for substantial folders, the project hasn\'t been onboarded yet — invoke `discover` (Workflow tools table) before writing. Once onboarded, the cascade carries the discipline.\n\n\nFull guidance lives in the bundled `open-knowledge` skill at `~/.ok/skills/open-knowledge/SKILL.md`.\n'}function installPrettyZodErrors(e){let t=e;if(t.__prettyZodErrorsInstalled===!0)return;let s=t.validateToolInput;if(typeof s!=`function`){console.warn(`[pretty-zod-errors] McpServer.validateToolInput not found — SDK internals may have changed. Falling back to default error formatting.`);return}t.validateToolInput=async function(e,t,g){if(!e.inputSchema||!isZodSchema(e.inputSchema))return s.call(this,e,t,g);let S=await e.inputSchema.safeParseAsync(t);if(S.success)return S.data;let w=prettifyError(S.error);throw new McpError(ErrorCode.InvalidParams,`Input validation error: Invalid arguments for tool ${g}:\n${w}`)},t.__prettyZodErrorsInstalled=!0}function isZodSchema(e){return typeof e!=`object`||!e?!1:typeof e.safeParseAsync==`function`}const loggerContext=new AsyncLocalStorage;var McpLogger=class e{sessionId;corrId;component;constructor(e=`mcp`,t){this.sessionId=t??randomUUID().slice(0,12),this.corrId=randomUUID().slice(0,8),this.component=e}info(e,t={}){this.emit(`info`,e,t)}warn(e,t={}){this.emit(`warn`,e,t)}error(e,t,s={}){let g=t?{error:t instanceof Error?t.message:String(t),...s}:s;this.emit(`error`,e,g)}debug(e,t={}){(process.env.MCP_DEBUG===`1`||process.env.DEBUG?.includes(`mcp`))&&this.emit(`debug`,e,t)}child(t){return new e(t??this.component,this.sessionId)}asCallback(){return e=>this.info(e)}emit(e,t,s){let g={ts:new Date().toISOString(),level:e,sessionId:this.sessionId,corrId:this.corrId,component:this.component,msg:t,...s},S=`${JSON.stringify(g)}\n`;process.stderr.write(S);let w=process.env.OK_LOG_FILE;if(w)try{appendFileSync(w,S)}catch(e){console.warn(`[mcp-logger] Failed to write to OK_LOG_FILE: ${e instanceof Error?e.message:e}`)}}};function runWithMcpLogger(e,t){return loggerContext.run(e,t)}function getCurrentMcpLogger(){return loggerContext.getStore()}const REDACTED_STRING_KEYS=new Set([`find`,`markdown`,`replace`]),COMMON_ARRAY_KEYS=[`backlinks`,`deadLinks`,`documents`,`enrichedPaths`,`entries`,`forwardLinks`,`hints`,`hubs`,`orphans`,`results`],COMMON_SCALAR_KEYS=[`checkpointRef`,`cwd`,`fileCount`,`matchCount`,`ok`,`query`,`stdoutTruncated`,`truncated`];function isPlainObject(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function isToolExtraLike(e){return isPlainObject(e)&&`requestId`in e}function summarizeStringForLog(e,t){if(REDACTED_STRING_KEYS.has(e))return{redacted:!0,type:`string`,length:t.length,lines:t.length===0?0:t.split(`
1959
1959
  `).length};let s=e===`command`?240:120;return t.length<=s?t:{type:`string`,length:t.length,preview:`${t.slice(0,s)}...`}}function summarizeArgValue(e,t){if(t===null)return null;if(typeof t==`string`)return summarizeStringForLog(e,t);if(typeof t==`number`||typeof t==`boolean`)return t;if(Array.isArray(t))return{type:`array`,length:t.length};if(isPlainObject(t)){let e=Object.keys(t).sort();return{type:`object`,keyCount:e.length,keys:e.slice(0,12)}}if(t!==void 0)return{type:typeof t}}function summarizeArgsForLog(e,t){return isPlainObject(t)?Object.fromEntries(Object.entries(t).map(([e,t])=>[e,summarizeArgValue(e,t)])):summarizeArgValue(e,t)}function summarizeStructuredContentForLog(e){let t={structuredKeys:Object.keys(e).sort()};for(let s of COMMON_SCALAR_KEYS)s in e&&(t[s]=e[s]);for(let s of COMMON_ARRAY_KEYS){let g=e[s];Array.isArray(g)&&(t[`${s}Count`]=g.length)}return`previewUrl`in e&&(t.previewUrl=e.previewUrl??null),`previewUrlSource`in e&&(t.previewUrlSource=e.previewUrlSource),typeof e.stdout==`string`&&(t.stdoutChars=e.stdout.length),Array.isArray(e.warnings)&&(t.warningsCount=e.warnings.length),isPlainObject(e.warning)&&(t.warning=!0,`previewUrl`in e.warning&&(t.warningPreviewUrl=e.warning.previewUrl??null)),t}function summarizeToolResultForLog(e){if(!isPlainObject(e))return{resultType:typeof e};let t={isError:e.isError===!0};return Array.isArray(e.content)&&(t.contentItems=e.content.length,t.contentTextChars=e.content.reduce((e,t)=>isPlainObject(t)&&typeof t.text==`string`?e+t.text.length:e,0)),isPlainObject(e.structuredContent)&&Object.assign(t,summarizeStructuredContentForLog(e.structuredContent)),t}function summarizeIdentityForLog(e){return{connectionId:e.connectionId.slice(0,8),displayName:e.displayName,...e.clientInfo?.name?{clientName:e.clientInfo.name}:{}}}function splitInvocationArgs(e){let t=e.at(-1);return isToolExtraLike(t)?{toolArgs:e.length>1?e[0]:void 0,extra:t}:{toolArgs:e[0],extra:void 0}}function wrapToolHandlerForLogging(e,t,s){let g=s.logger;return g?async(...S)=>{let w=g.child(),E=Date.now(),{toolArgs:D,extra:O}=splitInvocationArgs(S);w.info(`tool start`,{tool:e,...O?.requestId===void 0?{}:{requestId:O.requestId},...O?.sessionId?{transportSessionId:O.sessionId}:{},...s.identityRef?.current?{agent:summarizeIdentityForLog(s.identityRef.current)}:{},...D===void 0?{}:{args:summarizeArgsForLog(e,D)}});try{let s=await runWithMcpLogger(w,async()=>await t(...S));return w.info(`tool finish`,{tool:e,...O?.requestId===void 0?{}:{requestId:O.requestId},durationMs:Date.now()-E,result:summarizeToolResultForLog(s)}),s}catch(t){throw w.error(`tool error`,t,{tool:e,...O?.requestId===void 0?{}:{requestId:O.requestId},durationMs:Date.now()-E}),t}}:t}function createLoggedServer(e,t){if(!t.logger)return e;let s=e.tool.bind(e),g=e.registerTool,S=typeof g==`function`?g.bind(e):void 0,w=Object.create(e);return w.tool=((...e)=>{let g=String(e[0]),S=e.at(-1);if(typeof S!=`function`)return s(...e);let w=[...e];return w[w.length-1]=wrapToolHandlerForLogging(g,S,t),s(...w)}),S&&(w.registerTool=((e,s,g)=>typeof g==`function`?S(e,s,wrapToolHandlerForLogging(e,g,t)):S(e,s,g))),w}function buildBody$2(e,t){return`Promote existing research on this topic into a canonical article inside the project content directory. **Canonical, not provisional** — the output is the source of truth for future agents.
1960
1960
 
1961
1961
  Topic: ${e}
@@ -2459,8 +2459,8 @@ $$`,guidance:"Write LaTeX in `$…$` (inline) or `$$…$$` (block) — OK auto-p
2459
2459
  `),InputSchema$3={ids:array(string().min(1)).max(ID_CARDINALITY_CAP).describe(`Array of canonical ids to fetch. Max ${ID_CARDINALITY_CAP} ids per call. Empty array returns an empty components list.`),cwd:string().optional().describe(ROUTED_CWD_DESCRIPTION)},ParamSchema=object$1({name:string(),type:_enum([`string`,`boolean`,`number`,`enum`,`reactnode`]),values:array(string()).optional(),required:boolean(),defaultValue:union([string(),boolean(),number()]).optional(),description:string().optional(),omitOnDefault:literal(!0).optional(),advanced:literal(!0).optional(),language:_enum([`mermaid`,`latex`,`html`,`json`,`yaml`,`javascript`,`markdown`]).optional(),accept:array(string()).optional()}),ComponentEntrySchema=object$1({id:string(),displayName:string(),description:string(),kind:_enum([`jsx-block`,`jsx-void`]),example:string(),params:array(ParamSchema)}),OutputSchema$7=outputSchemaWithText({version:literal(1).describe(`Schema version stamp — bump for breaking shape changes.`),components:array(ComponentEntrySchema).describe(`Full per-entry details for ids that matched.`),notFound:array(string()).describe(`Ids that did not match any canonical descriptor.`)});function register$14(e,t){e.registerTool(`get_components`,{description:DESCRIPTION$14,inputSchema:InputSchema$3,outputSchema:OutputSchema$7,annotations:{readOnlyHint:!0,idempotentHint:!0}},async e=>{e.cwd;let t=getAgentCanonicalDescriptors(),s=new Map(t.map(e=>[e.name,e])),g=[],S=[],w=new Set;for(let t of e.ids){if(w.has(t))continue;w.add(t);let e=s.get(t);if(e===void 0){S.push(t);continue}g.push(projectFull(e))}let E={version:1,components:g,notFound:S};return textPlusStructured(JSON.stringify(E,null,2),E)})}const DESCRIPTION$13=[`[Operates on disk; no running OK server required] Read the effective merged Open Knowledge config (defaults → user → project).`,``,`Use this when you need to inspect the config mid-session — e.g., after a write that may have changed disk state, or to re-confirm the value of a field before reading it again.`,``,"Read returns the FULL merged config or a sub-tree when `path` is provided. There is no allowlist on reads — every field is readable.",``,"Note: the `server.*`, `mcp.*`, `github.*`, and `preview.*` config sub-trees were removed; their values are now built-in constants in `@inkeep/open-knowledge-core` (or hardcoded behavior, in the case of `preview.*`). Reading those paths returns `exists: false`.",``,`**Parameters:**`,'- `path` (optional) — Dotted-segments array. `["content"]` returns the content sub-tree; `["appearance", "theme"]` returns just that leaf. Omit for full config.',"- `cwd` (optional) — Project root (see `cwd` description below)."].join(`
2460
2460
  `),InputSchema$2={path:array(string()).optional().describe(`Dotted path as array of segments (e.g. ["appearance","theme"]). Omit to return the full merged config.`),cwd:string().optional().describe(ROUTED_CWD_DESCRIPTION)},OutputSchema$6=outputSchemaWithText({value:unknown().describe(`Resolved config value at the requested path (or full config).`),exists:boolean().optional().describe('Whether the requested path resolved to a value. `false` distinguishes "path absent" from "path explicitly set to null"; absent on full-config reads.'),path:array(string()).optional().describe(`Echo of the requested dotted path (empty when reading the full config).`)});function readConfigPath(e,t){let s=e;for(let e of t){if(typeof s!=`object`||!s)return;s=s[e]}return s}function register$13(e,t){e.registerTool(`get_config`,{description:DESCRIPTION$13,inputSchema:InputSchema$2,outputSchema:OutputSchema$6,annotations:{readOnlyHint:!0,idempotentHint:!0}},async e=>{let s=await resolveProjectConfigContext(t.resolveCwd,t.config,e.cwd);if(!s.ok)return{isError:!0,content:[{type:`text`,text:`Error: ${s.error}`}]};let g=e.path??[],S=g.length>0?readConfigPath(s.config,g):s.config;return g.length>0&&S===void 0?textPlusStructured(`(no value at ${g.join(`.`)})`,{value:null,exists:!1,path:g}):textPlusStructured(JSON.stringify(S,null,2),{value:S,exists:!0,path:g})})}const DESCRIPTION$12=[`[Requires: Hocuspocus server] Fetch the three merge stages (base / ours / theirs) for a doc currently in a merge-conflict state, plus the doc's lifecycle status and the conflict shape discriminator.`,`Returns 404 if no conflict is tracked for the path.`,"The `ours` field is sourced from the live Y.Text (showing any pre-conflict unflushed user edits) when the doc is loaded server-side; falls back to `git show :2:<file>` otherwise.","The `kind` field discriminates conflict shape: `both-modified` (both sides edited the file), `delete-modify` (DU — you deleted, they edited; stage 2 absent, `ours` empty), or `modify-delete` (UD — you edited, they deleted; stage 3 absent, `theirs` empty). Use it to pick the right `resolve_conflict` strategy: both-modified accepts `mine`/`theirs`/`content`; delete-modify accepts `delete` (keep deletion) or `theirs` (restore); modify-delete accepts `mine` (keep your version) or `delete` (accept their deletion).",``,`**Parameters:**`,"- `file` — Relative-to-projectDir path WITH the `.md` extension (e.g. `notes/sso.md`). Mirrors the server-side wire contract."].join(`
2461
2461
  `),OutputSchema$5=outputSchemaWithText({file:string(),base:string(),ours:string(),theirs:string(),kind:_enum([`both-modified`,`delete-modify`,`modify-delete`]),lifecycleStatus:string().nullable()});function register$12(e,t){e.registerTool(`get_conflict_content`,{description:DESCRIPTION$12,inputSchema:{file:string().min(1).describe("Relative-to-projectDir path WITH .md extension (e.g. `notes/sso.md`). Server-side contract — do NOT strip the extension."),cwd:string().optional().describe(ROUTED_CWD_DESCRIPTION)},outputSchema:OutputSchema$5,annotations:{readOnlyHint:!0,idempotentHint:!0}},async e=>{let s=await resolveProjectServerContext(t.resolveCwd,t.config,t.serverUrl,e.cwd);if(!s.ok)return textResult(`Error: ${s.error}`,!0);let{url:g}=s;if(!g)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let S=await httpGet(g,`/api/sync/conflict-content${`?file=${encodeURIComponent(e.file)}&source=ytext`}`);if(!S.ok){let e=S.error,t=typeof S.detail==`string`?S.detail:void 0;return textResult(`Error: ${t?`${e} — ${t}`:e}`,!0)}let w=S,E=typeof w.file==`string`?w.file:e.file,D=typeof w.base==`string`?w.base:``,O=typeof w.ours==`string`?w.ours:``,k=typeof w.theirs==`string`?w.theirs:``,j=w.kind===`delete-modify`||w.kind===`modify-delete`?w.kind:`both-modified`,F=typeof w.lifecycleStatus==`string`?w.lifecycleStatus:null,L={file:E,base:D,ours:O,theirs:k,kind:j,lifecycleStatus:F};return textPlusStructured(`Conflict stages for ${E} (kind: ${j})${F?` (lifecycle: ${F})`:``}:\n--- base ---\n${D}\n--- ours ---\n${O}\n--- theirs ---\n${k}`,L)})}const DESCRIPTION$11=[`[Requires: Hocuspocus server] List version history for a document.`,`Returns timeline entries from the shadow repo, sorted by timestamp descending.`,'Each entry includes a commit SHA that can be passed to `version({ action: "rollback" })`.',``,`**Parameters:**`,"- `docName` — Document name to query history for, typically without extension. A trailing `.md` or `.mdx` is stripped automatically.","- `branch` (optional) — Branch name (default: current branch)","- `limit` (optional) — Maximum entries to return (default 50, max 200)","- `offset` (optional) — Number of entries to skip for pagination (default 0)",'- `type` (optional) — Filter by entry type: "checkpoint", "upstream", or "wip"',"- `author` (optional) — Filter to entries by this author name or email","- `excludeAuthor` (optional) — Exclude entries by this author name or email"].join(`
2462
- `);function register$11(e,t){e.registerTool(`get_history`,{description:DESCRIPTION$11,inputSchema:{docName:string().describe(`Document name to query history for`),branch:string().optional().describe(`Branch name (default: current branch)`),limit:number().int().min(1).max(200).optional().describe(`Maximum entries to return (default 50, max 200)`),offset:number().int().min(0).optional().describe(`Number of entries to skip for pagination (default 0)`),type:_enum([`checkpoint`,`upstream`,`wip`]).optional().describe(`Filter by entry type`),author:string().optional().describe(`Filter to entries by this author name or email`),excludeAuthor:string().optional().describe(`Exclude entries by this author name or email`),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,url:S}=s;if(!S)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let w=normalizeDocName(e.docName);if(!w.ok)return textResult(w.error,!0);let E=new URLSearchParams;E.set(`docName`,w.docName),e.branch&&E.set(`branch`,e.branch),e.limit!=null&&E.set(`limit`,String(e.limit)),e.offset!=null&&E.set(`offset`,String(e.offset)),e.type&&E.set(`type`,e.type),e.author&&E.set(`author`,e.author),e.excludeAuthor&&E.set(`excludeAuthor`,e.excludeAuthor);let D=await httpGet(S,`/api/history?${E.toString()}`);if(!D.ok)return textResult(`Error: ${D.error}`,!0);let{ok:O,...k}=D,j=await resolvePreviewUrlForTool(w.docName,{config:t.config,resolveCwd:t.resolveCwd},g);return textPlusStructured(JSON.stringify(k,null,2),{...k,previewUrl:j?.url??null,...j?{previewUrlSource:j.source}:{}})})}const DESCRIPTION$10=[`[Operates on disk; no running OK server required] Resolve the browser-reachable preview URL for an Open Knowledge project (optionally for a specific doc).`,``,"Per-response `previewUrl` fields on read/write tools are ROUTE-ONLY (`/#/<doc>`, no host:port) — they identify which doc to preview, not a URL to open by itself. Call this tool to get the full, openable URL.",``,'Use this when YOUR host opens the URL itself: navigate your in-app browser to the returned `url`, or — only on a stdio host with no browser tool — `open` it in the system browser. Claude Code does NOT need this tool: it calls `preview_start("open-knowledge-ui")`, whose pane supplies its own origin.',``,"Returns `{ url, baseUrl, running: false }` and a recovery hint when no UI is running for the project (start one with `ok ui`).",``,`**Parameters:**`,"- `docName` (optional) — Extension-less doc path (e.g. `specs/foo/SPEC`). Omit for the UI root URL.","- `cwd` (optional) — Project root (see `cwd` description below)."].join(`
2463
- `),InputSchema$1={docName:string().optional().describe(`Extension-less doc path to resolve a preview URL for (e.g. "specs/foo/SPEC"). Omit to get the UI root URL.`),cwd:string().optional().describe(ROUTED_CWD_DESCRIPTION)},OutputSchema$4=outputSchemaWithText({url:string().nullable().describe("Browser-reachable URL — the UI base joined with the doc route when `docName` is given, else the UI root. `null` when no UI is running."),baseUrl:string().nullable().describe("Browser-reachable origin of the running UI (e.g. `http://localhost:5173`). `null` when no UI is running."),running:boolean().describe(`Whether a UI is running for the project.`),autoOpen:boolean().describe("User-scoped preview-auto-open preference (`appearance.preview.autoOpen`). When `true`, the agent should route the preview using capability-based routing (in-app browser if available, system browser as fallback). When `false`, the user is managing their own preview view (OK Desktop window, a browser tab they opened, etc.) — the agent must NOT open or refresh any preview UI, and should surface this URL only on direct user ask. Resolved fresh on every call; defaults to `true`.")}),NO_UI_MESSAGE='No UI is running for this project. Start one to see the preview: `ok ui` (terminal), `preview_start("open-knowledge-ui")` (Claude Code), or open the project in OK Electron.';function register$10(e,t){e.registerTool(`get_preview_url`,{description:DESCRIPTION$10,inputSchema:InputSchema$1,outputSchema:OutputSchema$4,annotations:{readOnlyHint:!0,idempotentHint:!0}},async e=>{let s=await resolveProjectConfigContext(t.resolveCwd,t.config,e.cwd);if(!s.ok)return{isError:!0,content:[{type:`text`,text:`Error: ${s.error}`}]};let{baseUrl:g}=resolveUiInfo({lockDir:resolveLockDir(s.cwd)}),S=s.config.appearance.preview.autoOpen;if(g===null)return textPlusStructured(NO_UI_MESSAGE,{url:null,baseUrl:null,running:!1,autoOpen:S});let w=e.docName?`${g}/#/${encodeDocName(e.docName)}`:g;return textPlusStructured(`Preview URL: ${w}`,{url:w,baseUrl:g,running:!0,autoOpen:S})})}function buildBody$1(e,t){return`Capture this external source into the project knowledge base as raw reference material. The KB is **closed-loop**: external sources are pulled INTO the knowledge base here so downstream docs cite local paths, never bare web URLs. This applies whether a user shared the source OR you fetched it yourself to ground a knowledge-base claim — agent-initiated fetches are not exempt. **Raw preservation only** — no summary, no analysis, no interpretation. Summarizing is the job of the \`research\` tool later.
2462
+ `);function register$11(e,t){e.registerTool(`get_history`,{description:DESCRIPTION$11,inputSchema:{docName:string().describe(`Document name to query history for`),branch:string().optional().describe(`Branch name (default: current branch)`),limit:number().int().min(1).max(200).optional().describe(`Maximum entries to return (default 50, max 200)`),offset:number().int().min(0).optional().describe(`Number of entries to skip for pagination (default 0)`),type:_enum([`checkpoint`,`upstream`,`wip`]).optional().describe(`Filter by entry type`),author:string().optional().describe(`Filter to entries by this author name or email`),excludeAuthor:string().optional().describe(`Exclude entries by this author name or email`),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,url:S}=s;if(!S)return textResult(HOCUSPOCUS_NOT_RUNNING_ERROR,!0);let w=normalizeDocName(e.docName);if(!w.ok)return textResult(w.error,!0);let E=new URLSearchParams;E.set(`docName`,w.docName),e.branch&&E.set(`branch`,e.branch),e.limit!=null&&E.set(`limit`,String(e.limit)),e.offset!=null&&E.set(`offset`,String(e.offset)),e.type&&E.set(`type`,e.type),e.author&&E.set(`author`,e.author),e.excludeAuthor&&E.set(`excludeAuthor`,e.excludeAuthor);let D=await httpGet(S,`/api/history?${E.toString()}`);if(!D.ok)return textResult(`Error: ${D.error}`,!0);let{ok:O,...k}=D,j=await resolvePreviewUrlForTool(w.docName,{config:t.config,resolveCwd:t.resolveCwd},g);return textPlusStructured(JSON.stringify(k,null,2),{...k,previewUrl:j?.url??null,...j?{previewUrlSource:j.source}:{}})})}const PANE_TARGET_FILE=`pane-target.json`,PANE_TARGET_TTL_MS=3e4;function armPaneTarget(e,t,s=Date.now()){if(!t.startsWith(`#/`))return!1;tracedMkdirSync(e,{recursive:!0});let g={route:t,armedAtMs:s};return tracedWriteFileSync(resolve(e,PANE_TARGET_FILE),JSON.stringify(g)),!0}function readArmedPaneTarget(e,t=Date.now(),s=PANE_TARGET_TTL_MS){let g=resolve(e,PANE_TARGET_FILE);if(!existsSync(g))return null;try{let e=JSON.parse(readFileSync(g,`utf-8`));return typeof e.route!=`string`||typeof e.armedAtMs!=`number`||t-e.armedAtMs>s?null:e.route}catch(e){let t=e.code;return(t===`EACCES`||t===`EPERM`||t===`EIO`)&&process.stderr.write(`[pane-target] readArmedPaneTarget failed at ${g}: ${e instanceof Error?e.message:String(e)}\n`),null}}function clearArmedPaneTarget(e){let t=resolve(e,PANE_TARGET_FILE);if(existsSync(t))try{tracedUnlinkSync(t)}catch{}}const DESCRIPTION$10=[`[Operates on disk; no running OK server required] Resolve the browser-reachable preview URL for an Open Knowledge project (optionally for a specific doc).`,``,"Per-response `previewUrl` fields on read/write tools are ROUTE-ONLY (`/#/<doc>`, no host:port) — they identify which doc to preview, not a URL to open by itself. Call this tool to get the full, openable URL.",``,'Use this when YOUR host opens the URL itself: navigate your in-app browser to the returned `url`, or — only on a stdio host with no browser tool — `open` it in the system browser. Claude Code does NOT need this tool: it calls `preview_start("open-knowledge-ui")`, whose pane supplies its own origin.',``,"Returns `{ url, baseUrl, running: false }` and a recovery hint when no UI is running for the project (start one with `ok ui`).",``,`**Parameters:**`,"- `docName` (optional) — Extension-less doc path (e.g. `specs/foo/SPEC`). Omit for the UI root URL.","- `folder` (optional) — Folder path (e.g. `specs/foo`); returns the `…/#/<folder>/` route. Mutually exclusive with `docName`.","- `armPaneTarget` (optional) — When true with a `docName`/`folder`, writes a small TTL-bounded (~30s) state file under `.ok/local/` so a later Claude-pane base-open lands on that target. This is the tool’s ONLY side effect; omit it and the call is read-only.","- `cwd` (optional) — Project root (see `cwd` description below)."].join(`
2463
+ `),InputSchema$1={docName:string().optional().describe(`Extension-less doc path to resolve a preview URL for (e.g. "specs/foo/SPEC"). Omit to get the UI root URL.`),folder:string().min(1).optional().describe('Folder path to resolve a folder-route preview URL for (e.g. "specs/foo"); returns the `…/#/<folder>/` route. Mutually exclusive with `docName`.'),armPaneTarget:boolean().optional().describe("When true with a `docName` or `folder`, arm that target so a subsequent Claude-pane base-open (`preview_start`) lands there instead of the presence-driven default. TTL-bounded (~30s) so a stale arm cannot hijack a later open."),cwd:string().optional().describe(ROUTED_CWD_DESCRIPTION)};function encodeFolderRoute(e){let t=e.replace(/^\/+|\/+$/g,``);return t?`${encodeDocName(t)}/`:``}const OutputSchema$4=outputSchemaWithText({url:string().nullable().describe("Browser-reachable URL — the UI base joined with the doc route when `docName` is given, else the UI root. `null` when no UI is running."),baseUrl:string().nullable().describe("Browser-reachable origin of the running UI (e.g. `http://localhost:5173`). `null` when no UI is running."),running:boolean().describe(`Whether a UI is running for the project.`),autoOpen:boolean().describe("User-scoped preview-auto-open preference (`appearance.preview.autoOpen`). When `true`, the agent should route the preview using capability-based routing (in-app browser if available, system browser as fallback). When `false`, the user is managing their own preview view (OK Desktop window, a browser tab they opened, etc.) — the agent must NOT open or refresh any preview UI, and should surface this URL only on direct user ask. Resolved fresh on every call; defaults to `true`.")}),NO_UI_MESSAGE='No UI is running for this project. Start one to see the preview: `ok ui` (terminal), `preview_start("open-knowledge-ui")` (Claude Code), or open the project in OK Electron.';function register$10(e,t){e.registerTool(`get_preview_url`,{description:DESCRIPTION$10,inputSchema:InputSchema$1,outputSchema:OutputSchema$4,annotations:{readOnlyHint:!1,idempotentHint:!0}},async e=>{if(e.docName&&e.folder)return{isError:!0,content:[{type:`text`,text:`Error: docName and folder are mutually exclusive — pass exactly one.`}]};let s=await resolveProjectConfigContext(t.resolveCwd,t.config,e.cwd);if(!s.ok)return{isError:!0,content:[{type:`text`,text:`Error: ${s.error}`}]};let g=resolveLockDir(s.cwd),{baseUrl:S}=resolveUiInfo({lockDir:g}),w=s.config.appearance.preview.autoOpen,E=e.docName?`#/${encodeDocName(e.docName)}`:e.folder?`#/${encodeFolderRoute(e.folder)}`:null;if(e.armPaneTarget&&E)try{armPaneTarget(g,E)}catch{}let D=e.armPaneTarget&&!E?` (note: armPaneTarget was set but no docName/folder was given, so nothing was armed)`:``;if(S===null)return textPlusStructured(`${NO_UI_MESSAGE}${D}`,{url:null,baseUrl:null,running:!1,autoOpen:w});let O=E?`${S}/${E}`:S;return textPlusStructured(`Preview URL: ${O}${D}`,{url:O,baseUrl:S,running:!0,autoOpen:w})})}function buildBody$1(e,t){return`Capture this external source into the project knowledge base as raw reference material. The KB is **closed-loop**: external sources are pulled INTO the knowledge base here so downstream docs cite local paths, never bare web URLs. This applies whether a user shared the source OR you fetched it yourself to ground a knowledge-base claim — agent-initiated fetches are not exempt. **Raw preservation only** — no summary, no analysis, no interpretation. Summarizing is the job of the \`research\` tool later.
2464
2464
 
2465
2465
  **Bias toward binary preservation.** When the source is a binary file (PDF, image, audio, video, Office doc, archive, dataset), preserve the raw bytes — do NOT settle for a text scrape. OK already ships a complete asset-embed surface (\`![[file.ext]]\` wiki-embed, file-watcher pickup, sha256 dedup, blocked-extension enforcement); this tool's job is to bridge \`ingest\` to it via your shell tool.
2466
2466
 
@@ -3080,5 +3080,5 @@ In headless mode, write the recap into the research article's "Further reading"
3080
3080
  `).split(`
3081
3081
  `),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(s);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=(e,s)=>{let g=ne.resolveEmbed(e,s);if(!g&&e.includes(`/`)&&(g=e.replace(/^\.?\//,``)),!g)return null;let S=resolve(t,g),w=resolve(t);if(S!==w&&!S.startsWith(`${w}/`))return null;try{let e=statSync(S);return e.isFile()?e.size:null}catch{return null}},se,ce,ue,de,fe,me,ge,_e=null,ve=null,ye=null,Ce=null,we=null,Te=new Set,De=!1,je,Me,Pe,Ie=new Promise((e,t)=>{Me=e,Pe=t});function Re(e){_e?.signal(e)}let ze=2e3,Be=null;function Ve(){Be!==null&&clearTimeout(Be),Be=setTimeout(()=>{Be=null,ce.saveToDisk().catch(e=>{console.warn(`[backlinks] Failed to persist debounced cache:`,e)})},2e3)}let Ue=new RecentlyRemovedDocs(void 0,{onEviction:()=>incrementRecentlyRemovedDocsEviction(),onSizeChange:e=>setRecentlyRemovedDocsSize(e)}),We=(e,t)=>{isSystemDoc(e)||isConfigDoc(e)||Ue.setRenamed(e,t)},Ge=e=>{if(!(isSystemDoc(e)||isConfigDoc(e))){if(Ue.peek(e)?.kind===`renamed`){console.info(JSON.stringify({event:`recently-removed-docs-unpaired-delete-suppressed`,docName:e,source:`watcher-delete`}));return}Ue.setDeleted(e)}},Ke=e=>{isSystemDoc(e)||isConfigDoc(e)||Ue.delete(e)};try{se=createContentFilter({projectDir:s,contentDir:t,onAfterRebuild:()=>{ce.rebuildFromDisk(getActiveBranch()).catch(e=>{getLogger(`server-factory`).warn({err:e},`[content-filter] backlink-index rebuild failed after onAfterRebuild`)});try{ue.init()}catch(e){getLogger(`server-factory`).warn({err:e},`[content-filter] tag-index rebuild failed after onAfterRebuild`)}try{let{prunedFiles:e,prunedFolders:t}=reconcileFileIndexAfterFilterRebuild(Lt),s=e+t;s>0?getLogger(`server-factory`).info({pruned:s,prunedFiles:e,prunedFolders:t},`[content-filter] reconciled file indexes after onAfterRebuild`):getLogger(`server-factory`).debug({prunedFiles:e,prunedFolders:t},`[content-filter] file index reconcile completed after onAfterRebuild (no entries pruned; rescan may have added entries)`)}catch(e){getLogger(`server-factory`).warn({err:e},`[content-filter] file index reconcile failed after onAfterRebuild`)}}}),ce=new BacklinkIndex({projectDir:s,contentDir:t,contentFilter:se}),ue=new TagIndex({contentDir:t,contentFilter:se});try{ue.init()}catch(e){console.warn(`[server-factory] tag-index init failed; continuing with empty index:`,e)}de={current:F},fe=createPersistenceExtension({contentDir:t,projectDir:s,gitEnabled:E,commitDebounceMs:D,wipRef:O,shadowRef:de,contentRoot:L,backlinkIndex:ce,configHomedirOverride:k,getCurrentBranch:()=>Rt?.getLastKnownBranch()??null,resolveEmbed:ae,resolveSize:oe,getPrincipal:()=>we,onAgentCommit:()=>_e?.signal(`session-activity`),onDiskFlush:(e,t,s,g)=>{_e?.emitDiskAck(e,t),!(isSystemDoc(e)||isConfigDoc(e))&&assetReferencesChanged(g,s)&&(Ce?.(),Re(`files`))},onConfigRejected:(e,t)=>_e?.emitConfigValidationRejected(e,t),mdManager:e.mdManager}),me=new Hocuspocus({quiet:g,debounce:S,maxDebounce:w,extensions:[fe.extension]});let B=me.shouldUnloadDocument.bind(me);me.shouldUnloadDocument=e=>{if(Te.has(e)||De&&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)},je=async e=>{Te.add(e);try{await me.unloadDocument(e)}finally{Te.delete(e)}},_e=new CC1Broadcaster(me),ve=new AgentFocusBroadcaster(me),ye=new AgentPresenceBroadcaster(me),ge=new AgentSessionManager(me);let q=createLiveDerivedIndexExtension({backlinkIndex:ce,tagIndex:ue,signalChannel:Re});me.configuration.extensions.push(q),me.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`&&(we&&s.principalId===we.id?E.principalId=we.id:we?console.warn(JSON.stringify({event:`principal-token-mismatch`,claimed:s.principalId,loaded:we.id})):E.principalId=s.principalId),typeof s.tabSessionId==`string`&&(E.tabSessionId=s.tabSessionId),E.kind=`human`}}),me.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})`)}});let J=resolve(t);function Y(e){if(!isSafeDocName(e))return null;let t=resolve(J,`${e}${getDocExtension(e)}`);return!t.startsWith(`${J}/`)&&t!==J?null:t}me.configuration.extensions.push({__kind:`removal-redirect-guard`,async onAuthenticate(e){await runRemovalRedirectGuard(e.documentName,{recentlyRemovedDocs:Ue,resolveFilePath:Y,fileExists:existsSync})}}),me.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 te=createApiExtension({hocuspocus:me,sessionManager:ge,contentDir:t,contentFilter:se,serverInstanceId:ee,getFileIndex:()=>Lt?Lt.getFileIndex():new Map,getFolderIndex:()=>Lt?Lt.getFolderIndex():new Map,getAliasMap:()=>Lt?Lt.getAliasMap():new Map,rescanFiles:()=>Lt?.rescanFromDisk(),enableTestRoutes:j,shadowRef:de,flushGitCommit:()=>fe.flushPendingGitCommit(),flushContributors:()=>fe.flushContributors(),getCurrentBranch:()=>Rt?.getLastKnownBranch()??null,getDiskAckSVs:()=>_e?.getLatestDiskAckSVsAsBase64()??{},contentRoot:L,backlinkIndex:ce,tagIndex:ue,signalChannel:Re,agentFocusBroadcaster:ve,agentPresenceBroadcaster:ye,onAgentWrite:e.onAgentWrite,getSyncEngine:()=>zt,localOpCliArgs:H,projectDir:s,resolveEmbed:ae,getPrincipal:()=>we,forceUnloadDocument:je,ready:Ie,recentlyRemovedDocs:Ue,serializeDoc:it,onReferencedAssetsCacheInvalidator:e=>{Ce=e}});me.configuration.extensions.push(te),me.configuration.extensions.push(createServerObserverExtension({mdManager,schema,shadowRef:de,contentRoot:L,getCurrentBranch:()=>Rt?.getLastKnownBranch()??null,resolveEmbed:ae,resolveSize:oe})),me.configuration.extensions.push(createSyncHandshakeSpanExtension()),me.configuration.extensions.push(createConflictLifecycleSeedExtension({getSyncEngine:()=>zt,projectDir:s,contentDir:t}))}catch(e){throw releaseServerLock(te),e}let Xe=null,$e=new Map,nt=[];function rt(e,t){let s=resolve(e,`rescue`),g=resolve(s,`${t}${getDocExtension(t)}`);return g.startsWith(`${s}/`)?g:null}function it(e){let t=me.documents.get(e);if(!t)return null;let{frontmatter:s,body:g}=stripFrontmatter(t.getText(`source`).toString());return prependFrontmatter(s,g)}let at=(e,t)=>applyExternalChange(me,e,t,ae,oe);function st(e){if(!isDocInConflict(e))return;let t=e.getMap(`lifecycle`);t.delete(`status`),t.delete(`reason`)}let vt=e=>{if(!e)return;let t=`[[${e}]]`;for(let[s]of me.documents){if(isSystemDoc(s)||isConfigDoc(s))continue;let g=me.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}`)}}},Tt=null,Et=e=>{e&&(Tt===null&&(Tt=new Set,setImmediate(()=>{let e=Tt;if(Tt=null,e)try{for(let t of e)vt(t)}catch(t){J.error({err:t,basenames:[...e]},`[asset-event] dedup rerender pass crashed`)}})),Tt.add(e))};function Dt(e){switch(e.kind){case`rename`:return e.newDocName;case`asset-create`:case`asset-delete`:case`folder-create`:case`folder-delete`:return e.relativePath;case`create`:case`update`:case`delete`:case`conflict`:return e.docName;default:return assertNeverDiskEvent(e)}}async function jt(e){try{switch(e.kind){case`create`:J.info({docName:e.docName},`[reconcile] create: ${e.docName}`),ce.updateDocumentFromMarkdown(e.docName,e.content),Ve(),ue.updateDocumentFromMarkdown(e.docName,e.content),Re(`files`),Re(`backlinks`),Re(`graph`),Re(`tags`),Ke(e.docName);break;case`update`:{let{docName:t,content:s}=e,g=me.documents.get(t);if(!g){ce.updateDocumentFromMarkdown(t,s),Ve(),ue.updateDocumentFromMarkdown(t,s),Re(`backlinks`),Re(`graph`),Re(`tags`);return}let S=getReconciledBase(t)??``,w=it(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`:st(g),ce.updateDocumentFromMarkdown(t,s),Ve(),ue.updateDocumentFromMarkdown(t,s),Re(`backlinks`),Re(`graph`),Re(`tags`);break;case`clean`:try{at(t,E.newContent),setReconciledBase(t,E.newContent),incrementReconcile(),st(g),ce.updateDocumentFromMarkdown(t,s),Ve(),ue.updateDocumentFromMarkdown(t,s),Re(`backlinks`),Re(`graph`),Re(`tags`)}catch(e){J.error({err:e,docName:t},`[reconcile] failed to apply clean content to Y.Doc for ${t}`),setReconciledBase(t,s),st(g)}break;case`merged`:try{at(t,E.newContent),setReconciledBase(t,E.newContent),incrementReconcile(),st(g),ce.updateDocumentFromMarkdown(t,s),Ve(),ue.updateDocumentFromMarkdown(t,s),Re(`backlinks`),Re(`graph`),Re(`tags`)}catch(e){J.error({err:e,docName:t},`[reconcile] failed to apply merged content to Y.Doc for ${t}`),setReconciledBase(t,s),st(g)}break;case`conflicts`:try{at(t,E.newContent),setReconciledBase(t,E.newContent),incrementReconcile(),incrementConflict(),ce.updateDocumentFromMarkdown(t,s),Ve(),ue.updateDocumentFromMarkdown(t,s),Re(`backlinks`),Re(`graph`),Re(`tags`)}catch(e){J.error({err:e,docName:t},`[reconcile] failed to apply conflict content to Y.Doc for ${t}`),setReconciledBase(t,s)}{let e=g.getMap(`lifecycle`);e.set(`status`,`conflict`),e.set(`reason`,`merged-with-markers`)}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=me.documents.get(t);if(!s){ce.deleteDocument(t),Ve(),ue.deleteDocument(t),Re(`files`),Re(`backlinks`),Re(`graph`),Re(`tags`),Ge(t),console.info(JSON.stringify({event:`recently-removed-docs-populate`,docName:t,kind:`deleted`,source:`watcher-delete`}));return}let g=getReconciledBase(t)??``,S=it(t)??``,w=S!==g;if(w&&de.current){let e=de.current,s=Rt?.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),ce.deleteDocument(t),Ve(),ue.deleteDocument(t),J.info({docName:t,isDirty:w},`[reconcile] delete: ${t} (dirty=${w})`),me.closeConnections(t),await je(s),Re(`files`),Re(`backlinks`),Re(`graph`),Re(`tags`),Ge(t),console.info(JSON.stringify({event:`recently-removed-docs-populate`,docName:t,kind:`deleted`,source:`watcher-delete`}));break}case`rename`:{let{oldDocName:t,newDocName:s,content:g}=e,S=me.documents.get(t);if(deleteReconciledBase(t),setReconciledBase(s,g),ce.renameDocument(t,s,g),Ve(),ue.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}`),Re(`files`),Re(`backlinks`),Re(`graph`),Re(`tags`),We(t,s),console.info(JSON.stringify({event:`recently-removed-docs-populate`,from:t,to:s,kind:`renamed`,source:`watcher-rename`}));break}case`conflict`:{let{docName:t}=e,s=me.documents.get(t);if(!s)return;let g=it(t);g===null?J.warn({docName:t},`[reconcile] case 'conflict': serializeDoc returned null for ${t}; reconciledBase snapshot skipped — post-resolution reconcile may degrade to 3-way merge`):setReconciledBase(t,g);let S=s.getMap(`lifecycle`);S.set(`status`,`conflict`),S.set(`reason`,`conflict-markers`),J.info({docName:t},`[reconcile] conflict markers detected: ${t}`);break}case`asset-create`:ne.add(e.relativePath),Re(`files`),Et(basename(e.relativePath));break;case`asset-delete`:ne.remove(e.relativePath),Re(`files`),Et(basename(e.relativePath));break;case`folder-create`:case`folder-delete`:Re(`files`);break;default:assertNeverDiskEvent(e)}}catch(t){let s=Dt(e);J.error({err:t,kind:e.kind,label:s},`[reconcile] failed to handle ${e.kind} for ${s}`)}}let Mt=[];async function Ft(e){if(isBatchInProgress()){Mt.push(e);return}await jt(e)}async function It(){let e=Mt.splice(0,Mt.length);for(let t of e)await jt(t)}let Lt=null,Rt=null,zt=null,Bt=null;async function Vt(e){if(me.documents.size===0)return;let t=!1,s=new Promise(e=>{me.configuration.extensions.push({async afterUnloadDocument({instance:s}){!t&&s.getDocumentsCount()===0&&(t=!0,e())}})}),g=Array.from(me.documents.keys());me.closeConnections(),me.flushPendingStores();for(let e of me.documents.values())e.getConnectionsCount()===0&&me.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(me.documents.keys()),S=[],E=[];if(de.current){for(let e of s)if(!(isSystemDoc(e)||isConfigDoc(e)))try{let t=it(e);if(t===null){J.warn({docName:e},`[rescue] skipping ${e} — document dropped from map mid-rescue`),E.push(e);continue}let s=rt(de.current.gitDir,e);if(!s){J.warn({docName:e,gitDir:de.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 Ht(){return Bt||(Bt=(async()=>{let e=Date.now(),t=[];De=!0,Be!==null&&(clearTimeout(Be),Be=null);let g,S=await Promise.race([Ie.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=me.documents.size;try{try{try{Rt&&=(await Rt.unsubscribe(),null),Lt&&=(await Lt.unsubscribe(),null);for(let{docName:e,cleanup:t}of nt)try{await t()}catch(t){J.warn({err:t,docName:e},`[server] failed to stop config-file-watcher for ${e}`)}nt.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{_e?.destroy(),ye?.destroy(),Xe&&=(await Xe.disconnect(),null);for(let[e,t]of $e)try{await t.disconnect()}catch(t){J.warn({err:t,docName:e},`[server] failed to disconnect ${e} during shutdown`)}$e.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 ge.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 Vt(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 fe.flushPendingGitCommit(),await fe.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{zt&&=(await zt.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(de.current){try{let e=(await esm_default({baseDir:s,timeout:{block:5e3}}).revparse(`HEAD`)).trim();e&&writeFileSync(resolve(de.current.gitDir,`last-known-head`),e,`utf-8`)}catch{}try{destroyShadowRepo(de.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)})}}})(),Bt)}let Ut=[];async function Wt(){try{we=await loadPrincipal(s),J.info({principalId:we.id},`[server] principal loaded`)}catch(e){J.warn({err:e},`[server] principal load failed — browser writes will use SERVICE_WRITER`)}if(!de.current)try{de.current=await initShadowRepo(s),J.info({gitDir:de.current.gitDir},`[server] history repo initialized at ${de.current.gitDir}`)}catch(e){J.error({err:e},`[server] history repo init failed`),Ut.push(`shadow-repo`)}if(de.current){let e=null;try{e=loadRenameLogIndex(de.current.gitDir),sweepLazyPopOrphans(de.current.gitDir,e),setRenameLogIndex(de.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(de.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(de.current)try{await shadowGit(de.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{de.current=await initShadowRepo(s)}catch(e){J.error({err:e},`[server] history repo reinit failed`),de.current=void 0,Ut.includes(`shadow-repo`)||Ut.push(`shadow-repo`)}}else J.error({err:e},`[server] history repo check failed (transient?)`)}if(de.current)try{let e=resolve(de.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(de.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,s);if(e.recovered&&e.journal){let t=e.journal.version===2?e.journal.fromPath:e.journal.sourceDocName,s=e.journal.version===2?e.journal.toPath:e.journal.destinationDocName;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`),Ut.push(`managed-rename-recovery`)}try{let e=cleanupOrphanUploadTempfiles(s);(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`),Ut.push(`upload-tempfile-sweep`)}try{Xe=await me.openDirectConnection(SYSTEM_DOC_NAME),_e?.emitServerInfo(ee,getActiveBranch())}catch(e){J.error({err:e},`[server] failed to open __system__ direct connection — CC1 push disabled`),Ut.push(`cc1-push`)}for(let e of CONFIG_DOC_NAMES)try{let t=await me.openDirectConnection(e);$e.set(e,t)}catch(t){J.error({err:t,docName:e},`[server] failed to open ${e} direct connection — config bind degraded`),Ut.push(`config-doc:${e}`)}let g=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 e of CONFIG_DOC_NAMES){let t=g.get(e);if(t)try{J.info({docName:e,path:t},`[config-file-watcher] starting`);let s=await startConfigFileWatcher(t,t=>{let s=me.documents.get(e);J.info({docName:e,hasDocument:s!==void 0,contentLength:t.length},`[config-file-watcher] file changed`);let g=applyExternalConfigChange(s??null,e,t,fe.configPersistenceCtx);if(J.info({docName:e,outcome:g},`[config-file-watcher] applyExternalConfigChange outcome`),e===`__config__/project`||e===`__local__/project`){let e=Y();zt?.setEnabled(e).catch(t=>{J.warn({err:t,enabled:e},`[sync] failed to apply autoSync.enabled from config`)})}});nt.push({docName:e,cleanup:s}),J.info({docName:e,path:t},`[config-file-watcher] started`)}catch(s){J.warn({err:s,docName:e,path:t},`[config-file-watcher] failed to start for ${e}`),Ut.push(`config-file-watcher:${e}`)}}try{let e=resolve(t,`.okignore`),g=resolve(s,`.gitignore`),S=null;try{let e=spawnSync(`git`,[`rev-parse`,`--git-common-dir`],{cwd:s,encoding:`utf-8`,timeout:5e3});if(e.status===0&&e.stdout){let t=join(resolve(s,e.stdout.trim()),`info`,`exclude`);existsSync(dirname(t))&&(S=t)}}catch{}let w=S?[e,g,S]:[e,g],E=J;E.info({okignorePath:e,gitignorePath:g,gitInfoExcludePath:S},`[ignore-watcher] starting multi-path watcher for .okignore + .gitignore (+ .git/info/exclude when present)`);let D=await startMultiPathConfigFileWatcher(w,(t,g)=>{(async()=>{if(t===e)try{let e=applyExternalConfigChange(me.documents.get(`__config__/okignore`)??null,CONFIG_DOC_NAME_OKIGNORE,g,fe.configPersistenceCtx);E.info({docName:CONFIG_DOC_NAME_OKIGNORE,outcome:e},`[ignore-watcher] applyExternalConfigChange outcome`)}catch(e){E.error({err:e,changedPath:relative(s,t)},`[ignore-watcher] applyExternalConfigChange failed; rebuild proceeds independently`)}let S=await se.rebuildIgnorePatterns();if(S.ok)E.info({changedPath:relative(s,t),patternCount:S.patternCount,nestedFileCount:S.nestedFileCount,durationMs:S.durationMs},`[ignore-watcher] rebuild succeeded — broadcasting files channel`),_e?.signal(`files`);else{let e=relative(s,t)||`.`;E.warn({changedPath:e,error:S.error.message},`[ignore-watcher] rebuild failed — emitting config-ignore-nested-error`),_e?.emitConfigIgnoreNestedError(e,S.error.message)}})().catch(e=>{E.error({err:e,changedPath:relative(s,t)||`.`},`[ignore-watcher] handler threw`)})});nt.push({docName:`__ignore-files__`,cleanup:D}),E.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`),Ut.push(`ignore-files-watcher`)}let S=resolveGitDir(s),w=S?readBranchFromHead(S)??`main`:`main`;switchReconciledBaseScope(w),ce.switchBranch(w);try{{let e=getActiveBranch();try{if(await ce.loadFromDisk(e)){let t=await ce.reconcileWithDisk(e);(t.added>0||t.updated>0||t.deleted>0)&&J.info(t,`[backlinks] startup reconcile: offline changes applied`)}else await ce.rebuildFromDisk(e);ce.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`)}}Lt=await startWatcher(t,Ft,se),ue.init();let e=0;try{seedBasenameIndex({contentDir:t,contentFilter:se,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`),Ut.push(`basename-index-partial`))}catch(e){J.error({err:e},`[basename-index] startup seed failed`),Ut.push(`basename-index`)}}catch(e){J.error({err:e},`[server] disk bridge watcher failed to start`),Ut.push(`file-watcher`)}try{Rt=await startHeadWatcher(s,async({trigger:e})=>{if(J.info({trigger:e},`[batch] begin trigger=${e}`),incrementBatch(),me.flushPendingStores(),await fe.flushPendingGitCommit(),setBatchInProgress(!0),de.current){let e=getActiveBranch(),t=resolveGitDir(s),g=t?readBranchFromHead(t)??e:e,S=[];for(let[e,t]of me.documents){if(isSystemDoc(e)||isConfigDoc(e))continue;let s=null;if(t.transact(()=>{s=it(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(de.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=Mt.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`){if(setBatchInProgress(!1),await It(),await fe.flushDeferredStores(`within-branch`),zt!==null)try{await zt.reconcileConflictsFromGit()}catch(e){J.warn({err:e},`[head-watcher] sync engine conflict reconcile failed`)}}else{incrementBranchSwitch(),Mt.splice(0,Mt.length),switchReconciledBaseScope(g),Be!==null&&(clearTimeout(Be),Be=null),ce.switchBranch(g),se.rebuildDirCount();try{let e=0;ne.clear(),seedBasenameIndex({contentDir:t,contentFilter:se,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`),Ut.includes(`basename-index-partial`)||Ut.push(`basename-index-partial`))}catch(e){J.error({err:e,branch:g},`[basename-index] branch-switch reseed failed`)}for(let[e,s]of me.documents)if(!(isSystemDoc(e)||isConfigDoc(e)))try{let S=safeContentPath(e,t);if(!existsSync(S)){let t=getReconciledBase(e)??``,S=it(e)??``;if(S!==t&&de.current){let t=de.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`);at(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:me.documents.size},`[branch-switch] loaded branch ${g} (${me.documents.size} docs)`);try{if(await ce.loadFromDisk(g)){let e=await ce.reconcileWithDisk(g);(e.added>0||e.updated>0||e.deleted>0)&&J.info(e,`[backlinks] branch-switch reconcile for ${g}`)}else await ce.rebuildFromDisk(g);ce.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(ue.init(),de.current&&e.batchKind===`cross-branch`){let e=0;for(let[t]of me.documents)if(!(isSystemDoc(t)||isConfigDoc(t)))try{let s=await readParkedState(de.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`:at(t,w.newContent),setReconciledBase(t,w.newContent),e++;break;case`conflicts`:at(t,w.newContent),setReconciledBase(t,w.newContent),incrementConflict(),e++;{let e=me.documents.get(t);if(e){let t=e.getMap(`lifecycle`);t.set(`status`,`conflict`),t.set(`reason`,`merged-with-markers`)}}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-`)&&de.current)try{let t=shadowGit(de.current),s=(await t.raw(`for-each-ref`,`refs/wip/${e.oldBranch}/`,`--format=%(refname)`)).trim();if(s){for(let e of s.split(`
3082
3082
  `))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 fe.flushDeferredStores(`discard-stale`),_e?.emitBranchSwitched(g)}if(e.headMoved&&e.newHead&&de.current&&s>0){let t=L??`.`;try{let s=await commitUpstreamImport(de.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`),Ut.push(`head-watcher`)}function E(e){for(let g of e)try{let e=relative(t,join(s,g));if(e.startsWith(`..`))continue;let S=stripDocExtension(e),w=me.documents.get(S);if(!w)continue;let E=it(S);E===null?J.warn({docName:S,file:g},`[sync] content conflict: serializeDoc returned null; reconciledBase snapshot skipped`):setReconciledBase(S,E);let D=w.getMap(`lifecycle`);D.set(`status`,`conflict`),D.set(`reason`,`sync-merge-conflict`),J.info({docName:S,file:g},`[sync] marked loaded content conflict`)}catch(e){J.warn({err:e,file:g},`[sync] failed to mark loaded content conflict`)}}let D=H?.[0]??`open-knowledge`,O=[`-c`,`credential.helper=!${H&&H.length>1?H.join(` `):D} auth git-credential`];try{zt=new SyncEngine({projectDir:s,contentDir:t,contentFilter:se,contentRoot:L,syncEnabled:Y(),credentialArgs:O,cc1Broadcaster:_e,detectGh:e.detectGh,tokenStore:e.tokenStore,checkPushPermissionFn:e.checkPushPermissionFn,setBatchInProgress:e=>{setBatchInProgress(e),e||fe.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}`)},onContentConflictsDetected: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 zt.start()}catch(e){J.warn({err:e},`[server] SyncEngine failed to start — sync disabled`),zt=null}Re(`files`),Re(`backlinks`),Re(`graph`),Re(`tags`)}return Wt().then(Me,Pe),{hocuspocus:me,sessionManager:ge,cc1Broadcaster:_e,agentFocusBroadcaster:ve,agentPresenceBroadcaster:ye,contentFilter:se,basenameIndex:ne,serverInstanceId:ee,destroy:Ht,ready:Ie,degraded:Ut,lockDir:te,get syncEngine(){return zt}}}const LEGACY_RUNTIME_FILENAMES=[`server.lock`,`ui.lock`,`state.json`,`principal.json`,`sync-state.json`,`conflicts.json`,`last-spawn-error.log`],LEGACY_RUNTIME_DIRNAMES=[`cache`,`tmp`];function findLegacyRuntimeFiles(e){let t=resolve(e,LOCAL_DIR);if(!(()=>{if(!existsSync(t))return!0;try{return readdirSync(t).length===0}catch{return!0}})())return[];let s=[];for(let t of LEGACY_RUNTIME_FILENAMES)existsSync(resolve(e,t))&&s.push(t);for(let t of LEGACY_RUNTIME_DIRNAMES){let 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){let t=resolveLocalSinkConfig({projectDir:e.projectDir??e.contentDir,contentDir:e.contentDir});if(t){let e=t.telemetry.attributeDenylist,s=[];for(let t of e)s.push(t),s.push(`*.${t}`);loggerFactory.configure({pinoConfig:{fileSink:t.logs,redactPaths:s}})}initTelemetry({localSink:t?.telemetry});let{kind:s,gitdir:g}=computeWorktreeAttributes(e.projectDir??e.contentDir),S={"ok.worktree.kind":s};return g!==null&&(S[`ok.worktree.gitdir`]=normalizeFsPath(g)),withSpan(`ok.boot`,{attributes:S},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-CyhBidkz-Bp84kpW5.mjs`),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=e.gitPreflight??assertGitAvailable;try{L()}catch(e){if(e instanceof GitNotAvailableError||e instanceof GitTooOldError){let t=e instanceof GitTooOldError?e.detected:``,s=e instanceof GitTooOldError?`too_old`:`not_available`;emitPreflightFailureSpan(e),S.warn({event:`git_preflight_fail`,platform:e.platform,reason:s,detectedVersion:t},s===`not_available`?`git binary not found`:`git binary too old`),process.stderr.write(`${e.message}\n`)}throw await shutdownTelemetry(),e}let B=findLegacyRuntimeFiles(F);B.length>0&&console.warn(`[boot] Found legacy runtime files at .ok/${B.join(`, `)}. Delete .ok/ and re-init — these files moved to .ok/${LOCAL_DIR}/.`);let H=createServer$1({contentDir:e.contentDir,projectDir:e.projectDir,contentRoot:e.contentRoot,port:e.port,host:e.host,quiet:e.quiet??!1,debounce:e.debounce,maxDebounce:e.maxDebounce,gitEnabled:e.gitEnabled,commitDebounceMs:e.commitDebounceMs,wipRef:e.wipRef,enableTestRoutes:e.enableTestRoutes,shadowRepo:e.shadowRepo,destroyTimeoutMs:e.destroyTimeoutMs,localOpCliArgs:e.localOpCliArgs,onAgentWrite:e.onAgentWrite,lockKind:E,skipStateManifestCheck:e.skipStateManifestCheck,detectGh:e.detectGh,tokenStore:e.tokenStore}),{hocuspocus:q,destroy:J,ready:Y,degraded:ee,lockDir:te,sessionManager:ne,agentFocusBroadcaster:ae,agentPresenceBroadcaster:oe}=H,se=(()=>{let t=e.host??`localhost`;return t===`0.0.0.0`||t===`::`?`localhost`:t.includes(`:`)&&!t.startsWith(`[`)?`[${t}]`:t})(),ce=e.port??0,ue=createMcpHttpHandler({contentDir:e.contentDir,projectDir:e.projectDir??e.contentDir,config:e.config,getServerUrl:()=>`http://${se}:${ce}`,log:S}),de=D();de.headersTimeout=3e4,de.requestTimeout=6e4;let fe=e.serveContentAssets?createAssetServeMiddleware({contentFilter:H.contentFilter,contentSirv:build_default(e.contentDir,{dev:!0,dotfiles:!1}),inlineExtensions:INLINE_RENDERABLE_EXTENSIONS,assetExtensions:ASSET_EXTENSIONS,blocklistExtensions:EXECUTABLE_BLOCKLIST_EXTENSIONS}):void 0,me=!1;if(e.reactShellDistDir)try{acquireUiLock(te,{port:0,worktreeRoot:e.projectDir??e.contentDir}),me=!0}catch(e){if(e instanceof UiLockCollisionError)S.info({event:`ui-lock-yielded-to-live-holder`,pid:process.pid,existingPid:e.existing.pid,existingPort:e.existing.port,lockDir:te},`ui.lock already held by a live process — yielding (advertisement is fulfilled)`);else throw await J().catch(()=>{}),e}let ge=e.reactShellDistDir?build_default(e.reactShellDistDir,{single:!0,gzip:!0,immutable:!0}):void 0,_e=mountMcpAndApi({httpServer:de,hocuspocus:q,mcpHttpHandler:ue,log:S,sessionManager:ne,agentFocusBroadcaster:ae,agentPresenceBroadcaster:oe,keepaliveGraceMs:e.keepaliveGraceMs,contentAssetMiddleware:fe,reactShellMiddleware:ge}),ve=async()=>{throw Error(`bootServer: destroy() invoked before initialization — boot did not complete`)},ye=null;g!==null&&(ye=attachIdleShutdown({httpServer:de,thresholdMs:g??DEFAULT_IDLE_THRESHOLD_MS,log:S,onShutdown:(e.idleShutdownHandler??(e=>async()=>{await e()}))(async()=>{await ve()})})),await restoreLifecycleFromConflictsJson({hocuspocus:q,projectDir:e.projectDir??e.contentDir,log:S});try{await new Promise((t,s)=>{let g=e=>s(e);de.once(`error`,g),de.listen(e.port,e.host,()=>{de.removeListener(`error`,g),t()})})}catch(e){if(me)try{releaseUiLock(te)}catch(e){S.warn({err:e},`releaseUiLock failed during listen-error cleanup`)}throw await J().catch(()=>{}),e}let Ce=de.address(),we=typeof Ce==`object`&&Ce?Ce.port:e.port??0;if(ce=we,O(te,we),me&&updateUiLockPort(te,we),s&&e.spawnUiSiblingFn)try{await e.spawnUiSiblingFn({lockDir:te,log:S})}catch(e){S.warn({err:e},`spawnUiSiblingFn failed`)}let Te=!1,De=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 ve=async()=>{if(Te)return;Te=!0;let e=[],t=async(t,s)=>{try{await De(t,s)}catch(s){e.push(s),S.warn({err:s,step:t},`bootServer destroy step failed`)}};try{ye?.detach()}catch(t){e.push(t),S.warn({err:t,step:`idleHandle.detach`},`bootServer destroy step failed`)}if(await t(`mount.shutdown`,()=>_e.shutdown()),await t(`mcpHttpHandler.close`,()=>ue.close()),await t(`mount.wss.close`,()=>new Promise((e,t)=>{_e.wss.close(s=>s?t(s):e())})),await t(`httpServer.closeAllConnections`,async()=>{de.closeAllConnections?.()}),await t(`httpServer.close`,()=>new Promise((e,t)=>{de.close(s=>s&&s.code!==`ERR_SERVER_NOT_RUNNING`?t(s):e())})),await t(`destroyHocuspocus`,()=>J()),me&&await t(`releaseUiLock`,async()=>releaseUiLock(te)),await t(`shutdownTelemetry`,()=>shutdownTelemetry()),await t(`flushLogFileSinks`,()=>loggerFactory.flushAllFileSinks()),e.length>0)throw AggregateError(e,`bootServer destroy completed with errors`)},{httpServer:de,destroy:ve,lockDir:te,contentDir:e.contentDir,port:we,ready:Y,degraded:ee,didAutoInit:k,serverInstance:H}}async function restoreLifecycleFromConflictsJson(e){let{hocuspocus:t,projectDir:s,log:g}=e,S,w;try{S=new ConflictStore(s),w=S.list()}catch(e){g.warn({err:e,projectDir:s},`[boot] lifecycle restore: failed to read conflicts.json — skipping`);return}if(w.length===0)return;let E=null;try{let e=resolveGitDir(s),t=e?join(e,`MERGE_HEAD`):null;if(!t||!existsSync(t)){S.clear(),console.warn(JSON.stringify({event:`lifecycle-restore-cleared-stale-conflicts`,reason:`no-merge-head`,count:w.length}));return}let g=(await simpleGit({baseDir:s,timeout:{block:5e3}}).raw([`diff`,`--name-only`,`--diff-filter=U`])).trim();E=new Set(g?g.split(`
3083
- `).map(e=>e.trim()).filter(Boolean):[])}catch(e){g.warn({err:e,projectDir:s},`[boot] lifecycle restore: git unmerged probe failed — restoring all entries`)}if(E!==null){let e=0;for(let t of w)E.has(t.file)||(S.removeConflict(t.file),e++);if(e>0&&console.warn(JSON.stringify({event:`lifecycle-restore-pruned-resolved-entries`,pruned:e,remaining:w.length-e})),w=w.filter(e=>E?.has(e.file)),w.length===0)return}for(let e of w){let s=stripDocExtension(e.file),S=null,w=!1;try{S=await t.openDirectConnection(s);let e=S.document;if(!e)continue;let g=e.getMap(`lifecycle`);g.set(`status`,`conflict`),g.set(`reason`,`conflict-markers`),w=!0,console.warn(JSON.stringify({event:`lifecycle-restored-from-conflicts-json`,"doc.name":s}))}catch(e){g.warn({err:e,docName:s},`[boot] lifecycle restore: failed to set lifecycle for doc — skipping`)}finally{if(S)try{await S.disconnect()}catch(e){g.warn({err:e,docName:s,restored:w},`[boot] lifecycle restore: disconnect failed after lifecycle write`)}}}}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 OK_LOGS_DIR=join(homedir(),`.ok`,`logs`),MAX_ROTATED_FILES=2,MAX_AGE_DAYS=7,MAX_DIR_SIZE_BYTES=45*1024*1024,REDACT_PATHS=[`authorization`,`password`,`token`,`apiKey`,`secret`,`*.authorization`,`*.password`,`*.token`,`*.apiKey`,`*.secret`];function resolveLogLevel(){let e=process.env.OK_LOG_LEVEL??process.env.LOG_LEVEL;if(e){let t=[`fatal`,`error`,`warn`,`info`,`debug`],s=e.toLowerCase();if(t.includes(s))return s}return process.env.NODE_ENV===`test`?`silent`:`info`}function ensureDir(e){mkdirSync(e,{recursive:!0})}function todayDateString(){return new Date().toISOString().slice(0,10)}function rotateIfNeeded(e){try{if(statSync(e).size<5242880)return}catch{return}for(let t=MAX_ROTATED_FILES;t>=1;t--){let s=t===1?e:`${e}.${t-1}`,g=`${e}.${t}`;try{renameSync(s,g)}catch{}}try{unlinkSync(`${e}.${MAX_ROTATED_FILES+1}`)}catch{}}function pruneLogsDir(e){try{let t=Date.now(),s=MAX_AGE_DAYS*24*60*60*1e3,g=readdirSync(e).filter(e=>e.endsWith(`.log`)||/\.log\.\d+$/.test(e)).map(t=>{try{let s=statSync(join(e,t));return{name:t,mtime:s.mtimeMs,size:s.size}}catch{return null}}).filter(Boolean);for(let S of g)if(t-S.mtime>s)try{unlinkSync(join(e,S.name))}catch{}let S=g.filter(e=>t-e.mtime<=s).sort((e,t)=>e.mtime-t.mtime),w=S.reduce((e,t)=>e+t.size,0);for(let t of S){if(w<=MAX_DIR_SIZE_BYTES)break;try{unlinkSync(join(e,t.name)),w-=t.size}catch{}}}catch{}}function createFileLogger(e){ensureDir(OK_LOGS_DIR);let t=todayDateString(),s=e.filePath??join(OK_LOGS_DIR,`${e.name}.${t}.log`);rotateIfNeeded(s),setTimeout(()=>pruneLogsDir(OK_LOGS_DIR),5e3);let g=import_pino.default.destination({dest:s,append:!0,sync:!1});return(0,import_pino.default)({level:resolveLogLevel(),name:e.name,redact:{paths:REDACT_PATHS,censor:`[REDACTED]`},base:{pid:process.pid,hostname:void 0,runtime:`cli`,project:e.project??`<no-project>`},timestamp:import_pino.default.stdTimeFunctions.isoTime,...e.additionalOptions},g)}function getLogFilePath(e){return join(OK_LOGS_DIR,`${e}.${todayDateString()}.log`)}function getLogsDir(){return OK_LOGS_DIR}const ANCESTOR_WALK_DEPTH_LIMIT=30,GIT_MARKER=`.git`;function findEnclosingGitRoot(e){let t=resolve(e),s=0;for(;s<ANCESTOR_WALK_DEPTH_LIMIT;){let e=!1;try{e=existsSync(resolve(t,GIT_MARKER))}catch{e=!1}if(e)return{gitRoot:t,distance:s};let g=dirname(t);if(g===t)return null;t=g,s+=1}return null}const execFileAsync=promisify(execFile),log=getLogger(`project-git`);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`),g=resolve(s,`HEAD`),S=!1;if(existsSync(s)){if(!statSync(s).isDirectory()||existsSync(g))return{didInit:!1};log.info({},`detected partial .git/ — running git init to repair`),S=!0}else if(await isInsideExistingWorkTree(t))return{didInit:!1};let w=``;try{w=(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(g))throw new ProjectGitInitError(`git init reported success but ${s}/HEAD is missing (partial init detected)`,w);return S?(log.info({path:t},`backfilled missing .git/HEAD`),{didInit:!0,repaired:!0}):(log.info({path:t,branch:`main`},`initialized .git/`),{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}}const MAX_CAUSE_DEPTH=5,HOME_PATH_PATTERNS=[{regex:/\/Users\/[^/]+\//g,replacement:`~/`},{regex:/\/home\/[^/]+\//g,replacement:`~/`},{regex:/C:\\\\Users\\\\[^\\\\]+\\\\/g,replacement:`~\\`},{regex:/C:\\Users\\[^\\]+\\/g,replacement:`~\\`}];function scrubPaths(e){if(e===void 0)return;let t=e;for(let{regex:e,replacement:s}of HOME_PATH_PATTERNS)t=t.replace(e,s);return t}function serializeError(e,t=0,s=new WeakSet){if(t>=MAX_CAUSE_DEPTH)return{name:`SerializedError.CauseDepthExceeded`,message:`cause chain depth > ${MAX_CAUSE_DEPTH}; truncated`};if(typeof e==`object`&&e){if(s.has(e))return{name:`SerializedError.CauseCycle`,message:`cyclic cause; truncated`};s.add(e)}if(e instanceof Error)return{name:e.name,message:scrubPaths(e.message)??``,stack:scrubPaths(e.stack),code:e.code,cause:e.cause===void 0?void 0:serializeError(e.cause,t+1,s)};if(e==null)return{name:`UnknownError`,message:String(e)};if(typeof e==`string`)return{name:`StringError`,message:scrubPaths(e)??e};if(typeof e==`object`){let g=e;return{name:String(g.name??`ObjectError`),message:scrubPaths(String(g.message??``))??``,stack:scrubPaths(g.stack),code:g.code,cause:g.cause===void 0?void 0:serializeError(g.cause,t+1,s)}}return{name:`UnknownError`,message:String(e)}}export{TagIndex as $,readTargetRecordedAt as $n,tracedUnlinkSync as $r,formatAuthRejectionWire as $t,MCP_CONNECTION_ID_HEADER as A,isSelfWrite as An,saveInMemoryCheckpoint as Ar,createContentFilter as At,ROLLBACK_ORIGIN as B,normalizeFsPath as Bn,splitMarkdownBlocks as Br,createStreamingErrorWriter as Bt,HocuspocusAuthRejection as C,writeConfigPatch as Ci,isConfigDoc as Cn,runCloneSubprocess as Cr,commitWipFromTree as Ct,LOG_MD_TEMPLATE as D,isPairedWriteOrigin as Dn,safeSubdir as Dr,contributorCount as Dt,LIVE_DERIVED_INDEX_DEBOUNCE_MS as E,resolveShadowDir as Ei,isLoopbackAddress as En,safeContentPath as Er,contentHash as Et,MissingOkConfigError as F,loadPrincipal as Fn,shadowGit as Fr,createMcpHttpHandler as Ft,STARTER_FOLDER_FRONTMATTER_FILENAME as G,parseKeepaliveConnectionId as Gn,tracedAppendFileSync as Gr,emitPreflightFailureSpan as Gt,SERVICE_WRITER as H,parseAuthRejectionWire as Hn,streamingProblemEvent as Hr,detectClaudeDesktopPresence as Ht,OBSERVER_SYNC_ORIGIN as I,loggerFactory as In,shutdownTelemetry as Ir,createOsProbe as It,STARTER_TEMPLATES as J,readAllTargets as Jn,tracedMkdirSync as Jr,evictStaleTrackerEntries as Jt,STARTER_PACKS as K,pathToDocName as Kn,tracedLinkSync as Kr,ensureProjectGit as Kt,OK_OKIGNORE_TEMPLATE as L,logsCurrentPath as Ln,spansCurrentPath as Lr,createPersistenceExtension as Lt,MIN_GIT_VERSION as M,lastKnownHash as Mn,seedBasenameIndex as Mr,createExternalChangeHandler as Mt,MISSING_OK_CONFIG_MESSAGE as N,listRescueCheckpoints as Nn,serializeError as Nr,createFileLogger as Nt,MANAGED_RENAME_ORIGIN as O,isPathWithinDir as On,safetyCheckpoint as Or,createApiExtension as Ot,McpLogger as P,listStarterPacks as Pn,setActiveSpanAttributes as Pr,createLiveDerivedIndexExtension as Pt,StateManifestError as Q,readStateManifest as Qn,tracedRmdirSync as Qr,findEnclosingProjectRoot as Qt,PinoLogger as R,logsPreviousPath as Rn,spansPreviousPath as Rr,createServer$1 as Rt,HOCUSPOCUS_AUTH_REJECTION_REASONS as S,withFileLockSync as Si,isAllowedWorkspaceHostHeader as Sn,runAuthStatusSubprocess as Sr,commitWip as St,INSTALLED_AGENTS_SCHEMES as T,MalformedGitPointerError as Ti,isKnownPackId as Tn,runWithMcpLogger as Tr,containsConflictMarkers as Tt,SKILL_INSTALL_EVENTS_FILE_REL as U,parseGitVersion as Un,swapContributors as Ur,detectGit as Ut,ROOT_GITIGNORE_TEMPLATE as V,packageVersionMajorMinor as Vn,startWatcher as Vr,createTestLogger as Vt,STARTER_FOLDERS as W,parseHocuspocusAuthToken as Wn,toBroadcasterKey as Wr,detectProjectShape as Wt,SeedPrerequisiteError as X,readServerPackageVersion as Xn,tracedRenameSync as Xr,fallbackPaths as Xt,STATE_MANIFEST_FILENAME as Y,readBranchFromHead as Yn,tracedRename as Yr,extractWikiLinksFromMarkdown as Yt,SeedRootDirError as Z,readSkillInstallStateSnapshot as Zn,tracedRmSync as Zr,findEnclosingGitRoot as Zt,FILE_WATCHER_ORIGIN as _,isJSONRPCRequest as _i,initTelemetry as _n,restoreContributors as _r,classifyEvents as _t,AgentPresenceBroadcaster as a,validateCloneInputs as ai,getLogFilePath as an,registerAllTools as ar,assertCompatibleStateManifest as at,GitNotAvailableError as b,readConfigSafely as bi,installUserSkill as bn,rewriteWikiLinksForDocumentRename as br,coercePackId as bt,BacklinkIndex as c,withSpanSync as ci,getMeter as cn,removeLastKnownHash as cr,attachIdleShutdown as ct,CONFLICT_MARKER_RE as d,writeTargetVersion as di,handleCollabSocketError as dn,resolveContentDir as dr,buildConfigYmlContent as dt,tracedWriteFile as ei,formatContributors as en,readTargetVersion as er,UiLockCollisionError as et,CURSOR_BUNDLE_PATHS_BY_PLATFORM as f,writeTracker as fi,handleSpawnCursor as fn,resolveCursorBinaryDefault as fr,buildExecResult as ft,FILE_SYSTEM_WRITER as g,isInitializedNotification as gi,initShadowRepo as gn,resolvePackageVersion as gr,buildWipTree as gt,DEFAULT_PACK_ID as h,LATEST_PROTOCOL_VERSION as hi,initContent as hn,resolvePack as hr,buildStarterFolderFrontmatterYaml as ht,AgentFocusBroadcaster as i,validateAgentId as ii,getLocalDir as in,recordSkillInstallEvent as ir,applySeed as it,MCP_SERVER_NAME as j,isSystemDoc as jn,saveVersion as jr,createContentFilterAsync as jt,MAX_AGENT_SESSIONS as k,isProjectRoot as kn,sanitizeClientName as kr,createAssetServeMiddleware as kt,CC1Broadcaster as l,writeRootGitignoreForNewRepo as li,getMetrics as ln,resetMetrics as lr,bootServer as lt,DEFAULT_CHECKPOINT_RETENTION as m,JSONRPCMessageSchema as mi,incrementServerObserverFire as mn,resolveLockDir as mr,buildSkillZip as mt,AGENT_ID_RE as n,updateLastKnownHash as ni,gcCheckpointRefs as nn,reconcile as nr,applyAgentMarkdownWrite as nt,AgentSessionCapacityError as o,validateSkillZip as oi,getLogger as on,registerWrite as or,assertGitAvailable as ot,ConfigSchema as p,McpServer as pi,incrementCollabSocketFilteredError as pn,resolveCursorSpawnInvocation as pr,buildInstructions as pt,STARTER_PACK_IDS as q,planSeed as qn,tracedMkdir as qr,errorResponse as qt,AGENT_WRITE_ORIGIN as r,updateUiLockPort as ri,getCurrentMcpLogger as rn,recordContributor as rr,applyExternalChange as rt,AgentSessionManager as s,withSpan as si,getLogsDir as sn,releaseUiLock as sr,assertNeverDiskEvent as st,AGENT_ID_MAX_LEN as t,tracedWriteFileSync as ti,formatContributorsFrom as tn,readUiLock as tr,acquireUiLock as tt,CONFIG_FILENAME as u,writeStateManifest as ui,getTracer as un,resolveBundledSkillDir as ur,buildAndOpenSkill as ut,GIT_PREFLIGHT_FAIL_SPAN_NAME as v,isJSONRPCResultResponse as vi,installPrettyZodErrors as vn,restoreLifecycleFromConflictsJson as vr,classifyFsPath as vt,HocuspocusAuthTokenSchema as w,GitDirAccessError as wi,isHocuspocusAuthRejectionReason as wn,runDeviceFlowSubprocess as wr,compareSemver as wt,GitTooOldError as x,resolveConfigPath as xi,isAllowedApiOrigin as xn,runAuthReposSubprocess as xr,commitUpstreamImport as xt,GIT_UPSTREAM_WRITER as y,atomicWriteFileSync as yi,installTestLoggers as yn,rewriteMarkdownLinksForDocumentRename as yr,clearContributors as yt,ProjectGitInitError as z,mountMcpAndApi as zn,spawnDetached as zr,createServerObserverExtension as zt};
3084
- //# sourceMappingURL=dist-DKgq69uI.mjs.map
3083
+ `).map(e=>e.trim()).filter(Boolean):[])}catch(e){g.warn({err:e,projectDir:s},`[boot] lifecycle restore: git unmerged probe failed — restoring all entries`)}if(E!==null){let e=0;for(let t of w)E.has(t.file)||(S.removeConflict(t.file),e++);if(e>0&&console.warn(JSON.stringify({event:`lifecycle-restore-pruned-resolved-entries`,pruned:e,remaining:w.length-e})),w=w.filter(e=>E?.has(e.file)),w.length===0)return}for(let e of w){let s=stripDocExtension(e.file),S=null,w=!1;try{S=await t.openDirectConnection(s);let e=S.document;if(!e)continue;let g=e.getMap(`lifecycle`);g.set(`status`,`conflict`),g.set(`reason`,`conflict-markers`),w=!0,console.warn(JSON.stringify({event:`lifecycle-restored-from-conflicts-json`,"doc.name":s}))}catch(e){g.warn({err:e,docName:s},`[boot] lifecycle restore: failed to set lifecycle for doc — skipping`)}finally{if(S)try{await S.disconnect()}catch(e){g.warn({err:e,docName:s,restored:w},`[boot] lifecycle restore: disconnect failed after lifecycle write`)}}}}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 OK_LOGS_DIR=join(homedir(),`.ok`,`logs`),MAX_ROTATED_FILES=2,MAX_AGE_DAYS=7,MAX_DIR_SIZE_BYTES=45*1024*1024,REDACT_PATHS=[`authorization`,`password`,`token`,`apiKey`,`secret`,`*.authorization`,`*.password`,`*.token`,`*.apiKey`,`*.secret`];function resolveLogLevel(){let e=process.env.OK_LOG_LEVEL??process.env.LOG_LEVEL;if(e){let t=[`fatal`,`error`,`warn`,`info`,`debug`],s=e.toLowerCase();if(t.includes(s))return s}return process.env.NODE_ENV===`test`?`silent`:`info`}function ensureDir(e){mkdirSync(e,{recursive:!0})}function todayDateString(){return new Date().toISOString().slice(0,10)}function rotateIfNeeded(e){try{if(statSync(e).size<5242880)return}catch{return}for(let t=MAX_ROTATED_FILES;t>=1;t--){let s=t===1?e:`${e}.${t-1}`,g=`${e}.${t}`;try{renameSync(s,g)}catch{}}try{unlinkSync(`${e}.${MAX_ROTATED_FILES+1}`)}catch{}}function pruneLogsDir(e){try{let t=Date.now(),s=MAX_AGE_DAYS*24*60*60*1e3,g=readdirSync(e).filter(e=>e.endsWith(`.log`)||/\.log\.\d+$/.test(e)).map(t=>{try{let s=statSync(join(e,t));return{name:t,mtime:s.mtimeMs,size:s.size}}catch{return null}}).filter(Boolean);for(let S of g)if(t-S.mtime>s)try{unlinkSync(join(e,S.name))}catch{}let S=g.filter(e=>t-e.mtime<=s).sort((e,t)=>e.mtime-t.mtime),w=S.reduce((e,t)=>e+t.size,0);for(let t of S){if(w<=MAX_DIR_SIZE_BYTES)break;try{unlinkSync(join(e,t.name)),w-=t.size}catch{}}}catch{}}function createFileLogger(e){ensureDir(OK_LOGS_DIR);let t=todayDateString(),s=e.filePath??join(OK_LOGS_DIR,`${e.name}.${t}.log`);rotateIfNeeded(s),setTimeout(()=>pruneLogsDir(OK_LOGS_DIR),5e3);let g=import_pino.default.destination({dest:s,append:!0,sync:!1});return(0,import_pino.default)({level:resolveLogLevel(),name:e.name,redact:{paths:REDACT_PATHS,censor:`[REDACTED]`},base:{pid:process.pid,hostname:void 0,runtime:`cli`,project:e.project??`<no-project>`},timestamp:import_pino.default.stdTimeFunctions.isoTime,...e.additionalOptions},g)}function getLogFilePath(e){return join(OK_LOGS_DIR,`${e}.${todayDateString()}.log`)}function getLogsDir(){return OK_LOGS_DIR}const ANCESTOR_WALK_DEPTH_LIMIT=30,GIT_MARKER=`.git`;function findEnclosingGitRoot(e){let t=resolve(e),s=0;for(;s<ANCESTOR_WALK_DEPTH_LIMIT;){let e=!1;try{e=existsSync(resolve(t,GIT_MARKER))}catch{e=!1}if(e)return{gitRoot:t,distance:s};let g=dirname(t);if(g===t)return null;t=g,s+=1}return null}const execFileAsync=promisify(execFile),log=getLogger(`project-git`);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`),g=resolve(s,`HEAD`),S=!1;if(existsSync(s)){if(!statSync(s).isDirectory()||existsSync(g))return{didInit:!1};log.info({},`detected partial .git/ — running git init to repair`),S=!0}else if(await isInsideExistingWorkTree(t))return{didInit:!1};let w=``;try{w=(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(g))throw new ProjectGitInitError(`git init reported success but ${s}/HEAD is missing (partial init detected)`,w);return S?(log.info({path:t},`backfilled missing .git/HEAD`),{didInit:!0,repaired:!0}):(log.info({path:t,branch:`main`},`initialized .git/`),{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}}const MAX_CAUSE_DEPTH=5,HOME_PATH_PATTERNS=[{regex:/\/Users\/[^/]+\//g,replacement:`~/`},{regex:/\/home\/[^/]+\//g,replacement:`~/`},{regex:/C:\\\\Users\\\\[^\\\\]+\\\\/g,replacement:`~\\`},{regex:/C:\\Users\\[^\\]+\\/g,replacement:`~\\`}];function scrubPaths(e){if(e===void 0)return;let t=e;for(let{regex:e,replacement:s}of HOME_PATH_PATTERNS)t=t.replace(e,s);return t}function serializeError(e,t=0,s=new WeakSet){if(t>=MAX_CAUSE_DEPTH)return{name:`SerializedError.CauseDepthExceeded`,message:`cause chain depth > ${MAX_CAUSE_DEPTH}; truncated`};if(typeof e==`object`&&e){if(s.has(e))return{name:`SerializedError.CauseCycle`,message:`cyclic cause; truncated`};s.add(e)}if(e instanceof Error)return{name:e.name,message:scrubPaths(e.message)??``,stack:scrubPaths(e.stack),code:e.code,cause:e.cause===void 0?void 0:serializeError(e.cause,t+1,s)};if(e==null)return{name:`UnknownError`,message:String(e)};if(typeof e==`string`)return{name:`StringError`,message:scrubPaths(e)??e};if(typeof e==`object`){let g=e;return{name:String(g.name??`ObjectError`),message:scrubPaths(String(g.message??``))??``,stack:scrubPaths(g.stack),code:g.code,cause:g.cause===void 0?void 0:serializeError(g.cause,t+1,s)}}return{name:`UnknownError`,message:String(e)}}export{StateManifestError as $,readBranchFromHead as $n,tracedRename as $r,fallbackPaths as $t,MCP_CONNECTION_ID_HEADER as A,resolveShadowDir as Ai,isPairedWriteOrigin as An,safeContentPath as Ar,contributorCount as At,ProjectGitInitError as B,logsCurrentPath as Bn,shutdownTelemetry as Br,createPersistenceExtension as Bt,HocuspocusAuthRejection as C,atomicWriteFileSync as Ci,installUserSkill as Cn,rewriteMarkdownLinksForDocumentRename as Cr,coercePackId as Ct,LOG_MD_TEMPLATE as D,writeConfigPatch as Di,isHocuspocusAuthRejectionReason as Dn,runCloneSubprocess as Dr,compareSemver as Dt,LIVE_DERIVED_INDEX_DEBOUNCE_MS as E,withFileLockSync as Ei,isConfigDoc as En,runAuthStatusSubprocess as Er,commitWipFromTree as Et,MissingOkConfigError as F,lastKnownHash as Fn,saveVersion as Fr,createExternalChangeHandler as Ft,STARTER_FOLDERS as G,parseAuthRejectionWire as Gn,startWatcher as Gr,detectClaudeDesktopPresence as Gt,ROOT_GITIGNORE_TEMPLATE as H,mountMcpAndApi as Hn,spansPreviousPath as Hr,createServerObserverExtension as Ht,OBSERVER_SYNC_ORIGIN as I,listRescueCheckpoints as In,seedBasenameIndex as Ir,createFileLogger as It,STARTER_PACK_IDS as J,parseKeepaliveConnectionId as Jn,toBroadcasterKey as Jr,emitPreflightFailureSpan as Jt,STARTER_FOLDER_FRONTMATTER_FILENAME as K,parseGitVersion as Kn,streamingProblemEvent as Kr,detectGit as Kt,OK_OKIGNORE_TEMPLATE as L,listStarterPacks as Ln,serializeError as Lr,createLiveDerivedIndexExtension as Lt,MIN_GIT_VERSION as M,isProjectRoot as Mn,safetyCheckpoint as Mr,createAssetServeMiddleware as Mt,MISSING_OK_CONFIG_MESSAGE as N,isSelfWrite as Nn,sanitizeClientName as Nr,createContentFilter as Nt,MANAGED_RENAME_ORIGIN as O,GitDirAccessError as Oi,isKnownPackId as On,runDeviceFlowSubprocess as Or,containsConflictMarkers as Ot,McpLogger as P,isSystemDoc as Pn,saveInMemoryCheckpoint as Pr,createContentFilterAsync as Pt,SeedRootDirError as Q,readArmedPaneTarget as Qn,tracedMkdirSync as Qr,extractWikiLinksFromMarkdown as Qt,PANE_TARGET_TTL_MS as R,loadPrincipal as Rn,setActiveSpanAttributes as Rr,createMcpHttpHandler as Rt,HOCUSPOCUS_AUTH_REJECTION_REASONS as S,isJSONRPCResultResponse as Si,installTestLoggers as Sn,restoreLifecycleFromConflictsJson as Sr,clearContributors as St,INSTALLED_AGENTS_SCHEMES as T,resolveConfigPath as Ti,isAllowedWorkspaceHostHeader as Tn,runAuthReposSubprocess as Tr,commitWip as Tt,SERVICE_WRITER as U,normalizeFsPath as Un,spawnDetached as Ur,createStreamingErrorWriter as Ut,ROLLBACK_ORIGIN as V,logsPreviousPath as Vn,spansCurrentPath as Vr,createServer$1 as Vt,SKILL_INSTALL_EVENTS_FILE_REL as W,packageVersionMajorMinor as Wn,splitMarkdownBlocks as Wr,createTestLogger as Wt,STATE_MANIFEST_FILENAME as X,planSeed as Xn,tracedLinkSync as Xr,errorResponse as Xt,STARTER_TEMPLATES as Y,pathToDocName as Yn,tracedAppendFileSync as Yr,ensureProjectGit as Yt,SeedPrerequisiteError as Z,readAllTargets as Zn,tracedMkdir as Zr,evictStaleTrackerEntries as Zt,FILE_WATCHER_ORIGIN as _,McpServer as _i,incrementServerObserverFire as _n,resolveCursorSpawnInvocation as _r,buildStarterFolderFrontmatterYaml as _t,AgentPresenceBroadcaster as a,tracedWriteFileSync as ai,gcCheckpointRefs as an,readUiLock as ar,applySeed as at,GitNotAvailableError as b,isInitializedNotification as bi,initTelemetry as bn,resolvePackageVersion as br,classifyFsPath as bt,BacklinkIndex as c,validateAgentId as ci,getLogFilePath as cn,recordSkillInstallEvent as cr,assertGitAvailable as ct,CONFLICT_MARKER_RE as d,withSpan as di,getMeter as dn,releaseUiLock as dr,bootServer as dt,tracedRenameSync as ei,findEnclosingGitRoot as en,readServerPackageVersion as er,TagIndex as et,CURSOR_BUNDLE_PATHS_BY_PLATFORM as f,withSpanSync as fi,getMetrics as fn,removeLastKnownHash as fr,buildAndOpenSkill as ft,FILE_SYSTEM_WRITER as g,writeTracker as gi,incrementCollabSocketFilteredError as gn,resolveCursorBinaryDefault as gr,buildSkillZip as gt,DEFAULT_PACK_ID as h,writeTargetVersion as hi,handleSpawnCursor as hn,resolveContentDir as hr,buildInstructions as ht,AgentFocusBroadcaster as i,tracedWriteFile as ii,formatContributorsFrom as in,readTargetVersion as ir,applyExternalChange as it,MCP_SERVER_NAME as j,isPathWithinDir as jn,safeSubdir as jr,createApiExtension as jt,MAX_AGENT_SESSIONS as k,MalformedGitPointerError as ki,isLoopbackAddress as kn,runWithMcpLogger as kr,contentHash as kt,CC1Broadcaster as l,validateCloneInputs as li,getLogger as ln,registerAllTools as lr,assertNeverDiskEvent as lt,DEFAULT_CHECKPOINT_RETENTION as m,writeStateManifest as mi,handleCollabSocketError as mn,resolveBundledSkillDir as mr,buildExecResult as mt,AGENT_ID_RE as n,tracedRmdirSync as ni,formatAuthRejectionWire as nn,readStateManifest as nr,acquireUiLock as nt,AgentSessionCapacityError as o,updateLastKnownHash as oi,getCurrentMcpLogger as on,reconcile as or,armPaneTarget as ot,ConfigSchema as p,writeRootGitignoreForNewRepo as pi,getTracer as pn,resetMetrics as pr,buildConfigYmlContent as pt,STARTER_PACKS as q,parseHocuspocusAuthToken as qn,swapContributors as qr,detectProjectShape as qt,AGENT_WRITE_ORIGIN as r,tracedUnlinkSync as ri,formatContributors as rn,readTargetRecordedAt as rr,applyAgentMarkdownWrite as rt,AgentSessionManager as s,updateUiLockPort as si,getLocalDir as sn,recordContributor as sr,assertCompatibleStateManifest as st,AGENT_ID_MAX_LEN as t,tracedRmSync as ti,findEnclosingProjectRoot as tn,readSkillInstallStateSnapshot as tr,UiLockCollisionError as tt,CONFIG_FILENAME as u,validateSkillZip as ui,getLogsDir as un,registerWrite as ur,attachIdleShutdown as ut,GIT_PREFLIGHT_FAIL_SPAN_NAME as v,JSONRPCMessageSchema as vi,initContent as vn,resolveLockDir as vr,buildWipTree as vt,HocuspocusAuthTokenSchema as w,readConfigSafely as wi,isAllowedApiOrigin as wn,rewriteWikiLinksForDocumentRename as wr,commitUpstreamImport as wt,GitTooOldError as x,isJSONRPCRequest as xi,installPrettyZodErrors as xn,restoreContributors as xr,clearArmedPaneTarget as xt,GIT_UPSTREAM_WRITER as y,LATEST_PROTOCOL_VERSION as yi,initShadowRepo as yn,resolvePack as yr,classifyEvents as yt,PinoLogger as z,loggerFactory as zn,shadowGit as zr,createOsProbe as zt};
3084
+ //# sourceMappingURL=dist-eWWovL1R.mjs.map
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{i as e,r as t,t as n}from"./gh-detect-D3_evne3.mjs";import{_ as r,d as i,f as a,g as o,h as s,i as c,m as l,r as u,s as d,t as f,u as p,v as m,y as h}from"./init-htUcoMvf.mjs";import{i as g,n as _,r as v,t as y}from"./src-CqKV9RHO.mjs";import{n as b}from"./loader-Kl4WTX1f.mjs";import{n as x}from"./preview-BeyH-UEE.mjs";import{n as S,t as C}from"./mcp-migrate-event-BF8ILHwp.mjs";export{l as ALL_EDITOR_IDS,s as EDITOR_LABELS,o as EDITOR_TARGETS,f as LAUNCH_CONFIG_NAME,r as buildManagedServerEntry,C as buildMcpConfigMigrateEvent,u as classifyExistingMcpEntry,t as createTokenStore,n as detectGh,c as detectInstalledEditors,m as isEntryUpToDate,b as loadConfig,e as makeLazyProbeTokenStore,v as parseGitHubBlobUrl,g as parseGitUrl,x as previewContent,d as readExistingMcpEntry,h as resolveProjectRoot,p as scaffoldLaunchJson,S as truncatePriorEntry,_ as validateLocalFolderForShare,i as writeEditorMcpConfig,y as writeProjectAiIntegrations,a as writeUserMcpConfigs};
1
+ import{i as e,r as t,t as n}from"./gh-detect-D3_evne3.mjs";import{_ as r,d as i,f as a,g as o,h as s,i as c,m as l,r as u,s as d,t as f,u as p,v as m,y as h}from"./init-C65xzxs_.mjs";import{i as g,n as _,r as v,t as y}from"./src-DXQs_Tkb.mjs";import{n as b}from"./loader-CYrZw2xs.mjs";import{n as x}from"./preview-DrBr_hFy.mjs";import{n as S,t as C}from"./mcp-migrate-event-BF8ILHwp.mjs";export{l as ALL_EDITOR_IDS,s as EDITOR_LABELS,o as EDITOR_TARGETS,f as LAUNCH_CONFIG_NAME,r as buildManagedServerEntry,C as buildMcpConfigMigrateEvent,u as classifyExistingMcpEntry,t as createTokenStore,n as detectGh,c as detectInstalledEditors,m as isEntryUpToDate,b as loadConfig,e as makeLazyProbeTokenStore,v as parseGitHubBlobUrl,g as parseGitUrl,x as previewContent,d as readExistingMcpEntry,h as resolveProjectRoot,p as scaffoldLaunchJson,S as truncatePriorEntry,_ as validateLocalFolderForShare,i as writeEditorMcpConfig,y as writeProjectAiIntegrations,a as writeUserMcpConfigs};
@@ -0,0 +1 @@
1
+ import{l as e}from"./init-C65xzxs_.mjs";export{e as runInit};