refactor: memory provider (#140)

* refactor: memory provider

* fix: migrations

* feat: divide collection from different built-in memory

* feat: add `MEMORY.md` and `PROFILES.md`

* use .env for docker compose. fix #142 (#143)

* feat(web): add brand icons for search providers (#144)

Add custom FontAwesome icon definitions for all 9 search providers:
- Yandex: uses existing faYandex from FA free brands
- Tavily, Jina, Exa, Bocha, Serper: custom icons from brand SVGs
- DuckDuckGo, SearXNG, Sogou: custom icons from Simple Icons

Icons are registered with a custom 'fac' prefix and rendered as
monochrome (currentColor) via FontAwesome's standard rendering.

* fix: resolve multiple UI bugs (#147)

* feat: add email service with multi-adapter support (#146)

* feat: add email service with multi-adapter support

Implement a full-stack email service with global provider management,
per-bot bindings with granular read/write permissions, outbox audit
storage, and MCP tool integration for direct mailbox access.

Backend:
- Email providers: CRUD with dynamic config schema (generic SMTP/IMAP, Mailgun)
- Generic adapter: go-mail (SMTP) + go-imap/v2 (IMAP IDLE real-time push via
  UnilateralDataHandler + UID-based tracking + periodic check fallback)
- Mailgun adapter: mailgun-go/v5 with dual inbound mode (webhook + poll)
- Bot email bindings: per-bot provider binding with independent r/w permissions
- Outbox: outbound email audit log with status tracking
- Trigger: inbound emails push notification to bot_inbox (from/subject only,
  LLM reads full content on demand via MCP tools)
- MailboxReader interface: on-demand IMAP queries for listing/reading emails
- MCP tools: email_accounts, email_send, email_list (paginated mailbox),
  email_read (by UID) — all with multi-binding and provider_id selection
- Webhook: /email/mailgun/webhook/:config_id (JWT-skipped, signature-verified)
- DB migration: 0019_add_email (email_providers, bot_email_bindings, email_outbox)

Frontend:
- Email Providers page: /email-providers with MasterDetailSidebarLayout
- Dynamic config form rendered from ordered provider meta schema with i18n keys
- Bot detail: Email tab with bindings management + outbox audit table
- Sidebar navigation entry
- Full i18n support (en + zh)
- Auto-generated SDK from Swagger

Closes #17

* feat(email): trigger bot conversation immediately on inbound email

Instead of only storing an inbox item and waiting for the next chat,
the email trigger now proactively invokes the conversation resolver
so the bot processes new emails right away — aligned with the
schedule/heartbeat trigger pattern.

* fix: lint

---------

Co-authored-by: Acbox <acbox0328@gmail.com>

* chore: update AGENTS.md

* feat: files preview

* feat(web): improve MCP details page

* refactor(skills): import skill with pure markdown string

* merge main into refactor/memory

* fix: migration

* refactor: temp delete qdrant and bm25 index

* fix: clean merge code

* fix: update memory handler

---------

Co-authored-by: Leohearts <leohearts@leohearts.com>
Co-authored-by: Menci <mencici@msn.com>
Co-authored-by: Quincy <69751197+dqygit@users.noreply.github.com>
Co-authored-by: BBQ <35603386+HoneyBBQ@users.noreply.github.com>
Co-authored-by: Ran <16112591+chen-ran@users.noreply.github.com>
This commit is contained in:
Acbox Liu
2026-03-03 15:33:50 +08:00
committed by GitHub
parent 567a1f3761
commit ea719f7ca7
85 changed files with 6405 additions and 6906 deletions
+498 -280
View File
@@ -2344,7 +2344,7 @@ const docTemplate = `{
},
{
"type": "boolean",
"description": "Skip sparse vector stats (top_k_buckets, cdf_curve) to reduce overhead",
"description": "Skip optional stats in memory search response",
"name": "no_stats",
"in": "query"
}
@@ -2353,7 +2353,7 @@ const docTemplate = `{
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/memory.SearchResponse"
"$ref": "#/definitions/provider.SearchResponse"
}
},
"400": {
@@ -2416,7 +2416,7 @@ const docTemplate = `{
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/memory.SearchResponse"
"$ref": "#/definitions/provider.SearchResponse"
}
},
"400": {
@@ -2478,7 +2478,7 @@ const docTemplate = `{
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/memory.DeleteResponse"
"$ref": "#/definitions/provider.DeleteResponse"
}
},
"400": {
@@ -2543,7 +2543,7 @@ const docTemplate = `{
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/memory.CompactResult"
"$ref": "#/definitions/provider.CompactResult"
}
},
"400": {
@@ -2575,7 +2575,7 @@ const docTemplate = `{
},
"/bots/{bot_id}/memory/rebuild": {
"post": {
"description": "Read memory files from the container filesystem (source of truth) and restore missing entries to Qdrant",
"description": "Read memory files from the container filesystem (source of truth) and restore missing entries to memory storage",
"produces": [
"application/json"
],
@@ -2596,7 +2596,7 @@ const docTemplate = `{
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/memory.RebuildResult"
"$ref": "#/definitions/provider.RebuildResult"
}
},
"400": {
@@ -2661,7 +2661,7 @@ const docTemplate = `{
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/memory.SearchResponse"
"$ref": "#/definitions/provider.SearchResponse"
}
},
"400": {
@@ -2720,7 +2720,7 @@ const docTemplate = `{
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/memory.UsageResponse"
"$ref": "#/definitions/provider.UsageResponse"
}
},
"400": {
@@ -2780,7 +2780,7 @@ const docTemplate = `{
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/memory.DeleteResponse"
"$ref": "#/definitions/provider.DeleteResponse"
}
},
"400": {
@@ -5022,29 +5022,62 @@ const docTemplate = `{
}
}
},
"/embeddings": {
"post": {
"description": "Create text or multimodal embeddings",
"/memory-providers": {
"get": {
"description": "List configured memory providers",
"produces": [
"application/json"
],
"tags": [
"embeddings"
],
"summary": "Create embeddings",
"parameters": [
{
"description": "Embeddings request",
"name": "payload",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/handlers.EmbeddingsRequest"
}
}
"memory-providers"
],
"summary": "List memory providers",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handlers.EmbeddingsResponse"
"type": "array",
"items": {
"$ref": "#/definitions/provider.ProviderGetResponse"
}
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
}
}
},
"post": {
"description": "Create a memory provider configuration",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"memory-providers"
],
"summary": "Create a memory provider",
"parameters": [
{
"description": "Memory provider configuration",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/provider.ProviderCreateRequest"
}
}
],
"responses": {
"201": {
"description": "Created",
"schema": {
"$ref": "#/definitions/provider.ProviderGetResponse"
}
},
"400": {
@@ -5058,11 +5091,150 @@ const docTemplate = `{
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"501": {
"description": "Not Implemented",
}
}
}
},
"/memory-providers/meta": {
"get": {
"description": "List available memory provider types and config schemas",
"tags": [
"memory-providers"
],
"summary": "List memory provider metadata",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handlers.EmbeddingsResponse"
"type": "array",
"items": {
"$ref": "#/definitions/provider.ProviderMeta"
}
}
}
}
}
},
"/memory-providers/{id}": {
"get": {
"description": "Get memory provider by ID",
"produces": [
"application/json"
],
"tags": [
"memory-providers"
],
"summary": "Get a memory provider",
"parameters": [
{
"type": "string",
"description": "Provider ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/provider.ProviderGetResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
}
}
},
"put": {
"description": "Update memory provider by ID",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"memory-providers"
],
"summary": "Update a memory provider",
"parameters": [
{
"type": "string",
"description": "Provider ID",
"name": "id",
"in": "path",
"required": true
},
{
"description": "Updated configuration",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/provider.ProviderUpdateRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/provider.ProviderGetResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
}
}
},
"delete": {
"description": "Delete memory provider by ID",
"tags": [
"memory-providers"
],
"summary": "Delete a memory provider",
"parameters": [
{
"type": "string",
"description": "Provider ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"204": {
"description": "No Content"
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
}
}
@@ -7671,6 +7843,29 @@ const docTemplate = `{
}
}
},
"github_com_memohai_memoh_internal_fs.FileInfo": {
"type": "object",
"properties": {
"isDir": {
"type": "boolean"
},
"modTime": {
"type": "string"
},
"mode": {
"type": "string"
},
"name": {
"type": "string"
},
"path": {
"type": "string"
},
"size": {
"type": "integer"
}
}
},
"github_com_memohai_memoh_internal_mcp.Connection": {
"type": "object",
"properties": {
@@ -7814,83 +8009,6 @@ const docTemplate = `{
}
}
},
"handlers.EmbeddingsInput": {
"type": "object",
"properties": {
"image_url": {
"type": "string"
},
"text": {
"type": "string"
},
"video_url": {
"type": "string"
}
}
},
"handlers.EmbeddingsRequest": {
"type": "object",
"properties": {
"dimensions": {
"type": "integer"
},
"input": {
"$ref": "#/definitions/handlers.EmbeddingsInput"
},
"model": {
"type": "string"
},
"provider": {
"type": "string"
},
"type": {
"type": "string"
}
}
},
"handlers.EmbeddingsResponse": {
"type": "object",
"properties": {
"dimensions": {
"type": "integer"
},
"embedding": {
"type": "array",
"items": {
"type": "number"
}
},
"message": {
"type": "string"
},
"model": {
"type": "string"
},
"provider": {
"type": "string"
},
"type": {
"type": "string"
},
"usage": {
"$ref": "#/definitions/handlers.EmbeddingsUsage"
}
}
},
"handlers.EmbeddingsUsage": {
"type": "object",
"properties": {
"duration": {
"type": "integer"
},
"image_tokens": {
"type": "integer"
},
"input_tokens": {
"type": "integer"
}
}
},
"handlers.ErrorResponse": {
"type": "object",
"properties": {
@@ -7939,7 +8057,7 @@ const docTemplate = `{
"entries": {
"type": "array",
"items": {
"$ref": "#/definitions/handlers.FSFileInfo"
"$ref": "#/definitions/github_com_memohai_memoh_internal_fs.FileInfo"
}
},
"path": {
@@ -8354,7 +8472,7 @@ const docTemplate = `{
"messages": {
"type": "array",
"items": {
"$ref": "#/definitions/memory.Message"
"$ref": "#/definitions/provider.Message"
}
},
"metadata": {
@@ -8674,168 +8792,6 @@ const docTemplate = `{
}
}
},
"memory.CDFPoint": {
"type": "object",
"properties": {
"cumulative": {
"description": "cumulative weight fraction [0.0, 1.0]",
"type": "number"
},
"k": {
"description": "rank position (1-based, sorted by value desc)",
"type": "integer"
}
}
},
"memory.CompactResult": {
"type": "object",
"properties": {
"after_count": {
"type": "integer"
},
"before_count": {
"type": "integer"
},
"ratio": {
"type": "number"
},
"results": {
"type": "array",
"items": {
"$ref": "#/definitions/memory.MemoryItem"
}
}
}
},
"memory.DeleteResponse": {
"type": "object",
"properties": {
"message": {
"type": "string"
}
}
},
"memory.MemoryItem": {
"type": "object",
"properties": {
"agent_id": {
"type": "string"
},
"bot_id": {
"type": "string"
},
"cdf_curve": {
"type": "array",
"items": {
"$ref": "#/definitions/memory.CDFPoint"
}
},
"created_at": {
"type": "string"
},
"hash": {
"type": "string"
},
"id": {
"type": "string"
},
"memory": {
"type": "string"
},
"metadata": {
"type": "object",
"additionalProperties": {}
},
"run_id": {
"type": "string"
},
"score": {
"type": "number"
},
"top_k_buckets": {
"type": "array",
"items": {
"$ref": "#/definitions/memory.TopKBucket"
}
},
"updated_at": {
"type": "string"
}
}
},
"memory.Message": {
"type": "object",
"properties": {
"content": {
"type": "string"
},
"role": {
"type": "string"
}
}
},
"memory.RebuildResult": {
"type": "object",
"properties": {
"fs_count": {
"type": "integer"
},
"missing_count": {
"type": "integer"
},
"qdrant_count": {
"type": "integer"
},
"restored_count": {
"type": "integer"
}
}
},
"memory.SearchResponse": {
"type": "object",
"properties": {
"relations": {
"type": "array",
"items": {}
},
"results": {
"type": "array",
"items": {
"$ref": "#/definitions/memory.MemoryItem"
}
}
}
},
"memory.TopKBucket": {
"type": "object",
"properties": {
"index": {
"description": "sparse dimension index (term hash)",
"type": "integer"
},
"value": {
"description": "weight (term frequency)",
"type": "number"
}
}
},
"memory.UsageResponse": {
"type": "object",
"properties": {
"avg_text_bytes": {
"type": "integer"
},
"count": {
"type": "integer"
},
"estimated_storage_bytes": {
"type": "integer"
},
"total_text_bytes": {
"type": "integer"
}
}
},
"message.Message": {
"type": "object",
"properties": {
@@ -9096,6 +9052,274 @@ const docTemplate = `{
}
}
},
"provider.CDFPoint": {
"type": "object",
"properties": {
"cumulative": {
"description": "cumulative weight fraction [0.0, 1.0]",
"type": "number"
},
"k": {
"description": "rank position (1-based, sorted by value desc)",
"type": "integer"
}
}
},
"provider.CompactResult": {
"type": "object",
"properties": {
"after_count": {
"type": "integer"
},
"before_count": {
"type": "integer"
},
"ratio": {
"type": "number"
},
"results": {
"type": "array",
"items": {
"$ref": "#/definitions/provider.MemoryItem"
}
}
}
},
"provider.DeleteResponse": {
"type": "object",
"properties": {
"message": {
"type": "string"
}
}
},
"provider.MemoryItem": {
"type": "object",
"properties": {
"agent_id": {
"type": "string"
},
"bot_id": {
"type": "string"
},
"cdf_curve": {
"type": "array",
"items": {
"$ref": "#/definitions/provider.CDFPoint"
}
},
"created_at": {
"type": "string"
},
"hash": {
"type": "string"
},
"id": {
"type": "string"
},
"memory": {
"type": "string"
},
"metadata": {
"type": "object",
"additionalProperties": {}
},
"run_id": {
"type": "string"
},
"score": {
"type": "number"
},
"top_k_buckets": {
"type": "array",
"items": {
"$ref": "#/definitions/provider.TopKBucket"
}
},
"updated_at": {
"type": "string"
}
}
},
"provider.Message": {
"type": "object",
"properties": {
"content": {
"type": "string"
},
"role": {
"type": "string"
}
}
},
"provider.ProviderConfigSchema": {
"type": "object",
"properties": {
"fields": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/provider.ProviderFieldSchema"
}
}
}
},
"provider.ProviderCreateRequest": {
"type": "object",
"properties": {
"config": {
"type": "object",
"additionalProperties": {}
},
"name": {
"type": "string"
},
"provider": {
"$ref": "#/definitions/provider.ProviderType"
}
}
},
"provider.ProviderFieldSchema": {
"type": "object",
"properties": {
"description": {
"type": "string"
},
"example": {},
"required": {
"type": "boolean"
},
"title": {
"type": "string"
},
"type": {
"type": "string"
}
}
},
"provider.ProviderGetResponse": {
"type": "object",
"properties": {
"config": {
"type": "object",
"additionalProperties": {}
},
"created_at": {
"type": "string"
},
"id": {
"type": "string"
},
"is_default": {
"type": "boolean"
},
"name": {
"type": "string"
},
"provider": {
"type": "string"
},
"updated_at": {
"type": "string"
}
}
},
"provider.ProviderMeta": {
"type": "object",
"properties": {
"config_schema": {
"$ref": "#/definitions/provider.ProviderConfigSchema"
},
"display_name": {
"type": "string"
},
"provider": {
"type": "string"
}
}
},
"provider.ProviderType": {
"type": "string",
"enum": [
"builtin"
],
"x-enum-varnames": [
"ProviderBuiltin"
]
},
"provider.ProviderUpdateRequest": {
"type": "object",
"properties": {
"config": {
"type": "object",
"additionalProperties": {}
},
"name": {
"type": "string"
}
}
},
"provider.RebuildResult": {
"type": "object",
"properties": {
"fs_count": {
"type": "integer"
},
"missing_count": {
"type": "integer"
},
"qdrant_count": {
"type": "integer"
},
"restored_count": {
"type": "integer"
}
}
},
"provider.SearchResponse": {
"type": "object",
"properties": {
"relations": {
"type": "array",
"items": {}
},
"results": {
"type": "array",
"items": {
"$ref": "#/definitions/provider.MemoryItem"
}
}
}
},
"provider.TopKBucket": {
"type": "object",
"properties": {
"index": {
"description": "sparse dimension index (term hash)",
"type": "integer"
},
"value": {
"description": "weight (term frequency)",
"type": "number"
}
}
},
"provider.UsageResponse": {
"type": "object",
"properties": {
"avg_text_bytes": {
"type": "integer"
},
"count": {
"type": "integer"
},
"estimated_storage_bytes": {
"type": "integer"
},
"total_text_bytes": {
"type": "integer"
}
}
},
"providers.CountResponse": {
"type": "object",
"properties": {
@@ -9435,9 +9659,6 @@ const docTemplate = `{
"chat_model_id": {
"type": "string"
},
"embedding_model_id": {
"type": "string"
},
"heartbeat_enabled": {
"type": "boolean"
},
@@ -9459,7 +9680,7 @@ const docTemplate = `{
"max_inbox_items": {
"type": "integer"
},
"memory_model_id": {
"memory_provider_id": {
"type": "string"
},
"reasoning_effort": {
@@ -9482,9 +9703,6 @@ const docTemplate = `{
"chat_model_id": {
"type": "string"
},
"embedding_model_id": {
"type": "string"
},
"heartbeat_enabled": {
"type": "boolean"
},
@@ -9506,7 +9724,7 @@ const docTemplate = `{
"max_inbox_items": {
"type": "integer"
},
"memory_model_id": {
"memory_provider_id": {
"type": "string"
},
"reasoning_effort": {
+498 -280
View File
@@ -2335,7 +2335,7 @@
},
{
"type": "boolean",
"description": "Skip sparse vector stats (top_k_buckets, cdf_curve) to reduce overhead",
"description": "Skip optional stats in memory search response",
"name": "no_stats",
"in": "query"
}
@@ -2344,7 +2344,7 @@
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/memory.SearchResponse"
"$ref": "#/definitions/provider.SearchResponse"
}
},
"400": {
@@ -2407,7 +2407,7 @@
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/memory.SearchResponse"
"$ref": "#/definitions/provider.SearchResponse"
}
},
"400": {
@@ -2469,7 +2469,7 @@
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/memory.DeleteResponse"
"$ref": "#/definitions/provider.DeleteResponse"
}
},
"400": {
@@ -2534,7 +2534,7 @@
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/memory.CompactResult"
"$ref": "#/definitions/provider.CompactResult"
}
},
"400": {
@@ -2566,7 +2566,7 @@
},
"/bots/{bot_id}/memory/rebuild": {
"post": {
"description": "Read memory files from the container filesystem (source of truth) and restore missing entries to Qdrant",
"description": "Read memory files from the container filesystem (source of truth) and restore missing entries to memory storage",
"produces": [
"application/json"
],
@@ -2587,7 +2587,7 @@
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/memory.RebuildResult"
"$ref": "#/definitions/provider.RebuildResult"
}
},
"400": {
@@ -2652,7 +2652,7 @@
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/memory.SearchResponse"
"$ref": "#/definitions/provider.SearchResponse"
}
},
"400": {
@@ -2711,7 +2711,7 @@
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/memory.UsageResponse"
"$ref": "#/definitions/provider.UsageResponse"
}
},
"400": {
@@ -2771,7 +2771,7 @@
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/memory.DeleteResponse"
"$ref": "#/definitions/provider.DeleteResponse"
}
},
"400": {
@@ -5013,29 +5013,62 @@
}
}
},
"/embeddings": {
"post": {
"description": "Create text or multimodal embeddings",
"/memory-providers": {
"get": {
"description": "List configured memory providers",
"produces": [
"application/json"
],
"tags": [
"embeddings"
],
"summary": "Create embeddings",
"parameters": [
{
"description": "Embeddings request",
"name": "payload",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/handlers.EmbeddingsRequest"
}
}
"memory-providers"
],
"summary": "List memory providers",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handlers.EmbeddingsResponse"
"type": "array",
"items": {
"$ref": "#/definitions/provider.ProviderGetResponse"
}
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
}
}
},
"post": {
"description": "Create a memory provider configuration",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"memory-providers"
],
"summary": "Create a memory provider",
"parameters": [
{
"description": "Memory provider configuration",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/provider.ProviderCreateRequest"
}
}
],
"responses": {
"201": {
"description": "Created",
"schema": {
"$ref": "#/definitions/provider.ProviderGetResponse"
}
},
"400": {
@@ -5049,11 +5082,150 @@
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"501": {
"description": "Not Implemented",
}
}
}
},
"/memory-providers/meta": {
"get": {
"description": "List available memory provider types and config schemas",
"tags": [
"memory-providers"
],
"summary": "List memory provider metadata",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handlers.EmbeddingsResponse"
"type": "array",
"items": {
"$ref": "#/definitions/provider.ProviderMeta"
}
}
}
}
}
},
"/memory-providers/{id}": {
"get": {
"description": "Get memory provider by ID",
"produces": [
"application/json"
],
"tags": [
"memory-providers"
],
"summary": "Get a memory provider",
"parameters": [
{
"type": "string",
"description": "Provider ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/provider.ProviderGetResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
}
}
},
"put": {
"description": "Update memory provider by ID",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"memory-providers"
],
"summary": "Update a memory provider",
"parameters": [
{
"type": "string",
"description": "Provider ID",
"name": "id",
"in": "path",
"required": true
},
{
"description": "Updated configuration",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/provider.ProviderUpdateRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/provider.ProviderGetResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
}
}
},
"delete": {
"description": "Delete memory provider by ID",
"tags": [
"memory-providers"
],
"summary": "Delete a memory provider",
"parameters": [
{
"type": "string",
"description": "Provider ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"204": {
"description": "No Content"
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
}
}
@@ -7662,6 +7834,29 @@
}
}
},
"github_com_memohai_memoh_internal_fs.FileInfo": {
"type": "object",
"properties": {
"isDir": {
"type": "boolean"
},
"modTime": {
"type": "string"
},
"mode": {
"type": "string"
},
"name": {
"type": "string"
},
"path": {
"type": "string"
},
"size": {
"type": "integer"
}
}
},
"github_com_memohai_memoh_internal_mcp.Connection": {
"type": "object",
"properties": {
@@ -7805,83 +8000,6 @@
}
}
},
"handlers.EmbeddingsInput": {
"type": "object",
"properties": {
"image_url": {
"type": "string"
},
"text": {
"type": "string"
},
"video_url": {
"type": "string"
}
}
},
"handlers.EmbeddingsRequest": {
"type": "object",
"properties": {
"dimensions": {
"type": "integer"
},
"input": {
"$ref": "#/definitions/handlers.EmbeddingsInput"
},
"model": {
"type": "string"
},
"provider": {
"type": "string"
},
"type": {
"type": "string"
}
}
},
"handlers.EmbeddingsResponse": {
"type": "object",
"properties": {
"dimensions": {
"type": "integer"
},
"embedding": {
"type": "array",
"items": {
"type": "number"
}
},
"message": {
"type": "string"
},
"model": {
"type": "string"
},
"provider": {
"type": "string"
},
"type": {
"type": "string"
},
"usage": {
"$ref": "#/definitions/handlers.EmbeddingsUsage"
}
}
},
"handlers.EmbeddingsUsage": {
"type": "object",
"properties": {
"duration": {
"type": "integer"
},
"image_tokens": {
"type": "integer"
},
"input_tokens": {
"type": "integer"
}
}
},
"handlers.ErrorResponse": {
"type": "object",
"properties": {
@@ -7930,7 +8048,7 @@
"entries": {
"type": "array",
"items": {
"$ref": "#/definitions/handlers.FSFileInfo"
"$ref": "#/definitions/github_com_memohai_memoh_internal_fs.FileInfo"
}
},
"path": {
@@ -8345,7 +8463,7 @@
"messages": {
"type": "array",
"items": {
"$ref": "#/definitions/memory.Message"
"$ref": "#/definitions/provider.Message"
}
},
"metadata": {
@@ -8665,168 +8783,6 @@
}
}
},
"memory.CDFPoint": {
"type": "object",
"properties": {
"cumulative": {
"description": "cumulative weight fraction [0.0, 1.0]",
"type": "number"
},
"k": {
"description": "rank position (1-based, sorted by value desc)",
"type": "integer"
}
}
},
"memory.CompactResult": {
"type": "object",
"properties": {
"after_count": {
"type": "integer"
},
"before_count": {
"type": "integer"
},
"ratio": {
"type": "number"
},
"results": {
"type": "array",
"items": {
"$ref": "#/definitions/memory.MemoryItem"
}
}
}
},
"memory.DeleteResponse": {
"type": "object",
"properties": {
"message": {
"type": "string"
}
}
},
"memory.MemoryItem": {
"type": "object",
"properties": {
"agent_id": {
"type": "string"
},
"bot_id": {
"type": "string"
},
"cdf_curve": {
"type": "array",
"items": {
"$ref": "#/definitions/memory.CDFPoint"
}
},
"created_at": {
"type": "string"
},
"hash": {
"type": "string"
},
"id": {
"type": "string"
},
"memory": {
"type": "string"
},
"metadata": {
"type": "object",
"additionalProperties": {}
},
"run_id": {
"type": "string"
},
"score": {
"type": "number"
},
"top_k_buckets": {
"type": "array",
"items": {
"$ref": "#/definitions/memory.TopKBucket"
}
},
"updated_at": {
"type": "string"
}
}
},
"memory.Message": {
"type": "object",
"properties": {
"content": {
"type": "string"
},
"role": {
"type": "string"
}
}
},
"memory.RebuildResult": {
"type": "object",
"properties": {
"fs_count": {
"type": "integer"
},
"missing_count": {
"type": "integer"
},
"qdrant_count": {
"type": "integer"
},
"restored_count": {
"type": "integer"
}
}
},
"memory.SearchResponse": {
"type": "object",
"properties": {
"relations": {
"type": "array",
"items": {}
},
"results": {
"type": "array",
"items": {
"$ref": "#/definitions/memory.MemoryItem"
}
}
}
},
"memory.TopKBucket": {
"type": "object",
"properties": {
"index": {
"description": "sparse dimension index (term hash)",
"type": "integer"
},
"value": {
"description": "weight (term frequency)",
"type": "number"
}
}
},
"memory.UsageResponse": {
"type": "object",
"properties": {
"avg_text_bytes": {
"type": "integer"
},
"count": {
"type": "integer"
},
"estimated_storage_bytes": {
"type": "integer"
},
"total_text_bytes": {
"type": "integer"
}
}
},
"message.Message": {
"type": "object",
"properties": {
@@ -9087,6 +9043,274 @@
}
}
},
"provider.CDFPoint": {
"type": "object",
"properties": {
"cumulative": {
"description": "cumulative weight fraction [0.0, 1.0]",
"type": "number"
},
"k": {
"description": "rank position (1-based, sorted by value desc)",
"type": "integer"
}
}
},
"provider.CompactResult": {
"type": "object",
"properties": {
"after_count": {
"type": "integer"
},
"before_count": {
"type": "integer"
},
"ratio": {
"type": "number"
},
"results": {
"type": "array",
"items": {
"$ref": "#/definitions/provider.MemoryItem"
}
}
}
},
"provider.DeleteResponse": {
"type": "object",
"properties": {
"message": {
"type": "string"
}
}
},
"provider.MemoryItem": {
"type": "object",
"properties": {
"agent_id": {
"type": "string"
},
"bot_id": {
"type": "string"
},
"cdf_curve": {
"type": "array",
"items": {
"$ref": "#/definitions/provider.CDFPoint"
}
},
"created_at": {
"type": "string"
},
"hash": {
"type": "string"
},
"id": {
"type": "string"
},
"memory": {
"type": "string"
},
"metadata": {
"type": "object",
"additionalProperties": {}
},
"run_id": {
"type": "string"
},
"score": {
"type": "number"
},
"top_k_buckets": {
"type": "array",
"items": {
"$ref": "#/definitions/provider.TopKBucket"
}
},
"updated_at": {
"type": "string"
}
}
},
"provider.Message": {
"type": "object",
"properties": {
"content": {
"type": "string"
},
"role": {
"type": "string"
}
}
},
"provider.ProviderConfigSchema": {
"type": "object",
"properties": {
"fields": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/provider.ProviderFieldSchema"
}
}
}
},
"provider.ProviderCreateRequest": {
"type": "object",
"properties": {
"config": {
"type": "object",
"additionalProperties": {}
},
"name": {
"type": "string"
},
"provider": {
"$ref": "#/definitions/provider.ProviderType"
}
}
},
"provider.ProviderFieldSchema": {
"type": "object",
"properties": {
"description": {
"type": "string"
},
"example": {},
"required": {
"type": "boolean"
},
"title": {
"type": "string"
},
"type": {
"type": "string"
}
}
},
"provider.ProviderGetResponse": {
"type": "object",
"properties": {
"config": {
"type": "object",
"additionalProperties": {}
},
"created_at": {
"type": "string"
},
"id": {
"type": "string"
},
"is_default": {
"type": "boolean"
},
"name": {
"type": "string"
},
"provider": {
"type": "string"
},
"updated_at": {
"type": "string"
}
}
},
"provider.ProviderMeta": {
"type": "object",
"properties": {
"config_schema": {
"$ref": "#/definitions/provider.ProviderConfigSchema"
},
"display_name": {
"type": "string"
},
"provider": {
"type": "string"
}
}
},
"provider.ProviderType": {
"type": "string",
"enum": [
"builtin"
],
"x-enum-varnames": [
"ProviderBuiltin"
]
},
"provider.ProviderUpdateRequest": {
"type": "object",
"properties": {
"config": {
"type": "object",
"additionalProperties": {}
},
"name": {
"type": "string"
}
}
},
"provider.RebuildResult": {
"type": "object",
"properties": {
"fs_count": {
"type": "integer"
},
"missing_count": {
"type": "integer"
},
"qdrant_count": {
"type": "integer"
},
"restored_count": {
"type": "integer"
}
}
},
"provider.SearchResponse": {
"type": "object",
"properties": {
"relations": {
"type": "array",
"items": {}
},
"results": {
"type": "array",
"items": {
"$ref": "#/definitions/provider.MemoryItem"
}
}
}
},
"provider.TopKBucket": {
"type": "object",
"properties": {
"index": {
"description": "sparse dimension index (term hash)",
"type": "integer"
},
"value": {
"description": "weight (term frequency)",
"type": "number"
}
}
},
"provider.UsageResponse": {
"type": "object",
"properties": {
"avg_text_bytes": {
"type": "integer"
},
"count": {
"type": "integer"
},
"estimated_storage_bytes": {
"type": "integer"
},
"total_text_bytes": {
"type": "integer"
}
}
},
"providers.CountResponse": {
"type": "object",
"properties": {
@@ -9426,9 +9650,6 @@
"chat_model_id": {
"type": "string"
},
"embedding_model_id": {
"type": "string"
},
"heartbeat_enabled": {
"type": "boolean"
},
@@ -9450,7 +9671,7 @@
"max_inbox_items": {
"type": "integer"
},
"memory_model_id": {
"memory_provider_id": {
"type": "string"
},
"reasoning_effort": {
@@ -9473,9 +9694,6 @@
"chat_model_id": {
"type": "string"
},
"embedding_model_id": {
"type": "string"
},
"heartbeat_enabled": {
"type": "boolean"
},
@@ -9497,7 +9715,7 @@
"max_inbox_items": {
"type": "integer"
},
"memory_model_id": {
"memory_provider_id": {
"type": "string"
},
"reasoning_effort": {
+337 -193
View File
@@ -690,6 +690,21 @@ definitions:
provider:
type: string
type: object
github_com_memohai_memoh_internal_fs.FileInfo:
properties:
isDir:
type: boolean
modTime:
type: string
mode:
type: string
name:
type: string
path:
type: string
size:
type: integer
type: object
github_com_memohai_memoh_internal_mcp.Connection:
properties:
bot_id:
@@ -783,56 +798,6 @@ definitions:
reasoning_tokens:
type: integer
type: object
handlers.EmbeddingsInput:
properties:
image_url:
type: string
text:
type: string
video_url:
type: string
type: object
handlers.EmbeddingsRequest:
properties:
dimensions:
type: integer
input:
$ref: '#/definitions/handlers.EmbeddingsInput'
model:
type: string
provider:
type: string
type:
type: string
type: object
handlers.EmbeddingsResponse:
properties:
dimensions:
type: integer
embedding:
items:
type: number
type: array
message:
type: string
model:
type: string
provider:
type: string
type:
type: string
usage:
$ref: '#/definitions/handlers.EmbeddingsUsage'
type: object
handlers.EmbeddingsUsage:
properties:
duration:
type: integer
image_tokens:
type: integer
input_tokens:
type: integer
type: object
handlers.ErrorResponse:
properties:
message:
@@ -864,7 +829,7 @@ definitions:
properties:
entries:
items:
$ref: '#/definitions/handlers.FSFileInfo'
$ref: '#/definitions/github_com_memohai_memoh_internal_fs.FileInfo'
type: array
path:
type: string
@@ -1133,7 +1098,7 @@ definitions:
type: string
messages:
items:
$ref: '#/definitions/memory.Message'
$ref: '#/definitions/provider.Message'
type: array
metadata:
additionalProperties: {}
@@ -1343,113 +1308,6 @@ definitions:
url:
type: string
type: object
memory.CDFPoint:
properties:
cumulative:
description: cumulative weight fraction [0.0, 1.0]
type: number
k:
description: rank position (1-based, sorted by value desc)
type: integer
type: object
memory.CompactResult:
properties:
after_count:
type: integer
before_count:
type: integer
ratio:
type: number
results:
items:
$ref: '#/definitions/memory.MemoryItem'
type: array
type: object
memory.DeleteResponse:
properties:
message:
type: string
type: object
memory.MemoryItem:
properties:
agent_id:
type: string
bot_id:
type: string
cdf_curve:
items:
$ref: '#/definitions/memory.CDFPoint'
type: array
created_at:
type: string
hash:
type: string
id:
type: string
memory:
type: string
metadata:
additionalProperties: {}
type: object
run_id:
type: string
score:
type: number
top_k_buckets:
items:
$ref: '#/definitions/memory.TopKBucket'
type: array
updated_at:
type: string
type: object
memory.Message:
properties:
content:
type: string
role:
type: string
type: object
memory.RebuildResult:
properties:
fs_count:
type: integer
missing_count:
type: integer
qdrant_count:
type: integer
restored_count:
type: integer
type: object
memory.SearchResponse:
properties:
relations:
items: {}
type: array
results:
items:
$ref: '#/definitions/memory.MemoryItem'
type: array
type: object
memory.TopKBucket:
properties:
index:
description: sparse dimension index (term hash)
type: integer
value:
description: weight (term frequency)
type: number
type: object
memory.UsageResponse:
properties:
avg_text_bytes:
type: integer
count:
type: integer
estimated_storage_bytes:
type: integer
total_text_bytes:
type: integer
type: object
message.Message:
properties:
assets:
@@ -1625,6 +1483,183 @@ definitions:
type:
$ref: '#/definitions/models.ModelType'
type: object
provider.CDFPoint:
properties:
cumulative:
description: cumulative weight fraction [0.0, 1.0]
type: number
k:
description: rank position (1-based, sorted by value desc)
type: integer
type: object
provider.CompactResult:
properties:
after_count:
type: integer
before_count:
type: integer
ratio:
type: number
results:
items:
$ref: '#/definitions/provider.MemoryItem'
type: array
type: object
provider.DeleteResponse:
properties:
message:
type: string
type: object
provider.MemoryItem:
properties:
agent_id:
type: string
bot_id:
type: string
cdf_curve:
items:
$ref: '#/definitions/provider.CDFPoint'
type: array
created_at:
type: string
hash:
type: string
id:
type: string
memory:
type: string
metadata:
additionalProperties: {}
type: object
run_id:
type: string
score:
type: number
top_k_buckets:
items:
$ref: '#/definitions/provider.TopKBucket'
type: array
updated_at:
type: string
type: object
provider.Message:
properties:
content:
type: string
role:
type: string
type: object
provider.ProviderConfigSchema:
properties:
fields:
additionalProperties:
$ref: '#/definitions/provider.ProviderFieldSchema'
type: object
type: object
provider.ProviderCreateRequest:
properties:
config:
additionalProperties: {}
type: object
name:
type: string
provider:
$ref: '#/definitions/provider.ProviderType'
type: object
provider.ProviderFieldSchema:
properties:
description:
type: string
example: {}
required:
type: boolean
title:
type: string
type:
type: string
type: object
provider.ProviderGetResponse:
properties:
config:
additionalProperties: {}
type: object
created_at:
type: string
id:
type: string
is_default:
type: boolean
name:
type: string
provider:
type: string
updated_at:
type: string
type: object
provider.ProviderMeta:
properties:
config_schema:
$ref: '#/definitions/provider.ProviderConfigSchema'
display_name:
type: string
provider:
type: string
type: object
provider.ProviderType:
enum:
- builtin
type: string
x-enum-varnames:
- ProviderBuiltin
provider.ProviderUpdateRequest:
properties:
config:
additionalProperties: {}
type: object
name:
type: string
type: object
provider.RebuildResult:
properties:
fs_count:
type: integer
missing_count:
type: integer
qdrant_count:
type: integer
restored_count:
type: integer
type: object
provider.SearchResponse:
properties:
relations:
items: {}
type: array
results:
items:
$ref: '#/definitions/provider.MemoryItem'
type: array
type: object
provider.TopKBucket:
properties:
index:
description: sparse dimension index (term hash)
type: integer
value:
description: weight (term frequency)
type: number
type: object
provider.UsageResponse:
properties:
avg_text_bytes:
type: integer
count:
type: integer
estimated_storage_bytes:
type: integer
total_text_bytes:
type: integer
type: object
providers.CountResponse:
properties:
count:
@@ -1856,8 +1891,6 @@ definitions:
type: boolean
chat_model_id:
type: string
embedding_model_id:
type: string
heartbeat_enabled:
type: boolean
heartbeat_interval:
@@ -1872,7 +1905,7 @@ definitions:
type: integer
max_inbox_items:
type: integer
memory_model_id:
memory_provider_id:
type: string
reasoning_effort:
type: string
@@ -1887,8 +1920,6 @@ definitions:
type: boolean
chat_model_id:
type: string
embedding_model_id:
type: string
heartbeat_enabled:
type: boolean
heartbeat_interval:
@@ -1903,7 +1934,7 @@ definitions:
type: integer
max_inbox_items:
type: integer
memory_model_id:
memory_provider_id:
type: string
reasoning_effort:
type: string
@@ -3585,7 +3616,7 @@ paths:
"200":
description: OK
schema:
$ref: '#/definitions/memory.DeleteResponse'
$ref: '#/definitions/provider.DeleteResponse'
"400":
description: Bad Request
schema:
@@ -3613,8 +3644,7 @@ paths:
name: bot_id
required: true
type: string
- description: Skip sparse vector stats (top_k_buckets, cdf_curve) to reduce
overhead
- description: Skip optional stats in memory search response
in: query
name: no_stats
type: boolean
@@ -3624,7 +3654,7 @@ paths:
"200":
description: OK
schema:
$ref: '#/definitions/memory.SearchResponse'
$ref: '#/definitions/provider.SearchResponse'
"400":
description: Bad Request
schema:
@@ -3666,7 +3696,7 @@ paths:
"200":
description: OK
schema:
$ref: '#/definitions/memory.SearchResponse'
$ref: '#/definitions/provider.SearchResponse'
"400":
description: Bad Request
schema:
@@ -3706,7 +3736,7 @@ paths:
"200":
description: OK
schema:
$ref: '#/definitions/memory.DeleteResponse'
$ref: '#/definitions/provider.DeleteResponse'
"400":
description: Bad Request
schema:
@@ -3757,7 +3787,7 @@ paths:
"200":
description: OK
schema:
$ref: '#/definitions/memory.CompactResult'
$ref: '#/definitions/provider.CompactResult'
"400":
description: Bad Request
schema:
@@ -3780,7 +3810,7 @@ paths:
/bots/{bot_id}/memory/rebuild:
post:
description: Read memory files from the container filesystem (source of truth)
and restore missing entries to Qdrant
and restore missing entries to memory storage
parameters:
- description: Bot ID
in: path
@@ -3793,7 +3823,7 @@ paths:
"200":
description: OK
schema:
$ref: '#/definitions/memory.RebuildResult'
$ref: '#/definitions/provider.RebuildResult'
"400":
description: Bad Request
schema:
@@ -3836,7 +3866,7 @@ paths:
"200":
description: OK
schema:
$ref: '#/definitions/memory.SearchResponse'
$ref: '#/definitions/provider.SearchResponse'
"400":
description: Bad Request
schema:
@@ -3875,7 +3905,7 @@ paths:
"200":
description: OK
schema:
$ref: '#/definitions/memory.UsageResponse'
$ref: '#/definitions/provider.UsageResponse'
"400":
description: Bad Request
schema:
@@ -5363,21 +5393,43 @@ paths:
summary: Mailgun inbound email webhook
tags:
- email-webhook
/embeddings:
post:
description: Create text or multimodal embeddings
parameters:
- description: Embeddings request
in: body
name: payload
required: true
schema:
$ref: '#/definitions/handlers.EmbeddingsRequest'
/memory-providers:
get:
description: List configured memory providers
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handlers.EmbeddingsResponse'
items:
$ref: '#/definitions/provider.ProviderGetResponse'
type: array
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/handlers.ErrorResponse'
summary: List memory providers
tags:
- memory-providers
post:
consumes:
- application/json
description: Create a memory provider configuration
parameters:
- description: Memory provider configuration
in: body
name: request
required: true
schema:
$ref: '#/definitions/provider.ProviderCreateRequest'
produces:
- application/json
responses:
"201":
description: Created
schema:
$ref: '#/definitions/provider.ProviderGetResponse'
"400":
description: Bad Request
schema:
@@ -5386,13 +5438,105 @@ paths:
description: Internal Server Error
schema:
$ref: '#/definitions/handlers.ErrorResponse'
"501":
description: Not Implemented
schema:
$ref: '#/definitions/handlers.EmbeddingsResponse'
summary: Create embeddings
summary: Create a memory provider
tags:
- embeddings
- memory-providers
/memory-providers/{id}:
delete:
description: Delete memory provider by ID
parameters:
- description: Provider ID
in: path
name: id
required: true
type: string
responses:
"204":
description: No Content
"400":
description: Bad Request
schema:
$ref: '#/definitions/handlers.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/handlers.ErrorResponse'
summary: Delete a memory provider
tags:
- memory-providers
get:
description: Get memory provider by ID
parameters:
- description: Provider ID
in: path
name: id
required: true
type: string
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/provider.ProviderGetResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/handlers.ErrorResponse'
"404":
description: Not Found
schema:
$ref: '#/definitions/handlers.ErrorResponse'
summary: Get a memory provider
tags:
- memory-providers
put:
consumes:
- application/json
description: Update memory provider by ID
parameters:
- description: Provider ID
in: path
name: id
required: true
type: string
- description: Updated configuration
in: body
name: request
required: true
schema:
$ref: '#/definitions/provider.ProviderUpdateRequest'
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/provider.ProviderGetResponse'
"400":
description: Bad Request
schema:
$ref: '#/definitions/handlers.ErrorResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/handlers.ErrorResponse'
summary: Update a memory provider
tags:
- memory-providers
/memory-providers/meta:
get:
description: List available memory provider types and config schemas
responses:
"200":
description: OK
schema:
items:
$ref: '#/definitions/provider.ProviderMeta'
type: array
summary: List memory provider metadata
tags:
- memory-providers
/models:
get:
description: Get a list of all configured models, optionally filtered by type