@dosu/cli 0.11.0 → 0.12.1

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.
Files changed (2) hide show
  1. package/bin/dosu.js +237 -34
  2. package/package.json +2 -2
package/bin/dosu.js CHANGED
@@ -4341,7 +4341,7 @@ function getSupabaseAnonKey() {
4341
4341
  function getVersionString() {
4342
4342
  return `v${VERSION}`;
4343
4343
  }
4344
- var VERSION = "0.11.0";
4344
+ var VERSION = "0.12.1";
4345
4345
 
4346
4346
  // src/debug/logger.ts
4347
4347
  import {
@@ -6258,6 +6258,88 @@ var init_dist6 = __esm(() => {
6258
6258
  J2 = `${import_picocolors20.default.gray(o)} `;
6259
6259
  });
6260
6260
 
6261
+ // src/setup/analytics.ts
6262
+ async function trackCliOnboardingEvent(cfg, onboardingRunID, event, properties = {}) {
6263
+ if (!cfg.access_token)
6264
+ return;
6265
+ try {
6266
+ const trpc = createTypedClient(cfg);
6267
+ await withTimeout(trpc.user.trackCliOnboardingEvent.mutate({
6268
+ event,
6269
+ properties: {
6270
+ ...baseProperties(cfg),
6271
+ onboarding_run_id: onboardingRunID,
6272
+ ...properties
6273
+ }
6274
+ }), TRACKING_TIMEOUT_MS);
6275
+ } catch (err) {
6276
+ const msg = err instanceof Error ? err.message : String(err);
6277
+ logger.debug("setup", `CLI onboarding analytics failed: ${event}: ${msg}`);
6278
+ }
6279
+ }
6280
+ async function trackCliOnboardingPreAuthEvent(onboardingRunID, event, properties = {}) {
6281
+ try {
6282
+ const trpc = createAnonymousClient();
6283
+ await withTimeout(trpc.user.trackCliOnboardingPreAuthEvent.mutate({
6284
+ event,
6285
+ onboarding_run_id: onboardingRunID,
6286
+ properties: {
6287
+ ...baseProperties({ access_token: "", refresh_token: "", expires_at: 0 }),
6288
+ ...properties
6289
+ }
6290
+ }), TRACKING_TIMEOUT_MS);
6291
+ } catch (err) {
6292
+ const msg = err instanceof Error ? err.message : String(err);
6293
+ logger.debug("setup", `CLI onboarding pre-auth analytics failed: ${event}: ${msg}`);
6294
+ }
6295
+ }
6296
+ function baseProperties(cfg) {
6297
+ return {
6298
+ cli_version: VERSION,
6299
+ platform: process.platform,
6300
+ arch: process.arch,
6301
+ mode: cfg.mode ?? "cloud",
6302
+ org_id: cfg.org_id,
6303
+ deployment_id: cfg.deployment_id,
6304
+ space_id: cfg.space_id
6305
+ };
6306
+ }
6307
+ function createAnonymousClient() {
6308
+ const webAppURL = getWebAppURL();
6309
+ if (!webAppURL) {
6310
+ throw new Error("Web app URL not configured");
6311
+ }
6312
+ return createTRPCClient({
6313
+ links: [
6314
+ httpLink({
6315
+ url: `${webAppURL}/api/trpc`,
6316
+ transformer: dist_default
6317
+ })
6318
+ ]
6319
+ });
6320
+ }
6321
+ async function withTimeout(promise, timeoutMs) {
6322
+ let timeout;
6323
+ try {
6324
+ return await Promise.race([
6325
+ promise,
6326
+ new Promise((_3, reject) => {
6327
+ timeout = setTimeout(() => reject(new Error("tracking timeout")), timeoutMs);
6328
+ })
6329
+ ]);
6330
+ } finally {
6331
+ if (timeout)
6332
+ clearTimeout(timeout);
6333
+ }
6334
+ }
6335
+ var TRACKING_TIMEOUT_MS = 1500;
6336
+ var init_analytics = __esm(() => {
6337
+ init_dist();
6338
+ init_dist4();
6339
+ init_trpc();
6340
+ init_logger();
6341
+ });
6342
+
6261
6343
  // src/setup/styles.ts
6262
6344
  function dim(msg) {
6263
6345
  return import_picocolors21.default.dim(msg);
@@ -7660,7 +7742,8 @@ ${dim(`deployment ${deployment_id}`)}`);
7660
7742
  has_connected_repo: true,
7661
7743
  deployment_id: primary.deployment_id,
7662
7744
  space_id: cfg.space_id,
7663
- created_data_source_ids: survived.map((c) => c.data_source_id)
7745
+ created_data_source_ids: survived.map((c) => c.data_source_id),
7746
+ created_repository_slugs: survived.map((c) => c.slug)
7664
7747
  };
7665
7748
  }
7666
7749
  }
@@ -8043,7 +8126,7 @@ async function stepImportGitHubDocs(cfg, opts = {}) {
8043
8126
  }
8044
8127
  if (files.length === 0) {
8045
8128
  M2.info("No markdown docs available to import right now. You can import them later.");
8046
- return { advance: true };
8129
+ return { advance: true, imported: false, imported_count: 0 };
8047
8130
  }
8048
8131
  const repositories = buildRepositories(files);
8049
8132
  const selected = await promptGitHubDocsImport({ repositories });
@@ -8054,7 +8137,7 @@ async function stepImportGitHubDocs(cfg, opts = {}) {
8054
8137
  const fileIDs = selected;
8055
8138
  if (fileIDs.length === 0) {
8056
8139
  M2.info("Skipped importing docs for now. You can import them later.");
8057
- return { advance: true };
8140
+ return { advance: true, imported: false, imported_count: 0 };
8058
8141
  }
8059
8142
  const knowledgeStoreID = await getKnowledgeStoreID(trpc, cfg.space_id);
8060
8143
  if (!knowledgeStoreID) {
@@ -8073,7 +8156,7 @@ async function stepImportGitHubDocs(cfg, opts = {}) {
8073
8156
  spinner.stop("Import task started");
8074
8157
  M2.success("Import task started.");
8075
8158
  M2.info("Your docs should finish importing in a few minutes.");
8076
- return { advance: true };
8159
+ return { advance: true, imported: false, imported_count: 0, queued: true };
8077
8160
  }
8078
8161
  spinner.stop("Import task started");
8079
8162
  logger.info("setup", `Watching import task ${taskID}`);
@@ -8085,10 +8168,23 @@ async function stepImportGitHubDocs(cfg, opts = {}) {
8085
8168
  progressSpinner.stop("Stopped watching import progress");
8086
8169
  M2.info(`The import is still running in the background.
8087
8170
  Check status later with: dosu docs import-status ${taskID}`);
8088
- return { advance: true };
8171
+ return {
8172
+ advance: true,
8173
+ imported: false,
8174
+ imported_count: 0,
8175
+ queued: true,
8176
+ task_id: taskID
8177
+ };
8089
8178
  }
8090
8179
  handleImportCompletion(finalStatus, progressSpinner);
8091
- return { advance: true };
8180
+ const importedCount = finalStatus.detail?.completed ?? 0;
8181
+ return {
8182
+ advance: true,
8183
+ imported: importedCount > 0,
8184
+ imported_count: importedCount,
8185
+ failed_count: finalStatus.detail?.failed ?? 0,
8186
+ task_id: taskID
8187
+ };
8092
8188
  } catch (err) {
8093
8189
  spinner.stop("Failed");
8094
8190
  const msg = err instanceof Error ? err.message : String(err);
@@ -8164,13 +8260,23 @@ async function waitForImportableGithubFiles(trpc, orgID, spaceID, expectedDataSo
8164
8260
  M2.info("This usually takes a few seconds.");
8165
8261
  const startedAt = Date.now();
8166
8262
  let latestFiles = [];
8263
+ const waitsForExpectedDataSources = expectedDataSourceIds !== undefined && expectedDataSourceIds.length > 0;
8167
8264
  while (Date.now() - startedAt < DOC_SCAN_POLL_TIMEOUT_MS) {
8265
+ const dataSources = await fetchGitHubDataSources(trpc, orgID);
8266
+ if (waitsForExpectedDataSources) {
8267
+ if (isScanComplete(dataSources, expectedDataSourceIds)) {
8268
+ latestFiles = await fetchImportableGithubFiles(trpc, spaceID);
8269
+ spinner.stop(latestFiles.length > 0 ? "Docs ready" : "No markdown docs found");
8270
+ return latestFiles;
8271
+ }
8272
+ await sleep3(DOC_SCAN_POLL_INTERVAL_MS);
8273
+ continue;
8274
+ }
8168
8275
  latestFiles = await fetchImportableGithubFiles(trpc, spaceID);
8169
8276
  if (latestFiles.length > 0) {
8170
8277
  spinner.stop("Docs ready");
8171
8278
  return latestFiles;
8172
8279
  }
8173
- const dataSources = await fetchGitHubDataSources(trpc, orgID);
8174
8280
  if (isScanComplete(dataSources, expectedDataSourceIds)) {
8175
8281
  spinner.stop("No markdown docs found");
8176
8282
  return [];
@@ -8533,13 +8639,13 @@ var exports_flow = {};
8533
8639
  __export(exports_flow, {
8534
8640
  startOAuthFlow: () => startOAuthFlow
8535
8641
  });
8536
- async function startOAuthFlow(signal, path2 = "/cli/auth") {
8642
+ async function startOAuthFlow(signal, path2 = "/cli/auth", params = {}) {
8537
8643
  const { server, tokenPromise } = await startCallbackServer();
8538
8644
  let timeoutId;
8539
8645
  try {
8540
8646
  const callbackURL = `http://localhost:${server.port}/callback`;
8541
8647
  logger.debug("auth.flow", `Callback URL: ${callbackURL}`);
8542
- const authURL = buildAuthURL(callbackURL, path2);
8648
+ const authURL = buildAuthURL(callbackURL, path2, params);
8543
8649
  logger.info("auth.flow", `Auth URL: ${authURL}`);
8544
8650
  const open2 = await Promise.resolve().then(() => (init_open(), exports_open));
8545
8651
  await open2.default(authURL);
@@ -8565,9 +8671,9 @@ async function startOAuthFlow(signal, path2 = "/cli/auth") {
8565
8671
  logger.debug("auth.flow", "Cleaning up: timeout cleared, server closed");
8566
8672
  }
8567
8673
  }
8568
- function buildAuthURL(callbackURL, path2) {
8674
+ function buildAuthURL(callbackURL, path2, extraParams) {
8569
8675
  const webAppURL = getWebAppURL();
8570
- const params = new URLSearchParams({ callback: callbackURL });
8676
+ const params = new URLSearchParams({ callback: callbackURL, ...extraParams });
8571
8677
  return `${webAppURL}${path2}?${params}`;
8572
8678
  }
8573
8679
  var init_flow = __esm(() => {
@@ -8586,21 +8692,28 @@ __export(exports_flow2, {
8586
8692
  runInstallSkill: () => runInstallSkill,
8587
8693
  isStdioOnly: () => isStdioOnly
8588
8694
  });
8695
+ import { randomUUID } from "node:crypto";
8589
8696
  import { existsSync as existsSync9 } from "node:fs";
8590
8697
  import { join as join19 } from "node:path";
8591
8698
  async function runSetup(opts = {}) {
8699
+ const onboardingRunID = randomUUID();
8592
8700
  logger.info("setup", `Setup flow started${opts.deploymentID ? ` deployment=${opts.deploymentID}` : ""}${opts.mode ? ` mode=${opts.mode}` : ""}`);
8593
8701
  Ie("Dosu CLI Setup");
8702
+ await trackCliOnboardingPreAuthEvent(onboardingRunID, "cli_onboarding_launch_attempted", {
8703
+ has_deployment_option: Boolean(opts.deploymentID),
8704
+ mode_option: opts.mode
8705
+ });
8594
8706
  let cfg = loadConfig();
8595
8707
  applyModeOverride(cfg, opts);
8596
8708
  if (opts.deploymentID) {
8597
8709
  cfg.mode = undefined;
8598
8710
  saveConfig(cfg);
8599
8711
  }
8600
- const authedCfg = await stepAuthenticate(cfg);
8712
+ const authedCfg = await stepAuthenticate(cfg, onboardingRunID);
8601
8713
  if (!authedCfg)
8602
8714
  return;
8603
8715
  cfg = authedCfg;
8716
+ await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_auth_completed");
8604
8717
  const apiClient = new Client(cfg);
8605
8718
  let cloudSetupContext = null;
8606
8719
  if (cfg.mode !== MODE_OSS) {
@@ -8608,46 +8721,102 @@ async function runSetup(opts = {}) {
8608
8721
  s.start("Loading your workspace...");
8609
8722
  cloudSetupContext = await resolveCloudSetupContext(cfg);
8610
8723
  if (!cloudSetupContext) {
8724
+ await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_failed", {
8725
+ reason: "cloud_setup_context_failed"
8726
+ });
8611
8727
  s.stop("Workspace load failed");
8612
8728
  return;
8613
8729
  }
8614
8730
  s.stop("Workspace loaded");
8615
8731
  }
8732
+ await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_started", {
8733
+ flow_kind: cloudSetupContext?.kind ?? "oss"
8734
+ });
8616
8735
  if (cfg.mode !== MODE_OSS && cloudSetupContext?.kind === "onboarding") {
8617
8736
  const ok = await bindOnboardingDeployment(apiClient, cfg, cloudSetupContext.targetOrg ?? null);
8618
- if (!ok)
8737
+ if (!ok) {
8738
+ await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_failed", {
8739
+ reason: "onboarding_deployment_failed"
8740
+ });
8619
8741
  return;
8742
+ }
8620
8743
  } else if (!cfg.deployment_id || opts.deploymentID) {
8621
8744
  const ok = await resolveDeployment(apiClient, cfg, opts);
8622
- if (!ok)
8745
+ if (!ok) {
8746
+ await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_failed", {
8747
+ reason: "deployment_resolution_failed"
8748
+ });
8623
8749
  return;
8750
+ }
8624
8751
  }
