claude-mem-lite 3.35.1 → 3.36.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.
@@ -1,175 +0,0 @@
1
- // claude-mem-lite: Resource indexer — extracts metadata via Haiku LLM
2
- // Called during installation and when resource content changes
3
-
4
- import { upsertResource } from './registry.mjs';
5
- import { callHaikuJSON } from './haiku-client.mjs';
6
- import { debugLog, debugCatch, truncate } from './utils.mjs';
7
-
8
- // ─── Index Prompt ────────────────────────────────────────────────────────────
9
-
10
- /**
11
- * Build the LLM prompt for extracting structured metadata from a resource.
12
- * @param {object} resource Scanned resource with name, type, and content
13
- * @returns {string} Prompt string for Haiku JSON extraction
14
- */
15
- function buildIndexPrompt(resource) {
16
- const content = truncate(resource.content, 3000);
17
- return `Analyze this Claude Code ${resource.type} definition and extract structured metadata.
18
- Return ONLY valid JSON, no markdown fences.
19
-
20
- <resource-name>${resource.name}</resource-name>
21
- <resource-type>${resource.type}</resource-type>
22
- <content>
23
- ${content}
24
- </content>
25
-
26
- JSON format:
27
- {"intent_tags":"comma-separated intent keywords (e.g. test,debug,deploy,review)","domain_tags":"comma-separated tech/language tags (e.g. javascript,react,python)","action_type":"analyze|generate|transform|validate|deploy|configure|review","trigger_patterns":"natural language describing when to use this (e.g. when user needs to write tests; when debugging errors)","capability_summary":"50-100 char description of what it does","keywords":"specific technical terms, framework names, method names not duplicating intent_tags (e.g. jest,vitest,red-green-refactor,pytest)","tech_stack":"specific frameworks and tools this works with (e.g. jest,vitest,mocha,pytest)","use_cases":"3-5 specific usage scenarios separated by semicolons","input_type":"code|file|directory|url|text","output_type":"report|file|diff|terminal_output|analysis"}`;
28
- }
29
-
30
- // ─── Fallback Extraction ─────────────────────────────────────────────────────
31
-
32
- /**
33
- * Extract basic metadata from resource content using regex when Haiku fails.
34
- * Better than nothing — provides minimal FTS5 searchability.
35
- */
36
- function fallbackExtract(resource) {
37
- const content = (resource.content || '').toLowerCase();
38
- const name = resource.name.toLowerCase();
39
-
40
- // Infer intent tags from name and common patterns
41
- const intentMap = {
42
- commit: 'commit,git,version-control',
43
- test: 'test,testing,tdd,qa',
44
- debug: 'debug,troubleshoot,fix,error',
45
- review: 'review,code-review,quality',
46
- lint: 'lint,format,style,quality',
47
- deploy: 'deploy,release,ci,cd',
48
- build: 'build,compile,bundle',
49
- refactor: 'refactor,clean,simplify',
50
- security: 'security,audit,vulnerability',
51
- perf: 'performance,optimize,benchmark',
52
- doc: 'documentation,readme,docs',
53
- design: 'design,ui,ux,frontend',
54
- infra: 'infrastructure,devops,cloud',
55
- };
56
-
57
- const intentTagSet = new Set();
58
- for (const [key, tags] of Object.entries(intentMap)) {
59
- if (name.includes(key) || content.includes(key)) {
60
- for (const t of tags.split(',')) intentTagSet.add(t);
61
- }
62
- }
63
- const intentTags = [...intentTagSet].join(',');
64
-
65
- // Infer domain tags from content
66
- const domainPatterns = [
67
- [/\b(javascript|typescript|node|npm|yarn|pnpm)\b/, 'javascript,typescript,node'],
68
- [/\b(python|pip|poetry|django|flask)\b/, 'python'],
69
- [/\b(react|vue|angular|svelte|next)\b/, 'frontend,javascript'],
70
- [/\b(rust|cargo)\b/, 'rust'],
71
- [/\b(go|golang)\b/, 'go'],
72
- [/\b(docker|kubernetes|k8s|terraform)\b/, 'infrastructure,devops'],
73
- [/\b(postgres|mysql|sqlite|mongodb)\b/, 'database'],
74
- [/\b(api|rest|graphql|grpc)\b/, 'api,backend'],
75
- ];
76
-
77
- let domainTags = '';
78
- for (const [pattern, tags] of domainPatterns) {
79
- if (pattern.test(content)) {
80
- domainTags = domainTags ? `${domainTags},${tags}` : tags;
81
- }
82
- }
83
-
84
- return {
85
- intent_tags: intentTags || resource.type,
86
- domain_tags: domainTags || '',
87
- action_type: resource.type === 'agent' ? 'analyze' : 'generate',
88
- trigger_patterns: `when user needs ${name.replace(/-/g, ' ')} functionality`,
89
- capability_summary: truncate(`${resource.type}: ${name.replace(/-/g, ' ')}`, 100),
90
- input_type: 'code',
91
- output_type: resource.type === 'agent' ? 'analysis' : 'file',
92
- };
93
- }
94
-
95
- // ─── Single Resource Indexing ────────────────────────────────────────────────
96
-
97
- /**
98
- * Index a single resource: call Haiku for metadata, then upsert to DB.
99
- * Falls back to regex extraction if Haiku fails.
100
- * @param {Database} db Registry database
101
- * @param {object} resource Scanned resource object
102
- * @returns {Promise<number>} Resource ID
103
- */
104
- export async function indexResource(db, resource) {
105
- const prompt = buildIndexPrompt(resource);
106
- let metadata = await callHaikuJSON(prompt, { timeout: 15000, maxTokens: 400 });
107
-
108
- if (!metadata || !metadata.capability_summary) {
109
- debugLog('WARN', 'indexer', `Haiku failed for ${resource.name}, using fallback`);
110
- metadata = fallbackExtract(resource);
111
- }
112
-
113
- const now = new Date().toISOString();
114
- const id = upsertResource(db, {
115
- name: resource.name,
116
- type: resource.type,
117
- status: 'active',
118
- source: resource.source,
119
- repo_url: resource.repoUrl || null,
120
- repo_stars: resource.repoStars || 0,
121
- local_path: resource.localPath,
122
- file_hash: resource.fileHash,
123
- intent_tags: metadata.intent_tags || '',
124
- domain_tags: metadata.domain_tags || '',
125
- action_type: metadata.action_type || '',
126
- trigger_patterns: metadata.trigger_patterns || '',
127
- capability_summary: metadata.capability_summary || '',
128
- input_type: metadata.input_type || '',
129
- output_type: metadata.output_type || '',
130
- keywords: metadata.keywords || '',
131
- tech_stack: metadata.tech_stack || '',
132
- use_cases: metadata.use_cases || '',
133
- prerequisites: typeof metadata.prerequisites === 'object'
134
- ? JSON.stringify(metadata.prerequisites) : '{}',
135
- indexed_at: now,
136
- });
137
-
138
- return id;
139
- }
140
-
141
- /**
142
- * Index multiple resources sequentially.
143
- * Logs progress and continues on individual failures.
144
- * @param {Database} db Registry database
145
- * @param {object[]} resources Array of scanned resources
146
- * @returns {Promise<{indexed: number, failed: number}>} Results summary
147
- */
148
- export async function indexAll(db, resources) {
149
- let indexed = 0;
150
- let failed = 0;
151
-
152
- for (const resource of resources) {
153
- try {
154
- await indexResource(db, resource);
155
- indexed++;
156
- debugLog('DEBUG', 'indexer', `indexed: ${resource.type}/${resource.name}`);
157
- } catch (e) {
158
- failed++;
159
- debugCatch(e, `indexResource(${resource.name})`);
160
- // Mark as error in DB so it can be retried later
161
- try {
162
- upsertResource(db, {
163
- name: resource.name,
164
- type: resource.type,
165
- status: 'error',
166
- source: resource.source,
167
- local_path: resource.localPath,
168
- file_hash: resource.fileHash,
169
- });
170
- } catch {}
171
- }
172
- }
173
-
174
- return { indexed, failed };
175
- }