@modusensus/dsh-mneme 0.8.14 → 0.8.16
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/LICENSE +21 -21
- package/README.md +660 -654
- package/assets/icon.svg +3 -3
- package/bin/cli.mjs +691 -689
- package/bin/dsh-mneme-mcp.mjs +510 -510
- package/bin/dsh-mneme-serve.mjs +151 -151
- package/cordis.patch.yml +21 -21
- package/docs/CONFIGURATION.md +275 -0
- package/docs/CONTINUITY.md +124 -0
- package/docs/DAEMON.md +46 -0
- package/docs/DISTILL.md +162 -0
- package/docs/ENTITIES.md +245 -0
- package/docs/LOCAL_MODEL.md +222 -0
- package/docs/SEMANTIC.md +256 -0
- package/docs/SLEEP.md +164 -0
- package/docs/STORAGE.md +98 -0
- package/lib/api-standalone.js +656 -673
- package/lib/api.js +1605 -1433
- package/lib/bootstrap.js +211 -211
- package/lib/client.js +6354 -5296
- package/lib/commands.js +95 -95
- package/lib/config.js +947 -843
- package/lib/content-hash.js +54 -54
- package/lib/continuity.js +220 -220
- package/lib/document-index.js +94 -94
- package/lib/document.js +303 -303
- package/lib/dream/clustering.js +118 -118
- package/lib/dream/decisions.js +694 -674
- package/lib/dream/narratives.js +44 -44
- package/lib/dream/sleep.js +819 -819
- package/lib/dream.js +1503 -1501
- package/lib/embedding.js +177 -177
- package/lib/entities/extractor.js +252 -252
- package/lib/graph/anchoring.js +179 -179
- package/lib/guide.js +74 -74
- package/lib/heat.js +144 -144
- package/lib/hot-memory.js +108 -46
- package/lib/index.js +552 -503
- package/lib/inject.js +428 -450
- package/lib/lang.js +248 -229
- package/lib/local-embedder.js +358 -358
- package/lib/maintenance.js +162 -142
- package/lib/mirror.js +330 -330
- package/lib/organize.js +450 -450
- package/lib/peak-hours.js +117 -117
- package/lib/placement.js +13 -0
- package/lib/pre-inject-gate.js +340 -0
- package/lib/quality-filter.js +126 -126
- package/lib/recall-stats.js +190 -175
- package/lib/reclaim-http.js +150 -0
- package/lib/reranker.js +269 -269
- package/lib/runtime/adopt.js +176 -176
- package/lib/runtime/closure.js +172 -172
- package/lib/runtime/download.js +247 -247
- package/lib/runtime/layout.js +265 -265
- package/lib/runtime/loader.js +252 -252
- package/lib/runtime/model-fetch.js +361 -361
- package/lib/runtime/provision.js +237 -237
- package/lib/runtime/tarball.js +130 -130
- package/lib/runtime/verify.js +223 -204
- package/lib/safe-slice.js +18 -0
- package/lib/scope.js +146 -146
- package/lib/search/adaptive.js +60 -60
- package/lib/search/bm25.js +96 -96
- package/lib/semantic.js +229 -229
- package/lib/sensitive-scan.js +209 -209
- package/lib/serve.js +215 -215
- package/lib/service.js +2688 -2605
- package/lib/settings.js +528 -511
- package/lib/store.js +3196 -3007
- package/lib/summarize.js +1039 -856
- package/lib/tools.js +743 -737
- package/lib/vector-index.js +110 -110
- package/lib/version-check.js +122 -122
- package/lib/write-admission.js +402 -402
- package/locale/en.json +6 -6
- package/locale/zh.json +6 -6
- package/package.json +118 -118
- package/runtime-manifest.json +526 -526
- package/scripts/benchmark-embed.js +201 -201
- package/scripts/benchmark-recall.js +249 -249
- package/scripts/benchmark-rerank.js +166 -166
- package/scripts/build-runtime-manifest.mjs +224 -224
- package/scripts/changelog-prep.mjs +36 -36
- package/scripts/check-sync.js +42 -42
- package/scripts/e2e-dsh.js +220 -220
- package/scripts/mneme-runtime.mjs +277 -277
- package/scripts/stress-dsh.js +255 -255
- package/scripts/sync-lib.js +47 -47
- package/scripts/sync-test-badge.mjs +69 -69
- package/scripts/test-count-sync.mjs +44 -44
- package/src/api-standalone.js +656 -673
- package/src/api.js +1605 -1433
- package/src/bootstrap.js +211 -211
- package/src/commands.js +95 -95
- package/src/config.js +947 -843
- package/src/content-hash.js +54 -54
- package/src/continuity.js +220 -220
- package/src/document-index.js +94 -94
- package/src/document.js +303 -303
- package/src/dream/clustering.js +118 -118
- package/src/dream/decisions.js +694 -674
- package/src/dream/narratives.js +44 -44
- package/src/dream/sleep.js +819 -819
- package/src/dream.js +1503 -1501
- package/src/embedding.js +177 -177
- package/src/entities/extractor.js +252 -252
- package/src/graph/anchoring.js +179 -179
- package/src/guide.js +74 -74
- package/src/heat.js +144 -144
- package/src/hot-memory.js +108 -46
- package/src/index.js +552 -503
- package/src/inject.js +428 -450
- package/src/lang.js +248 -229
- package/src/local-embedder.js +358 -358
- package/src/maintenance.js +162 -142
- package/src/mirror.js +330 -330
- package/src/organize.js +450 -450
- package/src/peak-hours.js +117 -117
- package/src/placement.js +13 -0
- package/src/pre-inject-gate.js +340 -0
- package/src/quality-filter.js +126 -126
- package/src/recall-stats.js +190 -175
- package/src/reclaim-http.js +150 -0
- package/src/reranker.js +269 -269
- package/src/runtime/adopt.js +176 -176
- package/src/runtime/closure.js +172 -172
- package/src/runtime/download.js +247 -247
- package/src/runtime/layout.js +265 -265
- package/src/runtime/loader.js +252 -252
- package/src/runtime/model-fetch.js +361 -361
- package/src/runtime/provision.js +237 -237
- package/src/runtime/tarball.js +130 -130
- package/src/runtime/verify.js +223 -204
- package/src/safe-slice.js +18 -0
- package/src/scope.js +146 -146
- package/src/search/adaptive.js +60 -60
- package/src/search/bm25.js +96 -96
- package/src/semantic.js +229 -229
- package/src/sensitive-scan.js +209 -209
- package/src/serve.js +215 -215
- package/src/service.js +2688 -2605
- package/src/settings.js +528 -511
- package/src/store.js +3196 -3007
- package/src/summarize.js +1039 -856
- package/src/tools.js +743 -737
- package/src/vector-index.js +110 -110
- package/src/version-check.js +122 -122
- package/src/write-admission.js +402 -402
- package/test/adaptive-inject-budget.test.js +85 -85
- package/test/api-routes-gaps.test.js +899 -218
- package/test/api.test.js +1725 -1690
- package/test/audit.test.js +448 -448
- package/test/baseline-persist.test.js +248 -248
- package/test/benchmark.test.js +94 -94
- package/test/bootstrap.test.js +220 -220
- package/test/changelog-prep.test.js +60 -60
- package/test/client.test.js +1582 -1169
- package/test/clustering.test.js +100 -100
- package/test/commands.test.js +106 -106
- package/test/config.test.js +66 -66
- package/test/conflict-freeze.test.js +300 -300
- package/test/content-hash.test.js +204 -204
- package/test/continuity.test.js +333 -333
- package/test/contrast.test.js +314 -0
- package/test/document-dir.test.js +233 -233
- package/test/document.test.js +671 -671
- package/test/dream-archive-guardrail.test.js +116 -116
- package/test/dream-candidate-hybrid.test.js +281 -281
- package/test/dream-coverage-degrade.test.js +86 -86
- package/test/dream-failure-backoff.test.js +173 -173
- package/test/dream-merge-guardrail.test.js +219 -0
- package/test/dream-peak-hours.test.js +194 -194
- package/test/dream.test.js +1385 -1383
- package/test/embedding-ready.test.js +196 -196
- package/test/entities.test.js +627 -547
- package/test/entity-recall.test.js +179 -179
- package/test/epistemic.test.js +325 -325
- package/test/fnew-0112.test.js +311 -311
- package/test/fnew-03.test.js +422 -422
- package/test/graph-anchoring.test.js +184 -184
- package/test/graph-api.test.js +175 -175
- package/test/graph-inject-budget.test.js +103 -103
- package/test/graph-passive-confirm.test.js +91 -91
- package/test/graph-weight-evolution.test.js +104 -104
- package/test/heat.test.js +175 -175
- package/test/helpers/dream-mock.js +82 -82
- package/test/helpers/peer-worker.mjs +25 -25
- package/test/helpers/runtime-source.js +60 -60
- package/test/helpers/tar-builder.js +80 -80
- package/test/helpers/write-admission-samples.js +308 -308
- package/test/hot-memory.test.js +211 -145
- package/test/inject-content-cap.test.js +91 -91
- package/test/inject-first-round-bm25.test.js +89 -89
- package/test/inject-heat.test.js +77 -77
- package/test/inject-parent-gate.test.js +106 -106
- package/test/inject-pools.test.js +194 -194
- package/test/inject-recall.test.js +144 -105
- package/test/inject-rotation.test.js +161 -161
- package/test/inject.test.js +443 -420
- package/test/lang.test.js +87 -87
- package/test/lastrunat-persist.test.js +101 -101
- package/test/lib-smoke.test.js +96 -96
- package/test/llm-audit.test.js +696 -598
- package/test/llm-message-source.test.js +207 -207
- package/test/local-embedder.test.js +292 -292
- package/test/maintenance.test.js +501 -391
- package/test/mcp-stdio.test.js +385 -385
- package/test/mirror-dirty.test.js +424 -424
- package/test/mirror-edit-digest.test.js +187 -187
- package/test/mirror-generation.test.js +499 -499
- package/test/mirror-types.test.js +208 -208
- package/test/mirror.test.js +249 -249
- package/test/narrative-bars.test.js +162 -162
- package/test/organize.test.js +418 -418
- package/test/peer-blockers.test.js +193 -193
- package/test/placement.test.js +36 -0
- package/test/policy-epoch.test.js +259 -259
- package/test/pre-inject-gate.test.js +444 -0
- package/test/quality-filter.test.js +186 -186
- package/test/reasoning-effort.test.js +752 -752
- package/test/recall-anti-update.test.js +82 -82
- package/test/recall-evals.test.js +253 -253
- package/test/recall-layer.test.js +326 -326
- package/test/recall-stats.test.js +274 -189
- package/test/receipt-chain.test.js +451 -451
- package/test/reclaim-http.test.js +209 -0
- package/test/reflection.test.js +226 -226
- package/test/reindex-backfill.test.js +62 -62
- package/test/reranker-single-logit.test.js +73 -73
- package/test/reranker.test.js +197 -197
- package/test/resident-status.test.js +83 -83
- package/test/runtime-adopt.test.js +206 -206
- package/test/runtime-cli.test.js +89 -89
- package/test/runtime-closure.test.js +193 -193
- package/test/runtime-download.test.js +302 -302
- package/test/runtime-layout.test.js +163 -163
- package/test/runtime-loader.test.js +255 -255
- package/test/runtime-manifest.test.js +159 -159
- package/test/runtime-model-fetch.test.js +348 -348
- package/test/runtime-provision.test.js +101 -101
- package/test/runtime-tarball.test.js +81 -81
- package/test/runtime-verify.test.js +319 -279
- package/test/scope-candidates.test.js +239 -239
- package/test/scope-explicit.test.js +452 -452
- package/test/scope-inject-soft.test.js +106 -106
- package/test/scope-retrieval.test.js +197 -197
- package/test/scope-storage.test.js +255 -255
- package/test/scope-strict.test.js +367 -367
- package/test/search-fusion.test.js +90 -90
- package/test/semantic.test.js +124 -124
- package/test/sensitive-scan.test.js +207 -207
- package/test/serve-bin.test.js +121 -121
- package/test/serve.test.js +196 -196
- package/test/service-search.test.js +174 -174
- package/test/service.test.js +410 -405
- package/test/settings.test.js +269 -261
- package/test/skip-invalid-restore.test.js +262 -262
- package/test/sleep-action-set.test.js +422 -422
- package/test/sleep-heat.test.js +126 -126
- package/test/sleep-scheduler-rearm.test.js +89 -89
- package/test/sleep.test.js +527 -527
- package/test/standalone-api.test.js +751 -751
- package/test/store-vector-cache.test.js +98 -98
- package/test/store.test.js +504 -396
- package/test/stress.test.js +209 -209
- package/test/summarize-occurred-at.test.js +127 -0
- package/test/summarize-reasoning-effort.test.js +189 -189
- package/test/summarize.test.js +1639 -1465
- package/test/supersede-state-tracking.test.js +394 -0
- package/test/test-count-sync.test.js +60 -60
- package/test/tools-dto-schema-matrix.test.js +325 -325
- package/test/tools-memory-get-schema.test.js +65 -65
- package/test/tools.test.js +428 -374
- package/test/updated-at-semantics.test.js +113 -113
- package/test/vector-index.test.js +221 -221
- package/test/version-check.test.js +152 -152
- package/test/webServer-optional.test.js +82 -82
- package/test/write-admission.test.js +668 -668
package/lib/document-index.js
CHANGED
|
@@ -1,94 +1,94 @@
|
|
|
1
|
-
// dsh-mneme/src/document-index.js
|
|
2
|
-
// documentDir 的索引(issue #296 第二批)。`<documentDir>/index.md` 整文件机器所有,
|
|
3
|
-
// 可从库随时重建:内容里没有任何「生成时间」,所以删掉再同步一次得到逐字节相同的
|
|
4
|
-
// 文件(test/document-dir.test.js 钉住这一条)。
|
|
5
|
-
//
|
|
6
|
-
// 与镜像侧 documents.md 的分工(#296 第 2 节表格):这里是 document 子系统自己的
|
|
7
|
-
// 索引(id + 标题 + 定位 + managed 标记),那份是带 frontmatter 的镜像只读视图
|
|
8
|
-
// (多一个摘要首句)。两份都只列指针行,都不含正文——正文永远在 doc_path 指向的
|
|
9
|
-
// 文件里,那是 agent 的东西。
|
|
10
|
-
import { readFileSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
11
|
-
import { join } from "node:path";
|
|
12
|
-
import { STR } from "./lang.js";
|
|
13
|
-
import { isManagedDocumentPath } from "./document.js";
|
|
14
|
-
|
|
15
|
-
function oneLine(text) {
|
|
16
|
-
return String(text ?? "").replace(/\s+/g, " ").trim();
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* @param {string} dir resolved documentDir (see resolveDocumentDir)
|
|
21
|
-
* @param {"zh"|"en"} language instance language, same as the mirror
|
|
22
|
-
*/
|
|
23
|
-
export function createDocumentIndex(dir, language = "zh") {
|
|
24
|
-
const filePath = join(dir, "index.md");
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Render the whole file from the given rows. Sorted updated_at DESC, id ASC:
|
|
28
|
-
* the same store state must always render the same bytes (rebuildable).
|
|
29
|
-
*/
|
|
30
|
-
function render(memories) {
|
|
31
|
-
const items = (memories ?? []).slice().sort((a, b) => {
|
|
32
|
-
if (a.updated_at !== b.updated_at) return a.updated_at < b.updated_at ? 1 : -1;
|
|
33
|
-
return a.id < b.id ? -1 : 1;
|
|
34
|
-
});
|
|
35
|
-
const lines = [STR.documentIndexHeader[language]()];
|
|
36
|
-
for (const m of items) {
|
|
37
|
-
const where = isManagedDocumentPath(dir, m.doc_path) ? "managed" : "external";
|
|
38
|
-
// doc_path 理论上必带(store.saveDocument 是唯一铸造口),缺了就只写定位
|
|
39
|
-
// 标记,不编造路径。
|
|
40
|
-
const path = m.doc_path ? ` · \`${oneLine(m.doc_path)}\`` : "";
|
|
41
|
-
lines.push(`- \`${m.id}\` **${oneLine(m.title)}** · ${where}${path}`);
|
|
42
|
-
}
|
|
43
|
-
return `${lines.join("\n")}\n`;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Ensure the directory exists (recursive). Never throws: callers warn and move
|
|
48
|
-
* on — a managed directory that cannot be created must not fail plugin boot.
|
|
49
|
-
*/
|
|
50
|
-
function ensure() {
|
|
51
|
-
try {
|
|
52
|
-
mkdirSync(dir, { recursive: true });
|
|
53
|
-
return { ok: true };
|
|
54
|
-
} catch (error) {
|
|
55
|
-
return { ok: false, error: error?.message ?? String(error) };
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Write the index if it changed. Never throws: a failed index write must not
|
|
61
|
-
* fail the business write that triggered it (same fail-safe shape as
|
|
62
|
-
* mirror.sync). Returns { ok, changed } or { ok: false, error }.
|
|
63
|
-
*/
|
|
64
|
-
function sync(memories) {
|
|
65
|
-
const text = render(memories);
|
|
66
|
-
let prev = null;
|
|
67
|
-
try { prev = readFileSync(filePath, "utf8"); } catch { /* first write */ }
|
|
68
|
-
if (prev === text) return { ok: true, changed: false };
|
|
69
|
-
const ready = ensure();
|
|
70
|
-
if (!ready.ok) return { ok: false, error: ready.error };
|
|
71
|
-
try {
|
|
72
|
-
writeFileSync(filePath, text, "utf8");
|
|
73
|
-
return { ok: true, changed: true };
|
|
74
|
-
} catch (error) {
|
|
75
|
-
return { ok: false, error: error?.message ?? String(error) };
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Drop the index file (闸关时用)。闸关意味着 document 子系统整体退出,留一份
|
|
81
|
-
* 陈旧索引会列出已归档、已遗忘的指针行——正是 documents.md 在闸关时被镜像删掉
|
|
82
|
-
* 要避免的那种「看着还在、其实已关」的视图。删掉不从库取数,O(1),也不抛。
|
|
83
|
-
*/
|
|
84
|
-
function remove() {
|
|
85
|
-
try {
|
|
86
|
-
rmSync(filePath, { force: true });
|
|
87
|
-
return { ok: true };
|
|
88
|
-
} catch (error) {
|
|
89
|
-
return { ok: false, error: error?.message ?? String(error) };
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return { filePath, render, sync, ensure, remove };
|
|
94
|
-
}
|
|
1
|
+
// dsh-mneme/src/document-index.js
|
|
2
|
+
// documentDir 的索引(issue #296 第二批)。`<documentDir>/index.md` 整文件机器所有,
|
|
3
|
+
// 可从库随时重建:内容里没有任何「生成时间」,所以删掉再同步一次得到逐字节相同的
|
|
4
|
+
// 文件(test/document-dir.test.js 钉住这一条)。
|
|
5
|
+
//
|
|
6
|
+
// 与镜像侧 documents.md 的分工(#296 第 2 节表格):这里是 document 子系统自己的
|
|
7
|
+
// 索引(id + 标题 + 定位 + managed 标记),那份是带 frontmatter 的镜像只读视图
|
|
8
|
+
// (多一个摘要首句)。两份都只列指针行,都不含正文——正文永远在 doc_path 指向的
|
|
9
|
+
// 文件里,那是 agent 的东西。
|
|
10
|
+
import { readFileSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { STR } from "./lang.js";
|
|
13
|
+
import { isManagedDocumentPath } from "./document.js";
|
|
14
|
+
|
|
15
|
+
function oneLine(text) {
|
|
16
|
+
return String(text ?? "").replace(/\s+/g, " ").trim();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {string} dir resolved documentDir (see resolveDocumentDir)
|
|
21
|
+
* @param {"zh"|"en"} language instance language, same as the mirror
|
|
22
|
+
*/
|
|
23
|
+
export function createDocumentIndex(dir, language = "zh") {
|
|
24
|
+
const filePath = join(dir, "index.md");
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Render the whole file from the given rows. Sorted updated_at DESC, id ASC:
|
|
28
|
+
* the same store state must always render the same bytes (rebuildable).
|
|
29
|
+
*/
|
|
30
|
+
function render(memories) {
|
|
31
|
+
const items = (memories ?? []).slice().sort((a, b) => {
|
|
32
|
+
if (a.updated_at !== b.updated_at) return a.updated_at < b.updated_at ? 1 : -1;
|
|
33
|
+
return a.id < b.id ? -1 : 1;
|
|
34
|
+
});
|
|
35
|
+
const lines = [STR.documentIndexHeader[language]()];
|
|
36
|
+
for (const m of items) {
|
|
37
|
+
const where = isManagedDocumentPath(dir, m.doc_path) ? "managed" : "external";
|
|
38
|
+
// doc_path 理论上必带(store.saveDocument 是唯一铸造口),缺了就只写定位
|
|
39
|
+
// 标记,不编造路径。
|
|
40
|
+
const path = m.doc_path ? ` · \`${oneLine(m.doc_path)}\`` : "";
|
|
41
|
+
lines.push(`- \`${m.id}\` **${oneLine(m.title)}** · ${where}${path}`);
|
|
42
|
+
}
|
|
43
|
+
return `${lines.join("\n")}\n`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Ensure the directory exists (recursive). Never throws: callers warn and move
|
|
48
|
+
* on — a managed directory that cannot be created must not fail plugin boot.
|
|
49
|
+
*/
|
|
50
|
+
function ensure() {
|
|
51
|
+
try {
|
|
52
|
+
mkdirSync(dir, { recursive: true });
|
|
53
|
+
return { ok: true };
|
|
54
|
+
} catch (error) {
|
|
55
|
+
return { ok: false, error: error?.message ?? String(error) };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Write the index if it changed. Never throws: a failed index write must not
|
|
61
|
+
* fail the business write that triggered it (same fail-safe shape as
|
|
62
|
+
* mirror.sync). Returns { ok, changed } or { ok: false, error }.
|
|
63
|
+
*/
|
|
64
|
+
function sync(memories) {
|
|
65
|
+
const text = render(memories);
|
|
66
|
+
let prev = null;
|
|
67
|
+
try { prev = readFileSync(filePath, "utf8"); } catch { /* first write */ }
|
|
68
|
+
if (prev === text) return { ok: true, changed: false };
|
|
69
|
+
const ready = ensure();
|
|
70
|
+
if (!ready.ok) return { ok: false, error: ready.error };
|
|
71
|
+
try {
|
|
72
|
+
writeFileSync(filePath, text, "utf8");
|
|
73
|
+
return { ok: true, changed: true };
|
|
74
|
+
} catch (error) {
|
|
75
|
+
return { ok: false, error: error?.message ?? String(error) };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Drop the index file (闸关时用)。闸关意味着 document 子系统整体退出,留一份
|
|
81
|
+
* 陈旧索引会列出已归档、已遗忘的指针行——正是 documents.md 在闸关时被镜像删掉
|
|
82
|
+
* 要避免的那种「看着还在、其实已关」的视图。删掉不从库取数,O(1),也不抛。
|
|
83
|
+
*/
|
|
84
|
+
function remove() {
|
|
85
|
+
try {
|
|
86
|
+
rmSync(filePath, { force: true });
|
|
87
|
+
return { ok: true };
|
|
88
|
+
} catch (error) {
|
|
89
|
+
return { ok: false, error: error?.message ?? String(error) };
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return { filePath, render, sync, ensure, remove };
|
|
94
|
+
}
|