Commit Graph
30 Commits
Author SHA1 Message Date
can1357 2b4c33569b Merge PR #7367: fix(mnemopi): surface scoped recall failures (@roboomp) 2026-08-02 20:53:21 +02:00
roboomp e82aa25590 fix(mnemopi): contained auto-recall failures
- Caught all-target recall failures inside the fire-and-forget auto-recall path.
- Kept first-turn recall eligible for retry after an engine failure.
- Added regression coverage for the background failure contract.
2026-08-02 09:18:09 +00:00
roboomp d99adc9325 fix(mnemopi): surfaced scoped recall failures
- Warned when a scoped recall target fails while preserving partial results from healthy targets.
- Re-threw the underlying failure when every target fails so recall cannot masquerade as an empty search.
- Added tool-level regression coverage for total and partial scoped failures.

Fixes #7364
2026-08-02 09:11:36 +00:00
roboomp b9bdbcec03 fix(mnemopi): bound busy timeout on every owned bank
Extended the shutdown busy-timeout clamp from the retain bank to all owned banks so a locked shared bank (per-project-tagged) cannot stall teardown for the default 5s SQLite timeout.

Fixes #7351
2026-08-02 05:34:58 +00:00
roboomp 82095f0c12 fix(mnemopi): bounded locked retention during teardown
Capped synchronous SQLite busy waits before starting bounded final consolidation, then spent only the remaining shutdown deadline on asynchronous drains.

Added regression coverage for a locked Mnemopi writer in the headless teardown path.

Fixes #7351
2026-08-02 05:27:11 +00:00
can1357 b6e9d387d7 fix(mnemopi): derive legacy retention cursor conservatively
Pre-fix resumed sessions wrote cumulative transcript rows under the
incremental ${sessionId}-<ts> source_id shape, so summing every prefixed
legacy row could overshoot the real retained prefix and permanently skip
unseen turns. Use per-row max instead: it can only under-count, which at
worst re-stores one suffix before an explicit cursor row takes over.
Adds a regression seeding a legacy bank with two incremental rows plus a
cumulative resumed row and asserting turns 7-8 still get retained.
2026-07-22 21:13:16 +02:00
roboomp a480e99205 fix(mnemopi): retained only unretained session turns
Persisted the retained user-turn cursor in transcript metadata and restored it when sessions resume, including legacy rows from before the cursor existed.

Made forced lifecycle retention slice from that cursor so enqueue and shutdown no longer add cumulative snapshots beside incremental windows.

Fixes #6058
2026-07-21 20:34:48 +00:00
iacore cd98f6a610 Merge remote-tracking branch 'origin/main' into mnemopi 2026-07-18 11:05:24 +08:00
can1357 ca68daa81c fix(mnemopi): made recall fact ids resolvable via memory reads
recall (includeFacts) surfaces facts.fact_id as a result id, but
store.get only searched working_memory + episodic_memory, so every
surfaced fact id was a dead end for 'read memory://<id>' and
memory_edit ('not found in any scoped bank').

- store.get now falls back to the facts table (visibility mirrors
  factRecall: same-session or scope='global'), returning a read-only
  row with memory_store 'fact' and the full triple as content.
- coding-agent labels the store honestly ('fact') in memory:// reads
  and reports not_editable (instead of not_found) for memory_edit ops
  on fact ids; the facts table stays immutable.

Fixes #4725
2026-07-09 18:27:23 +02:00
iacore 831b94fee9 fix(mnemopi): skip sleep on dispose so /quit avoids cross-session bank consolidation 2026-07-08 20:49:12 +08:00
iacore d698580d67 fix(mnemopi): lighter dispose consolidation so /quit returns quickly
Interactive shutdown (AgentSession.dispose) now runs a bounded
consolidation on the current session only and skips fresh LLM fact
extraction. The heavier cross-session consolidation with extraction is
still performed by the /memory enqueue command and the backend enqueue
path.

This avoids blocking /quit and /exit on a fresh LLM round-trip
and a full sleepAllSessions scan.

- Add full and extract options to consolidate() and
  forceRetainCurrentSession()
- Route dispose() through consolidate({ full: false, extract: false })
- Route /memory enqueue and backend enqueue through
  consolidate({ full: true })

Fixes #3641
2026-07-08 19:54:18 +08:00
can1357 29340cf3cb Merge PR #4445: fix(mnemopi): let agents read stored memories in full (@roboomp)
# Conflicts:
#	packages/mnemopi/src/core/beam/recall.ts
2026-07-05 13:12:31 +02:00
can1357 45f1d63861 Merge remote-tracking branch 'origin/farm/035627c4/slice-mnemopi-retain-window' 2026-07-04 05:10:38 +02:00
roboomp 536ecc725a fix(mnemopi): let agents read stored memories in full
Recall silently clipped every result to 500 chars mid-word with no marker,
and memory_edit update replaces content wholesale by id. There was no way
for an agent to inspect the full row before overwriting it: Mnemopi.get
existed but nothing surfaced it, and the advertised URI only served the
file-backed memory summary. The natural recall/inspect/update loop had no
inspect step.

