Skip to main content
Tuturuuu AI memory is backed by an internal Postgres/pgvector sidecar through the server-only @tuturuuu/ai/memory boundary. Product routes must not call the sidecar from the browser and must not create product-specific memory stores.

Scope

Memory scope is always user + workspace. The shared helper builds a stable container tag from those two identifiers and stores product, surface, route, locale, timezone, conversation, and workspace metadata on each write. Default recall is cross-product within that user + workspace container. Use metadata filters only when a route needs a narrower product or surface view.

Runtime

Use withAiMemory for AI SDK calls when the route has a user and workspace. Use ingestAiMemoryEvent, buildAiMemoryContext, and the Mira-compatible tool executors for explicit memory reads and writes. Reads fail open by default, and writes are best effort. Every embedding used for memory add/search is generated through the metered @tuturuuu/ai embedding helper before the sidecar is called. If credits, pricing, token counting, or billable attribution cannot be verified, the memory operation skips before calling Google. Structural metering failures disable memory for the user scope. Keep SUPERMEMORY_FAIL_OPEN=true unless a product explicitly requires strict persistence. Required server-side env:
For Docker blue/green and watcher deployments, the Docker helper auto-generates and injects the internal API key, bundled Postgres password, database URL, internal base URL, fail-open setting, and timeout. Use DOCKER_SUPERMEMORY_API_KEY, DOCKER_SUPERMEMORY_POSTGRES_PASSWORD, DOCKER_SUPERMEMORY_DATABASE_URL, or DOCKER_SUPERMEMORY_ENABLED=false only when an operator needs to override that generated runtime. An explicit false value also removes the sidecar from Docker blue/green support builds and health gates. SUPERMEMORY_API_KEY is internal infrastructure configuration. Never expose it through browser-visible env vars or client responses.

User Controls

Workspace settings live behind:
These first-class API handlers forward the incoming request to authentication, so mobile Bearer credentials and browser cookies use the same current-user and MEMBER workspace checks. Export and deletion remain available while collection is disabled; that does not enable collection or authorize another actor. The settings dialog exposes enable/disable, product toggles, search/list, delete, and export controls. API routes call private schema RPCs through the server-side Supabase admin client.

Migration

Legacy mira_memories rows are imported with the admin-only backfill endpoint:
Backfill is idempotent through stable customId values. Rows without a legacy workspace are imported into the user’s default or personal workspace and tagged with legacy_mira metadata.

Self-Hosting

The Docker fleet runs the first-party memory sidecar as an internal support service named supermemory for compatibility with existing base URL, API key, watcher, and Compose wiring. The sidecar stores 3072-dimensional gemini-embedding-2 vectors in extensions.halfvec(3072) with HNSW cosine indexes, plus GIN indexes for metadata and full-text hybrid search. The supermemory-db-migrate service applies apps/supermemory/db schema changes before the runtime starts. The watcher and cron recovery path use the same generated Docker env, so recreating web-blue-green-watcher does not require manually exporting memory service secrets. There is no SUPERMEMORY_IMAGE enterprise-image contract. Connectors such as Google Drive, OneDrive, and Notion are disabled for the first rollout. Product ingestion should persist concise summaries only; do not ingest raw files or binaries unless the source is user-owned, enabled, and explicitly appropriate for memory.

Mobile Assistant Settings

