musememory 1.3.0 → 1.4.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.
Files changed (3) hide show
  1. package/README.md +24 -2
  2. package/dist/index.js +2865 -336
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -20,12 +20,14 @@ var __toESM = (mod, isNodeMode, target) => {
20
20
  }
21
21
  target = mod != null ? __create(__getProtoOf(mod)) : {};
22
22
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
23
- for (let key of __getOwnPropNames(mod))
24
- if (!__hasOwnProp.call(to, key))
25
- __defProp(to, key, {
26
- get: __accessProp.bind(mod, key),
27
- enumerable: true
28
- });
23
+ if (mod && typeof mod === "object" || typeof mod === "function") {
24
+ for (let key of __getOwnPropNames(mod))
25
+ if (!__hasOwnProp.call(to, key))
26
+ __defProp(to, key, {
27
+ get: __accessProp.bind(mod, key),
28
+ enumerable: true
29
+ });
30
+ }
29
31
  if (canCache)
30
32
  cache.set(mod, to);
31
33
  return to;
@@ -4693,9 +4695,9 @@ var init_graph = () => {};
4693
4695
  // src/prompt.ts
4694
4696
  var exports_prompt = {};
4695
4697
  __export(exports_prompt, {
4696
- promptSingleSelect: () => promptSingleSelect,
4698
+ parseSelectionInput: () => parseSelectionInput,
4697
4699
  promptMultiSelect: () => promptMultiSelect,
4698
- parseSelectionInput: () => parseSelectionInput
4700
+ promptSingleSelect: () => promptSingleSelect
4699
4701
  });
4700
4702
  import { createInterface } from "node:readline";
