Keep shared-interaction evidence, pagination, and token truncation accurate while bounding anchor inputs, proximity scans, contact discovery, and reply aggregation. Resolve participants across all imported history and isolate damaged database candidates without changing the final analysis tree.
Use the all-history contact snapshot and validate raw session candidates inside the cancellable scan loop. Bound model-visible structural results to the configured token budget while preserving full tool details and continuation metadata.
Keep full entity resolution details available to the application while bounding the model-visible payload with the runtime tokenizer. Preserve coverage and truncation metadata, prioritize usable scopes fairly, and cap ambiguity hints to avoid duplicate unbounded source lists.
Count complete tool payloads with the runtime tokenizer so Chinese evidence respects the configured model context budget.\n\nResolve contact sources incrementally with cancellation checks and targeted member lookups to keep long cross-chat investigations responsive.
Centralise the better-sqlite3 native-binding selection for tests in
tests/helpers/sqlite.mts so test files consistently use the CLI-side
binding (apps/cli/native/better_sqlite3.node) rather than the default
one, which may be compiled for a different Node.js ABI.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
Prevent stale semantic index writes by checking write guard before
persisting chunks; make rebuild detection explicit on app restart via
reactivate() path; preserve full evidence snippet text without truncation;
add regression test for same-second chunk tie-breaking in mapMessageToChunk.
retrieve-chat-evidence:
- repair semantic cleanup and keyword time filter; pass context timeFilter
(seconds→ms) when no explicit date params are provided
- classifyGroup: skip Chinese keyword matching for non-Chinese locales and
update the English LLM instruction to allow judgment on uncertain groups,
so English-language chats are not permanently stuck at "cannot confirm"
- mergeCandidates: replace ID-range overlap check with timestamp overlap
so keyword hits are not incorrectly dropped after incremental imports
backfill older messages with non-monotonic IDs
semantic-search-current-chat:
- forward context.timeFilter (seconds→ms) to searchForTool so the tool
respects session time range the same way other retrieval tools do
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
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>
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>
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>
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>
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>
Add optional `rows` parameter to render_chart so AI can pass pre-fetched
data arrays (e.g. from get_time_stats, member_stats) directly instead of
rewriting SQL from scratch. Update chart capability prompts and all locale
files to guide AI to check high-level tools first before falling back to SQL.
Remove debug console.debug log from agent-core thinkingLevel resolution.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add "type": "module" to all workspace package.json files
- Replace __dirname with import.meta.url-based resolveCliPath() helper
- Convert stream-json/stream-chain CJS named imports to default + destructure
for ESM compatibility
- Use createRequire() for @node-rs/jieba native module loading in ESM context
Co-authored-by: Cursor <cursoragent@cursor.com>
- Expand MCP_TOOL_REGISTRY from 8 to 33 tools by including all
AGENT_TOOL_REGISTRY tools (analytics, deep search, conversation, etc.)
- Add format=text|json parameter to all MCP tools (default: text for
most, json for SQL tools) for token-efficient LLM consumption
- Create format.ts: message filtering, consecutive-sender merging,
content truncation, and compact text output
- Inspired by community chatlab-mcp-server project
Co-authored-by: Cursor <cursoragent@cursor.com>
Extract 10 query functions from Electron worker to @openchatlab/core:
- message-queries: getMessageContext, getSearchMessageContext,
getConversationBetween, getMemberNameHistory, getMembersWithAliases,
executeParameterizedSql
- session-queries: getChatOverview, searchSessions, getSessionMessages,
getSessionSummaries
- filters: hasTable, hasColumn utilities
CoreDataProvider now delegates to core functions instead of throwing
NotImplementedError. All 27 Server Agent tools are functional.
Also inject segmentText (batchSegmentWithFrequency) into server
ToolExecutionContext so keyword_frequency tool works properly.
- Rename TOOL_REGISTRY to MCP_TOOL_REGISTRY (MCP Server only)
- Create AGENT_TOOL_REGISTRY with full Electron-aligned tool set (27 tools)
- MCP-only tools (list_sessions, get_session_info, search_keyword) excluded
from agent registry
- Update ai.ts to use AGENT_TOOL_REGISTRY, mcp.ts to use MCP_TOOL_REGISTRY
- Add truncation strategies for newly registered agent tools
Note: Most newly registered agent tools require CoreDataProvider method
implementations (currently NotImplementedError). See follow-up task doc.
Remove chatlab_ prefix from all tool definitions in @openchatlab/tools,
aligning with Electron-style names (get_*, search_*, etc.). The chatlab_
prefix is now only added at the MCP registration layer via MCP_TOOL_PREFIX
constant, keeping MCP namespace isolation without polluting internal names.
This ensures the AI agent uses identical tool names in both Electron and
CLI Web environments, fixing skill system compatibility and tool catalog
consistency.
Create shared-tool-adapter to convert @openchatlab/tools ToolDefinition → AgentTool.
Delete Electron-specific get-member-stats.ts and get-time-stats.ts,
replaced by shared definitions via adaptSharedTool().
Make ToolExecutionContext.db optional to support Electron (no DatabaseAdapter).
Replace direct @openchatlab/core function calls with dataProvider abstraction:
- member-stats, time-stats, search, recent-messages, sql, schema
- Handlers are now async, using context.dataProvider for data access
- Server consumers inject CoreDataProvider alongside db for backward compat
Add ToolDataProvider implementations for both platforms:
- CoreDataProvider: wraps @openchatlab/core sync queries for Server/MCP
- WorkerDataProvider: wraps workerManager async IPC for Electron