Files
MyAiDesk/nomifun-tauri/docs/guides/companions.md
T
freedak f7a720204a Update: 将子项目从 submodule 转为完整内容
- 移除 GovAI, nomifun-tauri, 算力盒子 的 submodule 引用
- 添加所有子项目的完整源代码
- 保留原始 .git 为 .git.bak 备份
2026-07-04 19:20:46 +08:00

14 KiB

Companions

Nomi's virtual companion has grown from "a single nomi" into a multi-companion family: you can create several companions, use them side by side, raise them separately, and give each its own name, character, persona, and chat model. Each companion can also be bound to its own dedicated knowledge bases (turning it into a finance companion, a literature companion, a coding companion, …), while every companion shares one memory hub — collection and learning run as a single global pipeline, so whatever one companion learns, the whole family remembers. Memories, companions, and knowledge bases can each be packed into a .zip bundle for export/import, making machine-to-machine migration painless.

The entry point is the Desktop Companion page in the sidebar (the /nomi route); the right-click menu of any desktop companion window ("Open chat") deep-links there too.

Page layout: companion switcher + two tab domains

The top of the Desktop Companion page is the companion switcher bar: one card per companion (character thumbnail + name + level) plus a New companion button. The selected companion drives the companion-domain tabs below; everything that is global lives in the shared-domain tabs:

Domain Tab Contents
Companion domain (follows the switcher) Overview Desktop-companion toggle + that companion's level / XP / mood + shared stats
Chat That companion's own companion threads
Model & Knowledge Chat model picker / knowledge bindings
Remote That companion's IM bots (bound per companion — see the channels guide)
Settings Name / character / persona / quiet hours / delete companion
Shared domain (one per install) Memories · Collect · Learn · Suggestions The shared memory hub (one copy for all companions)
Migrate Export / import migration bundles (see below)

Creating and managing companions

  1. Click New companion on the switcher bar, pick a name and one of the six characters (mochi / ink / roux / pixel / bolt / boo).
  2. The first companion automatically becomes the default companion (its card carries a "default" badge). The default companion is the fallback whenever a channel has no explicit binding (see the channels section below).
  3. In a companion's Settings tab you can rename it at any time (takes effect immediately), swap the character, tune the persona (preset or custom), pick a chat model just for this companion, and toggle the desktop companion plus its quiet hours.
  4. Deleting a companion cascades: its companion conversations, runtime state (XP, …), and ('companion', companionId) knowledge bindings are removed together; if you delete the default companion, the default role moves on to the next one. Deleting down to zero companions is allowed (the shared memory hub exists independently of companions — collection and learning keep running).

On disk each companion is a directory — {data_dir}/companion/companions/{companion_id}/config.json, the directory is the source of truth — which is also the unit the companion bundle exports and imports.

Multiple desktop companions on screen

Every companion with the desktop-companion switch enabled gets its own desktop window (transparent, always-on-top, draggable; window label companion-{companionId}). Several can share the screen; keeping it to 5 or fewer is recommended (each window is an independent WebView instance — the UI warns about performance beyond that but does not enforce a limit). Right-click any desktop companion to jump straight to its chat.

The shared memory hub

All companions share one set of memory facilities under {data_dir}/companion/shared/:

  • Collection — a single pipeline subscribes to the global event bus, gathers your working data according to the collect switches, and writes shared/events/YYYYMMDD.jsonl.
  • Learning — a single learner incrementally distills events into long-term memories on the configured interval, stored in shared/memory.db. The learning pipeline uses the learn model from the shared config (independent of each companion's chat model — one pipeline, one budget).
  • Memories saved during any companion's chat, and memories produced by learning, are visible to every companion — switch companions mid-stream and the new one remembers everything that happened before.

XP and mood attribution

Source Credited to
Learning-run output (scored by events processed + new memories) All companions (the family grows together)
Suggestion adopted (+20) All companions
Companion chat turn (+2) Only the companion in that conversation
Memory saved during chat (+5) Only that companion

Mood is global: it is produced by learning runs and stored in shared state, so all companions share one mood (per-companion mood/personality divergence is reserved for a later version).

Binding knowledge bases to a companion

In a companion's Model & Knowledge tab → Knowledge section, use the binding control to mount one or more knowledge bases on that companion (the binding is ('companion', companionId)). Scope of effect:

  • The companion's companion chats and the channel conversations it greets (conversations carrying extra.companionId) mount that companion's bound knowledge bases — searchable during the conversation. Regular conversations without a companionId keep their conversation-level bindings; the two are not merged.
  • What the agent sees: bases are mounted at {workspace}/.nomi/knowledge/, and the injected context carries, per base, the description + an AI digest + "when to consult" hints + a budgeted table of contents (20 entries per base / 60 global, directories aggregated beyond that), plus an explicit retrieval protocol — the agent is told to look things up rather than answer from memory.
  • Write-back comes in two modes, briefly:
    • staged — knowledge produced during a conversation first lands in the base's _inbox/ (isolated per conversation) for you to review on the knowledge page before it is committed;
    • direct — skips staging and writes straight into the base.
  • AI bootstrap: the AI generate button on the knowledge page (list edit modal and detail page) calls POST /api/knowledge/bases/{id}/autogen to produce the base's description and README.md; a .zip import auto-fills an empty description. Requires a configured AI provider (409 otherwise).
  • URL sources: a base can be created from up to 16 URLs. snapshot mode fetches them at creation, converts each page to markdown under the base's snapshots/ (pages over 32 KB are AI-compressed) and auto-generates the digest — refreshable from the detail page; live mode lets the agent fetch at runtime (engines without a web tool can call the gateway tool nomi_knowledge_fetch_url). Only public http/https URLs are accepted (SSRF guard).
  • The companion can also grow its own libraries: the Desktop Gateway ships seven knowledge tools (list / bindings / create / write / autogen / fetch-url), and knowledge-deposit tips are built into the companion's system prompt — a companion or channel chat can create a base and distill notes into it unprompted. When nomi_knowledge_create_base is called with urls, the fetching runs as a background job — the tool returns immediately, so the agent must not create the base again just because the snapshots haven't appeared yet; once the base's description shows up, the fetch + digest pipeline has finished.

Bind different bases to different companions and you get a "finance companion", a "literature companion", a "coding companion" — persona, model, and knowledge are all per-companion, while memory stays shared.

Binding a companion to a channel

Each IM platform (Telegram / Lark / DingTalk / WeChat) can bind its own greeter companion for remote messages: open the companion's Remote tab (/nomi?companion=<id>&tab=remote) and connect or rebind the bot there. The binding is still persisted as assistant.{platform}.companionId for legacy platform-level preferences when a channel row has no direct companion binding. With no binding the default companion takes over; switching the binding resets that channel's active sessions (the next message is greeted by the new companion); if a bound companion is deleted, the platform falls back to the default companion and the sessions are likewise reset. See the "Master Agent mode" section of the Channels guide.

A companionId grants no permissions (memory is shared anyway): it only selects persona / model / knowledge mounts — unlike the desktopGateway marker, which grants gateway tools.

Export / import: migrating between machines

The shared-domain Migrate tab offers three kinds of .zip bundles (the migration UI is desktop-only; paths are picked with the system dialog):

Bundle Contents Import semantics
Memory bundle All long-term memories + learning history + mood; optionally the raw event data (checkbox) Merged with dedup into local memories (original timestamps and sources preserved)
Companion bundle One companion's persona / character / settings / XP + the name list of its bound knowledge bases (knowledge_refs) Creates a new companion under a fresh id, name conflicts get a "(2)" suffix; knowledge refs are matched by name against local bases to rebuild bindings — unmatched names are listed so you can import those knowledge bundles first and bind manually
Knowledge-base bundle Base metadata + the md file tree verbatim Lands as a new knowledge base, name conflicts get "(2)"

Migration steps:

  1. Old machine: export the memory bundle (tick events only if you want them) → export a companion bundle per companion → export a knowledge-base bundle per base.
  2. New machine: import the knowledge-base bundles first (so companion bundles can rebuild bindings by name) → then the companion bundles → then the memory bundle.
  3. Check each companion's model setting: model config travels verbatim in the bundle, but if the new machine has no matching provider it shows as unconfigured — re-select in settings.

Privacy boundaries

  • events/*.jsonl is raw collected data containing your working content verbatim — it is not exported by default; it only enters the memory bundle when you explicitly tick "include raw event data".
  • Chat history does not travel with the companion bundle: companion conversation logs live in the main database; the companion bundle carries only persona and settings. Chat logs stay on the original machine.

Automatic migration of legacy data

After upgrading from the single-companion version, the first boot detects the legacy layout {data_dir}/companion/nomi/: if it exists and companion/shared/ does not, it is automatically migrated into the shared memory hub plus a first companion (default name "Nomi", inheriting the existing XP / persona / character / model / desktop-companion position / companion threads). The migration is idempotent and re-entrant; on completion a .migrated marker is written into the legacy directory, which is kept around (to be cleaned up after one release cycle). No manual action is needed.

Manual walkthrough checklist

To verify a multi-companion setup end to end, walk through in order:

  1. Create two companions: create companions A and B, rename them, change characters; confirm the first one carries the "default" badge.
  2. Bind one base each: bind knowledge base X to A and Y to B (companion Model & Knowledge tab → Knowledge).
  3. Retrieval isolation: in A's and B's chats, ask about content that only exists in X / Y respectively; confirm A only hits X and B only hits Y.
  4. Shared memory round-trip: in A's chat, have it remember something (save a memory); switch to B's chat and ask — confirm B knows it.
  5. Export/import roundtrip: export the memory bundle + A's companion bundle + base X's bundle; (on a new machine or after a wipe) import in the order knowledge base → companion → memory; confirm the rebuilt A has its binding restored automatically and memories merge without duplicates.
  6. Channel companion switch: on some channel platform, switch the greeter companion from A to B; confirm the active sessions are reset and the next remote message is greeted with B's persona and B's knowledge mounts.

Routes & API

What Where
List / create companions GET/POST /api/companion/companions
Companion detail / update / delete GET/PATCH/DELETE /api/companion/companions/{companionId}
Shared config (collect / learn / default companion) GET/PATCH /api/companion/config
Per-companion companion threads GET /api/companion/companions/{companionId}/companion/threads, …/companion/active
Export memory bundle POST /api/companion/export/memory ({dest_path, include_events})
Export companion bundle POST /api/companion/export/companions/{companionId}
Import memory / companion bundle POST /api/companion/import (dispatched by manifest.kind)
Export / import knowledge-base bundle POST /api/knowledge/bases/{id}/export, POST /api/knowledge/bases/import
Bind a companion to a channel POST /api/channel/settings/companion
  • Channels — channel Master Agent mode and per-platform companion binding.
  • Data and Storage — the companion/ data directory layout.