@offworld/sdk 0.1.6 → 0.1.7

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/index.d.mts CHANGED
@@ -5,7 +5,7 @@ import { Agent, Config, Config as Config$1, FileIndex, FileIndexEntry, FileRole,
5
5
  * SDK Constants
6
6
  */
7
7
  /** SDK version - must match package.json */
8
- declare const VERSION = "0.1.6";
8
+ declare const VERSION = "0.1.7";
9
9
  /**
10
10
  * Default patterns to ignore when scanning repositories.
11
11
  * Includes directories, binary files, IDE configs, and build outputs.
package/dist/index.mjs CHANGED
@@ -15,7 +15,7 @@ import { api } from "@offworld/backend-api/api";
15
15
  * SDK Constants
16
16
  */
17
17
  /** SDK version - must match package.json */
18
- const VERSION = "0.1.6";
18
+ const VERSION = "0.1.7";
19
19
  /**
20
20
  * Default patterns to ignore when scanning repositories.
21
21
  * Includes directories, binary files, IDE configs, and build outputs.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["GlobalMapSchema","ProjectMapSchema","RepoNotFoundError"],"sources":["../src/constants.ts","../src/paths.ts","../src/config.ts","../src/repo-source.ts","../src/index-manager.ts","../src/map.ts","../src/clone.ts","../src/ai/errors.ts","../src/ai/stream/types.ts","../src/ai/stream/accumulator.ts","../src/ai/stream/transformer.ts","../src/ai/opencode.ts","../src/sync.ts","../src/auth.ts","../src/agents.ts","../src/generate.ts","../src/manifest.ts","../src/dep-mappings.ts","../src/reference-matcher.ts","../src/agents-md.ts","../src/repo-manager.ts","../src/models.ts","../src/installation.ts"],"sourcesContent":["/**\n * SDK Constants\n */\n\n/** SDK version - must match package.json */\nexport const VERSION = \"0.1.6\";\n\n/**\n * Default patterns to ignore when scanning repositories.\n * Includes directories, binary files, IDE configs, and build outputs.\n */\nexport const DEFAULT_IGNORE_PATTERNS = [\n\t\".git\",\n\t\".git/**\",\n\t\".svn\",\n\t\".hg\",\n\n\t\"node_modules\",\n\t\"node_modules/**\",\n\t\"vendor\",\n\t\"vendor/**\",\n\t\".pnpm\",\n\t\".yarn\",\n\n\t\"dist\",\n\t\"dist/**\",\n\t\"build\",\n\t\"build/**\",\n\t\"out\",\n\t\"out/**\",\n\t\".next\",\n\t\".nuxt\",\n\t\".output\",\n\t\"target\",\n\t\"__pycache__\",\n\t\"*.pyc\",\n\n\t\".vscode\",\n\t\".vscode/**\",\n\t\".idea\",\n\t\".idea/**\",\n\t\"*.swp\",\n\t\"*.swo\",\n\t\".DS_Store\",\n\n\t\"*.jpg\",\n\t\"*.jpeg\",\n\t\"*.png\",\n\t\"*.gif\",\n\t\"*.ico\",\n\t\"*.webp\",\n\t\"*.svg\",\n\t\"*.bmp\",\n\t\"*.tiff\",\n\t\"*.mp4\",\n\t\"*.webm\",\n\t\"*.mov\",\n\t\"*.avi\",\n\t\"*.mkv\",\n\t\"*.mp3\",\n\t\"*.wav\",\n\t\"*.flac\",\n\t\"*.ogg\",\n\t\"*.pdf\",\n\t\"*.zip\",\n\t\"*.tar\",\n\t\"*.gz\",\n\t\"*.rar\",\n\t\"*.7z\",\n\t\"*.exe\",\n\t\"*.dll\",\n\t\"*.so\",\n\t\"*.dylib\",\n\t\"*.bin\",\n\t\"*.wasm\",\n\t\"*.woff\",\n\t\"*.woff2\",\n\t\"*.ttf\",\n\t\"*.eot\",\n\t\"*.otf\",\n\n\t\"package-lock.json\",\n\t\"yarn.lock\",\n\t\"pnpm-lock.yaml\",\n\t\"bun.lockb\",\n\t\"Cargo.lock\",\n\t\"Gemfile.lock\",\n\t\"poetry.lock\",\n\t\"composer.lock\",\n\t\"go.sum\",\n\n\t\"coverage\",\n\t\"coverage/**\",\n\t\".nyc_output\",\n\t\".coverage\",\n\t\"htmlcov\",\n\n\t\"*.log\",\n\t\"logs\",\n\t\"tmp\",\n\t\"temp\",\n\t\".tmp\",\n\t\".temp\",\n\t\".cache\",\n\n\t\".env\",\n\t\".env.*\",\n\t\"*.pem\",\n\t\"*.key\",\n] as const;\n","/**\n * XDG-based directory paths for offworld CLI\n * Uses xdg-basedir package for cross-platform compatibility (Linux/macOS)\n */\n\nimport { xdgConfig, xdgData, xdgState } from \"xdg-basedir\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\nconst APP_NAME = \"offworld\";\n\n/**\n * Main namespace for all XDG-compliant paths\n */\nexport const Paths = {\n\t/**\n\t * XDG_CONFIG_HOME/offworld\n\t * Fallback: ~/.config/offworld\n\t */\n\tget config(): string {\n\t\treturn join(xdgConfig ?? join(homedir(), \".config\"), APP_NAME);\n\t},\n\n\t/**\n\t * XDG_DATA_HOME/offworld\n\t * Fallback: ~/.local/share/offworld\n\t */\n\tget data(): string {\n\t\treturn join(xdgData ?? join(homedir(), \".local\", \"share\"), APP_NAME);\n\t},\n\n\t/**\n\t * XDG_STATE_HOME/offworld\n\t * Fallback: ~/.local/state/offworld\n\t */\n\tget state(): string {\n\t\treturn join(xdgState ?? join(homedir(), \".local\", \"state\"), APP_NAME);\n\t},\n\n\t/**\n\t * Configuration file path: ~/.config/offworld/offworld.json\n\t */\n\tget configFile(): string {\n\t\treturn join(this.config, \"offworld.json\");\n\t},\n\n\t/**\n\t * Auth file path: ~/.local/share/offworld/auth.json\n\t */\n\tget authFile(): string {\n\t\treturn join(this.data, \"auth.json\");\n\t},\n\n\t/**\n\t * Meta directory: ~/.local/share/offworld/meta\n\t */\n\tget metaDir(): string {\n\t\treturn join(this.data, \"meta\");\n\t},\n\n\t/**\n\t * Default repo root: ~/ow\n\t */\n\tget defaultRepoRoot(): string {\n\t\treturn join(homedir(), \"ow\");\n\t},\n\n\t/**\n\t * Offworld single-skill directory: ~/.local/share/offworld/skill/offworld\n\t */\n\tget offworldSkillDir(): string {\n\t\treturn join(this.data, \"skill\", \"offworld\");\n\t},\n\n\t/**\n\t * Offworld references directory: ~/.local/share/offworld/skill/offworld/references\n\t */\n\tget offworldReferencesDir(): string {\n\t\treturn join(this.offworldSkillDir, \"references\");\n\t},\n\n\t/**\n\t * Offworld assets directory: ~/.local/share/offworld/skill/offworld/assets\n\t */\n\tget offworldAssetsDir(): string {\n\t\treturn join(this.offworldSkillDir, \"assets\");\n\t},\n\n\t/**\n\t * Global map path: ~/.local/share/offworld/skill/offworld/assets/map.json\n\t */\n\tget offworldGlobalMapPath(): string {\n\t\treturn join(this.offworldAssetsDir, \"map.json\");\n\t},\n};\n\n/**\n * Expands ~ to user's home directory (for backward compatibility)\n */\nexport function expandTilde(path: string): string {\n\tif (path.startsWith(\"~/\")) {\n\t\treturn join(homedir(), path.slice(2));\n\t}\n\treturn path;\n}\n","/**\n * Config utilities for path management and configuration loading\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { ConfigSchema } from \"@offworld/types\";\nimport type { Config } from \"@offworld/types\";\nimport { Paths, expandTilde } from \"./paths\";\n\n/**\n * Returns the repository root directory.\n * Uses configured repoRoot or defaults to ~/ow\n */\nexport function getMetaRoot(): string {\n\treturn Paths.data;\n}\n\nexport function getRepoRoot(config?: Config): string {\n\tconst root = config?.repoRoot ?? Paths.defaultRepoRoot;\n\treturn expandTilde(root);\n}\n\n/**\n * Returns the path for a specific repository.\n * Format: {repoRoot}/{provider}/{owner}/{repo}\n *\n * @param fullName - The repo identifier in \"owner/repo\" format\n * @param provider - Git provider (defaults to \"github\")\n * @param config - Optional config for custom repoRoot\n */\nexport function getRepoPath(\n\tfullName: string,\n\tprovider: \"github\" | \"gitlab\" | \"bitbucket\" = \"github\",\n\tconfig?: Config,\n): string {\n\tconst root = getRepoRoot(config);\n\tconst [owner, repo] = fullName.split(\"/\");\n\tif (!owner || !repo) {\n\t\tthrow new Error(`Invalid fullName format: ${fullName}. Expected \"owner/repo\"`);\n\t}\n\treturn join(root, provider, owner, repo);\n}\n\n/**\n * Convert owner/repo format to meta directory name.\n * Collapses owner==repo (e.g., better-auth/better-auth -> better-auth)\n */\nexport function toMetaDirName(repoName: string): string {\n\tif (repoName.includes(\"/\")) {\n\t\tconst parts = repoName.split(\"/\");\n\t\tconst owner = parts[0];\n\t\tconst repo = parts[1];\n\t\tif (!owner || !repo) {\n\t\t\treturn repoName;\n\t\t}\n\t\tif (owner === repo) {\n\t\t\treturn repo;\n\t\t}\n\t\treturn `${owner}-${repo}`;\n\t}\n\treturn repoName;\n}\n\n/**\n * Convert owner/repo format to reference filename.\n * Collapses redundant owner/repo pairs by checking if repo name is contained in owner:\n * - honojs/hono -> hono.md (hono is in honojs)\n * - get-convex/convex-backend -> convex-backend.md (convex is in get-convex)\n * - tanstack/query -> tanstack-query.md (query is not in tanstack)\n */\nexport function toReferenceFileName(repoName: string): string {\n\tif (repoName.includes(\"/\")) {\n\t\tconst parts = repoName.split(\"/\");\n\t\tconst owner = parts[0];\n\t\tconst repo = parts[1];\n\t\tif (!owner || !repo) {\n\t\t\treturn `${repoName.toLowerCase()}.md`;\n\t\t}\n\t\tconst ownerLower = owner.toLowerCase();\n\t\tconst repoLower = repo.toLowerCase();\n\n\t\tconst repoParts = repoLower.split(\"-\");\n\t\tconst significantPart = repoParts.find((part) => part.length >= 3 && ownerLower.includes(part));\n\n\t\tif (significantPart || ownerLower === repoLower) {\n\t\t\treturn `${repoLower}.md`;\n\t\t}\n\n\t\treturn `${ownerLower}-${repoLower}.md`;\n\t}\n\treturn `${repoName.toLowerCase()}.md`;\n}\n\nexport function toReferenceName(repoName: string): string {\n\treturn toReferenceFileName(repoName).replace(/\\.md$/, \"\");\n}\n\nexport function getReferencePath(fullName: string): string {\n\treturn join(Paths.offworldReferencesDir, toReferenceFileName(fullName));\n}\n\nexport function getMetaPath(fullName: string): string {\n\treturn join(Paths.data, \"meta\", toMetaDirName(fullName));\n}\n\n/**\n * Returns the path to the configuration file\n * Uses XDG Base Directory specification\n */\nexport function getConfigPath(): string {\n\treturn Paths.configFile;\n}\n\n/**\n * Loads configuration from ~/.config/offworld/offworld.json\n * Returns defaults if file doesn't exist\n */\nexport function loadConfig(): Config {\n\tconst configPath = getConfigPath();\n\n\tif (!existsSync(configPath)) {\n\t\treturn ConfigSchema.parse({});\n\t}\n\n\ttry {\n\t\tconst content = readFileSync(configPath, \"utf-8\");\n\t\tconst data = JSON.parse(content);\n\t\treturn ConfigSchema.parse(data);\n\t} catch {\n\t\treturn ConfigSchema.parse({});\n\t}\n}\n\n/**\n * Saves configuration to ~/.config/offworld/offworld.json\n * Creates directory if it doesn't exist\n * Merges with existing config\n */\nexport function saveConfig(updates: Partial<Config>): Config {\n\tconst configPath = getConfigPath();\n\tconst configDir = dirname(configPath);\n\n\tif (!existsSync(configDir)) {\n\t\tmkdirSync(configDir, { recursive: true });\n\t}\n\n\tconst existing = loadConfig();\n\tconst merged = { ...existing, ...updates };\n\n\tconst validated = ConfigSchema.parse(merged);\n\n\twriteFileSync(configPath, JSON.stringify(validated, null, 2), \"utf-8\");\n\n\treturn validated;\n}\n","/**\n * Repository source parsing utilities\n */\n\nimport { createHash } from \"node:crypto\";\nimport { existsSync, statSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { basename } from \"node:path\";\nimport type { GitProvider, LocalRepoSource, RemoteRepoSource, RepoSource } from \"@offworld/types\";\nimport { toReferenceFileName } from \"./config.js\";\nimport { expandTilde } from \"./paths.js\";\n\nexport class RepoSourceError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"RepoSourceError\";\n\t}\n}\n\nexport class PathNotFoundError extends RepoSourceError {\n\tconstructor(path: string) {\n\t\tsuper(`Path does not exist: ${path}`);\n\t\tthis.name = \"PathNotFoundError\";\n\t}\n}\n\nexport class NotGitRepoError extends RepoSourceError {\n\tconstructor(path: string) {\n\t\tsuper(`Directory is not a git repository: ${path}`);\n\t\tthis.name = \"NotGitRepoError\";\n\t}\n}\n\nconst PROVIDER_HOSTS: Record<string, GitProvider> = {\n\t\"github.com\": \"github\",\n\t\"gitlab.com\": \"gitlab\",\n\t\"bitbucket.org\": \"bitbucket\",\n};\n\nconst HTTPS_URL_REGEX =\n\t/^https?:\\/\\/(github\\.com|gitlab\\.com|bitbucket\\.org)\\/([^/]+)\\/([^/]+?)(?:\\.git)?$/;\nconst SSH_URL_REGEX = /^git@(github\\.com|gitlab\\.com|bitbucket\\.org):([^/]+)\\/([^/]+?)(?:\\.git)?$/;\nconst SHORT_FORMAT_REGEX = /^([^/:@]+)\\/([^/:@]+)$/;\n\n/**\n * Generates a short hash of a path for local repo identification\n */\nfunction hashPath(path: string): string {\n\treturn createHash(\"sha256\").update(path).digest(\"hex\").slice(0, 12);\n}\n\n/**\n * Builds a clone URL for a remote repository\n */\nfunction buildCloneUrl(provider: GitProvider, owner: string, repo: string): string {\n\tconst hosts: Record<GitProvider, string> = {\n\t\tgithub: \"github.com\",\n\t\tgitlab: \"gitlab.com\",\n\t\tbitbucket: \"bitbucket.org\",\n\t};\n\treturn `https://${hosts[provider]}/${owner}/${repo}.git`;\n}\n\n/**\n * Parses a remote repository from HTTPS URL format\n */\nfunction parseHttpsUrl(input: string): RemoteRepoSource | null {\n\tconst match = input.match(HTTPS_URL_REGEX);\n\tif (!match) return null;\n\n\tconst [, host, owner, repo] = match;\n\tif (!host || !owner || !repo) return null;\n\n\tconst provider = PROVIDER_HOSTS[host];\n\tif (!provider) return null;\n\n\tconst ownerLower = owner.toLowerCase();\n\tconst repoLower = repo.toLowerCase();\n\treturn {\n\t\ttype: \"remote\",\n\t\tprovider,\n\t\towner: ownerLower,\n\t\trepo: repoLower,\n\t\tfullName: `${ownerLower}/${repoLower}`,\n\t\tqualifiedName: `${host}:${ownerLower}/${repoLower}`,\n\t\tcloneUrl: buildCloneUrl(provider, ownerLower, repoLower),\n\t};\n}\n\n/**\n * Parses a remote repository from SSH URL format\n */\nfunction parseSshUrl(input: string): RemoteRepoSource | null {\n\tconst match = input.match(SSH_URL_REGEX);\n\tif (!match) return null;\n\n\tconst [, host, owner, repo] = match;\n\tif (!host || !owner || !repo) return null;\n\n\tconst provider = PROVIDER_HOSTS[host];\n\tif (!provider) return null;\n\n\tconst ownerLower = owner.toLowerCase();\n\tconst repoLower = repo.toLowerCase();\n\treturn {\n\t\ttype: \"remote\",\n\t\tprovider,\n\t\towner: ownerLower,\n\t\trepo: repoLower,\n\t\tfullName: `${ownerLower}/${repoLower}`,\n\t\tqualifiedName: `${host}:${ownerLower}/${repoLower}`,\n\t\tcloneUrl: buildCloneUrl(provider, ownerLower, repoLower),\n\t};\n}\n\n/**\n * Parses a remote repository from short format (owner/repo)\n * Defaults to GitHub as provider\n */\nfunction parseShortFormat(input: string): RemoteRepoSource | null {\n\tconst match = input.match(SHORT_FORMAT_REGEX);\n\tif (!match) return null;\n\n\tconst [, owner, repo] = match;\n\tif (!owner || !repo) return null;\n\n\tconst provider: GitProvider = \"github\";\n\tconst host = \"github.com\";\n\n\tconst ownerLower = owner.toLowerCase();\n\tconst repoLower = repo.toLowerCase();\n\treturn {\n\t\ttype: \"remote\",\n\t\tprovider,\n\t\towner: ownerLower,\n\t\trepo: repoLower,\n\t\tfullName: `${ownerLower}/${repoLower}`,\n\t\tqualifiedName: `${host}:${ownerLower}/${repoLower}`,\n\t\tcloneUrl: buildCloneUrl(provider, ownerLower, repoLower),\n\t};\n}\n\n/**\n * Parses a local repository path\n * Validates that the path exists and contains a .git directory\n */\nfunction parseLocalPath(input: string): LocalRepoSource {\n\tconst absolutePath = resolve(expandTilde(input));\n\n\tif (!existsSync(absolutePath)) {\n\t\tthrow new PathNotFoundError(absolutePath);\n\t}\n\n\tconst stats = statSync(absolutePath);\n\tif (!stats.isDirectory()) {\n\t\tthrow new RepoSourceError(`Path is not a directory: ${absolutePath}`);\n\t}\n\n\tconst gitPath = resolve(absolutePath, \".git\");\n\tif (!existsSync(gitPath)) {\n\t\tthrow new NotGitRepoError(absolutePath);\n\t}\n\n\tconst name = basename(absolutePath);\n\tconst hash = hashPath(absolutePath);\n\n\treturn {\n\t\ttype: \"local\",\n\t\tpath: absolutePath,\n\t\tname,\n\t\tqualifiedName: `local:${hash}`,\n\t};\n}\n\n/**\n * Determines if input looks like a local path\n */\nfunction isLocalPath(input: string): boolean {\n\treturn input.startsWith(\".\") || input.startsWith(\"/\") || input.startsWith(\"~\");\n}\n\n/**\n * Parses a repository input and returns a structured RepoSource\n *\n * Supported formats:\n * - owner/repo (short format, defaults to GitHub)\n * - https://github.com/owner/repo\n * - https://gitlab.com/owner/repo\n * - https://bitbucket.org/owner/repo\n * - git@github.com:owner/repo.git (SSH format)\n * - . (current directory as local repo)\n * - /absolute/path (local repo)\n *\n * @throws PathNotFoundError if local path doesn't exist\n * @throws NotGitRepoError if local path is not a git repository\n * @throws RepoSourceError for other parsing failures\n */\nexport function parseRepoInput(input: string): RepoSource {\n\tconst trimmed = input.trim();\n\n\tconst httpsResult = parseHttpsUrl(trimmed);\n\tif (httpsResult) return httpsResult;\n\n\tconst sshResult = parseSshUrl(trimmed);\n\tif (sshResult) return sshResult;\n\n\tif (isLocalPath(trimmed)) {\n\t\treturn parseLocalPath(trimmed);\n\t}\n\n\tconst shortResult = parseShortFormat(trimmed);\n\tif (shortResult) return shortResult;\n\n\tthrow new RepoSourceError(\n\t\t`Unable to parse repository input: ${input}. ` +\n\t\t\t\"Expected formats: owner/repo, https://github.com/owner/repo, git@github.com:owner/repo.git, or a local path\",\n\t);\n}\n\nexport function getReferenceFileNameForSource(source: RepoSource): string {\n\tif (source.type === \"remote\") {\n\t\treturn toReferenceFileName(source.fullName);\n\t}\n\treturn toReferenceFileName(source.name);\n}\n","/**\n * Map manager for global and project maps\n *\n * Manages:\n * - Global map: ~/.local/share/offworld/skill/offworld/assets/map.json\n * - Project map: ./.offworld/map.json\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport {\n\tGlobalMapSchema,\n\tProjectMapSchema,\n\ttype GlobalMap,\n\ttype GlobalMapRepoEntry,\n\ttype ProjectMap,\n\ttype ProjectMapRepoEntry,\n} from \"@offworld/types\";\nimport { Paths } from \"./paths.js\";\n\n/**\n * Reads the global map from ~/.local/share/offworld/skill/offworld/assets/map.json\n * Returns empty map if file doesn't exist or is invalid\n */\nexport function readGlobalMap(): GlobalMap {\n\tconst mapPath = Paths.offworldGlobalMapPath;\n\n\tif (!existsSync(mapPath)) {\n\t\treturn { repos: {} };\n\t}\n\n\ttry {\n\t\tconst content = readFileSync(mapPath, \"utf-8\");\n\t\tconst data = JSON.parse(content);\n\t\treturn GlobalMapSchema.parse(data);\n\t} catch {\n\t\treturn { repos: {} };\n\t}\n}\n\n/**\n * Writes the global map to ~/.local/share/offworld/skill/offworld/assets/map.json\n * Creates directory if it doesn't exist\n */\nexport function writeGlobalMap(map: GlobalMap): void {\n\tconst mapPath = Paths.offworldGlobalMapPath;\n\tconst mapDir = dirname(mapPath);\n\n\tif (!existsSync(mapDir)) {\n\t\tmkdirSync(mapDir, { recursive: true });\n\t}\n\n\tconst validated = GlobalMapSchema.parse(map);\n\twriteFileSync(mapPath, JSON.stringify(validated, null, 2), \"utf-8\");\n}\n\n/**\n * Adds or updates a repo entry in the global map\n *\n * @param qualifiedName - The qualified repo name (owner/repo)\n * @param entry - The map entry to add/update\n */\nexport function upsertGlobalMapEntry(qualifiedName: string, entry: GlobalMapRepoEntry): void {\n\tconst map = readGlobalMap();\n\tmap.repos[qualifiedName] = entry;\n\twriteGlobalMap(map);\n}\n\n/**\n * Removes a repo entry from the global map\n *\n * @param qualifiedName - The qualified repo name (owner/repo)\n * @returns true if repo was removed, false if not found\n */\nexport function removeGlobalMapEntry(qualifiedName: string): boolean {\n\tconst map = readGlobalMap();\n\n\tif (!(qualifiedName in map.repos)) {\n\t\treturn false;\n\t}\n\n\tdelete map.repos[qualifiedName];\n\twriteGlobalMap(map);\n\treturn true;\n}\n\n/**\n * Writes a project map to ./.offworld/map.json\n *\n * @param projectRoot - Absolute path to project root\n * @param entries - Map of qualified repo names to project map entries\n */\nexport function writeProjectMap(\n\tprojectRoot: string,\n\tentries: Record<string, ProjectMapRepoEntry>,\n): void {\n\tconst mapPath = join(projectRoot, \".offworld\", \"map.json\");\n\tconst mapDir = dirname(mapPath);\n\n\tif (!existsSync(mapDir)) {\n\t\tmkdirSync(mapDir, { recursive: true });\n\t}\n\n\tconst projectMap: ProjectMap = {\n\t\tversion: 1,\n\t\tscope: \"project\",\n\t\tglobalMapPath: Paths.offworldGlobalMapPath,\n\t\trepos: entries,\n\t};\n\n\tconst validated = ProjectMapSchema.parse(projectMap);\n\twriteFileSync(mapPath, JSON.stringify(validated, null, 2), \"utf-8\");\n}\n","/**\n * Map query helpers for fast routing without reading full map.json\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type {\n\tGlobalMap,\n\tGlobalMapRepoEntry,\n\tProjectMap,\n\tProjectMapRepoEntry,\n} from \"@offworld/types\";\nimport { GlobalMapSchema, ProjectMapSchema } from \"@offworld/types/schemas\";\nimport { Paths } from \"./paths.js\";\n\nexport interface MapEntry {\n\tscope: \"project\" | \"global\";\n\tqualifiedName: string;\n\tentry: GlobalMapRepoEntry | ProjectMapRepoEntry;\n}\n\nexport interface SearchResult {\n\tqualifiedName: string;\n\tfullName: string;\n\tlocalPath: string;\n\tprimary: string;\n\tkeywords: string[];\n\tscore: number;\n}\n\nexport interface GetMapEntryOptions {\n\tpreferProject?: boolean;\n\tcwd?: string;\n}\n\nexport interface SearchMapOptions {\n\tlimit?: number;\n\tcwd?: string;\n}\n\nfunction readGlobalMapSafe(): GlobalMap | null {\n\tconst mapPath = Paths.offworldGlobalMapPath;\n\tif (!existsSync(mapPath)) return null;\n\n\ttry {\n\t\tconst content = readFileSync(mapPath, \"utf-8\");\n\t\treturn GlobalMapSchema.parse(JSON.parse(content));\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction readProjectMapSafe(cwd: string): ProjectMap | null {\n\tconst mapPath = resolve(cwd, \".offworld/map.json\");\n\tif (!existsSync(mapPath)) return null;\n\n\ttry {\n\t\tconst content = readFileSync(mapPath, \"utf-8\");\n\t\treturn ProjectMapSchema.parse(JSON.parse(content));\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Normalize input to match against repo keys.\n * Accepts: github.com:owner/repo, owner/repo, repo\n */\nfunction normalizeInput(input: string): { provider?: string; fullName: string; repoName: string } {\n\tconst trimmed = input.trim().toLowerCase();\n\n\tif (trimmed.includes(\":\")) {\n\t\tconst parts = trimmed.split(\":\", 2);\n\t\tconst provider = parts[0];\n\t\tconst fullName = parts[1] ?? \"\";\n\t\tconst repoName = fullName.split(\"/\").pop() ?? fullName;\n\t\treturn { provider, fullName, repoName };\n\t}\n\n\tif (trimmed.includes(\"/\")) {\n\t\tconst repoName = trimmed.split(\"/\").pop() ?? trimmed;\n\t\treturn { fullName: trimmed, repoName };\n\t}\n\n\treturn { fullName: trimmed, repoName: trimmed };\n}\n\n/**\n * Tokenize a string for search matching.\n * Lowercase, strip @, split on /_- and whitespace.\n */\nfunction tokenize(str: string): string[] {\n\treturn str\n\t\t.toLowerCase()\n\t\t.replace(/@/g, \"\")\n\t\t.split(/[/_\\-\\s]+/)\n\t\t.filter(Boolean);\n}\n\n/**\n * Resolve an input string to a qualified repo key in a map.\n *\n * @param input - Accepts github.com:owner/repo, owner/repo, or repo name\n * @param map - A global or project map\n * @returns The matching qualified name or null\n */\nexport function resolveRepoKey(input: string, map: GlobalMap | ProjectMap): string | null {\n\tconst { provider, fullName, repoName } = normalizeInput(input);\n\tconst keys = Object.keys(map.repos);\n\n\tif (provider) {\n\t\tconst qualifiedKey = `${provider}:${fullName}`;\n\t\tif (keys.includes(qualifiedKey)) {\n\t\t\treturn qualifiedKey;\n\t\t}\n\t}\n\n\tfor (const key of keys) {\n\t\tconst keyFullName = key.includes(\":\") ? key.split(\":\")[1] : key;\n\t\tif (keyFullName?.toLowerCase() === fullName) {\n\t\t\treturn key;\n\t\t}\n\t}\n\n\tfor (const key of keys) {\n\t\tconst keyRepoName = key.split(\"/\").pop()?.toLowerCase();\n\t\tif (keyRepoName === repoName) {\n\t\t\treturn key;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Get a map entry for a repo, preferring project map if available.\n *\n * @param input - Repo identifier (github.com:owner/repo, owner/repo, or repo)\n * @param options - Options for lookup\n * @returns Entry with scope and qualified name, or null if not found\n */\nexport function getMapEntry(input: string, options: GetMapEntryOptions = {}): MapEntry | null {\n\tconst { preferProject = true, cwd = process.cwd() } = options;\n\n\tconst projectMap = preferProject ? readProjectMapSafe(cwd) : null;\n\tconst globalMap = readGlobalMapSafe();\n\n\tif (projectMap) {\n\t\tconst key = resolveRepoKey(input, projectMap);\n\t\tif (key && projectMap.repos[key]) {\n\t\t\treturn {\n\t\t\t\tscope: \"project\",\n\t\t\t\tqualifiedName: key,\n\t\t\t\tentry: projectMap.repos[key],\n\t\t\t};\n\t\t}\n\t}\n\n\tif (globalMap) {\n\t\tconst key = resolveRepoKey(input, globalMap);\n\t\tif (key && globalMap.repos[key]) {\n\t\t\treturn {\n\t\t\t\tscope: \"global\",\n\t\t\t\tqualifiedName: key,\n\t\t\t\tentry: globalMap.repos[key],\n\t\t\t};\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Search the map for repos matching a term.\n *\n * Scoring:\n * - Exact fullName match: 100\n * - Keyword hit: 50 per keyword\n * - Partial contains in fullName: 25\n * - Partial contains in keywords: 10\n *\n * @param term - Search term\n * @param options - Search options\n * @returns Sorted list of matches\n */\nexport function searchMap(term: string, options: SearchMapOptions = {}): SearchResult[] {\n\tconst { limit = 10 } = options;\n\n\tconst globalMap = readGlobalMapSafe();\n\tif (!globalMap) return [];\n\n\tconst termTokens = tokenize(term);\n\tconst termLower = term.toLowerCase();\n\tconst results: SearchResult[] = [];\n\n\tfor (const qualifiedName of Object.keys(globalMap.repos)) {\n\t\tconst entry = globalMap.repos[qualifiedName];\n\t\tif (!entry) continue;\n\n\t\tconst fullName = qualifiedName.includes(\":\")\n\t\t\t? (qualifiedName.split(\":\")[1] ?? qualifiedName)\n\t\t\t: qualifiedName;\n\t\tconst fullNameLower = fullName.toLowerCase();\n\t\tconst keywords = entry.keywords ?? [];\n\t\tconst keywordsLower = keywords.map((k) => k.toLowerCase());\n\n\t\tlet score = 0;\n\n\t\tif (fullNameLower === termLower) {\n\t\t\tscore += 100;\n\t\t}\n\n\t\tfor (const token of termTokens) {\n\t\t\tif (keywordsLower.includes(token)) {\n\t\t\t\tscore += 50;\n\t\t\t}\n\t\t}\n\n\t\tif (fullNameLower.includes(termLower) && score < 100) {\n\t\t\tscore += 25;\n\t\t}\n\n\t\tfor (const kw of keywordsLower) {\n\t\t\tif (kw.includes(termLower)) {\n\t\t\t\tscore += 10;\n\t\t\t}\n\t\t}\n\n\t\tconst fullNameTokens = tokenize(fullName);\n\t\tfor (const token of termTokens) {\n\t\t\tif (fullNameTokens.includes(token)) {\n\t\t\t\tscore += 30;\n\t\t\t}\n\t\t}\n\n\t\tif (score > 0) {\n\t\t\tresults.push({\n\t\t\t\tqualifiedName,\n\t\t\t\tfullName,\n\t\t\t\tlocalPath: entry.localPath,\n\t\t\t\tprimary: entry.primary,\n\t\t\t\tkeywords,\n\t\t\t\tscore,\n\t\t\t});\n\t\t}\n\t}\n\n\tresults.sort((a, b) => {\n\t\tif (b.score !== a.score) return b.score - a.score;\n\t\treturn a.fullName.localeCompare(b.fullName);\n\t});\n\n\treturn results.slice(0, limit);\n}\n\n/**\n * Get the project map path if it exists in cwd.\n */\nexport function getProjectMapPath(cwd: string = process.cwd()): string | null {\n\tconst mapPath = resolve(cwd, \".offworld/map.json\");\n\treturn existsSync(mapPath) ? mapPath : null;\n}\n","/**\n * Git clone and repository management utilities\n */\n\nimport { existsSync, readdirSync, rmSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { execFileSync, spawn } from \"node:child_process\";\nimport type { Config, RemoteRepoSource } from \"@offworld/types\";\nimport { getRepoPath, loadConfig, toReferenceFileName } from \"./config.js\";\nimport { readGlobalMap, upsertGlobalMapEntry, removeGlobalMapEntry } from \"./index-manager.js\";\nimport { Paths } from \"./paths.js\";\n\nexport class CloneError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"CloneError\";\n\t}\n}\n\nexport class RepoExistsError extends CloneError {\n\tconstructor(path: string) {\n\t\tsuper(`Repository already exists at: ${path}`);\n\t\tthis.name = \"RepoExistsError\";\n\t}\n}\n\nexport class RepoNotFoundError extends CloneError {\n\tconstructor(qualifiedName: string) {\n\t\tsuper(`Repository not found in index: ${qualifiedName}`);\n\t\tthis.name = \"RepoNotFoundError\";\n\t}\n}\n\nexport class GitError extends CloneError {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly command: string,\n\t\tpublic readonly exitCode: number | null,\n\t) {\n\t\tsuper(`Git command failed: ${message}`);\n\t\tthis.name = \"GitError\";\n\t}\n}\n\nexport interface CloneOptions {\n\t/** Use shallow clone (--depth 1) */\n\tshallow?: boolean;\n\t/** Clone specific branch */\n\tbranch?: string;\n\t/** Custom config for repo root path */\n\tconfig?: Config;\n\t/** Force clone even if directory exists (removes existing) */\n\tforce?: boolean;\n\t/** Use sparse checkout for large repos (only src/, lib/, packages/, docs/) */\n\tsparse?: boolean;\n}\n\nfunction execGit(args: string[], cwd?: string): string {\n\ttry {\n\t\tconst result = execFileSync(\"git\", args, {\n\t\t\tcwd,\n\t\t\tencoding: \"utf-8\",\n\t\t\tstdio: [\"pipe\", \"pipe\", \"pipe\"],\n\t\t});\n\t\treturn result.trim();\n\t} catch (error) {\n\t\tconst err = error as { status?: number; stderr?: Buffer | string; message?: string };\n\t\tconst stderr = err.stderr\n\t\t\t? typeof err.stderr === \"string\"\n\t\t\t\t? err.stderr\n\t\t\t\t: err.stderr.toString()\n\t\t\t: err.message || \"Unknown error\";\n\t\tthrow new GitError(stderr.trim(), `git ${args.join(\" \")}`, err.status ?? null);\n\t}\n}\n\nfunction execGitAsync(args: string[], cwd?: string): Promise<string> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst proc = spawn(\"git\", args, {\n\t\t\tcwd,\n\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\tenv: { ...process.env, GIT_TERMINAL_PROMPT: \"0\" },\n\t\t});\n\n\t\tlet stdout = \"\";\n\t\tlet stderr = \"\";\n\n\t\tproc.stdout.on(\"data\", (data: Buffer) => {\n\t\t\tstdout += data.toString();\n\t\t});\n\t\tproc.stderr.on(\"data\", (data: Buffer) => {\n\t\t\tstderr += data.toString();\n\t\t});\n\n\t\tproc.on(\"close\", (code) => {\n\t\t\tif (code === 0) {\n\t\t\t\tresolve(stdout.trim());\n\t\t\t} else {\n\t\t\t\treject(new GitError(stderr.trim() || \"Unknown error\", `git ${args.join(\" \")}`, code));\n\t\t\t}\n\t\t});\n\n\t\tproc.on(\"error\", (err) => {\n\t\t\treject(new GitError(err.message, `git ${args.join(\" \")}`, null));\n\t\t});\n\t});\n}\n\nexport function getCommitSha(repoPath: string): string {\n\treturn execGit([\"rev-parse\", \"HEAD\"], repoPath);\n}\n\nexport function getCommitDistance(\n\trepoPath: string,\n\tolderSha: string,\n\tnewerSha = \"HEAD\",\n): number | null {\n\ttry {\n\t\ttry {\n\t\t\texecGit([\"cat-file\", \"-e\", olderSha], repoPath);\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t\tconst count = execGit([\"rev-list\", \"--count\", `${olderSha}..${newerSha}`], repoPath);\n\t\treturn Number.parseInt(count, 10);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nconst SPARSE_CHECKOUT_DIRS = [\"src\", \"lib\", \"packages\", \"docs\", \"README.md\", \"package.json\"];\n\n/**\n * Clone a remote repository to the local repo root.\n *\n * @param source - Remote repo source from parseRepoInput()\n * @param options - Clone options (shallow, branch, config)\n * @returns The local path where the repo was cloned\n * @throws RepoExistsError if repo already exists (unless force is true)\n * @throws GitError if clone fails\n */\nexport async function cloneRepo(\n\tsource: RemoteRepoSource,\n\toptions: CloneOptions = {},\n): Promise<string> {\n\tconst config = options.config ?? loadConfig();\n\tconst repoPath = getRepoPath(source.fullName, source.provider, config);\n\n\tif (existsSync(repoPath)) {\n\t\tif (options.force) {\n\t\t\trmSync(repoPath, { recursive: true, force: true });\n\t\t} else {\n\t\t\tthrow new RepoExistsError(repoPath);\n\t\t}\n\t}\n\n\ttry {\n\t\tif (options.sparse) {\n\t\t\tawait cloneSparse(source.cloneUrl, repoPath, options);\n\t\t} else {\n\t\t\tawait cloneStandard(source.cloneUrl, repoPath, options);\n\t\t}\n\t} catch (err) {\n\t\tcleanupEmptyParentDirs(repoPath);\n\t\tthrow err;\n\t}\n\n\tconst referenceFileName = toReferenceFileName(source.fullName);\n\tconst referencePath = join(Paths.offworldReferencesDir, referenceFileName);\n\tconst hasReference = existsSync(referencePath);\n\n\tupsertGlobalMapEntry(source.qualifiedName, {\n\t\tlocalPath: repoPath,\n\t\treferences: hasReference ? [referenceFileName] : [],\n\t\tprimary: hasReference ? referenceFileName : \"\",\n\t\tkeywords: [],\n\t\tupdatedAt: new Date().toISOString(),\n\t});\n\n\treturn repoPath;\n}\n\nfunction cleanupEmptyParentDirs(repoPath: string): void {\n\tconst ownerDir = dirname(repoPath);\n\tif (existsSync(ownerDir) && readdirSync(ownerDir).length === 0) {\n\t\trmSync(ownerDir, { recursive: true, force: true });\n\t}\n}\n\nasync function cloneStandard(\n\tcloneUrl: string,\n\trepoPath: string,\n\toptions: CloneOptions,\n): Promise<void> {\n\tconst args = [\"clone\"];\n\n\tif (options.shallow) {\n\t\targs.push(\"--depth\", \"1\");\n\t}\n\n\tif (options.branch) {\n\t\targs.push(\"--branch\", options.branch);\n\t}\n\n\targs.push(cloneUrl, repoPath);\n\tawait execGitAsync(args);\n}\n\nasync function cloneSparse(\n\tcloneUrl: string,\n\trepoPath: string,\n\toptions: CloneOptions,\n): Promise<void> {\n\tconst args = [\"clone\", \"--filter=blob:none\", \"--no-checkout\", \"--sparse\"];\n\n\tif (options.shallow) {\n\t\targs.push(\"--depth\", \"1\");\n\t}\n\n\tif (options.branch) {\n\t\targs.push(\"--branch\", options.branch);\n\t}\n\n\targs.push(cloneUrl, repoPath);\n\tawait execGitAsync(args);\n\n\tawait execGitAsync([\"sparse-checkout\", \"set\", ...SPARSE_CHECKOUT_DIRS], repoPath);\n\tawait execGitAsync([\"checkout\"], repoPath);\n}\n\nexport function isShallowClone(repoPath: string): boolean {\n\ttry {\n\t\tconst result = execGit([\"rev-parse\", \"--is-shallow-repository\"], repoPath);\n\t\treturn result === \"true\";\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nexport async function unshallowRepo(repoPath: string): Promise<boolean> {\n\tif (!isShallowClone(repoPath)) {\n\t\treturn false;\n\t}\n\n\tawait execGitAsync([\"fetch\", \"--unshallow\"], repoPath);\n\treturn true;\n}\n\nexport interface UpdateResult {\n\t/** Whether any updates were fetched */\n\tupdated: boolean;\n\t/** Previous commit SHA before update */\n\tpreviousSha: string;\n\t/** Current commit SHA after update */\n\tcurrentSha: string;\n\t/** Whether the repo was unshallowed */\n\tunshallowed?: boolean;\n}\n\nexport interface UpdateOptions {\n\t/** Convert shallow clone to full clone */\n\tunshallow?: boolean;\n}\n\n/**\n * Update a cloned repository by running git fetch and pull.\n *\n * @param qualifiedName - The qualified name of the repo (e.g., \"github.com:owner/repo\")\n * @param options - Update options\n * @returns Update result with commit SHAs\n * @throws RepoNotFoundError if repo not in index\n * @throws GitError if fetch/pull fails\n */\nexport async function updateRepo(\n\tqualifiedName: string,\n\toptions: UpdateOptions = {},\n): Promise<UpdateResult> {\n\tconst map = readGlobalMap();\n\tconst entry = map.repos[qualifiedName];\n\tif (!entry) {\n\t\tthrow new RepoNotFoundError(qualifiedName);\n\t}\n\n\tconst repoPath = entry.localPath;\n\n\tif (!existsSync(repoPath)) {\n\t\tthrow new RepoNotFoundError(qualifiedName);\n\t}\n\n\tconst previousSha = getCommitSha(repoPath);\n\tlet unshallowed = false;\n\tif (options.unshallow) {\n\t\tunshallowed = await unshallowRepo(repoPath);\n\t}\n\n\tawait execGitAsync([\"fetch\"], repoPath);\n\tawait execGitAsync([\"pull\", \"--ff-only\"], repoPath);\n\n\tconst currentSha = getCommitSha(repoPath);\n\tupsertGlobalMapEntry(qualifiedName, {\n\t\t...entry,\n\t\tupdatedAt: new Date().toISOString(),\n\t});\n\n\treturn {\n\t\tupdated: previousSha !== currentSha,\n\t\tpreviousSha,\n\t\tcurrentSha,\n\t\tunshallowed,\n\t};\n}\n\nexport interface RemoveOptions {\n\treferenceOnly?: boolean;\n\trepoOnly?: boolean;\n}\n\nexport async function removeRepo(\n\tqualifiedName: string,\n\toptions: RemoveOptions = {},\n): Promise<boolean> {\n\tconst map = readGlobalMap();\n\tconst entry = map.repos[qualifiedName];\n\tif (!entry) {\n\t\treturn false;\n\t}\n\n\tconst { referenceOnly = false, repoOnly = false } = options;\n\tconst removeRepoFiles = !referenceOnly;\n\tconst removeReferenceFiles = !repoOnly;\n\n\tif (removeRepoFiles && existsSync(entry.localPath)) {\n\t\trmSync(entry.localPath, { recursive: true, force: true });\n\t\tcleanupEmptyParentDirs(entry.localPath);\n\t}\n\n\tif (removeReferenceFiles) {\n\t\tfor (const referenceFileName of entry.references) {\n\t\t\tconst referencePath = join(Paths.offworldReferencesDir, referenceFileName);\n\t\t\tif (existsSync(referencePath)) {\n\t\t\t\trmSync(referencePath, { force: true });\n\t\t\t}\n\t\t}\n\n\t\tif (entry.primary) {\n\t\t\tconst metaDirName = entry.primary.replace(/\\.md$/, \"\");\n\t\t\tconst metaPath = join(Paths.metaDir, metaDirName);\n\t\t\tif (existsSync(metaPath)) {\n\t\t\t\trmSync(metaPath, { recursive: true, force: true });\n\t\t\t}\n\t\t}\n\t}\n\n\tif (removeRepoFiles) {\n\t\tremoveGlobalMapEntry(qualifiedName);\n\t} else if (removeReferenceFiles) {\n\t\tupsertGlobalMapEntry(qualifiedName, {\n\t\t\t...entry,\n\t\t\treferences: [],\n\t\t\tprimary: \"\",\n\t\t});\n\t}\n\n\treturn true;\n}\n\nexport function listRepos(): string[] {\n\tconst map = readGlobalMap();\n\treturn Object.keys(map.repos);\n}\n\nexport function isRepoCloned(qualifiedName: string): boolean {\n\tconst map = readGlobalMap();\n\tconst entry = map.repos[qualifiedName];\n\tif (!entry) return false;\n\treturn existsSync(entry.localPath);\n}\n\n/**\n * Get the local path for a cloned repository.\n *\n * @param qualifiedName - The qualified name of the repo\n * @returns The local path or undefined if not cloned\n */\nexport function getClonedRepoPath(qualifiedName: string): string | undefined {\n\tconst map = readGlobalMap();\n\tconst entry = map.repos[qualifiedName];\n\tif (!entry) return undefined;\n\tif (!existsSync(entry.localPath)) return undefined;\n\treturn entry.localPath;\n}\n","/**\n * Base class for OpenCode reference errors\n */\nexport class OpenCodeReferenceError extends Error {\n\treadonly _tag: string = \"OpenCodeReferenceError\";\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly details?: unknown,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"OpenCodeReferenceError\";\n\t}\n}\n\n/**\n * Error when the @opencode-ai/sdk package is not installed or invalid\n */\nexport class OpenCodeSDKError extends OpenCodeReferenceError {\n\treadonly _tag = \"OpenCodeSDKError\" as const;\n\tconstructor(message?: string) {\n\t\tsuper(\n\t\t\tmessage ?? \"Failed to import @opencode-ai/sdk. Install it with: bun add @opencode-ai/sdk\",\n\t\t);\n\t\tthis.name = \"OpenCodeSDKError\";\n\t}\n}\n\n/**\n * Error when the requested provider is not found\n */\nexport class InvalidProviderError extends OpenCodeReferenceError {\n\treadonly _tag = \"InvalidProviderError\" as const;\n\treadonly hint: string;\n\n\tconstructor(\n\t\tpublic readonly providerID: string,\n\t\tpublic readonly availableProviders: string[],\n\t) {\n\t\tconst hint =\n\t\t\tavailableProviders.length > 0\n\t\t\t\t? `Available providers: ${availableProviders.join(\", \")}`\n\t\t\t\t: \"No providers available. Check your OpenCode configuration.\";\n\t\tsuper(`Provider \"${providerID}\" not found. ${hint}`);\n\t\tthis.name = \"InvalidProviderError\";\n\t\tthis.hint = hint;\n\t}\n}\n\n/**\n * Error when the provider exists but is not connected/authenticated\n */\nexport class ProviderNotConnectedError extends OpenCodeReferenceError {\n\treadonly _tag = \"ProviderNotConnectedError\" as const;\n\treadonly hint: string;\n\n\tconstructor(\n\t\tpublic readonly providerID: string,\n\t\tpublic readonly connectedProviders: string[],\n\t) {\n\t\tconst hint =\n\t\t\tconnectedProviders.length > 0\n\t\t\t\t? `Connected providers: ${connectedProviders.join(\", \")}. Run 'opencode auth ${providerID}' to connect.`\n\t\t\t\t: `No providers connected. Run 'opencode auth ${providerID}' to authenticate.`;\n\t\tsuper(`Provider \"${providerID}\" is not connected. ${hint}`);\n\t\tthis.name = \"ProviderNotConnectedError\";\n\t\tthis.hint = hint;\n\t}\n}\n\n/**\n * Error when the requested model is not found for a provider\n */\nexport class InvalidModelError extends OpenCodeReferenceError {\n\treadonly _tag = \"InvalidModelError\" as const;\n\treadonly hint: string;\n\n\tconstructor(\n\t\tpublic readonly modelID: string,\n\t\tpublic readonly providerID: string,\n\t\tpublic readonly availableModels: string[],\n\t) {\n\t\tconst hint =\n\t\t\tavailableModels.length > 0\n\t\t\t\t? `Available models for ${providerID}: ${availableModels.slice(0, 10).join(\", \")}${availableModels.length > 10 ? ` (and ${availableModels.length - 10} more)` : \"\"}`\n\t\t\t\t: `No models available for provider \"${providerID}\".`;\n\t\tsuper(`Model \"${modelID}\" not found for provider \"${providerID}\". ${hint}`);\n\t\tthis.name = \"InvalidModelError\";\n\t\tthis.hint = hint;\n\t}\n}\n\n/**\n * Error when the OpenCode server fails to start\n */\nexport class ServerStartError extends OpenCodeReferenceError {\n\treadonly _tag = \"ServerStartError\" as const;\n\treadonly hint: string;\n\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly port?: number,\n\t\tdetails?: unknown,\n\t) {\n\t\tconst hint = port\n\t\t\t? `Failed to start server on port ${port}. Ensure no other process is using this port.`\n\t\t\t: \"Failed to start OpenCode server. Check your OpenCode installation and configuration.\";\n\t\tsuper(`${message}. ${hint}`, details);\n\t\tthis.name = \"ServerStartError\";\n\t\tthis.hint = hint;\n\t}\n}\n\n/**\n * Error when a session operation fails\n */\nexport class SessionError extends OpenCodeReferenceError {\n\treadonly _tag = \"SessionError\" as const;\n\treadonly hint: string;\n\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly sessionId?: string,\n\t\tpublic readonly sessionState?: string,\n\t\tdetails?: unknown,\n\t) {\n\t\tconst context = sessionId ? ` (session: ${sessionId})` : \"\";\n\t\tconst stateInfo = sessionState ? ` State: ${sessionState}.` : \"\";\n\t\tconst hint = `Session operation failed${context}.${stateInfo} Try creating a new session.`;\n\t\tsuper(`${message}. ${hint}`, details);\n\t\tthis.name = \"SessionError\";\n\t\tthis.hint = hint;\n\t}\n}\n\n/**\n * Error when a request times out\n */\nexport class TimeoutError extends OpenCodeReferenceError {\n\treadonly _tag = \"TimeoutError\" as const;\n\treadonly hint: string;\n\n\tconstructor(\n\t\tpublic readonly timeoutMs: number,\n\t\tpublic readonly operation: string = \"operation\",\n\t) {\n\t\tconst hint = `The ${operation} did not complete within ${timeoutMs}ms. Consider increasing the timeout or checking if the model is responding.`;\n\t\tsuper(`Timeout: ${operation} did not complete within ${timeoutMs}ms. ${hint}`);\n\t\tthis.name = \"TimeoutError\";\n\t\tthis.hint = hint;\n\t}\n}\n","/**\n * Zod schemas for OpenCode stream events\n * Replaces inline `as` casts with runtime-validated types\n */\n\nimport { z } from \"zod\";\n\nconst PartBaseSchema = z.object({\n\tid: z.string().optional(),\n\tsessionID: z.string().optional(),\n\tmessageID: z.string().optional(),\n});\n\nexport const TextPartSchema = PartBaseSchema.extend({\n\ttype: z.literal(\"text\"),\n\ttext: z.string().optional(),\n});\n\nexport const ToolStatePendingSchema = z.object({\n\tstatus: z.literal(\"pending\"),\n});\n\nexport const ToolStateRunningSchema = z.object({\n\tstatus: z.literal(\"running\"),\n\ttitle: z.string().optional(),\n\tinput: z.unknown().optional(),\n\tmetadata: z.record(z.string(), z.unknown()).optional(),\n\ttime: z\n\t\t.object({\n\t\t\tstart: z.number(),\n\t\t})\n\t\t.optional(),\n});\n\nexport const ToolStateCompletedSchema = z.object({\n\tstatus: z.literal(\"completed\"),\n\ttitle: z.string().optional(),\n\tinput: z.record(z.string(), z.unknown()).optional(),\n\toutput: z.string().optional(),\n\tmetadata: z.record(z.string(), z.unknown()).optional(),\n\ttime: z\n\t\t.object({\n\t\t\tstart: z.number(),\n\t\t\tend: z.number(),\n\t\t})\n\t\t.optional(),\n});\n\nexport const ToolStateErrorSchema = z.object({\n\tstatus: z.literal(\"error\"),\n\terror: z.string().optional(),\n\tinput: z.record(z.string(), z.unknown()).optional(),\n\ttime: z\n\t\t.object({\n\t\t\tstart: z.number(),\n\t\t\tend: z.number(),\n\t\t})\n\t\t.optional(),\n});\n\nexport const ToolStateSchema = z.discriminatedUnion(\"status\", [\n\tToolStatePendingSchema,\n\tToolStateRunningSchema,\n\tToolStateCompletedSchema,\n\tToolStateErrorSchema,\n]);\n\nexport const ToolPartSchema = PartBaseSchema.extend({\n\ttype: z.literal(\"tool\"),\n\tcallID: z.string().optional(),\n\ttool: z.string().optional(),\n\tstate: ToolStateSchema.optional(),\n});\n\nexport const StepStartPartSchema = PartBaseSchema.extend({\n\ttype: z.literal(\"step-start\"),\n});\n\nexport const StepFinishPartSchema = PartBaseSchema.extend({\n\ttype: z.literal(\"step-finish\"),\n\treason: z.string().optional(),\n});\n\nexport const ToolUsePartSchema = PartBaseSchema.extend({\n\ttype: z.literal(\"tool-use\"),\n\ttoolUseId: z.string().optional(),\n\tname: z.string().optional(),\n});\n\nexport const ToolResultPartSchema = PartBaseSchema.extend({\n\ttype: z.literal(\"tool-result\"),\n\ttoolUseId: z.string().optional(),\n});\n\nexport const MessagePartSchema = z.discriminatedUnion(\"type\", [\n\tTextPartSchema,\n\tToolPartSchema,\n\tStepStartPartSchema,\n\tStepFinishPartSchema,\n\tToolUsePartSchema,\n\tToolResultPartSchema,\n]);\n\n/**\n * Session error payload\n */\nexport const SessionErrorSchema = z.object({\n\tname: z.string().optional(),\n\tmessage: z.string().optional(),\n\tcode: z.string().optional(),\n});\n\nexport const MessagePartUpdatedPropsSchema = z.object({\n\tpart: MessagePartSchema,\n});\n\n/**\n * Properties for session.idle event\n */\nexport const SessionIdlePropsSchema = z.object({\n\tsessionID: z.string(),\n});\n\n/**\n * Properties for session.error event\n */\nexport const SessionErrorPropsSchema = z.object({\n\tsessionID: z.string(),\n\terror: SessionErrorSchema.optional(),\n});\n\n/**\n * Properties for session.updated event\n */\nexport const SessionUpdatedPropsSchema = z.object({\n\tsessionID: z.string(),\n\tstatus: z.string().optional(),\n});\n\n/**\n * message.part.updated event\n */\nexport const MessagePartUpdatedEventSchema = z.object({\n\ttype: z.literal(\"message.part.updated\"),\n\tproperties: MessagePartUpdatedPropsSchema,\n});\n\n/**\n * session.idle event\n */\nexport const SessionIdleEventSchema = z.object({\n\ttype: z.literal(\"session.idle\"),\n\tproperties: SessionIdlePropsSchema,\n});\n\n/**\n * session.error event\n */\nexport const SessionErrorEventSchema = z.object({\n\ttype: z.literal(\"session.error\"),\n\tproperties: SessionErrorPropsSchema,\n});\n\n/**\n * session.updated event\n */\nexport const SessionUpdatedEventSchema = z.object({\n\ttype: z.literal(\"session.updated\"),\n\tproperties: SessionUpdatedPropsSchema,\n});\n\n/**\n * Generic event for unknown types (passthrough)\n */\nexport const GenericEventSchema = z.object({\n\ttype: z.string(),\n\tproperties: z.record(z.string(), z.unknown()),\n});\n\nexport type TextPart = z.infer<typeof TextPartSchema>;\nexport type ToolPart = z.infer<typeof ToolPartSchema>;\nexport type ToolState = z.infer<typeof ToolStateSchema>;\nexport type ToolStateRunning = z.infer<typeof ToolStateRunningSchema>;\nexport type ToolUsePart = z.infer<typeof ToolUsePartSchema>;\nexport type ToolResultPart = z.infer<typeof ToolResultPartSchema>;\nexport type MessagePart = z.infer<typeof MessagePartSchema>;\n\nexport type SessionErrorPayload = z.infer<typeof SessionErrorSchema>;\n\nexport type MessagePartUpdatedProps = z.infer<typeof MessagePartUpdatedPropsSchema>;\nexport type SessionIdleProps = z.infer<typeof SessionIdlePropsSchema>;\nexport type SessionErrorProps = z.infer<typeof SessionErrorPropsSchema>;\nexport type SessionUpdatedProps = z.infer<typeof SessionUpdatedPropsSchema>;\n\nexport type MessagePartUpdatedEvent = z.infer<typeof MessagePartUpdatedEventSchema>;\nexport type SessionIdleEvent = z.infer<typeof SessionIdleEventSchema>;\nexport type SessionErrorEvent = z.infer<typeof SessionErrorEventSchema>;\nexport type SessionUpdatedEvent = z.infer<typeof SessionUpdatedEventSchema>;\nexport type GenericEvent = z.infer<typeof GenericEventSchema>;\n\n/**\n * All known stream event types\n */\nexport type StreamEvent =\n\t| MessagePartUpdatedEvent\n\t| SessionIdleEvent\n\t| SessionErrorEvent\n\t| SessionUpdatedEvent\n\t| GenericEvent;\n","/**\n * Text accumulator for stream events\n * Manages accumulation of text parts by ID and provides delta extraction\n */\n\nimport type { TextPart } from \"./types.js\";\n\n/**\n * Accumulates text from streaming message parts.\n * Tracks multiple parts by ID and provides delta text between updates.\n */\nexport class TextAccumulator {\n\tprivate readonly parts = new Map<string, string>();\n\tprivate _firstTextReceived = false;\n\n\t/**\n\t * Whether any text has been received\n\t */\n\tget hasReceivedText(): boolean {\n\t\treturn this._firstTextReceived;\n\t}\n\n\t/**\n\t * Accumulate text from a message part and return the delta (new text only).\n\t * Returns null if the part should be skipped (non-text, no ID, no text).\n\t */\n\taccumulatePart(part: TextPart): string | null {\n\t\tif (part.type !== \"text\" || !part.text || !part.id) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst partId = part.id;\n\t\tconst prevText = this.parts.get(partId) ?? \"\";\n\t\tthis.parts.set(partId, part.text);\n\n\t\tif (!this._firstTextReceived) {\n\t\t\tthis._firstTextReceived = true;\n\t\t}\n\n\t\tif (part.text.length > prevText.length) {\n\t\t\treturn part.text.slice(prevText.length);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Get the full accumulated text from all parts\n\t */\n\tgetFullText(): string {\n\t\treturn Array.from(this.parts.values()).join(\"\");\n\t}\n\n\t/**\n\t * Clear accumulated text\n\t */\n\tclear(): void {\n\t\tthis.parts.clear();\n\t\tthis._firstTextReceived = false;\n\t}\n}\n","/**\n * Stream event transformer and parser\n * Safely parses and validates stream events using Zod schemas\n */\n\nimport {\n\tMessagePartUpdatedPropsSchema,\n\tSessionIdlePropsSchema,\n\tSessionErrorPropsSchema,\n\tSessionErrorSchema,\n\ttype TextPart,\n\ttype ToolPart,\n\ttype SessionErrorPayload,\n\ttype MessagePartUpdatedProps,\n\ttype SessionIdleProps,\n\ttype SessionErrorProps,\n} from \"./types.js\";\n\n/**\n * Raw event from the OpenCode SDK stream\n */\nexport interface RawStreamEvent {\n\ttype: string;\n\tproperties: Record<string, unknown>;\n}\n\n/**\n * Result of parsing a stream event\n */\nexport type ParsedEventResult =\n\t| {\n\t\t\ttype: \"message.part.updated\";\n\t\t\tprops: MessagePartUpdatedProps;\n\t\t\ttextPart: TextPart | null;\n\t\t\ttoolPart: ToolPart | null;\n\t }\n\t| { type: \"session.idle\"; props: SessionIdleProps }\n\t| { type: \"session.error\"; props: SessionErrorProps; error: SessionErrorPayload | null }\n\t| { type: \"unknown\"; rawType: string };\n\n/**\n * Parse a raw stream event into a typed result.\n * Uses safe parsing - returns type: \"unknown\" for unrecognized or invalid events.\n */\nexport function parseStreamEvent(event: RawStreamEvent): ParsedEventResult {\n\tswitch (event.type) {\n\t\tcase \"message.part.updated\": {\n\t\t\tconst propsResult = MessagePartUpdatedPropsSchema.safeParse(event.properties);\n\t\t\tif (!propsResult.success) {\n\t\t\t\treturn { type: \"unknown\", rawType: event.type };\n\t\t\t}\n\t\t\tconst props = propsResult.data;\n\t\t\tconst textPart = props.part.type === \"text\" ? props.part : null;\n\t\t\tconst toolPart = props.part.type === \"tool\" ? props.part : null;\n\t\t\treturn { type: \"message.part.updated\", props, textPart, toolPart };\n\t\t}\n\n\t\tcase \"session.idle\": {\n\t\t\tconst propsResult = SessionIdlePropsSchema.safeParse(event.properties);\n\t\t\tif (!propsResult.success) {\n\t\t\t\treturn { type: \"unknown\", rawType: event.type };\n\t\t\t}\n\t\t\treturn { type: \"session.idle\", props: propsResult.data };\n\t\t}\n\n\t\tcase \"session.error\": {\n\t\t\tconst propsResult = SessionErrorPropsSchema.safeParse(event.properties);\n\t\t\tif (!propsResult.success) {\n\t\t\t\treturn { type: \"unknown\", rawType: event.type };\n\t\t\t}\n\t\t\tconst props = propsResult.data;\n\n\t\t\tlet error: SessionErrorPayload | null = null;\n\t\t\tif (props.error) {\n\t\t\t\tconst errorResult = SessionErrorSchema.safeParse(props.error);\n\t\t\t\tif (errorResult.success) {\n\t\t\t\t\terror = errorResult.data;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn { type: \"session.error\", props, error };\n\t\t}\n\n\t\tdefault:\n\t\t\treturn { type: \"unknown\", rawType: event.type };\n\t}\n}\n\nexport function isEventForSession(event: RawStreamEvent, sessionId: string): boolean {\n\tconst props = event.properties;\n\tif (\"sessionID\" in props && typeof props.sessionID === \"string\") {\n\t\treturn props.sessionID === sessionId;\n\t}\n\tif (\n\t\t\"part\" in props &&\n\t\ttypeof props.part === \"object\" &&\n\t\tprops.part !== null &&\n\t\t\"sessionID\" in props.part &&\n\t\ttypeof props.part.sessionID === \"string\"\n\t) {\n\t\treturn props.part.sessionID === sessionId;\n\t}\n\treturn true;\n}\n","import {\n\tOpenCodeReferenceError,\n\tOpenCodeSDKError,\n\tInvalidProviderError,\n\tProviderNotConnectedError,\n\tInvalidModelError,\n\tServerStartError,\n\tSessionError,\n\tTimeoutError,\n} from \"./errors.js\";\nimport { TextAccumulator, parseStreamEvent, isEventForSession } from \"./stream/index.js\";\n\nexport const DEFAULT_AI_PROVIDER = \"opencode\";\nexport const DEFAULT_AI_MODEL = \"claude-opus-4-5\";\n\nexport interface StreamPromptOptions {\n\tprompt: string;\n\tcwd: string;\n\tsystemPrompt?: string;\n\tprovider?: string;\n\n\tmodel?: string;\n\t/** Timeout in milliseconds. Set to 0 or undefined for no timeout. */\n\ttimeoutMs?: number;\n\tonDebug?: (message: string) => void;\n\tonStream?: (text: string) => void;\n}\n\nexport interface StreamPromptResult {\n\ttext: string;\n\tsessionId: string;\n\tdurationMs: number;\n}\n\ninterface OpenCodeServer {\n\tclose: () => void;\n\turl: string;\n}\n\ninterface OpenCodeSession {\n\tid: string;\n}\n\ninterface OpenCodeEvent {\n\ttype: string;\n\tproperties: Record<string, unknown>;\n}\n\ninterface OpenCodeProviderModel {\n\tid: string;\n\tname: string;\n}\n\ninterface OpenCodeProvider {\n\tid: string;\n\tname: string;\n\tmodels: Record<string, OpenCodeProviderModel>;\n}\n\ninterface OpenCodeProviderListResponse {\n\tall: OpenCodeProvider[];\n\tconnected: string[];\n\tdefault: Record<string, string>;\n}\n\ninterface OpenCodeClient {\n\tsession: {\n\t\tcreate: () => Promise<{ data: OpenCodeSession; error?: unknown }>;\n\t\tprompt: (options: {\n\t\t\tpath: { id: string };\n\t\t\tbody: {\n\t\t\t\tagent?: string;\n\t\t\t\tparts: Array<{ type: string; text: string }>;\n\t\t\t\tmodel?: { providerID: string; modelID: string };\n\t\t\t};\n\t\t}) => Promise<{ data: unknown; error?: unknown }>;\n\t};\n\tevent: {\n\t\tsubscribe: () => Promise<{\n\t\t\tstream: AsyncIterable<OpenCodeEvent>;\n\t\t}>;\n\t};\n\tprovider: {\n\t\tlist: () => Promise<{ data: OpenCodeProviderListResponse; error?: unknown }>;\n\t};\n}\n\ninterface AgentConfig {\n\tdisable?: boolean;\n\tprompt?: string;\n\tdescription?: string;\n\tmode?: string;\n\tpermission?: Record<string, string>;\n\ttools?: Record<string, boolean>;\n}\n\ninterface OpenCodeConfig {\n\tplugin?: unknown[];\n\tmcp?: Record<string, unknown>;\n\tinstructions?: unknown[];\n\tagent?: Record<string, AgentConfig>;\n}\n\ntype CreateOpencodeResult = { server: OpenCodeServer };\ntype CreateOpencodeClientFn = (opts: { baseUrl: string; directory: string }) => OpenCodeClient;\ntype CreateOpencodeFn = (opts: {\n\tport: number;\n\tcwd?: string;\n\tconfig?: OpenCodeConfig;\n}) => Promise<CreateOpencodeResult>;\n\nlet cachedCreateOpencode: CreateOpencodeFn | null = null;\nlet cachedCreateOpencodeClient: CreateOpencodeClientFn | null = null;\n\nasync function getOpenCodeSDK(): Promise<{\n\tcreateOpencode: CreateOpencodeFn;\n\tcreateOpencodeClient: CreateOpencodeClientFn;\n}> {\n\tif (cachedCreateOpencode && cachedCreateOpencodeClient) {\n\t\treturn {\n\t\t\tcreateOpencode: cachedCreateOpencode,\n\t\t\tcreateOpencodeClient: cachedCreateOpencodeClient,\n\t\t};\n\t}\n\n\ttry {\n\t\tconst sdk = await import(\"@opencode-ai/sdk\");\n\t\tif (\n\t\t\ttypeof sdk.createOpencode !== \"function\" ||\n\t\t\ttypeof sdk.createOpencodeClient !== \"function\"\n\t\t) {\n\t\t\tthrow new OpenCodeSDKError(\"SDK missing required exports\");\n\t\t}\n\t\tcachedCreateOpencode = sdk.createOpencode as CreateOpencodeFn;\n\t\tcachedCreateOpencodeClient = sdk.createOpencodeClient as CreateOpencodeClientFn;\n\t\treturn {\n\t\t\tcreateOpencode: cachedCreateOpencode,\n\t\t\tcreateOpencodeClient: cachedCreateOpencodeClient,\n\t\t};\n\t} catch (error) {\n\t\tif (error instanceof OpenCodeSDKError) {\n\t\t\tthrow error;\n\t\t}\n\t\tthrow new OpenCodeSDKError();\n\t}\n}\n\ninterface ToolRunningState {\n\tstatus: \"running\";\n\ttitle?: string;\n\tinput?: unknown;\n}\n\nfunction formatToolMessage(tool: string | undefined, state: ToolRunningState): string | null {\n\tif (state.title) {\n\t\treturn state.title;\n\t}\n\n\tif (!tool) {\n\t\treturn null;\n\t}\n\n\tconst input =\n\t\tstate.input && typeof state.input === \"object\" && !Array.isArray(state.input)\n\t\t\t? (state.input as Record<string, unknown>)\n\t\t\t: undefined;\n\tif (!input) {\n\t\treturn `Running ${tool}...`;\n\t}\n\n\tswitch (tool) {\n\t\tcase \"read\": {\n\t\t\tconst path = input.filePath ?? input.path;\n\t\t\tif (typeof path === \"string\") {\n\t\t\t\tconst filename = path.split(\"/\").pop();\n\t\t\t\treturn `Reading ${filename}...`;\n\t\t\t}\n\t\t\treturn \"Reading file...\";\n\t\t}\n\t\tcase \"glob\": {\n\t\t\tconst pattern = input.pattern;\n\t\t\tif (typeof pattern === \"string\") {\n\t\t\t\treturn `Globbing ${pattern}...`;\n\t\t\t}\n\t\t\treturn \"Searching files...\";\n\t\t}\n\t\tcase \"grep\": {\n\t\t\tconst pattern = input.pattern;\n\t\t\tif (typeof pattern === \"string\") {\n\t\t\t\tconst truncated = pattern.length > 30 ? `${pattern.slice(0, 30)}...` : pattern;\n\t\t\t\treturn `Searching for \"${truncated}\"...`;\n\t\t\t}\n\t\t\treturn \"Searching content...\";\n\t\t}\n\t\tcase \"list\": {\n\t\t\tconst path = input.path;\n\t\t\tif (typeof path === \"string\") {\n\t\t\t\treturn `Listing ${path}...`;\n\t\t\t}\n\t\t\treturn \"Listing directory...\";\n\t\t}\n\t\tdefault:\n\t\t\treturn `Running ${tool}...`;\n\t}\n}\n\nexport async function streamPrompt(options: StreamPromptOptions): Promise<StreamPromptResult> {\n\tconst {\n\t\tprompt,\n\t\tcwd,\n\t\tsystemPrompt,\n\t\tprovider: optProvider,\n\t\tmodel: optModel,\n\t\ttimeoutMs,\n\t\tonDebug,\n\t\tonStream,\n\t} = options;\n\n\tconst debug = onDebug ?? (() => {});\n\tconst stream = onStream ?? (() => {});\n\tconst startTime = Date.now();\n\n\tdebug(\"Loading OpenCode SDK...\");\n\tconst { createOpencode, createOpencodeClient } = await getOpenCodeSDK();\n\n\tconst maxAttempts = 10;\n\tlet server: OpenCodeServer | null = null;\n\tlet client: OpenCodeClient | null = null;\n\tlet port = 0;\n\n\tconst config: OpenCodeConfig = {\n\t\tplugin: [],\n\t\tmcp: {},\n\t\tinstructions: [],\n\t\tagent: {\n\t\t\tbuild: { disable: true },\n\t\t\tgeneral: { disable: true },\n\t\t\tplan: { disable: true },\n\t\t\texplore: { disable: true },\n\t\t\tanalyze: {\n\t\t\t\tprompt: [\n\t\t\t\t\t\"You are an expert at analyzing open source codebases and producing documentation.\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"Your job is to read the codebase and produce structured output based on the user's request.\",\n\t\t\t\t\t\"Use glob to discover files, grep to search for patterns, and read to examine file contents.\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"Guidelines:\",\n\t\t\t\t\t\"- Explore the codebase thoroughly before producing output\",\n\t\t\t\t\t\"- Focus on understanding architecture, key abstractions, and usage patterns\",\n\t\t\t\t\t\"- When asked for JSON output, respond with ONLY valid JSON - no markdown, no code blocks\",\n\t\t\t\t\t\"- When asked for prose, write clear and concise documentation\",\n\t\t\t\t\t\"- Always base your analysis on actual code you've read, never speculate\",\n\t\t\t\t].join(\"\\n\"),\n\t\t\t\tmode: \"primary\",\n\t\t\t\tdescription: \"Analyze open source codebases and produce summaries and reference files\",\n\t\t\t\ttools: {\n\t\t\t\t\tread: true,\n\t\t\t\t\tgrep: true,\n\t\t\t\t\tglob: true,\n\t\t\t\t\tlist: true,\n\t\t\t\t\twrite: false,\n\t\t\t\t\tbash: false,\n\t\t\t\t\tdelete: false,\n\t\t\t\t\tedit: false,\n\t\t\t\t\tpatch: false,\n\t\t\t\t\tpath: false,\n\t\t\t\t\ttodowrite: false,\n\t\t\t\t\ttodoread: false,\n\t\t\t\t\twebsearch: false,\n\t\t\t\t\twebfetch: false,\n\t\t\t\t\tcodesearch: false,\n\t\t\t\t\tskill: false,\n\t\t\t\t\ttask: false,\n\t\t\t\t\tmcp: false,\n\t\t\t\t\tquestion: false,\n\t\t\t\t\tplan_enter: false,\n\t\t\t\t\tplan_exit: false,\n\t\t\t\t},\n\t\t\t\tpermission: {\n\t\t\t\t\tedit: \"deny\",\n\t\t\t\t\tbash: \"deny\",\n\t\t\t\t\twebfetch: \"deny\",\n\t\t\t\t\texternal_directory: \"deny\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t};\n\n\tdebug(\"Starting embedded OpenCode server...\");\n\n\tfor (let attempt = 0; attempt < maxAttempts; attempt++) {\n\t\tport = Math.floor(Math.random() * 3000) + 3000;\n\t\ttry {\n\t\t\tconst result = await createOpencode({ port, cwd, config });\n\t\t\tserver = result.server;\n\t\t\tclient = createOpencodeClient({\n\t\t\t\tbaseUrl: `http://localhost:${port}`,\n\t\t\t\tdirectory: cwd,\n\t\t\t});\n\t\t\tdebug(`Server started on port ${port}`);\n\t\t\tbreak;\n\t\t} catch (err) {\n\t\t\tif (err instanceof Error && err.message?.includes(\"port\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthrow new ServerStartError(\"Failed to start OpenCode server\", port, err);\n\t\t}\n\t}\n\n\tif (!server || !client) {\n\t\tthrow new ServerStartError(\"Failed to start OpenCode server after all attempts\");\n\t}\n\n\tconst providerID = optProvider ?? DEFAULT_AI_PROVIDER;\n\tconst modelID = optModel ?? DEFAULT_AI_MODEL;\n\n\ttry {\n\t\tdebug(\"Creating session...\");\n\t\tconst sessionResult = await client.session.create();\n\t\tif (sessionResult.error) {\n\t\t\tthrow new SessionError(\"Failed to create session\", undefined, undefined, sessionResult.error);\n\t\t}\n\t\tconst sessionId = sessionResult.data.id;\n\t\tdebug(`Session created: ${sessionId}`);\n\n\t\tdebug(\"Validating provider and model...\");\n\t\tconst providerResult = await client.provider.list();\n\t\tif (providerResult.error) {\n\t\t\tthrow new OpenCodeReferenceError(\"Failed to fetch provider list\", providerResult.error);\n\t\t}\n\n\t\tconst { all: allProviders, connected: connectedProviders } = providerResult.data;\n\t\tconst allProviderIds = allProviders.map((p) => p.id);\n\n\t\tconst provider = allProviders.find((p) => p.id === providerID);\n\t\tif (!provider) {\n\t\t\tthrow new InvalidProviderError(providerID, allProviderIds);\n\t\t}\n\n\t\tif (!connectedProviders.includes(providerID)) {\n\t\t\tthrow new ProviderNotConnectedError(providerID, connectedProviders);\n\t\t}\n\n\t\tconst availableModelIds = Object.keys(provider.models);\n\t\tif (!provider.models[modelID]) {\n\t\t\tthrow new InvalidModelError(modelID, providerID, availableModelIds);\n\t\t}\n\n\t\tdebug(`Provider \"${providerID}\" and model \"${modelID}\" validated`);\n\n\t\tdebug(\"Subscribing to events...\");\n\t\tconst { stream: eventStream } = await client.event.subscribe();\n\n\t\tconst fullPrompt = systemPrompt\n\t\t\t? `${systemPrompt}\\n\\nAnalyzing codebase at: ${cwd}\\n\\n${prompt}`\n\t\t\t: `Analyzing codebase at: ${cwd}\\n\\n${prompt}`;\n\n\t\tdebug(\"Sending prompt...\");\n\t\tconst promptPromise = client.session.prompt({\n\t\t\tpath: { id: sessionId },\n\t\t\tbody: {\n\t\t\t\tagent: \"analyze\",\n\t\t\t\tparts: [{ type: \"text\", text: fullPrompt }],\n\t\t\t\tmodel: { providerID, modelID },\n\t\t\t},\n\t\t});\n\n\t\tconst textAccumulator = new TextAccumulator();\n\t\tdebug(\"Waiting for response...\");\n\n\t\tlet timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n\t\tconst processEvents = async (): Promise<string> => {\n\t\t\tfor await (const event of eventStream) {\n\t\t\t\tif (!isEventForSession(event, sessionId)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst parsed = parseStreamEvent(event);\n\n\t\t\t\tswitch (parsed.type) {\n\t\t\t\t\tcase \"message.part.updated\": {\n\t\t\t\t\t\tif (parsed.toolPart?.state) {\n\t\t\t\t\t\t\tconst { state, tool } = parsed.toolPart;\n\t\t\t\t\t\t\tif (state.status === \"running\") {\n\t\t\t\t\t\t\t\tconst message = formatToolMessage(tool, state);\n\t\t\t\t\t\t\t\tif (message) {\n\t\t\t\t\t\t\t\t\tdebug(message);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (parsed.textPart) {\n\t\t\t\t\t\t\tconst delta = textAccumulator.accumulatePart(parsed.textPart);\n\t\t\t\t\t\t\tif (!textAccumulator.hasReceivedText) {\n\t\t\t\t\t\t\t\tdebug(\"Writing reference...\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (delta) {\n\t\t\t\t\t\t\t\tstream(delta);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase \"session.idle\": {\n\t\t\t\t\t\tif (parsed.props.sessionID === sessionId) {\n\t\t\t\t\t\t\tdebug(\"Response complete\");\n\t\t\t\t\t\t\treturn textAccumulator.getFullText();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase \"session.error\": {\n\t\t\t\t\t\tif (parsed.props.sessionID === sessionId) {\n\t\t\t\t\t\t\tconst errorName = parsed.error?.name ?? \"Unknown session error\";\n\t\t\t\t\t\t\tdebug(`Session error: ${JSON.stringify(parsed.props.error)}`);\n\t\t\t\t\t\t\tthrow new SessionError(errorName, sessionId, \"error\", parsed.props.error);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase \"unknown\":\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn textAccumulator.getFullText();\n\t\t};\n\n\t\tlet responseText: string;\n\t\tif (timeoutMs && timeoutMs > 0) {\n\t\t\tconst timeoutPromise = new Promise<never>((_, reject) => {\n\t\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\t\treject(new TimeoutError(timeoutMs, \"session response\"));\n\t\t\t\t}, timeoutMs);\n\t\t\t});\n\t\t\tresponseText = await Promise.race([processEvents(), timeoutPromise]);\n\t\t\tif (timeoutId) clearTimeout(timeoutId);\n\t\t} else {\n\t\t\tresponseText = await processEvents();\n\t\t}\n\n\t\tawait promptPromise;\n\n\t\tif (!responseText) {\n\t\t\tthrow new OpenCodeReferenceError(\"No response received from OpenCode\");\n\t\t}\n\n\t\tdebug(`Response received (${responseText.length} chars)`);\n\n\t\tconst durationMs = Date.now() - startTime;\n\t\tdebug(`Complete in ${durationMs}ms`);\n\n\t\treturn {\n\t\t\ttext: responseText,\n\t\t\tsessionId,\n\t\t\tdurationMs,\n\t\t};\n\t} finally {\n\t\tdebug(\"Closing server...\");\n\t\tserver.close();\n\t}\n}\n","/**\n * Sync utilities for CLI-Convex communication\n * Uses ConvexHttpClient for direct type-safe API calls\n */\n\nimport { ConvexHttpClient } from \"convex/browser\";\nimport { api } from \"@offworld/backend-api/api\";\nimport { toReferenceName } from \"./config.js\";\nimport { GitHubRepoMetadataSchema, type RepoSource } from \"@offworld/types\";\n\nfunction getConvexUrl(): string {\n\treturn process.env.CONVEX_URL || \"\";\n}\n\nconst GITHUB_API_BASE = \"https://api.github.com\";\n\nexport class SyncError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"SyncError\";\n\t}\n}\n\nexport class NetworkError extends SyncError {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly statusCode?: number,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"NetworkError\";\n\t}\n}\n\nexport class AuthenticationError extends SyncError {\n\tconstructor(message = \"Authentication required. Please run 'ow auth login' first.\") {\n\t\tsuper(message);\n\t\tthis.name = \"AuthenticationError\";\n\t}\n}\n\nexport class RateLimitError extends SyncError {\n\tconstructor(message = \"Rate limit exceeded. You can push up to 3 times per repo per day.\") {\n\t\tsuper(message);\n\t\tthis.name = \"RateLimitError\";\n\t}\n}\n\nexport class ConflictError extends SyncError {\n\tconstructor(\n\t\tmessage = \"A newer reference already exists on the server.\",\n\t\tpublic readonly remoteCommitSha?: string,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"ConflictError\";\n\t}\n}\n\nexport class CommitExistsError extends SyncError {\n\tconstructor(message = \"A reference already exists for this commit SHA.\") {\n\t\tsuper(message);\n\t\tthis.name = \"CommitExistsError\";\n\t}\n}\n\nexport class InvalidInputError extends SyncError {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"InvalidInputError\";\n\t}\n}\n\nexport class InvalidReferenceError extends SyncError {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"InvalidReferenceError\";\n\t}\n}\n\nexport class RepoNotFoundError extends SyncError {\n\tconstructor(message = \"Repository not found on GitHub.\") {\n\t\tsuper(message);\n\t\tthis.name = \"RepoNotFoundError\";\n\t}\n}\n\nexport class LowStarsError extends SyncError {\n\tconstructor(message = \"Repository has less than 5 stars.\") {\n\t\tsuper(message);\n\t\tthis.name = \"LowStarsError\";\n\t}\n}\n\nexport class PrivateRepoError extends SyncError {\n\tconstructor(message = \"Private repositories are not supported.\") {\n\t\tsuper(message);\n\t\tthis.name = \"PrivateRepoError\";\n\t}\n}\n\nexport class CommitNotFoundError extends SyncError {\n\tconstructor(message = \"Commit not found in repository.\") {\n\t\tsuper(message);\n\t\tthis.name = \"CommitNotFoundError\";\n\t}\n}\n\nexport class GitHubError extends SyncError {\n\tconstructor(message = \"GitHub API error.\") {\n\t\tsuper(message);\n\t\tthis.name = \"GitHubError\";\n\t}\n}\n\nexport class PushNotAllowedError extends SyncError {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly reason: \"local\" | \"not-github\",\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"PushNotAllowedError\";\n\t}\n}\n\n/** Reference data structure for sync operations */\nexport interface ReferenceData {\n\tfullName: string;\n\treferenceName: string;\n\treferenceDescription: string;\n\treferenceContent: string;\n\tcommitSha: string;\n\tgeneratedAt: string;\n}\n\n/** Response from pull query */\nexport interface PullResponse {\n\tfullName: string;\n\treferenceName: string;\n\treferenceDescription: string;\n\treferenceContent: string;\n\tcommitSha: string;\n\tgeneratedAt: string;\n}\n\n/** Response from check query */\nexport interface CheckResponse {\n\texists: boolean;\n\tcommitSha?: string;\n\tgeneratedAt?: string;\n}\n\n/** Response from push mutation */\nexport interface PushResponse {\n\tsuccess: boolean;\n\tmessage?: string;\n}\n\n/** Staleness check result */\nexport interface StalenessResult {\n\tisStale: boolean;\n\tlocalCommitSha?: string;\n\tremoteCommitSha?: string;\n}\n\n/** Can push result */\nexport interface CanPushResult {\n\tallowed: boolean;\n\treason?: string;\n\tstars?: number;\n}\n\nfunction createClient(token?: string): ConvexHttpClient {\n\tconst convexUrl = getConvexUrl();\n\tif (!convexUrl) {\n\t\tthrow new SyncError(\n\t\t\t\"CONVEX_URL not configured. \" +\n\t\t\t\t\"For local development, ensure apps/cli/.env contains CONVEX_URL=your_convex_url\",\n\t\t);\n\t}\n\tconst client = new ConvexHttpClient(convexUrl);\n\tif (token) client.setAuth(token);\n\treturn client;\n}\n\n/**\n * Fetches reference from the remote server\n * @param fullName - Repository full name (owner/repo)\n * @returns Reference data or null if not found\n */\nexport async function pullReference(fullName: string): Promise<PullResponse | null> {\n\tconst client = createClient();\n\ttry {\n\t\tlet result = await client.query(api.references.pull, {\n\t\t\tfullName,\n\t\t\treferenceName: toReferenceName(fullName),\n\t\t});\n\t\tif (!result) {\n\t\t\tresult = await client.query(api.references.pull, { fullName });\n\t\t}\n\t\tif (!result) return null;\n\n\t\tclient\n\t\t\t.mutation(api.references.recordPull, { fullName, referenceName: result.referenceName })\n\t\t\t.catch(() => {});\n\n\t\treturn {\n\t\t\tfullName: result.fullName,\n\t\t\treferenceName: result.referenceName,\n\t\t\treferenceDescription: result.referenceDescription,\n\t\t\treferenceContent: result.referenceContent,\n\t\t\tcommitSha: result.commitSha,\n\t\t\tgeneratedAt: result.generatedAt,\n\t\t};\n\t} catch (error) {\n\t\tthrow new NetworkError(\n\t\t\t`Failed to pull reference: ${error instanceof Error ? error.message : error}`,\n\t\t);\n\t}\n}\n\n/**\n * Fetches a specific reference by name from the remote server\n * @param fullName - Repository full name (owner/repo)\n * @param referenceName - Specific reference name to pull\n * @returns Reference data or null if not found\n */\nexport async function pullReferenceByName(\n\tfullName: string,\n\treferenceName: string,\n): Promise<PullResponse | null> {\n\tconst client = createClient();\n\ttry {\n\t\tconst result = await client.query(api.references.pull, { fullName, referenceName });\n\t\tif (!result) return null;\n\n\t\tclient.mutation(api.references.recordPull, { fullName, referenceName }).catch(() => {});\n\n\t\treturn {\n\t\t\tfullName: result.fullName,\n\t\t\treferenceName: result.referenceName,\n\t\t\treferenceDescription: result.referenceDescription,\n\t\t\treferenceContent: result.referenceContent,\n\t\t\tcommitSha: result.commitSha,\n\t\t\tgeneratedAt: result.generatedAt,\n\t\t};\n\t} catch (error) {\n\t\tthrow new NetworkError(\n\t\t\t`Failed to pull reference: ${error instanceof Error ? error.message : error}`,\n\t\t);\n\t}\n}\n\n/**\n * Pushes reference to the remote server\n * All validation happens server-side\n * @param reference - Reference data to push\n * @param token - Authentication token\n * @returns Push result\n */\nexport async function pushReference(\n\treference: ReferenceData,\n\ttoken: string,\n): Promise<PushResponse> {\n\tconst client = createClient(token);\n\ttry {\n\t\tconst result = await client.action(api.references.push, {\n\t\t\tfullName: reference.fullName,\n\t\t\treferenceName: reference.referenceName,\n\t\t\treferenceDescription: reference.referenceDescription,\n\t\t\treferenceContent: reference.referenceContent,\n\t\t\tcommitSha: reference.commitSha,\n\t\t\tgeneratedAt: reference.generatedAt,\n\t\t});\n\n\t\tif (!result.success) {\n\t\t\tswitch (result.error) {\n\t\t\t\tcase \"auth_required\":\n\t\t\t\t\tthrow new AuthenticationError();\n\t\t\t\tcase \"rate_limit\":\n\t\t\t\t\tthrow new RateLimitError(\"Rate limit exceeded. You can push up to 20 times per day.\");\n\t\t\t\tcase \"commit_already_exists\":\n\t\t\t\t\tthrow new CommitExistsError(result.message);\n\t\t\t\tcase \"invalid_input\":\n\t\t\t\t\tthrow new InvalidInputError(result.message ?? \"Invalid input\");\n\t\t\t\tcase \"invalid_reference\":\n\t\t\t\t\tthrow new InvalidReferenceError(result.message ?? \"Invalid reference content\");\n\t\t\t\tcase \"repo_not_found\":\n\t\t\t\t\tthrow new RepoNotFoundError(result.message);\n\t\t\t\tcase \"low_stars\":\n\t\t\t\t\tthrow new LowStarsError(result.message);\n\t\t\t\tcase \"private_repo\":\n\t\t\t\t\tthrow new PrivateRepoError(result.message);\n\t\t\t\tcase \"commit_not_found\":\n\t\t\t\t\tthrow new CommitNotFoundError(result.message);\n\t\t\t\tcase \"github_error\":\n\t\t\t\t\tthrow new GitHubError(result.message);\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new SyncError(result.message ?? \"Unknown error\");\n\t\t\t}\n\t\t}\n\n\t\treturn { success: true };\n\t} catch (error) {\n\t\tif (error instanceof SyncError) throw error;\n\t\tthrow new NetworkError(\n\t\t\t`Failed to push reference: ${error instanceof Error ? error.message : error}`,\n\t\t);\n\t}\n}\n\n/**\n * Checks if reference exists on remote server (lightweight check)\n * @param fullName - Repository full name (owner/repo)\n * @returns Check result\n */\nexport async function checkRemote(fullName: string): Promise<CheckResponse> {\n\tconst client = createClient();\n\ttry {\n\t\tlet result = await client.query(api.references.check, {\n\t\t\tfullName,\n\t\t\treferenceName: toReferenceName(fullName),\n\t\t});\n\t\tif (!result.exists) {\n\t\t\tresult = await client.query(api.references.check, { fullName });\n\t\t}\n\t\tif (!result.exists) {\n\t\t\treturn { exists: false };\n\t\t}\n\t\treturn {\n\t\t\texists: true,\n\t\t\tcommitSha: result.commitSha,\n\t\t\tgeneratedAt: result.generatedAt,\n\t\t};\n\t} catch (error) {\n\t\tthrow new NetworkError(\n\t\t\t`Failed to check remote: ${error instanceof Error ? error.message : error}`,\n\t\t);\n\t}\n}\n\n/**\n * Checks if a specific reference exists on the remote server\n * @param fullName - Repository full name (owner/repo)\n * @param referenceName - Specific reference name to check\n * @returns Check result\n */\nexport async function checkRemoteByName(\n\tfullName: string,\n\treferenceName: string,\n): Promise<CheckResponse> {\n\tconst client = createClient();\n\ttry {\n\t\tconst result = await client.query(api.references.check, { fullName, referenceName });\n\t\tif (!result.exists) {\n\t\t\treturn { exists: false };\n\t\t}\n\t\treturn {\n\t\t\texists: true,\n\t\t\tcommitSha: result.commitSha,\n\t\t\tgeneratedAt: result.generatedAt,\n\t\t};\n\t} catch (error) {\n\t\tthrow new NetworkError(\n\t\t\t`Failed to check remote: ${error instanceof Error ? error.message : error}`,\n\t\t);\n\t}\n}\n\n/**\n * Compares local vs remote commit SHA to check staleness\n * @param fullName - Repository full name (owner/repo)\n * @param localCommitSha - Local commit SHA\n * @returns Staleness result\n */\nexport async function checkStaleness(\n\tfullName: string,\n\tlocalCommitSha: string,\n): Promise<StalenessResult> {\n\tconst remote = await checkRemote(fullName);\n\n\tif (!remote.exists || !remote.commitSha) {\n\t\treturn {\n\t\t\tisStale: false,\n\t\t\tlocalCommitSha,\n\t\t\tremoteCommitSha: undefined,\n\t\t};\n\t}\n\n\treturn {\n\t\tisStale: localCommitSha !== remote.commitSha,\n\t\tlocalCommitSha,\n\t\tremoteCommitSha: remote.commitSha,\n\t};\n}\n\n/** GitHub repository metadata */\nexport interface GitHubRepoMetadata {\n\tstars: number;\n\tdescription?: string;\n\tlanguage?: string;\n\tdefaultBranch: string;\n}\n\n/**\n * Fetches GitHub repository metadata\n * @param owner - Repository owner\n * @param repo - Repository name\n * @returns Repository metadata or null on error\n */\nexport async function fetchGitHubMetadata(\n\towner: string,\n\trepo: string,\n): Promise<GitHubRepoMetadata | null> {\n\ttry {\n\t\tconst response = await fetch(`${GITHUB_API_BASE}/repos/${owner}/${repo}`, {\n\t\t\theaders: {\n\t\t\t\tAccept: \"application/vnd.github.v3+json\",\n\t\t\t\t\"User-Agent\": \"offworld-cli\",\n\t\t\t},\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst json = await response.json();\n\t\tconst result = GitHubRepoMetadataSchema.safeParse(json);\n\t\tif (!result.success) {\n\t\t\treturn null;\n\t\t}\n\t\tconst data = result.data;\n\n\t\treturn {\n\t\t\tstars: data.stargazers_count ?? 0,\n\t\t\tdescription: data.description ?? undefined,\n\t\t\tlanguage: data.language ?? undefined,\n\t\t\tdefaultBranch: data.default_branch ?? \"main\",\n\t\t};\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Fetches GitHub repository stars\n * @param owner - Repository owner\n * @param repo - Repository name\n * @returns Number of stars, or 0 on error\n */\nexport async function fetchRepoStars(owner: string, repo: string): Promise<number> {\n\tconst metadata = await fetchGitHubMetadata(owner, repo);\n\treturn metadata?.stars ?? 0;\n}\n\n/**\n * Checks if a repository can be pushed to offworld.sh (client-side quick checks)\n * Note: Star count and other validations happen server-side\n *\n * @param source - Repository source\n * @returns Can push result\n */\nexport function canPushToWeb(source: RepoSource): CanPushResult {\n\tif (source.type === \"local\") {\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\treason:\n\t\t\t\t\"Local repositories cannot be pushed to offworld.sh. \" +\n\t\t\t\t\"Only remote repositories with a public URL are supported.\",\n\t\t};\n\t}\n\n\tif (source.provider !== \"github\") {\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\treason:\n\t\t\t\t`${source.provider} repositories are not yet supported. ` +\n\t\t\t\t\"GitHub support only for now - GitLab and Bitbucket coming soon!\",\n\t\t};\n\t}\n\n\treturn {\n\t\tallowed: true,\n\t};\n}\n\n/**\n * Validates that a source can be pushed and throws appropriate error if not\n * Note: This only does quick client-side checks. Full validation happens server-side.\n * @param source - Repository source\n * @throws PushNotAllowedError if push is not allowed\n */\nexport function validatePushAllowed(source: RepoSource): void {\n\tconst result = canPushToWeb(source);\n\n\tif (!result.allowed) {\n\t\tconst reason: \"local\" | \"not-github\" = source.type === \"local\" ? \"local\" : \"not-github\";\n\n\t\tthrow new PushNotAllowedError(result.reason!, reason);\n\t}\n}\n","/**\n * Authentication utilities for offworld CLI\n */\n\nimport { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { z } from \"zod\";\nimport { WorkOSTokenResponseSchema } from \"@offworld/types\";\nimport { Paths } from \"./paths\";\n\nconst AuthDataSchema = z.object({\n\ttoken: z.string(),\n\texpiresAt: z.string().optional(),\n\tworkosId: z.string().optional(),\n\trefreshToken: z.string().optional(),\n\temail: z.string().optional(),\n});\n\nexport interface AuthData {\n\ttoken: string;\n\texpiresAt?: string;\n\tworkosId?: string;\n\trefreshToken?: string;\n\temail?: string;\n}\n\n/** Authentication status */\nexport interface AuthStatus {\n\tisLoggedIn: boolean;\n\temail?: string;\n\tworkosId?: string;\n\texpiresAt?: string;\n}\n\nexport class AuthError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"AuthError\";\n\t}\n}\n\nexport class NotLoggedInError extends AuthError {\n\tconstructor(message = \"Not logged in. Please run 'ow auth login' first.\") {\n\t\tsuper(message);\n\t\tthis.name = \"NotLoggedInError\";\n\t}\n}\n\nexport class TokenExpiredError extends AuthError {\n\tconstructor(message = \"Session expired. Please run 'ow auth login' again.\") {\n\t\tsuper(message);\n\t\tthis.name = \"TokenExpiredError\";\n\t}\n}\n\nfunction extractJwtExpiration(token: string): string | undefined {\n\ttry {\n\t\tconst parts = token.split(\".\");\n\t\tif (parts.length !== 3) return undefined;\n\n\t\tconst payload = parts[1];\n\t\tif (!payload) return undefined;\n\n\t\tconst decoded = JSON.parse(Buffer.from(payload, \"base64\").toString(\"utf-8\"));\n\t\tif (typeof decoded.exp !== \"number\") return undefined;\n\n\t\treturn new Date(decoded.exp * 1000).toISOString();\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function getAuthPath(): string {\n\treturn Paths.authFile;\n}\n\nexport function saveAuthData(data: AuthData): void {\n\tconst authPath = getAuthPath();\n\tconst authDir = dirname(authPath);\n\n\tif (!existsSync(authDir)) {\n\t\tmkdirSync(authDir, { recursive: true });\n\t}\n\n\twriteFileSync(authPath, JSON.stringify(data, null, 2), \"utf-8\");\n\tchmodSync(authPath, 0o600);\n}\n\n/**\n * Loads authentication data from ~/.local/share/offworld/auth.json\n * Returns null if file doesn't exist or is invalid\n */\nexport function loadAuthData(): AuthData | null {\n\tconst authPath = getAuthPath();\n\n\tif (!existsSync(authPath)) {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\tconst content = readFileSync(authPath, \"utf-8\");\n\t\tconst json = JSON.parse(content);\n\t\tconst parsed = AuthDataSchema.safeParse(json);\n\n\t\tif (!parsed.success) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn parsed.data;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Clears stored authentication data\n * @returns true if auth file was deleted, false if it didn't exist\n */\nexport function clearAuthData(): boolean {\n\tconst authPath = getAuthPath();\n\n\tif (!existsSync(authPath)) {\n\t\treturn false;\n\t}\n\n\ttry {\n\t\tunlinkSync(authPath);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nexport async function getToken(): Promise<string> {\n\tconst data = loadAuthData();\n\n\tif (!data) {\n\t\tthrow new NotLoggedInError();\n\t}\n\n\tlet expiresAtStr = data.expiresAt;\n\tif (!expiresAtStr) {\n\t\texpiresAtStr = extractJwtExpiration(data.token);\n\t\tif (expiresAtStr) {\n\t\t\tdata.expiresAt = expiresAtStr;\n\t\t\tsaveAuthData(data);\n\t\t}\n\t}\n\n\tif (expiresAtStr) {\n\t\tconst expiresAt = new Date(expiresAtStr);\n\t\tconst now = new Date();\n\t\tconst oneMinute = 60 * 1000;\n\n\t\tif (expiresAt <= now) {\n\t\t\tif (data.refreshToken) {\n\t\t\t\ttry {\n\t\t\t\t\tconst refreshed = await refreshAccessToken();\n\t\t\t\t\treturn refreshed.token;\n\t\t\t\t} catch {\n\t\t\t\t\tthrow new TokenExpiredError();\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new TokenExpiredError();\n\t\t}\n\n\t\tif (expiresAt.getTime() - now.getTime() < oneMinute) {\n\t\t\tif (data.refreshToken) {\n\t\t\t\ttry {\n\t\t\t\t\tconst refreshed = await refreshAccessToken();\n\t\t\t\t\treturn refreshed.token;\n\t\t\t\t} catch {\n\t\t\t\t\treturn data.token;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn data.token;\n}\n\n/**\n * Gets the current authentication token, or null if not logged in\n * Does not throw errors\n */\nexport async function getTokenOrNull(): Promise<string | null> {\n\ttry {\n\t\treturn await getToken();\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport async function isLoggedIn(): Promise<boolean> {\n\treturn (await getTokenOrNull()) !== null;\n}\n\nexport async function getAuthStatus(): Promise<AuthStatus> {\n\tconst data = loadAuthData();\n\n\tif (!data) {\n\t\treturn { isLoggedIn: false };\n\t}\n\n\tif (data.expiresAt) {\n\t\tconst expiresAt = new Date(data.expiresAt);\n\t\tif (expiresAt <= new Date()) {\n\t\t\tif (data.refreshToken) {\n\t\t\t\ttry {\n\t\t\t\t\tconst refreshed = await refreshAccessToken();\n\t\t\t\t\treturn {\n\t\t\t\t\t\tisLoggedIn: true,\n\t\t\t\t\t\temail: refreshed.email,\n\t\t\t\t\t\tworkosId: refreshed.workosId,\n\t\t\t\t\t\texpiresAt: refreshed.expiresAt,\n\t\t\t\t\t};\n\t\t\t\t} catch {\n\t\t\t\t\treturn { isLoggedIn: false };\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { isLoggedIn: false };\n\t\t}\n\t}\n\n\treturn {\n\t\tisLoggedIn: true,\n\t\temail: data.email,\n\t\tworkosId: data.workosId,\n\t\texpiresAt: data.expiresAt,\n\t};\n}\n\nconst WORKOS_API = \"https://api.workos.com\";\n\nfunction getWorkosClientId(): string {\n\treturn process.env.WORKOS_CLIENT_ID || \"\";\n}\n\nexport async function refreshAccessToken(): Promise<AuthData> {\n\tconst data = loadAuthData();\n\n\tif (!data?.refreshToken) {\n\t\tthrow new AuthError(\"No refresh token available. Please log in again.\");\n\t}\n\n\tconst clientId = getWorkosClientId();\n\tif (!clientId) {\n\t\tthrow new AuthError(\"WORKOS_CLIENT_ID not configured\");\n\t}\n\n\ttry {\n\t\tconst response = await fetch(`${WORKOS_API}/user_management/authenticate`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n\t\t\tbody: new URLSearchParams({\n\t\t\t\tgrant_type: \"refresh_token\",\n\t\t\t\trefresh_token: data.refreshToken,\n\t\t\t\tclient_id: clientId,\n\t\t\t}),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response.text();\n\t\t\tthrow new AuthError(`Token refresh failed: ${error}`);\n\t\t}\n\n\t\tconst json = await response.json();\n\t\tconst tokenData = WorkOSTokenResponseSchema.parse(json);\n\n\t\tconst newAuthData: AuthData = {\n\t\t\ttoken: tokenData.access_token,\n\t\t\temail: tokenData.user.email,\n\t\t\tworkosId: tokenData.user.id,\n\t\t\trefreshToken: tokenData.refresh_token,\n\t\t\texpiresAt: tokenData.expires_at\n\t\t\t\t? new Date(tokenData.expires_at * 1000).toISOString()\n\t\t\t\t: extractJwtExpiration(tokenData.access_token),\n\t\t};\n\n\t\tsaveAuthData(newAuthData);\n\t\treturn newAuthData;\n\t} catch (error) {\n\t\tif (error instanceof AuthError) throw error;\n\t\tthrow new AuthError(\n\t\t\t`Failed to refresh token: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n\t\t);\n\t}\n}\n","/**\n * Agent Registry & Auto-Detection\n *\n * Centralized registry of supported AI coding agents with their\n * skill directory locations and detection functions.\n */\n\nimport { existsSync } from \"node:fs\";\nimport type { Agent } from \"@offworld/types\";\nimport { expandTilde } from \"./paths\";\n\nexport interface AgentConfig {\n\t/** Agent identifier (matches AgentSchema enum) */\n\tname: Agent;\n\t/** Human-readable name for display */\n\tdisplayName: string;\n\t/** Project-level skill directory (relative path) */\n\tskillsDir: string;\n\t/** User-level skill directory (absolute with ~) */\n\tglobalSkillsDir: string;\n\t/** Check if this agent is installed on the system */\n\tdetectInstalled: () => boolean;\n}\n\nexport const agents: Record<Agent, AgentConfig> = {\n\topencode: {\n\t\tname: \"opencode\",\n\t\tdisplayName: \"OpenCode\",\n\t\tskillsDir: \".opencode/skills\",\n\t\tglobalSkillsDir: \"~/.config/opencode/skills\",\n\t\tdetectInstalled: () => existsSync(expandTilde(\"~/.config/opencode\")),\n\t},\n\t\"claude-code\": {\n\t\tname: \"claude-code\",\n\t\tdisplayName: \"Claude Code\",\n\t\tskillsDir: \".claude/skills\",\n\t\tglobalSkillsDir: \"~/.claude/skills\",\n\t\tdetectInstalled: () => existsSync(expandTilde(\"~/.claude\")),\n\t},\n\tcodex: {\n\t\tname: \"codex\",\n\t\tdisplayName: \"Codex (OpenAI)\",\n\t\tskillsDir: \".codex/skills\",\n\t\tglobalSkillsDir: \"~/.codex/skills\",\n\t\tdetectInstalled: () => existsSync(expandTilde(\"~/.codex\")),\n\t},\n\tamp: {\n\t\tname: \"amp\",\n\t\tdisplayName: \"Amp\",\n\t\tskillsDir: \".agents/skills\",\n\t\tglobalSkillsDir: \"~/.config/agents/skills\",\n\t\tdetectInstalled: () => existsSync(expandTilde(\"~/.config/amp\")),\n\t},\n\tantigravity: {\n\t\tname: \"antigravity\",\n\t\tdisplayName: \"Antigravity\",\n\t\tskillsDir: \".agent/skills\",\n\t\tglobalSkillsDir: \"~/.gemini/antigravity/skills\",\n\t\tdetectInstalled: () => existsSync(expandTilde(\"~/.gemini/antigravity\")),\n\t},\n\tcursor: {\n\t\tname: \"cursor\",\n\t\tdisplayName: \"Cursor\",\n\t\tskillsDir: \".cursor/skills\",\n\t\tglobalSkillsDir: \"~/.cursor/skills\",\n\t\tdetectInstalled: () => existsSync(expandTilde(\"~/.cursor\")),\n\t},\n};\n\n/**\n * Detect which agents are installed on the system.\n * Checks for the existence of each agent's config directory.\n *\n * @returns Array of installed agent identifiers\n */\nexport function detectInstalledAgents(): Agent[] {\n\tconst installed: Agent[] = [];\n\n\tfor (const config of Object.values(agents)) {\n\t\tif (config.detectInstalled()) {\n\t\t\tinstalled.push(config.name);\n\t\t}\n\t}\n\n\treturn installed;\n}\n\n/**\n * Get the configuration for a specific agent.\n *\n * @param type - Agent identifier\n * @returns AgentConfig for the specified agent\n */\nexport function getAgentConfig(type: Agent): AgentConfig {\n\treturn agents[type];\n}\n\n/**\n * Get all agent configurations as an array.\n *\n * @returns Array of all agent configurations\n */\nexport function getAllAgentConfigs(): AgentConfig[] {\n\treturn Object.values(agents);\n}\n","/**\n * This module provides a streamlined approach to generating reference files\n * by delegating all codebase exploration to the AI agent via OpenCode.\n */\n\nimport {\n\tmkdirSync,\n\twriteFileSync,\n\treadFileSync,\n\tlstatSync,\n\tunlinkSync,\n\trmSync,\n\tsymlinkSync,\n\texistsSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\nimport { z } from \"zod\";\nimport { streamPrompt, type StreamPromptOptions } from \"./ai/opencode.js\";\nimport { loadConfig, toReferenceName, toMetaDirName, toReferenceFileName } from \"./config.js\";\nimport { getCommitSha } from \"./clone.js\";\nimport { agents } from \"./agents.js\";\nimport { expandTilde, Paths } from \"./paths.js\";\nimport { readGlobalMap, writeGlobalMap } from \"./index-manager.js\";\n\nconst PackageJsonKeywordsSchema = z.object({\n\tname: z.string().optional(),\n\tkeywords: z.array(z.string()).optional(),\n});\n\nexport interface GenerateReferenceOptions {\n\t/** AI provider ID (e.g., \"anthropic\", \"openai\"). Defaults to config value. */\n\tprovider?: string;\n\t/** AI model ID. Defaults to config value. */\n\tmodel?: string;\n\t/** Debug callback for detailed logging */\n\tonDebug?: (message: string) => void;\n\t/** Stream callback for real-time AI output */\n\tonStream?: (text: string) => void;\n}\n\nexport interface GenerateReferenceResult {\n\t/** The generated reference markdown content */\n\treferenceContent: string;\n\t/** The commit SHA at the time of generation */\n\tcommitSha: string;\n}\n\nexport interface InstallReferenceMeta {\n\t/** ISO timestamp when the reference was generated */\n\treferenceUpdatedAt: string;\n\t/** Git commit SHA at time of generation */\n\tcommitSha: string;\n\t/** SDK version used for generation */\n\tversion: string;\n}\n\nfunction normalizeKeyword(value: string): string[] {\n\tconst trimmed = value.trim();\n\tif (!trimmed) return [];\n\tconst normalized = trimmed.toLowerCase();\n\tconst tokens = new Set<string>();\n\n\tconst addToken = (token: string): void => {\n\t\tconst cleaned = token.trim().toLowerCase();\n\t\tif (cleaned.length < 2) return;\n\t\ttokens.add(cleaned);\n\t};\n\n\taddToken(normalized);\n\taddToken(normalized.replaceAll(\"/\", \"-\"));\n\taddToken(normalized.replaceAll(\"/\", \"\"));\n\n\tfor (const token of normalized.split(/[\\s/_-]+/)) {\n\t\taddToken(token);\n\t}\n\n\tif (normalized.startsWith(\"@\")) {\n\t\taddToken(normalized.slice(1));\n\t}\n\n\treturn Array.from(tokens);\n}\n\nfunction deriveKeywords(fullName: string, localPath: string, referenceContent: string): string[] {\n\tconst keywords = new Set<string>();\n\n\tconst addKeywords = (value: string): void => {\n\t\tfor (const token of normalizeKeyword(value)) {\n\t\t\tkeywords.add(token);\n\t\t}\n\t};\n\n\taddKeywords(fullName);\n\n\tconst headingMatch = referenceContent.match(/^#\\s+(.+)$/m);\n\tif (headingMatch?.[1]) {\n\t\taddKeywords(headingMatch[1]);\n\t}\n\n\tconst packageJsonPath = join(localPath, \"package.json\");\n\tif (existsSync(packageJsonPath)) {\n\t\ttry {\n\t\t\tconst content = readFileSync(packageJsonPath, \"utf-8\");\n\t\t\tconst json = JSON.parse(content);\n\t\t\tconst parsed = PackageJsonKeywordsSchema.safeParse(json);\n\n\t\t\tif (parsed.success) {\n\t\t\t\tif (parsed.data.name) {\n\t\t\t\t\taddKeywords(parsed.data.name);\n\t\t\t\t}\n\n\t\t\t\tif (parsed.data.keywords) {\n\t\t\t\t\tfor (const keyword of parsed.data.keywords) {\n\t\t\t\t\t\taddKeywords(keyword);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {}\n\t}\n\n\treturn Array.from(keywords);\n}\n\nfunction createReferenceGenerationPrompt(referenceName: string): string {\n\treturn `You are an expert at analyzing open source libraries and producing reference documentation for AI coding agents.\n\n## PRIMARY GOAL\n\nGenerate a reference markdown file that helps developers USE this library effectively. This is NOT a contribution guide - it's a usage reference for developers consuming this library in their own projects.\n\n## CRITICAL RULES\n\n1. **USER PERSPECTIVE ONLY**: Write for developers who will npm/pip/cargo install this library and use it in THEIR code.\n - DO NOT include: how to contribute, internal test commands, repo-specific policies\n - DO NOT include: \"never mock in tests\" or similar internal dev guidelines\n - DO NOT include: commands like \"npx hereby\", \"just ready\", \"bun test\" that run the library's own tests\n - DO include: how to install, import, configure, and use the public API\n\n2. **NO FRONTMATTER**: Output pure markdown with NO YAML frontmatter. Start directly with the library name heading.\n\n3. **QUICK REFERENCES**: Include a \"Quick References\" section with paths to key entry points in the repo:\n - Paths must be relative from repo root (e.g., \\`src/index.ts\\`, \\`docs/api.md\\`)\n - Include: main entry point, type definitions, README, key docs\n - DO NOT include absolute paths or user-specific paths\n - Keep to 3-5 most important files that help users understand the library\n\n4. **PUBLIC API FOCUS**: Document what users import and call, not internal implementation details.\n - Entry points: what to import from the package\n - Configuration: how to set up/initialize\n - Core methods/functions: the main API surface\n - Types: key TypeScript interfaces users need\n\n5. **MONOREPO AWARENESS**: Many libraries are monorepos with multiple packages:\n - Check for \\`packages/\\`, \\`apps/\\`, \\`crates/\\`, or \\`libs/\\` directories\n - Check root package.json for \\`workspaces\\` field\n - If monorepo: document the package structure and key packages users would install\n - Use full paths from repo root (e.g., \\`packages/core/src/index.ts\\`)\n - Identify which packages are publishable vs internal\n\n## EXPLORATION STEPS\n\nUse Read, Grep, Glob tools to explore:\n1. Root package.json / Cargo.toml - check for workspaces/monorepo config\n2. Check for \\`packages/\\`, \\`apps/\\`, \\`crates/\\` directories\n3. README.md - official usage documentation\n4. For monorepos: explore each publishable package's entry point\n5. docs/ or website/ - find documentation\n6. examples/ - real usage patterns\n7. TypeScript definitions (.d.ts) - public API surface\n\n## OUTPUT FORMAT\n\nIMPORTANT: Reference name is \"${referenceName}\" (for internal tracking only - do NOT include in output).\n\n\\`\\`\\`markdown\n# {Library Name}\n\n{2-3 sentence overview of what this library does and its key value proposition}\n\n## Quick References\n\n| File | Purpose |\n|------|---------|\n| \\`packages/{pkg}/src/index.ts\\` | Main entry point (monorepo example) |\n| \\`src/index.ts\\` | Main entry point (single-package example) |\n| \\`README.md\\` | Documentation |\n\n(For monorepos, include paths to key publishable packages)\n\n## Packages (for monorepos only)\n\n| Package | npm name | Description |\n|---------|----------|-------------|\n| \\`packages/core\\` | \\`@scope/core\\` | Core functionality |\n| \\`packages/react\\` | \\`@scope/react\\` | React bindings |\n\n(OMIT this section for single-package repos)\n\n## When to Use\n\n- {Practical scenario where a developer would reach for this library}\n- {Another real-world use case}\n- {Problem this library solves}\n\n## Installation\n\n\\`\\`\\`bash\n# Single package\nnpm install {package-name}\n\n# Monorepo (show key packages)\nnpm install @scope/core @scope/react\n\\`\\`\\`\n\n## Best Practices\n\n1. {Actionable best practice for USERS of this library}\n2. {Common mistake to avoid when using this library}\n3. {Performance or correctness tip}\n\n## Common Patterns\n\n**{Pattern Name}:**\n\\`\\`\\`{language}\n{Minimal working code example}\n\\`\\`\\`\n\n**{Another Pattern}:**\n\\`\\`\\`{language}\n{Another code example}\n\\`\\`\\`\n\n## API Quick Reference\n\n| Export | Type | Description |\n|--------|------|-------------|\n| \\`{main export}\\` | {type} | {what it does} |\n| \\`{another export}\\` | {type} | {what it does} |\n\n{Add more sections as appropriate for the library: Configuration, Types, CLI Commands (if user-facing), etc.}\n\\`\\`\\`\n\n## QUALITY CHECKLIST\n\nBefore outputting, verify:\n- [ ] NO YAML frontmatter - start directly with # heading\n- [ ] Every code example is something a USER would write, not a contributor\n- [ ] No internal test commands or contribution workflows\n- [ ] Quick References paths are relative from repo root (no absolute/user paths)\n- [ ] Best practices are for using the library, not developing it\n- [ ] If monorepo: Packages section lists publishable packages with npm names\n- [ ] If monorepo: paths include package directory (e.g., \\`packages/core/src/index.ts\\`)\n\nNow explore the codebase and generate the reference content.\n\nCRITICAL: Wrap your final reference output in XML tags exactly like this:\n<reference_output>\n# {Library Name}\n(the complete markdown content with NO frontmatter)\n</reference_output>\n\nOutput ONLY the reference content inside the tags. No explanations before or after the tags.`;\n}\n\n/**\n * Extract the actual reference markdown content from AI response.\n * The response may include echoed prompt/system context before the actual reference.\n * We look for the LAST occurrence of XML tags: <reference_output>...</reference_output>\n * (Using last occurrence avoids extracting example tags from echoed prompt)\n */\nfunction extractReferenceContent(rawResponse: string): string {\n\tconst openTag = \"<reference_output>\";\n\tconst closeTag = \"</reference_output>\";\n\tconst closeIndex = rawResponse.lastIndexOf(closeTag);\n\n\tif (closeIndex !== -1) {\n\t\tconst openIndex = rawResponse.lastIndexOf(openTag, closeIndex);\n\n\t\tif (openIndex !== -1) {\n\t\t\tlet content = rawResponse.slice(openIndex + openTag.length, closeIndex).trim();\n\n\t\t\tif (content.startsWith(\"```\")) {\n\t\t\t\tcontent = content.replace(/^```(?:markdown)?\\s*\\n?/, \"\");\n\t\t\t\tcontent = content.replace(/\\n?```\\s*$/, \"\");\n\t\t\t}\n\n\t\t\tcontent = content.trim();\n\t\t\tvalidateReferenceContent(content);\n\t\t\treturn content;\n\t\t}\n\t}\n\n\tthrow new Error(\n\t\t\"Failed to extract reference content: no <reference_output> tags found in AI response. \" +\n\t\t\t\"The AI may have failed to follow the output format instructions.\",\n\t);\n}\n\n/**\n * Validate extracted reference content has minimum required structure.\n * Throws if content is invalid.\n */\nfunction validateReferenceContent(content: string): void {\n\tif (content.length < 500) {\n\t\tthrow new Error(\n\t\t\t`Invalid reference content: too short (${content.length} chars, minimum 500). ` +\n\t\t\t\t\"The AI may have produced placeholder or incomplete content.\",\n\t\t);\n\t}\n\n\tif (!content.startsWith(\"#\")) {\n\t\tthrow new Error(\n\t\t\t\"Invalid reference content: must start with markdown heading. \" +\n\t\t\t\t\"Content must begin with '# Library Name' (no YAML frontmatter).\",\n\t\t);\n\t}\n}\n\n/**\n * Generate a reference markdown file for a repository using AI.\n *\n * Opens an OpenCode session and instructs the AI agent to explore the codebase\n * using Read, Grep, and Glob tools, then produce a comprehensive reference.\n *\n * @param repoPath - Path to the repository to analyze\n * @param repoName - Qualified name of the repo (e.g., \"tanstack/query\" or \"my-local-repo\")\n * @param options - Generation options (provider, model, callbacks)\n * @returns The generated reference content and commit SHA\n */\nexport async function generateReferenceWithAI(\n\trepoPath: string,\n\trepoName: string,\n\toptions: GenerateReferenceOptions = {},\n): Promise<GenerateReferenceResult> {\n\tconst { provider, model, onDebug, onStream } = options;\n\tconst config = loadConfig();\n\n\tconst [configProvider, configModel] = config.defaultModel?.split(\"/\") ?? [];\n\tconst aiProvider = provider ?? configProvider;\n\tconst aiModel = model ?? configModel;\n\n\tonDebug?.(`Starting AI reference generation for ${repoName}`);\n\tonDebug?.(`Repo path: ${repoPath}`);\n\tonDebug?.(`Provider: ${aiProvider ?? \"default\"}, Model: ${aiModel ?? \"default\"}`);\n\n\tconst commitSha = getCommitSha(repoPath);\n\tonDebug?.(`Commit SHA: ${commitSha}`);\n\n\tconst referenceName = toReferenceName(repoName);\n\tonDebug?.(`Reference name: ${referenceName}`);\n\n\tconst promptOptions: StreamPromptOptions = {\n\t\tprompt: createReferenceGenerationPrompt(referenceName),\n\t\tcwd: repoPath,\n\t\tprovider: aiProvider,\n\t\tmodel: aiModel,\n\t\tonDebug,\n\t\tonStream,\n\t};\n\n\tconst result = await streamPrompt(promptOptions);\n\n\tonDebug?.(`Generation complete (${result.durationMs}ms, ${result.text.length} chars)`);\n\n\tconst referenceContent = extractReferenceContent(result.text);\n\tonDebug?.(`Extracted reference content (${referenceContent.length} chars)`);\n\n\treturn {\n\t\treferenceContent,\n\t\tcommitSha,\n\t};\n}\n\n/**\n * Ensure a symlink exists, removing any existing file/directory at the path\n */\nfunction ensureSymlink(target: string, linkPath: string): void {\n\ttry {\n\t\tconst stat = lstatSync(linkPath);\n\t\tif (stat.isSymbolicLink()) {\n\t\t\tunlinkSync(linkPath);\n\t\t} else if (stat.isDirectory()) {\n\t\t\trmSync(linkPath, { recursive: true });\n\t\t} else {\n\t\t\tunlinkSync(linkPath);\n\t\t}\n\t} catch {}\n\n\tconst linkDir = join(linkPath, \"..\");\n\tmkdirSync(linkDir, { recursive: true });\n\tsymlinkSync(target, linkPath, \"dir\");\n}\n\n/**\n * Static template for the global SKILL.md file.\n * This is the single routing skill that all agents see.\n */\nconst GLOBAL_SKILL_TEMPLATE = `---\nname: offworld\ndescription: Routes queries to Offworld reference files. Find and read per-repo references for dependency knowledge.\nallowed-tools: Bash(ow:*) Read\n---\n\n# Offworld Reference Router\n\nUse \\`ow\\` to locate and read Offworld reference files for dependencies.\n\n## What This Does\n\n- Finds references for libraries and repos\n- Returns paths for reference files and local clones\n- Helps you read the right context fast\n\n## When to Use\n\n- You need docs or patterns for a dependency\n- You want the verified reference instead of web search\n- You are about to work inside a repo clone\n\n## Prerequisites\n\nCheck that the CLI is available:\n\n\\`\\`\\`bash\now --version\n\\`\\`\\`\n\nIf \\`ow\\` is not available, install it:\n\n\\`\\`\\`bash\ncurl -fsSL https://offworld.sh/install | bash\n\\`\\`\\`\n\n## Setup\n\nInitialize Offworld once per machine:\n\n\\`\\`\\`bash\now init\n\\`\\`\\`\n\nFor a specific project, build a project map:\n\n\\`\\`\\`bash\now project init\n\\`\\`\\`\n\n## Usage\n\n**Find a reference:**\n\\`\\`\\`bash\now map search <term> # search by name or keyword\now map show <repo> # get info for specific repo\n\\`\\`\\`\n\n**Get paths for tools:**\n\\`\\`\\`bash\now map show <repo> --ref # reference file path (use with Read)\now map show <repo> --path # clone directory path\n\\`\\`\\`\n\n**Example workflow:**\n\\`\\`\\`bash\n# 1. Find the repo\now map search zod\n\n# 2. Get reference path\now map show colinhacks/zod --ref\n# Output: /Users/.../.local/share/offworld/skill/offworld/references/colinhacks-zod.md\n\n# 3. Read the reference with the path from step 2\n\\`\\`\\`\n\n## If Reference Not Found\n\n\\`\\`\\`bash\now pull <owner/repo> # clone + generate reference\now project init # scan project deps, install references\n\\`\\`\\`\n\n## Notes\n\n- Project map (\\`.offworld/map.json\\`) takes precedence over global map when present\n- Reference files are markdown with API docs, patterns, best practices\n- Clone paths useful for exploring source code after reading reference\n\n## Additional Resources\n\n- Docs: https://offworld.sh/cli\n`;\n\n/**\n * Ensures the global SKILL.md exists and symlinks the offworld/ directory to all agent skill directories.\n *\n * Creates:\n * - ~/.local/share/offworld/skill/offworld/SKILL.md (static routing template)\n * - ~/.local/share/offworld/skill/offworld/assets/ (for map.json)\n * - ~/.local/share/offworld/skill/offworld/references/ (for reference files)\n * - Symlinks entire offworld/ directory to each agent's skill directory\n */\nexport function installGlobalSkill(): void {\n\tconst config = loadConfig();\n\n\tmkdirSync(Paths.offworldSkillDir, { recursive: true });\n\tmkdirSync(Paths.offworldAssetsDir, { recursive: true });\n\tmkdirSync(Paths.offworldReferencesDir, { recursive: true });\n\n\tconst skillPath = join(Paths.offworldSkillDir, \"SKILL.md\");\n\tif (!existsSync(skillPath)) {\n\t\twriteFileSync(skillPath, GLOBAL_SKILL_TEMPLATE, \"utf-8\");\n\t}\n\n\tconst configuredAgents = config.agents ?? [];\n\tfor (const agentName of configuredAgents) {\n\t\tconst agentConfig = agents[agentName];\n\t\tif (agentConfig) {\n\t\t\tconst agentSkillDir = expandTilde(join(agentConfig.globalSkillsDir, \"offworld\"));\n\t\t\tensureSymlink(Paths.offworldSkillDir, agentSkillDir);\n\t\t}\n\t}\n}\n\n/**\n * Install a reference file for a specific repository.\n *\n * Creates:\n * - ~/.local/share/offworld/skill/offworld/references/{owner-repo}.md\n * - ~/.local/share/offworld/meta/{owner-repo}/meta.json\n * - Updates global map with reference info\n *\n * @param qualifiedName - Qualified key for map storage (e.g., \"github.com:owner/repo\" or \"local:name\")\n * @param fullName - Full repo name for file naming (e.g., \"owner/repo\")\n * @param localPath - Absolute path to the cloned repository\n * @param referenceContent - The generated reference markdown content\n * @param meta - Metadata about the generation (referenceUpdatedAt, commitSha, version)\n * @param keywords - Optional array of keywords for search/routing\n */\nexport function installReference(\n\tqualifiedName: string,\n\tfullName: string,\n\tlocalPath: string,\n\treferenceContent: string,\n\tmeta: InstallReferenceMeta,\n\tkeywords?: string[],\n): void {\n\tinstallGlobalSkill();\n\n\tconst referenceFileName = toReferenceFileName(fullName);\n\tconst metaDirName = toMetaDirName(fullName);\n\n\tconst referencePath = join(Paths.offworldReferencesDir, referenceFileName);\n\tmkdirSync(Paths.offworldReferencesDir, { recursive: true });\n\twriteFileSync(referencePath, referenceContent, \"utf-8\");\n\n\tconst metaDir = join(Paths.metaDir, metaDirName);\n\tmkdirSync(metaDir, { recursive: true });\n\tconst metaJson = JSON.stringify(meta, null, 2);\n\twriteFileSync(join(metaDir, \"meta.json\"), metaJson, \"utf-8\");\n\n\tconst map = readGlobalMap();\n\tconst existingEntry = map.repos[qualifiedName];\n\tconst legacyProviderMap: Record<string, string> = {\n\t\t\"github.com\": \"github\",\n\t\t\"gitlab.com\": \"gitlab\",\n\t\t\"bitbucket.org\": \"bitbucket\",\n\t};\n\tconst [host] = qualifiedName.split(\":\");\n\tconst legacyProvider = host ? legacyProviderMap[host] : undefined;\n\tconst legacyQualifiedName = legacyProvider ? `${legacyProvider}:${fullName}` : undefined;\n\tconst legacyEntry = legacyQualifiedName ? map.repos[legacyQualifiedName] : undefined;\n\n\tconst references = [...(existingEntry?.references ?? []), ...(legacyEntry?.references ?? [])];\n\tif (!references.includes(referenceFileName)) {\n\t\treferences.push(referenceFileName);\n\t}\n\n\tconst derivedKeywords = keywords ?? deriveKeywords(fullName, localPath, referenceContent);\n\tconst keywordsSet = new Set<string>([\n\t\t...(existingEntry?.keywords ?? []),\n\t\t...(legacyEntry?.keywords ?? []),\n\t\t...derivedKeywords,\n\t]);\n\n\tmap.repos[qualifiedName] = {\n\t\tlocalPath,\n\t\treferences,\n\t\tprimary: referenceFileName,\n\t\tkeywords: Array.from(keywordsSet),\n\t\tupdatedAt: new Date().toISOString(),\n\t};\n\n\tif (legacyQualifiedName && legacyQualifiedName in map.repos) {\n\t\tdelete map.repos[legacyQualifiedName];\n\t}\n\n\twriteGlobalMap(map);\n}\n","/**\n * Dependency manifest parsing for multiple package ecosystems\n */\n\nimport { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport type { Dirent } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport type ManifestType = \"npm\" | \"python\" | \"rust\" | \"go\" | \"unknown\";\n\nexport interface Dependency {\n\tname: string;\n\tversion?: string;\n\tdev: boolean;\n}\n\nconst DEFAULT_IGNORED_DIRS = new Set([\n\t\".git\",\n\t\".offworld\",\n\t\".turbo\",\n\t\"build\",\n\t\"dist\",\n\t\"node_modules\",\n\t\"out\",\n]);\n\n/**\n * Detects the manifest type in a directory\n */\nexport function detectManifestType(dir: string): ManifestType {\n\tif (existsSync(join(dir, \"package.json\"))) return \"npm\";\n\tif (existsSync(join(dir, \"pyproject.toml\"))) return \"python\";\n\tif (existsSync(join(dir, \"Cargo.toml\"))) return \"rust\";\n\tif (existsSync(join(dir, \"go.mod\"))) return \"go\";\n\tif (existsSync(join(dir, \"requirements.txt\"))) return \"python\";\n\treturn \"unknown\";\n}\n\n/**\n * Parses dependencies from manifest files\n */\nexport function parseDependencies(dir: string): Dependency[] {\n\tconst type = detectManifestType(dir);\n\n\tswitch (type) {\n\t\tcase \"npm\":\n\t\t\treturn parseNpmDependencies(dir);\n\t\tcase \"python\":\n\t\t\treturn existsSync(join(dir, \"pyproject.toml\"))\n\t\t\t\t? parsePyprojectToml(join(dir, \"pyproject.toml\"))\n\t\t\t\t: parseRequirementsTxt(join(dir, \"requirements.txt\"));\n\t\tcase \"rust\":\n\t\t\treturn parseCargoToml(join(dir, \"Cargo.toml\"));\n\t\tcase \"go\":\n\t\t\treturn parseGoMod(join(dir, \"go.mod\"));\n\t\tdefault:\n\t\t\treturn [];\n\t}\n}\n\nfunction parseNpmDependencies(dir: string): Dependency[] {\n\tconst rootPath = join(dir, \"package.json\");\n\tconst rootDeps = parsePackageJson(rootPath);\n\tconst workspaceDeps = parseWorkspaceDependencies(dir);\n\treturn mergeDependencies(rootDeps, workspaceDeps).sort((a, b) => a.name.localeCompare(b.name));\n}\n\nfunction parseWorkspaceDependencies(dir: string): Dependency[] {\n\tconst workspacePatterns = getWorkspacePatterns(dir);\n\tif (workspacePatterns.length === 0) return [];\n\n\tconst packageJsonPaths = resolveWorkspacePackageJsonPaths(dir, workspacePatterns);\n\tconst deps: Dependency[] = [];\n\tfor (const path of packageJsonPaths) {\n\t\tdeps.push(...parsePackageJson(path));\n\t}\n\n\treturn mergeDependencies([], deps);\n}\n\nfunction getWorkspacePatterns(dir: string): string[] {\n\tconst patterns = new Set<string>();\n\n\tconst packageJsonPath = join(dir, \"package.json\");\n\tif (existsSync(packageJsonPath)) {\n\t\tconst rootJson = readJson(packageJsonPath);\n\t\tconst workspaces = rootJson?.workspaces;\n\t\tif (Array.isArray(workspaces)) {\n\t\t\tfor (const pattern of workspaces) {\n\t\t\t\tif (typeof pattern === \"string\") patterns.add(pattern);\n\t\t\t}\n\t\t} else if (workspaces && typeof workspaces === \"object\") {\n\t\t\tconst packagesField = (workspaces as { packages?: unknown }).packages;\n\t\t\tif (Array.isArray(packagesField)) {\n\t\t\t\tfor (const pattern of packagesField) {\n\t\t\t\t\tif (typeof pattern === \"string\") patterns.add(pattern);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tconst pnpmWorkspacePath = existsSync(join(dir, \"pnpm-workspace.yaml\"))\n\t\t? join(dir, \"pnpm-workspace.yaml\")\n\t\t: existsSync(join(dir, \"pnpm-workspace.yml\"))\n\t\t\t? join(dir, \"pnpm-workspace.yml\")\n\t\t\t: null;\n\n\tif (pnpmWorkspacePath) {\n\t\tfor (const pattern of parsePnpmWorkspacePackages(pnpmWorkspacePath)) {\n\t\t\tpatterns.add(pattern);\n\t\t}\n\t}\n\n\treturn Array.from(patterns);\n}\n\nfunction resolveWorkspacePackageJsonPaths(dir: string, patterns: string[]): string[] {\n\tconst includePatterns = patterns.filter((pattern) => !pattern.startsWith(\"!\"));\n\tconst excludePatterns = patterns\n\t\t.filter((pattern) => pattern.startsWith(\"!\"))\n\t\t.map((pattern) => pattern.slice(1));\n\n\tif (includePatterns.length === 0) return [];\n\n\tconst includeRegexes = includePatterns.map(patternToRegex);\n\tconst excludeRegexes = excludePatterns.map(patternToRegex);\n\n\tconst matches: string[] = [];\n\tconst directories = walkDirectories(dir);\n\n\tfor (const relativePath of directories) {\n\t\tif (!includeRegexes.some((regex) => regex.test(relativePath))) continue;\n\t\tif (excludeRegexes.some((regex) => regex.test(relativePath))) continue;\n\n\t\tconst packageJsonPath = join(dir, relativePath, \"package.json\");\n\t\tif (existsSync(packageJsonPath)) {\n\t\t\tmatches.push(packageJsonPath);\n\t\t}\n\t}\n\n\treturn Array.from(new Set(matches));\n}\n\nfunction walkDirectories(root: string): string[] {\n\tconst results: string[] = [];\n\tconst stack: string[] = [\"\"];\n\n\twhile (stack.length > 0) {\n\t\tconst relativePath = stack.pop();\n\t\tconst currentPath = relativePath ? join(root, relativePath) : root;\n\n\t\tlet entries: Dirent[];\n\t\ttry {\n\t\t\tentries = readdirSync(currentPath, { withFileTypes: true }) as Dirent[];\n\t\t} catch {\n\t\t\tcontinue;\n\t\t}\n\n\t\tfor (const entry of entries) {\n\t\t\tif (!entry.isDirectory()) continue;\n\t\t\tif (DEFAULT_IGNORED_DIRS.has(entry.name)) continue;\n\n\t\t\tconst nextRelative = relativePath ? `${relativePath}/${entry.name}` : entry.name;\n\t\t\tresults.push(nextRelative);\n\t\t\tstack.push(nextRelative);\n\t\t}\n\t}\n\n\treturn results;\n}\n\nfunction patternToRegex(pattern: string): RegExp {\n\tlet normalized = pattern.trim().replace(/\\\\/g, \"/\");\n\tif (normalized.startsWith(\"./\")) normalized = normalized.slice(2);\n\tif (normalized.endsWith(\"/\")) normalized = normalized.slice(0, -1);\n\n\tconst escaped = normalized.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\tconst withGlob = escaped.replace(/\\\\\\*\\\\\\*/g, \".*\").replace(/\\\\\\*/g, \"[^/]+\");\n\n\treturn new RegExp(`^${withGlob}$`);\n}\n\nfunction parsePnpmWorkspacePackages(path: string): string[] {\n\ttry {\n\t\tconst content = readFileSync(path, \"utf-8\");\n\t\tconst lines = content.split(\"\\n\");\n\t\tconst patterns: string[] = [];\n\t\tlet inPackages = false;\n\n\t\tfor (const line of lines) {\n\t\t\tconst trimmed = line.trim();\n\t\t\tif (!trimmed || trimmed.startsWith(\"#\")) continue;\n\n\t\t\tif (/^packages\\s*:/.test(trimmed)) {\n\t\t\t\tinPackages = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!inPackages) continue;\n\n\t\t\tconst entryMatch = trimmed.match(/^-\\s*(.+)$/);\n\t\t\tif (entryMatch?.[1]) {\n\t\t\t\tconst value = entryMatch[1].trim().replace(/^['\"]|['\"]$/g, \"\");\n\t\t\t\tif (value) patterns.push(value);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!line.startsWith(\" \") && !line.startsWith(\"\\t\")) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn patterns;\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction readJson(path: string): Record<string, unknown> | null {\n\ttry {\n\t\tconst content = readFileSync(path, \"utf-8\");\n\t\treturn JSON.parse(content) as Record<string, unknown>;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction mergeDependencies(base: Dependency[], incoming: Dependency[]): Dependency[] {\n\tconst map = new Map<string, Dependency>();\n\n\tfor (const dep of [...base, ...incoming]) {\n\t\tconst existing = map.get(dep.name);\n\t\tif (!existing) {\n\t\t\tmap.set(dep.name, { ...dep });\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst dev = existing.dev && dep.dev;\n\t\tconst version = existing.version ?? dep.version;\n\t\tmap.set(dep.name, { name: dep.name, version, dev });\n\t}\n\n\treturn Array.from(map.values());\n}\n\n/**\n * Parse package.json dependencies\n */\nfunction parsePackageJson(path: string): Dependency[] {\n\ttry {\n\t\tconst content = readFileSync(path, \"utf-8\");\n\t\tconst pkg = JSON.parse(content);\n\t\tconst deps: Dependency[] = [];\n\n\t\tif (pkg.dependencies && typeof pkg.dependencies === \"object\") {\n\t\t\tfor (const [name, version] of Object.entries(pkg.dependencies)) {\n\t\t\t\tdeps.push({ name, version: version as string, dev: false });\n\t\t\t}\n\t\t}\n\n\t\tif (pkg.devDependencies && typeof pkg.devDependencies === \"object\") {\n\t\t\tfor (const [name, version] of Object.entries(pkg.devDependencies)) {\n\t\t\t\tdeps.push({ name, version: version as string, dev: true });\n\t\t\t}\n\t\t}\n\n\t\tif (pkg.peerDependencies && typeof pkg.peerDependencies === \"object\") {\n\t\t\tfor (const [name, version] of Object.entries(pkg.peerDependencies)) {\n\t\t\t\tdeps.push({ name, version: version as string, dev: false });\n\t\t\t}\n\t\t}\n\n\t\tif (pkg.optionalDependencies && typeof pkg.optionalDependencies === \"object\") {\n\t\t\tfor (const [name, version] of Object.entries(pkg.optionalDependencies)) {\n\t\t\t\tdeps.push({ name, version: version as string, dev: false });\n\t\t\t}\n\t\t}\n\n\t\treturn deps;\n\t} catch {\n\t\treturn [];\n\t}\n}\n\n/**\n * Parse pyproject.toml dependencies\n */\nfunction parsePyprojectToml(path: string): Dependency[] {\n\ttry {\n\t\tconst content = readFileSync(path, \"utf-8\");\n\t\tconst deps: Dependency[] = [];\n\n\t\tconst depsSection = content.match(/\\[project\\.dependencies\\]([\\s\\S]*?)(?=\\[|$)/);\n\t\tif (!depsSection?.[1]) return [];\n\n\t\tconst lines = depsSection[1].split(\"\\n\");\n\t\tfor (const line of lines) {\n\t\t\tconst match = line.match(/[\"']([a-zA-Z0-9_-]+)(?:[>=<~!]+([^\"']+))?[\"']/);\n\t\t\tif (match?.[1]) {\n\t\t\t\tdeps.push({\n\t\t\t\t\tname: match[1],\n\t\t\t\t\tversion: match[2]?.trim(),\n\t\t\t\t\tdev: false,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn deps;\n\t} catch {\n\t\treturn [];\n\t}\n}\n\n/**\n * Parse Cargo.toml dependencies\n */\nfunction parseCargoToml(path: string): Dependency[] {\n\ttry {\n\t\tconst content = readFileSync(path, \"utf-8\");\n\t\tconst deps: Dependency[] = [];\n\n\t\tconst depsSection = content.match(/\\[dependencies\\]([\\s\\S]*?)(?=\\[|$)/);\n\t\tif (!depsSection?.[1]) return [];\n\n\t\tconst lines = depsSection[1].split(\"\\n\");\n\t\tfor (const line of lines) {\n\t\t\tconst simpleMatch = line.match(/^([a-zA-Z0-9_-]+)\\s*=\\s*\"([^\"]+)\"/);\n\t\t\tconst tableMatch = line.match(/^([a-zA-Z0-9_-]+)\\s*=\\s*{.*version\\s*=\\s*\"([^\"]+)\"/);\n\n\t\t\tif (simpleMatch?.[1] && simpleMatch[2]) {\n\t\t\t\tdeps.push({ name: simpleMatch[1], version: simpleMatch[2], dev: false });\n\t\t\t} else if (tableMatch?.[1] && tableMatch[2]) {\n\t\t\t\tdeps.push({ name: tableMatch[1], version: tableMatch[2], dev: false });\n\t\t\t}\n\t\t}\n\n\t\treturn deps;\n\t} catch {\n\t\treturn [];\n\t}\n}\n\n/**\n * Parse go.mod dependencies\n */\nfunction parseGoMod(path: string): Dependency[] {\n\ttry {\n\t\tconst content = readFileSync(path, \"utf-8\");\n\t\tconst deps: Dependency[] = [];\n\n\t\tconst requireSection = content.match(/require\\s*\\(([\\s\\S]*?)\\)/);\n\t\tif (!requireSection?.[1]) {\n\t\t\tconst singleRequire = content.match(/require\\s+([^\\s]+)\\s+([^\\s]+)/);\n\t\t\tif (singleRequire?.[1] && singleRequire[2]) {\n\t\t\t\tdeps.push({\n\t\t\t\t\tname: singleRequire[1],\n\t\t\t\t\tversion: singleRequire[2],\n\t\t\t\t\tdev: false,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn deps;\n\t\t}\n\n\t\tconst lines = requireSection[1].split(\"\\n\");\n\t\tfor (const line of lines) {\n\t\t\tconst match = line.match(/^\\s*([^\\s]+)\\s+([^\\s]+)/);\n\t\t\tif (match?.[1] && match[2]) {\n\t\t\t\tdeps.push({ name: match[1], version: match[2], dev: false });\n\t\t\t}\n\t\t}\n\n\t\treturn deps;\n\t} catch {\n\t\treturn [];\n\t}\n}\n\n/**\n * Parse requirements.txt dependencies\n */\nfunction parseRequirementsTxt(path: string): Dependency[] {\n\ttry {\n\t\tconst content = readFileSync(path, \"utf-8\");\n\t\tconst deps: Dependency[] = [];\n\n\t\tconst lines = content.split(\"\\n\");\n\t\tfor (const line of lines) {\n\t\t\tconst trimmed = line.trim();\n\t\t\tif (!trimmed || trimmed.startsWith(\"#\")) continue;\n\n\t\t\tconst match = trimmed.match(/^([a-zA-Z0-9_-]+)(?:[>=<~!]+(.+))?/);\n\t\t\tif (match?.[1]) {\n\t\t\t\tdeps.push({\n\t\t\t\t\tname: match[1],\n\t\t\t\t\tversion: match[2]?.trim(),\n\t\t\t\t\tdev: false,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn deps;\n\t} catch {\n\t\treturn [];\n\t}\n}\n","/**\n * Three-tier dependency name to GitHub repo resolution:\n * 1. KNOWN_MAPPINGS - hardcoded popular packages\n * 2. npm registry fallback\n * 3. User prompt (handled by caller)\n */\n\nimport { NpmPackageResponseSchema } from \"@offworld/types\";\n\nexport type ResolvedDep = {\n\tdep: string;\n\trepo: string | null;\n\tsource: \"known\" | \"npm\" | \"unknown\";\n};\n\n/**\n * Hardcoded mappings for popular packages.\n * Covers top ecosystems: React, Vue, Svelte, backend, database, validation, styling.\n */\nexport const KNOWN_MAPPINGS: Record<string, string> = {\n\treact: \"facebook/react\",\n\t\"react-dom\": \"facebook/react\",\n\tnext: \"vercel/next.js\",\n\tremix: \"remix-run/remix\",\n\t\"@remix-run/react\": \"remix-run/remix\",\n\t\"@remix-run/node\": \"remix-run/remix\",\n\n\tvue: \"vuejs/core\",\n\tnuxt: \"nuxt/nuxt\",\n\t\"@nuxt/kit\": \"nuxt/nuxt\",\n\n\tsvelte: \"sveltejs/svelte\",\n\tsveltekit: \"sveltejs/kit\",\n\t\"@sveltejs/kit\": \"sveltejs/kit\",\n\n\t\"@tanstack/query\": \"tanstack/query\",\n\t\"@tanstack/react-query\": \"tanstack/query\",\n\t\"@tanstack/vue-query\": \"tanstack/query\",\n\t\"@tanstack/router\": \"tanstack/router\",\n\t\"@tanstack/react-router\": \"tanstack/router\",\n\t\"@tanstack/start\": \"tanstack/router\",\n\tzustand: \"pmndrs/zustand\",\n\tjotai: \"pmndrs/jotai\",\n\tvaltio: \"pmndrs/valtio\",\n\tredux: \"reduxjs/redux\",\n\t\"@reduxjs/toolkit\": \"reduxjs/redux-toolkit\",\n\n\texpress: \"expressjs/express\",\n\thono: \"honojs/hono\",\n\tfastify: \"fastify/fastify\",\n\tkoa: \"koajs/koa\",\n\tnestjs: \"nestjs/nest\",\n\t\"@nestjs/core\": \"nestjs/nest\",\n\n\t// API/RPC\n\ttrpc: \"trpc/trpc\",\n\t\"@trpc/server\": \"trpc/trpc\",\n\t\"@trpc/client\": \"trpc/trpc\",\n\t\"@trpc/react-query\": \"trpc/trpc\",\n\tgraphql: \"graphql/graphql-js\",\n\t\"apollo-server\": \"apollographql/apollo-server\",\n\t\"@apollo/client\": \"apollographql/apollo-client\",\n\n\t\"drizzle-orm\": \"drizzle-team/drizzle-orm\",\n\tprisma: \"prisma/prisma\",\n\t\"@prisma/client\": \"prisma/prisma\",\n\ttypeorm: \"typeorm/typeorm\",\n\tsequelize: \"sequelize/sequelize\",\n\tmongoose: \"Automattic/mongoose\",\n\tknex: \"knex/knex\",\n\n\tzod: \"colinhacks/zod\",\n\tvalibot: \"fabian-hiller/valibot\",\n\tyup: \"jquense/yup\",\n\tjoi: \"hapijs/joi\",\n\n\ttailwindcss: \"tailwindlabs/tailwindcss\",\n\t\"styled-components\": \"styled-components/styled-components\",\n\t\"@emotion/react\": \"emotion-js/emotion\",\n\tsass: \"sass/sass\",\n\n\tvite: \"vitejs/vite\",\n\twebpack: \"webpack/webpack\",\n\tesbuild: \"evanw/esbuild\",\n\trollup: \"rollup/rollup\",\n\t\"@vitejs/plugin-react\": \"vitejs/vite-plugin-react\",\n\n\tvitest: \"vitest-dev/vitest\",\n\tjest: \"jestjs/jest\",\n\t\"@testing-library/react\": \"testing-library/react-testing-library\",\n\tcypress: \"cypress-io/cypress\",\n\tplaywright: \"microsoft/playwright\",\n\n\tconvex: \"get-convex/convex-backend\",\n\n\t\"better-auth\": \"better-auth/better-auth\",\n\n\tlodash: \"lodash/lodash\",\n\t\"date-fns\": \"date-fns/date-fns\",\n\taxios: \"axios/axios\",\n\tky: \"sindresorhus/ky\",\n\n\tturborepo: \"vercel/turborepo\",\n\tnx: \"nrwl/nx\",\n};\n\n/**\n * Parse GitHub repo from various git URL formats.\n * Handles:\n * - git+https://github.com/owner/repo.git\n * - https://github.com/owner/repo\n * - git://github.com/owner/repo.git\n * - github:owner/repo\n */\nfunction parseGitHubUrl(url: string): string | null {\n\tconst patterns = [\n\t\t/github\\.com[/:]([\\w-]+)\\/([\\w.-]+?)(?:\\.git)?$/,\n\t\t/^github:([\\w-]+)\\/([\\w.-]+)$/,\n\t];\n\n\tfor (const pattern of patterns) {\n\t\tconst match = url.match(pattern);\n\t\tif (match) {\n\t\t\treturn `${match[1]}/${match[2]}`;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Fallback to npm registry to extract repository.url.\n * Returns null if package not found, no repo field, or not a GitHub repo.\n */\nexport async function resolveFromNpm(packageName: string): Promise<string | null> {\n\ttry {\n\t\tconst res = await fetch(`https://registry.npmjs.org/${packageName}`);\n\t\tif (!res.ok) return null;\n\n\t\tconst json = await res.json();\n\t\tconst result = NpmPackageResponseSchema.safeParse(json);\n\t\tif (!result.success) return null;\n\n\t\tconst repoUrl = result.data.repository?.url;\n\t\tif (!repoUrl) return null;\n\n\t\treturn parseGitHubUrl(repoUrl);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Three-tier resolution:\n * 1. Check KNOWN_MAPPINGS\n * 2. Query npm registry\n * 3. Return unknown (caller prompts user)\n */\nexport async function resolveDependencyRepo(dep: string): Promise<ResolvedDep> {\n\tif (dep in KNOWN_MAPPINGS) {\n\t\treturn { dep, repo: KNOWN_MAPPINGS[dep] ?? null, source: \"known\" };\n\t}\n\n\tconst npmRepo = await resolveFromNpm(dep);\n\tif (npmRepo) {\n\t\treturn { dep, repo: npmRepo, source: \"npm\" };\n\t}\n\n\treturn { dep, repo: null, source: \"unknown\" };\n}\n","/**\n * Reference matching utilities for dependency resolution\n *\n * Maps dependencies to their reference status (installed, available, generate, unknown)\n */\n\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { toReferenceFileName } from \"./config.js\";\nimport { Paths } from \"./paths.js\";\nimport type { ResolvedDep } from \"./dep-mappings.js\";\n\nexport type ReferenceStatus = \"installed\" | \"available\" | \"generate\" | \"unknown\";\n\nexport interface ReferenceMatch {\n\t/** Dependency name */\n\tdep: string;\n\t/** GitHub repo (owner/repo) or null if unknown */\n\trepo: string | null;\n\t/** Reference availability status */\n\tstatus: ReferenceStatus;\n\t/** Resolution source: 'known' | 'npm' | 'unknown' */\n\tsource: \"known\" | \"npm\" | \"unknown\";\n}\n\n/**\n * Check if a reference is installed locally.\n * A reference is considered installed if {owner-repo}.md exists in offworld/references/.\n *\n * @param repo - Repo name in owner/repo format\n * @returns true if reference is installed locally\n */\nexport function isReferenceInstalled(repo: string): boolean {\n\tconst referenceFileName = toReferenceFileName(repo);\n\tconst referencePath = join(Paths.offworldReferencesDir, referenceFileName);\n\treturn existsSync(referencePath);\n}\n\n/**\n * Match dependencies to their reference availability status.\n *\n * Status logic:\n * - installed: {owner-repo}.md exists in offworld/references/\n * - available: Has valid GitHub repo (can be cloned)\n * - generate: Has valid GitHub repo but will need AI generation\n * - unknown: No GitHub repo found\n *\n * Note: Since we don't have a reference registry/index, \"available\" and \"generate\"\n * are the same. We use \"available\" for consistency and reserve \"generate\" for\n * future use when we can distinguish pre-existing vs needs-generation.\n *\n * @param resolvedDeps - Array of resolved dependencies with repo info\n * @returns Array of reference matches with status\n */\nexport function matchDependenciesToReferences(resolvedDeps: ResolvedDep[]): ReferenceMatch[] {\n\treturn resolvedDeps.map((dep) => {\n\t\tif (!dep.repo) {\n\t\t\treturn {\n\t\t\t\tdep: dep.dep,\n\t\t\t\trepo: null,\n\t\t\t\tstatus: \"unknown\",\n\t\t\t\tsource: dep.source,\n\t\t\t};\n\t\t}\n\n\t\tif (isReferenceInstalled(dep.repo)) {\n\t\t\treturn {\n\t\t\t\tdep: dep.dep,\n\t\t\t\trepo: dep.repo,\n\t\t\t\tstatus: \"installed\",\n\t\t\t\tsource: dep.source,\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tdep: dep.dep,\n\t\t\trepo: dep.repo,\n\t\t\tstatus: \"available\",\n\t\t\tsource: dep.source,\n\t\t};\n\t});\n}\n","/**\n * AGENTS.md manipulation utilities\n *\n * Manages updating project AGENTS.md and agent-specific files with reference information.\n */\n\nimport { readFileSync, writeFileSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport interface InstalledReference {\n\t/** Dependency name */\n\tdependency: string;\n\t/** Reference identifier (matches reference file name without .md) */\n\treference: string;\n\t/** Absolute path to reference file */\n\tpath: string;\n}\n\n/**\n * Generate markdown table for project references section.\n *\n * @param references - Array of installed references\n * @returns Markdown string with table\n */\nfunction generateReferencesTable(references: InstalledReference[]): string {\n\tconst lines = [\n\t\t\"## Project References\",\n\t\t\"\",\n\t\t\"References installed for this project's dependencies:\",\n\t\t\"\",\n\t\t\"| Dependency | Reference | Path |\",\n\t\t\"| --- | --- | --- |\",\n\t];\n\n\tfor (const reference of references) {\n\t\tlines.push(`| ${reference.dependency} | ${reference.reference} | ${reference.path} |`);\n\t}\n\n\tlines.push(\"\");\n\tlines.push(\"To update references: `ow pull <dependency>`\");\n\tlines.push(\"To regenerate all: `ow project init --all --generate`\");\n\tlines.push(\"\");\n\n\treturn lines.join(\"\\n\");\n}\n\n/**\n * Update or append Project References section in a markdown file.\n * If the section exists, replaces its content. Otherwise, appends to end.\n *\n * @param filePath - Path to markdown file\n * @param references - Array of installed references\n */\nexport function appendReferencesSection(filePath: string, references: InstalledReference[]): void {\n\tconst content = existsSync(filePath) ? readFileSync(filePath, \"utf-8\") : \"\";\n\tconst referencesMarkdown = generateReferencesTable(references);\n\n\tconst sectionRegex = /^## Project References\\n(?:.*\\n)*?(?=^## |$)/m;\n\tconst match = content.match(sectionRegex);\n\n\tlet updatedContent: string;\n\tif (match) {\n\t\tupdatedContent = content.replace(sectionRegex, referencesMarkdown);\n\t} else {\n\t\tupdatedContent = content.trim() + \"\\n\\n\" + referencesMarkdown;\n\t}\n\n\twriteFileSync(filePath, updatedContent, \"utf-8\");\n}\n\n/**\n * Update AGENTS.md and agent-specific files with project references.\n * Creates files if they don't exist.\n *\n * @param projectRoot - Project root directory\n * @param references - Array of installed references to document\n */\nexport function updateAgentFiles(projectRoot: string, references: InstalledReference[]): void {\n\tconst agentsMdPath = join(projectRoot, \"AGENTS.md\");\n\tconst claudeMdPath = join(projectRoot, \"CLAUDE.md\");\n\n\tappendReferencesSection(agentsMdPath, references);\n\n\tif (existsSync(claudeMdPath)) {\n\t\tappendReferencesSection(claudeMdPath, references);\n\t}\n}\n","import { existsSync, statSync, readdirSync, rmSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { updateRepo, GitError } from \"./clone.js\";\nimport { readGlobalMap, removeGlobalMapEntry, upsertGlobalMapEntry } from \"./index-manager.js\";\nimport { loadConfig, getRepoRoot } from \"./config.js\";\nimport { Paths } from \"./paths.js\";\n\nexport interface RepoStatusSummary {\n\ttotal: number;\n\twithReference: number;\n\tmissing: number;\n\tdiskBytes: number;\n}\n\nexport interface RepoStatusOptions {\n\tonProgress?: (current: number, total: number, repo: string) => void;\n}\n\nexport interface UpdateAllOptions {\n\tpattern?: string;\n\tdryRun?: boolean;\n\t/** Convert shallow clones to full clones */\n\tunshallow?: boolean;\n\tonProgress?: (\n\t\trepo: string,\n\t\tstatus: \"updating\" | \"updated\" | \"skipped\" | \"error\" | \"unshallowed\",\n\t\tmessage?: string,\n\t) => void;\n}\n\nexport interface UpdateAllResult {\n\tupdated: string[];\n\tskipped: string[];\n\tunshallowed: string[];\n\terrors: Array<{ repo: string; error: string }>;\n}\n\nexport interface PruneOptions {\n\tdryRun?: boolean;\n\tonProgress?: (repo: string, reason: string) => void;\n}\n\nexport interface PruneResult {\n\tremovedFromIndex: string[];\n\torphanedDirs: string[];\n}\n\nexport interface GcOptions {\n\tolderThanDays?: number;\n\twithoutReference?: boolean;\n\tdryRun?: boolean;\n\tonProgress?: (repo: string, reason: string, sizeBytes?: number) => void;\n}\n\nexport interface GcResult {\n\tremoved: Array<{ repo: string; reason: string; sizeBytes: number }>;\n\tfreedBytes: number;\n}\n\nfunction getDirSize(dirPath: string): number {\n\tif (!existsSync(dirPath)) return 0;\n\n\tlet size = 0;\n\ttry {\n\t\tconst entries = readdirSync(dirPath, { withFileTypes: true });\n\t\tfor (const entry of entries) {\n\t\t\tconst fullPath = join(dirPath, entry.name);\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\tsize += getDirSize(fullPath);\n\t\t\t} else if (entry.isFile()) {\n\t\t\t\ttry {\n\t\t\t\t\tsize += statSync(fullPath).size;\n\t\t\t\t} catch {}\n\t\t\t}\n\t\t}\n\t} catch {}\n\treturn size;\n}\n\nfunction getLastAccessTime(dirPath: string): Date | null {\n\tif (!existsSync(dirPath)) return null;\n\n\tlet latestTime: Date | null = null;\n\ttry {\n\t\tconst stat = statSync(dirPath);\n\t\tlatestTime = stat.mtime;\n\n\t\tconst fetchHead = join(dirPath, \".git\", \"FETCH_HEAD\");\n\t\tif (existsSync(fetchHead)) {\n\t\t\tconst fetchStat = statSync(fetchHead);\n\t\t\tif (!latestTime || fetchStat.mtime > latestTime) {\n\t\t\t\tlatestTime = fetchStat.mtime;\n\t\t\t}\n\t\t}\n\t} catch {}\n\treturn latestTime;\n}\n\nfunction matchesPattern(name: string, pattern: string): boolean {\n\tif (!pattern || pattern === \"*\") return true;\n\n\tconst regex = new RegExp(\n\t\t\"^\" +\n\t\t\tpattern\n\t\t\t\t.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n\t\t\t\t.replace(/\\*/g, \".*\")\n\t\t\t\t.replace(/\\?/g, \".\") +\n\t\t\t\"$\",\n\t\t\"i\",\n\t);\n\treturn regex.test(name);\n}\n\nconst yieldToEventLoop = () => new Promise<void>((resolve) => setImmediate(resolve));\n\nexport async function getRepoStatus(options: RepoStatusOptions = {}): Promise<RepoStatusSummary> {\n\tconst { onProgress } = options;\n\tconst map = readGlobalMap();\n\tconst qualifiedNames = Object.keys(map.repos);\n\tconst total = qualifiedNames.length;\n\n\tlet withReference = 0;\n\tlet missing = 0;\n\tlet diskBytes = 0;\n\n\tfor (let i = 0; i < qualifiedNames.length; i++) {\n\t\tconst qualifiedName = qualifiedNames[i]!;\n\t\tconst entry = map.repos[qualifiedName]!;\n\t\tonProgress?.(i + 1, total, qualifiedName);\n\n\t\tawait yieldToEventLoop();\n\n\t\tconst exists = existsSync(entry.localPath);\n\n\t\tif (!exists) {\n\t\t\tmissing++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (entry.references.length > 0) {\n\t\t\twithReference++;\n\t\t}\n\n\t\tdiskBytes += getDirSize(entry.localPath);\n\t}\n\n\treturn {\n\t\ttotal,\n\t\twithReference,\n\t\tmissing,\n\t\tdiskBytes,\n\t};\n}\n\nexport async function updateAllRepos(options: UpdateAllOptions = {}): Promise<UpdateAllResult> {\n\tconst { pattern, dryRun = false, unshallow = false, onProgress } = options;\n\n\tconst map = readGlobalMap();\n\tconst qualifiedNames = Object.keys(map.repos);\n\tconst updated: string[] = [];\n\tconst skipped: string[] = [];\n\tconst unshallowed: string[] = [];\n\tconst errors: Array<{ repo: string; error: string }> = [];\n\n\tfor (const qualifiedName of qualifiedNames) {\n\t\tconst entry = map.repos[qualifiedName]!;\n\n\t\tif (pattern && !matchesPattern(qualifiedName, pattern)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!existsSync(entry.localPath)) {\n\t\t\tskipped.push(qualifiedName);\n\t\t\tonProgress?.(qualifiedName, \"skipped\", \"missing on disk\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (dryRun) {\n\t\t\tupdated.push(qualifiedName);\n\t\t\tonProgress?.(qualifiedName, \"updated\", \"would update\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tonProgress?.(qualifiedName, \"updating\");\n\t\ttry {\n\t\t\tconst result = await updateRepo(qualifiedName, { unshallow });\n\t\t\tif (result.unshallowed) {\n\t\t\t\tunshallowed.push(qualifiedName);\n\t\t\t\tonProgress?.(qualifiedName, \"unshallowed\", \"converted to full clone\");\n\t\t\t}\n\t\t\tif (result.updated) {\n\t\t\t\tupdated.push(qualifiedName);\n\t\t\t\tonProgress?.(\n\t\t\t\t\tqualifiedName,\n\t\t\t\t\t\"updated\",\n\t\t\t\t\t`${result.previousSha.slice(0, 7)} → ${result.currentSha.slice(0, 7)}`,\n\t\t\t\t);\n\t\t\t} else if (!result.unshallowed) {\n\t\t\t\tskipped.push(qualifiedName);\n\t\t\t\tonProgress?.(qualifiedName, \"skipped\", \"already up to date\");\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof GitError ? err.message : String(err);\n\t\t\terrors.push({ repo: qualifiedName, error: message });\n\t\t\tonProgress?.(qualifiedName, \"error\", message);\n\t\t}\n\t}\n\n\treturn { updated, skipped, unshallowed, errors };\n}\n\nexport async function pruneRepos(options: PruneOptions = {}): Promise<PruneResult> {\n\tconst { dryRun = false, onProgress } = options;\n\n\tconst map = readGlobalMap();\n\tconst qualifiedNames = Object.keys(map.repos);\n\tconst removedFromIndex: string[] = [];\n\tconst orphanedDirs: string[] = [];\n\n\tfor (const qualifiedName of qualifiedNames) {\n\t\tconst entry = map.repos[qualifiedName]!;\n\t\tawait yieldToEventLoop();\n\n\t\tif (!existsSync(entry.localPath)) {\n\t\t\tonProgress?.(qualifiedName, \"missing on disk\");\n\t\t\tremovedFromIndex.push(qualifiedName);\n\n\t\t\tif (!dryRun) {\n\t\t\t\tremoveGlobalMapEntry(qualifiedName);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst config = loadConfig();\n\tconst repoRoot = getRepoRoot(config);\n\n\tif (existsSync(repoRoot)) {\n\t\tconst indexedPaths = new Set(Object.values(map.repos).map((r) => r.localPath));\n\n\t\ttry {\n\t\t\tconst providers = readdirSync(repoRoot, { withFileTypes: true });\n\t\t\tfor (const provider of providers) {\n\t\t\t\tif (!provider.isDirectory()) continue;\n\t\t\t\tconst providerPath = join(repoRoot, provider.name);\n\n\t\t\t\tconst owners = readdirSync(providerPath, { withFileTypes: true });\n\t\t\t\tfor (const owner of owners) {\n\t\t\t\t\tif (!owner.isDirectory()) continue;\n\t\t\t\t\tconst ownerPath = join(providerPath, owner.name);\n\n\t\t\t\t\tconst repoNames = readdirSync(ownerPath, { withFileTypes: true });\n\t\t\t\t\tfor (const repoName of repoNames) {\n\t\t\t\t\t\tawait yieldToEventLoop();\n\n\t\t\t\t\t\tif (!repoName.isDirectory()) continue;\n\t\t\t\t\t\tconst repoPath = join(ownerPath, repoName.name);\n\n\t\t\t\t\t\tif (!existsSync(join(repoPath, \".git\"))) continue;\n\n\t\t\t\t\t\tif (!indexedPaths.has(repoPath)) {\n\t\t\t\t\t\t\tconst fullName = `${owner.name}/${repoName.name}`;\n\t\t\t\t\t\t\tonProgress?.(fullName, \"not in map\");\n\t\t\t\t\t\t\torphanedDirs.push(repoPath);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {}\n\t}\n\n\treturn { removedFromIndex, orphanedDirs };\n}\n\nexport async function gcRepos(options: GcOptions = {}): Promise<GcResult> {\n\tconst { olderThanDays, withoutReference = false, dryRun = false, onProgress } = options;\n\n\tconst map = readGlobalMap();\n\tconst qualifiedNames = Object.keys(map.repos);\n\tconst removed: Array<{ repo: string; reason: string; sizeBytes: number }> = [];\n\tlet freedBytes = 0;\n\n\tconst now = new Date();\n\tconst cutoffDate = olderThanDays\n\t\t? new Date(now.getTime() - olderThanDays * 24 * 60 * 60 * 1000)\n\t\t: null;\n\n\tfor (const qualifiedName of qualifiedNames) {\n\t\tconst entry = map.repos[qualifiedName]!;\n\t\tawait yieldToEventLoop();\n\n\t\tif (!existsSync(entry.localPath)) continue;\n\n\t\tlet shouldRemove = false;\n\t\tlet reason = \"\";\n\n\t\tif (cutoffDate) {\n\t\t\tconst lastAccess = getLastAccessTime(entry.localPath);\n\t\t\tif (lastAccess && lastAccess < cutoffDate) {\n\t\t\t\tshouldRemove = true;\n\t\t\t\treason = `not accessed in ${olderThanDays}+ days`;\n\t\t\t}\n\t\t}\n\n\t\tif (withoutReference && entry.references.length === 0) {\n\t\t\tshouldRemove = true;\n\t\t\treason = reason ? `${reason}, no reference` : \"no reference\";\n\t\t}\n\n\t\tif (!shouldRemove) continue;\n\n\t\tconst sizeBytes = getDirSize(entry.localPath);\n\t\tonProgress?.(qualifiedName, reason, sizeBytes);\n\n\t\tif (!dryRun) {\n\t\t\trmSync(entry.localPath, { recursive: true, force: true });\n\n\t\t\tfor (const refFile of entry.references) {\n\t\t\t\tconst refPath = join(Paths.offworldReferencesDir, refFile);\n\t\t\t\tif (existsSync(refPath)) {\n\t\t\t\t\trmSync(refPath, { force: true });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (entry.primary) {\n\t\t\t\tconst metaDirName = entry.primary.replace(/\\.md$/, \"\");\n\t\t\t\tconst metaPath = join(Paths.metaDir, metaDirName);\n\t\t\t\tif (existsSync(metaPath)) {\n\t\t\t\t\trmSync(metaPath, { recursive: true, force: true });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tremoveGlobalMapEntry(qualifiedName);\n\t\t}\n\n\t\tremoved.push({ repo: qualifiedName, reason, sizeBytes });\n\t\tfreedBytes += sizeBytes;\n\t}\n\n\treturn { removed, freedBytes };\n}\n\nexport interface DiscoverOptions {\n\trepoRoot?: string;\n\tdryRun?: boolean;\n\tonProgress?: (repo: string, provider: string) => void;\n}\n\nexport interface DiscoverResult {\n\tdiscovered: Array<{ fullName: string; qualifiedName: string; localPath: string }>;\n\talreadyIndexed: number;\n}\n\nexport async function discoverRepos(options: DiscoverOptions = {}): Promise<DiscoverResult> {\n\tconst { dryRun = false, onProgress } = options;\n\n\tconst config = loadConfig();\n\tconst repoRoot = options.repoRoot ?? getRepoRoot(config);\n\tconst discovered: Array<{ fullName: string; qualifiedName: string; localPath: string }> = [];\n\tlet alreadyIndexed = 0;\n\n\tif (!existsSync(repoRoot)) {\n\t\treturn { discovered, alreadyIndexed };\n\t}\n\n\tconst map = readGlobalMap();\n\tconst indexedPaths = new Set(Object.values(map.repos).map((r) => r.localPath));\n\n\ttry {\n\t\tconst providers = readdirSync(repoRoot, { withFileTypes: true });\n\t\tfor (const provider of providers) {\n\t\t\tif (!provider.isDirectory()) continue;\n\t\t\tconst providerPath = join(repoRoot, provider.name);\n\n\t\t\tconst providerHostMap: Record<string, string> = {\n\t\t\t\tgithub: \"github.com\",\n\t\t\t\tgitlab: \"gitlab.com\",\n\t\t\t\tbitbucket: \"bitbucket.org\",\n\t\t\t};\n\t\t\tconst providerHost = providerHostMap[provider.name] ?? provider.name;\n\n\t\t\tconst owners = readdirSync(providerPath, { withFileTypes: true });\n\t\t\tfor (const owner of owners) {\n\t\t\t\tif (!owner.isDirectory()) continue;\n\t\t\t\tconst ownerPath = join(providerPath, owner.name);\n\n\t\t\t\tconst repoNames = readdirSync(ownerPath, { withFileTypes: true });\n\t\t\t\tfor (const repoName of repoNames) {\n\t\t\t\t\tawait yieldToEventLoop();\n\n\t\t\t\t\tif (!repoName.isDirectory()) continue;\n\t\t\t\t\tconst repoPath = join(ownerPath, repoName.name);\n\n\t\t\t\t\tif (!existsSync(join(repoPath, \".git\"))) continue;\n\n\t\t\t\t\tif (indexedPaths.has(repoPath)) {\n\t\t\t\t\t\talreadyIndexed++;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst fullName = `${owner.name}/${repoName.name}`;\n\t\t\t\t\tconst qualifiedName = `${providerHost}:${fullName}`;\n\n\t\t\t\t\tonProgress?.(fullName, providerHost);\n\n\t\t\t\t\tif (!dryRun) {\n\t\t\t\t\t\tupsertGlobalMapEntry(qualifiedName, {\n\t\t\t\t\t\t\tlocalPath: repoPath,\n\t\t\t\t\t\t\treferences: [],\n\t\t\t\t\t\t\tprimary: \"\",\n\t\t\t\t\t\t\tkeywords: [],\n\t\t\t\t\t\t\tupdatedAt: new Date().toISOString(),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tdiscovered.push({ fullName, qualifiedName, localPath: repoPath });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {}\n\n\treturn { discovered, alreadyIndexed };\n}\n","import { ModelsDevDataSchema, type ModelsDevProvider } from \"@offworld/types\";\n\nconst MODELS_DEV_URL = \"https://models.dev/api.json\";\n\n/**\n * Simplified provider info for CLI display\n */\nexport interface ProviderInfo {\n\tid: string;\n\tname: string;\n\tenv: string[];\n}\n\n/**\n * Simplified model info for CLI display\n */\nexport interface ModelInfo {\n\tid: string;\n\tname: string;\n\treasoning: boolean;\n\texperimental?: boolean;\n\tstatus?: \"alpha\" | \"beta\" | \"deprecated\";\n}\n\n/**\n * Full provider with models for CLI display\n */\nexport interface ProviderWithModels extends ProviderInfo {\n\tmodels: ModelInfo[];\n}\n\nlet cachedData: Record<string, ModelsDevProvider> | null = null;\nlet cacheTime = 0;\nconst CACHE_TTL_MS = 5 * 60 * 1000;\n\n/**\n * Fetch raw data from models.dev with caching\n */\nasync function fetchModelsDevData(): Promise<Record<string, ModelsDevProvider>> {\n\tconst now = Date.now();\n\tif (cachedData && now - cacheTime < CACHE_TTL_MS) {\n\t\treturn cachedData;\n\t}\n\n\tconst res = await fetch(MODELS_DEV_URL, {\n\t\tsignal: AbortSignal.timeout(10_000),\n\t});\n\n\tif (!res.ok) {\n\t\tthrow new Error(`Failed to fetch models.dev: ${res.status} ${res.statusText}`);\n\t}\n\n\tconst json = await res.json();\n\tconst parsed = ModelsDevDataSchema.safeParse(json);\n\tif (!parsed.success) {\n\t\tthrow new Error(`Invalid models.dev response: ${parsed.error.message}`);\n\t}\n\tcachedData = parsed.data;\n\tcacheTime = now;\n\treturn cachedData;\n}\n\n/**\n * List all available providers from models.dev\n */\nexport async function listProviders(): Promise<ProviderInfo[]> {\n\tconst data = await fetchModelsDevData();\n\n\treturn Object.values(data)\n\t\t.map((p) => ({\n\t\t\tid: p.id,\n\t\t\tname: p.name,\n\t\t\tenv: p.env ?? [],\n\t\t}))\n\t\t.sort((a, b) => a.name.localeCompare(b.name));\n}\n\n/**\n * Get a specific provider with all its models\n */\nexport async function getProvider(providerId: string): Promise<ProviderWithModels | null> {\n\tconst data = await fetchModelsDevData();\n\tconst provider = data[providerId];\n\n\tif (!provider) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tid: provider.id,\n\t\tname: provider.name,\n\t\tenv: provider.env ?? [],\n\t\tmodels: Object.values(provider.models)\n\t\t\t.filter((m) => m.status !== \"deprecated\")\n\t\t\t.map((m) => ({\n\t\t\t\tid: m.id,\n\t\t\t\tname: m.name,\n\t\t\t\treasoning: m.reasoning ?? false,\n\t\t\t\texperimental: m.experimental,\n\t\t\t\tstatus: m.status,\n\t\t\t}))\n\t\t\t.sort((a, b) => a.name.localeCompare(b.name)),\n\t};\n}\n\n/**\n * Get all providers with their models\n */\nexport async function listProvidersWithModels(): Promise<ProviderWithModels[]> {\n\tconst data = await fetchModelsDevData();\n\n\treturn Object.values(data)\n\t\t.map((p) => ({\n\t\t\tid: p.id,\n\t\t\tname: p.name,\n\t\t\tenv: p.env ?? [],\n\t\t\tmodels: Object.values(p.models)\n\t\t\t\t.filter((m) => m.status !== \"deprecated\")\n\t\t\t\t.map((m) => ({\n\t\t\t\t\tid: m.id,\n\t\t\t\t\tname: m.name,\n\t\t\t\t\treasoning: m.reasoning ?? false,\n\t\t\t\t\texperimental: m.experimental,\n\t\t\t\t\tstatus: m.status,\n\t\t\t\t}))\n\t\t\t\t.sort((a, b) => a.name.localeCompare(b.name)),\n\t\t}))\n\t\t.sort((a, b) => a.name.localeCompare(b.name));\n}\n\n/**\n * Validate that a provider/model combination exists\n */\nexport async function validateProviderModel(\n\tproviderId: string,\n\tmodelId: string,\n): Promise<{ valid: boolean; error?: string }> {\n\tconst provider = await getProvider(providerId);\n\n\tif (!provider) {\n\t\tconst providers = await listProviders();\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\terror: `Provider \"${providerId}\" not found. Available: ${providers\n\t\t\t\t.slice(0, 10)\n\t\t\t\t.map((p) => p.id)\n\t\t\t\t.join(\", \")}${providers.length > 10 ? \"...\" : \"\"}`,\n\t\t};\n\t}\n\n\tconst model = provider.models.find((m) => m.id === modelId);\n\tif (!model) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\terror: `Model \"${modelId}\" not found for provider \"${providerId}\". Available: ${provider.models\n\t\t\t\t.slice(0, 10)\n\t\t\t\t.map((m) => m.id)\n\t\t\t\t.join(\", \")}${provider.models.length > 10 ? \"...\" : \"\"}`,\n\t\t};\n\t}\n\n\treturn { valid: true };\n}\n","/**\n * Installation utilities for upgrade/uninstall commands\n */\n\nimport { execSync, spawn } from \"node:child_process\";\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { NpmPackageResponseSchema } from \"@offworld/types\";\nimport { VERSION } from \"./constants.js\";\n\nconst GITHUB_REPO = \"oscabriel/offworld\";\nconst NPM_PACKAGE = \"offworld\";\n\nexport type InstallMethod = \"curl\" | \"npm\" | \"pnpm\" | \"bun\" | \"brew\" | \"unknown\";\n\n/**\n * Detect how offworld was installed\n */\nexport function detectInstallMethod(): InstallMethod {\n\tconst execPath = process.execPath;\n\n\tif (execPath.includes(\".local/bin\")) return \"curl\";\n\n\tconst checks: Array<{ name: InstallMethod; test: () => boolean }> = [\n\t\t{\n\t\t\tname: \"npm\",\n\t\t\ttest: () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = execSync(\"npm list -g --depth=0 2>/dev/null\", {\n\t\t\t\t\t\tencoding: \"utf-8\",\n\t\t\t\t\t});\n\t\t\t\t\treturn result.includes(NPM_PACKAGE);\n\t\t\t\t} catch {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"pnpm\",\n\t\t\ttest: () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = execSync(\"pnpm list -g --depth=0 2>/dev/null\", {\n\t\t\t\t\t\tencoding: \"utf-8\",\n\t\t\t\t\t});\n\t\t\t\t\treturn result.includes(NPM_PACKAGE);\n\t\t\t\t} catch {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"bun\",\n\t\t\ttest: () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = execSync(\"bun pm ls -g 2>/dev/null\", {\n\t\t\t\t\t\tencoding: \"utf-8\",\n\t\t\t\t\t});\n\t\t\t\t\treturn result.includes(NPM_PACKAGE);\n\t\t\t\t} catch {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"brew\",\n\t\t\ttest: () => {\n\t\t\t\ttry {\n\t\t\t\t\texecSync(\"brew list --formula offworld 2>/dev/null\", {\n\t\t\t\t\t\tencoding: \"utf-8\",\n\t\t\t\t\t});\n\t\t\t\t\treturn true;\n\t\t\t\t} catch {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t];\n\n\tif (execPath.includes(\"npm\")) {\n\t\tconst check = checks.find((c) => c.name === \"npm\");\n\t\tif (check?.test()) return \"npm\";\n\t}\n\tif (execPath.includes(\"pnpm\")) {\n\t\tconst check = checks.find((c) => c.name === \"pnpm\");\n\t\tif (check?.test()) return \"pnpm\";\n\t}\n\tif (execPath.includes(\"bun\")) {\n\t\tconst check = checks.find((c) => c.name === \"bun\");\n\t\tif (check?.test()) return \"bun\";\n\t}\n\tif (execPath.includes(\"Cellar\") || execPath.includes(\"homebrew\")) {\n\t\tconst check = checks.find((c) => c.name === \"brew\");\n\t\tif (check?.test()) return \"brew\";\n\t}\n\n\tfor (const check of checks) {\n\t\tif (check.test()) return check.name;\n\t}\n\n\treturn \"unknown\";\n}\n\n/**\n * Get current installed version\n */\nexport function getCurrentVersion(): string {\n\treturn VERSION;\n}\n\n/**\n * Fetch latest version from appropriate source\n */\nexport async function fetchLatestVersion(method?: InstallMethod): Promise<string | null> {\n\tconst installMethod = method ?? detectInstallMethod();\n\n\ttry {\n\t\tif (installMethod === \"npm\" || installMethod === \"pnpm\" || installMethod === \"bun\") {\n\t\t\tconst response = await fetch(`https://registry.npmjs.org/${NPM_PACKAGE}/latest`);\n\t\t\tif (!response.ok) return null;\n\t\t\tconst json = await response.json();\n\t\t\tconst result = NpmPackageResponseSchema.safeParse(json);\n\t\t\tif (!result.success) return null;\n\t\t\treturn result.data.version ?? null;\n\t\t}\n\n\t\tconst response = await fetch(`https://api.github.com/repos/${GITHUB_REPO}/releases/latest`, {\n\t\t\theaders: {\n\t\t\t\tAccept: \"application/vnd.github.v3+json\",\n\t\t\t\t\"User-Agent\": \"offworld-cli\",\n\t\t\t},\n\t\t});\n\t\tif (!response.ok) return null;\n\t\tconst json = await response.json();\n\t\tconst tagName =\n\t\t\ttypeof json === \"object\" && json !== null && \"tag_name\" in json\n\t\t\t\t? String(json.tag_name)\n\t\t\t\t: null;\n\t\treturn tagName?.replace(/^v/, \"\") ?? null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Execute upgrade for given method\n */\nexport function executeUpgrade(method: InstallMethod, version: string): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tlet cmd: string;\n\t\tlet args: string[];\n\n\t\tswitch (method) {\n\t\t\tcase \"curl\":\n\t\t\t\tcmd = \"bash\";\n\t\t\t\targs = [\"-c\", `curl -fsSL https://offworld.sh/install | VERSION=${version} bash`];\n\t\t\t\tbreak;\n\t\t\tcase \"npm\":\n\t\t\t\tcmd = \"npm\";\n\t\t\t\targs = [\"install\", \"-g\", `${NPM_PACKAGE}@${version}`];\n\t\t\t\tbreak;\n\t\t\tcase \"pnpm\":\n\t\t\t\tcmd = \"pnpm\";\n\t\t\t\targs = [\"install\", \"-g\", `${NPM_PACKAGE}@${version}`];\n\t\t\t\tbreak;\n\t\t\tcase \"bun\":\n\t\t\t\tcmd = \"bun\";\n\t\t\t\targs = [\"install\", \"-g\", `${NPM_PACKAGE}@${version}`];\n\t\t\t\tbreak;\n\t\t\tcase \"brew\":\n\t\t\t\tcmd = \"brew\";\n\t\t\t\targs = [\"upgrade\", \"offworld\"];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treject(new Error(`Cannot upgrade: unknown installation method`));\n\t\t\t\treturn;\n\t\t}\n\n\t\tconst proc = spawn(cmd, args, { stdio: \"inherit\" });\n\t\tproc.on(\"close\", (code) => {\n\t\t\tif (code === 0) resolve();\n\t\t\telse reject(new Error(`Upgrade failed with exit code ${code}`));\n\t\t});\n\t\tproc.on(\"error\", reject);\n\t});\n}\n\n/**\n * Execute uninstall for given method\n */\nexport function executeUninstall(method: InstallMethod): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tlet cmd: string;\n\t\tlet args: string[];\n\n\t\tswitch (method) {\n\t\t\tcase \"curl\":\n\t\t\t\ttry {\n\t\t\t\t\tconst binPath = join(homedir(), \".local\", \"bin\", \"ow\");\n\t\t\t\t\tif (existsSync(binPath)) {\n\t\t\t\t\t\texecSync(`rm -f \"${binPath}\"`, { stdio: \"inherit\" });\n\t\t\t\t\t}\n\t\t\t\t\tresolve();\n\t\t\t\t} catch (err) {\n\t\t\t\t\treject(err);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\tcase \"npm\":\n\t\t\t\tcmd = \"npm\";\n\t\t\t\targs = [\"uninstall\", \"-g\", NPM_PACKAGE];\n\t\t\t\tbreak;\n\t\t\tcase \"pnpm\":\n\t\t\t\tcmd = \"pnpm\";\n\t\t\t\targs = [\"uninstall\", \"-g\", NPM_PACKAGE];\n\t\t\t\tbreak;\n\t\t\tcase \"bun\":\n\t\t\t\tcmd = \"bun\";\n\t\t\t\targs = [\"remove\", \"-g\", NPM_PACKAGE];\n\t\t\t\tbreak;\n\t\t\tcase \"brew\":\n\t\t\t\tcmd = \"brew\";\n\t\t\t\targs = [\"uninstall\", \"offworld\"];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treject(new Error(`Cannot uninstall: unknown installation method`));\n\t\t\t\treturn;\n\t\t}\n\n\t\tconst proc = spawn(cmd, args, { stdio: \"inherit\" });\n\t\tproc.on(\"close\", (code) => {\n\t\t\tif (code === 0) resolve();\n\t\t\telse reject(new Error(`Uninstall failed with exit code ${code}`));\n\t\t});\n\t\tproc.on(\"error\", reject);\n\t});\n}\n\n/**\n * Get shell config files to clean\n */\nexport function getShellConfigFiles(): string[] {\n\tconst home = homedir();\n\tconst configs: string[] = [];\n\n\tconst candidates = [\n\t\t\".bashrc\",\n\t\t\".bash_profile\",\n\t\t\".profile\",\n\t\t\".zshrc\",\n\t\t\".zshenv\",\n\t\t\".config/fish/config.fish\",\n\t];\n\n\tfor (const file of candidates) {\n\t\tconst path = join(home, file);\n\t\tif (existsSync(path)) {\n\t\t\tconfigs.push(path);\n\t\t}\n\t}\n\n\treturn configs;\n}\n\n/**\n * Clean PATH entries from shell config\n */\nexport function cleanShellConfig(filePath: string): boolean {\n\ttry {\n\t\tconst content = readFileSync(filePath, \"utf-8\");\n\t\tconst lines = content.split(\"\\n\");\n\t\tconst filtered: string[] = [];\n\t\tlet modified = false;\n\n\t\tfor (const line of lines) {\n\t\t\tconst trimmed = line.trim();\n\t\t\tif (\n\t\t\t\ttrimmed.includes(\".local/bin\") &&\n\t\t\t\t(trimmed.startsWith(\"export PATH=\") || trimmed.startsWith(\"fish_add_path\"))\n\t\t\t) {\n\t\t\t\tif (trimmed.includes(\"# offworld\") || trimmed === 'export PATH=\"$HOME/.local/bin:$PATH\"') {\n\t\t\t\t\tmodified = true;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiltered.push(line);\n\t\t}\n\n\t\tif (modified) {\n\t\t\twriteFileSync(filePath, filtered.join(\"\\n\"), \"utf-8\");\n\t\t}\n\n\t\treturn modified;\n\t} catch {\n\t\treturn false;\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["GlobalMapSchema","ProjectMapSchema","RepoNotFoundError"],"sources":["../src/constants.ts","../src/paths.ts","../src/config.ts","../src/repo-source.ts","../src/index-manager.ts","../src/map.ts","../src/clone.ts","../src/ai/errors.ts","../src/ai/stream/types.ts","../src/ai/stream/accumulator.ts","../src/ai/stream/transformer.ts","../src/ai/opencode.ts","../src/sync.ts","../src/auth.ts","../src/agents.ts","../src/generate.ts","../src/manifest.ts","../src/dep-mappings.ts","../src/reference-matcher.ts","../src/agents-md.ts","../src/repo-manager.ts","../src/models.ts","../src/installation.ts"],"sourcesContent":["/**\n * SDK Constants\n */\n\n/** SDK version - must match package.json */\nexport const VERSION = \"0.1.7\";\n\n/**\n * Default patterns to ignore when scanning repositories.\n * Includes directories, binary files, IDE configs, and build outputs.\n */\nexport const DEFAULT_IGNORE_PATTERNS = [\n\t\".git\",\n\t\".git/**\",\n\t\".svn\",\n\t\".hg\",\n\n\t\"node_modules\",\n\t\"node_modules/**\",\n\t\"vendor\",\n\t\"vendor/**\",\n\t\".pnpm\",\n\t\".yarn\",\n\n\t\"dist\",\n\t\"dist/**\",\n\t\"build\",\n\t\"build/**\",\n\t\"out\",\n\t\"out/**\",\n\t\".next\",\n\t\".nuxt\",\n\t\".output\",\n\t\"target\",\n\t\"__pycache__\",\n\t\"*.pyc\",\n\n\t\".vscode\",\n\t\".vscode/**\",\n\t\".idea\",\n\t\".idea/**\",\n\t\"*.swp\",\n\t\"*.swo\",\n\t\".DS_Store\",\n\n\t\"*.jpg\",\n\t\"*.jpeg\",\n\t\"*.png\",\n\t\"*.gif\",\n\t\"*.ico\",\n\t\"*.webp\",\n\t\"*.svg\",\n\t\"*.bmp\",\n\t\"*.tiff\",\n\t\"*.mp4\",\n\t\"*.webm\",\n\t\"*.mov\",\n\t\"*.avi\",\n\t\"*.mkv\",\n\t\"*.mp3\",\n\t\"*.wav\",\n\t\"*.flac\",\n\t\"*.ogg\",\n\t\"*.pdf\",\n\t\"*.zip\",\n\t\"*.tar\",\n\t\"*.gz\",\n\t\"*.rar\",\n\t\"*.7z\",\n\t\"*.exe\",\n\t\"*.dll\",\n\t\"*.so\",\n\t\"*.dylib\",\n\t\"*.bin\",\n\t\"*.wasm\",\n\t\"*.woff\",\n\t\"*.woff2\",\n\t\"*.ttf\",\n\t\"*.eot\",\n\t\"*.otf\",\n\n\t\"package-lock.json\",\n\t\"yarn.lock\",\n\t\"pnpm-lock.yaml\",\n\t\"bun.lockb\",\n\t\"Cargo.lock\",\n\t\"Gemfile.lock\",\n\t\"poetry.lock\",\n\t\"composer.lock\",\n\t\"go.sum\",\n\n\t\"coverage\",\n\t\"coverage/**\",\n\t\".nyc_output\",\n\t\".coverage\",\n\t\"htmlcov\",\n\n\t\"*.log\",\n\t\"logs\",\n\t\"tmp\",\n\t\"temp\",\n\t\".tmp\",\n\t\".temp\",\n\t\".cache\",\n\n\t\".env\",\n\t\".env.*\",\n\t\"*.pem\",\n\t\"*.key\",\n] as const;\n","/**\n * XDG-based directory paths for offworld CLI\n * Uses xdg-basedir package for cross-platform compatibility (Linux/macOS)\n */\n\nimport { xdgConfig, xdgData, xdgState } from \"xdg-basedir\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\nconst APP_NAME = \"offworld\";\n\n/**\n * Main namespace for all XDG-compliant paths\n */\nexport const Paths = {\n\t/**\n\t * XDG_CONFIG_HOME/offworld\n\t * Fallback: ~/.config/offworld\n\t */\n\tget config(): string {\n\t\treturn join(xdgConfig ?? join(homedir(), \".config\"), APP_NAME);\n\t},\n\n\t/**\n\t * XDG_DATA_HOME/offworld\n\t * Fallback: ~/.local/share/offworld\n\t */\n\tget data(): string {\n\t\treturn join(xdgData ?? join(homedir(), \".local\", \"share\"), APP_NAME);\n\t},\n\n\t/**\n\t * XDG_STATE_HOME/offworld\n\t * Fallback: ~/.local/state/offworld\n\t */\n\tget state(): string {\n\t\treturn join(xdgState ?? join(homedir(), \".local\", \"state\"), APP_NAME);\n\t},\n\n\t/**\n\t * Configuration file path: ~/.config/offworld/offworld.json\n\t */\n\tget configFile(): string {\n\t\treturn join(this.config, \"offworld.json\");\n\t},\n\n\t/**\n\t * Auth file path: ~/.local/share/offworld/auth.json\n\t */\n\tget authFile(): string {\n\t\treturn join(this.data, \"auth.json\");\n\t},\n\n\t/**\n\t * Meta directory: ~/.local/share/offworld/meta\n\t */\n\tget metaDir(): string {\n\t\treturn join(this.data, \"meta\");\n\t},\n\n\t/**\n\t * Default repo root: ~/ow\n\t */\n\tget defaultRepoRoot(): string {\n\t\treturn join(homedir(), \"ow\");\n\t},\n\n\t/**\n\t * Offworld single-skill directory: ~/.local/share/offworld/skill/offworld\n\t */\n\tget offworldSkillDir(): string {\n\t\treturn join(this.data, \"skill\", \"offworld\");\n\t},\n\n\t/**\n\t * Offworld references directory: ~/.local/share/offworld/skill/offworld/references\n\t */\n\tget offworldReferencesDir(): string {\n\t\treturn join(this.offworldSkillDir, \"references\");\n\t},\n\n\t/**\n\t * Offworld assets directory: ~/.local/share/offworld/skill/offworld/assets\n\t */\n\tget offworldAssetsDir(): string {\n\t\treturn join(this.offworldSkillDir, \"assets\");\n\t},\n\n\t/**\n\t * Global map path: ~/.local/share/offworld/skill/offworld/assets/map.json\n\t */\n\tget offworldGlobalMapPath(): string {\n\t\treturn join(this.offworldAssetsDir, \"map.json\");\n\t},\n};\n\n/**\n * Expands ~ to user's home directory (for backward compatibility)\n */\nexport function expandTilde(path: string): string {\n\tif (path.startsWith(\"~/\")) {\n\t\treturn join(homedir(), path.slice(2));\n\t}\n\treturn path;\n}\n","/**\n * Config utilities for path management and configuration loading\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { ConfigSchema } from \"@offworld/types\";\nimport type { Config } from \"@offworld/types\";\nimport { Paths, expandTilde } from \"./paths\";\n\n/**\n * Returns the repository root directory.\n * Uses configured repoRoot or defaults to ~/ow\n */\nexport function getMetaRoot(): string {\n\treturn Paths.data;\n}\n\nexport function getRepoRoot(config?: Config): string {\n\tconst root = config?.repoRoot ?? Paths.defaultRepoRoot;\n\treturn expandTilde(root);\n}\n\n/**\n * Returns the path for a specific repository.\n * Format: {repoRoot}/{provider}/{owner}/{repo}\n *\n * @param fullName - The repo identifier in \"owner/repo\" format\n * @param provider - Git provider (defaults to \"github\")\n * @param config - Optional config for custom repoRoot\n */\nexport function getRepoPath(\n\tfullName: string,\n\tprovider: \"github\" | \"gitlab\" | \"bitbucket\" = \"github\",\n\tconfig?: Config,\n): string {\n\tconst root = getRepoRoot(config);\n\tconst [owner, repo] = fullName.split(\"/\");\n\tif (!owner || !repo) {\n\t\tthrow new Error(`Invalid fullName format: ${fullName}. Expected \"owner/repo\"`);\n\t}\n\treturn join(root, provider, owner, repo);\n}\n\n/**\n * Convert owner/repo format to meta directory name.\n * Collapses owner==repo (e.g., better-auth/better-auth -> better-auth)\n */\nexport function toMetaDirName(repoName: string): string {\n\tif (repoName.includes(\"/\")) {\n\t\tconst parts = repoName.split(\"/\");\n\t\tconst owner = parts[0];\n\t\tconst repo = parts[1];\n\t\tif (!owner || !repo) {\n\t\t\treturn repoName;\n\t\t}\n\t\tif (owner === repo) {\n\t\t\treturn repo;\n\t\t}\n\t\treturn `${owner}-${repo}`;\n\t}\n\treturn repoName;\n}\n\n/**\n * Convert owner/repo format to reference filename.\n * Collapses redundant owner/repo pairs by checking if repo name is contained in owner:\n * - honojs/hono -> hono.md (hono is in honojs)\n * - get-convex/convex-backend -> convex-backend.md (convex is in get-convex)\n * - tanstack/query -> tanstack-query.md (query is not in tanstack)\n */\nexport function toReferenceFileName(repoName: string): string {\n\tif (repoName.includes(\"/\")) {\n\t\tconst parts = repoName.split(\"/\");\n\t\tconst owner = parts[0];\n\t\tconst repo = parts[1];\n\t\tif (!owner || !repo) {\n\t\t\treturn `${repoName.toLowerCase()}.md`;\n\t\t}\n\t\tconst ownerLower = owner.toLowerCase();\n\t\tconst repoLower = repo.toLowerCase();\n\n\t\tconst repoParts = repoLower.split(\"-\");\n\t\tconst significantPart = repoParts.find((part) => part.length >= 3 && ownerLower.includes(part));\n\n\t\tif (significantPart || ownerLower === repoLower) {\n\t\t\treturn `${repoLower}.md`;\n\t\t}\n\n\t\treturn `${ownerLower}-${repoLower}.md`;\n\t}\n\treturn `${repoName.toLowerCase()}.md`;\n}\n\nexport function toReferenceName(repoName: string): string {\n\treturn toReferenceFileName(repoName).replace(/\\.md$/, \"\");\n}\n\nexport function getReferencePath(fullName: string): string {\n\treturn join(Paths.offworldReferencesDir, toReferenceFileName(fullName));\n}\n\nexport function getMetaPath(fullName: string): string {\n\treturn join(Paths.data, \"meta\", toMetaDirName(fullName));\n}\n\n/**\n * Returns the path to the configuration file\n * Uses XDG Base Directory specification\n */\nexport function getConfigPath(): string {\n\treturn Paths.configFile;\n}\n\n/**\n * Loads configuration from ~/.config/offworld/offworld.json\n * Returns defaults if file doesn't exist\n */\nexport function loadConfig(): Config {\n\tconst configPath = getConfigPath();\n\n\tif (!existsSync(configPath)) {\n\t\treturn ConfigSchema.parse({});\n\t}\n\n\ttry {\n\t\tconst content = readFileSync(configPath, \"utf-8\");\n\t\tconst data = JSON.parse(content);\n\t\treturn ConfigSchema.parse(data);\n\t} catch {\n\t\treturn ConfigSchema.parse({});\n\t}\n}\n\n/**\n * Saves configuration to ~/.config/offworld/offworld.json\n * Creates directory if it doesn't exist\n * Merges with existing config\n */\nexport function saveConfig(updates: Partial<Config>): Config {\n\tconst configPath = getConfigPath();\n\tconst configDir = dirname(configPath);\n\n\tif (!existsSync(configDir)) {\n\t\tmkdirSync(configDir, { recursive: true });\n\t}\n\n\tconst existing = loadConfig();\n\tconst merged = { ...existing, ...updates };\n\n\tconst validated = ConfigSchema.parse(merged);\n\n\twriteFileSync(configPath, JSON.stringify(validated, null, 2), \"utf-8\");\n\n\treturn validated;\n}\n","/**\n * Repository source parsing utilities\n */\n\nimport { createHash } from \"node:crypto\";\nimport { existsSync, statSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { basename } from \"node:path\";\nimport type { GitProvider, LocalRepoSource, RemoteRepoSource, RepoSource } from \"@offworld/types\";\nimport { toReferenceFileName } from \"./config.js\";\nimport { expandTilde } from \"./paths.js\";\n\nexport class RepoSourceError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"RepoSourceError\";\n\t}\n}\n\nexport class PathNotFoundError extends RepoSourceError {\n\tconstructor(path: string) {\n\t\tsuper(`Path does not exist: ${path}`);\n\t\tthis.name = \"PathNotFoundError\";\n\t}\n}\n\nexport class NotGitRepoError extends RepoSourceError {\n\tconstructor(path: string) {\n\t\tsuper(`Directory is not a git repository: ${path}`);\n\t\tthis.name = \"NotGitRepoError\";\n\t}\n}\n\nconst PROVIDER_HOSTS: Record<string, GitProvider> = {\n\t\"github.com\": \"github\",\n\t\"gitlab.com\": \"gitlab\",\n\t\"bitbucket.org\": \"bitbucket\",\n};\n\nconst HTTPS_URL_REGEX =\n\t/^https?:\\/\\/(github\\.com|gitlab\\.com|bitbucket\\.org)\\/([^/]+)\\/([^/]+?)(?:\\.git)?$/;\nconst SSH_URL_REGEX = /^git@(github\\.com|gitlab\\.com|bitbucket\\.org):([^/]+)\\/([^/]+?)(?:\\.git)?$/;\nconst SHORT_FORMAT_REGEX = /^([^/:@]+)\\/([^/:@]+)$/;\n\n/**\n * Generates a short hash of a path for local repo identification\n */\nfunction hashPath(path: string): string {\n\treturn createHash(\"sha256\").update(path).digest(\"hex\").slice(0, 12);\n}\n\n/**\n * Builds a clone URL for a remote repository\n */\nfunction buildCloneUrl(provider: GitProvider, owner: string, repo: string): string {\n\tconst hosts: Record<GitProvider, string> = {\n\t\tgithub: \"github.com\",\n\t\tgitlab: \"gitlab.com\",\n\t\tbitbucket: \"bitbucket.org\",\n\t};\n\treturn `https://${hosts[provider]}/${owner}/${repo}.git`;\n}\n\n/**\n * Parses a remote repository from HTTPS URL format\n */\nfunction parseHttpsUrl(input: string): RemoteRepoSource | null {\n\tconst match = input.match(HTTPS_URL_REGEX);\n\tif (!match) return null;\n\n\tconst [, host, owner, repo] = match;\n\tif (!host || !owner || !repo) return null;\n\n\tconst provider = PROVIDER_HOSTS[host];\n\tif (!provider) return null;\n\n\tconst ownerLower = owner.toLowerCase();\n\tconst repoLower = repo.toLowerCase();\n\treturn {\n\t\ttype: \"remote\",\n\t\tprovider,\n\t\towner: ownerLower,\n\t\trepo: repoLower,\n\t\tfullName: `${ownerLower}/${repoLower}`,\n\t\tqualifiedName: `${host}:${ownerLower}/${repoLower}`,\n\t\tcloneUrl: buildCloneUrl(provider, ownerLower, repoLower),\n\t};\n}\n\n/**\n * Parses a remote repository from SSH URL format\n */\nfunction parseSshUrl(input: string): RemoteRepoSource | null {\n\tconst match = input.match(SSH_URL_REGEX);\n\tif (!match) return null;\n\n\tconst [, host, owner, repo] = match;\n\tif (!host || !owner || !repo) return null;\n\n\tconst provider = PROVIDER_HOSTS[host];\n\tif (!provider) return null;\n\n\tconst ownerLower = owner.toLowerCase();\n\tconst repoLower = repo.toLowerCase();\n\treturn {\n\t\ttype: \"remote\",\n\t\tprovider,\n\t\towner: ownerLower,\n\t\trepo: repoLower,\n\t\tfullName: `${ownerLower}/${repoLower}`,\n\t\tqualifiedName: `${host}:${ownerLower}/${repoLower}`,\n\t\tcloneUrl: buildCloneUrl(provider, ownerLower, repoLower),\n\t};\n}\n\n/**\n * Parses a remote repository from short format (owner/repo)\n * Defaults to GitHub as provider\n */\nfunction parseShortFormat(input: string): RemoteRepoSource | null {\n\tconst match = input.match(SHORT_FORMAT_REGEX);\n\tif (!match) return null;\n\n\tconst [, owner, repo] = match;\n\tif (!owner || !repo) return null;\n\n\tconst provider: GitProvider = \"github\";\n\tconst host = \"github.com\";\n\n\tconst ownerLower = owner.toLowerCase();\n\tconst repoLower = repo.toLowerCase();\n\treturn {\n\t\ttype: \"remote\",\n\t\tprovider,\n\t\towner: ownerLower,\n\t\trepo: repoLower,\n\t\tfullName: `${ownerLower}/${repoLower}`,\n\t\tqualifiedName: `${host}:${ownerLower}/${repoLower}`,\n\t\tcloneUrl: buildCloneUrl(provider, ownerLower, repoLower),\n\t};\n}\n\n/**\n * Parses a local repository path\n * Validates that the path exists and contains a .git directory\n */\nfunction parseLocalPath(input: string): LocalRepoSource {\n\tconst absolutePath = resolve(expandTilde(input));\n\n\tif (!existsSync(absolutePath)) {\n\t\tthrow new PathNotFoundError(absolutePath);\n\t}\n\n\tconst stats = statSync(absolutePath);\n\tif (!stats.isDirectory()) {\n\t\tthrow new RepoSourceError(`Path is not a directory: ${absolutePath}`);\n\t}\n\n\tconst gitPath = resolve(absolutePath, \".git\");\n\tif (!existsSync(gitPath)) {\n\t\tthrow new NotGitRepoError(absolutePath);\n\t}\n\n\tconst name = basename(absolutePath);\n\tconst hash = hashPath(absolutePath);\n\n\treturn {\n\t\ttype: \"local\",\n\t\tpath: absolutePath,\n\t\tname,\n\t\tqualifiedName: `local:${hash}`,\n\t};\n}\n\n/**\n * Determines if input looks like a local path\n */\nfunction isLocalPath(input: string): boolean {\n\treturn input.startsWith(\".\") || input.startsWith(\"/\") || input.startsWith(\"~\");\n}\n\n/**\n * Parses a repository input and returns a structured RepoSource\n *\n * Supported formats:\n * - owner/repo (short format, defaults to GitHub)\n * - https://github.com/owner/repo\n * - https://gitlab.com/owner/repo\n * - https://bitbucket.org/owner/repo\n * - git@github.com:owner/repo.git (SSH format)\n * - . (current directory as local repo)\n * - /absolute/path (local repo)\n *\n * @throws PathNotFoundError if local path doesn't exist\n * @throws NotGitRepoError if local path is not a git repository\n * @throws RepoSourceError for other parsing failures\n */\nexport function parseRepoInput(input: string): RepoSource {\n\tconst trimmed = input.trim();\n\n\tconst httpsResult = parseHttpsUrl(trimmed);\n\tif (httpsResult) return httpsResult;\n\n\tconst sshResult = parseSshUrl(trimmed);\n\tif (sshResult) return sshResult;\n\n\tif (isLocalPath(trimmed)) {\n\t\treturn parseLocalPath(trimmed);\n\t}\n\n\tconst shortResult = parseShortFormat(trimmed);\n\tif (shortResult) return shortResult;\n\n\tthrow new RepoSourceError(\n\t\t`Unable to parse repository input: ${input}. ` +\n\t\t\t\"Expected formats: owner/repo, https://github.com/owner/repo, git@github.com:owner/repo.git, or a local path\",\n\t);\n}\n\nexport function getReferenceFileNameForSource(source: RepoSource): string {\n\tif (source.type === \"remote\") {\n\t\treturn toReferenceFileName(source.fullName);\n\t}\n\treturn toReferenceFileName(source.name);\n}\n","/**\n * Map manager for global and project maps\n *\n * Manages:\n * - Global map: ~/.local/share/offworld/skill/offworld/assets/map.json\n * - Project map: ./.offworld/map.json\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport {\n\tGlobalMapSchema,\n\tProjectMapSchema,\n\ttype GlobalMap,\n\ttype GlobalMapRepoEntry,\n\ttype ProjectMap,\n\ttype ProjectMapRepoEntry,\n} from \"@offworld/types\";\nimport { Paths } from \"./paths.js\";\n\n/**\n * Reads the global map from ~/.local/share/offworld/skill/offworld/assets/map.json\n * Returns empty map if file doesn't exist or is invalid\n */\nexport function readGlobalMap(): GlobalMap {\n\tconst mapPath = Paths.offworldGlobalMapPath;\n\n\tif (!existsSync(mapPath)) {\n\t\treturn { repos: {} };\n\t}\n\n\ttry {\n\t\tconst content = readFileSync(mapPath, \"utf-8\");\n\t\tconst data = JSON.parse(content);\n\t\treturn GlobalMapSchema.parse(data);\n\t} catch {\n\t\treturn { repos: {} };\n\t}\n}\n\n/**\n * Writes the global map to ~/.local/share/offworld/skill/offworld/assets/map.json\n * Creates directory if it doesn't exist\n */\nexport function writeGlobalMap(map: GlobalMap): void {\n\tconst mapPath = Paths.offworldGlobalMapPath;\n\tconst mapDir = dirname(mapPath);\n\n\tif (!existsSync(mapDir)) {\n\t\tmkdirSync(mapDir, { recursive: true });\n\t}\n\n\tconst validated = GlobalMapSchema.parse(map);\n\twriteFileSync(mapPath, JSON.stringify(validated, null, 2), \"utf-8\");\n}\n\n/**\n * Adds or updates a repo entry in the global map\n *\n * @param qualifiedName - The qualified repo name (owner/repo)\n * @param entry - The map entry to add/update\n */\nexport function upsertGlobalMapEntry(qualifiedName: string, entry: GlobalMapRepoEntry): void {\n\tconst map = readGlobalMap();\n\tmap.repos[qualifiedName] = entry;\n\twriteGlobalMap(map);\n}\n\n/**\n * Removes a repo entry from the global map\n *\n * @param qualifiedName - The qualified repo name (owner/repo)\n * @returns true if repo was removed, false if not found\n */\nexport function removeGlobalMapEntry(qualifiedName: string): boolean {\n\tconst map = readGlobalMap();\n\n\tif (!(qualifiedName in map.repos)) {\n\t\treturn false;\n\t}\n\n\tdelete map.repos[qualifiedName];\n\twriteGlobalMap(map);\n\treturn true;\n}\n\n/**\n * Writes a project map to ./.offworld/map.json\n *\n * @param projectRoot - Absolute path to project root\n * @param entries - Map of qualified repo names to project map entries\n */\nexport function writeProjectMap(\n\tprojectRoot: string,\n\tentries: Record<string, ProjectMapRepoEntry>,\n): void {\n\tconst mapPath = join(projectRoot, \".offworld\", \"map.json\");\n\tconst mapDir = dirname(mapPath);\n\n\tif (!existsSync(mapDir)) {\n\t\tmkdirSync(mapDir, { recursive: true });\n\t}\n\n\tconst projectMap: ProjectMap = {\n\t\tversion: 1,\n\t\tscope: \"project\",\n\t\tglobalMapPath: Paths.offworldGlobalMapPath,\n\t\trepos: entries,\n\t};\n\n\tconst validated = ProjectMapSchema.parse(projectMap);\n\twriteFileSync(mapPath, JSON.stringify(validated, null, 2), \"utf-8\");\n}\n","/**\n * Map query helpers for fast routing without reading full map.json\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport type {\n\tGlobalMap,\n\tGlobalMapRepoEntry,\n\tProjectMap,\n\tProjectMapRepoEntry,\n} from \"@offworld/types\";\nimport { GlobalMapSchema, ProjectMapSchema } from \"@offworld/types/schemas\";\nimport { Paths } from \"./paths.js\";\n\nexport interface MapEntry {\n\tscope: \"project\" | \"global\";\n\tqualifiedName: string;\n\tentry: GlobalMapRepoEntry | ProjectMapRepoEntry;\n}\n\nexport interface SearchResult {\n\tqualifiedName: string;\n\tfullName: string;\n\tlocalPath: string;\n\tprimary: string;\n\tkeywords: string[];\n\tscore: number;\n}\n\nexport interface GetMapEntryOptions {\n\tpreferProject?: boolean;\n\tcwd?: string;\n}\n\nexport interface SearchMapOptions {\n\tlimit?: number;\n\tcwd?: string;\n}\n\nfunction readGlobalMapSafe(): GlobalMap | null {\n\tconst mapPath = Paths.offworldGlobalMapPath;\n\tif (!existsSync(mapPath)) return null;\n\n\ttry {\n\t\tconst content = readFileSync(mapPath, \"utf-8\");\n\t\treturn GlobalMapSchema.parse(JSON.parse(content));\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction readProjectMapSafe(cwd: string): ProjectMap | null {\n\tconst mapPath = resolve(cwd, \".offworld/map.json\");\n\tif (!existsSync(mapPath)) return null;\n\n\ttry {\n\t\tconst content = readFileSync(mapPath, \"utf-8\");\n\t\treturn ProjectMapSchema.parse(JSON.parse(content));\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Normalize input to match against repo keys.\n * Accepts: github.com:owner/repo, owner/repo, repo\n */\nfunction normalizeInput(input: string): { provider?: string; fullName: string; repoName: string } {\n\tconst trimmed = input.trim().toLowerCase();\n\n\tif (trimmed.includes(\":\")) {\n\t\tconst parts = trimmed.split(\":\", 2);\n\t\tconst provider = parts[0];\n\t\tconst fullName = parts[1] ?? \"\";\n\t\tconst repoName = fullName.split(\"/\").pop() ?? fullName;\n\t\treturn { provider, fullName, repoName };\n\t}\n\n\tif (trimmed.includes(\"/\")) {\n\t\tconst repoName = trimmed.split(\"/\").pop() ?? trimmed;\n\t\treturn { fullName: trimmed, repoName };\n\t}\n\n\treturn { fullName: trimmed, repoName: trimmed };\n}\n\n/**\n * Tokenize a string for search matching.\n * Lowercase, strip @, split on /_- and whitespace.\n */\nfunction tokenize(str: string): string[] {\n\treturn str\n\t\t.toLowerCase()\n\t\t.replace(/@/g, \"\")\n\t\t.split(/[/_\\-\\s]+/)\n\t\t.filter(Boolean);\n}\n\n/**\n * Resolve an input string to a qualified repo key in a map.\n *\n * @param input - Accepts github.com:owner/repo, owner/repo, or repo name\n * @param map - A global or project map\n * @returns The matching qualified name or null\n */\nexport function resolveRepoKey(input: string, map: GlobalMap | ProjectMap): string | null {\n\tconst { provider, fullName, repoName } = normalizeInput(input);\n\tconst keys = Object.keys(map.repos);\n\n\tif (provider) {\n\t\tconst qualifiedKey = `${provider}:${fullName}`;\n\t\tif (keys.includes(qualifiedKey)) {\n\t\t\treturn qualifiedKey;\n\t\t}\n\t}\n\n\tfor (const key of keys) {\n\t\tconst keyFullName = key.includes(\":\") ? key.split(\":\")[1] : key;\n\t\tif (keyFullName?.toLowerCase() === fullName) {\n\t\t\treturn key;\n\t\t}\n\t}\n\n\tfor (const key of keys) {\n\t\tconst keyRepoName = key.split(\"/\").pop()?.toLowerCase();\n\t\tif (keyRepoName === repoName) {\n\t\t\treturn key;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Get a map entry for a repo, preferring project map if available.\n *\n * @param input - Repo identifier (github.com:owner/repo, owner/repo, or repo)\n * @param options - Options for lookup\n * @returns Entry with scope and qualified name, or null if not found\n */\nexport function getMapEntry(input: string, options: GetMapEntryOptions = {}): MapEntry | null {\n\tconst { preferProject = true, cwd = process.cwd() } = options;\n\n\tconst projectMap = preferProject ? readProjectMapSafe(cwd) : null;\n\tconst globalMap = readGlobalMapSafe();\n\n\tif (projectMap) {\n\t\tconst key = resolveRepoKey(input, projectMap);\n\t\tif (key && projectMap.repos[key]) {\n\t\t\treturn {\n\t\t\t\tscope: \"project\",\n\t\t\t\tqualifiedName: key,\n\t\t\t\tentry: projectMap.repos[key],\n\t\t\t};\n\t\t}\n\t}\n\n\tif (globalMap) {\n\t\tconst key = resolveRepoKey(input, globalMap);\n\t\tif (key && globalMap.repos[key]) {\n\t\t\treturn {\n\t\t\t\tscope: \"global\",\n\t\t\t\tqualifiedName: key,\n\t\t\t\tentry: globalMap.repos[key],\n\t\t\t};\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Search the map for repos matching a term.\n *\n * Scoring:\n * - Exact fullName match: 100\n * - Keyword hit: 50 per keyword\n * - Partial contains in fullName: 25\n * - Partial contains in keywords: 10\n *\n * @param term - Search term\n * @param options - Search options\n * @returns Sorted list of matches\n */\nexport function searchMap(term: string, options: SearchMapOptions = {}): SearchResult[] {\n\tconst { limit = 10 } = options;\n\n\tconst globalMap = readGlobalMapSafe();\n\tif (!globalMap) return [];\n\n\tconst termTokens = tokenize(term);\n\tconst termLower = term.toLowerCase();\n\tconst results: SearchResult[] = [];\n\n\tfor (const qualifiedName of Object.keys(globalMap.repos)) {\n\t\tconst entry = globalMap.repos[qualifiedName];\n\t\tif (!entry) continue;\n\n\t\tconst fullName = qualifiedName.includes(\":\")\n\t\t\t? (qualifiedName.split(\":\")[1] ?? qualifiedName)\n\t\t\t: qualifiedName;\n\t\tconst fullNameLower = fullName.toLowerCase();\n\t\tconst keywords = entry.keywords ?? [];\n\t\tconst keywordsLower = keywords.map((k) => k.toLowerCase());\n\n\t\tlet score = 0;\n\n\t\tif (fullNameLower === termLower) {\n\t\t\tscore += 100;\n\t\t}\n\n\t\tfor (const token of termTokens) {\n\t\t\tif (keywordsLower.includes(token)) {\n\t\t\t\tscore += 50;\n\t\t\t}\n\t\t}\n\n\t\tif (fullNameLower.includes(termLower) && score < 100) {\n\t\t\tscore += 25;\n\t\t}\n\n\t\tfor (const kw of keywordsLower) {\n\t\t\tif (kw.includes(termLower)) {\n\t\t\t\tscore += 10;\n\t\t\t}\n\t\t}\n\n\t\tconst fullNameTokens = tokenize(fullName);\n\t\tfor (const token of termTokens) {\n\t\t\tif (fullNameTokens.includes(token)) {\n\t\t\t\tscore += 30;\n\t\t\t}\n\t\t}\n\n\t\tif (score > 0) {\n\t\t\tresults.push({\n\t\t\t\tqualifiedName,\n\t\t\t\tfullName,\n\t\t\t\tlocalPath: entry.localPath,\n\t\t\t\tprimary: entry.primary,\n\t\t\t\tkeywords,\n\t\t\t\tscore,\n\t\t\t});\n\t\t}\n\t}\n\n\tresults.sort((a, b) => {\n\t\tif (b.score !== a.score) return b.score - a.score;\n\t\treturn a.fullName.localeCompare(b.fullName);\n\t});\n\n\treturn results.slice(0, limit);\n}\n\n/**\n * Get the project map path if it exists in cwd.\n */\nexport function getProjectMapPath(cwd: string = process.cwd()): string | null {\n\tconst mapPath = resolve(cwd, \".offworld/map.json\");\n\treturn existsSync(mapPath) ? mapPath : null;\n}\n","/**\n * Git clone and repository management utilities\n */\n\nimport { existsSync, readdirSync, rmSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { execFileSync, spawn } from \"node:child_process\";\nimport type { Config, RemoteRepoSource } from \"@offworld/types\";\nimport { getRepoPath, loadConfig, toReferenceFileName } from \"./config.js\";\nimport { readGlobalMap, upsertGlobalMapEntry, removeGlobalMapEntry } from \"./index-manager.js\";\nimport { Paths } from \"./paths.js\";\n\nexport class CloneError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"CloneError\";\n\t}\n}\n\nexport class RepoExistsError extends CloneError {\n\tconstructor(path: string) {\n\t\tsuper(`Repository already exists at: ${path}`);\n\t\tthis.name = \"RepoExistsError\";\n\t}\n}\n\nexport class RepoNotFoundError extends CloneError {\n\tconstructor(qualifiedName: string) {\n\t\tsuper(`Repository not found in index: ${qualifiedName}`);\n\t\tthis.name = \"RepoNotFoundError\";\n\t}\n}\n\nexport class GitError extends CloneError {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly command: string,\n\t\tpublic readonly exitCode: number | null,\n\t) {\n\t\tsuper(`Git command failed: ${message}`);\n\t\tthis.name = \"GitError\";\n\t}\n}\n\nexport interface CloneOptions {\n\t/** Use shallow clone (--depth 1) */\n\tshallow?: boolean;\n\t/** Clone specific branch */\n\tbranch?: string;\n\t/** Custom config for repo root path */\n\tconfig?: Config;\n\t/** Force clone even if directory exists (removes existing) */\n\tforce?: boolean;\n\t/** Use sparse checkout for large repos (only src/, lib/, packages/, docs/) */\n\tsparse?: boolean;\n}\n\nfunction execGit(args: string[], cwd?: string): string {\n\ttry {\n\t\tconst result = execFileSync(\"git\", args, {\n\t\t\tcwd,\n\t\t\tencoding: \"utf-8\",\n\t\t\tstdio: [\"pipe\", \"pipe\", \"pipe\"],\n\t\t});\n\t\treturn result.trim();\n\t} catch (error) {\n\t\tconst err = error as { status?: number; stderr?: Buffer | string; message?: string };\n\t\tconst stderr = err.stderr\n\t\t\t? typeof err.stderr === \"string\"\n\t\t\t\t? err.stderr\n\t\t\t\t: err.stderr.toString()\n\t\t\t: err.message || \"Unknown error\";\n\t\tthrow new GitError(stderr.trim(), `git ${args.join(\" \")}`, err.status ?? null);\n\t}\n}\n\nfunction execGitAsync(args: string[], cwd?: string): Promise<string> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst proc = spawn(\"git\", args, {\n\t\t\tcwd,\n\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\tenv: { ...process.env, GIT_TERMINAL_PROMPT: \"0\" },\n\t\t});\n\n\t\tlet stdout = \"\";\n\t\tlet stderr = \"\";\n\n\t\tproc.stdout.on(\"data\", (data: Buffer) => {\n\t\t\tstdout += data.toString();\n\t\t});\n\t\tproc.stderr.on(\"data\", (data: Buffer) => {\n\t\t\tstderr += data.toString();\n\t\t});\n\n\t\tproc.on(\"close\", (code) => {\n\t\t\tif (code === 0) {\n\t\t\t\tresolve(stdout.trim());\n\t\t\t} else {\n\t\t\t\treject(new GitError(stderr.trim() || \"Unknown error\", `git ${args.join(\" \")}`, code));\n\t\t\t}\n\t\t});\n\n\t\tproc.on(\"error\", (err) => {\n\t\t\treject(new GitError(err.message, `git ${args.join(\" \")}`, null));\n\t\t});\n\t});\n}\n\nexport function getCommitSha(repoPath: string): string {\n\treturn execGit([\"rev-parse\", \"HEAD\"], repoPath);\n}\n\nexport function getCommitDistance(\n\trepoPath: string,\n\tolderSha: string,\n\tnewerSha = \"HEAD\",\n): number | null {\n\ttry {\n\t\ttry {\n\t\t\texecGit([\"cat-file\", \"-e\", olderSha], repoPath);\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t\tconst count = execGit([\"rev-list\", \"--count\", `${olderSha}..${newerSha}`], repoPath);\n\t\treturn Number.parseInt(count, 10);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nconst SPARSE_CHECKOUT_DIRS = [\"src\", \"lib\", \"packages\", \"docs\", \"README.md\", \"package.json\"];\n\n/**\n * Clone a remote repository to the local repo root.\n *\n * @param source - Remote repo source from parseRepoInput()\n * @param options - Clone options (shallow, branch, config)\n * @returns The local path where the repo was cloned\n * @throws RepoExistsError if repo already exists (unless force is true)\n * @throws GitError if clone fails\n */\nexport async function cloneRepo(\n\tsource: RemoteRepoSource,\n\toptions: CloneOptions = {},\n): Promise<string> {\n\tconst config = options.config ?? loadConfig();\n\tconst repoPath = getRepoPath(source.fullName, source.provider, config);\n\n\tif (existsSync(repoPath)) {\n\t\tif (options.force) {\n\t\t\trmSync(repoPath, { recursive: true, force: true });\n\t\t} else {\n\t\t\tthrow new RepoExistsError(repoPath);\n\t\t}\n\t}\n\n\ttry {\n\t\tif (options.sparse) {\n\t\t\tawait cloneSparse(source.cloneUrl, repoPath, options);\n\t\t} else {\n\t\t\tawait cloneStandard(source.cloneUrl, repoPath, options);\n\t\t}\n\t} catch (err) {\n\t\tcleanupEmptyParentDirs(repoPath);\n\t\tthrow err;\n\t}\n\n\tconst referenceFileName = toReferenceFileName(source.fullName);\n\tconst referencePath = join(Paths.offworldReferencesDir, referenceFileName);\n\tconst hasReference = existsSync(referencePath);\n\n\tupsertGlobalMapEntry(source.qualifiedName, {\n\t\tlocalPath: repoPath,\n\t\treferences: hasReference ? [referenceFileName] : [],\n\t\tprimary: hasReference ? referenceFileName : \"\",\n\t\tkeywords: [],\n\t\tupdatedAt: new Date().toISOString(),\n\t});\n\n\treturn repoPath;\n}\n\nfunction cleanupEmptyParentDirs(repoPath: string): void {\n\tconst ownerDir = dirname(repoPath);\n\tif (existsSync(ownerDir) && readdirSync(ownerDir).length === 0) {\n\t\trmSync(ownerDir, { recursive: true, force: true });\n\t}\n}\n\nasync function cloneStandard(\n\tcloneUrl: string,\n\trepoPath: string,\n\toptions: CloneOptions,\n): Promise<void> {\n\tconst args = [\"clone\"];\n\n\tif (options.shallow) {\n\t\targs.push(\"--depth\", \"1\");\n\t}\n\n\tif (options.branch) {\n\t\targs.push(\"--branch\", options.branch);\n\t}\n\n\targs.push(cloneUrl, repoPath);\n\tawait execGitAsync(args);\n}\n\nasync function cloneSparse(\n\tcloneUrl: string,\n\trepoPath: string,\n\toptions: CloneOptions,\n): Promise<void> {\n\tconst args = [\"clone\", \"--filter=blob:none\", \"--no-checkout\", \"--sparse\"];\n\n\tif (options.shallow) {\n\t\targs.push(\"--depth\", \"1\");\n\t}\n\n\tif (options.branch) {\n\t\targs.push(\"--branch\", options.branch);\n\t}\n\n\targs.push(cloneUrl, repoPath);\n\tawait execGitAsync(args);\n\n\tawait execGitAsync([\"sparse-checkout\", \"set\", ...SPARSE_CHECKOUT_DIRS], repoPath);\n\tawait execGitAsync([\"checkout\"], repoPath);\n}\n\nexport function isShallowClone(repoPath: string): boolean {\n\ttry {\n\t\tconst result = execGit([\"rev-parse\", \"--is-shallow-repository\"], repoPath);\n\t\treturn result === \"true\";\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nexport async function unshallowRepo(repoPath: string): Promise<boolean> {\n\tif (!isShallowClone(repoPath)) {\n\t\treturn false;\n\t}\n\n\tawait execGitAsync([\"fetch\", \"--unshallow\"], repoPath);\n\treturn true;\n}\n\nexport interface UpdateResult {\n\t/** Whether any updates were fetched */\n\tupdated: boolean;\n\t/** Previous commit SHA before update */\n\tpreviousSha: string;\n\t/** Current commit SHA after update */\n\tcurrentSha: string;\n\t/** Whether the repo was unshallowed */\n\tunshallowed?: boolean;\n}\n\nexport interface UpdateOptions {\n\t/** Convert shallow clone to full clone */\n\tunshallow?: boolean;\n}\n\n/**\n * Update a cloned repository by running git fetch and pull.\n *\n * @param qualifiedName - The qualified name of the repo (e.g., \"github.com:owner/repo\")\n * @param options - Update options\n * @returns Update result with commit SHAs\n * @throws RepoNotFoundError if repo not in index\n * @throws GitError if fetch/pull fails\n */\nexport async function updateRepo(\n\tqualifiedName: string,\n\toptions: UpdateOptions = {},\n): Promise<UpdateResult> {\n\tconst map = readGlobalMap();\n\tconst entry = map.repos[qualifiedName];\n\tif (!entry) {\n\t\tthrow new RepoNotFoundError(qualifiedName);\n\t}\n\n\tconst repoPath = entry.localPath;\n\n\tif (!existsSync(repoPath)) {\n\t\tthrow new RepoNotFoundError(qualifiedName);\n\t}\n\n\tconst previousSha = getCommitSha(repoPath);\n\tlet unshallowed = false;\n\tif (options.unshallow) {\n\t\tunshallowed = await unshallowRepo(repoPath);\n\t}\n\n\tawait execGitAsync([\"fetch\"], repoPath);\n\tawait execGitAsync([\"pull\", \"--ff-only\"], repoPath);\n\n\tconst currentSha = getCommitSha(repoPath);\n\tupsertGlobalMapEntry(qualifiedName, {\n\t\t...entry,\n\t\tupdatedAt: new Date().toISOString(),\n\t});\n\n\treturn {\n\t\tupdated: previousSha !== currentSha,\n\t\tpreviousSha,\n\t\tcurrentSha,\n\t\tunshallowed,\n\t};\n}\n\nexport interface RemoveOptions {\n\treferenceOnly?: boolean;\n\trepoOnly?: boolean;\n}\n\nexport async function removeRepo(\n\tqualifiedName: string,\n\toptions: RemoveOptions = {},\n): Promise<boolean> {\n\tconst map = readGlobalMap();\n\tconst entry = map.repos[qualifiedName];\n\tif (!entry) {\n\t\treturn false;\n\t}\n\n\tconst { referenceOnly = false, repoOnly = false } = options;\n\tconst removeRepoFiles = !referenceOnly;\n\tconst removeReferenceFiles = !repoOnly;\n\n\tif (removeRepoFiles && existsSync(entry.localPath)) {\n\t\trmSync(entry.localPath, { recursive: true, force: true });\n\t\tcleanupEmptyParentDirs(entry.localPath);\n\t}\n\n\tif (removeReferenceFiles) {\n\t\tfor (const referenceFileName of entry.references) {\n\t\t\tconst referencePath = join(Paths.offworldReferencesDir, referenceFileName);\n\t\t\tif (existsSync(referencePath)) {\n\t\t\t\trmSync(referencePath, { force: true });\n\t\t\t}\n\t\t}\n\n\t\tif (entry.primary) {\n\t\t\tconst metaDirName = entry.primary.replace(/\\.md$/, \"\");\n\t\t\tconst metaPath = join(Paths.metaDir, metaDirName);\n\t\t\tif (existsSync(metaPath)) {\n\t\t\t\trmSync(metaPath, { recursive: true, force: true });\n\t\t\t}\n\t\t}\n\t}\n\n\tif (removeRepoFiles) {\n\t\tremoveGlobalMapEntry(qualifiedName);\n\t} else if (removeReferenceFiles) {\n\t\tupsertGlobalMapEntry(qualifiedName, {\n\t\t\t...entry,\n\t\t\treferences: [],\n\t\t\tprimary: \"\",\n\t\t});\n\t}\n\n\treturn true;\n}\n\nexport function listRepos(): string[] {\n\tconst map = readGlobalMap();\n\treturn Object.keys(map.repos);\n}\n\nexport function isRepoCloned(qualifiedName: string): boolean {\n\tconst map = readGlobalMap();\n\tconst entry = map.repos[qualifiedName];\n\tif (!entry) return false;\n\treturn existsSync(entry.localPath);\n}\n\n/**\n * Get the local path for a cloned repository.\n *\n * @param qualifiedName - The qualified name of the repo\n * @returns The local path or undefined if not cloned\n */\nexport function getClonedRepoPath(qualifiedName: string): string | undefined {\n\tconst map = readGlobalMap();\n\tconst entry = map.repos[qualifiedName];\n\tif (!entry) return undefined;\n\tif (!existsSync(entry.localPath)) return undefined;\n\treturn entry.localPath;\n}\n","/**\n * Base class for OpenCode reference errors\n */\nexport class OpenCodeReferenceError extends Error {\n\treadonly _tag: string = \"OpenCodeReferenceError\";\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly details?: unknown,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"OpenCodeReferenceError\";\n\t}\n}\n\n/**\n * Error when the @opencode-ai/sdk package is not installed or invalid\n */\nexport class OpenCodeSDKError extends OpenCodeReferenceError {\n\treadonly _tag = \"OpenCodeSDKError\" as const;\n\tconstructor(message?: string) {\n\t\tsuper(\n\t\t\tmessage ?? \"Failed to import @opencode-ai/sdk. Install it with: bun add @opencode-ai/sdk\",\n\t\t);\n\t\tthis.name = \"OpenCodeSDKError\";\n\t}\n}\n\n/**\n * Error when the requested provider is not found\n */\nexport class InvalidProviderError extends OpenCodeReferenceError {\n\treadonly _tag = \"InvalidProviderError\" as const;\n\treadonly hint: string;\n\n\tconstructor(\n\t\tpublic readonly providerID: string,\n\t\tpublic readonly availableProviders: string[],\n\t) {\n\t\tconst hint =\n\t\t\tavailableProviders.length > 0\n\t\t\t\t? `Available providers: ${availableProviders.join(\", \")}`\n\t\t\t\t: \"No providers available. Check your OpenCode configuration.\";\n\t\tsuper(`Provider \"${providerID}\" not found. ${hint}`);\n\t\tthis.name = \"InvalidProviderError\";\n\t\tthis.hint = hint;\n\t}\n}\n\n/**\n * Error when the provider exists but is not connected/authenticated\n */\nexport class ProviderNotConnectedError extends OpenCodeReferenceError {\n\treadonly _tag = \"ProviderNotConnectedError\" as const;\n\treadonly hint: string;\n\n\tconstructor(\n\t\tpublic readonly providerID: string,\n\t\tpublic readonly connectedProviders: string[],\n\t) {\n\t\tconst hint =\n\t\t\tconnectedProviders.length > 0\n\t\t\t\t? `Connected providers: ${connectedProviders.join(\", \")}. Run 'opencode auth ${providerID}' to connect.`\n\t\t\t\t: `No providers connected. Run 'opencode auth ${providerID}' to authenticate.`;\n\t\tsuper(`Provider \"${providerID}\" is not connected. ${hint}`);\n\t\tthis.name = \"ProviderNotConnectedError\";\n\t\tthis.hint = hint;\n\t}\n}\n\n/**\n * Error when the requested model is not found for a provider\n */\nexport class InvalidModelError extends OpenCodeReferenceError {\n\treadonly _tag = \"InvalidModelError\" as const;\n\treadonly hint: string;\n\n\tconstructor(\n\t\tpublic readonly modelID: string,\n\t\tpublic readonly providerID: string,\n\t\tpublic readonly availableModels: string[],\n\t) {\n\t\tconst hint =\n\t\t\tavailableModels.length > 0\n\t\t\t\t? `Available models for ${providerID}: ${availableModels.slice(0, 10).join(\", \")}${availableModels.length > 10 ? ` (and ${availableModels.length - 10} more)` : \"\"}`\n\t\t\t\t: `No models available for provider \"${providerID}\".`;\n\t\tsuper(`Model \"${modelID}\" not found for provider \"${providerID}\". ${hint}`);\n\t\tthis.name = \"InvalidModelError\";\n\t\tthis.hint = hint;\n\t}\n}\n\n/**\n * Error when the OpenCode server fails to start\n */\nexport class ServerStartError extends OpenCodeReferenceError {\n\treadonly _tag = \"ServerStartError\" as const;\n\treadonly hint: string;\n\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly port?: number,\n\t\tdetails?: unknown,\n\t) {\n\t\tconst hint = port\n\t\t\t? `Failed to start server on port ${port}. Ensure no other process is using this port.`\n\t\t\t: \"Failed to start OpenCode server. Check your OpenCode installation and configuration.\";\n\t\tsuper(`${message}. ${hint}`, details);\n\t\tthis.name = \"ServerStartError\";\n\t\tthis.hint = hint;\n\t}\n}\n\n/**\n * Error when a session operation fails\n */\nexport class SessionError extends OpenCodeReferenceError {\n\treadonly _tag = \"SessionError\" as const;\n\treadonly hint: string;\n\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly sessionId?: string,\n\t\tpublic readonly sessionState?: string,\n\t\tdetails?: unknown,\n\t) {\n\t\tconst context = sessionId ? ` (session: ${sessionId})` : \"\";\n\t\tconst stateInfo = sessionState ? ` State: ${sessionState}.` : \"\";\n\t\tconst hint = `Session operation failed${context}.${stateInfo} Try creating a new session.`;\n\t\tsuper(`${message}. ${hint}`, details);\n\t\tthis.name = \"SessionError\";\n\t\tthis.hint = hint;\n\t}\n}\n\n/**\n * Error when a request times out\n */\nexport class TimeoutError extends OpenCodeReferenceError {\n\treadonly _tag = \"TimeoutError\" as const;\n\treadonly hint: string;\n\n\tconstructor(\n\t\tpublic readonly timeoutMs: number,\n\t\tpublic readonly operation: string = \"operation\",\n\t) {\n\t\tconst hint = `The ${operation} did not complete within ${timeoutMs}ms. Consider increasing the timeout or checking if the model is responding.`;\n\t\tsuper(`Timeout: ${operation} did not complete within ${timeoutMs}ms. ${hint}`);\n\t\tthis.name = \"TimeoutError\";\n\t\tthis.hint = hint;\n\t}\n}\n","/**\n * Zod schemas for OpenCode stream events\n * Replaces inline `as` casts with runtime-validated types\n */\n\nimport { z } from \"zod\";\n\nconst PartBaseSchema = z.object({\n\tid: z.string().optional(),\n\tsessionID: z.string().optional(),\n\tmessageID: z.string().optional(),\n});\n\nexport const TextPartSchema = PartBaseSchema.extend({\n\ttype: z.literal(\"text\"),\n\ttext: z.string().optional(),\n});\n\nexport const ToolStatePendingSchema = z.object({\n\tstatus: z.literal(\"pending\"),\n});\n\nexport const ToolStateRunningSchema = z.object({\n\tstatus: z.literal(\"running\"),\n\ttitle: z.string().optional(),\n\tinput: z.unknown().optional(),\n\tmetadata: z.record(z.string(), z.unknown()).optional(),\n\ttime: z\n\t\t.object({\n\t\t\tstart: z.number(),\n\t\t})\n\t\t.optional(),\n});\n\nexport const ToolStateCompletedSchema = z.object({\n\tstatus: z.literal(\"completed\"),\n\ttitle: z.string().optional(),\n\tinput: z.record(z.string(), z.unknown()).optional(),\n\toutput: z.string().optional(),\n\tmetadata: z.record(z.string(), z.unknown()).optional(),\n\ttime: z\n\t\t.object({\n\t\t\tstart: z.number(),\n\t\t\tend: z.number(),\n\t\t})\n\t\t.optional(),\n});\n\nexport const ToolStateErrorSchema = z.object({\n\tstatus: z.literal(\"error\"),\n\terror: z.string().optional(),\n\tinput: z.record(z.string(), z.unknown()).optional(),\n\ttime: z\n\t\t.object({\n\t\t\tstart: z.number(),\n\t\t\tend: z.number(),\n\t\t})\n\t\t.optional(),\n});\n\nexport const ToolStateSchema = z.discriminatedUnion(\"status\", [\n\tToolStatePendingSchema,\n\tToolStateRunningSchema,\n\tToolStateCompletedSchema,\n\tToolStateErrorSchema,\n]);\n\nexport const ToolPartSchema = PartBaseSchema.extend({\n\ttype: z.literal(\"tool\"),\n\tcallID: z.string().optional(),\n\ttool: z.string().optional(),\n\tstate: ToolStateSchema.optional(),\n});\n\nexport const StepStartPartSchema = PartBaseSchema.extend({\n\ttype: z.literal(\"step-start\"),\n});\n\nexport const StepFinishPartSchema = PartBaseSchema.extend({\n\ttype: z.literal(\"step-finish\"),\n\treason: z.string().optional(),\n});\n\nexport const ToolUsePartSchema = PartBaseSchema.extend({\n\ttype: z.literal(\"tool-use\"),\n\ttoolUseId: z.string().optional(),\n\tname: z.string().optional(),\n});\n\nexport const ToolResultPartSchema = PartBaseSchema.extend({\n\ttype: z.literal(\"tool-result\"),\n\ttoolUseId: z.string().optional(),\n});\n\nexport const MessagePartSchema = z.discriminatedUnion(\"type\", [\n\tTextPartSchema,\n\tToolPartSchema,\n\tStepStartPartSchema,\n\tStepFinishPartSchema,\n\tToolUsePartSchema,\n\tToolResultPartSchema,\n]);\n\n/**\n * Session error payload\n */\nexport const SessionErrorSchema = z.object({\n\tname: z.string().optional(),\n\tmessage: z.string().optional(),\n\tcode: z.string().optional(),\n});\n\nexport const MessagePartUpdatedPropsSchema = z.object({\n\tpart: MessagePartSchema,\n});\n\n/**\n * Properties for session.idle event\n */\nexport const SessionIdlePropsSchema = z.object({\n\tsessionID: z.string(),\n});\n\n/**\n * Properties for session.error event\n */\nexport const SessionErrorPropsSchema = z.object({\n\tsessionID: z.string(),\n\terror: SessionErrorSchema.optional(),\n});\n\n/**\n * Properties for session.updated event\n */\nexport const SessionUpdatedPropsSchema = z.object({\n\tsessionID: z.string(),\n\tstatus: z.string().optional(),\n});\n\n/**\n * message.part.updated event\n */\nexport const MessagePartUpdatedEventSchema = z.object({\n\ttype: z.literal(\"message.part.updated\"),\n\tproperties: MessagePartUpdatedPropsSchema,\n});\n\n/**\n * session.idle event\n */\nexport const SessionIdleEventSchema = z.object({\n\ttype: z.literal(\"session.idle\"),\n\tproperties: SessionIdlePropsSchema,\n});\n\n/**\n * session.error event\n */\nexport const SessionErrorEventSchema = z.object({\n\ttype: z.literal(\"session.error\"),\n\tproperties: SessionErrorPropsSchema,\n});\n\n/**\n * session.updated event\n */\nexport const SessionUpdatedEventSchema = z.object({\n\ttype: z.literal(\"session.updated\"),\n\tproperties: SessionUpdatedPropsSchema,\n});\n\n/**\n * Generic event for unknown types (passthrough)\n */\nexport const GenericEventSchema = z.object({\n\ttype: z.string(),\n\tproperties: z.record(z.string(), z.unknown()),\n});\n\nexport type TextPart = z.infer<typeof TextPartSchema>;\nexport type ToolPart = z.infer<typeof ToolPartSchema>;\nexport type ToolState = z.infer<typeof ToolStateSchema>;\nexport type ToolStateRunning = z.infer<typeof ToolStateRunningSchema>;\nexport type ToolUsePart = z.infer<typeof ToolUsePartSchema>;\nexport type ToolResultPart = z.infer<typeof ToolResultPartSchema>;\nexport type MessagePart = z.infer<typeof MessagePartSchema>;\n\nexport type SessionErrorPayload = z.infer<typeof SessionErrorSchema>;\n\nexport type MessagePartUpdatedProps = z.infer<typeof MessagePartUpdatedPropsSchema>;\nexport type SessionIdleProps = z.infer<typeof SessionIdlePropsSchema>;\nexport type SessionErrorProps = z.infer<typeof SessionErrorPropsSchema>;\nexport type SessionUpdatedProps = z.infer<typeof SessionUpdatedPropsSchema>;\n\nexport type MessagePartUpdatedEvent = z.infer<typeof MessagePartUpdatedEventSchema>;\nexport type SessionIdleEvent = z.infer<typeof SessionIdleEventSchema>;\nexport type SessionErrorEvent = z.infer<typeof SessionErrorEventSchema>;\nexport type SessionUpdatedEvent = z.infer<typeof SessionUpdatedEventSchema>;\nexport type GenericEvent = z.infer<typeof GenericEventSchema>;\n\n/**\n * All known stream event types\n */\nexport type StreamEvent =\n\t| MessagePartUpdatedEvent\n\t| SessionIdleEvent\n\t| SessionErrorEvent\n\t| SessionUpdatedEvent\n\t| GenericEvent;\n","/**\n * Text accumulator for stream events\n * Manages accumulation of text parts by ID and provides delta extraction\n */\n\nimport type { TextPart } from \"./types.js\";\n\n/**\n * Accumulates text from streaming message parts.\n * Tracks multiple parts by ID and provides delta text between updates.\n */\nexport class TextAccumulator {\n\tprivate readonly parts = new Map<string, string>();\n\tprivate _firstTextReceived = false;\n\n\t/**\n\t * Whether any text has been received\n\t */\n\tget hasReceivedText(): boolean {\n\t\treturn this._firstTextReceived;\n\t}\n\n\t/**\n\t * Accumulate text from a message part and return the delta (new text only).\n\t * Returns null if the part should be skipped (non-text, no ID, no text).\n\t */\n\taccumulatePart(part: TextPart): string | null {\n\t\tif (part.type !== \"text\" || !part.text || !part.id) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst partId = part.id;\n\t\tconst prevText = this.parts.get(partId) ?? \"\";\n\t\tthis.parts.set(partId, part.text);\n\n\t\tif (!this._firstTextReceived) {\n\t\t\tthis._firstTextReceived = true;\n\t\t}\n\n\t\tif (part.text.length > prevText.length) {\n\t\t\treturn part.text.slice(prevText.length);\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Get the full accumulated text from all parts\n\t */\n\tgetFullText(): string {\n\t\treturn Array.from(this.parts.values()).join(\"\");\n\t}\n\n\t/**\n\t * Clear accumulated text\n\t */\n\tclear(): void {\n\t\tthis.parts.clear();\n\t\tthis._firstTextReceived = false;\n\t}\n}\n","/**\n * Stream event transformer and parser\n * Safely parses and validates stream events using Zod schemas\n */\n\nimport {\n\tMessagePartUpdatedPropsSchema,\n\tSessionIdlePropsSchema,\n\tSessionErrorPropsSchema,\n\tSessionErrorSchema,\n\ttype TextPart,\n\ttype ToolPart,\n\ttype SessionErrorPayload,\n\ttype MessagePartUpdatedProps,\n\ttype SessionIdleProps,\n\ttype SessionErrorProps,\n} from \"./types.js\";\n\n/**\n * Raw event from the OpenCode SDK stream\n */\nexport interface RawStreamEvent {\n\ttype: string;\n\tproperties: Record<string, unknown>;\n}\n\n/**\n * Result of parsing a stream event\n */\nexport type ParsedEventResult =\n\t| {\n\t\t\ttype: \"message.part.updated\";\n\t\t\tprops: MessagePartUpdatedProps;\n\t\t\ttextPart: TextPart | null;\n\t\t\ttoolPart: ToolPart | null;\n\t }\n\t| { type: \"session.idle\"; props: SessionIdleProps }\n\t| { type: \"session.error\"; props: SessionErrorProps; error: SessionErrorPayload | null }\n\t| { type: \"unknown\"; rawType: string };\n\n/**\n * Parse a raw stream event into a typed result.\n * Uses safe parsing - returns type: \"unknown\" for unrecognized or invalid events.\n */\nexport function parseStreamEvent(event: RawStreamEvent): ParsedEventResult {\n\tswitch (event.type) {\n\t\tcase \"message.part.updated\": {\n\t\t\tconst propsResult = MessagePartUpdatedPropsSchema.safeParse(event.properties);\n\t\t\tif (!propsResult.success) {\n\t\t\t\treturn { type: \"unknown\", rawType: event.type };\n\t\t\t}\n\t\t\tconst props = propsResult.data;\n\t\t\tconst textPart = props.part.type === \"text\" ? props.part : null;\n\t\t\tconst toolPart = props.part.type === \"tool\" ? props.part : null;\n\t\t\treturn { type: \"message.part.updated\", props, textPart, toolPart };\n\t\t}\n\n\t\tcase \"session.idle\": {\n\t\t\tconst propsResult = SessionIdlePropsSchema.safeParse(event.properties);\n\t\t\tif (!propsResult.success) {\n\t\t\t\treturn { type: \"unknown\", rawType: event.type };\n\t\t\t}\n\t\t\treturn { type: \"session.idle\", props: propsResult.data };\n\t\t}\n\n\t\tcase \"session.error\": {\n\t\t\tconst propsResult = SessionErrorPropsSchema.safeParse(event.properties);\n\t\t\tif (!propsResult.success) {\n\t\t\t\treturn { type: \"unknown\", rawType: event.type };\n\t\t\t}\n\t\t\tconst props = propsResult.data;\n\n\t\t\tlet error: SessionErrorPayload | null = null;\n\t\t\tif (props.error) {\n\t\t\t\tconst errorResult = SessionErrorSchema.safeParse(props.error);\n\t\t\t\tif (errorResult.success) {\n\t\t\t\t\terror = errorResult.data;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn { type: \"session.error\", props, error };\n\t\t}\n\n\t\tdefault:\n\t\t\treturn { type: \"unknown\", rawType: event.type };\n\t}\n}\n\nexport function isEventForSession(event: RawStreamEvent, sessionId: string): boolean {\n\tconst props = event.properties;\n\tif (\"sessionID\" in props && typeof props.sessionID === \"string\") {\n\t\treturn props.sessionID === sessionId;\n\t}\n\tif (\n\t\t\"part\" in props &&\n\t\ttypeof props.part === \"object\" &&\n\t\tprops.part !== null &&\n\t\t\"sessionID\" in props.part &&\n\t\ttypeof props.part.sessionID === \"string\"\n\t) {\n\t\treturn props.part.sessionID === sessionId;\n\t}\n\treturn true;\n}\n","import {\n\tOpenCodeReferenceError,\n\tOpenCodeSDKError,\n\tInvalidProviderError,\n\tProviderNotConnectedError,\n\tInvalidModelError,\n\tServerStartError,\n\tSessionError,\n\tTimeoutError,\n} from \"./errors.js\";\nimport { TextAccumulator, parseStreamEvent, isEventForSession } from \"./stream/index.js\";\n\nexport const DEFAULT_AI_PROVIDER = \"opencode\";\nexport const DEFAULT_AI_MODEL = \"claude-opus-4-5\";\n\nexport interface StreamPromptOptions {\n\tprompt: string;\n\tcwd: string;\n\tsystemPrompt?: string;\n\tprovider?: string;\n\n\tmodel?: string;\n\t/** Timeout in milliseconds. Set to 0 or undefined for no timeout. */\n\ttimeoutMs?: number;\n\tonDebug?: (message: string) => void;\n\tonStream?: (text: string) => void;\n}\n\nexport interface StreamPromptResult {\n\ttext: string;\n\tsessionId: string;\n\tdurationMs: number;\n}\n\ninterface OpenCodeServer {\n\tclose: () => void;\n\turl: string;\n}\n\ninterface OpenCodeSession {\n\tid: string;\n}\n\ninterface OpenCodeEvent {\n\ttype: string;\n\tproperties: Record<string, unknown>;\n}\n\ninterface OpenCodeProviderModel {\n\tid: string;\n\tname: string;\n}\n\ninterface OpenCodeProvider {\n\tid: string;\n\tname: string;\n\tmodels: Record<string, OpenCodeProviderModel>;\n}\n\ninterface OpenCodeProviderListResponse {\n\tall: OpenCodeProvider[];\n\tconnected: string[];\n\tdefault: Record<string, string>;\n}\n\ninterface OpenCodeClient {\n\tsession: {\n\t\tcreate: () => Promise<{ data: OpenCodeSession; error?: unknown }>;\n\t\tprompt: (options: {\n\t\t\tpath: { id: string };\n\t\t\tbody: {\n\t\t\t\tagent?: string;\n\t\t\t\tparts: Array<{ type: string; text: string }>;\n\t\t\t\tmodel?: { providerID: string; modelID: string };\n\t\t\t};\n\t\t}) => Promise<{ data: unknown; error?: unknown }>;\n\t};\n\tevent: {\n\t\tsubscribe: () => Promise<{\n\t\t\tstream: AsyncIterable<OpenCodeEvent>;\n\t\t}>;\n\t};\n\tprovider: {\n\t\tlist: () => Promise<{ data: OpenCodeProviderListResponse; error?: unknown }>;\n\t};\n}\n\ninterface AgentConfig {\n\tdisable?: boolean;\n\tprompt?: string;\n\tdescription?: string;\n\tmode?: string;\n\tpermission?: Record<string, string>;\n\ttools?: Record<string, boolean>;\n}\n\ninterface OpenCodeConfig {\n\tplugin?: unknown[];\n\tmcp?: Record<string, unknown>;\n\tinstructions?: unknown[];\n\tagent?: Record<string, AgentConfig>;\n}\n\ntype CreateOpencodeResult = { server: OpenCodeServer };\ntype CreateOpencodeClientFn = (opts: { baseUrl: string; directory: string }) => OpenCodeClient;\ntype CreateOpencodeFn = (opts: {\n\tport: number;\n\tcwd?: string;\n\tconfig?: OpenCodeConfig;\n}) => Promise<CreateOpencodeResult>;\n\nlet cachedCreateOpencode: CreateOpencodeFn | null = null;\nlet cachedCreateOpencodeClient: CreateOpencodeClientFn | null = null;\n\nasync function getOpenCodeSDK(): Promise<{\n\tcreateOpencode: CreateOpencodeFn;\n\tcreateOpencodeClient: CreateOpencodeClientFn;\n}> {\n\tif (cachedCreateOpencode && cachedCreateOpencodeClient) {\n\t\treturn {\n\t\t\tcreateOpencode: cachedCreateOpencode,\n\t\t\tcreateOpencodeClient: cachedCreateOpencodeClient,\n\t\t};\n\t}\n\n\ttry {\n\t\tconst sdk = await import(\"@opencode-ai/sdk\");\n\t\tif (\n\t\t\ttypeof sdk.createOpencode !== \"function\" ||\n\t\t\ttypeof sdk.createOpencodeClient !== \"function\"\n\t\t) {\n\t\t\tthrow new OpenCodeSDKError(\"SDK missing required exports\");\n\t\t}\n\t\tcachedCreateOpencode = sdk.createOpencode as CreateOpencodeFn;\n\t\tcachedCreateOpencodeClient = sdk.createOpencodeClient as CreateOpencodeClientFn;\n\t\treturn {\n\t\t\tcreateOpencode: cachedCreateOpencode,\n\t\t\tcreateOpencodeClient: cachedCreateOpencodeClient,\n\t\t};\n\t} catch (error) {\n\t\tif (error instanceof OpenCodeSDKError) {\n\t\t\tthrow error;\n\t\t}\n\t\tthrow new OpenCodeSDKError();\n\t}\n}\n\ninterface ToolRunningState {\n\tstatus: \"running\";\n\ttitle?: string;\n\tinput?: unknown;\n}\n\nfunction formatToolMessage(tool: string | undefined, state: ToolRunningState): string | null {\n\tif (state.title) {\n\t\treturn state.title;\n\t}\n\n\tif (!tool) {\n\t\treturn null;\n\t}\n\n\tconst input =\n\t\tstate.input && typeof state.input === \"object\" && !Array.isArray(state.input)\n\t\t\t? (state.input as Record<string, unknown>)\n\t\t\t: undefined;\n\tif (!input) {\n\t\treturn `Running ${tool}...`;\n\t}\n\n\tswitch (tool) {\n\t\tcase \"read\": {\n\t\t\tconst path = input.filePath ?? input.path;\n\t\t\tif (typeof path === \"string\") {\n\t\t\t\tconst filename = path.split(\"/\").pop();\n\t\t\t\treturn `Reading ${filename}...`;\n\t\t\t}\n\t\t\treturn \"Reading file...\";\n\t\t}\n\t\tcase \"glob\": {\n\t\t\tconst pattern = input.pattern;\n\t\t\tif (typeof pattern === \"string\") {\n\t\t\t\treturn `Globbing ${pattern}...`;\n\t\t\t}\n\t\t\treturn \"Searching files...\";\n\t\t}\n\t\tcase \"grep\": {\n\t\t\tconst pattern = input.pattern;\n\t\t\tif (typeof pattern === \"string\") {\n\t\t\t\tconst truncated = pattern.length > 30 ? `${pattern.slice(0, 30)}...` : pattern;\n\t\t\t\treturn `Searching for \"${truncated}\"...`;\n\t\t\t}\n\t\t\treturn \"Searching content...\";\n\t\t}\n\t\tcase \"list\": {\n\t\t\tconst path = input.path;\n\t\t\tif (typeof path === \"string\") {\n\t\t\t\treturn `Listing ${path}...`;\n\t\t\t}\n\t\t\treturn \"Listing directory...\";\n\t\t}\n\t\tdefault:\n\t\t\treturn `Running ${tool}...`;\n\t}\n}\n\nexport async function streamPrompt(options: StreamPromptOptions): Promise<StreamPromptResult> {\n\tconst {\n\t\tprompt,\n\t\tcwd,\n\t\tsystemPrompt,\n\t\tprovider: optProvider,\n\t\tmodel: optModel,\n\t\ttimeoutMs,\n\t\tonDebug,\n\t\tonStream,\n\t} = options;\n\n\tconst debug = onDebug ?? (() => {});\n\tconst stream = onStream ?? (() => {});\n\tconst startTime = Date.now();\n\n\tdebug(\"Loading OpenCode SDK...\");\n\tconst { createOpencode, createOpencodeClient } = await getOpenCodeSDK();\n\n\tconst maxAttempts = 10;\n\tlet server: OpenCodeServer | null = null;\n\tlet client: OpenCodeClient | null = null;\n\tlet port = 0;\n\n\tconst config: OpenCodeConfig = {\n\t\tplugin: [],\n\t\tmcp: {},\n\t\tinstructions: [],\n\t\tagent: {\n\t\t\tbuild: { disable: true },\n\t\t\tgeneral: { disable: true },\n\t\t\tplan: { disable: true },\n\t\t\texplore: { disable: true },\n\t\t\tanalyze: {\n\t\t\t\tprompt: [\n\t\t\t\t\t\"You are an expert at analyzing open source codebases and producing documentation.\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"Your job is to read the codebase and produce structured output based on the user's request.\",\n\t\t\t\t\t\"Use glob to discover files, grep to search for patterns, and read to examine file contents.\",\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"Guidelines:\",\n\t\t\t\t\t\"- Explore the codebase thoroughly before producing output\",\n\t\t\t\t\t\"- Focus on understanding architecture, key abstractions, and usage patterns\",\n\t\t\t\t\t\"- When asked for JSON output, respond with ONLY valid JSON - no markdown, no code blocks\",\n\t\t\t\t\t\"- When asked for prose, write clear and concise documentation\",\n\t\t\t\t\t\"- Always base your analysis on actual code you've read, never speculate\",\n\t\t\t\t].join(\"\\n\"),\n\t\t\t\tmode: \"primary\",\n\t\t\t\tdescription: \"Analyze open source codebases and produce summaries and reference files\",\n\t\t\t\ttools: {\n\t\t\t\t\tread: true,\n\t\t\t\t\tgrep: true,\n\t\t\t\t\tglob: true,\n\t\t\t\t\tlist: true,\n\t\t\t\t\twrite: false,\n\t\t\t\t\tbash: false,\n\t\t\t\t\tdelete: false,\n\t\t\t\t\tedit: false,\n\t\t\t\t\tpatch: false,\n\t\t\t\t\tpath: false,\n\t\t\t\t\ttodowrite: false,\n\t\t\t\t\ttodoread: false,\n\t\t\t\t\twebsearch: false,\n\t\t\t\t\twebfetch: false,\n\t\t\t\t\tcodesearch: false,\n\t\t\t\t\tskill: false,\n\t\t\t\t\ttask: false,\n\t\t\t\t\tmcp: false,\n\t\t\t\t\tquestion: false,\n\t\t\t\t\tplan_enter: false,\n\t\t\t\t\tplan_exit: false,\n\t\t\t\t},\n\t\t\t\tpermission: {\n\t\t\t\t\tedit: \"deny\",\n\t\t\t\t\tbash: \"deny\",\n\t\t\t\t\twebfetch: \"deny\",\n\t\t\t\t\texternal_directory: \"deny\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t};\n\n\tdebug(\"Starting embedded OpenCode server...\");\n\n\tfor (let attempt = 0; attempt < maxAttempts; attempt++) {\n\t\tport = Math.floor(Math.random() * 3000) + 3000;\n\t\ttry {\n\t\t\tconst result = await createOpencode({ port, cwd, config });\n\t\t\tserver = result.server;\n\t\t\tclient = createOpencodeClient({\n\t\t\t\tbaseUrl: `http://localhost:${port}`,\n\t\t\t\tdirectory: cwd,\n\t\t\t});\n\t\t\tdebug(`Server started on port ${port}`);\n\t\t\tbreak;\n\t\t} catch (err) {\n\t\t\tif (err instanceof Error && err.message?.includes(\"port\")) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthrow new ServerStartError(\"Failed to start OpenCode server\", port, err);\n\t\t}\n\t}\n\n\tif (!server || !client) {\n\t\tthrow new ServerStartError(\"Failed to start OpenCode server after all attempts\");\n\t}\n\n\tconst providerID = optProvider ?? DEFAULT_AI_PROVIDER;\n\tconst modelID = optModel ?? DEFAULT_AI_MODEL;\n\n\ttry {\n\t\tdebug(\"Creating session...\");\n\t\tconst sessionResult = await client.session.create();\n\t\tif (sessionResult.error) {\n\t\t\tthrow new SessionError(\"Failed to create session\", undefined, undefined, sessionResult.error);\n\t\t}\n\t\tconst sessionId = sessionResult.data.id;\n\t\tdebug(`Session created: ${sessionId}`);\n\n\t\tdebug(\"Validating provider and model...\");\n\t\tconst providerResult = await client.provider.list();\n\t\tif (providerResult.error) {\n\t\t\tthrow new OpenCodeReferenceError(\"Failed to fetch provider list\", providerResult.error);\n\t\t}\n\n\t\tconst { all: allProviders, connected: connectedProviders } = providerResult.data;\n\t\tconst allProviderIds = allProviders.map((p) => p.id);\n\n\t\tconst provider = allProviders.find((p) => p.id === providerID);\n\t\tif (!provider) {\n\t\t\tthrow new InvalidProviderError(providerID, allProviderIds);\n\t\t}\n\n\t\tif (!connectedProviders.includes(providerID)) {\n\t\t\tthrow new ProviderNotConnectedError(providerID, connectedProviders);\n\t\t}\n\n\t\tconst availableModelIds = Object.keys(provider.models);\n\t\tif (!provider.models[modelID]) {\n\t\t\tthrow new InvalidModelError(modelID, providerID, availableModelIds);\n\t\t}\n\n\t\tdebug(`Provider \"${providerID}\" and model \"${modelID}\" validated`);\n\n\t\tdebug(\"Subscribing to events...\");\n\t\tconst { stream: eventStream } = await client.event.subscribe();\n\n\t\tconst fullPrompt = systemPrompt\n\t\t\t? `${systemPrompt}\\n\\nAnalyzing codebase at: ${cwd}\\n\\n${prompt}`\n\t\t\t: `Analyzing codebase at: ${cwd}\\n\\n${prompt}`;\n\n\t\tdebug(\"Sending prompt...\");\n\t\tconst promptPromise = client.session.prompt({\n\t\t\tpath: { id: sessionId },\n\t\t\tbody: {\n\t\t\t\tagent: \"analyze\",\n\t\t\t\tparts: [{ type: \"text\", text: fullPrompt }],\n\t\t\t\tmodel: { providerID, modelID },\n\t\t\t},\n\t\t});\n\n\t\tconst textAccumulator = new TextAccumulator();\n\t\tdebug(\"Waiting for response...\");\n\n\t\tlet timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n\t\tconst processEvents = async (): Promise<string> => {\n\t\t\tfor await (const event of eventStream) {\n\t\t\t\tif (!isEventForSession(event, sessionId)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst parsed = parseStreamEvent(event);\n\n\t\t\t\tswitch (parsed.type) {\n\t\t\t\t\tcase \"message.part.updated\": {\n\t\t\t\t\t\tif (parsed.toolPart?.state) {\n\t\t\t\t\t\t\tconst { state, tool } = parsed.toolPart;\n\t\t\t\t\t\t\tif (state.status === \"running\") {\n\t\t\t\t\t\t\t\tconst message = formatToolMessage(tool, state);\n\t\t\t\t\t\t\t\tif (message) {\n\t\t\t\t\t\t\t\t\tdebug(message);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (parsed.textPart) {\n\t\t\t\t\t\t\tconst delta = textAccumulator.accumulatePart(parsed.textPart);\n\t\t\t\t\t\t\tif (!textAccumulator.hasReceivedText) {\n\t\t\t\t\t\t\t\tdebug(\"Writing reference...\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (delta) {\n\t\t\t\t\t\t\t\tstream(delta);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase \"session.idle\": {\n\t\t\t\t\t\tif (parsed.props.sessionID === sessionId) {\n\t\t\t\t\t\t\tdebug(\"Response complete\");\n\t\t\t\t\t\t\treturn textAccumulator.getFullText();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase \"session.error\": {\n\t\t\t\t\t\tif (parsed.props.sessionID === sessionId) {\n\t\t\t\t\t\t\tconst errorName = parsed.error?.name ?? \"Unknown session error\";\n\t\t\t\t\t\t\tdebug(`Session error: ${JSON.stringify(parsed.props.error)}`);\n\t\t\t\t\t\t\tthrow new SessionError(errorName, sessionId, \"error\", parsed.props.error);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase \"unknown\":\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn textAccumulator.getFullText();\n\t\t};\n\n\t\tlet responseText: string;\n\t\tif (timeoutMs && timeoutMs > 0) {\n\t\t\tconst timeoutPromise = new Promise<never>((_, reject) => {\n\t\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\t\treject(new TimeoutError(timeoutMs, \"session response\"));\n\t\t\t\t}, timeoutMs);\n\t\t\t});\n\t\t\tresponseText = await Promise.race([processEvents(), timeoutPromise]);\n\t\t\tif (timeoutId) clearTimeout(timeoutId);\n\t\t} else {\n\t\t\tresponseText = await processEvents();\n\t\t}\n\n\t\tawait promptPromise;\n\n\t\tif (!responseText) {\n\t\t\tthrow new OpenCodeReferenceError(\"No response received from OpenCode\");\n\t\t}\n\n\t\tdebug(`Response received (${responseText.length} chars)`);\n\n\t\tconst durationMs = Date.now() - startTime;\n\t\tdebug(`Complete in ${durationMs}ms`);\n\n\t\treturn {\n\t\t\ttext: responseText,\n\t\t\tsessionId,\n\t\t\tdurationMs,\n\t\t};\n\t} finally {\n\t\tdebug(\"Closing server...\");\n\t\tserver.close();\n\t}\n}\n","/**\n * Sync utilities for CLI-Convex communication\n * Uses ConvexHttpClient for direct type-safe API calls\n */\n\nimport { ConvexHttpClient } from \"convex/browser\";\nimport { api } from \"@offworld/backend-api/api\";\nimport { toReferenceName } from \"./config.js\";\nimport { GitHubRepoMetadataSchema, type RepoSource } from \"@offworld/types\";\n\nfunction getConvexUrl(): string {\n\treturn process.env.CONVEX_URL || \"\";\n}\n\nconst GITHUB_API_BASE = \"https://api.github.com\";\n\nexport class SyncError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"SyncError\";\n\t}\n}\n\nexport class NetworkError extends SyncError {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly statusCode?: number,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"NetworkError\";\n\t}\n}\n\nexport class AuthenticationError extends SyncError {\n\tconstructor(message = \"Authentication required. Please run 'ow auth login' first.\") {\n\t\tsuper(message);\n\t\tthis.name = \"AuthenticationError\";\n\t}\n}\n\nexport class RateLimitError extends SyncError {\n\tconstructor(message = \"Rate limit exceeded. You can push up to 3 times per repo per day.\") {\n\t\tsuper(message);\n\t\tthis.name = \"RateLimitError\";\n\t}\n}\n\nexport class ConflictError extends SyncError {\n\tconstructor(\n\t\tmessage = \"A newer reference already exists on the server.\",\n\t\tpublic readonly remoteCommitSha?: string,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"ConflictError\";\n\t}\n}\n\nexport class CommitExistsError extends SyncError {\n\tconstructor(message = \"A reference already exists for this commit SHA.\") {\n\t\tsuper(message);\n\t\tthis.name = \"CommitExistsError\";\n\t}\n}\n\nexport class InvalidInputError extends SyncError {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"InvalidInputError\";\n\t}\n}\n\nexport class InvalidReferenceError extends SyncError {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"InvalidReferenceError\";\n\t}\n}\n\nexport class RepoNotFoundError extends SyncError {\n\tconstructor(message = \"Repository not found on GitHub.\") {\n\t\tsuper(message);\n\t\tthis.name = \"RepoNotFoundError\";\n\t}\n}\n\nexport class LowStarsError extends SyncError {\n\tconstructor(message = \"Repository has less than 5 stars.\") {\n\t\tsuper(message);\n\t\tthis.name = \"LowStarsError\";\n\t}\n}\n\nexport class PrivateRepoError extends SyncError {\n\tconstructor(message = \"Private repositories are not supported.\") {\n\t\tsuper(message);\n\t\tthis.name = \"PrivateRepoError\";\n\t}\n}\n\nexport class CommitNotFoundError extends SyncError {\n\tconstructor(message = \"Commit not found in repository.\") {\n\t\tsuper(message);\n\t\tthis.name = \"CommitNotFoundError\";\n\t}\n}\n\nexport class GitHubError extends SyncError {\n\tconstructor(message = \"GitHub API error.\") {\n\t\tsuper(message);\n\t\tthis.name = \"GitHubError\";\n\t}\n}\n\nexport class PushNotAllowedError extends SyncError {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly reason: \"local\" | \"not-github\",\n\t) {\n\t\tsuper(message);\n\t\tthis.name = \"PushNotAllowedError\";\n\t}\n}\n\n/** Reference data structure for sync operations */\nexport interface ReferenceData {\n\tfullName: string;\n\treferenceName: string;\n\treferenceDescription: string;\n\treferenceContent: string;\n\tcommitSha: string;\n\tgeneratedAt: string;\n}\n\n/** Response from pull query */\nexport interface PullResponse {\n\tfullName: string;\n\treferenceName: string;\n\treferenceDescription: string;\n\treferenceContent: string;\n\tcommitSha: string;\n\tgeneratedAt: string;\n}\n\n/** Response from check query */\nexport interface CheckResponse {\n\texists: boolean;\n\tcommitSha?: string;\n\tgeneratedAt?: string;\n}\n\n/** Response from push mutation */\nexport interface PushResponse {\n\tsuccess: boolean;\n\tmessage?: string;\n}\n\n/** Staleness check result */\nexport interface StalenessResult {\n\tisStale: boolean;\n\tlocalCommitSha?: string;\n\tremoteCommitSha?: string;\n}\n\n/** Can push result */\nexport interface CanPushResult {\n\tallowed: boolean;\n\treason?: string;\n\tstars?: number;\n}\n\nfunction createClient(token?: string): ConvexHttpClient {\n\tconst convexUrl = getConvexUrl();\n\tif (!convexUrl) {\n\t\tthrow new SyncError(\n\t\t\t\"CONVEX_URL not configured. \" +\n\t\t\t\t\"For local development, ensure apps/cli/.env contains CONVEX_URL=your_convex_url\",\n\t\t);\n\t}\n\tconst client = new ConvexHttpClient(convexUrl);\n\tif (token) client.setAuth(token);\n\treturn client;\n}\n\n/**\n * Fetches reference from the remote server\n * @param fullName - Repository full name (owner/repo)\n * @returns Reference data or null if not found\n */\nexport async function pullReference(fullName: string): Promise<PullResponse | null> {\n\tconst client = createClient();\n\ttry {\n\t\tlet result = await client.query(api.references.pull, {\n\t\t\tfullName,\n\t\t\treferenceName: toReferenceName(fullName),\n\t\t});\n\t\tif (!result) {\n\t\t\tresult = await client.query(api.references.pull, { fullName });\n\t\t}\n\t\tif (!result) return null;\n\n\t\tclient\n\t\t\t.mutation(api.references.recordPull, { fullName, referenceName: result.referenceName })\n\t\t\t.catch(() => {});\n\n\t\treturn {\n\t\t\tfullName: result.fullName,\n\t\t\treferenceName: result.referenceName,\n\t\t\treferenceDescription: result.referenceDescription,\n\t\t\treferenceContent: result.referenceContent,\n\t\t\tcommitSha: result.commitSha,\n\t\t\tgeneratedAt: result.generatedAt,\n\t\t};\n\t} catch (error) {\n\t\tthrow new NetworkError(\n\t\t\t`Failed to pull reference: ${error instanceof Error ? error.message : error}`,\n\t\t);\n\t}\n}\n\n/**\n * Fetches a specific reference by name from the remote server\n * @param fullName - Repository full name (owner/repo)\n * @param referenceName - Specific reference name to pull\n * @returns Reference data or null if not found\n */\nexport async function pullReferenceByName(\n\tfullName: string,\n\treferenceName: string,\n): Promise<PullResponse | null> {\n\tconst client = createClient();\n\ttry {\n\t\tconst result = await client.query(api.references.pull, { fullName, referenceName });\n\t\tif (!result) return null;\n\n\t\tclient.mutation(api.references.recordPull, { fullName, referenceName }).catch(() => {});\n\n\t\treturn {\n\t\t\tfullName: result.fullName,\n\t\t\treferenceName: result.referenceName,\n\t\t\treferenceDescription: result.referenceDescription,\n\t\t\treferenceContent: result.referenceContent,\n\t\t\tcommitSha: result.commitSha,\n\t\t\tgeneratedAt: result.generatedAt,\n\t\t};\n\t} catch (error) {\n\t\tthrow new NetworkError(\n\t\t\t`Failed to pull reference: ${error instanceof Error ? error.message : error}`,\n\t\t);\n\t}\n}\n\n/**\n * Pushes reference to the remote server\n * All validation happens server-side\n * @param reference - Reference data to push\n * @param token - Authentication token\n * @returns Push result\n */\nexport async function pushReference(\n\treference: ReferenceData,\n\ttoken: string,\n): Promise<PushResponse> {\n\tconst client = createClient(token);\n\ttry {\n\t\tconst result = await client.action(api.references.push, {\n\t\t\tfullName: reference.fullName,\n\t\t\treferenceName: reference.referenceName,\n\t\t\treferenceDescription: reference.referenceDescription,\n\t\t\treferenceContent: reference.referenceContent,\n\t\t\tcommitSha: reference.commitSha,\n\t\t\tgeneratedAt: reference.generatedAt,\n\t\t});\n\n\t\tif (!result.success) {\n\t\t\tswitch (result.error) {\n\t\t\t\tcase \"auth_required\":\n\t\t\t\t\tthrow new AuthenticationError();\n\t\t\t\tcase \"rate_limit\":\n\t\t\t\t\tthrow new RateLimitError(\"Rate limit exceeded. You can push up to 20 times per day.\");\n\t\t\t\tcase \"commit_already_exists\":\n\t\t\t\t\tthrow new CommitExistsError(result.message);\n\t\t\t\tcase \"invalid_input\":\n\t\t\t\t\tthrow new InvalidInputError(result.message ?? \"Invalid input\");\n\t\t\t\tcase \"invalid_reference\":\n\t\t\t\t\tthrow new InvalidReferenceError(result.message ?? \"Invalid reference content\");\n\t\t\t\tcase \"repo_not_found\":\n\t\t\t\t\tthrow new RepoNotFoundError(result.message);\n\t\t\t\tcase \"low_stars\":\n\t\t\t\t\tthrow new LowStarsError(result.message);\n\t\t\t\tcase \"private_repo\":\n\t\t\t\t\tthrow new PrivateRepoError(result.message);\n\t\t\t\tcase \"commit_not_found\":\n\t\t\t\t\tthrow new CommitNotFoundError(result.message);\n\t\t\t\tcase \"github_error\":\n\t\t\t\t\tthrow new GitHubError(result.message);\n\t\t\t\tdefault:\n\t\t\t\t\tthrow new SyncError(result.message ?? \"Unknown error\");\n\t\t\t}\n\t\t}\n\n\t\treturn { success: true };\n\t} catch (error) {\n\t\tif (error instanceof SyncError) throw error;\n\t\tthrow new NetworkError(\n\t\t\t`Failed to push reference: ${error instanceof Error ? error.message : error}`,\n\t\t);\n\t}\n}\n\n/**\n * Checks if reference exists on remote server (lightweight check)\n * @param fullName - Repository full name (owner/repo)\n * @returns Check result\n */\nexport async function checkRemote(fullName: string): Promise<CheckResponse> {\n\tconst client = createClient();\n\ttry {\n\t\tlet result = await client.query(api.references.check, {\n\t\t\tfullName,\n\t\t\treferenceName: toReferenceName(fullName),\n\t\t});\n\t\tif (!result.exists) {\n\t\t\tresult = await client.query(api.references.check, { fullName });\n\t\t}\n\t\tif (!result.exists) {\n\t\t\treturn { exists: false };\n\t\t}\n\t\treturn {\n\t\t\texists: true,\n\t\t\tcommitSha: result.commitSha,\n\t\t\tgeneratedAt: result.generatedAt,\n\t\t};\n\t} catch (error) {\n\t\tthrow new NetworkError(\n\t\t\t`Failed to check remote: ${error instanceof Error ? error.message : error}`,\n\t\t);\n\t}\n}\n\n/**\n * Checks if a specific reference exists on the remote server\n * @param fullName - Repository full name (owner/repo)\n * @param referenceName - Specific reference name to check\n * @returns Check result\n */\nexport async function checkRemoteByName(\n\tfullName: string,\n\treferenceName: string,\n): Promise<CheckResponse> {\n\tconst client = createClient();\n\ttry {\n\t\tconst result = await client.query(api.references.check, { fullName, referenceName });\n\t\tif (!result.exists) {\n\t\t\treturn { exists: false };\n\t\t}\n\t\treturn {\n\t\t\texists: true,\n\t\t\tcommitSha: result.commitSha,\n\t\t\tgeneratedAt: result.generatedAt,\n\t\t};\n\t} catch (error) {\n\t\tthrow new NetworkError(\n\t\t\t`Failed to check remote: ${error instanceof Error ? error.message : error}`,\n\t\t);\n\t}\n}\n\n/**\n * Compares local vs remote commit SHA to check staleness\n * @param fullName - Repository full name (owner/repo)\n * @param localCommitSha - Local commit SHA\n * @returns Staleness result\n */\nexport async function checkStaleness(\n\tfullName: string,\n\tlocalCommitSha: string,\n): Promise<StalenessResult> {\n\tconst remote = await checkRemote(fullName);\n\n\tif (!remote.exists || !remote.commitSha) {\n\t\treturn {\n\t\t\tisStale: false,\n\t\t\tlocalCommitSha,\n\t\t\tremoteCommitSha: undefined,\n\t\t};\n\t}\n\n\treturn {\n\t\tisStale: localCommitSha !== remote.commitSha,\n\t\tlocalCommitSha,\n\t\tremoteCommitSha: remote.commitSha,\n\t};\n}\n\n/** GitHub repository metadata */\nexport interface GitHubRepoMetadata {\n\tstars: number;\n\tdescription?: string;\n\tlanguage?: string;\n\tdefaultBranch: string;\n}\n\n/**\n * Fetches GitHub repository metadata\n * @param owner - Repository owner\n * @param repo - Repository name\n * @returns Repository metadata or null on error\n */\nexport async function fetchGitHubMetadata(\n\towner: string,\n\trepo: string,\n): Promise<GitHubRepoMetadata | null> {\n\ttry {\n\t\tconst response = await fetch(`${GITHUB_API_BASE}/repos/${owner}/${repo}`, {\n\t\t\theaders: {\n\t\t\t\tAccept: \"application/vnd.github.v3+json\",\n\t\t\t\t\"User-Agent\": \"offworld-cli\",\n\t\t\t},\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst json = await response.json();\n\t\tconst result = GitHubRepoMetadataSchema.safeParse(json);\n\t\tif (!result.success) {\n\t\t\treturn null;\n\t\t}\n\t\tconst data = result.data;\n\n\t\treturn {\n\t\t\tstars: data.stargazers_count ?? 0,\n\t\t\tdescription: data.description ?? undefined,\n\t\t\tlanguage: data.language ?? undefined,\n\t\t\tdefaultBranch: data.default_branch ?? \"main\",\n\t\t};\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Fetches GitHub repository stars\n * @param owner - Repository owner\n * @param repo - Repository name\n * @returns Number of stars, or 0 on error\n */\nexport async function fetchRepoStars(owner: string, repo: string): Promise<number> {\n\tconst metadata = await fetchGitHubMetadata(owner, repo);\n\treturn metadata?.stars ?? 0;\n}\n\n/**\n * Checks if a repository can be pushed to offworld.sh (client-side quick checks)\n * Note: Star count and other validations happen server-side\n *\n * @param source - Repository source\n * @returns Can push result\n */\nexport function canPushToWeb(source: RepoSource): CanPushResult {\n\tif (source.type === \"local\") {\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\treason:\n\t\t\t\t\"Local repositories cannot be pushed to offworld.sh. \" +\n\t\t\t\t\"Only remote repositories with a public URL are supported.\",\n\t\t};\n\t}\n\n\tif (source.provider !== \"github\") {\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\treason:\n\t\t\t\t`${source.provider} repositories are not yet supported. ` +\n\t\t\t\t\"GitHub support only for now - GitLab and Bitbucket coming soon!\",\n\t\t};\n\t}\n\n\treturn {\n\t\tallowed: true,\n\t};\n}\n\n/**\n * Validates that a source can be pushed and throws appropriate error if not\n * Note: This only does quick client-side checks. Full validation happens server-side.\n * @param source - Repository source\n * @throws PushNotAllowedError if push is not allowed\n */\nexport function validatePushAllowed(source: RepoSource): void {\n\tconst result = canPushToWeb(source);\n\n\tif (!result.allowed) {\n\t\tconst reason: \"local\" | \"not-github\" = source.type === \"local\" ? \"local\" : \"not-github\";\n\n\t\tthrow new PushNotAllowedError(result.reason!, reason);\n\t}\n}\n","/**\n * Authentication utilities for offworld CLI\n */\n\nimport { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { z } from \"zod\";\nimport { WorkOSTokenResponseSchema } from \"@offworld/types\";\nimport { Paths } from \"./paths\";\n\nconst AuthDataSchema = z.object({\n\ttoken: z.string(),\n\texpiresAt: z.string().optional(),\n\tworkosId: z.string().optional(),\n\trefreshToken: z.string().optional(),\n\temail: z.string().optional(),\n});\n\nexport interface AuthData {\n\ttoken: string;\n\texpiresAt?: string;\n\tworkosId?: string;\n\trefreshToken?: string;\n\temail?: string;\n}\n\n/** Authentication status */\nexport interface AuthStatus {\n\tisLoggedIn: boolean;\n\temail?: string;\n\tworkosId?: string;\n\texpiresAt?: string;\n}\n\nexport class AuthError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"AuthError\";\n\t}\n}\n\nexport class NotLoggedInError extends AuthError {\n\tconstructor(message = \"Not logged in. Please run 'ow auth login' first.\") {\n\t\tsuper(message);\n\t\tthis.name = \"NotLoggedInError\";\n\t}\n}\n\nexport class TokenExpiredError extends AuthError {\n\tconstructor(message = \"Session expired. Please run 'ow auth login' again.\") {\n\t\tsuper(message);\n\t\tthis.name = \"TokenExpiredError\";\n\t}\n}\n\nfunction extractJwtExpiration(token: string): string | undefined {\n\ttry {\n\t\tconst parts = token.split(\".\");\n\t\tif (parts.length !== 3) return undefined;\n\n\t\tconst payload = parts[1];\n\t\tif (!payload) return undefined;\n\n\t\tconst decoded = JSON.parse(Buffer.from(payload, \"base64\").toString(\"utf-8\"));\n\t\tif (typeof decoded.exp !== \"number\") return undefined;\n\n\t\treturn new Date(decoded.exp * 1000).toISOString();\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function getAuthPath(): string {\n\treturn Paths.authFile;\n}\n\nexport function saveAuthData(data: AuthData): void {\n\tconst authPath = getAuthPath();\n\tconst authDir = dirname(authPath);\n\n\tif (!existsSync(authDir)) {\n\t\tmkdirSync(authDir, { recursive: true });\n\t}\n\n\twriteFileSync(authPath, JSON.stringify(data, null, 2), \"utf-8\");\n\tchmodSync(authPath, 0o600);\n}\n\n/**\n * Loads authentication data from ~/.local/share/offworld/auth.json\n * Returns null if file doesn't exist or is invalid\n */\nexport function loadAuthData(): AuthData | null {\n\tconst authPath = getAuthPath();\n\n\tif (!existsSync(authPath)) {\n\t\treturn null;\n\t}\n\n\ttry {\n\t\tconst content = readFileSync(authPath, \"utf-8\");\n\t\tconst json = JSON.parse(content);\n\t\tconst parsed = AuthDataSchema.safeParse(json);\n\n\t\tif (!parsed.success) {\n\t\t\treturn null;\n\t\t}\n\n\t\treturn parsed.data;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Clears stored authentication data\n * @returns true if auth file was deleted, false if it didn't exist\n */\nexport function clearAuthData(): boolean {\n\tconst authPath = getAuthPath();\n\n\tif (!existsSync(authPath)) {\n\t\treturn false;\n\t}\n\n\ttry {\n\t\tunlinkSync(authPath);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nexport async function getToken(): Promise<string> {\n\tconst data = loadAuthData();\n\n\tif (!data) {\n\t\tthrow new NotLoggedInError();\n\t}\n\n\tlet expiresAtStr = data.expiresAt;\n\tif (!expiresAtStr) {\n\t\texpiresAtStr = extractJwtExpiration(data.token);\n\t\tif (expiresAtStr) {\n\t\t\tdata.expiresAt = expiresAtStr;\n\t\t\tsaveAuthData(data);\n\t\t}\n\t}\n\n\tif (expiresAtStr) {\n\t\tconst expiresAt = new Date(expiresAtStr);\n\t\tconst now = new Date();\n\t\tconst oneMinute = 60 * 1000;\n\n\t\tif (expiresAt <= now) {\n\t\t\tif (data.refreshToken) {\n\t\t\t\ttry {\n\t\t\t\t\tconst refreshed = await refreshAccessToken();\n\t\t\t\t\treturn refreshed.token;\n\t\t\t\t} catch {\n\t\t\t\t\tthrow new TokenExpiredError();\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new TokenExpiredError();\n\t\t}\n\n\t\tif (expiresAt.getTime() - now.getTime() < oneMinute) {\n\t\t\tif (data.refreshToken) {\n\t\t\t\ttry {\n\t\t\t\t\tconst refreshed = await refreshAccessToken();\n\t\t\t\t\treturn refreshed.token;\n\t\t\t\t} catch {\n\t\t\t\t\treturn data.token;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn data.token;\n}\n\n/**\n * Gets the current authentication token, or null if not logged in\n * Does not throw errors\n */\nexport async function getTokenOrNull(): Promise<string | null> {\n\ttry {\n\t\treturn await getToken();\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nexport async function isLoggedIn(): Promise<boolean> {\n\treturn (await getTokenOrNull()) !== null;\n}\n\nexport async function getAuthStatus(): Promise<AuthStatus> {\n\tconst data = loadAuthData();\n\n\tif (!data) {\n\t\treturn { isLoggedIn: false };\n\t}\n\n\tif (data.expiresAt) {\n\t\tconst expiresAt = new Date(data.expiresAt);\n\t\tif (expiresAt <= new Date()) {\n\t\t\tif (data.refreshToken) {\n\t\t\t\ttry {\n\t\t\t\t\tconst refreshed = await refreshAccessToken();\n\t\t\t\t\treturn {\n\t\t\t\t\t\tisLoggedIn: true,\n\t\t\t\t\t\temail: refreshed.email,\n\t\t\t\t\t\tworkosId: refreshed.workosId,\n\t\t\t\t\t\texpiresAt: refreshed.expiresAt,\n\t\t\t\t\t};\n\t\t\t\t} catch {\n\t\t\t\t\treturn { isLoggedIn: false };\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { isLoggedIn: false };\n\t\t}\n\t}\n\n\treturn {\n\t\tisLoggedIn: true,\n\t\temail: data.email,\n\t\tworkosId: data.workosId,\n\t\texpiresAt: data.expiresAt,\n\t};\n}\n\nconst WORKOS_API = \"https://api.workos.com\";\n\nfunction getWorkosClientId(): string {\n\treturn process.env.WORKOS_CLIENT_ID || \"\";\n}\n\nexport async function refreshAccessToken(): Promise<AuthData> {\n\tconst data = loadAuthData();\n\n\tif (!data?.refreshToken) {\n\t\tthrow new AuthError(\"No refresh token available. Please log in again.\");\n\t}\n\n\tconst clientId = getWorkosClientId();\n\tif (!clientId) {\n\t\tthrow new AuthError(\"WORKOS_CLIENT_ID not configured\");\n\t}\n\n\ttry {\n\t\tconst response = await fetch(`${WORKOS_API}/user_management/authenticate`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n\t\t\tbody: new URLSearchParams({\n\t\t\t\tgrant_type: \"refresh_token\",\n\t\t\t\trefresh_token: data.refreshToken,\n\t\t\t\tclient_id: clientId,\n\t\t\t}),\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tconst error = await response.text();\n\t\t\tthrow new AuthError(`Token refresh failed: ${error}`);\n\t\t}\n\n\t\tconst json = await response.json();\n\t\tconst tokenData = WorkOSTokenResponseSchema.parse(json);\n\n\t\tconst newAuthData: AuthData = {\n\t\t\ttoken: tokenData.access_token,\n\t\t\temail: tokenData.user.email,\n\t\t\tworkosId: tokenData.user.id,\n\t\t\trefreshToken: tokenData.refresh_token,\n\t\t\texpiresAt: tokenData.expires_at\n\t\t\t\t? new Date(tokenData.expires_at * 1000).toISOString()\n\t\t\t\t: extractJwtExpiration(tokenData.access_token),\n\t\t};\n\n\t\tsaveAuthData(newAuthData);\n\t\treturn newAuthData;\n\t} catch (error) {\n\t\tif (error instanceof AuthError) throw error;\n\t\tthrow new AuthError(\n\t\t\t`Failed to refresh token: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n\t\t);\n\t}\n}\n","/**\n * Agent Registry & Auto-Detection\n *\n * Centralized registry of supported AI coding agents with their\n * skill directory locations and detection functions.\n */\n\nimport { existsSync } from \"node:fs\";\nimport type { Agent } from \"@offworld/types\";\nimport { expandTilde } from \"./paths\";\n\nexport interface AgentConfig {\n\t/** Agent identifier (matches AgentSchema enum) */\n\tname: Agent;\n\t/** Human-readable name for display */\n\tdisplayName: string;\n\t/** Project-level skill directory (relative path) */\n\tskillsDir: string;\n\t/** User-level skill directory (absolute with ~) */\n\tglobalSkillsDir: string;\n\t/** Check if this agent is installed on the system */\n\tdetectInstalled: () => boolean;\n}\n\nexport const agents: Record<Agent, AgentConfig> = {\n\topencode: {\n\t\tname: \"opencode\",\n\t\tdisplayName: \"OpenCode\",\n\t\tskillsDir: \".opencode/skills\",\n\t\tglobalSkillsDir: \"~/.config/opencode/skills\",\n\t\tdetectInstalled: () => existsSync(expandTilde(\"~/.config/opencode\")),\n\t},\n\t\"claude-code\": {\n\t\tname: \"claude-code\",\n\t\tdisplayName: \"Claude Code\",\n\t\tskillsDir: \".claude/skills\",\n\t\tglobalSkillsDir: \"~/.claude/skills\",\n\t\tdetectInstalled: () => existsSync(expandTilde(\"~/.claude\")),\n\t},\n\tcodex: {\n\t\tname: \"codex\",\n\t\tdisplayName: \"Codex (OpenAI)\",\n\t\tskillsDir: \".codex/skills\",\n\t\tglobalSkillsDir: \"~/.codex/skills\",\n\t\tdetectInstalled: () => existsSync(expandTilde(\"~/.codex\")),\n\t},\n\tamp: {\n\t\tname: \"amp\",\n\t\tdisplayName: \"Amp\",\n\t\tskillsDir: \".agents/skills\",\n\t\tglobalSkillsDir: \"~/.config/agents/skills\",\n\t\tdetectInstalled: () => existsSync(expandTilde(\"~/.config/amp\")),\n\t},\n\tantigravity: {\n\t\tname: \"antigravity\",\n\t\tdisplayName: \"Antigravity\",\n\t\tskillsDir: \".agent/skills\",\n\t\tglobalSkillsDir: \"~/.gemini/antigravity/skills\",\n\t\tdetectInstalled: () => existsSync(expandTilde(\"~/.gemini/antigravity\")),\n\t},\n\tcursor: {\n\t\tname: \"cursor\",\n\t\tdisplayName: \"Cursor\",\n\t\tskillsDir: \".cursor/skills\",\n\t\tglobalSkillsDir: \"~/.cursor/skills\",\n\t\tdetectInstalled: () => existsSync(expandTilde(\"~/.cursor\")),\n\t},\n};\n\n/**\n * Detect which agents are installed on the system.\n * Checks for the existence of each agent's config directory.\n *\n * @returns Array of installed agent identifiers\n */\nexport function detectInstalledAgents(): Agent[] {\n\tconst installed: Agent[] = [];\n\n\tfor (const config of Object.values(agents)) {\n\t\tif (config.detectInstalled()) {\n\t\t\tinstalled.push(config.name);\n\t\t}\n\t}\n\n\treturn installed;\n}\n\n/**\n * Get the configuration for a specific agent.\n *\n * @param type - Agent identifier\n * @returns AgentConfig for the specified agent\n */\nexport function getAgentConfig(type: Agent): AgentConfig {\n\treturn agents[type];\n}\n\n/**\n * Get all agent configurations as an array.\n *\n * @returns Array of all agent configurations\n */\nexport function getAllAgentConfigs(): AgentConfig[] {\n\treturn Object.values(agents);\n}\n","/**\n * This module provides a streamlined approach to generating reference files\n * by delegating all codebase exploration to the AI agent via OpenCode.\n */\n\nimport {\n\tmkdirSync,\n\twriteFileSync,\n\treadFileSync,\n\tlstatSync,\n\tunlinkSync,\n\trmSync,\n\tsymlinkSync,\n\texistsSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\nimport { z } from \"zod\";\nimport { streamPrompt, type StreamPromptOptions } from \"./ai/opencode.js\";\nimport { loadConfig, toReferenceName, toMetaDirName, toReferenceFileName } from \"./config.js\";\nimport { getCommitSha } from \"./clone.js\";\nimport { agents } from \"./agents.js\";\nimport { expandTilde, Paths } from \"./paths.js\";\nimport { readGlobalMap, writeGlobalMap } from \"./index-manager.js\";\n\nconst PackageJsonKeywordsSchema = z.object({\n\tname: z.string().optional(),\n\tkeywords: z.array(z.string()).optional(),\n});\n\nexport interface GenerateReferenceOptions {\n\t/** AI provider ID (e.g., \"anthropic\", \"openai\"). Defaults to config value. */\n\tprovider?: string;\n\t/** AI model ID. Defaults to config value. */\n\tmodel?: string;\n\t/** Debug callback for detailed logging */\n\tonDebug?: (message: string) => void;\n\t/** Stream callback for real-time AI output */\n\tonStream?: (text: string) => void;\n}\n\nexport interface GenerateReferenceResult {\n\t/** The generated reference markdown content */\n\treferenceContent: string;\n\t/** The commit SHA at the time of generation */\n\tcommitSha: string;\n}\n\nexport interface InstallReferenceMeta {\n\t/** ISO timestamp when the reference was generated */\n\treferenceUpdatedAt: string;\n\t/** Git commit SHA at time of generation */\n\tcommitSha: string;\n\t/** SDK version used for generation */\n\tversion: string;\n}\n\nfunction normalizeKeyword(value: string): string[] {\n\tconst trimmed = value.trim();\n\tif (!trimmed) return [];\n\tconst normalized = trimmed.toLowerCase();\n\tconst tokens = new Set<string>();\n\n\tconst addToken = (token: string): void => {\n\t\tconst cleaned = token.trim().toLowerCase();\n\t\tif (cleaned.length < 2) return;\n\t\ttokens.add(cleaned);\n\t};\n\n\taddToken(normalized);\n\taddToken(normalized.replaceAll(\"/\", \"-\"));\n\taddToken(normalized.replaceAll(\"/\", \"\"));\n\n\tfor (const token of normalized.split(/[\\s/_-]+/)) {\n\t\taddToken(token);\n\t}\n\n\tif (normalized.startsWith(\"@\")) {\n\t\taddToken(normalized.slice(1));\n\t}\n\n\treturn Array.from(tokens);\n}\n\nfunction deriveKeywords(fullName: string, localPath: string, referenceContent: string): string[] {\n\tconst keywords = new Set<string>();\n\n\tconst addKeywords = (value: string): void => {\n\t\tfor (const token of normalizeKeyword(value)) {\n\t\t\tkeywords.add(token);\n\t\t}\n\t};\n\n\taddKeywords(fullName);\n\n\tconst headingMatch = referenceContent.match(/^#\\s+(.+)$/m);\n\tif (headingMatch?.[1]) {\n\t\taddKeywords(headingMatch[1]);\n\t}\n\n\tconst packageJsonPath = join(localPath, \"package.json\");\n\tif (existsSync(packageJsonPath)) {\n\t\ttry {\n\t\t\tconst content = readFileSync(packageJsonPath, \"utf-8\");\n\t\t\tconst json = JSON.parse(content);\n\t\t\tconst parsed = PackageJsonKeywordsSchema.safeParse(json);\n\n\t\t\tif (parsed.success) {\n\t\t\t\tif (parsed.data.name) {\n\t\t\t\t\taddKeywords(parsed.data.name);\n\t\t\t\t}\n\n\t\t\t\tif (parsed.data.keywords) {\n\t\t\t\t\tfor (const keyword of parsed.data.keywords) {\n\t\t\t\t\t\taddKeywords(keyword);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {}\n\t}\n\n\treturn Array.from(keywords);\n}\n\nfunction createReferenceGenerationPrompt(referenceName: string): string {\n\treturn `You are an expert at analyzing open source libraries and producing reference documentation for AI coding agents.\n\n## PRIMARY GOAL\n\nGenerate a reference markdown file that helps developers USE this library effectively. This is NOT a contribution guide - it's a usage reference for developers consuming this library in their own projects.\n\n## CRITICAL RULES\n\n1. **USER PERSPECTIVE ONLY**: Write for developers who will npm/pip/cargo install this library and use it in THEIR code.\n - DO NOT include: how to contribute, internal test commands, repo-specific policies\n - DO NOT include: \"never mock in tests\" or similar internal dev guidelines\n - DO NOT include: commands like \"npx hereby\", \"just ready\", \"bun test\" that run the library's own tests\n - DO include: how to install, import, configure, and use the public API\n\n2. **NO FRONTMATTER**: Output pure markdown with NO YAML frontmatter. Start directly with the library name heading.\n\n3. **QUICK REFERENCES**: Include a \"Quick References\" section with paths to key entry points in the repo:\n - Paths must be relative from repo root (e.g., \\`src/index.ts\\`, \\`docs/api.md\\`)\n - Include: main entry point, type definitions, README, key docs\n - DO NOT include absolute paths or user-specific paths\n - Keep to 3-5 most important files that help users understand the library\n\n4. **PUBLIC API FOCUS**: Document what users import and call, not internal implementation details.\n - Entry points: what to import from the package\n - Configuration: how to set up/initialize\n - Core methods/functions: the main API surface\n - Types: key TypeScript interfaces users need\n\n5. **MONOREPO AWARENESS**: Many libraries are monorepos with multiple packages:\n - Check for \\`packages/\\`, \\`apps/\\`, \\`crates/\\`, or \\`libs/\\` directories\n - Check root package.json for \\`workspaces\\` field\n - If monorepo: document the package structure and key packages users would install\n - Use full paths from repo root (e.g., \\`packages/core/src/index.ts\\`)\n - Identify which packages are publishable vs internal\n\n## EXPLORATION STEPS\n\nUse Read, Grep, Glob tools to explore:\n1. Root package.json / Cargo.toml - check for workspaces/monorepo config\n2. Check for \\`packages/\\`, \\`apps/\\`, \\`crates/\\` directories\n3. README.md - official usage documentation\n4. For monorepos: explore each publishable package's entry point\n5. docs/ or website/ - find documentation\n6. examples/ - real usage patterns\n7. TypeScript definitions (.d.ts) - public API surface\n\n## OUTPUT FORMAT\n\nIMPORTANT: Reference name is \"${referenceName}\" (for internal tracking only - do NOT include in output).\n\n\\`\\`\\`markdown\n# {Library Name}\n\n{2-3 sentence overview of what this library does and its key value proposition}\n\n## Quick References\n\n| File | Purpose |\n|------|---------|\n| \\`packages/{pkg}/src/index.ts\\` | Main entry point (monorepo example) |\n| \\`src/index.ts\\` | Main entry point (single-package example) |\n| \\`README.md\\` | Documentation |\n\n(For monorepos, include paths to key publishable packages)\n\n## Packages (for monorepos only)\n\n| Package | npm name | Description |\n|---------|----------|-------------|\n| \\`packages/core\\` | \\`@scope/core\\` | Core functionality |\n| \\`packages/react\\` | \\`@scope/react\\` | React bindings |\n\n(OMIT this section for single-package repos)\n\n## When to Use\n\n- {Practical scenario where a developer would reach for this library}\n- {Another real-world use case}\n- {Problem this library solves}\n\n## Installation\n\n\\`\\`\\`bash\n# Single package\nnpm install {package-name}\n\n# Monorepo (show key packages)\nnpm install @scope/core @scope/react\n\\`\\`\\`\n\n## Best Practices\n\n1. {Actionable best practice for USERS of this library}\n2. {Common mistake to avoid when using this library}\n3. {Performance or correctness tip}\n\n## Common Patterns\n\n**{Pattern Name}:**\n\\`\\`\\`{language}\n{Minimal working code example}\n\\`\\`\\`\n\n**{Another Pattern}:**\n\\`\\`\\`{language}\n{Another code example}\n\\`\\`\\`\n\n## API Quick Reference\n\n| Export | Type | Description |\n|--------|------|-------------|\n| \\`{main export}\\` | {type} | {what it does} |\n| \\`{another export}\\` | {type} | {what it does} |\n\n{Add more sections as appropriate for the library: Configuration, Types, CLI Commands (if user-facing), etc.}\n\\`\\`\\`\n\n## QUALITY CHECKLIST\n\nBefore outputting, verify:\n- [ ] NO YAML frontmatter - start directly with # heading\n- [ ] Every code example is something a USER would write, not a contributor\n- [ ] No internal test commands or contribution workflows\n- [ ] Quick References paths are relative from repo root (no absolute/user paths)\n- [ ] Best practices are for using the library, not developing it\n- [ ] If monorepo: Packages section lists publishable packages with npm names\n- [ ] If monorepo: paths include package directory (e.g., \\`packages/core/src/index.ts\\`)\n\nNow explore the codebase and generate the reference content.\n\nCRITICAL: Wrap your final reference output in XML tags exactly like this:\n<reference_output>\n# {Library Name}\n(the complete markdown content with NO frontmatter)\n</reference_output>\n\nOutput ONLY the reference content inside the tags. No explanations before or after the tags.`;\n}\n\n/**\n * Extract the actual reference markdown content from AI response.\n * The response may include echoed prompt/system context before the actual reference.\n * We look for the LAST occurrence of XML tags: <reference_output>...</reference_output>\n * (Using last occurrence avoids extracting example tags from echoed prompt)\n */\nfunction extractReferenceContent(rawResponse: string): string {\n\tconst openTag = \"<reference_output>\";\n\tconst closeTag = \"</reference_output>\";\n\tconst closeIndex = rawResponse.lastIndexOf(closeTag);\n\n\tif (closeIndex !== -1) {\n\t\tconst openIndex = rawResponse.lastIndexOf(openTag, closeIndex);\n\n\t\tif (openIndex !== -1) {\n\t\t\tlet content = rawResponse.slice(openIndex + openTag.length, closeIndex).trim();\n\n\t\t\tif (content.startsWith(\"```\")) {\n\t\t\t\tcontent = content.replace(/^```(?:markdown)?\\s*\\n?/, \"\");\n\t\t\t\tcontent = content.replace(/\\n?```\\s*$/, \"\");\n\t\t\t}\n\n\t\t\tcontent = content.trim();\n\t\t\tvalidateReferenceContent(content);\n\t\t\treturn content;\n\t\t}\n\t}\n\n\tthrow new Error(\n\t\t\"Failed to extract reference content: no <reference_output> tags found in AI response. \" +\n\t\t\t\"The AI may have failed to follow the output format instructions.\",\n\t);\n}\n\n/**\n * Validate extracted reference content has minimum required structure.\n * Throws if content is invalid.\n */\nfunction validateReferenceContent(content: string): void {\n\tif (content.length < 500) {\n\t\tthrow new Error(\n\t\t\t`Invalid reference content: too short (${content.length} chars, minimum 500). ` +\n\t\t\t\t\"The AI may have produced placeholder or incomplete content.\",\n\t\t);\n\t}\n\n\tif (!content.startsWith(\"#\")) {\n\t\tthrow new Error(\n\t\t\t\"Invalid reference content: must start with markdown heading. \" +\n\t\t\t\t\"Content must begin with '# Library Name' (no YAML frontmatter).\",\n\t\t);\n\t}\n}\n\n/**\n * Generate a reference markdown file for a repository using AI.\n *\n * Opens an OpenCode session and instructs the AI agent to explore the codebase\n * using Read, Grep, and Glob tools, then produce a comprehensive reference.\n *\n * @param repoPath - Path to the repository to analyze\n * @param repoName - Qualified name of the repo (e.g., \"tanstack/query\" or \"my-local-repo\")\n * @param options - Generation options (provider, model, callbacks)\n * @returns The generated reference content and commit SHA\n */\nexport async function generateReferenceWithAI(\n\trepoPath: string,\n\trepoName: string,\n\toptions: GenerateReferenceOptions = {},\n): Promise<GenerateReferenceResult> {\n\tconst { provider, model, onDebug, onStream } = options;\n\tconst config = loadConfig();\n\n\tconst [configProvider, configModel] = config.defaultModel?.split(\"/\") ?? [];\n\tconst aiProvider = provider ?? configProvider;\n\tconst aiModel = model ?? configModel;\n\n\tonDebug?.(`Starting AI reference generation for ${repoName}`);\n\tonDebug?.(`Repo path: ${repoPath}`);\n\tonDebug?.(`Provider: ${aiProvider ?? \"default\"}, Model: ${aiModel ?? \"default\"}`);\n\n\tconst commitSha = getCommitSha(repoPath);\n\tonDebug?.(`Commit SHA: ${commitSha}`);\n\n\tconst referenceName = toReferenceName(repoName);\n\tonDebug?.(`Reference name: ${referenceName}`);\n\n\tconst promptOptions: StreamPromptOptions = {\n\t\tprompt: createReferenceGenerationPrompt(referenceName),\n\t\tcwd: repoPath,\n\t\tprovider: aiProvider,\n\t\tmodel: aiModel,\n\t\tonDebug,\n\t\tonStream,\n\t};\n\n\tconst result = await streamPrompt(promptOptions);\n\n\tonDebug?.(`Generation complete (${result.durationMs}ms, ${result.text.length} chars)`);\n\n\tconst referenceContent = extractReferenceContent(result.text);\n\tonDebug?.(`Extracted reference content (${referenceContent.length} chars)`);\n\n\treturn {\n\t\treferenceContent,\n\t\tcommitSha,\n\t};\n}\n\n/**\n * Ensure a symlink exists, removing any existing file/directory at the path\n */\nfunction ensureSymlink(target: string, linkPath: string): void {\n\ttry {\n\t\tconst stat = lstatSync(linkPath);\n\t\tif (stat.isSymbolicLink()) {\n\t\t\tunlinkSync(linkPath);\n\t\t} else if (stat.isDirectory()) {\n\t\t\trmSync(linkPath, { recursive: true });\n\t\t} else {\n\t\t\tunlinkSync(linkPath);\n\t\t}\n\t} catch {}\n\n\tconst linkDir = join(linkPath, \"..\");\n\tmkdirSync(linkDir, { recursive: true });\n\tsymlinkSync(target, linkPath, \"dir\");\n}\n\n/**\n * Static template for the global SKILL.md file.\n * This is the single routing skill that all agents see.\n */\nconst GLOBAL_SKILL_TEMPLATE = `---\nname: offworld\ndescription: Routes queries to Offworld reference files. Find and read per-repo references for dependency knowledge.\nallowed-tools: Bash(ow:*) Read\n---\n\n# Offworld Reference Router\n\nUse \\`ow\\` to locate and read Offworld reference files for dependencies.\n\n## What This Does\n\n- Finds references for libraries and repos\n- Returns paths for reference files and local clones\n- Helps you read the right context fast\n\n## When to Use\n\n- You need docs or patterns for a dependency\n- You want the verified reference instead of web search\n- You are about to work inside a repo clone\n\n## Prerequisites\n\nCheck that the CLI is available:\n\n\\`\\`\\`bash\now --version\n\\`\\`\\`\n\nIf \\`ow\\` is not available, install it:\n\n\\`\\`\\`bash\ncurl -fsSL https://offworld.sh/install | bash\n\\`\\`\\`\n\n## Setup\n\nInitialize Offworld once per machine:\n\n\\`\\`\\`bash\now init\n\\`\\`\\`\n\nFor a specific project, build a project map:\n\n\\`\\`\\`bash\now project init\n\\`\\`\\`\n\n## Usage\n\n**Find a reference:**\n\\`\\`\\`bash\now map search <term> # search by name or keyword\now map show <repo> # get info for specific repo\n\\`\\`\\`\n\n**Get paths for tools:**\n\\`\\`\\`bash\now map show <repo> --ref # reference file path (use with Read)\now map show <repo> --path # clone directory path\n\\`\\`\\`\n\n**Example workflow:**\n\\`\\`\\`bash\n# 1. Find the repo\now map search zod\n\n# 2. Get reference path\now map show colinhacks/zod --ref\n# Output: /Users/.../.local/share/offworld/skill/offworld/references/colinhacks-zod.md\n\n# 3. Read the reference with the path from step 2\n\\`\\`\\`\n\n## If Reference Not Found\n\n\\`\\`\\`bash\now pull <owner/repo> # clone + generate reference\now project init # scan project deps, install references\n\\`\\`\\`\n\n## Notes\n\n- Project map (\\`.offworld/map.json\\`) takes precedence over global map when present\n- Reference files are markdown with API docs, patterns, best practices\n- Clone paths useful for exploring source code after reading reference\n\n## Additional Resources\n\n- Docs: https://offworld.sh/cli\n`;\n\n/**\n * Ensures the global SKILL.md exists and symlinks the offworld/ directory to all agent skill directories.\n *\n * Creates:\n * - ~/.local/share/offworld/skill/offworld/SKILL.md (static routing template)\n * - ~/.local/share/offworld/skill/offworld/assets/ (for map.json)\n * - ~/.local/share/offworld/skill/offworld/references/ (for reference files)\n * - Symlinks entire offworld/ directory to each agent's skill directory\n */\nexport function installGlobalSkill(): void {\n\tconst config = loadConfig();\n\n\tmkdirSync(Paths.offworldSkillDir, { recursive: true });\n\tmkdirSync(Paths.offworldAssetsDir, { recursive: true });\n\tmkdirSync(Paths.offworldReferencesDir, { recursive: true });\n\n\tconst skillPath = join(Paths.offworldSkillDir, \"SKILL.md\");\n\tif (!existsSync(skillPath)) {\n\t\twriteFileSync(skillPath, GLOBAL_SKILL_TEMPLATE, \"utf-8\");\n\t}\n\n\tconst configuredAgents = config.agents ?? [];\n\tfor (const agentName of configuredAgents) {\n\t\tconst agentConfig = agents[agentName];\n\t\tif (agentConfig) {\n\t\t\tconst agentSkillDir = expandTilde(join(agentConfig.globalSkillsDir, \"offworld\"));\n\t\t\tensureSymlink(Paths.offworldSkillDir, agentSkillDir);\n\t\t}\n\t}\n}\n\n/**\n * Install a reference file for a specific repository.\n *\n * Creates:\n * - ~/.local/share/offworld/skill/offworld/references/{owner-repo}.md\n * - ~/.local/share/offworld/meta/{owner-repo}/meta.json\n * - Updates global map with reference info\n *\n * @param qualifiedName - Qualified key for map storage (e.g., \"github.com:owner/repo\" or \"local:name\")\n * @param fullName - Full repo name for file naming (e.g., \"owner/repo\")\n * @param localPath - Absolute path to the cloned repository\n * @param referenceContent - The generated reference markdown content\n * @param meta - Metadata about the generation (referenceUpdatedAt, commitSha, version)\n * @param keywords - Optional array of keywords for search/routing\n */\nexport function installReference(\n\tqualifiedName: string,\n\tfullName: string,\n\tlocalPath: string,\n\treferenceContent: string,\n\tmeta: InstallReferenceMeta,\n\tkeywords?: string[],\n): void {\n\tinstallGlobalSkill();\n\n\tconst referenceFileName = toReferenceFileName(fullName);\n\tconst metaDirName = toMetaDirName(fullName);\n\n\tconst referencePath = join(Paths.offworldReferencesDir, referenceFileName);\n\tmkdirSync(Paths.offworldReferencesDir, { recursive: true });\n\twriteFileSync(referencePath, referenceContent, \"utf-8\");\n\n\tconst metaDir = join(Paths.metaDir, metaDirName);\n\tmkdirSync(metaDir, { recursive: true });\n\tconst metaJson = JSON.stringify(meta, null, 2);\n\twriteFileSync(join(metaDir, \"meta.json\"), metaJson, \"utf-8\");\n\n\tconst map = readGlobalMap();\n\tconst existingEntry = map.repos[qualifiedName];\n\tconst legacyProviderMap: Record<string, string> = {\n\t\t\"github.com\": \"github\",\n\t\t\"gitlab.com\": \"gitlab\",\n\t\t\"bitbucket.org\": \"bitbucket\",\n\t};\n\tconst [host] = qualifiedName.split(\":\");\n\tconst legacyProvider = host ? legacyProviderMap[host] : undefined;\n\tconst legacyQualifiedName = legacyProvider ? `${legacyProvider}:${fullName}` : undefined;\n\tconst legacyEntry = legacyQualifiedName ? map.repos[legacyQualifiedName] : undefined;\n\n\tconst references = [...(existingEntry?.references ?? []), ...(legacyEntry?.references ?? [])];\n\tif (!references.includes(referenceFileName)) {\n\t\treferences.push(referenceFileName);\n\t}\n\n\tconst derivedKeywords = keywords ?? deriveKeywords(fullName, localPath, referenceContent);\n\tconst keywordsSet = new Set<string>([\n\t\t...(existingEntry?.keywords ?? []),\n\t\t...(legacyEntry?.keywords ?? []),\n\t\t...derivedKeywords,\n\t]);\n\n\tmap.repos[qualifiedName] = {\n\t\tlocalPath,\n\t\treferences,\n\t\tprimary: referenceFileName,\n\t\tkeywords: Array.from(keywordsSet),\n\t\tupdatedAt: new Date().toISOString(),\n\t};\n\n\tif (legacyQualifiedName && legacyQualifiedName in map.repos) {\n\t\tdelete map.repos[legacyQualifiedName];\n\t}\n\n\twriteGlobalMap(map);\n}\n","/**\n * Dependency manifest parsing for multiple package ecosystems\n */\n\nimport { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport type { Dirent } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport type ManifestType = \"npm\" | \"python\" | \"rust\" | \"go\" | \"unknown\";\n\nexport interface Dependency {\n\tname: string;\n\tversion?: string;\n\tdev: boolean;\n}\n\nconst DEFAULT_IGNORED_DIRS = new Set([\n\t\".git\",\n\t\".offworld\",\n\t\".turbo\",\n\t\"build\",\n\t\"dist\",\n\t\"node_modules\",\n\t\"out\",\n]);\n\n/**\n * Detects the manifest type in a directory\n */\nexport function detectManifestType(dir: string): ManifestType {\n\tif (existsSync(join(dir, \"package.json\"))) return \"npm\";\n\tif (existsSync(join(dir, \"pyproject.toml\"))) return \"python\";\n\tif (existsSync(join(dir, \"Cargo.toml\"))) return \"rust\";\n\tif (existsSync(join(dir, \"go.mod\"))) return \"go\";\n\tif (existsSync(join(dir, \"requirements.txt\"))) return \"python\";\n\treturn \"unknown\";\n}\n\n/**\n * Parses dependencies from manifest files\n */\nexport function parseDependencies(dir: string): Dependency[] {\n\tconst type = detectManifestType(dir);\n\n\tswitch (type) {\n\t\tcase \"npm\":\n\t\t\treturn parseNpmDependencies(dir);\n\t\tcase \"python\":\n\t\t\treturn existsSync(join(dir, \"pyproject.toml\"))\n\t\t\t\t? parsePyprojectToml(join(dir, \"pyproject.toml\"))\n\t\t\t\t: parseRequirementsTxt(join(dir, \"requirements.txt\"));\n\t\tcase \"rust\":\n\t\t\treturn parseCargoToml(join(dir, \"Cargo.toml\"));\n\t\tcase \"go\":\n\t\t\treturn parseGoMod(join(dir, \"go.mod\"));\n\t\tdefault:\n\t\t\treturn [];\n\t}\n}\n\nfunction parseNpmDependencies(dir: string): Dependency[] {\n\tconst rootPath = join(dir, \"package.json\");\n\tconst rootDeps = parsePackageJson(rootPath);\n\tconst workspaceDeps = parseWorkspaceDependencies(dir);\n\treturn mergeDependencies(rootDeps, workspaceDeps).sort((a, b) => a.name.localeCompare(b.name));\n}\n\nfunction parseWorkspaceDependencies(dir: string): Dependency[] {\n\tconst workspacePatterns = getWorkspacePatterns(dir);\n\tif (workspacePatterns.length === 0) return [];\n\n\tconst packageJsonPaths = resolveWorkspacePackageJsonPaths(dir, workspacePatterns);\n\tconst deps: Dependency[] = [];\n\tfor (const path of packageJsonPaths) {\n\t\tdeps.push(...parsePackageJson(path));\n\t}\n\n\treturn mergeDependencies([], deps);\n}\n\nfunction getWorkspacePatterns(dir: string): string[] {\n\tconst patterns = new Set<string>();\n\n\tconst packageJsonPath = join(dir, \"package.json\");\n\tif (existsSync(packageJsonPath)) {\n\t\tconst rootJson = readJson(packageJsonPath);\n\t\tconst workspaces = rootJson?.workspaces;\n\t\tif (Array.isArray(workspaces)) {\n\t\t\tfor (const pattern of workspaces) {\n\t\t\t\tif (typeof pattern === \"string\") patterns.add(pattern);\n\t\t\t}\n\t\t} else if (workspaces && typeof workspaces === \"object\") {\n\t\t\tconst packagesField = (workspaces as { packages?: unknown }).packages;\n\t\t\tif (Array.isArray(packagesField)) {\n\t\t\t\tfor (const pattern of packagesField) {\n\t\t\t\t\tif (typeof pattern === \"string\") patterns.add(pattern);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tconst pnpmWorkspacePath = existsSync(join(dir, \"pnpm-workspace.yaml\"))\n\t\t? join(dir, \"pnpm-workspace.yaml\")\n\t\t: existsSync(join(dir, \"pnpm-workspace.yml\"))\n\t\t\t? join(dir, \"pnpm-workspace.yml\")\n\t\t\t: null;\n\n\tif (pnpmWorkspacePath) {\n\t\tfor (const pattern of parsePnpmWorkspacePackages(pnpmWorkspacePath)) {\n\t\t\tpatterns.add(pattern);\n\t\t}\n\t}\n\n\treturn Array.from(patterns);\n}\n\nfunction resolveWorkspacePackageJsonPaths(dir: string, patterns: string[]): string[] {\n\tconst includePatterns = patterns.filter((pattern) => !pattern.startsWith(\"!\"));\n\tconst excludePatterns = patterns\n\t\t.filter((pattern) => pattern.startsWith(\"!\"))\n\t\t.map((pattern) => pattern.slice(1));\n\n\tif (includePatterns.length === 0) return [];\n\n\tconst includeRegexes = includePatterns.map(patternToRegex);\n\tconst excludeRegexes = excludePatterns.map(patternToRegex);\n\n\tconst matches: string[] = [];\n\tconst directories = walkDirectories(dir);\n\n\tfor (const relativePath of directories) {\n\t\tif (!includeRegexes.some((regex) => regex.test(relativePath))) continue;\n\t\tif (excludeRegexes.some((regex) => regex.test(relativePath))) continue;\n\n\t\tconst packageJsonPath = join(dir, relativePath, \"package.json\");\n\t\tif (existsSync(packageJsonPath)) {\n\t\t\tmatches.push(packageJsonPath);\n\t\t}\n\t}\n\n\treturn Array.from(new Set(matches));\n}\n\nfunction walkDirectories(root: string): string[] {\n\tconst results: string[] = [];\n\tconst stack: string[] = [\"\"];\n\n\twhile (stack.length > 0) {\n\t\tconst relativePath = stack.pop();\n\t\tconst currentPath = relativePath ? join(root, relativePath) : root;\n\n\t\tlet entries: Dirent[];\n\t\ttry {\n\t\t\tentries = readdirSync(currentPath, { withFileTypes: true }) as Dirent[];\n\t\t} catch {\n\t\t\tcontinue;\n\t\t}\n\n\t\tfor (const entry of entries) {\n\t\t\tif (!entry.isDirectory()) continue;\n\t\t\tif (DEFAULT_IGNORED_DIRS.has(entry.name)) continue;\n\n\t\t\tconst nextRelative = relativePath ? `${relativePath}/${entry.name}` : entry.name;\n\t\t\tresults.push(nextRelative);\n\t\t\tstack.push(nextRelative);\n\t\t}\n\t}\n\n\treturn results;\n}\n\nfunction patternToRegex(pattern: string): RegExp {\n\tlet normalized = pattern.trim().replace(/\\\\/g, \"/\");\n\tif (normalized.startsWith(\"./\")) normalized = normalized.slice(2);\n\tif (normalized.endsWith(\"/\")) normalized = normalized.slice(0, -1);\n\n\tconst escaped = normalized.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\tconst withGlob = escaped.replace(/\\\\\\*\\\\\\*/g, \".*\").replace(/\\\\\\*/g, \"[^/]+\");\n\n\treturn new RegExp(`^${withGlob}$`);\n}\n\nfunction parsePnpmWorkspacePackages(path: string): string[] {\n\ttry {\n\t\tconst content = readFileSync(path, \"utf-8\");\n\t\tconst lines = content.split(\"\\n\");\n\t\tconst patterns: string[] = [];\n\t\tlet inPackages = false;\n\n\t\tfor (const line of lines) {\n\t\t\tconst trimmed = line.trim();\n\t\t\tif (!trimmed || trimmed.startsWith(\"#\")) continue;\n\n\t\t\tif (/^packages\\s*:/.test(trimmed)) {\n\t\t\t\tinPackages = true;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!inPackages) continue;\n\n\t\t\tconst entryMatch = trimmed.match(/^-\\s*(.+)$/);\n\t\t\tif (entryMatch?.[1]) {\n\t\t\t\tconst value = entryMatch[1].trim().replace(/^['\"]|['\"]$/g, \"\");\n\t\t\t\tif (value) patterns.push(value);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!line.startsWith(\" \") && !line.startsWith(\"\\t\")) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn patterns;\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction readJson(path: string): Record<string, unknown> | null {\n\ttry {\n\t\tconst content = readFileSync(path, \"utf-8\");\n\t\treturn JSON.parse(content) as Record<string, unknown>;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction mergeDependencies(base: Dependency[], incoming: Dependency[]): Dependency[] {\n\tconst map = new Map<string, Dependency>();\n\n\tfor (const dep of [...base, ...incoming]) {\n\t\tconst existing = map.get(dep.name);\n\t\tif (!existing) {\n\t\t\tmap.set(dep.name, { ...dep });\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst dev = existing.dev && dep.dev;\n\t\tconst version = existing.version ?? dep.version;\n\t\tmap.set(dep.name, { name: dep.name, version, dev });\n\t}\n\n\treturn Array.from(map.values());\n}\n\n/**\n * Parse package.json dependencies\n */\nfunction parsePackageJson(path: string): Dependency[] {\n\ttry {\n\t\tconst content = readFileSync(path, \"utf-8\");\n\t\tconst pkg = JSON.parse(content);\n\t\tconst deps: Dependency[] = [];\n\n\t\tif (pkg.dependencies && typeof pkg.dependencies === \"object\") {\n\t\t\tfor (const [name, version] of Object.entries(pkg.dependencies)) {\n\t\t\t\tdeps.push({ name, version: version as string, dev: false });\n\t\t\t}\n\t\t}\n\n\t\tif (pkg.devDependencies && typeof pkg.devDependencies === \"object\") {\n\t\t\tfor (const [name, version] of Object.entries(pkg.devDependencies)) {\n\t\t\t\tdeps.push({ name, version: version as string, dev: true });\n\t\t\t}\n\t\t}\n\n\t\tif (pkg.peerDependencies && typeof pkg.peerDependencies === \"object\") {\n\t\t\tfor (const [name, version] of Object.entries(pkg.peerDependencies)) {\n\t\t\t\tdeps.push({ name, version: version as string, dev: false });\n\t\t\t}\n\t\t}\n\n\t\tif (pkg.optionalDependencies && typeof pkg.optionalDependencies === \"object\") {\n\t\t\tfor (const [name, version] of Object.entries(pkg.optionalDependencies)) {\n\t\t\t\tdeps.push({ name, version: version as string, dev: false });\n\t\t\t}\n\t\t}\n\n\t\treturn deps;\n\t} catch {\n\t\treturn [];\n\t}\n}\n\n/**\n * Parse pyproject.toml dependencies\n */\nfunction parsePyprojectToml(path: string): Dependency[] {\n\ttry {\n\t\tconst content = readFileSync(path, \"utf-8\");\n\t\tconst deps: Dependency[] = [];\n\n\t\tconst depsSection = content.match(/\\[project\\.dependencies\\]([\\s\\S]*?)(?=\\[|$)/);\n\t\tif (!depsSection?.[1]) return [];\n\n\t\tconst lines = depsSection[1].split(\"\\n\");\n\t\tfor (const line of lines) {\n\t\t\tconst match = line.match(/[\"']([a-zA-Z0-9_-]+)(?:[>=<~!]+([^\"']+))?[\"']/);\n\t\t\tif (match?.[1]) {\n\t\t\t\tdeps.push({\n\t\t\t\t\tname: match[1],\n\t\t\t\t\tversion: match[2]?.trim(),\n\t\t\t\t\tdev: false,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn deps;\n\t} catch {\n\t\treturn [];\n\t}\n}\n\n/**\n * Parse Cargo.toml dependencies\n */\nfunction parseCargoToml(path: string): Dependency[] {\n\ttry {\n\t\tconst content = readFileSync(path, \"utf-8\");\n\t\tconst deps: Dependency[] = [];\n\n\t\tconst depsSection = content.match(/\\[dependencies\\]([\\s\\S]*?)(?=\\[|$)/);\n\t\tif (!depsSection?.[1]) return [];\n\n\t\tconst lines = depsSection[1].split(\"\\n\");\n\t\tfor (const line of lines) {\n\t\t\tconst simpleMatch = line.match(/^([a-zA-Z0-9_-]+)\\s*=\\s*\"([^\"]+)\"/);\n\t\t\tconst tableMatch = line.match(/^([a-zA-Z0-9_-]+)\\s*=\\s*{.*version\\s*=\\s*\"([^\"]+)\"/);\n\n\t\t\tif (simpleMatch?.[1] && simpleMatch[2]) {\n\t\t\t\tdeps.push({ name: simpleMatch[1], version: simpleMatch[2], dev: false });\n\t\t\t} else if (tableMatch?.[1] && tableMatch[2]) {\n\t\t\t\tdeps.push({ name: tableMatch[1], version: tableMatch[2], dev: false });\n\t\t\t}\n\t\t}\n\n\t\treturn deps;\n\t} catch {\n\t\treturn [];\n\t}\n}\n\n/**\n * Parse go.mod dependencies\n */\nfunction parseGoMod(path: string): Dependency[] {\n\ttry {\n\t\tconst content = readFileSync(path, \"utf-8\");\n\t\tconst deps: Dependency[] = [];\n\n\t\tconst requireSection = content.match(/require\\s*\\(([\\s\\S]*?)\\)/);\n\t\tif (!requireSection?.[1]) {\n\t\t\tconst singleRequire = content.match(/require\\s+([^\\s]+)\\s+([^\\s]+)/);\n\t\t\tif (singleRequire?.[1] && singleRequire[2]) {\n\t\t\t\tdeps.push({\n\t\t\t\t\tname: singleRequire[1],\n\t\t\t\t\tversion: singleRequire[2],\n\t\t\t\t\tdev: false,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn deps;\n\t\t}\n\n\t\tconst lines = requireSection[1].split(\"\\n\");\n\t\tfor (const line of lines) {\n\t\t\tconst match = line.match(/^\\s*([^\\s]+)\\s+([^\\s]+)/);\n\t\t\tif (match?.[1] && match[2]) {\n\t\t\t\tdeps.push({ name: match[1], version: match[2], dev: false });\n\t\t\t}\n\t\t}\n\n\t\treturn deps;\n\t} catch {\n\t\treturn [];\n\t}\n}\n\n/**\n * Parse requirements.txt dependencies\n */\nfunction parseRequirementsTxt(path: string): Dependency[] {\n\ttry {\n\t\tconst content = readFileSync(path, \"utf-8\");\n\t\tconst deps: Dependency[] = [];\n\n\t\tconst lines = content.split(\"\\n\");\n\t\tfor (const line of lines) {\n\t\t\tconst trimmed = line.trim();\n\t\t\tif (!trimmed || trimmed.startsWith(\"#\")) continue;\n\n\t\t\tconst match = trimmed.match(/^([a-zA-Z0-9_-]+)(?:[>=<~!]+(.+))?/);\n\t\t\tif (match?.[1]) {\n\t\t\t\tdeps.push({\n\t\t\t\t\tname: match[1],\n\t\t\t\t\tversion: match[2]?.trim(),\n\t\t\t\t\tdev: false,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn deps;\n\t} catch {\n\t\treturn [];\n\t}\n}\n","/**\n * Three-tier dependency name to GitHub repo resolution:\n * 1. KNOWN_MAPPINGS - hardcoded popular packages\n * 2. npm registry fallback\n * 3. User prompt (handled by caller)\n */\n\nimport { NpmPackageResponseSchema } from \"@offworld/types\";\n\nexport type ResolvedDep = {\n\tdep: string;\n\trepo: string | null;\n\tsource: \"known\" | \"npm\" | \"unknown\";\n};\n\n/**\n * Hardcoded mappings for popular packages.\n * Covers top ecosystems: React, Vue, Svelte, backend, database, validation, styling.\n */\nexport const KNOWN_MAPPINGS: Record<string, string> = {\n\treact: \"facebook/react\",\n\t\"react-dom\": \"facebook/react\",\n\tnext: \"vercel/next.js\",\n\tremix: \"remix-run/remix\",\n\t\"@remix-run/react\": \"remix-run/remix\",\n\t\"@remix-run/node\": \"remix-run/remix\",\n\n\tvue: \"vuejs/core\",\n\tnuxt: \"nuxt/nuxt\",\n\t\"@nuxt/kit\": \"nuxt/nuxt\",\n\n\tsvelte: \"sveltejs/svelte\",\n\tsveltekit: \"sveltejs/kit\",\n\t\"@sveltejs/kit\": \"sveltejs/kit\",\n\n\t\"@tanstack/query\": \"tanstack/query\",\n\t\"@tanstack/react-query\": \"tanstack/query\",\n\t\"@tanstack/vue-query\": \"tanstack/query\",\n\t\"@tanstack/router\": \"tanstack/router\",\n\t\"@tanstack/react-router\": \"tanstack/router\",\n\t\"@tanstack/start\": \"tanstack/router\",\n\tzustand: \"pmndrs/zustand\",\n\tjotai: \"pmndrs/jotai\",\n\tvaltio: \"pmndrs/valtio\",\n\tredux: \"reduxjs/redux\",\n\t\"@reduxjs/toolkit\": \"reduxjs/redux-toolkit\",\n\n\texpress: \"expressjs/express\",\n\thono: \"honojs/hono\",\n\tfastify: \"fastify/fastify\",\n\tkoa: \"koajs/koa\",\n\tnestjs: \"nestjs/nest\",\n\t\"@nestjs/core\": \"nestjs/nest\",\n\n\t// API/RPC\n\ttrpc: \"trpc/trpc\",\n\t\"@trpc/server\": \"trpc/trpc\",\n\t\"@trpc/client\": \"trpc/trpc\",\n\t\"@trpc/react-query\": \"trpc/trpc\",\n\tgraphql: \"graphql/graphql-js\",\n\t\"apollo-server\": \"apollographql/apollo-server\",\n\t\"@apollo/client\": \"apollographql/apollo-client\",\n\n\t\"drizzle-orm\": \"drizzle-team/drizzle-orm\",\n\tprisma: \"prisma/prisma\",\n\t\"@prisma/client\": \"prisma/prisma\",\n\ttypeorm: \"typeorm/typeorm\",\n\tsequelize: \"sequelize/sequelize\",\n\tmongoose: \"Automattic/mongoose\",\n\tknex: \"knex/knex\",\n\n\tzod: \"colinhacks/zod\",\n\tvalibot: \"fabian-hiller/valibot\",\n\tyup: \"jquense/yup\",\n\tjoi: \"hapijs/joi\",\n\n\ttailwindcss: \"tailwindlabs/tailwindcss\",\n\t\"styled-components\": \"styled-components/styled-components\",\n\t\"@emotion/react\": \"emotion-js/emotion\",\n\tsass: \"sass/sass\",\n\n\tvite: \"vitejs/vite\",\n\twebpack: \"webpack/webpack\",\n\tesbuild: \"evanw/esbuild\",\n\trollup: \"rollup/rollup\",\n\t\"@vitejs/plugin-react\": \"vitejs/vite-plugin-react\",\n\n\tvitest: \"vitest-dev/vitest\",\n\tjest: \"jestjs/jest\",\n\t\"@testing-library/react\": \"testing-library/react-testing-library\",\n\tcypress: \"cypress-io/cypress\",\n\tplaywright: \"microsoft/playwright\",\n\n\tconvex: \"get-convex/convex-backend\",\n\n\t\"better-auth\": \"better-auth/better-auth\",\n\n\tlodash: \"lodash/lodash\",\n\t\"date-fns\": \"date-fns/date-fns\",\n\taxios: \"axios/axios\",\n\tky: \"sindresorhus/ky\",\n\n\tturborepo: \"vercel/turborepo\",\n\tnx: \"nrwl/nx\",\n};\n\n/**\n * Parse GitHub repo from various git URL formats.\n * Handles:\n * - git+https://github.com/owner/repo.git\n * - https://github.com/owner/repo\n * - git://github.com/owner/repo.git\n * - github:owner/repo\n */\nfunction parseGitHubUrl(url: string): string | null {\n\tconst patterns = [\n\t\t/github\\.com[/:]([\\w-]+)\\/([\\w.-]+?)(?:\\.git)?$/,\n\t\t/^github:([\\w-]+)\\/([\\w.-]+)$/,\n\t];\n\n\tfor (const pattern of patterns) {\n\t\tconst match = url.match(pattern);\n\t\tif (match) {\n\t\t\treturn `${match[1]}/${match[2]}`;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Fallback to npm registry to extract repository.url.\n * Returns null if package not found, no repo field, or not a GitHub repo.\n */\nexport async function resolveFromNpm(packageName: string): Promise<string | null> {\n\ttry {\n\t\tconst res = await fetch(`https://registry.npmjs.org/${packageName}`);\n\t\tif (!res.ok) return null;\n\n\t\tconst json = await res.json();\n\t\tconst result = NpmPackageResponseSchema.safeParse(json);\n\t\tif (!result.success) return null;\n\n\t\tconst repoUrl = result.data.repository?.url;\n\t\tif (!repoUrl) return null;\n\n\t\treturn parseGitHubUrl(repoUrl);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Three-tier resolution:\n * 1. Check KNOWN_MAPPINGS\n * 2. Query npm registry\n * 3. Return unknown (caller prompts user)\n */\nexport async function resolveDependencyRepo(dep: string): Promise<ResolvedDep> {\n\tif (dep in KNOWN_MAPPINGS) {\n\t\treturn { dep, repo: KNOWN_MAPPINGS[dep] ?? null, source: \"known\" };\n\t}\n\n\tconst npmRepo = await resolveFromNpm(dep);\n\tif (npmRepo) {\n\t\treturn { dep, repo: npmRepo, source: \"npm\" };\n\t}\n\n\treturn { dep, repo: null, source: \"unknown\" };\n}\n","/**\n * Reference matching utilities for dependency resolution\n *\n * Maps dependencies to their reference status (installed, available, generate, unknown)\n */\n\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { toReferenceFileName } from \"./config.js\";\nimport { Paths } from \"./paths.js\";\nimport type { ResolvedDep } from \"./dep-mappings.js\";\n\nexport type ReferenceStatus = \"installed\" | \"available\" | \"generate\" | \"unknown\";\n\nexport interface ReferenceMatch {\n\t/** Dependency name */\n\tdep: string;\n\t/** GitHub repo (owner/repo) or null if unknown */\n\trepo: string | null;\n\t/** Reference availability status */\n\tstatus: ReferenceStatus;\n\t/** Resolution source: 'known' | 'npm' | 'unknown' */\n\tsource: \"known\" | \"npm\" | \"unknown\";\n}\n\n/**\n * Check if a reference is installed locally.\n * A reference is considered installed if {owner-repo}.md exists in offworld/references/.\n *\n * @param repo - Repo name in owner/repo format\n * @returns true if reference is installed locally\n */\nexport function isReferenceInstalled(repo: string): boolean {\n\tconst referenceFileName = toReferenceFileName(repo);\n\tconst referencePath = join(Paths.offworldReferencesDir, referenceFileName);\n\treturn existsSync(referencePath);\n}\n\n/**\n * Match dependencies to their reference availability status.\n *\n * Status logic:\n * - installed: {owner-repo}.md exists in offworld/references/\n * - available: Has valid GitHub repo (can be cloned)\n * - generate: Has valid GitHub repo but will need AI generation\n * - unknown: No GitHub repo found\n *\n * Note: Since we don't have a reference registry/index, \"available\" and \"generate\"\n * are the same. We use \"available\" for consistency and reserve \"generate\" for\n * future use when we can distinguish pre-existing vs needs-generation.\n *\n * @param resolvedDeps - Array of resolved dependencies with repo info\n * @returns Array of reference matches with status\n */\nexport function matchDependenciesToReferences(resolvedDeps: ResolvedDep[]): ReferenceMatch[] {\n\treturn resolvedDeps.map((dep) => {\n\t\tif (!dep.repo) {\n\t\t\treturn {\n\t\t\t\tdep: dep.dep,\n\t\t\t\trepo: null,\n\t\t\t\tstatus: \"unknown\",\n\t\t\t\tsource: dep.source,\n\t\t\t};\n\t\t}\n\n\t\tif (isReferenceInstalled(dep.repo)) {\n\t\t\treturn {\n\t\t\t\tdep: dep.dep,\n\t\t\t\trepo: dep.repo,\n\t\t\t\tstatus: \"installed\",\n\t\t\t\tsource: dep.source,\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tdep: dep.dep,\n\t\t\trepo: dep.repo,\n\t\t\tstatus: \"available\",\n\t\t\tsource: dep.source,\n\t\t};\n\t});\n}\n","/**\n * AGENTS.md manipulation utilities\n *\n * Manages updating project AGENTS.md and agent-specific files with reference information.\n */\n\nimport { readFileSync, writeFileSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport interface InstalledReference {\n\t/** Dependency name */\n\tdependency: string;\n\t/** Reference identifier (matches reference file name without .md) */\n\treference: string;\n\t/** Absolute path to reference file */\n\tpath: string;\n}\n\n/**\n * Generate markdown table for project references section.\n *\n * @param references - Array of installed references\n * @returns Markdown string with table\n */\nfunction generateReferencesTable(references: InstalledReference[]): string {\n\tconst lines = [\n\t\t\"## Project References\",\n\t\t\"\",\n\t\t\"References installed for this project's dependencies:\",\n\t\t\"\",\n\t\t\"| Dependency | Reference | Path |\",\n\t\t\"| --- | --- | --- |\",\n\t];\n\n\tfor (const reference of references) {\n\t\tlines.push(`| ${reference.dependency} | ${reference.reference} | ${reference.path} |`);\n\t}\n\n\tlines.push(\"\");\n\tlines.push(\"To update references: `ow pull <dependency>`\");\n\tlines.push(\"To regenerate all: `ow project init --all --generate`\");\n\tlines.push(\"\");\n\n\treturn lines.join(\"\\n\");\n}\n\n/**\n * Update or append Project References section in a markdown file.\n * If the section exists, replaces its content. Otherwise, appends to end.\n *\n * @param filePath - Path to markdown file\n * @param references - Array of installed references\n */\nexport function appendReferencesSection(filePath: string, references: InstalledReference[]): void {\n\tconst content = existsSync(filePath) ? readFileSync(filePath, \"utf-8\") : \"\";\n\tconst referencesMarkdown = generateReferencesTable(references);\n\n\tconst sectionRegex = /^## Project References\\n(?:.*\\n)*?(?=^## |$)/m;\n\tconst match = content.match(sectionRegex);\n\n\tlet updatedContent: string;\n\tif (match) {\n\t\tupdatedContent = content.replace(sectionRegex, referencesMarkdown);\n\t} else {\n\t\tupdatedContent = content.trim() + \"\\n\\n\" + referencesMarkdown;\n\t}\n\n\twriteFileSync(filePath, updatedContent, \"utf-8\");\n}\n\n/**\n * Update AGENTS.md and agent-specific files with project references.\n * Creates files if they don't exist.\n *\n * @param projectRoot - Project root directory\n * @param references - Array of installed references to document\n */\nexport function updateAgentFiles(projectRoot: string, references: InstalledReference[]): void {\n\tconst agentsMdPath = join(projectRoot, \"AGENTS.md\");\n\tconst claudeMdPath = join(projectRoot, \"CLAUDE.md\");\n\n\tappendReferencesSection(agentsMdPath, references);\n\n\tif (existsSync(claudeMdPath)) {\n\t\tappendReferencesSection(claudeMdPath, references);\n\t}\n}\n","import { existsSync, statSync, readdirSync, rmSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { updateRepo, GitError } from \"./clone.js\";\nimport { readGlobalMap, removeGlobalMapEntry, upsertGlobalMapEntry } from \"./index-manager.js\";\nimport { loadConfig, getRepoRoot } from \"./config.js\";\nimport { Paths } from \"./paths.js\";\n\nexport interface RepoStatusSummary {\n\ttotal: number;\n\twithReference: number;\n\tmissing: number;\n\tdiskBytes: number;\n}\n\nexport interface RepoStatusOptions {\n\tonProgress?: (current: number, total: number, repo: string) => void;\n}\n\nexport interface UpdateAllOptions {\n\tpattern?: string;\n\tdryRun?: boolean;\n\t/** Convert shallow clones to full clones */\n\tunshallow?: boolean;\n\tonProgress?: (\n\t\trepo: string,\n\t\tstatus: \"updating\" | \"updated\" | \"skipped\" | \"error\" | \"unshallowed\",\n\t\tmessage?: string,\n\t) => void;\n}\n\nexport interface UpdateAllResult {\n\tupdated: string[];\n\tskipped: string[];\n\tunshallowed: string[];\n\terrors: Array<{ repo: string; error: string }>;\n}\n\nexport interface PruneOptions {\n\tdryRun?: boolean;\n\tonProgress?: (repo: string, reason: string) => void;\n}\n\nexport interface PruneResult {\n\tremovedFromIndex: string[];\n\torphanedDirs: string[];\n}\n\nexport interface GcOptions {\n\tolderThanDays?: number;\n\twithoutReference?: boolean;\n\tdryRun?: boolean;\n\tonProgress?: (repo: string, reason: string, sizeBytes?: number) => void;\n}\n\nexport interface GcResult {\n\tremoved: Array<{ repo: string; reason: string; sizeBytes: number }>;\n\tfreedBytes: number;\n}\n\nfunction getDirSize(dirPath: string): number {\n\tif (!existsSync(dirPath)) return 0;\n\n\tlet size = 0;\n\ttry {\n\t\tconst entries = readdirSync(dirPath, { withFileTypes: true });\n\t\tfor (const entry of entries) {\n\t\t\tconst fullPath = join(dirPath, entry.name);\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\tsize += getDirSize(fullPath);\n\t\t\t} else if (entry.isFile()) {\n\t\t\t\ttry {\n\t\t\t\t\tsize += statSync(fullPath).size;\n\t\t\t\t} catch {}\n\t\t\t}\n\t\t}\n\t} catch {}\n\treturn size;\n}\n\nfunction getLastAccessTime(dirPath: string): Date | null {\n\tif (!existsSync(dirPath)) return null;\n\n\tlet latestTime: Date | null = null;\n\ttry {\n\t\tconst stat = statSync(dirPath);\n\t\tlatestTime = stat.mtime;\n\n\t\tconst fetchHead = join(dirPath, \".git\", \"FETCH_HEAD\");\n\t\tif (existsSync(fetchHead)) {\n\t\t\tconst fetchStat = statSync(fetchHead);\n\t\t\tif (!latestTime || fetchStat.mtime > latestTime) {\n\t\t\t\tlatestTime = fetchStat.mtime;\n\t\t\t}\n\t\t}\n\t} catch {}\n\treturn latestTime;\n}\n\nfunction matchesPattern(name: string, pattern: string): boolean {\n\tif (!pattern || pattern === \"*\") return true;\n\n\tconst regex = new RegExp(\n\t\t\"^\" +\n\t\t\tpattern\n\t\t\t\t.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n\t\t\t\t.replace(/\\*/g, \".*\")\n\t\t\t\t.replace(/\\?/g, \".\") +\n\t\t\t\"$\",\n\t\t\"i\",\n\t);\n\treturn regex.test(name);\n}\n\nconst yieldToEventLoop = () => new Promise<void>((resolve) => setImmediate(resolve));\n\nexport async function getRepoStatus(options: RepoStatusOptions = {}): Promise<RepoStatusSummary> {\n\tconst { onProgress } = options;\n\tconst map = readGlobalMap();\n\tconst qualifiedNames = Object.keys(map.repos);\n\tconst total = qualifiedNames.length;\n\n\tlet withReference = 0;\n\tlet missing = 0;\n\tlet diskBytes = 0;\n\n\tfor (let i = 0; i < qualifiedNames.length; i++) {\n\t\tconst qualifiedName = qualifiedNames[i]!;\n\t\tconst entry = map.repos[qualifiedName]!;\n\t\tonProgress?.(i + 1, total, qualifiedName);\n\n\t\tawait yieldToEventLoop();\n\n\t\tconst exists = existsSync(entry.localPath);\n\n\t\tif (!exists) {\n\t\t\tmissing++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (entry.references.length > 0) {\n\t\t\twithReference++;\n\t\t}\n\n\t\tdiskBytes += getDirSize(entry.localPath);\n\t}\n\n\treturn {\n\t\ttotal,\n\t\twithReference,\n\t\tmissing,\n\t\tdiskBytes,\n\t};\n}\n\nexport async function updateAllRepos(options: UpdateAllOptions = {}): Promise<UpdateAllResult> {\n\tconst { pattern, dryRun = false, unshallow = false, onProgress } = options;\n\n\tconst map = readGlobalMap();\n\tconst qualifiedNames = Object.keys(map.repos);\n\tconst updated: string[] = [];\n\tconst skipped: string[] = [];\n\tconst unshallowed: string[] = [];\n\tconst errors: Array<{ repo: string; error: string }> = [];\n\n\tfor (const qualifiedName of qualifiedNames) {\n\t\tconst entry = map.repos[qualifiedName]!;\n\n\t\tif (pattern && !matchesPattern(qualifiedName, pattern)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (!existsSync(entry.localPath)) {\n\t\t\tskipped.push(qualifiedName);\n\t\t\tonProgress?.(qualifiedName, \"skipped\", \"missing on disk\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (dryRun) {\n\t\t\tupdated.push(qualifiedName);\n\t\t\tonProgress?.(qualifiedName, \"updated\", \"would update\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tonProgress?.(qualifiedName, \"updating\");\n\t\ttry {\n\t\t\tconst result = await updateRepo(qualifiedName, { unshallow });\n\t\t\tif (result.unshallowed) {\n\t\t\t\tunshallowed.push(qualifiedName);\n\t\t\t\tonProgress?.(qualifiedName, \"unshallowed\", \"converted to full clone\");\n\t\t\t}\n\t\t\tif (result.updated) {\n\t\t\t\tupdated.push(qualifiedName);\n\t\t\t\tonProgress?.(\n\t\t\t\t\tqualifiedName,\n\t\t\t\t\t\"updated\",\n\t\t\t\t\t`${result.previousSha.slice(0, 7)} → ${result.currentSha.slice(0, 7)}`,\n\t\t\t\t);\n\t\t\t} else if (!result.unshallowed) {\n\t\t\t\tskipped.push(qualifiedName);\n\t\t\t\tonProgress?.(qualifiedName, \"skipped\", \"already up to date\");\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof GitError ? err.message : String(err);\n\t\t\terrors.push({ repo: qualifiedName, error: message });\n\t\t\tonProgress?.(qualifiedName, \"error\", message);\n\t\t}\n\t}\n\n\treturn { updated, skipped, unshallowed, errors };\n}\n\nexport async function pruneRepos(options: PruneOptions = {}): Promise<PruneResult> {\n\tconst { dryRun = false, onProgress } = options;\n\n\tconst map = readGlobalMap();\n\tconst qualifiedNames = Object.keys(map.repos);\n\tconst removedFromIndex: string[] = [];\n\tconst orphanedDirs: string[] = [];\n\n\tfor (const qualifiedName of qualifiedNames) {\n\t\tconst entry = map.repos[qualifiedName]!;\n\t\tawait yieldToEventLoop();\n\n\t\tif (!existsSync(entry.localPath)) {\n\t\t\tonProgress?.(qualifiedName, \"missing on disk\");\n\t\t\tremovedFromIndex.push(qualifiedName);\n\n\t\t\tif (!dryRun) {\n\t\t\t\tremoveGlobalMapEntry(qualifiedName);\n\t\t\t}\n\t\t}\n\t}\n\n\tconst config = loadConfig();\n\tconst repoRoot = getRepoRoot(config);\n\n\tif (existsSync(repoRoot)) {\n\t\tconst indexedPaths = new Set(Object.values(map.repos).map((r) => r.localPath));\n\n\t\ttry {\n\t\t\tconst providers = readdirSync(repoRoot, { withFileTypes: true });\n\t\t\tfor (const provider of providers) {\n\t\t\t\tif (!provider.isDirectory()) continue;\n\t\t\t\tconst providerPath = join(repoRoot, provider.name);\n\n\t\t\t\tconst owners = readdirSync(providerPath, { withFileTypes: true });\n\t\t\t\tfor (const owner of owners) {\n\t\t\t\t\tif (!owner.isDirectory()) continue;\n\t\t\t\t\tconst ownerPath = join(providerPath, owner.name);\n\n\t\t\t\t\tconst repoNames = readdirSync(ownerPath, { withFileTypes: true });\n\t\t\t\t\tfor (const repoName of repoNames) {\n\t\t\t\t\t\tawait yieldToEventLoop();\n\n\t\t\t\t\t\tif (!repoName.isDirectory()) continue;\n\t\t\t\t\t\tconst repoPath = join(ownerPath, repoName.name);\n\n\t\t\t\t\t\tif (!existsSync(join(repoPath, \".git\"))) continue;\n\n\t\t\t\t\t\tif (!indexedPaths.has(repoPath)) {\n\t\t\t\t\t\t\tconst fullName = `${owner.name}/${repoName.name}`;\n\t\t\t\t\t\t\tonProgress?.(fullName, \"not in map\");\n\t\t\t\t\t\t\torphanedDirs.push(repoPath);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {}\n\t}\n\n\treturn { removedFromIndex, orphanedDirs };\n}\n\nexport async function gcRepos(options: GcOptions = {}): Promise<GcResult> {\n\tconst { olderThanDays, withoutReference = false, dryRun = false, onProgress } = options;\n\n\tconst map = readGlobalMap();\n\tconst qualifiedNames = Object.keys(map.repos);\n\tconst removed: Array<{ repo: string; reason: string; sizeBytes: number }> = [];\n\tlet freedBytes = 0;\n\n\tconst now = new Date();\n\tconst cutoffDate = olderThanDays\n\t\t? new Date(now.getTime() - olderThanDays * 24 * 60 * 60 * 1000)\n\t\t: null;\n\n\tfor (const qualifiedName of qualifiedNames) {\n\t\tconst entry = map.repos[qualifiedName]!;\n\t\tawait yieldToEventLoop();\n\n\t\tif (!existsSync(entry.localPath)) continue;\n\n\t\tlet shouldRemove = false;\n\t\tlet reason = \"\";\n\n\t\tif (cutoffDate) {\n\t\t\tconst lastAccess = getLastAccessTime(entry.localPath);\n\t\t\tif (lastAccess && lastAccess < cutoffDate) {\n\t\t\t\tshouldRemove = true;\n\t\t\t\treason = `not accessed in ${olderThanDays}+ days`;\n\t\t\t}\n\t\t}\n\n\t\tif (withoutReference && entry.references.length === 0) {\n\t\t\tshouldRemove = true;\n\t\t\treason = reason ? `${reason}, no reference` : \"no reference\";\n\t\t}\n\n\t\tif (!shouldRemove) continue;\n\n\t\tconst sizeBytes = getDirSize(entry.localPath);\n\t\tonProgress?.(qualifiedName, reason, sizeBytes);\n\n\t\tif (!dryRun) {\n\t\t\trmSync(entry.localPath, { recursive: true, force: true });\n\n\t\t\tfor (const refFile of entry.references) {\n\t\t\t\tconst refPath = join(Paths.offworldReferencesDir, refFile);\n\t\t\t\tif (existsSync(refPath)) {\n\t\t\t\t\trmSync(refPath, { force: true });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (entry.primary) {\n\t\t\t\tconst metaDirName = entry.primary.replace(/\\.md$/, \"\");\n\t\t\t\tconst metaPath = join(Paths.metaDir, metaDirName);\n\t\t\t\tif (existsSync(metaPath)) {\n\t\t\t\t\trmSync(metaPath, { recursive: true, force: true });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tremoveGlobalMapEntry(qualifiedName);\n\t\t}\n\n\t\tremoved.push({ repo: qualifiedName, reason, sizeBytes });\n\t\tfreedBytes += sizeBytes;\n\t}\n\n\treturn { removed, freedBytes };\n}\n\nexport interface DiscoverOptions {\n\trepoRoot?: string;\n\tdryRun?: boolean;\n\tonProgress?: (repo: string, provider: string) => void;\n}\n\nexport interface DiscoverResult {\n\tdiscovered: Array<{ fullName: string; qualifiedName: string; localPath: string }>;\n\talreadyIndexed: number;\n}\n\nexport async function discoverRepos(options: DiscoverOptions = {}): Promise<DiscoverResult> {\n\tconst { dryRun = false, onProgress } = options;\n\n\tconst config = loadConfig();\n\tconst repoRoot = options.repoRoot ?? getRepoRoot(config);\n\tconst discovered: Array<{ fullName: string; qualifiedName: string; localPath: string }> = [];\n\tlet alreadyIndexed = 0;\n\n\tif (!existsSync(repoRoot)) {\n\t\treturn { discovered, alreadyIndexed };\n\t}\n\n\tconst map = readGlobalMap();\n\tconst indexedPaths = new Set(Object.values(map.repos).map((r) => r.localPath));\n\n\ttry {\n\t\tconst providers = readdirSync(repoRoot, { withFileTypes: true });\n\t\tfor (const provider of providers) {\n\t\t\tif (!provider.isDirectory()) continue;\n\t\t\tconst providerPath = join(repoRoot, provider.name);\n\n\t\t\tconst providerHostMap: Record<string, string> = {\n\t\t\t\tgithub: \"github.com\",\n\t\t\t\tgitlab: \"gitlab.com\",\n\t\t\t\tbitbucket: \"bitbucket.org\",\n\t\t\t};\n\t\t\tconst providerHost = providerHostMap[provider.name] ?? provider.name;\n\n\t\t\tconst owners = readdirSync(providerPath, { withFileTypes: true });\n\t\t\tfor (const owner of owners) {\n\t\t\t\tif (!owner.isDirectory()) continue;\n\t\t\t\tconst ownerPath = join(providerPath, owner.name);\n\n\t\t\t\tconst repoNames = readdirSync(ownerPath, { withFileTypes: true });\n\t\t\t\tfor (const repoName of repoNames) {\n\t\t\t\t\tawait yieldToEventLoop();\n\n\t\t\t\t\tif (!repoName.isDirectory()) continue;\n\t\t\t\t\tconst repoPath = join(ownerPath, repoName.name);\n\n\t\t\t\t\tif (!existsSync(join(repoPath, \".git\"))) continue;\n\n\t\t\t\t\tif (indexedPaths.has(repoPath)) {\n\t\t\t\t\t\talreadyIndexed++;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst fullName = `${owner.name}/${repoName.name}`;\n\t\t\t\t\tconst qualifiedName = `${providerHost}:${fullName}`;\n\n\t\t\t\t\tonProgress?.(fullName, providerHost);\n\n\t\t\t\t\tif (!dryRun) {\n\t\t\t\t\t\tupsertGlobalMapEntry(qualifiedName, {\n\t\t\t\t\t\t\tlocalPath: repoPath,\n\t\t\t\t\t\t\treferences: [],\n\t\t\t\t\t\t\tprimary: \"\",\n\t\t\t\t\t\t\tkeywords: [],\n\t\t\t\t\t\t\tupdatedAt: new Date().toISOString(),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tdiscovered.push({ fullName, qualifiedName, localPath: repoPath });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch {}\n\n\treturn { discovered, alreadyIndexed };\n}\n","import { ModelsDevDataSchema, type ModelsDevProvider } from \"@offworld/types\";\n\nconst MODELS_DEV_URL = \"https://models.dev/api.json\";\n\n/**\n * Simplified provider info for CLI display\n */\nexport interface ProviderInfo {\n\tid: string;\n\tname: string;\n\tenv: string[];\n}\n\n/**\n * Simplified model info for CLI display\n */\nexport interface ModelInfo {\n\tid: string;\n\tname: string;\n\treasoning: boolean;\n\texperimental?: boolean;\n\tstatus?: \"alpha\" | \"beta\" | \"deprecated\";\n}\n\n/**\n * Full provider with models for CLI display\n */\nexport interface ProviderWithModels extends ProviderInfo {\n\tmodels: ModelInfo[];\n}\n\nlet cachedData: Record<string, ModelsDevProvider> | null = null;\nlet cacheTime = 0;\nconst CACHE_TTL_MS = 5 * 60 * 1000;\n\n/**\n * Fetch raw data from models.dev with caching\n */\nasync function fetchModelsDevData(): Promise<Record<string, ModelsDevProvider>> {\n\tconst now = Date.now();\n\tif (cachedData && now - cacheTime < CACHE_TTL_MS) {\n\t\treturn cachedData;\n\t}\n\n\tconst res = await fetch(MODELS_DEV_URL, {\n\t\tsignal: AbortSignal.timeout(10_000),\n\t});\n\n\tif (!res.ok) {\n\t\tthrow new Error(`Failed to fetch models.dev: ${res.status} ${res.statusText}`);\n\t}\n\n\tconst json = await res.json();\n\tconst parsed = ModelsDevDataSchema.safeParse(json);\n\tif (!parsed.success) {\n\t\tthrow new Error(`Invalid models.dev response: ${parsed.error.message}`);\n\t}\n\tcachedData = parsed.data;\n\tcacheTime = now;\n\treturn cachedData;\n}\n\n/**\n * List all available providers from models.dev\n */\nexport async function listProviders(): Promise<ProviderInfo[]> {\n\tconst data = await fetchModelsDevData();\n\n\treturn Object.values(data)\n\t\t.map((p) => ({\n\t\t\tid: p.id,\n\t\t\tname: p.name,\n\t\t\tenv: p.env ?? [],\n\t\t}))\n\t\t.sort((a, b) => a.name.localeCompare(b.name));\n}\n\n/**\n * Get a specific provider with all its models\n */\nexport async function getProvider(providerId: string): Promise<ProviderWithModels | null> {\n\tconst data = await fetchModelsDevData();\n\tconst provider = data[providerId];\n\n\tif (!provider) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tid: provider.id,\n\t\tname: provider.name,\n\t\tenv: provider.env ?? [],\n\t\tmodels: Object.values(provider.models)\n\t\t\t.filter((m) => m.status !== \"deprecated\")\n\t\t\t.map((m) => ({\n\t\t\t\tid: m.id,\n\t\t\t\tname: m.name,\n\t\t\t\treasoning: m.reasoning ?? false,\n\t\t\t\texperimental: m.experimental,\n\t\t\t\tstatus: m.status,\n\t\t\t}))\n\t\t\t.sort((a, b) => a.name.localeCompare(b.name)),\n\t};\n}\n\n/**\n * Get all providers with their models\n */\nexport async function listProvidersWithModels(): Promise<ProviderWithModels[]> {\n\tconst data = await fetchModelsDevData();\n\n\treturn Object.values(data)\n\t\t.map((p) => ({\n\t\t\tid: p.id,\n\t\t\tname: p.name,\n\t\t\tenv: p.env ?? [],\n\t\t\tmodels: Object.values(p.models)\n\t\t\t\t.filter((m) => m.status !== \"deprecated\")\n\t\t\t\t.map((m) => ({\n\t\t\t\t\tid: m.id,\n\t\t\t\t\tname: m.name,\n\t\t\t\t\treasoning: m.reasoning ?? false,\n\t\t\t\t\texperimental: m.experimental,\n\t\t\t\t\tstatus: m.status,\n\t\t\t\t}))\n\t\t\t\t.sort((a, b) => a.name.localeCompare(b.name)),\n\t\t}))\n\t\t.sort((a, b) => a.name.localeCompare(b.name));\n}\n\n/**\n * Validate that a provider/model combination exists\n */\nexport async function validateProviderModel(\n\tproviderId: string,\n\tmodelId: string,\n): Promise<{ valid: boolean; error?: string }> {\n\tconst provider = await getProvider(providerId);\n\n\tif (!provider) {\n\t\tconst providers = await listProviders();\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\terror: `Provider \"${providerId}\" not found. Available: ${providers\n\t\t\t\t.slice(0, 10)\n\t\t\t\t.map((p) => p.id)\n\t\t\t\t.join(\", \")}${providers.length > 10 ? \"...\" : \"\"}`,\n\t\t};\n\t}\n\n\tconst model = provider.models.find((m) => m.id === modelId);\n\tif (!model) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\terror: `Model \"${modelId}\" not found for provider \"${providerId}\". Available: ${provider.models\n\t\t\t\t.slice(0, 10)\n\t\t\t\t.map((m) => m.id)\n\t\t\t\t.join(\", \")}${provider.models.length > 10 ? \"...\" : \"\"}`,\n\t\t};\n\t}\n\n\treturn { valid: true };\n}\n","/**\n * Installation utilities for upgrade/uninstall commands\n */\n\nimport { execSync, spawn } from \"node:child_process\";\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { NpmPackageResponseSchema } from \"@offworld/types\";\nimport { VERSION } from \"./constants.js\";\n\nconst GITHUB_REPO = \"oscabriel/offworld\";\nconst NPM_PACKAGE = \"offworld\";\n\nexport type InstallMethod = \"curl\" | \"npm\" | \"pnpm\" | \"bun\" | \"brew\" | \"unknown\";\n\n/**\n * Detect how offworld was installed\n */\nexport function detectInstallMethod(): InstallMethod {\n\tconst execPath = process.execPath;\n\n\tif (execPath.includes(\".local/bin\")) return \"curl\";\n\n\tconst checks: Array<{ name: InstallMethod; test: () => boolean }> = [\n\t\t{\n\t\t\tname: \"npm\",\n\t\t\ttest: () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = execSync(\"npm list -g --depth=0 2>/dev/null\", {\n\t\t\t\t\t\tencoding: \"utf-8\",\n\t\t\t\t\t});\n\t\t\t\t\treturn result.includes(NPM_PACKAGE);\n\t\t\t\t} catch {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"pnpm\",\n\t\t\ttest: () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = execSync(\"pnpm list -g --depth=0 2>/dev/null\", {\n\t\t\t\t\t\tencoding: \"utf-8\",\n\t\t\t\t\t});\n\t\t\t\t\treturn result.includes(NPM_PACKAGE);\n\t\t\t\t} catch {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"bun\",\n\t\t\ttest: () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = execSync(\"bun pm ls -g 2>/dev/null\", {\n\t\t\t\t\t\tencoding: \"utf-8\",\n\t\t\t\t\t});\n\t\t\t\t\treturn result.includes(NPM_PACKAGE);\n\t\t\t\t} catch {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t\t{\n\t\t\tname: \"brew\",\n\t\t\ttest: () => {\n\t\t\t\ttry {\n\t\t\t\t\texecSync(\"brew list --formula offworld 2>/dev/null\", {\n\t\t\t\t\t\tencoding: \"utf-8\",\n\t\t\t\t\t});\n\t\t\t\t\treturn true;\n\t\t\t\t} catch {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t},\n\t];\n\n\tif (execPath.includes(\"npm\")) {\n\t\tconst check = checks.find((c) => c.name === \"npm\");\n\t\tif (check?.test()) return \"npm\";\n\t}\n\tif (execPath.includes(\"pnpm\")) {\n\t\tconst check = checks.find((c) => c.name === \"pnpm\");\n\t\tif (check?.test()) return \"pnpm\";\n\t}\n\tif (execPath.includes(\"bun\")) {\n\t\tconst check = checks.find((c) => c.name === \"bun\");\n\t\tif (check?.test()) return \"bun\";\n\t}\n\tif (execPath.includes(\"Cellar\") || execPath.includes(\"homebrew\")) {\n\t\tconst check = checks.find((c) => c.name === \"brew\");\n\t\tif (check?.test()) return \"brew\";\n\t}\n\n\tfor (const check of checks) {\n\t\tif (check.test()) return check.name;\n\t}\n\n\treturn \"unknown\";\n}\n\n/**\n * Get current installed version\n */\nexport function getCurrentVersion(): string {\n\treturn VERSION;\n}\n\n/**\n * Fetch latest version from appropriate source\n */\nexport async function fetchLatestVersion(method?: InstallMethod): Promise<string | null> {\n\tconst installMethod = method ?? detectInstallMethod();\n\n\ttry {\n\t\tif (installMethod === \"npm\" || installMethod === \"pnpm\" || installMethod === \"bun\") {\n\t\t\tconst response = await fetch(`https://registry.npmjs.org/${NPM_PACKAGE}/latest`);\n\t\t\tif (!response.ok) return null;\n\t\t\tconst json = await response.json();\n\t\t\tconst result = NpmPackageResponseSchema.safeParse(json);\n\t\t\tif (!result.success) return null;\n\t\t\treturn result.data.version ?? null;\n\t\t}\n\n\t\tconst response = await fetch(`https://api.github.com/repos/${GITHUB_REPO}/releases/latest`, {\n\t\t\theaders: {\n\t\t\t\tAccept: \"application/vnd.github.v3+json\",\n\t\t\t\t\"User-Agent\": \"offworld-cli\",\n\t\t\t},\n\t\t});\n\t\tif (!response.ok) return null;\n\t\tconst json = await response.json();\n\t\tconst tagName =\n\t\t\ttypeof json === \"object\" && json !== null && \"tag_name\" in json\n\t\t\t\t? String(json.tag_name)\n\t\t\t\t: null;\n\t\treturn tagName?.replace(/^v/, \"\") ?? null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n/**\n * Execute upgrade for given method\n */\nexport function executeUpgrade(method: InstallMethod, version: string): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tlet cmd: string;\n\t\tlet args: string[];\n\n\t\tswitch (method) {\n\t\t\tcase \"curl\":\n\t\t\t\tcmd = \"bash\";\n\t\t\t\targs = [\"-c\", `curl -fsSL https://offworld.sh/install | VERSION=${version} bash`];\n\t\t\t\tbreak;\n\t\t\tcase \"npm\":\n\t\t\t\tcmd = \"npm\";\n\t\t\t\targs = [\"install\", \"-g\", `${NPM_PACKAGE}@${version}`];\n\t\t\t\tbreak;\n\t\t\tcase \"pnpm\":\n\t\t\t\tcmd = \"pnpm\";\n\t\t\t\targs = [\"install\", \"-g\", `${NPM_PACKAGE}@${version}`];\n\t\t\t\tbreak;\n\t\t\tcase \"bun\":\n\t\t\t\tcmd = \"bun\";\n\t\t\t\targs = [\"install\", \"-g\", `${NPM_PACKAGE}@${version}`];\n\t\t\t\tbreak;\n\t\t\tcase \"brew\":\n\t\t\t\tcmd = \"brew\";\n\t\t\t\targs = [\"upgrade\", \"offworld\"];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treject(new Error(`Cannot upgrade: unknown installation method`));\n\t\t\t\treturn;\n\t\t}\n\n\t\tconst proc = spawn(cmd, args, { stdio: \"inherit\" });\n\t\tproc.on(\"close\", (code) => {\n\t\t\tif (code === 0) resolve();\n\t\t\telse reject(new Error(`Upgrade failed with exit code ${code}`));\n\t\t});\n\t\tproc.on(\"error\", reject);\n\t});\n}\n\n/**\n * Execute uninstall for given method\n */\nexport function executeUninstall(method: InstallMethod): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tlet cmd: string;\n\t\tlet args: string[];\n\n\t\tswitch (method) {\n\t\t\tcase \"curl\":\n\t\t\t\ttry {\n\t\t\t\t\tconst binPath = join(homedir(), \".local\", \"bin\", \"ow\");\n\t\t\t\t\tif (existsSync(binPath)) {\n\t\t\t\t\t\texecSync(`rm -f \"${binPath}\"`, { stdio: \"inherit\" });\n\t\t\t\t\t}\n\t\t\t\t\tresolve();\n\t\t\t\t} catch (err) {\n\t\t\t\t\treject(err);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\tcase \"npm\":\n\t\t\t\tcmd = \"npm\";\n\t\t\t\targs = [\"uninstall\", \"-g\", NPM_PACKAGE];\n\t\t\t\tbreak;\n\t\t\tcase \"pnpm\":\n\t\t\t\tcmd = \"pnpm\";\n\t\t\t\targs = [\"uninstall\", \"-g\", NPM_PACKAGE];\n\t\t\t\tbreak;\n\t\t\tcase \"bun\":\n\t\t\t\tcmd = \"bun\";\n\t\t\t\targs = [\"remove\", \"-g\", NPM_PACKAGE];\n\t\t\t\tbreak;\n\t\t\tcase \"brew\":\n\t\t\t\tcmd = \"brew\";\n\t\t\t\targs = [\"uninstall\", \"offworld\"];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treject(new Error(`Cannot uninstall: unknown installation method`));\n\t\t\t\treturn;\n\t\t}\n\n\t\tconst proc = spawn(cmd, args, { stdio: \"inherit\" });\n\t\tproc.on(\"close\", (code) => {\n\t\t\tif (code === 0) resolve();\n\t\t\telse reject(new Error(`Uninstall failed with exit code ${code}`));\n\t\t});\n\t\tproc.on(\"error\", reject);\n\t});\n}\n\n/**\n * Get shell config files to clean\n */\nexport function getShellConfigFiles(): string[] {\n\tconst home = homedir();\n\tconst configs: string[] = [];\n\n\tconst candidates = [\n\t\t\".bashrc\",\n\t\t\".bash_profile\",\n\t\t\".profile\",\n\t\t\".zshrc\",\n\t\t\".zshenv\",\n\t\t\".config/fish/config.fish\",\n\t];\n\n\tfor (const file of candidates) {\n\t\tconst path = join(home, file);\n\t\tif (existsSync(path)) {\n\t\t\tconfigs.push(path);\n\t\t}\n\t}\n\n\treturn configs;\n}\n\n/**\n * Clean PATH entries from shell config\n */\nexport function cleanShellConfig(filePath: string): boolean {\n\ttry {\n\t\tconst content = readFileSync(filePath, \"utf-8\");\n\t\tconst lines = content.split(\"\\n\");\n\t\tconst filtered: string[] = [];\n\t\tlet modified = false;\n\n\t\tfor (const line of lines) {\n\t\t\tconst trimmed = line.trim();\n\t\t\tif (\n\t\t\t\ttrimmed.includes(\".local/bin\") &&\n\t\t\t\t(trimmed.startsWith(\"export PATH=\") || trimmed.startsWith(\"fish_add_path\"))\n\t\t\t) {\n\t\t\t\tif (trimmed.includes(\"# offworld\") || trimmed === 'export PATH=\"$HOME/.local/bin:$PATH\"') {\n\t\t\t\t\tmodified = true;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiltered.push(line);\n\t\t}\n\n\t\tif (modified) {\n\t\t\twriteFileSync(filePath, filtered.join(\"\\n\"), \"utf-8\");\n\t\t}\n\n\t\treturn modified;\n\t} catch {\n\t\treturn false;\n\t}\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@offworld/sdk",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Core SDK for Offworld - clone repos, generate references, sync with offworld.sh",
5
5
  "keywords": [
6
6
  "ai",