@lotargo/memory_plugin 1.4.621 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +352 -366
  2. package/mcp-server/admin/auth.js +31 -4
  3. package/mcp-server/cli/direct_commands.js +313 -0
  4. package/mcp-server/cli/handlers/cloud_actions.js +138 -0
  5. package/mcp-server/cli/handlers/diagnostics_actions.js +107 -0
  6. package/mcp-server/cli/handlers/engine_actions.js +214 -0
  7. package/mcp-server/cli/handlers/prompt_actions.js +24 -0
  8. package/mcp-server/cli/handlers/storage_actions.js +749 -0
  9. package/mcp-server/cli/quick_stats.js +39 -0
  10. package/mcp-server/cli/ui.js +565 -0
  11. package/mcp-server/cli.js +324 -2085
  12. package/mcp-server/config/auth_store.js +56 -9
  13. package/mcp-server/config/config_manager.js +1 -0
  14. package/mcp-server/db/database.js +14 -1
  15. package/mcp-server/db/migrations.js +28 -0
  16. package/mcp-server/fact_format.js +244 -177
  17. package/mcp-server/identity.js +152 -0
  18. package/mcp-server/index.js +42 -679
  19. package/mcp-server/memory.js +50 -63
  20. package/mcp-server/prompt_manager.js +1 -1
  21. package/mcp-server/tools/helpers.js +39 -0
  22. package/mcp-server/tools/identity_tools.js +277 -0
  23. package/mcp-server/tools/index.js +9 -0
  24. package/mcp-server/tools/memory_tools.js +506 -0
  25. package/mcp-server/tools/rag_tools.js +235 -0
  26. package/opencode-plugin/index.js +460 -48
  27. package/package.json +7 -3
  28. package/skills/using-memory/SKILL.md +31 -14
  29. package/mcp-server/benchmarks/fetch_real_corpus.js +0 -351
  30. package/mcp-server/benchmarks/gpu_profile_benchmark.js +0 -170
  31. package/mcp-server/benchmarks/quality_evaluator.js +0 -600
  32. package/mcp-server/benchmarks/run_benchmarks.js +0 -347
  33. package/mcp-server/benchmarks/stress_ingestion.js +0 -195
  34. package/mcp-server/benchmarks/test_dual_layer.js +0 -140
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "@lotargo/memory_plugin",
3
- "version": "1.4.621",
3
+ "version": "1.5.0",
4
4
  "description": "100% local hybrid RAG memory for AI coding agents (OpenCode, Claude Code, Codex, Antigravity). MCP server + plugin: persistent user facts, document ingestion, vector + SQLite FTS5 retrieval across sessions.",
5
5
  "type": "module",
6
6
  "main": "opencode-plugin/index.js",
7
7
  "scripts": {
8
- "preinstall": "node mcp-server/preinstall.js || true"
8
+ "preinstall": "node mcp-server/preinstall.js || true",
9
+ "test": "node mcp-server/test.js",
10
+ "benchmark": "node mcp-server/benchmarks/run_benchmarks.js"
9
11
  },
