@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/.agents/skills/slopdex/SKILL.md +2 -1
- package/README.md +5 -0
- package/dist/cli.js +62 -11
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.js +33 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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({
|