@equationalapplications/core-llm-wiki 4.14.1 → 4.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { __privateAdd, EmbeddingService, SearchService, JobManager, PromptService, IngestionService, MaintenanceService, ImportExportService, RetrievalService, WriteService, __privateGet, __privateSet, normalizeSourceRef, normalizeSourceHash, generateId } from './chunk-
|
|
2
|
-
export { HOOK_TIMEOUT_MARKER, PromptService, PrunePartialFailureError, WikiBusyError, parseEmbedding } from './chunk-
|
|
3
|
-
import { buildConceptDocument, buildLogMd, buildIndexMd, buildRootIndexMd } from '@equationalapplications/core-okf';
|
|
1
|
+
import { __privateAdd, EmbeddingService, SearchService, JobManager, PromptService, IngestionService, MaintenanceService, ImportExportService, RetrievalService, WriteService, __privateGet, __privateSet, normalizeSourceRef, normalizeSourceHash, generateId } from './chunk-J4GBC6CP.mjs';
|
|
2
|
+
export { HOOK_TIMEOUT_MARKER, PromptService, PrunePartialFailureError, WikiBusyError, parseEmbedding } from './chunk-J4GBC6CP.mjs';
|
|
3
|
+
import { buildConceptDocument, buildLogMd, buildIndexMd, buildRootIndexMd, parseConcept, extractMarkdownLinks, parseLogMd } from '@equationalapplications/core-okf';
|
|
4
4
|
|
|
5
5
|
// src/db/schema.ts
|
|
6
6
|
async function setupDatabase(db, prefix) {
|
|
@@ -21,7 +21,8 @@ async function setupDatabase(db, prefix) {
|
|
|
21
21
|
access_count INTEGER NOT NULL DEFAULT 0,
|
|
22
22
|
deleted_at INTEGER,
|
|
23
23
|
embedding TEXT,
|
|
24
|
-
embedding_blob BLOB
|
|
24
|
+
embedding_blob BLOB,
|
|
25
|
+
okf_type TEXT
|
|
25
26
|
);
|
|
26
27
|
|
|
27
28
|
CREATE INDEX IF NOT EXISTS ${prefix}entries_entity_idx ON ${prefix}entries(entity_id);
|
|
@@ -38,11 +39,24 @@ async function setupDatabase(db, prefix) {
|
|
|
38
39
|
created_at INTEGER NOT NULL,
|
|
39
40
|
updated_at INTEGER NOT NULL,
|
|
40
41
|
resolved_at INTEGER,
|
|
41
|
-
deleted_at INTEGER
|
|
42
|
+
deleted_at INTEGER,
|
|
43
|
+
okf_type TEXT
|
|
42
44
|
);
|
|
43
45
|
|
|
44
46
|
CREATE INDEX IF NOT EXISTS ${prefix}tasks_entity_idx ON ${prefix}tasks(entity_id, status);
|
|
45
47
|
|
|
48
|
+
CREATE TABLE IF NOT EXISTS ${prefix}edges (
|
|
49
|
+
id TEXT PRIMARY KEY,
|
|
50
|
+
entity_id TEXT NOT NULL,
|
|
51
|
+
source_id TEXT NOT NULL,
|
|
52
|
+
target_id TEXT NOT NULL,
|
|
53
|
+
edge_type TEXT NOT NULL,
|
|
54
|
+
created_at INTEGER NOT NULL,
|
|
55
|
+
UNIQUE(entity_id, source_id, target_id, edge_type)
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
CREATE INDEX IF NOT EXISTS ${prefix}edges_entity_idx ON ${prefix}edges(entity_id);
|
|
59
|
+
|
|
46
60
|
CREATE TABLE IF NOT EXISTS ${prefix}events (
|
|
47
61
|
id TEXT PRIMARY KEY,
|
|
48
62
|
entity_id TEXT NOT NULL,
|
|
@@ -143,6 +157,32 @@ var MIGRATIONS = [
|
|
|
143
157
|
ON ${prefix}outbox (entity_id, created_at);
|
|
144
158
|
`);
|
|
145
159
|
}
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
version: 5,
|
|
163
|
+
description: "Add okf_type to entries/tasks for OKF type fidelity; create edges table for OKF graph import",
|
|
164
|
+
run: async (db, prefix) => {
|
|
165
|
+
for (const table of ["entries", "tasks"]) {
|
|
166
|
+
const cols = await db.getAllAsync(
|
|
167
|
+
`PRAGMA table_info(${prefix}${table})`
|
|
168
|
+
);
|
|
169
|
+
if (!cols.some((c) => c.name === "okf_type")) {
|
|
170
|
+
await db.execAsync(`ALTER TABLE ${prefix}${table} ADD COLUMN okf_type TEXT`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
await db.execAsync(`
|
|
174
|
+
CREATE TABLE IF NOT EXISTS ${prefix}edges (
|
|
175
|
+
id TEXT PRIMARY KEY,
|
|
176
|
+
entity_id TEXT NOT NULL,
|
|
177
|
+
source_id TEXT NOT NULL,
|
|
178
|
+
target_id TEXT NOT NULL,
|
|
179
|
+
edge_type TEXT NOT NULL,
|
|
180
|
+
created_at INTEGER NOT NULL,
|
|
181
|
+
UNIQUE(entity_id, source_id, target_id, edge_type)
|
|
182
|
+
);
|
|
183
|
+
CREATE INDEX IF NOT EXISTS ${prefix}edges_entity_idx ON ${prefix}edges (entity_id);
|
|
184
|
+
`);
|
|
185
|
+
}
|
|
146
186
|
}
|
|
147
187
|
];
|
|
148
188
|
for (let i = 1; i < MIGRATIONS.length; i++) {
|
|
@@ -194,7 +234,8 @@ function mapRowToFact(row) {
|
|
|
194
234
|
updated_at: Number(row.updated_at),
|
|
195
235
|
last_accessed_at: row.last_accessed_at === null || row.last_accessed_at === void 0 ? null : Number(row.last_accessed_at),
|
|
196
236
|
deleted_at: row.deleted_at != null ? Number(row.deleted_at) : null,
|
|
197
|
-
access_count: Number(row.access_count ?? 0)
|
|
237
|
+
access_count: Number(row.access_count ?? 0),
|
|
238
|
+
okf_type: row.okf_type ?? null
|
|
198
239
|
};
|
|
199
240
|
}
|
|
200
241
|
function normalizeEmbeddingBlobValue(blob) {
|
|
@@ -367,8 +408,8 @@ var EntryRepository = class extends BaseRepository {
|
|
|
367
408
|
`INSERT INTO ${this.prefix}entries (
|
|
368
409
|
id, entity_id, title, body, tags, confidence, source_type,
|
|
369
410
|
source_hash, source_ref, created_at, updated_at, last_accessed_at, access_count,
|
|
370
|
-
deleted_at, embedding_blob, embedding
|
|
371
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
411
|
+
deleted_at, embedding_blob, embedding, okf_type
|
|
412
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
372
413
|
ON CONFLICT(id) DO UPDATE SET
|
|
373
414
|
entity_id = excluded.entity_id,
|
|
374
415
|
title = excluded.title,
|
|
@@ -384,7 +425,8 @@ var EntryRepository = class extends BaseRepository {
|
|
|
384
425
|
access_count = excluded.access_count,
|
|
385
426
|
deleted_at = excluded.deleted_at,
|
|
386
427
|
embedding_blob = excluded.embedding_blob,
|
|
387
|
-
embedding = NULL
|
|
428
|
+
embedding = NULL,
|
|
429
|
+
okf_type = excluded.okf_type`,
|
|
388
430
|
[
|
|
389
431
|
fact.id,
|
|
390
432
|
fact.entity_id,
|
|
@@ -401,7 +443,8 @@ var EntryRepository = class extends BaseRepository {
|
|
|
401
443
|
fact.access_count,
|
|
402
444
|
fact.deleted_at ?? null,
|
|
403
445
|
embeddingBlob ?? null,
|
|
404
|
-
null
|
|
446
|
+
null,
|
|
447
|
+
fact.okf_type ?? null
|
|
405
448
|
]
|
|
406
449
|
);
|
|
407
450
|
return result;
|
|
@@ -966,7 +1009,8 @@ function mapRowToTask(row) {
|
|
|
966
1009
|
created_at: Number(row.created_at),
|
|
967
1010
|
updated_at: Number(row.updated_at),
|
|
968
1011
|
resolved_at: row.resolved_at != null ? Number(row.resolved_at) : null,
|
|
969
|
-
deleted_at: row.deleted_at != null ? Number(row.deleted_at) : null
|
|
1012
|
+
deleted_at: row.deleted_at != null ? Number(row.deleted_at) : null,
|
|
1013
|
+
okf_type: row.okf_type ?? null
|
|
970
1014
|
};
|
|
971
1015
|
}
|
|
972
1016
|
var TaskRepository = class extends BaseRepository {
|
|
@@ -1068,8 +1112,8 @@ var TaskRepository = class extends BaseRepository {
|
|
|
1068
1112
|
await executor.runAsync(
|
|
1069
1113
|
`INSERT INTO ${this.prefix}tasks (
|
|
1070
1114
|
id, entity_id, description, status, priority,
|
|
1071
|
-
created_at, updated_at, resolved_at, deleted_at
|
|
1072
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1115
|
+
created_at, updated_at, resolved_at, deleted_at, okf_type
|
|
1116
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
1073
1117
|
ON CONFLICT(id) DO UPDATE SET
|
|
1074
1118
|
entity_id = excluded.entity_id,
|
|
1075
1119
|
description = excluded.description,
|
|
@@ -1077,7 +1121,8 @@ var TaskRepository = class extends BaseRepository {
|
|
|
1077
1121
|
priority = excluded.priority,
|
|
1078
1122
|
updated_at = excluded.updated_at,
|
|
1079
1123
|
resolved_at = excluded.resolved_at,
|
|
1080
|
-
deleted_at = excluded.deleted_at
|
|
1124
|
+
deleted_at = excluded.deleted_at,
|
|
1125
|
+
okf_type = excluded.okf_type`,
|
|
1081
1126
|
[
|
|
1082
1127
|
task.id,
|
|
1083
1128
|
task.entity_id,
|
|
@@ -1087,7 +1132,8 @@ var TaskRepository = class extends BaseRepository {
|
|
|
1087
1132
|
task.created_at,
|
|
1088
1133
|
now,
|
|
1089
1134
|
task.resolved_at ?? null,
|
|
1090
|
-
task.deleted_at ?? null
|
|
1135
|
+
task.deleted_at ?? null,
|
|
1136
|
+
task.okf_type ?? null
|
|
1091
1137
|
]
|
|
1092
1138
|
);
|
|
1093
1139
|
}
|
|
@@ -1309,6 +1355,53 @@ var EventRepository = class extends BaseRepository {
|
|
|
1309
1355
|
}
|
|
1310
1356
|
};
|
|
1311
1357
|
|
|
1358
|
+
// src/repositories/EdgeRepository.ts
|
|
1359
|
+
var EdgeRepository = class extends BaseRepository {
|
|
1360
|
+
/**
|
|
1361
|
+
* Insert an edge, silently skipping on primary-key or uniqueness conflicts.
|
|
1362
|
+
* Throws when the insert was skipped due to an id collision with a different edge tuple.
|
|
1363
|
+
*/
|
|
1364
|
+
async addIgnoreDuplicate(edge, tx) {
|
|
1365
|
+
const executor = this.getExecutor(tx);
|
|
1366
|
+
const result = await executor.runAsync(
|
|
1367
|
+
`INSERT OR IGNORE INTO ${this.prefix}edges (id, entity_id, source_id, target_id, edge_type, created_at)
|
|
1368
|
+
VALUES (?, ?, ?, ?, ?, ?)`,
|
|
1369
|
+
[edge.id, edge.entity_id, edge.source_id, edge.target_id, edge.edge_type, edge.created_at]
|
|
1370
|
+
);
|
|
1371
|
+
if (result.changes > 0) return;
|
|
1372
|
+
const existing = await executor.getFirstAsync(
|
|
1373
|
+
`SELECT entity_id, source_id, target_id, edge_type FROM ${this.prefix}edges WHERE id = ?`,
|
|
1374
|
+
[edge.id]
|
|
1375
|
+
);
|
|
1376
|
+
if (!existing) return;
|
|
1377
|
+
if (String(existing.entity_id) !== edge.entity_id || String(existing.source_id) !== edge.source_id || String(existing.target_id) !== edge.target_id || String(existing.edge_type) !== edge.edge_type) {
|
|
1378
|
+
throw new Error(
|
|
1379
|
+
`Edge id collision: ${JSON.stringify(edge.id)} already exists with a different (entity_id, source_id, target_id, edge_type) tuple`
|
|
1380
|
+
);
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
async getByEntityId(entityId, tx) {
|
|
1384
|
+
const executor = this.getExecutor(tx);
|
|
1385
|
+
const rows = await executor.getAllAsync(
|
|
1386
|
+
`SELECT * FROM ${this.prefix}edges WHERE entity_id = ? ORDER BY created_at ASC`,
|
|
1387
|
+
[entityId]
|
|
1388
|
+
);
|
|
1389
|
+
return rows.map((row) => ({
|
|
1390
|
+
id: String(row.id),
|
|
1391
|
+
entity_id: String(row.entity_id),
|
|
1392
|
+
source_id: String(row.source_id),
|
|
1393
|
+
target_id: String(row.target_id),
|
|
1394
|
+
edge_type: String(row.edge_type),
|
|
1395
|
+
created_at: Number(row.created_at)
|
|
1396
|
+
}));
|
|
1397
|
+
}
|
|
1398
|
+
/** Hard delete — edges have no soft-delete concept, only presence/absence. `tx` is REQUIRED. */
|
|
1399
|
+
async bulkDeleteByEntityId(entityId, tx) {
|
|
1400
|
+
const executor = this.getExecutor(tx);
|
|
1401
|
+
await executor.runAsync(`DELETE FROM ${this.prefix}edges WHERE entity_id = ?`, [entityId]);
|
|
1402
|
+
}
|
|
1403
|
+
};
|
|
1404
|
+
|
|
1312
1405
|
// src/repositories/MetadataRepository.ts
|
|
1313
1406
|
var MetadataRepository = class extends BaseRepository {
|
|
1314
1407
|
// CHECKPOINTS TABLE METHODS
|
|
@@ -1428,6 +1521,7 @@ var WikiMemory = class {
|
|
|
1428
1521
|
this.entryRepo = new EntryRepository(db, this.prefix, this.outboxRepo);
|
|
1429
1522
|
this.taskRepo = new TaskRepository(db, this.prefix, this.outboxRepo);
|
|
1430
1523
|
this.eventRepo = new EventRepository(db, this.prefix);
|
|
1524
|
+
this.edgeRepo = new EdgeRepository(db, this.prefix);
|
|
1431
1525
|
this.metadataRepo = new MetadataRepository(db, this.prefix);
|
|
1432
1526
|
this.embeddingService = new EmbeddingService(this.db, this.options, this.entryRepo, this.metadataRepo);
|
|
1433
1527
|
this.searchService = new SearchService(this.entryRepo);
|
|
@@ -1461,6 +1555,7 @@ var WikiMemory = class {
|
|
|
1461
1555
|
this.entryRepo,
|
|
1462
1556
|
this.taskRepo,
|
|
1463
1557
|
this.eventRepo,
|
|
1558
|
+
this.edgeRepo,
|
|
1464
1559
|
this.metadataRepo,
|
|
1465
1560
|
this.searchService,
|
|
1466
1561
|
this.jobManager,
|
|
@@ -1921,7 +2016,7 @@ function formatMemoryDump(dump) {
|
|
|
1921
2016
|
}
|
|
1922
2017
|
function factFrontmatter(f) {
|
|
1923
2018
|
return {
|
|
1924
|
-
type: "fact",
|
|
2019
|
+
type: f.okf_type ?? "fact",
|
|
1925
2020
|
title: f.title,
|
|
1926
2021
|
tags: f.tags,
|
|
1927
2022
|
timestamp: new Date(f.updated_at).toISOString(),
|
|
@@ -1939,7 +2034,7 @@ function factFrontmatter(f) {
|
|
|
1939
2034
|
}
|
|
1940
2035
|
function taskFrontmatter(t) {
|
|
1941
2036
|
return {
|
|
1942
|
-
type: "task",
|
|
2037
|
+
type: t.okf_type ?? "task",
|
|
1943
2038
|
title: t.description,
|
|
1944
2039
|
timestamp: new Date(t.updated_at).toISOString(),
|
|
1945
2040
|
id: t.id,
|
|
@@ -2014,6 +2109,227 @@ function formatOkfBundle(dump) {
|
|
|
2014
2109
|
});
|
|
2015
2110
|
return { files };
|
|
2016
2111
|
}
|
|
2112
|
+
var CONFIDENCE_VALUES = /* @__PURE__ */ new Set(["certain", "inferred", "tentative"]);
|
|
2113
|
+
var SOURCE_TYPES = /* @__PURE__ */ new Set([
|
|
2114
|
+
"user_stated",
|
|
2115
|
+
"librarian_inferred",
|
|
2116
|
+
"user_confirmed",
|
|
2117
|
+
"immutable_document"
|
|
2118
|
+
]);
|
|
2119
|
+
var TASK_STATUSES = /* @__PURE__ */ new Set(["pending", "in_progress", "done", "abandoned"]);
|
|
2120
|
+
var EVENT_TYPES = /* @__PURE__ */ new Set(["observation", "decision", "action", "outcome"]);
|
|
2121
|
+
function basenameMd(filePath) {
|
|
2122
|
+
const name = filePath.slice(filePath.lastIndexOf("/") + 1);
|
|
2123
|
+
return name.endsWith(".md") ? name.slice(0, -3) : name;
|
|
2124
|
+
}
|
|
2125
|
+
function isConceptFile(filePath) {
|
|
2126
|
+
if (!filePath.endsWith(".md")) return false;
|
|
2127
|
+
if (filePath.endsWith("/index.md") || filePath === "index.md") return false;
|
|
2128
|
+
if (filePath.endsWith("/log.md") || filePath === "log.md") return false;
|
|
2129
|
+
return true;
|
|
2130
|
+
}
|
|
2131
|
+
function isStructuralPath(filePath) {
|
|
2132
|
+
return filePath.endsWith("/index.md") || filePath === "index.md" || filePath.endsWith("/log.md") || filePath === "log.md";
|
|
2133
|
+
}
|
|
2134
|
+
function posixDirname(filePath) {
|
|
2135
|
+
const idx = filePath.lastIndexOf("/");
|
|
2136
|
+
return idx === -1 ? "" : filePath.slice(0, idx);
|
|
2137
|
+
}
|
|
2138
|
+
function resolveRelativePath(fromFile, linkPath) {
|
|
2139
|
+
const baseDir = posixDirname(fromFile);
|
|
2140
|
+
const segments = [...baseDir ? baseDir.split("/") : [], ...linkPath.split("/")];
|
|
2141
|
+
const resolved = [];
|
|
2142
|
+
for (const seg of segments) {
|
|
2143
|
+
if (seg === "" || seg === ".") continue;
|
|
2144
|
+
if (seg === "..") {
|
|
2145
|
+
resolved.pop();
|
|
2146
|
+
continue;
|
|
2147
|
+
}
|
|
2148
|
+
resolved.push(seg);
|
|
2149
|
+
}
|
|
2150
|
+
return resolved.join("/");
|
|
2151
|
+
}
|
|
2152
|
+
function addPathAliases(map, filePath, resolvedId) {
|
|
2153
|
+
map.set(filePath, resolvedId);
|
|
2154
|
+
const withoutDot = filePath.replace(/^\.\//, "");
|
|
2155
|
+
if (withoutDot !== filePath) map.set(withoutDot, resolvedId);
|
|
2156
|
+
const entityRelative = filePath.replace(/^entities\/[^/]+\//, "");
|
|
2157
|
+
if (entityRelative !== filePath) {
|
|
2158
|
+
map.set(entityRelative, resolvedId);
|
|
2159
|
+
map.set(`./${entityRelative}`, resolvedId);
|
|
2160
|
+
}
|
|
2161
|
+
}
|
|
2162
|
+
function lookupResolvedId(map, path) {
|
|
2163
|
+
const normalized = path.replace(/^\.\//, "");
|
|
2164
|
+
return map.get(path) ?? map.get(normalized) ?? map.get(`./${normalized}`);
|
|
2165
|
+
}
|
|
2166
|
+
function stripLinkSuffix(linkPath) {
|
|
2167
|
+
const hashIdx = linkPath.indexOf("#");
|
|
2168
|
+
const queryIdx = linkPath.indexOf("?");
|
|
2169
|
+
if (hashIdx === -1 && queryIdx === -1) return linkPath;
|
|
2170
|
+
const cut = hashIdx === -1 ? queryIdx : queryIdx === -1 ? hashIdx : Math.min(hashIdx, queryIdx);
|
|
2171
|
+
return linkPath.slice(0, cut);
|
|
2172
|
+
}
|
|
2173
|
+
function resolveRoute(filePath, frontmatterType, options) {
|
|
2174
|
+
if (options?.typeMapping && Object.prototype.hasOwnProperty.call(options.typeMapping, frontmatterType)) {
|
|
2175
|
+
return options.typeMapping[frontmatterType];
|
|
2176
|
+
}
|
|
2177
|
+
if (filePath.includes("/facts/")) return "fact";
|
|
2178
|
+
if (filePath.includes("/tasks/")) return "task";
|
|
2179
|
+
return options?.defaultSchema ?? "fact";
|
|
2180
|
+
}
|
|
2181
|
+
function parseFrontmatterTimestamp(value, fallback) {
|
|
2182
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
2183
|
+
if (typeof value === "string") {
|
|
2184
|
+
const parsed = Date.parse(value);
|
|
2185
|
+
if (Number.isFinite(parsed)) return parsed;
|
|
2186
|
+
}
|
|
2187
|
+
return fallback;
|
|
2188
|
+
}
|
|
2189
|
+
function unescapeLogSummary(summary) {
|
|
2190
|
+
return summary.replace(/\\\]/g, "]").replace(/\\\[/g, "[").replace(/\\\\/g, "\\");
|
|
2191
|
+
}
|
|
2192
|
+
var LOG_LINE_PATTERN = /^\(([^)]+)\)\s*(?:\[((?:\\.|[^\]])*)\]\(([^)]+)\)|(.+))$/;
|
|
2193
|
+
function parseLogEntryText(text) {
|
|
2194
|
+
const match = LOG_LINE_PATTERN.exec(text.trim());
|
|
2195
|
+
if (!match) return null;
|
|
2196
|
+
const [, rawType, linkedSummary, linkPath, plainSummary] = match;
|
|
2197
|
+
const event_type = EVENT_TYPES.has(rawType) ? rawType : "observation";
|
|
2198
|
+
if (linkPath) {
|
|
2199
|
+
return { event_type, summary: unescapeLogSummary(linkedSummary), linkPath };
|
|
2200
|
+
}
|
|
2201
|
+
return { event_type, summary: (plainSummary ?? "").trim() };
|
|
2202
|
+
}
|
|
2203
|
+
function frontmatterToFact(entityId, id, frontmatter, body, now) {
|
|
2204
|
+
const created_at = parseFrontmatterTimestamp(frontmatter.created_at, now);
|
|
2205
|
+
const updated_at = parseFrontmatterTimestamp(
|
|
2206
|
+
frontmatter.timestamp,
|
|
2207
|
+
parseFrontmatterTimestamp(frontmatter.updated_at, now)
|
|
2208
|
+
);
|
|
2209
|
+
return {
|
|
2210
|
+
id,
|
|
2211
|
+
entity_id: entityId,
|
|
2212
|
+
title: typeof frontmatter.title === "string" ? frontmatter.title : "",
|
|
2213
|
+
body,
|
|
2214
|
+
tags: Array.isArray(frontmatter.tags) ? frontmatter.tags.filter((t) => typeof t === "string") : [],
|
|
2215
|
+
confidence: CONFIDENCE_VALUES.has(String(frontmatter.confidence)) ? frontmatter.confidence : "tentative",
|
|
2216
|
+
source_type: SOURCE_TYPES.has(String(frontmatter.source_type)) ? frontmatter.source_type : "user_stated",
|
|
2217
|
+
source_hash: typeof frontmatter.source_hash === "string" ? frontmatter.source_hash : null,
|
|
2218
|
+
source_ref: typeof frontmatter.resource === "string" ? frontmatter.resource : null,
|
|
2219
|
+
created_at,
|
|
2220
|
+
updated_at,
|
|
2221
|
+
last_accessed_at: frontmatter.last_accessed_at != null ? parseFrontmatterTimestamp(frontmatter.last_accessed_at, now) : null,
|
|
2222
|
+
access_count: typeof frontmatter.access_count === "number" ? frontmatter.access_count : 0,
|
|
2223
|
+
deleted_at: frontmatter.deleted_at != null ? parseFrontmatterTimestamp(frontmatter.deleted_at, 0) : null,
|
|
2224
|
+
okf_type: frontmatter.type
|
|
2225
|
+
};
|
|
2226
|
+
}
|
|
2227
|
+
function frontmatterToTask(entityId, id, frontmatter, now) {
|
|
2228
|
+
const created_at = parseFrontmatterTimestamp(frontmatter.created_at, now);
|
|
2229
|
+
const updated_at = parseFrontmatterTimestamp(
|
|
2230
|
+
frontmatter.timestamp,
|
|
2231
|
+
parseFrontmatterTimestamp(frontmatter.updated_at, now)
|
|
2232
|
+
);
|
|
2233
|
+
return {
|
|
2234
|
+
id,
|
|
2235
|
+
entity_id: entityId,
|
|
2236
|
+
description: typeof frontmatter.title === "string" ? frontmatter.title : "",
|
|
2237
|
+
status: TASK_STATUSES.has(String(frontmatter.status)) ? frontmatter.status : "pending",
|
|
2238
|
+
priority: typeof frontmatter.priority === "number" ? frontmatter.priority : 0,
|
|
2239
|
+
created_at,
|
|
2240
|
+
updated_at,
|
|
2241
|
+
resolved_at: frontmatter.resolved_at != null ? parseFrontmatterTimestamp(frontmatter.resolved_at, now) : null,
|
|
2242
|
+
deleted_at: frontmatter.deleted_at != null ? parseFrontmatterTimestamp(frontmatter.deleted_at, 0) : null,
|
|
2243
|
+
okf_type: frontmatter.type
|
|
2244
|
+
};
|
|
2245
|
+
}
|
|
2246
|
+
function findLogMdPath(files) {
|
|
2247
|
+
return files.find((f) => f.path.endsWith("/log.md") || f.path === "log.md")?.path;
|
|
2248
|
+
}
|
|
2249
|
+
function parseOkfBundle(entityId, files, options) {
|
|
2250
|
+
const now = Date.now();
|
|
2251
|
+
const pathToResolvedId = /* @__PURE__ */ new Map();
|
|
2252
|
+
for (const file of files) {
|
|
2253
|
+
if (!isConceptFile(file.path)) continue;
|
|
2254
|
+
const { frontmatter } = parseConcept(file.content);
|
|
2255
|
+
const route = resolveRoute(file.path, frontmatter.type ?? "", options);
|
|
2256
|
+
if (route === "ignore") continue;
|
|
2257
|
+
const resolvedId = typeof frontmatter.id === "string" && frontmatter.id ? frontmatter.id : basenameMd(file.path);
|
|
2258
|
+
addPathAliases(pathToResolvedId, file.path, resolvedId);
|
|
2259
|
+
}
|
|
2260
|
+
const facts = [];
|
|
2261
|
+
const tasks = [];
|
|
2262
|
+
const edges = [];
|
|
2263
|
+
let logContent = null;
|
|
2264
|
+
const logMdPath = findLogMdPath(files);
|
|
2265
|
+
for (const file of files) {
|
|
2266
|
+
if (file.path.endsWith("/log.md") || file.path === "log.md") {
|
|
2267
|
+
logContent = file.content;
|
|
2268
|
+
continue;
|
|
2269
|
+
}
|
|
2270
|
+
if (!isConceptFile(file.path)) continue;
|
|
2271
|
+
const { frontmatter, body } = parseConcept(file.content);
|
|
2272
|
+
const route = resolveRoute(file.path, frontmatter.type ?? "", options);
|
|
2273
|
+
if (route === "ignore") continue;
|
|
2274
|
+
const resolvedId = typeof frontmatter.id === "string" && frontmatter.id ? frontmatter.id : basenameMd(file.path);
|
|
2275
|
+
if (route === "fact") {
|
|
2276
|
+
facts.push(frontmatterToFact(entityId, resolvedId, frontmatter, body, now));
|
|
2277
|
+
} else {
|
|
2278
|
+
tasks.push(frontmatterToTask(entityId, resolvedId, frontmatter, now));
|
|
2279
|
+
}
|
|
2280
|
+
const seenEdges = /* @__PURE__ */ new Set();
|
|
2281
|
+
for (const link of extractMarkdownLinks(body)) {
|
|
2282
|
+
const strippedPath = stripLinkSuffix(link.path);
|
|
2283
|
+
const directTargetId = lookupResolvedId(pathToResolvedId, strippedPath);
|
|
2284
|
+
const resolvedTargetPath = resolveRelativePath(file.path, strippedPath);
|
|
2285
|
+
if (isStructuralPath(strippedPath) || isStructuralPath(resolvedTargetPath)) continue;
|
|
2286
|
+
const targetId = directTargetId ?? lookupResolvedId(pathToResolvedId, resolvedTargetPath);
|
|
2287
|
+
if (!targetId) continue;
|
|
2288
|
+
const edgeKey = `${resolvedId}\0${targetId}\0${link.text}`;
|
|
2289
|
+
if (seenEdges.has(edgeKey)) continue;
|
|
2290
|
+
seenEdges.add(edgeKey);
|
|
2291
|
+
edges.push({
|
|
2292
|
+
id: generateId(),
|
|
2293
|
+
entity_id: entityId,
|
|
2294
|
+
source_id: resolvedId,
|
|
2295
|
+
target_id: targetId,
|
|
2296
|
+
edge_type: link.text,
|
|
2297
|
+
created_at: now
|
|
2298
|
+
});
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
2301
|
+
const events = [];
|
|
2302
|
+
if (logContent != null) {
|
|
2303
|
+
const logPath = logMdPath ?? `entities/${entityId}/log.md`;
|
|
2304
|
+
for (const entry of parseLogMd(logContent)) {
|
|
2305
|
+
const parsed = parseLogEntryText(entry.text);
|
|
2306
|
+
if (!parsed) continue;
|
|
2307
|
+
let related_entry_id = null;
|
|
2308
|
+
if (parsed.linkPath) {
|
|
2309
|
+
const targetPath = resolveRelativePath(logPath, stripLinkSuffix(parsed.linkPath));
|
|
2310
|
+
if (!isStructuralPath(targetPath) && targetPath.includes("/facts/")) {
|
|
2311
|
+
related_entry_id = lookupResolvedId(pathToResolvedId, targetPath) ?? null;
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
const created_at = (/* @__PURE__ */ new Date(`${entry.date}T00:00:00.000Z`)).getTime();
|
|
2315
|
+
if (!Number.isFinite(created_at)) continue;
|
|
2316
|
+
events.push({
|
|
2317
|
+
id: generateId("evt_"),
|
|
2318
|
+
entity_id: entityId,
|
|
2319
|
+
event_type: parsed.event_type,
|
|
2320
|
+
summary: parsed.summary,
|
|
2321
|
+
related_entry_id,
|
|
2322
|
+
created_at
|
|
2323
|
+
});
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
2326
|
+
return {
|
|
2327
|
+
generatedAt: now,
|
|
2328
|
+
entities: {
|
|
2329
|
+
[entityId]: { facts, tasks, events, edges }
|
|
2330
|
+
}
|
|
2331
|
+
};
|
|
2332
|
+
}
|
|
2017
2333
|
|
|
2018
2334
|
// src/librarianPrompt.ts
|
|
2019
2335
|
var DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT = `You are a careful memory synthesis assistant.
|
|
@@ -2059,6 +2375,6 @@ function createWiki(db, options) {
|
|
|
2059
2375
|
return new WikiMemory(db, options);
|
|
2060
2376
|
}
|
|
2061
2377
|
|
|
2062
|
-
export { DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT, WikiMemory, createWiki, formatContext, formatMemoryDump, formatOkfBundle, hydrateLibrarianPrompt, mapLibrarianOptionsToReadOptions, validateLibrarianPromptTemplate };
|
|
2378
|
+
export { DEFAULT_LIBRARIAN_SYNTHESIS_PROMPT, WikiMemory, createWiki, formatContext, formatMemoryDump, formatOkfBundle, hydrateLibrarianPrompt, mapLibrarianOptionsToReadOptions, parseOkfBundle, validateLibrarianPromptTemplate };
|
|
2063
2379
|
//# sourceMappingURL=index.mjs.map
|
|
2064
2380
|
//# sourceMappingURL=index.mjs.map
|