@ait-co/console-cli 0.1.29 → 0.1.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md CHANGED
@@ -160,21 +160,34 @@ Every command accepts `--json`. When set:
160
160
 
161
161
  ## Telemetry
162
162
 
163
- `aitcc` can collect optional anonymous usage statistics. **Opt-in only by default** on first run the CLI prompts for consent in a TTY, and silently defaults to deny in CI/pipe environments.
163
+ `aitcc` collects anonymous usage statistics split into two tiers. See the [privacy page](https://docs.aitc.dev/privacy) for details.
164
164
 
165
- Collected: command name, version, platform, random anonymous ID. No personally identifiable information (email, session, user ID, etc.) is ever sent. See the [privacy page](https://docs.aitc.dev/privacy) for details.
165
+ ### Tier 0 anonymous daily ping (on by default, opt-out)
166
+
167
+ Once per day per machine, a minimal anonymous ping is sent on every invocation. Collected: `{source, version, platform}`. No PII, no `anon_id` — the server derives a daily hash from IP + User-Agent using a rotating salt, and stores nothing else. This is the minimum signal needed to know "is anyone actually using this version?"
168
+
169
+ Three ways to opt out:
170
+
171
+ - `AITC_TELEMETRY=off` environment variable — disables all telemetry for this shell session
172
+ - `--no-telemetry` flag — disables for this single invocation only (not permanent)
173
+ - `aitcc telemetry tier0-off` — permanently opts out (persisted to the state file)
174
+
175
+ ### Tier 1 — detailed events (off by default, opt-in)
176
+
177
+ On first run in a TTY, the CLI prompts for consent. In CI or pipe environments it silently defaults to deny. Collected: command name, version, platform, random persistent anonymous ID (`anon_id`). No personally identifiable information (email, session, user ID, etc.) is ever sent.
166
178
 
167
179
  ```sh
168
- aitcc telemetry status # show current consent state + anon ID
169
- aitcc telemetry enable # enable usage statistics
170
- aitcc telemetry disable # disable
171
- aitcc telemetry delete # request deletion of server-side data + rotate local anon ID
180
+ aitcc telemetry status # show both tier status + anon ID
181
+ aitcc telemetry status --json # machine-readable output
182
+ aitcc telemetry enable # enable Tier 1 events
183
+ aitcc telemetry disable # disable Tier 1 events
184
+ aitcc telemetry delete # request deletion of Tier 1 server data + rotate local anon ID
185
+ aitcc telemetry tier0-off # permanently opt out of Tier 0 daily ping
186
+ aitcc telemetry tier0-on # re-enable Tier 0 after a previous tier0-off
172
187
  ```
173
188
 
174
189
  State file: `$XDG_CONFIG_HOME/aitcc/telemetry.json` (fallback `~/.config/aitcc/telemetry.json`, mode `0600`).
175
190
 
176
- > **Note**: events will be rejected server-side until the metrics-ingest `source` allowlist is updated to include `console-cli`. The client-side code is ready.
177
-
178
191
  ## Status
179
192
 
180
193
  `login`, `logout`, `whoami`, and `upgrade` are implemented end-to-end — `login` drives a real browser over CDP and `whoami` reads the live console member API. `deploy`, `logs`, `status` are next. See the [organization landing page](https://aitc.dev/) for the full roadmap.
package/README.md CHANGED
@@ -160,21 +160,34 @@ aitcc app deploy --bundle ./dist/app.zip --json
160
160
 
161
161
  ## 텔레메트리
162
162
 
163
- `aitcc`는 선택적 익명 사용 통계를 수집할 있습니다. **기본값은 비활성(opt-in)** — 처음 실행 시 TTY 환경에서만 동의를 묻고, CI/파이프 환경에선 자동으로 비활성화됩니다.
163
+ `aitcc`는 단계로 분리된 익명 사용 통계를 수집합니다. 자세한 내용은 [privacy 페이지](https://docs.aitc.dev/privacy) 참조.
164
164
 
165
- 수집하는 정보: 실행된 명령 이름, 버전, 플랫폼, 임의 익명 ID. 개인 식별 정보(이메일, 세션, 사용자 ID 등)는 절대 전송하지 않습니다. 자세한 내용은 [privacy 페이지](https://docs.aitc.dev/privacy) 참조.
165
+ ### Tier 0 일별 익명 (기본 ON, opt-out)
166
+
167
+ 매 실행 시 하루 한 번 익명 핑을 보냅니다. 수집 항목: `{source, version, platform}`. 개인 식별 정보 없음. `anon_id`도 없음 — 서버가 일별 salt로 IP+UA 해시를 계산해 저장하며, 그 외 정보는 저장하지 않습니다. "이 버전을 실제로 쓰는 사람이 있는가"를 파악하기 위한 최소 신호입니다.
168
+
169
+ opt-out 방법 (세 가지):
170
+
171
+ - `AITC_TELEMETRY=off` 환경 변수 — 이 쉘 세션 전체 비활성
172
+ - `--no-telemetry` 플래그 — 이 invocation만 비활성 (영구 X)
173
+ - `aitcc telemetry tier0-off` — 영구 opt-out (state file에 저장)
174
+
175
+ ### Tier 1 — 세부 이벤트 (기본 OFF, opt-in)
176
+
177
+ 처음 실행 시 TTY 환경에서만 동의를 묻습니다. CI/파이프 환경에선 자동으로 비활성화됩니다. 수집 항목: 실행된 명령 이름, 버전, 플랫폼, 임의 익명 ID (`anon_id`). 개인 식별 정보(이메일, 세션, 사용자 ID 등)는 절대 전송하지 않습니다.
166
178
 
167
179
  ```sh
168
- aitcc telemetry status # 현재 동의 상태 + 익명 ID 확인
169
- aitcc telemetry enable # 통계 수집 활성화
170
- aitcc telemetry disable # 비활성화
171
- aitcc telemetry delete # 서버에 저장된 데이터 삭제 요청 + 로컬 익명 ID 교체
180
+ aitcc telemetry status # tier 상태 + 익명 ID 확인
181
+ aitcc telemetry status --json # machine-readable 출력
182
+ aitcc telemetry enable # Tier 1 활성화
183
+ aitcc telemetry disable # Tier 1 비활성화
184
+ aitcc telemetry delete # 서버에 저장된 Tier 1 데이터 삭제 요청 + 로컬 익명 ID 교체
185
+ aitcc telemetry tier0-off # Tier 0 익명 핑 영구 비활성화
186
+ aitcc telemetry tier0-on # Tier 0 다시 활성화
172
187
  ```
173
188
 
174
189
  상태 파일: `$XDG_CONFIG_HOME/aitcc/telemetry.json` (fallback `~/.config/aitcc/telemetry.json`, mode `0600`).
175
190
 
176
- > **참고**: metrics-ingest 서버의 `source` allowlist가 `console-cli`를 포함하도록 업데이트되기 전까지는 이벤트가 서버에서 거부될 수 있습니다. 클라이언트 측 코드는 이미 준비돼 있습니다.
177
-
178
191
  ## 진행 상황
179
192
 
180
193
  `login`, `logout`, `whoami`, `upgrade`는 end-to-end 동작 — `login`은 CDP로 실제 브라우저를 띄우고 `whoami`는 live console member API를 호출합니다. `deploy`, `logs`, `status`가 다음 작업입니다. 전체 로드맵은 [organization landing page](https://aitc.dev/) 참조.
package/dist/cli.mjs CHANGED
@@ -9199,7 +9199,7 @@ function resolveVersion() {
9199
9199
  if (typeof injected === "string" && injected.length > 0) return injected;
9200
9200
  } catch {}
9201
9201
  try {
9202
- return "0.1.29";
9202
+ return "0.1.30";
9203
9203
  } catch {}
9204
9204
  return "0.0.0-dev";
9205
9205
  }
@@ -9213,7 +9213,7 @@ const VERSION = resolveVersion();
9213
9213
  * Consistent with devtools' localStorage schema names where applicable.
9214
9214
  */
9215
9215
  /** Current policy version. Bump whenever the privacy policy changes. */
9216
- const CURRENT_POLICY_VERSION = "2026-05-12";
9216
+ const CURRENT_POLICY_VERSION = "2026-05-18";
9217
9217
  function telemetryFilePath() {
9218
9218
  return join(configDir(), "telemetry.json");
9219
9219
  }
@@ -9239,7 +9239,9 @@ async function readStateFile() {
9239
9239
  schemaVersion: 1,
9240
9240
  consent: obj.consent,
9241
9241
  policyVersion: obj.policyVersion,
9242
- ...typeof obj.anonId === "string" ? { anonId: obj.anonId } : {}
9242
+ ...typeof obj.anonId === "string" ? { anonId: obj.anonId } : {},
9243
+ ...typeof obj.tier0LastSent === "string" ? { tier0LastSent: obj.tier0LastSent } : {},
9244
+ ...obj.tier0OptOut === true ? { tier0OptOut: true } : {}
9243
9245
  };
9244
9246
  }
9245
9247
  async function writeStateFile(state) {
@@ -9272,7 +9274,7 @@ async function resolveEffectiveConsent() {
9272
9274
  const s = await readStateFile();
9273
9275
  if (!s) return "undecided";
9274
9276
  if (s.consent === "granted") {
9275
- if (s.policyVersion !== "2026-05-12") return "undecided";
9277
+ if (s.policyVersion !== "2026-05-18") return "undecided";
9276
9278
  return "granted";
9277
9279
  }
9278
9280
  return s.consent;
@@ -9289,7 +9291,7 @@ async function getOrCreateAnonId() {
9289
9291
  ...s ?? {
9290
9292
  schemaVersion: 1,
9291
9293
  consent: "undecided",
9292
- policyVersion: "2026-05-12"
9294
+ policyVersion: "2026-05-18"
9293
9295
  },
9294
9296
  anonId: id
9295
9297
  });
@@ -9312,6 +9314,45 @@ async function denyConsent() {
9312
9314
  ...s?.anonId ? { anonId: s.anonId } : {}
9313
9315
  });
9314
9316
  }
9317
+ /** Returns true if Tier 0 pings are permanently opted out. */
9318
+ async function isTier0OptedOut() {
9319
+ return (await readStateFile())?.tier0OptOut === true;
9320
+ }
9321
+ /** Permanently opt out of Tier 0 pings (sets tier0OptOut: true). */
9322
+ async function setTier0OptOut(optOut) {
9323
+ const current = await readStateFile() ?? {
9324
+ schemaVersion: 1,
9325
+ consent: "undecided",
9326
+ policyVersion: "2026-05-18"
9327
+ };
9328
+ if (optOut) await writeStateFile({
9329
+ ...current,
9330
+ tier0OptOut: true
9331
+ });
9332
+ else {
9333
+ const { tier0OptOut: _removed, ...rest } = current;
9334
+ await writeStateFile(rest);
9335
+ }
9336
+ }
9337
+ /**
9338
+ * Returns the ISO date (YYYY-MM-DD) of the last sent Tier 0 ping, or null.
9339
+ */
9340
+ async function getTier0LastSent() {
9341
+ return (await readStateFile())?.tier0LastSent ?? null;
9342
+ }
9343
+ /**
9344
+ * Record that a Tier 0 ping was sent today (ISO date marker).
9345
+ */
9346
+ async function markTier0Sent(date) {
9347
+ await writeStateFile({
9348
+ ...await readStateFile() ?? {
9349
+ schemaVersion: 1,
9350
+ consent: "undecided",
9351
+ policyVersion: "2026-05-18"
9352
+ },
9353
+ tier0LastSent: date
9354
+ });
9355
+ }
9315
9356
  /**
9316
9357
  * Delete data: send DELETE /e?anon_id=... to the server (if we have an id),
9317
9358
  * then rotate local anon_id so subsequent events are unlinkable.
@@ -9335,7 +9376,12 @@ async function deleteMyData(endpoint) {
9335
9376
  /**
9336
9377
  * Telemetry send — fire-and-forget with one retry.
9337
9378
  *
9338
- * Rules:
9379
+ * Tier 0 rules:
9380
+ * 1. No consent check — fires regardless of opt-in state (unless opted out via tier0OptOut).
9381
+ * 2. No anon_id — server generates a daily hash.
9382
+ * 3. 5 s timeout, no retry. Drops silently on any failure.
9383
+ *
9384
+ * Tier 1 rules:
9339
9385
  * 1. If consent ≠ "granted" — drop silently.
9340
9386
  * 2. POST event as JSON with 5 s timeout.
9341
9387
  * 3. On network error or non-2xx: retry ONCE after 2 s. On second failure: drop.
@@ -9372,13 +9418,14 @@ function delay(ms) {
9372
9418
  /** Retry delay in ms — injectable for tests. */
9373
9419
  let RETRY_DELAY_MS = 2e3;
9374
9420
  /**
9375
- * Send a telemetry event. Drops silently if consent is not 'granted'.
9421
+ * Send a Tier 1 telemetry event. Drops silently if consent is not 'granted'.
9376
9422
  * Returns a Promise but callers should NOT await it — fire-and-forget only.
9377
9423
  */
9378
9424
  async function send(endpoint, event, version, meta) {
9379
9425
  if (await readConsentState() !== "granted") return;
9380
9426
  const sanitized = sanitizeMeta(meta);
9381
9427
  const payload = {
9428
+ tier: 1,
9382
9429
  source: "console-cli",
9383
9430
  event,
9384
9431
  anon_id: await getOrCreateAnonId(),
@@ -9390,15 +9437,45 @@ async function send(endpoint, event, version, meta) {
9390
9437
  await delay(RETRY_DELAY_MS);
9391
9438
  await doFetch(endpoint, payload);
9392
9439
  }
9440
+ /**
9441
+ * Send a Tier 0 anonymous daily ping.
9442
+ * - No anon_id (server generates a daily hash from IP+UA).
9443
+ * - No retry. 5 s timeout. Fire-and-forget.
9444
+ * - Callers should NOT await this.
9445
+ */
9446
+ async function sendTier0Ping(endpoint, version) {
9447
+ const payload = {
9448
+ tier: 0,
9449
+ source: "console-cli",
9450
+ version,
9451
+ platform: process.platform
9452
+ };
9453
+ const controller = new AbortController();
9454
+ const timeoutId = setTimeout(() => controller.abort(), 5e3);
9455
+ try {
9456
+ await fetch(`${endpoint}/e`, {
9457
+ method: "POST",
9458
+ headers: { "Content-Type": "application/json" },
9459
+ body: JSON.stringify(payload),
9460
+ signal: controller.signal
9461
+ });
9462
+ } catch {} finally {
9463
+ clearTimeout(timeoutId);
9464
+ }
9465
+ }
9393
9466
  //#endregion
9394
9467
  //#region src/telemetry/index.ts
9395
9468
  /**
9396
9469
  * Telemetry client — internal to @ait-co/console-cli.
9397
9470
  *
9398
- * Usage: import { trackInvocation, trackInstall } from './telemetry/index.js'
9471
+ * Usage: import { trackInvocation, trackTier0Ping } from './telemetry/index.js'
9472
+ *
9473
+ * Tier 0 (opt-out): anonymous daily ping. Fires on every invocation; client-side
9474
+ * daily dedupe via tier0LastSent. Respects AITC_TELEMETRY=off, --no-telemetry,
9475
+ * and permanent tier0OptOut flag.
9399
9476
  *
9400
- * Events are fire-and-forget (non-blocking). Consent is opt-in only.
9401
- * First invocation on a TTY prompts the user; non-TTY (CI) defaults to deny.
9477
+ * Tier 1 (opt-in): detailed events. First invocation on a TTY prompts the user;
9478
+ * non-TTY (CI) defaults to deny.
9402
9479
  *
9403
9480
  * Endpoint override for staging: AITCC_TELEMETRY_ENV=staging
9404
9481
  * (or automatically when VERSION contains '-dev').
@@ -9442,6 +9519,37 @@ async function promptConsent() {
9442
9519
  rl.close();
9443
9520
  }
9444
9521
  }
9522
+ /**
9523
+ * Check whether telemetry is globally disabled via environment or CLI flag.
9524
+ * Accepts the parsed --no-telemetry flag value from argv.
9525
+ */
9526
+ function isTelemetryGloballyDisabled(noTelemetryFlag) {
9527
+ if (noTelemetryFlag) return true;
9528
+ const env = process.env.AITC_TELEMETRY;
9529
+ if (env !== void 0 && env.toLowerCase() === "off") return true;
9530
+ return false;
9531
+ }
9532
+ /**
9533
+ * Send a Tier 0 anonymous daily ping (fire-and-forget).
9534
+ *
9535
+ * Skips if:
9536
+ * - AITC_TELEMETRY=off or --no-telemetry flag
9537
+ * - tier0OptOut === true in the state file
9538
+ * - already sent today (tier0LastSent === today's ISO date)
9539
+ *
9540
+ * On success, records today's date in tier0LastSent for client-side daily dedupe.
9541
+ * The server also deduplicates server-side via KV, so this is an extra client guard.
9542
+ */
9543
+ async function trackTier0Ping(noTelemetryFlag = false) {
9544
+ try {
9545
+ if (isTelemetryGloballyDisabled(noTelemetryFlag)) return;
9546
+ if (await isTier0OptedOut()) return;
9547
+ const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
9548
+ if (await getTier0LastSent() === today) return;
9549
+ sendTier0Ping(TELEMETRY_ENDPOINT, VERSION);
9550
+ await markTier0Sent(today);
9551
+ } catch {}
9552
+ }
9445
9553
  /** True only on the first invocation after a fresh install. */
9446
9554
  async function isNewInstall() {
9447
9555
  const markerPath = `${telemetryFilePath()}.install`;
@@ -9455,11 +9563,14 @@ async function isNewInstall() {
9455
9563
  }
9456
9564
  /**
9457
9565
  * Called at CLI entry point with the resolved top-level command name.
9458
- * Handles first-run consent prompt, install detection, and event send.
9566
+ * Handles first-run Tier 1 consent prompt, install detection, and Tier 1 event send.
9459
9567
  * Fire-and-forget: do NOT await this.
9568
+ *
9569
+ * Note: Tier 0 ping is sent separately via trackTier0Ping() before this call.
9460
9570
  */
9461
- async function trackInvocation(command) {
9571
+ async function trackInvocation(command, noTelemetryFlag = false) {
9462
9572
  try {
9573
+ if (isTelemetryGloballyDisabled(noTelemetryFlag)) return;
9463
9574
  if (isFirstRun()) await promptConsent();
9464
9575
  if (await resolveEffectiveConsent() !== "granted") return;
9465
9576
  if (await isNewInstall()) send(TELEMETRY_ENDPOINT, "cli_install", VERSION, {
@@ -9472,13 +9583,13 @@ async function trackInvocation(command) {
9472
9583
  const telemetryCommand = defineCommand({
9473
9584
  meta: {
9474
9585
  name: "telemetry",
9475
- description: "Manage anonymous usage telemetry (opt-in)."
9586
+ description: "Manage anonymous usage telemetry."
9476
9587
  },
9477
9588
  subCommands: {
9478
9589
  status: defineCommand({
9479
9590
  meta: {
9480
9591
  name: "status",
9481
- description: "Show current telemetry consent state and anon_id."
9592
+ description: "Show current telemetry status for both Tier 0 and Tier 1."
9482
9593
  },
9483
9594
  args: { json: {
9484
9595
  type: "boolean",
@@ -9486,24 +9597,37 @@ const telemetryCommand = defineCommand({
9486
9597
  default: false
9487
9598
  } },
9488
9599
  async run({ args }) {
9489
- const consent = await resolveEffectiveConsent();
9490
- const anonId = consent === "granted" ? await getOrCreateAnonId() : null;
9600
+ const [tier1Consent, tier0OptOut, tier0LastSent, anonId] = await Promise.all([
9601
+ resolveEffectiveConsent(),
9602
+ isTier0OptedOut(),
9603
+ getTier0LastSent(),
9604
+ resolveEffectiveConsent().then((c) => c === "granted" ? getOrCreateAnonId() : null)
9605
+ ]);
9491
9606
  const filePath = telemetryFilePath();
9607
+ const tier0Status = tier0OptOut ? "off (opted out)" : "on";
9608
+ const tier0Display = tier0LastSent ? `${tier0Status} (last sent: ${tier0LastSent})` : tier0Status;
9492
9609
  if (args.json) {
9493
9610
  process.stdout.write(`${JSON.stringify({
9494
9611
  ok: true,
9495
- consent,
9496
- policyVersion: CURRENT_POLICY_VERSION,
9612
+ tier0: {
9613
+ status: tier0OptOut ? "opted-out" : "on",
9614
+ lastSent: tier0LastSent ?? null
9615
+ },
9616
+ tier1: {
9617
+ consent: tier1Consent,
9618
+ policyVersion: CURRENT_POLICY_VERSION,
9619
+ ...anonId ? { anonId } : {}
9620
+ },
9497
9621
  endpoint: TELEMETRY_ENDPOINT,
9498
- ...anonId ? { anonId } : {},
9499
9622
  filePath
9500
9623
  })}\n`);
9501
9624
  return exitAfterFlush(ExitCode.Ok);
9502
9625
  }
9503
- process.stdout.write(`Telemetry: ${consent}\n`);
9504
- process.stdout.write(`Policy version: ${CURRENT_POLICY_VERSION}\n`);
9505
- process.stdout.write(`Endpoint: ${TELEMETRY_ENDPOINT}\n`);
9506
- if (anonId) process.stdout.write(`Anon ID: ${anonId}\n`);
9626
+ process.stdout.write("Telemetry status\n");
9627
+ process.stdout.write(` Tier 0 (anonymous daily ping): ${tier0Display}\n`);
9628
+ process.stdout.write(` Tier 1 (opt-in events): ${tier1Consent} (policyVersion: ${CURRENT_POLICY_VERSION})\n`);
9629
+ process.stdout.write(`\nEndpoint: ${TELEMETRY_ENDPOINT}\n`);
9630
+ if (anonId) process.stdout.write(`Anon ID: ${anonId}\n`);
9507
9631
  process.stdout.write(`State file: ${filePath}\n`);
9508
9632
  return exitAfterFlush(ExitCode.Ok);
9509
9633
  }
@@ -9575,6 +9699,46 @@ const telemetryCommand = defineCommand({
9575
9699
  else process.stderr.write("Deletion request failed. Please try again or contact the maintainers.\n");
9576
9700
  return exitAfterFlush(ok || beforeConsent === "undecided" ? ExitCode.Ok : ExitCode.NetworkError);
9577
9701
  }
9702
+ }),
9703
+ "tier0-off": defineCommand({
9704
+ meta: {
9705
+ name: "tier0-off",
9706
+ description: "Permanently opt out of the Tier 0 anonymous daily ping."
9707
+ },
9708
+ args: { json: {
9709
+ type: "boolean",
9710
+ description: "Emit machine-readable JSON.",
9711
+ default: false
9712
+ } },
9713
+ async run({ args }) {
9714
+ await setTier0OptOut(true);
9715
+ if (args.json) process.stdout.write(`${JSON.stringify({
9716
+ ok: true,
9717
+ tier0: { status: "opted-out" }
9718
+ })}\n`);
9719
+ else process.stdout.write("Tier 0 anonymous ping disabled. No daily pings will be sent.\n");
9720
+ return exitAfterFlush(ExitCode.Ok);
9721
+ }
9722
+ }),
9723
+ "tier0-on": defineCommand({
9724
+ meta: {
9725
+ name: "tier0-on",
9726
+ description: "Re-enable the Tier 0 anonymous daily ping after a previous tier0-off."
9727
+ },
9728
+ args: { json: {
9729
+ type: "boolean",
9730
+ description: "Emit machine-readable JSON.",
9731
+ default: false
9732
+ } },
9733
+ async run({ args }) {
9734
+ await setTier0OptOut(false);
9735
+ if (args.json) process.stdout.write(`${JSON.stringify({
9736
+ ok: true,
9737
+ tier0: { status: "on" }
9738
+ })}\n`);
9739
+ else process.stdout.write("Tier 0 anonymous ping re-enabled.\n");
9740
+ return exitAfterFlush(ExitCode.Ok);
9741
+ }
9578
9742
  })
9579
9743
  }
9580
9744
  });
@@ -10864,7 +11028,10 @@ const main = defineCommand({
10864
11028
  }
10865
11029
  });
10866
11030
  cleanupStaleUpgradeArtifacts().catch(() => {});
10867
- trackInvocation(process.argv.slice(2).find((a) => !a.startsWith("-")) ?? "(none)");
11031
+ const _telemetryCmd = process.argv.slice(2).find((a) => !a.startsWith("-")) ?? "(none)";
11032
+ const _noTelemetry = process.argv.includes("--no-telemetry");
11033
+ trackTier0Ping(_noTelemetry);
11034
+ trackInvocation(_telemetryCmd, _noTelemetry);
10868
11035
  runMain(main);
10869
11036
  //#endregion
10870
11037
  export {};