@cmdoss/memwal-sdk 0.8.0 → 1.0.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.
Files changed (209) hide show
  1. package/README.md +522 -160
  2. package/dist/client/ClientMemoryManager.d.ts.map +1 -1
  3. package/dist/client/ClientMemoryManager.js +25 -8
  4. package/dist/client/ClientMemoryManager.js.map +1 -1
  5. package/dist/client/PersonalDataWallet.d.ts.map +1 -1
  6. package/dist/client/SimplePDWClient.d.ts +62 -2
  7. package/dist/client/SimplePDWClient.d.ts.map +1 -1
  8. package/dist/client/SimplePDWClient.js +96 -11
  9. package/dist/client/SimplePDWClient.js.map +1 -1
  10. package/dist/client/namespaces/IndexNamespace.d.ts +1 -1
  11. package/dist/client/namespaces/IndexNamespace.d.ts.map +1 -1
  12. package/dist/client/namespaces/IndexNamespace.js +7 -4
  13. package/dist/client/namespaces/IndexNamespace.js.map +1 -1
  14. package/dist/client/namespaces/MemoryNamespace.d.ts +47 -0
  15. package/dist/client/namespaces/MemoryNamespace.d.ts.map +1 -1
  16. package/dist/client/namespaces/MemoryNamespace.js +257 -27
  17. package/dist/client/namespaces/MemoryNamespace.js.map +1 -1
  18. package/dist/client/namespaces/consolidated/AdvancedNamespace.d.ts +215 -0
  19. package/dist/client/namespaces/consolidated/AdvancedNamespace.d.ts.map +1 -0
  20. package/dist/client/namespaces/consolidated/AdvancedNamespace.js +214 -0
  21. package/dist/client/namespaces/consolidated/AdvancedNamespace.js.map +1 -0
  22. package/dist/client/namespaces/consolidated/StorageNamespace.d.ts +3 -1
  23. package/dist/client/namespaces/consolidated/StorageNamespace.d.ts.map +1 -1
  24. package/dist/client/namespaces/consolidated/StorageNamespace.js.map +1 -1
  25. package/dist/client/namespaces/consolidated/index.d.ts +1 -0
  26. package/dist/client/namespaces/consolidated/index.d.ts.map +1 -1
  27. package/dist/client/namespaces/consolidated/index.js +1 -0
  28. package/dist/client/namespaces/consolidated/index.js.map +1 -1
  29. package/dist/config/ConfigurationHelper.js +61 -61
  30. package/dist/config/defaults.d.ts.map +1 -1
  31. package/dist/config/defaults.js +9 -4
  32. package/dist/config/defaults.js.map +1 -1
  33. package/dist/config/index.d.ts +1 -0
  34. package/dist/config/index.d.ts.map +1 -1
  35. package/dist/config/index.js +2 -0
  36. package/dist/config/index.js.map +1 -1
  37. package/dist/config/modelDefaults.d.ts +67 -0
  38. package/dist/config/modelDefaults.d.ts.map +1 -0
  39. package/dist/config/modelDefaults.js +91 -0
  40. package/dist/config/modelDefaults.js.map +1 -0
  41. package/dist/core/types/index.d.ts +4 -0
  42. package/dist/core/types/index.d.ts.map +1 -1
  43. package/dist/core/types/index.js.map +1 -1
  44. package/dist/graph/GraphService.d.ts.map +1 -1
  45. package/dist/graph/GraphService.js +22 -21
  46. package/dist/graph/GraphService.js.map +1 -1
  47. package/dist/index.d.ts +1 -1
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +1 -1
  50. package/dist/index.js.map +1 -1
  51. package/dist/infrastructure/walrus/WalrusStorageService.d.ts +6 -0
  52. package/dist/infrastructure/walrus/WalrusStorageService.d.ts.map +1 -1
  53. package/dist/infrastructure/walrus/WalrusStorageService.js +23 -4
  54. package/dist/infrastructure/walrus/WalrusStorageService.js.map +1 -1
  55. package/dist/langchain/createPDWRAG.js +30 -30
  56. package/dist/pipeline/MemoryPipeline.d.ts.map +1 -1
  57. package/dist/pipeline/MemoryPipeline.js +2 -1
  58. package/dist/pipeline/MemoryPipeline.js.map +1 -1
  59. package/dist/services/EmbeddingService.d.ts +9 -0
  60. package/dist/services/EmbeddingService.d.ts.map +1 -1
  61. package/dist/services/EmbeddingService.js +31 -10
  62. package/dist/services/EmbeddingService.js.map +1 -1
  63. package/dist/services/GeminiAIService.d.ts.map +1 -1
  64. package/dist/services/GeminiAIService.js +311 -310
  65. package/dist/services/GeminiAIService.js.map +1 -1
  66. package/dist/services/MemoryIndexService.d.ts +2 -0
  67. package/dist/services/MemoryIndexService.d.ts.map +1 -1
  68. package/dist/services/MemoryIndexService.js +11 -4
  69. package/dist/services/MemoryIndexService.js.map +1 -1
  70. package/dist/services/StorageService.d.ts +4 -1
  71. package/dist/services/StorageService.d.ts.map +1 -1
  72. package/dist/services/StorageService.js.map +1 -1
  73. package/dist/services/VectorService.js +1 -1
  74. package/dist/services/VectorService.js.map +1 -1
  75. package/dist/services/storage/QuiltBatchManager.d.ts +7 -0
  76. package/dist/services/storage/QuiltBatchManager.d.ts.map +1 -1
  77. package/dist/services/storage/QuiltBatchManager.js +24 -5
  78. package/dist/services/storage/QuiltBatchManager.js.map +1 -1
  79. package/dist/services/storage/WalrusStorageManager.d.ts +10 -1
  80. package/dist/services/storage/WalrusStorageManager.d.ts.map +1 -1
  81. package/dist/services/storage/WalrusStorageManager.js +53 -12
  82. package/dist/services/storage/WalrusStorageManager.js.map +1 -1
  83. package/dist/vector/BrowserHnswIndexService.js +3 -3
  84. package/dist/vector/BrowserHnswIndexService.js.map +1 -1
  85. package/dist/vector/HnswWasmService.js +1 -1
  86. package/dist/vector/HnswWasmService.js.map +1 -1
  87. package/dist/vector/NodeHnswService.js +5 -5
  88. package/dist/vector/NodeHnswService.js.map +1 -1
  89. package/dist/vector/createHnswService.d.ts +4 -0
  90. package/dist/vector/createHnswService.d.ts.map +1 -1
  91. package/dist/vector/createHnswService.js +15 -3
  92. package/dist/vector/createHnswService.js.map +1 -1
  93. package/package.json +1 -1
  94. package/src/access/PermissionService.ts +635 -635
  95. package/src/aggregation/AggregationService.ts +389 -389
  96. package/src/ai-sdk/PDWVectorStore.ts +715 -715
  97. package/src/ai-sdk/index.ts +65 -65
  98. package/src/ai-sdk/tools.ts +460 -460
  99. package/src/ai-sdk/types.ts +404 -404
  100. package/src/batch/BatchManager.ts +597 -597
  101. package/src/batch/BatchingService.ts +429 -429
  102. package/src/batch/MemoryProcessingCache.ts +492 -492
  103. package/src/batch/index.ts +30 -30
  104. package/src/browser.ts +200 -200
  105. package/src/client/ClientMemoryManager.ts +1004 -987
  106. package/src/client/PersonalDataWallet.ts +345 -345
  107. package/src/client/SimplePDWClient.ts +1387 -1289
  108. package/src/client/factory.ts +154 -154
  109. package/src/client/namespaces/AnalyticsNamespace.ts +377 -377
  110. package/src/client/namespaces/BatchNamespace.ts +356 -356
  111. package/src/client/namespaces/CacheNamespace.ts +123 -123
  112. package/src/client/namespaces/CapabilityNamespace.ts +217 -217
  113. package/src/client/namespaces/ClassifyNamespace.ts +169 -169
  114. package/src/client/namespaces/ContextNamespace.ts +297 -297
  115. package/src/client/namespaces/EncryptionNamespace.ts +221 -221
  116. package/src/client/namespaces/GraphNamespace.ts +468 -468
  117. package/src/client/namespaces/IndexNamespace.ts +364 -361
  118. package/src/client/namespaces/MemoryNamespace.ts +1704 -1422
  119. package/src/client/namespaces/PermissionsNamespace.ts +254 -254
  120. package/src/client/namespaces/PipelineNamespace.ts +220 -220
  121. package/src/client/namespaces/StorageNamespace.ts +458 -458
  122. package/src/client/namespaces/TxNamespace.ts +260 -260
  123. package/src/client/namespaces/WalletNamespace.ts +243 -243
  124. package/src/client/namespaces/consolidated/AdvancedNamespace.ts +264 -0
  125. package/src/client/namespaces/consolidated/BlockchainNamespace.ts +607 -607
  126. package/src/client/namespaces/consolidated/SecurityNamespace.ts +648 -648
  127. package/src/client/namespaces/consolidated/StorageNamespace.ts +1143 -1141
  128. package/src/client/namespaces/consolidated/index.ts +41 -39
  129. package/src/client/signers/KeypairSigner.ts +108 -108
  130. package/src/client/signers/UnifiedSigner.ts +110 -110
  131. package/src/client/signers/WalletAdapterSigner.ts +159 -159
  132. package/src/client/signers/index.ts +26 -26
  133. package/src/config/ConfigurationHelper.ts +412 -412
  134. package/src/config/defaults.ts +56 -51
  135. package/src/config/index.ts +16 -9
  136. package/src/config/modelDefaults.ts +103 -0
  137. package/src/config/validation.ts +70 -70
  138. package/src/core/index.ts +14 -14
  139. package/src/core/interfaces/IService.ts +307 -307
  140. package/src/core/interfaces/index.ts +8 -8
  141. package/src/core/types/capability.ts +297 -297
  142. package/src/core/types/index.ts +874 -870
  143. package/src/core/types/wallet.ts +270 -270
  144. package/src/core/types.ts +9 -9
  145. package/src/core/wallet.ts +222 -222
  146. package/src/embedding/index.ts +19 -19
  147. package/src/embedding/types.ts +357 -357
  148. package/src/errors/index.ts +602 -602
  149. package/src/errors/recovery.ts +461 -461
  150. package/src/errors/validation.ts +567 -567
  151. package/src/generated/pdw/capability.ts +319 -319
  152. package/src/graph/GraphService.ts +888 -887
  153. package/src/graph/KnowledgeGraphManager.ts +728 -728
  154. package/src/graph/index.ts +25 -25
  155. package/src/index.ts +498 -498
  156. package/src/infrastructure/index.ts +22 -22
  157. package/src/infrastructure/seal/EncryptionService.ts +628 -628
  158. package/src/infrastructure/seal/SealService.ts +613 -613
  159. package/src/infrastructure/seal/index.ts +9 -9
  160. package/src/infrastructure/sui/BlockchainManager.ts +627 -627
  161. package/src/infrastructure/sui/SuiService.ts +888 -888
  162. package/src/infrastructure/sui/index.ts +9 -9
  163. package/src/infrastructure/walrus/StorageManager.ts +604 -604
  164. package/src/infrastructure/walrus/WalrusStorageService.ts +637 -612
  165. package/src/infrastructure/walrus/index.ts +9 -9
  166. package/src/langchain/createPDWRAG.ts +303 -303
  167. package/src/langchain/index.ts +47 -47
  168. package/src/permissions/ConsentRepository.browser.ts +249 -249
  169. package/src/permissions/ConsentRepository.ts +364 -364
  170. package/src/pipeline/MemoryPipeline.ts +863 -862
  171. package/src/pipeline/PipelineManager.ts +683 -683
  172. package/src/pipeline/index.ts +26 -26
  173. package/src/retrieval/AdvancedSearchService.ts +629 -629
  174. package/src/retrieval/MemoryAnalyticsService.ts +711 -711
  175. package/src/retrieval/MemoryDecryptionPipeline.ts +825 -825
  176. package/src/retrieval/index.ts +42 -42
  177. package/src/services/BatchService.ts +352 -352
  178. package/src/services/CapabilityService.ts +464 -464
  179. package/src/services/ClassifierService.ts +465 -465
  180. package/src/services/CrossContextPermissionService.ts +486 -486
  181. package/src/services/EmbeddingService.ts +796 -771
  182. package/src/services/EncryptionService.ts +712 -712
  183. package/src/services/GeminiAIService.ts +754 -753
  184. package/src/services/MemoryIndexService.ts +1009 -1003
  185. package/src/services/MemoryService.ts +369 -369
  186. package/src/services/QueryService.ts +890 -890
  187. package/src/services/StorageService.ts +1185 -1182
  188. package/src/services/TransactionService.ts +838 -838
  189. package/src/services/VectorService.ts +462 -462
  190. package/src/services/ViewService.ts +484 -484
  191. package/src/services/index.ts +25 -25
  192. package/src/services/storage/BlobAttributesManager.ts +333 -333
  193. package/src/services/storage/KnowledgeGraphManager.ts +425 -425
  194. package/src/services/storage/MemorySearchManager.ts +387 -387
  195. package/src/services/storage/QuiltBatchManager.ts +1157 -1130
  196. package/src/services/storage/WalrusMetadataManager.ts +268 -268
  197. package/src/services/storage/WalrusStorageManager.ts +333 -287
  198. package/src/services/storage/index.ts +57 -57
  199. package/src/types/index.ts +13 -13
  200. package/src/utils/index.ts +76 -76
  201. package/src/utils/memoryIndexOnChain.ts +507 -507
  202. package/src/vector/BrowserHnswIndexService.ts +758 -758
  203. package/src/vector/HnswWasmService.ts +731 -731
  204. package/src/vector/IHnswService.ts +233 -233
  205. package/src/vector/NodeHnswService.ts +833 -833
  206. package/src/vector/createHnswService.ts +147 -135
  207. package/src/vector/index.ts +56 -56
  208. package/src/wallet/ContextWalletService.ts +656 -656
  209. package/src/wallet/MainWalletService.ts +317 -317