8625
8752
  const apiKey = await stepMintAPIKey(apiClient, cfg);
8626
- if (!apiKey)
8753
+ if (!apiKey) {
8754
+ await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_failed", {
8755
+ reason: "api_key_failed"
8756
+ });
8627
8757
  return;
8758
+ }
8628
8759
  cfg.api_key = apiKey;
8629
8760
  saveConfig(cfg);
8630
8761
  const choices = await stepOneShotConfirm({
8631
8762
  includeGitHub: cloudSetupContext?.kind === "onboarding"
8632
8763
  });
8633
- if (!choices)
8764
+ if (!choices) {
8765
+ await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_cancelled", {
8766
+ reason: "options_cancelled"
8767
+ });
8634
8768
  return;
8769
+ }
8770
+ await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_options_selected", {
8771
+ configure_mcp: choices.configureMcp,
8772
+ install_skill: choices.installSkill,
8773
+ connect_github: choices.connectGitHub
8774
+ });
8635
8775
  let mcpConfiguredThisRun = false;
8776
+ let mcpCompleted = false;
8777
+ let skillCompleted = false;
8778
+ let docsImported = false;
8636
8779
  if (choices.configureMcp) {
8637
8780
  const configured = await stepConfigureMcpTools(cfg);
8638
- if (configured === null)
8781
+ if (configured === null) {
8782
+ await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_cancelled", {
8783
+ reason: "mcp_selection_cancelled"
8784
+ });
8639
8785
  return;