Three fixes across mnemopi and coding-agent:
- recall now appends an ellipsis marker when it clips content and reports
  truncated=true plus full_length. The cap is exposed as
  RecallOptions.contentPreviewChars (default 500, 0 disables). The factLine
  200-char clip used by the enhanced-context sandwich gets the same marker.
- Under the mnemopi backend the read-tool URI scheme now routes an id host
  to Mnemopi.get() across every session's scoped banks, returning the row
  as text/markdown with a YAML-frontmatter header (bank, store, source,
  timestamp, importance, veracity). The root namespace remains for the
  file-backed summary. Miss errors now name the backend explicitly.
- Updated the recall and memory_edit tool prompts to document the
  truncation marker and require reading the full memory before any
  wholesale content update.

Fixes #4443
2026-07-03 15:05:43 +00:00
roboomp ed715eda7b fix(mnemopi): stripped retention markers from embeddings
Added an embedText projection for remember() so stored transcripts can remain readable while embeddings, FTS indexing, and embedding-model rebuilds use marker-free text. Updated coding-agent retention to pass the marker-free projection and strip retained protocol markers from recall display.

Fixes #4395
2026-07-03 04:59:02 +00:00
roboomp 5b6385df19 fix(mnemopi): retained only new auto-retain turns
Auto-retain now slices the transcript after the last retained user turn before storing an episode, preventing cumulative duplicate session transcripts in mnemopi banks.

Fixes #4396
2026-07-03 04:50:44 +00:00
roboompandcan1357 efaad3ffb5 fix(coding-agent): bounded mnemopi consolidate-on-dispose so /quit returns within ~2 s
/quit and /exit hung for many seconds because AgentSession.dispose()
awaited MnemopiSessionState.dispose() unconditionally, and that path
runs consolidate() (state.ts:421) which fires a fresh LLM fact
extraction for the just-retained transcript and then awaits
flushExtractions() per owned bank. One LLM round-trip per shutdown,
no upper bound, no visible status.

- Add a timeoutMs option to MnemopiSessionState.dispose. When the cap
  fires the in-flight consolidate is detached to the background and the
  SQLite handles close once it settles, so writes never race a closed
  handle.
- AgentSession.dispose passes SHUTDOWN_CONSOLIDATE_BUDGET_MS = 1_500 on
  the user-visible shutdown path. Per-turn maybeRetainOnAgentEnd has
  already retained earlier turns, so the worst case is losing episodic
  promotion for the last few turns. State-replacement disposes
  (mnemopiBackend.start) stay unbounded.
- InteractiveMode.shutdown surfaces a 'Closing session…' status before
  dispose runs so the brief pause is explained rather than mysterious.

Two regression tests in memory-tools.test.ts cover (1) dispose returns
within the budget when flushExtractions stalls and the deferred close
still runs once consolidate settles, and (2) unbounded dispose still
runs the full #2320 consolidate-then-close pipeline.

Fixes #3641
2026-07-01 22:18:44 +02:00
roboomp f97e05a1c4 fix(memory): scope mnemopi extraction to user turns
- Added an extractText override to pi-mnemopi remember paths so stored content and mined facts can use different text.
- Routed coding-agent mnemopi retention to store the full transcript while extracting only user-authored turns.
- Tightened deterministic Instruction extraction to require an explicit I/you subject.

Fixes #3372
2026-06-24 14:21:26 +00:00
can1357 829d6c66dc Merge PR #2903: fix(mnemopi): make proactive linking configurable from host settings (@wolfiesch) 2026-06-21 00:09:20 +02:00
roboomp bf56a76e59 fix(mnemopi): isolated local embeddings worker in subprocess to skip onnxruntime napi crash
Moved mnemopi's local embedding provider out of the main agent process by
spawning a dedicated `Bun.spawn` child for fastembed + onnxruntime-node. The
agent CLI gains a hidden `__omp_worker_mnemopi_embed` dispatch; `loadMnemopi`
/ `loadMnemopiCore` install the subprocess-backed initializer through the
newly-exposed `setLocalModelInitializer` seam so every `embed()` call
round-trips through IPC instead of loading the NAPI module. The parent
SIGKILLs the child on dispose so the destructor that segfaults Bun on
Windows shutdown (NAPI finalizer at exit on npm installs, `process.dlopen`
constructor at session start on standalone binaries) never runs in any
address space the agent owns. Mirrors the tiny-model fix from #1607.