package/README.md CHANGED
@@ -5,29 +5,50 @@
5
5
 
6
6
  **MemWal** (Memory + Walrus) - TypeScript SDK for decentralized memory storage on Sui blockchain with Walrus.
7
7
 
8
+ ## Contract Addresses
9
+
10
+ | Network | Package ID |
11
+ |---------|------------|
12
+ | **Testnet** | `0xa5d7d98ea41620c9aaf9f13afa6512455d4d10ca06ccea3f8cd5b2b9568e3a9e` |
13
+ | **Mainnet** | Coming soon |
14
+
15
+ ## Features
16
+
17
+ | Feature | Description |
18
+ |---------|-------------|
19
+ | **Memory CRUD** | Create, read, search, delete memories on Sui + Walrus |
20
+ | **Unified Search** | `pdw.memory.search()` - auto-embeds query and searches |
21
+ | **SEAL Encryption** | Identity-based encryption v2.2 (enabled by default) |
22
+ | **Vector Search** | Fast HNSW search with IndexedDB persistence (browser) |
23
+ | **AI Classification** | Auto-categorize memories (fact, event, preference, etc.) |
24
+ | **Batch Upload** | ~90% gas savings with Quilt batching |
25
+ | **Knowledge Graph** | Entity and relationship extraction |
26
+ | **IndexedDB Storage** | Persistent local vector index in browser |
27
+
8
28
  ## Installation
