221 Commits
Author SHA1 Message Date
digua 98a92c73f1 docs(cli): add agent query usage guide 2026-07-04 15:12:50 +08:00
digua c4f5e06e5e feat(cli): add agent-facing query commands 2026-07-04 15:12:50 +08:00
digua b346b51eee refactor(sync): share automation routes across runtimes 2026-07-02 10:35:02 +08:00
digua 70ada5031c fix(ai): share AI log opening route 2026-07-02 10:35:02 +08:00
digua 57d6450430 release: v0.29.0 2026-07-01 01:27:49 +08:00
digua d3d2661882 fix(relationships): address galaxy review regressions
Bundle relationship worker entries for packaged builds.

Refresh and surface galaxy task failures, clean detached Pixi layers, cap focused neighborhoods, merge owner nodes across platforms, apply manual friend overrides, and track owner group activity.
2026-06-30 14:41:46 +08:00
digua 9563c26645 refactor(contacts): group contacts service files 2026-06-27 15:54:08 +08:00
digua c8c4e1aca6 feat(contacts): compute contacts in background worker 2026-06-27 15:54:08 +08:00
digua f74aae1bb4 release: v0.28.1 2026-06-26 10:07:20 +08:00
diguaandClaude Sonnet 4.6 1209e2ce4b refactor(import): migrate CLI sync/pull path to shared streaming importer
Removes the legacy apps/cli/src/import/importer.ts (hand-rolled FTS, dedup,
session-ID generation) and apps/cli/src/import/chatlab-reader.ts (buffered
in-memory JSON/JSONL parser). DirectImporter in sync/adapters.ts now calls
streamImport / incrementalImport from stream-import.ts, which use the
@openchatlab/parser streaming pipeline and node-runtime shared logic.

Changes:
- Add sessionId? to StreamImportOptions so callers can fix the target session
  ID instead of auto-generating one (needed by pull engine full-import path)
- Rewrite DirectImporter.incrementalImportFile and fullImportFile to use
  the shared importers; map IncrementalImportResult fields to ImportResult
- Remove legacy exports from apps/cli/src/import/index.ts
- Rewrite importer.test.ts to use streamImport + a temp ChatLab JSON file
  (same two data-dir compatibility gate assertions as before)
- Delete importer.ts and chatlab-reader.ts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 21:45:16 +08:00
diguaandClaude Sonnet 4.6 ced4ed16bd feat(import): auto-generate session index after all import paths
Session index (segment/message_context tables) was previously generated
inconsistently: CLI used postImportHook, Desktop relied on a separate
explicit RPC call, and the CLI sync/pull legacy importer never built it.

Move generateSessionIndex / generateIncrementalSessionIndex into the
shared importers (streaming-importer.ts, incremental-importer.ts) so
every caller gets it automatically. Remove the now-redundant calls from
CLI's postImportHook. Also add the calls to the legacy importer.ts used
by CLI sync/pull, which had no session index at all.

Incremental imports use generateIncrementalSessionIndex, which preserves
existing AI summaries. Full imports call generateSessionIndex only on
newly created sessions where no summaries exist.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 21:45:16 +08:00
digua a2158cccc4 release: v0.28.0 2026-06-25 00:12:53 +08:00
diguaandClaude Sonnet 4.6 aff59c7503 feat(import): wire Google Chat archive sources into CLI, Electron and frontend
Add archive reader, Google Chat resolver and source manager in node-runtime.
Expose prepared archive sources via CLI HTTP route and Electron IPC.
Add frontend service adapters and an import selection flow with i18n support
for all four locales. Fix rescanning on repeated archive imports.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 18:10:30 +08:00
diguaandClaude Sonnet 4.6 2dbe569f2a fix(logging): fix four review issues in unified logger
- Front-end error reporter was posting to /_web/_web/logs/report (double
  base URL prefix); fixed to /logs/report
- uncaughtException/unhandledRejection handlers in CLI and Electron did not
  exit after logging, overriding Node's default crash behavior; added
  process.exit(1)
- NodePathProvider constructor in run() and chatlab status triggered
  migrateFromElectronIfNeeded() as a side effect; added getSystemLogsDir()
  to get the system logs path without resolving user data
