@equationalapplications/core-llm-wiki 4.14.1 → 4.15.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/README.md +61 -7
- package/dist/{chunk-24ANTHZB.mjs → chunk-J4GBC6CP.mjs} +28 -10
- package/dist/chunk-J4GBC6CP.mjs.map +1 -0
- package/dist/index.d.mts +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.js +357 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +334 -18
- package/dist/index.mjs.map +1 -1
- package/dist/{testing-DW1qufP0.d.mts → testing-NH1_Aigh.d.mts} +32 -2
- package/dist/{testing-DW1qufP0.d.ts → testing-NH1_Aigh.d.ts} +32 -2
- package/dist/testing.d.mts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +26 -8
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +1 -1
- package/package.json +2 -2
- package/dist/chunk-24ANTHZB.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -20,6 +20,7 @@ Platform-agnostic TypeScript engine for hybrid LLM memory. Features episodic fac
|
|
|
20
20
|
- **Immutable vs mutable facts** — Use `WikiFact.source_type` to distinguish document-sourced facts (`immutable_document`) from derived or user-provided facts (`librarian_inferred`, `user_stated`, `user_confirmed`). Immutable document facts are not rewritten by `runLibrarian()` or `runHeal()` and can only be removed by `forget()` or re-ingesting.
|
|
21
21
|
- **Full-featured memory** — Facts, tasks, events, maintenance jobs (librarian, heal, reembed, prune)
|
|
22
22
|
- **Type-safe** — Built with TypeScript, full type exports
|
|
23
|
+
- **Interoperability:** Supports [Open Knowledge Format (OKF) v0.1](https://github.com/GoogleCloudPlatform/knowledge-catalog/tree/main/okf) import and export.
|
|
23
24
|
|
|
24
25
|
## Installation
|
|
25
26
|
|
|
@@ -444,6 +445,58 @@ Notes:
|
|
|
444
445
|
- A throwing callback is caught (logged via `console.error`) and does not block other subscribers or the underlying job.
|
|
445
446
|
- Subscriptions are scoped to a single `entityId`. There is no wildcard or "all entities" form.
|
|
446
447
|
|
|
448
|
+
## OKF Import/Export
|
|
449
|
+
|
|
450
|
+
The core package integrates with `@equationalapplications/core-okf` to seamlessly adapt wiki data dumps to and from Open Knowledge Format (OKF) v0.1 bundles.
|
|
451
|
+
|
|
452
|
+
### Exporting an OKF Bundle
|
|
453
|
+
|
|
454
|
+
Convert an existing wiki dump into a flat array of OKF files, ready to be written to disk or zipped:
|
|
455
|
+
|
|
456
|
+
```typescript
|
|
457
|
+
import { formatOkfBundle } from '@equationalapplications/core-llm-wiki';
|
|
458
|
+
|
|
459
|
+
const dump = await wiki.exportDump(['entity-123']);
|
|
460
|
+
const { files } = formatOkfBundle(dump);
|
|
461
|
+
|
|
462
|
+
// files: Array<{ path: string; content: string }>
|
|
463
|
+
// e.g., [{ path: 'entities/entity-123/facts/fact_abc.md', content: '---\n...' }]
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
### Importing an OKF Bundle
|
|
467
|
+
|
|
468
|
+
Parse raw OKF files back into a `MemoryDump` that the wiki can ingest:
|
|
469
|
+
|
|
470
|
+
```typescript
|
|
471
|
+
import { parseOkfBundle } from '@equationalapplications/core-llm-wiki';
|
|
472
|
+
|
|
473
|
+
// Assuming you read OKF files for this entity (e.g. under `entities/entity-123/`) from disk/zip into OkfFile[] shape
|
|
474
|
+
const dump = parseOkfBundle('entity-123', files, {
|
|
475
|
+
defaultSchema: 'fact',
|
|
476
|
+
typeMapping: {
|
|
477
|
+
'custom_type': 'fact',
|
|
478
|
+
'archived': 'ignore', // Skips these concepts
|
|
479
|
+
},
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
await wiki.importDump(dump, { merge: true });
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
**Routing Precedence:** Concepts are routed into either the `entries` (facts) or `tasks` tables based on a three-step fallback:
|
|
486
|
+
|
|
487
|
+
1. `OkfImportOptions.typeMapping` explicitly mapping an OKF `type` to `'fact'`, `'task'`, or `'ignore'`.
|
|
488
|
+
2. Directory convention (e.g., files in `/facts/` become facts, `/tasks/` become tasks).
|
|
489
|
+
3. The `OkfImportOptions.defaultSchema` (defaults to `'fact'`).
|
|
490
|
+
|
|
491
|
+
### WikiEdge and Markdown Links
|
|
492
|
+
|
|
493
|
+
A `WikiEdge` represents a markdown cross-link found inside a concept body, resolved to a `source_id` and `target_id`.
|
|
494
|
+
Edges automatically round-trip during OKF import and export. Because the markdown body is the source of truth for edges in the OKF spec, edges are extracted during `parseOkfBundle()` and persisted via the `EdgeRepository` on `importDump()` — there is no separate edge export step required. The `edges` array is included in bundles returned by `getMemoryBundle()` / `exportDump()` (not by `read()`).
|
|
495
|
+
|
|
496
|
+
### The `okf_type` Field
|
|
497
|
+
|
|
498
|
+
Facts and tasks include a nullable `okf_type` column. This preserves the literal OKF `type` string from an imported bundle frontmatter, independent of whether the item was routed to the `entries` or `tasks` table. When `formatOkfBundle` runs, it restores this specific string, falling back to `'fact'` or `'task'` if the field is null (ensuring non-imported rows export cleanly).
|
|
499
|
+
|
|
447
500
|
## Security
|
|
448
501
|
|
|
449
502
|
`@equationalapplications/core-llm-wiki` enforces multiple security layers:
|
|
@@ -706,13 +759,14 @@ The flowchart shows:
|
|
|
706
759
|
|
|
707
760
|
## Monorepo Ecosystem
|
|
708
761
|
|
|
709
|
-
| Package |
|
|
710
|
-
|
|
711
|
-
|
|
|
712
|
-
| [
|
|
713
|
-
| [
|
|
714
|
-
| [
|
|
715
|
-
| [
|
|
762
|
+
| Package | Purpose |
|
|
763
|
+
| ----- | ----- |
|
|
764
|
+
| **@equationalapplications/core-llm-wiki** | Persistent episodic memory |
|
|
765
|
+
| [@equationalapplications/expo-llm-wiki](https://github.com/equationalapplications/expo-llm-wiki/blob/main/packages/expo/README.md) | Persistent episodic memory for Expo/React Native |
|
|
766
|
+
| [@equationalapplications/react-llm-wiki](https://github.com/equationalapplications/expo-llm-wiki/blob/main/packages/react/README.md) | Persistent episodic memory for Web |
|
|
767
|
+
| [@equationalapplications/prisma-outbox](https://github.com/equationalapplications/expo-llm-wiki/blob/main/packages/prisma-outbox/README.md) | Sync SQLite outbox events to Prisma |
|
|
768
|
+
| [@equationalapplications/core-llm-tools](https://github.com/equationalapplications/expo-llm-wiki/blob/main/packages/core-llm-tools/README.md) | Gemini tool schemas and capability injector |
|
|
769
|
+
| [@equationalapplications/core-okf](https://github.com/equationalapplications/expo-llm-wiki/blob/main/packages/okf/README.md) | Zero-dependency Open Knowledge Format (OKF) v0.1 primitives — parse and produce interoperable knowledge bundles. |
|
|
716
770
|
|
|
717
771
|
## License
|
|
718
772
|
|
|
@@ -1428,11 +1428,12 @@ var MAX_EMBEDDING_BLOB_BYTES = 32 * 1024;
|
|
|
1428
1428
|
var IMPORT_TITLE_MAX = 500;
|
|
1429
1429
|
var IMPORT_BODY_MAX = 8e3;
|
|
1430
1430
|
var ImportExportService = class {
|
|
1431
|
-
constructor(db, entryRepo, taskRepo, eventRepo, metadataRepo, searchService, jobManager, embeddingService) {
|
|
1431
|
+
constructor(db, entryRepo, taskRepo, eventRepo, edgeRepo, metadataRepo, searchService, jobManager, embeddingService) {
|
|
1432
1432
|
this.db = db;
|
|
1433
1433
|
this.entryRepo = entryRepo;
|
|
1434
1434
|
this.taskRepo = taskRepo;
|
|
1435
1435
|
this.eventRepo = eventRepo;
|
|
1436
|
+
this.edgeRepo = edgeRepo;
|
|
1436
1437
|
this.metadataRepo = metadataRepo;
|
|
1437
1438
|
this.searchService = searchService;
|
|
1438
1439
|
this.jobManager = jobManager;
|
|
@@ -1477,10 +1478,11 @@ var ImportExportService = class {
|
|
|
1477
1478
|
}
|
|
1478
1479
|
}
|
|
1479
1480
|
async getFullBundle(entityId, opts) {
|
|
1480
|
-
const [factsRaw, tasks, events] = await Promise.all([
|
|
1481
|
+
const [factsRaw, tasks, events, edges] = await Promise.all([
|
|
1481
1482
|
opts?.includeBlobs ? this.entryRepo.findAllByEntityIdWithBlobs(entityId) : this.entryRepo.findAllByEntityId(entityId),
|
|
1482
1483
|
this.taskRepo.findAllByEntityId(entityId),
|
|
1483
|
-
this.eventRepo.getByEntityId(entityId, opts?.maxEvents)
|
|
1484
|
+
this.eventRepo.getByEntityId(entityId, opts?.maxEvents),
|
|
1485
|
+
this.edgeRepo.getByEntityId(entityId)
|
|
1484
1486
|
]);
|
|
1485
1487
|
const facts = factsRaw.map((f) => {
|
|
1486
1488
|
const {
|
|
@@ -1499,7 +1501,7 @@ var ImportExportService = class {
|
|
|
1499
1501
|
tags: typeof factBase.tags === "string" ? JSON.parse(factBase.tags) : factBase.tags
|
|
1500
1502
|
};
|
|
1501
1503
|
});
|
|
1502
|
-
return { facts, tasks, events };
|
|
1504
|
+
return { facts, tasks, events, edges };
|
|
1503
1505
|
}
|
|
1504
1506
|
/** Single-entity import transaction + post-processing; package-internal hook for tests. */
|
|
1505
1507
|
async doImportEntity(entityId, bundle, merge) {
|
|
@@ -1521,6 +1523,7 @@ var ImportExportService = class {
|
|
|
1521
1523
|
softDeletedFactIds.push(...deletedLiveFactIds);
|
|
1522
1524
|
await this.entryRepo.bulkSoftDeleteByEntityId(entityId, tx);
|
|
1523
1525
|
await this.taskRepo.bulkSoftDeleteByEntityId(entityId, tx);
|
|
1526
|
+
await this.edgeRepo.bulkDeleteByEntityId(entityId, tx);
|
|
1524
1527
|
await this.metadataRepo.deleteCheckpoint(entityId, tx);
|
|
1525
1528
|
}
|
|
1526
1529
|
const factIds = bundle.facts.map((fact) => fact.id);
|
|
@@ -1618,7 +1621,8 @@ var ImportExportService = class {
|
|
|
1618
1621
|
last_accessed_at: fact.last_accessed_at,
|
|
1619
1622
|
access_count: fact.access_count,
|
|
1620
1623
|
deleted_at: fact.deleted_at,
|
|
1621
|
-
embedding_blob: blobData ?? void 0
|
|
1624
|
+
embedding_blob: blobData ?? void 0,
|
|
1625
|
+
okf_type: fact.okf_type ?? null
|
|
1622
1626
|
};
|
|
1623
1627
|
await this.entryRepo.upsertForImport(factObj, tx);
|
|
1624
1628
|
if (blobData != null) {
|
|
@@ -1667,7 +1671,8 @@ var ImportExportService = class {
|
|
|
1667
1671
|
created_at: task.created_at,
|
|
1668
1672
|
updated_at: safeUpdatedAt,
|
|
1669
1673
|
resolved_at: task.resolved_at,
|
|
1670
|
-
deleted_at: task.deleted_at
|
|
1674
|
+
deleted_at: task.deleted_at,
|
|
1675
|
+
okf_type: task.okf_type ?? null
|
|
1671
1676
|
},
|
|
1672
1677
|
tx,
|
|
1673
1678
|
safeUpdatedAt
|
|
@@ -1691,6 +1696,19 @@ var ImportExportService = class {
|
|
|
1691
1696
|
tx
|
|
1692
1697
|
);
|
|
1693
1698
|
}
|
|
1699
|
+
for (const edge of bundle.edges ?? []) {
|
|
1700
|
+
await this.edgeRepo.addIgnoreDuplicate(
|
|
1701
|
+
{
|
|
1702
|
+
id: edge.id,
|
|
1703
|
+
entity_id: entityId,
|
|
1704
|
+
source_id: edge.source_id,
|
|
1705
|
+
target_id: edge.target_id,
|
|
1706
|
+
edge_type: edge.edge_type,
|
|
1707
|
+
created_at: edge.created_at
|
|
1708
|
+
},
|
|
1709
|
+
tx
|
|
1710
|
+
);
|
|
1711
|
+
}
|
|
1694
1712
|
});
|
|
1695
1713
|
await this.searchService.sync(entityId);
|
|
1696
1714
|
for (const fact of bundle.facts) {
|
|
@@ -2007,7 +2025,7 @@ var RetrievalService = class {
|
|
|
2007
2025
|
const sanitizedTierWeights = shouldExposeReadMetadata(entityId) ? sanitizeTierWeights(entityIds, options?.tierWeights) : void 0;
|
|
2008
2026
|
const exposeMetadata = shouldExposeReadMetadata(entityId);
|
|
2009
2027
|
if (entityIds.length === 0) {
|
|
2010
|
-
const empty = { facts: [], tasks: [], events: [] };
|
|
2028
|
+
const empty = { facts: [], tasks: [], events: [], edges: [] };
|
|
2011
2029
|
if (exposeMetadata) {
|
|
2012
2030
|
empty.metadata = { query, entityIds: [] };
|
|
2013
2031
|
if (sanitizedTierWeights && Object.keys(sanitizedTierWeights).length > 0) empty.metadata.tierWeights = sanitizedTierWeights;
|
|
@@ -2397,7 +2415,7 @@ var RetrievalService = class {
|
|
|
2397
2415
|
if (exposeMetadata && trimmedQuery && scoreByFactId) {
|
|
2398
2416
|
factScores = Object.fromEntries(facts.map((fact) => [fact.id, scoreByFactId.get(fact.id) ?? 0]));
|
|
2399
2417
|
}
|
|
2400
|
-
const bundle = { facts, tasks, events: events.reverse() };
|
|
2418
|
+
const bundle = { facts, tasks, events: events.reverse(), edges: [] };
|
|
2401
2419
|
if (exposeMetadata) {
|
|
2402
2420
|
bundle.metadata = { query, entityIds };
|
|
2403
2421
|
if (sanitizedTierWeights && Object.keys(sanitizedTierWeights).length > 0) bundle.metadata.tierWeights = sanitizedTierWeights;
|
|
@@ -2597,5 +2615,5 @@ var WriteService = class {
|
|
|
2597
2615
|
};
|
|
2598
2616
|
|
|
2599
2617
|
export { EmbeddingService, HOOK_TIMEOUT_MARKER, ImportExportService, IngestionService, JobManager, MaintenanceService, PromptService, PrunePartialFailureError, RetrievalService, SearchService, WikiBusyError, WriteService, __privateAdd, __privateGet, __privateSet, generateId, normalizeSourceHash, normalizeSourceRef, parseEmbedding };
|
|
2600
|
-
//# sourceMappingURL=chunk-
|
|
2601
|
-
//# sourceMappingURL=chunk-
|
|
2618
|
+
//# sourceMappingURL=chunk-J4GBC6CP.mjs.map
|
|
2619
|
+
//# sourceMappingURL=chunk-J4GBC6CP.mjs.map
|