@totalreclaw/totalreclaw 3.3.1-rc.2 → 3.3.1-rc.21

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 (70) hide show
  1. package/CHANGELOG.md +330 -0
  2. package/SKILL.md +50 -83
  3. package/api-client.ts +18 -11
  4. package/config.ts +117 -3
  5. package/crypto.ts +10 -2
  6. package/dist/api-client.js +226 -0
  7. package/dist/billing-cache.js +100 -0
  8. package/dist/claims-helper.js +606 -0
  9. package/dist/config.js +280 -0
  10. package/dist/consolidation.js +258 -0
  11. package/dist/contradiction-sync.js +1034 -0
  12. package/dist/crypto.js +138 -0
  13. package/dist/digest-sync.js +361 -0
  14. package/dist/download-ux.js +63 -0
  15. package/dist/embedding.js +86 -0
  16. package/dist/extractor.js +1225 -0
  17. package/dist/first-run.js +103 -0
  18. package/dist/fs-helpers.js +563 -0
  19. package/dist/gateway-url.js +197 -0
  20. package/dist/generate-mnemonic.js +13 -0
  21. package/dist/hot-cache-wrapper.js +101 -0
  22. package/dist/import-adapters/base-adapter.js +64 -0
  23. package/dist/import-adapters/chatgpt-adapter.js +238 -0
  24. package/dist/import-adapters/claude-adapter.js +114 -0
  25. package/dist/import-adapters/gemini-adapter.js +201 -0
  26. package/dist/import-adapters/index.js +26 -0
  27. package/dist/import-adapters/mcp-memory-adapter.js +219 -0
  28. package/dist/import-adapters/mem0-adapter.js +158 -0
  29. package/dist/import-adapters/types.js +1 -0
  30. package/dist/index.js +5348 -0
  31. package/dist/llm-client.js +686 -0
  32. package/dist/llm-profile-reader.js +346 -0
  33. package/dist/lsh.js +62 -0
  34. package/dist/onboarding-cli.js +750 -0
  35. package/dist/pair-cli.js +344 -0
  36. package/dist/pair-crypto.js +359 -0
  37. package/dist/pair-http.js +404 -0
  38. package/dist/pair-page.js +826 -0
  39. package/dist/pair-qr.js +107 -0
  40. package/dist/pair-remote-client.js +410 -0
  41. package/dist/pair-session-store.js +566 -0
  42. package/dist/pin.js +542 -0
  43. package/dist/qa-bug-report.js +301 -0
  44. package/dist/relay-headers.js +44 -0
  45. package/dist/reranker.js +442 -0
  46. package/dist/retype-setscope.js +348 -0
  47. package/dist/semantic-dedup.js +75 -0
  48. package/dist/subgraph-search.js +289 -0
  49. package/dist/subgraph-store.js +694 -0
  50. package/dist/tool-gating.js +58 -0
  51. package/download-ux.ts +91 -0
  52. package/embedding.ts +32 -9
  53. package/fs-helpers.ts +124 -0
  54. package/gateway-url.ts +57 -9
  55. package/index.ts +586 -357
  56. package/llm-client.ts +211 -23
  57. package/lsh.ts +7 -2
  58. package/onboarding-cli.ts +114 -1
  59. package/package.json +19 -5
  60. package/pair-cli.ts +76 -8
  61. package/pair-crypto.ts +34 -24
  62. package/pair-page.ts +28 -17
  63. package/pair-qr.ts +152 -0
  64. package/pair-remote-client.ts +540 -0
  65. package/qa-bug-report.ts +381 -0
  66. package/relay-headers.ts +50 -0
  67. package/reranker.ts +73 -0
  68. package/retype-setscope.ts +12 -0
  69. package/subgraph-search.ts +4 -3
  70. package/subgraph-store.ts +109 -16