- formatData() was called outside write()'s try/catch, so errors with
  circular cause objects could escape appLogger.error(); moved inside

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 15:28:09 +08:00
diguaandClaude Opus 4.8 7c21d1c879 feat(logging): add unified app logger with file rotation and global error capture
Build a shared appLogger (node-runtime) that all three runtimes write to a
single rolling logs/app.log (10 MB → rename to app.old.log). Replaces the
four independent hand-written loggers (app.log/api.log Electron wrappers)
with a unified entry point while leaving AiLogger/perf-logger intact.

Key additions:
- packages/node-runtime/src/logging/app-logger.ts: initAppLogger/appLogger
  singleton, INFO threshold by default (CHATLAB_LOG_LEVEL to override),
  atomic rename rotation, Error data auto-extracts message+stack
- Three-runtime init: Electron main, CLI Web (http/index.ts), CLI (run())
- Global crash capture: uncaughtException + unhandledRejection on all three
  Node runtimes now land in app.log scope 'crash'
- Fastify setErrorHandler fallback logs scope 'http' on CLI Web and Electron
  internal server for unexpected 5xx errors
- Frontend: window.onerror + unhandledrejection + Vue errorHandler feed into
  POST /_web/logs/report (scope 'web') with dedup+throttle
- AGENTS.md: logging rules section requiring key-path logs on new/changed features

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 15:28:09 +08:00
digua 46fb1cd4ca release: v0.27.2 2026-06-24 00:02:01 +08:00
digua 43e6ffdb81 fix(cli): include analytics key in release build 2026-06-23 22:58:22 +08:00
diguaandClaude Sonnet 4.6 c8cccbefd4 feat(analytics): track CLI web daily active users via shared AnalyticsService
- Extract shared AnalyticsService to packages/node-runtime using direct
  Aptabase HTTP API (removes @aptabase/electron dependency)
- Add POST /_web/telemetry/track route for generic event reporting
- Desktop: migrate analytics.json from userData to systemDir (~/.chatlab/),
  trigger daily active from renderer via new IPC so user-selected locale is used
- CLI: inject APTABASE_APP_KEY at build time, create AnalyticsService on
  server start, report app_active with platform: cli-web
- Both platforms report user-selected locale via platform service abstraction

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 22:58:22 +08:00
diguaandClaude Sonnet 4.6 04680fc840 fix(ai): delete auth profile when removing a model service config
When deleteConfig was called, the auth profile written to
auth-profiles.json during addConfig was never cleaned up, leaving
orphaned credentials on disk indefinitely.

Add onApiKeyDeleted callback to LLMConfigStoreDeps and call it in
deleteConfig with the removed config so callers can clean up the
corresponding auth profile. Wire up deleteAuthProfile in both the
CLI HTTP server and the Desktop internal API.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 22:58:22 +08:00
digua 5bb01966fa release: v0.27.1 2026-06-23 14:39:53 +08:00
digua 434334b203 feat(semantic-index): run local embeddings in lazy worker 2026-06-23 14:18:32 +08:00
diguaandClaude Sonnet 4.6 39393cf38d refactor: remove dead code and simplify over-engineered abstractions
- Delete NotificationBus interface (no implementations, no callers)
- Delete useAsyncData/useMultipleAsyncData composables (zero import sites)
- Inline CHART_CAPABILITY_SKILL_ID into tool-catalog.ts (was a single-constant file)
- Inline AsyncSqlExecutor into message-query-functions.ts (was a single-interface file)
- Rename tools TimeFilter → ToolTimeRange to eliminate name collision with shared-types
- Shrink useToast wrapper: two interfaces → one type, 40 lines → 17 lines
- Simplify deepMerge: remove recursion, config is at most 1 level deep

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 14:18:32 +08:00
digua 307b0380bd release: v0.27.0 2026-06-22 13:56:43 +08:00
diguaandClaude Sonnet 4.6 88dea48ec6 fix(cli): forward session context and apply preprocessing in tool adapter
agent-stream-runner: pass timeFilter and maxMessagesLimit from request
params into the tool context so evidence and retrieval tools respect the
active session time range in CLI Web sessions, matching the desktop runner.

