* feat(memory): add OPENAI_EMBEDDING_BATCH_DELAY support * docs(memory): update SKILL.md for progressive enhancement and auto-setup * docs(memory): update AGENTS.md tool usage policy * docs(memory): fix stale snake_case tool references in skills, agents, tools * docs(handoff): add handoff + ADR for reindex-skill-update * docs(handoff): set PR number * refactor(memory): extract _embed_in_batches to satisfy xenon rank A --------- Co-authored-by: opencode-agent <agent@opencode.local>
104 lines
No EOL
8.7 KiB
Markdown
104 lines
No EOL
8.7 KiB
Markdown
---
|
||
pr: 104
|
||
title: Reindex memory + update SKILL.md/AGENTS.md for kebab-case tools
|
||
---
|
||
|
||
## Что сделано
|
||
|
||
Финальная фаза починки памяти (issue #99, часть #94). После PR #100–#103
|
||
(Python safe, 5 TS tools, E2E tests, remove plugin + Rust) — переиндекс + docs.
|
||
|
||
### 1. Переиндекс памяти через Python
|
||
|
||
Запущен `uv run python -m src.memory index` из `/root/workspace/opencode-config`.
|
||
Env vars (`OPENAI_BASE_URL`, `OPENAI_API_KEY`, `OPENAI_EMBEDDING_MODEL=qwen/qwen3-embedding-8b`)
|
||
наследованы из окружения — OpenRouter ответил.
|
||
|
||
Результат:
|
||
- `.rag/index.json` — 239 MB (было 220 MB), 2584 entries (было 2379), 4096-dim embeddings
|
||
- `.rag/meta.json` — создан, `version: "qwen/qwen3-embedding-8b:512:64"` (Python формат, `version` key — НЕ `model_id` который был Rust)
|
||
- `.rag/reindex.log` — финальная строка `done: total=86 took=286s changed=86 unchanged=0 deleted=0` (incremental: 86 изменившихся файлов переиндексировано, остальные merged из старого index.json)
|
||
- `.rag/index.bin` — НЕ существует (Rust, удалён в PR #103)
|
||
- Время: 2026-07-26 22:55 (свежее)
|
||
|
||
### 2. `OPENAI_EMBEDDING_BATCH_DELAY` — добавлена поддержка в код + `.env.example`
|
||
|
||
Issue #99 просил добавить `OPENAI_EMBEDDING_BATCH_DELAY=0.5` в `.env.example`, но
|
||
embedder.py НЕ поддерживал эту env var. Добавлена:
|
||
- `src/memory/embedder.py`: `BATCH_DELAY = float(os.environ.get("OPENAI_EMBEDDING_BATCH_DELAY", "0"))` + `time.sleep(BATCH_DELAY)` между батчами (только если `BATCH_DELAY > 0` и не последний батч)
|
||
- `.env.example`: `OPENAI_EMBEDDING_BATCH_DELAY=0.5` с комментарием про OpenRouter rate limits
|
||
- Default `0` (без задержки) — backwards compatible, не ломает существующие вызовы
|
||
|
||
Проверка: env var уже set в окружении (`=1`), import OK, E2E 4 passed.
|
||
|
||
### 3. SKILL.md (memory) — обновлён
|
||
|
||
`.opencode/skills/memory/SKILL.md`:
|
||
- Добавлена секция "Аритектура (progressive enhancement)": keyword всегда, semantic если `OPENAI_BASE_URL` set, fallback (OpenRouter упал → keyword), auto-setup (первый `memory-save` всё создаёт), `memory-doctor` как read-only диагностика
|
||
- Убрано упоминание `@mathew-cf/opencode-memory` plugin (было "Плагин удалён" — стало "без wrapper-hop, без MCP-плагина")
|
||
- Убрано упоминание `memory-setup` (удалённый tool)
|
||
- Исправлен default путь: `~/opencode-memory` (устаревший) → `/root/.local/share/opencode/opencode-memory` (актуальный, соответствует `_memory-shared.ts:17`)
|
||
- Tools уже были kebab-case (`memory-search`, `memory-save`, `memory-list`, `memory-access`, `memory-doctor`) — проверено, не требовало правок
|
||
|
||
### 4. AGENTS.md — обновлён
|
||
|
||
`AGENTS.md` (root):
|
||
- Tool Usage Policy таблица — уже содержала 5 kebab-case tools (`memory-doctor`, `memory-save`, `memory-search`, `memory-list`, `memory-access`)
|
||
- Убрано упоминание `memory-setup` из описания `memory-doctor` (было "замена `memory-setup`" — стало чистое описание)
|
||
|
||
### 5. Stale references — найдены и обновлены
|
||
|
||
Поиск `grep -rnE "memory_(search|save|list|access|setup|doctor)"` по `.opencode/`, `docs/`, `AGENTS.md`:
|
||
|
||
**Активные файлы (обновлены):**
|
||
- `.opencode/skills/memory/SKILL.md` — `memory-setup` упоминание убрано
|
||
- `.opencode/skills/run-pipeline/SKILL.md` — `memory_save` → `memory-save` (2 места), `app_data/opencode-memory` → `<memory_dir>/repos/...`
|
||
- `.opencode/skills/repo-init/SKILL.md` — `memory_save` → `memory-save` (gotcha-блок)
|
||
- `.opencode/skills/release/SKILL.md` — `memory_save` → `memory-save` (gotcha-блок)
|
||
- `.opencode/skills/configure-opencode/SKILL.md` — `memory_save` → `memory-save` (gotcha-блок)
|
||
- `.opencode/skills/add-skill/SKILL.md` — `memory_save` → `memory-save` (gotcha-блок)
|
||
- `.opencode/skills/spec/SKILL.md` — `memory_search` → `memory-search` (6 мест, replaceAll)
|
||
- `.opencode/skills/issue/SKILL.md` — `app_data/opencode-memory` → `<memory_dir>/repos/...`
|
||
- `.opencode/agents/memory-syncer.md` — `memory_save` → `memory-save` (2 места), `app_data/opencode-memory` → `<memory_dir>` (3 места)
|
||
- `.opencode/commands/spec.md` — `memory_search` → `memory-search`
|
||
- `.opencode/tools/memory-access.ts` — `memory_save` → `memory-save` (user-facing message)
|
||
- `.opencode/tools/memory-doctor.ts` — `memory_save`/`memory_search` → `memory-save`/`memory-search` (4 user-facing messages)
|
||
- `.opencode/tools/memory-search.ts` — `memory_save` → `memory-save` (user-facing message)
|
||
|
||
**Исторические файлы (НЕ тронуты — snake_case отражает реальные имена на момент написания):**
|
||
- `docs/decisions/*.md` — 20+ ADR (ADR-014, 022, 023, 024, 026, 030, 032, 033, 035, 036, 037, 038, 039, 043, 045)
|
||
- `docs/handoff/*.md` — 15+ handoffs (pr-36, 53, 57, 63, 71, 75, 77, 78, 80, 83, 89, 101, 103)
|
||
|
||
### 6. Memory file `technical/rag-cli-embeddings-model.md` — переписан
|
||
|
||
`~/.local/share/opencode/opencode-memory/technical/rag-cli-embeddings-model.md`:
|
||
- Был: описание Rust rag-cli как активного (candle-transformers, all-MiniLM-L6-v2, 384-dim, GLIBC 2.39)
|
||
- Стал: описание Python + OpenRouter как единственного пути semantic (qwen/qwen3-embedding-8b, 4096-dim, progressive enhancement, auto-setup)
|
||
- Зафиксировано что удалено: `@mathew-cf/opencode-memory` plugin, `@mathew-cf/rag-cli` Rust binary, `setup-memory.sh`, `memory-setup.ts`, `.rag/index.bin`, `meta.json` с `model_id`
|
||
- Ссылки на ADR-030, 036, 043, 045
|
||
|
||
### 7. E2E тест
|
||
|
||
`RUN_LIVE=1 uv run pytest tests/test_memory_tools_e2e.py -x -q --no-cov` — 4 passed (до и после правок embedder.py).
|
||
|
||
## Почему
|
||
|
||
PR #100–#103 сделали инфраструктуру (Python safe, 5 TS tools, E2E, remove plugin + Rust),
|
||
но:
|
||
- Индекс был старый (17:19, без `meta.json` — Python incremental reindex не мог определить version mismatch)
|
||
- Документация (SKILL.md, AGENTS.md, skills, agents, TS tools) содержала stale snake_case tool names (`memory_save`, `memory_search`) — agents могли вызывать несуществующие tools
|
||
- `OPENAI_EMBEDDING_BATCH_DELAY` была в issue #99 как требование, но не поддерживалась в коде — добавление в `.env.example` без поддержки вводило бы в заблуждение
|
||
- Memory file `rag-cli-embeddings-model.md` описывал Rust rag-cli как активный — агенты могли пытаться использовать удалённый путь
|
||
|
||
Без этого PR: semantic search работал (index.json был), но docs лгали агентам про tool names → агенты могли вызывать `memory_save` (snake_case) и получать "tool not found".
|
||
|
||
## Pending
|
||
|
||
— (переиндекс выполнен, env vars были в окружении)
|
||
|
||
## Watch out
|
||
|
||
- **Reindex требует env vars** (`OPENAI_BASE_URL`, `OPENAI_API_KEY`). Без них `embed_texts` возвращает `None`, индекс не строится. Keyword search продолжает работать. Если env vars отсутствуют при деплое — reindex нужно запустить вручную после настройки env.
|
||
- **`OPENAI_EMBEDDING_BATCH_DELAY` default `0`** в коде — backwards compatible. `.env.example` рекомендует `0.5` для OpenRouter. В текущем окружении set `=1` (унаследовано).
|
||
- **`docs/decisions/` и `docs/handoff/` содержат snake_case** (`memory_save`, `memory_search`) — это исторические записи, отражают реальные имена tools на момент написания. НЕ трогать.
|
||
- **Reindex был incremental** (86 changed файлов, 286s) — не полный. Полный reindex при `meta.json` отсутствии или `version` mismatch. Если нужен полный — удалить `.rag/meta.json` + `.rag/index.json` и запустить снова. |