@canonry/canonry 7.22.0 → 7.23.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/assets/agent-workspace/skills/canonry/references/canonry-cli.md +14 -0
- package/dist/{chunk-6Z2LFFRT.js → chunk-3OPV5XBY.js} +31 -17
- package/dist/{chunk-6H2BC5EY.js → chunk-KWBFKTOA.js} +1 -1
- package/dist/{chunk-NDQOCFJQ.js → chunk-UF7MH6TU.js} +37 -2
- package/dist/cli.js +191 -113
- package/dist/index.js +2 -2
- package/dist/mcp.js +2 -2
- package/package.json +13 -13
|
@@ -12,6 +12,7 @@ cnry stop # stop daemon
|
|
|
12
12
|
cnry serve # foreground mode
|
|
13
13
|
cnry serve --host 0.0.0.0 --port 4100
|
|
14
14
|
cnry serve --embed --embed-allow-origin https://app.example.com # read-only embed mode (#716)
|
|
15
|
+
cnry dashboard reset-password # clear a forgotten dashboard password (edits local config.yaml)
|
|
15
16
|
cnry --version
|
|
16
17
|
```
|
|
17
18
|
|
|
@@ -41,6 +42,19 @@ install's server, or restart it, to apply the saved providers. Any other
|
|
|
41
42
|
rejected reload reports `failed` and exits nonzero; the saved config remains
|
|
42
43
|
available. Bootstrap never reloads a remote server automatically.
|
|
43
44
|
|
|
45
|
+
`cnry dashboard reset-password` clears a forgotten dashboard password. It edits
|
|
46
|
+
`config.yaml` under `$CANONRY_CONFIG_DIR` on this machine and never calls the
|
|
47
|
+
server, so run it where the server's config lives. A missing file is a
|
|
48
|
+
`CONFIG_REQUIRED` error, not "nothing to reset". Restart the server afterward:
|
|
49
|
+
until then it still accepts the old password. The dashboard then asks for a new
|
|
50
|
+
password under the first-run rules, so stop any port forwarder first and set it
|
|
51
|
+
right away. `--format json` returns
|
|
52
|
+
`{ reset, configPath, restartRequired, namedAccounts, nextSteps[] }`; `reset` is
|
|
53
|
+
`false` when no password was set. On an install with named accounts
|
|
54
|
+
(`namedAccounts: true`) the shared password is not used, so clearing it changes
|
|
55
|
+
nothing: restore an account with `cnry user delete <name>` and `cnry user
|
|
56
|
+
create`. The command has no API route and no MCP tool.
|
|
57
|
+
|
|
44
58
|
### Read-only embed mode (#716)
|
|
45
59
|
|
|
46
60
|
Opt-in, OFF by default. Renders the dashboard "chromeless" (no nav/topbar/settings) so it can be iframed read-only, and emits a fail-closed framing contract. With `--embed` absent, served HTML + headers are byte-for-byte unchanged.
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
saveConfig,
|
|
21
21
|
saveConfigPatch,
|
|
22
22
|
sentimentInstallReadiness
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-UF7MH6TU.js";
|
|
24
24
|
import {
|
|
25
25
|
computeFactorAverages,
|
|
26
26
|
deleteSiteCrawlGraphLayout,
|
|
@@ -3572,7 +3572,7 @@ import path8 from "path";
|
|
|
3572
3572
|
import { isIP } from "net";
|
|
3573
3573
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
3574
3574
|
import { setImmediate as yieldToEventLoop4 } from "timers/promises";
|
|
3575
|
-
import { and as and24, eq as eq29, isNotNull as isNotNull4, isNull as isNull4, lte as lte2, ne as ne3, or as or3, sql as sql11 } from "drizzle-orm";
|
|
3575
|
+
import { and as and24, eq as eq29, isNotNull as isNotNull4, isNull as isNull4, lte as lte2, max, ne as ne3, or as or3, sql as sql11 } from "drizzle-orm";
|
|
3576
3576
|
|
|
3577
3577
|
// ../integration-typesafe/src/classifier.ts
|
|
3578
3578
|
import { createHash } from "crypto";
|
|
@@ -8052,7 +8052,7 @@ function nonBlank(value) {
|
|
|
8052
8052
|
return trimmed ? trimmed : void 0;
|
|
8053
8053
|
}
|
|
8054
8054
|
function resolveBuildCommit(env = process.env) {
|
|
8055
|
-
const embedded = true ? "
|
|
8055
|
+
const embedded = true ? "8c7755db32156f7620744d4a8993c66ac41c40d8" : void 0;
|
|
8056
8056
|
return nonBlank(embedded) ?? nonBlank(env.CANONRY_COMMIT);
|
|
8057
8057
|
}
|
|
8058
8058
|
function resolveInstanceIdentity(env = process.env) {
|
|
@@ -10715,10 +10715,10 @@ async function executeGscSync(db, runId, projectId, opts) {
|
|
|
10715
10715
|
createdAt: dailyTotalsNow
|
|
10716
10716
|
}).run();
|
|
10717
10717
|
}
|
|
10718
|
-
const observedThrough = totalRows.map((row) => row.keys[0] ?? "").filter((date) => date !== "").reduce((
|
|
10718
|
+
const observedThrough = totalRows.map((row) => row.keys[0] ?? "").filter((date) => date !== "").reduce((max2, date) => max2 === null || date > max2 ? date : max2, null);
|
|
10719
10719
|
if (observedThrough !== null || endDate) {
|
|
10720
10720
|
const existing = db.select().from(gscDataWatermarks).where(eq5(gscDataWatermarks.projectId, projectId)).get();
|
|
10721
|
-
const nextThrough = [existing?.dataThroughDate ?? null, observedThrough].filter((d) => d !== null).reduce((
|
|
10721
|
+
const nextThrough = [existing?.dataThroughDate ?? null, observedThrough].filter((d) => d !== null).reduce((max2, d) => max2 === null || d > max2 ? d : max2, null);
|
|
10722
10722
|
if (nextThrough !== null) {
|
|
10723
10723
|
db.insert(gscDataWatermarks).values({
|
|
10724
10724
|
projectId,
|
|
@@ -13420,7 +13420,7 @@ function buildSeedPrompt(input) {
|
|
|
13420
13420
|
`Generate EXACTLY ${QUERIES_PER_INTENT_BUCKET} queries per bucket \u2014 ${QUERIES_PER_INTENT_BUCKET * 5} total. Return ONE query per line. Plain text only \u2014 no numbering, bullets, quotes, bucket labels, or commentary.`
|
|
13421
13421
|
].join("\n");
|
|
13422
13422
|
}
|
|
13423
|
-
function parseQueryLines(text,
|
|
13423
|
+
function parseQueryLines(text, max2) {
|
|
13424
13424
|
const lines = text.split("\n");
|
|
13425
13425
|
const out = [];
|
|
13426
13426
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -13434,7 +13434,7 @@ function parseQueryLines(text, max) {
|
|
|
13434
13434
|
if (seen.has(key)) continue;
|
|
13435
13435
|
seen.add(key);
|
|
13436
13436
|
out.push(line);
|
|
13437
|
-
if (out.length >=
|
|
13437
|
+
if (out.length >= max2) break;
|
|
13438
13438
|
}
|
|
13439
13439
|
return out;
|
|
13440
13440
|
}
|
|
@@ -17059,9 +17059,9 @@ function largestArrayKey(obj) {
|
|
|
17059
17059
|
function fitsCap(text) {
|
|
17060
17060
|
return text.length <= MAX_TOOL_RESULT_CHARS;
|
|
17061
17061
|
}
|
|
17062
|
-
function largestFitting(
|
|
17062
|
+
function largestFitting(max2, fits) {
|
|
17063
17063
|
let low = 0;
|
|
17064
|
-
let high =
|
|
17064
|
+
let high = max2;
|
|
17065
17065
|
while (low < high) {
|
|
17066
17066
|
const middle = Math.ceil((low + high) / 2);
|
|
17067
17067
|
if (fits(middle)) low = middle;
|
|
@@ -17211,7 +17211,7 @@ function trimNestedArrays(full) {
|
|
|
17211
17211
|
};
|
|
17212
17212
|
const fits = () => spent <= TRUNCATION_SERIALIZE_BUDGET_CHARS && fitsCap(render2());
|
|
17213
17213
|
const members2 = (stage) => lists.flatMap((_, index) => stagesOf[index].includes(stage) ? [index] : []);
|
|
17214
|
-
const longest = (indexes) => indexes.reduce((
|
|
17214
|
+
const longest = (indexes) => indexes.reduce((max2, index) => Math.max(max2, lists[index].rows.length), 0);
|
|
17215
17215
|
let out = render2();
|
|
17216
17216
|
let fittedAt = -1;
|
|
17217
17217
|
for (let stage = 0; stage < TRIM_STAGES.length && !fitsCap(out); stage++) {
|
|
@@ -17695,9 +17695,9 @@ async function readSection(fn) {
|
|
|
17695
17695
|
};
|
|
17696
17696
|
}
|
|
17697
17697
|
}
|
|
17698
|
-
function clampInteger(value, fallback, min,
|
|
17698
|
+
function clampInteger(value, fallback, min, max2) {
|
|
17699
17699
|
if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
|
|
17700
|
-
return Math.max(min, Math.min(
|
|
17700
|
+
return Math.max(min, Math.min(max2, Math.trunc(value)));
|
|
17701
17701
|
}
|
|
17702
17702
|
function isoDateDaysAgo(days) {
|
|
17703
17703
|
const d = new Date(Date.now() - (days - 1) * 24 * 60 * 60 * 1e3);
|
|
@@ -19776,9 +19776,9 @@ function viewerAeroDailyLimitExceeded(limit) {
|
|
|
19776
19776
|
var VIEWER_AERO_KEY_PREFIX = "aero-viewer:";
|
|
19777
19777
|
var VIEWER_AERO_PROMPT = "\n\nThis conversation is with a view-only account. You can read this project's data but cannot change anything, start or schedule sweeps, or spend on live provider reads. If asked to, say an administrator has to do it. You cannot see the operator's own Aero conversations or notes.";
|
|
19778
19778
|
var MAX_VIEWER_MESSAGES = 40;
|
|
19779
|
-
function trimViewerTranscript(messages,
|
|
19780
|
-
if (messages.length <=
|
|
19781
|
-
for (let i = messages.length -
|
|
19779
|
+
function trimViewerTranscript(messages, max2 = MAX_VIEWER_MESSAGES) {
|
|
19780
|
+
if (messages.length <= max2) return messages;
|
|
19781
|
+
for (let i = messages.length - max2; i < messages.length; i++) {
|
|
19782
19782
|
if (messages[i].role === "user") return messages.slice(i);
|
|
19783
19783
|
}
|
|
19784
19784
|
const lastUser = messages.map((message) => message.role).lastIndexOf("user");
|
|
@@ -23005,6 +23005,19 @@ async function createServer(opts) {
|
|
|
23005
23005
|
ne3(dashboardSessions.passwordFingerprint, currentPasswordFingerprint())
|
|
23006
23006
|
)
|
|
23007
23007
|
)).run();
|
|
23008
|
+
if (!opts.config.dashboardPasswordHash) {
|
|
23009
|
+
const lastPasswordEventAt = (action) => opts.db.select({ at: max(auditLog.createdAt) }).from(auditLog).where(and24(eq29(auditLog.entityType, "dashboard-password"), eq29(auditLog.action, action))).get()?.at ?? null;
|
|
23010
|
+
const createdAt = lastPasswordEventAt("dashboard-password.created");
|
|
23011
|
+
const clearedAt = lastPasswordEventAt("dashboard-password.cleared");
|
|
23012
|
+
if (createdAt !== null && (clearedAt === null || clearedAt < createdAt)) {
|
|
23013
|
+
writeAuditLog(opts.db, {
|
|
23014
|
+
actor: "system",
|
|
23015
|
+
action: "dashboard-password.cleared",
|
|
23016
|
+
entityType: "dashboard-password",
|
|
23017
|
+
diff: { detectedAt: "startup" }
|
|
23018
|
+
});
|
|
23019
|
+
}
|
|
23020
|
+
}
|
|
23008
23021
|
const createSession = (key, passwordBased = false, db = opts.db) => {
|
|
23009
23022
|
const now = /* @__PURE__ */ new Date();
|
|
23010
23023
|
db.delete(dashboardSessions).where(lte2(dashboardSessions.expiresAt, now.toISOString())).run();
|
|
@@ -23121,7 +23134,8 @@ async function createServer(opts) {
|
|
|
23121
23134
|
const err = serverApiKeyMissing();
|
|
23122
23135
|
return reply.status(err.statusCode).send(err.toJSON());
|
|
23123
23136
|
}
|
|
23124
|
-
|
|
23137
|
+
const passwordHash = hashDashboardPassword(password);
|
|
23138
|
+
opts.config.dashboardPasswordHash = passwordHash;
|
|
23125
23139
|
let sessionId;
|
|
23126
23140
|
try {
|
|
23127
23141
|
sessionId = opts.db.transaction((tx) => {
|
|
@@ -23134,7 +23148,7 @@ async function createServer(opts) {
|
|
|
23134
23148
|
diff: { authorizedBy: presentedRootKey ? "root-api-key" : "local-request" }
|
|
23135
23149
|
}));
|
|
23136
23150
|
const created = createSession(defaultKey, true, tx);
|
|
23137
|
-
saveConfigPatch(opts.config);
|
|
23151
|
+
saveConfigPatch(opts.config, { setDashboardPasswordHash: passwordHash });
|
|
23138
23152
|
return created;
|
|
23139
23153
|
});
|
|
23140
23154
|
} catch (err) {
|
|
@@ -582,17 +582,20 @@ function saveConfig(config) {
|
|
|
582
582
|
const yaml = stringify(merged);
|
|
583
583
|
writeConfigAtomically(configPath, yaml);
|
|
584
584
|
}
|
|
585
|
-
function saveConfigPatch(patch) {
|
|
585
|
+
function saveConfigPatch(patch, options = {}) {
|
|
586
586
|
const configDir = getConfigDir();
|
|
587
587
|
if (!fs.existsSync(configDir)) {
|
|
588
588
|
fs.mkdirSync(configDir, { recursive: true });
|
|
589
589
|
}
|
|
590
590
|
const configPath = getConfigPath();
|
|
591
591
|
let base = {};
|
|
592
|
+
let baseRead = false;
|
|
592
593
|
if (fs.existsSync(configPath)) {
|
|
593
594
|
try {
|
|
594
595
|
const raw = fs.readFileSync(configPath, "utf-8");
|
|
595
|
-
|
|
596
|
+
const parsed = parse(raw);
|
|
597
|
+
base = parsed ?? {};
|
|
598
|
+
baseRead = typeof parsed === "object" && parsed !== null && !Array.isArray(parsed);
|
|
596
599
|
} catch {
|
|
597
600
|
base = {};
|
|
598
601
|
}
|
|
@@ -602,6 +605,8 @@ function saveConfigPatch(patch) {
|
|
|
602
605
|
if (base.apiKey) merged.apiKey = base.apiKey;
|
|
603
606
|
if (base.anonymousId) merged.anonymousId = base.anonymousId;
|
|
604
607
|
if (base.dashboardPasswordHash) merged.dashboardPasswordHash = base.dashboardPasswordHash;
|
|
608
|
+
else if (options.setDashboardPasswordHash) merged.dashboardPasswordHash = options.setDashboardPasswordHash;
|
|
609
|
+
else if (baseRead) delete merged.dashboardPasswordHash;
|
|
605
610
|
if (base.sentiment === void 0) delete merged.sentiment;
|
|
606
611
|
else merged.sentiment = base.sentiment;
|
|
607
612
|
if (base.providers && patch.providers) {
|
|
@@ -614,6 +619,35 @@ function saveConfigPatch(patch) {
|
|
|
614
619
|
const yaml = stringify(merged);
|
|
615
620
|
writeConfigAtomically(configPath, yaml);
|
|
616
621
|
}
|
|
622
|
+
function clearDashboardPassword() {
|
|
623
|
+
const configPath = getConfigPath();
|
|
624
|
+
if (!fs.existsSync(configPath)) {
|
|
625
|
+
throw new CliError({
|
|
626
|
+
code: "CONFIG_REQUIRED",
|
|
627
|
+
message: `No config found at ${configPath}. If the server uses another config directory, set CANONRY_CONFIG_DIR to it and retry.`
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
const raw = fs.readFileSync(configPath, "utf-8");
|
|
631
|
+
let parsed;
|
|
632
|
+
try {
|
|
633
|
+
parsed = parse(raw) ?? {};
|
|
634
|
+
} catch {
|
|
635
|
+
parsed = void 0;
|
|
636
|
+
}
|
|
637
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
638
|
+
throw new CliError({
|
|
639
|
+
code: "CONFIG_INVALID",
|
|
640
|
+
message: `Invalid config at ${configPath}: it could not be read as YAML settings. Repair the file and retry.`
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
const config = parsed;
|
|
644
|
+
if (!config.dashboardPasswordHash) {
|
|
645
|
+
return { cleared: false, configPath };
|
|
646
|
+
}
|
|
647
|
+
delete config.dashboardPasswordHash;
|
|
648
|
+
writeConfigAtomically(configPath, stringify(config));
|
|
649
|
+
return { cleared: true, configPath };
|
|
650
|
+
}
|
|
617
651
|
function configExists() {
|
|
618
652
|
return fs.existsSync(getConfigPath());
|
|
619
653
|
}
|
|
@@ -10590,6 +10624,7 @@ export {
|
|
|
10590
10624
|
loadConfigRaw,
|
|
10591
10625
|
saveConfig,
|
|
10592
10626
|
saveConfigPatch,
|
|
10627
|
+
clearDashboardPassword,
|
|
10593
10628
|
configExists,
|
|
10594
10629
|
BUNDLED_SKILL_NAMES,
|
|
10595
10630
|
getBundledSkillSnapshots,
|
package/dist/cli.js
CHANGED
|
@@ -35,12 +35,13 @@ import {
|
|
|
35
35
|
trackCliCommandFinished,
|
|
36
36
|
trackEvent,
|
|
37
37
|
waitForServerRuntimeStartup
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-3OPV5XBY.js";
|
|
39
39
|
import {
|
|
40
40
|
autoSyncSkills,
|
|
41
41
|
formatAutoSyncNotice
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-KWBFKTOA.js";
|
|
43
43
|
import {
|
|
44
|
+
clearDashboardPassword,
|
|
44
45
|
configExists,
|
|
45
46
|
createApiClient,
|
|
46
47
|
emitInstallSummary,
|
|
@@ -57,7 +58,7 @@ import {
|
|
|
57
58
|
saveConfigPatch,
|
|
58
59
|
shouldPrintServeSkillsNudge,
|
|
59
60
|
withBootstrapProviderDefaults
|
|
60
|
-
} from "./chunk-
|
|
61
|
+
} from "./chunk-UF7MH6TU.js";
|
|
61
62
|
import {
|
|
62
63
|
DEFAULT_DEMO_TRUSTED_PROXIES,
|
|
63
64
|
trustedProxiesProblem,
|
|
@@ -82,6 +83,7 @@ import {
|
|
|
82
83
|
CLOUDFLARE_WRANGLER_GENERATED_MARKER,
|
|
83
84
|
DEFAULT_BOT_LIST,
|
|
84
85
|
aiUserFetchEventsHourly,
|
|
86
|
+
anyUsersExist,
|
|
85
87
|
apiKeys,
|
|
86
88
|
auditLog,
|
|
87
89
|
backfillProjectAnswerMentions,
|
|
@@ -3015,6 +3017,80 @@ var CDP_CLI_COMMANDS = [
|
|
|
3015
3017
|
}
|
|
3016
3018
|
];
|
|
3017
3019
|
|
|
3020
|
+
// src/commands/dashboard.ts
|
|
3021
|
+
import fs2 from "fs";
|
|
3022
|
+
function namedAccountsInUse() {
|
|
3023
|
+
const database = loadConfigRaw()?.database;
|
|
3024
|
+
if (typeof database !== "string" || !fs2.existsSync(database)) return false;
|
|
3025
|
+
try {
|
|
3026
|
+
const db = createClient(database);
|
|
3027
|
+
try {
|
|
3028
|
+
return anyUsersExist(db);
|
|
3029
|
+
} finally {
|
|
3030
|
+
db.$client.close();
|
|
3031
|
+
}
|
|
3032
|
+
} catch {
|
|
3033
|
+
return false;
|
|
3034
|
+
}
|
|
3035
|
+
}
|
|
3036
|
+
function nextStepsFor(cleared, namedAccounts) {
|
|
3037
|
+
if (namedAccounts) {
|
|
3038
|
+
return [
|
|
3039
|
+
"This install signs in with named accounts, so the shared dashboard password is not used and clearing it does not change who can sign in.",
|
|
3040
|
+
'To restore an account, run "canonry user list", then "canonry user delete <name>" and "canonry user create".'
|
|
3041
|
+
];
|
|
3042
|
+
}
|
|
3043
|
+
if (!cleared) {
|
|
3044
|
+
return ["If the dashboard still asks for a password, restart the server: it keeps the password it started with."];
|
|
3045
|
+
}
|
|
3046
|
+
return [
|
|
3047
|
+
"Restart the server to apply the reset. Until then it still accepts the old password.",
|
|
3048
|
+
// First-run setup on a loopback bind takes the password from any process
|
|
3049
|
+
// that can open a loopback connection (docs/deployment.md).
|
|
3050
|
+
"Then open the dashboard and create the new password right away. Until one is set, a server that listens only on this machine accepts it from any local connection, so stop any port forwarder (ssh -R, ngrok tcp, tailscale serve --tcp) first."
|
|
3051
|
+
];
|
|
3052
|
+
}
|
|
3053
|
+
async function resetDashboardPassword(opts) {
|
|
3054
|
+
const { cleared, configPath } = clearDashboardPassword();
|
|
3055
|
+
const namedAccounts = namedAccountsInUse();
|
|
3056
|
+
const nextSteps = nextStepsFor(cleared, namedAccounts);
|
|
3057
|
+
if (isMachineFormat(opts.format)) {
|
|
3058
|
+
console.log(JSON.stringify({
|
|
3059
|
+
reset: cleared,
|
|
3060
|
+
configPath,
|
|
3061
|
+
restartRequired: cleared && !namedAccounts,
|
|
3062
|
+
namedAccounts,
|
|
3063
|
+
nextSteps
|
|
3064
|
+
}, null, 2));
|
|
3065
|
+
return;
|
|
3066
|
+
}
|
|
3067
|
+
console.log(cleared ? `Dashboard password cleared from ${configPath}.` : `No dashboard password is set in ${configPath}; nothing to reset.`);
|
|
3068
|
+
for (const step of nextSteps) console.log(step);
|
|
3069
|
+
}
|
|
3070
|
+
|
|
3071
|
+
// src/cli-commands/dashboard.ts
|
|
3072
|
+
var DASHBOARD_CLI_COMMANDS = [
|
|
3073
|
+
{
|
|
3074
|
+
path: ["dashboard", "reset-password"],
|
|
3075
|
+
usage: "canonry dashboard reset-password [--format json]",
|
|
3076
|
+
help: "Clears the dashboard password from config.yaml, so the dashboard asks for a new one after a restart.\nLocal only: it edits the config file under CANONRY_CONFIG_DIR and does not call the server.",
|
|
3077
|
+
run: async (input) => {
|
|
3078
|
+
await resetDashboardPassword({ format: input.format });
|
|
3079
|
+
}
|
|
3080
|
+
},
|
|
3081
|
+
{
|
|
3082
|
+
path: ["dashboard"],
|
|
3083
|
+
usage: "canonry dashboard <reset-password>",
|
|
3084
|
+
run: async (input) => {
|
|
3085
|
+
unknownSubcommand(input.positionals[0], {
|
|
3086
|
+
command: "dashboard",
|
|
3087
|
+
usage: "canonry dashboard <reset-password>",
|
|
3088
|
+
available: ["reset-password"]
|
|
3089
|
+
});
|
|
3090
|
+
}
|
|
3091
|
+
}
|
|
3092
|
+
];
|
|
3093
|
+
|
|
3018
3094
|
// src/commands/discover.ts
|
|
3019
3095
|
var TERMINAL_DISCOVERY_STATUSES = /* @__PURE__ */ new Set([
|
|
3020
3096
|
"completed",
|
|
@@ -3360,7 +3436,7 @@ async function pollSession(client, project2, sessionId, quiet = false) {
|
|
|
3360
3436
|
}
|
|
3361
3437
|
|
|
3362
3438
|
// src/commands/discover-eval.ts
|
|
3363
|
-
import
|
|
3439
|
+
import fs3 from "fs";
|
|
3364
3440
|
import path from "path";
|
|
3365
3441
|
|
|
3366
3442
|
// src/discovery-eval.ts
|
|
@@ -3589,7 +3665,7 @@ async function discoverEvalWithClient(client, opts) {
|
|
|
3589
3665
|
const baselinePath = path.resolve(opts.baseline ?? DEFAULT_BASELINE_PATH);
|
|
3590
3666
|
if (opts.updateBaseline) {
|
|
3591
3667
|
const baseline2 = { capturedAt: (/* @__PURE__ */ new Date()).toISOString(), scorecards };
|
|
3592
|
-
|
|
3668
|
+
fs3.writeFileSync(baselinePath, JSON.stringify(baseline2, null, 2) + "\n");
|
|
3593
3669
|
if (opts.format === "json" || opts.format === "jsonl") {
|
|
3594
3670
|
console.log(JSON.stringify({ scorecards, baselineWritten: baselinePath }, null, 2));
|
|
3595
3671
|
} else {
|
|
@@ -3598,14 +3674,14 @@ async function discoverEvalWithClient(client, opts) {
|
|
|
3598
3674
|
}
|
|
3599
3675
|
return;
|
|
3600
3676
|
}
|
|
3601
|
-
if (!
|
|
3677
|
+
if (!fs3.existsSync(baselinePath)) {
|
|
3602
3678
|
throw new CliError({
|
|
3603
3679
|
code: "EVAL_NO_BASELINE",
|
|
3604
3680
|
message: `no baseline at ${baselinePath}; run with --update-baseline to capture one`,
|
|
3605
3681
|
exitCode: EXIT_USER_ERROR
|
|
3606
3682
|
});
|
|
3607
3683
|
}
|
|
3608
|
-
const baseline = JSON.parse(
|
|
3684
|
+
const baseline = JSON.parse(fs3.readFileSync(baselinePath, "utf8"));
|
|
3609
3685
|
const verdict = compareToBaseline(scorecards, baseline);
|
|
3610
3686
|
if (opts.format === "json" || opts.format === "jsonl") {
|
|
3611
3687
|
console.log(JSON.stringify({ scorecards, verdict, baseline: { capturedAt: baseline.capturedAt } }, null, 2));
|
|
@@ -4437,7 +4513,7 @@ var DOCTOR_CLI_COMMANDS = [
|
|
|
4437
4513
|
];
|
|
4438
4514
|
|
|
4439
4515
|
// src/commands/ads.ts
|
|
4440
|
-
import
|
|
4516
|
+
import fs4 from "fs";
|
|
4441
4517
|
function getClient6() {
|
|
4442
4518
|
return createApiClient();
|
|
4443
4519
|
}
|
|
@@ -4450,7 +4526,7 @@ function readRequest(inputPath, schema) {
|
|
|
4450
4526
|
});
|
|
4451
4527
|
}
|
|
4452
4528
|
try {
|
|
4453
|
-
const raw =
|
|
4529
|
+
const raw = fs4.readFileSync(inputPath === "-" ? 0 : inputPath, "utf8");
|
|
4454
4530
|
return schema.parse(JSON.parse(raw));
|
|
4455
4531
|
} catch (err) {
|
|
4456
4532
|
if (err instanceof CliError) throw err;
|
|
@@ -5326,9 +5402,9 @@ async function gaConnect(project2, opts) {
|
|
|
5326
5402
|
propertyId: opts.propertyId
|
|
5327
5403
|
};
|
|
5328
5404
|
if (opts.keyFile) {
|
|
5329
|
-
const
|
|
5405
|
+
const fs20 = await import("fs");
|
|
5330
5406
|
try {
|
|
5331
|
-
const content =
|
|
5407
|
+
const content = fs20.readFileSync(opts.keyFile, "utf-8");
|
|
5332
5408
|
JSON.parse(content);
|
|
5333
5409
|
body.keyJson = content;
|
|
5334
5410
|
} catch (e) {
|
|
@@ -6916,7 +6992,7 @@ var GBP_CLI_COMMANDS = [
|
|
|
6916
6992
|
];
|
|
6917
6993
|
|
|
6918
6994
|
// src/commands/google-marketing.ts
|
|
6919
|
-
import
|
|
6995
|
+
import fs5 from "fs";
|
|
6920
6996
|
function printMachine(value, format) {
|
|
6921
6997
|
if (!isMachineFormat(format)) return false;
|
|
6922
6998
|
console.log(JSON.stringify(value, null, 2));
|
|
@@ -6957,7 +7033,7 @@ function readConversionTrackingContractInput(inputPath) {
|
|
|
6957
7033
|
});
|
|
6958
7034
|
}
|
|
6959
7035
|
try {
|
|
6960
|
-
const raw =
|
|
7036
|
+
const raw = fs5.readFileSync(inputPath === "-" ? 0 : inputPath, "utf8");
|
|
6961
7037
|
return conversionTrackingContractWriteRequestSchema.parse(JSON.parse(raw));
|
|
6962
7038
|
} catch (err) {
|
|
6963
7039
|
const message = describeError(err);
|
|
@@ -7671,12 +7747,12 @@ var GET_CLI_COMMANDS = [
|
|
|
7671
7747
|
];
|
|
7672
7748
|
|
|
7673
7749
|
// src/commands/traffic.ts
|
|
7674
|
-
import
|
|
7750
|
+
import fs7 from "fs";
|
|
7675
7751
|
|
|
7676
7752
|
// src/cloudflare-worker-deploy.ts
|
|
7677
7753
|
import { spawn } from "child_process";
|
|
7678
7754
|
import { randomUUID } from "crypto";
|
|
7679
|
-
import
|
|
7755
|
+
import fs6 from "fs";
|
|
7680
7756
|
import os from "os";
|
|
7681
7757
|
import path2 from "path";
|
|
7682
7758
|
import { stripVTControlCharacters } from "util";
|
|
@@ -7694,7 +7770,7 @@ function projectSlug(project2) {
|
|
|
7694
7770
|
}
|
|
7695
7771
|
function lstatIfPresent(filePath) {
|
|
7696
7772
|
try {
|
|
7697
|
-
return
|
|
7773
|
+
return fs6.lstatSync(filePath);
|
|
7698
7774
|
} catch (error) {
|
|
7699
7775
|
if (error.code === "ENOENT") return null;
|
|
7700
7776
|
throw error;
|
|
@@ -7712,7 +7788,7 @@ function prepareCloudflareWorkerOutputDirectory(outputDirectory) {
|
|
|
7712
7788
|
throw new Error(`output directory is not a regular directory: ${resolved}`);
|
|
7713
7789
|
}
|
|
7714
7790
|
} else {
|
|
7715
|
-
|
|
7791
|
+
fs6.mkdirSync(resolved, { recursive: true, mode: 448 });
|
|
7716
7792
|
}
|
|
7717
7793
|
const artifacts = {
|
|
7718
7794
|
outputDirectory: resolved,
|
|
@@ -7725,7 +7801,7 @@ function prepareCloudflareWorkerOutputDirectory(outputDirectory) {
|
|
|
7725
7801
|
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
7726
7802
|
throw new Error(`artifact path is not a regular file: ${artifactPath}`);
|
|
7727
7803
|
}
|
|
7728
|
-
const contents =
|
|
7804
|
+
const contents = fs6.readFileSync(artifactPath, "utf-8");
|
|
7729
7805
|
if (!isRecognizablyCanonryGenerated(artifactPath, contents)) {
|
|
7730
7806
|
throw new Error(`refusing to overwrite an operator-owned artifact: ${artifactPath}`);
|
|
7731
7807
|
}
|
|
@@ -7738,7 +7814,7 @@ function readRegularArtifact(filePath) {
|
|
|
7738
7814
|
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
7739
7815
|
throw new Error(`artifact path is not a regular file: ${filePath}`);
|
|
7740
7816
|
}
|
|
7741
|
-
return
|
|
7817
|
+
return fs6.readFileSync(filePath, "utf-8");
|
|
7742
7818
|
}
|
|
7743
7819
|
function isRecognizablyCanonryGenerated(filePath, contents) {
|
|
7744
7820
|
if (path2.basename(filePath) === "worker.js") {
|
|
@@ -7755,22 +7831,22 @@ function writePrivateTemporaryFile(filePath, contents) {
|
|
|
7755
7831
|
path2.dirname(filePath),
|
|
7756
7832
|
`.${path2.basename(filePath)}.${randomUUID()}.tmp`
|
|
7757
7833
|
);
|
|
7758
|
-
const fd =
|
|
7834
|
+
const fd = fs6.openSync(temporaryPath, "wx", 384);
|
|
7759
7835
|
let closed = false;
|
|
7760
7836
|
try {
|
|
7761
|
-
|
|
7762
|
-
|
|
7763
|
-
|
|
7837
|
+
fs6.writeFileSync(fd, contents, "utf-8");
|
|
7838
|
+
fs6.fsyncSync(fd);
|
|
7839
|
+
fs6.closeSync(fd);
|
|
7764
7840
|
closed = true;
|
|
7765
7841
|
} catch (error) {
|
|
7766
7842
|
if (!closed) {
|
|
7767
7843
|
try {
|
|
7768
|
-
|
|
7844
|
+
fs6.closeSync(fd);
|
|
7769
7845
|
} catch {
|
|
7770
7846
|
}
|
|
7771
7847
|
}
|
|
7772
7848
|
try {
|
|
7773
|
-
|
|
7849
|
+
fs6.unlinkSync(temporaryPath);
|
|
7774
7850
|
} catch {
|
|
7775
7851
|
}
|
|
7776
7852
|
throw error;
|
|
@@ -7804,10 +7880,10 @@ function writeCloudflareWorkerArtifacts(artifacts, contents) {
|
|
|
7804
7880
|
throw new Error(`artifact changed during update: ${change.filePath}`);
|
|
7805
7881
|
}
|
|
7806
7882
|
if (change.previous === null) {
|
|
7807
|
-
|
|
7808
|
-
|
|
7883
|
+
fs6.linkSync(change.temporaryPath, change.filePath);
|
|
7884
|
+
fs6.unlinkSync(change.temporaryPath);
|
|
7809
7885
|
} else {
|
|
7810
|
-
|
|
7886
|
+
fs6.renameSync(change.temporaryPath, change.filePath);
|
|
7811
7887
|
}
|
|
7812
7888
|
applied.push(change);
|
|
7813
7889
|
}
|
|
@@ -7816,10 +7892,10 @@ function writeCloudflareWorkerArtifacts(artifacts, contents) {
|
|
|
7816
7892
|
try {
|
|
7817
7893
|
if (readRegularArtifact(change.filePath) !== change.contents) continue;
|
|
7818
7894
|
if (change.previous === null) {
|
|
7819
|
-
|
|
7895
|
+
fs6.unlinkSync(change.filePath);
|
|
7820
7896
|
} else {
|
|
7821
7897
|
const restorePath = writePrivateTemporaryFile(change.filePath, change.previous);
|
|
7822
|
-
|
|
7898
|
+
fs6.renameSync(restorePath, change.filePath);
|
|
7823
7899
|
}
|
|
7824
7900
|
} catch {
|
|
7825
7901
|
}
|
|
@@ -7828,7 +7904,7 @@ function writeCloudflareWorkerArtifacts(artifacts, contents) {
|
|
|
7828
7904
|
} finally {
|
|
7829
7905
|
for (const change of pending) {
|
|
7830
7906
|
try {
|
|
7831
|
-
if (
|
|
7907
|
+
if (fs6.existsSync(change.temporaryPath)) fs6.unlinkSync(change.temporaryPath);
|
|
7832
7908
|
} catch {
|
|
7833
7909
|
}
|
|
7834
7910
|
}
|
|
@@ -7914,7 +7990,7 @@ async function preflightCloudflareWrangler(opts = {}) {
|
|
|
7914
7990
|
if (missing.length > 0) {
|
|
7915
7991
|
throw new Error(`Wrangler deploy does not support required flags: ${missing.join(", ")}`);
|
|
7916
7992
|
}
|
|
7917
|
-
const tempDirectory =
|
|
7993
|
+
const tempDirectory = fs6.mkdtempSync(path2.join(
|
|
7918
7994
|
opts.tempRoot ?? os.tmpdir(),
|
|
7919
7995
|
"canonry-cloudflare-wrangler-preflight-"
|
|
7920
7996
|
));
|
|
@@ -7922,13 +7998,13 @@ async function preflightCloudflareWrangler(opts = {}) {
|
|
|
7922
7998
|
const wranglerTomlPath = path2.join(tempDirectory, "wrangler.toml");
|
|
7923
7999
|
const secretsPath = path2.join(tempDirectory, "secrets.json");
|
|
7924
8000
|
try {
|
|
7925
|
-
|
|
7926
|
-
|
|
8001
|
+
fs6.chmodSync(tempDirectory, 448);
|
|
8002
|
+
fs6.writeFileSync(workerScriptPath, generateWorkerScript({
|
|
7927
8003
|
deliveryMode,
|
|
7928
8004
|
workerVersion: "preflight",
|
|
7929
8005
|
botList: DEFAULT_BOT_LIST
|
|
7930
8006
|
}), { encoding: "utf-8", flag: "wx", mode: 384 });
|
|
7931
|
-
|
|
8007
|
+
fs6.writeFileSync(wranglerTomlPath, generateWranglerToml(
|
|
7932
8008
|
deliveryMode === "queue-pull" ? {
|
|
7933
8009
|
deliveryMode,
|
|
7934
8010
|
sourceId: "preflight",
|
|
@@ -7944,7 +8020,7 @@ async function preflightCloudflareWrangler(opts = {}) {
|
|
|
7944
8020
|
}
|
|
7945
8021
|
), { encoding: "utf-8", flag: "wx", mode: 384 });
|
|
7946
8022
|
if (deliveryMode === "direct-push") {
|
|
7947
|
-
|
|
8023
|
+
fs6.writeFileSync(secretsPath, JSON.stringify({
|
|
7948
8024
|
[CLOUDFLARE_WORKER_BINDINGS.bearerToken]: "preflight-bearer",
|
|
7949
8025
|
[CLOUDFLARE_WORKER_BINDINGS.hmacSecret]: "preflight-hmac"
|
|
7950
8026
|
}), { encoding: "utf-8", flag: "wx", mode: 384 });
|
|
@@ -7972,7 +8048,7 @@ ${wranglerDiagnostic(validationOutput)}`
|
|
|
7972
8048
|
);
|
|
7973
8049
|
}
|
|
7974
8050
|
} finally {
|
|
7975
|
-
|
|
8051
|
+
fs6.rmSync(tempDirectory, { recursive: true, force: true });
|
|
7976
8052
|
}
|
|
7977
8053
|
}
|
|
7978
8054
|
async function deployCloudflareWorker(opts) {
|
|
@@ -7988,11 +8064,11 @@ async function deployCloudflareWorker(opts) {
|
|
|
7988
8064
|
}
|
|
7989
8065
|
if (!opts.secrets) throw new Error("Direct-push Worker deploy requires bearer and HMAC secrets");
|
|
7990
8066
|
const secrets = opts.secrets;
|
|
7991
|
-
const tempDirectory =
|
|
8067
|
+
const tempDirectory = fs6.mkdtempSync(path2.join(opts.tempRoot ?? os.tmpdir(), "canonry-cloudflare-secrets-"));
|
|
7992
8068
|
const secretsPath = path2.join(tempDirectory, "secrets.json");
|
|
7993
8069
|
try {
|
|
7994
|
-
|
|
7995
|
-
|
|
8070
|
+
fs6.chmodSync(tempDirectory, 448);
|
|
8071
|
+
fs6.writeFileSync(
|
|
7996
8072
|
secretsPath,
|
|
7997
8073
|
JSON.stringify({
|
|
7998
8074
|
[CLOUDFLARE_WORKER_BINDINGS.bearerToken]: secrets.bearerToken,
|
|
@@ -8000,7 +8076,7 @@ async function deployCloudflareWorker(opts) {
|
|
|
8000
8076
|
}),
|
|
8001
8077
|
{ encoding: "utf-8", flag: "wx", mode: 384 }
|
|
8002
8078
|
);
|
|
8003
|
-
|
|
8079
|
+
fs6.chmodSync(secretsPath, 384);
|
|
8004
8080
|
const runner = opts.run ?? runWrangler;
|
|
8005
8081
|
await runner(
|
|
8006
8082
|
"wrangler",
|
|
@@ -8016,9 +8092,9 @@ async function deployCloudflareWorker(opts) {
|
|
|
8016
8092
|
);
|
|
8017
8093
|
} finally {
|
|
8018
8094
|
try {
|
|
8019
|
-
if (
|
|
8095
|
+
if (fs6.existsSync(secretsPath)) fs6.unlinkSync(secretsPath);
|
|
8020
8096
|
} finally {
|
|
8021
|
-
|
|
8097
|
+
fs6.rmSync(tempDirectory, { recursive: true, force: true });
|
|
8022
8098
|
}
|
|
8023
8099
|
}
|
|
8024
8100
|
}
|
|
@@ -8048,11 +8124,11 @@ function requireCloudflareQueueOption(project2, value, option) {
|
|
|
8048
8124
|
}
|
|
8049
8125
|
function readCloudflareQueueApiToken(project2, tokenFile) {
|
|
8050
8126
|
try {
|
|
8051
|
-
const stat =
|
|
8127
|
+
const stat = fs7.lstatSync(tokenFile);
|
|
8052
8128
|
if (!stat.isFile() || stat.isSymbolicLink()) {
|
|
8053
8129
|
throw new Error("not a regular file");
|
|
8054
8130
|
}
|
|
8055
|
-
const apiToken =
|
|
8131
|
+
const apiToken = fs7.readFileSync(tokenFile, "utf-8").trim();
|
|
8056
8132
|
if (!apiToken) throw new Error("file is empty");
|
|
8057
8133
|
return apiToken;
|
|
8058
8134
|
} catch (error) {
|
|
@@ -8334,9 +8410,9 @@ async function trafficConnectWordpress(project2, opts) {
|
|
|
8334
8410
|
}
|
|
8335
8411
|
let applicationPassword = opts.appPassword?.trim() ?? "";
|
|
8336
8412
|
if (!applicationPassword && opts.appPasswordFile) {
|
|
8337
|
-
const
|
|
8413
|
+
const fs20 = await import("fs");
|
|
8338
8414
|
try {
|
|
8339
|
-
applicationPassword =
|
|
8415
|
+
applicationPassword = fs20.readFileSync(opts.appPasswordFile, "utf-8").trim();
|
|
8340
8416
|
} catch (e) {
|
|
8341
8417
|
const msg = describeError(e);
|
|
8342
8418
|
throw new CliError({
|
|
@@ -8392,10 +8468,10 @@ async function trafficConnectCloudRun(project2, opts) {
|
|
|
8392
8468
|
details: { project: project2 }
|
|
8393
8469
|
});
|
|
8394
8470
|
}
|
|
8395
|
-
const
|
|
8471
|
+
const fs20 = await import("fs");
|
|
8396
8472
|
let keyJson;
|
|
8397
8473
|
try {
|
|
8398
|
-
keyJson =
|
|
8474
|
+
keyJson = fs20.readFileSync(opts.serviceAccountKey, "utf-8");
|
|
8399
8475
|
JSON.parse(keyJson);
|
|
8400
8476
|
} catch (e) {
|
|
8401
8477
|
const msg = describeError(e);
|
|
@@ -8455,9 +8531,9 @@ async function trafficConnectVercel(project2, opts) {
|
|
|
8455
8531
|
}
|
|
8456
8532
|
let token = opts.token?.trim() ?? "";
|
|
8457
8533
|
if (!token && opts.tokenFile) {
|
|
8458
|
-
const
|
|
8534
|
+
const fs20 = await import("fs");
|
|
8459
8535
|
try {
|
|
8460
|
-
token =
|
|
8536
|
+
token = fs20.readFileSync(opts.tokenFile, "utf-8").trim();
|
|
8461
8537
|
} catch (e) {
|
|
8462
8538
|
const msg = describeError(e);
|
|
8463
8539
|
throw new CliError({
|
|
@@ -11504,7 +11580,7 @@ var USERS_CLI_COMMANDS = [
|
|
|
11504
11580
|
];
|
|
11505
11581
|
|
|
11506
11582
|
// src/commands/keyword.ts
|
|
11507
|
-
import
|
|
11583
|
+
import fs8 from "fs";
|
|
11508
11584
|
function getClient14() {
|
|
11509
11585
|
return createApiClient();
|
|
11510
11586
|
}
|
|
@@ -11572,7 +11648,7 @@ async function listKeywords(project2, format) {
|
|
|
11572
11648
|
}
|
|
11573
11649
|
}
|
|
11574
11650
|
async function importKeywords(project2, filePath, format) {
|
|
11575
|
-
if (!
|
|
11651
|
+
if (!fs8.existsSync(filePath)) {
|
|
11576
11652
|
throw new CliError({
|
|
11577
11653
|
code: "KEYWORD_IMPORT_FILE_NOT_FOUND",
|
|
11578
11654
|
message: `File not found: ${filePath}`,
|
|
@@ -11583,7 +11659,7 @@ async function importKeywords(project2, filePath, format) {
|
|
|
11583
11659
|
}
|
|
11584
11660
|
});
|
|
11585
11661
|
}
|
|
11586
|
-
const content =
|
|
11662
|
+
const content = fs8.readFileSync(filePath, "utf-8");
|
|
11587
11663
|
const keywords = content.split("\n").map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
11588
11664
|
if (keywords.length === 0) {
|
|
11589
11665
|
if (isMachineFormat(format)) {
|
|
@@ -11784,7 +11860,7 @@ var KEYWORD_CLI_COMMANDS = [
|
|
|
11784
11860
|
];
|
|
11785
11861
|
|
|
11786
11862
|
// src/commands/query.ts
|
|
11787
|
-
import
|
|
11863
|
+
import fs9 from "fs";
|
|
11788
11864
|
function getClient15() {
|
|
11789
11865
|
return createApiClient();
|
|
11790
11866
|
}
|
|
@@ -11875,7 +11951,7 @@ async function listQueries(project2, format) {
|
|
|
11875
11951
|
}
|
|
11876
11952
|
}
|
|
11877
11953
|
async function importQueries(project2, filePath, format) {
|
|
11878
|
-
if (!
|
|
11954
|
+
if (!fs9.existsSync(filePath)) {
|
|
11879
11955
|
throw new CliError({
|
|
11880
11956
|
code: "QUERY_IMPORT_FILE_NOT_FOUND",
|
|
11881
11957
|
message: `File not found: ${filePath}`,
|
|
@@ -11886,7 +11962,7 @@ async function importQueries(project2, filePath, format) {
|
|
|
11886
11962
|
}
|
|
11887
11963
|
});
|
|
11888
11964
|
}
|
|
11889
|
-
const content =
|
|
11965
|
+
const content = fs9.readFileSync(filePath, "utf-8");
|
|
11890
11966
|
const queries2 = content.split("\n").map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
11891
11967
|
if (queries2.length === 0) {
|
|
11892
11968
|
if (isMachineFormat(format)) {
|
|
@@ -11950,16 +12026,16 @@ Saved ${result.queries.length} ${result.queries.length === 1 ? "query" : "querie
|
|
|
11950
12026
|
|
|
11951
12027
|
// src/commands/measurement-plan.ts
|
|
11952
12028
|
import crypto from "crypto";
|
|
11953
|
-
import
|
|
12029
|
+
import fs10 from "fs";
|
|
11954
12030
|
import { parse as parse2 } from "yaml";
|
|
11955
12031
|
import { z as z2 } from "zod";
|
|
11956
12032
|
function readPlan(source) {
|
|
11957
|
-
const content = source === "-" ?
|
|
12033
|
+
const content = source === "-" ? fs10.readFileSync(0, "utf8") : fs10.readFileSync(source, "utf8");
|
|
11958
12034
|
const parsed = source.endsWith(".json") ? JSON.parse(content) : parse2(content);
|
|
11959
12035
|
return measurementPlanInputSchema.parse(parsed);
|
|
11960
12036
|
}
|
|
11961
12037
|
function readDiscoveryRule(source) {
|
|
11962
|
-
const content = source === "-" ?
|
|
12038
|
+
const content = source === "-" ? fs10.readFileSync(0, "utf8") : fs10.readFileSync(source, "utf8");
|
|
11963
12039
|
const parsed = source.endsWith(".json") ? JSON.parse(content) : parse2(content);
|
|
11964
12040
|
return measurementDiscoveryRuleSchema.parse(parsed);
|
|
11965
12041
|
}
|
|
@@ -12012,7 +12088,7 @@ var advancedDeactivateInputSchema = z2.object({
|
|
|
12012
12088
|
}).strict();
|
|
12013
12089
|
function readAdvancedMeasurementInput(source) {
|
|
12014
12090
|
if (source === void 0) return {};
|
|
12015
|
-
const content = source === "-" ?
|
|
12091
|
+
const content = source === "-" ? fs10.readFileSync(0, "utf8") : fs10.readFileSync(source, "utf8");
|
|
12016
12092
|
return JSON.parse(content);
|
|
12017
12093
|
}
|
|
12018
12094
|
var advancedMeasurementCollectionKeys = {
|
|
@@ -12211,7 +12287,7 @@ async function replaceMeasurementPlanAssignments(project2, opts) {
|
|
|
12211
12287
|
console.log(JSON.stringify({ preview, result }, null, 2));
|
|
12212
12288
|
}
|
|
12213
12289
|
function readGroupMembershipCsv(source) {
|
|
12214
|
-
return source === "-" ?
|
|
12290
|
+
return source === "-" ? fs10.readFileSync(0, "utf8") : fs10.readFileSync(source, "utf8");
|
|
12215
12291
|
}
|
|
12216
12292
|
async function previewMeasurementPlanGroups(project2, source) {
|
|
12217
12293
|
const preview = await createApiClient().previewMeasurementDraftGroupMembership(project2, {
|
|
@@ -12562,7 +12638,7 @@ var QUERY_CLI_COMMANDS = [
|
|
|
12562
12638
|
];
|
|
12563
12639
|
|
|
12564
12640
|
// src/commands/mcp.ts
|
|
12565
|
-
import
|
|
12641
|
+
import fs11 from "fs";
|
|
12566
12642
|
import path4 from "path";
|
|
12567
12643
|
import { createRequire } from "module";
|
|
12568
12644
|
|
|
@@ -12678,8 +12754,8 @@ function renderClientSnippet(client, serverName, entry) {
|
|
|
12678
12754
|
return renderJsonSnippet(serverName, entry, client.format);
|
|
12679
12755
|
}
|
|
12680
12756
|
function readJsonConfig(configPath) {
|
|
12681
|
-
if (!
|
|
12682
|
-
const raw =
|
|
12757
|
+
if (!fs11.existsSync(configPath)) return {};
|
|
12758
|
+
const raw = fs11.readFileSync(configPath, "utf-8").trim();
|
|
12683
12759
|
if (!raw) return {};
|
|
12684
12760
|
try {
|
|
12685
12761
|
const parsed = JSON.parse(raw);
|
|
@@ -12697,14 +12773,14 @@ function readJsonConfig(configPath) {
|
|
|
12697
12773
|
}
|
|
12698
12774
|
}
|
|
12699
12775
|
function writeJsonConfig(configPath, value) {
|
|
12700
|
-
|
|
12701
|
-
|
|
12776
|
+
fs11.mkdirSync(path4.dirname(configPath), { recursive: true });
|
|
12777
|
+
fs11.writeFileSync(configPath, `${JSON.stringify(value, null, 2)}
|
|
12702
12778
|
`, "utf-8");
|
|
12703
12779
|
}
|
|
12704
12780
|
function backupConfigIfPresent(configPath) {
|
|
12705
|
-
if (!
|
|
12781
|
+
if (!fs11.existsSync(configPath)) return void 0;
|
|
12706
12782
|
const backupPath = `${configPath}.canonry.bak`;
|
|
12707
|
-
|
|
12783
|
+
fs11.copyFileSync(configPath, backupPath);
|
|
12708
12784
|
return backupPath;
|
|
12709
12785
|
}
|
|
12710
12786
|
function findClientOrThrow(id) {
|
|
@@ -13067,13 +13143,13 @@ var NOTIFY_CLI_COMMANDS = [
|
|
|
13067
13143
|
];
|
|
13068
13144
|
|
|
13069
13145
|
// src/commands/apply.ts
|
|
13070
|
-
import
|
|
13146
|
+
import fs12 from "fs";
|
|
13071
13147
|
import { parseAllDocuments } from "yaml";
|
|
13072
13148
|
async function applyConfigFile(filePath) {
|
|
13073
|
-
if (!
|
|
13149
|
+
if (!fs12.existsSync(filePath)) {
|
|
13074
13150
|
throw new Error(`File not found: ${filePath}`);
|
|
13075
13151
|
}
|
|
13076
|
-
const content =
|
|
13152
|
+
const content = fs12.readFileSync(filePath, "utf-8");
|
|
13077
13153
|
const docs = parseAllDocuments(content);
|
|
13078
13154
|
const client = createApiClient();
|
|
13079
13155
|
const errors = [];
|
|
@@ -13539,7 +13615,7 @@ async function loadLatestRunForExport(client, project2) {
|
|
|
13539
13615
|
}
|
|
13540
13616
|
|
|
13541
13617
|
// src/commands/results-export.ts
|
|
13542
|
-
import
|
|
13618
|
+
import fs13 from "fs";
|
|
13543
13619
|
import path5 from "path";
|
|
13544
13620
|
async function exportResults(project2, opts) {
|
|
13545
13621
|
const { output, ...request } = opts;
|
|
@@ -13549,8 +13625,8 @@ async function exportResults(project2, opts) {
|
|
|
13549
13625
|
return;
|
|
13550
13626
|
}
|
|
13551
13627
|
const target = output ? path5.resolve(output) : path5.resolve(process.cwd(), path5.basename(artifact.filename));
|
|
13552
|
-
|
|
13553
|
-
|
|
13628
|
+
fs13.mkdirSync(path5.dirname(target), { recursive: true });
|
|
13629
|
+
fs13.writeFileSync(target, artifact.content, "utf8");
|
|
13554
13630
|
console.log(`Results export written to ${target}`);
|
|
13555
13631
|
}
|
|
13556
13632
|
|
|
@@ -15852,11 +15928,11 @@ var SKILLS_CLI_COMMANDS = [
|
|
|
15852
15928
|
];
|
|
15853
15929
|
|
|
15854
15930
|
// src/commands/snapshot.ts
|
|
15855
|
-
import
|
|
15931
|
+
import fs15 from "fs";
|
|
15856
15932
|
import path7 from "path";
|
|
15857
15933
|
|
|
15858
15934
|
// src/snapshot-pdf.ts
|
|
15859
|
-
import
|
|
15935
|
+
import fs14 from "fs";
|
|
15860
15936
|
import path6 from "path";
|
|
15861
15937
|
import { PDFDocument, StandardFonts, rgb } from "pdf-lib";
|
|
15862
15938
|
var PAGE_WIDTH = 612;
|
|
@@ -16070,8 +16146,8 @@ async function writeSnapshotPdf(report, outputPath) {
|
|
|
16070
16146
|
renderQueries(pdf, report);
|
|
16071
16147
|
const bytes = await doc.save();
|
|
16072
16148
|
const resolvedPath = path6.resolve(outputPath);
|
|
16073
|
-
|
|
16074
|
-
|
|
16149
|
+
fs14.mkdirSync(path6.dirname(resolvedPath), { recursive: true });
|
|
16150
|
+
fs14.writeFileSync(resolvedPath, bytes);
|
|
16075
16151
|
return resolvedPath;
|
|
16076
16152
|
}
|
|
16077
16153
|
function renderCover(pdf, report) {
|
|
@@ -16232,8 +16308,8 @@ PDF saved: ${savedPdfPath}`);
|
|
|
16232
16308
|
}
|
|
16233
16309
|
function writeSnapshotMarkdown(report, outputPath) {
|
|
16234
16310
|
const resolvedPath = path7.resolve(outputPath);
|
|
16235
|
-
|
|
16236
|
-
|
|
16311
|
+
fs15.mkdirSync(path7.dirname(resolvedPath), { recursive: true });
|
|
16312
|
+
fs15.writeFileSync(resolvedPath, formatSnapshotMarkdown(report), "utf-8");
|
|
16237
16313
|
return resolvedPath;
|
|
16238
16314
|
}
|
|
16239
16315
|
function formatSnapshotMarkdown(report) {
|
|
@@ -17569,7 +17645,7 @@ async function bootstrapCommand(opts) {
|
|
|
17569
17645
|
|
|
17570
17646
|
// src/commands/daemon.ts
|
|
17571
17647
|
import { spawn as spawn2 } from "child_process";
|
|
17572
|
-
import
|
|
17648
|
+
import fs16 from "fs";
|
|
17573
17649
|
import path9 from "path";
|
|
17574
17650
|
|
|
17575
17651
|
// src/operator-url.ts
|
|
@@ -17640,8 +17716,8 @@ function buildServeForwardArgs(opts) {
|
|
|
17640
17716
|
async function startDaemon(opts) {
|
|
17641
17717
|
const pidPath = getPidPath();
|
|
17642
17718
|
const format = opts.format ?? "text";
|
|
17643
|
-
if (
|
|
17644
|
-
const existingPid = parseInt(
|
|
17719
|
+
if (fs16.existsSync(pidPath)) {
|
|
17720
|
+
const existingPid = parseInt(fs16.readFileSync(pidPath, "utf-8").trim(), 10);
|
|
17645
17721
|
if (!isNaN(existingPid) && isProcessAlive(existingPid)) {
|
|
17646
17722
|
throw new CliError({
|
|
17647
17723
|
code: "DAEMON_ALREADY_RUNNING",
|
|
@@ -17652,7 +17728,7 @@ async function startDaemon(opts) {
|
|
|
17652
17728
|
}
|
|
17653
17729
|
});
|
|
17654
17730
|
}
|
|
17655
|
-
|
|
17731
|
+
fs16.unlinkSync(pidPath);
|
|
17656
17732
|
}
|
|
17657
17733
|
const config = loadConfig();
|
|
17658
17734
|
const endpoint = resolveDaemonEndpoint(opts, process.env, config.port);
|
|
@@ -17675,10 +17751,10 @@ async function startDaemon(opts) {
|
|
|
17675
17751
|
});
|
|
17676
17752
|
}
|
|
17677
17753
|
const configDir = getConfigDir();
|
|
17678
|
-
if (!
|
|
17679
|
-
|
|
17754
|
+
if (!fs16.existsSync(configDir)) {
|
|
17755
|
+
fs16.mkdirSync(configDir, { recursive: true });
|
|
17680
17756
|
}
|
|
17681
|
-
|
|
17757
|
+
fs16.writeFileSync(pidPath, String(child.pid), "utf-8");
|
|
17682
17758
|
if (!isMachineFormat(format)) {
|
|
17683
17759
|
process.stderr.write("Waiting for server to start...");
|
|
17684
17760
|
}
|
|
@@ -17689,7 +17765,7 @@ async function startDaemon(opts) {
|
|
|
17689
17765
|
} catch {
|
|
17690
17766
|
}
|
|
17691
17767
|
try {
|
|
17692
|
-
|
|
17768
|
+
fs16.unlinkSync(pidPath);
|
|
17693
17769
|
} catch {
|
|
17694
17770
|
}
|
|
17695
17771
|
throw new CliError({
|
|
@@ -17721,7 +17797,7 @@ async function startDaemon(opts) {
|
|
|
17721
17797
|
}
|
|
17722
17798
|
function stopDaemon(format = "text") {
|
|
17723
17799
|
const pidPath = getPidPath();
|
|
17724
|
-
if (!
|
|
17800
|
+
if (!fs16.existsSync(pidPath)) {
|
|
17725
17801
|
if (isMachineFormat(format)) {
|
|
17726
17802
|
console.log(JSON.stringify({
|
|
17727
17803
|
stopped: false,
|
|
@@ -17732,7 +17808,7 @@ function stopDaemon(format = "text") {
|
|
|
17732
17808
|
console.log("Canonry is not running (no PID file found)");
|
|
17733
17809
|
return;
|
|
17734
17810
|
}
|
|
17735
|
-
const pid = parseInt(
|
|
17811
|
+
const pid = parseInt(fs16.readFileSync(pidPath, "utf-8").trim(), 10);
|
|
17736
17812
|
if (isNaN(pid)) {
|
|
17737
17813
|
if (isMachineFormat(format)) {
|
|
17738
17814
|
console.log(JSON.stringify({
|
|
@@ -17743,7 +17819,7 @@ function stopDaemon(format = "text") {
|
|
|
17743
17819
|
} else {
|
|
17744
17820
|
console.error("Invalid PID file. Removing it.");
|
|
17745
17821
|
}
|
|
17746
|
-
|
|
17822
|
+
fs16.unlinkSync(pidPath);
|
|
17747
17823
|
return;
|
|
17748
17824
|
}
|
|
17749
17825
|
if (!isProcessAlive(pid)) {
|
|
@@ -17757,12 +17833,12 @@ function stopDaemon(format = "text") {
|
|
|
17757
17833
|
} else {
|
|
17758
17834
|
console.log(`Canonry is not running (stale PID: ${pid}). Cleaning up.`);
|
|
17759
17835
|
}
|
|
17760
|
-
|
|
17836
|
+
fs16.unlinkSync(pidPath);
|
|
17761
17837
|
return;
|
|
17762
17838
|
}
|
|
17763
17839
|
try {
|
|
17764
17840
|
process.kill(pid, "SIGTERM");
|
|
17765
|
-
|
|
17841
|
+
fs16.unlinkSync(pidPath);
|
|
17766
17842
|
if (isMachineFormat(format)) {
|
|
17767
17843
|
console.log(JSON.stringify({
|
|
17768
17844
|
stopped: true,
|
|
@@ -17786,7 +17862,7 @@ function stopDaemon(format = "text") {
|
|
|
17786
17862
|
|
|
17787
17863
|
// src/commands/init.ts
|
|
17788
17864
|
import crypto3 from "crypto";
|
|
17789
|
-
import
|
|
17865
|
+
import fs17 from "fs";
|
|
17790
17866
|
import readline2 from "readline";
|
|
17791
17867
|
import path10 from "path";
|
|
17792
17868
|
var pendingServeHandoff = false;
|
|
@@ -17824,7 +17900,7 @@ var PROJECT_MARKERS = [".git", "canonry.yaml", "canonry.yml", "package.json"];
|
|
|
17824
17900
|
function cwdLooksLikeProject(dir) {
|
|
17825
17901
|
const home = process.env.HOME ?? "";
|
|
17826
17902
|
if (home && path10.resolve(dir) === path10.resolve(home)) return false;
|
|
17827
|
-
return PROJECT_MARKERS.some((marker) =>
|
|
17903
|
+
return PROJECT_MARKERS.some((marker) => fs17.existsSync(path10.join(dir, marker)));
|
|
17828
17904
|
}
|
|
17829
17905
|
var DEFAULT_AGENT_MODELS = {
|
|
17830
17906
|
anthropic: "anthropic/claude-sonnet-4-6",
|
|
@@ -17855,8 +17931,8 @@ async function initCommand(opts) {
|
|
|
17855
17931
|
return void 0;
|
|
17856
17932
|
}
|
|
17857
17933
|
const configDir = getConfigDir();
|
|
17858
|
-
if (!
|
|
17859
|
-
|
|
17934
|
+
if (!fs17.existsSync(configDir)) {
|
|
17935
|
+
fs17.mkdirSync(configDir, { recursive: true });
|
|
17860
17936
|
}
|
|
17861
17937
|
const bootstrapEnv = getBootstrapEnv(process.env, {
|
|
17862
17938
|
GEMINI_API_KEY: opts?.geminiKey,
|
|
@@ -18208,7 +18284,7 @@ async function repairPathsOnce(db, name, repair) {
|
|
|
18208
18284
|
}
|
|
18209
18285
|
|
|
18210
18286
|
// src/agent-plugin.ts
|
|
18211
|
-
import
|
|
18287
|
+
import fs18 from "fs";
|
|
18212
18288
|
import path11 from "path";
|
|
18213
18289
|
var CANONRY_PLUGIN_ID = "canonry@canonry";
|
|
18214
18290
|
var REQUIRED_SKILLS = ["canonry", "aero"];
|
|
@@ -18253,7 +18329,7 @@ function isCanonryPluginId(value) {
|
|
|
18253
18329
|
}
|
|
18254
18330
|
function readJson(filePath) {
|
|
18255
18331
|
try {
|
|
18256
|
-
return JSON.parse(
|
|
18332
|
+
return JSON.parse(fs18.readFileSync(filePath, "utf8"));
|
|
18257
18333
|
} catch {
|
|
18258
18334
|
return null;
|
|
18259
18335
|
}
|
|
@@ -18272,7 +18348,7 @@ function readCodexPluginConfigured(filePath) {
|
|
|
18272
18348
|
try {
|
|
18273
18349
|
let currentPlugin = null;
|
|
18274
18350
|
let inPluginsTable = false;
|
|
18275
|
-
for (const line of
|
|
18351
|
+
for (const line of fs18.readFileSync(filePath, "utf8").split(/\r?\n/)) {
|
|
18276
18352
|
const section = /^\s*\[plugins\.(?:"([^"]+)"|'([^']+)'|(\S+))\]\s*(?:#.*)?$/.exec(line);
|
|
18277
18353
|
if (section) {
|
|
18278
18354
|
const captures = section.slice(1, 4);
|
|
@@ -18305,7 +18381,7 @@ function readCodexPluginConfigured(filePath) {
|
|
|
18305
18381
|
}
|
|
18306
18382
|
}
|
|
18307
18383
|
function verifiedPluginVersion(root, client) {
|
|
18308
|
-
if (client === "codex" &&
|
|
18384
|
+
if (client === "codex" && fs18.existsSync(path11.join(root, "plugin.json"))) {
|
|
18309
18385
|
const manifest2 = readJson(path11.join(root, "plugin.json"));
|
|
18310
18386
|
if (manifest2 && typeof manifest2 === "object") {
|
|
18311
18387
|
const plugin2 = manifest2;
|
|
@@ -18319,7 +18395,7 @@ function verifiedPluginVersion(root, client) {
|
|
|
18319
18395
|
if (portableMcp.$schema !== AGENT_PLUGINS_MCP_SCHEMA || portableMcp.mcpServers?.canonry?.type !== "stdio" || portableMcp.mcpServers.canonry.command !== "canonry-mcp") {
|
|
18320
18396
|
return null;
|
|
18321
18397
|
}
|
|
18322
|
-
return REQUIRED_SKILLS.every((name) =>
|
|
18398
|
+
return REQUIRED_SKILLS.every((name) => fs18.existsSync(path11.join(root, "skills", name, "SKILL.md"))) ? plugin2.version : null;
|
|
18323
18399
|
}
|
|
18324
18400
|
if (typeof plugin2.$schema === "string" && plugin2.$schema.startsWith("https://agent-plugins.org/schemas/")) {
|
|
18325
18401
|
return null;
|
|
@@ -18337,7 +18413,7 @@ function verifiedPluginVersion(root, client) {
|
|
|
18337
18413
|
if (!mcp || typeof mcp !== "object") return null;
|
|
18338
18414
|
const canonryServer = mcp.mcpServers?.canonry;
|
|
18339
18415
|
if (canonryServer?.command !== "canonry-mcp") return null;
|
|
18340
|
-
return REQUIRED_SKILLS.every((name) =>
|
|
18416
|
+
return REQUIRED_SKILLS.every((name) => fs18.existsSync(path11.join(root, "skills", name, "SKILL.md"))) ? plugin.version : null;
|
|
18341
18417
|
}
|
|
18342
18418
|
function readClaudeUserInstallPaths(claudeConfigDir) {
|
|
18343
18419
|
const parsed = readJson(path11.join(claudeConfigDir, "plugins", "installed_plugins.json"));
|
|
@@ -18354,7 +18430,7 @@ function readClaudeUserInstallPaths(claudeConfigDir) {
|
|
|
18354
18430
|
}
|
|
18355
18431
|
function listDirectories(dir) {
|
|
18356
18432
|
try {
|
|
18357
|
-
return
|
|
18433
|
+
return fs18.readdirSync(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => path11.join(dir, entry.name));
|
|
18358
18434
|
} catch {
|
|
18359
18435
|
return [];
|
|
18360
18436
|
}
|
|
@@ -20242,7 +20318,7 @@ var VISIBILITY_STATS_CLI_COMMANDS = [
|
|
|
20242
20318
|
];
|
|
20243
20319
|
|
|
20244
20320
|
// src/cli-commands/wordpress.ts
|
|
20245
|
-
import
|
|
20321
|
+
import fs19 from "fs";
|
|
20246
20322
|
|
|
20247
20323
|
// src/commands/wordpress.ts
|
|
20248
20324
|
function getClient28() {
|
|
@@ -20481,12 +20557,12 @@ async function wordpressSetMeta(project2, body) {
|
|
|
20481
20557
|
printPageDetail(result);
|
|
20482
20558
|
}
|
|
20483
20559
|
async function wordpressBulkSetMeta(project2, opts) {
|
|
20484
|
-
const
|
|
20560
|
+
const fs20 = await import("fs/promises");
|
|
20485
20561
|
const path12 = await import("path");
|
|
20486
20562
|
const filePath = path12.resolve(opts.from);
|
|
20487
20563
|
let raw;
|
|
20488
20564
|
try {
|
|
20489
|
-
raw = await
|
|
20565
|
+
raw = await fs20.readFile(filePath, "utf8");
|
|
20490
20566
|
} catch {
|
|
20491
20567
|
throw new CliError({
|
|
20492
20568
|
code: "FILE_READ_ERROR",
|
|
@@ -20583,13 +20659,13 @@ async function wordpressSetSchema(project2, body) {
|
|
|
20583
20659
|
printManualAssist(`Schema update for "${body.slug}"`, result);
|
|
20584
20660
|
}
|
|
20585
20661
|
async function wordpressSchemaDeploy(project2, opts) {
|
|
20586
|
-
const
|
|
20662
|
+
const fs20 = await import("fs/promises");
|
|
20587
20663
|
const path12 = await import("path");
|
|
20588
20664
|
const yaml = await loadYamlModule();
|
|
20589
20665
|
const filePath = path12.resolve(opts.profile);
|
|
20590
20666
|
let raw;
|
|
20591
20667
|
try {
|
|
20592
|
-
raw = await
|
|
20668
|
+
raw = await fs20.readFile(filePath, "utf8");
|
|
20593
20669
|
} catch {
|
|
20594
20670
|
throw new CliError({
|
|
20595
20671
|
code: "FILE_READ_ERROR",
|
|
@@ -20694,13 +20770,13 @@ async function wordpressOnboard(project2, opts) {
|
|
|
20694
20770
|
}
|
|
20695
20771
|
let profileData;
|
|
20696
20772
|
if (opts.profile) {
|
|
20697
|
-
const
|
|
20773
|
+
const fs20 = await import("fs/promises");
|
|
20698
20774
|
const path12 = await import("path");
|
|
20699
20775
|
const yaml = await loadYamlModule();
|
|
20700
20776
|
const filePath = path12.resolve(opts.profile);
|
|
20701
20777
|
let raw;
|
|
20702
20778
|
try {
|
|
20703
|
-
raw = await
|
|
20779
|
+
raw = await fs20.readFile(filePath, "utf8");
|
|
20704
20780
|
} catch {
|
|
20705
20781
|
throw new CliError({
|
|
20706
20782
|
code: "FILE_READ_ERROR",
|
|
@@ -20849,7 +20925,7 @@ function resolveContent(input, command, usage, options) {
|
|
|
20849
20925
|
}
|
|
20850
20926
|
if (contentFile) {
|
|
20851
20927
|
try {
|
|
20852
|
-
return
|
|
20928
|
+
return fs19.readFileSync(contentFile, "utf-8");
|
|
20853
20929
|
} catch (error) {
|
|
20854
20930
|
const message = describeError(error);
|
|
20855
20931
|
throw usageError(`Error: could not read --content-file "${contentFile}": ${message}`, {
|
|
@@ -22165,6 +22241,7 @@ var REGISTERED_CLI_COMMANDS = [
|
|
|
22165
22241
|
...USERS_CLI_COMMANDS,
|
|
22166
22242
|
...COMPETITOR_CLI_COMMANDS,
|
|
22167
22243
|
...SETTINGS_CLI_COMMANDS,
|
|
22244
|
+
...DASHBOARD_CLI_COMMANDS,
|
|
22168
22245
|
...SKILLS_CLI_COMMANDS,
|
|
22169
22246
|
...SNAPSHOT_CLI_COMMANDS,
|
|
22170
22247
|
...RUN_CLI_COMMANDS,
|
|
@@ -22304,6 +22381,7 @@ Automation:
|
|
|
22304
22381
|
|
|
22305
22382
|
Admin:
|
|
22306
22383
|
settings Show/update provider and quota settings
|
|
22384
|
+
dashboard Reset the dashboard password
|
|
22307
22385
|
backfill Backfill answer visibility or insights
|
|
22308
22386
|
telemetry Manage anonymous telemetry
|
|
22309
22387
|
history <project> Show audit trail
|
package/dist/index.js
CHANGED
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
createGoogleMarketingCredentialStore,
|
|
4
4
|
createGoogleMarketingRuntime,
|
|
5
5
|
createServer
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-3OPV5XBY.js";
|
|
7
7
|
import {
|
|
8
8
|
loadConfig
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-UF7MH6TU.js";
|
|
10
10
|
import "./chunk-222NAFTY.js";
|
|
11
11
|
import "./chunk-5IXQAOVK.js";
|
|
12
12
|
import "./chunk-46JZR2IV.js";
|
package/dist/mcp.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
autoSyncSkills
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-KWBFKTOA.js";
|
|
4
4
|
import {
|
|
5
5
|
createApiClient,
|
|
6
6
|
createCanonryMcpServer
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-UF7MH6TU.js";
|
|
8
8
|
import "./chunk-5IXQAOVK.js";
|
|
9
9
|
import {
|
|
10
10
|
isReadOnlyKey,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonry/canonry",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.23.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Self-hosted AI visibility (AEO) platform: track how ChatGPT, Claude, Gemini, and Perplexity cite your domain, join it with Search Console, GA4, server-side traffic, and paid media, and fix what you find through agent tools (CLI, REST, MCP). Local SQLite.",
|
|
6
6
|
"keywords": [
|
|
@@ -85,34 +85,34 @@
|
|
|
85
85
|
"@types/node-cron": "^3.0.11",
|
|
86
86
|
"tsup": "^8.5.1",
|
|
87
87
|
"tsx": "^4.19.0",
|
|
88
|
-
"@ainyc/canonry-api-client": "0.0.0",
|
|
89
|
-
"@ainyc/canonry-api-routes": "0.0.0",
|
|
90
88
|
"@ainyc/canonry-web": "0.0.0",
|
|
89
|
+
"@ainyc/canonry-api-routes": "0.0.0",
|
|
90
|
+
"@ainyc/canonry-api-client": "0.0.0",
|
|
91
91
|
"@ainyc/canonry-config": "0.0.0",
|
|
92
|
-
"@ainyc/canonry-db": "0.0.0",
|
|
93
92
|
"@ainyc/canonry-contracts": "0.0.0",
|
|
93
|
+
"@ainyc/canonry-db": "0.0.0",
|
|
94
|
+
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
94
95
|
"@ainyc/canonry-integration-cloud-run": "0.0.0",
|
|
95
96
|
"@ainyc/canonry-integration-cloudflare-queue": "0.0.0",
|
|
96
97
|
"@ainyc/canonry-integration-commoncrawl": "0.0.0",
|
|
97
98
|
"@ainyc/canonry-integration-google": "0.0.0",
|
|
98
99
|
"@ainyc/canonry-integration-cloudflare-worker": "0.0.0",
|
|
99
|
-
"@ainyc/canonry-integration-bing": "0.0.0",
|
|
100
|
-
"@ainyc/canonry-integration-google-ads": "0.0.0",
|
|
101
|
-
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
102
|
-
"@ainyc/canonry-integration-google-business-profile": "0.0.0",
|
|
103
100
|
"@ainyc/canonry-integration-google-tag-manager": "0.0.0",
|
|
101
|
+
"@ainyc/canonry-integration-google-business-profile": "0.0.0",
|
|
102
|
+
"@ainyc/canonry-integration-google-places": "0.0.0",
|
|
103
|
+
"@ainyc/canonry-integration-google-ads": "0.0.0",
|
|
104
104
|
"@ainyc/canonry-integration-openai-ads": "0.0.0",
|
|
105
105
|
"@ainyc/canonry-integration-traffic": "0.0.0",
|
|
106
106
|
"@ainyc/canonry-integration-wordpress": "0.0.0",
|
|
107
|
-
"@ainyc/canonry-intelligence": "0.0.0",
|
|
108
|
-
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
109
107
|
"@ainyc/canonry-provider-cdp": "0.0.0",
|
|
110
108
|
"@ainyc/canonry-provider-claude": "0.0.0",
|
|
111
|
-
"@ainyc/canonry-
|
|
109
|
+
"@ainyc/canonry-intelligence": "0.0.0",
|
|
110
|
+
"@ainyc/canonry-provider-gemini": "0.0.0",
|
|
111
|
+
"@ainyc/canonry-provider-muse": "0.0.0",
|
|
112
112
|
"@ainyc/canonry-provider-openai": "0.0.0",
|
|
113
|
+
"@ainyc/canonry-integration-typesafe": "0.0.0",
|
|
113
114
|
"@ainyc/canonry-provider-perplexity": "0.0.0",
|
|
114
|
-
"@ainyc/canonry-provider-
|
|
115
|
-
"@ainyc/canonry-integration-typesafe": "0.0.0"
|
|
115
|
+
"@ainyc/canonry-provider-local": "0.0.0"
|
|
116
116
|
},
|
|
117
117
|
"scripts": {
|
|
118
118
|
"build": "pnpm run build:cli && pnpm run build:web",
|