@gi4nks/ph 1.6.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -1
- package/LICENSE +1 -1
- package/README.md +79 -19
- package/dist/cli.js +3593 -3677
- package/dist/cli.js.map +1 -1
- package/docs/evals/context-retrieval-golden.json +17 -1
- package/docs/ph-architecture-review.html +179 -0
- package/docs/ph-manual.md +129 -73
- package/docs/ph-operational-memory-analysis.html +104 -0
- package/docs/plans/2026-10-10-operational-memory.md +192 -0
- package/docs/specs/SPEC-001-architecture-cli.md +100 -72
- package/docs/specs/SPEC-002-database-layer.md +22 -3
- package/docs/specs/SPEC-003-capture-modes.md +22 -9
- package/docs/specs/SPEC-005-search.md +46 -11
- package/docs/specs/SPEC-006-analysis-pipeline.md +8 -6
- package/docs/specs/SPEC-007-memory-summaries.md +19 -19
- package/docs/specs/SPEC-008-embeddings.md +8 -2
- package/docs/specs/SPEC-009-retention-archive.md +2 -2
- package/docs/specs/SPEC-010-remote-sync.md +77 -103
- package/docs/specs/SPEC-011-mcp-server.md +7 -4
- package/docs/specs/SPEC-012-tui-browser.md +30 -96
- package/docs/specs/SPEC-015-config-env.md +4 -0
- package/docs/specs/SPEC-016-operational-memory.md +48 -0
- package/docs/specs/SPEC-017-architecture-consolidation.md +63 -0
- package/docs/specs/SPEC-018-interaction-inspection-and-recall-integrity.md +164 -0
- package/docs/specs/SPEC-019-network-capture-and-ranking-integrity.md +36 -0
- package/docs/specs/SPEC-INDEX.md +12 -7
- package/docs/specs/SPEC-ISSUES.md +104 -18
- package/hooks/claude/README.md +1 -1
- package/hooks/codex/README.md +1 -1
- package/hooks/codex/ph-hook.sh +2 -1
- package/hooks/gemini/README.md +1 -1
- package/package.json +6 -7
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/config/index.ts","../src/db/index.ts","../src/db/semantic-index.ts","../src/runner/inline.ts","../src/runner/git-context.ts","../src/capture/index.ts","../src/runner/project.ts","../src/utils/extractTopic.ts","../src/pty/wrapper.ts","../src/mcp/server.ts","../src/embedding/index.ts","../src/context/index.ts","../src/server/index.ts","../src/utils/syncHash.ts","../src/commands/remote.ts","../src/ui/BrowseApp.tsx","../src/ui/Header.tsx","../package.json","../src/ui/Footer.tsx","../src/ui/FilterPanel.tsx","../src/ui/filtering.ts","../src/ui/themes.ts","../src/ui/SearchBar.tsx","../src/ui/ListEntry.tsx","../src/ui/PreviewPane.tsx","../src/utils/syntaxHighlight.ts","../src/display/print.ts","../src/commands/_utils.ts","../src/commands/search.ts","../src/commands/last.ts","../src/commands/star.ts","../src/commands/export.ts","../src/commands/import.ts","../src/importer/gemini.ts","../src/analyzer/index.ts","../src/importer/claude.ts","../src/importer/opencode.ts","../src/importer/codex.ts","../src/filter/index.ts","../src/ai/ollama.ts","../src/ai/gemini.ts","../src/ai/provider.ts","../src/commands/analyze.ts","../src/commands/embed-all.ts","../src/background/analyzer.ts","../src/commands/log.ts","../src/commands/config.ts","../src/commands/background-analyze.ts","../src/commands/cleanup.ts","../src/commands/vacuum.ts","../src/commands/context.ts","../src/sessions/index.ts","../src/commands/sessions.ts","../src/stats/index.ts","../src/commands/stats.ts","../src/cluster/index.ts","../src/commands/cluster.ts","../src/commands/analyze-reusability.ts","../src/analyzer/reusability.ts","../src/commands/cleanup-reusability.ts","../src/commands/timeline.ts","../src/commands/memory-migrate.ts","../src/commands/wrap.ts","../src/commands/chat.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { spawnSync } from 'child_process';\nimport React from 'react';\nimport { render } from 'ink';\nimport { load as loadConfig } from './config/index.js';\nimport { PhDB, defaultPath } from './db/index.js';\nimport { resolveRealBinary } from './runner/inline.js';\nimport { isTerminal } from './pty/wrapper.js';\nimport { runMCPServer } from './mcp/server.js';\nimport { runServer } from './server/index.js';\nimport { cmdRemote } from './commands/remote.js';\nimport { BrowseApp } from './ui/BrowseApp.js';\nimport { cmdSearch } from './commands/search.js';\nimport { cmdLast } from './commands/last.js';\nimport { cmdStar } from './commands/star.js';\nimport { cmdExport } from './commands/export.js';\nimport { cmdImport } from './commands/import.js';\nimport { cmdAnalyze } from './commands/analyze.js';\nimport { cmdEmbedAll } from './commands/embed-all.js';\nimport { cmdLog } from './commands/log.js';\nimport { cmdConfig } from './commands/config.js';\nimport { cmdBackgroundAnalyze } from './commands/background-analyze.js';\nimport { cmdCleanup } from './commands/cleanup.js';\nimport { cmdVacuum } from './commands/vacuum.js';\nimport { cmdContext } from './commands/context.js';\nimport { cmdSessions } from './commands/sessions.js';\nimport { cmdStats } from './commands/stats.js';\nimport { cmdCluster } from './commands/cluster.js';\nimport { cmdAnalyzeReusability } from './commands/analyze-reusability.js';\nimport { cmdCleanupReusability } from './commands/cleanup-reusability.js';\nimport { cmdTimeline } from './commands/timeline.js';\nimport { cmdMemoryMigrate } from './commands/memory-migrate.js';\nimport { cmdWrap } from './commands/wrap.js';\nimport { cmdChat } from './commands/chat.js';\nimport { parseFlags } from './commands/_utils.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 context [options] [query] Get RAG context for the current project\n ph chat <tool> <prompt...> Run tool with project context injected\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 <source> [--dry-run] [--analyze] [--filter] [--file <path>]\n Import from Gemini, Claude, OpenCode, or Codex history\n ph analyze [--limit n] [--force] [--prune] [--dry-run] Analyze prompts with LLM\n ph mcp Start MCP server (Stdio)\n ph server [--port 3001] Start HTTP REST server for remote sync\n ph timeline [project] Show full project history with prompts and memories\n ph memory-migrate Merge existing memories into project_summaries\n ph remote push|pull|status Sync prompts with remote ph server\n ph cleanup [--dry-run] [--min-length N] [--min-score N] Remove useless prompts\n ph cleanup --retention [--dry-run] Archive prompts per retention policy\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, opencode, codex, …)\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 --archive Search archived prompts\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\nCONTEXT OPTIONS:\n --project <name> Project to get context for (default: auto-detect)\n --limit <n> Max results (default 5)\n --prompts-only Show only prompt-based context, skip project knowledge\n --memories-only Show only project knowledge, skip prompts\n --verbose Include full prompt text in output\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 --export <n> Export session N as markdown\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 context\n ph context \"how to add a new database table\"\n ph context --memories-only --project ph\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\n\n\n\n// ─── Entry point ──────────────────────────────────────────────────────────────\n\ntype BrowseAppProps = React.ComponentProps<typeof BrowseApp>;\n\n/**\n * Opens the TUI browser inside the alternate screen (SPEC-001).\n * Shared by the default, `browse` and `search -i` paths (SPEC-ISSUES-010).\n * Resolves with the rerun request (or null) after the TUI exits.\n */\nasync function openBrowser(\n db: PhDB,\n opts: Pick<BrowseAppProps, 'initialTextFilter' | 'initialFilters'> = {},\n): Promise<{ tool: string; prompt: string } | null> {\n let pendingRerun: { tool: string; prompt: string } | null = null;\n process.stdout.write('\\x1b[?1049h');\n try {\n const { waitUntilExit } = render(\n React.createElement(BrowseApp, {\n db,\n ...opts,\n onRerun: (tool, prompt) => { pendingRerun = { tool, prompt }; },\n })\n );\n await waitUntilExit();\n } finally {\n process.stdout.write('\\x1b[?1049l');\n }\n return pendingRerun;\n}\n\n/** Executes a TUI rerun request after the browser closed. */\nfunction runRerun(rerun: { tool: string; prompt: string } | null): void {\n if (!rerun) return;\n const realBin = resolveRealBinary(rerun.tool);\n const child = spawnSync(realBin, [rerun.prompt], { stdio: 'inherit' });\n process.exit(child.status ?? 0);\n}\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 const rerun = await openBrowser(db);\n db.close();\n runRerun(rerun);\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 const rerun = await openBrowser(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 });\n db.close();\n runRerun(rerun);\n break;\n }\n\n const db = new PhDB(dbPath);\n await cmdSearch(db, cfg, cmdArgs);\n db.close();\n break;\n }\n case 'context': {\n const db = new PhDB(dbPath);\n await cmdContext(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, cfg, 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 'memory-migrate': {\n const db = new PhDB(dbPath);\n cmdMemoryMigrate(db);\n db.close();\n break;\n }\n case 'mcp': {\n await runMCPServer();\n break;\n }\n case 'server': {\n const { flags } = parseFlags(cmdArgs);\n const port = Number(flags['port']) || 3001;\n const host = (flags['host'] as string) || '0.0.0.0';\n await runServer(port, host);\n break;\n }\n case 'remote': {\n await cmdRemote(dbPath, cmdArgs);\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 'vacuum': {\n const db = new PhDB(dbPath);\n await cmdVacuum(db);\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 const rerun = await openBrowser(db);\n db.close();\n runRerun(rerun);\n break;\n }\n\n case 'chat': {\n await cmdChat(dbPath, cfg, cmdArgs);\n break;\n }\n\n case 'timeline': {\n const db = new PhDB(dbPath);\n await cmdTimeline(db, cfg, cmdArgs);\n db.close();\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 remoteUrl?: string; // HTTP URL of remote ph server (or set PH_REMOTE_URL env)\n remoteApiKey?: string; // optional API key for remote server\n remoteLastPush?: string; // ISO timestamp of last successful push\n remoteLastPull?: string; // ISO timestamp of last successful pull\n retentionDays?: number; // default: 90 — auto-archive prompts older than N days\n retentionMinStarred?: boolean; // default: true — never archive starred prompts\n retentionMinAnalyzed?: boolean; // default: true — never archive analyzed prompts (has summary or role)\n retentionMinRelevance?: number; // default: 3 — prompts below this relevance are archived first\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 * as sqliteVec from 'sqlite-vec';\nimport type { PromptEntry, SearchOptions, MemoryEntry, ProjectSummary } from '../types.js';\nimport { SemanticIndex } from './semantic-index.js';\n\nexport function defaultPath(): string {\n return path.join(os.homedir(), '.prompt_history.db');\n}\n\nexport class PhDB {\n private static readonly PROJECT_SUMMARIES_SCHEMA = `\n CREATE TABLE IF NOT EXISTS project_summaries (\n project TEXT PRIMARY KEY,\n summary TEXT NOT NULL DEFAULT '',\n key_insights TEXT NOT NULL DEFAULT '[]',\n technical_decisions TEXT NOT NULL DEFAULT '[]',\n prompt_count INTEGER NOT NULL DEFAULT 0,\n first_analyzed TEXT NOT NULL,\n last_analyzed TEXT NOT NULL,\n git_context_snapshot TEXT\n );\n `;\n\n private static readonly ARCHIVE_SCHEMA = `\n CREATE TABLE IF NOT EXISTS prompts_archive (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n timestamp TEXT NOT NULL,\n tool TEXT NOT NULL,\n prompt TEXT NOT NULL,\n response TEXT NOT NULL DEFAULT '',\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 archived_at TEXT NOT NULL,\n original_id INTEGER\n );\n CREATE INDEX IF NOT EXISTS idx_archive_timestamp ON prompts_archive(timestamp);\n CREATE INDEX IF NOT EXISTS idx_archive_original_id ON prompts_archive(original_id);\n `;\n\n private db: Database.Database;\n private semanticIndex: SemanticIndex;\n\n /** Absolute path of the SQLite file (used by the HTTP server health endpoint). */\n readonly dbPath: string;\n\n constructor(dbPath: string) {\n this.dbPath = dbPath;\n this.db = new Database(dbPath);\n this.db.pragma('journal_mode = WAL');\n sqliteVec.load(this.db);\n this.semanticIndex = new SemanticIndex(this.db);\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 // New native vector table (sqlite-vec)\n const vecTable = this.db.prepare(\"SELECT sql FROM sqlite_master WHERE type='table' AND name='vec_embeddings'\").get() as { sql: string } | undefined;\n if (vecTable && !vecTable.sql.includes('vec0')) {\n this.db.exec(\"DROP TABLE vec_embeddings\");\n }\n\n this.db.exec(`\n CREATE VIRTUAL TABLE IF NOT EXISTS vec_embeddings USING vec0(\n embedding float[768]\n );\n `);\n\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS memories (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n project TEXT NOT NULL,\n prompt_ids TEXT NOT NULL DEFAULT '[]',\n summary TEXT NOT NULL,\n key_insights TEXT NOT NULL DEFAULT '[]',\n technical_decisions TEXT NOT NULL DEFAULT '[]',\n git_context_snapshot TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n access_count INTEGER DEFAULT 0,\n last_accessed TEXT\n );\n CREATE INDEX IF NOT EXISTS idx_memories_project ON memories(project);\n `);\n\n this.db.exec(PhDB.PROJECT_SUMMARIES_SCHEMA);\n this.db.exec(PhDB.ARCHIVE_SCHEMA);\n\n // Migration: $schema_version in existing metadata\n const rowsWithoutSchema = this.db\n .prepare(\"SELECT id, metadata FROM prompts WHERE json_extract(metadata, '$.\\\\$schema_version') IS NULL\")\n .all() as { id: number; metadata: string }[];\n for (const row of rowsWithoutSchema) {\n try {\n const meta = JSON.parse(row.metadata);\n meta.$schema_version = 1;\n this.db.prepare('UPDATE prompts SET metadata = ? WHERE id = ?').run(JSON.stringify(meta), row.id);\n } catch { /* skip malformed metadata */ }\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: migrate data from old embeddings to new vec_embeddings if needed\n const oldEmbeds = this.db.prepare('SELECT count(*) as count FROM embeddings').get() as { count: number };\n const newEmbeds = this.db.prepare('SELECT count(*) as count FROM vec_embeddings').get() as { count: number };\n\n if (oldEmbeds.count > 0 && newEmbeds.count === 0) {\n const rows = this.db.prepare('SELECT prompt_id, vector FROM embeddings').all() as { prompt_id: number; vector: Buffer }[];\n const insert = this.db.prepare('INSERT INTO vec_embeddings(rowid, embedding) VALUES (?, vec_f32(?))');\n for (const row of rows) {\n try {\n insert.run(BigInt(row.prompt_id), row.vector);\n } catch (e: unknown) {\n console.error(`DEBUG Migration error for prompt #${row.prompt_id}: ${(e as Error).message}`);\n }\n }\n }\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 /** `response` is optional at the call site (runtime defaults to ''). */\n insert(entry: Omit<PromptEntry, 'id' | 'response'> & { response?: string }): 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 this.semanticIndex.save(id, vector);\n }\n\n searchSemantic(queryVector: Float32Array, limit: number, project?: string): PromptEntry[] {\n return this.semanticIndex.search(queryVector, limit, project);\n }\n\n getAllEmbeddings(): Map<number, Float32Array> {\n return this.semanticIndex.loadAll();\n }\n\n getPromptsWithoutEmbeddings(): PromptEntry[] {\n return this.semanticIndex.findMissingPrompts();\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 getPromptsSince(timestamp: string, limit: number = 10000): PromptEntry[] {\n return this.db\n .prepare('SELECT * FROM prompts WHERE timestamp > ? ORDER BY timestamp ASC LIMIT ?')\n .all(timestamp, limit) as PromptEntry[];\n }\n\n getPromptCount(): number {\n return (this.db.prepare('SELECT count(*) as c FROM prompts').get() as { c: number }).c;\n }\n\n getPromptCountSince(timestamp: string): number {\n return (this.db.prepare('SELECT count(*) as c FROM prompts WHERE timestamp > ?').get(timestamp) as { c: number }).c;\n }\n\n getStats(): { total: number; totalMemories: number; byTool: Array<{ tool: string; count: number }> } {\n const total = (this.db.prepare('SELECT count(*) as c FROM prompts').get() as { c: number }).c;\n const totalMemories = (this.db.prepare('SELECT count(*) as c FROM memories').get() as { c: number }).c;\n const byTool = this.db\n .prepare('SELECT tool, count(*) as count FROM prompts GROUP BY tool ORDER BY count DESC')\n .all() as Array<{ tool: string; count: number }>;\n return { total, totalMemories, byTool };\n }\n\n getPromptBySyncHash(hash: string): PromptEntry | undefined {\n return this.db\n .prepare(\"SELECT * FROM prompts WHERE json_extract(metadata, '$.sync_hash') = ?\")\n .get(hash) as PromptEntry | undefined;\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 getProjectMemory(projectName: string, limit: number = 10): PromptEntry[] {\n return this.db\n .prepare(`\n SELECT * FROM prompts \n WHERE json_extract(metadata, '$.project') = ? \n AND json_extract(metadata, '$.summary') IS NOT NULL\n ORDER BY timestamp DESC \n LIMIT ?\n `)\n .all(projectName, limit) as PromptEntry[];\n }\n\n delete(id: number): void {\n this.db.prepare('DELETE FROM prompts WHERE id = ?').run(id);\n // Cascadedelete for embeddings/vec_embeddings should be handled by FOREIGN KEY if supported, \n // but better-sqlite3 needs pragma foreign_keys = ON.\n // However, vec0 doesn't support traditional foreign keys easily.\n this.db.prepare('DELETE FROM vec_embeddings WHERE rowid = ?').run(BigInt(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 \n // For vec_embeddings we need to loop and cast to BigInt\n const delVec = this.db.prepare('DELETE FROM vec_embeddings WHERE rowid = ?');\n for (const id of ids) {\n delVec.run(BigInt(id));\n }\n return info.changes;\n }\n\n deleteOlderThan(days: number): number {\n // We need to find IDs first to clean up vec_embeddings\n const ids = this.db\n .prepare(\"SELECT id FROM prompts WHERE timestamp < datetime('now', ?)\")\n .all(`-${days} days`) as { id: number }[];\n \n if (ids.length > 0) {\n return this.deleteByIds(ids.map(i => i.id));\n }\n return 0;\n }\n\n archivePrompts(ids: number[]): number {\n if (ids.length === 0) return 0;\n const now = new Date().toISOString();\n const select = this.db.prepare(`\n SELECT id, timestamp, tool, prompt, response, args, workdir, hostname, exit_code, metadata\n FROM prompts WHERE id = ?\n `);\n const insert = this.db.prepare(`\n INSERT INTO prompts_archive (timestamp, tool, prompt, response, args, workdir, hostname, exit_code, metadata, archived_at, original_id)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `);\n const del = this.db.prepare('DELETE FROM prompts WHERE id = ?');\n\n const transaction = this.db.transaction((toArchive: number[]) => {\n let count = 0;\n for (const id of toArchive) {\n const row = select.get(id) as Record<string, unknown> | undefined;\n if (!row) continue;\n insert.run(\n row.timestamp, row.tool, row.prompt, row.response, row.args,\n row.workdir, row.hostname, row.exit_code, row.metadata,\n now, id\n );\n del.run(id);\n count++;\n }\n return count;\n });\n\n return transaction(ids);\n }\n\n searchArchive(opts: { since?: string; until?: string; limit?: number }): Array<Record<string, unknown>> {\n let sql = 'SELECT * FROM prompts_archive WHERE 1=1';\n const params: unknown[] = [];\n if (opts.since) { sql += ' AND timestamp >= ?'; params.push(opts.since); }\n if (opts.until) { sql += ' AND timestamp <= ?'; params.push(opts.until); }\n sql += ' ORDER BY timestamp DESC';\n if (opts.limit) { sql += ' LIMIT ?'; params.push(opts.limit); }\n return this.db.prepare(sql).all(...params) as Array<Record<string, unknown>>;\n }\n\n purgeArchive(beforeDate: string): number {\n const result = this.db.prepare('DELETE FROM prompts_archive WHERE archived_at < ?').run(beforeDate);\n return result.changes;\n }\n\n getArchiveStats(): { total: number; oldest: string | null; newest: string | null } {\n const row = this.db.prepare(`\n SELECT COUNT(*) as total, MIN(timestamp) as oldest, MAX(timestamp) as newest\n FROM prompts_archive\n `).get() as { total: number; oldest: string | null; newest: string | null };\n return row;\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 // ─── Memory operations ──────────────────────────────────────────────────────\n\n insertMemory(mem: Omit<MemoryEntry, 'id'>): number {\n const info = this.db\n .prepare(`\n INSERT INTO memories (project, prompt_ids, summary, key_insights, technical_decisions,\n git_context_snapshot, created_at, updated_at, access_count, last_accessed)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n .run(\n mem.project,\n JSON.stringify(mem.prompt_ids),\n mem.summary,\n JSON.stringify(mem.key_insights),\n JSON.stringify(mem.technical_decisions),\n mem.git_context_snapshot ?? null,\n mem.created_at,\n mem.updated_at,\n mem.access_count,\n mem.last_accessed ?? null,\n );\n return info.lastInsertRowid as number;\n }\n\n updateMemory(id: number, updates: Partial<Omit<MemoryEntry, 'id' | 'project' | 'created_at'>>): void {\n const setClauses: string[] = [];\n const params: unknown[] = [];\n\n if (updates.prompt_ids !== undefined) {\n setClauses.push('prompt_ids = ?');\n params.push(JSON.stringify(updates.prompt_ids));\n }\n if (updates.summary !== undefined) {\n setClauses.push('summary = ?');\n params.push(updates.summary);\n }\n if (updates.key_insights !== undefined) {\n setClauses.push('key_insights = ?');\n params.push(JSON.stringify(updates.key_insights));\n }\n if (updates.technical_decisions !== undefined) {\n setClauses.push('technical_decisions = ?');\n params.push(JSON.stringify(updates.technical_decisions));\n }\n if (updates.git_context_snapshot !== undefined) {\n setClauses.push('git_context_snapshot = ?');\n params.push(updates.git_context_snapshot);\n }\n if (updates.access_count !== undefined) {\n setClauses.push('access_count = ?');\n params.push(updates.access_count);\n }\n if (updates.last_accessed !== undefined) {\n setClauses.push('last_accessed = ?');\n params.push(updates.last_accessed);\n }\n\n setClauses.push('updated_at = ?');\n params.push(new Date().toISOString());\n params.push(id);\n\n this.db\n .prepare(`UPDATE memories SET ${setClauses.join(', ')} WHERE id = ?`)\n .run(...params);\n }\n\n getMemoryById(id: number): MemoryEntry | undefined {\n const row = this.db.prepare('SELECT * FROM memories WHERE id = ?').get(id) as Record<string, unknown> | undefined;\n if (!row) return undefined;\n return this.hydrateMemory(row);\n }\n\n searchMemories(project: string, limit: number = 10): MemoryEntry[] {\n const rows = this.db\n .prepare('SELECT * FROM memories WHERE project = ? ORDER BY updated_at DESC LIMIT ?')\n .all(project, limit) as Record<string, unknown>[];\n return rows.map(r => this.hydrateMemory(r));\n }\n\n upsertProjectMemory(entry: { project: string; prompt_id: number; summary: string; key_insights: string[]; technical_decisions: string[]; git_context_snapshot?: string }): number {\n // Append-only: create a new memory entry each time, preserving full history\n return this.insertMemory({\n project: entry.project,\n prompt_ids: [entry.prompt_id],\n summary: entry.summary,\n key_insights: entry.key_insights,\n technical_decisions: entry.technical_decisions,\n git_context_snapshot: entry.git_context_snapshot,\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n access_count: 0,\n last_accessed: undefined,\n });\n }\n\n getLastMemoryForProject(project: string): MemoryEntry | undefined {\n const row = this.db\n .prepare('SELECT * FROM memories WHERE project = ? ORDER BY updated_at DESC LIMIT 1')\n .get(project) as Record<string, unknown> | undefined;\n if (!row) return undefined;\n return this.hydrateMemory(row);\n }\n\n getAllProjectsWithMemories(): string[] {\n const rows = this.db\n .prepare('SELECT DISTINCT project FROM memories ORDER BY project')\n .all() as { project: string }[];\n return rows.map(r => r.project);\n }\n\n upsertProjectSummary(params: {\n project: string;\n summary: string;\n key_insights: string[];\n technical_decisions: string[];\n git_context_snapshot?: string;\n }): void {\n const existing = this.getProjectSummary(params.project);\n const now = new Date().toISOString();\n\n if (existing) {\n const allInsights = new Set([...existing.key_insights, ...params.key_insights]);\n const allDecisions = new Set([...existing.technical_decisions, ...params.technical_decisions]);\n\n this.db.prepare(`\n UPDATE project_summaries\n SET summary = ?,\n key_insights = ?,\n technical_decisions = ?,\n prompt_count = prompt_count + 1,\n last_analyzed = ?,\n git_context_snapshot = COALESCE(?, git_context_snapshot)\n WHERE project = ?\n `).run(\n params.summary,\n JSON.stringify([...allInsights]),\n JSON.stringify([...allDecisions]),\n now,\n params.git_context_snapshot || null,\n params.project\n );\n } else {\n this.db.prepare(`\n INSERT INTO project_summaries (project, summary, key_insights, technical_decisions, prompt_count, first_analyzed, last_analyzed, git_context_snapshot)\n VALUES (?, ?, ?, ?, 1, ?, ?, ?)\n `).run(\n params.project,\n params.summary,\n JSON.stringify(params.key_insights),\n JSON.stringify(params.technical_decisions),\n now,\n now,\n params.git_context_snapshot || null\n );\n }\n }\n\n getProjectSummary(project: string): ProjectSummary | null {\n const row = this.db.prepare('SELECT * FROM project_summaries WHERE project = ?').get(project) as Record<string, unknown> | undefined;\n if (!row) return null;\n return this.hydrateProjectSummary(row);\n }\n\n getAllProjectsWithSummaries(): string[] {\n const rows = this.db.prepare('SELECT project FROM project_summaries ORDER BY project').all() as { project: string }[];\n return rows.map(r => r.project);\n }\n\n recordMemoryAccess(id: number): void {\n this.db\n .prepare('UPDATE memories SET access_count = access_count + 1, last_accessed = ? WHERE id = ?')\n .run(new Date().toISOString(), id);\n }\n\n deleteMemory(id: number): void {\n this.db.prepare('DELETE FROM memories WHERE id = ?').run(id);\n }\n\n private hydrateMemory(row: Record<string, unknown>): MemoryEntry {\n return {\n id: row.id as number,\n project: row.project as string,\n prompt_ids: JSON.parse(row.prompt_ids as string),\n summary: row.summary as string,\n key_insights: JSON.parse(row.key_insights as string),\n technical_decisions: JSON.parse(row.technical_decisions as string),\n git_context_snapshot: row.git_context_snapshot as string | undefined,\n created_at: row.created_at as string,\n updated_at: row.updated_at as string,\n access_count: row.access_count as number,\n last_accessed: row.last_accessed as string | undefined,\n };\n }\n\n private hydrateProjectSummary(row: Record<string, unknown>): ProjectSummary {\n return {\n project: row.project as string,\n summary: row.summary as string,\n key_insights: JSON.parse(row.key_insights as string),\n technical_decisions: JSON.parse(row.technical_decisions as string),\n prompt_count: row.prompt_count as number,\n first_analyzed: row.first_analyzed as string,\n last_analyzed: row.last_analyzed as string,\n git_context_snapshot: row.git_context_snapshot as string | undefined,\n };\n }\n\n getAllPromptsByProject(project: string): PromptEntry[] {\n return this.db\n .prepare(`\n SELECT * FROM prompts\n WHERE json_extract(metadata, '$.project') = ?\n ORDER BY timestamp ASC\n `)\n .all(project) as PromptEntry[];\n }\n\n getPromptsByProjectPaginated(project: string, page: number, pageSize: number): { entries: PromptEntry[]; total: number } {\n const total = this.db\n .prepare(\"SELECT COUNT(*) as count FROM prompts WHERE json_extract(metadata, '$.project') = ?\")\n .get(project) as { count: number };\n\n const entries = this.db\n .prepare(`\n SELECT * FROM prompts\n WHERE json_extract(metadata, '$.project') = ?\n ORDER BY timestamp DESC\n LIMIT ? OFFSET ?\n `)\n .all(project, pageSize, (page - 1) * pageSize) as PromptEntry[];\n\n return { entries, total: total.count };\n }\n\n getPromptCountByProject(project: string): number {\n const row = this.db\n .prepare(\"SELECT COUNT(*) as count FROM prompts WHERE json_extract(metadata, '$.project') = ?\")\n .get(project) as { count: number };\n return row.count;\n }\n\n getAllMemoriesByProject(project: string): MemoryEntry[] {\n const rows = this.db\n .prepare('SELECT * FROM memories WHERE project = ? ORDER BY created_at ASC')\n .all(project) as Record<string, unknown>[];\n return rows.map(r => this.hydrateMemory(r));\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 type Database from 'better-sqlite3';\nimport type { PromptEntry } from '../types.js';\n\n/** Owns vector encoding, compatibility storage, and semantic nearest-neighbor queries. */\nexport class SemanticIndex {\n constructor(private readonly db: Database.Database) {}\n\n save(promptId: number, vector: Float32Array): void {\n const encoded = this.encode(vector);\n // Keep the legacy BLOB table populated while older databases migrate.\n this.db.prepare('INSERT OR REPLACE INTO embeddings (prompt_id, vector) VALUES (?, ?)').run(promptId, encoded);\n this.db.prepare('INSERT OR REPLACE INTO vec_embeddings(rowid, embedding) VALUES (?, vec_f32(?))').run(BigInt(promptId), encoded);\n }\n\n search(query: Float32Array, limit: number, project?: string): PromptEntry[] {\n const encodedQuery = this.encode(query);\n // sqlite-vec applies k before SQLite evaluates metadata predicates. Scoped\n // searches therefore inspect all vectors, then filter and apply the limit.\n const projectFilter = project ? \"AND json_extract(p.metadata, '$.project') = ?\" : '';\n const candidateLimit = project\n ? Math.max(1, (this.db.prepare('SELECT count(*) AS count FROM vec_embeddings').get() as { count: number }).count)\n : limit;\n const sql = `\n SELECT p.*, v.distance\n FROM vec_embeddings v\n JOIN prompts p ON p.id = v.rowid\n WHERE v.embedding MATCH vec_f32(?) AND k = ?\n ${projectFilter}\n ORDER BY v.distance ASC\n `;\n return this.db.prepare(project ? `${sql} LIMIT ?` : sql).all(\n encodedQuery,\n candidateLimit,\n ...(project ? [project, limit] : []),\n ) as PromptEntry[];\n }\n\n loadAll(): Map<number, Float32Array> {\n const rows = this.db.prepare('SELECT prompt_id, vector FROM embeddings').all() as { prompt_id: number; vector: Buffer }[];\n return new Map(rows.map(row => [row.prompt_id, this.decode(row.vector)]));\n }\n\n findMissingPrompts(): PromptEntry[] {\n return this.db.prepare(\n `SELECT p.* FROM prompts p\n LEFT JOIN vec_embeddings e ON e.rowid = p.id\n WHERE e.rowid IS NULL`,\n ).all() as PromptEntry[];\n }\n\n private encode(vector: Float32Array): Buffer {\n const buffer = Buffer.alloc(vector.length * 4);\n for (let i = 0; i < vector.length; i++) buffer.writeFloatLE(vector[i], i * 4);\n return buffer;\n }\n\n private decode(buffer: Buffer): Float32Array {\n const vector = new Float32Array(buffer.length / 4);\n for (let i = 0; i < vector.length; i++) vector[i] = buffer.readFloatLE(i * 4);\n return vector;\n }\n}\n","import { spawn, execFileSync } from 'child_process';\nimport fs from 'fs';\nimport { PhDB } from '../db/index.js';\nimport { captureGitContext } from './git-context.js';\nimport { createCaptureRecord } from '../capture/index.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 gitContext = captureGitContext(workdir);\n\n const id = db.insert(createCaptureRecord({\n tool,\n prompt: extractPrompt(args),\n args: args.join(' '),\n workdir,\n gitContext,\n metadata: { ...(role ? { role } : {}), ...(tags.length > 0 ? { tags } : {}) },\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 { 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 os from 'node:os';\nimport { detectProject, detectLanguage } from '../runner/project.js';\nimport type { GitContext } from '../runner/git-context.js';\nimport { extractTopic } from '../utils/extractTopic.js';\nimport type { PromptEntry } from '../types.js';\n\nexport interface CaptureInput {\n tool: string;\n prompt: string;\n response?: string;\n args?: string;\n workdir: string;\n timestamp?: string;\n hostname?: string;\n exit_code?: number;\n metadata?: Record<string, unknown>;\n gitContext?: GitContext | null;\n}\n\n/** Build the canonical record shared by live capture entry points. */\nexport function createCaptureRecord(input: CaptureInput): Omit<PromptEntry, 'id'> {\n const { rootDir, projectName } = detectProject(input.workdir);\n const language = detectLanguage(rootDir);\n const title = extractTopic(input.prompt);\n const metadata: Record<string, unknown> = {\n $schema_version: 1,\n ...(projectName ? { project: projectName } : {}),\n ...(language ? { language } : {}),\n ...(title ? { title } : {}),\n ...(input.gitContext ? { git_context: input.gitContext } : {}),\n ...input.metadata,\n };\n\n return {\n timestamp: input.timestamp ?? new Date().toISOString(),\n tool: input.tool,\n prompt: input.prompt,\n response: input.response ?? '',\n args: input.args ?? '',\n workdir: input.workdir,\n hostname: input.hostname ?? os.hostname(),\n exit_code: input.exit_code ?? 0,\n metadata: JSON.stringify(metadata),\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","/**\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 pty from '@lydell/node-pty';\nimport fs from 'fs';\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 */\nexport function stripPtyControlSequences(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, stripPtyControlSequences(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, stripPtyControlSequences(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 { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { PhDB, defaultPath } from \"../db/index.js\";\nimport { load as loadConfig } from \"../config/index.js\";\nimport { getEmbeddings } from \"../embedding/index.js\";\nimport type { PromptEntry, PromptMetadata } from \"../types.js\";\nimport { formatProjectContext, getProjectContext } from \"../context/index.js\";\nimport { z } from \"zod\";\n\nexport function createMCPServer(db: PhDB, cfg = loadConfig()) {\n const server = new Server(\n {\n name: \"ph-memory\",\n version: \"1.0.0\",\n },\n {\n capabilities: {\n tools: {},\n },\n }\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n return {\n tools: [\n {\n name: \"list_prompts\",\n description: \"List prompts for a project with pagination. Use page=1, pageSize=10 to browse.\",\n inputSchema: {\n type: \"object\",\n properties: {\n project: { type: \"string\", description: \"Project name to list prompts for\" },\n page: { type: \"number\", description: \"Page number (1-based)\", default: 1 },\n pageSize: { type: \"number\", description: \"Results per page (max 100)\", default: 20 },\n },\n required: [\"project\"],\n },\n },\n {\n name: \"save_decision\",\n description: \"Save an architectural decision or key insight to project memory.\",\n inputSchema: {\n type: \"object\",\n properties: {\n project: { type: \"string\", description: \"Project name\" },\n summary: { type: \"string\", description: \"Brief summary of the decision\" },\n keyInsights: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Key insights or takeaways\",\n },\n technicalDecisions: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Technical decisions made\",\n },\n },\n required: [\"project\", \"summary\"],\n },\n },\n {\n name: \"get_project_diff\",\n description: \"Compare project state between two points in time. Shows prompts and memory entries created in the date range.\",\n inputSchema: {\n type: \"object\",\n properties: {\n project: { type: \"string\", description: \"Project name\" },\n since: { type: \"string\", description: \"Start date (ISO 8601, e.g. 2026-01-01)\" },\n until: { type: \"string\", description: \"End date (ISO 8601, defaults to now)\" },\n },\n required: [\"project\", \"since\"],\n },\n },\n {\n name: \"search_project_memory\",\n description: \"Search for past interactions and technical decisions in a specific project using semantic search.\",\n inputSchema: {\n type: \"object\",\n properties: {\n query: { type: \"string\", description: \"The search query (e.g. 'how did we handle auth?')\" },\n project: { type: \"string\", description: \"The project name to filter by\" },\n limit: { type: \"number\", description: \"Max results to return\", default: 5 },\n },\n required: [\"query\", \"project\"],\n },\n },\n {\n name: \"get_project_context\",\n description: \"Retrieve recent summaries, key insights, and technical decisions for a project.\",\n inputSchema: {\n type: \"object\",\n properties: {\n project: { type: \"string\", description: \"The project name\" },\n limit: { type: \"number\", description: \"Max interactions to retrieve\", default: 10 },\n },\n required: [\"project\"],\n },\n },\n {\n name: \"get_project_summary\",\n description: \"Get high-level accumulated project knowledge from memories: key insights and technical decisions.\",\n inputSchema: {\n type: \"object\",\n properties: {\n project: { type: \"string\", description: \"The project name\" },\n },\n required: [\"project\"],\n },\n },\n {\n name: \"search_prompts\",\n description: \"Search prompt history by text or filters. Omit query for recent prompts.\",\n inputSchema: {\n type: \"object\",\n properties: {\n query: { type: \"string\", description: \"Full-text search query (searches prompt + response)\" },\n tool: { type: \"string\", description: \"Filter by tool name (e.g. claude, gemini)\" },\n project: { type: \"string\", description: \"Filter by project name\" },\n role: { type: \"string\", description: \"Filter by role (debug, refactor, explain, etc.)\" },\n tag: { type: \"string\", description: \"Filter by tag\" },\n since: { type: \"string\", description: \"ISO date string — only prompts after this date\" },\n until: { type: \"string\", description: \"ISO date string — only prompts before this date\" },\n limit: { type: \"number\", description: \"Max results (default 10)\", default: 10 },\n },\n },\n },\n {\n name: \"get_prompt\",\n description: \"Get full details of a single prompt by ID.\",\n inputSchema: {\n type: \"object\",\n properties: {\n id: { type: \"number\", description: \"The prompt ID\" },\n },\n required: [\"id\"],\n },\n },\n {\n name: \"search_prompts_semantic\",\n description: \"Search prompt history by semantic similarity (vector search).\",\n inputSchema: {\n type: \"object\",\n properties: {\n query: { type: \"string\", description: \"Natural language query\" },\n project: { type: \"string\", description: \"Filter by project name\" },\n limit: { type: \"number\", description: \"Max results (default 5)\", default: 5 },\n },\n required: [\"query\"],\n },\n },\n {\n name: \"get_project_timeline\",\n description: \"Get full chronological timeline of a project: all prompts, analysis summaries, key insights, and technical decisions in sequence.\",\n inputSchema: {\n type: \"object\",\n properties: {\n project: { type: \"string\", description: \"The project name\" },\n since: { type: \"string\", description: \"Start date (ISO 8601, optional)\" },\n until: { type: \"string\", description: \"End date (ISO 8601, optional)\" },\n limit: { type: \"number\", description: \"Max events to return (default 100)\", default: 100 },\n },\n required: [\"project\"],\n },\n },\n {\n name: \"check_project_knowledge\",\n description: \"Before implementing a feature, check if it already exists in project history. Searches memories and prompts for previous implementations, discussions, and technical decisions related to a task.\",\n inputSchema: {\n type: \"object\",\n properties: {\n project: { type: \"string\", description: \"The project name\" },\n task: { type: \"string\", description: \"Description of the feature or task to check\" },\n limit: { type: \"number\", description: \"Max results per search (default 5)\", default: 5 },\n },\n required: [\"project\", \"task\"],\n },\n },\n ],\n };\n });\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n try {\n if (name === \"list_prompts\") {\n const { project, page = 1, pageSize = 20 } = z.object({\n project: z.string(),\n page: z.number().optional(),\n pageSize: z.number().max(100).optional(),\n }).parse(args);\n\n const result = db.getPromptsByProjectPaginated(project, page, pageSize);\n const totalPages = Math.ceil(result.total / pageSize);\n\n const text = [\n `## Prompts for \"${project}\"`,\n `Page ${page}/${totalPages} (${result.total} total)\\n`,\n ...result.entries.map(e => {\n let meta: PromptMetadata = {};\n try { meta = JSON.parse(e.metadata); } catch {}\n const date = new Date(e.timestamp).toLocaleString();\n const title = meta.title ? ` — ${meta.title}` : '';\n const roleStr = meta.role ? ` (${meta.role})` : '';\n return `### #${e.id} — ${e.tool}${roleStr} (${date})${title}\\n${(meta.summary ? `Summary: ${meta.summary}\\n` : '')}Prompt: ${e.prompt.slice(0, 200)}${e.prompt.length > 200 ? '...' : ''}`;\n }).join('\\n\\n'),\n '',\n `Page ${page}/${totalPages} | ${result.total} total prompts`,\n ].join('\\n');\n\n return { content: [{ type: \"text\", text }] };\n }\n\n if (name === \"save_decision\") {\n const { project, summary, keyInsights, technicalDecisions } = z.object({\n project: z.string(),\n summary: z.string(),\n keyInsights: z.array(z.string()).optional(),\n technicalDecisions: z.array(z.string()).optional(),\n }).parse(args);\n\n const id = db.insertMemory({\n project,\n prompt_ids: [],\n summary,\n key_insights: keyInsights ?? [],\n technical_decisions: technicalDecisions ?? [],\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n access_count: 0,\n });\n\n db.upsertProjectSummary({\n project,\n summary,\n key_insights: keyInsights ?? [],\n technical_decisions: technicalDecisions ?? [],\n });\n\n return {\n content: [{ type: \"text\", text: `Decision saved as memory #${id} for project \"${project}\".\\n\\nSummary: ${summary}\\nKey Insights: ${(keyInsights ?? []).length}\\nTechnical Decisions: ${(technicalDecisions ?? []).length}` }],\n };\n }\n\n if (name === \"get_project_diff\") {\n const { project, since, until } = z.object({\n project: z.string(),\n since: z.string(),\n until: z.string().optional(),\n }).parse(args);\n\n const sinceDate = new Date(since);\n const untilDate = until ? new Date(until) : new Date();\n\n const prompts = db.search({\n project,\n since: sinceDate,\n until: untilDate,\n limit: 1000,\n });\n\n const memories = db.getAllMemoriesByProject(project)\n .filter(m => {\n const created = new Date(m.created_at);\n return created >= sinceDate && created <= untilDate;\n });\n\n const lines: string[] = [\n `## Project Diff: ${project}`,\n `From: ${since} To: ${until || 'now'}`,\n `Prompts: ${prompts.length} Memories: ${memories.length}\\n`,\n ];\n\n if (prompts.length > 0) {\n lines.push('### Prompts\\n');\n for (const p of prompts.reverse()) {\n let meta: PromptMetadata = {};\n try { meta = JSON.parse(p.metadata); } catch {}\n const title = meta.title ? ` — ${meta.title}` : '';\n const roleStr = meta.role ? ` (${meta.role})` : '';\n lines.push(`- **#${p.id}** ${p.tool}${roleStr}${title} (${new Date(p.timestamp).toLocaleDateString()})`);\n if (meta.summary) lines.push(` Summary: ${meta.summary}`);\n }\n }\n\n if (memories.length > 0) {\n lines.push('\\n### Memory Entries\\n');\n for (const m of memories) {\n lines.push(`- **Memory #${m.id}**: ${m.summary}`);\n for (const i of m.key_insights) lines.push(` - Insight: ${i}`);\n for (const d of m.technical_decisions) lines.push(` - Decision: ${d}`);\n }\n }\n\n return { content: [{ type: \"text\", text: lines.join('\\n') }] };\n }\n\n if (name === \"search_project_memory\") {\n const { query, project, limit = 5 } = z.object({\n query: z.string(),\n project: z.string(),\n limit: z.number().optional(),\n }).parse(args);\n\n const ollamaUrl = cfg.ollamaUrl ?? 'http://localhost:11434';\n const model = cfg.ollamaEmbedModel ?? 'nomic-embed-text-v2-moe';\n\n const [queryVec] = await getEmbeddings([query], ollamaUrl, model, 1);\n if (!queryVec) {\n throw new Error(\"Failed to generate embedding for query\");\n }\n\n const filtered = db.searchSemantic(queryVec, limit, project);\n\n if (filtered.length === 0) {\n const merged = db.getProjectSummary(project);\n if (merged) {\n const parts: string[] = [\n `## Project Knowledge: ${project}\\n`,\n `Based on ${merged.prompt_count} interactions.\\n`,\n ];\n if (merged.summary) parts.push(`${merged.summary}\\n`);\n if (merged.key_insights.length > 0) {\n parts.push('\\n**Key Insights:**');\n for (const i of merged.key_insights) parts.push(`- ${i}`);\n }\n if (merged.technical_decisions.length > 0) {\n parts.push('\\n**Technical Decisions:**');\n for (const d of merged.technical_decisions) parts.push(`- ${d}`);\n }\n return { content: [{ type: \"text\", text: parts.join('\\n') }] };\n }\n return { content: [{ type: \"text\", text: `No relevant memory found for project \"${project}\".` }] };\n }\n\n return {\n content: [{ type: \"text\", text: formatResultsAsMarkdown(filtered) }],\n };\n }\n\n if (name === \"get_project_context\") {\n const { project, limit = 10 } = z.object({\n project: z.string(),\n limit: z.number().optional(),\n }).parse(args);\n\n const context = await getProjectContext(db, { project, limit, memoryLimit: 3 });\n\n return {\n content: [{ type: \"text\", text: formatProjectContext(context, {\n promptExcerptLength: 300,\n responseExcerptLength: 200,\n emptyMessage: 'No context found for this project.',\n }) }],\n };\n }\n\n if (name === \"get_project_summary\") {\n const { project } = z.object({\n project: z.string(),\n }).parse(args);\n\n const summary = db.getProjectSummary(project);\n\n if (!summary) {\n return {\n content: [{ type: \"text\", text: `No accumulated knowledge for project \"${project}\". Run \"ph analyze\" to generate insights.` }],\n };\n }\n\n const parts: string[] = [];\n parts.push(`## ${summary.summary || 'Project Memory'}\\n`);\n parts.push(`Based on ${summary.prompt_count} interactions.\\n`);\n if (summary.key_insights.length > 0) {\n parts.push('**Key Insights:**');\n for (const i of summary.key_insights) parts.push(`- ${i}`);\n parts.push('');\n }\n if (summary.technical_decisions.length > 0) {\n parts.push('**Technical Decisions:**');\n for (const d of summary.technical_decisions) parts.push(`- ${d}`);\n parts.push('');\n }\n\n return {\n content: [{ type: \"text\", text: parts.join('\\n') }],\n };\n }\n\n if (name === \"search_prompts\") {\n const { query, tool, project, role, tag, since, until, limit = 10 } = z.object({\n query: z.string().optional(),\n tool: z.string().optional(),\n project: z.string().optional(),\n role: z.string().optional(),\n tag: z.string().optional(),\n since: z.string().optional(),\n until: z.string().optional(),\n limit: z.number().optional(),\n }).parse(args);\n\n const results = db.search({\n query,\n tool,\n project,\n role,\n tag,\n ...(since ? { since: new Date(since) } : {}),\n ...(until ? { until: new Date(until) } : {}),\n limit,\n });\n\n return {\n content: [{ type: \"text\", text: formatPromptList(results, query) }],\n };\n }\n\n if (name === \"get_prompt\") {\n const { id } = z.object({\n id: z.number(),\n }).parse(args);\n\n const entry = db.getById(id);\n if (!entry) {\n return {\n content: [{ type: \"text\", text: `Prompt #${id} not found.` }],\n };\n }\n\n return {\n content: [{ type: \"text\", text: formatSinglePrompt(entry) }],\n };\n }\n\n if (name === \"search_prompts_semantic\") {\n const { query, project, limit = 5 } = z.object({\n query: z.string(),\n project: z.string().optional(),\n limit: z.number().optional(),\n }).parse(args);\n\n const ollamaUrl = cfg.ollamaUrl ?? 'http://localhost:11434';\n const model = cfg.ollamaEmbedModel ?? 'nomic-embed-text-v2-moe';\n\n const [queryVec] = await getEmbeddings([query], ollamaUrl, model, 1);\n if (!queryVec) {\n throw new Error(\"Failed to generate embedding for query\");\n }\n\n const filtered = db.searchSemantic(queryVec, limit, project);\n\n return {\n content: [{ type: \"text\", text: formatPromptList(filtered, query) }],\n };\n }\n\n if (name === \"get_project_timeline\") {\n const { project, since, until, limit = 100 } = z.object({\n project: z.string(),\n since: z.string().optional(),\n until: z.string().optional(),\n limit: z.number().optional(),\n }).parse(args);\n\n let allPrompts = db.getAllPromptsByProject(project);\n let memories = db.getAllMemoriesByProject(project);\n\n // Apply date filters\n if (since) {\n const sinceDate = new Date(since);\n allPrompts = allPrompts.filter(p => new Date(p.timestamp) >= sinceDate);\n memories = memories.filter(m => new Date(m.created_at) >= sinceDate);\n }\n if (until) {\n const untilDate = new Date(until);\n allPrompts = allPrompts.filter(p => new Date(p.timestamp) <= untilDate);\n memories = memories.filter(m => new Date(m.created_at) <= untilDate);\n }\n\n if (allPrompts.length === 0 && memories.length === 0) {\n return {\n content: [{ type: \"text\", text: `No history found for project \"${project}\"${since ? ` since ${since}` : ''}${until ? ` until ${until}` : ''}.` }],\n };\n }\n\n const events: Array<{ timestamp: string; text: string }> = [];\n\n for (const p of allPrompts.slice(0, limit)) {\n let meta: PromptMetadata = {};\n try { meta = JSON.parse(p.metadata); } catch {}\n events.push({\n timestamp: p.timestamp,\n text: [\n `### #${p.id} — ${p.tool}`,\n meta.role ? `Role: ${meta.role}` : '',\n meta.title ? `Title: ${meta.title}` : '',\n meta.tags?.length ? `Tags: ${meta.tags.join(', ')}` : '',\n meta.summary ? `Summary: ${meta.summary}` : '',\n `Prompt: ${p.prompt.slice(0, 500)}${p.prompt.length > 500 ? '...' : ''}`,\n p.response ? `Response: ${p.response.slice(0, 300)}${p.response.length > 300 ? '...' : ''}` : '',\n meta.key_insights?.length ? `Insights:\\n${meta.key_insights.map(i => `- ${i}`).join('\\n')}` : '',\n ].filter(Boolean).join('\\n'),\n });\n }\n\n for (const m of memories) {\n events.push({\n timestamp: m.created_at,\n text: [\n `📌 Memory #${m.id}`,\n m.prompt_ids.length > 0 ? `From prompts: #${m.prompt_ids.join(', #')}` : '',\n m.summary ? `Summary: ${m.summary}` : '',\n m.key_insights.length > 0 ? `Key Insights:\\n${m.key_insights.map(i => `- ${i}`).join('\\n')}` : '',\n m.technical_decisions.length > 0 ? `Technical Decisions:\\n${m.technical_decisions.map(d => `- ${d}`).join('\\n')}` : '',\n ].filter(Boolean).join('\\n'),\n });\n }\n\n events.sort((a, b) => a.timestamp.localeCompare(b.timestamp));\n\n const range = since || until ? ` (${since || '…'} → ${until || 'now'})` : '';\n const header = `# Timeline: ${project}${range}\\n\\n${allPrompts.length} prompts · ${memories.length} memory entries\\n\\n`;\n const body = events.map(e => {\n const date = new Date(e.timestamp).toLocaleDateString('en-CA');\n const time = new Date(e.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });\n return `## ${date} ${time}\\n\\n${e.text}\\n`;\n }).join('---\\n');\n\n return {\n content: [{ type: \"text\", text: header + body }],\n };\n }\n\n if (name === \"check_project_knowledge\") {\n const { project, task, limit = 5 } = z.object({\n project: z.string(),\n task: z.string(),\n limit: z.number().optional(),\n }).parse(args);\n\n const parts: string[] = [];\n parts.push(`# Knowledge Check: \"${task}\" in ${project}\\n`);\n\n // 1. Search memories\n const memories = db.searchMemories(project, limit);\n const relevantMemories = memories.filter(m =>\n m.summary.toLowerCase().includes(task.toLowerCase()) ||\n m.key_insights.some(k => k.toLowerCase().includes(task.toLowerCase())) ||\n m.technical_decisions.some(d => d.toLowerCase().includes(task.toLowerCase()))\n );\n\n if (relevantMemories.length > 0) {\n parts.push(`## Found in Project Memories\\n`);\n for (const m of relevantMemories) {\n parts.push(`### Memory #${m.id}`);\n if (m.summary) parts.push(`Summary: ${m.summary}`);\n if (m.key_insights.length > 0) {\n parts.push(`Key Insights:\\n${m.key_insights.map(i => `- ${i}`).join('\\n')}`);\n }\n if (m.technical_decisions.length > 0) {\n parts.push(`Technical Decisions:\\n${m.technical_decisions.map(d => `- ${d}`).join('\\n')}`);\n }\n parts.push('');\n }\n }\n\n // 2. Search prompts semantically\n const ollamaUrl = cfg.ollamaUrl ?? 'http://localhost:11434';\n const embedModel = cfg.ollamaEmbedModel ?? 'nomic-embed-text-v2-moe';\n\n try {\n const [queryVec] = await getEmbeddings([`${project}: ${task}`], ollamaUrl, embedModel, 1);\n if (queryVec) {\n const projectPrompts = db.searchSemantic(queryVec, limit, project);\n\n if (projectPrompts.length > 0) {\n parts.push(`## Related Prompts\\n`);\n for (const p of projectPrompts) {\n let meta: PromptMetadata = {};\n try { meta = JSON.parse(p.metadata); } catch {}\n parts.push(`### #${p.id} — ${p.tool} (${new Date(p.timestamp).toLocaleDateString()})`);\n if (meta.role) parts.push(`Role: ${meta.role}`);\n if (meta.summary) parts.push(`Summary: ${meta.summary}`);\n parts.push(`Prompt: ${p.prompt.slice(0, 400)}${p.prompt.length > 400 ? '...' : ''}`);\n parts.push('');\n }\n }\n }\n } catch {\n parts.push('(Semantic search unavailable — Ollama may not be running)\\n');\n }\n\n if (relevantMemories.length === 0 && !parts.some(p => p.startsWith('## Related Prompts'))) {\n parts.push('No existing knowledge found for this task. This appears to be new work.\\n');\n }\n\n parts.push('---\\n');\n parts.push('**Recommendation**: Review the above before implementing. If a previous implementation exists, consider reusing or adapting it.\\n');\n\n return {\n content: [{ type: \"text\", text: parts.join('\\n') }],\n };\n }\n\n throw new Error(`Unknown tool: ${name}`);\n } catch (error) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error: ${(error as Error).message}` }],\n };\n }\n });\n\n return server;\n}\n\nexport async function runMCPServer() {\n const cfg = loadConfig();\n const dbPath = process.env.PH_DB ?? cfg.dbPath ?? defaultPath();\n const db = new PhDB(dbPath);\n const server = createMCPServer(db, cfg);\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error(\"ph MCP server running on stdio\");\n}\n\nfunction formatResultsAsMarkdown(entries: PromptEntry[]): string {\n if (entries.length === 0) return \"No relevant memory found for this project.\";\n\n return entries.map(e => {\n let meta: PromptMetadata = {};\n try { meta = JSON.parse(e.metadata); } catch {}\n \n let out = `### Interaction #${e.id} (${new Date(e.timestamp).toLocaleDateString()})\\n`;\n if (meta.role) out += `Role: ${meta.role} \\n`;\n if (meta.summary) out += `**Summary**: ${meta.summary}\\n`;\n out += `**Prompt**: ${e.prompt.slice(0, 300)}${e.prompt.length > 300 ? '...' : ''}\\n`;\n if (meta.key_insights && meta.key_insights.length > 0) {\n out += `**Key Insights**:\\n${meta.key_insights.map(i => `- ${i}`).join('\\n')}\\n`;\n }\n return out;\n }).join('\\n---\\n\\n');\n}\n\nfunction formatPromptList(entries: PromptEntry[], query?: string): string {\n if (entries.length === 0) return \"No prompts found.\";\n\n const header = query\n ? `Found ${entries.length} prompts matching \"${query}\":\\n\\n`\n : `Recent ${entries.length} prompts:\\n\\n`;\n\n return header + entries.map(e => {\n let meta: PromptMetadata = {};\n try { meta = JSON.parse(e.metadata); } catch {}\n\n const date = new Date(e.timestamp).toLocaleString();\n const proj = meta.project ? ` [${meta.project}]` : '';\n const title = meta.title ? ` — ${meta.title}` : '';\n const roleStr = meta.role ? ` \\nRole: ${meta.role}` : '';\n\n let out = `### #${e.id} — ${e.tool}${proj} (${date})${title}\\n`;\n if (meta.summary) out += `**Summary**: ${meta.summary} \\n`;\n out += `${roleStr} \\n`; // keep role placement consistent\n out += `**Prompt**: ${e.prompt.slice(0, 300)}${e.prompt.length > 300 ? '...' : ''}\\n`;\n if (e.response) {\n out += `**Response**: ${e.response.slice(0, 200)}${e.response.length > 200 ? '...' : ''}\\n`;\n }\n return out;\n }).join('\\n---\\n\\n');\n}\n\nfunction formatSinglePrompt(e: PromptEntry): string {\n let meta: PromptMetadata = {};\n try { meta = JSON.parse(e.metadata); } catch {}\n\n const date = new Date(e.timestamp).toLocaleString();\n const parts: string[] = [];\n\n parts.push(`# Prompt #${e.id}\\n`);\n parts.push(`**Tool**: ${e.tool} `);\n parts.push(`**Date**: ${date} `);\n if (meta.project) parts.push(`**Project**: ${meta.project} `);\n if (meta.role) parts.push(`**Role**: ${meta.role} `);\n if (meta.title) parts.push(`**Title**: ${meta.title} `);\n if (meta.tags?.length) parts.push(`**Tags**: ${meta.tags.join(', ')} `);\n if (e.workdir) parts.push(`**Workdir**: ${e.workdir} `);\n if (e.exit_code !== 0) parts.push(`**Exit Code**: ${e.exit_code} `);\n parts.push('');\n\n if (meta.summary) {\n parts.push(`**Summary**: ${meta.summary}\\n`);\n }\n\n parts.push('---\\n');\n parts.push('**Prompt**:\\n');\n parts.push('```\\n' + e.prompt + '\\n```\\n');\n\n if (e.response) {\n parts.push('\\n**Response**:\\n');\n parts.push('```\\n' + e.response + '\\n```\\n');\n }\n\n if (meta.key_insights?.length) {\n parts.push('\\n**Key Insights**:\\n');\n for (const i of meta.key_insights) parts.push(`- ${i}\\n`);\n }\n\n return parts.join('\\n');\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 { MemoryEntry, ProjectSummary, PromptEntry, PromptMetadata } from '../types.js';\n\nexport interface ProjectContextStore {\n getProjectSummary(project: string): ProjectSummary | null;\n searchMemories(project: string, limit?: number): MemoryEntry[];\n getProjectMemory(project: string, limit?: number): PromptEntry[];\n searchSemantic(queryVector: Float32Array, limit: number, project?: string): PromptEntry[];\n}\n\nexport interface ProjectContextOptions {\n project: string;\n query?: string;\n limit?: number;\n memoryLimit?: number;\n includeSummary?: boolean;\n includeMemories?: boolean;\n includePrompts?: boolean;\n}\n\nexport interface ProjectContext {\n project: string;\n summary: ProjectSummary | null;\n memories: MemoryEntry[];\n prompts: PromptEntry[];\n}\n\nexport type ContextEmbedder = (query: string) => Promise<Float32Array | undefined>;\n\n/** Retrieve all project context evidence through one consumer-facing boundary. */\nexport async function getProjectContext(\n db: ProjectContextStore,\n options: ProjectContextOptions,\n embedQuery?: ContextEmbedder,\n): Promise<ProjectContext> {\n const limit = Math.max(1, Math.floor(options.limit ?? 5));\n const memoryLimit = Math.max(1, Math.floor(options.memoryLimit ?? limit));\n const includeSummary = options.includeSummary ?? true;\n const includeMemories = options.includeMemories ?? true;\n const includePrompts = options.includePrompts ?? true;\n\n const summary = includeSummary ? db.getProjectSummary(options.project) : null;\n const memories = includeMemories ? db.searchMemories(options.project, memoryLimit) : [];\n let prompts: PromptEntry[] = [];\n\n if (includePrompts) {\n const query = options.query?.trim();\n if (query) {\n if (!embedQuery) throw new Error('Semantic context requires an embedding provider.');\n const vector = await embedQuery(query);\n prompts = vector ? db.searchSemantic(vector, limit, options.project) : [];\n } else {\n prompts = db.getProjectMemory(options.project, limit);\n }\n }\n\n return { project: options.project, summary, memories, prompts };\n}\n\nexport interface FormatProjectContextOptions {\n includePromptText?: boolean;\n promptExcerptLength?: number;\n responseExcerptLength?: number;\n emptyMessage?: string;\n}\n\n/** Render retrieved evidence as stable Markdown for terminal and agent consumers. */\nexport function formatProjectContext(\n context: ProjectContext,\n options: FormatProjectContextOptions = {},\n): string {\n const parts: string[] = [];\n const { summary, memories, prompts, project } = context;\n\n if (summary || memories.length > 0) {\n parts.push(`## Project Knowledge: ${project}\\n`);\n if (summary?.summary) parts.push(`${summary.summary}\\n`);\n if (summary?.key_insights.length) {\n parts.push('Key Insights:');\n for (const insight of summary.key_insights) parts.push(` - ${insight}`);\n parts.push('');\n }\n if (summary?.technical_decisions.length) {\n parts.push('Technical Decisions:');\n for (const decision of summary.technical_decisions) parts.push(` - ${decision}`);\n parts.push('');\n }\n if (!summary && memories.length > 0) {\n for (const memory of memories) {\n parts.push(`### Memory #${memory.id}`);\n if (memory.summary) parts.push(`${memory.summary}\\n`);\n if (memory.key_insights.length) {\n parts.push('Key Insights:');\n for (const insight of memory.key_insights) parts.push(` - ${insight}`);\n parts.push('');\n }\n if (memory.technical_decisions.length) {\n parts.push('Technical Decisions:');\n for (const decision of memory.technical_decisions) parts.push(` - ${decision}`);\n parts.push('');\n }\n }\n }\n if (summary && memories.length > 0) {\n parts.push('Recent Memory Entries:');\n for (const memory of memories) {\n if (memory.summary) parts.push(` - [memory #${memory.id}] ${memory.summary}`);\n }\n parts.push('');\n }\n }\n\n if (prompts.length > 0) {\n if (parts.length > 0) parts.push('---\\n');\n parts.push('## Recent Context\\n');\n for (const entry of prompts) {\n let metadata: PromptMetadata = {};\n try { metadata = JSON.parse(entry.metadata) as PromptMetadata; } catch {}\n parts.push(`### Interaction #${entry.id} — ${entry.tool} (${new Date(entry.timestamp).toLocaleDateString()})`);\n if (metadata.role) parts.push(`Role: ${metadata.role}`);\n const promptSummary = metadata.summary || (\n options.includePromptText || options.promptExcerptLength\n ? ''\n : entry.prompt.slice(0, 100).replace(/\\n/g, ' ')\n );\n if (promptSummary) parts.push(promptSummary);\n if (metadata.key_insights?.length) {\n for (const insight of metadata.key_insights) parts.push(` - ${insight}`);\n }\n if (options.includePromptText) {\n parts.push('```\\n' + entry.prompt.slice(0, 1000) + (entry.prompt.length > 1000 ? '\\n...' : '') + '\\n```');\n } else if (options.promptExcerptLength) {\n const excerpt = entry.prompt.slice(0, options.promptExcerptLength);\n parts.push(`Prompt: ${excerpt}${entry.prompt.length > options.promptExcerptLength ? '...' : ''}`);\n }\n if (options.responseExcerptLength && entry.response) {\n const response = entry.response.slice(0, options.responseExcerptLength);\n parts.push(`Response: ${response}${entry.response.length > options.responseExcerptLength ? '...' : ''}`);\n }\n parts.push('');\n }\n }\n\n if (parts.length === 0) return options.emptyMessage ?? `No relevant context found for project \"${project}\".`;\n return parts.join('\\n').trimEnd();\n}\n","import http from 'http';\nimport { URL } from 'url';\nimport { PhDB, defaultPath } from '../db/index.js';\nimport { load as loadConfig } from '../config/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport { getEmbeddings } from '../embedding/index.js';\nimport { syncHash } from '../utils/syncHash.js';\nimport { timingSafeEqual } from 'crypto';\n\nexport async function runServer(port: number = 3001, host: string = '0.0.0.0'): Promise<void> {\n const cfg = loadConfig();\n const dbPath = process.env.PH_DB ?? cfg.dbPath ?? defaultPath();\n const db = new PhDB(dbPath);\n\n const server = http.createServer(createRequestHandler(db, cfg));\n\n return new Promise((resolve) => {\n server.listen(port, host, () => {\n console.error(`ph server listening on http://${host}:${port}`);\n resolve();\n });\n });\n}\n\n/**\n * Builds the request handler for a PhDB + config. Exported for testability\n * (SPEC-ISSUES-013: auth enforcement lives here).\n */\nexport function createRequestHandler(db: PhDB, cfg: PhConfig) {\n return async (req: http.IncomingMessage, res: http.ServerResponse): Promise<void> => {\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n const url = new URL(req.url || '/', `http://${req.headers.host || 'localhost'}`);\n\n // Auth gate (SPEC-ISSUES-013): when remoteApiKey is configured, every\n // endpoint except /health requires `Authorization: Bearer <key>`.\n if (url.pathname !== '/health' && !authorized(req, cfg)) {\n json(res, 401, { error: 'unauthorized' });\n return;\n }\n\n try {\n const body = await readBody(req);\n await route(req, res, body, db, cfg);\n } catch (err) {\n json(res, 500, { error: (err as Error).message });\n }\n };\n}\n\nfunction authorized(req: http.IncomingMessage, cfg: PhConfig): boolean {\n if (!cfg.remoteApiKey) return true;\n const expected = `Bearer ${cfg.remoteApiKey}`;\n const a = Buffer.from(req.headers.authorization ?? '');\n const b = Buffer.from(expected);\n return a.length === b.length && timingSafeEqual(a, b);\n}\n\nasync function route(req: http.IncomingMessage, res: http.ServerResponse, body: string, db: PhDB, cfg: PhConfig): Promise<void> {\n const url = new URL(req.url || '/', `http://${req.headers.host || 'localhost'}`);\n const path = url.pathname;\n const method = req.method || 'GET';\n\n if (method === 'GET' && path === '/health') {\n return json(res, 200, { status: 'ok', dbPath: db.dbPath });\n }\n\n if (method === 'POST' && path === '/api/prompts/search') {\n const { query, tool, project, role, tag, since, until, limit = 10 } = JSON.parse(body);\n const results = db.search({\n query,\n tool,\n project,\n role,\n tag,\n ...(since ? { since: new Date(since) } : {}),\n ...(until ? { until: new Date(until) } : {}),\n limit,\n });\n return json(res, 200, { prompts: results });\n }\n\n if (method === 'POST' && path === '/api/prompts/by-id') {\n const { id } = JSON.parse(body);\n const entry = db.getById(id);\n if (!entry) return json(res, 404, { error: `Prompt #${id} not found` });\n return json(res, 200, { prompt: entry });\n }\n\n if (method === 'POST' && path === '/api/prompts/semantic') {\n const { query, project, limit = 5 } = JSON.parse(body);\n if (!query) return json(res, 400, { error: 'query is required' });\n\n const ollamaUrl = cfg.ollamaUrl ?? 'http://localhost:11434';\n const model = cfg.ollamaEmbedModel ?? 'nomic-embed-text-v2-moe';\n const [queryVec] = await getEmbeddings([query], ollamaUrl, model, 1);\n if (!queryVec) return json(res, 500, { error: 'Failed to generate embedding' });\n\n const filtered = db.searchSemantic(queryVec, limit, project);\n\n return json(res, 200, { prompts: filtered });\n }\n\n if (method === 'POST' && path === '/api/sync/push') {\n const { prompts } = JSON.parse(body);\n if (!Array.isArray(prompts)) return json(res, 400, { error: 'prompts must be an array' });\n\n let imported = 0;\n let skipped = 0;\n const errors: string[] = [];\n\n for (const p of prompts) {\n try {\n const hash = syncHash(p);\n const existing = db.getPromptBySyncHash(hash);\n if (existing) { skipped++; continue; }\n\n const metaObj = { ...JSON.parse(p.metadata || '{}'), sync_hash: hash };\n db.insert({\n timestamp: p.timestamp || new Date().toISOString(),\n tool: p.tool || 'unknown',\n prompt: p.prompt || '',\n response: p.response || '',\n args: p.args || '',\n workdir: p.workdir || '',\n hostname: p.hostname || '',\n exit_code: p.exit_code ?? 0,\n metadata: JSON.stringify(metaObj),\n });\n imported++;\n } catch (e) {\n errors.push((e as Error).message);\n }\n }\n\n return json(res, 200, { imported, skipped, errors });\n }\n\n if (method === 'POST' && path === '/api/sync/pull') {\n const { since } = JSON.parse(body);\n const limit = 10000;\n const results = since\n ? db.getPromptsSince(since, limit)\n : db.getAllPrompts(limit);\n return json(res, 200, { prompts: results, hasMore: results.length >= limit });\n }\n\n if (method === 'POST' && path === '/api/memories/search') {\n const { project, limit = 10 } = JSON.parse(body);\n const memories = project\n ? db.searchMemories(project, limit)\n : [];\n return json(res, 200, { memories });\n }\n\n if (method === 'POST' && path === '/api/memories/summary') {\n const { project } = JSON.parse(body);\n if (!project) return json(res, 400, { error: 'project is required' });\n const memories = db.searchMemories(project, 5);\n return json(res, 200, { memories });\n }\n\n if (method === 'GET' && path === '/api/stats') {\n const { total, totalMemories, byTool } = db.getStats();\n return json(res, 200, { total, totalMemories, byTool });\n }\n\n json(res, 404, { error: `Not found: ${method} ${path}` });\n}\n\nfunction json(res: http.ServerResponse, status: number, data: unknown): void {\n res.writeHead(status, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(data));\n}\n\nfunction readBody(req: http.IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n if (req.method === 'GET') return resolve('');\n const chunks: Buffer[] = [];\n req.on('data', (chunk: Buffer) => chunks.push(chunk));\n req.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));\n req.on('error', reject);\n });\n}\n","import { createHash } from 'crypto';\n\n/**\n * Shared sync dedup key (SPEC-010).\n * Previously duplicated as inline sha256 in server/index.ts and\n * commands/remote.ts (SPEC-ISSUES-012): the two copies could drift.\n *\n * Backward compatible (SPEC-ISSUES-012): entries WITHOUT args hash exactly as\n * the legacy `tool|prompt|response` format, so existing sync_hash values are\n * preserved and nothing is re-pushed. Entries WITH args include them — two runs\n * of the same tool+prompt with different args are distinct interactions and\n * must NOT collapse on pull.\n */\nexport function syncHash(entry: { tool: string; prompt: string; response: string; args?: string }): string {\n const body = entry.args\n ? `${entry.tool}|${entry.prompt}|${entry.response}|${entry.args}`\n : `${entry.tool}|${entry.prompt}|${entry.response}`;\n return createHash('sha256').update(body).digest('hex');\n}\n","import { PhDB } from '../db/index.js';\nimport { load as loadConfig, save as saveConfig } from '../config/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport type { PromptEntry } from '../types.js';\nimport { syncHash } from '../utils/syncHash.js';\n\nfunction remoteUrl(cfg: PhConfig): string {\n return process.env.PH_REMOTE_URL || cfg.remoteUrl || '';\n}\n\nexport async function cmdRemote(dbPath: string, args: string[]): Promise<void> {\n const cfg = loadConfig();\n const url = remoteUrl(cfg);\n if (!url) {\n process.stderr.write('ph: remote not configured. Set PH_REMOTE_URL env or: ph config set remoteUrl <url>\\n');\n process.exit(1);\n }\n\n const sub = args[0];\n switch (sub) {\n case 'push':\n await push(dbPath, cfg, url);\n break;\n case 'pull':\n await pull(dbPath, cfg, url);\n break;\n case 'status':\n await status(dbPath, cfg, url);\n break;\n default:\n process.stdout.write(`ph remote commands:\n push Push new local prompts to remote\n pull Pull remote prompts and merge into local\n status Show sync status\n\nRemote: ${url}\\n`);\n }\n}\n\nasync function push(dbPath: string, cfg: PhConfig, url: string): Promise<void> {\n const db = new PhDB(dbPath);\n const since = cfg.remoteLastPush || '1970-01-01T00:00:00.000Z';\n const prompts = db.getPromptsSince(since, 5000);\n if (prompts.length === 0) {\n process.stdout.write('Nothing to push.\\n');\n db.close();\n return;\n }\n\n process.stdout.write(`Pushing ${prompts.length} prompts to ${url}...\\n`);\n\n try {\n const res = await fetch(`${url}/api/sync/push`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(cfg.remoteApiKey ? { Authorization: `Bearer ${cfg.remoteApiKey}` } : {}),\n },\n body: JSON.stringify({ prompts }),\n });\n\n if (!res.ok) {\n const err = await res.text();\n throw new Error(`Remote error ${res.status}: ${err}`);\n }\n\n const result = await res.json() as { imported: number; skipped: number; errors: string[] };\n process.stdout.write(`Imported: ${result.imported}, Skipped: ${result.skipped}\\n`);\n if (result.errors.length > 0) {\n result.errors.forEach(e => process.stderr.write(` Error: ${e}\\n`));\n }\n\n const maxTs = prompts.reduce((max, p) => p.timestamp > max ? p.timestamp : max, '');\n cfg.remoteLastPush = maxTs;\n saveConfig(cfg);\n process.stdout.write(`Push timestamp saved.\\n`);\n } catch (err) {\n process.stderr.write(`ph: push failed: ${(err as Error).message}\\n`);\n process.exit(1);\n } finally {\n db.close();\n }\n}\n\nasync function pull(dbPath: string, cfg: PhConfig, url: string): Promise<void> {\n const db = new PhDB(dbPath);\n const since = cfg.remoteLastPull || '';\n\n process.stdout.write(`Pulling from ${url}${since ? ` (since ${since})` : ''}...\\n`);\n\n try {\n const res = await fetch(`${url}/api/sync/pull`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(cfg.remoteApiKey ? { Authorization: `Bearer ${cfg.remoteApiKey}` } : {}),\n },\n body: JSON.stringify({ since: since || undefined }),\n });\n\n if (!res.ok) {\n const err = await res.text();\n throw new Error(`Remote error ${res.status}: ${err}`);\n }\n\n const result = await res.json() as { prompts: PromptEntry[]; hasMore: boolean };\n if (result.prompts.length === 0) {\n process.stdout.write('No new prompts on remote.\\n');\n db.close();\n return;\n }\n\n let imported = 0;\n let skipped = 0;\n for (const p of result.prompts) {\n const hash = syncHash(p);\n const existing = db.getPromptBySyncHash(hash);\n if (existing) { skipped++; continue; }\n\n const metaObj = { ...JSON.parse(p.metadata || '{}'), sync_hash: hash };\n db.insert({\n timestamp: p.timestamp || new Date().toISOString(),\n tool: p.tool || 'unknown',\n prompt: p.prompt || '',\n response: p.response || '',\n args: p.args || '',\n workdir: p.workdir || '',\n hostname: p.hostname || '',\n exit_code: p.exit_code ?? 0,\n metadata: JSON.stringify(metaObj),\n });\n imported++;\n }\n\n process.stdout.write(`Imported: ${imported}, Skipped (already local): ${skipped}\\n`);\n\n const maxTs = result.prompts.reduce((max: string, p: PromptEntry) => p.timestamp > max ? p.timestamp : max, '');\n cfg.remoteLastPull = maxTs;\n saveConfig(cfg);\n } catch (err) {\n process.stderr.write(`ph: pull failed: ${(err as Error).message}\\n`);\n process.exit(1);\n } finally {\n db.close();\n }\n}\n\nasync function status(dbPath: string, cfg: PhConfig, url: string): Promise<void> {\n const db = new PhDB(dbPath);\n\n const localTotal = db.getPromptCount();\n const lastPush = cfg.remoteLastPush || 'never';\n const lastPull = cfg.remoteLastPull || 'never';\n\n const pending = cfg.remoteLastPush\n ? db.getPromptCountSince(cfg.remoteLastPush)\n : localTotal;\n\n process.stdout.write(`Remote: ${url}\\n`);\n process.stdout.write(`Local total: ${localTotal} prompts\\n`);\n process.stdout.write(`Last push: ${lastPush}\\n`);\n process.stdout.write(`Last pull: ${lastPull}\\n`);\n process.stdout.write(`Pending: ${pending} prompts to push\\n`);\n db.close();\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 { FilterPanel } from './FilterPanel.js';\nimport { applyFilters, parseMetadata as parseMeta, ROLE_COLOR } from './filtering.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';\nimport { load as loadConfig, save as saveConfig } from '../config/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport { wrapTextLines, buildRichLines } from '../utils/syntaxHighlight.js';\nimport type { RichLine } from '../utils/syntaxHighlight.js';\n\n// ─── Types ────────────────────────────────────────────────────────────────────\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 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 hasProject(entry: PromptEntry | undefined): boolean {\n if (!entry) return false;\n const meta = parseMeta(entry.metadata);\n return Boolean(meta.project);\n}\n\nconst SESSION_GAP_MS = 2 * 60 * 60 * 1000;\n\nfunction formatDateLabel(ts: string): string {\n try {\n const d = new Date(ts);\n const months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];\n return `${months[d.getMonth()]} ${d.getDate()}`;\n } catch {\n return ts.slice(0, 10);\n }\n}\n\nfunction needsSessionSeparator(entries: PromptEntry[], idx: number): boolean {\n if (idx <= 0) return false;\n const prev = new Date(entries[idx - 1].timestamp).getTime();\n const curr = new Date(entries[idx].timestamp).getTime();\n return (prev - curr) > SESSION_GAP_MS;\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' | 'memory'>(entry.response ? 'response' : 'prompt');\n const [scrollOffset, setScrollOffset] = useState(0);\n const [copied, setCopied] = useState(false);\n\n const switchTab = (tab: 'prompt' | 'response' | 'memory') => {\n setActiveTab(tab);\n setScrollOffset(0);\n };\n\n const contentWidth = Math.max(10, termWidth - 4);\n const text = activeTab === 'prompt' ? entry.prompt : (entry.response || '(no response captured)');\n\n const lines = useMemo((): RichLine[] => {\n if (activeTab === 'prompt' || activeTab === 'response') {\n return buildRichLines(text, contentWidth);\n }\n\n // Memory tab logic\n const memLines: RichLine[] = [];\n const push = (t: string) => memLines.push({ segments: [{ text: t }] });\n if (meta.summary) {\n push('SUMMARY:');\n for (const l of wrapTextLines(meta.summary, contentWidth)) push(l);\n push('');\n }\n if (meta.key_insights && meta.key_insights.length > 0) {\n push('KEY INSIGHTS:');\n for (const insight of meta.key_insights) {\n for (const l of wrapTextLines(`• ${insight}`, contentWidth)) push(l);\n }\n }\n if (memLines.length === 0) push('(no AI analysis found - run ph analyze)');\n return memLines;\n }, [activeTab, text, contentWidth, meta]);\n\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' || char === '3') {\n if (char === '1') switchTab('prompt');\n else if (char === '2') switchTab('response');\n else if (char === '3') switchTab('memory');\n else switchTab(activeTab === 'prompt' ? 'response' : activeTab === 'response' ? 'memory' : 'prompt');\n }\n else if (char === 'y') {\n const copyText = activeTab === 'memory'\n ? lines.map(l => l.segments.map(s => s.text).join('')).join('\\n')\n : text;\n copyToClipboard(copyText);\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={activeTab === 'prompt'}>\n {activeTab === 'prompt' ? '●' : '○'} 1:PROMPT\n </Text>\n <Text> </Text>\n <Text color={theme.primary} bold underline={activeTab === 'response'}>\n {activeTab === 'response' ? '●' : '○'} 2:RESPONSE\n </Text>\n <Text> </Text>\n <Text color={theme.primary} bold underline={activeTab === 'memory'}>\n {activeTab === 'memory' ? '●' : '○'} 3:MEMORY\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}>\n {line.segments.length > 0\n ? line.segments.map((seg, j) => (\n <Text key={j} color={seg.color} dimColor={seg.dim}>{seg.text}</Text>\n ))\n : ' '}\n </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// ─── ProviderPicker ────────────────────────────────────────────────────────────\n\nconst KNOWN_PROVIDERS: { key: string; label: string; tool: string }[] = [\n { key: '1', label: 'claude', tool: 'claude' },\n { key: '2', label: 'gemini', tool: 'gemini' },\n { key: '3', label: 'opencode', tool: 'opencode' },\n { key: '4', label: 'codex', tool: 'codex' },\n { key: '5', label: 'ollama', tool: 'ollama' },\n { key: '6', label: 'chatgpt', tool: 'chatgpt' },\n];\n\ninterface ProviderPickerProps {\n entry: PromptEntry;\n onPick: (tool: string, prompt: string) => void;\n onClose: () => void;\n theme: Theme;\n}\n\nconst ProviderPicker: React.FC<ProviderPickerProps> = ({ entry, onPick, onClose, theme }) => {\n useInput((char) => {\n if (char === 'q' || char === '\\x1b') { onClose(); return; }\n const provider = KNOWN_PROVIDERS.find(p => p.key === char);\n if (provider) {\n onPick(provider.tool, entry.prompt);\n }\n });\n\n return (\n <Box flexDirection=\"column\" padding={2}>\n <Text bold color={theme.primary}>Send prompt #{entry.id} to:</Text>\n <Box marginTop={1} flexDirection=\"column\">\n {KNOWN_PROVIDERS.map(p => (\n <Text key={p.key}>\n <Text color={theme.warning}>{p.key}</Text>\n <Text>: {p.label}</Text>\n </Text>\n ))}\n </Box>\n <Box marginTop={1}>\n <Text dimColor>Pick a number · q to cancel</Text>\n </Box>\n </Box>\n );\n};\n\n// ─── SettingsView ─────────────────────────────────────────────────────────────\n\nconst SETTING_FIELDS: { key: keyof PhConfig; label: string; type: 'boolean' | 'string' | 'number' }[] = [\n { key: 'backgroundAnalysis', label: 'Auto-analysis on capture', type: 'boolean' },\n { key: 'ollamaUrl', label: 'Ollama URL', type: 'string' },\n { key: 'ollamaModel', label: 'Ollama model (analysis)', type: 'string' },\n { key: 'ollamaEmbedModel', label: 'Ollama model (embeddings)', type: 'string' },\n { key: 'analyzeProvider', label: 'Analysis provider', type: 'string' },\n { key: 'filterMinLength', label: 'Min prompt length filter', type: 'number' },\n { key: 'filterMinRelevance', label: 'Min relevance filter', type: 'number' },\n];\n\ninterface SettingsViewProps {\n onClose: () => void;\n theme: Theme;\n}\n\nconst SettingsView: React.FC<SettingsViewProps> = ({ onClose, theme }) => {\n const [cfg, setCfg] = useState<PhConfig>(() => loadConfig());\n const [cursor, setCursor] = useState(0);\n const [dirty, setDirty] = useState(false);\n const [saved, setSaved] = useState(false);\n\n const toggleField = (key: keyof PhConfig) => {\n const updated = { ...cfg };\n if (key === 'backgroundAnalysis') {\n updated[key] = !(cfg[key] as boolean);\n }\n setCfg(updated);\n setDirty(true);\n setSaved(false);\n };\n\n const save = () => {\n saveConfig(cfg);\n setDirty(false);\n setSaved(true);\n setTimeout(() => setSaved(false), 2000);\n };\n\n useInput((char, key) => {\n if (key.escape) { onClose(); return; }\n if (char === 'q') { onClose(); return; }\n if (char === 's' && dirty) { save(); return; }\n\n if (key.upArrow) setCursor(c => Math.max(0, c - 1));\n if (key.downArrow) setCursor(c => Math.min(SETTING_FIELDS.length - 1, c + 1));\n\n if (key.return || char === ' ') {\n const field = SETTING_FIELDS[cursor];\n if (!field) return;\n if (field.type === 'boolean') {\n toggleField(field.key);\n }\n }\n });\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Box marginBottom={1}>\n <Text color={theme.primary} bold>Settings </Text>\n {dirty && <Text color={theme.warning}>modified </Text>}\n {saved && <Text color={theme.success}>✓ saved</Text>}\n </Box>\n\n <Box borderStyle=\"single\" borderColor={theme.dim} flexDirection=\"column\" padding={1}>\n {SETTING_FIELDS.map((field, i) => {\n const isCur = i === cursor;\n const val = cfg[field.key];\n let display: string;\n if (field.type === 'boolean') {\n display = val ? 'true' : 'false';\n } else {\n display = val !== undefined ? String(val) : '(default)';\n }\n const valColor = field.type === 'boolean'\n ? (val ? theme.success : theme.dim)\n : (val !== undefined ? 'white' : theme.dim);\n\n return (\n <Box key={field.key}>\n <Text bold={isCur} color={isCur ? theme.primary : theme.dim}>\n {isCur ? '❯ ' : ' '}\n </Text>\n <Text color={isCur ? theme.primary : 'white'}>\n {field.label}\n </Text>\n <Text>{' '.repeat(Math.max(1, 30 - field.label.length))}</Text>\n <Text color={valColor} bold={field.type === 'boolean' && isCur}>\n {display}\n </Text>\n {field.type === 'boolean' && isCur && (\n <Text color={theme.warning}> [Enter toggle]</Text>\n )}\n </Box>\n );\n })}\n </Box>\n\n <Box marginTop={1}>\n <Text dimColor>\n ↑↓ navigate · Enter toggle boolean · {dirty ? 's save · ' : ''}q/ESC close\n </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 const [archiveCount] = useState(() => db.getArchiveStats().total);\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 const [showSettings, setShowSettings] = 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 [providerPicking, setProviderPicking] = 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 4n-1 lines (3 per entry + 1 separator, except last).\n // n = floor((termHeight - 4 + 1) / 4) = floor((termHeight - 3) / 4)\n const PAGE_SIZE = Math.max(1, Math.floor((termHeight - 3) / 4));\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 || showSettings || rerunning || providerPicking) 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 === 'p') { if (entries[cursor]) setProviderPicking(entries[cursor]); }\n else if (char === 'x') { if (entries[cursor]) handleDelete(entries[cursor]); }\n else if (char === 'f') { setFilterPanel(true); }\n else if (char === 'o') { setShowSettings(true); }\n else if (char === 'c') { setActiveFilters({}); setTextFilter(''); setCursor(0); setScrollOffset(0); }\n else if (char === 'C') {\n // Chat: launch tool with project context injected\n const entry = entries[cursor];\n if (!entry) return;\n const meta = parseMeta(entry.metadata);\n const project = meta.project;\n if (!project) return;\n const memories = db.searchMemories(project, 3);\n const recent = db.getProjectMemory(project, 5);\n const ctx: string[] = [];\n if (memories.length > 0) {\n ctx.push(`## Project Knowledge: ${project}`);\n for (const mem of memories) {\n if (mem.summary) ctx.push(`\\n${mem.summary}`);\n if (mem.key_insights.length > 0) {\n ctx.push('\\nKey Insights:');\n for (const i of mem.key_insights) ctx.push(` - ${i}`);\n }\n if (mem.technical_decisions.length > 0) {\n ctx.push('\\nTechnical Decisions:');\n for (const d of mem.technical_decisions) ctx.push(` - ${d}`);\n }\n }\n }\n if (recent.length > 0) {\n ctx.push('\\n---\\n## Recent Context');\n for (const p of recent) {\n const pm = parseMeta(p.metadata);\n ctx.push(`\\n- #${p.id}: ${pm.summary || p.prompt.slice(0, 100).replace(/\\n/g, ' ')}`);\n }\n }\n const fullPrompt = `Context from project \"${project}\":\\n\\n${ctx.join('\\n')}\\n\\n---\\n\\n${entry.prompt}`;\n onRerun?.(entry.tool, fullPrompt);\n exit();\n }\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 (showSettings) {\n mainContent = (\n <SettingsView\n onClose={() => setShowSettings(false)}\n theme={theme}\n />\n );\n } else 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 (providerPicking) {\n mainContent = (\n <ProviderPicker\n entry={providerPicking}\n onPick={(tool, prompt) => {\n onRerun?.(tool, prompt);\n setProviderPicking(null);\n exit();\n }}\n onClose={() => setProviderPicking(null)}\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 const absIdx = pageStart + i;\n const isNewSession = needsSessionSeparator(entries, absIdx);\n return (\n <React.Fragment key={entry.id}>\n {isNewSession && (\n <Box>\n <Text color={theme.dim}>\n {'╌'.repeat(2)} {formatDateLabel(entry.timestamp)} {'╌'.repeat(leftPaneWidth - 4 - formatDateLabel(entry.timestamp).length)}\n </Text>\n </Box>\n )}\n <ListEntry\n entry={entry}\n isSelected={absIdx === cursor}\n paneWidth={leftPaneWidth}\n theme={theme}\n />\n {i < visible.length - 1 && !needsSessionSeparator(entries, absIdx + 1) && (\n <Box>\n <Text color={theme.dim}>{'·'.repeat(Math.max(1, leftPaneWidth - 2))}</Text>\n </Box>\n )}\n </React.Fragment>\n );\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 key={entries[cursor]?.id ?? 'empty'}\n entry={entries[cursor] ?? null}\n paneWidth={termWidth - leftPaneWidth - 1}\n paneHeight={termHeight - 3}\n isFocused={previewFocused}\n theme={theme}\n getProjectMemories={(p) => db.searchMemories(p, 3)}\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 const absIdx = pageStart + i;\n const isNewSession = needsSessionSeparator(entries, absIdx);\n return (\n <React.Fragment key={entry.id}>\n {isNewSession && (\n <Box>\n <Text color={theme.dim}>\n {'╌'.repeat(2)} {formatDateLabel(entry.timestamp)} {'╌'.repeat(termWidth - 4 - formatDateLabel(entry.timestamp).length)}\n </Text>\n </Box>\n )}\n <ListEntry\n entry={entry}\n isSelected={absIdx === cursor}\n paneWidth={termWidth}\n theme={theme}\n />\n {i < visible.length - 1 && !needsSessionSeparator(entries, absIdx + 1) && (\n <Box>\n <Text color={theme.dim}>{'·'.repeat(Math.max(1, termWidth - 2))}</Text>\n </Box>\n )}\n </React.Fragment>\n );\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 archiveCount={archiveCount}\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 isWide={isWide}\n hasDetail={Boolean(entries[cursor] && isWide)}\n hasProject={hasProject(entries[cursor])}\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 archiveCount?: 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 archiveCount,\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 {archiveCount !== undefined && archiveCount > 0 ? <Text color=\"yellow\"> ({archiveCount} archived)</Text> : null}\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.5.0\",\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 \"publishConfig\": {\n \"access\": \"public\",\n \"registry\": \"https://registry.npmjs.org/\",\n \"provenance\": true\n },\n \"release\": {\n \"branches\": [\n \"main\"\n ],\n \"plugins\": [\n \"@semantic-release/commit-analyzer\",\n \"@semantic-release/release-notes-generator\",\n \"@semantic-release/changelog\",\n \"@semantic-release/npm\",\n \"@semantic-release/github\",\n [\n \"@semantic-release/git\",\n {\n \"assets\": [\n \"package.json\",\n \"CHANGELOG.md\"\n ],\n \"message\": \"chore(release): ${nextRelease.version} [skip ci]\\n\\n${nextRelease.notes}\"\n }\n ]\n ]\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 \"eval:retrieval\": \"tsx scripts/eval-context-retrieval.ts\"\n },\n \"dependencies\": {\n \"@gi4nks/ink\": \"^1.5.0\",\n \"@lydell/node-pty\": \"^1.2.0-beta.3\",\n \"@modelcontextprotocol/sdk\": \"^1.29.0\",\n \"better-sqlite3\": \"^12.8.0\",\n \"ink\": \"^7.0.5\",\n \"react\": \"^19.2.7\",\n \"sqlite-vec\": \"^0.1.9\",\n \"zod\": \"^4.3.6\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.39.5\",\n \"@semantic-release/changelog\": \"^6.0.3\",\n \"@semantic-release/git\": \"^10.0.1\",\n \"@semantic-release/github\": \"^12.0.8\",\n \"@semantic-release/npm\": \"^13.1.5\",\n \"@types/better-sqlite3\": \"^7.6.13\",\n \"@types/node\": \"^25.9.3\",\n \"@types/react\": \"^19.2.7\",\n \"@typescript-eslint/eslint-plugin\": \"^8.58.2\",\n \"@typescript-eslint/parser\": \"^8.58.2\",\n \"eslint\": \"^9.39.5\",\n \"eslint-plugin-react\": \"^7.37.5\",\n \"eslint-plugin-react-hooks\": \"^7.0.1\",\n \"semantic-release\": \"^25.0.3\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.21.0\",\n \"typescript\": \"^6.0.3\",\n \"vitest\": \"^4.1.8\"\n }\n}\n","import React, { useMemo } from 'react';\nimport { AppFooter, THEMES } from '@gi4nks/ink';\nimport type { HintItem } from '@gi4nks/ink';\n\ninterface FooterProps {\n cursor: number;\n total: number;\n copiedId?: number | null;\n hasProject?: boolean;\n isWide?: boolean;\n hasDetail?: boolean;\n theme?: string;\n}\n\nexport const Footer: React.FC<FooterProps> = ({\n cursor,\n total,\n copiedId,\n hasProject,\n isWide,\n hasDetail,\n theme: themeName = 'dark',\n}) => {\n const theme = THEMES[themeName] || THEMES.dark;\n const position = total > 0 ? `${cursor + 1}/${total}` : '0/0';\n\n const hints = useMemo<Array<HintItem | '|'>>(() => {\n const base: Array<HintItem | '|'> = [\n { key: '↑↓', description: 'nav' },\n ];\n if (isWide) base.push({ key: 'Tab', description: 'pane' });\n if (hasDetail) base.push({ key: '1/2/3', description: 'tab' });\n base.push(\n { key: 'y', description: 'copy' },\n { key: 's', description: '★' },\n { key: 'e', description: 'edit' },\n );\n if (hasProject) base.push({ key: 'C', description: 'chat' });\n base.push({ key: 'r', description: 'rerun' });\n base.push({ key: 'p', description: 'provider' });\n base.push('|');\n base.push(\n { key: 'x', description: 'del' },\n { key: '/', description: 'search' },\n { key: 'f', description: 'filter' },\n { key: 'o', description: 'settings' },\n { key: 'q', description: 'quit' },\n );\n return base;\n }, [isWide, hasDetail, hasProject]);\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","import React, { useMemo, useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport type { PromptEntry } from '../types.js';\nimport type { ActiveFilters } from './Header.js';\nimport { buildFilterOptions, ROLE_COLOR, toggleFilter } from './filtering.js';\nimport type { FilterOption } from './filtering.js';\nimport type { Theme } from './themes.js';\n\ninterface Props {\n allEntries: PromptEntry[];\n active: ActiveFilters;\n onUpdate: (filters: ActiveFilters) => void;\n onClose: () => void;\n theme: Theme;\n}\n\nexport const FilterPanel: React.FC<Props> = ({ allEntries, active, onUpdate, onClose, theme }) => {\n const options = useMemo<FilterOption[]>(() => buildFilterOptions(allEntries, active), [allEntries, active]);\n const [cursor, setCursor] = useState(0);\n const visibleCount = Math.min(options.length, 16);\n const scrollOffset = Math.max(0, Math.min(cursor - Math.floor(visibleCount / 2), options.length - visibleCount));\n const visible = options.slice(Math.max(0, scrollOffset), scrollOffset + visibleCount);\n\n useInput((char, key) => {\n if (key.escape) { onClose(); return; }\n if (char === 'c') { onUpdate({}); return; }\n if (key.return || char === ' ') {\n const option = options[cursor];\n if (!option) return;\n onUpdate(toggleFilter(active, option));\n return;\n }\n if (key.upArrow) setCursor(value => Math.max(0, value - 1));\n if (key.downArrow) setCursor(value => Math.min(options.length - 1, value + 1));\n if (key.pageUp) setCursor(value => Math.max(0, value - visibleCount));\n if (key.pageDown) setCursor(value => Math.min(options.length - 1, value + visibleCount));\n if (char && /^[a-z]$/.test(char)) {\n const index = options.findIndex((option, i) => i > cursor && option.category[0] === char);\n if (index !== -1) setCursor(index);\n }\n });\n\n const activeCount = Object.values(active).filter(value => value !== undefined && value !== false).length;\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Box marginBottom={1}>\n <Text color={theme.primary} bold>Filters </Text>\n {activeCount > 0 ? <Text color={theme.warning}>{activeCount} active </Text> : <Text dimColor>none active </Text>}\n {activeCount > 0 && <Text dimColor>(c clear)</Text>}\n </Box>\n <Box borderStyle=\"single\" borderColor={theme.dim} flexDirection=\"column\" padding={1} minHeight={18}>\n <Box flexDirection=\"column\">\n {visible.map((option, index) => {\n const absoluteIndex = Math.max(0, scrollOffset) + index;\n const isCurrent = absoluteIndex === cursor;\n const categoryColor = option.category === 'project' ? 'blue'\n : option.category === 'language' ? 'green'\n : option.category === 'role' ? ROLE_COLOR[option.label] || 'cyan'\n : option.category === 'tool' ? 'yellow' : option.category === 'tag' ? 'cyan' : 'white';\n return (\n <Box key={`${option.category}-${option.label}`}>\n <Text bold={isCurrent} color={isCurrent ? theme.primary : theme.dim}>{isCurrent ? '❯ ' : ' '}</Text>\n <Text color={option.active ? theme.warning : categoryColor} bold={option.active || isCurrent}>\n {option.category}:{option.label}\n </Text>\n <Text dimColor> [{option.count}]</Text>\n {option.active && <Text color={theme.success}> ✓</Text>}\n </Box>\n );\n })}\n </Box>\n {options.length > visibleCount && <Box marginTop={1}><Text dimColor> {cursor + 1}/{options.length} · ↑↓ navigate · Enter toggle · c clear · ESC close</Text></Box>}\n </Box>\n <Box marginTop={1}><Text dimColor>↑↓ navigate · Enter toggle · c clear all · ESC close · letter jumps to category</Text></Box>\n </Box>\n );\n};\n","import type { PromptEntry, PromptMetadata } from '../types.js';\nimport type { ActiveFilters } from './Header.js';\nimport { extractTopic } from '../utils/extractTopic.js';\n\nexport const FILTER_CATEGORIES = ['project', 'language', 'role', 'tool', 'tag', 'starred', 'quality', 'relevance'] as const;\nexport type FilterCategory = (typeof FILTER_CATEGORIES)[number];\n\nexport const 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 function parseMetadata(raw: string): PromptMetadata {\n try { return JSON.parse(raw) as PromptMetadata; } catch { return {}; }\n}\n\nconst CODEX_RETRY_WINDOW_MS = 2 * 60 * 1000;\nconst CODEX_RETRY_MIN_PREFIX_LENGTH = 80;\n\nfunction displayTitle(entry: PromptEntry): string {\n return parseMetadata(entry.metadata).title || extractTopic(entry.prompt);\n}\n\nfunction normalizedPrompt(prompt: string): string {\n return prompt.trim().replace(/\\s+/g, ' ');\n}\n\n/** Hide an abandoned Codex prompt when the same request was retried and completed. */\nfunction collapseCodexRetries(entries: PromptEntry[]): PromptEntry[] {\n const buckets = new Map<string, PromptEntry[]>();\n for (const entry of entries) {\n if (entry.tool.toLowerCase() !== 'codex') continue;\n const key = `${entry.workdir}\\0${displayTitle(entry)}`;\n const bucket = buckets.get(key) ?? [];\n bucket.push(entry);\n buckets.set(key, bucket);\n }\n\n const hidden = new Set<number>();\n for (const bucket of buckets.values()) {\n const incomplete = bucket.filter(entry => !entry.response.trim());\n const completed = bucket.filter(entry => !!entry.response.trim());\n for (const pending of incomplete) {\n const pendingPrompt = normalizedPrompt(pending.prompt);\n if (pendingPrompt.length < CODEX_RETRY_MIN_PREFIX_LENGTH) continue;\n const pendingTime = Date.parse(pending.timestamp);\n if (!Number.isFinite(pendingTime)) continue;\n\n const retried = completed.some(candidate => {\n const candidateTime = Date.parse(candidate.timestamp);\n const candidatePrompt = normalizedPrompt(candidate.prompt);\n const delta = Math.abs(candidateTime - pendingTime);\n return Number.isFinite(candidateTime)\n && delta <= CODEX_RETRY_WINDOW_MS\n && candidatePrompt.length > pendingPrompt.length\n && candidatePrompt.startsWith(pendingPrompt);\n });\n if (retried) hidden.add(pending.id);\n }\n }\n\n return hidden.size ? entries.filter(entry => !hidden.has(entry.id)) : entries;\n}\n\nfunction getDistinctValues(entries: PromptEntry[], category: FilterCategory): string[] {\n const values = new Set<string>();\n for (const entry of entries) {\n if (category === 'tool') { values.add(entry.tool); continue; }\n const metadata = parseMetadata(entry.metadata);\n if (category === 'project' && metadata.project) values.add(metadata.project);\n if (category === 'language' && metadata.language) values.add(metadata.language);\n if (category === 'role' && metadata.role) values.add(metadata.role);\n if (category === 'tag') metadata.tags?.forEach(tag => values.add(tag));\n }\n return [...values].sort();\n}\n\nexport function applyFilters(entries: PromptEntry[], active: ActiveFilters, textFilter: string): PromptEntry[] {\n let result = collapseCodexRetries(entries);\n const hasActiveFilter = Object.values(active).some(value => value !== undefined && value !== false);\n if (hasActiveFilter) {\n result = result.filter(entry => {\n const metadata = parseMetadata(entry.metadata);\n if (active.tool && entry.tool !== active.tool) return false;\n if (active.project && metadata.project !== active.project) return false;\n if (active.language && metadata.language !== active.language) return false;\n if (active.role && metadata.role !== active.role) return false;\n if (active.tag && !metadata.tags?.includes(active.tag)) return false;\n if (active.starred && !metadata.starred) return false;\n if (active.minQuality !== undefined && (metadata.quality ?? 0) < active.minQuality) return false;\n if (active.minRelevance !== undefined && (metadata.relevance ?? 0) < active.minRelevance) return false;\n return true;\n });\n }\n\n if (textFilter) {\n const query = textFilter.toLowerCase();\n result = result.filter(entry => {\n const metadata = parseMetadata(entry.metadata);\n return entry.prompt.toLowerCase().includes(query)\n || entry.tool.toLowerCase().includes(query)\n || (metadata.project?.toLowerCase().includes(query) ?? false)\n || (metadata.role?.toLowerCase().includes(query) ?? false)\n || (metadata.tags?.some(tag => tag.toLowerCase().includes(query)) ?? false);\n });\n }\n return result;\n}\n\nexport interface FilterOption {\n category: FilterCategory;\n label: string;\n count: number;\n active: boolean;\n}\n\nexport function toggleFilter(active: ActiveFilters, option: FilterOption): ActiveFilters {\n if (option.category === 'starred') return { ...active, starred: !option.active || undefined };\n if (option.category === 'quality' || option.category === 'relevance') {\n const value = parseInt(option.label.replace(option.category === 'quality' ? 'Q ≥ ' : 'R ≥ ', ''), 10);\n return option.category === 'quality'\n ? { ...active, minQuality: option.active ? undefined : value }\n : { ...active, minRelevance: option.active ? undefined : value };\n }\n const filterKey = option.category as keyof Omit<ActiveFilters, 'starred' | 'minQuality' | 'minRelevance'>;\n if (option.active) {\n const updated = { ...active };\n delete updated[filterKey];\n return updated;\n }\n return { ...active, [filterKey]: option.label };\n}\n\nexport function buildFilterOptions(entries: PromptEntry[], active: ActiveFilters): FilterOption[] {\n const options: FilterOption[] = [];\n for (const category of FILTER_CATEGORIES) {\n if (category === 'starred') {\n const count = entries.filter(entry => parseMetadata(entry.metadata).starred).length;\n options.push({ category, label: '★ Only starred', count, active: !!active.starred });\n continue;\n }\n if (category === 'quality' || category === 'relevance') {\n const isQuality = category === 'quality';\n const activeValue = isQuality ? active.minQuality : active.minRelevance;\n const prefix = isQuality ? 'Q ≥ ' : 'R ≥ ';\n options.push({ category, label: `${prefix}${activeValue ?? '?'}`, count: 0, active: activeValue !== undefined });\n for (const value of [1,2,3,4,5,6,7,8,9,10]) {\n const count = entries.filter(entry => {\n const metadata = parseMetadata(entry.metadata);\n return ((isQuality ? metadata.quality : metadata.relevance) ?? 0) >= value;\n }).length;\n options.push({ category, label: `${prefix}${value}`, count, active: activeValue === value });\n }\n continue;\n }\n\n for (const value of getDistinctValues(entries, category)) {\n const count = entries.filter(entry => {\n const metadata = parseMetadata(entry.metadata);\n if (category === 'project') return metadata.project === value;\n if (category === 'language') return metadata.language === value;\n if (category === 'role') return metadata.role === value;\n if (category === 'tool') return entry.tool === value;\n if (category === 'tag') return metadata.tags?.includes(value) ?? false;\n return false;\n }).length;\n const activeValue = active[category as keyof Omit<ActiveFilters, 'starred' | 'minQuality' | 'minRelevance'>];\n options.push({ category, label: value, count, active: activeValue === value });\n }\n }\n return options;\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 const isEmpty = value === '';\n\n const bgColor = isActive ? theme.primary : theme.dim;\n\n return (\n <Box paddingX={1} paddingY={0}>\n <Text color={bgColor} bold={isActive}>\n {isActive ? '⌕' : '⌕'}\n </Text>\n <Text color={isActive ? 'white' : theme.dim}>\n {' '}{isEmpty ? (isActive ? '' : 'search (/)') : value}{isActive ? '█' : ''}\n </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 if (tool === 'opencode') return { char: '●', color: '#e040fb' };\n if (tool === 'codex') return { char: '●', color: '#74aa9c' };\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 hasAnalysis = Boolean(meta.summary || meta.role || (meta.tags && meta.tags.length > 0));\n const roleBar = meta.role ? ROLE_COLOR[meta.role] || theme.dim : theme.dim;\n const rawTitle = meta.title || extractTopic(entry.prompt);\n const displayPrompt = truncate(rawTitle, paneWidth - 5);\n\n let summaryLine = '';\n if (meta.summary) {\n summaryLine = truncate(meta.summary.replace(/\\n/g, ' '), paneWidth - 5);\n }\n\n return (\n <Box flexDirection=\"column\">\n <Box flexDirection=\"row\" width={paneWidth} overflow=\"hidden\">\n <Text color={roleBar}>│</Text>\n <Text color={indicator.color}> {indicator.char}</Text>\n <Text dimColor> {entry.tool.padEnd(8)}</Text>\n {meta.starred ? <Text color={theme.warning}>★</Text> : <Text> </Text>}\n {hasAnalysis ? <Text color={theme.success}>●</Text> : <Text dimColor>○</Text>}\n <Text>{' '}</Text>\n <Text dimColor>{hhmm} </Text>\n {role && <Text color={roleColor}>{role}</Text>}\n {meta.quality !== undefined && (\n <Text color={theme.success}> Q{meta.quality}</Text>\n )}\n {meta.relevance !== undefined && (\n <Text color={theme.warning}> R{meta.relevance}</Text>\n )}\n </Box>\n\n <Box flexDirection=\"row\">\n <Text color={roleBar}>│</Text>\n {isSelected ? (\n <Text inverse bold>\n {' '}{displayPrompt.padEnd(paneWidth - 3)}\n </Text>\n ) : (\n <Text>\n {' '}{displayPrompt}\n </Text>\n )}\n </Box>\n\n {summaryLine && (\n <Box flexDirection=\"row\">\n <Text color={roleBar}>│</Text>\n <Text dimColor> {summaryLine}</Text>\n </Box>\n )}\n </Box>\n );\n};\n","import React, { useState, useMemo } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport type { PromptEntry, PromptMetadata, MemoryEntry } from '../types.js';\nimport type { Theme } from './themes.js';\nimport { wrapTextLines, buildRichLines } from '../utils/syntaxHighlight.js';\nimport type { RichLine } from '../utils/syntaxHighlight.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 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 getProjectMemories?: (project: string) => MemoryEntry[];\n}\n\nexport const PreviewPane: React.FC<PreviewPaneProps> = ({\n entry,\n paneWidth,\n paneHeight,\n isFocused,\n theme,\n getProjectMemories,\n}) => {\n const [activeTab, setActiveTab] = useState<'prompt' | 'response' | 'memory'>(\n entry?.response ? 'response' : 'prompt'\n );\n const [scrollOffset, setScrollOffset] = useState(0);\n\n const switchTab = (tab: 'prompt' | 'response' | 'memory') => {\n setActiveTab(tab);\n setScrollOffset(0);\n };\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((): RichLine[] => {\n if (!entry) return [];\n if (activeTab === 'prompt') return buildRichLines(entry.prompt, contentWidth);\n if (activeTab === 'response') return buildRichLines(entry.response || '(no response captured)', contentWidth);\n\n // Memory tab\n const lines: RichLine[] = [];\n const push = (text: string) => lines.push({ segments: [{ text }] });\n\n if (meta.project && getProjectMemories) {\n const memories = getProjectMemories(meta.project);\n if (memories.length > 0) {\n push(`── Project Knowledge: ${meta.project} ──`);\n push('');\n for (const mem of memories) {\n if (mem.summary) {\n for (const l of wrapTextLines(mem.summary, contentWidth)) push(l);\n push('');\n }\n if (mem.key_insights.length > 0) {\n push('Key Insights:');\n for (const i of mem.key_insights) for (const l of wrapTextLines(` • ${i}`, contentWidth)) push(l);\n push('');\n }\n if (mem.technical_decisions.length > 0) {\n push('Technical Decisions:');\n for (const d of mem.technical_decisions) for (const l of wrapTextLines(` • ${d}`, contentWidth)) push(l);\n push('');\n }\n }\n push('── This Entry ──');\n push('');\n }\n }\n if (meta.summary) {\n for (const l of wrapTextLines(meta.summary, contentWidth)) push(l);\n push('');\n }\n if (meta.key_insights && meta.key_insights.length > 0) {\n for (const insight of meta.key_insights) {\n for (const l of wrapTextLines(`• ${insight}`, contentWidth)) push(l);\n }\n push('');\n }\n if (lines.length === 0) push('(no AI analysis - run ph analyze)');\n return lines;\n }, [entry, activeTab, contentWidth, meta, getProjectMemories]);\n\n const maxScroll = Math.max(0, allLines.length - contentHeight);\n\n useInput((_char, key) => {\n if (!isFocused) return;\n\n if (_char === '1') switchTab('prompt');\n if (_char === '2') switchTab('response');\n if (_char === '3') switchTab('memory');\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: RichLine[] = [...visibleLines];\n while (paddedLines.length < contentHeight) paddedLines.push({ segments: [{ text: ' ' }] });\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 const isMemoryActive = activeTab === 'memory';\n\n const tabPromptColor = isPromptActive && isFocused ? theme.primary : theme.dim;\n const tabResponseColor = isResponseActive && isFocused ? theme.primary : theme.dim;\n const tabMemoryColor = isMemoryActive && 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 ? '● ' : '○ '}1:PROMPT\n </Text>\n <Text>{' '}</Text>\n <Text\n color={tabResponseColor}\n bold={isResponseActive && isFocused}\n underline={isResponseActive && isFocused}\n >\n {isResponseActive ? '● ' : '○ '}2:RESPONSE\n </Text>\n <Text>{' '}</Text>\n <Text\n color={tabMemoryColor}\n bold={isMemoryActive && isFocused}\n underline={isMemoryActive && isFocused}\n >\n {isMemoryActive ? '● ' : '○ '}3:MEMORY\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}>\n {line.segments.length > 0\n ? line.segments.map((seg, j) => (\n <Text key={j} color={seg.color} dimColor={seg.dim}>{seg.text}</Text>\n ))\n : ' '}\n </Text>\n ))}\n\n {/* scroll-bot indicator */}\n <Text dimColor>{botIndicator}</Text>\n </Box>\n );\n};\n","export interface TextSegment {\n text: string;\n color?: string;\n dim?: boolean;\n}\n\nexport interface RichLine {\n segments: TextSegment[];\n}\n\nconst KEYWORDS = new Set([\n 'if', 'else', 'for', 'while', 'do', 'switch', 'case', 'break', 'continue',\n 'return', 'function', 'class', 'struct', 'interface', 'enum', 'type',\n 'const', 'let', 'var', 'import', 'export', 'from', 'default', 'async',\n 'await', 'yield', 'throw', 'try', 'catch', 'finally', 'new', 'delete',\n 'typeof', 'instanceof', 'void', 'null', 'undefined', 'true', 'false',\n 'this', 'super', 'extends', 'implements', 'package', 'namespace', 'using',\n 'def', 'in', 'not', 'is', 'and', 'or', 'with', 'as', 'pass', 'raise', 'lambda',\n 'pub', 'fn', 'let', 'mut', 'impl', 'trait', 'use', 'mod', 'where', 'ref',\n 'func', 'go', 'defer', 'select', 'chan', 'range', 'map',\n 'SELECT', 'FROM', 'WHERE', 'INSERT', 'UPDATE', 'DELETE', 'CREATE', 'TABLE',\n 'INTO', 'VALUES', 'SET', 'JOIN', 'LEFT', 'RIGHT', 'INNER', 'OUTER', 'ON',\n 'AND', 'OR', 'NOT', 'IN', 'AS', 'ORDER', 'BY', 'GROUP', 'HAVING', 'LIMIT', 'OFFSET',\n 'static', 'public', 'private', 'protected', 'readonly', 'abstract', 'virtual',\n 'override', 'final', 'sealed', 'internal', 'extern',\n 'module', 'requires', 'exports', 'opens', 'provides', 'to', 'transitive',\n 'match', 'enum', 'macro', 'unsafe',\n]);\n\nfunction tokenizeLine(line: string): TextSegment[] {\n const segments: TextSegment[] = [];\n let i = 0;\n\n while (i < line.length) {\n const rest = line.slice(i);\n\n const strMatch = rest.match(/^(\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*'|`(?:[^`\\\\]|\\\\.)*`)/);\n if (strMatch) {\n segments.push({ text: strMatch[1], color: 'green' });\n i += strMatch[1].length;\n continue;\n }\n\n const commentMatch = rest.match(/^(\\/\\/.*)/);\n if (commentMatch) {\n segments.push({ text: commentMatch[1], dim: true });\n i += commentMatch[1].length;\n continue;\n }\n\n if (rest[0] === '#') {\n segments.push({ text: rest.slice(i), dim: true });\n break;\n }\n\n const numMatch = rest.match(/^(\\d+(?:\\.\\d+)?)/);\n if (numMatch) {\n segments.push({ text: numMatch[1], color: 'yellow' });\n i += numMatch[1].length;\n continue;\n }\n\n const wordMatch = rest.match(/^([a-zA-Z_][a-zA-Z0-9_]*)/);\n if (wordMatch) {\n const word = wordMatch[1];\n if (KEYWORDS.has(word)) {\n segments.push({ text: word, color: 'blue' });\n } else if (/^[A-Z]/.test(word)) {\n segments.push({ text: word, color: 'cyan' });\n } else {\n segments.push({ text: word });\n }\n i += word.length;\n continue;\n }\n\n segments.push({ text: rest[0] });\n i++;\n }\n\n return segments;\n}\n\nexport function 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.slice(0, width));\n current = current.slice(width);\n }\n if (current.length > 0) result.push(current);\n }\n return result;\n}\n\nfunction wrapRichLines(lines: RichLine[], width: number): RichLine[] {\n const result: RichLine[] = [];\n\n for (const line of lines) {\n const totalLen = line.segments.reduce((sum, s) => sum + s.text.length, 0);\n\n if (totalLen <= width) {\n result.push(line);\n continue;\n }\n\n let currentSegs: TextSegment[] = [];\n let currentLen = 0;\n\n for (const seg of line.segments) {\n let remaining = seg.text;\n while (remaining.length > 0) {\n const space = width - currentLen;\n if (remaining.length <= space) {\n currentSegs.push({ text: remaining, color: seg.color, dim: seg.dim });\n currentLen += remaining.length;\n remaining = '';\n } else {\n currentSegs.push({ text: remaining.slice(0, space), color: seg.color, dim: seg.dim });\n result.push({ segments: currentSegs });\n currentSegs = [];\n currentLen = 0;\n remaining = remaining.slice(space);\n }\n }\n }\n\n if (currentLen > 0) {\n result.push({ segments: currentSegs });\n }\n }\n\n return result;\n}\n\nexport function buildRichLines(text: string, width: number): RichLine[] {\n const rawLines = text.split('\\n');\n let inCode = false;\n const parsed: RichLine[] = [];\n\n for (const rawLine of rawLines) {\n const trimmed = rawLine.trim();\n if (trimmed.startsWith('```')) {\n inCode = !inCode;\n continue;\n }\n\n if (inCode) {\n parsed.push({ segments: tokenizeLine(rawLine) });\n } else {\n parsed.push({ segments: [{ text: rawLine }] });\n }\n }\n\n return wrapRichLines(parsed, width);\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","export function 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\nexport function 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","import { PhDB, cosineSimilarity } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport type { SearchOptions } from '../types.js';\nimport { getEmbeddings } from '../embedding/index.js';\nimport { printResults } from '../display/print.js';\nimport { parseFlags, parseDate } from './_utils.js';\n\nexport async function cmdSearch(db: PhDB, cfg: PhConfig, args: string[]): Promise<void> {\n const { flags, positional } = parseFlags(args);\n const query = positional.join(' ');\n\n if (flags['archive']) {\n const archiveResults = db.searchArchive({\n since: flags['since'] ? new Date(flags['since'] as string).toISOString() : undefined,\n until: flags['until'] ? new Date(flags['until'] as string).toISOString() : undefined,\n limit: Number(flags['limit'] ?? 50),\n });\n if (archiveResults.length === 0) {\n console.log('No archived prompts found.');\n return;\n }\n console.log(`Found ${archiveResults.length} archived prompts:\\n`);\n for (const r of archiveResults) {\n const date = new Date(r.timestamp as string).toLocaleString();\n const id = r.original_id ?? r.id;\n const prompt = (r.prompt as string).replace(/\\n/g, ' ').slice(0, 120);\n console.log(` #${id} [${r.tool}] (${date})`);\n console.log(` ${prompt}${(r.prompt as string).length > 120 ? '...' : ''}`);\n if (r.response) {\n const resp = (r.response as string).replace(/\\n/g, ' ').slice(0, 80);\n console.log(` Response: ${resp}${(r.response as string).length > 80 ? '...' : ''}`);\n }\n console.log();\n }\n return;\n }\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 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\nexport async 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","import { PhDB } from '../db/index.js';\nimport { printResults } from '../display/print.js';\n\nexport async 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","import { PhDB } from '../db/index.js';\nimport type { PromptMetadata } from '../types.js';\n\nexport async 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","import { PhDB } from '../db/index.js';\nimport type { PromptMetadata } from '../types.js';\nimport { parseFlags } from './_utils.js';\n\nexport async 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","import path from 'path';\nimport os from 'os';\nimport { PhDB } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport { importGeminiHistory } from '../importer/gemini.js';\nimport { importClaudeHistory } from '../importer/claude.js';\nimport { importOpenCodeHistory } from '../importer/opencode.js';\nimport { importCodexHistory } from '../importer/codex.js';\nimport { getProvider } from '../ai/provider.js';\nimport { FilterPipeline } from '../filter/index.js';\nimport { parseFlags } from './_utils.js';\n\nexport async 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.stderr.write('Supported sources: gemini, claude, opencode, codex\\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 transcriptFile = typeof flags.file === 'string' ? flags.file : undefined;\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 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 filter = new FilterPipeline({\n minLength: 0,\n minRelevance: 0,\n existingHashes,\n });\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 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 case 'opencode':\n result = await importOpenCodeHistory(db, path.join(homeDir, '.local', 'share', 'opencode', 'storage'), dryRun, analyzer, onProgress, filter);\n break;\n case 'codex':\n result = await importCodexHistory(db, path.join(homeDir, '.codex'), dryRun, analyzer, onProgress, filter, transcriptFile);\n break;\n default:\n process.stderr.write(`ph: unknown import source \"${source}\". Supported: gemini, claude, opencode, codex\\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","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';\nimport { createCaptureRecord } from '../capture/index.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(createCaptureRecord({\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: JSON.parse(metadata) as Record<string, unknown>,\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 { createHash } from 'crypto';\nimport type { LLMProvider } from '../ai/provider.js';\nimport type { PhDB } from '../db/index.js';\nimport type { PromptEntry, PromptMetadata } from '../types.js';\nimport { captureGitContext } from '../runner/git-context.js';\nimport type { GitContext } from '../runner/git-context.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 summary?: string;\n key_insights?: string[];\n technical_decisions?: string[];\n}\n\nconst ANALYSIS_PROMPT = (text: string) => `\\\nAnalyze this AI tool prompt and response 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 \"summary\": \"<a concise 1-sentence summary of the interaction>\",\n \"key_insights\": [\"<insight1>\", \"<insight2>\"],\n \"technical_decisions\": [\"<decision1>\", \"<decision2>\"]\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- summary: Focus on the technical achievement or question asked.\n- key_insights: List 1-3 specific technical decisions, library choices, or architectural findings.\n- technical_decisions: List 1-3 concrete technology choices, architectural decisions, or trade-offs made (e.g. \"Using SQLite over Postgres for simplicity\", \"Chose tsup for ESM build\"). Empty array if not applicable.\n- Return ONLY the JSON object — no markdown fences, no explanation, no other text\n\nInteraction to analyze:\n\"\"\"\n${text.slice(0, 2000)}\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 if (typeof parsed['summary'] === 'string' && parsed['summary'].trim()) {\n result.summary = parsed['summary'].trim();\n }\n if (Array.isArray(parsed['key_insights'])) {\n const insights = (parsed['key_insights'] as unknown[])\n .filter((t): t is string => typeof t === 'string' && t.trim().length > 0)\n .slice(0, 5);\n if (insights.length > 0) result.key_insights = insights;\n }\n if (Array.isArray(parsed['technical_decisions'])) {\n const decisions = (parsed['technical_decisions'] as unknown[])\n .filter((t): t is string => typeof t === 'string' && t.trim().length > 0)\n .slice(0, 5);\n if (decisions.length > 0) result.technical_decisions = decisions;\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 \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 if (result.summary && (force || !merged.summary)) {\n merged.summary = result.summary;\n }\n if (result.key_insights && (force || !merged.key_insights?.length)) {\n merged.key_insights = result.key_insights;\n }\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\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\nfunction gitFingerprint(ctx: GitContext): string {\n const hash = createHash('sha256');\n hash.update(ctx.branch);\n hash.update(ctx.diff);\n return `git:${hash.digest('hex').slice(0, 14)}`;\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 // Capture git context once for the batch\n const gitCtx = captureGitContext(process.cwd());\n const gitFp = gitCtx ? gitFingerprint(gitCtx) : undefined;\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 // Populate project memory if we have a project + summary\n if (result.project && result.summary) {\n // Skip duplicate memory when project git state hasn't changed\n if (gitFp) {\n const lastMem = db.getLastMemoryForProject(result.project);\n if (lastMem?.git_context_snapshot === gitFp) {\n stats.updated++;\n continue;\n }\n }\n db.upsertProjectMemory({\n project: result.project,\n prompt_id: entry.id,\n summary: result.summary,\n key_insights: result.key_insights ?? [],\n technical_decisions: result.technical_decisions ?? [],\n git_context_snapshot: gitFp,\n });\n db.upsertProjectSummary({\n project: result.project,\n summary: result.summary,\n key_insights: result.key_insights ?? [],\n technical_decisions: result.technical_decisions ?? [],\n });\n }\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';\nimport { createCaptureRecord } from '../capture/index.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(createCaptureRecord({\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: JSON.parse(metadata) as Record<string, unknown>,\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","import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport Database from 'better-sqlite3';\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';\nimport { createCaptureRecord } from '../capture/index.js';\n\nconst MAX_RESPONSE_LENGTH = 8000;\nconst TRUNCATION_SUFFIX = '\\n... (truncated)';\n\ninterface OCMessageData {\n role: 'user' | 'assistant';\n time: { created: number; completed?: number };\n summary?: { title?: string; diffs?: unknown[] };\n parentID?: string;\n agent?: string;\n model?: { providerID?: string; modelID?: string };\n modelID?: string;\n providerID?: string;\n mode?: string;\n path?: { cwd?: string; root?: string };\n tokens?: { input?: number; output?: number; reasoning?: number };\n finish?: string;\n}\n\ninterface OCPartData {\n type: string;\n text?: string;\n}\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\nexport async function importOpenCodeHistory(\n db: PhDB,\n opencodeDir: 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 dbPath = path.join(opencodeDir, '..', 'opencode.db');\n if (!fs.existsSync(dbPath)) {\n result.errors.push(`opencode database not found at ${dbPath}`);\n return result;\n }\n\n let ocDb: Database.Database;\n try {\n ocDb = new Database(dbPath, { readonly: true });\n } catch (e: unknown) {\n result.errors.push(`cannot open opencode database: ${(e as Error).message}`);\n return result;\n }\n\n result.filesScanned = 1;\n\n const hostname = os.hostname();\n\n interface PendingEntry {\n prompt: string;\n response: string;\n timestamp: string;\n workdir: string;\n sessionId: string;\n agent?: string;\n modelInfo?: string;\n tokens?: string;\n title?: string;\n }\n\n const pendingEntries: PendingEntry[] = [];\n\n try {\n const sessions = ocDb.prepare(\n `SELECT id, directory, time_created FROM session ORDER BY time_created`\n ).all() as { id: string; directory: string; time_created: number }[];\n\n const getMessages = ocDb.prepare(\n `SELECT id, data, time_created FROM message WHERE session_id = ? ORDER BY time_created, id`\n );\n\n const getParts = ocDb.prepare(\n `SELECT data FROM part WHERE message_id = ? ORDER BY id`\n );\n\n function getTextContent(messageId: string): string {\n const partRows = getParts.all(messageId) as { data: string }[];\n const texts: string[] = [];\n for (const row of partRows) {\n try {\n const partData = JSON.parse(row.data) as OCPartData;\n if (partData.type === 'text' && partData.text) {\n texts.push(partData.text);\n }\n } catch { /* skip unparseable parts */ }\n }\n return texts.join('');\n }\n\n for (const session of sessions) {\n const messageRows = getMessages.all(session.id) as { id: string; data: string; time_created: number }[];\n if (messageRows.length === 0) continue;\n\n const messages: { id: string; data: OCMessageData; time_created: number }[] = [];\n for (const row of messageRows) {\n try {\n const data = JSON.parse(row.data) as OCMessageData;\n messages.push({ id: row.id, data, time_created: row.time_created });\n } catch { /* skip */ }\n }\n\n const assistantByParent = new Map<string, { id: string; data: OCMessageData }>();\n for (const msg of messages) {\n if (msg.data.role === 'assistant' && msg.data.parentID) {\n assistantByParent.set(msg.data.parentID, { id: msg.id, data: msg.data });\n }\n }\n\n for (const msg of messages) {\n if (msg.data.role !== 'user') continue;\n\n const prompt = getTextContent(msg.id);\n if (!prompt.trim()) continue;\n\n const assistant = assistantByParent.get(msg.id);\n let response = '';\n if (assistant) {\n const rawText = getTextContent(assistant.id);\n if (rawText) response = truncateResponse(rawText);\n }\n\n const timestamp = new Date(msg.data.time.created).toISOString();\n const workdir = session.directory || '';\n\n pendingEntries.push({\n prompt: prompt.trim(),\n response,\n timestamp,\n workdir,\n sessionId: session.id,\n agent: msg.data.agent || assistant?.data?.mode,\n modelInfo: msg.data.model ? JSON.stringify(msg.data.model) :\n (assistant?.data?.providerID ? JSON.stringify({ providerID: assistant.data.providerID, modelID: assistant.data.modelID }) : undefined),\n tokens: assistant?.data?.tokens ? JSON.stringify(assistant.data.tokens) : undefined,\n title: msg.data.summary?.title,\n });\n }\n }\n } finally {\n ocDb.close();\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 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: Record<string, unknown> = {};\n\n if (analyzer) {\n try {\n const analysis = await analyzePrompt(entry.prompt, 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 = { ...merged };\n } catch { /* analysis failure is non-fatal */ }\n }\n\n if (entry.title) metadata.title = entry.title;\n if (entry.agent) metadata.agent = entry.agent;\n if (entry.modelInfo && entry.modelInfo !== '{}') {\n try { metadata.model = JSON.parse(entry.modelInfo); } catch { metadata.model = entry.modelInfo; }\n }\n if (entry.tokens) {\n try { metadata.tokens = JSON.parse(entry.tokens); } catch { metadata.tokens = entry.tokens; }\n }\n\n const id = db.insert(createCaptureRecord({\n timestamp: entry.timestamp,\n tool: 'opencode',\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(`insert session ${entry.sessionId}: ${(e as Error).message}`);\n result.skipped++;\n }\n }\n\n return result;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\nimport { PhDB } from '../db/index.js';\nimport { FilterPipeline } from '../filter/index.js';\nimport type { ImportResult, PromptMetadata } from '../types.js';\nimport { createCaptureRecord } from '../capture/index.js';\nimport type { LLMProvider } from '../ai/provider.js';\nimport { analyzePrompt, mergeMetadata } from '../analyzer/index.js';\n\ntype RolloutEvent = { timestamp?: string; type?: string; payload?: Record<string, unknown> };\n\nfunction textFromContent(content: unknown): string {\n if (typeof content === 'string') return content;\n if (!Array.isArray(content)) return '';\n return content.flatMap((part) => {\n if (!part || typeof part !== 'object') return [];\n const item = part as Record<string, unknown>;\n return typeof item.text === 'string' && ['output_text', 'input_text', 'text'].includes(String(item.type))\n ? [item.text] : [];\n }).join('');\n}\n\nfunction rolloutFiles(sessionsDir: string): string[] {\n if (!fs.existsSync(sessionsDir)) return [];\n const files: string[] = [];\n const visit = (dir: string): void => {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) visit(full);\n else if (entry.isFile() && /^rollout-.*\\.jsonl$/.test(entry.name)) files.push(full);\n }\n };\n visit(sessionsDir);\n return files;\n}\n\nexport async function importCodexHistory(\n db: PhDB,\n codexDir: string,\n dryRun: boolean,\n analyzer?: LLMProvider,\n onProgress?: (evaluated: number, imported: number, total: number, current: string) => void,\n filter?: FilterPipeline,\n transcriptFile?: string,\n): Promise<ImportResult> {\n const result: ImportResult = { filesScanned: 0, promptsFound: 0, promptsImported: 0, skipped: 0, filtered: 0, errors: [] };\n const dedupFilter = filter ?? new FilterPipeline({ minLength: 0, minRelevance: 0, existingHashes: db.getAllPromptHashes() });\n const files = transcriptFile ? [transcriptFile] : rolloutFiles(path.join(codexDir, 'sessions'));\n result.filesScanned = files.length;\n const hostname = os.hostname();\n const entries: { prompt: string; response: string; timestamp: string; workdir: string; sessionId: string }[] = [];\n\n for (const file of files) {\n let lines: string[];\n try { lines = fs.readFileSync(file, 'utf8').split('\\n'); }\n catch (error) { result.errors.push(`read ${file}: ${(error as Error).message}`); continue; }\n let workdir = '';\n let sessionId = path.basename(file, '.jsonl').replace(/^rollout-.*?-/, '');\n const events: RolloutEvent[] = [];\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n const event = JSON.parse(line) as RolloutEvent;\n events.push(event);\n if (event.type === 'session_meta' && event.payload) {\n if (typeof event.payload.cwd === 'string') workdir = event.payload.cwd;\n if (typeof event.payload.id === 'string') sessionId = event.payload.id;\n }\n } catch { /* Ignore partial or malformed JSONL records. */ }\n }\n for (let i = 0; i < events.length; i++) {\n const event = events[i];\n const payload = event.payload ?? {};\n const isUserMessage = (event.type === 'event_msg' && payload.type === 'user_message')\n || (event.type === 'response_item' && payload.type === 'message' && payload.role === 'user');\n const prompt = !isUserMessage ? '' : typeof payload.message === 'string'\n ? payload.message.trim() : textFromContent(payload.content).trim();\n if (!prompt) continue;\n const agentMessages: string[] = [];\n const assistantItems: string[] = [];\n const finalAssistantItems: string[] = [];\n for (let j = i + 1; j < events.length; j++) {\n const candidate = events[j].payload ?? {};\n const nextIsUserMessage = (events[j].type === 'event_msg' && candidate.type === 'user_message')\n || (events[j].type === 'response_item' && candidate.type === 'message' && candidate.role === 'user');\n if (nextIsUserMessage) break;\n if (events[j].type === 'event_msg' && candidate.type === 'agent_message' && typeof candidate.message === 'string') agentMessages.push(candidate.message);\n if (events[j].type === 'response_item' && candidate.type === 'message' && candidate.role === 'assistant') {\n const text = textFromContent(candidate.content);\n assistantItems.push(text);\n if (candidate.phase === 'final_answer') finalAssistantItems.push(text);\n }\n }\n const response = agentMessages.length > 0 ? agentMessages.join('')\n : finalAssistantItems.length > 0 ? finalAssistantItems.join('') : assistantItems.join('');\n entries.push({ prompt, response: response.slice(0, 8000), timestamp: event.timestamp ?? new Date(0).toISOString(), workdir, sessionId });\n }\n }\n\n for (let i = 0; i < entries.length; i++) {\n const entry = entries[i];\n result.promptsFound++;\n onProgress?.(i + 1, result.promptsImported, entries.length, entry.prompt.slice(0, 60));\n if (dryRun) { result.promptsImported++; continue; }\n const rules = dedupFilter.checkRules(entry.prompt);\n if (!rules.keep || !dedupFilter.checkDuplicate(entry.prompt).keep) { result.filtered++; continue; }\n try {\n let metadata: PromptMetadata = {};\n if (analyzer) {\n try { metadata = mergeMetadata({}, await analyzePrompt(entry.prompt, analyzer), false); }\n catch { /* Analysis failure does not prevent importing the transcript. */ }\n }\n const id = db.insert(createCaptureRecord({ timestamp: entry.timestamp, tool: 'codex', prompt: entry.prompt, response: entry.response,\n args: entry.prompt, workdir: entry.workdir, hostname, exit_code: 0, metadata: { ...metadata } }));\n dedupFilter.registerHash(entry.prompt, id);\n result.promptsImported++;\n } catch (error) { result.errors.push(`insert session ${entry.sessionId}: ${(error as Error).message}`); result.skipped++; }\n }\n return result;\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|grazie|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: escape sequences and control chars. The lookahead\n// requires at least one actual control char — plain words must NOT match here\n// (they fall through to the trivial/pattern rules).\n// eslint-disable-next-line no-control-regex\nconst NON_PRINTABLE_PATTERN = /^(?=.*[\\x00-\\x1f\\x7f])[\\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 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}?`, { cause: err });\n }\n throw new Error(`Ollama unreachable at ${this.url}: ${msg}`, { cause: err });\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 { PhDB } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport { getProvider } from '../ai/provider.js';\nimport { analyzeAll } from '../analyzer/index.js';\nimport { parseFlags } from './_utils.js';\n\nexport async 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","import { PhDB } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport { getEmbeddings } from '../embedding/index.js';\n\nexport async 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","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 { PhDB } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport type { PromptEntry } from '../types.js';\nimport { createCaptureRecord } from '../capture/index.js';\nimport { spawnBackgroundAnalysis } from '../background/analyzer.js';\nimport { parseFlags } from './_utils.js';\n\nexport async function cmdLog(dbPath: string, cfg: PhConfig, args: string[]): Promise<void> {\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 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 record = createCaptureRecord({ tool, prompt, response, args: '', workdir });\n\n const db = new PhDB(dbPath);\n const id = db.insert(record);\n db.close();\n\n if (cfg.backgroundAnalysis) {\n spawnBackgroundAnalysis(id, dbPath);\n }\n\n // Background push to remote if configured\n const pushUrl = process.env.PH_REMOTE_URL || cfg.remoteUrl;\n if (pushUrl) {\n pushToRemote(pushUrl, cfg.remoteApiKey, record).catch(() => {});\n }\n}\n\nasync function pushToRemote(url: string, apiKey: string | undefined, entry: Omit<PromptEntry, 'id'>): Promise<void> {\n const res = await fetch(`${url}/api/sync/push`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}),\n },\n body: JSON.stringify({ prompts: [entry] }),\n });\n if (!res.ok) {\n const err = await res.text();\n throw new Error(`Remote push error: ${err}`);\n }\n}\n","import { load as loadConfig, save as saveConfig } from '../config/index.js';\n\nexport function 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 console.log(' remote-url, remote-api-key');\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 case 'remote-url':\n cfg.remoteUrl = val;\n break;\n case 'remote-api-key':\n cfg.remoteApiKey = val;\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","import { createHash } from 'crypto';\nimport { PhDB } from '../db/index.js';\nimport { load as loadConfig } from '../config/index.js';\nimport { getProvider } from '../ai/provider.js';\nimport { analyzePrompt, mergeMetadata } from '../analyzer/index.js';\nimport { captureGitContext } from '../runner/git-context.js';\nimport type { GitContext } from '../runner/git-context.js';\nimport type { PromptMetadata } from '../types.js';\n\nfunction gitFingerprint(ctx: GitContext): string {\n const hash = createHash('sha256');\n hash.update(ctx.branch);\n hash.update(ctx.diff);\n return `git:${hash.digest('hex').slice(0, 14)}`;\n}\n\nexport async 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\n // Populate project memory, dedup on git state\n if (result.project && result.summary) {\n const gitCtx = captureGitContext(process.cwd());\n const gitFp = gitCtx ? gitFingerprint(gitCtx) : undefined;\n\n if (gitFp) {\n const lastMem = db.getLastMemoryForProject(result.project);\n if (lastMem?.git_context_snapshot === gitFp) return;\n }\n\n db.upsertProjectMemory({\n project: result.project,\n prompt_id: id,\n summary: result.summary,\n key_insights: result.key_insights ?? [],\n technical_decisions: result.technical_decisions ?? [],\n git_context_snapshot: gitFp,\n });\n db.upsertProjectSummary({\n project: result.project,\n summary: result.summary,\n key_insights: result.key_insights ?? [],\n technical_decisions: result.technical_decisions ?? [],\n });\n }\n } catch (_err: unknown) {\n } finally {\n db.close();\n }\n}\n","import { PhDB } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport type { PromptMetadata } from '../types.js';\nimport { FilterPipeline } from '../filter/index.js';\nimport { parseFlags } from './_utils.js';\n\nexport async function cmdCleanup(db: PhDB, cfg: PhConfig, args: string[]): Promise<void> {\n const { flags } = parseFlags(args);\n const dryRun = Boolean(flags['dry-run']);\n const retention = Boolean(flags['retention']);\n\n if (retention) {\n await runRetention(db, cfg, dryRun);\n return;\n }\n\n // Original rule-based cleanup\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 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 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 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 runRetention(db: PhDB, cfg: PhConfig, dryRun: boolean): Promise<void> {\n const retentionDays = cfg.retentionDays ?? 90;\n const minStarred = cfg.retentionMinStarred ?? true;\n const minAnalyzed = cfg.retentionMinAnalyzed ?? true;\n const minRelevance = cfg.retentionMinRelevance ?? 3;\n\n const cutoff = new Date();\n cutoff.setDate(cutoff.getDate() - retentionDays);\n const cutoffStr = cutoff.toISOString();\n\n const allEntries = db.search({ limit: 100000 });\n const stats = db.getArchiveStats();\n\n console.log(`Retention policy: ${retentionDays} days, minRelevance=${minRelevance}, keepStarred=${minStarred}, keepAnalyzed=${minAnalyzed}`);\n console.log(`Archive: ${stats.total} entries (${stats.oldest ? `oldest ${stats.oldest}` : 'empty'})`);\n console.log(`Scanning ${allEntries.length} prompts...\\n`);\n\n // Priority 1: relevance < threshold AND age > retentionDays → archive\n // Priority 2: age > retentionDays AND not starred AND not analyzed → archive\n const toArchive: Array<{ id: number; prompt: string; reason: string; meta: PromptMetadata }> = [];\n\n for (const entry of allEntries) {\n let meta: PromptMetadata = {};\n try { meta = JSON.parse(entry.metadata) as PromptMetadata; } catch {}\n\n const age = entry.timestamp;\n const isOld = age < cutoffStr;\n const isStarred = meta.starred === true;\n const isAnalyzed = Boolean(meta.summary || meta.role);\n const relevance = meta.relevance ?? 5;\n\n if (!isOld) continue;\n\n // Priority 1: low relevance + old\n if (relevance < minRelevance) {\n toArchive.push({ id: entry.id, prompt: entry.prompt, reason: `low_relevance(${relevance})`, meta });\n continue;\n }\n\n // Priority 2: old + not protected\n if (!(minStarred && isStarred) && !(minAnalyzed && isAnalyzed)) {\n toArchive.push({ id: entry.id, prompt: entry.prompt, reason: `old(>${retentionDays}d)`, meta });\n }\n }\n\n if (toArchive.length === 0) {\n console.log('No prompts match retention criteria.');\n return;\n }\n\n console.log(`Candidates for archiving: ${toArchive.length}`);\n for (const item of toArchive.slice(0, 20)) {\n const short = item.prompt.replace(/\\n/g, ' ').slice(0, 60);\n const starred = item.meta.starred ? ' *' : '';\n const analyzed = item.meta.summary ? ' [A]' : '';\n console.log(` #${String(item.id).padEnd(5)} [${item.reason}]${starred}${analyzed} \"${short}\"`);\n }\n if (toArchive.length > 20) {\n console.log(` ... and ${toArchive.length - 20} more`);\n }\n\n if (dryRun) {\n console.log(`\\n(dry-run) Would archive ${toArchive.length} prompts. Run without --dry-run to apply.`);\n return;\n }\n\n const ids = toArchive.map(e => e.id);\n const archived = db.archivePrompts(ids);\n console.log(`\\nArchived ${archived} prompts.`);\n\n // Auto-purge: archived entries older than 2x retentionDays\n const purgeCutoff = new Date();\n purgeCutoff.setDate(purgeCutoff.getDate() - retentionDays * 2);\n const purged = db.purgeArchive(purgeCutoff.toISOString());\n if (purged > 0) {\n console.log(`Purged ${purged} archived entries older than ${retentionDays * 2} days.`);\n }\n}\n","import { PhDB } from '../db/index.js';\n\nexport async 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","import { PhDB } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport { getEmbeddings } from '../embedding/index.js';\nimport { detectProject } from '../runner/project.js';\nimport { parseFlags } from './_utils.js';\nimport { formatProjectContext, getProjectContext } from '../context/index.js';\n\nexport async function cmdContext(db: PhDB, cfg: PhConfig, args: string[]): Promise<void> {\n const { flags, positional } = parseFlags(args);\n const query = positional.join(' ');\n const project = (flags['project'] as string) || detectProject(process.cwd()).projectName;\n const limit = Number(flags['limit'] ?? 5);\n const promptsOnly = Boolean(flags['prompts-only']);\n const memoriesOnly = Boolean(flags['memories-only']);\n const verbose = Boolean(flags['verbose']);\n\n if (!project) {\n process.stderr.write('ph: could not detect project. Use --project <name>\\n');\n process.exit(1);\n }\n\n const ollamaUrl = cfg.ollamaUrl ?? 'http://localhost:11434';\n const model = cfg.ollamaEmbedModel ?? 'nomic-embed-text-v2-moe';\n const context = await getProjectContext(db, {\n project,\n query,\n limit,\n includeSummary: !promptsOnly,\n includeMemories: !promptsOnly,\n includePrompts: !memoriesOnly,\n }, async (text) => {\n const [vector] = await getEmbeddings([text], ollamaUrl, model, 1);\n return vector;\n });\n\n process.stdout.write(formatProjectContext(context, { includePromptText: verbose }) + '\\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';\nimport { groupIntoSessions, computeSessionCohesion } from '../sessions/index.js';\nimport { parseFlags } from './_utils.js';\n\nfunction formatTimestamp(ts: string): string {\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}\n\nfunction 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\nfunction parseMeta(raw: string): PromptMetadata {\n try { return JSON.parse(raw) as PromptMetadata; } catch { return {}; }\n}\n\nfunction exportSessionMarkdown(session: { index: number; startTime: Date; endTime: Date; entries: import('../types.js').PromptEntry[] }): string {\n const lines: string[] = [];\n const dateStr = formatTimestamp(session.startTime.toISOString());\n const endStr = fmtTime(session.endTime.toISOString());\n\n lines.push(`# Session ${session.index} — ${dateStr} → ${endStr}`);\n lines.push('');\n lines.push(`**${session.entries.length} prompts**`);\n lines.push('');\n lines.push('---');\n lines.push('');\n\n for (const entry of session.entries) {\n const meta = parseMeta(entry.metadata);\n const ts = formatTimestamp(entry.timestamp);\n const title = meta.title || entry.prompt.replace(/\\n/g, ' ').slice(0, 60);\n\n lines.push(`## #${entry.id} — ${entry.tool} — ${ts}`);\n if (title) lines.push(`**${title}**`);\n lines.push('');\n\n const metaLine: string[] = [];\n if (meta.role) metaLine.push(`Role: ${meta.role}`);\n if (meta.project) metaLine.push(`Project: ${meta.project}`);\n if (meta.language) metaLine.push(`Language: ${meta.language}`);\n if (meta.tags?.length) metaLine.push(`Tags: ${meta.tags.join(', ')}`);\n if (meta.relevance !== undefined) metaLine.push(`Relevance: ${meta.relevance}/10`);\n if (meta.quality !== undefined) metaLine.push(`Quality: ${meta.quality}/10`);\n if (metaLine.length > 0) {\n lines.push(metaLine.join(' · '));\n lines.push('');\n }\n\n if (meta.summary) {\n lines.push(`> ${meta.summary}`);\n lines.push('');\n }\n\n lines.push('### Prompt');\n lines.push('');\n lines.push('```');\n lines.push(entry.prompt);\n lines.push('```');\n lines.push('');\n\n if (entry.response) {\n lines.push('### Response');\n lines.push('');\n lines.push('```');\n lines.push(entry.response.slice(0, 2000));\n lines.push('```');\n lines.push('');\n }\n\n if (meta.key_insights?.length) {\n lines.push('**Insights:**');\n for (const ins of meta.key_insights) lines.push(`- ${ins}`);\n lines.push('');\n }\n\n if (meta.git_context) {\n lines.push(`*Git: ${meta.git_context.branch}, ${meta.git_context.files?.length || 0} files modified*`);\n lines.push('');\n }\n\n lines.push('---');\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\nexport async 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 const exportIndex = flags['export'] !== undefined ? Number(flags['export']) : undefined;\n\n const allEntries = db.search({ limit: 100000 });\n const entriesAsc = [...allEntries].reverse();\n\n const sessions = groupIntoSessions(entriesAsc, gapHours);\n\n let embeddings: Map<number, Float32Array> | null = null;\n if (!noCohesion && exportIndex === undefined) {\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 // Export mode: output a single session as markdown\n if (exportIndex !== undefined) {\n const session = sessions.find(s => s.index === exportIndex);\n if (!session) {\n process.stderr.write(`Session ${exportIndex} not found.\\n`);\n return;\n }\n process.stdout.write(exportSessionMarkdown(session));\n return;\n }\n\n const filtered = sessions.filter(s => s.entries.length >= minSize);\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 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 for (const session of visible) {\n const projectCounts = new Map<string, number>();\n const languageCounts = new Map<string, number>();\n for (const entry of session.entries) {\n const meta = parseMeta(entry.metadata);\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 const startStr = formatTimestamp(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 for (const entry of session.entries) {\n const meta = parseMeta(entry.metadata);\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","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 { PhDB } from '../db/index.js';\nimport { getStats } from '../stats/index.js';\n\nexport async 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","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: Float32Array<ArrayBufferLike>[] = 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: Float32Array<ArrayBufferLike>[] = 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","import { PhDB } from '../db/index.js';\nimport { kmeans } from '../cluster/index.js';\nimport { parseFlags } from './_utils.js';\n\nexport async 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 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","import fs from 'fs';\nimport { PhDB } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport { ReusabilityAnalyzer } from '../analyzer/reusability.js';\nimport { parseFlags } from './_utils.js';\n\nexport async function cmdAnalyzeReusability(db: PhDB, _cfg: PhConfig, 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","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 fs from 'fs';\nimport { PhDB } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport { ReusabilityAnalyzer } from '../analyzer/reusability.js';\nimport { parseFlags } from './_utils.js';\n\nexport async 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 const totalSize = candidates.reduce((sum, c) => sum + c.promptSize + c.responseSize, 0);\n const totalEmbeddingSize = candidates.filter(c => c.hasEmbedding).length * 768 * 4;\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 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, null);\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","import { PhDB } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport type { PromptEntry, PromptMetadata, MemoryEntry } from '../types.js';\nimport { detectProject } from '../runner/project.js';\nimport { parseFlags } from './_utils.js';\n\ninterface TimelineEvent {\n type: 'prompt' | 'memory';\n timestamp: string;\n prompt?: PromptEntry;\n memory?: MemoryEntry;\n}\n\nexport async function cmdTimeline(db: PhDB, cfg: PhConfig, args: string[]): Promise<void> {\n const { flags, positional } = parseFlags(args);\n const project = (flags['project'] as string) || positional.join(' ') || detectProject(process.cwd()).projectName;\n\n if (!project) {\n process.stderr.write('ph: could not detect project. Use --project <name> or pass a project name.\\n');\n process.exit(1);\n }\n\n const prompts = db.getAllPromptsByProject(project);\n const memories = db.getAllMemoriesByProject(project);\n\n if (prompts.length === 0 && memories.length === 0) {\n process.stdout.write(`No history found for project \"${project}\".\\n`);\n return;\n }\n\n const output: string[] = [];\n\n output.push(`# Timeline: ${project}\\n`);\n output.push(`**${prompts.length} prompts** · **${memories.length} memory entries**\\n`);\n\n const events: TimelineEvent[] = [\n ...prompts.map(p => ({ type: 'prompt' as const, timestamp: p.timestamp, prompt: p })),\n ...memories.map(m => ({ type: 'memory' as const, timestamp: m.created_at, memory: m })),\n ];\n events.sort((a, b) => a.timestamp.localeCompare(b.timestamp));\n\n let currentDate = '';\n\n for (const event of events) {\n const date = new Date(event.timestamp).toLocaleDateString('en-CA'); // YYYY-MM-DD\n if (date !== currentDate) {\n currentDate = date;\n output.push(`\\n## ${date}\\n`);\n }\n\n if (event.type === 'prompt' && event.prompt) {\n output.push(formatPromptEntry(event.prompt));\n }\n\n if (event.type === 'memory' && event.memory) {\n output.push(formatMemoryEntry(event.memory));\n }\n }\n\n process.stdout.write(output.join('\\n'));\n}\n\nfunction formatPromptEntry(e: PromptEntry): string {\n let meta: PromptMetadata = {};\n try { meta = JSON.parse(e.metadata); } catch {}\n\n const time = new Date(e.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });\n const lines: string[] = [];\n lines.push(`### #${e.id} — ${e.tool} — ${time}`);\n if (meta.role) lines.push(`**Role**: ${meta.role}`);\n if (meta.title) lines.push(`**Title**: ${meta.title}`);\n if (meta.tags?.length) lines.push(`**Tags**: ${meta.tags.join(', ')}`);\n if (meta.summary) lines.push(`**Summary**: ${meta.summary}`);\n if (meta.relevance !== undefined) lines.push(`**Relevance**: ${meta.relevance}/10`);\n lines.push('');\n lines.push('**Prompt**:');\n lines.push('```');\n lines.push(e.prompt.slice(0, 500) + (e.prompt.length > 500 ? '\\n...' : ''));\n lines.push('```');\n if (e.response) {\n lines.push('');\n lines.push('**Response**:');\n lines.push('```');\n lines.push(e.response.slice(0, 300) + (e.response.length > 300 ? '\\n...' : ''));\n lines.push('```');\n }\n if (meta.key_insights?.length) {\n lines.push('');\n lines.push('**Insights**:');\n for (const i of meta.key_insights) lines.push(`- ${i}`);\n }\n lines.push('---\\n');\n return lines.join('\\n');\n}\n\nfunction formatMemoryEntry(m: MemoryEntry): string {\n const time = new Date(m.created_at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });\n const lines: string[] = [];\n lines.push(`> 📌 **Memory #${m.id} — ${time}**`);\n if (m.prompt_ids.length > 0) {\n lines.push(`> _Derived from prompts: #${m.prompt_ids.join(', #')}_`);\n }\n if (m.summary) lines.push(`> **Summary**: ${m.summary}`);\n if (m.key_insights.length > 0) {\n lines.push(`> **Insights**:`);\n for (const i of m.key_insights) lines.push(`> - ${i}`);\n }\n if (m.technical_decisions.length > 0) {\n lines.push(`> **Technical Decisions**:`);\n for (const d of m.technical_decisions) lines.push(`> - ${d}`);\n }\n lines.push('---\\n');\n return lines.join('\\n');\n}\n","import { PhDB } from '../db/index.js';\n\nexport function cmdMemoryMigrate(db: PhDB): void {\n const projects = db.getAllProjectsWithMemories();\n if (projects.length === 0) {\n console.log('No memories found. Nothing to migrate.');\n return;\n }\n\n let count = 0;\n for (const project of projects) {\n const memories = db.searchMemories(project, 1000);\n const allInsights = new Set<string>();\n const allDecisions = new Set<string>();\n let lastSummary = '';\n let gitCtx: string | undefined;\n\n for (const mem of memories) {\n if (mem.summary) lastSummary = mem.summary;\n for (const i of mem.key_insights) allInsights.add(i);\n for (const d of mem.technical_decisions) allDecisions.add(d);\n if (mem.git_context_snapshot) gitCtx = mem.git_context_snapshot;\n }\n\n db.upsertProjectSummary({\n project,\n summary: lastSummary,\n key_insights: [...allInsights],\n technical_decisions: [...allDecisions],\n git_context_snapshot: gitCtx,\n });\n count++;\n }\n\n console.log(`Migrated ${count} project(s) into project_summaries.`);\n}\n","import path from 'path';\nimport os from 'os';\nimport { PhDB } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport { captureGitContext } from '../runner/git-context.js';\nimport { createCaptureRecord } from '../capture/index.js';\nimport { runInline, resolveRealBinary } from '../runner/inline.js';\nimport { runPTY, isTerminal } from '../pty/wrapper.js';\nimport { spawnBackgroundAnalysis } from '../background/analyzer.js';\n\nexport async function cmdWrap(dbPath: string, tool: string, args: string[], cfg: PhConfig): Promise<void> {\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 gitContext = captureGitContext(workdir);\n\n const onPrompt = (prompt: string, ts: Date): number => {\n return db.insert(createCaptureRecord({\n timestamp: ts.toISOString(),\n tool,\n prompt,\n args: prompt,\n workdir,\n gitContext,\n metadata: { ...(role ? { role } : {}), ...(tags.length > 0 ? { tags } : {}) },\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 }\n}\n","import { spawnSync } from 'child_process';\nimport { PhDB } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport { detectProject } from '../runner/project.js';\nimport { resolveRealBinary } from '../runner/inline.js';\nimport { getEmbeddings } from '../embedding/index.js';\nimport { formatProjectContext, getProjectContext } from '../context/index.js';\n\nexport async function cmdChat(dbPath: string, cfg: PhConfig, args: string[]): Promise<void> {\n if (args.length === 0) {\n process.stderr.write('Usage: ph chat <tool> [tool-args...]\\n');\n process.exit(1);\n }\n\n const tool = args[0];\n const userPrompt = args.slice(1).join(' ');\n if (!userPrompt) {\n process.stderr.write('ph chat: no prompt provided\\n');\n process.exit(1);\n }\n\n const project = detectProject(process.cwd()).projectName;\n if (!project) {\n process.stderr.write('ph chat: could not detect project. Run from a project directory.\\n');\n process.exit(1);\n }\n\n const db = new PhDB(dbPath);\n const ollamaUrl = cfg.ollamaUrl ?? 'http://localhost:11434';\n const model = cfg.ollamaEmbedModel ?? 'nomic-embed-text-v2-moe';\n const context = await getProjectContext(db, { project, limit: 5, memoryLimit: 3 }, async (query) => {\n const [vector] = await getEmbeddings([query], ollamaUrl, model, 1);\n return vector;\n });\n\n db.close();\n\n const contextStr = formatProjectContext(context);\n const fullPrompt = `Context from project \"${project}\":\\n\\n${contextStr}\\n\\n---\\n\\n${userPrompt}`;\n\n const realBin = resolveRealBinary(tool);\n const child = spawnSync(realBin, [fullPrompt], { stdio: 'inherit', cwd: process.cwd() });\n process.exit(child.status ?? 0);\n}\n"],"mappings":"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","names":["spawnSync","React","path","os","path","os","execFileSync","fs","os","fs","path","os","execFileSync","fs","fs","createHash","path","status","React","useState","useMemo","Box","Text","useInput","spawn","React","THEMES","hasProject","React","useMemo","Text","ROLE_COLOR","useMemo","React","Text","ROLE_COLOR","THEMES","React","Box","Text","React","Box","Text","ROLE_COLOR","React","Box","Text","React","useState","useMemo","Box","Text","useInput","ROLE_COLOR","useState","useMemo","push","useInput","React","Box","Text","spawn","useState","formatTimestamp","useMemo","push","useInput","React","Box","Text","ROLE_COLOR","save","THEMES","formatTimestamp","path","os","fs","path","os","createHash","parseMeta","createHash","fs","path","os","fs","path","os","fs","path","os","fs","path","os","Database","MAX_RESPONSE_LENGTH","TRUNCATION_SUFFIX","truncateResponse","path","fs","Database","os","getTextContent","fs","path","os","createHash","fs","path","os","os","path","spawn","createHash","gitFingerprint","createHash","deleted","formatTimestamp","parseMeta","C","C","C","fs","C","fs","fs","C","fs","path","os","path","os","React","spawnSync","db"]}
|
|
1
|
+
{"version":3,"sources":["../src/config/index.ts","../src/db/index.ts","../src/db/semantic-index.ts","../src/db/memory-repository.ts","../src/db/archive-repository.ts","../src/mcp/server.ts","../src/mcp/tools/definitions.ts","../src/mcp/tools/prompts.ts","../src/embedding/index.ts","../src/interaction/detail.ts","../src/mcp/tools/format.ts","../src/mcp/tools/projects.ts","../src/context/index.ts","../src/knowledge/promotion.ts","../src/knowledge/task-context.ts","../src/mcp/tools/timeline.ts","../src/server/index.ts","../src/utils/syncHash.ts","../src/sync/protocol.ts","../src/sync/client.ts","../src/commands/remote.ts","../src/interaction/lifecycle.ts","../src/display/print.ts","../src/commands/_utils.ts","../src/runner/project.ts","../src/commands/search.ts","../src/commands/show.ts","../src/commands/status.ts","../src/commands/last.ts","../src/commands/star.ts","../src/commands/export.ts","../src/commands/import.ts","../src/importer/gemini.ts","../src/analyzer/index.ts","../src/capture/index.ts","../src/utils/extractTopic.ts","../src/importer/claude.ts","../src/importer/opencode.ts","../src/importer/codex.ts","../src/filter/index.ts","../src/ai/ollama.ts","../src/ai/gemini.ts","../src/ai/wise.ts","../src/ai/provider.ts","../src/commands/analyze.ts","../src/commands/embed-all.ts","../src/background/analyzer.ts","../src/capture/lifecycle.ts","../src/commands/log.ts","../src/config/provider-summary.ts","../src/commands/config.ts","../src/commands/background-analyze.ts","../src/commands/cleanup.ts","../src/commands/vacuum.ts","../src/commands/context.ts","../src/commands/close.ts","../src/sessions/index.ts","../src/commands/sessions.ts","../src/stats/index.ts","../src/commands/stats.ts","../src/cluster/index.ts","../src/commands/cluster.ts","../src/commands/analyze-reusability.ts","../src/analyzer/reusability.ts","../src/commands/cleanup-reusability.ts","../src/commands/timeline.ts","../src/commands/memory-migrate.ts","../src/commands/wrap.ts","../src/runner/git-context.ts","../src/runner/inline.ts","../src/pty/wrapper.ts","../src/commands/chat.ts","../src/commands/setup.ts","../src/commands/models.ts","../src/cli.ts"],"sourcesContent":["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' | 'openrouter' | 'mlx-serve'; // default: 'ollama'\n ollamaUrl?: string; // default: 'http://localhost:11434'\n ollamaModel?: string; // default: 'llama3.1:latest'\n openrouterModel?: string; // OpenRouter model ID, e.g. provider/model\n openrouterUrl?: string; // default: https://openrouter.ai/api/v1\n openrouterApiKey?: string; // overridden by OPENROUTER_API_KEY\n mlxServeModel?: string; // exact model ID returned by MLX-Serve\n mlxServeUrl?: string; // default: http://127.0.0.1:11234/v1 (SSH tunnel)\n mlxServeApiKey?: string; // overridden by MLX_SERVE_API_KEY / GLB_OMLX_API_KEY\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 remoteUrl?: string; // HTTP URL of remote ph server (or set PH_REMOTE_URL env)\n remoteApiKey?: string; // optional API key for remote server\n remoteLastPush?: string; // ISO timestamp of last successful push\n remoteLastPull?: string; // ISO timestamp of last successful pull\n remotePushCursor?: { target: string; databaseId: string; id: number };\n remotePullCursor?: { target: string; databaseId: string; id: number };\n retentionDays?: number; // default: 90 — auto-archive prompts older than N days\n retentionMinStarred?: boolean; // default: true — never archive starred prompts\n retentionMinAnalyzed?: boolean; // default: true — never archive analyzed prompts (has summary or role)\n retentionMinRelevance?: number; // default: 3 — prompts below this relevance are archived first\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 fs.chmodSync(CONFIG_PATH, 0o600);\n}\n","import Database from 'better-sqlite3';\nimport path from 'path';\nimport os from 'os';\nimport { createHash, randomUUID } from 'crypto';\nimport * as sqliteVec from 'sqlite-vec';\nimport type { PromptEntry, SearchOptions, MemoryEntry, ProjectSummary, ArchivedPromptEntry } from '../types.js';\nimport { SemanticIndex } from './semantic-index.js';\nimport { MemoryRepository } from './memory-repository.js';\nimport { ArchiveRepository } from './archive-repository.js';\n\nexport function defaultPath(): string {\n return path.join(os.homedir(), '.prompt_history.db');\n}\n\nfunction analysisSearchText(raw: string): string {\n try {\n const metadata = JSON.parse(raw) as Record<string, unknown>;\n const values: unknown[] = [metadata['title'], metadata['role'], metadata['project'], metadata['language'], metadata['summary']];\n for (const key of ['tags', 'key_insights', 'technical_decisions']) {\n const value = metadata[key];\n if (Array.isArray(value)) values.push(...value);\n }\n return values.filter((value): value is string => typeof value === 'string').join(' ');\n } catch {\n return '';\n }\n}\n\nexport class PhDB {\n private static readonly PROJECT_SUMMARIES_SCHEMA = `\n CREATE TABLE IF NOT EXISTS project_summaries (\n project TEXT PRIMARY KEY,\n summary TEXT NOT NULL DEFAULT '',\n key_insights TEXT NOT NULL DEFAULT '[]',\n technical_decisions TEXT NOT NULL DEFAULT '[]',\n prompt_count INTEGER NOT NULL DEFAULT 0,\n first_analyzed TEXT NOT NULL,\n last_analyzed TEXT NOT NULL,\n git_context_snapshot TEXT\n );\n `;\n\n private static readonly ARCHIVE_SCHEMA = `\n CREATE TABLE IF NOT EXISTS prompts_archive (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n timestamp TEXT NOT NULL,\n tool TEXT NOT NULL,\n prompt TEXT NOT NULL,\n response TEXT NOT NULL DEFAULT '',\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 archived_at TEXT NOT NULL,\n original_id INTEGER\n );\n CREATE INDEX IF NOT EXISTS idx_archive_timestamp ON prompts_archive(timestamp);\n CREATE INDEX IF NOT EXISTS idx_archive_original_id ON prompts_archive(original_id);\n `;\n\n private db: Database.Database;\n private semanticIndex: SemanticIndex;\n private memoryRepository: MemoryRepository;\n private archiveRepository: ArchiveRepository;\n\n /** Absolute path of the SQLite file (used by the HTTP server health endpoint). */\n readonly dbPath: string;\n /** Stable identity stored in the database; remote cursors are scoped to it. */\n readonly databaseId: string;\n\n constructor(dbPath: string) {\n this.dbPath = dbPath;\n this.db = new Database(dbPath);\n this.db.pragma('journal_mode = WAL');\n sqliteVec.load(this.db);\n this.semanticIndex = new SemanticIndex(this.db);\n this.migrate();\n this.databaseId = (this.db.prepare(\"SELECT value FROM ph_meta WHERE key = 'database_id'\").get() as { value: string }).value;\n this.memoryRepository = new MemoryRepository(this.db);\n this.archiveRepository = new ArchiveRepository(this.db);\n }\n\n private migrate(): void {\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS ph_meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n\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 const databaseId = this.db.prepare(\"SELECT value FROM ph_meta WHERE key = 'database_id'\").get();\n if (!databaseId) this.db.prepare(\"INSERT OR IGNORE INTO ph_meta (key, value) VALUES ('database_id', ?)\").run(randomUUID());\n\n // New native vector table (sqlite-vec)\n const vecTable = this.db.prepare(\"SELECT sql FROM sqlite_master WHERE type='table' AND name='vec_embeddings'\").get() as { sql: string } | undefined;\n if (vecTable && !vecTable.sql.includes('vec0')) {\n this.db.exec(\"DROP TABLE vec_embeddings\");\n }\n\n this.db.exec(`\n CREATE VIRTUAL TABLE IF NOT EXISTS vec_embeddings USING vec0(\n embedding float[768]\n );\n `);\n\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS memories (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n project TEXT NOT NULL,\n prompt_ids TEXT NOT NULL DEFAULT '[]',\n summary TEXT NOT NULL,\n key_insights TEXT NOT NULL DEFAULT '[]',\n technical_decisions TEXT NOT NULL DEFAULT '[]',\n git_context_snapshot TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n access_count INTEGER DEFAULT 0,\n last_accessed TEXT\n );\n CREATE INDEX IF NOT EXISTS idx_memories_project ON memories(project);\n `);\n\n this.db.exec(PhDB.PROJECT_SUMMARIES_SCHEMA);\n this.db.exec(PhDB.ARCHIVE_SCHEMA);\n\n // Migration: $schema_version in existing metadata\n const rowsWithoutSchema = this.db\n .prepare(\"SELECT id, metadata FROM prompts WHERE json_extract(metadata, '$.\\\\$schema_version') IS NULL\")\n .all() as { id: number; metadata: string }[];\n for (const row of rowsWithoutSchema) {\n try {\n const meta = JSON.parse(row.metadata);\n meta.$schema_version = 1;\n this.db.prepare('UPDATE prompts SET metadata = ? WHERE id = ?').run(JSON.stringify(meta), row.id);\n } catch { /* skip malformed metadata */ }\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 // Derived searchable metadata keeps analysis text in the FTS index without\n // requiring a JSON scan for every query.\n try {\n this.db.exec(\"ALTER TABLE prompts ADD COLUMN search_metadata TEXT NOT NULL DEFAULT ''\");\n } catch { /* already exists */ }\n const searchMetadataMigration = this.db.prepare(\n \"SELECT value FROM ph_meta WHERE key = 'search_metadata_backfill_v1'\",\n ).get();\n if (!searchMetadataMigration) {\n const backfillSearchMetadata = this.db.transaction(() => {\n const migration = this.db.prepare(\n \"SELECT value FROM ph_meta WHERE key = 'search_metadata_backfill_v1'\",\n ).get();\n if (migration) return;\n const metadataRows = this.db.prepare(\"SELECT id, metadata FROM prompts WHERE search_metadata = ''\").all() as { id: number; metadata: string }[];\n const updateSearchMetadata = this.db.prepare('UPDATE prompts SET search_metadata = ? WHERE id = ?');\n for (const row of metadataRows) updateSearchMetadata.run(analysisSearchText(row.metadata), row.id);\n this.db.prepare(\"INSERT OR IGNORE INTO ph_meta (key, value) VALUES ('search_metadata_backfill_v1', 'complete')\").run();\n });\n backfillSearchMetadata.immediate();\n }\n\n // Migration: migrate data from old embeddings to new vec_embeddings if needed\n const oldEmbeds = this.db.prepare('SELECT count(*) as count FROM embeddings').get() as { count: number };\n const newEmbeds = this.db.prepare('SELECT count(*) as count FROM vec_embeddings').get() as { count: number };\n\n if (oldEmbeds.count > 0 && newEmbeds.count === 0) {\n const rows = this.db.prepare('SELECT prompt_id, vector FROM embeddings').all() as { prompt_id: number; vector: Buffer }[];\n const insert = this.db.prepare('INSERT INTO vec_embeddings(rowid, embedding) VALUES (?, vec_f32(?))');\n for (const row of rows) {\n try {\n insert.run(BigInt(row.prompt_id), row.vector);\n } catch (e: unknown) {\n console.error(`DEBUG Migration error for prompt #${row.prompt_id}: ${(e as Error).message}`);\n }\n }\n }\n\n // Keep raw-text BM25 isolated from analyzed metadata so derived fields do not\n // change the ranking of existing prompt/response matches.\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') || ftsRow.sql.includes('search_metadata')) {\n this.db.exec('BEGIN IMMEDIATE');\n try {\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 DROP TRIGGER IF EXISTS prompts_au;\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 CREATE TRIGGER prompts_au AFTER UPDATE OF prompt, response, tool 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 INSERT INTO prompts_fts(rowid, prompt, response, tool)\n VALUES (new.id, new.prompt, new.response, new.tool);\n END;\n\n INSERT INTO prompts_fts(prompts_fts) VALUES('rebuild');\n `);\n this.db.exec('COMMIT');\n } catch (error) {\n this.db.exec('ROLLBACK');\n throw error;\n }\n }\n\n const rawFtsUpdateTrigger = this.db.prepare(\n \"SELECT name FROM sqlite_master WHERE type='trigger' AND name='prompts_au'\"\n ).get();\n if (!rawFtsUpdateTrigger) {\n this.db.exec(`\n CREATE TRIGGER prompts_au AFTER UPDATE OF prompt, response, tool 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 INSERT INTO prompts_fts(rowid, prompt, response, tool)\n VALUES (new.id, new.prompt, new.response, new.tool);\n END;\n `);\n }\n\n // Analysis text has a separate FTS index so adding metadata does not perturb\n // the established BM25 scores of prompt and response matches.\n const analysisFtsRow = this.db.prepare(\n \"SELECT sql FROM sqlite_master WHERE type='table' AND name='prompts_analysis_fts'\"\n ).get() as { sql: string } | undefined;\n if (!analysisFtsRow?.sql?.includes('search_metadata')) {\n this.db.exec('BEGIN IMMEDIATE');\n try {\n this.db.exec(`\n DROP TABLE IF EXISTS prompts_analysis_fts;\n DROP TRIGGER IF EXISTS prompts_analysis_ai;\n DROP TRIGGER IF EXISTS prompts_analysis_ad;\n DROP TRIGGER IF EXISTS prompts_analysis_au;\n\n CREATE VIRTUAL TABLE prompts_analysis_fts USING fts5(\n search_metadata,\n content='prompts',\n content_rowid='id'\n );\n\n CREATE TRIGGER prompts_analysis_ai AFTER INSERT ON prompts BEGIN\n INSERT INTO prompts_analysis_fts(rowid, search_metadata) VALUES (new.id, new.search_metadata);\n END;\n\n CREATE TRIGGER prompts_analysis_ad AFTER DELETE ON prompts BEGIN\n INSERT INTO prompts_analysis_fts(prompts_analysis_fts, rowid, search_metadata)\n VALUES('delete', old.id, old.search_metadata);\n END;\n\n CREATE TRIGGER prompts_analysis_au AFTER UPDATE OF search_metadata ON prompts BEGIN\n INSERT INTO prompts_analysis_fts(prompts_analysis_fts, rowid, search_metadata)\n VALUES('delete', old.id, old.search_metadata);\n INSERT INTO prompts_analysis_fts(rowid, search_metadata) VALUES (new.id, new.search_metadata);\n END;\n\n INSERT INTO prompts_analysis_fts(prompts_analysis_fts) VALUES('rebuild');\n `);\n this.db.exec('COMMIT');\n } catch (error) {\n this.db.exec('ROLLBACK');\n throw error;\n }\n }\n }\n\n /** `response` is optional at the call site (runtime defaults to ''). */\n insert(entry: Omit<PromptEntry, 'id' | 'response'> & { response?: string }): 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, search_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 analysisSearchText(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 = ?, search_metadata = ? WHERE id = ?').run(metadata, analysisSearchText(metadata), id);\n }\n\n updateMetadataFields(id: number, patch: Record<string, unknown>): void {\n const update = this.db.transaction(() => {\n const entry = this.getById(id);\n if (!entry) return;\n let metadata: Record<string, unknown>;\n try {\n const parsed: unknown = JSON.parse(entry.metadata);\n metadata = parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed as Record<string, unknown> : {};\n } catch {\n metadata = {};\n }\n for (const [key, value] of Object.entries(patch)) {\n if (value === undefined || value === null) delete metadata[key];\n else metadata[key] = value;\n }\n this.updateMetadata(id, JSON.stringify(metadata));\n });\n update();\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 getArchivedById(id: number): ArchivedPromptEntry | undefined {\n return this.archiveRepository.getByOriginalIdOrArchiveId(id);\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 WITH raw_matches AS (\n SELECT f.rowid AS id, bm25(prompts_fts) AS score\n FROM prompts_fts f WHERE prompts_fts MATCH ?\n ), raw_ranked AS (\n SELECT m.id, ROW_NUMBER() OVER (ORDER BY m.score ASC, p.timestamp DESC, p.id DESC) AS position\n FROM raw_matches m JOIN prompts p ON p.id = m.id\n ), analysis_matches AS (\n SELECT f.rowid AS id, bm25(prompts_analysis_fts) AS score\n FROM prompts_analysis_fts f WHERE prompts_analysis_fts MATCH ?\n ), analysis_ranked AS (\n SELECT m.id, ROW_NUMBER() OVER (ORDER BY m.score ASC, p.timestamp DESC, p.id DESC) AS position\n FROM analysis_matches m JOIN prompts p ON p.id = m.id\n ), ranked_sources AS (\n SELECT id, position FROM raw_ranked\n UNION ALL\n SELECT id, position FROM analysis_ranked\n ), fused AS (\n SELECT id, SUM(1.0 / (60.0 + position)) AS score\n FROM ranked_sources GROUP BY id\n )\n SELECT p.*\n FROM fused r\n JOIN prompts p ON p.id = r.id\n WHERE 1=1${filterClause}\n ORDER BY r.score DESC, p.timestamp DESC, p.id DESC\n LIMIT ?\n `;\n return this.db.prepare(sql).all(sanitized, 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 this.semanticIndex.save(id, vector);\n }\n\n searchSemantic(queryVector: Float32Array, limit: number, project?: string): PromptEntry[] {\n return this.semanticIndex.search(queryVector, limit, project);\n }\n\n getAllEmbeddings(): Map<number, Float32Array> {\n return this.semanticIndex.loadAll();\n }\n\n getEmbeddingsForProject(project: string): Map<number, Float32Array> {\n return this.semanticIndex.loadProject(project);\n }\n\n getPromptsWithoutEmbeddings(): PromptEntry[] {\n return this.semanticIndex.findMissingPrompts();\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 getPromptsSince(timestamp: string, limit: number = 10000): PromptEntry[] {\n return this.db\n .prepare('SELECT * FROM prompts WHERE timestamp > ? ORDER BY timestamp ASC LIMIT ?')\n .all(timestamp, limit) as PromptEntry[];\n }\n\n getPromptsAfterId(id: number, limit: number): PromptEntry[] {\n return this.db\n .prepare('SELECT * FROM prompts WHERE id > ? ORDER BY id ASC LIMIT ?')\n .all(id, limit) as PromptEntry[];\n }\n\n getPromptCountAfterId(id: number): number {\n return (this.db.prepare('SELECT count(*) as c FROM prompts WHERE id > ?').get(id) as { c: number }).c;\n }\n\n getPromptCount(): number {\n return (this.db.prepare('SELECT count(*) as c FROM prompts').get() as { c: number }).c;\n }\n\n getPromptCountSince(timestamp: string): number {\n return (this.db.prepare('SELECT count(*) as c FROM prompts WHERE timestamp > ?').get(timestamp) as { c: number }).c;\n }\n\n getStats(): { total: number; totalMemories: number; byTool: Array<{ tool: string; count: number }> } {\n const total = (this.db.prepare('SELECT count(*) as c FROM prompts').get() as { c: number }).c;\n const totalMemories = (this.db.prepare('SELECT count(*) as c FROM memories').get() as { c: number }).c;\n const byTool = this.db\n .prepare('SELECT tool, count(*) as count FROM prompts GROUP BY tool ORDER BY count DESC')\n .all() as Array<{ tool: string; count: number }>;\n return { total, totalMemories, byTool };\n }\n\n getPromptBySyncHash(hash: string): PromptEntry | undefined {\n return this.db\n .prepare(\"SELECT * FROM prompts WHERE json_extract(metadata, '$.sync_hash') = ?\")\n .get(hash) as PromptEntry | undefined;\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 getProjectMemory(projectName: string, limit: number = 10): PromptEntry[] {\n return this.db\n .prepare(`\n SELECT * FROM prompts \n WHERE json_extract(metadata, '$.project') = ? \n AND json_extract(metadata, '$.summary') IS NOT NULL\n ORDER BY timestamp DESC \n LIMIT ?\n `)\n .all(projectName, limit) as PromptEntry[];\n }\n\n delete(id: number): void {\n this.db.prepare('DELETE FROM prompts WHERE id = ?').run(id);\n // Cascadedelete for embeddings/vec_embeddings should be handled by FOREIGN KEY if supported, \n // but better-sqlite3 needs pragma foreign_keys = ON.\n // However, vec0 doesn't support traditional foreign keys easily.\n this.db.prepare('DELETE FROM vec_embeddings WHERE rowid = ?').run(BigInt(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 \n // For vec_embeddings we need to loop and cast to BigInt\n const delVec = this.db.prepare('DELETE FROM vec_embeddings WHERE rowid = ?');\n for (const id of ids) {\n delVec.run(BigInt(id));\n }\n return info.changes;\n }\n\n deleteOlderThan(days: number): number {\n // We need to find IDs first to clean up vec_embeddings\n const ids = this.db\n .prepare(\"SELECT id FROM prompts WHERE timestamp < datetime('now', ?)\")\n .all(`-${days} days`) as { id: number }[];\n \n if (ids.length > 0) {\n return this.deleteByIds(ids.map(i => i.id));\n }\n return 0;\n }\n\n archivePrompts(ids: number[]): number { return this.archiveRepository.archivePrompts(ids); }\n searchArchive(opts: { since?: string; until?: string; limit?: number }): Array<Record<string, unknown>> { return this.archiveRepository.searchArchive(opts); }\n purgeArchive(beforeDate: string): number { return this.archiveRepository.purgeArchive(beforeDate); }\n getArchiveStats(): { total: number; oldest: string | null; newest: string | null } { return this.archiveRepository.getArchiveStats(); }\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 // ─── Memory repository facade ─────────────────────────────────────────────\n\n insertMemory(mem: Omit<MemoryEntry, 'id'>): number { return this.memoryRepository.insertMemory(mem); }\n promoteMemories(memories: Omit<MemoryEntry, 'id'>[]): number[] { return this.memoryRepository.promoteMemories(memories); }\n updateMemory(id: number, updates: Partial<Omit<MemoryEntry, 'id' | 'project' | 'created_at'>>): void { this.memoryRepository.updateMemory(id, updates); }\n getMemoryById(id: number): MemoryEntry | undefined { return this.memoryRepository.getMemoryById(id); }\n searchMemories(project: string, limit = 10): MemoryEntry[] { return this.memoryRepository.searchMemories(project, limit); }\n upsertProjectMemory(entry: { project: string; prompt_id: number; summary: string; key_insights: string[]; technical_decisions: string[]; git_context_snapshot?: string }): number { return this.memoryRepository.upsertProjectMemory(entry); }\n getLastMemoryForProject(project: string): MemoryEntry | undefined { return this.memoryRepository.getLastMemoryForProject(project); }\n getAllProjectsWithMemories(): string[] { return this.memoryRepository.getAllProjectsWithMemories(); }\n upsertProjectSummary(params: { project: string; summary: string; key_insights: string[]; technical_decisions: string[]; git_context_snapshot?: string }): void { this.memoryRepository.upsertProjectSummary(params); }\n getProjectSummary(project: string): ProjectSummary | null { return this.memoryRepository.getProjectSummary(project); }\n getAllProjectsWithSummaries(): string[] { return this.memoryRepository.getAllProjectsWithSummaries(); }\n recordMemoryAccess(id: number): void { this.memoryRepository.recordMemoryAccess(id); }\n deleteMemory(id: number): void { this.memoryRepository.deleteMemory(id); }\n getAllMemoriesByProject(project: string): MemoryEntry[] { return this.memoryRepository.getAllMemoriesByProject(project); }\n\n getAllPromptsByProject(project: string): PromptEntry[] {\n return this.db\n .prepare(`SELECT * FROM prompts WHERE json_extract(metadata, '$.project') = ? ORDER BY timestamp ASC`)\n .all(project) as PromptEntry[];\n }\n\n getPromptsByProjectPaginated(project: string, page: number, pageSize: number): { entries: PromptEntry[]; total: number } {\n const total = this.db.prepare(\"SELECT COUNT(*) as count FROM prompts WHERE json_extract(metadata, '$.project') = ?\").get(project) as { count: number };\n const entries = this.db\n .prepare(`SELECT * FROM prompts WHERE json_extract(metadata, '$.project') = ? ORDER BY timestamp DESC LIMIT ? OFFSET ?`)\n .all(project, pageSize, (page - 1) * pageSize) as PromptEntry[];\n return { entries, total: total.count };\n }\n\n getPromptCountByProject(project: string): number {\n const row = this.db.prepare(\"SELECT COUNT(*) as count FROM prompts WHERE json_extract(metadata, '$.project') = ?\").get(project) as { count: number };\n return row.count;\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 type Database from 'better-sqlite3';\nimport type { PromptEntry } from '../types.js';\n\n/** Owns vector encoding, compatibility storage, and semantic nearest-neighbor queries. */\nexport class SemanticIndex {\n constructor(private readonly db: Database.Database) {}\n\n save(promptId: number, vector: Float32Array): void {\n const encoded = this.encode(vector);\n // Keep the legacy BLOB table populated while older databases migrate.\n this.db.prepare('INSERT OR REPLACE INTO embeddings (prompt_id, vector) VALUES (?, ?)').run(promptId, encoded);\n this.db.prepare('INSERT OR REPLACE INTO vec_embeddings(rowid, embedding) VALUES (?, vec_f32(?))').run(BigInt(promptId), encoded);\n }\n\n search(query: Float32Array, limit: number, project?: string): PromptEntry[] {\n const encodedQuery = this.encode(query);\n // sqlite-vec applies k before SQLite evaluates metadata predicates. Scoped\n // searches therefore inspect all vectors, then filter and apply the limit.\n const projectFilter = project ? \"AND json_extract(p.metadata, '$.project') = ?\" : '';\n const candidateLimit = project\n ? Math.max(1, (this.db.prepare('SELECT count(*) AS count FROM vec_embeddings').get() as { count: number }).count)\n : limit;\n const sql = `\n SELECT p.*, v.distance\n FROM vec_embeddings v\n JOIN prompts p ON p.id = v.rowid\n WHERE v.embedding MATCH vec_f32(?) AND k = ?\n ${projectFilter}\n ORDER BY v.distance ASC\n `;\n return this.db.prepare(project ? `${sql} LIMIT ?` : sql).all(\n encodedQuery,\n candidateLimit,\n ...(project ? [project, limit] : []),\n ) as PromptEntry[];\n }\n\n loadAll(): Map<number, Float32Array> {\n const rows = this.db.prepare('SELECT prompt_id, vector FROM embeddings').all() as { prompt_id: number; vector: Buffer }[];\n return new Map(rows.map(row => [row.prompt_id, this.decode(row.vector)]));\n }\n\n loadProject(project: string): Map<number, Float32Array> {\n const rows = this.db.prepare(`\n SELECT e.prompt_id, e.vector\n FROM embeddings e\n JOIN prompts p ON p.id = e.prompt_id\n WHERE json_valid(p.metadata) AND json_extract(p.metadata, '$.project') = ?\n `).all(project) as { prompt_id: number; vector: Buffer }[];\n return new Map(rows.map(row => [row.prompt_id, this.decode(row.vector)]));\n }\n\n findMissingPrompts(): PromptEntry[] {\n return this.db.prepare(\n `SELECT p.* FROM prompts p\n LEFT JOIN vec_embeddings e ON e.rowid = p.id\n WHERE e.rowid IS NULL`,\n ).all() as PromptEntry[];\n }\n\n private encode(vector: Float32Array): Buffer {\n const buffer = Buffer.alloc(vector.length * 4);\n for (let i = 0; i < vector.length; i++) buffer.writeFloatLE(vector[i], i * 4);\n return buffer;\n }\n\n private decode(buffer: Buffer): Float32Array {\n const vector = new Float32Array(buffer.length / 4);\n for (let i = 0; i < vector.length; i++) vector[i] = buffer.readFloatLE(i * 4);\n return vector;\n }\n}\n","import type Database from 'better-sqlite3';\nimport type { MemoryEntry, ProjectSummary } from '../types.js';\n\nexport class MemoryRepository {\n constructor(private readonly db: Database.Database) {}\n\n insertMemory(mem: Omit<MemoryEntry, 'id'>): number {\n const info = this.db\n .prepare(`\n INSERT INTO memories (project, prompt_ids, summary, key_insights, technical_decisions,\n git_context_snapshot, created_at, updated_at, access_count, last_accessed)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n .run(\n mem.project,\n JSON.stringify(mem.prompt_ids),\n mem.summary,\n JSON.stringify(mem.key_insights),\n JSON.stringify(mem.technical_decisions),\n mem.git_context_snapshot ?? null,\n mem.created_at,\n mem.updated_at,\n mem.access_count,\n mem.last_accessed ?? null,\n );\n return info.lastInsertRowid as number;\n }\n\n /** Persist an approved knowledge batch and its aggregate summaries atomically. */\n promoteMemories(memories: Omit<MemoryEntry, 'id'>[]): number[] {\n return this.db.transaction(() => memories.map(memory => {\n const id = this.insertMemory(memory);\n this.upsertProjectSummary({\n project: memory.project,\n summary: memory.summary,\n key_insights: memory.key_insights,\n technical_decisions: memory.technical_decisions,\n git_context_snapshot: memory.git_context_snapshot,\n });\n return id;\n }))();\n }\n\n updateMemory(id: number, updates: Partial<Omit<MemoryEntry, 'id' | 'project' | 'created_at'>>): void {\n const setClauses: string[] = [];\n const params: unknown[] = [];\n\n if (updates.prompt_ids !== undefined) {\n setClauses.push('prompt_ids = ?');\n params.push(JSON.stringify(updates.prompt_ids));\n }\n if (updates.summary !== undefined) {\n setClauses.push('summary = ?');\n params.push(updates.summary);\n }\n if (updates.key_insights !== undefined) {\n setClauses.push('key_insights = ?');\n params.push(JSON.stringify(updates.key_insights));\n }\n if (updates.technical_decisions !== undefined) {\n setClauses.push('technical_decisions = ?');\n params.push(JSON.stringify(updates.technical_decisions));\n }\n if (updates.git_context_snapshot !== undefined) {\n setClauses.push('git_context_snapshot = ?');\n params.push(updates.git_context_snapshot);\n }\n if (updates.access_count !== undefined) {\n setClauses.push('access_count = ?');\n params.push(updates.access_count);\n }\n if (updates.last_accessed !== undefined) {\n setClauses.push('last_accessed = ?');\n params.push(updates.last_accessed);\n }\n\n setClauses.push('updated_at = ?');\n params.push(new Date().toISOString());\n params.push(id);\n\n this.db\n .prepare(`UPDATE memories SET ${setClauses.join(', ')} WHERE id = ?`)\n .run(...params);\n }\n\n getMemoryById(id: number): MemoryEntry | undefined {\n const row = this.db.prepare('SELECT * FROM memories WHERE id = ?').get(id) as Record<string, unknown> | undefined;\n if (!row) return undefined;\n return this.hydrateMemory(row);\n }\n\n searchMemories(project: string, limit: number = 10): MemoryEntry[] {\n const rows = this.db\n .prepare('SELECT * FROM memories WHERE project = ? ORDER BY updated_at DESC LIMIT ?')\n .all(project, limit) as Record<string, unknown>[];\n return rows.map(r => this.hydrateMemory(r));\n }\n\n upsertProjectMemory(entry: { project: string; prompt_id: number; summary: string; key_insights: string[]; technical_decisions: string[]; git_context_snapshot?: string }): number {\n // Append-only: create a new memory entry each time, preserving full history\n return this.insertMemory({\n project: entry.project,\n prompt_ids: [entry.prompt_id],\n summary: entry.summary,\n key_insights: entry.key_insights,\n technical_decisions: entry.technical_decisions,\n git_context_snapshot: entry.git_context_snapshot,\n created_at: new Date().toISOString(),\n updated_at: new Date().toISOString(),\n access_count: 0,\n last_accessed: undefined,\n });\n }\n\n getLastMemoryForProject(project: string): MemoryEntry | undefined {\n const row = this.db\n .prepare('SELECT * FROM memories WHERE project = ? ORDER BY updated_at DESC LIMIT 1')\n .get(project) as Record<string, unknown> | undefined;\n if (!row) return undefined;\n return this.hydrateMemory(row);\n }\n\n getAllProjectsWithMemories(): string[] {\n const rows = this.db\n .prepare('SELECT DISTINCT project FROM memories ORDER BY project')\n .all() as { project: string }[];\n return rows.map(r => r.project);\n }\n\n upsertProjectSummary(params: {\n project: string;\n summary: string;\n key_insights: string[];\n technical_decisions: string[];\n git_context_snapshot?: string;\n }): void {\n const existing = this.getProjectSummary(params.project);\n const now = new Date().toISOString();\n\n if (existing) {\n const allInsights = new Set([...existing.key_insights, ...params.key_insights]);\n const allDecisions = new Set([...existing.technical_decisions, ...params.technical_decisions]);\n\n this.db.prepare(`\n UPDATE project_summaries\n SET summary = ?,\n key_insights = ?,\n technical_decisions = ?,\n prompt_count = prompt_count + 1,\n last_analyzed = ?,\n git_context_snapshot = COALESCE(?, git_context_snapshot)\n WHERE project = ?\n `).run(\n params.summary,\n JSON.stringify([...allInsights]),\n JSON.stringify([...allDecisions]),\n now,\n params.git_context_snapshot || null,\n params.project\n );\n } else {\n this.db.prepare(`\n INSERT INTO project_summaries (project, summary, key_insights, technical_decisions, prompt_count, first_analyzed, last_analyzed, git_context_snapshot)\n VALUES (?, ?, ?, ?, 1, ?, ?, ?)\n `).run(\n params.project,\n params.summary,\n JSON.stringify(params.key_insights),\n JSON.stringify(params.technical_decisions),\n now,\n now,\n params.git_context_snapshot || null\n );\n }\n }\n\n getProjectSummary(project: string): ProjectSummary | null {\n const row = this.db.prepare('SELECT * FROM project_summaries WHERE project = ?').get(project) as Record<string, unknown> | undefined;\n if (!row) return null;\n return this.hydrateProjectSummary(row);\n }\n\n getAllProjectsWithSummaries(): string[] {\n const rows = this.db.prepare('SELECT project FROM project_summaries ORDER BY project').all() as { project: string }[];\n return rows.map(r => r.project);\n }\n\n recordMemoryAccess(id: number): void {\n this.db\n .prepare('UPDATE memories SET access_count = access_count + 1, last_accessed = ? WHERE id = ?')\n .run(new Date().toISOString(), id);\n }\n\n deleteMemory(id: number): void {\n this.db.prepare('DELETE FROM memories WHERE id = ?').run(id);\n }\n\n private hydrateMemory(row: Record<string, unknown>): MemoryEntry {\n return {\n id: row.id as number,\n project: row.project as string,\n prompt_ids: JSON.parse(row.prompt_ids as string),\n summary: row.summary as string,\n key_insights: JSON.parse(row.key_insights as string),\n technical_decisions: JSON.parse(row.technical_decisions as string),\n git_context_snapshot: row.git_context_snapshot as string | undefined,\n created_at: row.created_at as string,\n updated_at: row.updated_at as string,\n access_count: row.access_count as number,\n last_accessed: row.last_accessed as string | undefined,\n };\n }\n\n private hydrateProjectSummary(row: Record<string, unknown>): ProjectSummary {\n return {\n project: row.project as string,\n summary: row.summary as string,\n key_insights: JSON.parse(row.key_insights as string),\n technical_decisions: JSON.parse(row.technical_decisions as string),\n prompt_count: row.prompt_count as number,\n first_analyzed: row.first_analyzed as string,\n last_analyzed: row.last_analyzed as string,\n git_context_snapshot: row.git_context_snapshot as string | undefined,\n };\n }\n\n getAllMemoriesByProject(project: string): MemoryEntry[] {\n const rows = this.db\n .prepare('SELECT * FROM memories WHERE project = ? ORDER BY created_at ASC')\n .all(project) as Record<string, unknown>[];\n return rows.map(r => this.hydrateMemory(r));\n }\n\n}\n","import type Database from 'better-sqlite3';\nimport type { ArchivedPromptEntry } from '../types.js';\n\nexport class ArchiveRepository {\n constructor(private readonly db: Database.Database) {}\n\n archivePrompts(ids: number[]): number {\n if (ids.length === 0) return 0;\n const now = new Date().toISOString();\n const select = this.db.prepare(`\n SELECT id, timestamp, tool, prompt, response, args, workdir, hostname, exit_code, metadata\n FROM prompts WHERE id = ?\n `);\n const insert = this.db.prepare(`\n INSERT INTO prompts_archive (timestamp, tool, prompt, response, args, workdir, hostname, exit_code, metadata, archived_at, original_id)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `);\n const del = this.db.prepare('DELETE FROM prompts WHERE id = ?');\n\n const transaction = this.db.transaction((toArchive: number[]) => {\n let count = 0;\n for (const id of toArchive) {\n const row = select.get(id) as Record<string, unknown> | undefined;\n if (!row) continue;\n insert.run(\n row.timestamp, row.tool, row.prompt, row.response, row.args,\n row.workdir, row.hostname, row.exit_code, row.metadata,\n now, id\n );\n del.run(id);\n count++;\n }\n return count;\n });\n\n return transaction(ids);\n }\n\n searchArchive(opts: { since?: string; until?: string; limit?: number }): Array<Record<string, unknown>> {\n let sql = 'SELECT * FROM prompts_archive WHERE 1=1';\n const params: unknown[] = [];\n if (opts.since) { sql += ' AND timestamp >= ?'; params.push(opts.since); }\n if (opts.until) { sql += ' AND timestamp <= ?'; params.push(opts.until); }\n sql += ' ORDER BY timestamp DESC';\n if (opts.limit) { sql += ' LIMIT ?'; params.push(opts.limit); }\n return this.db.prepare(sql).all(...params) as Array<Record<string, unknown>>;\n }\n\n getByOriginalIdOrArchiveId(id: number): ArchivedPromptEntry | undefined {\n return this.db.prepare(\n 'SELECT * FROM prompts_archive WHERE original_id = ? OR (original_id IS NULL AND id = ?) ORDER BY archived_at DESC LIMIT 1'\n ).get(id, id) as ArchivedPromptEntry | undefined;\n }\n\n purgeArchive(beforeDate: string): number {\n const result = this.db.prepare('DELETE FROM prompts_archive WHERE archived_at < ?').run(beforeDate);\n return result.changes;\n }\n\n getArchiveStats(): { total: number; oldest: string | null; newest: string | null } {\n const row = this.db.prepare(`\n SELECT COUNT(*) as total, MIN(timestamp) as oldest, MAX(timestamp) as newest\n FROM prompts_archive\n `).get() as { total: number; oldest: string | null; newest: string | null };\n return row;\n }\n\n}\n","import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { CallToolRequestSchema, ListToolsRequestSchema } from \"@modelcontextprotocol/sdk/types.js\";\nimport { PhDB, defaultPath } from \"../db/index.js\";\nimport { load as loadConfig } from \"../config/index.js\";\nimport type { PhConfig } from \"../config/index.js\";\nimport { MCP_TOOL_DEFINITIONS } from \"./tools/definitions.js\";\nimport { handlePromptTool } from \"./tools/prompts.js\";\nimport { handleProjectTool } from \"./tools/projects.js\";\nimport { handleTimelineTool } from \"./tools/timeline.js\";\n\nexport function createMCPServer(db: PhDB, cfg: PhConfig = loadConfig()) {\n const server = new Server(\n { name: \"ph-memory\", version: \"1.0.0\" },\n { capabilities: { tools: {} } },\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: MCP_TOOL_DEFINITIONS,\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async request => {\n const { name, arguments: args } = request.params;\n try {\n const handlers = [handlePromptTool, handleProjectTool, handleTimelineTool];\n for (const handle of handlers) {\n const result = await handle(name, args, db, cfg);\n if (result) return result;\n }\n throw new Error(`Unknown tool: ${name}`);\n } catch (error) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error: ${(error as Error).message}` }],\n };\n }\n });\n\n return server;\n}\n\nexport async function runMCPServer() {\n const cfg = loadConfig();\n const dbPath = process.env.PH_DB ?? cfg.dbPath ?? defaultPath();\n const db = new PhDB(dbPath);\n const server = createMCPServer(db, cfg);\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error(\"ph MCP server running on stdio\");\n}\n","export const MCP_TOOL_DEFINITIONS = [\n {\n name: \"list_prompts\",\n description: \"List prompts for a project with pagination. Use page=1, pageSize=10 to browse.\",\n inputSchema: {\n type: \"object\",\n properties: {\n project: { type: \"string\", description: \"Project name to list prompts for\" },\n page: { type: \"number\", description: \"Page number (1-based)\", default: 1 },\n pageSize: { type: \"number\", description: \"Results per page (max 100)\", default: 20 },\n },\n required: [\"project\"],\n },\n },\n {\n name: \"save_decision\",\n description: \"Save an architectural decision or key insight to project memory.\",\n inputSchema: {\n type: \"object\",\n properties: {\n project: { type: \"string\", description: \"Project name\" },\n summary: { type: \"string\", description: \"Brief summary of the decision\" },\n keyInsights: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Key insights or takeaways\",\n },\n technicalDecisions: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Technical decisions made\",\n },\n promptIds: {\n type: \"array\",\n items: { type: \"number\" },\n description: \"Optional source prompt IDs; every prompt must belong to project\",\n },\n },\n required: [\"project\", \"summary\"],\n },\n },\n {\n name: \"get_project_diff\",\n description: \"Compare project state between two points in time. Shows prompts and memory entries created in the date range.\",\n inputSchema: {\n type: \"object\",\n properties: {\n project: { type: \"string\", description: \"Project name\" },\n since: { type: \"string\", description: \"Start date (ISO 8601, e.g. 2026-01-01)\" },\n until: { type: \"string\", description: \"End date (ISO 8601, defaults to now)\" },\n },\n required: [\"project\", \"since\"],\n },\n },\n {\n name: \"search_project_memory\",\n description: \"Search for past interactions and technical decisions in a specific project using semantic search.\",\n inputSchema: {\n type: \"object\",\n properties: {\n query: { type: \"string\", description: \"The search query (e.g. 'how did we handle auth?')\" },\n project: { type: \"string\", description: \"The project name to filter by\" },\n limit: { type: \"number\", description: \"Max results to return\", default: 5 },\n },\n required: [\"query\", \"project\"],\n },\n },\n {\n name: \"get_project_context\",\n description: \"Retrieve recent summaries, key insights, and technical decisions for a project.\",\n inputSchema: {\n type: \"object\",\n properties: {\n project: { type: \"string\", description: \"The project name\" },\n limit: { type: \"number\", description: \"Max interactions to retrieve\", default: 10 },\n },\n required: [\"project\"],\n },\n },\n {\n name: \"get_project_summary\",\n description: \"Get high-level accumulated project knowledge from memories: key insights and technical decisions.\",\n inputSchema: {\n type: \"object\",\n properties: {\n project: { type: \"string\", description: \"The project name\" },\n },\n required: [\"project\"],\n },\n },\n {\n name: \"search_prompts\",\n description: \"Search prompt history by text or filters. Omit query for recent prompts.\",\n inputSchema: {\n type: \"object\",\n properties: {\n query: { type: \"string\", description: \"Full-text search query (searches prompt + response)\" },\n tool: { type: \"string\", description: \"Filter by tool name (e.g. claude, gemini)\" },\n project: { type: \"string\", description: \"Filter by project name\" },\n role: { type: \"string\", description: \"Filter by role (debug, refactor, explain, etc.)\" },\n tag: { type: \"string\", description: \"Filter by tag\" },\n since: { type: \"string\", description: \"ISO date string — only prompts after this date\" },\n until: { type: \"string\", description: \"ISO date string — only prompts before this date\" },\n limit: { type: \"number\", description: \"Max results (default 10)\", default: 10 },\n },\n },\n },\n {\n name: \"get_prompt\",\n description: \"Get full details of a single prompt by ID.\",\n inputSchema: {\n type: \"object\",\n properties: {\n id: { type: \"number\", description: \"The prompt ID\" },\n },\n required: [\"id\"],\n },\n },\n {\n name: \"search_prompts_semantic\",\n description: \"Search prompt history by semantic similarity (vector search).\",\n inputSchema: {\n type: \"object\",\n properties: {\n query: { type: \"string\", description: \"Natural language query\" },\n project: { type: \"string\", description: \"Filter by project name\" },\n limit: { type: \"number\", description: \"Max results (default 5)\", default: 5 },\n },\n required: [\"query\"],\n },\n },\n {\n name: \"get_project_timeline\",\n description: \"Get full chronological timeline of a project: all prompts, analysis summaries, key insights, and technical decisions in sequence.\",\n inputSchema: {\n type: \"object\",\n properties: {\n project: { type: \"string\", description: \"The project name\" },\n since: { type: \"string\", description: \"Start date (ISO 8601, optional)\" },\n until: { type: \"string\", description: \"End date (ISO 8601, optional)\" },\n limit: { type: \"number\", description: \"Max events to return (default 100)\", default: 100 },\n },\n required: [\"project\"],\n },\n },\n {\n name: \"check_project_knowledge\",\n description: \"Before implementing a feature, check if it already exists in project history. Searches memories and prompts for previous implementations, discussions, and technical decisions related to a task.\",\n inputSchema: {\n type: \"object\",\n properties: {\n project: { type: \"string\", description: \"The project name\" },\n task: { type: \"string\", description: \"Description of the feature or task to check\" },\n limit: { type: \"number\", description: \"Max results per search (default 5)\", default: 5 },\n },\n required: [\"project\", \"task\"],\n },\n },\n ];\n","import type { PhDB } from '../../db/index.js';\nimport type { PhConfig } from '../../config/index.js';\nimport { z } from 'zod';\nimport type { PromptMetadata } from '../../types.js';\nimport { getEmbeddings } from '../../embedding/index.js';\nimport { formatPromptList, formatSinglePrompt } from './format.js';\n\nexport async function handlePromptTool(name: string, args: unknown, db: PhDB, cfg: PhConfig) {\n if (name === \"list_prompts\") {\n const { project, page = 1, pageSize = 20 } = z.object({\n project: z.string(),\n page: z.number().optional(),\n pageSize: z.number().max(100).optional(),\n }).parse(args);\n\n const result = db.getPromptsByProjectPaginated(project, page, pageSize);\n const totalPages = Math.ceil(result.total / pageSize);\n\n const text = [\n `## Prompts for \"${project}\"`,\n `Page ${page}/${totalPages} (${result.total} total)\\n`,\n ...result.entries.map(e => {\n let meta: PromptMetadata = {};\n try { meta = JSON.parse(e.metadata); } catch {}\n const date = new Date(e.timestamp).toLocaleString();\n const title = meta.title ? ` — ${meta.title}` : '';\n const roleStr = meta.role ? ` (${meta.role})` : '';\n return `### #${e.id} — ${e.tool}${roleStr} (${date})${title}\\n${(meta.summary ? `Summary: ${meta.summary}\\n` : '')}Prompt: ${e.prompt.slice(0, 200)}${e.prompt.length > 200 ? '...' : ''}`;\n }).join('\\n\\n'),\n '',\n `Page ${page}/${totalPages} | ${result.total} total prompts`,\n ].join('\\n');\n\n return { content: [{ type: \"text\", text }] };\n }\n\n if (name === \"search_prompts\") {\n const { query, tool, project, role, tag, since, until, limit = 10 } = z.object({\n query: z.string().optional(),\n tool: z.string().optional(),\n project: z.string().optional(),\n role: z.string().optional(),\n tag: z.string().optional(),\n since: z.string().optional(),\n until: z.string().optional(),\n limit: z.number().optional(),\n }).parse(args);\n\n const results = db.search({\n query,\n tool,\n project,\n role,\n tag,\n ...(since ? { since: new Date(since) } : {}),\n ...(until ? { until: new Date(until) } : {}),\n limit,\n });\n\n return {\n content: [{ type: \"text\", text: formatPromptList(results, query) }],\n };\n }\n\n if (name === \"get_prompt\") {\n const { id } = z.object({\n id: z.number(),\n }).parse(args);\n\n const entry = db.getById(id);\n if (!entry) {\n return {\n content: [{ type: \"text\", text: `Prompt #${id} not found.` }],\n };\n }\n\n return {\n content: [{ type: \"text\", text: formatSinglePrompt(entry) }],\n };\n }\n\n if (name === \"search_prompts_semantic\") {\n const { query, project, limit = 5 } = z.object({\n query: z.string(),\n project: z.string().optional(),\n limit: z.number().optional(),\n }).parse(args);\n\n const ollamaUrl = cfg.ollamaUrl ?? 'http://localhost:11434';\n const model = cfg.ollamaEmbedModel ?? 'nomic-embed-text-v2-moe';\n\n const [queryVec] = await getEmbeddings([query], ollamaUrl, model, 1);\n if (!queryVec) {\n throw new Error(\"Failed to generate embedding for query\");\n }\n\n const filtered = db.searchSemantic(queryVec, limit, project);\n\n return {\n content: [{ type: \"text\", text: formatPromptList(filtered, query) }],\n };\n }\n return undefined;\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 { PromptEntry, PromptMetadata } from '../types.js';\n\nexport type InteractionAnalysisStatus = 'pending' | 'complete' | 'failed' | 'not analyzed';\n\nexport interface InteractionDetail extends Omit<PromptEntry, 'metadata'> {\n metadata: PromptMetadata;\n analysis: {\n status: InteractionAnalysisStatus;\n error?: PromptMetadata['analysis_error'];\n summary?: string;\n key_insights: string[];\n technical_decisions: string[];\n quality?: number;\n relevance?: number;\n };\n}\n\nconst ANALYSIS_FIELDS: Array<keyof PromptMetadata> = [\n 'summary', 'key_insights', 'technical_decisions', 'quality', 'relevance',\n];\n\nexport function decodePromptMetadata(raw: string): PromptMetadata {\n try {\n const value: unknown = JSON.parse(raw);\n return value && typeof value === 'object' && !Array.isArray(value)\n ? value as PromptMetadata\n : {};\n } catch {\n return {};\n }\n}\n\nexport function toInteractionDetail(entry: PromptEntry): InteractionDetail {\n const metadata = decodePromptMetadata(entry.metadata);\n const hasAnalysis = ANALYSIS_FIELDS.some(key => {\n const value = metadata[key];\n return Array.isArray(value) ? value.length > 0 : value !== undefined;\n });\n const status = metadata.analysis_status ?? (hasAnalysis ? 'complete' : 'not analyzed');\n\n return {\n id: entry.id,\n timestamp: entry.timestamp,\n tool: entry.tool,\n prompt: entry.prompt,\n response: entry.response,\n args: entry.args,\n workdir: entry.workdir,\n hostname: entry.hostname,\n exit_code: entry.exit_code,\n metadata,\n analysis: {\n status,\n ...(metadata.analysis_error ? { error: metadata.analysis_error } : {}),\n ...(metadata.summary ? { summary: metadata.summary } : {}),\n key_insights: metadata.key_insights ?? [],\n technical_decisions: metadata.technical_decisions ?? [],\n ...(metadata.quality !== undefined ? { quality: metadata.quality } : {}),\n ...(metadata.relevance !== undefined ? { relevance: metadata.relevance } : {}),\n },\n };\n}\n\nexport function formatInteractionDetail(entry: PromptEntry): string {\n const detail = toInteractionDetail(entry);\n const meta = detail.metadata;\n const lines = [\n `Interaction #${detail.id}`,\n `Tool: ${detail.tool}`,\n `Date: ${detail.timestamp}`,\n `Project: ${meta.project ?? '(unknown)'}`,\n `Language: ${meta.language ?? '(unknown)'}`,\n `Role: ${meta.role ?? '(unclassified)'}`,\n `Tags: ${meta.tags?.join(', ') || '(none)'}`,\n `Workdir: ${detail.workdir || '(unknown)'}`,\n `Host: ${detail.hostname || '(unknown)'}`,\n `Exit code: ${detail.exit_code}`,\n `Response captured: ${detail.response ? 'yes' : 'no'}`,\n `Analysis: ${detail.analysis.status}${detail.analysis.error ? ` (${detail.analysis.error})` : ''}`,\n ];\n\n if (detail.analysis.summary) lines.push('', 'Analysis summary:', detail.analysis.summary);\n if (detail.analysis.relevance !== undefined) lines.push(`Relevance: ${detail.analysis.relevance}/10`);\n if (detail.analysis.quality !== undefined) lines.push(`Quality: ${detail.analysis.quality}/10`);\n if (detail.analysis.key_insights.length) {\n lines.push('', 'Key insights:', ...detail.analysis.key_insights.map(value => `- ${value}`));\n }\n if (detail.analysis.technical_decisions.length) {\n lines.push('', 'Technical decisions:', ...detail.analysis.technical_decisions.map(value => `- ${value}`));\n }\n if (meta.git_context) {\n lines.push('', 'Git context:', `Branch: ${meta.git_context.branch}`);\n if (meta.git_context.files.length) lines.push(`Files: ${meta.git_context.files.join(', ')}`);\n if (meta.git_context.diff) lines.push(meta.git_context.diff);\n }\n\n const known = new Set<string>([\n '$schema_version', 'title', 'project', 'language', 'role', 'tags', 'starred',\n 'relevance', 'quality', 'technical_decisions', 'git_context', 'summary',\n 'key_insights', 'analysis_status', 'analysis_error', 'remote_sync_status',\n 'remote_sync_error', 'remote_sync_target', 'capture_status', 'capture_owner_pid',\n ]);\n const additional = Object.fromEntries(Object.entries(meta).filter(([key]) => !known.has(key)));\n if (Object.keys(additional).length) lines.push('', 'Additional metadata:', JSON.stringify(additional, null, 2));\n\n lines.push('', 'Prompt:', detail.prompt || '(empty)', '', 'Response:', detail.response || '(No response captured)');\n return lines.join('\\n');\n}\n\nexport function formatInteractionMarkdown(entry: PromptEntry): string {\n const detail = toInteractionDetail(entry);\n const meta = detail.metadata;\n const lines = [\n `# Interaction #${detail.id}`,\n '',\n `- **Tool**: ${detail.tool}`,\n `- **Date**: ${detail.timestamp}`,\n `- **Project**: ${meta.project ?? '(unknown)'}`,\n `- **Language**: ${meta.language ?? '(unknown)'}`,\n `- **Role**: ${meta.role ?? '(unclassified)'}`,\n `- **Tags**: ${meta.tags?.join(', ') || '(none)'}`,\n `- **Workdir**: ${detail.workdir || '(unknown)'}`,\n `- **Host**: ${detail.hostname || '(unknown)'}`,\n `- **Exit code**: ${detail.exit_code}`,\n `- **Analysis**: ${detail.analysis.status}${detail.analysis.error ? ` (${detail.analysis.error})` : ''}`,\n '',\n '## Prompt',\n '',\n detail.prompt || '(empty)',\n '',\n '## Response',\n '',\n detail.response || '(No response captured)',\n '',\n '## Analysis',\n '',\n detail.analysis.summary ?? '(No summary)',\n '',\n `**Relevance**: ${detail.analysis.relevance === undefined ? '(not scored)' : `${detail.analysis.relevance}/10`}`,\n `**Quality**: ${detail.analysis.quality === undefined ? '(not scored)' : `${detail.analysis.quality}/10`}`,\n '',\n '### Key insights',\n '',\n ...(detail.analysis.key_insights.length ? detail.analysis.key_insights.map(value => `- ${value}`) : ['(None)']),\n '',\n '### Technical decisions',\n '',\n ...(detail.analysis.technical_decisions.length ? detail.analysis.technical_decisions.map(value => `- ${value}`) : ['(None)']),\n '',\n '## Metadata',\n '',\n '```json',\n JSON.stringify(meta, null, 2),\n '```',\n '',\n ];\n return lines.join('\\n');\n}\n\nexport function formatInteractionJson(entry: PromptEntry): string {\n return JSON.stringify(toInteractionDetail(entry), null, 2);\n}\n","import type { PromptEntry, PromptMetadata } from '../../types.js';\nimport { formatInteractionMarkdown } from '../../interaction/detail.js';\n\nexport function formatResultsAsMarkdown(entries: PromptEntry[]): string {\n if (entries.length === 0) return \"No relevant memory found for this project.\";\n\n return entries.map(e => {\n let meta: PromptMetadata = {};\n try { meta = JSON.parse(e.metadata); } catch {}\n\n let out = `### Interaction #${e.id} (${new Date(e.timestamp).toLocaleDateString()})\\n`;\n if (meta.role) out += `Role: ${meta.role} \\n`;\n if (meta.summary) out += `**Summary**: ${meta.summary}\\n`;\n out += `**Prompt**: ${e.prompt.slice(0, 300)}${e.prompt.length > 300 ? '...' : ''}\\n`;\n if (meta.key_insights && meta.key_insights.length > 0) {\n out += `**Key Insights**:\\n${meta.key_insights.map(i => `- ${i}`).join('\\n')}\\n`;\n }\n return out;\n }).join('\\n---\\n\\n');\n}\n\nexport function formatPromptList(entries: PromptEntry[], query?: string): string {\n if (entries.length === 0) return \"No prompts found.\";\n\n const header = query\n ? `Found ${entries.length} prompts matching \"${query}\":\\n\\n`\n : `Recent ${entries.length} prompts:\\n\\n`;\n\n return header + entries.map(e => {\n let meta: PromptMetadata = {};\n try { meta = JSON.parse(e.metadata); } catch {}\n\n const date = new Date(e.timestamp).toLocaleString();\n const proj = meta.project ? ` [${meta.project}]` : '';\n const title = meta.title ? ` — ${meta.title}` : '';\n const roleStr = meta.role ? ` \\nRole: ${meta.role}` : '';\n\n let out = `### #${e.id} — ${e.tool}${proj} (${date})${title}\\n`;\n if (meta.summary) out += `**Summary**: ${meta.summary} \\n`;\n out += `${roleStr} \\n`; // keep role placement consistent\n out += `**Prompt**: ${e.prompt.slice(0, 300)}${e.prompt.length > 300 ? '...' : ''}\\n`;\n if (e.response) {\n out += `**Response**: ${e.response.slice(0, 200)}${e.response.length > 200 ? '...' : ''}\\n`;\n }\n out += `Inspect full interaction with get_prompt(id: ${e.id}).\\n`;\n return out;\n }).join('\\n---\\n\\n');\n}\n\nexport function formatSinglePrompt(e: PromptEntry): string {\n return formatInteractionMarkdown(e);\n}\n","import type { PhDB } from '../../db/index.js';\nimport type { PhConfig } from '../../config/index.js';\nimport { z } from 'zod';\nimport type { PromptMetadata } from '../../types.js';\nimport { getEmbeddings } from '../../embedding/index.js';\nimport { formatProjectContext, getProjectContext } from '../../context/index.js';\nimport { formatResultsAsMarkdown } from './format.js';\nimport { promoteProjectKnowledge } from '../../knowledge/promotion.js';\nimport { retrieveTaskContext } from '../../knowledge/task-context.js';\n\nexport async function handleProjectTool(name: string, args: unknown, db: PhDB, cfg: PhConfig) {\n if (name === \"save_decision\") {\n const { project, summary, keyInsights, technicalDecisions, promptIds } = z.object({\n project: z.string(),\n summary: z.string(),\n keyInsights: z.array(z.string()).optional(),\n technicalDecisions: z.array(z.string()).optional(),\n promptIds: z.array(z.number().int().positive()).optional(),\n }).parse(args);\n\n const [id] = promoteProjectKnowledge(db, [{\n project,\n prompt_ids: [...new Set(promptIds ?? [])],\n summary,\n key_insights: keyInsights ?? [],\n technical_decisions: technicalDecisions ?? [],\n }]);\n\n return {\n content: [{ type: \"text\", text: `Decision saved as memory #${id} for project \"${project}\".\\n\\nSummary: ${summary}\\nKey Insights: ${(keyInsights ?? []).length}\\nTechnical Decisions: ${(technicalDecisions ?? []).length}` }],\n };\n }\n\n if (name === \"get_project_diff\") {\n const { project, since, until } = z.object({\n project: z.string(),\n since: z.string(),\n until: z.string().optional(),\n }).parse(args);\n\n const sinceDate = new Date(since);\n const untilDate = until ? new Date(until) : new Date();\n\n const prompts = db.search({\n project,\n since: sinceDate,\n until: untilDate,\n limit: 1000,\n });\n\n const memories = db.getAllMemoriesByProject(project)\n .filter(m => {\n const created = new Date(m.created_at);\n return created >= sinceDate && created <= untilDate;\n });\n\n const lines: string[] = [\n `## Project Diff: ${project}`,\n `From: ${since} To: ${until || 'now'}`,\n `Prompts: ${prompts.length} Memories: ${memories.length}\\n`,\n ];\n\n if (prompts.length > 0) {\n lines.push('### Prompts\\n');\n for (const p of prompts.reverse()) {\n let meta: PromptMetadata = {};\n try { meta = JSON.parse(p.metadata); } catch {}\n const title = meta.title ? ` — ${meta.title}` : '';\n const roleStr = meta.role ? ` (${meta.role})` : '';\n lines.push(`- **#${p.id}** ${p.tool}${roleStr}${title} (${new Date(p.timestamp).toLocaleDateString()})`);\n if (meta.summary) lines.push(` Summary: ${meta.summary}`);\n }\n }\n\n if (memories.length > 0) {\n lines.push('\\n### Memory Entries\\n');\n for (const m of memories) {\n lines.push(`- **Memory #${m.id}**: ${m.summary}`);\n for (const i of m.key_insights) lines.push(` - Insight: ${i}`);\n for (const d of m.technical_decisions) lines.push(` - Decision: ${d}`);\n }\n }\n\n return { content: [{ type: \"text\", text: lines.join('\\n') }] };\n }\n\n if (name === \"search_project_memory\") {\n const { query, project, limit = 5 } = z.object({\n query: z.string(),\n project: z.string(),\n limit: z.number().optional(),\n }).parse(args);\n\n const ollamaUrl = cfg.ollamaUrl ?? 'http://localhost:11434';\n const model = cfg.ollamaEmbedModel ?? 'nomic-embed-text-v2-moe';\n\n const [queryVec] = await getEmbeddings([query], ollamaUrl, model, 1);\n if (!queryVec) {\n throw new Error(\"Failed to generate embedding for query\");\n }\n\n const filtered = db.searchSemantic(queryVec, limit, project);\n\n if (filtered.length === 0) {\n const merged = db.getProjectSummary(project);\n if (merged) {\n const parts: string[] = [\n `## Project Knowledge: ${project}\\n`,\n `Based on ${merged.prompt_count} interactions.\\n`,\n ];\n if (merged.summary) parts.push(`${merged.summary}\\n`);\n if (merged.key_insights.length > 0) {\n parts.push('\\n**Key Insights:**');\n for (const i of merged.key_insights) parts.push(`- ${i}`);\n }\n if (merged.technical_decisions.length > 0) {\n parts.push('\\n**Technical Decisions:**');\n for (const d of merged.technical_decisions) parts.push(`- ${d}`);\n }\n return { content: [{ type: \"text\", text: parts.join('\\n') }] };\n }\n return { content: [{ type: \"text\", text: `No relevant memory found for project \"${project}\".` }] };\n }\n\n return {\n content: [{ type: \"text\", text: formatResultsAsMarkdown(filtered) }],\n };\n }\n\n if (name === \"get_project_context\") {\n const { project, limit = 10 } = z.object({\n project: z.string(),\n limit: z.number().optional(),\n }).parse(args);\n\n const context = await getProjectContext(db, { project, limit, memoryLimit: 3 });\n\n return {\n content: [{ type: \"text\", text: formatProjectContext(context, {\n promptExcerptLength: 300,\n responseExcerptLength: 200,\n emptyMessage: 'No context found for this project.',\n }) }],\n };\n }\n\n if (name === \"get_project_summary\") {\n const { project } = z.object({\n project: z.string(),\n }).parse(args);\n\n const summary = db.getProjectSummary(project);\n\n if (!summary) {\n return {\n content: [{ type: \"text\", text: `No accumulated knowledge for project \"${project}\". Run \"ph analyze\" to generate insights.` }],\n };\n }\n\n const parts: string[] = [];\n parts.push(`## ${summary.summary || 'Project Memory'}\\n`);\n parts.push(`Based on ${summary.prompt_count} interactions.\\n`);\n if (summary.key_insights.length > 0) {\n parts.push('**Key Insights:**');\n for (const i of summary.key_insights) parts.push(`- ${i}`);\n parts.push('');\n }\n if (summary.technical_decisions.length > 0) {\n parts.push('**Technical Decisions:**');\n for (const d of summary.technical_decisions) parts.push(`- ${d}`);\n parts.push('');\n }\n\n return {\n content: [{ type: \"text\", text: parts.join('\\n') }],\n };\n }\n\n if (name === \"check_project_knowledge\") {\n const { project, task, limit = 5 } = z.object({\n project: z.string(),\n task: z.string(),\n limit: z.number().optional(),\n }).parse(args);\n\n const { context, fallbackReason } = await retrieveTaskContext(db, cfg, project, task, limit);\n const warning = fallbackReason ? 'Semantic search unavailable; showing recent project context.' : '';\n const rendered = formatProjectContext(context, { promptExcerptLength: 400, responseExcerptLength: 250, emptyMessage: 'No existing knowledge found for this task. This appears to be new work.' });\n return {\n content: [{ type: \"text\", text: `# Knowledge Check: \"${task}\" in ${project}\\n\\n${warning ? `> ${warning}\\n\\n` : ''}${rendered}\\n\\n---\\n**Recommendation**: Review related evidence before implementing; adapt prior work where it applies.` }],\n };\n }\n return undefined;\n}\n","import type { MemoryEntry, ProjectSummary, PromptEntry, PromptMetadata } from '../types.js';\n\nexport interface ProjectContextStore {\n getProjectSummary(project: string): ProjectSummary | null;\n searchMemories(project: string, limit?: number): MemoryEntry[];\n getProjectMemory(project: string, limit?: number): PromptEntry[];\n searchSemantic(queryVector: Float32Array, limit: number, project?: string): PromptEntry[];\n}\n\nexport interface ProjectContextOptions {\n project: string;\n query?: string;\n limit?: number;\n memoryLimit?: number;\n includeSummary?: boolean;\n includeMemories?: boolean;\n includePrompts?: boolean;\n}\n\nexport interface ProjectContext {\n project: string;\n summary: ProjectSummary | null;\n memories: MemoryEntry[];\n prompts: PromptEntry[];\n}\n\nexport type ContextEmbedder = (query: string) => Promise<Float32Array | undefined>;\n\n/** Retrieve all project context evidence through one consumer-facing boundary. */\nexport async function getProjectContext(\n db: ProjectContextStore,\n options: ProjectContextOptions,\n embedQuery?: ContextEmbedder,\n): Promise<ProjectContext> {\n const limit = Math.max(1, Math.floor(options.limit ?? 5));\n const memoryLimit = Math.max(1, Math.floor(options.memoryLimit ?? limit));\n const includeSummary = options.includeSummary ?? true;\n const includeMemories = options.includeMemories ?? true;\n const includePrompts = options.includePrompts ?? true;\n\n const summary = includeSummary ? db.getProjectSummary(options.project) : null;\n const memories = includeMemories ? db.searchMemories(options.project, memoryLimit) : [];\n let prompts: PromptEntry[] = [];\n\n if (includePrompts) {\n const query = options.query?.trim();\n if (query) {\n if (!embedQuery) throw new Error('Semantic context requires an embedding provider.');\n const vector = await embedQuery(query);\n prompts = vector ? db.searchSemantic(vector, limit, options.project) : [];\n } else {\n prompts = db.getProjectMemory(options.project, limit);\n }\n }\n\n return { project: options.project, summary, memories, prompts };\n}\n\nexport interface FormatProjectContextOptions {\n includePromptText?: boolean;\n promptExcerptLength?: number;\n responseExcerptLength?: number;\n emptyMessage?: string;\n maxChars?: number;\n}\n\n/** Render retrieved evidence as stable Markdown for terminal and agent consumers. */\nexport function formatProjectContext(\n context: ProjectContext,\n options: FormatProjectContextOptions = {},\n): string {\n const parts: string[] = [];\n const { summary, memories, prompts, project } = context;\n\n if (summary || memories.length > 0) {\n parts.push(`## Project Knowledge: ${project}\\n`);\n if (summary?.summary) parts.push(`${summary.summary}\\n`);\n if (summary?.key_insights.length) {\n parts.push('Key Insights:');\n for (const insight of summary.key_insights) parts.push(` - ${insight}`);\n parts.push('');\n }\n if (summary?.technical_decisions.length) {\n parts.push('Technical Decisions:');\n for (const decision of summary.technical_decisions) parts.push(` - ${decision}`);\n parts.push('');\n }\n if (!summary && memories.length > 0) {\n for (const memory of memories) {\n parts.push(`### Memory #${memory.id}`);\n if (memory.summary) parts.push(`${memory.summary}\\n`);\n parts.push(memory.prompt_ids.length ? `Sources: ${memory.prompt_ids.map(id => `#${id}`).join(', ')}` : 'Sources: none recorded');\n if (memory.key_insights.length) {\n parts.push('Key Insights:');\n for (const insight of memory.key_insights) parts.push(` - ${insight}`);\n parts.push('');\n }\n if (memory.technical_decisions.length) {\n parts.push('Technical Decisions:');\n for (const decision of memory.technical_decisions) parts.push(` - ${decision}`);\n parts.push('');\n }\n }\n }\n if (summary && memories.length > 0) {\n parts.push('Recent Memory Entries:');\n for (const memory of memories) {\n if (memory.summary) parts.push(` - [memory #${memory.id}; prompts ${memory.prompt_ids.length ? memory.prompt_ids.map(id => `#${id}`).join(', ') : 'none recorded'}] ${memory.summary}`);\n }\n parts.push('');\n }\n }\n\n if (prompts.length > 0) {\n if (parts.length > 0) parts.push('---\\n');\n parts.push('## Recent Context\\n');\n for (const entry of prompts) {\n let metadata: PromptMetadata = {};\n try { metadata = JSON.parse(entry.metadata) as PromptMetadata; } catch {}\n parts.push(`### Interaction #${entry.id} — ${entry.tool} (${new Date(entry.timestamp).toLocaleDateString()})`);\n if (metadata.role) parts.push(`Role: ${metadata.role}`);\n const promptSummary = metadata.summary || (\n options.includePromptText || options.promptExcerptLength\n ? ''\n : entry.prompt.slice(0, 100).replace(/\\n/g, ' ')\n );\n if (promptSummary) parts.push(promptSummary);\n if (metadata.key_insights?.length) {\n for (const insight of metadata.key_insights) parts.push(` - ${insight}`);\n }\n if (options.includePromptText) {\n parts.push('```\\n' + entry.prompt.slice(0, 1000) + (entry.prompt.length > 1000 ? '\\n...' : '') + '\\n```');\n } else if (options.promptExcerptLength) {\n const excerpt = entry.prompt.slice(0, options.promptExcerptLength);\n parts.push(`Prompt: ${excerpt}${entry.prompt.length > options.promptExcerptLength ? '...' : ''}`);\n }\n if (options.responseExcerptLength && entry.response) {\n const response = entry.response.slice(0, options.responseExcerptLength);\n parts.push(`Response: ${response}${entry.response.length > options.responseExcerptLength ? '...' : ''}`);\n }\n parts.push('');\n }\n }\n\n if (parts.length === 0) return options.emptyMessage ?? `No relevant context found for project \"${project}\".`;\n const rendered = parts.join('\\n').trimEnd();\n if (!options.maxChars || rendered.length <= options.maxChars) return rendered;\n\n const sources = new Set<string>();\n for (const memory of memories) {\n if (memory.prompt_ids.length) sources.add(`memory #${memory.id} ← prompts ${memory.prompt_ids.map(id => `#${id}`).join(', ')}`);\n else sources.add(`memory #${memory.id} (no prompt source recorded)`);\n }\n for (const prompt of prompts) sources.add(`prompt #${prompt.id} (${prompt.tool}, ${prompt.timestamp})`);\n const sourceBlock = `\\n\\nSources:\\n${[...sources].map(source => `- ${source}`).join('\\n')}`;\n const budget = Math.max(0, options.maxChars - sourceBlock.length - 40);\n const prefix = rendered.slice(0, budget).trimEnd();\n return `${prefix}${prefix ? '\\n\\n' : ''}[Context truncated; source references are preserved]${sourceBlock}`;\n}\n","import type { MemoryEntry, PromptMetadata } from '../types.js';\n\nexport interface KnowledgeProposalInput {\n project: string;\n prompt_ids: number[];\n summary: string;\n key_insights: string[];\n technical_decisions: string[];\n}\n\nexport interface KnowledgePromotionStore {\n getById(id: number): { metadata: string } | undefined;\n promoteMemories(memories: Omit<MemoryEntry, 'id'>[]): number[];\n}\n\n/** Validate provenance and atomically persist approved project knowledge. */\nexport function promoteProjectKnowledge(\n store: KnowledgePromotionStore,\n proposals: KnowledgeProposalInput[],\n): number[] {\n for (const proposal of proposals) {\n for (const sourceId of new Set(proposal.prompt_ids)) {\n const prompt = store.getById(sourceId);\n let metadata: PromptMetadata = {};\n try { if (prompt) metadata = JSON.parse(prompt.metadata) as PromptMetadata; } catch {}\n if (!prompt || metadata.project !== proposal.project) {\n throw new Error(`Prompt #${sourceId} does not exist in project \"${proposal.project}\".`);\n }\n }\n }\n\n return store.promoteMemories(proposals.map(proposal => {\n const now = new Date().toISOString();\n return {\n ...proposal,\n created_at: now,\n updated_at: now,\n access_count: 0,\n };\n }));\n}\n","import { getEmbeddings } from '../embedding/index.js';\nimport { getProjectContext } from '../context/index.js';\nimport type { ProjectContextOptions } from '../context/index.js';\nimport type { ProjectContext, ProjectContextStore } from '../context/index.js';\nimport type { PhConfig } from '../config/index.js';\n\nexport async function retrieveTaskContext(\n db: ProjectContextStore,\n cfg: Pick<PhConfig, 'ollamaUrl' | 'ollamaEmbedModel'>,\n project: string,\n task: string,\n limit: number,\n options: Pick<ProjectContextOptions, 'includeSummary' | 'includeMemories' | 'includePrompts'> = {},\n): Promise<{ context: ProjectContext; fallbackReason?: string }> {\n try {\n const context = await getProjectContext(db, { project, query: task, limit, memoryLimit: limit, ...options }, async query => {\n const [vector] = await getEmbeddings(\n [`${project}: ${query}`],\n cfg.ollamaUrl ?? 'http://localhost:11434',\n cfg.ollamaEmbedModel ?? 'nomic-embed-text-v2-moe',\n 1,\n );\n if (!vector?.length) throw new Error('Embedding provider returned no vector');\n return vector;\n });\n return { context };\n } catch (error) {\n const context = await getProjectContext(db, { project, limit, memoryLimit: limit, ...options });\n return { context, fallbackReason: (error as Error).message };\n }\n}\n","import type { PhDB } from '../../db/index.js';\nimport type { PhConfig } from '../../config/index.js';\nimport { z } from 'zod';\nimport type { PromptMetadata } from '../../types.js';\n\nexport async function handleTimelineTool(name: string, args: unknown, db: PhDB, _cfg: PhConfig) {\n if (name === \"get_project_timeline\") {\n const { project, since, until, limit = 100 } = z.object({\n project: z.string(),\n since: z.string().optional(),\n until: z.string().optional(),\n limit: z.number().optional(),\n }).parse(args);\n\n let allPrompts = db.getAllPromptsByProject(project);\n let memories = db.getAllMemoriesByProject(project);\n\n // Apply date filters\n if (since) {\n const sinceDate = new Date(since);\n allPrompts = allPrompts.filter(p => new Date(p.timestamp) >= sinceDate);\n memories = memories.filter(m => new Date(m.created_at) >= sinceDate);\n }\n if (until) {\n const untilDate = new Date(until);\n allPrompts = allPrompts.filter(p => new Date(p.timestamp) <= untilDate);\n memories = memories.filter(m => new Date(m.created_at) <= untilDate);\n }\n\n if (allPrompts.length === 0 && memories.length === 0) {\n return {\n content: [{ type: \"text\", text: `No history found for project \"${project}\"${since ? ` since ${since}` : ''}${until ? ` until ${until}` : ''}.` }],\n };\n }\n\n const events: Array<{ timestamp: string; text: string }> = [];\n\n for (const p of allPrompts.slice(0, limit)) {\n let meta: PromptMetadata = {};\n try { meta = JSON.parse(p.metadata); } catch {}\n events.push({\n timestamp: p.timestamp,\n text: [\n `### #${p.id} — ${p.tool}`,\n meta.role ? `Role: ${meta.role}` : '',\n meta.title ? `Title: ${meta.title}` : '',\n meta.tags?.length ? `Tags: ${meta.tags.join(', ')}` : '',\n meta.summary ? `Summary: ${meta.summary}` : '',\n `Prompt: ${p.prompt.slice(0, 500)}${p.prompt.length > 500 ? '...' : ''}`,\n p.response ? `Response: ${p.response.slice(0, 300)}${p.response.length > 300 ? '...' : ''}` : '',\n meta.key_insights?.length ? `Insights:\\n${meta.key_insights.map(i => `- ${i}`).join('\\n')}` : '',\n ].filter(Boolean).join('\\n'),\n });\n }\n\n for (const m of memories) {\n events.push({\n timestamp: m.created_at,\n text: [\n `📌 Memory #${m.id}`,\n m.prompt_ids.length > 0 ? `From prompts: #${m.prompt_ids.join(', #')}` : '',\n m.summary ? `Summary: ${m.summary}` : '',\n m.key_insights.length > 0 ? `Key Insights:\\n${m.key_insights.map(i => `- ${i}`).join('\\n')}` : '',\n m.technical_decisions.length > 0 ? `Technical Decisions:\\n${m.technical_decisions.map(d => `- ${d}`).join('\\n')}` : '',\n ].filter(Boolean).join('\\n'),\n });\n }\n\n events.sort((a, b) => a.timestamp.localeCompare(b.timestamp));\n\n const range = since || until ? ` (${since || '…'} → ${until || 'now'})` : '';\n const header = `# Timeline: ${project}${range}\\n\\n${allPrompts.length} prompts · ${memories.length} memory entries\\n\\n`;\n const body = events.map(e => {\n const date = new Date(e.timestamp).toLocaleDateString('en-CA');\n const time = new Date(e.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });\n return `## ${date} ${time}\\n\\n${e.text}\\n`;\n }).join('---\\n');\n\n return {\n content: [{ type: \"text\", text: header + body }],\n };\n }\n return undefined;\n}\n","import http from 'http';\nimport { URL } from 'url';\nimport { PhDB, defaultPath } from '../db/index.js';\nimport { load as loadConfig } from '../config/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport { getEmbeddings } from '../embedding/index.js';\nimport { syncHash } from '../utils/syncHash.js';\nimport { timingSafeEqual } from 'crypto';\nimport { MAX_REQUEST_BODY_BYTES, SYNC_PAGE_SIZE } from '../sync/protocol.js';\n\nexport async function runServer(port: number = 3001, host: string = '127.0.0.1'): Promise<void> {\n const cfg = loadConfig();\n assertServerConfig(cfg);\n const dbPath = process.env.PH_DB ?? cfg.dbPath ?? defaultPath();\n const db = new PhDB(dbPath);\n\n const server = http.createServer(createRequestHandler(db, cfg));\n\n return new Promise((resolve) => {\n server.listen(port, host, () => {\n console.error(`ph server listening on http://${host}:${port}`);\n resolve();\n });\n });\n}\n\nexport function assertServerConfig(cfg: PhConfig): void {\n if (!cfg.remoteApiKey?.trim()) {\n throw new Error('Configure remote-api-key before starting the PH HTTP server.');\n }\n}\n\n/**\n * Builds the request handler for a PhDB + config. Exported for testability\n * (SPEC-ISSUES-013: auth enforcement lives here).\n */\nexport function createRequestHandler(db: PhDB, cfg: PhConfig) {\n return async (req: http.IncomingMessage, res: http.ServerResponse): Promise<void> => {\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n const url = new URL(req.url || '/', `http://${req.headers.host || 'localhost'}`);\n\n // Health is public; all other endpoints require a configured bearer key.\n if (url.pathname !== '/health' && !authorized(req, cfg)) {\n json(res, 401, { error: 'unauthorized' });\n return;\n }\n\n try {\n const body = await readBody(req, MAX_REQUEST_BODY_BYTES);\n await route(req, res, body, db, cfg);\n } catch (err) {\n if ((err as Error).name === 'RequestBodyTooLargeError') {\n json(res, 413, { error: 'request body too large' });\n } else if (err instanceof SyntaxError) {\n json(res, 400, { error: 'invalid JSON request body' });\n } else {\n json(res, 500, { error: 'internal server error' });\n }\n }\n };\n}\n\nfunction authorized(req: http.IncomingMessage, cfg: PhConfig): boolean {\n if (!cfg.remoteApiKey?.trim()) return false;\n const expected = `Bearer ${cfg.remoteApiKey}`;\n const a = Buffer.from(req.headers.authorization ?? '');\n const b = Buffer.from(expected);\n return a.length === b.length && timingSafeEqual(a, b);\n}\n\nasync function route(req: http.IncomingMessage, res: http.ServerResponse, body: string, db: PhDB, cfg: PhConfig): Promise<void> {\n const url = new URL(req.url || '/', `http://${req.headers.host || 'localhost'}`);\n const path = url.pathname;\n const method = req.method || 'GET';\n\n if (method === 'GET' && path === '/health') {\n return json(res, 200, { status: 'ok' });\n }\n\n if (method === 'POST' && path === '/api/prompts/search') {\n const { query, tool, project, role, tag, since, until, limit = 10 } = JSON.parse(body);\n const results = db.search({\n query,\n tool,\n project,\n role,\n tag,\n ...(since ? { since: new Date(since) } : {}),\n ...(until ? { until: new Date(until) } : {}),\n limit,\n });\n return json(res, 200, { prompts: results });\n }\n\n if (method === 'POST' && path === '/api/prompts/by-id') {\n const { id } = JSON.parse(body);\n const entry = db.getById(id);\n if (!entry) return json(res, 404, { error: `Prompt #${id} not found` });\n return json(res, 200, { prompt: entry });\n }\n\n if (method === 'POST' && path === '/api/prompts/semantic') {\n const { query, project, limit = 5 } = JSON.parse(body);\n if (!query) return json(res, 400, { error: 'query is required' });\n\n const ollamaUrl = cfg.ollamaUrl ?? 'http://localhost:11434';\n const model = cfg.ollamaEmbedModel ?? 'nomic-embed-text-v2-moe';\n const [queryVec] = await getEmbeddings([query], ollamaUrl, model, 1);\n if (!queryVec) return json(res, 500, { error: 'Failed to generate embedding' });\n\n const filtered = db.searchSemantic(queryVec, limit, project);\n\n return json(res, 200, { prompts: filtered });\n }\n\n if (method === 'POST' && path === '/api/sync/push') {\n const { prompts } = JSON.parse(body);\n if (!Array.isArray(prompts)) return json(res, 400, { error: 'prompts must be an array' });\n if (prompts.length > SYNC_PAGE_SIZE) return json(res, 400, { error: `prompts must contain at most ${SYNC_PAGE_SIZE} records` });\n\n let imported = 0;\n let skipped = 0;\n const errors: string[] = [];\n\n for (const p of prompts) {\n try {\n const hash = syncHash(p);\n const existing = db.getPromptBySyncHash(hash);\n if (existing) { skipped++; continue; }\n\n const metaObj = { ...JSON.parse(p.metadata || '{}'), sync_hash: hash };\n db.insert({\n timestamp: p.timestamp || new Date().toISOString(),\n tool: p.tool || 'unknown',\n prompt: p.prompt || '',\n response: p.response || '',\n args: p.args || '',\n workdir: p.workdir || '',\n hostname: p.hostname || '',\n exit_code: p.exit_code ?? 0,\n metadata: JSON.stringify(metaObj),\n });\n imported++;\n } catch {\n errors.push('record rejected');\n }\n }\n\n return json(res, 200, { imported, skipped, errors });\n }\n\n if (method === 'POST' && path === '/api/sync/pull') {\n const { afterId = 0, limit = SYNC_PAGE_SIZE } = JSON.parse(body);\n if (!Number.isInteger(afterId) || afterId < 0 || !Number.isInteger(limit) || limit < 1 || limit > SYNC_PAGE_SIZE) {\n return json(res, 400, { error: 'afterId and limit are outside the supported range' });\n }\n const page = db.getPromptsAfterId(afterId, limit + 1);\n const hasMore = page.length > limit;\n const prompts = hasMore ? page.slice(0, limit) : page;\n const nextCursor = prompts.at(-1)?.id ?? afterId;\n return json(res, 200, { prompts, hasMore, nextCursor });\n }\n\n if (method === 'POST' && path === '/api/memories/search') {\n const { project, limit = 10 } = JSON.parse(body);\n const memories = project\n ? db.searchMemories(project, limit)\n : [];\n return json(res, 200, { memories });\n }\n\n if (method === 'POST' && path === '/api/memories/summary') {\n const { project } = JSON.parse(body);\n if (!project) return json(res, 400, { error: 'project is required' });\n const memories = db.searchMemories(project, 5);\n return json(res, 200, { memories });\n }\n\n if (method === 'GET' && path === '/api/stats') {\n const { total, totalMemories, byTool } = db.getStats();\n return json(res, 200, { total, totalMemories, byTool });\n }\n\n json(res, 404, { error: `Not found: ${method} ${path}` });\n}\n\nfunction json(res: http.ServerResponse, status: number, data: unknown): void {\n res.writeHead(status, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(data));\n}\n\nfunction readBody(req: http.IncomingMessage, maxBytes: number): Promise<string> {\n return new Promise((resolve, reject) => {\n if (req.method === 'GET') return resolve('');\n const chunks: Buffer[] = [];\n let size = 0;\n let rejected = false;\n req.on('data', (chunk: Buffer) => {\n if (rejected) return;\n size += chunk.length;\n if (size > maxBytes) {\n rejected = true;\n const error = new Error('request body too large');\n error.name = 'RequestBodyTooLargeError';\n reject(error);\n req.resume();\n return;\n }\n chunks.push(chunk);\n });\n req.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));\n req.on('error', reject);\n });\n}\n","import { createHash } from 'crypto';\n\n/**\n * Shared sync dedup key (SPEC-010).\n * Previously duplicated as inline sha256 in server/index.ts and\n * commands/remote.ts (SPEC-ISSUES-012): the two copies could drift.\n *\n * Backward compatible (SPEC-ISSUES-012): entries WITHOUT args hash exactly as\n * the legacy `tool|prompt|response` format, so existing sync_hash values are\n * preserved and nothing is re-pushed. Entries WITH args include them — two runs\n * of the same tool+prompt with different args are distinct interactions and\n * must NOT collapse on pull.\n */\nexport function syncHash(entry: { tool: string; prompt: string; response: string; args?: string }): string {\n const body = entry.args\n ? `${entry.tool}|${entry.prompt}|${entry.response}|${entry.args}`\n : `${entry.tool}|${entry.prompt}|${entry.response}`;\n return createHash('sha256').update(body).digest('hex');\n}\n","import { createHash } from 'node:crypto';\nimport type { PromptEntry } from '../types.js';\n\nexport const SYNC_PAGE_SIZE = 500;\nexport const MAX_REQUEST_BODY_BYTES = 32 * 1024 * 1024;\n\nexport interface SyncCursor {\n target: string;\n databaseId: string;\n id: number;\n}\n\nexport interface SyncPushResponse {\n imported: number;\n skipped: number;\n errors: string[];\n}\n\nexport interface SyncPullResponse {\n prompts: PromptEntry[];\n hasMore: boolean;\n nextCursor: number;\n}\n\n/** Parse only absolute HTTP(S) endpoints accepted by fetch. */\nexport function parseRemoteUrl(url: string): URL {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n throw new Error('Remote URL must be an absolute HTTP or HTTPS URL.');\n }\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n throw new Error('Remote URL must use HTTP or HTTPS.');\n }\n if (!parsed.hostname) throw new Error('Remote URL must include a host.');\n return parsed;\n}\n\n/** Target identity excludes credentials/query parameters so secrets are never persisted in the cursor. */\nexport function syncTarget(url: string): string {\n const parsed = parseRemoteUrl(url);\n const canonical = `${parsed.protocol}//${parsed.host}${parsed.pathname.replace(/\\/$/, '')}`;\n return createHash('sha256').update(canonical).digest('hex');\n}\n\nexport function parseSyncPushResponse(value: unknown): SyncPushResponse {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('Remote server returned an invalid push response.');\n }\n const result = value as Partial<SyncPushResponse>;\n if (!Number.isInteger(result.imported) || result.imported! < 0 || !Number.isInteger(result.skipped) || result.skipped! < 0 || !Array.isArray(result.errors)) {\n throw new Error('Remote server returned an invalid push response.');\n }\n if (result.errors.some(error => typeof error !== 'string')) {\n throw new Error('Remote server returned an invalid push response.');\n }\n return result as SyncPushResponse;\n}\n\nexport function parseSyncPullResponse(value: unknown): SyncPullResponse {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('Remote server does not support cursor-based sync; upgrade the remote PH server.');\n }\n const result = value as Partial<SyncPullResponse>;\n if (!Array.isArray(result.prompts) || typeof result.hasMore !== 'boolean' || !Number.isInteger(result.nextCursor) || result.nextCursor! < 0) {\n throw new Error('Remote server does not support cursor-based sync; upgrade the remote PH server.');\n }\n if (result.prompts.some(prompt => !prompt || !Number.isInteger(prompt.id) || prompt.id < 1)) {\n throw new Error('Remote server returned an invalid sync page.');\n }\n return result as SyncPullResponse;\n}\n","import type { PromptEntry } from '../types.js';\nimport { MAX_REQUEST_BODY_BYTES, parseSyncPushResponse } from './protocol.js';\n\nexport interface SyncPushOptions {\n timeoutMs?: number;\n maxBodyBytes?: number;\n}\n\nexport function splitSyncPushPages(prompts: PromptEntry[], maxBodyBytes = MAX_REQUEST_BODY_BYTES): PromptEntry[][] {\n if (!Number.isInteger(maxBodyBytes) || maxBodyBytes < 1) throw new Error('Sync request body limit must be a positive integer.');\n const pages: PromptEntry[][] = [];\n let current: PromptEntry[] = [];\n const wrapperBytes = Buffer.byteLength('{\"prompts\":[]}', 'utf8');\n let currentBytes = wrapperBytes;\n\n for (const prompt of prompts) {\n const encoded = JSON.stringify(prompt);\n const promptBytes = Buffer.byteLength(encoded, 'utf8');\n const additionalBytes = promptBytes + (current.length ? 1 : 0);\n if (wrapperBytes + promptBytes > maxBodyBytes) {\n throw new Error(`Interaction #${prompt.id} exceeds the remote request body limit (${maxBodyBytes} bytes).`);\n }\n if (current.length && currentBytes + additionalBytes > maxBodyBytes) {\n pages.push(current);\n current = [];\n currentBytes = wrapperBytes;\n }\n current.push(prompt);\n currentBytes += promptBytes + (current.length > 1 ? 1 : 0);\n }\n\n if (current.length) pages.push(current);\n return pages;\n}\n\nexport async function sendSyncPushPage(url: string, apiKey: string | undefined, prompts: PromptEntry[], options: SyncPushOptions = {}): Promise<{ imported: number; skipped: number; errors: string[] }> {\n const totals = { imported: 0, skipped: 0, errors: [] as string[] };\n for (const page of splitSyncPushPages(prompts, options.maxBodyBytes)) {\n const res = await fetch(`${url}/api/sync/push`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}),\n },\n ...(options.timeoutMs ? { signal: AbortSignal.timeout(options.timeoutMs) } : {}),\n body: JSON.stringify({ prompts: page }),\n });\n if (!res.ok) throw new Error(`Remote error ${res.status}: ${await res.text()}`);\n const result = parseSyncPushResponse(await res.json());\n totals.imported += result.imported;\n totals.skipped += result.skipped;\n totals.errors.push(...result.errors);\n }\n return totals;\n}\n","import { PhDB } from '../db/index.js';\nimport { load as loadConfig, save as saveConfig } from '../config/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport { syncHash } from '../utils/syncHash.js';\nimport { parseSyncPullResponse, SYNC_PAGE_SIZE, syncTarget } from '../sync/protocol.js';\nimport { sendSyncPushPage } from '../sync/client.js';\nimport { decodePromptMetadata } from '../interaction/detail.js';\nimport type { PromptEntry } from '../types.js';\n\nfunction remoteUrl(cfg: PhConfig): string {\n return process.env.PH_REMOTE_URL || cfg.remoteUrl || '';\n}\n\nexport async function cmdRemote(dbPath: string, args: string[]): Promise<void> {\n const cfg = loadConfig();\n const url = remoteUrl(cfg);\n if (!url) {\n process.stderr.write('ph: remote not configured. Set PH_REMOTE_URL env or: ph config set remoteUrl <url>\\n');\n process.exit(1);\n }\n\n const sub = args[0];\n switch (sub) {\n case 'push':\n await push(dbPath, cfg, url);\n break;\n case 'pull':\n await pull(dbPath, cfg, url);\n break;\n case 'status':\n await status(dbPath, cfg, url);\n break;\n default:\n process.stdout.write(`ph remote commands:\n push Push local prompts to remote (resumable)\n pull Pull remote prompts into local history (resumable)\n status Show sync status\n\nRemote: ${url}\\n`);\n }\n}\n\nasync function push(dbPath: string, cfg: PhConfig, url: string): Promise<void> {\n const target = syncTarget(url);\n const db = new PhDB(dbPath);\n const databaseId = db.databaseId;\n let cursor = cfg.remotePushCursor?.target === target && cfg.remotePushCursor.databaseId === databaseId\n ? cfg.remotePushCursor.id\n : 0;\n let imported = 0;\n let skipped = 0;\n\n try {\n const initial = db.getPromptsAfterId(cursor, SYNC_PAGE_SIZE);\n if (initial.length === 0) {\n process.stdout.write('Nothing to push.\\n');\n return;\n }\n process.stdout.write(`Pushing local history to ${url} in pages of ${SYNC_PAGE_SIZE}...\\n`);\n\n while (true) {\n const candidates = db.getPromptsAfterId(cursor, SYNC_PAGE_SIZE);\n if (candidates.length === 0) break;\n const prompts: PromptEntry[] = [];\n let activeCaptureId: number | undefined;\n for (const candidate of candidates) {\n const metadata = decodePromptMetadata(candidate.metadata);\n if (metadata.capture_status === 'in_progress') {\n if (isProcessRunning(metadata.capture_owner_pid)) {\n activeCaptureId = candidate.id;\n break;\n }\n db.updateMetadataFields(candidate.id, { capture_status: null, capture_owner_pid: null });\n prompts.push(db.getById(candidate.id) ?? candidate);\n } else {\n prompts.push(candidate);\n }\n }\n if (prompts.length === 0) {\n process.stdout.write(`Waiting for active capture #${activeCaptureId}; sync cursor remains at #${cursor}.\\n`);\n break;\n }\n const response = await sendSyncPushPage(url, cfg.remoteApiKey, prompts);\n if (response.errors.length || response.imported + response.skipped !== prompts.length) {\n throw new Error(`Remote rejected part of the page after local record #${cursor}; this page was not checkpointed and can be retried.`);\n }\n\n imported += response.imported;\n skipped += response.skipped;\n cursor = prompts[prompts.length - 1].id;\n cfg.remotePushCursor = { target, databaseId, id: cursor };\n cfg.remoteLastPush = new Date().toISOString();\n saveConfig(cfg);\n process.stdout.write(`Checkpointed through local record #${cursor}.\\n`);\n if (activeCaptureId !== undefined) {\n process.stdout.write(`Waiting for active capture #${activeCaptureId}; sync cursor remains at #${cursor}.\\n`);\n break;\n }\n if (candidates.length < SYNC_PAGE_SIZE) break;\n }\n\n process.stdout.write(`Imported: ${imported}, skipped as duplicates: ${skipped}.\\n`);\n } catch (err) {\n process.stderr.write(`ph: push stopped safely: ${(err as Error).message}\\n`);\n process.exitCode = 1;\n } finally {\n db.close();\n }\n}\n\nasync function pull(dbPath: string, cfg: PhConfig, url: string): Promise<void> {\n const target = syncTarget(url);\n const db = new PhDB(dbPath);\n const databaseId = db.databaseId;\n // A legacy timestamp cursor cannot express a stable page boundary. Replay from\n // row zero and rely on sync_hash so existing records remain idempotent.\n let cursor = cfg.remotePullCursor?.target === target && cfg.remotePullCursor.databaseId === databaseId\n ? cfg.remotePullCursor.id\n : 0;\n\n try {\n process.stdout.write(`Pulling remote history from ${url} in pages of ${SYNC_PAGE_SIZE}...\\n`);\n let imported = 0;\n let skipped = 0;\n\n while (true) {\n const res = await fetch(`${url}/api/sync/pull`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(cfg.remoteApiKey ? { Authorization: `Bearer ${cfg.remoteApiKey}` } : {}),\n },\n body: JSON.stringify({ afterId: cursor, limit: SYNC_PAGE_SIZE }),\n });\n if (!res.ok) throw new Error(`Remote error ${res.status}: ${await res.text()}`);\n const page = parseSyncPullResponse(await res.json());\n if (page.prompts.length > SYNC_PAGE_SIZE) throw new Error('Remote server returned an oversized sync page.');\n if (page.prompts.length === 0 && page.hasMore) throw new Error('Remote server returned an empty page with more records pending.');\n if (page.prompts.length > 0) {\n const ids = page.prompts.map(prompt => prompt.id);\n if (ids.some((id, index) => id <= cursor || (index > 0 && id <= ids[index - 1])) || page.nextCursor !== ids[ids.length - 1]) {\n throw new Error('Remote server returned an invalid cursor order; this page was not checkpointed.');\n }\n } else if (page.nextCursor !== cursor) {\n throw new Error('Remote server returned an invalid empty-page cursor.');\n }\n\n for (const prompt of page.prompts) {\n const hash = syncHash(prompt);\n if (db.getPromptBySyncHash(hash)) { skipped++; continue; }\n const metaObj = { ...JSON.parse(prompt.metadata || '{}'), sync_hash: hash };\n db.insert({\n timestamp: prompt.timestamp || new Date().toISOString(),\n tool: prompt.tool || 'unknown',\n prompt: prompt.prompt || '',\n response: prompt.response || '',\n args: prompt.args || '',\n workdir: prompt.workdir || '',\n hostname: prompt.hostname || '',\n exit_code: prompt.exit_code ?? 0,\n metadata: JSON.stringify(metaObj),\n });\n imported++;\n }\n\n if (page.prompts.length > 0) cursor = page.nextCursor;\n cfg.remotePullCursor = { target, databaseId, id: cursor };\n cfg.remoteLastPull = new Date().toISOString();\n saveConfig(cfg);\n process.stdout.write(`Checkpointed through remote record #${cursor}.\\n`);\n if (!page.hasMore) break;\n }\n\n process.stdout.write(`Imported: ${imported}, skipped as duplicates: ${skipped}.\\n`);\n } catch (err) {\n process.stderr.write(`ph: pull stopped safely: ${(err as Error).message}\\n`);\n process.exitCode = 1;\n } finally {\n db.close();\n }\n}\n\nasync function status(dbPath: string, cfg: PhConfig, url: string): Promise<void> {\n const target = syncTarget(url);\n const db = new PhDB(dbPath);\n try {\n const localTotal = db.getPromptCount();\n const cursor = cfg.remotePushCursor?.target === target && cfg.remotePushCursor.databaseId === db.databaseId\n ? cfg.remotePushCursor.id\n : 0;\n const lastPush = cfg.remoteLastPush || 'never';\n const lastPull = cfg.remoteLastPull || 'never';\n const pending = db.getPromptCountAfterId(cursor);\n\n process.stdout.write(`Remote: ${url}\\n`);\n process.stdout.write(`Local total: ${localTotal} prompts\\n`);\n process.stdout.write(`Last push: ${lastPush}\\n`);\n process.stdout.write(`Last pull: ${lastPull}\\n`);\n process.stdout.write(`Pending bulk push: ${pending} prompts\\n`);\n } finally {\n db.close();\n }\n}\n\nfunction isProcessRunning(pid: number | undefined): boolean {\n if (!Number.isInteger(pid) || !pid || pid < 1) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n return (error as { code?: string }).code === 'EPERM';\n }\n}\n","import type { PhDB } from '../db/index.js';\nimport type { PromptMetadata } from '../types.js';\n\nexport type PromptMetadataPatch = { [K in keyof PromptMetadata]?: PromptMetadata[K] | null };\n\nexport function patchPromptMetadata(db: Pick<PhDB, 'updateMetadataFields'>, id: number, patch: PromptMetadataPatch): void {\n db.updateMetadataFields(id, patch as Record<string, unknown>);\n}\n\nexport function getAnalysisStatus(metadata: PromptMetadata): string {\n if (metadata.analysis_status) return metadata.analysis_status;\n if (metadata.summary || metadata.key_insights?.length || metadata.technical_decisions?.length || metadata.quality !== undefined || metadata.relevance !== undefined) return 'complete';\n return 'not analyzed';\n}\n\nexport function getRemoteSyncStatus(metadata: PromptMetadata, configured: boolean): string {\n if (metadata.remote_sync_status) return metadata.remote_sync_status;\n return configured ? 'unknown (legacy record)' : 'not configured';\n}\n","import type { PromptEntry, PromptMetadata } from '../types.js';\nimport { decodePromptMetadata } from '../interaction/detail.js';\nimport { getAnalysisStatus } from '../interaction/lifecycle.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 const meta: PromptMetadata = decodePromptMetadata(e.metadata);\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 const prompt = showFull ? e.prompt : truncatePrompt(e.prompt);\n process.stdout.write(` Prompt: ${prompt.replace(/\\n/g, '\\n ')}\\n`);\n if (e.response) {\n const response = showFull ? e.response : truncatePrompt(e.response, 180);\n process.stdout.write(` Response: ${response.replace(/\\n/g, '\\n ')}\\n`);\n } else {\n process.stdout.write(' Response: (not captured)\\n');\n }\n if (meta.summary) {\n const summary = showFull ? meta.summary : truncatePrompt(meta.summary, 160);\n process.stdout.write(` Analysis: ${getAnalysisStatus(meta)} — ${summary.replace(/\\n/g, '\\n ')}\\n`);\n } else {\n process.stdout.write(` Analysis: ${getAnalysisStatus(meta)}\\n`);\n }\n process.stdout.write(` Inspect: ph show ${e.id}\\n\\n`);\n}\n","export function 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\nexport function 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","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 { PhDB, cosineSimilarity } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport type { SearchOptions } from '../types.js';\nimport { getEmbeddings } from '../embedding/index.js';\nimport { printResults } from '../display/print.js';\nimport { decodePromptMetadata } from '../interaction/detail.js';\nimport { parseFlags, parseDate } from './_utils.js';\nimport { detectProject } from '../runner/project.js';\n\nconst DEFAULT_LIMIT = 5;\nconst MAX_LIMIT = 1000;\n\nexport async function cmdSearch(db: PhDB, cfg: PhConfig, args: string[]): Promise<void> {\n const interactive = args.includes('-i') || args.includes('--interactive');\n const { flags, positional } = parseFlags(args.filter(arg => arg !== '-i' && arg !== '--interactive'));\n if (interactive) process.stderr.write('ph search -i now prints plain-text results; the interactive browser has been removed.\\n');\n const query = positional.join(' ');\n const explicitProject = typeof flags.project === 'string' ? flags.project : undefined;\n const currentProject = detectProject(process.cwd()).projectName;\n const project = flags.all || flags.archive ? undefined : (explicitProject ?? (currentProject || undefined));\n const limit = parseLimit(flags.limit);\n\n if (flags.archive) process.stdout.write('Scope: archived work\\n');\n else if (project) process.stdout.write(`Project: ${project}\\n`);\n else if (flags.all) process.stdout.write('Scope: all projects\\n');\n else process.stdout.write('Scope: all saved work (no project detected)\\n');\n\n if (flags['archive']) {\n const archiveResults = db.searchArchive({\n since: flags['since'] ? new Date(flags['since'] as string).toISOString() : undefined,\n until: flags['until'] ? new Date(flags['until'] as string).toISOString() : undefined,\n limit,\n });\n if (archiveResults.length === 0) {\n console.log('No archived prompts found.');\n return;\n }\n console.log(`Found ${archiveResults.length} archived prompts:\\n`);\n for (const r of archiveResults) {\n const date = new Date(r.timestamp as string).toLocaleString();\n const id = r.original_id ?? r.id;\n const full = Boolean(flags['full']);\n const promptRaw = r.prompt as string;\n const prompt = full ? promptRaw : promptRaw.replace(/\\n/g, ' ').slice(0, 120);\n console.log(` #${id} [${r.tool}] (${date})`);\n console.log(` Prompt: ${prompt}${!full && promptRaw.length > 120 ? '...' : ''}`);\n if (r.response) {\n const responseRaw = r.response as string;\n const resp = full ? responseRaw : responseRaw.replace(/\\n/g, ' ').slice(0, 120);\n console.log(` Response: ${resp}${!full && responseRaw.length > 120 ? '...' : ''}`);\n }\n const metadata = decodePromptMetadata(String(r.metadata ?? '{}'));\n if (metadata.summary) console.log(` Analysis: ${metadata.summary}`);\n console.log(` Inspect: ph show ${id} --archive`);\n console.log();\n }\n return;\n }\n\n if (flags['semantic'] && query) {\n await cmdSearchSemantic(db, cfg, query, limit, Boolean(flags['full']), project);\n return;\n }\n\n const opts: SearchOptions = {\n query,\n tool: flags['tool'] as string | undefined,\n project,\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,\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 d.setHours(23, 59, 59, 999);\n opts.until = d;\n }\n\n const results = db.search(opts);\n if (results.length === 0 && project) {\n process.stdout.write(query\n ? `No matches in ${project}. Use ph search --all to search other projects.\\n`\n : `No saved work for ${project}. Use ph search --all to search all projects.\\n`);\n return;\n }\n printResults(results, Boolean(flags['full']));\n}\n\nexport async function cmdSearchSemantic(db: PhDB, cfg: PhConfig, query: string, limit: number, showFull: boolean, project?: string): 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 = project ? db.getEmbeddingsForProject(project) : 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\nfunction parseLimit(raw: string | boolean | undefined): number {\n if (raw === undefined) return DEFAULT_LIMIT;\n const limit = Number(raw);\n if (!Number.isInteger(limit) || limit < 1 || limit > MAX_LIMIT) {\n throw new Error(`--limit must be an integer between 1 and ${MAX_LIMIT}`);\n }\n return limit;\n}\n","import { PhDB } from '../db/index.js';\nimport { parseFlags } from './_utils.js';\nimport { formatInteractionDetail, formatInteractionJson } from '../interaction/detail.js';\n\nexport async function cmdShow(db: PhDB, args: string[]): Promise<void> {\n const { flags, positional } = parseFlags(args);\n const id = Number(positional[0]);\n if (!Number.isInteger(id) || id < 1) {\n process.stderr.write('Usage: ph show <id> [--json] [--archive]\\n');\n process.exitCode = 2;\n return;\n }\n\n const entry = flags.archive ? db.getArchivedById(id) : db.getById(id);\n if (!entry) {\n process.stderr.write(`ph: ${flags.archive ? 'archived ' : ''}interaction #${id} not found\\n`);\n process.exitCode = 1;\n return;\n }\n\n process.stdout.write(flags.json\n ? `${formatInteractionJson(entry)}\\n`\n : `${formatInteractionDetail(entry)}\\n`);\n}\n","import type { PhDB } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport { decodePromptMetadata } from '../interaction/detail.js';\nimport { getAnalysisStatus, getRemoteSyncStatus } from '../interaction/lifecycle.js';\n\nexport async function cmdStatus(db: PhDB, cfg: PhConfig): Promise<void> {\n const entries = db.search({ limit: 10 });\n process.stdout.write('PH capture status\\n');\n process.stdout.write(`Background analysis: ${cfg.backgroundAnalysis ? 'enabled' : 'disabled'}\\n`);\n process.stdout.write(`Remote push: ${(process.env.PH_REMOTE_URL || cfg.remoteUrl) ? 'configured' : 'not configured'}\\n\\n`);\n\n if (entries.length === 0) {\n process.stdout.write('No interactions have been captured yet.\\n');\n return;\n }\n\n process.stdout.write('Recent interactions (prompt and response content hidden):\\n');\n for (const entry of entries) {\n const metadata = decodePromptMetadata(entry.metadata);\n process.stdout.write(\n `#${entry.id} ${new Date(entry.timestamp).toLocaleString()} ${entry.tool}` +\n `${metadata.project ? ` [${metadata.project}]` : ''}\\n` +\n ` response: ${entry.response ? 'captured' : 'missing'} · analysis: ${getAnalysisStatus(metadata)}` +\n ` · remote: ${getRemoteSyncStatus(metadata, Boolean(process.env.PH_REMOTE_URL || cfg.remoteUrl))}\\n`\n );\n }\n}\n","import { PhDB } from '../db/index.js';\nimport { printResults } from '../display/print.js';\n\nexport async 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","import { PhDB } from '../db/index.js';\nimport type { PromptMetadata } from '../types.js';\n\nexport async 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","import { PhDB } from '../db/index.js';\nimport { parseFlags } from './_utils.js';\nimport { formatInteractionDetail, formatInteractionJson, formatInteractionMarkdown } from '../interaction/detail.js';\n\nexport async 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] [--archive]\\n');\n process.exit(1);\n }\n\n const entry = flags.archive ? db.getArchivedById(id) : 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(formatInteractionDetail(entry));\n break;\n\n case 'json': {\n process.stdout.write(formatInteractionJson(entry) + '\\n');\n break;\n }\n\n case 'md':\n case 'markdown': {\n process.stdout.write(formatInteractionMarkdown(entry));\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","import path from 'path';\nimport os from 'os';\nimport { PhDB } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport { importGeminiHistory } from '../importer/gemini.js';\nimport { importClaudeHistory } from '../importer/claude.js';\nimport { importOpenCodeHistory } from '../importer/opencode.js';\nimport { importCodexHistory } from '../importer/codex.js';\nimport { getProvider, getProviderSetupError } from '../ai/provider.js';\nimport { FilterPipeline } from '../filter/index.js';\nimport { parseFlags } from './_utils.js';\n\nexport async 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] [--filter] [--file <path>] [--workdir <path>]\\n');\n process.stderr.write('Supported sources: gemini, claude, opencode, codex\\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 transcriptFile = typeof flags.file === 'string' ? flags.file : undefined;\n const workdirOverride = typeof flags.workdir === 'string' ? flags.workdir : undefined;\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 const detail = getProviderSetupError(cfg) ?? 'No LLM provider is configured. Run: ph config set analyze-provider ollama';\n process.stderr.write(`ph: ${detail}\\n`);\n process.exit(1);\n }\n console.log(`Analyzing with ${analyzer.name} during import...`);\n }\n\n let filter: FilterPipeline | undefined;\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 filter = new FilterPipeline({\n minLength: 0,\n minRelevance: 0,\n existingHashes,\n });\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 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 case 'opencode':\n result = await importOpenCodeHistory(db, path.join(homeDir, '.local', 'share', 'opencode', 'storage'), dryRun, analyzer, onProgress, filter, transcriptFile, workdirOverride);\n break;\n case 'codex':\n result = await importCodexHistory(db, path.join(homeDir, '.codex'), dryRun, analyzer, onProgress, filter, transcriptFile, workdirOverride);\n break;\n default:\n process.stderr.write(`ph: unknown import source \"${source}\". Supported: gemini, claude, opencode, codex\\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","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';\nimport { createCaptureRecord } from '../capture/index.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(createCaptureRecord({\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: JSON.parse(metadata) as Record<string, unknown>,\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 summary?: string;\n key_insights?: string[];\n technical_decisions?: string[];\n}\n\nconst ANALYSIS_PROMPT = (text: string) => `\\\nAnalyze this AI tool prompt and response 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 \"summary\": \"<a concise 1-sentence summary of the interaction>\",\n \"key_insights\": [\"<insight1>\", \"<insight2>\"],\n \"technical_decisions\": [\"<decision1>\", \"<decision2>\"]\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- summary: Focus on the technical achievement or question asked.\n- key_insights: List 1-3 specific technical decisions, library choices, or architectural findings.\n- technical_decisions: List 1-3 concrete technology choices, architectural decisions, or trade-offs made (e.g. \"Using SQLite over Postgres for simplicity\", \"Chose tsup for ESM build\"). Empty array if not applicable.\n- Return ONLY the JSON object — no markdown fences, no explanation, no other text\n\nInteraction to analyze:\n\"\"\"\n${text.slice(0, 2000)}\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 if (typeof parsed['summary'] === 'string' && parsed['summary'].trim()) {\n result.summary = parsed['summary'].trim();\n }\n if (Array.isArray(parsed['key_insights'])) {\n const insights = (parsed['key_insights'] as unknown[])\n .filter((t): t is string => typeof t === 'string' && t.trim().length > 0)\n .slice(0, 5);\n if (insights.length > 0) result.key_insights = insights;\n }\n if (Array.isArray(parsed['technical_decisions'])) {\n const decisions = (parsed['technical_decisions'] as unknown[])\n .filter((t): t is string => typeof t === 'string' && t.trim().length > 0)\n .slice(0, 5);\n if (decisions.length > 0) result.technical_decisions = decisions;\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 \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 if (result.summary && (force || !merged.summary)) {\n merged.summary = result.summary;\n }\n if (result.key_insights && (force || !merged.key_insights?.length)) {\n merged.key_insights = result.key_insights;\n }\n if (result.technical_decisions && (force || !merged.technical_decisions?.length)) {\n merged.technical_decisions = result.technical_decisions;\n }\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\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 if (!dryRun) db.updateMetadataFields(entry.id, { analysis_status: 'pending', analysis_error: null });\n result = await analyzePrompt(entry.prompt, provider);\n const existing = parseMeta(entry.metadata);\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 if (Object.keys(result).length === 0) {\n if (!dryRun) db.updateMetadataFields(entry.id, { analysis_status: 'failed', analysis_error: 'analysis_failed' });\n stats.failed++;\n errMsg = 'analysis_failed';\n } else {\n db.updateMetadataFields(entry.id, {\n ...mergeMetadata(existing, result, force),\n analysis_status: 'complete',\n analysis_error: null,\n });\n stats.updated++;\n }\n }\n } catch (e: unknown) {\n errMsg = (e as Error).message;\n stats.failed++;\n if (!dryRun) {\n try { db.updateMetadataFields(entry.id, { analysis_status: 'failed', analysis_error: 'analysis_persistence_failed' }); }\n catch { /* retain the original failure in the command result */ }\n }\n }\n\n onProgress?.(i + 1, toProcess.length, entry, result, errMsg);\n }\n\n return stats;\n}\n","import os from 'node:os';\nimport { detectProject, detectLanguage } from '../runner/project.js';\nimport type { GitContext } from '../runner/git-context.js';\nimport { extractTopic } from '../utils/extractTopic.js';\nimport type { PromptEntry } from '../types.js';\n\nexport interface CaptureInput {\n tool: string;\n prompt: string;\n response?: string;\n args?: string;\n workdir: string;\n timestamp?: string;\n hostname?: string;\n exit_code?: number;\n metadata?: Record<string, unknown>;\n gitContext?: GitContext | null;\n}\n\n/** Build the canonical record shared by live capture entry points. */\nexport function createCaptureRecord(input: CaptureInput): Omit<PromptEntry, 'id'> {\n const { rootDir, projectName } = detectProject(input.workdir);\n const language = detectLanguage(rootDir);\n const title = extractTopic(input.prompt);\n const metadata: Record<string, unknown> = {\n $schema_version: 1,\n ...(projectName ? { project: projectName } : {}),\n ...(language ? { language } : {}),\n ...(title ? { title } : {}),\n ...(input.gitContext ? { git_context: input.gitContext } : {}),\n ...input.metadata,\n };\n\n return {\n timestamp: input.timestamp ?? new Date().toISOString(),\n tool: input.tool,\n prompt: input.prompt,\n response: input.response ?? '',\n args: input.args ?? '',\n workdir: input.workdir,\n hostname: input.hostname ?? os.hostname(),\n exit_code: input.exit_code ?? 0,\n metadata: JSON.stringify(metadata),\n };\n}\n","/**\n * Extracts a short, meaningful title from raw prompt text.\n * Always returns a non-empty string (fallback: first 72 characters, truncated).\n */\nexport function extractTopic(prompt: string): string {\n // 1. Trim leading and trailing whitespace and newlines.\n let text = prompt.trim();\n\n // Edge case: empty prompt or whitespace only.\n if (!text) {\n return '(empty prompt)';\n }\n\n // Edge case: prompt contains only code (starts with ``` or `).\n // Return the first 72 characters of the trimmed original text.\n if (text.startsWith('```') || text.startsWith('`')) {\n return truncateAtWordBoundary(text, 72);\n }\n\n const originalTrimmed = text;\n\n // 2. MARKDOWN HEADING\n // If the text starts with one or more # characters followed by a space, extract the heading text.\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. PREFIXES TO REMOVE (case-insensitive, English and Italian)\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 // Italian\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; // Restart the loop after removing a prefix.\n }\n }\n }\n\n // 4. FIRST MEANINGFUL SENTENCE\n // Keep the text up to the first period, question mark, exclamation mark, newline, or code backtick.\n const sentenceEndMatch = text.match(/[\\n.?!`]/);\n if (sentenceEndMatch && sentenceEndMatch.index !== undefined) {\n text = text.slice(0, sentenceEndMatch.index).trim();\n }\n\n // Fall back if the result is empty after transformations.\n if (!text) {\n return truncateAtWordBoundary(originalTrimmed, 72);\n }\n\n // 5. TRUNCATE to a maximum of 72 characters.\n text = truncateAtWordBoundary(text, 72);\n\n // 6. Capitalize the first letter.\n return text.charAt(0).toUpperCase() + text.slice(1);\n}\n\n/**\n * Truncate at the last space within the character limit.\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 — Phase 4: Refactor BrowseApp ##\\n\\nThe main file is...\") -> \"Phase 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(\"can you fix the bug in the ListEntry component when paneWidth is zero?\") -> \"Fix the bug in the ListEntry component when paneWidth is 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 instead of callbacks\"\n// test: extractTopic(\"claude, I don't like PH's UI. Not at all.\") -> \"I don't like PH's UI\"\n// test: extractTopic(\" \\n\\nPlease review this code:\\n\\n```typescript\\nfunction foo() {...\") -> \"Review this code\"\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';\nimport { createCaptureRecord } from '../capture/index.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-example-foo` → `/Users/example/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(createCaptureRecord({\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: JSON.parse(metadata) as Record<string, unknown>,\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","import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport Database from 'better-sqlite3';\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';\nimport { createCaptureRecord } from '../capture/index.js';\n\nconst MAX_RESPONSE_LENGTH = 8000;\nconst TRUNCATION_SUFFIX = '\\n... (truncated)';\n\ninterface OCMessageData {\n role: 'user' | 'assistant';\n time: { created: number; completed?: number };\n summary?: { title?: string; diffs?: unknown[] };\n parentID?: string;\n agent?: string;\n model?: { providerID?: string; modelID?: string };\n modelID?: string;\n providerID?: string;\n mode?: string;\n path?: { cwd?: string; root?: string };\n tokens?: { input?: number; output?: number; reasoning?: number };\n finish?: string;\n}\n\ninterface OCPartData {\n type: string;\n text?: string;\n}\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\nexport async function importOpenCodeHistory(\n db: PhDB,\n opencodeDir: string,\n dryRun: boolean,\n analyzer?: LLMProvider,\n onProgress?: (evaluated: number, imported: number, total: number, current: string) => void,\n filter?: FilterPipeline,\n dbFileOverride?: string,\n workdirOverride?: string\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 let dbPath: string;\n if (dbFileOverride) {\n dbPath = path.resolve(dbFileOverride);\n } else if (opencodeDir.endsWith('.db') && fs.existsSync(opencodeDir)) {\n dbPath = opencodeDir;\n } else if (fs.existsSync(path.join(opencodeDir, 'opencode.db'))) {\n dbPath = path.join(opencodeDir, 'opencode.db');\n } else {\n dbPath = path.join(opencodeDir, '..', 'opencode.db');\n }\n\n if (!fs.existsSync(dbPath)) {\n result.errors.push(`opencode database not found at ${dbPath}`);\n return result;\n }\n\n let ocDb: Database.Database;\n try {\n ocDb = new Database(dbPath, { readonly: true });\n } catch (e: unknown) {\n result.errors.push(`cannot open opencode database: ${(e as Error).message}`);\n return result;\n }\n\n result.filesScanned = 1;\n\n const hostname = os.hostname();\n\n interface PendingEntry {\n prompt: string;\n response: string;\n timestamp: string;\n workdir: string;\n sessionId: string;\n agent?: string;\n modelInfo?: string;\n tokens?: string;\n title?: string;\n }\n\n const pendingEntries: PendingEntry[] = [];\n\n try {\n const sessions = ocDb.prepare(\n `SELECT id, directory, time_created FROM session ORDER BY time_created`\n ).all() as { id: string; directory: string; time_created: number }[];\n\n const getMessages = ocDb.prepare(\n `SELECT id, data, time_created FROM message WHERE session_id = ? ORDER BY time_created, id`\n );\n\n const getParts = ocDb.prepare(\n `SELECT data FROM part WHERE message_id = ? ORDER BY id`\n );\n\n function getTextContent(messageId: string): string {\n const partRows = getParts.all(messageId) as { data: string }[];\n const texts: string[] = [];\n for (const row of partRows) {\n try {\n const partData = JSON.parse(row.data) as OCPartData;\n if (partData.type === 'text' && partData.text) {\n texts.push(partData.text);\n }\n } catch { /* skip unparseable parts */ }\n }\n return texts.join('');\n }\n\n for (const session of sessions) {\n const messageRows = getMessages.all(session.id) as { id: string; data: string; time_created: number }[];\n if (messageRows.length === 0) continue;\n\n const messages: { id: string; data: OCMessageData; time_created: number }[] = [];\n for (const row of messageRows) {\n try {\n const data = JSON.parse(row.data) as OCMessageData;\n messages.push({ id: row.id, data, time_created: row.time_created });\n } catch { /* skip */ }\n }\n\n const assistantByParent = new Map<string, { id: string; data: OCMessageData }>();\n for (const msg of messages) {\n if (msg.data.role === 'assistant' && msg.data.parentID) {\n assistantByParent.set(msg.data.parentID, { id: msg.id, data: msg.data });\n }\n }\n\n for (const msg of messages) {\n if (msg.data.role !== 'user') continue;\n\n const prompt = getTextContent(msg.id);\n if (!prompt.trim()) continue;\n\n const assistant = assistantByParent.get(msg.id);\n let response = '';\n if (assistant) {\n const rawText = getTextContent(assistant.id);\n if (rawText) response = truncateResponse(rawText);\n }\n\n const timestamp = new Date(msg.data.time.created).toISOString();\n const workdir = workdirOverride?.trim() || session.directory || '';\n\n pendingEntries.push({\n prompt: prompt.trim(),\n response,\n timestamp,\n workdir,\n sessionId: session.id,\n agent: msg.data.agent || assistant?.data?.mode,\n modelInfo: msg.data.model ? JSON.stringify(msg.data.model) :\n (assistant?.data?.providerID ? JSON.stringify({ providerID: assistant.data.providerID, modelID: assistant.data.modelID }) : undefined),\n tokens: assistant?.data?.tokens ? JSON.stringify(assistant.data.tokens) : undefined,\n title: msg.data.summary?.title,\n });\n }\n }\n } finally {\n ocDb.close();\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 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: Record<string, unknown> = {};\n\n if (analyzer) {\n try {\n const analysis = await analyzePrompt(entry.prompt, 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 = { ...merged };\n } catch { /* analysis failure is non-fatal */ }\n }\n\n if (entry.title) metadata.title = entry.title;\n if (entry.agent) metadata.agent = entry.agent;\n if (entry.modelInfo && entry.modelInfo !== '{}') {\n try { metadata.model = JSON.parse(entry.modelInfo); } catch { metadata.model = entry.modelInfo; }\n }\n if (entry.tokens) {\n try { metadata.tokens = JSON.parse(entry.tokens); } catch { metadata.tokens = entry.tokens; }\n }\n\n const id = db.insert(createCaptureRecord({\n timestamp: entry.timestamp,\n tool: 'opencode',\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(`insert session ${entry.sessionId}: ${(e as Error).message}`);\n result.skipped++;\n }\n }\n\n return result;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\nimport { PhDB } from '../db/index.js';\nimport { FilterPipeline } from '../filter/index.js';\nimport type { ImportResult, PromptMetadata } from '../types.js';\nimport { createCaptureRecord } from '../capture/index.js';\nimport type { LLMProvider } from '../ai/provider.js';\nimport { analyzePrompt, mergeMetadata } from '../analyzer/index.js';\n\ntype RolloutEvent = { timestamp?: string; type?: string; payload?: Record<string, unknown> };\n\nfunction textFromContent(content: unknown): string {\n if (typeof content === 'string') return content;\n if (!Array.isArray(content)) return '';\n return content.flatMap((part) => {\n if (!part || typeof part !== 'object') return [];\n const item = part as Record<string, unknown>;\n return typeof item.text === 'string' && ['output_text', 'input_text', 'text'].includes(String(item.type))\n ? [item.text] : [];\n }).join('');\n}\n\nfunction rolloutFiles(sessionsDir: string): string[] {\n if (!fs.existsSync(sessionsDir)) return [];\n const files: string[] = [];\n const visit = (dir: string): void => {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) visit(full);\n else if (entry.isFile() && /^rollout-.*\\.jsonl$/.test(entry.name)) files.push(full);\n }\n };\n visit(sessionsDir);\n return files;\n}\n\nexport async function importCodexHistory(\n db: PhDB,\n codexDir: string,\n dryRun: boolean,\n analyzer?: LLMProvider,\n onProgress?: (evaluated: number, imported: number, total: number, current: string) => void,\n filter?: FilterPipeline,\n transcriptFile?: string,\n workdirOverride?: string,\n): Promise<ImportResult> {\n const result: ImportResult = { filesScanned: 0, promptsFound: 0, promptsImported: 0, skipped: 0, filtered: 0, errors: [] };\n const dedupFilter = filter ?? new FilterPipeline({ minLength: 0, minRelevance: 0, existingHashes: db.getAllPromptHashes() });\n const files = transcriptFile ? [transcriptFile] : rolloutFiles(path.join(codexDir, 'sessions'));\n result.filesScanned = files.length;\n const hostname = os.hostname();\n const entries: { prompt: string; response: string; timestamp: string; workdir: string; sessionId: string }[] = [];\n\n for (const file of files) {\n let lines: string[];\n try { lines = fs.readFileSync(file, 'utf8').split('\\n'); }\n catch (error) { result.errors.push(`read ${file}: ${(error as Error).message}`); continue; }\n let workdir = '';\n let sessionId = path.basename(file, '.jsonl').replace(/^rollout-.*?-/, '');\n const events: RolloutEvent[] = [];\n for (const line of lines) {\n if (!line.trim()) continue;\n try {\n const event = JSON.parse(line) as RolloutEvent;\n events.push(event);\n if (event.type === 'session_meta' && event.payload) {\n if (typeof event.payload.cwd === 'string') workdir = event.payload.cwd;\n if (typeof event.payload.id === 'string') sessionId = event.payload.id;\n }\n } catch { /* Ignore partial or malformed JSONL records. */ }\n }\n for (let i = 0; i < events.length; i++) {\n const event = events[i];\n const payload = event.payload ?? {};\n const isUserMessage = (event.type === 'event_msg' && payload.type === 'user_message')\n || (event.type === 'response_item' && payload.type === 'message' && payload.role === 'user');\n const prompt = !isUserMessage ? '' : typeof payload.message === 'string'\n ? payload.message.trim() : textFromContent(payload.content).trim();\n if (!prompt) continue;\n const agentMessages: string[] = [];\n const assistantItems: string[] = [];\n const finalAssistantItems: string[] = [];\n for (let j = i + 1; j < events.length; j++) {\n const candidate = events[j].payload ?? {};\n const nextIsUserMessage = (events[j].type === 'event_msg' && candidate.type === 'user_message')\n || (events[j].type === 'response_item' && candidate.type === 'message' && candidate.role === 'user');\n if (nextIsUserMessage) break;\n if (events[j].type === 'event_msg' && candidate.type === 'agent_message' && typeof candidate.message === 'string') agentMessages.push(candidate.message);\n if (events[j].type === 'response_item' && candidate.type === 'message' && candidate.role === 'assistant') {\n const text = textFromContent(candidate.content);\n assistantItems.push(text);\n if (candidate.phase === 'final_answer') finalAssistantItems.push(text);\n }\n }\n const response = agentMessages.length > 0 ? agentMessages.join('')\n : finalAssistantItems.length > 0 ? finalAssistantItems.join('') : assistantItems.join('');\n entries.push({ prompt, response: response.slice(0, 8000), timestamp: event.timestamp ?? new Date(0).toISOString(), workdir: workdirOverride || workdir, sessionId });\n }\n }\n\n for (let i = 0; i < entries.length; i++) {\n const entry = entries[i];\n result.promptsFound++;\n onProgress?.(i + 1, result.promptsImported, entries.length, entry.prompt.slice(0, 60));\n if (dryRun) { result.promptsImported++; continue; }\n const rules = dedupFilter.checkRules(entry.prompt);\n if (!rules.keep || !dedupFilter.checkDuplicate(entry.prompt).keep) { result.filtered++; continue; }\n try {\n let metadata: PromptMetadata = {};\n if (analyzer) {\n try { metadata = mergeMetadata({}, await analyzePrompt(entry.prompt, analyzer), false); }\n catch { /* Analysis failure does not prevent importing the transcript. */ }\n }\n const id = db.insert(createCaptureRecord({ timestamp: entry.timestamp, tool: 'codex', prompt: entry.prompt, response: entry.response,\n args: entry.prompt, workdir: entry.workdir, hostname, exit_code: 0, metadata: { ...metadata } }));\n dedupFilter.registerHash(entry.prompt, id);\n result.promptsImported++;\n } catch (error) { result.errors.push(`insert session ${entry.sessionId}: ${(error as Error).message}`); result.skipped++; }\n }\n return result;\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|grazie|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: escape sequences and control chars. The lookahead\n// requires at least one actual control char — plain words must NOT match here\n// (they fall through to the trivial/pattern rules).\n// eslint-disable-next-line no-control-regex\nconst NON_PRINTABLE_PATTERN = /^(?=.*[\\x00-\\x1f\\x7f])[\\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 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}?`, { cause: err });\n }\n throw new Error(`Ollama unreachable at ${this.url}: ${msg}`, { cause: err });\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 { generateText, type LanguageModel } from 'ai';\nimport { createAIModel, type ProviderConfig } from '@gi4nks/wise';\nimport type { LLMProvider } from './provider.js';\n\nexport const OPENROUTER_DEFAULT_URL = 'https://openrouter.ai/api/v1';\nexport const MLX_SERVE_DEFAULT_URL = 'http://127.0.0.1:11234/v1';\n\ntype WiseProviderName = 'openai' | 'omlx';\n\nexport class WiseLLMProvider implements LLMProvider {\n readonly name: string;\n private readonly model: LanguageModel;\n\n constructor(\n wiseProvider: WiseProviderName,\n displayName: string,\n modelId: string,\n config: ProviderConfig,\n ) {\n this.name = `${displayName} (${modelId})`;\n // OpenRouter speaks the OpenAI API; MLX-Serve speaks the same API used by Wise's oMLX adapter.\n this.model = createAIModel(wiseProvider, modelId, config);\n }\n\n async generate(prompt: string): Promise<string> {\n const result = await generateText({\n model: this.model,\n prompt,\n // OpenRouter requests can incur cost. Avoid hidden automatic replays.\n maxRetries: 0,\n });\n return result.text;\n }\n}\n\nexport async function discoverModels(\n provider: 'openrouter' | 'mlx-serve',\n apiKey: string,\n baseUrl?: string,\n): Promise<Array<{ id: string; name: string; loaded?: boolean; state?: string }>> {\n if (provider === 'mlx-serve') {\n const url = (baseUrl || MLX_SERVE_DEFAULT_URL).replace(/\\/+$/, '');\n const response = await fetch(`${url}/models`, {\n headers: { Authorization: `Bearer ${apiKey}` },\n signal: AbortSignal.timeout(15_000),\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\n const data = await response.json() as { data?: Array<{ id?: string; name?: string; loaded?: boolean; state?: string }> };\n return (data.data ?? [])\n .filter((model): model is { id: string; name?: string; loaded?: boolean; state?: string } => typeof model.id === 'string' && model.id.length > 0)\n .map(model => ({ id: model.id, name: model.name || model.id, loaded: model.loaded, state: model.state }));\n }\n\n // Wise 2.1's generic OpenAI discovery falls back to a static catalog on errors.\n // Query OpenRouter's compatible catalog directly so a network failure cannot\n // present fake models as available. Generation still goes through Wise.\n const url = (baseUrl || OPENROUTER_DEFAULT_URL).replace(/\\/+$/, '');\n const response = await fetch(`${url}/models`, {\n headers: { Authorization: `Bearer ${apiKey}` },\n signal: AbortSignal.timeout(15_000),\n });\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n\n const data = await response.json() as { data?: Array<{ id?: string; name?: string }> };\n return (data.data ?? [])\n .filter((model): model is { id: string; name?: string } => typeof model.id === 'string' && model.id.length > 0)\n .map(model => ({ id: model.id, name: model.name || model.id }));\n}\n","import type { PhConfig } from '../config/index.js';\nimport { OllamaProvider } from './ollama.js';\nimport { GeminiProvider } from './gemini.js';\nimport { MLX_SERVE_DEFAULT_URL, OPENROUTER_DEFAULT_URL, WiseLLMProvider } from './wise.js';\n\nexport interface LLMProvider {\n readonly name: string;\n generate(prompt: string): Promise<string>;\n}\n\nexport function getProviderSetupError(cfg: PhConfig, selectedProvider?: PhConfig['analyzeProvider']): string | null {\n const provider = selectedProvider ?? cfg.analyzeProvider ?? 'ollama';\n if (provider === 'openrouter') {\n if (!(process.env.OPENROUTER_API_KEY || cfg.openrouterApiKey)) return 'Set a key with `ph config set openrouter-api-key` or OPENROUTER_API_KEY.';\n if (!(process.env.OPENROUTER_MODEL || cfg.openrouterModel)) return 'Choose a model with `ph config set openrouter-model <provider/model>`.';\n }\n if (provider === 'mlx-serve' && !(process.env.MLX_SERVE_MODEL || cfg.mlxServeModel)) {\n return 'Choose an MLX-Serve model with `ph config set mlx-serve-model <model-id>`.';\n }\n return null;\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, selectedProvider?: PhConfig['analyzeProvider']): LLMProvider | null {\n const provider = selectedProvider ?? cfg.analyzeProvider ?? 'ollama';\n\n if (provider === 'openrouter') {\n const apiKey = process.env.OPENROUTER_API_KEY ?? cfg.openrouterApiKey;\n const model = process.env.OPENROUTER_MODEL ?? cfg.openrouterModel;\n if (!apiKey || !model) return null;\n return new WiseLLMProvider('openai', 'OpenRouter', model, {\n openai: {\n apiKey,\n baseUrl: process.env.OPENROUTER_BASE_URL ?? cfg.openrouterUrl ?? OPENROUTER_DEFAULT_URL,\n },\n });\n }\n\n if (provider === 'mlx-serve') {\n const model = process.env.MLX_SERVE_MODEL ?? cfg.mlxServeModel;\n if (!model) return null;\n const apiKey = process.env.MLX_SERVE_API_KEY ?? process.env.GLB_OMLX_API_KEY ?? cfg.mlxServeApiKey ?? 'local';\n return new WiseLLMProvider('omlx', 'MLX-Serve', model, {\n omlx: {\n apiKey,\n baseUrl: process.env.MLX_SERVE_BASE_URL ?? cfg.mlxServeUrl ?? MLX_SERVE_DEFAULT_URL,\n },\n });\n }\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 { PhDB } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport { getProvider, getProviderSetupError } from '../ai/provider.js';\nimport { analyzeAll } from '../analyzer/index.js';\nimport { parseFlags } from './_utils.js';\n\nexport async 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 const detail = getProviderSetupError(cfg) ?? 'No LLM provider is configured. Set analyze-provider in config.';\n process.stderr.write(`ph: ${detail}\\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","import { PhDB } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport { getEmbeddings } from '../embedding/index.js';\n\nexport async 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","import { spawn } from 'child_process';\nimport { PhDB } from '../db/index.js';\nimport { patchPromptMetadata } from '../interaction/lifecycle.js';\nimport { decodePromptMetadata } from '../interaction/detail.js';\n\nfunction setLaunchFailure(dbPath: string, id: number): void {\n try {\n const db = new PhDB(dbPath);\n try {\n const entry = db.getById(id);\n if (entry && (!decodePromptMetadata(entry.metadata).analysis_status || decodePromptMetadata(entry.metadata).analysis_status === 'pending')) {\n patchPromptMetadata(db, id, { analysis_status: 'failed', analysis_error: 'worker_launch_failed' });\n }\n } finally {\n db.close();\n }\n } catch {\n // The record remains pending and ph status will show that it did not finish.\n }\n}\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) {\n setLaunchFailure(dbPath, id);\n return;\n }\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 child.on('error', () => setLaunchFailure(dbPath, id));\n child.on('exit', code => {\n if (code !== 0) setLaunchFailure(dbPath, id);\n });\n\n // Let the parent process exit without waiting for the child\n child.unref();\n } catch (_err: unknown) {\n setLaunchFailure(dbPath, id);\n }\n}\n","import type { PhConfig } from '../config/index.js';\nimport { PhDB } from '../db/index.js';\nimport { decodePromptMetadata } from '../interaction/detail.js';\nimport { patchPromptMetadata } from '../interaction/lifecycle.js';\nimport { spawnBackgroundAnalysis } from '../background/analyzer.js';\nimport { sendSyncPushPage } from '../sync/client.js';\nimport type { PromptEntry } from '../types.js';\nimport { syncTarget } from '../sync/protocol.js';\n\nexport function configuredRemoteUrl(cfg: PhConfig): string | undefined {\n return process.env.PH_REMOTE_URL || cfg.remoteUrl || undefined;\n}\n\nexport function prepareLiveCapture<T extends Omit<PromptEntry, 'id'>>(\n record: T,\n cfg: PhConfig,\n options: { inProgress?: boolean } = {},\n): T {\n const metadata = decodePromptMetadata(record.metadata);\n if (cfg.backgroundAnalysis) {\n metadata.analysis_status = 'pending';\n delete metadata.analysis_error;\n }\n const remoteUrl = configuredRemoteUrl(cfg);\n if (remoteUrl) {\n if (options.inProgress) {\n metadata.capture_status = 'in_progress';\n metadata.capture_owner_pid = process.pid;\n }\n try {\n metadata.remote_sync_status = 'pending';\n delete metadata.remote_sync_error;\n metadata.remote_sync_target = syncTarget(remoteUrl);\n } catch {\n metadata.remote_sync_status = 'failed';\n metadata.remote_sync_error = 'invalid_remote_url';\n delete metadata.remote_sync_target;\n }\n }\n return { ...record, metadata: JSON.stringify(metadata) };\n}\n\n/** Apply configured follow-up work to a persisted live interaction, regardless of capture adapter. */\nexport async function completeLiveCapture(dbPath: string, cfg: PhConfig, id: number): Promise<void> {\n if (cfg.backgroundAnalysis) spawnBackgroundAnalysis(id, dbPath);\n const remoteUrl = configuredRemoteUrl(cfg);\n if (!remoteUrl) return;\n\n let entry: PromptEntry | undefined;\n try {\n const db = new PhDB(dbPath);\n try {\n patchPromptMetadata(db, id, { capture_status: null, capture_owner_pid: null });\n entry = db.getById(id);\n }\n finally { db.close(); }\n } catch {\n setRemoteStatus(dbPath, id, 'failed', 'push_failed');\n return;\n }\n if (!entry) return;\n\n try {\n syncTarget(remoteUrl);\n } catch {\n setRemoteStatus(dbPath, id, 'failed', 'invalid_remote_url');\n process.stderr.write(`ph: invalid remote URL; interaction #${id} was saved locally but not pushed\\n`);\n return;\n }\n\n const metadata = decodePromptMetadata(entry.metadata);\n delete metadata.analysis_status;\n delete metadata.analysis_error;\n delete metadata.remote_sync_status;\n delete metadata.remote_sync_error;\n delete metadata.remote_sync_target;\n delete metadata.capture_status;\n delete metadata.capture_owner_pid;\n const remoteEntry = { ...entry, metadata: JSON.stringify(metadata) };\n try {\n const result = await sendSyncPushPage(remoteUrl, cfg.remoteApiKey, [remoteEntry], { timeoutMs: 5_000 });\n if (result.errors.length || result.imported + result.skipped !== 1) throw new Error('Remote rejected the interaction.');\n setRemoteStatus(dbPath, id, 'complete');\n } catch {\n setRemoteStatus(dbPath, id, 'failed', 'push_failed');\n process.stderr.write(`ph: remote push failed for interaction #${id}; run ph remote status for details\\n`);\n }\n}\n\nfunction setRemoteStatus(dbPath: string, id: number, status: 'complete' | 'failed', error?: 'push_failed' | 'invalid_remote_url'): void {\n try {\n const db = new PhDB(dbPath);\n try { patchPromptMetadata(db, id, { remote_sync_status: status, remote_sync_error: error ?? null }); }\n finally { db.close(); }\n } catch {\n process.stderr.write(`ph: could not save remote lifecycle status for interaction #${id}\\n`);\n }\n}\n","import { PhDB } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport { createCaptureRecord } from '../capture/index.js';\nimport { completeLiveCapture, prepareLiveCapture } from '../capture/lifecycle.js';\nimport { parseFlags } from './_utils.js';\n\nexport async function cmdLog(dbPath: string, cfg: PhConfig, args: string[]): Promise<void> {\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 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 baseRecord = createCaptureRecord({ tool, prompt, response, args: '', workdir });\n const record = prepareLiveCapture(baseRecord, cfg);\n\n const db = new PhDB(dbPath);\n const id = db.insert(record);\n db.close();\n\n await completeLiveCapture(dbPath, cfg, id);\n}\n","import type { PhConfig } from './index.js';\n\nexport interface ProviderSummary {\n id: NonNullable<PhConfig['analyzeProvider']>;\n label: string;\n model: string;\n url: string;\n credential: 'configured' | 'not set' | 'not required';\n active: boolean;\n ready: boolean;\n}\n\nexport function getProviderSummaries(cfg: PhConfig): ProviderSummary[] {\n const active = cfg.analyzeProvider ?? 'ollama';\n return [\n {\n id: 'ollama', label: 'Ollama',\n model: cfg.ollamaModel ?? 'llama3.1:latest',\n url: cfg.ollamaUrl ?? 'http://localhost:11434',\n credential: 'not required', active: active === 'ollama', ready: true,\n },\n {\n id: 'gemini', label: 'Gemini',\n model: 'gemini-2.5-flash', url: '(default)',\n credential: process.env.GEMINI_API_KEY || cfg.geminiApiKey ? 'configured' : 'not set',\n active: active === 'gemini', ready: Boolean(process.env.GEMINI_API_KEY || cfg.geminiApiKey),\n },\n {\n id: 'openrouter', label: 'OpenRouter',\n model: process.env.OPENROUTER_MODEL ?? cfg.openrouterModel ?? '(not set)',\n url: process.env.OPENROUTER_BASE_URL ?? cfg.openrouterUrl ?? 'https://openrouter.ai/api/v1',\n credential: process.env.OPENROUTER_API_KEY || cfg.openrouterApiKey ? 'configured' : 'not set',\n active: active === 'openrouter', ready: Boolean((process.env.OPENROUTER_API_KEY || cfg.openrouterApiKey) && (process.env.OPENROUTER_MODEL || cfg.openrouterModel)),\n },\n {\n id: 'mlx-serve', label: 'MLX-Serve',\n model: process.env.MLX_SERVE_MODEL ?? cfg.mlxServeModel ?? '(not set)',\n url: process.env.MLX_SERVE_BASE_URL ?? cfg.mlxServeUrl ?? 'http://127.0.0.1:11234/v1',\n credential: process.env.MLX_SERVE_API_KEY || process.env.GLB_OMLX_API_KEY || cfg.mlxServeApiKey ? 'configured' : 'not required',\n active: active === 'mlx-serve', ready: Boolean(process.env.MLX_SERVE_MODEL || cfg.mlxServeModel),\n },\n ];\n}\n\nexport function formatProviderSummary(provider: ProviderSummary): string {\n return `${provider.active ? '*' : ' '} ${provider.label}: model=${provider.model}, url=${provider.url}, key=${provider.credential}, setup=${provider.ready ? 'ready' : 'incomplete'}`;\n}\n","import { load as loadConfig, save as saveConfig } from '../config/index.js';\nimport { formatProviderSummary, getProviderSummaries } from '../config/provider-summary.js';\nimport { parseRemoteUrl } from '../sync/protocol.js';\n\nconst SECRET_KEYS = new Set([\n 'gemini-api-key',\n 'openrouter-api-key',\n 'mlx-serve-api-key',\n 'remote-api-key',\n]);\n\nconst KEY_ALIASES: Record<string, string> = {\n geminiApiKey: 'gemini-api-key',\n 'gemini-api-key': 'gemini-api-key',\n dbPath: 'db-path',\n 'db-path': 'db-path',\n analyzeProvider: 'analyze-provider',\n 'analyze-provider': 'analyze-provider',\n ollamaUrl: 'ollama-url',\n 'ollama-url': 'ollama-url',\n ollamaModel: 'ollama-model',\n 'ollama-model': 'ollama-model',\n openrouterModel: 'openrouter-model',\n 'openrouter-model': 'openrouter-model',\n openrouterUrl: 'openrouter-url',\n 'openrouter-url': 'openrouter-url',\n openrouterApiKey: 'openrouter-api-key',\n 'openrouter-api-key': 'openrouter-api-key',\n mlxServeModel: 'mlx-serve-model',\n 'mlx-serve-model': 'mlx-serve-model',\n mlxServeUrl: 'mlx-serve-url',\n 'mlx-serve-url': 'mlx-serve-url',\n mlxServeApiKey: 'mlx-serve-api-key',\n 'mlx-serve-api-key': 'mlx-serve-api-key',\n ollamaEmbedModel: 'ollama-embed-model',\n 'ollama-embed-model': 'ollama-embed-model',\n filterMinLength: 'filter-min-length',\n 'filter-min-length': 'filter-min-length',\n filterMinRelevance: 'filter-min-relevance',\n 'filter-min-relevance': 'filter-min-relevance',\n backgroundAnalysis: 'background-analysis',\n 'background-analysis': 'background-analysis',\n retentionDays: 'retention-days',\n 'retention-days': 'retention-days',\n retentionMinRelevance: 'retention-min-relevance',\n 'retention-min-relevance': 'retention-min-relevance',\n retentionMinStarred: 'retention-min-starred',\n 'retention-min-starred': 'retention-min-starred',\n retentionMinAnalyzed: 'retention-min-analyzed',\n 'retention-min-analyzed': 'retention-min-analyzed',\n remoteUrl: 'remote-url',\n 'remote-url': 'remote-url',\n remoteApiKey: 'remote-api-key',\n 'remote-api-key': 'remote-api-key',\n};\n\nconst CANONICAL_TO_PROP: Record<string, keyof ReturnType<typeof loadConfig>> = {\n 'gemini-api-key': 'geminiApiKey',\n 'db-path': 'dbPath',\n 'analyze-provider': 'analyzeProvider',\n 'ollama-url': 'ollamaUrl',\n 'ollama-model': 'ollamaModel',\n 'openrouter-model': 'openrouterModel',\n 'openrouter-url': 'openrouterUrl',\n 'openrouter-api-key': 'openrouterApiKey',\n 'mlx-serve-model': 'mlxServeModel',\n 'mlx-serve-url': 'mlxServeUrl',\n 'mlx-serve-api-key': 'mlxServeApiKey',\n 'ollama-embed-model': 'ollamaEmbedModel',\n 'filter-min-length': 'filterMinLength',\n 'filter-min-relevance': 'filterMinRelevance',\n 'background-analysis': 'backgroundAnalysis',\n 'retention-days': 'retentionDays',\n 'retention-min-relevance': 'retentionMinRelevance',\n 'retention-min-starred': 'retentionMinStarred',\n 'retention-min-analyzed': 'retentionMinAnalyzed',\n 'remote-url': 'remoteUrl',\n 'remote-api-key': 'remoteApiKey',\n};\n\nfunction parseBooleanConfig(key: string, val: string): boolean {\n if (val === 'true' || val === '1') return true;\n if (val === 'false' || val === '0') return false;\n throw new Error(`${key} must be true or false`);\n}\n\nexport async function cmdConfig(args: string[]): Promise<void> {\n if (args[0] === 'show') {\n const cfg = loadConfig();\n console.log('Analysis providers (* = active; credentials are never shown):');\n for (const provider of getProviderSummaries(cfg)) console.log(formatProviderSummary(provider));\n console.log('Configure with: ph config set analyze-provider <ollama|gemini|openrouter|mlx-serve>');\n return;\n }\n\n if (args[0] === 'get' && args.length >= 2) {\n const rawKey = args[1];\n const key = KEY_ALIASES[rawKey];\n if (!key) throw new Error(`unknown config key \"${rawKey}\"`);\n const cfg = loadConfig();\n const prop = CANONICAL_TO_PROP[key];\n const value = cfg[prop];\n if (SECRET_KEYS.has(key)) {\n console.log(value ? '[redacted]' : '(not set)');\n return;\n }\n console.log(value !== undefined ? String(value) : '(not set)');\n return;\n }\n\n if (args[0] !== 'set' || args.length < 2) {\n console.log('Usage: ph config show | ph config get <key> | ph config set <key> [value]');\n console.log('Keys: gemini-api-key, db-path, analyze-provider, ollama-url, ollama-model,');\n console.log(' openrouter-model, openrouter-url, openrouter-api-key,');\n console.log(' mlx-serve-model, mlx-serve-url, mlx-serve-api-key,');\n console.log(' ollama-embed-model, filter-min-length, filter-min-relevance, background-analysis,');\n console.log(' retention-days, retention-min-relevance, retention-min-starred, retention-min-analyzed,');\n console.log(' remote-url, remote-api-key');\n return;\n }\n\n const cfg = loadConfig();\n const rawKey = args[1];\n const key = KEY_ALIASES[rawKey];\n if (!key) throw new Error(`unknown config key \"${rawKey}\"`);\n\n let val = args.slice(2).join(' ');\n if (!val && SECRET_KEYS.has(key)) val = await readSecret(`${key}: `);\n if (!val) throw new Error(`A value is required for ${rawKey}.`);\n\n switch (key) {\n case 'gemini-api-key': cfg.geminiApiKey = val; break;\n case 'db-path': cfg.dbPath = val; break;\n case 'analyze-provider':\n if (!['ollama', 'gemini', 'openrouter', 'mlx-serve'].includes(val)) throw new Error('analyze-provider must be ollama, gemini, openrouter, or mlx-serve');\n cfg.analyzeProvider = val as NonNullable<typeof cfg.analyzeProvider>;\n break;\n case 'ollama-url': cfg.ollamaUrl = val; break;\n case 'ollama-model': cfg.ollamaModel = val; break;\n case 'openrouter-model': cfg.openrouterModel = val; break;\n case 'openrouter-url': cfg.openrouterUrl = val; break;\n case 'openrouter-api-key': cfg.openrouterApiKey = val; break;\n case 'mlx-serve-model': cfg.mlxServeModel = val; break;\n case 'mlx-serve-url': cfg.mlxServeUrl = val; break;\n case 'mlx-serve-api-key': cfg.mlxServeApiKey = val; break;\n case 'ollama-embed-model': cfg.ollamaEmbedModel = val; break;\n case 'filter-min-length': {\n const n = Number(val);\n if (!Number.isInteger(n) || n < 0) throw new Error('filter-min-length must be a non-negative integer');\n cfg.filterMinLength = n;\n break;\n }\n case 'filter-min-relevance': {\n const n = Number(val);\n if (!Number.isInteger(n) || n < 0 || n > 10) throw new Error('filter-min-relevance must be 0-10');\n cfg.filterMinRelevance = n;\n break;\n }\n case 'background-analysis': cfg.backgroundAnalysis = parseBooleanConfig(rawKey, val); break;\n case 'retention-days': {\n const n = Number(val);\n if (!Number.isInteger(n) || n < 1) throw new Error('retention-days must be a positive integer');\n cfg.retentionDays = n;\n break;\n }\n case 'retention-min-relevance': {\n const n = Number(val);\n if (!Number.isInteger(n) || n < 0 || n > 10) throw new Error('retention-min-relevance must be 0-10');\n cfg.retentionMinRelevance = n;\n break;\n }\n case 'retention-min-starred': cfg.retentionMinStarred = parseBooleanConfig(rawKey, val); break;\n case 'retention-min-analyzed': cfg.retentionMinAnalyzed = parseBooleanConfig(rawKey, val); break;\n case 'remote-url': parseRemoteUrl(val); cfg.remoteUrl = val; break;\n case 'remote-api-key': cfg.remoteApiKey = val; break;\n default: throw new Error(`unknown config key \"${rawKey}\"`);\n }\n\n saveConfig(cfg);\n console.log(SECRET_KEYS.has(key) ? `Config \"${key}\" updated (value hidden).` : `Config \"${key}\" updated successfully.`);\n}\n\nfunction readSecret(prompt: string): Promise<string> {\n if (!process.stdin.isTTY) throw new Error(`No value supplied for ${prompt.trim()}; use an environment variable in non-interactive shells.`);\n return new Promise((resolve, reject) => {\n const input = process.stdin;\n const previousRawMode = input.isRaw ?? false;\n let value = '';\n process.stderr.write(prompt);\n input.setRawMode(true);\n input.resume();\n const cleanup = () => {\n input.removeListener('data', onData);\n input.setRawMode(previousRawMode);\n process.stderr.write('\\n');\n };\n const onData = (chunk: Buffer) => {\n for (const byte of chunk) {\n if (byte === 3) { cleanup(); reject(new Error('Input cancelled.')); return; }\n if (byte === 13 || byte === 10) { cleanup(); resolve(value); return; }\n if (byte === 127 || byte === 8) value = value.slice(0, -1);\n else if (byte >= 32) value += String.fromCharCode(byte);\n }\n };\n input.on('data', onData);\n });\n}\n","import { PhDB } from '../db/index.js';\nimport { load as loadConfig } from '../config/index.js';\nimport { getProvider } from '../ai/provider.js';\nimport { analyzePrompt, mergeMetadata } from '../analyzer/index.js';\nimport { decodePromptMetadata } from '../interaction/detail.js';\n\nexport async 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 db = new PhDB(finalDbPath);\n try {\n const entry = db.getById(id);\n if (!entry) return;\n\n db.updateMetadataFields(id, { analysis_status: 'pending', analysis_error: null });\n let provider;\n try {\n provider = getProvider(loadConfig());\n } catch {\n db.updateMetadataFields(id, { analysis_status: 'failed', analysis_error: 'provider_unavailable' });\n return;\n }\n if (!provider) {\n db.updateMetadataFields(id, { analysis_status: 'failed', analysis_error: 'provider_unavailable' });\n return;\n }\n\n let result;\n try {\n result = await analyzePrompt(entry.prompt, provider);\n } catch {\n db.updateMetadataFields(id, { analysis_status: 'failed', analysis_error: 'analysis_failed' });\n return;\n }\n if (Object.keys(result).length === 0) {\n db.updateMetadataFields(id, { analysis_status: 'failed', analysis_error: 'analysis_failed' });\n return;\n }\n const metadata = decodePromptMetadata(entry.metadata);\n try {\n db.updateMetadataFields(id, {\n ...mergeMetadata(metadata, result, false),\n analysis_status: 'complete',\n analysis_error: null,\n });\n } catch {\n try { db.updateMetadataFields(id, { analysis_status: 'failed', analysis_error: 'analysis_persistence_failed' }); }\n catch { /* the database itself may be unavailable */ }\n }\n } catch (_err: unknown) {\n try { db.updateMetadataFields(id, { analysis_status: 'failed', analysis_error: 'analysis_failed' }); }\n catch { /* the database itself may be unavailable */ }\n } finally {\n db.close();\n }\n}\n","import { PhDB } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport type { PromptMetadata } from '../types.js';\nimport { FilterPipeline } from '../filter/index.js';\nimport { parseFlags } from './_utils.js';\n\nexport async function cmdCleanup(db: PhDB, cfg: PhConfig, args: string[]): Promise<void> {\n const { flags } = parseFlags(args);\n const dryRun = Boolean(flags['dry-run']);\n const retention = Boolean(flags['retention']);\n\n if (retention) {\n await runRetention(db, cfg, dryRun);\n return;\n }\n\n // Original rule-based cleanup\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 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 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 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 runRetention(db: PhDB, cfg: PhConfig, dryRun: boolean): Promise<void> {\n const retentionDays = cfg.retentionDays ?? 90;\n const minStarred = cfg.retentionMinStarred ?? true;\n const minAnalyzed = cfg.retentionMinAnalyzed ?? true;\n const minRelevance = cfg.retentionMinRelevance ?? 3;\n\n const cutoff = new Date();\n cutoff.setDate(cutoff.getDate() - retentionDays);\n const cutoffStr = cutoff.toISOString();\n\n const allEntries = db.search({ limit: 100000 });\n const stats = db.getArchiveStats();\n\n console.log(`Retention policy: ${retentionDays} days, minRelevance=${minRelevance}, keepStarred=${minStarred}, keepAnalyzed=${minAnalyzed}`);\n console.log(`Archive: ${stats.total} entries (${stats.oldest ? `oldest ${stats.oldest}` : 'empty'})`);\n console.log(`Scanning ${allEntries.length} prompts...\\n`);\n\n // Priority 1: relevance < threshold AND age > retentionDays → archive\n // Priority 2: age > retentionDays AND not starred AND not analyzed → archive\n const toArchive: Array<{ id: number; prompt: string; reason: string; meta: PromptMetadata }> = [];\n\n for (const entry of allEntries) {\n let meta: PromptMetadata = {};\n try { meta = JSON.parse(entry.metadata) as PromptMetadata; } catch {}\n\n const age = entry.timestamp;\n const isOld = age < cutoffStr;\n const isStarred = meta.starred === true;\n const isAnalyzed = Boolean(meta.summary || meta.role);\n const relevance = meta.relevance ?? 5;\n\n if (!isOld) continue;\n\n // Priority 1: low relevance + old\n if (relevance < minRelevance) {\n toArchive.push({ id: entry.id, prompt: entry.prompt, reason: `low_relevance(${relevance})`, meta });\n continue;\n }\n\n // Priority 2: old + not protected\n if (!(minStarred && isStarred) && !(minAnalyzed && isAnalyzed)) {\n toArchive.push({ id: entry.id, prompt: entry.prompt, reason: `old(>${retentionDays}d)`, meta });\n }\n }\n\n if (toArchive.length === 0) {\n console.log('No prompts match retention criteria.');\n return;\n }\n\n console.log(`Candidates for archiving: ${toArchive.length}`);\n for (const item of toArchive.slice(0, 20)) {\n const short = item.prompt.replace(/\\n/g, ' ').slice(0, 60);\n const starred = item.meta.starred ? ' *' : '';\n const analyzed = item.meta.summary ? ' [A]' : '';\n console.log(` #${String(item.id).padEnd(5)} [${item.reason}]${starred}${analyzed} \"${short}\"`);\n }\n if (toArchive.length > 20) {\n console.log(` ... and ${toArchive.length - 20} more`);\n }\n\n if (dryRun) {\n console.log(`\\n(dry-run) Would archive ${toArchive.length} prompts. Run without --dry-run to apply.`);\n return;\n }\n\n const ids = toArchive.map(e => e.id);\n const archived = db.archivePrompts(ids);\n console.log(`\\nArchived ${archived} prompts.`);\n\n // Auto-purge: archived entries older than 2x retentionDays\n const purgeCutoff = new Date();\n purgeCutoff.setDate(purgeCutoff.getDate() - retentionDays * 2);\n const purged = db.purgeArchive(purgeCutoff.toISOString());\n if (purged > 0) {\n console.log(`Purged ${purged} archived entries older than ${retentionDays * 2} days.`);\n }\n}\n","import { PhDB } from '../db/index.js';\n\nexport async 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","import { PhDB } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport { detectProject } from '../runner/project.js';\nimport { parseFlags } from './_utils.js';\nimport { formatProjectContext, getProjectContext } from '../context/index.js';\nimport { retrieveTaskContext } from '../knowledge/task-context.js';\n\nexport async function cmdContext(db: PhDB, cfg: PhConfig, args: string[]): Promise<void> {\n const { flags, positional } = parseFlags(args);\n const query = positional.join(' ');\n const project = (flags['project'] as string) || detectProject(process.cwd()).projectName;\n const limit = Number(flags['limit'] ?? 5);\n const promptsOnly = Boolean(flags['prompts-only']);\n const memoriesOnly = Boolean(flags['memories-only']);\n const verbose = Boolean(flags['verbose']);\n\n if (!project) {\n process.stderr.write('ph: could not detect project. Use --project <name>\\n');\n process.exit(1);\n }\n\n if (query) {\n const { context, fallbackReason } = await retrieveTaskContext(db, cfg, project, query, limit, {\n includeSummary: !promptsOnly,\n includeMemories: !promptsOnly,\n includePrompts: !memoriesOnly,\n });\n const requestedBudget = flags['budget'];\n const budget = typeof requestedBudget === 'string' ? Number(requestedBudget) : 3500;\n const warning = fallbackReason\n ? `\\nRetrieval fallback: ${fallbackReason}. Showing recent project context.\\n`\n : '';\n process.stdout.write(`# Project context: ${query}\\nProject: ${project}${warning}\\n`);\n process.stdout.write(formatProjectContext(context, {\n ...(!verbose ? { promptExcerptLength: 500 } : { includePromptText: true }),\n responseExcerptLength: 300,\n maxChars: Number.isInteger(budget) && budget >= 500 && budget <= 12000 ? budget : 3500,\n emptyMessage: `No saved knowledge found for project \"${project}\". This may be new work.`,\n }) + '\\n');\n return;\n }\n\n const context = await getProjectContext(db, {\n project,\n query,\n limit,\n includeSummary: !promptsOnly,\n includeMemories: !promptsOnly,\n includePrompts: !memoriesOnly,\n });\n\n process.stdout.write(formatProjectContext(context, { includePromptText: verbose }) + '\\n');\n}\n","import { createInterface } from 'node:readline/promises';\nimport type { PhConfig } from '../config/index.js';\nimport { getProvider, getProviderSetupError } from '../ai/provider.js';\nimport type { PhDB } from '../db/index.js';\nimport type { PromptEntry } from '../types.js';\nimport { promoteProjectKnowledge } from '../knowledge/promotion.js';\nimport { detectProject } from '../runner/project.js';\nimport { parseFlags } from './_utils.js';\n\nexport interface KnowledgeProposal {\n summary: string;\n key_insights: string[];\n technical_decisions: string[];\n source_prompt_ids: number[];\n}\n\nexport function parseKnowledgeProposals(raw: string, allowedPromptIds?: number[]): KnowledgeProposal[] {\n const text = raw.trim().replace(/^```(?:json)?\\s*/i, '').replace(/\\s*```$/, '');\n const parsed = JSON.parse(text) as { proposals?: unknown };\n if (!Array.isArray(parsed.proposals)) throw new Error('Provider response must contain a proposals array');\n return parsed.proposals.map((value, index) => {\n if (!value || typeof value !== 'object') throw new Error(`Proposal ${index + 1} is invalid`);\n const item = value as Record<string, unknown>;\n const summary = typeof item.summary === 'string' ? item.summary.trim() : '';\n const strings = (v: unknown) => Array.isArray(v) && v.every(x => typeof x === 'string') ? v.map(x => x.trim()).filter(Boolean) : [];\n if (!summary) throw new Error(`Proposal ${index + 1} has no summary`);\n const sourceIds = Array.isArray(item.source_prompt_ids) && item.source_prompt_ids.every(id => Number.isInteger(id) && Number(id) > 0)\n ? [...new Set(item.source_prompt_ids as number[])] : [];\n if (allowedPromptIds && (!sourceIds.length || sourceIds.some(id => !allowedPromptIds.includes(id)))) {\n throw new Error(`Proposal ${index + 1} must cite selected source prompt IDs`);\n }\n return { summary, key_insights: strings(item.key_insights), technical_decisions: strings(item.technical_decisions), source_prompt_ids: sourceIds };\n });\n}\n\nexport async function cmdClose(db: PhDB, cfg: PhConfig, args: string[]): Promise<void> {\n const { flags } = parseFlags(args);\n const project = (flags.project as string | undefined) || detectProject(process.cwd()).projectName;\n if (!project) throw new Error('Could not detect project. Use --project <name>.');\n const since = (flags.since as string | undefined) ?? (!flags.from && !flags.to ? '3h' : undefined);\n const from = flags.from as string | undefined;\n const to = flags.to as string | undefined;\n if (Boolean(since) === Boolean(from || to) || Boolean(from) !== Boolean(to)) {\n throw new Error('Choose either --since <duration> or both --from <id> --to <id>.');\n }\n const entries = since\n ? db.search({ project, since: new Date(Date.now() - parseDuration(since)), limit: 200 })\n : promptRange(db, project, Number(from), Number(to));\n if (!entries.length) throw new Error(`No prompts found for project \"${project}\" in the selected range.`);\n const selected = entries.slice(0, 12).sort((a, b) => a.timestamp.localeCompare(b.timestamp));\n process.stdout.write(`Close review for ${project}: ${selected.length} prompt(s)${entries.length > selected.length ? ` (first 12 of ${entries.length})` : ''}\\n`);\n for (const entry of selected) {\n process.stdout.write(`\\n#${entry.id} ${entry.tool} ${entry.timestamp}\\nPrompt: ${entry.prompt.slice(0, 1000)}${entry.prompt.length > 1000 ? '…' : ''}\\nResponse: ${entry.response.slice(0, 1200)}${entry.response.length > 1200 ? '…' : ''}\\n`);\n }\n if (flags['dry-run']) {\n process.stdout.write('\\nDry run: no model call and no database changes.\\n');\n return;\n }\n if (!process.stdin.isTTY || !process.stdout.isTTY) throw new Error('Interactive approval requires a TTY. Re-run ph close in a terminal; no model call or database changes were made.');\n const provider = getProvider(cfg);\n if (!provider) throw new Error(getProviderSetupError(cfg) ?? 'No LLM provider is configured.');\n const source = selected.map(e => `PROMPT #${e.id} (${e.tool})\\n${e.prompt.slice(0, 2500)}\\nRESPONSE\\n${e.response.slice(0, 3000)}`).join('\\n\\n---\\n\\n');\n const answer = await provider.generate(`Extract only durable, reusable project knowledge from the work log below. Propose zero or more separate items. Do not invent facts. For each proposal, cite the relevant source IDs from this work log. Return JSON only: {\"proposals\":[{\"summary\":\"...\",\"key_insights\":[\"...\"],\"technical_decisions\":[\"...\"],\"source_prompt_ids\":[123]}]}.\\nProject: ${project}\\n\\n${source}`);\n const proposals = parseKnowledgeProposals(answer, selected.map(entry => entry.id));\n if (!proposals.length) {\n process.stdout.write('\\nNo durable knowledge proposal. Nothing saved.\\n');\n return;\n }\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n const approved: KnowledgeProposal[] = [];\n let cancelled = false;\n try {\n for (const [index, initial] of proposals.entries()) {\n let proposal = initial;\n process.stdout.write(`\\nProposal ${index + 1}/${proposals.length}\\nSummary: ${proposal.summary}\\nKey insights: ${proposal.key_insights.join(' | ') || '(none)'}\\nDecisions: ${proposal.technical_decisions.join(' | ') || '(none)'}\\nSources: ${proposal.source_prompt_ids.map(id => `#${id}`).join(', ')}\\n`);\n const action = (await rl.question('[a]pprove, [e]dit, [s]kip, [q]uit? ')).trim().toLowerCase();\n if (action === 'q') { cancelled = true; break; }\n if (action === 's' || !action) continue;\n if (action === 'e') {\n const summary = (await rl.question(`Summary [${proposal.summary}]: `)).trim();\n const insights = (await rl.question(`Key insights separated by | [${proposal.key_insights.join(' | ')}]: `)).trim();\n const decisions = (await rl.question(`Technical decisions separated by | [${proposal.technical_decisions.join(' | ')}]: `)).trim();\n proposal = {\n summary: summary || proposal.summary,\n key_insights: insights ? splitList(insights) : proposal.key_insights,\n technical_decisions: decisions ? splitList(decisions) : proposal.technical_decisions,\n source_prompt_ids: proposal.source_prompt_ids,\n };\n process.stdout.write(`\\nEdited summary: ${proposal.summary}\\nInsights: ${proposal.key_insights.join(' | ')}\\nDecisions: ${proposal.technical_decisions.join(' | ')}\\n`);\n if ((await rl.question('Save this proposal? [y/N] ')).trim().toLowerCase() !== 'y') continue;\n } else if (action !== 'a') continue;\n approved.push(proposal);\n }\n } finally {\n rl.close();\n }\n if (cancelled) {\n process.stdout.write('\\nReview cancelled. No proposals were saved.\\n');\n return;\n }\n const savedIds = promoteProjectKnowledge(db, approved.map(proposal => ({\n project,\n prompt_ids: proposal.source_prompt_ids,\n summary: proposal.summary,\n key_insights: proposal.key_insights,\n technical_decisions: proposal.technical_decisions,\n })));\n approved.forEach((proposal, index) => process.stdout.write(`Saved memory #${savedIds[index]} with sources ${proposal.source_prompt_ids.map(i => `#${i}`).join(', ')}.\\n`));\n}\n\nfunction parseDuration(raw: string): number {\n const match = /^(\\d+)(m|h|d)$/.exec(raw);\n if (!match) throw new Error('--since accepts durations like 30m, 3h, or 1d');\n const amount = Number(match[1]);\n const multiplier = match[2] === 'm' ? 60_000 : match[2] === 'h' ? 3_600_000 : 86_400_000;\n const result = amount * multiplier;\n if (result <= 0 || result > 30 * 86_400_000) throw new Error('--since must be between 1 minute and 30 days');\n return result;\n}\n\nfunction promptRange(db: PhDB, project: string, from: number, to: number): PromptEntry[] {\n if (!Number.isInteger(from) || !Number.isInteger(to) || from <= 0 || to < from || to - from > 500) throw new Error('Prompt range must be valid IDs with at most 500 IDs between them.');\n const entries: PromptEntry[] = [];\n for (let id = from; id <= to; id++) {\n const entry = db.getById(id);\n if (!entry) continue;\n let metadata: { project?: string } = {};\n try { metadata = JSON.parse(entry.metadata) as { project?: string }; } catch {}\n if (metadata.project === project) entries.push(entry);\n }\n return entries;\n}\n\nfunction splitList(value: string): string[] { return value.split('|').map(item => item.trim()).filter(Boolean); }\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';\nimport { groupIntoSessions, computeSessionCohesion } from '../sessions/index.js';\nimport { parseFlags } from './_utils.js';\n\nfunction formatTimestamp(ts: string): string {\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}\n\nfunction 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\nfunction parseMeta(raw: string): PromptMetadata {\n try { return JSON.parse(raw) as PromptMetadata; } catch { return {}; }\n}\n\nfunction exportSessionMarkdown(session: { index: number; startTime: Date; endTime: Date; entries: import('../types.js').PromptEntry[] }): string {\n const lines: string[] = [];\n const dateStr = formatTimestamp(session.startTime.toISOString());\n const endStr = fmtTime(session.endTime.toISOString());\n\n lines.push(`# Session ${session.index} — ${dateStr} → ${endStr}`);\n lines.push('');\n lines.push(`**${session.entries.length} prompts**`);\n lines.push('');\n lines.push('---');\n lines.push('');\n\n for (const entry of session.entries) {\n const meta = parseMeta(entry.metadata);\n const ts = formatTimestamp(entry.timestamp);\n const title = meta.title || entry.prompt.replace(/\\n/g, ' ').slice(0, 60);\n\n lines.push(`## #${entry.id} — ${entry.tool} — ${ts}`);\n if (title) lines.push(`**${title}**`);\n lines.push('');\n\n const metaLine: string[] = [];\n if (meta.role) metaLine.push(`Role: ${meta.role}`);\n if (meta.project) metaLine.push(`Project: ${meta.project}`);\n if (meta.language) metaLine.push(`Language: ${meta.language}`);\n if (meta.tags?.length) metaLine.push(`Tags: ${meta.tags.join(', ')}`);\n if (meta.relevance !== undefined) metaLine.push(`Relevance: ${meta.relevance}/10`);\n if (meta.quality !== undefined) metaLine.push(`Quality: ${meta.quality}/10`);\n if (metaLine.length > 0) {\n lines.push(metaLine.join(' · '));\n lines.push('');\n }\n\n if (meta.summary) {\n lines.push(`> ${meta.summary}`);\n lines.push('');\n }\n\n lines.push('### Prompt');\n lines.push('');\n lines.push('```');\n lines.push(entry.prompt);\n lines.push('```');\n lines.push('');\n\n if (entry.response) {\n lines.push('### Response');\n lines.push('');\n lines.push('```');\n lines.push(entry.response.slice(0, 2000));\n lines.push('```');\n lines.push('');\n }\n\n if (meta.key_insights?.length) {\n lines.push('**Insights:**');\n for (const ins of meta.key_insights) lines.push(`- ${ins}`);\n lines.push('');\n }\n\n if (meta.git_context) {\n lines.push(`*Git: ${meta.git_context.branch}, ${meta.git_context.files?.length || 0} files modified*`);\n lines.push('');\n }\n\n lines.push('---');\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\nexport async 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 const exportIndex = flags['export'] !== undefined ? Number(flags['export']) : undefined;\n\n const allEntries = db.search({ limit: 100000 });\n const entriesAsc = [...allEntries].reverse();\n\n const sessions = groupIntoSessions(entriesAsc, gapHours);\n\n let embeddings: Map<number, Float32Array> | null = null;\n if (!noCohesion && exportIndex === undefined) {\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 // Export mode: output a single session as markdown\n if (exportIndex !== undefined) {\n const session = sessions.find(s => s.index === exportIndex);\n if (!session) {\n process.stderr.write(`Session ${exportIndex} not found.\\n`);\n return;\n }\n process.stdout.write(exportSessionMarkdown(session));\n return;\n }\n\n const filtered = sessions.filter(s => s.entries.length >= minSize);\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 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 for (const session of visible) {\n const projectCounts = new Map<string, number>();\n const languageCounts = new Map<string, number>();\n for (const entry of session.entries) {\n const meta = parseMeta(entry.metadata);\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 const startStr = formatTimestamp(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 for (const entry of session.entries) {\n const meta = parseMeta(entry.metadata);\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","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 { PhDB } from '../db/index.js';\nimport { getStats } from '../stats/index.js';\n\nexport async 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","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: Float32Array<ArrayBufferLike>[] = 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: Float32Array<ArrayBufferLike>[] = 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","import { PhDB } from '../db/index.js';\nimport { kmeans } from '../cluster/index.js';\nimport { parseFlags } from './_utils.js';\n\nexport async 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 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","import fs from 'fs';\nimport { PhDB } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport { ReusabilityAnalyzer } from '../analyzer/reusability.js';\nimport { parseFlags } from './_utils.js';\n\nexport async function cmdAnalyzeReusability(db: PhDB, _cfg: PhConfig, 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","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 fs from 'fs';\nimport { PhDB } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport { ReusabilityAnalyzer } from '../analyzer/reusability.js';\nimport { parseFlags } from './_utils.js';\n\nexport async 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 const totalSize = candidates.reduce((sum, c) => sum + c.promptSize + c.responseSize, 0);\n const totalEmbeddingSize = candidates.filter(c => c.hasEmbedding).length * 768 * 4;\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 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, null);\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","import { PhDB } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport type { PromptEntry, PromptMetadata, MemoryEntry } from '../types.js';\nimport { detectProject } from '../runner/project.js';\nimport { parseFlags } from './_utils.js';\n\ninterface TimelineEvent {\n type: 'prompt' | 'memory';\n timestamp: string;\n prompt?: PromptEntry;\n memory?: MemoryEntry;\n}\n\nexport async function cmdTimeline(db: PhDB, cfg: PhConfig, args: string[]): Promise<void> {\n const { flags, positional } = parseFlags(args);\n const project = (flags['project'] as string) || positional.join(' ') || detectProject(process.cwd()).projectName;\n\n if (!project) {\n process.stderr.write('ph: could not detect project. Use --project <name> or pass a project name.\\n');\n process.exit(1);\n }\n\n const prompts = db.getAllPromptsByProject(project);\n const memories = db.getAllMemoriesByProject(project);\n\n if (prompts.length === 0 && memories.length === 0) {\n process.stdout.write(`No history found for project \"${project}\".\\n`);\n return;\n }\n\n const output: string[] = [];\n\n output.push(`# Timeline: ${project}\\n`);\n output.push(`**${prompts.length} prompts** · **${memories.length} memory entries**\\n`);\n\n const events: TimelineEvent[] = [\n ...prompts.map(p => ({ type: 'prompt' as const, timestamp: p.timestamp, prompt: p })),\n ...memories.map(m => ({ type: 'memory' as const, timestamp: m.created_at, memory: m })),\n ];\n events.sort((a, b) => a.timestamp.localeCompare(b.timestamp));\n\n let currentDate = '';\n\n for (const event of events) {\n const date = new Date(event.timestamp).toLocaleDateString('en-CA'); // YYYY-MM-DD\n if (date !== currentDate) {\n currentDate = date;\n output.push(`\\n## ${date}\\n`);\n }\n\n if (event.type === 'prompt' && event.prompt) {\n output.push(formatPromptEntry(event.prompt));\n }\n\n if (event.type === 'memory' && event.memory) {\n output.push(formatMemoryEntry(event.memory));\n }\n }\n\n process.stdout.write(output.join('\\n'));\n}\n\nfunction formatPromptEntry(e: PromptEntry): string {\n let meta: PromptMetadata = {};\n try { meta = JSON.parse(e.metadata); } catch {}\n\n const time = new Date(e.timestamp).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });\n const lines: string[] = [];\n lines.push(`### #${e.id} — ${e.tool} — ${time}`);\n if (meta.role) lines.push(`**Role**: ${meta.role}`);\n if (meta.title) lines.push(`**Title**: ${meta.title}`);\n if (meta.tags?.length) lines.push(`**Tags**: ${meta.tags.join(', ')}`);\n if (meta.summary) lines.push(`**Summary**: ${meta.summary}`);\n if (meta.relevance !== undefined) lines.push(`**Relevance**: ${meta.relevance}/10`);\n lines.push('');\n lines.push('**Prompt**:');\n lines.push('```');\n lines.push(e.prompt.slice(0, 500) + (e.prompt.length > 500 ? '\\n...' : ''));\n lines.push('```');\n if (e.response) {\n lines.push('');\n lines.push('**Response**:');\n lines.push('```');\n lines.push(e.response.slice(0, 300) + (e.response.length > 300 ? '\\n...' : ''));\n lines.push('```');\n }\n if (meta.key_insights?.length) {\n lines.push('');\n lines.push('**Insights**:');\n for (const i of meta.key_insights) lines.push(`- ${i}`);\n }\n lines.push('---\\n');\n return lines.join('\\n');\n}\n\nfunction formatMemoryEntry(m: MemoryEntry): string {\n const time = new Date(m.created_at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });\n const lines: string[] = [];\n lines.push(`> 📌 **Memory #${m.id} — ${time}**`);\n if (m.prompt_ids.length > 0) {\n lines.push(`> _Derived from prompts: #${m.prompt_ids.join(', #')}_`);\n }\n if (m.summary) lines.push(`> **Summary**: ${m.summary}`);\n if (m.key_insights.length > 0) {\n lines.push(`> **Insights**:`);\n for (const i of m.key_insights) lines.push(`> - ${i}`);\n }\n if (m.technical_decisions.length > 0) {\n lines.push(`> **Technical Decisions**:`);\n for (const d of m.technical_decisions) lines.push(`> - ${d}`);\n }\n lines.push('---\\n');\n return lines.join('\\n');\n}\n","import { PhDB } from '../db/index.js';\n\nexport function cmdMemoryMigrate(db: PhDB): void {\n const projects = db.getAllProjectsWithMemories();\n if (projects.length === 0) {\n console.log('No memories found. Nothing to migrate.');\n return;\n }\n\n let count = 0;\n for (const project of projects) {\n const memories = db.searchMemories(project, 1000);\n const allInsights = new Set<string>();\n const allDecisions = new Set<string>();\n let lastSummary = '';\n let gitCtx: string | undefined;\n\n for (const mem of memories) {\n if (mem.summary) lastSummary = mem.summary;\n for (const i of mem.key_insights) allInsights.add(i);\n for (const d of mem.technical_decisions) allDecisions.add(d);\n if (mem.git_context_snapshot) gitCtx = mem.git_context_snapshot;\n }\n\n db.upsertProjectSummary({\n project,\n summary: lastSummary,\n key_insights: [...allInsights],\n technical_decisions: [...allDecisions],\n git_context_snapshot: gitCtx,\n });\n count++;\n }\n\n console.log(`Migrated ${count} project(s) into project_summaries.`);\n}\n","import path from 'path';\nimport os from 'os';\nimport { PhDB } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport { captureGitContext } from '../runner/git-context.js';\nimport { createCaptureRecord } from '../capture/index.js';\nimport { completeLiveCapture, prepareLiveCapture } from '../capture/lifecycle.js';\nimport { runInline, resolveRealBinary } from '../runner/inline.js';\nimport { runPTY, isTerminal } from '../pty/wrapper.js';\n\nexport async function cmdWrap(dbPath: string, tool: string, args: string[], cfg: PhConfig): Promise<void> {\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 gitContext = captureGitContext(workdir);\n const completionTasks: Promise<void>[] = [];\n\n const onPrompt = (prompt: string, ts: Date): number => {\n return db.insert(prepareLiveCapture(createCaptureRecord({\n timestamp: ts.toISOString(),\n tool,\n prompt,\n args: prompt,\n workdir,\n gitContext,\n metadata: { ...(role ? { role } : {}), ...(tags.length > 0 ? { tags } : {}) },\n }), cfg, { inProgress: true }));\n };\n\n const onResponse = (id: number, response: string) => {\n db.updateResponse(id, response);\n completionTasks.push(completeLiveCapture(dbPath, cfg, id));\n };\n\n let exitCode: number;\n try {\n exitCode = await runPTY(realBin, cleanArgs, onPrompt, onResponse, debugLog);\n await Promise.all(completionTasks);\n } finally {\n db.close();\n }\n process.exit(exitCode);\n } else {\n try {\n await runInline(realBin, cleanArgs, db, tool, tags, cfg, role);\n } finally {\n db.close();\n }\n }\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 { spawn, execFileSync } from 'child_process';\nimport fs from 'fs';\nimport { PhDB } from '../db/index.js';\nimport { captureGitContext } from './git-context.js';\nimport { createCaptureRecord } from '../capture/index.js';\nimport { completeLiveCapture, prepareLiveCapture } from '../capture/lifecycle.js';\nimport type { PhConfig } from '../config/index.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 cfg: PhConfig,\n role?: string\n): Promise<void> {\n const workdir = process.cwd();\n const gitContext = captureGitContext(workdir);\n\n const record = prepareLiveCapture(createCaptureRecord({\n tool,\n prompt: extractPrompt(args),\n args: args.join(' '),\n workdir,\n gitContext,\n metadata: { ...(role ? { role } : {}), ...(tags.length > 0 ? { tags } : {}) },\n }), cfg, { inProgress: true });\n const id = db.insert(record);\n\n const child = spawn(realBin, args, { stdio: ['inherit', 'pipe', 'inherit'] });\n let response = '';\n let spawnError: Error | undefined;\n child.stdout?.setEncoding('utf8');\n child.stdout?.on('data', (chunk: string) => {\n process.stdout.write(chunk);\n response += chunk;\n });\n\n return new Promise(resolve => {\n child.once('error', error => { spawnError = error; });\n child.once('close', async (code, signal) => {\n const exitCode = spawnError ? 1 : (code ?? (signal ? 1 : 0));\n if (spawnError) process.stderr.write(`ph: spawn error: ${spawnError.message}\\n`);\n try {\n db.updateResponse(id, response);\n db.updateExitCode(id, exitCode);\n } catch (error) {\n process.stderr.write(`ph: could not persist wrapper response: ${(error as Error).message}\\n`);\n process.exitCode = 1;\n }\n await completeLiveCapture(db.dbPath, cfg, id);\n if (process.exitCode === undefined || process.exitCode === 0) process.exitCode = exitCode;\n resolve();\n });\n });\n}\n","import pty from '@lydell/node-pty';\nimport fs from 'fs';\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 */\nexport function stripPtyControlSequences(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, stripPtyControlSequences(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, stripPtyControlSequences(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 { spawnSync } from 'child_process';\nimport { PhDB } from '../db/index.js';\nimport type { PhConfig } from '../config/index.js';\nimport { detectProject } from '../runner/project.js';\nimport { resolveRealBinary } from '../runner/inline.js';\nimport { formatProjectContext } from '../context/index.js';\nimport { retrieveTaskContext } from '../knowledge/task-context.js';\n\nexport async function cmdChat(dbPath: string, cfg: PhConfig, args: string[]): Promise<void> {\n if (args.length === 0) {\n process.stderr.write('Usage: ph chat <tool> [tool-args...]\\n');\n process.exit(1);\n }\n\n const tool = args[0];\n const userPrompt = args.slice(1).join(' ');\n if (!userPrompt) {\n process.stderr.write('ph chat: no prompt provided\\n');\n process.exit(1);\n }\n\n const project = detectProject(process.cwd()).projectName;\n if (!project) {\n process.stderr.write('ph chat: could not detect project. Run from a project directory.\\n');\n process.exit(1);\n }\n\n const db = new PhDB(dbPath);\n let context;\n let fallbackReason: string | undefined;\n try {\n const retrieved = await retrieveTaskContext(db, cfg, project, userPrompt, 5);\n context = retrieved.context;\n fallbackReason = retrieved.fallbackReason;\n } finally {\n db.close();\n }\n\n const contextStr = formatProjectContext(context);\n const fallbackLabel = fallbackReason\n ? `Context retrieval fallback: ${fallbackReason}. The following context is recent project history, not a semantic task match.\\n\\n`\n : '';\n const fullPrompt = `Context from project \"${project}\":\\n\\n${fallbackLabel}${contextStr}\\n\\n---\\n\\n${userPrompt}`;\n\n const realBin = resolveRealBinary(tool);\n const child = spawnSync(realBin, [fullPrompt], { stdio: 'inherit', cwd: process.cwd() });\n process.exit(child.status ?? 0);\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\ntype HookFile = 'settings.json' | 'hooks.json';\ntype JsonObject = Record<string, unknown>;\n\nconst hookDefinitions: Record<string, { directory: string; file: HookFile; event: string; script: string }> = {\n claude: { directory: '.claude', file: 'settings.json', event: 'Stop', script: 'claude/ph-hook.sh' },\n codex: { directory: '.codex', file: 'hooks.json', event: 'Stop', script: 'codex/ph-hook.sh' },\n gemini: { directory: '.gemini', file: 'settings.json', event: 'AfterAgent', script: 'gemini/ph-hook.sh' },\n};\nconst supportedTools = ['claude', 'codex', 'gemini', 'opencode'];\nexport type SetupStatus = 'installed' | 'updated' | 'already-configured';\nexport interface SetupResult { tool: string; status: SetupStatus }\n\nexport function detectCaptureTools(pathValue = process.env.PATH ?? ''): string[] {\n const directories = pathValue.split(path.delimiter).filter(Boolean);\n return supportedTools.filter(tool => directories.some(directory => {\n const binary = path.join(directory, tool);\n try { fs.accessSync(binary, fs.constants.X_OK); return true; } catch { return false; }\n }));\n}\n\n/** Install capture hooks into the user's existing AI CLI configuration. */\nexport function setupCapture(home = process.env.HOME ?? '', hooksRoot = defaultHooksRoot(), tools = supportedTools): SetupResult[] {\n if (!home) throw new Error('Cannot determine the home directory.');\n const results: SetupResult[] = [];\n const destination = path.join(home, '.ph', 'hooks');\n fs.mkdirSync(destination, { recursive: true });\n\n for (const tool of tools) {\n if (tool === 'opencode') {\n const source = path.join(hooksRoot, 'opencode/ph-plugin.ts');\n if (!fs.existsSync(source)) throw new Error(`Hook script not found: ${source}`);\n const plugin = path.join(home, '.config/opencode/plugins/ph-plugin.ts');\n fs.mkdirSync(path.dirname(plugin), { recursive: true });\n if (fs.existsSync(plugin)) {\n if (fs.readFileSync(plugin, 'utf8') !== fs.readFileSync(source, 'utf8')) {\n throw new Error(`Refusing to overwrite existing OpenCode plugin: ${plugin}`);\n }\n results.push({ tool, status: 'already-configured' });\n } else {\n fs.copyFileSync(source, plugin);\n results.push({ tool, status: 'installed' });\n }\n continue;\n }\n const definition = hookDefinitions[tool];\n if (!definition) continue;\n const source = path.join(hooksRoot, definition.script);\n if (!fs.existsSync(source)) throw new Error(`Hook script not found: ${source}`);\n const targetScript = path.join(destination, `${tool}-ph-hook.sh`);\n const scriptExists = fs.existsSync(targetScript);\n const scriptChanged = !scriptExists || fs.readFileSync(targetScript, 'utf8') !== fs.readFileSync(source, 'utf8');\n if (scriptChanged) fs.copyFileSync(source, targetScript);\n fs.chmodSync(targetScript, 0o755);\n\n const configPath = path.join(home, definition.directory, definition.file);\n const config = readConfig(configPath);\n if (config.hooks !== undefined && (!config.hooks || typeof config.hooks !== 'object' || Array.isArray(config.hooks))) {\n throw new Error(`Cannot safely update ${configPath}: hooks must be an object`);\n }\n const hooks = asObject(config.hooks);\n const currentEvent = hooks[definition.event];\n if (currentEvent !== undefined && !Array.isArray(currentEvent)) {\n throw new Error(`Cannot safely update ${configPath}: hooks.${definition.event} must be an array`);\n }\n const entries = (currentEvent ?? []) as unknown[];\n const command = `${targetScript}`;\n const configured = entries.some(entry => JSON.stringify(entry).includes(command));\n if (!configured) {\n const hook = { type: 'command', command };\n const entry = tool === 'codex'\n ? { hooks: [hook] }\n : { ...(tool === 'claude' ? { matcher: '.*' } : {}), hooks: [{ ...hook, ...(tool === 'claude' ? { async: true } : {}) }] };\n hooks[definition.event] = [...entries, entry];\n config.hooks = hooks;\n writeConfig(configPath, config);\n }\n results.push({\n tool,\n status: configured ? (scriptChanged ? 'updated' : 'already-configured') : 'installed',\n });\n }\n return results;\n}\n\nexport function defaultHooksRoot(): string {\n const here = path.dirname(fileURLToPath(import.meta.url));\n return [path.resolve(here, '../../hooks'), path.resolve(here, '../hooks')].find(candidate => fs.existsSync(candidate))\n ?? path.resolve(here, '../../hooks');\n}\n\nfunction readConfig(file: string): JsonObject {\n if (!fs.existsSync(file)) return {};\n try {\n const parsed: unknown = JSON.parse(fs.readFileSync(file, 'utf8'));\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) throw new Error('root must be an object');\n return parsed as JsonObject;\n } catch (error) {\n throw new Error(`Cannot safely update ${file}: ${(error as Error).message}`);\n }\n}\n\nfunction asObject(value: unknown): JsonObject {\n return value && typeof value === 'object' && !Array.isArray(value) ? value as JsonObject : {};\n}\n\nfunction writeConfig(file: string, config: JsonObject): void {\n const target = fs.existsSync(file) && fs.lstatSync(file).isSymbolicLink() ? fs.realpathSync(file) : file;\n fs.mkdirSync(path.dirname(target), { recursive: true });\n const temp = `${target}.ph-tmp`;\n const mode = fs.existsSync(target) ? fs.statSync(target).mode & 0o777 : 0o600;\n fs.writeFileSync(temp, `${JSON.stringify(config, null, 2)}\\n`, { mode });\n fs.renameSync(temp, target);\n}\n\n","import type { PhConfig } from '../config/index.js';\nimport { discoverModels, MLX_SERVE_DEFAULT_URL, OPENROUTER_DEFAULT_URL } from '../ai/wise.js';\n\nexport async function cmdModels(cfg: PhConfig, args: string[]): Promise<void> {\n const provider = args[0] ?? cfg.analyzeProvider;\n if (provider !== 'openrouter' && provider !== 'mlx-serve') {\n throw new Error('Choose a provider: `ph models openrouter` or `ph models mlx-serve`.');\n }\n\n const cfgKey = provider === 'openrouter' ? cfg.openrouterApiKey : cfg.mlxServeApiKey;\n if (provider === 'openrouter' && !(process.env.OPENROUTER_API_KEY || cfgKey)) {\n throw new Error('Configure a key with `ph config set openrouter-api-key` or set OPENROUTER_API_KEY.');\n }\n\n const apiKey = provider === 'openrouter'\n ? process.env.OPENROUTER_API_KEY ?? cfg.openrouterApiKey!\n : process.env.MLX_SERVE_API_KEY ?? process.env.GLB_OMLX_API_KEY ?? cfg.mlxServeApiKey ?? 'local';\n const baseUrl = provider === 'openrouter'\n ? process.env.OPENROUTER_BASE_URL ?? cfg.openrouterUrl ?? OPENROUTER_DEFAULT_URL\n : process.env.MLX_SERVE_BASE_URL ?? cfg.mlxServeUrl ?? MLX_SERVE_DEFAULT_URL;\n\n let models;\n try {\n models = await discoverModels(provider, apiKey, baseUrl);\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n const tunnel = provider === 'mlx-serve' && /127\\.0\\.0\\.1|localhost/.test(baseUrl)\n ? '\\nParmenide: apri in un altro terminale `ssh -N -L 11234:127.0.0.1:11234 parmenide`, poi riprova. Puoi impostare un URL raggiungibile con `ph config set mlx-serve-url <url>`.'\n : '';\n throw new Error(`Cannot query ${provider} at ${baseUrl}: ${detail}${tunnel}`);\n }\n if (models.length === 0) {\n const tunnel = provider === 'mlx-serve'\n ? '\\nSe il CLI gira sul Mac e il server su Parmenide, apri: ssh -N -L 11234:127.0.0.1:11234 parmenide'\n : '';\n throw new Error(`No models returned by ${provider} at ${baseUrl}. Check connectivity and credentials.${tunnel}`);\n }\n\n console.log(`Models listed by ${provider} at ${baseUrl}:`);\n for (const model of models) {\n const status = model.loaded === undefined ? '' : model.loaded ? ' [loaded]' : ` [${model.state ?? 'unloaded'}]`;\n console.log(` ${model.id}${model.name !== model.id ? ` — ${model.name}` : ''}${status}`);\n }\n if (provider === 'mlx-serve') {\n console.log('\\nph can list installed models even when they are unloaded. Select a model marked [loaded] to run it immediately.');\n }\n}\n","#!/usr/bin/env node\n\nimport { load as loadConfig } from './config/index.js';\nimport { PhDB, defaultPath } from './db/index.js';\nimport { runMCPServer } from './mcp/server.js';\nimport { runServer } from './server/index.js';\nimport { cmdRemote } from './commands/remote.js';\nimport { cmdSearch } from './commands/search.js';\nimport { cmdShow } from './commands/show.js';\nimport { cmdStatus } from './commands/status.js';\nimport { cmdLast } from './commands/last.js';\nimport { cmdStar } from './commands/star.js';\nimport { cmdExport } from './commands/export.js';\nimport { cmdImport } from './commands/import.js';\nimport { cmdAnalyze } from './commands/analyze.js';\nimport { cmdEmbedAll } from './commands/embed-all.js';\nimport { cmdLog } from './commands/log.js';\nimport { cmdConfig } from './commands/config.js';\nimport { cmdBackgroundAnalyze } from './commands/background-analyze.js';\nimport { cmdCleanup } from './commands/cleanup.js';\nimport { cmdVacuum } from './commands/vacuum.js';\nimport { cmdContext } from './commands/context.js';\nimport { cmdClose } from './commands/close.js';\nimport { cmdSessions } from './commands/sessions.js';\nimport { cmdStats } from './commands/stats.js';\nimport { cmdCluster } from './commands/cluster.js';\nimport { cmdAnalyzeReusability } from './commands/analyze-reusability.js';\nimport { cmdCleanupReusability } from './commands/cleanup-reusability.js';\nimport { cmdTimeline } from './commands/timeline.js';\nimport { cmdMemoryMigrate } from './commands/memory-migrate.js';\nimport { cmdWrap } from './commands/wrap.js';\nimport { cmdChat } from './commands/chat.js';\nimport { detectCaptureTools, setupCapture } from './commands/setup.js';\nimport { cmdModels } from './commands/models.js';\nimport { parseFlags } from './commands/_utils.js';\n\nconst ADVANCED_USAGE = `ph — local history and project context for AI CLI tools\n\nUSAGE:\n ph Print the short everyday-use guide\n ph setup [tool...] Connect supported AI CLIs for automatic capture\n ph <tool> [tool-args...] Wrap a CLI tool, save prompt to history\n ph search [options] [query] Search this project (5 matches; --all searches everything)\n ph show <id> [--json] [--archive] Inspect one complete interaction and its analysis\n ph context [options] [query] Get RAG context for the current project\n ph prepare \"<task>\" [options] Alias for task-aware ph context\n ph close [--since 3h] [options] Review work and propose knowledge to save\n ph chat <tool> <prompt...> Run tool with project context injected\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 status Show recent capture and background-work status\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] [--archive] Export one complete interaction\n ph import <source> [--dry-run] [--analyze] [--filter] [--file <path>] [--workdir <path>]\n Import from Gemini, Claude, OpenCode, or Codex history\n ph analyze [--limit n] [--force] [--prune] [--dry-run] Analyze prompts with LLM\n ph models [openrouter|mlx-serve] List models from an AI provider\n ph mcp Start MCP server (Stdio)\n ph server [--port 3001] Start HTTP REST server for remote sync\n ph timeline [project] Show full project history with prompts and memories\n ph memory-migrate Merge existing memories into project_summaries\n ph remote push|pull|status Sync prompts with remote ph server\n ph cleanup [--dry-run] [--min-length N] [--min-score N] Remove useless prompts\n ph cleanup --retention [--dry-run] Archive prompts per retention policy\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 show Show active AI provider configuration\n ph config get <key> Read config value (secrets are redacted)\n ph config set <key> [value] Save config value (secret keys prompt hidden)\n ph browse Print the latest interactions\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 --tool <name> Filter by tool name (claude, gemini, opencode, codex, …)\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 --archive Search archived prompts\n --since YYYY-MM-DD\n --until YYYY-MM-DD\n --limit <n> Max results (default 5)\n --full Show full prompt and response without truncation\n\nCONTEXT OPTIONS:\n --project <name> Project to get context for (default: auto-detect)\n --limit <n> Max results (default 5)\n --prompts-only Show only prompt-based context, skip project knowledge\n --memories-only Show only project knowledge, skip prompts\n --verbose Include full prompt text in output\n\nPREPARE OPTIONS:\n --project <name> Project to retrieve context for (default: auto-detect)\n --limit <n> Max results (default 5, max 20)\n --budget <chars> Maximum brief content target (default 3500)\n\nCLOSE OPTIONS:\n --since <duration> Select recent prompts (e.g. 30m, 3h, 1d)\n --from <id> --to <id> Select an inclusive prompt ID range\n --project <name> Project to review (default: auto-detect)\n --dry-run Show selected prompts without calling an LLM\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 --export <n> Export session N as markdown\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 show 42\n ph search --tool claude --role debug --since 2026-01-01 \"error handling\"\n ph search --semantic \"how to handle errors gracefully\"\n ph context \"add Wise provider\" --limit 5\n ph show 42 --json\n ph close --since 3h\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 context\n ph context \"how to add a new database table\"\n ph context --memories-only --project ph\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 ph models openrouter Discover OpenRouter models\n ph models mlx-serve Discover models on MLX-Serve (default Parmenide tunnel)\n`;\n\nconst USAGE = `PH remembers work across your AI coding sessions.\n\nOne-time setup:\n ph setup Connect PH to installed supported AI CLIs\n\nThen use those tools normally. PH saves completed exchanges in the background.\n\nWhen you need something back:\n ph search \"query\" Search this project; use --all to search everything\n ph show <id> Inspect the full prompt, response, and available analysis\n ph context \"task\" Retrieve relevant project context when needed\n\nRun ph help --all for optional integrations and maintenance commands.\n`;\n\nfunction setupStatusLabel(status: 'installed' | 'updated' | 'already-configured'): string {\n switch (status) {\n case 'installed': return 'Installed capture for';\n case 'updated': return 'Updated capture for';\n case 'already-configured': return 'Already configured for';\n }\n}\n\n\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 process.stdout.write(USAGE);\n process.exit(0);\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(argv.includes('--all') ? ADVANCED_USAGE : 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 'setup': {\n if (cmdArgs.includes('--help') || cmdArgs.includes('-h')) {\n process.stdout.write('Usage: ph setup [claude|codex|gemini|opencode...]\\nWithout tool names, PH detects installed supported CLIs.\\n');\n break;\n }\n const selectedTools = cmdArgs.filter(arg => !arg.startsWith('-'));\n const tools = selectedTools.length ? selectedTools : detectCaptureTools();\n const results = setupCapture(process.env.HOME, undefined, tools);\n if (results.length === 0) {\n process.stdout.write('No supported AI CLI detected. Install one or select it explicitly: claude, codex, gemini, opencode.\\n');\n break;\n }\n for (const status of ['installed', 'updated', 'already-configured'] as const) {\n const names = results.filter(result => result.status === status).map(result => result.tool);\n if (names.length) process.stdout.write(`${setupStatusLabel(status)}: ${names.join(', ')}.\\n`);\n }\n const restart = results.filter(result => result.status === 'installed' || result.status === 'updated').map(result => result.tool);\n process.stdout.write(restart.length\n ? `Restart ${restart.join(' and ')} to load the capture hook.\\n`\n : 'No changes needed.\\n');\n break;\n }\n case 'search': {\n const db = new PhDB(dbPath);\n await cmdSearch(db, cfg, cmdArgs);\n db.close();\n break;\n }\n case 'show': {\n const db = new PhDB(dbPath);\n await cmdShow(db, cmdArgs);\n db.close();\n break;\n }\n case 'status': {\n const db = new PhDB(dbPath);\n await cmdStatus(db, cfg);\n db.close();\n break;\n }\n case 'context': {\n const db = new PhDB(dbPath);\n await cmdContext(db, cfg, cmdArgs);\n db.close();\n break;\n }\n case 'prepare': {\n const db = new PhDB(dbPath);\n await cmdContext(db, cfg, cmdArgs);\n db.close();\n break;\n }\n case 'close': {\n const db = new PhDB(dbPath);\n await cmdClose(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, cfg, 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 'models': {\n await cmdModels(cfg, cmdArgs);\n break;\n }\n case 'memory-migrate': {\n const db = new PhDB(dbPath);\n cmdMemoryMigrate(db);\n db.close();\n break;\n }\n case 'mcp': {\n await runMCPServer();\n break;\n }\n case 'server': {\n const { flags } = parseFlags(cmdArgs);\n const port = Number(flags['port']) || 3001;\n const host = (flags['host'] as string) || '127.0.0.1';\n await runServer(port, host);\n break;\n }\n case 'remote': {\n await cmdRemote(dbPath, cmdArgs);\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 'vacuum': {\n const db = new PhDB(dbPath);\n await cmdVacuum(db);\n db.close();\n break;\n }\n case 'config':\n await 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.stderr.write('ph browse is now a text-based history listing; use ph search to find specific work.\\n');\n await cmdLast(db, []);\n db.close();\n break;\n }\n\n case 'chat': {\n await cmdChat(dbPath, cfg, cmdArgs);\n break;\n }\n\n case 'timeline': {\n const db = new PhDB(dbPath);\n await cmdTimeline(db, cfg, cmdArgs);\n db.close();\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(cmdArgs.includes('--all') ? ADVANCED_USAGE : 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"],"mappings":"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","names":["path","os","path","os","status","z","z","z","URL","createHash","createHash","URL","path","status","fs","path","path","os","fs","path","os","os","os","fs","path","os","fs","path","os","fs","path","os","fs","path","os","Database","MAX_RESPONSE_LENGTH","TRUNCATION_SUFFIX","truncateResponse","path","fs","Database","os","getTextContent","fs","path","os","createHash","fs","path","os","url","response","data","os","path","remoteUrl","status","cfg","rawKey","key","deleted","context","formatTimestamp","parseMeta","C","C","C","fs","C","fs","fs","C","fs","path","os","spawn","execFileSync","fs","execFileSync","fs","spawn","fs","path","os","fs","path","source","status","status"]}
|