@ait-co/console-cli 0.1.38 → 0.1.40

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.mjs CHANGED
@@ -9,7 +9,6 @@ import { checkbox, confirm, editor, input, password, select } from "@inquirer/pr
9
9
  import { imageSize } from "image-size";
10
10
  import { execFile, execFileSync, spawn } from "node:child_process";
11
11
  import { constants, createReadStream, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
12
- import { createInterface } from "node:readline/promises";
13
12
  import { promisify } from "node:util";
14
13
  import { createHash } from "node:crypto";
15
14
  //#region src/api/http.ts
@@ -3611,7 +3610,7 @@ function serviceStatusFor(entry) {
3611
3610
  }
3612
3611
  const POLL_MIN_INTERVAL_SEC = 30;
3613
3612
  const POLL_MAX_INTERVAL_SEC = 3600;
3614
- const statusCommand$2 = defineCommand({
3613
+ const statusCommand$1 = defineCommand({
3615
3614
  meta: {
3616
3615
  name: "status",
3617
3616
  description: "Show the derived review state of a mini-app (under-review / rejected / approved)."
@@ -5721,7 +5720,7 @@ const appCommand = defineCommand({
5721
5720
  }),
5722
5721
  ls: lsCommand$4,
5723
5722
  show: showCommand$2,
5724
- status: statusCommand$2,
5723
+ status: statusCommand$1,
5725
5724
  ratings: ratingsCommand,
5726
5725
  reports: reportsCommand,
5727
5726
  bundles: bundlesCommand,
@@ -6833,8 +6832,11 @@ function readCredentials(path) {
6833
6832
  }
6834
6833
  function writeCredentials(path, map) {
6835
6834
  const dir = join(path, "..");
6836
- if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
6837
- writeFileSync(path, JSON.stringify(map, null, 2) + "\n", {
6835
+ if (!existsSync(dir)) mkdirSync(dir, {
6836
+ recursive: true,
6837
+ mode: 448
6838
+ });
6839
+ writeFileSync(path, `${JSON.stringify(map, null, 2)}\n`, {
6838
6840
  encoding: "utf8",
6839
6841
  mode: 384
6840
6842
  });
@@ -6952,6 +6954,20 @@ function validateKeyName(raw) {
6952
6954
  if (!NAME_REGEX.test(raw)) return "bad-chars";
6953
6955
  return null;
6954
6956
  }
6957
+ /**
6958
+ * Resolve the ait profile name to save the Deploy Key under.
6959
+ *
6960
+ * - `noSaveProfile: true` → undefined (skip saving)
6961
+ * - `saveProfileOverride` present → use that name
6962
+ * - default → use `name` (the --name value)
6963
+ *
6964
+ * Exported for unit testing.
6965
+ */
6966
+ function resolveProfileName(name, opts) {
6967
+ if (opts.noSaveProfile) return void 0;
6968
+ if (opts.saveProfileOverride) return opts.saveProfileOverride;
6969
+ return name;
6970
+ }
6955
6971
  function parseAppsFlag(raw) {
6956
6972
  const slugs = raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
6957
6973
  if (slugs.length === 0) return {
@@ -7045,7 +7061,12 @@ const createCommand = defineCommand({
7045
7061
  },
7046
7062
  "save-profile": {
7047
7063
  type: "string",
7048
- description: "After issuing, save the key as an `ait` token profile (written to `~/.ait/credentials`). The named profile can then be used with `ait deploy --profile <name>` immediately. If omitted, the key is printed to stdout once and not persisted locally."
7064
+ description: "Profile name for the ait token (defaults to --name). The key is written to `~/.ait/credentials` so `ait deploy --profile <name>` works immediately. Use --no-save-profile to skip."
7065
+ },
7066
+ "no-save-profile": {
7067
+ type: "boolean",
7068
+ default: false,
7069
+ description: "Do not save the issued key to an ait token profile — print to stdout only (for CI pipes that store it elsewhere)."
7049
7070
  },
7050
7071
  json: {
7051
7072
  type: "boolean",
@@ -7096,7 +7117,10 @@ const createCommand = defineCommand({
7096
7117
  name,
7097
7118
  target
7098
7119
  }, session.cookies);
7099
- const saveProfileName = args["save-profile"] ? String(args["save-profile"]) : void 0;
7120
+ const saveProfileName = resolveProfileName(name, {
7121
+ noSaveProfile: args["no-save-profile"],
7122
+ ...args["save-profile"] ? { saveProfileOverride: String(args["save-profile"]) } : {}
7123
+ });
7100
7124
  let savedProfile;
7101
7125
  let saveProfileWarning;
7102
7126
  if (saveProfileName !== void 0) {
@@ -9160,557 +9184,6 @@ const noticesCommand = defineCommand({
9160
9184
  }
9161
9185
  });
9162
9186
  //#endregion
9163
- //#region src/version.ts
9164
- function resolveVersion() {
9165
- try {
9166
- const injected = globalThis.AITCC_VERSION;
9167
- if (typeof injected === "string" && injected.length > 0) return injected;
9168
- } catch {}
9169
- try {
9170
- return "0.1.38";
9171
- } catch {}
9172
- return "0.0.0-dev";
9173
- }
9174
- const VERSION = resolveVersion();
9175
- //#endregion
9176
- //#region src/telemetry/state.ts
9177
- /**
9178
- * Telemetry consent state + anon_id I/O for console-cli.
9179
- *
9180
- * Storage: ~/.config/aitcc/telemetry.json (0600, XDG-aware via configDir())
9181
- * Consistent with devtools' localStorage schema names where applicable.
9182
- */
9183
- /** Current policy version. Bump whenever the privacy policy changes. */
9184
- const CURRENT_POLICY_VERSION = "2026-05-18";
9185
- function telemetryFilePath() {
9186
- return join(configDir(), "telemetry.json");
9187
- }
9188
- async function readStateFile() {
9189
- let raw;
9190
- try {
9191
- raw = await readFile(telemetryFilePath(), "utf8");
9192
- } catch {
9193
- return null;
9194
- }
9195
- let parsed;
9196
- try {
9197
- parsed = JSON.parse(raw);
9198
- } catch {
9199
- return null;
9200
- }
9201
- if (!parsed || typeof parsed !== "object") return null;
9202
- const obj = parsed;
9203
- if (obj.schemaVersion !== 1) return null;
9204
- if (obj.consent !== "granted" && obj.consent !== "denied" && obj.consent !== "undecided") return null;
9205
- if (typeof obj.policyVersion !== "string") return null;
9206
- return {
9207
- schemaVersion: 1,
9208
- consent: obj.consent,
9209
- policyVersion: obj.policyVersion,
9210
- ...typeof obj.anonId === "string" ? { anonId: obj.anonId } : {},
9211
- ...typeof obj.tier0LastSent === "string" ? { tier0LastSent: obj.tier0LastSent } : {},
9212
- ...obj.tier0OptOut === true ? { tier0OptOut: true } : {}
9213
- };
9214
- }
9215
- async function writeStateFile(state) {
9216
- const path = telemetryFilePath();
9217
- await mkdir(dirname(path), {
9218
- recursive: true,
9219
- mode: 448
9220
- });
9221
- const tmp = `${path}.${process.pid}.${Date.now()}.tmp`;
9222
- try {
9223
- await writeFile(tmp, JSON.stringify(state, null, 2), { mode: 384 });
9224
- await rename(tmp, path);
9225
- } catch (err) {
9226
- await unlink(tmp).catch(() => {});
9227
- throw err;
9228
- }
9229
- }
9230
- /** Read the raw consent from disk. Returns 'undecided' if no file. */
9231
- async function readConsentState() {
9232
- const s = await readStateFile();
9233
- if (!s) return "undecided";
9234
- return s.consent;
9235
- }
9236
- /**
9237
- * Resolve effective consent with policy-version bump rule:
9238
- * - Previously 'granted' but on an old policy version → revert to 'undecided'
9239
- * - Previously 'denied' on any version → stay 'denied'
9240
- */
9241
- async function resolveEffectiveConsent() {
9242
- const s = await readStateFile();
9243
- if (!s) return "undecided";
9244
- if (s.consent === "granted") {
9245
- if (s.policyVersion !== "2026-05-18") return "undecided";
9246
- return "granted";
9247
- }
9248
- return s.consent;
9249
- }
9250
- /**
9251
- * Returns the stored anon_id, or generates + persists a new UUID v4.
9252
- * Once generated it is never overwritten except after a successful deleteMyData call.
9253
- */
9254
- async function getOrCreateAnonId() {
9255
- const s = await readStateFile();
9256
- if (s?.anonId) return s.anonId;
9257
- const id = crypto.randomUUID();
9258
- await writeStateFile({
9259
- ...s ?? {
9260
- schemaVersion: 1,
9261
- consent: "undecided",
9262
- policyVersion: "2026-05-18"
9263
- },
9264
- anonId: id
9265
- });
9266
- return id;
9267
- }
9268
- async function acceptConsent() {
9269
- await writeStateFile({
9270
- schemaVersion: 1,
9271
- consent: "granted",
9272
- policyVersion: CURRENT_POLICY_VERSION,
9273
- anonId: (await readStateFile())?.anonId ?? crypto.randomUUID()
9274
- });
9275
- }
9276
- async function denyConsent() {
9277
- const s = await readStateFile();
9278
- await writeStateFile({
9279
- schemaVersion: 1,
9280
- consent: "denied",
9281
- policyVersion: CURRENT_POLICY_VERSION,
9282
- ...s?.anonId ? { anonId: s.anonId } : {}
9283
- });
9284
- }
9285
- /** Returns true if Tier 0 pings are permanently opted out. */
9286
- async function isTier0OptedOut() {
9287
- return (await readStateFile())?.tier0OptOut === true;
9288
- }
9289
- /** Permanently opt out of Tier 0 pings (sets tier0OptOut: true). */
9290
- async function setTier0OptOut(optOut) {
9291
- const current = await readStateFile() ?? {
9292
- schemaVersion: 1,
9293
- consent: "undecided",
9294
- policyVersion: "2026-05-18"
9295
- };
9296
- if (optOut) await writeStateFile({
9297
- ...current,
9298
- tier0OptOut: true
9299
- });
9300
- else {
9301
- const { tier0OptOut: _removed, ...rest } = current;
9302
- await writeStateFile(rest);
9303
- }
9304
- }
9305
- /**
9306
- * Returns the ISO date (YYYY-MM-DD) of the last sent Tier 0 ping, or null.
9307
- */
9308
- async function getTier0LastSent() {
9309
- return (await readStateFile())?.tier0LastSent ?? null;
9310
- }
9311
- /**
9312
- * Record that a Tier 0 ping was sent today (ISO date marker).
9313
- */
9314
- async function markTier0Sent(date) {
9315
- await writeStateFile({
9316
- ...await readStateFile() ?? {
9317
- schemaVersion: 1,
9318
- consent: "undecided",
9319
- policyVersion: "2026-05-18"
9320
- },
9321
- tier0LastSent: date
9322
- });
9323
- }
9324
- /**
9325
- * Delete data: send DELETE /e?anon_id=... to the server (if we have an id),
9326
- * then rotate local anon_id so subsequent events are unlinkable.
9327
- */
9328
- async function deleteMyData(endpoint) {
9329
- const s = await readStateFile();
9330
- if (!s?.anonId) return false;
9331
- try {
9332
- if (!(await fetch(`${endpoint}/e?anon_id=${encodeURIComponent(s.anonId)}`, { method: "DELETE" })).ok) return false;
9333
- await writeStateFile({
9334
- ...s,
9335
- anonId: crypto.randomUUID()
9336
- });
9337
- return true;
9338
- } catch {
9339
- return false;
9340
- }
9341
- }
9342
- //#endregion
9343
- //#region src/telemetry/send.ts
9344
- /**
9345
- * Telemetry send — fire-and-forget with one retry.
9346
- *
9347
- * Tier 0 rules:
9348
- * 1. No consent check — fires regardless of opt-in state (unless opted out via tier0OptOut).
9349
- * 2. No anon_id — server generates a daily hash.
9350
- * 3. 5 s timeout, no retry. Drops silently on any failure.
9351
- *
9352
- * Tier 1 rules:
9353
- * 1. If consent ≠ "granted" — drop silently.
9354
- * 2. POST event as JSON with 5 s timeout.
9355
- * 3. On network error or non-2xx: retry ONCE after 2 s. On second failure: drop.
9356
- * 4. Meta is capped at 256 bytes (JSON-serialized); oversized meta is dropped.
9357
- * 5. All calls are non-blocking — caller never awaits send().
9358
- */
9359
- /** Meta size cap per server contract (JSON bytes). */
9360
- const META_BYTE_CAP = 256;
9361
- function sanitizeMeta(meta) {
9362
- if (meta === void 0) return void 0;
9363
- const serialized = JSON.stringify(meta);
9364
- if (new TextEncoder().encode(serialized).byteLength > META_BYTE_CAP) return void 0;
9365
- return meta;
9366
- }
9367
- async function doFetch(endpoint, payload) {
9368
- const controller = new AbortController();
9369
- const timeoutId = setTimeout(() => controller.abort(), 5e3);
9370
- try {
9371
- return (await fetch(`${endpoint}/e`, {
9372
- method: "POST",
9373
- headers: { "Content-Type": "application/json" },
9374
- body: JSON.stringify(payload),
9375
- signal: controller.signal
9376
- })).ok;
9377
- } catch {
9378
- return false;
9379
- } finally {
9380
- clearTimeout(timeoutId);
9381
- }
9382
- }
9383
- function delay(ms) {
9384
- return new Promise((resolve) => setTimeout(resolve, ms));
9385
- }
9386
- /** Retry delay in ms — injectable for tests. */
9387
- let RETRY_DELAY_MS = 2e3;
9388
- /**
9389
- * Send a Tier 1 telemetry event. Drops silently if consent is not 'granted'.
9390
- * Returns a Promise but callers should NOT await it — fire-and-forget only.
9391
- */
9392
- async function send(endpoint, event, version, meta) {
9393
- if (await readConsentState() !== "granted") return;
9394
- const sanitized = sanitizeMeta(meta);
9395
- const payload = {
9396
- tier: 1,
9397
- source: "console-cli",
9398
- event,
9399
- anon_id: await getOrCreateAnonId(),
9400
- version,
9401
- ts: Date.now(),
9402
- ...sanitized !== void 0 ? { meta: sanitized } : {}
9403
- };
9404
- if (await doFetch(endpoint, payload)) return;
9405
- await delay(RETRY_DELAY_MS);
9406
- await doFetch(endpoint, payload);
9407
- }
9408
- /**
9409
- * Send a Tier 0 anonymous daily ping.
9410
- * - No anon_id (server generates a daily hash from IP+UA).
9411
- * - No retry. 5 s timeout. Fire-and-forget.
9412
- * - Callers should NOT await this.
9413
- */
9414
- async function sendTier0Ping(endpoint, version) {
9415
- const payload = {
9416
- tier: 0,
9417
- source: "console-cli",
9418
- version,
9419
- platform: process.platform
9420
- };
9421
- const controller = new AbortController();
9422
- const timeoutId = setTimeout(() => controller.abort(), 5e3);
9423
- try {
9424
- await fetch(`${endpoint}/e`, {
9425
- method: "POST",
9426
- headers: { "Content-Type": "application/json" },
9427
- body: JSON.stringify(payload),
9428
- signal: controller.signal
9429
- });
9430
- } catch {} finally {
9431
- clearTimeout(timeoutId);
9432
- }
9433
- }
9434
- //#endregion
9435
- //#region src/telemetry/index.ts
9436
- /**
9437
- * Telemetry client — internal to @ait-co/console-cli.
9438
- *
9439
- * Usage: import { trackInvocation, trackTier0Ping } from './telemetry/index.js'
9440
- *
9441
- * Tier 0 (opt-out): anonymous daily ping. Fires on every invocation; client-side
9442
- * daily dedupe via tier0LastSent. Respects AITCC_TELEMETRY=off, --no-telemetry,
9443
- * and permanent tier0OptOut flag.
9444
- *
9445
- * Tier 1 (opt-in): detailed events. First invocation on a TTY prompts the user;
9446
- * non-TTY (CI) defaults to deny.
9447
- *
9448
- * Endpoint override for staging: AITCC_TELEMETRY_ENV=staging
9449
- * (or automatically when VERSION contains '-dev').
9450
- */
9451
- function resolveEndpoint() {
9452
- if (process.env.AITCC_TELEMETRY_ENV === "staging") return "https://t-staging.aitc.dev";
9453
- if (VERSION.includes("-dev")) return "https://t-staging.aitc.dev";
9454
- return "https://t.aitc.dev";
9455
- }
9456
- const TELEMETRY_ENDPOINT = resolveEndpoint();
9457
- /** Returns true if this is the very first run (telemetry.json does not exist). */
9458
- function isFirstRun() {
9459
- return !existsSync(telemetryFilePath());
9460
- }
9461
- /**
9462
- * Prompt for consent on TTY. Defaults to deny on any non-TTY or error.
9463
- * Called once per install (no file yet) when stdin/stdout are both TTYs.
9464
- */
9465
- async function promptConsent() {
9466
- if (!process.stdin.isTTY || !process.stdout.isTTY) {
9467
- await denyConsent();
9468
- return;
9469
- }
9470
- const rl = createInterface({
9471
- input: process.stdin,
9472
- output: process.stdout
9473
- });
9474
- try {
9475
- process.stderr.write([
9476
- "",
9477
- "aitcc 사용 개선을 위해 익명 사용 통계를 수집해도 될까요?",
9478
- " · 개인 식별 정보 없음 · 랜덤 익명 ID만 사용 · 언제든 off 가능",
9479
- " 자세한 내용: https://docs.aitc.dev/privacy",
9480
- ""
9481
- ].join("\n"));
9482
- if ((await rl.question("보내도 될까요? [y/N] ")).trim().toLowerCase() === "y") await acceptConsent();
9483
- else await denyConsent();
9484
- } catch {
9485
- await denyConsent();
9486
- } finally {
9487
- rl.close();
9488
- }
9489
- }
9490
- /**
9491
- * Check whether telemetry is globally disabled via environment or CLI flag.
9492
- * Accepts the parsed --no-telemetry flag value from argv.
9493
- */
9494
- function isTelemetryGloballyDisabled(noTelemetryFlag) {
9495
- if (noTelemetryFlag) return true;
9496
- const env = process.env.AITCC_TELEMETRY;
9497
- if (env !== void 0 && env.toLowerCase() === "off") return true;
9498
- return false;
9499
- }
9500
- /**
9501
- * Send a Tier 0 anonymous daily ping (fire-and-forget).
9502
- *
9503
- * Skips if:
9504
- * - AITCC_TELEMETRY=off or --no-telemetry flag
9505
- * - tier0OptOut === true in the state file
9506
- * - already sent today (tier0LastSent === today's ISO date)
9507
- *
9508
- * On success, records today's date in tier0LastSent for client-side daily dedupe.
9509
- * The server also deduplicates server-side via KV, so this is an extra client guard.
9510
- */
9511
- async function trackTier0Ping(noTelemetryFlag = false) {
9512
- try {
9513
- if (isTelemetryGloballyDisabled(noTelemetryFlag)) return;
9514
- if (await isTier0OptedOut()) return;
9515
- const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
9516
- if (await getTier0LastSent() === today) return;
9517
- sendTier0Ping(TELEMETRY_ENDPOINT, VERSION);
9518
- await markTier0Sent(today);
9519
- } catch {}
9520
- }
9521
- /** True only on the first invocation after a fresh install. */
9522
- async function isNewInstall() {
9523
- const markerPath = `${telemetryFilePath()}.install`;
9524
- if (existsSync(markerPath)) return false;
9525
- try {
9526
- await writeFile(markerPath, "1", { mode: 384 });
9527
- return true;
9528
- } catch {
9529
- return false;
9530
- }
9531
- }
9532
- /**
9533
- * Called at CLI entry point with the resolved top-level command name.
9534
- * Handles first-run Tier 1 consent prompt, install detection, and Tier 1 event send.
9535
- * Fire-and-forget: do NOT await this.
9536
- *
9537
- * Note: Tier 0 ping is sent separately via trackTier0Ping() before this call.
9538
- */
9539
- async function trackInvocation(command, noTelemetryFlag = false) {
9540
- try {
9541
- if (isTelemetryGloballyDisabled(noTelemetryFlag)) return;
9542
- if (isFirstRun()) await promptConsent();
9543
- if (await resolveEffectiveConsent() !== "granted") return;
9544
- if (await isNewInstall()) send(TELEMETRY_ENDPOINT, "cli_install", VERSION, {
9545
- platform: process.platform,
9546
- arch: process.arch
9547
- });
9548
- send(TELEMETRY_ENDPOINT, "cli_invoked", VERSION, { command });
9549
- } catch {}
9550
- }
9551
- const telemetryCommand = defineCommand({
9552
- meta: {
9553
- name: "telemetry",
9554
- description: "Manage anonymous usage telemetry."
9555
- },
9556
- subCommands: {
9557
- status: defineCommand({
9558
- meta: {
9559
- name: "status",
9560
- description: "Show current telemetry status for both Tier 0 and Tier 1."
9561
- },
9562
- args: { json: {
9563
- type: "boolean",
9564
- description: "Emit machine-readable JSON.",
9565
- default: false
9566
- } },
9567
- async run({ args }) {
9568
- const [tier1Consent, tier0OptOut, tier0LastSent, anonId] = await Promise.all([
9569
- resolveEffectiveConsent(),
9570
- isTier0OptedOut(),
9571
- getTier0LastSent(),
9572
- resolveEffectiveConsent().then((c) => c === "granted" ? getOrCreateAnonId() : null)
9573
- ]);
9574
- const filePath = telemetryFilePath();
9575
- const tier0Status = tier0OptOut ? "off (opted out)" : "on";
9576
- const tier0Display = tier0LastSent ? `${tier0Status} (last sent: ${tier0LastSent})` : tier0Status;
9577
- if (args.json) {
9578
- process.stdout.write(`${JSON.stringify({
9579
- ok: true,
9580
- tier0: {
9581
- status: tier0OptOut ? "opted-out" : "on",
9582
- lastSent: tier0LastSent ?? null
9583
- },
9584
- tier1: {
9585
- consent: tier1Consent,
9586
- policyVersion: CURRENT_POLICY_VERSION,
9587
- ...anonId ? { anonId } : {}
9588
- },
9589
- endpoint: TELEMETRY_ENDPOINT,
9590
- filePath
9591
- })}\n`);
9592
- return exitAfterFlush(ExitCode.Ok);
9593
- }
9594
- process.stdout.write("Telemetry status\n");
9595
- process.stdout.write(` Tier 0 (anonymous daily ping): ${tier0Display}\n`);
9596
- process.stdout.write(` Tier 1 (opt-in events): ${tier1Consent} (policyVersion: ${CURRENT_POLICY_VERSION})\n`);
9597
- process.stdout.write(`\nEndpoint: ${TELEMETRY_ENDPOINT}\n`);
9598
- if (anonId) process.stdout.write(`Anon ID: ${anonId}\n`);
9599
- process.stdout.write(`State file: ${filePath}\n`);
9600
- return exitAfterFlush(ExitCode.Ok);
9601
- }
9602
- }),
9603
- enable: defineCommand({
9604
- meta: {
9605
- name: "enable",
9606
- description: "Enable anonymous usage telemetry (opt-in)."
9607
- },
9608
- args: { json: {
9609
- type: "boolean",
9610
- description: "Emit machine-readable JSON.",
9611
- default: false
9612
- } },
9613
- async run({ args }) {
9614
- await acceptConsent();
9615
- const anonId = await getOrCreateAnonId();
9616
- if (args.json) process.stdout.write(`${JSON.stringify({
9617
- ok: true,
9618
- consent: "granted",
9619
- anonId
9620
- })}\n`);
9621
- else {
9622
- process.stdout.write("Telemetry enabled. Thank you!\n");
9623
- process.stdout.write(`Anon ID: ${anonId}\n`);
9624
- }
9625
- return exitAfterFlush(ExitCode.Ok);
9626
- }
9627
- }),
9628
- disable: defineCommand({
9629
- meta: {
9630
- name: "disable",
9631
- description: "Disable anonymous usage telemetry."
9632
- },
9633
- args: { json: {
9634
- type: "boolean",
9635
- description: "Emit machine-readable JSON.",
9636
- default: false
9637
- } },
9638
- async run({ args }) {
9639
- await denyConsent();
9640
- if (args.json) process.stdout.write(`${JSON.stringify({
9641
- ok: true,
9642
- consent: "denied"
9643
- })}\n`);
9644
- else process.stdout.write("Telemetry disabled.\n");
9645
- return exitAfterFlush(ExitCode.Ok);
9646
- }
9647
- }),
9648
- delete: defineCommand({
9649
- meta: {
9650
- name: "delete",
9651
- description: "Delete your telemetry data from the server and rotate the local anon_id."
9652
- },
9653
- args: { json: {
9654
- type: "boolean",
9655
- description: "Emit machine-readable JSON.",
9656
- default: false
9657
- } },
9658
- async run({ args }) {
9659
- const beforeConsent = await readConsentState();
9660
- const ok = await deleteMyData(TELEMETRY_ENDPOINT);
9661
- if (args.json) process.stdout.write(`${JSON.stringify({
9662
- ok,
9663
- ...ok ? {} : { reason: beforeConsent === "undecided" ? "no-data" : "server-error" }
9664
- })}\n`);
9665
- else if (ok) process.stdout.write("Deletion request sent. Your data has been removed and a new anon ID assigned.\n");
9666
- else if (beforeConsent === "undecided") process.stdout.write("No telemetry data to delete (telemetry was never enabled).\n");
9667
- else process.stderr.write("Deletion request failed. Please try again or contact the maintainers.\n");
9668
- return exitAfterFlush(ok || beforeConsent === "undecided" ? ExitCode.Ok : ExitCode.NetworkError);
9669
- }
9670
- }),
9671
- "tier0-off": defineCommand({
9672
- meta: {
9673
- name: "tier0-off",
9674
- description: "Permanently opt out of the Tier 0 anonymous daily ping."
9675
- },
9676
- args: { json: {
9677
- type: "boolean",
9678
- description: "Emit machine-readable JSON.",
9679
- default: false
9680
- } },
9681
- async run({ args }) {
9682
- await setTier0OptOut(true);
9683
- if (args.json) process.stdout.write(`${JSON.stringify({
9684
- ok: true,
9685
- tier0: { status: "opted-out" }
9686
- })}\n`);
9687
- else process.stdout.write("Tier 0 anonymous ping disabled. No daily pings will be sent.\n");
9688
- return exitAfterFlush(ExitCode.Ok);
9689
- }
9690
- }),
9691
- "tier0-on": defineCommand({
9692
- meta: {
9693
- name: "tier0-on",
9694
- description: "Re-enable the Tier 0 anonymous daily ping after a previous tier0-off."
9695
- },
9696
- args: { json: {
9697
- type: "boolean",
9698
- description: "Emit machine-readable JSON.",
9699
- default: false
9700
- } },
9701
- async run({ args }) {
9702
- await setTier0OptOut(false);
9703
- if (args.json) process.stdout.write(`${JSON.stringify({
9704
- ok: true,
9705
- tier0: { status: "on" }
9706
- })}\n`);
9707
- else process.stdout.write("Tier 0 anonymous ping re-enabled.\n");
9708
- return exitAfterFlush(ExitCode.Ok);
9709
- }
9710
- })
9711
- }
9712
- });
9713
- //#endregion
9714
9187
  //#region src/github.ts
9715
9188
  const REPO_OWNER = "apps-in-toss-community";
9716
9189
  const REPO_NAME = "console-cli";
@@ -9844,6 +9317,19 @@ function sha256OfFile(path) {
9844
9317
  });
9845
9318
  }
9846
9319
  //#endregion
9320
+ //#region src/version.ts
9321
+ function resolveVersion() {
9322
+ try {
9323
+ const injected = globalThis.AITCC_VERSION;
9324
+ if (typeof injected === "string" && injected.length > 0) return injected;
9325
+ } catch {}
9326
+ try {
9327
+ return "0.1.40";
9328
+ } catch {}
9329
+ return "0.0.0-dev";
9330
+ }
9331
+ const VERSION = resolveVersion();
9332
+ //#endregion
9847
9333
  //#region src/commands/upgrade.ts
9848
9334
  const execFileP = promisify(execFile);
9849
9335
  function isStandaloneBinary() {
@@ -10991,15 +10477,10 @@ const main = defineCommand({
10991
10477
  keys: keysCommand,
10992
10478
  notices: noticesCommand,
10993
10479
  me: meCommand,
10994
- telemetry: telemetryCommand,
10995
10480
  completion: completionCommand
10996
10481
  }
10997
10482
  });
10998
10483
  cleanupStaleUpgradeArtifacts().catch(() => {});
10999
- const _telemetryCmd = process.argv.slice(2).find((a) => !a.startsWith("-")) ?? "(none)";
11000
- const _noTelemetry = process.argv.includes("--no-telemetry");
11001
- trackTier0Ping(_noTelemetry);
11002
- trackInvocation(_telemetryCmd, _noTelemetry);
11003
10484
  runMain(main);
11004
10485
  //#endregion
11005
10486
  export {};