Skip to content

feat(memory): system-wide memory model; drop per-agent model (#580)#584

Merged
jaylfc merged 2 commits into
devfrom
feat/memory-model-systemwide
Jun 4, 2026
Merged

feat(memory): system-wide memory model; drop per-agent model (#580)#584
jaylfc merged 2 commits into
devfrom
feat/memory-model-systemwide

Conversation

@jaylfc
Copy link
Copy Markdown
Owner

@jaylfc jaylfc commented Jun 4, 2026

Completes the memory-model move (taOS#580). Pairs with taOSmd#82 (shipped): taosmd.get_memory_model() / set_memory_model(model, clear=False).

What

The memory/Librarian model is now a single system-wide setting (managed in the Memory app), not per-agent. Memory is shared infrastructure, so its model is a quality/infra choice — distinct from each agent's per-agent chat model.

  • Backend (routes/librarian.py): GET/PUT /api/memory/model calling taOSmd's global getter/setter, guarded with getattr so an older taosmd degrades gracefully (supported:false / 501) instead of crashing. Removed model/clear_model from LibrarianPatch and stopped forwarding them (taOSmd dropped per-agent model).
  • Frontend: removed the per-agent model <select> from the agent's Memory tab (Enable Librarian / tasks / fanout stay per-agent). Added a single Memory model control to the Memory app settings (MemorySettings.tsx) — shows the current model or "Built-in default", with a picker (reusing ModelPickerModal) and a "use built-in default" action. New memory-api.ts helpers.

Model id format is provider:model (e.g. ollama:qwen3:4b); null = built-in default.

Tests

tests/test_memory_model.py (8: GET model/null/unsupported, PUT set/clear/400/501), test_librarian_api.py updated (model no longer forwarded), MemoryApp.test.tsx (4). Full vitest 973 pass; npm run build clean.

Summary by CodeRabbit

  • New Features

    • System-wide memory model section added to settings — view, select, change, or clear the memory model; shows “not supported” or “Built-in default” when applicable. Updates require admin privileges.
  • Refactor

    • Librarian model selector removed from the librarian controls; librarian advanced controls remain under “Show advanced…”
  • Tests

    • Added UI and API tests covering memory model display, selection, clearing, and server endpoints.

…ent model (#580)

The memory/Librarian model is now a single system-wide setting (taOSmd's
get_memory_model/set_memory_model), managed in the Memory app. Remove the
per-agent model dropdown from agent Memory settings (enable/tasks/fanout stay
per-agent) and stop forwarding the dropped per-agent model to taOSmd.

- GET/PUT /api/memory/model (guarded for older taosmd without the API).
- Memory app gains a single Memory-model picker + 'use built-in default'.
- MemoryTab loses the per-agent model select; LibrarianPatch drops model/clear_model.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 4, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a0e3d3ed-9578-45be-9433-397107226715

📥 Commits

Reviewing files that changed from the base of the PR and between a6e5132 and 15f7402.

📒 Files selected for processing (2)
  • tests/test_memory_model.py
  • tinyagentos/routes/librarian.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/test_memory_model.py
  • tinyagentos/routes/librarian.py

📝 Walkthrough

Walkthrough

Adds system-wide memory model support: new GET/PUT /api/memory/model endpoints and schemas, backend tests, a frontend client module and MemoryModelSection UI placed in MemorySettings, removal of the per-agent librarian model selector, and matching frontend tests.

Changes

Memory Model System-Wide Configuration

Layer / File(s) Summary
Backend memory model API contract and endpoints
tinyagentos/routes/librarian.py
Adds taosmd import, updates LibrarianPatch, adds MemoryModelUpdate, refactors PATCH handler, and implements GET and PUT /api/memory/model with capability detection, validation, admin gating, and error mappings.
Backend tests: memory model endpoints and librarian cleanup
tests/test_memory_model.py, tests/test_librarian_api.py
Adds async tests covering GET/PUT /api/memory/model (supported/unsupported, validation, capability 501, authorization 403) and updates _DEFAULT_LIBRARIAN and PATCH forwarding assertions to drop model/clear_model.
Frontend HTTP client library for memory model API
desktop/src/lib/memory-api.ts
New module exports fetchMemoryModel() and setMemoryModel() with shared throwOnError JSON error parsing and non-OK response handling.
Frontend system-wide memory model UI component
desktop/src/components/memory/MemorySettings.tsx
Adds internal MemoryModelSection that fetches {model,supported}, shows unsupported card when needed, opens picker to list provider models, and applies changes via setMemoryModel({model}) or setMemoryModel({clear:true}) with error/save-state handling.
Frontend cleanup: remove per-agent librarian model selector
desktop/src/components/agent-settings/MemoryTab.tsx
Removes detectHwClass/HwClass import and effect, drops model from LibrarianConfig, and deletes the per-agent librarian "Model" selector UI.
Frontend UI tests for system memory model configuration
desktop/src/apps/__tests__/MemoryApp.test.tsx
Vitest + React Testing Library tests with mocked transitive components and makeFetch helper; tests verify current model rendering, "Built-in default" when null, "not supported" state when unsupported, and correct PUT payload on model selection.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Frontend as MemoryModelSection
  participant API as /api/memory/model
  participant taosmd
  User->>Frontend: Mounts / interacts (Change / Clear)
  Frontend->>API: GET /api/memory/model
  API->>taosmd: getattr(get_memory_model)
  taosmd-->>API: current model or missing
  API-->>Frontend: {model, supported}
  alt User selects model
    Frontend->>API: PUT {model}
    API->>taosmd: set_memory_model(model, clear=false)
    taosmd-->>API: success / raises
    API-->>Frontend: 200 {model} or 400 error
  else User clears
    Frontend->>API: PUT {clear:true}
    API->>taosmd: set_memory_model(None, clear=true)
    taosmd-->>API: success / raises
    API-->>Frontend: 200 {model:null} or 400 error
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Poem

🐰 I hopped through code to change a rule,
From per-agent nook to a system-wide pool.
A picker, API, tests in tow,
The librarian's chooser now lets global settings grow.
Cheers — a carrot for the CI to show! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: introducing a system-wide memory model setting while removing per-agent model configuration.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/memory-model-systemwide

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

The system-wide memory model is install-level config; gate the write with
_require_admin (mirrors other admin-only settings) so a non-admin session
can't change which model powers memory for everyone. GET stays open — it
returns only a model-id string, and gating it would break the read-only
display for non-admin users. Addresses the commit security review finding.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
desktop/src/components/memory/MemorySettings.tsx (1)

30-43: 💤 Low value

Consider logging fetch errors for easier debugging.

The empty catch block on line 41 silently ignores errors when fetching available models. This makes it harder to diagnose issues if the models endpoint fails. Consider adding console.error(err) or a subtle user-facing indicator.

🔍 Optional enhancement
     } catch { /* leave empty */ }
+    } catch (err) {
+      console.error("Failed to load models for picker:", err);
     } finally { setModelsLoaded(true); }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@desktop/src/components/memory/MemorySettings.tsx` around lines 30 - 43, The
openPicker function swallows fetch errors in an empty catch which hinders
debugging; update the catch to log the caught error (e.g., console.error(err) or
use a logger) and optionally set a small user-facing state/flag (or call
setModelsLoaded with an error state) so the UI can indicate the fetch failed,
keeping the existing finally that calls setModelsLoaded(true) or adjusting it to
reflect the error state if you add an error flag; refer to openPicker,
setModels, setModelsLoaded and modelsLoaded when making these changes.
tinyagentos/routes/librarian.py (1)

63-64: 💤 Low value

Consider logging or narrowing the exception handler.

The broad Exception catch ensures robustness when calling the external taosmd.set_memory_model API, but it may obscure unexpected failures. Consider logging the exception before returning the 400 response, or catching more specific exception types if known.

📋 Optional: Add exception logging
+import logging
+
+logger = logging.getLogger(__name__)
+
 ...
     try:
         setter(body.model or "", clear=body.clear)
     except Exception as exc:
+        logger.exception("taosmd.set_memory_model failed")
         return JSONResponse(status_code=400, content={"detail": str(exc)})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tinyagentos/routes/librarian.py` around lines 63 - 64, The except block
catching Exception when calling taosmd.set_memory_model should either log the
error or narrow the exception types; update the handler that contains the
taosmd.set_memory_model call to call logger.exception(...) (or use the existing
module logger) before returning the JSONResponse so the stack/trace is recorded,
and if you know specific errors from taosmd (e.g., TaosMDError, HTTPError,
ValueError) replace the broad except Exception with individual except clauses to
return 400 for expected client errors and let unexpected exceptions propagate or
be handled by a global error handler; ensure you reference the existing
taosmd.set_memory_model call and the JSONResponse return when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@desktop/src/components/memory/MemorySettings.tsx`:
- Around line 30-43: The openPicker function swallows fetch errors in an empty
catch which hinders debugging; update the catch to log the caught error (e.g.,
console.error(err) or use a logger) and optionally set a small user-facing
state/flag (or call setModelsLoaded with an error state) so the UI can indicate
the fetch failed, keeping the existing finally that calls setModelsLoaded(true)
or adjusting it to reflect the error state if you add an error flag; refer to
openPicker, setModels, setModelsLoaded and modelsLoaded when making these
changes.

In `@tinyagentos/routes/librarian.py`:
- Around line 63-64: The except block catching Exception when calling
taosmd.set_memory_model should either log the error or narrow the exception
types; update the handler that contains the taosmd.set_memory_model call to call
logger.exception(...) (or use the existing module logger) before returning the
JSONResponse so the stack/trace is recorded, and if you know specific errors
from taosmd (e.g., TaosMDError, HTTPError, ValueError) replace the broad except
Exception with individual except clauses to return 400 for expected client
errors and let unexpected exceptions propagate or be handled by a global error
handler; ensure you reference the existing taosmd.set_memory_model call and the
JSONResponse return when making the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 56c11e1b-7a13-4178-b049-4c1f57481b5b

📥 Commits

Reviewing files that changed from the base of the PR and between 683b80a and a6e5132.

📒 Files selected for processing (7)
  • desktop/src/apps/__tests__/MemoryApp.test.tsx
  • desktop/src/components/agent-settings/MemoryTab.tsx
  • desktop/src/components/memory/MemorySettings.tsx
  • desktop/src/lib/memory-api.ts
  • tests/test_librarian_api.py
  • tests/test_memory_model.py
  • tinyagentos/routes/librarian.py
💤 Files with no reviewable changes (1)
  • desktop/src/components/agent-settings/MemoryTab.tsx

if not body.clear and not (body.model and body.model.strip()):
return JSONResponse(status_code=400, content={"detail": "model is required unless clear=true"})
try:
setter(body.model or "", clear=body.clear)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Potential issue with None to empty string conversion

When body.model is None (which happens when clearing without specifying a model), the code converts it to empty string via body.model or "". This may not be correct if the taosmd.set_memory_model function expects None to have a special meaning.

Looking at the frontend code:

  • handleClear() calls setMemoryModel({ clear: true }) (no model field)
  • This results in body.model = None in the endpoint
  • The validation correctly allows this when body.clear = true

However, we then pass "" (empty string) to the setter instead of None.

Since the MemoryModelUpdate schema allows model: str | None = None, and the getter returns None when no model is set, it seems more appropriate to pass body.model directly to preserve the None value when no model is specified.

Suggested fix: Pass body.model directly instead of converting None to empty string.

@kilo-code-bot
Copy link
Copy Markdown

kilo-code-bot Bot commented Jun 4, 2026

Code Review Summary

Status: 1 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
tinyagentos/routes/librarian.py 68 Potential issue with None to empty string conversion

When body.model is None (which happens when clearing without specifying a model), the code converts it to empty string via body.model or "". This may not be correct if the taosmd.set_memory_model function expects None to have a special meaning.

Looking at the frontend code:

  • handleClear() calls setMemoryModel({ clear: true }) (no model field)
  • This results in body.model = None in the endpoint
  • The validation correctly allows this when body.clear = true

However, we then pass "" (empty string) to the setter instead of None.

Since the MemoryModelUpdate schema allows model: str | None = None, and the getter returns None when no model is set, it seems more appropriate to pass body.model directly to preserve the None value when no model is specified.

Suggested fix: Pass body.model directly instead of converting None to empty string.

Files Reviewed (7 files)
  • desktop/src/apps/__tests__/MemoryApp.test.tsx - 0 issues
  • desktop/src/components/agent-settings/MemoryTab.tsx - 0 issues
  • desktop/src/components/memory/MemorySettings.tsx - 0 issues
  • desktop/src/lib/memory-api.ts - 0 issues
  • tests/test_librarian_api.py - 0 issues
  • tests/test_memory_model.py - 0 issues
  • tinyagentos/routes/librarian.py - 1 issues

Reviewed by nemotron-3-super-120b-a12b-20230311:free · 506,526 tokens

@jaylfc jaylfc merged commit ea42f80 into dev Jun 4, 2026
6 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in TinyAgentOS Roadmap Jun 4, 2026
@jaylfc jaylfc deleted the feat/memory-model-systemwide branch June 4, 2026 22:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

1 participant