9
29
 
10
30
  ```bash
11
- npm install @cmdoss/memwal-sdk @mysten/sui
31
+ npm install @cmdoss/memwal-sdk @mysten/sui @mysten/dapp-kit
12
32
  ```
13
33
 
14
34
  ## Quick Start
15
35
 
16
- ### Node.js (with Keypair)
36
+ ### Minimal Example (Node.js Server)
17
37
 
18
38
  ```typescript
19
39
  import { SimplePDWClient } from '@cmdoss/memwal-sdk';
20
- import { Ed25519Keypair, decodeSuiPrivateKey } from '@mysten/sui/keypairs/ed25519';
40
+ import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
21
41
 
22
- // Setup keypair
23
- const { secretKey } = decodeSuiPrivateKey(process.env.SUI_PRIVATE_KEY!);
24
- const keypair = Ed25519Keypair.fromSecretKey(secretKey);
42
+ const PACKAGE_ID = '0xa5d7d98ea41620c9aaf9f13afa6512455d4d10ca06ccea3f8cd5b2b9568e3a9e';
43
+
44
+ // Create keypair (for server-side automation)
45
+ const keypair = Ed25519Keypair.generate();
46
+ console.log('Address:', keypair.toSuiAddress());
25
47
 
26
- // Initialize client
27
48
  const pdw = new SimplePDWClient({
28
49
  signer: keypair,
29
50
  network: 'testnet',
30
- packageId: process.env.PACKAGE_ID!,
51
+ sui: { packageId: PACKAGE_ID },
31
52
  embedding: {
32
53
  provider: 'openrouter',
33
54
  apiKey: process.env.OPENROUTER_API_KEY!,
@@ -36,268 +57,609 @@ const pdw = new SimplePDWClient({
36
57
 
37
58
  await pdw.ready();
38
59
 
39
- // Create memory
40
- const memory = await pdw.memory.create('I work at CommandOSS as a developer');
41
- console.log('Memory ID:', memory.id);
42
-
43
- // Search memories
44
- const results = await pdw.search.vector('work experience', { limit: 5 });
60
+ // Create & Search
61
+ const memory = await pdw.memory.create('I love programming');
62
+ const results = await pdw.memory.search('coding', { limit: 5 });
45
63
  ```
46
64
 
47
- ### Browser (with dapp-kit + Slush/Sui Wallet)
65
+ ### React/Next.js (with Sui Wallet)
48
66
 
49
67
  ```typescript
50
- import { DappKitSigner, SimplePDWClient } from '@cmdoss/memwal-sdk/browser';
68
+ import { SimplePDWClient, DappKitSigner } from '@cmdoss/memwal-sdk/browser';
51
69
  import { useCurrentAccount, useSignAndExecuteTransaction, useSuiClient } from '@mysten/dapp-kit';
52
70
 
53
- function MyComponent() {
71
+ const PACKAGE_ID = '0xa5d7d98ea41620c9aaf9f13afa6512455d4d10ca06ccea3f8cd5b2b9568e3a9e';
72
+
73
+ function MemoryComponent() {
54
74
  const account = useCurrentAccount();
55
75
  const suiClient = useSuiClient();
56
76
  const { mutateAsync: signAndExecute } = useSignAndExecuteTransaction();
57
77
 
58
- const handleSave = async () => {
59
- // Create signer from dapp-kit hooks
78
+ const saveMemory = async (content: string) => {
79
+ // Create signer - pass signAndExecute directly
60
80
  const signer = new DappKitSigner({
61
- address: account.address,
81
+ address: account!.address,
62
82
  client: suiClient,
63
- signAndExecuteTransaction: async ({ transaction }) => {
64
- const result = await signAndExecute({ transaction });
65
- return { digest: result.digest, effects: result.effects };
66
- },
83
+ signAndExecuteTransaction: signAndExecute,
67
84
  });
68
85
 
69
- // Initialize client
70
86
  const pdw = new SimplePDWClient({
71
87
  signer,
72
88
  network: 'testnet',
73
- userAddress: account.address,
74
- sui: { packageId: process.env.NEXT_PUBLIC_PACKAGE_ID! },
75
- features: { enableLocalIndexing: false }, // Disable for browser
89
+ userAddress: account!.address,
90
+ sui: { packageId: PACKAGE_ID },
91
+ features: {
92
+ enableLocalIndexing: false, // Browser: use server-side indexing
93
+ enableEncryption: true,
94
+ },
76
95
  });
77
96
 
78
- // Create memory - wallet popup appears for signing
79
- const memory = await pdw.memory.create('Hello from browser!');
97
+ await pdw.ready();
98
+ return await pdw.memory.create(content);
80
99
  };
100
+
101
+ return <button onClick={() => saveMemory('Hello World!')}>Save Memory</button>;
81
102
  }
82
103
  ```
83
104
 
84
- ## Features
105
+ > **Note**: Browser SDK doesn't include embedding service. For AI features (embeddings, classification), call your server API which uses the full SDK.
85
106
 
86
- | Feature | Description |
87
- |---------|-------------|
88
- | Memory CRUD | Create, read, update, delete memories on Sui + Walrus |
89
- | Vector Search | Semantic search with HNSW (3072 dimensions) |
90
- | AI Classification | Auto-categorize memories (fact, event, preference, etc.) |
91
- | SEAL Encryption | Optional identity-based encryption |
92
- | Batch Upload | ~90% gas savings with Quilt batching |
93
- | Knowledge Graph | Entity and relationship extraction |
94
-
95
- ## Environment Variables
96
-
97
- ```env
98
- SUI_PRIVATE_KEY=suiprivkey1...
99
- PACKAGE_ID=0x...
100
- OPENROUTER_API_KEY=sk-or-v1-...
107
+ ### Environment Variables
101
108
 
102
- # Optional
103
- WALRUS_AGGREGATOR=https://aggregator.walrus-testnet.walrus.space
104
- WALRUS_PUBLISHER=https://publisher.walrus-testnet.walrus.space
109
+ ```bash
110
+ # .env (Browser/Next.js)
111
+ NEXT_PUBLIC_OPENROUTER_API_KEY=sk-or-v1-... # For AI embeddings
112
+
113
+ # .env (Node.js server - optional)
114
+ OPENROUTER_API_KEY=sk-or-v1-... # For server-side embeddings
105
115
  ```
106
116
 
107
- ## API Overview
117
+ ## API Reference
118
+
119
+ ### Core Namespaces
120
+
121
+ The SDK provides 5 core namespaces for common operations:
108
122
 
109
123
  ```typescript
110
- // Memory operations
111
- await pdw.memory.create(content, { category, importance });
112
- await pdw.memory.createBatch([...contents]);
113
- await pdw.memory.get(id);
114
- await pdw.memory.delete(id);
115
-
116
- // Search
117
- await pdw.search.vector(query, { limit });
118
- await pdw.search.byCategory('fact');
119
- await pdw.search.hybrid(query, { category });
120
-
121
- // AI
122
- await pdw.ai.embed(text);
123
- await pdw.ai.classify(content);
124
- await pdw.ai.shouldSave(content);
124
+ pdw.memory // Create, get, search, list, delete memories
125
+ pdw.ai // Embed, classify, extract commands
126
+ pdw.index // HNSW index management
127
+ pdw.wallet // Wallet address and balance info
128
+ pdw.advanced // Power user features (graph, analytics, etc.)
129
+ ```
125
130
 
126
- // Knowledge Graph
127
- await pdw.graph.extract(content);
131
+ ### `pdw.memory` - Memory Operations
132
+
133
+ ```typescript
134
+ // CREATE - handles everything internally (embed, encrypt, upload, register, index)
135
+ const memory = await pdw.memory.create(content, {
136
+ category?: string, // Auto-classify if not provided
137
+ importance?: number, // Auto-score if not provided (1-10)
138
+ embedding?: number[], // Auto-generate if not provided
139
+ });
140
+
141
+ // CREATE BATCH - upload multiple memories efficiently
142
+ const memories = await pdw.memory.createBatch([
143
+ { content: 'Memory 1', category: 'fact' },
144
+ { content: 'Memory 2', category: 'preference' }
145
+ ]);
146
+
147
+ // SEARCH - unified semantic search (auto-embeds query)
148
+ const results = await pdw.memory.search(query, {
149
+ limit?: number, // Max results (default: 10)
150
+ threshold?: number, // Min similarity 0-1 (default: 0.7)
151
+ category?: string, // Filter by category
152
+ includeContent?: boolean // Include decrypted content (default: true)
153
+ });
154
+
155
+ // GET - retrieve by ID (auto-decrypts)
156
+ const memory = await pdw.memory.get(memoryId);
157
+
158
+ // LIST - list all memories with filters
159
+ const memories = await pdw.memory.list({
160
+ category?: string,
161
+ limit?: number,
162
+ offset?: number
163
+ });
164
+
165
+ // DELETE
166
+ await pdw.memory.delete(memoryId);
167
+ await pdw.memory.deleteBatch([id1, id2, id3]);
128
168
  ```
129
169
 
130
- ## Vector Search (HNSW)
170
+ ### `pdw.ai` - AI Operations
131
171
 
132
- The SDK uses HNSW for fast vector search:
172
+ ```typescript
173
+ // Generate embeddings
174
+ const embedding = await pdw.ai.embed(text);
175
+ const embeddings = await pdw.ai.embedBatch([text1, text2]);
133
176
 
