@ainyc/canonry 1.37.1 → 1.38.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/{chunk-U2ZNKIWK.js → chunk-SAVCFB5B.js} +330 -158
- package/dist/cli.js +49 -50
- package/dist/index.js +1 -1
- package/package.json +8 -8
|
@@ -1878,6 +1878,12 @@ var MIGRATIONS = [
|
|
|
1878
1878
|
`DROP INDEX IF EXISTS idx_ga_ai_ref_unique`,
|
|
1879
1879
|
`CREATE UNIQUE INDEX IF NOT EXISTS idx_ga_ai_ref_unique_v2 ON ga_ai_referrals(project_id, date, source, medium, source_dimension)`
|
|
1880
1880
|
];
|
|
1881
|
+
function isDuplicateColumnError(err) {
|
|
1882
|
+
if (!(err instanceof Error)) return false;
|
|
1883
|
+
if (err.message.includes("duplicate column name")) return true;
|
|
1884
|
+
if (err.cause instanceof Error && err.cause.message.includes("duplicate column name")) return true;
|
|
1885
|
+
return false;
|
|
1886
|
+
}
|
|
1881
1887
|
function migrate(db) {
|
|
1882
1888
|
const statements = MIGRATION_SQL.split(";").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
1883
1889
|
for (const statement of statements) {
|
|
@@ -1886,7 +1892,9 @@ function migrate(db) {
|
|
|
1886
1892
|
for (const migration of MIGRATIONS) {
|
|
1887
1893
|
try {
|
|
1888
1894
|
db.run(sql.raw(migration));
|
|
1889
|
-
} catch {
|
|
1895
|
+
} catch (err) {
|
|
1896
|
+
if (isDuplicateColumnError(err)) continue;
|
|
1897
|
+
throw err;
|
|
1890
1898
|
}
|
|
1891
1899
|
}
|
|
1892
1900
|
}
|
|
@@ -10386,6 +10394,27 @@ async function apiRoutes(app, opts) {
|
|
|
10386
10394
|
|
|
10387
10395
|
// ../provider-gemini/src/normalize.ts
|
|
10388
10396
|
import { GoogleGenAI } from "@google/genai";
|
|
10397
|
+
|
|
10398
|
+
// ../provider-gemini/src/utils.ts
|
|
10399
|
+
async function withRetry(fn, options = {}) {
|
|
10400
|
+
const { maxRetries = 3, initialDelay = 1e3 } = options;
|
|
10401
|
+
let lastError;
|
|
10402
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
10403
|
+
try {
|
|
10404
|
+
return await fn();
|
|
10405
|
+
} catch (err) {
|
|
10406
|
+
lastError = err;
|
|
10407
|
+
if (attempt < maxRetries) {
|
|
10408
|
+
const delay = initialDelay * Math.pow(2, attempt);
|
|
10409
|
+
console.warn(`[provider] Attempt ${attempt + 1} failed, retrying in ${delay}ms...`, err);
|
|
10410
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
10411
|
+
}
|
|
10412
|
+
}
|
|
10413
|
+
}
|
|
10414
|
+
throw lastError;
|
|
10415
|
+
}
|
|
10416
|
+
|
|
10417
|
+
// ../provider-gemini/src/normalize.ts
|
|
10389
10418
|
var DEFAULT_MODEL = "gemini-3-flash";
|
|
10390
10419
|
function isVertexConfig(config) {
|
|
10391
10420
|
return !!config.vertexProject;
|
|
@@ -10434,10 +10463,12 @@ async function healthcheck(config) {
|
|
|
10434
10463
|
try {
|
|
10435
10464
|
const model = resolveModel(config);
|
|
10436
10465
|
const client = createClient2(config);
|
|
10437
|
-
const result = await
|
|
10438
|
-
|
|
10439
|
-
|
|
10440
|
-
|
|
10466
|
+
const result = await withRetry(
|
|
10467
|
+
() => client.models.generateContent({
|
|
10468
|
+
model,
|
|
10469
|
+
contents: 'Say "ok"'
|
|
10470
|
+
})
|
|
10471
|
+
);
|
|
10441
10472
|
const text2 = result.text ?? "";
|
|
10442
10473
|
const backend = isVertexConfig(config) ? "vertex ai" : "api key";
|
|
10443
10474
|
return {
|
|
@@ -10459,22 +10490,29 @@ async function executeTrackedQuery(input) {
|
|
|
10459
10490
|
const model = resolveModel(input.config);
|
|
10460
10491
|
const prompt = buildPrompt(input.keyword, input.location);
|
|
10461
10492
|
const client = createClient2(input.config);
|
|
10462
|
-
|
|
10463
|
-
|
|
10464
|
-
|
|
10465
|
-
|
|
10466
|
-
|
|
10467
|
-
|
|
10468
|
-
|
|
10469
|
-
|
|
10470
|
-
|
|
10471
|
-
|
|
10472
|
-
|
|
10473
|
-
|
|
10474
|
-
|
|
10475
|
-
|
|
10476
|
-
|
|
10477
|
-
|
|
10493
|
+
try {
|
|
10494
|
+
const result = await withRetry(
|
|
10495
|
+
() => client.models.generateContent({
|
|
10496
|
+
model,
|
|
10497
|
+
contents: prompt,
|
|
10498
|
+
config: {
|
|
10499
|
+
tools: [{ googleSearch: {} }]
|
|
10500
|
+
}
|
|
10501
|
+
})
|
|
10502
|
+
);
|
|
10503
|
+
const groundingSources = extractGroundingMetadata(result);
|
|
10504
|
+
const searchQueries = extractSearchQueries(result);
|
|
10505
|
+
return {
|
|
10506
|
+
provider: "gemini",
|
|
10507
|
+
rawResponse: responseToRecord(result),
|
|
10508
|
+
model,
|
|
10509
|
+
groundingSources,
|
|
10510
|
+
searchQueries
|
|
10511
|
+
};
|
|
10512
|
+
} catch (err) {
|
|
10513
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
10514
|
+
throw new Error(`[provider-gemini] ${msg}`);
|
|
10515
|
+
}
|
|
10478
10516
|
}
|
|
10479
10517
|
function normalizeResult(raw) {
|
|
10480
10518
|
const answerText = extractAnswerText(raw.rawResponse);
|
|
@@ -10576,10 +10614,12 @@ function extractDomainFromUri(uri) {
|
|
|
10576
10614
|
async function generateText(prompt, config) {
|
|
10577
10615
|
const model = resolveModel(config);
|
|
10578
10616
|
const client = createClient2(config);
|
|
10579
|
-
const result = await
|
|
10580
|
-
|
|
10581
|
-
|
|
10582
|
-
|
|
10617
|
+
const result = await withRetry(
|
|
10618
|
+
() => client.models.generateContent({
|
|
10619
|
+
model,
|
|
10620
|
+
contents: prompt
|
|
10621
|
+
})
|
|
10622
|
+
);
|
|
10583
10623
|
return result.text ?? "";
|
|
10584
10624
|
}
|
|
10585
10625
|
function responseToRecord(response) {
|
|
@@ -10688,6 +10728,27 @@ var geminiAdapter = {
|
|
|
10688
10728
|
|
|
10689
10729
|
// ../provider-openai/src/normalize.ts
|
|
10690
10730
|
import OpenAI from "openai";
|
|
10731
|
+
|
|
10732
|
+
// ../provider-openai/src/utils.ts
|
|
10733
|
+
async function withRetry2(fn, options = {}) {
|
|
10734
|
+
const { maxRetries = 3, initialDelay = 1e3 } = options;
|
|
10735
|
+
let lastError;
|
|
10736
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
10737
|
+
try {
|
|
10738
|
+
return await fn();
|
|
10739
|
+
} catch (err) {
|
|
10740
|
+
lastError = err;
|
|
10741
|
+
if (attempt < maxRetries) {
|
|
10742
|
+
const delay = initialDelay * Math.pow(2, attempt);
|
|
10743
|
+
console.warn(`[provider] Attempt ${attempt + 1} failed, retrying in ${delay}ms...`, err);
|
|
10744
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
10745
|
+
}
|
|
10746
|
+
}
|
|
10747
|
+
}
|
|
10748
|
+
throw lastError;
|
|
10749
|
+
}
|
|
10750
|
+
|
|
10751
|
+
// ../provider-openai/src/normalize.ts
|
|
10691
10752
|
var DEFAULT_MODEL2 = "gpt-5.4";
|
|
10692
10753
|
function validateConfig2(config) {
|
|
10693
10754
|
if (!config.apiKey || config.apiKey.length === 0) {
|
|
@@ -10705,10 +10766,12 @@ async function healthcheck2(config) {
|
|
|
10705
10766
|
if (!validation.ok) return validation;
|
|
10706
10767
|
try {
|
|
10707
10768
|
const client = new OpenAI({ apiKey: config.apiKey });
|
|
10708
|
-
const response = await
|
|
10709
|
-
|
|
10710
|
-
|
|
10711
|
-
|
|
10769
|
+
const response = await withRetry2(
|
|
10770
|
+
() => client.responses.create({
|
|
10771
|
+
model: config.model ?? DEFAULT_MODEL2,
|
|
10772
|
+
input: 'Say "ok"'
|
|
10773
|
+
})
|
|
10774
|
+
);
|
|
10712
10775
|
const text2 = extractResponseText(response);
|
|
10713
10776
|
return {
|
|
10714
10777
|
ok: text2.length > 0,
|
|
@@ -10738,21 +10801,28 @@ async function executeTrackedQuery2(input) {
|
|
|
10738
10801
|
...input.location.timezone ? { timezone: input.location.timezone } : {}
|
|
10739
10802
|
};
|
|
10740
10803
|
}
|
|
10741
|
-
|
|
10742
|
-
|
|
10743
|
-
|
|
10744
|
-
|
|
10745
|
-
|
|
10746
|
-
|
|
10747
|
-
|
|
10748
|
-
|
|
10749
|
-
|
|
10750
|
-
|
|
10751
|
-
|
|
10752
|
-
|
|
10753
|
-
|
|
10754
|
-
|
|
10755
|
-
|
|
10804
|
+
try {
|
|
10805
|
+
const response = await withRetry2(
|
|
10806
|
+
() => client.responses.create({
|
|
10807
|
+
model,
|
|
10808
|
+
tools: [webSearchTool],
|
|
10809
|
+
tool_choice: "required",
|
|
10810
|
+
input: buildPrompt2(input.keyword)
|
|
10811
|
+
})
|
|
10812
|
+
);
|
|
10813
|
+
const groundingSources = extractGroundingSources(response);
|
|
10814
|
+
const searchQueries = extractSearchQueries2(response);
|
|
10815
|
+
return {
|
|
10816
|
+
provider: "openai",
|
|
10817
|
+
rawResponse: responseToRecord2(response),
|
|
10818
|
+
model,
|
|
10819
|
+
groundingSources,
|
|
10820
|
+
searchQueries
|
|
10821
|
+
};
|
|
10822
|
+
} catch (err) {
|
|
10823
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
10824
|
+
throw new Error(`[provider-openai] ${msg}`);
|
|
10825
|
+
}
|
|
10756
10826
|
}
|
|
10757
10827
|
function normalizeResult2(raw) {
|
|
10758
10828
|
const answerText = extractAnswerTextFromRaw(raw.rawResponse);
|
|
@@ -10863,10 +10933,12 @@ function extractDomainFromUri2(uri) {
|
|
|
10863
10933
|
async function generateText2(prompt, config) {
|
|
10864
10934
|
const model = config.model ?? DEFAULT_MODEL2;
|
|
10865
10935
|
const client = new OpenAI({ apiKey: config.apiKey });
|
|
10866
|
-
const response = await
|
|
10867
|
-
|
|
10868
|
-
|
|
10869
|
-
|
|
10936
|
+
const response = await withRetry2(
|
|
10937
|
+
() => client.responses.create({
|
|
10938
|
+
model,
|
|
10939
|
+
input: prompt
|
|
10940
|
+
})
|
|
10941
|
+
);
|
|
10870
10942
|
return extractResponseText(response);
|
|
10871
10943
|
}
|
|
10872
10944
|
function responseToRecord2(response) {
|
|
@@ -10962,6 +11034,27 @@ var openaiAdapter = {
|
|
|
10962
11034
|
|
|
10963
11035
|
// ../provider-claude/src/normalize.ts
|
|
10964
11036
|
import Anthropic from "@anthropic-ai/sdk";
|
|
11037
|
+
|
|
11038
|
+
// ../provider-claude/src/utils.ts
|
|
11039
|
+
async function withRetry3(fn, options = {}) {
|
|
11040
|
+
const { maxRetries = 3, initialDelay = 1e3 } = options;
|
|
11041
|
+
let lastError;
|
|
11042
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
11043
|
+
try {
|
|
11044
|
+
return await fn();
|
|
11045
|
+
} catch (err) {
|
|
11046
|
+
lastError = err;
|
|
11047
|
+
if (attempt < maxRetries) {
|
|
11048
|
+
const delay = initialDelay * Math.pow(2, attempt);
|
|
11049
|
+
console.warn(`[provider] Attempt ${attempt + 1} failed, retrying in ${delay}ms...`, err);
|
|
11050
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
11051
|
+
}
|
|
11052
|
+
}
|
|
11053
|
+
}
|
|
11054
|
+
throw lastError;
|
|
11055
|
+
}
|
|
11056
|
+
|
|
11057
|
+
// ../provider-claude/src/normalize.ts
|
|
10965
11058
|
var DEFAULT_MODEL3 = "claude-sonnet-4-6";
|
|
10966
11059
|
var VALIDATION_PATTERN = /^claude-/;
|
|
10967
11060
|
function resolveModel2(config) {
|
|
@@ -10992,11 +11085,13 @@ async function healthcheck3(config) {
|
|
|
10992
11085
|
try {
|
|
10993
11086
|
const model = resolveModel2(config);
|
|
10994
11087
|
const client = new Anthropic({ apiKey: config.apiKey });
|
|
10995
|
-
const response = await
|
|
10996
|
-
|
|
10997
|
-
|
|
10998
|
-
|
|
10999
|
-
|
|
11088
|
+
const response = await withRetry3(
|
|
11089
|
+
() => client.messages.create({
|
|
11090
|
+
model,
|
|
11091
|
+
max_tokens: 32,
|
|
11092
|
+
messages: [{ role: "user", content: 'Say "ok"' }]
|
|
11093
|
+
})
|
|
11094
|
+
);
|
|
11000
11095
|
const text2 = extractTextFromResponse(response);
|
|
11001
11096
|
return {
|
|
11002
11097
|
ok: text2.length > 0,
|
|
@@ -11030,21 +11125,28 @@ async function executeTrackedQuery3(input) {
|
|
|
11030
11125
|
...input.location.timezone ? { timezone: input.location.timezone } : {}
|
|
11031
11126
|
};
|
|
11032
11127
|
}
|
|
11033
|
-
|
|
11034
|
-
|
|
11035
|
-
|
|
11036
|
-
|
|
11037
|
-
|
|
11038
|
-
|
|
11039
|
-
|
|
11040
|
-
|
|
11041
|
-
|
|
11042
|
-
|
|
11043
|
-
|
|
11044
|
-
|
|
11045
|
-
|
|
11046
|
-
|
|
11047
|
-
|
|
11128
|
+
try {
|
|
11129
|
+
const response = await withRetry3(
|
|
11130
|
+
() => client.messages.create({
|
|
11131
|
+
model,
|
|
11132
|
+
max_tokens: 4096,
|
|
11133
|
+
tools: [webSearchTool],
|
|
11134
|
+
messages: [{ role: "user", content: input.keyword }]
|
|
11135
|
+
})
|
|
11136
|
+
);
|
|
11137
|
+
const groundingSources = extractGroundingSources2(response);
|
|
11138
|
+
const searchQueries = extractSearchQueries3(response);
|
|
11139
|
+
return {
|
|
11140
|
+
provider: "claude",
|
|
11141
|
+
rawResponse: responseToRecord3(response),
|
|
11142
|
+
model,
|
|
11143
|
+
groundingSources,
|
|
11144
|
+
searchQueries
|
|
11145
|
+
};
|
|
11146
|
+
} catch (err) {
|
|
11147
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
11148
|
+
throw new Error(`[provider-claude] ${msg}`);
|
|
11149
|
+
}
|
|
11048
11150
|
}
|
|
11049
11151
|
function normalizeResult3(raw) {
|
|
11050
11152
|
const answerText = extractAnswerTextFromRaw2(raw.rawResponse);
|
|
@@ -11138,11 +11240,13 @@ function extractDomainFromUri3(uri) {
|
|
|
11138
11240
|
async function generateText3(prompt, config) {
|
|
11139
11241
|
const model = resolveModel2(config);
|
|
11140
11242
|
const client = new Anthropic({ apiKey: config.apiKey });
|
|
11141
|
-
const response = await
|
|
11142
|
-
|
|
11143
|
-
|
|
11144
|
-
|
|
11145
|
-
|
|
11243
|
+
const response = await withRetry3(
|
|
11244
|
+
() => client.messages.create({
|
|
11245
|
+
model,
|
|
11246
|
+
max_tokens: 2048,
|
|
11247
|
+
messages: [{ role: "user", content: prompt }]
|
|
11248
|
+
})
|
|
11249
|
+
);
|
|
11146
11250
|
return extractTextFromResponse(response);
|
|
11147
11251
|
}
|
|
11148
11252
|
function responseToRecord3(response) {
|
|
@@ -11235,6 +11339,27 @@ var claudeAdapter = {
|
|
|
11235
11339
|
|
|
11236
11340
|
// ../provider-local/src/normalize.ts
|
|
11237
11341
|
import OpenAI2 from "openai";
|
|
11342
|
+
|
|
11343
|
+
// ../provider-local/src/utils.ts
|
|
11344
|
+
async function withRetry4(fn, options = {}) {
|
|
11345
|
+
const { maxRetries = 3, initialDelay = 1e3 } = options;
|
|
11346
|
+
let lastError;
|
|
11347
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
11348
|
+
try {
|
|
11349
|
+
return await fn();
|
|
11350
|
+
} catch (err) {
|
|
11351
|
+
lastError = err;
|
|
11352
|
+
if (attempt < maxRetries) {
|
|
11353
|
+
const delay = initialDelay * Math.pow(2, attempt);
|
|
11354
|
+
console.warn(`[provider] Attempt ${attempt + 1} failed, retrying in ${delay}ms...`, err);
|
|
11355
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
11356
|
+
}
|
|
11357
|
+
}
|
|
11358
|
+
}
|
|
11359
|
+
throw lastError;
|
|
11360
|
+
}
|
|
11361
|
+
|
|
11362
|
+
// ../provider-local/src/normalize.ts
|
|
11238
11363
|
var DEFAULT_MODEL4 = "llama3";
|
|
11239
11364
|
function validateConfig4(config) {
|
|
11240
11365
|
if (!config.baseUrl || config.baseUrl.length === 0) {
|
|
@@ -11255,16 +11380,19 @@ async function healthcheck4(config) {
|
|
|
11255
11380
|
baseURL: config.baseUrl,
|
|
11256
11381
|
apiKey: config.apiKey || "not-needed"
|
|
11257
11382
|
});
|
|
11258
|
-
const models = await
|
|
11259
|
-
|
|
11260
|
-
|
|
11261
|
-
|
|
11262
|
-
|
|
11263
|
-
|
|
11383
|
+
const models = await withRetry4(async () => {
|
|
11384
|
+
const list = await client.models.list();
|
|
11385
|
+
const items = [];
|
|
11386
|
+
for await (const m of list) {
|
|
11387
|
+
items.push(m.id);
|
|
11388
|
+
if (items.length >= 5) break;
|
|
11389
|
+
}
|
|
11390
|
+
return items;
|
|
11391
|
+
});
|
|
11264
11392
|
return {
|
|
11265
11393
|
ok: true,
|
|
11266
11394
|
provider: "local",
|
|
11267
|
-
message: `connected, ${
|
|
11395
|
+
message: `connected, ${models.length} model(s) available`,
|
|
11268
11396
|
model: config.model ?? DEFAULT_MODEL4
|
|
11269
11397
|
};
|
|
11270
11398
|
} catch (err) {
|
|
@@ -11282,26 +11410,33 @@ async function executeTrackedQuery4(input) {
|
|
|
11282
11410
|
baseURL: input.config.baseUrl,
|
|
11283
11411
|
apiKey: input.config.apiKey || "not-needed"
|
|
11284
11412
|
});
|
|
11285
|
-
|
|
11286
|
-
|
|
11287
|
-
|
|
11288
|
-
|
|
11289
|
-
|
|
11290
|
-
|
|
11291
|
-
|
|
11292
|
-
|
|
11293
|
-
|
|
11294
|
-
|
|
11295
|
-
|
|
11296
|
-
|
|
11297
|
-
|
|
11298
|
-
|
|
11299
|
-
|
|
11300
|
-
|
|
11301
|
-
|
|
11302
|
-
|
|
11303
|
-
|
|
11304
|
-
|
|
11413
|
+
try {
|
|
11414
|
+
const response = await withRetry4(
|
|
11415
|
+
() => client.chat.completions.create({
|
|
11416
|
+
model,
|
|
11417
|
+
messages: [
|
|
11418
|
+
{
|
|
11419
|
+
role: "system",
|
|
11420
|
+
content: "You are a helpful assistant. Provide comprehensive, factual answers. When mentioning websites or services, include their domain names."
|
|
11421
|
+
},
|
|
11422
|
+
{
|
|
11423
|
+
role: "user",
|
|
11424
|
+
content: buildPrompt3(input.keyword, input.location)
|
|
11425
|
+
}
|
|
11426
|
+
]
|
|
11427
|
+
})
|
|
11428
|
+
);
|
|
11429
|
+
return {
|
|
11430
|
+
provider: "local",
|
|
11431
|
+
rawResponse: responseToRecord4(response),
|
|
11432
|
+
model,
|
|
11433
|
+
groundingSources: [],
|
|
11434
|
+
searchQueries: []
|
|
11435
|
+
};
|
|
11436
|
+
} catch (err) {
|
|
11437
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
11438
|
+
throw new Error(`[provider-local] ${msg}`);
|
|
11439
|
+
}
|
|
11305
11440
|
}
|
|
11306
11441
|
function normalizeResult4(raw) {
|
|
11307
11442
|
const answerText = extractAnswerText2(raw.rawResponse);
|
|
@@ -11333,10 +11468,12 @@ async function generateText4(prompt, config) {
|
|
|
11333
11468
|
baseURL: config.baseUrl,
|
|
11334
11469
|
apiKey: config.apiKey || "not-needed"
|
|
11335
11470
|
});
|
|
11336
|
-
const response = await
|
|
11337
|
-
|
|
11338
|
-
|
|
11339
|
-
|
|
11471
|
+
const response = await withRetry4(
|
|
11472
|
+
() => client.chat.completions.create({
|
|
11473
|
+
model,
|
|
11474
|
+
messages: [{ role: "user", content: prompt }]
|
|
11475
|
+
})
|
|
11476
|
+
);
|
|
11340
11477
|
return response.choices[0]?.message?.content ?? "";
|
|
11341
11478
|
}
|
|
11342
11479
|
function extractDomainMentions(text2) {
|
|
@@ -11952,35 +12089,40 @@ var cdpChatgptAdapter = {
|
|
|
11952
12089
|
async executeTrackedQuery(input, config) {
|
|
11953
12090
|
const conn = getConnection(config);
|
|
11954
12091
|
const target = chatgptTarget;
|
|
11955
|
-
const client = await conn.prepareForQuery(target);
|
|
11956
|
-
await target.submitQuery(client, input.keyword);
|
|
11957
|
-
await target.waitForResponse(client);
|
|
11958
|
-
const answerText = await target.extractAnswer(client);
|
|
11959
|
-
const groundingSources = await target.extractCitations(client);
|
|
11960
|
-
const screenshotId = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
11961
|
-
const screenshotPath = path4.join(getScreenshotDir2(), `${screenshotId}.png`);
|
|
11962
|
-
let capturedScreenshotPath;
|
|
11963
12092
|
try {
|
|
11964
|
-
|
|
11965
|
-
|
|
11966
|
-
|
|
11967
|
-
|
|
11968
|
-
);
|
|
11969
|
-
|
|
11970
|
-
|
|
11971
|
-
|
|
11972
|
-
|
|
11973
|
-
|
|
11974
|
-
|
|
12093
|
+
const client = await conn.prepareForQuery(target);
|
|
12094
|
+
await target.submitQuery(client, input.keyword);
|
|
12095
|
+
await target.waitForResponse(client);
|
|
12096
|
+
const answerText = await target.extractAnswer(client);
|
|
12097
|
+
const groundingSources = await target.extractCitations(client);
|
|
12098
|
+
const screenshotId = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
12099
|
+
const screenshotPath = path4.join(getScreenshotDir2(), `${screenshotId}.png`);
|
|
12100
|
+
let capturedScreenshotPath;
|
|
12101
|
+
try {
|
|
12102
|
+
capturedScreenshotPath = await captureElementScreenshot(
|
|
12103
|
+
client,
|
|
12104
|
+
target.responseSelector,
|
|
12105
|
+
screenshotPath
|
|
12106
|
+
);
|
|
12107
|
+
} catch {
|
|
12108
|
+
}
|
|
12109
|
+
return {
|
|
12110
|
+
provider: "cdp:chatgpt",
|
|
12111
|
+
rawResponse: {
|
|
12112
|
+
answerText,
|
|
12113
|
+
groundingSources,
|
|
12114
|
+
extractedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12115
|
+
targetUrl: target.newConversationUrl
|
|
12116
|
+
},
|
|
12117
|
+
model: "chatgpt-web",
|
|
11975
12118
|
groundingSources,
|
|
11976
|
-
|
|
11977
|
-
|
|
11978
|
-
}
|
|
11979
|
-
|
|
11980
|
-
|
|
11981
|
-
|
|
11982
|
-
|
|
11983
|
-
};
|
|
12119
|
+
searchQueries: [input.keyword],
|
|
12120
|
+
screenshotPath: capturedScreenshotPath
|
|
12121
|
+
};
|
|
12122
|
+
} catch (err) {
|
|
12123
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
12124
|
+
throw new Error(`[provider-cdp] ${msg}`);
|
|
12125
|
+
}
|
|
11984
12126
|
},
|
|
11985
12127
|
normalizeResult(raw) {
|
|
11986
12128
|
return normalizeResult5(raw);
|
|
@@ -11992,6 +12134,27 @@ var cdpChatgptAdapter = {
|
|
|
11992
12134
|
|
|
11993
12135
|
// ../provider-perplexity/src/normalize.ts
|
|
11994
12136
|
import OpenAI3 from "openai";
|
|
12137
|
+
|
|
12138
|
+
// ../provider-perplexity/src/utils.ts
|
|
12139
|
+
async function withRetry5(fn, options = {}) {
|
|
12140
|
+
const { maxRetries = 3, initialDelay = 1e3 } = options;
|
|
12141
|
+
let lastError;
|
|
12142
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
12143
|
+
try {
|
|
12144
|
+
return await fn();
|
|
12145
|
+
} catch (err) {
|
|
12146
|
+
lastError = err;
|
|
12147
|
+
if (attempt < maxRetries) {
|
|
12148
|
+
const delay = initialDelay * Math.pow(2, attempt);
|
|
12149
|
+
console.warn(`[provider] Attempt ${attempt + 1} failed, retrying in ${delay}ms...`, err);
|
|
12150
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
12151
|
+
}
|
|
12152
|
+
}
|
|
12153
|
+
}
|
|
12154
|
+
throw lastError;
|
|
12155
|
+
}
|
|
12156
|
+
|
|
12157
|
+
// ../provider-perplexity/src/normalize.ts
|
|
11995
12158
|
var DEFAULT_MODEL5 = "sonar";
|
|
11996
12159
|
var BASE_URL = "https://api.perplexity.ai";
|
|
11997
12160
|
function validateConfig5(config) {
|
|
@@ -12010,10 +12173,12 @@ async function healthcheck5(config) {
|
|
|
12010
12173
|
if (!validation.ok) return validation;
|
|
12011
12174
|
try {
|
|
12012
12175
|
const client = new OpenAI3({ apiKey: config.apiKey, baseURL: BASE_URL });
|
|
12013
|
-
const response = await
|
|
12014
|
-
|
|
12015
|
-
|
|
12016
|
-
|
|
12176
|
+
const response = await withRetry5(
|
|
12177
|
+
() => client.chat.completions.create({
|
|
12178
|
+
model: config.model ?? DEFAULT_MODEL5,
|
|
12179
|
+
messages: [{ role: "user", content: 'Say "ok"' }]
|
|
12180
|
+
})
|
|
12181
|
+
);
|
|
12017
12182
|
const text2 = response.choices[0]?.message?.content ?? "";
|
|
12018
12183
|
return {
|
|
12019
12184
|
ok: text2.length > 0,
|
|
@@ -12034,25 +12199,30 @@ async function executeTrackedQuery5(input) {
|
|
|
12034
12199
|
const model = input.config.model ?? DEFAULT_MODEL5;
|
|
12035
12200
|
const client = new OpenAI3({ apiKey: input.config.apiKey, baseURL: BASE_URL });
|
|
12036
12201
|
const prompt = buildPrompt4(input.keyword, input.location);
|
|
12037
|
-
|
|
12038
|
-
|
|
12039
|
-
|
|
12040
|
-
|
|
12041
|
-
|
|
12042
|
-
|
|
12043
|
-
|
|
12044
|
-
|
|
12045
|
-
|
|
12046
|
-
|
|
12047
|
-
|
|
12048
|
-
|
|
12049
|
-
|
|
12050
|
-
|
|
12051
|
-
|
|
12052
|
-
|
|
12053
|
-
|
|
12054
|
-
|
|
12055
|
-
|
|
12202
|
+
try {
|
|
12203
|
+
const response = await withRetry5(
|
|
12204
|
+
() => client.chat.completions.create({
|
|
12205
|
+
model,
|
|
12206
|
+
messages: [{ role: "user", content: prompt }]
|
|
12207
|
+
})
|
|
12208
|
+
);
|
|
12209
|
+
const rawResponse = responseToRecord5(response);
|
|
12210
|
+
const citations = extractCitations(rawResponse);
|
|
12211
|
+
const groundingSources = citations.map((url) => ({
|
|
12212
|
+
uri: url,
|
|
12213
|
+
title: ""
|
|
12214
|
+
}));
|
|
12215
|
+
return {
|
|
12216
|
+
provider: "perplexity",
|
|
12217
|
+
rawResponse,
|
|
12218
|
+
model,
|
|
12219
|
+
groundingSources,
|
|
12220
|
+
searchQueries: [input.keyword]
|
|
12221
|
+
};
|
|
12222
|
+
} catch (err) {
|
|
12223
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
12224
|
+
throw new Error(`[provider-perplexity] ${msg}`);
|
|
12225
|
+
}
|
|
12056
12226
|
}
|
|
12057
12227
|
function normalizeResult6(raw) {
|
|
12058
12228
|
const answerText = extractAnswerText3(raw.rawResponse);
|
|
@@ -12112,10 +12282,12 @@ function extractDomainFromUri4(uri) {
|
|
|
12112
12282
|
async function generateText5(prompt, config) {
|
|
12113
12283
|
const model = config.model ?? DEFAULT_MODEL5;
|
|
12114
12284
|
const client = new OpenAI3({ apiKey: config.apiKey, baseURL: BASE_URL });
|
|
12115
|
-
const response = await
|
|
12116
|
-
|
|
12117
|
-
|
|
12118
|
-
|
|
12285
|
+
const response = await withRetry5(
|
|
12286
|
+
() => client.chat.completions.create({
|
|
12287
|
+
model,
|
|
12288
|
+
messages: [{ role: "user", content: prompt }]
|
|
12289
|
+
})
|
|
12290
|
+
);
|
|
12119
12291
|
return response.choices[0]?.message?.content ?? "";
|
|
12120
12292
|
}
|
|
12121
12293
|
function responseToRecord5(response) {
|
package/dist/cli.js
CHANGED
|
@@ -26,22 +26,26 @@ import {
|
|
|
26
26
|
setGoogleAuthConfig,
|
|
27
27
|
showFirstRunNotice,
|
|
28
28
|
trackEvent
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-SAVCFB5B.js";
|
|
30
30
|
|
|
31
31
|
// src/cli.ts
|
|
32
32
|
import { pathToFileURL } from "url";
|
|
33
33
|
|
|
34
34
|
// src/cli-error.ts
|
|
35
|
+
var EXIT_USER_ERROR = 1;
|
|
36
|
+
var EXIT_SYSTEM_ERROR = 2;
|
|
35
37
|
var CliError = class extends Error {
|
|
36
38
|
code;
|
|
37
39
|
displayMessage;
|
|
38
40
|
details;
|
|
41
|
+
exitCode;
|
|
39
42
|
constructor(options) {
|
|
40
43
|
super(options.message);
|
|
41
44
|
this.name = "CliError";
|
|
42
45
|
this.code = options.code;
|
|
43
46
|
this.displayMessage = options.displayMessage;
|
|
44
47
|
this.details = options.details;
|
|
48
|
+
this.exitCode = options.exitCode ?? EXIT_USER_ERROR;
|
|
45
49
|
}
|
|
46
50
|
};
|
|
47
51
|
function usageError(displayMessage, options) {
|
|
@@ -398,13 +402,16 @@ var ApiClient = class {
|
|
|
398
402
|
body: serializedBody
|
|
399
403
|
});
|
|
400
404
|
} catch (err) {
|
|
405
|
+
if (err instanceof CliError) throw err;
|
|
401
406
|
const msg = err instanceof Error ? err.message : String(err);
|
|
402
407
|
if (msg.includes("fetch failed") || msg.includes("ECONNREFUSED") || msg.includes("connect ECONNREFUSED")) {
|
|
403
|
-
throw new
|
|
404
|
-
|
|
405
|
-
|
|
408
|
+
throw new CliError({
|
|
409
|
+
code: "CONNECTION_ERROR",
|
|
410
|
+
message: `Could not connect to canonry server at ${this.baseUrl.replace("/api/v1", "")}. Start it with "canonry serve" (or "canonry serve &" to run in background).`,
|
|
411
|
+
exitCode: EXIT_SYSTEM_ERROR
|
|
412
|
+
});
|
|
406
413
|
}
|
|
407
|
-
throw
|
|
414
|
+
throw new CliError({ code: "CONNECTION_ERROR", message: msg, exitCode: EXIT_SYSTEM_ERROR });
|
|
408
415
|
}
|
|
409
416
|
if (!res.ok) {
|
|
410
417
|
let errorBody;
|
|
@@ -413,8 +420,11 @@ var ApiClient = class {
|
|
|
413
420
|
} catch {
|
|
414
421
|
errorBody = { error: { code: "UNKNOWN", message: res.statusText } };
|
|
415
422
|
}
|
|
416
|
-
const
|
|
417
|
-
|
|
423
|
+
const errorObj = errorBody && typeof errorBody === "object" && "error" in errorBody && errorBody.error && typeof errorBody.error === "object" ? errorBody.error : null;
|
|
424
|
+
const msg = errorObj?.message ? String(errorObj.message) : `HTTP ${res.status}: ${res.statusText}`;
|
|
425
|
+
const code = errorObj?.code ? String(errorObj.code) : "API_ERROR";
|
|
426
|
+
const exitCode = res.status >= 500 ? EXIT_SYSTEM_ERROR : EXIT_USER_ERROR;
|
|
427
|
+
throw new CliError({ code, message: msg, exitCode });
|
|
418
428
|
}
|
|
419
429
|
if (res.status === 204) {
|
|
420
430
|
return void 0;
|
|
@@ -751,22 +761,12 @@ function getClient() {
|
|
|
751
761
|
return createApiClient();
|
|
752
762
|
}
|
|
753
763
|
async function bingConnect(project, opts) {
|
|
754
|
-
|
|
755
|
-
if (!apiKey) {
|
|
756
|
-
const readline2 = await import("readline");
|
|
757
|
-
const rl = readline2.createInterface({ input: process.stdin, output: process.stderr });
|
|
758
|
-
apiKey = await new Promise((resolve) => {
|
|
759
|
-
rl.question("Bing Webmaster Tools API key: ", (answer) => {
|
|
760
|
-
rl.close();
|
|
761
|
-
resolve(answer.trim());
|
|
762
|
-
});
|
|
763
|
-
});
|
|
764
|
-
}
|
|
764
|
+
const apiKey = opts?.apiKey;
|
|
765
765
|
if (!apiKey) {
|
|
766
766
|
throw new CliError({
|
|
767
767
|
code: "BING_API_KEY_REQUIRED",
|
|
768
|
-
message: "API key is required
|
|
769
|
-
displayMessage: "Error: API key is required
|
|
768
|
+
message: "API key is required. Pass --api-key <key>.",
|
|
769
|
+
displayMessage: "Error: API key is required. Pass --api-key <key>.",
|
|
770
770
|
details: {
|
|
771
771
|
project
|
|
772
772
|
}
|
|
@@ -3287,13 +3287,13 @@ async function showStatus(project, format) {
|
|
|
3287
3287
|
console.log(JSON.stringify({ project: projectData, runs: runs2 }, null, 2));
|
|
3288
3288
|
return;
|
|
3289
3289
|
}
|
|
3290
|
-
console.log(`Status: ${projectData.displayName} (${projectData.name})
|
|
3290
|
+
console.log(`Status: ${projectData.displayName ?? projectData.name} (${projectData.name})
|
|
3291
3291
|
`);
|
|
3292
3292
|
console.log(` Domain: ${projectData.canonicalDomain}`);
|
|
3293
3293
|
console.log(` Country: ${projectData.country}`);
|
|
3294
3294
|
console.log(` Language: ${projectData.language}`);
|
|
3295
3295
|
if (runs2.length > 0) {
|
|
3296
|
-
const latest = runs2[
|
|
3296
|
+
const latest = runs2[0];
|
|
3297
3297
|
console.log(`
|
|
3298
3298
|
Latest run:`);
|
|
3299
3299
|
console.log(` ID: ${latest.id}`);
|
|
@@ -3313,25 +3313,25 @@ async function showStatus(project, format) {
|
|
|
3313
3313
|
var OPERATOR_CLI_COMMANDS = [
|
|
3314
3314
|
{
|
|
3315
3315
|
path: ["status"],
|
|
3316
|
-
usage: "canonry status <project>",
|
|
3316
|
+
usage: "canonry status <project> [--format json]",
|
|
3317
3317
|
run: async (input) => {
|
|
3318
|
-
const project = requireProject(input, "status", "canonry status <project>");
|
|
3318
|
+
const project = requireProject(input, "status", "canonry status <project> [--format json]");
|
|
3319
3319
|
await showStatus(project, input.format);
|
|
3320
3320
|
}
|
|
3321
3321
|
},
|
|
3322
3322
|
{
|
|
3323
3323
|
path: ["evidence"],
|
|
3324
|
-
usage: "canonry evidence <project>",
|
|
3324
|
+
usage: "canonry evidence <project> [--format json]",
|
|
3325
3325
|
run: async (input) => {
|
|
3326
|
-
const project = requireProject(input, "evidence", "canonry evidence <project>");
|
|
3326
|
+
const project = requireProject(input, "evidence", "canonry evidence <project> [--format json]");
|
|
3327
3327
|
await showEvidence(project, input.format);
|
|
3328
3328
|
}
|
|
3329
3329
|
},
|
|
3330
3330
|
{
|
|
3331
3331
|
path: ["history"],
|
|
3332
|
-
usage: "canonry history <project>",
|
|
3332
|
+
usage: "canonry history <project> [--format json]",
|
|
3333
3333
|
run: async (input) => {
|
|
3334
|
-
const project = requireProject(input, "history", "canonry history <project>");
|
|
3334
|
+
const project = requireProject(input, "history", "canonry history <project> [--format json]");
|
|
3335
3335
|
await showHistory(project, input.format);
|
|
3336
3336
|
}
|
|
3337
3337
|
},
|
|
@@ -3437,7 +3437,7 @@ async function showProject(name, format) {
|
|
|
3437
3437
|
console.log(JSON.stringify(project, null, 2));
|
|
3438
3438
|
return;
|
|
3439
3439
|
}
|
|
3440
|
-
console.log(`Project: ${project.displayName}
|
|
3440
|
+
console.log(`Project: ${project.displayName ?? project.name}
|
|
3441
3441
|
`);
|
|
3442
3442
|
console.log(` Name: ${project.name}`);
|
|
3443
3443
|
console.log(` ID: ${project.id}`);
|
|
@@ -3453,8 +3453,8 @@ async function showProject(name, format) {
|
|
|
3453
3453
|
console.log(` Tags: ${project.tags.length > 0 ? project.tags.join(", ") : "(none)"}`);
|
|
3454
3454
|
const labelEntries = Object.entries(project.labels);
|
|
3455
3455
|
console.log(` Labels: ${labelEntries.length > 0 ? labelEntries.map(([k, v]) => `${k}=${v}`).join(", ") : "(none)"}`);
|
|
3456
|
-
console.log(` Created: ${project.createdAt}`);
|
|
3457
|
-
console.log(` Updated: ${project.updatedAt}`);
|
|
3456
|
+
if (project.createdAt) console.log(` Created: ${project.createdAt}`);
|
|
3457
|
+
if (project.updatedAt) console.log(` Updated: ${project.updatedAt}`);
|
|
3458
3458
|
}
|
|
3459
3459
|
async function updateProjectSettings(name, opts) {
|
|
3460
3460
|
const client = getClient12();
|
|
@@ -3469,7 +3469,7 @@ async function updateProjectSettings(name, opts) {
|
|
|
3469
3469
|
ownedDomains = ownedDomains.filter((d) => !toRemove.has(d));
|
|
3470
3470
|
}
|
|
3471
3471
|
const result = await client.putProject(name, {
|
|
3472
|
-
displayName: opts.displayName ?? project.displayName,
|
|
3472
|
+
displayName: opts.displayName ?? project.displayName ?? project.name,
|
|
3473
3473
|
canonicalDomain: opts.domain ?? project.canonicalDomain,
|
|
3474
3474
|
ownedDomains,
|
|
3475
3475
|
country: opts.country ?? project.country,
|
|
@@ -5454,6 +5454,15 @@ async function serveCommand(format = "text") {
|
|
|
5454
5454
|
const db = createClient(config.database);
|
|
5455
5455
|
migrate(db);
|
|
5456
5456
|
const app = await createServer({ config, db });
|
|
5457
|
+
const shutdown = () => {
|
|
5458
|
+
app.close().then(() => {
|
|
5459
|
+
process.exit(0);
|
|
5460
|
+
}).catch(() => {
|
|
5461
|
+
process.exit(1);
|
|
5462
|
+
});
|
|
5463
|
+
};
|
|
5464
|
+
process.on("SIGTERM", shutdown);
|
|
5465
|
+
process.on("SIGINT", shutdown);
|
|
5457
5466
|
try {
|
|
5458
5467
|
await app.listen({ host, port });
|
|
5459
5468
|
const url = `http://${host === "0.0.0.0" ? "localhost" : host}:${port}`;
|
|
@@ -5758,16 +5767,6 @@ import fs6 from "fs";
|
|
|
5758
5767
|
function getClient17() {
|
|
5759
5768
|
return createApiClient();
|
|
5760
5769
|
}
|
|
5761
|
-
async function promptForAppPassword() {
|
|
5762
|
-
const readline2 = await import("readline");
|
|
5763
|
-
const rl = readline2.createInterface({ input: process.stdin, output: process.stderr });
|
|
5764
|
-
return new Promise((resolve) => {
|
|
5765
|
-
rl.question("WordPress Application Password: ", (answer) => {
|
|
5766
|
-
rl.close();
|
|
5767
|
-
resolve(answer.trim());
|
|
5768
|
-
});
|
|
5769
|
-
});
|
|
5770
|
-
}
|
|
5771
5770
|
function printJson(value) {
|
|
5772
5771
|
console.log(JSON.stringify(value, null, 2));
|
|
5773
5772
|
}
|
|
@@ -5903,12 +5902,12 @@ Staging:`);
|
|
|
5903
5902
|
console.log(` Snippet: ${diff.staging.contentSnippet || "(empty)"}`);
|
|
5904
5903
|
}
|
|
5905
5904
|
async function wordpressConnect(project, opts) {
|
|
5906
|
-
const appPassword = opts.appPassword
|
|
5905
|
+
const appPassword = opts.appPassword;
|
|
5907
5906
|
if (!appPassword) {
|
|
5908
5907
|
throw new CliError({
|
|
5909
5908
|
code: "WORDPRESS_APP_PASSWORD_REQUIRED",
|
|
5910
5909
|
message: "WordPress Application Password is required",
|
|
5911
|
-
displayMessage: "Error: WordPress Application Password is required
|
|
5910
|
+
displayMessage: "Error: WordPress Application Password is required. Pass --app-password <password>.",
|
|
5912
5911
|
details: { project }
|
|
5913
5912
|
});
|
|
5914
5913
|
}
|
|
@@ -6200,12 +6199,12 @@ async function wordpressSchemaStatus(project, opts) {
|
|
|
6200
6199
|
}
|
|
6201
6200
|
}
|
|
6202
6201
|
async function wordpressOnboard(project, opts) {
|
|
6203
|
-
const appPassword = opts.appPassword
|
|
6202
|
+
const appPassword = opts.appPassword;
|
|
6204
6203
|
if (!appPassword) {
|
|
6205
6204
|
throw new CliError({
|
|
6206
6205
|
code: "WORDPRESS_APP_PASSWORD_REQUIRED",
|
|
6207
6206
|
message: "WordPress Application Password is required",
|
|
6208
|
-
displayMessage: "Error: WordPress Application Password is required
|
|
6207
|
+
displayMessage: "Error: WordPress Application Password is required. Pass --app-password <password>.",
|
|
6209
6208
|
details: { project }
|
|
6210
6209
|
});
|
|
6211
6210
|
}
|
|
@@ -6857,10 +6856,10 @@ Usage:
|
|
|
6857
6856
|
canonry run --all Trigger runs for all projects
|
|
6858
6857
|
canonry run show <id> Show run details and snapshots
|
|
6859
6858
|
canonry runs <project> List runs for a project (--limit <n>)
|
|
6860
|
-
canonry status <project> Show project summary
|
|
6861
|
-
canonry evidence <project> Show per-phrase results
|
|
6859
|
+
canonry status <project> Show project summary [--format json]
|
|
6860
|
+
canonry evidence <project> Show per-phrase results [--format json]
|
|
6862
6861
|
canonry analytics <project> Show analytics (--feature metrics|gaps|sources, --window 7d|30d|90d|all)
|
|
6863
|
-
canonry history <project> Show audit trail
|
|
6862
|
+
canonry history <project> Show audit trail [--format json]
|
|
6864
6863
|
canonry export <project> Export project as YAML
|
|
6865
6864
|
canonry apply <file...> Apply declarative config (multi-doc YAML supported)
|
|
6866
6865
|
canonry schedule set <project> Set schedule (--preset or --cron)
|
|
@@ -7019,7 +7018,7 @@ Run "canonry --help" for usage.`, {
|
|
|
7019
7018
|
});
|
|
7020
7019
|
} catch (err) {
|
|
7021
7020
|
printCliError(err, format);
|
|
7022
|
-
return
|
|
7021
|
+
return err instanceof CliError ? err.exitCode : EXIT_SYSTEM_ERROR;
|
|
7023
7022
|
}
|
|
7024
7023
|
}
|
|
7025
7024
|
async function main(args = process.argv.slice(2)) {
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ainyc/canonry",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.38.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The ultimate open-source AEO monitoring tool - track how answer engines cite your domain",
|
|
6
6
|
"license": "FSL-1.1-ALv2",
|
|
@@ -55,18 +55,18 @@
|
|
|
55
55
|
"tsup": "^8.5.1",
|
|
56
56
|
"tsx": "^4.19.0",
|
|
57
57
|
"@ainyc/canonry-api-routes": "0.0.0",
|
|
58
|
-
"@ainyc/canonry-contracts": "0.0.0",
|
|
59
58
|
"@ainyc/canonry-integration-google": "0.0.0",
|
|
60
59
|
"@ainyc/canonry-db": "0.0.0",
|
|
61
|
-
"@ainyc/canonry-config": "0.0.0",
|
|
62
|
-
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
63
60
|
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
64
|
-
"@ainyc/canonry-
|
|
65
|
-
"@ainyc/canonry-
|
|
66
|
-
"@ainyc/canonry-
|
|
61
|
+
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
62
|
+
"@ainyc/canonry-contracts": "0.0.0",
|
|
63
|
+
"@ainyc/canonry-config": "0.0.0",
|
|
67
64
|
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
65
|
+
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
68
66
|
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
69
|
-
"@ainyc/canonry-provider-
|
|
67
|
+
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
68
|
+
"@ainyc/canonry-provider-perplexity": "0.0.0",
|
|
69
|
+
"@ainyc/canonry-provider-local": "0.0.0"
|
|
70
70
|
},
|
|
71
71
|
"scripts": {
|
|
72
72
|
"build": "tsup && tsx build-web.ts",
|