@goobits/sherpa 1.0.3 → 1.0.5
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/{chunk-U3WYNL3O.js → chunk-M5RTGB7M.js} +2 -2
- package/dist/{chunk-3CILH2TO.js → chunk-T2XUTRSA.js} +3 -5
- package/dist/{chunk-3CILH2TO.js.map → chunk-T2XUTRSA.js.map} +1 -1
- package/dist/{chunk-IIU6U7TE.js → chunk-WBU2V2G7.js} +105 -48
- package/dist/chunk-WBU2V2G7.js.map +7 -0
- package/dist/cli.js +5 -5
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/{daemon-QRXJH453.js → daemon-4YRI3APH.js} +3 -3
- package/dist/index.js +3 -3
- package/dist/reviewer/index.js +1 -1
- package/dist/{status-Q6Z4TFJZ.js → status-UGO6L7NZ.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-5NF3BSD6.js +0 -512
- package/dist/chunk-5NF3BSD6.js.map +0 -7
- package/dist/chunk-IIU6U7TE.js.map +0 -7
- package/dist/chunk-LQZTKH3U.js +0 -307
- package/dist/chunk-LQZTKH3U.js.map +0 -7
- package/dist/commands/init.js +0 -333
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/post.js +0 -183
- package/dist/commands/post.js.map +0 -1
- package/dist/commands/pre.js +0 -102
- package/dist/commands/pre.js.map +0 -1
- package/dist/commands/status.js +0 -48
- package/dist/commands/status.js.map +0 -1
- package/dist/daemon-V2QDZTUB.js +0 -89
- package/dist/daemon-V2QDZTUB.js.map +0 -7
- package/dist/daemon.js +0 -112
- package/dist/daemon.js.map +0 -1
- package/dist/parser.js +0 -152
- package/dist/parser.js.map +0 -1
- package/dist/rules.js +0 -165
- package/dist/rules.js.map +0 -1
- package/dist/types.js +0 -13
- package/dist/types.js.map +0 -1
- /package/dist/{chunk-U3WYNL3O.js.map → chunk-M5RTGB7M.js.map} +0 -0
- /package/dist/{daemon-QRXJH453.js.map → daemon-4YRI3APH.js.map} +0 -0
- /package/dist/{status-Q6Z4TFJZ.js.map → status-UGO6L7NZ.js.map} +0 -0
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
loadConfig,
|
|
5
5
|
readHookInput,
|
|
6
6
|
writeHookOutput
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-T2XUTRSA.js";
|
|
8
8
|
|
|
9
9
|
// src/types.ts
|
|
10
10
|
var DEFAULT_CONFIG = {
|
|
@@ -524,4 +524,4 @@ export {
|
|
|
524
524
|
checkBashCommand,
|
|
525
525
|
runPre
|
|
526
526
|
};
|
|
527
|
-
//# sourceMappingURL=chunk-
|
|
527
|
+
//# sourceMappingURL=chunk-M5RTGB7M.js.map
|
|
@@ -29,8 +29,8 @@ function loadConfig(configName, defaults, searchPaths = [process.cwd(), join(pro
|
|
|
29
29
|
|
|
30
30
|
// ../core/dist/llm.js
|
|
31
31
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
32
|
-
import { join as join2 } from "path";
|
|
33
32
|
import OpenAI from "openai";
|
|
33
|
+
import { join as join2 } from "path";
|
|
34
34
|
function loadEnvFiles() {
|
|
35
35
|
const envPaths = [
|
|
36
36
|
join2(process.cwd(), ".env"),
|
|
@@ -82,9 +82,7 @@ var PROVIDERS = {
|
|
|
82
82
|
openai: {
|
|
83
83
|
baseURL: "https://api.openai.com/v1",
|
|
84
84
|
envKey: "OPENAI_API_KEY",
|
|
85
|
-
models: [
|
|
86
|
-
"gpt-4o-mini"
|
|
87
|
-
]
|
|
85
|
+
models: ["gpt-4o-mini"]
|
|
88
86
|
}
|
|
89
87
|
};
|
|
90
88
|
var modelIndex = /* @__PURE__ */ new Map();
|
|
@@ -384,4 +382,4 @@ export {
|
|
|
384
382
|
chat,
|
|
385
383
|
countTokens
|
|
386
384
|
};
|
|
387
|
-
//# sourceMappingURL=chunk-
|
|
385
|
+
//# sourceMappingURL=chunk-T2XUTRSA.js.map
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../core/src/hooks.ts", "../../core/src/llm.ts", "../../core/src/files.ts", "../../core/src/git.ts", "../../core/src/tokens.ts"],
|
|
4
4
|
"sourcesContent": ["/**\n * Shared utilities for Claude Code hooks\n */\n\nimport { existsSync,readFileSync } from 'fs'\nimport { join } from 'path'\n\n/**\n * PreToolUse hook input structure\n */\nexport interface PreToolInput {\n\ttool_name?: string;\n\ttool_input?: {\n\t\tcommand?: string;\n\t\t[key: string]: unknown;\n\t};\n}\n\n/**\n * PostToolUse hook input structure\n */\nexport interface PostToolOutput {\n\ttool_name?: string;\n\ttool_input?: {\n\t\tcommand?: string;\n\t\t[key: string]: unknown;\n\t};\n\ttool_result?: {\n\t\tstdout?: string;\n\t\tstderr?: string;\n\t\texit_code?: number;\n\t\t[key: string]: unknown;\n\t};\n}\n\n/**\n * Read hook input from stdin\n */\nexport function readHookInput<T>(): T {\n\tconst input = readFileSync(0, 'utf-8')\n\treturn JSON.parse(input) as T\n}\n\n/**\n * Write hook output to stdout\n */\nexport function writeHookOutput(data: unknown): void {\n\tconsole.log(JSON.stringify(data))\n}\n\n/**\n * Exit codes for hooks\n */\nexport const EXIT = {\n\tALLOW: 0,\n\tBLOCK: 2\n} as const\n\n/**\n * Load JSON config with defaults\n */\nexport function loadConfig<T extends object>(\n\tconfigName: string,\n\tdefaults: T,\n\tsearchPaths: string[] = [ process.cwd(), join(process.cwd(), '..') ]\n): T {\n\tfor (const basePath of searchPaths) {\n\t\tconst configPath = join(basePath, configName)\n\t\tif (existsSync(configPath)) {\n\t\t\ttry {\n\t\t\t\tconst content = readFileSync(configPath, 'utf-8')\n\t\t\t\tconst loaded = JSON.parse(content)\n\t\t\t\treturn { ...defaults, ...loaded }\n\t\t\t} catch {\n\t\t\t\t// Ignore parse errors, use defaults\n\t\t\t}\n\t\t}\n\t}\n\treturn defaults\n}\n\n/**\n * Load config from environment variables with prefix\n */\nexport function loadEnvConfig<T extends object>(\n\tprefix: string,\n\tdefaults: T\n): T {\n\tconst result = { ...defaults }\n\n\tfor (const key of Object.keys(defaults)) {\n\t\tconst envKey = `${ prefix }_${ key.toUpperCase() }`\n\t\tconst envValue = process.env[envKey]\n\n\t\tif (envValue !== undefined) {\n\t\t\tconst defaultValue = defaults[key as keyof T]\n\n\t\t\t// Type coercion based on default value type\n\t\t\tif (typeof defaultValue === 'number') {\n\t\t\t\t(result as Record<string, unknown>)[key] = parseInt(envValue, 10)\n\t\t\t} else if (typeof defaultValue === 'boolean') {\n\t\t\t\t(result as Record<string, unknown>)[key] = envValue === 'true'\n\t\t\t} else {\n\t\t\t\t(result as Record<string, unknown>)[key] = envValue\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result\n}\n", "/**\n * LLM utilities: Multi-provider support (Cerebras, Groq, OpenAI-compatible)\n */\n\nimport { existsSync, readFileSync } from 'fs'\nimport OpenAI from 'openai'\nimport { join } from 'path'\n\n// Auto-load .env files (simple implementation, no dotenv dependency)\nfunction loadEnvFiles(): void {\n const envPaths = [\n join(process.cwd(), '.env'),\n join(process.cwd(), '..', '.env'),\n join(process.cwd(), '..', '..', '.env'),\n join(process.cwd(), 'packages', 'backend', '.env')\n ]\n\n for (const envPath of envPaths) {\n if (existsSync(envPath)) {\n const content = readFileSync(envPath, 'utf-8')\n for (const line of content.split('\\n')) {\n const trimmed = line.trim()\n if (trimmed && !trimmed.startsWith('#')) {\n const eqIdx = trimmed.indexOf('=')\n if (eqIdx > 0) {\n const key = trimmed.slice(0, eqIdx).trim()\n const value = trimmed.slice(eqIdx + 1).trim()\n // Only set if not already defined\n if (!process.env[key]) {\n process.env[key] = value\n }\n }\n }\n }\n }\n }\n}\n\n// Load env on module init\nloadEnvFiles()\n\n/** Supported LLM providers */\nexport type Provider = 'cerebras' | 'groq' | 'openai'\n\n/** Provider configuration */\ninterface ProviderConfig {\n baseURL: string\n envKey: string\n models: string[] // Ordered best \u2192 worst, will rotate on rate limit\n}\n\nconst PROVIDERS: Record<Provider, ProviderConfig> = {\n cerebras: {\n baseURL: 'https://api.cerebras.ai/v1',\n envKey: 'CEREBRAS_API_KEY',\n models: [\n 'zai-glm-4.7', // Best quality, 100 req/day\n 'qwen-3-235b-a22b-instruct-2507', // 235B, 1,440 req/day\n 'gpt-oss-120b' // 120B, 14,400 req/day\n ]\n },\n groq: {\n baseURL: 'https://api.groq.com/openai/v1',\n envKey: 'GROQ_API_KEY',\n models: [\n 'openai/gpt-oss-120b' // Same 120B model\n ]\n },\n openai: {\n baseURL: 'https://api.openai.com/v1',\n envKey: 'OPENAI_API_KEY',\n models: ['gpt-4o-mini']\n }\n}\n\n// Track which model index to use per provider (rotates on rate limit)\nconst modelIndex = new Map<Provider, number>()\n\n// Client cache per provider\nconst clients = new Map<Provider, OpenAI>()\n\n/**\n * Get available providers (those with API keys set)\n */\nexport function getAvailableProviders(): Provider[] {\n return (Object.keys(PROVIDERS) as Provider[]).filter(\n (provider) => !!process.env[PROVIDERS[provider].envKey]\n )\n}\n\n/**\n * Get or create client for a specific provider\n */\nfunction getClient(provider: Provider): OpenAI {\n let client = clients.get(provider)\n if (!client) {\n const config = PROVIDERS[provider]\n const apiKey = process.env[config.envKey]\n if (!apiKey) {\n throw new Error(`${config.envKey} environment variable not set`)\n }\n client = new OpenAI({\n apiKey,\n baseURL: config.baseURL\n })\n clients.set(provider, client)\n }\n return client\n}\n\n/**\n * Get the default provider (first available)\n */\nfunction getDefaultProvider(): Provider {\n const available = getAvailableProviders()\n if (available.length === 0) {\n throw new Error(\n 'No LLM provider configured. Set CEREBRAS_API_KEY, GROQ_API_KEY, or OPENAI_API_KEY'\n )\n }\n return available[0]\n}\n\n/**\n * Get current model for provider (with rotation support)\n */\nfunction getCurrentModel(provider: Provider): string {\n const config = PROVIDERS[provider]\n const idx = modelIndex.get(provider) || 0\n return config.models[Math.min(idx, config.models.length - 1)]\n}\n\n/**\n * Rotate to next model for provider (called on rate limit)\n */\nfunction rotateModel(provider: Provider): string | null {\n const config = PROVIDERS[provider]\n const currentIdx = modelIndex.get(provider) || 0\n const nextIdx = currentIdx + 1\n\n if (nextIdx >= config.models.length) {\n return null // No more models\n }\n\n modelIndex.set(provider, nextIdx)\n return config.models[nextIdx]\n}\n\n/** Chat options */\nexport interface ChatOptions {\n system?: string\n model?: string\n provider?: Provider\n fallback?: boolean // Try next provider on failure\n}\n\n/** Rate limit info from provider */\nexport interface RateLimitInfo {\n provider: Provider\n available: boolean\n error?: string\n limits?: {\n requestsPerMinute?: number\n requestsRemainingMinute?: number\n requestsPerDay?: number\n requestsRemainingDay?: number\n tokensPerMinute?: number\n tokensRemainingMinute?: number\n tokensPerDay?: number\n tokensRemainingDay?: number\n }\n}\n\n/**\n * Check rate limits for all available providers\n */\nexport async function checkProviderStatus(): Promise<RateLimitInfo[]> {\n const results: RateLimitInfo[] = []\n\n for (const provider of getAvailableProviders()) {\n try {\n const client = getClient(provider)\n const config = PROVIDERS[provider]\n\n // Make a minimal request to get headers (use first model)\n const response = await client.chat.completions\n .create({\n model: config.models[0],\n messages: [{ role: 'user', content: 'hi' }],\n max_tokens: 1\n })\n .asResponse()\n\n const h = response.headers\n const getInt = (name: string) => parseInt(h.get(name) || '0') || undefined\n\n results.push({\n provider,\n available: true,\n limits: {\n // Groq style (per minute)\n requestsPerMinute: getInt('x-ratelimit-limit-requests'),\n requestsRemainingMinute: getInt('x-ratelimit-remaining-requests'),\n tokensPerMinute: getInt('x-ratelimit-limit-tokens'),\n tokensRemainingMinute: getInt('x-ratelimit-remaining-tokens'),\n // Cerebras style (per day)\n requestsPerDay: getInt('x-ratelimit-limit-requests-day'),\n requestsRemainingDay: getInt('x-ratelimit-remaining-requests-day'),\n tokensPerDay: getInt('x-ratelimit-limit-tokens-day'),\n tokensRemainingDay: getInt('x-ratelimit-remaining-tokens-day')\n }\n })\n } catch (error) {\n results.push({\n provider,\n available: false,\n error: (error as Error).message\n })\n }\n }\n\n return results\n}\n\n/**\n * Check if error is a rate limit (429)\n */\nfunction isRateLimitError(error: unknown): boolean {\n if (error && typeof error === 'object') {\n const status = (error as { status?: number }).status\n return status === 429\n }\n return false\n}\n\n/**\n * Chat with LLM (supports model rotation + provider fallback)\n *\n * Order: cerebras(zai-glm-4.7 \u2192 qwen-235b \u2192 gpt-oss-120b) \u2192 groq \u2192 openai\n */\nexport async function chat(prompt: string, options: ChatOptions = {}): Promise<string> {\n const { system, fallback = true } = options\n let { provider, model } = options\n\n // Get provider\n if (!provider) {\n provider = getDefaultProvider()\n }\n\n // Use specified model or current rotation model\n if (!model) {\n model = getCurrentModel(provider)\n }\n\n const messages: OpenAI.ChatCompletionMessageParam[] = []\n if (system) {\n messages.push({ role: 'system', content: system })\n }\n messages.push({ role: 'user', content: prompt })\n\n // Try current provider with model rotation\n let currentProvider = provider\n let currentModel = model\n\n while (true) {\n try {\n const response = await getClient(currentProvider).chat.completions.create({\n model: currentModel,\n messages\n })\n\n return response.choices[0]?.message?.content || ''\n } catch (error) {\n // On rate limit, try next model in same provider\n if (isRateLimitError(error)) {\n const nextModel = rotateModel(currentProvider)\n if (nextModel) {\n console.error(`Rate limited on ${currentModel}, rotating to ${nextModel}`)\n currentModel = nextModel\n continue\n }\n }\n\n // No more models in this provider, try next provider\n if (fallback) {\n const available = getAvailableProviders().filter((p) => p !== currentProvider)\n if (available.length > 0) {\n currentProvider = available[0]\n currentModel = getCurrentModel(currentProvider)\n console.error(`Falling back to ${currentProvider}/${currentModel}`)\n continue\n }\n }\n\n throw new Error(`LLM API error (${currentProvider}/${currentModel}): ${error}`)\n }\n }\n}\n", "/**\n * File utilities: glob patterns, line-numbered formatting\n */\n\nimport { readFileSync, statSync } from 'fs'\nimport { glob } from 'glob'\n\nimport { filterIgnored } from './git.js'\n\n/** Code file extensions to include */\nexport const CODE_EXTENSIONS = new Set([\n\t'.py',\n\t'.rs',\n\t'.ts',\n\t'.js',\n\t'.svelte',\n\t'.tsx',\n\t'.jsx',\n\t'.go',\n\t'.java',\n\t'.rb',\n\t'.sh',\n\t'.json',\n\t'.yaml',\n\t'.yml',\n\t'.toml',\n\t'.md'\n])\n\n/**\n * Find files matching glob pattern, respecting .gitignore\n */\nexport async function findFiles(\n\tpattern: string,\n\toptions: { codeOnly?: boolean } = {}\n): Promise<string[]> {\n\tconst files = await glob(pattern, {\n\t\tignore: [\n\t\t\t'**/node_modules/**',\n\t\t\t'**/.venv/**',\n\t\t\t'**/venv/**',\n\t\t\t'**/dist/**',\n\t\t\t'**/build/**',\n\t\t\t'**/__pycache__/**',\n\t\t\t'**/.git/**'\n\t\t],\n\t\tnodir: true,\n\t\tdot: false\n\t})\n\n\t// Filter by .gitignore\n\tlet filtered = filterIgnored(files)\n\n\t// Filter by code extensions if requested\n\tif (options.codeOnly) {\n\t\tfiltered = filtered.filter(f => {\n\t\t\tconst ext = f.substring(f.lastIndexOf('.'))\n\t\t\treturn CODE_EXTENSIONS.has(ext)\n\t\t})\n\t}\n\n\treturn filtered.sort()\n}\n\n/**\n * Format file content with line numbers\n */\nexport function formatWithLineNumbers(path: string): string {\n\tconst content = readFileSync(path, 'utf8')\n\tconst lines = content.split('\\n')\n\tconst totalLines = lines.length\n\n\tconst numbered = lines.map(\n\t\t(line, i) => `${ String(i + 1).padStart(4) } | ${ line }`\n\t)\n\n\treturn `\n--- BEGIN FILE: ${ path } (lines 1-${ totalLines }) ---\n${ numbered.join('\\n') }\n--- END FILE: ${ path } ---\n`\n}\n\n/**\n * Read multiple files with size limit\n */\nexport function readFilesWithLimit(\n\tpaths: string[],\n\tmaxBytes: number = 120_000\n): { files: string[]; truncated: number } {\n\tconst files: string[] = []\n\tlet totalSize = 0\n\tlet truncated = 0\n\n\tfor (const path of paths) {\n\t\ttry {\n\t\t\tstatSync(path) // Verify file exists and is readable\n\t\t\tconst formatted = formatWithLineNumbers(path)\n\n\t\t\tif (totalSize + formatted.length > maxBytes) {\n\t\t\t\ttruncated = paths.length - files.length\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tfiles.push(formatted)\n\t\t\ttotalSize += formatted.length\n\t\t} catch {\n\t\t\t// Skip unreadable files\n\t\t}\n\t}\n\n\treturn { files, truncated }\n}\n\n/**\n * Check if path is a file\n */\nexport function isFile(path: string): boolean {\n\ttry {\n\t\treturn statSync(path).isFile()\n\t} catch {\n\t\treturn false\n\t}\n}\n\n/**\n * Check if path is a directory\n */\nexport function isDirectory(path: string): boolean {\n\ttry {\n\t\treturn statSync(path).isDirectory()\n\t} catch {\n\t\treturn false\n\t}\n}\n", "/**\n * Git utilities: .gitignore parsing, diff operations\n */\n\nimport { exec,execSync } from 'child_process'\nimport { existsSync,readFileSync } from 'fs'\nimport ignore, { type Ignore } from 'ignore'\nimport { dirname,join, resolve } from 'path'\nimport { promisify } from 'util'\n\nconst execAsync = promisify(exec)\n\n/**\n * Load .gitignore patterns from directory and parents\n */\nexport function loadGitignore(dir: string = '.'): Ignore {\n\tconst ig = ignore()\n\tconst absoluteDir = resolve(dir)\n\n\t// Walk up the tree loading .gitignore files\n\tlet current = absoluteDir\n\tconst gitignoreFiles: string[] = []\n\n\twhile (current) {\n\t\tconst gitignorePath = join(current, '.gitignore')\n\t\tif (existsSync(gitignorePath)) {\n\t\t\tgitignoreFiles.unshift(gitignorePath) // Add to front (parent patterns first)\n\t\t}\n\n\t\t// Check if we've hit the git root\n\t\tif (existsSync(join(current, '.git'))) {\n\t\t\tbreak\n\t\t}\n\n\t\tconst parent = dirname(current)\n\t\tif (parent === current) {break}\n\t\tcurrent = parent\n\t}\n\n\t// Load patterns (parent first, then child - child overrides)\n\tfor (const path of gitignoreFiles) {\n\t\tig.add(readFileSync(path, 'utf8'))\n\t}\n\n\t// Always ignore common junk\n\tig.add([\n\t\t'node_modules/',\n\t\t'__pycache__/',\n\t\t'.venv/',\n\t\t'venv/',\n\t\t'dist/',\n\t\t'build/',\n\t\t'.git/',\n\t\t'.eggs/',\n\t\t'*.egg-info/'\n\t])\n\n\treturn ig\n}\n\n/**\n * Filter paths, removing those matched by .gitignore\n */\nexport function filterIgnored(paths: string[], dir: string = '.'): string[] {\n\tconst ig = loadGitignore(dir)\n\treturn paths.filter(p => !ig.ignores(p))\n}\n\n/**\n * Check if paths are ignored using git check-ignore (batch)\n */\nexport function getIgnoredPaths(paths: string[]): Set<string> {\n\tif (paths.length === 0) {return new Set()}\n\n\ttry {\n\t\tconst result = execSync('git check-ignore --stdin', {\n\t\t\tinput: paths.join('\\n'),\n\t\t\tencoding: 'utf8',\n\t\t\tstdio: [ 'pipe', 'pipe', 'pipe' ]\n\t\t})\n\t\treturn new Set(result.trim().split('\\n').filter(Boolean))\n\t} catch {\n\t\treturn new Set()\n\t}\n}\n\n/**\n * Get git diff\n */\nexport async function getDiff(\n\tbase: string = 'HEAD~1',\n\tpath?: string\n): Promise<string> {\n\tconst args = [ 'git', 'diff', base ]\n\tif (path) {args.push('--', path)}\n\n\ttry {\n\t\tconst { stdout } = await execAsync(args.join(' '))\n\t\treturn stdout\n\t} catch(error) {\n\t\tthrow new Error(`Git diff failed: ${ error }`)\n\t}\n}\n\n/**\n * Check if we're in a git repository\n */\nexport function isGitRepo(dir: string = '.'): boolean {\n\ttry {\n\t\texecSync('git rev-parse --git-dir', {\n\t\t\tcwd: dir,\n\t\t\tstdio: [ 'pipe', 'pipe', 'pipe' ]\n\t\t})\n\t\treturn true\n\t} catch {\n\t\treturn false\n\t}\n}\n", "/**\n * Token counting utilities using tiktoken (Rust/WASM)\n */\n\nimport { get_encoding, type Tiktoken } from 'tiktoken'\n\nlet encoder: Tiktoken | null = null\n\n/**\n * Get or create the tokenizer instance\n */\nfunction getEncoder(): Tiktoken {\n\tif (!encoder) {\n\t\t// cl100k_base is used by GPT-4, Claude uses similar tokenization\n\t\tencoder = get_encoding('cl100k_base')\n\t}\n\treturn encoder\n}\n\n/**\n * Count tokens accurately using tiktoken\n */\nexport function countTokens(text: string): number {\n\treturn getEncoder().encode(text).length\n}\n\n/**\n * Estimate tokens quickly without full tokenization\n * ~4 chars per token for code, useful for quick checks\n */\nexport function estimateTokens(text: string): number {\n\treturn Math.ceil(text.length / 4)\n}\n\n/**\n * Check if text exceeds token limit\n */\nexport function exceedsTokenLimit(text: string, limit: number): boolean {\n\t// Quick estimate first\n\tif (estimateTokens(text) < limit * 0.8) {\n\t\treturn false\n\t}\n\t// Accurate count if close to limit\n\treturn countTokens(text) > limit\n}\n\n/**\n * Truncate text to fit within token limit\n */\nexport function truncateToTokens(text: string, maxTokens: number): string {\n\tconst tokens = getEncoder().encode(text)\n\tif (tokens.length <= maxTokens) {\n\t\treturn text\n\t}\n\tconst truncated = tokens.slice(0, maxTokens)\n\tconst decoded = getEncoder().decode(truncated)\n\treturn new TextDecoder().decode(decoded)\n}\n\n/**\n * Free the encoder when done (optional, for memory cleanup)\n */\nexport function freeEncoder(): void {\n\tif (encoder) {\n\t\tencoder.free()\n\t\tencoder = null\n\t}\n}\n"],
|
|
5
|
-
"mappings": ";AAIA,SAAS,YAAW,oBAAoB;AACxC,SAAS,YAAY;AAiCf,SAAU,gBAAa;AAC5B,QAAM,QAAQ,aAAa,GAAG,OAAO;AACrC,SAAO,KAAK,MAAM,KAAK;AACxB;AAKM,SAAU,gBAAgB,MAAa;AAC5C,UAAQ,IAAI,KAAK,UAAU,IAAI,CAAC;AACjC;AAKO,IAAM,OAAO;EACnB,OAAO;EACP,OAAO;;AAMF,SAAU,WACf,YACA,UACA,cAAwB,CAAE,QAAQ,IAAG,GAAI,KAAK,QAAQ,IAAG,GAAI,IAAI,CAAC,GAAE;AAEpE,aAAW,YAAY,aAAa;AACnC,UAAM,aAAa,KAAK,UAAU,UAAU;AAC5C,QAAI,WAAW,UAAU,GAAG;AAC3B,UAAI;AACH,cAAM,UAAU,aAAa,YAAY,OAAO;AAChD,cAAM,SAAS,KAAK,MAAM,OAAO;AACjC,eAAO,EAAE,GAAG,UAAU,GAAG,OAAM;MAChC,QAAQ;MAER;IACD;EACD;AACA,SAAO;AACR;;;AC3EA,SAAS,cAAAA,aAAY,gBAAAC,qBAAoB;AACzC,SAAS,QAAAC,aAAY;
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["existsSync", "readFileSync", "join", "readFileSync", "existsSync", "readFileSync", "join", "readFileSync"]
|
|
7
7
|
}
|
|
@@ -16,16 +16,6 @@ var GUARD_CONFIG = {
|
|
|
16
16
|
maxAgeMinutes: 60,
|
|
17
17
|
maxScratchSizeMB: 50
|
|
18
18
|
};
|
|
19
|
-
var REVIEW_COMMAND = `# review
|
|
20
|
-
|
|
21
|
-
Use the MCP tool \`review\` with the arguments provided by the user.
|
|
22
|
-
If no arguments are given, ask for the paths or mode.
|
|
23
|
-
`;
|
|
24
|
-
var TREE_COMMAND = `# tree
|
|
25
|
-
|
|
26
|
-
Use the MCP tool \`tree\` with the arguments provided by the user.
|
|
27
|
-
If no arguments are given, show the default repo tree.
|
|
28
|
-
`;
|
|
29
19
|
var LINT_STAGED_CONFIG = {
|
|
30
20
|
"*.{js,jsx,ts,tsx,json,md,yml,yaml}": ["prettier --write"]
|
|
31
21
|
};
|
|
@@ -36,13 +26,6 @@ else
|
|
|
36
26
|
echo "gitleaks not found - skipping"
|
|
37
27
|
fi
|
|
38
28
|
`;
|
|
39
|
-
function getNodePath() {
|
|
40
|
-
try {
|
|
41
|
-
return execSync("which node", { encoding: "utf-8" }).trim();
|
|
42
|
-
} catch {
|
|
43
|
-
return "node";
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
29
|
function getReviewerPath() {
|
|
47
30
|
const require2 = createRequire(import.meta.url);
|
|
48
31
|
const bundledPath = resolve(__dirname, "..", "reviewer", "index.js");
|
|
@@ -59,6 +42,85 @@ function getReviewerPath() {
|
|
|
59
42
|
}
|
|
60
43
|
return reviewerPath;
|
|
61
44
|
}
|
|
45
|
+
function commandExists(command) {
|
|
46
|
+
try {
|
|
47
|
+
const checkCmd = process.platform === "win32" ? `where ${command}` : `command -v ${command}`;
|
|
48
|
+
execSync(checkCmd, { stdio: "pipe" });
|
|
49
|
+
return true;
|
|
50
|
+
} catch {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function getLocalReviewerPath(cwd) {
|
|
55
|
+
const localPath = join(cwd, "node_modules", "@goobits", "sherpa", "dist", "reviewer", "index.js");
|
|
56
|
+
if (existsSync(localPath)) {
|
|
57
|
+
return "./node_modules/@goobits/sherpa/dist/reviewer/index.js";
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
function getPackageManager(cwd) {
|
|
62
|
+
const pkgPath = join(cwd, "package.json");
|
|
63
|
+
if (existsSync(pkgPath)) {
|
|
64
|
+
try {
|
|
65
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
66
|
+
if (pkg.packageManager) {
|
|
67
|
+
const name = pkg.packageManager.split("@")[0];
|
|
68
|
+
if (name === "pnpm" || name === "npm" || name === "yarn" || name === "bun") {
|
|
69
|
+
return name;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
} catch {
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (existsSync(join(cwd, "pnpm-lock.yaml"))) {
|
|
76
|
+
return "pnpm";
|
|
77
|
+
}
|
|
78
|
+
if (existsSync(join(cwd, "yarn.lock"))) {
|
|
79
|
+
return "yarn";
|
|
80
|
+
}
|
|
81
|
+
if (existsSync(join(cwd, "package-lock.json"))) {
|
|
82
|
+
return "npm";
|
|
83
|
+
}
|
|
84
|
+
if (existsSync(join(cwd, "bun.lockb"))) {
|
|
85
|
+
return "bun";
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
function installLocalSherpa(cwd) {
|
|
90
|
+
const pkgPath = join(cwd, "package.json");
|
|
91
|
+
if (!existsSync(pkgPath)) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
const packageManager = getPackageManager(cwd);
|
|
95
|
+
if (!packageManager || !commandExists(packageManager)) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
const installCommand = packageManager === "pnpm" ? "pnpm add -D @goobits/sherpa" : packageManager === "yarn" ? "yarn add -D @goobits/sherpa" : packageManager === "bun" ? "bun add -D @goobits/sherpa" : "npm install -D @goobits/sherpa";
|
|
99
|
+
try {
|
|
100
|
+
console.log(`Installing @goobits/sherpa locally with ${packageManager}...`);
|
|
101
|
+
execSync(installCommand, { cwd, stdio: "pipe" });
|
|
102
|
+
} catch {
|
|
103
|
+
console.warn(`Warning: Failed to install @goobits/sherpa with ${packageManager}.`);
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
function quoteArg(arg) {
|
|
109
|
+
if (/^[A-Za-z0-9_./:@-]+$/.test(arg)) {
|
|
110
|
+
return arg;
|
|
111
|
+
}
|
|
112
|
+
return `"${arg.replace(/"/g, '\\"')}"`;
|
|
113
|
+
}
|
|
114
|
+
function getMcpCommand(cwd) {
|
|
115
|
+
const localReviewer = getLocalReviewerPath(cwd);
|
|
116
|
+
if (localReviewer) {
|
|
117
|
+
return { command: "node", args: [localReviewer], isPortable: true };
|
|
118
|
+
}
|
|
119
|
+
if (commandExists("reviewer")) {
|
|
120
|
+
return { command: "reviewer", args: [], isPortable: true };
|
|
121
|
+
}
|
|
122
|
+
return { command: "node", args: [getReviewerPath()], isPortable: false };
|
|
123
|
+
}
|
|
62
124
|
function runInit() {
|
|
63
125
|
const isInitCommand = process.argv[2] === "init";
|
|
64
126
|
const initArgs = isInitCommand ? process.argv.slice(3) : [];
|
|
@@ -66,7 +128,6 @@ function runInit() {
|
|
|
66
128
|
const cwd = process.cwd();
|
|
67
129
|
console.log("Setting up sherpa...\n");
|
|
68
130
|
setupClaudeHooks(cwd, force);
|
|
69
|
-
setupClaudeCommands(cwd, force);
|
|
70
131
|
setupMcpConfig(cwd, force);
|
|
71
132
|
setupHusky(cwd, force);
|
|
72
133
|
setupLintStaged(cwd, force);
|
|
@@ -77,8 +138,6 @@ ${"=".repeat(50)}`);
|
|
|
77
138
|
console.log("What was configured:");
|
|
78
139
|
console.log(" [x] .claude/settings.local.json - Hooks");
|
|
79
140
|
console.log(" [x] .claude/guard.json - Guard config");
|
|
80
|
-
console.log(" [x] .claude/commands/review.md - Slash command");
|
|
81
|
-
console.log(" [x] .claude/commands/tree.md - Slash command");
|
|
82
141
|
console.log(" [x] .mcp.json - MCP servers");
|
|
83
142
|
console.log(" [x] .husky/pre-commit - Git pre-commit hook");
|
|
84
143
|
console.log(" [x] .lintstagedrc.json - Lint staged files");
|
|
@@ -138,32 +197,15 @@ function setupClaudeHooks(cwd, force) {
|
|
|
138
197
|
console.log("Claude hooks already configured");
|
|
139
198
|
}
|
|
140
199
|
}
|
|
141
|
-
function setupClaudeCommands(cwd, force) {
|
|
142
|
-
const claudeDir = join(cwd, ".claude");
|
|
143
|
-
const commandsDir = join(claudeDir, "commands");
|
|
144
|
-
const reviewCommandPath = join(commandsDir, "review.md");
|
|
145
|
-
const treeCommandPath = join(commandsDir, "tree.md");
|
|
146
|
-
if (!existsSync(commandsDir)) {
|
|
147
|
-
mkdirSync(commandsDir, { recursive: true });
|
|
148
|
-
}
|
|
149
|
-
if (!existsSync(reviewCommandPath) || force) {
|
|
150
|
-
writeFileSync(reviewCommandPath, REVIEW_COMMAND);
|
|
151
|
-
console.log("Created .claude/commands/review.md");
|
|
152
|
-
} else {
|
|
153
|
-
console.log(".claude/commands/review.md already exists");
|
|
154
|
-
}
|
|
155
|
-
if (!existsSync(treeCommandPath) || force) {
|
|
156
|
-
writeFileSync(treeCommandPath, TREE_COMMAND);
|
|
157
|
-
console.log("Created .claude/commands/tree.md");
|
|
158
|
-
} else {
|
|
159
|
-
console.log(".claude/commands/tree.md already exists");
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
200
|
function setupMcpConfig(cwd, force) {
|
|
163
201
|
const mcpPath = join(cwd, ".mcp.json");
|
|
164
202
|
const settingsPath = join(cwd, ".claude/settings.local.json");
|
|
165
|
-
|
|
166
|
-
|
|
203
|
+
if (!getLocalReviewerPath(cwd) && !commandExists("reviewer")) {
|
|
204
|
+
if (installLocalSherpa(cwd)) {
|
|
205
|
+
console.log("Installed @goobits/sherpa for portable MCP config.");
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
const mcpCommand = getMcpCommand(cwd);
|
|
167
209
|
if (existsSync(settingsPath)) {
|
|
168
210
|
try {
|
|
169
211
|
const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
@@ -178,10 +220,14 @@ function setupMcpConfig(cwd, force) {
|
|
|
178
220
|
}
|
|
179
221
|
const mcpConfig = {
|
|
180
222
|
type: "stdio",
|
|
181
|
-
command:
|
|
182
|
-
args:
|
|
223
|
+
command: mcpCommand.command,
|
|
224
|
+
args: mcpCommand.args,
|
|
183
225
|
env: {}
|
|
184
226
|
};
|
|
227
|
+
if (!mcpCommand.isPortable) {
|
|
228
|
+
console.warn("Warning: reviewer path is outside the project.");
|
|
229
|
+
console.warn("Install @goobits/sherpa locally (devDependency) to keep .mcp.json portable.");
|
|
230
|
+
}
|
|
185
231
|
try {
|
|
186
232
|
execSync("claude mcp remove reviewer -s project 2>/dev/null || true", {
|
|
187
233
|
cwd,
|
|
@@ -191,7 +237,17 @@ function setupMcpConfig(cwd, force) {
|
|
|
191
237
|
cwd,
|
|
192
238
|
stdio: "pipe"
|
|
193
239
|
});
|
|
194
|
-
|
|
240
|
+
const addArgs = [
|
|
241
|
+
"claude",
|
|
242
|
+
"mcp",
|
|
243
|
+
"add",
|
|
244
|
+
"reviewer",
|
|
245
|
+
"-s",
|
|
246
|
+
"project",
|
|
247
|
+
mcpCommand.command,
|
|
248
|
+
...mcpCommand.args
|
|
249
|
+
];
|
|
250
|
+
execSync(addArgs.map(quoteArg).join(" "), {
|
|
195
251
|
cwd,
|
|
196
252
|
stdio: "pipe"
|
|
197
253
|
});
|
|
@@ -213,7 +269,8 @@ function setupMcpConfig(cwd, force) {
|
|
|
213
269
|
console.log("Configured .mcp.json with reviewer");
|
|
214
270
|
try {
|
|
215
271
|
const testMsg = '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}}}';
|
|
216
|
-
|
|
272
|
+
const runCommand = [mcpCommand.command, ...mcpCommand.args].map(quoteArg).join(" ");
|
|
273
|
+
execSync(`echo '${testMsg}' | ${runCommand}`, {
|
|
217
274
|
stdio: "pipe",
|
|
218
275
|
timeout: 5e3
|
|
219
276
|
});
|
|
@@ -304,4 +361,4 @@ function checkGitleaks() {
|
|
|
304
361
|
export {
|
|
305
362
|
runInit
|
|
306
363
|
};
|
|
307
|
-
//# sourceMappingURL=chunk-
|
|
364
|
+
//# sourceMappingURL=chunk-WBU2V2G7.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/commands/init.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * sherpa init - Set up repo with husky, lint-staged, gitleaks, and claude hooks\n *\n * Usage: sherpa init [--force]\n */\n\nimport { execSync } from 'child_process'\nimport { createRequire } from 'module'\nimport { appendFileSync, chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs'\nimport { dirname, join, resolve } from 'path'\nimport { fileURLToPath } from 'url'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\ninterface HookEntry {\n matcher: string\n hooks: Array<{ type: string; command: string }>\n}\n\ninterface McpServer {\n type: 'stdio'\n command: string\n args: string[]\n env?: Record<string, string>\n}\n\ninterface McpJson {\n mcpServers: Record<string, McpServer>\n}\n\ninterface ClaudeSettings {\n hooks?: {\n PreToolUse?: HookEntry[]\n PostToolUse?: HookEntry[]\n }\n [key: string]: unknown\n}\n\nconst CLAUDE_HOOK_CONFIG = {\n PreToolUse: [{ matcher: 'Bash', hooks: [{ type: 'command', command: 'sherpa pre' }] }],\n PostToolUse: [{ matcher: 'Bash', hooks: [{ type: 'command', command: 'sherpa post' }] }]\n}\n\nconst GUARD_CONFIG = {\n maxTokens: 2000,\n previewTokens: 500,\n scratchDir: '.claude/scratch',\n maxAgeMinutes: 60,\n maxScratchSizeMB: 50\n}\n\nconst LINT_STAGED_CONFIG = {\n '*.{js,jsx,ts,tsx,json,md,yml,yaml}': ['prettier --write']\n}\n\nconst HUSKY_PRE_COMMIT = `npx lint-staged\nif command -v gitleaks >/dev/null 2>&1; then\n\tgitleaks protect --staged --verbose\nelse\n\techo \"gitleaks not found - skipping\"\nfi\n`\n\n/**\n * Get absolute path to reviewer dist\n */\nfunction getReviewerPath(): string {\n const require = createRequire(import.meta.url)\n const bundledPath = resolve(__dirname, '..', 'reviewer', 'index.js')\n if (existsSync(bundledPath)) {\n return bundledPath\n }\n try {\n return require.resolve('@goobits/sherpa-reviewer/dist/index.js')\n } catch {\n // Fall through to monorepo path\n }\n\n // __dirname is packages/sherpa/dist/commands in compiled code\n // Reviewer is at packages/reviewer/dist/index.js\n const reviewerPath = resolve(__dirname, '../../../reviewer/dist/index.js')\n if (existsSync(reviewerPath)) {\n return reviewerPath\n }\n\n return reviewerPath\n}\n\nfunction commandExists(command: string): boolean {\n try {\n const checkCmd = process.platform === 'win32' ? `where ${command}` : `command -v ${command}`\n execSync(checkCmd, { stdio: 'pipe' })\n return true\n } catch {\n return false\n }\n}\n\nfunction getLocalReviewerPath(cwd: string): string | null {\n const localPath = join(cwd, 'node_modules', '@goobits', 'sherpa', 'dist', 'reviewer', 'index.js')\n if (existsSync(localPath)) {\n return './node_modules/@goobits/sherpa/dist/reviewer/index.js'\n }\n\n return null\n}\n\nfunction getPackageManager(cwd: string): 'pnpm' | 'npm' | 'yarn' | 'bun' | null {\n const pkgPath = join(cwd, 'package.json')\n if (existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')) as { packageManager?: string }\n if (pkg.packageManager) {\n const name = pkg.packageManager.split('@')[0]\n if (name === 'pnpm' || name === 'npm' || name === 'yarn' || name === 'bun') {\n return name\n }\n }\n } catch {}\n }\n\n if (existsSync(join(cwd, 'pnpm-lock.yaml'))) {\n return 'pnpm'\n }\n if (existsSync(join(cwd, 'yarn.lock'))) {\n return 'yarn'\n }\n if (existsSync(join(cwd, 'package-lock.json'))) {\n return 'npm'\n }\n if (existsSync(join(cwd, 'bun.lockb'))) {\n return 'bun'\n }\n\n return null\n}\n\nfunction installLocalSherpa(cwd: string): boolean {\n const pkgPath = join(cwd, 'package.json')\n if (!existsSync(pkgPath)) {\n return false\n }\n\n const packageManager = getPackageManager(cwd)\n if (!packageManager || !commandExists(packageManager)) {\n return false\n }\n\n const installCommand =\n packageManager === 'pnpm'\n ? 'pnpm add -D @goobits/sherpa'\n : packageManager === 'yarn'\n ? 'yarn add -D @goobits/sherpa'\n : packageManager === 'bun'\n ? 'bun add -D @goobits/sherpa'\n : 'npm install -D @goobits/sherpa'\n\n try {\n console.log(`Installing @goobits/sherpa locally with ${packageManager}...`)\n execSync(installCommand, { cwd, stdio: 'pipe' })\n } catch {\n console.warn(`Warning: Failed to install @goobits/sherpa with ${packageManager}.`)\n return false\n }\n\n return true\n}\n\nfunction quoteArg(arg: string): string {\n if (/^[A-Za-z0-9_./:@-]+$/.test(arg)) {\n return arg\n }\n\n return `\"${arg.replace(/\"/g, '\\\\\"')}\"`\n}\n\nfunction getMcpCommand(cwd: string): { command: string; args: string[]; isPortable: boolean } {\n const localReviewer = getLocalReviewerPath(cwd)\n if (localReviewer) {\n return { command: 'node', args: [localReviewer], isPortable: true }\n }\n\n if (commandExists('reviewer')) {\n return { command: 'reviewer', args: [], isPortable: true }\n }\n\n return { command: 'node', args: [getReviewerPath()], isPortable: false }\n}\n\nexport function runInit(): void {\n const isInitCommand = process.argv[2] === 'init'\n const initArgs = isInitCommand ? process.argv.slice(3) : []\n const force = initArgs.includes('--force')\n const cwd = process.cwd()\n\n console.log('Setting up sherpa...\\n')\n\n // 1. Create .claude directory and hooks config\n setupClaudeHooks(cwd, force)\n\n // 2. Set up MCP server in .mcp.json\n setupMcpConfig(cwd, force)\n\n // 3. Set up husky\n setupHusky(cwd, force)\n\n // 4. Set up lint-staged\n setupLintStaged(cwd, force)\n\n // 6. Check for gitleaks\n checkGitleaks()\n\n // Print success\n console.log(`\\n${'='.repeat(50)}`)\n console.log('Sherpa setup complete!\\n')\n console.log('What was configured:')\n console.log(' [x] .claude/settings.local.json - Hooks')\n console.log(' [x] .claude/guard.json - Guard config')\n console.log(' [x] .mcp.json - MCP servers')\n console.log(' [x] .husky/pre-commit - Git pre-commit hook')\n console.log(' [x] .lintstagedrc.json - Lint staged files')\n console.log('')\n console.log('Pre-commit will run:')\n console.log(' 1. lint-staged (lint/format changed files)')\n console.log(' 2. gitleaks (scan for secrets)')\n console.log('')\n console.log('Claude Code:')\n console.log(' - sherpa pre: Block dangerous bash commands')\n console.log(' - sherpa post: Offload large outputs')\n console.log(' - reviewer: AI code review (MCP)')\n console.log('')\n console.log('IMPORTANT: Restart Claude Code to load the MCP server.')\n console.log('='.repeat(50))\n}\n\nfunction setupClaudeHooks(cwd: string, force: boolean): void {\n const claudeDir = join(cwd, '.claude')\n const configPath = join(claudeDir, 'guard.json')\n const settingsPath = join(claudeDir, 'settings.local.json')\n\n // Create .claude directory\n if (!existsSync(claudeDir)) {\n mkdirSync(claudeDir, { recursive: true })\n console.log('Created .claude/ directory')\n }\n\n // Create guard.json\n if (!existsSync(configPath) || force) {\n writeFileSync(configPath, `${JSON.stringify(GUARD_CONFIG, null, 2)}\\n`)\n console.log('Created .claude/guard.json')\n } else {\n console.log('.claude/guard.json already exists (use --force to overwrite)')\n }\n\n // Update settings.local.json with hooks only (not MCP)\n let settings: ClaudeSettings = {}\n if (existsSync(settingsPath)) {\n try {\n settings = JSON.parse(readFileSync(settingsPath, 'utf-8'))\n } catch {\n console.warn('Warning: Could not parse existing settings.local.json')\n }\n }\n\n // Merge hook config\n settings.hooks = settings.hooks || {}\n let hooksUpdated = false\n\n for (const [hookType, hooks] of Object.entries(CLAUDE_HOOK_CONFIG)) {\n const existing = settings.hooks[hookType as keyof typeof CLAUDE_HOOK_CONFIG] || []\n const hasSherpa = existing.some((h) =>\n h.hooks?.some((hook: { command?: string }) => hook.command?.startsWith('sherpa '))\n )\n\n if (!hasSherpa) {\n settings.hooks[hookType as keyof typeof CLAUDE_HOOK_CONFIG] = [...existing, ...hooks]\n hooksUpdated = true\n }\n }\n\n if (hooksUpdated) {\n writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}\\n`)\n console.log('Updated .claude/settings.local.json with hooks')\n } else {\n console.log('Claude hooks already configured')\n }\n}\n\nfunction setupMcpConfig(cwd: string, force: boolean): void {\n const mcpPath = join(cwd, '.mcp.json')\n const settingsPath = join(cwd, '.claude/settings.local.json')\n\n if (!getLocalReviewerPath(cwd) && !commandExists('reviewer')) {\n if (installLocalSherpa(cwd)) {\n console.log('Installed @goobits/sherpa for portable MCP config.')\n }\n }\n\n const mcpCommand = getMcpCommand(cwd)\n\n // 1. Clean up stale MCP config from settings.local.json (wrong location)\n if (existsSync(settingsPath)) {\n try {\n const settings = JSON.parse(readFileSync(settingsPath, 'utf-8'))\n if (settings.mcpServers) {\n delete settings.mcpServers\n writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}\\n`)\n console.log('Cleaned up stale MCP config from settings.local.json')\n }\n } catch {\n // Ignore parse errors\n }\n }\n\n const mcpConfig: McpServer = {\n type: 'stdio',\n command: mcpCommand.command,\n args: mcpCommand.args,\n env: {}\n }\n\n if (!mcpCommand.isPortable) {\n console.warn('Warning: reviewer path is outside the project.')\n console.warn('Install @goobits/sherpa locally (devDependency) to keep .mcp.json portable.')\n }\n\n // 2. Try using claude CLI first (most reliable)\n try {\n // Remove existing and add fresh (always, to ensure correct config)\n execSync('claude mcp remove reviewer -s project 2>/dev/null || true', {\n cwd,\n stdio: 'pipe'\n })\n execSync('claude mcp remove cerebras-reviewer -s project 2>/dev/null || true', {\n cwd,\n stdio: 'pipe'\n })\n const addArgs = [\n 'claude',\n 'mcp',\n 'add',\n 'reviewer',\n '-s',\n 'project',\n mcpCommand.command,\n ...mcpCommand.args\n ]\n execSync(addArgs.map(quoteArg).join(' '), {\n cwd,\n stdio: 'pipe'\n })\n console.log('Configured MCP server via claude CLI')\n return\n } catch {\n // Claude CLI not available, fall back to manual config\n }\n\n // 3. Manual .mcp.json creation (always overwrite reviewer to fix any issues)\n let mcpJson: McpJson = { mcpServers: {} }\n if (existsSync(mcpPath)) {\n try {\n mcpJson = JSON.parse(readFileSync(mcpPath, 'utf-8'))\n } catch {\n // Start fresh if parse fails\n }\n }\n\n delete mcpJson.mcpServers['cerebras-reviewer']\n mcpJson.mcpServers['reviewer'] = mcpConfig\n writeFileSync(mcpPath, `${JSON.stringify(mcpJson, null, 2)}\\n`)\n console.log('Configured .mcp.json with reviewer')\n\n // 4. Verify it works\n try {\n const testMsg =\n '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{},\"clientInfo\":{\"name\":\"test\",\"version\":\"1.0.0\"}}}'\n const runCommand = [mcpCommand.command, ...mcpCommand.args].map(quoteArg).join(' ')\n execSync(`echo '${testMsg}' | ${runCommand}`, {\n stdio: 'pipe',\n timeout: 5000\n })\n console.log('Verified MCP server responds correctly')\n } catch {\n console.warn('Warning: MCP server test failed - check paths and try restarting Claude Code')\n }\n}\n\nfunction setupHusky(cwd: string, force: boolean): void {\n const huskyDir = join(cwd, '.husky')\n const preCommitPath = join(huskyDir, 'pre-commit')\n const pkgPath = join(cwd, 'package.json')\n\n if (!existsSync(pkgPath)) {\n console.log('No package.json found - skipping husky setup')\n return\n }\n\n try {\n JSON.parse(readFileSync(pkgPath, 'utf-8'))\n } catch {\n console.warn('Warning: Could not parse package.json')\n return\n }\n\n const hasHusky = existsSync(huskyDir)\n\n if (!hasHusky) {\n try {\n console.log('Initializing husky...')\n execSync('npx husky init', { cwd, stdio: 'pipe' })\n console.log('Initialized husky')\n } catch {\n console.warn('Could not initialize husky automatically')\n console.warn('Run: npx husky init')\n return\n }\n }\n\n if (!existsSync(preCommitPath) || force) {\n writeFileSync(preCommitPath, HUSKY_PRE_COMMIT)\n chmodSync(preCommitPath, '755')\n console.log('Created .husky/pre-commit')\n } else {\n const existing = readFileSync(preCommitPath, 'utf-8')\n if (existing.includes('npm test')) {\n writeFileSync(preCommitPath, HUSKY_PRE_COMMIT)\n chmodSync(preCommitPath, '755')\n console.log('Replaced default pre-commit with lint-staged + gitleaks')\n return\n }\n\n let updated = false\n\n if (!existing.includes('lint-staged')) {\n appendFileSync(preCommitPath, '\\nnpx lint-staged\\n')\n updated = true\n }\n\n if (!existing.includes('gitleaks')) {\n appendFileSync(preCommitPath, '\\ngitleaks protect --staged --verbose\\n')\n updated = true\n }\n\n if (updated) {\n console.log('Updated .husky/pre-commit with lint-staged + gitleaks')\n } else {\n console.log('.husky/pre-commit already configured')\n }\n }\n}\n\nfunction setupLintStaged(cwd: string, force: boolean): void {\n const configPath = join(cwd, '.lintstagedrc.json')\n\n if (!existsSync(configPath) || force) {\n writeFileSync(configPath, `${JSON.stringify(LINT_STAGED_CONFIG, null, 2)}\\n`)\n console.log('Created .lintstagedrc.json')\n } else {\n console.log('.lintstagedrc.json already exists')\n }\n}\n\nfunction checkGitleaks(): void {\n try {\n const checkCmd = process.platform === 'win32' ? 'where gitleaks' : 'command -v gitleaks'\n execSync(checkCmd, { stdio: 'pipe' })\n console.log('gitleaks found')\n } catch {\n console.log('')\n console.log('NOTE: gitleaks not found. Install it:')\n console.log(' brew install gitleaks # macOS')\n console.log(' apt install gitleaks # Debian/Ubuntu')\n console.log(' choco install gitleaks # Windows')\n console.log(' https://github.com/gitleaks/gitleaks#installing')\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["require"]
|
|
7
|
+
}
|
package/dist/cli.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
runInit
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-WBU2V2G7.js";
|
|
5
5
|
import {
|
|
6
6
|
runPost,
|
|
7
7
|
runPre
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-M5RTGB7M.js";
|
|
9
|
+
import "./chunk-T2XUTRSA.js";
|
|
10
10
|
|
|
11
11
|
// src/cli.ts
|
|
12
12
|
import { readFileSync } from "fs";
|
|
@@ -57,10 +57,10 @@ try {
|
|
|
57
57
|
runPost();
|
|
58
58
|
break;
|
|
59
59
|
case "daemon":
|
|
60
|
-
import("./daemon-
|
|
60
|
+
import("./daemon-4YRI3APH.js");
|
|
61
61
|
break;
|
|
62
62
|
case "status":
|
|
63
|
-
import("./status-
|
|
63
|
+
import("./status-UGO6L7NZ.js").then((m) => m.runStatus());
|
|
64
64
|
break;
|
|
65
65
|
case "--help":
|
|
66
66
|
case "-h":
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAyLH,wBAAgB,OAAO,IAAI,IAAI,CA4C9B"}
|
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
DEFAULT_CONFIG,
|
|
4
4
|
checkBashCommand,
|
|
5
5
|
offloadOutput
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-M5RTGB7M.js";
|
|
7
7
|
import {
|
|
8
8
|
loadConfig
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-T2XUTRSA.js";
|
|
10
10
|
|
|
11
11
|
// src/daemon.ts
|
|
12
12
|
import { existsSync, unlinkSync } from "fs";
|
|
@@ -86,4 +86,4 @@ function main() {
|
|
|
86
86
|
});
|
|
87
87
|
}
|
|
88
88
|
main();
|
|
89
|
-
//# sourceMappingURL=daemon-
|
|
89
|
+
//# sourceMappingURL=daemon-4YRI3APH.js.map
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runInit
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-WBU2V2G7.js";
|
|
4
4
|
import {
|
|
5
5
|
DEFAULT_CONFIG,
|
|
6
6
|
checkBashCommand,
|
|
@@ -15,8 +15,8 @@ import {
|
|
|
15
15
|
parseCommand,
|
|
16
16
|
runPost,
|
|
17
17
|
runPre
|
|
18
|
-
} from "./chunk-
|
|
19
|
-
import "./chunk-
|
|
18
|
+
} from "./chunk-M5RTGB7M.js";
|
|
19
|
+
import "./chunk-T2XUTRSA.js";
|
|
20
20
|
export {
|
|
21
21
|
DEFAULT_CONFIG,
|
|
22
22
|
checkBashCommand,
|
package/dist/reviewer/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
checkProviderStatus,
|
|
3
3
|
getAvailableProviders
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-T2XUTRSA.js";
|
|
5
5
|
|
|
6
6
|
// src/commands/status.ts
|
|
7
7
|
async function runStatus() {
|
|
@@ -49,4 +49,4 @@ async function runStatus() {
|
|
|
49
49
|
export {
|
|
50
50
|
runStatus
|
|
51
51
|
};
|
|
52
|
-
//# sourceMappingURL=status-
|
|
52
|
+
//# sourceMappingURL=status-UGO6L7NZ.js.map
|