lumiverse-spindle-types 0.5.0 → 0.5.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lumiverse-spindle-types",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "types": "./src/index.ts",
5
5
  "keywords": [
6
6
  "lumiverse",
package/src/api.ts CHANGED
@@ -1,5 +1,14 @@
1
1
  import type { SpindleManifest } from "./manifest";
2
2
  import type { CouncilMemberContext } from "./council";
3
+ import type {
4
+ ChatLinkAttachDTO,
5
+ CortexQueryDTO,
6
+ MemoryCortexConfigDTO,
7
+ MemoryEntityStatusUpdateDTO,
8
+ MemoryEntityUpsertDTO,
9
+ MemoryRelationUpsertDTO,
10
+ VaultCreateDTO,
11
+ } from "./memories";
3
12
 
4
13
  // ─── DTO types for messages ──────────────────────────────────────────────
5
14
 
@@ -2281,6 +2290,50 @@ export type WorkerToHost =
2281
2290
  | { type: "generate_dry_run"; requestId: string; input: DryRunRequestDTO; userId?: string }
2282
2291
  // ─── Chat Memories (gated: "chats") ───────────────────────────────
2283
2292
  | { type: "chats_get_memories"; requestId: string; chatId: string; topK?: number; userId?: string }
2293
+ // ─── Memory Cortex & Long-Term Chat Memory (gated: "memories") ────
2294
+ | { type: "memories_config_get"; requestId: string; userId?: string }
2295
+ | { type: "memories_config_put"; requestId: string; patch: Partial<MemoryCortexConfigDTO>; userId?: string }
2296
+ | { type: "memories_query_cortex"; requestId: string; query: CortexQueryDTO }
2297
+ | { type: "memories_query_linked"; requestId: string; chatId: string; queryText?: string; userId?: string }
2298
+ | { type: "memories_get_cached"; requestId: string; chatId: string }
2299
+ | { type: "memories_get_cached_linked"; requestId: string; chatId: string }
2300
+ | { type: "memories_invalidate_cache"; requestId: string; chatId: string }
2301
+ | { type: "memories_invalidate_linked_cache"; requestId: string; chatId: string }
2302
+ | { type: "memories_entities_list"; requestId: string; chatId: string; activeOnly?: boolean; limit?: number; userId?: string }
2303
+ | { type: "memories_entities_get"; requestId: string; entityId: string; userId?: string }
2304
+ | { type: "memories_entities_find_by_name"; requestId: string; chatId: string; name: string; userId?: string }
2305
+ | { type: "memories_entities_upsert"; requestId: string; chatId: string; entity: MemoryEntityUpsertDTO; chunkId?: string | null; createdAt?: number; userId?: string }
2306
+ | { type: "memories_entities_update_status"; requestId: string; entityId: string; patch: MemoryEntityStatusUpdateDTO; userId?: string }
2307
+ | { type: "memories_entities_add_facts"; requestId: string; entityId: string; facts: string[]; userId?: string }
2308
+ | { type: "memories_entities_get_facts"; requestId: string; entityId: string; userId?: string }
2309
+ | { type: "memories_entities_update_emotional_valence"; requestId: string; entityId: string; valence: Record<string, number>; userId?: string }
2310
+ | { type: "memories_relations_list"; requestId: string; chatId: string; userId?: string }
2311
+ | { type: "memories_relations_list_all"; requestId: string; chatId: string; userId?: string }
2312
+ | { type: "memories_relations_for_entity"; requestId: string; chatId: string; entityId: string; userId?: string }
2313
+ | { type: "memories_relations_for_entities"; requestId: string; chatId: string; entityIds: string[]; limit?: number; userId?: string }
2314
+ | { type: "memories_relations_upsert"; requestId: string; chatId: string; relation: MemoryRelationUpsertDTO; chunkId?: string | null; userId?: string }
2315
+ | { type: "memories_consolidations_list"; requestId: string; chatId: string; tier?: number; userId?: string }
2316
+ | { type: "memories_consolidations_latest_arc"; requestId: string; chatId: string; userId?: string }
2317
+ | { type: "memories_consolidations_run"; requestId: string; chatId: string; userId?: string }
2318
+ | { type: "memories_salience_get"; requestId: string; chatId: string; limit?: number; offset?: number; userId?: string }
2319
+ | { type: "memories_vaults_list"; requestId: string; userId?: string }
2320
+ | { type: "memories_vaults_get"; requestId: string; vaultId: string; userId?: string }
2321
+ | { type: "memories_vaults_get_chunks"; requestId: string; vaultId: string; userId?: string }
2322
+ | { type: "memories_vaults_create"; requestId: string; input: VaultCreateDTO; userId?: string }
2323
+ | { type: "memories_vaults_rename"; requestId: string; vaultId: string; name: string; userId?: string }
2324
+ | { type: "memories_vaults_delete"; requestId: string; vaultId: string; userId?: string }
2325
+ | { type: "memories_vaults_reindex"; requestId: string; vaultId: string; userId?: string }
2326
+ | { type: "memories_links_list"; requestId: string; chatId: string; userId?: string }
2327
+ | { type: "memories_links_attach"; requestId: string; input: ChatLinkAttachDTO; userId?: string }
2328
+ | { type: "memories_links_remove"; requestId: string; chatId: string; linkId: string; userId?: string }
2329
+ | { type: "memories_links_toggle"; requestId: string; chatId: string; linkId: string; enabled: boolean; userId?: string }
2330
+ | { type: "memories_chat_chunks_list"; requestId: string; chatId: string; userId?: string }
2331
+ | { type: "memories_chat_memory_get"; requestId: string; chatId: string; topK?: number; userId?: string }
2332
+ | { type: "memories_chat_memory_warm"; requestId: string; chatId: string; force?: boolean; userId?: string }
2333
+ | { type: "memories_chat_memory_invalidate"; requestId: string; chatId: string; userId?: string }
2334
+ | { type: "memories_stats_usage"; requestId: string; chatId: string; userId?: string }
2335
+ | { type: "memories_stats_ingestion_status"; requestId: string; chatId: string; userId?: string }
2336
+ | { type: "memories_stats_ingestion_telemetry"; requestId: string; chatId: string; userId?: string }
2284
2337
  // ─── Toast (free tier) ───────────────────────────────────────────────
2285
2338
  | { type: "toast_show"; toastType: "success" | "warning" | "error" | "info"; message: string; title?: string; duration?: number; userId?: string }
2286
2339
  // ─── Push Notifications (gated: "push_notification") ────────────────
package/src/index.ts CHANGED
@@ -210,6 +210,58 @@ export type {
210
210
 
211
211
  export type { ExtensionInfo } from "./extension-info";
212
212
 
213
+ export type {
214
+ EntityTypeDTO,
215
+ EntityStatusDTO,
216
+ MentionRoleDTO,
217
+ RelationTypeDTO,
218
+ RelationStatusDTO,
219
+ EmotionalTagDTO,
220
+ NarrativeFlagDTO,
221
+ ContradictionFlagDTO,
222
+ FactExtractionStatusDTO,
223
+ EntityConfidenceDTO,
224
+ SalienceSourceDTO,
225
+ ChatLinkTypeDTO,
226
+ SalienceBreakdownDTO,
227
+ MemoryEntityDTO,
228
+ MemoryEntityUpsertDTO,
229
+ MemoryEntityStatusUpdateDTO,
230
+ MemoryMentionDTO,
231
+ MemoryRelationDTO,
232
+ MemoryRelationUpsertDTO,
233
+ StatusChangeDTO,
234
+ MemorySalienceDTO,
235
+ MemoryConsolidationDTO,
236
+ CortexQueryDTO,
237
+ CortexMemoryComponentsDTO,
238
+ CortexMemoryDTO,
239
+ EntitySnapshotRelationshipDTO,
240
+ EntitySnapshotDTO,
241
+ RelationEdgeDTO,
242
+ CortexStatsDTO,
243
+ CortexResultDTO,
244
+ VaultDTO,
245
+ VaultChunkDTO,
246
+ VaultEntityDTO,
247
+ VaultRelationDTO,
248
+ VaultCreateDTO,
249
+ VaultWithContentsDTO,
250
+ VaultReindexResultDTO,
251
+ ChatLinkDTO,
252
+ ChatLinkAttachDTO,
253
+ VaultCortexDataDTO,
254
+ InterlinkCortexDataDTO,
255
+ LinkedCortexResultDTO,
256
+ MemoryCortexConfigDTO,
257
+ CortexUsageStatsDTO,
258
+ CortexIngestionTimingsDTO,
259
+ CortexIngestionStatusDTO,
260
+ CortexIngestionTelemetryDTO,
261
+ ChatChunkDTO,
262
+ ChatMemoryWarmupResultDTO,
263
+ } from "./memories";
264
+
213
265
  export type {
214
266
  SpindleAPI,
215
267
  FrontendProcessHandle,
@@ -0,0 +1,607 @@
1
+ /**
2
+ * Memory Cortex & Long-Term Chat Memory DTOs.
3
+ *
4
+ * Surfaces the Lumiverse hybrid memory architecture to extensions via the
5
+ * `memories` permission. Covers:
6
+ *
7
+ * - Memory Cortex
8
+ * • config (entity tracking, salience scoring, retrieval tuning)
9
+ * • retrieval (cortex query, linked-cortex query, vault query)
10
+ * • entity graph (entities, relations, mentions)
11
+ * • consolidations & salience records
12
+ * • vaults (snapshots of cortex state) and chat links (vault attach /
13
+ * bidirectional interlinks)
14
+ * • ingestion / maintenance telemetry
15
+ *
16
+ * - Long-Term Chat Memory
17
+ * • vectorized chat chunks (list, get, warm)
18
+ * • cached retrieval result for the {{memories}} macro
19
+ *
20
+ * Service-layer shapes use camelCase; SQLite row shapes (snake_case) are not
21
+ * exposed to extensions — DTOs are normalised here.
22
+ */
23
+
24
+ // ─── Enums ─────────────────────────────────────────────────────────────
25
+
26
+ export type EntityTypeDTO =
27
+ | "character"
28
+ | "location"
29
+ | "item"
30
+ | "faction"
31
+ | "concept"
32
+ | "event";
33
+
34
+ export type EntityStatusDTO =
35
+ | "active"
36
+ | "inactive"
37
+ | "deceased"
38
+ | "destroyed"
39
+ | "unknown";
40
+
41
+ export type MentionRoleDTO =
42
+ | "subject"
43
+ | "object"
44
+ | "present"
45
+ | "referenced"
46
+ | "absent";
47
+
48
+ export type RelationTypeDTO =
49
+ | "ally"
50
+ | "enemy"
51
+ | "lover"
52
+ | "parent"
53
+ | "child"
54
+ | "sibling"
55
+ | "mentor"
56
+ | "rival"
57
+ | "owns"
58
+ | "member_of"
59
+ | "located_in"
60
+ | "fears"
61
+ | "serves"
62
+ | "custom";
63
+
64
+ export type RelationStatusDTO = "active" | "broken" | "dormant" | "former";
65
+
66
+ export type EmotionalTagDTO =
67
+ | "grief"
68
+ | "joy"
69
+ | "tension"
70
+ | "dread"
71
+ | "intimacy"
72
+ | "betrayal"
73
+ | "revelation"
74
+ | "resolve"
75
+ | "humor"
76
+ | "melancholy"
77
+ | "awe"
78
+ | "fury";
79
+
80
+ export type NarrativeFlagDTO =
81
+ | "first_meeting"
82
+ | "death"
83
+ | "promise"
84
+ | "confession"
85
+ | "departure"
86
+ | "transformation"
87
+ | "battle"
88
+ | "discovery"
89
+ | "reunion"
90
+ | "loss";
91
+
92
+ export type ContradictionFlagDTO = "none" | "temporal" | "complex" | "suspect";
93
+
94
+ export type FactExtractionStatusDTO = "never" | "attempted_empty" | "ok";
95
+
96
+ export type EntityConfidenceDTO = "confirmed" | "provisional";
97
+
98
+ export type SalienceSourceDTO = "heuristic" | "sidecar";
99
+
100
+ export type ChatLinkTypeDTO = "vault" | "interlink";
101
+
102
+ // ─── Entity Graph ──────────────────────────────────────────────────────
103
+
104
+ export interface SalienceBreakdownDTO {
105
+ mentionComponent: number;
106
+ arcComponent: number;
107
+ graphComponent: number;
108
+ total: number;
109
+ }
110
+
111
+ export interface MemoryEntityDTO {
112
+ id: string;
113
+ chatId: string;
114
+ name: string;
115
+ entityType: EntityTypeDTO;
116
+ aliases: string[];
117
+ description: string;
118
+ firstSeenChunkId: string | null;
119
+ lastSeenChunkId: string | null;
120
+ firstSeenAt: number | null;
121
+ lastSeenAt: number | null;
122
+ mentionCount: number;
123
+ salienceAvg: number;
124
+ status: EntityStatusDTO;
125
+ statusChangedAt: number | null;
126
+ facts: string[];
127
+ emotionalValence: Record<string, number>;
128
+ metadata: Record<string, unknown>;
129
+ createdAt: number;
130
+ updatedAt: number;
131
+ factExtractionStatus: FactExtractionStatusDTO;
132
+ factExtractionLastAttempt: number | null;
133
+ salienceBreakdown: SalienceBreakdownDTO;
134
+ lastMentionTimestamp: number | null;
135
+ recentMentionCount: number;
136
+ confidence: EntityConfidenceDTO;
137
+ userEditedAt: number | null;
138
+ }
139
+
140
+ /**
141
+ * Input shape for upserting an entity. Matches the heuristic / sidecar
142
+ * extraction shape so an extension can replay its own NER results into the
143
+ * graph. `confidence` is the raw [0, 1] extractor confidence; entities below
144
+ * the configured threshold are dropped by the host.
145
+ */
146
+ export interface MemoryEntityUpsertDTO {
147
+ name: string;
148
+ type: EntityTypeDTO;
149
+ aliases?: string[];
150
+ confidence?: number;
151
+ role?: MentionRoleDTO;
152
+ /** Marks the entity as needing corroboration before promotion. */
153
+ provisional?: boolean;
154
+ }
155
+
156
+ export interface MemoryEntityStatusUpdateDTO {
157
+ status: EntityStatusDTO;
158
+ statusChangedAt?: number;
159
+ }
160
+
161
+ export interface MemoryMentionDTO {
162
+ id: string;
163
+ entityId: string;
164
+ chunkId: string;
165
+ chatId: string;
166
+ role: MentionRoleDTO;
167
+ excerpt: string | null;
168
+ sentiment: number;
169
+ createdAt: number;
170
+ }
171
+
172
+ // ─── Relations ─────────────────────────────────────────────────────────
173
+
174
+ export interface MemoryRelationDTO {
175
+ id: string;
176
+ chatId: string;
177
+ sourceEntityId: string;
178
+ targetEntityId: string;
179
+ relationType: RelationTypeDTO;
180
+ relationLabel: string | null;
181
+ strength: number;
182
+ sentiment: number;
183
+ evidenceChunkIds: string[];
184
+ firstEstablishedAt: number | null;
185
+ lastReinforcedAt: number | null;
186
+ status: RelationStatusDTO;
187
+ metadata: Record<string, unknown>;
188
+ createdAt: number;
189
+ updatedAt: number;
190
+ contradictionFlag: ContradictionFlagDTO;
191
+ contradictionPeerId: string | null;
192
+ sentimentRange: [number, number] | null;
193
+ supersededBy: string | null;
194
+ arcIds: string[];
195
+ firstSeenArcId: string | null;
196
+ lastSeenArcId: string | null;
197
+ lastEvidenceTimestamp: number | null;
198
+ decayRate: number;
199
+ edgeSalience: number;
200
+ labelAliases: string[];
201
+ canonicalEdgeId: string | null;
202
+ mergedInto: string | null;
203
+ }
204
+
205
+ /**
206
+ * Input shape for upserting a relation. Uses entity *names* (not ids) so
207
+ * extensions can produce relations symbolically — the host resolves canonical
208
+ * ids server-side. Both endpoints must already exist in the entity graph;
209
+ * the relation is silently dropped otherwise.
210
+ */
211
+ export interface MemoryRelationUpsertDTO {
212
+ source: string;
213
+ target: string;
214
+ type: RelationTypeDTO;
215
+ label: string;
216
+ sentiment: number;
217
+ }
218
+
219
+ // ─── Salience ──────────────────────────────────────────────────────────
220
+
221
+ export interface StatusChangeDTO {
222
+ entity: string;
223
+ change: string;
224
+ detail: string;
225
+ }
226
+
227
+ export interface MemorySalienceDTO {
228
+ chunkId: string;
229
+ chatId: string;
230
+ score: number;
231
+ scoreSource: SalienceSourceDTO;
232
+ emotionalTags: EmotionalTagDTO[];
233
+ statusChanges: StatusChangeDTO[];
234
+ narrativeFlags: NarrativeFlagDTO[];
235
+ hasDialogue: boolean;
236
+ hasAction: boolean;
237
+ hasInternalThought: boolean;
238
+ wordCount: number;
239
+ scoredAt: number;
240
+ scoredBy: string | null;
241
+ }
242
+
243
+ // ─── Consolidations ────────────────────────────────────────────────────
244
+
245
+ export interface MemoryConsolidationDTO {
246
+ id: string;
247
+ chatId: string;
248
+ tier: number;
249
+ title: string | null;
250
+ summary: string;
251
+ sourceChunkIds: string[];
252
+ sourceConsolidationIds: string[];
253
+ entityIds: string[];
254
+ messageRangeStart: number | null;
255
+ messageRangeEnd: number | null;
256
+ timeRangeStart: number | null;
257
+ timeRangeEnd: number | null;
258
+ salienceAvg: number;
259
+ emotionalTags: EmotionalTagDTO[];
260
+ tokenCount: number;
261
+ vectorizedAt: number | null;
262
+ vectorModel: string | null;
263
+ createdAt: number;
264
+ updatedAt: number;
265
+ }
266
+
267
+ // ─── Cortex Retrieval ──────────────────────────────────────────────────
268
+
269
+ /**
270
+ * Input to a Memory Cortex retrieval query.
271
+ *
272
+ * The `userId` field is normally inferred from the calling extension's
273
+ * effective user; pass it explicitly only for operator-scoped extensions.
274
+ */
275
+ export interface CortexQueryDTO {
276
+ chatId: string;
277
+ queryText: string;
278
+ entityFilter?: string[];
279
+ timeRange?: { start?: number; end?: number };
280
+ emotionalContext?: EmotionalTagDTO[];
281
+ generationType?: string;
282
+ topK?: number;
283
+ includeConsolidations?: boolean;
284
+ includeRelationships?: boolean;
285
+ excludeMessageIds?: string[];
286
+ userId?: string;
287
+ }
288
+
289
+ export interface CortexMemoryComponentsDTO {
290
+ semantic: number;
291
+ salience: number;
292
+ recency: number;
293
+ reinforcement: number;
294
+ emotional: number;
295
+ entity: number;
296
+ }
297
+
298
+ export interface CortexMemoryDTO {
299
+ source: "chunk" | "consolidation";
300
+ sourceId: string;
301
+ content: string;
302
+ finalScore: number;
303
+ components: CortexMemoryComponentsDTO;
304
+ emotionalTags: EmotionalTagDTO[];
305
+ entityNames: string[];
306
+ messageRange: [number, number];
307
+ timeRange: [number, number];
308
+ }
309
+
310
+ export interface EntitySnapshotRelationshipDTO {
311
+ targetName: string;
312
+ type: RelationTypeDTO;
313
+ label: string | null;
314
+ strength: number;
315
+ sentiment: number;
316
+ }
317
+
318
+ export interface EntitySnapshotDTO {
319
+ id: string;
320
+ name: string;
321
+ type: EntityTypeDTO;
322
+ status: EntityStatusDTO;
323
+ description: string;
324
+ lastSeenAt: number | null;
325
+ mentionCount: number;
326
+ topFacts: string[];
327
+ emotionalProfile: Record<string, number>;
328
+ relationships: EntitySnapshotRelationshipDTO[];
329
+ }
330
+
331
+ export interface RelationEdgeDTO {
332
+ sourceName: string;
333
+ targetName: string;
334
+ type: RelationTypeDTO;
335
+ label: string | null;
336
+ strength: number;
337
+ sentiment: number;
338
+ }
339
+
340
+ export interface CortexStatsDTO {
341
+ candidatePoolSize: number;
342
+ vectorSearchResults: number;
343
+ entitiesMatched: number;
344
+ scoreFusionApplied: boolean;
345
+ topScore: number;
346
+ retrievalTimeMs: number;
347
+ /** Set when the retrieval hit its internal time budget. */
348
+ timedOut?: boolean;
349
+ /** Set when retrieval bailed out because the caller's AbortSignal fired. */
350
+ aborted?: boolean;
351
+ }
352
+
353
+ export interface CortexResultDTO {
354
+ memories: CortexMemoryDTO[];
355
+ entityContext: EntitySnapshotDTO[];
356
+ activeRelationships: RelationEdgeDTO[];
357
+ arcContext: string | null;
358
+ stats: CortexStatsDTO;
359
+ }
360
+
361
+ // ─── Vaults & Linked Cortex ────────────────────────────────────────────
362
+
363
+ export interface VaultDTO {
364
+ id: string;
365
+ userId: string;
366
+ sourceChatId: string | null;
367
+ sourceChatName: string | null;
368
+ name: string;
369
+ description: string;
370
+ entityCount: number;
371
+ relationCount: number;
372
+ chunkCount: number;
373
+ createdAt: number;
374
+ }
375
+
376
+ export interface VaultChunkDTO {
377
+ id: string;
378
+ vaultId: string;
379
+ sourceChunkId: string;
380
+ content: string;
381
+ salienceScore: number | null;
382
+ emotionalTags: string[];
383
+ entityNames: string[];
384
+ sourceCreatedAt: number;
385
+ copiedAt: number;
386
+ }
387
+
388
+ export interface VaultEntityDTO {
389
+ id: string;
390
+ vaultId: string;
391
+ name: string;
392
+ entityType: EntityTypeDTO;
393
+ aliases: string[];
394
+ description: string;
395
+ status: EntityStatusDTO;
396
+ facts: string[];
397
+ emotionalValence: Record<string, number>;
398
+ salienceAvg: number;
399
+ }
400
+
401
+ export interface VaultRelationDTO {
402
+ id: string;
403
+ vaultId: string;
404
+ sourceEntityName: string;
405
+ targetEntityName: string;
406
+ relationType: RelationTypeDTO;
407
+ relationLabel: string | null;
408
+ strength: number;
409
+ sentiment: number;
410
+ status: RelationStatusDTO;
411
+ }
412
+
413
+ export interface VaultCreateDTO {
414
+ chatId: string;
415
+ name: string;
416
+ description?: string;
417
+ }
418
+
419
+ export interface VaultWithContentsDTO {
420
+ vault: VaultDTO;
421
+ entities: VaultEntityDTO[];
422
+ relations: VaultRelationDTO[];
423
+ }
424
+
425
+ export interface VaultReindexResultDTO {
426
+ mode: string;
427
+ chunkCount: number;
428
+ }
429
+
430
+ export interface ChatLinkDTO {
431
+ id: string;
432
+ userId: string;
433
+ chatId: string;
434
+ linkType: ChatLinkTypeDTO;
435
+ vaultId: string | null;
436
+ vaultName: string | null;
437
+ vaultEntityCount: number | null;
438
+ vaultRelationCount: number | null;
439
+ targetChatId: string | null;
440
+ targetChatName: string | null;
441
+ targetChatExists: boolean;
442
+ label: string;
443
+ enabled: boolean;
444
+ priority: number;
445
+ createdAt: number;
446
+ }
447
+
448
+ export interface ChatLinkAttachDTO {
449
+ chatId: string;
450
+ linkType: ChatLinkTypeDTO;
451
+ vaultId?: string;
452
+ targetChatId?: string;
453
+ label?: string;
454
+ /** Interlinks only. When true, also creates the reverse link on the target chat. */
455
+ bidirectional?: boolean;
456
+ }
457
+
458
+ export interface VaultCortexDataDTO {
459
+ vaultId: string;
460
+ vaultName: string;
461
+ sourceChatId?: string;
462
+ entities: EntitySnapshotDTO[];
463
+ relations: RelationEdgeDTO[];
464
+ /** Retrieved memories from the vault's chunk snapshot (when queryText supplied). */
465
+ memories?: CortexMemoryDTO[];
466
+ arcContext?: string | null;
467
+ }
468
+
469
+ export interface InterlinkCortexDataDTO {
470
+ targetChatId: string;
471
+ targetChatName: string;
472
+ result: CortexResultDTO;
473
+ }
474
+
475
+ export interface LinkedCortexResultDTO {
476
+ vaults: VaultCortexDataDTO[];
477
+ interlinks: InterlinkCortexDataDTO[];
478
+ }
479
+
480
+ // ─── Cortex Config ─────────────────────────────────────────────────────
481
+
482
+ /**
483
+ * Memory Cortex configuration.
484
+ *
485
+ * The host owns the canonical schema (see `MemoryCortexConfig` in the
486
+ * backend). The DTO is intentionally permissive — only the top-level toggles
487
+ * extensions are likely to flip are typed, and the index signature passes
488
+ * advanced fields (retrieval tuning, sidecar configuration, decay curves,
489
+ * consolidation thresholds, entity pruning, etc.) straight through. New
490
+ * fields added by the host are visible immediately to extensions without
491
+ * a coordinated type bump.
492
+ */
493
+ export interface MemoryCortexConfigDTO {
494
+ enabled: boolean;
495
+ entityTracking: boolean;
496
+ entityExtractionMode: string;
497
+ salienceScoring: boolean;
498
+ salienceScoringMode?: string;
499
+ thoughtMarkers?: unknown;
500
+ entityWhitelist?: string[];
501
+ entityExtractionFilters?: unknown;
502
+ retrieval?: Record<string, unknown>;
503
+ decay?: Record<string, unknown>;
504
+ consolidation?: Record<string, unknown>;
505
+ entityPruning?: Record<string, unknown>;
506
+ sidecar?: Record<string, unknown>;
507
+ sidecarTimeoutMs?: number;
508
+ retrievalTimeoutMs?: number;
509
+ [key: string]: unknown;
510
+ }
511
+
512
+ // ─── Telemetry & Stats ─────────────────────────────────────────────────
513
+
514
+ export interface CortexUsageStatsDTO {
515
+ entityCount: number;
516
+ relationCount: number;
517
+ salienceRecordCount: number;
518
+ consolidationCount: number;
519
+ /** Advanced fields exposed by the host's gc module (mention counts, last
520
+ * GC timestamp, etc.) pass through unchanged. */
521
+ [key: string]: number | string | boolean | null | undefined;
522
+ }
523
+
524
+ export interface CortexIngestionTimingsDTO {
525
+ mode: "heuristic" | "sidecar" | "mixed";
526
+ fontMs: number;
527
+ heuristicMs: number;
528
+ heuristicSalienceMs: number;
529
+ heuristicEntityMs: number;
530
+ heuristicRelationshipMs: number;
531
+ heuristicAliasMs: number;
532
+ sidecarMs: number;
533
+ graphMs: number;
534
+ dbMs: number;
535
+ totalMs: number;
536
+ completedAt: number;
537
+ chunkId: string;
538
+ }
539
+
540
+ export interface CortexIngestionStatusDTO {
541
+ chatId: string;
542
+ status: "idle" | "processing" | "complete" | "error";
543
+ phase:
544
+ | "queued"
545
+ | "font"
546
+ | "heuristics"
547
+ | "sidecar"
548
+ | "persisting"
549
+ | "complete"
550
+ | "error";
551
+ chunkId: string | null;
552
+ startedAt: number | null;
553
+ updatedAt: number;
554
+ pendingJobs: number;
555
+ error?: string;
556
+ timings?: CortexIngestionTimingsDTO | null;
557
+ }
558
+
559
+ export interface CortexIngestionTelemetryDTO {
560
+ samples: number;
561
+ last: CortexIngestionTimingsDTO | null;
562
+ averages: {
563
+ fontMs: number;
564
+ heuristicMs: number;
565
+ sidecarMs: number;
566
+ graphMs: number;
567
+ dbMs: number;
568
+ totalMs: number;
569
+ };
570
+ }
571
+
572
+ // ─── Long-Term Chat Memory ─────────────────────────────────────────────
573
+
574
+ /**
575
+ * A vectorized chat chunk — the basic unit of long-term chat memory. Chunks
576
+ * are produced from contiguous same-role messages bounded by token target
577
+ * and scene-break heuristics; the {{memories}} macro retrieves the top-K
578
+ * chunks by hybrid vector + BM25 score during prompt assembly.
579
+ */
580
+ export interface ChatChunkDTO {
581
+ id: string;
582
+ chatId: string;
583
+ startMessageId: string;
584
+ endMessageId: string;
585
+ messageIds: string[];
586
+ content: string;
587
+ tokenCount: number;
588
+ messageCount: number;
589
+ vectorizedAt: number | null;
590
+ vectorModel: string | null;
591
+ retrievalCount: number;
592
+ lastRetrievedAt: number | null;
593
+ createdAt: number;
594
+ updatedAt: number;
595
+ }
596
+
597
+ /**
598
+ * Result of a long-term chat memory warmup. `status` describes the action
599
+ * taken; `reason` is a short human-readable string useful for diagnostics
600
+ * when nothing was queued.
601
+ */
602
+ export interface ChatMemoryWarmupResultDTO {
603
+ status: "skipped" | "complete" | "rebuilding" | "queued" | "error";
604
+ reason?: string;
605
+ rebuilt?: boolean;
606
+ vectorizationsQueued?: number;
607
+ }
@@ -15,6 +15,9 @@
15
15
  * - "presets" — CRUD on user presets and prompt blocks
16
16
  * - "personas" — CRUD on personas
17
17
  * - "databanks" — CRUD on databanks and their documents
18
+ * - "memories" — CRUD on the Memory Cortex (entities, relations, vaults, chat
19
+ * links, consolidations) and long-term chat memory (vectorized
20
+ * chat-chunk retrieval, warmup, cache).
18
21
  * - "macro_interceptor" — transform raw templates before macro parsing/dispatch
19
22
  */
20
23
  export type SpindlePermission =
@@ -35,6 +38,7 @@ export type SpindlePermission =
35
38
  | "world_books"
36
39
  | "regex_scripts"
37
40
  | "databanks"
41
+ | "memories"
38
42
  | "personas"
39
43
  | "push_notification"
40
44
  | "image_gen"
@@ -60,6 +64,7 @@ export const ALL_PERMISSIONS: readonly SpindlePermission[] = [
60
64
  "world_books",
61
65
  "regex_scripts",
62
66
  "databanks",
67
+ "memories",
63
68
  "personas",
64
69
  "push_notification",
65
70
  "image_gen",
@@ -104,6 +104,31 @@ import type {
104
104
  SharedRpcRequestContextDTO,
105
105
  SharedRpcEndpointPolicyDTO,
106
106
  } from "./api";
107
+ import type {
108
+ ChatChunkDTO,
109
+ ChatLinkAttachDTO,
110
+ ChatLinkDTO,
111
+ ChatMemoryWarmupResultDTO,
112
+ CortexIngestionStatusDTO,
113
+ CortexIngestionTelemetryDTO,
114
+ CortexQueryDTO,
115
+ CortexResultDTO,
116
+ CortexUsageStatsDTO,
117
+ LinkedCortexResultDTO,
118
+ MemoryConsolidationDTO,
119
+ MemoryCortexConfigDTO,
120
+ MemoryEntityDTO,
121
+ MemoryEntityStatusUpdateDTO,
122
+ MemoryEntityUpsertDTO,
123
+ MemoryRelationDTO,
124
+ MemoryRelationUpsertDTO,
125
+ MemorySalienceDTO,
126
+ VaultChunkDTO,
127
+ VaultCreateDTO,
128
+ VaultDTO,
129
+ VaultReindexResultDTO,
130
+ VaultWithContentsDTO,
131
+ } from "./memories";
107
132
 
108
133
  export interface FrontendProcessHandle {
109
134
  /** Host-assigned process ID unique within the extension runtime. */
@@ -827,6 +852,193 @@ export interface SpindleAPI {
827
852
  };
828
853
  };
829
854
 
855
+ /**
856
+ * Memory Cortex & Long-Term Chat Memory (permission: "memories").
857
+ *
858
+ * Lumiverse's hybrid memory architecture exposed as a single CRUD surface:
859
+ *
860
+ * - **`cortex`** — config get/put, retrieval (cortex query, linked-cortex
861
+ * query for vaults + interlinks), warm-cache reads, cache invalidation.
862
+ * - **`entities`** / **`relations`** — entity graph CRUD: list, find,
863
+ * upsert, status updates, fact appends, emotional valence, plus active
864
+ * + unfiltered relation reads and `upsert` for symbolic edges.
865
+ * - **`consolidations`** — list arcs by tier, fetch the latest arc, and
866
+ * `run()` to trigger a background consolidation pass.
867
+ * - **`salience`** — read salience records (score, emotional tags,
868
+ * narrative flags) for chunks already ingested.
869
+ * - **`vaults`** — frozen snapshots of cortex state. `create()` snapshots
870
+ * a chat's entities/relations/chunks, `reindex()` re-copies the chunk
871
+ * snapshot after a LanceDB reset, plus list / get / rename / delete.
872
+ * - **`links`** — attach vaults to chats or set up bidirectional
873
+ * chat-to-chat interlinks; list / remove / toggle.
874
+ * - **`chatMemory`** — the long-term chat memory layer used by the
875
+ * `{{memories}}` macro: list vectorized chunks, fetch top-K retrieval,
876
+ * warm a chat (rebuild + queue vectorization), invalidate cache.
877
+ * - **`stats`** — usage counters, live ingestion phase, and ingestion
878
+ * timing telemetry.
879
+ *
880
+ * For user-scoped extensions, `userId` is inferred from the extension
881
+ * owner. For operator-scoped extensions, pass `userId` to scope a call
882
+ * to a specific user.
883
+ *
884
+ * All chat-scoped calls verify chat ownership against the resolved user
885
+ * — extensions cannot read or mutate cortex state for chats they do not
886
+ * own.
887
+ */
888
+ memories: {
889
+ cortex: {
890
+ /** Get the user's Memory Cortex configuration. */
891
+ getConfig(userId?: string): Promise<MemoryCortexConfigDTO>;
892
+ /** Patch the user's Memory Cortex configuration. Unspecified fields are left untouched. */
893
+ putConfig(patch: Partial<MemoryCortexConfigDTO>, userId?: string): Promise<MemoryCortexConfigDTO>;
894
+ /**
895
+ * Execute a cortex-enhanced memory retrieval. Combines vector search,
896
+ * entity-context fan-out, recency, reinforcement, and emotional
897
+ * components into a unified `CortexResultDTO`.
898
+ *
899
+ * Results are cached server-side; the next call within ~5 minutes
900
+ * for the same chat + query shape returns the cached value.
901
+ */
902
+ query(query: CortexQueryDTO): Promise<CortexResultDTO>;
903
+ /**
904
+ * Read the most recent cortex result from the warm cache without
905
+ * triggering a re-query. Returns `null` if no cached result exists
906
+ * or it expired. Synchronous from the caller's perspective (no
907
+ * vector search runs); useful when an extension just needs the same
908
+ * memories the active generation saw.
909
+ */
910
+ getCached(chatId: string): Promise<CortexResultDTO | null>;
911
+ /**
912
+ * Resolve linked-cortex data for a chat — every attached vault plus
913
+ * every bidirectional interlink target. When `queryText` is supplied,
914
+ * vault retrieval and interlink queries are enriched with relevance
915
+ * to the current conversation.
916
+ */
917
+ queryLinked(chatId: string, options?: { queryText?: string; userId?: string }): Promise<LinkedCortexResultDTO>;
918
+ /** Read the cached linked-cortex result for a chat. Mirrors {@link getCached}. */
919
+ getCachedLinked(chatId: string): Promise<LinkedCortexResultDTO | null>;
920
+ /** Invalidate the cortex retrieval cache for a chat. */
921
+ invalidateCache(chatId: string): Promise<void>;
922
+ /** Invalidate the linked-cortex retrieval cache for a chat. */
923
+ invalidateLinkedCache(chatId: string): Promise<void>;
924
+ };
925
+
926
+ entities: {
927
+ /**
928
+ * List entities for a chat. By default returns only entities with
929
+ * `status: "active"`, ordered by salience; pass `activeOnly: false`
930
+ * to include retired / deceased / destroyed entities.
931
+ */
932
+ list(chatId: string, options?: { activeOnly?: boolean; limit?: number; userId?: string }): Promise<MemoryEntityDTO[]>;
933
+ get(entityId: string, userId?: string): Promise<MemoryEntityDTO | null>;
934
+ findByName(chatId: string, name: string, userId?: string): Promise<MemoryEntityDTO | null>;
935
+ /**
936
+ * Upsert an entity. Matches against canonical name and known aliases;
937
+ * inserts a new row on miss. `chunkId` and `createdAt` attribute the
938
+ * mention used to fill `lastSeen*` fields — pass them when replaying
939
+ * an extractor over a specific chunk.
940
+ */
941
+ upsert(
942
+ chatId: string,
943
+ entity: MemoryEntityUpsertDTO,
944
+ options?: { chunkId?: string | null; createdAt?: number; userId?: string },
945
+ ): Promise<MemoryEntityDTO>;
946
+ updateStatus(entityId: string, patch: MemoryEntityStatusUpdateDTO, userId?: string): Promise<MemoryEntityDTO>;
947
+ addFacts(entityId: string, facts: string[], userId?: string): Promise<MemoryEntityDTO>;
948
+ getFacts(entityId: string, userId?: string): Promise<string[]>;
949
+ updateEmotionalValence(entityId: string, valence: Record<string, number>, userId?: string): Promise<MemoryEntityDTO>;
950
+ };
951
+
952
+ relations: {
953
+ /** Active relations for a chat (excludes superseded / merged edges). */
954
+ list(chatId: string, userId?: string): Promise<MemoryRelationDTO[]>;
955
+ /** Every relation row including superseded / merged edges — for diagnostics. */
956
+ listAll(chatId: string, userId?: string): Promise<MemoryRelationDTO[]>;
957
+ forEntity(chatId: string, entityId: string, userId?: string): Promise<MemoryRelationDTO[]>;
958
+ forEntities(chatId: string, entityIds: string[], options?: { limit?: number; userId?: string }): Promise<MemoryRelationDTO[]>;
959
+ /**
960
+ * Upsert a relation. Both endpoints must already exist in the entity
961
+ * graph (use `entities.upsert` first); the relation is silently
962
+ * dropped otherwise. `chunkId` attributes the evidence to a chunk.
963
+ */
964
+ upsert(
965
+ chatId: string,
966
+ relation: MemoryRelationUpsertDTO,
967
+ options?: { chunkId?: string | null; userId?: string },
968
+ ): Promise<MemoryRelationDTO | null>;
969
+ };
970
+
971
+ consolidations: {
972
+ /** List arcs for a chat. Pass `tier` to filter to one tier (1 = scene, 2 = chapter, …). */
973
+ list(chatId: string, options?: { tier?: number; userId?: string }): Promise<MemoryConsolidationDTO[]>;
974
+ /** The most recent arc across all tiers, or `null` if none have been produced. */
975
+ latestArc(chatId: string, userId?: string): Promise<MemoryConsolidationDTO | null>;
976
+ /**
977
+ * Trigger an async consolidation pass over the chat's chunks. Returns
978
+ * immediately; new arcs become visible via `list()` once the
979
+ * background job completes.
980
+ */
981
+ run(chatId: string, userId?: string): Promise<void>;
982
+ };
983
+
984
+ salience: {
985
+ /** List salience records for a chat's chunks, ordered by `scoredAt`. */
986
+ list(chatId: string, options?: { limit?: number; offset?: number; userId?: string }): Promise<MemorySalienceDTO[]>;
987
+ };
988
+
989
+ vaults: {
990
+ list(userId?: string): Promise<VaultDTO[]>;
991
+ /** Fetch a vault with its entities + relations. Returns `null` if not found or not owned by the resolved user. */
992
+ get(vaultId: string, userId?: string): Promise<VaultWithContentsDTO | null>;
993
+ getChunks(vaultId: string, userId?: string): Promise<VaultChunkDTO[]>;
994
+ /**
995
+ * Snapshot a chat's cortex state into a new vault. Copies entities,
996
+ * relations and chunk content; LanceDB embeddings are copied in the
997
+ * background.
998
+ */
999
+ create(input: VaultCreateDTO, userId?: string): Promise<VaultDTO>;
1000
+ rename(vaultId: string, name: string, userId?: string): Promise<boolean>;
1001
+ delete(vaultId: string, userId?: string): Promise<boolean>;
1002
+ /** Re-run the LanceDB chunk copy for a vault (e.g. after an embedding model swap). */
1003
+ reindex(vaultId: string, userId?: string): Promise<VaultReindexResultDTO>;
1004
+ };
1005
+
1006
+ links: {
1007
+ list(chatId: string, userId?: string): Promise<ChatLinkDTO[]>;
1008
+ /**
1009
+ * Attach a vault or set up a chat-to-chat interlink. For interlinks,
1010
+ * pass `bidirectional: true` to also create the reverse link.
1011
+ */
1012
+ attach(input: ChatLinkAttachDTO, userId?: string): Promise<ChatLinkDTO[]>;
1013
+ remove(chatId: string, linkId: string, userId?: string): Promise<boolean>;
1014
+ toggle(chatId: string, linkId: string, enabled: boolean, userId?: string): Promise<boolean>;
1015
+ };
1016
+
1017
+ chatMemory: {
1018
+ /**
1019
+ * List the vectorized chunks for a chat. Useful for inspecting the
1020
+ * raw retrieval index used by the `{{memories}}` macro.
1021
+ */
1022
+ listChunks(chatId: string, userId?: string): Promise<ChatChunkDTO[]>;
1023
+ /** Top-K chat memory chunks for a chat via hybrid vector + BM25 search. */
1024
+ get(chatId: string, options?: { topK?: number; userId?: string }): Promise<ChatMemoryResultDTO>;
1025
+ /**
1026
+ * Warm long-term chat memory: rebuilds chunks if stale and queues any
1027
+ * pending chunk vectorizations. Pass `force: true` to rebuild even
1028
+ * when the chunk hash is fresh.
1029
+ */
1030
+ warm(chatId: string, options?: { force?: boolean; userId?: string }): Promise<ChatMemoryWarmupResultDTO>;
1031
+ /** Drop the cached `{{memories}}` retrieval result for a chat. */
1032
+ invalidate(chatId: string, userId?: string): Promise<void>;
1033
+ };
1034
+
1035
+ stats: {
1036
+ usage(chatId: string, userId?: string): Promise<CortexUsageStatsDTO>;
1037
+ ingestionStatus(chatId: string, userId?: string): Promise<CortexIngestionStatusDTO | null>;
1038
+ ingestionTelemetry(chatId: string, userId?: string): Promise<CortexIngestionTelemetryDTO>;
1039
+ };
1040
+ };
1041
+
830
1042
  /**
831
1043
  * Personas CRUD (permission: "personas").
832
1044
  * Manage user personas (identity profiles).