Commit Graph
1014 Commits
Author SHA1 Message Date
digua 2ec99e5880 feat(ai): streamline agent tool results 2026-06-21 16:18:39 +08:00
digua 5d20429af7 fix(tools): support multi-keyword message search 2026-06-21 16:18:39 +08:00
diguaandCursor 25df662579 fix(ai): route enumeration/topic questions to semantic search
For "what X did we discuss / which ones / what did we talk about" style
enumeration and topic-discovery questions, the model was brute-forcing
search_messages across many keyword-guess rounds instead of using vector
search. Strengthen the semantic-search guidance to send these questions to
semantic_search_current_chat and explicitly discourage multi-round keyword
guessing; restrict search_messages to known exact word/quote/sender/time.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-21 16:18:39 +08:00
diguaandCursor d58168a029 fix(ai): correct evidence snippet time unit and strip per-message times
Evidence messages carry millisecond timestamps but the preprocessing pipeline
renders times assuming seconds (multiplies by 1000), producing absurd years
(e.g. 56150) inside semantic snippets. Convert ms back to seconds before
rendering. Also strip the per-line time prefix from semantic snippets so the
evidence block shows a single group time instead of a time on every message,
and drop the redundant time span in the group header. Adds regression tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-21 16:18:39 +08:00
diguaandCursor a23bb1b937 feat(ai): simplify evidence source rows
Drop the per-source timestamp line and show a single overall time per group
(falling back to the source min/max when no group range is set). Each source
now renders as a compact sender + snippet line, reducing visual clutter.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-21 16:18:39 +08:00
diguaandCursor 62d55d12d6 feat(ai): make evidence block collapsible to reduce footprint
The evidence block is now collapsed by default, showing only a compact header
with per-status group counts and the retrieval mode. Expanding reveals query,
criteria, warnings, grouped sources and a total-sources footnote. Tightens
spacing throughout.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-21 16:18:39 +08:00
diguaandCursor 402b78b683 feat(ai): render evidence content block with click-through tracing
Add a structured "evidence" content block produced by retrieve_chat_evidence:
extract the payload from tool results, persist it in AI chat history, and
render grouped, desensitized sources in EvidenceBlock.vue. Sources open the
chat record drawer at the matched message for traceability. Evidence payload
types move to @openchatlab/core so tools, node-runtime and the frontend share
one definition. Includes zh-CN/en-US/ja-JP/zh-TW i18n.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-21 16:18:39 +08:00
diguaandCursor b248e48787 feat(ai): route evidence questions to retrieve_chat_evidence via planner
Add an "evidence" planner intent and tiered retrieval guidance so
fact/occurrence/count questions are routed to retrieve_chat_evidence
instead of a single low-level search path.

- planner: new evidence intent + prompt strategy suggesting only
  retrieve_chat_evidence for that step
- semantic-search guidance: three-tier tool selection (evidence > semantic > keyword)
- expose retrieve_chat_evidence as an always-on Agent tool (desktop special
  append; CLI via AGENT_TOOL_REGISTRY core), semantic tool stays dynamic
- export evidence tool + payload types from @openchatlab/tools
- TDD: planner evidence-intent test

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-21 16:18:39 +08:00
diguaandCursor 27a5bbf9bf feat(ai): apply millisecond time-range filter to semantic retrieval
Thread an optional timeFilter through SemanticSearchToolOptions →
searchForTool → search → hybridSearch so evidence retrieval no longer
mixes time ranges between semantic and keyword paths.

- hybridSearch filters dense + FTS-mapped chunks by startTs/endTs overlap
  (millisecond, single-sided supported) and amplifies the candidate pool
  when filtering to avoid under-recall
- retrieve_chat_evidence now passes its parsed ms range to the semantic path
- TDD: hybrid-search overlap unit tests + service wiring test

Co-authored-by: Cursor <cursoragent@cursor.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 509f7b4262 fix(database): add missing i18n for v8 migration
Add the missing translations for the v8 database migration across the
desktop locales and cover them with a regression assertion.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-21 16:18:39 +08:00
diguaandCursor d0f6972202 feat(semantic-index): add index management UI, conversation picker and i18n
Add the frontend semantic-index service layer and the index management UI:
a settings section for vector model selection and index lifecycle with live
build-progress polling, a conversation picker plus current-conversation
entry, a session-scoped modal, and the tool-block summary rendering in the
chat message flow. Include the en/ja/zh-CN/zh-TW translations.

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
diguaandCursor fede744758 chore(deps): add sqlite-vec and transformers for semantic index P0
为语义索引 Phase 1 的 P0 前置验证引入 sqlite-vec(vec0 向量存储)
和 @huggingface/transformers(本地 ONNX embedding 推理)依赖。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-21 16:18:39 +08:00
diguaandClaude Sonnet 4.6 0ba08bd8de fix(electron): address post-review issues from #229
- capture worker reference in sendToWorkerWithProgress to match
  sendToWorker and avoid stale-closure risk on worker restart