8786
+ }
8640
8787
  mcpConfiguredThisRun = configured.some((r) => r.action === "install" || r.action === "skip");
8788
+ const configuredProviders = configured.filter((r) => (r.action === "install" || r.action === "skip") && !r.error);
8789
+ mcpCompleted = configuredProviders.length > 0;
8790
+ if (mcpCompleted) {
8791
+ await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_mcp_configured", {
8792
+ provider_count: configuredProviders.length,
8793
+ providers: configuredProviders.map((r) => r.provider.id())
8794
+ });
8795
+ }
8641
8796
  }
8642
8797
  if (choices.installSkill) {
8643
- await runInstallSkill();
8798
+ skillCompleted = await runInstallSkill();
8799
+ if (skillCompleted) {
8800
+ await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_skill_installed");
8801
+ }
8644
8802
  }
8645
8803
  let githubOnboardingDone = !choices.connectGitHub;
8646
8804
  if (choices.connectGitHub && cloudSetupContext?.kind === "onboarding") {
8647
8805
  const { stepConnectGitHubRepo: stepConnectGitHubRepo2 } = await Promise.resolve().then(() => (init_github_step(), exports_github_step));
8648
8806
  const connectResult = await stepConnectGitHubRepo2(cfg);
8649
- if (!connectResult.advance)
8807
+ if (!connectResult.advance) {
8808
+ await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_cancelled", {
8809
+ reason: "github_connect_not_advanced",
8810
+ has_connected_repo: connectResult.has_connected_repo
8811
+ });
8650
8812
  return;