The mobile Assistant settings hub separates personal assistant identity from workspace memory. Name, tone, personality, and boundaries update the current user’s existing Mira soul. Memory controls address that user’s current workspace and list Mira memories only. Opening settings never changes consent. The global memory toggle preserves all existing product overrides; an existing disabled Mira override remains visible rather than implying that the global toggle enables Mira. An unavailable consent read is shown as unavailable, with retry, rather than inventing an enabled or disabled state. Memory viewing, confirmed deletion, and explicit export use the existing internal API. A row disappears only after the server confirms deletion. Export is shared only after the request completes within the same authorized settings scope. These controls create no offline privacy replay or separate memory store. Meet’s separate opt-in memory remains independent. Central Settings and the Assistant settings action open the same settings hub. Personality opens a dedicated page listing Assistant name, Tone, Response length, Personality, and Boundaries. Each row opens its own settings editor; saving updates that field against the latest confirmed personal soul and returns to Personality. Failed saves retain the draft for an explicit retry. Existing custom tone and response-detail values remain selectable. These pages and individual memory editors share the hub’s single title and floating back action, with scrollable content and the frame kept above the keyboard. System back and dock back return one level without submitting an edit. Opening a memory row reads its canonical content and revision through the existing Mira memory API. Saving uses that revision; a conflict retains the draft and requires reviewing the latest version before explicitly saving again. A confirmed receipt updates the list. An audit warning keeps the editor open, says the change is saved, and disables resubmitting the same content. Editors cancel on account or workspace transitions, including switching away and back during a pending read, review, or save. They never approximate editing by deleting and recreating a memory, and do not change collection consent. Settings retain prior confirmed values when a write fails and expose a localized retryable error. Account or workspace changes invalidate delayed reads, writes, and exports. Returning from settings refreshes the assistant soul from the server; request generations and the page’s actor epoch prevent older responses and account/workspace ABA transitions from replacing the current assistant identity. Regression coverage lives in assistant_personal_settings_repository_test.dart, assistant_personal_settings_cubit_test.dart, assistant_personal_settings_section_test.dart, assistant_routed_editors_test.dart, assistant_personality_route_scope_test.dart, assistant_memory_editor_section_test.dart, assistant_memory_editor_scope_test.dart, settings_assistant_entrypoint_checks.dart, and assistant_soul_refresh_test.dart. These tests cover API receipts, product preservation, delayed scope changes, English/Vietnamese controls, and large text with a visible keyboard; they do not establish native-device or deployed runtime proof.

Consolidating Mira memories

The merge_memories tool preserves source memories until the sidecar confirms that the replacement has persisted (done with a memory ID). Skipped, queued, missing, or failed replacement receipts never authorize original deletion. A successful replacement does not imply that every deletion succeeded: the result includes its replacement ID/key, confirmed deleted keys, and retained keys. Retry only retained keys; never claim the whole merge completed when any deletion remains unconfirmed. Duplicate source keys are processed once, and the replacement key is never deleted. This rule applies to Mira’s existing user/workspace memory tool. It does not admit background consolidation or combine Meet’s separately opted-in private Live memory with workspace memory. Regression coverage lives in packages/ai/src/tools/executors/memory.test.ts.

Settings lookup failures

Consent-checked memory operations deny admission when the current user/workspace/product settings RPC reports an error or throws. No metered embedding or sidecar read/write starts from that failed lookup. Existing separately authorized memory-management routes that explicitly bypass collection settings retain their current permissions; the repair does not change that management exception. A successful lookup with no settings row retains the existing enabled defaults; explicit disabled global or product settings still deny admission. This distinction changes outage behavior, not the existing missing-row consent policy. It does not introduce consent for background dreaming or merge Meet’s separately opted-in memory. The failure path returns a skipped memory operation so an optional memory outage does not make the surrounding chat depend on embedding or storage availability. Regression coverage in packages/ai/src/memory/operations-consent.test.ts uses the real settings/admission flow with synthetic RPC error and exception boundaries, asserting no embedding or sidecar access. Positive missing-row and disabled/product cases distinguish this rule from a blanket change to successful lookups.

In-place edit foundation

