claude-memory-layer 1.0.29 → 1.0.31
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/README.md +20 -6
- package/dist/cli/index.js +38 -5
- package/dist/cli/index.js.map +2 -2
- package/dist/core/index.js +42 -5
- package/dist/core/index.js.map +2 -2
- package/dist/hooks/post-tool-use.js +36 -3
- package/dist/hooks/post-tool-use.js.map +2 -2
- package/dist/hooks/semantic-daemon.js +36 -3
- package/dist/hooks/semantic-daemon.js.map +2 -2
- package/dist/hooks/session-end.js +36 -3
- package/dist/hooks/session-end.js.map +2 -2
- package/dist/hooks/session-start.js +36 -3
- package/dist/hooks/session-start.js.map +2 -2
- package/dist/hooks/stop.js +36 -3
- package/dist/hooks/stop.js.map +2 -2
- package/dist/hooks/user-prompt-submit.js +36 -3
- package/dist/hooks/user-prompt-submit.js.map +2 -2
- package/dist/index.js +42 -5
- package/dist/index.js.map +2 -2
- package/dist/mcp/index.js +36 -3
- package/dist/mcp/index.js.map +2 -2
- package/dist/server/api/index.js +36 -3
- package/dist/server/api/index.js.map +2 -2
- package/dist/server/index.js +36 -3
- package/dist/server/index.js.map +2 -2
- package/dist/services/memory-service.js +36 -3
- package/dist/services/memory-service.js.map +2 -2
- package/package.json +4 -6
- package/scripts/postinstall-embedding-backend.cjs +4 -7
- package/src/apps/cli/index.ts +5 -1
- package/src/core/types.ts +2 -2
- package/src/extensions/vector/embedder.ts +40 -3
- package/tests/apps/postinstall-embedding-backend.test.ts +36 -18
- package/tests/extensions/embedder-warning-suppression.test.ts +31 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-memory-layer",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.31",
|
|
4
4
|
"description": "Claude Code plugin that learns from conversations to provide personalized assistance",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -40,18 +40,16 @@
|
|
|
40
40
|
"node": ">=18.0.0"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@hono/node-server": "^1.
|
|
43
|
+
"@hono/node-server": "^1.19.14",
|
|
44
|
+
"@huggingface/transformers": "^3.8.1",
|
|
44
45
|
"@lancedb/lancedb": "^0.5.0",
|
|
45
46
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
46
47
|
"better-sqlite3": "^12.6.2",
|
|
47
48
|
"commander": "^12.0.0",
|
|
48
|
-
"hono": "^4.
|
|
49
|
+
"hono": "^4.12.18",
|
|
49
50
|
"mongodb": "^6.14.0",
|
|
50
51
|
"zod": "^3.22.0"
|
|
51
52
|
},
|
|
52
|
-
"optionalDependencies": {
|
|
53
|
-
"@huggingface/transformers": "^3.8.1"
|
|
54
|
-
},
|
|
55
53
|
"devDependencies": {
|
|
56
54
|
"@types/better-sqlite3": "^7.6.13",
|
|
57
55
|
"@types/node": "^20.11.0",
|
|
@@ -45,8 +45,6 @@ function detectCudaMajor({ env = process.env, execFileSyncImpl = execFileSync }
|
|
|
45
45
|
|
|
46
46
|
function isSkipRequested(env = process.env) {
|
|
47
47
|
if (env[SKIP_ENV] === '1' || env[REPAIR_GUARD_ENV] === '1') return true;
|
|
48
|
-
if (env.npm_config_optional === 'false') return true;
|
|
49
|
-
if (String(env.npm_config_omit || '').split(',').map((item) => item.trim()).includes('optional')) return true;
|
|
50
48
|
return false;
|
|
51
49
|
}
|
|
52
50
|
|
|
@@ -60,10 +58,9 @@ function isEmbeddingBackendAvailable(rootDir = process.cwd()) {
|
|
|
60
58
|
}
|
|
61
59
|
}
|
|
62
60
|
|
|
63
|
-
function shouldAttemptAutoInstall({ platform, arch,
|
|
61
|
+
function shouldAttemptAutoInstall({ platform, arch, transformersAvailable, skipRequested }) {
|
|
64
62
|
return platform === 'linux' &&
|
|
65
63
|
arch === 'x64' &&
|
|
66
|
-
cudaMajor === 11 &&
|
|
67
64
|
!transformersAvailable &&
|
|
68
65
|
!skipRequested;
|
|
69
66
|
}
|
|
@@ -104,7 +101,7 @@ function runPostinstall({
|
|
|
104
101
|
return { attempted: false, cudaMajor, transformersAvailable, skipRequested };
|
|
105
102
|
}
|
|
106
103
|
|
|
107
|
-
log('[claude-memory-layer]
|
|
104
|
+
log('[claude-memory-layer] Required embedding backend is missing on Linux x64. Repairing with CPU-only ONNX Runtime...');
|
|
108
105
|
|
|
109
106
|
const npmCommand = platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
110
107
|
const result = spawnSyncImpl(npmCommand, createNpmInstallArgs(), {
|
|
@@ -114,13 +111,13 @@ function runPostinstall({
|
|
|
114
111
|
});
|
|
115
112
|
|
|
116
113
|
if (result.error || result.status !== 0) {
|
|
117
|
-
warn('[claude-memory-layer]
|
|
114
|
+
warn('[claude-memory-layer] Required embedding backend repair failed. Semantic/vector embeddings may be unavailable until you run:');
|
|
118
115
|
warn(` ONNXRUNTIME_NODE_INSTALL_CUDA=skip npm install -g claude-memory-layer@latest`);
|
|
119
116
|
if (result.error) warn(` ${result.error.message}`);
|
|
120
117
|
return { attempted: true, success: false, cudaMajor, transformersAvailable, skipRequested };
|
|
121
118
|
}
|
|
122
119
|
|
|
123
|
-
log('[claude-memory-layer]
|
|
120
|
+
log('[claude-memory-layer] Required embedding backend repaired with CPU-only ONNX Runtime.');
|
|
124
121
|
return { attempted: true, success: true, cudaMajor, transformersAvailable, skipRequested };
|
|
125
122
|
}
|
|
126
123
|
|
package/src/apps/cli/index.ts
CHANGED
|
@@ -59,6 +59,10 @@ import {
|
|
|
59
59
|
renderExternalMarketContextReport,
|
|
60
60
|
type ExternalMarketProvider
|
|
61
61
|
} from '../../core/external-market-context.js';
|
|
62
|
+
import {
|
|
63
|
+
DEFAULT_EMBEDDING_FALLBACK_MODEL,
|
|
64
|
+
DEFAULT_EMBEDDING_MODEL
|
|
65
|
+
} from '../../extensions/vector/embedder.js';
|
|
62
66
|
|
|
63
67
|
// ============================================================
|
|
64
68
|
// Hook Installation Utilities
|
|
@@ -1025,7 +1029,7 @@ program
|
|
|
1025
1029
|
.option('-l, --limit <number>', 'Limit messages per session')
|
|
1026
1030
|
.option('--session-limit <number>', 'Limit recent matching sessions to import')
|
|
1027
1031
|
.option('-f, --force', 'Force reimport: delete existing events and reimport with turn_id grouping')
|
|
1028
|
-
.option('--embedding-model <name>',
|
|
1032
|
+
.option('--embedding-model <name>', `Embedding model override (default: ${DEFAULT_EMBEDDING_MODEL}, or env CLAUDE_MEMORY_EMBEDDING_MODEL; fallback: ${DEFAULT_EMBEDDING_FALLBACK_MODEL} or env CLAUDE_MEMORY_EMBEDDING_FALLBACK_MODEL)`)
|
|
1029
1033
|
.option('-v, --verbose', 'Show detailed progress')
|
|
1030
1034
|
.action(async (options) => {
|
|
1031
1035
|
const startTime = Date.now();
|
package/src/core/types.ts
CHANGED
|
@@ -152,8 +152,8 @@ export const ConfigSchema = z.object({
|
|
|
152
152
|
}).default({}),
|
|
153
153
|
embedding: z.object({
|
|
154
154
|
provider: z.enum(['local', 'openai']).default('local'),
|
|
155
|
-
model: z.string().default('
|
|
156
|
-
openaiModel: z.string().default('
|
|
155
|
+
model: z.string().default('Xenova/multilingual-e5-small'),
|
|
156
|
+
openaiModel: z.string().default('Xenova/multilingual-e5-small'),
|
|
157
157
|
batchSize: z.number().default(32)
|
|
158
158
|
}).default({}),
|
|
159
159
|
retrieval: z.object({
|
|
@@ -14,13 +14,16 @@ type FeatureExtractionPipelineFactory = (
|
|
|
14
14
|
model: string
|
|
15
15
|
) => Promise<NonNullable<Embedder['pipeline']>>;
|
|
16
16
|
|
|
17
|
+
export const DEFAULT_EMBEDDING_MODEL = 'Xenova/multilingual-e5-small';
|
|
18
|
+
export const DEFAULT_EMBEDDING_FALLBACK_MODEL = 'intfloat/multilingual-e5-small';
|
|
19
|
+
|
|
17
20
|
export class Embedder {
|
|
18
21
|
private pipeline: ((input: string, options?: Record<string, unknown>) => Promise<{ data: Float32Array }>) | null = null;
|
|
19
22
|
private readonly modelName: string;
|
|
20
23
|
private activeModelName: string;
|
|
21
24
|
private initialized = false;
|
|
22
25
|
|
|
23
|
-
constructor(modelName: string =
|
|
26
|
+
constructor(modelName: string = DEFAULT_EMBEDDING_MODEL) {
|
|
24
27
|
this.modelName = modelName;
|
|
25
28
|
this.activeModelName = modelName;
|
|
26
29
|
}
|
|
@@ -31,7 +34,16 @@ export class Embedder {
|
|
|
31
34
|
async initialize(): Promise<void> {
|
|
32
35
|
if (this.initialized) return;
|
|
33
36
|
|
|
34
|
-
const pipeline = await withSuppressedKnownTransformersWarnings(() =>
|
|
37
|
+
const pipeline = await withSuppressedKnownTransformersWarnings(async () => {
|
|
38
|
+
try {
|
|
39
|
+
return await loadTransformersPipeline();
|
|
40
|
+
} catch (error) {
|
|
41
|
+
if (isMissingTransformersDependencyError(error)) {
|
|
42
|
+
throw createEmbeddingBackendUnavailableError(error);
|
|
43
|
+
}
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
35
47
|
|
|
36
48
|
try {
|
|
37
49
|
this.pipeline = await withSuppressedKnownTransformersWarnings(() => pipeline('feature-extraction', this.modelName));
|
|
@@ -39,7 +51,7 @@ export class Embedder {
|
|
|
39
51
|
this.initialized = true;
|
|
40
52
|
return;
|
|
41
53
|
} catch (primaryError) {
|
|
42
|
-
const fallbackModel = process.env.CLAUDE_MEMORY_EMBEDDING_FALLBACK_MODEL ||
|
|
54
|
+
const fallbackModel = process.env.CLAUDE_MEMORY_EMBEDDING_FALLBACK_MODEL || DEFAULT_EMBEDDING_FALLBACK_MODEL;
|
|
43
55
|
if (fallbackModel === this.modelName) {
|
|
44
56
|
throw primaryError;
|
|
45
57
|
}
|
|
@@ -186,6 +198,31 @@ export function isKnownBenignTransformersWarning(message: string): boolean {
|
|
|
186
198
|
message.includes('dtype not specified for "model"');
|
|
187
199
|
}
|
|
188
200
|
|
|
201
|
+
export function isMissingTransformersDependencyError(error: unknown): boolean {
|
|
202
|
+
const maybeError = error as { code?: unknown; message?: unknown } | null;
|
|
203
|
+
const message = typeof maybeError?.message === 'string' ? maybeError.message : '';
|
|
204
|
+
return maybeError?.code === 'ERR_MODULE_NOT_FOUND' &&
|
|
205
|
+
message.includes("@huggingface/transformers");
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export function createEmbeddingBackendUnavailableError(cause: unknown): Error & { cause?: unknown } {
|
|
209
|
+
const error = new Error(
|
|
210
|
+
[
|
|
211
|
+
'Required embedding backend is not installed.',
|
|
212
|
+
'',
|
|
213
|
+
'Claude Memory Layer requires @huggingface/transformers for local semantic/vector embeddings.',
|
|
214
|
+
'The backend runs on CPU-only ONNX Runtime; CUDA is not required.',
|
|
215
|
+
'Reinstall globally with:',
|
|
216
|
+
' ONNXRUNTIME_NODE_INSTALL_CUDA=skip npm install -g claude-memory-layer@latest',
|
|
217
|
+
'',
|
|
218
|
+
'If you are inside a local checkout or package directory, repair only the backend with:',
|
|
219
|
+
' ONNXRUNTIME_NODE_INSTALL_CUDA=skip npm install --no-save --no-package-lock --omit=dev @huggingface/transformers@3.8.1'
|
|
220
|
+
].join('\n')
|
|
221
|
+
) as Error & { cause?: unknown };
|
|
222
|
+
error.cause = cause;
|
|
223
|
+
return error;
|
|
224
|
+
}
|
|
225
|
+
|
|
189
226
|
async function loadTransformersPipeline(): Promise<FeatureExtractionPipelineFactory> {
|
|
190
227
|
// Keep @huggingface/transformers lazy so importing MemoryService or pure
|
|
191
228
|
// adapter helpers does not eagerly dlopen onnxruntime native bindings.
|
|
@@ -16,6 +16,7 @@ type SpawnCall = {
|
|
|
16
16
|
type PostinstallEmbeddingBackend = {
|
|
17
17
|
EMBEDDING_BACKEND_PACKAGE: string;
|
|
18
18
|
parseCudaMajor(output: string): number | null;
|
|
19
|
+
isSkipRequested(env: NodeJS.ProcessEnv): boolean;
|
|
19
20
|
shouldAttemptAutoInstall(input: {
|
|
20
21
|
platform: NodeJS.Platform;
|
|
21
22
|
arch: string;
|
|
@@ -42,20 +43,29 @@ function loadPostinstallModule(): PostinstallEmbeddingBackend {
|
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
describe('embedding backend postinstall repair', () => {
|
|
45
|
-
it('
|
|
46
|
+
it('requires the embedding backend at install time and registers a broken-install repair hook', () => {
|
|
46
47
|
const pkg = JSON.parse(readFileSync('package.json', 'utf-8')) as {
|
|
47
48
|
scripts: Record<string, string>;
|
|
48
49
|
dependencies?: Record<string, string>;
|
|
49
50
|
optionalDependencies?: Record<string, string>;
|
|
50
51
|
};
|
|
51
52
|
|
|
52
|
-
expect(pkg.dependencies).
|
|
53
|
-
expect(pkg.optionalDependencies).toMatchObject({
|
|
53
|
+
expect(pkg.dependencies).toMatchObject({
|
|
54
54
|
'@huggingface/transformers': '^3.8.1'
|
|
55
55
|
});
|
|
56
|
+
expect(pkg.optionalDependencies ?? {}).not.toHaveProperty('@huggingface/transformers');
|
|
56
57
|
expect(pkg.scripts.postinstall).toBe('node scripts/postinstall-embedding-backend.cjs');
|
|
57
58
|
});
|
|
58
59
|
|
|
60
|
+
it('only skips required-backend repair when the explicit repair guards are set', () => {
|
|
61
|
+
const postinstall = loadPostinstallModule();
|
|
62
|
+
|
|
63
|
+
expect(postinstall.isSkipRequested({ CLAUDE_MEMORY_LAYER_SKIP_EMBEDDING_POSTINSTALL: '1' })).toBe(true);
|
|
64
|
+
expect(postinstall.isSkipRequested({ CLAUDE_MEMORY_LAYER_EMBEDDING_POSTINSTALL_REPAIR: '1' })).toBe(true);
|
|
65
|
+
expect(postinstall.isSkipRequested({ npm_config_optional: 'false' })).toBe(false);
|
|
66
|
+
expect(postinstall.isSkipRequested({ npm_config_omit: 'optional' })).toBe(false);
|
|
67
|
+
});
|
|
68
|
+
|
|
59
69
|
it('detects CUDA major version from nvcc output', () => {
|
|
60
70
|
const postinstall = loadPostinstallModule();
|
|
61
71
|
|
|
@@ -64,7 +74,7 @@ describe('embedding backend postinstall repair', () => {
|
|
|
64
74
|
expect(postinstall.parseCudaMajor('nvcc: NVIDIA (R) Cuda compiler driver')).toBeNull();
|
|
65
75
|
});
|
|
66
76
|
|
|
67
|
-
it('
|
|
77
|
+
it('auto-installs a missing embedding backend for Linux x64 even when CUDA cannot be detected', () => {
|
|
68
78
|
const postinstall = loadPostinstallModule();
|
|
69
79
|
|
|
70
80
|
expect(postinstall.shouldAttemptAutoInstall({
|
|
@@ -78,31 +88,39 @@ describe('embedding backend postinstall repair', () => {
|
|
|
78
88
|
expect(postinstall.shouldAttemptAutoInstall({
|
|
79
89
|
platform: 'linux',
|
|
80
90
|
arch: 'x64',
|
|
81
|
-
cudaMajor:
|
|
82
|
-
transformersAvailable:
|
|
91
|
+
cudaMajor: null,
|
|
92
|
+
transformersAvailable: false,
|
|
83
93
|
skipRequested: false
|
|
84
|
-
})).toBe(
|
|
94
|
+
})).toBe(true);
|
|
85
95
|
|
|
86
96
|
expect(postinstall.shouldAttemptAutoInstall({
|
|
87
97
|
platform: 'linux',
|
|
88
|
-
arch: '
|
|
89
|
-
cudaMajor:
|
|
98
|
+
arch: 'x64',
|
|
99
|
+
cudaMajor: 12,
|
|
90
100
|
transformersAvailable: false,
|
|
91
101
|
skipRequested: false
|
|
92
|
-
})).toBe(
|
|
102
|
+
})).toBe(true);
|
|
93
103
|
|
|
94
104
|
expect(postinstall.shouldAttemptAutoInstall({
|
|
95
|
-
platform: '
|
|
105
|
+
platform: 'linux',
|
|
96
106
|
arch: 'x64',
|
|
97
|
-
cudaMajor:
|
|
98
|
-
transformersAvailable:
|
|
107
|
+
cudaMajor: null,
|
|
108
|
+
transformersAvailable: true,
|
|
99
109
|
skipRequested: false
|
|
100
110
|
})).toBe(false);
|
|
101
111
|
|
|
102
112
|
expect(postinstall.shouldAttemptAutoInstall({
|
|
103
113
|
platform: 'linux',
|
|
114
|
+
arch: 'arm64',
|
|
115
|
+
cudaMajor: null,
|
|
116
|
+
transformersAvailable: false,
|
|
117
|
+
skipRequested: false
|
|
118
|
+
})).toBe(false);
|
|
119
|
+
|
|
120
|
+
expect(postinstall.shouldAttemptAutoInstall({
|
|
121
|
+
platform: 'darwin',
|
|
104
122
|
arch: 'x64',
|
|
105
|
-
cudaMajor:
|
|
123
|
+
cudaMajor: null,
|
|
106
124
|
transformersAvailable: false,
|
|
107
125
|
skipRequested: false
|
|
108
126
|
})).toBe(false);
|
|
@@ -110,7 +128,7 @@ describe('embedding backend postinstall repair', () => {
|
|
|
110
128
|
expect(postinstall.shouldAttemptAutoInstall({
|
|
111
129
|
platform: 'linux',
|
|
112
130
|
arch: 'x64',
|
|
113
|
-
cudaMajor:
|
|
131
|
+
cudaMajor: null,
|
|
114
132
|
transformersAvailable: false,
|
|
115
133
|
skipRequested: true
|
|
116
134
|
})).toBe(false);
|
|
@@ -132,7 +150,7 @@ describe('embedding backend postinstall repair', () => {
|
|
|
132
150
|
]);
|
|
133
151
|
});
|
|
134
152
|
|
|
135
|
-
it('runs the
|
|
153
|
+
it('runs the repair command when Linux x64 is missing the required backend without detectable CUDA', () => {
|
|
136
154
|
const postinstall = loadPostinstallModule();
|
|
137
155
|
const rootDir = mkdtempSync(join(tmpdir(), 'cml-postinstall-test-'));
|
|
138
156
|
const calls: SpawnCall[] = [];
|
|
@@ -145,7 +163,7 @@ describe('embedding backend postinstall repair', () => {
|
|
|
145
163
|
env: {},
|
|
146
164
|
platform: 'linux',
|
|
147
165
|
arch: 'x64',
|
|
148
|
-
execFileSyncImpl: () => '
|
|
166
|
+
execFileSyncImpl: () => '',
|
|
149
167
|
spawnSyncImpl: (cmd, args, options) => {
|
|
150
168
|
calls.push({ cmd, args, env: options.env });
|
|
151
169
|
return { status: 0 };
|
|
@@ -154,7 +172,7 @@ describe('embedding backend postinstall repair', () => {
|
|
|
154
172
|
warn: () => undefined
|
|
155
173
|
});
|
|
156
174
|
|
|
157
|
-
expect(result).toMatchObject({ attempted: true, success: true, cudaMajor:
|
|
175
|
+
expect(result).toMatchObject({ attempted: true, success: true, cudaMajor: null, transformersAvailable: false });
|
|
158
176
|
expect(calls).toHaveLength(1);
|
|
159
177
|
expect(calls[0]?.cmd).toBe('npm');
|
|
160
178
|
expect(calls[0]?.args).toEqual(postinstall.createNpmInstallArgs());
|
|
@@ -1,11 +1,42 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from 'vitest';
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
|
+
DEFAULT_EMBEDDING_MODEL,
|
|
5
|
+
Embedder,
|
|
6
|
+
createEmbeddingBackendUnavailableError,
|
|
4
7
|
isKnownBenignTransformersWarning,
|
|
8
|
+
isMissingTransformersDependencyError,
|
|
5
9
|
withSuppressedKnownTransformersWarnings
|
|
6
10
|
} from '../../src/extensions/vector/embedder.js';
|
|
11
|
+
import { ConfigSchema } from '../../src/core/types.js';
|
|
7
12
|
|
|
8
13
|
describe('Embedder warning suppression', () => {
|
|
14
|
+
it('uses a CPU-friendly multilingual Korean-capable default embedding model', () => {
|
|
15
|
+
expect(DEFAULT_EMBEDDING_MODEL).toBe('Xenova/multilingual-e5-small');
|
|
16
|
+
expect(new Embedder().getModelName()).toBe(DEFAULT_EMBEDDING_MODEL);
|
|
17
|
+
|
|
18
|
+
const parsedConfig = ConfigSchema.parse({});
|
|
19
|
+
expect(parsedConfig.embedding.model).toBe(DEFAULT_EMBEDDING_MODEL);
|
|
20
|
+
expect(parsedConfig.embedding.openaiModel).toBe(DEFAULT_EMBEDDING_MODEL);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('turns missing required @huggingface/transformers errors into actionable install guidance', () => {
|
|
24
|
+
const missingBackendError = Object.assign(
|
|
25
|
+
new Error("Cannot find package '@huggingface/transformers' imported from /tmp/dist/cli/index.js"),
|
|
26
|
+
{ code: 'ERR_MODULE_NOT_FOUND' }
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
expect(isMissingTransformersDependencyError(missingBackendError)).toBe(true);
|
|
30
|
+
expect(isMissingTransformersDependencyError(new Error('network failure'))).toBe(false);
|
|
31
|
+
|
|
32
|
+
const friendly = createEmbeddingBackendUnavailableError(missingBackendError);
|
|
33
|
+
expect(friendly.message).toContain('Required embedding backend is not installed');
|
|
34
|
+
expect(friendly.message).toContain('Claude Memory Layer requires @huggingface/transformers');
|
|
35
|
+
expect(friendly.message).toContain('ONNXRUNTIME_NODE_INSTALL_CUDA=skip npm install -g claude-memory-layer@latest');
|
|
36
|
+
expect(friendly.message).toContain('ONNXRUNTIME_NODE_INSTALL_CUDA=skip npm install --no-save --no-package-lock --omit=dev @huggingface/transformers@3.8.1');
|
|
37
|
+
expect(friendly.cause).toBe(missingBackendError);
|
|
38
|
+
});
|
|
39
|
+
|
|
9
40
|
it('recognizes known benign transformer warnings', () => {
|
|
10
41
|
expect(isKnownBenignTransformersWarning('Unknown model class "eurobert", attempting to construct from base class.')).toBe(true);
|
|
11
42
|
expect(isKnownBenignTransformersWarning('dtype not specified for "model". Using the default dtype (fp32).')).toBe(true);
|