feat: learn scoped filing and tagging preferences in Paw mode

This commit is contained in:
tianma-if committed 2026-09-05 12:22:02 +08:00
1 parent db231ffa1d
commit 245ac044b6
26 files changed
+800 -387

No files matched your search

+54 -123
View File
@@ -2,158 +2,89 @@
[简体中文](personality-memory-agent.zh-CN.md)
Updated: 2026-09-03. This document describes the current product direction, implementation boundaries, and outstanding validation—not release notes or a development log. Git retains implementation history and verification records.
Updated: 2026-09-05. This describes implementation and validation limits, not release notes.
## 1. Product positioning
## 1. Product purpose
The Agent is a long-term assistant working with the user's knowledge, not just a chatbot familiar with notes or a general-purpose computer operator. Its value is connecting scattered records, understanding enduring interests, and helping organize notes.
Paw connects knowledge and proposes organization during everyday note work. Long-term memory must change future suggestions, not merely accumulate chat logs. Explicit preferences and evidence-backed filing/tagging habits now form this loop; understanding every user intention is not promised.
The product must stay lightweight, fast, and reliable. Presence can be subtle; suggestions must be useful. Personality should emerge through continuing understanding, accurate memory, and measured actions—not anthropomorphic lines, simulated emotions, or frequent interruptions. Chat is a supporting entry point, not the primary experience.
Suggestions stay separate from notes. Without a useful result Paw stays quiet. Merge, append, filing and tagging require confirmation. Existing business services execute saved arguments; the model cannot rewrite them during confirmation or write unattended.
The main flow is: normal note-taking → the Agent identifies an opportunity at an appropriate time → grounded information or an action proposal → execution after confirmation. Without a worthwhile result, remain quiet.
## 2. Controls and interface
## 2. Interaction rules
- Settings → Paw mode. Initial activation requires an available default AI model. Disabling Paw, pausing learning and stopping memory use do not require a working provider.
- “Learn from my choices” processes future operations only. Re-enabling skips operations performed while paused; disabling Paw also stops learning processing.
- “Use saved memories” controls both chat and discovery. Chat retains per-request note access, off by default. Pausing learning keeps memories; disabling recall does not delete them.
- Existing accounts do not silently opt into learning or discovery memory. Enable these controls explicitly. The chat memory checkbox updates the same global setting.
- “Conversation and personal memory” shows explicit information, candidate/active/conflicting inferences and evidence. Memories can be corrected or forgotten.
- Organization cards offer “Stop suggesting this kind of organization,” recording an explicit preference for the source notebook. Ordinary dismissal is not a lasting preference.
- Web and desktop provide the UI. Native Android/iOS have no Paw entry yet. Only reliably attributed operations reaching the shared server business services can contribute; native end-to-end behavior is unverified.
- Entry: Settings → Paw mode, off by default. It can be enabled only after a default AI model is configured and enabled; the client links to model setup and the server enforces the same model-availability check. Paw mode can still be turned off while the model is unavailable. Enabling covers all notes in the current account, including child notebooks and future notes, without notebook selection. This does not mean reading or sending the entire library at once.
- Use a small bell and unread dot, without primary navigation, automatic popups, or system notifications. Currently available to signed-in personal accounts on non-demo instances with login enabled; no native Android/iOS entry yet.
- Informational notifications offer useful connections, explanations, and source links without requiring a task. Action notifications explain which notes will change, how, and with what consequences; confirmation invokes existing note capabilities.
- Suggestions do not enter the normal note list or automatically become “AI suggestion drafts.” Notes are created or modified only after confirmation of the corresponding write.
- Users may dismiss suggestions or disable the mode. Disabling invalidates unconfirmed discovery actions; already-started confirmed operations retain receipts. Disabling does not undo completed changes.
## 3. Current capabilities
The settings page starts with a short benefit description, then makes the background behavior visible without adding configuration burden. A read-only status panel shows whether Paw mode is idle, checking, ready, or failed; the last check time; the conditions for another check; the data scope and confirmation boundary; and the latest generated discovery when one exists:
> When enabled, EdgeEver quietly helps tuck scattered fragments together, append new ideas to existing notes, and surface relevant past insights like a gentle cat paw.
>
> The longer you use it, the better Paw mode understands you.
## 3. Current capabilities and boundaries
| Path | Current capability | Boundary |
| --- | --- | --- |
| Proactive discovery: connections | Resurface related older notes and explain their connection to new records | Sources required; no notification without a suitable result |
| Proactive discovery: merge | Combine fragments of one idea while preserving text, attachments, and tags | Confirmation required; sources move to trash and their shares are revoked; no complete one-click undo promise |
| Proactive discovery: append | Add a new fragment to an existing note while preserving the source and original target content | Currently limited to plain-text notes without attachments; no automatic rewriting of rich documents |
| Optional conversation: note tools | 28 existing tools: 13 reads and 15 confirmed writes covering creation, import, editing, merging, moving, tags, trash, revision recovery, and notebook organization | Discovery does not propose all these operations; permanent deletion, public sharing, binary uploads, and system administration are not exposed |
“Conversation and personal memory” remains an optional settings entry. Conversation currently has independent note-access and memory controls, with note access off by default; these are not unified with the Paw-mode switch. This is the implementation state, not a requirement to select notebooks, and must not be presented as a single permission switch across the product.
“Note-operation capabilities” means reusing existing APIs and business services, not building another note system or granting unattended write authority to the model. Proactive tagging and other notification-based organization scenarios are not yet connected; the full tool catalog must not be advertised as proactive functionality.
## 4. Personality and memory
The long-term goal is for suggestions to reflect preferences, project context, shared decisions, and feedback. Personality and memory belong to EdgeEver's product data and behavior rules, not to a particular model; their value does not depend on adding a dedicated chat surface.
Implemented today:
- A product-controlled stable identity, conversation continuity, and explicit cross-conversation memory in the optional conversation workspace.
- Users manually add memories or save their own words through the UI, and can correct, forget, or suspend their use. The model cannot independently add or remove memories.
- Small-scale retrieval using segmentation, weighted keywords, and update recency, without a vector index. Memory edits/forgetting invalidate old context; user-confirmed information must remain distinct from model inference.
- Server-side storage isolated by workspace and user. Separate JSON export includes memories, chats, and organization records; import merges memories only, not chats or execution records.
Not yet connected: proactive discovery does not read personal memory. Current notifications must not be described as understanding long-term preferences. Automatic memory candidates, relationship modeling, and suggestion adaptation based on long-term feedback are also unimplemented.
The next priority is to test whether controlled memory improves relevance, not to expand personality settings. Connecting memory to discovery requires explicit user control, provenance, correction, and forgetting propagation; do not silently broaden memory use. Dismissing one notification should not directly become a lasting preference.
Deleting a note does not delete its text or snapshots in chats; forgetting a memory does not delete its source. This data is not yet included in note ZIP backups, desktop offline mirrors, or native mobile sync. Do not promise full cross-device recovery or deletion of exported files or provider-retained data.
## 5. How the implementation works
The architecture is “client trigger + server-side retrieval and model judgment + existing business operations after confirmation,” not an autonomous program permanently running inside Electron. The client handles interaction and sync checks; the instance server handles model calls, authorization, and persistence.
```text
Client activity/sync/visibility events → idle check → server rate/change checks
→ retrieve a few relevant notes → model returns a structured suggestion
├─ No useful result: finish without notification
├─ Knowledge connection: persist discovery → informational notification
└─ Organization proposal: persist discovery and action → confirmation notification
→ user confirms action ID → revalidate → existing note service executes → save receipt, refresh notes
```
### How proactive discoveries are generated
1. Client events reset a one-shot idle timer rather than a polling loop. Before a check, verify visibility, connectivity, and pending sync changes. A conditional database update claims the server-side check; account rate limits and the workspace change cursor prevent duplicate model calls across devices.
2. Start from a recently updated note, find related records through existing search, and read bodies within the budget. The model sees only selected notes; it does not connect directly to the database or automatically know the entire library.
3. Create a `ToolLoopAgent` on demand, using `Output.object` and a shared schema to constrain output to no suggestion or one `insight / merge / append`. This path exposes no model-callable tools. The model judges connections and explains reasons; the server revalidates source IDs, data versions, and operation conditions.
4. The server constructs concrete merge/append tool arguments and persists notifications in `companion_discoveries` and action plans in `companion_actions`. Deduplicate by type and source combination. These are separate records, not ordinary notes; the client reads them to display the two notification types.
### How personality, memory, and conversation work
Optional conversation combines product-maintained identity instructions, the current message, eligible recent conversation, retrieved explicit memories, and tool results into model context. Memories come from the database and are selected by relevance when the user permits their use. This is not model training or reliance on the provider automatically remembering the user. Proactive discovery currently does not use this personal-memory retrieval path.
The conversation `ToolLoopAgent` can call exposed note tools within a step budget: read tools return query results immediately, while write tools only persist proposals awaiting confirmation. Tool definitions reuse the MCP catalog, but the built-in Agent calls the shared business executor directly, without an external MCP client round trip.
### Which database tables are involved
Seven Agent-specific tables live in the existing instance database; no separate database is introduced. Business records are scoped by workspace and user; `companion_action_checks` is for transaction-local validation and stores no user content.
| Table | Purpose |
| Path | Capability and boundary |
| --- | --- |
| `companion_discovery_settings` | Stores the Agent switch, settings version, check time, workspace cursor, and active check claim. `last_input_hash` holds the last successfully analyzed input fingerprint to reduce repeat calls. The retained `notebook_ids_json` no longer selects the note-access scope. |
| `companion_discoveries` | Stores notification type, title, body, sources, deduplication fingerprint, and seen/dismissed status. `turn_id` links to the generation run; action notifications also link to a proposal through `action_id`. These are not notes. |
| `companion_turns` | Stores conversation or discovery generation runs: input, response, sources, model, permission snapshot, context version, status, and expiry. Token fields record usage when available, not complete billing statistics for every discovery request. `origin` distinguishes chat from discovery. |
| `companion_actions` | Stores exact proposed arguments and source snapshots, status, expiry, execution claims, and result receipts. Confirmation executes this persisted record without having the model regenerate arguments. |
| `companion_state` | Stores the account's `memory_revision` context version. Editing/forgetting memories or clearing history increments it to prevent generation or execution with stale context. It does not store personality content. |
| `companion_memories` | Stores explicitly added long-term memories, optional source runs, versions, and timestamps. Optional conversation retrieves them; proactive discovery currently does not. |
| `companion_action_checks` | Asserts valid permissions, context, and data versions within a database batch. A failed constraint rolls back the batch; successful check rows are deleted before commit. This is not an operation log or task queue. |
| Connection | Explains a concrete relationship between at least two notes |
| Merge | Fragments of one concrete idea only; preserves text, attachments and tags, trashes sources and revokes shares; no complete one-click undo |
| Append | Adds a plain-text fragment to a target and preserves both originals; excludes complex documents and source attachments |
| Filing | Proposes an existing notebook; confirmation uses the existing move tool |
| Tagging | Uses tags present in candidate notes and preserves the target's existing tags |
| Optional chat | Retains the existing 28 note tools and confirmation flow; explicit and active inferred memories can enter context |
Identity instructions and tool-exposure rules remain in code; there is no separate “personality table.” Schemas are defined by migrations [0040](../migrations/0040_companion_memory.sql), [0041](../migrations/0041_companion_actions.sql), [0042](../migrations/0042_companion_tool_execution.sql), [0043](../migrations/0043_companion_discovery.sql), and [0044](../migrations/0044_companion_discovery_input_hash.sql).
## 4. Learning and durable memory
### Why confirmation can execute directly
Reuse the existing AI SDK, database and business services. No new agent framework, vector database or permanently running background process.
Confirmation submits an action ID instead of asking the model to regenerate a task. The server reads the persisted arguments and source snapshots, rechecks account, status, expiry, and versions, then calls existing note services. Execution claims and write guards apply within database batches; outcomes become persistent receipts. The client uses those receipts to show success or uncertainty and refresh notes. Model judgment and actual writes are separate; the next section specifies conflict and partial-completion boundaries.
The first implementation uses deterministic evidence rules rather than model self-rated confidence:
Implementation entry points: [client triggers](../apps/web/src/components/CompanionDiscoveryHub.tsx), [discovery service](../apps/api/src/companion-discovery.ts), [structured generation](../apps/api/src/companion-discovery-runtime.ts), [conversation and memory retrieval](../apps/api/src/companion-runtime.ts), [tool catalog](../apps/api/src/companion-tool-catalog.ts), [confirmed execution](../apps/api/src/companion-tool-actions.ts).
1. Existing `memo.move`, `memo.update`, `tag.add/remove` audit records include before/after notebooks and tags. Note saving does not call a model or maintain memories.
2. Idle checks asynchronously consume committed audits, scoped to workspace/user and attributable user operations. Imports lack learning snapshots; tool execution is marked as agent activity and does not count as independent user behavior.
3. Learn two scoped patterns: notes with a particular tag are usually filed in a notebook; notes in a notebook are frequently given a particular tag.
4. Require three distinct notes, three independent time windows and at least two days of consistent choices. A bulk burst within ten minutes counts at most once. Event IDs deduplicate; evidence and processing cursor commit together.
5. Reevaluate when sources are deleted, filing changes, competing targets appear, or evidence exceeds 90 days. Conflicting inferences are excluded from recall. These thresholds are initial product rules, not proven accuracy guarantees.
6. Corrections become explicit user statements and cannot be overwritten by learning. Forgetting removes evidence and keeps a content-free rule exclusion key, preventing the same rule from returning from old or future observations.
## 6. Technical and reliability tradeoffs
Up to 50 memories, including at most 30 automatic inferences, reserving room for explicit preferences. Each pass consumes at most 50 audit events with a small number of rules per event and reviews at most 2,000 recent evidence records. Busy accounts may process later; learning every action is not guaranteed.
### Reuse existing capabilities
Automatic extraction from free-form chat, abstract project/relationship modeling, weighted learning from accepted suggestions, and precise undo attribution remain unimplemented. Explicit chat preferences can be saved with “Remember this message.” Paw's own operations do not positively reinforce its habits.
Keep AI SDK `ToolLoopAgent` and existing model configuration; EdgeEver manages identity, memory, permissions, proposals, and execution receipts. Do not currently introduce Mastra, ElizaOS, a second database, or a custom general-purpose agent/workflow framework.
## 5. How memory changes suggestions
Tool names and parameters come from the existing MCP catalog and use the same business executor. Add only Agent exposure policy, preview, and confirmation adaptation. Cloudflare and Docker share business logic. Agent UI and server-side AI runtimes load on demand; build tests inspect the entire startup dependency graph, including shared chunks.
Discovery searches multiple keywords and recent records, selecting at most six complete note bodies within 12,000 characters. The most recently updated note remains the anchor; rotating through multiple anchors is not implemented.
There are no new runtime dependencies, always-on autonomous processes, or bundled local models. No new dependencies does not mean zero package growth, memory use, model fees, or maintenance. Measure actual deltas rather than promising results from early, non-reproducible framework comparisons.
Chat and discovery share memory selection: valid status, scope, keywords and recency, with explicit preferences before inferences. Up to eight records within 4,000 characters; a small fallback is used without keyword matches. No full-library prompt or model training.
### Projects considered and why they were not adopted
The model receives selected notes, related memories and existing notebooks. Notes and memories are untrusted data, not permission changes or confirmations. Structured results cite note and memory identifiers; the server validates them and persists exact proposals. Cards can show memories used. Explicit “stop suggesting” rules are also filtered server-side.
- [ElizaOS](https://github.com/elizaos/eliza): considered as a reference for personality, memory, and plugin-based agents. EdgeEver already has note storage, plugins, and permissions; adopting another agent runtime would require reconciling its memory, state, and plugin contracts. Current lightweight discovery and confirmed organization do not yet justify that adaptation cost. Retain design ideas without adopting the runtime.
- [Mastra](https://github.com/mastra-ai/mastra): evaluated for its TypeScript agents, memory, workflows, and human approval capabilities. Model integration, the tool loop, and note execution already have reusable foundations, while current flows do not require full workflow orchestration. A framework would still require EdgeEver-specific permissions, version checks, and memory governance; the benefits do not yet justify additional dependencies and integration maintenance.
Input fingerprints include memory and notebook context. A memory version change can trigger analysis without a note change and invalidates old context/pending actions. Execution still rechecks access, versions, sources and synchronization. Completed operations retain their receipts.
This is a provisional decision based on current scope and architecture, not a claim that either framework cannot be embedded in Electron or necessarily consumes excessive resources. Reevaluate if requirements outgrow the maintainable scope of the existing approach, using package-size, memory, and startup measurements from an actual integration.
## 6. Storage, deletion and backup
### Bounded cost
New migration [0045](../migrations/0045_companion_learning.sql), without editing old migrations:
- Proactive checks run only while the app is open, visible, online, free of pending sync changes, and inactive for three minutes. A cross-device limit allows at most one attempt per account per 24 hours; unchanged notes are skipped. After one completed check, the client makes no further request in that session until another note or sync change occurs. This is not an always-running background service.
- Each check selects a small set from recent records and keyword searches: at most six note bodies totaling 12,000 characters. One structured generation, at most 1,200 output tokens, cancellation after 60 seconds, and no automatic model retries.
- Full conversations have separate tool-call, context, concurrency, and timeout budgets. Library-wide authorization does not mean putting the entire library into a prompt.
- Selected content is sent to the user's configured default model provider. A check can incur charges without producing a visible suggestion. Keyword retrieval may miss semantic connections, and low-frequency checks do not guarantee timely discovery of every opportunity.
- Extend `companion_memories` with kind, scope, rule key and state; preserve legacy explicit records and versions.
- Add `companion_memory_evidence` and `companion_memory_exclusions` for evidence references and excluded rule identifiers.
- Extend discovery settings with learning/recall controls, learning cursor and last analyzed memory version.
- Expand the discovery kind constraint, preserve old discoveries and add used-memory IDs.
### Token controls
Records are isolated by workspace and user. Cloudflare/D1 and Docker/Bun SQLite share business services and SQL.
- Proactive discovery stores a fingerprint of the last successfully analyzed input. Even when unrelated workspace changes trigger another eligible check, identical candidate notes, instructions, language, settings, context, and model-configuration versions skip the model call. Successful no-suggestion results count too. Failures are not cached; clearing history removes the fingerprint. Old results are not replayed and invalidated actions are not revived.
- Note IDs sent to the model become short, invocation-local aliases, strictly mapped back to real IDs by the server. Bodies remain complete; organization sources are not truncated to save tokens.
- Conversations retrieve at most eight relevant memories, reducing the total memory-body budget from 8,000 to 4,000 characters. Without keyword matches, retain at most two recent memories. Stored memories are not deleted, but relevant older preferences may be missed; validate this tradeoff against real scenarios.
- Repeated reads of a completely read note within one run return a reference hint, reusing the body already in that run's context. Authorization and data-version checks still apply; there is no cross-run cache. Confirmed operations continue to use persisted arguments without another model call.
Separate JSON export uses version 2, preserving memory kinds and learning controls. Version 1 import remains supported. Version 2 merges memories and restores controls; imported inferences have no trusted evidence and remain candidates until explicitly confirmed. Notebook scopes, exclusions and evidence are not reconstructed across instances. Chat and execution history are not imported.
These controls reuse the existing AI SDK without changing the default model, trigger frequency, or confirmation permissions. Character budgets are not token measurements; actual cost depends on model, language, and content, so no fixed savings percentage is promised. Upgrades require [database migration 0044](../migrations/0044_companion_discovery_input_hash.sql), which adds only a nullable fingerprint field without changing note content.
These records remain outside note ZIP backups, desktop offline mirrors and native mobile synchronization. Deleting a note retracts its learning evidence, not existing chat snapshots. Forgetting cannot delete exported files or provider-retained data.
### Confirmation and recovery
## 7. Runtime and costs
1. The model proposes; the server validates sources and arguments. For proactive merges/appends, the server constructs the arguments. Persist the exact operation, reason, and data versions; a proposal does not modify notes.
2. Confirmation binds to that operation, without another model decision at execution. Check account, expiry, source versions, and sync state; expired proposals or changed data require regeneration.
3. Reuse transactions, execution claims, and persistent receipts to prevent duplicate confirmation and concurrent overwrites. Recover or query outcomes after disconnection; generated text is not a success receipt, and uncertain writes must not be blindly replayed.
4. Multi-batch operations may partially complete; cancellation does not roll back completed effects. The current workspace-cursor policy is conservative, so unrelated note changes may also invalidate other proposals.
Checks require a visible, online app without pending synchronization, after three idle minutes. Ordinary note changes are checked at most daily; memory changes can trigger earlier checks, at most hourly. Rate limits and concurrency claims are account-wide. The client does not poll continuously or retry without new events. Rule learning makes no model calls.
Notes, memories, attachments, and tool results are untrusted data. They cannot change identity, grant permissions, or forge confirmation. Do not expose shell/computer control, automatic external messaging, or publication, or relax authorization because the Agent “knows the user.”
Each discovery makes at most one structured generation, with 1,200 output tokens, a 60-second timeout and no automatic paid retry. Selected notes and memories go to the default model provider; a check producing no notification can still cost money. Character budgets are not token counts; no fixed cost or savings claim.
## 7. Outstanding validation and priorities
## 8. Validation and rollback
- Build a real-note evaluation set: whether fragments belong to one idea, whether merging/appending is worthwhile, and whether connections are useful. Measure false positives, interruptions, acceptance, and harmful organization—not notification count or chat duration.
- Validate structured outputs, tool calling, cancellation, source accuracy, and prompt-injection defenses with real models. Model failures must not disrupt ordinary note operations.
- Measure installer size, cold start, CPU, RSS/heap, and model costs with the Agent disabled, idle, on first use, during sustained use, and after cancellation. Separate client and server measurements; use the [desktop performance baseline](desktop-performance-baseline.md).
- Once current scenarios are reliable, evaluate memory-informed suggestions, proactive tagging, and consistent permissions across conversation and Paw mode. These document goals are not completed features.
- Complete backup/recovery, deletion propagation, and cross-device experience. Automation, reminders, multiple agents, and heavier retrieval infrastructure are not in the current default scope; reconsider only when actual needs and measurements justify them.
Coverage includes bulk/repeated operations, pause/re-enable, isolation, conflicts, corrections, forgetting, candidate imports, memory-triggered discovery, filing/tagging confirmation and reopening/upgrading an old SQLite database. An isolated local D1 database also receives old migrations/data, then migration 0045, followed by data-preservation and foreign-key checks.
Implementation changes must pass relevant tests, the full non-E2E suite, `bun run typecheck`, `bun run typecheck:mobile`, and `bun run build:web`. Passing tests does not establish suggestion quality or acceptable resource usage.
Run the full non-E2E suite, `bun run typecheck`, `bun run typecheck:mobile`, and `bun run build:web`. Browser verification uses Codex's built-in Browser.
Zero new dependencies is a current strategy, not a permanent prohibition. New dependencies must justify user value, resource deltas, maintenance costs, and an exit path; never reinvent a general framework merely to preserve a “zero dependencies” claim.
Unverified: production D1 upgrade, long-term real-user suggestion quality, actual model cost and native mobile cross-version behavior. Do not claim no impact on existing users or automatic updates.
Pause learning to stop new evidence processing; disable memory use to return discovery to note context. Retain additive database fields instead of destructive reverse migrations. Disable Paw before downgrading code so old clients do not handle new discovery kinds. Confirmed note operations are not automatically undone by disabling or rolling back Paw.
+53 -122
View File
@@ -2,158 +2,89 @@
[English](personality-memory-agent.md)
更新:2026-09-03。本文记录当前产品方向、实现边界与待验证事项;不是发布说明或开发日志。实现历史与验证记录保留在 Git 中。
更新:2026-09-05。本文描述当前实现与验证边界,不是发布说明。
## 1. 产品定位
Agent 是围绕用户知识工作的长期助手,不是一个熟悉笔记的聊天机器人,也不是通用电脑操作工具。它的价值在于发现零散记录之间的联系、理解用户长期关注的事情,并帮助完成笔记整理。
猫爪围绕日常笔记工作提供知识关联和整理建议。长期记忆必须影响后续建议,而不只是积累聊天记录。当前通过显式偏好和有证据的归档、标签规律实现这一闭环;不承诺理解用户的所有意图。
产品底线:轻量、快速、可靠。存在感不必强,建议必须有用;人格通过持续的理解、准确的记忆和有分寸的行动体现,不依赖拟人台词、情绪模拟或频繁打扰。聊天是辅助入口,不是功能主线。
建议独立于正常笔记;没有有用结果就保持安静。合并、补入、归档和添加标签均需要用户确认后执行。确认复用现有业务服务,模型不重新生成参数,也没有无人值守写入权限。
当前主要体验:用户正常记笔记 → Agent 在合适时机发现机会 → 展示有来源的内容或操作建议 → 用户确认后执行。没有有价值的结果就保持安静。
## 2. 开关与界面
## 2. 交互规则
- 设置 → 猫爪模式。首次开启需要可用的默认 AI 模型;关闭模式、暂停学习和停止使用记忆不依赖模型可用性。
- “从操作中学习”只处理开启之后的操作;暂停及重新开启不会补学停用期间的历史。关闭猫爪也停止处理学习事件。
- “使用已保存的记忆”统一控制对话和主动发现。对话仍有本轮笔记访问控制,默认关闭。暂停学习保留记忆,停止使用不删除记忆。
- 旧账户升级不自动开启学习或主动发现记忆;需要在设置中明确启用。对话的记忆复选框同步这一全局设置。
- “对话与个人记忆”展示显式信息、候选推测、有效推测和冲突状态,以及操作证据。可以编辑和忘记。
- 整理卡片提供“不再建议这种整理”:针对来源笔记本记录明确偏好。普通忽略只关闭当前建议,不被解释为长期偏好。
- Web / 桌面提供界面。原生 Android / iOS 尚无猫爪入口;只有经过同一服务端业务并可靠归因的同步操作才可能参与学习,尚未完成原生端到端验证。
- 入口为「设置 → 猫爪模式」,默认关闭。只有已配置并启用默认 AI 模型时才能开启;前端给出配置入口,服务端执行同样的模型可用性校验,模型不可用时仍可随时关闭。开启后,笔记访问范围覆盖当前账户的全部笔记,包括子笔记本和以后新建的笔记,无需选择笔记本;不代表一次读取或发送全库。
- 使用轻量铃铛和未读圆点,不占主导航、不自动弹窗、不发系统通知。当前仅向已登录的个人账户开放,要求非 Demo 且启用登录的实例;原生 Android/iOS 尚无入口。
- 普通通知提供有价值的关联、解释和来源链接,无须执行任务。操作通知说明处理哪些笔记、如何处理及其后果,用户确认后调用现有笔记能力执行。
- 建议不混入正常笔记,也不默认生成「AI 建议草稿」。只有确认了相应写入操作,才创建或修改笔记。
- 用户可忽略建议或关闭模式。关闭后未确认的发现操作失效;已经开始的确认操作保留执行记录,关闭不等于撤销已完成的修改。
## 3. 当前能力
设置页以简短用途介绍开头,再以只读状态呈现后台行为,不增加配置负担。状态面板展示猫爪处于安静观察、检查中、发现就绪或检查失败,最近检查时间、下次检查条件、数据范围与确认边界;存在生成结果时还展示最近一条发现:
> 开启后,EdgeEver 会像猫爪轻推纸片一样,帮你归拢零散碎片、将新想法沉淀到已有笔记、挑出过往的相关灵感。
>
> 用得越久,猫爪越懂你。
## 3. 当前能力与边界
| 路径 | 当前能力 | 边界 |
| --- | --- | --- |
| 主动发现:知识关联 | 唤回相关旧笔记,说明与新记录的联系 | 必须有来源;没有合适结果不通知 |
| 主动发现:合并 | 将属于同一想法的碎片归为一篇,保留原文、附件和标签 | 确认后执行;来源移入回收站并撤销原有分享,不承诺一键整体撤销 |
| 主动发现:补入 | 把新片段追加到已有笔记,保留来源和目标原文 | 当前仅支持无附件的纯文字笔记,不自动改写复杂文档 |
| 可选对话:笔记工具 | 28 项现有工具:13 项读取、15 项确认写入,覆盖创建、导入、修改、合并、移动、标签、回收站、版本恢复及笔记本整理 | 不等于主动发现会提出所有这些操作;永久删除、公开分享、二进制上传和系统管理未开放 |
「对话与个人记忆」仍是设置中的可选入口。当前对话有独立的笔记访问和记忆开关,笔记访问默认关闭;它与猫爪模式开关尚未统一。这是实现现状,不是要求用户额外选择笔记本,也不应被描述为全产品只有一个权限开关。
“具备笔记操作能力”意味着复用既有 API 和业务服务,而不是另写一套笔记系统,也不意味着模型获得无人值守修改权限。主动通知中的打标签等更多整理场景尚未接入,不能按完整工具目录对外承诺。
## 4. 人格与记忆
长期目标是让建议逐步体现用户的偏好、项目背景、共同决定和反馈。人格与记忆属于 EdgeEver 的产品数据和行为规则,不绑定某个模型,也不靠增加独立聊天入口体现价值。
当前已实现:
- 受产品控制的稳定身份;可选对话中的会话连续性与跨会话显式记忆。
- 用户通过界面手动添加记忆,或保存自己的原话,并可纠正、忘记、暂停使用;模型不能自行增删记忆。
- 基于分词、关键词权重和近期更新的小规模召回,不使用向量索引。记忆修改/遗忘会使旧上下文失效;用户确认的信息与模型推断不能混为一谈。
- 服务端按工作区和用户隔离存储;独立 JSON 导出包含记忆、聊天和整理记录,导入仅合并记忆,不恢复聊天和执行记录。
尚未打通:主动发现不读取个人记忆,不能宣称当前通知已理解用户的长期偏好。自动记忆候选、关系建模和基于长期反馈的建议调整也尚未实现。
下一步应优先验证“受控记忆能否让建议更相关”,而不是扩展人格配置。若接入主动发现,必须明确用户控制、来源、纠正和遗忘传播,不能静默扩大记忆用途。忽略一条通知也不应直接成为长期偏好。
删除笔记不等于删除聊天中的原文或快照,忘记一条记忆也不等于删除其来源。当前数据尚未纳入笔记 ZIP 备份、桌面离线镜像或原生移动端同步;不承诺完整跨端恢复,也不能代用户删除导出文件或模型服务商留存的数据。
## 5. 技术实现原理
整体是“客户端触发 + 服务端检索与模型判断 + 确认后执行现有业务”,不是在 Electron 中常驻一个自主程序。客户端负责交互与同步检查;模型调用、权限校验和数据持久化在实例服务端完成。
```text
客户端活动/同步/可见性事件 → 空闲检查 → 服务端限频与笔记变更检查
→ 检索少量相关笔记 → 模型返回结构化建议
├─ 无有用结果:结束,不通知
├─ 知识关联:保存发现记录 → 普通通知
└─ 整理建议:保存发现记录和操作方案 → 带确认按钮的通知
→ 用户确认操作 ID → 重新校验 → 现有笔记服务执行 → 保存回执、刷新笔记
```
### 主动发现如何产生
1. 前端事件重置一次性空闲计时器,不使用常驻轮询;触发时先检查可见性、网络与待同步改动。服务端通过数据库条件更新占用本次检查,结合账户限频和工作区变更游标,防止多设备重复调用模型。
2. 以近期更新的笔记为线索,利用现有搜索查找相关记录,再在预算内读取正文。模型只看到选中的笔记,不直接连接数据库,也不会自动掌握整个知识库。
3. 按需创建 `ToolLoopAgent`,用 `Output.object` 和共享 Schema 约束结果:无建议,或一条 `insight / merge / append`。这一条路径不开放模型工具调用;模型负责判断关联和表达理由,服务端再次校验来源 ID、数据版本及操作条件。
4. 服务端为合并/补入构造确定的工具参数,将通知写入 `companion_discoveries`,操作方案写入 `companion_actions`;以类型和来源组合去重。它们是独立记录,不是普通笔记。客户端读取记录并展示两类通知。
### 人格、记忆与对话如何工作
可选对话将产品维护的身份指令、用户本轮输入、符合权限的近期会话、检索到的显式记忆和工具结果组合为模型上下文。记忆来自数据库,在用户允许使用时按相关性选入;不是训练模型,也不依赖模型服务商自动记住用户。当前主动发现不走个人记忆召回这条路径。
对话中的 `ToolLoopAgent` 可在步数预算内调用已开放的笔记工具:读取工具直接返回查询结果,写入工具仅保存待确认方案。工具目录复用 MCP 定义,但内置 Agent 直接调用共享业务执行器,不需要绕行外部 MCP 客户端。
### 涉及哪些数据表
Agent 专用表共七张,位于现有实例数据库中,不另建数据库。业务记录按工作区和用户隔离;`companion_action_checks` 是事务内校验用表,不保存用户内容。
| 表 | 用途 |
| 路径 | 能力与边界 |
| --- | --- |
| `companion_discovery_settings` | 保存 Agent 开关、设置版本、检查时间、工作区游标及当前检查占用;`last_input_hash` 保存最近成功分析的输入指纹,减少重复调用。保留的 `notebook_ids_json` 不再用于选择笔记范围。 |
| `companion_discoveries` | 保存通知的类型、标题、正文、来源、去重指纹及已读/忽略状态;通过 `turn_id` 关联生成轮次,操作通知再通过 `action_id` 关联待确认方案。不是笔记表。 |
| `companion_turns` | 保存对话或主动发现的生成轮次:输入、回复、来源、模型、权限快照、上下文版本、运行状态和有效期;Token 字段在取得用量时记录,不代表所有发现请求已有完整计费统计。`origin` 区分聊天和发现。 |
| `companion_actions` | 保存待确认操作的准确参数及来源快照、状态、有效期、执行占用和结果回执;确认时读取这份记录执行,不让模型重新生成参数。 |
| `companion_state` | 保存账户的 `memory_revision` 上下文版本。记忆修改、遗忘或清空历史后递增,用来阻止旧上下文继续生成或执行。不是人格内容表。 |
| `companion_memories` | 保存用户明确添加的长期记忆、可选来源轮次、版本和时间;供可选对话召回,当前主动发现不读取。 |
| `companion_action_checks` | 在同一数据库批次中断言权限、上下文和数据版本仍有效;校验失败通过约束使批次回滚,成功则在提交前删除检查行。不是操作日志或任务队列。 |
| 知识关联 | 解释新旧笔记间的具体联系,至少两篇来源 |
| 合并 | 仅同一具体想法的片段;保留正文、附件、标签,来源移入回收站并撤销分享;不承诺一键整体撤销 |
| 补入 | 将纯文本片段追加到目标,保留两篇原文;不处理复杂文档或带附件的来源 |
| 归档 | 提出已有笔记本目标,确认后执行现有移动工具 |
| 添加标签 | 仅使用候选笔记中的已有标签,保留目标原有标签 |
| 可选对话 | 保留原有 28 项笔记工具与写入确认流程;显式记忆和有效推测均可进入上下文 |
身份指令和工具开放规则保留在代码中,没有单独的“人格表”。表结构见迁移 [0040](../migrations/0040_companion_memory.sql)、[0041](../migrations/0041_companion_actions.sql)、[0042](../migrations/0042_companion_tool_execution.sql)、[0043](../migrations/0043_companion_discovery.sql)、[0044](../migrations/0044_companion_discovery_input_hash.sql)。
## 4. 学习与长期记忆
### 为什么确认后可以直接执行
采用现有 AI SDK、数据库和业务服务,不引入新的 Agent 框架、向量数据库或常驻后台进程。
确认请求提交操作 ID,而非让模型重新生成任务。服务端读取之前保存的参数和来源快照,重新验证账户、状态、有效期与版本,再调用现有笔记服务。执行占用和写入检查随数据库批次生效,结果保存为回执;前端依据回执展示成功或不确定状态并刷新笔记。模型判断与实际写入因此分离,具体冲突和部分完成边界见下一节。
第一版使用确定的证据规则,不调用模型给自己打置信分:
实现入口:[客户端触发](../apps/web/src/components/CompanionDiscoveryHub.tsx)、[发现服务](../apps/api/src/companion-discovery.ts)、[结构化生成](../apps/api/src/companion-discovery-runtime.ts)、[对话与记忆召回](../apps/api/src/companion-runtime.ts)、[工具目录](../apps/api/src/companion-tool-catalog.ts)、[确认执行](../apps/api/src/companion-tool-actions.ts)。
1. 在现有 `memo.move`、`memo.update`、`tag.add/remove` 审计中补充笔记本及标签前后值,不在笔记保存路径调用模型或更新记忆。
2. 空闲检查异步消费已经提交的审计。按工作区、用户过滤,仅使用可归因的用户操作;导入没有学习快照,工具执行标记为 agent,不作为主动习惯证据。
3. 学习“带某标签的笔记通常放入某笔记本”和“某笔记本中经常添加某标签”两类有范围的规律。
4. 至少三个不同笔记、三个独立时间段、跨两天的一致选择才使推测生效。同一十分钟内的批量操作至多贡献一次选择。事件 ID 去重,处理游标和证据写入同一事务。
5. 来源被删除、归类被改动、出现竞争目标或证据超过 90 天后重新评估;有冲突的推测不参与召回。这些阈值是初始产品规则,仍需真实场景验证。
6. 显式纠正转为用户确认的信息,后续学习不能覆盖。忘记学习规律会删除其证据并保存无正文的规则排除键,阻止旧证据及后续相同规律重新出现。
## 6. 技术与可靠性取舍
最多保存 50 条记忆,其中自动推测最多 30 条,给明确偏好留出空间。每次消费最多 50 个审计事件,每事件最多提取少量规律;回顾最多 2,000 条近期证据。预算可能使繁忙账户延后处理,不能保证所有行为都学到。
### 复用已有能力
自动从自由对话提取偏好、抽象项目背景/关系建模、从接受建议中加权学习以及精确关联撤销操作,仍未实现。明确对话偏好可以通过“记住这句话”保存。猫爪自己的操作不用于正向强化,避免形成自我证明的循环。
保留 AI SDK `ToolLoopAgent` 和现有模型配置,由 EdgeEver 管理身份、记忆、权限、建议和执行记录。当前不引入 Mastra、ElizaOS、第二套数据库或自制通用 Agent/工作流框架。
## 5. 如何影响建议
工具名称和参数来自既有 MCP 目录,通过同一个业务执行器调用笔记服务;只增加 Agent 的开放策略、预览和确认适配。Cloudflare 与 Docker 共用业务逻辑。Agent 界面与服务端 AI 运行时按需加载,构建测试检查包括共享 chunk 在内的完整启动依赖链。
主动发现通过多个关键词检索相关旧笔记,结合近期记录选取最多六篇正文,总计 12,000 字符。仍以最近更新的一篇为当前线索,尚未实现多线索轮转。
当前不新增运行时依赖、常驻自治进程或捆绑本地模型。没有新增依赖不等于没有包体、内存、模型费用和维护成本;实际增量必须测量,不使用早期不可复现的框架对比数字作保证。
同一记忆选择模块供对话与发现复用:按有效状态、适用范围、关键词及时间召回,显式偏好优先于推测。最多八条、总计 4,000 字符;无关键词匹配时保留少量回退内容,不读取全库或训练模型。
### 曾参考的项目与未采用原因
模型收到选中笔记、相关记忆和已有笔记本。笔记、记忆都是不可信数据,不能改变权限或伪造确认。结构化结果返回笔记与记忆来源编号,服务端校验并保存准确操作方案;通知可显示采用的记忆。明确的“不再建议”规则同时在服务端过滤。
- [ElizaOS](https://github.com/elizaos/eliza):曾作为人格化、记忆与插件化 Agent 的参考。当前未采用,是因为 EdgeEver 已有笔记存储、插件和权限体系,接入另一套 Agent runtime 需要协调其记忆、状态与插件契约;这些适配成本尚未被当前的轻量发现和确认式整理需求证明合理。保留设计借鉴,不引入其运行时。
- [Mastra](https://github.com/mastra-ai/mastra):曾评估其 TypeScript Agent、记忆、工作流与人工审批能力。当前未采用,是因为模型接入、工具循环和笔记执行已有可复用基础,当前流程还不需要完整的工作流编排;引入框架仍需实现 EdgeEver 专属的权限、版本校验和记忆治理,暂不足以抵消新增依赖及集成维护成本。
输入指纹包含记忆和笔记本上下文,避免用旧偏好缓存结果。记忆版本变化即使没有笔记变化也可触发重新分析,并使旧上下文及待确认操作失效。确认执行仍重查权限、版本、来源和同步状态;已完成操作保留回执。
这是基于当前产品范围与既有架构的阶段性取舍,不是认定它们无法嵌入 Electron 或必然造成高资源占用。未来若需求超出现有方案的可维护范围,可重新评估,并以实际集成后的包体、内存和启动测量为依据。
## 6. 存储、删除与备份
### 有界成本
新增迁移 [0045](../migrations/0045_companion_learning.sql),不修改旧迁移:
- 主动检查仅在应用打开、可见、联网、无待同步改动且停止操作 3 分钟后进行。跨设备共享限频,每账户每 24 小时最多尝试一次,笔记无变化跳过;客户端完成一次检查后,若没有新的笔记或同步变化,本轮会话不再重复请求。它不是全天候后台服务。
- 每次从近期记录和关键词查询中选择少量笔记,最多六篇正文、总计 12,000 字符;一次结构化生成,最多 1,200 输出 token、60 秒取消,不自动重试模型请求。
- 完整对话有独立的工具调用、上下文、并发和超时预算;授权全库不等于把全库放进 Prompt。
- 按需选出的内容会发送给用户配置的默认模型服务商。没有生成可展示建议也可能产生费用。关键词召回可能漏掉语义关联,低频检查也不保证及时发现所有机会。
- 扩展 `companion_memories`:类型、范围、规则键、状态,保留原显式记忆及版本。
- 新增 `companion_memory_evidence` 和 `companion_memory_exclusions`,分别存储证据引用和排除键。
- 扩展发现设置:学习与使用开关、学习游标、最近分析记忆版本。
- 扩展发现类型约束,迁移原发现记录并增加使用的记忆 ID。
### Token 开销控制
记录按工作区和用户隔离。Cloudflare/D1 与 Docker/Bun SQLite 使用相同服务代码和 SQL。
- 主动发现保存最近一次成功分析的输入指纹。后续检查即使被无关的工作区变化触发,只要候选笔记、提示词、语言、设置、上下文及模型配置版本相同,就跳过模型调用;无建议的成功结果也计入。失败不缓存,清空历史会清除指纹;不会重放旧结果或恢复失效操作。
- 发送给模型的笔记 ID 换成当次有效的短编号,输出由服务端严格映射回真实 ID。正文保持完整,不靠截断整理来源来节省 Token。
- 对话只召回最多八条相关记忆,总正文预算从 8,000 降到 4,000 字符;没有关键词匹配时最多保留最近两条。不删除已存记忆,但可能漏掉相关的旧偏好,需通过真实场景验证取舍。
- 同一轮已完整读取的笔记,再次读取只返回引用提示,复用该轮上下文中的正文;仍检查权限及数据版本,不跨轮缓存。用户确认操作沿用已保存参数,不另调模型。
独立 JSON 导出升级至版本 2,保留记忆类型和学习控制项。兼容版本 1 导入;版本 2 导入恢复控制项,合并记忆,但推测不带入可信证据,作为候选等待用户确认。笔记本范围、规则排除键和证据不跨实例重建,导入不恢复聊天或执行记录。
这些优化复用现有 AI SDK,不改变默认模型、触发频率或确认权限。字符预算不是 Token 计量,实际费用取决于模型、语言和内容;不承诺固定节省比例。升级需应用 [0044 数据库迁移](../migrations/0044_companion_discovery_input_hash.sql),仅新增可空指纹字段,不修改笔记内容。
这些数据仍未纳入笔记 ZIP、桌面离线镜像或原生移动同步。删除笔记会撤销其学习证据,但不删除已有聊天快照;忘记不能删除用户导出文件或模型服务商留存。
### 确认与恢复
## 7. 运行与成本
1. 模型提出建议,服务端校验来源和参数;主动发现的合并/补入参数由服务端构造。保存准确操作、理由和数据版本,提议不修改笔记。
2. 用户确认绑定该份操作,执行时不再让模型重新决策。检查账户、有效期、来源版本和同步状态;建议过期或数据变化后需要重新生成。
3. 复用事务、执行占用和持久化记录,防止重复确认和覆盖并发改动。连接中断后恢复或查询结果,不把生成文本当作成功回执,也不盲目重跑不确定的写入。
4. 多批次操作可能部分完成;取消不自动回滚已发生的副作用。当前工作区游标策略较保守,无关笔记变化也可能使其他建议失效。
应用可见、联网、无待同步改动,停止操作三分钟后尝试检查。常规笔记变化每天最多检查一次;记忆变化可提前检查,最多每小时一次。按账户共享限频和并发占用。客户端不常驻轮询,持续没有新事件就不重复请求。规则学习不调用模型。
笔记、记忆、附件和工具结果都是不可信数据,不能改变身份、授予权限或伪造用户确认。不开放 Shell、电脑控制、自动对外发送或发布;不因为“熟悉用户”放宽授权。
每次发现最多一次结构化模型生成、1,200 输出 token、60 秒超时,不自动付费重试。选中笔记和相关记忆发送给默认模型服务商;无通知也可能产生费用。字符预算不是 token 计量,不承诺固定费用或节省比例。
## 7. 待验证事项与后续优先级
## 8. 验证与回滚
- 建立真实笔记场景集:判断是否属于同一想法、是否值得合并/补入、关联是否有用;评估误报、打扰、采纳率和错误整理风险,而不是通知数量或聊天时长。
- 验证真实模型的结构化输出、工具调用、取消、来源准确性及 Prompt 注入防护;模型不可用时不得影响正常笔记读写。
- 测量 Agent 关闭、空闲、首次运行、连续运行及取消后的安装包、冷启动、CPU、RSS/堆和模型费用;分别记录客户端与服务端,参照[桌面性能基线](desktop-performance-baseline.md)。
- 在现有场景质量可靠后,再验证记忆驱动的建议、主动标签整理以及对话与猫爪模式的权限一致性;不要把这些文档目标当作已经完成的功能。
- 补齐备份恢复、删除传播与跨端体验。自动化、提醒、多 Agent 和更重的检索基础设施不是当前默认范围;只有真实需求与测量证明必要时再评估。
验证覆盖批量/重复操作、关闭与重新启用、隔离、冲突、纠正、遗忘传播、候选导入、记忆触发发现、归档/标签确认及旧 SQLite 数据库重开升级。另在隔离的本地 D1 中应用旧迁移、写入旧数据、升级 0045,并检查保留数据和外键。
实现变更需通过相关测试、全量非 E2E 回归、`bun run typecheck`、`bun run typecheck:mobile` 和 `bun run build:web`。测试通过不等于建议质量或资源指标已达标。
必须运行全量非 E2E 测试、`bun run typecheck`、`bun run typecheck:mobile`、`bun run build:web`。浏览器验证使用 Codex 内置 Browser。
零新增依赖是当前策略,不是永久禁令。新增依赖必须说明用户收益、资源增量、维护成本和退出路径;不能为了保持“零依赖”而重新发明通用框架。
尚未验证:线上 D1 升级、真实用户长期建议质量、真实模型成本和原生移动端跨版本行为。不能据此声称“不影响现有用户”或“不影响自动升级”。
关闭学习可停止新证据处理;关闭记忆使用可让发现退回笔记上下文。数据库保持向前兼容字段,不用破坏性逆向迁移回滚;降级旧代码前应关闭猫爪,避免旧客户端处理新增发现类型。已确认笔记操作不因关闭或回滚而自动撤销。