10 Commits
Author SHA1 Message Date
viettranx 9625a20e8b fix(vault): complete chat_id isolation coverage
- Extend migration 000056 with legacy-docs backfill (telegram/<chat>,
  ws/<chat>, delegate/<chat>, and agent/bot/<chat> path shapes) so
  scope=shared/personal docs created before team-scope refactor also
  get stamped with chat_id and stop leaking across chats
- rescan: inferOwnerFromPath now returns chat_id extracted from team
  path third segment; stamp onto VaultDocument so admin /vault/rescan
  preserves chat isolation
- HTTP vault search: accept optional chat_id body param, set
  TeamIsolated=true when TeamID + ChatID both present (admin UI can
  view vault from a specific chat perspective)

Applied to staging DB via MCP: 91 legacy rows backfilled.
2026-04-23 18:56:57 +07:00
viettranx 1ea24ef8e2 fix(vault): centralize enrich skip filter and fix stop cancel bug
Extract shouldSkipEnrichment() replacing 4 scattered goclaw_gen_ checks.
Filter also skips UUID, hex hash, digit-only, short, and known junk filenames.
Fix cancelFuncs never being populated — Stop() was a no-op leaving UI stuck.
2026-04-13 12:36:14 +07:00
viettranx 2c2e2cb536 fix(vault): skip goclaw_gen media in enrichment, improve graph UX
Backend:
- Skip goclaw_gen_* files in Handle, EnqueueUnenriched, gatherCandidates
- Skip in RescanWorkspace PendingEvents (progress count)
- Reduces noisy auto-links by ~59%

Frontend:
- Theme-aware node colors (Tailwind -600/-400 matching sidebar)
- Neutral gray edges (zinc-500/300), lighter inactive edges
- Disable hover label white box (defaultDrawNodeHover)
- Auto-expand + load first-level folders
- Group hover text colors for tree items
- Edge density based on camera zoom
2026-04-12 18:56:27 +07:00
viettranx 50821b6207 fix(vault): re-enqueue unenriched docs on rescan when all files unchanged
When rescan finds no new/updated files but some docs still lack summaries
(e.g. previous enrichment failed due to provider timeout), automatically
re-enqueue them for enrichment retry.

- Add VaultStore.ListUnenrichedDocs() to fetch docs with empty summary
- Add EnrichWorker.EnqueueUnenriched() to emit events for retry
- Add RescanResult.Reenqueued field to track re-enqueued count
- Update UI to show "X re-queued for enrichment" toast
2026-04-12 18:06:51 +07:00
viettranx 28d29ba046 fix(vault): enrichment pipeline reliability + cross-agent classify
9 fixes for vault enrichment pipeline:

1. Queue key = tenant-only (was per-agent, caused multiple batches
   blocking EventBus workers and progress bar flashing)
2. Classify chunks 5 candidates per LLM call (prevents response
   truncation that caused parse_still_failed errors)
3. Classify prompt improved: explicit "EXACTLY one entry per
   candidate", 5-entry example, ctx capped at 30 words
4. max_tokens kept at 1024 (sufficient for 5 candidates)
5. Progress AddDone removes !running guard (safe before Start)
6. Rescan defers event publishing via PendingEvents — Start()
   called before workers receive events, eliminating race
7. Upload handler same deferred publish pattern
8. Frontend enrichment timer cancels stale "complete" timeout
   when new enrichment starts (prevents bar disappearing)
9. Sidebar tree reloads after rescan completes

Classify now searches across entire tenant (empty agentID) to
build cross-agent links for future vault sharing. Access control
enforced at query time — agents only see their own docs.
2026-04-12 14:31:36 +07:00
viettranx 7810b8b78a fix(vault): agent filter support + rescan agent_key path matching
- Add AgentID to VaultTreeOptions, pass agent_id filter through
  backend tree endpoint and frontend hook
- Fix rescan inferOwnerFromPath: match root-level {agent_key}/...
  folders against agentMap (workspace uses agent_key directly,
  not agents/ prefix). Keep legacy agents/ prefix for compat