tool-adapter: pass preprocessConfig, anonymizeNames and ownerPlatformId to
applyPreprocessingPipeline in the rawMessages branch so desensitization and
name anonymization apply to search_messages / recent_messages results,
matching the desktop adapter behavior.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 16:18:39 +08:00
diguaandCursor 6886eb3dc6 feat(ai): add retrieve_chat_evidence tool with evidence payload protocol
Introduce a high-level evidence retrieval tool for fact/occurrence/count
questions. It resolves auto mode, runs semantic + keyword paths, de-identifies
keyword snippets via an injected desensitizeMessages callback, applies a
tool-layer millisecond time-range fallback (keyword path can't rely on the CLI
provider's timeFilter), and merges/dedupes candidates into conservative groups.

- Add ChatEvidencePayload / group / source types and EvidenceTimeRangeMs to tools
- Register tool in AGENT_TOOL_REGISTRY only (Agent-only, excluded from MCP)
- Inject desensitizeMessages (preprocessMessages) in desktop + CLI adapters
- TDD: tool + registry unit tests

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-21 16:18:39 +08:00
diguaandCursor b9599da1c8 feat(semantic-index): expose semantic search via routes, agent tool and pipeline
Add shared /_web/ai/semantic-index HTTP routes and wire the service into
CLI web and Electron internal API. Introduce the semantic_search_current_chat
agent tool (AGENT-only, not MCP) with desensitized output and a narrowed
service interface, forward the semantic-search context through the CLI and
Desktop tool adapters, and integrate on-demand semantic search into the
agent pipeline with guidance and a max-result-token evidence budget.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-21 16:18:39 +08:00
diguaandCursor e3f38cfb8b refactor(ai): replace legacy RAG with semantic-index core infrastructure
Remove the deprecated always-on RAG system and introduce the new
semantic-index core: parent/child chunker with version/hash derivation,
embedding providers (local + OpenAI-compatible) and profiles, sqlite-vec
vector store, dense+FTS+RRF hybrid retrieval, evidence assembly, serial
warmup job queue and single-session runner, session business-state store,
and the SemanticIndexService that ties them together. Add an independent
config store and a dedicated vector directory via the path providers.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-21 16:18:39 +08:00
digua fd55e85d05 release: v0.26.3 2026-06-15 10:14:09 +08:00
diguaandClaude Sonnet 4.6 c80ee8b8ec fix(cli): sync cli package version with product version to stop false update notice
In CLI Web mode, the frontend displays __APP_VERSION__ injected from the
root package.json at build time (0.26.2), while the server-side getVersion()
reads apps/cli/package.json at runtime (stuck at 0.25.1). This caused
buildWebUpdateCheckResult to compare remote 0.26.2 against local 0.25.1,
permanently reporting a false update notice even when the user was already
on the latest version.

Fix apps/cli/package.json to 0.26.2 to align with the product version.

Also extend set_release_version.sh to keep apps/cli/package.json in sync
with the root package.json on every release, preventing the drift from
recurring. apps/desktop/package.json is intentionally kept at 0.0.0 (the
desktop runtime uses app.getVersion() with __APP_VERSION__ fallback).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 16:24:53 +08:00
diguaandCursor e6d67afdad fix(ai,cli): remove top capture button from AI chat and support arrow key selection in CLI update prompt
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 16:24:53 +08:00
diguaandClaude Sonnet 4.6 968cb39e87 fix(cli): invalidate preferences cache before applying owner profile on sync
The sync module creates its own PreferencesManager at server startup,
separate from the one shared by web routes. When the user configures their
identity through the web UI, the web routes' manager writes to disk and
updates its own cache, but the sync module's manager retains a stale cache
from startup. Subsequent pull imports then call tryApplyOwnerProfile with
the stale cache, returning no_profile and skipping owner assignment even
though a profile exists on disk.

Fix: invalidate the sync manager's cache before each onSessionImported
callback so the fresh profile is always read from disk.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 13:16:52 +08:00
diguaandClaude Fable 5 82ce9dcc2f feat(owner): auto-apply owner profile after pull sync and CLI import
PullEngine gains an onSessionImported hook (hook errors never fail the
pull), wired in both the CLI server and Electron main to silently fill
session owner from the stored platform profile. The chatlab import CLI
command does the same after a successful import.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 13:16:52 +08:00
digua 82a6be4fcb fix(sync): delete imported session files completely 2026-06-13 13:16:52 +08:00
diguaandCursor 39700b95b7 feat(ai): display cache hit/miss token usage in chat status bar
Extend TokenUsage types across the full data pipeline to include
cacheReadTokens and cacheWriteTokens. The ChatStatusBar tooltip now
shows cache hit information when available. This is a generic
implementation that works with any API provider reporting cache metrics,
not limited to DeepSeek.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-10 22:18:20 +08:00
diguaandClaude Fable 5 9c7778f7e3 fix(ai): keep rawMessages out of LLM-facing tool result text
Message-retrieval tools mirror rawMessages inside data, and the
preprocessing pipeline rendered that array into the tool result text as
"rawMessages: [object Object], [object Object], ..." — roughly 1.7KB of
junk per call (~400-500 wasted tokens) that also polluted the truncated
result text persisted for history replay.

- formatToolResultAsText skips the rawMessages key (raw message objects
  are already rendered via the formatted messages list)
- CLI tool adapter strips rawMessages from extraDetails before invoking
  the pipeline, matching the existing desktop adapter behavior

Regression tests fail without the fix at both the format layer and the
CLI adapter layer.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 22:18:20 +08:00
digua 1290ae6569 feat(ai): add chart auto mode preference 2026-06-10 00:15:25 +08:00
digua 718735a748 feat(ai): build extended data snapshots 2026-06-10 00:15:25 +08:00
digua 0801ccf940 feat(ai): stream structured analysis plans 2026-06-10 00:15:25 +08:00
digua 9ad012680d feat(ai): integrate chart planning support 2026-06-10 00:15:25 +08:00
digua 6f54dcc62b feat(cli): expose full agent stream events 2026-06-10 00:15:25 +08:00
digua b61974136e feat(ai): emit analysis plan guidance 2026-06-10 00:15:25 +08:00
digua 8ca3f0be8b feat(ai): add llm fallback for shadow routing 2026-06-10 00:15:25 +08:00
digua 712d5212c2 feat(ai): log shadow agent route decisions 2026-06-10 00:15:25 +08:00
diguaandClaude Sonnet 4.6 c3a5d22a43 fix: enforce data directory compatibility gate at runtime boundaries
MCP server checks the gate at startup and exits before opening stdio if
the data directory requires a newer runtime. Desktop HTTP API maps
DataDirCompatibilityError (including wrapped causes) to a 409 response
so the renderer can surface a clear upgrade prompt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 10:14:42 +08:00
diguaandClaude Sonnet 4.6 e7561e224e fix: write data directory compatibility gate on migration and import
Harden the startup migration path: fail fast and show an error dialog if
schema migration cannot complete. Repair the gate retroactively for
databases that were already migrated before the gate system existed.

Raise the gate after every import path (full import, incremental import,
stream import) and after opening any database that already carries a
current-segment schema. Centralise gate-raising inside DatabaseManager so
call sites cannot accidentally skip it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 10:14:42 +08:00
diguaandClaude Sonnet 4.6 1c7781d85b fix: establish runtime identity for data directory gates
Use the packaged app version (not Electron's dev-mode 0.0.0) across all
compatibility checks. Make DatabaseManager require a RuntimeIdentity so
every gate write carries a verified version and kind.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 10:14:42 +08:00
digua 6ae32e8b57 feat(http): report incompatible data directories 2026-06-08 10:14:42 +08:00
digua 84b42a68f7 feat(cli): block incompatible data directories at startup 2026-06-08 10:14:42 +08:00
diguaandClaude Sonnet 4.6 62ad3c6248 fix: normalize legacy tool names and harden cli chat command
- Add normalizeBuiltinToolNames() to map old session-based tool names
  (search_sessions, get_session_messages, get_session_summaries) to
  current segment names; applied in assistant parser, agent-stream-runner,
  and desktop tool-filter so existing assistant configs keep working
- Propagate agent stream error chunks as thrown Errors in CLI chat command
- Pass assistantId through ResolvedAIChatTarget to agent stream
- Preserve legacy chat_session rows in v6 migration when segment table
  already exists (INSERT OR IGNORE + DROP); revert v3/v5 DDL to chat_session
- Rename session_id alias to segment_id in relationship query
- Add tests: assistant-parser normalization, tool-filter legacy names,
  agent-stream-runner legacy allowlist, REPL error resilience, migration paths

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 20:27:27 +08:00
digua 9b17b09354 feat: add cli ai chat command 2026-06-07 20:27:27 +08:00