@cmdoss/memwal-sdk 0.6.1 → 0.6.2
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/ARCHITECTURE.md +547 -547
- package/BENCHMARKS.md +238 -238
- package/README.md +181 -181
- package/dist/ai-sdk/PDWVectorStore.d.ts.map +1 -1
- package/dist/ai-sdk/PDWVectorStore.js +4 -1
- package/dist/ai-sdk/PDWVectorStore.js.map +1 -1
- package/dist/browser.d.ts +5 -6
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +7 -6
- package/dist/browser.js.map +1 -1
- package/dist/client/ClientMemoryManager.d.ts +1 -0
- package/dist/client/ClientMemoryManager.d.ts.map +1 -1
- package/dist/client/ClientMemoryManager.js +5 -1
- package/dist/client/ClientMemoryManager.js.map +1 -1
- package/dist/client/PersonalDataWallet.d.ts.map +1 -1
- package/dist/client/SimplePDWClient.d.ts +23 -0
- package/dist/client/SimplePDWClient.d.ts.map +1 -1
- package/dist/client/SimplePDWClient.js +15 -2
- package/dist/client/SimplePDWClient.js.map +1 -1
- package/dist/client/namespaces/IndexNamespace.d.ts +38 -9
- package/dist/client/namespaces/IndexNamespace.d.ts.map +1 -1
- package/dist/client/namespaces/IndexNamespace.js +77 -10
- package/dist/client/namespaces/IndexNamespace.js.map +1 -1
- package/dist/client/namespaces/SearchNamespace.d.ts.map +1 -1
- package/dist/client/namespaces/SearchNamespace.js +25 -14
- package/dist/client/namespaces/SearchNamespace.js.map +1 -1
- package/dist/client/namespaces/consolidated/BlockchainNamespace.d.ts.map +1 -1
- package/dist/client/namespaces/consolidated/BlockchainNamespace.js +49 -1
- package/dist/client/namespaces/consolidated/BlockchainNamespace.js.map +1 -1
- package/dist/client/namespaces/consolidated/StorageNamespace.d.ts +46 -0
- package/dist/client/namespaces/consolidated/StorageNamespace.d.ts.map +1 -1
- package/dist/client/namespaces/consolidated/StorageNamespace.js +34 -0
- package/dist/client/namespaces/consolidated/StorageNamespace.js.map +1 -1
- package/dist/graph/GraphService.js +1 -1
- package/dist/permissions/ConsentRepository.browser.d.ts +56 -0
- package/dist/permissions/ConsentRepository.browser.d.ts.map +1 -0
- package/dist/permissions/ConsentRepository.browser.js +198 -0
- package/dist/permissions/ConsentRepository.browser.js.map +1 -0
- package/dist/services/GeminiAIService.d.ts.map +1 -1
- package/dist/services/GeminiAIService.js +283 -27
- package/dist/services/GeminiAIService.js.map +1 -1
- package/dist/services/MemoryIndexService.d.ts +31 -2
- package/dist/services/MemoryIndexService.d.ts.map +1 -1
- package/dist/services/MemoryIndexService.js +75 -3
- package/dist/services/MemoryIndexService.js.map +1 -1
- package/dist/services/storage/QuiltBatchManager.d.ts +10 -3
- package/dist/services/storage/QuiltBatchManager.d.ts.map +1 -1
- package/dist/services/storage/QuiltBatchManager.js +49 -27
- package/dist/services/storage/QuiltBatchManager.js.map +1 -1
- package/dist/utils/rebuildIndexNode.d.ts.map +1 -1
- package/dist/utils/rebuildIndexNode.js +109 -35
- package/dist/utils/rebuildIndexNode.js.map +1 -1
- package/dist/vector/NodeHnswService.d.ts.map +1 -1
- package/dist/vector/NodeHnswService.js +26 -7
- package/dist/vector/NodeHnswService.js.map +1 -1
- package/package.json +1 -1
- package/src/access/index.ts +8 -8
- package/src/aggregation/index.ts +8 -8
- package/src/ai-sdk/PDWVectorStore.ts +4 -1
- package/src/browser.ts +15 -10
- package/src/client/ClientMemoryManager.ts +6 -1
- package/src/client/SimplePDWClient.ts +40 -2
- package/src/client/namespaces/IndexNamespace.ts +89 -11
- package/src/client/namespaces/SearchNamespace.ts +27 -14
- package/src/client/namespaces/consolidated/BlockchainNamespace.ts +55 -1
- package/src/client/namespaces/consolidated/StorageNamespace.ts +57 -0
- package/src/client/signers/DappKitSigner.ts +207 -207
- package/src/generated/pdw/capability.ts +319 -319
- package/src/generated/pdw/deps/sui/object.ts +12 -12
- package/src/generated/pdw/deps/sui/vec_map.ts +32 -32
- package/src/generated/pdw/memory.ts +1087 -1087
- package/src/generated/pdw/wallet.ts +123 -123
- package/src/generated/utils/index.ts +159 -159
- package/src/graph/GraphService.ts +1 -1
- package/src/permissions/ConsentRepository.browser.ts +249 -0
- package/src/permissions/index.ts +9 -9
- package/src/services/GeminiAIService.ts +283 -27
- package/src/services/MemoryIndexService.ts +85 -3
- package/src/services/storage/QuiltBatchManager.ts +55 -29
- package/src/utils/rebuildIndexNode.ts +126 -43
- package/src/vector/NodeHnswService.ts +29 -7
- package/src/wallet/index.ts +17 -17
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-safe Consent Repository implementations
|
|
3
|
+
*
|
|
4
|
+
* This file contains only browser-compatible implementations.
|
|
5
|
+
* FileSystemConsentRepository is excluded as it requires Node.js fs/promises.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
ConsentRequestRecord,
|
|
10
|
+
ConsentStatus,
|
|
11
|
+
} from '../core/types/wallet.js';
|
|
12
|
+
import { normalizeSuiAddress } from '@mysten/sui/utils';
|
|
13
|
+
|
|
14
|
+
export interface ConsentRepository {
|
|
15
|
+
save(request: ConsentRequestRecord): Promise<void>;
|
|
16
|
+
updateStatus(requestId: string, status: ConsentStatus, updatedAt: number): Promise<void>;
|
|
17
|
+
getById(requestId: string): Promise<ConsentRequestRecord | null>;
|
|
18
|
+
listByTarget(targetWallet: string, status?: ConsentStatus): Promise<ConsentRequestRecord[]>;
|
|
19
|
+
listByRequester(requesterWallet: string, status?: ConsentStatus): Promise<ConsentRequestRecord[]>;
|
|
20
|
+
delete(requestId: string): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface StoredConsentRecord extends ConsentRequestRecord {}
|
|
24
|
+
|
|
25
|
+
function normalizeRecord(record: ConsentRequestRecord): StoredConsentRecord {
|
|
26
|
+
return {
|
|
27
|
+
...record,
|
|
28
|
+
requesterWallet: normalizeSuiAddress(record.requesterWallet),
|
|
29
|
+
targetWallet: normalizeSuiAddress(record.targetWallet),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export class InMemoryConsentRepository implements ConsentRepository {
|
|
34
|
+
private store = new Map<string, StoredConsentRecord>();
|
|
35
|
+
|
|
36
|
+
async save(request: ConsentRequestRecord): Promise<void> {
|
|
37
|
+
const normalized = normalizeRecord(request);
|
|
38
|
+
this.store.set(normalized.requestId, normalized);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async updateStatus(requestId: string, status: ConsentStatus, updatedAt: number): Promise<void> {
|
|
42
|
+
const record = this.store.get(requestId);
|
|
43
|
+
if (!record) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
this.store.set(requestId, {
|
|
47
|
+
...record,
|
|
48
|
+
status,
|
|
49
|
+
updatedAt,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async getById(requestId: string): Promise<ConsentRequestRecord | null> {
|
|
54
|
+
const record = this.store.get(requestId);
|
|
55
|
+
return record ? { ...record } : null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async listByTarget(targetWallet: string, status?: ConsentStatus): Promise<ConsentRequestRecord[]> {
|
|
59
|
+
const normalizedTarget = normalizeSuiAddress(targetWallet);
|
|
60
|
+
return Array.from(this.store.values())
|
|
61
|
+
.filter((record) => record.targetWallet === normalizedTarget)
|
|
62
|
+
.filter((record) => (status ? record.status === status : true))
|
|
63
|
+
.map((record) => ({ ...record }));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async listByRequester(requesterWallet: string, status?: ConsentStatus): Promise<ConsentRequestRecord[]> {
|
|
67
|
+
const normalizedRequester = normalizeSuiAddress(requesterWallet);
|
|
68
|
+
return Array.from(this.store.values())
|
|
69
|
+
.filter((record) => record.requesterWallet === normalizedRequester)
|
|
70
|
+
.filter((record) => (status ? record.status === status : true))
|
|
71
|
+
.map((record) => ({ ...record }));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async delete(requestId: string): Promise<void> {
|
|
75
|
+
this.store.delete(requestId);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* IndexedDBConsentRepository - Browser-compatible implementation
|
|
81
|
+
* Uses IndexedDB for persistent storage in browser environments.
|
|
82
|
+
*/
|
|
83
|
+
export class IndexedDBConsentRepository implements ConsentRepository {
|
|
84
|
+
private dbName = 'pdw-consent-store';
|
|
85
|
+
private storeName = 'consent-requests';
|
|
86
|
+
private dbVersion = 1;
|
|
87
|
+
private db: IDBDatabase | null = null;
|
|
88
|
+
|
|
89
|
+
constructor(options?: { dbName?: string }) {
|
|
90
|
+
if (options?.dbName) {
|
|
91
|
+
this.dbName = options.dbName;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private async getDB(): Promise<IDBDatabase> {
|
|
96
|
+
if (this.db) {
|
|
97
|
+
return this.db;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return new Promise((resolve, reject) => {
|
|
101
|
+
const request = indexedDB.open(this.dbName, this.dbVersion);
|
|
102
|
+
|
|
103
|
+
request.onerror = () => reject(request.error);
|
|
104
|
+
request.onsuccess = () => {
|
|
105
|
+
this.db = request.result;
|
|
106
|
+
resolve(request.result);
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
request.onupgradeneeded = (event) => {
|
|
110
|
+
const db = (event.target as IDBOpenDBRequest).result;
|
|
111
|
+
if (!db.objectStoreNames.contains(this.storeName)) {
|
|
112
|
+
const store = db.createObjectStore(this.storeName, { keyPath: 'requestId' });
|
|
113
|
+
store.createIndex('targetWallet', 'targetWallet', { unique: false });
|
|
114
|
+
store.createIndex('requesterWallet', 'requesterWallet', { unique: false });
|
|
115
|
+
store.createIndex('status', 'status', { unique: false });
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async save(request: ConsentRequestRecord): Promise<void> {
|
|
122
|
+
const db = await this.getDB();
|
|
123
|
+
const normalized = normalizeRecord(request);
|
|
124
|
+
|
|
125
|
+
return new Promise((resolve, reject) => {
|
|
126
|
+
const tx = db.transaction(this.storeName, 'readwrite');
|
|
127
|
+
const store = tx.objectStore(this.storeName);
|
|
128
|
+
const req = store.put(normalized);
|
|
129
|
+
|
|
130
|
+
req.onerror = () => reject(req.error);
|
|
131
|
+
req.onsuccess = () => resolve();
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async updateStatus(requestId: string, status: ConsentStatus, updatedAt: number): Promise<void> {
|
|
136
|
+
const record = await this.getById(requestId);
|
|
137
|
+
if (!record) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
await this.save({
|
|
142
|
+
...record,
|
|
143
|
+
status,
|
|
144
|
+
updatedAt,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async getById(requestId: string): Promise<ConsentRequestRecord | null> {
|
|
149
|
+
const db = await this.getDB();
|
|
150
|
+
|
|
151
|
+
return new Promise((resolve, reject) => {
|
|
152
|
+
const tx = db.transaction(this.storeName, 'readonly');
|
|
153
|
+
const store = tx.objectStore(this.storeName);
|
|
154
|
+
const req = store.get(requestId);
|
|
155
|
+
|
|
156
|
+
req.onerror = () => reject(req.error);
|
|
157
|
+
req.onsuccess = () => {
|
|
158
|
+
const record = req.result as StoredConsentRecord | undefined;
|
|
159
|
+
resolve(record ? { ...record } : null);
|
|
160
|
+
};
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async listByTarget(targetWallet: string, status?: ConsentStatus): Promise<ConsentRequestRecord[]> {
|
|
165
|
+
const normalizedTarget = normalizeSuiAddress(targetWallet);
|
|
166
|
+
const db = await this.getDB();
|
|
167
|
+
|
|
168
|
+
return new Promise((resolve, reject) => {
|
|
169
|
+
const tx = db.transaction(this.storeName, 'readonly');
|
|
170
|
+
const store = tx.objectStore(this.storeName);
|
|
171
|
+
const index = store.index('targetWallet');
|
|
172
|
+
const req = index.getAll(normalizedTarget);
|
|
173
|
+
|
|
174
|
+
req.onerror = () => reject(req.error);
|
|
175
|
+
req.onsuccess = () => {
|
|
176
|
+
let records = req.result as StoredConsentRecord[];
|
|
177
|
+
if (status) {
|
|
178
|
+
records = records.filter((r) => r.status === status);
|
|
179
|
+
}
|
|
180
|
+
resolve(records.map((r) => ({ ...r })));
|
|
181
|
+
};
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async listByRequester(requesterWallet: string, status?: ConsentStatus): Promise<ConsentRequestRecord[]> {
|
|
186
|
+
const normalizedRequester = normalizeSuiAddress(requesterWallet);
|
|
187
|
+
const db = await this.getDB();
|
|
188
|
+
|
|
189
|
+
return new Promise((resolve, reject) => {
|
|
190
|
+
const tx = db.transaction(this.storeName, 'readonly');
|
|
191
|
+
const store = tx.objectStore(this.storeName);
|
|
192
|
+
const index = store.index('requesterWallet');
|
|
193
|
+
const req = index.getAll(normalizedRequester);
|
|
194
|
+
|
|
195
|
+
req.onerror = () => reject(req.error);
|
|
196
|
+
req.onsuccess = () => {
|
|
197
|
+
let records = req.result as StoredConsentRecord[];
|
|
198
|
+
if (status) {
|
|
199
|
+
records = records.filter((r) => r.status === status);
|
|
200
|
+
}
|
|
201
|
+
resolve(records.map((r) => ({ ...r })));
|
|
202
|
+
};
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
async delete(requestId: string): Promise<void> {
|
|
207
|
+
const db = await this.getDB();
|
|
208
|
+
|
|
209
|
+
return new Promise((resolve, reject) => {
|
|
210
|
+
const tx = db.transaction(this.storeName, 'readwrite');
|
|
211
|
+
const store = tx.objectStore(this.storeName);
|
|
212
|
+
const req = store.delete(requestId);
|
|
213
|
+
|
|
214
|
+
req.onerror = () => reject(req.error);
|
|
215
|
+
req.onsuccess = () => resolve();
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Close the database connection
|
|
221
|
+
*/
|
|
222
|
+
close(): void {
|
|
223
|
+
if (this.db) {
|
|
224
|
+
this.db.close();
|
|
225
|
+
this.db = null;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Factory function to create the appropriate ConsentRepository for browser
|
|
232
|
+
*/
|
|
233
|
+
export function createBrowserConsentRepository(options?: {
|
|
234
|
+
dbName?: string;
|
|
235
|
+
forceInMemory?: boolean;
|
|
236
|
+
}): ConsentRepository {
|
|
237
|
+
// Force in-memory for testing
|
|
238
|
+
if (options?.forceInMemory) {
|
|
239
|
+
return new InMemoryConsentRepository();
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Browser environment - use IndexedDB
|
|
243
|
+
if (typeof window !== 'undefined' && typeof indexedDB !== 'undefined') {
|
|
244
|
+
return new IndexedDBConsentRepository({ dbName: options?.dbName });
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Fallback to in-memory
|
|
248
|
+
return new InMemoryConsentRepository();
|
|
249
|
+
}
|
package/src/permissions/index.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Permissions Module
|
|
3
|
-
*
|
|
4
|
-
* Consent persistence and repository implementations.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
export type { ConsentRepository } from './ConsentRepository';
|
|
8
|
-
export { FileSystemConsentRepository } from './ConsentRepository';
|
|
9
|
-
export { InMemoryConsentRepository } from './ConsentRepository';
|
|
1
|
+
/**
|
|
2
|
+
* Permissions Module
|
|
3
|
+
*
|
|
4
|
+
* Consent persistence and repository implementations.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export type { ConsentRepository } from './ConsentRepository';
|
|
8
|
+
export { FileSystemConsentRepository } from './ConsentRepository';
|
|
9
|
+
export { InMemoryConsentRepository } from './ConsentRepository';
|
|
@@ -223,35 +223,291 @@ JSON:`;
|
|
|
223
223
|
const contextSection = context ? `\nCONTEXT: ${context}\n` : '';
|
|
224
224
|
|
|
225
225
|
return `
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
-
|
|
247
|
-
- "
|
|
248
|
-
-
|
|
249
|
-
|
|
250
|
-
|
|
226
|
+
You are a knowledge graph extraction system for a Personal Data Wallet application. Your task is to extract meaningful entities and relationships from personal memories, notes, and user statements.
|
|
227
|
+
|
|
228
|
+
## CRITICAL RULE: User Entity
|
|
229
|
+
ALWAYS include a "user" entity to represent the person who wrote this memory:
|
|
230
|
+
{
|
|
231
|
+
"id": "user",
|
|
232
|
+
"label": "User",
|
|
233
|
+
"type": "person",
|
|
234
|
+
"confidence": 1.0
|
|
235
|
+
}
|
|
236
|
+
This "user" entity should be the source or target of relationships describing personal preferences, attributes, or experiences.
|
|
237
|
+
|
|
238
|
+
## Entity Types (Comprehensive List)
|
|
239
|
+
|
|
240
|
+
### People & Social
|
|
241
|
+
- **person**: Individual people, including the user themselves
|
|
242
|
+
- Examples: "user", "john_doe", "my_mother", "boss"
|
|
243
|
+
- Properties: name, role, relationship_to_user
|
|
244
|
+
|
|
245
|
+
### Organizations & Groups
|
|
246
|
+
- **organization**: Companies, institutions, teams, communities
|
|
247
|
+
- Examples: "google", "harvard_university", "local_gym"
|
|
248
|
+
- Properties: industry, size, location
|
|
249
|
+
|
|
250
|
+
### Locations & Places
|
|
251
|
+
- **location**: Geographic places, addresses, venues
|
|
252
|
+
- Examples: "ho_chi_minh_city", "vietnam", "my_office", "central_park"
|
|
253
|
+
- Properties: type (city/country/venue), coordinates
|
|
254
|
+
|
|
255
|
+
### Food & Dining
|
|
256
|
+
- **food**: Foods, dishes, cuisines, beverages, ingredients
|
|
257
|
+
- Examples: "spaghetti", "vietnamese_cuisine", "coffee", "chocolate"
|
|
258
|
+
- Properties: cuisine_type, meal_type, dietary_info
|
|
259
|
+
- **restaurant**: Eating establishments
|
|
260
|
+
- Examples: "starbucks", "local_pho_shop"
|
|
261
|
+
- Properties: cuisine, price_range
|
|
262
|
+
|
|
263
|
+
### Preferences & Interests
|
|
264
|
+
- **preference**: General likes, dislikes, favorites
|
|
265
|
+
- Examples: "blue_color", "morning_routine", "minimalist_style"
|
|
266
|
+
- Properties: sentiment (positive/negative/neutral), intensity (1-10)
|
|
267
|
+
- **hobby**: Recreational activities, pastimes
|
|
268
|
+
- Examples: "playing_guitar", "photography", "hiking", "gaming"
|
|
269
|
+
- Properties: frequency, skill_level
|
|
270
|
+
- **interest**: Topics of curiosity or passion
|
|
271
|
+
- Examples: "artificial_intelligence", "history", "cooking"
|
|
272
|
+
- Properties: depth (casual/moderate/deep)
|
|
273
|
+
|
|
274
|
+
### Skills & Abilities
|
|
275
|
+
- **skill**: Technical or soft skills, expertise areas
|
|
276
|
+
- Examples: "python_programming", "public_speaking", "cooking"
|
|
277
|
+
- Properties: proficiency (beginner/intermediate/expert)
|
|
278
|
+
- **language**: Languages known or being learned
|
|
279
|
+
- Examples: "english", "vietnamese", "japanese"
|
|
280
|
+
- Properties: proficiency, native (true/false)
|
|
281
|
+
|
|
282
|
+
### Objects & Possessions
|
|
283
|
+
- **object**: Physical items, products, tools
|
|
284
|
+
- Examples: "macbook_pro", "my_car", "guitar"
|
|
285
|
+
- Properties: brand, model, acquisition_date
|
|
286
|
+
- **digital_product**: Software, apps, digital services
|
|
287
|
+
- Examples: "spotify", "notion", "chatgpt"
|
|
288
|
+
- Properties: category, usage_frequency
|
|
289
|
+
|
|
290
|
+
### Time & Events
|
|
291
|
+
- **event**: Occasions, milestones, meetings
|
|
292
|
+
- Examples: "birthday_2024", "job_interview", "vacation_trip"
|
|
293
|
+
- Properties: date, duration, importance
|
|
294
|
+
- **routine**: Regular activities or habits
|
|
295
|
+
- Examples: "morning_workout", "weekly_meeting", "daily_meditation"
|
|
296
|
+
- Properties: frequency, time_of_day
|
|
297
|
+
|
|
298
|
+
### Abstract & Conceptual
|
|
299
|
+
- **concept**: Ideas, topics, abstract things
|
|
300
|
+
- Examples: "work_life_balance", "productivity", "happiness"
|
|
301
|
+
- **goal**: Objectives, aspirations, plans
|
|
302
|
+
- Examples: "learn_japanese", "run_marathon", "save_money"
|
|
303
|
+
- Properties: deadline, priority, status
|
|
304
|
+
- **emotion**: Feelings, moods, emotional states
|
|
305
|
+
- Examples: "happiness", "stress", "excitement"
|
|
306
|
+
- Properties: intensity, trigger
|
|
307
|
+
|
|
308
|
+
### Health & Wellness
|
|
309
|
+
- **health_condition**: Medical conditions, allergies
|
|
310
|
+
- Examples: "lactose_intolerance", "migraine", "allergy_to_peanuts"
|
|
311
|
+
- **medication**: Medicines, supplements
|
|
312
|
+
- Examples: "vitamin_d", "aspirin"
|
|
313
|
+
- **exercise**: Physical activities for health
|
|
314
|
+
- Examples: "running", "yoga", "weight_training"
|
|
315
|
+
|
|
316
|
+
### Media & Entertainment
|
|
317
|
+
- **music**: Songs, artists, genres, albums
|
|
318
|
+
- Examples: "jazz_music", "beatles", "classical_piano"
|
|
319
|
+
- **movie**: Films, TV shows, documentaries
|
|
320
|
+
- Examples: "inception", "game_of_thrones"
|
|
321
|
+
- **book**: Books, authors, genres
|
|
322
|
+
- Examples: "atomic_habits", "fiction_genre"
|
|
323
|
+
- **game**: Video games, board games
|
|
324
|
+
- Examples: "chess", "minecraft"
|
|
325
|
+
|
|
326
|
+
## Relationship Types (Comprehensive List)
|
|
327
|
+
|
|
328
|
+
### Preference Relationships (source: usually "user")
|
|
329
|
+
- **loves**: Strong positive preference (intensity 9-10)
|
|
330
|
+
- **likes**: Moderate positive preference (intensity 6-8)
|
|
331
|
+
- **enjoys**: Positive experience with something
|
|
332
|
+
- **prefers**: Comparative preference
|
|
333
|
+
- **favorite**: Top choice in a category
|
|
334
|
+
- **interested_in**: Curiosity or engagement
|
|
335
|
+
- **dislikes**: Moderate negative preference
|
|
336
|
+
- **hates**: Strong negative preference (intensity 9-10)
|
|
337
|
+
- **avoids**: Intentionally stays away from
|
|
338
|
+
- **allergic_to**: Medical/physical aversion
|
|
339
|
+
|
|
340
|
+
### Affiliation Relationships
|
|
341
|
+
- **works_at**: Employment relationship
|
|
342
|
+
- **studies_at**: Educational institution
|
|
343
|
+
- **member_of**: Group membership
|
|
344
|
+
- **belongs_to**: General affiliation
|
|
345
|
+
- **founded**: Created an organization
|
|
346
|
+
- **leads**: Leadership role
|
|
347
|
+
|
|
348
|
+
### Location Relationships
|
|
349
|
+
- **lives_in**: Current residence
|
|
350
|
+
- **from**: Origin/hometown
|
|
351
|
+
- **located_in**: Physical location
|
|
352
|
+
- **visited**: Past travel
|
|
353
|
+
- **wants_to_visit**: Travel aspiration
|
|
354
|
+
|
|
355
|
+
### Social Relationships
|
|
356
|
+
- **knows**: Acquaintance
|
|
357
|
+
- **friends_with**: Friendship
|
|
358
|
+
- **family_of**: Family relationship (specify: parent, sibling, child, spouse)
|
|
359
|
+
- **works_with**: Professional relationship
|
|
360
|
+
- **mentored_by**: Learning relationship
|
|
361
|
+
|
|
362
|
+
### Skill & Knowledge Relationships
|
|
363
|
+
- **has_skill**: Possesses ability
|
|
364
|
+
- **expert_in**: High proficiency
|
|
365
|
+
- **learning**: Currently acquiring
|
|
366
|
+
- **wants_to_learn**: Aspiration to learn
|
|
367
|
+
- **teaches**: Instructing others
|
|
368
|
+
- **certified_in**: Formal qualification
|
|
369
|
+
|
|
370
|
+
### Possession & Usage
|
|
371
|
+
- **owns**: Ownership
|
|
372
|
+
- **uses**: Regular usage
|
|
373
|
+
- **wants**: Desire to acquire
|
|
374
|
+
- **recommends**: Positive endorsement
|
|
375
|
+
|
|
376
|
+
### Temporal Relationships
|
|
377
|
+
- **started_on**: Beginning date
|
|
378
|
+
- **ended_on**: Ending date
|
|
379
|
+
- **scheduled_for**: Future event
|
|
380
|
+
- **happens_during**: Temporal context
|
|
381
|
+
|
|
382
|
+
### Causal & Descriptive
|
|
383
|
+
- **causes**: Causal relationship
|
|
384
|
+
- **related_to**: General association
|
|
385
|
+
- **part_of**: Component relationship
|
|
386
|
+
- **similar_to**: Similarity
|
|
387
|
+
- **opposite_of**: Contrast
|
|
388
|
+
|
|
389
|
+
## Output Format
|
|
390
|
+
|
|
391
|
+
Return ONLY valid JSON with this structure:
|
|
392
|
+
{
|
|
393
|
+
"entities": [
|
|
394
|
+
{
|
|
395
|
+
"id": "snake_case_identifier",
|
|
396
|
+
"label": "Human Readable Name",
|
|
397
|
+
"type": "entity_type_from_list_above",
|
|
398
|
+
"confidence": 0.0-1.0,
|
|
399
|
+
"properties": { "optional": "attributes" }
|
|
400
|
+
}
|
|
401
|
+
],
|
|
402
|
+
"relationships": [
|
|
403
|
+
{
|
|
404
|
+
"source": "source_entity_id",
|
|
405
|
+
"target": "target_entity_id",
|
|
406
|
+
"label": "relationship_type_from_list_above",
|
|
407
|
+
"confidence": 0.0-1.0,
|
|
408
|
+
"type": "optional_category"
|
|
409
|
+
}
|
|
410
|
+
]
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
## Examples
|
|
414
|
+
|
|
415
|
+
### Example 1: Food Preference
|
|
416
|
+
Input: "i love spaghetti"
|
|
417
|
+
Output:
|
|
418
|
+
{
|
|
419
|
+
"entities": [
|
|
420
|
+
{"id": "user", "label": "User", "type": "person", "confidence": 1.0},
|
|
421
|
+
{"id": "spaghetti", "label": "Spaghetti", "type": "food", "confidence": 0.95, "properties": {"cuisine": "italian", "meal_type": "main_course"}}
|
|
422
|
+
],
|
|
423
|
+
"relationships": [
|
|
424
|
+
{"source": "user", "target": "spaghetti", "label": "loves", "confidence": 0.95, "type": "preference"}
|
|
425
|
+
]
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
### Example 2: Multiple Preferences
|
|
429
|
+
Input: "i like hamburgers but hate vegetables"
|
|
430
|
+
Output:
|
|
431
|
+
{
|
|
432
|
+
"entities": [
|
|
433
|
+
{"id": "user", "label": "User", "type": "person", "confidence": 1.0},
|
|
434
|
+
{"id": "hamburgers", "label": "Hamburgers", "type": "food", "confidence": 0.95},
|
|
435
|
+
{"id": "vegetables", "label": "Vegetables", "type": "food", "confidence": 0.95}
|
|
436
|
+
],
|
|
437
|
+
"relationships": [
|
|
438
|
+
{"source": "user", "target": "hamburgers", "label": "likes", "confidence": 0.9, "type": "preference"},
|
|
439
|
+
{"source": "user", "target": "vegetables", "label": "dislikes", "confidence": 0.9, "type": "preference"}
|
|
440
|
+
]
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
### Example 3: Work Information
|
|
444
|
+
Input: "i work at Google as a software engineer in Mountain View"
|
|
445
|
+
Output:
|
|
446
|
+
{
|
|
447
|
+
"entities": [
|
|
448
|
+
{"id": "user", "label": "User", "type": "person", "confidence": 1.0, "properties": {"role": "software_engineer"}},
|
|
449
|
+
{"id": "google", "label": "Google", "type": "organization", "confidence": 0.98, "properties": {"industry": "technology"}},
|
|
450
|
+
{"id": "software_engineer", "label": "Software Engineer", "type": "skill", "confidence": 0.9},
|
|
451
|
+
{"id": "mountain_view", "label": "Mountain View", "type": "location", "confidence": 0.95, "properties": {"type": "city"}}
|
|
452
|
+
],
|
|
453
|
+
"relationships": [
|
|
454
|
+
{"source": "user", "target": "google", "label": "works_at", "confidence": 0.98, "type": "affiliation"},
|
|
455
|
+
{"source": "user", "target": "software_engineer", "label": "has_skill", "confidence": 0.9, "type": "skill"},
|
|
456
|
+
{"source": "google", "target": "mountain_view", "label": "located_in", "confidence": 0.85, "type": "location"}
|
|
457
|
+
]
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
### Example 4: Personal Life
|
|
461
|
+
Input: "my name is Aaron and I live in Ho Chi Minh City with my wife"
|
|
462
|
+
Output:
|
|
463
|
+
{
|
|
464
|
+
"entities": [
|
|
465
|
+
{"id": "user", "label": "Aaron", "type": "person", "confidence": 1.0, "properties": {"name": "Aaron"}},
|
|
466
|
+
{"id": "ho_chi_minh_city", "label": "Ho Chi Minh City", "type": "location", "confidence": 0.98, "properties": {"type": "city", "country": "Vietnam"}},
|
|
467
|
+
{"id": "wife", "label": "Wife", "type": "person", "confidence": 0.9, "properties": {"relationship": "spouse"}}
|
|
468
|
+
],
|
|
469
|
+
"relationships": [
|
|
470
|
+
{"source": "user", "target": "ho_chi_minh_city", "label": "lives_in", "confidence": 0.98, "type": "location"},
|
|
471
|
+
{"source": "user", "target": "wife", "label": "family_of", "confidence": 0.95, "type": "social", "properties": {"relationship_type": "spouse"}}
|
|
472
|
+
]
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
### Example 5: Hobbies and Interests
|
|
476
|
+
Input: "i enjoy playing guitar and listening to jazz music on weekends"
|
|
477
|
+
Output:
|
|
478
|
+
{
|
|
479
|
+
"entities": [
|
|
480
|
+
{"id": "user", "label": "User", "type": "person", "confidence": 1.0},
|
|
481
|
+
{"id": "playing_guitar", "label": "Playing Guitar", "type": "hobby", "confidence": 0.95},
|
|
482
|
+
{"id": "guitar", "label": "Guitar", "type": "object", "confidence": 0.9, "properties": {"category": "musical_instrument"}},
|
|
483
|
+
{"id": "jazz_music", "label": "Jazz Music", "type": "music", "confidence": 0.95, "properties": {"genre": "jazz"}},
|
|
484
|
+
{"id": "weekends", "label": "Weekends", "type": "routine", "confidence": 0.8, "properties": {"frequency": "weekly"}}
|
|
485
|
+
],
|
|
486
|
+
"relationships": [
|
|
487
|
+
{"source": "user", "target": "playing_guitar", "label": "enjoys", "confidence": 0.95, "type": "hobby"},
|
|
488
|
+
{"source": "playing_guitar", "target": "guitar", "label": "uses", "confidence": 0.9, "type": "activity"},
|
|
489
|
+
{"source": "user", "target": "jazz_music", "label": "enjoys", "confidence": 0.9, "type": "preference"},
|
|
490
|
+
{"source": "playing_guitar", "target": "weekends", "label": "happens_during", "confidence": 0.8, "type": "temporal"}
|
|
491
|
+
]
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
## Guidelines
|
|
495
|
+
|
|
496
|
+
1. **Always include "user" entity** for personal statements (first-person: "I", "my", "me")
|
|
497
|
+
2. **Extract implicit information**: "i'm a doctor" implies medical skill
|
|
498
|
+
3. **Handle negations properly**: "don't like" = dislikes relationship
|
|
499
|
+
4. **Capture intensity**: "love" vs "like" vs "enjoy" = different confidence/intensity
|
|
500
|
+
5. **Include relevant properties**: cuisine type for food, location type for places
|
|
501
|
+
6. **Create bidirectional relationships when applicable**: if A works_at B, B employs A
|
|
502
|
+
7. **Minimum confidence threshold**: 0.5 for entities, 0.5 for relationships
|
|
503
|
+
8. **Be comprehensive**: Extract ALL meaningful entities, even from short texts
|
|
504
|
+
9. **Handle multilingual content**: Vietnamese, English, etc.
|
|
505
|
+
10. **Infer entity types from context**: "spaghetti" = food, "Python" = skill/language based on context
|
|
251
506
|
${contextSection}
|
|
252
|
-
TEXT:
|
|
507
|
+
## TEXT TO ANALYZE:
|
|
508
|
+
${content}
|
|
253
509
|
|
|
254
|
-
JSON:`;
|
|
510
|
+
## JSON OUTPUT:`;
|
|
255
511
|
}
|
|
256
512
|
|
|
257
513
|
private parseExtractionResponse(response: string): { entities: any[]; relationships: any[] } {
|