@ushiradineth/veil 0.1.5 → 0.1.6

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 (4) hide show
  1. package/README.md +106 -113
  2. package/bin/veil.mjs +1 -19
  3. package/dist/bin.js +758 -404
  4. package/package.json +5 -1
package/dist/bin.js CHANGED
@@ -456,15 +456,15 @@ var init_parseUtil = __esm({
456
456
  message: issueData.message
457
457
  };
458
458
  }
459
- let errorMessage = "";
459
+ let errorMessage2 = "";
460
460
  const maps = errorMaps.filter((m) => !!m).slice().reverse();
461
461
  for (const map of maps) {
462
- errorMessage = map(fullIssue, { data, defaultError: errorMessage }).message;
462
+ errorMessage2 = map(fullIssue, { data, defaultError: errorMessage2 }).message;
463
463
  }
464
464
  return {
465
465
  ...issueData,
466
466
  path: fullPath,
467
- message: errorMessage
467
+ message: errorMessage2
468
468
  };
469
469
  };
470
470
  EMPTY_PATH = [];
@@ -6774,13 +6774,13 @@ var init_registries = __esm({
6774
6774
  this._idmap = /* @__PURE__ */ new Map();
6775
6775
  }
6776
6776
  add(schema, ..._meta) {
6777
- const meta = _meta[0];
6778
- this._map.set(schema, meta);
6779
- if (meta && typeof meta === "object" && "id" in meta) {
6780
- if (this._idmap.has(meta.id)) {
6781
- throw new Error(`ID ${meta.id} already exists in the registry`);
6777
+ const meta2 = _meta[0];
6778
+ this._map.set(schema, meta2);
6779
+ if (meta2 && typeof meta2 === "object" && "id" in meta2) {
6780
+ if (this._idmap.has(meta2.id)) {
6781
+ throw new Error(`ID ${meta2.id} already exists in the registry`);
6782
6782
  }
6783
- this._idmap.set(meta.id, schema);
6783
+ this._idmap.set(meta2.id, schema);
6784
6784
  }
6785
6785
  return this;
6786
6786
  }
@@ -6790,9 +6790,9 @@ var init_registries = __esm({
6790
6790
  return this;
6791
6791
  }
6792
6792
  remove(schema) {
6793
- const meta = this._map.get(schema);
6794
- if (meta && typeof meta === "object" && "id" in meta) {
6795
- this._idmap.delete(meta.id);
6793
+ const meta2 = this._map.get(schema);
6794
+ if (meta2 && typeof meta2 === "object" && "id" in meta2) {
6795
+ this._idmap.delete(meta2.id);
6796
6796
  }
6797
6797
  this._map.delete(schema);
6798
6798
  return this;
@@ -7869,9 +7869,9 @@ var init_to_json_schema = __esm({
7869
7869
  }
7870
7870
  }
7871
7871
  }
7872
- const meta = this.metadataRegistry.get(schema);
7873
- if (meta)
7874
- Object.assign(result.schema, meta);
7872
+ const meta2 = this.metadataRegistry.get(schema);
7873
+ if (meta2)
7874
+ Object.assign(result.schema, meta2);
7875
7875
  if (this.io === "input" && isTransforming(schema)) {
7876
7876
  delete result.schema.examples;
7877
7877
  delete result.schema.default;
@@ -8114,8 +8114,8 @@ var init_schemas2 = __esm({
8114
8114
  };
8115
8115
  inst.clone = (_def, params) => clone(inst, _def, params);
8116
8116
  inst.brand = () => inst;
8117
- inst.register = ((reg, meta) => {
8118
- reg.add(inst, meta);
8117
+ inst.register = ((reg, meta2) => {
8118
+ reg.add(inst, meta2);
8119
8119
  return inst;
8120
8120
  });
8121
8121
  });
@@ -8651,8 +8651,8 @@ var init_schemas3 = __esm({
8651
8651
  };
8652
8652
  inst.clone = (def2, params) => clone(inst, def2, params);
8653
8653
  inst.brand = () => inst;
8654
- inst.register = ((reg, meta) => {
8655
- reg.add(inst, meta);
8654
+ inst.register = ((reg, meta2) => {
8655
+ reg.add(inst, meta2);
8656
8656
  return inst;
8657
8657
  });
8658
8658
  inst.parse = (data, params) => parse2(inst, data, params, { callee: inst.parse });
@@ -10696,19 +10696,19 @@ var init_Refs = __esm({
10696
10696
  });
10697
10697
 
10698
10698
  // node_modules/zod-to-json-schema/dist/esm/errorMessages.js
10699
- function addErrorMessage(res, key, errorMessage, refs) {
10699
+ function addErrorMessage(res, key, errorMessage2, refs) {
10700
10700
  if (!refs?.errorMessages)
10701
10701
  return;
10702
- if (errorMessage) {
10702
+ if (errorMessage2) {
10703
10703
  res.errorMessage = {
10704
10704
  ...res.errorMessage,
10705
- [key]: errorMessage
10705
+ [key]: errorMessage2
10706
10706
  };
10707
10707
  }
10708
10708
  }
10709
- function setResponseValueAndErrors(res, key, value, errorMessage, refs) {
10709
+ function setResponseValueAndErrors(res, key, value, errorMessage2, refs) {
10710
10710
  res[key] = value;
10711
- addErrorMessage(res, key, errorMessage, refs);
10711
+ addErrorMessage(res, key, errorMessage2, refs);
10712
10712
  }
10713
10713
  var init_errorMessages = __esm({
10714
10714
  "node_modules/zod-to-json-schema/dist/esm/errorMessages.js"() {
@@ -12330,8 +12330,8 @@ var init_protocol = __esm({
12330
12330
  if (queuedMessage.type === "response") {
12331
12331
  resolver(message);
12332
12332
  } else {
12333
- const errorMessage = message;
12334
- const error2 = new McpError(errorMessage.error.code, errorMessage.error.message, errorMessage.error.data);
12333
+ const errorMessage2 = message;
12334
+ const error2 = new McpError(errorMessage2.error.code, errorMessage2.error.message, errorMessage2.error.data);
12335
12335
  resolver(error2);
12336
12336
  }
12337
12337
  } else {
@@ -15410,8 +15410,8 @@ var require_resolve = __commonJS({
15410
15410
  }
15411
15411
  return count;
15412
15412
  }
15413
- function getFullPath(resolver, id = "", normalize2) {
15414
- if (normalize2 !== false)
15413
+ function getFullPath(resolver, id = "", normalize3) {
15414
+ if (normalize3 !== false)
15415
15415
  id = normalizeId(id);
15416
15416
  const p = resolver.parse(id);
15417
15417
  return _getFullPath(resolver, p);
@@ -16751,7 +16751,7 @@ var require_fast_uri = __commonJS({
16751
16751
  "use strict";
16752
16752
  var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizeComponentEncoding, isIPv4, nonSimpleDomain } = require_utils();
16753
16753
  var { SCHEMES, getSchemeHandler } = require_schemes();
16754
- function normalize2(uri, options) {
16754
+ function normalize3(uri, options) {
16755
16755
  if (typeof uri === "string") {
16756
16756
  uri = /** @type {T} */
16757
16757
  serialize(parse3(uri, options), options);
@@ -16767,49 +16767,49 @@ var require_fast_uri = __commonJS({
16767
16767
  schemelessOptions.skipEscape = true;
16768
16768
  return serialize(resolved, schemelessOptions);
16769
16769
  }
16770
- function resolveComponent(base, relative3, options, skipNormalization) {
16770
+ function resolveComponent(base, relative4, options, skipNormalization) {
16771
16771
  const target = {};
16772
16772
  if (!skipNormalization) {
16773
16773
  base = parse3(serialize(base, options), options);
16774
- relative3 = parse3(serialize(relative3, options), options);
16774
+ relative4 = parse3(serialize(relative4, options), options);
16775
16775
  }
16776
16776
  options = options || {};
16777
- if (!options.tolerant && relative3.scheme) {
16778
- target.scheme = relative3.scheme;
16779
- target.userinfo = relative3.userinfo;
16780
- target.host = relative3.host;
16781
- target.port = relative3.port;
16782
- target.path = removeDotSegments(relative3.path || "");
16783
- target.query = relative3.query;
16777
+ if (!options.tolerant && relative4.scheme) {
16778
+ target.scheme = relative4.scheme;
16779
+ target.userinfo = relative4.userinfo;
16780
+ target.host = relative4.host;
16781
+ target.port = relative4.port;
16782
+ target.path = removeDotSegments(relative4.path || "");
16783
+ target.query = relative4.query;
16784
16784
  } else {
16785
- if (relative3.userinfo !== void 0 || relative3.host !== void 0 || relative3.port !== void 0) {
16786
- target.userinfo = relative3.userinfo;
16787
- target.host = relative3.host;
16788
- target.port = relative3.port;
16789
- target.path = removeDotSegments(relative3.path || "");
16790
- target.query = relative3.query;
16785
+ if (relative4.userinfo !== void 0 || relative4.host !== void 0 || relative4.port !== void 0) {
16786
+ target.userinfo = relative4.userinfo;
16787
+ target.host = relative4.host;
16788
+ target.port = relative4.port;
16789
+ target.path = removeDotSegments(relative4.path || "");
16790
+ target.query = relative4.query;
16791
16791
  } else {
16792
- if (!relative3.path) {
16792
+ if (!relative4.path) {
16793
16793
  target.path = base.path;
16794
- if (relative3.query !== void 0) {
16795
- target.query = relative3.query;
16794
+ if (relative4.query !== void 0) {
16795
+ target.query = relative4.query;
16796
16796
  } else {
16797
16797
  target.query = base.query;
16798
16798
  }
16799
16799
  } else {
16800
- if (relative3.path[0] === "/") {
16801
- target.path = removeDotSegments(relative3.path);
16800
+ if (relative4.path[0] === "/") {
16801
+ target.path = removeDotSegments(relative4.path);
16802
16802
  } else {
16803
16803
  if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
16804
- target.path = "/" + relative3.path;
16804
+ target.path = "/" + relative4.path;
16805
16805
  } else if (!base.path) {
16806
- target.path = relative3.path;
16806
+ target.path = relative4.path;
16807
16807
  } else {
16808
- target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative3.path;
16808
+ target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative4.path;
16809
16809
  }
16810
16810
  target.path = removeDotSegments(target.path);
16811
16811
  }
16812
- target.query = relative3.query;
16812
+ target.query = relative4.query;
16813
16813
  }
16814
16814
  target.userinfo = base.userinfo;
16815
16815
  target.host = base.host;
@@ -16817,7 +16817,7 @@ var require_fast_uri = __commonJS({
16817
16817
  }
16818
16818
  target.scheme = base.scheme;
16819
16819
  }
16820
- target.fragment = relative3.fragment;
16820
+ target.fragment = relative4.fragment;
16821
16821
  return target;
16822
16822
  }
16823
16823
  function equal(uriA, uriB, options) {
@@ -16987,7 +16987,7 @@ var require_fast_uri = __commonJS({
16987
16987
  }
16988
16988
  var fastUri = {
16989
16989
  SCHEMES,
16990
- normalize: normalize2,
16990
+ normalize: normalize3,
16991
16991
  resolve: resolve2,
16992
16992
  resolveComponent,
16993
16993
  equal,
@@ -17152,19 +17152,19 @@ var require_core = __commonJS({
17152
17152
  this.addKeyword("$async");
17153
17153
  }
17154
17154
  _addDefaultMetaSchema() {
17155
- const { $data, meta, schemaId } = this.opts;
17155
+ const { $data, meta: meta2, schemaId } = this.opts;
17156
17156
  let _dataRefSchema = $dataRefSchema;
17157
17157
  if (schemaId === "id") {
17158
17158
  _dataRefSchema = { ...$dataRefSchema };
17159
17159
  _dataRefSchema.id = _dataRefSchema.$id;
17160
17160
  delete _dataRefSchema.$id;
17161
17161
  }
17162
- if (meta && $data)
17162
+ if (meta2 && $data)
17163
17163
  this.addMetaSchema(_dataRefSchema, _dataRefSchema[schemaId], false);
17164
17164
  }
17165
17165
  defaultMeta() {
17166
- const { meta, schemaId } = this.opts;
17167
- return this.opts.defaultMeta = typeof meta == "object" ? meta[schemaId] || meta : void 0;
17166
+ const { meta: meta2, schemaId } = this.opts;
17167
+ return this.opts.defaultMeta = typeof meta2 == "object" ? meta2[schemaId] || meta2 : void 0;
17168
17168
  }
17169
17169
  validate(schemaKeyRef, data) {
17170
17170
  let v;
@@ -17184,12 +17184,12 @@ var require_core = __commonJS({
17184
17184
  const sch = this._addSchema(schema, _meta);
17185
17185
  return sch.validate || this._compileSchemaEnv(sch);
17186
17186
  }
17187
- compileAsync(schema, meta) {
17187
+ compileAsync(schema, meta2) {
17188
17188
  if (typeof this.opts.loadSchema != "function") {
17189
17189
  throw new Error("options.loadSchema should be a function");
17190
17190
  }
17191
17191
  const { loadSchema } = this.opts;
17192
- return runCompileAsync.call(this, schema, meta);
17192
+ return runCompileAsync.call(this, schema, meta2);
17193
17193
  async function runCompileAsync(_schema, _meta) {
17194
17194
  await loadMetaSchema.call(this, _schema.$schema);
17195
17195
  const sch = this._addSchema(_schema, _meta);
@@ -17221,7 +17221,7 @@ var require_core = __commonJS({
17221
17221
  if (!this.refs[ref])
17222
17222
  await loadMetaSchema.call(this, _schema.$schema);
17223
17223
  if (!this.refs[ref])
17224
- this.addSchema(_schema, ref, meta);
17224
+ this.addSchema(_schema, ref, meta2);
17225
17225
  }
17226
17226
  async function _loadSchema(ref) {
17227
17227
  const p = this._loading[ref];
@@ -17326,8 +17326,8 @@ var require_core = __commonJS({
17326
17326
  return this;
17327
17327
  }
17328
17328
  case "object": {
17329
- const cacheKey = schemaKeyRef;
17330
- this._cache.delete(cacheKey);
17329
+ const cacheKey2 = schemaKeyRef;
17330
+ this._cache.delete(cacheKey2);
17331
17331
  let id = schemaKeyRef[this.opts.schemaId];
17332
17332
  if (id) {
17333
17333
  id = (0, resolve_1.normalizeId)(id);
@@ -17438,7 +17438,7 @@ var require_core = __commonJS({
17438
17438
  }
17439
17439
  }
17440
17440
  }
17441
- _addSchema(schema, meta, baseId, validateSchema = this.opts.validateSchema, addSchema = this.opts.addUsedSchema) {
17441
+ _addSchema(schema, meta2, baseId, validateSchema = this.opts.validateSchema, addSchema = this.opts.addUsedSchema) {
17442
17442
  let id;
17443
17443
  const { schemaId } = this.opts;
17444
17444
  if (typeof schema == "object") {
@@ -17454,7 +17454,7 @@ var require_core = __commonJS({
17454
17454
  return sch;
17455
17455
  baseId = (0, resolve_1.normalizeId)(id || baseId);
17456
17456
  const localRefs = resolve_1.getSchemaRefs.call(this, schema, baseId);
17457
- sch = new compile_1.SchemaEnv({ schema, schemaId, meta, baseId, localRefs });
17457
+ sch = new compile_1.SchemaEnv({ schema, schemaId, meta: meta2, baseId, localRefs });
17458
17458
  this._cache.set(sch.schema, sch);
17459
17459
  if (addSchema && !baseId.startsWith("#")) {
17460
17460
  if (baseId)
@@ -20401,23 +20401,23 @@ var init_server2 = __esm({
20401
20401
  const wrappedHandler = async (request, extra) => {
20402
20402
  const validatedRequest = safeParse2(CallToolRequestSchema, request);
20403
20403
  if (!validatedRequest.success) {
20404
- const errorMessage = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
20405
- throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call request: ${errorMessage}`);
20404
+ const errorMessage2 = validatedRequest.error instanceof Error ? validatedRequest.error.message : String(validatedRequest.error);
20405
+ throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call request: ${errorMessage2}`);
20406
20406
  }
20407
20407
  const { params } = validatedRequest.data;
20408
20408
  const result = await Promise.resolve(handler(request, extra));
20409
20409
  if (params.task) {
20410
20410
  const taskValidationResult = safeParse2(CreateTaskResultSchema, result);
20411
20411
  if (!taskValidationResult.success) {
20412
- const errorMessage = taskValidationResult.error instanceof Error ? taskValidationResult.error.message : String(taskValidationResult.error);
20413
- throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${errorMessage}`);
20412
+ const errorMessage2 = taskValidationResult.error instanceof Error ? taskValidationResult.error.message : String(taskValidationResult.error);
20413
+ throw new McpError(ErrorCode.InvalidParams, `Invalid task creation result: ${errorMessage2}`);
20414
20414
  }
20415
20415
  return taskValidationResult.data;
20416
20416
  }
20417
20417
  const validationResult = safeParse2(CallToolResultSchema, result);
20418
20418
  if (!validationResult.success) {
20419
- const errorMessage = validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);
20420
- throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call result: ${errorMessage}`);
20419
+ const errorMessage2 = validationResult.error instanceof Error ? validationResult.error.message : String(validationResult.error);
20420
+ throw new McpError(ErrorCode.InvalidParams, `Invalid tools/call result: ${errorMessage2}`);
20421
20421
  }
20422
20422
  return validationResult.data;
20423
20423
  };
@@ -20704,8 +20704,8 @@ function isCompletable(schema) {
20704
20704
  return !!schema && typeof schema === "object" && COMPLETABLE_SYMBOL in schema;
20705
20705
  }
20706
20706
  function getCompleter(schema) {
20707
- const meta = schema[COMPLETABLE_SYMBOL];
20708
- return meta?.complete;
20707
+ const meta2 = schema[COMPLETABLE_SYMBOL];
20708
+ return meta2?.complete;
20709
20709
  }
20710
20710
  var COMPLETABLE_SYMBOL, McpZodTypeKind;
20711
20711
  var init_completable = __esm({
@@ -21015,12 +21015,12 @@ var init_mcp = __esm({
21015
21015
  * @param errorMessage - The error message.
21016
21016
  * @returns The tool error result.
21017
21017
  */
21018
- createToolError(errorMessage) {
21018
+ createToolError(errorMessage2) {
21019
21019
  return {
21020
21020
  content: [
21021
21021
  {
21022
21022
  type: "text",
21023
- text: errorMessage
21023
+ text: errorMessage2
21024
21024
  }
21025
21025
  ],
21026
21026
  isError: true
@@ -21038,8 +21038,8 @@ var init_mcp = __esm({
21038
21038
  const parseResult = await safeParseAsync2(schemaToParse, args);
21039
21039
  if (!parseResult.success) {
21040
21040
  const error2 = "error" in parseResult ? parseResult.error : "Unknown error";
21041
- const errorMessage = getParseErrorMessage(error2);
21042
- throw new McpError(ErrorCode.InvalidParams, `Input validation error: Invalid arguments for tool ${toolName}: ${errorMessage}`);
21041
+ const errorMessage2 = getParseErrorMessage(error2);
21042
+ throw new McpError(ErrorCode.InvalidParams, `Input validation error: Invalid arguments for tool ${toolName}: ${errorMessage2}`);
21043
21043
  }
21044
21044
  return parseResult.data;
21045
21045
  }
@@ -21063,8 +21063,8 @@ var init_mcp = __esm({
21063
21063
  const parseResult = await safeParseAsync2(outputObj, result.structuredContent);
21064
21064
  if (!parseResult.success) {
21065
21065
  const error2 = "error" in parseResult ? parseResult.error : "Unknown error";
21066
- const errorMessage = getParseErrorMessage(error2);
21067
- throw new McpError(ErrorCode.InvalidParams, `Output validation error: Invalid structured content for tool ${toolName}: ${errorMessage}`);
21066
+ const errorMessage2 = getParseErrorMessage(error2);
21067
+ throw new McpError(ErrorCode.InvalidParams, `Output validation error: Invalid structured content for tool ${toolName}: ${errorMessage2}`);
21068
21068
  }
21069
21069
  }
21070
21070
  /**
@@ -21276,8 +21276,8 @@ var init_mcp = __esm({
21276
21276
  const parseResult = await safeParseAsync2(argsObj, request.params.arguments);
21277
21277
  if (!parseResult.success) {
21278
21278
  const error2 = "error" in parseResult ? parseResult.error : "Unknown error";
21279
- const errorMessage = getParseErrorMessage(error2);
21280
- throw new McpError(ErrorCode.InvalidParams, `Invalid arguments for prompt ${request.params.name}: ${errorMessage}`);
21279
+ const errorMessage2 = getParseErrorMessage(error2);
21280
+ throw new McpError(ErrorCode.InvalidParams, `Invalid arguments for prompt ${request.params.name}: ${errorMessage2}`);
21281
21281
  }
21282
21282
  const args = parseResult.data;
21283
21283
  const cb = prompt.callback;
@@ -21716,13 +21716,126 @@ var init_stdio2 = __esm({
21716
21716
  }
21717
21717
  });
21718
21718
 
21719
+ // src/cache.ts
21720
+ function getLru(cache, key) {
21721
+ const value = cache.get(key);
21722
+ if (value === void 0) return void 0;
21723
+ cache.delete(key);
21724
+ cache.set(key, value);
21725
+ return value;
21726
+ }
21727
+ function setLru(cache, key, value, maxSize) {
21728
+ if (cache.has(key)) cache.delete(key);
21729
+ cache.set(key, value);
21730
+ while (cache.size > maxSize) {
21731
+ const first = cache.keys().next().value;
21732
+ if (first === void 0) break;
21733
+ cache.delete(first);
21734
+ }
21735
+ }
21736
+ var TopKHeap;
21737
+ var init_cache = __esm({
21738
+ "src/cache.ts"() {
21739
+ "use strict";
21740
+ TopKHeap = class {
21741
+ heap = [];
21742
+ k;
21743
+ constructor(k) {
21744
+ this.k = k;
21745
+ }
21746
+ parent(i) {
21747
+ return Math.floor((i - 1) / 2);
21748
+ }
21749
+ left(i) {
21750
+ return 2 * i + 1;
21751
+ }
21752
+ right(i) {
21753
+ return 2 * i + 2;
21754
+ }
21755
+ swap(i, j) {
21756
+ const temp = this.heap[i];
21757
+ this.heap[i] = this.heap[j];
21758
+ this.heap[j] = temp;
21759
+ }
21760
+ heapifyUp(i) {
21761
+ while (i > 0) {
21762
+ const p = this.parent(i);
21763
+ if (this.heap[i].score >= this.heap[p].score) break;
21764
+ this.swap(i, p);
21765
+ i = p;
21766
+ }
21767
+ }
21768
+ heapifyDown(i) {
21769
+ while (true) {
21770
+ let smallest = i;
21771
+ const l = this.left(i);
21772
+ const r = this.right(i);
21773
+ if (l < this.heap.length && this.heap[l].score < this.heap[smallest].score) {
21774
+ smallest = l;
21775
+ }
21776
+ if (r < this.heap.length && this.heap[r].score < this.heap[smallest].score) {
21777
+ smallest = r;
21778
+ }
21779
+ if (smallest === i) break;
21780
+ this.swap(i, smallest);
21781
+ i = smallest;
21782
+ }
21783
+ }
21784
+ insert(item, score) {
21785
+ if (this.k <= 0) return;
21786
+ if (this.heap.length < this.k) {
21787
+ this.heap.push({ item, score });
21788
+ this.heapifyUp(this.heap.length - 1);
21789
+ } else if (score > this.heap[0].score) {
21790
+ this.heap[0] = { item, score };
21791
+ this.heapifyDown(0);
21792
+ }
21793
+ }
21794
+ toSortedArray() {
21795
+ const sorted = [...this.heap].sort((a, b) => b.score - a.score);
21796
+ return sorted.map((entry) => entry.item);
21797
+ }
21798
+ };
21799
+ }
21800
+ });
21801
+
21802
+ // src/state-root.ts
21803
+ import { isAbsolute, join, normalize, relative } from "node:path";
21804
+ function resolveStateRoot(workspace, override) {
21805
+ const raw = (override ?? process.env.VEIL_STATE_ROOT ?? DEFAULT_STATE_ROOT).trim();
21806
+ if (!raw) return join(workspace, DEFAULT_STATE_ROOT);
21807
+ if (isAbsolute(raw)) return normalize(raw);
21808
+ return normalize(join(workspace, raw));
21809
+ }
21810
+ function resolveIndexDir(workspace, override) {
21811
+ return join(resolveStateRoot(workspace, override), "index");
21812
+ }
21813
+ function relativeStateRoot(workspace, override) {
21814
+ const stateRoot = resolveStateRoot(workspace, override);
21815
+ const rel = relative(workspace, stateRoot);
21816
+ if (!rel || rel === ".") return "";
21817
+ if (rel.startsWith("..") || isAbsolute(rel)) return null;
21818
+ return rel.replace(/\\/g, "/");
21819
+ }
21820
+ function diagnosticsStatePath(workspace, override) {
21821
+ return join(resolveIndexDir(workspace, override), "diagnostics-state.json");
21822
+ }
21823
+ var DEFAULT_STATE_ROOT;
21824
+ var init_state_root = __esm({
21825
+ "src/state-root.ts"() {
21826
+ "use strict";
21827
+ DEFAULT_STATE_ROOT = ".veil";
21828
+ }
21829
+ });
21830
+
21719
21831
  // src/diagnostics.ts
21720
21832
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
21721
- import { dirname, join } from "node:path";
21833
+ import { dirname, join as join2 } from "node:path";
21722
21834
  var PerformanceDiagnostics, diagnostics, Profiler, profiler;
21723
21835
  var init_diagnostics = __esm({
21724
21836
  "src/diagnostics.ts"() {
21725
21837
  "use strict";
21838
+ init_state_root();
21726
21839
  PerformanceDiagnostics = class {
21727
21840
  queryCacheHits = 0;
21728
21841
  queryCacheMisses = 0;
@@ -21749,7 +21862,7 @@ var init_diagnostics = __esm({
21749
21862
  exitFn;
21750
21863
  constructor(options) {
21751
21864
  this.persistIntervalMs = options?.persistIntervalMs ?? Number(process.env.VEIL_DIAGNOSTICS_PERSIST_MS ?? "1000");
21752
- this.statePath = options?.statePath ?? (process.env.VEIL_DIAGNOSTICS_PATH ?? join(process.cwd(), ".agents", "index", "diagnostics-state.json"));
21865
+ this.statePath = options?.statePath ?? (process.env.VEIL_DIAGNOSTICS_PATH ?? join2(resolveIndexDir(process.cwd()), "diagnostics-state.json"));
21753
21866
  this.registerHook = options?.registerHook ?? ((event, handler) => {
21754
21867
  process.on(event, handler);
21755
21868
  });
@@ -21757,6 +21870,12 @@ var init_diagnostics = __esm({
21757
21870
  process.exit(code);
21758
21871
  });
21759
21872
  }
21873
+ configureStatePath(statePath) {
21874
+ if (statePath.trim() && statePath !== this.statePath) {
21875
+ this.statePath = statePath;
21876
+ this.loaded = false;
21877
+ }
21878
+ }
21760
21879
  installExitHooks() {
21761
21880
  if (this.hooksInstalled) return;
21762
21881
  this.hooksInstalled = true;
@@ -22050,17 +22169,138 @@ var init_diagnostics = __esm({
22050
22169
  }
22051
22170
  });
22052
22171
 
22172
+ // src/indexer/build.ts
22173
+ function mergeIncrementalRecords(prevFiles, prevSymbols, prevChunks, changedSet, recomputed) {
22174
+ const keptFiles = prevFiles.filter((f) => !changedSet.has(f.path));
22175
+ const keptSymbols = prevSymbols.filter((s) => !changedSet.has(s.path));
22176
+ const keptChunks = prevChunks.filter((c) => !changedSet.has(c.path));
22177
+ return {
22178
+ files: [...keptFiles, ...recomputed.files],
22179
+ symbols: [...keptSymbols, ...recomputed.symbols],
22180
+ chunks: [...keptChunks, ...recomputed.chunks]
22181
+ };
22182
+ }
22183
+ function sortIndexedRecords(records) {
22184
+ records.files.sort((a, b) => a.path.localeCompare(b.path));
22185
+ records.symbols.sort((a, b) => a.path === b.path ? a.line - b.line : a.path.localeCompare(b.path));
22186
+ records.chunks.sort((a, b) => a.id.localeCompare(b.id));
22187
+ }
22188
+ var init_build = __esm({
22189
+ "src/indexer/build.ts"() {
22190
+ "use strict";
22191
+ }
22192
+ });
22193
+
22194
+ // src/query.ts
22195
+ function normalizeText(input) {
22196
+ return input.toLowerCase();
22197
+ }
22198
+ function toConfidence(score) {
22199
+ if (score >= 8) return "high";
22200
+ if (score >= 4) return "medium";
22201
+ return "low";
22202
+ }
22203
+ function scoreFile(path, parsed) {
22204
+ const pathLower = normalizeText(path);
22205
+ let score = pathLower.includes(parsed.normalized) ? 8 : 2;
22206
+ const reasons = [];
22207
+ if (pathLower.includes(parsed.normalized)) {
22208
+ reasons.push({ label: "exact-path-match", detail: "Path contains the full normalized query" });
22209
+ }
22210
+ for (const token of parsed.tokens) {
22211
+ if (pathLower.includes(token)) {
22212
+ score += 1.5;
22213
+ reasons.push({ label: "token-path-match", detail: `Path contains token '${token}'` });
22214
+ }
22215
+ }
22216
+ return { score, reasons };
22217
+ }
22218
+ function scoreSymbol(symbol, parsed) {
22219
+ const nameLower = normalizeText(symbol.name);
22220
+ const pathLower = normalizeText(symbol.path);
22221
+ let score = nameLower.includes(parsed.normalized) ? 9 : 3;
22222
+ const reasons = [];
22223
+ if (nameLower.includes(parsed.normalized)) {
22224
+ reasons.push({ label: "exact-symbol-match", detail: "Symbol name contains the full query" });
22225
+ }
22226
+ for (const token of parsed.tokens) {
22227
+ if (nameLower.includes(token)) {
22228
+ score += 2;
22229
+ reasons.push({ label: "token-symbol-match", detail: `Symbol name contains token '${token}'` });
22230
+ }
22231
+ if (pathLower.includes(token)) {
22232
+ score += 0.8;
22233
+ reasons.push({ label: "token-path-context", detail: `Symbol path contains token '${token}'` });
22234
+ }
22235
+ }
22236
+ return { score, reasons };
22237
+ }
22238
+ function scoreChunk(chunk, parsed) {
22239
+ const hay = normalizeText(`${chunk.path}
22240
+ ${chunk.content}`);
22241
+ const pathLower = normalizeText(chunk.path);
22242
+ let score = hay.includes(parsed.normalized) ? 7 : 2;
22243
+ const reasons = [];
22244
+ if (hay.includes(parsed.normalized)) {
22245
+ reasons.push({ label: "exact-content-match", detail: "Chunk content contains the full query" });
22246
+ }
22247
+ for (const token of parsed.tokens) {
22248
+ if (hay.includes(token)) {
22249
+ score += 1.3;
22250
+ reasons.push({ label: "token-content-match", detail: `Chunk content contains token '${token}'` });
22251
+ }
22252
+ if (pathLower.includes(token)) {
22253
+ score += 1;
22254
+ reasons.push({ label: "token-path-match", detail: `Chunk path contains token '${token}'` });
22255
+ }
22256
+ }
22257
+ return { score, reasons };
22258
+ }
22259
+ function ensureLookupReasons(reasons, label, detail) {
22260
+ if (reasons.length > 0) return reasons;
22261
+ return [{ label, detail }];
22262
+ }
22263
+ function rankLookupResults(items, scorer, fallbackReason) {
22264
+ return items.map((item) => {
22265
+ const scored = scorer(item);
22266
+ const reasons = ensureLookupReasons(scored.reasons, fallbackReason.label, fallbackReason.detail);
22267
+ return { item, score: scored.score, confidence: toConfidence(scored.score), reasons };
22268
+ }).sort((a, b) => b.score - a.score);
22269
+ }
22270
+ var init_query = __esm({
22271
+ "src/query.ts"() {
22272
+ "use strict";
22273
+ }
22274
+ });
22275
+
22053
22276
  // src/indexer.ts
22054
22277
  import { createHash } from "node:crypto";
22055
22278
  import { existsSync as existsSync2 } from "node:fs";
22056
22279
  import { mkdir, readdir, readFile, stat, writeFile } from "node:fs/promises";
22057
- import { join as join2, relative } from "node:path";
22280
+ import { join as join3, relative as relative2 } from "node:path";
22058
22281
  import { spawnSync } from "node:child_process";
22059
- function getIndexDir(workspace) {
22060
- return join2(workspace, ".agents", "index");
22282
+ function cacheKey(workspace, stateRoot) {
22283
+ return `${workspace}::${resolveIndexDir(workspace, stateRoot)}`;
22284
+ }
22285
+ function setIndexCache(key, entry) {
22286
+ INDEX_CACHE.set(key, entry);
22287
+ if (INDEX_CACHE.size > MAX_INDEX_CACHE_SIZE) {
22288
+ const first = INDEX_CACHE.keys().next().value;
22289
+ if (first) INDEX_CACHE.delete(first);
22290
+ }
22291
+ }
22292
+ function setStatusCache(key, value) {
22293
+ STATUS_CACHE.set(key, { value, ts: Date.now() });
22294
+ if (STATUS_CACHE.size > MAX_STATUS_CACHE_SIZE) {
22295
+ const first = STATUS_CACHE.keys().next().value;
22296
+ if (first) STATUS_CACHE.delete(first);
22297
+ }
22298
+ }
22299
+ function getIndexDir(workspace, stateRoot) {
22300
+ return resolveIndexDir(workspace, stateRoot);
22061
22301
  }
22062
- function getIndexPath(workspace, file) {
22063
- return join2(getIndexDir(workspace), file);
22302
+ function getIndexPath(workspace, file, stateRoot) {
22303
+ return join3(getIndexDir(workspace, stateRoot), file);
22064
22304
  }
22065
22305
  function hashText(content) {
22066
22306
  return createHash("sha1").update(content).digest("hex");
@@ -22123,18 +22363,19 @@ function hasDirtyWorkspace(workspace) {
22123
22363
  if (raw === null) return false;
22124
22364
  return raw.length > 0;
22125
22365
  }
22126
- async function listFilesFallback(workspace) {
22366
+ async function listFilesFallback(workspace, stateRoot) {
22127
22367
  const out = [];
22368
+ const stateRootRel = relativeStateRoot(workspace, stateRoot);
22128
22369
  async function walk(abs) {
22129
22370
  const items = await readdir(abs, { withFileTypes: true });
22130
22371
  for (const item of items) {
22131
22372
  if (item.name === ".git" || item.name === "node_modules") continue;
22132
- if (item.name === ".agents") continue;
22133
- const nextAbs = join2(abs, item.name);
22373
+ if (stateRootRel && item.name === stateRootRel.split("/")[0]) continue;
22374
+ const nextAbs = join3(abs, item.name);
22134
22375
  if (item.isDirectory()) {
22135
22376
  await walk(nextAbs);
22136
22377
  } else if (item.isFile()) {
22137
- out.push(relative(workspace, nextAbs));
22378
+ out.push(relative2(workspace, nextAbs));
22138
22379
  }
22139
22380
  }
22140
22381
  }
@@ -22168,16 +22409,16 @@ async function mtimeMs(path) {
22168
22409
  return null;
22169
22410
  }
22170
22411
  }
22171
- function normalizeText(input) {
22412
+ function normalizeText2(input) {
22172
22413
  return input.toLowerCase();
22173
22414
  }
22174
22415
  function tokenize(input) {
22175
- const normalized = normalizeText(input);
22416
+ const normalized = normalizeText2(input);
22176
22417
  const tokens = normalized.split(/[^a-z0-9_./-]+/).map((token) => token.trim()).filter((token) => token.length >= 3 && token.length <= 64).filter((token) => !STOP_TOKENS.has(token));
22177
22418
  return [...new Set(tokens)];
22178
22419
  }
22179
22420
  function normalizeQuery(input) {
22180
- return normalizeText(input).replace(/\s+/g, " ").trim();
22421
+ return normalizeText2(input).replace(/\s+/g, " ").trim();
22181
22422
  }
22182
22423
  function resolveIntent(normalized, tokens, requested = "auto") {
22183
22424
  if (requested !== "auto") return requested;
@@ -22187,8 +22428,8 @@ function resolveIntent(normalized, tokens, requested = "auto") {
22187
22428
  if (tokens.some((token) => SYMBOL_HINT_TOKENS.has(token))) return "symbols";
22188
22429
  return "code";
22189
22430
  }
22190
- function cacheParsedQuery(cacheKey, parsed) {
22191
- QUERY_PARSE_CACHE.set(cacheKey, parsed);
22431
+ function cacheParsedQuery(cacheKey2, parsed) {
22432
+ QUERY_PARSE_CACHE.set(cacheKey2, parsed);
22192
22433
  if (QUERY_PARSE_CACHE.size > MAX_QUERY_PARSE_CACHE) {
22193
22434
  const first = QUERY_PARSE_CACHE.keys().next().value;
22194
22435
  if (first) QUERY_PARSE_CACHE.delete(first);
@@ -22196,8 +22437,8 @@ function cacheParsedQuery(cacheKey, parsed) {
22196
22437
  return parsed;
22197
22438
  }
22198
22439
  function parseQuery(input, intent = "auto") {
22199
- const cacheKey = `${intent}\0${input}`;
22200
- const cached2 = QUERY_PARSE_CACHE.get(cacheKey);
22440
+ const cacheKey2 = `${intent}\0${input}`;
22441
+ const cached2 = QUERY_PARSE_CACHE.get(cacheKey2);
22201
22442
  if (cached2) return cached2;
22202
22443
  const normalized = normalizeQuery(input);
22203
22444
  let tokens = tokenize(normalized);
@@ -22211,7 +22452,7 @@ function parseQuery(input, intent = "auto") {
22211
22452
  pathTokens,
22212
22453
  intent: resolveIntent(normalized, tokens, intent)
22213
22454
  };
22214
- return cacheParsedQuery(cacheKey, parsed);
22455
+ return cacheParsedQuery(cacheKey2, parsed);
22215
22456
  }
22216
22457
  function codePathBias(pathLower) {
22217
22458
  let score = 0;
@@ -22286,7 +22527,7 @@ function buildCacheEntry(files, symbols, chunks, mtimes) {
22286
22527
  const normalizePath = (path) => {
22287
22528
  let cached2 = pathNormCache.get(path);
22288
22529
  if (cached2 === void 0) {
22289
- cached2 = normalizeText(path);
22530
+ cached2 = normalizeText2(path);
22290
22531
  pathNormCache.set(path, cached2);
22291
22532
  }
22292
22533
  return cached2;
@@ -22311,13 +22552,13 @@ function buildCacheEntry(files, symbols, chunks, mtimes) {
22311
22552
  return cached2;
22312
22553
  };
22313
22554
  const chunksPathLower = chunks.map((c) => normalizePath(c.path));
22314
- const chunksTopLevelLower = chunks.map((c) => normalizeText(getTopLevel(c.path)));
22315
- const chunksBasenameLower = chunks.map((c) => normalizeText(getBasename(c.path)));
22316
- const chunksSearch = chunks.map((c) => normalizeText(`${c.path}
22555
+ const chunksTopLevelLower = chunks.map((c) => normalizeText2(getTopLevel(c.path)));
22556
+ const chunksBasenameLower = chunks.map((c) => normalizeText2(getBasename(c.path)));
22557
+ const chunksSearch = chunks.map((c) => normalizeText2(`${c.path}
22317
22558
  ${c.content}`));
22318
22559
  const chunksCodeBias = chunksPathLower.map((pathLower) => codePathBias(pathLower));
22319
22560
  const chunksDocsBias = chunksPathLower.map((pathLower, i) => docsPathBias(pathLower, chunksBasenameLower[i] ?? ""));
22320
- const symbolsLower = symbols.map((s) => normalizeText(s.name));
22561
+ const symbolsLower = symbols.map((s) => normalizeText2(s.name));
22321
22562
  return {
22322
22563
  filesMtimeMs: mtimes.files,
22323
22564
  symbolsMtimeMs: mtimes.symbols,
@@ -22401,8 +22642,8 @@ function makeChunks(path, content) {
22401
22642
  }
22402
22643
  return chunks;
22403
22644
  }
22404
- async function readExistingIndex(workspace, name) {
22405
- const p = getIndexPath(workspace, name);
22645
+ async function readExistingIndex(workspace, name, stateRoot) {
22646
+ const p = getIndexPath(workspace, name, stateRoot);
22406
22647
  if (!existsSync2(p)) return [];
22407
22648
  try {
22408
22649
  const raw = await readFile(p, "utf-8");
@@ -22411,24 +22652,25 @@ async function readExistingIndex(workspace, name) {
22411
22652
  return [];
22412
22653
  }
22413
22654
  }
22414
- async function loadCachedIndex(workspace) {
22415
- const filesPath = getIndexPath(workspace, "files.ndjson");
22416
- const symbolsPath = getIndexPath(workspace, "symbols.ndjson");
22417
- const chunksPath = getIndexPath(workspace, "chunks.ndjson");
22655
+ async function loadCachedIndex(workspace, stateRoot) {
22656
+ const filesPath = getIndexPath(workspace, "files.ndjson", stateRoot);
22657
+ const symbolsPath = getIndexPath(workspace, "symbols.ndjson", stateRoot);
22658
+ const chunksPath = getIndexPath(workspace, "chunks.ndjson", stateRoot);
22418
22659
  const [filesMtime, symbolsMtime, chunksMtime] = await Promise.all([
22419
22660
  mtimeMs(filesPath),
22420
22661
  mtimeMs(symbolsPath),
22421
22662
  mtimeMs(chunksPath)
22422
22663
  ]);
22423
- const cached2 = INDEX_CACHE.get(workspace);
22664
+ const key = cacheKey(workspace, stateRoot);
22665
+ const cached2 = INDEX_CACHE.get(key);
22424
22666
  if (cached2 && cached2.filesMtimeMs === filesMtime && cached2.symbolsMtimeMs === symbolsMtime && cached2.chunksMtimeMs === chunksMtime) {
22425
22667
  diagnostics.updateCacheSizes(INDEX_CACHE.size, STATUS_CACHE.size);
22426
22668
  return cached2;
22427
22669
  }
22428
22670
  const [files, symbols, chunks] = await Promise.all([
22429
- readExistingIndex(workspace, "files.ndjson"),
22430
- readExistingIndex(workspace, "symbols.ndjson"),
22431
- readExistingIndex(workspace, "chunks.ndjson")
22671
+ readExistingIndex(workspace, "files.ndjson", stateRoot),
22672
+ readExistingIndex(workspace, "symbols.ndjson", stateRoot),
22673
+ readExistingIndex(workspace, "chunks.ndjson", stateRoot)
22432
22674
  ]);
22433
22675
  const entry = buildCacheEntry(files, symbols, chunks, {
22434
22676
  files: filesMtime,
@@ -22436,11 +22678,11 @@ async function loadCachedIndex(workspace) {
22436
22678
  chunks: chunksMtime
22437
22679
  });
22438
22680
  if (cached2) diagnostics.recordCacheInvalidation();
22439
- INDEX_CACHE.set(workspace, entry);
22681
+ setIndexCache(key, entry);
22440
22682
  diagnostics.updateCacheSizes(INDEX_CACHE.size, STATUS_CACHE.size);
22441
22683
  return entry;
22442
22684
  }
22443
- async function writeHumanDocs(workspace, files) {
22685
+ async function writeHumanDocs(workspace, files, stateRoot) {
22444
22686
  const byTop = /* @__PURE__ */ new Map();
22445
22687
  for (const file of files) {
22446
22688
  byTop.set(file.top_level, (byTop.get(file.top_level) ?? 0) + 1);
@@ -22450,7 +22692,7 @@ async function writeHumanDocs(workspace, files) {
22450
22692
  dirsLines.push(`- ${dir}: ${count}`);
22451
22693
  }
22452
22694
  dirsLines.push("");
22453
- await writeFile(getIndexPath(workspace, "dirs.md"), dirsLines.join("\n"), "utf-8");
22695
+ await writeFile(getIndexPath(workspace, "dirs.md", stateRoot), dirsLines.join("\n"), "utf-8");
22454
22696
  const entryCandidates = /* @__PURE__ */ new Set([
22455
22697
  "README.md",
22456
22698
  "AGENTS.md",
@@ -22464,15 +22706,16 @@ async function writeHumanDocs(workspace, files) {
22464
22706
  const entryLines = ["# Entrypoints", "", "High-signal files for navigation:", ""];
22465
22707
  for (const path of entries) entryLines.push(`- ${path}`);
22466
22708
  entryLines.push("");
22467
- await writeFile(getIndexPath(workspace, "entrypoints.md"), entryLines.join("\n"), "utf-8");
22709
+ await writeFile(getIndexPath(workspace, "entrypoints.md", stateRoot), entryLines.join("\n"), "utf-8");
22468
22710
  }
22469
- async function getStatus(workspace) {
22470
- const cached2 = STATUS_CACHE.get(workspace);
22711
+ async function getStatus(workspace, options = {}) {
22712
+ const key = cacheKey(workspace, options.state_root);
22713
+ const cached2 = STATUS_CACHE.get(key);
22471
22714
  if (cached2 && Date.now() - cached2.ts < STATUS_CACHE_TTL_MS) {
22472
22715
  diagnostics.updateCacheSizes(INDEX_CACHE.size, STATUS_CACHE.size);
22473
22716
  return cached2.value;
22474
22717
  }
22475
- const manifestPath = getIndexPath(workspace, "manifest.json");
22718
+ const manifestPath = getIndexPath(workspace, "manifest.json", options.state_root);
22476
22719
  const currentHead = runGit(workspace, ["rev-parse", "HEAD"]);
22477
22720
  if (!existsSync2(manifestPath)) {
22478
22721
  const status2 = {
@@ -22484,7 +22727,7 @@ async function getStatus(workspace) {
22484
22727
  };
22485
22728
  if (hasDirtyWorkspace(workspace)) status2.reasons.push("workspace-dirty");
22486
22729
  status2.stale = status2.reasons.length > 0;
22487
- STATUS_CACHE.set(workspace, { value: status2, ts: Date.now() });
22730
+ setStatusCache(key, status2);
22488
22731
  diagnostics.updateCacheSizes(INDEX_CACHE.size, STATUS_CACHE.size);
22489
22732
  return status2;
22490
22733
  }
@@ -22501,7 +22744,7 @@ async function getStatus(workspace) {
22501
22744
  current_git_head: currentHead
22502
22745
  };
22503
22746
  if (hasDirtyWorkspace(workspace)) malformedStatus.reasons.push("workspace-dirty");
22504
- STATUS_CACHE.set(workspace, { value: malformedStatus, ts: Date.now() });
22747
+ setStatusCache(key, malformedStatus);
22505
22748
  diagnostics.updateCacheSizes(INDEX_CACHE.size, STATUS_CACHE.size);
22506
22749
  return malformedStatus;
22507
22750
  }
@@ -22520,7 +22763,7 @@ async function getStatus(workspace) {
22520
22763
  manifest,
22521
22764
  current_git_head: currentHead
22522
22765
  };
22523
- STATUS_CACHE.set(workspace, { value: status, ts: Date.now() });
22766
+ setStatusCache(key, status);
22524
22767
  diagnostics.updateCacheSizes(INDEX_CACHE.size, STATUS_CACHE.size);
22525
22768
  return status;
22526
22769
  }
@@ -22528,10 +22771,11 @@ function shouldRefreshDiscover(status) {
22528
22771
  if (!status.stale) return false;
22529
22772
  return status.reasons.some((reason) => reason !== "workspace-dirty");
22530
22773
  }
22531
- async function processFile(workspace, rel) {
22532
- if (rel.startsWith(".agents/index/")) return { file: null, symbols: [], chunks: [] };
22774
+ async function processFile(workspace, rel, stateRoot) {
22775
+ const stateRootRel = relativeStateRoot(workspace, stateRoot);
22776
+ if (stateRootRel && (rel === stateRootRel || rel.startsWith(`${stateRootRel}/`))) return { file: null, symbols: [], chunks: [] };
22533
22777
  if (rel.startsWith(".git/")) return { file: null, symbols: [], chunks: [] };
22534
- const abs = join2(workspace, rel);
22778
+ const abs = join3(workspace, rel);
22535
22779
  let st;
22536
22780
  try {
22537
22781
  st = await stat(abs);
@@ -22561,13 +22805,13 @@ async function processFile(workspace, rel) {
22561
22805
  chunks: makeChunks(rel, content)
22562
22806
  };
22563
22807
  }
22564
- async function computeForPaths(workspace, paths) {
22808
+ async function computeForPaths(workspace, paths, stateRoot) {
22565
22809
  const files = [];
22566
22810
  const symbols = [];
22567
22811
  const chunks = [];
22568
22812
  for (let i = 0; i < paths.length; i += BATCH_SIZE) {
22569
22813
  const batch = paths.slice(i, i + BATCH_SIZE);
22570
- const results = await Promise.all(batch.map((rel) => processFile(workspace, rel)));
22814
+ const results = await Promise.all(batch.map((rel) => processFile(workspace, rel, stateRoot)));
22571
22815
  for (const result of results) {
22572
22816
  if (result.file) {
22573
22817
  files.push(result.file);
@@ -22578,24 +22822,24 @@ async function computeForPaths(workspace, paths) {
22578
22822
  }
22579
22823
  return { files, symbols, chunks };
22580
22824
  }
22581
- async function buildIndex(workspace, mode = "full") {
22825
+ async function buildIndex(workspace, mode = "full", options = {}) {
22582
22826
  const buildStart = nowMs();
22583
- const indexDir = getIndexDir(workspace);
22827
+ const indexDir = getIndexDir(workspace, options.state_root);
22584
22828
  await mkdir(indexDir, { recursive: true });
22585
- const tracked = listTrackedFiles(workspace) ?? await listFilesFallback(workspace);
22829
+ const tracked = listTrackedFiles(workspace) ?? await listFilesFallback(workspace, options.state_root);
22586
22830
  const gitHead = runGit(workspace, ["rev-parse", "HEAD"]);
22587
22831
  let files = [];
22588
22832
  let symbols = [];
22589
22833
  let chunks = [];
22590
22834
  if (mode === "full") {
22591
- const computed = await computeForPaths(workspace, tracked);
22835
+ const computed = await computeForPaths(workspace, tracked, options.state_root);
22592
22836
  files = computed.files;
22593
22837
  symbols = computed.symbols;
22594
22838
  chunks = computed.chunks;
22595
22839
  } else {
22596
- const prevStatus = await getStatus(workspace);
22840
+ const prevStatus = await getStatus(workspace, options);
22597
22841
  if (!prevStatus.exists || !prevStatus.manifest?.git_head) {
22598
- const computed = await computeForPaths(workspace, tracked);
22842
+ const computed = await computeForPaths(workspace, tracked, options.state_root);
22599
22843
  files = computed.files;
22600
22844
  symbols = computed.symbols;
22601
22845
  chunks = computed.chunks;
@@ -22605,33 +22849,29 @@ async function buildIndex(workspace, mode = "full") {
22605
22849
  for (const prevFile of await readExistingIndex(workspace, "files.ndjson")) {
22606
22850
  if (!trackedSet.has(prevFile.path)) changedSet.add(prevFile.path);
22607
22851
  }
22608
- const prevFiles = await readExistingIndex(workspace, "files.ndjson");
22609
- const prevSymbols = await readExistingIndex(workspace, "symbols.ndjson");
22610
- const prevChunks = await readExistingIndex(workspace, "chunks.ndjson");
22611
- const keptFiles = prevFiles.filter((f) => !changedSet.has(f.path));
22612
- const keptSymbols = prevSymbols.filter((s) => !changedSet.has(s.path));
22613
- const keptChunks = prevChunks.filter((c) => !changedSet.has(c.path));
22852
+ const prevFiles = await readExistingIndex(workspace, "files.ndjson", options.state_root);
22853
+ const prevSymbols = await readExistingIndex(workspace, "symbols.ndjson", options.state_root);
22854
+ const prevChunks = await readExistingIndex(workspace, "chunks.ndjson", options.state_root);
22614
22855
  const changedPaths = [...changedSet];
22615
- const recomputed = await computeForPaths(workspace, changedPaths);
22616
- files = [...keptFiles, ...recomputed.files];
22617
- symbols = [...keptSymbols, ...recomputed.symbols];
22618
- chunks = [...keptChunks, ...recomputed.chunks];
22619
- }
22620
- }
22621
- files.sort((a, b) => a.path.localeCompare(b.path));
22622
- symbols.sort((a, b) => a.path === b.path ? a.line - b.line : a.path.localeCompare(b.path));
22623
- chunks.sort((a, b) => a.id.localeCompare(b.id));
22624
- await writeFile(getIndexPath(workspace, "files.ndjson"), toNdjson(files), "utf-8");
22625
- await writeFile(getIndexPath(workspace, "symbols.ndjson"), toNdjson(symbols), "utf-8");
22626
- await writeFile(getIndexPath(workspace, "chunks.ndjson"), toNdjson(chunks), "utf-8");
22627
- await writeHumanDocs(workspace, files);
22856
+ const recomputed = await computeForPaths(workspace, changedPaths, options.state_root);
22857
+ const merged = mergeIncrementalRecords(prevFiles, prevSymbols, prevChunks, changedSet, recomputed);
22858
+ files = merged.files;
22859
+ symbols = merged.symbols;
22860
+ chunks = merged.chunks;
22861
+ }
22862
+ }
22863
+ sortIndexedRecords({ files, symbols, chunks });
22864
+ await writeFile(getIndexPath(workspace, "files.ndjson", options.state_root), toNdjson(files), "utf-8");
22865
+ await writeFile(getIndexPath(workspace, "symbols.ndjson", options.state_root), toNdjson(symbols), "utf-8");
22866
+ await writeFile(getIndexPath(workspace, "chunks.ndjson", options.state_root), toNdjson(chunks), "utf-8");
22867
+ await writeHumanDocs(workspace, files, options.state_root);
22628
22868
  const [filesMtime, symbolsMtime, chunksMtime] = await Promise.all([
22629
- mtimeMs(getIndexPath(workspace, "files.ndjson")),
22630
- mtimeMs(getIndexPath(workspace, "symbols.ndjson")),
22631
- mtimeMs(getIndexPath(workspace, "chunks.ndjson"))
22869
+ mtimeMs(getIndexPath(workspace, "files.ndjson", options.state_root)),
22870
+ mtimeMs(getIndexPath(workspace, "symbols.ndjson", options.state_root)),
22871
+ mtimeMs(getIndexPath(workspace, "chunks.ndjson", options.state_root))
22632
22872
  ]);
22633
- INDEX_CACHE.set(
22634
- workspace,
22873
+ setIndexCache(
22874
+ cacheKey(workspace, options.state_root),
22635
22875
  buildCacheEntry(files, symbols, chunks, {
22636
22876
  files: filesMtime,
22637
22877
  symbols: symbolsMtime,
@@ -22648,9 +22888,9 @@ async function buildIndex(workspace, mode = "full") {
22648
22888
  symbol_count: symbols.length,
22649
22889
  chunk_count: chunks.length
22650
22890
  };
22651
- await writeFile(getIndexPath(workspace, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
22891
+ await writeFile(getIndexPath(workspace, "manifest.json", options.state_root), `${JSON.stringify(manifest, null, 2)}
22652
22892
  `, "utf-8");
22653
- STATUS_CACHE.delete(workspace);
22893
+ STATUS_CACHE.delete(cacheKey(workspace, options.state_root));
22654
22894
  diagnostics.recordIndexBuild();
22655
22895
  diagnostics.recordBuildLatency(nowMs() - buildStart);
22656
22896
  diagnostics.recordCacheInvalidation();
@@ -22659,7 +22899,7 @@ async function buildIndex(workspace, mode = "full") {
22659
22899
  }
22660
22900
  function queryFilesFromCache(cache, parsed, limit) {
22661
22901
  const key = `${parsed.intent}\0${parsed.normalized}\0${limit}`;
22662
- const cached2 = cache.queryFilesCache.get(key);
22902
+ const cached2 = getLru(cache.queryFilesCache, key);
22663
22903
  if (cached2) {
22664
22904
  diagnostics.recordCacheHit();
22665
22905
  return cached2;
@@ -22673,18 +22913,18 @@ function queryFilesFromCache(cache, parsed, limit) {
22673
22913
  for (const token of parsed.tokens) {
22674
22914
  if (pathLower.includes(token)) score += token.includes("/") ? 3 : 1.5;
22675
22915
  }
22676
- const topDir = normalizeText(topLevel(pathLower));
22916
+ const topDir = normalizeText2(topLevel(pathLower));
22677
22917
  if (parsed.intent === "code" && CODE_TOP_LEVEL_HINTS.has(topDir)) score += 0.6;
22678
22918
  if (parsed.intent === "docs" && (pathLower.endsWith(".md") || pathLower.includes("/docs/"))) score += 1.5;
22679
22919
  if (score > 0.5) heap.insert(i, score);
22680
22920
  }
22681
22921
  const result = heap.toSortedArray().map((index) => cache.files[index]);
22682
- cache.queryFilesCache.set(key, result);
22922
+ setLru(cache.queryFilesCache, key, result, MAX_QUERY_CACHE_SIZE);
22683
22923
  return result;
22684
22924
  }
22685
22925
  function querySymbolsFromCache(cache, parsed, limit) {
22686
22926
  const key = `${parsed.intent}\0${parsed.normalized}\0${limit}`;
22687
- const cached2 = cache.querySymbolsCache.get(key);
22927
+ const cached2 = getLru(cache.querySymbolsCache, key);
22688
22928
  if (cached2) {
22689
22929
  diagnostics.recordCacheHit();
22690
22930
  return cached2;
@@ -22703,7 +22943,7 @@ function querySymbolsFromCache(cache, parsed, limit) {
22703
22943
  const symbol = cache.symbols[i];
22704
22944
  if (!symbol) continue;
22705
22945
  const nameLower = cache.symbolsLower[i] ?? "";
22706
- const pathLower = normalizeText(symbol.path);
22946
+ const pathLower = normalizeText2(symbol.path);
22707
22947
  let score = nameLower.includes(parsed.normalized) ? 7 : 0;
22708
22948
  for (const token of parsed.tokens) {
22709
22949
  if (nameLower.includes(token)) score += 2;
@@ -22714,7 +22954,7 @@ function querySymbolsFromCache(cache, parsed, limit) {
22714
22954
  if (score >= 1.5) heap.insert(i, score);
22715
22955
  }
22716
22956
  const result = heap.toSortedArray().map((index) => cache.symbols[index]);
22717
- cache.querySymbolsCache.set(key, result);
22957
+ setLru(cache.querySymbolsCache, key, result, MAX_QUERY_CACHE_SIZE);
22718
22958
  return result;
22719
22959
  }
22720
22960
  function queryChunksFromCache(cache, parsed, limit, options) {
@@ -22726,15 +22966,15 @@ function queryChunksFromCache(cache, parsed, limit, options) {
22726
22966
  options.path_prefix ?? "",
22727
22967
  options.language ?? ""
22728
22968
  ].join("\0");
22729
- const cached2 = cache.queryChunksCache.get(key);
22969
+ const cached2 = getLru(cache.queryChunksCache, key);
22730
22970
  if (cached2) {
22731
22971
  diagnostics.recordCacheHit();
22732
22972
  return cached2;
22733
22973
  }
22734
22974
  diagnostics.recordCacheMiss();
22735
22975
  if (!parsed.normalized) return [];
22736
- const languageFilter = options.language ? normalizeText(options.language) : "";
22737
- const pathPrefix = options.path_prefix ? normalizeText(options.path_prefix) : "";
22976
+ const languageFilter = options.language ? normalizeText2(options.language) : "";
22977
+ const pathPrefix = options.path_prefix ? normalizeText2(options.path_prefix) : "";
22738
22978
  const shouldPreferCode = options.prefer_code ?? parsed.intent !== "docs";
22739
22979
  const tokenScoreByIndex = /* @__PURE__ */ new Map();
22740
22980
  for (const token of parsed.tokens) {
@@ -22774,21 +23014,21 @@ function queryChunksFromCache(cache, parsed, limit, options) {
22774
23014
  if (score >= 2) heap.insert(i, score);
22775
23015
  }
22776
23016
  const result = heap.toSortedArray().map((index) => cache.chunks[index]);
22777
- cache.queryChunksCache.set(key, result);
23017
+ setLru(cache.queryChunksCache, key, result, MAX_QUERY_CACHE_SIZE);
22778
23018
  return result;
22779
23019
  }
22780
- async function queryFiles(workspace, q, limit = 20) {
23020
+ async function queryFiles(workspace, q, limit = 20, options = {}) {
22781
23021
  const start = nowMs();
22782
- const cache = await loadCachedIndex(workspace);
23022
+ const cache = await loadCachedIndex(workspace, options.state_root);
22783
23023
  const parsed = parseQuery(q);
22784
23024
  const out = queryFilesFromCache(cache, parsed, limit);
22785
23025
  diagnostics.recordQuery(nowMs() - start);
22786
23026
  diagnostics.updateCacheSizes(INDEX_CACHE.size, STATUS_CACHE.size);
22787
23027
  return out;
22788
23028
  }
22789
- async function querySymbols(workspace, q, limit = 20) {
23029
+ async function querySymbols(workspace, q, limit = 20, options = {}) {
22790
23030
  const start = nowMs();
22791
- const cache = await loadCachedIndex(workspace);
23031
+ const cache = await loadCachedIndex(workspace, options.state_root);
22792
23032
  const parsed = parseQuery(q);
22793
23033
  const out = querySymbolsFromCache(cache, parsed, limit);
22794
23034
  diagnostics.recordQuery(nowMs() - start);
@@ -22797,7 +23037,7 @@ async function querySymbols(workspace, q, limit = 20) {
22797
23037
  }
22798
23038
  async function queryChunks(workspace, q, limit = 10, options = {}) {
22799
23039
  const start = nowMs();
22800
- const cache = await loadCachedIndex(workspace);
23040
+ const cache = await loadCachedIndex(workspace, options.state_root);
22801
23041
  const parsed = parseQuery(q, options.intent);
22802
23042
  const out = queryChunksFromCache(cache, parsed, limit, options);
22803
23043
  diagnostics.recordQuery(nowMs() - start);
@@ -22806,7 +23046,7 @@ async function queryChunks(workspace, q, limit = 10, options = {}) {
22806
23046
  }
22807
23047
  async function discoverIndex(workspace, query, options = {}) {
22808
23048
  const start = nowMs();
22809
- const cache = await loadCachedIndex(workspace);
23049
+ const cache = await loadCachedIndex(workspace, options.state_root);
22810
23050
  const parsed = parseQuery(query, options.intent);
22811
23051
  const filesLimit = options.files_limit ?? 20;
22812
23052
  const symbolsLimit = options.symbols_limit ?? (parsed.intent === "symbols" ? 40 : 20);
@@ -22824,81 +23064,9 @@ async function discoverIndex(workspace, query, options = {}) {
22824
23064
  diagnostics.updateCacheSizes(INDEX_CACHE.size, STATUS_CACHE.size);
22825
23065
  return { intent: parsed.intent, files, symbols, chunks };
22826
23066
  }
22827
- function toConfidence(score) {
22828
- if (score >= 8) return "high";
22829
- if (score >= 4) return "medium";
22830
- return "low";
22831
- }
22832
- function scoreFile(path, parsed) {
22833
- const pathLower = normalizeText(path);
22834
- let score = pathLower.includes(parsed.normalized) ? 8 : 2;
22835
- const reasons = [];
22836
- if (pathLower.includes(parsed.normalized)) {
22837
- reasons.push({ label: "exact-path-match", detail: "Path contains the full normalized query" });
22838
- }
22839
- for (const token of parsed.tokens) {
22840
- if (pathLower.includes(token)) {
22841
- score += 1.5;
22842
- reasons.push({ label: "token-path-match", detail: `Path contains token '${token}'` });
22843
- }
22844
- }
22845
- return { score, reasons };
22846
- }
22847
- function scoreSymbol(symbol, parsed) {
22848
- const nameLower = normalizeText(symbol.name);
22849
- const pathLower = normalizeText(symbol.path);
22850
- let score = nameLower.includes(parsed.normalized) ? 9 : 3;
22851
- const reasons = [];
22852
- if (nameLower.includes(parsed.normalized)) {
22853
- reasons.push({ label: "exact-symbol-match", detail: "Symbol name contains the full query" });
22854
- }
22855
- for (const token of parsed.tokens) {
22856
- if (nameLower.includes(token)) {
22857
- score += 2;
22858
- reasons.push({ label: "token-symbol-match", detail: `Symbol name contains token '${token}'` });
22859
- }
22860
- if (pathLower.includes(token)) {
22861
- score += 0.8;
22862
- reasons.push({ label: "token-path-context", detail: `Symbol path contains token '${token}'` });
22863
- }
22864
- }
22865
- return { score, reasons };
22866
- }
22867
- function scoreChunk(chunk, parsed) {
22868
- const hay = normalizeText(`${chunk.path}
22869
- ${chunk.content}`);
22870
- const pathLower = normalizeText(chunk.path);
22871
- let score = hay.includes(parsed.normalized) ? 7 : 2;
22872
- const reasons = [];
22873
- if (hay.includes(parsed.normalized)) {
22874
- reasons.push({ label: "exact-content-match", detail: "Chunk content contains the full query" });
22875
- }
22876
- for (const token of parsed.tokens) {
22877
- if (hay.includes(token)) {
22878
- score += 1.3;
22879
- reasons.push({ label: "token-content-match", detail: `Chunk content contains token '${token}'` });
22880
- }
22881
- if (pathLower.includes(token)) {
22882
- score += 1;
22883
- reasons.push({ label: "token-path-match", detail: `Chunk path contains token '${token}'` });
22884
- }
22885
- }
22886
- return { score, reasons };
22887
- }
22888
- function ensureLookupReasons(reasons, label, detail) {
22889
- if (reasons.length > 0) return reasons;
22890
- return [{ label, detail }];
22891
- }
22892
- function rankLookupResults(items, scorer, fallbackReason) {
22893
- return items.map((item) => {
22894
- const scored = scorer(item);
22895
- const reasons = ensureLookupReasons(scored.reasons, fallbackReason.label, fallbackReason.detail);
22896
- return { item, score: scored.score, confidence: toConfidence(scored.score), reasons };
22897
- }).sort((a, b) => b.score - a.score);
22898
- }
22899
23067
  async function lookupIndex(workspace, query, options = {}) {
22900
23068
  const start = nowMs();
22901
- const cache = await loadCachedIndex(workspace);
23069
+ const cache = await loadCachedIndex(workspace, options.state_root);
22902
23070
  const parsed = parseQuery(query, options.intent);
22903
23071
  const filesLimit = options.files_limit ?? 8;
22904
23072
  const symbolsLimit = options.symbols_limit ?? (parsed.intent === "symbols" ? 20 : 12);
@@ -22973,78 +23141,27 @@ async function lookupIndex(workspace, query, options = {}) {
22973
23141
  diagnostics.updateCacheSizes(INDEX_CACHE.size, STATUS_CACHE.size);
22974
23142
  return response;
22975
23143
  }
22976
- var SCHEMA_VERSION, DEFAULT_STALE_HOURS, MAX_FILE_SIZE, CHUNK_SIZE_LINES, CHUNK_OVERLAP_LINES, BATCH_SIZE, TopKHeap, INDEX_CACHE, STATUS_CACHE, STATUS_CACHE_TTL_MS, STOP_TOKENS, DOC_HINT_TOKENS, SYMBOL_HINT_TOKENS, CODE_TOP_LEVEL_HINTS, MAX_QUERY_PARSE_CACHE, QUERY_PARSE_CACHE;
23144
+ var SCHEMA_VERSION, DEFAULT_STALE_HOURS, MAX_FILE_SIZE, CHUNK_SIZE_LINES, CHUNK_OVERLAP_LINES, BATCH_SIZE, INDEX_CACHE, STATUS_CACHE, STATUS_CACHE_TTL_MS, MAX_INDEX_CACHE_SIZE, MAX_STATUS_CACHE_SIZE, MAX_QUERY_CACHE_SIZE, STOP_TOKENS, DOC_HINT_TOKENS, SYMBOL_HINT_TOKENS, CODE_TOP_LEVEL_HINTS, MAX_QUERY_PARSE_CACHE, QUERY_PARSE_CACHE;
22977
23145
  var init_indexer = __esm({
22978
23146
  "src/indexer.ts"() {
22979
23147
  "use strict";
23148
+ init_cache();
22980
23149
  init_diagnostics();
23150
+ init_build();
23151
+ init_query();
23152
+ init_state_root();
22981
23153
  SCHEMA_VERSION = "1";
22982
23154
  DEFAULT_STALE_HOURS = 24;
22983
23155
  MAX_FILE_SIZE = 512 * 1024;
22984
23156
  CHUNK_SIZE_LINES = 120;
22985
23157
  CHUNK_OVERLAP_LINES = 20;
22986
23158
  BATCH_SIZE = 20;
22987
- TopKHeap = class {
22988
- heap = [];
22989
- k;
22990
- constructor(k) {
22991
- this.k = k;
22992
- }
22993
- parent(i) {
22994
- return Math.floor((i - 1) / 2);
22995
- }
22996
- left(i) {
22997
- return 2 * i + 1;
22998
- }
22999
- right(i) {
23000
- return 2 * i + 2;
23001
- }
23002
- swap(i, j) {
23003
- const temp = this.heap[i];
23004
- this.heap[i] = this.heap[j];
23005
- this.heap[j] = temp;
23006
- }
23007
- heapifyUp(i) {
23008
- while (i > 0) {
23009
- const p = this.parent(i);
23010
- if (this.heap[i].score >= this.heap[p].score) break;
23011
- this.swap(i, p);
23012
- i = p;
23013
- }
23014
- }
23015
- heapifyDown(i) {
23016
- while (true) {
23017
- let smallest = i;
23018
- const l = this.left(i);
23019
- const r = this.right(i);
23020
- if (l < this.heap.length && this.heap[l].score < this.heap[smallest].score) {
23021
- smallest = l;
23022
- }
23023
- if (r < this.heap.length && this.heap[r].score < this.heap[smallest].score) {
23024
- smallest = r;
23025
- }
23026
- if (smallest === i) break;
23027
- this.swap(i, smallest);
23028
- i = smallest;
23029
- }
23030
- }
23031
- insert(item, score) {
23032
- if (this.heap.length < this.k) {
23033
- this.heap.push({ item, score });
23034
- this.heapifyUp(this.heap.length - 1);
23035
- } else if (score > this.heap[0].score) {
23036
- this.heap[0] = { item, score };
23037
- this.heapifyDown(0);
23038
- }
23039
- }
23040
- toSortedArray() {
23041
- const sorted = [...this.heap].sort((a, b) => b.score - a.score);
23042
- return sorted.map((entry) => entry.item);
23043
- }
23044
- };
23045
23159
  INDEX_CACHE = /* @__PURE__ */ new Map();
23046
23160
  STATUS_CACHE = /* @__PURE__ */ new Map();
23047
23161
  STATUS_CACHE_TTL_MS = 1500;
23162
+ MAX_INDEX_CACHE_SIZE = 32;
23163
+ MAX_STATUS_CACHE_SIZE = 64;
23164
+ MAX_QUERY_CACHE_SIZE = 100;
23048
23165
  STOP_TOKENS = /* @__PURE__ */ new Set([
23049
23166
  "the",
23050
23167
  "and",
@@ -25735,10 +25852,10 @@ var require_helpers = __commonJS({
25735
25852
  return !arr.includes(node, i + 1);
25736
25853
  });
25737
25854
  nodes.sort(function(a, b) {
25738
- var relative3 = compareDocumentPosition(a, b);
25739
- if (relative3 & DocumentPosition.PRECEDING) {
25855
+ var relative4 = compareDocumentPosition(a, b);
25856
+ if (relative4 & DocumentPosition.PRECEDING) {
25740
25857
  return -1;
25741
- } else if (relative3 & DocumentPosition.FOLLOWING) {
25858
+ } else if (relative4 & DocumentPosition.FOLLOWING) {
25742
25859
  return 1;
25743
25860
  }
25744
25861
  return 0;
@@ -30100,6 +30217,34 @@ var require_dist3 = __commonJS({
30100
30217
  }
30101
30218
  });
30102
30219
 
30220
+ // src/errors.ts
30221
+ function errorMessage(error2) {
30222
+ return error2 instanceof Error ? error2.message : String(error2);
30223
+ }
30224
+ function isAbortLike(aborted2, message) {
30225
+ const lower = message.toLowerCase();
30226
+ return aborted2 || message.includes("AbortError") || lower.includes("aborted") || lower.includes("timeout");
30227
+ }
30228
+ var init_errors4 = __esm({
30229
+ "src/errors.ts"() {
30230
+ "use strict";
30231
+ }
30232
+ });
30233
+
30234
+ // src/validation.ts
30235
+ function clampInt(value, min, max, fallback) {
30236
+ const candidate = Number.isFinite(value) ? Math.trunc(value) : fallback;
30237
+ return Math.min(max, Math.max(min, candidate));
30238
+ }
30239
+ function trimQuery(value) {
30240
+ return (value ?? "").trim();
30241
+ }
30242
+ var init_validation = __esm({
30243
+ "src/validation.ts"() {
30244
+ "use strict";
30245
+ }
30246
+ });
30247
+
30103
30248
  // src/fetch-url.ts
30104
30249
  function nowMs2(bunLike = typeof Bun === "undefined" ? void 0 : Bun) {
30105
30250
  if (bunLike && typeof bunLike.nanoseconds === "function") {
@@ -30183,8 +30328,8 @@ async function fetchUrl(options) {
30183
30328
  const started = nowMs2();
30184
30329
  const parsed = parseUrl(options.url.trim());
30185
30330
  const format = options.format ?? "markdown";
30186
- const timeoutMs = Math.min(2e4, Math.max(300, options.timeout_ms ?? 8e3));
30187
- const maxBytes = Math.min(2e6, Math.max(100, options.max_bytes ?? 2e5));
30331
+ const timeoutMs = clampInt(options.timeout_ms, 100, 2e4, 8e3);
30332
+ const maxBytes = clampInt(options.max_bytes, 100, 2e6, 2e5);
30188
30333
  if (!parsed) {
30189
30334
  return {
30190
30335
  meta: { ok: false, duration_ms: Number((nowMs2() - started).toFixed(4)), truncated: false },
@@ -30262,8 +30407,8 @@ async function fetchUrl(options) {
30262
30407
  error: null
30263
30408
  };
30264
30409
  } catch (error2) {
30265
- const message = error2 instanceof Error ? error2.message : String(error2);
30266
- const timeoutLike = abort.signal.aborted || message.includes("AbortError") || message.toLowerCase().includes("timeout");
30410
+ const message = errorMessage(error2);
30411
+ const timeoutLike = isAbortLike(abort.signal.aborted, message);
30267
30412
  return {
30268
30413
  meta: { ok: false, duration_ms: Number((nowMs2() - started).toFixed(4)), truncated: false },
30269
30414
  data: null,
@@ -30281,6 +30426,8 @@ var init_fetch_url = __esm({
30281
30426
  "src/fetch-url.ts"() {
30282
30427
  "use strict";
30283
30428
  import_node_html_markdown = __toESM(require_dist3(), 1);
30429
+ init_errors4();
30430
+ init_validation();
30284
30431
  NHM = new import_node_html_markdown.NodeHtmlMarkdown({
30285
30432
  maxConsecutiveNewlines: 3
30286
30433
  });
@@ -30289,8 +30436,8 @@ var init_fetch_url = __esm({
30289
30436
 
30290
30437
  // src/git.ts
30291
30438
  import { spawnSync as spawnSync2 } from "node:child_process";
30292
- import { realpathSync } from "node:fs";
30293
- import { isAbsolute, normalize, relative as relative2, resolve } from "node:path";
30439
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, realpathSync } from "node:fs";
30440
+ import { basename, dirname as dirname2, isAbsolute as isAbsolute2, join as join4, normalize as normalize2, relative as relative3, resolve } from "node:path";
30294
30441
  function nowMs3(bunRef) {
30295
30442
  if (process.env.VEIL_FORCE_DATE_NOW === "1") {
30296
30443
  return Date.now();
@@ -30302,21 +30449,42 @@ function nowMs3(bunRef) {
30302
30449
  return Date.now();
30303
30450
  }
30304
30451
  function runCommand(command, args, cwd, timeoutMs) {
30305
- const out = spawnSync2(command, args, {
30306
- cwd,
30307
- encoding: "utf-8",
30308
- stdio: "pipe",
30309
- timeout: timeoutMs
30310
- });
30311
- return {
30312
- ok: out.status === 0 && !out.error,
30313
- stdout: out.stdout ?? "",
30314
- stderr: out.stderr ?? "",
30315
- code: out.status,
30316
- timedOut: out.signal === "SIGTERM" && out.status === null,
30317
- error: out.error?.message,
30318
- errorCode: out.error?.code
30319
- };
30452
+ const started = nowMs3();
30453
+ try {
30454
+ const out = spawnSync2(command, args, {
30455
+ cwd,
30456
+ encoding: "utf-8",
30457
+ stdio: "pipe",
30458
+ timeout: timeoutMs
30459
+ });
30460
+ const elapsed = nowMs3() - started;
30461
+ const timedOut = out.signal === "SIGTERM" && out.status === null || elapsed > timeoutMs;
30462
+ return {
30463
+ ok: out.status === 0 && !out.error && !timedOut,
30464
+ stdout: out.stdout ?? "",
30465
+ stderr: out.stderr ?? "",
30466
+ code: out.status,
30467
+ timedOut,
30468
+ error: out.error?.message,
30469
+ errorCode: out.error?.code
30470
+ };
30471
+ } catch (error2) {
30472
+ const value = error2;
30473
+ return {
30474
+ ok: false,
30475
+ stdout: "",
30476
+ stderr: "",
30477
+ code: null,
30478
+ timedOut: false,
30479
+ error: value.message ?? String(error2),
30480
+ errorCode: value.code
30481
+ };
30482
+ }
30483
+ }
30484
+ function isMissingBinary(result) {
30485
+ if (result.errorCode === "ENOENT") return true;
30486
+ if (!result.error) return false;
30487
+ return result.error.includes("ENOENT") || result.error.includes("Executable not found in $PATH") || result.error.includes("No such file or directory");
30320
30488
  }
30321
30489
  function responseMeta(workspace, tool, started, truncated, warnings) {
30322
30490
  return {
@@ -30359,21 +30527,69 @@ function truncateText(raw, maxBytes) {
30359
30527
  }
30360
30528
  function validatePathArg(workspace, path) {
30361
30529
  if (!path) return { ok: true };
30362
- if (path.startsWith("-") || isAbsolute(path)) {
30530
+ if (path.indexOf("\0") >= 0) {
30531
+ return { ok: false, error: { code: "invalid-path", message: "Path contains null bytes" } };
30532
+ }
30533
+ if (path.startsWith("-")) {
30534
+ return { ok: false, error: { code: "invalid-path", message: "Path cannot start with hyphen" } };
30535
+ }
30536
+ if (isAbsolute2(path)) {
30363
30537
  return { ok: false, error: { code: "invalid-path", message: "Path must be a relative path inside workspace" } };
30364
30538
  }
30365
- const normalized = normalize(path);
30539
+ const normalized = normalize2(path);
30366
30540
  const abs = resolve(workspace, normalized);
30367
- const rel = relative2(workspace, abs);
30368
- if (rel.startsWith("..") || isAbsolute(rel)) {
30541
+ const rel = relative3(workspace, abs);
30542
+ if (rel.startsWith("..") || isAbsolute2(rel)) {
30369
30543
  return { ok: false, error: { code: "invalid-path", message: "Path escapes workspace" } };
30370
30544
  }
30545
+ try {
30546
+ const workspaceReal = realpathSync(workspace);
30547
+ let absReal = abs;
30548
+ try {
30549
+ absReal = realpathSync(abs);
30550
+ } catch {
30551
+ const parentDir = dirname2(abs);
30552
+ try {
30553
+ const parentReal = realpathSync(parentDir);
30554
+ absReal = resolve(parentReal, basename(abs));
30555
+ } catch {
30556
+ absReal = abs;
30557
+ }
30558
+ }
30559
+ const relReal = relative3(workspaceReal, absReal);
30560
+ if (relReal.startsWith("..") || isAbsolute2(relReal)) {
30561
+ return { ok: false, error: { code: "invalid-path", message: "Path escapes workspace via symlink" } };
30562
+ }
30563
+ } catch (error2) {
30564
+ const workspaceResolved = resolve(workspace);
30565
+ const absResolved = resolve(workspace, normalized);
30566
+ const relResolved = relative3(workspaceResolved, absResolved);
30567
+ if (relResolved.startsWith("..") || isAbsolute2(relResolved)) {
30568
+ return { ok: false, error: { code: "invalid-path", message: "Path escapes workspace" } };
30569
+ }
30570
+ }
30371
30571
  return { ok: true, value: normalized };
30372
30572
  }
30373
30573
  function validateRevision(rev) {
30374
30574
  if (!rev) return { ok: true };
30375
- if (rev.length > 200 || rev.startsWith("-") || /\s/.test(rev)) {
30376
- return { ok: false, error: { code: "invalid-revision", message: "Revision contains unsafe characters" } };
30575
+ if (rev.length > 200) {
30576
+ return { ok: false, error: { code: "invalid-revision", message: "Revision string too long (max 200 characters)" } };
30577
+ }
30578
+ if (rev.startsWith("-")) {
30579
+ return { ok: false, error: { code: "invalid-revision", message: "Revision cannot start with hyphen" } };
30580
+ }
30581
+ const hasControlChar = Array.from(rev).some((ch) => {
30582
+ const code = ch.charCodeAt(0);
30583
+ return code === 0 || code >= 1 && code <= 31;
30584
+ });
30585
+ if (hasControlChar) {
30586
+ return { ok: false, error: { code: "invalid-revision", message: "Revision contains null bytes or control characters" } };
30587
+ }
30588
+ if (/\s/.test(rev)) {
30589
+ return { ok: false, error: { code: "invalid-revision", message: "Revision contains whitespace" } };
30590
+ }
30591
+ if (/[;|&$`(){}[\]<>!\\'"]/.test(rev)) {
30592
+ return { ok: false, error: { code: "invalid-revision", message: "Revision contains shell metacharacters" } };
30377
30593
  }
30378
30594
  const safeRefPattern = /^[A-Za-z0-9._/\-~^]+(\.{2,3}[A-Za-z0-9._/\-~^]+)?$/;
30379
30595
  if (!safeRefPattern.test(rev)) {
@@ -30383,7 +30599,7 @@ function validateRevision(rev) {
30383
30599
  }
30384
30600
  function ensureGitRepo(workspace, options) {
30385
30601
  const probe = runCommand(options.command ?? "git", ["-C", workspace, "rev-parse", "--is-inside-work-tree"], workspace, options.timeoutMs);
30386
- if (probe.errorCode === "ENOENT" || probe.error && probe.error.includes("ENOENT")) {
30602
+ if (isMissingBinary(probe)) {
30387
30603
  return { ok: false, error: { code: "git-unavailable", message: "git is not available in PATH" }, gitAvailable: false };
30388
30604
  }
30389
30605
  if (!probe.ok) {
@@ -30402,8 +30618,8 @@ function ensureGitRepo(workspace, options) {
30402
30618
  workspaceReal = resolve(workspace);
30403
30619
  topReal = resolve(topReal);
30404
30620
  }
30405
- const fromTop = relative2(topReal, workspaceReal);
30406
- if (fromTop.startsWith("..") || isAbsolute(fromTop)) {
30621
+ const fromTop = relative3(topReal, workspaceReal);
30622
+ if (fromTop.startsWith("..") || isAbsolute2(fromTop)) {
30407
30623
  return { ok: false, error: { code: "not-a-repo", message: "Workspace is outside git repository root" }, gitAvailable: true };
30408
30624
  }
30409
30625
  return { ok: true };
@@ -30640,23 +30856,124 @@ function ghLookup(workspace, options) {
30640
30856
  const timeoutMs = Math.min(2e4, Math.max(500, options.timeout_ms ?? 12e3));
30641
30857
  const command = options.command ?? "gh";
30642
30858
  const probe = runCommand(command, ["--version"], workspace, timeoutMs);
30643
- if (probe.errorCode === "ENOENT" || probe.error && probe.error.includes("ENOENT")) {
30859
+ if (isMissingBinary(probe)) {
30644
30860
  recordDiagnostics("gh_lookup", started, false, false);
30645
- return fail(workspace, "gh_lookup", started, { code: "gh-unavailable", message: "gh is not available in PATH" }, true);
30861
+ return Promise.resolve(fail(workspace, "gh_lookup", started, { code: "gh-unavailable", message: "gh is not available in PATH" }, true));
30646
30862
  }
30647
30863
  if (!probe.ok) {
30648
30864
  recordDiagnostics("gh_lookup", started, false, probe.timedOut);
30649
- return fail(workspace, "gh_lookup", started, {
30865
+ return Promise.resolve(fail(workspace, "gh_lookup", started, {
30650
30866
  code: probe.timedOut ? "timeout" : "gh-unavailable",
30651
30867
  message: "gh command is unavailable"
30652
- });
30868
+ }));
30653
30869
  }
30654
30870
  const auth = runCommand(command, ["auth", "status"], workspace, timeoutMs);
30655
30871
  if (!auth.ok) {
30656
30872
  recordDiagnostics("gh_lookup", started, false, auth.timedOut);
30657
- return fail(workspace, "gh_lookup", started, {
30873
+ return Promise.resolve(fail(workspace, "gh_lookup", started, {
30658
30874
  code: auth.timedOut ? "timeout" : "gh-unauthenticated",
30659
30875
  message: "gh is unauthenticated or cannot access GitHub"
30876
+ }));
30877
+ }
30878
+ const parseRepoRef = (repoRef2) => {
30879
+ const trimmed = repoRef2.trim();
30880
+ if (!trimmed) return null;
30881
+ if (trimmed.startsWith("http://") || trimmed.startsWith("https://")) {
30882
+ try {
30883
+ const url = new URL(trimmed);
30884
+ const parts2 = url.pathname.replace(/^\/+/, "").replace(/\.git$/, "").split("/").filter(Boolean);
30885
+ if (parts2.length < 2) return null;
30886
+ const owner2 = parts2[0] ?? "";
30887
+ const name2 = parts2[1] ?? "";
30888
+ if (!owner2 || !name2) return null;
30889
+ return { repo: `${owner2}/${name2}`, owner: owner2, name: name2, url: `https://github.com/${owner2}/${name2}.git` };
30890
+ } catch {
30891
+ return null;
30892
+ }
30893
+ }
30894
+ const normalizedRepo = trimmed.replace(/\.git$/, "");
30895
+ const parts = normalizedRepo.split("/").filter(Boolean);
30896
+ if (parts.length !== 2) return null;
30897
+ const owner = parts[0] ?? "";
30898
+ const name = parts[1] ?? "";
30899
+ if (!owner || !name) return null;
30900
+ return { repo: `${owner}/${name}`, owner, name, url: `https://github.com/${owner}/${name}.git` };
30901
+ };
30902
+ const repoRef = parseRepoRef(options.repo);
30903
+ if (!repoRef) {
30904
+ recordDiagnostics("gh_lookup", started, false, false);
30905
+ return Promise.resolve(
30906
+ fail(workspace, "gh_lookup", started, {
30907
+ code: "command-failed",
30908
+ message: "repo must be 'owner/repo' or a GitHub URL"
30909
+ })
30910
+ );
30911
+ }
30912
+ if (options.kind === "repo_context") {
30913
+ const gitProbe = runCommand("git", ["--version"], workspace, timeoutMs);
30914
+ if (isMissingBinary(gitProbe)) {
30915
+ recordDiagnostics("gh_lookup", started, false, false);
30916
+ return Promise.resolve(fail(workspace, "gh_lookup", started, { code: "git-unavailable", message: "git is not available in PATH" }, false));
30917
+ }
30918
+ if (!gitProbe.ok) {
30919
+ recordDiagnostics("gh_lookup", started, false, gitProbe.timedOut);
30920
+ return Promise.resolve(
30921
+ fail(workspace, "gh_lookup", started, {
30922
+ code: gitProbe.timedOut ? "timeout" : "command-failed",
30923
+ message: "git command is unavailable"
30924
+ }, false)
30925
+ );
30926
+ }
30927
+ const tempRoot = options.temp_root && options.temp_root.trim() ? options.temp_root.trim() : "/tmp";
30928
+ const target = join4(tempRoot, basename(repoRef.name));
30929
+ mkdirSync2(tempRoot, { recursive: true });
30930
+ const gitDir = join4(target, ".git");
30931
+ let syncOut;
30932
+ if (!existsSync3(gitDir)) {
30933
+ syncOut = runCommand("git", ["clone", "--depth", "1", repoRef.url, target], workspace, timeoutMs);
30934
+ } else {
30935
+ const remote = runCommand("git", ["-C", target, "remote", "set-url", "origin", repoRef.url], workspace, timeoutMs);
30936
+ const fetch2 = runCommand("git", ["-C", target, "fetch", "--depth", "1", "origin"], workspace, timeoutMs);
30937
+ const headRef = runCommand("git", ["-C", target, "symbolic-ref", "refs/remotes/origin/HEAD"], workspace, timeoutMs);
30938
+ const branchRef = headRef.ok ? headRef.stdout.trim().replace(/^refs\/remotes\//, "") : "origin/main";
30939
+ const reset = runCommand("git", ["-C", target, "reset", "--hard", branchRef], workspace, timeoutMs);
30940
+ syncOut = !remote.ok || !fetch2.ok || !reset.ok ? { ok: false, stdout: `${remote.stdout}
30941
+ ${fetch2.stdout}
30942
+ ${reset.stdout}`, stderr: `${remote.stderr}
30943
+ ${fetch2.stderr}
30944
+ ${reset.stderr}`, code: 1, timedOut: remote.timedOut || fetch2.timedOut || reset.timedOut } : reset;
30945
+ }
30946
+ if (!syncOut.ok) {
30947
+ recordDiagnostics("gh_lookup", started, false, syncOut.timedOut);
30948
+ return Promise.resolve(
30949
+ fail(workspace, "gh_lookup", started, {
30950
+ code: syncOut.timedOut ? "timeout" : "command-failed",
30951
+ message: `failed to sync repo ${repoRef.repo}: ${(syncOut.stderr || syncOut.error || "unknown").trim()}`
30952
+ })
30953
+ );
30954
+ }
30955
+ return buildIndex(target, "changed", { state_root: options.state_root }).then(async (manifest) => {
30956
+ const status = await getStatus(target, { state_root: options.state_root });
30957
+ const stateRootResolved = resolveStateRoot(target, options.state_root);
30958
+ const data2 = {
30959
+ repo: repoRef.repo,
30960
+ kind: "repo_context",
30961
+ query: options.query ?? "",
30962
+ limit: 0,
30963
+ text: `repo indexed at ${target}`,
30964
+ repo_url: repoRef.url,
30965
+ cloned_workspace: target,
30966
+ state_root: stateRootResolved,
30967
+ status_exists: status.exists
30968
+ };
30969
+ recordDiagnostics("gh_lookup", started, true, false);
30970
+ return finish(workspace, "gh_lookup", started, data2, { truncated: false });
30971
+ }).catch((error2) => {
30972
+ recordDiagnostics("gh_lookup", started, false, false);
30973
+ return fail(workspace, "gh_lookup", started, {
30974
+ code: "command-failed",
30975
+ message: `failed to index cloned repo: ${String(error2)}`
30976
+ });
30660
30977
  });
30661
30978
  }
30662
30979
  const limit = Math.min(50, Math.max(1, options.limit ?? 10));
@@ -30665,41 +30982,44 @@ function ghLookup(workspace, options) {
30665
30982
  let args;
30666
30983
  if (options.kind === "issues") {
30667
30984
  subcommand = "issue";
30668
- args = ["search", query || "is:open", "--repo", options.repo, "--limit", String(limit)];
30985
+ args = ["search", query || "is:open", "--repo", repoRef.repo, "--limit", String(limit)];
30669
30986
  } else if (options.kind === "prs") {
30670
30987
  subcommand = "pr";
30671
- args = ["list", "--repo", options.repo, "--limit", String(limit)];
30988
+ args = ["list", "--repo", repoRef.repo, "--limit", String(limit)];
30672
30989
  if (query) {
30673
30990
  args.push("--search", query);
30674
30991
  }
30675
30992
  } else {
30676
30993
  subcommand = "run";
30677
- args = ["list", "--repo", options.repo, "--limit", String(limit)];
30994
+ args = ["list", "--repo", repoRef.repo, "--limit", String(limit)];
30678
30995
  }
30679
30996
  const out = runCommand(command, [subcommand, ...args], workspace, timeoutMs);
30680
30997
  if (!out.ok) {
30681
30998
  recordDiagnostics("gh_lookup", started, false, out.timedOut);
30682
- return fail(workspace, "gh_lookup", started, {
30999
+ return Promise.resolve(fail(workspace, "gh_lookup", started, {
30683
31000
  code: out.timedOut ? "timeout" : "command-failed",
30684
31001
  message: `gh lookup failed: ${(out.stderr || out.error || "unknown").trim()}`
30685
- });
31002
+ }));
30686
31003
  }
30687
31004
  const truncation = truncateText(out.stdout, DEFAULT_MAX_BYTES);
30688
31005
  const data = {
30689
- repo: options.repo,
31006
+ repo: repoRef.repo,
30690
31007
  kind: options.kind,
30691
31008
  query,
30692
31009
  limit,
30693
- text: truncation.text
31010
+ text: truncation.text,
31011
+ repo_url: repoRef.url
30694
31012
  };
30695
31013
  recordDiagnostics("gh_lookup", started, true, false);
30696
- return finish(workspace, "gh_lookup", started, data, truncation);
31014
+ return Promise.resolve(finish(workspace, "gh_lookup", started, data, truncation));
30697
31015
  }
30698
31016
  var DEFAULT_MAX_BYTES, MAX_BYTES_CAP;
30699
31017
  var init_git = __esm({
30700
31018
  "src/git.ts"() {
30701
31019
  "use strict";
30702
31020
  init_diagnostics();
31021
+ init_indexer();
31022
+ init_state_root();
30703
31023
  DEFAULT_MAX_BYTES = 64e3;
30704
31024
  MAX_BYTES_CAP = 5e5;
30705
31025
  }
@@ -31386,8 +31706,8 @@ async function runProvider(def, fetchImpl, query, limit, signal) {
31386
31706
  warning: results.length > 0 ? null : "no-parseable-results"
31387
31707
  };
31388
31708
  } catch (error2) {
31389
- const message = error2 instanceof Error ? error2.message : String(error2);
31390
- const timeoutLike = signal.aborted || message === "timeout" || message.includes("AbortError") || message.toLowerCase().includes("aborted");
31709
+ const message = errorMessage(error2);
31710
+ const timeoutLike = isAbortLike(signal.aborted || message === "timeout", message);
31391
31711
  return {
31392
31712
  provider: def.provider,
31393
31713
  ok: false,
@@ -31477,9 +31797,9 @@ function traceForPending(provider, durationMs, warning) {
31477
31797
  }
31478
31798
  async function webSearch(workspace, options) {
31479
31799
  const started = nowMs4();
31480
- const query = options.query.trim();
31481
- const limit = Math.min(25, Math.max(1, options.limit ?? 8));
31482
- const timeoutMs = Math.min(15e3, Math.max(300, options.timeout_ms ?? 5e3));
31800
+ const query = trimQuery(options.query);
31801
+ const limit = clampInt(options.limit, 1, 25, 8);
31802
+ const timeoutMs = clampInt(options.timeout_ms, 100, 2e4, 5e3);
31483
31803
  const debug = options.debug ?? false;
31484
31804
  if (!query) {
31485
31805
  return {
@@ -31604,6 +31924,8 @@ var PROVIDER_ORDER, PROVIDER_BASE_SCORE, TRACKING_PARAMS, PROVIDERS;
31604
31924
  var init_web_search = __esm({
31605
31925
  "src/web-search.ts"() {
31606
31926
  "use strict";
31927
+ init_errors4();
31928
+ init_validation();
31607
31929
  PROVIDER_ORDER = ["google", "duckduckgo", "wikipedia", "github", "reddit", "deepwiki"];
31608
31930
  PROVIDER_BASE_SCORE = {
31609
31931
  google: 10,
@@ -31801,34 +32123,39 @@ var init_server3 = __esm({
31801
32123
  init_fetch_url();
31802
32124
  init_git();
31803
32125
  init_format();
32126
+ init_state_root();
31804
32127
  init_web_search();
31805
32128
  server = new McpServer({
31806
32129
  name: "veil",
31807
- version: "0.1.0"
32130
+ version: "0.1.6"
31808
32131
  });
31809
32132
  server.tool(
31810
32133
  "status",
31811
32134
  "Return current index status and staleness reasons",
31812
32135
  {
31813
- workspace: external_exports.string().optional()
32136
+ workspace: external_exports.string().optional(),
32137
+ state_root: external_exports.string().optional()
31814
32138
  },
31815
- async ({ workspace }) => {
32139
+ async ({ workspace, state_root }) => {
31816
32140
  const ws = workspace ?? process.cwd();
31817
- const status = await getStatus(ws);
32141
+ diagnostics.configureStatePath(diagnosticsStatePath(ws, state_root));
32142
+ const status = await getStatus(ws, { state_root });
31818
32143
  return asText(status);
31819
32144
  }
31820
32145
  );
31821
32146
  server.tool(
31822
32147
  "refresh",
31823
- "Build or refresh the index in .agents/index",
32148
+ "Build or refresh the index in .veil/index",
31824
32149
  {
31825
32150
  workspace: external_exports.string().optional(),
31826
- mode: external_exports.enum(["full", "changed"]).optional()
32151
+ mode: external_exports.enum(["full", "changed"]).optional(),
32152
+ state_root: external_exports.string().optional()
31827
32153
  },
31828
- async ({ workspace, mode }) => {
32154
+ async ({ workspace, mode, state_root }) => {
31829
32155
  const ws = workspace ?? process.cwd();
31830
32156
  const selectedMode = mode ?? "changed";
31831
- const manifest = await buildIndex(ws, selectedMode);
32157
+ diagnostics.configureStatePath(diagnosticsStatePath(ws, state_root));
32158
+ const manifest = await buildIndex(ws, selectedMode, { state_root });
31832
32159
  return asText({ ok: true, mode: selectedMode, manifest });
31833
32160
  }
31834
32161
  );
@@ -31838,11 +32165,13 @@ var init_server3 = __esm({
31838
32165
  {
31839
32166
  workspace: external_exports.string().optional(),
31840
32167
  query: external_exports.string(),
31841
- limit: external_exports.number().int().positive().max(200).optional()
32168
+ limit: external_exports.number().int().positive().max(200).optional(),
32169
+ state_root: external_exports.string().optional()
31842
32170
  },
31843
- async ({ workspace, query, limit }) => {
32171
+ async ({ workspace, query, limit, state_root }) => {
31844
32172
  const ws = workspace ?? process.cwd();
31845
- const items = await queryFiles(ws, query, limit ?? 20);
32173
+ diagnostics.configureStatePath(diagnosticsStatePath(ws, state_root));
32174
+ const items = await queryFiles(ws, query, limit ?? 20, { state_root });
31846
32175
  return asText({ items });
31847
32176
  }
31848
32177
  );
@@ -31852,11 +32181,13 @@ var init_server3 = __esm({
31852
32181
  {
31853
32182
  workspace: external_exports.string().optional(),
31854
32183
  query: external_exports.string(),
31855
- limit: external_exports.number().int().positive().max(200).optional()
32184
+ limit: external_exports.number().int().positive().max(200).optional(),
32185
+ state_root: external_exports.string().optional()
31856
32186
  },
31857
- async ({ workspace, query, limit }) => {
32187
+ async ({ workspace, query, limit, state_root }) => {
31858
32188
  const ws = workspace ?? process.cwd();
31859
- const items = await querySymbols(ws, query, limit ?? 20);
32189
+ diagnostics.configureStatePath(diagnosticsStatePath(ws, state_root));
32190
+ const items = await querySymbols(ws, query, limit ?? 20, { state_root });
31860
32191
  return asText({ items });
31861
32192
  }
31862
32193
  );
@@ -31870,15 +32201,18 @@ var init_server3 = __esm({
31870
32201
  prefer_code: external_exports.boolean().optional(),
31871
32202
  path_prefix: external_exports.string().optional(),
31872
32203
  language: external_exports.string().optional(),
31873
- intent: external_exports.enum(["auto", "code", "docs", "symbols"]).optional()
32204
+ intent: external_exports.enum(["auto", "code", "docs", "symbols"]).optional(),
32205
+ state_root: external_exports.string().optional()
31874
32206
  },
31875
- async ({ workspace, query, limit, prefer_code, path_prefix, language, intent }) => {
32207
+ async ({ workspace, query, limit, prefer_code, path_prefix, language, intent, state_root }) => {
31876
32208
  const ws = workspace ?? process.cwd();
32209
+ diagnostics.configureStatePath(diagnosticsStatePath(ws, state_root));
31877
32210
  const items = await queryChunks(ws, query, limit ?? 10, {
31878
32211
  prefer_code,
31879
32212
  path_prefix,
31880
32213
  language,
31881
- intent
32214
+ intent,
32215
+ state_root
31882
32216
  });
31883
32217
  return asText({ items });
31884
32218
  }
@@ -31895,10 +32229,12 @@ var init_server3 = __esm({
31895
32229
  prefer_code: external_exports.boolean().optional(),
31896
32230
  path_prefix: external_exports.string().optional(),
31897
32231
  language: external_exports.string().optional(),
31898
- intent: external_exports.enum(["auto", "code", "docs", "symbols"]).optional()
32232
+ intent: external_exports.enum(["auto", "code", "docs", "symbols"]).optional(),
32233
+ state_root: external_exports.string().optional()
31899
32234
  },
31900
- async ({ workspace, query, files_limit, symbols_limit, search_limit, prefer_code, path_prefix, language, intent }) => {
32235
+ async ({ workspace, query, files_limit, symbols_limit, search_limit, prefer_code, path_prefix, language, intent, state_root }) => {
31901
32236
  const ws = workspace ?? process.cwd();
32237
+ diagnostics.configureStatePath(diagnosticsStatePath(ws, state_root));
31902
32238
  const result = await lookupIndex(ws, query, {
31903
32239
  files_limit,
31904
32240
  symbols_limit,
@@ -31906,7 +32242,8 @@ var init_server3 = __esm({
31906
32242
  prefer_code,
31907
32243
  path_prefix,
31908
32244
  language,
31909
- intent
32245
+ intent,
32246
+ state_root
31910
32247
  });
31911
32248
  return asText(result);
31912
32249
  }
@@ -31924,7 +32261,8 @@ var init_server3 = __esm({
31924
32261
  prefer_code: external_exports.boolean().optional(),
31925
32262
  path_prefix: external_exports.string().optional(),
31926
32263
  language: external_exports.string().optional(),
31927
- intent: external_exports.enum(["auto", "code", "docs", "symbols"]).optional()
32264
+ intent: external_exports.enum(["auto", "code", "docs", "symbols"]).optional(),
32265
+ state_root: external_exports.string().optional()
31928
32266
  },
31929
32267
  async ({
31930
32268
  workspace,
@@ -31936,13 +32274,15 @@ var init_server3 = __esm({
31936
32274
  prefer_code,
31937
32275
  path_prefix,
31938
32276
  language,
31939
- intent
32277
+ intent,
32278
+ state_root
31940
32279
  }) => {
31941
32280
  const ws = workspace ?? process.cwd();
31942
- let status = await getStatus(ws);
32281
+ diagnostics.configureStatePath(diagnosticsStatePath(ws, state_root));
32282
+ let status = await getStatus(ws, { state_root });
31943
32283
  if (shouldRefreshDiscover(status) && (refresh_if_stale ?? true)) {
31944
- await buildIndex(ws, "changed");
31945
- status = await getStatus(ws);
32284
+ await buildIndex(ws, "changed", { state_root });
32285
+ status = await getStatus(ws, { state_root });
31946
32286
  }
31947
32287
  const discovered = await discoverIndex(ws, query, {
31948
32288
  files_limit,
@@ -31951,7 +32291,8 @@ var init_server3 = __esm({
31951
32291
  prefer_code,
31952
32292
  path_prefix,
31953
32293
  language,
31954
- intent
32294
+ intent,
32295
+ state_root
31955
32296
  });
31956
32297
  return asText({ status, intent: discovered.intent, files: discovered.files, symbols: discovered.symbols, chunks: discovered.chunks });
31957
32298
  }
@@ -32052,14 +32393,17 @@ var init_server3 = __esm({
32052
32393
  {
32053
32394
  workspace: external_exports.string().optional(),
32054
32395
  repo: external_exports.string(),
32055
- kind: external_exports.enum(["issues", "prs", "checks"]),
32396
+ kind: external_exports.enum(["repo_context", "issues", "prs", "checks"]),
32056
32397
  query: external_exports.string().optional(),
32057
32398
  limit: external_exports.number().int().positive().max(50).optional(),
32058
- timeout_ms: external_exports.number().int().positive().max(2e4).optional()
32399
+ timeout_ms: external_exports.number().int().positive().max(2e4).optional(),
32400
+ temp_root: external_exports.string().optional(),
32401
+ state_root: external_exports.string().optional()
32059
32402
  },
32060
- async ({ workspace, repo, kind, query, limit, timeout_ms }) => {
32403
+ async ({ workspace, repo, kind, query, limit, timeout_ms, temp_root, state_root }) => {
32061
32404
  const ws = workspace ?? process.cwd();
32062
- return asText(ghLookup(ws, { repo, kind, query, limit, timeout_ms }));
32405
+ diagnostics.configureStatePath(diagnosticsStatePath(ws, state_root));
32406
+ return asText(await ghLookup(ws, { repo, kind, query, limit, timeout_ms, temp_root, state_root }));
32063
32407
  }
32064
32408
  );
32065
32409
  server.tool(
@@ -32101,6 +32445,11 @@ function writeOutput(data) {
32101
32445
  async function main() {
32102
32446
  const cmd = process.argv[2] ?? "status";
32103
32447
  const workspace = resolveWorkspace();
32448
+ const stateRoot = getArg("--state-root");
32449
+ if (stateRoot) {
32450
+ process.env.VEIL_STATE_ROOT = stateRoot;
32451
+ }
32452
+ diagnostics.configureStatePath(diagnosticsStatePath(workspace, stateRoot));
32104
32453
  const enableProfiling = hasFlag("--profile");
32105
32454
  if (enableProfiling) {
32106
32455
  profiler.enable();
@@ -32113,12 +32462,12 @@ async function main() {
32113
32462
  }
32114
32463
  if (cmd === "refresh") {
32115
32464
  const mode = getArg("--mode", "changed") ?? "changed";
32116
- const manifest = await buildIndex(workspace, mode);
32465
+ const manifest = await buildIndex(workspace, mode, { state_root: stateRoot });
32117
32466
  writeOutput({ ok: true, mode, manifest });
32118
32467
  return;
32119
32468
  }
32120
32469
  if (cmd === "status") {
32121
- const status = await getStatus(workspace);
32470
+ const status = await getStatus(workspace, { state_root: stateRoot });
32122
32471
  writeOutput(status);
32123
32472
  return;
32124
32473
  }
@@ -32126,19 +32475,19 @@ async function main() {
32126
32475
  const query = getArg("--query", "") ?? "";
32127
32476
  const intent = getArg("--intent", "auto") ?? "auto";
32128
32477
  const refreshIfStale = (getArg("--refresh-if-stale", "1") ?? "1") !== "0";
32129
- let status = await getStatus(workspace);
32478
+ let status = await getStatus(workspace, { state_root: stateRoot });
32130
32479
  if (shouldRefreshDiscover(status) && refreshIfStale) {
32131
- await buildIndex(workspace, "changed");
32132
- status = await getStatus(workspace);
32480
+ await buildIndex(workspace, "changed", { state_root: stateRoot });
32481
+ status = await getStatus(workspace, { state_root: stateRoot });
32133
32482
  }
32134
- const discovered = await discoverIndex(workspace, query, { prefer_code: true, intent });
32483
+ const discovered = await discoverIndex(workspace, query, { prefer_code: true, intent, state_root: stateRoot });
32135
32484
  writeOutput({ status, intent: discovered.intent, files: discovered.files, symbols: discovered.symbols, chunks: discovered.chunks });
32136
32485
  return;
32137
32486
  }
32138
32487
  if (cmd === "lookup") {
32139
32488
  const query = getArg("--query", "") ?? "";
32140
32489
  const intent = getArg("--intent", "auto") ?? "auto";
32141
- const result = await lookupIndex(workspace, query, { intent, prefer_code: true });
32490
+ const result = await lookupIndex(workspace, query, { intent, prefer_code: true, state_root: stateRoot });
32142
32491
  writeOutput(result);
32143
32492
  return;
32144
32493
  }
@@ -32226,15 +32575,17 @@ async function main() {
32226
32575
  }
32227
32576
  if (cmd === "gh-lookup") {
32228
32577
  const repo = getArg("--repo", "") ?? "";
32229
- const kind = getArg("--kind", "issues") ?? "issues";
32578
+ const kind = getArg("--kind", "repo_context") ?? "repo_context";
32230
32579
  const limit = Number(getArg("--limit", "10") ?? "10");
32231
32580
  const timeout_ms = Number(getArg("--timeout-ms", "12000") ?? "12000");
32232
- const result = ghLookup(workspace, {
32581
+ const result = await ghLookup(workspace, {
32233
32582
  repo,
32234
32583
  kind,
32235
32584
  query: getArg("--query"),
32236
32585
  limit: Number.isFinite(limit) ? limit : 10,
32237
- timeout_ms: Number.isFinite(timeout_ms) ? timeout_ms : 12e3
32586
+ timeout_ms: Number.isFinite(timeout_ms) ? timeout_ms : 12e3,
32587
+ state_root: stateRoot,
32588
+ temp_root: getArg("--temp-root")
32238
32589
  });
32239
32590
  writeOutput(result);
32240
32591
  return;
@@ -32243,7 +32594,7 @@ async function main() {
32243
32594
  console.error("\n" + profiler.report());
32244
32595
  }
32245
32596
  process.stderr.write(
32246
- "Usage: bun run src/cli.ts <build|refresh|status|discover|lookup|web-search|fetch-url|diagnostics|git-status|git-log|git-diff|git-show|gh-lookup> [--workspace <path>] [--mode full|changed] [--query <text>] [--profile]\nOutput format: TOON\nweb-search providers: google, duckduckgo, wikipedia, github, reddit, deepwiki\nweb-search debug: --debug 1\nfetch-url: --url <https://...> [--format markdown|text|html] [--timeout-ms 8000] [--max-bytes 200000]\n"
32597
+ "Usage: bun run src/cli.ts <build|refresh|status|discover|lookup|web-search|fetch-url|diagnostics|git-status|git-log|git-diff|git-show|gh-lookup> [--workspace <path>] [--state-root <.veil|relative|/abs/path>] [--mode full|changed] [--query <text>] [--profile]\nOutput format: TOON\nweb-search providers: google, duckduckgo, wikipedia, github, reddit, deepwiki\nweb-search debug: --debug 1\nfetch-url: --url <https://...> [--format markdown|text|html] [--timeout-ms 8000] [--max-bytes 200000]\n"
32247
32598
  );
32248
32599
  process.exitCode = 1;
32249
32600
  }
@@ -32255,6 +32606,7 @@ var init_cli = __esm({
32255
32606
  init_fetch_url();
32256
32607
  init_format();
32257
32608
  init_git();
32609
+ init_state_root();
32258
32610
  init_web_search();
32259
32611
  main().catch((error2) => {
32260
32612
  process.stderr.write(`${String(error2)}
@@ -32306,7 +32658,9 @@ var __internalBin = {
32306
32658
  usage,
32307
32659
  route
32308
32660
  };
32309
- if (import.meta.main) {
32661
+ var meta = import.meta;
32662
+ var isMain = typeof meta.main === "boolean" ? meta.main : true;
32663
+ if (isMain) {
32310
32664
  main2().catch((error2) => {
32311
32665
  process.stderr.write(`${String(error2)}
32312
32666
  `);