AI conversations should be stored in OSIS (per-context, per-user, persistent) #45

Closed
opened 2026-03-19 00:24:10 +00:00 by mik-tf · 6 comments
Owner

Problem

AI conversations are stored in Shrimp's local SQLite (data/shrimp.db), not in OSIS. This means:

  • No per-context isolation (switching context doesn't scope conversations)
  • No per-user isolation (all users share one conversation history)
  • No persistence across container recreation (SQLite is ephemeral)
  • No sync/replication via Fossil/hero_db
  • No integration with OSIS search, embedder, or other data pipelines

Expected

Conversations should be stored in OSIS, likely in the ai or communication domain, scoped by context and user:

  • ai.conversation — conversation metadata (title, created_at, context)
  • ai.message — individual messages (role, content, timestamp, conversation_id)

Impact

This ties into the broader question of whether Shrimp (Bun/TypeScript) should be rewritten as a native Rust agent that integrates directly with the Hero ecosystem:

Current (Shrimp/Bun) Future (Rust agent)
Local SQLite OSIS domains (per-context, per-user)
Separate Bun runtime Native Rust binary, same as all other services
Child process MCP bridges Direct OSIS SDK calls
REST proxy to aibroker Direct provider API calls
No HeroRpcServer integration Full lifecycle, sockets, discovery
No Fossil sync Automatic replication

Approach Options

  1. Short-term: Add OSIS conversation storage to current Shrimp via MCP/RPC calls (moderate effort, keeps Bun)
  2. Long-term: Build a Rust AI agent (hero_agent) that uses OSIS SDK natively, replaces Shrimp gradually
  • #27 — HeroRpcServer unification (would apply to the Rust agent)
  • #36 — MCP architecture cleanup (already simplified)
  • #32 — SSE streaming (easier in Rust with native streaming)
## Problem AI conversations are stored in Shrimp's local SQLite (`data/shrimp.db`), not in OSIS. This means: - No per-context isolation (switching context doesn't scope conversations) - No per-user isolation (all users share one conversation history) - No persistence across container recreation (SQLite is ephemeral) - No sync/replication via Fossil/hero_db - No integration with OSIS search, embedder, or other data pipelines ## Expected Conversations should be stored in OSIS, likely in the `ai` or `communication` domain, scoped by context and user: - `ai.conversation` — conversation metadata (title, created_at, context) - `ai.message` — individual messages (role, content, timestamp, conversation_id) ## Impact This ties into the broader question of whether Shrimp (Bun/TypeScript) should be rewritten as a native Rust agent that integrates directly with the Hero ecosystem: | Current (Shrimp/Bun) | Future (Rust agent) | |---------------------|--------------------| | Local SQLite | OSIS domains (per-context, per-user) | | Separate Bun runtime | Native Rust binary, same as all other services | | Child process MCP bridges | Direct OSIS SDK calls | | REST proxy to aibroker | Direct provider API calls | | No HeroRpcServer integration | Full lifecycle, sockets, discovery | | No Fossil sync | Automatic replication | ## Approach Options 1. **Short-term**: Add OSIS conversation storage to current Shrimp via MCP/RPC calls (moderate effort, keeps Bun) 2. **Long-term**: Build a Rust AI agent (`hero_agent`) that uses OSIS SDK natively, replaces Shrimp gradually ## Related - #27 — HeroRpcServer unification (would apply to the Rust agent) - #36 — MCP architecture cleanup (already simplified) - #32 — SSE streaming (easier in Rust with native streaming)
Author
Owner

Decision: Enhance Shrimp, no Rust rewrite

Shrimp (Bun/TypeScript) stays as the AI agent. The approach for OSIS conversation storage:

  1. Add RPC calls from Shrimp to OSIS ai.conversation / ai.message domains
  2. Tag conversations with context name (passed from UI via context_name param)
  3. Replace local SQLite conversation storage with OSIS-backed storage
  4. Keep Shrimp's SQLite for ephemeral data (audit log, usage stats, tool cache)

Why not Rust: TypeScript is better for AI agent iteration speed — prompt engineering, tool development, LLM API integration. Shrimp works well, the gap is only storage integration.

Estimated effort: ~2-3 days

### Decision: Enhance Shrimp, no Rust rewrite Shrimp (Bun/TypeScript) stays as the AI agent. The approach for OSIS conversation storage: 1. Add RPC calls from Shrimp to OSIS `ai.conversation` / `ai.message` domains 2. Tag conversations with context name (passed from UI via `context_name` param) 3. Replace local SQLite conversation storage with OSIS-backed storage 4. Keep Shrimp's SQLite for ephemeral data (audit log, usage stats, tool cache) **Why not Rust**: TypeScript is better for AI agent iteration speed — prompt engineering, tool development, LLM API integration. Shrimp works well, the gap is only storage integration. **Estimated effort**: ~2-3 days
Author
Owner

Implementation Plan — Full OSIS Migration (no SQLite)

Drop SQLite entirely. Conversations stored in OSIS with real user identity.

Phase 1: OSIS Schema (hero_osis)

Create hero_osis/schemas/ai/conversation.oschema:

Conversation [rootobject] = {
    user_id: sid
    title: str
    context: str
    message_count: i32
    created_at: u64
    updated_at: u64
    is_archived: bool
    tags: [str]
}

ConversationMessage [rootobject] = {
    conversation_id: sid
    role: str
    content: str
    timestamp: u64
    channel: str
    tool_calls: str
    tool_call_id: str
}

Generates: types, CRUD, RPC methods, SDK client.

Phase 2: hero_agent Backend Migration

Remove: db.rs (SQLite), conversation.rs (SQLite wrapper), rusqlite dep

Add: OSIS client, conversation_osis.rs with list/get/create/save_message/load_history/delete/rename via OSIS RPC

Keep: All REST API endpoints unchanged — frontend doesn't know backend changed

Phase 3: User Identity

Replace hardcoded anonymous with real user from auth session token. All OSIS operations scoped to real user.

Phase 4: Data Migration

One-time script: SQLite conversations → OSIS objects. Then remove SQLite file.

Phase 5: Frontend Cleanup

Remove localStorage conversation tracking. Sidebar already uses /api/conversations — no UI changes needed.

Testing (7 layers)

  1. Unit: OSIS conversation CRUD
  2. Smoke: conversation API endpoints
  3. Integration: create → send message → list history → verify persistence
  4. E2E regression: sidebar, rename, delete
  5. E2E adversarial: delete active conversation, rapid create/delete
  6. Hero Browser MCP: sidebar renders, history persists across reload
  7. Remote: all above against herodev

Files

File Action
hero_osis/schemas/ai/conversation.oschema CREATE
hero_agent/src/db.rs DELETE
hero_agent/src/conversation.rs DELETE
hero_agent/src/conversation_osis.rs CREATE
hero_agent/src/agent.rs MODIFY
hero_agent_server/src/routes.rs MODIFY
hero_agent/Cargo.toml MODIFY
hero_services/tests/e2e/conversations.spec.ts CREATE

Signed-off-by: mik-tf

## Implementation Plan — Full OSIS Migration (no SQLite) Drop SQLite entirely. Conversations stored in OSIS with real user identity. ### Phase 1: OSIS Schema (hero_osis) Create `hero_osis/schemas/ai/conversation.oschema`: ``` Conversation [rootobject] = { user_id: sid title: str context: str message_count: i32 created_at: u64 updated_at: u64 is_archived: bool tags: [str] } ConversationMessage [rootobject] = { conversation_id: sid role: str content: str timestamp: u64 channel: str tool_calls: str tool_call_id: str } ``` Generates: types, CRUD, RPC methods, SDK client. ### Phase 2: hero_agent Backend Migration **Remove:** db.rs (SQLite), conversation.rs (SQLite wrapper), rusqlite dep **Add:** OSIS client, conversation_osis.rs with list/get/create/save_message/load_history/delete/rename via OSIS RPC **Keep:** All REST API endpoints unchanged — frontend doesn't know backend changed ### Phase 3: User Identity Replace hardcoded `anonymous` with real user from auth session token. All OSIS operations scoped to real user. ### Phase 4: Data Migration One-time script: SQLite conversations → OSIS objects. Then remove SQLite file. ### Phase 5: Frontend Cleanup Remove localStorage conversation tracking. Sidebar already uses /api/conversations — no UI changes needed. ### Testing (7 layers) 1. Unit: OSIS conversation CRUD 2. Smoke: conversation API endpoints 3. Integration: create → send message → list history → verify persistence 4. E2E regression: sidebar, rename, delete 5. E2E adversarial: delete active conversation, rapid create/delete 6. Hero Browser MCP: sidebar renders, history persists across reload 7. Remote: all above against herodev ### Files | File | Action | |------|--------| | hero_osis/schemas/ai/conversation.oschema | CREATE | | hero_agent/src/db.rs | DELETE | | hero_agent/src/conversation.rs | DELETE | | hero_agent/src/conversation_osis.rs | CREATE | | hero_agent/src/agent.rs | MODIFY | | hero_agent_server/src/routes.rs | MODIFY | | hero_agent/Cargo.toml | MODIFY | | hero_services/tests/e2e/conversations.spec.ts | CREATE | Signed-off-by: mik-tf
Author
Owner

Implementation Plan — Confirmed

Proceeding with the 5-phase plan. Key clarifications from code review:

Phase 1: OSIS Schema (hero_osis)

  • Create schemas/ai/conversation.oschema with AI-specific types
  • Not reusing communication/chat.oschema — that's for general messaging (DMs, groups, reactions). AI conversations need different fields: role, tool_calls, context, tool_call_id
  • Run OSIS codegen → generates types + client + server traits

Phase 2: Backend Migration (hero_agent)

  • Create conversation_osis.rs — wraps generated OSIS client
  • Modify agent.rs to use OSIS instead of SQLite ConversationStore
  • Modify routes.rs — same REST API surface, backend swap
  • Keep db.rs partially — audit_log, usage_log, memories stay in SQLite for now (tracked in #91)

Phase 3: User Identity

  • Extract real user from auth session token
  • Pass to all OSIS operations — no more hardcoded anonymous

Phase 4: Data Migration

  • One-time script: SQLite conversations + messages → OSIS objects
  • Remove conversation/message tables from SQLite schema

Phase 5: Frontend Cleanup

  • Remove localStorage conversation tracking
  • Sidebar already uses /api/conversations — no UI changes

Files

File Action
hero_osis/schemas/ai/conversation.oschema CREATE
hero_agent/crates/hero_agent/src/conversation_osis.rs CREATE
hero_agent/crates/hero_agent/src/conversation.rs DELETE
hero_agent/crates/hero_agent/src/db.rs MODIFY (remove conversation/message tables, keep audit/usage/memories)
hero_agent/crates/hero_agent/src/agent.rs MODIFY
hero_agent/crates/hero_agent_server/src/routes.rs MODIFY
hero_agent/crates/hero_agent/Cargo.toml MODIFY (add hero_osis_sdk)

What stays in SQLite (tracked separately)

  • audit_log — tool execution tracking
  • usage_log — token usage per model
  • memories — agent memory storage

These will be migrated in #91.

Signed-off-by: mik-tf

## Implementation Plan — Confirmed Proceeding with the 5-phase plan. Key clarifications from code review: ### Phase 1: OSIS Schema (hero_osis) - Create `schemas/ai/conversation.oschema` with AI-specific types - **Not reusing** `communication/chat.oschema` — that's for general messaging (DMs, groups, reactions). AI conversations need different fields: `role`, `tool_calls`, `context`, `tool_call_id` - Run OSIS codegen → generates types + client + server traits ### Phase 2: Backend Migration (hero_agent) - Create `conversation_osis.rs` — wraps generated OSIS client - Modify `agent.rs` to use OSIS instead of SQLite `ConversationStore` - Modify `routes.rs` — same REST API surface, backend swap - **Keep `db.rs` partially** — audit_log, usage_log, memories stay in SQLite for now (tracked in https://forge.ourworld.tf/lhumina_code/home/issues/91) ### Phase 3: User Identity - Extract real user from auth session token - Pass to all OSIS operations — no more hardcoded `anonymous` ### Phase 4: Data Migration - One-time script: SQLite conversations + messages → OSIS objects - Remove conversation/message tables from SQLite schema ### Phase 5: Frontend Cleanup - Remove localStorage conversation tracking - Sidebar already uses `/api/conversations` — no UI changes ### Files | File | Action | |------|--------| | `hero_osis/schemas/ai/conversation.oschema` | CREATE | | `hero_agent/crates/hero_agent/src/conversation_osis.rs` | CREATE | | `hero_agent/crates/hero_agent/src/conversation.rs` | DELETE | | `hero_agent/crates/hero_agent/src/db.rs` | MODIFY (remove conversation/message tables, keep audit/usage/memories) | | `hero_agent/crates/hero_agent/src/agent.rs` | MODIFY | | `hero_agent/crates/hero_agent_server/src/routes.rs` | MODIFY | | `hero_agent/crates/hero_agent/Cargo.toml` | MODIFY (add hero_osis_sdk) | ### What stays in SQLite (tracked separately) - `audit_log` — tool execution tracking - `usage_log` — token usage per model - `memories` — agent memory storage These will be migrated in https://forge.ourworld.tf/lhumina_code/home/issues/91. Signed-off-by: mik-tf
Author
Owner

Implementation Complete — Full OSIS Migration

All 5 SQLite tables migrated to OSIS. SQLite and rusqlite dependency removed entirely.

Changes by repo

hero_osis

  • NEW: schemas/ai/agent_data.oschema — 5 rootobjects: AgentConversation, AgentMessage, AgentMemory, AgentAuditEntry, AgentUsageEntry
  • MODIFIED: crates/hero_osis_server/src/ai/rpc.rs — added trigger stubs for all 5 new rootobjects
  • Codegen produces types, SDK client, server handlers automatically

hero_agent

  • NEW: crates/hero_agent/src/osis_store.rs — OSIS-backed store replacing SQLite, wraps AiClient CRUD operations
  • DELETED: crates/hero_agent/src/db.rs (711 lines, SQLite)
  • DELETED: crates/hero_agent/src/conversation.rs (90 lines, SQLite wrapper)
  • MODIFIED: crates/hero_agent/src/agent.rs — uses OsisStore instead of Database + ConversationStore
  • MODIFIED: crates/hero_agent/src/memory.rs — async OSIS-backed MemoryStore
  • MODIFIED: crates/hero_agent/src/auto_memory.rs — async memory save
  • MODIFIED: crates/hero_agent/src/channels/cli.rs — uses store.clear_conversation()
  • MODIFIED: crates/hero_agent/src/channels/telegram.rs — uses store.clear_conversation()
  • MODIFIED: crates/hero_agent/src/lib.rs — replaced db + conversation modules with osis_store
  • MODIFIED: crates/hero_agent/Cargo.tomlrusqlite removed, hero_osis_sdk added
  • MODIFIED: crates/hero_agent_server/src/main.rsOsisStore::new() replaces Database::open()
  • MODIFIED: crates/hero_agent_server/src/routes.rs — all 12+ route handlers migrated to async OSIS calls
  • MODIFIED: Cargo.toml (workspace) — removed rusqlite, added hero_osis_sdk

hero_services

  • MODIFIED: docker/cargo-server-patches.toml — added hero_osis_sdk patch for Docker builds

API Surface

All REST endpoints unchanged — frontend needs zero changes:

  • GET/POST /api/conversations
  • GET/DELETE/PATCH /api/conversations/{id}
  • GET /api/conversations/{id}/messages
  • GET /api/stats, /api/audit, /api/usage, /api/memories
  • POST /api/chat, /api/voice/chat

Configuration

New env vars for OSIS connection:

  • OSIS_URL (default: http://127.0.0.1:9999/hero_osis)
  • OSIS_CONTEXT (default: default)

What was removed

  • rusqlite crate (no more SQLite dependency)
  • hero_agent.db file (no more SQLite database)
  • All SQL queries, migrations, WAL/pragma setup

This also completes #91 — all 5 tables (conversations, messages, audit_log, usage_log, memories) are now in OSIS.

Signed-off-by: mik-tf

## Implementation Complete — Full OSIS Migration All 5 SQLite tables migrated to OSIS. SQLite and `rusqlite` dependency removed entirely. ### Changes by repo #### hero_osis - **NEW**: `schemas/ai/agent_data.oschema` — 5 rootobjects: `AgentConversation`, `AgentMessage`, `AgentMemory`, `AgentAuditEntry`, `AgentUsageEntry` - **MODIFIED**: `crates/hero_osis_server/src/ai/rpc.rs` — added trigger stubs for all 5 new rootobjects - Codegen produces types, SDK client, server handlers automatically #### hero_agent - **NEW**: `crates/hero_agent/src/osis_store.rs` — OSIS-backed store replacing SQLite, wraps AiClient CRUD operations - **DELETED**: `crates/hero_agent/src/db.rs` (711 lines, SQLite) - **DELETED**: `crates/hero_agent/src/conversation.rs` (90 lines, SQLite wrapper) - **MODIFIED**: `crates/hero_agent/src/agent.rs` — uses `OsisStore` instead of `Database` + `ConversationStore` - **MODIFIED**: `crates/hero_agent/src/memory.rs` — async OSIS-backed `MemoryStore` - **MODIFIED**: `crates/hero_agent/src/auto_memory.rs` — async memory save - **MODIFIED**: `crates/hero_agent/src/channels/cli.rs` — uses `store.clear_conversation()` - **MODIFIED**: `crates/hero_agent/src/channels/telegram.rs` — uses `store.clear_conversation()` - **MODIFIED**: `crates/hero_agent/src/lib.rs` — replaced `db` + `conversation` modules with `osis_store` - **MODIFIED**: `crates/hero_agent/Cargo.toml` — `rusqlite` removed, `hero_osis_sdk` added - **MODIFIED**: `crates/hero_agent_server/src/main.rs` — `OsisStore::new()` replaces `Database::open()` - **MODIFIED**: `crates/hero_agent_server/src/routes.rs` — all 12+ route handlers migrated to async OSIS calls - **MODIFIED**: `Cargo.toml` (workspace) — removed `rusqlite`, added `hero_osis_sdk` #### hero_services - **MODIFIED**: `docker/cargo-server-patches.toml` — added `hero_osis_sdk` patch for Docker builds ### API Surface All REST endpoints unchanged — frontend needs zero changes: - `GET/POST /api/conversations` - `GET/DELETE/PATCH /api/conversations/{id}` - `GET /api/conversations/{id}/messages` - `GET /api/stats`, `/api/audit`, `/api/usage`, `/api/memories` - `POST /api/chat`, `/api/voice/chat` ### Configuration New env vars for OSIS connection: - `OSIS_URL` (default: `http://127.0.0.1:9999/hero_osis`) - `OSIS_CONTEXT` (default: `default`) ### What was removed - `rusqlite` crate (no more SQLite dependency) - `hero_agent.db` file (no more SQLite database) - All SQL queries, migrations, WAL/pragma setup This also completes https://forge.ourworld.tf/lhumina_code/home/issues/91 — all 5 tables (conversations, messages, audit_log, usage_log, memories) are now in OSIS. Signed-off-by: mik-tf
Author
Owner

Testing Complete

Build

  • make dist-quick22/22 succeeded, 0 failed
  • TAG=local make pack — image built successfully

Smoke tests (layer 2)

  • 119 passed, 2 failed, 3 skipped / 124 total
  • All OSIS data endpoints pass: stats, audit, usage, memories, conversations
  • Full conversation CRUD cycle passes: create → get → rename → delete
  • 2 pre-existing failures: hero_whiteboard_ui status-dot (unrelated)

Integration tests (layer 3)

  • 18 passed, 2 failed / 20 total
  • OSIS conversation persistence verified (conversation_id returned from OSIS)
  • 2 pre-existing failures: LLM round-trip (aibroker config), voice transcription (Groq 400)

OSIS migration verified

  • Conversation created via OSIS → returned id 0006
  • Chat endpoint uses OSIS-persisted conversation
  • All data endpoints (stats, audit, usage, memories) return valid JSON
  • Full CRUD cycle on conversations works

Repos ready for squash merge

Repo Branch Commits
hero_osis development_mik 2 (schema + regen)
hero_agent development_mik 3 (migration + patch fix + URL fix)
hero_services development_mik 2 (server patches + smoke tests)
hero_biz development_mik 1 (patch fix)

Signed-off-by: mik-tf

## Testing Complete ### Build - `make dist-quick` — **22/22 succeeded, 0 failed** - `TAG=local make pack` — image built successfully ### Smoke tests (layer 2) - **119 passed, 2 failed, 3 skipped / 124 total** - All OSIS data endpoints pass: stats, audit, usage, memories, conversations - Full conversation CRUD cycle passes: create → get → rename → delete - 2 pre-existing failures: hero_whiteboard_ui status-dot (unrelated) ### Integration tests (layer 3) - **18 passed, 2 failed / 20 total** - OSIS conversation persistence verified (conversation_id returned from OSIS) - 2 pre-existing failures: LLM round-trip (aibroker config), voice transcription (Groq 400) ### OSIS migration verified - Conversation created via OSIS → returned id `0006` - Chat endpoint uses OSIS-persisted conversation - All data endpoints (stats, audit, usage, memories) return valid JSON - Full CRUD cycle on conversations works ### Repos ready for squash merge | Repo | Branch | Commits | |------|--------|---------| | hero_osis | development_mik | 2 (schema + regen) | | hero_agent | development_mik | 3 (migration + patch fix + URL fix) | | hero_services | development_mik | 2 (server patches + smoke tests) | | hero_biz | development_mik | 1 (patch fix) | Signed-off-by: mik-tf
Author
Owner

Deferred: User Identity (Phase 3)

Phase 3 (replace hardcoded "anonymous" with real auth user) was deferred to #92 — requires auth middleware design work.

All other phases (1-2, 4-5) completed. v0.7.2-dev deployed and verified.

Signed-off-by: mik-tf

## Deferred: User Identity (Phase 3) Phase 3 (replace hardcoded "anonymous" with real auth user) was deferred to https://forge.ourworld.tf/lhumina_code/home/issues/92 — requires auth middleware design work. All other phases (1-2, 4-5) completed. v0.7.2-dev deployed and verified. Signed-off-by: mik-tf
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/home#45
No description provided.