@dikolab/kbdb 0.4.0 → 0.4.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 +13 -5
- package/dist/{chunk-BJPSPNGX.mjs → chunk-BJXEVALU.mjs} +115 -1
- package/dist/chunk-BJXEVALU.mjs.map +7 -0
- package/dist/cli.cjs +462 -79
- package/dist/cli.cjs.map +4 -4
- package/dist/cli.mjs +356 -79
- package/dist/cli.mjs.map +4 -4
- package/dist/kbdb-worker.cjs +413 -53
- package/dist/kbdb-worker.cjs.map +4 -4
- package/dist/mod.cjs +230 -54
- package/dist/mod.cjs.map +4 -4
- package/dist/mod.mjs +229 -53
- package/dist/mod.mjs.map +4 -4
- package/dist/src/shared/cli/typings/cli-options.interface.d.ts +5 -0
- package/dist/src/shared/embedding/classes/tfidf-embedding-provider.class.d.ts +28 -0
- package/dist/src/shared/embedding/constants/tfidf-defaults.constant.d.ts +4 -0
- package/dist/src/shared/embedding/functions/create-embedding-provider.function.d.ts +5 -2
- package/dist/src/shared/embedding/index.d.ts +2 -0
- package/dist/src/shared/log/constants/log-colors.constant.d.ts +5 -0
- package/dist/src/shared/log/constants/log-defaults.constant.d.ts +3 -0
- package/dist/src/shared/log/constants/log-icons.constant.d.ts +3 -0
- package/dist/src/shared/log/functions/configure-log.function.d.ts +12 -0
- package/dist/src/shared/log/functions/log.function.d.ts +28 -0
- package/dist/src/shared/log/functions/parse-log-level.function.d.ts +10 -0
- package/dist/src/shared/log/functions/resolve-log-level.function.d.ts +12 -0
- package/dist/src/shared/log/functions/write-stderr.function.d.ts +10 -0
- package/dist/src/shared/log/index.d.ts +10 -0
- package/dist/src/shared/log/typings/log-config.interface.d.ts +7 -0
- package/dist/src/shared/log/typings/log-level.type.d.ts +7 -0
- package/dist/src/shared/log/typings/log-output.interface.d.ts +4 -0
- package/dist/src/shared/version/constants/version.constant.d.ts +1 -1
- package/dist/src/shared/worker-client/classes/worker-client.class.d.ts +7 -0
- package/dist/src/shared/worker-client/functions/retry-on-timeout.function.d.ts +1 -0
- package/dist/src/shared/worker-daemon/classes/worker-daemon.class.d.ts +1 -0
- package/dist/src/shared/worker-daemon/functions/run-worker.function.d.ts +6 -1
- package/dist/src/shared/worker-daemon/typings/wasm-modules.interface.d.ts +5 -0
- package/dist/wasm/default-embedding/kbdb_default_embedding.d.ts +55 -0
- package/dist/wasm/default-embedding/kbdb_default_embedding.js +156 -0
- package/dist/wasm/default-embedding/kbdb_default_embedding_bg.wasm +0 -0
- package/dist/wasm/default-embedding/kbdb_default_embedding_bg.wasm.d.ts +12 -0
- package/dist/wasm/default-embedding/package.json +13 -0
- package/dist/wasm/fs-database/kbdb_fs_database_bg.wasm +0 -0
- package/dist/wasm/fs-migration/kbdb_fs_migration.d.ts +38 -0
- package/dist/wasm/fs-migration/kbdb_fs_migration.js +130 -0
- package/dist/wasm/fs-migration/kbdb_fs_migration_bg.wasm +0 -0
- package/dist/wasm/fs-migration/kbdb_fs_migration_bg.wasm.d.ts +9 -0
- package/dist/wasm/fs-migration/package.json +13 -0
- package/dist/wasm/kb-worker/kbdb_worker_bg.wasm +0 -0
- package/dist/wasm/query-parser/kbdb_query_parser_bg.wasm +0 -0
- package/dist/worker.mjs +306 -54
- package/dist/worker.mjs.map +4 -4
- package/docs/details/agent-tooling.md +10 -0
- package/docs/details/cli.md +29 -13
- package/docs/details/knowledge-base.md +15 -8
- package/docs/details/mcp-server.md +16 -1
- package/docs/details/search-and-ranking.md +6 -2
- package/docs/goals/cli.md +33 -4
- package/docs/goals/content-parser.md +1 -1
- package/docs/goals/hybrid-search.md +71 -42
- package/docs/goals/mcp.md +3 -1
- package/docs/goals/overview.md +1 -1
- package/docs/goals/query-parser.md +1 -1
- package/docs/goals/semantic-dedup.md +7 -3
- package/docs/goals/worker-daemon.md +31 -20
- package/docs/modules/overview.md +43 -22
- package/docs/modules/rust/embedding/module.md +91 -0
- package/docs/modules/rust/overview.md +56 -21
- package/docs/modules/rust/query-parser/functions/module.md +7 -5
- package/docs/modules/rust/query-parser/functions/pipeline.md +6 -138
- package/docs/modules/rust/query-parser/module.md +16 -22
- package/docs/modules/rust/query-parser/types/module.md +5 -4
- package/docs/modules/rust/query-parser/types/token.md +5 -1
- package/docs/modules/rust/shared/content-parser/functions.md +1 -1
- package/docs/modules/rust/shared/memory/module.md +1 -1
- package/docs/modules/rust/shared/module.md +33 -5
- package/docs/modules/rust/shared/pipeline/functions.md +141 -0
- package/docs/modules/rust/shared/pipeline/module.md +62 -0
- package/docs/modules/rust/shared/pipeline/types.md +43 -0
- package/docs/modules/rust/shared/section/module.md +1 -1
- package/docs/modules/rust/shared/section/types.md +1 -1
- package/docs/modules/typescript/cli.md +4 -2
- package/docs/modules/typescript/kbdb-worker.md +20 -5
- package/docs/modules/typescript/overview.md +28 -6
- package/docs/modules/typescript/shared/cli/functions.md +15 -4
- package/docs/modules/typescript/shared/cli/typings.md +21 -0
- package/docs/modules/typescript/shared/embedding/functions.md +30 -3
- package/docs/modules/typescript/shared/embedding/module.md +10 -4
- package/docs/modules/typescript/shared/embedding/typings.md +7 -5
- package/docs/modules/typescript/shared/log/constants.md +82 -0
- package/docs/modules/typescript/shared/log/functions.md +131 -0
- package/docs/modules/typescript/shared/log/module.md +153 -0
- package/docs/modules/typescript/shared/log/typings.md +82 -0
- package/docs/modules/typescript/shared/module.md +22 -6
- package/docs/modules/typescript/shared/worker-daemon/functions.md +19 -6
- package/docs/modules/typescript/shared/worker-daemon/module.md +5 -2
- package/docs/modules/typescript/shared/worker-daemon/typings.md +13 -7
- package/docs/release-notes/0.4.1.md +149 -0
- package/package.json +2 -2
- package/dist/chunk-BJPSPNGX.mjs.map +0 -7
package/dist/cli.mjs
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
computeSha256,
|
|
3
|
+
configureLog,
|
|
3
4
|
detectRuntime,
|
|
4
5
|
getArgs,
|
|
5
6
|
getIpcPath,
|
|
7
|
+
log,
|
|
8
|
+
parseLogLevel,
|
|
6
9
|
parseWorkerToml,
|
|
7
10
|
resolveBaseDir,
|
|
11
|
+
resolveLogLevel,
|
|
8
12
|
resolveWorkerScript
|
|
9
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-BJXEVALU.mjs";
|
|
10
14
|
|
|
11
15
|
// src/cli.ts
|
|
12
16
|
import { readFileSync as readFileSync4 } from "node:fs";
|
|
@@ -46,19 +50,31 @@ function parseArgs(argv) {
|
|
|
46
50
|
}
|
|
47
51
|
return options;
|
|
48
52
|
case "--version":
|
|
49
|
-
case "-v":
|
|
50
53
|
options.command = "version";
|
|
51
54
|
return options;
|
|
55
|
+
case "-v":
|
|
56
|
+
case "--verbose": {
|
|
57
|
+
const next = argv[i + 1];
|
|
58
|
+
if (next && !next.startsWith("-")) {
|
|
59
|
+
options.logLevel = parseLogLevel(next);
|
|
60
|
+
i++;
|
|
61
|
+
} else {
|
|
62
|
+
options.logLevel = 2 /* WARNING */;
|
|
63
|
+
}
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
case "-vv":
|
|
67
|
+
case "--verbose-info":
|
|
68
|
+
options.logLevel = 1 /* INFO */;
|
|
69
|
+
break;
|
|
70
|
+
case "-vvv":
|
|
71
|
+
case "--verbose-debug":
|
|
72
|
+
options.logLevel = 0 /* DEBUG */;
|
|
73
|
+
break;
|
|
52
74
|
case "--init":
|
|
53
|
-
console.error(
|
|
54
|
-
'warning: --init is deprecated, use "kbdb db init"'
|
|
55
|
-
);
|
|
56
75
|
options.command = "init";
|
|
57
76
|
break;
|
|
58
77
|
case "--migrate":
|
|
59
|
-
console.error(
|
|
60
|
-
'warning: --migrate is deprecated, use "kbdb db migrate"'
|
|
61
|
-
);
|
|
62
78
|
options.command = "migrate";
|
|
63
79
|
break;
|
|
64
80
|
case "--db":
|
|
@@ -143,6 +159,9 @@ function parseArgs(argv) {
|
|
|
143
159
|
case "--retry":
|
|
144
160
|
options.retry = parseInt(argv[++i] ?? "", 10) || void 0;
|
|
145
161
|
break;
|
|
162
|
+
case "--non-interactive":
|
|
163
|
+
options.nonInteractive = true;
|
|
164
|
+
break;
|
|
146
165
|
default:
|
|
147
166
|
if (!options.command) {
|
|
148
167
|
options.command = arg;
|
|
@@ -219,6 +238,7 @@ function formatMcp(paged) {
|
|
|
219
238
|
|
|
220
239
|
// src/shared/cli/functions/run-search.function.ts
|
|
221
240
|
async function runSearch(client, options) {
|
|
241
|
+
log("searching: " + options.args.join(" "), 0 /* DEBUG */);
|
|
222
242
|
const query = options.args.join(" ").trim();
|
|
223
243
|
if (!query) {
|
|
224
244
|
return {
|
|
@@ -238,6 +258,10 @@ async function runSearch(client, options) {
|
|
|
238
258
|
algo: options.algo,
|
|
239
259
|
relaxed: options.relaxed
|
|
240
260
|
});
|
|
261
|
+
log(
|
|
262
|
+
"search returned " + results.total.toString() + " results",
|
|
263
|
+
0 /* DEBUG */
|
|
264
|
+
);
|
|
241
265
|
return {
|
|
242
266
|
items: results.items.map((r) => ({
|
|
243
267
|
kbid: r.kbid,
|
|
@@ -275,12 +299,14 @@ async function resolveKbidPrefix(prefix, client) {
|
|
|
275
299
|
}
|
|
276
300
|
}
|
|
277
301
|
if (seen.size === 0) {
|
|
278
|
-
|
|
302
|
+
const msg = `no section matches prefix "${prefix}"`;
|
|
303
|
+
log(msg, 3 /* ERROR */);
|
|
304
|
+
throw new Error(msg);
|
|
279
305
|
}
|
|
280
306
|
if (seen.size > 1) {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
);
|
|
307
|
+
const msg = `ambiguous prefix "${prefix}": ${seen.size.toString()} matches`;
|
|
308
|
+
log(msg, 3 /* ERROR */);
|
|
309
|
+
throw new Error(msg);
|
|
284
310
|
}
|
|
285
311
|
return [...seen][0];
|
|
286
312
|
}
|
|
@@ -288,6 +314,7 @@ async function resolveKbidPrefix(prefix, client) {
|
|
|
288
314
|
// src/shared/cli/functions/run-recall.function.ts
|
|
289
315
|
var MAX_RECALL_DEPTH = 3;
|
|
290
316
|
async function runRecall(client, options) {
|
|
317
|
+
log("running recall", 0 /* DEBUG */);
|
|
291
318
|
if (options.args.length === 0) {
|
|
292
319
|
return { error: "no kbid provided" };
|
|
293
320
|
}
|
|
@@ -306,6 +333,7 @@ async function runRecall(client, options) {
|
|
|
306
333
|
|
|
307
334
|
// src/shared/cli/functions/run-export.function.ts
|
|
308
335
|
async function runExport(client, options) {
|
|
336
|
+
log("running export", 0 /* DEBUG */);
|
|
309
337
|
const path = options.args[0];
|
|
310
338
|
return client.export({ path });
|
|
311
339
|
}
|
|
@@ -314,6 +342,10 @@ async function runExport(client, options) {
|
|
|
314
342
|
import { readFileSync, readdirSync, statSync } from "node:fs";
|
|
315
343
|
import { basename, extname, join } from "node:path";
|
|
316
344
|
async function runLearn(client, options, io) {
|
|
345
|
+
log(
|
|
346
|
+
"learning " + options.args.length.toString() + " targets",
|
|
347
|
+
0 /* DEBUG */
|
|
348
|
+
);
|
|
317
349
|
const results = [];
|
|
318
350
|
let stdinConsumed = false;
|
|
319
351
|
const readStdin = io?.readStdin ?? readProcessStdin;
|
|
@@ -352,6 +384,10 @@ async function runLearn(client, options, io) {
|
|
|
352
384
|
);
|
|
353
385
|
}
|
|
354
386
|
}
|
|
387
|
+
log(
|
|
388
|
+
"learned " + results.length.toString() + " sections",
|
|
389
|
+
0 /* DEBUG */
|
|
390
|
+
);
|
|
355
391
|
return results;
|
|
356
392
|
}
|
|
357
393
|
function mapAddSectionResult(result, path, size) {
|
|
@@ -415,6 +451,7 @@ function isSupportedFile(path) {
|
|
|
415
451
|
|
|
416
452
|
// src/shared/cli/functions/run-unlearn.function.ts
|
|
417
453
|
async function runUnlearn(client, options) {
|
|
454
|
+
log("running unlearn", 0 /* DEBUG */);
|
|
418
455
|
const results = [];
|
|
419
456
|
for (const arg of options.args) {
|
|
420
457
|
const kbid = await resolveKbidPrefix(arg, client);
|
|
@@ -426,6 +463,7 @@ async function runUnlearn(client, options) {
|
|
|
426
463
|
|
|
427
464
|
// src/shared/cli/functions/run-content.function.ts
|
|
428
465
|
async function runContent(client, options) {
|
|
466
|
+
log("running content", 0 /* DEBUG */);
|
|
429
467
|
const resolved = await Promise.all(
|
|
430
468
|
options.args.map((a) => resolveKbidPrefix(a, client))
|
|
431
469
|
);
|
|
@@ -443,6 +481,7 @@ function parseDivergentContent(encoded) {
|
|
|
443
481
|
}).filter((entry) => entry.kbids.length > 0);
|
|
444
482
|
}
|
|
445
483
|
async function runCheck(client, _options) {
|
|
484
|
+
log("running check", 0 /* DEBUG */);
|
|
446
485
|
const raw = await client.integrityCheck();
|
|
447
486
|
return {
|
|
448
487
|
ok: raw.ok,
|
|
@@ -457,11 +496,13 @@ async function runCheck(client, _options) {
|
|
|
457
496
|
|
|
458
497
|
// src/shared/cli/functions/run-gc.function.ts
|
|
459
498
|
async function runGc(client, _options) {
|
|
499
|
+
log("running gc", 0 /* DEBUG */);
|
|
460
500
|
return client.gc();
|
|
461
501
|
}
|
|
462
502
|
|
|
463
503
|
// src/shared/cli/functions/run-rebuild.function.ts
|
|
464
504
|
async function runRebuild(client, _options) {
|
|
505
|
+
log("running rebuild", 0 /* DEBUG */);
|
|
465
506
|
return client.rebuildIndexes();
|
|
466
507
|
}
|
|
467
508
|
|
|
@@ -617,6 +658,7 @@ function createScaffold(dbDir) {
|
|
|
617
658
|
writeFileSync2(join4(dbDir, ".gitignore"), GITIGNORE);
|
|
618
659
|
}
|
|
619
660
|
function runInit(options) {
|
|
661
|
+
log("running init", 0 /* DEBUG */);
|
|
620
662
|
const basePath = options.dbPath ? resolve2(options.dbPath) : process.cwd();
|
|
621
663
|
const dbDir = join4(basePath, ".kbdb");
|
|
622
664
|
try {
|
|
@@ -668,11 +710,13 @@ function askReadline(question) {
|
|
|
668
710
|
|
|
669
711
|
// src/shared/cli/functions/run-status.function.ts
|
|
670
712
|
async function runStatus(client, _options) {
|
|
713
|
+
log("running status", 0 /* DEBUG */);
|
|
671
714
|
return client.dbStatus();
|
|
672
715
|
}
|
|
673
716
|
|
|
674
717
|
// src/shared/cli/functions/run-db-init.function.ts
|
|
675
718
|
function runDbInit(options, runInitFn) {
|
|
719
|
+
log("running db-init", 0 /* DEBUG */);
|
|
676
720
|
const result = runInitFn(options);
|
|
677
721
|
if (result.ok) {
|
|
678
722
|
return {
|
|
@@ -692,6 +736,7 @@ function runDbInit(options, runInitFn) {
|
|
|
692
736
|
|
|
693
737
|
// src/shared/cli/functions/run-db-migrate.function.ts
|
|
694
738
|
async function runDbMigrate(client, options) {
|
|
739
|
+
log("running db-migrate", 0 /* DEBUG */);
|
|
695
740
|
const dbPath = options.dbPath ?? process.cwd();
|
|
696
741
|
return client.migrateDatabase(dbPath);
|
|
697
742
|
}
|
|
@@ -719,6 +764,7 @@ function serializeSkillContent(skill) {
|
|
|
719
764
|
|
|
720
765
|
// src/shared/cli/functions/run-skill-learn.function.ts
|
|
721
766
|
async function runSkillLearn(client, options) {
|
|
767
|
+
log("running skill-learn", 0 /* DEBUG */);
|
|
722
768
|
const name = options.name;
|
|
723
769
|
if (!name) {
|
|
724
770
|
return { error: "--name is required", exitCode: 1 };
|
|
@@ -749,6 +795,7 @@ async function runSkillLearn(client, options) {
|
|
|
749
795
|
|
|
750
796
|
// src/shared/cli/functions/run-skill-list.function.ts
|
|
751
797
|
async function runSkillList(client, _options) {
|
|
798
|
+
log("running skill-list", 0 /* DEBUG */);
|
|
752
799
|
const records = await client.listByType("skill");
|
|
753
800
|
const items = records.map((r) => {
|
|
754
801
|
let argumentCount = 0;
|
|
@@ -776,9 +823,11 @@ async function runSkillList(client, _options) {
|
|
|
776
823
|
function parseSkillContent(json) {
|
|
777
824
|
const raw = JSON.parse(json);
|
|
778
825
|
if (typeof raw["name"] !== "string" || !raw["name"]) {
|
|
826
|
+
log("skill name is required", 3 /* ERROR */);
|
|
779
827
|
throw new Error("skill name is required");
|
|
780
828
|
}
|
|
781
829
|
if (typeof raw["body"] !== "string") {
|
|
830
|
+
log("skill body is required", 3 /* ERROR */);
|
|
782
831
|
throw new Error("skill body is required");
|
|
783
832
|
}
|
|
784
833
|
return {
|
|
@@ -791,6 +840,7 @@ function parseSkillContent(json) {
|
|
|
791
840
|
|
|
792
841
|
// src/shared/cli/functions/run-skill-get.function.ts
|
|
793
842
|
async function runSkillGet(client, options) {
|
|
843
|
+
log("running skill-get", 0 /* DEBUG */);
|
|
794
844
|
const identifier = options.args[0] ?? options.name;
|
|
795
845
|
if (!identifier) {
|
|
796
846
|
return {
|
|
@@ -827,6 +877,7 @@ async function runSkillGet(client, options) {
|
|
|
827
877
|
|
|
828
878
|
// src/shared/cli/functions/run-skill-delete.function.ts
|
|
829
879
|
async function runSkillDelete(client, options) {
|
|
880
|
+
log("running skill-delete", 0 /* DEBUG */);
|
|
830
881
|
const kbid = options.args[0];
|
|
831
882
|
if (!kbid) {
|
|
832
883
|
return { error: "kbid is required", exitCode: 1 };
|
|
@@ -844,6 +895,7 @@ async function runSkillDelete(client, options) {
|
|
|
844
895
|
|
|
845
896
|
// src/shared/cli/functions/run-agent-create.function.ts
|
|
846
897
|
async function runAgentCreate(client, options) {
|
|
898
|
+
log("running agent-create", 0 /* DEBUG */);
|
|
847
899
|
const name = options.name;
|
|
848
900
|
if (!name) {
|
|
849
901
|
return { error: "--name is required", exitCode: 1 };
|
|
@@ -889,6 +941,7 @@ async function runAgentCreate(client, options) {
|
|
|
889
941
|
|
|
890
942
|
// src/shared/cli/functions/run-agent-list.function.ts
|
|
891
943
|
async function runAgentList(client, _options) {
|
|
944
|
+
log("running agent-list", 0 /* DEBUG */);
|
|
892
945
|
const docs = await client.listDocumentsByType("agent");
|
|
893
946
|
const items = docs.map((d) => ({
|
|
894
947
|
docid: d.docid,
|
|
@@ -945,6 +998,7 @@ async function resolveSkills(client, skillRefs) {
|
|
|
945
998
|
});
|
|
946
999
|
}
|
|
947
1000
|
async function runAgentGet(client, options) {
|
|
1001
|
+
log("running agent-get", 0 /* DEBUG */);
|
|
948
1002
|
const docid = options.args[0];
|
|
949
1003
|
if (!docid) {
|
|
950
1004
|
return { error: "docid is required", exitCode: 1 };
|
|
@@ -966,6 +1020,7 @@ async function runAgentGet(client, options) {
|
|
|
966
1020
|
|
|
967
1021
|
// src/shared/cli/functions/run-agent-delete.function.ts
|
|
968
1022
|
async function runAgentDelete(client, options) {
|
|
1023
|
+
log("running agent-delete", 0 /* DEBUG */);
|
|
969
1024
|
const docid = options.args[0];
|
|
970
1025
|
if (!docid) {
|
|
971
1026
|
return { error: "docid is required", exitCode: 1 };
|
|
@@ -981,7 +1036,9 @@ async function runAgentDelete(client, options) {
|
|
|
981
1036
|
async function runImport(client, options) {
|
|
982
1037
|
const from = options.from;
|
|
983
1038
|
if (!from) {
|
|
984
|
-
|
|
1039
|
+
const msg = "import requires --from <path>";
|
|
1040
|
+
log(msg, 3 /* ERROR */);
|
|
1041
|
+
throw new Error(msg);
|
|
985
1042
|
}
|
|
986
1043
|
return client.import({
|
|
987
1044
|
from,
|
|
@@ -991,6 +1048,7 @@ async function runImport(client, options) {
|
|
|
991
1048
|
|
|
992
1049
|
// src/shared/cli/functions/dispatch-command.function.ts
|
|
993
1050
|
async function dispatchCommand(client, options, io) {
|
|
1051
|
+
log("dispatching command: " + options.command, 0 /* DEBUG */);
|
|
994
1052
|
switch (options.command) {
|
|
995
1053
|
case "learn":
|
|
996
1054
|
return handleLearn(client, options, io);
|
|
@@ -1051,6 +1109,7 @@ async function dispatchCommand(client, options, io) {
|
|
|
1051
1109
|
return result;
|
|
1052
1110
|
}
|
|
1053
1111
|
default:
|
|
1112
|
+
log("unknown command: " + options.command, 2 /* WARNING */);
|
|
1054
1113
|
return {
|
|
1055
1114
|
error: `unknown command: ${options.command}`,
|
|
1056
1115
|
exitCode: 1
|
|
@@ -1250,7 +1309,7 @@ async function hydrateSearchPreviews(client, paged) {
|
|
|
1250
1309
|
}
|
|
1251
1310
|
|
|
1252
1311
|
// src/shared/version/constants/version.constant.ts
|
|
1253
|
-
var VERSION = "0.4.
|
|
1312
|
+
var VERSION = "0.4.1";
|
|
1254
1313
|
|
|
1255
1314
|
// src/shared/cli/functions/generate-help.function.ts
|
|
1256
1315
|
var KNOWN_COMMANDS = /* @__PURE__ */ new Set([
|
|
@@ -1796,6 +1855,57 @@ function generateSubcommandHelp(command, subcommand) {
|
|
|
1796
1855
|
|
|
1797
1856
|
// src/shared/worker-client/classes/worker-client.class.ts
|
|
1798
1857
|
import { connect } from "node:net";
|
|
1858
|
+
|
|
1859
|
+
// src/shared/worker-client/functions/discover-daemon.function.ts
|
|
1860
|
+
import { existsSync as existsSync4, readFileSync as readFileSync2, unlinkSync } from "node:fs";
|
|
1861
|
+
import { join as join5 } from "node:path";
|
|
1862
|
+
import { tmpdir } from "node:os";
|
|
1863
|
+
|
|
1864
|
+
// src/shared/platform/functions/is-process-alive.function.ts
|
|
1865
|
+
function isProcessAlive(pid) {
|
|
1866
|
+
try {
|
|
1867
|
+
process.kill(pid, 0);
|
|
1868
|
+
return true;
|
|
1869
|
+
} catch {
|
|
1870
|
+
return false;
|
|
1871
|
+
}
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
// src/shared/worker-client/functions/discover-daemon.function.ts
|
|
1875
|
+
function discoverDaemon(contextId) {
|
|
1876
|
+
log("discovering daemon for context: " + contextId, 0 /* DEBUG */);
|
|
1877
|
+
const pidPath = join5(tmpdir(), `kbdb-${contextId}.pid`);
|
|
1878
|
+
if (!existsSync4(pidPath)) {
|
|
1879
|
+
log(
|
|
1880
|
+
"no daemon PID file found for context: " + contextId,
|
|
1881
|
+
0 /* DEBUG */
|
|
1882
|
+
);
|
|
1883
|
+
return null;
|
|
1884
|
+
}
|
|
1885
|
+
const pidStr = readFileSync2(pidPath, "utf-8").trim();
|
|
1886
|
+
const pid = parseInt(pidStr, 10);
|
|
1887
|
+
if (isNaN(pid) || !isProcessAlive(pid)) {
|
|
1888
|
+
log(
|
|
1889
|
+
"daemon process not alive for context: " + contextId,
|
|
1890
|
+
0 /* DEBUG */
|
|
1891
|
+
);
|
|
1892
|
+
try {
|
|
1893
|
+
unlinkSync(pidPath);
|
|
1894
|
+
} catch {
|
|
1895
|
+
}
|
|
1896
|
+
return null;
|
|
1897
|
+
}
|
|
1898
|
+
log("daemon found: pid=" + pid.toString(), 0 /* DEBUG */);
|
|
1899
|
+
const socketPath = join5(tmpdir(), `kbdb-${contextId}.sock`);
|
|
1900
|
+
const crashPath = join5(tmpdir(), `kbdb-${contextId}.crash`);
|
|
1901
|
+
try {
|
|
1902
|
+
unlinkSync(crashPath);
|
|
1903
|
+
} catch {
|
|
1904
|
+
}
|
|
1905
|
+
return { pid, socketPath };
|
|
1906
|
+
}
|
|
1907
|
+
|
|
1908
|
+
// src/shared/worker-client/classes/worker-client.class.ts
|
|
1799
1909
|
var WorkerClient = class {
|
|
1800
1910
|
/**
|
|
1801
1911
|
* @param socketPath - absolute path to the daemon's IPC socket
|
|
@@ -1831,11 +1941,13 @@ var WorkerClient = class {
|
|
|
1831
1941
|
* @throws {Error} if the connection cannot be established
|
|
1832
1942
|
*/
|
|
1833
1943
|
async connect() {
|
|
1944
|
+
log("connecting to " + this.socketPath, 0 /* DEBUG */);
|
|
1834
1945
|
const maxRetries = 5;
|
|
1835
1946
|
let delay = 50;
|
|
1836
1947
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
1837
1948
|
try {
|
|
1838
1949
|
await this.tryConnect();
|
|
1950
|
+
log("connected", 0 /* DEBUG */);
|
|
1839
1951
|
return;
|
|
1840
1952
|
} catch (err) {
|
|
1841
1953
|
const code = err.code;
|
|
@@ -1843,6 +1955,10 @@ var WorkerClient = class {
|
|
|
1843
1955
|
if (!retriable || attempt === maxRetries) {
|
|
1844
1956
|
throw err;
|
|
1845
1957
|
}
|
|
1958
|
+
log(
|
|
1959
|
+
"connect retry: attempt=" + attempt.toString() + " code=" + code + " delay=" + delay.toString() + "ms",
|
|
1960
|
+
0 /* DEBUG */
|
|
1961
|
+
);
|
|
1846
1962
|
await new Promise((r) => setTimeout(r, delay));
|
|
1847
1963
|
delay = Math.min(delay * 2, 1e3);
|
|
1848
1964
|
}
|
|
@@ -1850,11 +1966,32 @@ var WorkerClient = class {
|
|
|
1850
1966
|
}
|
|
1851
1967
|
/** Destroys the IPC socket and clears the connection state. */
|
|
1852
1968
|
disconnect() {
|
|
1969
|
+
log("disconnecting client", 0 /* DEBUG */);
|
|
1853
1970
|
if (this.socket) {
|
|
1854
1971
|
this.socket.destroy();
|
|
1855
1972
|
this.socket = null;
|
|
1856
1973
|
}
|
|
1857
1974
|
}
|
|
1975
|
+
/**
|
|
1976
|
+
* Kills the daemon process and disconnects the client.
|
|
1977
|
+
*
|
|
1978
|
+
* Discovers the daemon via PID file and sends `SIGTERM`.
|
|
1979
|
+
* Always disconnects the socket regardless of kill outcome.
|
|
1980
|
+
*/
|
|
1981
|
+
killDaemon() {
|
|
1982
|
+
const info = discoverDaemon(this.contextId);
|
|
1983
|
+
log(
|
|
1984
|
+
"killing daemon: pid=" + (info ? info.pid.toString() : "unknown"),
|
|
1985
|
+
0 /* DEBUG */
|
|
1986
|
+
);
|
|
1987
|
+
if (info) {
|
|
1988
|
+
try {
|
|
1989
|
+
process.kill(info.pid, "SIGTERM");
|
|
1990
|
+
} catch {
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1993
|
+
this.disconnect();
|
|
1994
|
+
}
|
|
1858
1995
|
/**
|
|
1859
1996
|
* Single connection attempt with keepalive and
|
|
1860
1997
|
* post-connect failure handlers.
|
|
@@ -1865,9 +2002,14 @@ var WorkerClient = class {
|
|
|
1865
2002
|
sock.removeListener("error", reject);
|
|
1866
2003
|
sock.setKeepAlive(true, 3e4);
|
|
1867
2004
|
sock.on("error", (err) => {
|
|
2005
|
+
log(
|
|
2006
|
+
"socket error: code=" + (err.code ?? err.message),
|
|
2007
|
+
0 /* DEBUG */
|
|
2008
|
+
);
|
|
1868
2009
|
this.handleSocketFailure(err);
|
|
1869
2010
|
});
|
|
1870
2011
|
sock.on("close", () => {
|
|
2012
|
+
log("socket closed", 0 /* DEBUG */);
|
|
1871
2013
|
if (this.pending.size > 0) {
|
|
1872
2014
|
this.handleSocketFailure(
|
|
1873
2015
|
new Error("connection closed")
|
|
@@ -1889,6 +2031,10 @@ var WorkerClient = class {
|
|
|
1889
2031
|
* disconnected.
|
|
1890
2032
|
*/
|
|
1891
2033
|
handleSocketFailure(err) {
|
|
2034
|
+
log(
|
|
2035
|
+
"socket failure: pending=" + this.pending.size.toString() + " err=" + err.message,
|
|
2036
|
+
0 /* DEBUG */
|
|
2037
|
+
);
|
|
1892
2038
|
const sock = this.socket;
|
|
1893
2039
|
this.socket = null;
|
|
1894
2040
|
for (const [id, call] of this.pending) {
|
|
@@ -2189,6 +2335,10 @@ var WorkerClient = class {
|
|
|
2189
2335
|
throw new Error("not connected");
|
|
2190
2336
|
}
|
|
2191
2337
|
const id = this.nextId++;
|
|
2338
|
+
log(
|
|
2339
|
+
"call: method=" + method + " id=" + id.toString(),
|
|
2340
|
+
0 /* DEBUG */
|
|
2341
|
+
);
|
|
2192
2342
|
const request = {
|
|
2193
2343
|
jsonrpc: "2.0",
|
|
2194
2344
|
id,
|
|
@@ -2202,6 +2352,10 @@ var WorkerClient = class {
|
|
|
2202
2352
|
call.timer = setTimeout(() => {
|
|
2203
2353
|
if (!this.pending.has(id)) return;
|
|
2204
2354
|
this.pending.delete(id);
|
|
2355
|
+
log(
|
|
2356
|
+
"request timeout after " + String(timeoutMs) + "ms",
|
|
2357
|
+
2 /* WARNING */
|
|
2358
|
+
);
|
|
2205
2359
|
const err = new Error(
|
|
2206
2360
|
`request timeout after ${String(timeoutMs)}ms`
|
|
2207
2361
|
);
|
|
@@ -2232,14 +2386,31 @@ var WorkerClient = class {
|
|
|
2232
2386
|
this.pending.delete(response.id);
|
|
2233
2387
|
if (pending.timer) clearTimeout(pending.timer);
|
|
2234
2388
|
if (response.error) {
|
|
2389
|
+
log(
|
|
2390
|
+
"response error: id=" + response.id.toString() + " code=" + response.error.code.toString(),
|
|
2391
|
+
0 /* DEBUG */
|
|
2392
|
+
);
|
|
2235
2393
|
const err = new Error(response.error.message);
|
|
2236
2394
|
err.code = response.error.code;
|
|
2237
2395
|
pending.reject(err);
|
|
2238
2396
|
} else {
|
|
2397
|
+
log(
|
|
2398
|
+
"response ok: id=" + response.id.toString(),
|
|
2399
|
+
0 /* DEBUG */
|
|
2400
|
+
);
|
|
2239
2401
|
pending.resolve(response.result);
|
|
2240
2402
|
}
|
|
2403
|
+
} else {
|
|
2404
|
+
log(
|
|
2405
|
+
"unmatched response id=" + response.id.toString(),
|
|
2406
|
+
0 /* DEBUG */
|
|
2407
|
+
);
|
|
2241
2408
|
}
|
|
2242
|
-
} catch {
|
|
2409
|
+
} catch (parseErr) {
|
|
2410
|
+
log(
|
|
2411
|
+
"json parse error: " + parseErr.message,
|
|
2412
|
+
0 /* DEBUG */
|
|
2413
|
+
);
|
|
2243
2414
|
}
|
|
2244
2415
|
}
|
|
2245
2416
|
}
|
|
@@ -2251,13 +2422,15 @@ import { join as join8 } from "node:path";
|
|
|
2251
2422
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
2252
2423
|
|
|
2253
2424
|
// src/shared/worker-client/functions/resolve-db-path.function.ts
|
|
2254
|
-
import { existsSync as
|
|
2255
|
-
import { join as
|
|
2425
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
2426
|
+
import { join as join6, resolve as resolve3 } from "node:path";
|
|
2256
2427
|
function resolveDbPath(targetDir) {
|
|
2257
2428
|
const base = targetDir ? resolve3(targetDir) : process.cwd();
|
|
2258
|
-
const dbPath =
|
|
2259
|
-
if (!
|
|
2260
|
-
|
|
2429
|
+
const dbPath = join6(base, ".kbdb");
|
|
2430
|
+
if (!existsSync5(dbPath)) {
|
|
2431
|
+
const msg = `database not found: ${dbPath}`;
|
|
2432
|
+
log(msg, 3 /* ERROR */);
|
|
2433
|
+
throw new Error(msg);
|
|
2261
2434
|
}
|
|
2262
2435
|
return dbPath;
|
|
2263
2436
|
}
|
|
@@ -2268,53 +2441,22 @@ async function computeContextId(absolutePath) {
|
|
|
2268
2441
|
return hash.slice(0, 16);
|
|
2269
2442
|
}
|
|
2270
2443
|
|
|
2271
|
-
// src/shared/worker-client/functions/discover-daemon.function.ts
|
|
2272
|
-
import { existsSync as existsSync5, readFileSync as readFileSync2, unlinkSync } from "node:fs";
|
|
2273
|
-
import { join as join6 } from "node:path";
|
|
2274
|
-
import { tmpdir } from "node:os";
|
|
2275
|
-
|
|
2276
|
-
// src/shared/platform/functions/is-process-alive.function.ts
|
|
2277
|
-
function isProcessAlive(pid) {
|
|
2278
|
-
try {
|
|
2279
|
-
process.kill(pid, 0);
|
|
2280
|
-
return true;
|
|
2281
|
-
} catch {
|
|
2282
|
-
return false;
|
|
2283
|
-
}
|
|
2284
|
-
}
|
|
2285
|
-
|
|
2286
|
-
// src/shared/worker-client/functions/discover-daemon.function.ts
|
|
2287
|
-
function discoverDaemon(contextId) {
|
|
2288
|
-
const pidPath = join6(tmpdir(), `kbdb-${contextId}.pid`);
|
|
2289
|
-
if (!existsSync5(pidPath)) return null;
|
|
2290
|
-
const pidStr = readFileSync2(pidPath, "utf-8").trim();
|
|
2291
|
-
const pid = parseInt(pidStr, 10);
|
|
2292
|
-
if (isNaN(pid) || !isProcessAlive(pid)) {
|
|
2293
|
-
try {
|
|
2294
|
-
unlinkSync(pidPath);
|
|
2295
|
-
} catch {
|
|
2296
|
-
}
|
|
2297
|
-
return null;
|
|
2298
|
-
}
|
|
2299
|
-
const socketPath = join6(tmpdir(), `kbdb-${contextId}.sock`);
|
|
2300
|
-
const crashPath = join6(tmpdir(), `kbdb-${contextId}.crash`);
|
|
2301
|
-
try {
|
|
2302
|
-
unlinkSync(crashPath);
|
|
2303
|
-
} catch {
|
|
2304
|
-
}
|
|
2305
|
-
return { pid, socketPath };
|
|
2306
|
-
}
|
|
2307
|
-
|
|
2308
2444
|
// src/shared/worker-client/functions/spawn-daemon.function.ts
|
|
2309
2445
|
import { spawn } from "node:child_process";
|
|
2310
2446
|
function spawnDaemon(contextPath, runtime2, workerScript2) {
|
|
2311
2447
|
if (!workerScript2) {
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
);
|
|
2448
|
+
const msg = "workerScript must be provided (resolve at entry point)";
|
|
2449
|
+
log(msg, 3 /* ERROR */);
|
|
2450
|
+
throw new Error(msg);
|
|
2315
2451
|
}
|
|
2316
2452
|
const execPath = runtime2 === "deno" ? "deno" : process.execPath;
|
|
2317
|
-
const
|
|
2453
|
+
const logLevelEnv = process.env["KBDB_LOG_LEVEL"];
|
|
2454
|
+
const logArgs = logLevelEnv ? ["--log-level", logLevelEnv] : [];
|
|
2455
|
+
const args = runtime2 === "deno" ? ["run", "--allow-all", workerScript2, contextPath, ...logArgs] : [workerScript2, contextPath, ...logArgs];
|
|
2456
|
+
log(
|
|
2457
|
+
"spawning daemon: " + execPath + " " + args.join(" "),
|
|
2458
|
+
0 /* DEBUG */
|
|
2459
|
+
);
|
|
2318
2460
|
const child = spawn(execPath, args, {
|
|
2319
2461
|
detached: true,
|
|
2320
2462
|
stdio: "ignore"
|
|
@@ -2329,12 +2471,30 @@ import { tmpdir as tmpdir2 } from "node:os";
|
|
|
2329
2471
|
var DEFAULT_TIMEOUT_MS = 1e4;
|
|
2330
2472
|
var POLL_INTERVAL_MS = 100;
|
|
2331
2473
|
async function waitForDaemon(contextId, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
2474
|
+
log("waiting for daemon: contextId=" + contextId, 0 /* DEBUG */);
|
|
2332
2475
|
const pidPath = join7(tmpdir2(), `kbdb-${contextId}.pid`);
|
|
2333
2476
|
const start = Date.now();
|
|
2477
|
+
let iteration = 0;
|
|
2334
2478
|
while (Date.now() - start < timeoutMs) {
|
|
2335
|
-
if (existsSync6(pidPath))
|
|
2479
|
+
if (existsSync6(pidPath)) {
|
|
2480
|
+
log("daemon PID file appeared", 0 /* DEBUG */);
|
|
2481
|
+
return true;
|
|
2482
|
+
}
|
|
2483
|
+
iteration++;
|
|
2484
|
+
if (iteration % 10 === 0) {
|
|
2485
|
+
const elapsed2 = Date.now() - start;
|
|
2486
|
+
log(
|
|
2487
|
+
"still waiting for daemon: elapsed=" + elapsed2.toString() + "ms",
|
|
2488
|
+
0 /* DEBUG */
|
|
2489
|
+
);
|
|
2490
|
+
}
|
|
2336
2491
|
await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
|
|
2337
2492
|
}
|
|
2493
|
+
const elapsed = Date.now() - start;
|
|
2494
|
+
log(
|
|
2495
|
+
"timed out waiting for daemon: elapsed=" + elapsed.toString() + "ms",
|
|
2496
|
+
0 /* DEBUG */
|
|
2497
|
+
);
|
|
2338
2498
|
return false;
|
|
2339
2499
|
}
|
|
2340
2500
|
|
|
@@ -2342,19 +2502,28 @@ async function waitForDaemon(contextId, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
|
2342
2502
|
async function createWorkerClient(options) {
|
|
2343
2503
|
const dbPath = options?.contextPath ?? resolveDbPath(options?.dbPath);
|
|
2344
2504
|
const contextId = await computeContextId(dbPath);
|
|
2505
|
+
log("create-worker-client: contextId=" + contextId, 0 /* DEBUG */);
|
|
2345
2506
|
const socketPath = getIpcPath(contextId);
|
|
2346
2507
|
let daemon = discoverDaemon(contextId);
|
|
2508
|
+
if (daemon) {
|
|
2509
|
+
log("daemon found: pid=" + daemon.pid.toString(), 0 /* DEBUG */);
|
|
2510
|
+
} else {
|
|
2511
|
+
log("no daemon found", 0 /* DEBUG */);
|
|
2512
|
+
}
|
|
2347
2513
|
if (!daemon && options?.autoSpawn !== false) {
|
|
2348
2514
|
const runtime2 = detectRuntime();
|
|
2515
|
+
log("auto-spawning daemon", 0 /* DEBUG */);
|
|
2349
2516
|
spawnDaemon(dbPath, runtime2, options?.workerScript);
|
|
2517
|
+
log("waiting for daemon after spawn", 0 /* DEBUG */);
|
|
2350
2518
|
await waitForDaemon(contextId, options?.connectTimeoutMs);
|
|
2351
2519
|
daemon = discoverDaemon(contextId);
|
|
2352
2520
|
}
|
|
2353
2521
|
if (!daemon) {
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
);
|
|
2522
|
+
const msg = `kbdb worker daemon did not start: ${readCrashReason(contextId)}`;
|
|
2523
|
+
log(msg, 3 /* ERROR */);
|
|
2524
|
+
throw new Error(msg);
|
|
2357
2525
|
}
|
|
2526
|
+
log("connecting to daemon", 0 /* DEBUG */);
|
|
2358
2527
|
const client = new WorkerClient(
|
|
2359
2528
|
socketPath,
|
|
2360
2529
|
contextId,
|
|
@@ -2380,27 +2549,58 @@ function readCrashReason(contextId) {
|
|
|
2380
2549
|
|
|
2381
2550
|
// src/shared/cli/functions/run-worker-stop.function.ts
|
|
2382
2551
|
async function runWorkerStop(dbDir) {
|
|
2552
|
+
log("running worker-stop", 0 /* DEBUG */);
|
|
2383
2553
|
const contextId = await computeContextId(dbDir);
|
|
2384
2554
|
const info = discoverDaemon(contextId);
|
|
2385
2555
|
if (!info) {
|
|
2386
2556
|
return { output: "no daemon running", exitCode: 0 };
|
|
2387
2557
|
}
|
|
2558
|
+
log("pid found: " + info.pid.toString(), 0 /* DEBUG */);
|
|
2388
2559
|
try {
|
|
2389
2560
|
process.kill(info.pid, "SIGTERM");
|
|
2390
|
-
|
|
2391
|
-
output: `stopped daemon (pid ${info.pid.toString()})`,
|
|
2392
|
-
exitCode: 0
|
|
2393
|
-
};
|
|
2561
|
+
log("sigterm sent to pid=" + info.pid.toString(), 0 /* DEBUG */);
|
|
2394
2562
|
} catch {
|
|
2395
2563
|
return {
|
|
2396
2564
|
error: "error: failed to stop daemon",
|
|
2397
2565
|
exitCode: 1
|
|
2398
2566
|
};
|
|
2399
2567
|
}
|
|
2568
|
+
const deadline = Date.now() + 5e3;
|
|
2569
|
+
let pollIteration = 0;
|
|
2570
|
+
while (Date.now() < deadline) {
|
|
2571
|
+
try {
|
|
2572
|
+
process.kill(info.pid, 0);
|
|
2573
|
+
} catch {
|
|
2574
|
+
log(
|
|
2575
|
+
"process exited: pid=" + info.pid.toString(),
|
|
2576
|
+
0 /* DEBUG */
|
|
2577
|
+
);
|
|
2578
|
+
break;
|
|
2579
|
+
}
|
|
2580
|
+
pollIteration++;
|
|
2581
|
+
if (pollIteration % 5 === 0) {
|
|
2582
|
+
log(
|
|
2583
|
+
"waiting for exit: pid=" + info.pid.toString() + " poll=" + pollIteration.toString(),
|
|
2584
|
+
0 /* DEBUG */
|
|
2585
|
+
);
|
|
2586
|
+
}
|
|
2587
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
2588
|
+
}
|
|
2589
|
+
if (Date.now() >= deadline) {
|
|
2590
|
+
log(
|
|
2591
|
+
"timed out waiting for exit: pid=" + info.pid.toString(),
|
|
2592
|
+
0 /* DEBUG */
|
|
2593
|
+
);
|
|
2594
|
+
}
|
|
2595
|
+
return {
|
|
2596
|
+
output: `stopped daemon (pid ${info.pid.toString()})`,
|
|
2597
|
+
exitCode: 0
|
|
2598
|
+
};
|
|
2400
2599
|
}
|
|
2401
2600
|
|
|
2402
2601
|
// src/shared/cli/functions/run-worker-restart.function.ts
|
|
2403
2602
|
async function runWorkerRestart(dbDir) {
|
|
2603
|
+
log("running worker-restart", 0 /* DEBUG */);
|
|
2404
2604
|
const stopResult = await runWorkerStop(dbDir);
|
|
2405
2605
|
if (stopResult.exitCode !== 0) return stopResult;
|
|
2406
2606
|
return {
|
|
@@ -2418,20 +2618,44 @@ function resolveRawDbPath(options) {
|
|
|
2418
2618
|
async function retryOnTimeout(createClient, operation, maxRetries) {
|
|
2419
2619
|
let lastError = new Error("retryOnTimeout exhausted");
|
|
2420
2620
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
2621
|
+
log(
|
|
2622
|
+
"retry-on-timeout: attempt=" + attempt.toString() + " max=" + maxRetries.toString(),
|
|
2623
|
+
0 /* DEBUG */
|
|
2624
|
+
);
|
|
2421
2625
|
const client = await createClient();
|
|
2422
2626
|
try {
|
|
2423
2627
|
const result = await operation(client);
|
|
2628
|
+
log(
|
|
2629
|
+
"retry-on-timeout: success on attempt=" + attempt.toString(),
|
|
2630
|
+
0 /* DEBUG */
|
|
2631
|
+
);
|
|
2424
2632
|
return { client, result };
|
|
2425
2633
|
} catch (err) {
|
|
2426
2634
|
const code = err.code;
|
|
2427
2635
|
if (code !== "REQUEST_TIMEOUT" || attempt >= maxRetries) {
|
|
2636
|
+
log(
|
|
2637
|
+
"retry-on-timeout: non-retriable error code=" + String(code),
|
|
2638
|
+
0 /* DEBUG */
|
|
2639
|
+
);
|
|
2428
2640
|
client.disconnect();
|
|
2429
2641
|
throw err;
|
|
2430
2642
|
}
|
|
2431
2643
|
lastError = err;
|
|
2432
|
-
client.
|
|
2644
|
+
if (client.killDaemon) {
|
|
2645
|
+
log(
|
|
2646
|
+
"retry " + String(attempt + 1) + "/" + String(maxRetries) + ": killing daemon",
|
|
2647
|
+
2 /* WARNING */
|
|
2648
|
+
);
|
|
2649
|
+
client.killDaemon();
|
|
2650
|
+
} else {
|
|
2651
|
+
client.disconnect();
|
|
2652
|
+
}
|
|
2433
2653
|
}
|
|
2434
2654
|
}
|
|
2655
|
+
log(
|
|
2656
|
+
"retry-on-timeout: all retries exhausted max=" + maxRetries.toString(),
|
|
2657
|
+
0 /* DEBUG */
|
|
2658
|
+
);
|
|
2435
2659
|
throw lastError;
|
|
2436
2660
|
}
|
|
2437
2661
|
|
|
@@ -2444,8 +2668,22 @@ var DEFAULT_RETRY_COUNT = 5;
|
|
|
2444
2668
|
// src/shared/cli/functions/run-cli.function.ts
|
|
2445
2669
|
async function runCli(argv, deps2) {
|
|
2446
2670
|
const options = parseArgs(argv);
|
|
2671
|
+
const logLevel = resolveLogLevel(options.logLevel);
|
|
2672
|
+
configureLog({ level: logLevel });
|
|
2673
|
+
log("command: " + options.command, 0 /* DEBUG */);
|
|
2674
|
+
if (options.command === "init") {
|
|
2675
|
+
log('--init is deprecated, use "kbdb db init"', 2 /* WARNING */);
|
|
2676
|
+
}
|
|
2677
|
+
if (options.command === "migrate") {
|
|
2678
|
+
log(
|
|
2679
|
+
'--migrate is deprecated, use "kbdb db migrate"',
|
|
2680
|
+
2 /* WARNING */
|
|
2681
|
+
);
|
|
2682
|
+
}
|
|
2683
|
+
const nonInteractive = options.nonInteractive || process.env["KBDB_NON_INTERACTIVE"] === "1" || process.env["KBDB_NON_INTERACTIVE"] === "true";
|
|
2684
|
+
const effectiveDeps = nonInteractive ? { ...deps2, isStdinTty: () => false } : deps2;
|
|
2447
2685
|
if (!options.formatExplicit) {
|
|
2448
|
-
options.format =
|
|
2686
|
+
options.format = effectiveDeps.isStdoutTty() ? "text" : "json";
|
|
2449
2687
|
}
|
|
2450
2688
|
if (options.command === "help" || !options.command) {
|
|
2451
2689
|
const helpCommand = options.args[0];
|
|
@@ -2460,21 +2698,29 @@ async function runCli(argv, deps2) {
|
|
|
2460
2698
|
return { output: VERSION, exitCode: 0 };
|
|
2461
2699
|
}
|
|
2462
2700
|
if (options.command === "init" || options.command === "db-init") {
|
|
2463
|
-
return handleInit(options,
|
|
2701
|
+
return handleInit(options, effectiveDeps);
|
|
2464
2702
|
}
|
|
2465
2703
|
if (options.command === "mcp") {
|
|
2466
|
-
return handleMcp(options,
|
|
2704
|
+
return handleMcp(options, effectiveDeps);
|
|
2467
2705
|
}
|
|
2468
2706
|
if (options.command === "migrate" || options.command === "db-migrate") {
|
|
2469
|
-
return handleMigrate(options,
|
|
2707
|
+
return handleMigrate(options, effectiveDeps);
|
|
2470
2708
|
}
|
|
2471
2709
|
if (options.command === "worker-stop") {
|
|
2472
|
-
return handleWorkerLifecycle(
|
|
2710
|
+
return handleWorkerLifecycle(
|
|
2711
|
+
options,
|
|
2712
|
+
effectiveDeps,
|
|
2713
|
+
runWorkerStop
|
|
2714
|
+
);
|
|
2473
2715
|
}
|
|
2474
2716
|
if (options.command === "worker-restart") {
|
|
2475
|
-
return handleWorkerLifecycle(
|
|
2717
|
+
return handleWorkerLifecycle(
|
|
2718
|
+
options,
|
|
2719
|
+
effectiveDeps,
|
|
2720
|
+
runWorkerRestart
|
|
2721
|
+
);
|
|
2476
2722
|
}
|
|
2477
|
-
return handleDataCommand(options,
|
|
2723
|
+
return handleDataCommand(options, effectiveDeps);
|
|
2478
2724
|
}
|
|
2479
2725
|
function handleInit(options, deps2) {
|
|
2480
2726
|
const result = deps2.runInit(options);
|
|
@@ -2615,6 +2861,7 @@ async function handleDataCommand(options, deps2) {
|
|
|
2615
2861
|
}
|
|
2616
2862
|
dbDir = initResult.targetPath;
|
|
2617
2863
|
}
|
|
2864
|
+
log("db path: " + dbDir, 0 /* DEBUG */);
|
|
2618
2865
|
const timeoutMs = resolveTimeoutMs(options);
|
|
2619
2866
|
const maxRetries = resolveRetryCount(options);
|
|
2620
2867
|
try {
|
|
@@ -3387,6 +3634,7 @@ function asStringArray2(value) {
|
|
|
3387
3634
|
return [];
|
|
3388
3635
|
}
|
|
3389
3636
|
async function handleToolCall(client, name, args) {
|
|
3637
|
+
log("tool call: " + name, 0 /* DEBUG */);
|
|
3390
3638
|
try {
|
|
3391
3639
|
switch (name) {
|
|
3392
3640
|
case "search":
|
|
@@ -3430,6 +3678,7 @@ async function handleToolCall(client, name, args) {
|
|
|
3430
3678
|
case "auto-capture-review":
|
|
3431
3679
|
return handleAutoCaptureReview();
|
|
3432
3680
|
default:
|
|
3681
|
+
log("unknown tool: " + name, 2 /* WARNING */);
|
|
3433
3682
|
return {
|
|
3434
3683
|
content: [
|
|
3435
3684
|
{
|
|
@@ -3441,6 +3690,10 @@ async function handleToolCall(client, name, args) {
|
|
|
3441
3690
|
};
|
|
3442
3691
|
}
|
|
3443
3692
|
} catch (err) {
|
|
3693
|
+
log(
|
|
3694
|
+
"tool call failed: " + name + ": " + (err instanceof Error ? err.message : String(err)),
|
|
3695
|
+
3 /* ERROR */
|
|
3696
|
+
);
|
|
3444
3697
|
return {
|
|
3445
3698
|
content: [
|
|
3446
3699
|
{
|
|
@@ -3815,6 +4068,7 @@ async function handleResourceRead(client, uri) {
|
|
|
3815
4068
|
]
|
|
3816
4069
|
};
|
|
3817
4070
|
}
|
|
4071
|
+
log(`Unknown resource URI: ${uri}`, 3 /* ERROR */);
|
|
3818
4072
|
throw new Error(`Unknown resource URI: ${uri}`);
|
|
3819
4073
|
}
|
|
3820
4074
|
|
|
@@ -3891,6 +4145,7 @@ async function handleAgentPrompt(name, client) {
|
|
|
3891
4145
|
const agents = await client.listDocumentsByType("agent");
|
|
3892
4146
|
const doc = agents.find((a) => a.title === agentName);
|
|
3893
4147
|
if (!doc) {
|
|
4148
|
+
log("agent not found: " + agentName, 3 /* ERROR */);
|
|
3894
4149
|
throw new Error("agent not found: " + agentName);
|
|
3895
4150
|
}
|
|
3896
4151
|
const sections = doc.sections;
|
|
@@ -3935,6 +4190,7 @@ async function handleSkillPrompt(name, promptArgs, client) {
|
|
|
3935
4190
|
}
|
|
3936
4191
|
}
|
|
3937
4192
|
if (matchContent === void 0) {
|
|
4193
|
+
log(`Prompt not found: ${name}`, 3 /* ERROR */);
|
|
3938
4194
|
throw new Error(`Prompt not found: ${name}`);
|
|
3939
4195
|
}
|
|
3940
4196
|
const parsed = JSON.parse(matchContent);
|
|
@@ -4048,6 +4304,7 @@ function isSamplingResponse(v) {
|
|
|
4048
4304
|
async function runAutoCapture(controller, config, client, hostCapabilities, requestSampling) {
|
|
4049
4305
|
try {
|
|
4050
4306
|
const trigger = controller.evaluate();
|
|
4307
|
+
log("auto-capture trigger evaluated", 0 /* DEBUG */);
|
|
4051
4308
|
if (!trigger.shouldCapture) return;
|
|
4052
4309
|
if (!hasSamplingCapability(hostCapabilities)) return;
|
|
4053
4310
|
const prompt = buildCapturePrompt("recent conversation context");
|
|
@@ -4059,17 +4316,20 @@ async function runAutoCapture(controller, config, client, hostCapabilities, requ
|
|
|
4059
4316
|
const text = raw.content.text.trim();
|
|
4060
4317
|
if (!text) return;
|
|
4061
4318
|
if (config.dryRun) return;
|
|
4319
|
+
log("auto-capture storing knowledge", 0 /* DEBUG */);
|
|
4062
4320
|
await client.addSection({
|
|
4063
4321
|
sectionType: "text/markdown",
|
|
4064
4322
|
content: text,
|
|
4065
4323
|
title: "Auto-captured knowledge"
|
|
4066
4324
|
});
|
|
4067
4325
|
} catch {
|
|
4326
|
+
log("auto-capture error (non-fatal)", 0 /* DEBUG */);
|
|
4068
4327
|
}
|
|
4069
4328
|
}
|
|
4070
4329
|
|
|
4071
4330
|
// src/shared/auto-capture/functions/evaluate-trigger.function.ts
|
|
4072
4331
|
function evaluateTrigger(config, state) {
|
|
4332
|
+
log("evaluating auto-capture trigger conditions", 0 /* DEBUG */);
|
|
4073
4333
|
if (!config.enabled) {
|
|
4074
4334
|
return {
|
|
4075
4335
|
shouldCapture: false,
|
|
@@ -4121,6 +4381,7 @@ var AutoCaptureController = class {
|
|
|
4121
4381
|
* @returns the trigger decision with a human-readable reason
|
|
4122
4382
|
*/
|
|
4123
4383
|
evaluate() {
|
|
4384
|
+
log("evaluating auto-capture trigger", 0 /* DEBUG */);
|
|
4124
4385
|
const trigger = evaluateTrigger(this.config, this.state());
|
|
4125
4386
|
if (trigger.shouldCapture) {
|
|
4126
4387
|
this.totalCapturesThisSession += 1;
|
|
@@ -4131,6 +4392,7 @@ var AutoCaptureController = class {
|
|
|
4131
4392
|
}
|
|
4132
4393
|
/** Reset all counters, e.g. on client disconnect. */
|
|
4133
4394
|
reset() {
|
|
4395
|
+
log("resetting auto-capture controller", 0 /* DEBUG */);
|
|
4134
4396
|
this.toolCallsSinceLastCapture = 0;
|
|
4135
4397
|
this.lastCaptureTimestamp = 0;
|
|
4136
4398
|
this.totalCapturesThisSession = 0;
|
|
@@ -4181,10 +4443,12 @@ var McpServer = class {
|
|
|
4181
4443
|
}
|
|
4182
4444
|
async reconnectClient() {
|
|
4183
4445
|
if (!this.clientFactory) {
|
|
4446
|
+
log("no client factory for reconnect", 3 /* ERROR */);
|
|
4184
4447
|
throw new Error("no client factory for reconnect");
|
|
4185
4448
|
}
|
|
4186
4449
|
this.client.disconnect();
|
|
4187
4450
|
this.client = await this.clientFactory();
|
|
4451
|
+
log("MCP client reconnected", 0 /* DEBUG */);
|
|
4188
4452
|
}
|
|
4189
4453
|
async withRetry(fn) {
|
|
4190
4454
|
for (let attempt = 0; ; attempt++) {
|
|
@@ -4195,6 +4459,10 @@ var McpServer = class {
|
|
|
4195
4459
|
if (code !== "REQUEST_TIMEOUT" || attempt >= this.maxRetries || !this.clientFactory) {
|
|
4196
4460
|
throw err;
|
|
4197
4461
|
}
|
|
4462
|
+
log(
|
|
4463
|
+
"request timeout, reconnecting (attempt " + (attempt + 1).toString() + "/" + this.maxRetries.toString() + ")",
|
|
4464
|
+
2 /* WARNING */
|
|
4465
|
+
);
|
|
4198
4466
|
await this.reconnectClient();
|
|
4199
4467
|
}
|
|
4200
4468
|
}
|
|
@@ -4204,6 +4472,7 @@ var McpServer = class {
|
|
|
4204
4472
|
input: process.stdin,
|
|
4205
4473
|
terminal: false
|
|
4206
4474
|
});
|
|
4475
|
+
log("MCP server listening on stdin", 0 /* DEBUG */);
|
|
4207
4476
|
let pending = Promise.resolve();
|
|
4208
4477
|
await new Promise((resolve4) => {
|
|
4209
4478
|
rl.on("line", (line) => {
|
|
@@ -4214,6 +4483,7 @@ var McpServer = class {
|
|
|
4214
4483
|
this.autoCaptureController?.reset();
|
|
4215
4484
|
this.autoCaptureController = null;
|
|
4216
4485
|
this.client.disconnect();
|
|
4486
|
+
log("MCP stdin closed", 0 /* DEBUG */);
|
|
4217
4487
|
resolve4();
|
|
4218
4488
|
});
|
|
4219
4489
|
});
|
|
@@ -4277,6 +4547,7 @@ var McpServer = class {
|
|
|
4277
4547
|
*/
|
|
4278
4548
|
async requestSampling(messages, maxTokens) {
|
|
4279
4549
|
if (!this.hostCapabilities?.["sampling"]) {
|
|
4550
|
+
log("Host does not support sampling", 3 /* ERROR */);
|
|
4280
4551
|
throw new Error("Host does not support sampling");
|
|
4281
4552
|
}
|
|
4282
4553
|
return this.sendRequest("sampling/createMessage", {
|
|
@@ -4323,10 +4594,12 @@ var McpServer = class {
|
|
|
4323
4594
|
return null;
|
|
4324
4595
|
}
|
|
4325
4596
|
const request = parsed;
|
|
4597
|
+
log("MCP request: " + request.method, 0 /* DEBUG */);
|
|
4326
4598
|
if (request.id === void 0) {
|
|
4327
4599
|
if (request.method === "notifications/initialized" || request.method === "notifications/cancelled") {
|
|
4328
4600
|
if (request.method === "notifications/initialized" && !this.initialized) {
|
|
4329
4601
|
this.initialized = true;
|
|
4602
|
+
log("MCP initialized", 1 /* INFO */);
|
|
4330
4603
|
if (this.autoCaptureConfig !== null) {
|
|
4331
4604
|
this.autoCaptureController = new AutoCaptureController(this.autoCaptureConfig);
|
|
4332
4605
|
}
|
|
@@ -4563,6 +4836,7 @@ var McpServer = class {
|
|
|
4563
4836
|
|
|
4564
4837
|
// src/shared/mcp/functions/create-mcp-server.function.ts
|
|
4565
4838
|
function createMcpServer(client, contextPath, autoCaptureConfig, clientFactory, maxRetries) {
|
|
4839
|
+
log("creating MCP server", 0 /* DEBUG */);
|
|
4566
4840
|
return new McpServer(
|
|
4567
4841
|
client,
|
|
4568
4842
|
contextPath,
|
|
@@ -4584,6 +4858,7 @@ var deps = {
|
|
|
4584
4858
|
findDb,
|
|
4585
4859
|
runInit,
|
|
4586
4860
|
startMcpServer: async (contextPath, clientFactory, maxRetries) => {
|
|
4861
|
+
log("starting MCP server", 1 /* INFO */);
|
|
4587
4862
|
const client = await createWorkerClient({
|
|
4588
4863
|
contextPath,
|
|
4589
4864
|
workerScript
|
|
@@ -4604,7 +4879,9 @@ var deps = {
|
|
|
4604
4879
|
clientFactory,
|
|
4605
4880
|
maxRetries
|
|
4606
4881
|
);
|
|
4882
|
+
log("MCP server listening on stdio", 0 /* DEBUG */);
|
|
4607
4883
|
await server.listen();
|
|
4884
|
+
log("MCP server closed", 1 /* INFO */);
|
|
4608
4885
|
} finally {
|
|
4609
4886
|
client.disconnect();
|
|
4610
4887
|
}
|
|
@@ -4616,7 +4893,7 @@ async function main() {
|
|
|
4616
4893
|
console.log(result.output);
|
|
4617
4894
|
}
|
|
4618
4895
|
if (result.error) {
|
|
4619
|
-
|
|
4896
|
+
log(result.error, 3 /* ERROR */);
|
|
4620
4897
|
}
|
|
4621
4898
|
if (result.exitCode !== 0) {
|
|
4622
4899
|
process.exitCode = result.exitCode;
|
|
@@ -4624,7 +4901,7 @@ async function main() {
|
|
|
4624
4901
|
}
|
|
4625
4902
|
main().catch((err) => {
|
|
4626
4903
|
const msg = err instanceof Error ? err.message : String(err);
|
|
4627
|
-
|
|
4904
|
+
log("error: " + msg, 3 /* ERROR */);
|
|
4628
4905
|
process.exitCode = 1;
|
|
4629
4906
|
});
|
|
4630
4907
|
//# sourceMappingURL=cli.mjs.map
|