diff --git a/NAVI.md b/NAVI.md
index 486eeb2..a19396b 100644
--- a/NAVI.md
+++ b/NAVI.md
@@ -22,8 +22,9 @@
| `tools/` | User tools (auto-loaded at startup) |
| `tools/enabled.json` | Tools enabled across all profiles |
| `persona.txt` | Global persona injected into every profile |
-| `navi.db` | SQLite session store |
-| `workspace/` | Persistent working files |
+| `DATABASE_URL` | PostgreSQL session + memory store |
+| `workspace/` | Persistent private working files for Navi |
+| `session_files/{session_id}/` | Per-session uploads and publishable chat artifacts (`SESSION_FILES_DIR`) |
| `manuals/` | Tool manuals (served by `tool_manual`) |
## Documentation
@@ -50,7 +51,7 @@
Call the `tool_manual` tool with the relevant tool name.
-Manuals exist for: `write_tool`, `spawn_agent`, `reflect`, `gmail`, `share_file`.
+Manuals exist for: `write_tool`, `spawn_agent`, `reflect`, `gmail`, `share_file`, `content_publish`.
## Extending Navi
@@ -62,3 +63,4 @@
- Before asking the user for project facts, proactively check nearest `NAVI.md`, then `docs/`, `manuals/`, memory, files, tool schemas, or web sources.
- Treat `NAVI.md` as the active operational notebook for its directory, not just static project documentation. Update it with stable commands, conventions, local quirks, and current project decisions.
- For Navi internals, use `docs/index.md` as the documentation map before scanning broad source trees.
+- File-location rule: `workspace/` is persistent/private working storage; `session_files/{session_id}/` is the per-session area for uploads and files that `content_publish` can show in chat. To publish an artifact, put the final file in the session directory first; `content_publish` only registers it and does not copy from `workspace/`.
diff --git a/README.md b/README.md
index a5d6e77..4ef505a 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
navi-1
===============
-Модульная агентная система с REST API и WebSocket. FastAPI бэкенд, Ollama LLM, vanilla JS клиент.
+Модульная агентная система с REST API и WebSocket. FastAPI бэкенд, Ollama LLM, Vue 3 + Pinia клиент.
## Запуск
@@ -90,7 +90,7 @@
├── enabled.json # список инструментов, активных во всех профилях
├── _template.py # шаблон формата
├── get_current_datetime.py
-├── user_notes.py
+├── gmail.py
└── weather.py
manuals/ # markdown-мануалы для tool_manual
@@ -102,12 +102,13 @@
| ID | Назначение | Температура | Планирование |
|----|-----------|-------------|--------------|
-| `secretary` | Исследования, написание текстов, повседневные задачи | 0.7 | ✓ |
-| `server_admin` | Администрирование серверов, мониторинг, инфраструктура | 0.2 | ✓ |
-| `smart_home` | Home Assistant, IoT, автоматизации | 0.3 | ✓ |
-| `developer` | Написание, тестирование и отладка пользовательских инструментов | 0.2 | ✓ |
+| `secretary` | Исследования, написание текстов, повседневные задачи | 0.65 | ✓ |
+| `server_admin` | Администрирование серверов, мониторинг, инфраструктура | 0.3 | ✓ |
+| `developer` | Разработка, анализ кода, архитектура | 0.45 | ✓ |
+| `tool_developer` | Написание, тестирование и отладка пользовательских инструментов | 0.35 | ✓ |
+| `discuss` | Свободное обсуждение, мозговой штурм, лёгкие беседы | 0.85 | — |
-Каждый профиль определяет свой набор `enabled_tools`. `developer` — единственный профиль с `reload_tools`, `delete_tool` и `test_tool`; остальные профили не имеют доступа к инструментам разработки.
+`tool_developer` — единственный профиль с `reload_tools`, `delete_tool` и `test_tool`.
## Расширение
diff --git a/docs/architecture.md b/docs/architecture.md
index e95a721..beb99a9 100644
--- a/docs/architecture.md
+++ b/docs/architecture.md
@@ -37,13 +37,13 @@
▼ ▼ ▼
┌────────┐ ┌──────────────┐ ┌────────────────────────┐
│ LLM │ │ ToolRegistry│ │ SessionStore │
-│Backend │ │ (built-ins │ │ (SQLite / in-memory) │
+│Backend │ │ (built-ins │ │ (PostgreSQL) │
│(Ollama)│ │ + user tools│ │ │
└────────┘ └──────────────┘ └────────────────────────┘
│
┌─────────┴──────────┐
│ MemoryStore │
- │ (SQLite facts) │
+ │ (PostgreSQL + pgvector) │
└────────────────────┘
```
diff --git a/docs/profiles.md b/docs/profiles.md
index 910901b..70d0a61 100644
--- a/docs/profiles.md
+++ b/docs/profiles.md
@@ -80,10 +80,11 @@
| ID | Name | Models (priority order) | Temp | Planning |
|---|---|---|---|---|
-| `secretary` | Personal Secretary | gemma4:31b-cloud → gemma4:26b-a4b-it-q4_K_M | 0.7 | Yes |
-| `server_admin` | Server Administrator | gemma4:31b-cloud → gemma4:26b-a4b-it-q4_K_M | 0.2 | Yes |
-| `developer` | Developer | gemma4:31b-cloud → gemma4:26b-a4b-it-q4_K_M | 0.2 | Yes |
-| `tool_developer` | Tool Developer | gemma4:31b-cloud → gemma4:26b-a4b-it-q4_K_M | 0.2 | Yes |
+| `secretary` | Personal Secretary | gemma4:31b-cloud → gemma4:26b-a4b-it-q4_K_M | 0.65 | Yes |
+| `server_admin` | Server Administrator | gemma4:31b-cloud → gemma4:26b-a4b-it-q4_K_M | 0.3 | Yes |
+| `developer` | Developer | gemma4:31b-cloud → gemma4:26b-a4b-it-q4_K_M | 0.45 | Yes |
+| `tool_developer` | Tool Developer | gemma4:31b-cloud → gemma4:26b-a4b-it-q4_K_M | 0.35 | Yes |
+| `discuss` | Discussion | gemma4:31b-cloud → gemma4:26b-a4b-it-q4_K_M | 0.85 | No |
All profiles share a base tool set. User tools from `tools/enabled.json` are merged in at runtime.
diff --git a/docs/sessions.md b/docs/sessions.md
index afba2bf..9447383 100644
--- a/docs/sessions.md
+++ b/docs/sessions.md
@@ -108,8 +108,7 @@
Files uploaded via `POST /sessions/{id}/files` are stored in `session_files/{session_id}/`.
- Max size: `session_files_max_size_mb` (default: 200 MB)
-- TTL: `session_files_ttl_hours` (default: 24 hours)
-- A background `cleanup_loop` (started on FastAPI startup) deletes stale session directories.
+- A background `cleanup_loop` (started on FastAPI startup) deletes orphaned session directories after their DB session no longer exists.
- Executable files (`.sh`, `.py`, `.exe`, etc.) are rejected.
- Duplicate filenames get a numeric suffix.
@@ -121,6 +120,8 @@
This lets the agent use `filesystem` or `code_exec` to access the files.
+`workspace/` is separate from session files. Use `workspace/` for persistent private working files and `session_files/{session_id}/` for files that belong to the current chat. Published content uses the same session directory: `content_publish` registers a file that already exists there and exposes it through `/sessions/{id}/files/{filename}`.
+
---
## Debug endpoints
diff --git a/docs/tools.md b/docs/tools.md
index 71f476e..d993fc9 100644
--- a/docs/tools.md
+++ b/docs/tools.md
@@ -24,10 +24,17 @@
| `WriteToolTool` | `write_tool` | Write a new user tool file and reload immediately |
| `ListToolsTool` | `list_tools` | Return the live tool list from registry |
| `ToolManualTool` | `tool_manual` | Return manuals/{name}.md or auto-generate from schema |
+| `MemorySaveTool` | `memory_save` | Save a fact to long-term memory |
| `MemorySearchTool` | `memory_search` | Search long-term memory facts |
| `MemoryForgetTool` | `memory_forget` | Delete a fact from long-term memory |
| `SpawnAgentTool` | `spawn_agent` | Spawn an isolated subagent (blocking, synchronous from caller's view) |
| `SwitchProfileTool` | `switch_profile` | Switch the active profile for a session |
+| `ListProfilesTool` | `list_profiles` | List all available profiles |
+| `ContentPublishTool` | `content_publish` | Publish a session file for inline viewing in chat |
+| `ShareFileTool` | `share_file` | Share a file with the user |
+| `DeleteToolTool` | `delete_tool` | Delete a user tool file |
+| `TestToolTool` | `test_tool` | Run a user tool and verify its output |
+| `ReflectTool` | `reflect` | Self-reflection and analysis |
### User tools (`tools/*.py`)
@@ -37,7 +44,7 @@
- `tools/enabled.json` — list of user tool names to include in all profiles automatically.
- `tools/_template.py` — canonical format reference (not loaded).
-Currently present: `get_current_datetime.py`, `user_notes.py`, `text_formatter.py`, `internal_monitor.py`, `weather.py`, `gmail.py`, `instagram_engine.py`, `instagram_viewer.py`.
+Currently present: `get_current_datetime.py`, `gmail.py`, `weather.py`.
---
diff --git a/manuals/content_publish.md b/manuals/content_publish.md
index 3015145..7578026 100644
--- a/manuals/content_publish.md
+++ b/manuals/content_publish.md
@@ -2,11 +2,18 @@
## Что делает
-Публикует файл из директории сессии для просмотра пользователем прямо в чате. Поддерживаются интерактивные viewer'ы для 3D-моделей (STL), HTML-страниц, SVG, PDF, изображений и видео.
+Публикует файл из директории текущей сессии для просмотра пользователем прямо в чате. Поддерживаются интерактивные viewer'ы для 3D-моделей (STL), HTML-страниц, SVG, PDF, изображений и видео.
+
+Важно: `workspace/` и директория сессии — разные места.
+
+- `workspace/` — постоянная приватная рабочая зона Нави для черновиков, скриптов, заметок, промежуточных данных и файлов, которые могут пригодиться позже.
+- `session_files/{session_id}/` — временная зона конкретной сессии для загруженных пользователем файлов и артефактов, которые пользователь должен увидеть в чате.
+- `content_publish` публикует только файлы из директории текущей сессии. Он не копирует файлы из `workspace/`.
+- Если нужен только download link для файла из `workspace/`, используйте `share_file`: он сам копирует файл в директорию сессии. Если нужен inline viewer, файл должен оказаться в директории сессии, а затем его нужно зарегистрировать через `content_publish`.
## Как работает внутри
-1. **Файл уже должен быть в директории сессии** (`uploads/sessions/{session_id}/`).
+1. **Файл уже должен быть в директории сессии** (`session_files/{session_id}/` по умолчанию; точный корень задаёт `SESSION_FILES_DIR`).
2. Инструмент **не копирует** файл — он только регистрирует метаданные в базе данных.
3. Пользователь видит файл по URL `/sessions/{session_id}/files/{filename}`.
4. Если вы отредактируете файл после публикации, пользователь увидит изменения **сразу** (перезагружать страницу не нужно).
@@ -23,14 +30,14 @@
## Где находится директория сессии
-Директория сессии — это `uploads/sessions/{session_id}/`. Полный путь зависит от настроек сервера.
+Директория сессии — это `session_files/{session_id}/` по умолчанию. Полный путь зависит от настройки `SESSION_FILES_DIR`.
**Как узнать путь:**
```
-filesystem info uploads/sessions/{session_id}
+filesystem info session_files/{session_id}
```
-Или просто пишите файлы относительно текущей директории — если вы уже в рабочей директории, используйте полный путь через `filesystem write`.
+Если `content_publish` не нашёл файл, он вернёт точный путь директории текущей сессии. Доверяйте этому пути и пишите/копируйте файл туда.
## Типичный workflow
@@ -38,7 +45,7 @@
```
# Создать SVG в директории сессии
-filesystem write uploads/sessions/sess-abc/chart.svg ""
+filesystem write session_files/sess-abc/chart.svg ""
# Опубликовать
content_publish(filename="chart.svg", title="Диаграмма продаж")
@@ -48,10 +55,10 @@
```
# Прочитать текущий файл
-filesystem read uploads/sessions/sess-abc/chart.svg
+filesystem read session_files/sess-abc/chart.svg
# Отредактировать
-filesystem write uploads/sessions/sess-abc/chart.svg ""
+filesystem write session_files/sess-abc/chart.svg ""
```
Пользователь увидит изменения мгновенно — URL не меняется.
@@ -72,6 +79,7 @@
## Важные правила
1. **Файл должен существовать ДО вызова** — `content_publish` не создаёт файлы, только регистрирует.
-2. **Проверяйте коллизии** — если файл с таким именем уже есть, он будет перезаписан при публикации.
-3. **Используйте понятные имена** — `chart.svg` лучше чем `file_1.svg`.
-4. **Для редактирования используйте тот же путь** — не создавайте новые копии, правьте оригинал.
+2. **Не публикуйте напрямую из `workspace/`** — сначала поместите финальный файл в директорию текущей сессии.
+3. **Проверяйте коллизии** — если файл с таким именем уже есть, запись публикации будет обновлена, а файл останется тем же путём.
+4. **Используйте понятные имена** — `chart.svg` лучше чем `file_1.svg`.
+5. **Для редактирования используйте тот же путь** — не создавайте новые копии, правьте оригинал в директории сессии.
diff --git a/navi/content_store.py b/navi/content_store.py
index 9f0c2aa..34871fa 100644
--- a/navi/content_store.py
+++ b/navi/content_store.py
@@ -1,6 +1,6 @@
-"""Content store — tracks published files for inline viewing.
+"""Content store — tracks session files published for inline viewing.
-Files live in the session directory (uploads/sessions//).
+Files live in the session directory (settings.SESSION_FILES_DIR//).
Publishing only registers metadata in the DB; the file itself is NOT copied.
The URL points to the existing /sessions/{id}/files/{filename} endpoint.
"""
@@ -85,7 +85,7 @@
) -> dict:
"""Register a file from the session directory for inline viewing.
- The file must already exist in uploads/sessions/{session_id}/.
+ The file must already exist in settings.SESSION_FILES_DIR/{session_id}/.
Returns {"id": "...", "url": "...", "filename": "...", "content_type": "..."}
"""
src = ensure_session_dir(session_id) / filename
diff --git a/navi/tools/content_publish.py b/navi/tools/content_publish.py
index cfc258a..bb1fcb8 100644
--- a/navi/tools/content_publish.py
+++ b/navi/tools/content_publish.py
@@ -1,4 +1,4 @@
-"""content_publish tool — publish a file for inline viewing in the chat client.
+"""content_publish tool — publish a session file for inline viewing in chat.
The file must already exist in the session's file directory.
Publishing only registers metadata; the file itself is NOT copied.
@@ -9,7 +9,8 @@
from pathlib import Path
from navi.content_store import publish
-from navi.session_files import ensure_session_dir, session_dir
+from navi.config import settings
+from navi.session_files import session_dir
from .base import Tool, ToolResult, current_session_id
@@ -20,13 +21,19 @@
"Publish a file for inline viewing in the chat client. "
"Use this when you generate or produce content the user will want to see interactively "
"(3D models, HTML pages, SVG graphics, images, videos, PDFs, etc.).\n\n"
- "IMPORTANT — the file MUST already be inside the session directory. "
- "Before publishing, write or move the file into the session folder. "
- "To find the session directory path, use `filesystem info ` or write directly to it. "
+ "There are two different file areas: workspace/ is for persistent private working files; "
+ "the session directory is for files visible to the user in this chat. "
+ "IMPORTANT — the file MUST already be inside the current session directory. "
+ "The default path is session_files/{session_id}/, but the root is configured by "
+ "SESSION_FILES_DIR. This tool does NOT copy from workspace/. "
+ "Before publishing, write, copy, or move the final file into the session folder. "
"If a file with the same name already exists in the session directory, choose a different name "
"or check the directory contents first with `filesystem list `.\n\n"
"Best practices:\n"
- "- Always create files in the session directory (uploads/sessions/{session_id}/)\n"
+ "- Use workspace/ for drafts and reusable work files\n"
+ "- Use the session directory for final artifacts the user should view now\n"
+ "- If a file already exists elsewhere and only needs a download link, use share_file instead\n"
+ "- If a file exists elsewhere but needs an inline viewer, copy it into the session directory first\n"
"- Use descriptive filenames (e.g., 'sales_chart.svg' not 'file.svg')\n"
"- After publishing, you can edit the file directly and the user will see changes immediately\n"
"- For images, use PNG or JPEG; for interactive content, use HTML or SVG"
@@ -73,7 +80,9 @@
success=False,
output=(
f"File '{filename}' not found in the session directory: {sess_dir}\n"
- f"Make sure the file was written or moved there before publishing. "
+ f"SESSION_FILES_DIR is configured as: {settings.session_files_dir}\n"
+ f"Make sure the file was written, copied, or moved there before publishing. "
+ f"`workspace/` is separate and is not publishable directly. "
f"You can check the directory contents with `filesystem list {sess_dir}`."
),
error="not_found",
diff --git a/persona.txt b/persona.txt
index 1e12c87..6457f26 100644
--- a/persona.txt
+++ b/persona.txt
@@ -24,8 +24,21 @@
- Never switch back and forth repeatedly within one conversation.
- When unsure which profile fits, call list_profiles.
-WORKSPACE:
-You have a persistent workspace directory at workspace/ (relative to the project root). Use it freely for any long-term files: scripts, notes, data, configs, research results. Do NOT write working files to the project root.
+FILE LOCATIONS:
+You have two different file areas. Do not confuse them.
+
+1. Persistent workspace: `workspace/` (relative to the project root).
+Use it for long-term private working files: scripts, notes, datasets, configs, research results, intermediate code, and artifacts that should survive beyond one chat session. Do NOT write working files to the project root.
+
+2. Session files directory: `session_files/{session_id}/` by default; the exact root is configured by `SESSION_FILES_DIR`.
+This is the per-session file area used for user uploads and files the user should view in the chat. `content_publish` can publish ONLY files that already exist directly inside the current session directory. It does not copy files from `workspace/`.
+
+Decision rule:
+- If the file is private, reusable later, or part of your own work process — use `workspace/`.
+- If the user should open, preview, download, or see live updates to the file in this chat — create or move it into the current session directory, then call `content_publish`.
+- If you create something in `workspace/` and later decide to publish it, copy or rewrite the final artifact into the session directory first.
+- If the user only needs a download link for an existing local file, `share_file` can copy it into the session directory. If the user needs an inline viewer card, the file must be in the session directory and then `content_publish` registers it.
+- To discover the exact session directory, call `content_publish` after checking/creating the intended filename, or inspect the filesystem path from uploaded-file hints/tool output. When a publish fails, trust the error message's session directory path.
EXECUTION MODES:
By default you operate collaboratively — you may flag risks and confirm before irreversible actions.