@@ -0,0 +1,158 @@
1
+ import { BaseImportAdapter } from './base-adapter.js';
2
+ /**
3
+ * Category mapping from Mem0 categories to TotalReclaw types.
4
+ */
5
+ const CATEGORY_MAP = {
6
+ preference: 'preference',
7
+ preferences: 'preference',
8
+ like: 'preference',
9
+ dislike: 'preference',
10
+ fact: 'fact',
11
+ personal: 'fact',
12
+ biographical: 'fact',
13
+ decision: 'decision',
14
+ goal: 'goal',
15
+ objective: 'goal',
16
+ experience: 'episodic',
17
+ event: 'episodic',
18
+ memory: 'episodic',
19
+ };
20
+ export class Mem0Adapter extends BaseImportAdapter {
21
+ source = 'mem0';
22
+ displayName = 'Mem0';
23
+ async parse(input, onProgress) {
24
+ const warnings = [];
25
+ const errors = [];
26
+ let memories;
27
+ if (input.content) {
28
+ // Parse from pasted content or export file
29
+ memories = this.parseExportContent(input.content, errors);
30
+ }
31
+ else if (input.api_key) {
32
+ // Fetch from Mem0 API
33
+ memories = await this.fetchFromApi(input.api_key, input.source_user_id, input.api_url, onProgress, errors);
34
+ }
35
+ else {
36
+ errors.push('Mem0 import requires either content (export file) or api_key');
37
+ return { facts: [], chunks: [], totalMessages: 0, warnings, errors };
38
+ }
39
+ if (onProgress) {
40
+ onProgress({
41
+ current: 0,
42
+ total: memories.length,
43
+ phase: 'parsing',
44
+ message: `Parsing ${memories.length} Mem0 memories...`,
45
+ });
46
+ }
47
+ // Convert Mem0 memories to NormalizedFacts
48
+ const rawFacts = memories.map((mem) => ({
49
+ text: mem.memory,
50
+ type: this.mapCategory(mem.categories, mem.metadata?.category),
51
+ importance: 6, // Mem0 doesn't provide importance — default to 6 (above threshold)
52
+ source: 'mem0',
53
+ sourceId: mem.id,
54
+ sourceTimestamp: mem.metadata?.updated_at || mem.metadata?.created_at,
55
+ tags: mem.categories || [],
56
+ }));
57
+ const { facts, invalidCount } = this.validateFacts(rawFacts);
58
+ if (invalidCount > 0) {
59
+ warnings.push(`${invalidCount} memories had invalid/empty text and were skipped`);
60
+ }
61
+ return { facts, chunks: [], totalMessages: 0, warnings, errors, source_metadata: { total_from_source: memories.length } };
62
+ }
63
+ /**
64
+ * Parse Mem0 export file or pasted JSON.
65
+ */
66
+ parseExportContent(content, errors) {
67
+ try {
68
+ const data = JSON.parse(content.trim());
69
+ // Handle export file format: { memories: [...] }
70
+ if (data.memories && Array.isArray(data.memories)) {
71
+ return data.memories;
72
+ }
73
+ // Handle API response format: { results: [...] }
74
+ if (data.results && Array.isArray(data.results)) {
75
+ return data.results;
76
+ }
77
+ // Handle bare array
78
+ if (Array.isArray(data)) {
79
+ return data;
80
+ }
81
+ errors.push('Unrecognized Mem0 format. Expected { memories: [...] }, { results: [...] }, or bare array.');
82
+ return [];
83
+ }
84
+ catch (e) {
85
+ errors.push(`Failed to parse Mem0 JSON: ${e instanceof Error ? e.message : 'Unknown error'}`);
86
+ return [];
87
+ }
88
+ }
89
+ /**
90
+ * Fetch all memories from Mem0 API with pagination.
91
+ */
92
+ async fetchFromApi(apiKey, sourceUserId, apiUrl, onProgress, errors) {
93
+ const baseUrl = apiUrl || 'https://api.mem0.ai';
94
+ const allMemories = [];
95
+ let page = 1;
96
+ const pageSize = 100;
97
+ let hasMore = true;
98
+ while (hasMore) {
99
+ try {
100
+ const url = new URL(`${baseUrl}/v1/memories/`);
101
+ url.searchParams.set('page', String(page));
102
+ url.searchParams.set('page_size', String(pageSize));
103
+ if (sourceUserId) {
104
+ url.searchParams.set('user_id', sourceUserId);
105
+ }
106
+ const response = await fetch(url.toString(), {
107
+ headers: {
108
+ Authorization: `Token ${apiKey}`,
109
+ 'Content-Type': 'application/json',
110
+ },
111
+ });
112
+ if (!response.ok) {
113
+ const errorText = await response.text();
114
+ errors?.push(`Mem0 API error (${response.status}): ${errorText.slice(0, 200)}`);
115
+ break;
116
+ }
117
+ const data = await response.json();
118
+ const memories = data.results || [];
119
+ allMemories.push(...memories);
120
+ if (onProgress) {
121
+ onProgress({
122
+ current: allMemories.length,
123
+ total: data.total || allMemories.length,
124
+ phase: 'fetching',
125
+ message: `Fetched ${allMemories.length} memories from Mem0...`,
126
+ });
127
+ }
128
+ hasMore = memories.length === pageSize;
129
+ page++;
130
+ // Safety limit: 10,000 memories max
131
+ if (allMemories.length >= 10_000) {
132
+ errors?.push('Reached 10,000 memory limit. Some memories may not have been fetched.');
133
+ break;
134
+ }
135
+ }
136
+ catch (e) {
137
+ errors?.push(`Mem0 API fetch error: ${e instanceof Error ? e.message : 'Unknown error'}`);
138
+ break;
139
+ }
140
+ }
141
+ return allMemories;
142
+ }
143
+ /**
144
+ * Map Mem0 category to TotalReclaw fact type.
145
+ */
146
+ mapCategory(categories, singleCategory) {
147
+ const allCategories = [
148
+ ...(categories || []),
149
+ ...(singleCategory ? [singleCategory] : []),
150
+ ];
151
+ for (const cat of allCategories) {
152
+ const mapped = CATEGORY_MAP[cat.toLowerCase()];
153
+ if (mapped)
154
+ return mapped;
155
+ }
156
+ return 'fact'; // default
157
+ }
158
+ }
@@ -0,0 +1 @@
1
+ export {};