4701
4703
  function parseSelectionInput(rawInput, options, defaultAll = true) {
@@ -5341,9 +5343,9 @@ var init_registry = __esm(() => {
5341
5343
  // src/agents/detect.ts
5342
5344
  var exports_detect = {};
5343
5345
  __export(exports_detect, {
5344
- findBinary: () => findBinary,
5346
+ clearBinaryCache: () => clearBinaryCache,
5345
5347
  detectAgents: () => detectAgents,
5346
- clearBinaryCache: () => clearBinaryCache
5348
+ findBinary: () => findBinary
5347
5349
  });
5348
5350
  import { existsSync as existsSync12, readFileSync as readFileSync10 } from "node:fs";
5349
5351
  import { join as join12 } from "node:path";
@@ -5438,16 +5440,16 @@ var init_detect2 = __esm(() => {
5438
5440
  // src/connect.ts
5439
5441
  var exports_connect = {};
5440
5442
  __export(exports_connect, {
5441
- disconnectSingleAgent: () => disconnectSingleAgent,
5442
- disconnectAllAgents: () => disconnectAllAgents,
5443
- connectOpenCode: () => connectOpenCode,
5444
- connectOpenClaw: () => connectOpenClaw,
5445
- connectHermes: () => connectHermes,
5446
- connectGoose: () => connectGoose,
5447
- connectCursor: () => connectCursor,
5448
- connectClaudeCode: () => connectClaudeCode,
5443
+ ALL_MEMORY_TOOLS: () => ALL_MEMORY_TOOLS,
5449
5444
  connectAgent: () => connectAgent,
5450
- ALL_MEMORY_TOOLS: () => ALL_MEMORY_TOOLS
5445
+ connectClaudeCode: () => connectClaudeCode,
5446
+ connectCursor: () => connectCursor,
5447
+ connectGoose: () => connectGoose,
5448
+ connectHermes: () => connectHermes,
5449
+ connectOpenClaw: () => connectOpenClaw,
5450
+ connectOpenCode: () => connectOpenCode,
5451
+ disconnectAllAgents: () => disconnectAllAgents,
5452
+ disconnectSingleAgent: () => disconnectSingleAgent
5451
5453
  });
5452
5454
  import { existsSync as existsSync13, readFileSync as readFileSync11, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, statSync as statSync5 } from "node:fs";
5453
5455
  import { join as join13, dirname as dirname2 } from "node:path";
@@ -5851,7 +5853,7 @@ var init_connect = __esm(() => {
5851
5853
  });
5852
5854
 
5853
5855
  // node_modules/ajv/dist/compile/codegen/code.js
5854
- var require_code = __commonJS((exports) => {
5856
+ var require_code = __commonJS(function(exports) {
5855
5857
  Object.defineProperty(exports, "__esModule", { value: true });
5856
5858
  exports.regexpCode = exports.getEsmExportName = exports.getProperty = exports.safeStringify = exports.stringify = exports.strConcat = exports.addCodeArg = exports.str = exports._ = exports.nil = exports._Code = exports.Name = exports.IDENTIFIER = exports._CodeOrName = undefined;
5857
5859
 
@@ -6005,7 +6007,7 @@ var require_code = __commonJS((exports) => {
6005
6007
  });
6006
6008
 
6007
6009
  // node_modules/ajv/dist/compile/codegen/scope.js
6008
- var require_scope = __commonJS((exports) => {
6010
+ var require_scope = __commonJS(function(exports) {
6009
6011
  Object.defineProperty(exports, "__esModule", { value: true });
6010
6012
  exports.ValueScope = exports.ValueScopeName = exports.Scope = exports.varKinds = exports.UsedValueState = undefined;
6011
6013
  var code_1 = require_code();
@@ -6151,7 +6153,7 @@ var require_scope = __commonJS((exports) => {
6151
6153
  });
6152
6154
 
6153
6155
  // node_modules/ajv/dist/compile/codegen/index.js
6154
- var require_codegen = __commonJS((exports) => {
6156
+ var require_codegen = __commonJS(function(exports) {
6155
6157
  Object.defineProperty(exports, "__esModule", { value: true });
6156
6158
  exports.or = exports.and = exports.not = exports.CodeGen = exports.operators = exports.varKinds = exports.ValueScopeName = exports.ValueScope = exports.Scope = exports.Name = exports.regexpCode = exports.stringify = exports.getProperty = exports.nil = exports.strConcat = exports.str = exports._ = undefined;
6157
6159
  var code_1 = require_code();
@@ -6861,7 +6863,7 @@ var require_codegen = __commonJS((exports) => {
6861
6863
  });
6862
6864
 
6863
6865
  // node_modules/ajv/dist/compile/util.js
6864
- var require_util = __commonJS((exports) => {
6866
+ var require_util = __commonJS(function(exports) {
6865
6867
  Object.defineProperty(exports, "__esModule", { value: true });
6866
6868
  exports.checkStrictMode = exports.getErrorPath = exports.Type = exports.useFunc = exports.setEvaluated = exports.evaluatedPropsToName = exports.mergeEvaluated = exports.eachItem = exports.unescapeJsonPointer = exports.escapeJsonPointer = exports.escapeFragment = exports.unescapeFragment = exports.schemaRefOrVal = exports.schemaHasRulesButRef = exports.schemaHasRules = exports.checkUnknownRules = exports.alwaysValidSchema = exports.toHash = undefined;
6867
6869
  var codegen_1 = require_codegen();
@@ -7025,7 +7027,7 @@ var require_util = __commonJS((exports) => {
7025
7027
  });
7026
7028
 
7027
7029
  // node_modules/ajv/dist/compile/names.js
7028
- var require_names = __commonJS((exports) => {
7030
+ var require_names = __commonJS(function(exports) {
7029
7031
  Object.defineProperty(exports, "__esModule", { value: true });
7030
7032
  var codegen_1 = require_codegen();
7031
7033
  var names = {
@@ -7050,7 +7052,7 @@ var require_names = __commonJS((exports) => {
7050
7052
  });
7051
7053
 
7052
7054
  // node_modules/ajv/dist/compile/errors.js
7053
- var require_errors = __commonJS((exports) => {
7055
+ var require_errors = __commonJS(function(exports) {
7054
7056
  Object.defineProperty(exports, "__esModule", { value: true });
7055
7057
  exports.extendErrors = exports.resetErrorsCount = exports.reportExtraError = exports.reportError = exports.keyword$DataError = exports.keywordError = undefined;
7056
7058
  var codegen_1 = require_codegen();
@@ -7168,7 +7170,7 @@ var require_errors = __commonJS((exports) => {
7168
7170
  });
7169
7171
 
7170
7172
  // node_modules/ajv/dist/compile/validate/boolSchema.js
7171
- var require_boolSchema = __commonJS((exports) => {
7173
+ var require_boolSchema = __commonJS(function(exports) {
7172
7174
  Object.defineProperty(exports, "__esModule", { value: true });
7173
7175
  exports.boolOrEmptySchema = exports.topBoolOrEmptySchema = undefined;
7174
7176
  var errors_1 = require_errors();
@@ -7216,7 +7218,7 @@ var require_boolSchema = __commonJS((exports) => {
7216
7218
  });
7217
7219
 
7218
7220
  // node_modules/ajv/dist/compile/rules.js
7219
- var require_rules = __commonJS((exports) => {
7221
+ var require_rules = __commonJS(function(exports) {
7220
7222
  Object.defineProperty(exports, "__esModule", { value: true });
7221
7223
  exports.getRules = exports.isJSONType = undefined;
7222
7224
  var _jsonTypes = ["string", "number", "integer", "boolean", "null", "object", "array"];
@@ -7244,7 +7246,7 @@ var require_rules = __commonJS((exports) => {
7244
7246
  });
7245
7247
 
7246
7248
  // node_modules/ajv/dist/compile/validate/applicability.js
7247
- var require_applicability = __commonJS((exports) => {
7249
+ var require_applicability = __commonJS(function(exports) {
7248
7250
  Object.defineProperty(exports, "__esModule", { value: true });
7249
7251
  exports.shouldUseRule = exports.shouldUseGroup = exports.schemaHasRulesForType = undefined;
7250
7252
  function schemaHasRulesForType({ schema: schema2, self }, type2) {
@@ -7264,7 +7266,7 @@ var require_applicability = __commonJS((exports) => {
7264
7266
  });
7265
7267
 
7266
7268
  // node_modules/ajv/dist/compile/validate/dataType.js
7267
- var require_dataType = __commonJS((exports) => {
7269
+ var require_dataType = __commonJS(function(exports) {
7268
7270
  Object.defineProperty(exports, "__esModule", { value: true });
7269
7271
  exports.reportTypeError = exports.checkDataTypes = exports.checkDataType = exports.coerceAndCheckDataType = exports.getJSONTypes = exports.getSchemaTypes = exports.DataType = undefined;
7270
7272
  var rules_1 = require_rules();
@@ -7445,7 +7447,7 @@ var require_dataType = __commonJS((exports) => {
7445
7447
  });
7446
7448
 
7447
7449
  // node_modules/ajv/dist/compile/validate/defaults.js
7448
- var require_defaults = __commonJS((exports) => {
7450
+ var require_defaults = __commonJS(function(exports) {
7449
7451
  Object.defineProperty(exports, "__esModule", { value: true });
7450
7452
  exports.assignDefaults = undefined;
7451
7453
  var codegen_1 = require_codegen();
@@ -7479,7 +7481,7 @@ var require_defaults = __commonJS((exports) => {
7479
7481
  });
7480
7482
 
7481
7483
  // node_modules/ajv/dist/vocabularies/code.js
7482
- var require_code2 = __commonJS((exports) => {
7484
+ var require_code2 = __commonJS(function(exports) {
7483
7485
  Object.defineProperty(exports, "__esModule", { value: true });
7484
7486
  exports.validateUnion = exports.validateArray = exports.usePattern = exports.callValidateCode = exports.schemaProperties = exports.allSchemaProperties = exports.noPropertyInData = exports.propertyInData = exports.isOwnProperty = exports.hasPropFunc = exports.reportMissingProp = exports.checkMissingProp = exports.checkReportMissingProp = undefined;
7485
7487
  var codegen_1 = require_codegen();
@@ -7608,7 +7610,7 @@ var require_code2 = __commonJS((exports) => {
7608
7610
  });
7609
7611
 
7610
7612
  // node_modules/ajv/dist/compile/validate/keyword.js
7611
- var require_keyword = __commonJS((exports) => {
7613
+ var require_keyword = __commonJS(function(exports) {
7612
7614
  Object.defineProperty(exports, "__esModule", { value: true });
7613
7615
  exports.validateKeywordUsage = exports.validSchemaType = exports.funcKeywordCode = exports.macroKeywordCode = undefined;
7614
7616
  var codegen_1 = require_codegen();
@@ -7723,7 +7725,7 @@ var require_keyword = __commonJS((exports) => {
7723
7725
  });
7724
7726
 
7725
7727
  // node_modules/ajv/dist/compile/validate/subschema.js
7726
- var require_subschema = __commonJS((exports) => {
7728
+ var require_subschema = __commonJS(function(exports) {
7727
7729
  Object.defineProperty(exports, "__esModule", { value: true });
7728
7730
  exports.extendSubschemaMode = exports.extendSubschemaData = exports.getSubschema = undefined;
7729
7731
  var codegen_1 = require_codegen();
@@ -7803,7 +7805,7 @@ var require_subschema = __commonJS((exports) => {
7803
7805
  });
7804
7806
 
7805
7807
  // node_modules/fast-deep-equal/index.js
7806
- var require_fast_deep_equal = __commonJS((exports, module) => {
7808
+ var require_fast_deep_equal = __commonJS(function(exports, module) {
7807
7809
  module.exports = function equal(a, b) {
7808
7810
  if (a === b)
7809
7811
  return true;
@@ -7845,7 +7847,7 @@ var require_fast_deep_equal = __commonJS((exports, module) => {
7845
7847
  });
7846
7848
 
7847
7849
  // node_modules/json-schema-traverse/index.js
7848
- var require_json_schema_traverse = __commonJS((exports, module) => {
7850
+ var require_json_schema_traverse = __commonJS(function(exports, module) {
7849
7851
  var traverse = module.exports = function(schema2, opts, cb) {
7850
7852
  if (typeof opts == "function") {
7851
7853
  cb = opts;
@@ -7928,7 +7930,7 @@ var require_json_schema_traverse = __commonJS((exports, module) => {
7928
7930
  });
7929
7931
 
7930
7932
  // node_modules/ajv/dist/compile/resolve.js
7931
- var require_resolve = __commonJS((exports) => {
7933
+ var require_resolve = __commonJS(function(exports) {
7932
7934
  Object.defineProperty(exports, "__esModule", { value: true });
7933
7935
  exports.getSchemaRefs = exports.resolveUrl = exports.normalizeId = exports._getFullPath = exports.getFullPath = exports.inlineRef = undefined;
7934
7936
  var util_1 = require_util();
@@ -8081,7 +8083,7 @@ var require_resolve = __commonJS((exports) => {
8081
8083
  });
8082
8084
 
8083
8085
  // node_modules/ajv/dist/compile/validate/index.js
8084
- var require_validate = __commonJS((exports) => {
8086
+ var require_validate = __commonJS(function(exports) {
8085
8087
  Object.defineProperty(exports, "__esModule", { value: true });
8086
8088
  exports.getData = exports.KeywordCxt = exports.validateFunctionCode = undefined;
8087
8089
  var boolSchema_1 = require_boolSchema();
@@ -8586,7 +8588,7 @@ var require_validate = __commonJS((exports) => {
8586
8588
  });
8587
8589
 
8588
8590
  // node_modules/ajv/dist/runtime/validation_error.js
8589
- var require_validation_error = __commonJS((exports) => {
8591
+ var require_validation_error = __commonJS(function(exports) {
8590
8592
  Object.defineProperty(exports, "__esModule", { value: true });
8591
8593
 
8592
8594
  class ValidationError extends Error {
@@ -8600,7 +8602,7 @@ var require_validation_error = __commonJS((exports) => {
8600
8602
  });
8601
8603
 
8602
8604
  // node_modules/ajv/dist/compile/ref_error.js
8603
- var require_ref_error = __commonJS((exports) => {
8605
+ var require_ref_error = __commonJS(function(exports) {
8604
8606
  Object.defineProperty(exports, "__esModule", { value: true });
8605
8607
  var resolve_1 = require_resolve();
8606
8608
 
@@ -8615,7 +8617,7 @@ var require_ref_error = __commonJS((exports) => {
8615
8617
  });
8616
8618
 
8617
8619
  // node_modules/ajv/dist/compile/index.js
8618
- var require_compile = __commonJS((exports) => {
8620
+ var require_compile = __commonJS(function(exports) {
8619
8621
  Object.defineProperty(exports, "__esModule", { value: true });
8620
8622
  exports.resolveSchema = exports.getCompilingSchema = exports.resolveRef = exports.compileSchema = exports.SchemaEnv = undefined;
8621
8623
  var codegen_1 = require_codegen();
@@ -8836,7 +8838,7 @@ var require_compile = __commonJS((exports) => {
8836
8838
  });
8837
8839
 
8838
8840
  // node_modules/ajv/dist/refs/data.json
8839
- var require_data = __commonJS((exports, module) => {
8841
+ var require_data = __commonJS(function(exports, module) {
8840
8842
  module.exports = {
8841
8843
  $id: "https://raw.githubusercontent.com/ajv-validator/ajv/master/lib/refs/data.json#",
8842
8844
  description: "Meta-schema for $data reference (JSON AnySchema extension proposal)",
@@ -8853,7 +8855,7 @@ var require_data = __commonJS((exports, module) => {
8853
8855
  });
8854
8856
 
8855
8857
  // node_modules/fast-uri/lib/utils.js
8856
- var require_utils = __commonJS((exports, module) => {
8858
+ var require_utils = __commonJS(function(exports, module) {
8857
8859
  var isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
8858
8860
  var isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
8859
8861
  var isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
@@ -9164,7 +9166,7 @@ var require_utils = __commonJS((exports, module) => {
9164
9166
  });
9165
9167
 
9166
9168
  // node_modules/fast-uri/lib/schemes.js
9167
- var require_schemes = __commonJS((exports, module) => {
9169
+ var require_schemes = __commonJS(function(exports, module) {
9168
9170
  var { isUUID } = require_utils();
9169
9171
  var URN_REG = /([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-.:;=@]|%[\da-f]{2})+)/iu;
9170
9172
  var supportedSchemeNames = [
@@ -9338,7 +9340,7 @@ var require_schemes = __commonJS((exports, module) => {
9338
9340
  });
9339
9341
 
9340
9342
  // node_modules/fast-uri/index.js
9341
- var require_fast_uri = __commonJS((exports, module) => {
9343
+ var require_fast_uri = __commonJS(function(exports, module) {
9342
9344
  var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, escapePreservingEscapes, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
9343
9345
  var { SCHEMES, getSchemeHandler } = require_schemes();
9344
9346
  function normalize(uri, options) {
@@ -9646,7 +9648,7 @@ var require_fast_uri = __commonJS((exports, module) => {
9646
9648
  });
9647
9649
 
9648
9650
  // node_modules/ajv/dist/runtime/uri.js
9649
- var require_uri = __commonJS((exports) => {
9651
+ var require_uri = __commonJS(function(exports) {
9650
9652
  Object.defineProperty(exports, "__esModule", { value: true });
9651
9653
  var uri = require_fast_uri();
9652
9654
  uri.code = 'require("ajv/dist/runtime/uri").default';
@@ -9654,7 +9656,7 @@ var require_uri = __commonJS((exports) => {
9654
9656
  });
9655
9657
 
9656
9658
  // node_modules/ajv/dist/core.js
9657
- var require_core = __commonJS((exports) => {
9659
+ var require_core = __commonJS(function(exports) {
9658
9660
  Object.defineProperty(exports, "__esModule", { value: true });
9659
9661
  exports.CodeGen = exports.Name = exports.nil = exports.stringify = exports.str = exports._ = exports.KeywordCxt = undefined;
9660
9662
  var validate_1 = require_validate();
@@ -10247,7 +10249,7 @@ var require_core = __commonJS((exports) => {
10247
10249
  });
10248
10250
 
10249
10251
  // node_modules/ajv/dist/vocabularies/core/id.js
10250
- var require_id = __commonJS((exports) => {
10252
+ var require_id = __commonJS(function(exports) {
10251
10253
  Object.defineProperty(exports, "__esModule", { value: true });
10252
10254
  var def = {
10253
10255
  keyword: "id",
@@ -10259,7 +10261,7 @@ var require_id = __commonJS((exports) => {
10259
10261
  });
10260
10262
 
10261
10263
  // node_modules/ajv/dist/vocabularies/core/ref.js
10262
- var require_ref = __commonJS((exports) => {
10264
+ var require_ref = __commonJS(function(exports) {
10263
10265
  Object.defineProperty(exports, "__esModule", { value: true });
10264
10266
  exports.callRef = exports.getValidate = undefined;
10265
10267
  var ref_error_1 = require_ref_error();
@@ -10378,7 +10380,7 @@ var require_ref = __commonJS((exports) => {
10378
10380
  });
10379
10381
 
10380
10382
  // node_modules/ajv/dist/vocabularies/core/index.js
10381
- var require_core2 = __commonJS((exports) => {
10383
+ var require_core2 = __commonJS(function(exports) {
10382
10384
  Object.defineProperty(exports, "__esModule", { value: true });
10383
10385
  var id_1 = require_id();
10384
10386
  var ref_1 = require_ref();
@@ -10396,7 +10398,7 @@ var require_core2 = __commonJS((exports) => {
10396
10398
  });
10397
10399
 
10398
10400
  // node_modules/ajv/dist/vocabularies/validation/limitNumber.js
10399
- var require_limitNumber = __commonJS((exports) => {
10401
+ var require_limitNumber = __commonJS(function(exports) {
10400
10402
  Object.defineProperty(exports, "__esModule", { value: true });
10401
10403
  var codegen_1 = require_codegen();
10402
10404
  var ops = codegen_1.operators;
@@ -10425,7 +10427,7 @@ var require_limitNumber = __commonJS((exports) => {
10425
10427
  });
10426
10428
 
10427
10429
  // node_modules/ajv/dist/vocabularies/validation/multipleOf.js
10428
- var require_multipleOf = __commonJS((exports) => {
10430
+ var require_multipleOf = __commonJS(function(exports) {
10429
10431
  Object.defineProperty(exports, "__esModule", { value: true });
10430
10432
  var codegen_1 = require_codegen();
10431
10433
  var error = {
@@ -10450,7 +10452,7 @@ var require_multipleOf = __commonJS((exports) => {
10450
10452
  });
10451
10453
 
10452
10454
  // node_modules/ajv/dist/runtime/ucs2length.js
10453
- var require_ucs2length = __commonJS((exports) => {
10455
+ var require_ucs2length = __commonJS(function(exports) {
10454
10456
  Object.defineProperty(exports, "__esModule", { value: true });
10455
10457
  function ucs2length(str2) {
10456
10458
  const len = str2.length;
@@ -10473,7 +10475,7 @@ var require_ucs2length = __commonJS((exports) => {
10473
10475
  });
10474
10476
 
10475
10477
  // node_modules/ajv/dist/vocabularies/validation/limitLength.js
10476
- var require_limitLength = __commonJS((exports) => {
10478
+ var require_limitLength = __commonJS(function(exports) {
10477
10479
  Object.defineProperty(exports, "__esModule", { value: true });
10478
10480
  var codegen_1 = require_codegen();
10479
10481
  var util_1 = require_util();
@@ -10502,7 +10504,7 @@ var require_limitLength = __commonJS((exports) => {
10502
10504
  });
10503
10505
 
10504
10506
  // node_modules/ajv/dist/vocabularies/validation/pattern.js
10505
- var require_pattern = __commonJS((exports) => {
10507
+ var require_pattern = __commonJS(function(exports) {
10506
10508
  Object.defineProperty(exports, "__esModule", { value: true });
10507
10509
  var code_1 = require_code2();
10508
10510
  var util_1 = require_util();
@@ -10536,7 +10538,7 @@ var require_pattern = __commonJS((exports) => {
10536
10538
  });
10537
10539
 
10538
10540
  // node_modules/ajv/dist/vocabularies/validation/limitProperties.js
10539
- var require_limitProperties = __commonJS((exports) => {
10541
+ var require_limitProperties = __commonJS(function(exports) {
10540
10542
  Object.defineProperty(exports, "__esModule", { value: true });
10541
10543
  var codegen_1 = require_codegen();
10542
10544
  var error = {
@@ -10562,7 +10564,7 @@ var require_limitProperties = __commonJS((exports) => {
10562
10564
  });
10563
10565
 
10564
10566
  // node_modules/ajv/dist/vocabularies/validation/required.js
10565
- var require_required = __commonJS((exports) => {
10567
+ var require_required = __commonJS(function(exports) {
10566
10568
  Object.defineProperty(exports, "__esModule", { value: true });
10567
10569
  var code_1 = require_code2();
10568
10570
  var codegen_1 = require_codegen();
@@ -10641,7 +10643,7 @@ var require_required = __commonJS((exports) => {
10641
10643
  });
10642
10644
 
10643
10645
  // node_modules/ajv/dist/vocabularies/validation/limitItems.js
10644
- var require_limitItems = __commonJS((exports) => {
10646
+ var require_limitItems = __commonJS(function(exports) {
10645
10647
  Object.defineProperty(exports, "__esModule", { value: true });
10646
10648
  var codegen_1 = require_codegen();
10647
10649
  var error = {
@@ -10667,7 +10669,7 @@ var require_limitItems = __commonJS((exports) => {
10667
10669
  });
10668
10670
 
10669
10671
  // node_modules/ajv/dist/runtime/equal.js
10670
- var require_equal = __commonJS((exports) => {
10672
+ var require_equal = __commonJS(function(exports) {
10671
10673
  Object.defineProperty(exports, "__esModule", { value: true });
10672
10674
  var equal = require_fast_deep_equal();
10673
10675
  equal.code = 'require("ajv/dist/runtime/equal").default';
@@ -10675,7 +10677,7 @@ var require_equal = __commonJS((exports) => {
10675
10677
  });
10676
10678
 
10677
10679
  // node_modules/ajv/dist/vocabularies/validation/uniqueItems.js
10678
- var require_uniqueItems = __commonJS((exports) => {
10680
+ var require_uniqueItems = __commonJS(function(exports) {
10679
10681
  Object.defineProperty(exports, "__esModule", { value: true });
10680
10682
  var dataType_1 = require_dataType();
10681
10683
  var codegen_1 = require_codegen();
@@ -10739,7 +10741,7 @@ var require_uniqueItems = __commonJS((exports) => {
10739
10741
  });
10740
10742
 
10741
10743
  // node_modules/ajv/dist/vocabularies/validation/const.js
10742
- var require_const = __commonJS((exports) => {
10744
+ var require_const = __commonJS(function(exports) {
10743
10745
  Object.defineProperty(exports, "__esModule", { value: true });
10744
10746
  var codegen_1 = require_codegen();
10745
10747
  var util_1 = require_util();
@@ -10765,7 +10767,7 @@ var require_const = __commonJS((exports) => {
10765
10767
  });
10766
10768
 
10767
10769
  // node_modules/ajv/dist/vocabularies/validation/enum.js
10768
- var require_enum = __commonJS((exports) => {
10770
+ var require_enum = __commonJS(function(exports) {
10769
10771
  Object.defineProperty(exports, "__esModule", { value: true });
10770
10772
  var codegen_1 = require_codegen();
10771
10773
  var util_1 = require_util();
@@ -10811,7 +10813,7 @@ var require_enum = __commonJS((exports) => {
10811
10813
  });
10812
10814
 
10813
10815
  // node_modules/ajv/dist/vocabularies/validation/index.js
10814
- var require_validation = __commonJS((exports) => {
10816
+ var require_validation = __commonJS(function(exports) {
10815
10817
  Object.defineProperty(exports, "__esModule", { value: true });
10816
10818
  var limitNumber_1 = require_limitNumber();
10817
10819
  var multipleOf_1 = require_multipleOf();
@@ -10841,7 +10843,7 @@ var require_validation = __commonJS((exports) => {
10841
10843
  });
10842
10844
 
10843
10845
  // node_modules/ajv/dist/vocabularies/applicator/additionalItems.js
10844
- var require_additionalItems = __commonJS((exports) => {
10846
+ var require_additionalItems = __commonJS(function(exports) {
10845
10847
  Object.defineProperty(exports, "__esModule", { value: true });
10846
10848
  exports.validateAdditionalItems = undefined;
10847
10849
  var codegen_1 = require_codegen();
@@ -10891,7 +10893,7 @@ var require_additionalItems = __commonJS((exports) => {
10891
10893
  });
10892
10894
 
10893
10895
  // node_modules/ajv/dist/vocabularies/applicator/items.js
10894
- var require_items = __commonJS((exports) => {
10896
+ var require_items = __commonJS(function(exports) {
10895
10897
  Object.defineProperty(exports, "__esModule", { value: true });
10896
10898
  exports.validateTuple = undefined;
10897
10899
  var codegen_1 = require_codegen();
@@ -10945,7 +10947,7 @@ var require_items = __commonJS((exports) => {
10945
10947
  });
10946
10948
 
10947
10949
  // node_modules/ajv/dist/vocabularies/applicator/prefixItems.js
10948
- var require_prefixItems = __commonJS((exports) => {
10950
+ var require_prefixItems = __commonJS(function(exports) {
10949
10951
  Object.defineProperty(exports, "__esModule", { value: true });
10950
10952
  var items_1 = require_items();
10951
10953
  var def = {
@@ -10959,7 +10961,7 @@ var require_prefixItems = __commonJS((exports) => {
10959
10961
  });
10960
10962
 
10961
10963
  // node_modules/ajv/dist/vocabularies/applicator/items2020.js
10962
- var require_items2020 = __commonJS((exports) => {
10964
+ var require_items2020 = __commonJS(function(exports) {
10963
10965
  Object.defineProperty(exports, "__esModule", { value: true });
10964
10966
  var codegen_1 = require_codegen();
10965
10967
  var util_1 = require_util();
@@ -10991,7 +10993,7 @@ var require_items2020 = __commonJS((exports) => {
10991
10993
  });
10992
10994
 
10993
10995
  // node_modules/ajv/dist/vocabularies/applicator/contains.js
10994
- var require_contains = __commonJS((exports) => {
10996
+ var require_contains = __commonJS(function(exports) {
10995
10997
  Object.defineProperty(exports, "__esModule", { value: true });
10996
10998
  var codegen_1 = require_codegen();
10997
10999
  var util_1 = require_util();
@@ -11082,7 +11084,7 @@ var require_contains = __commonJS((exports) => {
11082
11084
  });
11083
11085
 
11084
11086
  // node_modules/ajv/dist/vocabularies/applicator/dependencies.js
11085
- var require_dependencies = __commonJS((exports) => {
11087
+ var require_dependencies = __commonJS(function(exports) {
11086
11088
  Object.defineProperty(exports, "__esModule", { value: true });
11087
11089
  exports.validateSchemaDeps = exports.validatePropertyDeps = exports.error = undefined;
11088
11090
  var codegen_1 = require_codegen();
@@ -11167,7 +11169,7 @@ var require_dependencies = __commonJS((exports) => {
11167
11169
  });
11168
11170
 
11169
11171
  // node_modules/ajv/dist/vocabularies/applicator/propertyNames.js
11170
- var require_propertyNames = __commonJS((exports) => {
11172
+ var require_propertyNames = __commonJS(function(exports) {
11171
11173
  Object.defineProperty(exports, "__esModule", { value: true });
11172
11174
  var codegen_1 = require_codegen();
11173
11175
  var util_1 = require_util();
@@ -11207,7 +11209,7 @@ var require_propertyNames = __commonJS((exports) => {
11207
11209
  });
11208
11210
 
11209
11211
  // node_modules/ajv/dist/vocabularies/applicator/additionalProperties.js
11210
- var require_additionalProperties = __commonJS((exports) => {
11212
+ var require_additionalProperties = __commonJS(function(exports) {
11211
11213
  Object.defineProperty(exports, "__esModule", { value: true });
11212
11214
  var code_1 = require_code2();
11213
11215
  var codegen_1 = require_codegen();
@@ -11310,7 +11312,7 @@ var require_additionalProperties = __commonJS((exports) => {
11310
11312
  });
11311
11313
 
11312
11314
  // node_modules/ajv/dist/vocabularies/applicator/properties.js
11313
- var require_properties = __commonJS((exports) => {
11315
+ var require_properties = __commonJS(function(exports) {
11314
11316
  Object.defineProperty(exports, "__esModule", { value: true });
11315
11317
  var validate_1 = require_validate();
11316
11318
  var code_1 = require_code2();
@@ -11365,7 +11367,7 @@ var require_properties = __commonJS((exports) => {
11365
11367
  });
11366
11368
 
11367
11369
  // node_modules/ajv/dist/vocabularies/applicator/patternProperties.js
11368
- var require_patternProperties = __commonJS((exports) => {
11370
+ var require_patternProperties = __commonJS(function(exports) {
11369
11371
  Object.defineProperty(exports, "__esModule", { value: true });
11370
11372
  var code_1 = require_code2();
11371
11373
  var codegen_1 = require_codegen();
@@ -11436,7 +11438,7 @@ var require_patternProperties = __commonJS((exports) => {
11436
11438
  });
11437
11439
 
11438
11440
  // node_modules/ajv/dist/vocabularies/applicator/not.js
11439
- var require_not = __commonJS((exports) => {
11441
+ var require_not = __commonJS(function(exports) {
11440
11442
  Object.defineProperty(exports, "__esModule", { value: true });
11441
11443
  var util_1 = require_util();
11442
11444
  var def = {
@@ -11464,7 +11466,7 @@ var require_not = __commonJS((exports) => {
11464
11466
  });
11465
11467
 
11466
11468
  // node_modules/ajv/dist/vocabularies/applicator/anyOf.js
11467
- var require_anyOf = __commonJS((exports) => {
11469
+ var require_anyOf = __commonJS(function(exports) {
11468
11470
  Object.defineProperty(exports, "__esModule", { value: true });
11469
11471
  var code_1 = require_code2();
11470
11472
  var def = {
@@ -11478,7 +11480,7 @@ var require_anyOf = __commonJS((exports) => {
11478
11480
  });
11479
11481
 
11480
11482
  // node_modules/ajv/dist/vocabularies/applicator/oneOf.js
11481
- var require_oneOf = __commonJS((exports) => {
11483
+ var require_oneOf = __commonJS(function(exports) {
11482
11484
  Object.defineProperty(exports, "__esModule", { value: true });
11483
11485
  var codegen_1 = require_codegen();
11484
11486
  var util_1 = require_util();
@@ -11533,7 +11535,7 @@ var require_oneOf = __commonJS((exports) => {
11533
11535
  });
11534
11536
 
11535
11537
  // node_modules/ajv/dist/vocabularies/applicator/allOf.js
11536
- var require_allOf = __commonJS((exports) => {
11538
+ var require_allOf = __commonJS(function(exports) {
11537
11539
  Object.defineProperty(exports, "__esModule", { value: true });
11538
11540
  var util_1 = require_util();
11539
11541
  var def = {
@@ -11557,7 +11559,7 @@ var require_allOf = __commonJS((exports) => {
11557
11559
  });
11558
11560
 
11559
11561
  // node_modules/ajv/dist/vocabularies/applicator/if.js
11560
- var require_if = __commonJS((exports) => {
11562
+ var require_if = __commonJS(function(exports) {
11561
11563
  Object.defineProperty(exports, "__esModule", { value: true });
11562
11564
  var codegen_1 = require_codegen();
11563
11565
  var util_1 = require_util();
@@ -11623,7 +11625,7 @@ var require_if = __commonJS((exports) => {
11623
11625
  });
11624
11626
 
11625
11627
  // node_modules/ajv/dist/vocabularies/applicator/thenElse.js
11626
- var require_thenElse = __commonJS((exports) => {
11628
+ var require_thenElse = __commonJS(function(exports) {
11627
11629
  Object.defineProperty(exports, "__esModule", { value: true });
11628
11630
  var util_1 = require_util();
11629
11631
  var def = {
@@ -11638,7 +11640,7 @@ var require_thenElse = __commonJS((exports) => {
11638
11640
  });
11639
11641
 
11640
11642
  // node_modules/ajv/dist/vocabularies/applicator/index.js
11641
- var require_applicator = __commonJS((exports) => {
11643
+ var require_applicator = __commonJS(function(exports) {
11642
11644
  Object.defineProperty(exports, "__esModule", { value: true });
11643
11645
  var additionalItems_1 = require_additionalItems();
11644
11646
  var prefixItems_1 = require_prefixItems();
@@ -11681,7 +11683,7 @@ var require_applicator = __commonJS((exports) => {
11681
11683
  });
11682
11684
 
11683
11685
  // node_modules/ajv/dist/vocabularies/format/format.js
11684
- var require_format = __commonJS((exports) => {
11686
+ var require_format = __commonJS(function(exports) {
11685
11687
  Object.defineProperty(exports, "__esModule", { value: true });
11686
11688
  var codegen_1 = require_codegen();
11687
11689
  var error = {
@@ -11768,7 +11770,7 @@ var require_format = __commonJS((exports) => {
11768
11770
  });
11769
11771
 
11770
11772
  // node_modules/ajv/dist/vocabularies/format/index.js
11771
- var require_format2 = __commonJS((exports) => {
11773
+ var require_format2 = __commonJS(function(exports) {
11772
11774
  Object.defineProperty(exports, "__esModule", { value: true });
11773
11775
  var format_1 = require_format();
11774
11776
  var format = [format_1.default];
@@ -11776,7 +11778,7 @@ var require_format2 = __commonJS((exports) => {
11776
11778
  });
11777
11779
 
11778
11780
  // node_modules/ajv/dist/vocabularies/metadata.js
11779
- var require_metadata = __commonJS((exports) => {
11781
+ var require_metadata = __commonJS(function(exports) {
11780
11782
  Object.defineProperty(exports, "__esModule", { value: true });
11781
11783
  exports.contentVocabulary = exports.metadataVocabulary = undefined;
11782
11784
  exports.metadataVocabulary = [
@@ -11796,7 +11798,7 @@ var require_metadata = __commonJS((exports) => {
11796
11798
  });
11797
11799
 
11798
11800
  // node_modules/ajv/dist/vocabularies/draft7.js
11799
- var require_draft7 = __commonJS((exports) => {
11801
+ var require_draft7 = __commonJS(function(exports) {
11800
11802
  Object.defineProperty(exports, "__esModule", { value: true });
11801
11803
  var core_1 = require_core2();
11802
11804
  var validation_1 = require_validation();
@@ -11815,7 +11817,7 @@ var require_draft7 = __commonJS((exports) => {
11815
11817
  });
11816
11818
 
11817
11819
  // node_modules/ajv/dist/vocabularies/discriminator/types.js
11818
- var require_types = __commonJS((exports) => {
11820
+ var require_types = __commonJS(function(exports) {
11819
11821
  Object.defineProperty(exports, "__esModule", { value: true });
11820
11822
  exports.DiscrError = undefined;
11821
11823
  var DiscrError;
@@ -11826,7 +11828,7 @@ var require_types = __commonJS((exports) => {
11826
11828
  });
11827
11829
 
11828
11830
  // node_modules/ajv/dist/vocabularies/discriminator/index.js
11829
- var require_discriminator = __commonJS((exports) => {
11831
+ var require_discriminator = __commonJS(function(exports) {
11830
11832
  Object.defineProperty(exports, "__esModule", { value: true });
11831
11833
  var codegen_1 = require_codegen();
11832
11834
  var types_1 = require_types();
@@ -11928,7 +11930,7 @@ var require_discriminator = __commonJS((exports) => {
11928
11930
  });
11929
11931
 
11930
11932
  // node_modules/ajv/dist/refs/json-schema-draft-07.json
11931
- var require_json_schema_draft_07 = __commonJS((exports, module) => {
11933
+ var require_json_schema_draft_07 = __commonJS(function(exports, module) {
11932
11934
  module.exports = {
11933
11935
  $schema: "http://json-schema.org/draft-07/schema#",
11934
11936
  $id: "http://json-schema.org/draft-07/schema#",
@@ -12083,7 +12085,7 @@ var require_json_schema_draft_07 = __commonJS((exports, module) => {
12083
12085
  });
12084
12086
 
12085
12087
  // node_modules/ajv/dist/ajv.js
12086
- var require_ajv = __commonJS((exports, module) => {
12088
+ var require_ajv = __commonJS(function(exports, module) {
12087
12089
  Object.defineProperty(exports, "__esModule", { value: true });
12088
12090
  exports.MissingRefError = exports.ValidationError = exports.CodeGen = exports.Name = exports.nil = exports.stringify = exports.str = exports._ = exports.KeywordCxt = exports.Ajv = undefined;
12089
12091
  var core_1 = require_core();
@@ -12593,8 +12595,8 @@ var init_schema = __esm(() => {
12593
12595
  // src/doctor.ts
12594
12596
  var exports_doctor = {};
12595
12597
  __export(exports_doctor, {
12596
- runDoctor: () => runDoctor,
12597
- printDoctorReport: () => printDoctorReport
12598
+ printDoctorReport: () => printDoctorReport,
12599
+ runDoctor: () => runDoctor
12598
12600
  });
12599
12601
  import { existsSync as existsSync15, statSync as statSync6, readFileSync as readFileSync14 } from "node:fs";
12600
12602
  import { join as join16 } from "node:path";
@@ -12842,6 +12844,7 @@ var init_snapshot = __esm(() => {
12842
12844
  // src/ui.ts
12843
12845
  var exports_ui = {};
12844
12846
  __export(exports_ui, {
12847
+ exportStandaloneHtml: () => exportStandaloneHtml,
12845
12848
  startUiServer: () => startUiServer
12846
12849
  });
12847
12850
  import { createServer } from "node:http";
@@ -12917,6 +12920,13 @@ function startUiServer(opts) {
12917
12920
  }
12918
12921
  return;
12919
12922
  }
12923
+ if (pathname === "/api/export-html" && req.method === "GET") {
12924
+ const html = exportStandaloneHtml(opts.store);
12925
+ res.setHeader("Content-Disposition", 'attachment; filename="musememory-graph.html"');
12926
+ res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
12927
+ res.end(html);
12928
+ return;
12929
+ }
12920
12930
  if (pathname === "/" || pathname === "/index.html") {
12921
12931
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
12922
12932
  res.end(EMBEDDED_HTML);
@@ -12957,6 +12967,12 @@ function parseJsonBody(req) {
12957
12967
  req.on("error", reject2);
12958
12968
  });
12959
12969
  }
12970
+ function exportStandaloneHtml(store) {
12971
+ const memories = list(store);
12972
+ const script = `<script>window.STANDALONE_DATA = ${JSON.stringify(memories)};</script>`;
12973
+ return EMBEDDED_HTML.replace("</head>", `${script}
12974
+ </head>`);
12975
+ }
12960
12976
  var EMBEDDED_HTML = `<!DOCTYPE html>
12961
12977
  <html lang="en">
12962
12978
  <head>
@@ -13091,8 +13107,12 @@ var EMBEDDED_HTML = `<!DOCTYPE html>
13091
13107
 
13092
13108
  async function loadData() {
13093
13109
  try {
13094
- const res = await fetch('/api/memories');
13095
- allMemories = await res.json();
13110
+ if (window.STANDALONE_DATA) {
13111
+ allMemories = window.STANDALONE_DATA;
13112
+ } else {
13113
+ const res = await fetch('/api/memories');
13114
+ allMemories = await res.json();
13115
+ }
13096
13116
  renderList();
13097
13117
  initGraph();
13098
13118
  buildClusterFilters();
@@ -13263,20 +13283,96 @@ var EMBEDDED_HTML = `<!DOCTYPE html>
13263
13283
  simAlpha = 1; // re-energize layout after data changes
13264
13284
  }
13265
13285
 
13286
+ function buildQuadtree(nodes) {
13287
+ let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
13288
+ for (const n of nodes) {
13289
+ if (n.x < minX) minX = n.x;
13290
+ if (n.x > maxX) maxX = n.x;
13291
+ if (n.y < minY) minY = n.y;
13292
+ if (n.y > maxY) maxY = n.y;
13293
+ }
13294
+ const size = Math.max(maxX - minX, maxY - minY, 100);
13295
+ const cx = (minX + maxX) / 2;
13296
+ const cy = (minY + maxY) / 2;
13297
+
13298
+ function createQuad(x, y, s) {
13299
+ return { x, y, size: s, mass: 0, cx: 0, cy: 0, cz: 0, body: null, children: null };
13300
+ }
13301
+ const root = createQuad(cx, cy, size);
13302
+
13303
+ function insert(tree, body) {
13304
+ if (tree.mass === 0) {
13305
+ tree.body = body;
13306
+ tree.cx = body.x; tree.cy = body.y; tree.cz = body.z;
13307
+ tree.mass = 1;
13308
+ return;
13309
+ }
13310
+ if (!tree.children) {
13311
+ const b2 = tree.body;
13312
+ tree.body = null;
13313
+ const hs = tree.size / 2;
13314
+ const qs = tree.size / 4;
13315
+ tree.children = [
13316
+ createQuad(tree.x - qs, tree.y - qs, hs),
13317
+ createQuad(tree.x + qs, tree.y - qs, hs),
13318
+ createQuad(tree.x - qs, tree.y + qs, hs),
13319
+ createQuad(tree.x + qs, tree.y + qs, hs)
13320
+ ];
13321
+ if (b2) insertChild(tree, b2);
13322
+ }
13323
+ tree.cx = (tree.cx * tree.mass + body.x) / (tree.mass + 1);
13324
+ tree.cy = (tree.cy * tree.mass + body.y) / (tree.mass + 1);
13325
+ tree.cz = (tree.cz * tree.mass + body.z) / (tree.mass + 1);
13326
+ tree.mass++;
13327
+ insertChild(tree, body);
13328
+ }
13329
+
13330
+ function insertChild(tree, body) {
13331
+ const idx = (body.x >= tree.x ? 1 : 0) + (body.y >= tree.y ? 2 : 0);
13332
+ insert(tree.children[idx], body);
13333
+ }
13334
+
13335
+ for (const n of nodes) insert(root, n);
13336
+ return root;
13337
+ }
13338
+
13339
+ function applyRepulsionBarnesHut(nodes, tree, theta, alpha) {
13340
+ for (const a of nodes) computeForce(a, tree);
13341
+
13342
+ function computeForce(a, node) {
13343
+ if (node.mass === 0 || node.body === a) return;
13344
+ let dx = a.x - node.cx, dy = a.y - node.cy, dz = a.z - node.cz;
13345
+ let dist2 = dx * dx + dy * dy + dz * dz + 0.01;
13346
+ let dist = Math.sqrt(dist2);
13347
+ if (node.children && (node.size / dist) > theta) {
13348
+ for (const child of node.children) computeForce(a, child);
13349
+ } else {
13350
+ const force = (2400 * alpha * node.mass) / dist2;
13351
+ dx /= dist; dy /= dist; dz /= dist;
13352
+ a.x += dx * force; a.y += dy * force; a.z += dz * force;
13353
+ }
13354
+ }
13355
+ }
13356
+
13266
13357
  function simulateStep() {
13267
13358
  if (nodes3d.length === 0) return;
13268
13359
  const alpha = simAlpha;
13269
- // Pairwise repulsion (O(n^2) — fine at memory-store scale)
13270
- for (let i = 0; i < nodes3d.length; i++) {
13271
- for (let j = i + 1; j < nodes3d.length; j++) {
13272
- const a = nodes3d[i], b = nodes3d[j];
13273
- let dx = a.x - b.x, dy = a.y - b.y, dz = a.z - b.z;
13274
- let dist2 = dx * dx + dy * dy + dz * dz + 0.01;
13275
- const force = (2400 * alpha) / dist2;
13276
- const dist = Math.sqrt(dist2);
13277
- dx /= dist; dy /= dist; dz /= dist;
13278
- a.x += dx * force; a.y += dy * force; a.z += dz * force;
13279
- b.x -= dx * force; b.y -= dy * force; b.z -= dz * force;
13360
+ if (nodes3d.length > 50) {
13361
+ const qtree = buildQuadtree(nodes3d);
13362
+ applyRepulsionBarnesHut(nodes3d, qtree, 0.6, alpha);
13363
+ } else {
13364
+ // Pairwise repulsion (O(n^2) for small graphs)
13365
+ for (let i = 0; i < nodes3d.length; i++) {
13366
+ for (let j = i + 1; j < nodes3d.length; j++) {
13367
+ const a = nodes3d[i], b = nodes3d[j];
13368
+ let dx = a.x - b.x, dy = a.y - b.y, dz = a.z - b.z;
13369
+ let dist2 = dx * dx + dy * dy + dz * dz + 0.01;
13370
+ const force = (2400 * alpha) / dist2;
13371
+ const dist = Math.sqrt(dist2);
13372
+ dx /= dist; dy /= dist; dz /= dist;
13373
+ a.x += dx * force; a.y += dy * force; a.z += dz * force;
13374
+ b.x -= dx * force; b.y -= dy * force; b.z -= dz * force;
13375
+ }
13280
13376
  }
13281
13377
  }
13282
13378
  // Springs along graph edges
@@ -13566,69 +13662,69 @@ var init_core2 = __esm(() => {
13566
13662
  // node_modules/zod/v4/core/util.js
13567
13663
  var exports_util = {};
13568
13664
  __export(exports_util, {
13569
- unwrapMessage: () => unwrapMessage,
13570
- uint8ArrayToHex: () => uint8ArrayToHex,
13571
- uint8ArrayToBase64url: () => uint8ArrayToBase64url,
13572
- uint8ArrayToBase64: () => uint8ArrayToBase64,
13573
- stringifyPrimitive: () => stringifyPrimitive,
13574
- slugify: () => slugify,
13575
- shallowClone: () => shallowClone,
13576
- safeExtend: () => safeExtend,
13577
- required: () => required,
13578
- randomString: () => randomString,
13579
- propertyKeyTypes: () => propertyKeyTypes,
13580
- promiseAllObject: () => promiseAllObject,
13581
- primitiveTypes: () => primitiveTypes,
13582
- prefixIssues: () => prefixIssues,
13583
- pick: () => pick,
13584
- partial: () => partial,
13585
- parsedType: () => parsedType,
13586
- optionalKeys: () => optionalKeys,
13587
- omit: () => omit,
13588
- objectClone: () => objectClone,
13589
- numKeys: () => numKeys,
13590
- nullish: () => nullish,
13591
- normalizeParams: () => normalizeParams,
13592
- mergeDefs: () => mergeDefs,
13593
- merge: () => merge2,
13594
- jsonStringifyReplacer: () => jsonStringifyReplacer,
13595
- joinValues: () => joinValues,
13596
- issue: () => issue,
13597
- isPlainObject: () => isPlainObject,
13598
- isObject: () => isObject,
13599
- hexToUint8Array: () => hexToUint8Array,
13600
- getSizableOrigin: () => getSizableOrigin,
13601
- getParsedType: () => getParsedType,
13602
- getLengthableOrigin: () => getLengthableOrigin,
13603
- getEnumValues: () => getEnumValues,
13604
- getElementAtPath: () => getElementAtPath,
13605
- floatSafeRemainder: () => floatSafeRemainder,
13606
- finalizeIssue: () => finalizeIssue,
13607
- extend: () => extend,
13608
- explicitlyAborted: () => explicitlyAborted,
13609
- escapeRegex: () => escapeRegex,
13610
- esc: () => esc,
13611
- defineLazy: () => defineLazy,
13612
- createTransparentProxy: () => createTransparentProxy,
13613
- cloneDef: () => cloneDef,
13614
- clone: () => clone,
13615
- cleanRegex: () => cleanRegex,
13616
- cleanEnum: () => cleanEnum,
13617
- captureStackTrace: () => captureStackTrace,
13618
- cached: () => cached,
13619
- base64urlToUint8Array: () => base64urlToUint8Array,
13620
- base64ToUint8Array: () => base64ToUint8Array,
13621
- assignProp: () => assignProp,
13622
- assertNotEqual: () => assertNotEqual,
13623
- assertNever: () => assertNever,
13624
- assertIs: () => assertIs,
13625
- assertEqual: () => assertEqual,
13626
- assert: () => assert,
13627
- allowsEval: () => allowsEval,
13628
- aborted: () => aborted,
13629
- NUMBER_FORMAT_RANGES: () => NUMBER_FORMAT_RANGES,
13665
+ BIGINT_FORMAT_RANGES: () => BIGINT_FORMAT_RANGES,
13630
13666
  Class: () => Class,
13631
- BIGINT_FORMAT_RANGES: () => BIGINT_FORMAT_RANGES
13667
+ NUMBER_FORMAT_RANGES: () => NUMBER_FORMAT_RANGES,
13668
+ aborted: () => aborted,
13669
+ allowsEval: () => allowsEval,
13670
+ assert: () => assert,
13671
+ assertEqual: () => assertEqual,
13672
+ assertIs: () => assertIs,
13673
+ assertNever: () => assertNever,
13674
+ assertNotEqual: () => assertNotEqual,
13675
+ assignProp: () => assignProp,
13676
+ base64ToUint8Array: () => base64ToUint8Array,
13677
+ base64urlToUint8Array: () => base64urlToUint8Array,
13678
+ cached: () => cached,
13679
+ captureStackTrace: () => captureStackTrace,
13680
+ cleanEnum: () => cleanEnum,
13681
+ cleanRegex: () => cleanRegex,
13682
+ clone: () => clone,
13683
+ cloneDef: () => cloneDef,
13684
+ createTransparentProxy: () => createTransparentProxy,
13685
+ defineLazy: () => defineLazy,
13686
+ esc: () => esc,
13687
+ escapeRegex: () => escapeRegex,
13688
+ explicitlyAborted: () => explicitlyAborted,
13689
+ extend: () => extend,
13690
+ finalizeIssue: () => finalizeIssue,
13691
+ floatSafeRemainder: () => floatSafeRemainder,
13692
+ getElementAtPath: () => getElementAtPath,
13693
+ getEnumValues: () => getEnumValues,
13694
+ getLengthableOrigin: () => getLengthableOrigin,
13695
+ getParsedType: () => getParsedType,
13696
+ getSizableOrigin: () => getSizableOrigin,
13697
+ hexToUint8Array: () => hexToUint8Array,
13698
+ isObject: () => isObject,
13699
+ isPlainObject: () => isPlainObject,
13700
+ issue: () => issue,
13701
+ joinValues: () => joinValues,
13702
+ jsonStringifyReplacer: () => jsonStringifyReplacer,
13703
+ merge: () => merge2,
13704
+ mergeDefs: () => mergeDefs,
13705
+ normalizeParams: () => normalizeParams,
13706
+ nullish: () => nullish,
13707
+ numKeys: () => numKeys,
13708
+ objectClone: () => objectClone,
13709
+ omit: () => omit,
13710
+ optionalKeys: () => optionalKeys,
13711
+ parsedType: () => parsedType,
13712
+ partial: () => partial,
13713
+ pick: () => pick,
13714
+ prefixIssues: () => prefixIssues,
13715
+ primitiveTypes: () => primitiveTypes,
13716
+ promiseAllObject: () => promiseAllObject,
13717
+ propertyKeyTypes: () => propertyKeyTypes,
13718
+ randomString: () => randomString,
13719
+ required: () => required,
13720
+ safeExtend: () => safeExtend,
13721
+ shallowClone: () => shallowClone,
13722
+ slugify: () => slugify,
13723
+ stringifyPrimitive: () => stringifyPrimitive,
13724
+ uint8ArrayToBase64: () => uint8ArrayToBase64,
13725
+ uint8ArrayToBase64url: () => uint8ArrayToBase64url,
13726
+ uint8ArrayToHex: () => uint8ArrayToHex,
13727
+ unwrapMessage: () => unwrapMessage
13632
13728
  });
13633
13729
  function assertEqual(val) {
13634
13730
  return val;
@@ -17820,14 +17916,14 @@ var init_checks3 = __esm(() => {
17820
17916
  // node_modules/zod/v4/classic/iso.js
17821
17917
  var exports_iso2 = {};
17822
17918
  __export(exports_iso2, {
17823
- time: () => time2,
17824
- duration: () => duration2,
17825
- datetime: () => datetime2,
17826
- date: () => date2,
17827
- ZodISOTime: () => ZodISOTime,
17828
- ZodISODuration: () => ZodISODuration,
17919
+ ZodISODate: () => ZodISODate,
17829
17920
  ZodISODateTime: () => ZodISODateTime,
17830
- ZodISODate: () => ZodISODate
17921
+ ZodISODuration: () => ZodISODuration,
17922
+ ZodISOTime: () => ZodISOTime,
17923
+ date: () => date2,
17924
+ datetime: () => datetime2,
17925
+ duration: () => duration2,
17926
+ time: () => time2
17831
17927
  });
17832
17928
  function datetime2(params) {
17833
17929
  return _isoDateTime(ZodISODateTime, params);
@@ -20724,7 +20820,7 @@ var init_protocol = __esm(() => {
20724
20820
  });
20725
20821
 
20726
20822
  // node_modules/ajv-formats/dist/formats.js
20727
- var require_formats = __commonJS((exports) => {
20823
+ var require_formats = __commonJS(function(exports) {
20728
20824
  Object.defineProperty(exports, "__esModule", { value: true });
20729
20825
  exports.formatNames = exports.fastFormats = exports.fullFormats = undefined;
20730
20826
  function fmtDef(validate, compare) {
@@ -20901,7 +20997,7 @@ var require_formats = __commonJS((exports) => {
20901
20997
  });
20902
20998
 
20903
20999
  // node_modules/ajv-formats/dist/limit.js
20904
- var require_limit = __commonJS((exports) => {
21000
+ var require_limit = __commonJS(function(exports) {
20905
21001
  Object.defineProperty(exports, "__esModule", { value: true });
20906
21002
  exports.formatLimitDefinition = undefined;
20907
21003
  var ajv_1 = require_ajv();
@@ -20970,7 +21066,7 @@ var require_limit = __commonJS((exports) => {
20970
21066
  });
20971
21067
 
20972
21068
  // node_modules/ajv-formats/dist/index.js
20973
- var require_dist = __commonJS((exports, module) => {
21069
+ var require_dist = __commonJS(function(exports, module) {
20974
21070
  Object.defineProperty(exports, "__esModule", { value: true });
20975
21071
  var formats_1 = require_formats();
20976
21072
  var limit_1 = require_limit();
@@ -22488,15 +22584,15 @@ var init_verify = __esm(() => {
22488
22584
  // src/vector.ts
22489
22585
  var exports_vector = {};
22490
22586
  __export(exports_vector, {
22491
- termFrequencies: () => termFrequencies,
22492
- saveIndex: () => saveIndex,
22493
- rebuildIndex: () => rebuildIndex,
22494
- loadIndex: () => loadIndex,
22495
- indexFilePath: () => indexFilePath,
22496
- hybridSearch: () => hybridSearch,
22497
- embed: () => embed,
22587
+ bm25Score: () => bm25Score,
22498
22588
  cosineSimilarity: () => cosineSimilarity2,
22499
- bm25Score: () => bm25Score
22589
+ embed: () => embed,
22590
+ hybridSearch: () => hybridSearch,
22591
+ indexFilePath: () => indexFilePath,
22592
+ loadIndex: () => loadIndex,
22593
+ rebuildIndex: () => rebuildIndex,
22594
+ saveIndex: () => saveIndex,
22595
+ termFrequencies: () => termFrequencies
22500
22596
  });
22501
22597
  import { existsSync as existsSync19, readFileSync as readFileSync17, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8 } from "node:fs";
22502
22598
  import { join as join18 } from "node:path";
@@ -22666,80 +22762,1923 @@ var init_sessions = __esm(() => {
22666
22762
  init_store();
22667
22763
  });
22668
22764
 
22669
- // src/mcp.ts
22670
- var exports_mcp = {};
22671
- __export(exports_mcp, {
22672
- runMcpServer: () => runMcpServer
22673
- });
22674
- async function runMcpServer() {
22675
- const targetDir = process.env.MUSE_MEMORY_PROJECT_DIR || process.env.PROJECT_ROOT || process.cwd();
22676
- const { root, memoryDir } = findOrCreateProjectRoot(targetDir);
22677
- const store = openStore(memoryDir);
22678
- const server = new Server({ name: "musememory", version: "1.2.0" }, { capabilities: { tools: {} } });
22679
- server.setRequestHandler(ListToolsRequestSchema, async () => ({
22680
- tools: [
22681
- {
22682
- name: "memory_read",
22683
- description: "Read a full memory entry by id",
22684
- inputSchema: {
22685
- type: "object",
22686
- properties: { id: { type: "string" } },
22687
- required: ["id"]
22688
- }
22689
- },
22690
- {
22691
- name: "get_context",
22692
- description: "Ranked active context entries for prompt injection (with optional token budget)",
22693
- inputSchema: {
22694
- type: "object",
22695
- properties: {
22696
- query: { type: "string" },
22697
- project: { type: "string" },
22698
- limit: { type: "number" },
22699
- token_budget: { type: "number", description: "Maximum token budget to consume for retrieved context" },
22700
- type: { type: "string" },
22701
- status: { type: "string" },
22702
- verified: { type: "boolean" },
22703
- depth: { type: "string", enum: ["L1", "L2", "L3"], description: "Progressive disclosure tier: L1 = id+title lines, L2 = title+content+tags (default), L3 = full raw entry" }
22704
- }
22705
- }
22706
- },
22707
- {
22708
- name: "search",
22709
- description: "Ranked search over memory entries",
22710
- inputSchema: {
22711
- type: "object",
22712
- properties: {
22713
- query: { type: "string" },
22714
- limit: { type: "number" },
22715
- token_budget: { type: "number", description: "Maximum token budget to consume" },
22716
- include_superseded: { type: "boolean" },
22717
- hybrid: { type: "boolean", description: "Use the offline vector+BM25 index (requires 'memory reindex'); falls back to live scoring when absent" },
22718
- type: { type: "string" },
22719
- status: { type: "string" },
22720
- verified: { type: "boolean" }
22721
- },
22722
- required: ["query"]
22723
- }
22724
- },
22725
- {
22726
- name: "memory_capture",
22727
- description: "Create a new memory entry with inline secret scan (refuses probable secrets)",
22728
- inputSchema: {
22729
- type: "object",
22730
- properties: {
22731
- content: { type: "string" },
22732
- project: { type: "string" },
22733
- title: { type: "string" },
22734
- tags: { type: "array", items: { type: "string" } },
22735
- type: { type: "string" },
22736
- confirmed: { type: "boolean" }
22737
- },
22738
- required: ["content", "project"]
22739
- }
22740
- },
22741
- {
22742
- name: "memory_harvest",
22765
+ // src/retrieval/tree-index.ts
22766
+ import { existsSync as existsSync20, readFileSync as readFileSync18, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9, rmSync } from "node:fs";
22767
+ import { join as join19 } from "node:path";
22768
+ function tokenize2(text) {
22769
+ if (!text || typeof text !== "string")
22770
+ return [];
22771
+ return text.toLowerCase().match(/[a-z0-9]+/g) ?? [];
22772
+ }
22773
+ function indexDir(memoryDir) {
22774
+ return join19(memoryDir, "tree-index");
22775
+ }
22776
+ function partitionDir(idxDir, project, type2) {
22777
+ return join19(idxDir, project, type2);
22778
+ }
22779
+ function shardFilePath(pDir, shardId) {
22780
+ return join19(pDir, `${shardId}.json`);
22781
+ }
22782
+ function partitionIndexFilePath(pDir) {
22783
+ return join19(pDir, "index.json");
22784
+ }
22785
+ function globalIndexFilePath(idxDir) {
22786
+ return join19(idxDir, "index.json");
22787
+ }
22788
+ function nowIso2() {
22789
+ return new Date().toISOString();
22790
+ }
22791
+ function formatTimeBucket(date4) {
22792
+ const year = date4.getFullYear();
22793
+ const month = String(date4.getMonth() + 1).padStart(2, "0");
22794
+ return `${year}-${month}`;
22795
+ }
22796
+ function parseTimeBucket(bucket) {
22797
+ const parts = bucket.split("-").map(Number);
22798
+ const year = parts[0] || 2026;
22799
+ const month = parts[1] || 1;
22800
+ const start = new Date(year, month - 1, 1);
22801
+ const end = new Date(year, month, 0, 23, 59, 59);
22802
+ return { start, end };
22803
+ }
22804
+ function makeShardId(project, type2, date4) {
22805
+ const bucket = formatTimeBucket(date4);
22806
+ return `${project}_${type2}_${bucket}`;
22807
+ }
22808
+ function cosineSimilarity3(a, b) {
22809
+ let dot = 0;
22810
+ let na = 0;
22811
+ let nb = 0;
22812
+ for (const v of a.values())
22813
+ na += v * v;
22814
+ for (const [t, v] of b) {
22815
+ nb += v * v;
22816
+ const av = a.get(t);
22817
+ if (av)
22818
+ dot += av * v;
22819
+ }
22820
+ return na > 0 && nb > 0 ? dot / Math.sqrt(na * nb) : 0;
22821
+ }
22822
+ function tokenBag2(text, weight = 1) {
22823
+ const bag = new Map;
22824
+ for (const t of tokenize2(text)) {
22825
+ bag.set(t, (bag.get(t) ?? 0) + weight);
22826
+ }
22827
+ return bag;
22828
+ }
22829
+ function mergeBag2(target, add) {
22830
+ for (const [t, v] of add)
22831
+ target.set(t, (target.get(t) ?? 0) + v);
22832
+ }
22833
+ function dominantTopicTokens2(titles) {
22834
+ const stopwords = new Set([
22835
+ "the",
22836
+ "a",
22837
+ "an",
22838
+ "and",
22839
+ "or",
22840
+ "to",
22841
+ "of",
22842
+ "in",
22843
+ "for",
22844
+ "with",
22845
+ "on",
22846
+ "is",
22847
+ "use",
22848
+ "uses",
22849
+ "when",
22850
+ "always",
22851
+ "never",
22852
+ "via",
22853
+ "after",
22854
+ "before",
22855
+ "not",
22856
+ "this",
22857
+ "about"
22858
+ ]);
22859
+ const freq = new Map;
22860
+ for (const title of titles) {
22861
+ for (const t of tokenize2(title)) {
22862
+ if (stopwords.has(t))
22863
+ continue;
22864
+ freq.set(t, (freq.get(t) ?? 0) + 1);
22865
+ }
22866
+ }
22867
+ return [...freq.entries()].sort((a, b) => b[1] - a[1]).slice(0, 2).map(([t]) => t);
22868
+ }
22869
+ function entryTokens2(e) {
22870
+ const bag = tokenBag2(e.title, 2);
22871
+ mergeBag2(bag, tokenBag2(e.content, 1));
22872
+ return bag;
22873
+ }
22874
+ function clusterByTokenOverlap2(items, tokensFor, threshold = 0.5) {
22875
+ const clusters = [];
22876
+ for (const item of items) {
22877
+ const bag = tokensFor(item);
22878
+ let best = null;
22879
+ let bestScore = 0;
22880
+ for (const c of clusters) {
22881
+ const score = cosineSimilarity3(bag, c.bag);
22882
+ if (score > bestScore) {
22883
+ bestScore = score;
22884
+ best = c;
22885
+ }
22886
+ }
22887
+ if (best && bestScore >= threshold) {
22888
+ best.items.push(item);
22889
+ mergeBag2(best.bag, bag);
22890
+ } else {
22891
+ clusters.push({ bag: new Map(bag), items: [item] });
22892
+ }
22893
+ }
22894
+ return clusters.map((c) => c.items);
22895
+ }
22896
+ function buildLeafCluster(cluster) {
22897
+ const topic = dominantTopicTokens2(cluster.map((e) => e.title));
22898
+ const rootId = `node_${Date.now()}_${Math.random().toString(36).slice(2, 7)}_${topic.join("-") || "cluster"}`;
22899
+ return {
22900
+ id: rootId,
22901
+ title: topic.length > 0 ? topic.join(" ") : cluster[0]?.type ?? "cluster",
22902
+ summary: cluster.map((e) => e.content.replace(/\s+/g, " ").slice(0, 200)).join(" | "),
22903
+ type: cluster[0]?.type ?? "discovery",
22904
+ status: "confirmed",
22905
+ project: cluster[0]?.project ?? "default",
22906
+ children: [],
22907
+ memoryIds: cluster.map((e) => e.id),
22908
+ metadata: {
22909
+ createdAt: cluster[0]?.created_at ?? nowIso2(),
22910
+ updatedAt: cluster[0]?.updated_at ?? nowIso2(),
22911
+ salience: cluster.reduce((max, e) => Math.max(max, e.salience ?? 0), 0),
22912
+ verification: "user-confirmed",
22913
+ tags: [...new Set(cluster.flatMap((e) => e.tags ?? []))]
22914
+ },
22915
+ content: cluster.map((e) => e.content).join(`
22916
+ ---
22917
+ `)
22918
+ };
22919
+ }
22920
+ function buildClusterHierarchy(cluster, config2, depth = 0) {
22921
+ if (depth >= MAX_RECURSION_DEPTH || cluster.length <= config2.minClusterSize * 2) {
22922
+ return buildLeafCluster(cluster);
22923
+ }
22924
+ const topic = dominantTopicTokens2(cluster.map((e) => e.title));
22925
+ const rootId = `node_${Date.now()}_${Math.random().toString(36).slice(2, 7)}_${topic.join("-") || "cluster"}`;
22926
+ const root = {
22927
+ id: rootId,
22928
+ title: topic.length > 0 ? topic.join(" ") : cluster[0]?.type ?? "cluster",
22929
+ summary: cluster.map((e) => e.content.replace(/\s+/g, " ").slice(0, 200)).join(" | "),
22930
+ type: cluster[0]?.type ?? "discovery",
22931
+ status: "confirmed",
22932
+ project: cluster[0]?.project ?? "default",
22933
+ children: [],
22934
+ memoryIds: [],
22935
+ metadata: {
22936
+ createdAt: cluster[0]?.created_at ?? nowIso2(),
22937
+ updatedAt: cluster[0]?.updated_at ?? nowIso2(),
22938
+ salience: cluster.reduce((max, e) => Math.max(max, e.salience ?? 0), 0),
22939
+ verification: "user-confirmed",
22940
+ tags: [...new Set(cluster.flatMap((e) => e.tags ?? []))]
22941
+ }
22942
+ };
22943
+ const subClusters = clusterByTokenOverlap2(cluster, entryTokens2, config2.clusteringThreshold);
22944
+ const validSubClusters = subClusters.filter((sc) => sc.length < cluster.length && sc.length >= config2.minClusterSize);
22945
+ if (validSubClusters.length === 0) {
22946
+ return buildLeafCluster(cluster);
22947
+ }
22948
+ for (const subCluster of validSubClusters) {
22949
+ root.children.push(buildClusterHierarchy(subCluster, config2, depth + 1));
22950
+ }
22951
+ const remaining = subClusters.filter((sc) => sc.length < config2.minClusterSize).flatMap((sc) => sc.map((e) => e.id));
22952
+ root.memoryIds.push(...remaining);
22953
+ root.content = root.children.map((c) => c.summary).join(`
22954
+ ---
22955
+ `);
22956
+ return root;
22957
+ }
22958
+ function countNodes(node) {
22959
+ return 1 + node.children.reduce((sum, c) => sum + countNodes(c), 0);
22960
+ }
22961
+ function buildTreeIndex(store, memoryDir, config2 = {}) {
22962
+ const cfg = { ...DEFAULT_CONFIG, ...config2 };
22963
+ const allMemories = list(store).filter((e) => e.status === "confirmed");
22964
+ mkdirSync9(indexDir(memoryDir), { recursive: true });
22965
+ if (allMemories.length === 0) {
22966
+ const emptyIndex = {
22967
+ version: 1,
22968
+ partitions: {},
22969
+ totalNodes: 0,
22970
+ totalMemories: 0,
22971
+ builtAt: nowIso2()
22972
+ };
22973
+ writeFileSync9(globalIndexFilePath(indexDir(memoryDir)), JSON.stringify(emptyIndex, null, 2), "utf8");
22974
+ return emptyIndex;
22975
+ }
22976
+ const groups = new Map;
22977
+ for (const e of allMemories) {
22978
+ const key = `${e.project}|${e.type ?? "unknown"}`;
22979
+ const group = groups.get(key);
22980
+ if (group)
22981
+ group.push(e);
22982
+ else
22983
+ groups.set(key, [e]);
22984
+ }
22985
+ const partitions = {};
22986
+ let totalIndexNodes = 0;
22987
+ let totalIndexMemories = 0;
22988
+ for (const [key, memories] of groups) {
22989
+ const [project, type2] = key.split("|");
22990
+ const pDir = partitionDir(indexDir(memoryDir), project, type2);
22991
+ mkdirSync9(pDir, { recursive: true });
22992
+ const maxShardSize = cfg.shardThreshold || 1e4;
22993
+ const finalShards = [];
22994
+ const memoryChunks = [];
22995
+ if (memories.length > maxShardSize) {
22996
+ for (let i = 0;i < memories.length; i += maxShardSize) {
22997
+ memoryChunks.push(memories.slice(i, i + maxShardSize));
22998
+ }
22999
+ } else {
23000
+ memoryChunks.push(memories);
23001
+ }
23002
+ for (let chunkIdx = 0;chunkIdx < memoryChunks.length; chunkIdx++) {
23003
+ const chunk = memoryChunks[chunkIdx];
23004
+ const clusters = clusterByTokenOverlap2(chunk, entryTokens2, cfg.clusteringThreshold);
23005
+ const medianTime = chunk.map((e) => e.created_at ? Date.parse(e.created_at) : Date.now()).sort((a, b) => a - b)[Math.floor(chunk.length / 2)] || Date.now();
23006
+ const baseShardId = makeShardId(project, type2, new Date(medianTime));
23007
+ const shardId = memoryChunks.length > 1 ? `${baseShardId}_p${chunkIdx + 1}` : baseShardId;
23008
+ const bucket = formatTimeBucket(new Date(medianTime));
23009
+ const { start, end } = parseTimeBucket(bucket);
23010
+ const shardNodes = [];
23011
+ for (const cluster of clusters) {
23012
+ if (cluster.length === 0)
23013
+ continue;
23014
+ const node = cluster.length >= cfg.minClusterSize ? buildClusterHierarchy(cluster, cfg) : buildLeafCluster(cluster);
23015
+ node.partition = { shardId, nodeCount: countNodes(node), minScore: 0, maxScore: 0 };
23016
+ shardNodes.push(node);
23017
+ }
23018
+ const shard = {
23019
+ id: shardId,
23020
+ project,
23021
+ type: type2,
23022
+ timeRange: { start: start.toISOString(), end: end.toISOString() },
23023
+ nodes: shardNodes,
23024
+ stats: {
23025
+ memoryCount: chunk.length,
23026
+ nodeCount: shardNodes.reduce((sum, n) => sum + countNodes(n), 0),
23027
+ minScore: 1,
23028
+ maxScore: 0,
23029
+ builtAt: nowIso2()
23030
+ }
23031
+ };
23032
+ for (const node of shardNodes) {
23033
+ const score = node.metadata?.salience ?? 0;
23034
+ shard.stats.minScore = Math.min(shard.stats.minScore, score);
23035
+ shard.stats.maxScore = Math.max(shard.stats.maxScore, score);
23036
+ }
23037
+ finalShards.push(shard);
23038
+ }
23039
+ const partitionMemories = memories.length;
23040
+ const partitionNodes = finalShards.reduce((sum, s) => sum + s.nodes.length, 0);
23041
+ const partition = {
23042
+ project,
23043
+ type: type2,
23044
+ shards: finalShards,
23045
+ totalNodes: partitionNodes,
23046
+ totalMemories: partitionMemories,
23047
+ updatedAt: nowIso2()
23048
+ };
23049
+ partitions[`${project}|${type2}`] = partition;
23050
+ totalIndexNodes += partitionNodes;
23051
+ totalIndexMemories += partitionMemories;
23052
+ writeFileSync9(partitionIndexFilePath(pDir), JSON.stringify(partition, null, 2), "utf8");
23053
+ for (const shard of finalShards) {
23054
+ writeFileSync9(shardFilePath(pDir, shard.id), JSON.stringify(shard, null, 2), "utf8");
23055
+ }
23056
+ }
23057
+ const index = {
23058
+ version: 1,
23059
+ partitions,
23060
+ totalNodes: totalIndexNodes,
23061
+ totalMemories: totalIndexMemories,
23062
+ builtAt: nowIso2()
23063
+ };
23064
+ writeFileSync9(globalIndexFilePath(indexDir(memoryDir)), JSON.stringify(index, null, 2), "utf8");
23065
+ return index;
23066
+ }
23067
+ function loadTreeIndex(memoryDir) {
23068
+ const path = globalIndexFilePath(indexDir(memoryDir));
23069
+ if (!existsSync20(path))
23070
+ return null;
23071
+ try {
23072
+ const data = JSON.parse(readFileSync18(path, "utf8"));
23073
+ return data.version === 1 ? data : null;
23074
+ } catch {
23075
+ return null;
23076
+ }
23077
+ }
23078
+ function selectPartitions(index, options) {
23079
+ const result = [];
23080
+ for (const partition of Object.values(index.partitions)) {
23081
+ if (options.project && partition.project !== options.project)
23082
+ continue;
23083
+ if (options.type && partition.type !== options.type)
23084
+ continue;
23085
+ result.push(partition);
23086
+ }
23087
+ return result;
23088
+ }
23089
+ function scoreNode(node, query) {
23090
+ const queryTokens = new Set(tokenize2(query));
23091
+ if (queryTokens.size === 0)
23092
+ return 0;
23093
+ const haystack = tokenize2(`${node.title} ${node.summary} ${(node.metadata?.tags ?? []).join(" ")}`);
23094
+ const hay = new Set(haystack);
23095
+ let overlap = 0;
23096
+ for (const t of queryTokens)
23097
+ if (hay.has(t))
23098
+ overlap++;
23099
+ const baseScore = overlap / Math.max(1, queryTokens.size);
23100
+ const salienceBonus = (node.metadata?.salience ?? 0) * 0.1;
23101
+ return baseScore + salienceBonus;
23102
+ }
23103
+ function estimateNodeTokens(node, depth) {
23104
+ const base = (node.title?.length ?? 0) + (node.summary?.length ?? 0);
23105
+ const contentLen = node.content?.length ?? 0;
23106
+ const metaLen = JSON.stringify(node.metadata ?? {}).length;
23107
+ switch (depth) {
23108
+ case "L1":
23109
+ return Math.max(1, Math.ceil(base / 4));
23110
+ case "L2":
23111
+ return Math.max(1, Math.ceil((base + contentLen) / 4));
23112
+ case "L3":
23113
+ return Math.max(1, Math.ceil((base + contentLen + metaLen) / 4));
23114
+ }
23115
+ }
23116
+ function traverseShardBestFirst(shard, query, maxDepth, remainingBudget, disclosureDepth) {
23117
+ if (remainingBudget <= 0)
23118
+ return { nodes: [], tokensUsed: 0 };
23119
+ const results = [];
23120
+ let tokensUsed = 0;
23121
+ const queue = [];
23122
+ for (const node of shard.nodes) {
23123
+ const score = scoreNode(node, query);
23124
+ if (score >= SEARCH_SCORE_THRESHOLD) {
23125
+ queue.push({ node, depth: 0, score });
23126
+ }
23127
+ }
23128
+ queue.sort((a, b) => b.score - a.score);
23129
+ while (queue.length > 0 && tokensUsed < remainingBudget) {
23130
+ const { node, depth, score } = queue.shift();
23131
+ if (depth > maxDepth)
23132
+ continue;
23133
+ const nodeTokens = estimateNodeTokens(node, disclosureDepth);
23134
+ if (tokensUsed + nodeTokens > remainingBudget && results.length > 0)
23135
+ break;
23136
+ results.push({ node, score });
23137
+ tokensUsed += nodeTokens;
23138
+ for (const child of node.children) {
23139
+ const childScore = scoreNode(child, query);
23140
+ if (childScore >= SEARCH_SCORE_THRESHOLD) {
23141
+ queue.push({ node: child, depth: depth + 1, score: childScore });
23142
+ }
23143
+ }
23144
+ queue.sort((a, b) => b.score - a.score);
23145
+ }
23146
+ return { nodes: results, tokensUsed };
23147
+ }
23148
+ function paginateResults(results, page, pageSize) {
23149
+ const start = Math.max(0, (page - 1) * pageSize);
23150
+ return results.slice(start, start + pageSize);
23151
+ }
23152
+ function searchTree(index, options) {
23153
+ const tokenBudget = options.tokenBudget ?? 2000;
23154
+ const maxDepth = options.maxDepth ?? 5;
23155
+ const maxNodes = options.maxNodes ?? 100;
23156
+ const disclosureDepth = options.disclosureDepth ?? "L1";
23157
+ let tokensUsed = 0;
23158
+ const partitions = selectPartitions(index, options);
23159
+ const results = [];
23160
+ let partitionsSearched = 0;
23161
+ let shardsSearched = 0;
23162
+ for (const partition of partitions) {
23163
+ if (tokensUsed >= tokenBudget || results.length >= maxNodes)
23164
+ break;
23165
+ partitionsSearched++;
23166
+ for (const shard of partition.shards) {
23167
+ if (tokensUsed >= tokenBudget || results.length >= maxNodes)
23168
+ break;
23169
+ shardsSearched++;
23170
+ const shardResults = traverseShardBestFirst(shard, options.query, maxDepth, tokenBudget - tokensUsed, disclosureDepth);
23171
+ tokensUsed += shardResults.tokensUsed;
23172
+ results.push(...shardResults.nodes);
23173
+ if (results.length >= maxNodes)
23174
+ break;
23175
+ }
23176
+ }
23177
+ results.sort((a, b) => b.score - a.score);
23178
+ const paginated = paginateResults(results, options.page ?? 1, options.pageSize ?? 10);
23179
+ return {
23180
+ nodes: paginated,
23181
+ memories: [],
23182
+ total: results.length,
23183
+ tokensUsed,
23184
+ partitionsSearched,
23185
+ shardsSearched
23186
+ };
23187
+ }
23188
+ var SHARD_THRESHOLD = 1e4, SHARD_TIME_BUCKET = "monthly", UPSERT_INTERVAL_MS = 60000, MAX_RECURSION_DEPTH = 5, SEARCH_SCORE_THRESHOLD = 0.05, DEFAULT_CONFIG;
23189
+ var init_tree_index = __esm(() => {
23190
+ init_store();
23191
+ DEFAULT_CONFIG = {
23192
+ maxDepth: 5,
23193
+ maxNodesPerQuery: 100,
23194
+ clusteringThreshold: 0.5,
23195
+ minClusterSize: 3,
23196
+ shardThreshold: SHARD_THRESHOLD,
23197
+ shardTimeBucket: SHARD_TIME_BUCKET,
23198
+ enableLLMReasoning: false,
23199
+ upsertIntervalMs: UPSERT_INTERVAL_MS
23200
+ };
23201
+ });
23202
+
23203
+ // src/retrieval/index.ts
23204
+ var init_retrieval3 = __esm(() => {
23205
+ init_tree_index();
23206
+ });
23207
+
23208
+ // src/wiki/render.ts
23209
+ function renderConceptPage(page) {
23210
+ const frontmatter = [
23211
+ "---",
23212
+ `title: "${page.title}"`,
23213
+ `type: ${page.type}`,
23214
+ `project: ${page.project}`,
23215
+ `updatedAt: ${page.updatedAt}`,
23216
+ `tags: [${page.tags.map((t) => `"${t}"`).join(", ")}]`,
23217
+ `relatedConcepts: [${page.relatedConcepts.map((s) => `"${s}"`).join(", ")}]`,
23218
+ `relatedEntities: [${page.relatedEntities.map((s) => `"${s}"`).join(", ")}]`,
23219
+ `memoryRefs: [${page.memoryRefs.map((s) => `"${s}"`).join(", ")}]`,
23220
+ "---"
23221
+ ].join(`
23222
+ `);
23223
+ const related = [
23224
+ page.relatedConcepts.length > 0 && `## Related Concepts
23225
+
23226
+ ${page.relatedConcepts.map((s) => `- [[${s}]]`).join(`
23227
+ `)}`,
23228
+ page.relatedEntities.length > 0 && `## Related Entities
23229
+
23230
+ ${page.relatedEntities.map((s) => `- [[${s}]]`).join(`
23231
+ `)}`
23232
+ ].filter(Boolean).join(`
23233
+
23234
+ `);
23235
+ const memories = page.memoryRefs.length > 0 ? `
23236
+ ## Source Memories
23237
+
23238
+ ${page.memoryRefs.map((id) => `- [[${id}]]`).join(`
23239
+ `)}` : "";
23240
+ return `${frontmatter}
23241
+
23242
+ # ${page.title}
23243
+
23244
+ ## Summary
23245
+
23246
+ ${page.summary}
23247
+
23248
+ ## Content
23249
+
23250
+ ${page.content}
23251
+
23252
+ ${related}${memories}
23253
+ `;
23254
+ }
23255
+ function renderEntityPage(page) {
23256
+ const frontmatter = [
23257
+ "---",
23258
+ `title: "${page.title}"`,
23259
+ `type: ${page.type}`,
23260
+ `entityType: ${page.entityType}`,
23261
+ `project: ${page.project}`,
23262
+ `updatedAt: ${page.updatedAt}`,
23263
+ `relatedEntities: [${page.relatedEntities.map((s) => `"${s}"`).join(", ")}]`,
23264
+ `relatedConcepts: [${page.relatedConcepts.map((s) => `"${s}"`).join(", ")}]`,
23265
+ `memoryRefs: [${page.memoryRefs.map((s) => `"${s}"`).join(", ")}]`,
23266
+ "---"
23267
+ ].join(`
23268
+ `);
23269
+ const related = [
23270
+ page.relatedEntities.length > 0 && `## Related Entities
23271
+
23272
+ ${page.relatedEntities.map((s) => `- [[${s}]]`).join(`
23273
+ `)}`,
23274
+ page.relatedConcepts.length > 0 && `## Related Concepts
23275
+
23276
+ ${page.relatedConcepts.map((s) => `- [[${s}]]`).join(`
23277
+ `)}`
23278
+ ].filter(Boolean).join(`
23279
+
23280
+ `);
23281
+ const mentions = page.mentions.length > 0 ? `
23282
+ ## Mentions
23283
+
23284
+ ${page.mentions.map((m) => `- [[${m.memoryId}]]: ${m.context}`).join(`
23285
+ `)}` : "";
23286
+ return `${frontmatter}
23287
+
23288
+ # ${page.title}
23289
+
23290
+ **Type:** ${page.entityType}
23291
+
23292
+ ## Summary
23293
+
23294
+ ${page.summary}
23295
+
23296
+ ## Content
23297
+
23298
+ ${page.content}
23299
+
23300
+ ${related}${mentions}
23301
+ `;
23302
+ }
23303
+ function renderIndexPage(page) {
23304
+ const frontmatter = [
23305
+ "---",
23306
+ `title: "${page.title}"`,
23307
+ `type: ${page.type}`,
23308
+ `project: ${page.project}`,
23309
+ `updatedAt: ${page.updatedAt}`,
23310
+ "---"
23311
+ ].join(`
23312
+ `);
23313
+ const sections = page.sections.map((section) => {
23314
+ const items = section.items.map((slug) => `- [[${slug}]]`).join(`
23315
+ `);
23316
+ return `## ${section.title}
23317
+
23318
+ ${items}`;
23319
+ }).join(`
23320
+
23321
+ `);
23322
+ return `${frontmatter}
23323
+
23324
+ # ${page.title}
23325
+
23326
+ ${sections}
23327
+ `;
23328
+ }
23329
+ function renderLogPage(page) {
23330
+ const frontmatter = [
23331
+ "---",
23332
+ `title: "${page.title}"`,
23333
+ `type: ${page.type}`,
23334
+ `project: ${page.project}`,
23335
+ `updatedAt: ${page.updatedAt}`,
23336
+ "---"
23337
+ ].join(`
23338
+ `);
23339
+ const entries = page.entries.map((entry) => {
23340
+ const memRefs = entry.memoryIds && entry.memoryIds.length > 0 ? ` (${entry.memoryIds.map((id) => `[[${id}]]`).join(", ")})` : "";
23341
+ return `- **${entry.timestamp}** [${entry.action}] ${entry.pageSlug}${memRefs}${entry.details ? `: ${entry.details}` : ""}`;
23342
+ }).join(`
23343
+ `);
23344
+ return `${frontmatter}
23345
+
23346
+ # ${page.title}
23347
+
23348
+ ${entries}
23349
+ `;
23350
+ }
23351
+
23352
+ // src/wiki/compiler.ts
23353
+ import { existsSync as existsSync21, mkdirSync as mkdirSync10, writeFileSync as writeFileSync10, readFileSync as readFileSync19, readdirSync as readdirSync7 } from "node:fs";
23354
+ import { join as join20 } from "node:path";
23355
+ function compileWiki(store, memoryDir, options = {}) {
23356
+ const project = options.project;
23357
+ const dryRun = options.dryRun ?? false;
23358
+ const minClusterSize = options.minClusterSize ?? DEFAULT_MIN_CLUSTER_SIZE;
23359
+ const clusteringThreshold = options.clusteringThreshold ?? DEFAULT_CLUSTERING_THRESHOLD;
23360
+ const includeTypes = options.includeTypes ?? [
23361
+ "fix",
23362
+ "decision",
23363
+ "architecture",
23364
+ "operation",
23365
+ "failure",
23366
+ "constraint",
23367
+ "preference",
23368
+ "discovery"
23369
+ ];
23370
+ const allMemories = list(store).filter((e) => e.status === "confirmed" && includeTypes.includes(e.type ?? "discovery"));
23371
+ if (project) {
23372
+ const filtered = allMemories.filter((e) => e.project === project);
23373
+ if (filtered.length === 0) {
23374
+ return { pagesCreated: [], pagesUpdated: [], logEntries: [], errors: [`No confirmed memories found for project: ${project}`] };
23375
+ }
23376
+ }
23377
+ const memories = project ? allMemories.filter((e) => e.project === project) : allMemories;
23378
+ const wikiDir = join20(memoryDir, "wiki");
23379
+ const conceptsDir = join20(wikiDir, "concepts");
23380
+ const entitiesDir = join20(wikiDir, "entities");
23381
+ if (!dryRun) {
23382
+ mkdirSync10(conceptsDir, { recursive: true });
23383
+ mkdirSync10(entitiesDir, { recursive: true });
23384
+ }
23385
+ const result = { pagesCreated: [], pagesUpdated: [], logEntries: [], errors: [] };
23386
+ const existingConcepts = loadExistingConcepts(conceptsDir);
23387
+ const existingEntities = loadExistingEntities(entitiesDir);
23388
+ const conceptMap = new Map;
23389
+ const entityMap = new Map;
23390
+ const groups = new Map;
23391
+ for (const e of memories) {
23392
+ const key = `${e.project}|${e.type ?? "unknown"}`;
23393
+ const group = groups.get(key);
23394
+ if (group)
23395
+ group.push(e);
23396
+ else
23397
+ groups.set(key, [e]);
23398
+ }
23399
+ for (const [, groupMemories] of groups) {
23400
+ const clusters = clusterByTokenOverlap(groupMemories, entryTokens3, clusteringThreshold);
23401
+ for (const cluster of clusters) {
23402
+ if (cluster.length < minClusterSize)
23403
+ continue;
23404
+ const topic = dominantTopicTokens(cluster.map((e) => e.title));
23405
+ const slug = slugify2(topic.join("-") || (cluster[0].type ?? "concept"));
23406
+ const existing = existingConcepts.get(slug);
23407
+ const conceptPage = buildConceptPage(cluster, topic, slug, existing);
23408
+ if (existing) {
23409
+ result.pagesUpdated.push(conceptPage);
23410
+ result.logEntries.push({
23411
+ timestamp: new Date().toISOString(),
23412
+ action: "updated",
23413
+ pageSlug: slug,
23414
+ memoryIds: cluster.map((e) => e.id),
23415
+ details: `Updated concept from ${cluster.length} memories`
23416
+ });
23417
+ } else {
23418
+ result.pagesCreated.push(conceptPage);
23419
+ result.logEntries.push({
23420
+ timestamp: new Date().toISOString(),
23421
+ action: "created",
23422
+ pageSlug: slug,
23423
+ memoryIds: cluster.map((e) => e.id),
23424
+ details: `Created concept from ${cluster.length} memories`
23425
+ });
23426
+ }
23427
+ conceptMap.set(slug, conceptPage);
23428
+ }
23429
+ }
23430
+ crossLinkConcepts(conceptMap);
23431
+ const extractedEntities = extractEntities(memories);
23432
+ for (const [slug, entity] of extractedEntities) {
23433
+ const existing = existingEntities.get(slug);
23434
+ if (existing) {
23435
+ entity.memoryRefs = Array.from(new Set([...existing.memoryRefs, ...entity.memoryRefs]));
23436
+ entity.mentions = [...existing.mentions, ...entity.mentions].slice(-50);
23437
+ result.pagesUpdated.push(entity);
23438
+ result.logEntries.push({
23439
+ timestamp: new Date().toISOString(),
23440
+ action: "updated",
23441
+ pageSlug: slug,
23442
+ memoryIds: entity.memoryRefs,
23443
+ details: `Updated entity with ${entity.memoryRefs.length} mentions`
23444
+ });
23445
+ } else {
23446
+ result.pagesCreated.push(entity);
23447
+ result.logEntries.push({
23448
+ timestamp: new Date().toISOString(),
23449
+ action: "created",
23450
+ pageSlug: slug,
23451
+ memoryIds: entity.memoryRefs,
23452
+ details: `Created entity from ${entity.memoryRefs.length} mentions`
23453
+ });
23454
+ }
23455
+ entityMap.set(slug, entity);
23456
+ }
23457
+ crossLinkEntities(entityMap, conceptMap);
23458
+ const indexPage = buildIndexPage(conceptMap, entityMap, project ?? "all");
23459
+ result.pagesCreated.push(indexPage);
23460
+ const logPage = buildLogPage(result.logEntries);
23461
+ result.pagesCreated.push(logPage);
23462
+ if (!dryRun) {
23463
+ writeConceptPages(conceptMap, conceptsDir);
23464
+ writeEntityPages(entityMap, entitiesDir);
23465
+ writeIndexPage(indexPage, wikiDir);
23466
+ writeLogPage(logPage, wikiDir);
23467
+ }
23468
+ return result;
23469
+ }
23470
+ function entryTokens3(e) {
23471
+ const bag = new Map;
23472
+ for (const t of tokenize3(e.title))
23473
+ bag.set(t, (bag.get(t) ?? 0) + 2);
23474
+ for (const t of tokenize3(e.content))
23475
+ bag.set(t, (bag.get(t) ?? 0) + 1);
23476
+ return bag;
23477
+ }
23478
+ function buildConceptPage(cluster, topic, slug, existing) {
23479
+ const clusterProject = cluster[0].project;
23480
+ const memoryIds = cluster.map((e) => e.id);
23481
+ const tags = Array.from(new Set(cluster.flatMap((e) => e.tags ?? [])));
23482
+ const content = cluster.map((e) => `## ${e.title}
23483
+
23484
+ ${e.content}
23485
+
23486
+ *Source: ${e.id}*`).join(`
23487
+
23488
+ ---
23489
+
23490
+ `);
23491
+ const summary = cluster.map((e) => e.content.slice(0, 200)).join(" | ");
23492
+ return {
23493
+ slug,
23494
+ title: topic.length > 0 ? topic.join(" ") : cluster[0].type ?? "concept",
23495
+ type: "concept",
23496
+ clusterProject,
23497
+ updatedAt: new Date().toISOString(),
23498
+ relatedPages: existing?.relatedPages ?? [],
23499
+ memoryRefs: memoryIds,
23500
+ summary,
23501
+ content,
23502
+ tags: Array.from(new Set(cluster.flatMap((e) => e.tags ?? []))),
23503
+ relatedConcepts: existing?.relatedConcepts ?? [],
23504
+ relatedEntities: existing?.relatedEntities ?? []
23505
+ };
23506
+ }
23507
+ function crossLinkConcepts(conceptMap) {
23508
+ const concepts = Array.from(conceptMap.values());
23509
+ for (let i = 0;i < concepts.length; i++) {
23510
+ for (let j = i + 1;j < concepts.length; j++) {
23511
+ const a = concepts[i];
23512
+ const b = concepts[j];
23513
+ const similarity = cosineSimilarity4(tokenBag3(a.title + " " + a.summary + " " + a.tags.join(" ")), tokenBag3(b.title + " " + b.summary + " " + b.tags.join(" ")));
23514
+ if (similarity >= 0.3) {
23515
+ if (!a.relatedConcepts.includes(b.slug))
23516
+ a.relatedConcepts.push(b.slug);
23517
+ if (!b.relatedConcepts.includes(a.slug))
23518
+ b.relatedConcepts.push(a.slug);
23519
+ }
23520
+ }
23521
+ }
23522
+ }
23523
+ function extractEntities(memories) {
23524
+ const entityMap = new Map;
23525
+ for (const memory of memories) {
23526
+ const entities = extractEntitiesFromText(memory.content, memory.id);
23527
+ for (const entity of entities) {
23528
+ const slug = slugify2(entity.name);
23529
+ const existing = entityMap.get(slug);
23530
+ if (existing) {
23531
+ existing.memoryRefs.push(memory.id);
23532
+ existing.mentions.push({ memoryId: memory.id, context: extractContext(memory.content, entity.name) });
23533
+ } else {
23534
+ entityMap.set(slug, {
23535
+ slug,
23536
+ title: entity.name,
23537
+ type: "entity",
23538
+ entityType: entity.type,
23539
+ project: memory.project,
23540
+ updatedAt: new Date().toISOString(),
23541
+ relatedPages: [],
23542
+ memoryRefs: [memory.id],
23543
+ summary: `${entity.type}: ${entity.name}`,
23544
+ content: `## ${entity.name}
23545
+
23546
+ **Type:** ${entity.type}
23547
+
23548
+ **Mentions:**
23549
+ - ${memory.id}: ${extractContext(memory.content, entity.name)}`,
23550
+ mentions: [{ memoryId: memory.id, context: extractContext(memory.content, entity.name) }],
23551
+ relatedEntities: [],
23552
+ relatedConcepts: []
23553
+ });
23554
+ }
23555
+ }
23556
+ }
23557
+ return entityMap;
23558
+ }
23559
+ function extractEntitiesFromText(text, memoryId) {
23560
+ const entities = [];
23561
+ const personMatches = text.match(/@(\w+)/g);
23562
+ if (personMatches) {
23563
+ for (const match of personMatches) {
23564
+ entities.push({ name: match.slice(1), type: "person" });
23565
+ }
23566
+ }
23567
+ const productPatterns = [
23568
+ /\b(?:Next\.js|React|TypeScript|Node\.js|Bun|Vercel|Anthropic|OpenAI|PostgreSQL|Redis|Docker|Kubernetes|GraphQL|REST|gRPC|WebAssembly|WASM|Tailwind|ESLint|Prettier|Jest|Vitest|Playwright|Cypress)\b/gi,
23569
+ /\b\w+\.js\b/gi
23570
+ ];
23571
+ for (const pattern of productPatterns) {
23572
+ const matches = text.match(pattern);
23573
+ if (matches) {
23574
+ for (const match of matches) {
23575
+ entities.push({ name: match, type: "product" });
23576
+ }
23577
+ }
23578
+ }
23579
+ const orgPatterns = [
23580
+ /\b(?:Vercel|Anthropic|OpenAI|Google|Microsoft|GitHub|GitLab|AWS|GCP|Azure|Meta|Facebook|Amazon|Netflix|Shopify|Stripe|Supabase|PlanetScale|Neon|Turso)\b/gi
23581
+ ];
23582
+ for (const pattern of orgPatterns) {
23583
+ const matches = text.match(pattern);
23584
+ if (matches) {
23585
+ for (const match of matches) {
23586
+ entities.push({ name: match, type: "organization" });
23587
+ }
23588
+ }
23589
+ }
23590
+ const fileMatches = text.match(/(?:src|lib|test|docs|scripts)\/[\w\/\.-]+\.(?:ts|tsx|js|jsx|json|yaml|yml|md|mdx)/g);
23591
+ if (fileMatches) {
23592
+ for (const match of fileMatches) {
23593
+ entities.push({ name: match, type: "file" });
23594
+ }
23595
+ }
23596
+ const seen = new Set;
23597
+ return entities.filter((e) => {
23598
+ const key = e.name.toLowerCase();
23599
+ if (seen.has(key))
23600
+ return false;
23601
+ seen.add(key);
23602
+ return true;
23603
+ });
23604
+ }
23605
+ function extractContext(text, entityName) {
23606
+ const idx = text.toLowerCase().indexOf(entityName.toLowerCase());
23607
+ if (idx === -1)
23608
+ return text.slice(0, 100);
23609
+ const start = Math.max(0, idx - 50);
23610
+ const end = Math.min(text.length, idx + entityName.length + 50);
23611
+ return "..." + text.slice(start, end) + "...";
23612
+ }
23613
+ function crossLinkEntities(entityMap, conceptMap) {
23614
+ const entities = Array.from(entityMap.values());
23615
+ for (let i = 0;i < entities.length; i++) {
23616
+ for (let j = i + 1;j < entities.length; j++) {
23617
+ const a = entities[i];
23618
+ const b = entities[j];
23619
+ const commonMemories = a.memoryRefs.filter((id) => b.memoryRefs.includes(id));
23620
+ if (commonMemories.length >= 2) {
23621
+ if (!a.relatedEntities.includes(b.slug))
23622
+ a.relatedEntities.push(b.slug);
23623
+ if (!b.relatedEntities.includes(a.slug))
23624
+ b.relatedEntities.push(a.slug);
23625
+ }
23626
+ }
23627
+ }
23628
+ for (const entity of entities) {
23629
+ for (const concept of conceptMap.values()) {
23630
+ const similarity = cosineSimilarity4(tokenBag3(entity.title + " " + entity.summary), tokenBag3(concept.title + " " + concept.summary + " " + concept.tags.join(" ")));
23631
+ if (similarity >= 0.3) {
23632
+ if (!entity.relatedConcepts.includes(concept.slug))
23633
+ entity.relatedConcepts.push(concept.slug);
23634
+ if (!concept.relatedEntities.includes(entity.slug))
23635
+ concept.relatedEntities.push(entity.slug);
23636
+ }
23637
+ }
23638
+ }
23639
+ }
23640
+ function buildIndexPage(conceptMap, entityMap, project) {
23641
+ const concepts = Array.from(conceptMap.values());
23642
+ const entities = Array.from(entityMap.values());
23643
+ return {
23644
+ slug: "index",
23645
+ title: "Knowledge Base Index",
23646
+ type: "index",
23647
+ project: project || "all",
23648
+ updatedAt: new Date().toISOString(),
23649
+ relatedPages: [],
23650
+ memoryRefs: [],
23651
+ sections: [
23652
+ {
23653
+ title: "Concepts",
23654
+ type: "concepts",
23655
+ items: concepts.map((c) => c.slug)
23656
+ },
23657
+ {
23658
+ title: "Entities",
23659
+ type: "entities",
23660
+ items: entities.map((e) => e.slug)
23661
+ },
23662
+ {
23663
+ title: "By Type",
23664
+ type: "by-type",
23665
+ items: Array.from(new Set(concepts.map((c) => c.type))).map((t) => `type:${t}`)
23666
+ }
23667
+ ]
23668
+ };
23669
+ }
23670
+ function buildLogPage(logEntries) {
23671
+ return {
23672
+ slug: "log",
23673
+ title: "Compilation Log",
23674
+ type: "log",
23675
+ project: "all",
23676
+ updatedAt: new Date().toISOString(),
23677
+ relatedPages: [],
23678
+ memoryRefs: [],
23679
+ entries: logEntries
23680
+ };
23681
+ }
23682
+ function loadExistingConcepts(dir) {
23683
+ const map3 = new Map;
23684
+ if (!existsSync21(dir))
23685
+ return map3;
23686
+ for (const file of readdirSync7(dir)) {
23687
+ if (!file.endsWith(".md"))
23688
+ continue;
23689
+ const slug = file.slice(0, -3);
23690
+ try {
23691
+ const content = readFileSync19(join20(dir, file), "utf8");
23692
+ const frontmatter = parseFrontmatter(content);
23693
+ map3.set(slug, { ...frontmatter, slug, content: content.slice(content.indexOf(`
23694
+ ---
23695
+ `) + 5) });
23696
+ } catch {}
23697
+ }
23698
+ return map3;
23699
+ }
23700
+ function loadExistingEntities(dir) {
23701
+ const map3 = new Map;
23702
+ if (!existsSync21(dir))
23703
+ return map3;
23704
+ for (const file of readdirSync7(dir)) {
23705
+ if (!file.endsWith(".md"))
23706
+ continue;
23707
+ const slug = file.slice(0, -3);
23708
+ try {
23709
+ const content = readFileSync19(join20(dir, file), "utf8");
23710
+ const frontmatter = parseFrontmatter(content);
23711
+ map3.set(slug, { ...frontmatter, slug, content: content.slice(content.indexOf(`
23712
+ ---
23713
+ `) + 5) });
23714
+ } catch {}
23715
+ }
23716
+ return map3;
23717
+ }
23718
+ function parseFrontmatter(content) {
23719
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
23720
+ if (!match)
23721
+ return {};
23722
+ const lines = match[1].split(`
23723
+ `);
23724
+ const obj = {};
23725
+ for (const line of lines) {
23726
+ const idx = line.indexOf(":");
23727
+ if (idx > 0) {
23728
+ const key = line.slice(0, idx).trim();
23729
+ const value = line.slice(idx + 1).trim();
23730
+ obj[key] = value.replace(/^["']|["']$/g, "");
23731
+ }
23732
+ }
23733
+ return obj;
23734
+ }
23735
+ function slugify2(text) {
23736
+ return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60);
23737
+ }
23738
+ function writeConceptPages(map3, dir) {
23739
+ for (const [slug, page] of map3) {
23740
+ const content = renderConceptPage(page);
23741
+ writeFileSync10(join20(dir, slug + ".md"), content, "utf8");
23742
+ }
23743
+ }
23744
+ function writeEntityPages(map3, dir) {
23745
+ for (const [slug, page] of map3) {
23746
+ const content = renderEntityPage(page);
23747
+ writeFileSync10(join20(dir, slug + ".md"), content, "utf8");
23748
+ }
23749
+ }
23750
+ function writeIndexPage(page, dir) {
23751
+ const content = renderIndexPage(page);
23752
+ writeFileSync10(join20(dir, "index.md"), content, "utf8");
23753
+ }
23754
+ function writeLogPage(page, dir) {
23755
+ const content = renderLogPage(page);
23756
+ writeFileSync10(join20(dir, "log.md"), content, "utf8");
23757
+ }
23758
+ function tokenBag3(text, weight = 1) {
23759
+ const bag = new Map;
23760
+ for (const t of tokenize3(text)) {
23761
+ bag.set(t, (bag.get(t) ?? 0) + weight);
23762
+ }
23763
+ return bag;
23764
+ }
23765
+ function cosineSimilarity4(a, b) {
23766
+ let dot = 0;
23767
+ let na = 0;
23768
+ let nb = 0;
23769
+ for (const v of a.values())
23770
+ na += v * v;
23771
+ for (const [t, v] of b) {
23772
+ nb += v * v;
23773
+ const av = a.get(t);
23774
+ if (av)
23775
+ dot += av * v;
23776
+ }
23777
+ return na > 0 && nb > 0 ? dot / Math.sqrt(na * nb) : 0;
23778
+ }
23779
+ function tokenize3(text) {
23780
+ if (!text || typeof text !== "string")
23781
+ return [];
23782
+ return text.toLowerCase().match(/[a-z0-9]+/g) ?? [];
23783
+ }
23784
+ function listWikiPages(memoryDir, options = {}) {
23785
+ const wikiDir = join20(memoryDir, "wiki");
23786
+ const pages = [];
23787
+ if (options.type === undefined || options.type === "concept") {
23788
+ const concepts = loadExistingConcepts(join20(wikiDir, "concepts"));
23789
+ for (const page of concepts.values()) {
23790
+ if (!options.project || page.project === options.project) {
23791
+ pages.push(page);
23792
+ }
23793
+ }
23794
+ }
23795
+ if (options.type === undefined || options.type === "entity") {
23796
+ const entities = loadExistingEntities(join20(wikiDir, "entities"));
23797
+ for (const page of entities.values()) {
23798
+ if (!options.project || page.project === options.project) {
23799
+ pages.push(page);
23800
+ }
23801
+ }
23802
+ }
23803
+ if (options.type === undefined || options.type === "index") {
23804
+ const idxPath = join20(wikiDir, "index.md");
23805
+ if (existsSync21(idxPath)) {
23806
+ try {
23807
+ const raw = readFileSync19(idxPath, "utf8");
23808
+ const fm = parseFrontmatter(raw);
23809
+ pages.push({ ...fm, slug: "index", type: "index", content: raw });
23810
+ } catch {}
23811
+ }
23812
+ }
23813
+ if (options.type === undefined || options.type === "log") {
23814
+ const logPath = join20(wikiDir, "log.md");
23815
+ if (existsSync21(logPath)) {
23816
+ try {
23817
+ const raw = readFileSync19(logPath, "utf8");
23818
+ const fm = parseFrontmatter(raw);
23819
+ pages.push({ ...fm, slug: "log", type: "log", content: raw });
23820
+ } catch {}
23821
+ }
23822
+ }
23823
+ return pages;
23824
+ }
23825
+ function getWikiPage(memoryDir, slug, type2) {
23826
+ const wikiDir = join20(memoryDir, "wiki");
23827
+ if (slug === "index") {
23828
+ const p = join20(wikiDir, "index.md");
23829
+ if (existsSync21(p)) {
23830
+ const raw = readFileSync19(p, "utf8");
23831
+ const fm = parseFrontmatter(raw);
23832
+ return { ...fm, slug: "index", type: "index", content: raw };
23833
+ }
23834
+ return null;
23835
+ }
23836
+ if (slug === "log") {
23837
+ const p = join20(wikiDir, "log.md");
23838
+ if (existsSync21(p)) {
23839
+ const raw = readFileSync19(p, "utf8");
23840
+ const fm = parseFrontmatter(raw);
23841
+ return { ...fm, slug: "log", type: "log", content: raw };
23842
+ }
23843
+ return null;
23844
+ }
23845
+ if (!type2 || type2 === "concept") {
23846
+ const p = join20(wikiDir, "concepts", `${slug}.md`);
23847
+ if (existsSync21(p)) {
23848
+ const raw = readFileSync19(p, "utf8");
23849
+ const fm = parseFrontmatter(raw);
23850
+ return { ...fm, slug, type: "concept", content: raw };
23851
+ }
23852
+ }
23853
+ if (!type2 || type2 === "entity") {
23854
+ const p = join20(wikiDir, "entities", `${slug}.md`);
23855
+ if (existsSync21(p)) {
23856
+ const raw = readFileSync19(p, "utf8");
23857
+ const fm = parseFrontmatter(raw);
23858
+ return { ...fm, slug, type: "entity", content: raw };
23859
+ }
23860
+ }
23861
+ return null;
23862
+ }
23863
+ var DEFAULT_MIN_CLUSTER_SIZE = 3, DEFAULT_CLUSTERING_THRESHOLD = 0.5;
23864
+ var init_compiler = __esm(() => {
23865
+ init_store();
23866
+ init_consolidate();
23867
+ });
23868
+
23869
+ // src/wiki/index.ts
23870
+ var init_wiki = __esm(() => {
23871
+ init_compiler();
23872
+ });
23873
+ // src/entities/extractor.ts
23874
+ import { existsSync as existsSync22, mkdirSync as mkdirSync11, readFileSync as readFileSync20, writeFileSync as writeFileSync11 } from "node:fs";
23875
+ import { join as join21 } from "node:path";
23876
+ function slugify3(text) {
23877
+ return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60);
23878
+ }
23879
+ function extractEntitiesFromMemories(memories, config2 = {}) {
23880
+ const enabledTypes = new Set(config2.enabledTypes ?? ["person", "product", "organization", "file", "concept"]);
23881
+ const aliasMap = config2.aliasMap ?? {};
23882
+ const cooccurrenceThreshold = config2.cooccurrenceThreshold ?? 1;
23883
+ const entityMap = new Map;
23884
+ const memoryEntityMap = new Map;
23885
+ for (const memory of memories) {
23886
+ const text = `${memory.title} ${memory.content} ${(memory.tags ?? []).join(" ")}`;
23887
+ const foundInThisMemory = new Map;
23888
+ if (enabledTypes.has("person")) {
23889
+ for (const pattern of DEFAULT_ENTITY_PATTERNS.person) {
23890
+ const matches = text.matchAll(new RegExp(pattern));
23891
+ for (const match of matches) {
23892
+ const raw = match[1] ?? match[0];
23893
+ const name = raw.replace(/^@/, "").trim();
23894
+ if (name.length > 1) {
23895
+ const slug = slugify3(aliasMap[name.toLowerCase()] ?? name);
23896
+ if (slug)
23897
+ foundInThisMemory.set(slug, { name, type: "person" });
23898
+ }
23899
+ }
23900
+ }
23901
+ }
23902
+ if (enabledTypes.has("product")) {
23903
+ for (const pattern of DEFAULT_ENTITY_PATTERNS.product) {
23904
+ const matches = text.matchAll(new RegExp(pattern));
23905
+ for (const match of matches) {
23906
+ const raw = match[0].trim();
23907
+ if (raw.length > 1) {
23908
+ const slug = slugify3(aliasMap[raw.toLowerCase()] ?? raw);
23909
+ if (slug)
23910
+ foundInThisMemory.set(slug, { name: raw, type: "product" });
23911
+ }
23912
+ }
23913
+ }
23914
+ }
23915
+ if (enabledTypes.has("organization")) {
23916
+ for (const pattern of DEFAULT_ENTITY_PATTERNS.organization) {
23917
+ const matches = text.matchAll(new RegExp(pattern));
23918
+ for (const match of matches) {
23919
+ const raw = match[0].trim();
23920
+ if (raw.length > 1) {
23921
+ const slug = slugify3(aliasMap[raw.toLowerCase()] ?? raw);
23922
+ if (slug)
23923
+ foundInThisMemory.set(slug, { name: raw, type: "organization" });
23924
+ }
23925
+ }
23926
+ }
23927
+ }
23928
+ if (enabledTypes.has("file")) {
23929
+ for (const pattern of DEFAULT_ENTITY_PATTERNS.file) {
23930
+ const matches = text.matchAll(new RegExp(pattern));
23931
+ for (const match of matches) {
23932
+ const raw = match[0].trim();
23933
+ if (raw.length > 1) {
23934
+ const slug = slugify3(raw);
23935
+ if (slug)
23936
+ foundInThisMemory.set(slug, { name: raw, type: "file" });
23937
+ }
23938
+ }
23939
+ }
23940
+ }
23941
+ if (enabledTypes.has("concept")) {
23942
+ for (const pattern of DEFAULT_ENTITY_PATTERNS.concept) {
23943
+ const matches = text.matchAll(new RegExp(pattern));
23944
+ for (const match of matches) {
23945
+ const raw = match[0].trim();
23946
+ if (raw.length > 1) {
23947
+ const slug = slugify3(aliasMap[raw.toLowerCase()] ?? raw);
23948
+ if (slug)
23949
+ foundInThisMemory.set(slug, { name: raw, type: "concept" });
23950
+ }
23951
+ }
23952
+ }
23953
+ }
23954
+ const memoryEntitySlugs = [];
23955
+ const memoryTime = memory.created_at || new Date().toISOString();
23956
+ for (const [slug, { name, type: type2 }] of foundInThisMemory) {
23957
+ memoryEntitySlugs.push(slug);
23958
+ const existing = entityMap.get(slug);
23959
+ if (existing) {
23960
+ if (!existing.memoryRefs.includes(memory.id)) {
23961
+ existing.memoryRefs.push(memory.id);
23962
+ }
23963
+ existing.metadata.mentionCount++;
23964
+ if (memoryTime > existing.metadata.lastSeen)
23965
+ existing.metadata.lastSeen = memoryTime;
23966
+ if (memoryTime < existing.metadata.firstSeen)
23967
+ existing.metadata.firstSeen = memoryTime;
23968
+ } else {
23969
+ entityMap.set(slug, {
23970
+ id: slug,
23971
+ name,
23972
+ type: type2,
23973
+ aliases: [name.toLowerCase()],
23974
+ project: memory.project,
23975
+ memoryRefs: [memory.id],
23976
+ relatedEntities: [],
23977
+ metadata: {
23978
+ firstSeen: memoryTime,
23979
+ lastSeen: memoryTime,
23980
+ mentionCount: 1
23981
+ }
23982
+ });
23983
+ }
23984
+ }
23985
+ memoryEntityMap.set(memory.id, memoryEntitySlugs);
23986
+ }
23987
+ const cooccurrences = new Map;
23988
+ for (const [, entitySlugs] of memoryEntityMap) {
23989
+ for (let i = 0;i < entitySlugs.length; i++) {
23990
+ for (let j = i + 1;j < entitySlugs.length; j++) {
23991
+ const a = entitySlugs[i];
23992
+ const b = entitySlugs[j];
23993
+ if (a === b)
23994
+ continue;
23995
+ if (!cooccurrences.has(a))
23996
+ cooccurrences.set(a, new Map);
23997
+ if (!cooccurrences.has(b))
23998
+ cooccurrences.set(b, new Map);
23999
+ const mapA = cooccurrences.get(a);
24000
+ const mapB = cooccurrences.get(b);
24001
+ mapA.set(b, (mapA.get(b) ?? 0) + 1);
24002
+ mapB.set(a, (mapB.get(a) ?? 0) + 1);
24003
+ }
24004
+ }
24005
+ }
24006
+ for (const [slug, entity] of entityMap) {
24007
+ const relMap = cooccurrences.get(slug);
24008
+ if (relMap) {
24009
+ for (const [otherSlug, strength] of relMap) {
24010
+ if (strength >= cooccurrenceThreshold) {
24011
+ entity.relatedEntities.push({ entityId: otherSlug, strength });
24012
+ }
24013
+ }
24014
+ entity.relatedEntities.sort((a, b) => b.strength - a.strength);
24015
+ }
24016
+ }
24017
+ return {
24018
+ entities: Array.from(entityMap.values()),
24019
+ memoryEntityMap
24020
+ };
24021
+ }
24022
+ function saveEntities(memoryDir, entities) {
24023
+ const filePath = join21(memoryDir, "entities.json");
24024
+ mkdirSync11(memoryDir, { recursive: true });
24025
+ writeFileSync11(filePath, JSON.stringify(entities, null, 2), "utf8");
24026
+ }
24027
+ function loadEntities(memoryDir) {
24028
+ const filePath = join21(memoryDir, "entities.json");
24029
+ if (!existsSync22(filePath))
24030
+ return [];
24031
+ try {
24032
+ return JSON.parse(readFileSync20(filePath, "utf8"));
24033
+ } catch {
24034
+ return [];
24035
+ }
24036
+ }
24037
+ function findEntity(memoryDir, id) {
24038
+ const entities = loadEntities(memoryDir);
24039
+ const cleanId = slugify3(id);
24040
+ return entities.find((e) => e.id === cleanId || e.name.toLowerCase() === id.toLowerCase()) ?? null;
24041
+ }
24042
+ function findRelatedEntities(memoryDir, id) {
24043
+ const entities = loadEntities(memoryDir);
24044
+ const target = findEntity(memoryDir, id);
24045
+ if (!target)
24046
+ return [];
24047
+ const entityIndex = new Map(entities.map((e) => [e.id, e]));
24048
+ const results = [];
24049
+ for (const rel of target.relatedEntities) {
24050
+ const found = entityIndex.get(rel.entityId);
24051
+ if (found) {
24052
+ results.push({ entity: found, strength: rel.strength });
24053
+ }
24054
+ }
24055
+ return results;
24056
+ }
24057
+ var DEFAULT_ENTITY_PATTERNS;
24058
+ var init_extractor = __esm(() => {
24059
+ DEFAULT_ENTITY_PATTERNS = {
24060
+ person: [
24061
+ /@([a-zA-Z0-9_-]+)/g,
24062
+ /\b(?:authored|reviewed|fixed|reported by)\s+([a-zA-Z0-9_-]+)/gi
24063
+ ],
24064
+ product: [
24065
+ /\b(?:Next\.js|React|TypeScript|Node\.js|Bun|Vercel|Anthropic|OpenAI|PostgreSQL|Redis|Docker|Kubernetes|GraphQL|REST|gRPC|WebAssembly|WASM|Tailwind|ESLint|Prettier|Jest|Vitest|Playwright|Cypress)\b/gi,
24066
+ /\b[a-zA-Z0-9_-]+\.js\b/gi
24067
+ ],
24068
+ organization: [
24069
+ /\b(?:Vercel|Anthropic|OpenAI|Google|Microsoft|GitHub|GitLab|AWS|GCP|Azure|Meta|Facebook|Amazon|Netflix|Shopify|Stripe|Supabase|PlanetScale|Neon|Turso)\b/gi
24070
+ ],
24071
+ file: [
24072
+ /(?:src|lib|test|docs|scripts)\/[a-zA-Z0-9_\/\.-]+\.(?:ts|tsx|js|jsx|json|yaml|yml|md|mdx)/g,
24073
+ /\b(?:package\.json|tsconfig\.json|eslint\.config|prettier\.config)\b/gi
24074
+ ],
24075
+ concept: [
24076
+ /\b(?:tree-indexed retrieval|wiki compilation|knapsack budgeting|progressive disclosure|semantic reasoning|vector search|BM25|hybrid search|entity extraction|memory lifecycle|consolidation|distillation)\b/gi
24077
+ ]
24078
+ };
24079
+ });
24080
+
24081
+ // src/entities/index.ts
24082
+ var init_entities = __esm(() => {
24083
+ init_extractor();
24084
+ });
24085
+ // src/pageindex/engine.ts
24086
+ import { existsSync as existsSync23, mkdirSync as mkdirSync12, readFileSync as readFileSync21, writeFileSync as writeFileSync12, rmSync as rmSync2, readdirSync as readdirSync8 } from "node:fs";
24087
+ import { join as join22 } from "node:path";
24088
+ function slugify4(text) {
24089
+ return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 50);
24090
+ }
24091
+ function buildPageIndex(content, options) {
24092
+ const secrets = scanSecrets(content);
24093
+ if (secrets.length > 0) {
24094
+ throw new Error(`Probable secret detected in PageIndex input: ${secrets.join(", ")}`);
24095
+ }
24096
+ const project = options.project;
24097
+ const title = options.title || content.slice(0, 50).trim() || "Untitled Document";
24098
+ const maxDepth = options.maxDepth ?? 5;
24099
+ const indexId = `idx_${Date.now()}_${slugify4(title) || "doc"}`;
24100
+ const now = new Date().toISOString();
24101
+ const lines = content.split(`
24102
+ `);
24103
+ const rootNode = {
24104
+ id: "node_root",
24105
+ title,
24106
+ summary: content.slice(0, 200).trim(),
24107
+ content: content.slice(0, 500).trim(),
24108
+ path: title,
24109
+ depth: 0,
24110
+ children: [],
24111
+ citations: [{ doc: title, line: 1 }]
24112
+ };
24113
+ const stack = [{ node: rootNode, level: 0 }];
24114
+ let totalNodes = 1;
24115
+ let lineNumber = 0;
24116
+ for (const line of lines) {
24117
+ lineNumber++;
24118
+ const headerMatch = line.match(/^(#{1,6})\s+(.+)$/);
24119
+ if (headerMatch) {
24120
+ const level = headerMatch[1].length;
24121
+ const hTitle = headerMatch[2].trim();
24122
+ if (level === 1 && stack.length === 1 && (hTitle.toLowerCase() === title.toLowerCase() || title === "Untitled Document")) {
24123
+ stack[0].level = 1;
24124
+ stack[0].node.title = hTitle;
24125
+ continue;
24126
+ }
24127
+ while (stack.length > 1 && stack[stack.length - 1].level >= level) {
24128
+ stack.pop();
24129
+ }
24130
+ const parent = stack[stack.length - 1].node;
24131
+ const childNode = {
24132
+ id: `node_${totalNodes++}`,
24133
+ title: hTitle,
24134
+ summary: "",
24135
+ content: "",
24136
+ path: `${parent.path} > ${hTitle}`,
24137
+ depth: Math.min(level, maxDepth),
24138
+ children: [],
24139
+ citations: [{ doc: title, line: lineNumber }]
24140
+ };
24141
+ parent.children.push(childNode);
24142
+ stack.push({ node: childNode, level });
24143
+ } else {
24144
+ const current = stack[stack.length - 1].node;
24145
+ if (line.trim().length > 0) {
24146
+ current.content = (current.content ? current.content + `
24147
+ ` : "") + line;
24148
+ if (!current.summary) {
24149
+ current.summary = line.slice(0, 150).trim();
24150
+ }
24151
+ }
24152
+ }
24153
+ }
24154
+ const doc2 = {
24155
+ id: indexId,
24156
+ title,
24157
+ project,
24158
+ builtAt: now,
24159
+ depth: Math.min(stack.length, maxDepth),
24160
+ totalNodes,
24161
+ root: rootNode
24162
+ };
24163
+ if (options.memoryDir && !options.dryRun) {
24164
+ const dir = join22(options.memoryDir, "pageindex", project);
24165
+ mkdirSync12(dir, { recursive: true });
24166
+ writeFileSync12(join22(dir, `${indexId}.json`), JSON.stringify(doc2, null, 2), "utf8");
24167
+ }
24168
+ return doc2;
24169
+ }
24170
+ function searchPageIndex(doc2, options) {
24171
+ const query = options.query;
24172
+ const maxNodes = options.maxNodes ?? 50;
24173
+ const tokenBudget = options.tokenBudget ?? 4000;
24174
+ const queryTokens = new Set(tokenize(query));
24175
+ const scoredNodes = [];
24176
+ let totalNodesSearched = 0;
24177
+ function traverse(node) {
24178
+ totalNodesSearched++;
24179
+ const haystack = tokenize(`${node.title} ${node.summary} ${node.content} ${node.path}`);
24180
+ const haySet = new Set(haystack);
24181
+ let overlap = 0;
24182
+ for (const t of queryTokens) {
24183
+ if (haySet.has(t)) {
24184
+ overlap++;
24185
+ } else {
24186
+ const matchedStem = haystack.some((h) => h.length >= 3 && t.length >= 3 && (h.startsWith(t.slice(0, 4)) || t.startsWith(h.slice(0, 4))));
24187
+ if (matchedStem)
24188
+ overlap += 0.8;
24189
+ }
24190
+ }
24191
+ const baseScore = queryTokens.size > 0 ? overlap / queryTokens.size : 0;
24192
+ const depthBonus = node.depth > 0 ? 0.1 * Math.min(node.depth, 3) : 0;
24193
+ const score = baseScore > 0 ? baseScore + depthBonus : 0;
24194
+ if (score > 0.05) {
24195
+ scoredNodes.push({ node, score });
24196
+ }
24197
+ for (const child of node.children) {
24198
+ traverse(child);
24199
+ }
24200
+ }
24201
+ traverse(doc2.root);
24202
+ scoredNodes.sort((a, b) => b.score - a.score);
24203
+ const matched = scoredNodes.slice(0, maxNodes);
24204
+ let tokensUsed = 0;
24205
+ const results = [];
24206
+ for (const item of matched) {
24207
+ const approxTokens = Math.max(10, Math.ceil((item.node.title.length + item.node.summary.length + item.node.content.length) / 4));
24208
+ if (tokensUsed + approxTokens > tokenBudget && results.length > 0)
24209
+ break;
24210
+ results.push({
24211
+ nodeId: item.node.id,
24212
+ title: item.node.title,
24213
+ summary: item.node.summary || item.node.title,
24214
+ path: item.node.path,
24215
+ score: Number(item.score.toFixed(2)),
24216
+ citations: item.node.citations
24217
+ });
24218
+ tokensUsed += approxTokens;
24219
+ }
24220
+ const topMatch = results[0];
24221
+ const reasoning = topMatch ? `Query matches "${query}". Tree traversal found relevant node "${topMatch.title}" along path "${topMatch.path}" with relevance score ${topMatch.score}.` : `No high-confidence nodes found matching query "${query}".`;
24222
+ return {
24223
+ results,
24224
+ reasoning,
24225
+ totalNodesSearched,
24226
+ tokensUsed
24227
+ };
24228
+ }
24229
+ function loadPageIndex(memoryDir, project, indexId) {
24230
+ const filePath = join22(memoryDir, "pageindex", project, `${indexId}.json`);
24231
+ if (!existsSync23(filePath))
24232
+ return null;
24233
+ try {
24234
+ return JSON.parse(readFileSync21(filePath, "utf8"));
24235
+ } catch {
24236
+ return null;
24237
+ }
24238
+ }
24239
+ function deletePageIndex(memoryDir, project, indexId) {
24240
+ const base = join22(memoryDir, "pageindex");
24241
+ if (!existsSync23(base))
24242
+ return { deletedCount: 0 };
24243
+ let count = 0;
24244
+ if (!project && !indexId) {
24245
+ rmSync2(base, { recursive: true, force: true });
24246
+ return { deletedCount: 1 };
24247
+ }
24248
+ if (project && !indexId) {
24249
+ const pDir = join22(base, project);
24250
+ if (existsSync23(pDir)) {
24251
+ rmSync2(pDir, { recursive: true, force: true });
24252
+ count++;
24253
+ }
24254
+ } else if (project && indexId) {
24255
+ const file = join22(base, project, `${indexId}.json`);
24256
+ if (existsSync23(file)) {
24257
+ rmSync2(file, { force: true });
24258
+ count++;
24259
+ }
24260
+ }
24261
+ return { deletedCount: count };
24262
+ }
24263
+ var init_engine2 = __esm(() => {
24264
+ init_secrets();
24265
+ init_retrieval();
24266
+ });
24267
+
24268
+ // src/pageindex/index.ts
24269
+ var init_pageindex = __esm(() => {
24270
+ init_engine2();
24271
+ });
24272
+ // src/settings/defaults.ts
24273
+ var DEFAULT_SETTINGS;
24274
+ var init_defaults = __esm(() => {
24275
+ DEFAULT_SETTINGS = {
24276
+ version: 1,
24277
+ retrieval: {
24278
+ defaultMode: "hybrid",
24279
+ defaultTokenBudget: 2000,
24280
+ defaultDisclosureDepth: "L2",
24281
+ treeMaxDepth: 5,
24282
+ enableLLMReasoning: false,
24283
+ hybridVectorWeight: 0.5,
24284
+ hybridTreeWeight: 0.5
24285
+ },
24286
+ wiki: {
24287
+ autoCompile: false,
24288
+ compileIntervalMinutes: 60,
24289
+ minClusterSize: 3,
24290
+ clusteringThreshold: 0.5,
24291
+ conceptOverlapThreshold: 0.3,
24292
+ includeTypes: ["fix", "decision", "architecture", "operation", "failure", "constraint", "preference", "discovery"],
24293
+ outputDir: "wiki",
24294
+ incremental: true
24295
+ },
24296
+ entities: {
24297
+ autoExtract: false,
24298
+ minMentionsForPage: 2,
24299
+ cooccurrenceThreshold: 2,
24300
+ enabledTypes: ["person", "product", "organization", "file", "concept"],
24301
+ customPatterns: {},
24302
+ aliasMap: {}
24303
+ },
24304
+ pageindex: {
24305
+ enabled: true,
24306
+ maxIndexesPerProject: 100,
24307
+ maxDepth: 5,
24308
+ enableLLMReasoning: false,
24309
+ localMode: true,
24310
+ storagePath: "pageindex"
24311
+ },
24312
+ ui: {
24313
+ defaultMode: "graph",
24314
+ graphLayout: "force",
24315
+ graphEngine: "auto",
24316
+ theme: "auto",
24317
+ animationEnabled: true,
24318
+ sidebarWidth: 380,
24319
+ detailPaneWidth: 420,
24320
+ autoRefresh: true,
24321
+ refreshIntervalMs: 30000
24322
+ },
24323
+ mcp: {
24324
+ enabledTools: [
24325
+ "memory_read",
24326
+ "get_context",
24327
+ "search",
24328
+ "memory_capture",
24329
+ "memory_harvest",
24330
+ "memory_import_transcript",
24331
+ "memory_search_transcripts",
24332
+ "memory_get_user_profile",
24333
+ "memory_set_user_profile",
24334
+ "memory_recall",
24335
+ "memory_confirm",
24336
+ "memory_supersede",
24337
+ "memory_link",
24338
+ "memory_mark_stale",
24339
+ "memory_reject",
24340
+ "memory_delete",
24341
+ "memory_audit",
24342
+ "memory_detect_providers",
24343
+ "memory_migrate",
24344
+ "memory_detect_agents",
24345
+ "memory_export",
24346
+ "memory_import",
24347
+ "memory_validate",
24348
+ "graph_status",
24349
+ "memory_core",
24350
+ "memory_consolidate",
24351
+ "memory_trace",
24352
+ "memory_loops",
24353
+ "memory_distill",
24354
+ "memory_verify",
24355
+ "memory_tree_search",
24356
+ "memory_wiki_get",
24357
+ "memory_wiki_search",
24358
+ "memory_wiki_compile",
24359
+ "memory_entities_get",
24360
+ "memory_entities_search",
24361
+ "memory_pageindex_index",
24362
+ "memory_pageindex_search",
24363
+ "memory_pageindex_import",
24364
+ "memory_disconnect_pageindex",
24365
+ "memory_settings_get",
24366
+ "memory_settings_set"
24367
+ ],
24368
+ pageindexEnabled: true,
24369
+ autoConnectAgents: false,
24370
+ defaultProject: "default",
24371
+ permissionsAutoApprove: false
24372
+ },
24373
+ skills: {
24374
+ autoDistill: false,
24375
+ minCount: 3,
24376
+ outputDir: ".agents/skills",
24377
+ dryRunByDefault: true
24378
+ },
24379
+ imports: {
24380
+ allowedProviders: ["agentmemory", "beads", "mem0", "letta", "everos"],
24381
+ secretScanEnabled: true,
24382
+ overwriteByDefault: false,
24383
+ dryRunByDefault: true
24384
+ },
24385
+ commands: {
24386
+ defaultProject: "default",
24387
+ confirmPrompt: true,
24388
+ verboseByDefault: false,
24389
+ outputFormat: "table"
24390
+ }
24391
+ };
24392
+ });
24393
+
24394
+ // src/settings/schema.ts
24395
+ function validateSafePath(path, context = "Path") {
24396
+ if (!path || typeof path !== "string") {
24397
+ throw new Error(`${context}: invalid or missing path`);
24398
+ }
24399
+ if (path.includes("..") || path.startsWith("/") || path.includes("\\")) {
24400
+ throw new Error(`${context}: path traversal not allowed ("${path}")`);
24401
+ }
24402
+ if (!SAFE_PATH_REGEX.test(path)) {
24403
+ throw new Error(`${context}: path contains invalid characters ("${path}")`);
24404
+ }
24405
+ }
24406
+ function validateSettings(settings) {
24407
+ const errors3 = [];
24408
+ if (settings.retrieval) {
24409
+ const r = settings.retrieval;
24410
+ if (r.defaultMode && !["tree", "vector", "hybrid"].includes(r.defaultMode)) {
24411
+ errors3.push(`retrieval.defaultMode must be one of 'tree', 'vector', 'hybrid'`);
24412
+ }
24413
+ if (r.defaultTokenBudget !== undefined && (r.defaultTokenBudget <= 0 || !Number.isInteger(r.defaultTokenBudget))) {
24414
+ errors3.push(`retrieval.defaultTokenBudget must be a positive integer`);
24415
+ }
24416
+ if (r.defaultDisclosureDepth && !["L1", "L2", "L3"].includes(r.defaultDisclosureDepth)) {
24417
+ errors3.push(`retrieval.defaultDisclosureDepth must be one of 'L1', 'L2', 'L3'`);
24418
+ }
24419
+ if (r.hybridVectorWeight !== undefined && r.hybridTreeWeight !== undefined) {
24420
+ if (Math.abs(r.hybridVectorWeight + r.hybridTreeWeight - 1) > 0.001) {
24421
+ errors3.push(`retrieval weights (hybridVectorWeight + hybridTreeWeight) must sum to 1.0`);
24422
+ }
24423
+ }
24424
+ }
24425
+ if (settings.wiki) {
24426
+ const w = settings.wiki;
24427
+ if (w.outputDir) {
24428
+ try {
24429
+ validateSafePath(w.outputDir, "wiki.outputDir");
24430
+ } catch (err) {
24431
+ errors3.push(err.message);
24432
+ }
24433
+ }
24434
+ if (w.minClusterSize !== undefined && w.minClusterSize <= 0) {
24435
+ errors3.push(`wiki.minClusterSize must be positive`);
24436
+ }
24437
+ }
24438
+ if (settings.pageindex) {
24439
+ const p = settings.pageindex;
24440
+ if (p.storagePath) {
24441
+ try {
24442
+ validateSafePath(p.storagePath, "pageindex.storagePath");
24443
+ } catch (err) {
24444
+ errors3.push(err.message);
24445
+ }
24446
+ }
24447
+ }
24448
+ if (settings.ui) {
24449
+ const u = settings.ui;
24450
+ if (u.defaultMode && !["tree", "graph", "timeline", "cluster"].includes(u.defaultMode)) {
24451
+ errors3.push(`ui.defaultMode must be 'tree', 'graph', 'timeline', or 'cluster'`);
24452
+ }
24453
+ if (u.graphEngine && !["barnes-hut", "webgl", "auto"].includes(u.graphEngine)) {
24454
+ errors3.push(`ui.graphEngine must be 'barnes-hut', 'webgl', or 'auto'`);
24455
+ }
24456
+ }
24457
+ return {
24458
+ valid: errors3.length === 0,
24459
+ errors: errors3
24460
+ };
24461
+ }
24462
+ var SAFE_PATH_REGEX;
24463
+ var init_schema2 = __esm(() => {
24464
+ SAFE_PATH_REGEX = /^[a-zA-Z0-9_\/\.-]+$/;
24465
+ });
24466
+
24467
+ // src/settings/loader.ts
24468
+ import { existsSync as existsSync24, mkdirSync as mkdirSync13, readFileSync as readFileSync22, writeFileSync as writeFileSync13 } from "node:fs";
24469
+ import { join as join23 } from "node:path";
24470
+ function getSettingsFilePath(memoryDir) {
24471
+ return join23(memoryDir, "settings.json");
24472
+ }
24473
+ function loadSettings(memoryDir) {
24474
+ const filePath = getSettingsFilePath(memoryDir);
24475
+ if (!existsSync24(filePath)) {
24476
+ return {
24477
+ version: 1,
24478
+ global: JSON.parse(JSON.stringify(DEFAULT_SETTINGS)),
24479
+ projects: {}
24480
+ };
24481
+ }
24482
+ try {
24483
+ const raw = readFileSync22(filePath, "utf8");
24484
+ const parsed = JSON.parse(raw);
24485
+ return {
24486
+ version: parsed.version || 1,
24487
+ global: { ...DEFAULT_SETTINGS, ...parsed.global || {} },
24488
+ projects: parsed.projects || {}
24489
+ };
24490
+ } catch {
24491
+ return {
24492
+ version: 1,
24493
+ global: JSON.parse(JSON.stringify(DEFAULT_SETTINGS)),
24494
+ projects: {}
24495
+ };
24496
+ }
24497
+ }
24498
+ function saveSettings(store, memoryDir) {
24499
+ mkdirSync13(memoryDir, { recursive: true });
24500
+ const filePath = getSettingsFilePath(memoryDir);
24501
+ writeFileSync13(filePath, JSON.stringify(store, null, 2), "utf8");
24502
+ }
24503
+ function getSettings(memoryDir) {
24504
+ return loadSettings(memoryDir).global;
24505
+ }
24506
+ function setSettings(memoryDir, partial2) {
24507
+ const check = validateSettings(partial2);
24508
+ if (!check.valid) {
24509
+ throw new Error(`Invalid settings: ${check.errors.join("; ")}`);
24510
+ }
24511
+ const store = loadSettings(memoryDir);
24512
+ store.global = deepMerge(store.global, partial2);
24513
+ saveSettings(store, memoryDir);
24514
+ return store.global;
24515
+ }
24516
+ function getProjectSettings(memoryDir, project) {
24517
+ const store = loadSettings(memoryDir);
24518
+ const proj = store.projects[project] ?? { project };
24519
+ return { ...store.global, ...proj, project };
24520
+ }
24521
+ function setProjectSettings(memoryDir, project, partial2) {
24522
+ const check = validateSettings(partial2);
24523
+ if (!check.valid) {
24524
+ throw new Error(`Invalid project settings: ${check.errors.join("; ")}`);
24525
+ }
24526
+ const store = loadSettings(memoryDir);
24527
+ const existing = store.projects[project] ?? { project };
24528
+ store.projects[project] = deepMerge(existing, partial2);
24529
+ saveSettings(store, memoryDir);
24530
+ return store.projects[project];
24531
+ }
24532
+ function resetSettings(memoryDir) {
24533
+ const store = loadSettings(memoryDir);
24534
+ store.global = JSON.parse(JSON.stringify(DEFAULT_SETTINGS));
24535
+ saveSettings(store, memoryDir);
24536
+ return store.global;
24537
+ }
24538
+ function resetProjectSettings(memoryDir, project) {
24539
+ const store = loadSettings(memoryDir);
24540
+ delete store.projects[project];
24541
+ saveSettings(store, memoryDir);
24542
+ }
24543
+ function exportSettings(memoryDir) {
24544
+ const store = loadSettings(memoryDir);
24545
+ return JSON.stringify(store, null, 2);
24546
+ }
24547
+ function importSettings(memoryDir, json2) {
24548
+ const parsed = JSON.parse(json2);
24549
+ if (!parsed || typeof parsed !== "object") {
24550
+ throw new Error("Invalid settings payload: expected object");
24551
+ }
24552
+ const store = loadSettings(memoryDir);
24553
+ if (parsed.global) {
24554
+ const check = validateSettings(parsed.global);
24555
+ if (!check.valid) {
24556
+ throw new Error(`Invalid global settings in import: ${check.errors.join("; ")}`);
24557
+ }
24558
+ store.global = deepMerge(store.global, parsed.global);
24559
+ }
24560
+ if (parsed.projects && typeof parsed.projects === "object") {
24561
+ store.projects = { ...store.projects, ...parsed.projects };
24562
+ }
24563
+ saveSettings(store, memoryDir);
24564
+ return store;
24565
+ }
24566
+ function deepMerge(target, source) {
24567
+ const result = { ...target };
24568
+ for (const key of Object.keys(source)) {
24569
+ const sVal = source[key];
24570
+ const tVal = target[key];
24571
+ if (sVal !== undefined) {
24572
+ if (typeof sVal === "object" && sVal !== null && !Array.isArray(sVal) && typeof tVal === "object" && tVal !== null && !Array.isArray(tVal)) {
24573
+ result[key] = deepMerge(tVal, sVal);
24574
+ } else {
24575
+ result[key] = sVal;
24576
+ }
24577
+ }
24578
+ }
24579
+ return result;
24580
+ }
24581
+ var init_loader = __esm(() => {
24582
+ init_defaults();
24583
+ init_schema2();
24584
+ });
24585
+
24586
+ // src/settings/watcher.ts
24587
+ var init_watcher = __esm(() => {
24588
+ init_loader();
24589
+ });
24590
+
24591
+ // src/settings/migration.ts
24592
+ var init_migration = () => {};
24593
+
24594
+ // src/settings/index.ts
24595
+ var init_settings = __esm(() => {
24596
+ init_defaults();
24597
+ init_schema2();
24598
+ init_loader();
24599
+ init_watcher();
24600
+ init_migration();
24601
+ });
24602
+
24603
+ // src/settings.ts
24604
+ var init_settings2 = __esm(() => {
24605
+ init_settings();
24606
+ });
24607
+
24608
+ // src/mcp.ts
24609
+ var exports_mcp = {};
24610
+ __export(exports_mcp, {
24611
+ runMcpServer: () => runMcpServer
24612
+ });
24613
+ async function runMcpServer() {
24614
+ const targetDir = process.env.MUSE_MEMORY_PROJECT_DIR || process.env.PROJECT_ROOT || process.cwd();
24615
+ const { root, memoryDir } = findOrCreateProjectRoot(targetDir);
24616
+ const store = openStore(memoryDir);
24617
+ const server = new Server({ name: "musememory", version: "1.2.0" }, { capabilities: { tools: {} } });
24618
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
24619
+ tools: [
24620
+ {
24621
+ name: "memory_read",
24622
+ description: "Read a full memory entry by id",
24623
+ inputSchema: {
24624
+ type: "object",
24625
+ properties: { id: { type: "string" } },
24626
+ required: ["id"]
24627
+ }
24628
+ },
24629
+ {
24630
+ name: "get_context",
24631
+ description: "Ranked active context entries for prompt injection (with optional token budget)",
24632
+ inputSchema: {
24633
+ type: "object",
24634
+ properties: {
24635
+ query: { type: "string" },
24636
+ project: { type: "string" },
24637
+ limit: { type: "number" },
24638
+ token_budget: { type: "number", description: "Maximum token budget to consume for retrieved context" },
24639
+ type: { type: "string" },
24640
+ status: { type: "string" },
24641
+ verified: { type: "boolean" },
24642
+ depth: { type: "string", enum: ["L1", "L2", "L3"], description: "Progressive disclosure tier: L1 = id+title lines, L2 = title+content+tags (default), L3 = full raw entry" }
24643
+ }
24644
+ }
24645
+ },
24646
+ {
24647
+ name: "search",
24648
+ description: "Ranked search over memory entries",
24649
+ inputSchema: {
24650
+ type: "object",
24651
+ properties: {
24652
+ query: { type: "string" },
24653
+ limit: { type: "number" },
24654
+ token_budget: { type: "number", description: "Maximum token budget to consume" },
24655
+ include_superseded: { type: "boolean" },
24656
+ hybrid: { type: "boolean", description: "Use the offline vector+BM25 index (requires 'memory reindex'); falls back to live scoring when absent" },
24657
+ type: { type: "string" },
24658
+ status: { type: "string" },
24659
+ verified: { type: "boolean" }
24660
+ },
24661
+ required: ["query"]
24662
+ }
24663
+ },
24664
+ {
24665
+ name: "memory_capture",
24666
+ description: "Create a new memory entry with inline secret scan (refuses probable secrets)",
24667
+ inputSchema: {
24668
+ type: "object",
24669
+ properties: {
24670
+ content: { type: "string" },
24671
+ project: { type: "string" },
24672
+ title: { type: "string" },
24673
+ tags: { type: "array", items: { type: "string" } },
24674
+ type: { type: "string" },
24675
+ confirmed: { type: "boolean" }
24676
+ },
24677
+ required: ["content", "project"]
24678
+ }
24679
+ },
24680
+ {
24681
+ name: "memory_harvest",
22743
24682
  description: "Distill conversation/text into structured outcome, fix, decision, and failure memories",
22744
24683
  inputSchema: {
22745
24684
  type: "object",
@@ -23052,6 +24991,157 @@ async function runMcpServer() {
23052
24991
  type: "object",
23053
24992
  properties: {}
23054
24993
  }
24994
+ },
24995
+ {
24996
+ name: "memory_tree_search",
24997
+ description: "Hierarchical tree-indexed reasoning search across partitioned memory shards",
24998
+ inputSchema: {
24999
+ type: "object",
25000
+ properties: {
25001
+ query: { type: "string", description: "Search query" },
25002
+ project: { type: "string", description: "Filter by project" },
25003
+ type: { type: "string", description: "Filter by memory type" },
25004
+ token_budget: { type: "number", description: "Token budget limit" },
25005
+ disclosure_depth: { type: "string", enum: ["L1", "L2", "L3"], description: "Disclosure depth tier" },
25006
+ max_nodes: { type: "number", description: "Maximum nodes to return" }
25007
+ },
25008
+ required: ["query"]
25009
+ }
25010
+ },
25011
+ {
25012
+ name: "memory_wiki_get",
25013
+ description: "Read a compiled wiki page (concept, entity, index, or log)",
25014
+ inputSchema: {
25015
+ type: "object",
25016
+ properties: {
25017
+ slug: { type: "string", description: "Page slug (e.g. 'index', 'log', or concept slug)" },
25018
+ type: { type: "string", enum: ["concept", "entity", "index", "log"], description: "Optional page type" }
25019
+ },
25020
+ required: ["slug"]
25021
+ }
25022
+ },
25023
+ {
25024
+ name: "memory_wiki_search",
25025
+ description: "List compiled wiki pages with optional filtering",
25026
+ inputSchema: {
25027
+ type: "object",
25028
+ properties: {
25029
+ project: { type: "string", description: "Filter by project" },
25030
+ type: { type: "string", enum: ["concept", "entity", "index", "log"], description: "Filter by page type" }
25031
+ }
25032
+ }
25033
+ },
25034
+ {
25035
+ name: "memory_wiki_compile",
25036
+ description: "Compile confirmed memories into structured wiki markdown pages",
25037
+ inputSchema: {
25038
+ type: "object",
25039
+ properties: {
25040
+ project: { type: "string", description: "Project to compile (omit for all)" },
25041
+ dry_run: { type: "boolean", description: "Preview without writing to disk" }
25042
+ }
25043
+ }
25044
+ },
25045
+ {
25046
+ name: "memory_entities_get",
25047
+ description: "Get detailed information about an extracted entity and its relationships",
25048
+ inputSchema: {
25049
+ type: "object",
25050
+ properties: {
25051
+ id: { type: "string", description: "Entity ID or name" },
25052
+ include_related: { type: "boolean", description: "Include related entities in response" }
25053
+ },
25054
+ required: ["id"]
25055
+ }
25056
+ },
25057
+ {
25058
+ name: "memory_entities_search",
25059
+ description: "List extracted entities by type or project",
25060
+ inputSchema: {
25061
+ type: "object",
25062
+ properties: {
25063
+ type: { type: "string", enum: ["person", "product", "organization", "file", "concept"], description: "Filter by entity type" },
25064
+ project: { type: "string", description: "Filter by project" }
25065
+ }
25066
+ }
25067
+ },
25068
+ {
25069
+ name: "memory_pageindex_index",
25070
+ description: "Build a PageIndex-style hierarchical tree index from document/text for reasoning-based retrieval",
25071
+ inputSchema: {
25072
+ type: "object",
25073
+ properties: {
25074
+ content: { type: "string", description: "Document text content (max 10MB)" },
25075
+ project: { type: "string", description: "Project to associate the index with" },
25076
+ title: { type: "string", description: "Optional title for the index" },
25077
+ maxDepth: { type: "number", description: "Max tree depth (default: 5)" },
25078
+ dryRun: { type: "boolean", description: "Preview without persisting" }
25079
+ },
25080
+ required: ["content", "project"]
25081
+ }
25082
+ },
25083
+ {
25084
+ name: "memory_pageindex_search",
25085
+ description: "Search a PageIndex tree index with reasoning-based retrieval",
25086
+ inputSchema: {
25087
+ type: "object",
25088
+ properties: {
25089
+ indexId: { type: "string", description: "Tree index ID to search" },
25090
+ query: { type: "string", description: "Search query" },
25091
+ project: { type: "string", description: "Project scope" },
25092
+ tokenBudget: { type: "number", description: "Maximum token budget" },
25093
+ maxDepth: { type: "number", description: "Max search depth" }
25094
+ },
25095
+ required: ["indexId", "query"]
25096
+ }
25097
+ },
25098
+ {
25099
+ name: "memory_pageindex_import",
25100
+ description: "Import PageIndex search results/insights as memory entries",
25101
+ inputSchema: {
25102
+ type: "object",
25103
+ properties: {
25104
+ indexId: { type: "string", description: "Tree index ID" },
25105
+ query: { type: "string", description: "Search query" },
25106
+ project: { type: "string", description: "Project scope" },
25107
+ type: { type: "string", description: "Memory type (default: discovery)" },
25108
+ confirmed: { type: "boolean", description: "Auto-confirm imported entries" }
25109
+ },
25110
+ required: ["indexId", "query", "project"]
25111
+ }
25112
+ },
25113
+ {
25114
+ name: "memory_disconnect_pageindex",
25115
+ description: "Disconnect PageIndex MCP tools and remove associated indexes",
25116
+ inputSchema: {
25117
+ type: "object",
25118
+ properties: {
25119
+ indexId: { type: "string", description: "Specific index to remove, or omit for all" },
25120
+ project: { type: "string", description: "Project scope" }
25121
+ }
25122
+ }
25123
+ },
25124
+ {
25125
+ name: "memory_settings_get",
25126
+ description: "Read unified global or project configuration settings",
25127
+ inputSchema: {
25128
+ type: "object",
25129
+ properties: {
25130
+ project: { type: "string", description: "Optional project scope override" }
25131
+ }
25132
+ }
25133
+ },
25134
+ {
25135
+ name: "memory_settings_set",
25136
+ description: "Update unified global or project configuration settings",
25137
+ inputSchema: {
25138
+ type: "object",
25139
+ properties: {
25140
+ settings: { type: "object", description: "Settings object to merge" },
25141
+ project: { type: "string", description: "Optional project scope override" }
25142
+ },
25143
+ required: ["settings"]
25144
+ }
23055
25145
  }
23056
25146
  ]
23057
25147
  }));
@@ -23341,6 +25431,128 @@ Resolution: ${String(a.resolution)}`;
23341
25431
  return toolError(err instanceof Error ? err.message : String(err));
23342
25432
  }
23343
25433
  }
25434
+ case "memory_tree_search": {
25435
+ let index = loadTreeIndex(memoryDir);
25436
+ if (!index) {
25437
+ index = buildTreeIndex(store, memoryDir);
25438
+ }
25439
+ const res = searchTree(index, {
25440
+ query: String(a.query),
25441
+ project: a.project ? String(a.project) : undefined,
25442
+ type: a.type ? String(a.type) : undefined,
25443
+ tokenBudget: typeof a.token_budget === "number" ? a.token_budget : undefined,
25444
+ disclosureDepth: a.disclosure_depth ? String(a.disclosure_depth) : undefined,
25445
+ maxNodes: typeof a.max_nodes === "number" ? a.max_nodes : undefined
25446
+ });
25447
+ return toolResult(res);
25448
+ }
25449
+ case "memory_wiki_get": {
25450
+ const page = getWikiPage(memoryDir, String(a.slug), a.type ? String(a.type) : undefined);
25451
+ if (!page)
25452
+ return toolError(`Wiki page '${a.slug}' not found.`);
25453
+ return toolResult(page);
25454
+ }
25455
+ case "memory_wiki_search": {
25456
+ const pages = listWikiPages(memoryDir, {
25457
+ project: a.project ? String(a.project) : undefined,
25458
+ type: a.type ? String(a.type) : undefined
25459
+ });
25460
+ return toolResult({ pages, count: pages.length });
25461
+ }
25462
+ case "memory_wiki_compile": {
25463
+ const res = compileWiki(store, memoryDir, {
25464
+ project: a.project ? String(a.project) : undefined,
25465
+ dryRun: a.dry_run === true
25466
+ });
25467
+ return toolResult(res);
25468
+ }
25469
+ case "memory_entities_get": {
25470
+ const ent = findEntity(memoryDir, String(a.id));
25471
+ if (!ent)
25472
+ return toolError(`Entity '${a.id}' not found.`);
25473
+ if (a.include_related === true) {
25474
+ const rel = findRelatedEntities(memoryDir, String(a.id));
25475
+ return toolResult({ entity: ent, related: rel });
25476
+ }
25477
+ return toolResult(ent);
25478
+ }
25479
+ case "memory_entities_search": {
25480
+ let entities = loadEntities(memoryDir);
25481
+ if (a.type)
25482
+ entities = entities.filter((e) => e.type === a.type);
25483
+ if (a.project)
25484
+ entities = entities.filter((e) => !e.project || e.project === a.project);
25485
+ return toolResult({ entities, count: entities.length });
25486
+ }
25487
+ case "memory_pageindex_index": {
25488
+ try {
25489
+ const doc2 = buildPageIndex(String(a.content), {
25490
+ project: String(a.project),
25491
+ title: a.title ? String(a.title) : undefined,
25492
+ maxDepth: typeof a.maxDepth === "number" ? a.maxDepth : undefined,
25493
+ dryRun: a.dryRun === true,
25494
+ memoryDir
25495
+ });
25496
+ return toolResult(doc2);
25497
+ } catch (err) {
25498
+ return toolError(err instanceof Error ? err.message : String(err));
25499
+ }
25500
+ }
25501
+ case "memory_pageindex_search": {
25502
+ const project = a.project ? String(a.project) : "default";
25503
+ const doc2 = loadPageIndex(memoryDir, project, String(a.indexId));
25504
+ if (!doc2)
25505
+ return toolError(`PageIndex '${a.indexId}' not found for project '${project}'`);
25506
+ const res = searchPageIndex(doc2, {
25507
+ query: String(a.query),
25508
+ maxDepth: typeof a.maxDepth === "number" ? a.maxDepth : undefined,
25509
+ maxNodes: typeof a.maxNodes === "number" ? a.maxNodes : undefined,
25510
+ tokenBudget: typeof a.tokenBudget === "number" ? a.tokenBudget : undefined
25511
+ });
25512
+ return toolResult(res);
25513
+ }
25514
+ case "memory_pageindex_import": {
25515
+ const project = String(a.project);
25516
+ const doc2 = loadPageIndex(memoryDir, project, String(a.indexId));
25517
+ if (!doc2)
25518
+ return toolError(`PageIndex '${a.indexId}' not found for project '${project}'`);
25519
+ const search = searchPageIndex(doc2, { query: String(a.query), maxNodes: 5 });
25520
+ const imported = [];
25521
+ for (const item of search.results) {
25522
+ const entry = proposeMemory(store, {
25523
+ project,
25524
+ title: item.title,
25525
+ content: `${item.summary}
25526
+
25527
+ Path: ${item.path}`,
25528
+ type: a.type ? String(a.type) : "discovery",
25529
+ confirmed: a.confirmed === true
25530
+ });
25531
+ imported.push(entry);
25532
+ }
25533
+ return toolResult({ importedCount: imported.length, entries: imported });
25534
+ }
25535
+ case "memory_disconnect_pageindex": {
25536
+ const res = deletePageIndex(memoryDir, a.project ? String(a.project) : undefined, a.indexId ? String(a.indexId) : undefined);
25537
+ return toolResult({ success: true, deletedIndexes: res.deletedCount });
25538
+ }
25539
+ case "memory_settings_get": {
25540
+ const settings2 = a.project ? getProjectSettings(memoryDir, String(a.project)) : getSettings(memoryDir);
25541
+ return toolResult(settings2);
25542
+ }
25543
+ case "memory_settings_set": {
25544
+ try {
25545
+ if (a.project) {
25546
+ const updated = setProjectSettings(memoryDir, String(a.project), a.settings);
25547
+ return toolResult(updated);
25548
+ } else {
25549
+ const updated = setSettings(memoryDir, a.settings);
25550
+ return toolResult(updated);
25551
+ }
25552
+ } catch (err) {
25553
+ return toolError(err instanceof Error ? err.message : String(err));
25554
+ }
25555
+ }
23344
25556
  default:
23345
25557
  return toolError(`unknown tool ${name}`);
23346
25558
  }
@@ -23394,6 +25606,11 @@ var init_mcp = __esm(() => {
23394
25606
  init_migrator();
23395
25607
  init_detect2();
23396
25608
  init_connect();
25609
+ init_retrieval3();
25610
+ init_wiki();
25611
+ init_entities();
25612
+ init_pageindex();
25613
+ init_settings2();
23397
25614
  });
23398
25615
 
23399
25616
  // src/daemon.ts
@@ -23402,8 +25619,8 @@ __export(exports_daemon, {
23402
25619
  startHub: () => startHub
23403
25620
  });
23404
25621
  import { createServer as createServer2 } from "node:http";
23405
- import { existsSync as existsSync20 } from "node:fs";
23406
- import { join as join19 } from "node:path";
25622
+ import { existsSync as existsSync25 } from "node:fs";
25623
+ import { join as join24 } from "node:path";
23407
25624
  import { watch } from "node:fs";
23408
25625
  function startHub(port, memoryDir) {
23409
25626
  const clients = new Set;
@@ -23469,7 +25686,7 @@ data: ${JSON.stringify(event)}
23469
25686
  return clients.size;
23470
25687
  }
23471
25688
  if (memoryDir) {
23472
- const memoriesDir = join19(memoryDir, "memories");
25689
+ const memoriesDir = join24(memoryDir, "memories");
23473
25690
  const armDebounced = (type2) => {
23474
25691
  if (debounceTimer)
23475
25692
  clearTimeout(debounceTimer);
@@ -23478,11 +25695,11 @@ data: ${JSON.stringify(event)}
23478
25695
  }, DEBOUNCE_MS);
23479
25696
  };
23480
25697
  try {
23481
- if (existsSync20(memoriesDir)) {
25698
+ if (existsSync25(memoriesDir)) {
23482
25699
  watchers.push(watch(memoriesDir, () => armDebounced("memory.changed")));
23483
25700
  }
23484
- const currentMd = join19(memoryDir, "CURRENT.md");
23485
- if (existsSync20(currentMd)) {
25701
+ const currentMd = join24(memoryDir, "CURRENT.md");
25702
+ if (existsSync25(currentMd)) {
23486
25703
  watchers.push(watch(currentMd, () => armDebounced("constraints.changed")));
23487
25704
  }
23488
25705
  } catch {}
@@ -23515,22 +25732,22 @@ var DEBOUNCE_MS = 300;
23515
25732
  var init_daemon = () => {};
23516
25733
 
23517
25734
  // src/cli/ecosystem.ts
23518
- import { join as join20 } from "node:path";
23519
- import { existsSync as existsSync21, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "node:fs";
25735
+ import { join as join25 } from "node:path";
25736
+ import { existsSync as existsSync26, mkdirSync as mkdirSync14, writeFileSync as writeFileSync14 } from "node:fs";
23520
25737
  async function handleInstallCommand({ positional, flags }) {
23521
25738
  const isGlobal = flags["global"] === "true" || flags["g"] === "true";
23522
- const targetDir = positional[0] ? join20(process.cwd(), positional[0]) : process.cwd();
23523
- const memoryDir = isGlobal ? getGlobalMemoryDir() : join20(targetDir, ".memory");
25739
+ const targetDir = positional[0] ? join25(process.cwd(), positional[0]) : process.cwd();
25740
+ const memoryDir = isGlobal ? getGlobalMemoryDir() : join25(targetDir, ".memory");
23524
25741
  const globalDir = getGlobalMemoryDir();
23525
- mkdirSync9(join20(memoryDir, "memories"), { recursive: true });
23526
- mkdirSync9(join20(globalDir, "memories"), { recursive: true });
23527
- const currentPath = join20(memoryDir, "CURRENT.md");
23528
- if (!existsSync21(currentPath)) {
23529
- writeFileSync9(currentPath, `# Active Project Constraints
25742
+ mkdirSync14(join25(memoryDir, "memories"), { recursive: true });
25743
+ mkdirSync14(join25(globalDir, "memories"), { recursive: true });
25744
+ const currentPath = join25(memoryDir, "CURRENT.md");
25745
+ if (!existsSync26(currentPath)) {
25746
+ writeFileSync14(currentPath, `# Active Project Constraints
23530
25747
  `, "utf8");
23531
25748
  }
23532
25749
  const globalUserPath = userFilePath(globalDir);
23533
- if (!existsSync21(globalUserPath)) {
25750
+ if (!existsSync26(globalUserPath)) {
23534
25751
  const { promptSingleSelect: promptSingleSelect2 } = await Promise.resolve().then(() => (init_prompt(), exports_prompt));
23535
25752
  const archetypeOptions = [
23536
25753
  { id: "developer", label: "Software Engineer / Developer", hint: "Code-first, direct, strict typing" },
@@ -23589,9 +25806,9 @@ async function handleUninstallCommand({ positional, flags }) {
23589
25806
  }
23590
25807
  if (purge) {
23591
25808
  const ctx = requireRoot(flags);
23592
- if (ctx && existsSync21(ctx.memoryDir) && !dryRun) {
23593
- const { rmSync } = await import("node:fs");
23594
- rmSync(ctx.memoryDir, { recursive: true, force: true });
25809
+ if (ctx && existsSync26(ctx.memoryDir) && !dryRun) {
25810
+ const { rmSync: rmSync3 } = await import("node:fs");
25811
+ rmSync3(ctx.memoryDir, { recursive: true, force: true });
23595
25812
  console.log(` [PURGED] Memory directory removed: ${ctx.memoryDir}`);
23596
25813
  }
23597
25814
  } else {
@@ -23602,13 +25819,13 @@ async function handleUninstallCommand({ positional, flags }) {
23602
25819
  }
23603
25820
  async function handleInitCommand({ positional, flags }) {
23604
25821
  const isGlobal = flags["global"] === "true";
23605
- const targetDir = positional[0] ? join20(process.cwd(), positional[0]) : process.cwd();
25822
+ const targetDir = positional[0] ? join25(process.cwd(), positional[0]) : process.cwd();
23606
25823
  const memoryDirName = flags["legacy"] === "true" ? ".musememory" : ".memory";
23607
- const memoryDir = isGlobal ? getGlobalMemoryDir() : join20(targetDir, memoryDirName);
23608
- mkdirSync9(join20(memoryDir, "memories"), { recursive: true });
23609
- const currentPath = join20(memoryDir, "CURRENT.md");
23610
- if (!existsSync21(currentPath)) {
23611
- writeFileSync9(currentPath, `# Active Project Constraints
25824
+ const memoryDir = isGlobal ? getGlobalMemoryDir() : join25(targetDir, memoryDirName);
25825
+ mkdirSync14(join25(memoryDir, "memories"), { recursive: true });
25826
+ const currentPath = join25(memoryDir, "CURRENT.md");
25827
+ if (!existsSync26(currentPath)) {
25828
+ writeFileSync14(currentPath, `# Active Project Constraints
23612
25829
  `, "utf8");
23613
25830
  }
23614
25831
  console.log(`Initialized memory store in ${memoryDir}`);
@@ -23833,28 +26050,28 @@ var init_ecosystem = __esm(() => {
23833
26050
 
23834
26051
  // src/hook.ts
23835
26052
  import {
23836
- existsSync as existsSync22,
23837
- readFileSync as readFileSync18,
23838
- writeFileSync as writeFileSync10,
23839
- mkdirSync as mkdirSync10,
23840
- readdirSync as readdirSync6,
26053
+ existsSync as existsSync27,
26054
+ readFileSync as readFileSync23,
26055
+ writeFileSync as writeFileSync15,
26056
+ mkdirSync as mkdirSync15,
26057
+ readdirSync as readdirSync9,
23841
26058
  statSync as statSync7,
23842
26059
  renameSync as renameSync2,
23843
26060
  chmodSync
23844
26061
  } from "node:fs";
23845
- import { join as join21, relative } from "node:path";
26062
+ import { join as join26, relative } from "node:path";
23846
26063
  function installGitHook(workspaceRoot) {
23847
- const gitDir = join21(workspaceRoot, ".git");
23848
- if (!existsSync22(gitDir)) {
26064
+ const gitDir = join26(workspaceRoot, ".git");
26065
+ if (!existsSync27(gitDir)) {
23849
26066
  return { installed: false, message: `no .git directory in ${workspaceRoot} — run inside a git repository` };
23850
26067
  }
23851
- const hooksDir = join21(gitDir, "hooks");
23852
- const hookPath = join21(hooksDir, "pre-commit");
23853
- if (existsSync22(hookPath)) {
26068
+ const hooksDir = join26(gitDir, "hooks");
26069
+ const hookPath = join26(hooksDir, "pre-commit");
26070
+ if (existsSync27(hookPath)) {
23854
26071
  return { installed: false, path: hookPath, message: `pre-commit hook already exists at ${hookPath} — leaving it untouched` };
23855
26072
  }
23856
- mkdirSync10(hooksDir, { recursive: true });
23857
- writeFileSync10(hookPath, HOOK_SCRIPT, "utf8");
26073
+ mkdirSync15(hooksDir, { recursive: true });
26074
+ writeFileSync15(hookPath, HOOK_SCRIPT, "utf8");
23858
26075
  chmodSync(hookPath, 493);
23859
26076
  return { installed: true, path: hookPath, message: `installed pre-commit hook at ${hookPath}` };
23860
26077
  }
@@ -23865,14 +26082,14 @@ function globToRegex(glob) {
23865
26082
  function walkFiles(dir, root, regex, out = []) {
23866
26083
  let entries;
23867
26084
  try {
23868
- entries = readdirSync6(dir, { withFileTypes: true });
26085
+ entries = readdirSync9(dir, { withFileTypes: true });
23869
26086
  } catch {
23870
26087
  return out;
23871
26088
  }
23872
26089
  for (const e of entries) {
23873
26090
  if (e.name === ".git" || e.name === "node_modules" || e.name === ".memory")
23874
26091
  continue;
23875
- const p = join21(dir, e.name);
26092
+ const p = join26(dir, e.name);
23876
26093
  if (e.isDirectory()) {
23877
26094
  walkFiles(p, root, regex, out);
23878
26095
  } else if (regex.test(relative(root, p))) {
@@ -23882,9 +26099,9 @@ function walkFiles(dir, root, regex, out = []) {
23882
26099
  return out;
23883
26100
  }
23884
26101
  function newestInboxJsonl(inboxDir) {
23885
- if (!existsSync22(inboxDir))
26102
+ if (!existsSync27(inboxDir))
23886
26103
  return null;
23887
- const files = readdirSync6(inboxDir).filter((f) => f.endsWith(".jsonl")).map((f) => join21(inboxDir, f)).filter((f) => statSync7(f).isFile());
26104
+ const files = readdirSync9(inboxDir).filter((f) => f.endsWith(".jsonl")).map((f) => join26(inboxDir, f)).filter((f) => statSync7(f).isFile());
23888
26105
  if (files.length === 0)
23889
26106
  return null;
23890
26107
  return files.sort((a, b) => statSync7(b).mtimeMs - statSync7(a).mtimeMs)[0];
@@ -23899,7 +26116,7 @@ function harvestAuto(store, workspaceRoot, memoryDir, options = {}) {
23899
26116
  return result;
23900
26117
  }
23901
26118
  } else {
23902
- const inboxDir = join21(memoryDir, "inbox");
26119
+ const inboxDir = join26(memoryDir, "inbox");
23903
26120
  const newest = newestInboxJsonl(inboxDir);
23904
26121
  if (!newest) {
23905
26122
  result.message = "no transcripts waiting in .memory/inbox/";
@@ -23907,20 +26124,20 @@ function harvestAuto(store, workspaceRoot, memoryDir, options = {}) {
23907
26124
  }
23908
26125
  files = [newest];
23909
26126
  }
23910
- const processedDir = join21(memoryDir, "inbox", "processed");
26127
+ const processedDir = join26(memoryDir, "inbox", "processed");
23911
26128
  for (const file of files) {
23912
26129
  try {
23913
- const content = readFileSync18(file, "utf8");
26130
+ const content = readFileSync23(file, "utf8");
23914
26131
  const res = importTranscript(store, content, {
23915
26132
  project: options.project ?? "inbox",
23916
26133
  confirmed: false,
23917
26134
  source: "harvest_auto"
23918
26135
  });
23919
- mkdirSync10(processedDir, { recursive: true });
26136
+ mkdirSync15(processedDir, { recursive: true });
23920
26137
  const base = file.split("/").pop() ?? "transcript.jsonl";
23921
- let dest = join21(processedDir, base);
23922
- if (existsSync22(dest)) {
23923
- dest = join21(processedDir, base.replace(/\.jsonl$/, `_moved_${Date.now()}.jsonl`));
26138
+ let dest = join26(processedDir, base);
26139
+ if (existsSync27(dest)) {
26140
+ dest = join26(processedDir, base.replace(/\.jsonl$/, `_moved_${Date.now()}.jsonl`));
23924
26141
  }
23925
26142
  renameSync2(file, dest);
23926
26143
  result.processed.push({ file, movedTo: dest, imported: res.imported });
@@ -23948,8 +26165,8 @@ var init_hook = __esm(() => {
23948
26165
  });
23949
26166
 
23950
26167
  // src/agentcontract.ts
23951
- import { existsSync as existsSync23 } from "node:fs";
23952
- import { join as join22 } from "node:path";
26168
+ import { existsSync as existsSync28 } from "node:fs";
26169
+ import { join as join27 } from "node:path";
23953
26170
  function parseAgentMemoryContract(markdown) {
23954
26171
  if (!markdown || !markdown.startsWith("---"))
23955
26172
  return null;
@@ -23981,17 +26198,17 @@ function parseAgentMemoryContract(markdown) {
23981
26198
  function resolveAgentFile(nameOrPath, workspaceRoot) {
23982
26199
  if (!nameOrPath)
23983
26200
  return null;
23984
- if (existsSync23(nameOrPath))
26201
+ if (existsSync28(nameOrPath))
23985
26202
  return nameOrPath;
23986
26203
  const candidates = [
23987
- join22(workspaceRoot, ".agents", `${nameOrPath}.md`),
23988
- join22(workspaceRoot, ".memory", "agents", `${nameOrPath}.md`)
26204
+ join27(workspaceRoot, ".agents", `${nameOrPath}.md`),
26205
+ join27(workspaceRoot, ".memory", "agents", `${nameOrPath}.md`)
23989
26206
  ];
23990
26207
  const home = process.env.HOME;
23991
26208
  if (home)
23992
- candidates.push(join22(home, ".config", "opencode", "agents", `${nameOrPath}.md`));
26209
+ candidates.push(join27(home, ".config", "opencode", "agents", `${nameOrPath}.md`));
23993
26210
  for (const c of candidates) {
23994
- if (existsSync23(c))
26211
+ if (existsSync28(c))
23995
26212
  return c;
23996
26213
  }
23997
26214
  return null;
@@ -24001,8 +26218,8 @@ var init_agentcontract = __esm(() => {
24001
26218
  });
24002
26219
 
24003
26220
  // src/cli/retrieval.ts
24004
- import { existsSync as existsSync24, readFileSync as readFileSync19 } from "node:fs";
24005
- import { join as join23 } from "node:path";
26221
+ import { existsSync as existsSync29, readFileSync as readFileSync24 } from "node:fs";
26222
+ import { join as join28 } from "node:path";
24006
26223
  async function handleContextCommand({ positional, flags }) {
24007
26224
  let agentTypes;
24008
26225
  let agentTags;
@@ -24010,7 +26227,7 @@ async function handleContextCommand({ positional, flags }) {
24010
26227
  const file = resolveAgentFile(flags["for-agent"], flags["dir"] ?? process.cwd());
24011
26228
  if (!file)
24012
26229
  return usageError(`--for-agent: cannot resolve agent '${flags["for-agent"]}'`);
24013
- const contract = parseAgentMemoryContract(readFileSync19(file, "utf8"));
26230
+ const contract = parseAgentMemoryContract(readFileSync24(file, "utf8"));
24014
26231
  if (contract) {
24015
26232
  agentTypes = contract.types;
24016
26233
  agentTags = contract.tags;
@@ -24067,6 +26284,28 @@ async function handleSearchCommand({ positional, flags }) {
24067
26284
  return usageError("search requires a query");
24068
26285
  const limit = parseInt(flags["limit"] ?? "10", 10) || 10;
24069
26286
  const tokenBudget = flags["token-budget"] ? parseInt(flags["token-budget"], 10) : undefined;
26287
+ if (flags["tree"] === "true") {
26288
+ let index = loadTreeIndex(ctx.memoryDir);
26289
+ if (!index) {
26290
+ console.log("no tree index found — building tree index now");
26291
+ index = buildTreeIndex(ctx.store, ctx.memoryDir);
26292
+ }
26293
+ const treeRes = searchTree(index, {
26294
+ query: positional[0],
26295
+ project: flags["project"],
26296
+ type: flags["type"],
26297
+ maxNodes: limit,
26298
+ tokenBudget,
26299
+ disclosureDepth: flags["depth"] || "L2"
26300
+ });
26301
+ for (const r of treeRes.nodes) {
26302
+ console.log(`- [score=${r.score.toFixed(3)}] ${r.node.title} (${r.node.project})`);
26303
+ if (r.node.summary)
26304
+ console.log(` ${r.node.summary}`);
26305
+ }
26306
+ console.log(`source=tree-index count=${treeRes.nodes.length} tokens=${treeRes.tokensUsed}`);
26307
+ return 0;
26308
+ }
24070
26309
  if (flags["hybrid"] === "true") {
24071
26310
  const hybrid = hybridSearch(ctx.store, ctx.memoryDir, positional[0], { limit });
24072
26311
  if (!hybrid) {
@@ -24127,7 +26366,7 @@ async function handleHarvestCommand({ positional, flags }) {
24127
26366
  const project = flags["project"];
24128
26367
  if (!project)
24129
26368
  return usageError("harvest requires --project");
24130
- const rawText = existsSync24(target) ? readFileSync19(target, "utf8") : target;
26369
+ const rawText = existsSync29(target) ? readFileSync24(target, "utf8") : target;
24131
26370
  const created = harvestMemory(ctx.store, {
24132
26371
  text: rawText,
24133
26372
  project,
@@ -24163,8 +26402,8 @@ async function handleSearchTranscriptCommand({ positional, flags }) {
24163
26402
  const filePath = positional[1];
24164
26403
  if (!query)
24165
26404
  return usageError("search-transcript requires <query> [file.jsonl]");
24166
- const targetFile = filePath ? filePath.startsWith("/") ? filePath : join23(process.cwd(), filePath) : join23(process.cwd(), "transcript.jsonl");
24167
- if (!existsSync24(targetFile)) {
26405
+ const targetFile = filePath ? filePath.startsWith("/") ? filePath : join28(process.cwd(), filePath) : join28(process.cwd(), "transcript.jsonl");
26406
+ if (!existsSync29(targetFile)) {
24168
26407
  return fail(`error: transcript file not found: ${targetFile}`);
24169
26408
  }
24170
26409
  const windowSize = flags["window"] ? parseInt(flags["window"], 10) : 2;
@@ -24180,7 +26419,7 @@ async function handleReindexCommand({ flags }) {
24180
26419
  const { rebuildIndex: rebuildIndex2, saveIndex: saveIndex2 } = await Promise.resolve().then(() => (init_vector(), exports_vector));
24181
26420
  const index = rebuildIndex2(ctx.store);
24182
26421
  saveIndex2(index, ctx.memoryDir);
24183
- console.log(`indexed ${Object.keys(index.entries).length} entries -> ${join23(ctx.memoryDir, "index.json")}`);
26422
+ console.log(`indexed ${Object.keys(index.entries).length} entries -> ${join28(ctx.memoryDir, "index.json")}`);
24184
26423
  return 0;
24185
26424
  }
24186
26425
  async function handleHookCommand({ positional, flags }) {
@@ -24212,9 +26451,10 @@ async function handleHarvestAutoCommand({ flags }) {
24212
26451
  console.log(res.message);
24213
26452
  return 0;
24214
26453
  }
24215
- var init_retrieval3 = __esm(() => {
26454
+ var init_retrieval4 = __esm(() => {
24216
26455
  init_retrieval();
24217
26456
  init_vector();
26457
+ init_retrieval3();
24218
26458
  init_harvest();
24219
26459
  init_retrieval2();
24220
26460
  init_hook();
@@ -24337,6 +26577,278 @@ var init_persona = __esm(() => {
24337
26577
  init_shared();
24338
26578
  });
24339
26579
 
26580
+ // src/cli/wiki.ts
26581
+ function handleWikiCommand(parsed) {
26582
+ const ctx = requireRoot(parsed.flags);
26583
+ if (!ctx)
26584
+ return 1;
26585
+ const memoryDir = ctx.memoryDir;
26586
+ const store = ctx.store;
26587
+ const sub = parsed.positional[1] ?? "compile";
26588
+ if (sub === "compile") {
26589
+ const project = parsed.flags.project;
26590
+ const dryRun = Boolean(parsed.flags["dry-run"]);
26591
+ const typesStr = parsed.flags.types;
26592
+ const includeTypes = typesStr ? typesStr.split(",") : undefined;
26593
+ console.log(`Compiling wiki for ${project ?? "all projects"} (dryRun: ${dryRun})...`);
26594
+ const result = compileWiki(store, memoryDir, { project, dryRun, includeTypes });
26595
+ console.log(`Wiki compilation complete:`);
26596
+ console.log(` Pages created: ${result.pagesCreated.length}`);
26597
+ console.log(` Pages updated: ${result.pagesUpdated.length}`);
26598
+ console.log(` Log entries: ${result.logEntries.length}`);
26599
+ if (result.errors.length > 0) {
26600
+ console.warn(`Warnings/Errors:`);
26601
+ for (const err of result.errors)
26602
+ console.warn(` - ${err}`);
26603
+ }
26604
+ return 0;
26605
+ }
26606
+ if (sub === "list" || sub === "ls") {
26607
+ const project = parsed.flags.project;
26608
+ const type2 = parsed.flags.type;
26609
+ const pages = listWikiPages(memoryDir, { project, type: type2 });
26610
+ if (pages.length === 0) {
26611
+ console.log("No wiki pages found. Run `memory wiki compile` to generate pages.");
26612
+ return 0;
26613
+ }
26614
+ console.log(`Wiki Pages (${pages.length}):`);
26615
+ for (const page of pages) {
26616
+ const typeBadge = `[${page.type}]`.padEnd(10);
26617
+ console.log(` ${typeBadge} ${page.slug} - "${page.title}" (${page.memoryRefs?.length ?? 0} memories)`);
26618
+ }
26619
+ return 0;
26620
+ }
26621
+ if (sub === "show" || sub === "get") {
26622
+ const slug = parsed.positional[2];
26623
+ if (!slug) {
26624
+ console.error("Error: please specify a page slug (e.g. `memory wiki show index` or `memory wiki show concept-name`)");
26625
+ return 2;
26626
+ }
26627
+ const type2 = parsed.flags.type;
26628
+ const page = getWikiPage(memoryDir, slug, type2);
26629
+ if (!page) {
26630
+ console.error(`Error: wiki page "${slug}" not found.`);
26631
+ return 1;
26632
+ }
26633
+ const content = "content" in page && page.content ? page.content : JSON.stringify(page, null, 2);
26634
+ console.log(content);
26635
+ return 0;
26636
+ }
26637
+ console.error(`Error: unknown wiki subcommand "${sub}". Supported: compile, list, show`);
26638
+ return 2;
26639
+ }
26640
+ var init_wiki2 = __esm(() => {
26641
+ init_shared();
26642
+ init_wiki();
26643
+ });
26644
+
26645
+ // src/cli/entities.ts
26646
+ function handleExtractEntitiesCommand(parsed) {
26647
+ const ctx = requireRoot(parsed.flags);
26648
+ if (!ctx)
26649
+ return 1;
26650
+ const memoryDir = ctx.memoryDir;
26651
+ const store = ctx.store;
26652
+ const project = parsed.flags.project;
26653
+ const dryRun = Boolean(parsed.flags["dry-run"]);
26654
+ let memories = list(store).filter((e) => e.status === "confirmed");
26655
+ if (project)
26656
+ memories = memories.filter((e) => e.project === project);
26657
+ console.log(`Extracting entities from ${memories.length} confirmed memories (dryRun: ${dryRun})...`);
26658
+ const result = extractEntitiesFromMemories(memories);
26659
+ console.log(`Extracted ${result.entities.length} unique entities across memories:`);
26660
+ const countsByType = new Map;
26661
+ for (const ent of result.entities) {
26662
+ countsByType.set(ent.type, (countsByType.get(ent.type) ?? 0) + 1);
26663
+ }
26664
+ for (const [type2, count] of countsByType) {
26665
+ console.log(` - ${type2}: ${count}`);
26666
+ }
26667
+ if (!dryRun) {
26668
+ saveEntities(memoryDir, result.entities);
26669
+ console.log(`Saved entity index to .memory/entities.json`);
26670
+ }
26671
+ return 0;
26672
+ }
26673
+ function handleEntitiesCommand(parsed) {
26674
+ const ctx = requireRoot(parsed.flags);
26675
+ if (!ctx)
26676
+ return 1;
26677
+ const memoryDir = ctx.memoryDir;
26678
+ const sub = parsed.positional[1] ?? "list";
26679
+ if (sub === "list" || sub === "ls") {
26680
+ const type2 = parsed.flags.type;
26681
+ const project = parsed.flags.project;
26682
+ let entities = loadEntities(memoryDir);
26683
+ if (entities.length === 0) {
26684
+ console.log("No entities found. Run `memory extract-entities` to scan memories.");
26685
+ return 0;
26686
+ }
26687
+ if (type2)
26688
+ entities = entities.filter((e) => e.type === type2);
26689
+ if (project)
26690
+ entities = entities.filter((e) => !e.project || e.project === project);
26691
+ console.log(`Entities (${entities.length}):`);
26692
+ for (const ent of entities) {
26693
+ const typeBadge = `[${ent.type}]`.padEnd(14);
26694
+ console.log(` ${typeBadge} ${ent.id} ("${ent.name}") - ${ent.memoryRefs.length} refs, ${ent.relatedEntities.length} related`);
26695
+ }
26696
+ return 0;
26697
+ }
26698
+ if (sub === "show" || sub === "get") {
26699
+ const id = parsed.positional[2];
26700
+ if (!id) {
26701
+ console.error("Error: please specify an entity ID or name (e.g. `memory entities show nextjs`)");
26702
+ return 2;
26703
+ }
26704
+ const entity = findEntity(memoryDir, id);
26705
+ if (!entity) {
26706
+ console.error(`Error: entity "${id}" not found.`);
26707
+ return 1;
26708
+ }
26709
+ console.log(JSON.stringify(entity, null, 2));
26710
+ return 0;
26711
+ }
26712
+ if (sub === "related") {
26713
+ const id = parsed.positional[2];
26714
+ if (!id) {
26715
+ console.error("Error: please specify an entity ID or name (e.g. `memory entities related nextjs`)");
26716
+ return 2;
26717
+ }
26718
+ const related = findRelatedEntities(memoryDir, id);
26719
+ if (related.length === 0) {
26720
+ console.log(`No related entities found for "${id}".`);
26721
+ return 0;
26722
+ }
26723
+ console.log(`Related Entities for "${id}":`);
26724
+ for (const { entity, strength } of related) {
26725
+ console.log(` - [strength ${strength}] ${entity.id} (${entity.type}: "${entity.name}")`);
26726
+ }
26727
+ return 0;
26728
+ }
26729
+ console.error(`Error: unknown entities subcommand "${sub}". Supported: list, show, related`);
26730
+ return 2;
26731
+ }
26732
+ var init_entities2 = __esm(() => {
26733
+ init_shared();
26734
+ init_store();
26735
+ init_entities();
26736
+ });
26737
+
26738
+ // src/cli/settings.ts
26739
+ import { writeFileSync as writeFileSync16, readFileSync as readFileSync25 } from "node:fs";
26740
+ function handleSettingsCommand(parsed) {
26741
+ const ctx = requireRoot(parsed.flags);
26742
+ if (!ctx)
26743
+ return 1;
26744
+ const memoryDir = ctx.memoryDir;
26745
+ const sub = parsed.positional[1] ?? "get";
26746
+ const project = parsed.flags.project;
26747
+ if (sub === "get") {
26748
+ const key = parsed.positional[2];
26749
+ const settings2 = project ? getProjectSettings(memoryDir, project) : getSettings(memoryDir);
26750
+ if (key) {
26751
+ const parts = key.split(".");
26752
+ let val = settings2;
26753
+ for (const p of parts) {
26754
+ val = val?.[p];
26755
+ }
26756
+ if (val === undefined) {
26757
+ console.error(`Error: setting key "${key}" not found.`);
26758
+ return 1;
26759
+ }
26760
+ console.log(typeof val === "object" ? JSON.stringify(val, null, 2) : val);
26761
+ return 0;
26762
+ }
26763
+ console.log(JSON.stringify(settings2, null, 2));
26764
+ return 0;
26765
+ }
26766
+ if (sub === "set") {
26767
+ const key = parsed.positional[2];
26768
+ const rawVal = parsed.positional[3];
26769
+ if (!key || rawVal === undefined) {
26770
+ console.error("Error: please specify key and value (e.g. `memory settings set retrieval.defaultMode tree`)");
26771
+ return 2;
26772
+ }
26773
+ let parsedVal = rawVal;
26774
+ if (rawVal === "true")
26775
+ parsedVal = true;
26776
+ else if (rawVal === "false")
26777
+ parsedVal = false;
26778
+ else if (!isNaN(Number(rawVal)) && rawVal.trim() !== "")
26779
+ parsedVal = Number(rawVal);
26780
+ else {
26781
+ try {
26782
+ parsedVal = JSON.parse(rawVal);
26783
+ } catch {}
26784
+ }
26785
+ const parts = key.split(".");
26786
+ const updateObj = {};
26787
+ let cur = updateObj;
26788
+ for (let i = 0;i < parts.length - 1; i++) {
26789
+ cur[parts[i]] = {};
26790
+ cur = cur[parts[i]];
26791
+ }
26792
+ cur[parts[parts.length - 1]] = parsedVal;
26793
+ try {
26794
+ if (project) {
26795
+ setProjectSettings(memoryDir, project, updateObj);
26796
+ console.log(`Updated project "${project}" settings: ${key} = ${JSON.stringify(parsedVal)}`);
26797
+ } else {
26798
+ setSettings(memoryDir, updateObj);
26799
+ console.log(`Updated global settings: ${key} = ${JSON.stringify(parsedVal)}`);
26800
+ }
26801
+ return 0;
26802
+ } catch (err) {
26803
+ console.error(`Error: ${err.message}`);
26804
+ return 1;
26805
+ }
26806
+ }
26807
+ if (sub === "reset") {
26808
+ if (project) {
26809
+ resetProjectSettings(memoryDir, project);
26810
+ console.log(`Reset settings for project "${project}".`);
26811
+ } else {
26812
+ resetSettings(memoryDir);
26813
+ console.log("Reset global settings to defaults.");
26814
+ }
26815
+ return 0;
26816
+ }
26817
+ if (sub === "export") {
26818
+ const out = parsed.flags.out;
26819
+ const json2 = exportSettings(memoryDir);
26820
+ if (out) {
26821
+ writeFileSync16(out, json2, "utf8");
26822
+ console.log(`Exported settings to ${out}`);
26823
+ } else {
26824
+ console.log(json2);
26825
+ }
26826
+ return 0;
26827
+ }
26828
+ if (sub === "import") {
26829
+ const file = parsed.positional[2];
26830
+ if (!file) {
26831
+ console.error("Error: please specify a JSON file to import (e.g. `memory settings import team-settings.json`)");
26832
+ return 2;
26833
+ }
26834
+ try {
26835
+ const raw = readFileSync25(file, "utf8");
26836
+ importSettings(memoryDir, raw);
26837
+ console.log(`Successfully imported settings from ${file}`);
26838
+ return 0;
26839
+ } catch (err) {
26840
+ console.error(`Error importing settings: ${err.message}`);
26841
+ return 1;
26842
+ }
26843
+ }
26844
+ console.error(`Error: unknown settings subcommand "${sub}". Supported: get, set, reset, export, import`);
26845
+ return 2;
26846
+ }
26847
+ var init_settings3 = __esm(() => {
26848
+ init_shared();
26849
+ init_settings2();
26850
+ });
26851
+
24340
26852
  // src/nudge.ts
24341
26853
  function dueEntries(entries, now = Date.now()) {
24342
26854
  return entries.filter((e) => {
@@ -24406,16 +26918,16 @@ var init_nudge = __esm(() => {
24406
26918
  });
24407
26919
 
24408
26920
  // src/routines.ts
24409
- import { readFileSync as readFileSync20, existsSync as existsSync25 } from "node:fs";
24410
- import { join as join24 } from "node:path";
26921
+ import { readFileSync as readFileSync26, existsSync as existsSync30 } from "node:fs";
26922
+ import { join as join29 } from "node:path";
24411
26923
  function routinesPath(memoryDir) {
24412
- return join24(memoryDir, "routines.yaml");
26924
+ return join29(memoryDir, "routines.yaml");
24413
26925
  }
24414
26926
  function loadRoutines(memoryDir) {
24415
26927
  const p = routinesPath(memoryDir);
24416
- if (!existsSync25(p))
26928
+ if (!existsSync30(p))
24417
26929
  return { routines: {} };
24418
- const doc2 = yaml.load(readFileSync20(p, "utf8"), { schema: yaml.JSON_SCHEMA }) ?? {};
26930
+ const doc2 = yaml.load(readFileSync26(p, "utf8"), { schema: yaml.JSON_SCHEMA }) ?? {};
24419
26931
  const routines = doc2.routines ?? {};
24420
26932
  for (const [name, r] of Object.entries(routines)) {
24421
26933
  if (!r || typeof r.schedule !== "string" || !r.schedule.trim()) {
@@ -24453,7 +26965,7 @@ var init_routines = __esm(() => {
24453
26965
  });
24454
26966
 
24455
26967
  // src/cli/lifecycle.ts
24456
- import { writeFileSync as writeFileSync11, readFileSync as readFileSync21, existsSync as existsSync26 } from "node:fs";
26968
+ import { writeFileSync as writeFileSync17, readFileSync as readFileSync27, existsSync as existsSync31 } from "node:fs";
24457
26969
  async function handleProposeCommand({ positional, flags }) {
24458
26970
  const ctx = requireRoot(flags);
24459
26971
  if (!ctx)
@@ -24610,7 +27122,7 @@ async function handleExportCommand({ flags }) {
24610
27122
  const snapshot = exportSnapshot(ctx.store);
24611
27123
  const outPath = flags["out"];
24612
27124
  if (outPath) {
24613
- writeFileSync11(outPath, JSON.stringify(snapshot, null, 2), "utf8");
27125
+ writeFileSync17(outPath, JSON.stringify(snapshot, null, 2), "utf8");
24614
27126
  console.log(`exported ${snapshot.total} memories to ${outPath}`);
24615
27127
  } else {
24616
27128
  console.log(JSON.stringify(snapshot, null, 2));
@@ -24624,9 +27136,9 @@ async function handleImportCommand({ positional, flags }) {
24624
27136
  const file = positional[0];
24625
27137
  if (!file)
24626
27138
  return usageError("import requires <file.json>");
24627
- if (!existsSync26(file))
27139
+ if (!existsSync31(file))
24628
27140
  return fail(`error: file ${file} does not exist`);
24629
- const raw = JSON.parse(readFileSync21(file, "utf8"));
27141
+ const raw = JSON.parse(readFileSync27(file, "utf8"));
24630
27142
  const res = importSnapshot(ctx.store, raw, { overwrite: flags["overwrite"] === "true" });
24631
27143
  if (res.errors.length > 0) {
24632
27144
  console.error(`import encountered errors:`);
@@ -24975,11 +27487,11 @@ var init_lifecycle2 = __esm(() => {
24975
27487
  // src/cli.ts
24976
27488
  var exports_cli = {};
24977
27489
  __export(exports_cli, {
24978
- requireRoot: () => requireRoot,
24979
- printEntry: () => printEntry,
24980
- parseFlags: () => parseFlags,
27490
+ USAGE: () => USAGE,
24981
27491
  main: () => main,
24982
- USAGE: () => USAGE
27492
+ parseFlags: () => parseFlags,
27493
+ printEntry: () => printEntry,
27494
+ requireRoot: () => requireRoot
24983
27495
  });
24984
27496
  async function main(argv) {
24985
27497
  if (argv.length === 0 || argv[0] === "--help" || argv[0] === "-h" || argv[0] === "help") {
@@ -25091,6 +27603,14 @@ async function main(argv) {
25091
27603
  return handleVerifyCommand(parsed);
25092
27604
  case "session":
25093
27605
  return handleSessionCommand(parsed);
27606
+ case "wiki":
27607
+ return handleWikiCommand(parsed);
27608
+ case "extract-entities":
27609
+ return handleExtractEntitiesCommand(parsed);
27610
+ case "entities":
27611
+ return handleEntitiesCommand(parsed);
27612
+ case "settings":
27613
+ return handleSettingsCommand(parsed);
25094
27614
  default:
25095
27615
  console.error(`Error: unknown command "${cmd}"`);
25096
27616
  return 2;
@@ -25130,12 +27650,18 @@ Core Memory Lifecycle Commands:
25130
27650
 
25131
27651
  Context & Retrieval Commands:
25132
27652
  context [query] [--limit N] [--token-budget N] [--depth L1|L2|L3] Top-ranked prompt injection context
25133
- search <query> [--limit N] [--token-budget N] [--hybrid] Scored token retrieval (hybrid: offline vector+BM25 via index)
27653
+ search <query> [--limit N] [--token-budget N] [--hybrid] [--tree] Scored token retrieval (hybrid: vector+BM25, tree: hierarchical reasoning)
25134
27654
  reindex Rebuild the local vector index (.memory/index.json) for hybrid search
25135
27655
  recall [query] Search active/confirmed memories with filters
25136
27656
  search-transcript <query> [file.jsonl] [--window N] Full-text transcript search with bookends
25137
27657
 
25138
- Persona & Constraints Commands:
27658
+ Wiki & Entity Knowledge Compounding:
27659
+ wiki [compile|list|show] Compile memories into structured Obsidian-compatible markdown wiki pages
27660
+ extract-entities [--dry-run] Extract named entities (persons, products, orgs, files, concepts) from memories
27661
+ entities [list|show|related] Inspect extracted knowledge graph entities and co-occurrences
27662
+
27663
+ Persona, Settings & Constraints Commands:
27664
+ settings [get|set|reset|export|import] Manage unified global and project configuration
25139
27665
  user [get|init|set] [--global] Manage USER.md persona & working preferences
25140
27666
  current [get|set] Manage CURRENT.md active project constraints
25141
27667
  core [tier] [--set T|--remove|--show] Manage CORE.md permanent partitions (identity|directives|conventions|context)
@@ -25160,8 +27686,11 @@ Ecosystem, Migration & Connectivity:
25160
27686
  var init_cli = __esm(() => {
25161
27687
  init_shared();
25162
27688
  init_ecosystem();
25163
- init_retrieval3();
27689
+ init_retrieval4();
25164
27690
  init_persona();
27691
+ init_wiki2();
27692
+ init_entities2();
27693
+ init_settings3();
25165
27694
  init_lifecycle2();
25166
27695
  });
25167
27696