@ninjaxtools/slopdex 0.14.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -176,6 +176,8 @@ interface CodeIndexOptions {
176
176
  exclude?: readonly string[];
177
177
  maxFileSize?: number;
178
178
  embeddingBatchSize?: number;
179
+ /** Emit a stderr notice for every call made by the default description provider. */
180
+ verbose?: boolean;
179
181
  readOnly?: boolean;
180
182
  }
181
183
  interface UpdateFilesOptions {
@@ -418,6 +420,7 @@ interface OpenAIEmbeddingProviderOptions {
418
420
  model?: string;
419
421
  dimensions?: number;
420
422
  baseUrl?: string;
423
+ verbose?: boolean;
421
424
  }
422
425
  declare class OpenAIEmbeddingProvider implements EmbeddingProvider {
423
426
  #private;
@@ -441,6 +444,7 @@ interface OpenAIDescriptionProviderOptions {
441
444
  model?: string;
442
445
  baseUrl?: string;
443
446
  provider?: DescriptionProviderName;
447
+ verbose?: boolean;
444
448
  }
445
449
  declare const DESCRIPTION_PROVIDER_NAMES: readonly ["openai", "opencode", "opencode-go"];
446
450
  type DescriptionProviderName = typeof DESCRIPTION_PROVIDER_NAMES[number];
@@ -466,6 +470,7 @@ interface JinaEmbeddingProviderOptions {
466
470
  model?: string;
467
471
  dimensions?: number;
468
472
  baseUrl?: string;
473
+ verbose?: boolean;
469
474
  }
470
475
  declare class JinaEmbeddingProvider implements EmbeddingProvider {
471
476
  #private;
@@ -488,6 +493,7 @@ interface HostedRerankerOptions {
488
493
  apiKey?: string;
489
494
  model?: string;
490
495
  baseUrl?: string;
496
+ verbose?: boolean;
491
497
  }
492
498
  interface HostedRerankerSettings {
493
499
  provider: "cohere" | "jina";
@@ -525,6 +531,7 @@ interface OpenAILLMRerankerOptions {
525
531
  model?: string;
526
532
  baseUrl?: string;
527
533
  candidateCount?: number;
534
+ verbose?: boolean;
528
535
  }
529
536
  declare class OpenAILLMReranker implements Reranker {
530
537
  #private;
package/dist/index.js CHANGED
@@ -1678,6 +1678,20 @@ function reconcileFunctions(current, previous) {
1678
1678
  import { createOpenAI } from "@ai-sdk/openai";
1679
1679
  import { APICallError, generateText } from "ai";
1680
1680
  import { randomUUID } from "node:crypto";
1681
+
1682
+ // src/model-call-notice.ts
1683
+ var reportedCalls = /* @__PURE__ */ new Set();
1684
+ function reportModelCall(kind, profile, verbose = false) {
1685
+ const key = JSON.stringify([kind, profile.provider, profile.model]);
1686
+ if (!verbose && reportedCalls.has(key)) return;
1687
+ reportedCalls.add(key);
1688
+ process.stderr.write(
1689
+ `slopdex: notice: external model call: kind=${kind} provider=${JSON.stringify(profile.provider)} model=${JSON.stringify(profile.model)}
1690
+ `
1691
+ );
1692
+ }
1693
+
1694
+ // src/descriptions/openai.ts
1681
1695
  var DESCRIPTION_PROVIDER_NAMES = ["openai", "opencode", "opencode-go"];
1682
1696
  function isDescriptionProviderName(value) {
1683
1697
  return DESCRIPTION_PROVIDER_NAMES.includes(value);
@@ -1699,6 +1713,7 @@ var OpenAIDescriptionProvider = class {
1699
1713
  #apiKeyName;
1700
1714
  #baseUrl;
1701
1715
  #openCode;
1716
+ #verbose;
1702
1717
  constructor(options = {}) {
1703
1718
  const provider = options.provider ?? "openai";
1704
1719
  const defaults = PROVIDERS[provider];
@@ -1706,6 +1721,7 @@ var OpenAIDescriptionProvider = class {
1706
1721
  this.#apiKey = options.apiKey ?? process.env[this.#apiKeyName] ?? "";
1707
1722
  this.#baseUrl = (options.baseUrl ?? defaults.baseUrl).replace(/\/$/, "");
1708
1723
  this.#openCode = provider !== "openai";
1724
+ this.#verbose = options.verbose ?? false;
1709
1725
  this.profile = {
1710
1726
  provider,
1711
1727
  model: options.model ?? defaults.model,
@@ -1755,6 +1771,7 @@ var OpenAIDescriptionProvider = class {
1755
1771
  throwIfAborted(options?.signal);
1756
1772
  if (!this.#apiKey) throw new CodeIndexError(`${this.#apiKeyName} is required to generate descriptions.`);
1757
1773
  const { model, responses } = await this.#languageModel(headers);
1774
+ reportModelCall("descriptions", this.profile, this.#verbose);
1758
1775
  let text;
1759
1776
  try {
1760
1777
  ({ text } = await generateText({
@@ -1881,7 +1898,8 @@ var CodeIndex = class {
1881
1898
  this.#database = new IndexDatabase(this.indexPath, this.rootDir, profile, options.readOnly ?? false);
1882
1899
  const storedDescriptionProfile = this.#database.descriptionProfile();
1883
1900
  this.descriptionProvider = options.descriptionProvider ?? new OpenAIDescriptionProvider({
1884
- ...storedDescriptionProfile && isDescriptionProviderName(storedDescriptionProfile.provider) ? { provider: storedDescriptionProfile.provider, model: storedDescriptionProfile.model } : {}
1901
+ ...storedDescriptionProfile && isDescriptionProviderName(storedDescriptionProfile.provider) ? { provider: storedDescriptionProfile.provider, model: storedDescriptionProfile.model } : {},
1902
+ ...options.verbose ? { verbose: true } : {}
1885
1903
  });
1886
1904
  this.#policy = new SourcePolicy(options.include, options.exclude);
1887
1905
  this.#maxFileSize = options.maxFileSize ?? DEFAULT_MAX_FILE_SIZE;
@@ -3273,6 +3291,7 @@ function truncateInput(input) {
3273
3291
  var OpenAIEmbeddingProvider = class {
3274
3292
  profile;
3275
3293
  #model;
3294
+ #verbose;
3276
3295
  constructor(options = {}) {
3277
3296
  const apiKey = options.apiKey ?? process.env.OPENAI_API_KEY ?? "";
3278
3297
  if (!apiKey) throw new Error("OPENAI_API_KEY is required.");
@@ -3280,6 +3299,7 @@ var OpenAIEmbeddingProvider = class {
3280
3299
  const dimensions = options.dimensions ?? 3072;
3281
3300
  if (!Number.isInteger(dimensions) || dimensions < 1) throw new Error("dimensions must be a positive integer.");
3282
3301
  this.profile = { provider: "openai", model, dimensions, strategyVersion: "callable-v2" };
3302
+ this.#verbose = options.verbose ?? false;
3283
3303
  this.#model = createOpenAI2({
3284
3304
  apiKey,
3285
3305
  baseURL: (options.baseUrl ?? "https://api.openai.com/v1").replace(/\/$/, "")
@@ -3287,6 +3307,7 @@ var OpenAIEmbeddingProvider = class {
3287
3307
  }
3288
3308
  async embedDocuments(inputs, options) {
3289
3309
  if (inputs.length === 0) return [];
3310
+ reportModelCall("vectors", this.profile, this.#verbose);
3290
3311
  return requestEmbeddings(
3291
3312
  embedMany({
3292
3313
  model: this.#model,
@@ -3299,6 +3320,7 @@ var OpenAIEmbeddingProvider = class {
3299
3320
  );
3300
3321
  }
3301
3322
  async embedQuery(input, options) {
3323
+ reportModelCall("vectors", this.profile, this.#verbose);
3302
3324
  return (await requestEmbeddings(
3303
3325
  embed({
3304
3326
  model: this.#model,
@@ -3319,6 +3341,7 @@ var JinaEmbeddingProvider = class {
3319
3341
  profile;
3320
3342
  #apiKey;
3321
3343
  #baseUrl;
3344
+ #verbose;
3322
3345
  constructor(options = {}) {
3323
3346
  this.#apiKey = options.apiKey ?? process.env.JINA_API_KEY ?? "";
3324
3347
  if (!this.#apiKey) throw new Error("JINA_API_KEY is required.");
@@ -3331,11 +3354,13 @@ var JinaEmbeddingProvider = class {
3331
3354
  dimensions,
3332
3355
  strategyVersion: "callable-v2:code-query-passage"
3333
3356
  };
3357
+ this.#verbose = options.verbose ?? false;
3334
3358
  const url = (options.baseUrl ?? "https://api.jina.ai/v1/embeddings").replace(/\/$/, "");
3335
3359
  this.#baseUrl = url.endsWith("/embeddings") ? url.slice(0, -"/embeddings".length) : url;
3336
3360
  }
3337
3361
  async embedDocuments(inputs, options) {
3338
3362
  if (inputs.length === 0) return [];
3363
+ reportModelCall("vectors", this.profile, this.#verbose);
3339
3364
  return requestEmbeddings(
3340
3365
  embedMany2({
3341
3366
  model: this.#model("code.passage"),
@@ -3348,6 +3373,7 @@ var JinaEmbeddingProvider = class {
3348
3373
  );
3349
3374
  }
3350
3375
  async embedQuery(input, options) {
3376
+ reportModelCall("vectors", this.profile, this.#verbose);
3351
3377
  return (await requestEmbeddings(
3352
3378
  embed2({
3353
3379
  model: this.#model("code.query"),
@@ -3383,12 +3409,14 @@ var HostedReranker = class {
3383
3409
  #apiKey;
3384
3410
  #url;
3385
3411
  #returnDocuments;
3412
+ #verbose;
3386
3413
  constructor(options, settings) {
3387
3414
  this.#apiKey = options.apiKey ?? process.env[settings.apiKeyName] ?? "";
3388
3415
  if (!this.#apiKey) throw new Error(`${settings.apiKeyName} is required.`);
3389
3416
  const model = options.model ?? settings.defaultModel;
3390
3417
  if (!model.trim()) throw new Error("reranker model must not be empty.");
3391
3418
  this.profile = { provider: settings.provider, model };
3419
+ this.#verbose = options.verbose ?? false;
3392
3420
  const url = (options.baseUrl ?? settings.defaultUrl).replace(/\/$/, "");
3393
3421
  this.#url = url.endsWith("/rerank") ? url : `${url}/rerank`;
3394
3422
  this.#returnDocuments = settings.returnDocuments;
@@ -3398,6 +3426,7 @@ var HostedReranker = class {
3398
3426
  const limit = options.limit ?? documents.length;
3399
3427
  assertPositiveInteger(limit, "rerank limit");
3400
3428
  throwIfAborted(options.signal);
3429
+ reportModelCall("reranking", this.profile, this.#verbose);
3401
3430
  let response;
3402
3431
  try {
3403
3432
  response = await fetch(this.#url, {
@@ -3487,9 +3516,11 @@ var OpenAILLMReranker = class {
3487
3516
  maximumCandidateCount = MAX_CANDIDATES;
3488
3517
  #apiKey;
3489
3518
  #baseUrl;
3519
+ #verbose;
3490
3520
  constructor(options = {}) {
3491
3521
  this.#apiKey = options.apiKey ?? process.env.OPENAI_API_KEY ?? "";
3492
3522
  this.#baseUrl = (options.baseUrl ?? "https://api.openai.com/v1").replace(/\/$/, "");
3523
+ this.#verbose = options.verbose ?? false;
3493
3524
  this.candidateCount = options.candidateCount ?? 10;
3494
3525
  assertPositiveInteger(this.candidateCount, "reranker candidate count");
3495
3526
  if (this.candidateCount > MAX_CANDIDATES) {
@@ -3541,6 +3572,7 @@ var OpenAILLMReranker = class {
3541
3572
  document: tokens.length <= candidateTokenLimit ? document : tokenizer2.decode(tokens.slice(0, candidateTokenLimit))
3542
3573
  };
3543
3574
  });
3575
+ reportModelCall("reranking", this.profile, this.#verbose);
3544
3576
  ({ output } = await generateText2({
3545
3577
  model: createOpenAI4({ apiKey: this.#apiKey, baseURL: this.#baseUrl }).responses(this.profile.model),
3546
3578
  prompt: JSON.stringify({