8813
+ }
8814
+ if (connectResult.has_connected_repo || (connectResult.created_data_source_ids?.length ?? 0) > 0) {
8815
+ await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_github_connected", {
8816
+ created_data_source_count: connectResult.created_data_source_ids?.length ?? 0,
8817
+ created_repository_slugs: connectResult.created_repository_slugs
8818
+ });
8819
+ }
8651
8820
  if (connectResult.space_id && !cfg.space_id) {
8652
8821
  cfg.space_id = connectResult.space_id;
8653
8822
  saveConfig(cfg);
@@ -8657,8 +8826,24 @@ async function runSetup(opts = {}) {
8657
8826
  waitForFreshDocs: Boolean(connectResult.deployment_id),
8658
8827
  expectedDataSourceIds: connectResult.created_data_source_ids
8659
8828
  });
8660
- if (!importResult.advance)
8829
+ if (!importResult.advance) {
8830
+ await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_failed", {
8831
+ reason: "github_docs_import_failed"
8832
+ });
8661
8833
  return;
8834
+ }
8835
+ docsImported = importResult.imported === true && (importResult.imported_count ?? 0) > 0;
8836
+ if (docsImported) {
8837
+ await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_docs_imported", {
8838
+ imported_count: importResult.imported_count ?? 0,
8839
+ failed_count: importResult.failed_count ?? 0,
8840
+ task_id: importResult.task_id
8841
+ });
8842
+ await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_activated", {
8843
+ imported_count: importResult.imported_count ?? 0,
8844
+ failed_count: importResult.failed_count ?? 0
8845
+ });
8846
+ }
8662
8847
  githubOnboardingDone = true;
