Skip to content

Comments

Add memory plugin with semantic search and session planning#145

Merged
chriswritescode-dev merged 2 commits intomainfrom
feature/memory
Feb 23, 2026
Merged

Add memory plugin with semantic search and session planning#145
chriswritescode-dev merged 2 commits intomainfrom
feature/memory

Conversation

@chriswritescode-dev
Copy link
Owner

Summary

  • Introduces @opencode-manager/memory — a new workspace package that acts as an OpenCode plugin, providing semantic memory storage and retrieval via vector embeddings (local all-MiniLM-L6-v2, OpenAI, or Voyage AI)
  • Adds full backend routes + services (/memory), frontend Memories page, MemoryPluginConfig settings UI, and shared Zod schemas and types to integrate the plugin with the web UI
  • Includes comprehensive test coverage across the memory package (cache, embedding, hooks, memory service, planning, setup) and refactors DB migrations to a runner-based approach

Changes

New Package: @opencode-manager/memory

  • src/index.ts — Plugin entry point with setup, hooks, tools, and agents
  • src/embedding/ — Local and API-based embedding providers with server-side sync
  • src/storage/ — SQLite + vector store (vec) implementations with metadata queries
  • src/services/ — Memory service with deduplication, session state management, embedding sync
  • src/hooks/ — Keyword, session, and compaction hooks for memory lifecycle
  • src/agents/ — Code agent with memory-aware context injection for code review tasks

Backend

  • New /memory routes for CRUD, search, planning state, and embedding sync
  • Plugin loader integration for @opencode-manager/memory
  • Database migration runner with timestamped migration files

Frontend

  • New Memories page with list and form dialog for managing memories
  • New MemoryPluginConfig component in Settings for plugin configuration
  • useMemories hook for API integration
  • Updated RepoDetail to show memory plugin status

Testing

  • Full test suite in packages/memory/test/ covering all major modules
  • Tests for caching, embedding, hooks, memory service, session state, and setup
  • Refactored test imports across backend to use vitest

Scope

116 files changed, ~11,240 insertions, ~1,226 deletions

}

function normalizeBaseUrl(baseUrl: string): string {
const trimmed = baseUrl.replace(/\/+$/, '')

Check failure

Code scanning / CodeQL

Polynomial regular expression used on uncontrolled data High

This
regular expression
that depends on
library input
may run slow on strings with many repetitions of '/'.
store.delete(key)
},
async invalidatePattern(pattern: string): Promise<void> {
const regex = new RegExp(pattern.replace('*', '.*'))

Check failure

Code scanning / CodeQL

Incomplete string escaping or encoding High test

This replaces only the first occurrence of '*'.

Copilot Autofix

AI about 17 hours ago

To fix this, we should (a) ensure all * characters are handled, not just the first, and (b) avoid letting other characters in pattern be interpreted as regex metacharacters unless explicitly intended. The most robust approach is to escape the entire pattern for use inside a RegExp, then specifically transform escaped \* into .* and apply the g flag when replacing, so that every * becomes a wildcard segment and all other characters are treated literally.

Concretely, in packages/memory/test/memory-service.test.ts, inside createMockCache, change the invalidatePattern implementation. Replace new RegExp(pattern.replace('*', '.*')) with logic that:

  1. Escapes regex metacharacters in pattern using a small helper.
  2. Replaces all escaped \* with .* using a global regex.
  3. Constructs a RegExp from the resulting string.

Because we’re in a test file and can freely define small helpers, we can add a local escapeRegex function above createMockCache. No external dependencies are required, and behavior for existing single-* patterns will be preserved, while multi-* patterns will now work correctly.

Suggested changeset 1
packages/memory/test/memory-service.test.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/packages/memory/test/memory-service.test.ts b/packages/memory/test/memory-service.test.ts
--- a/packages/memory/test/memory-service.test.ts
+++ b/packages/memory/test/memory-service.test.ts
@@ -32,6 +32,11 @@
   }
 }
 
+function escapeRegex(input: string): string {
+  // Escape characters that have special meaning in regular expressions
+  return input.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
+}
+
 function createMockCache(): CacheService {
   const store = new Map<string, { value: unknown; expiry: number }>()
 
@@ -53,7 +58,11 @@
       store.delete(key)
     },
     async invalidatePattern(pattern: string): Promise<void> {
-      const regex = new RegExp(pattern.replace('*', '.*'))
+      // Treat pattern as a glob where '*' matches any sequence of characters.
+      // First escape regex metacharacters, then turn escaped '*' into '.*'.
+      const escaped = escapeRegex(pattern)
+      const regexPattern = escaped.replace(/\\\*/g, '.*')
+      const regex = new RegExp(regexPattern)
       for (const key of store.keys()) {
         if (regex.test(key)) {
           store.delete(key)
EOF
@@ -32,6 +32,11 @@
}
}

function escapeRegex(input: string): string {
// Escape characters that have special meaning in regular expressions
return input.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
}

function createMockCache(): CacheService {
const store = new Map<string, { value: unknown; expiry: number }>()

@@ -53,7 +58,11 @@
store.delete(key)
},
async invalidatePattern(pattern: string): Promise<void> {
const regex = new RegExp(pattern.replace('*', '.*'))
// Treat pattern as a glob where '*' matches any sequence of characters.
// First escape regex metacharacters, then turn escaped '*' into '.*'.
const escaped = escapeRegex(pattern)
const regexPattern = escaped.replace(/\\\*/g, '.*')
const regex = new RegExp(regexPattern)
for (const key of store.keys()) {
if (regex.test(key)) {
store.delete(key)
Copilot is powered by AI and may make mistakes. Always verify output.
@chriswritescode-dev chriswritescode-dev merged commit 3461f86 into main Feb 23, 2026
3 checks passed
@chriswritescode-dev chriswritescode-dev deleted the feature/memory branch February 23, 2026 20:36
chriswritescode-dev added a commit that referenced this pull request Feb 23, 2026
PR #145 accidentally reverted all source control enhancements from PR #138. This cherry-picks those changes back: discard changes functionality, commit detail view, commit file diffs, diff truncation, and UI improvements.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant