@personize/sdk 0.7.2 → 0.7.4

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 CHANGED
@@ -541,22 +541,45 @@ const result = await client.agents.run(agentId, {
541
541
 
542
542
  ### Collections
543
543
 
544
+ Collections define the property schemas that the AI extraction pipeline uses when memorizing content.
545
+
544
546
  ```typescript
545
547
  // List collections
546
548
  const collections = await client.collections.list();
547
549
 
548
- // Create a collection
550
+ // Create a collection with properties
549
551
  await client.collections.create({
550
- collectionName: 'Deal Properties',
552
+ collectionName: 'Contact Properties',
551
553
  entityType: 'Contact',
554
+ definition: 'Customer profile fields for GTM workflows',
555
+ properties: [
556
+ { propertyName: 'Lifecycle Stage', type: 'options', options: 'Lead, MQL, SQL, Customer', description: 'Current funnel stage', update: true },
557
+ { propertyName: 'Meeting Notes', type: 'array', description: 'Chronological meeting log', update: false, tags: ['interaction'] },
558
+ ],
559
+ });
560
+
561
+ // Add a single property to an existing collection (incremental -- existing properties are preserved)
562
+ await client.collections.update(collectionId, {
563
+ properties: [
564
+ { propertyName: 'Location', type: 'text', description: 'City or region', update: true, tags: ['identity'] },
565
+ ],
566
+ historyNote: 'Added Location property',
567
+ });
568
+
569
+ // Add multiple properties at once
570
+ await client.collections.update(collectionId, {
552
571
  properties: [
553
- { propertyName: 'Deal Stage', type: 'options', options: 'Discovery,Proposal,Closed' },
572
+ { propertyName: 'Budget Range', type: 'options', options: '<50K, 50K-200K, 200K-1M, >1M', update: true },
573
+ { propertyName: 'Decision Timeline', type: 'text', description: 'When they plan to buy', update: true },
574
+ { propertyName: 'Objections Log', type: 'array', description: 'Sales objections raised', update: false },
554
575
  ],
576
+ historyNote: 'Added qualification properties for lead scoring',
555
577
  });
556
578
 
557
- // Update a collection
579
+ // Soft-delete a property (existing stored values are preserved)
558
580
  await client.collections.update(collectionId, {
559
- properties: [{ propertyName: 'Budget', type: 'number', description: 'Estimated budget' }],
581
+ properties: [{ propertyName: 'Old Field', systemName: 'old_field', status: 'Deleted' }],
582
+ historyNote: 'Retired Old Field property',
560
583
  });
561
584
 
562
585
  // Delete a collection
@@ -566,6 +589,24 @@ await client.collections.delete(collectionId);
566
589
  const history = await client.collections.history(collectionId, { mode: 'diff', limit: 10 });
567
590
  ```
568
591
 
592
+ **Property definition fields:** `propertyName` (required), `systemName` (auto-generated), `type` (`'text'` | `'number'` | `'boolean'` | `'array'` | `'date'` | `'options'`, default `'text'`), `description`, `update` (`true` = replaceable, `false` = append-only), `options`, `tags`, `status` (`'Active'` | `'Deleted'`).
593
+
594
+ See `CollectionPropertyDefinition` in `types.ts` for the full reference.
595
+
596
+ ### Defaults & Limits
597
+
598
+ Default result sizes for retrieval methods. All are optional -- pass explicitly to request more or fewer.
599
+
600
+ | Method | Param | Default | Max | Notes |
601
+ |--------|-------|---------|-----|-------|
602
+ | `memory.smartRecall()` | `token_budget` | 4,000 tokens | -- | Token-budgeted, not count-based |
603
+ | `memory.recall()` | `limit` | 10 memories | 5,000 | |
604
+ | `memory.smartDigest()` | `token_budget` | 1,000 tokens | -- | Also accepts `maxMemories` (default 20) |
605
+ | `memory.search()` / `memory.filterByProperty()` | `pageSize` | 50 records | 200 | |
606
+ | `memory.similar()` | `topK` | 25 records | 5,000 | |
607
+ | `memory.segment()` | `maxPerTier` | 50 per tier | -- | No hard cap |
608
+ | `memory.memorize()` (batch) | items | -- | 100 | Optimal: 10-50 per call |
609
+
569
610
  ### Evaluation
570
611
 
571
612
  ```typescript
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { PersonizeConfig, ApiResponse, MeResponse, TestResponse, ListOptions, GuidelinesResponse, GuidelineSectionOptions, GuidelineUpdatePayload, GuidelineCreatePayload, GuidelineHistoryResponse, GuidelineHistoryOptions, CollectionsResponse, CollectionCreatePayload, CollectionUpdatePayload, CollectionHistoryOptions, CollectionHistoryResponse, SmartGuidelinesOptions, SmartGuidelinesResponse, PromptOptions, PromptResponse, PromptStreamOptions, PromptSSEEvent, AgentRunOptions, AgentResponse, MemorizeOptions, SmartRecallOptions, RecallOptions, RecallResponse, SearchOptions, SearchResponse, BatchMemorizeOptions, SmartDigestOptions, SmartDigestResponse, EvaluateMemorizationOptions, EvaluateMemorizationResponse, UpdatePropertyOptions, UpdateResult, BulkUpdateOptions, BulkUpdateResult, PropertyHistoryOptions, PropertyHistoryResult, QueryPropertiesOptions, QueryPropertiesResult, DeleteMemoriesOptions, DeleteRecordOptions, DeletionResult, CancelDeletionOptions, CancelDeletionResult, FilterByPropertyOptions, FilterByPropertyResult, GetPropertiesOptions, GetPropertiesResponse, ResponsesCreateOptions, ResponsesCompletedResult, ChatCompletionsOptions, ChatCompletionResult, SimilarOptions, SimilarResponse, SegmentOptions, SegmentResponse } from './types';
1
+ import { PersonizeConfig, ApiResponse, MeResponse, TestResponse, ListOptions, GuidelinesResponse, GuidelineSectionOptions, GuidelineUpdatePayload, GuidelineCreatePayload, GuidelineHistoryResponse, GuidelineHistoryOptions, CollectionsResponse, CollectionCreatePayload, CollectionUpdatePayload, CollectionHistoryOptions, CollectionHistoryResponse, SmartGuidelinesOptions, SmartGuidelinesResponse, PromptOptions, PromptResponse, PromptStreamOptions, PromptSSEEvent, AgentRunOptions, AgentResponse, MemorizeOptions, SmartRecallOptions, RecallOptions, RecallResponse, SearchOptions, SearchResponse, BatchMemorizeOptions, SmartDigestOptions, SmartDigestResponse, EvaluateMemorizationOptions, EvaluateMemorizationResponse, UpdatePropertyOptions, UpdateResult, BulkUpdateOptions, BulkUpdateResult, PropertyHistoryOptions, PropertyHistoryResult, QueryPropertiesOptions, QueryPropertiesResult, DeleteMemoriesOptions, DeleteRecordOptions, DeletionResult, CancelDeletionOptions, CancelDeletionResult, FilterByPropertyOptions, FilterByPropertyResult, GetPropertiesOptions, GetPropertiesResponse, ResponsesCreateOptions, ResponsesCompletedResult, ChatCompletionsOptions, ChatCompletionResult, SimilarOptions, SimilarResponse, SegmentOptions, SegmentResponse, UpdateKeysOptions, UpdateKeysResponse, UpdateKeysBatchOptions, UpdateKeysBatchResponse, ListKeysOptions, ListKeysResponse, DeleteKeysOptions, DeleteKeysResponse, SmartUpdateOptions, SmartUpdateResponse, GovernanceAttachment, AttachmentUpdateOptions, AttachmentUploadOptions, BatchAttachmentUploadOptions } from './types';
2
2
  export declare class Personize {
3
3
  private client;
4
4
  private _organizationId?;
@@ -27,6 +27,8 @@ export declare class Personize {
27
27
  private normalizeSearchResponse;
28
28
  private normalizeRecallResponse;
29
29
  private isBatchRecordProperty;
30
+ private hasRecordIdentity;
31
+ private buildContentValueWithMetadata;
30
32
  private memorizeBatchFromRecords;
31
33
  /**
32
34
  * GET /api/v1/test — Verify API key is valid. Returns request metadata and resolved identity.
@@ -66,6 +68,48 @@ export declare class Personize {
66
68
  * GET /api/v1/actions/:id/history — Get version history for a guideline
67
69
  */
68
70
  history: (id: string, options?: GuidelineHistoryOptions) => Promise<ApiResponse<GuidelineHistoryResponse>>;
71
+ /**
72
+ * POST /api/v1/smart-update -- AI-powered governance & schema evolution.
73
+ * Analyzes instruction + material against existing guidelines or collections
74
+ * and returns (or applies) a structured change plan.
75
+ */
76
+ smartUpdate: (data: SmartUpdateOptions) => Promise<ApiResponse<SmartUpdateResponse>>;
77
+ /**
78
+ * GET /api/v1/guidelines/:guidelineId/attachments — List all attachments for a guideline.
79
+ */
80
+ listAttachments: (guidelineId: string) => Promise<ApiResponse<GovernanceAttachment[]>>;
81
+ /**
82
+ * GET /api/v1/guidelines/:guidelineId/attachments/:attachmentId — Get attachment metadata and a signed download URL.
83
+ */
84
+ getAttachment: (guidelineId: string, attachmentId: string) => Promise<ApiResponse<GovernanceAttachment & {
85
+ downloadUrl: string;
86
+ }>>;
87
+ /**
88
+ * PATCH /api/v1/guidelines/:guidelineId/attachments/:attachmentId — Update attachment metadata (description, usage, type, language, sectionHeader).
89
+ */
90
+ updateAttachment: (guidelineId: string, attachmentId: string, options: AttachmentUpdateOptions) => Promise<ApiResponse<GovernanceAttachment>>;
91
+ /**
92
+ * DELETE /api/v1/guidelines/:guidelineId/attachments/:attachmentId — Delete an attachment.
93
+ */
94
+ deleteAttachment: (guidelineId: string, attachmentId: string) => Promise<ApiResponse<void>>;
95
+ /**
96
+ * POST /api/v1/guidelines/:guidelineId/attachments — Upload a new attachment.
97
+ * @todo Requires multipart/form-data support (postFormData). Not yet implemented.
98
+ */
99
+ uploadAttachment: (_guidelineId: string, _options: AttachmentUploadOptions) => Promise<ApiResponse<GovernanceAttachment>>;
100
+ /**
101
+ * PUT /api/v1/guidelines/:guidelineId/attachments/:attachmentId/content — Replace attachment file content.
102
+ * @todo Requires multipart/form-data support (postFormData). Not yet implemented.
103
+ */
104
+ replaceAttachmentContent: (_guidelineId: string, _attachmentId: string, _file: Buffer) => Promise<ApiResponse<GovernanceAttachment>>;
105
+ /**
106
+ * POST /api/v1/guidelines/:guidelineId/attachments/batch — Upload multiple attachments in one request.
107
+ * @todo Requires multipart/form-data support (postFormData). Not yet implemented.
108
+ */
109
+ batchUploadAttachments: (_guidelineId: string, _options: BatchAttachmentUploadOptions) => Promise<ApiResponse<{
110
+ uploaded: GovernanceAttachment[];
111
+ warnings: string[];
112
+ }>>;
69
113
  };
70
114
  collections: {
71
115
  /**
@@ -241,6 +285,74 @@ export declare class Personize {
241
285
  * @see https://docs.personize.ai/api#segment
242
286
  */
243
287
  segment: (data: SegmentOptions) => Promise<ApiResponse<SegmentResponse>>;
288
+ /**
289
+ * POST /api/v1/memory/update-keys -- Add keys (standard or custom) to a record.
290
+ * Identify the record by recordId, email, websiteUrl, or any CRM key.
291
+ */
292
+ updateKeys: (data: UpdateKeysOptions) => Promise<ApiResponse<UpdateKeysResponse>>;
293
+ /**
294
+ * POST /api/v1/memory/update-keys-batch -- Add keys across multiple records.
295
+ * Max 100 records, 50 keys per record.
296
+ */
297
+ updateKeysBatch: (data: UpdateKeysBatchOptions) => Promise<ApiResponse<UpdateKeysBatchResponse>>;
298
+ /**
299
+ * POST /api/v1/memory/list-keys -- List all keys (standard + custom) on a record.
300
+ */
301
+ listKeys: (data: ListKeysOptions) => Promise<ApiResponse<ListKeysResponse>>;
302
+ /**
303
+ * POST /api/v1/memory/delete-keys -- Delete specific key aliases from a record.
304
+ * Blocks deletion if it would leave zero aliases.
305
+ */
306
+ deleteKeys: (data: DeleteKeysOptions) => Promise<ApiResponse<DeleteKeysResponse>>;
307
+ };
308
+ smartRecallUnified: (data: import("./types").SmartRecallUnifiedOptions) => Promise<import("./types").ApiResponse<import("./types").SmartRecallUnifiedResponse>>;
309
+ rag: {
310
+ configure: (data: import("./types").ExternalRAGConfigOptions) => Promise<import("./types").ApiResponse<{
311
+ configured: boolean;
312
+ }>>;
313
+ search: (data: import("./types").ExternalRAGSearchOptions) => Promise<import("./types").ApiResponse<{
314
+ results: import("./types").ExternalRAGSearchResult[];
315
+ }>>;
316
+ test: () => Promise<import("./types").ApiResponse<{
317
+ healthy: boolean;
318
+ latencyMs: number;
319
+ }>>;
320
+ /** Our LanceDB RAG: ingest documents into a project */
321
+ ingest: (data: import("./types").RAGIngestOptions) => Promise<import("./types").ApiResponse<{
322
+ ingested: number;
323
+ errors: string[];
324
+ }>>;
325
+ /** Our LanceDB RAG: search a project */
326
+ searchProject: (data: import("./types").RAGSearchOptions) => Promise<import("./types").ApiResponse<{
327
+ results: import("./types").RAGSearchResult[];
328
+ count: number;
329
+ }>>;
330
+ /** Our LanceDB RAG: list projects for this org */
331
+ listProjects: () => Promise<import("./types").ApiResponse<{
332
+ projects: string[];
333
+ count: number;
334
+ }>>;
335
+ /** Our LanceDB RAG: delete documents from a project */
336
+ deleteDocuments: (data: import("./types").RAGDeleteOptions) => Promise<import("./types").ApiResponse<{
337
+ deleted: number;
338
+ }>>;
339
+ /** Our LanceDB RAG: delete an entire project */
340
+ deleteProject: (projectId: string) => Promise<import("./types").ApiResponse<{
341
+ message: string;
342
+ }>>;
343
+ };
344
+ multimodal: {
345
+ memorize: (data: import("./types").MultimodalMemorizeOptions) => Promise<import("./types").ApiResponse<{
346
+ stored: boolean;
347
+ }>>;
348
+ search: (data: import("./types").MultimodalSearchOptions) => Promise<import("./types").ApiResponse<{
349
+ results: import("./types").MultimodalSearchResult[];
350
+ }>>;
351
+ status: () => Promise<import("./types").ApiResponse<{
352
+ enabled: boolean;
353
+ provider?: string;
354
+ model?: string;
355
+ }>>;
244
356
  };
245
357
  evaluate: {
246
358
  /**
package/dist/client.js CHANGED
@@ -85,6 +85,77 @@ class Personize {
85
85
  });
86
86
  return response.data;
87
87
  },
88
+ /**
89
+ * POST /api/v1/smart-update -- AI-powered governance & schema evolution.
90
+ * Analyzes instruction + material against existing guidelines or collections
91
+ * and returns (or applies) a structured change plan.
92
+ */
93
+ smartUpdate: async (data) => {
94
+ const payload = {
95
+ type: data.type,
96
+ instruction: data.instruction,
97
+ material: data.material,
98
+ strategy: data.strategy || 'suggest',
99
+ };
100
+ if (data.targetIds || data.target_ids) {
101
+ payload.targetIds = data.targetIds || data.target_ids;
102
+ }
103
+ const response = await this.client.post('/api/v1/smart-update', payload);
104
+ return response.data;
105
+ },
106
+ // ── Attachment methods ────────────────────────────────────────────────
107
+ /**
108
+ * GET /api/v1/guidelines/:guidelineId/attachments — List all attachments for a guideline.
109
+ */
110
+ listAttachments: async (guidelineId) => {
111
+ const response = await this.client.get(`/api/v1/guidelines/${guidelineId}/attachments`);
112
+ return response.data;
113
+ },
114
+ /**
115
+ * GET /api/v1/guidelines/:guidelineId/attachments/:attachmentId — Get attachment metadata and a signed download URL.
116
+ */
117
+ getAttachment: async (guidelineId, attachmentId) => {
118
+ const response = await this.client.get(`/api/v1/guidelines/${guidelineId}/attachments/${attachmentId}`);
119
+ return response.data;
120
+ },
121
+ /**
122
+ * PATCH /api/v1/guidelines/:guidelineId/attachments/:attachmentId — Update attachment metadata (description, usage, type, language, sectionHeader).
123
+ */
124
+ updateAttachment: async (guidelineId, attachmentId, options) => {
125
+ const response = await this.client.patch(`/api/v1/guidelines/${guidelineId}/attachments/${attachmentId}`, options);
126
+ return response.data;
127
+ },
128
+ /**
129
+ * DELETE /api/v1/guidelines/:guidelineId/attachments/:attachmentId — Delete an attachment.
130
+ */
131
+ deleteAttachment: async (guidelineId, attachmentId) => {
132
+ const response = await this.client.delete(`/api/v1/guidelines/${guidelineId}/attachments/${attachmentId}`);
133
+ return response.data;
134
+ },
135
+ // TODO: The following attachment methods require multipart/form-data upload support,
136
+ // which the SDK HTTP client does not currently implement. Add postFormData() to the
137
+ // Axios instance wrapper and then implement these methods.
138
+ /**
139
+ * POST /api/v1/guidelines/:guidelineId/attachments — Upload a new attachment.
140
+ * @todo Requires multipart/form-data support (postFormData). Not yet implemented.
141
+ */
142
+ uploadAttachment: async (_guidelineId, _options) => {
143
+ throw new Error('uploadAttachment requires multipart/form-data support, which is not yet implemented in the SDK HTTP layer. Add postFormData() to the client and reimplement this method.');
144
+ },
145
+ /**
146
+ * PUT /api/v1/guidelines/:guidelineId/attachments/:attachmentId/content — Replace attachment file content.
147
+ * @todo Requires multipart/form-data support (postFormData). Not yet implemented.
148
+ */
149
+ replaceAttachmentContent: async (_guidelineId, _attachmentId, _file) => {
150
+ throw new Error('replaceAttachmentContent requires multipart/form-data support, which is not yet implemented in the SDK HTTP layer. Add postFormData() to the client and reimplement this method.');
151
+ },
152
+ /**
153
+ * POST /api/v1/guidelines/:guidelineId/attachments/batch — Upload multiple attachments in one request.
154
+ * @todo Requires multipart/form-data support (postFormData). Not yet implemented.
155
+ */
156
+ batchUploadAttachments: async (_guidelineId, _options) => {
157
+ throw new Error('batchUploadAttachments requires multipart/form-data support, which is not yet implemented in the SDK HTTP layer. Add postFormData() to the client and reimplement this method.');
158
+ },
88
159
  };
89
160
  this.collections = {
90
161
  /**
@@ -249,6 +320,7 @@ class Personize {
249
320
  return this.memorizeBatchFromRecords({
250
321
  source: 'SDK memorize compatibility',
251
322
  enhanced: data.enhanced,
323
+ extractionPrompt: data.extractionPrompt,
252
324
  records: [{
253
325
  content: data.content,
254
326
  email: data.email,
@@ -474,6 +546,97 @@ class Personize {
474
546
  const response = await this.client.post('/api/v1/segment', data);
475
547
  return response.data;
476
548
  },
549
+ /**
550
+ * POST /api/v1/memory/update-keys -- Add keys (standard or custom) to a record.
551
+ * Identify the record by recordId, email, websiteUrl, or any CRM key.
552
+ */
553
+ updateKeys: async (data) => {
554
+ const response = await this.client.post('/api/v1/memory/update-keys', data);
555
+ return response.data;
556
+ },
557
+ /**
558
+ * POST /api/v1/memory/update-keys-batch -- Add keys across multiple records.
559
+ * Max 100 records, 50 keys per record.
560
+ */
561
+ updateKeysBatch: async (data) => {
562
+ const response = await this.client.post('/api/v1/memory/update-keys-batch', data);
563
+ return response.data;
564
+ },
565
+ /**
566
+ * POST /api/v1/memory/list-keys -- List all keys (standard + custom) on a record.
567
+ */
568
+ listKeys: async (data) => {
569
+ const response = await this.client.post('/api/v1/memory/list-keys', data);
570
+ return response.data;
571
+ },
572
+ /**
573
+ * POST /api/v1/memory/delete-keys -- Delete specific key aliases from a record.
574
+ * Blocks deletion if it would leave zero aliases.
575
+ */
576
+ deleteKeys: async (data) => {
577
+ const response = await this.client.post('/api/v1/memory/delete-keys', data);
578
+ return response.data;
579
+ },
580
+ };
581
+ // ============ SmartRecall Unified ============
582
+ this.smartRecallUnified = async (data) => {
583
+ const response = await this.client.post('/api/v1/smart-recall-unified', data);
584
+ return response.data;
585
+ };
586
+ // ============ External RAG ============
587
+ this.rag = {
588
+ configure: async (data) => {
589
+ const response = await this.client.post('/api/v1/external-rag/config', data);
590
+ return response.data;
591
+ },
592
+ search: async (data) => {
593
+ const response = await this.client.post('/api/v1/external-rag/search', data);
594
+ return response.data;
595
+ },
596
+ test: async () => {
597
+ const response = await this.client.post('/api/v1/external-rag/test', {});
598
+ return response.data;
599
+ },
600
+ /** Our LanceDB RAG: ingest documents into a project */
601
+ ingest: async (data) => {
602
+ const response = await this.client.post('/api/v1/rag/ingest', data);
603
+ return response.data;
604
+ },
605
+ /** Our LanceDB RAG: search a project */
606
+ searchProject: async (data) => {
607
+ const response = await this.client.post('/api/v1/rag/search', data);
608
+ return response.data;
609
+ },
610
+ /** Our LanceDB RAG: list projects for this org */
611
+ listProjects: async () => {
612
+ const response = await this.client.get('/api/v1/rag/projects');
613
+ return response.data;
614
+ },
615
+ /** Our LanceDB RAG: delete documents from a project */
616
+ deleteDocuments: async (data) => {
617
+ const response = await this.client.post('/api/v1/rag/delete', data);
618
+ return response.data;
619
+ },
620
+ /** Our LanceDB RAG: delete an entire project */
621
+ deleteProject: async (projectId) => {
622
+ const response = await this.client.post('/api/v1/rag/delete-project', { projectId });
623
+ return response.data;
624
+ },
625
+ };
626
+ // ============ Multimodal ============
627
+ this.multimodal = {
628
+ memorize: async (data) => {
629
+ const response = await this.client.post('/api/v1/multimodal/memorize', data);
630
+ return response.data;
631
+ },
632
+ search: async (data) => {
633
+ const response = await this.client.post('/api/v1/multimodal/search', data);
634
+ return response.data;
635
+ },
636
+ status: async () => {
637
+ const response = await this.client.get('/api/v1/multimodal/status');
638
+ return response.data;
639
+ },
477
640
  };
478
641
  this.evaluate = {
479
642
  /**
@@ -767,6 +930,8 @@ class Personize {
767
930
  }),
768
931
  customKeyName: data.customKeyName,
769
932
  customKeyValue: data.customKeyValue,
933
+ name: data.name,
934
+ parentIdentifier: data.parentIdentifier,
770
935
  filters: data.filters,
771
936
  collectionNames: data.collectionNames || (data.collectionName ? [data.collectionName] : undefined),
772
937
  };
@@ -895,42 +1060,71 @@ class Personize {
895
1060
  isBatchRecordProperty(value) {
896
1061
  return typeof value === 'object' && value !== null && 'value' in value;
897
1062
  }
1063
+ hasRecordIdentity(record) {
1064
+ return Boolean(record.email
1065
+ || record.website_url || record.websiteUrl
1066
+ || record.record_id || record.recordId
1067
+ || record.customKeyValue);
1068
+ }
1069
+ buildContentValueWithMetadata(record) {
1070
+ const content = String(record.content);
1071
+ const metaParts = [];
1072
+ if (record.speaker)
1073
+ metaParts.push(`Speaker: ${record.speaker}`);
1074
+ if (record.timestamp)
1075
+ metaParts.push(`Date: ${record.timestamp}`);
1076
+ if (!metaParts.length)
1077
+ return content;
1078
+ return `[${metaParts.join(' | ')}] ${content}`;
1079
+ }
898
1080
  async memorizeBatchFromRecords(data) {
899
1081
  const records = data.records || [];
900
1082
  if (!records.length) {
901
1083
  return { success: true, data: { memorized: 0 } };
902
1084
  }
903
- const contentRecords = records.filter((record) => record.content);
904
- for (const record of contentRecords) {
1085
+ const batchRecords = [];
1086
+ const fallbackRecords = [];
1087
+ for (const record of records) {
1088
+ const hasContent = Boolean(record.content && String(record.content).trim());
1089
+ const hasProperties = Boolean(record.properties && Object.keys(record.properties).length > 0);
1090
+ if (!hasContent && !hasProperties)
1091
+ continue;
1092
+ if (this.hasRecordIdentity(record)) {
1093
+ batchRecords.push(record);
1094
+ }
1095
+ else if (hasContent) {
1096
+ fallbackRecords.push(record);
1097
+ }
1098
+ }
1099
+ const fallbackPromises = fallbackRecords.map(async (record) => {
905
1100
  const normalizedMemorize = await this.normalizeMemorizeOptions({
906
1101
  content: String(record.content),
907
- email: record.email,
908
- website_url: record.website_url || record.websiteUrl,
909
- record_id: record.record_id || record.recordId,
910
1102
  type: record.type,
911
- customKeyName: record.customKeyName,
912
- customKeyValue: record.customKeyValue,
913
1103
  tags: record.tags,
914
1104
  enhanced: record.enhanced ?? data.enhanced,
1105
+ extractionPrompt: data.extractionPrompt,
915
1106
  timestamp: record.timestamp,
916
1107
  speaker: record.speaker,
917
1108
  collectionNames: record.collectionName ? [record.collectionName] : undefined,
918
1109
  collectionIds: record.collectionId ? [record.collectionId] : undefined,
919
1110
  });
920
- await this.memory.memorize(normalizedMemorize);
921
- }
922
- const structuredRecords = records.filter((record) => record.properties && Object.keys(record.properties).length > 0);
923
- if (!structuredRecords.length) {
924
- return { success: true, data: { memorized: contentRecords.length } };
1111
+ return this.memory.memorize(normalizedMemorize);
1112
+ });
1113
+ if (!batchRecords.length) {
1114
+ if (fallbackPromises.length) {
1115
+ await Promise.all(fallbackPromises);
1116
+ }
1117
+ return { success: true, data: { memorized: fallbackRecords.length } };
925
1118
  }
926
- const first = structuredRecords[0];
1119
+ const first = batchRecords[0];
927
1120
  const entityType = first.type || this.inferEntityTypeFromKeys({
928
1121
  email: first.email,
929
1122
  website_url: first.website_url,
930
1123
  websiteUrl: first.websiteUrl,
931
1124
  }) || 'Record';
932
1125
  const mappingProperties = {};
933
- const rows = structuredRecords.map((record) => {
1126
+ const rows = [];
1127
+ for (const record of batchRecords) {
934
1128
  const row = {};
935
1129
  if (record.email)
936
1130
  row.email = record.email;
@@ -940,6 +1134,17 @@ class Personize {
940
1134
  row.record_id = record.record_id || record.recordId;
941
1135
  if (record.customKeyValue)
942
1136
  row.custom_key = record.customKeyValue;
1137
+ if (record.content && String(record.content).trim()) {
1138
+ row._content = this.buildContentValueWithMetadata(record);
1139
+ if (!mappingProperties._content) {
1140
+ mappingProperties._content = {
1141
+ sourceField: '_content',
1142
+ collectionId: '',
1143
+ collectionName: '',
1144
+ extractMemories: true,
1145
+ };
1146
+ }
1147
+ }
943
1148
  for (const [propertyName, rawProperty] of Object.entries(record.properties || {})) {
944
1149
  const property = this.isBatchRecordProperty(rawProperty)
945
1150
  ? rawProperty
@@ -954,11 +1159,11 @@ class Personize {
954
1159
  };
955
1160
  }
956
1161
  }
957
- return row;
958
- });
959
- const unresolvedNames = Array.from(new Set(Object.values(mappingProperties)
960
- .filter((property) => !property.collectionId && property.collectionName)
961
- .map((property) => property.collectionName)));
1162
+ rows.push(row);
1163
+ }
1164
+ const unresolvedNames = Array.from(new Set(Object.entries(mappingProperties)
1165
+ .filter(([name, property]) => name !== '_content' && !property.collectionId && property.collectionName)
1166
+ .map(([, property]) => property.collectionName)));
962
1167
  const resolvedMap = new Map();
963
1168
  if (unresolvedNames.length) {
964
1169
  const collections = await this.listAllCollections();
@@ -968,7 +1173,9 @@ class Personize {
968
1173
  }
969
1174
  }
970
1175
  }
971
- for (const property of Object.values(mappingProperties)) {
1176
+ for (const [name, property] of Object.entries(mappingProperties)) {
1177
+ if (name === '_content')
1178
+ continue;
972
1179
  if (!property.collectionId && property.collectionName) {
973
1180
  property.collectionId = resolvedMap.get(property.collectionName.toLowerCase()) || '';
974
1181
  }
@@ -977,15 +1184,17 @@ class Personize {
977
1184
  }
978
1185
  }
979
1186
  const { organizationId, userId } = await this.resolveIdentity();
980
- const response = await this.client.post('/api/v1/batch-memorize', {
1187
+ const batchPromise = this.client.post('/api/v1/batch-memorize', {
981
1188
  source: data.source || 'SDK records shorthand',
982
1189
  tier: data.tier,
1190
+ extractionPrompt: data.extractionPrompt,
983
1191
  dryRun: data.dryRun,
984
1192
  chunkSize: data.chunkSize,
985
1193
  mapping: {
986
1194
  entityType,
987
1195
  email: rows.some((row) => row.email) ? 'email' : undefined,
988
1196
  website: rows.some((row) => row.website) ? 'website' : undefined,
1197
+ recordId: rows.some((row) => row.record_id) ? 'record_id' : undefined,
989
1198
  customKeyName: first.customKeyName,
990
1199
  customKey: rows.some((row) => row.custom_key) ? 'custom_key' : undefined,
991
1200
  properties: mappingProperties,
@@ -994,7 +1203,11 @@ class Personize {
994
1203
  orgId: organizationId,
995
1204
  userId,
996
1205
  });
997
- return response.data;
1206
+ const [batchResponse] = await Promise.all([
1207
+ batchPromise,
1208
+ ...fallbackPromises,
1209
+ ]);
1210
+ return batchResponse.data;
998
1211
  }
999
1212
  /**
1000
1213
  * GET /api/v1/test — Verify API key is valid. Returns request metadata and resolved identity.
package/dist/types.d.ts CHANGED
@@ -112,6 +112,103 @@ export interface GuidelineUpdatePayload {
112
112
  }
113
113
  /** @deprecated Use GuidelineUpdatePayload instead. */
114
114
  export type VariableUpdatePayload = GuidelineUpdatePayload;
115
+ export type GovernanceAttachmentType = 'script' | 'template' | 'reference' | 'config' | 'data' | 'schema' | 'prompt' | 'image';
116
+ export interface AttachmentAuditFinding {
117
+ severity: 'info' | 'warning' | 'error';
118
+ message: string;
119
+ line?: number;
120
+ }
121
+ export interface AttachmentAudit {
122
+ status: 'pending' | 'clean' | 'warnings' | 'errors';
123
+ findings: AttachmentAuditFinding[];
124
+ auditedAt: string;
125
+ model: string;
126
+ }
127
+ export interface GovernanceAttachment {
128
+ id: string;
129
+ name: string;
130
+ type: GovernanceAttachmentType;
131
+ description: string;
132
+ usage: string;
133
+ language?: string;
134
+ mimeType: string;
135
+ sizeBytes: number;
136
+ sha256: string;
137
+ preview?: string;
138
+ sectionHeader?: string;
139
+ uploadedBy: string;
140
+ fetchCount: number;
141
+ lastFetchedAt?: string;
142
+ audit?: AttachmentAudit;
143
+ createdAt: string;
144
+ updatedAt: string;
145
+ }
146
+ export interface AttachmentUploadOptions {
147
+ file: Buffer | ReadableStream;
148
+ name?: string;
149
+ type: GovernanceAttachmentType;
150
+ description: string;
151
+ usage: string;
152
+ language?: string;
153
+ sectionHeader?: string;
154
+ }
155
+ export interface AttachmentUpdateOptions {
156
+ description?: string;
157
+ usage?: string;
158
+ type?: GovernanceAttachmentType;
159
+ language?: string;
160
+ sectionHeader?: string;
161
+ }
162
+ export interface BatchAttachmentUploadOptions {
163
+ files: Array<{
164
+ file: Buffer | ReadableStream;
165
+ metadata: AttachmentUploadOptions;
166
+ }>;
167
+ }
168
+ export interface SmartUpdateOptions {
169
+ /** Whether to operate on guidelines or collections */
170
+ type: 'guideline' | 'collection';
171
+ /** What to do with the material */
172
+ instruction: string;
173
+ /** Raw content: text, notes, JSON, meeting notes, etc. (max 50K chars) */
174
+ material: string;
175
+ /** Specific guideline/collection IDs to target. Falls back to semantic discovery. */
176
+ targetIds?: string[];
177
+ target_ids?: string[];
178
+ /** Execution strategy */
179
+ strategy?: 'suggest' | 'safe' | 'force';
180
+ }
181
+ export interface SmartUpdateItem {
182
+ itemId: string;
183
+ action: 'create' | 'update_section' | 'append_section' | 'add_property' | 'update_property';
184
+ target: string;
185
+ targetId?: string;
186
+ sectionHeader?: string;
187
+ reasoning: string;
188
+ detail: string;
189
+ preview: {
190
+ before?: string;
191
+ after: string;
192
+ };
193
+ hasConflict: boolean;
194
+ conflictDescription?: string;
195
+ applied: boolean;
196
+ createMetadata?: {
197
+ name?: string;
198
+ description?: string;
199
+ tags?: string[];
200
+ collectionName?: string;
201
+ entityType?: string;
202
+ definition?: string;
203
+ };
204
+ }
205
+ export interface SmartUpdateResponse {
206
+ status: 'planned' | 'applied' | 'partial';
207
+ creditsUsed: number;
208
+ items: SmartUpdateItem[];
209
+ summary: string;
210
+ warnings?: string[];
211
+ }
115
212
  export interface GuidelineCreatePayload {
116
213
  name: string;
117
214
  value?: string;
@@ -179,10 +276,84 @@ export interface CollectionsResponse extends Array<CollectionListItem> {
179
276
  /** Cursor for the next page. Undefined when on the last page. */
180
277
  nextToken?: string;
181
278
  }
279
+ /**
280
+ * Property definition for a collection.
281
+ *
282
+ * Each property defines a field that the AI extraction pipeline will populate
283
+ * when content is memorized against this collection.
284
+ *
285
+ * @example Single replaceable property
286
+ * ```ts
287
+ * { propertyName: 'Job Title', type: 'text', description: 'Current role', update: true }
288
+ * ```
289
+ *
290
+ * @example Append-only array property
291
+ * ```ts
292
+ * { propertyName: 'Meeting Notes', type: 'array', description: 'Chronological meeting log', update: false, tags: ['interaction'] }
293
+ * ```
294
+ *
295
+ * @example Options property with predefined values
296
+ * ```ts
297
+ * { propertyName: 'Lifecycle Stage', type: 'options', options: 'Lead, MQL, SQL, Customer', update: true }
298
+ * ```
299
+ */
300
+ export interface CollectionPropertyDefinition {
301
+ /** Display name (e.g., 'Job Title', 'Deal Value'). Required for create. */
302
+ propertyName: string;
303
+ /** Internal unique ID. Auto-generated if omitted. Immutable after creation. */
304
+ propertyId?: string;
305
+ /**
306
+ * Machine name for filtering (e.g., 'job_title'). Auto-generated from propertyName if omitted.
307
+ * Immutable after creation -- used to identify which property to update in PATCH calls.
308
+ */
309
+ systemName?: string;
310
+ /**
311
+ * Data type. Aliases accepted: `'string'` -> `'text'`, `'bool'` -> `'boolean'`,
312
+ * `'int'`/`'float'` -> `'number'`, `'list'` -> `'array'`.
313
+ * @default 'text'
314
+ */
315
+ type?: 'text' | 'date' | 'options' | 'number' | 'boolean' | 'array';
316
+ /**
317
+ * Example values or comma-separated options. Most useful for `type: 'options'`.
318
+ * @example 'Lead, MQL, SQL, Customer, Churned'
319
+ */
320
+ options?: string | string[];
321
+ /**
322
+ * Extraction instructions for AI -- describe what this property captures and
323
+ * give examples of expected values. Better descriptions produce better extraction.
324
+ */
325
+ description?: string;
326
+ /** If true, AI automatically populates this field during extraction. */
327
+ autoSystem?: boolean;
328
+ /**
329
+ * `true` (default) = replaceable via 'set' operation.
330
+ * `false` = append-only, can only 'push' new items.
331
+ * Use `false` for properties that accumulate history (e.g., meeting notes, interaction log).
332
+ * @default true
333
+ */
334
+ update?: boolean;
335
+ /** Compatibility alias. `'append'` maps to `update: false`, `'replace'` to `update: true`. */
336
+ updateSemantics?: 'replace' | 'append';
337
+ /**
338
+ * Tags for property selection boosting during extraction.
339
+ * @example ['identity', 'qualification', 'vip']
340
+ */
341
+ tags?: string[];
342
+ /**
343
+ * Property status. Set to `'Deleted'` to soft-remove a property from
344
+ * extraction without deleting stored values.
345
+ * @default 'Active'
346
+ */
347
+ status?: 'Active' | 'Deleted';
348
+ }
182
349
  export interface CollectionCreatePayload {
350
+ /** Display name (e.g., 'Contact Properties', 'Deal Tracker'). */
183
351
  collectionName?: string;
352
+ /** Optional custom ID. Auto-generated (UUID) if omitted. */
184
353
  collectionId?: string;
354
+ /** Description or extraction instructions for the whole collection. Helps AI understand the collection's purpose. */
185
355
  definition?: string;
356
+ /** Entity type: 'Contact', 'Company', 'Deal', 'Employee', or any custom type. */
186
357
  entityType?: string;
187
358
  /** Compatibility alias for collectionName. */
188
359
  name?: string;
@@ -196,40 +367,63 @@ export interface CollectionCreatePayload {
196
367
  color?: string;
197
368
  /** Accepted for compatibility; may be used to infer entityType client-side. */
198
369
  primaryKeyField?: string;
199
- properties?: Array<{
200
- propertyName: string;
201
- propertyId?: string;
202
- systemName?: string;
203
- type?: 'text' | 'date' | 'options' | 'number' | 'boolean' | 'array';
204
- options?: string | string[];
205
- description?: string;
206
- autoSystem?: boolean;
207
- update?: boolean;
208
- /** Compatibility alias. `append` maps to `update: false`, `replace` to `update: true`. */
209
- updateSemantics?: 'replace' | 'append';
210
- tags?: string[];
211
- status?: 'Active' | 'Deleted';
212
- }>;
370
+ /**
371
+ * Initial property definitions. Can be added later via `collections.update()`.
372
+ * See {@link CollectionPropertyDefinition} for the full field reference.
373
+ */
374
+ properties?: CollectionPropertyDefinition[];
213
375
  status?: 'Active' | 'Deleted';
214
376
  }
377
+ /**
378
+ * Payload for `collections.update()`. **Incremental**: send only the properties
379
+ * you want to add or change -- existing properties not included are preserved.
380
+ *
381
+ * @example Add a single property to an existing collection
382
+ * ```ts
383
+ * await client.collections.update(collectionId, {
384
+ * properties: [
385
+ * { propertyName: 'Location', type: 'text', description: 'City or region', update: true },
386
+ * ],
387
+ * historyNote: 'Added Location property',
388
+ * });
389
+ * ```
390
+ *
391
+ * @example Add multiple properties at once
392
+ * ```ts
393
+ * await client.collections.update(collectionId, {
394
+ * properties: [
395
+ * { propertyName: 'Budget Range', type: 'options', options: '<50K, 50K-200K, 200K-1M, >1M', update: true },
396
+ * { propertyName: 'Decision Timeline', type: 'text', description: 'When they plan to buy', update: true },
397
+ * { propertyName: 'Objections Log', type: 'array', description: 'Sales objections', update: false },
398
+ * ],
399
+ * historyNote: 'Added qualification properties for lead scoring',
400
+ * });
401
+ * ```
402
+ *
403
+ * @example Soft-delete a property
404
+ * ```ts
405
+ * await client.collections.update(collectionId, {
406
+ * properties: [
407
+ * { propertyName: 'Old Field', systemName: 'old_field', status: 'Deleted' },
408
+ * ],
409
+ * historyNote: 'Retired Old Field property',
410
+ * });
411
+ * ```
412
+ */
215
413
  export interface CollectionUpdatePayload {
414
+ /** Updated display name (only if renaming). */
216
415
  collectionName?: string;
416
+ /** Updated description or extraction instructions. */
217
417
  definition?: string;
218
418
  entityType?: string;
219
- properties?: Array<{
220
- propertyId?: string;
221
- propertyName?: string;
222
- systemName?: string;
223
- type?: 'text' | 'date' | 'options' | 'number' | 'boolean' | 'array';
224
- options?: string | string[];
225
- description?: string;
226
- autoSystem?: boolean;
227
- update?: boolean;
228
- /** Compatibility alias. `append` maps to `update: false`, `replace` to `update: true`. */
229
- updateSemantics?: 'replace' | 'append';
230
- tags?: string[];
231
- status?: 'Active' | 'Deleted';
232
- }>;
419
+ /**
420
+ * Properties to add or modify. **Incremental** -- send only new or changed
421
+ * properties. Existing properties not listed here are preserved unchanged.
422
+ * See {@link CollectionPropertyDefinition} for the full field reference.
423
+ */
424
+ properties?: CollectionPropertyDefinition[];
425
+ /** Human-readable change note for the audit trail. */
426
+ historyNote?: string;
233
427
  status?: 'Active' | 'Deleted';
234
428
  }
235
429
  export interface CollectionHistoryOptions {
@@ -650,6 +844,8 @@ export interface MemorizeOptions {
650
844
  customKeyName?: string;
651
845
  /** Custom key value — the unique identifier value (e.g. 'S12345', 'https://linkedin.com/in/johndoe'). */
652
846
  customKeyValue?: string;
847
+ /** Optional extraction focus instructions for the LLM (max 500 chars). Guides what the extraction prioritizes. Example: "Focus on pricing tiers and competitive positioning." */
848
+ extractionPrompt?: string;
653
849
  /** Enable enhanced dual extraction (structured + free-form). */
654
850
  enhanced?: boolean;
655
851
  /** Compatibility shorthand for structured property writes. */
@@ -678,6 +874,10 @@ export interface MemorizeOptions {
678
874
  deviceId?: string;
679
875
  /** Content ID for entity scoping. */
680
876
  contentId?: string;
877
+ /** IDv2: Human name for weak identity resolution */
878
+ name?: string;
879
+ /** IDv2: Parent entity's natural key for disambiguation (e.g., company domain) */
880
+ parentIdentifier?: string;
681
881
  }
682
882
  /** @deprecated Use MemorizeOptions instead. */
683
883
  export type MemorizeProOptions = MemorizeOptions;
@@ -724,6 +924,10 @@ export interface SmartRecallOptions {
724
924
  customKeyName?: string;
725
925
  /** Custom key value — the unique identifier value. */
726
926
  customKeyValue?: string;
927
+ /** IDv2: Human name for weak identity resolution */
928
+ name?: string;
929
+ /** IDv2: Parent entity's natural key for disambiguation (e.g., company domain) */
930
+ parentIdentifier?: string;
727
931
  /** Scope results to specific collections by ID. */
728
932
  collectionIds?: string[];
729
933
  /** Scope results to specific collections by name (resolved server-side, case-insensitive). */
@@ -798,6 +1002,10 @@ export interface RecallOptions {
798
1002
  deviceId?: string;
799
1003
  /** Content ID for entity scoping. */
800
1004
  contentId?: string;
1005
+ /** IDv2: Human name for weak identity resolution */
1006
+ name?: string;
1007
+ /** IDv2: Parent entity's natural key for disambiguation (e.g., company domain) */
1008
+ parentIdentifier?: string;
801
1009
  /** Additional filters. */
802
1010
  filters?: Record<string, unknown>;
803
1011
  /** Scope results to specific collections by ID. */
@@ -826,6 +1034,16 @@ export interface RecallResultItem {
826
1034
  name?: string;
827
1035
  properties?: Record<string, PropertyValue>;
828
1036
  metadata?: Record<string, unknown>;
1037
+ /** IDv2: Identity resolution state */
1038
+ resolutionState?: 'resolved' | 'provisional' | 'merged';
1039
+ /** IDv2: How the record was resolved */
1040
+ resolutionSource?: string;
1041
+ /** IDv2: Known aliases for this record */
1042
+ knownAliases?: Array<{
1043
+ kind: string;
1044
+ value: string;
1045
+ strength: 'strong' | 'weak';
1046
+ }>;
829
1047
  [key: string]: unknown;
830
1048
  }
831
1049
  export interface RecallResponse extends Array<RecallResultItem> {
@@ -851,6 +1069,8 @@ export interface BatchMemorizeMapping {
851
1069
  email?: string;
852
1070
  /** Source field name that contains the website URL (e.g. 'company_website_url') */
853
1071
  website?: string;
1072
+ /** Source field name that contains a pre-resolved record ID (e.g. 'record_id') */
1073
+ recordId?: string;
854
1074
  /**
855
1075
  * Custom key name — the identifier name for custom entity types (e.g. 'studentNumber', 'linkedinUrl').
856
1076
  * Use with `customKey` to specify which source field holds the identifier value.
@@ -878,6 +1098,8 @@ export interface BatchMemorizeOptions {
878
1098
  chunkSize?: number;
879
1099
  /** Compatibility flag accepted and ignored when not needed. */
880
1100
  enhanced?: boolean;
1101
+ /** Optional extraction focus instructions applied to all items in the batch (max 500 chars). */
1102
+ extractionPrompt?: string;
881
1103
  /** Compatibility shorthand accepted by the SDK and normalized client-side. */
882
1104
  records?: BatchMemorizeRecord[];
883
1105
  }
@@ -1314,6 +1536,104 @@ export interface CancelDeletionResult {
1314
1536
  };
1315
1537
  warning?: string;
1316
1538
  }
1539
+ /** Lookup fields -- provide any ONE to identify the target record. */
1540
+ export interface KeyLookupFields {
1541
+ recordId?: string;
1542
+ email?: string;
1543
+ websiteUrl?: string;
1544
+ phoneNumber?: string;
1545
+ postalCode?: string;
1546
+ deviceId?: string;
1547
+ contentId?: string;
1548
+ customKeyName?: string;
1549
+ customKeyValue?: string;
1550
+ }
1551
+ export interface UpdateKeysOptions extends KeyLookupFields {
1552
+ /** Entity type (e.g. 'contact', 'company'). */
1553
+ type: string;
1554
+ /** Keys to register. Both standard CRM keys and custom keys accepted. */
1555
+ keys: Record<string, string>;
1556
+ }
1557
+ export interface UpdateKeysResponse {
1558
+ /** Resolved record ID (useful when looked up by CRM key). */
1559
+ recordId: string;
1560
+ /** Set if the original record was merged into this one. */
1561
+ redirectedFrom?: string;
1562
+ /** Number of keys successfully registered. */
1563
+ registered: number;
1564
+ /** Keys that conflicted with existing aliases on different records. */
1565
+ conflicts: Array<{
1566
+ keyName: string;
1567
+ keyValue: string;
1568
+ existingRecordId: string;
1569
+ }>;
1570
+ /** Keys that were rejected (e.g. empty values, weak alias kinds). */
1571
+ rejected?: Array<{
1572
+ keyName: string;
1573
+ reason: string;
1574
+ }>;
1575
+ }
1576
+ export interface UpdateKeysBatchOptions {
1577
+ /** Array of records to register keys for. Max 100. */
1578
+ records: Array<KeyLookupFields & {
1579
+ /** Entity type. */
1580
+ type: string;
1581
+ /** Keys to register. Max 50 per record. */
1582
+ keys: Record<string, string>;
1583
+ }>;
1584
+ }
1585
+ export interface UpdateKeysBatchResponse {
1586
+ /** Per-record registration results. */
1587
+ results: Array<{
1588
+ recordId: string;
1589
+ registered: number;
1590
+ conflicts: Array<{
1591
+ keyName: string;
1592
+ keyValue: string;
1593
+ existingRecordId: string;
1594
+ }>;
1595
+ }>;
1596
+ /** Records that were not found (echoes back lookup fields). */
1597
+ notFound: Array<Record<string, string>>;
1598
+ }
1599
+ export interface ListKeysOptions extends KeyLookupFields {
1600
+ /** Entity type. */
1601
+ type: string;
1602
+ }
1603
+ export interface KeyEntry {
1604
+ kind: string;
1605
+ value: string;
1606
+ standard: boolean;
1607
+ createdAt: string;
1608
+ lastSeenAt: string;
1609
+ }
1610
+ export interface ListKeysResponse {
1611
+ recordId: string;
1612
+ redirectedFrom?: string;
1613
+ keys: KeyEntry[];
1614
+ }
1615
+ export interface DeleteKeysOptions extends KeyLookupFields {
1616
+ /** Entity type. */
1617
+ type: string;
1618
+ /** Keys to delete. */
1619
+ keys: Array<{
1620
+ keyName: string;
1621
+ keyValue: string;
1622
+ }>;
1623
+ }
1624
+ export interface DeleteKeysResponse {
1625
+ recordId: string;
1626
+ /** Number of keys deleted. */
1627
+ deleted: number;
1628
+ /** Number of keys not found. */
1629
+ notFound: number;
1630
+ /** Keys blocked from deletion (e.g. last remaining alias). */
1631
+ blocked?: Array<{
1632
+ keyName: string;
1633
+ keyValue: string;
1634
+ reason: string;
1635
+ }>;
1636
+ }
1317
1637
  /** Comparison operators for deterministic property filters. */
1318
1638
  export type FilterOperator = 'equals' | 'notEquals' | 'contains' | 'gt' | 'lt' | 'gte' | 'lte' | 'exists' | 'isEmpty';
1319
1639
  export interface PropertyFilterCondition {
@@ -1756,3 +2076,184 @@ export interface SegmentResponse {
1756
2076
  credits: number;
1757
2077
  };
1758
2078
  }
2079
+ /** SmartRecall Unified: 1 endpoint replaces 10 for LLMs/agents. Natural language in, structured intelligence out. */
2080
+ export interface SmartRecallUnifiedOptions {
2081
+ /** Natural language query describing what you need from memory. Be specific about what, who, how many. */
2082
+ message: string;
2083
+ /** Scope to specific records by identifier. Omit for org-wide queries. */
2084
+ identifiers?: {
2085
+ emails?: string[];
2086
+ websites?: string[];
2087
+ recordIds?: string[];
2088
+ type?: string;
2089
+ phoneNumbers?: string[];
2090
+ postalCodes?: string[];
2091
+ deviceIds?: string[];
2092
+ contentIds?: string[];
2093
+ customKeyName?: string;
2094
+ customKeyValue?: string;
2095
+ /** IDv2: person or entity name for identity resolution without email. */
2096
+ name?: string;
2097
+ /** IDv2: parent domain or company (e.g., "acme.com") for name disambiguation. */
2098
+ parentIdentifier?: string;
2099
+ };
2100
+ /** Control response depth. Auto-detected from query if omitted. */
2101
+ responseDetail?: 'ids' | 'labels' | 'summary' | 'context' | 'full';
2102
+ /** Max tokens for the response. Default: 4000. */
2103
+ tokenBudget?: number;
2104
+ /** Classification mode. "fast" (~50ms rules), "deep" (~500ms LLM), "auto" (default). */
2105
+ mode?: 'fast' | 'deep' | 'auto';
2106
+ /** Session ID for follow-up queries. Same sessionId links queries so pronouns resolve to previous results. */
2107
+ sessionId?: string;
2108
+ /** Include results from external RAG source (if configured). Default: true. */
2109
+ includeExternalRag?: boolean;
2110
+ /** Include multimodal search results (if enabled). Default: false. */
2111
+ includeMultimodal?: boolean;
2112
+ }
2113
+ export interface SmartRecallUnifiedRecord {
2114
+ recordId: string;
2115
+ type?: string;
2116
+ email?: string;
2117
+ websiteUrl?: string;
2118
+ displayName?: string;
2119
+ label?: string;
2120
+ summary?: Record<string, unknown>;
2121
+ context?: string;
2122
+ memories?: {
2123
+ text: string;
2124
+ topic?: string;
2125
+ score?: number;
2126
+ source?: string;
2127
+ }[];
2128
+ properties?: Record<string, unknown>;
2129
+ highlightedProperties?: Record<string, {
2130
+ value: unknown;
2131
+ relevant: boolean;
2132
+ confidence?: number;
2133
+ }>;
2134
+ score?: number;
2135
+ relevanceTier?: 'direct' | 'partial' | 'might';
2136
+ sources?: string[];
2137
+ resolutionState?: 'resolved' | 'provisional' | 'merged';
2138
+ freshness?: {
2139
+ score: number;
2140
+ memoryCount?: number;
2141
+ };
2142
+ completeness?: {
2143
+ score: number;
2144
+ filledProperties: string[];
2145
+ missingProperties: string[];
2146
+ memoryCount: number;
2147
+ propertyCount: number;
2148
+ };
2149
+ }
2150
+ export interface SmartRecallUnifiedWarning {
2151
+ type: 'potential_duplicate' | 'stale_record' | 'missing_identity' | 'missing_relationship';
2152
+ records: string[];
2153
+ reason: string;
2154
+ suggestedAction?: string;
2155
+ }
2156
+ export interface SmartRecallUnifiedSuggestedAction {
2157
+ action: 'enrich_identity' | 'memorize_update' | 'merge_records' | 'create_relationship' | 'external_rag_lookup';
2158
+ records?: string[];
2159
+ reason: string;
2160
+ }
2161
+ export interface SmartRecallUnifiedResponse {
2162
+ success: boolean;
2163
+ answer?: string;
2164
+ plan: {
2165
+ classifiedAs: string[];
2166
+ steps: string[];
2167
+ mode: 'fast' | 'deep';
2168
+ confidence: number;
2169
+ };
2170
+ records: SmartRecallUnifiedRecord[];
2171
+ warnings?: SmartRecallUnifiedWarning[];
2172
+ suggestedActions?: SmartRecallUnifiedSuggestedAction[];
2173
+ meta: {
2174
+ totalMatched: number;
2175
+ returned: number;
2176
+ enrichmentDepth: string;
2177
+ tokensUsed: number;
2178
+ creditsCharged: number;
2179
+ latencyMs: number;
2180
+ sources: string[];
2181
+ sessionId?: string;
2182
+ identityResolution?: {
2183
+ resolverUsed: boolean;
2184
+ provisionalCount: number;
2185
+ mergedCount: number;
2186
+ resolvedCount: number;
2187
+ };
2188
+ };
2189
+ }
2190
+ export interface ExternalRAGConfigOptions {
2191
+ url: string;
2192
+ apiKey: string;
2193
+ timeout?: number;
2194
+ maxResults?: number;
2195
+ }
2196
+ export interface ExternalRAGSearchOptions {
2197
+ query: string;
2198
+ limit?: number;
2199
+ context?: {
2200
+ recordId?: string;
2201
+ type?: string;
2202
+ };
2203
+ }
2204
+ export interface ExternalRAGSearchResult {
2205
+ text: string;
2206
+ score: number;
2207
+ source: string;
2208
+ url?: string;
2209
+ metadata?: Record<string, unknown>;
2210
+ }
2211
+ export interface MultimodalMemorizeOptions {
2212
+ recordId: string;
2213
+ type: string;
2214
+ attachment: string;
2215
+ mimeType: string;
2216
+ content?: string;
2217
+ }
2218
+ export interface MultimodalSearchOptions {
2219
+ image: string;
2220
+ mimeType: string;
2221
+ limit?: number;
2222
+ }
2223
+ export interface MultimodalSearchResult {
2224
+ recordId: string;
2225
+ score: number;
2226
+ text?: string;
2227
+ sourceUrl?: string;
2228
+ mimeType?: string;
2229
+ }
2230
+ export interface RAGIngestOptions {
2231
+ projectId: string;
2232
+ documents: {
2233
+ id?: string;
2234
+ text: string;
2235
+ source?: string;
2236
+ sourceUrl?: string;
2237
+ title?: string;
2238
+ metadata?: Record<string, unknown>;
2239
+ }[];
2240
+ }
2241
+ export interface RAGSearchOptions {
2242
+ projectId: string;
2243
+ query: string;
2244
+ limit?: number;
2245
+ minScore?: number;
2246
+ }
2247
+ export interface RAGSearchResult {
2248
+ id: string;
2249
+ text: string;
2250
+ score: number;
2251
+ source: string;
2252
+ sourceUrl?: string;
2253
+ title?: string;
2254
+ metadata?: Record<string, unknown>;
2255
+ }
2256
+ export interface RAGDeleteOptions {
2257
+ projectId: string;
2258
+ documentIds: string[];
2259
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@personize/sdk",
3
- "version": "0.7.2",
3
+ "version": "0.7.4",
4
4
  "description": "Official Personize SDK",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -44,4 +44,4 @@
44
44
  "dependencies": {
45
45
  "axios": "^1.6.0"
46
46
  }
47
- }
47
+ }