The private first-party sidecar exposes scoped read and revision-CAS update primitives for existing active memories. The service must have an API key configured for these new surfaces. Every read/update matches the memory ID, container, metadata user, workspace, product, and done status. This foundation alone does not expose a web/mobile editing API or a new assistant tool. The opaque revision is computed in PostgreSQL from the full-precision timestamp and stored content/metadata plus the PostgreSQL tuple version, before JavaScript can round timestamp precision. The tuple component fences same-content updates within one transaction. PostgreSQL documents that the tuple version changes on update or VACUUM FULL; table maintenance can require a fresh scoped read even when content is unchanged; it does not change the logical memory ID. It is a concurrency token, not an authorization token. Updates replace text and its fresh 3072-dimensional vector atomically, clear the old derived summary, and preserve the ID, original custom ID, creation time and provenance metadata. Forgotten memories are never revived. A stale update receives a conflict instead of overwriting the winner. The service operation preflights ownership and revision before metered embedding. Default operation admission still honors memory collection settings; the existing explicit management exception must be passed deliberately by an authorized future API. A stale preflight starts no embedding. Another edit or deletion can win while embedding is underway: that CAS conflict may occur after credits were used. Retrying the same stale revision is rejected before another embedding, but there is no persistent idempotency key or guarantee of idempotent charging. Do not retry using a newly loaded revision without reviewing the current content. Regression coverage uses the actual sidecar route and emitted parameterized SQL with a synthetic database boundary, plus operation/client tests with synthetic network and embedding boundaries. This is source evidence, not live PostgreSQL, provider, deployment or device proof. Proper edit-audit recording and the public API/mobile editor remain dependent packets; no existing audit action is relabeled and no background dreaming is dispatched.

Authenticated in-place editing

The live workspace memory item route provides GET/HEAD for an uncached id, content, and opaque revision projection, and PATCH for a strict value/revision body with the product in the query. Bearer and cookie sessions both resolve the current actor, normalized workspace, and MEMBER admission before private memory access. Another actor’s memory is unavailable; unknown products are rejected rather than silently mapped to a different product. Explicit owner editing remains available when automatic memory collection is disabled, matching manual creation/deletion. This exception does not authorize background consolidation or automatic dreaming. A stale revision returns 409; callers preserve unsaved text and reread the current revision before retrying. Embedding may already be metered when a concurrent edit wins the final CAS. Confirmed edits record the distinct edit audit action with revision-only metadata, never memory content or private provenance. If audit recording fails after the durable edit, the response remains updated: true with auditRecorded: false and warning: "audit_failed"; callers must not treat it as a rolled-back edit or repeat the mutation. A missing audit receipt also counts as an audit failure. GET responses do not expose source metadata or custom IDs. Regression coverage: the item route and internal API client tests cover admission, validation, conflicts, safe projections, and partial audit receipts. The ai-memory-edit-audit.sql pgTAP fixture exercises the actual audit RPC and CHECK, prior actions, membership and service-only access; the existing Programming database contract workflow runs it after complete schema replay. Local wiring checks are not PostgreSQL execution proof. Exact-head CI schema replay, typegen, and web build remain required; the mobile editor is a separate dependent packet.

Mobile memory editor

Mira’s Assistant Settings memory list opens a dedicated settings page with keyboard-safe scrollable content and the shared title and floating back action. Opening an item reads canonical content and its current opaque revision; the list preview is not the mutation source of truth. Editing preserves the original ID and uses the scoped PATCH route, without delete-and-create replacement. Manual editing does not enable automatic collection or expand Meet memory scope. A conflict preserves the draft and requires a successful reread of the saved version before an explicit retry. Permission and missing-item failures remain visible. A confirmed save with an unconfirmed audit record stays open with a warning and does not resubmit the unchanged content. Text typed while a save is pending remains editable against the returned revision. Closing the editor does not promise cancellation of an already admitted server write. Account/workspace changes cancel the route, including a switch away and back. Once its route is dismissed, a late response cannot update the list or pop the underlying page. Confirmed list updates preserve newer consent/personality state and fence older list reads. Regression tests cover these held-response boundaries, conflict review, audit warnings, English/Vietnamese labels, enlarged text and 48-pixel actions. Actual native paste gestures run through the global keyboard wrapper on Android/iOS widget targets; these are not physical-device proof.