- Preserve full relPath for DB storage in all patterns
- Show filename with extension in tree (use path basename, not title)
- Start tree folders collapsed (prevent stuck loading state)
- Remove orphaned useVaultGraphData call from vault-page
- Tenant isolation verified: agentMap built per-tenant via scopeClause
2026-04-12 13:25:15 +07:00
viettranx 5623f97961 feat(vault): extension whitelist + document docType + media summary
- Add extension_whitelist.go to deterministically skip binary .bin/.exe/.dll
- Add media_summary.go: synthesize docType + generate short summary from vault fields
- Update rescan.go: detect document type for PDF/office files + propagate docType
- Update safe_walk.go test: .bin now filtered by whitelist, use .txt instead
- Update rescan_test.go: add document docType coverage
- Add link_types.go: define AUTO_LINK_TASK, AUTO_LINK_DELEGATION link types
2026-04-11 21:22:23 +07:00
viettranx 57957ba6b1 fix(vault): rescan path resolution, batch enrichment pipeline, cross-agent create
- Fix rescan storing stripped paths (teams/{uuid}/... → file.md) causing
  enrichment worker to fail locating files on disk. Now stores full
  workspace-relative path with backward-compat fallback for old records.
- Refactor enrichment into chunked pipeline: batch 5 files per LLM call
  (was 1:1), 3 parallel goroutines via semaphore — reduces LLM calls ~80%.
- Extract shared chatWithRetry for summarize + classify (3 retries,
  escalating timeouts 5m→7m→10m).
- Add POST /v1/vault/documents route for cross-agent doc creation
  (agentID optional, defaults scope to shared when no agent).
- Add path traversal validation (reject .. and leading /) on create.
- Skip media files in syncWikilinks to prevent binary garbage parsing.
- Bound syncWikilinks file read to 4MB.
2026-04-10 17:28:16 +07:00
viettranx 9f77bfe711 feat(vault): tenant-wide rescan with nullable agent_id + media preview
Vault rescan redesigned from per-agent to tenant-wide:
- POST /v1/vault/rescan replaces POST /v1/agents/{id}/vault/rescan
- agent_id nullable in vault_documents (PG migration 046 + SQLite v14)
- Path-based scope inference: agents/{key}/ → personal, teams/{uuid}/ → team, root → shared
- Interceptor sets agent_id=NULL for team-scoped file writes
- Enrichment worker batch key handles empty agent_id
- web-fetch/ directory excluded from vault scan at any depth
- Media preview: images render via authenticated blob URL, binary files show metadata
- Scan button no longer requires agent selection
2026-04-10 16:32:54 +07:00
viettranx dabb1eaa11 feat(vault): workspace rescan endpoint with symlink-safe walker
Add POST /v1/agents/{agentID}/vault/rescan to backfill vault_documents
from filesystem. Walks agent workspace, registers missing/changed files,
publishes enrichment events for async summarize + embed + link classify.

Backend:
- SafeWalkWorkspace: symlink-safe walker with exclusion patterns,
  resource limits (5K files, 500MB, 50MB/file), context deadline
- RescanWorkspace: hash-based dedup, path-based scope detection
  (teams/{id}/ → team scope), idempotent via UpsertDocument ON CONFLICT
- Per-agent mutex (409 Conflict for concurrent rescans)
- Tenant-scoped workspace resolution (config.TenantWorkspace)
- Enrichment worker: semaphore-based parallel summarize (max 3 concurrent)
- Media files without summary skip LLM summarize, embed title+path only
- DRY: export InferTitle/InferDocType from vault pkg, remove from interceptor
- Auto-register text uploads in vault via onTextUploaded callback

Frontend:
- Rescan button in vault page header (FolderSync icon)
- Toast with result counts, 409 warning, error handling
- i18n strings for en/vi/zh

Security: skip all symlinks, boundary checks, per-file size limit,
tenant isolation via server-side workspace resolution.
2026-04-10 13:28:44 +07:00