@danielsimonjr/memoryjs 2.1.1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli/index.js +1472 -599
- package/dist/cli/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -11245,7 +11245,7 @@ var init_GraphTraversal = __esm({
|
|
|
11245
11245
|
Object.entries(options).filter(([, v]) => v !== void 0)
|
|
11246
11246
|
);
|
|
11247
11247
|
const opts = { ...DEFAULT_OPTIONS, ...definedOptions };
|
|
11248
|
-
const
|
|
11248
|
+
const neighbors2 = [];
|
|
11249
11249
|
let relations = [];
|
|
11250
11250
|
if (opts.direction === "outgoing" || opts.direction === "both") {
|
|
11251
11251
|
relations = relations.concat(this.storage.getRelationsFrom(entityName));
|
|
@@ -11266,9 +11266,9 @@ var init_GraphTraversal = __esm({
|
|
|
11266
11266
|
const typeSet = new Set(opts.entityTypes.map((t) => t.toLowerCase()));
|
|
11267
11267
|
if (!typeSet.has(entity.entityType.toLowerCase())) continue;
|
|
11268
11268
|
}
|
|
11269
|
-
|
|
11269
|
+
neighbors2.push({ neighbor, relation });
|
|
11270
11270
|
}
|
|
11271
|
-
return
|
|
11271
|
+
return neighbors2;
|
|
11272
11272
|
}
|
|
11273
11273
|
/**
|
|
11274
11274
|
* Breadth-First Search traversal starting from a given entity.
|
|
@@ -11294,8 +11294,8 @@ var init_GraphTraversal = __esm({
|
|
|
11294
11294
|
if (depth > opts.maxDepth) continue;
|
|
11295
11295
|
nodes.push(node);
|
|
11296
11296
|
depths.set(node, depth);
|
|
11297
|
-
const
|
|
11298
|
-
for (const { neighbor } of
|
|
11297
|
+
const neighbors2 = this.getNeighborsWithRelations(node, opts);
|
|
11298
|
+
for (const { neighbor } of neighbors2) {
|
|
11299
11299
|
if (!visited.has(neighbor)) {
|
|
11300
11300
|
visited.add(neighbor);
|
|
11301
11301
|
queue.push({ node: neighbor, depth: depth + 1 });
|
|
@@ -11330,8 +11330,8 @@ var init_GraphTraversal = __esm({
|
|
|
11330
11330
|
visited.add(node);
|
|
11331
11331
|
nodes.push(node);
|
|
11332
11332
|
depths.set(node, depth);
|
|
11333
|
-
const
|
|
11334
|
-
for (const { neighbor } of
|
|
11333
|
+
const neighbors2 = this.getNeighborsWithRelations(node, opts);
|
|
11334
|
+
for (const { neighbor } of neighbors2) {
|
|
11335
11335
|
if (!visited.has(neighbor)) {
|
|
11336
11336
|
stack.push({ node: neighbor, depth: depth + 1 });
|
|
11337
11337
|
if (!parents.has(neighbor)) {
|
|
@@ -11378,8 +11378,8 @@ var init_GraphTraversal = __esm({
|
|
|
11378
11378
|
}
|
|
11379
11379
|
return result;
|
|
11380
11380
|
}
|
|
11381
|
-
const
|
|
11382
|
-
for (const { neighbor, relation } of
|
|
11381
|
+
const neighbors2 = this.getNeighborsWithRelations(current, opts);
|
|
11382
|
+
for (const { neighbor, relation } of neighbors2) {
|
|
11383
11383
|
if (!visited.has(neighbor)) {
|
|
11384
11384
|
visited.add(neighbor);
|
|
11385
11385
|
queue.push(neighbor);
|
|
@@ -11453,8 +11453,8 @@ var init_GraphTraversal = __esm({
|
|
|
11453
11453
|
});
|
|
11454
11454
|
return;
|
|
11455
11455
|
}
|
|
11456
|
-
const
|
|
11457
|
-
for (const { neighbor, relation } of
|
|
11456
|
+
const neighbors2 = this.getNeighborsWithRelations(current, opts);
|
|
11457
|
+
for (const { neighbor, relation } of neighbors2) {
|
|
11458
11458
|
if (!visited.has(neighbor)) {
|
|
11459
11459
|
visited.add(neighbor);
|
|
11460
11460
|
currentPath.push(neighbor);
|
|
@@ -11498,8 +11498,8 @@ var init_GraphTraversal = __esm({
|
|
|
11498
11498
|
while (queue.length > 0) {
|
|
11499
11499
|
const current = queue.shift();
|
|
11500
11500
|
component.push(current);
|
|
11501
|
-
const
|
|
11502
|
-
for (const { neighbor } of
|
|
11501
|
+
const neighbors2 = this.getNeighborsWithRelations(current, { direction: "both" });
|
|
11502
|
+
for (const { neighbor } of neighbors2) {
|
|
11503
11503
|
if (!visited.has(neighbor)) {
|
|
11504
11504
|
visited.add(neighbor);
|
|
11505
11505
|
queue.push(neighbor);
|
|
@@ -11594,8 +11594,8 @@ var init_GraphTraversal = __esm({
|
|
|
11594
11594
|
while (queue.length > 0) {
|
|
11595
11595
|
const v = queue.shift();
|
|
11596
11596
|
stack.push(v);
|
|
11597
|
-
const
|
|
11598
|
-
for (const { neighbor: w } of
|
|
11597
|
+
const neighbors2 = this.getNeighborsWithRelations(v, { direction: "both" });
|
|
11598
|
+
for (const { neighbor: w } of neighbors2) {
|
|
11599
11599
|
if (distance.get(w) === -1) {
|
|
11600
11600
|
distance.set(w, distance.get(v) + 1);
|
|
11601
11601
|
queue.push(w);
|
|
@@ -33370,11 +33370,11 @@ var init_CausalReasoner = __esm({
|
|
|
33370
33370
|
if (d > depth) return;
|
|
33371
33371
|
inPath.add(node);
|
|
33372
33372
|
path6.push(node);
|
|
33373
|
-
const
|
|
33373
|
+
const neighbors2 = this.traversal.getNeighborsWithRelations(node, {
|
|
33374
33374
|
relationTypes: this.causalTypes,
|
|
33375
33375
|
direction: "outgoing"
|
|
33376
33376
|
});
|
|
33377
|
-
for (const { neighbor, relation } of
|
|
33377
|
+
for (const { neighbor, relation } of neighbors2) {
|
|
33378
33378
|
if (inPath.has(neighbor)) {
|
|
33379
33379
|
const idx = path6.indexOf(neighbor);
|
|
33380
33380
|
if (idx >= 0) {
|
|
@@ -35164,657 +35164,940 @@ var init_ManagerContext = __esm({
|
|
|
35164
35164
|
}
|
|
35165
35165
|
});
|
|
35166
35166
|
|
|
35167
|
-
// src/cli/
|
|
35168
|
-
|
|
35169
|
-
|
|
35170
|
-
|
|
35171
|
-
|
|
35172
|
-
|
|
35173
|
-
|
|
35174
|
-
|
|
35175
|
-
|
|
35176
|
-
const interactiveCtx = {
|
|
35177
|
-
ctx,
|
|
35178
|
-
options,
|
|
35179
|
-
history: []
|
|
35167
|
+
// src/cli/options.ts
|
|
35168
|
+
function parseGlobalOptions(opts) {
|
|
35169
|
+
const rawFormat = opts.outputFormat;
|
|
35170
|
+
const format = rawFormat && ["json", "table", "csv"].includes(rawFormat) ? rawFormat : defaultOptions.format;
|
|
35171
|
+
return {
|
|
35172
|
+
storage: opts.storage || defaultOptions.storage,
|
|
35173
|
+
format,
|
|
35174
|
+
quiet: Boolean(opts.quiet),
|
|
35175
|
+
verbose: Boolean(opts.verbose)
|
|
35180
35176
|
};
|
|
35181
|
-
|
|
35182
|
-
|
|
35183
|
-
|
|
35184
|
-
|
|
35185
|
-
|
|
35186
|
-
|
|
35187
|
-
|
|
35188
|
-
|
|
35189
|
-
|
|
35190
|
-
|
|
35191
|
-
|
|
35192
|
-
|
|
35193
|
-
|
|
35194
|
-
|
|
35195
|
-
|
|
35196
|
-
|
|
35197
|
-
|
|
35198
|
-
|
|
35199
|
-
|
|
35200
|
-
|
|
35201
|
-
|
|
35202
|
-
|
|
35203
|
-
|
|
35204
|
-
|
|
35205
|
-
|
|
35206
|
-
|
|
35177
|
+
}
|
|
35178
|
+
function createLogger(options) {
|
|
35179
|
+
return {
|
|
35180
|
+
info: (msg) => !options.quiet && console.log(msg),
|
|
35181
|
+
debug: (msg) => options.verbose && console.log(`[DEBUG] ${msg}`),
|
|
35182
|
+
error: (msg) => console.error(`[ERROR] ${msg}`),
|
|
35183
|
+
warn: (msg) => !options.quiet && console.warn(`[WARN] ${msg}`)
|
|
35184
|
+
};
|
|
35185
|
+
}
|
|
35186
|
+
var defaultOptions;
|
|
35187
|
+
var init_options = __esm({
|
|
35188
|
+
"src/cli/options.ts"() {
|
|
35189
|
+
"use strict";
|
|
35190
|
+
init_esm_shims();
|
|
35191
|
+
defaultOptions = {
|
|
35192
|
+
storage: process.env.MEMORYJS_STORAGE_PATH || "./memory.jsonl",
|
|
35193
|
+
format: process.env.MEMORYJS_OUTPUT_FORMAT || "json",
|
|
35194
|
+
quiet: false,
|
|
35195
|
+
verbose: false
|
|
35196
|
+
};
|
|
35197
|
+
}
|
|
35198
|
+
});
|
|
35199
|
+
|
|
35200
|
+
// src/cli/config.ts
|
|
35201
|
+
import { existsSync as existsSync2, readFileSync } from "fs";
|
|
35202
|
+
import { resolve as resolve2, dirname as dirname8 } from "path";
|
|
35203
|
+
function findConfigFile(startDir = process.cwd()) {
|
|
35204
|
+
let currentDir = startDir;
|
|
35205
|
+
const root = resolve2("/");
|
|
35206
|
+
while (currentDir !== root) {
|
|
35207
|
+
for (const filename of CONFIG_FILES) {
|
|
35208
|
+
const configPath = resolve2(currentDir, filename);
|
|
35209
|
+
if (existsSync2(configPath)) {
|
|
35210
|
+
return configPath;
|
|
35211
|
+
}
|
|
35207
35212
|
}
|
|
35208
|
-
|
|
35209
|
-
|
|
35210
|
-
|
|
35211
|
-
|
|
35212
|
-
|
|
35213
|
-
|
|
35214
|
-
|
|
35215
|
-
|
|
35216
|
-
|
|
35213
|
+
const parentDir = dirname8(currentDir);
|
|
35214
|
+
if (parentDir === currentDir) break;
|
|
35215
|
+
currentDir = parentDir;
|
|
35216
|
+
}
|
|
35217
|
+
return null;
|
|
35218
|
+
}
|
|
35219
|
+
function loadConfig(configPath) {
|
|
35220
|
+
try {
|
|
35221
|
+
const content = readFileSync(configPath, "utf-8");
|
|
35222
|
+
const config = JSON.parse(content);
|
|
35223
|
+
return validateConfig2(config);
|
|
35224
|
+
} catch (error) {
|
|
35225
|
+
console.warn(`Warning: Failed to load config from ${configPath}`);
|
|
35226
|
+
return {};
|
|
35227
|
+
}
|
|
35228
|
+
}
|
|
35229
|
+
function validateConfig2(config) {
|
|
35230
|
+
const validated = {};
|
|
35231
|
+
if (typeof config.storage === "string") {
|
|
35232
|
+
validated.storage = config.storage;
|
|
35233
|
+
}
|
|
35234
|
+
if (config.format && ["json", "table", "csv"].includes(config.format)) {
|
|
35235
|
+
validated.format = config.format;
|
|
35236
|
+
}
|
|
35237
|
+
if (typeof config.quiet === "boolean") {
|
|
35238
|
+
validated.quiet = config.quiet;
|
|
35239
|
+
}
|
|
35240
|
+
if (typeof config.verbose === "boolean") {
|
|
35241
|
+
validated.verbose = config.verbose;
|
|
35242
|
+
}
|
|
35243
|
+
return validated;
|
|
35244
|
+
}
|
|
35245
|
+
function mergeConfig2(fileConfig, cliOptions) {
|
|
35246
|
+
return {
|
|
35247
|
+
storage: cliOptions.storage ?? fileConfig.storage ?? "./memory.jsonl",
|
|
35248
|
+
format: cliOptions.format ?? fileConfig.format ?? "json",
|
|
35249
|
+
quiet: cliOptions.quiet ?? fileConfig.quiet ?? false,
|
|
35250
|
+
verbose: cliOptions.verbose ?? fileConfig.verbose ?? false
|
|
35251
|
+
};
|
|
35252
|
+
}
|
|
35253
|
+
var CONFIG_FILES;
|
|
35254
|
+
var init_config = __esm({
|
|
35255
|
+
"src/cli/config.ts"() {
|
|
35256
|
+
"use strict";
|
|
35257
|
+
init_esm_shims();
|
|
35258
|
+
CONFIG_FILES = [
|
|
35259
|
+
".memoryjsrc",
|
|
35260
|
+
".memoryjsrc.json",
|
|
35261
|
+
"memoryjs.config.json"
|
|
35262
|
+
];
|
|
35263
|
+
}
|
|
35264
|
+
});
|
|
35265
|
+
|
|
35266
|
+
// src/cli/formatters.ts
|
|
35267
|
+
import Table from "cli-table3";
|
|
35268
|
+
import chalk from "chalk";
|
|
35269
|
+
function getTerminalWidth() {
|
|
35270
|
+
return process.stdout.columns || 80;
|
|
35271
|
+
}
|
|
35272
|
+
function formatEntities(entities, format) {
|
|
35273
|
+
if (entities.length === 0) {
|
|
35274
|
+
return format === "json" ? "[]" : "No entities found.";
|
|
35275
|
+
}
|
|
35276
|
+
switch (format) {
|
|
35277
|
+
case "json":
|
|
35278
|
+
return JSON.stringify(entities, null, 2);
|
|
35279
|
+
case "table": {
|
|
35280
|
+
const table = new Table({
|
|
35281
|
+
head: [chalk.cyan("Name"), chalk.cyan("Type"), chalk.cyan("Observations"), chalk.cyan("Tags")],
|
|
35282
|
+
colWidths: calculateColWidths(getTerminalWidth(), [0.25, 0.15, 0.4, 0.2]),
|
|
35283
|
+
wordWrap: true
|
|
35284
|
+
});
|
|
35285
|
+
for (const entity of entities) {
|
|
35286
|
+
table.push([
|
|
35287
|
+
entity.name,
|
|
35288
|
+
entity.entityType,
|
|
35289
|
+
(entity.observations || []).slice(0, 3).join("; ") + (entity.observations && entity.observations.length > 3 ? "..." : ""),
|
|
35290
|
+
(entity.tags || []).join(", ")
|
|
35291
|
+
]);
|
|
35292
|
+
}
|
|
35293
|
+
return table.toString();
|
|
35217
35294
|
}
|
|
35218
|
-
|
|
35219
|
-
|
|
35220
|
-
|
|
35221
|
-
|
|
35222
|
-
|
|
35295
|
+
case "csv": {
|
|
35296
|
+
const header = "name,entityType,observations,tags";
|
|
35297
|
+
const rows = entities.map((e) => [
|
|
35298
|
+
escapeCSV(e.name),
|
|
35299
|
+
escapeCSV(e.entityType),
|
|
35300
|
+
escapeCSV((e.observations || []).join("; ")),
|
|
35301
|
+
escapeCSV((e.tags || []).join(", "))
|
|
35302
|
+
].join(","));
|
|
35303
|
+
return [header, ...rows].join("\n");
|
|
35223
35304
|
}
|
|
35224
|
-
|
|
35225
|
-
});
|
|
35226
|
-
rl.on("close", () => {
|
|
35227
|
-
console.log(chalk2.gray("\nGoodbye!"));
|
|
35228
|
-
process.exit(0);
|
|
35229
|
-
});
|
|
35305
|
+
}
|
|
35230
35306
|
}
|
|
35231
|
-
|
|
35232
|
-
|
|
35233
|
-
|
|
35234
|
-
|
|
35235
|
-
|
|
35236
|
-
case "
|
|
35237
|
-
|
|
35238
|
-
|
|
35239
|
-
|
|
35240
|
-
|
|
35241
|
-
|
|
35242
|
-
|
|
35243
|
-
|
|
35244
|
-
|
|
35245
|
-
case ".clear":
|
|
35246
|
-
console.clear();
|
|
35247
|
-
break;
|
|
35248
|
-
case "entities":
|
|
35249
|
-
case "ls": {
|
|
35250
|
-
const graph = await ctx.storage.loadGraph();
|
|
35251
|
-
const entities = graph.entities;
|
|
35252
|
-
console.log(`
|
|
35253
|
-
Entities (${entities.length}):`);
|
|
35254
|
-
for (const e of entities.slice(0, 20)) {
|
|
35255
|
-
console.log(` ${chalk2.cyan(e.name)} [${e.entityType}]`);
|
|
35256
|
-
}
|
|
35257
|
-
if (entities.length > 20) {
|
|
35258
|
-
console.log(` ... and ${entities.length - 20} more`);
|
|
35307
|
+
function formatRelations(relations, format) {
|
|
35308
|
+
if (relations.length === 0) {
|
|
35309
|
+
return format === "json" ? "[]" : "No relations found.";
|
|
35310
|
+
}
|
|
35311
|
+
switch (format) {
|
|
35312
|
+
case "json":
|
|
35313
|
+
return JSON.stringify(relations, null, 2);
|
|
35314
|
+
case "table": {
|
|
35315
|
+
const table = new Table({
|
|
35316
|
+
head: [chalk.cyan("From"), chalk.cyan("Relation"), chalk.cyan("To")],
|
|
35317
|
+
colWidths: calculateColWidths(getTerminalWidth(), [0.35, 0.3, 0.35])
|
|
35318
|
+
});
|
|
35319
|
+
for (const rel of relations) {
|
|
35320
|
+
table.push([rel.from, rel.relationType, rel.to]);
|
|
35259
35321
|
}
|
|
35260
|
-
|
|
35322
|
+
return table.toString();
|
|
35261
35323
|
}
|
|
35262
|
-
case "
|
|
35263
|
-
const
|
|
35264
|
-
|
|
35265
|
-
|
|
35266
|
-
|
|
35267
|
-
|
|
35268
|
-
|
|
35269
|
-
|
|
35270
|
-
console.log(JSON.stringify(entity, null, 2));
|
|
35271
|
-
} else {
|
|
35272
|
-
console.log(chalk2.yellow(`Entity not found: ${name}`));
|
|
35273
|
-
}
|
|
35274
|
-
break;
|
|
35324
|
+
case "csv": {
|
|
35325
|
+
const header = "from,relationType,to";
|
|
35326
|
+
const rows = relations.map((r) => [
|
|
35327
|
+
escapeCSV(r.from),
|
|
35328
|
+
escapeCSV(r.relationType),
|
|
35329
|
+
escapeCSV(r.to)
|
|
35330
|
+
].join(","));
|
|
35331
|
+
return [header, ...rows].join("\n");
|
|
35275
35332
|
}
|
|
35276
|
-
|
|
35277
|
-
|
|
35278
|
-
|
|
35279
|
-
|
|
35280
|
-
|
|
35281
|
-
|
|
35282
|
-
|
|
35283
|
-
|
|
35284
|
-
|
|
35285
|
-
|
|
35286
|
-
|
|
35287
|
-
|
|
35288
|
-
|
|
35289
|
-
|
|
35290
|
-
|
|
35291
|
-
|
|
35292
|
-
|
|
35293
|
-
|
|
35333
|
+
}
|
|
35334
|
+
}
|
|
35335
|
+
function formatSearchResults(results, format) {
|
|
35336
|
+
if (results.length === 0) {
|
|
35337
|
+
return format === "json" ? "[]" : "No results found.";
|
|
35338
|
+
}
|
|
35339
|
+
switch (format) {
|
|
35340
|
+
case "json":
|
|
35341
|
+
return JSON.stringify(results, null, 2);
|
|
35342
|
+
case "table": {
|
|
35343
|
+
const table = new Table({
|
|
35344
|
+
head: [chalk.cyan("Name"), chalk.cyan("Type"), chalk.cyan("Score"), chalk.cyan("Observations")],
|
|
35345
|
+
colWidths: calculateColWidths(getTerminalWidth(), [0.25, 0.15, 0.1, 0.5]),
|
|
35346
|
+
wordWrap: true
|
|
35347
|
+
});
|
|
35348
|
+
for (const result of results) {
|
|
35349
|
+
table.push([
|
|
35350
|
+
result.entity.name,
|
|
35351
|
+
result.entity.entityType,
|
|
35352
|
+
result.score !== void 0 ? result.score.toFixed(3) : "-",
|
|
35353
|
+
(result.entity.observations || []).slice(0, 2).join("; ") + (result.entity.observations && result.entity.observations.length > 2 ? "..." : "")
|
|
35354
|
+
]);
|
|
35294
35355
|
}
|
|
35295
|
-
|
|
35356
|
+
return table.toString();
|
|
35296
35357
|
}
|
|
35297
|
-
case "
|
|
35298
|
-
const
|
|
35299
|
-
|
|
35300
|
-
|
|
35301
|
-
|
|
35302
|
-
|
|
35303
|
-
|
|
35304
|
-
|
|
35305
|
-
|
|
35306
|
-
|
|
35307
|
-
|
|
35308
|
-
|
|
35309
|
-
|
|
35310
|
-
|
|
35311
|
-
|
|
35312
|
-
|
|
35313
|
-
|
|
35314
|
-
|
|
35358
|
+
case "csv": {
|
|
35359
|
+
const header = "name,entityType,score,observations";
|
|
35360
|
+
const rows = results.map((r) => [
|
|
35361
|
+
escapeCSV(r.entity.name),
|
|
35362
|
+
escapeCSV(r.entity.entityType),
|
|
35363
|
+
r.score !== void 0 ? r.score.toFixed(3) : "",
|
|
35364
|
+
escapeCSV((r.entity.observations || []).join("; "))
|
|
35365
|
+
].join(","));
|
|
35366
|
+
return [header, ...rows].join("\n");
|
|
35367
|
+
}
|
|
35368
|
+
}
|
|
35369
|
+
}
|
|
35370
|
+
function formatEntityDetail(entity, format) {
|
|
35371
|
+
if (!entity) {
|
|
35372
|
+
return format === "json" ? "null" : "Entity not found.";
|
|
35373
|
+
}
|
|
35374
|
+
switch (format) {
|
|
35375
|
+
case "json":
|
|
35376
|
+
return JSON.stringify(entity, null, 2);
|
|
35377
|
+
case "table": {
|
|
35378
|
+
const lines = [
|
|
35379
|
+
`${chalk.bold("Name:")} ${entity.name}`,
|
|
35380
|
+
`${chalk.bold("Type:")} ${entity.entityType}`,
|
|
35381
|
+
`${chalk.bold("Importance:")} ${entity.importance ?? "N/A"}`,
|
|
35382
|
+
`${chalk.bold("Tags:")} ${(entity.tags || []).join(", ") || "None"}`,
|
|
35383
|
+
`${chalk.bold("Parent:")} ${entity.parentId || "None"}`,
|
|
35384
|
+
`${chalk.bold("Created:")} ${entity.createdAt || "N/A"}`,
|
|
35385
|
+
`${chalk.bold("Modified:")} ${entity.lastModified || "N/A"}`,
|
|
35386
|
+
"",
|
|
35387
|
+
chalk.bold("Observations:"),
|
|
35388
|
+
...(entity.observations || []).map((o, i) => ` ${i + 1}. ${o}`)
|
|
35389
|
+
];
|
|
35390
|
+
return lines.join("\n");
|
|
35391
|
+
}
|
|
35392
|
+
case "csv": {
|
|
35393
|
+
const header = "field,value";
|
|
35394
|
+
const rows = [
|
|
35395
|
+
`name,${escapeCSV(entity.name)}`,
|
|
35396
|
+
`entityType,${escapeCSV(entity.entityType)}`,
|
|
35397
|
+
`importance,${entity.importance ?? ""}`,
|
|
35398
|
+
`tags,${escapeCSV((entity.tags || []).join("; "))}`,
|
|
35399
|
+
`parentId,${escapeCSV(entity.parentId || "")}`,
|
|
35400
|
+
`observations,${escapeCSV((entity.observations || []).join("; "))}`
|
|
35401
|
+
];
|
|
35402
|
+
return [header, ...rows].join("\n");
|
|
35403
|
+
}
|
|
35404
|
+
}
|
|
35405
|
+
}
|
|
35406
|
+
function formatSuccess(message) {
|
|
35407
|
+
return chalk.green("\u2713") + " " + message;
|
|
35408
|
+
}
|
|
35409
|
+
function formatError(message) {
|
|
35410
|
+
return chalk.red("\u2717") + " " + message;
|
|
35411
|
+
}
|
|
35412
|
+
function formatPath(result, format) {
|
|
35413
|
+
switch (format) {
|
|
35414
|
+
case "json":
|
|
35415
|
+
return JSON.stringify(result, null, 2);
|
|
35416
|
+
case "csv": {
|
|
35417
|
+
const header = "step,entity";
|
|
35418
|
+
const rows = result.path.map((name, i) => `${i},${escapeCSV(name)}`);
|
|
35419
|
+
return [header, ...rows].join("\n");
|
|
35420
|
+
}
|
|
35421
|
+
default: {
|
|
35422
|
+
const lines = [
|
|
35423
|
+
`${chalk.bold("Path")} (${result.length} hops):`,
|
|
35424
|
+
result.path.join(" \u2192 ")
|
|
35425
|
+
];
|
|
35426
|
+
if (result.relations.length > 0) {
|
|
35427
|
+
lines.push("", chalk.bold("Relations:"));
|
|
35428
|
+
for (const rel of result.relations) {
|
|
35429
|
+
lines.push(` ${rel.from} --[${rel.relationType}]--> ${rel.to}`);
|
|
35315
35430
|
}
|
|
35316
35431
|
}
|
|
35317
|
-
|
|
35432
|
+
return lines.join("\n");
|
|
35318
35433
|
}
|
|
35319
|
-
|
|
35320
|
-
|
|
35321
|
-
|
|
35322
|
-
|
|
35323
|
-
|
|
35324
|
-
|
|
35325
|
-
|
|
35326
|
-
|
|
35327
|
-
|
|
35434
|
+
}
|
|
35435
|
+
}
|
|
35436
|
+
function formatCentrality(result, format) {
|
|
35437
|
+
switch (format) {
|
|
35438
|
+
case "json":
|
|
35439
|
+
return JSON.stringify(
|
|
35440
|
+
{ algorithm: result.algorithm, topEntities: result.topEntities },
|
|
35441
|
+
null,
|
|
35442
|
+
2
|
|
35443
|
+
);
|
|
35444
|
+
case "csv": {
|
|
35445
|
+
const header = "rank,name,score";
|
|
35446
|
+
const rows = result.topEntities.map(
|
|
35447
|
+
(e, i) => `${i + 1},${escapeCSV(e.name)},${e.score.toFixed(4)}`
|
|
35448
|
+
);
|
|
35449
|
+
return [header, ...rows].join("\n");
|
|
35328
35450
|
}
|
|
35329
|
-
|
|
35330
|
-
const
|
|
35331
|
-
|
|
35332
|
-
|
|
35333
|
-
|
|
35334
|
-
|
|
35335
|
-
|
|
35336
|
-
|
|
35337
|
-
|
|
35338
|
-
|
|
35339
|
-
Tags for "${tagName}": ${tags.length > 0 ? tags.join(", ") : "None"}`);
|
|
35340
|
-
} else {
|
|
35341
|
-
console.log(chalk2.yellow(`Entity not found: ${tagName}`));
|
|
35342
|
-
}
|
|
35343
|
-
break;
|
|
35451
|
+
default: {
|
|
35452
|
+
const table = new Table({
|
|
35453
|
+
head: [chalk.cyan("Rank"), chalk.cyan("Entity"), chalk.cyan("Score")],
|
|
35454
|
+
colWidths: calculateColWidths(getTerminalWidth(), [0.1, 0.6, 0.3])
|
|
35455
|
+
});
|
|
35456
|
+
result.topEntities.forEach((e, i) => {
|
|
35457
|
+
table.push([String(i + 1), e.name, e.score.toFixed(4)]);
|
|
35458
|
+
});
|
|
35459
|
+
return `${chalk.bold(`Centrality (${result.algorithm})`)}
|
|
35460
|
+
${table.toString()}`;
|
|
35344
35461
|
}
|
|
35345
|
-
|
|
35346
|
-
|
|
35347
|
-
|
|
35348
|
-
|
|
35349
|
-
|
|
35350
|
-
|
|
35351
|
-
|
|
35352
|
-
|
|
35353
|
-
|
|
35354
|
-
|
|
35355
|
-
|
|
35356
|
-
|
|
35357
|
-
}
|
|
35358
|
-
} else {
|
|
35359
|
-
console.log(chalk2.yellow(`No path found between "${pathFrom}" and "${pathTo}"`));
|
|
35360
|
-
}
|
|
35361
|
-
break;
|
|
35462
|
+
}
|
|
35463
|
+
}
|
|
35464
|
+
function formatComponents(result, format) {
|
|
35465
|
+
switch (format) {
|
|
35466
|
+
case "json":
|
|
35467
|
+
return JSON.stringify(result, null, 2);
|
|
35468
|
+
case "csv": {
|
|
35469
|
+
const header = "component,size,entities";
|
|
35470
|
+
const rows = result.components.map(
|
|
35471
|
+
(comp, i) => `${i + 1},${comp.length},${escapeCSV(comp.join("; "))}`
|
|
35472
|
+
);
|
|
35473
|
+
return [header, ...rows].join("\n");
|
|
35362
35474
|
}
|
|
35363
|
-
|
|
35364
|
-
const
|
|
35365
|
-
|
|
35366
|
-
|
|
35367
|
-
|
|
35368
|
-
|
|
35369
|
-
|
|
35370
|
-
|
|
35371
|
-
|
|
35372
|
-
|
|
35373
|
-
}]);
|
|
35374
|
-
console.log(chalk2.green(`Added observation to ${obsEntity}`));
|
|
35375
|
-
break;
|
|
35475
|
+
default: {
|
|
35476
|
+
const lines = [
|
|
35477
|
+
`${chalk.bold("Connected Components")}: ${result.count} found`,
|
|
35478
|
+
`Largest component size: ${result.largestComponentSize}`,
|
|
35479
|
+
""
|
|
35480
|
+
];
|
|
35481
|
+
result.components.forEach((comp, i) => {
|
|
35482
|
+
lines.push(` Component ${i + 1} (${comp.length} nodes): ${comp.join(", ")}`);
|
|
35483
|
+
});
|
|
35484
|
+
return lines.join("\n");
|
|
35376
35485
|
}
|
|
35377
|
-
|
|
35378
|
-
|
|
35379
|
-
|
|
35380
|
-
|
|
35381
|
-
|
|
35486
|
+
}
|
|
35487
|
+
}
|
|
35488
|
+
function formatValidation(result, format) {
|
|
35489
|
+
switch (format) {
|
|
35490
|
+
case "json":
|
|
35491
|
+
return JSON.stringify(result, null, 2);
|
|
35492
|
+
case "csv": {
|
|
35493
|
+
const header = "type,message";
|
|
35494
|
+
const rows = [];
|
|
35495
|
+
for (const issue of result.issues) {
|
|
35496
|
+
rows.push(`error,${escapeCSV(issue.message)}`);
|
|
35382
35497
|
}
|
|
35383
|
-
|
|
35384
|
-
|
|
35385
|
-
|
|
35498
|
+
for (const warn of result.warnings) {
|
|
35499
|
+
rows.push(`warning,${escapeCSV(warn.message)}`);
|
|
35500
|
+
}
|
|
35501
|
+
return [header, ...rows].join("\n");
|
|
35386
35502
|
}
|
|
35387
|
-
|
|
35388
|
-
const
|
|
35389
|
-
const
|
|
35390
|
-
|
|
35391
|
-
|
|
35392
|
-
|
|
35503
|
+
default: {
|
|
35504
|
+
const status = result.isValid ? chalk.green("\u2713 Valid") : chalk.red("\u2717 Invalid");
|
|
35505
|
+
const lines = [
|
|
35506
|
+
`${chalk.bold("Graph Validation")} \u2014 ${status}`,
|
|
35507
|
+
`Errors: ${result.summary.totalErrors} Warnings: ${result.summary.totalWarnings}`
|
|
35508
|
+
];
|
|
35509
|
+
for (const issue of result.issues) {
|
|
35510
|
+
lines.push(` ${chalk.red("ERROR")}: ${issue.message}`);
|
|
35393
35511
|
}
|
|
35394
|
-
const
|
|
35395
|
-
|
|
35396
|
-
|
|
35397
|
-
|
|
35512
|
+
for (const warn of result.warnings) {
|
|
35513
|
+
lines.push(` ${chalk.yellow("WARN")}: ${warn.message}`);
|
|
35514
|
+
}
|
|
35515
|
+
return lines.join("\n");
|
|
35398
35516
|
}
|
|
35399
|
-
case "history":
|
|
35400
|
-
console.log("\nCommand history:");
|
|
35401
|
-
ictx.history.slice(-20).forEach((cmd, i) => {
|
|
35402
|
-
console.log(` ${i + 1}. ${cmd}`);
|
|
35403
|
-
});
|
|
35404
|
-
break;
|
|
35405
|
-
default:
|
|
35406
|
-
console.log(chalk2.yellow(`Unknown command: ${command}. Type "help" for available commands.`));
|
|
35407
35517
|
}
|
|
35408
35518
|
}
|
|
35409
|
-
function
|
|
35410
|
-
|
|
35411
|
-
|
|
35412
|
-
|
|
35413
|
-
${chalk2.cyan("entities")} / ${chalk2.cyan("ls")} List all entities
|
|
35414
|
-
${chalk2.cyan("get <name>")} Get entity details
|
|
35415
|
-
${chalk2.cyan("search <query>")} Search entities
|
|
35416
|
-
${chalk2.cyan("relations <name>")} Show relations for entity
|
|
35417
|
-
${chalk2.cyan("tags <name>")} Show tags for entity
|
|
35418
|
-
${chalk2.cyan("path <from> <to>")} Find shortest path
|
|
35419
|
-
${chalk2.cyan("observe <e> <text>")} Add observation to entity
|
|
35420
|
-
${chalk2.cyan("delete <name>")} Delete entity
|
|
35421
|
-
${chalk2.cyan("export [format]")} Export graph to stdout
|
|
35422
|
-
${chalk2.cyan("stats")} Show graph statistics
|
|
35423
|
-
${chalk2.cyan("history")} Show command history
|
|
35424
|
-
${chalk2.cyan("clear")} Clear screen
|
|
35425
|
-
${chalk2.cyan("help")} Show this help
|
|
35426
|
-
${chalk2.cyan("exit")} Exit interactive mode
|
|
35427
|
-
|
|
35428
|
-
${chalk2.gray("Tab completion available for entity names.")}
|
|
35429
|
-
`);
|
|
35519
|
+
function calculateColWidths(totalWidth, ratios) {
|
|
35520
|
+
const padding = 4;
|
|
35521
|
+
const available = totalWidth - padding;
|
|
35522
|
+
return ratios.map((r) => Math.max(10, Math.floor(available * r)));
|
|
35430
35523
|
}
|
|
35431
|
-
|
|
35432
|
-
"
|
|
35524
|
+
function escapeCSV(value) {
|
|
35525
|
+
if (value.includes(",") || value.includes('"') || value.includes("\n")) {
|
|
35526
|
+
return `"${value.replace(/"/g, '""')}"`;
|
|
35527
|
+
}
|
|
35528
|
+
return value;
|
|
35529
|
+
}
|
|
35530
|
+
var init_formatters2 = __esm({
|
|
35531
|
+
"src/cli/formatters.ts"() {
|
|
35433
35532
|
"use strict";
|
|
35434
35533
|
init_esm_shims();
|
|
35435
|
-
init_ManagerContext();
|
|
35436
35534
|
}
|
|
35437
35535
|
});
|
|
35438
35536
|
|
|
35439
|
-
// src/cli/index.ts
|
|
35440
|
-
init_esm_shims();
|
|
35441
|
-
import { Command as Command2 } from "commander";
|
|
35442
|
-
|
|
35443
|
-
// src/cli/commands/index.ts
|
|
35444
|
-
init_esm_shims();
|
|
35445
|
-
|
|
35446
|
-
// src/cli/commands/entity.ts
|
|
35447
|
-
init_esm_shims();
|
|
35448
|
-
|
|
35449
35537
|
// src/cli/commands/helpers.ts
|
|
35450
|
-
|
|
35451
|
-
|
|
35452
|
-
|
|
35453
|
-
|
|
35454
|
-
|
|
35455
|
-
var defaultOptions = {
|
|
35456
|
-
storage: process.env.MEMORYJS_STORAGE_PATH || "./memory.jsonl",
|
|
35457
|
-
format: process.env.MEMORYJS_OUTPUT_FORMAT || "json",
|
|
35458
|
-
quiet: false,
|
|
35459
|
-
verbose: false
|
|
35460
|
-
};
|
|
35461
|
-
function parseGlobalOptions(opts) {
|
|
35462
|
-
const rawFormat = opts.outputFormat;
|
|
35463
|
-
const format = rawFormat && ["json", "table", "csv"].includes(rawFormat) ? rawFormat : defaultOptions.format;
|
|
35464
|
-
return {
|
|
35465
|
-
storage: opts.storage || defaultOptions.storage,
|
|
35466
|
-
format,
|
|
35467
|
-
quiet: Boolean(opts.quiet),
|
|
35468
|
-
verbose: Boolean(opts.verbose)
|
|
35469
|
-
};
|
|
35538
|
+
function getOptions(program2) {
|
|
35539
|
+
const cliOpts = program2.opts();
|
|
35540
|
+
const configPath = findConfigFile();
|
|
35541
|
+
const fileConfig = configPath ? loadConfig(configPath) : {};
|
|
35542
|
+
return mergeConfig2(fileConfig, parseGlobalOptions(cliOpts));
|
|
35470
35543
|
}
|
|
35471
|
-
function
|
|
35472
|
-
return
|
|
35473
|
-
|
|
35474
|
-
|
|
35475
|
-
|
|
35476
|
-
|
|
35544
|
+
function createContext(options) {
|
|
35545
|
+
return new ManagerContext(options.storage);
|
|
35546
|
+
}
|
|
35547
|
+
var init_helpers = __esm({
|
|
35548
|
+
"src/cli/commands/helpers.ts"() {
|
|
35549
|
+
"use strict";
|
|
35550
|
+
init_esm_shims();
|
|
35551
|
+
init_ManagerContext();
|
|
35552
|
+
init_options();
|
|
35553
|
+
init_config();
|
|
35554
|
+
init_formatters2();
|
|
35555
|
+
}
|
|
35556
|
+
});
|
|
35557
|
+
|
|
35558
|
+
// src/cli/commands/inspect.ts
|
|
35559
|
+
var inspect_exports = {};
|
|
35560
|
+
__export(inspect_exports, {
|
|
35561
|
+
buildSizeReport: () => buildSizeReport,
|
|
35562
|
+
buildTree: () => buildTree,
|
|
35563
|
+
neighbors: () => neighbors,
|
|
35564
|
+
registerInspectCommands: () => registerInspectCommands,
|
|
35565
|
+
renderTreeAscii: () => renderTreeAscii,
|
|
35566
|
+
snapshotEntity: () => snapshotEntity
|
|
35567
|
+
});
|
|
35568
|
+
import { promises as fs17 } from "fs";
|
|
35569
|
+
async function snapshotEntity(ctx, name) {
|
|
35570
|
+
const graph = await ctx.storage.loadGraph();
|
|
35571
|
+
const entity = ctx.storage.getEntityByName(name);
|
|
35572
|
+
if (!entity) throw new Error(`entity not found: ${name}`);
|
|
35573
|
+
const observations = await ctx.observationManager.getObservationsFor(name);
|
|
35574
|
+
const outgoing = graph.relations.filter((r) => r.from === name).map((r) => ({ to: r.to, type: r.relationType }));
|
|
35575
|
+
const incoming = graph.relations.filter((r) => r.to === name).map((r) => ({ from: r.from, type: r.relationType }));
|
|
35576
|
+
const children = (await ctx.hierarchyManager.getChildren(name)).map((c) => c.name);
|
|
35577
|
+
const ancestors = (await ctx.hierarchyManager.getAncestors(name)).map((a) => a.name);
|
|
35578
|
+
return {
|
|
35579
|
+
name: entity.name,
|
|
35580
|
+
entityType: entity.entityType,
|
|
35581
|
+
observations,
|
|
35582
|
+
tags: entity.tags,
|
|
35583
|
+
importance: entity.importance,
|
|
35584
|
+
createdAt: entity.createdAt,
|
|
35585
|
+
lastModified: entity.lastModified,
|
|
35586
|
+
parentId: entity.parentId,
|
|
35587
|
+
children,
|
|
35588
|
+
ancestors,
|
|
35589
|
+
relations: { outgoing, incoming }
|
|
35477
35590
|
};
|
|
35478
35591
|
}
|
|
35479
|
-
|
|
35480
|
-
|
|
35481
|
-
|
|
35482
|
-
|
|
35483
|
-
|
|
35484
|
-
|
|
35485
|
-
|
|
35486
|
-
|
|
35487
|
-
|
|
35488
|
-
|
|
35489
|
-
function findConfigFile(startDir = process.cwd()) {
|
|
35490
|
-
let currentDir = startDir;
|
|
35491
|
-
const root = resolve2("/");
|
|
35492
|
-
while (currentDir !== root) {
|
|
35493
|
-
for (const filename of CONFIG_FILES) {
|
|
35494
|
-
const configPath = resolve2(currentDir, filename);
|
|
35495
|
-
if (existsSync2(configPath)) {
|
|
35496
|
-
return configPath;
|
|
35497
|
-
}
|
|
35592
|
+
async function buildTree(ctx, root) {
|
|
35593
|
+
await ctx.storage.loadGraph();
|
|
35594
|
+
const rootEntity = ctx.storage.getEntityByName(root);
|
|
35595
|
+
if (!rootEntity) throw new Error(`entity not found: ${root}`);
|
|
35596
|
+
async function walk(name) {
|
|
35597
|
+
const entity = ctx.storage.getEntityByName(name);
|
|
35598
|
+
const children = await ctx.hierarchyManager.getChildren(name);
|
|
35599
|
+
const childNodes = [];
|
|
35600
|
+
for (const c of children) {
|
|
35601
|
+
childNodes.push(await walk(c.name));
|
|
35498
35602
|
}
|
|
35499
|
-
|
|
35500
|
-
|
|
35501
|
-
|
|
35603
|
+
return {
|
|
35604
|
+
name,
|
|
35605
|
+
entityType: entity?.entityType ?? "unknown",
|
|
35606
|
+
children: childNodes
|
|
35607
|
+
};
|
|
35502
35608
|
}
|
|
35503
|
-
return
|
|
35609
|
+
return walk(root);
|
|
35504
35610
|
}
|
|
35505
|
-
function
|
|
35506
|
-
|
|
35507
|
-
|
|
35508
|
-
|
|
35509
|
-
|
|
35510
|
-
|
|
35511
|
-
|
|
35512
|
-
return {};
|
|
35611
|
+
function renderTreeAscii(node, prefix = "", isRoot = true, isLast = true) {
|
|
35612
|
+
const connector = isRoot ? "" : isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
35613
|
+
let out = `${prefix}${connector}${node.name} (${node.entityType})
|
|
35614
|
+
`;
|
|
35615
|
+
const childPrefix = isRoot ? "" : prefix + (isLast ? " " : "\u2502 ");
|
|
35616
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
35617
|
+
out += renderTreeAscii(node.children[i], childPrefix, false, i === node.children.length - 1);
|
|
35513
35618
|
}
|
|
35619
|
+
return out;
|
|
35514
35620
|
}
|
|
35515
|
-
function
|
|
35516
|
-
const
|
|
35517
|
-
|
|
35518
|
-
|
|
35519
|
-
|
|
35520
|
-
|
|
35521
|
-
|
|
35522
|
-
}
|
|
35523
|
-
|
|
35524
|
-
|
|
35525
|
-
|
|
35526
|
-
|
|
35527
|
-
|
|
35621
|
+
async function buildSizeReport(ctx, storagePath) {
|
|
35622
|
+
const graph = await ctx.storage.loadGraph();
|
|
35623
|
+
let observationCount = 0;
|
|
35624
|
+
const tagSet = /* @__PURE__ */ new Set();
|
|
35625
|
+
for (const e of graph.entities) {
|
|
35626
|
+
observationCount += e.observations.length;
|
|
35627
|
+
if (e.tags) for (const t of e.tags) tagSet.add(t);
|
|
35628
|
+
}
|
|
35629
|
+
let exists = false;
|
|
35630
|
+
let sizeBytes = 0;
|
|
35631
|
+
let lineCount = 0;
|
|
35632
|
+
try {
|
|
35633
|
+
const stat = await fs17.stat(storagePath);
|
|
35634
|
+
exists = true;
|
|
35635
|
+
sizeBytes = stat.size;
|
|
35636
|
+
if (sizeBytes > 0) {
|
|
35637
|
+
const content = await fs17.readFile(storagePath, "utf8");
|
|
35638
|
+
lineCount = content.split("\n").filter((l) => l.length > 0).length;
|
|
35639
|
+
}
|
|
35640
|
+
} catch {
|
|
35528
35641
|
}
|
|
35529
|
-
return validated;
|
|
35530
|
-
}
|
|
35531
|
-
function mergeConfig2(fileConfig, cliOptions) {
|
|
35532
35642
|
return {
|
|
35533
|
-
|
|
35534
|
-
|
|
35535
|
-
|
|
35536
|
-
|
|
35643
|
+
graph: {
|
|
35644
|
+
entities: graph.entities.length,
|
|
35645
|
+
relations: graph.relations.length,
|
|
35646
|
+
observations: observationCount,
|
|
35647
|
+
distinctTags: tagSet.size,
|
|
35648
|
+
avgObservationsPerEntity: graph.entities.length === 0 ? 0 : Number((observationCount / graph.entities.length).toFixed(2))
|
|
35649
|
+
},
|
|
35650
|
+
storage: {
|
|
35651
|
+
path: storagePath,
|
|
35652
|
+
exists,
|
|
35653
|
+
sizeBytes,
|
|
35654
|
+
lineCount
|
|
35655
|
+
}
|
|
35537
35656
|
};
|
|
35538
35657
|
}
|
|
35539
|
-
|
|
35540
|
-
|
|
35541
|
-
|
|
35542
|
-
|
|
35543
|
-
|
|
35544
|
-
|
|
35545
|
-
return
|
|
35658
|
+
async function neighbors(ctx, name) {
|
|
35659
|
+
const graph = await ctx.storage.loadGraph();
|
|
35660
|
+
const entity = ctx.storage.getEntityByName(name);
|
|
35661
|
+
if (!entity) throw new Error(`entity not found: ${name}`);
|
|
35662
|
+
const outgoing = graph.relations.filter((r) => r.from === name).map((r) => ({ to: r.to, type: r.relationType }));
|
|
35663
|
+
const incoming = graph.relations.filter((r) => r.to === name).map((r) => ({ from: r.from, type: r.relationType }));
|
|
35664
|
+
return {
|
|
35665
|
+
entity: name,
|
|
35666
|
+
outgoing,
|
|
35667
|
+
incoming,
|
|
35668
|
+
outDegree: outgoing.length,
|
|
35669
|
+
inDegree: incoming.length
|
|
35670
|
+
};
|
|
35546
35671
|
}
|
|
35547
|
-
function
|
|
35548
|
-
|
|
35549
|
-
|
|
35550
|
-
|
|
35551
|
-
|
|
35552
|
-
|
|
35553
|
-
|
|
35554
|
-
|
|
35555
|
-
|
|
35556
|
-
|
|
35557
|
-
|
|
35558
|
-
|
|
35559
|
-
|
|
35560
|
-
|
|
35561
|
-
|
|
35562
|
-
|
|
35563
|
-
|
|
35564
|
-
|
|
35565
|
-
|
|
35566
|
-
|
|
35672
|
+
function registerInspectCommands(program2) {
|
|
35673
|
+
program2.command("show <entity>").description("Verbose snapshot of one entity (observations, relations in/out, tags, hierarchy, timestamps)").action(async (entity) => {
|
|
35674
|
+
const options = getOptions(program2);
|
|
35675
|
+
const logger2 = createLogger(options);
|
|
35676
|
+
const ctx = createContext(options);
|
|
35677
|
+
try {
|
|
35678
|
+
const snap = await snapshotEntity(ctx, entity);
|
|
35679
|
+
console.log(JSON.stringify(snap, null, 2));
|
|
35680
|
+
} catch (e) {
|
|
35681
|
+
logger2.error(formatError(e.message));
|
|
35682
|
+
process.exit(1);
|
|
35683
|
+
}
|
|
35684
|
+
});
|
|
35685
|
+
program2.command("tree [root]").description("Hierarchy tree from a root entity (or all roots when omitted)").option("--ascii", "Render as ASCII tree instead of JSON (overrides --output-format)").action(async (root, opts) => {
|
|
35686
|
+
const options = getOptions(program2);
|
|
35687
|
+
const logger2 = createLogger(options);
|
|
35688
|
+
const ctx = createContext(options);
|
|
35689
|
+
try {
|
|
35690
|
+
let trees;
|
|
35691
|
+
if (root) {
|
|
35692
|
+
trees = [await buildTree(ctx, root)];
|
|
35693
|
+
} else {
|
|
35694
|
+
const roots = await ctx.hierarchyManager.getRootEntities();
|
|
35695
|
+
trees = await Promise.all(roots.map((r) => buildTree(ctx, r.name)));
|
|
35567
35696
|
}
|
|
35568
|
-
|
|
35697
|
+
if (opts.ascii) {
|
|
35698
|
+
for (const t of trees) {
|
|
35699
|
+
process.stdout.write(renderTreeAscii(t));
|
|
35700
|
+
}
|
|
35701
|
+
} else {
|
|
35702
|
+
console.log(JSON.stringify(trees, null, 2));
|
|
35703
|
+
}
|
|
35704
|
+
} catch (e) {
|
|
35705
|
+
logger2.error(formatError(e.message));
|
|
35706
|
+
process.exit(1);
|
|
35569
35707
|
}
|
|
35570
|
-
|
|
35571
|
-
|
|
35572
|
-
|
|
35573
|
-
|
|
35574
|
-
|
|
35575
|
-
|
|
35576
|
-
|
|
35577
|
-
|
|
35578
|
-
|
|
35708
|
+
});
|
|
35709
|
+
program2.command("neighbors <entity>").description("Incoming + outgoing relations of one entity (with in/out degree counts)").action(async (entity) => {
|
|
35710
|
+
const options = getOptions(program2);
|
|
35711
|
+
const logger2 = createLogger(options);
|
|
35712
|
+
const ctx = createContext(options);
|
|
35713
|
+
try {
|
|
35714
|
+
const report = await neighbors(ctx, entity);
|
|
35715
|
+
console.log(JSON.stringify(report, null, 2));
|
|
35716
|
+
} catch (e) {
|
|
35717
|
+
logger2.error(formatError(e.message));
|
|
35718
|
+
process.exit(1);
|
|
35579
35719
|
}
|
|
35580
|
-
}
|
|
35720
|
+
});
|
|
35721
|
+
program2.command("size").description("Graph size + storage footprint summary (entity/relation/observation counts, file bytes, line count)").action(async () => {
|
|
35722
|
+
const options = getOptions(program2);
|
|
35723
|
+
const logger2 = createLogger(options);
|
|
35724
|
+
const ctx = createContext(options);
|
|
35725
|
+
try {
|
|
35726
|
+
const report = await buildSizeReport(ctx, options.storage);
|
|
35727
|
+
console.log(JSON.stringify(report, null, 2));
|
|
35728
|
+
} catch (e) {
|
|
35729
|
+
logger2.error(formatError(e.message));
|
|
35730
|
+
process.exit(1);
|
|
35731
|
+
}
|
|
35732
|
+
});
|
|
35581
35733
|
}
|
|
35582
|
-
|
|
35583
|
-
|
|
35584
|
-
|
|
35734
|
+
var init_inspect = __esm({
|
|
35735
|
+
"src/cli/commands/inspect.ts"() {
|
|
35736
|
+
"use strict";
|
|
35737
|
+
init_esm_shims();
|
|
35738
|
+
init_helpers();
|
|
35739
|
+
init_formatters2();
|
|
35585
35740
|
}
|
|
35586
|
-
|
|
35587
|
-
|
|
35588
|
-
|
|
35589
|
-
|
|
35590
|
-
|
|
35591
|
-
|
|
35592
|
-
|
|
35593
|
-
|
|
35594
|
-
|
|
35595
|
-
|
|
35596
|
-
|
|
35597
|
-
|
|
35741
|
+
});
|
|
35742
|
+
|
|
35743
|
+
// src/cli/interactive.ts
|
|
35744
|
+
var interactive_exports = {};
|
|
35745
|
+
__export(interactive_exports, {
|
|
35746
|
+
startInteractiveMode: () => startInteractiveMode
|
|
35747
|
+
});
|
|
35748
|
+
import * as readline from "readline";
|
|
35749
|
+
import chalk2 from "chalk";
|
|
35750
|
+
async function startInteractiveMode(options) {
|
|
35751
|
+
const ctx = new ManagerContext(options.storage);
|
|
35752
|
+
const interactiveCtx = {
|
|
35753
|
+
ctx,
|
|
35754
|
+
options,
|
|
35755
|
+
history: []
|
|
35756
|
+
};
|
|
35757
|
+
const graph = await ctx.storage.loadGraph();
|
|
35758
|
+
const entityNames = graph.entities.map((e) => e.name);
|
|
35759
|
+
const rl = readline.createInterface({
|
|
35760
|
+
input: process.stdin,
|
|
35761
|
+
output: process.stdout,
|
|
35762
|
+
prompt: chalk2.cyan("memory> "),
|
|
35763
|
+
completer: (line) => {
|
|
35764
|
+
const completions = [
|
|
35765
|
+
"entities",
|
|
35766
|
+
"relations",
|
|
35767
|
+
"search",
|
|
35768
|
+
"get",
|
|
35769
|
+
"stats",
|
|
35770
|
+
"tags",
|
|
35771
|
+
"path",
|
|
35772
|
+
"observe",
|
|
35773
|
+
"delete",
|
|
35774
|
+
"export",
|
|
35775
|
+
"help",
|
|
35776
|
+
"exit",
|
|
35777
|
+
"clear",
|
|
35778
|
+
"history",
|
|
35779
|
+
...entityNames
|
|
35780
|
+
];
|
|
35781
|
+
const hits = completions.filter((c) => c.toLowerCase().startsWith(line.toLowerCase()));
|
|
35782
|
+
return [hits.length ? hits : completions, line];
|
|
35598
35783
|
}
|
|
35599
|
-
|
|
35600
|
-
|
|
35601
|
-
|
|
35602
|
-
|
|
35603
|
-
|
|
35604
|
-
|
|
35605
|
-
|
|
35606
|
-
|
|
35784
|
+
});
|
|
35785
|
+
console.log(chalk2.green("MemoryJS Interactive Mode"));
|
|
35786
|
+
console.log(chalk2.gray('Type "help" for commands, "exit" to quit.\n'));
|
|
35787
|
+
rl.prompt();
|
|
35788
|
+
rl.on("line", async (line) => {
|
|
35789
|
+
const trimmed = line.trim();
|
|
35790
|
+
if (!trimmed) {
|
|
35791
|
+
rl.prompt();
|
|
35792
|
+
return;
|
|
35607
35793
|
}
|
|
35608
|
-
|
|
35794
|
+
interactiveCtx.history.push(trimmed);
|
|
35795
|
+
try {
|
|
35796
|
+
await processCommand(trimmed, interactiveCtx, rl);
|
|
35797
|
+
} catch (error) {
|
|
35798
|
+
console.error(chalk2.red(`Error: ${error.message}`));
|
|
35799
|
+
}
|
|
35800
|
+
rl.prompt();
|
|
35801
|
+
});
|
|
35802
|
+
rl.on("close", () => {
|
|
35803
|
+
console.log(chalk2.gray("\nGoodbye!"));
|
|
35804
|
+
process.exit(0);
|
|
35805
|
+
});
|
|
35609
35806
|
}
|
|
35610
|
-
function
|
|
35611
|
-
|
|
35612
|
-
|
|
35613
|
-
|
|
35614
|
-
|
|
35615
|
-
case "
|
|
35616
|
-
|
|
35617
|
-
|
|
35618
|
-
|
|
35619
|
-
|
|
35620
|
-
|
|
35621
|
-
|
|
35622
|
-
|
|
35623
|
-
|
|
35624
|
-
|
|
35625
|
-
|
|
35626
|
-
|
|
35627
|
-
|
|
35628
|
-
|
|
35629
|
-
|
|
35807
|
+
async function processCommand(input, ictx, rl) {
|
|
35808
|
+
const [command, ...args] = input.split(/\s+/);
|
|
35809
|
+
const ctx = ictx.ctx;
|
|
35810
|
+
switch (command.toLowerCase()) {
|
|
35811
|
+
case "help":
|
|
35812
|
+
case ".help":
|
|
35813
|
+
showHelp();
|
|
35814
|
+
break;
|
|
35815
|
+
case "exit":
|
|
35816
|
+
case ".exit":
|
|
35817
|
+
case "quit":
|
|
35818
|
+
rl.close();
|
|
35819
|
+
break;
|
|
35820
|
+
case "clear":
|
|
35821
|
+
case ".clear":
|
|
35822
|
+
console.clear();
|
|
35823
|
+
break;
|
|
35824
|
+
case "entities":
|
|
35825
|
+
case "ls": {
|
|
35826
|
+
const graph = await ctx.storage.loadGraph();
|
|
35827
|
+
const entities = graph.entities;
|
|
35828
|
+
console.log(`
|
|
35829
|
+
Entities (${entities.length}):`);
|
|
35830
|
+
for (const e of entities.slice(0, 20)) {
|
|
35831
|
+
console.log(` ${chalk2.cyan(e.name)} [${e.entityType}]`);
|
|
35630
35832
|
}
|
|
35631
|
-
|
|
35833
|
+
if (entities.length > 20) {
|
|
35834
|
+
console.log(` ... and ${entities.length - 20} more`);
|
|
35835
|
+
}
|
|
35836
|
+
break;
|
|
35632
35837
|
}
|
|
35633
|
-
case "
|
|
35634
|
-
const
|
|
35635
|
-
|
|
35636
|
-
|
|
35637
|
-
|
|
35638
|
-
|
|
35639
|
-
|
|
35640
|
-
|
|
35641
|
-
|
|
35838
|
+
case "get": {
|
|
35839
|
+
const name = args.join(" ");
|
|
35840
|
+
if (!name) {
|
|
35841
|
+
console.log(chalk2.yellow("Usage: get <entity-name>"));
|
|
35842
|
+
break;
|
|
35843
|
+
}
|
|
35844
|
+
const entity = await ctx.entityManager.getEntity(name);
|
|
35845
|
+
if (entity) {
|
|
35846
|
+
console.log(JSON.stringify(entity, null, 2));
|
|
35847
|
+
} else {
|
|
35848
|
+
console.log(chalk2.yellow(`Entity not found: ${name}`));
|
|
35849
|
+
}
|
|
35850
|
+
break;
|
|
35642
35851
|
}
|
|
35643
|
-
|
|
35644
|
-
|
|
35645
|
-
|
|
35646
|
-
|
|
35647
|
-
|
|
35648
|
-
|
|
35649
|
-
|
|
35650
|
-
|
|
35651
|
-
|
|
35652
|
-
|
|
35653
|
-
|
|
35654
|
-
|
|
35655
|
-
|
|
35656
|
-
|
|
35657
|
-
|
|
35658
|
-
|
|
35659
|
-
|
|
35660
|
-
|
|
35661
|
-
|
|
35662
|
-
|
|
35663
|
-
...(entity.observations || []).map((o, i) => ` ${i + 1}. ${o}`)
|
|
35664
|
-
];
|
|
35665
|
-
return lines.join("\n");
|
|
35852
|
+
case "search": {
|
|
35853
|
+
const query = args.join(" ");
|
|
35854
|
+
if (!query) {
|
|
35855
|
+
console.log(chalk2.yellow("Usage: search <query>"));
|
|
35856
|
+
break;
|
|
35857
|
+
}
|
|
35858
|
+
const result = await ctx.searchManager.searchNodes(query);
|
|
35859
|
+
console.log(`
|
|
35860
|
+
Search results for "${query}":`);
|
|
35861
|
+
for (const entity of result.entities.slice(0, 10)) {
|
|
35862
|
+
console.log(` ${chalk2.cyan(entity.name)} [${entity.entityType}]`);
|
|
35863
|
+
if (entity.observations && entity.observations.length > 0) {
|
|
35864
|
+
const preview = entity.observations[0].substring(0, 60);
|
|
35865
|
+
console.log(` ${chalk2.gray(preview)}${entity.observations[0].length > 60 ? "..." : ""}`);
|
|
35866
|
+
}
|
|
35867
|
+
}
|
|
35868
|
+
if (result.entities.length > 10) {
|
|
35869
|
+
console.log(` ... and ${result.entities.length - 10} more`);
|
|
35870
|
+
}
|
|
35871
|
+
break;
|
|
35666
35872
|
}
|
|
35667
|
-
case "
|
|
35668
|
-
const
|
|
35669
|
-
|
|
35670
|
-
|
|
35671
|
-
|
|
35672
|
-
|
|
35673
|
-
|
|
35674
|
-
|
|
35675
|
-
|
|
35676
|
-
|
|
35677
|
-
|
|
35873
|
+
case "relations": {
|
|
35874
|
+
const name = args.join(" ");
|
|
35875
|
+
if (!name) {
|
|
35876
|
+
console.log(chalk2.yellow("Usage: relations <entity-name>"));
|
|
35877
|
+
break;
|
|
35878
|
+
}
|
|
35879
|
+
const relations = await ctx.relationManager.getRelations(name);
|
|
35880
|
+
if (relations.length === 0) {
|
|
35881
|
+
console.log(chalk2.yellow(`No relations found for: ${name}`));
|
|
35882
|
+
break;
|
|
35883
|
+
}
|
|
35884
|
+
console.log(`
|
|
35885
|
+
Relations for "${name}":`);
|
|
35886
|
+
for (const rel of relations) {
|
|
35887
|
+
if (rel.from === name) {
|
|
35888
|
+
console.log(` ${chalk2.cyan(name)} --[${rel.relationType}]--> ${rel.to}`);
|
|
35889
|
+
} else {
|
|
35890
|
+
console.log(` ${rel.from} --[${rel.relationType}]--> ${chalk2.cyan(name)}`);
|
|
35891
|
+
}
|
|
35892
|
+
}
|
|
35893
|
+
break;
|
|
35678
35894
|
}
|
|
35679
|
-
|
|
35680
|
-
|
|
35681
|
-
|
|
35682
|
-
|
|
35683
|
-
}
|
|
35684
|
-
|
|
35685
|
-
|
|
35686
|
-
}
|
|
35687
|
-
|
|
35688
|
-
switch (format) {
|
|
35689
|
-
case "json":
|
|
35690
|
-
return JSON.stringify(result, null, 2);
|
|
35691
|
-
case "csv": {
|
|
35692
|
-
const header = "step,entity";
|
|
35693
|
-
const rows = result.path.map((name, i) => `${i},${escapeCSV(name)}`);
|
|
35694
|
-
return [header, ...rows].join("\n");
|
|
35895
|
+
case "stats": {
|
|
35896
|
+
const stats = await ctx.analyticsManager.getGraphStats();
|
|
35897
|
+
console.log(`
|
|
35898
|
+
Knowledge Graph Statistics:`);
|
|
35899
|
+
console.log(` Entities: ${stats.totalEntities}`);
|
|
35900
|
+
console.log(` Relations: ${stats.totalRelations}`);
|
|
35901
|
+
console.log(` Entity Types: ${Object.keys(stats.entityTypesCounts).length}`);
|
|
35902
|
+
console.log(` Relation Types: ${Object.keys(stats.relationTypesCounts).length}`);
|
|
35903
|
+
break;
|
|
35695
35904
|
}
|
|
35696
|
-
|
|
35697
|
-
const
|
|
35698
|
-
|
|
35699
|
-
|
|
35700
|
-
|
|
35701
|
-
|
|
35702
|
-
|
|
35703
|
-
|
|
35704
|
-
|
|
35905
|
+
case "tags": {
|
|
35906
|
+
const tagName = args.join(" ");
|
|
35907
|
+
if (!tagName) {
|
|
35908
|
+
console.log(chalk2.yellow("Usage: tags <entity-name>"));
|
|
35909
|
+
break;
|
|
35910
|
+
}
|
|
35911
|
+
const tagEntity = await ctx.entityManager.getEntity(tagName);
|
|
35912
|
+
if (tagEntity) {
|
|
35913
|
+
const tags = tagEntity.tags || [];
|
|
35914
|
+
console.log(`
|
|
35915
|
+
Tags for "${tagName}": ${tags.length > 0 ? tags.join(", ") : "None"}`);
|
|
35916
|
+
} else {
|
|
35917
|
+
console.log(chalk2.yellow(`Entity not found: ${tagName}`));
|
|
35918
|
+
}
|
|
35919
|
+
break;
|
|
35920
|
+
}
|
|
35921
|
+
case "path": {
|
|
35922
|
+
if (args.length < 2) {
|
|
35923
|
+
console.log(chalk2.yellow("Usage: path <from> <to>"));
|
|
35924
|
+
break;
|
|
35925
|
+
}
|
|
35926
|
+
const [pathFrom, pathTo] = args;
|
|
35927
|
+
const pathResult = await ctx.graphTraversal.findShortestPath(pathFrom, pathTo);
|
|
35928
|
+
if (pathResult) {
|
|
35929
|
+
console.log(`
|
|
35930
|
+
Path (${pathResult.length} hops): ${pathResult.path.join(" -> ")}`);
|
|
35931
|
+
for (const rel of pathResult.relations) {
|
|
35932
|
+
console.log(` ${rel.from} --[${rel.relationType}]--> ${rel.to}`);
|
|
35705
35933
|
}
|
|
35934
|
+
} else {
|
|
35935
|
+
console.log(chalk2.yellow(`No path found between "${pathFrom}" and "${pathTo}"`));
|
|
35706
35936
|
}
|
|
35707
|
-
|
|
35937
|
+
break;
|
|
35708
35938
|
}
|
|
35709
|
-
|
|
35710
|
-
|
|
35711
|
-
|
|
35712
|
-
|
|
35713
|
-
|
|
35714
|
-
|
|
35715
|
-
|
|
35716
|
-
|
|
35717
|
-
|
|
35718
|
-
|
|
35719
|
-
|
|
35720
|
-
|
|
35721
|
-
|
|
35722
|
-
(e, i) => `${i + 1},${escapeCSV(e.name)},${e.score.toFixed(4)}`
|
|
35723
|
-
);
|
|
35724
|
-
return [header, ...rows].join("\n");
|
|
35939
|
+
case "observe": {
|
|
35940
|
+
const obsEntity = args[0];
|
|
35941
|
+
const obsText = args.slice(1).join(" ");
|
|
35942
|
+
if (!obsEntity || !obsText) {
|
|
35943
|
+
console.log(chalk2.yellow("Usage: observe <entity> <observation text>"));
|
|
35944
|
+
break;
|
|
35945
|
+
}
|
|
35946
|
+
await ctx.observationManager.addObservations([{
|
|
35947
|
+
entityName: obsEntity,
|
|
35948
|
+
contents: [obsText]
|
|
35949
|
+
}]);
|
|
35950
|
+
console.log(chalk2.green(`Added observation to ${obsEntity}`));
|
|
35951
|
+
break;
|
|
35725
35952
|
}
|
|
35726
|
-
|
|
35727
|
-
const
|
|
35728
|
-
|
|
35729
|
-
|
|
35730
|
-
|
|
35731
|
-
|
|
35732
|
-
|
|
35733
|
-
});
|
|
35734
|
-
|
|
35735
|
-
${table.toString()}`;
|
|
35953
|
+
case "delete": {
|
|
35954
|
+
const delName = args.join(" ");
|
|
35955
|
+
if (!delName) {
|
|
35956
|
+
console.log(chalk2.yellow("Usage: delete <entity-name>"));
|
|
35957
|
+
break;
|
|
35958
|
+
}
|
|
35959
|
+
await ctx.entityManager.deleteEntities([delName]);
|
|
35960
|
+
console.log(chalk2.green(`Deleted entity: ${delName}`));
|
|
35961
|
+
break;
|
|
35736
35962
|
}
|
|
35737
|
-
|
|
35738
|
-
|
|
35739
|
-
|
|
35740
|
-
|
|
35741
|
-
|
|
35742
|
-
|
|
35743
|
-
|
|
35744
|
-
const
|
|
35745
|
-
const
|
|
35746
|
-
|
|
35747
|
-
|
|
35748
|
-
return [header, ...rows].join("\n");
|
|
35963
|
+
case "export": {
|
|
35964
|
+
const validFormats = ["json", "csv", "graphml", "gexf", "dot", "markdown", "mermaid", "turtle", "rdf-xml", "json-ld"];
|
|
35965
|
+
const fmt = args[0] || "json";
|
|
35966
|
+
if (!validFormats.includes(fmt)) {
|
|
35967
|
+
console.log(chalk2.yellow(`Invalid format: ${fmt}. Use: ${validFormats.join(", ")}`));
|
|
35968
|
+
break;
|
|
35969
|
+
}
|
|
35970
|
+
const exportGraph = await ctx.storage.loadGraph();
|
|
35971
|
+
const output = ctx.ioManager.exportGraph(exportGraph, fmt);
|
|
35972
|
+
console.log(output);
|
|
35973
|
+
break;
|
|
35749
35974
|
}
|
|
35750
|
-
|
|
35751
|
-
|
|
35752
|
-
|
|
35753
|
-
`
|
|
35754
|
-
""
|
|
35755
|
-
];
|
|
35756
|
-
result.components.forEach((comp, i) => {
|
|
35757
|
-
lines.push(` Component ${i + 1} (${comp.length} nodes): ${comp.join(", ")}`);
|
|
35975
|
+
case "history":
|
|
35976
|
+
console.log("\nCommand history:");
|
|
35977
|
+
ictx.history.slice(-20).forEach((cmd, i) => {
|
|
35978
|
+
console.log(` ${i + 1}. ${cmd}`);
|
|
35758
35979
|
});
|
|
35759
|
-
|
|
35760
|
-
|
|
35761
|
-
|
|
35762
|
-
|
|
35763
|
-
|
|
35764
|
-
|
|
35765
|
-
case "json":
|
|
35766
|
-
return JSON.stringify(result, null, 2);
|
|
35767
|
-
case "csv": {
|
|
35768
|
-
const header = "type,message";
|
|
35769
|
-
const rows = [];
|
|
35770
|
-
for (const issue of result.issues) {
|
|
35771
|
-
rows.push(`error,${escapeCSV(issue.message)}`);
|
|
35980
|
+
break;
|
|
35981
|
+
case "show": {
|
|
35982
|
+
const name = args.join(" ");
|
|
35983
|
+
if (!name) {
|
|
35984
|
+
console.log(chalk2.yellow("Usage: show <entity-name>"));
|
|
35985
|
+
break;
|
|
35772
35986
|
}
|
|
35773
|
-
|
|
35774
|
-
|
|
35987
|
+
const { snapshotEntity: snapshotEntity2 } = await Promise.resolve().then(() => (init_inspect(), inspect_exports));
|
|
35988
|
+
try {
|
|
35989
|
+
const snap = await snapshotEntity2(ctx, name);
|
|
35990
|
+
console.log(JSON.stringify(snap, null, 2));
|
|
35991
|
+
} catch (e) {
|
|
35992
|
+
console.log(chalk2.yellow(e.message));
|
|
35775
35993
|
}
|
|
35776
|
-
|
|
35994
|
+
break;
|
|
35777
35995
|
}
|
|
35778
|
-
|
|
35779
|
-
const
|
|
35780
|
-
const
|
|
35781
|
-
|
|
35782
|
-
|
|
35783
|
-
|
|
35784
|
-
|
|
35785
|
-
|
|
35996
|
+
case "tree": {
|
|
35997
|
+
const root = args[0];
|
|
35998
|
+
const { buildTree: buildTree2, renderTreeAscii: renderTreeAscii2 } = await Promise.resolve().then(() => (init_inspect(), inspect_exports));
|
|
35999
|
+
try {
|
|
36000
|
+
if (root) {
|
|
36001
|
+
const t = await buildTree2(ctx, root);
|
|
36002
|
+
process.stdout.write(renderTreeAscii2(t));
|
|
36003
|
+
} else {
|
|
36004
|
+
const roots = await ctx.hierarchyManager.getRootEntities();
|
|
36005
|
+
for (const r of roots) {
|
|
36006
|
+
const t = await buildTree2(ctx, r.name);
|
|
36007
|
+
process.stdout.write(renderTreeAscii2(t));
|
|
36008
|
+
}
|
|
36009
|
+
}
|
|
36010
|
+
} catch (e) {
|
|
36011
|
+
console.log(chalk2.yellow(e.message));
|
|
35786
36012
|
}
|
|
35787
|
-
|
|
35788
|
-
|
|
36013
|
+
break;
|
|
36014
|
+
}
|
|
36015
|
+
case "neighbors": {
|
|
36016
|
+
const name = args.join(" ");
|
|
36017
|
+
if (!name) {
|
|
36018
|
+
console.log(chalk2.yellow("Usage: neighbors <entity-name>"));
|
|
36019
|
+
break;
|
|
35789
36020
|
}
|
|
35790
|
-
|
|
36021
|
+
const { neighbors: neighbors2 } = await Promise.resolve().then(() => (init_inspect(), inspect_exports));
|
|
36022
|
+
try {
|
|
36023
|
+
const report = await neighbors2(ctx, name);
|
|
36024
|
+
console.log(JSON.stringify(report, null, 2));
|
|
36025
|
+
} catch (e) {
|
|
36026
|
+
console.log(chalk2.yellow(e.message));
|
|
36027
|
+
}
|
|
36028
|
+
break;
|
|
36029
|
+
}
|
|
36030
|
+
case "diag":
|
|
36031
|
+
case "health": {
|
|
36032
|
+
const graph = await ctx.storage.loadGraph();
|
|
36033
|
+
const names = new Set(graph.entities.map((e) => e.name));
|
|
36034
|
+
const orphans = graph.relations.filter((r) => !names.has(r.from) || !names.has(r.to)).length;
|
|
36035
|
+
const dupNames = graph.entities.length - names.size;
|
|
36036
|
+
console.log(JSON.stringify({
|
|
36037
|
+
entities: graph.entities.length,
|
|
36038
|
+
relations: graph.relations.length,
|
|
36039
|
+
orphan_relations: orphans,
|
|
36040
|
+
duplicate_names: dupNames,
|
|
36041
|
+
storage: ictx.options.storage
|
|
36042
|
+
}, null, 2));
|
|
36043
|
+
break;
|
|
36044
|
+
}
|
|
36045
|
+
case "size": {
|
|
36046
|
+
const { buildSizeReport: buildSizeReport2 } = await Promise.resolve().then(() => (init_inspect(), inspect_exports));
|
|
36047
|
+
const report = await buildSizeReport2(ctx, ictx.options.storage);
|
|
36048
|
+
console.log(JSON.stringify(report, null, 2));
|
|
36049
|
+
break;
|
|
35791
36050
|
}
|
|
36051
|
+
default:
|
|
36052
|
+
console.log(chalk2.yellow(`Unknown command: ${command}. Type "help" for available commands.`));
|
|
35792
36053
|
}
|
|
35793
36054
|
}
|
|
35794
|
-
function
|
|
35795
|
-
|
|
35796
|
-
|
|
35797
|
-
|
|
36055
|
+
function showHelp() {
|
|
36056
|
+
console.log(`
|
|
36057
|
+
${chalk2.green("Available Commands:")}
|
|
36058
|
+
|
|
36059
|
+
${chalk2.cyan("entities")} / ${chalk2.cyan("ls")} List all entities
|
|
36060
|
+
${chalk2.cyan("get <name>")} Get entity details
|
|
36061
|
+
${chalk2.cyan("search <query>")} Search entities
|
|
36062
|
+
${chalk2.cyan("relations <name>")} Show relations for entity
|
|
36063
|
+
${chalk2.cyan("tags <name>")} Show tags for entity
|
|
36064
|
+
${chalk2.cyan("path <from> <to>")} Find shortest path
|
|
36065
|
+
${chalk2.cyan("observe <e> <text>")} Add observation to entity
|
|
36066
|
+
${chalk2.cyan("delete <name>")} Delete entity
|
|
36067
|
+
${chalk2.cyan("export [format]")} Export graph to stdout
|
|
36068
|
+
${chalk2.cyan("stats")} Show graph statistics
|
|
36069
|
+
${chalk2.cyan("show <name>")} Verbose entity snapshot (obs + relations + hierarchy)
|
|
36070
|
+
${chalk2.cyan("tree [root]")} ASCII hierarchy tree (all roots if omitted)
|
|
36071
|
+
${chalk2.cyan("neighbors <name>")} Incoming + outgoing relations + degree counts
|
|
36072
|
+
${chalk2.cyan("diag")} / ${chalk2.cyan("health")} Quick integrity summary
|
|
36073
|
+
${chalk2.cyan("size")} Graph + storage footprint
|
|
36074
|
+
${chalk2.cyan("history")} Show command history
|
|
36075
|
+
${chalk2.cyan("clear")} Clear screen
|
|
36076
|
+
${chalk2.cyan("help")} Show this help
|
|
36077
|
+
${chalk2.cyan("exit")} Exit interactive mode
|
|
36078
|
+
|
|
36079
|
+
${chalk2.gray("Tab completion available for entity names.")}
|
|
36080
|
+
`);
|
|
35798
36081
|
}
|
|
35799
|
-
|
|
35800
|
-
|
|
35801
|
-
|
|
36082
|
+
var init_interactive = __esm({
|
|
36083
|
+
"src/cli/interactive.ts"() {
|
|
36084
|
+
"use strict";
|
|
36085
|
+
init_esm_shims();
|
|
36086
|
+
init_ManagerContext();
|
|
35802
36087
|
}
|
|
35803
|
-
|
|
35804
|
-
}
|
|
36088
|
+
});
|
|
35805
36089
|
|
|
35806
|
-
// src/cli/
|
|
35807
|
-
|
|
35808
|
-
|
|
35809
|
-
|
|
35810
|
-
|
|
35811
|
-
|
|
35812
|
-
}
|
|
35813
|
-
function createContext(options) {
|
|
35814
|
-
return new ManagerContext(options.storage);
|
|
35815
|
-
}
|
|
36090
|
+
// src/cli/index.ts
|
|
36091
|
+
init_esm_shims();
|
|
36092
|
+
import { Command as Command2 } from "commander";
|
|
36093
|
+
|
|
36094
|
+
// src/cli/commands/index.ts
|
|
36095
|
+
init_esm_shims();
|
|
35816
36096
|
|
|
35817
36097
|
// src/cli/commands/entity.ts
|
|
36098
|
+
init_esm_shims();
|
|
36099
|
+
init_helpers();
|
|
36100
|
+
init_formatters2();
|
|
35818
36101
|
function registerEntityCommands(program2) {
|
|
35819
36102
|
const entity = program2.command("entity").description("Manage entities (create, read, update, delete)");
|
|
35820
36103
|
entity.command("create <name>").description("Create a new entity").option("-t, --type <type>", "Entity type", "generic").option("-o, --observation <obs...>", "Observations to add").option("--tags <tags...>", "Tags to add").option("-i, --importance <n>", "Importance score (0-10)", parseFloat).action(async (name, opts) => {
|
|
@@ -35921,6 +36204,8 @@ function registerEntityCommands(program2) {
|
|
|
35921
36204
|
|
|
35922
36205
|
// src/cli/commands/relation.ts
|
|
35923
36206
|
init_esm_shims();
|
|
36207
|
+
init_helpers();
|
|
36208
|
+
init_formatters2();
|
|
35924
36209
|
function registerRelationCommands(program2) {
|
|
35925
36210
|
const relation = program2.command("relation").description("Manage relations between entities");
|
|
35926
36211
|
relation.command("create <from> <type> <to>").description("Create a new relation").action(async (from, relationType, to) => {
|
|
@@ -35973,6 +36258,8 @@ function registerRelationCommands(program2) {
|
|
|
35973
36258
|
|
|
35974
36259
|
// src/cli/commands/search.ts
|
|
35975
36260
|
init_esm_shims();
|
|
36261
|
+
init_helpers();
|
|
36262
|
+
init_formatters2();
|
|
35976
36263
|
function registerSearchCommands(program2) {
|
|
35977
36264
|
program2.command("search <query>").description("Search entities and observations").option("-l, --limit <n>", "Limit results", parseInt, 10).option("-t, --type <type>", "Filter by entity type").option("--ranked", "Use TF-IDF/BM25 ranked search").option("--boolean", "Use boolean search (AND/OR/NOT)").option("--fuzzy", "Use fuzzy search").option("--threshold <n>", "Fuzzy search threshold (0-1)", parseFloat, 0.6).option("--suggest", "Get search suggestions instead of results").action(async (query, opts) => {
|
|
35978
36265
|
const options = getOptions(program2);
|
|
@@ -36030,6 +36317,8 @@ function registerSearchCommands(program2) {
|
|
|
36030
36317
|
|
|
36031
36318
|
// src/cli/commands/observation.ts
|
|
36032
36319
|
init_esm_shims();
|
|
36320
|
+
init_helpers();
|
|
36321
|
+
init_formatters2();
|
|
36033
36322
|
function registerObservationCommands(program2) {
|
|
36034
36323
|
const observation = program2.command("observation").description("Manage entity observations");
|
|
36035
36324
|
observation.command("add <entity> <text...>").description("Add observation(s) to an entity").action(async (entity, text) => {
|
|
@@ -36102,6 +36391,8 @@ function registerObservationCommands(program2) {
|
|
|
36102
36391
|
|
|
36103
36392
|
// src/cli/commands/tag.ts
|
|
36104
36393
|
init_esm_shims();
|
|
36394
|
+
init_helpers();
|
|
36395
|
+
init_formatters2();
|
|
36105
36396
|
function registerTagCommands(program2) {
|
|
36106
36397
|
const tag = program2.command("tag").description("Manage entity tags and aliases");
|
|
36107
36398
|
tag.command("add <entity> <tags...>").description("Add tags to an entity").action(async (entity, tags) => {
|
|
@@ -36176,6 +36467,8 @@ function registerTagCommands(program2) {
|
|
|
36176
36467
|
|
|
36177
36468
|
// src/cli/commands/hierarchy.ts
|
|
36178
36469
|
init_esm_shims();
|
|
36470
|
+
init_helpers();
|
|
36471
|
+
init_formatters2();
|
|
36179
36472
|
function registerHierarchyCommands(program2) {
|
|
36180
36473
|
const hierarchy = program2.command("hierarchy").description("Manage entity hierarchy (parent/child relationships)");
|
|
36181
36474
|
hierarchy.command("set-parent <entity> <parent>").description('Set parent of an entity (use "none" to remove)').action(async (entity, parent) => {
|
|
@@ -36247,6 +36540,8 @@ function registerHierarchyCommands(program2) {
|
|
|
36247
36540
|
|
|
36248
36541
|
// src/cli/commands/graph.ts
|
|
36249
36542
|
init_esm_shims();
|
|
36543
|
+
init_helpers();
|
|
36544
|
+
init_formatters2();
|
|
36250
36545
|
function registerGraphCommands(program2) {
|
|
36251
36546
|
const graph = program2.command("graph").description("Graph algorithms (shortest path, centrality, components)");
|
|
36252
36547
|
graph.command("shortest-path <from> <to>").description("Find shortest path between two entities").action(async (from, to) => {
|
|
@@ -36317,10 +36612,12 @@ function registerGraphCommands(program2) {
|
|
|
36317
36612
|
|
|
36318
36613
|
// src/cli/commands/io.ts
|
|
36319
36614
|
init_esm_shims();
|
|
36615
|
+
init_helpers();
|
|
36616
|
+
init_formatters2();
|
|
36617
|
+
init_entityUtils();
|
|
36320
36618
|
import { readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
36321
36619
|
import { resolve as resolve3 } from "path";
|
|
36322
36620
|
import { Option } from "commander";
|
|
36323
|
-
init_entityUtils();
|
|
36324
36621
|
var IMPORT_FORMATS = ["json", "csv", "graphml"];
|
|
36325
36622
|
var EXPORT_FORMATS = ["json", "csv", "graphml", "gexf", "dot", "markdown", "mermaid", "turtle", "rdf-xml", "json-ld"];
|
|
36326
36623
|
function registerIOCommands(program2) {
|
|
@@ -36370,6 +36667,8 @@ function registerIOCommands(program2) {
|
|
|
36370
36667
|
|
|
36371
36668
|
// src/cli/commands/maintenance.ts
|
|
36372
36669
|
init_esm_shims();
|
|
36670
|
+
init_helpers();
|
|
36671
|
+
init_formatters2();
|
|
36373
36672
|
function registerMaintenanceCommands(program2) {
|
|
36374
36673
|
program2.command("stats").description("Show knowledge graph statistics").action(async () => {
|
|
36375
36674
|
const options = getOptions(program2);
|
|
@@ -36494,6 +36793,8 @@ Tags Used: ${allTags.size}
|
|
|
36494
36793
|
|
|
36495
36794
|
// src/cli/commands/exclusion.ts
|
|
36496
36795
|
init_esm_shims();
|
|
36796
|
+
init_helpers();
|
|
36797
|
+
init_formatters2();
|
|
36497
36798
|
function registerExclusionCommands(program2) {
|
|
36498
36799
|
const exclude = program2.command("exclude").description("Manage do_not_remember exclusion rules");
|
|
36499
36800
|
exclude.command("add <pattern>").description("Add an exclusion rule (substring match)").option("--scope <scope>", "Rule scope: 'future-only' | 'past-only' | 'both'", "both").option("--entity-type <type>", "Restrict to a single entity type").option("--reason <reason>", "Free-text justification").action(async (pattern2, opts) => {
|
|
@@ -36573,6 +36874,8 @@ function registerExclusionCommands(program2) {
|
|
|
36573
36874
|
// src/cli/commands/decision.ts
|
|
36574
36875
|
init_esm_shims();
|
|
36575
36876
|
init_DecisionManager();
|
|
36877
|
+
init_helpers();
|
|
36878
|
+
init_formatters2();
|
|
36576
36879
|
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
36577
36880
|
function registerDecisionCommands(program2) {
|
|
36578
36881
|
const decision = program2.command("decision").description("Manage decision-rationale records (ADR-equivalent)");
|
|
@@ -36727,6 +37030,8 @@ function registerDecisionCommands(program2) {
|
|
|
36727
37030
|
|
|
36728
37031
|
// src/cli/commands/projectContext.ts
|
|
36729
37032
|
init_esm_shims();
|
|
37033
|
+
init_helpers();
|
|
37034
|
+
init_formatters2();
|
|
36730
37035
|
function registerProjectContextCommands(program2) {
|
|
36731
37036
|
const pc = program2.command("project-context").description("Manage structured per-project knowledge (facts/conventions/commands/glossary)");
|
|
36732
37037
|
pc.command("show <projectId>").description("Show the project-context record as rendered prose").action(async (projectId) => {
|
|
@@ -36821,6 +37126,8 @@ function registerProjectContextCommands(program2) {
|
|
|
36821
37126
|
|
|
36822
37127
|
// src/cli/commands/toolAffordance.ts
|
|
36823
37128
|
init_esm_shims();
|
|
37129
|
+
init_helpers();
|
|
37130
|
+
init_formatters2();
|
|
36824
37131
|
function registerToolAffordanceCommands(program2) {
|
|
36825
37132
|
const ta = program2.command("tool-affordance").description("Inspect per-tool rolling outcome statistics");
|
|
36826
37133
|
ta.command("list").description("List all tools with affordance records").action(async () => {
|
|
@@ -36896,7 +37203,570 @@ function registerToolAffordanceCommands(program2) {
|
|
|
36896
37203
|
});
|
|
36897
37204
|
}
|
|
36898
37205
|
|
|
37206
|
+
// src/cli/commands/smoke.ts
|
|
37207
|
+
init_esm_shims();
|
|
37208
|
+
init_ManagerContext();
|
|
37209
|
+
init_formatters2();
|
|
37210
|
+
import { promises as fs18 } from "fs";
|
|
37211
|
+
import { join as join8 } from "path";
|
|
37212
|
+
import { tmpdir } from "os";
|
|
37213
|
+
import { performance } from "perf_hooks";
|
|
37214
|
+
async function runSteps(steps, verbose) {
|
|
37215
|
+
const results = [];
|
|
37216
|
+
for (const step of steps) {
|
|
37217
|
+
const start = performance.now();
|
|
37218
|
+
try {
|
|
37219
|
+
await step.run();
|
|
37220
|
+
const durationMs = performance.now() - start;
|
|
37221
|
+
results.push({ name: step.name, ok: true, durationMs });
|
|
37222
|
+
if (verbose) {
|
|
37223
|
+
console.log(` ${formatSuccess("\u2713")} ${step.name} (${durationMs.toFixed(1)} ms)`);
|
|
37224
|
+
}
|
|
37225
|
+
} catch (error) {
|
|
37226
|
+
const durationMs = performance.now() - start;
|
|
37227
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
37228
|
+
results.push({ name: step.name, ok: false, durationMs, error: message });
|
|
37229
|
+
if (verbose) {
|
|
37230
|
+
console.log(` ${formatError("\u2717")} ${step.name} (${durationMs.toFixed(1)} ms) \u2014 ${message}`);
|
|
37231
|
+
}
|
|
37232
|
+
}
|
|
37233
|
+
}
|
|
37234
|
+
return results;
|
|
37235
|
+
}
|
|
37236
|
+
function buildSteps(ctx) {
|
|
37237
|
+
return [
|
|
37238
|
+
// ---- Entity (CRUD) ----
|
|
37239
|
+
{
|
|
37240
|
+
name: "entity:create",
|
|
37241
|
+
run: async () => {
|
|
37242
|
+
const [created] = await ctx.entityManager.createEntities([{
|
|
37243
|
+
name: "Alpha",
|
|
37244
|
+
entityType: "service",
|
|
37245
|
+
observations: ["root node"]
|
|
37246
|
+
}]);
|
|
37247
|
+
if (created.name !== "Alpha") throw new Error(`expected Alpha got ${created.name}`);
|
|
37248
|
+
}
|
|
37249
|
+
},
|
|
37250
|
+
{
|
|
37251
|
+
name: "entity:open_nodes",
|
|
37252
|
+
run: async () => {
|
|
37253
|
+
const result = await ctx.searchManager.openNodes(["Alpha"]);
|
|
37254
|
+
if (result.entities.length !== 1) throw new Error(`expected 1 entity got ${result.entities.length}`);
|
|
37255
|
+
}
|
|
37256
|
+
},
|
|
37257
|
+
{
|
|
37258
|
+
name: "entity:update",
|
|
37259
|
+
run: async () => {
|
|
37260
|
+
await ctx.entityManager.updateEntity("Alpha", { importance: 7 });
|
|
37261
|
+
const after = ctx.storage.getEntityByName("Alpha");
|
|
37262
|
+
if (after?.importance !== 7) throw new Error(`importance not persisted: ${after?.importance}`);
|
|
37263
|
+
}
|
|
37264
|
+
},
|
|
37265
|
+
// ---- Relation ----
|
|
37266
|
+
{
|
|
37267
|
+
name: "relation:create_endpoints",
|
|
37268
|
+
run: async () => {
|
|
37269
|
+
await ctx.entityManager.createEntities([
|
|
37270
|
+
{ name: "Beta", entityType: "service", observations: ["second node"] },
|
|
37271
|
+
{ name: "Gamma", entityType: "service", observations: ["third node"] }
|
|
37272
|
+
]);
|
|
37273
|
+
}
|
|
37274
|
+
},
|
|
37275
|
+
{
|
|
37276
|
+
name: "relation:create",
|
|
37277
|
+
run: async () => {
|
|
37278
|
+
await ctx.relationManager.createRelations([{ from: "Alpha", to: "Beta", relationType: "depends_on" }]);
|
|
37279
|
+
const graph = await ctx.storage.loadGraph();
|
|
37280
|
+
if (!graph.relations.some((r) => r.from === "Alpha" && r.to === "Beta")) {
|
|
37281
|
+
throw new Error("relation Alpha\u2192Beta not found in graph");
|
|
37282
|
+
}
|
|
37283
|
+
}
|
|
37284
|
+
},
|
|
37285
|
+
// ---- Observation ----
|
|
37286
|
+
{
|
|
37287
|
+
name: "observation:add",
|
|
37288
|
+
run: async () => {
|
|
37289
|
+
await ctx.observationManager.addObservations([
|
|
37290
|
+
{ entityName: "Alpha", contents: ["extra note for search"] }
|
|
37291
|
+
]);
|
|
37292
|
+
const obs = await ctx.observationManager.getObservationsFor("Alpha");
|
|
37293
|
+
if (!obs.some((o) => o.includes("extra note"))) throw new Error("observation not persisted");
|
|
37294
|
+
}
|
|
37295
|
+
},
|
|
37296
|
+
{
|
|
37297
|
+
name: "observation:delete",
|
|
37298
|
+
run: async () => {
|
|
37299
|
+
await ctx.observationManager.deleteObservations([
|
|
37300
|
+
{ entityName: "Alpha", observations: ["root node"] }
|
|
37301
|
+
]);
|
|
37302
|
+
const obs = await ctx.observationManager.getObservationsFor("Alpha");
|
|
37303
|
+
if (obs.includes("root node")) throw new Error("observation not deleted");
|
|
37304
|
+
}
|
|
37305
|
+
},
|
|
37306
|
+
// ---- Search ----
|
|
37307
|
+
{
|
|
37308
|
+
name: "search:basic",
|
|
37309
|
+
run: async () => {
|
|
37310
|
+
const result = await ctx.searchManager.searchNodes("extra note");
|
|
37311
|
+
if (result.entities.length === 0) throw new Error("basic search returned no entities");
|
|
37312
|
+
}
|
|
37313
|
+
},
|
|
37314
|
+
{
|
|
37315
|
+
name: "search:boolean",
|
|
37316
|
+
run: async () => {
|
|
37317
|
+
const result = await ctx.searchManager.booleanSearch("extra AND note");
|
|
37318
|
+
if (result.entities.length === 0) throw new Error("boolean search returned no entities");
|
|
37319
|
+
}
|
|
37320
|
+
},
|
|
37321
|
+
{
|
|
37322
|
+
name: "search:ranked",
|
|
37323
|
+
run: async () => {
|
|
37324
|
+
const result = await ctx.rankedSearch.searchNodesRanked("extra note", void 0, void 0, void 0, 5);
|
|
37325
|
+
if (result.length === 0) throw new Error("ranked search returned no results");
|
|
37326
|
+
}
|
|
37327
|
+
},
|
|
37328
|
+
// ---- Tag ----
|
|
37329
|
+
{
|
|
37330
|
+
name: "tag:add",
|
|
37331
|
+
run: async () => {
|
|
37332
|
+
await ctx.entityManager.addTags("Alpha", ["critical", "core"]);
|
|
37333
|
+
const e = ctx.storage.getEntityByName("Alpha");
|
|
37334
|
+
if (!e?.tags?.includes("critical")) throw new Error("tag not added");
|
|
37335
|
+
}
|
|
37336
|
+
},
|
|
37337
|
+
{
|
|
37338
|
+
name: "tag:remove",
|
|
37339
|
+
run: async () => {
|
|
37340
|
+
await ctx.entityManager.removeTags("Alpha", ["core"]);
|
|
37341
|
+
const e = ctx.storage.getEntityByName("Alpha");
|
|
37342
|
+
if (e?.tags?.includes("core")) throw new Error("tag not removed");
|
|
37343
|
+
}
|
|
37344
|
+
},
|
|
37345
|
+
// ---- Hierarchy ----
|
|
37346
|
+
{
|
|
37347
|
+
name: "hierarchy:set_parent",
|
|
37348
|
+
run: async () => {
|
|
37349
|
+
await ctx.hierarchyManager.setEntityParent("Beta", "Alpha");
|
|
37350
|
+
const e = ctx.storage.getEntityByName("Beta");
|
|
37351
|
+
if (e?.parentId !== "Alpha") throw new Error(`parent not set: ${e?.parentId}`);
|
|
37352
|
+
}
|
|
37353
|
+
},
|
|
37354
|
+
{
|
|
37355
|
+
name: "hierarchy:ancestors",
|
|
37356
|
+
run: async () => {
|
|
37357
|
+
const ancestors = await ctx.hierarchyManager.getAncestors("Beta");
|
|
37358
|
+
if (!ancestors.some((a) => a.name === "Alpha")) throw new Error("Alpha not in Beta ancestors");
|
|
37359
|
+
}
|
|
37360
|
+
},
|
|
37361
|
+
// ---- Graph algorithms ----
|
|
37362
|
+
{
|
|
37363
|
+
name: "graph:shortest_path",
|
|
37364
|
+
run: async () => {
|
|
37365
|
+
const result = await ctx.graphTraversal.findShortestPath("Alpha", "Beta");
|
|
37366
|
+
if (!result || result.path.length === 0) throw new Error("no path found Alpha\u2192Beta");
|
|
37367
|
+
}
|
|
37368
|
+
},
|
|
37369
|
+
{
|
|
37370
|
+
name: "graph:connected_components",
|
|
37371
|
+
run: async () => {
|
|
37372
|
+
const result = await ctx.graphTraversal.findConnectedComponents();
|
|
37373
|
+
if (result.components.length === 0) throw new Error("no connected components");
|
|
37374
|
+
}
|
|
37375
|
+
},
|
|
37376
|
+
// ---- IO ----
|
|
37377
|
+
{
|
|
37378
|
+
name: "io:export_json",
|
|
37379
|
+
run: async () => {
|
|
37380
|
+
const graph = await ctx.storage.loadGraph();
|
|
37381
|
+
const exported = ctx.ioManager.exportGraph(graph, "json");
|
|
37382
|
+
const parsed = JSON.parse(exported);
|
|
37383
|
+
if (!Array.isArray(parsed.entities) || parsed.entities.length < 3) {
|
|
37384
|
+
throw new Error(`export json had ${parsed.entities?.length} entities`);
|
|
37385
|
+
}
|
|
37386
|
+
}
|
|
37387
|
+
},
|
|
37388
|
+
// ---- Maintenance / Analytics ----
|
|
37389
|
+
{
|
|
37390
|
+
name: "analytics:stats",
|
|
37391
|
+
run: async () => {
|
|
37392
|
+
const stats = await ctx.analyticsManager.getGraphStats();
|
|
37393
|
+
if (stats.totalEntities < 3) throw new Error(`stats.totalEntities=${stats.totalEntities}`);
|
|
37394
|
+
}
|
|
37395
|
+
},
|
|
37396
|
+
{
|
|
37397
|
+
name: "maintenance:validate",
|
|
37398
|
+
run: async () => {
|
|
37399
|
+
const report = await ctx.analyticsManager.validateGraph();
|
|
37400
|
+
if (!report) throw new Error("validate returned nothing");
|
|
37401
|
+
}
|
|
37402
|
+
},
|
|
37403
|
+
// ---- Decision Rationale (v2.1.0) ----
|
|
37404
|
+
{
|
|
37405
|
+
name: "decision:propose",
|
|
37406
|
+
run: async () => {
|
|
37407
|
+
const r = await ctx.decisionManager.propose({
|
|
37408
|
+
context: "choosing storage",
|
|
37409
|
+
decision: "use SQLite",
|
|
37410
|
+
alternatives: ["JSONL"],
|
|
37411
|
+
consequences: ["ACID"]
|
|
37412
|
+
});
|
|
37413
|
+
if (!r.id) throw new Error("propose returned no id");
|
|
37414
|
+
}
|
|
37415
|
+
},
|
|
37416
|
+
{
|
|
37417
|
+
name: "decision:accept",
|
|
37418
|
+
run: async () => {
|
|
37419
|
+
const list = await ctx.decisionManager.list({ status: "proposed" });
|
|
37420
|
+
if (list.length === 0) throw new Error("no proposed decision to accept");
|
|
37421
|
+
const result = await ctx.decisionManager.accept(list[0].id);
|
|
37422
|
+
if (result !== "accepted") throw new Error(`accept returned ${result}`);
|
|
37423
|
+
}
|
|
37424
|
+
},
|
|
37425
|
+
{
|
|
37426
|
+
name: "decision:list",
|
|
37427
|
+
run: async () => {
|
|
37428
|
+
const list = await ctx.decisionManager.list({ status: "accepted" });
|
|
37429
|
+
if (list.length === 0) throw new Error("accepted decision missing from list");
|
|
37430
|
+
}
|
|
37431
|
+
},
|
|
37432
|
+
// ---- Heuristic Guidelines (v2.1.0) ----
|
|
37433
|
+
{
|
|
37434
|
+
name: "heuristic:add",
|
|
37435
|
+
run: async () => {
|
|
37436
|
+
const id = await ctx.heuristicManager.add({
|
|
37437
|
+
condition: "editing TypeScript",
|
|
37438
|
+
action: "run typecheck before commit"
|
|
37439
|
+
});
|
|
37440
|
+
if (!id) throw new Error("add_heuristic returned no id");
|
|
37441
|
+
}
|
|
37442
|
+
},
|
|
37443
|
+
{
|
|
37444
|
+
name: "heuristic:match",
|
|
37445
|
+
run: async () => {
|
|
37446
|
+
const matches2 = await ctx.heuristicManager.match("editing TypeScript file");
|
|
37447
|
+
if (matches2.length === 0) throw new Error("match returned no heuristics");
|
|
37448
|
+
}
|
|
37449
|
+
},
|
|
37450
|
+
// ---- Project Context (v2.1.0) ----
|
|
37451
|
+
{
|
|
37452
|
+
name: "project_context:upsert",
|
|
37453
|
+
run: async () => {
|
|
37454
|
+
const rec = await ctx.projectContextManager.upsert("smoke", {
|
|
37455
|
+
facts: ["smoke test project"]
|
|
37456
|
+
});
|
|
37457
|
+
if (!rec) throw new Error("upsert returned nothing");
|
|
37458
|
+
}
|
|
37459
|
+
},
|
|
37460
|
+
{
|
|
37461
|
+
name: "project_context:get",
|
|
37462
|
+
run: async () => {
|
|
37463
|
+
const rec = ctx.projectContextManager.get("smoke");
|
|
37464
|
+
if (!rec) throw new Error("project context not found after upsert");
|
|
37465
|
+
}
|
|
37466
|
+
},
|
|
37467
|
+
// ---- Tool Affordance (v2.1.0) ----
|
|
37468
|
+
{
|
|
37469
|
+
name: "tool_affordance:record + stats",
|
|
37470
|
+
run: async () => {
|
|
37471
|
+
await ctx.toolAffordanceManager.recordOutcome("test_tool", {
|
|
37472
|
+
outcome: "success",
|
|
37473
|
+
durationMs: 10
|
|
37474
|
+
});
|
|
37475
|
+
const stats = ctx.toolAffordanceManager.rollingStats("test_tool");
|
|
37476
|
+
if (!stats) throw new Error("rollingStats returned null after recording");
|
|
37477
|
+
}
|
|
37478
|
+
},
|
|
37479
|
+
// ---- Exclusion (do_not_remember) (v2.1.0) ----
|
|
37480
|
+
{
|
|
37481
|
+
name: "exclusion:add + check",
|
|
37482
|
+
run: async () => {
|
|
37483
|
+
await ctx.exclusionManager.add({ pattern: "secret-token" });
|
|
37484
|
+
const verdict = await ctx.exclusionManager.check("this contains secret-token");
|
|
37485
|
+
if (!verdict.blocked) throw new Error("exclusion check failed to block matching content");
|
|
37486
|
+
}
|
|
37487
|
+
},
|
|
37488
|
+
// ---- Observation Dedup (v2.1.0) ----
|
|
37489
|
+
{
|
|
37490
|
+
name: "observation_dedup:find",
|
|
37491
|
+
run: async () => {
|
|
37492
|
+
await ctx.entityManager.createEntities([
|
|
37493
|
+
{ name: "DupA", entityType: "note", observations: ["shared dedup fact"] },
|
|
37494
|
+
{ name: "DupB", entityType: "note", observations: ["shared dedup fact"] }
|
|
37495
|
+
]);
|
|
37496
|
+
const groups = await ctx.observationDedupManager.findDuplicateObservations({});
|
|
37497
|
+
if (groups.length === 0) throw new Error("dedup found 0 groups despite seeded duplicates");
|
|
37498
|
+
}
|
|
37499
|
+
},
|
|
37500
|
+
// ---- Spell Correction (v2.1.0) ----
|
|
37501
|
+
{
|
|
37502
|
+
name: "spell:rebuild + suggest",
|
|
37503
|
+
run: async () => {
|
|
37504
|
+
await ctx.spellChecker.rebuild();
|
|
37505
|
+
const suggestions = await ctx.spellChecker.suggest("Alpa", { limit: 3 });
|
|
37506
|
+
if (!Array.isArray(suggestions)) throw new Error("suggest did not return an array");
|
|
37507
|
+
}
|
|
37508
|
+
}
|
|
37509
|
+
];
|
|
37510
|
+
}
|
|
37511
|
+
function printSummary(results, totalMs, verbose) {
|
|
37512
|
+
const passed = results.filter((r) => r.ok).length;
|
|
37513
|
+
const failed = results.length - passed;
|
|
37514
|
+
if (!verbose) {
|
|
37515
|
+
for (const r of results) {
|
|
37516
|
+
const marker = r.ok ? formatSuccess("\u2713") : formatError("\u2717");
|
|
37517
|
+
const tail = r.ok ? "" : ` \u2014 ${r.error}`;
|
|
37518
|
+
console.log(` ${marker} ${r.name}${tail}`);
|
|
37519
|
+
}
|
|
37520
|
+
}
|
|
37521
|
+
console.log("");
|
|
37522
|
+
if (failed === 0) {
|
|
37523
|
+
console.log(formatSuccess(`Smoke test passed: ${passed}/${results.length} steps in ${totalMs.toFixed(0)} ms`));
|
|
37524
|
+
} else {
|
|
37525
|
+
console.log(formatError(`Smoke test FAILED: ${failed} failing / ${results.length} total in ${totalMs.toFixed(0)} ms`));
|
|
37526
|
+
}
|
|
37527
|
+
}
|
|
37528
|
+
function registerSmokeCommand(program2) {
|
|
37529
|
+
program2.command("smoke").description("Run a per-category end-to-end smoke test (~30 ops) against a fresh temp graph").option("-s, --storage <path>", "Storage path for the smoke run (default: temp dir)").option("-k, --keep", "Preserve the smoke graph after the run and print its path (default: cleanup)").option("-v, --verbose", "Print each step as it runs (default: print summary only)").action(async (opts) => {
|
|
37530
|
+
const verbose = Boolean(opts.verbose);
|
|
37531
|
+
const keep = Boolean(opts.keep);
|
|
37532
|
+
const storagePath = opts.storage ? opts.storage : await fs18.mkdtemp(join8(tmpdir(), "memoryjs-smoke-"));
|
|
37533
|
+
const graphPath = opts.storage ? storagePath : join8(storagePath, "graph.jsonl");
|
|
37534
|
+
if (verbose) console.log(`Smoke storage: ${graphPath}`);
|
|
37535
|
+
const ctx = new ManagerContext(graphPath);
|
|
37536
|
+
const steps = buildSteps(ctx);
|
|
37537
|
+
const start = performance.now();
|
|
37538
|
+
const results = await runSteps(steps, verbose);
|
|
37539
|
+
const totalMs = performance.now() - start;
|
|
37540
|
+
printSummary(results, totalMs, verbose);
|
|
37541
|
+
if (keep) {
|
|
37542
|
+
console.log(`
|
|
37543
|
+
Keeping smoke graph at: ${graphPath}`);
|
|
37544
|
+
} else if (!opts.storage) {
|
|
37545
|
+
try {
|
|
37546
|
+
await fs18.rm(storagePath, { recursive: true, force: true });
|
|
37547
|
+
} catch {
|
|
37548
|
+
}
|
|
37549
|
+
}
|
|
37550
|
+
const failed = results.filter((r) => !r.ok).length;
|
|
37551
|
+
if (failed > 0) process.exit(1);
|
|
37552
|
+
});
|
|
37553
|
+
}
|
|
37554
|
+
|
|
37555
|
+
// src/cli/commands/diag.ts
|
|
37556
|
+
init_esm_shims();
|
|
37557
|
+
init_helpers();
|
|
37558
|
+
init_formatters2();
|
|
37559
|
+
import { promises as fs19 } from "fs";
|
|
37560
|
+
import { performance as performance2 } from "perf_hooks";
|
|
37561
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
37562
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
37563
|
+
import { dirname as dirname9, join as join9 } from "path";
|
|
37564
|
+
var ENV_VAR_CATALOG = [
|
|
37565
|
+
// Core
|
|
37566
|
+
{ name: "MEMORY_STORAGE_TYPE", defaultValue: "jsonl", description: "jsonl | sqlite \u2014 storage backend selector" },
|
|
37567
|
+
{ name: "MEMORY_FILE_PATH", defaultValue: "(repo default)", description: "Custom storage file path" },
|
|
37568
|
+
{ name: "SKIP_BENCHMARKS", defaultValue: "false", description: "Skip performance-benchmark tests" },
|
|
37569
|
+
{ name: "LOG_LEVEL", defaultValue: "(none)", description: "debug | info | warn | error" },
|
|
37570
|
+
// Embeddings
|
|
37571
|
+
{ name: "MEMORY_EMBEDDING_PROVIDER", defaultValue: "local", description: "openai | local | none" },
|
|
37572
|
+
{ name: "MEMORY_OPENAI_API_KEY", defaultValue: "(unset)", description: "OpenAI API key (when provider=openai)" },
|
|
37573
|
+
{ name: "MEMORY_EMBEDDING_MODEL", defaultValue: "(provider default)", description: "Override embedding model name" },
|
|
37574
|
+
{ name: "MEMORY_AUTO_INDEX_EMBEDDINGS", defaultValue: "false", description: "Auto-index new entities for semantic search" },
|
|
37575
|
+
// Read pool / coalescing
|
|
37576
|
+
{ name: "MEMORY_SQLITE_READ_POOL_SIZE", defaultValue: "4", description: "SQLite read-connection pool size" },
|
|
37577
|
+
{ name: "MEMORY_INDEX_COALESCE_MS", defaultValue: "50", description: "TF-IDF event-sync coalescing window (ms)" },
|
|
37578
|
+
// Governance
|
|
37579
|
+
{ name: "MEMORY_GOVERNANCE_ENABLED", defaultValue: "false", description: "Enable governance policy enforcement" },
|
|
37580
|
+
{ name: "MEMORY_AUDIT_LOG_FILE", defaultValue: "(unset)", description: "Path for audit JSONL trail" },
|
|
37581
|
+
{ name: "MEMORY_FRESHNESS_TTL_DEFAULT_HOURS", defaultValue: "168", description: "Default freshness TTL (hours)" },
|
|
37582
|
+
// Agent role + advanced
|
|
37583
|
+
{ name: "MEMORY_AGENT_ROLE", defaultValue: "(unset)", description: "researcher | planner | executor | reviewer | coordinator" },
|
|
37584
|
+
{ name: "MEMORY_ENTROPY_FILTER_ENABLED", defaultValue: "false", description: "Enable low-entropy observation filter" },
|
|
37585
|
+
{ name: "MEMORY_ENTROPY_THRESHOLD", defaultValue: "0.3", description: "Entropy filter threshold (0\u20131)" },
|
|
37586
|
+
{ name: "MEMORY_CONSOLIDATION_SCHEDULER_ENABLED", defaultValue: "false", description: "Enable background consolidation" },
|
|
37587
|
+
{ name: "MEMORY_CONSOLIDATION_INTERVAL_MS", defaultValue: "3600000", description: "Consolidation interval (ms)" },
|
|
37588
|
+
{ name: "MEMORY_DEFAULT_VISIBILITY", defaultValue: "private", description: "private | team | org | shared | public" },
|
|
37589
|
+
// CLI-only
|
|
37590
|
+
{ name: "MEMORYJS_STORAGE_PATH", defaultValue: "./memory.jsonl", description: "CLI: default storage path" },
|
|
37591
|
+
{ name: "MEMORYJS_OUTPUT_FORMAT", defaultValue: "json", description: "CLI: json | table | csv" }
|
|
37592
|
+
];
|
|
37593
|
+
function readPackageVersion() {
|
|
37594
|
+
try {
|
|
37595
|
+
const here = dirname9(fileURLToPath3(import.meta.url));
|
|
37596
|
+
for (const candidate of [
|
|
37597
|
+
join9(here, "../../../package.json"),
|
|
37598
|
+
join9(here, "../../package.json"),
|
|
37599
|
+
join9(here, "../package.json")
|
|
37600
|
+
]) {
|
|
37601
|
+
try {
|
|
37602
|
+
const raw = readFileSync4(candidate, "utf8");
|
|
37603
|
+
const pkg = JSON.parse(raw);
|
|
37604
|
+
if (pkg.name === "@danielsimonjr/memoryjs" && pkg.version) return pkg.version;
|
|
37605
|
+
} catch {
|
|
37606
|
+
}
|
|
37607
|
+
}
|
|
37608
|
+
} catch {
|
|
37609
|
+
}
|
|
37610
|
+
return "unknown";
|
|
37611
|
+
}
|
|
37612
|
+
async function buildSnapshot(ctx, storagePath) {
|
|
37613
|
+
let sizeBytes = 0;
|
|
37614
|
+
let exists = false;
|
|
37615
|
+
try {
|
|
37616
|
+
const stat = await fs19.stat(storagePath);
|
|
37617
|
+
exists = true;
|
|
37618
|
+
sizeBytes = stat.size;
|
|
37619
|
+
} catch {
|
|
37620
|
+
}
|
|
37621
|
+
const stats = await ctx.analyticsManager.getGraphStats();
|
|
37622
|
+
return {
|
|
37623
|
+
memoryjs: { version: readPackageVersion() },
|
|
37624
|
+
runtime: {
|
|
37625
|
+
node: process.version,
|
|
37626
|
+
platform: process.platform,
|
|
37627
|
+
arch: process.arch,
|
|
37628
|
+
pid: process.pid
|
|
37629
|
+
},
|
|
37630
|
+
storage: {
|
|
37631
|
+
path: storagePath,
|
|
37632
|
+
type: process.env.MEMORY_STORAGE_TYPE ?? "jsonl",
|
|
37633
|
+
exists,
|
|
37634
|
+
sizeBytes,
|
|
37635
|
+
entities: stats.totalEntities,
|
|
37636
|
+
relations: stats.totalRelations
|
|
37637
|
+
},
|
|
37638
|
+
loadedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
37639
|
+
};
|
|
37640
|
+
}
|
|
37641
|
+
async function runHealthChecks(ctx) {
|
|
37642
|
+
const checks = [];
|
|
37643
|
+
const t1 = performance2.now();
|
|
37644
|
+
let graph;
|
|
37645
|
+
try {
|
|
37646
|
+
graph = await ctx.storage.loadGraph();
|
|
37647
|
+
checks.push({ name: "storage:loadGraph", ok: true, durationMs: performance2.now() - t1 });
|
|
37648
|
+
} catch (e) {
|
|
37649
|
+
checks.push({
|
|
37650
|
+
name: "storage:loadGraph",
|
|
37651
|
+
ok: false,
|
|
37652
|
+
durationMs: performance2.now() - t1,
|
|
37653
|
+
detail: e instanceof Error ? e.message : String(e)
|
|
37654
|
+
});
|
|
37655
|
+
return checks;
|
|
37656
|
+
}
|
|
37657
|
+
const t2 = performance2.now();
|
|
37658
|
+
const names = /* @__PURE__ */ new Set();
|
|
37659
|
+
const dupes = [];
|
|
37660
|
+
for (const e of graph.entities) {
|
|
37661
|
+
if (names.has(e.name)) dupes.push(e.name);
|
|
37662
|
+
else names.add(e.name);
|
|
37663
|
+
}
|
|
37664
|
+
checks.push({
|
|
37665
|
+
name: "entities:distinct-names",
|
|
37666
|
+
ok: dupes.length === 0,
|
|
37667
|
+
durationMs: performance2.now() - t2,
|
|
37668
|
+
detail: dupes.length === 0 ? void 0 : `duplicates: ${dupes.slice(0, 5).join(", ")}${dupes.length > 5 ? "\u2026" : ""}`
|
|
37669
|
+
});
|
|
37670
|
+
const t3 = performance2.now();
|
|
37671
|
+
const orphans = [];
|
|
37672
|
+
for (const r of graph.relations) {
|
|
37673
|
+
if (!names.has(r.from)) orphans.push(`${r.from} \u2192 ${r.to} (from missing)`);
|
|
37674
|
+
else if (!names.has(r.to)) orphans.push(`${r.from} \u2192 ${r.to} (to missing)`);
|
|
37675
|
+
}
|
|
37676
|
+
checks.push({
|
|
37677
|
+
name: "relations:no-orphans",
|
|
37678
|
+
ok: orphans.length === 0,
|
|
37679
|
+
durationMs: performance2.now() - t3,
|
|
37680
|
+
detail: orphans.length === 0 ? void 0 : `${orphans.length} orphan(s); first: ${orphans.slice(0, 3).join("; ")}`
|
|
37681
|
+
});
|
|
37682
|
+
const t4 = performance2.now();
|
|
37683
|
+
const byName = /* @__PURE__ */ new Map();
|
|
37684
|
+
for (const e of graph.entities) byName.set(e.name, e);
|
|
37685
|
+
const cycleIssues = [];
|
|
37686
|
+
for (const e of graph.entities) {
|
|
37687
|
+
if (!e.parentId) continue;
|
|
37688
|
+
const visited = /* @__PURE__ */ new Set();
|
|
37689
|
+
let cur = byName.get(e.parentId);
|
|
37690
|
+
while (cur && cur.parentId) {
|
|
37691
|
+
if (visited.has(cur.name)) {
|
|
37692
|
+
cycleIssues.push(`cycle through ${cur.name}`);
|
|
37693
|
+
break;
|
|
37694
|
+
}
|
|
37695
|
+
visited.add(cur.name);
|
|
37696
|
+
cur = byName.get(cur.parentId);
|
|
37697
|
+
}
|
|
37698
|
+
if (e.parentId && !byName.has(e.parentId)) {
|
|
37699
|
+
cycleIssues.push(`${e.name}.parentId='${e.parentId}' missing`);
|
|
37700
|
+
}
|
|
37701
|
+
}
|
|
37702
|
+
checks.push({
|
|
37703
|
+
name: "hierarchy:no-cycles-no-missing-parents",
|
|
37704
|
+
ok: cycleIssues.length === 0,
|
|
37705
|
+
durationMs: performance2.now() - t4,
|
|
37706
|
+
detail: cycleIssues.length === 0 ? void 0 : cycleIssues.slice(0, 3).join("; ")
|
|
37707
|
+
});
|
|
37708
|
+
return checks;
|
|
37709
|
+
}
|
|
37710
|
+
function registerDiagCommand(program2) {
|
|
37711
|
+
program2.command("diag").description("One-shot diagnostic snapshot: memoryjs version, runtime, storage, env").action(async () => {
|
|
37712
|
+
const options = getOptions(program2);
|
|
37713
|
+
const logger2 = createLogger(options);
|
|
37714
|
+
const ctx = createContext(options);
|
|
37715
|
+
try {
|
|
37716
|
+
const snapshot = await buildSnapshot(ctx, options.storage);
|
|
37717
|
+
console.log(JSON.stringify(snapshot, null, 2));
|
|
37718
|
+
} catch (e) {
|
|
37719
|
+
logger2.error(formatError(e.message));
|
|
37720
|
+
process.exit(1);
|
|
37721
|
+
}
|
|
37722
|
+
});
|
|
37723
|
+
program2.command("env").description("Print all memoryjs env vars with documented defaults and resolved values").option("--all", "Include vars that are unset and have no documented default override").action(async (opts) => {
|
|
37724
|
+
const showAll = Boolean(opts.all);
|
|
37725
|
+
const rows = ENV_VAR_CATALOG.map((spec) => {
|
|
37726
|
+
const current = process.env[spec.name];
|
|
37727
|
+
return {
|
|
37728
|
+
name: spec.name,
|
|
37729
|
+
value: current ?? null,
|
|
37730
|
+
default: spec.defaultValue,
|
|
37731
|
+
set: current !== void 0,
|
|
37732
|
+
description: spec.description
|
|
37733
|
+
};
|
|
37734
|
+
});
|
|
37735
|
+
const filtered = showAll ? rows : rows.filter((r) => r.set || !r.default.startsWith("("));
|
|
37736
|
+
console.log(JSON.stringify({ count: filtered.length, vars: filtered }, null, 2));
|
|
37737
|
+
});
|
|
37738
|
+
program2.command("health").description("Run fast integrity checks (graph loads, distinct names, no orphan relations, no hierarchy cycles)").action(async () => {
|
|
37739
|
+
const options = getOptions(program2);
|
|
37740
|
+
const logger2 = createLogger(options);
|
|
37741
|
+
const ctx = createContext(options);
|
|
37742
|
+
try {
|
|
37743
|
+
const checks = await runHealthChecks(ctx);
|
|
37744
|
+
const failed = checks.filter((c) => !c.ok).length;
|
|
37745
|
+
const totalMs = checks.reduce((acc, c) => acc + c.durationMs, 0);
|
|
37746
|
+
console.log(JSON.stringify({
|
|
37747
|
+
ok: failed === 0,
|
|
37748
|
+
failed,
|
|
37749
|
+
totalChecks: checks.length,
|
|
37750
|
+
totalMs: Number(totalMs.toFixed(2)),
|
|
37751
|
+
checks
|
|
37752
|
+
}, null, 2));
|
|
37753
|
+
if (failed > 0) process.exit(1);
|
|
37754
|
+
} catch (e) {
|
|
37755
|
+
logger2.error(formatError(e.message));
|
|
37756
|
+
process.exit(1);
|
|
37757
|
+
}
|
|
37758
|
+
});
|
|
37759
|
+
program2.command("version").description("Compact version line: memoryjs, node, platform").action(() => {
|
|
37760
|
+
console.log(JSON.stringify({
|
|
37761
|
+
memoryjs: readPackageVersion(),
|
|
37762
|
+
node: process.version,
|
|
37763
|
+
platform: `${process.platform}/${process.arch}`
|
|
37764
|
+
}));
|
|
37765
|
+
});
|
|
37766
|
+
}
|
|
37767
|
+
|
|
36899
37768
|
// src/cli/commands/index.ts
|
|
37769
|
+
init_inspect();
|
|
36900
37770
|
function registerCommands(program2) {
|
|
36901
37771
|
registerEntityCommands(program2);
|
|
36902
37772
|
registerRelationCommands(program2);
|
|
@@ -36911,14 +37781,17 @@ function registerCommands(program2) {
|
|
|
36911
37781
|
registerDecisionCommands(program2);
|
|
36912
37782
|
registerProjectContextCommands(program2);
|
|
36913
37783
|
registerToolAffordanceCommands(program2);
|
|
37784
|
+
registerSmokeCommand(program2);
|
|
37785
|
+
registerDiagCommand(program2);
|
|
37786
|
+
registerInspectCommands(program2);
|
|
36914
37787
|
}
|
|
36915
37788
|
|
|
36916
37789
|
// src/cli/index.ts
|
|
36917
37790
|
init_logger();
|
|
36918
|
-
import { readFileSync as
|
|
37791
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
36919
37792
|
import { createInterface as createInterface2 } from "readline";
|
|
36920
|
-
import { fileURLToPath as
|
|
36921
|
-
import { dirname as
|
|
37793
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
37794
|
+
import { dirname as dirname10, join as join10 } from "path";
|
|
36922
37795
|
process.on("unhandledRejection", (reason) => {
|
|
36923
37796
|
logger.error("Unhandled promise rejection:", reason);
|
|
36924
37797
|
});
|
|
@@ -36927,10 +37800,10 @@ process.on("uncaughtException", (err) => {
|
|
|
36927
37800
|
});
|
|
36928
37801
|
function getVersion() {
|
|
36929
37802
|
try {
|
|
36930
|
-
const __filename2 =
|
|
36931
|
-
const __dirname2 =
|
|
36932
|
-
const pkgPath =
|
|
36933
|
-
const pkg = JSON.parse(
|
|
37803
|
+
const __filename2 = fileURLToPath4(import.meta.url);
|
|
37804
|
+
const __dirname2 = dirname10(__filename2);
|
|
37805
|
+
const pkgPath = join10(__dirname2, "..", "..", "package.json");
|
|
37806
|
+
const pkg = JSON.parse(readFileSync5(pkgPath, "utf-8"));
|
|
36934
37807
|
return pkg.version;
|
|
36935
37808
|
} catch {
|
|
36936
37809
|
return "0.0.0";
|