134
- | Implementation | Environment | Performance |
135
- |----------------|-------------|-------------|
136
- | `hnswlib-node` | Node.js | **Fastest** (native C++) |
137
- | `hnswlib-wasm` | Browser + Node.js | Good (fallback) |
177
+ // Classify content
178
+ const { category, importance } = await pdw.ai.classify(content);
138
179
 
139
- The SDK auto-detects and uses the best available implementation.
180
+ // Extract memory commands from user input
181
+ const memories = pdw.ai.extractMultipleMemories(userMessage);
182
+ // Input: "remember I like pizza and my name is John"
183
+ // Output: ["I like pizza", "my name is John"]
140
184
 
141
- **For best performance in Node.js:**
185
+ // Check if content should be saved as memory
186
+ const shouldSave = await pdw.ai.shouldSave(content);
187
+ ```
142
188
 
143
- ```bash
144
- # Requires C++ build tools
145
- npm install hnswlib-node
189
+ ### `pdw.index` - HNSW Index Management
190
+
191
+ ```typescript
192
+ // Add vector to index
193
+ await pdw.index.add(spaceId, vectorId, vector, {
194
+ content: string,
195
+ blobId: string,
196
+ category: string,
197
+ importance: number,
198
+ isEncrypted: boolean,
199
+ forceStoreContent: boolean // Store content even when encrypted (for RAG)
200
+ });
201
+
202
+ // Search vectors
203
+ const results = await pdw.index.search(spaceId, queryVector, {
204
+ k: 10,
205
+ threshold: 0.7
206
+ });
207
+
208
+ // Get index stats
209
+ const stats = pdw.index.getStats(spaceId);
210
+
211
+ // Rebuild index from blockchain
212
+ await pdw.index.rebuild(userAddress);
213
+
214
+ // Clear index
215
+ await pdw.index.clear(spaceId);
216
+
217
+ // Flush to disk
218
+ await pdw.index.flush(spaceId);
146
219
  ```
147
220
 
148
- <details>
149
- <summary>Build tools installation</summary>
221
+ ### `pdw.wallet` - Wallet Information
150
222
 
151
- | Platform | Command |
152
- |----------|---------|
153
- | Windows | Install [VS Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/) with C++ workload |
154
- | macOS | `xcode-select --install` |
155
- | Linux | `sudo apt-get install build-essential python3` |
223
+ ```typescript
224
+ // Get wallet address
225
+ const address = pdw.wallet.address;
156
226
 
157
- </details>
227
+ // Get SUI balance
228
+ const balance = await pdw.wallet.balance();
229
+
230
+ // Get memory count
231
+ const count = await pdw.wallet.memoryCount();
232
+ ```
233
+
234
+ ### `pdw.advanced` - Power User Features
235
+
236
+ ```typescript
237
+ // Knowledge Graph
238
+ const graph = await pdw.advanced.graph.extract(content);
239
+ // Returns: { entities: [...], relationships: [...] }
240
+
241
+ // Analytics
242
+ const insights = await pdw.advanced.analytics.getInsights();
243
+
244
+ // Manual encryption/decryption
245
+ const encrypted = await pdw.advanced.encryption.encrypt(data);
246
+ const decrypted = await pdw.advanced.encryption.decrypt(encrypted);
247
+
248
+ // Permissions
249
+ await pdw.advanced.permissions.grant(memoryId, targetAddress);
250
+ await pdw.advanced.permissions.revoke(memoryId, targetAddress);
251
+
252
+ // Transaction building (low-level)
253
+ const tx = pdw.advanced.blockchain.buildCreateMemoryTx(params);
254
+ ```
255
+
256
+ ### Legacy Search API (Deprecated)
257
+
258
+ ```typescript
259
+ // Still works but deprecated - use pdw.memory.search() instead
260
+ await pdw.search.vector(query, { limit }); // -> pdw.memory.search()
261
+ await pdw.search.byCategory('fact'); // -> pdw.memory.list({ category: 'fact' })
262
+ await pdw.search.hybrid(query, { category }); // -> pdw.memory.search(query, { category })
263
+ ```
158
264
 
159
265
  ## Configuration
160
266
 
161
- ### Basic Configuration
267
+ ### Full Configuration
162
268
 
163
269
  ```typescript
164
270
  const pdw = new SimplePDWClient({
165
- signer: keypair, // Required: Sui keypair or wallet adapter
166
- network: 'testnet', // Required: 'testnet' | 'mainnet' | 'devnet'
271
+ // Required
272
+ signer: keypair, // Sui keypair or wallet adapter
273
+ network: 'testnet', // 'testnet' | 'mainnet' | 'devnet'
167
274
 
168
275
  // Embedding configuration (required for AI features)
169
276
  embedding: {
170
- provider: 'openrouter', // 'google' | 'openai' | 'openrouter' | 'cohere'
277
+ provider: 'openrouter', // 'google' | 'openai' | 'openrouter' | 'cohere'
171
278
  apiKey: process.env.OPENROUTER_API_KEY,
172
- modelName: 'google/gemini-embedding-001', // Optional: defaults per provider
173
- dimensions: 3072 // Optional: defaults per provider
279
+ modelName: 'google/text-embedding-004', // Optional: defaults per provider
280
+ dimensions: 768 // Optional: 768 (default), 1536, or 3072
174
281
  },
175
282
 
176
283
  // Optional: Sui configuration
177
284
  sui: {
178
- packageId: '0x...', // Default: from env PACKAGE_ID
179
- rpcUrl: 'https://...', // Default: from network
285
+ packageId: '0x...', // Default: from env PACKAGE_ID
286
+ rpcUrl: 'https://...', // Default: from network
180
287
  },
181
288
 
182
289
  // Optional: Walrus configuration
183
290
  walrus: {
184
- aggregator: 'https://...', // Default: from network
185
- publisher: 'https://...', // Default: from network
291
+ aggregatorUrl: 'https://aggregator.walrus-testnet.walrus.space',
292
+ publisherUrl: 'https://publisher.walrus-testnet.walrus.space',
293
+ },
294
+
295
+ // Optional: AI configuration
296
+ ai: {
297
+ apiKey: process.env.OPENROUTER_API_KEY,
298
+ chatModel: 'google/gemini-2.5-flash',
186
299
  },
187
300
 
188
301
  // Optional: Feature flags
189
302
  features: {
190
- enableEncryption: true, // Default: true (SEAL encryption)
191
- enableLocalIndexing: true, // Default: true (HNSW vector search)
192
- enableKnowledgeGraph: true // Default: true (entity extraction)
303
+ enableEncryption: true, // Default: true (SEAL encryption)
304
+ enableLocalIndexing: true, // Default: true (HNSW vector search)
305
+ enableKnowledgeGraph: true // Default: true (entity extraction)
306
+ },
307
+
308
+ // Optional: Encryption configuration
309
+ encryption: {
310
+ enabled: true,
311
+ keyServers: ['0x...', '0x...'], // Default: testnet key servers
312
+ threshold: 2, // M of N key servers required
313
+ accessRegistryId: '0x...'
314
+ },
315
+
316
+ // Optional: Index backup to Walrus (cloud sync)
317
+ indexBackup: {
318
+ enabled: true,
319
+ aggregatorUrl: 'https://...',
320
+ publisherUrl: 'https://...',
321
+ autoSync: false,
322
+ epochs: 3
193
323
  }
194
324
  });
195
325
  ```
