feat(sessions): indexação multi-fonte Hermes + OpenCode com fix TypeScript

- Novos indexadores hermes-indexer.ts e opencode-indexer.ts para unificar
  sessões Claude, Hermes Agent e OpenCode num único sessions.db
- SessionMeta alargado: source (obrigatório), model, input/output_tokens,
  estimated_cost; project_path/jsonl_path agora nullable
- Fix TS: tipos explícitos, guard jsonl_path null, dependências instaladas

Security Audit (Regra #47):
- npm audit executado — 0 vulnerabilities após fix
- vite 7→8.0.16 (breaking upgrade, resolve esbuild CVE GHSA-gv7w-rqvm-qjhr)
- vitest 4.0.18→4.1.9 (resolve esbuild interno CVE GHSA-gv7w-rqvm-qjhr)
- shell-quote override ^1.8.4 via package.json#overrides (CVE GHSA-w7jw-789q-3m8p)
- react-router, joi, qs, form-data, ip-address, js-yaml resolvidos via npm audit fix

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-15 19:41:32 +01:00
parent 9f3d14dc51
commit f733998945
18 changed files with 1475 additions and 678 deletions
+14 -6
View File
@@ -1,10 +1,11 @@
#!/usr/bin/env tsx
/**
* CLI do indexer de sessões Claude Code (Observabilidade/Espelho).
* CLI do indexer de sessões (Observabilidade/Espelho) — multi-agente.
*
* Modos:
* --full Full scan de ~/.claude/projects -> SQLite em ~/.claude-work/sessions.db
* --watch Modo incremental (stub; implementação Task 8)
* --full Full scan de todas as fontes
* --watch Modo incremental (Claude Code watcher)
* --source Filtrar fonte: claude, hermes, opencode (repetível)
*
* Env:
* OBSERVABILIDADE_DB Override ao caminho da BD SQLite
@@ -16,16 +17,22 @@ async function main(): Promise<void> {
const args = process.argv.slice(2)
const mode = args.find((a) => a === '--full' || a === '--watch')
if (!mode) {
console.error('Uso: sessions-indexer.ts [--full|--watch]')
console.error('Uso: sessions-indexer.ts [--full|--watch] [--source claude|hermes|opencode]')
process.exit(1)
}
const dbPath = process.env.OBSERVABILIDADE_DB ?? DEFAULT_DB_PATH
console.log(`[indexer] modo=${mode} db=${dbPath}`)
const sourceFlags = args.filter((a) => !a.startsWith('--'))
const sources: ('claude' | 'hermes' | 'opencode')[] = sourceFlags.length > 0
? sourceFlags.filter((s): s is 'claude' | 'hermes' | 'opencode' =>
['claude', 'hermes', 'opencode'].includes(s))
: ['claude', 'hermes', 'opencode']
console.log(`[indexer] modo=${mode} fontes=${sources.join(',')} db=${dbPath}`)
if (mode === '--watch') {
console.log(`[indexer] watch mode em ${PROJECTS_ROOT} -> ${dbPath}`)
await indexAll({ dbPath })
await indexAll({ dbPath, sources })
await startWatcher(dbPath)
return
}
@@ -34,6 +41,7 @@ async function main(): Promise<void> {
let lastLogged = 0
const { indexed, failed } = await indexAll({
dbPath,
sources,
onProgress: (done, total) => {
if (done - lastLogged >= 50 || done === total) {
console.log(`[indexer] ${done}/${total}`)