@autorag/librarian 2.10.4 → 2.10.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mcp/index.js CHANGED
@@ -5143,7 +5143,20 @@ function configuredVectorDimension(workspacePath) {
5143
5143
  const dimension = options.dimension;
5144
5144
  return typeof dimension === "number" ? dimension : undefined;
5145
5145
  }
5146
- function rewriteEmbedderConfig(workspacePath, embedder, chunkerConfig = {}) {
5146
+ function configuredLexicalLanguage(workspacePath) {
5147
+ let raw;
5148
+ try {
5149
+ raw = readFileSync8(minSyncConfigPath(workspacePath), "utf8");
5150
+ } catch {
5151
+ return;
5152
+ }
5153
+ const lexical = parse(raw).lexical;
5154
+ if (typeof lexical !== "object" || lexical === null || Array.isArray(lexical))
5155
+ return "simple";
5156
+ const language = lexical.language;
5157
+ return typeof language === "string" ? language : "simple";
5158
+ }
5159
+ function rewriteEmbedderConfig(workspacePath, embedder, managed = {}) {
5147
5160
  const configPath = minSyncConfigPath(workspacePath);
5148
5161
  let raw;
5149
5162
  try {
@@ -5186,8 +5199,13 @@ function rewriteEmbedderConfig(workspacePath, embedder, chunkerConfig = {}) {
5186
5199
  }
5187
5200
  if (embedder.dimension !== undefined)
5188
5201
  options.dimension = embedder.dimension;
5189
- if (chunkerConfig.maxChunkSize !== undefined)
5190
- chunkerOptions.max_chunk_size = chunkerConfig.maxChunkSize;
5202
+ if (managed.maxChunkSize !== undefined)
5203
+ chunkerOptions.max_chunk_size = managed.maxChunkSize;
5204
+ if (managed.lexicalLanguage !== undefined) {
5205
+ const lexical = typeof parsed.lexical === "object" && parsed.lexical !== null && !Array.isArray(parsed.lexical) ? parsed.lexical : {};
5206
+ parsed.lexical = lexical;
5207
+ lexical.language = managed.lexicalLanguage;
5208
+ }
5191
5209
  writeFileSync6(configPath, stringify(parsed));
5192
5210
  return true;
5193
5211
  }
@@ -5199,6 +5217,66 @@ var init_embedder_config = __esm(() => {
5199
5217
  };
5200
5218
  });
5201
5219
 
5220
+ // src/minsync/kiwi.ts
5221
+ import { existsSync as existsSync10 } from "node:fs";
5222
+ import { homedir as homedir2 } from "node:os";
5223
+ import { posix as posix3, win32 as win323 } from "node:path";
5224
+ function kiwiAvailable(environment = defaultEnvironment()) {
5225
+ const { env, exists } = environment;
5226
+ const library = env.KIWI_LIBRARY_PATH;
5227
+ const model = env.KIWI_MODEL_PATH;
5228
+ const libraryFound = library !== undefined && library !== "" ? exists(library) : libraryCandidates(environment).some(exists);
5229
+ const modelFound = model !== undefined && model !== "" ? exists(model) : modelCandidates(environment).some(exists);
5230
+ return libraryFound && modelFound;
5231
+ }
5232
+ function defaultEnvironment() {
5233
+ let home;
5234
+ try {
5235
+ home = homedir2();
5236
+ } catch {
5237
+ home = undefined;
5238
+ }
5239
+ return { env: process.env, platform: process.platform, home, exists: existsSync10 };
5240
+ }
5241
+ function userRoots({ env, platform, home }) {
5242
+ if (platform === "win32") {
5243
+ const roots = [];
5244
+ if (env.LOCALAPPDATA)
5245
+ roots.push(win323.join(env.LOCALAPPDATA, "kiwi"));
5246
+ const profile = env.USERPROFILE ?? home;
5247
+ if (profile)
5248
+ roots.push(win323.join(profile, "AppData", "Local", "kiwi"));
5249
+ roots.push("C:\\kiwi", "C:\\Program Files\\Kiwi");
5250
+ return roots;
5251
+ }
5252
+ return home ? [posix3.join(home, ".local", "kiwi")] : [];
5253
+ }
5254
+ function libraryCandidates(environment) {
5255
+ const { platform } = environment;
5256
+ if (platform === "win32")
5257
+ return userRoots(environment).map((root) => win323.join(root, "lib", "kiwi.dll"));
5258
+ const file = platform === "darwin" ? "libkiwi.dylib" : "libkiwi.so";
5259
+ const system = platform === "darwin" ? ["/usr/local/lib", "/opt/homebrew/lib"] : ["/usr/local/lib", "/usr/lib"];
5260
+ return [
5261
+ ...userRoots(environment).map((root) => posix3.join(root, "lib", file)),
5262
+ ...system.map((dir) => posix3.join(dir, file))
5263
+ ];
5264
+ }
5265
+ function modelCandidates(environment) {
5266
+ const { platform } = environment;
5267
+ if (platform === "win32")
5268
+ return userRoots(environment).map((root) => win323.join(root, "models", "cong", "base"));
5269
+ const system = platform === "darwin" ? ["/usr/local/models", "/opt/homebrew/models", "/usr/local/share/kiwi/models"] : ["/usr/local/models", "/usr/local/share/kiwi/models", "/usr/share/kiwi/models"];
5270
+ return [
5271
+ ...userRoots(environment).map((root) => posix3.join(root, "models", "cong", "base")),
5272
+ ...system.map((dir) => posix3.join(dir, "cong", "base"))
5273
+ ];
5274
+ }
5275
+ var init_kiwi = () => {};
5276
+
5277
+ // src/minsync/lexical-language.ts
5278
+ var MINSYNC_LEXICAL_LANGUAGE = "multilingual";
5279
+
5202
5280
  // src/minsync/local-embedder.ts
5203
5281
  import { spawn as spawn7 } from "node:child_process";
5204
5282
  import { request } from "node:http";
@@ -5387,7 +5465,7 @@ var init_process = __esm(() => {
5387
5465
  });
5388
5466
 
5389
5467
  // src/minsync/client.ts
5390
- import { existsSync as existsSync10, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "node:fs";
5468
+ import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "node:fs";
5391
5469
  import { join as join14 } from "node:path";
5392
5470
 
5393
5471
  class MinSyncClient {
@@ -5482,7 +5560,7 @@ class MinSyncClient {
5482
5560
  return previous === undefined || JSON.stringify(previous) !== JSON.stringify(identity);
5483
5561
  }
5484
5562
  async sync(force = false, signal) {
5485
- if (!existsSync10(this.binaryPath))
5563
+ if (!existsSync11(this.binaryPath))
5486
5564
  throw minSyncBinaryMissingError();
5487
5565
  let effective = { config: {} };
5488
5566
  try {
@@ -5520,14 +5598,16 @@ class MinSyncClient {
5520
5598
  }
5521
5599
  }
5522
5600
  const spawnOptions = signal === undefined ? {} : { signal };
5523
- const initialized = existsSync10(minSyncConfigPath(this.workspacePath));
5601
+ const lexical = this.resolveLexicalLanguage();
5602
+ const initialized = existsSync11(minSyncConfigPath(this.workspacePath));
5524
5603
  if (!initialized) {
5525
5604
  const initArgs = ["init", "--format", "json"];
5526
5605
  if (this.embedder?.id) {
5527
5606
  initArgs.push("--embedder", this.embedder.id);
5528
5607
  }
5608
+ initArgs.push("--language", lexical.language);
5529
5609
  const init = await this.spawn(initArgs, spawnOptions);
5530
- if (!init.ok || !existsSync10(minSyncConfigPath(this.workspacePath))) {
5610
+ if (!init.ok || !existsSync11(minSyncConfigPath(this.workspacePath))) {
5531
5611
  return {
5532
5612
  ok: false,
5533
5613
  synced: 0,
@@ -5539,20 +5619,29 @@ class MinSyncClient {
5539
5619
  const chunkSizeChanged = this.maxChunkSize !== undefined && configuredMaxChunkSize(this.workspacePath) !== this.maxChunkSize;
5540
5620
  const dimensionChanged = embedder.dimension !== undefined && configuredVectorDimension(this.workspacePath) !== embedder.dimension;
5541
5621
  const configPath = minSyncConfigPath(this.workspacePath);
5542
- const shouldRewriteConfig = this.embedder !== undefined || this.maxChunkSize !== undefined || effective.identity !== undefined;
5543
- const originalConfig = shouldRewriteConfig ? readConfigSnapshot(configPath) : undefined;
5544
- const configRewritten = shouldRewriteConfig && rewriteEmbedderConfig(this.workspacePath, embedder, { maxChunkSize: this.maxChunkSize });
5622
+ const originalConfig = readConfigSnapshot(configPath);
5623
+ const configRewritten = rewriteEmbedderConfig(this.workspacePath, embedder, {
5624
+ maxChunkSize: this.maxChunkSize,
5625
+ lexicalLanguage: lexical.language
5626
+ });
5545
5627
  const restoreConfig = () => {
5546
5628
  if (configRewritten && originalConfig !== undefined)
5547
5629
  writeFileSync7(configPath, originalConfig);
5548
5630
  };
5549
5631
  try {
5550
- return await this.checkAndSync(force || chunkSizeChanged || dimensionChanged, signal, effective, restoreConfig);
5632
+ const result = await this.checkAndSync(force || chunkSizeChanged || dimensionChanged, signal, effective, restoreConfig);
5633
+ return result.ok && lexical.fallback !== undefined ? { ...result, lexicalFallback: lexical.fallback } : result;
5551
5634
  } catch (error) {
5552
5635
  restoreConfig();
5553
5636
  throw error;
5554
5637
  }
5555
5638
  }
5639
+ resolveLexicalLanguage() {
5640
+ const requested = MINSYNC_LEXICAL_LANGUAGE;
5641
+ if (kiwiAvailable() || configuredLexicalLanguage(this.workspacePath) === requested)
5642
+ return { language: requested };
5643
+ return { language: "simple", fallback: { requested, used: "simple" } };
5644
+ }
5556
5645
  lockHeldResult(stderr) {
5557
5646
  return {
5558
5647
  ok: false,
@@ -5605,7 +5694,7 @@ class MinSyncClient {
5605
5694
  }
5606
5695
  const identityChanged = effective.identity !== undefined && this.identityMismatch(effective.identity);
5607
5696
  const fullReindex = forceFull || identityChanged;
5608
- const syncArgs = existsSync10(cursorPath) && !fullReindex ? ["sync", "--format", "json"] : ["sync", "--full", "--format", "json"];
5697
+ const syncArgs = existsSync11(cursorPath) && !fullReindex ? ["sync", "--format", "json"] : ["sync", "--full", "--format", "json"];
5609
5698
  const result = await this.spawn(syncArgs, spawnOptions);
5610
5699
  if (!result.ok && result.code === MINSYNC_LOCK_HELD_EXIT_CODE) {
5611
5700
  restoreConfig();
@@ -5626,7 +5715,7 @@ class MinSyncClient {
5626
5715
  }
5627
5716
  };
5628
5717
  }
5629
- if (!existsSync10(cursorPath)) {
5718
+ if (!existsSync11(cursorPath)) {
5630
5719
  restoreConfig();
5631
5720
  return { ok: false, synced: 0, workspacePath: this.workspacePath, reason: "not-ready: missing cursor" };
5632
5721
  }
@@ -5647,7 +5736,7 @@ class MinSyncClient {
5647
5736
  };
5648
5737
  }
5649
5738
  async query(text, topK, mode = "vector", signal) {
5650
- if (!existsSync10(this.binaryPath))
5739
+ if (!existsSync11(this.binaryPath))
5651
5740
  throw minSyncBinaryMissingError();
5652
5741
  const result = await this.spawn(["query", "--format", "json", "--mode", mode, "-k", String(topK), text], {
5653
5742
  ...signal === undefined ? {} : { signal }
@@ -5741,6 +5830,7 @@ var MINSYNC_OLLAMA_MIGRATION_MESSAGE = "This workspace uses the legacy 768-dimen
5741
5830
  var init_client4 = __esm(() => {
5742
5831
  init_embedder_config();
5743
5832
  init_errors();
5833
+ init_kiwi();
5744
5834
  init_local_embedder();
5745
5835
  init_process();
5746
5836
  API_KEY_ENV_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
@@ -5763,14 +5853,14 @@ var init_client4 = __esm(() => {
5763
5853
 
5764
5854
  // src/minsync/installer.ts
5765
5855
  import { createHash as createHash9 } from "node:crypto";
5766
- import { copyFileSync, createWriteStream as createWriteStream2, existsSync as existsSync11, mkdirSync as mkdirSync8, renameSync as renameSync4, rmSync as rmSync5 } from "node:fs";
5856
+ import { copyFileSync, createWriteStream as createWriteStream2, existsSync as existsSync12, mkdirSync as mkdirSync8, renameSync as renameSync4, rmSync as rmSync5 } from "node:fs";
5767
5857
  import { chmod as chmod2, mkdtemp } from "node:fs/promises";
5768
5858
  import { get } from "node:https";
5769
5859
  import { basename as basename7, delimiter as delimiter2, dirname as dirname7, join as join15 } from "node:path";
5770
5860
  import { pipeline } from "node:stream/promises";
5771
5861
  async function ensureMinSyncBinary(options) {
5772
5862
  const binaryPath = join15(options.root, ".autorag", "bin", executableName(options.platform ?? process.platform));
5773
- if (existsSync11(binaryPath))
5863
+ if (existsSync12(binaryPath))
5774
5864
  return { binaryPath, version: "cached" };
5775
5865
  mkdirSync8(dirname7(binaryPath), { recursive: true });
5776
5866
  const cargoInstaller = options.cargoInstaller ?? ((destination) => installMinSyncFromCargoIfAvailable(options, destination));
@@ -5818,7 +5908,7 @@ async function installMinSyncFromCargo(options, destination, cargo) {
5818
5908
  throw new MinSyncReleaseError(result.stderr || `Could not install MinSync ${MINSYNC_VERSION} from crates.io`);
5819
5909
  }
5820
5910
  const installedBinary = join15(cargoRoot, "bin", executableName(options.platform ?? process.platform));
5821
- if (!existsSync11(installedBinary)) {
5911
+ if (!existsSync12(installedBinary)) {
5822
5912
  throw new MinSyncReleaseError(`Cargo did not produce the MinSync ${MINSYNC_VERSION} binary`);
5823
5913
  }
5824
5914
  copyFileSync(installedBinary, destination);
@@ -5950,7 +6040,7 @@ function lookupCargo(env, platform) {
5950
6040
  if (dir.length === 0)
5951
6041
  continue;
5952
6042
  const candidate = join15(dir, execName);
5953
- if (existsSync11(candidate))
6043
+ if (existsSync12(candidate))
5954
6044
  return candidate;
5955
6045
  }
5956
6046
  return;
@@ -5981,7 +6071,7 @@ function isGitHubAsset(value) {
5981
6071
  function isRecord5(value) {
5982
6072
  return typeof value === "object" && value !== null;
5983
6073
  }
5984
- var LATEST_RELEASE_URL = "https://api.github.com/repos/NomaDamas/MinSync/releases/latest", SHA256_HEX_PATTERN, MINSYNC_VERSION = "0.4.8", MINSYNC_CARGO_INSTALL_TIMEOUT_MS, CARGO_PROBE_TIMEOUT_MS = 5000, MinSyncReleaseError;
6074
+ var LATEST_RELEASE_URL = "https://api.github.com/repos/NomaDamas/MinSync/releases/latest", SHA256_HEX_PATTERN, MINSYNC_VERSION = "0.4.10", MINSYNC_CARGO_INSTALL_TIMEOUT_MS, CARGO_PROBE_TIMEOUT_MS = 5000, MinSyncReleaseError;
5985
6075
  var init_installer2 = __esm(() => {
5986
6076
  init_process();
5987
6077
  SHA256_HEX_PATTERN = /^[a-f0-9]{64}$/;
@@ -6009,7 +6099,7 @@ var init_paths2 = __esm(() => {
6009
6099
  import { randomUUID as randomUUID4 } from "node:crypto";
6010
6100
  import {
6011
6101
  copyFileSync as copyFileSync2,
6012
- existsSync as existsSync12,
6102
+ existsSync as existsSync13,
6013
6103
  lstatSync as lstatSync2,
6014
6104
  mkdirSync as mkdirSync9,
6015
6105
  readdirSync as readdirSync2,
@@ -6024,8 +6114,8 @@ function syncMinSyncWorkspace(root, options = {}) {
6024
6114
  const filesRoot = join17(workspacePath, "files");
6025
6115
  const index = loadMirrorIndex(root);
6026
6116
  const candidates = Object.values(index.entries).sort((a, b) => a.virtualPath.localeCompare(b.virtualPath));
6027
- const excluded = candidates.filter((entry) => normalizeVirtualPath(entry.virtualPath) !== entry.virtualPath || !existsSync12(entry.outputPath)).map((entry) => entry.virtualPath);
6028
- const entries = candidates.filter((entry) => normalizeVirtualPath(entry.virtualPath) === entry.virtualPath && existsSync12(entry.outputPath)).map((entry) => {
6117
+ const excluded = candidates.filter((entry) => normalizeVirtualPath(entry.virtualPath) !== entry.virtualPath || !existsSync13(entry.outputPath)).map((entry) => entry.virtualPath);
6118
+ const entries = candidates.filter((entry) => normalizeVirtualPath(entry.virtualPath) === entry.virtualPath && existsSync13(entry.outputPath)).map((entry) => {
6029
6119
  const minSyncPath = minSyncDocumentPath(workspacePath, entry.virtualPath);
6030
6120
  return {
6031
6121
  virtualPath: entry.virtualPath,
@@ -6162,7 +6252,7 @@ var init_workspace = __esm(() => {
6162
6252
  });
6163
6253
 
6164
6254
  // src/minsync/method.ts
6165
- import { accessSync, constants, existsSync as existsSync13, realpathSync as realpathSync4 } from "node:fs";
6255
+ import { accessSync, constants, existsSync as existsSync14, realpathSync as realpathSync4 } from "node:fs";
6166
6256
  import { basename as basename9, delimiter as delimiter3, join as join18, normalize as normalize2 } from "node:path";
6167
6257
  function lookupInPath(env) {
6168
6258
  const pathEnv = env.PATH;
@@ -6258,19 +6348,19 @@ class MinSyncVectorMethod {
6258
6348
  }
6259
6349
  isBinaryMissing() {
6260
6350
  if (this.binaryPath !== undefined)
6261
- return !existsSync13(this.binaryPath);
6351
+ return !existsSync14(this.binaryPath);
6262
6352
  if (lookupInPath(process.env) !== undefined)
6263
6353
  return false;
6264
6354
  const cachedBinary = join18(this.root, ".autorag", "bin", executableName(process.platform));
6265
- if (existsSync13(cachedBinary))
6355
+ if (existsSync14(cachedBinary))
6266
6356
  return false;
6267
6357
  return true;
6268
6358
  }
6269
6359
  isExplicitBinaryMissing() {
6270
- return this.binaryPath !== undefined && !existsSync13(this.binaryPath);
6360
+ return this.binaryPath !== undefined && !existsSync14(this.binaryPath);
6271
6361
  }
6272
6362
  isReady() {
6273
- return existsSync13(join18(this.workspacePath, ".minsync", "cursor.json"));
6363
+ return existsSync14(join18(this.workspacePath, ".minsync", "cursor.json"));
6274
6364
  }
6275
6365
  async retrieve(query, options) {
6276
6366
  if ((workspaceSyncInFlight.get(this.workspacePath) ?? 0) > 0) {
@@ -6323,7 +6413,7 @@ class MinSyncVectorMethod {
6323
6413
  return results;
6324
6414
  }
6325
6415
  async resolveBinary(options = {}) {
6326
- if (this.binaryPath && existsSync13(this.binaryPath))
6416
+ if (this.binaryPath && existsSync14(this.binaryPath))
6327
6417
  return this.binaryPath;
6328
6418
  if (this.binaryPath !== undefined)
6329
6419
  throw minSyncBinaryMissingError();
@@ -6331,7 +6421,7 @@ class MinSyncVectorMethod {
6331
6421
  if (pathBinary)
6332
6422
  return pathBinary;
6333
6423
  const cachedBinary = join18(this.root, ".autorag", "bin", executableName(process.platform));
6334
- if (existsSync13(cachedBinary))
6424
+ if (existsSync14(cachedBinary))
6335
6425
  return cachedBinary;
6336
6426
  if (this.autoInstall && options.install !== false) {
6337
6427
  try {
@@ -7034,7 +7124,7 @@ var init_defaults = __esm(() => {
7034
7124
  });
7035
7125
 
7036
7126
  // src/parser/isolated.ts
7037
- import { existsSync as existsSync14 } from "node:fs";
7127
+ import { existsSync as existsSync15 } from "node:fs";
7038
7128
  import { dirname as dirname10, join as join21 } from "node:path";
7039
7129
  import { fileURLToPath as fileURLToPath2, pathToFileURL } from "node:url";
7040
7130
  import { Worker } from "node:worker_threads";
@@ -7173,7 +7263,7 @@ function defaultWorkerUrl() {
7173
7263
  join21(here, "parser", "parse-worker.js"),
7174
7264
  join21(here, "..", "parser", "parse-worker.js")
7175
7265
  ]) {
7176
- if (existsSync14(candidate))
7266
+ if (existsSync15(candidate))
7177
7267
  return pathToFileURL(candidate);
7178
7268
  }
7179
7269
  throw new Error(`The AutoRAG parse worker entry was not found near ${here}.`);
@@ -7185,7 +7275,7 @@ var init_isolated = __esm(() => {
7185
7275
  });
7186
7276
 
7187
7277
  // src/mirror/sync.ts
7188
- import { existsSync as existsSync15, rmSync as rmSync7 } from "node:fs";
7278
+ import { existsSync as existsSync16, rmSync as rmSync7 } from "node:fs";
7189
7279
  import { opendir, readFile as readFile3, stat as stat5 } from "node:fs/promises";
7190
7280
  import { extname as extname3, resolve as resolve11, sep as sep6 } from "node:path";
7191
7281
  import { setTimeout as sleep3 } from "node:timers/promises";
@@ -7377,7 +7467,7 @@ async function syncWithRegistry(options, registry, isolated) {
7377
7467
  }
7378
7468
  const previousEntry = previous.entries[entry.virtualPath];
7379
7469
  const outputPath = parsedOutputPath(options.root, entry.virtualPath);
7380
- const unchanged = !options.force && previousEntry?.sourceMtimeNs === entry.mtimeNs && previousEntry.sourceSizeBytes === entry.sizeBytes && previousEntry.parserName === parser.name && existsSync15(outputPath);
7470
+ const unchanged = !options.force && previousEntry?.sourceMtimeNs === entry.mtimeNs && previousEntry.sourceSizeBytes === entry.sizeBytes && previousEntry.parserName === parser.name && existsSync16(outputPath);
7381
7471
  if (!unchanged) {
7382
7472
  let bytes;
7383
7473
  try {
@@ -7758,7 +7848,7 @@ function removePrevious(root, index, virtualPath) {
7758
7848
  return 1;
7759
7849
  }
7760
7850
  function removeFile(path) {
7761
- if (existsSync15(path))
7851
+ if (existsSync16(path))
7762
7852
  rmSync7(path, { force: true });
7763
7853
  }
7764
7854
  var DEFAULT_MAX_SOURCE_BYTES, MIRROR_CHECKPOINT_EVERY = 25, DEFAULT_MAX_DELETE_RATIO = 0.3, MASS_DELETE_FLOOR = 100, DEFAULT_MAX_SCANNED_ENTRIES = 2000000, DEFAULT_MAX_WALK_DEPTH = 64, PRODUCT_ARTIFACT_FILE_NAMES, SKIP_DIR_NAMES, PARSER_FAILURE_MESSAGE = "The registered parser failed on this file; it was skipped during indexing.", PARSER_CRASH_MESSAGE = "The registered parser crashed unexpectedly on this file; it was skipped during indexing.", DEFAULT_TRANSIENT_RETRIES = 3, DEFAULT_TRANSIENT_BACKOFF_MS = 50, TRANSIENT_ERROR_CODES, WORKSPACE_ERROR_CODES, MirrorWorkspaceError, STANDALONE_OCR_IMAGE_EXTENSIONS, RETRYABLE_SKIP_MESSAGES, SEARCH_ROOT_UNAVAILABLE_MESSAGES;
@@ -11483,6 +11573,20 @@ function interactiveKeyOf(data) {
11483
11573
  return "followUp";
11484
11574
  return;
11485
11575
  }
11576
+ function stripTelegramEnvelope(text) {
11577
+ return text.replace(/^\s*\[telegram\]\s?/u, "").replace(/\n*\[time\][^\n]*/gu, "").trim();
11578
+ }
11579
+ function userInputText(event) {
11580
+ if (event.source === "interactive")
11581
+ return event.text.trim();
11582
+ if (event.source === "extension" && event.text.trimStart().startsWith(TELEGRAM_INPUT_PREFIX)) {
11583
+ return stripTelegramEnvelope(event.text);
11584
+ }
11585
+ if (event.source === "extension" && event.text.trimStart().startsWith(WHATSAPP_INPUT_PREFIX)) {
11586
+ return event.text.trim();
11587
+ }
11588
+ return;
11589
+ }
11486
11590
  function createAutoRAGInteractiveExtension(getSystemPrompt, contextTransform, options, updateNotice) {
11487
11591
  return (pi) => {
11488
11592
  pi.on("before_agent_start", () => ({ systemPrompt: getSystemPrompt() }));
@@ -11513,8 +11617,8 @@ function createAutoRAGInteractiveExtension(getSystemPrompt, contextTransform, op
11513
11617
  });
11514
11618
  }
11515
11619
  pi.on("input", (event) => {
11516
- const text = event.text.trim();
11517
- if (event.source !== "interactive" || text.length === 0)
11620
+ const text = userInputText(event);
11621
+ if (text === undefined || text.length === 0)
11518
11622
  return;
11519
11623
  if (text.startsWith("/") && isSearchRunning?.() !== true)
11520
11624
  return;
@@ -11611,7 +11715,9 @@ async function createAutoRAGPiInteractiveRuntime(options) {
11611
11715
  agentDir: runtimeAgentDir,
11612
11716
  modelRuntime,
11613
11717
  settingsManager,
11718
+ ...options.extensionFlags === undefined ? {} : { extensionFlagValues: new Map(Object.entries(options.extensionFlags)) },
11614
11719
  resourceLoaderOptions: {
11720
+ ...options.extensionPaths === undefined ? {} : { additionalExtensionPaths: [...options.extensionPaths] },
11615
11721
  extensionFactories: [
11616
11722
  createAutoRAGInteractiveExtension(options.getSystemPrompt, options.contextTransform, { onInput: options.onInput, isSearchRunning: options.isSearchRunning, onKey: options.onKey }, options.updateNotice),
11617
11723
  ...options.extensionFactories ?? []
@@ -11645,7 +11751,7 @@ async function createAutoRAGPiInteractiveRuntime(options) {
11645
11751
  });
11646
11752
  return { runtime, dispose: () => runtime.dispose() };
11647
11753
  }
11648
- var PI_BUILTIN_TOOL_NAMES, EMBEDDED_AUTH_MARKER = "<autorag-embedded-model>";
11754
+ var PI_BUILTIN_TOOL_NAMES, EMBEDDED_AUTH_MARKER = "<autorag-embedded-model>", TELEGRAM_INPUT_PREFIX = "[telegram]", WHATSAPP_INPUT_PREFIX = "Message from ";
11649
11755
  var init_pi_session = __esm(() => {
11650
11756
  init_provider();
11651
11757
  init_context_token_guard();
@@ -11901,11 +12007,11 @@ var init_jikji_find_tool = __esm(() => {
11901
12007
 
11902
12008
  // src/agent/local-model.ts
11903
12009
  import { readFileSync as readFileSync12 } from "node:fs";
11904
- import { homedir as homedir2 } from "node:os";
12010
+ import { homedir as homedir3 } from "node:os";
11905
12011
  import { join as join24 } from "node:path";
11906
12012
  import { parse as parse2 } from "smol-toml";
11907
12013
  function loadLocalAutoRAGModel(options = {}) {
11908
- const configPath = options.configPath ?? join24(homedir2(), ".codex", "config.toml");
12014
+ const configPath = options.configPath ?? join24(homedir3(), ".codex", "config.toml");
11909
12015
  const config = parse2(readFileSync12(configPath, "utf8"));
11910
12016
  const provider = config.model_provider;
11911
12017
  if (typeof provider !== "string" || provider.length === 0) {
@@ -11948,7 +12054,7 @@ var init_local_model = () => {};
11948
12054
 
11949
12055
  // src/p2p/approval-store.ts
11950
12056
  import {
11951
- existsSync as existsSync16,
12057
+ existsSync as existsSync17,
11952
12058
  mkdirSync as mkdirSync11,
11953
12059
  readdirSync as readdirSync3,
11954
12060
  readFileSync as readFileSync13,
@@ -12013,7 +12119,7 @@ function savePendingPeerRequest(workspacePath, request) {
12013
12119
  }
12014
12120
  function loadPendingPeerRequest(workspacePath, id) {
12015
12121
  const path = requestPath(workspacePath, id);
12016
- if (!existsSync16(path))
12122
+ if (!existsSync17(path))
12017
12123
  return;
12018
12124
  try {
12019
12125
  return parsePending(JSON.parse(readFileSync13(path, "utf8")));
@@ -12023,7 +12129,7 @@ function loadPendingPeerRequest(workspacePath, id) {
12023
12129
  }
12024
12130
  function listPendingPeerRequests(workspacePath) {
12025
12131
  const dir = requestsDir(workspacePath);
12026
- if (!existsSync16(dir))
12132
+ if (!existsSync17(dir))
12027
12133
  return [];
12028
12134
  const requests = [];
12029
12135
  for (const name of readdirSync3(dir)) {
@@ -12045,7 +12151,7 @@ function writePeerRequestDecision(workspacePath, id, decision) {
12045
12151
  }
12046
12152
  function loadPeerRequestDecision(workspacePath, id) {
12047
12153
  const path = decisionPath(workspacePath, id);
12048
- if (!existsSync16(path))
12154
+ if (!existsSync17(path))
12049
12155
  return;
12050
12156
  try {
12051
12157
  return parseDecision(JSON.parse(readFileSync13(path, "utf8")));
@@ -12379,7 +12485,7 @@ var init_egress_gate = __esm(() => {
12379
12485
  });
12380
12486
 
12381
12487
  // src/p2p/policy.ts
12382
- import { existsSync as existsSync17, mkdirSync as mkdirSync12, readFileSync as readFileSync14, writeFileSync as writeFileSync10 } from "node:fs";
12488
+ import { existsSync as existsSync18, mkdirSync as mkdirSync12, readFileSync as readFileSync14, writeFileSync as writeFileSync10 } from "node:fs";
12383
12489
  import { basename as basename10, dirname as dirname13, join as join26, resolve as resolve12 } from "node:path";
12384
12490
  import { parse as parseToml } from "smol-toml";
12385
12491
  function isRecord11(value) {
@@ -12459,7 +12565,7 @@ function normalizePolicyEntries(value, workspacePath, context) {
12459
12565
  return entries;
12460
12566
  }
12461
12567
  function readJsonFile(path) {
12462
- if (!existsSync17(path))
12568
+ if (!existsSync18(path))
12463
12569
  return;
12464
12570
  let raw;
12465
12571
  try {
@@ -12474,7 +12580,7 @@ function readJsonFile(path) {
12474
12580
  }
12475
12581
  }
12476
12582
  function readTomlFile(path) {
12477
- if (!existsSync17(path))
12583
+ if (!existsSync18(path))
12478
12584
  return;
12479
12585
  let raw;
12480
12586
  try {
@@ -12615,7 +12721,7 @@ function globToRegExp(pattern) {
12615
12721
  return new RegExp(`${expression}$`, "u");
12616
12722
  }
12617
12723
  function loadSeenSources(path, workspacePath) {
12618
- if (!existsSync17(path))
12724
+ if (!existsSync18(path))
12619
12725
  return { promoted: new Set, pending: new Set };
12620
12726
  let parsed;
12621
12727
  try {
@@ -12922,7 +13028,7 @@ var init_wire = __esm(() => {
12922
13028
 
12923
13029
  // src/p2p/simplex-query-store.ts
12924
13030
  import { randomUUID as randomUUID5 } from "node:crypto";
12925
- import { existsSync as existsSync18, mkdirSync as mkdirSync13, readdirSync as readdirSync4, readFileSync as readFileSync15, renameSync as renameSync7, unlinkSync as unlinkSync4, writeFileSync as writeFileSync11 } from "node:fs";
13031
+ import { existsSync as existsSync19, mkdirSync as mkdirSync13, readdirSync as readdirSync4, readFileSync as readFileSync15, renameSync as renameSync7, unlinkSync as unlinkSync4, writeFileSync as writeFileSync11 } from "node:fs";
12926
13032
  import { dirname as dirname14, join as join27 } from "node:path";
12927
13033
  import { Value as Value2 } from "typebox/value";
12928
13034
  function statePath(workspacePath, directory, id) {
@@ -12958,7 +13064,7 @@ function parseState(value) {
12958
13064
  return value;
12959
13065
  }
12960
13066
  function readState(path) {
12961
- if (!existsSync18(path))
13067
+ if (!existsSync19(path))
12962
13068
  return;
12963
13069
  try {
12964
13070
  return parseState(JSON.parse(readFileSync15(path, "utf8")));
@@ -12985,14 +13091,14 @@ function moveState(workspacePath, from, to, state) {
12985
13091
  }
12986
13092
  function recoverClaims(workspacePath) {
12987
13093
  const directory = join27(workspacePath, QUERY_DIR, PENDING_DIR);
12988
- if (!existsSync18(directory))
13094
+ if (!existsSync19(directory))
12989
13095
  return;
12990
13096
  for (const name of readdirSync4(directory)) {
12991
13097
  if (!name.endsWith(".json.claim"))
12992
13098
  continue;
12993
13099
  const claim = join27(directory, name);
12994
13100
  const restored = join27(directory, name.slice(0, -".claim".length));
12995
- if (!existsSync18(restored))
13101
+ if (!existsSync19(restored))
12996
13102
  renameSync7(claim, restored);
12997
13103
  }
12998
13104
  }
@@ -13016,7 +13122,7 @@ function loadSimplexQueryState(workspacePath, id) {
13016
13122
  }
13017
13123
  function listPendingSimplexQueryStates(workspacePath) {
13018
13124
  const directory = join27(workspacePath, QUERY_DIR, PENDING_DIR);
13019
- if (!existsSync18(directory))
13125
+ if (!existsSync19(directory))
13020
13126
  return [];
13021
13127
  return readdirSync4(directory).filter((name) => name.endsWith(".json")).map((name) => readState(join27(directory, name))).filter((state) => state?.status === "pending").filter((state) => loadSimplexQueryState(workspacePath, state.id)?.status === "pending").sort((left, right) => left.createdAt.localeCompare(right.createdAt));
13022
13128
  }
@@ -13159,7 +13265,7 @@ var init_simplex_query_store = __esm(() => {
13159
13265
  });
13160
13266
 
13161
13267
  // src/p2p/simplex-server.ts
13162
- import { existsSync as existsSync19, mkdirSync as mkdirSync14, readFileSync as readFileSync16, writeFileSync as writeFileSync12 } from "node:fs";
13268
+ import { existsSync as existsSync20, mkdirSync as mkdirSync14, readFileSync as readFileSync16, writeFileSync as writeFileSync12 } from "node:fs";
13163
13269
  import { join as join28 } from "node:path";
13164
13270
  import { Type as Type10 } from "typebox";
13165
13271
  import { Value as Value3 } from "typebox/value";
@@ -13188,7 +13294,7 @@ function rankSimplexPeerTargets(query, registry) {
13188
13294
  }
13189
13295
  function loadSimplexPeerRegistry(workspacePath) {
13190
13296
  const path = join28(workspacePath, PEERS_DIR, PEERS_FILENAME);
13191
- if (!existsSync19(path))
13297
+ if (!existsSync20(path))
13192
13298
  return {};
13193
13299
  try {
13194
13300
  const parsed = JSON.parse(readFileSync16(path, "utf8"));
@@ -14313,14 +14419,14 @@ var init_search_single_datasource_tool = __esm(() => {
14313
14419
  });
14314
14420
 
14315
14421
  // src/agent/self-config.ts
14316
- import { existsSync as existsSync20, readFileSync as readFileSync18, rmSync as rmSync9, writeFileSync as writeFileSync14 } from "node:fs";
14422
+ import { existsSync as existsSync21, readFileSync as readFileSync18, rmSync as rmSync9, writeFileSync as writeFileSync14 } from "node:fs";
14317
14423
  import { dirname as dirname16, join as join29 } from "node:path";
14318
14424
  import { fileURLToPath as fileURLToPath3 } from "node:url";
14319
14425
  function findPackagedSetupSkill() {
14320
14426
  let dir = dirname16(fileURLToPath3(import.meta.url));
14321
14427
  for (let depth = 0;depth < 6; depth += 1) {
14322
14428
  const candidate = join29(dir, SETUP_SKILL_RELATIVE_PATH);
14323
- if (existsSync20(candidate))
14429
+ if (existsSync21(candidate))
14324
14430
  return candidate;
14325
14431
  const parent = dirname16(dir);
14326
14432
  if (parent === dir)
@@ -14343,7 +14449,7 @@ function loadSetupSkill(skillPath) {
14343
14449
  return text.replace(/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n)+/u, "");
14344
14450
  }
14345
14451
  function snapshotConfigFile(configPath) {
14346
- return existsSync20(configPath) ? readFileSync18(configPath, "utf8") : undefined;
14452
+ return existsSync21(configPath) ? readFileSync18(configPath, "utf8") : undefined;
14347
14453
  }
14348
14454
  async function rollbackIfBroken(options, before) {
14349
14455
  if (options.validate === undefined)
@@ -16866,11 +16972,6 @@ var init_types3 = __esm(() => {
16866
16972
  label: "xAI",
16867
16973
  description: "xAI Responses web_search via the agent's xAI model credentials (XAI_API_KEY)"
16868
16974
  },
16869
- {
16870
- value: "perplexity",
16871
- label: "Perplexity",
16872
- description: "Anonymous Perplexity ask endpoint; no key or signup required"
16873
- },
16874
16975
  {
16875
16976
  value: "parallel",
16876
16977
  label: "Parallel",
@@ -16881,16 +16982,21 @@ var init_types3 = __esm(() => {
16881
16982
  label: "SearXNG",
16882
16983
  description: "Advanced: requires a self-hosted SEARXNG_ENDPOINT; never part of the default experience"
16883
16984
  },
16884
- {
16885
- value: "startpage",
16886
- label: "Startpage",
16887
- description: "Credential-free scrape of Startpage (Google-backed) results; may be bot-challenged"
16888
- },
16889
16985
  {
16890
16986
  value: "duckduckgo",
16891
16987
  label: "DuckDuckGo",
16892
16988
  description: "Credential-free best-effort fallback; may be bot-challenged on datacenter/shared-egress IPs"
16893
16989
  },
16990
+ {
16991
+ value: "perplexity",
16992
+ label: "Perplexity",
16993
+ description: "Anonymous Perplexity ask endpoint; no key or signup required"
16994
+ },
16995
+ {
16996
+ value: "startpage",
16997
+ label: "Startpage",
16998
+ description: "Credential-free scrape of Startpage (Google-backed) results; may be bot-challenged"
16999
+ },
16894
17000
  {
16895
17001
  value: "ecosia",
16896
17002
  label: "Ecosia",
@@ -18238,12 +18344,11 @@ function eventAnswer(event) {
18238
18344
  }
18239
18345
  return "";
18240
18346
  }
18241
- var PERPLEXITY_ASK_URL = "https://www.perplexity.ai/rest/sse/perplexity_ask", API_VERSION2 = "2.18", DEFLECTION_PATTERN, MAX_ERROR_BYTES4, ANONYMOUS_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36", PERPLEXITY_QUERY_SYNTAX, PerplexityProvider;
18347
+ var PERPLEXITY_ASK_URL = "https://www.perplexity.ai/rest/sse/perplexity_ask", API_VERSION2 = "2.18", MAX_ERROR_BYTES4, ANONYMOUS_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36", PERPLEXITY_QUERY_SYNTAX, PerplexityProvider;
18242
18348
  var init_perplexity = __esm(() => {
18243
18349
  init_query();
18244
18350
  init_types3();
18245
18351
  init_utils();
18246
- DEFLECTION_PATTERN = /sign up|log in|create an account|verify you are human|are you a robot|가입|로그인|회원 ?가입/i;
18247
18352
  MAX_ERROR_BYTES4 = 8 * 1024;
18248
18353
  PERPLEXITY_QUERY_SYNTAX = {
18249
18354
  phrases: true,
@@ -18357,8 +18462,8 @@ var init_perplexity = __esm(() => {
18357
18462
  break;
18358
18463
  }
18359
18464
  const sources = [...sourcesByUrl.values()];
18360
- if (sources.length === 0 && DEFLECTION_PATTERN.test(answer)) {
18361
- throw new SearchProviderError("perplexity", "Perplexity anonymous ask was deflected with a sign-up wall", 403);
18465
+ if (sources.length === 0) {
18466
+ throw new SearchProviderError("perplexity", `Perplexity anonymous ask returned no web sources (sign-up wall or conversational deflection): ${answer.slice(0, 120)}`, 403);
18362
18467
  }
18363
18468
  const numResults = params.numSearchResults ?? params.limit;
18364
18469
  return {
@@ -18776,7 +18881,7 @@ var init_browser_headers = __esm(() => {
18776
18881
  });
18777
18882
 
18778
18883
  // src/web/search/browser-loader.ts
18779
- import { existsSync as existsSync21 } from "node:fs";
18884
+ import { existsSync as existsSync22 } from "node:fs";
18780
18885
  async function closeBounded(close) {
18781
18886
  let timer;
18782
18887
  try {
@@ -18855,7 +18960,7 @@ function ensureWebSearchBrowserLoader(options = {}) {
18855
18960
  return true;
18856
18961
  const exists = options.exists ?? ((path) => {
18857
18962
  try {
18858
- return existsSync21(path);
18963
+ return existsSync22(path);
18859
18964
  } catch {
18860
18965
  return false;
18861
18966
  }
@@ -18960,6 +19065,8 @@ function normalizeText(value) {
18960
19065
  function isChallengeResponse(page) {
18961
19066
  if (/\/(?:errors|captcha)\//.test(page.url) || page.url.includes("/sp/captcha"))
18962
19067
  return true;
19068
+ if (ANUBIS_CHALLENGE_PATTERN.test(page.html))
19069
+ return true;
18963
19070
  return page.html.includes("component---src-pages-captcha") || page.html.includes("/sp/captcha");
18964
19071
  }
18965
19072
  function parseSearchFormInputs(html) {
@@ -19064,7 +19171,7 @@ async function callStartpageHtml(params) {
19064
19171
  });
19065
19172
  }
19066
19173
  if (isChallengeResponse(page)) {
19067
- throw new SearchProviderError("startpage", "Startpage blocked the request with a CAPTCHA challenge. Startpage rate-limits automated searches from datacenter/shared-egress IPs; try another provider such as DuckDuckGo or Mojeek, or retry later.", 429);
19174
+ throw new SearchProviderError("startpage", "Startpage blocked the request with a bot challenge (CAPTCHA or Anubis proof-of-work). Startpage rate-limits automated searches from datacenter/shared-egress IPs; try another provider such as DuckDuckGo or Mojeek, or retry later.", 429);
19068
19175
  }
19069
19176
  if (page.status < 200 || page.status >= 300) {
19070
19177
  const classified = classifyProviderHttpError("startpage", page.status, page.html);
@@ -19090,7 +19197,7 @@ async function searchStartpage(params) {
19090
19197
  }
19091
19198
  return { provider: "startpage", sources };
19092
19199
  }
19093
- var STARTPAGE_HOME_URL = "https://www.startpage.com/", STARTPAGE_SEARCH_URL = "https://www.startpage.com/sp/search", DEFAULT_NUM_RESULTS3 = 10, MAX_NUM_RESULTS3 = 20, RECENCY_TO_STARTPAGE_WITH_DATE, StartpageProvider;
19200
+ var STARTPAGE_HOME_URL = "https://www.startpage.com/", STARTPAGE_SEARCH_URL = "https://www.startpage.com/sp/search", DEFAULT_NUM_RESULTS3 = 10, MAX_NUM_RESULTS3 = 20, RECENCY_TO_STARTPAGE_WITH_DATE, ANUBIS_CHALLENGE_PATTERN, StartpageProvider;
19094
19201
  var init_startpage = __esm(() => {
19095
19202
  init_entities();
19096
19203
  init_browser_page();
@@ -19103,6 +19210,7 @@ var init_startpage = __esm(() => {
19103
19210
  month: "m",
19104
19211
  year: "y"
19105
19212
  };
19213
+ ANUBIS_CHALLENGE_PATTERN = /<script\b[^>]*\bid\s*=\s*["']anubis_(?:challenge|version)["']/i;
19106
19214
  StartpageProvider = class StartpageProvider extends SearchProvider {
19107
19215
  id = "startpage";
19108
19216
  label = "Startpage";
@@ -20320,7 +20428,7 @@ var init_web_search_tool = __esm(() => {
20320
20428
 
20321
20429
  // src/agent/agent.ts
20322
20430
  import { randomUUID as randomUUID7 } from "node:crypto";
20323
- import { existsSync as existsSync22, watch as fsWatch, mkdirSync as mkdirSync16, realpathSync as realpathSync5, statSync as statSync2, writeFileSync as writeFileSync15 } from "node:fs";
20431
+ import { existsSync as existsSync23, watch as fsWatch, mkdirSync as mkdirSync16, realpathSync as realpathSync5, statSync as statSync2, writeFileSync as writeFileSync15 } from "node:fs";
20324
20432
  import { basename as basename11, dirname as dirname17, join as join31, resolve as resolve13 } from "node:path";
20325
20433
  import { clampThinkingLevel } from "@earendil-works/pi-ai/compat";
20326
20434
  import { getAgentDir as getAgentDir3 } from "@earendil-works/pi-coding-agent";
@@ -20451,6 +20559,9 @@ class AutoRAGAgent {
20451
20559
  piSessionDir;
20452
20560
  persistPiSessions;
20453
20561
  updateNotice;
20562
+ piExtensionPaths;
20563
+ piExtensionFlags;
20564
+ telegram;
20454
20565
  boundPiRuntime;
20455
20566
  memoryEmbedder;
20456
20567
  memoryVectorPath;
@@ -20476,6 +20587,9 @@ class AutoRAGAgent {
20476
20587
  this.piSessionDir = options.piSessionDir;
20477
20588
  this.persistPiSessions = options.persistPiSessions ?? true;
20478
20589
  this.updateNotice = options.updateNotice;
20590
+ this.piExtensionPaths = options.piExtensionPaths;
20591
+ this.piExtensionFlags = options.piExtensionFlags;
20592
+ this.telegram = options.telegram === true;
20479
20593
  this.datasourceSkills = options.datasourceSkills ?? [];
20480
20594
  this.datasourceRetry = options.datasourceRetry ?? {};
20481
20595
  this.datasourceVirtualScopePrefixes = this.datasourceSkills.map((skill) => normalizeVirtualPath2(`/${skill.describe().name}`));
@@ -20947,6 +21061,7 @@ ${context.text}
20947
21061
  }
20948
21062
  async createPiInteractiveRuntime() {
20949
21063
  const resolved = this.configuredModel === undefined ? undefined : await this.resolveSessionModel();
21064
+ const telegramBridge = this.telegram ? (await import("@llblab/pi-telegram")).default : undefined;
20950
21065
  const runtime = await createAutoRAGPiInteractiveRuntime({
20951
21066
  cwd: this.workspaceProjectRoot,
20952
21067
  agentDir: this.piAgentDir,
@@ -20967,11 +21082,14 @@ ${context.text}
20967
21082
  onKey: (key) => this.handleInteractiveKey(key),
20968
21083
  extensionFactories: [
20969
21084
  createEvidencePersistence(this.evidenceLedger),
20970
- ...this.jevExtension !== undefined ? [this.jevExtension] : []
21085
+ ...this.jevExtension !== undefined ? [this.jevExtension] : [],
21086
+ ...telegramBridge !== undefined ? [telegramBridge] : []
20971
21087
  ],
20972
21088
  ...this.jevExtension !== undefined ? { extensionToolNames: [JEV_TOOL_NAME] } : {},
20973
21089
  remoteSession: this.remoteSession,
20974
- ...this.updateNotice === undefined ? {} : { updateNotice: this.updateNotice }
21090
+ ...this.updateNotice === undefined ? {} : { updateNotice: this.updateNotice },
21091
+ ...this.piExtensionPaths === undefined ? {} : { extensionPaths: this.piExtensionPaths },
21092
+ ...this.piExtensionFlags === undefined ? {} : { extensionFlags: this.piExtensionFlags }
20975
21093
  });
20976
21094
  this.boundPiRuntime = runtime.runtime;
20977
21095
  const dispose = runtime.dispose;
@@ -21891,22 +22009,22 @@ ${result.content.replace(/\s+/gu, " ")}`).join(`
21891
22009
  const scope = options.scope ? ` Restrict search to virtual path scope ${options.scope}.` : "";
21892
22010
  return `Answer this original query immediately: ${query}${limit}${scope}
21893
22011
 
21894
- ` + `Baseline retrieval evidence (already gathered for you):
22012
+ Baseline retrieval evidence (already gathered for you):
21895
22013
  ${baseline}
21896
22014
 
21897
- ` + `Produce the best complete, self-contained answer you can RIGHT NOW from this evidence. Do NOT call any search, retrieval, or file-reading tools and do NOT wait for more evidence. ` + `If the query is answerable from general knowledge alone, answer directly.
22015
+ Produce the best complete, self-contained answer you can RIGHT NOW from this evidence. Do NOT call any search, retrieval, or file-reading tools and do NOT wait for more evidence. If the query is answerable from general knowledge alone, answer directly.
21898
22016
 
21899
- ` + `Formatting and content rules for the answer:
21900
- ` + `- Unless the user explicitly requests a different format or length, provide the core answer to the user's question in at most 5 bullet points. If additional explanation is necessary, append it after the bullet points.
21901
- ` + `- Unless the user explicitly requests otherwise, answer the question directly. Do not include specific file paths, datasource descriptions, or retrieval mechanics in the answer text.
21902
- ` + `- ${ANSWER_DELIVERABLE_RULE}
21903
- ` + `- ${ANSWER_CITATION_RULE}
21904
- ` + `- ${ANSWER_IMAGE_EMBED_RULE}
21905
- ` + `- Do not report per-source negative findings (e.g. "no information found in Slack" or "checked Drive but found nothing").
21906
- ` + `- When evidence conflicts, treat the freshest (most recent) information as the correct source of truth.
21907
- ` + `- If information is incomplete or uncertain, acknowledge it briefly without lengthy explanations, stating that it is difficult to answer fully with the given information and searching continues. If there are partial clues or leads (even if not the exact answer), mention those clues concisely.
22017
+ Formatting and content rules for the answer:
22018
+ - Unless the user explicitly requests a different format or length, provide the core answer to the user's question in at most 5 bullet points. If additional explanation is necessary, append it after the bullet points.
22019
+ - Unless the user explicitly requests otherwise, answer the question directly. Do not include specific file paths, datasource descriptions, or retrieval mechanics in the answer text.
22020
+ - ${ANSWER_DELIVERABLE_RULE}
22021
+ - ${ANSWER_CITATION_RULE}
22022
+ - ${ANSWER_IMAGE_EMBED_RULE}
22023
+ - Do not report per-source negative findings (e.g. "no information found in Slack" or "checked Drive but found nothing").
22024
+ - When evidence conflicts, treat the freshest (most recent) information as the correct source of truth.
22025
+ - If information is incomplete or uncertain, acknowledge it briefly without lengthy explanations, stating that it is difficult to answer fully with the given information and searching continues. If there are partial clues or leads (even if not the exact answer), mention those clues concisely.
21908
22026
 
21909
- ` + `Write the answer as your reply, then stop.`;
22027
+ Write the answer as your reply, then stop.`;
21910
22028
  }
21911
22029
  isConversationTurn() {
21912
22030
  if (this.remoteSession || this.boundPiRuntime === undefined)
@@ -21916,7 +22034,7 @@ ${baseline}
21916
22034
  buildDirectAnswerPrompt(query) {
21917
22035
  return `Answer this query directly from your own general knowledge: ${query}
21918
22036
 
21919
- ` + `It needs no search: it is general knowledge, simple reasoning, or conversation. Do NOT call any search, retrieval, web, or file-reading tools. ` + `Reply naturally and concisely; for small talk, just respond conversationally. Do not cite sources or mention retrieval.`;
22037
+ It needs no search: it is general knowledge, simple reasoning, or conversation. Do NOT call any search, retrieval, web, or file-reading tools. Reply naturally and concisely; for small talk, just respond conversationally. Do not cite sources or mention retrieval.`;
21920
22038
  }
21921
22039
  discoveryHint(sentence) {
21922
22040
  const names = this.tools.map((tool) => tool.name).filter((name) => name === JIKJI_FIND_TOOL_NAME || name === EVERYTHING_SEARCH_TOOL_NAME);
@@ -21934,55 +22052,55 @@ ${baseline}
21934
22052
  const scope = options.scope ? ` Restrict search to virtual path scope ${options.scope}.` : "";
21935
22053
  const firstAnswer = formatFirstAnswerContext(fastAnswer, fastAnswerDelivered);
21936
22054
  const answerRules = fastAnswerDelivered ? `Formatting and content rules for your final answer (DELTA ONLY):
21937
- ` + `- The user already has the first answer above. Your final answer MUST contain only the delta against it: (a) corrections to anything in the first answer that is wrong, unsupported, or outdated, and (b) newly verified findings that were not present in the first answer.
21938
- ` + `- NEVER restate or re-list first-answer facts that remain correct, and never repeat its bullet list.
21939
- ` + `- Mark each item clearly as a correction or as a new finding.
21940
- ` + `- If verification changed nothing and found nothing new, say so in one short line (the first answer is confirmed as-is) instead of restating it.
21941
- ` + `- ${ANSWER_DELIVERABLE_RULE} ${ANSWER_DELIVERABLE_DELTA_RULE}
21942
- ` + `- ${ANSWER_CITATION_RULE} A correction or new finding that relies on evidence the first answer cited must cite that evidence's id again.
21943
- ` + `- ${ANSWER_IMAGE_EMBED_RULE} ${ANSWER_IMAGE_DELTA_RULE}
21944
- ` + `- Do not report per-source negative findings (e.g. "no information found in Slack").
21945
- ` + `- When evidence conflicts, treat the freshest (most recent) information as the correct source of truth.` : `Formatting and content rules for the final answer (COMPLETE — no first answer reached the caller):
22055
+ - The user already has the first answer above. Your final answer MUST contain only the delta against it: (a) corrections to anything in the first answer that is wrong, unsupported, or outdated, and (b) newly verified findings that were not present in the first answer.
22056
+ - NEVER restate or re-list first-answer facts that remain correct, and never repeat its bullet list.
22057
+ - Mark each item clearly as a correction or as a new finding.
22058
+ - If verification changed nothing and found nothing new, say so in one short line (the first answer is confirmed as-is) instead of restating it.
22059
+ - ${ANSWER_DELIVERABLE_RULE} ${ANSWER_DELIVERABLE_DELTA_RULE}
22060
+ - ${ANSWER_CITATION_RULE} A correction or new finding that relies on evidence the first answer cited must cite that evidence's id again.
22061
+ - ${ANSWER_IMAGE_EMBED_RULE} ${ANSWER_IMAGE_DELTA_RULE}
22062
+ - Do not report per-source negative findings (e.g. "no information found in Slack").
22063
+ - When evidence conflicts, treat the freshest (most recent) information as the correct source of truth.` : `Formatting and content rules for the final answer (COMPLETE — no first answer reached the caller):
21946
22064
  ` + `- Unless the user explicitly requests a different format or length, provide the core answer to the user's question in at most 5 bullet points. If additional explanation is necessary, append it after the bullet points.
21947
- ` + `- Unless the user explicitly requests otherwise, answer the question directly. Do not include specific file paths, datasource descriptions, or retrieval mechanics in the answer text.
21948
- ` + `- ${ANSWER_DELIVERABLE_RULE}${fastAnswer !== undefined ? ` ${ANSWER_DELIVERABLE_DELTA_RULE}` : ""}
21949
- ` + `- ${ANSWER_CITATION_RULE}
21950
- ` + `- ${ANSWER_IMAGE_EMBED_RULE}
21951
- ` + `- Do not report per-source negative findings (e.g. "no information found in Slack").
21952
- ` + `- When evidence conflicts, treat the freshest (most recent) information as the correct source of truth.`;
22065
+ - Unless the user explicitly requests otherwise, answer the question directly. Do not include specific file paths, datasource descriptions, or retrieval mechanics in the answer text.
22066
+ - ${ANSWER_DELIVERABLE_RULE}${fastAnswer !== undefined ? ` ${ANSWER_DELIVERABLE_DELTA_RULE}` : ""}
22067
+ - ${ANSWER_CITATION_RULE}
22068
+ - ${ANSWER_IMAGE_EMBED_RULE}
22069
+ - Do not report per-source negative findings (e.g. "no information found in Slack").
22070
+ - When evidence conflicts, treat the freshest (most recent) information as the correct source of truth.`;
21953
22071
  return `Original query: ${query}${limit}${scope}
21954
22072
 
21955
- ` + `${firstAnswer}
22073
+ ${firstAnswer}
21956
22074
 
21957
22075
  ` + formatSteerContext(steers) + `Now verify it rigorously. ${this.discoveryHint((tools) => `Actively use ${tools} when discovering or exploring local files and folders. `)}Check important claims against source files with bash when needed, correct anything wrong or unsupported, fill gaps with retrieval tools, and resolve conflicts and freshness. ${this.webFallbackHint()}
21958
22076
 
21959
- ` + `${answerRules}
22077
+ ${answerRules}
21960
22078
 
21961
- ` + `Do not use broad grep/find or recursive filesystem scans: only inspect a path or narrow neighborhood surfaced by retrieval, and only when evidence clearly points there. ` + `Avoid spinning repeated near-identical queries against the same datasource; once additional attempts stop surfacing new evidence, conclude from the evidence available. ` + `If more search is needed, first write a brief 1–2 line progress update stating the best current hypothesis and what you are checking next, then call retrieval tools. ` + `When finished, reply with the final answer and no tool call: that last reply is what the user receives, so keep progress notes out of it.`;
22079
+ Do not use broad grep/find or recursive filesystem scans: only inspect a path or narrow neighborhood surfaced by retrieval, and only when evidence clearly points there. Avoid spinning repeated near-identical queries against the same datasource; once additional attempts stop surfacing new evidence, conclude from the evidence available. ` + `If more search is needed, first write a brief 1–2 line progress update stating the best current hypothesis and what you are checking next, then call retrieval tools. ` + `When finished, reply with the final answer and no tool call: that last reply is what the user receives, so keep progress notes out of it.`;
21962
22080
  }
21963
22081
  buildSearchPrompt(query, options, initialRetrievalContext) {
21964
22082
  const limit = typeof options.topK === "number" ? ` Cite at most ${options.topK} sources.` : "";
21965
22083
  const scope = options.scope ? ` Restrict search to virtual path scope ${options.scope}.` : "";
21966
22084
  return `Find and curate information for this original query: ${query}${limit}${scope}
21967
22085
 
21968
- ` + `Start by deciding whether this is answerable from general knowledge or memory. If it is a generic, stable question, answer it immediately without retrieval. ` + `Otherwise, baseline MinSync and Jikji retrieval is already running in parallel; do not give the final answer until its next message arrives.
22086
+ Start by deciding whether this is answerable from general knowledge or memory. If it is a generic, stable question, answer it immediately without retrieval. Otherwise, baseline MinSync and Jikji retrieval is already running in parallel; do not give the final answer until its next message arrives.
21969
22087
 
21970
- ` + `Baseline retrieval context:
22088
+ Baseline retrieval context:
21971
22089
  ${initialRetrievalContext ?? "Pending; continue only with a brief progress statement."}
21972
22090
 
21973
- ` + `Treat candidates as unverified evidence, verify important claims against source files when needed, and use additional tools when needed. ` + `Judge relevance, conflicts, freshness, and sufficiency in this agent loop.
22091
+ Treat candidates as unverified evidence, verify important claims against source files when needed, and use additional tools when needed. Judge relevance, conflicts, freshness, and sufficiency in this agent loop.
21974
22092
 
21975
- ` + `Formatting and content rules for the answer:
21976
- ` + `- Unless the user explicitly requests a different format or length, provide the core answer to the user's question in at most 5 bullet points. If additional explanation is necessary, append it after the bullet points.
21977
- ` + `- Unless the user explicitly requests otherwise, answer the question directly. Do not include specific file paths, datasource descriptions, or retrieval mechanics in the answer text.
21978
- ` + `- ${ANSWER_DELIVERABLE_RULE}
21979
- ` + `- ${ANSWER_CITATION_RULE}
21980
- ` + `- ${ANSWER_IMAGE_EMBED_RULE}
21981
- ` + `- Do not report per-source negative findings (e.g. "no information found in Slack").
21982
- ` + `- When evidence conflicts, treat the freshest (most recent) information as the correct source of truth.
21983
- ` + `- If information is incomplete or uncertain, acknowledge it briefly without lengthy explanations. If there are partial clues or leads, mention them concisely.
22093
+ Formatting and content rules for the answer:
22094
+ - Unless the user explicitly requests a different format or length, provide the core answer to the user's question in at most 5 bullet points. If additional explanation is necessary, append it after the bullet points.
22095
+ - Unless the user explicitly requests otherwise, answer the question directly. Do not include specific file paths, datasource descriptions, or retrieval mechanics in the answer text.
22096
+ - ${ANSWER_DELIVERABLE_RULE}
22097
+ - ${ANSWER_CITATION_RULE}
22098
+ - ${ANSWER_IMAGE_EMBED_RULE}
22099
+ - Do not report per-source negative findings (e.g. "no information found in Slack").
22100
+ - When evidence conflicts, treat the freshest (most recent) information as the correct source of truth.
22101
+ - If information is incomplete or uncertain, acknowledge it briefly without lengthy explanations. If there are partial clues or leads, mention them concisely.
21984
22102
 
21985
- ` + `${this.discoveryHint((tools) => `When exploring local files and folders, actively use ${tools} rather than exploratory bash commands. `)}If more search is needed, first write a brief 1–2 line progress update stating the best current hypothesis and what you are checking next, then call retrieval tools. ` + `Never repeat a generic status message. Do not use broad grep/find or recursive filesystem scans: only inspect a path or narrow neighborhood surfaced by retrieval, and only when evidence clearly points there. ` + `Avoid spinning repeated near-identical queries against the same datasource; once additional attempts stop surfacing new evidence, conclude from the evidence available. ` + `When finished, reply with the final answer and no tool call: that last reply is what the user receives, so keep progress notes out of it.`;
22103
+ ${this.discoveryHint((tools) => `When exploring local files and folders, actively use ${tools} rather than exploratory bash commands. `)}If more search is needed, first write a brief 1–2 line progress update stating the best current hypothesis and what you are checking next, then call retrieval tools. ` + `Never repeat a generic status message. Do not use broad grep/find or recursive filesystem scans: only inspect a path or narrow neighborhood surfaced by retrieval, and only when evidence clearly points there. Avoid spinning repeated near-identical queries against the same datasource; once additional attempts stop surfacing new evidence, conclude from the evidence available. When finished, reply with the final answer and no tool call: that last reply is what the user receives, so keep progress notes out of it.`;
21986
22104
  }
21987
22105
  async refresh(force = false, opts) {
21988
22106
  const signal = opts?.signal;
@@ -22218,7 +22336,7 @@ ${initialRetrievalContext ?? "Pending; continue only with a brief progress state
22218
22336
  });
22219
22337
  }
22220
22338
  const state = this.refreshState.inFlight || persistedRunning && ownerAlive ? "indexing" : interrupted ? "failed" : persistedProgress?.state === "success" || persistedProgress?.state === "failed" ? persistedProgress.state : this.refreshState.lastOutcome === "never" ? "idle" : this.refreshState.lastOutcome;
22221
- const parsedMirrorReady = this.refreshState.lastOutcome === "success" || persistedProgress?.state === "success" || existsSync22(refreshReadinessPath(this.workspaceProjectRoot));
22339
+ const parsedMirrorReady = this.refreshState.lastOutcome === "success" || persistedProgress?.state === "success" || existsSync23(refreshReadinessPath(this.workspaceProjectRoot));
22222
22340
  const effectiveProgress = this.refreshState.inFlight || persistedRunning ? persistedProgress : undefined;
22223
22341
  return {
22224
22342
  state,
@@ -22678,7 +22796,7 @@ function buildSteerMessage(text) {
22678
22796
 
22679
22797
  ${text}
22680
22798
 
22681
- ` + `Treat it as direction for the search in progress, not as a new question: adjust which sources, queries, or claims you pursue, then continue. ` + `When finished, reply with the final answer to the original question, updated for this correction, and no tool call.`;
22799
+ Treat it as direction for the search in progress, not as a new question: adjust which sources, queries, or claims you pursue, then continue. When finished, reply with the final answer to the original question, updated for this correction, and no tool call.`;
22682
22800
  }
22683
22801
  function frameSteers(messages, steerTexts) {
22684
22802
  if (steerTexts.size === 0)
@@ -22698,12 +22816,12 @@ function formatSteerContext(steers) {
22698
22816
  return `While the search ran, the user corrected it:
22699
22817
  ${steers.map((steer) => `- ${steer}`).join(`
22700
22818
  `)}
22701
- ` + `The first answer predates these corrections; follow them over it.
22819
+ The first answer predates these corrections; follow them over it.
22702
22820
 
22703
22821
  `;
22704
22822
  }
22705
22823
  function buildSteerContinuationPrompt(steers) {
22706
- return `${formatSteerContext(steers)}Apply the latest correction: search or verify further if it needs that, ` + `then reply with the complete final answer to the original question and no tool call.`;
22824
+ return `${formatSteerContext(steers)}Apply the latest correction: search or verify further if it needs that, then reply with the complete final answer to the original question and no tool call.`;
22707
22825
  }
22708
22826
  function formatFirstAnswerContext(fastAnswer, delivered) {
22709
22827
  if (fastAnswer === undefined) {
@@ -22826,11 +22944,20 @@ function fsearchRefreshDiagnostics(fsearch) {
22826
22944
  function minSyncRefreshDiagnostics(minsync) {
22827
22945
  if (!minsync)
22828
22946
  return [];
22947
+ const diagnostics = [];
22829
22948
  if (minsync.diagnostic)
22830
- return [toMinSyncDiagnostic(minsync.diagnostic, minsync.ok)];
22831
- if (!minsync.ok && minsync.reason)
22832
- return [toMinSyncReasonDiagnostic(minsync.reason)];
22833
- return [];
22949
+ diagnostics.push(toMinSyncDiagnostic(minsync.diagnostic, minsync.ok));
22950
+ else if (!minsync.ok && minsync.reason)
22951
+ diagnostics.push(toMinSyncReasonDiagnostic(minsync.reason));
22952
+ if (minsync.lexicalFallback) {
22953
+ diagnostics.push({
22954
+ code: "lexical-tokenizer-unavailable",
22955
+ severity: "warning",
22956
+ message: `The "${minsync.lexicalFallback.requested}" BM25 tokenizer needs the Kiwi native library and model, which were not found, so MinSync tokenizes on whitespace and a Korean word with a particle (인증서를) does not match its stem (인증서). Install Kiwi (set KIWI_LIBRARY_PATH and KIWI_MODEL_PATH, or install it under ~/.local/kiwi), then refresh again.`,
22957
+ source: "minsync"
22958
+ });
22959
+ }
22960
+ return diagnostics;
22834
22961
  }
22835
22962
  function toMinSyncDiagnostic(diag, ok) {
22836
22963
  const code = diag.code === "embedder-unavailable" ? "embedder-unavailable" : diag.code === "embedding-identity-mismatch" ? "embedding-identity-mismatch" : diag.code === "minsync-lock-held" ? "minsync-lock-held" : "minsync-sync-failed";
@@ -23166,7 +23293,7 @@ var init_connector = () => {};
23166
23293
 
23167
23294
  // src/datasource/sidecar/config.ts
23168
23295
  import { readFileSync as readFileSync19 } from "node:fs";
23169
- import { homedir as homedir3 } from "node:os";
23296
+ import { homedir as homedir4 } from "node:os";
23170
23297
  import { dirname as dirname18, isAbsolute as isAbsolute8, join as join32, resolve as resolve14, sep as sep7 } from "node:path";
23171
23298
  import { parse as parseToml2 } from "smol-toml";
23172
23299
  function resolveSidecarOptions(input) {
@@ -23206,9 +23333,9 @@ function archivePathFromCrawlerConfig(input) {
23206
23333
  }
23207
23334
  function expandHome(path) {
23208
23335
  if (path === "~")
23209
- return homedir3();
23336
+ return homedir4();
23210
23337
  const prefixed = path.startsWith("~/") || sep7 === "\\" && path.startsWith("~\\");
23211
- return prefixed ? join32(homedir3(), path.slice(2)) : path;
23338
+ return prefixed ? join32(homedir4(), path.slice(2)) : path;
23212
23339
  }
23213
23340
  var init_config2 = __esm(() => {
23214
23341
  init_connector();
@@ -23299,7 +23426,7 @@ var init_descriptors = __esm(() => {
23299
23426
 
23300
23427
  // src/datasource/skills/clawgallery/client.ts
23301
23428
  import { spawn as spawn10 } from "node:child_process";
23302
- import { existsSync as existsSync23 } from "node:fs";
23429
+ import { existsSync as existsSync24 } from "node:fs";
23303
23430
 
23304
23431
  class ClawGalleryClient {
23305
23432
  options;
@@ -23307,7 +23434,7 @@ class ClawGalleryClient {
23307
23434
  this.options = options;
23308
23435
  }
23309
23436
  async bootstrap(signal) {
23310
- if (this.options.path !== undefined && !existsSync23(this.options.path)) {
23437
+ if (this.options.path !== undefined && !existsSync24(this.options.path)) {
23311
23438
  return {
23312
23439
  ok: false,
23313
23440
  reason: "nonzero-exit",
@@ -24225,7 +24352,7 @@ var init_rclone_connector = __esm(() => {
24225
24352
  });
24226
24353
 
24227
24354
  // src/datasource/chunk-store.ts
24228
- import { existsSync as existsSync24, mkdirSync as mkdirSync18, readFileSync as readFileSync21, writeFileSync as writeFileSync17 } from "node:fs";
24355
+ import { existsSync as existsSync25, mkdirSync as mkdirSync18, readFileSync as readFileSync21, writeFileSync as writeFileSync17 } from "node:fs";
24229
24356
  import { dirname as dirname20, join as join34 } from "node:path";
24230
24357
  function datasourceChunkStorePath(workspaceRoot, skillName, instanceId) {
24231
24358
  return join34(workspaceRoot, ".autorag", "datasources", sanitizeIdSegment(skillName), sanitizeIdSegment(instanceId), "chunks.json");
@@ -24265,7 +24392,7 @@ class DatasourceChunkStore {
24265
24392
  if (this.storePath === undefined)
24266
24393
  return false;
24267
24394
  try {
24268
- if (!existsSync24(this.storePath))
24395
+ if (!existsSync25(this.storePath))
24269
24396
  return false;
24270
24397
  const parsed = JSON.parse(readFileSync21(this.storePath, "utf8"));
24271
24398
  if (parsed.version !== STORE_VERSION || !Array.isArray(parsed.chunks))
@@ -25792,7 +25919,7 @@ var init_github = __esm(() => {
25792
25919
 
25793
25920
  // src/datasource/skills/github-gist/connector.ts
25794
25921
  import { execFile as execFile2 } from "node:child_process";
25795
- import { existsSync as existsSync25, mkdirSync as mkdirSync20, readFileSync as readFileSync23, writeFileSync as writeFileSync19 } from "node:fs";
25922
+ import { existsSync as existsSync26, mkdirSync as mkdirSync20, readFileSync as readFileSync23, writeFileSync as writeFileSync19 } from "node:fs";
25796
25923
  import { dirname as dirname22 } from "node:path";
25797
25924
  async function defaultGhTokenRunner() {
25798
25925
  return new Promise((resolve) => {
@@ -25912,7 +26039,7 @@ class GitHubGistConnector {
25912
26039
  }
25913
26040
  loadState() {
25914
26041
  const statePath = this.options.statePath;
25915
- if (statePath === undefined || !existsSync25(statePath))
26042
+ if (statePath === undefined || !existsSync26(statePath))
25916
26043
  return { version: STATE_VERSION, gists: {} };
25917
26044
  try {
25918
26045
  const parsed = JSON.parse(readFileSync23(statePath, "utf8"));
@@ -25975,7 +26102,7 @@ var init_connector3 = () => {};
25975
26102
 
25976
26103
  // src/datasource/skills/github-gist/semantic.ts
25977
26104
  import { createHash as createHash13 } from "node:crypto";
25978
- import { existsSync as existsSync26, mkdirSync as mkdirSync21, readFileSync as readFileSync24, writeFileSync as writeFileSync20 } from "node:fs";
26105
+ import { existsSync as existsSync27, mkdirSync as mkdirSync21, readFileSync as readFileSync24, writeFileSync as writeFileSync20 } from "node:fs";
25979
26106
  import { dirname as dirname23 } from "node:path";
25980
26107
  function contentHash(chunk) {
25981
26108
  return createHash13("sha256").update(`${chunk.title ?? ""}
@@ -26066,7 +26193,7 @@ ${chunk.content}`));
26066
26193
  if (this.loaded)
26067
26194
  return;
26068
26195
  this.loaded = true;
26069
- if (this.statePath === undefined || !existsSync26(this.statePath))
26196
+ if (this.statePath === undefined || !existsSync27(this.statePath))
26070
26197
  return;
26071
26198
  try {
26072
26199
  const parsed = JSON.parse(readFileSync24(this.statePath, "utf8"));
@@ -26929,7 +27056,7 @@ var init_types5 = __esm(() => {
26929
27056
 
26930
27057
  // src/datasource/skills/lazykatok/client.ts
26931
27058
  import { spawn as spawn14 } from "node:child_process";
26932
- import { existsSync as existsSync27 } from "node:fs";
27059
+ import { existsSync as existsSync28 } from "node:fs";
26933
27060
  import { delimiter as delimiter4, join as join36 } from "node:path";
26934
27061
 
26935
27062
  class LazykatokClient {
@@ -27119,7 +27246,7 @@ function lookupInPath2(executable, env) {
27119
27246
  if (dir.length === 0)
27120
27247
  continue;
27121
27248
  const candidate = join36(dir, executable);
27122
- if (existsSync27(candidate))
27249
+ if (existsSync28(candidate))
27123
27250
  return candidate;
27124
27251
  }
27125
27252
  return;
@@ -30872,7 +30999,7 @@ var init_wacrawl = __esm(() => {
30872
30999
  });
30873
31000
 
30874
31001
  // src/datasource/skills/factory.ts
30875
- import { homedir as homedir4 } from "node:os";
31002
+ import { homedir as homedir5 } from "node:os";
30876
31003
  import { join as join39 } from "node:path";
30877
31004
  function chatCrawlerArgs(descriptor, defaultCrawlerDb, config, workspaceRoot, registrationName) {
30878
31005
  const sidecar = resolveSidecarOptions({
@@ -30976,9 +31103,9 @@ var init_factory = __esm(() => {
30976
31103
  init_telecrawl();
30977
31104
  init_wacrawl();
30978
31105
  BUILDERS = {
30979
- telegram: (config, workspaceRoot, registrationName) => new TelecrawlSkill(chatCrawlerArgs(CRAWLER_DESCRIPTORS.telegram, join39(homedir4(), ".telecrawl", "telecrawl.db"), config, workspaceRoot, registrationName)),
30980
- whatsapp: (config, workspaceRoot, registrationName) => new WacrawlSkill(chatCrawlerArgs(CRAWLER_DESCRIPTORS.whatsapp, join39(homedir4(), ".wacrawl", "wacrawl.db"), config, workspaceRoot, registrationName)),
30981
- slack: (config, workspaceRoot, registrationName) => new SlackSkill(chatCrawlerArgs(CRAWLER_DESCRIPTORS.slack, join39(homedir4(), ".slacrawl", "slacrawl.db"), config, workspaceRoot, registrationName)),
31106
+ telegram: (config, workspaceRoot, registrationName) => new TelecrawlSkill(chatCrawlerArgs(CRAWLER_DESCRIPTORS.telegram, join39(homedir5(), ".telecrawl", "telecrawl.db"), config, workspaceRoot, registrationName)),
31107
+ whatsapp: (config, workspaceRoot, registrationName) => new WacrawlSkill(chatCrawlerArgs(CRAWLER_DESCRIPTORS.whatsapp, join39(homedir5(), ".wacrawl", "wacrawl.db"), config, workspaceRoot, registrationName)),
31108
+ slack: (config, workspaceRoot, registrationName) => new SlackSkill(chatCrawlerArgs(CRAWLER_DESCRIPTORS.slack, join39(homedir5(), ".slacrawl", "slacrawl.db"), config, workspaceRoot, registrationName)),
30982
31109
  discord: (config, workspaceRoot, registrationName, embeddingRuntime) => {
30983
31110
  const connector = config.connector ?? {};
30984
31111
  const clientOptions = {
@@ -31036,7 +31163,7 @@ var init_factory = __esm(() => {
31036
31163
  }),
31037
31164
  kakao: (config, workspaceRoot, registrationName) => {
31038
31165
  const connector = config.connector ?? {};
31039
- const dataDir = typeof connector.workspacePath === "string" && connector.workspacePath.length > 0 ? connector.workspacePath : join39(homedir4(), "Library", "Application Support", "katok");
31166
+ const dataDir = typeof connector.workspacePath === "string" && connector.workspacePath.length > 0 ? connector.workspacePath : join39(homedir5(), "Library", "Application Support", "katok");
31040
31167
  const sidecar = resolveSidecarOptions({
31041
31168
  descriptor: CRAWLER_DESCRIPTORS.kakao,
31042
31169
  connector: config.connector,
@@ -31060,11 +31187,16 @@ var init_factory = __esm(() => {
31060
31187
  skillName: registrationName,
31061
31188
  connectorOptions: config.connector
31062
31189
  }),
31063
- "github-gist": (config, workspaceRoot, registrationName) => new GitHubGistSkill({
31064
- ...common(config, workspaceRoot),
31065
- skillName: registrationName,
31066
- connectorOptions: config.connector
31067
- }),
31190
+ "github-gist": (config, workspaceRoot, registrationName) => {
31191
+ const { semantic, ...connectorOptions } = config.connector ?? {};
31192
+ const semanticOff = semantic === false || typeof semantic === "object" && semantic !== null && semantic.enabled === false;
31193
+ return new GitHubGistSkill({
31194
+ ...common(config, workspaceRoot),
31195
+ skillName: registrationName,
31196
+ connectorOptions,
31197
+ ...semanticOff ? { semantic: { enabled: false } } : {}
31198
+ });
31199
+ },
31068
31200
  "cloud-drive": (config, workspaceRoot, registrationName) => new CloudDriveSkill({
31069
31201
  ...common(config, workspaceRoot),
31070
31202
  skillName: registrationName,
@@ -31110,7 +31242,7 @@ var init_factory = __esm(() => {
31110
31242
 
31111
31243
  // src/cli/config.ts
31112
31244
  import { randomUUID as randomUUID8 } from "node:crypto";
31113
- import { existsSync as existsSync28, mkdirSync as mkdirSync25, readFileSync as readFileSync25, renameSync as renameSync10, unlinkSync as unlinkSync5, writeFileSync as writeFileSync22 } from "node:fs";
31245
+ import { existsSync as existsSync29, mkdirSync as mkdirSync25, readFileSync as readFileSync25, renameSync as renameSync10, unlinkSync as unlinkSync5, writeFileSync as writeFileSync22 } from "node:fs";
31114
31246
  import { basename as basename14, dirname as dirname26, isAbsolute as isAbsolute10, join as join40, resolve as resolve16 } from "node:path";
31115
31247
  import { findEnvKeys, getEnvApiKey } from "@earendil-works/pi-ai/compat";
31116
31248
  import { getAgentDir as getAgentDir4, ModelRuntime as ModelRuntime2, SettingsManager as SettingsManager2 } from "@earendil-works/pi-coding-agent";
@@ -31135,7 +31267,7 @@ function resolveConfigPath(input) {
31135
31267
  function readConfigFile(configPath, explicit) {
31136
31268
  let exists;
31137
31269
  try {
31138
- exists = existsSync28(configPath);
31270
+ exists = existsSync29(configPath);
31139
31271
  } catch {
31140
31272
  exists = false;
31141
31273
  }
@@ -31195,7 +31327,7 @@ function replaceFileAtomically(path, contents, assertCommitAllowed) {
31195
31327
  }
31196
31328
  }
31197
31329
  function migrateLegacyConfig(configPath, legacyPath) {
31198
- if (existsSync28(configPath) || !existsSync28(legacyPath))
31330
+ if (existsSync29(configPath) || !existsSync29(legacyPath))
31199
31331
  return;
31200
31332
  const legacy = readConfigFile(legacyPath, true);
31201
31333
  const legacyBytes = readFileSync25(legacyPath);
@@ -32466,7 +32598,7 @@ function writeDefaultConfig(path, partial, opts = {}) {
32466
32598
  `;
32467
32599
  const lock = acquireConfigWriteLock(path);
32468
32600
  try {
32469
- const exists = existsSync28(path);
32601
+ const exists = existsSync29(path);
32470
32602
  if (!opts.force && exists) {
32471
32603
  throw new ConfigError(`Config file already exists: ${path}`);
32472
32604
  }