@ijfw/memory-server 1.5.3 → 1.5.4
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.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ijfw/memory-server",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.4",
|
|
4
4
|
"description": "Cross-platform persistent memory server for IJFW. 14 MCP tools (memory + admin/update + brain). Works with 15 platforms: 14 via MCP (Claude Code, Codex, Gemini CLI, Cursor, Windsurf, Copilot, Hermes, Wayland, OpenCode, QwenCode, Cline, KimiCode, OpenClaw, Antigravity) plus Aider via the rules-only tier.",
|
|
5
5
|
"author": "Sean Donahoe",
|
|
6
6
|
"license": "MIT",
|
|
@@ -129,7 +129,7 @@ function buildExtractionPrompt(chunk) {
|
|
|
129
129
|
].join('\n');
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
export async function defaultExtractFacts({ file, text, chunks, env, guard, callTieredFn }) {
|
|
132
|
+
export async function defaultExtractFacts({ file: _file, text, chunks, env, guard, callTieredFn }) {
|
|
133
133
|
// No LLM configured -> graceful no-op (preserves prior behavior).
|
|
134
134
|
if (!llmReachable(env)) return [];
|
|
135
135
|
if (!text || typeof text !== 'string') return [];
|
package/src/brain/export.js
CHANGED
|
@@ -18,7 +18,12 @@ import { resolveBrainPaths } from './paths.js';
|
|
|
18
18
|
import { validateSafeRepoPath } from './path-guard.js';
|
|
19
19
|
|
|
20
20
|
const WIKI_TYPES = ['concepts', 'entities', 'decisions', 'milestones'];
|
|
21
|
-
|
|
21
|
+
// Match the entire bracket-pair content as a single negated character class.
|
|
22
|
+
// The slug (left of optional `|`) is extracted in JS after the regex match
|
|
23
|
+
// instead of via a nested optional group -- safe-regex flagged the original
|
|
24
|
+
// pattern (`[^\]\n|]+(?:\|[^\]\n]*)?`) as potentially unsafe even though it
|
|
25
|
+
// can't backtrack catastrophically. This single-class form is provably linear.
|
|
26
|
+
const WIKILINK_RE = /\[\[([^\]\n]+)\]\]/g;
|
|
22
27
|
|
|
23
28
|
function findPage(wikiDir, slug) {
|
|
24
29
|
for (const t of WIKI_TYPES) {
|
|
@@ -32,7 +37,11 @@ function parseWikilinks(md) {
|
|
|
32
37
|
if (!md) return [];
|
|
33
38
|
const out = new Set();
|
|
34
39
|
for (const m of md.matchAll(WIKILINK_RE)) {
|
|
35
|
-
|
|
40
|
+
// The capture group now includes the optional `|alias` suffix; the slug
|
|
41
|
+
// is the substring before the first `|` (matches the original semantics).
|
|
42
|
+
const inner = m[1];
|
|
43
|
+
const pipeIdx = inner.indexOf('|');
|
|
44
|
+
const target = (pipeIdx === -1 ? inner : inner.slice(0, pipeIdx)).trim();
|
|
36
45
|
if (target) out.add(target);
|
|
37
46
|
}
|
|
38
47
|
return [...out];
|
|
@@ -297,7 +297,7 @@ function verbConflictResolve(db, repoRoot, args) {
|
|
|
297
297
|
return { ok: true, resolved: true, winnerId: args.winnerId, supersededIds, validTo: chosenValidTo };
|
|
298
298
|
}
|
|
299
299
|
|
|
300
|
-
export async function handleIjfwBrain({ verb, args = {}, db, repoRoot, env, opts = {} } = {}) {
|
|
300
|
+
export async function handleIjfwBrain({ verb, args = {}, db, repoRoot, env: _env, opts = {} } = {}) {
|
|
301
301
|
if (!verb || typeof verb !== 'string') return { ok: false, error: 'missing-verb' };
|
|
302
302
|
switch (verb) {
|
|
303
303
|
case 'think': return verbThink(db, repoRoot, args, opts);
|
|
@@ -149,23 +149,6 @@ function extractTypeFromFrontmatter(raw) {
|
|
|
149
149
|
return null;
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
/**
|
|
153
|
-
* Return true if any direct child entry name of `dir` satisfies `predicate`.
|
|
154
|
-
* Best-effort: returns false on any readdir error.
|
|
155
|
-
*
|
|
156
|
-
* @param {string} dir
|
|
157
|
-
* @param {(name: string) => boolean} predicate
|
|
158
|
-
* @returns {boolean}
|
|
159
|
-
*/
|
|
160
|
-
function hasDirEntryMatching(dir, predicate) {
|
|
161
|
-
try {
|
|
162
|
-
const entries = readdirSync(dir);
|
|
163
|
-
return entries.some(predicate);
|
|
164
|
-
} catch {
|
|
165
|
-
return false;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
152
|
/**
|
|
170
153
|
* Return true if `name` is a direct child of `repoRoot` that is a directory
|
|
171
154
|
* AND contains at least one `.md` file. Avoids false-positive on plain files
|
package/src/server.js
CHANGED
|
@@ -28,7 +28,7 @@ import { migrateFactsInternalOnce } from './brain/migrate-facts-internal-once.js
|
|
|
28
28
|
// importing server.js.
|
|
29
29
|
import { runLayoutMigrations } from './memory/layout-migrations/index.js';
|
|
30
30
|
import { homedir } from 'os';
|
|
31
|
-
import { fileURLToPath
|
|
31
|
+
import { fileURLToPath } from 'url';
|
|
32
32
|
import { createHash, randomBytes } from 'crypto';
|
|
33
33
|
|
|
34
34
|
// Read version dynamically from package.json so bumps don't require a code change.
|
|
@@ -351,7 +351,7 @@ const __isServerEntryPoint = (() => {
|
|
|
351
351
|
})();
|
|
352
352
|
// Back-compat values for the line-2349 re-export. New code MUST use paths().memoryDir / paths().sessionsDir.
|
|
353
353
|
const MEMORY_DIR = join(IJFW_DIR, 'memory');
|
|
354
|
-
|
|
354
|
+
// SESSIONS_DIR removed -- replaced by paths().sessionsDir via brainPaths() helper.
|
|
355
355
|
const GLOBAL_DIR = join(homedir(), '.ijfw', 'memory');
|
|
356
356
|
// Legacy single-file location (pre-Phase 2). Still read for backward compat
|
|
357
357
|
// but new writes go to the faceted structure.
|