@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.
- package/bin/dosu.js +237 -34
- 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.
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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",
|