196
326
 
197
- ### SEAL Encryption (Enabled by Default)
327
+ ### All Environment Variables Reference
328
+
329
+ ```bash
330
+ # Package ID (Testnet)
331
+ PACKAGE_ID=0xa5d7d98ea41620c9aaf9f13afa6512455d4d10ca06ccea3f8cd5b2b9568e3a9e
332
+
333
+ # Embedding Configuration
334
+ EMBEDDING_PROVIDER=openrouter # google, openai, openrouter, cohere
335
+ EMBEDDING_API_KEY= # Falls back to provider-specific keys
336
+ EMBEDDING_MODEL= # Optional: override default model
337
+ EMBEDDING_DIMENSIONS=768 # 768 (default), 1536, 3072
338
+
339
+ # Provider-specific API keys (fallback)
340
+ OPENROUTER_API_KEY=sk-or-v1-...
341
+ GEMINI_API_KEY=...
342
+ OPENAI_API_KEY=sk-...
343
+ COHERE_API_KEY=...
344
+
345
+ # AI Chat Model (for RAG responses, knowledge graph extraction)
346
+ AI_CHAT_MODEL=google/gemini-2.5-flash
347
+
348
+ # Walrus (optional - defaults to testnet)
349
+ WALRUS_NETWORK=testnet
350
+ WALRUS_AGGREGATOR=https://aggregator.walrus-testnet.walrus.space
351
+ WALRUS_PUBLISHER=https://publisher.walrus-testnet.walrus.space
352
+
353
+ # SEAL Encryption (optional - defaults configured)
354
+ ENABLE_ENCRYPTION=true
355
+ SEAL_KEY_SERVERS=0xKEY1,0xKEY2
356
+ SEAL_THRESHOLD=2
357
+ ACCESS_REGISTRY_ID=0x...
358
+ ```
359
+
360
+ ### Embedding Providers
361
+
362
+ | Provider | Model Default | Dimensions | API Key |
363
+ |----------|---------------|------------|---------|
364
+ | `openrouter` | `google/text-embedding-004` | 768 | `OPENROUTER_API_KEY` |
365
+ | `google` | `text-embedding-004` | 768 | `GEMINI_API_KEY` |
366
+ | `openai` | `text-embedding-3-small` | 1536 | `OPENAI_API_KEY` |
367
+ | `cohere` | `embed-english-v3.0` | 1024 | `COHERE_API_KEY` |
198
368
 
199
- **🔒 Encryption is enabled by default in v0.7.0+**
369
+ **Dimensions Trade-offs:**
370
+ - **768** (default): Fast embedding + small storage + fast search
371
+ - **1536**: Balance of quality and speed
372
+ - **3072**: Highest quality, slowest
200
373
 
201
- All memory content is automatically encrypted using SEAL (Secure Encrypted Access Layer) with identity-based encryption.
374
+ **Recommendation**: Use `openrouter` with 768 dimensions for best performance.
202
375
 
203
- #### Default Encryption (Recommended)
376
+ ### AI Model Configuration
377
+
378
+ The SDK uses centralized defaults that can be customized via environment variables or code.
379
+
380
+ #### Configuration Priority
381
+
382
+ ```text
383
+ User Config (code) → Environment Variable → SDK Default
384
+ ```
385
+
386
+ #### SDK Defaults
204
387
 
205
388
  ```typescript
206
- const pdw = new SimplePDWClient({
207
- signer: keypair,
208
- network: 'testnet',
209
- embedding: { provider: 'openrouter', apiKey: 'key' }
210
- // Encryption automatically enabled with defaults!
211
- });
389
+ import { MODEL_DEFAULTS, getChatModel } from '@cmdoss/memwal-sdk';
390
+
391
+ // View default values
392
+ console.log(MODEL_DEFAULTS);
393
+ // {
394
+ // EMBEDDING_OPENROUTER: 'google/gemini-embedding-001',
395
+ // EMBEDDING_GOOGLE: 'text-embedding-004',
396
+ // EMBEDDING_OPENAI: 'text-embedding-3-small',
397
+ // EMBEDDING_COHERE: 'embed-english-v3.0',
398
+ // CHAT_MODEL: 'google/gemini-2.5-flash',
399
+ // EMBEDDING_DIMENSIONS: 768,
400
+ // }
401
+
402
+ // Get current chat model (checks env first, then default)
403
+ const model = getChatModel(); // 'google/gemini-2.5-flash'
404
+ ```
212
405
 
213
- // Memories are encrypted on upload, decrypted on retrieval
214
- await pdw.memory.create('My private data');
406
+ #### Method 1: Environment Variables (Recommended)
407
+
408
+ ```bash
409
+ # .env
410
+ # Embedding
411
+ EMBEDDING_PROVIDER=openrouter
412
+ EMBEDDING_MODEL=google/gemini-embedding-001
413
+ EMBEDDING_DIMENSIONS=768
414
+
415
+ # Chat/Analysis (RAG, knowledge graph)
416
+ AI_CHAT_MODEL=google/gemini-2.5-flash
215
417
  ```
216
418
 
217
- #### Custom Encryption Configuration
419
+ #### Method 2: Code Configuration
218
420
 
