@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/index.js CHANGED
@@ -5142,7 +5142,20 @@ function configuredVectorDimension(workspacePath) {
5142
5142
  const dimension = options.dimension;
5143
5143
  return typeof dimension === "number" ? dimension : undefined;
5144
5144
  }
5145
- function rewriteEmbedderConfig(workspacePath, embedder, chunkerConfig = {}) {
5145
+ function configuredLexicalLanguage(workspacePath) {
5146
+ let raw;
5147
+ try {
5148
+ raw = readFileSync8(minSyncConfigPath(workspacePath), "utf8");
5149
+ } catch {
5150
+ return;
5151
+ }
5152
+ const lexical = parse(raw).lexical;
5153
+ if (typeof lexical !== "object" || lexical === null || Array.isArray(lexical))
5154
+ return "simple";
5155
+ const language = lexical.language;
5156
+ return typeof language === "string" ? language : "simple";
5157
+ }
5158
+ function rewriteEmbedderConfig(workspacePath, embedder, managed = {}) {
5146
5159
  const configPath = minSyncConfigPath(workspacePath);
5147
5160
  let raw;
5148
5161
  try {
@@ -5185,8 +5198,13 @@ function rewriteEmbedderConfig(workspacePath, embedder, chunkerConfig = {}) {
5185
5198
  }
5186
5199
  if (embedder.dimension !== undefined)
5187
5200
  options.dimension = embedder.dimension;
5188
- if (chunkerConfig.maxChunkSize !== undefined)
5189
- chunkerOptions.max_chunk_size = chunkerConfig.maxChunkSize;
5201
+ if (managed.maxChunkSize !== undefined)
5202
+ chunkerOptions.max_chunk_size = managed.maxChunkSize;
5203
+ if (managed.lexicalLanguage !== undefined) {
5204
+ const lexical = typeof parsed.lexical === "object" && parsed.lexical !== null && !Array.isArray(parsed.lexical) ? parsed.lexical : {};
5205
+ parsed.lexical = lexical;
5206
+ lexical.language = managed.lexicalLanguage;
5207
+ }
5190
5208
  writeFileSync6(configPath, stringify(parsed));
5191
5209
  return true;
5192
5210
  }
@@ -5198,6 +5216,66 @@ var init_embedder_config = __esm(() => {
5198
5216
  };
5199
5217
  });
5200
5218
 
5219
+ // src/minsync/kiwi.ts
5220
+ import { existsSync as existsSync10 } from "node:fs";
5221
+ import { homedir as homedir2 } from "node:os";
5222
+ import { posix as posix3, win32 as win323 } from "node:path";
5223
+ function kiwiAvailable(environment = defaultEnvironment()) {
5224
+ const { env, exists } = environment;
5225
+ const library = env.KIWI_LIBRARY_PATH;
5226
+ const model = env.KIWI_MODEL_PATH;
5227
+ const libraryFound = library !== undefined && library !== "" ? exists(library) : libraryCandidates(environment).some(exists);
5228
+ const modelFound = model !== undefined && model !== "" ? exists(model) : modelCandidates(environment).some(exists);
5229
+ return libraryFound && modelFound;
5230
+ }
5231
+ function defaultEnvironment() {
5232
+ let home;
5233
+ try {
5234
+ home = homedir2();
5235
+ } catch {
5236
+ home = undefined;
5237
+ }
5238
+ return { env: process.env, platform: process.platform, home, exists: existsSync10 };
5239
+ }
5240
+ function userRoots({ env, platform, home }) {
5241
+ if (platform === "win32") {
5242
+ const roots = [];
5243
+ if (env.LOCALAPPDATA)
5244
+ roots.push(win323.join(env.LOCALAPPDATA, "kiwi"));
5245
+ const profile = env.USERPROFILE ?? home;
5246
+ if (profile)
5247
+ roots.push(win323.join(profile, "AppData", "Local", "kiwi"));
5248
+ roots.push("C:\\kiwi", "C:\\Program Files\\Kiwi");
5249
+ return roots;
5250
+ }
5251
+ return home ? [posix3.join(home, ".local", "kiwi")] : [];
5252
+ }
5253
+ function libraryCandidates(environment) {
5254
+ const { platform } = environment;
5255
+ if (platform === "win32")
5256
+ return userRoots(environment).map((root) => win323.join(root, "lib", "kiwi.dll"));
5257
+ const file = platform === "darwin" ? "libkiwi.dylib" : "libkiwi.so";
5258
+ const system = platform === "darwin" ? ["/usr/local/lib", "/opt/homebrew/lib"] : ["/usr/local/lib", "/usr/lib"];
5259
+ return [
5260
+ ...userRoots(environment).map((root) => posix3.join(root, "lib", file)),
5261
+ ...system.map((dir) => posix3.join(dir, file))
5262
+ ];
5263
+ }
5264
+ function modelCandidates(environment) {
5265
+ const { platform } = environment;
5266
+ if (platform === "win32")
5267
+ return userRoots(environment).map((root) => win323.join(root, "models", "cong", "base"));
5268
+ 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"];
5269
+ return [
5270
+ ...userRoots(environment).map((root) => posix3.join(root, "models", "cong", "base")),
5271
+ ...system.map((dir) => posix3.join(dir, "cong", "base"))
5272
+ ];
5273
+ }
5274
+ var init_kiwi = () => {};
5275
+
5276
+ // src/minsync/lexical-language.ts
5277
+ var MINSYNC_LEXICAL_LANGUAGE = "multilingual";
5278
+
5201
5279
  // src/minsync/local-embedder.ts
5202
5280
  import { spawn as spawn7 } from "node:child_process";
5203
5281
  import { request } from "node:http";
@@ -5386,7 +5464,7 @@ var init_process = __esm(() => {
5386
5464
  });
5387
5465
 
5388
5466
  // src/minsync/client.ts
5389
- import { existsSync as existsSync10, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "node:fs";
5467
+ import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "node:fs";
5390
5468
  import { join as join14 } from "node:path";
5391
5469
 
5392
5470
  class MinSyncClient {
@@ -5481,7 +5559,7 @@ class MinSyncClient {
5481
5559
  return previous === undefined || JSON.stringify(previous) !== JSON.stringify(identity);
5482
5560
  }
5483
5561
  async sync(force = false, signal) {
5484
- if (!existsSync10(this.binaryPath))
5562
+ if (!existsSync11(this.binaryPath))
5485
5563
  throw minSyncBinaryMissingError();
5486
5564
  let effective = { config: {} };
5487
5565
  try {
@@ -5519,14 +5597,16 @@ class MinSyncClient {
5519
5597
  }
5520
5598
  }
5521
5599
  const spawnOptions = signal === undefined ? {} : { signal };
5522
- const initialized = existsSync10(minSyncConfigPath(this.workspacePath));
5600
+ const lexical = this.resolveLexicalLanguage();
5601
+ const initialized = existsSync11(minSyncConfigPath(this.workspacePath));
5523
5602
  if (!initialized) {
5524
5603
  const initArgs = ["init", "--format", "json"];
5525
5604
  if (this.embedder?.id) {
5526
5605
  initArgs.push("--embedder", this.embedder.id);
5527
5606
  }
5607
+ initArgs.push("--language", lexical.language);
5528
5608
  const init = await this.spawn(initArgs, spawnOptions);
5529
- if (!init.ok || !existsSync10(minSyncConfigPath(this.workspacePath))) {
5609
+ if (!init.ok || !existsSync11(minSyncConfigPath(this.workspacePath))) {
5530
5610
  return {
5531
5611
  ok: false,
5532
5612
  synced: 0,
@@ -5538,20 +5618,29 @@ class MinSyncClient {
5538
5618
  const chunkSizeChanged = this.maxChunkSize !== undefined && configuredMaxChunkSize(this.workspacePath) !== this.maxChunkSize;
5539
5619
  const dimensionChanged = embedder.dimension !== undefined && configuredVectorDimension(this.workspacePath) !== embedder.dimension;
5540
5620
  const configPath = minSyncConfigPath(this.workspacePath);
5541
- const shouldRewriteConfig = this.embedder !== undefined || this.maxChunkSize !== undefined || effective.identity !== undefined;
5542
- const originalConfig = shouldRewriteConfig ? readConfigSnapshot(configPath) : undefined;
5543
- const configRewritten = shouldRewriteConfig && rewriteEmbedderConfig(this.workspacePath, embedder, { maxChunkSize: this.maxChunkSize });
5621
+ const originalConfig = readConfigSnapshot(configPath);
5622
+ const configRewritten = rewriteEmbedderConfig(this.workspacePath, embedder, {
5623
+ maxChunkSize: this.maxChunkSize,
5624
+ lexicalLanguage: lexical.language
5625
+ });
5544
5626
  const restoreConfig = () => {
5545
5627
  if (configRewritten && originalConfig !== undefined)
5546
5628
  writeFileSync7(configPath, originalConfig);
5547
5629
  };
5548
5630
  try {
5549
- return await this.checkAndSync(force || chunkSizeChanged || dimensionChanged, signal, effective, restoreConfig);
5631
+ const result = await this.checkAndSync(force || chunkSizeChanged || dimensionChanged, signal, effective, restoreConfig);
5632
+ return result.ok && lexical.fallback !== undefined ? { ...result, lexicalFallback: lexical.fallback } : result;
5550
5633
  } catch (error) {
5551
5634
  restoreConfig();
5552
5635
  throw error;
5553
5636
  }
5554
5637
  }
5638
+ resolveLexicalLanguage() {
5639
+ const requested = MINSYNC_LEXICAL_LANGUAGE;
5640
+ if (kiwiAvailable() || configuredLexicalLanguage(this.workspacePath) === requested)
5641
+ return { language: requested };
5642
+ return { language: "simple", fallback: { requested, used: "simple" } };
5643
+ }
5555
5644
  lockHeldResult(stderr) {
5556
5645
  return {
5557
5646
  ok: false,
@@ -5604,7 +5693,7 @@ class MinSyncClient {
5604
5693
  }
5605
5694
  const identityChanged = effective.identity !== undefined && this.identityMismatch(effective.identity);
5606
5695
  const fullReindex = forceFull || identityChanged;
5607
- const syncArgs = existsSync10(cursorPath) && !fullReindex ? ["sync", "--format", "json"] : ["sync", "--full", "--format", "json"];
5696
+ const syncArgs = existsSync11(cursorPath) && !fullReindex ? ["sync", "--format", "json"] : ["sync", "--full", "--format", "json"];
5608
5697
  const result = await this.spawn(syncArgs, spawnOptions);
5609
5698
  if (!result.ok && result.code === MINSYNC_LOCK_HELD_EXIT_CODE) {
5610
5699
  restoreConfig();
@@ -5625,7 +5714,7 @@ class MinSyncClient {
5625
5714
  }
5626
5715
  };
5627
5716
  }
5628
- if (!existsSync10(cursorPath)) {
5717
+ if (!existsSync11(cursorPath)) {
5629
5718
  restoreConfig();
5630
5719
  return { ok: false, synced: 0, workspacePath: this.workspacePath, reason: "not-ready: missing cursor" };
5631
5720
  }
@@ -5646,7 +5735,7 @@ class MinSyncClient {
5646
5735
  };
5647
5736
  }
5648
5737
  async query(text, topK, mode = "vector", signal) {
5649
- if (!existsSync10(this.binaryPath))
5738
+ if (!existsSync11(this.binaryPath))
5650
5739
  throw minSyncBinaryMissingError();
5651
5740
  const result = await this.spawn(["query", "--format", "json", "--mode", mode, "-k", String(topK), text], {
5652
5741
  ...signal === undefined ? {} : { signal }
@@ -5740,6 +5829,7 @@ var MINSYNC_OLLAMA_MIGRATION_MESSAGE = "This workspace uses the legacy 768-dimen
5740
5829
  var init_client4 = __esm(() => {
5741
5830
  init_embedder_config();
5742
5831
  init_errors();
5832
+ init_kiwi();
5743
5833
  init_local_embedder();
5744
5834
  init_process();
5745
5835
  API_KEY_ENV_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
@@ -5762,14 +5852,14 @@ var init_client4 = __esm(() => {
5762
5852
 
5763
5853
  // src/minsync/installer.ts
5764
5854
  import { createHash as createHash9 } from "node:crypto";
5765
- import { copyFileSync, createWriteStream as createWriteStream2, existsSync as existsSync11, mkdirSync as mkdirSync8, renameSync as renameSync4, rmSync as rmSync5 } from "node:fs";
5855
+ import { copyFileSync, createWriteStream as createWriteStream2, existsSync as existsSync12, mkdirSync as mkdirSync8, renameSync as renameSync4, rmSync as rmSync5 } from "node:fs";
5766
5856
  import { chmod as chmod2, mkdtemp } from "node:fs/promises";
5767
5857
  import { get } from "node:https";
5768
5858
  import { basename as basename7, delimiter as delimiter2, dirname as dirname7, join as join15 } from "node:path";
5769
5859
  import { pipeline } from "node:stream/promises";
5770
5860
  async function ensureMinSyncBinary(options) {
5771
5861
  const binaryPath = join15(options.root, ".autorag", "bin", executableName(options.platform ?? process.platform));
5772
- if (existsSync11(binaryPath))
5862
+ if (existsSync12(binaryPath))
5773
5863
  return { binaryPath, version: "cached" };
5774
5864
  mkdirSync8(dirname7(binaryPath), { recursive: true });
5775
5865
  const cargoInstaller = options.cargoInstaller ?? ((destination) => installMinSyncFromCargoIfAvailable(options, destination));
@@ -5817,7 +5907,7 @@ async function installMinSyncFromCargo(options, destination, cargo) {
5817
5907
  throw new MinSyncReleaseError(result.stderr || `Could not install MinSync ${MINSYNC_VERSION} from crates.io`);
5818
5908
  }
5819
5909
  const installedBinary = join15(cargoRoot, "bin", executableName(options.platform ?? process.platform));
5820
- if (!existsSync11(installedBinary)) {
5910
+ if (!existsSync12(installedBinary)) {
5821
5911
  throw new MinSyncReleaseError(`Cargo did not produce the MinSync ${MINSYNC_VERSION} binary`);
5822
5912
  }
5823
5913
  copyFileSync(installedBinary, destination);
@@ -5949,7 +6039,7 @@ function lookupCargo(env, platform) {
5949
6039
  if (dir.length === 0)
5950
6040
  continue;
5951
6041
  const candidate = join15(dir, execName);
5952
- if (existsSync11(candidate))
6042
+ if (existsSync12(candidate))
5953
6043
  return candidate;
5954
6044
  }
5955
6045
  return;
@@ -5980,7 +6070,7 @@ function isGitHubAsset(value) {
5980
6070
  function isRecord5(value) {
5981
6071
  return typeof value === "object" && value !== null;
5982
6072
  }
5983
- 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;
6073
+ 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;
5984
6074
  var init_installer2 = __esm(() => {
5985
6075
  init_process();
5986
6076
  SHA256_HEX_PATTERN = /^[a-f0-9]{64}$/;
@@ -6008,7 +6098,7 @@ var init_paths2 = __esm(() => {
6008
6098
  import { randomUUID as randomUUID4 } from "node:crypto";
6009
6099
  import {
6010
6100
  copyFileSync as copyFileSync2,
6011
- existsSync as existsSync12,
6101
+ existsSync as existsSync13,
6012
6102
  lstatSync as lstatSync2,
6013
6103
  mkdirSync as mkdirSync9,
6014
6104
  readdirSync as readdirSync2,
@@ -6023,8 +6113,8 @@ function syncMinSyncWorkspace(root, options = {}) {
6023
6113
  const filesRoot = join17(workspacePath, "files");
6024
6114
  const index = loadMirrorIndex(root);
6025
6115
  const candidates = Object.values(index.entries).sort((a, b) => a.virtualPath.localeCompare(b.virtualPath));
6026
- const excluded = candidates.filter((entry) => normalizeVirtualPath(entry.virtualPath) !== entry.virtualPath || !existsSync12(entry.outputPath)).map((entry) => entry.virtualPath);
6027
- const entries = candidates.filter((entry) => normalizeVirtualPath(entry.virtualPath) === entry.virtualPath && existsSync12(entry.outputPath)).map((entry) => {
6116
+ const excluded = candidates.filter((entry) => normalizeVirtualPath(entry.virtualPath) !== entry.virtualPath || !existsSync13(entry.outputPath)).map((entry) => entry.virtualPath);
6117
+ const entries = candidates.filter((entry) => normalizeVirtualPath(entry.virtualPath) === entry.virtualPath && existsSync13(entry.outputPath)).map((entry) => {
6028
6118
  const minSyncPath = minSyncDocumentPath(workspacePath, entry.virtualPath);
6029
6119
  return {
6030
6120
  virtualPath: entry.virtualPath,
@@ -6161,7 +6251,7 @@ var init_workspace = __esm(() => {
6161
6251
  });
6162
6252
 
6163
6253
  // src/minsync/method.ts
6164
- import { accessSync, constants, existsSync as existsSync13, realpathSync as realpathSync4 } from "node:fs";
6254
+ import { accessSync, constants, existsSync as existsSync14, realpathSync as realpathSync4 } from "node:fs";
6165
6255
  import { basename as basename9, delimiter as delimiter3, join as join18, normalize as normalize2 } from "node:path";
6166
6256
  function lookupInPath(env) {
6167
6257
  const pathEnv = env.PATH;
@@ -6257,19 +6347,19 @@ class MinSyncVectorMethod {
6257
6347
  }
6258
6348
  isBinaryMissing() {
6259
6349
  if (this.binaryPath !== undefined)
6260
- return !existsSync13(this.binaryPath);
6350
+ return !existsSync14(this.binaryPath);
6261
6351
  if (lookupInPath(process.env) !== undefined)
6262
6352
  return false;
6263
6353
  const cachedBinary = join18(this.root, ".autorag", "bin", executableName(process.platform));
6264
- if (existsSync13(cachedBinary))
6354
+ if (existsSync14(cachedBinary))
6265
6355
  return false;
6266
6356
  return true;
6267
6357
  }
6268
6358
  isExplicitBinaryMissing() {
6269
- return this.binaryPath !== undefined && !existsSync13(this.binaryPath);
6359
+ return this.binaryPath !== undefined && !existsSync14(this.binaryPath);
6270
6360
  }
6271
6361
  isReady() {
6272
- return existsSync13(join18(this.workspacePath, ".minsync", "cursor.json"));
6362
+ return existsSync14(join18(this.workspacePath, ".minsync", "cursor.json"));
6273
6363
  }
6274
6364
  async retrieve(query, options) {
6275
6365
  if ((workspaceSyncInFlight.get(this.workspacePath) ?? 0) > 0) {
@@ -6322,7 +6412,7 @@ class MinSyncVectorMethod {
6322
6412
  return results;
6323
6413
  }
6324
6414
  async resolveBinary(options = {}) {
6325
- if (this.binaryPath && existsSync13(this.binaryPath))
6415
+ if (this.binaryPath && existsSync14(this.binaryPath))
6326
6416
  return this.binaryPath;
6327
6417
  if (this.binaryPath !== undefined)
6328
6418
  throw minSyncBinaryMissingError();
@@ -6330,7 +6420,7 @@ class MinSyncVectorMethod {
6330
6420
  if (pathBinary)
6331
6421
  return pathBinary;
6332
6422
  const cachedBinary = join18(this.root, ".autorag", "bin", executableName(process.platform));
6333
- if (existsSync13(cachedBinary))
6423
+ if (existsSync14(cachedBinary))
6334
6424
  return cachedBinary;
6335
6425
  if (this.autoInstall && options.install !== false) {
6336
6426
  try {
@@ -7033,7 +7123,7 @@ var init_defaults = __esm(() => {
7033
7123
  });
7034
7124
 
7035
7125
  // src/parser/isolated.ts
7036
- import { existsSync as existsSync14 } from "node:fs";
7126
+ import { existsSync as existsSync15 } from "node:fs";
7037
7127
  import { dirname as dirname10, join as join21 } from "node:path";
7038
7128
  import { fileURLToPath as fileURLToPath2, pathToFileURL } from "node:url";
7039
7129
  import { Worker } from "node:worker_threads";
@@ -7172,7 +7262,7 @@ function defaultWorkerUrl() {
7172
7262
  join21(here, "parser", "parse-worker.js"),
7173
7263
  join21(here, "..", "parser", "parse-worker.js")
7174
7264
  ]) {
7175
- if (existsSync14(candidate))
7265
+ if (existsSync15(candidate))
7176
7266
  return pathToFileURL(candidate);
7177
7267
  }
7178
7268
  throw new Error(`The AutoRAG parse worker entry was not found near ${here}.`);
@@ -7184,7 +7274,7 @@ var init_isolated = __esm(() => {
7184
7274
  });
7185
7275
 
7186
7276
  // src/mirror/sync.ts
7187
- import { existsSync as existsSync15, rmSync as rmSync7 } from "node:fs";
7277
+ import { existsSync as existsSync16, rmSync as rmSync7 } from "node:fs";
7188
7278
  import { opendir, readFile as readFile3, stat as stat5 } from "node:fs/promises";
7189
7279
  import { extname as extname3, resolve as resolve11, sep as sep6 } from "node:path";
7190
7280
  import { setTimeout as sleep3 } from "node:timers/promises";
@@ -7376,7 +7466,7 @@ async function syncWithRegistry(options, registry, isolated) {
7376
7466
  }
7377
7467
  const previousEntry = previous.entries[entry.virtualPath];
7378
7468
  const outputPath = parsedOutputPath(options.root, entry.virtualPath);
7379
- const unchanged = !options.force && previousEntry?.sourceMtimeNs === entry.mtimeNs && previousEntry.sourceSizeBytes === entry.sizeBytes && previousEntry.parserName === parser.name && existsSync15(outputPath);
7469
+ const unchanged = !options.force && previousEntry?.sourceMtimeNs === entry.mtimeNs && previousEntry.sourceSizeBytes === entry.sizeBytes && previousEntry.parserName === parser.name && existsSync16(outputPath);
7380
7470
  if (!unchanged) {
7381
7471
  let bytes;
7382
7472
  try {
@@ -7757,7 +7847,7 @@ function removePrevious(root, index, virtualPath) {
7757
7847
  return 1;
7758
7848
  }
7759
7849
  function removeFile(path) {
7760
- if (existsSync15(path))
7850
+ if (existsSync16(path))
7761
7851
  rmSync7(path, { force: true });
7762
7852
  }
7763
7853
  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;
@@ -11482,6 +11572,20 @@ function interactiveKeyOf(data) {
11482
11572
  return "followUp";
11483
11573
  return;
11484
11574
  }
11575
+ function stripTelegramEnvelope(text) {
11576
+ return text.replace(/^\s*\[telegram\]\s?/u, "").replace(/\n*\[time\][^\n]*/gu, "").trim();
11577
+ }
11578
+ function userInputText(event) {
11579
+ if (event.source === "interactive")
11580
+ return event.text.trim();
11581
+ if (event.source === "extension" && event.text.trimStart().startsWith(TELEGRAM_INPUT_PREFIX)) {
11582
+ return stripTelegramEnvelope(event.text);
11583
+ }
11584
+ if (event.source === "extension" && event.text.trimStart().startsWith(WHATSAPP_INPUT_PREFIX)) {
11585
+ return event.text.trim();
11586
+ }
11587
+ return;
11588
+ }
11485
11589
  function createAutoRAGInteractiveExtension(getSystemPrompt, contextTransform, options, updateNotice) {
11486
11590
  return (pi) => {
11487
11591
  pi.on("before_agent_start", () => ({ systemPrompt: getSystemPrompt() }));
@@ -11512,8 +11616,8 @@ function createAutoRAGInteractiveExtension(getSystemPrompt, contextTransform, op
11512
11616
  });
11513
11617
  }
11514
11618
  pi.on("input", (event) => {
11515
- const text = event.text.trim();
11516
- if (event.source !== "interactive" || text.length === 0)
11619
+ const text = userInputText(event);
11620
+ if (text === undefined || text.length === 0)
11517
11621
  return;
11518
11622
  if (text.startsWith("/") && isSearchRunning?.() !== true)
11519
11623
  return;
@@ -11610,7 +11714,9 @@ async function createAutoRAGPiInteractiveRuntime(options) {
11610
11714
  agentDir: runtimeAgentDir,
11611
11715
  modelRuntime,
11612
11716
  settingsManager,
11717
+ ...options.extensionFlags === undefined ? {} : { extensionFlagValues: new Map(Object.entries(options.extensionFlags)) },
11613
11718
  resourceLoaderOptions: {
11719
+ ...options.extensionPaths === undefined ? {} : { additionalExtensionPaths: [...options.extensionPaths] },
11614
11720
  extensionFactories: [
11615
11721
  createAutoRAGInteractiveExtension(options.getSystemPrompt, options.contextTransform, { onInput: options.onInput, isSearchRunning: options.isSearchRunning, onKey: options.onKey }, options.updateNotice),
11616
11722
  ...options.extensionFactories ?? []
@@ -11644,7 +11750,7 @@ async function createAutoRAGPiInteractiveRuntime(options) {
11644
11750
  });
11645
11751
  return { runtime, dispose: () => runtime.dispose() };
11646
11752
  }
11647
- var PI_BUILTIN_TOOL_NAMES, EMBEDDED_AUTH_MARKER = "<autorag-embedded-model>";
11753
+ var PI_BUILTIN_TOOL_NAMES, EMBEDDED_AUTH_MARKER = "<autorag-embedded-model>", TELEGRAM_INPUT_PREFIX = "[telegram]", WHATSAPP_INPUT_PREFIX = "Message from ";
11648
11754
  var init_pi_session = __esm(() => {
11649
11755
  init_provider();
11650
11756
  init_context_token_guard();
@@ -11900,11 +12006,11 @@ var init_jikji_find_tool = __esm(() => {
11900
12006
 
11901
12007
  // src/agent/local-model.ts
11902
12008
  import { readFileSync as readFileSync12 } from "node:fs";
11903
- import { homedir as homedir2 } from "node:os";
12009
+ import { homedir as homedir3 } from "node:os";
11904
12010
  import { join as join24 } from "node:path";
11905
12011
  import { parse as parse2 } from "smol-toml";
11906
12012
  function loadLocalAutoRAGModel(options = {}) {
11907
- const configPath = options.configPath ?? join24(homedir2(), ".codex", "config.toml");
12013
+ const configPath = options.configPath ?? join24(homedir3(), ".codex", "config.toml");
11908
12014
  const config = parse2(readFileSync12(configPath, "utf8"));
11909
12015
  const provider = config.model_provider;
11910
12016
  if (typeof provider !== "string" || provider.length === 0) {
@@ -11947,7 +12053,7 @@ var init_local_model = () => {};
11947
12053
 
11948
12054
  // src/p2p/approval-store.ts
11949
12055
  import {
11950
- existsSync as existsSync16,
12056
+ existsSync as existsSync17,
11951
12057
  mkdirSync as mkdirSync11,
11952
12058
  readdirSync as readdirSync3,
11953
12059
  readFileSync as readFileSync13,
@@ -12012,7 +12118,7 @@ function savePendingPeerRequest(workspacePath, request) {
12012
12118
  }
12013
12119
  function loadPendingPeerRequest(workspacePath, id) {
12014
12120
  const path = requestPath(workspacePath, id);
12015
- if (!existsSync16(path))
12121
+ if (!existsSync17(path))
12016
12122
  return;
12017
12123
  try {
12018
12124
  return parsePending(JSON.parse(readFileSync13(path, "utf8")));
@@ -12022,7 +12128,7 @@ function loadPendingPeerRequest(workspacePath, id) {
12022
12128
  }
12023
12129
  function listPendingPeerRequests(workspacePath) {
12024
12130
  const dir = requestsDir(workspacePath);
12025
- if (!existsSync16(dir))
12131
+ if (!existsSync17(dir))
12026
12132
  return [];
12027
12133
  const requests = [];
12028
12134
  for (const name of readdirSync3(dir)) {
@@ -12044,7 +12150,7 @@ function writePeerRequestDecision(workspacePath, id, decision) {
12044
12150
  }
12045
12151
  function loadPeerRequestDecision(workspacePath, id) {
12046
12152
  const path = decisionPath(workspacePath, id);
12047
- if (!existsSync16(path))
12153
+ if (!existsSync17(path))
12048
12154
  return;
12049
12155
  try {
12050
12156
  return parseDecision(JSON.parse(readFileSync13(path, "utf8")));
@@ -12378,7 +12484,7 @@ var init_egress_gate = __esm(() => {
12378
12484
  });
12379
12485
 
12380
12486
  // src/p2p/policy.ts
12381
- import { existsSync as existsSync17, mkdirSync as mkdirSync12, readFileSync as readFileSync14, writeFileSync as writeFileSync10 } from "node:fs";
12487
+ import { existsSync as existsSync18, mkdirSync as mkdirSync12, readFileSync as readFileSync14, writeFileSync as writeFileSync10 } from "node:fs";
12382
12488
  import { basename as basename10, dirname as dirname13, join as join26, resolve as resolve12 } from "node:path";
12383
12489
  import { parse as parseToml } from "smol-toml";
12384
12490
  function isRecord11(value) {
@@ -12458,7 +12564,7 @@ function normalizePolicyEntries(value, workspacePath, context) {
12458
12564
  return entries;
12459
12565
  }
12460
12566
  function readJsonFile(path) {
12461
- if (!existsSync17(path))
12567
+ if (!existsSync18(path))
12462
12568
  return;
12463
12569
  let raw;
12464
12570
  try {
@@ -12473,7 +12579,7 @@ function readJsonFile(path) {
12473
12579
  }
12474
12580
  }
12475
12581
  function readTomlFile(path) {
12476
- if (!existsSync17(path))
12582
+ if (!existsSync18(path))
12477
12583
  return;
12478
12584
  let raw;
12479
12585
  try {
@@ -12614,7 +12720,7 @@ function globToRegExp(pattern) {
12614
12720
  return new RegExp(`${expression}$`, "u");
12615
12721
  }
12616
12722
  function loadSeenSources(path, workspacePath) {
12617
- if (!existsSync17(path))
12723
+ if (!existsSync18(path))
12618
12724
  return { promoted: new Set, pending: new Set };
12619
12725
  let parsed;
12620
12726
  try {
@@ -12921,7 +13027,7 @@ var init_wire = __esm(() => {
12921
13027
 
12922
13028
  // src/p2p/simplex-query-store.ts
12923
13029
  import { randomUUID as randomUUID5 } from "node:crypto";
12924
- 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";
13030
+ 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";
12925
13031
  import { dirname as dirname14, join as join27 } from "node:path";
12926
13032
  import { Value as Value2 } from "typebox/value";
12927
13033
  function statePath(workspacePath, directory, id) {
@@ -12957,7 +13063,7 @@ function parseState(value) {
12957
13063
  return value;
12958
13064
  }
12959
13065
  function readState(path) {
12960
- if (!existsSync18(path))
13066
+ if (!existsSync19(path))
12961
13067
  return;
12962
13068
  try {
12963
13069
  return parseState(JSON.parse(readFileSync15(path, "utf8")));
@@ -12984,14 +13090,14 @@ function moveState(workspacePath, from, to, state) {
12984
13090
  }
12985
13091
  function recoverClaims(workspacePath) {
12986
13092
  const directory = join27(workspacePath, QUERY_DIR, PENDING_DIR);
12987
- if (!existsSync18(directory))
13093
+ if (!existsSync19(directory))
12988
13094
  return;
12989
13095
  for (const name of readdirSync4(directory)) {
12990
13096
  if (!name.endsWith(".json.claim"))
12991
13097
  continue;
12992
13098
  const claim = join27(directory, name);
12993
13099
  const restored = join27(directory, name.slice(0, -".claim".length));
12994
- if (!existsSync18(restored))
13100
+ if (!existsSync19(restored))
12995
13101
  renameSync7(claim, restored);
12996
13102
  }
12997
13103
  }
@@ -13015,7 +13121,7 @@ function loadSimplexQueryState(workspacePath, id) {
13015
13121
  }
13016
13122
  function listPendingSimplexQueryStates(workspacePath) {
13017
13123
  const directory = join27(workspacePath, QUERY_DIR, PENDING_DIR);
13018
- if (!existsSync18(directory))
13124
+ if (!existsSync19(directory))
13019
13125
  return [];
13020
13126
  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));
13021
13127
  }
@@ -13158,7 +13264,7 @@ var init_simplex_query_store = __esm(() => {
13158
13264
  });
13159
13265
 
13160
13266
  // src/p2p/simplex-server.ts
13161
- import { existsSync as existsSync19, mkdirSync as mkdirSync14, readFileSync as readFileSync16, writeFileSync as writeFileSync12 } from "node:fs";
13267
+ import { existsSync as existsSync20, mkdirSync as mkdirSync14, readFileSync as readFileSync16, writeFileSync as writeFileSync12 } from "node:fs";
13162
13268
  import { join as join28 } from "node:path";
13163
13269
  import { Type as Type10 } from "typebox";
13164
13270
  import { Value as Value3 } from "typebox/value";
@@ -13187,7 +13293,7 @@ function rankSimplexPeerTargets(query, registry) {
13187
13293
  }
13188
13294
  function loadSimplexPeerRegistry(workspacePath) {
13189
13295
  const path = join28(workspacePath, PEERS_DIR, PEERS_FILENAME);
13190
- if (!existsSync19(path))
13296
+ if (!existsSync20(path))
13191
13297
  return {};
13192
13298
  try {
13193
13299
  const parsed = JSON.parse(readFileSync16(path, "utf8"));
@@ -14312,14 +14418,14 @@ var init_search_single_datasource_tool = __esm(() => {
14312
14418
  });
14313
14419
 
14314
14420
  // src/agent/self-config.ts
14315
- import { existsSync as existsSync20, readFileSync as readFileSync18, rmSync as rmSync9, writeFileSync as writeFileSync14 } from "node:fs";
14421
+ import { existsSync as existsSync21, readFileSync as readFileSync18, rmSync as rmSync9, writeFileSync as writeFileSync14 } from "node:fs";
14316
14422
  import { dirname as dirname16, join as join29 } from "node:path";
14317
14423
  import { fileURLToPath as fileURLToPath3 } from "node:url";
14318
14424
  function findPackagedSetupSkill() {
14319
14425
  let dir = dirname16(fileURLToPath3(import.meta.url));
14320
14426
  for (let depth = 0;depth < 6; depth += 1) {
14321
14427
  const candidate = join29(dir, SETUP_SKILL_RELATIVE_PATH);
14322
- if (existsSync20(candidate))
14428
+ if (existsSync21(candidate))
14323
14429
  return candidate;
14324
14430
  const parent = dirname16(dir);
14325
14431
  if (parent === dir)
@@ -14342,7 +14448,7 @@ function loadSetupSkill(skillPath) {
14342
14448
  return text.replace(/^---\r?\n[\s\S]*?\r?\n---(?:\r?\n)+/u, "");
14343
14449
  }
14344
14450
  function snapshotConfigFile(configPath) {
14345
- return existsSync20(configPath) ? readFileSync18(configPath, "utf8") : undefined;
14451
+ return existsSync21(configPath) ? readFileSync18(configPath, "utf8") : undefined;
14346
14452
  }
14347
14453
  async function rollbackIfBroken(options, before) {
14348
14454
  if (options.validate === undefined)
@@ -16865,11 +16971,6 @@ var init_types3 = __esm(() => {
16865
16971
  label: "xAI",
16866
16972
  description: "xAI Responses web_search via the agent's xAI model credentials (XAI_API_KEY)"
16867
16973
  },
16868
- {
16869
- value: "perplexity",
16870
- label: "Perplexity",
16871
- description: "Anonymous Perplexity ask endpoint; no key or signup required"
16872
- },
16873
16974
  {
16874
16975
  value: "parallel",
16875
16976
  label: "Parallel",
@@ -16880,16 +16981,21 @@ var init_types3 = __esm(() => {
16880
16981
  label: "SearXNG",
16881
16982
  description: "Advanced: requires a self-hosted SEARXNG_ENDPOINT; never part of the default experience"
16882
16983
  },
16883
- {
16884
- value: "startpage",
16885
- label: "Startpage",
16886
- description: "Credential-free scrape of Startpage (Google-backed) results; may be bot-challenged"
16887
- },
16888
16984
  {
16889
16985
  value: "duckduckgo",
16890
16986
  label: "DuckDuckGo",
16891
16987
  description: "Credential-free best-effort fallback; may be bot-challenged on datacenter/shared-egress IPs"
16892
16988
  },
16989
+ {
16990
+ value: "perplexity",
16991
+ label: "Perplexity",
16992
+ description: "Anonymous Perplexity ask endpoint; no key or signup required"
16993
+ },
16994
+ {
16995
+ value: "startpage",
16996
+ label: "Startpage",
16997
+ description: "Credential-free scrape of Startpage (Google-backed) results; may be bot-challenged"
16998
+ },
16893
16999
  {
16894
17000
  value: "ecosia",
16895
17001
  label: "Ecosia",
@@ -18237,12 +18343,11 @@ function eventAnswer(event) {
18237
18343
  }
18238
18344
  return "";
18239
18345
  }
18240
- 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;
18346
+ 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;
18241
18347
  var init_perplexity = __esm(() => {
18242
18348
  init_query();
18243
18349
  init_types3();
18244
18350
  init_utils();
18245
- DEFLECTION_PATTERN = /sign up|log in|create an account|verify you are human|are you a robot|가입|로그인|회원 ?가입/i;
18246
18351
  MAX_ERROR_BYTES4 = 8 * 1024;
18247
18352
  PERPLEXITY_QUERY_SYNTAX = {
18248
18353
  phrases: true,
@@ -18356,8 +18461,8 @@ var init_perplexity = __esm(() => {
18356
18461
  break;
18357
18462
  }
18358
18463
  const sources = [...sourcesByUrl.values()];
18359
- if (sources.length === 0 && DEFLECTION_PATTERN.test(answer)) {
18360
- throw new SearchProviderError("perplexity", "Perplexity anonymous ask was deflected with a sign-up wall", 403);
18464
+ if (sources.length === 0) {
18465
+ throw new SearchProviderError("perplexity", `Perplexity anonymous ask returned no web sources (sign-up wall or conversational deflection): ${answer.slice(0, 120)}`, 403);
18361
18466
  }
18362
18467
  const numResults = params.numSearchResults ?? params.limit;
18363
18468
  return {
@@ -18775,7 +18880,7 @@ var init_browser_headers = __esm(() => {
18775
18880
  });
18776
18881
 
18777
18882
  // src/web/search/browser-loader.ts
18778
- import { existsSync as existsSync21 } from "node:fs";
18883
+ import { existsSync as existsSync22 } from "node:fs";
18779
18884
  async function closeBounded(close) {
18780
18885
  let timer;
18781
18886
  try {
@@ -18854,7 +18959,7 @@ function ensureWebSearchBrowserLoader(options = {}) {
18854
18959
  return true;
18855
18960
  const exists = options.exists ?? ((path) => {
18856
18961
  try {
18857
- return existsSync21(path);
18962
+ return existsSync22(path);
18858
18963
  } catch {
18859
18964
  return false;
18860
18965
  }
@@ -18959,6 +19064,8 @@ function normalizeText(value) {
18959
19064
  function isChallengeResponse(page) {
18960
19065
  if (/\/(?:errors|captcha)\//.test(page.url) || page.url.includes("/sp/captcha"))
18961
19066
  return true;
19067
+ if (ANUBIS_CHALLENGE_PATTERN.test(page.html))
19068
+ return true;
18962
19069
  return page.html.includes("component---src-pages-captcha") || page.html.includes("/sp/captcha");
18963
19070
  }
18964
19071
  function parseSearchFormInputs(html) {
@@ -19063,7 +19170,7 @@ async function callStartpageHtml(params) {
19063
19170
  });
19064
19171
  }
19065
19172
  if (isChallengeResponse(page)) {
19066
- 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);
19173
+ 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);
19067
19174
  }
19068
19175
  if (page.status < 200 || page.status >= 300) {
19069
19176
  const classified = classifyProviderHttpError("startpage", page.status, page.html);
@@ -19089,7 +19196,7 @@ async function searchStartpage(params) {
19089
19196
  }
19090
19197
  return { provider: "startpage", sources };
19091
19198
  }
19092
- 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;
19199
+ 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;
19093
19200
  var init_startpage = __esm(() => {
19094
19201
  init_entities();
19095
19202
  init_browser_page();
@@ -19102,6 +19209,7 @@ var init_startpage = __esm(() => {
19102
19209
  month: "m",
19103
19210
  year: "y"
19104
19211
  };
19212
+ ANUBIS_CHALLENGE_PATTERN = /<script\b[^>]*\bid\s*=\s*["']anubis_(?:challenge|version)["']/i;
19105
19213
  StartpageProvider = class StartpageProvider extends SearchProvider {
19106
19214
  id = "startpage";
19107
19215
  label = "Startpage";
@@ -20319,7 +20427,7 @@ var init_web_search_tool = __esm(() => {
20319
20427
 
20320
20428
  // src/agent/agent.ts
20321
20429
  import { randomUUID as randomUUID7 } from "node:crypto";
20322
- import { existsSync as existsSync22, watch as fsWatch, mkdirSync as mkdirSync16, realpathSync as realpathSync5, statSync as statSync2, writeFileSync as writeFileSync15 } from "node:fs";
20430
+ import { existsSync as existsSync23, watch as fsWatch, mkdirSync as mkdirSync16, realpathSync as realpathSync5, statSync as statSync2, writeFileSync as writeFileSync15 } from "node:fs";
20323
20431
  import { basename as basename11, dirname as dirname17, join as join31, resolve as resolve13 } from "node:path";
20324
20432
  import { clampThinkingLevel } from "@earendil-works/pi-ai/compat";
20325
20433
  import { getAgentDir as getAgentDir3 } from "@earendil-works/pi-coding-agent";
@@ -20450,6 +20558,9 @@ class AutoRAGAgent {
20450
20558
  piSessionDir;
20451
20559
  persistPiSessions;
20452
20560
  updateNotice;
20561
+ piExtensionPaths;
20562
+ piExtensionFlags;
20563
+ telegram;
20453
20564
  boundPiRuntime;
20454
20565
  memoryEmbedder;
20455
20566
  memoryVectorPath;
@@ -20475,6 +20586,9 @@ class AutoRAGAgent {
20475
20586
  this.piSessionDir = options.piSessionDir;
20476
20587
  this.persistPiSessions = options.persistPiSessions ?? true;
20477
20588
  this.updateNotice = options.updateNotice;
20589
+ this.piExtensionPaths = options.piExtensionPaths;
20590
+ this.piExtensionFlags = options.piExtensionFlags;
20591
+ this.telegram = options.telegram === true;
20478
20592
  this.datasourceSkills = options.datasourceSkills ?? [];
20479
20593
  this.datasourceRetry = options.datasourceRetry ?? {};
20480
20594
  this.datasourceVirtualScopePrefixes = this.datasourceSkills.map((skill) => normalizeVirtualPath2(`/${skill.describe().name}`));
@@ -20946,6 +21060,7 @@ ${context.text}
20946
21060
  }
20947
21061
  async createPiInteractiveRuntime() {
20948
21062
  const resolved = this.configuredModel === undefined ? undefined : await this.resolveSessionModel();
21063
+ const telegramBridge = this.telegram ? (await import("@llblab/pi-telegram")).default : undefined;
20949
21064
  const runtime = await createAutoRAGPiInteractiveRuntime({
20950
21065
  cwd: this.workspaceProjectRoot,
20951
21066
  agentDir: this.piAgentDir,
@@ -20966,11 +21081,14 @@ ${context.text}
20966
21081
  onKey: (key) => this.handleInteractiveKey(key),
20967
21082
  extensionFactories: [
20968
21083
  createEvidencePersistence(this.evidenceLedger),
20969
- ...this.jevExtension !== undefined ? [this.jevExtension] : []
21084
+ ...this.jevExtension !== undefined ? [this.jevExtension] : [],
21085
+ ...telegramBridge !== undefined ? [telegramBridge] : []
20970
21086
  ],
20971
21087
  ...this.jevExtension !== undefined ? { extensionToolNames: [JEV_TOOL_NAME] } : {},
20972
21088
  remoteSession: this.remoteSession,
20973
- ...this.updateNotice === undefined ? {} : { updateNotice: this.updateNotice }
21089
+ ...this.updateNotice === undefined ? {} : { updateNotice: this.updateNotice },
21090
+ ...this.piExtensionPaths === undefined ? {} : { extensionPaths: this.piExtensionPaths },
21091
+ ...this.piExtensionFlags === undefined ? {} : { extensionFlags: this.piExtensionFlags }
20974
21092
  });
20975
21093
  this.boundPiRuntime = runtime.runtime;
20976
21094
  const dispose = runtime.dispose;
@@ -21890,22 +22008,22 @@ ${result.content.replace(/\s+/gu, " ")}`).join(`
21890
22008
  const scope = options.scope ? ` Restrict search to virtual path scope ${options.scope}.` : "";
21891
22009
  return `Answer this original query immediately: ${query}${limit}${scope}
21892
22010
 
21893
- ` + `Baseline retrieval evidence (already gathered for you):
22011
+ Baseline retrieval evidence (already gathered for you):
21894
22012
  ${baseline}
21895
22013
 
21896
- ` + `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.
22014
+ 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.
21897
22015
 
21898
- ` + `Formatting and content rules for the answer:
21899
- ` + `- 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.
21900
- ` + `- 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.
21901
- ` + `- ${ANSWER_DELIVERABLE_RULE}
21902
- ` + `- ${ANSWER_CITATION_RULE}
21903
- ` + `- ${ANSWER_IMAGE_EMBED_RULE}
21904
- ` + `- Do not report per-source negative findings (e.g. "no information found in Slack" or "checked Drive but found nothing").
21905
- ` + `- When evidence conflicts, treat the freshest (most recent) information as the correct source of truth.
21906
- ` + `- 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.
22016
+ Formatting and content rules for the answer:
22017
+ - 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.
22018
+ - 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.
22019
+ - ${ANSWER_DELIVERABLE_RULE}
22020
+ - ${ANSWER_CITATION_RULE}
22021
+ - ${ANSWER_IMAGE_EMBED_RULE}
22022
+ - Do not report per-source negative findings (e.g. "no information found in Slack" or "checked Drive but found nothing").
22023
+ - When evidence conflicts, treat the freshest (most recent) information as the correct source of truth.
22024
+ - 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.
21907
22025
 
21908
- ` + `Write the answer as your reply, then stop.`;
22026
+ Write the answer as your reply, then stop.`;
21909
22027
  }
21910
22028
  isConversationTurn() {
21911
22029
  if (this.remoteSession || this.boundPiRuntime === undefined)
@@ -21915,7 +22033,7 @@ ${baseline}
21915
22033
  buildDirectAnswerPrompt(query) {
21916
22034
  return `Answer this query directly from your own general knowledge: ${query}
21917
22035
 
21918
- ` + `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.`;
22036
+ 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.`;
21919
22037
  }
21920
22038
  discoveryHint(sentence) {
21921
22039
  const names = this.tools.map((tool) => tool.name).filter((name) => name === JIKJI_FIND_TOOL_NAME || name === EVERYTHING_SEARCH_TOOL_NAME);
@@ -21933,55 +22051,55 @@ ${baseline}
21933
22051
  const scope = options.scope ? ` Restrict search to virtual path scope ${options.scope}.` : "";
21934
22052
  const firstAnswer = formatFirstAnswerContext(fastAnswer, fastAnswerDelivered);
21935
22053
  const answerRules = fastAnswerDelivered ? `Formatting and content rules for your final answer (DELTA ONLY):
21936
- ` + `- 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.
21937
- ` + `- NEVER restate or re-list first-answer facts that remain correct, and never repeat its bullet list.
21938
- ` + `- Mark each item clearly as a correction or as a new finding.
21939
- ` + `- 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.
21940
- ` + `- ${ANSWER_DELIVERABLE_RULE} ${ANSWER_DELIVERABLE_DELTA_RULE}
21941
- ` + `- ${ANSWER_CITATION_RULE} A correction or new finding that relies on evidence the first answer cited must cite that evidence's id again.
21942
- ` + `- ${ANSWER_IMAGE_EMBED_RULE} ${ANSWER_IMAGE_DELTA_RULE}
21943
- ` + `- Do not report per-source negative findings (e.g. "no information found in Slack").
21944
- ` + `- 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):
22054
+ - 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.
22055
+ - NEVER restate or re-list first-answer facts that remain correct, and never repeat its bullet list.
22056
+ - Mark each item clearly as a correction or as a new finding.
22057
+ - 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.
22058
+ - ${ANSWER_DELIVERABLE_RULE} ${ANSWER_DELIVERABLE_DELTA_RULE}
22059
+ - ${ANSWER_CITATION_RULE} A correction or new finding that relies on evidence the first answer cited must cite that evidence's id again.
22060
+ - ${ANSWER_IMAGE_EMBED_RULE} ${ANSWER_IMAGE_DELTA_RULE}
22061
+ - Do not report per-source negative findings (e.g. "no information found in Slack").
22062
+ - 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):
21945
22063
  ` + `- 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.
21946
- ` + `- 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.
21947
- ` + `- ${ANSWER_DELIVERABLE_RULE}${fastAnswer !== undefined ? ` ${ANSWER_DELIVERABLE_DELTA_RULE}` : ""}
21948
- ` + `- ${ANSWER_CITATION_RULE}
21949
- ` + `- ${ANSWER_IMAGE_EMBED_RULE}
21950
- ` + `- Do not report per-source negative findings (e.g. "no information found in Slack").
21951
- ` + `- When evidence conflicts, treat the freshest (most recent) information as the correct source of truth.`;
22064
+ - 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.
22065
+ - ${ANSWER_DELIVERABLE_RULE}${fastAnswer !== undefined ? ` ${ANSWER_DELIVERABLE_DELTA_RULE}` : ""}
22066
+ - ${ANSWER_CITATION_RULE}
22067
+ - ${ANSWER_IMAGE_EMBED_RULE}
22068
+ - Do not report per-source negative findings (e.g. "no information found in Slack").
22069
+ - When evidence conflicts, treat the freshest (most recent) information as the correct source of truth.`;
21952
22070
  return `Original query: ${query}${limit}${scope}
21953
22071
 
21954
- ` + `${firstAnswer}
22072
+ ${firstAnswer}
21955
22073
 
21956
22074
  ` + 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()}
21957
22075
 
21958
- ` + `${answerRules}
22076
+ ${answerRules}
21959
22077
 
21960
- ` + `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.`;
22078
+ 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.`;
21961
22079
  }
21962
22080
  buildSearchPrompt(query, options, initialRetrievalContext) {
21963
22081
  const limit = typeof options.topK === "number" ? ` Cite at most ${options.topK} sources.` : "";
21964
22082
  const scope = options.scope ? ` Restrict search to virtual path scope ${options.scope}.` : "";
21965
22083
  return `Find and curate information for this original query: ${query}${limit}${scope}
21966
22084
 
21967
- ` + `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.
22085
+ 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.
21968
22086
 
21969
- ` + `Baseline retrieval context:
22087
+ Baseline retrieval context:
21970
22088
  ${initialRetrievalContext ?? "Pending; continue only with a brief progress statement."}
21971
22089
 
21972
- ` + `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.
22090
+ 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.
21973
22091
 
21974
- ` + `Formatting and content rules for the answer:
21975
- ` + `- 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.
21976
- ` + `- 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.
21977
- ` + `- ${ANSWER_DELIVERABLE_RULE}
21978
- ` + `- ${ANSWER_CITATION_RULE}
21979
- ` + `- ${ANSWER_IMAGE_EMBED_RULE}
21980
- ` + `- Do not report per-source negative findings (e.g. "no information found in Slack").
21981
- ` + `- When evidence conflicts, treat the freshest (most recent) information as the correct source of truth.
21982
- ` + `- If information is incomplete or uncertain, acknowledge it briefly without lengthy explanations. If there are partial clues or leads, mention them concisely.
22092
+ Formatting and content rules for the answer:
22093
+ - 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.
22094
+ - 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.
22095
+ - ${ANSWER_DELIVERABLE_RULE}
22096
+ - ${ANSWER_CITATION_RULE}
22097
+ - ${ANSWER_IMAGE_EMBED_RULE}
22098
+ - Do not report per-source negative findings (e.g. "no information found in Slack").
22099
+ - When evidence conflicts, treat the freshest (most recent) information as the correct source of truth.
22100
+ - If information is incomplete or uncertain, acknowledge it briefly without lengthy explanations. If there are partial clues or leads, mention them concisely.
21983
22101
 
21984
- ` + `${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.`;
22102
+ ${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.`;
21985
22103
  }
21986
22104
  async refresh(force = false, opts) {
21987
22105
  const signal = opts?.signal;
@@ -22217,7 +22335,7 @@ ${initialRetrievalContext ?? "Pending; continue only with a brief progress state
22217
22335
  });
22218
22336
  }
22219
22337
  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;
22220
- const parsedMirrorReady = this.refreshState.lastOutcome === "success" || persistedProgress?.state === "success" || existsSync22(refreshReadinessPath(this.workspaceProjectRoot));
22338
+ const parsedMirrorReady = this.refreshState.lastOutcome === "success" || persistedProgress?.state === "success" || existsSync23(refreshReadinessPath(this.workspaceProjectRoot));
22221
22339
  const effectiveProgress = this.refreshState.inFlight || persistedRunning ? persistedProgress : undefined;
22222
22340
  return {
22223
22341
  state,
@@ -22677,7 +22795,7 @@ function buildSteerMessage(text) {
22677
22795
 
22678
22796
  ${text}
22679
22797
 
22680
- ` + `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.`;
22798
+ 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.`;
22681
22799
  }
22682
22800
  function frameSteers(messages, steerTexts) {
22683
22801
  if (steerTexts.size === 0)
@@ -22697,12 +22815,12 @@ function formatSteerContext(steers) {
22697
22815
  return `While the search ran, the user corrected it:
22698
22816
  ${steers.map((steer) => `- ${steer}`).join(`
22699
22817
  `)}
22700
- ` + `The first answer predates these corrections; follow them over it.
22818
+ The first answer predates these corrections; follow them over it.
22701
22819
 
22702
22820
  `;
22703
22821
  }
22704
22822
  function buildSteerContinuationPrompt(steers) {
22705
- 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.`;
22823
+ 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.`;
22706
22824
  }
22707
22825
  function formatFirstAnswerContext(fastAnswer, delivered) {
22708
22826
  if (fastAnswer === undefined) {
@@ -22825,11 +22943,20 @@ function fsearchRefreshDiagnostics(fsearch) {
22825
22943
  function minSyncRefreshDiagnostics(minsync) {
22826
22944
  if (!minsync)
22827
22945
  return [];
22946
+ const diagnostics = [];
22828
22947
  if (minsync.diagnostic)
22829
- return [toMinSyncDiagnostic(minsync.diagnostic, minsync.ok)];
22830
- if (!minsync.ok && minsync.reason)
22831
- return [toMinSyncReasonDiagnostic(minsync.reason)];
22832
- return [];
22948
+ diagnostics.push(toMinSyncDiagnostic(minsync.diagnostic, minsync.ok));
22949
+ else if (!minsync.ok && minsync.reason)
22950
+ diagnostics.push(toMinSyncReasonDiagnostic(minsync.reason));
22951
+ if (minsync.lexicalFallback) {
22952
+ diagnostics.push({
22953
+ code: "lexical-tokenizer-unavailable",
22954
+ severity: "warning",
22955
+ 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.`,
22956
+ source: "minsync"
22957
+ });
22958
+ }
22959
+ return diagnostics;
22833
22960
  }
22834
22961
  function toMinSyncDiagnostic(diag, ok) {
22835
22962
  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";
@@ -23219,7 +23346,7 @@ var init_connector = () => {};
23219
23346
 
23220
23347
  // src/datasource/sidecar/config.ts
23221
23348
  import { readFileSync as readFileSync19 } from "node:fs";
23222
- import { homedir as homedir3 } from "node:os";
23349
+ import { homedir as homedir4 } from "node:os";
23223
23350
  import { dirname as dirname18, isAbsolute as isAbsolute8, join as join32, resolve as resolve14, sep as sep7 } from "node:path";
23224
23351
  import { parse as parseToml2 } from "smol-toml";
23225
23352
  function resolveSidecarOptions(input) {
@@ -23259,9 +23386,9 @@ function archivePathFromCrawlerConfig(input) {
23259
23386
  }
23260
23387
  function expandHome(path) {
23261
23388
  if (path === "~")
23262
- return homedir3();
23389
+ return homedir4();
23263
23390
  const prefixed = path.startsWith("~/") || sep7 === "\\" && path.startsWith("~\\");
23264
- return prefixed ? join32(homedir3(), path.slice(2)) : path;
23391
+ return prefixed ? join32(homedir4(), path.slice(2)) : path;
23265
23392
  }
23266
23393
  var init_config2 = __esm(() => {
23267
23394
  init_connector();
@@ -23352,7 +23479,7 @@ var init_descriptors = __esm(() => {
23352
23479
 
23353
23480
  // src/datasource/skills/clawgallery/client.ts
23354
23481
  import { spawn as spawn10 } from "node:child_process";
23355
- import { existsSync as existsSync23 } from "node:fs";
23482
+ import { existsSync as existsSync24 } from "node:fs";
23356
23483
 
23357
23484
  class ClawGalleryClient {
23358
23485
  options;
@@ -23360,7 +23487,7 @@ class ClawGalleryClient {
23360
23487
  this.options = options;
23361
23488
  }
23362
23489
  async bootstrap(signal) {
23363
- if (this.options.path !== undefined && !existsSync23(this.options.path)) {
23490
+ if (this.options.path !== undefined && !existsSync24(this.options.path)) {
23364
23491
  return {
23365
23492
  ok: false,
23366
23493
  reason: "nonzero-exit",
@@ -24278,7 +24405,7 @@ var init_rclone_connector = __esm(() => {
24278
24405
  });
24279
24406
 
24280
24407
  // src/datasource/chunk-store.ts
24281
- import { existsSync as existsSync24, mkdirSync as mkdirSync18, readFileSync as readFileSync21, writeFileSync as writeFileSync17 } from "node:fs";
24408
+ import { existsSync as existsSync25, mkdirSync as mkdirSync18, readFileSync as readFileSync21, writeFileSync as writeFileSync17 } from "node:fs";
24282
24409
  import { dirname as dirname20, join as join34 } from "node:path";
24283
24410
  function datasourceChunkStorePath(workspaceRoot, skillName, instanceId) {
24284
24411
  return join34(workspaceRoot, ".autorag", "datasources", sanitizeIdSegment(skillName), sanitizeIdSegment(instanceId), "chunks.json");
@@ -24318,7 +24445,7 @@ class DatasourceChunkStore {
24318
24445
  if (this.storePath === undefined)
24319
24446
  return false;
24320
24447
  try {
24321
- if (!existsSync24(this.storePath))
24448
+ if (!existsSync25(this.storePath))
24322
24449
  return false;
24323
24450
  const parsed = JSON.parse(readFileSync21(this.storePath, "utf8"));
24324
24451
  if (parsed.version !== STORE_VERSION || !Array.isArray(parsed.chunks))
@@ -25845,7 +25972,7 @@ var init_github = __esm(() => {
25845
25972
 
25846
25973
  // src/datasource/skills/github-gist/connector.ts
25847
25974
  import { execFile as execFile2 } from "node:child_process";
25848
- import { existsSync as existsSync25, mkdirSync as mkdirSync20, readFileSync as readFileSync23, writeFileSync as writeFileSync19 } from "node:fs";
25975
+ import { existsSync as existsSync26, mkdirSync as mkdirSync20, readFileSync as readFileSync23, writeFileSync as writeFileSync19 } from "node:fs";
25849
25976
  import { dirname as dirname22 } from "node:path";
25850
25977
  async function defaultGhTokenRunner() {
25851
25978
  return new Promise((resolve) => {
@@ -25965,7 +26092,7 @@ class GitHubGistConnector {
25965
26092
  }
25966
26093
  loadState() {
25967
26094
  const statePath = this.options.statePath;
25968
- if (statePath === undefined || !existsSync25(statePath))
26095
+ if (statePath === undefined || !existsSync26(statePath))
25969
26096
  return { version: STATE_VERSION, gists: {} };
25970
26097
  try {
25971
26098
  const parsed = JSON.parse(readFileSync23(statePath, "utf8"));
@@ -26028,7 +26155,7 @@ var init_connector3 = () => {};
26028
26155
 
26029
26156
  // src/datasource/skills/github-gist/semantic.ts
26030
26157
  import { createHash as createHash13 } from "node:crypto";
26031
- import { existsSync as existsSync26, mkdirSync as mkdirSync21, readFileSync as readFileSync24, writeFileSync as writeFileSync20 } from "node:fs";
26158
+ import { existsSync as existsSync27, mkdirSync as mkdirSync21, readFileSync as readFileSync24, writeFileSync as writeFileSync20 } from "node:fs";
26032
26159
  import { dirname as dirname23 } from "node:path";
26033
26160
  function contentHash(chunk) {
26034
26161
  return createHash13("sha256").update(`${chunk.title ?? ""}
@@ -26119,7 +26246,7 @@ ${chunk.content}`));
26119
26246
  if (this.loaded)
26120
26247
  return;
26121
26248
  this.loaded = true;
26122
- if (this.statePath === undefined || !existsSync26(this.statePath))
26249
+ if (this.statePath === undefined || !existsSync27(this.statePath))
26123
26250
  return;
26124
26251
  try {
26125
26252
  const parsed = JSON.parse(readFileSync24(this.statePath, "utf8"));
@@ -26982,7 +27109,7 @@ var init_types5 = __esm(() => {
26982
27109
 
26983
27110
  // src/datasource/skills/lazykatok/client.ts
26984
27111
  import { spawn as spawn14 } from "node:child_process";
26985
- import { existsSync as existsSync27 } from "node:fs";
27112
+ import { existsSync as existsSync28 } from "node:fs";
26986
27113
  import { delimiter as delimiter4, join as join36 } from "node:path";
26987
27114
 
26988
27115
  class LazykatokClient {
@@ -27172,7 +27299,7 @@ function lookupInPath2(executable, env) {
27172
27299
  if (dir.length === 0)
27173
27300
  continue;
27174
27301
  const candidate = join36(dir, executable);
27175
- if (existsSync27(candidate))
27302
+ if (existsSync28(candidate))
27176
27303
  return candidate;
27177
27304
  }
27178
27305
  return;
@@ -30925,7 +31052,7 @@ var init_wacrawl = __esm(() => {
30925
31052
  });
30926
31053
 
30927
31054
  // src/datasource/skills/factory.ts
30928
- import { homedir as homedir4 } from "node:os";
31055
+ import { homedir as homedir5 } from "node:os";
30929
31056
  import { join as join39 } from "node:path";
30930
31057
  function chatCrawlerArgs(descriptor, defaultCrawlerDb, config, workspaceRoot, registrationName) {
30931
31058
  const sidecar = resolveSidecarOptions({
@@ -31029,9 +31156,9 @@ var init_factory = __esm(() => {
31029
31156
  init_telecrawl();
31030
31157
  init_wacrawl();
31031
31158
  BUILDERS = {
31032
- telegram: (config, workspaceRoot, registrationName) => new TelecrawlSkill(chatCrawlerArgs(CRAWLER_DESCRIPTORS.telegram, join39(homedir4(), ".telecrawl", "telecrawl.db"), config, workspaceRoot, registrationName)),
31033
- whatsapp: (config, workspaceRoot, registrationName) => new WacrawlSkill(chatCrawlerArgs(CRAWLER_DESCRIPTORS.whatsapp, join39(homedir4(), ".wacrawl", "wacrawl.db"), config, workspaceRoot, registrationName)),
31034
- slack: (config, workspaceRoot, registrationName) => new SlackSkill(chatCrawlerArgs(CRAWLER_DESCRIPTORS.slack, join39(homedir4(), ".slacrawl", "slacrawl.db"), config, workspaceRoot, registrationName)),
31159
+ telegram: (config, workspaceRoot, registrationName) => new TelecrawlSkill(chatCrawlerArgs(CRAWLER_DESCRIPTORS.telegram, join39(homedir5(), ".telecrawl", "telecrawl.db"), config, workspaceRoot, registrationName)),
31160
+ whatsapp: (config, workspaceRoot, registrationName) => new WacrawlSkill(chatCrawlerArgs(CRAWLER_DESCRIPTORS.whatsapp, join39(homedir5(), ".wacrawl", "wacrawl.db"), config, workspaceRoot, registrationName)),
31161
+ slack: (config, workspaceRoot, registrationName) => new SlackSkill(chatCrawlerArgs(CRAWLER_DESCRIPTORS.slack, join39(homedir5(), ".slacrawl", "slacrawl.db"), config, workspaceRoot, registrationName)),
31035
31162
  discord: (config, workspaceRoot, registrationName, embeddingRuntime) => {
31036
31163
  const connector = config.connector ?? {};
31037
31164
  const clientOptions = {
@@ -31089,7 +31216,7 @@ var init_factory = __esm(() => {
31089
31216
  }),
31090
31217
  kakao: (config, workspaceRoot, registrationName) => {
31091
31218
  const connector = config.connector ?? {};
31092
- const dataDir = typeof connector.workspacePath === "string" && connector.workspacePath.length > 0 ? connector.workspacePath : join39(homedir4(), "Library", "Application Support", "katok");
31219
+ const dataDir = typeof connector.workspacePath === "string" && connector.workspacePath.length > 0 ? connector.workspacePath : join39(homedir5(), "Library", "Application Support", "katok");
31093
31220
  const sidecar = resolveSidecarOptions({
31094
31221
  descriptor: CRAWLER_DESCRIPTORS.kakao,
31095
31222
  connector: config.connector,
@@ -31113,11 +31240,16 @@ var init_factory = __esm(() => {
31113
31240
  skillName: registrationName,
31114
31241
  connectorOptions: config.connector
31115
31242
  }),
31116
- "github-gist": (config, workspaceRoot, registrationName) => new GitHubGistSkill({
31117
- ...common(config, workspaceRoot),
31118
- skillName: registrationName,
31119
- connectorOptions: config.connector
31120
- }),
31243
+ "github-gist": (config, workspaceRoot, registrationName) => {
31244
+ const { semantic, ...connectorOptions } = config.connector ?? {};
31245
+ const semanticOff = semantic === false || typeof semantic === "object" && semantic !== null && semantic.enabled === false;
31246
+ return new GitHubGistSkill({
31247
+ ...common(config, workspaceRoot),
31248
+ skillName: registrationName,
31249
+ connectorOptions,
31250
+ ...semanticOff ? { semantic: { enabled: false } } : {}
31251
+ });
31252
+ },
31121
31253
  "cloud-drive": (config, workspaceRoot, registrationName) => new CloudDriveSkill({
31122
31254
  ...common(config, workspaceRoot),
31123
31255
  skillName: registrationName,
@@ -31163,7 +31295,7 @@ var init_factory = __esm(() => {
31163
31295
 
31164
31296
  // src/cli/config.ts
31165
31297
  import { randomUUID as randomUUID8 } from "node:crypto";
31166
- import { existsSync as existsSync28, mkdirSync as mkdirSync25, readFileSync as readFileSync25, renameSync as renameSync10, unlinkSync as unlinkSync5, writeFileSync as writeFileSync22 } from "node:fs";
31298
+ import { existsSync as existsSync29, mkdirSync as mkdirSync25, readFileSync as readFileSync25, renameSync as renameSync10, unlinkSync as unlinkSync5, writeFileSync as writeFileSync22 } from "node:fs";
31167
31299
  import { basename as basename14, dirname as dirname26, isAbsolute as isAbsolute10, join as join40, resolve as resolve16 } from "node:path";
31168
31300
  import { findEnvKeys, getEnvApiKey } from "@earendil-works/pi-ai/compat";
31169
31301
  import { getAgentDir as getAgentDir4, ModelRuntime as ModelRuntime2, SettingsManager as SettingsManager2 } from "@earendil-works/pi-coding-agent";
@@ -31188,7 +31320,7 @@ function resolveConfigPath(input) {
31188
31320
  function readConfigFile(configPath, explicit) {
31189
31321
  let exists;
31190
31322
  try {
31191
- exists = existsSync28(configPath);
31323
+ exists = existsSync29(configPath);
31192
31324
  } catch {
31193
31325
  exists = false;
31194
31326
  }
@@ -31248,7 +31380,7 @@ function replaceFileAtomically(path, contents, assertCommitAllowed) {
31248
31380
  }
31249
31381
  }
31250
31382
  function migrateLegacyConfig(configPath, legacyPath) {
31251
- if (existsSync28(configPath) || !existsSync28(legacyPath))
31383
+ if (existsSync29(configPath) || !existsSync29(legacyPath))
31252
31384
  return;
31253
31385
  const legacy = readConfigFile(legacyPath, true);
31254
31386
  const legacyBytes = readFileSync25(legacyPath);
@@ -32519,7 +32651,7 @@ function writeDefaultConfig(path, partial, opts = {}) {
32519
32651
  `;
32520
32652
  const lock = acquireConfigWriteLock(path);
32521
32653
  try {
32522
- const exists = existsSync28(path);
32654
+ const exists = existsSync29(path);
32523
32655
  if (!opts.force && exists) {
32524
32656
  throw new ConfigError(`Config file already exists: ${path}`);
32525
32657
  }