@fortemi/core 2026.6.6 → 2026.6.7
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/index.d.ts +121 -31
- package/dist/index.js +423 -55
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2000,6 +2000,55 @@ var SearchRepository = class {
|
|
|
2000
2000
|
return tagMap;
|
|
2001
2001
|
}
|
|
2002
2002
|
};
|
|
2003
|
+
|
|
2004
|
+
// src/repositories/links-repository.ts
|
|
2005
|
+
var LinksRepository = class {
|
|
2006
|
+
constructor(db) {
|
|
2007
|
+
this.db = db;
|
|
2008
|
+
}
|
|
2009
|
+
async create(sourceNoteId, targetNoteId, linkType = "related") {
|
|
2010
|
+
const existing = await this.db.query(
|
|
2011
|
+
`SELECT * FROM link WHERE source_note_id = $1 AND target_note_id = $2 AND link_type = $3 AND deleted_at IS NULL`,
|
|
2012
|
+
[sourceNoteId, targetNoteId, linkType]
|
|
2013
|
+
);
|
|
2014
|
+
if (existing.rows.length > 0) return existing.rows[0];
|
|
2015
|
+
const id = generateId();
|
|
2016
|
+
await this.db.query(
|
|
2017
|
+
`INSERT INTO link (id, source_note_id, target_note_id, link_type) VALUES ($1, $2, $3, $4)`,
|
|
2018
|
+
[id, sourceNoteId, targetNoteId, linkType]
|
|
2019
|
+
);
|
|
2020
|
+
return this.get(id);
|
|
2021
|
+
}
|
|
2022
|
+
async get(id) {
|
|
2023
|
+
const result = await this.db.query(
|
|
2024
|
+
`SELECT * FROM link WHERE id = $1`,
|
|
2025
|
+
[id]
|
|
2026
|
+
);
|
|
2027
|
+
if (result.rows.length === 0) throw new Error(`Link not found: ${id}`);
|
|
2028
|
+
return result.rows[0];
|
|
2029
|
+
}
|
|
2030
|
+
async listForNote(noteId) {
|
|
2031
|
+
const outbound = await this.db.query(
|
|
2032
|
+
`SELECT * FROM link WHERE source_note_id = $1 AND deleted_at IS NULL`,
|
|
2033
|
+
[noteId]
|
|
2034
|
+
);
|
|
2035
|
+
const inbound = await this.db.query(
|
|
2036
|
+
`SELECT * FROM link WHERE target_note_id = $1 AND deleted_at IS NULL`,
|
|
2037
|
+
[noteId]
|
|
2038
|
+
);
|
|
2039
|
+
return { outbound: outbound.rows, inbound: inbound.rows };
|
|
2040
|
+
}
|
|
2041
|
+
async getBacklinks(noteId) {
|
|
2042
|
+
const result = await this.db.query(
|
|
2043
|
+
`SELECT source_note_id FROM link WHERE target_note_id = $1 AND deleted_at IS NULL`,
|
|
2044
|
+
[noteId]
|
|
2045
|
+
);
|
|
2046
|
+
return result.rows.map((r) => r.source_note_id);
|
|
2047
|
+
}
|
|
2048
|
+
async delete(id) {
|
|
2049
|
+
await this.db.query(`UPDATE link SET deleted_at = now() WHERE id = $1`, [id]);
|
|
2050
|
+
}
|
|
2051
|
+
};
|
|
2003
2052
|
var CaptureKnowledgeInputSchema = z.object({
|
|
2004
2053
|
action: z.enum(["create", "bulk_create", "from_template"]),
|
|
2005
2054
|
// For create
|
|
@@ -2163,10 +2212,129 @@ function searchResultToBackend(r) {
|
|
|
2163
2212
|
updatedAt: toIso(r.updated_at)
|
|
2164
2213
|
};
|
|
2165
2214
|
}
|
|
2215
|
+
function remoteNoteToBackend(n) {
|
|
2216
|
+
return {
|
|
2217
|
+
id: n.id,
|
|
2218
|
+
title: n.title,
|
|
2219
|
+
tags: n.tags ?? [],
|
|
2220
|
+
createdAt: n.createdAt ?? n.created_at ?? "",
|
|
2221
|
+
updatedAt: n.updatedAt ?? n.updated_at ?? "",
|
|
2222
|
+
source: n.source,
|
|
2223
|
+
starred: n.starred ?? n.is_starred,
|
|
2224
|
+
archived: n.archived ?? n.is_archived
|
|
2225
|
+
};
|
|
2226
|
+
}
|
|
2227
|
+
function remoteFullToBackend(n) {
|
|
2228
|
+
return {
|
|
2229
|
+
...remoteNoteToBackend(n),
|
|
2230
|
+
content: n.content ?? n.current?.content ?? ""
|
|
2231
|
+
};
|
|
2232
|
+
}
|
|
2233
|
+
function linkToBackend(link) {
|
|
2234
|
+
return {
|
|
2235
|
+
id: link.id,
|
|
2236
|
+
fromNoteId: link.source_note_id,
|
|
2237
|
+
toNoteId: link.target_note_id,
|
|
2238
|
+
kind: link.link_type,
|
|
2239
|
+
score: link.confidence,
|
|
2240
|
+
createdAt: toIso(link.created_at)
|
|
2241
|
+
};
|
|
2242
|
+
}
|
|
2243
|
+
function shardLinkToBackend(link) {
|
|
2244
|
+
return {
|
|
2245
|
+
id: link.id,
|
|
2246
|
+
fromNoteId: link.from_note_id,
|
|
2247
|
+
toNoteId: link.to_note_id,
|
|
2248
|
+
kind: link.kind,
|
|
2249
|
+
score: link.score,
|
|
2250
|
+
createdAt: link.created_at,
|
|
2251
|
+
...link.metadata ? { metadata: link.metadata } : {}
|
|
2252
|
+
};
|
|
2253
|
+
}
|
|
2254
|
+
function conceptToBackend(concept) {
|
|
2255
|
+
const altLabels = typeof concept.alt_labels === "string" ? JSON.parse(concept.alt_labels) : concept.alt_labels;
|
|
2256
|
+
return {
|
|
2257
|
+
id: concept.id,
|
|
2258
|
+
schemeId: concept.scheme_id,
|
|
2259
|
+
prefLabel: concept.pref_label,
|
|
2260
|
+
altLabels,
|
|
2261
|
+
definition: concept.definition,
|
|
2262
|
+
createdAt: toIso(concept.created_at),
|
|
2263
|
+
updatedAt: toIso(concept.updated_at)
|
|
2264
|
+
};
|
|
2265
|
+
}
|
|
2266
|
+
function shardConceptToBackend(concept) {
|
|
2267
|
+
return conceptToBackend(concept);
|
|
2268
|
+
}
|
|
2269
|
+
function parseAttributes(attributes) {
|
|
2270
|
+
if (attributes === null) return null;
|
|
2271
|
+
if (typeof attributes === "string") return JSON.parse(attributes);
|
|
2272
|
+
return attributes;
|
|
2273
|
+
}
|
|
2274
|
+
function provenanceToBackend(edge) {
|
|
2275
|
+
return {
|
|
2276
|
+
id: edge.id,
|
|
2277
|
+
entityType: edge.entity_type,
|
|
2278
|
+
entityId: edge.entity_id,
|
|
2279
|
+
activity: edge.activity,
|
|
2280
|
+
agent: edge.agent,
|
|
2281
|
+
startedAt: toIso(edge.started_at),
|
|
2282
|
+
endedAt: edge.ended_at ? toIso(edge.ended_at) : null,
|
|
2283
|
+
attributes: parseAttributes(edge.attributes)
|
|
2284
|
+
};
|
|
2285
|
+
}
|
|
2286
|
+
function shardProvenanceToBackend(edge) {
|
|
2287
|
+
return provenanceToBackend(edge);
|
|
2288
|
+
}
|
|
2289
|
+
function remoteLinkToBackend(link) {
|
|
2290
|
+
return {
|
|
2291
|
+
id: link.id,
|
|
2292
|
+
fromNoteId: link.fromNoteId ?? link.from_note_id ?? link.source_note_id ?? "",
|
|
2293
|
+
toNoteId: link.toNoteId ?? link.to_note_id ?? link.target_note_id ?? "",
|
|
2294
|
+
kind: link.kind ?? link.link_type ?? "",
|
|
2295
|
+
score: link.score ?? link.confidence ?? null,
|
|
2296
|
+
createdAt: link.createdAt ?? link.created_at ?? "",
|
|
2297
|
+
...link.metadata ? { metadata: link.metadata } : {}
|
|
2298
|
+
};
|
|
2299
|
+
}
|
|
2300
|
+
function remoteConceptToBackend(concept) {
|
|
2301
|
+
if ("schemeId" in concept) return concept;
|
|
2302
|
+
return conceptToBackend(concept);
|
|
2303
|
+
}
|
|
2304
|
+
function remoteProvenanceToBackend(edge) {
|
|
2305
|
+
if ("entityType" in edge) return edge;
|
|
2306
|
+
return provenanceToBackend(edge);
|
|
2307
|
+
}
|
|
2166
2308
|
function createPGliteBackend(db, options = {}) {
|
|
2167
2309
|
const semanticAvailable = options.semanticAvailable ?? false;
|
|
2168
2310
|
const notes = new NotesRepository(db);
|
|
2169
2311
|
const search = new SearchRepository(db, semanticAvailable);
|
|
2312
|
+
const links = new LinksRepository(db);
|
|
2313
|
+
async function linksOf(id) {
|
|
2314
|
+
const result = await links.listForNote(id);
|
|
2315
|
+
return [...result.outbound, ...result.inbound].map(linkToBackend);
|
|
2316
|
+
}
|
|
2317
|
+
async function conceptsOf(id) {
|
|
2318
|
+
const result = await db.query(
|
|
2319
|
+
`SELECT c.*
|
|
2320
|
+
FROM skos_concept c
|
|
2321
|
+
INNER JOIN note_skos_tag nst ON nst.concept_id = c.id
|
|
2322
|
+
WHERE nst.note_id = $1 AND c.deleted_at IS NULL
|
|
2323
|
+
ORDER BY c.pref_label`,
|
|
2324
|
+
[id]
|
|
2325
|
+
);
|
|
2326
|
+
return result.rows.map(conceptToBackend);
|
|
2327
|
+
}
|
|
2328
|
+
async function provenanceOf(id) {
|
|
2329
|
+
const result = await db.query(
|
|
2330
|
+
`SELECT *
|
|
2331
|
+
FROM provenance_edge
|
|
2332
|
+
WHERE entity_type = 'note' AND entity_id = $1
|
|
2333
|
+
ORDER BY started_at`,
|
|
2334
|
+
[id]
|
|
2335
|
+
);
|
|
2336
|
+
return result.rows.map(provenanceToBackend);
|
|
2337
|
+
}
|
|
2170
2338
|
return {
|
|
2171
2339
|
id: options.id ?? "pglite",
|
|
2172
2340
|
capabilities: {
|
|
@@ -2210,16 +2378,155 @@ function createPGliteBackend(db, options = {}) {
|
|
|
2210
2378
|
async getNoteFull(id) {
|
|
2211
2379
|
try {
|
|
2212
2380
|
const f = await notes.get(id);
|
|
2213
|
-
|
|
2381
|
+
const [noteLinks, concepts, provenance] = await Promise.all([
|
|
2382
|
+
linksOf(id),
|
|
2383
|
+
conceptsOf(id),
|
|
2384
|
+
provenanceOf(id)
|
|
2385
|
+
]);
|
|
2386
|
+
return { ...summaryToBackend(f), content: f.current.content, links: noteLinks, concepts, provenance };
|
|
2214
2387
|
} catch {
|
|
2215
2388
|
return null;
|
|
2216
2389
|
}
|
|
2217
2390
|
},
|
|
2391
|
+
linksOf,
|
|
2392
|
+
conceptsOf,
|
|
2393
|
+
provenanceOf,
|
|
2218
2394
|
async manageNote(input) {
|
|
2219
2395
|
return manageNote(db, input);
|
|
2220
2396
|
}
|
|
2221
2397
|
};
|
|
2222
2398
|
}
|
|
2399
|
+
var DEFAULT_REMOTE_PATHS = {
|
|
2400
|
+
notes: "/api/v1/notes",
|
|
2401
|
+
note: "/api/v1/notes/:id",
|
|
2402
|
+
search: "/api/v1/search",
|
|
2403
|
+
links: "/api/v1/notes/:id/links",
|
|
2404
|
+
concepts: "/api/v1/notes/:id/concepts",
|
|
2405
|
+
provenance: "/api/v1/notes/:id/provenance",
|
|
2406
|
+
manageNote: "/api/v1/tools/manage-note",
|
|
2407
|
+
semantic: "/api/v1/semantic/search"
|
|
2408
|
+
};
|
|
2409
|
+
function remotePath(template, id) {
|
|
2410
|
+
return id ? template.replace(":id", encodeURIComponent(id)) : template;
|
|
2411
|
+
}
|
|
2412
|
+
function remoteUrl(baseUrl, path, params) {
|
|
2413
|
+
const url = new URL(path, baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`);
|
|
2414
|
+
for (const [key, value] of Object.entries(params ?? {})) {
|
|
2415
|
+
if (value === void 0) continue;
|
|
2416
|
+
if (Array.isArray(value)) {
|
|
2417
|
+
for (const item of value) url.searchParams.append(key, String(item));
|
|
2418
|
+
} else {
|
|
2419
|
+
url.searchParams.set(key, String(value));
|
|
2420
|
+
}
|
|
2421
|
+
}
|
|
2422
|
+
return url.toString();
|
|
2423
|
+
}
|
|
2424
|
+
async function remoteHeaders(config, json2 = false) {
|
|
2425
|
+
const configured = typeof config.headers === "function" ? await config.headers() : config.headers;
|
|
2426
|
+
const headers = new Headers(configured);
|
|
2427
|
+
if (config.authToken) headers.set("Authorization", `Bearer ${config.authToken}`);
|
|
2428
|
+
if (json2) headers.set("Content-Type", "application/json");
|
|
2429
|
+
return headers;
|
|
2430
|
+
}
|
|
2431
|
+
async function remoteJson(config, path, init = {}) {
|
|
2432
|
+
const fetchImpl = config.fetchImpl ?? globalThis.fetch;
|
|
2433
|
+
const response = await fetchImpl(remoteUrl(config.baseUrl, path), init);
|
|
2434
|
+
if (!response.ok) {
|
|
2435
|
+
throw new Error(`Remote backend request failed (${response.status}): ${path}`);
|
|
2436
|
+
}
|
|
2437
|
+
return response.json();
|
|
2438
|
+
}
|
|
2439
|
+
function createRemoteBackend(config) {
|
|
2440
|
+
const paths = { ...DEFAULT_REMOTE_PATHS, ...config.paths };
|
|
2441
|
+
async function getJson(path, params) {
|
|
2442
|
+
return remoteJson(config, remoteUrl(config.baseUrl, path, params), {
|
|
2443
|
+
method: "GET",
|
|
2444
|
+
headers: await remoteHeaders(config)
|
|
2445
|
+
});
|
|
2446
|
+
}
|
|
2447
|
+
async function postJson(path, body) {
|
|
2448
|
+
return remoteJson(config, path, {
|
|
2449
|
+
method: "POST",
|
|
2450
|
+
headers: await remoteHeaders(config, true),
|
|
2451
|
+
body: JSON.stringify(body)
|
|
2452
|
+
});
|
|
2453
|
+
}
|
|
2454
|
+
async function getNoteFull(id) {
|
|
2455
|
+
try {
|
|
2456
|
+
const note = await getJson(remotePath(paths.note, id), { full: true });
|
|
2457
|
+
const [links, concepts, provenance] = await Promise.all([
|
|
2458
|
+
linksOf(id),
|
|
2459
|
+
conceptsOf(id),
|
|
2460
|
+
provenanceOf(id)
|
|
2461
|
+
]);
|
|
2462
|
+
return { ...remoteFullToBackend(note), links, concepts, provenance };
|
|
2463
|
+
} catch {
|
|
2464
|
+
return null;
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
async function linksOf(id) {
|
|
2468
|
+
const links = await getJson(remotePath(paths.links, id));
|
|
2469
|
+
return links.map(remoteLinkToBackend);
|
|
2470
|
+
}
|
|
2471
|
+
async function conceptsOf(id) {
|
|
2472
|
+
const concepts = await getJson(
|
|
2473
|
+
remotePath(paths.concepts, id)
|
|
2474
|
+
);
|
|
2475
|
+
return concepts.map(remoteConceptToBackend);
|
|
2476
|
+
}
|
|
2477
|
+
async function provenanceOf(id) {
|
|
2478
|
+
const edges = await getJson(
|
|
2479
|
+
remotePath(paths.provenance, id)
|
|
2480
|
+
);
|
|
2481
|
+
return edges.map(remoteProvenanceToBackend);
|
|
2482
|
+
}
|
|
2483
|
+
return {
|
|
2484
|
+
id: config.id ?? "remote-server",
|
|
2485
|
+
capabilities: {
|
|
2486
|
+
read: true,
|
|
2487
|
+
write: true,
|
|
2488
|
+
merge: true,
|
|
2489
|
+
multiUser: true,
|
|
2490
|
+
semantic: "server",
|
|
2491
|
+
startupCost: "network"
|
|
2492
|
+
},
|
|
2493
|
+
async listNotes(o) {
|
|
2494
|
+
const result = await getJson(paths.notes, o ? { ...o } : void 0);
|
|
2495
|
+
return { items: result.items.map(remoteNoteToBackend), total: result.total };
|
|
2496
|
+
},
|
|
2497
|
+
async getNote(id) {
|
|
2498
|
+
try {
|
|
2499
|
+
return remoteNoteToBackend(await getJson(remotePath(paths.note, id)));
|
|
2500
|
+
} catch {
|
|
2501
|
+
return null;
|
|
2502
|
+
}
|
|
2503
|
+
},
|
|
2504
|
+
async search(query, o) {
|
|
2505
|
+
const result = await getJson(paths.search, { query, ...o });
|
|
2506
|
+
if (result.hits) return { hits: result.hits, total: result.total, facets: result.facets };
|
|
2507
|
+
return {
|
|
2508
|
+
hits: (result.results ?? []).map((hit) => ({
|
|
2509
|
+
note: remoteNoteToBackend(hit.note ?? hit),
|
|
2510
|
+
rank: hit.rank,
|
|
2511
|
+
snippet: hit.snippet
|
|
2512
|
+
})),
|
|
2513
|
+
total: result.total,
|
|
2514
|
+
facets: result.facets
|
|
2515
|
+
};
|
|
2516
|
+
},
|
|
2517
|
+
getNoteFull,
|
|
2518
|
+
linksOf,
|
|
2519
|
+
conceptsOf,
|
|
2520
|
+
provenanceOf,
|
|
2521
|
+
async semantic(query, k) {
|
|
2522
|
+
const result = await getJson(paths.semantic, { query, k });
|
|
2523
|
+
return result.hits;
|
|
2524
|
+
},
|
|
2525
|
+
async manageNote(input) {
|
|
2526
|
+
return postJson(paths.manageNote, input);
|
|
2527
|
+
}
|
|
2528
|
+
};
|
|
2529
|
+
}
|
|
2223
2530
|
function shardNoteToBackend(n) {
|
|
2224
2531
|
return {
|
|
2225
2532
|
id: n.id,
|
|
@@ -2266,9 +2573,21 @@ function createShardBackend(reader, options = {}) {
|
|
|
2266
2573
|
if (!f) return null;
|
|
2267
2574
|
return {
|
|
2268
2575
|
...shardNoteToBackend(f.note),
|
|
2269
|
-
content: f.note.revised_content ?? f.note.original_content
|
|
2576
|
+
content: f.note.revised_content ?? f.note.original_content,
|
|
2577
|
+
links: f.links.map(shardLinkToBackend),
|
|
2578
|
+
concepts: f.concepts.map(shardConceptToBackend),
|
|
2579
|
+
provenance: f.provenance.map(shardProvenanceToBackend)
|
|
2270
2580
|
};
|
|
2271
2581
|
},
|
|
2582
|
+
async linksOf(id) {
|
|
2583
|
+
return (await reader.linksOf(id)).map(shardLinkToBackend);
|
|
2584
|
+
},
|
|
2585
|
+
async conceptsOf(id) {
|
|
2586
|
+
return (await reader.conceptsOf(id)).map(shardConceptToBackend);
|
|
2587
|
+
},
|
|
2588
|
+
async provenanceOf(id) {
|
|
2589
|
+
return (await reader.provenanceOf(id)).map(shardProvenanceToBackend);
|
|
2590
|
+
},
|
|
2272
2591
|
async semantic(query, k) {
|
|
2273
2592
|
const r = await reader.semantic(query, k);
|
|
2274
2593
|
return r.map(({ note, score }) => ({ note: shardNoteToBackend(note), rank: score }));
|
|
@@ -3996,55 +4315,6 @@ var CollectionsRepository = class {
|
|
|
3996
4315
|
}
|
|
3997
4316
|
};
|
|
3998
4317
|
|
|
3999
|
-
// src/repositories/links-repository.ts
|
|
4000
|
-
var LinksRepository = class {
|
|
4001
|
-
constructor(db) {
|
|
4002
|
-
this.db = db;
|
|
4003
|
-
}
|
|
4004
|
-
async create(sourceNoteId, targetNoteId, linkType = "related") {
|
|
4005
|
-
const existing = await this.db.query(
|
|
4006
|
-
`SELECT * FROM link WHERE source_note_id = $1 AND target_note_id = $2 AND link_type = $3 AND deleted_at IS NULL`,
|
|
4007
|
-
[sourceNoteId, targetNoteId, linkType]
|
|
4008
|
-
);
|
|
4009
|
-
if (existing.rows.length > 0) return existing.rows[0];
|
|
4010
|
-
const id = generateId();
|
|
4011
|
-
await this.db.query(
|
|
4012
|
-
`INSERT INTO link (id, source_note_id, target_note_id, link_type) VALUES ($1, $2, $3, $4)`,
|
|
4013
|
-
[id, sourceNoteId, targetNoteId, linkType]
|
|
4014
|
-
);
|
|
4015
|
-
return this.get(id);
|
|
4016
|
-
}
|
|
4017
|
-
async get(id) {
|
|
4018
|
-
const result = await this.db.query(
|
|
4019
|
-
`SELECT * FROM link WHERE id = $1`,
|
|
4020
|
-
[id]
|
|
4021
|
-
);
|
|
4022
|
-
if (result.rows.length === 0) throw new Error(`Link not found: ${id}`);
|
|
4023
|
-
return result.rows[0];
|
|
4024
|
-
}
|
|
4025
|
-
async listForNote(noteId) {
|
|
4026
|
-
const outbound = await this.db.query(
|
|
4027
|
-
`SELECT * FROM link WHERE source_note_id = $1 AND deleted_at IS NULL`,
|
|
4028
|
-
[noteId]
|
|
4029
|
-
);
|
|
4030
|
-
const inbound = await this.db.query(
|
|
4031
|
-
`SELECT * FROM link WHERE target_note_id = $1 AND deleted_at IS NULL`,
|
|
4032
|
-
[noteId]
|
|
4033
|
-
);
|
|
4034
|
-
return { outbound: outbound.rows, inbound: inbound.rows };
|
|
4035
|
-
}
|
|
4036
|
-
async getBacklinks(noteId) {
|
|
4037
|
-
const result = await this.db.query(
|
|
4038
|
-
`SELECT source_note_id FROM link WHERE target_note_id = $1 AND deleted_at IS NULL`,
|
|
4039
|
-
[noteId]
|
|
4040
|
-
);
|
|
4041
|
-
return result.rows.map((r) => r.source_note_id);
|
|
4042
|
-
}
|
|
4043
|
-
async delete(id) {
|
|
4044
|
-
await this.db.query(`UPDATE link SET deleted_at = now() WHERE id = $1`, [id]);
|
|
4045
|
-
}
|
|
4046
|
-
};
|
|
4047
|
-
|
|
4048
4318
|
// src/repositories/skos-repository.ts
|
|
4049
4319
|
var SkosRepository = class {
|
|
4050
4320
|
constructor(db) {
|
|
@@ -4118,6 +4388,74 @@ var SkosRepository = class {
|
|
|
4118
4388
|
);
|
|
4119
4389
|
return result.rows;
|
|
4120
4390
|
}
|
|
4391
|
+
// ── Note tagging ───────────────────────────────────────────────────────────
|
|
4392
|
+
async tagNote(noteId, conceptId) {
|
|
4393
|
+
const existing = await this.db.query(
|
|
4394
|
+
`SELECT * FROM note_skos_tag WHERE note_id = $1 AND concept_id = $2`,
|
|
4395
|
+
[noteId, conceptId]
|
|
4396
|
+
);
|
|
4397
|
+
if (existing.rows.length > 0) return existing.rows[0];
|
|
4398
|
+
const id = generateId();
|
|
4399
|
+
await this.db.query(
|
|
4400
|
+
`INSERT INTO note_skos_tag (id, note_id, concept_id) VALUES ($1, $2, $3)`,
|
|
4401
|
+
[id, noteId, conceptId]
|
|
4402
|
+
);
|
|
4403
|
+
const result = await this.db.query(`SELECT * FROM note_skos_tag WHERE id = $1`, [id]);
|
|
4404
|
+
return result.rows[0];
|
|
4405
|
+
}
|
|
4406
|
+
async untagNote(noteId, conceptId) {
|
|
4407
|
+
await this.db.query(
|
|
4408
|
+
`DELETE FROM note_skos_tag WHERE note_id = $1 AND concept_id = $2`,
|
|
4409
|
+
[noteId, conceptId]
|
|
4410
|
+
);
|
|
4411
|
+
}
|
|
4412
|
+
async conceptsForNote(noteId) {
|
|
4413
|
+
const result = await this.db.query(
|
|
4414
|
+
`SELECT c.*
|
|
4415
|
+
FROM skos_concept c
|
|
4416
|
+
INNER JOIN note_skos_tag nst ON nst.concept_id = c.id
|
|
4417
|
+
WHERE nst.note_id = $1 AND c.deleted_at IS NULL
|
|
4418
|
+
ORDER BY c.pref_label`,
|
|
4419
|
+
[noteId]
|
|
4420
|
+
);
|
|
4421
|
+
return result.rows;
|
|
4422
|
+
}
|
|
4423
|
+
};
|
|
4424
|
+
|
|
4425
|
+
// src/repositories/provenance-repository.ts
|
|
4426
|
+
var ProvenanceRepository = class {
|
|
4427
|
+
constructor(db) {
|
|
4428
|
+
this.db = db;
|
|
4429
|
+
}
|
|
4430
|
+
async recordProvenance(entityType, entityId, input) {
|
|
4431
|
+
const id = generateId();
|
|
4432
|
+
await this.db.query(
|
|
4433
|
+
`INSERT INTO provenance_edge (id, entity_type, entity_id, activity, agent, started_at, ended_at, attributes)
|
|
4434
|
+
VALUES ($1, $2, $3, $4, $5, COALESCE($6, now()), $7, $8)`,
|
|
4435
|
+
[
|
|
4436
|
+
id,
|
|
4437
|
+
entityType,
|
|
4438
|
+
entityId,
|
|
4439
|
+
input.activity,
|
|
4440
|
+
input.agent,
|
|
4441
|
+
input.startedAt ?? null,
|
|
4442
|
+
input.endedAt ?? null,
|
|
4443
|
+
input.attributes === void 0 ? null : JSON.stringify(input.attributes)
|
|
4444
|
+
]
|
|
4445
|
+
);
|
|
4446
|
+
const result = await this.db.query(`SELECT * FROM provenance_edge WHERE id = $1`, [id]);
|
|
4447
|
+
return result.rows[0];
|
|
4448
|
+
}
|
|
4449
|
+
async forEntity(entityType, entityId) {
|
|
4450
|
+
const result = await this.db.query(
|
|
4451
|
+
`SELECT *
|
|
4452
|
+
FROM provenance_edge
|
|
4453
|
+
WHERE entity_type = $1 AND entity_id = $2
|
|
4454
|
+
ORDER BY started_at`,
|
|
4455
|
+
[entityType, entityId]
|
|
4456
|
+
);
|
|
4457
|
+
return result.rows;
|
|
4458
|
+
}
|
|
4121
4459
|
};
|
|
4122
4460
|
|
|
4123
4461
|
// src/tools/capture-knowledge.ts
|
|
@@ -7374,6 +7712,8 @@ var ShardReaderImpl = class {
|
|
|
7374
7712
|
links = null;
|
|
7375
7713
|
noteSkos = null;
|
|
7376
7714
|
concepts = null;
|
|
7715
|
+
relations = null;
|
|
7716
|
+
provenanceEdges = null;
|
|
7377
7717
|
matchCache = /* @__PURE__ */ new Map();
|
|
7378
7718
|
maxCachedMatches;
|
|
7379
7719
|
semanticPrepared = false;
|
|
@@ -7512,11 +7852,37 @@ var ShardReaderImpl = class {
|
|
|
7512
7852
|
}
|
|
7513
7853
|
return out;
|
|
7514
7854
|
}
|
|
7855
|
+
async loadRelations() {
|
|
7856
|
+
if (!this.relations) {
|
|
7857
|
+
this.relations = parseJsonlBytes(await this.store.read("skos_relations.jsonl"));
|
|
7858
|
+
}
|
|
7859
|
+
return this.relations;
|
|
7860
|
+
}
|
|
7861
|
+
async relationsOf(conceptId) {
|
|
7862
|
+
const relations = await this.loadRelations();
|
|
7863
|
+
return relations.filter(
|
|
7864
|
+
(relation) => relation.source_concept_id === conceptId || relation.target_concept_id === conceptId
|
|
7865
|
+
);
|
|
7866
|
+
}
|
|
7867
|
+
async loadProvenanceEdges() {
|
|
7868
|
+
if (!this.provenanceEdges) {
|
|
7869
|
+
this.provenanceEdges = parseJsonlBytes(await this.store.read("provenance_edges.jsonl"));
|
|
7870
|
+
}
|
|
7871
|
+
return this.provenanceEdges;
|
|
7872
|
+
}
|
|
7873
|
+
async provenanceOf(id) {
|
|
7874
|
+
const edges = await this.loadProvenanceEdges();
|
|
7875
|
+
return edges.filter((edge) => edge.entity_type === "note" && edge.entity_id === id).sort((a, b) => a.started_at.localeCompare(b.started_at));
|
|
7876
|
+
}
|
|
7515
7877
|
async getNoteFull(id) {
|
|
7516
7878
|
const note = await this.getNote(id);
|
|
7517
7879
|
if (!note) return null;
|
|
7518
|
-
const [links, concepts] = await Promise.all([
|
|
7519
|
-
|
|
7880
|
+
const [links, concepts, provenance] = await Promise.all([
|
|
7881
|
+
this.linksOf(id),
|
|
7882
|
+
this.conceptsOf(id),
|
|
7883
|
+
this.provenanceOf(id)
|
|
7884
|
+
]);
|
|
7885
|
+
return { note, links, concepts, provenance };
|
|
7520
7886
|
}
|
|
7521
7887
|
async semantic(query, k = 10) {
|
|
7522
7888
|
const provider = this.options.semantic;
|
|
@@ -7542,6 +7908,8 @@ var ShardReaderImpl = class {
|
|
|
7542
7908
|
this.links = null;
|
|
7543
7909
|
this.noteSkos = null;
|
|
7544
7910
|
this.concepts = null;
|
|
7911
|
+
this.relations = null;
|
|
7912
|
+
this.provenanceEdges = null;
|
|
7545
7913
|
}
|
|
7546
7914
|
};
|
|
7547
7915
|
async function openShard(source, options = {}) {
|
|
@@ -8484,8 +8852,8 @@ function communityIdsFor(item, options) {
|
|
|
8484
8852
|
}
|
|
8485
8853
|
|
|
8486
8854
|
// src/index.ts
|
|
8487
|
-
var VERSION = "2026.6.
|
|
8855
|
+
var VERSION = "2026.6.7";
|
|
8488
8856
|
|
|
8489
|
-
export { AIWG_SCAN_REQUIRED_FIELDS, ArchiveManager, AttachmentsRepository, CURRENT_MIGRATION_HEAD, CURRENT_SHARD_VERSION, CapabilityManager, CaptureKnowledgeInputSchema, CollectionsRepository, CommunitiesRepository, DB_SNAPSHOT_SCHEMA_VERSION, DbSnapshotVersionError, EMBED_REQUEST_KIND, EMBED_RESPONSE_KIND, EmbeddingSetsRepository, FallbackRouter, FortemiToolManifest, GetNoteInputSchema, GraphRepository, JOB_CAPABILITIES, JOB_PRIORITIES, JobQueueWorker, LOCAL_ENDPOINTS, LinksRepository, ListNotesInputSchema, ManageArchiveInputSchema, ManageAttachmentsInputSchema, ManageCapabilitiesInputSchema, ManageCollectionsInputSchema, ManageLinksInputSchema, ManageNoteInputSchema, ManageTagsInputSchema, MemoryBlobStore, MigrationRunner, NotesRepository, OpenAICompatibleProvider, PGliteStorageBackend, PGliteStorageBackendFactory, PGliteWorkerClient, PGliteWorkerStorageBackend, PGliteWorkerStorageBackendFactory, ProviderRegistry, SHARD_FORMAT, SUPPORTED_PGLITE_VERSION, SearchInputSchema, SearchRepository, SkosRepository, TagsRepository, TransactionProxy, TypedEventBus, VERSION, aiRevisionHandler, aiwgFortemiIndexToCommunityGraph, allMigrations, appendPluginScript, assertAiwgFortemiChunkManifest, assertAiwgFortemiChunkPart, assertAiwgFortemiIndexExport, buildAiwgChunkedIndex, buildNoteConditions, buildPluginCsp, captureKnowledge, chunkText, classifyError, classifyModel, clearPrefetchedShard, collectionFromShard, collectionToShard, computeHash, computeSri, conceptTaggingHandler, cosineSimilarity, createAiwgFetchChunkLoader, createAiwgFetchDetailLoader, createAiwgIndexController, createAiwgReviewDecisionExport, createBlobStore, createCosineSemanticProvider, createCspReportHandler, createFortemi, createLegacyProvider, createPGliteBackend, createPGliteInstance, createRoutes, createShardBackend, createWorkerEmbedFunction, defaultStorageBackendFactory, detectCommunities, detectGpuCapabilities, detectInferenceCapabilities, discoverLocalProviders, dumpDbSnapshot, embeddingFromShard, embeddingGenerationHandler, embeddingSetFromShard, embeddingSetMemberToShard, embeddingSetToShard, embeddingToShard, enqueueFullWorkflow, enqueueJob, enqueueNoteCreationJobs, estimateModelFit, estimateVramMB, estimateVramTier, exportShard, fetchPluginScript, fortemiManifest, fromPrefetched, generateId, getAiwgFortemiFacets, getEmbedFunction, getFortemiBridge, getFortemiSecretStore, getJobQueueStatus, getLlmFunction, getNote, getPrefetchedSha256, handleEmbedRequests, hasFortemiSecureSecrets, importShard, isPluginScriptAllowed, isShardPrefetched, linkFromShard, linkToShard, linkingHandler, listNotes, manageArchive, manageAttachments, manageCapabilities, manageCollections, manageLinks, manageNote, manageTags, matchRoute, noteFromShard, noteSkosTagToShard, noteToShard, openShard, packTarGz, parseCspReport, prefetchShard, provenanceEdgeToShard, queryAiwgFortemiIndex, registerLlmCapability, registerSemanticCapability, registerSemanticCapabilityWorker, registerServiceWorker, restoreDbSnapshot, searchTool, selectBackend, selectLlmModel, setEmbedFunction, setLlmFunction, sha256Hex, skosConceptToShard, skosRelationToShard, skosSchemeToShard, suggestTags, tagsFromShard, tagsToShard, titleGenerationHandler, unpackTarGz, unregisterLlmCapability, unregisterSemanticCapability, validateAiwgFortemiChunkManifest, validateAiwgFortemiChunkPart, validateAiwgFortemiIndexExport, validateChecksums, verifyDbSnapshotMeta, verifySri };
|
|
8857
|
+
export { AIWG_SCAN_REQUIRED_FIELDS, ArchiveManager, AttachmentsRepository, CURRENT_MIGRATION_HEAD, CURRENT_SHARD_VERSION, CapabilityManager, CaptureKnowledgeInputSchema, CollectionsRepository, CommunitiesRepository, DB_SNAPSHOT_SCHEMA_VERSION, DbSnapshotVersionError, EMBED_REQUEST_KIND, EMBED_RESPONSE_KIND, EmbeddingSetsRepository, FallbackRouter, FortemiToolManifest, GetNoteInputSchema, GraphRepository, JOB_CAPABILITIES, JOB_PRIORITIES, JobQueueWorker, LOCAL_ENDPOINTS, LinksRepository, ListNotesInputSchema, ManageArchiveInputSchema, ManageAttachmentsInputSchema, ManageCapabilitiesInputSchema, ManageCollectionsInputSchema, ManageLinksInputSchema, ManageNoteInputSchema, ManageTagsInputSchema, MemoryBlobStore, MigrationRunner, NotesRepository, OpenAICompatibleProvider, PGliteStorageBackend, PGliteStorageBackendFactory, PGliteWorkerClient, PGliteWorkerStorageBackend, PGliteWorkerStorageBackendFactory, ProvenanceRepository, ProviderRegistry, SHARD_FORMAT, SUPPORTED_PGLITE_VERSION, SearchInputSchema, SearchRepository, SkosRepository, TagsRepository, TransactionProxy, TypedEventBus, VERSION, aiRevisionHandler, aiwgFortemiIndexToCommunityGraph, allMigrations, appendPluginScript, assertAiwgFortemiChunkManifest, assertAiwgFortemiChunkPart, assertAiwgFortemiIndexExport, buildAiwgChunkedIndex, buildNoteConditions, buildPluginCsp, captureKnowledge, chunkText, classifyError, classifyModel, clearPrefetchedShard, collectionFromShard, collectionToShard, computeHash, computeSri, conceptTaggingHandler, cosineSimilarity, createAiwgFetchChunkLoader, createAiwgFetchDetailLoader, createAiwgIndexController, createAiwgReviewDecisionExport, createBlobStore, createCosineSemanticProvider, createCspReportHandler, createFortemi, createLegacyProvider, createPGliteBackend, createPGliteInstance, createRemoteBackend, createRoutes, createShardBackend, createWorkerEmbedFunction, defaultStorageBackendFactory, detectCommunities, detectGpuCapabilities, detectInferenceCapabilities, discoverLocalProviders, dumpDbSnapshot, embeddingFromShard, embeddingGenerationHandler, embeddingSetFromShard, embeddingSetMemberToShard, embeddingSetToShard, embeddingToShard, enqueueFullWorkflow, enqueueJob, enqueueNoteCreationJobs, estimateModelFit, estimateVramMB, estimateVramTier, exportShard, fetchPluginScript, fortemiManifest, fromPrefetched, generateId, getAiwgFortemiFacets, getEmbedFunction, getFortemiBridge, getFortemiSecretStore, getJobQueueStatus, getLlmFunction, getNote, getPrefetchedSha256, handleEmbedRequests, hasFortemiSecureSecrets, importShard, isPluginScriptAllowed, isShardPrefetched, linkFromShard, linkToShard, linkingHandler, listNotes, manageArchive, manageAttachments, manageCapabilities, manageCollections, manageLinks, manageNote, manageTags, matchRoute, noteFromShard, noteSkosTagToShard, noteToShard, openShard, packTarGz, parseCspReport, prefetchShard, provenanceEdgeToShard, queryAiwgFortemiIndex, registerLlmCapability, registerSemanticCapability, registerSemanticCapabilityWorker, registerServiceWorker, restoreDbSnapshot, searchTool, selectBackend, selectLlmModel, setEmbedFunction, setLlmFunction, sha256Hex, skosConceptToShard, skosRelationToShard, skosSchemeToShard, suggestTags, tagsFromShard, tagsToShard, titleGenerationHandler, unpackTarGz, unregisterLlmCapability, unregisterSemanticCapability, validateAiwgFortemiChunkManifest, validateAiwgFortemiChunkPart, validateAiwgFortemiIndexExport, validateChecksums, verifyDbSnapshotMeta, verifySri };
|
|
8490
8858
|
//# sourceMappingURL=index.js.map
|
|
8491
8859
|
//# sourceMappingURL=index.js.map
|