- replace `as any` casts with typed SupportedLocale / BatchSegmentOptions
  assertions in debug-executor
- destructure params.params as toolParams to remove unused testId binding

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-17 09:43:13 +08:00
LeoandLeo 28fedbd815 fix(ai): recover from analysis tool timeouts (#229)
Co-authored-by: Leo <jxy0811@users.noreply.github.com>
2026-06-16 11:30:02 +08:00
diguaandClaude Sonnet 4.6 2dba862c49 fix(wordcloud): fix UX regressions for word cloud dictionary loading (#228)
Switching to a different session left allWords/topicMiniWords/stats
populated with the previous session's data. With the earlier fix that
skips isLoading when allWords is non-empty, users could see and interact
with stale words until the new request resolved.

Extend the sessionId watcher to also clear all word cloud state so the
loading indicator triggers correctly for cross-session navigation while
still keeping old data visible for same-session filter refinements.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 23:11:06 +08:00
LeoandClaude a89d6f7429 fix(wordcloud): allow word cloud analysis without external dictionary (#221)
Co-authored-by: Claude <noreply@anthropic.com>
2026-06-15 22:52:27 +08:00
diguaandClaude Sonnet 4.6 4d03d6cf54 docs: rewrite quick-start, intro, and index pages
- quick-start: simplify download links, add clb alias tip, improve copy
- intro: expand with features, supported platforms table, and next steps
- index: optimize title and descriptions for GEO/SEO

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 19:57:43 +08:00
diguaandClaude Sonnet 4.6 7abb7bd782 docs: add acknowledgments pages and EN protocol translations
- Add CN/EN acknowledgments pages with Leo Oliveira story
- Add English translations of Push and Pull protocol docs
- Register acknowledgments in sidebar as top-level entry

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 19:51:08 +08:00
diguaandClaude Sonnet 4.6 0bdc198303 docs: update READMEs and contributing guidelines
- Mark iMessage as supported, remove WeChat from EN README
- Update dev setup to reflect interactive target selector
- Add docs site links to docs/README.md
- Remove single-PR rule, highlight feature discussion requirement

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 19:43:52 +08:00
diguaandClaude Sonnet 4.6 5d40db0fc3 chore: remove dev:app script and frontend-only dev selector
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 19:31:14 +08:00
diguaandClaude Sonnet 4.6 816c1eb573 refactor(charts): consolidate truncateRankName across all ranking charts
Replace per-component truncateName copies with the shared truncateRankName
from rankingChartLayout, and fix its ellipsis character to '…' (U+2026).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 19:22:37 +08:00
LeoandAgent Memory OS 674fc2af2a fix(charts): improve ranking labels and emoji cleanup (#225)
Co-authored-by: Agent Memory OS <jxy0811@users.noreply.github.com>
2026-06-15 10:42:01 +08:00
digua fd55e85d05 release: v0.26.3 v0.26.3 2026-06-15 10:14:09 +08:00
LeoandAgent Memory OS 208a125c48 fix(analysis): filter reply placeholders from catchphrases (#223)
Co-authored-by: Agent Memory OS <jxy0811@users.noreply.github.com>
2026-06-15 10:02:26 +08:00
Agent Memory OS ec2bb3d54b fix(wordcloud): filter media placeholders from text 2026-06-14 23:59:54 +08:00
diguaandClaude Sonnet 4.6 72f911a1cb fix(analytics): invalidate language-preference cache when Jieba dict changes
The language-preference endpoint calls createJiebaNlpProvider() which
uses the on-disk zh-CN dict. If the result was cached before the dict
was downloaded, the built-in fallback tokenization was served even after
the dict became available, until a DB write invalidated the cache.

Include the zh-CN dict file mtime/size as extraVersion in the cache
version so the entry is recomputed whenever the dict is added, replaced,
or deleted — consistent with the word-frequency fix.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 23:54:12 +08:00
diguaandClaude Sonnet 4.6 da2c48c801 fix(nlp): invalidate word-frequency cache when Jieba dict changes
When no dict was downloaded, word-frequency results were computed with
the built-in tokenizer and cached. Downloading a dict cleared the in-
memory Jieba instance but left the cached result unchanged, so subsequent
requests returned the lower-quality built-in tokenization until the chat
DB was modified.

Add an extraVersion option to withAnalyticsCache and pass the dict file's
mtime/size as extraVersion for word-frequency requests so the cache is
invalidated whenever the dict file is added, replaced, or deleted.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 23:54:12 +08:00
diguaandClaude Sonnet 4.6 8a1ed8005c fix(analytics): invalidate time-sensitive cache entries daily
getDivingAnalysis and getNightOwlAnalysis derive values from the current
date (daysSinceLastMessage, currentStreak) that change even when the DB
file is untouched. Without a date component in the cache version, stale
results were returned until the next import or DB write.

Add a dailyInvalidate option to withAnalyticsCache that appends today's
date to the version string, and enable it for the diving and night-owl
endpoints.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 23:54:12 +08:00
digua 77c5718b44 docs: update frontend architecture paths 2026-06-14 23:54:12 +08:00
diguaandCursor cc4e67bd24 refactor(data): remove pluginCompute plugin-compute path
图表已统一走缓存端点,pluginCompute 不再被任何调用方使用,移除其全链路实现。
pluginQuery 保留供消息浏览/搜索/分页与 session-index 等通用 SQL 访问。

- 删除 ElectronDataAdapter(已无覆写),electron registry 直接使用 FetchDataAdapter
- 移除 IPC handler、preload API/类型、worker dispatch 与 workerManager 导出中的 pluginCompute

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 23:54:12 +08:00
diguaandCursor 93608fa5eb refactor(analysis): migrate chart views to components/analysis on cached data layer
把 src/features 下的图表视图全部迁到 src/components/analysis(message/ranking/relationships),
数据访问统一改为 useDataService().getXxx() 走缓存端点,删除前端 pluginQuery/pluginCompute
图表查询与重复的分析类型定义,最终清空并移除 src/features。

- 视图迁移:message/ranking(含 sections、charts)/relationships(cluster、interaction)
- 数据层:fetch.ts/types.ts 新增 adapter 方法并移除 pluginCompute;类型统一到 @openchatlab/core
- 调用方更新:group/private ViewTab、GroupRelationships、HotRepeatTab import 与查询

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 23:54:12 +08:00
diguaandCursor 99ed14f8a5 refactor(analysis): add cached analytics endpoints for message & ranking charts
将 charts-message 的文字统计/长消息/月度趋势/文本长度百分位,以及 charts-ranking
的龙王/潜水/打卡/斗图/夜猫/复读六项分析从前端 pluginQuery+pluginCompute 移植到
@openchatlab/core,并通过 analytics 缓存路由暴露,消除前端拉全量数据再计算的开销。

- core: 新增 basic-queries 文本统计函数与 advanced/ranking.ts 六项分析及类型,含单测
- http-routes: 新增对应缓存路由,long-message-count 的 minLength 进缓存 key

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 23:54:12 +08:00
diguaandCursor 8192a43a41 refactor(electron): unify worker analytics cache onto file-version invalidation
The desktop worker kept a second analytics result cache in the same
cacheDir/query directory but invalidated it with a fragile scheme:
app-version .cache_version file, a dev-startup wipe, and explicit
invalidateAnalysisCache() calls after import. Replace it with the shared
getOrComputeAnalysisCache, fingerprinting entries by product version plus
the session DB file state, so the worker (still used by AI tools and the
desktop public REST API) and the shared HTTP routes share one cache and
one invalidation model. Fold the product version into the HTTP-route
fingerprint too, preserving the cross-release invalidation that
.cache_version used to provide, and drop the now-dead invalidation code.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 23:54:12 +08:00
diguaandCursor e87b359d23 perf(analysis): cache analytics results on disk keyed by db file version
Repeatedly switching time filters recomputed expensive analytics/NLP
queries from scratch (e.g. a 1-year word cloud took 10s+ after a detour
through 5-year), because cancelling the network request cannot stop the
synchronous server-side computation. Add a shared, platform-agnostic
disk cache under cacheDir/query, validated by a fingerprint derived from
the session DB file (mtime+size of the main file and its -wal sidecar) so
any import, incremental import or member edit transparently invalidates
it. Wire it through the shared HTTP routes (word-frequency plus all
analytics endpoints), so CLI Web and the desktop internal server share
one implementation.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 23:54:12 +08:00
diguaandCursor 22df3bc6fe perf(analysis): cancel stale analytics requests on filter/session change
Switching the time filter or active session while analytics requests are
in flight left obsolete requests pending, exhausting the browser's
per-origin connection budget and letting stale responses overwrite fresh
data. Introduce an AbortController-backed analytics request epoch
(analyticsGet/analyticsPost) that is reset whenever the filter or session
changes, silencing AbortError so cancelled requests never settle the UI.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 23:54:12 +08:00
diguaandCursor 3bcdd3a2d4 perf(nlp): avoid re-segmentation when switching wordcloud word count
Switching the word count (80/100/150/200/300) in Insights > Topics >
Wordcloud re-ran a full-corpus jieba segmentation on the Electron main
thread, since topN only affects the final slice while the segmentation
cost is independent of it. This blocked the main process and froze the UI.

- Frontend: fetch the full word list once (max tier) and slice locally on
  word-count change, recomputing percentages over the displayed subset.
  Word-count switching no longer hits the backend or triggers segmentation.
- Backend: for Chinese meaningful/custom mode, produce word frequency and
  POS-tag stats in a single jieba.tag pass instead of two, halving CPU for
  genuine recomputes (filter/time/member changes). Behavior is preserved
  (verified by an equivalence regression test).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 23:54:12 +08:00
diguaandCursor 9fbabd02b6 fix(electron): pre-bundle lazy-route deps to avoid dev 504
Analysis pages (private/group chat) are lazy-loaded routes that pull in
heavy deps (echarts, markdown-it, snapdom, vue-virtual, etc.) which Vite's
cold-start scan does not discover. The first navigation triggered an
in-flight dependency re-optimization, invalidating already-loaded chunks
and failing with 504 (Outdated Optimize Dep) on the dynamically imported
page module. This surfaced after a fresh pnpm install wiped the warm
node_modules/.vite cache.

Add optimizeDeps.include so the initial optimize pass already contains
these deps, preventing mid-session re-optimization and the 504.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 23:54:12 +08:00
diguaandCursor 3cd0d0f680 refactor(records): rename timeline panel label to summary
将聊天记录查看器左侧面板标题及空状态由「会话」统一改为「摘要」,
同步更新 zh-CN/zh-TW/en-US/ja-JP 四种语言。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 23:54:12 +08:00
diguaandCursor 7a7a322496 fix(records): restore timeline default scroll and session jump (resolve #199)
时间线左侧面板在 isLoading 为 true 时调用滚动,此时虚拟滚动容器(v-else)尚未挂载,
getScrollElement 返回 null 导致滚动失效,左侧停留在最早会话,与右侧消息列表展示最新内容不一致。
现将滚动移到加载完成后执行,并优先滚动到当前激活会话。

同时 FetchSessionIndexAdapter 的 getSessions/getByTimeRange/getRecent 查询漏掉 firstMessageId,
导致点击左侧会话无法跳转到对应消息(桌面端与 CLI Web 共用该 adapter,两端均受影响)。
补回与 core getChatSessionList 一致的 firstMessageId 子查询,并新增内存 SQLite 回归测试。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 23:54:12 +08:00
digua 615c0191b8 fix(database): repair missing segment message contexts 2026-06-14 23:54:12 +08:00
diguaandCursor 7afb31e679 fix(data): populate aiConversationCount from conversations.db instead of returning 0
The /_web/sessions route never called getAIChatCountsBySession() to
enrich session DTOs, leaving aiConversationCount always 0 in the
data management UI. Use the existing enrichSession callback and
AIChatManager to fill real counts for both list and detail endpoints.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-14 23:54:12 +08:00
diguaandCursor d90a6e4bf7 ci: add R2 cleanup workflow to remove old release versions
Keep only the latest 3 versions in Cloudflare R2 to stay within
storage limits. Triggered automatically after each stable release
and manually via workflow_dispatch.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-13 16:24:53 +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
diguaandClaude Sonnet 4.6 674db15b69 feat(web): add favicon for CLI Web
Copy favicon.ico from chatlab.fun and serve it via Vite's publicDir
(src/public/). Update index.html to reference the standard /favicon.ico
path; the previous /assets/imgs/favicon.ico path had no backing file.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 16:24:53 +08:00
diguaandCursor f56b2b79d6 fix(home): update tutorial link to docs.chatlab.fun root with locale path
Co-authored-by: Cursor <cursoragent@cursor.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
digua 40a4357ff7 release: v0.26.2 v0.26.2 2026-06-13 13:24:04 +08:00