agent-insights 0.0.9 → 0.0.12
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/cli.js +206 -98
- package/dist/cli.js.map +1 -1
- package/dist/index.js +68 -24
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -21,6 +21,9 @@ function configFile() {
|
|
|
21
21
|
function authFile() {
|
|
22
22
|
return join(configRoot(), "auth.json");
|
|
23
23
|
}
|
|
24
|
+
function bypassSecretFile() {
|
|
25
|
+
return join(configRoot(), "bypass-secret");
|
|
26
|
+
}
|
|
24
27
|
function sessionCacheDir() {
|
|
25
28
|
return join(configRoot(), "session-cache");
|
|
26
29
|
}
|
|
@@ -251,9 +254,9 @@ async function saveAuth(state) {
|
|
|
251
254
|
}
|
|
252
255
|
}
|
|
253
256
|
async function clearAuth() {
|
|
254
|
-
const { unlink } = await import("fs/promises");
|
|
257
|
+
const { unlink: unlink2 } = await import("fs/promises");
|
|
255
258
|
try {
|
|
256
|
-
await
|
|
259
|
+
await unlink2(authFile());
|
|
257
260
|
} catch (err) {
|
|
258
261
|
if (err.code !== "ENOENT") throw err;
|
|
259
262
|
}
|
|
@@ -299,9 +302,17 @@ import { spawn } from "child_process";
|
|
|
299
302
|
import { randomUUID } from "crypto";
|
|
300
303
|
|
|
301
304
|
// src/config/config.ts
|
|
302
|
-
init_paths();
|
|
303
305
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
304
306
|
import { dirname } from "path";
|
|
307
|
+
|
|
308
|
+
// src/config/analyzer.ts
|
|
309
|
+
var DEFAULT_ANALYZER_URL = "https://agent-insights.labs.vercel.dev";
|
|
310
|
+
function getAnalyzerUrl() {
|
|
311
|
+
return process.env.AGENT_INSIGHTS_ANALYZER_URL || DEFAULT_ANALYZER_URL;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// src/config/config.ts
|
|
315
|
+
init_paths();
|
|
305
316
|
function defaultConfig() {
|
|
306
317
|
return {
|
|
307
318
|
version: 1,
|
|
@@ -330,7 +341,7 @@ function defaultConfig() {
|
|
|
330
341
|
},
|
|
331
342
|
sessionAnalysis: {
|
|
332
343
|
enabled: false,
|
|
333
|
-
analyzerUrl:
|
|
344
|
+
analyzerUrl: getAnalyzerUrl(),
|
|
334
345
|
githubIssueRepo: "vercel-labs/agent-insights"
|
|
335
346
|
},
|
|
336
347
|
agents: {
|
|
@@ -878,8 +889,49 @@ init_store();
|
|
|
878
889
|
|
|
879
890
|
// src/transcript/store.ts
|
|
880
891
|
init_store();
|
|
881
|
-
import { readFile as
|
|
892
|
+
import { readFile as readFile6 } from "fs/promises";
|
|
882
893
|
import { put } from "@vercel/blob";
|
|
894
|
+
|
|
895
|
+
// src/config/bypass.ts
|
|
896
|
+
init_paths();
|
|
897
|
+
import { chmod as chmod2, mkdir as mkdir5, readFile as readFile5, unlink, writeFile as writeFile5 } from "fs/promises";
|
|
898
|
+
import { dirname as dirname5 } from "path";
|
|
899
|
+
async function loadBypassSecret() {
|
|
900
|
+
const fromEnv = process.env.AGENT_INSIGHTS_BYPASS_SECRET || process.env.VERCEL_AUTOMATION_BYPASS_SECRET;
|
|
901
|
+
if (fromEnv) return fromEnv;
|
|
902
|
+
try {
|
|
903
|
+
const raw = (await readFile5(bypassSecretFile(), "utf8")).trim();
|
|
904
|
+
return raw || void 0;
|
|
905
|
+
} catch (err) {
|
|
906
|
+
if (err.code === "ENOENT") return void 0;
|
|
907
|
+
throw err;
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
async function saveBypassSecret(secret) {
|
|
911
|
+
const path = bypassSecretFile();
|
|
912
|
+
await mkdir5(dirname5(path), { recursive: true });
|
|
913
|
+
await writeFile5(path, secret.trim(), { encoding: "utf8", mode: 384 });
|
|
914
|
+
try {
|
|
915
|
+
await chmod2(path, 384);
|
|
916
|
+
} catch {
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
async function clearBypassSecret() {
|
|
920
|
+
try {
|
|
921
|
+
await unlink(bypassSecretFile());
|
|
922
|
+
} catch (err) {
|
|
923
|
+
if (err.code !== "ENOENT") throw err;
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
async function withBypassHeader(headers) {
|
|
927
|
+
const secret = await loadBypassSecret();
|
|
928
|
+
if (secret) {
|
|
929
|
+
headers["x-vercel-protection-bypass"] = secret;
|
|
930
|
+
}
|
|
931
|
+
return headers;
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
// src/transcript/store.ts
|
|
883
935
|
var NoopTranscriptStore = class {
|
|
884
936
|
async upload() {
|
|
885
937
|
throw new Error("transcript store disabled (transcriptStore.type=none)");
|
|
@@ -896,7 +948,7 @@ var BlobTranscriptStore = class {
|
|
|
896
948
|
token;
|
|
897
949
|
prefix;
|
|
898
950
|
async upload(input) {
|
|
899
|
-
const body = await
|
|
951
|
+
const body = await readFile6(input.transcriptPath);
|
|
900
952
|
const requestedPath = buildPathname(
|
|
901
953
|
this.prefix,
|
|
902
954
|
input.userHash,
|
|
@@ -927,19 +979,16 @@ var AnalyzerTranscriptStore = class {
|
|
|
927
979
|
"transcript store: not logged in \u2014 run `agent-insights login`"
|
|
928
980
|
);
|
|
929
981
|
}
|
|
930
|
-
const body = await
|
|
982
|
+
const body = await readFile6(input.transcriptPath);
|
|
931
983
|
const url = new URL("/api/sessions/upload", this.analyzerUrl).toString();
|
|
932
|
-
const
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
"x-agent": input.agent,
|
|
939
|
-
"x-user-hash": input.userHash
|
|
940
|
-
},
|
|
941
|
-
body
|
|
984
|
+
const headers = await withBypassHeader({
|
|
985
|
+
authorization: `Bearer ${token}`,
|
|
986
|
+
"content-type": "application/jsonl",
|
|
987
|
+
"x-session-id": input.sessionId,
|
|
988
|
+
"x-agent": input.agent,
|
|
989
|
+
"x-user-hash": input.userHash
|
|
942
990
|
});
|
|
991
|
+
const res = await fetch(url, { method: "POST", headers, body });
|
|
943
992
|
if (!res.ok) {
|
|
944
993
|
const text = await res.text().catch(() => "");
|
|
945
994
|
throw new Error(
|
|
@@ -957,27 +1006,43 @@ var AnalyzerTranscriptStore = class {
|
|
|
957
1006
|
};
|
|
958
1007
|
}
|
|
959
1008
|
async ping() {
|
|
960
|
-
|
|
1009
|
+
const token = await getValidToken();
|
|
1010
|
+
if (!token) {
|
|
961
1011
|
return {
|
|
962
1012
|
ok: false,
|
|
963
|
-
reason: "
|
|
1013
|
+
reason: "not logged in \u2014 run `agent-insights login`"
|
|
964
1014
|
};
|
|
965
1015
|
}
|
|
966
|
-
|
|
967
|
-
|
|
1016
|
+
try {
|
|
1017
|
+
const url = new URL("/api/sessions/upload", this.analyzerUrl).toString();
|
|
1018
|
+
const headers = await withBypassHeader({
|
|
1019
|
+
authorization: `Bearer ${token}`
|
|
1020
|
+
});
|
|
1021
|
+
const res = await fetch(url, { method: "POST", headers });
|
|
1022
|
+
if (res.status === 400) return { ok: true };
|
|
1023
|
+
if (res.status === 401 || res.status === 403) {
|
|
1024
|
+
const ct = res.headers.get("content-type") ?? "";
|
|
1025
|
+
if (ct.includes("text/html")) {
|
|
1026
|
+
return {
|
|
1027
|
+
ok: false,
|
|
1028
|
+
reason: "blocked by Vercel deployment protection \u2014 set a bypass secret via `agent-insights init --bypass-secret <secret>`"
|
|
1029
|
+
};
|
|
1030
|
+
}
|
|
1031
|
+
return { ok: false, reason: `analyzer rejected token (${res.status})` };
|
|
1032
|
+
}
|
|
1033
|
+
return { ok: false, reason: `unexpected status ${res.status}` };
|
|
1034
|
+
} catch (err) {
|
|
968
1035
|
return {
|
|
969
1036
|
ok: false,
|
|
970
|
-
reason:
|
|
1037
|
+
reason: `analyzer unreachable: ${err.message}`
|
|
971
1038
|
};
|
|
972
1039
|
}
|
|
973
|
-
return { ok: true };
|
|
974
1040
|
}
|
|
975
1041
|
};
|
|
976
1042
|
function createTranscriptStore(cfg) {
|
|
977
1043
|
if (cfg.type === "none") return new NoopTranscriptStore();
|
|
978
1044
|
if (cfg.type === "analyzer") {
|
|
979
|
-
|
|
980
|
-
return new AnalyzerTranscriptStore(analyzerUrl);
|
|
1045
|
+
return new AnalyzerTranscriptStore(getAnalyzerUrl());
|
|
981
1046
|
}
|
|
982
1047
|
const token = process.env[cfg.tokenEnv];
|
|
983
1048
|
if (!token) {
|
|
@@ -1093,9 +1158,9 @@ async function runHook(eventName, opts) {
|
|
|
1093
1158
|
size: result.size,
|
|
1094
1159
|
pathname: result.pathname
|
|
1095
1160
|
});
|
|
1096
|
-
if (cfg.userConsent.sessionAnalysis
|
|
1161
|
+
if (cfg.userConsent.sessionAnalysis) {
|
|
1097
1162
|
await notifyAnalyzer({
|
|
1098
|
-
analyzerUrl:
|
|
1163
|
+
analyzerUrl: getAnalyzerUrl(),
|
|
1099
1164
|
payload: {
|
|
1100
1165
|
sessionId: mapped.sessionId ?? "unknown",
|
|
1101
1166
|
agent: adapter.id,
|
|
@@ -1115,10 +1180,11 @@ async function notifyAnalyzer(opts) {
|
|
|
1115
1180
|
try {
|
|
1116
1181
|
const { getValidToken: getValidToken2 } = await Promise.resolve().then(() => (init_store(), store_exports));
|
|
1117
1182
|
const token = await getValidToken2();
|
|
1118
|
-
const
|
|
1183
|
+
const baseHeaders = {
|
|
1119
1184
|
"content-type": "application/json"
|
|
1120
1185
|
};
|
|
1121
|
-
if (token)
|
|
1186
|
+
if (token) baseHeaders["authorization"] = `Bearer ${token}`;
|
|
1187
|
+
const headers = await withBypassHeader(baseHeaders);
|
|
1122
1188
|
const url = new URL("/api/sessions", opts.analyzerUrl).toString();
|
|
1123
1189
|
const res = await fetch(url, {
|
|
1124
1190
|
method: "POST",
|
|
@@ -1207,7 +1273,7 @@ function parseJsonObject(raw) {
|
|
|
1207
1273
|
}
|
|
1208
1274
|
|
|
1209
1275
|
// src/commands/init.ts
|
|
1210
|
-
import {
|
|
1276
|
+
import { checkbox, confirm, password } from "@inquirer/prompts";
|
|
1211
1277
|
import kleur3 from "kleur";
|
|
1212
1278
|
init_paths();
|
|
1213
1279
|
init_store();
|
|
@@ -1232,33 +1298,43 @@ async function runInit(opts) {
|
|
|
1232
1298
|
log.info("");
|
|
1233
1299
|
const existing = await loadConfig();
|
|
1234
1300
|
const interactive = !opts.yes && Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
choices = await promptChoices(opts, existing !== null);
|
|
1238
|
-
} else {
|
|
1239
|
-
if (existing && !opts.force) {
|
|
1301
|
+
if (existing && !opts.force) {
|
|
1302
|
+
if (!interactive) {
|
|
1240
1303
|
log.warn(
|
|
1241
1304
|
`Config already exists at ${configFile()} \u2014 re-run with --force to overwrite, or use interactive mode.`
|
|
1242
1305
|
);
|
|
1243
1306
|
return;
|
|
1244
1307
|
}
|
|
1308
|
+
log.warn(`Config already exists at ${configFile()}.`);
|
|
1309
|
+
const overwrite = await safePrompt(
|
|
1310
|
+
() => confirm({ message: "Overwrite existing config?", default: true })
|
|
1311
|
+
);
|
|
1312
|
+
if (overwrite === void 0) return;
|
|
1313
|
+
if (!overwrite) {
|
|
1314
|
+
log.info("Aborted \u2014 existing config left in place.");
|
|
1315
|
+
return;
|
|
1316
|
+
}
|
|
1317
|
+
log.info("");
|
|
1318
|
+
}
|
|
1319
|
+
let choices;
|
|
1320
|
+
if (interactive) {
|
|
1321
|
+
const result = await promptChoices(opts);
|
|
1322
|
+
if (!result) return;
|
|
1323
|
+
choices = result;
|
|
1324
|
+
} else {
|
|
1245
1325
|
choices = {
|
|
1246
1326
|
agents: parseAgents(opts.agents),
|
|
1247
1327
|
transcripts: opts.transcripts ?? true,
|
|
1248
|
-
analysis: opts.analysis ??
|
|
1249
|
-
telemetry: opts.telemetry ??
|
|
1250
|
-
|
|
1328
|
+
analysis: opts.analysis ?? true,
|
|
1329
|
+
telemetry: opts.telemetry ?? true,
|
|
1330
|
+
bypassSecret: opts.bypassSecret
|
|
1251
1331
|
};
|
|
1252
1332
|
}
|
|
1253
|
-
if (existing && !choices.overwrite) {
|
|
1254
|
-
log.info("Aborted \u2014 existing config left in place.");
|
|
1255
|
-
return;
|
|
1256
|
-
}
|
|
1257
1333
|
if (choices.agents.size === 0) {
|
|
1258
1334
|
log.fail("No agents selected \u2014 nothing to install.");
|
|
1259
1335
|
process.exit(1);
|
|
1260
1336
|
}
|
|
1261
|
-
const cfg =
|
|
1337
|
+
const cfg = defaultConfig();
|
|
1262
1338
|
cfg.userConsent.transcriptSync = choices.transcripts;
|
|
1263
1339
|
cfg.userConsent.sessionAnalysis = choices.analysis;
|
|
1264
1340
|
cfg.userConsent.eventTelemetry = choices.telemetry;
|
|
@@ -1266,6 +1342,15 @@ async function runInit(opts) {
|
|
|
1266
1342
|
cfg.agents.cursor.enabled = choices.agents.has("cursor");
|
|
1267
1343
|
await saveConfig(cfg);
|
|
1268
1344
|
log.ok(`Wrote config to ${configFile()}`);
|
|
1345
|
+
if (choices.bypassSecret !== void 0) {
|
|
1346
|
+
if (choices.bypassSecret === "") {
|
|
1347
|
+
await clearBypassSecret();
|
|
1348
|
+
log.ok("Cleared stored deployment-protection bypass secret.");
|
|
1349
|
+
} else {
|
|
1350
|
+
await saveBypassSecret(choices.bypassSecret);
|
|
1351
|
+
log.ok("Saved deployment-protection bypass secret.");
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1269
1354
|
const installHooks = opts.hooks ?? true;
|
|
1270
1355
|
const repoRoot = process.cwd();
|
|
1271
1356
|
if (installHooks) {
|
|
@@ -1280,65 +1365,85 @@ async function runInit(opts) {
|
|
|
1280
1365
|
log.info(`Config root: ${configRoot()}`);
|
|
1281
1366
|
log.hint("Run `agent-insights doctor` to verify the setup.");
|
|
1282
1367
|
}
|
|
1283
|
-
async function promptChoices(opts
|
|
1284
|
-
const
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
)
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1368
|
+
async function promptChoices(opts) {
|
|
1369
|
+
const requested = opts.agents ? parseAgents(opts.agents) : null;
|
|
1370
|
+
const selected = await safePrompt(
|
|
1371
|
+
() => checkbox({
|
|
1372
|
+
message: "Which agents would you like to install hooks for?",
|
|
1373
|
+
choices: adapterList.map((adapter) => ({
|
|
1374
|
+
name: adapter.label,
|
|
1375
|
+
value: adapter.id,
|
|
1376
|
+
checked: requested ? requested.has(adapter.id) : true
|
|
1377
|
+
})),
|
|
1378
|
+
required: true
|
|
1379
|
+
})
|
|
1380
|
+
);
|
|
1381
|
+
if (selected === void 0) return void 0;
|
|
1382
|
+
const transcripts = await safePrompt(
|
|
1383
|
+
() => confirm({
|
|
1384
|
+
message: "Sync session transcripts to Vercel Blob?",
|
|
1385
|
+
default: opts.transcripts ?? true
|
|
1386
|
+
})
|
|
1387
|
+
);
|
|
1388
|
+
if (transcripts === void 0) return void 0;
|
|
1389
|
+
const analysis = await safePrompt(
|
|
1390
|
+
() => confirm({
|
|
1391
|
+
message: "Enable SessionEnd analysis (internal LLM review)?",
|
|
1392
|
+
default: opts.analysis ?? true
|
|
1393
|
+
})
|
|
1394
|
+
);
|
|
1395
|
+
if (analysis === void 0) return void 0;
|
|
1396
|
+
const telemetry = await safePrompt(
|
|
1397
|
+
() => confirm({
|
|
1398
|
+
message: "Send OTLP event telemetry?",
|
|
1399
|
+
default: opts.telemetry ?? true
|
|
1400
|
+
})
|
|
1401
|
+
);
|
|
1402
|
+
if (telemetry === void 0) return void 0;
|
|
1403
|
+
let bypassSecret;
|
|
1404
|
+
if (opts.bypassSecret !== void 0) {
|
|
1405
|
+
bypassSecret = opts.bypassSecret;
|
|
1406
|
+
} else {
|
|
1407
|
+
const existing = await loadBypassSecret();
|
|
1408
|
+
const answer = await safePrompt(
|
|
1409
|
+
() => password({
|
|
1410
|
+
message: existing ? "Vercel deployment-protection bypass secret (Enter to keep existing, '-' to clear):" : "Vercel deployment-protection bypass secret (Enter to skip):",
|
|
1411
|
+
mask: true
|
|
1412
|
+
})
|
|
1317
1413
|
);
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1414
|
+
if (answer === void 0) return void 0;
|
|
1415
|
+
const trimmed = answer.trim();
|
|
1416
|
+
if (trimmed === "") bypassSecret = void 0;
|
|
1417
|
+
else if (trimmed === "-") bypassSecret = "";
|
|
1418
|
+
else bypassSecret = trimmed;
|
|
1322
1419
|
}
|
|
1323
|
-
}
|
|
1324
|
-
function emptyChoices() {
|
|
1325
1420
|
return {
|
|
1326
|
-
agents:
|
|
1327
|
-
transcripts
|
|
1328
|
-
analysis
|
|
1329
|
-
telemetry
|
|
1330
|
-
|
|
1421
|
+
agents: new Set(selected),
|
|
1422
|
+
transcripts,
|
|
1423
|
+
analysis,
|
|
1424
|
+
telemetry,
|
|
1425
|
+
bypassSecret
|
|
1331
1426
|
};
|
|
1332
1427
|
}
|
|
1333
|
-
async function
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1428
|
+
async function safePrompt(run) {
|
|
1429
|
+
try {
|
|
1430
|
+
return await run();
|
|
1431
|
+
} catch (err) {
|
|
1432
|
+
if (err instanceof Error && (err.name === "ExitPromptError" || err.name === "AbortPromptError")) {
|
|
1433
|
+
log.info("Aborted.");
|
|
1434
|
+
return void 0;
|
|
1435
|
+
}
|
|
1436
|
+
throw err;
|
|
1437
|
+
}
|
|
1338
1438
|
}
|
|
1339
1439
|
function parseAgents(value) {
|
|
1340
1440
|
const out = /* @__PURE__ */ new Set();
|
|
1341
|
-
const
|
|
1441
|
+
const trimmed = (value ?? "").trim();
|
|
1442
|
+
if (trimmed === "*") {
|
|
1443
|
+
for (const a of adapterList) out.add(a.id);
|
|
1444
|
+
return out;
|
|
1445
|
+
}
|
|
1446
|
+
const list = (trimmed || "claude-code,cursor").split(",").map((s) => s.trim()).filter(Boolean);
|
|
1342
1447
|
for (const id of list) {
|
|
1343
1448
|
if (id === "claude-code" || id === "cursor") out.add(id);
|
|
1344
1449
|
else log.warn(`Unknown agent id "${id}" \u2014 skipping.`);
|
|
@@ -1464,7 +1569,7 @@ function yn(v) {
|
|
|
1464
1569
|
var program = new Command();
|
|
1465
1570
|
program.name("agent-insights").description(
|
|
1466
1571
|
"Internal CLI for AI coding agent observability (Claude Code, Cursor)."
|
|
1467
|
-
).version("0.0.
|
|
1572
|
+
).version("0.0.12");
|
|
1468
1573
|
program.command("login").description("Authenticate with Vercel (Sign in with Vercel).").action(async () => {
|
|
1469
1574
|
await runLogin();
|
|
1470
1575
|
});
|
|
@@ -1474,9 +1579,12 @@ program.command("logout").description("Clear stored credentials.").action(async
|
|
|
1474
1579
|
program.command("init").description(
|
|
1475
1580
|
"Install agent hooks globally. Interactive by default; use --yes for non-interactive."
|
|
1476
1581
|
).option(
|
|
1477
|
-
"--agents <list>",
|
|
1478
|
-
"Comma-separated agent ids (claude-code,cursor)"
|
|
1479
|
-
).option("--transcripts", "Opt into transcript sync to Vercel Blob").option("--no-transcripts", "Skip transcript sync").option("--analysis", "Opt into SessionEnd analysis (Phase 2)").option("--telemetry", "Opt into OTLP event telemetry (Phase 3)").option("--no-hooks", "Skip installing per-agent hooks").option("--force", "Overwrite existing config").option("-y, --yes", "Non-interactive \u2014 accept defaults / passed flags").
|
|
1582
|
+
"-a, --agents <list>",
|
|
1583
|
+
"Comma-separated agent ids (claude-code,cursor); use '*' for all"
|
|
1584
|
+
).option("--transcripts", "Opt into transcript sync to Vercel Blob").option("--no-transcripts", "Skip transcript sync").option("--analysis", "Opt into SessionEnd analysis (Phase 2)").option("--telemetry", "Opt into OTLP event telemetry (Phase 3)").option("--no-hooks", "Skip installing per-agent hooks").option("--force", "Overwrite existing config").option("-y, --yes", "Non-interactive \u2014 accept defaults / passed flags").option(
|
|
1585
|
+
"--bypass-secret <secret>",
|
|
1586
|
+
"Vercel deployment-protection bypass secret (use '' to clear)"
|
|
1587
|
+
).action(async (opts) => {
|
|
1480
1588
|
await runInit(opts);
|
|
1481
1589
|
});
|
|
1482
1590
|
program.command("status").description("Show current config, consent, and adapter state.").option("--json", "Emit machine-readable JSON").action(async (opts) => {
|