@schoolai/shipyard 3.7.0 → 3.8.0-rc.20260529.0
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/{auth-SS7LV5XK.js → auth-EXHO3AG5.js} +4 -4
- package/dist/capability-detector-worker.js +142 -0
- package/dist/capability-detector-worker.js.map +1 -0
- package/dist/{chunk-DKMDBOFU.js → chunk-2CNIEBKO.js} +21 -11
- package/dist/chunk-2CNIEBKO.js.map +1 -0
- package/dist/chunk-4T2OQAVL.js +51 -0
- package/dist/chunk-4T2OQAVL.js.map +1 -0
- package/dist/chunk-5ER6ZHA2.js +46 -0
- package/dist/chunk-5ER6ZHA2.js.map +1 -0
- package/dist/chunk-7LSEE26O.js +24227 -0
- package/dist/chunk-7LSEE26O.js.map +1 -0
- package/dist/{chunk-7AHRFPAL.js → chunk-7YOU7MBN.js} +183 -17
- package/dist/chunk-7YOU7MBN.js.map +1 -0
- package/dist/chunk-CMGJGK6R.js +382 -0
- package/dist/chunk-CMGJGK6R.js.map +1 -0
- package/dist/{chunk-VPMN47TL.js → chunk-CNR7O5YH.js} +1 -2
- package/dist/{chunk-2J3WSIAF.js → chunk-EF2DAODF.js} +18 -3
- package/dist/chunk-EF2DAODF.js.map +1 -0
- package/dist/chunk-HQ43PHOH.js +1203 -0
- package/dist/chunk-HQ43PHOH.js.map +1 -0
- package/dist/chunk-KITSAHTX.js +134 -0
- package/dist/chunk-KITSAHTX.js.map +1 -0
- package/dist/chunk-LESHN5J5.js +6898 -0
- package/dist/chunk-LESHN5J5.js.map +1 -0
- package/dist/{chunk-LW2MS4T5.js → chunk-LMJFHKRD.js} +15 -12
- package/dist/chunk-LMJFHKRD.js.map +1 -0
- package/dist/{chunk-SNYEQHUK.js → chunk-NACJENDW.js} +14 -21
- package/dist/chunk-NACJENDW.js.map +1 -0
- package/dist/{chunk-IISLTKYY.js → chunk-TU63KZFW.js} +2 -2
- package/dist/chunk-TX6DK4PK.js +186 -0
- package/dist/chunk-TX6DK4PK.js.map +1 -0
- package/dist/chunk-UQVXWOPT.js +48 -0
- package/dist/chunk-UQVXWOPT.js.map +1 -0
- package/dist/{chunk-3MNPDCO5.js → chunk-WBB4XHLH.js} +139 -140
- package/dist/chunk-WBB4XHLH.js.map +1 -0
- package/dist/chunk-X3MULCV5.js +11 -0
- package/dist/chunk-X3MULCV5.js.map +1 -0
- package/dist/chunk-YZ3Z3ZYI.js +787 -0
- package/dist/chunk-YZ3Z3ZYI.js.map +1 -0
- package/dist/{chunk-2UN5AR7V.js → chunk-ZAOPND5G.js} +2 -2
- package/dist/chunk-ZFKJAYAN.js +542 -0
- package/dist/chunk-ZFKJAYAN.js.map +1 -0
- package/dist/cursor-hook-shim.js +316 -0
- package/dist/cursor-hook-shim.js.map +1 -0
- package/dist/cursor-runner.js +358 -0
- package/dist/cursor-runner.js.map +1 -0
- package/dist/electron-utility.js +111 -0
- package/dist/electron-utility.js.map +1 -0
- package/dist/git-pool-V73Q53NX.js +18 -0
- package/dist/{git-repo-VRT57DGC.js → git-repo-TN3VZXQV.js} +9 -6
- package/dist/index.js +12 -12
- package/dist/index.js.map +1 -1
- package/dist/{logger-GQCSLSZH.js → logger-QHPTO22N.js} +4 -4
- package/dist/login-Q7SZI7JJ.js +20 -0
- package/dist/{logout-VUNCW5B2.js → logout-O4AVMO5S.js} +6 -6
- package/dist/mcp-servers-F64M5T4I.js +24 -0
- package/dist/{roi-Y3MX5UW4.js → roi-EYDLPOCS.js} +5 -5
- package/dist/rss-worker.js +159 -0
- package/dist/rss-worker.js.map +1 -0
- package/dist/{serve-O53FNK64.js → serve-6A7RJWEF.js} +89862 -102999
- package/dist/{serve-O53FNK64.js.map → serve-6A7RJWEF.js.map} +1 -1
- package/dist/skills-ZHEPSBHW.js +11 -0
- package/dist/{start-IDFDHRD6.js → start-YGYYIK53.js} +229 -27
- package/dist/start-YGYYIK53.js.map +1 -0
- package/dist/vault-crypto-BKDOA65F.js +13 -0
- package/dist/vault-crypto-BKDOA65F.js.map +1 -0
- package/dist/worker.js +6 -3
- package/dist/worker.js.map +1 -1
- package/package.json +17 -10
- package/dist/chunk-2J3WSIAF.js.map +0 -1
- package/dist/chunk-3MNPDCO5.js.map +0 -1
- package/dist/chunk-66OBOZ3X.js +0 -79
- package/dist/chunk-66OBOZ3X.js.map +0 -1
- package/dist/chunk-7AHRFPAL.js.map +0 -1
- package/dist/chunk-DKMDBOFU.js.map +0 -1
- package/dist/chunk-L2WQMPWS.js +0 -666
- package/dist/chunk-L2WQMPWS.js.map +0 -1
- package/dist/chunk-LW2MS4T5.js.map +0 -1
- package/dist/chunk-PI77CUEP.js +0 -49
- package/dist/chunk-PI77CUEP.js.map +0 -1
- package/dist/chunk-RXI4637N.js +0 -395
- package/dist/chunk-RXI4637N.js.map +0 -1
- package/dist/chunk-SNYEQHUK.js.map +0 -1
- package/dist/chunk-VBPHGPBR.js +0 -126
- package/dist/chunk-VBPHGPBR.js.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/login-L4BBPUYO.js +0 -20
- package/dist/mcp-servers-MXS5VAWI.js +0 -18
- package/dist/shell-V36EX2IJ.js +0 -27
- package/dist/skills-GPGRNV4R.js +0 -9
- package/dist/start-IDFDHRD6.js.map +0 -1
- package/dist/worker.d.ts +0 -49
- /package/dist/{auth-SS7LV5XK.js.map → auth-EXHO3AG5.js.map} +0 -0
- /package/dist/{chunk-VPMN47TL.js.map → chunk-CNR7O5YH.js.map} +0 -0
- /package/dist/{chunk-IISLTKYY.js.map → chunk-TU63KZFW.js.map} +0 -0
- /package/dist/{chunk-2UN5AR7V.js.map → chunk-ZAOPND5G.js.map} +0 -0
- /package/dist/{git-repo-VRT57DGC.js.map → git-pool-V73Q53NX.js.map} +0 -0
- /package/dist/{logger-GQCSLSZH.js.map → git-repo-TN3VZXQV.js.map} +0 -0
- /package/dist/{login-L4BBPUYO.js.map → logger-QHPTO22N.js.map} +0 -0
- /package/dist/{mcp-servers-MXS5VAWI.js.map → login-Q7SZI7JJ.js.map} +0 -0
- /package/dist/{logout-VUNCW5B2.js.map → logout-O4AVMO5S.js.map} +0 -0
- /package/dist/{shell-V36EX2IJ.js.map → mcp-servers-F64M5T4I.js.map} +0 -0
- /package/dist/{roi-Y3MX5UW4.js.map → roi-EYDLPOCS.js.map} +0 -0
- /package/dist/{skills-GPGRNV4R.js.map → skills-ZHEPSBHW.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shared/capabilities/git-repo.ts","../src/shared/capabilities/environments-cache.ts","../src/shared/fs-utils.ts","../src/shared/capabilities/repo-paths-cache.ts"],"sourcesContent":["import { readdir } from 'node:fs/promises';\nimport { basename, join } from 'node:path';\nimport type { GitRepoInfo } from '@shipyard/session';\nimport {\n type CacheEntry,\n getHeadMtime,\n isCacheValid,\n loadCache,\n saveCache,\n} from './environments-cache.js';\nimport { getCachedRepoPaths, setCachedRepoPaths } from './repo-paths-cache.js';\nimport { run, runWithTimeout, TIMEOUT_MS } from './shell.js';\n\n/** Cache of directory paths to whether they are inside a git repository. */\nexport const gitRepoCache = new Map<string, boolean>();\n\n/**\n * Check whether the given directory is inside a git work-tree.\n * Results are cached per directory so repeated calls (e.g. during\n * debounced diff captures) do not re-spawn git processes.\n */\nexport async function isGitRepo(cwd: string): Promise<boolean> {\n const cached = gitRepoCache.get(cwd);\n if (cached !== undefined) return cached;\n try {\n await runWithTimeout('git', ['rev-parse', '--git-dir'], cwd, TIMEOUT_MS);\n gitRepoCache.set(cwd, true);\n return true;\n } catch {\n gitRepoCache.set(cwd, false);\n return false;\n }\n}\n\nlet ghAvailableCache = false;\n\nexport async function isGhAvailable(): Promise<boolean> {\n if (ghAvailableCache) return true;\n try {\n await run('which', ['gh']);\n ghAvailableCache = true;\n return true;\n } catch {\n return false;\n }\n}\n\nconst topLevelCache = new Map<string, string>();\n\nexport async function getGitTopLevel(cwd: string): Promise<string> {\n const cached = topLevelCache.get(cwd);\n if (cached !== undefined) return cached;\n const topLevel = (\n await runWithTimeout('git', ['rev-parse', '--show-toplevel'], cwd, TIMEOUT_MS)\n ).trim();\n topLevelCache.set(cwd, topLevel);\n return topLevel;\n}\n\nexport function parseOwnerRepo(remoteUrl: string): { owner: string; repo: string } | null {\n const match = remoteUrl.match(/github\\.com[:/]([^/]+)\\/([^/.]+)/);\n if (!match?.[1] || !match[2]) return null;\n return { owner: match[1], repo: match[2] };\n}\n\n/**\n * Look up the repo's default branch via the `origin/HEAD` symbolic ref.\n * Returns the branch name (e.g. `main`) or null when the symbolic ref\n * isn't set (rare — happens for repos cloned without `git remote\n * set-head` or local-only repos).\n */\nexport async function getRepoDefaultBranch(cwd: string): Promise<string | null> {\n try {\n const head = (\n await runWithTimeout(\n 'git',\n ['symbolic-ref', '--short', 'refs/remotes/origin/HEAD'],\n cwd,\n TIMEOUT_MS\n )\n ).trim();\n if (!head) return null;\n return head.replace(/^origin\\//, '') || null;\n } catch {\n return null;\n }\n}\n\nexport async function isAncestor(\n ancestor: string,\n descendant: string,\n cwd: string\n): Promise<boolean> {\n try {\n await runWithTimeout('git', ['merge-base', '--is-ancestor', ancestor, descendant], cwd, 5_000);\n return true;\n } catch {\n return false;\n }\n}\n\nconst EXCLUDE_DIRS = new Set([\n 'node_modules',\n 'Library',\n 'Applications',\n 'Pictures',\n 'Music',\n 'Movies',\n 'go',\n '.Trash',\n]);\n\nconst MAX_DEPTH = 4;\n\nexport async function findGitRepos(dir: string, depth = 0): Promise<string[]> {\n if (depth > MAX_DEPTH) return [];\n\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.name === '.git') {\n return [dir];\n }\n }\n\n if (depth >= MAX_DEPTH) return [];\n\n const promises: Promise<string[]>[] = [];\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n if (entry.name.startsWith('.')) continue;\n if (EXCLUDE_DIRS.has(entry.name)) continue;\n promises.push(findGitRepos(join(dir, entry.name), depth + 1));\n }\n\n const results = await Promise.all(promises);\n return results.flat();\n } catch {\n return [];\n }\n}\n\nexport async function getRepoMetadata(\n repoPath: string,\n cached?: CacheEntry\n): Promise<GitRepoInfo | null> {\n try {\n if (cached) {\n return {\n path: repoPath,\n name: basename(repoPath),\n branch: cached.branch,\n ...(cached.remote !== null && { remote: cached.remote }),\n };\n }\n\n const [branchResult, remoteResult] = await Promise.allSettled([\n run('git', ['branch', '--show-current'], repoPath),\n run('git', ['remote', 'get-url', 'origin'], repoPath),\n ]);\n\n const branch = branchResult.status === 'fulfilled' ? branchResult.value || 'HEAD' : 'HEAD';\n const remote =\n remoteResult.status === 'fulfilled' ? remoteResult.value || undefined : undefined;\n\n return {\n path: repoPath,\n name: basename(repoPath),\n branch,\n ...(remote && { remote }),\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Detect git environments under $HOME.\n *\n * `lastKnown` preserves the previously-detected environment list when the\n * underlying `findGitRepos` walk returns `[]` for a non-authoritative reason\n * (root readdir failure: EMFILE, EACCES, EBUSY). Without this, a transient\n * filesystem hiccup in the 30s capability-refresh tick collapses environments\n * to `[]`, which `applyFreshCapabilities` writes wholesale, and the browser\n * briefly renders \"No environment\" until the next successful tick. Mirror of\n * the `lastKnownAgents` pattern in `agents.ts`.\n *\n * Discrimination: a successful walk that genuinely finds zero repos is\n * indistinguishable from a swallowed-error walk in the current shape (the\n * inner `try/catch` in `findGitRepos` returns `[]` on readdir failure). The\n * `lastKnown.length > 0` guard means we only preserve when there's something\n * worth preserving; a clean machine that genuinely has zero repos still gets\n * `[]`.\n */\nexport async function detectEnvironments(lastKnown?: GitRepoInfo[]): Promise<GitRepoInfo[]> {\n const { homedir } = await import('node:os');\n\n /**\n * The repo-paths cache (`repo-paths-cache.ts`) holds the result of the\n * `findGitRepos(homedir())` walk and the N parallel `git worktree list`\n * spawns — together ~12-15s on a busy machine. Per-repo branch info is\n * still resolved fresh below via `getRepoMetadata` (cached separately by\n * `.git/HEAD` mtime in `environments-cache.ts`). The list cache lives\n * for the daemon lifetime; `invalidateRepoPaths()` is called by\n * worktree-service (add/remove), capability-watcher (FSEvents rescan),\n * and explicit force-refresh paths.\n */\n const cachedPaths = getCachedRepoPaths();\n let repoPaths: string[];\n let worktreePaths: string[];\n\n if (cachedPaths) {\n repoPaths = cachedPaths.repos;\n worktreePaths = cachedPaths.worktrees;\n } else {\n try {\n repoPaths = await findGitRepos(homedir());\n } catch (err) {\n if (lastKnown && lastKnown.length > 0) {\n const { logger } = await import('../logger.js');\n logger.warn(\n { err, lastKnownCount: lastKnown.length },\n 'detectEnvironments findGitRepos threw — preserving lastKnown'\n );\n return lastKnown;\n }\n return [];\n }\n\n if (repoPaths.length === 0 && lastKnown && lastKnown.length > 0) {\n /**\n * Walk returned empty but we know there used to be repos — almost\n * certainly a transient root-readdir error swallowed inside\n * `findGitRepos`. Preserve rather than wipe.\n */\n const { logger } = await import('../logger.js');\n logger.warn(\n { lastKnownCount: lastKnown.length },\n 'detectEnvironments walk empty but lastKnown non-empty — preserving lastKnown'\n );\n return lastKnown;\n }\n\n worktreePaths = await discoverWorktrees(repoPaths);\n setCachedRepoPaths(repoPaths, worktreePaths);\n }\n\n const allPaths = [...new Set([...repoPaths, ...worktreePaths])];\n\n const prevCache = await loadCache();\n const headMtimes = await Promise.all(allPaths.map(getHeadMtime));\n const nextCache = new Map<string, CacheEntry>();\n\n const resolved = await Promise.all(\n allPaths.map(async (path, idx) => {\n const currentMtime = headMtimes[idx] ?? null;\n const prev = prevCache.get(path);\n const cacheHit =\n prev !== undefined && currentMtime !== null && isCacheValid(prev, currentMtime);\n const info = await getRepoMetadata(path, cacheHit ? prev : undefined);\n if (info !== null && currentMtime !== null) {\n nextCache.set(path, {\n path,\n branch: info.branch,\n remote: info.remote ?? null,\n headMtimeMs: currentMtime,\n cachedAt: cacheHit && prev ? prev.cachedAt : Date.now(),\n });\n }\n return info;\n })\n );\n\n await saveCache(nextCache);\n\n return resolved.filter((info): info is GitRepoInfo => info !== null);\n}\n\n/**\n * For each repo, run `git worktree list --porcelain` to discover\n * linked worktrees (which may live in dot-directories like .claude/worktrees/).\n */\nasync function discoverWorktrees(repoPaths: string[]): Promise<string[]> {\n const results = await Promise.allSettled(repoPaths.map(listWorktreePaths));\n return results.flatMap((r) => (r.status === 'fulfilled' ? r.value : []));\n}\n\nasync function listWorktreePaths(repoPath: string): Promise<string[]> {\n try {\n const output = await runWithTimeout(\n 'git',\n ['worktree', 'list', '--porcelain'],\n repoPath,\n TIMEOUT_MS\n );\n return parseWorktreeListOutput(output, repoPath);\n } catch {\n return [];\n }\n}\n\nfunction parseWorktreeListOutput(output: string, repoPath: string): string[] {\n const paths: string[] = [];\n for (const line of output.split('\\n')) {\n if (line.startsWith('worktree ')) {\n const wt = line.slice('worktree '.length).trim();\n if (wt && wt !== repoPath) paths.push(wt);\n }\n }\n return paths;\n}\n\nexport const _testing = {\n parseWorktreeListOutput,\n resetGhAvailableCache: () => {\n ghAvailableCache = false;\n },\n};\n","import { mkdir, readFile, rename, stat, unlink, writeFile } from 'node:fs/promises';\nimport { dirname, isAbsolute, join, resolve } from 'node:path';\nimport { z } from 'zod';\nimport { getShipyardHome } from '../env.js';\nimport { isEnoent } from '../fs-utils.js';\nimport { logger } from '../logger.js';\n\nconst CacheEntrySchema = z.object({\n path: z.string(),\n branch: z.string(),\n remote: z.string().nullable(),\n headMtimeMs: z.number(),\n cachedAt: z.number(),\n});\n\nconst CacheFileSchema = z.object({\n entries: z.record(z.string(), CacheEntrySchema),\n});\n\nexport type CacheEntry = z.infer<typeof CacheEntrySchema>;\ntype CacheFile = z.infer<typeof CacheFileSchema>;\n\nexport const CACHE_TTL_MS = 24 * 60 * 60 * 1000;\n\nfunction cacheFilePath(): string {\n return join(getShipyardHome(), 'data', 'environments-cache.json');\n}\n\nexport async function loadCache(): Promise<Map<string, CacheEntry>> {\n const filePath = cacheFilePath();\n try {\n const raw = await readFile(filePath, 'utf8');\n const parsed: unknown = JSON.parse(raw);\n const result = CacheFileSchema.safeParse(parsed);\n if (!result.success) {\n logger.debug({ path: filePath }, 'environments-cache: malformed, treating as empty');\n return new Map();\n }\n return new Map(Object.entries(result.data.entries));\n } catch (err) {\n if (isEnoent(err)) {\n return new Map();\n }\n logger.debug({ err }, 'environments-cache: read failed, treating as empty');\n return new Map();\n }\n}\n\n/**\n * Resolve the actual path of HEAD for the given worktree.\n *\n * - If `<path>/.git` is a directory, HEAD lives at `<path>/.git/HEAD`.\n * - If `<path>/.git` is a file (linked worktree), it contains `gitdir: <path>`;\n * HEAD lives at `<gitdir>/HEAD`. The gitdir may be relative to `<path>`.\n * - Returns null on any error (missing, unreadable, malformed).\n */\nexport async function resolveHeadPath(worktreePath: string): Promise<string | null> {\n const dotGitPath = join(worktreePath, '.git');\n try {\n const dotGitStat = await stat(dotGitPath);\n if (dotGitStat.isDirectory()) {\n return join(dotGitPath, 'HEAD');\n }\n if (dotGitStat.isFile()) {\n const contents = await readFile(dotGitPath, 'utf8');\n const match = contents.match(/^gitdir:\\s*(.+)\\s*$/m);\n if (!match?.[1]) return null;\n const gitdirRaw = match[1].trim();\n const gitdir = isAbsolute(gitdirRaw) ? gitdirRaw : resolve(dirname(dotGitPath), gitdirRaw);\n return join(gitdir, 'HEAD');\n }\n return null;\n } catch {\n return null;\n }\n}\n\nexport async function getHeadMtime(worktreePath: string): Promise<number | null> {\n const headPath = await resolveHeadPath(worktreePath);\n if (!headPath) return null;\n try {\n const headStat = await stat(headPath);\n return headStat.mtimeMs;\n } catch {\n return null;\n }\n}\n\nexport function isCacheValid(entry: CacheEntry, currentMtimeMs: number): boolean {\n if (entry.headMtimeMs !== currentMtimeMs) return false;\n if (Date.now() - entry.cachedAt >= CACHE_TTL_MS) return false;\n return true;\n}\n\nexport async function saveCache(entries: Map<string, CacheEntry>): Promise<void> {\n const filePath = cacheFilePath();\n const tmpPath = `${filePath}.tmp`;\n try {\n await mkdir(dirname(filePath), { recursive: true });\n /**\n * Merge-on-save: re-read disk immediately before writing so a concurrent\n * saveCache call's entries are preserved rather than erased (new entries\n * win for paths present in both — they are fresher).\n */\n const current = await loadCache();\n for (const [path, entry] of entries) {\n current.set(path, entry);\n }\n const payload: CacheFile = { entries: Object.fromEntries(current) };\n await writeFile(tmpPath, JSON.stringify(payload), 'utf8');\n await rename(tmpPath, filePath);\n } catch (err) {\n logger.debug({ err, filePath }, 'environments-cache: save failed');\n void unlink(tmpPath).catch(() => {});\n }\n}\n","import { existsSync } from 'node:fs';\nimport { dirname, join, parse } from 'node:path';\n\nexport function isEnoent(err: unknown): boolean {\n return typeof err === 'object' && err !== null && 'code' in err && err.code === 'ENOENT';\n}\n\nexport function isEexist(err: unknown): boolean {\n return typeof err === 'object' && err !== null && 'code' in err && err.code === 'EEXIST';\n}\n\n/**\n * Detect JSON parse errors or Zod validation failures that indicate\n * a corrupt store file. Shared across all file-backed stores.\n */\nexport function isCorruptionError(err: unknown): boolean {\n if (err instanceof SyntaxError) return true;\n if (typeof err === 'object' && err !== null && 'name' in err && err.name === 'ZodError')\n return true;\n return false;\n}\n\n/**\n * Walk up the directory tree from `startDir` to find the project root.\n *\n * Looks for `.git` (directory or file — worktrees use a `.git` file) or\n * `pnpm-workspace.yaml` as root markers.\n *\n * Returns a discriminated result so callers can distinguish \"marker found\"\n * (genuinely scoped, even if the marker is in startDir itself) from\n * \"no marker anywhere\" (genuinely unscoped). The bare-string return shape\n * conflated these, since both cases produced `startDir` — breaking the\n * unscoped detection in `serve.ts` whenever the daemon was launched from\n * a project's own root directory.\n *\n * In dev: `startDir` is typically `apps/daemon/` (pnpm runs from package dir),\n * so this walks up to find the monorepo root. In prod install: `startDir` is\n * the user's project directory where the daemon is launched, and `.git` is\n * found immediately. Called once at daemon startup — the result is used as\n * the workspace root for file-io, LSP, and file watching.\n */\nexport function findProjectRoot(startDir: string): { root: string; foundMarker: boolean } {\n let dir = startDir;\n while (true) {\n if (existsSync(join(dir, 'pnpm-workspace.yaml')) || existsSync(join(dir, '.git'))) {\n return { root: dir, foundMarker: true };\n }\n const parent = dirname(dir);\n if (parent === dir || parent === parse(dir).root) {\n return { root: startDir, foundMarker: false };\n }\n dir = parent;\n }\n}\n","/**\n * In-memory cache of the list of git repo paths under $HOME and the linked\n * worktree paths discovered via `git worktree list --porcelain` for each.\n *\n * Distinct from `environments-cache.ts` (which caches per-repo branch info on\n * disk, keyed by `.git/HEAD` mtime). This one caches the LIST of repos and\n * worktrees — i.e. the `findGitRepos(homedir())` walk and the N parallel\n * `git worktree list` spawns. Those are the ~12-15s cost on a busy machine.\n *\n * Lifetime: daemon-lifetime, invalidated only on explicit triggers. The\n * previous 24h TTL was a backstop for the 5-min capability-refresh tick that\n * used to walk $HOME on a periodic timer; that tick is gone (B0) and the\n * walk is event-driven now.\n *\n * Invalidation:\n * - `invalidateRepoPaths()` — called by:\n * * capability-watcher.ts (FSEvents rescan + escalation paths)\n * * explicit force-refresh control message\n * - `addWorktreeToCache()` / `removeWorktreeFromCache()` — incremental\n * update used by worktree create/remove. Avoids the cold-walk recompute\n * storm that otherwise stalls the event loop 12-15s and kills the\n * daemon's WebRTC + control channels mid-creation. If there is no\n * active cache (boot before first walk), the call is a no-op — the\n * next cold walk picks up the new state.\n *\n * The walk + worktree spawns ARE NOT triggered by the capability-watcher's\n * normal events: scoped re-detect (`refreshMcpServers` etc.) skips\n * `detectEnvironments` entirely and reuses the existing `daemon.capabilities\n * ?.environments`. The cache is only consulted by full `detectCapabilities`\n * runs (manual Refresh button, boot, cwd-changed).\n */\n\nexport {\n getCachedRepoPaths,\n setCachedRepoPaths,\n invalidateRepoPaths,\n addWorktreeToCache,\n removeWorktreeFromCache,\n};\n\ninterface CachedEntry {\n repos: string[];\n worktrees: string[];\n populatedAt: number;\n}\n\nlet cache: CachedEntry | null = null;\n\nfunction getCachedRepoPaths(): { repos: string[]; worktrees: string[] } | null {\n if (!cache) return null;\n return { repos: cache.repos, worktrees: cache.worktrees };\n}\n\nfunction setCachedRepoPaths(repos: string[], worktrees: string[], now: number = Date.now()): void {\n cache = { repos, worktrees, populatedAt: now };\n}\n\nfunction invalidateRepoPaths(): void {\n cache = null;\n}\n\n/**\n * Append a freshly-created worktree to the existing cached result. Source\n * repo path is also added (deduped) because a brand-new repo can host a\n * brand-new worktree, and the next `detectEnvironments` call needs to see\n * both. No-op when there is no cache yet — the next cold walk will discover\n * the new entries naturally.\n */\nfunction addWorktreeToCache(worktreePath: string, sourceRepoPath: string): void {\n if (!cache) return;\n const repos = cache.repos.includes(sourceRepoPath)\n ? cache.repos\n : [...cache.repos, sourceRepoPath];\n const worktrees = cache.worktrees.includes(worktreePath)\n ? cache.worktrees\n : [...cache.worktrees, worktreePath];\n cache = { repos, worktrees, populatedAt: cache.populatedAt };\n}\n\n/**\n * Splice a worktree path out of the cached worktree list. The source repo\n * stays — removing a single linked worktree never deletes its source. No-op\n * when there is no cache yet.\n */\nfunction removeWorktreeFromCache(worktreePath: string): void {\n if (!cache) return;\n const next = cache.worktrees.filter((p) => p !== worktreePath);\n if (next.length === cache.worktrees.length) return;\n cache = { repos: cache.repos, worktrees: next, populatedAt: cache.populatedAt };\n}\n\nexport const _testing = {\n reset: invalidateRepoPaths,\n inspect: () => cache,\n};\n"],"mappings":"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","names":["join","dirname","join","join","dirname","join","logger"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shared/assert-never.ts","../src/services/watcher-worker/worker-protocol.ts"],"sourcesContent":["export function assertNever(value: never): never {\n throw new Error(`Unexpected value: ${JSON.stringify(value)}`);\n}\n","import { z } from 'zod';\n\n/**\n * IPC protocol between the daemon (parent) and the watcher worker subprocess.\n *\n * Wire format: line-delimited JSON over the worker's stdio. Each line is\n * exactly one Command (parent → worker) or one Reply (worker → parent), with\n * no embedded literal newlines — JSON encoding escapes newlines inside string\n * values (e.g. a path containing `\\n`) so the line protocol stays intact.\n *\n * Stdout is the IPC channel; structured worker logs go to stderr only.\n */\n\nexport const SubscribeOptionsSchema = z.object({\n ignore: z.array(z.string()).optional(),\n /**\n * Constrained to the subset the daemon actually uses. `@parcel/watcher`\n * supports more backends but they are platform-specific and we never set\n * them — accepting the wider union here would just invite bugs.\n */\n backend: z.enum(['default', 'brute-force', 'watchman']).optional(),\n});\nexport type WorkerSubscribeOptions = z.infer<typeof SubscribeOptionsSchema>;\n\nexport const CommandSchema = z.discriminatedUnion('cmd', [\n z.object({\n cmd: z.literal('subscribe'),\n id: z.string(),\n path: z.string(),\n opts: SubscribeOptionsSchema,\n }),\n z.object({ cmd: z.literal('unsubscribe'), id: z.string() }),\n z.object({ cmd: z.literal('shutdown') }),\n]);\nexport type WorkerCommand = z.infer<typeof CommandSchema>;\n\nconst ParcelEventSchema = z.object({\n type: z.enum(['create', 'update', 'delete']),\n path: z.string(),\n});\nexport type WorkerParcelEvent = z.infer<typeof ParcelEventSchema>;\n\nexport const ReplySchema = z.discriminatedUnion('type', [\n z.object({ type: z.literal('subscribed'), id: z.string() }),\n z.object({ type: z.literal('subscribe_failed'), id: z.string(), error: z.string() }),\n z.object({ type: z.literal('unsubscribed'), id: z.string() }),\n z.object({ type: z.literal('events'), id: z.string(), events: z.array(ParcelEventSchema) }),\n]);\nexport type WorkerReply = z.infer<typeof ReplySchema>;\n\nexport function encodeLine(msg: WorkerCommand | WorkerReply): string {\n return JSON.stringify(msg);\n}\n\n/**\n * Decode a single line. Returns `null` for any malformed or\n * schema-rejected input — the worker logs and continues, the supervisor\n * drops the bad line. Throwing here would let one corrupt line crash an\n * otherwise-healthy peer, which is the opposite of what process supervision\n * is for.\n */\nexport function decodeLine(line: string): WorkerCommand | WorkerReply | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n return null;\n }\n if (parsed === null || typeof parsed !== 'object') return null;\n\n const asCmd = CommandSchema.safeParse(parsed);\n if (asCmd.success) return asCmd.data;\n const asReply = ReplySchema.safeParse(parsed);\n if (asReply.success) return asReply.data;\n return null;\n}\n"],"mappings":";;;;;;AAAO,SAAS,YAAY,OAAqB;AAC/C,QAAM,IAAI,MAAM,qBAAqB,KAAK,UAAU,KAAK,CAAC,EAAE;AAC9D;;;ACWO,IAAM,yBAAyB,iBAAE,OAAO;AAAA,EAC7C,QAAQ,iBAAE,MAAM,iBAAE,OAAO,CAAC,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMrC,SAAS,iBAAE,KAAK,CAAC,WAAW,eAAe,UAAU,CAAC,EAAE,SAAS;AACnE,CAAC;AAGM,IAAM,gBAAgB,iBAAE,mBAAmB,OAAO;AAAA,EACvD,iBAAE,OAAO;AAAA,IACP,KAAK,iBAAE,QAAQ,WAAW;AAAA,IAC1B,IAAI,iBAAE,OAAO;AAAA,IACb,MAAM,iBAAE,OAAO;AAAA,IACf,MAAM;AAAA,EACR,CAAC;AAAA,EACD,iBAAE,OAAO,EAAE,KAAK,iBAAE,QAAQ,aAAa,GAAG,IAAI,iBAAE,OAAO,EAAE,CAAC;AAAA,EAC1D,iBAAE,OAAO,EAAE,KAAK,iBAAE,QAAQ,UAAU,EAAE,CAAC;AACzC,CAAC;AAGD,IAAM,oBAAoB,iBAAE,OAAO;AAAA,EACjC,MAAM,iBAAE,KAAK,CAAC,UAAU,UAAU,QAAQ,CAAC;AAAA,EAC3C,MAAM,iBAAE,OAAO;AACjB,CAAC;AAGM,IAAM,cAAc,iBAAE,mBAAmB,QAAQ;AAAA,EACtD,iBAAE,OAAO,EAAE,MAAM,iBAAE,QAAQ,YAAY,GAAG,IAAI,iBAAE,OAAO,EAAE,CAAC;AAAA,EAC1D,iBAAE,OAAO,EAAE,MAAM,iBAAE,QAAQ,kBAAkB,GAAG,IAAI,iBAAE,OAAO,GAAG,OAAO,iBAAE,OAAO,EAAE,CAAC;AAAA,EACnF,iBAAE,OAAO,EAAE,MAAM,iBAAE,QAAQ,cAAc,GAAG,IAAI,iBAAE,OAAO,EAAE,CAAC;AAAA,EAC5D,iBAAE,OAAO,EAAE,MAAM,iBAAE,QAAQ,QAAQ,GAAG,IAAI,iBAAE,OAAO,GAAG,QAAQ,iBAAE,MAAM,iBAAiB,EAAE,CAAC;AAC5F,CAAC;AAGM,SAAS,WAAW,KAA0C;AACnE,SAAO,KAAK,UAAU,GAAG;AAC3B;AASO,SAAS,WAAW,MAAkD;AAC3E,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,IAAI;AAAA,EAC1B,QAAQ;AACN,WAAO;AAAA,EACT;AACA,MAAI,WAAW,QAAQ,OAAO,WAAW,SAAU,QAAO;AAE1D,QAAM,QAAQ,cAAc,UAAU,MAAM;AAC5C,MAAI,MAAM,QAAS,QAAO,MAAM;AAChC,QAAM,UAAU,YAAY,UAAU,MAAM;AAC5C,MAAI,QAAQ,QAAS,QAAO,QAAQ;AACpC,SAAO;AACT;","names":[]}
|
package/dist/chunk-VBPHGPBR.js
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// src/shared/capabilities/skills.ts
|
|
4
|
-
import { readdir, readFile } from "fs/promises";
|
|
5
|
-
import { homedir } from "os";
|
|
6
|
-
import { join } from "path";
|
|
7
|
-
function parseSkillFrontmatter(content, fallbackName) {
|
|
8
|
-
const match = /^---\n([\s\S]*?)\n---/.exec(content);
|
|
9
|
-
if (!match?.[1]) return { name: fallbackName, description: "" };
|
|
10
|
-
const frontmatter = match[1];
|
|
11
|
-
const nameMatch = /^name:\s*["']?(.+?)["']?\s*$/m.exec(frontmatter);
|
|
12
|
-
const descMatch = /^description:\s*["']?(.+?)["']?\s*$/m.exec(frontmatter);
|
|
13
|
-
const name = nameMatch?.[1]?.trim() ?? fallbackName;
|
|
14
|
-
let description = descMatch?.[1]?.trim() ?? "";
|
|
15
|
-
if (description.length > 200) description = `${description.slice(0, 197)}...`;
|
|
16
|
-
return { name, description };
|
|
17
|
-
}
|
|
18
|
-
async function readSkillsFromDir(dirPath) {
|
|
19
|
-
try {
|
|
20
|
-
const entries = await readdir(dirPath, { withFileTypes: true });
|
|
21
|
-
const skills = [];
|
|
22
|
-
for (const entry of entries) {
|
|
23
|
-
if (!entry.isDirectory()) continue;
|
|
24
|
-
const skillDir = join(dirPath, entry.name);
|
|
25
|
-
const skillFile = join(skillDir, "SKILL.md");
|
|
26
|
-
try {
|
|
27
|
-
const content = await readFile(skillFile, "utf-8");
|
|
28
|
-
const parsed = parseSkillFrontmatter(content, entry.name);
|
|
29
|
-
if (parsed) skills.push(parsed);
|
|
30
|
-
} catch {
|
|
31
|
-
skills.push({ name: entry.name, description: "" });
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
return skills;
|
|
35
|
-
} catch {
|
|
36
|
-
return [];
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
async function readSkillsRecursive(dirPath) {
|
|
40
|
-
const skills = [];
|
|
41
|
-
try {
|
|
42
|
-
const entries = await readdir(dirPath, { withFileTypes: true });
|
|
43
|
-
for (const entry of entries) {
|
|
44
|
-
if (!entry.isDirectory()) continue;
|
|
45
|
-
const subDir = join(dirPath, entry.name);
|
|
46
|
-
const skillFile = join(subDir, "SKILL.md");
|
|
47
|
-
try {
|
|
48
|
-
const content = await readFile(skillFile, "utf-8");
|
|
49
|
-
const parsed = parseSkillFrontmatter(content, entry.name);
|
|
50
|
-
if (parsed) skills.push(parsed);
|
|
51
|
-
} catch {
|
|
52
|
-
const nested = await readSkillsRecursive(subDir);
|
|
53
|
-
skills.push(...nested);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
} catch {
|
|
57
|
-
}
|
|
58
|
-
return skills;
|
|
59
|
-
}
|
|
60
|
-
async function readPluginSkills() {
|
|
61
|
-
const skills = [];
|
|
62
|
-
try {
|
|
63
|
-
const settingsPath = join(homedir(), ".claude", "settings.json");
|
|
64
|
-
const settingsRaw = await readFile(settingsPath, "utf-8");
|
|
65
|
-
const settings = JSON.parse(settingsRaw);
|
|
66
|
-
if (!settings.enabledPlugins) return [];
|
|
67
|
-
const installedPath = join(homedir(), ".claude", "plugins", "installed_plugins.json");
|
|
68
|
-
const installedRaw = await readFile(installedPath, "utf-8");
|
|
69
|
-
const installed = JSON.parse(installedRaw);
|
|
70
|
-
if (!installed.plugins) return [];
|
|
71
|
-
for (const [pluginId, enabled] of Object.entries(settings.enabledPlugins)) {
|
|
72
|
-
if (!enabled) continue;
|
|
73
|
-
const installs = installed.plugins[pluginId];
|
|
74
|
-
if (!installs || installs.length === 0) continue;
|
|
75
|
-
const installPath = installs[0]?.installPath;
|
|
76
|
-
if (!installPath) continue;
|
|
77
|
-
const skillsDir = join(installPath, "skills");
|
|
78
|
-
const pluginSkills = await readSkillsRecursive(skillsDir);
|
|
79
|
-
skills.push(...pluginSkills);
|
|
80
|
-
}
|
|
81
|
-
} catch {
|
|
82
|
-
}
|
|
83
|
-
return skills;
|
|
84
|
-
}
|
|
85
|
-
async function detectSkills(environments, lastKnown) {
|
|
86
|
-
try {
|
|
87
|
-
return await detectSkillsInner(environments);
|
|
88
|
-
} catch (err) {
|
|
89
|
-
const { logger } = await import("./logger-GQCSLSZH.js");
|
|
90
|
-
if (lastKnown && lastKnown.length > 0) {
|
|
91
|
-
logger.warn(
|
|
92
|
-
{ err, lastKnownCount: lastKnown.length },
|
|
93
|
-
"detectSkills threw \u2014 preserving lastKnown"
|
|
94
|
-
);
|
|
95
|
-
return lastKnown;
|
|
96
|
-
}
|
|
97
|
-
logger.debug({ err }, "detectSkills threw with no lastKnown \u2014 returning []");
|
|
98
|
-
return [];
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
async function detectSkillsInner(environments) {
|
|
102
|
-
const userSkillsDir = join(homedir(), ".claude", "skills");
|
|
103
|
-
const [userSkills, pluginSkills] = await Promise.all([
|
|
104
|
-
readSkillsFromDir(userSkillsDir),
|
|
105
|
-
readPluginSkills()
|
|
106
|
-
]);
|
|
107
|
-
const allSkills = [...pluginSkills, ...userSkills];
|
|
108
|
-
const envSkillResults = await Promise.all(
|
|
109
|
-
environments.map((env) => readSkillsFromDir(join(env.path, ".claude", "skills")))
|
|
110
|
-
);
|
|
111
|
-
for (const projectSkills of envSkillResults) {
|
|
112
|
-
allSkills.push(...projectSkills);
|
|
113
|
-
}
|
|
114
|
-
const deduped = /* @__PURE__ */ new Map();
|
|
115
|
-
for (const skill of allSkills) {
|
|
116
|
-
if (!deduped.has(skill.name)) {
|
|
117
|
-
deduped.set(skill.name, skill);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
return [...deduped.values()];
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export {
|
|
124
|
-
detectSkills
|
|
125
|
-
};
|
|
126
|
-
//# sourceMappingURL=chunk-VBPHGPBR.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shared/capabilities/skills.ts"],"sourcesContent":["import { readdir, readFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport type { GitRepoInfo, SkillInfo } from '@shipyard/session';\n\n/**\n * Extract name and description from a SKILL.md YAML frontmatter.\n * Expects `---\\nname: ...\\ndescription: \"...\"\\n---` at the top.\n */\nfunction parseSkillFrontmatter(\n content: string,\n fallbackName: string\n): { name: string; description: string } | null {\n const match = /^---\\n([\\s\\S]*?)\\n---/.exec(content);\n if (!match?.[1]) return { name: fallbackName, description: '' };\n\n const frontmatter = match[1];\n const nameMatch = /^name:\\s*[\"']?(.+?)[\"']?\\s*$/m.exec(frontmatter);\n const descMatch = /^description:\\s*[\"']?(.+?)[\"']?\\s*$/m.exec(frontmatter);\n\n const name = nameMatch?.[1]?.trim() ?? fallbackName;\n let description = descMatch?.[1]?.trim() ?? '';\n if (description.length > 200) description = `${description.slice(0, 197)}...`;\n\n return { name, description };\n}\n\nasync function readSkillsFromDir(dirPath: string): Promise<SkillInfo[]> {\n try {\n const entries = await readdir(dirPath, { withFileTypes: true });\n const skills: SkillInfo[] = [];\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const skillDir = join(dirPath, entry.name);\n const skillFile = join(skillDir, 'SKILL.md');\n try {\n const content = await readFile(skillFile, 'utf-8');\n const parsed = parseSkillFrontmatter(content, entry.name);\n if (parsed) skills.push(parsed);\n } catch {\n skills.push({ name: entry.name, description: '' });\n }\n }\n\n return skills;\n } catch {\n return [];\n }\n}\n\nasync function readSkillsRecursive(dirPath: string): Promise<SkillInfo[]> {\n const skills: SkillInfo[] = [];\n try {\n const entries = await readdir(dirPath, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const subDir = join(dirPath, entry.name);\n const skillFile = join(subDir, 'SKILL.md');\n try {\n const content = await readFile(skillFile, 'utf-8');\n const parsed = parseSkillFrontmatter(content, entry.name);\n if (parsed) skills.push(parsed);\n } catch {\n const nested = await readSkillsRecursive(subDir);\n skills.push(...nested);\n }\n }\n } catch {}\n return skills;\n}\n\nasync function readPluginSkills(): Promise<SkillInfo[]> {\n const skills: SkillInfo[] = [];\n try {\n const settingsPath = join(homedir(), '.claude', 'settings.json');\n const settingsRaw = await readFile(settingsPath, 'utf-8');\n // eslint-disable-next-line no-restricted-syntax -- JSON.parse returns unknown; checking enabledPlugins field only\n const settings = JSON.parse(settingsRaw) as { enabledPlugins?: Record<string, boolean> };\n if (!settings.enabledPlugins) return [];\n\n const installedPath = join(homedir(), '.claude', 'plugins', 'installed_plugins.json');\n const installedRaw = await readFile(installedPath, 'utf-8');\n // eslint-disable-next-line no-restricted-syntax -- JSON.parse returns unknown; checking plugins field only\n const installed = JSON.parse(installedRaw) as {\n plugins?: Record<string, Array<{ installPath?: string }>>;\n };\n if (!installed.plugins) return [];\n\n for (const [pluginId, enabled] of Object.entries(settings.enabledPlugins)) {\n if (!enabled) continue;\n const installs = installed.plugins[pluginId];\n if (!installs || installs.length === 0) continue;\n const installPath = installs[0]?.installPath;\n if (!installPath) continue;\n\n const skillsDir = join(installPath, 'skills');\n const pluginSkills = await readSkillsRecursive(skillsDir);\n skills.push(...pluginSkills);\n }\n } catch {}\n return skills;\n}\n\n/**\n * Detect skills across user/plugin/project sources.\n *\n * `lastKnown` preserves the previously-detected list when this function\n * throws (rare — inner readers swallow errors — but defense in depth).\n * Mirror of the `lastKnownAgents` pattern in `agents.ts`.\n */\nexport async function detectSkills(\n environments: GitRepoInfo[],\n lastKnown?: SkillInfo[]\n): Promise<SkillInfo[]> {\n try {\n return await detectSkillsInner(environments);\n } catch (err) {\n /**\n * Preserve \"always resolves\" contract — inner readers already swallow\n * per-file errors. Never rethrow because the Promise.all in\n * detectCapabilities would tear down the whole refresh for a single\n * slice's failure.\n */\n const { logger } = await import('../logger.js');\n if (lastKnown && lastKnown.length > 0) {\n logger.warn(\n { err, lastKnownCount: lastKnown.length },\n 'detectSkills threw — preserving lastKnown'\n );\n return lastKnown;\n }\n logger.debug({ err }, 'detectSkills threw with no lastKnown — returning []');\n return [];\n }\n}\n\nasync function detectSkillsInner(environments: GitRepoInfo[]): Promise<SkillInfo[]> {\n const userSkillsDir = join(homedir(), '.claude', 'skills');\n const [userSkills, pluginSkills] = await Promise.all([\n readSkillsFromDir(userSkillsDir),\n readPluginSkills(),\n ]);\n const allSkills: SkillInfo[] = [...pluginSkills, ...userSkills];\n\n const envSkillResults = await Promise.all(\n environments.map((env) => readSkillsFromDir(join(env.path, '.claude', 'skills')))\n );\n for (const projectSkills of envSkillResults) {\n allSkills.push(...projectSkills);\n }\n\n const deduped = new Map<string, SkillInfo>();\n for (const skill of allSkills) {\n if (!deduped.has(skill.name)) {\n deduped.set(skill.name, skill);\n }\n }\n\n return [...deduped.values()];\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.ts
DELETED
package/dist/login-L4BBPUYO.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
ensureAuthenticated,
|
|
4
|
-
getSignalingUrl,
|
|
5
|
-
loginCommand
|
|
6
|
-
} from "./chunk-LW2MS4T5.js";
|
|
7
|
-
import "./chunk-7AHRFPAL.js";
|
|
8
|
-
import "./chunk-EHQITHQX.js";
|
|
9
|
-
import "./chunk-IISLTKYY.js";
|
|
10
|
-
import "./chunk-2UN5AR7V.js";
|
|
11
|
-
import "./chunk-2J3WSIAF.js";
|
|
12
|
-
import "./chunk-PI77CUEP.js";
|
|
13
|
-
import "./chunk-VPMN47TL.js";
|
|
14
|
-
import "./chunk-2H7UOFLK.js";
|
|
15
|
-
export {
|
|
16
|
-
ensureAuthenticated,
|
|
17
|
-
getSignalingUrl,
|
|
18
|
-
loginCommand
|
|
19
|
-
};
|
|
20
|
-
//# sourceMappingURL=login-L4BBPUYO.js.map
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
detectMCPServers,
|
|
4
|
-
redactArgs,
|
|
5
|
-
redactEnv,
|
|
6
|
-
shouldFetchClaudeAiIntegrations
|
|
7
|
-
} from "./chunk-L2WQMPWS.js";
|
|
8
|
-
import "./chunk-2UN5AR7V.js";
|
|
9
|
-
import "./chunk-PI77CUEP.js";
|
|
10
|
-
import "./chunk-VPMN47TL.js";
|
|
11
|
-
import "./chunk-2H7UOFLK.js";
|
|
12
|
-
export {
|
|
13
|
-
detectMCPServers,
|
|
14
|
-
redactArgs,
|
|
15
|
-
redactEnv,
|
|
16
|
-
shouldFetchClaudeAiIntegrations
|
|
17
|
-
};
|
|
18
|
-
//# sourceMappingURL=mcp-servers-MXS5VAWI.js.map
|
package/dist/shell-V36EX2IJ.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
AUTH_STATUS_TIMEOUT_MS,
|
|
4
|
-
BUFFER_OVERFLOW_MSG,
|
|
5
|
-
DIFF_TIMEOUT_MS,
|
|
6
|
-
MAX_DIFF_SIZE,
|
|
7
|
-
TIMEOUT_MS,
|
|
8
|
-
augmentPath,
|
|
9
|
-
isMaxBufferError,
|
|
10
|
-
run,
|
|
11
|
-
runWithTimeout,
|
|
12
|
-
truncateDiff
|
|
13
|
-
} from "./chunk-66OBOZ3X.js";
|
|
14
|
-
import "./chunk-2H7UOFLK.js";
|
|
15
|
-
export {
|
|
16
|
-
AUTH_STATUS_TIMEOUT_MS,
|
|
17
|
-
BUFFER_OVERFLOW_MSG,
|
|
18
|
-
DIFF_TIMEOUT_MS,
|
|
19
|
-
MAX_DIFF_SIZE,
|
|
20
|
-
TIMEOUT_MS,
|
|
21
|
-
augmentPath,
|
|
22
|
-
isMaxBufferError,
|
|
23
|
-
run,
|
|
24
|
-
runWithTimeout,
|
|
25
|
-
truncateDiff
|
|
26
|
-
};
|
|
27
|
-
//# sourceMappingURL=shell-V36EX2IJ.js.map
|
package/dist/skills-GPGRNV4R.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shared/commands/start.ts","../src/shared/commands/start-supervisor.ts"],"sourcesContent":["import { fork as childProcessFork } from 'node:child_process';\nimport { loadAuthToken } from '../../services/bootstrap/auth.js';\nimport { createMetricsCollector } from '../../services/metrics/metrics-collector.js';\nimport { validateEnv } from '../env.js';\nimport { ensureAuthenticated, getSignalingUrl } from './login.js';\nimport { print } from './output.js';\nimport { runStartSupervisor } from './start-supervisor.js';\n\n/**\n * `shipyard start` -- the primary entry point for running the daemon.\n *\n * Two-layer process model (Commit 3 of the watcher-worker subprocess\n * rollout): the parent CLI process forks itself and supervises a daemon\n * child. The branch is gated on `SHIPYARD_DAEMON_CHILD=1` in the env so the\n * forked child re-enters this same function and runs the existing\n * `serve()` path verbatim. The parent monitors the child's exit and\n * respawns on abnormal exits (SIGABRT/SIGSEGV/SIGBUS/SIGKILL or non-zero\n * exit code), backed by `decideAction`'s pure backoff/circuit core\n * (third use site after `file-watcher-guard.ts`'s per-path circuit and\n * the watcher-worker supervisor's restart circuit).\n */\nexport async function startCommand(): Promise<void> {\n if (process.env.SHIPYARD_DAEMON_CHILD === '1') {\n return runDaemonChild();\n }\n return runSupervisor();\n}\n\nasync function runDaemonChild(): Promise<void> {\n const env = validateEnv();\n const signalingUrl = getSignalingUrl();\n\n const codeIdx = process.argv.indexOf('--code');\n const webCode = codeIdx !== -1 ? process.argv[codeIdx + 1] : undefined;\n\n print('Starting Shipyard daemon...\\n');\n\n const authResult = await ensureAuthenticated({ signalingUrl, webCode });\n\n env.SHIPYARD_USER_TOKEN = authResult.token;\n env.SHIPYARD_USER_ID = authResult.userId;\n env.SHIPYARD_USER_DISPLAY_NAME = authResult.displayName;\n env.SHIPYARD_SIGNALING_URL = authResult.signalingUrl;\n\n const { serve } = await import('../../services/serve.js');\n return serve({ isDev: env.SHIPYARD_DEV, autoOpenBrowser: !authResult.deviceFlowRan });\n}\n\nasync function runSupervisor(): Promise<void> {\n /**\n * Re-fork the same entrypoint that started us. `process.argv[1]` is the\n * Node script (or bundled binary) currently executing; the forked child\n * picks up `SHIPYARD_DAEMON_CHILD=1` and takes the `runDaemonChild()`\n * branch above.\n */\n const childModulePath = process.argv[1];\n if (!childModulePath) {\n throw new Error('shipyard start: cannot determine childModulePath from process.argv');\n }\n\n /**\n * Build the supervisor's own metrics collector. The daemon child constructs\n * a separate one in `serve.ts` once it's authenticated. We use the existing\n * cached auth token here without running the device flow — if the user has\n * never logged in, metrics is just `undefined` (the supervisor still runs).\n * This keeps option (a) of Commit 4's spec: supervisor parent gets its own\n * collector at startup, daemon child gets its own as today.\n */\n const auth = await loadAuthToken();\n const METRICS_WORKER_URL =\n process.env.SHIPYARD_METRICS_WORKER_URL || 'https://shipyard-metrics.jacob-191.workers.dev';\n const metrics =\n auth.status === 'ok'\n ? createMetricsCollector(\n METRICS_WORKER_URL,\n auth.token,\n process.env.SHIPYARD_TELEMETRY !== '0'\n )\n : undefined;\n\n const { done } = runStartSupervisor({\n fork: childProcessFork,\n childModulePath,\n childArgs: process.argv.slice(2),\n log: (entry) => process.stderr.write(`${JSON.stringify(entry)}\\n`),\n metrics,\n now: () => Date.now(),\n setTimeout: (fn, ms) => setTimeout(fn, ms),\n clearTimeout: (timer) => {\n if (timer === null || timer === undefined) return;\n clearTimeout(timer as never);\n },\n onSignal: (sig, handler) => {\n process.on(sig, handler);\n },\n });\n\n const result = await done;\n /** Flush any pending metrics events before the supervisor exits. */\n metrics?.dispose();\n /**\n * Propagate the daemon child's exit code (or `1` for circuit-open) to\n * shell/CI. Exiting here also stops any non-trivial Node teardown that\n * the supervisor's signal handlers might otherwise block.\n */\n process.exit(result.exitCode);\n}\n","import type { ChildProcess } from 'node:child_process';\nimport { assertNever } from '../assert-never.js';\nimport { type AttemptState, decideAction, makeInitialAttemptState } from '../file-watcher-guard.js';\n\n/**\n * Mirrors the shape of `MetricsCapture` from\n * `apps/daemon/src/services/metrics/metrics-collector.ts`. Declared inline\n * (not imported) so the supervisor module stays in `apps/daemon/src/shared/`\n * with no upward dependency on `services/metrics/`. Production wiring in\n * `start.ts` constructs a `MetricsCollector` and passes it through.\n */\nexport interface StartSupervisorMetrics {\n capture(eventType: string, properties: Record<string, unknown>): void;\n}\n\n/**\n * Outer CLI supervisor: the parent `shipyard start` process forks itself and\n * supervises the daemon child. On abnormal exit (SIGABRT/SIGSEGV/SIGBUS/SIGKILL\n * or non-zero exit code) it applies the same backoff + circuit semantics as\n * the watcher worker supervisor (third use of `decideAction`'s pure core) and\n * respawns. On graceful exit it propagates the exit code.\n *\n * On supervisor SIGTERM/SIGINT it forwards `{cmd:'shutdown'}` over the IPC\n * channel that `child_process.fork` sets up automatically, then escalates\n * SIGTERM -> SIGKILL on the same shape as the watcher-worker supervisor.\n */\n\nexport interface StartSupervisorDeps {\n fork: typeof import('node:child_process').fork;\n /** Path to the daemon binary entrypoint (typically `process.argv[1]`). */\n childModulePath: string;\n /** Forwarded to the child verbatim (typically `process.argv.slice(2)`). */\n childArgs: string[];\n log: (entry: { event: string; [key: string]: unknown }) => void;\n /**\n * Optional metrics capture. Production wiring constructs a\n * `MetricsCollector` from `loadAuthToken()` config (the supervisor parent\n * runs before the daemon child constructs its own collector). When the\n * user has no saved auth token, the supervisor still runs — metrics is\n * just `undefined` and supervision events still surface via `log`.\n */\n metrics?: StartSupervisorMetrics;\n now: () => number;\n setTimeout: (fn: () => void, ms: number) => unknown;\n clearTimeout: (timer: unknown) => void;\n /**\n * Process signal subscription. Tests inject a stub so SIGTERM/SIGINT can be\n * driven without touching the real `process` global.\n */\n onSignal: (signal: NodeJS.Signals, handler: () => void) => void;\n}\n\nexport type StartSupervisorReason = 'graceful' | 'circuit_open';\n\nexport interface StartSupervisorResult {\n /**\n * Resolves when the child exits cleanly OR the circuit opens. Callers can\n * await this from the entrypoint to keep the supervisor process alive\n * until the supervised daemon settles.\n */\n done: Promise<{ exitCode: number; reason: StartSupervisorReason }>;\n}\n\n/** Empirically: SIGSEGV -> 139, SIGBUS -> 138, SIGABRT -> 134 on POSIX. */\nconst ABNORMAL_SIGNALS = new Set<NodeJS.Signals>(['SIGABRT', 'SIGSEGV', 'SIGBUS', 'SIGKILL']);\n\nconst SHUTDOWN_GRACEFUL_MS = 5_000;\nconst SHUTDOWN_SIGTERM_MS = 2_000;\n\ninterface ChildHolder {\n process: ChildProcess;\n spawnedAt: number;\n exited: boolean;\n}\n\nexport function runStartSupervisor(deps: StartSupervisorDeps): StartSupervisorResult {\n let child: ChildHolder | null = null;\n let restartState: AttemptState = makeInitialAttemptState();\n let restartTimer: unknown = null;\n let circuitLogged = false;\n let shutdownInitiated = false;\n\n let resolveDone: (value: { exitCode: number; reason: StartSupervisorReason }) => void = () => {};\n const done = new Promise<{ exitCode: number; reason: StartSupervisorReason }>((resolve) => {\n resolveDone = resolve;\n });\n\n function captureMetric(eventType: string, properties: Record<string, unknown>): void {\n deps.metrics?.capture(eventType, properties);\n }\n\n function spawnChild(opts: { isRespawn: boolean }): void {\n const proc = deps.fork(deps.childModulePath, deps.childArgs, {\n env: { ...process.env, SHIPYARD_DAEMON_CHILD: '1' },\n stdio: 'inherit',\n });\n const holder: ChildHolder = {\n process: proc,\n spawnedAt: deps.now(),\n exited: false,\n };\n child = holder;\n deps.log({\n event: 'daemon_supervisor_started',\n pid: proc.pid ?? null,\n deathCount: restartState.failureCount,\n });\n\n if (opts.isRespawn) {\n emitRespawn(proc.pid ?? null);\n }\n\n proc.on('exit', (code, signal) => {\n handleChildExit(holder, code, signal);\n });\n proc.on('error', (err) => {\n deps.log({\n event: 'daemon_supervisor_child_error',\n err: err instanceof Error ? err.message : String(err),\n });\n });\n }\n\n function handleChildExit(\n holder: ChildHolder,\n code: number | null,\n signal: NodeJS.Signals | null\n ): void {\n holder.exited = true;\n /** Drop stale exits — only the live child drives state. */\n if (child !== holder) return;\n child = null;\n\n const uptimeMs = deps.now() - holder.spawnedAt;\n\n if (shutdownInitiated) {\n deps.log({ event: 'daemon_supervisor_child_exited_during_shutdown', code, signal, uptimeMs });\n resolveDone({ exitCode: code ?? 0, reason: 'graceful' });\n return;\n }\n\n if (!isAbnormalExit(code, signal)) {\n deps.log({ event: 'daemon_supervisor_child_exited_clean', code, signal, uptimeMs });\n resolveDone({ exitCode: code ?? 0, reason: 'graceful' });\n return;\n }\n\n handleAbnormalChildExit(holder, code, signal, uptimeMs);\n }\n\n function handleAbnormalChildExit(\n holder: ChildHolder,\n code: number | null,\n signal: NodeJS.Signals | null,\n uptimeMs: number\n ): void {\n deps.log({ event: 'daemon_supervisor_child_died', code, signal, uptimeMs });\n\n /**\n * Reuse the guard's pure restart core: 'subscribe_failure' drives the\n * same backoff + circuit logic per-process. Different state instance,\n * same primitive (third use site after guard's per-path circuit and the\n * watcher-worker supervisor's restart circuit).\n */\n const failureDecision = decideAction(restartState, { kind: 'subscribe_failure' }, deps.now());\n restartState = failureDecision.state;\n emitFailureSignals(failureDecision.signals, holder);\n\n if (restartState.circuitOpenedAt !== null) {\n /**\n * Per the spec for this layer: rather than half-open probe like the\n * watcher worker (which lives inside the daemon), the CLI supervisor\n * surfaces the failure to the user so they can investigate. The\n * supervisor terminates rather than continuing to thrash.\n */\n resolveDone({ exitCode: 1, reason: 'circuit_open' });\n return;\n }\n\n scheduleRespawn();\n }\n\n function emitFailureSignals(\n signals: ReturnType<typeof decideAction>['signals'],\n holder: ChildHolder\n ): void {\n for (const sig of signals) {\n if (sig.kind === 'circuit_opened' && !circuitLogged) {\n circuitLogged = true;\n const windowMs = deps.now() - holder.spawnedAt;\n deps.log({\n event: 'daemon_supervisor_circuit_open',\n deathCount: restartState.failureCount,\n windowMs,\n });\n captureMetric('daemon_supervisor_circuit_open', {\n deathCount: restartState.failureCount,\n windowMs,\n });\n }\n }\n }\n\n function scheduleRespawn(): void {\n if (shutdownInitiated) return;\n if (restartState.circuitOpenedAt !== null) return;\n\n const requestDecision = decideAction(\n restartState,\n { kind: 'request_subscribe', reason: 'rescan', activeCount: 0 },\n deps.now()\n );\n restartState = requestDecision.state;\n deps.log({\n event: 'daemon_supervisor_respawn_scheduled',\n deathCount: restartState.failureCount,\n });\n\n switch (requestDecision.action.kind) {\n case 'wait': {\n restartTimer = deps.setTimeout(() => {\n restartTimer = null;\n if (shutdownInitiated) return;\n spawnChild({ isRespawn: true });\n }, requestDecision.action.ms);\n return;\n }\n case 'subscribe':\n case 'evict_and_subscribe':\n /**\n * `evict_and_subscribe` only fires when activeCount >= MAX_ACTIVE_WATCHERS;\n * we always pass activeCount: 0 so the pure core never returns it here.\n * Treating both as \"respawn now\" keeps the switch exhaustive without\n * coupling this layer to guard-internals.\n */\n spawnChild({ isRespawn: true });\n return;\n case 'reject_stub':\n /** Circuit-open path is handled by the caller before scheduleRespawn. */\n return;\n case 'noop':\n /** decideRequest never returns 'noop'. */\n return;\n default:\n assertNever(requestDecision.action);\n }\n }\n\n /**\n * Emit the `daemon_supervisor_respawned` log + metric. The metric carries\n * `newPid` (post-fork) plus `deathCount`. Called inline in `spawnChild` for\n * respawns; the initial spawn does not emit this event.\n */\n function emitRespawn(newPid: number | null): void {\n deps.log({ event: 'daemon_supervisor_respawned', deathCount: restartState.failureCount });\n captureMetric('daemon_supervisor_respawned', {\n newPid,\n deathCount: restartState.failureCount,\n });\n }\n\n function forwardShutdown(): void {\n if (shutdownInitiated) return;\n shutdownInitiated = true;\n\n if (restartTimer !== null) {\n deps.clearTimeout(restartTimer);\n restartTimer = null;\n }\n\n const holder = child;\n if (!holder) {\n /**\n * Either we never spawned, the previous child already exited, or the\n * circuit opened. Resolve with code 0 so the supervisor process exits.\n */\n deps.log({ event: 'daemon_supervisor_shutdown_no_child' });\n resolveDone({ exitCode: 0, reason: 'graceful' });\n return;\n }\n\n deps.log({ event: 'daemon_supervisor_shutdown_requested' });\n\n /**\n * Cooperative shutdown via the IPC channel that `fork()` sets up. The\n * child should listen for `process.on('message', ...)` and tear down\n * gracefully on `{cmd:'shutdown'}`.\n */\n try {\n holder.process.send?.({ cmd: 'shutdown' });\n } catch (err) {\n deps.log({\n event: 'daemon_supervisor_shutdown_send_failed',\n err: err instanceof Error ? err.message : String(err),\n });\n }\n\n /** SIGTERM after grace, SIGKILL after that. */\n deps.setTimeout(() => onSigtermDeadline(holder), SHUTDOWN_GRACEFUL_MS);\n }\n\n function onSigtermDeadline(holder: ChildHolder): void {\n if (holder.exited) return;\n deps.log({ event: 'daemon_supervisor_shutdown_sigterm' });\n try {\n holder.process.kill('SIGTERM');\n } catch (err) {\n deps.log({\n event: 'daemon_supervisor_kill_failed',\n signal: 'SIGTERM',\n err: err instanceof Error ? err.message : String(err),\n });\n }\n deps.setTimeout(() => onSigkillDeadline(holder), SHUTDOWN_SIGTERM_MS);\n }\n\n function onSigkillDeadline(holder: ChildHolder): void {\n if (holder.exited) return;\n deps.log({ event: 'daemon_supervisor_shutdown_sigkill' });\n try {\n holder.process.kill('SIGKILL');\n } catch (err) {\n deps.log({\n event: 'daemon_supervisor_kill_failed',\n signal: 'SIGKILL',\n err: err instanceof Error ? err.message : String(err),\n });\n /**\n * Safety net: SIGKILL throwing AND on-exit not firing is a paranoid\n * combination (zombie process, EPERM on a child we own), but if it\n * happens the `done` promise hangs forever and so does whoever\n * awaits it. Resolve here so the supervisor parent can exit.\n */\n resolveDone({ exitCode: 1, reason: 'graceful' });\n }\n }\n\n /** Wire signal forwarding via injected hook so tests can drive deterministically. */\n deps.onSignal('SIGTERM', forwardShutdown);\n deps.onSignal('SIGINT', forwardShutdown);\n\n /** Spawn the initial child immediately. */\n spawnChild({ isRespawn: false });\n\n return { done };\n}\n\nfunction isAbnormalExit(code: number | null, signal: NodeJS.Signals | null): boolean {\n if (signal !== null && ABNORMAL_SIGNALS.has(signal)) return true;\n if (code !== null && code !== 0) return true;\n return false;\n}\n"],"mappings":"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","names":[]}
|
package/dist/worker.d.ts
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* IPC protocol between the daemon (parent) and the watcher worker subprocess.
|
|
5
|
-
*
|
|
6
|
-
* Wire format: line-delimited JSON over the worker's stdio. Each line is
|
|
7
|
-
* exactly one Command (parent → worker) or one Reply (worker → parent), with
|
|
8
|
-
* no embedded literal newlines — JSON encoding escapes newlines inside string
|
|
9
|
-
* values (e.g. a path containing `\n`) so the line protocol stays intact.
|
|
10
|
-
*
|
|
11
|
-
* Stdout is the IPC channel; structured worker logs go to stderr only.
|
|
12
|
-
*/
|
|
13
|
-
declare const SubscribeOptionsSchema: z.ZodObject<{
|
|
14
|
-
ignore: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
15
|
-
backend: z.ZodOptional<z.ZodEnum<{
|
|
16
|
-
default: "default";
|
|
17
|
-
"brute-force": "brute-force";
|
|
18
|
-
watchman: "watchman";
|
|
19
|
-
}>>;
|
|
20
|
-
}, z.core.$strip>;
|
|
21
|
-
type WorkerSubscribeOptions = z.infer<typeof SubscribeOptionsSchema>;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Watcher worker entry point — the only place in the daemon that imports
|
|
25
|
-
* `@parcel/watcher` (post-Commit-4). The worker is intentionally minimal:
|
|
26
|
-
* subscribe/unsubscribe/shutdown over stdio, no business logic, no state
|
|
27
|
-
* beyond a Map<id, AsyncSubscription>.
|
|
28
|
-
*
|
|
29
|
-
* Crashes are expected (parcel/watcher SIGABRTs on FSEvents NULL-deref); we
|
|
30
|
-
* keep the blast surface as small as possible so the parent's supervisor
|
|
31
|
-
* can replay the subscription map onto a fresh worker.
|
|
32
|
-
*/
|
|
33
|
-
interface ParcelEventLike {
|
|
34
|
-
type: 'create' | 'update' | 'delete';
|
|
35
|
-
path: string;
|
|
36
|
-
}
|
|
37
|
-
interface ParcelAsyncSubscriptionLike {
|
|
38
|
-
unsubscribe(): Promise<void>;
|
|
39
|
-
}
|
|
40
|
-
type WorkerSubscribeFn = (path: string, fn: (err: Error | null, events: ParcelEventLike[]) => unknown, opts?: WorkerSubscribeOptions) => Promise<ParcelAsyncSubscriptionLike>;
|
|
41
|
-
interface RunWorkerDeps {
|
|
42
|
-
subscribe: WorkerSubscribeFn;
|
|
43
|
-
stdin: NodeJS.ReadableStream;
|
|
44
|
-
stdout: NodeJS.WritableStream;
|
|
45
|
-
stderr: NodeJS.WritableStream;
|
|
46
|
-
}
|
|
47
|
-
declare function runWorker(deps: RunWorkerDeps): Promise<void>;
|
|
48
|
-
|
|
49
|
-
export { type RunWorkerDeps, type WorkerSubscribeFn, runWorker };
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|