219
421
  ```typescript
220
422
  const pdw = new SimplePDWClient({
221
423
  signer: keypair,
222
424
  network: 'testnet',
223
- embedding: { provider: 'openrouter', apiKey: 'key' },
224
425
 
225
- // Encryption configuration (optional)
226
- encryption: {
227
- enabled: true, // Default: true
228
- keyServers: [ // Default: testnet key servers
229
- '0x73d05d62c18d9374e3ea529e8e0ed6161da1a141a94d3f76ae3fe4e99356db75',
230
- '0xf5d14a81a982144ae441cd7d64b09027f116a468bd36e7eca494f750591623c8'
231
- ],
232
- threshold: 2, // Default: 2 (M of N key servers required)
233
- accessRegistryId: '0x...' // Default: testnet registry
234
- }
426
+ // Embedding config
427
+ embedding: {
428
+ provider: 'openrouter',
429
+ apiKey: process.env.OPENROUTER_API_KEY!,
430
+ modelName: 'google/gemini-embedding-001', // Override default
431
+ dimensions: 1536, // Override default 768
432
+ },
433
+
434
+ // AI chat config
435
+ ai: {
436
+ apiKey: process.env.OPENROUTER_API_KEY!,
437
+ chatModel: 'google/gemini-2.5-pro', // Override default
438
+ },
235
439
  });
236
440
  ```
237
441
 
238
- #### Environment Variables
442
+ #### Available Models
239
443
 
240
- ```bash
241
- # Disable encryption (not recommended for production)
242
- ENABLE_ENCRYPTION=false
444
+ | Purpose | Environment Variable | Default | Alternatives |
445
+ |---------|---------------------|---------|--------------|
446
+ | **Embedding** | `EMBEDDING_MODEL` | `google/gemini-embedding-001` | `text-embedding-3-small`, `embed-english-v3.0` |
447
+ | **Chat/RAG** | `AI_CHAT_MODEL` | `google/gemini-2.5-flash` | `google/gemini-2.5-pro`, `openai/gpt-4o`, `anthropic/claude-3.5-sonnet` |
243
448
 
244
- # Custom key servers (comma-separated)
245
- SEAL_KEY_SERVERS=0xKEY1,0xKEY2,0xKEY3
449
+ #### Model Selection Tips
246
450
 
247
- # Custom threshold
248
- SEAL_THRESHOLD=2
451
+ | Model | Speed | Quality | Cost | Best For |
452
+ |-------|-------|---------|------|----------|
453
+ | `google/gemini-2.5-flash` | ⚡ Fast | Good | $ | Default, most tasks |
454
+ | `google/gemini-2.5-pro` | Medium | ⬆️ Better | $$ | Complex reasoning |
455
+ | `openai/gpt-4o-mini` | ⚡ Fast | Good | $ | OpenAI alternative |
456
+ | `openai/gpt-4o` | Slow | ⬆️ Best | $$$ | Highest quality |
457
+ | `anthropic/claude-3.5-sonnet` | Medium | ⬆️ Better | $$ | Balanced |
249
458
 
250
- # Custom access registry
251
- ACCESS_REGISTRY_ID=0x...
252
- ```
459
+ ## SEAL Encryption
253
460
 
254
- #### How SEAL Encryption Works
461
+ Encryption is **enabled by default** in v1.0.0. All memory content and embeddings are automatically encrypted using SEAL v2.2 (Secure Encrypted Access Layer with capability-based access).
255
462
 
256
- - **Zero gas for decryption** - No blockchain transactions required
257
- - **Identity-based** - Uses Sui address as identity (userAddress)
258
- - **Threshold security** - Requires M of N key servers (default: 2 of 2)
259
- - **Cross-app sharing** - Share memories between apps with same user
260
- - **Privacy-preserving** - Content never exposed on-chain or in plaintext
463
+ ### How It Works
261
464
 
262
- #### Disabling Encryption (Development Only)
465
+ 1. **Identity-based**: Uses Sui address as encryption identity
466
+ 2. **Threshold security**: Requires M of N key servers (default: 2 of 2)
467
+ 3. **Zero gas for decryption**: No blockchain transactions required
468
+ 4. **Privacy-preserving**: Content never exposed on-chain
263
469
 
264
- ⚠️ **Not recommended for production**. Only use for non-sensitive test data:
470
+ ### Default Encryption (Recommended)
265
471
 
266
472
  ```typescript
267
473
  const pdw = new SimplePDWClient({
268
474
  signer: keypair,
269
475
  network: 'testnet',
270
- embedding: { provider: 'openrouter', apiKey: 'key' },
476
+ embedding: { provider: 'openrouter', apiKey: 'key' }
477
+ // Encryption automatically enabled!
478
+ });
479
+
480
+ // Memories encrypted on upload, decrypted on retrieval
481
+ await pdw.memory.create('My private data');
482
+ ```
483
+
484
+ ### Disabling Encryption (Development Only)
485
+
486
+ ```typescript
487
+ const pdw = new SimplePDWClient({
488
+ // ...
271
489
  features: {
272
- enableEncryption: false // ⚠️ Stores content in plaintext!
490
+ enableEncryption: false // Stores content in plaintext!
273
491
  }
274
492
  });
275
493
  ```
276
494
 
277
- ### Embedding Providers
495
+ ## Server-Side RAG
278
496
 
279
- | Provider | Model Default | Dimensions | API Key |
280
- |----------|---------------|------------|---------|
281
- | `openrouter` | `google/gemini-embedding-001` | 3072 | `OPENROUTER_API_KEY` |
282
- | `google` | `text-embedding-004` | 3072 | `GEMINI_API_KEY` |
283
- | `openai` | `text-embedding-3-small` | 1536 | `OPENAI_API_KEY` |
284
- | `cohere` | `embed-english-v3.0` | 1024 | `COHERE_API_KEY` |
497
+ For server-side applications with RAG (Retrieval-Augmented Generation), content needs to be stored in the local index even when encrypted.
498
+
499
+ ### Configuration
500
+
501
+ When indexing memories server-side, use `forceStoreContent: true`:
502
+
503
+ ```typescript
504
+ await pdw.index.add(walletAddress, vectorId, embedding, {
505
+ content: plaintextContent,
506
+ blobId: blobId,
507
+ isEncrypted: true,
508
+ forceStoreContent: true // Store content for RAG even when encrypted
509
+ });
510
+ ```
511
+
512
+ ### API Route Example
285
513
 
