@gi4nks/ph 1.3.2
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/CHANGELOG.md +57 -0
- package/LICENSE +21 -0
- package/README.md +146 -0
- package/dist/cli.js +3885 -0
- package/dist/cli.js.map +1 -0
- package/docs/hooks.md +83 -0
- package/docs/ph-manual.md +283 -0
- package/hooks/claude/README.md +45 -0
- package/hooks/claude/ph-hook.sh +103 -0
- package/hooks/gemini/README.md +43 -0
- package/hooks/gemini/ph-hook.sh +56 -0
- package/package.json +55 -0
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/config/index.ts","../src/db/index.ts","../src/runner/inline.ts","../src/runner/project.ts","../src/runner/git-context.ts","../src/pty/wrapper.ts","../src/display/print.ts","../src/importer/gemini.ts","../src/analyzer/index.ts","../src/importer/claude.ts","../src/embedding/index.ts","../src/ai/ollama.ts","../src/ai/gemini.ts","../src/ai/provider.ts","../src/analyzer/reusability.ts","../src/background/analyzer.ts","../src/filter/index.ts","../src/ui/BrowseApp.tsx","../src/ui/Header.tsx","../package.json","../src/ui/Footer.tsx","../src/ui/themes.ts","../src/ui/SearchBar.tsx","../src/ui/ListEntry.tsx","../src/utils/extractTopic.ts","../src/ui/PreviewPane.tsx","../src/sessions/index.ts","../src/stats/index.ts","../src/cluster/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport os from 'os';\nimport path from 'path';\nimport fs from 'fs';\nimport { spawnSync } from 'child_process';\nimport React from 'react';\nimport { render } from 'ink';\nimport { load as loadConfig, save as saveConfig } from './config/index.js';\nimport { PhDB, defaultPath, cosineSimilarity } from './db/index.js';\nimport { runInline, resolveRealBinary } from './runner/inline.js';\nimport { detectProject, detectLanguage } from './runner/project.js';\nimport { captureGitContext } from './runner/git-context.js';\nimport { runPTY, isTerminal } from './pty/wrapper.js';\nimport { printResults } from './display/print.js';\nimport { importGeminiHistory } from './importer/gemini.js';\nimport { importClaudeHistory } from './importer/claude.js';\nimport { getEmbeddings } from './embedding/index.js';\nimport { getProvider } from './ai/provider.js';\nimport { analyzeAll, analyzePrompt, mergeMetadata } from './analyzer/index.js';\nimport { ReusabilityAnalyzer } from './analyzer/reusability.js';\nimport { spawnBackgroundAnalysis } from './background/analyzer.js';\nimport { FilterPipeline } from './filter/index.js';\nimport { BrowseApp } from './ui/BrowseApp.js';\nimport { groupIntoSessions, computeSessionCohesion } from './sessions/index.js';\nimport { getStats } from './stats/index.js';\nimport { kmeans } from './cluster/index.js';\nimport { extractTopic } from './utils/extractTopic.js';\nimport type { SearchOptions, PromptMetadata } from './types.js';\nimport type { PhConfig } from './config/index.js';\n\nconst USAGE = `ph — prompt history tracker\n\nUSAGE:\n ph Open interactive TUI browser (default)\n ph <tool> [tool-args...] Wrap a CLI tool, save prompt to history\n ph search [options] [query] Search saved prompts\n ph last [n] Show last N prompts (default 10)\n ph sessions [options] Group prompts into work sessions\n ph stats Show history statistics\n ph cluster [options] Cluster prompts by similarity\n ph analyze-reusability [options] Analyze prompt reusability\n ph star <id> Toggle star on a prompt\n ph export <id> [--format txt|json|md] Export a single prompt\n ph import gemini [--dry-run] [--analyze] [--filter] Import from Gemini CLI sessions\n ph import claude [--dry-run] [--analyze] [--filter] Import from Claude CLI sessions\n ph analyze [--limit n] [--force] [--prune] [--dry-run] Analyze prompts with LLM\n ph cleanup [--dry-run] [--min-length N] [--min-score N] Remove useless prompts\n ph cleanup-reusability [--dry-run] [--threshold 0.7] [--force] Cleanup based on reusability\n ph embed-all Generate embeddings for all prompts\n ph log --tool <name> --prompt <text> [--response <text>] Log a prompt+response directly\n ph config set <key> <value> Save config value\n ph browse Interactive TUI browser\n\nWRAP FLAGS (placed before the tool name):\n --ph-tag <tag> Add a tag to the captured prompt\n --ph-role <role> Set the prompt role (debug, refactor, explain, review, architect, test, docs, generate, research)\n --ph-debug Write a debug log to ~/.ph_debug.log\n\nSEARCH OPTIONS:\n -i, --interactive Open results in interactive TUI browser\n --tool <name> Filter by tool name (claude, gemini, …)\n --project <name> Filter by project name\n --language <lang> Filter by language (go, typescript, python, …)\n --role <role> Filter by role (debug, refactor, explain, …)\n --tag <tag> Filter by tag\n --starred Show only starred prompts\n --min-quality <n> Filter by min quality (0-10)\n --min-relevance <n> Filter by min relevance (0-10)\n --top Show only top quality prompts (quality >= 8)\n --semantic Use semantic search (requires embeddings)\n --since YYYY-MM-DD\n --until YYYY-MM-DD\n --limit <n> Max results (default 50)\n --full Show full prompt without truncation\n\nSESSIONS OPTIONS:\n --gap-hours <n> Hours gap to split sessions (default 2)\n --limit <n> Max sessions to show (default 20)\n --min-size <n> Minimum prompts per session (default 1)\n --no-cohesion Skip semantic cohesion computation\n\nCLUSTER OPTIONS:\n -k <number> Number of clusters (default 5)\n --limit <n> Max prompts per cluster to show (default 3)\n\nANALYZE-REUSABILITY OPTIONS:\n --export-csv <file> Export report to CSV\n --threshold <n> Scoring threshold (default 0.7)\n\nEXAMPLES:\n ph claude \"explain goroutines\"\n ph --ph-role debug --ph-tag auth claude \"fix JWT expiration bug\"\n ph search \"goroutines\"\n ph search --tool claude --role debug --since 2026-01-01 \"error handling\"\n ph search --semantic \"how to handle errors gracefully\"\n ph search -i \"database\"\n ph last 20\n ph sessions\n ph sessions --gap-hours 4 --min-size 3\n ph stats\n ph cluster -k 10\n ph export 5 --format md\n ph import claude --analyze --filter\n ph analyze --force --prune --min-score 3\n ph cleanup --dry-run\n ph embed-all\n ph analyze-reusability --export-csv report.csv\n ph cleanup-reusability --dry-run\n ph config set analyze-provider gemini\n ph config set background-analysis true\n ph config set ollama-model llama3.2:latest\n ph ollama-models List models available on the local Ollama instance\n`;\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction parseFlags(args: string[]): { flags: Record<string, string | boolean>; positional: string[] } {\n const flags: Record<string, string | boolean> = {};\n const positional: string[] = [];\n let i = 0;\n while (i < args.length) {\n const a = args[i];\n if (a.startsWith('--')) {\n const key = a.slice(2);\n if (i + 1 < args.length && !args[i + 1].startsWith('--')) {\n flags[key] = args[i + 1];\n i += 2;\n } else {\n flags[key] = true;\n i++;\n }\n } else {\n positional.push(a);\n i++;\n }\n }\n return { flags, positional };\n}\n\nfunction parseDate(s: string, label: string): Date {\n const d = new Date(s);\n if (isNaN(d.getTime())) {\n process.stderr.write(`ph: invalid ${label} date: ${s}\\n`);\n process.exit(1);\n }\n return d;\n}\n\n// ─── Commands ─────────────────────────────────────────────────────────────────\n\nasync function cmdSearch(db: PhDB, cfg: PhConfig, args: string[]): Promise<void> {\n const { flags, positional } = parseFlags(args);\n\n const query = positional.join(' ');\n\n if (flags['semantic'] && query) {\n await cmdSearchSemantic(db, cfg, query, Number(flags['limit'] ?? 50), Boolean(flags['full']));\n return;\n }\n\n const opts: SearchOptions = {\n query,\n tool: flags['tool'] as string | undefined,\n project: flags['project'] as string | undefined,\n language: flags['language'] as string | undefined,\n role: flags['role'] as string | undefined,\n tag: flags['tag'] as string | undefined,\n starred: Boolean(flags['starred']),\n minQuality: flags['top'] ? 8 : (flags['min-quality'] ? Number(flags['min-quality']) : undefined),\n minRelevance: flags['min-relevance'] ? Number(flags['min-relevance']) : undefined,\n limit: Number(flags['limit'] ?? 50),\n };\n\n if (flags['since']) opts.since = parseDate(flags['since'] as string, '--since');\n if (flags['until']) {\n const d = parseDate(flags['until'] as string, '--until');\n // Include the full day\n d.setHours(23, 59, 59, 999);\n opts.until = d;\n }\n\n const results = db.search(opts);\n printResults(results, Boolean(flags['full']));\n}\n\nasync function cmdSearchSemantic(db: PhDB, cfg: PhConfig, query: string, limit: number, showFull: boolean): Promise<void> {\n const ollamaUrl = cfg.ollamaUrl ?? 'http://localhost:11434';\n const model = cfg.ollamaEmbedModel ?? 'nomic-embed-text-v2-moe';\n\n process.stdout.write(`Searching semantically for: \"${query}\" (model: ${model})...\\n`);\n\n const [queryVec] = await getEmbeddings([query], ollamaUrl, model, 1);\n if (!queryVec) {\n process.stderr.write('ph: failed to get embedding for query\\n');\n process.exit(1);\n }\n\n const embeddings = db.getAllEmbeddings();\n const scores: Array<{ id: number; sim: number }> = [];\n\n for (const [id, vec] of embeddings) {\n const sim = cosineSimilarity(queryVec, vec);\n if (sim > 0.3) scores.push({ id, sim });\n }\n\n scores.sort((a, b) => b.sim - a.sim);\n const topScores = scores.slice(0, limit);\n\n const results = topScores\n .map(({ id }) => db.getById(id))\n .filter((e): e is NonNullable<typeof e> => e !== undefined);\n\n printResults(results, showFull);\n}\n\nasync function cmdLast(db: PhDB, args: string[]): Promise<void> {\n const n = parseInt(args[0] ?? '10', 10);\n const results = db.search({ limit: isNaN(n) ? 10 : n });\n printResults(results, false);\n}\n\nasync function cmdStar(db: PhDB, args: string[]): Promise<void> {\n const id = parseInt(args[0] ?? '', 10);\n if (isNaN(id)) {\n process.stderr.write('Usage: ph star <id>\\n');\n process.exit(1);\n }\n\n const entry = db.getById(id);\n if (!entry) {\n process.stderr.write(`ph: prompt #${id} not found\\n`);\n process.exit(1);\n }\n\n let meta: PromptMetadata = {};\n try { meta = JSON.parse(entry.metadata) as PromptMetadata; } catch {}\n\n const wasStarred = Boolean(meta.starred);\n meta.starred = !wasStarred;\n\n db.updateMetadata(id, JSON.stringify(meta));\n\n if (meta.starred) {\n console.log(`Prompt #${id} starred ★`);\n } else {\n console.log(`Prompt #${id} unstarred`);\n }\n}\n\nasync function cmdExport(db: PhDB, args: string[]): Promise<void> {\n const { flags, positional } = parseFlags(args);\n const id = parseInt(positional[0] ?? '', 10);\n\n if (isNaN(id)) {\n process.stderr.write('Usage: ph export <id> [--format txt|json|md]\\n');\n process.exit(1);\n }\n\n const entry = db.getById(id);\n if (!entry) {\n process.stderr.write(`ph: prompt #${id} not found\\n`);\n process.exit(1);\n }\n\n const format = (flags['format'] as string) ?? 'txt';\n\n switch (format) {\n case 'txt':\n case 'text':\n process.stdout.write(entry.prompt);\n break;\n\n case 'json': {\n const obj = {\n id: entry.id,\n timestamp: entry.timestamp,\n tool: entry.tool,\n prompt: entry.prompt,\n metadata: JSON.parse(entry.metadata) as unknown,\n };\n console.log(JSON.stringify(obj));\n break;\n }\n\n case 'md':\n case 'markdown': {\n let meta: PromptMetadata = {};\n try { meta = JSON.parse(entry.metadata) as PromptMetadata; } catch {}\n\n let md = `# Prompt #${entry.id}\\n\\n`;\n if (meta.starred) md += '★ **Starred**\\n\\n';\n md += `- **Tool**: ${entry.tool}\\n`;\n md += `- **Date**: ${entry.timestamp}\\n`;\n if (meta.project) md += `- **Project**: ${meta.project}\\n`;\n if (meta.language) md += `- **Language**: ${meta.language}\\n`;\n if (meta.role) md += `- **Role**: ${meta.role}\\n`;\n if (meta.tags && meta.tags.length > 0) md += `- **Tags**: ${meta.tags.join(', ')}\\n`;\n md += `- **Dir**: ${entry.workdir}\\n\\n---\\n\\n## Prompt\\n\\n${entry.prompt}\\n`;\n\n if (entry.response) {\n md += `\\n## Response\\n\\n${entry.response}\\n`;\n }\n\n if (meta.git_context) {\n md += `\\n## Git Context\\n\\n`;\n md += `**Branch**: ${meta.git_context.branch}\\n`;\n if (meta.git_context.files.length > 0) {\n md += `**Modified files**: ${meta.git_context.files.join(', ')}\\n`;\n }\n md += `\\n\\`\\`\\`diff\\n${meta.git_context.diff}\\n\\`\\`\\`\\n`;\n }\n\n process.stdout.write(md);\n break;\n }\n\n default:\n process.stderr.write(`ph: unknown format \"${format}\" — use txt, json, or md\\n`);\n process.exit(1);\n }\n}\n\nasync function cmdImport(db: PhDB, cfg: PhConfig, args: string[]): Promise<void> {\n if (args.length === 0) {\n process.stderr.write('Usage: ph import <source> [--dry-run] [--analyze]\\n');\n process.exit(1);\n }\n\n const source = args[0];\n const { flags } = parseFlags(args.slice(1));\n const dryRun = Boolean(flags['dry-run']);\n const analyze = Boolean(flags['analyze']);\n const useFilter = Boolean(flags['filter']);\n const homeDir = os.homedir();\n\n if (dryRun) console.log('Dry run — nothing will be written to the database.');\n\n let analyzer;\n if (analyze) {\n analyzer = getProvider(cfg);\n if (!analyzer) {\n process.stderr.write('ph: no LLM provider configured. Run: ph config set analyze-provider ollama\\n');\n process.exit(1);\n }\n console.log(`Analyzing with ${analyzer.name} during import...`);\n }\n\n let filter: FilterPipeline | undefined;\n \n // Always load existing hashes for deduplication unless we are doing a dry-run\n const existingHashes = dryRun ? new Map<string, number>() : db.getAllPromptHashes();\n \n if (useFilter) {\n filter = new FilterPipeline({\n minLength: cfg.filterMinLength,\n minRelevance: analyze ? (cfg.filterMinRelevance ?? 3) : 0,\n existingHashes,\n });\n console.log(`Filtering enabled (min-length: ${cfg.filterMinLength ?? 15}${analyze ? `, min-relevance: ${cfg.filterMinRelevance ?? 3}` : ''}).`);\n } else {\n // If not full filtering, we still create a minimal FilterPipeline just for exact duplication checks\n filter = new FilterPipeline({\n minLength: 0,\n minRelevance: 0,\n existingHashes,\n });\n // We mock checkRules so it only dedups, effectively bypassing the length/trivial rules\n filter.checkRules = () => ({ keep: true });\n }\n\n const onProgress = (evaluated: number, imported: number, total: number, current: string) => {\n const text = current.length > 50 ? current.slice(0, 47) + '...' : current;\n // Show [evaluated/total] (imported) so user knows progress\n process.stdout.write(`\\r [${evaluated}/${total}] (imported: ${imported}) ${text.replace(/\\n/g, ' ')}`.padEnd(80));\n };\n\n let result;\n switch (source) {\n case 'gemini':\n result = await importGeminiHistory(db, path.join(homeDir, '.gemini'), dryRun, analyzer, onProgress, filter);\n break;\n case 'claude':\n result = await importClaudeHistory(db, path.join(homeDir, '.claude'), dryRun, analyzer, onProgress, filter);\n break;\n default:\n process.stderr.write(`ph: unknown import source \"${source}\". Supported: gemini, claude\\n`);\n process.exit(1);\n }\n\n if (analyze) process.stdout.write('\\n');\n console.log(`Files scanned: ${result.filesScanned}`);\n console.log(`Prompts found: ${result.promptsFound}`);\n console.log(`Prompts imported: ${result.promptsImported}`);\n if (result.filtered > 0) console.log(`Filtered out: ${result.filtered}`);\n if (analyze) console.log(`Analyzed: ${result.promptsImported} prompts tagged`);\n if (result.skipped > 0) console.log(`Skipped: ${result.skipped}`);\n if (result.errors.length > 0) {\n console.log(`\\nWarnings (${result.errors.length}):`);\n for (const e of result.errors) console.log(` - ${e}`);\n }\n if (!dryRun && result.promptsImported > 0) {\n console.log(`\\nDone! Run \\`ph last ${Math.min(result.promptsImported, 20)}\\` to review.`);\n }\n}\n\nasync function cmdAnalyze(db: PhDB, cfg: PhConfig, args: string[]): Promise<void> {\n const { flags } = parseFlags(args);\n const force = Boolean(flags['force']);\n const dryRun = Boolean(flags['dry-run']);\n const prune = Boolean(flags['prune']);\n const limitFlag = flags['limit'] ? Number(flags['limit']) : undefined;\n const pruneBelow = prune ? (flags['min-score'] ? Number(flags['min-score']) : (cfg.filterMinRelevance ?? 3)) : 0;\n\n const provider = getProvider(cfg);\n if (!provider) {\n process.stderr.write('ph: no LLM provider configured. Set analyze-provider in config.\\n');\n process.exit(1);\n }\n\n const allRows = db.search({ limit: 10000 });\n const limit = limitFlag ?? (force ? undefined : 50);\n const entries = limit !== undefined ? allRows.slice(0, limit) : allRows;\n\n let modeStr = force ? ' (--force: reanalyze all)' : ' (untagged only)';\n if (prune) modeStr += dryRun ? ` + prune<${pruneBelow} [dry-run]` : ` + prune<${pruneBelow}`;\n console.log(`Analyzing with ${provider.name}${modeStr}...`);\n\n const stats = await analyzeAll(entries, provider, db, {\n force,\n pruneBelow,\n dryRun,\n onProgress: (done, total, entry, res, err) => {\n const truncated = entry.prompt.replace(/\\n/g, ' ');\n const short = truncated.length > 40 ? truncated.slice(0, 37) + '...' : truncated;\n if (err) {\n console.log(` [${done}/${total}] #${entry.id} → error: ${err}`);\n } else if (res) {\n const role = res.role || '-';\n const tags = (res.tags ?? []).join(',') || '-';\n const relStr = res.relevance !== undefined ? ` rel:${res.relevance}` : '';\n console.log(` [${done}/${total}] #${entry.id} → role:${role} tags:${tags}${relStr} | ${short}`);\n }\n },\n onPrune: (entry, relevance) => {\n const short = entry.prompt.replace(/\\n/g, ' ').slice(0, 50);\n console.log(` [prune${dryRun ? ' DRY' : ''}] #${entry.id} rel:${relevance} | ${short}`);\n },\n });\n\n let summary = `\\nDone. Updated: ${stats.updated}, Skipped: ${stats.skipped}, Failed: ${stats.failed}`;\n if (prune) summary += `, Pruned: ${stats.pruned}${dryRun ? ' (dry-run, not deleted)' : ''}`;\n console.log(summary);\n}\n\nasync function cmdEmbedAll(db: PhDB, cfg: PhConfig): Promise<void> {\n const ollamaUrl = cfg.ollamaUrl ?? 'http://localhost:11434';\n const model = cfg.ollamaEmbedModel ?? 'nomic-embed-text-v2-moe';\n\n const toEmbed = db.getPromptsWithoutEmbeddings();\n\n if (toEmbed.length === 0) {\n console.log('No new prompts to embed.');\n return;\n }\n\n const batchSize = 20;\n console.log(\n `Generating embeddings for ${toEmbed.length} prompts via Ollama (${model}), batches of ${batchSize}...`\n );\n\n for (let i = 0; i < toEmbed.length; i += batchSize) {\n const batch = toEmbed.slice(i, i + batchSize);\n const texts = batch.map((e) => e.response ? `${e.prompt}\\n\\n${e.response}` : e.prompt);\n process.stdout.write(`\\r→ ${i + batch.length}/${toEmbed.length}...`);\n\n try {\n const vecs = await getEmbeddings(texts, ollamaUrl, model, batchSize);\n for (let j = 0; j < vecs.length; j++) {\n try {\n db.saveEmbedding(batch[j].id, vecs[j]);\n } catch (e: unknown) {\n console.log(`\\n ! DB error for #${batch[j].id}: ${(e as Error).message}`);\n }\n }\n } catch (e: unknown) {\n console.log(`\\n ! Batch error: ${(e as Error).message}`);\n }\n }\n\n console.log('\\nDone!');\n}\n\nasync function cmdLog(dbPath: string, cfg: PhConfig, args: string[]): Promise<void> {\n // Support two modes:\n // 1. Flags: ph log --tool claude --prompt \"...\" --response \"...\"\n // 2. Stdin JSON: echo '{\"tool\":\"claude\",\"prompt\":\"...\",\"response\":\"...\"}' | ph log\n let tool: string;\n let prompt: string;\n let response: string;\n let workdir: string;\n\n const { flags } = parseFlags(args);\n\n if (flags['prompt']) {\n tool = (flags['tool'] as string) || 'unknown';\n prompt = (flags['prompt'] as string);\n response = (flags['response'] as string) || '';\n workdir = (flags['workdir'] as string) || process.cwd();\n } else {\n // Read JSON from stdin\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) chunks.push(chunk as Buffer);\n const raw = Buffer.concat(chunks).toString('utf-8').trim();\n if (!raw) { process.stderr.write('ph log: no input (use --prompt or pipe JSON)\\n'); process.exit(1); }\n let parsed: Record<string, string>;\n try { parsed = JSON.parse(raw) as Record<string, string>; }\n catch { process.stderr.write('ph log: invalid JSON on stdin\\n'); process.exit(1); }\n tool = parsed['tool'] || (flags['tool'] as string) || 'unknown';\n prompt = parsed['prompt'] || '';\n response = parsed['response'] || '';\n workdir = parsed['workdir'] || (flags['workdir'] as string) || process.cwd();\n if (!prompt) { process.stderr.write('ph log: missing \"prompt\" field\\n'); process.exit(1); }\n }\n\n const { rootDir, projectName } = detectProject(workdir);\n const language = detectLanguage(rootDir);\n\n const metaObj: Record<string, unknown> = {};\n if (projectName) metaObj.project = projectName;\n if (language) metaObj.language = language;\n\n const title = extractTopic(prompt);\n if (title) metaObj.title = title;\n\n const db = new PhDB(dbPath);\n const id = db.insert({\n timestamp: new Date().toISOString(),\n tool,\n prompt,\n response,\n args: '',\n workdir,\n hostname: os.hostname(),\n exit_code: 0,\n metadata: JSON.stringify(metaObj),\n });\n db.close();\n\n if (cfg.backgroundAnalysis) {\n spawnBackgroundAnalysis(id, dbPath);\n }\n}\n\nfunction cmdConfig(args: string[]): void {\n if (args.length < 3 || args[0] !== 'set') {\n console.log('Usage: ph config set <key> <value>');\n console.log('Keys: gemini-api-key, db-path, analyze-provider, ollama-url, ollama-model,');\n console.log(' ollama-embed-model, filter-min-length, filter-min-relevance, background-analysis');\n process.exit(1);\n }\n\n const cfg = loadConfig();\n const key = args[1];\n const val = args[2];\n\n switch (key) {\n case 'gemini-api-key':\n cfg.geminiApiKey = val;\n break;\n case 'db-path':\n cfg.dbPath = val;\n break;\n case 'analyze-provider':\n if (val !== 'ollama' && val !== 'gemini') {\n process.stderr.write('ph: analyze-provider must be \"ollama\" or \"gemini\"\\n');\n process.exit(1);\n }\n cfg.analyzeProvider = val as 'ollama' | 'gemini';\n break;\n case 'ollama-url':\n cfg.ollamaUrl = val;\n break;\n case 'ollama-model':\n cfg.ollamaModel = val;\n break;\n case 'ollama-embed-model':\n cfg.ollamaEmbedModel = val;\n break;\n case 'filter-min-length': {\n const n = Number(val);\n if (isNaN(n) || n < 0) { process.stderr.write('ph: filter-min-length must be a non-negative integer\\n'); process.exit(1); }\n cfg.filterMinLength = n;\n break;\n }\n case 'filter-min-relevance': {\n const n = Number(val);\n if (isNaN(n) || n < 0 || n > 10) { process.stderr.write('ph: filter-min-relevance must be 0-10\\n'); process.exit(1); }\n cfg.filterMinRelevance = n;\n break;\n }\n case 'background-analysis':\n cfg.backgroundAnalysis = val === 'true' || val === '1';\n break;\n default:\n process.stderr.write(`ph: unknown config key \"${key}\"\\n`);\n process.exit(1);\n }\n\n saveConfig(cfg);\n console.log(`Config \"${key}\" updated successfully.`);\n}\n\nasync function cmdBackgroundAnalyze(dbPath: string, args: string[]): Promise<void> {\n const id = parseInt(args[0], 10);\n if (isNaN(id)) return;\n\n let finalDbPath = dbPath;\n const dbIdx = args.indexOf('--db');\n if (dbIdx !== -1 && dbIdx + 1 < args.length) {\n finalDbPath = args[dbIdx + 1];\n }\n\n const cfg = loadConfig();\n const provider = getProvider(cfg);\n if (!provider) return;\n\n const db = new PhDB(finalDbPath);\n try {\n const entry = db.getById(id);\n if (!entry) return;\n\n const result = await analyzePrompt(entry.prompt, provider);\n if (Object.keys(result).length === 0) return;\n\n let existing: PromptMetadata = {};\n try { existing = JSON.parse(entry.metadata) as PromptMetadata; } catch {}\n\n const merged = mergeMetadata(existing, result, false);\n db.updateMetadata(id, JSON.stringify(merged));\n } catch (_err: unknown) {\n // Silent fail for background process\n } finally {\n db.close();\n }\n}\n\nasync function cmdCleanup(db: PhDB, cfg: PhConfig, args: string[]): Promise<void> {\n const { flags } = parseFlags(args);\n const dryRun = Boolean(flags['dry-run']);\n const minLength = flags['min-length'] ? Number(flags['min-length']) : (cfg.filterMinLength ?? 15);\n const minScore = flags['min-score'] ? Number(flags['min-score']) : (cfg.filterMinRelevance ?? 3);\n const days = flags['days'] ? Number(flags['days']) : undefined;\n\n if (days !== undefined) {\n if (dryRun) {\n console.log(`(dry-run) Would delete prompts older than ${days} days.`);\n } else {\n const deleted = db.deleteOlderThan(days);\n console.log(`Deleted ${deleted} prompts older than ${days} days.`);\n }\n }\n\n const allEntries = db.search({ limit: 100000 });\n console.log(`Scanning ${allEntries.length} prompts for rule-based cleanup (min-length: ${minLength}, min-score: ${minScore})...`);\n\n const toDelete: Array<{ id: number; prompt: string; reason: string }> = [];\n const existingHashes = new Map<string, number>();\n\n const filter = new FilterPipeline({ minLength, minRelevance: 0, existingHashes });\n\n for (const entry of allEntries) {\n // Rule-based check\n const ruleResult = filter.checkRules(entry.prompt);\n if (!ruleResult.keep) {\n toDelete.push({ id: entry.id, prompt: entry.prompt, reason: `${ruleResult.reason}: ${ruleResult.details ?? ''}` });\n continue;\n }\n\n // Exact dedup check\n const hash = FilterPipeline.hashPrompt(entry.prompt);\n if (existingHashes.has(hash)) {\n const dupId = existingHashes.get(hash);\n toDelete.push({ id: entry.id, prompt: entry.prompt, reason: `exact_duplicate of #${dupId}` });\n continue;\n }\n existingHashes.set(hash, entry.id);\n\n // Relevance score check (only for already-analyzed prompts)\n if (minScore > 0) {\n let meta: PromptMetadata = {};\n try { meta = JSON.parse(entry.metadata) as PromptMetadata; } catch {}\n if (meta.relevance !== undefined && meta.relevance < minScore) {\n toDelete.push({ id: entry.id, prompt: entry.prompt, reason: `low_relevance: ${meta.relevance} < ${minScore}` });\n }\n }\n }\n\n if (toDelete.length === 0) {\n if (days === undefined) console.log('Nothing else to clean up.');\n return;\n }\n\n console.log(`\\nCandidates for rule-based deletion: ${toDelete.length}`);\n for (const item of toDelete.slice(0, 30)) {\n const short = item.prompt.replace(/\\n/g, ' ').slice(0, 60);\n console.log(` #${String(item.id).padEnd(5)} [${item.reason}] \"${short}\"`);\n }\n if (toDelete.length > 30) {\n console.log(` ... and ${toDelete.length - 30} more`);\n }\n\n if (dryRun) {\n console.log(`\\n(dry-run) Would delete ${toDelete.length} more prompts. Run without --dry-run to apply.`);\n return;\n }\n\n const ids = toDelete.map(e => e.id);\n const deleted = db.deleteByIds(ids);\n console.log(`\\nDeleted ${deleted} prompts.`);\n}\n\nasync function cmdVacuum(db: PhDB): Promise<void> {\n process.stdout.write('Compacting database (VACUUM)... ');\n const start = Date.now();\n db.vacuum();\n const elapsed = ((Date.now() - start) / 1000).toFixed(2);\n console.log(`Done in ${elapsed}s.`);\n}\n\nasync function cmdSessions(db: PhDB, args: string[]): Promise<void> {\n const { flags } = parseFlags(args);\n const gapHours = Number(flags['gap-hours'] ?? 2);\n const limit = Number(flags['limit'] ?? 20);\n const minSize = Number(flags['min-size'] ?? 1);\n const noCohesion = Boolean(flags['no-cohesion']);\n\n const C = {\n reset: '\\x1b[0m',\n cyan: '\\x1b[36m',\n yellow: '\\x1b[33m',\n green: '\\x1b[32m',\n gray: '\\x1b[90m',\n red: '\\x1b[31m',\n blue: '\\x1b[34m',\n magenta: '\\x1b[35m',\n };\n\n function fmtDate(ts: string): string {\n const d = new Date(ts);\n const yr = d.getFullYear();\n const mo = String(d.getMonth() + 1).padStart(2, '0');\n const dy = String(d.getDate()).padStart(2, '0');\n const hh = String(d.getHours()).padStart(2, '0');\n const mm = String(d.getMinutes()).padStart(2, '0');\n return `${yr}-${mo}-${dy} ${hh}:${mm}`;\n }\n\n function fmtTime(ts: string): string {\n const d = new Date(ts);\n const hh = String(d.getHours()).padStart(2, '0');\n const mm = String(d.getMinutes()).padStart(2, '0');\n return `${hh}:${mm}`;\n }\n\n // Load all prompts in DESC order, then reverse to ASC\n const allEntries = db.search({ limit: 100000 });\n const entriesAsc = [...allEntries].reverse();\n\n const sessions = groupIntoSessions(entriesAsc, gapHours);\n\n // Load embeddings and compute cohesion unless --no-cohesion\n let embeddings: Map<number, Float32Array> | null = null;\n if (!noCohesion) {\n embeddings = db.getAllEmbeddings();\n }\n\n for (const session of sessions) {\n if (embeddings) {\n session.cohesion = computeSessionCohesion(session, embeddings);\n }\n }\n\n // Filter by min-size\n const filtered = sessions.filter(s => s.entries.length >= minSize);\n\n // Take the last `limit` sessions (most recent)\n const visible = filtered.slice(-limit);\n\n if (visible.length === 0) {\n process.stdout.write('No sessions found.\\n');\n return;\n }\n\n for (const session of visible) {\n // Determine dominant project and language (>50% frequency)\n const projectCounts = new Map<string, number>();\n const languageCounts = new Map<string, number>();\n for (const entry of session.entries) {\n let meta: PromptMetadata = {};\n try { meta = JSON.parse(entry.metadata) as PromptMetadata; } catch {}\n if (meta.project) projectCounts.set(meta.project, (projectCounts.get(meta.project) ?? 0) + 1);\n if (meta.language) languageCounts.set(meta.language, (languageCounts.get(meta.language) ?? 0) + 1);\n }\n\n const total = session.entries.length;\n let dominantProject: string | null = null;\n let dominantLanguage: string | null = null;\n\n for (const [proj, count] of projectCounts) {\n if (count / total > 0.5) { dominantProject = proj; break; }\n }\n for (const [lang, count] of languageCounts) {\n if (count / total > 0.5) { dominantLanguage = lang; break; }\n }\n\n // Build session header\n const startStr = fmtDate(session.startTime.toISOString());\n const endStr = fmtTime(session.endTime.toISOString());\n const promptWord = session.entries.length === 1 ? 'prompt' : 'prompts';\n\n let header = `${C.cyan}Session ${session.index}${C.reset}`;\n header += ` ${C.gray}·${C.reset} ${startStr} → ${endStr}`;\n header += ` ${C.gray}·${C.reset} ${C.yellow}${session.entries.length} ${promptWord}${C.reset}`;\n\n if (dominantProject && dominantLanguage) {\n header += ` ${C.gray}· [${dominantProject}:${dominantLanguage}]${C.reset}`;\n } else if (dominantProject) {\n header += ` ${C.gray}· [${dominantProject}]${C.reset}`;\n } else if (dominantLanguage) {\n header += ` ${C.gray}· [${dominantLanguage}]${C.reset}`;\n }\n\n if (session.cohesion !== null) {\n header += ` ${C.gray}· cohesion: ${session.cohesion.toFixed(2)}${C.reset}`;\n }\n\n process.stdout.write(header + '\\n');\n\n // Print each entry\n for (const entry of session.entries) {\n let meta: PromptMetadata = {};\n try { meta = JSON.parse(entry.metadata) as PromptMetadata; } catch {}\n\n const idStr = `${C.cyan}#${entry.id}${C.reset}`;\n const toolStr = `${C.yellow}${entry.tool.padEnd(8)}${C.reset}`;\n const timeStr = `${C.gray}${fmtTime(entry.timestamp)}${C.reset}`;\n\n let rolePart = '';\n if (meta.role) rolePart = ` ${C.magenta}{${meta.role}}${C.reset}`;\n\n let tagsPart = '';\n if (meta.tags && meta.tags.length > 0) tagsPart = ` ${C.cyan}(${meta.tags.join(', ')})${C.reset}`;\n\n const preview = entry.prompt.replace(/\\n/g, ' ').slice(0, 80);\n\n process.stdout.write(` ${idStr} ${toolStr} ${timeStr}${rolePart}${tagsPart} ${preview}\\n`);\n }\n\n process.stdout.write('\\n');\n }\n}\n\nasync function cmdStats(db: PhDB): Promise<void> {\n const stats = getStats(db);\n const C = {\n reset: '\\x1b[0m',\n cyan: '\\x1b[36m',\n yellow: '\\x1b[33m',\n green: '\\x1b[32m',\n gray: '\\x1b[90m',\n magenta: '\\x1b[35m',\n };\n\n console.log(`${C.cyan}ph — Prompt History Statistics${C.reset}\\n`);\n console.log(` Total prompts: ${C.yellow}${stats.total}${C.reset}`);\n console.log(` Analyzed: ${C.yellow}${stats.analyzed}${C.reset} (${Math.round((stats.analyzed / (stats.total || 1)) * 100)}%)`);\n console.log(` Starred: ${C.yellow}${stats.starred}${C.reset}`);\n \n if (stats.avgRelevance > 0 || stats.avgQuality > 0) {\n console.log(`\\n${C.cyan}Global Scores:${C.reset}`);\n console.log(` - Avg Relevance: ${C.yellow}${stats.avgRelevance.toFixed(1)}/10${C.reset}`);\n console.log(` - Avg Quality: ${C.yellow}${stats.avgQuality.toFixed(1)}/10${C.reset}`);\n }\n \n console.log(`\\n${C.cyan}By Tool:${C.reset}`);\n Object.entries(stats.byTool).sort((a, b) => b[1] - a[1]).forEach(([tool, count]) => {\n console.log(` - ${tool.padEnd(12)}: ${C.yellow}${count}${C.reset}`);\n });\n\n if (Object.keys(stats.byProject).length > 0) {\n console.log(`\\n${C.cyan}Top Projects:${C.reset}`);\n Object.entries(stats.byProject).sort((a, b) => b[1] - a[1]).slice(0, 10).forEach(([proj, count]) => {\n console.log(` - ${proj.padEnd(20)}: ${C.yellow}${count}${C.reset}`);\n });\n }\n\n if (Object.keys(stats.byLanguage).length > 0) {\n console.log(`\\n${C.cyan}Top Languages:${C.reset}`);\n Object.entries(stats.byLanguage).sort((a, b) => b[1] - a[1]).slice(0, 10).forEach(([lang, count]) => {\n console.log(` - ${lang.padEnd(12)}: ${C.yellow}${count}${C.reset}`);\n });\n }\n\n if (Object.keys(stats.byRole).length > 0) {\n console.log(`\\n${C.cyan}By Role:${C.reset}`);\n Object.entries(stats.byRole).sort((a, b) => b[1] - a[1]).forEach(([role, count]) => {\n console.log(` - ${role.padEnd(12)}: ${C.yellow}${count}${C.reset}`);\n });\n }\n console.log();\n}\n\nasync function cmdCluster(db: PhDB, args: string[]): Promise<void> {\n const { flags } = parseFlags(args);\n const k = Number(flags['k'] ?? 5);\n const limitPerCluster = Number(flags['limit'] ?? 3);\n\n const embeddings = db.getAllEmbeddings();\n if (embeddings.size === 0) {\n console.error('ph: no embeddings found. Run `ph embed-all` first.');\n return;\n }\n\n console.log(`Clustering ${embeddings.size} prompts into ${k} groups...`);\n const clusters = kmeans(embeddings, k);\n\n const C = {\n reset: '\\x1b[0m',\n cyan: '\\x1b[36m',\n yellow: '\\x1b[33m',\n gray: '\\x1b[90m',\n };\n\n clusters.forEach((cluster, i) => {\n if (cluster.entryIds.length === 0) return;\n console.log(`\\n${C.cyan}Cluster #${i + 1}${C.reset} (${C.yellow}${cluster.entryIds.length} prompts${C.reset})`);\n \n // Show some examples from this cluster\n const examples = cluster.entryIds.slice(0, limitPerCluster);\n examples.forEach(id => {\n const entry = db.getById(id);\n if (entry) {\n const preview = entry.prompt.replace(/\\n/g, ' ').slice(0, 80);\n console.log(` ${C.gray}#${entry.id}${C.reset} ${preview}`);\n }\n });\n if (cluster.entryIds.length > limitPerCluster) {\n console.log(` ${C.gray}... and ${cluster.entryIds.length - limitPerCluster} more${C.reset}`);\n }\n });\n console.log();\n}\n\nasync function cmdAnalyzeReusability(db: PhDB, args: string[]): Promise<void> {\n const { flags } = parseFlags(args);\n const threshold = flags['threshold'] ? Number(flags['threshold']) : 0.7;\n const exportCsv = flags['export-csv'] as string;\n\n const entries = db.getAllPrompts();\n const embeddings = db.getAllEmbeddings();\n\n if (embeddings.size === 0) {\n console.warn('ph: no embeddings found. Uniqueness score will be 1.0 for all. Run `ph embed-all` first.');\n }\n\n console.log(`Scanning ${entries.length} prompts...`);\n const analyzer = new ReusabilityAnalyzer(threshold);\n const report = analyzer.analyze(entries, embeddings);\n\n const C = {\n reset: '\\x1b[0m',\n cyan: '\\x1b[36m',\n yellow: '\\x1b[33m',\n green: '\\x1b[32m',\n red: '\\x1b[31m',\n gray: '\\x1b[90m',\n bold: '\\x1b[1m',\n };\n\n console.log(`\\n${C.bold}SUMMARY:${C.reset}`);\n console.log(` - ${C.green}KEEP${C.reset} (score 7+): ${C.yellow}${report.keep.length}${C.reset} prompts (${((report.keep.length / report.total) * 100).toFixed(1)}%)`);\n console.log(` - ${C.cyan}REVIEW${C.reset} (score 4-7): ${C.yellow}${report.review.length}${C.reset} prompts (${((report.review.length / report.total) * 100).toFixed(1)}%)`);\n console.log(` - ${C.red}REMOVE${C.reset} (score <4): ${C.yellow}${report.remove.length}${C.reset} prompts (${((report.remove.length / report.total) * 100).toFixed(1)}%)`);\n\n console.log(`\\n${C.bold}BY ROLE:${C.reset}`);\n const roles = Object.keys(report.byRole).sort();\n for (const role of roles) {\n const r = report.byRole[role];\n const roleStr = role.padEnd(12);\n console.log(` ${C.gray}${roleStr}${C.reset} | KEEP: ${C.green}${r.keep.toString().padEnd(4)}${C.reset} REVIEW: ${C.cyan}${r.review.toString().padEnd(4)}${C.reset} REMOVE: ${C.red}${r.remove.toString().padEnd(4)}${C.reset}`);\n }\n\n console.log(`\\n${C.bold}DUPLICATES FOUND:${C.reset}`);\n console.log(` - Exact semantic (sim > 0.95): ${C.yellow}${report.duplicates.exact}${C.reset} prompts`);\n console.log(` - Variant clusters (sim 0.85-0.95): ${C.yellow}${report.duplicates.variants}${C.reset} prompts`);\n\n console.log(`\\n${C.bold}TOP 10 KEEP (unique + high score):${C.reset}`);\n report.keep.slice(0, 10).forEach(s => {\n const scoreStr = s.score.toFixed(1).padStart(4);\n console.log(` [${C.green}${scoreStr}${C.reset}] ${s.prompt.replace(/\\n/g, ' ').slice(0, 80)}...`);\n });\n\n console.log(`\\n${C.bold}TOP 10 REMOVE (low score + duplicate):${C.reset}`);\n report.remove.slice(0, 10).forEach(s => {\n const scoreStr = s.score.toFixed(1).padStart(4);\n console.log(` [${C.red}${scoreStr}${C.reset}] ${s.prompt.replace(/\\n/g, ' ').slice(0, 80)}...`);\n });\n\n if (exportCsv) {\n fs.writeFileSync(exportCsv, analyzer.toCSV(report));\n console.log(`\\n${C.green}✅ Report exported to ${exportCsv}${C.reset}`);\n }\n console.log();\n}\n\nasync function cmdCleanupReusability(db: PhDB, cfg: PhConfig, args: string[]): Promise<void> {\n const { flags } = parseFlags(args);\n const threshold = flags['threshold'] ? parseFloat(flags['threshold'] as string) : 0.7;\n const dryRun = Boolean(flags['dry-run']);\n const force = Boolean(flags['force']);\n\n const entries = db.getAllPrompts();\n const embeddings = db.getAllEmbeddings();\n\n const analyzer = new ReusabilityAnalyzer(threshold);\n const candidates = analyzer.getRemovalCandidates(entries, embeddings, threshold);\n\n if (candidates.length === 0) {\n console.log('ph: no prompts match removal criteria');\n return;\n }\n\n // Calc sizes\n const totalSize = candidates.reduce((sum, c) => sum + c.promptSize + c.responseSize, 0);\n const totalEmbeddingSize = candidates.filter(c => c.hasEmbedding).length * 768 * 4; // estimate for 768-dim float32\n const totalToFree = totalSize + totalEmbeddingSize;\n\n const C = {\n reset: '\\x1b[0m',\n cyan: '\\x1b[36m',\n yellow: '\\x1b[33m',\n red: '\\x1b[31m',\n gray: '\\x1b[90m',\n bold: '\\x1b[1m',\n };\n\n const removeThreshold = Math.max(0, threshold - 0.3) * 10;\n const dbCount = entries.length;\n\n console.log(`\\nWould delete ${C.red}${candidates.length}${C.reset} prompts (${((candidates.length / dbCount) * 100).toFixed(1)}% of database):`);\n console.log(` - By score < ${removeThreshold.toFixed(1)}: ${candidates.length} prompts`);\n\n // Group by role\n const byRole: Record<string, number> = {};\n for (const c of candidates) {\n byRole[c.role] = (byRole[c.role] ?? 0) + 1;\n }\n const roleSummary = Object.entries(byRole)\n .sort((a, b) => b[1] - a[1])\n .map(([role, count]) => `${role} (${count})`)\n .join(', ');\n\n console.log(` - By role (mostly): ${roleSummary}`);\n\n console.log(`\\nStorage impact:`);\n console.log(` - Prompt text: ~${(candidates.reduce((sum, c) => sum + c.promptSize, 0) / 1024 / 1024).toFixed(2)} MB`);\n console.log(` - Response text: ~${(candidates.reduce((sum, c) => sum + c.responseSize, 0) / 1024 / 1024).toFixed(2)} MB`);\n console.log(` - Embeddings: ~${(totalEmbeddingSize / 1024 / 1024).toFixed(2)} MB`);\n console.log(` Total to free: ~${(totalToFree / 1024 / 1024).toFixed(2)} MB`);\n\n if (candidates.length > 0) {\n console.log(`\\n${C.bold}Example candidates (top 20):${C.reset}`);\n candidates.slice(0, 20).forEach(c => {\n const entry = entries.find(e => e.id === c.id);\n if (entry) {\n const preview = entry.prompt.replace(/\\n/g, ' ').slice(0, 80);\n console.log(` [${C.red}${c.score.toFixed(1)}${C.reset}] #${entry.id} ${preview}...`);\n }\n });\n }\n\n if (dryRun) {\n console.log(`\\nRun with ${C.bold}--force${C.reset} or without ${C.bold}--dry-run${C.reset} to proceed.`);\n return;\n }\n\n if (!force) {\n process.stdout.write(`\\nContinue and delete ${candidates.length} prompts? (y/N) `);\n const buffer = Buffer.alloc(16);\n const bytesRead = fs.readSync(0, buffer, 0, 16);\n const answer = buffer.toString('utf8', 0, bytesRead).trim().toLowerCase();\n if (answer !== 'y' && answer !== 'yes') {\n console.log('Aborted.');\n return;\n }\n }\n\n let deleted = 0;\n for (const candidate of candidates) {\n db.delete(candidate.id);\n deleted++;\n }\n\n console.log(`\\nDeleted ${deleted} prompts, freed ~${(totalToFree / 1024 / 1024).toFixed(1)} MB`);\n db.vacuum();\n console.log('Database vacuumed.');\n}\n\nasync function cmdWrap(dbPath: string, tool: string, args: string[], cfg: PhConfig): Promise<void> {\n // Strip --ph-tag, --ph-role and --ph-debug from args before passing to real tool\n let debugLog: string | undefined;\n let role: string | undefined;\n const tags: string[] = [];\n const cleanArgs: string[] = [];\n\n for (let i = 0; i < args.length; i++) {\n if (args[i] === '--ph-debug') {\n debugLog = path.join(os.homedir(), '.ph_debug.log');\n process.stderr.write(`ph: debug log → ${debugLog}\\n`);\n } else if (args[i] === '--ph-tag' && i + 1 < args.length) {\n tags.push(args[i + 1]);\n i++;\n } else if (args[i].startsWith('--ph-tag=')) {\n tags.push(args[i].slice('--ph-tag='.length));\n } else if (args[i] === '--ph-role' && i + 1 < args.length) {\n role = args[i + 1];\n i++;\n } else if (args[i].startsWith('--ph-role=')) {\n role = args[i].slice('--ph-role='.length);\n } else {\n cleanArgs.push(args[i]);\n }\n }\n\n let realBin: string;\n try {\n realBin = resolveRealBinary(tool);\n } catch (e: unknown) {\n process.stderr.write(`ph: cannot find \"${tool}\": ${(e as Error).message}\\n`);\n process.exit(1);\n }\n\n const interactive = cleanArgs.length === 0 && isTerminal();\n\n const db = new PhDB(dbPath);\n\n if (interactive) {\n const workdir = process.cwd();\n const { rootDir, projectName } = detectProject(workdir);\n const language = detectLanguage(rootDir);\n const gitContext = captureGitContext(workdir);\n\n const onPrompt = (prompt: string, ts: Date): number => {\n const metaObj: Record<string, unknown> = {};\n if (projectName) metaObj.project = projectName;\n if (language) metaObj.language = language;\n if (role) metaObj.role = role;\n if (tags.length > 0) metaObj.tags = tags;\n if (gitContext) metaObj.git_context = gitContext;\n const metadata = Object.keys(metaObj).length > 0 ? JSON.stringify(metaObj) : '{}';\n\n return db.insert({\n timestamp: ts.toISOString(),\n tool,\n prompt,\n response: '',\n args: prompt,\n workdir,\n hostname: os.hostname(),\n exit_code: 0,\n metadata,\n });\n };\n\n const onResponse = (id: number, response: string) => {\n if (!response.trim()) return;\n db.updateResponse(id, response);\n if (cfg.backgroundAnalysis) {\n spawnBackgroundAnalysis(id, dbPath);\n }\n };\n\n const exitCode = await runPTY(realBin!, cleanArgs, onPrompt, onResponse, debugLog);\n db.close();\n process.exit(exitCode);\n } else {\n await runInline(realBin!, cleanArgs, db, tool, tags, role, (id) => {\n if (cfg.backgroundAnalysis) {\n spawnBackgroundAnalysis(id, dbPath);\n }\n });\n // runInline calls process.exit itself\n }\n}\n\n// ─── Entry point ──────────────────────────────────────────────────────────────\n\nasync function main(): Promise<void> {\n const argv = process.argv.slice(2);\n\n // Load config first\n const cfg = loadConfig();\n if (cfg.geminiApiKey) {\n process.env.GEMINI_API_KEY = cfg.geminiApiKey;\n }\n\n const dbPath = process.env.PH_DB ?? cfg.dbPath ?? defaultPath();\n\n if (argv.length === 0) {\n if (isTerminal()) {\n const db = new PhDB(dbPath);\n process.stdout.write('\\x1b[?1049h');\n let pendingRerun: { tool: string; prompt: string } | null = null;\n try {\n const { waitUntilExit } = render(\n React.createElement(BrowseApp, {\n db,\n onRerun: (tool, prompt) => { pendingRerun = { tool, prompt }; }\n })\n );\n await waitUntilExit();\n } finally {\n process.stdout.write('\\x1b[?1049l');\n db.close();\n }\n if (pendingRerun) {\n const { tool, prompt } = pendingRerun;\n const realBin = resolveRealBinary(tool);\n const child = spawnSync(realBin, [prompt], { stdio: 'inherit' });\n process.exit(child.status ?? 0);\n }\n process.exit(0);\n } else {\n process.stdout.write(USAGE);\n process.exit(0);\n }\n }\n\n // Find first non-flag argument, skipping --ph-tag <value> and --ph-debug\n let cmdIdx = -1;\n for (let i = 0; i < argv.length; i++) {\n if (argv[i].startsWith('-')) {\n if (argv[i] === '--ph-tag' || argv[i] === '--ph-role') i++; // skip value\n continue;\n }\n cmdIdx = i;\n break;\n }\n\n if (cmdIdx === -1) {\n process.stdout.write(USAGE);\n process.exit(0);\n }\n\n const command = argv[cmdIdx];\n const cmdArgs = argv.slice(cmdIdx + 1);\n const preArgs = argv.slice(0, cmdIdx); // pre-tool flags like --ph-tag\n\n switch (command) {\n case 'search': {\n const { flags, positional } = parseFlags(cmdArgs);\n const query = positional.join(' ');\n \n if (flags['i'] || flags['interactive']) {\n const db = new PhDB(dbPath);\n process.stdout.write('\\x1b[?1049h');\n let pendingRerun: { tool: string; prompt: string } | null = null;\n try {\n const { waitUntilExit } = render(\n React.createElement(BrowseApp, {\n db,\n initialTextFilter: query,\n initialFilters: {\n tool: flags['tool'] as string,\n project: flags['project'] as string,\n language: flags['language'] as string,\n role: flags['role'] as string,\n tag: flags['tag'] as string,\n starred: Boolean(flags['starred']),\n minQuality: flags['top'] ? 8 : (flags['min-quality'] ? Number(flags['min-quality']) : undefined),\n minRelevance: flags['min-relevance'] ? Number(flags['min-relevance']) : undefined,\n },\n onRerun: (tool, prompt) => { pendingRerun = { tool, prompt }; }\n })\n );\n await waitUntilExit();\n } finally {\n process.stdout.write('\\x1b[?1049l');\n db.close();\n }\n if (pendingRerun) {\n const { tool, prompt } = pendingRerun;\n const realBin = resolveRealBinary(tool);\n const child = spawnSync(realBin, [prompt], { stdio: 'inherit' });\n process.exit(child.status ?? 0);\n }\n break;\n }\n\n const db = new PhDB(dbPath);\n await cmdSearch(db, cfg, cmdArgs);\n db.close();\n break;\n }\n case 'last': {\n const db = new PhDB(dbPath);\n await cmdLast(db, cmdArgs);\n db.close();\n break;\n }\n case 'sessions': {\n const db = new PhDB(dbPath);\n await cmdSessions(db, cmdArgs);\n db.close();\n break;\n }\n case 'stats': {\n const db = new PhDB(dbPath);\n await cmdStats(db);\n db.close();\n break;\n }\n case 'cluster': {\n const db = new PhDB(dbPath);\n await cmdCluster(db, cmdArgs);\n db.close();\n break;\n }\n case 'analyze-reusability': {\n const db = new PhDB(dbPath);\n await cmdAnalyzeReusability(db, cmdArgs);\n db.close();\n break;\n }\n case 'cleanup-reusability': {\n const db = new PhDB(dbPath);\n await cmdCleanupReusability(db, cfg, cmdArgs);\n db.close();\n break;\n }\n case 'star': {\n const db = new PhDB(dbPath);\n await cmdStar(db, cmdArgs);\n db.close();\n break;\n }\n case 'export': {\n const db = new PhDB(dbPath);\n await cmdExport(db, cmdArgs);\n db.close();\n break;\n }\n case 'import': {\n const db = new PhDB(dbPath);\n await cmdImport(db, cfg, cmdArgs);\n db.close();\n break;\n }\n case 'analyze': {\n const db = new PhDB(dbPath);\n await cmdAnalyze(db, cfg, cmdArgs);\n db.close();\n break;\n }\n case 'log': {\n await cmdLog(dbPath, cfg, cmdArgs);\n break;\n }\n case 'embed-all': {\n const db = new PhDB(dbPath);\n await cmdEmbedAll(db, cfg);\n db.close();\n break;\n }\n case 'cleanup': {\n const db = new PhDB(dbPath);\n await cmdCleanup(db, cfg, cmdArgs);\n db.close();\n break;\n }\n case 'config':\n cmdConfig(cmdArgs);\n break;\n\n case '_bg-analyze': {\n await cmdBackgroundAnalyze(dbPath, cmdArgs);\n break;\n }\n\n case 'browse': {\n const db = new PhDB(dbPath);\n process.stdout.write('\\x1b[?1049h');\n let pendingRerun: { tool: string; prompt: string } | null = null;\n try {\n const { waitUntilExit } = render(\n React.createElement(BrowseApp, {\n db,\n onRerun: (tool, prompt) => { pendingRerun = { tool, prompt }; }\n })\n );\n await waitUntilExit();\n } finally {\n process.stdout.write('\\x1b[?1049l');\n db.close();\n }\n if (pendingRerun) {\n const { tool, prompt } = pendingRerun;\n const realBin = resolveRealBinary(tool);\n const child = spawnSync(realBin, [prompt], { stdio: 'inherit' });\n process.exit(child.status ?? 0);\n }\n break;\n }\n\n case 'ollama-models': {\n const ollamaUrl = cfg.ollamaUrl ?? 'http://localhost:11434';\n try {\n const res = await fetch(`${ollamaUrl}/api/tags`);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = await res.json() as { models?: Array<{ name: string }> };\n const models = (data.models ?? []).map(m => m.name).filter(Boolean);\n if (models.length === 0) {\n console.log('No models found.');\n } else {\n console.log(`Available Ollama models at ${ollamaUrl}:`);\n for (const m of models) console.log(` ${m}`);\n }\n } catch (err: unknown) {\n process.stderr.write(`ph: cannot reach Ollama at ${ollamaUrl}: ${(err as Error).message}\\n`);\n process.exit(1);\n }\n break;\n }\n\n case 'help':\n case '--help':\n case '-h':\n process.stdout.write(USAGE);\n break;\n\n default:\n // Transparent wrap mode: merge pre-tool flags with post-tool args\n await cmdWrap(dbPath, command, [...preArgs, ...cmdArgs], cfg);\n break;\n }\n}\n\nmain().catch((e: unknown) => {\n process.stderr.write(`ph: ${(e as Error).message}\\n`);\n process.exit(1);\n});\n","import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\n\nexport interface PhConfig {\n geminiApiKey?: string;\n dbPath?: string;\n analyzeProvider?: 'ollama' | 'gemini'; // default: 'ollama'\n ollamaUrl?: string; // default: 'http://localhost:11434'\n ollamaModel?: string; // default: 'llama3.1:latest'\n filterMinLength?: number; // default: 15\n filterMinRelevance?: number; // default: 3 (0 = disable)\n backgroundAnalysis?: boolean; // default: false\n ollamaEmbedModel?: string; // default: nomic-embed-text-v2-moe\n}\n\nconst CONFIG_PATH = path.join(os.homedir(), '.ph_config.json');\n\nexport function load(): PhConfig {\n try {\n if (fs.existsSync(CONFIG_PATH)) {\n return JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8')) as PhConfig;\n }\n } catch (_) {\n // ignore parse errors, return empty config\n }\n return {};\n}\n\nexport function save(cfg: PhConfig): void {\n fs.writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2), { mode: 0o600 });\n}\n","import Database from 'better-sqlite3';\nimport path from 'path';\nimport os from 'os';\nimport { createHash } from 'crypto';\nimport type { PromptEntry, SearchOptions } from '../types.js';\n\nexport function defaultPath(): string {\n return path.join(os.homedir(), '.prompt_history.db');\n}\n\nexport class PhDB {\n private db: Database.Database;\n\n constructor(dbPath: string) {\n this.db = new Database(dbPath);\n this.db.pragma('journal_mode = WAL');\n this.migrate();\n }\n\n private migrate(): void {\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS prompts (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n timestamp TEXT NOT NULL,\n tool TEXT NOT NULL,\n prompt TEXT NOT NULL,\n args TEXT NOT NULL DEFAULT '',\n workdir TEXT NOT NULL DEFAULT '',\n hostname TEXT NOT NULL DEFAULT '',\n exit_code INTEGER NOT NULL DEFAULT 0,\n metadata TEXT NOT NULL DEFAULT '{}'\n );\n\n CREATE VIRTUAL TABLE IF NOT EXISTS prompts_fts USING fts5(\n prompt,\n tool UNINDEXED,\n content='prompts',\n content_rowid='id'\n );\n\n CREATE TRIGGER IF NOT EXISTS prompts_ai AFTER INSERT ON prompts BEGIN\n INSERT INTO prompts_fts(rowid, prompt, tool) VALUES (new.id, new.prompt, new.tool);\n END;\n\n CREATE TRIGGER IF NOT EXISTS prompts_ad AFTER DELETE ON prompts BEGIN\n INSERT INTO prompts_fts(prompts_fts, rowid, prompt, tool)\n VALUES('delete', old.id, old.prompt, old.tool);\n END;\n\n CREATE INDEX IF NOT EXISTS idx_prompts_tool ON prompts(tool);\n CREATE INDEX IF NOT EXISTS idx_prompts_timestamp ON prompts(timestamp);\n\n CREATE TABLE IF NOT EXISTS embeddings (\n prompt_id INTEGER PRIMARY KEY,\n vector BLOB NOT NULL,\n FOREIGN KEY(prompt_id) REFERENCES prompts(id) ON DELETE CASCADE\n );\n `);\n\n // Migration: metadata column (for legacy Go-created DBs)\n try {\n this.db.exec(\"ALTER TABLE prompts ADD COLUMN metadata TEXT NOT NULL DEFAULT '{}'\");\n } catch { /* already exists */ }\n\n // Migration: response column\n try {\n this.db.exec(\"ALTER TABLE prompts ADD COLUMN response TEXT NOT NULL DEFAULT ''\");\n } catch { /* already exists */ }\n\n // Migration: rebuild FTS5 to include response if not already indexed\n const ftsRow = this.db\n .prepare(\"SELECT sql FROM sqlite_master WHERE type='table' AND name='prompts_fts'\")\n .get() as { sql: string } | undefined;\n\n if (!ftsRow?.sql?.includes('response')) {\n this.db.exec(`\n DROP TABLE IF EXISTS prompts_fts;\n DROP TRIGGER IF EXISTS prompts_ai;\n DROP TRIGGER IF EXISTS prompts_ad;\n\n CREATE VIRTUAL TABLE prompts_fts USING fts5(\n prompt,\n response,\n tool UNINDEXED,\n content='prompts',\n content_rowid='id'\n );\n\n CREATE TRIGGER prompts_ai AFTER INSERT ON prompts BEGIN\n INSERT INTO prompts_fts(rowid, prompt, response, tool)\n VALUES (new.id, new.prompt, new.response, new.tool);\n END;\n\n CREATE TRIGGER prompts_ad AFTER DELETE ON prompts BEGIN\n INSERT INTO prompts_fts(prompts_fts, rowid, prompt, response, tool)\n VALUES('delete', old.id, old.prompt, old.response, old.tool);\n END;\n\n INSERT INTO prompts_fts(prompts_fts) VALUES('rebuild');\n `);\n }\n }\n\n insert(entry: Omit<PromptEntry, 'id'>): number {\n const meta = entry.metadata || '{}';\n const response = entry.response ?? '';\n const info = this.db\n .prepare(\n `INSERT INTO prompts (timestamp, tool, prompt, response, args, workdir, hostname, exit_code, metadata)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`\n )\n .run(\n entry.timestamp,\n entry.tool,\n entry.prompt,\n response,\n entry.args,\n entry.workdir,\n entry.hostname,\n entry.exit_code,\n meta\n );\n return info.lastInsertRowid as number;\n }\n\n updateExitCode(id: number, code: number): void {\n this.db.prepare('UPDATE prompts SET exit_code = ? WHERE id = ?').run(code, id);\n }\n\n updateMetadata(id: number, metadata: string): void {\n this.db.prepare('UPDATE prompts SET metadata = ? WHERE id = ?').run(metadata, id);\n }\n\n updateResponse(id: number, response: string): void {\n this.db.prepare('UPDATE prompts SET response = ? WHERE id = ?').run(response, id);\n }\n\n getById(id: number): PromptEntry | undefined {\n return this.db\n .prepare('SELECT * FROM prompts WHERE id = ?')\n .get(id) as PromptEntry | undefined;\n }\n\n search(opts: SearchOptions): PromptEntry[] {\n const ftsArgs: unknown[] = [];\n const ftsFilters: string[] = [];\n const scanArgs: unknown[] = [];\n const scanFilters: string[] = [];\n\n // Build filters for both paths.\n // FTS path uses a JOIN with alias 'p', so columns need the 'p.' prefix.\n // Scan path queries 'prompts' directly, no alias needed.\n if (opts.tool) {\n ftsFilters.push('p.tool = ?');\n ftsArgs.push(opts.tool);\n scanFilters.push('tool = ?');\n scanArgs.push(opts.tool);\n }\n if (opts.project) {\n ftsFilters.push(\"json_extract(p.metadata, '$.project') = ?\");\n ftsArgs.push(opts.project);\n scanFilters.push(\"json_extract(metadata, '$.project') = ?\");\n scanArgs.push(opts.project);\n }\n if (opts.language) {\n ftsFilters.push(\"json_extract(p.metadata, '$.language') = ?\");\n ftsArgs.push(opts.language);\n scanFilters.push(\"json_extract(metadata, '$.language') = ?\");\n scanArgs.push(opts.language);\n }\n if (opts.role) {\n ftsFilters.push(\"json_extract(p.metadata, '$.role') = ?\");\n ftsArgs.push(opts.role);\n scanFilters.push(\"json_extract(metadata, '$.role') = ?\");\n scanArgs.push(opts.role);\n }\n if (opts.tag) {\n // JSON array contains check: look for the tag value in the tags array\n ftsFilters.push(\"json_extract(p.metadata, '$.tags') LIKE ?\");\n ftsArgs.push(`%\"${opts.tag}\"%`);\n scanFilters.push(\"json_extract(metadata, '$.tags') LIKE ?\");\n scanArgs.push(`%\"${opts.tag}\"%`);\n }\n if (opts.starred) {\n ftsFilters.push(\"json_extract(p.metadata, '$.starred') = 1\");\n scanFilters.push(\"json_extract(metadata, '$.starred') = 1\");\n }\n if (opts.minQuality !== undefined) {\n ftsFilters.push(\"json_extract(p.metadata, '$.quality') >= ?\");\n ftsArgs.push(opts.minQuality);\n scanFilters.push(\"json_extract(metadata, '$.quality') >= ?\");\n scanArgs.push(opts.minQuality);\n }\n if (opts.minRelevance !== undefined) {\n ftsFilters.push(\"json_extract(p.metadata, '$.relevance') >= ?\");\n ftsArgs.push(opts.minRelevance);\n scanFilters.push(\"json_extract(metadata, '$.relevance') >= ?\");\n scanArgs.push(opts.minRelevance);\n }\n if (opts.since) {\n ftsFilters.push('p.timestamp >= ?');\n ftsArgs.push(opts.since.toISOString());\n scanFilters.push('timestamp >= ?');\n scanArgs.push(opts.since.toISOString());\n }\n if (opts.until) {\n ftsFilters.push('p.timestamp <= ?');\n ftsArgs.push(opts.until.toISOString());\n scanFilters.push('timestamp <= ?');\n scanArgs.push(opts.until.toISOString());\n }\n\n if (opts.query) {\n const sanitized = `\"${opts.query.replace(/\"/g, '\"\"')}\"`;\n const filterClause = ftsFilters.length > 0 ? ' AND ' + ftsFilters.join(' AND ') : '';\n const sql = `\n SELECT p.*\n FROM prompts_fts f\n JOIN prompts p ON p.id = f.rowid\n WHERE prompts_fts MATCH ?${filterClause}\n ORDER BY p.timestamp DESC\n LIMIT ?\n `;\n return this.db.prepare(sql).all(sanitized, ...ftsArgs, opts.limit) as PromptEntry[];\n } else {\n const filterClause = scanFilters.length > 0 ? ' AND ' + scanFilters.join(' AND ') : '';\n const sql = `\n SELECT * FROM prompts\n WHERE 1=1${filterClause}\n ORDER BY timestamp DESC\n LIMIT ?\n `;\n return this.db.prepare(sql).all(...scanArgs, opts.limit) as PromptEntry[];\n }\n }\n\n saveEmbedding(id: number, vector: Float32Array): void {\n const buf = Buffer.alloc(vector.length * 4);\n for (let i = 0; i < vector.length; i++) {\n buf.writeFloatLE(vector[i], i * 4);\n }\n this.db\n .prepare('INSERT OR REPLACE INTO embeddings (prompt_id, vector) VALUES (?, ?)')\n .run(id, buf);\n }\n\n getAllEmbeddings(): Map<number, Float32Array> {\n const rows = this.db\n .prepare('SELECT prompt_id, vector FROM embeddings')\n .all() as { prompt_id: number; vector: Buffer }[];\n\n const map = new Map<number, Float32Array>();\n for (const row of rows) {\n const vec = new Float32Array(row.vector.length / 4);\n for (let i = 0; i < vec.length; i++) {\n vec[i] = row.vector.readFloatLE(i * 4);\n }\n map.set(row.prompt_id, vec);\n }\n return map;\n }\n\n getPromptsWithoutEmbeddings(): PromptEntry[] {\n return this.db\n .prepare(\n `SELECT p.* FROM prompts p\n LEFT JOIN embeddings e ON e.prompt_id = p.id\n WHERE e.prompt_id IS NULL`\n )\n .all() as PromptEntry[];\n }\n\n getAllPrompts(limit: number = 1000000): PromptEntry[] {\n return this.db\n .prepare('SELECT * FROM prompts ORDER BY timestamp DESC LIMIT ?')\n .all(limit) as PromptEntry[];\n }\n\n getPromptsByRole(role: string): PromptEntry[] {\n return this.db\n .prepare(\"SELECT * FROM prompts WHERE json_extract(metadata, '$.role') = ? ORDER BY timestamp DESC\")\n .all(role) as PromptEntry[];\n }\n\n delete(id: number): void {\n this.db.prepare('DELETE FROM prompts WHERE id = ?').run(id);\n }\n\n deleteById(id: number): void {\n this.delete(id);\n }\n\n deleteByIds(ids: number[]): number {\n if (ids.length === 0) return 0;\n const placeholders = ids.map(() => '?').join(',');\n const info = this.db.prepare(`DELETE FROM prompts WHERE id IN (${placeholders})`).run(...ids);\n return info.changes;\n }\n\n deleteOlderThan(days: number): number {\n const info = this.db\n .prepare(\"DELETE FROM prompts WHERE timestamp < datetime('now', ?)\")\n .run(`-${days} days`);\n return info.changes;\n }\n\n vacuum(): void {\n this.db.exec('VACUUM');\n }\n\n getAllPromptHashes(): Map<string, number> {\n const rows = this.db.prepare('SELECT id, prompt FROM prompts').all() as { id: number; prompt: string }[];\n const map = new Map<string, number>();\n for (const row of rows) {\n const hash = createHash('sha256').update(row.prompt.trim().toLowerCase()).digest('hex');\n map.set(hash, row.id);\n }\n return map;\n }\n\n close(): void {\n this.db.close();\n }\n}\n\nexport function cosineSimilarity(a: Float32Array, b: Float32Array): number {\n if (a.length !== b.length) return 0;\n let dot = 0, normA = 0, normB = 0;\n for (let i = 0; i < a.length; i++) {\n dot += a[i] * b[i];\n normA += a[i] * a[i];\n normB += b[i] * b[i];\n }\n if (normA === 0 || normB === 0) return 0;\n return dot / (Math.sqrt(normA) * Math.sqrt(normB));\n}\n","import { spawn, execFileSync } from 'child_process';\nimport fs from 'fs';\nimport os from 'os';\nimport { PhDB } from '../db/index.js';\nimport { detectProject, detectLanguage } from './project.js';\nimport { captureGitContext } from './git-context.js';\n\nexport function extractPrompt(args: string[]): string {\n for (let i = args.length - 1; i >= 0; i--) {\n if (!args[i].startsWith('-')) return args[i];\n }\n return args.join(' ');\n}\n\nexport function resolveRealBinary(tool: string): string {\n let found: string;\n try {\n found = execFileSync('which', [tool], { encoding: 'utf-8' }).trim();\n } catch {\n throw new Error(`command not found: ${tool}`);\n }\n\n const realFound = fs.realpathSync(found);\n // Detect loop: ph wrapping itself\n const selfPath = fs.realpathSync(process.execPath);\n // process.execPath is node; check if the resolved binary is our own script\n // We compare against argv[1] (the script being run) when in dev mode\n const scriptPath = process.argv[1] ? fs.realpathSync(process.argv[1]) : '';\n if (realFound === selfPath || realFound === scriptPath) {\n throw new Error(\n `resolved to ph itself — would loop. Place ph AFTER the real ${tool} in $PATH`\n );\n }\n return realFound;\n}\n\nexport async function runInline(\n realBin: string,\n args: string[],\n db: PhDB,\n tool: string,\n tags: string[],\n role?: string,\n onInserted?: (id: number) => void\n): Promise<void> {\n const workdir = process.cwd();\n const { rootDir, projectName } = detectProject(workdir);\n const language = detectLanguage(rootDir);\n const gitContext = captureGitContext(workdir);\n\n const metaObj: Record<string, unknown> = {};\n if (projectName) metaObj.project = projectName;\n if (language) metaObj.language = language;\n if (role) metaObj.role = role;\n if (tags.length > 0) metaObj.tags = tags;\n if (gitContext) metaObj.git_context = gitContext;\n const metadata = Object.keys(metaObj).length > 0 ? JSON.stringify(metaObj) : '{}';\n\n const id = db.insert({\n timestamp: new Date().toISOString(),\n tool,\n prompt: extractPrompt(args),\n args: args.join(' '),\n workdir,\n hostname: os.hostname(),\n exit_code: 0,\n metadata,\n });\n\n if (onInserted) onInserted(id);\n\n const child = spawn(realBin, args, { stdio: 'inherit' });\n\n child.on('error', (err) => {\n process.stderr.write(`ph: spawn error: ${err.message}\\n`);\n process.exit(1);\n });\n\n child.on('exit', (code, signal) => {\n const exitCode = code ?? (signal ? 1 : 0);\n if (id > 0) db.updateExitCode(id, exitCode);\n process.exit(exitCode);\n });\n}\n","import fs from 'fs';\nimport path from 'path';\n\nconst PROJECT_MARKERS = [\n '.git',\n 'go.mod',\n 'package.json',\n 'Cargo.toml',\n 'Makefile',\n 'pyproject.toml',\n 'requirements.txt',\n];\n\nconst LANGUAGE_MAP: Record<string, string> = {\n 'go.mod': 'go',\n 'package.json': 'javascript',\n 'Cargo.toml': 'rust',\n 'pyproject.toml': 'python',\n 'requirements.txt': 'python',\n 'Makefile': 'make',\n 'composer.json': 'php',\n 'Gemfile': 'ruby',\n};\n\nexport function detectProject(startDir: string): { rootDir: string; projectName: string } {\n let curr = path.resolve(startDir);\n while (true) {\n for (const marker of PROJECT_MARKERS) {\n if (fs.existsSync(path.join(curr, marker))) {\n return { rootDir: curr, projectName: path.basename(curr) };\n }\n }\n const parent = path.dirname(curr);\n if (parent === curr) break;\n curr = parent;\n }\n return { rootDir: '', projectName: '' };\n}\n\nexport function detectLanguage(rootDir: string): string {\n if (!rootDir) return '';\n for (const [marker, lang] of Object.entries(LANGUAGE_MAP)) {\n if (fs.existsSync(path.join(rootDir, marker))) return lang;\n }\n return '';\n}\n","import { execFileSync } from 'child_process';\n\nexport interface GitContext {\n branch: string;\n files: string[];\n diff: string;\n}\n\nexport function captureGitContext(workdir: string): GitContext | null {\n try {\n const branch = execFileSync('git', ['-C', workdir, 'rev-parse', '--abbrev-ref', 'HEAD'], {\n encoding: 'utf-8',\n stdio: ['ignore', 'pipe', 'pipe'],\n }).trim();\n\n const filesRaw = execFileSync('git', ['-C', workdir, 'diff', '--name-only', 'HEAD'], {\n encoding: 'utf-8',\n stdio: ['ignore', 'pipe', 'pipe'],\n }).trim();\n const files = filesRaw ? filesRaw.split('\\n').filter(Boolean) : [];\n\n let diff = execFileSync('git', ['-C', workdir, 'diff', 'HEAD'], {\n encoding: 'utf-8',\n stdio: ['ignore', 'pipe', 'pipe'],\n });\n\n if (diff.length > 4000) {\n diff = diff.slice(0, 4000) + '\\n... (truncated)';\n }\n\n return { branch, files, diff };\n } catch {\n return null;\n }\n}\n","import pty from '@lydell/node-pty';\nimport fs from 'fs';\nimport os from 'os';\n\nexport type PromptCallback = (prompt: string, timestamp: Date) => number; // returns prompt ID\nexport type ResponseCallback = (id: number, response: string) => void;\n\nfunction cleanLine(bytes: number[]): string {\n const s = Buffer.from(bytes).toString('utf-8');\n return s.trim();\n}\n\n/**\n * Strips ANSI escape codes and PTY noise from a string.\n */\nfunction stripAnsi(text: string): string {\n // eslint-disable-next-line no-control-regex\n return text.replace(/[\\u001b\\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '');\n}\n\n// ESC sequence state machine states\ntype EscState = 'NORMAL' | 'ESC' | 'CSI' | 'OSC';\n\nexport async function runPTY(\n binary: string,\n args: string[],\n onPrompt: PromptCallback,\n onResponse: ResponseCallback,\n debugLog?: string\n): Promise<number> {\n let dbgStream: fs.WriteStream | null = null;\n if (debugLog) {\n dbgStream = fs.createWriteStream(debugLog, { flags: 'a' });\n dbgStream.write(`\\n=== session start: ${binary} ${args.join(' ')} @ ${new Date().toISOString()} ===\\n`);\n }\n\n const log = (msg: string) => {\n if (dbgStream) dbgStream.write(`[${new Date().toISOString()}] ${msg}\\n`);\n };\n\n const cols = process.stdout.columns || 80;\n const rows = process.stdout.rows || 24;\n\n const ptyProcess = pty.spawn(binary, args, {\n name: 'xterm-256color',\n cols,\n rows,\n cwd: process.cwd(),\n env: process.env as Record<string, string>,\n });\n\n let currentPromptId: number | null = null;\n let responseBuffer = '';\n\n // Forward PTY output to stdout and capture for response\n ptyProcess.onData((data: string) => {\n process.stdout.write(data);\n if (currentPromptId !== null) {\n responseBuffer += data;\n }\n });\n\n // Resize on SIGWINCH\n const onResize = () => {\n ptyProcess.resize(process.stdout.columns || 80, process.stdout.rows || 24);\n };\n process.stdout.on('resize', onResize);\n\n // Set stdin to raw mode for byte-level interception\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(true);\n }\n process.stdin.resume();\n\n let lineBuffer: number[] = [];\n let escState: EscState = 'NORMAL';\n\n const onData = (chunk: Buffer) => {\n for (let i = 0; i < chunk.length; i++) {\n const b = chunk[i];\n // log(`byte: 0x${b.toString(16).padStart(2, '0')} state:${escState} line:${JSON.stringify(Buffer.from(lineBuffer).toString())}`);\n\n // Always forward the raw byte to the PTY\n ptyProcess.write(String.fromCharCode(b));\n\n switch (escState) {\n case 'NORMAL':\n if (b === 13 || b === 10) {\n // Enter — capture prompt\n const prompt = cleanLine(lineBuffer);\n log(`ENTER → prompt: ${JSON.stringify(prompt)}`);\n if (prompt) {\n // If we have a previous prompt, finalize its response now\n if (currentPromptId !== null) {\n onResponse(currentPromptId, stripAnsi(responseBuffer));\n }\n currentPromptId = onPrompt(prompt, new Date());\n responseBuffer = '';\n }\n lineBuffer = [];\n } else if (b === 127 || b === 8) {\n // Backspace\n if (lineBuffer.length > 0) lineBuffer.pop();\n } else if (b === 3 || b === 4) {\n // Ctrl-C / Ctrl-D — discard line\n lineBuffer = [];\n } else if (b === 27) {\n // ESC — start escape sequence\n escState = 'ESC';\n } else if (b >= 32) {\n lineBuffer.push(b);\n }\n break;\n\n case 'ESC':\n if (b === 0x5b) {\n // '[' → CSI sequence\n escState = 'CSI';\n } else if (b === 0x5d || b === 0x50 || b === 0x5f || b === 0x5e || b === 0x58) {\n // ']', 'P', '_', '^', 'X' → OSC/DCS/APC/PM/SOS\n escState = 'OSC';\n } else {\n // 2-char ESC sequence, done\n escState = 'NORMAL';\n }\n break;\n\n case 'CSI':\n // CSI ends at first letter (A-Z, a-z) or '~'\n if ((b >= 0x41 && b <= 0x5a) || (b >= 0x61 && b <= 0x7a) || b === 0x7e) {\n escState = 'NORMAL';\n }\n break;\n\n case 'OSC':\n // OSC ends at BEL (0x07)\n if (b === 0x07) {\n escState = 'NORMAL';\n } else if (b === 0x1b) {\n // ESC \\ (ST) — the '\\' will come as the next byte; transition to absorb it\n escState = 'ESC';\n }\n break;\n }\n }\n };\n\n process.stdin.on('data', onData);\n\n return new Promise<number>((resolve) => {\n ptyProcess.onExit(({ exitCode }) => {\n // Finalize last response\n if (currentPromptId !== null) {\n onResponse(currentPromptId, stripAnsi(responseBuffer));\n }\n\n // Cleanup\n process.stdin.removeListener('data', onData);\n process.stdout.removeListener('resize', onResize);\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(false);\n }\n if (dbgStream) {\n dbgStream.write(`=== session end exitCode=${exitCode} ===\\n`);\n dbgStream.end();\n }\n resolve(exitCode);\n });\n });\n}\n\nexport function isTerminal(): boolean {\n return Boolean(process.stdin.isTTY);\n}\n","import type { PromptEntry, PromptMetadata } from '../types.js';\n\nconst C = {\n reset: '\\x1b[0m',\n cyan: '\\x1b[36m',\n yellow: '\\x1b[33m',\n green: '\\x1b[32m',\n gray: '\\x1b[90m',\n red: '\\x1b[31m',\n blue: '\\x1b[34m',\n magenta: '\\x1b[35m',\n};\n\nfunction truncatePrompt(s: string, max = 120): string {\n const flat = s.replace(/\\n/g, ' ');\n if (flat.length > max) return flat.slice(0, max) + '\\u2026';\n return flat;\n}\n\nfunction formatTimestamp(ts: string): string {\n try {\n const d = new Date(ts);\n const pad = (n: number) => String(n).padStart(2, '0');\n return (\n `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ` +\n `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`\n );\n } catch {\n return ts;\n }\n}\n\nexport function printResults(entries: PromptEntry[], showFull: boolean): void {\n if (entries.length === 0) {\n console.log('No results found.');\n return;\n }\n\n console.log(`${C.yellow}${entries.length} result(s)${C.reset}\\n`);\n\n for (const e of entries) {\n printEntry(e, showFull);\n }\n}\n\nexport function printEntry(e: PromptEntry, showFull: boolean): void {\n let meta: PromptMetadata = {};\n try {\n meta = JSON.parse(e.metadata) as PromptMetadata;\n } catch (_) {}\n\n const exitColor = e.exit_code === 0 ? C.green : C.red;\n\n const starStr = meta.starred ? `${C.yellow}★${C.reset} ` : '';\n\n let projectStr = '';\n if (meta.project && meta.language) {\n projectStr = `${C.blue}[${meta.project}:${meta.language}]${C.reset} `;\n } else if (meta.project) {\n projectStr = `${C.blue}[${meta.project}]${C.reset} `;\n } else if (meta.language) {\n projectStr = `${C.blue}[${meta.language}]${C.reset} `;\n }\n\n const roleStr = meta.role ? `${C.magenta}{${meta.role}}${C.reset} ` : '';\n\n let tagsStr = '';\n if (meta.tags && meta.tags.length > 0) {\n tagsStr = `${C.cyan}(${meta.tags.join(',')})${C.reset} `;\n }\n\n // Header line: #5 ★ claude 2026-01-15 10:23:45 [myproject:go] {debug} (api,auth) [exit:0]\n process.stdout.write(\n `${C.cyan}#${String(e.id).padEnd(4)}${C.reset} ` +\n `${starStr}` +\n `${C.yellow}${e.tool.padEnd(8)}${C.reset} ` +\n `${C.gray}${formatTimestamp(e.timestamp)}${C.reset} ` +\n `${projectStr}${roleStr}${tagsStr}` +\n `${exitColor}[exit:${e.exit_code}]${C.reset}\\n`\n );\n\n // Working dir\n if (e.workdir) {\n process.stdout.write(` ${C.gray}${e.workdir}${C.reset}\\n`);\n }\n\n // Prompt text\n let prompt = e.prompt;\n if (!showFull) {\n prompt = truncatePrompt(prompt);\n }\n // Indent multiline prompts\n prompt = prompt.replace(/\\n/g, '\\n ');\n process.stdout.write(` ${prompt}\\n\\n`);\n}\n","import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport { PhDB } from '../db/index.js';\nimport type { LLMProvider } from '../ai/provider.js';\nimport { analyzePrompt, mergeMetadata } from '../analyzer/index.js';\nimport type { FilterPipeline } from '../filter/index.js';\nimport type { ImportResult } from '../types.js';\n\ninterface GeminiMessage {\n id?: string;\n timestamp: string;\n type: string;\n content: string | Array<{ text: string }>;\n}\n\ninterface GeminiSession {\n messages: GeminiMessage[];\n}\n\nfunction getContent(msg: GeminiMessage): string {\n if (typeof msg.content === 'string') return msg.content;\n if (Array.isArray(msg.content)) {\n return msg.content.map((c) => c.text || '').join('');\n }\n return '';\n}\n\nfunction findSessionFiles(tmpDir: string): string[] {\n const files: string[] = [];\n if (!fs.existsSync(tmpDir)) return files;\n\n try {\n const hashes = fs.readdirSync(tmpDir);\n for (const hash of hashes) {\n const chatsDir = path.join(tmpDir, hash, 'chats');\n if (!fs.existsSync(chatsDir)) continue;\n const sessions = fs.readdirSync(chatsDir).filter(\n (f) => f.startsWith('session-') && f.endsWith('.json')\n );\n for (const s of sessions) {\n files.push(path.join(chatsDir, s));\n }\n }\n } catch (_) {}\n return files;\n}\n\nfunction inferWorkDir(sessionPath: string, geminiDir: string): string {\n const tmpDir = path.join(geminiDir, 'tmp');\n const rel = path.relative(tmpDir, sessionPath);\n const parts = rel.split(path.sep);\n if (parts.length > 0) {\n const hash = parts[0];\n const historyDir = path.join(geminiDir, 'history', hash);\n if (fs.existsSync(path.join(historyDir, '.git'))) {\n return historyDir;\n }\n }\n return '';\n}\n\nexport async function importGeminiHistory(\n db: PhDB,\n geminiDir: string,\n dryRun: boolean,\n analyzer?: LLMProvider,\n onProgress?: (evaluated: number, imported: number, total: number, current: string) => void,\n filter?: FilterPipeline\n): Promise<ImportResult> {\n const result: ImportResult = {\n filesScanned: 0,\n promptsFound: 0,\n promptsImported: 0,\n skipped: 0,\n filtered: 0,\n errors: [],\n };\n\n const files = findSessionFiles(path.join(geminiDir, 'tmp'));\n result.filesScanned = files.length;\n\n const hostname = os.hostname();\n\n // First pass: just count the total prompts so we can show a progress bar\n let totalPromptsToEvaluate = 0;\n for (const filePath of files) {\n try {\n const raw = fs.readFileSync(filePath, 'utf-8');\n const parsed = JSON.parse(raw);\n const messages: GeminiMessage[] = Array.isArray(parsed) ? parsed : ((parsed as GeminiSession).messages || []);\n totalPromptsToEvaluate += messages.filter(m => (m.type === 'human' || m.type === 'user') && getContent(m) !== '').length;\n } catch {\n // ignore errors in this dry-run counting phase\n }\n }\n\n let promptsEvaluated = 0;\n\n for (const filePath of files) {\n try {\n const raw = fs.readFileSync(filePath, 'utf-8');\n let messages: GeminiMessage[];\n\n try {\n const parsed = JSON.parse(raw);\n if (Array.isArray(parsed)) {\n messages = parsed as GeminiMessage[];\n } else {\n messages = (parsed as GeminiSession).messages || [];\n }\n } catch {\n result.errors.push(`${filePath}: JSON parse error`);\n continue;\n }\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i];\n if (!((msg.type === 'human' || msg.type === 'user') && getContent(msg) !== '')) continue;\n\n result.promptsFound++;\n promptsEvaluated++;\n const content = getContent(msg);\n onProgress?.(promptsEvaluated, result.promptsImported, totalPromptsToEvaluate, content.slice(0, 60));\n\n if (dryRun) { result.promptsImported++; continue; }\n\n // Stage 1+2: rule-based + dedup filter (no LLM)\n if (filter) {\n const preCheck = filter.checkRules(content);\n if (!preCheck.keep) { result.filtered++; continue; }\n const dupCheck = filter.checkDuplicate(content);\n if (!dupCheck.keep) { result.filtered++; continue; }\n }\n\n let metadata = '{}';\n let analysis;\n\n if (analyzer) {\n try {\n analysis = await analyzePrompt(content, analyzer);\n if (filter && analysis) {\n const relCheck = filter.checkRelevance(analysis);\n if (!relCheck.keep) { result.filtered++; continue; }\n }\n const merged = mergeMetadata({}, analysis, false);\n if (Object.keys(merged).length > 0) metadata = JSON.stringify(merged);\n } catch {\n // analysis failure is non-fatal\n }\n }\n\n // Capture the model response immediately following this user message\n let response = '';\n const nextMsg = messages[i + 1];\n if (nextMsg && (nextMsg.type === 'model' || nextMsg.type === 'assistant')) {\n response = getContent(nextMsg);\n if (response.length > 8000) response = response.slice(0, 8000) + '\\n... (truncated)';\n }\n\n try {\n const id = db.insert({\n timestamp: new Date(msg.timestamp).toISOString(),\n tool: 'gemini',\n prompt: content,\n response,\n args: content,\n workdir: inferWorkDir(filePath, geminiDir),\n hostname,\n exit_code: 0,\n metadata,\n });\n filter?.registerHash(content, id);\n result.promptsImported++;\n } catch (e: unknown) {\n result.errors.push(`insert ${msg.id || '?'}: ${(e as Error).message}`);\n result.skipped++;\n }\n }\n } catch (e: unknown) {\n result.errors.push(`${filePath}: ${(e as Error).message}`);\n }\n }\n\n return result;\n}\n","import type { LLMProvider } from '../ai/provider.js';\nimport type { PhDB } from '../db/index.js';\nimport type { PromptEntry, PromptMetadata } from '../types.js';\n\nexport interface AnalysisResult {\n project?: string;\n language?: string;\n role?: string;\n tags?: string[];\n relevance?: number; // 0-10: how useful/informative this prompt is for future reference\n quality?: number; // 0-10: how well-structured, detailed and clear the prompt is\n}\n\nconst ANALYSIS_PROMPT = (text: string) => `\\\nAnalyze this AI tool prompt and return ONLY a JSON object with these exact fields:\n{\n \"project\": \"<project name if clearly identifiable, else empty string>\",\n \"language\": \"<programming language if identifiable, else empty string>\",\n \"role\": \"<ONE of: debug, refactor, explain, review, architect, test, docs, generate, research — or empty string>\",\n \"tags\": [\"<tag1>\", \"<tag2>\"],\n \"relevance\": <integer 0-10>,\n \"quality\": <integer 0-10>\n}\n\nRules:\n- tags: 1-3 short lowercase words describing what the prompt is about\n- role: pick the single best match, or \"\" if none fits\n- project/language: only fill if clearly inferrable from the prompt text\n- relevance: how informative/useful is this prompt for future reference?\n 0=completely useless (single word, greeting, yes/no), 5=average technical question, 10=highly detailed technical question\n- quality: how well-structured is the prompt?\n 0=messy/vague, 5=clear but simple, 10=professional prompt engineering (context, instructions, examples, constraints)\n- Return ONLY the JSON object — no markdown fences, no explanation, no other text\n\nPrompt to analyze:\n\"\"\"\n${text.slice(0, 1500)}\n\"\"\"`;\n\n/**\n * Parses LLM output to extract AnalysisResult.\n * Handles markdown fences, leading/trailing text, malformed JSON gracefully.\n */\nexport function parseAnalysisResponse(raw: string): AnalysisResult {\n // Strip markdown code fences\n let cleaned = raw.replace(/```(?:json)?\\s*/gi, '').replace(/```/g, '').trim();\n\n // Find the first { ... } block\n const start = cleaned.indexOf('{');\n const end = cleaned.lastIndexOf('}');\n if (start === -1 || end === -1) return {};\n\n cleaned = cleaned.slice(start, end + 1);\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(cleaned) as Record<string, unknown>;\n } catch {\n return {};\n }\n\n const result: AnalysisResult = {};\n\n if (typeof parsed['project'] === 'string' && parsed['project'].trim()) {\n result.project = parsed['project'].trim();\n }\n if (typeof parsed['language'] === 'string' && parsed['language'].trim()) {\n result.language = parsed['language'].trim().toLowerCase();\n }\n if (typeof parsed['role'] === 'string' && parsed['role'].trim()) {\n const validRoles = ['debug', 'refactor', 'explain', 'review', 'architect', 'test', 'docs', 'generate', 'research'];\n const role = parsed['role'].trim().toLowerCase();\n if (validRoles.includes(role)) result.role = role;\n }\n if (Array.isArray(parsed['tags'])) {\n const tags = (parsed['tags'] as unknown[])\n .filter((t): t is string => typeof t === 'string' && t.trim().length > 0)\n .map(t => t.trim().toLowerCase())\n .slice(0, 5);\n if (tags.length > 0) result.tags = tags;\n }\n if (typeof parsed['relevance'] === 'number') {\n result.relevance = Math.max(0, Math.min(10, Math.round(parsed['relevance'])));\n }\n if (typeof parsed['quality'] === 'number') {\n result.quality = Math.max(0, Math.min(10, Math.round(parsed['quality'])));\n }\n\n return result;\n}\n\n/**\n * Analyze a single prompt text using the given LLM provider.\n * Returns empty object on any error (never throws).\n */\nexport async function analyzePrompt(text: string, provider: LLMProvider): Promise<AnalysisResult> {\n try {\n const raw = await provider.generate(ANALYSIS_PROMPT(text));\n return parseAnalysisResponse(raw);\n } catch {\n return {};\n }\n}\n\n/**\n * Merge new analysis result into existing metadata, preserving manually-set fields.\n * Manual fields (starred, project set by user) take precedence only if force=false.\n */\nexport function mergeMetadata(\n existing: PromptMetadata,\n result: AnalysisResult,\n force: boolean\n): PromptMetadata {\n const merged: PromptMetadata = { ...existing };\n if (force || !merged.project) merged.project = result.project || merged.project;\n if (force || !merged.language) merged.language = result.language || merged.language;\n if (force || !merged.role) merged.role = result.role || merged.role;\n if (force || !merged.tags?.length) merged.tags = result.tags ?? merged.tags;\n if (result.relevance !== undefined && (force || merged.relevance === undefined)) {\n merged.relevance = result.relevance;\n }\n if (result.quality !== undefined && (force || merged.quality === undefined)) {\n merged.quality = result.quality;\n }\n // Clean up empty strings set by LLM\n if (!merged.project) delete merged.project;\n if (!merged.language) delete merged.language;\n if (!merged.role) delete merged.role;\n if (!merged.tags?.length) delete merged.tags;\n return merged;\n}\n\nfunction parseMeta(raw: string): PromptMetadata {\n try { return JSON.parse(raw) as PromptMetadata; } catch { return {}; }\n}\n\nfunction hasMetadata(entry: PromptEntry): boolean {\n const meta = parseMeta(entry.metadata);\n return Boolean(meta.role || meta.tags?.length || meta.project || meta.language);\n}\n\nexport interface AnalyzeAllOpts {\n force?: boolean;\n pruneBelow?: number; // delete entries with relevance < this value (0 = disable)\n dryRun?: boolean; // if true, don't actually delete\n onProgress?: (done: number, total: number, entry: PromptEntry, result: AnalysisResult | null, err?: string) => void;\n onPrune?: (entry: PromptEntry, relevance: number) => void;\n}\n\nexport interface AnalyzeAllResult {\n updated: number;\n skipped: number;\n failed: number;\n pruned: number;\n}\n\n/**\n * Analyze all (or untagged) prompts sequentially and persist metadata to DB.\n * force=false → skip entries that already have metadata\n * force=true → reanalyze everything\n */\nexport async function analyzeAll(\n entries: PromptEntry[],\n provider: LLMProvider,\n db: PhDB,\n opts: AnalyzeAllOpts = {}\n): Promise<AnalyzeAllResult> {\n const { force = false, pruneBelow = 0, dryRun = false, onProgress, onPrune } = opts;\n\n const toProcess = force ? entries : entries.filter(e => !hasMetadata(e));\n const stats: AnalyzeAllResult = { updated: 0, skipped: entries.length - toProcess.length, failed: 0, pruned: 0 };\n\n for (let i = 0; i < toProcess.length; i++) {\n const entry = toProcess[i];\n let result: AnalysisResult | null = null;\n let errMsg: string | undefined;\n\n try {\n result = await analyzePrompt(entry.prompt, provider);\n const existing = parseMeta(entry.metadata);\n const merged = mergeMetadata(existing, result, force);\n\n // Prune if relevance is below threshold\n if (pruneBelow > 0 && result.relevance !== undefined && result.relevance < pruneBelow) {\n onPrune?.(entry, result.relevance);\n if (!dryRun) {\n db.deleteById(entry.id);\n }\n stats.pruned++;\n } else {\n db.updateMetadata(entry.id, JSON.stringify(merged));\n stats.updated++;\n }\n } catch (e: unknown) {\n errMsg = (e as Error).message;\n stats.failed++;\n }\n\n onProgress?.(i + 1, toProcess.length, entry, result, errMsg);\n }\n\n return stats;\n}\n","import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport { PhDB } from '../db/index.js';\nimport type { LLMProvider } from '../ai/provider.js';\nimport { analyzePrompt, mergeMetadata } from '../analyzer/index.js';\nimport type { FilterPipeline } from '../filter/index.js';\nimport type { ImportResult } from '../types.js';\n\nconst MAX_RESPONSE_LENGTH = 8000;\nconst TRUNCATION_SUFFIX = '\\n... (truncated)';\n\ninterface TranscriptUserMessage {\n type: 'user';\n content: string;\n timestamp: string;\n}\n\ninterface TranscriptAssistantContentPart {\n type: string;\n text?: string;\n}\n\ninterface TranscriptAssistantMessage {\n type: 'assistant';\n content: TranscriptAssistantContentPart[];\n timestamp: string;\n}\n\ntype TranscriptMessage = TranscriptUserMessage | TranscriptAssistantMessage | { type: string };\n\n/**\n * Convert a Claude project directory slug back to an absolute filesystem path.\n * The slug format is a path with slashes replaced by dashes and a leading dash\n * representing the leading slash. E.g. `-Users-gianluca-foo` → `/Users/gianluca/foo`.\n */\nfunction slugToPath(slug: string): string {\n // The slug starts with a dash representing the root separator.\n // Replace all dashes with slashes, then ensure a leading slash.\n // However, dashes within path segments are also dashes, so we use a heuristic:\n // the slug is produced by replacing '/' with '-', so we replace every '-' with '/'.\n // The leading '-' was the leading '/', so after replacement we get a path starting with '/'.\n return slug.replace(/-/g, '/');\n}\n\n/**\n * Extract text from an assistant message's content parts (skip thinking/tool_use/tool_result).\n */\nfunction extractAssistantText(parts: TranscriptAssistantContentPart[]): string {\n return parts\n .filter((p) => p.type === 'text' && typeof p.text === 'string')\n .map((p) => p.text as string)\n .join('');\n}\n\n/**\n * Truncate a response to MAX_RESPONSE_LENGTH with a truncation suffix if needed.\n */\nfunction truncateResponse(text: string): string {\n if (text.length <= MAX_RESPONSE_LENGTH) return text;\n return text.slice(0, MAX_RESPONSE_LENGTH - TRUNCATION_SUFFIX.length) + TRUNCATION_SUFFIX;\n}\n\n/**\n * Read all lines from a JSONL file and parse them as transcript messages.\n * Ignores unparseable lines silently (caller handles error tracking separately).\n */\nfunction parseTranscriptFile(filePath: string, errors: string[]): TranscriptMessage[] {\n let raw: string;\n try {\n raw = fs.readFileSync(filePath, 'utf8');\n } catch (e: unknown) {\n errors.push(`read ${filePath}: ${(e as Error).message}`);\n return [];\n }\n\n const messages: TranscriptMessage[] = [];\n for (const line of raw.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n messages.push(JSON.parse(trimmed) as TranscriptMessage);\n } catch {\n // skip unparseable lines\n }\n }\n return messages;\n}\n\n/**\n * Walk ~/.claude/projects/ and return all *.jsonl file paths, grouped by project slug.\n */\nfunction findTranscriptFiles(claudeDir: string): { filePath: string; projectSlug: string }[] {\n const projectsDir = path.join(claudeDir, 'projects');\n const result: { filePath: string; projectSlug: string }[] = [];\n\n if (!fs.existsSync(projectsDir)) return result;\n\n let projectEntries: fs.Dirent[];\n try {\n projectEntries = fs.readdirSync(projectsDir, { withFileTypes: true });\n } catch {\n return result;\n }\n\n for (const entry of projectEntries) {\n if (!entry.isDirectory()) continue;\n const projectSlug = entry.name;\n const projectDir = path.join(projectsDir, projectSlug);\n\n let sessionEntries: fs.Dirent[];\n try {\n sessionEntries = fs.readdirSync(projectDir, { withFileTypes: true });\n } catch {\n continue;\n }\n\n for (const sessionEntry of sessionEntries) {\n if (!sessionEntry.isFile() || !sessionEntry.name.endsWith('.jsonl')) continue;\n result.push({\n filePath: path.join(projectDir, sessionEntry.name),\n projectSlug,\n });\n }\n }\n\n return result;\n}\n\nexport async function importClaudeHistory(\n db: PhDB,\n claudeDir: string,\n dryRun: boolean,\n analyzer?: LLMProvider,\n onProgress?: (evaluated: number, imported: number, total: number, current: string) => void,\n filter?: FilterPipeline\n): Promise<ImportResult> {\n const result: ImportResult = {\n filesScanned: 0,\n promptsFound: 0,\n promptsImported: 0,\n skipped: 0,\n filtered: 0,\n errors: [],\n };\n\n const transcriptFiles = findTranscriptFiles(claudeDir);\n result.filesScanned = transcriptFiles.length;\n\n if (transcriptFiles.length === 0) return result;\n\n const hostname = os.hostname();\n\n // Collect all prompt+response pairs across all files for progress tracking\n interface PendingEntry {\n prompt: string;\n response: string;\n timestamp: string;\n workdir: string;\n sessionId: string;\n }\n\n const pendingEntries: PendingEntry[] = [];\n\n for (const { filePath, projectSlug } of transcriptFiles) {\n const messages = parseTranscriptFile(filePath, result.errors);\n const workdir = slugToPath(projectSlug);\n const sessionId = path.basename(filePath, '.jsonl');\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i];\n if (msg.type !== 'user') continue;\n\n const userMsg = msg as TranscriptUserMessage;\n const prompt = typeof userMsg.content === 'string' ? userMsg.content.trim() : '';\n if (!prompt) continue;\n\n // Look ahead for the assistant response\n let response = '';\n if (i + 1 < messages.length && messages[i + 1].type === 'assistant') {\n const assistantMsg = messages[i + 1] as TranscriptAssistantMessage;\n const rawText = extractAssistantText(assistantMsg.content ?? []);\n response = truncateResponse(rawText);\n }\n\n pendingEntries.push({\n prompt,\n response,\n timestamp: userMsg.timestamp,\n workdir,\n sessionId,\n });\n }\n }\n\n const totalPromptsToEvaluate = pendingEntries.length;\n let promptsEvaluated = 0;\n\n for (const entry of pendingEntries) {\n promptsEvaluated++;\n result.promptsFound++;\n\n onProgress?.(promptsEvaluated, result.promptsImported, totalPromptsToEvaluate, entry.prompt.slice(0, 60));\n\n if (dryRun) {\n result.promptsImported++;\n continue;\n }\n\n // Stage 1+2: rule-based + dedup filter (no LLM)\n if (filter) {\n const preCheck = filter.checkRules(entry.prompt);\n if (!preCheck.keep) { result.filtered++; continue; }\n const dupCheck = filter.checkDuplicate(entry.prompt);\n if (!dupCheck.keep) { result.filtered++; continue; }\n }\n\n try {\n let metadata = '{}';\n\n if (analyzer) {\n try {\n const analysis = await analyzePrompt(entry.prompt, analyzer);\n // Stage 3: relevance filter (LLM score)\n if (filter && analysis) {\n const relCheck = filter.checkRelevance(analysis);\n if (!relCheck.keep) { result.filtered++; continue; }\n }\n const merged = mergeMetadata({}, analysis, false);\n if (Object.keys(merged).length > 0) metadata = JSON.stringify(merged);\n } catch {\n // analysis failure is non-fatal\n }\n }\n\n const id = db.insert({\n timestamp: entry.timestamp,\n tool: 'claude',\n prompt: entry.prompt,\n response: entry.response,\n args: entry.prompt,\n workdir: entry.workdir,\n hostname,\n exit_code: 0,\n metadata,\n });\n filter?.registerHash(entry.prompt, id);\n result.promptsImported++;\n } catch (e: unknown) {\n result.errors.push(\n `insert session ${entry.sessionId}: ${(e as Error).message}`\n );\n result.skipped++;\n }\n }\n\n return result;\n}\n","interface OllamaEmbedResponse {\n embeddings: number[][];\n}\n\nexport async function getEmbeddings(\n texts: string[],\n ollamaUrl: string,\n model: string,\n batchSize = 20\n): Promise<Float32Array[]> {\n const results: Float32Array[] = [];\n\n for (let i = 0; i < texts.length; i += batchSize) {\n const batch = texts.slice(i, i + batchSize);\n\n const res = await fetch(`${ollamaUrl}/api/embed`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ model, input: batch }),\n });\n\n if (!res.ok) {\n const err = await res.text();\n throw new Error(`Ollama embed error ${res.status}: ${err}`);\n }\n\n const data = (await res.json()) as OllamaEmbedResponse;\n for (const vec of data.embeddings) {\n results.push(new Float32Array(vec));\n }\n }\n\n return results;\n}\n","import type { LLMProvider } from './provider.js';\n\ninterface OllamaResponse {\n response: string;\n done: boolean;\n}\n\nexport class OllamaProvider implements LLMProvider {\n readonly name = 'ollama';\n\n constructor(\n private readonly url: string,\n private readonly model: string\n ) {}\n\n async generate(prompt: string): Promise<string> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), 60_000);\n\n let res: Response;\n try {\n res = await fetch(`${this.url}/api/generate`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ model: this.model, prompt, stream: false }),\n signal: controller.signal,\n });\n } catch (err: unknown) {\n clearTimeout(timer);\n const msg = (err as Error).message ?? String(err);\n if (msg.includes('abort') || msg.includes('timeout')) {\n throw new Error(`Ollama request timed out (60s). Is Ollama running at ${this.url}?`);\n }\n throw new Error(`Ollama unreachable at ${this.url}: ${msg}`);\n } finally {\n clearTimeout(timer);\n }\n\n if (!res.ok) {\n const body = await res.text().catch(() => '');\n throw new Error(`Ollama error ${res.status}: ${body}`);\n }\n\n const data = (await res.json()) as OllamaResponse;\n return data.response ?? '';\n }\n}\n","import type { LLMProvider } from './provider.js';\n\nconst GENERATE_API =\n 'https://generativelanguage.googleapis.com/v1beta/models';\n\ninterface GenerateResponse {\n candidates: Array<{\n content: {\n parts: Array<{ text: string }>;\n };\n }>;\n}\n\nexport async function generateContent(\n prompt: string,\n model: string,\n apiKey: string\n): Promise<string> {\n const res = await fetch(`${GENERATE_API}/${model}:generateContent?key=${apiKey}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n contents: [{ parts: [{ text: prompt }] }],\n }),\n });\n\n if (!res.ok) {\n const err = await res.text();\n throw new Error(`Gemini API error ${res.status}: ${err}`);\n }\n\n const data = (await res.json()) as GenerateResponse;\n return data.candidates[0]?.content?.parts[0]?.text ?? '';\n}\n\nexport class GeminiProvider implements LLMProvider {\n readonly name = 'gemini';\n\n constructor(\n private readonly model: string,\n private readonly apiKey: string\n ) {}\n\n generate(prompt: string): Promise<string> {\n return generateContent(prompt, this.model, this.apiKey);\n }\n}\n","import type { PhConfig } from '../config/index.js';\nimport { OllamaProvider } from './ollama.js';\nimport { GeminiProvider } from './gemini.js';\n\nexport interface LLMProvider {\n readonly name: string;\n generate(prompt: string): Promise<string>;\n}\n\n/**\n * Returns the configured LLM provider, or null if none can be constructed.\n * Priority: explicit config → 'ollama' as default.\n */\nexport function getProvider(cfg: PhConfig): LLMProvider | null {\n const provider = cfg.analyzeProvider ?? 'ollama';\n\n if (provider === 'gemini') {\n const apiKey = process.env.GEMINI_API_KEY ?? cfg.geminiApiKey;\n if (!apiKey) return null;\n return new GeminiProvider('gemini-2.5-flash', apiKey);\n }\n\n // ollama (default)\n return new OllamaProvider(\n cfg.ollamaUrl ?? 'http://localhost:11434',\n cfg.ollamaModel ?? 'llama3.1:latest'\n );\n}\n","import { cosineSimilarity } from '../db/index.js';\nimport type { PromptEntry, PromptMetadata } from '../types.js';\n\nexport interface ReusabilityScore {\n id: number;\n prompt: string;\n role: string;\n score: number;\n details: {\n role: number;\n length: number;\n uniqueness: number;\n recency: number;\n };\n}\n\nexport interface ReusabilityReport {\n total: number;\n keep: ReusabilityScore[];\n review: ReusabilityScore[];\n remove: ReusabilityScore[];\n byRole: Record<string, { keep: number; review: number; remove: number }>;\n duplicates: {\n exact: number;\n variants: number;\n };\n}\n\nexport interface RemovalCandidate {\n id: number;\n score: number;\n reason: string;\n role: string;\n promptSize: number;\n responseSize: number;\n hasEmbedding: boolean;\n}\n\nexport class ReusabilityAnalyzer {\n private threshold: number;\n\n constructor(threshold: number = 0.7) {\n this.threshold = threshold;\n }\n\n analyze(entries: PromptEntry[], embeddings: Map<number, Float32Array>): ReusabilityReport {\n const scores: ReusabilityScore[] = entries.map(entry => {\n const meta = this.parseMeta(entry.metadata);\n const embedding = embeddings.get(entry.id);\n\n // Max similarity to any OTHER prompt\n let maxSim = 0;\n if (embedding) {\n for (const [otherId, otherVec] of embeddings.entries()) {\n if (otherId === entry.id) continue;\n const sim = cosineSimilarity(embedding, otherVec);\n if (sim > maxSim) maxSim = sim;\n }\n }\n\n const roleScore = this.calculateRoleScore(meta.role);\n const lengthScore = this.calculateLengthScore(entry.prompt.length);\n const uniquenessScore = 1 - maxSim;\n const recencyScore = this.calculateRecencyScore(entry.timestamp);\n\n const finalScore = (\n roleScore * 0.4 +\n lengthScore * 0.2 +\n uniquenessScore * 0.25 +\n recencyScore * 0.15\n ) * 10;\n\n return {\n id: entry.id,\n prompt: entry.prompt,\n role: meta.role || 'other',\n score: finalScore,\n details: {\n role: roleScore,\n length: lengthScore,\n uniqueness: uniquenessScore,\n recency: recencyScore\n }\n };\n });\n\n const report: ReusabilityReport = {\n total: entries.length,\n keep: [],\n review: [],\n remove: [],\n byRole: {},\n duplicates: { exact: 0, variants: 0 }\n };\n\n const keepThreshold = this.threshold * 10;\n const removeThreshold = Math.max(0, this.threshold - 0.3) * 10;\n\n // Semantic clusters\n for (const s of scores) {\n const uniqueness = s.details.uniqueness;\n const sim = 1 - uniqueness;\n if (sim > 0.95) report.duplicates.exact++;\n else if (sim > 0.85) report.duplicates.variants++;\n\n if (s.score >= keepThreshold) report.keep.push(s);\n else if (s.score >= removeThreshold) report.review.push(s);\n else report.remove.push(s);\n\n if (!report.byRole[s.role]) {\n report.byRole[s.role] = { keep: 0, review: 0, remove: 0 };\n }\n if (s.score >= keepThreshold) report.byRole[s.role].keep++;\n else if (s.score >= removeThreshold) report.byRole[s.role].review++;\n else report.byRole[s.role].remove++;\n }\n\n // Sort keep/remove for top 10\n report.keep.sort((a, b) => b.score - a.score);\n report.remove.sort((a, b) => a.score - b.score);\n\n return report;\n }\n\n getRemovalCandidates(entries: PromptEntry[], embeddings: Map<number, Float32Array>, threshold: number = 0.7): RemovalCandidate[] {\n const removeThreshold = Math.max(0, threshold - 0.3) * 10;\n const candidates: RemovalCandidate[] = [];\n\n // Temporary analyzer with specific threshold\n const tempAnalyzer = new ReusabilityAnalyzer(threshold);\n const report = tempAnalyzer.analyze(entries, embeddings);\n\n for (const s of report.remove) {\n const entry = entries.find(e => e.id === s.id);\n if (!entry) continue;\n\n const meta = this.parseMeta(entry.metadata);\n\n // Don't delete starred prompts\n if (meta.starred) continue;\n\n const hasEmbedding = embeddings.has(entry.id);\n\n candidates.push({\n id: s.id,\n score: s.score,\n reason: `score ${s.score.toFixed(1)} < ${removeThreshold.toFixed(1)}`,\n role: s.role,\n promptSize: entry.prompt.length,\n responseSize: (entry.response || '').length,\n hasEmbedding\n });\n }\n\n return candidates;\n }\n\n private parseMeta(raw: string): PromptMetadata {\n try {\n return JSON.parse(raw) as PromptMetadata;\n } catch {\n return {};\n }\n }\n\n private calculateRoleScore(role?: string): number {\n const scores: Record<string, number> = {\n review: 0.9,\n refactor: 0.9,\n architect: 0.9,\n debug: 0.5,\n explain: 0.5,\n generate: 0.2\n };\n return scores[role || ''] || 0.1;\n }\n\n private calculateLengthScore(length: number): number {\n if (length > 300 && length < 2000) {\n return Math.min(1, Math.max(0, length / 1000));\n }\n return 0.3;\n }\n\n private calculateRecencyScore(timestamp: string): number {\n const date = new Date(timestamp);\n const now = new Date();\n const diffTime = Math.abs(now.getTime() - date.getTime());\n const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));\n return Math.max(0, 1 - diffDays / 365);\n }\n\n toCSV(report: ReusabilityReport): string {\n const all = [...report.keep, ...report.review, ...report.remove];\n let csv = 'id,score,role,length,uniqueness,recency,prompt\\n';\n for (const s of all) {\n const cleanPrompt = s.prompt.replace(/\"/g, '\"\"').replace(/\\n/g, ' ');\n csv += `${s.id},${s.score.toFixed(2)},${s.role},${s.prompt.length},${s.details.uniqueness.toFixed(4)},${s.details.recency.toFixed(4)},\"${cleanPrompt.slice(0, 100)}\"\\n`;\n }\n return csv;\n }\n}\n","import { spawn } from 'child_process';\n\n/**\n * Spawns a background analysis process for a prompt ID.\n * This should be called after a prompt is inserted into the DB.\n */\nexport function spawnBackgroundAnalysis(id: number, dbPath: string): void {\n try {\n const scriptPath = process.argv[1];\n if (!scriptPath) return;\n\n // Use the same node binary as the parent\n const nodePath = process.execPath;\n\n // Command: node <scriptPath> _bg-analyze <id> --db <dbPath>\n const child = spawn(nodePath, [scriptPath, '_bg-analyze', String(id), '--db', dbPath], {\n detached: true,\n stdio: 'ignore',\n });\n\n // Let the parent process exit without waiting for the child\n child.unref();\n } catch (_err: unknown) {\n // Silently ignore spawn errors\n }\n}\n","import { createHash } from 'crypto';\nimport type { AnalysisResult } from '../analyzer/index.js';\n\nexport type FilterReason =\n | 'too_short'\n | 'pattern_match'\n | 'non_printable'\n | 'exact_duplicate'\n | 'low_relevance';\n\nexport interface FilterResult {\n keep: boolean;\n reason?: FilterReason;\n details?: string;\n}\n\nexport interface FilterOptions {\n minLength?: number; // default: 15\n minRelevance?: number; // default: 3 (0 = disable LLM scoring check)\n existingHashes?: Map<string, number>; // for exact dedup\n}\n\n// Patterns that indicate trivial/useless prompts (conversational filler)\nconst TRIVIAL_PATTERN =\n /^(yes|no|ok|okay|sure|thanks|thank you|continue|go on|next|exit|quit|stop|help|y|n|👍|👎|che dici\\??|dimmi|vai|go|do it|tell me|vadi|procedi|aspetta|wait|[.!?,;:]+|\\s*)$/i;\n\n// Fragments that look like orphan code or syntax noise\nconst ORPHAN_CODE_PATTERN = /^([{}()[\\]<>|&!=\\-+*/%^~#@\\\\:;.,\\s]+|\\.\\.\\.|console\\.log.*|print.*)$/i;\n\n// Non-printable / PTY noise: only control chars and escape sequences\n// eslint-disable-next-line no-control-regex\nconst NON_PRINTABLE_PATTERN = /^[\\x00-\\x1f\\x7f\\x1b[\\]()#;\\d;A-Za-z]*$/;\n\nexport class FilterPipeline {\n private readonly minLength: number;\n private readonly minRelevance: number;\n private readonly existingHashes: Map<string, number>;\n\n constructor(opts: FilterOptions = {}) {\n this.minLength = opts.minLength ?? 15;\n this.minRelevance = opts.minRelevance ?? 3;\n this.existingHashes = opts.existingHashes ?? new Map();\n }\n\n static hashPrompt(text: string): string {\n return createHash('sha256').update(text.trim().toLowerCase()).digest('hex');\n }\n\n checkRules(text: string): FilterResult {\n const trimmed = text.trim();\n\n // Too short\n if (trimmed.length < this.minLength) {\n return { keep: false, reason: 'too_short', details: `length ${trimmed.length} < ${this.minLength}` };\n }\n\n // Non-printable / PTY noise\n if (NON_PRINTABLE_PATTERN.test(trimmed)) {\n return { keep: false, reason: 'non_printable', details: 'only control characters' };\n }\n\n // Trivial pattern match (filler)\n if (TRIVIAL_PATTERN.test(trimmed)) {\n return { keep: false, reason: 'pattern_match', details: `matches trivial pattern: \"${trimmed}\"` };\n }\n\n // Orphan code or syntax noise\n if (ORPHAN_CODE_PATTERN.test(trimmed)) {\n return { keep: false, reason: 'pattern_match', details: `matches orphan code pattern: \"${trimmed}\"` };\n }\n\n return { keep: true };\n }\n\n checkDuplicate(text: string): FilterResult {\n const hash = FilterPipeline.hashPrompt(text);\n if (this.existingHashes.has(hash)) {\n const existingId = this.existingHashes.get(hash);\n return { keep: false, reason: 'exact_duplicate', details: `duplicate of #${existingId}` };\n }\n return { keep: true };\n }\n\n /**\n * Register a prompt hash after a successful insert to catch duplicates within the same batch.\n */\n registerHash(text: string, id: number): void {\n const hash = FilterPipeline.hashPrompt(text);\n this.existingHashes.set(hash, id);\n }\n\n checkRelevance(result: AnalysisResult): FilterResult {\n if (this.minRelevance <= 0) return { keep: true };\n if (result.relevance === undefined) return { keep: true };\n if (result.relevance < this.minRelevance) {\n return {\n keep: false,\n reason: 'low_relevance',\n details: `relevance ${result.relevance} < ${this.minRelevance}`,\n };\n }\n return { keep: true };\n }\n\n /**\n * Full pipeline check: rules → dedup → (relevance if provided).\n * Short-circuits on first failure.\n */\n check(text: string, analysisResult?: AnalysisResult): FilterResult {\n const rulesResult = this.checkRules(text);\n if (!rulesResult.keep) return rulesResult;\n\n const dupResult = this.checkDuplicate(text);\n if (!dupResult.keep) return dupResult;\n\n if (analysisResult !== undefined) {\n const relResult = this.checkRelevance(analysisResult);\n if (!relResult.keep) return relResult;\n }\n\n return { keep: true };\n }\n}\n","import React, { useState, useCallback, useEffect, useMemo } from 'react';\nimport { Box, Text, useInput, useApp } from 'ink';\nimport { spawn } from 'child_process';\nimport type { PromptEntry, PromptMetadata } from '../types.js';\nimport type { PhDB } from '../db/index.js';\nimport { Header, type ActiveFilters } from './Header.js';\nimport { Footer } from './Footer.js';\nimport { THEMES, type Theme } from './themes.js';\nimport { SearchBar } from './SearchBar.js';\nimport { ListEntry } from './ListEntry.js';\nimport { PreviewPane } from './PreviewPane.js';\nimport { extractTopic } from '../utils/extractTopic.js';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nconst FILTER_CATEGORIES = ['project', 'language', 'role', 'tool', 'tag', 'starred', 'quality', 'relevance'] as const;\ntype FilterCategory = (typeof FILTER_CATEGORIES)[number];\n\nconst CATEGORY_LABEL: Record<FilterCategory, string> = {\n project: 'Project',\n language: 'Language',\n role: 'Role',\n tool: 'Tool',\n tag: 'Tag',\n starred: 'Starred',\n quality: 'Quality',\n relevance: 'Relevance',\n};\n\n// Role → color mapping\nconst ROLE_COLOR: Record<string, string> = {\n debug: 'red',\n refactor: 'yellow',\n explain: 'blue',\n review: 'magenta',\n architect: 'green',\n test: 'cyan',\n docs: 'white',\n generate: 'green',\n research: 'blue',\n};\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction copyToClipboard(text: string) {\n try {\n const platform = process.platform;\n let cmd = '';\n let args: string[] = [];\n if (platform === 'darwin') { cmd = 'pbcopy'; }\n else if (platform === 'win32') { cmd = 'clip'; }\n else { cmd = 'xclip'; args = ['-selection', 'clipboard']; }\n \n const proc = spawn(cmd, args);\n proc.stdin.write(text);\n proc.stdin.end();\n } catch {\n // ignore\n }\n}\n\nfunction wrapTextLines(text: string, width: number): string[] {\n const result: string[] = [];\n for (const line of text.split('\\n')) {\n let current = line;\n if (current.length === 0) {\n result.push('');\n continue;\n }\n while (current.length > width) {\n result.push(current.slice(0, width));\n current = current.slice(width);\n }\n if (current.length > 0) result.push(current);\n }\n return result;\n}\n\nfunction useStdoutDimensions() {\n const [dimensions, setDimensions] = useState({\n columns: process.stdout.columns || 120,\n rows: process.stdout.rows || 24,\n });\n\n useEffect(() => {\n const handler = () => {\n setDimensions({\n columns: process.stdout.columns || 120,\n rows: process.stdout.rows || 24,\n });\n };\n process.stdout.on('resize', handler);\n return () => { process.stdout.off('resize', handler); };\n }, []);\n\n return dimensions;\n}\n\nfunction formatTimestamp(ts: string): string {\n try {\n const d = new Date(ts);\n const p = (n: number) => String(n).padStart(2, '0');\n return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}`;\n } catch {\n return ts.slice(0, 16);\n }\n}\n\nfunction parseMeta(raw: string): PromptMetadata {\n try { return JSON.parse(raw) as PromptMetadata; } catch { return {}; }\n}\n\nfunction getDistinctValues(entries: PromptEntry[], category: FilterCategory): string[] {\n const set = new Set<string>();\n for (const e of entries) {\n if (category === 'tool') { set.add(e.tool); continue; }\n const meta = parseMeta(e.metadata);\n if (category === 'project' && meta.project) set.add(meta.project);\n if (category === 'language' && meta.language) set.add(meta.language);\n if (category === 'role' && meta.role) set.add(meta.role);\n if (category === 'tag') meta.tags?.forEach(t => set.add(t));\n }\n return [...set].sort();\n}\n\nfunction applyFilters(\n entries: PromptEntry[],\n active: ActiveFilters,\n textFilter: string\n): PromptEntry[] {\n let result = entries;\n\n const hasActiveFilter = Object.values(active).some(v => v !== undefined && v !== false);\n if (hasActiveFilter) {\n result = result.filter(e => {\n const meta = parseMeta(e.metadata);\n if (active.tool && e.tool !== active.tool) return false;\n if (active.project && meta.project !== active.project) return false;\n if (active.language && meta.language !== active.language) return false;\n if (active.role && meta.role !== active.role) return false;\n if (active.tag && !meta.tags?.includes(active.tag)) return false;\n if (active.starred && !meta.starred) return false;\n if (active.minQuality !== undefined && (meta.quality ?? 0) < active.minQuality) return false;\n if (active.minRelevance !== undefined && (meta.relevance ?? 0) < active.minRelevance) return false;\n return true;\n });\n }\n\n if (textFilter) {\n const lq = textFilter.toLowerCase();\n result = result.filter(e => {\n const meta = parseMeta(e.metadata);\n return (\n e.prompt.toLowerCase().includes(lq) ||\n e.tool.toLowerCase().includes(lq) ||\n (meta.project?.toLowerCase().includes(lq) ?? false) ||\n (meta.role?.toLowerCase().includes(lq) ?? false) ||\n (meta.tags?.some(t => t.toLowerCase().includes(lq)) ?? false)\n );\n });\n }\n\n return result;\n}\n\n// ─── DetailView ───────────────────────────────────────────────────────────────\n\ninterface DetailProps {\n entry: PromptEntry;\n onClose: () => void;\n onEdit: () => void;\n termWidth: number;\n termHeight: number;\n theme: Theme;\n}\n\nconst DetailView: React.FC<DetailProps> = ({ entry, onClose, onEdit, termWidth, termHeight, theme }) => {\n const meta = parseMeta(entry.metadata);\n const [activeTab, setActiveTab] = useState<'prompt' | 'response'>(entry.response ? 'response' : 'prompt');\n const [scrollOffset, setScrollOffset] = useState(0);\n const [copied, setCopied] = useState(false);\n\n useEffect(() => {\n setScrollOffset(0);\n }, [activeTab]);\n\n const contentWidth = Math.max(10, termWidth - 4);\n const text = activeTab === 'prompt' ? entry.prompt : (entry.response || '(no response captured)');\n const lines = useMemo(() => wrapTextLines(text, contentWidth), [text, contentWidth]);\n\n // overhead = meta1(1) + meta2(1) + blank(1) + tabbar(1) + scroll-top(1) + scroll-bot(1) = 6\n // But we also have Header(1), SearchBar(1), Footer(1) = 3\n // Plus paddingTop(1) = 1.\n // Total overhead = 10.\n const contentHeight = Math.max(1, termHeight - 10);\n const maxScroll = Math.max(0, lines.length - contentHeight);\n\n useInput((char, key) => {\n if (key.escape || key.return) onClose();\n else if (char === 'e') onEdit();\n else if (key.tab || char === '1' || char === '2') {\n if (char === '1') setActiveTab('prompt');\n else if (char === '2') setActiveTab('response');\n else setActiveTab(t => t === 'prompt' ? 'response' : 'prompt');\n }\n else if (char === 'y') {\n copyToClipboard(text);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }\n else if (key.upArrow) setScrollOffset(s => Math.max(0, s - 1));\n else if (key.downArrow) setScrollOffset(s => Math.min(maxScroll, s + 1));\n else if (key.pageUp) setScrollOffset(s => Math.max(0, s - contentHeight));\n else if (key.pageDown) setScrollOffset(s => Math.min(maxScroll, s + contentHeight));\n });\n\n const visibleLines = lines.slice(scrollOffset, scrollOffset + contentHeight);\n const remaining = lines.length - (scrollOffset + contentHeight);\n\n return (\n <Box flexDirection=\"column\" paddingX={2} paddingTop={1} flexGrow={1}>\n {/* meta1 */}\n <Box>\n <Text color={theme.primary} bold>#{entry.id}</Text>\n <Text dimColor> · {entry.tool} · {formatTimestamp(entry.timestamp)} </Text>\n {meta.starred && <Text color={theme.warning}>★</Text>}\n </Box>\n\n {/* meta2 */}\n <Box>\n {meta.project && <Text color={theme.accent}>proj:{meta.project} </Text>}\n {meta.language && <Text color={theme.dim}>lang:{meta.language} </Text>}\n {meta.role && (\n <Text color={ROLE_COLOR[meta.role] ?? theme.primary}>role:{meta.role} </Text>\n )}\n {meta.quality !== undefined && <Text color={theme.success}>Q:{meta.quality} </Text>}\n {meta.relevance !== undefined && <Text color={theme.warning}>R:{meta.relevance} </Text>}\n <Text color={entry.exit_code === 0 ? theme.dim : theme.error}>exit:{entry.exit_code}</Text>\n </Box>\n\n <Box height={1} />\n\n {/* tab bar */}\n <Box marginBottom={0} justifyContent=\"space-between\">\n <Box>\n <Text color={theme.primary} bold underline>\n {activeTab === 'prompt' ? '●' : '○'} PROMPT\n </Text>\n <Text> </Text>\n <Text color={theme.primary} bold underline>\n {activeTab === 'response' ? '●' : '○'} RESPONSE\n </Text>\n </Box>\n <Box>\n {copied && <Text color={theme.success}>Copied! </Text>}\n <Text dimColor>[y:copy e:edit ESC:back]</Text>\n </Box>\n </Box>\n\n {/* scroll top */}\n <Box height={1}>\n {scrollOffset > 0 && <Text dimColor> ↑ {scrollOffset} above</Text>}\n </Box>\n\n {/* content */}\n <Box flexDirection=\"column\" flexGrow={1}>\n {visibleLines.map((line, i) => (\n <Text key={i}>{line || ' '}</Text>\n ))}\n {Array.from({ length: Math.max(0, contentHeight - visibleLines.length) }).map((_, i) => (\n <Text key={`pad-${i}`}> </Text>\n ))}\n </Box>\n\n {/* scroll bot */}\n <Box height={1}>\n {remaining > 0 && <Text dimColor> ↓ {remaining} more</Text>}\n </Box>\n </Box>\n );\n};\n\n// ─── EditView ─────────────────────────────────────────────────────────────────\n\ninterface EditProps {\n entry: PromptEntry;\n onSave: (meta: PromptMetadata) => void;\n onClose: () => void;\n theme: Theme;\n}\n\nconst EditView: React.FC<EditProps> = ({ entry, onSave, onClose, theme }) => {\n const initMeta = parseMeta(entry.metadata);\n\n const [field, setField] = useState<'title' | 'role' | 'tags'>('title');\n const [titleValue, setTitleValue] = useState(initMeta.title ?? extractTopic(entry.prompt));\n const [roleValue, setRoleValue] = useState(initMeta.role ?? '');\n const [tagsValue, setTagsValue] = useState(initMeta.tags?.join(', ') ?? '');\n\n useInput((char, key) => {\n if (key.escape) { onClose(); return; }\n if (key.return) {\n const newMeta: PromptMetadata = { ...initMeta };\n const trimmedTitle = titleValue.trim();\n newMeta.title = trimmedTitle || undefined;\n const trimmedRole = roleValue.trim();\n newMeta.role = trimmedRole || undefined;\n const parsedTags = tagsValue.split(',').map(t => t.trim()).filter(Boolean);\n newMeta.tags = parsedTags.length > 0 ? parsedTags : undefined;\n onSave(newMeta);\n return;\n }\n if (key.tab) {\n setField(f => {\n if (f === 'title') return 'role';\n if (f === 'role') return 'tags';\n return 'title';\n });\n return;\n }\n const setter =\n field === 'title' ? setTitleValue :\n field === 'role' ? setRoleValue :\n setTagsValue;\n if (key.backspace || key.delete) {\n setter(v => v.slice(0, -1));\n } else if (char && !key.ctrl && !key.meta) {\n setter(v => v + char);\n }\n });\n\n const ROLES = 'debug · refactor · explain · review · architect · test · docs · generate · research';\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Box marginBottom={1}>\n <Text color={theme.primary} bold>Edit Metadata — Prompt #{entry.id}</Text>\n </Box>\n <Box flexDirection=\"column\" borderStyle=\"single\" borderColor={theme.dim} padding={1}>\n <Box marginBottom={1}>\n <Text dimColor>Title: </Text>\n <Text color={field === 'title' ? theme.primary : 'white'} bold={field === 'title'}>\n {titleValue || '(none)'}{field === 'title' ? '█' : ''}\n </Text>\n </Box>\n <Box marginBottom={1}>\n <Text dimColor>Role: </Text>\n <Text color={field === 'role' ? theme.primary : 'white'} bold={field === 'role'}>\n {roleValue || '(none)'}{field === 'role' ? '█' : ''}\n </Text>\n </Box>\n <Box>\n <Text dimColor>Tags: </Text>\n <Text color={field === 'tags' ? theme.primary : 'white'} bold={field === 'tags'}>\n {tagsValue || '(none)'}{field === 'tags' ? '█' : ''}\n </Text>\n </Box>\n </Box>\n <Box marginTop={1}>\n <Text dimColor>Roles: {ROLES}</Text>\n </Box>\n <Box marginTop={1}>\n <Text dimColor>Tab switch field · Enter save · ESC cancel</Text>\n </Box>\n </Box>\n );\n};\n\n// ─── RerunView ────────────────────────────────────────────────────────────────\n\ninterface RerunProps {\n entry: PromptEntry;\n onConfirm: (tool: string, prompt: string) => void;\n onClose: () => void;\n theme: Theme;\n}\n\nconst RerunView: React.FC<RerunProps> = ({ entry, onConfirm, onClose, theme }) => {\n const [field, setField] = useState<'tool' | 'prompt'>('prompt');\n const [toolValue, setToolValue] = useState(entry.tool);\n const [promptValue, setPromptValue] = useState(entry.prompt);\n\n const meta = parseMeta(entry.metadata);\n const git = meta.git_context;\n\n useInput((char, key) => {\n if (key.escape) { onClose(); return; }\n if (key.return) {\n onConfirm(toolValue.trim(), promptValue.trim());\n return;\n }\n if (key.tab) {\n setField(f => f === 'tool' ? 'prompt' : 'tool');\n return;\n }\n\n const setter = field === 'tool' ? setToolValue : setPromptValue;\n if (key.backspace || key.delete) {\n setter(v => v.slice(0, -1));\n } else if (char && !key.ctrl && !key.meta) {\n setter(v => v + char);\n }\n });\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Box marginBottom={1}>\n <Text color={theme.primary} bold>Rerun Prompt #{entry.id}</Text>\n </Box>\n\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text dimColor>Tool: <Text color={theme.warning}>{entry.tool}</Text></Text>\n <Text dimColor>Date: <Text>{formatTimestamp(entry.timestamp)}</Text></Text>\n {meta.project && <Text dimColor>Project: <Text color={theme.accent}>{meta.project}</Text></Text>}\n {git && (\n <Text dimColor>Git: <Text color={theme.warning}>Captured on branch: {git.branch}, {git.files?.length || 0} files modified</Text></Text>\n )}\n </Box>\n\n <Box flexDirection=\"column\" borderStyle=\"single\" borderColor={theme.dim} padding={1}>\n <Box marginBottom={1}>\n <Text dimColor>Tool: </Text>\n <Text color={field === 'tool' ? theme.primary : 'white'} bold={field === 'tool'}>\n {toolValue}{field === 'tool' ? '█' : ''}\n </Text>\n </Box>\n <Box flexDirection=\"column\">\n <Text dimColor>Prompt: </Text>\n <Box borderStyle=\"round\" borderColor={field === 'prompt' ? theme.primary : theme.dim} paddingX={1}>\n <Text color={field === 'prompt' ? theme.primary : 'white'}>\n {promptValue}{field === 'prompt' ? '█' : ''}\n </Text>\n </Box>\n </Box>\n </Box>\n\n <Box marginTop={1}>\n <Text dimColor>Tab switch · Enter run · ESC cancel</Text>\n </Box>\n </Box>\n );\n};\n\n// ─── FilterPanel ──────────────────────────────────────────────────────────────\n\ninterface FilterPanelProps {\n allEntries: PromptEntry[];\n active: ActiveFilters;\n onUpdate: (filters: ActiveFilters) => void;\n onClose: () => void;\n theme: Theme;\n}\n\nconst FilterPanel: React.FC<FilterPanelProps> = ({ allEntries, active, onUpdate, onClose, theme }) => {\n const [catIdx, setCatIdx] = useState(0);\n const [itemIdx, setItemIdx] = useState(0);\n\n const category = FILTER_CATEGORIES[catIdx];\n const isStarred = category === 'starred';\n const isQuality = category === 'quality';\n const isRelevance = category === 'relevance';\n\n const values = useMemo(\n () => {\n if (isStarred) return [];\n if (isQuality || isRelevance) return ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'];\n return getDistinctValues(allEntries, category);\n },\n [allEntries, category, isStarred, isQuality, isRelevance]\n );\n const allValues = isStarred ? [] : ['(all)', ...values];\n\n const currentCatValue = useMemo(() => {\n if (isStarred) return active.starred ? 'yes' : undefined;\n if (isQuality) return active.minQuality?.toString();\n if (isRelevance) return active.minRelevance?.toString();\n return (active[category as keyof Omit<ActiveFilters, 'starred' | 'minQuality' | 'minRelevance'>]);\n }, [active, category, isStarred, isQuality, isRelevance]);\n\n const ITEMS_VISIBLE = 14;\n const pageStart = Math.max(0, Math.min(itemIdx - Math.floor(ITEMS_VISIBLE / 2), allValues.length - ITEMS_VISIBLE));\n const visibleValues = allValues.slice(pageStart, pageStart + ITEMS_VISIBLE);\n\n useInput((char, key) => {\n if (key.escape) { onClose(); return; }\n\n if (key.tab) {\n const next = (catIdx + 1) % FILTER_CATEGORIES.length;\n setCatIdx(next);\n setItemIdx(0);\n return;\n }\n if (key.leftArrow) {\n setCatIdx(i => (i - 1 + FILTER_CATEGORIES.length) % FILTER_CATEGORIES.length);\n setItemIdx(0);\n } else if (key.rightArrow) {\n setCatIdx(i => (i + 1) % FILTER_CATEGORIES.length);\n setItemIdx(0);\n } else if (key.upArrow) {\n setItemIdx(i => Math.max(0, i - 1));\n } else if (key.downArrow) {\n if (isStarred) {\n onUpdate({ ...active, starred: !active.starred || undefined });\n } else {\n setItemIdx(i => Math.min(allValues.length - 1, i + 1));\n }\n } else if (key.return || char === ' ') {\n if (isStarred) {\n onUpdate({ ...active, starred: !active.starred || undefined });\n } else {\n const selected = allValues[itemIdx];\n if (!selected) return;\n if (selected === '(all)') {\n const updated = { ...active };\n if (isQuality) delete updated.minQuality;\n else if (isRelevance) delete updated.minRelevance;\n else delete (updated as Record<string, unknown>)[category];\n onUpdate(updated);\n } else {\n if (isQuality) onUpdate({ ...active, minQuality: Number(selected) });\n else if (isRelevance) onUpdate({ ...active, minRelevance: Number(selected) });\n else onUpdate({ ...active, [category]: selected });\n }\n }\n }\n else if (char === 'c') {\n onUpdate({});\n }\n });\n\n const activeCount = Object.values(active).filter(v => v !== undefined && v !== false).length;\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n {/* Header */}\n <Box marginBottom={1}>\n <Text color={theme.primary} bold>Filter Panel </Text>\n {activeCount > 0\n ? <Text color={theme.warning}>{activeCount} active filter{activeCount > 1 ? 's' : ''} </Text>\n : <Text dimColor>no filters active </Text>\n }\n {activeCount > 0 && <Text dimColor>(c to clear all)</Text>}\n </Box>\n\n {/* Category tabs */}\n <Box marginBottom={1}>\n {FILTER_CATEGORIES.map((cat, i) => {\n let catVal: string | undefined;\n if (cat === 'starred') catVal = active.starred ? '★' : undefined;\n else if (cat === 'quality') catVal = active.minQuality ? `≥${active.minQuality}` : undefined;\n else if (cat === 'relevance') catVal = active.minRelevance ? `≥${active.minRelevance}` : undefined;\n else catVal = active[cat as keyof Omit<ActiveFilters, 'starred' | 'minQuality' | 'minRelevance'>];\n \n const isActive = i === catIdx;\n return (\n <Box key={cat} marginRight={2}>\n <Text color={isActive ? theme.primary : catVal ? theme.warning : theme.dim} bold={isActive}>\n {CATEGORY_LABEL[cat]}{catVal ? `[${catVal}]` : ''}\n </Text>\n </Box>\n );\n })}\n </Box>\n\n {/* Values list */}\n <Box borderStyle=\"single\" borderColor={theme.dim} flexDirection=\"column\" padding={1} minHeight={16}>\n {isStarred ? (\n <Box>\n <Text color={active.starred ? theme.warning : theme.dim} bold={active.starred}>\n {'❯ '}{active.starred ? '★' : '☆'} Only starred prompts{active.starred ? ' ✓' : ''}\n </Text>\n </Box>\n ) : allValues.length === 0 ? (\n <Text dimColor>(no values found)</Text>\n ) : (\n visibleValues.map((val, i) => {\n const absIdx = pageStart + i;\n const isCurrent = val === currentCatValue || (val === '(all)' && !currentCatValue);\n return (\n <Box key={val}>\n <Text\n color={absIdx === itemIdx ? theme.primary : isCurrent ? theme.warning : theme.dim}\n bold={absIdx === itemIdx}\n >\n {absIdx === itemIdx ? '❯ ' : ' '}{val}{isCurrent && val !== '(all)' ? ' ✓' : ''}\n </Text>\n </Box>\n );\n })\n )}\n </Box>\n\n <Box marginTop={1}>\n <Text dimColor>←→/Tab switch category · ↑↓ navigate · Enter/Space select · c clear all · ESC close</Text>\n </Box>\n </Box>\n );\n};\n\n// ─── BrowseApp ────────────────────────────────────────────────────────────────\n\ninterface Props {\n db: PhDB;\n initialTextFilter?: string;\n initialFilters?: ActiveFilters;\n onRerun?: (tool: string, prompt: string) => void;\n}\n\nexport const BrowseApp: React.FC<Props> = ({ db, initialTextFilter, initialFilters, onRerun }) => {\n const { exit } = useApp();\n\n const [allEntries, setAllEntries] = useState<PromptEntry[]>(() => db.search({ limit: 1000 }));\n const [refreshKey, setRefreshKey] = useState(0);\n\n const [textFilter, setTextFilter] = useState(initialTextFilter ?? '');\n const [isTextFiltering, setTextFiltering] = useState(false);\n const [activeFilters, setActiveFilters] = useState<ActiveFilters>(initialFilters ?? {});\n const [showFilterPanel, setFilterPanel] = useState(false);\n\n const [cursor, setCursor] = useState(0);\n const [detail, setDetail] = useState<PromptEntry | null>(null);\n const [editing, setEditing] = useState<PromptEntry | null>(null);\n const [rerunning, setRerunning] = useState<PromptEntry | null>(null);\n const [copiedId, setCopiedId] = useState<number | null>(null);\n\n // New state for split-pane focus\n const [focusPane, setFocusPane] = useState<'list' | 'preview'>('list');\n const [scrollOffset, setScrollOffset] = useState(0);\n\n const currentThemeName = 'dark'; // Could be made stateful later\n const theme = THEMES[currentThemeName] || THEMES.dark;\n\n const { columns: termWidth, rows: termHeight } = useStdoutDimensions();\n \n const SPLIT_THRESHOLD = 100;\n const isWide = termWidth >= SPLIT_THRESHOLD;\n const leftPaneWidth = isWide ? Math.max(32, Math.min(50, Math.floor(termWidth * 0.33))) : termWidth;\n\n // Wide mode: header(1) + searchbar(1) + footer(1) + pane-header(1) = 4 overhead lines.\n // n list entries occupy 3n-1 lines (2 per entry + 1 separator, except last).\n // n = floor((termHeight - 4 + 1) / 3) = floor((termHeight - 3) / 3)\n const PAGE_SIZE = Math.max(1, Math.floor((termHeight - 3) / 3));\n\n // Derived filtered entries — recomputed when filters or refreshKey change\n const entries = useMemo(\n () => applyFilters(allEntries, activeFilters, textFilter),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [allEntries, activeFilters, textFilter, refreshKey]\n );\n\n // Clamp cursor when entries shrink\n useEffect(() => {\n setCursor(c => Math.min(c, Math.max(0, entries.length - 1)));\n }, [entries.length]);\n\n // Scroll vim-style: muovi il viewport solo quando il cursore esce dal range visibile.\n useEffect(() => {\n setScrollOffset(prev => {\n const clamped = Math.max(0, Math.min(prev, Math.max(0, entries.length - PAGE_SIZE)));\n if (cursor < clamped) return cursor;\n if (cursor >= clamped + PAGE_SIZE) return cursor - PAGE_SIZE + 1;\n return clamped;\n });\n }, [cursor, PAGE_SIZE, entries.length]);\n\n const pageStart = scrollOffset;\n const visible = entries.slice(pageStart, pageStart + PAGE_SIZE);\n\n const triggerRefresh = useCallback(() => setRefreshKey(k => k + 1), []);\n\n const toggleStar = useCallback((entry: PromptEntry) => {\n const meta = parseMeta(entry.metadata);\n meta.starred = !meta.starred;\n const newMeta = JSON.stringify(meta);\n db.updateMetadata(entry.id, newMeta);\n entry.metadata = newMeta;\n triggerRefresh();\n }, [db, triggerRefresh]);\n\n const handleDelete = useCallback((entry: PromptEntry) => {\n db.deleteById(entry.id);\n setAllEntries(prev => prev.filter(e => e.id !== entry.id));\n // entries and cursor will update automatically\n }, [db]);\n\n const handleSaveEdit = useCallback((entry: PromptEntry, meta: PromptMetadata) => {\n const newMeta = JSON.stringify(meta);\n db.updateMetadata(entry.id, newMeta);\n entry.metadata = newMeta;\n setEditing(null);\n triggerRefresh();\n }, [db, triggerRefresh]);\n\n const handleFilterUpdate = useCallback((filters: ActiveFilters) => {\n setActiveFilters(filters);\n setCursor(0);\n setScrollOffset(0);\n }, []);\n\n useInput((char, key) => {\n if (detail || editing || showFilterPanel || rerunning) return;\n\n // Search mode\n if (isTextFiltering) {\n if (key.escape) { setTextFiltering(false); setTextFilter(''); }\n else if (key.return) { setTextFiltering(false); }\n else if (key.backspace || key.delete) { setTextFilter(v => v.slice(0, -1)); }\n else if (char && !key.ctrl) { setTextFilter(v => v + char); }\n return;\n }\n\n // Global shortcuts\n if (key.escape) {\n if (isWide && focusPane === 'preview') { setFocusPane('list'); return; }\n exit();\n return;\n }\n else if (char === 'q') { exit(); }\n else if (char === '/') { setTextFiltering(true); }\n else if (char === 's') { if (entries[cursor]) toggleStar(entries[cursor]); }\n else if (char === 'e') { if (entries[cursor]) setEditing(entries[cursor]); }\n else if (char === 'r') { if (entries[cursor]) setRerunning(entries[cursor]); }\n else if (char === 'x') { if (entries[cursor]) handleDelete(entries[cursor]); }\n else if (char === 'f') { setFilterPanel(true); }\n else if (char === 'c') { setActiveFilters({}); setTextFilter(''); setCursor(0); setScrollOffset(0); }\n else if (char === 'y') {\n if (entries[cursor]) {\n copyToClipboard(entries[cursor].prompt);\n setCopiedId(entries[cursor].id);\n setTimeout(() => setCopiedId(null), 2000);\n }\n }\n\n // Tab: in wide mode switch focus\n else if (key.tab && isWide) {\n setFocusPane(p => p === 'list' ? 'preview' : 'list');\n }\n\n // List navigation\n else if (focusPane === 'list' || !isWide) {\n if (key.upArrow) { setCursor(c => Math.max(0, c - 1)); }\n else if (key.downArrow) { setCursor(c => Math.min(entries.length - 1, c + 1)); }\n else if (key.pageUp) { setCursor(c => Math.max(0, c - PAGE_SIZE)); }\n else if (key.pageDown) { setCursor(c => Math.min(entries.length - 1, c + PAGE_SIZE)); }\n else if (key.return) {\n if (isWide) {\n if (entries[cursor]) {\n copyToClipboard(entries[cursor].prompt);\n setCopiedId(entries[cursor].id);\n setTimeout(() => setCopiedId(null), 2000);\n }\n } else {\n if (entries[cursor]) setDetail(entries[cursor]);\n }\n }\n }\n });\n\n // ── Render ────────────────────────────────────────────────────────────────\n\n let mainContent;\n if (showFilterPanel) {\n mainContent = (\n <FilterPanel\n allEntries={allEntries}\n active={activeFilters}\n onUpdate={handleFilterUpdate}\n onClose={() => setFilterPanel(false)}\n theme={theme}\n />\n );\n } else if (rerunning) {\n mainContent = (\n <RerunView\n entry={rerunning}\n onConfirm={(tool, prompt) => {\n onRerun?.(tool, prompt);\n setRerunning(null);\n exit();\n }}\n onClose={() => setRerunning(null)}\n theme={theme}\n />\n );\n } else if (editing) {\n mainContent = (\n <EditView\n entry={editing}\n onSave={meta => handleSaveEdit(editing, meta)}\n onClose={() => setEditing(null)}\n theme={theme}\n />\n );\n } else if (detail && !isWide) {\n mainContent = (\n <DetailView\n entry={detail}\n onClose={() => setDetail(null)}\n onEdit={() => { setEditing(detail); setDetail(null); }}\n termWidth={termWidth}\n termHeight={termHeight}\n theme={theme}\n />\n );\n } else if (isWide) {\n const listFocused = focusPane === 'list';\n const previewFocused = focusPane === 'preview';\n mainContent = (\n <Box flexDirection=\"row\" flexGrow={1}>\n {/* Left Pane: List */}\n <Box flexDirection=\"column\" width={leftPaneWidth}>\n {/* Pane header — focus indicator */}\n <Box paddingX={1}>\n <Text color={listFocused ? theme.primary : theme.dim} bold={listFocused}>\n {listFocused ? '❯ ' : ' '}HISTORY\n </Text>\n {entries.length > 0 && (\n <Text color={theme.dim}> {cursor + 1}/{entries.length}</Text>\n )}\n </Box>\n {entries.length === 0 ? (\n <Box paddingX={1}>\n <Text dimColor>(no results)</Text>\n </Box>\n ) : (\n visible.map((entry, i) => (\n <React.Fragment key={entry.id}>\n <ListEntry\n entry={entry}\n isSelected={pageStart + i === cursor}\n paneWidth={leftPaneWidth}\n theme={theme}\n />\n {i < visible.length - 1 && (\n <Box>\n <Text color={theme.dim}>{'─'.repeat(leftPaneWidth)}</Text>\n </Box>\n )}\n </React.Fragment>\n ))\n )}\n </Box>\n {/* Vertical separator + Preview Pane — border color reflects focus */}\n <Box\n borderLeft\n borderStyle=\"single\"\n borderColor={previewFocused ? theme.primary : theme.dim}\n flexGrow={1}\n flexDirection=\"column\"\n >\n <PreviewPane\n entry={entries[cursor] ?? null}\n paneWidth={termWidth - leftPaneWidth - 1}\n paneHeight={termHeight - 3}\n isFocused={previewFocused}\n theme={theme}\n />\n </Box>\n </Box>\n );\n\n } else {\n // Narrow Mode List\n mainContent = (\n <Box flexDirection=\"column\" paddingX={1} flexGrow={1}>\n {entries.length === 0 ? (\n <Box marginTop={1}>\n <Text color={theme.dim}>(no results)</Text>\n </Box>\n ) : (\n visible.map((entry, i) => (\n <React.Fragment key={entry.id}>\n <ListEntry\n entry={entry}\n isSelected={pageStart + i === cursor}\n paneWidth={termWidth}\n theme={theme}\n />\n {i < visible.length - 1 && (\n <Box>\n <Text color={theme.dim}>{'─'.repeat(termWidth)}</Text>\n </Box>\n )}\n </React.Fragment>\n ))\n )}\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\" height={termHeight}>\n <Header \n entriesCount={entries.length} \n allEntriesCount={allEntries.length}\n activeFilters={activeFilters}\n textFilter={textFilter}\n isTextFiltering={false} // SearchBar handles it\n theme={currentThemeName}\n />\n \n <SearchBar value={textFilter} isActive={isTextFiltering} theme={theme} />\n\n <Box flexGrow={1}>\n {mainContent}\n </Box>\n\n <Footer \n cursor={cursor} \n total={entries.length} \n copiedId={copiedId} \n theme={currentThemeName}\n />\n </Box>\n );\n};\n","import React from 'react';\nimport { Text } from 'ink';\nimport { AppHeader, THEMES } from '@gi4nks/ink';\nimport packageJson from '../../package.json' with { type: 'json' };\n\nconst ROLE_COLOR: Record<string, string> = {\n debug: 'red',\n refactor: 'yellow',\n explain: 'blue',\n review: 'magenta',\n architect: 'green',\n test: 'cyan',\n docs: 'white',\n generate: 'green',\n research: 'blue',\n};\n\nexport interface ActiveFilters {\n project?: string;\n language?: string;\n role?: string;\n tool?: string;\n tag?: string;\n starred?: boolean;\n minQuality?: number;\n minRelevance?: number;\n}\n\ninterface HeaderProps {\n entriesCount: number;\n allEntriesCount: number;\n activeFilters: ActiveFilters;\n textFilter: string;\n isTextFiltering: boolean;\n theme?: string;\n}\n\nconst FilterBadges: React.FC<{ active: ActiveFilters; textFilter: string }> = ({ active, textFilter }) => (\n <>\n {active.project && <Text color=\"blue\"> proj:{active.project}</Text>}\n {active.language && <Text color=\"green\"> lang:{active.language}</Text>}\n {active.role && <Text color={ROLE_COLOR[active.role] ?? 'cyan'}> role:{active.role}</Text>}\n {active.tool && <Text color=\"yellow\"> tool:{active.tool}</Text>}\n {active.tag && <Text color=\"cyan\"> tag:{active.tag}</Text>}\n {active.starred && <Text color=\"yellow\"> ★only</Text>}\n {active.minQuality !== undefined && <Text color=\"green\"> Q≥{active.minQuality}</Text>}\n {active.minRelevance !== undefined && <Text color=\"green\"> R≥{active.minRelevance}</Text>}\n {textFilter && <Text color=\"yellow\"> /{textFilter}</Text>}\n </>\n);\n\nexport const Header: React.FC<HeaderProps> = ({\n entriesCount,\n allEntriesCount,\n activeFilters,\n textFilter,\n isTextFiltering,\n theme: themeName = 'dark',\n}) => {\n const theme = THEMES[themeName] || THEMES.dark;\n const version = packageJson.version;\n const rawCwd = process.cwd();\n const cwd = rawCwd.replace(process.env.HOME || '', '~');\n\n const leftExtra = (\n <Text color=\"white\" dimColor>\n {' '}{entriesCount}{entriesCount < allEntriesCount ? `/${allEntriesCount}` : ''} prompts\n </Text>\n );\n\n const rightContent = (\n <>\n <FilterBadges active={activeFilters} textFilter={textFilter} />\n {isTextFiltering && <Text color={theme.success}> [typing…]</Text>}\n </>\n );\n\n return (\n <AppHeader\n appName=\"ph\"\n version={version}\n theme={theme}\n cwd={cwd}\n leftExtra={leftExtra}\n rightContent={rightContent}\n />\n );\n};\n","{\n \"name\": \"@gi4nks/ph\",\n \"version\": \"1.3.2\",\n \"description\": \"Transparent CLI wrapper that captures and indexes AI prompts\",\n \"type\": \"module\",\n \"license\": \"MIT\",\n \"bin\": {\n \"ph\": \"dist/cli.js\"\n },\n \"files\": [\n \"dist\",\n \"README.md\",\n \"LICENSE\",\n \"docs\",\n \"CHANGELOG.md\",\n \"hooks\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/gi4nks/ph.git\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsx src/cli.ts\",\n \"start\": \"node dist/cli.js\",\n \"test\": \"vitest run\",\n \"lint\": \"eslint src\",\n \"release:patch\": \"standard-version --release-as patch\",\n \"release:minor\": \"standard-version --release-as minor\",\n \"release:major\": \"standard-version --release-as major\"\n },\n \"dependencies\": {\n \"@gi4nks/ink\": \"^1.5.0\",\n \"@lydell/node-pty\": \"^1.2.0-beta.3\",\n \"better-sqlite3\": \"^12.8.0\",\n \"ink\": \"^6.8.0\",\n \"react\": \"^19.2.4\",\n \"zod\": \"^4.3.6\"\n },\n \"devDependencies\": {\n \"@types/better-sqlite3\": \"^7.6.13\",\n \"@types/node\": \"^25.5.0\",\n \"@types/react\": \"^19.2.14\",\n \"@typescript-eslint/eslint-plugin\": \"^8.57.2\",\n \"@typescript-eslint/parser\": \"^8.57.2\",\n \"eslint\": \"^9.39.4\",\n \"eslint-plugin-react\": \"^7.37.5\",\n \"eslint-plugin-react-hooks\": \"^7.0.1\",\n \"standard-version\": \"^9.5.0\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.21.0\",\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^4.1.0\"\n }\n}\n","import React from 'react';\nimport { AppFooter, THEMES } from '@gi4nks/ink';\nimport type { HintItem } from '@gi4nks/ink';\n\nconst HINTS: Array<HintItem | '|'> = [\n { key: '↑↓', description: 'nav' },\n { key: 'Tab', description: 'pane' },\n { key: '1/2', description: 'tab' },\n { key: 'y', description: 'copy' },\n { key: 's', description: '★' },\n { key: 'e', description: 'edit' },\n { key: 'r', description: 'rerun' },\n '|',\n { key: 'x', description: 'del' },\n { key: '/', description: 'search' },\n { key: 'f', description: 'filter' },\n { key: 'q', description: 'quit' },\n];\n\ninterface FooterProps {\n cursor: number;\n total: number;\n copiedId?: number | null;\n theme?: string;\n}\n\nexport const Footer: React.FC<FooterProps> = ({\n cursor,\n total,\n copiedId,\n theme: themeName = 'dark',\n}) => {\n const theme = THEMES[themeName] || THEMES.dark;\n const position = total > 0 ? `${cursor + 1}/${total}` : '0/0';\n\n return (\n <AppFooter\n theme={theme}\n hints={HINTS}\n position={position}\n toast={copiedId ? 'Copied to clipboard' : undefined}\n />\n );\n};\n","// Re-export from shared design system\nexport type { Theme, ThemeName } from '@gi4nks/ink';\nexport { THEMES, THEME_NAMES } from '@gi4nks/ink';\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport type { Theme } from './themes.js';\n\ninterface SearchBarProps {\n value: string;\n isActive: boolean;\n theme: Theme;\n}\n\nexport const SearchBar: React.FC<SearchBarProps> = ({ value, isActive, theme }) => {\n if (isActive) {\n return (\n <Box paddingX={1}>\n <Text color={theme.primary}>⌕ {value}█</Text>\n </Box>\n );\n }\n\n const content = value === '' ? 'type / to search…' : value;\n\n return (\n <Box paddingX={1}>\n <Text dimColor>⌕ {content}</Text>\n </Box>\n );\n};\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport type { PromptEntry, PromptMetadata } from '../types.js';\nimport type { Theme } from './themes.js';\nimport { extractTopic } from '../utils/extractTopic.js';\n\nconst ROLE_COLOR: Record<string, string> = {\n debug: 'red',\n refactor: 'yellow',\n explain: 'blue',\n review: 'magenta',\n architect: 'green',\n test: 'cyan',\n docs: 'white',\n generate: 'green',\n research: 'blue',\n};\n\nfunction toolIndicator(tool: string): { char: string; color: string } {\n if (tool === 'claude') return { char: '●', color: '#f5a623' };\n if (tool === 'gemini') return { char: '●', color: '#4fc3f7' };\n return { char: '○', color: 'gray' };\n}\n\nfunction truncate(str: string, width: number): string {\n if (str.length <= width) return str;\n return str.slice(0, width - 1) + '…';\n}\n\ninterface ListEntryProps {\n entry: PromptEntry;\n isSelected: boolean;\n paneWidth: number;\n theme: Theme;\n}\n\nexport const ListEntry: React.FC<ListEntryProps> = ({ entry, isSelected, paneWidth, theme }) => {\n let meta: PromptMetadata = {};\n try {\n meta = JSON.parse(entry.metadata || '{}') as PromptMetadata;\n } catch {\n /* ignore */\n }\n const indicator = toolIndicator(entry.tool);\n\n const date = new Date(entry.timestamp);\n const hhmm = date.toLocaleTimeString([], {\n hour: '2-digit',\n minute: '2-digit',\n hour12: false,\n });\n\n const role = meta.role ? truncate(meta.role, 6) : '';\n const roleColor = meta.role ? ROLE_COLOR[meta.role] || 'white' : 'white';\n\n const rawTitle = meta.title || extractTopic(entry.prompt);\n // Truncate to paneWidth - 3 to leave room for ' ❯ ' prefix\n const displayPrompt = truncate(rawTitle, paneWidth - 3);\n\n return (\n <Box flexDirection=\"column\">\n {/* Row 1 — info contestuali in dimColor per gerarchia visiva */}\n <Box flexDirection=\"row\" width={paneWidth} overflow=\"hidden\">\n <Text color={indicator.color}>{indicator.char} </Text>\n <Text dimColor>{entry.tool.padEnd(7)}</Text>\n {meta.starred ? <Text color={theme.warning}>★ </Text> : <Text> </Text>}\n <Text dimColor>{hhmm} </Text>\n {role && (\n <Text color={roleColor} dimColor>\n {role}\n </Text>\n )}\n </Box>\n\n {/* Row 2 — titolo con inverse video su selezione (barra a piena larghezza) */}\n <Box flexDirection=\"row\">\n {isSelected ? (\n <Text inverse bold>\n {' ❯ '}\n {displayPrompt.padEnd(paneWidth - 3)}\n </Text>\n ) : (\n <Text>\n {' '}\n {displayPrompt}\n </Text>\n )}\n </Box>\n </Box>\n );\n};\n","/**\n * Estrae un titolo breve e significativo dal testo grezzo di un prompt.\n * Restituisce sempre una stringa non vuota (fallback: primi 72 char troncati).\n */\nexport function extractTopic(prompt: string): string {\n // 1. Trim whitespace e newline iniziali/finali.\n let text = prompt.trim();\n\n // Edge cases: Prompt vuoto o solo whitespace\n if (!text) {\n return '(empty prompt)';\n }\n\n // Edge cases: Testo solo in codice (comincia con ``` o `)\n // Restituisce i primi 72 char del testo originale trimmato.\n if (text.startsWith('```') || text.startsWith('`')) {\n return truncateAtWordBoundary(text, 72);\n }\n\n const originalTrimmed = text;\n\n // 2. MARKDOWN HEADING\n // Se il testo inizia con uno o più # seguiti da spazio, estrai il testo del heading.\n if (text.startsWith('#')) {\n const headingMatch = text.match(/^#+\\s+(.*?)(?:\\s+#+)?(?:\\n|$)/);\n if (headingMatch && headingMatch[1]) {\n text = headingMatch[1].trim();\n }\n }\n\n // 3. PREFISSI DA RIMUOVERE (case-insensitive, inglese + italiano)\n const prefixes = [\n // English\n 'please, ', 'please ', 'can you please ', 'could you please ',\n 'can you ', 'could you ', 'would you ',\n 'i need you to ', 'i need to ', 'i want you to ', 'i want to ',\n 'i\\'d like you to ', 'i\\'d like to ',\n 'help me to ', 'help me ', 'i need ',\n 'claude, ', 'gemini, ', 'chatgpt, ',\n // Italiano\n 'puoi ', 'potresti ', 'potreste ',\n 'per favore ', 'per piacere ',\n 'ho bisogno che ', 'ho bisogno di ',\n 'voglio che ', 'vorrei che ', 'voglio ', 'vorrei ',\n 'aiutami a ', 'aiutami ',\n 'fammi vedere ', 'fammi ',\n 'si prega di ', 'si ',\n ];\n\n let changed = true;\n while (changed) {\n changed = false;\n const lowerText = text.toLowerCase();\n for (const prefix of prefixes) {\n if (lowerText.startsWith(prefix.toLowerCase())) {\n text = text.slice(prefix.length).trim();\n changed = true;\n break; // Ricomincia il loop dopo la rimozione\n }\n }\n }\n\n // 4. PRIMA FRASE SIGNIFICATIVA\n // Prendi il testo fino al primo . ? ! o newline o backtick (codice)\n const sentenceEndMatch = text.match(/[\\n.?!`]/);\n if (sentenceEndMatch && sentenceEndMatch.index !== undefined) {\n text = text.slice(0, sentenceEndMatch.index).trim();\n }\n\n // Fallback se il risultato è vuoto dopo le trasformazioni\n if (!text) {\n return truncateAtWordBoundary(originalTrimmed, 72);\n }\n\n // 5. TRUNCATE a max 72 caratteri\n text = truncateAtWordBoundary(text, 72);\n\n // 6. Capitalizza la prima lettera\n return text.charAt(0).toUpperCase() + text.slice(1);\n}\n\n/**\n * Troncamento intelligente all'ultimo spazio entro il limite.\n */\nfunction truncateAtWordBoundary(str: string, limit: number): string {\n const clean = str.replace(/\\s+/g, ' ').trim();\n if (clean.length <= limit) return clean;\n \n const sub = clean.slice(0, limit);\n const lastSpace = sub.lastIndexOf(' ');\n \n if (lastSpace > 0) {\n return sub.slice(0, lastSpace);\n }\n return sub;\n}\n\n// test: extractTopic(\"## PROMPT 4 — Fase 4: Refactor BrowseApp ##\\n\\nIl file principale è...\") -> \"Fase 4: Refactor BrowseApp\"\n// test: extractTopic(\"please help me fix the TypeScript error in the auth middleware, the types...\") -> \"Fix the TypeScript error in the auth middleware\"\n// test: extractTopic(\"puoi sistemare il bug nel componente ListEntry quando il paneWidth è zero?\") -> \"Sistemare il bug nel componente ListEntry quando il paneWidth è zero\"\n// test: extractTopic(\"I need you to refactor this function to use async/await instead of callbacks\") -> \"Refactor this function to use async/await invece di callbacks\"\n// test: extractTopic(\"claude, l'interfaccia ui di ph non mi piace. per niente.\") -> \"L'interfaccia ui di ph non mi piace\"\n// test: extractTopic(\" \\n\\nPlease review this code:\\n\\n```typescript\\nfunction foo() {...\") -> \"Review this code\"\n","import React, { useState, useEffect, useMemo } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport type { PromptEntry, PromptMetadata } from '../types.js';\nimport type { Theme } from './themes.js';\n\nconst ROLE_COLOR: Record<string, string> = {\n debug: 'red',\n refactor: 'yellow',\n explain: 'blue',\n review: 'magenta',\n architect: 'green',\n test: 'cyan',\n docs: 'white',\n generate: 'green',\n research: 'blue',\n};\n\nfunction wrapTextLines(text: string, width: number): string[] {\n const lines = text.split('\\n');\n const result: string[] = [];\n for (const line of lines) {\n if (line.length === 0) {\n result.push('');\n continue;\n }\n let current = line;\n while (current.length > width) {\n result.push(current.substring(0, width));\n current = current.substring(width);\n }\n if (current.length > 0) result.push(current);\n }\n return result;\n}\n\nfunction formatTimestamp(ts: string): string {\n try {\n const d = new Date(ts);\n const Y = d.getFullYear();\n const M = String(d.getMonth() + 1).padStart(2, '0');\n const D = String(d.getDate()).padStart(2, '0');\n const h = String(d.getHours()).padStart(2, '0');\n const m = String(d.getMinutes()).padStart(2, '0');\n return `${Y}-${M}-${D} ${h}:${m}`;\n } catch {\n return ts.slice(0, 16);\n }\n}\n\nfunction parseMeta(raw: string): PromptMetadata {\n try {\n return JSON.parse(raw) as PromptMetadata;\n } catch {\n return {};\n }\n}\n\ninterface PreviewPaneProps {\n entry: PromptEntry | null;\n paneWidth: number;\n paneHeight: number;\n isFocused: boolean;\n theme: Theme;\n}\n\nexport const PreviewPane: React.FC<PreviewPaneProps> = ({\n entry,\n paneWidth,\n paneHeight,\n isFocused,\n theme,\n}) => {\n const [activeTab, setActiveTab] = useState<'prompt' | 'response'>('prompt');\n const [scrollOffset, setScrollOffset] = useState(0);\n\n useEffect(() => {\n setActiveTab('prompt');\n setScrollOffset(0);\n }, [entry?.id]);\n\n useEffect(() => {\n setScrollOffset(0);\n }, [activeTab]);\n\n const meta = useMemo(() => (entry ? parseMeta(entry.metadata) : {}), [entry]);\n const contentWidth = Math.max(10, paneWidth - 4);\n const contentHeight = Math.max(3, paneHeight - 6);\n\n const allLines = useMemo(() => {\n if (!entry) return [];\n const text = activeTab === 'prompt' ? entry.prompt : (entry.response || '(no response captured)');\n return wrapTextLines(text, contentWidth);\n }, [entry, activeTab, contentWidth]);\n\n const maxScroll = Math.max(0, allLines.length - contentHeight);\n\n useInput((_char, key) => {\n if (!isFocused) return;\n\n if (_char === '1') {\n setActiveTab('prompt');\n return;\n }\n if (_char === '2') {\n setActiveTab('response');\n return;\n }\n\n if (key.upArrow) setScrollOffset((s) => Math.max(0, s - 1));\n if (key.downArrow) setScrollOffset((s) => Math.min(maxScroll, s + 1));\n if (key.pageUp) setScrollOffset((s) => Math.max(0, s - contentHeight));\n if (key.pageDown) setScrollOffset((s) => Math.min(maxScroll, s + contentHeight));\n });\n\n if (!entry) {\n return (\n <Box width={paneWidth} height={paneHeight} paddingX={2} flexDirection=\"column\" justifyContent=\"center\">\n <Text dimColor>(select an entry to preview)</Text>\n </Box>\n );\n }\n\n const visibleLines = allLines.slice(scrollOffset, scrollOffset + contentHeight);\n const paddedLines = [...visibleLines];\n while (paddedLines.length < contentHeight) paddedLines.push('');\n\n const topIndicator = scrollOffset > 0 ? ` ↑ ${scrollOffset} above` : ' ';\n const remaining = allLines.length - scrollOffset - contentHeight;\n const botIndicator = scrollOffset < maxScroll ? ` ↓ ${remaining} more` : ' ';\n\n const isPromptActive = activeTab === 'prompt';\n const isResponseActive = activeTab === 'response';\n\n const tabPromptColor = isPromptActive && isFocused ? theme.primary : theme.dim;\n const tabResponseColor = isResponseActive && isFocused ? theme.primary : theme.dim;\n\n return (\n <Box flexDirection=\"column\" paddingX={2}>\n {/* meta1 */}\n <Box>\n <Text color={theme.primary} bold>#{entry.id}</Text>\n <Text dimColor> · {entry.tool} · {formatTimestamp(entry.timestamp)}</Text>\n {meta.starred && <Text color={theme.warning}> ★</Text>}\n </Box>\n\n {/* meta2 */}\n <Box marginBottom={1}>\n {meta.project && <Text color={theme.accent}>proj:{meta.project} </Text>}\n {meta.language && <Text color={theme.dim}>lang:{meta.language} </Text>}\n {meta.role && (\n <Text color={ROLE_COLOR[meta.role] || theme.primary}>role:{meta.role} </Text>\n )}\n {meta.quality !== undefined && <Text color={theme.success}>Q:{meta.quality} </Text>}\n {meta.relevance !== undefined && <Text color={theme.warning}>R:{meta.relevance} </Text>}\n <Text color={entry.exit_code === 0 ? theme.dim : theme.error}>exit:{entry.exit_code}</Text>\n </Box>\n\n {/* tab bar */}\n <Box>\n <Text\n color={tabPromptColor}\n bold={isPromptActive && isFocused}\n underline={isPromptActive && isFocused}\n >\n {isPromptActive ? '● ' : '○ '}PROMPT\n </Text>\n <Text>{' '}</Text>\n <Text\n color={tabResponseColor}\n bold={isResponseActive && isFocused}\n underline={isResponseActive && isFocused}\n >\n {isResponseActive ? '● ' : '○ '}RESPONSE\n </Text>\n </Box>\n\n {/* scroll-top indicator */}\n <Text dimColor>{topIndicator}</Text>\n\n {/* content lines */}\n {paddedLines.map((line, i) => (\n <Text key={i}>{line || ' '}</Text>\n ))}\n\n {/* scroll-bot indicator */}\n <Text dimColor>{botIndicator}</Text>\n </Box>\n );\n};\n","import type { PromptEntry } from '../types.js';\nimport { cosineSimilarity } from '../db/index.js';\n\nexport interface WorkSession {\n index: number;\n entries: PromptEntry[];\n startTime: Date;\n endTime: Date;\n cohesion: number | null; // null if embeddings not available\n}\n\n/**\n * Group entries (sorted oldest-first) into work sessions.\n * A new session starts when the gap between consecutive entries exceeds gapHours.\n */\nexport function groupIntoSessions(\n entries: PromptEntry[],\n gapHours: number,\n): WorkSession[] {\n if (entries.length === 0) return [];\n\n const sessions: WorkSession[] = [];\n const gapMs = gapHours * 60 * 60 * 1000;\n\n let current: PromptEntry[] = [entries[0]];\n let lastTime = new Date(entries[0].timestamp).getTime();\n\n for (let i = 1; i < entries.length; i++) {\n const entry = entries[i];\n const entryTime = new Date(entry.timestamp).getTime();\n const gap = entryTime - lastTime;\n\n if (gap > gapMs) {\n // Flush current session\n sessions.push(makeSession(sessions.length + 1, current));\n current = [entry];\n } else {\n current.push(entry);\n }\n lastTime = entryTime;\n }\n\n // Flush last session\n if (current.length > 0) {\n sessions.push(makeSession(sessions.length + 1, current));\n }\n\n return sessions;\n}\n\nfunction makeSession(index: number, entries: PromptEntry[]): WorkSession {\n return {\n index,\n entries,\n startTime: new Date(entries[0].timestamp),\n endTime: new Date(entries[entries.length - 1].timestamp),\n cohesion: null,\n };\n}\n\n/**\n * Compute the average cosine similarity between all pairs of entries in the\n * session that have embeddings. Returns null if fewer than 2 entries have embeddings.\n */\nexport function computeSessionCohesion(\n session: WorkSession,\n embeddings: Map<number, Float32Array>,\n): number | null {\n const vecs: Float32Array[] = [];\n for (const entry of session.entries) {\n const vec = embeddings.get(entry.id);\n if (vec) vecs.push(vec);\n }\n\n if (vecs.length < 2) return null;\n\n let sum = 0;\n let count = 0;\n for (let i = 0; i < vecs.length; i++) {\n for (let j = i + 1; j < vecs.length; j++) {\n sum += cosineSimilarity(vecs[i], vecs[j]);\n count++;\n }\n }\n\n return count > 0 ? sum / count : null;\n}\n","import { PhDB } from '../db/index.js';\nimport type { PromptMetadata } from '../types.js';\n\nexport interface Stats {\n total: number;\n byTool: Record<string, number>;\n byProject: Record<string, number>;\n byLanguage: Record<string, number>;\n byRole: Record<string, number>;\n analyzed: number;\n starred: number;\n avgRelevance: number;\n avgQuality: number;\n}\n\nexport function getStats(db: PhDB): Stats {\n const all = db.search({ limit: 1000000 });\n const stats: Stats = {\n total: all.length,\n byTool: {},\n byProject: {},\n byLanguage: {},\n byRole: {},\n analyzed: 0,\n starred: 0,\n avgRelevance: 0,\n avgQuality: 0,\n };\n\n let totalRel = 0;\n let totalQual = 0;\n let analyzedWithScores = 0;\n\n for (const entry of all) {\n stats.byTool[entry.tool] = (stats.byTool[entry.tool] ?? 0) + 1;\n\n let meta: PromptMetadata = {};\n try {\n meta = JSON.parse(entry.metadata) as PromptMetadata;\n } catch {\n // ignore\n }\n\n if (meta.project) {\n stats.byProject[meta.project] = (stats.byProject[meta.project] ?? 0) + 1;\n }\n if (meta.language) {\n stats.byLanguage[meta.language] = (stats.byLanguage[meta.language] ?? 0) + 1;\n }\n if (meta.role) {\n stats.byRole[meta.role] = (stats.byRole[meta.role] ?? 0) + 1;\n stats.analyzed++;\n }\n if (meta.starred) {\n stats.starred++;\n }\n\n if (meta.relevance !== undefined || meta.quality !== undefined) {\n totalRel += meta.relevance ?? 0;\n totalQual += meta.quality ?? 0;\n analyzedWithScores++;\n }\n }\n\n if (analyzedWithScores > 0) {\n stats.avgRelevance = totalRel / analyzedWithScores;\n stats.avgQuality = totalQual / analyzedWithScores;\n }\n\n return stats;\n}\n","import { cosineSimilarity } from '../db/index.js';\n\nexport interface Cluster {\n centroid: Float32Array;\n entryIds: number[];\n label?: string;\n}\n\nexport function kmeans(\n embeddings: Map<number, Float32Array>,\n k: number,\n maxIterations: number = 20\n): Cluster[] {\n const ids = Array.from(embeddings.keys());\n const vecs = Array.from(embeddings.values());\n if (ids.length === 0 || k <= 0) return [];\n if (ids.length <= k) {\n return ids.map((id, i) => ({\n centroid: vecs[i],\n entryIds: [id],\n }));\n }\n\n // Initialize centroids randomly\n let centroids = vecs.slice(0, k).map((v) => new Float32Array(v));\n let clusters: Cluster[] = [];\n\n for (let iter = 0; iter < maxIterations; iter++) {\n clusters = centroids.map((c) => ({ centroid: c, entryIds: [] }));\n\n // Assign each vector to the nearest centroid\n for (let i = 0; i < ids.length; i++) {\n const vec = vecs[i];\n let bestSim = -1;\n let bestIdx = 0;\n\n for (let j = 0; j < k; j++) {\n const sim = cosineSimilarity(vec, centroids[j]);\n if (sim > bestSim) {\n bestSim = sim;\n bestIdx = j;\n }\n }\n clusters[bestIdx].entryIds.push(ids[i]);\n }\n\n // Recompute centroids\n const nextCentroids = clusters.map((cluster) => {\n if (cluster.entryIds.length === 0) return cluster.centroid;\n const first = embeddings.get(cluster.entryIds[0])!;\n const sum = new Float32Array(first.length);\n for (const id of cluster.entryIds) {\n const v = embeddings.get(id)!;\n for (let i = 0; i < v.length; i++) {\n sum[i] += v[i];\n }\n }\n for (let i = 0; i < sum.length; i++) {\n sum[i] /= cluster.entryIds.length;\n }\n return sum;\n });\n\n // Check for convergence\n let changed = false;\n for (let i = 0; i < k; i++) {\n if (cosineSimilarity(centroids[i], nextCentroids[i]) < 0.9999) {\n changed = true;\n break;\n }\n }\n\n centroids = nextCentroids;\n if (!changed) break;\n }\n\n return clusters;\n}\n"],"mappings":"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","names":["os","path","fs","React","path","os","execFileSync","fs","os","fs","path","execFileSync","fs","os","fs","fs","path","os","fs","path","os","fs","path","os","fs","path","os","spawn","createHash","React","useState","useEffect","useMemo","Box","Text","useInput","spawn","React","THEMES","THEMES","React","Text","React","Box","Text","ROLE_COLOR","React","Box","Text","React","Box","Text","ROLE_COLOR","formatTimestamp","parseMeta","ROLE_COLOR","spawn","wrapTextLines","useState","useEffect","formatTimestamp","parseMeta","useMemo","useInput","React","Box","Text","THEMES","os","path","deleted","C","fs","path","os","React","db"]}
|