8663
8848
  }
8664
8849
  const shouldCompleteRemoteOnboarding = cloudSetupContext?.kind === "onboarding" && githubOnboardingDone;
@@ -8684,6 +8869,13 @@ async function runSetup(opts = {}) {
8684
8869
  hasAgentsMd: existsSync9(join19(process.cwd(), "AGENTS.md"))
8685
8870
  });
8686
8871
  }
8872
+ if (mcpCompleted || skillCompleted || docsImported) {
8873
+ await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_completed", {
8874
+ completed_mcp: mcpCompleted,
8875
+ completed_skill: skillCompleted,
8876
+ imported_docs: docsImported
8877
+ });
8878
+ }
8687
8879
  if (cfg.mode === MODE_OSS) {
8688
8880
  Se("Setup complete! Using open-source libraries only.\n\nTips: Run `dosu setup --mode cloud` to connect your own repos.");
8689
8881
  } else {
@@ -8767,7 +8959,7 @@ async function runInstallSkill() {
8767
8959
  return false;
8768
8960
  }
8769
8961
  }
8770
- async function stepAuthenticate(existingCfg) {
8962
+ async function stepAuthenticate(existingCfg, onboardingRunID) {
8771
8963
  logger.info("setup", "Step: authenticate");
8772
8964
  const cfg = existingCfg ?? loadConfig();
8773
8965
  if (cfg.access_token) {
@@ -8798,16 +8990,25 @@ async function stepAuthenticate(existingCfg) {
8798
8990
  }
8799
8991
  }
8800
8992
  const shouldLogin = await ye({ message: "Open browser to log in?" });
8801
- if (pD(shouldLogin) || !shouldLogin)
8993
+ if (pD(shouldLogin) || !shouldLogin) {
8994
+ if (onboardingRunID) {
8995
+ await trackCliOnboardingPreAuthEvent(onboardingRunID, "cli_onboarding_auth_cancelled", {
8996
+ reason: pD(shouldLogin) ? "prompt_cancelled" : "login_declined"
8997
+ });
8998
+ }
8802
8999
  return null;
8803
- return await openBrowserForSetup(cfg);
9000
+ }
9001
+ if (onboardingRunID) {
9002
+ await trackCliOnboardingPreAuthEvent(onboardingRunID, "cli_onboarding_auth_started");
9003
+ }
9004
+ return await openBrowserForSetup(cfg, onboardingRunID);
8804
9005
  }
8805
- async function openBrowserForSetup(cfg) {
9006
+ async function openBrowserForSetup(cfg, onboardingRunID) {
8806
9007
  try {
8807
9008
  const { startOAuthFlow: startOAuthFlow2 } = await Promise.resolve().then(() => (init_flow(), exports_flow));
8808
9009
  const s = Y2();
8809
9010
  s.start("Waiting for authentication...");
8810
- const token = await startOAuthFlow2(undefined, "/cli/auth");
9011
+ const token = await startOAuthFlow2(undefined, "/cli/auth", onboardingRunID ? { onboarding_run_id: onboardingRunID } : {});
8811
9012
  s.stop("Authenticated");
8812
9013
  logger.info("setup", "Browser auth completed");
8813
9014
  cfg.access_token = token.access_token;
@@ -8819,6 +9020,11 @@ async function openBrowserForSetup(cfg) {
8819
9020
  const msg = err instanceof Error ? err.stack ?? err.message : String(err);
8820
9021
  logger.error("setup", `Auth failed: ${msg}`);
8821
9022
  M2.error(`Authentication failed: ${err instanceof Error ? err.message : String(err)}`);
9023
+ if (onboardingRunID) {
9024
+ await trackCliOnboardingPreAuthEvent(onboardingRunID, "cli_onboarding_auth_failed", {
9025
+ reason: err instanceof Error ? err.message : String(err)
9026
+ });
9027
+ }
8822
9028
  return null;
8823
9029
  }
8824
9030
  }
@@ -8856,14 +9062,11 @@ async function resolveCloudSetupContext(cfg) {
8856
9062
  }
8857
9063
  }
8858
9064
  async function resolveOnboardingTargetOrg(trpc) {
8859
- const ownerOrgs = await trpc.organization.getOrganizations.query({
8860
- userRole: "OWNER",
8861
- exact: true
8862
- });
8863
- if (ownerOrgs.length > 0) {
8864
- return ownerOrgs[0];
8865
- }
8866
9065
  const accessibleOrgs = await trpc.organization.getOrganizations.query();
9066
+ const ownerOrg = accessibleOrgs.find((org) => org.user_role === "OWNER");
9067
+ if (ownerOrg) {
9068
+ return ownerOrg;
9069
+ }
8867
9070
  return accessibleOrgs[0] ?? null;
8868
9071
  }
8869
9072
  async function bindOnboardingDeployment(apiClient, cfg, targetOrg) {
@@ -9142,6 +9345,7 @@ var init_flow2 = __esm(() => {
9142
9345
  init_config();
9143
9346
  init_logger();
9144
9347
  init_providers();
9348
+ init_analytics();
9145
9349
  init_styles();
9146
9350
  });
9147
9351
 
@@ -9379,7 +9583,6 @@ function analyticsCommand() {
9379
9583
  ["Low Confidence", String(stats.byConfidence.low)],
9380
9584
  ["Positive Reactions", String(stats.reactions.totalPositive)],
9381
9585
  ["Negative Reactions", String(stats.reactions.totalNegative)],
9382
- ["Reaction Rate", pct(stats.reactions.reactionRate)],
9383
9586
  ["Positive Rate", pct(stats.reactions.positiveRate)]
9384
9587
  ], { rawData: stats });
9385
9588
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dosu/cli",
3
- "version": "0.11.0",
3
+ "version": "0.12.1",
4
4
  "type": "module",
5
5
  "description": "Dosu CLI - Manage MCP servers for AI tools",
6
6
  "license": "MIT",
@@ -48,7 +48,7 @@
48
48
  },
49
49
  "dependencies": {
50
50
  "@clack/prompts": "^0.10.0",
51
- "@dosu/api-types": "0.0.4",
51
+ "@dosu/api-types": "0.0.7",
52
52
  "commander": "^13.1.0",
53
53
  "open": "^10.1.0",
54
54
  "picocolors": "^1.1.1",