@inkeep/open-knowledge 0.9.0-beta.29 → 0.9.0-beta.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/skills/discovery/SKILL.md +1 -1
- package/dist/assets/skills/project/SKILL.md +4 -3
- package/dist/cli.mjs +43 -43
- package/dist/constants-nygsGL1t.mjs +2 -0
- package/dist/dist-DFlSVgXA.mjs +1 -0
- package/dist/{dist-Bgfgx-ED.mjs → dist-DpfmiCV4.mjs} +6 -6
- package/dist/index.mjs +1 -1
- package/dist/{init-AqwH3_Z1.mjs → init-BnZOMZQO.mjs} +21 -21
- package/dist/init-D1mwIDbj.mjs +1 -0
- package/dist/loader-C_bcUreu.mjs +1 -0
- package/dist/{loader-D--Bn2qd.mjs → loader-DDiDxthB.mjs} +2 -2
- package/dist/{preview-CCsLMa5f.mjs → preview-CSNkLWHD.mjs} +2 -2
- package/dist/preview-CirVU2JW.mjs +1 -0
- package/dist/{repair-launch-json-Cf5aidZ-.mjs → repair-launch-json-D2yuZ2m2.mjs} +2 -2
- package/dist/{repair-mcp-configs-CQcAfhF-.mjs → repair-mcp-configs-BoZZdQfe.mjs} +2 -2
- package/dist/{repair-skills-D8EM4M-V.mjs → repair-skills-BSxYtEdR.mjs} +2 -2
- package/dist/repair-skills-BwSKUIVg.mjs +1 -0
- package/dist/{src-D4PeSWPS.mjs → src-DlZY1w-G.mjs} +2 -2
- package/dist/start-Cenma9Sz.mjs +1 -0
- package/dist/{start-Cx4TGgyT.mjs → start-Gdo8a38H.mjs} +2 -2
- package/dist/{write-project-skill-qNALBb1N.mjs → write-project-skill-PXFMiJn0.mjs} +2 -2
- package/package.json +1 -1
- package/dist/constants-DmtB2F4y.mjs +0 -2
- package/dist/dist-VW9VvVj2.mjs +0 -1
- package/dist/init-WiLkATHG.mjs +0 -1
- package/dist/loader-7XBcgb4m.mjs +0 -1
- package/dist/preview-HzacAuXR.mjs +0 -1
- package/dist/repair-skills-C0yYFa_K.mjs +0 -1
- package/dist/start-CVgnn0ll.mjs +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Gr as e,Vr as t,a as n,br as r,c as i,d as a,f as o,g as s,h as c,i as l,l as u,m as d,n as f,o as p,on as m,p as h,q as g,r as _,s as v,t as y,u as b,un as x,wn as S,xn as C}from"./server-lock-BpjJj3OD-dXtN3YgR.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,Ni as De,Nn as Oe,Nr as ke,Nt as Ae,O as je,On as Me,Or as Ne,Ot as Pe,P as Fe,Pi as Ie,Pn as Le,Pr as Re,Pt as ze,Q as Be,Qn as Ve,Qr as He,Qt as Ue,R as We,Rn as Ge,Rr as Ke,Rt as qe,S as Je,Sn as Ye,Sr as Xe,St as Ze,T as Qe,Tn as $e,Tr as et,Tt as tt,U as nt,Un as rt,Ur as it,Ut as at,V as ot,Vn as st,Vr as ct,Vt as lt,W as ut,Wn as dt,Wr as ft,Wt as pt,X as mt,Xn as ht,Xr as gt,Xt as _t,Y as vt,Yn as yt,Yr as bt,Yt as xt,Z as St,Zn as Ct,Zr as wt,Zt as Tt,_ as Et,_i as Dt,_n as Ot,_r as kt,_t as At,a as jt,ai as Mt,an as Nt,ar as Pt,at as Ft,b as It,bi as Lt,bn as Rt,br as zt,bt as Bt,c as Vt,ci as Ht,cn as Ut,cr as Wt,ct as Gt,d as Kt,di as qt,dn as Jt,dr as Yt,dt as Xt,ei as Zt,en as Qt,er as $t,et as en,f as tn,fi as nn,fn as rn,fr as an,ft as on,g as sn,gi as cn,gn as ln,gr as un,gt as dn,h as fn,hi as pn,hn as mn,hr as hn,ht as gn,i as _n,ii as vn,in as yn,ir as bn,it as xn,j as Sn,jn as Cn,jr as wn,jt as Tn,k as En,kn as Dn,kr as On,kt as kn,l as An,li as jn,ln as Mn,lr as Nn,lt as Pn,m as Fn,mi as In,mn as Ln,mr as Rn,mt as zn,n as Bn,ni as Vn,nn as Hn,nr as Un,nt as Wn,o as Gn,oi as Kn,on as qn,or as Jn,ot as Yn,p as Xn,pi as Zn,pn as Qn,pr as $n,pt as er,q as tr,qn as nr,qr as rr,qt as ir,r as ar,ri as or,rn as sr,rr as cr,rt as lr,s as ur,si as dr,sn as fr,sr as pr,st as mr,t as hr,ti as gr,tn as _r,tr as vr,tt as yr,u as br,ui as xr,un as Sr,ur as Cr,ut as wr,v as Tr,vi as Er,vn as Dr,vr as Or,vt as kr,w as Ar,wn as jr,wr as Mr,wt as Nr,x as Pr,xi as Fr,xn as Ir,xr as Lr,xt as Rr,y as zr,yi as Br,yn as Vr,yr as Hr,yt as Ur,z as Wr,zn as Gr,zr as Kr,zt as qr}from"./dist-DpfmiCV4.mjs";export{hr as AGENT_ID_MAX_LEN,Bn as AGENT_ID_RE,ar as AGENT_WRITE_ORIGIN,_n as AgentFocusBroadcaster,jt as AgentPresenceBroadcaster,Gn as AgentSessionCapacityError,ur as AgentSessionManager,Vt as BacklinkIndex,An as CC1Broadcaster,g as CC1_CONTRACT_VERSION,br as CONFIG_FILENAME,Kt as CONFLICT_MARKER_RE,tn as CURSOR_BUNDLE_PATHS_BY_PLATFORM,Xn as ConfigSchema,Fn as DEFAULT_CHECKPOINT_RETENTION,fn as DEFAULT_PACK_ID,sn as FILE_SYSTEM_WRITER,Et as FILE_WATCHER_ORIGIN,Tr as GIT_PREFLIGHT_FAIL_SPAN_NAME,zr as GIT_UPSTREAM_WRITER,De as GitDirAccessError,It as GitNotAvailableError,Pr as GitTooOldError,Je as HOCUSPOCUS_AUTH_REJECTION_REASONS,I as HocuspocusAuthRejection,Ar as HocuspocusAuthTokenSchema,Qe as INSTALLED_AGENTS_SCHEMES,W as LIVE_DERIVED_INDEX_DEBOUNCE_MS,B as LOG_MD_TEMPLATE,je as MANAGED_RENAME_ORIGIN,En as MAX_AGENT_SESSIONS,O as MCP_CONNECTION_ID_HEADER,Sn as MCP_SERVER_NAME,Se as MIN_GIT_VERSION,Ee as MISSING_OK_CONFIG_MESSAGE,Ie as MalformedGitPointerError,Fe as McpLogger,J as MissingOkConfigError,oe as OBSERVER_SYNC_ORIGIN,ve as OK_OKIGNORE_TEMPLATE,m as ORPHAN_MODES,We as PANE_TARGET_TTL_MS,x as PROTOCOL_VERSION,Wr as PinoLogger,y as ProcessLockCollisionError,M as ProjectGitInitError,ot as ROLLBACK_ORIGIN,ne as ROOT_GITIGNORE_TEMPLATE,f as RUNTIME_VERSION,nt as SERVICE_WRITER,ut as SKILL_INSTALL_EVENTS_FILE_REL,C as SKILL_STATE_TARGETS,Q as STARTER_FOLDERS,me as STARTER_FOLDER_FRONTMATTER_FILENAME,tr as STARTER_PACKS,ue as STARTER_PACK_IDS,vt as STARTER_TEMPLATES,mt as STATE_MANIFEST_FILENAME,_ as STATE_SCHEMA_VERSION,S as SYSTEM_DOC_NAME,St as SeedPrerequisiteError,Be as SeedRootDirError,l as ServerLockCollisionError,w as StateManifestError,en as TagIndex,yr as UiLockCollisionError,Wn as __getShowAllWalkStatsForTesting,lr as __resetShowAllWalkStatsForTesting,n as acquireProcessLock,p as acquireServerLock,xn as acquireUiLock,Ft as applyAgentMarkdownWrite,Yn as applyExternalChange,mr as applySeed,Gt as armPaneTarget,Pn as assertCompatibleStateManifest,wr as assertGitAvailable,Xt as assertNeverDiskEvent,on as attachIdleShutdown,er as bootServer,zn as buildAndOpenSkill,gn as buildConfigYmlContent,dn as buildExecResult,At as buildInstructions,kr as buildSkillZip,Ur as buildStarterFolderFrontmatterYaml,Bt as buildWipTree,Rr as classifyEvents,Ze as classifyFsPath,z as clearArmedPaneTarget,Nr as clearContributors,tt as coercePackId,r as colorFromSeed,q as commitUpstreamImport,U as commitWip,Pe as commitWipFromTree,kn as compareSemver,j as containsConflictMarkers,Tn as contentHash,Te as contributorCount,Ae as createApiExtension,ze as createAssetServeMiddleware,Z as createContentFilter,le as createContentFilterAsync,xe as createExternalChangeHandler,qe as createFileLogger,qr as createLiveDerivedIndexExtension,F as createMcpHttpHandler,lt as createOsProbe,ae as createPersistenceExtension,at as createServer,pt as createServerObserverExtension,te as createStreamingErrorWriter,_e as createTestLogger,ir as detectClaudeDesktopPresence,pe as detectGit,xt as detectProjectShape,_t as emitPreflightFailureSpan,Tt as encodeDocName,Ue as encodeFolderRoute,D as ensureProjectGit,Qt as errorResponse,_r as evictStaleTrackerEntries,Hn as extractWikiLinksFromMarkdown,sr as fallbackPaths,yn as findEnclosingGitRoot,Nt as findEnclosingProjectRoot,qn as formatAuthRejectionWire,fr as formatContributors,Ut as formatContributorsFrom,Mn as gcCheckpointRefs,Sr as getCurrentMcpLogger,Jt as getLocalDir,rn as getLogFilePath,Qn as getLogger,Ln as getLogsDir,mn as getMeter,ln as getMetrics,Ot as getTracer,Dr as handleCollabSocketError,Vr as handleSpawnCursor,t as iconFromClientName,Rt as incrementCollabSocketFilteredError,Ir as incrementServerObserverFire,Ye as initContent,L as initShadowRepo,jr as initTelemetry,$e as installPrettyZodErrors,G as installTestLoggers,V as installUserSkill,Me as isAllowedApiOrigin,Dn as isAllowedWorkspaceHostHeader,k as isConfigDoc,Cn as isHocuspocusAuthRejectionReason,Ce as isKnownPackId,Oe as isLoopbackAddress,e as isOrphanMode,Le as isPairedWriteOrigin,Y as isPathWithinDir,v as isProcessAlive,se as isProjectRoot,ye as isSelfWrite,Ge as isSystemDoc,i as isValidLockPid,Gr as lastKnownHash,N as listRescueCheckpoints,st as listStarterPacks,re as loadPrincipal,u as lockFilePath,rt as loggerFactory,dt as logsCurrentPath,$ as logsPreviousPath,he as mountMcpAndApi,nr as normalizeFsPath,de as packageVersionMajorMinor,yt as parseAuthRejectionWire,ht as parseGitVersion,Ct as parseHocuspocusAuthToken,Ve as parseKeepaliveConnectionId,T as pathToDocName,$t as planSeed,vr as readAllTargets,Un as readArmedPaneTarget,cr as readBranchFromHead,b as readProcessLock,a as readProcessLockDetailed,o as readServerLock,bn as readServerPackageVersion,Pt as readSkillInstallStateSnapshot,Jn as readStateManifest,pr as readTargetRecordedAt,Wt as readTargetVersion,Nn as readUiLock,Cr as reconcile,Yt as recordContributor,an as recordSkillInstallEvent,$n as registerAllTools,Rn as registerWrite,h as releaseProcessLock,d as releaseServerLock,hn as releaseUiLock,un as removeLastKnownHash,kt as resetMetrics,Or as resolveBundledSkillDir,Hr as resolveContentDir,zt as resolveCursorBinaryDefault,Lr as resolveCursorSpawnInvocation,Xe as resolveLockDir,R as resolvePack,Mr as resolvePackageVersion,et as resolveUiInfo,K as restoreContributors,H as restoreLifecycleFromConflictsJson,Ne as rewriteMarkdownLinksForDocumentRename,On as rewriteWikiLinksForDocumentRename,A as runAuthReposSubprocess,wn as runAuthStatusSubprocess,we as runCloneSubprocess,ke as runDeviceFlowSubprocess,Re as runWithMcpLogger,X as safeContentPath,ce as safeSubdir,be as safetyCheckpoint,Ke as sanitizeClientName,Kr as saveInMemoryCheckpoint,P as saveVersion,ct as seedBasenameIndex,ie as serializeError,it as setActiveSpanAttributes,ft as shadowGit,ee as shutdownTelemetry,ge as spansCurrentPath,rr as spansPreviousPath,fe as spawnDetached,bt as splitMarkdownBlocks,gt as startWatcher,wt as streamingProblemEvent,He as swapContributors,E as toBroadcasterKey,Zt as tracedAppendFileSync,gr as tracedLinkSync,Vn as tracedMkdir,or as tracedMkdirSync,vn as tracedRename,Mt as tracedRenameSync,Kn as tracedRmSync,dr as tracedRmdirSync,Ht as tracedUnlinkSync,jn as tracedWriteFile,xr as tracedWriteFileSync,qt as updateLastKnownHash,c as updateProcessLockPort,s as updateServerLockPort,nn as updateUiLockPort,Zn as validateAgentId,In as validateCloneInputs,pn as validateSkillZip,cn as withSpan,Dt as withSpanSync,Er as writeRootGitignoreForNewRepo,Br as writeStateManifest,Lt as writeTargetVersion,Fr 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:Kc}):successResponse(t,200,LocalOpAuthPatSuccessSchema,D,{handler:Kc})}catch(e){errorResponse(t,500,`urn:ok:error:auth-failed`,`Auth pat failed.`,{handler:Kc,cause:e})}finally{we.release(Pc)}},{handler:Kc,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:Kc})}),Jc=`local-op-auth-identity`;async function Yc(e,t){if(checkLocalOpSecurity(e,t,{handler:Jc})){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:Jc,extraHeaders:{Allow:`GET`}});return}if(!de){errorResponse(t,503,`urn:ok:error:no-project-dir`,`No project directory configured.`,{handler:Jc});return}try{successResponse(t,200,LocalOpAuthIdentitySuccessSchema,{identity:await resolveGitIdentity(de)},{handler:Jc})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Identity resolution failed.`,{handler:Jc,cause:e})}}}let Xc=`/api/local-op/auth/set-identity`,Zc=`local-op-auth-set-identity`,Qc=withValidation(LocalOpAuthSetIdentityRequestSchema,async(e,t,s)=>{let g=s.name.trim(),S=s.email.trim();if(!de){errorResponse(t,503,`urn:ok:error:no-project-dir`,`No project directory configured.`,{handler:Zc});return}if(!we.tryAcquire(Xc)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A set-identity operation is already in progress.`,{handler:Zc,extraHeaders:{"Retry-After":`5`}});return}try{writeGitIdentity(de,g,S),ce?.()?.refreshIdentity().catch(()=>{}),successResponse(t,200,LocalOpAuthEmptySuccessSchema,{},{handler:Zc})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Set-identity failed.`,{handler:Zc,cause:e})}finally{we.release(Xc)}},{handler:Zc,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:Zc})});async function $c(e,t){if(checkLocalOpSecurity(e,t,{handler:`sync-status`})){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`sync-status`,extraHeaders:{Allow:`GET`}});return}try{let e=ce?.();if(!e){successResponse(t,200,SyncStatusSchema,{state:`dormant`,lastSyncUtc:null,lastFetchUtc:null,lastPushedSha:null,ahead:0,behind:0,consecutiveFailures:0,conflictCount:0,hasRemote:!1,syncEnabled:!1,identityUnresolved:!1,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 nl=withValidation(SyncTriggerRequestSchema,async(e,t,s)=>{let g=ce?.();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`})?ce?.()?!0:(errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-trigger`}),!1):!1});async function il(e,t){if(checkLocalOpSecurity(e,t,{handler:`sync-conflicts`})){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`sync-conflicts`,extraHeaders:{Allow:`GET`}});return}try{let e=ce?.();successResponse(t,200,SyncConflictsSuccessSchema,{conflicts:e?e.getConflicts():[]},{handler:`sync-conflicts`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`sync-conflicts`,cause:e})}}}let al=withValidation(SyncResolveConflictRequestSchema,async(e,t,s)=>{let g=ce?.();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`})?ce?.()?!0:(errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-resolve-conflict`}),!1):!1});async function cl(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(!de){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=ce?.(),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:de,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=Ce?Ce(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 ll(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 ul=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 dl(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 fl=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 pl(e,t){if(checkLocalOpSecurity(e,t,{handler:`installed-agents`}))try{await handleInstalledAgents(e,t,Ve.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 ml(e,t){if(!checkLocalOpSecurity(e,t,{handler:`sync-abort-merge`}))return;if(e.method!==`POST`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`sync-abort-merge`,extraHeaders:{Allow:`POST`}});return}let s=ce?.();if(!s){errorResponse(t,503,`urn:ok:error:sync-not-active`,`Sync engine not active.`,{handler:`sync-abort-merge`});return}try{await s.abortMerge(),successResponse(t,200,SyncAbortMergeSuccessSchema,{},{handler:`sync-abort-merge`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to abort merge.`,{handler:`sync-abort-merge`,cause:e})}}let hl=withValidation(EmptyRequestSchema,async(e,t)=>{if(!te){errorResponse(t,503,`urn:ok:error:tag-index-not-configured`,`Tag index not configured.`,{handler:`tags-list`});return}try{successResponse(t,200,TagsListSuccessSchema,{tags:te.getAllTags()},{handler:`tags-list`})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Failed to read tags.`,{handler:`tags-list`,cause:e})}},{handler:`tags-list`,method:`GET`,skipBodyParse:!0});async function gl(e,t,s){if(e.method!==`GET`){errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`tags-for-name`,extraHeaders:{Allow:`GET`}});return}if(!te){errorResponse(t,503,`urn:ok:error:tag-index-not-configured`,`Tag index not configured.`,{handler:`tags-for-name`});return}let 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=te.getDocsForTagWithMatches(g).map(({docName:e,matchingTags:t})=>({docName:e,title:We(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 _l(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 vl=/^[A-Za-z0-9_-]+$/;function yl(e,t,s=`template`){return!e||!vl.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 xl(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 Cl(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 Tl(e,t){if(e.method===`GET`)return El(e,t);if(e.method===`PUT`)return Dl(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`folder-config`,extraHeaders:{Allow:`GET, PUT`}})}let El=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=_l(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}),Dl=withValidation(FolderConfigPutRequestSchema,async(e,t,s)=>{try{let e=_l(s.path,t,`path`,`folder-config-put`);if(!e)return;let g=e.folderRel===``?`**`:`${e.folderRel}/**`,S;if(s.declarations!==void 0){let e=Cl(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:xl(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 Ol(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 kl(e,t){if(e.method===`GET`)return Pl(e,t);if(e.method===`PUT`)return Fl(e,t);if(e.method===`DELETE`)return Il(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`template`,extraHeaders:{Allow:`GET, PUT, DELETE`}})}let jl=/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/,Ml=e=>{let t=e.match(jl),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}},Pl=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`name`)??``;if(!yl(g,t,`template-get`))return;let S=_l(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}=Ml(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}),Fl=withValidation(TemplatePutRequestSchema,async(e,t,s)=>{try{let e=s.name;if(!yl(e,t,`template-put`))return;let g=_l(s.folder,t,`folder`,`template-put`);if(!g||Ol(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:xl(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`}),Il=withValidation(EmptyRequestSchema,async(e,t)=>{try{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`name`)??``;if(!yl(g,t,`template-delete`))return;let S=_l(s.searchParams.get(`folder`)??``,t,`folder`,`template-delete`);if(!S||Ol(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 Ll(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 Rl(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 zl(e){return e===`autocomplete`||e===`full_text`||e===`omnibar`?e:`omnibar`}function Bl(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 Vl(){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,...Ll(e)]}function Hl(){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 Ul(){let e=`${g}${de??``}`,t=Hl(),s=workspaceSearchCaches.get(e);if(s?.fingerprint===t&&s.corpus)return s.corpus;if(s?.fingerprint===t&&s.pending)return s.pending;let S=Vl().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 Wl(){if(process.env.NODE_ENV!==`test`)for(let e of[0,1e3,3e3])setTimeout(()=>{Ul().catch(e=>{console.warn(`[search] Failed to prewarm workspace search cache:`,e)})},e)}Wl();async function Gl(e,t){if(e.method===`GET`)return Kl(e,t);if(e.method===`POST`)return ql(e,t);errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`search`,extraHeaders:{Allow:`GET, POST`}})}let Kl=withValidation(EmptyRequestSchema,async(e,t)=>{let s=new URL(e.url??``,`http://localhost`),g=s.searchParams.get(`limit`),S=s.searchParams.get(`query`)??``,w=zl(s.searchParams.get(`intent`)),E=Bl(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 Ul(),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`?Rl(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}),ql=withValidation(SearchRequestSchema,async(e,t,s)=>{let g=typeof s.query==`string`?s.query:``,S=zl(s.intent),w=Bl(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 Ul(),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`?Rl(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`}),Jl=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 Yl(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 Xl(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 Zl=withValidation(ShareConstructUrlRequestSchema,async(e,t,s)=>{try{if(!de){emitShareConstructUrlLog(`no-remote`),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`no-remote`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}if(!isValidShareDocPath(s.docPath)){emitShareConstructUrlLog(`invalid-path`),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`invalid-path`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}let e=readGitHeadBranch(de);if(e===null){if(readOriginGitHubRepo(de).kind===`no-remote`){emitShareConstructUrlLog(`no-remote`),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`no-remote`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}emitShareConstructUrlLog(`detached-head`),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`detached-head`},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}let g=readOriginGitHubRepo(de);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(de,e)){emitShareConstructUrlLog(`branch-not-on-origin`,!1),successResponse(t,200,ShareConstructUrlResponseSchema,{ok:!1,error:`branch-not-on-origin`,branch:e},{handler:SHARE_CONSTRUCT_URL_HANDLER_TAG});return}let 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(!de){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(de,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}),$l=withValidation(CheckoutRequestSchema,async(e,t,s)=>{if(extractActorIdentity(s,fe).kind===`invalid-summary`){errorResponse(t,400,`urn:ok:error:invalid-request`,`Summary must be a string.`,{handler:CHECKOUT_HANDLER_TAG});return}if(!de){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(de,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 eu(e){let[t,...s]=ue,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 tu=withValidation(EmptyRequestSchema,async(e,t)=>{if(!we.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 eu([`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{we.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})}),nu=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(!we.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 eu([`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{we.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})}),ru=withValidation(SharePublishRequestSchema,async(e,t,s)=>{if(!de){emitSharePublishLog(`publish-create`,`no-project`),successResponse(t,200,SharePublishResponseSchema,{ok:!1,error:`no-project`},{handler:SHARE_PUBLISH_HANDLER_TAG});return}if(!isValidShareOwnerName(s.owner)||!isValidShareRepoName(s.name)){errorResponse(t,400,`urn:ok:error:invalid-request`,`owner and name must be valid GitHub identifiers.`,{handler:SHARE_PUBLISH_HANDLER_TAG});return}if(!we.tryAcquire(`/api/share/publish`)){errorResponse(t,429,`urn:ok:error:concurrent-operation`,`A share publish operation is already in progress.`,{handler:SHARE_PUBLISH_HANDLER_TAG,extraHeaders:{"Retry-After":`5`}});return}try{let e=[`share`,`publish`,`--owner`,s.owner,`--name`,s.name,`--visibility`,s.visibility,`--project-dir`,de,`--json`];s.description!==void 0&&s.description.length>0&&e.push(`--description`,s.description);let{stdout:g}=await eu(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{we.release(SHARE_PUBLISH_KEY)}},{handler:SHARE_PUBLISH_HANDLER_TAG,method:`POST`,preBodyGate:(e,t)=>checkLocalOpSecurity(e,t,{handler:SHARE_PUBLISH_HANDLER_TAG})}),iu=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`})}),au=de?getLocalDir(de):null;async function ou(e,t){if(e.method===`DELETE`){let s=e.socket?.remoteAddress;if(s!==void 0&&!isLoopbackAddress(s)){errorResponse(t,403,`urn:ok:error:loopback-required`,`Loopback required.`,{handler:`api-config`});return}if(!isAllowedWorkspaceHostHeader(e.headers.host)){errorResponse(t,403,`urn:ok:error:host-not-allowed`,`Host header not allowed.`,{handler:`api-config`});return}au&&clearArmedPaneTarget(au),t.setHeader(`Cache-Control`,`no-store`),t.statusCode=204,t.end();return}if(e.method===`GET`||e.method===`HEAD`){try{let s=e.headers.host,g={collabUrl:s?`ws://${s}/collab`:null,previewUrl:null,port:au?readServerLock(au)?.port??0:0,paneTarget:au?readArmedPaneTarget(au):null};if(e.method===`HEAD`){t.setHeader(`Content-Type`,`application/json`),t.setHeader(`Cache-Control`,`no-store`),t.setHeader(`X-Content-Type-Options`,`nosniff`),t.statusCode=200,t.end();return}successResponse(t,200,ApiConfigSuccessSchema,g,{handler:`api-config`,extraHeaders:{"Cache-Control":`no-store`}})}catch(e){errorResponse(t,500,`urn:ok:error:internal-server-error`,`Internal server error.`,{handler:`api-config`,cause:e})}return}errorResponse(t,405,`urn:ok:error:method-not-allowed`,`Method not allowed.`,{handler:`api-config`,extraHeaders:{Allow:`GET, HEAD, DELETE`}})}let su={"/api/config":ou,"/api/asset":tc,"/api/asset-text":rc,"/api/document":Yr,"/api/documents":Xr,"/api/backlinks":Zr,"/api/backlink-counts":Qr,"/api/forward-links":ji,"/api/link-graph":Hi,"/api/dead-links":Ki,"/api/orphans":Ui,"/api/hubs":Gi,"/api/tags":hl,"/api/pages":mc,"/api/folder-config":Tl,"/api/template":kl,"/api/search":Gl,"/api/suggest-links":hc,"/api/page-headings":uc,"/api/create-page":sc,"/api/create-folder":cc,"/api/duplicate-path":lc,"/api/rename-path":dc,"/api/delete-path":fc,"/api/trash/cleanup":pc,"/api/upload":gc,"/api/agent-write":Gr,"/api/agent-write-md":Kr,"/api/frontmatter-patch":qr,"/api/agent-patch":Yi,"/api/agent-undo":Xi,"/api/agent-activity":Zi,"/api/agent-burst-diff":ka,"/api/save-version":Ts,"/api/history":Ds,"/api/diff":ks,"/api/rollback":As,"/api/metrics/reconciliation":Ns,"/api/metrics/parse-health":Ps,"/api/metrics/agent-presence":$s,"/api/server-info":Is,"/api/share/construct-url":Zl,"/api/git/branch-info":Ql,"/api/git/checkout":$l,"/api/share/publish/owners":tu,"/api/share/publish/name-check":nu,"/api/share/publish":ru,"/api/principal":Rs,"/api/rescue":ac,"/api/workspace":ec,"/api/sync/status":$c,"/api/sync/trigger":nl,"/api/sync/conflicts":il,"/api/sync/conflict-content":cl,"/api/sync/resolve-conflict":al,"/api/sync/abort-merge":ml,"/api/local-op/clone":Cc,"/api/local-op/open":Dc,"/api/local-op/ok-init":kc,"/api/local-op/auth/login":Lc,"/api/local-op/auth/status":Bc,"/api/local-op/auth/repos":Hc,"/api/local-op/auth/signout":Gc,"/api/local-op/auth/pat":qc,"/api/local-op/auth/identity":Yc,"/api/local-op/auth/set-identity":Qc,"/api/installed-agents":pl,"/api/spawn-cursor":Xl,"/api/handoff":Yl,"/api/install-skill":fl,"/api/skill/install-state":Jl,"/api/seed/plan":ll,"/api/seed/apply":ul,"/api/seed/packs":dl,"/api/client-logs":iu};j&&(su[`/api/test-reset`]=_s,su[`/api/test-rescan-backlinks`]=xs,su[`/api/test-rescan-files`]=Cs);let cu=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(`.`)),lu=[`/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(cu.has(s)||lu.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`:su[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=su[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 oc(e,t,g))}else if(s.startsWith(`/api/history/`)){let g=decodeURIComponent(s.slice(13));g&&(E=!0,await Os(e,t,g))}else if(s.startsWith(`/api/tags/`)){let g=s.slice(10);g&&(E=!0,await gl(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")`; 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(`
|
|
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, e.g. the Claude Code CLI) → for an "open `<doc>`/`<folder>`" request, run **`ok open <doc>`** (`--folder` for a folder) — opens the doc in OK Desktop via deep link (folders in the browser), with browser fallback; an action, not a URL to print. No `ok` on PATH or no shell → `get_preview_url`, then `open <url>` in the system browser as a last resort, and say so plainly. 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}
|
|
@@ -2104,7 +2104,7 @@ superseded_by: <path-to-new-canonical-article>.md
|
|
|
2104
2104
|
- **Don't rewrite research prose verbatim** — canonical articles have a different voice (direct, decided) than research (exploratory, provisional)
|
|
2105
2105
|
- **Don't skip the supersedes / superseded_by links** — the audit trail matters for future readers
|
|
2106
2106
|
`}const DESCRIPTION$22=[`Returns a step-by-step plan to promote stabilized research into a canonical article. Does NOT write — you execute the plan after a STOP gate confirms a real decision was made.`,"Canonical, not provisional — the output becomes the source of truth, with a `supersedes` trail back to the research.",`Use when a team has decided after research and wants the outcome committed as authoritative knowledge.`].join(`
|
|
2107
|
-
`);function register$22(e,t){e.registerTool(`consolidate`,{description:DESCRIPTION$22,inputSchema:{topic:string().describe(`The topic to consolidate into a canonical article`),cwd:string().optional().describe(ROUTED_CWD_DESCRIPTION)}},buildWorkflowHandler(`consolidate`,t,`topic`,buildBody$2))}const PREVIEW_URL_SOURCES=[`lock`];function encodeDocName(e){return e.split(`/`).map(encodeURIComponent).join(`/`)}const START_UI_MESSAGE='No UI is running for this project. Start one to see the preview: `ok ui` (terminal), `preview_start("open-knowledge-ui")` (Claude Code Desktop), or open the project in OK Electron.',ATTACH_PREVIEW_ONCE_MESSAGE=`No browser is attached to the preview. Open it with preview_start, or call get_preview_url for the URL.`;function buildPreviewAttachWarning(e,t){return e?{action:`attach-preview-once`,previewUrl:e.url,message:ATTACH_PREVIEW_ONCE_MESSAGE,autoOpen:t}:{action:`start-ui`,previewUrl:null,message:START_UI_MESSAGE,autoOpen:t}}const START_UI_TEXT_HINT=START_UI_MESSAGE;async function resolvePreviewUrlForTool(e,t,s){return resolvePreviewUrl(e,{lockDir:resolveLockDir(s??await t.resolveCwd())})}function resolveUiInfo(e){try{let t=readUiLock(e.lockDir);if(t&&t.port>0)return{baseUrl:`http://localhost:${t.port}`}}catch(t){process.stderr.write(`[preview-url] readUiLock failed at ${e.lockDir} while resolving ui info: ${t instanceof Error?t.message:String(t)}\n`)}return{baseUrl:null}}async function buildListResolver(e,t){let s={lockDir:resolveLockDir(t??await e.resolveCwd())};return{resolve:e=>resolvePreviewUrl(e,s)}}function docNameFromPath(e){let t=e.toLowerCase();return t.endsWith(`.md`)?e.slice(0,-3):t.endsWith(`.mdx`)?e.slice(0,-4):e}function resolvePreviewUrl(e,t){let s=`/#/${encodeDocName(e)}`;try{let e=readUiLock(t.lockDir);if(e&&e.port>0)return{url:s,source:`lock`}}catch(e){process.stderr.write(`[preview-url] readUiLock failed at ${t.lockDir}: ${e instanceof Error?e.message:String(e)}\n`)}return null}const DESCRIPTION$21=["[Requires: Hocuspocus server] Delete a document through the managed delete flow at `POST /api/delete-path` (kind: file).",`Closes all open agent sessions for the doc, unloads it from Hocuspocus, and removes the file from disk.`,``,`**Parameters:**`,"- `docName` — A single document to delete, typically extension-less. A trailing `.md` or `.mdx` is stripped automatically.","- `docNames` — Batch form: an array of documents to delete in one call. Mutually exclusive with `docName`. Each is deleted independently; the response reports per-doc status.",``,`**Notes:**`,'- Inbound wiki-links to the deleted doc become dead links (redlinks) — they are NOT rewritten. Call `links({ kind: "backlinks", docName: "your-doc" })` BEFORE deleting to see which docs link here, then update or remove those references first.','- Deletion is irreversible from this tool. Use `version({ action: "save" })` beforehand if you may need to roll back.',"- The structured response includes `previousPreviewUrl` (when a preview source resolves) so agents can close any stale preview tab pointing at the deleted doc.",``,`**Errors:**`,"- 400 — `docName` is not a valid relative content path.",`- 404 — document does not exist.`].join(`
|
|
2107
|
+
`);function register$22(e,t){e.registerTool(`consolidate`,{description:DESCRIPTION$22,inputSchema:{topic:string().describe(`The topic to consolidate into a canonical article`),cwd:string().optional().describe(ROUTED_CWD_DESCRIPTION)}},buildWorkflowHandler(`consolidate`,t,`topic`,buildBody$2))}const PREVIEW_URL_SOURCES=[`lock`];function encodeDocName(e){return e.split(`/`).map(encodeURIComponent).join(`/`)}function encodeFolderRoute(e){let t=e.replace(/^\/+|\/+$/g,``);return t?`${encodeDocName(t)}/`:``}const START_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 Desktop), or open the project in OK Electron.',ATTACH_PREVIEW_ONCE_MESSAGE=`No browser is attached to the preview. Open it with preview_start, or call get_preview_url for the URL.`;function buildPreviewAttachWarning(e,t){return e?{action:`attach-preview-once`,previewUrl:e.url,message:ATTACH_PREVIEW_ONCE_MESSAGE,autoOpen:t}:{action:`start-ui`,previewUrl:null,message:START_UI_MESSAGE,autoOpen:t}}const START_UI_TEXT_HINT=START_UI_MESSAGE;async function resolvePreviewUrlForTool(e,t,s){return resolvePreviewUrl(e,{lockDir:resolveLockDir(s??await t.resolveCwd())})}function resolveUiInfo(e){try{let t=readUiLock(e.lockDir);if(t&&t.port>0)return{baseUrl:`http://localhost:${t.port}`}}catch(t){process.stderr.write(`[preview-url] readUiLock failed at ${e.lockDir} while resolving ui info: ${t instanceof Error?t.message:String(t)}\n`)}return{baseUrl:null}}async function buildListResolver(e,t){let s={lockDir:resolveLockDir(t??await e.resolveCwd())};return{resolve:e=>resolvePreviewUrl(e,s)}}function docNameFromPath(e){let t=e.toLowerCase();return t.endsWith(`.md`)?e.slice(0,-3):t.endsWith(`.mdx`)?e.slice(0,-4):e}function resolvePreviewUrl(e,t){let s=`/#/${encodeDocName(e)}`;try{let e=readUiLock(t.lockDir);if(e&&e.port>0)return{url:s,source:`lock`}}catch(e){process.stderr.write(`[preview-url] readUiLock failed at ${t.lockDir}: ${e instanceof Error?e.message:String(e)}\n`)}return null}const DESCRIPTION$21=["[Requires: Hocuspocus server] Delete a document through the managed delete flow at `POST /api/delete-path` (kind: file).",`Closes all open agent sessions for the doc, unloads it from Hocuspocus, and removes the file from disk.`,``,`**Parameters:**`,"- `docName` — A single document to delete, typically extension-less. A trailing `.md` or `.mdx` is stripped automatically.","- `docNames` — Batch form: an array of documents to delete in one call. Mutually exclusive with `docName`. Each is deleted independently; the response reports per-doc status.",``,`**Notes:**`,'- Inbound wiki-links to the deleted doc become dead links (redlinks) — they are NOT rewritten. Call `links({ kind: "backlinks", docName: "your-doc" })` BEFORE deleting to see which docs link here, then update or remove those references first.','- Deletion is irreversible from this tool. Use `version({ action: "save" })` beforehand if you may need to roll back.',"- The structured response includes `previousPreviewUrl` (when a preview source resolves) so agents can close any stale preview tab pointing at the deleted doc.",``,`**Errors:**`,"- 400 — `docName` is not a valid relative content path.",`- 404 — document does not exist.`].join(`
|
|
2108
2108
|
`);function parseDeletedDocNames(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}async function deleteOne(e,t,s,g){let S=normalizeDocName(e);if(!S.ok)return{docName:e,ok:!1,error:S.error};let w=g.identityRef?.current,E=await httpPost(t,`/api/delete-path`,{kind:`file`,path:S.docName,...w?{agentId:w.connectionId,agentName:w.displayName,clientName:w.clientInfo?.name,colorSeed:w.colorSeed}:{}});if(!E.ok)return{docName:S.docName,ok:!1,error:E.error};let D=parseDeletedDocNames(E.deletedDocNames),O=await resolvePreviewUrlForTool(S.docName,{config:g.config,resolveCwd:g.resolveCwd},s);return{docName:S.docName,ok:!0,deletedDocNames:D.length>0?D:[S.docName],...O?{previousPreviewUrl:O.url}:{}}}function register$21(e,t){e.registerTool(`delete_document`,{description:DESCRIPTION$21,inputSchema:{docName:string().optional().describe(`A single document to delete.`),docNames:array(string()).min(1).optional().describe("Batch: documents to delete in one call. Mutually exclusive with `docName`."),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);if(e.docName===void 0&&e.docNames===void 0)return textResult("Error: provide `docName` (single) or `docNames` (batch).",!0);if(e.docName!==void 0&&e.docNames!==void 0)return textResult("Error: `docName` and `docNames` are mutually exclusive.",!0);if(e.docNames!==void 0){let s=await Promise.all(e.docNames.map(e=>deleteOne(e,S,g,t))),w=s.filter(e=>e.ok).length,E=w===s.length,D=s.map(e=>e.ok?`Deleted ${e.docName}.`:`Failed ${e.docName}: ${e.error}`);return textPlusStructured(`${w}/${s.length} deleted.\n${D.join(`
|
|
2109
2109
|
`)}`,{ok:E,documents:s},!E)}let w=await deleteOne(e.docName,S,g,t);if(!w.ok){let e={ok:!1,error:w.error??`unknown error`};return textPlusStructured(`Error: ${e.error}`,e,!0)}let E=w.deletedDocNames??[w.docName],D={ok:!0,deletedDocNames:E,...w.previousPreviewUrl?{previousPreviewUrl:w.previousPreviewUrl}:{}};return textPlusStructured(E.length===1?`Deleted ${E[0]}.`:`Deleted ${E.length} documents: ${E.join(`, `)}.`,D)})}function buildDiscoverBody(e){return`# Discover — Project Convention Extraction + Link Graph Activation
|
|
2110
2110
|
|
|
@@ -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.
|
|
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)}
|
|
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. Hosts with a preview pane (Claude Code Desktop) call `preview_start("open-knowledge-ui")` instead; the Claude Code CLI uses `ok open <doc>` to open in the OK Desktop app.',``,"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)},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 ee(){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 Y=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!==Y)throw new HocuspocusAuthRejection(`server-instance-mismatch`,`server instance mismatch: client claimed ${g}, this server is ${Y}`);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 ee(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:ee,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:Y,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(),takeStoreFailure:e=>fe.takeStoreFailure(e),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(Y,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=ee();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:ee(),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:Y,destroy:Ht,ready:Ie,degraded:Ut,lockDir:te,get syncEngine(){return zt}}}const SERVER_MEMORY_SCHEMA_VERSION=1,BYTES_PER_MB=1024*1024;function toMb(e){return e/BYTES_PER_MB}function captureServerMemorySnapshot(){let e=process.memoryUsage();return{schemaVersion:SERVER_MEMORY_SCHEMA_VERSION,capturedAt:new Date().toISOString(),snapshot:{rssMb:toMb(e.rss),heapTotalMb:toMb(e.heapTotal),heapUsedMb:toMb(e.heapUsed),externalMb:toMb(e.external),arrayBuffersMb:toMb(e.arrayBuffers)}}}let cachedGauge=null;onTelemetryShutdown(()=>{cachedGauge=null});function installServerMemoryGauge(){if(cachedGauge)return;let e=getMeter().createObservableGauge(`ok.server.memory.usage_megabytes`,{description:`Server process memory by section. Bounded labels: section ∈ {heap_used, heap_total, rss}.`,unit:`MB`});e.addCallback(e=>{let{snapshot:t}=captureServerMemorySnapshot();e.observe(t.heapUsedMb,{section:`heap_used`}),e.observe(t.heapTotalMb,{section:`heap_total`}),e.observe(t.rssMb,{section:`rss`})}),cachedGauge=e}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}),installServerMemoryGauge();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-B9YGymFa.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:ee,degraded:Y,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:ee,degraded:Y,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{StateManifestError as $,readAllTargets as $n,tracedMkdir as $r,evictStaleTrackerEntries as $t,MCP_CONNECTION_ID_HEADER as A,GitDirAccessError as Ai,isKnownPackId as An,runDeviceFlowSubprocess as Ar,containsConflictMarkers as At,ProjectGitInitError as B,loadPrincipal as Bn,setActiveSpanAttributes as Br,createMcpHttpHandler as Bt,HocuspocusAuthRejection as C,isJSONRPCRequest as Ci,installPrettyZodErrors as Cn,restoreContributors as Cr,clearArmedPaneTarget as Ct,LOG_MD_TEMPLATE as D,resolveConfigPath as Di,isAllowedWorkspaceHostHeader as Dn,runAuthReposSubprocess as Dr,commitWip as Dt,LIVE_DERIVED_INDEX_DEBOUNCE_MS as E,readConfigSafely as Ei,isAllowedApiOrigin as En,rewriteWikiLinksForDocumentRename as Er,commitUpstreamImport as Et,MissingOkConfigError as F,isSelfWrite as Fn,sanitizeClientName as Fr,createContentFilter as Ft,STARTER_FOLDERS as G,normalizeFsPath as Gn,spawnDetached as Gr,createStreamingErrorWriter as Gt,ROOT_GITIGNORE_TEMPLATE as H,logsCurrentPath as Hn,shutdownTelemetry as Hr,createPersistenceExtension as Ht,OBSERVER_SYNC_ORIGIN as I,isSystemDoc as In,saveInMemoryCheckpoint as Ir,createContentFilterAsync as It,STARTER_PACK_IDS as J,parseGitVersion as Jn,streamingProblemEvent as Jr,detectGit as Jt,STARTER_FOLDER_FRONTMATTER_FILENAME as K,packageVersionMajorMinor as Kn,splitMarkdownBlocks as Kr,createTestLogger as Kt,OK_OKIGNORE_TEMPLATE as L,lastKnownHash as Ln,saveVersion as Lr,createExternalChangeHandler as Lt,MIN_GIT_VERSION as M,resolveGitDirDetailed as Mi,isPairedWriteOrigin as Mn,safeContentPath as Mr,contributorCount as Mt,MISSING_OK_CONFIG_MESSAGE as N,resolveShadowDir as Ni,isPathWithinDir as Nn,safeSubdir as Nr,createApiExtension as Nt,MANAGED_RENAME_ORIGIN as O,withFileLockSync as Oi,isConfigDoc as On,runAuthStatusSubprocess as Or,commitWipFromTree as Ot,McpLogger as P,isProjectRoot as Pn,safetyCheckpoint as Pr,createAssetServeMiddleware as Pt,SeedRootDirError as Q,planSeed as Qn,tracedLinkSync as Qr,errorResponse as Qt,PANE_TARGET_TTL_MS as R,listRescueCheckpoints as Rn,seedBasenameIndex as Rr,createFileLogger as Rt,HOCUSPOCUS_AUTH_REJECTION_REASONS as S,isInitializedNotification as Si,initTelemetry as Sn,resolvePackageVersion as Sr,classifyFsPath as St,INSTALLED_AGENTS_SCHEMES as T,atomicWriteFileSync as Ti,installUserSkill as Tn,rewriteMarkdownLinksForDocumentRename as Tr,coercePackId as Tt,SERVICE_WRITER as U,logsPreviousPath as Un,spansCurrentPath as Ur,createServer$1 as Ut,ROLLBACK_ORIGIN as V,loggerFactory as Vn,shadowGit as Vr,createOsProbe as Vt,SKILL_INSTALL_EVENTS_FILE_REL as W,mountMcpAndApi as Wn,spansPreviousPath as Wr,createServerObserverExtension as Wt,STATE_MANIFEST_FILENAME as X,parseKeepaliveConnectionId as Xn,toBroadcasterKey as Xr,emitPreflightFailureSpan as Xt,STARTER_TEMPLATES as Y,parseHocuspocusAuthToken as Yn,swapContributors as Yr,detectProjectShape as Yt,SeedPrerequisiteError as Z,pathToDocName as Zn,tracedAppendFileSync as Zr,ensureProjectGit as Zt,FILE_WATCHER_ORIGIN as _,writeTargetVersion as _i,handleSpawnCursor as _n,resolveContentDir as _r,buildInstructions as _t,AgentPresenceBroadcaster as a,tracedUnlinkSync as ai,formatContributors as an,readTargetRecordedAt as ar,applyAgentMarkdownWrite as at,GitNotAvailableError as b,JSONRPCMessageSchema as bi,initContent as bn,resolveLockDir as br,buildWipTree as bt,BacklinkIndex as c,updateLastKnownHash as ci,getCurrentMcpLogger as cn,reconcile as cr,armPaneTarget as ct,CONFLICT_MARKER_RE as d,validateCloneInputs as di,getLogger as dn,registerAllTools as dr,assertNeverDiskEvent as dt,tracedMkdirSync as ei,extractWikiLinksFromMarkdown as en,readArmedPaneTarget as er,TagIndex as et,CURSOR_BUNDLE_PATHS_BY_PLATFORM as f,validateSkillZip as fi,getLogsDir as fn,registerWrite as fr,attachIdleShutdown as ft,FILE_SYSTEM_WRITER as g,writeStateManifest as gi,handleCollabSocketError as gn,resolveBundledSkillDir as gr,buildExecResult as gt,DEFAULT_PACK_ID as h,writeRootGitignoreForNewRepo as hi,getTracer as hn,resetMetrics as hr,buildConfigYmlContent as ht,AgentFocusBroadcaster as i,tracedRmdirSync as ii,formatAuthRejectionWire as in,readStateManifest as ir,acquireUiLock as it,MCP_SERVER_NAME as j,MalformedGitPointerError as ji,isLoopbackAddress as jn,runWithMcpLogger as jr,contentHash as jt,MAX_AGENT_SESSIONS as k,writeConfigPatch as ki,isHocuspocusAuthRejectionReason as kn,runCloneSubprocess as kr,compareSemver as kt,CC1Broadcaster as l,updateUiLockPort as li,getLocalDir as ln,recordContributor as lr,assertCompatibleStateManifest as lt,DEFAULT_CHECKPOINT_RETENTION as m,withSpanSync as mi,getMetrics as mn,removeLastKnownHash as mr,buildAndOpenSkill as mt,AGENT_ID_RE as n,tracedRenameSync as ni,findEnclosingGitRoot as nn,readServerPackageVersion as nr,__getShowAllWalkStatsForTesting as nt,AgentSessionCapacityError as o,tracedWriteFile as oi,formatContributorsFrom as on,readTargetVersion as or,applyExternalChange as ot,ConfigSchema as p,withSpan as pi,getMeter as pn,releaseUiLock as pr,bootServer as pt,STARTER_PACKS as q,parseAuthRejectionWire as qn,startWatcher as qr,detectClaudeDesktopPresence as qt,AGENT_WRITE_ORIGIN as r,tracedRmSync as ri,findEnclosingProjectRoot as rn,readSkillInstallStateSnapshot as rr,__resetShowAllWalkStatsForTesting as rt,AgentSessionManager as s,tracedWriteFileSync as si,gcCheckpointRefs as sn,readUiLock as sr,applySeed as st,AGENT_ID_MAX_LEN as t,tracedRename as ti,fallbackPaths as tn,readBranchFromHead as tr,UiLockCollisionError as tt,CONFIG_FILENAME as u,validateAgentId as ui,getLogFilePath as un,recordSkillInstallEvent as ur,assertGitAvailable as ut,GIT_PREFLIGHT_FAIL_SPAN_NAME as v,writeTracker as vi,incrementCollabSocketFilteredError as vn,resolveCursorBinaryDefault as vr,buildSkillZip as vt,HocuspocusAuthTokenSchema as w,isJSONRPCResultResponse as wi,installTestLoggers as wn,restoreLifecycleFromConflictsJson as wr,clearContributors as wt,GitTooOldError as x,LATEST_PROTOCOL_VERSION as xi,initShadowRepo as xn,resolvePack as xr,classifyEvents as xt,GIT_UPSTREAM_WRITER as y,McpServer as yi,incrementServerObserverFire as yn,resolveCursorSpawnInvocation as yr,buildStarterFolderFrontmatterYaml as yt,PinoLogger as z,listStarterPacks as zn,serializeError as zr,createLiveDerivedIndexExtension as zt};
|
|
3084
|
-
//# sourceMappingURL=dist-
|
|
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 $,pathToDocName as $n,toBroadcasterKey as $r,ensureProjectGit as $t,MCP_CONNECTION_ID_HEADER as A,resolveConfigPath as Ai,isConfigDoc as An,runAuthReposSubprocess as Ar,containsConflictMarkers as At,ProjectGitInitError as B,listRescueCheckpoints as Bn,saveVersion as Br,createMcpHttpHandler as Bt,HocuspocusAuthRejection as C,JSONRPCMessageSchema as Ci,initShadowRepo as Cn,resolvePack as Cr,clearArmedPaneTarget as Ct,LOG_MD_TEMPLATE as D,isJSONRPCResultResponse as Di,installUserSkill as Dn,restoreLifecycleFromConflictsJson as Dr,commitWip as Dt,LIVE_DERIVED_INDEX_DEBOUNCE_MS as E,isJSONRPCRequest as Ei,installTestLoggers as En,restoreContributors as Er,commitUpstreamImport as Et,MissingOkConfigError as F,resolveGitDirDetailed as Fi,isPathWithinDir as Fn,safeContentPath as Fr,createContentFilter as Ft,STARTER_FOLDERS as G,logsPreviousPath as Gn,shutdownTelemetry as Gr,createStreamingErrorWriter as Gt,ROOT_GITIGNORE_TEMPLATE as H,loadPrincipal as Hn,serializeError as Hr,createPersistenceExtension as Ht,OBSERVER_SYNC_ORIGIN as I,resolveShadowDir as Ii,isProjectRoot as In,safeSubdir as Ir,createContentFilterAsync as It,STARTER_PACK_IDS as J,packageVersionMajorMinor as Jn,spawnDetached as Jr,detectGit as Jt,STARTER_FOLDER_FRONTMATTER_FILENAME as K,mountMcpAndApi as Kn,spansCurrentPath as Kr,createTestLogger as Kt,OK_OKIGNORE_TEMPLATE as L,isSelfWrite as Ln,safetyCheckpoint as Lr,createExternalChangeHandler as Lt,MIN_GIT_VERSION as M,writeConfigPatch as Mi,isKnownPackId as Mn,runCloneSubprocess as Mr,contributorCount as Mt,MISSING_OK_CONFIG_MESSAGE as N,GitDirAccessError as Ni,isLoopbackAddress as Nn,runDeviceFlowSubprocess as Nr,createApiExtension as Nt,MANAGED_RENAME_ORIGIN as O,atomicWriteFileSync as Oi,isAllowedApiOrigin as On,rewriteMarkdownLinksForDocumentRename as Or,commitWipFromTree as Ot,McpLogger as P,MalformedGitPointerError as Pi,isPairedWriteOrigin as Pn,runWithMcpLogger as Pr,createAssetServeMiddleware as Pt,SeedRootDirError as Q,parseKeepaliveConnectionId as Qn,swapContributors as Qr,encodeFolderRoute as Qt,PANE_TARGET_TTL_MS as R,isSystemDoc as Rn,sanitizeClientName as Rr,createFileLogger as Rt,HOCUSPOCUS_AUTH_REJECTION_REASONS as S,McpServer as Si,initContent as Sn,resolveLockDir as Sr,classifyFsPath as St,INSTALLED_AGENTS_SCHEMES as T,isInitializedNotification as Ti,installPrettyZodErrors as Tn,resolveUiInfo as Tr,coercePackId as Tt,SERVICE_WRITER as U,loggerFactory as Un,setActiveSpanAttributes as Ur,createServer$1 as Ut,ROLLBACK_ORIGIN as V,listStarterPacks as Vn,seedBasenameIndex as Vr,createOsProbe as Vt,SKILL_INSTALL_EVENTS_FILE_REL as W,logsCurrentPath as Wn,shadowGit as Wr,createServerObserverExtension as Wt,STATE_MANIFEST_FILENAME as X,parseGitVersion as Xn,startWatcher as Xr,emitPreflightFailureSpan as Xt,STARTER_TEMPLATES as Y,parseAuthRejectionWire as Yn,splitMarkdownBlocks as Yr,detectProjectShape as Yt,SeedPrerequisiteError as Z,parseHocuspocusAuthToken as Zn,streamingProblemEvent as Zr,encodeDocName as Zt,FILE_WATCHER_ORIGIN as _,withSpanSync as _i,getTracer as _n,resetMetrics as _r,buildInstructions as _t,AgentPresenceBroadcaster as a,tracedRenameSync as ai,findEnclosingProjectRoot as an,readSkillInstallStateSnapshot as ar,applyAgentMarkdownWrite as at,GitNotAvailableError as b,writeTargetVersion as bi,incrementCollabSocketFilteredError as bn,resolveCursorBinaryDefault as br,buildWipTree as bt,BacklinkIndex as c,tracedUnlinkSync as ci,formatContributorsFrom as cn,readTargetVersion as cr,armPaneTarget as ct,CONFLICT_MARKER_RE as d,updateLastKnownHash as di,getLocalDir as dn,recordContributor as dr,assertNeverDiskEvent as dt,tracedAppendFileSync as ei,errorResponse as en,planSeed as er,TagIndex as et,CURSOR_BUNDLE_PATHS_BY_PLATFORM as f,updateUiLockPort as fi,getLogFilePath as fn,recordSkillInstallEvent as fr,attachIdleShutdown as ft,FILE_SYSTEM_WRITER as g,withSpan as gi,getMetrics as gn,removeLastKnownHash as gr,buildExecResult as gt,DEFAULT_PACK_ID as h,validateSkillZip as hi,getMeter as hn,releaseUiLock as hr,buildConfigYmlContent as ht,AgentFocusBroadcaster as i,tracedRename as ii,findEnclosingGitRoot as in,readServerPackageVersion as ir,acquireUiLock as it,MCP_SERVER_NAME as j,withFileLockSync as ji,isHocuspocusAuthRejectionReason as jn,runAuthStatusSubprocess as jr,contentHash as jt,MAX_AGENT_SESSIONS as k,readConfigSafely as ki,isAllowedWorkspaceHostHeader as kn,rewriteWikiLinksForDocumentRename as kr,compareSemver as kt,CC1Broadcaster as l,tracedWriteFile as li,gcCheckpointRefs as ln,readUiLock as lr,assertCompatibleStateManifest as lt,DEFAULT_CHECKPOINT_RETENTION as m,validateCloneInputs as mi,getLogsDir as mn,registerWrite as mr,buildAndOpenSkill as mt,AGENT_ID_RE as n,tracedMkdir as ni,extractWikiLinksFromMarkdown as nn,readArmedPaneTarget as nr,__getShowAllWalkStatsForTesting as nt,AgentSessionCapacityError as o,tracedRmSync as oi,formatAuthRejectionWire as on,readStateManifest as or,applyExternalChange as ot,ConfigSchema as p,validateAgentId as pi,getLogger as pn,registerAllTools as pr,bootServer as pt,STARTER_PACKS as q,normalizeFsPath as qn,spansPreviousPath as qr,detectClaudeDesktopPresence as qt,AGENT_WRITE_ORIGIN as r,tracedMkdirSync as ri,fallbackPaths as rn,readBranchFromHead as rr,__resetShowAllWalkStatsForTesting as rt,AgentSessionManager as s,tracedRmdirSync as si,formatContributors as sn,readTargetRecordedAt as sr,applySeed as st,AGENT_ID_MAX_LEN as t,tracedLinkSync as ti,evictStaleTrackerEntries as tn,readAllTargets as tr,UiLockCollisionError as tt,CONFIG_FILENAME as u,tracedWriteFileSync as ui,getCurrentMcpLogger as un,reconcile as ur,assertGitAvailable as ut,GIT_PREFLIGHT_FAIL_SPAN_NAME as v,writeRootGitignoreForNewRepo as vi,handleCollabSocketError as vn,resolveBundledSkillDir as vr,buildSkillZip as vt,HocuspocusAuthTokenSchema as w,LATEST_PROTOCOL_VERSION as wi,initTelemetry as wn,resolvePackageVersion as wr,clearContributors as wt,GitTooOldError as x,writeTracker as xi,incrementServerObserverFire as xn,resolveCursorSpawnInvocation as xr,classifyEvents as xt,GIT_UPSTREAM_WRITER as y,writeStateManifest as yi,handleSpawnCursor as yn,resolveContentDir as yr,buildStarterFolderFrontmatterYaml as yt,PinoLogger as z,lastKnownHash as zn,saveInMemoryCheckpoint as zr,createLiveDerivedIndexExtension as zt};
|
|
3084
|
+
//# sourceMappingURL=dist-DpfmiCV4.mjs.map
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{i as e,r as t,t as n}from"./gh-detect-B32mymgh.mjs";import{A as r,C as i,D as a,E as o,O as s,S as c,T as l,_ as u,b as d,d as f,g as p,h as m,i as h,j as g,k as _,o as v,r as y,s as b,t as x,w as S,x as C,y as w}from"./init-
|
|
1
|
+
import{i as e,r as t,t as n}from"./gh-detect-B32mymgh.mjs";import{A as r,C as i,D as a,E as o,O as s,S as c,T as l,_ as u,b as d,d as f,g as p,h as m,i as h,j as g,k as _,o as v,r as y,s as b,t as x,w as S,x as C,y as w}from"./init-BnZOMZQO.mjs";import{l as T,n as E,r as D,t as O,u as k}from"./src-DlZY1w-G.mjs";import{n as A}from"./loader-DDiDxthB.mjs";import{n as j}from"./preview-CSNkLWHD.mjs";import{n as M,t as N}from"./mcp-migrate-event-BF8ILHwp.mjs";export{a as ALL_EDITOR_IDS,s as EDITOR_LABELS,_ as EDITOR_TARGETS,x as LAUNCH_CONFIG_NAME,y as LAUNCH_UI_CHAIN_SENTINEL,h as LAUNCH_UI_CHAIN_V1,d as addOkPathsToGitExclude,r as buildManagedServerEntry,N as buildMcpConfigMigrateEvent,v as classifyExistingMcpEntry,t as createTokenStore,n as detectGh,b as detectInstalledEditors,C as formatTrackedRemediation,c as getExcludedOkPaths,i as getOkArtifactPaths,g as isEntryUpToDate,A as loadConfig,e as makeLazyProbeTokenStore,T as parseGitHubBlobUrl,k as parseGitUrl,j as previewContent,S as probeTrackedOkPaths,f as readExistingMcpEntry,l as readSharingMode,o as removeOkPathsFromGitExclude,w as resolveProjectRoot,D as runStop,m as scaffoldLaunchJson,M as truncatePriorEntry,E as validateLocalFolderForShare,p as writeEditorMcpConfig,O as writeProjectAiIntegrations,u as writeUserMcpConfigs};
|