@ainyc/canonry 1.10.1 → 1.11.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/README.md +26 -2
- package/assets/assets/index-CVK9fWdD.css +1 -0
- package/assets/assets/index-DnEgRRTR.js +243 -0
- package/assets/index.html +2 -2
- package/dist/{chunk-2DC7RBXJ.js → chunk-MVIL2UGM.js} +262 -97
- package/dist/cli.js +99 -13
- package/dist/index.d.ts +19 -0
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/assets/assets/index-BDoQOjXO.js +0 -243
- package/assets/assets/index-Dhvjw6Lo.css +0 -1
package/dist/cli.js
CHANGED
|
@@ -16,9 +16,10 @@ import {
|
|
|
16
16
|
notificationEventSchema,
|
|
17
17
|
providerQuotaPolicySchema,
|
|
18
18
|
saveConfig,
|
|
19
|
+
setGoogleAuthConfig,
|
|
19
20
|
showFirstRunNotice,
|
|
20
21
|
trackEvent
|
|
21
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-MVIL2UGM.js";
|
|
22
23
|
|
|
23
24
|
// src/cli.ts
|
|
24
25
|
import { parseArgs } from "util";
|
|
@@ -159,6 +160,14 @@ async function bootstrapCommand(_opts) {
|
|
|
159
160
|
if (providers?.openai) mergedProviders.openai = providers.openai;
|
|
160
161
|
if (providers?.claude) mergedProviders.claude = providers.claude;
|
|
161
162
|
if (providers?.local) mergedProviders.local = providers.local;
|
|
163
|
+
if (env.googleClientId && !env.googleClientSecret || !env.googleClientId && env.googleClientSecret) {
|
|
164
|
+
console.warn("Warning: GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET must both be set to configure Google OAuth. Skipping Google auth config.");
|
|
165
|
+
}
|
|
166
|
+
const mergedGoogle = env.googleClientId && env.googleClientSecret ? {
|
|
167
|
+
clientId: env.googleClientId,
|
|
168
|
+
clientSecret: env.googleClientSecret,
|
|
169
|
+
connections: existingConfig?.google?.connections ?? []
|
|
170
|
+
} : existingConfig?.google;
|
|
162
171
|
const keyHash = crypto.createHash("sha256").update(rawApiKey).digest("hex");
|
|
163
172
|
const keyPrefix = rawApiKey.slice(0, 9);
|
|
164
173
|
const db = createClient(databasePath);
|
|
@@ -176,7 +185,8 @@ async function bootstrapCommand(_opts) {
|
|
|
176
185
|
apiUrl: env.apiUrl || existingConfig?.apiUrl || `http://localhost:${process.env.CANONRY_PORT || "4100"}`,
|
|
177
186
|
database: databasePath,
|
|
178
187
|
apiKey: rawApiKey,
|
|
179
|
-
providers: mergedProviders
|
|
188
|
+
providers: mergedProviders,
|
|
189
|
+
google: mergedGoogle
|
|
180
190
|
});
|
|
181
191
|
console.log(`Bootstrap complete. Config saved to ${getConfigPath()}`);
|
|
182
192
|
console.log(`SQLite database path: ${databasePath}`);
|
|
@@ -218,23 +228,40 @@ async function initCommand(opts) {
|
|
|
218
228
|
if (!fs.existsSync(configDir)) {
|
|
219
229
|
fs.mkdirSync(configDir, { recursive: true });
|
|
220
230
|
}
|
|
221
|
-
const
|
|
231
|
+
const bootstrapEnv = getBootstrapEnv(process.env, {
|
|
222
232
|
GEMINI_API_KEY: opts?.geminiKey,
|
|
223
233
|
OPENAI_API_KEY: opts?.openaiKey,
|
|
224
234
|
ANTHROPIC_API_KEY: opts?.claudeKey,
|
|
225
235
|
LOCAL_BASE_URL: opts?.localUrl,
|
|
226
236
|
LOCAL_MODEL: opts?.localModel,
|
|
227
|
-
LOCAL_API_KEY: opts?.localKey
|
|
228
|
-
|
|
229
|
-
|
|
237
|
+
LOCAL_API_KEY: opts?.localKey,
|
|
238
|
+
GOOGLE_CLIENT_ID: opts?.googleClientId,
|
|
239
|
+
GOOGLE_CLIENT_SECRET: opts?.googleClientSecret
|
|
240
|
+
});
|
|
241
|
+
if (bootstrapEnv.googleClientId && !bootstrapEnv.googleClientSecret || !bootstrapEnv.googleClientId && bootstrapEnv.googleClientSecret) {
|
|
242
|
+
console.error("Google OAuth requires both a client ID and client secret when configured non-interactively.");
|
|
243
|
+
process.exit(1);
|
|
244
|
+
}
|
|
245
|
+
const envProviders = bootstrapEnv.providers;
|
|
246
|
+
const envGoogleConfigured = !!(bootstrapEnv.googleClientId && bootstrapEnv.googleClientSecret);
|
|
247
|
+
const nonInteractive = !!(envProviders.gemini || envProviders.openai || envProviders.claude || envProviders.local || envGoogleConfigured);
|
|
230
248
|
const providers = {};
|
|
249
|
+
let google;
|
|
231
250
|
if (nonInteractive) {
|
|
232
251
|
Object.assign(providers, envProviders);
|
|
252
|
+
if (envGoogleConfigured) {
|
|
253
|
+
google = {
|
|
254
|
+
clientId: bootstrapEnv.googleClientId,
|
|
255
|
+
clientSecret: bootstrapEnv.googleClientSecret,
|
|
256
|
+
connections: []
|
|
257
|
+
};
|
|
258
|
+
}
|
|
233
259
|
} else {
|
|
234
260
|
console.log("Configure AI providers (at least one required):\n");
|
|
235
|
-
console.log("Tip: For non-interactive setup, pass
|
|
236
|
-
console.log("
|
|
237
|
-
console.log(
|
|
261
|
+
console.log("Tip: For non-interactive setup, pass provider flags or set");
|
|
262
|
+
console.log("GEMINI_API_KEY, OPENAI_API_KEY, ANTHROPIC_API_KEY,");
|
|
263
|
+
console.log("GOOGLE_CLIENT_ID, and GOOGLE_CLIENT_SECRET env vars.");
|
|
264
|
+
console.log('Or use "canonry bootstrap".\n');
|
|
238
265
|
const geminiApiKey = await prompt("Gemini API key (press Enter to skip): ");
|
|
239
266
|
if (geminiApiKey) {
|
|
240
267
|
const geminiModel = await prompt(" Gemini model [gemini-2.5-flash]: ") || "gemini-2.5-flash";
|
|
@@ -257,6 +284,20 @@ async function initCommand(opts) {
|
|
|
257
284
|
const localApiKey = await prompt(" API key (press Enter if not needed): ") || void 0;
|
|
258
285
|
providers.local = { baseUrl: localBaseUrl, apiKey: localApiKey, model: localModel, quota: DEFAULT_QUOTA };
|
|
259
286
|
}
|
|
287
|
+
console.log("\nGoogle Search Console OAuth (optional):");
|
|
288
|
+
const googleClientId = await prompt("Google OAuth client ID (press Enter to skip): ");
|
|
289
|
+
if (googleClientId) {
|
|
290
|
+
const googleClientSecret = await prompt(" Google OAuth client secret: ");
|
|
291
|
+
if (!googleClientSecret) {
|
|
292
|
+
console.error("\nGoogle OAuth client secret is required when a client ID is provided.");
|
|
293
|
+
process.exit(1);
|
|
294
|
+
}
|
|
295
|
+
google = {
|
|
296
|
+
clientId: googleClientId,
|
|
297
|
+
clientSecret: googleClientSecret,
|
|
298
|
+
connections: []
|
|
299
|
+
};
|
|
300
|
+
}
|
|
260
301
|
}
|
|
261
302
|
const hasProvider = providers.gemini || providers.openai || providers.claude || providers.local;
|
|
262
303
|
if (!hasProvider) {
|
|
@@ -281,7 +322,8 @@ async function initCommand(opts) {
|
|
|
281
322
|
apiUrl: "http://localhost:4100",
|
|
282
323
|
database: databasePath,
|
|
283
324
|
apiKey: rawApiKey,
|
|
284
|
-
providers
|
|
325
|
+
providers,
|
|
326
|
+
google
|
|
285
327
|
});
|
|
286
328
|
const providerNames = Object.keys(providers);
|
|
287
329
|
console.log(`
|
|
@@ -1109,9 +1151,15 @@ async function setProvider(name, opts) {
|
|
|
1109
1151
|
}
|
|
1110
1152
|
async function showSettings(format) {
|
|
1111
1153
|
const client = getClient8();
|
|
1154
|
+
const config = loadConfig();
|
|
1112
1155
|
const settings = await client.getSettings();
|
|
1113
1156
|
if (format === "json") {
|
|
1114
|
-
console.log(JSON.stringify(
|
|
1157
|
+
console.log(JSON.stringify({
|
|
1158
|
+
...settings,
|
|
1159
|
+
google: {
|
|
1160
|
+
configured: Boolean(config.google?.clientId && config.google?.clientSecret)
|
|
1161
|
+
}
|
|
1162
|
+
}, null, 2));
|
|
1115
1163
|
return;
|
|
1116
1164
|
}
|
|
1117
1165
|
console.log("Provider settings:\n");
|
|
@@ -1125,6 +1173,18 @@ async function showSettings(format) {
|
|
|
1125
1173
|
}
|
|
1126
1174
|
}
|
|
1127
1175
|
}
|
|
1176
|
+
console.log("\nGoogle OAuth:\n");
|
|
1177
|
+
console.log(` ${config.google?.clientId && config.google?.clientSecret ? "configured" : "not configured"}`);
|
|
1178
|
+
}
|
|
1179
|
+
function setGoogleAuth(opts) {
|
|
1180
|
+
const config = loadConfig();
|
|
1181
|
+
setGoogleAuthConfig(config, {
|
|
1182
|
+
clientId: opts.clientId,
|
|
1183
|
+
clientSecret: opts.clientSecret
|
|
1184
|
+
});
|
|
1185
|
+
saveConfig(config);
|
|
1186
|
+
console.log(`Google OAuth credentials saved to ${getConfigPath()}.`);
|
|
1187
|
+
console.log("Restart the local server if it is already running.");
|
|
1128
1188
|
}
|
|
1129
1189
|
|
|
1130
1190
|
// src/commands/schedule.ts
|
|
@@ -1590,6 +1650,7 @@ Usage:
|
|
|
1590
1650
|
canonry google deindexed <project> Show pages that lost indexing
|
|
1591
1651
|
canonry settings Show active provider and quota settings
|
|
1592
1652
|
canonry settings provider <name> Update a provider config
|
|
1653
|
+
canonry settings google Update Google OAuth credentials
|
|
1593
1654
|
canonry telemetry status Show telemetry status
|
|
1594
1655
|
canonry telemetry enable Enable anonymous telemetry
|
|
1595
1656
|
canonry telemetry disable Disable anonymous telemetry
|
|
@@ -1603,6 +1664,8 @@ Options:
|
|
|
1603
1664
|
--local-url <url> Local LLM base URL (or LOCAL_BASE_URL env var)
|
|
1604
1665
|
--local-model <name> Local LLM model name (default: llama3)
|
|
1605
1666
|
--local-key <key> Local LLM API key (or LOCAL_API_KEY env var)
|
|
1667
|
+
--google-client-id <id> Google OAuth client ID (or GOOGLE_CLIENT_ID env var)
|
|
1668
|
+
--google-client-secret <key> Google OAuth client secret (or GOOGLE_CLIENT_SECRET env var)
|
|
1606
1669
|
--port <port> Server port (default: 4100)
|
|
1607
1670
|
--host <host> Server bind address (default: 127.0.0.1)
|
|
1608
1671
|
--domain <domain> Canonical domain for project create/update
|
|
@@ -1625,6 +1688,8 @@ Options:
|
|
|
1625
1688
|
--api-key <key> Provider API key (settings provider)
|
|
1626
1689
|
--base-url <url> Provider base URL (settings provider)
|
|
1627
1690
|
--model <name> Provider model name (settings provider)
|
|
1691
|
+
--client-id <id> Google OAuth client ID (settings google)
|
|
1692
|
+
--client-secret <key> Google OAuth client secret (settings google)
|
|
1628
1693
|
--max-concurrent <n> Max concurrent requests per provider
|
|
1629
1694
|
--max-per-minute <n> Max requests per minute per provider
|
|
1630
1695
|
--max-per-day <n> Max requests per day per provider
|
|
@@ -1669,7 +1734,9 @@ async function main() {
|
|
|
1669
1734
|
"claude-key": { type: "string" },
|
|
1670
1735
|
"local-url": { type: "string" },
|
|
1671
1736
|
"local-model": { type: "string" },
|
|
1672
|
-
"local-key": { type: "string" }
|
|
1737
|
+
"local-key": { type: "string" },
|
|
1738
|
+
"google-client-id": { type: "string" },
|
|
1739
|
+
"google-client-secret": { type: "string" }
|
|
1673
1740
|
},
|
|
1674
1741
|
allowPositionals: false
|
|
1675
1742
|
});
|
|
@@ -1680,7 +1747,9 @@ async function main() {
|
|
|
1680
1747
|
claudeKey: initValues["claude-key"],
|
|
1681
1748
|
localUrl: initValues["local-url"],
|
|
1682
1749
|
localModel: initValues["local-model"],
|
|
1683
|
-
localKey: initValues["local-key"]
|
|
1750
|
+
localKey: initValues["local-key"],
|
|
1751
|
+
googleClientId: initValues["google-client-id"],
|
|
1752
|
+
googleClientSecret: initValues["google-client-secret"]
|
|
1684
1753
|
});
|
|
1685
1754
|
break;
|
|
1686
1755
|
}
|
|
@@ -2171,6 +2240,23 @@ async function main() {
|
|
|
2171
2240
|
model: values.model,
|
|
2172
2241
|
quota: Object.keys(quota).length > 0 ? quota : void 0
|
|
2173
2242
|
});
|
|
2243
|
+
} else if (subcommand === "google") {
|
|
2244
|
+
const { values } = parseArgs({
|
|
2245
|
+
args: args.slice(2),
|
|
2246
|
+
options: {
|
|
2247
|
+
"client-id": { type: "string" },
|
|
2248
|
+
"client-secret": { type: "string" }
|
|
2249
|
+
},
|
|
2250
|
+
allowPositionals: false
|
|
2251
|
+
});
|
|
2252
|
+
if (!values["client-id"] || !values["client-secret"]) {
|
|
2253
|
+
console.error("Error: --client-id and --client-secret are both required");
|
|
2254
|
+
process.exit(1);
|
|
2255
|
+
}
|
|
2256
|
+
setGoogleAuth({
|
|
2257
|
+
clientId: values["client-id"],
|
|
2258
|
+
clientSecret: values["client-secret"]
|
|
2259
|
+
});
|
|
2174
2260
|
} else {
|
|
2175
2261
|
await showSettings(format);
|
|
2176
2262
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,12 +2,29 @@ import { FastifyInstance } from 'fastify';
|
|
|
2
2
|
import { DatabaseClient } from '@ainyc/canonry-db';
|
|
3
3
|
import { ProviderQuotaPolicy } from '@ainyc/canonry-contracts';
|
|
4
4
|
|
|
5
|
+
type GoogleConnectionType = 'gsc' | 'ga4';
|
|
5
6
|
interface ProviderConfigEntry {
|
|
6
7
|
apiKey?: string;
|
|
7
8
|
baseUrl?: string;
|
|
8
9
|
model?: string;
|
|
9
10
|
quota?: ProviderQuotaPolicy;
|
|
10
11
|
}
|
|
12
|
+
interface GoogleConnectionConfigEntry {
|
|
13
|
+
domain: string;
|
|
14
|
+
connectionType: GoogleConnectionType;
|
|
15
|
+
propertyId?: string | null;
|
|
16
|
+
accessToken?: string;
|
|
17
|
+
refreshToken?: string | null;
|
|
18
|
+
tokenExpiresAt?: string | null;
|
|
19
|
+
scopes?: string[];
|
|
20
|
+
createdAt: string;
|
|
21
|
+
updatedAt: string;
|
|
22
|
+
}
|
|
23
|
+
interface GoogleConfigEntry {
|
|
24
|
+
clientId?: string;
|
|
25
|
+
clientSecret?: string;
|
|
26
|
+
connections?: GoogleConnectionConfigEntry[];
|
|
27
|
+
}
|
|
11
28
|
interface CanonryConfig {
|
|
12
29
|
apiUrl: string;
|
|
13
30
|
database: string;
|
|
@@ -22,6 +39,7 @@ interface CanonryConfig {
|
|
|
22
39
|
claude?: ProviderConfigEntry;
|
|
23
40
|
local?: ProviderConfigEntry;
|
|
24
41
|
};
|
|
42
|
+
google?: GoogleConfigEntry;
|
|
25
43
|
telemetry?: boolean;
|
|
26
44
|
anonymousId?: string;
|
|
27
45
|
}
|
|
@@ -31,6 +49,7 @@ declare function createServer(opts: {
|
|
|
31
49
|
config: CanonryConfig;
|
|
32
50
|
db: DatabaseClient;
|
|
33
51
|
open?: boolean;
|
|
52
|
+
logger?: boolean;
|
|
34
53
|
}): Promise<FastifyInstance>;
|
|
35
54
|
|
|
36
55
|
export { type CanonryConfig, createServer, loadConfig };
|
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.11.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",
|
|
@@ -51,8 +51,8 @@
|
|
|
51
51
|
"@types/node-cron": "^3.0.11",
|
|
52
52
|
"tsup": "^8.5.1",
|
|
53
53
|
"tsx": "^4.19.0",
|
|
54
|
-
"@ainyc/canonry-config": "0.0.0",
|
|
55
54
|
"@ainyc/canonry-api-routes": "0.0.0",
|
|
55
|
+
"@ainyc/canonry-config": "0.0.0",
|
|
56
56
|
"@ainyc/canonry-contracts": "0.0.0",
|
|
57
57
|
"@ainyc/canonry-db": "0.0.0",
|
|
58
58
|
"@ainyc/canonry-provider-local": "0.0.0",
|