286
- **Recommendation**: Use `openrouter` for unified access to multiple models.
514
+ ```typescript
515
+ // /api/memory/index/route.ts
516
+ export async function POST(req: Request) {
517
+ const { walletAddress, memoryId, content, embedding, blobId } = await req.json();
518
+
519
+ const pdw = await getReadOnlyPDWClient(walletAddress);
520
+
521
+ await pdw.index.add(walletAddress, vectorId, embedding, {
522
+ content,
523
+ blobId,
524
+ isEncrypted: true,
525
+ forceStoreContent: true // Enable RAG for encrypted memories
526
+ });
527
+ }
528
+ ```
529
+
530
+ ### Chat API with Memory Search
531
+
532
+ ```typescript
533
+ // /api/chat/route.ts
534
+ export async function POST(req: Request) {
535
+ const { messages, walletAddress } = await req.json();
536
+ const pdw = await getReadOnlyPDWClient(walletAddress);
537
+
538
+ // Search memories for context
539
+ const memories = await pdw.memory.search(userMessage, {
540
+ limit: 10,
541
+ threshold: 0.3,
542
+ includeContent: true
543
+ });
544
+
545
+ // Build prompt with memory context
546
+ const systemPrompt = `
547
+ User's memories:
548
+ ${memories.map(m => m.content).join('\n')}
549
+ `;
550
+
551
+ // Call LLM with context
552
+ return streamText({ model, messages, system: systemPrompt });
553
+ }
554
+ ```
555
+
556
+ ## Vector Search (HNSW)
557
+
558
+ The SDK uses HNSW for fast approximate nearest neighbor search:
559
+
560
+ | Implementation | Environment | Performance | Storage |
561
+ |----------------|-------------|-------------|---------|
562
+ | `hnswlib-node` | Node.js | **Fastest** (native C++) | File system |
563
+ | `hnswlib-wasm` | Browser + Node.js | Good (fallback) | IndexedDB |
564
+
565
+ The SDK auto-detects and uses the best available implementation.
566
+
567
+ ### Browser IndexedDB Persistence
568
+
569
+ In browsers, the vector index is automatically persisted to IndexedDB:
570
+
571
+ - **Database**: `pdw-hnsw-index`
572
+ - **Store**: `vectors` (per user wallet address)
573
+ - **Auto-save**: After each memory creation
574
+ - **Auto-load**: On SDK initialization
575
+
576
+ This means users don't lose their local search index when refreshing the page or closing the browser.
577
+
578
+ ### For Best Performance in Node.js
579
+
580
+ ```bash
581
+ # Requires C++ build tools
582
+ npm install hnswlib-node
583
+ ```
584
+
585
+ <details>
586
+ <summary>Build tools installation</summary>
587
+
588
+ | Platform | Command |
589
+ |----------|---------|
590
+ | Windows | Install [VS Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/) with C++ workload |
591
+ | macOS | `xcode-select --install` |
592
+ | Linux | `sudo apt-get install build-essential python3` |
593
+
594
+ </details>
595
+
596
+ ## Index Rebuild
597
+
598
+ When users log in on a new device or the local index is lost, rebuild from blockchain:
599
+
600
+ ```typescript
601
+ import { rebuildIndexNode, hasExistingIndexNode } from '@cmdoss/memwal-sdk';
602
+ import { SuiClient, getFullnodeUrl } from '@mysten/sui/client';
603
+
604
+ const client = new SuiClient({ url: getFullnodeUrl('testnet') });
605
+
606
+ // Check if index exists
607
+ const hasIndex = await hasExistingIndexNode(userAddress);
608
+
609
+ if (!hasIndex) {
610
+ // Rebuild from blockchain + Walrus
611
+ const result = await rebuildIndexNode({
612
+ userAddress,
613
+ client,
614
+ packageId: process.env.PACKAGE_ID!,
615
+ network: 'testnet',
616
+ force: false, // Set true to force rebuild
617
+ fetchConcurrency: 10, // Parallel blob fetches
618
+ onProgress: (current, total, status) => {
619
+ console.log(`${current}/${total}: ${status}`);
620
+ }
621
+ });
622
+
623
+ console.log(`Indexed ${result.indexedMemories}/${result.totalMemories} memories`);
624
+ }
625
+ ```
626
+
627
+ ## Exports
628
+
629
+ ```typescript
630
+ // Main exports
631
+ import { SimplePDWClient } from '@cmdoss/memwal-sdk';
632
+
633
+ // Browser-safe exports
634
+ import { SimplePDWClient, DappKitSigner } from '@cmdoss/memwal-sdk/browser';
635
+
636
+ // React hooks
637
+ import { usePDWClient, useMemory } from '@cmdoss/memwal-sdk/hooks';
638
+
639
+ // Services (advanced)
640
+ import { EmbeddingService, MemoryIndexService } from '@cmdoss/memwal-sdk/services';
641
+
642
+ // LangChain integration
643
+ import { PDWVectorStore } from '@cmdoss/memwal-sdk/langchain';
644
+
645
+ // Vercel AI SDK integration
646
+ import { createPDWTool } from '@cmdoss/memwal-sdk/ai-sdk';
647
+
648
+ // Node.js utilities
649
+ import { rebuildIndexNode, hasExistingIndexNode, clearIndexNode } from '@cmdoss/memwal-sdk';
650
+ ```
287
651
 
288
652
  ## Benchmarks
289
653
 
290
- Tested on localhost with Option A+ (local content retrieval enabled):
654
+ Tested on localhost with encryption enabled:
291
655
 
292
656
  | Operation | Time | Description |
293
657
  |-----------|------|-------------|
294
- | Vector Search + RAG | ~2.3s | Chat with semantic search |
295
- | Create Memory | ~2.3s | Classify + embed + upload + index |
296
- | AI Classification | ~2.3s | Categorize content |
297
- | Batch Upload (2 items) | ~2.3s | Quilt batching |
298
- | Blockchain Query | ~2.3s | List memories from Sui |
299
-
300
- **Average query time: ~2.3s** (with OpenRouter API latency included)
658
+ | Memory Search | ~0.5s | Semantic search (local HNSW) |
659
+ | Create Memory | ~2.5s | Classify + embed + encrypt + upload + index |
660
+ | AI Classification | ~0.8s | Categorize content |
661
+ | Batch Upload (5 items) | ~3s | Quilt batching with encryption |
662
+ | Blockchain Query | ~0.3s | List memories from Sui |
301
663
 
302
664
  ## Documentation
303
665