10
12
  "bin": {
11
13
  "memory_plugin": "mcp-server/index.js",
@@ -15,7 +17,7 @@
15
17
  "files": [
16
18
  "opencode-plugin",
17
19
  "mcp-server/admin",
18
- "mcp-server/benchmarks",
20
+ "mcp-server/cli",
19
21
  "mcp-server/config",
20
22
  "mcp-server/db",
21
23
  "mcp-server/graph",
@@ -23,9 +25,11 @@
23
25
  "mcp-server/ml",
24
26
  "mcp-server/retrieval",
25
27
  "mcp-server/storage",
28
+ "mcp-server/tools",
26
29
  "mcp-server/cli.js",
27
30
  "mcp-server/index.js",
28
31
  "mcp-server/fact_format.js",
32
+ "mcp-server/identity.js",
29
33
  "mcp-server/memory.js",
30
34
  "mcp-server/setup.js",
31
35
  "mcp-server/preinstall.js",
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: using-memory
3
- description: Comprehensive guide for using the Memory, Hybrid RAG Knowledge Engine & MCP Helper tools (remember, recall, forget, update_fact, memory_info, link_knowledge, ingest_document, query_knowledge_base, manage_knowledge_base, list-mcp-tools, mcp-reminder). Trigger proactively whenever user preferences, project conventions, technology stack choices, or architecture decisions are introduced, or when querying ingested documentation, indexing files/repos, managing persistent knowledge, or looking up available MCP tool integrations.
3
+ description: Comprehensive guide for using the Memory, Hybrid RAG Knowledge Engine & MCP Helper tools (remember, recall, get_fact, forget, update_fact, memory_info, link_knowledge, link_project_memory, unlink_project_memory, relink_project_memory, ingest_document, query_knowledge_base, manage_knowledge_base, list-mcp-tools, mcp-reminder). Trigger proactively whenever user preferences, project conventions, technology stack choices, or architecture decisions are introduced, or when querying ingested documentation, indexing files/repos, managing persistent knowledge, or looking up available MCP tool integrations.
4
4
  ---
5
5
 
6
6
  # Using Memory, Hybrid RAG Knowledge Engine & MCP Helper Tools
@@ -17,19 +17,23 @@ You have access to a persistent dual-layer memory engine supercharged with an **
17
17
 
18
18
  | Scenario / Intent | Target Tool | Key Parameters |
19
19
  |-------------------|-------------|----------------|
20
- | User shares identity, tech stack preference, or workflow rule | `remember` | `fact` (English), `scope`, optional `docId`, `startLine`, `endLine` |
21
- | User asks what you remember about them, the project, or linked docs | `recall` | `scope` ("all", "global", or "project"), optional `query`, `tags`, `since`, `until`, `project` |
20
+ | User shares identity, tech stack preference, or workflow rule | `remember` | `fact` (English), `title` (concise 2-5 word headline), `scope`, optional `docId`, `startLine`, `endLine` |
21
+ | User asks what you remember about them, the project, or linked docs | `recall` | `scope` ("all", "global", "project", "list_projects"), `mode` ("full", "headers"), `offset`, `limit`, optional `query`, `tags`, `since`, `until`, `project` (at session start, MUST fetch all memories with `scope: "all"` without restrictive query filters) |
22
+ | Get a single fact's text and metadata by ID | `get_fact` | `id` (metadata id e.g. "8f3a2c"), `scope` |
22
23
  | User corrects/updates an old saved fact | `update_fact` | `id` (number/id/text), `newText`, `scope` |
23
24
  | Replace a fact but keep a version trail | `remember` | `fact`, `supersedes` (number/id/text) |
24
25
  | Protect a fact from accidental `forget` | `remember` | `keep: true` |
25
26
  | Set a time-to-live on a fact | `remember` | `ttl` ("90d", "2w", "24h", "12m") |
26
27
  | Filter facts by keyword / tags / date | `recall` | `query`, `tags`, `since`, `until` |
27
- | Show storage paths, versions, fact & RAG stats | `memory_info` | — |
28
- | Connect a Notebook fact to a document, section, or line range | `link_knowledge` | `factText`, `docId`, `startLine`, `endLine`, `relationType` |
29
- | User asks to index a documentation URL, file, or repository | `ingest_document` | `content` or `source_path`, `title`, `metadata` |
30
- | User asks a complex question about indexed docs or code | `query_knowledge_base` | `query`, `limit`, `generateEmbeddings` |
28
+ | Show storage paths, versions, fact & RAG stats, git identity | `memory_info` | — |
29
+ | Connect a Notebook fact to a document, section, or line range | `link_knowledge` | `action` ("link", "list_links", "get_doc_links"), `factText`, `docId`, `startLine`, `endLine`, `relationType` |
30
+ | Link directory to Git project identity / migrate legacy stores | `link_project_memory` | `directory`, optional `remote` |
31
+ | Remove path alias or purge project identity | `unlink_project_memory` | `directory`, `purge` (boolean) |
32
+ | Move or merge project memories to new target identity | `relink_project_memory` | `directory`, `remote` (target remote URL) |
33
+ | User asks to index a documentation URL, file, or repository | `ingest_document` | `content` (text/file path/URL), `type` ("text", "file", "url"), `title`, `path` |
34
+ | User asks a complex question about indexed docs or code | `query_knowledge_base` | `query`, `limit`, `instruction`, `generateEmbeddings` |
31
35
  | Read full raw content of an ambiguous/abstract document | `manage_knowledge_base` | `action: "read_document"`, `docId` |
32
- | User asks to view database stats, list indexed docs, or export snapshots | `manage_knowledge_base` | `action` ("stats", "list", "read_document", "delete", "export_snapshot", "import_snapshot") |
36
+ | View DB stats, list indexed docs, read/delete docs, export/import snapshots | `manage_knowledge_base` | `action` ("stats", "list", "read_document", "delete", "export_snapshot", "import_snapshot"), `docId`, `snapshotPath` |
33
37
  | Discover available MCP servers and their specific purposes | `list-mcp-tools` | — |
34
38
  | Ask which MCP tool / server is suitable for a specific task | `mcp-reminder` | `task` (string, e.g., "db migration") |
35
39
 
@@ -44,10 +48,13 @@ Whenever you ingest project documentation, web pages, or local files, you should
44
48
 
45
49
  ### What to Save and Link (`remember` & `link_knowledge`)
46
50
  - **High-Signal Facts**: User name, role, language preferences, architectural constraints, framework choices, coding standards, test rules.
47
- - **Formating**: Always translate the fact into clear, concise English before calling `remember`.
51
+ - **Formatting & Fact Titles**:
52
+ - Always translate the fact into clear, concise English before calling `remember`.
53
+ - **Always specify a descriptive `title` parameter** (a 2-5 word headline, e.g., `title: "Backend Framework Preference"`).
54
+ - Facts are stored in `**Title** — body` format. In `mode: "full"` (default in `recall`), both title and body are displayed. In `mode: "headers"` and in auto-injected `<MEMORY>` system prompt blocks, only `**Title**` is displayed to keep the system prompt lean.
48
55
  - **Linking to Knowledge Base Documents**:
49
56
  - Pass `docId` (or document title/path) and optional `startLine` / `endLine` when calling `remember` or `link_knowledge`.
50
- - Example: `remember(fact: "Use Fastify instead of Express for backend services", scope: "project", docId: "arch_specs.md", startLine: 5, endLine: 7)`
57
+ - Example: `remember(title: "Backend Framework Preference", fact: "Use Fastify instead of Express for backend services", scope: "project", docId: "arch_specs.md", startLine: 5, endLine: 7)`
51
58
  - Example: `link_knowledge(factText: "Use PostgreSQL 16 for primary persistence", docId: "database_guide.md", startLine: 20, endLine: 35, relationType: "IMPLEMENTS")`
52
59
 
53
60
  ### How Linked Memory Appears (`recall`)
@@ -76,12 +83,16 @@ Supported metadata keys (set via `remember`, rendered as badges by `recall`):
76
83
  - `tags`: comma-separated tags for later filtering, e.g. `"pref,arch"`.
77
84
  - `supersedes`: number (as listed by `recall`), metadata `id`, or text of the fact this one replaces.
78
85
 
79
- ### Filtering Facts (`recall`)
86
+ ### Filtering & Viewing Facts (`recall` & `get_fact`)
87
+ - `scope`: `"all"` (default), `"global"`, `"project"`, or `"list_projects"` (lists all project stores, total facts, file paths, and git identity bindings).
80
88
  - `query`: all space-separated terms must match (case-insensitive); searches text, id, tags, and date.
81
89
  - `tags`: comma-separated; returns facts with ANY matching tag.
82
90
  - `since` / `until`: "YYYY-MM-DD" (inclusive) to filter by fact date.
83
91
  - `project`: read a specific project's store from any working directory.
84
- - Output shows `[EXPIRED]`, `[KEEP]`, `[SUPERSEDED]` badges and the `Store file:` path.
92
+ - `mode`: `"full"` (default) or `"headers"` (returns title and badges only, omitting full text body).
93
+ - `offset` / `limit`: optional numeric pagination parameters.
94
+ - `get_fact`: fetch exact text and full metadata of a single fact by its metadata id (e.g. `get_fact(id: "8f3a2c")`).
95
+ - Output shows `[EXPIRED]`, `[KEEP]`, `[SUPERSEDED]`, `[INJECT]` badges and the `Store file:` path.
85
96
 
86
97
  ### Updating Facts (`update_fact`)
87
98
  When the user corrects an old fact, prefer `update_fact` over `forget`+`remember` — it rewrites the text while preserving the original date and all metadata (`ttl`, `keep`, `tags`, `supersedes`), and re-points any linked Knowledge Base documents.
@@ -92,8 +103,14 @@ When the user corrects an old fact, prefer `update_fact` over `forget`+`remember
92
103
  ### Protecting Facts (`forget` with `keep`)
93
104
  `forget` refuses to delete facts saved with `keep: true`; pass `force: true` to override. It still supports deleting by index number, range ("3-30"), or text.
94
105
 
106
+ ### Project Memory Identity Management (`link_project_memory`, `unlink_project_memory`, `relink_project_memory`)
107
+ Project stores are bound to Git-based project identities (`git:remote` or `git:local:<repo basename>`). Use these tools to manage bindings:
108
+ - `link_project_memory(directory, remote)`: Links a working directory to a Git identity, registers path/remote aliases, and automatically merges any legacy path-based stores.
109
+ - `unlink_project_memory(directory, purge)`: Removes the path alias link for a directory; set `purge: true` to purge the identity from SQLite.
110
+ - `relink_project_memory(directory, remote)`: Moves and merges memories from the current project identity to a new target remote URL identity.
111
+
95
112
  ### Storage Diagnostics (`memory_info`)
96
- `memory_info` returns the package version, `MEMORY_DIR`, SQLite DB path, store-file locations, fact counts per store, and RAG stats (documents, sections, chunks, graph edges, links).
113
+ `memory_info` returns the package version, `MEMORY_DIR`, SQLite DB path, store-file locations, fact counts per store, Git identity info, and RAG stats (documents, sections, chunks, graph edges, links).
97
114
 
98
115
  ---
99
116
 
@@ -176,7 +193,7 @@ When working in multi-server environments (e.g., OpenCode, Claude Code), you mig
176
193
 
177
194
  ## 5. Core Directives for AI Agents
178
195
 
179
- 1. **Read Memories First (MANDATORY)**: At the very start of any session or conversation, your VERY FIRST STEP MUST BE to execute `recall` to load all saved facts, user context, and project guidelines BEFORE performing any other task or code analysis.
196
+ 1. **Read Memories First (MANDATORY)**: At the very start of any session or conversation, your VERY FIRST STEP MUST BE to execute `recall` with `scope: "all"` (and without restrictive query filters) to load ALL saved global facts, user context, and project guidelines BEFORE performing any other task or code analysis. Do NOT filter or restrict the initial `recall` call with specific query keywords.
180
197
  2. **Be Proactive**: When the user mentions a durable preference, personal fact, or constraint, save it immediately using `remember`. Do not wait for explicit user commands.
181
198
  3. **Check Knowledge Base First**: If a query is related to specialized documentation, APIs, or project architectures, call `query_knowledge_base` using concept-dense search phrases.
182
199
  4. **Inspect Ambiguous Docs Directly**: If querying produces low relevance scores on abstractly-named documents, call `manage_knowledge_base(action: "read_document")` to inspect the full text directly.
@@ -1,351 +0,0 @@
1
- import { readFile, readdir, stat, rm, mkdir as mkdirAsync, writeFile as writeFileAsync } from "node:fs/promises";
2
- import { existsSync } from "node:fs";
3
- import { join } from "node:path";
4
- import { MEMORY_DIR } from "../memory.js";
5
-
6
- export const CORPUS_DIR = join(MEMORY_DIR, "cache", "benchmark_corpus");
7
- const PANEL_WIDTH = 58;
8
-
9
- function printRichPanel(title, subtitle = "") {
10
- const line = "─".repeat(PANEL_WIDTH - 2);
11
- console.log(`\x1b[36m╭${line}╮\x1b[0m`);
12
- console.log(`\x1b[36m│\x1b[0m \x1b[1m\x1b[37m${title.padEnd(PANEL_WIDTH - 6)}\x1b[0m \x1b[36m│\x1b[0m`);
13
- if (subtitle) {
14
- console.log(`\x1b[36m│\x1b[0m \x1b[90m${subtitle.padEnd(PANEL_WIDTH - 6)}\x1b[0m \x1b[36m│\x1b[0m`);
15
- }
16
- console.log(`\x1b[36m╰${line}╯\x1b[0m`);
17
- }
18
-
19
- const RAW_DOC_SOURCES = [
20
- // Frontend frameworks & libraries
21
- { id: "react_readme", title: "React README", url: "https://raw.githubusercontent.com/facebook/react/main/README.md" },
22
- { id: "react_license", title: "React License", url: "https://raw.githubusercontent.com/facebook/react/main/LICENSE" },
23
- { id: "vue_readme", title: "Vue.js README", url: "https://raw.githubusercontent.com/vuejs/core/main/README.md" },
24
- { id: "svelte_readme", title: "Svelte README", url: "https://raw.githubusercontent.com/sveltejs/svelte/main/README.md" },
25
- { id: "nextjs_readme", title: "Next.js README", url: "https://raw.githubusercontent.com/vercel/next.js/canary/packages/next/README.md" },
26
- // Build tools & bundlers
27
- { id: "vite_readme", title: "Vite README", url: "https://raw.githubusercontent.com/vitejs/vite/main/README.md" },
28
- { id: "esbuild_readme", title: "esbuild README", url: "https://raw.githubusercontent.com/evanw/esbuild/main/README.md" },
29
- { id: "webpack_readme", title: "Webpack README", url: "https://raw.githubusercontent.com/webpack/webpack/main/README.md" },
30
- // Backend & runtime
31
- { id: "express_readme", title: "Express.js README", url: "https://raw.githubusercontent.com/expressjs/express/master/Readme.md" },
32
- { id: "fastapi_readme", title: "FastAPI README", url: "https://raw.githubusercontent.com/fastapi/fastapi/master/README.md" },
33
- { id: "flask_readme", title: "Flask Python README", url: "https://raw.githubusercontent.com/pallets/flask/main/README.md" },
34
- { id: "deno_readme", title: "Deno Engine README", url: "https://raw.githubusercontent.com/denoland/deno/main/README.md" },
35
- { id: "bun_readme", title: "Bun Runtime README", url: "https://raw.githubusercontent.com/oven-sh/bun/main/README.md" },
36
- // Languages
37
- { id: "golang_readme", title: "Go Language README", url: "https://raw.githubusercontent.com/golang/go/master/README.md" },
38
- { id: "rust_readme", title: "Rust Language README", url: "https://raw.githubusercontent.com/rust-lang/rust/master/README.md" },
39
- { id: "typescript_readme", title: "TypeScript README", url: "https://raw.githubusercontent.com/microsoft/TypeScript/main/README.md" },
40
- // State management & data
41
- { id: "redux_readme", title: "Redux README", url: "https://raw.githubusercontent.com/reduxjs/redux/master/README.md" },
42
- { id: "prisma_readme", title: "Prisma ORM README", url: "https://raw.githubusercontent.com/prisma/prisma/main/README.md" },
43
- { id: "graphql_js_readme", title: "GraphQL.js README", url: "https://raw.githubusercontent.com/graphql/graphql-js/v16.8.1/README.md" },
44
- // Databases
45
- { id: "sqlite_readme", title: "SQLite README", url: "https://raw.githubusercontent.com/sqlite/sqlite/master/README.md" },
46
- // CSS & styling
47
- { id: "tailwindcss_readme", title: "Tailwind CSS README", url: "https://raw.githubusercontent.com/tailwindlabs/tailwindcss/master/README.md" },
48
- // Testing
49
- { id: "playwright_readme", title: "Playwright README", url: "https://raw.githubusercontent.com/microsoft/playwright/main/README.md" },
50
- // Networking & HTTP
51
- { id: "axios_readme", title: "Axios HTTP README", url: "https://raw.githubusercontent.com/axios/axios/v1.x/README.md" },
52
- // Utilities
53
- { id: "lodash_readme", title: "Lodash Utility README", url: "https://raw.githubusercontent.com/lodash/lodash/master/README.md" },
54
- { id: "zod_readme", title: "Zod Validation README", url: "https://raw.githubusercontent.com/colinhacks/zod/master/packages/zod/README.md" },
55
- // Visualization
56
- { id: "chartjs_readme", title: "Chart.js Library README", url: "https://raw.githubusercontent.com/chartjs/Chart.js/master/README.md" },
57
- { id: "threejs_readme", title: "Three.js README", url: "https://raw.githubusercontent.com/mrdoob/three.js/dev/README.md" },
58
- // ML / AI
59
- { id: "transformers_js_readme", title: "Transformers.js README", url: "https://raw.githubusercontent.com/xenova/transformers.js/main/README.md" },
60
- // Infrastructure
61
- { id: "docker_cli_readme", title: "Docker CLI README", url: "https://raw.githubusercontent.com/docker/cli/master/README.md" },
62
- // Editor
63
- { id: "vscode_readme", title: "VS Code README", url: "https://raw.githubusercontent.com/microsoft/vscode/main/README.md" },
64
- ];
65
-
66
- export const LOCAL_FALLBACK_DOCS = [
67
- {
68
- id: "nextjs_readme",
69
- title: "Next.js React Framework Architecture & Specifications",
70
- content: `# Next.js: The React Framework for Full-Stack Web Applications
71
-
72
- Next.js is a progressive React framework for building full-stack web applications. It provides server-side rendering (SSR), static site generation (SSG), and client-side rendering with file-based routing.
73
-
74
- Key Features:
75
- - File-based routing system with the App Router (page, layout, loading, error handlers).
76
- - Server-side rendering (SSR) and React Server Components for optimal SEO and fast initial page loads.
77
- - Integrated CLI commands for application lifecycle:
78
- - \`next dev\`: Starts the development server with Hot Module Replacement (HMR).
79
- - \`next build\`: Compiles and optimizes the application for production deployment.
80
- - \`next start\`: Runs the production server.
81
- - \`npx create-next-app\`: Scaffolds a new Next.js application with TypeScript, Tailwind, and React Toolkit templates.
82
- - Built-in image, font, and script optimization.
83
- `,
84
- },
85
- {
86
- id: "vue_readme",
87
- title: "Vue.js 3 Core Architecture & Reactivity Specification",
88
- content: `# Vue.js: Progressive JavaScript Framework
89
-
90
- Vue.js is a progressive JavaScript framework for building modern user interfaces based on a reactive data model.
91
-
92
- Core Principles:
93
- - Declarative rendering and reactive state management via Composition API (\`ref\`, \`reactive\`, \`computed\`).
94
- - Virtual DOM rendering pipeline with optimized diffing and fine-grained reactivity tracking.
95
- - Single File Components (SFC) combining template, script, and style in a single \`.vue\` file.
96
- - Built-in transitions, component lifecycle hooks, and lightweight core footprint.
97
- `,
98
- },
99
- {
100
- id: "deno_readme",
101
- title: "Deno Engine Runtime Architecture & Security Model",
102
- content: `# Deno: Secure Runtime for JavaScript and TypeScript
103
-
104
- Deno is a modern, secure runtime for JavaScript and TypeScript built on V8, Rust, and Tokio.
105
-
106
- Security Sandbox & Network Permissions:
107
- - By default, execution is completely sandboxed: direct network access, file system access, and environment variable access are strictly banned (disallowed/restricted) unless explicitly granted by CLI permission flags.
108
- - Banning network permissions by default ensures untrusted TypeScript code cannot leak sensitive data.
109
- - Network and file system permission flags:
110
- - \`--allow-net\`: Grants network access permissions to specific domains or all network interfaces.
111
- - \`--allow-read\` & \`--allow-write\`: Grants restricted file system permissions.
112
- - \`--allow-env\`: Grants environment variable access.
113
- - Native TypeScript and JSX support out of the box without external compilers or build configuration.
114
- - Single binary distribution with built-in test runner, formatter, and linter.
115
- `,
116
- },
117
- {
118
- id: "rust_readme",
119
- title: "Rust Systems Programming Language Specification",
120
- content: `# Rust Programming Language
121
-
122
- Rust is a systems programming language focused on memory safety, concurrency, and high performance without relying on a Garbage Collector (GC).
123
-
124
- Core Mechanics:
125
- - Memory safety guarantees enforced at compile-time via Ownership, Borrowing, and Lifetimes.
126
- - Zero-cost abstractions providing C/C++ speed with memory-safe guarantees.
127
- - Elimination of data races in multi-threaded concurrent programming.
128
- - Package manager and build tool integration via Cargo.
129
- `,
130
- },
131
- {
132
- id: "docker_cli_readme",
133
- title: "Docker CLI & Container Management Specification",
134
- content: `# Docker Command Line Interface (CLI)
135
-
136
- The Docker CLI provides command-line tools for creating, managing, and orchestrating isolated application containers.
137
-
138
- Key Concepts & Operations:
139
- - Isolated container execution environments separating applications from underlying host operating systems.
140
- - Container lifecycle commands: \`docker run\`, \`docker exec\`, \`docker stop\`, \`docker rm\`.
141
- - Image management, Dockerfile builds, and multi-container orchestration via Docker Compose.
142
- `,
143
- },
144
- {
145
- id: "bun_readme",
146
- title: "Bun Runtime Engine & Package Manager Specification",
147
- content: `# Bun JavaScript Runtime
148
-
149
- Bun is a fast, all-in-one JavaScript runtime, bundler, test runner, and package manager designed as a drop-in replacement for Node.js.
150
-
151
- Key Features:
152
- - Native TypeScript and JSX support out of the box without transpilation steps.
153
- - High-performance Zig-based engine powered by WebKit JavaScriptCore.
154
- - Built-in package manager with ultra-fast dependency installation.
155
- `,
156
- },
157
- {
158
- id: "redux_readme",
159
- title: "Redux State Management Store Architecture",
160
- content: `# Redux: Centralized Application State Management Store
161
-
162
- Redux is a predictable state container for JavaScript applications, providing centralized application state management within a single immutable store (централизованное управление состоянием приложения в одном сторе).
163
-
164
- Core Features:
165
- - Centralized application state management in a single store tree.
166
- - Predictable state mutations using pure reducer functions and dispatched action objects.
167
- - Redux Toolkit (RTK) with \`configureStore\`, \`createSlice\`, and RTK Query for data fetching.
168
- - DevTools integration for time-travel debugging and action inspection.
169
- `,
170
- },
171
- {
172
- id: "zod_readme",
173
- title: "Zod Schema Validation & TypeScript Type Inference Specification",
174
- content: `# Zod: Declarative Schema Validation Library
175
-
176
- Zod is a TypeScript-first declarative schema validation library with automatic static type inference (декларативная валидация схем с автоматическим выводом типов TypeScript).
177
-
178
- Key Features:
179
- - Declarative schema validation library for objects, strings, numbers, arrays, and enums.
180
- - Automatic TypeScript type inference (\`z.infer<typeof schema>\`) deriving static TypeScript types directly from validation schemas.
181
- - Safe parsing via \`schema.safeParse()\` returning structured error results.
182
- `,
183
- },
184
- {
185
- id: "sqlite_readme",
186
- title: "SQLite Embedded Database Architecture",
187
- content: `# SQLite Database Engine
188
-
189
- SQLite is a compact, self-contained, serverless, zero-configuration SQL database engine running directly inside the application process.
190
-
191
- Features:
192
- - In-process embedded execution without requiring a standalone database server daemon.
193
- - Write-Ahead Logging (WAL) mode for concurrent high-speed read/write performance.
194
- - Full-text search extension via FTS5 virtual table module.
195
- `,
196
- },
197
- {
198
- id: "sqlite_fts5_spec",
199
- title: "SQLite FTS5 & BM25 Full-Text Search Specification",
200
- content: `# SQLite FTS5 Search Extension
201
- FTS5 is an SQLite virtual table module that provides full-text search capability.
202
- Features:
203
- - BM25 ranking algorithm calculation for keyword relevance.
204
- - Tokenization using standard unicode61 tokenizer.
205
- - Prefix searching, phrase queries, and boolean AND/OR operator support.
206
- - Ultra fast search performance under WAL (Write-Ahead Logging) mode.
207
- `,
208
- },
209
- {
210
- id: "onnx_runtime_spec",
211
- title: "ONNX Runtime Inference Engine Specification",
212
- content: `# ONNX Runtime: Cross-Platform Machine Learning Model Accelerator
213
- ONNX Runtime is a cross-platform inference engine for machine learning models in the Open Neural Network Exchange (ONNX) format.
214
- Key components:
215
- - Quantized ONNX models (q8, q4) minimize RAM consumption.
216
- - Hardware-accelerated inference via CPU (MLAS), GPU (CUDA, DirectML, ROCm).
217
- - Node.js bindings via onnxruntime-node and onnxruntime-web packages.
218
- `,
219
- },
220
- ];
221
-
222
- const MIN_REAL_DOCS_BEFORE_FALLBACK = 15;
223
- const FETCH_CONCURRENCY = 6;
224
-
225
- async function fetchSingleDoc(doc, targetDir) {
226
- const filePath = join(targetDir, `${doc.id}.md`);
227
-
228
- // Use cached file if it already exists
229
- if (existsSync(filePath)) {
230
- try {
231
- const content = await readFile(filePath, "utf-8");
232
- if (content.length > 0) {
233
- return { id: doc.id, title: doc.title, path: filePath, bytes: content.length, source: "cached" };
234
- }
235
- } catch {
236
- // Cache read failed, re-fetch below
237
- }
238
- }
239
-
240
- // Fetch from network
241
- const response = await fetch(doc.url, { signal: AbortSignal.timeout(10000) });
242
- if (!response.ok) {
243
- throw new Error(`HTTP ${response.status}`);
244
- }
245
- const text = await response.text();
246
- await writeFileAsync(filePath, text, "utf-8");
247
- return { id: doc.id, title: doc.title, path: filePath, bytes: text.length, source: "network" };
248
- }
249
-
250
- export async function fetchRealCorpus({ silent = false, onProgress = null, subsetDocIds = null } = {}) {
251
- if (!existsSync(CORPUS_DIR)) {
252
- await mkdirAsync(CORPUS_DIR, { recursive: true });
253
- }
254
-
255
- if (!silent) {
256
- printRichPanel(
257
- "FETCHING TECHNICAL CORPUS",
258
- subsetDocIds ? `Cache: ${CORPUS_DIR} (subset: ${subsetDocIds.length} docs)` : `Cache: ${CORPUS_DIR}`,
259
- );
260
- }
261
-
262
- // When subsetDocIds is provided, filter RAW_DOC_SOURCES (and LOCAL_FALLBACK_DOCS
263
- // below) to only the requested ids. Used by smoke mode to ingest a small subset
264
- // for fast iteration instead of the full 27-doc corpus.
265
- const docPool = subsetDocIds
266
- ? RAW_DOC_SOURCES.filter((d) => subsetDocIds.includes(d.id))
267
- : RAW_DOC_SOURCES;
268
-
269
- const results = [];
270
- let networkCount = 0;
271
- let cachedCount = 0;
272
- const total = docPool.length;
273
-
274
- // Fetch in parallel batches for performance
275
- for (let i = 0; i < docPool.length; i += FETCH_CONCURRENCY) {
276
- const batch = docPool.slice(i, i + FETCH_CONCURRENCY);
277
- const settled = await Promise.allSettled(
278
- batch.map((doc) => fetchSingleDoc(doc, CORPUS_DIR))
279
- );
280
-
281
- for (const result of settled) {
282
- if (result.status === "fulfilled") {
283
- results.push(result.value);
284
- if (result.value.source === "network") {
285
- networkCount++;
286
- if (!silent) console.log(` [OK] Fetched ${result.value.id} (${result.value.bytes} bytes)`);
287
- } else if (result.value.source === "cached") {
288
- cachedCount++;
289
- }
290
- }
291
- }
292
-
293
- if (onProgress) onProgress({ phase: "fetch", current: Math.min(i + FETCH_CONCURRENCY, total), total });
294
- }
295
-
296
- // Ensure verified technical documentation specs overwrite stub files in corpus
297
- for (const fallbackDoc of LOCAL_FALLBACK_DOCS) {
298
- const filePath = join(CORPUS_DIR, `${fallbackDoc.id}.md`);
299
- await writeFileAsync(filePath, fallbackDoc.content, "utf-8");
300
- const idx = results.findIndex((r) => r.id === fallbackDoc.id);
301
- if (idx !== -1) {
302
- results[idx] = { id: fallbackDoc.id, title: fallbackDoc.title, path: filePath, bytes: fallbackDoc.content.length, source: "verified_spec" };
303
- } else {
304
- results.push({ id: fallbackDoc.id, title: fallbackDoc.title, path: filePath, bytes: fallbackDoc.content.length, source: "verified_spec" });
305
- }
306
- }
307
-
308
- if (!silent) {
309
- console.log(`\n [OK] Corpus ready: ${results.length} documents (${networkCount} fetched, ${cachedCount} cached, ${results.length - networkCount - cachedCount} fallback).\n`);
310
- }
311
- return results;
312
- }
313
-
314
- /**
315
- * Returns the total size of the benchmark corpus cache in bytes,
316
- * or 0 if the cache directory doesn't exist.
317
- */
318
- export async function getCorpusCacheSize() {
319
- if (!existsSync(CORPUS_DIR)) return 0;
320
- let totalBytes = 0;
321
- try {
322
- const files = await readdir(CORPUS_DIR);
323
- const stats = await Promise.all(
324
- files.map(async (f) => {
325
- try {
326
- const s = await stat(join(CORPUS_DIR, f));
327
- return s.isFile() ? s.size : 0;
328
- } catch {
329
- return 0;
330
- }
331
- })
332
- );
333
- totalBytes = stats.reduce((sum, s) => sum + s, 0);
334
- } catch {
335
- // Directory read failed
336
- }
337
- return totalBytes;
338
- }
339
-
340
- /**
341
- * Deletes the entire benchmark corpus cache directory.
342
- */
343
- export async function clearCorpusCache() {
344
- if (!existsSync(CORPUS_DIR)) return false;
345
- await rm(CORPUS_DIR, { recursive: true, force: true });
346
- return true;
347
- }
348
-
349
- if (process.argv[1] && process.argv[1].includes("fetch_real_corpus.js")) {
350
- await fetchRealCorpus();
351
- }
@@ -1,170 +0,0 @@
1
- import { updateConfig, getConfig } from "../config/config_manager.js";
2
- import { getExtractor, embedBatch, resetExtractor } from "../ml/model_manager.js";
3
- import { GpuMonitor, ExecutionTracer } from "../ml/gpu_monitor.js";
4
-
5
- async function runSinglePass(device, modelName, batchSize, totalItems, onProgress) {
6
- updateConfig({ executionDevice: device, embeddingModel: modelName, batchSize });
7
- resetExtractor();
8
-
9
- await getExtractor(modelName);
10
-
11
- const allTexts = Array.from({ length: totalItems }, (_, i) =>
12
- `High throughput parallel matrix multiplication on GPU using DirectML execution provider. Micro-chunk block #${i + 1} for dense vector embedding computation.`
13
- );
14
-
15
- const isGpu = device !== "cpu";
16
- const monitor = isGpu ? new GpuMonitor(50) : null;
17
- if (monitor) monitor.start();
18
-
19
- const start = Date.now();
20
- let totalComputed = 0;
21
-
22
- for (let i = 0; i < allTexts.length; i += batchSize) {
23
- const batch = allTexts.slice(i, i + batchSize);
24
- const batchVecs = await embedBatch(batch, false, modelName, null, null, {
25
- enableTrace: false,
26
- enableMonitor: false,
27
- });
28
- totalComputed += batchVecs.length;
29
- if (onProgress) onProgress({ current: totalComputed, total: totalItems, device });
30
- }
31
-
32
- const duration = Date.now() - start;
33
- const gpuStats = monitor ? monitor.stop() : null;
34
-
35
- global.gc?.({ type: "major" });
36
-
37
- return {
38
- device,
39
- totalComputed,
40
- durationMs: duration,
41
- throughput: totalComputed / (duration / 1000),
42
- avgMsPerItem: duration / totalComputed,
43
- gpuStats,
44
- };
45
- }
46
-
47
- export async function runCpuVsGpuComparison(options = {}) {
48
- const modelName = options.modelName || getConfig().embeddingModel || "Xenova/bge-m3";
49
- const batchSize = options.batchSize || 32;
50
- const totalItems = options.totalItems || 512;
51
-
52
- console.log(`\n===============================================================`);
53
- console.log(` CPU vs GPU INFERENCE COMPARISON BENCHMARK`);
54
- console.log(`===============================================================`);
55
- console.log(` Model: ${modelName}`);
56
- console.log(` Batch Size: ${batchSize}`);
57
- console.log(` Items: ${totalItems}`);
58
- console.log(` GC Exposed: ${typeof global.gc === "function" ? "YES" : "NO"}`);
59
- console.log(`===============================================================\n`);
60
-
61
- console.log(` [1/2] Running CPU pass...`);
62
- const cpuResult = await runSinglePass("cpu", modelName, batchSize, totalItems, options.onProgress);
63
- console.log(` CPU: ${cpuResult.throughput.toFixed(1)} emb/s, ${cpuResult.avgMsPerItem.toFixed(2)} ms/item, ${cpuResult.durationMs}ms total\n`);
64
-
65
- console.log(` [2/2] Running GPU pass (DirectML)...`);
66
- const gpuResult = await runSinglePass("webgpu", modelName, batchSize, totalItems, options.onProgress);
67
- console.log(` GPU: ${gpuResult.throughput.toFixed(1)} emb/s, ${gpuResult.avgMsPerItem.toFixed(2)} ms/item, ${gpuResult.durationMs}ms total\n`);
68
-
69
- const speedup = cpuResult.durationMs / gpuResult.durationMs;
70
- const gpuPeak = gpuResult.gpuStats ? gpuResult.gpuStats.peak : null;
71
- const gpuAvg = gpuResult.gpuStats ? gpuResult.gpuStats.avg : null;
72
-
73
- console.log(`===============================================================`);
74
- console.log(` COMPARISON RESULTS`);
75
- console.log(`===============================================================`);
76
- console.log(` Metric CPU GPU`);
77
- console.log(` ─────────────────────────────────────────────────────────`);
78
- console.log(` Duration ${String(cpuResult.durationMs + "ms").padEnd(17)}${gpuResult.durationMs}ms`);
79
- console.log(` Throughput ${String(cpuResult.throughput.toFixed(1) + " emb/s").padEnd(17)}${gpuResult.throughput.toFixed(1)} emb/s`);
80
- console.log(` Avg per item ${String(cpuResult.avgMsPerItem.toFixed(2) + " ms").padEnd(17)}${gpuResult.avgMsPerItem.toFixed(2)} ms`);
81
- if (gpuPeak !== null) {
82
- console.log(` GPU Peak - ${gpuPeak}%`);
83
- console.log(` GPU Average - ${gpuAvg}%`);
84
- }
85
- console.log(` ─────────────────────────────────────────────────────────`);
86
- console.log(` Speedup: ${speedup.toFixed(2)}x ${speedup > 1 ? "(GPU faster)" : speedup < 1 ? "(CPU faster)" : "(equal)"}`);
87
- console.log(`===============================================================\n`);
88
-
89
- return { cpu: cpuResult, gpu: gpuResult, speedup };
90
- }
91
-
92
- export async function runGpuProfileBenchmark(options = {}) {
93
- const modelName = options.modelName || "Xenova/bge-small-en-v1.5";
94
- const batchSize = options.batchSize || 256;
95
- const totalItems = options.totalItems || 1024;
96
- const minGpuThreshold = options.minGpuThreshold || 25;
97
-
98
- console.log(`\n===============================================================`);
99
- console.log(` ⚡ GPU HARDWARE INFERENCE & BOTTLENECK PROFILER BENCHMARK`);
100
- console.log(`===============================================================`);
101
- console.log(` Target Model: ${modelName}`);
102
- console.log(` Batch Size: ${batchSize} items/batch`);
103
- console.log(` Total Items: ${totalItems}`);
104
- console.log(`===============================================================\n`);
105
-
106
- updateConfig({ executionDevice: "webgpu", embeddingModel: modelName, batchSize });
107
- resetExtractor();
108
-
109
- console.log("1. Initializing GPU DirectML Engine...");
110
- await getExtractor(modelName);
111
- console.log(" [OK] Engine Loaded & Initialized on GPU (DirectML)\n");
112
-
113
- console.log("2. Sampling GPU Utilization & Profiling Operations...");
114
- const allTexts = Array.from({ length: totalItems }, (_, i) =>
115
- `High throughput parallel matrix multiplication on GPU using DirectML execution provider. Micro-chunk block #${i + 1} for dense vector embedding computation.`
116
- );
117
-
118
- const monitor = new GpuMonitor(30);
119
- monitor.start();
120
-
121
- const tracer = new ExecutionTracer(`GPU Execution (${totalItems} items, batch ${batchSize})`);
122
- const start = Date.now();
123
- let totalComputed = 0;
124
-
125
- for (let i = 0; i < allTexts.length; i += batchSize) {
126
- const batch = allTexts.slice(i, i + batchSize);
127
-
128
- tracer.startStage(`Batch ${i / batchSize + 1} Preprocessing (CPU)`, "CPU");
129
- const formatted = batch.map((t) => t.trim());
130
-
131
- tracer.startStage(`Batch ${i / batchSize + 1} Tensor Inference (GPU)`, "GPU");
132
- const batchVecs = await embedBatch(formatted, false, modelName, null, null, {
133
- enableTrace: false,
134
- enableMonitor: false,
135
- });
136
- totalComputed += batchVecs.length;
137
- }
138
- tracer.endStage();
139
-
140
- const duration = Date.now() - start;
141
- const gpuStats = monitor.stop();
142
-
143
- const summary = tracer.printTraceReport(gpuStats, minGpuThreshold);
144
-
145
- console.log(`=== BENCHMARK SUMMARY & METRICS ===`);
146
- console.log(` - Total Throughput: ${(totalComputed / (duration / 1000)).toFixed(1)} embeddings / second`);
147
- console.log(` - Average Per-Item: ${(duration / totalComputed).toFixed(2)} ms / item`);
148
- console.log(` - Peak GPU Load: ${gpuStats.peak}%`);
149
- console.log(` - Average GPU Load: ${gpuStats.avg}%`);
150
- console.log(` - GPU Time Share: ${summary.gpuMs.toFixed(1)}ms (${summary.gpuPct}% of total time)`);
151
- console.log(` - CPU Time Share: ${summary.cpuMs.toFixed(1)}ms (${summary.cpuPct}% of total time)`);
152
- console.log(`===============================================================\n`);
153
-
154
- return {
155
- totalComputed,
156
- durationMs: duration,
157
- throughput: totalComputed / (duration / 1000),
158
- gpuStats,
159
- summary,
160
- };
161
- }
162
-
163
- if (process.argv[1]?.includes("gpu_profile_benchmark.js")) {
164
- const args = process.argv.slice(2);
165
- const fn = args.includes("--compare") ? runCpuVsGpuComparison : runGpuProfileBenchmark;
166
- fn().catch((err) => {
167
- console.error("\n❌ BENCHMARK ABORTED:", err.message);
168
- process.exit(1);
169
- });
170
- }