Adds `smokeTestMnemopiEmbedWorker` to `omp --smoke-test`, a new
`test/issue-3031-repro.test.ts` that pins the spawn/dispatch/signal-exit
contract and forbids re-importing `fastembed-runtime` from the agent surface,
and changelog entries.

Fixes #3031
2026-06-19 08:09:50 +00:00
Wolfgang Schoenberger 70f9e604f0 fix(mnemopi): scope proactive linking per memory 2026-06-18 13:29:03 -07:00
Wolfgang SchoenbergerandClaude Opus 4.8 8eb8ec4b74 fix(mnemopi): make proactive linking configurable from host settings
Proactive linking (ingesting new memories into the episodic graph as they
are stored) could only be toggled through the MNEMOPI_PROACTIVE_LINKING
environment variable, unlike its sibling recall features polyphonicRecall
and enhancedRecall, which hosts drive through configureRecallFeatures() and
the coding-agent mnemopi.polyphonicRecall / mnemopi.enhancedRecall
config.yml settings. The write-path gate in store.ts read process.env
directly and the existing env-only proactiveLinkingEnabled() helper was
dead code, so host configuration never reached it.

- Add proactiveLinking to RecallFeatureFlags / configureRecallFeatures()
  and rewrite proactiveLinkingEnabled() to fall back to the configured
  default, matching the polyphonic/enhanced resolvers. The
  MNEMOPI_PROACTIVE_LINKING env var still takes precedence when set.
- Route the store.ts proactiveLinkIfEnabled gate through
  proactiveLinkingEnabled() instead of reading process.env directly.
- Add the mnemopi.proactiveLinking coding-agent config.yml setting (off by
  default, /settings -> Memory -> Mnemopi) and wire it through
  loadMnemopiConfig and createScopedResources.

Closes #2440

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 13:29:03 -07:00
can1357 12bbefd48b feat(mnemopi): exposed polyphonic and enhanced recall via config.yml
- Added `mnemopi.polyphonicRecall` and `mnemopi.enhancedRecall` boolean settings (default off) to `settings-schema.ts` and `loadMnemopiConfig`, applied via the new `configureRecallFeatures()` in `createScopedResources`.
- Made `polyphonicRecallEnabled()`, `enhancedRecallEnabled()`, and `isEnhancedRecallEnabled()` fall back to the configured defaults while `MNEMOPI_POLYPHONIC_RECALL` / `MNEMOPI_ENHANCED_RECALL` env vars still win when set.
- Exported `configureRecallFeatures`/`RecallFeatureFlags` from the package root and `core` barrels; documented the settings in `docs/mnemosyne-memory-backend.md`.
- Added `recall-feature-flags.test.ts` covering defaults, config enablement, and env precedence; the mnemopi changelog hunk also carries the adjacent #2322 entry (same contiguous run).

Fixes #2323: Mnemopi: MNEMOPI_POLYPHONIC_RECALL and MNEMOPI_ENHANCED_RECALL not configurable via config.yml
2026-06-12 04:01:36 +02:00
roboomp 9d4fcdb536 fix(mnemopi): keep consolidate() reachable from aliased subagent enqueue
The previous refactor dropped `if (this.aliasOf) return` into
consolidate(), which made `/memory enqueue` invoked from inside a
subagent a no-op. The old enqueue() body short-circuited only
forceRetainCurrentSession (via its own guard) but still flushed
extractions and slept on state.memory, which for aliased states points
at the parent's shared retain bank.

Moved the alias guard back out of consolidate(): forceRetainCurrentSession
keeps its own early-return (the subagent's transcript is the parent's
concern), so consolidate() runs the SQL-level flush+sleep on every
owned bank for both primary and aliased states. The lifecycle guard
stays in dispose() so disposing a subagent still does not flush, sleep,
or close the parent's memory.

Added a regression test: a /memory enqueue routed through the aliased
child state calls flushExtractions + sleepAllSessions(false) on the
parent's owned memory exactly once, and forceRetainCurrentSession runs
on the child (where its own guard returns early) but not on the parent.

Addresses #2327 review.
2026-06-11 18:34:53 +00:00
roboomp 6abe6401bc fix(mnemopi): skip consolidation when clearing memory
`/memory clear` (mnemopiBackend.clear) calls dispose() right before
removing the SQLite files. Running the consolidation pass first would
make a destructive clear spend tokens/time creating memories that get
deleted on the very next line, and a slow extraction could block the
clear path under llmMode: remote.

Added a `{ consolidate?: boolean }` option to
MnemopiSessionState.dispose; defaults to true so normal shutdown still
runs the SHMR/beam pipeline. mnemopiBackend.clear passes
`{ consolidate: false }` so the close path stays unsubscribe + close
only. Added a regression test that spies on forceRetainCurrentSession,
consolidate, flushExtractions, and sleepAllSessions to pin the new
behavior, while close still runs once per owned bank.

Addresses #2327 review.
2026-06-11 18:29:23 +00:00
roboomp aba01289d0 fix(mnemopi): consolidate working memory on session shutdown
MnemopiSessionState.dispose() now drains pending fact extractions and
runs sleepAllSessions on every owned bank before closing handles, and
AgentSession.dispose() awaits the result. This matches the manual
`/memory enqueue` slash command which was the only caller of the
consolidation pipeline.

Without the shutdown hook, episodic_memory, gists, consolidation_log,
graph_edges, and triples stayed empty for every deployment that never
typed `/memory enqueue|rebuild` — working memory accumulated forever
and long-term recall never formed.

Factored the consolidate step out of `mnemopiBackend.enqueue` into a
shared MnemopiSessionState#consolidate so the slash command and the
shutdown path share one implementation. Added two regression tests
verifying owned-bank consolidation order (flush -> sleep -> close, per
bank) and that aliased subagent dispose stays a no-op against the
parent.

Fixes #2320
2026-06-11 18:24:11 +00:00
can1357 8583421362 perf(coding-agent): deferred heavy imports until first feature use
- Added lazy async module loaders for @babel/parser, linkedom, puppeteer/browsers, @mozilla/readability, @xterm/headless, and mnemopi to avoid loading them during cold startup.
- Added an interactive startup splash before session construction and skipped it for resume/fork/continue, quiet mode, timing mode, or non-TTY runs.
- Updated JS import-rewrite and memory tests to match async parser loading and preloaded mnemopi modules for sync state helpers.
2026-06-10 03:57:32 +02:00
can1357 f638a5b3e0 refactor(coding-agent): added lazy loading for heavy dependencies
- Introduced memoized dynamic import loaders for Babel parser, mnemopi modules, puppeteer, and HTML-related packages.
- Refactored eval import-rewrite helpers and runtime call sites to use asynchronous wrapping and parsing flows.
- Shifted fetch and web-scraper linkedom usage to on-demand imports so heavy modules load only when needed.
2026-06-10 03:09:09 +02:00
roboomp 66b6597829 fix(mnemopi): populated memory_embeddings on remember and auto-derived queryEmbedding on recall
The beam backend never invoked the embedding pipeline during normal
operation: `remember()`/`rememberBatch()`/`updateWorking()` skipped `embed()`
entirely and `recall()`/`recallEnhanced()` never called `embedQuery()` on
the query text. As a result `memory_embeddings` stayed empty in every
deployment and recall silently degraded to FTS-only regardless of the
configured provider (fastembed, OpenAI-compatible API, custom).

- Added `scheduleEmbedding` on `beam.pendingExtractions` (mirroring
  `scheduleFactExtraction`) and wired it from `remember`, `rememberBatch`,
  `updateWorking`, and `consolidateToEpisodic`. Writes
  `INSERT OR REPLACE INTO memory_embeddings(memory_id, embedding_json, model)`
  with the active runtime-options model, captured before the AsyncLocalStorage
  scope exits and re-entered inside the task.
- Auto-derived `queryEmbedding` inside `recall()` via `embedQuery(query)` when
  the caller did not pass one. `queryEmbedding: null` is preserved as the
  explicit FTS-only opt-out; `undefined` triggers auto-derive.
- Propagated `queryEmbedding` through `Mnemopi`'s `toRecallOptions` so the
  facade no longer strips the override on the way to the beam layer.
- Made `Mnemopi.recall`/`recallEnhanced`/`search`/`query`, the module-level
  exports, `BeamMemory.recall`/`recallEnhanced`, the free `recall`/`recallEnhanced`,
  and `orchestrateRecall` async. MCP `handleToolCall`/`callToolJson`/`handleJsonRpc`
  follow suit so the recall handler can await.
- Fixed `withBeam`/`withSharedBeam` to defer `beam.close()` until the async
  handler resolves; otherwise the new async recall hit
  `RangeError: Cannot use a closed database`.
- Updated CLI, MCP entrypoints, coding-agent `MnemopiSessionState`, and every
  affected test to await the new shapes.

Verified with a new regression suite (`test/issue-1832-embedding-population.test.ts`)
exercising both ends of the bug: empty `memory_embeddings` and zero
`dense_score`.

Fixes #1832
2026-06-04 09:22:07 +00:00
can1357 68430dee5c chore: renamed mnemosyne package to mnemopi
- Updated package name, directory, and binary from mnemosyne to mnemopi.
- Updated all lockfile references and workspace paths accordingly.
2026-05-31 08:45:12 +02:00