@dosu/cli 0.30.0 → 0.32.0
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 +318 -900
- package/package.json +1 -1
package/bin/dosu.js
CHANGED
|
@@ -4577,7 +4577,7 @@ var init_dist4 = __esm(() => {
|
|
|
4577
4577
|
function getVersionString() {
|
|
4578
4578
|
return `v${VERSION}`;
|
|
4579
4579
|
}
|
|
4580
|
-
var VERSION = "0.
|
|
4580
|
+
var VERSION = "0.32.0", INSTALL_CHANNEL = "npm";
|
|
4581
4581
|
|
|
4582
4582
|
// src/debug/logger.ts
|
|
4583
4583
|
import {
|
|
@@ -4711,7 +4711,7 @@ var init_logger = __esm(() => {
|
|
|
4711
4711
|
});
|
|
4712
4712
|
|
|
4713
4713
|
// src/client/contract.ts
|
|
4714
|
-
var CLI_CONTRACT_HASH = "
|
|
4714
|
+
var CLI_CONTRACT_HASH = "f5c0727a7884";
|
|
4715
4715
|
|
|
4716
4716
|
// src/client/trpc.ts
|
|
4717
4717
|
var exports_trpc = {};
|
|
@@ -6961,6 +6961,10 @@ var init_installation_server = __esm(() => {
|
|
|
6961
6961
|
function dim(msg) {
|
|
6962
6962
|
return import_picocolors7.default.dim(msg);
|
|
6963
6963
|
}
|
|
6964
|
+
function browserFallbackHint(url) {
|
|
6965
|
+
return dim(`If your browser doesn't open automatically, visit:
|
|
6966
|
+
${url}`);
|
|
6967
|
+
}
|
|
6964
6968
|
function info(msg) {
|
|
6965
6969
|
return import_picocolors7.default.cyan(msg);
|
|
6966
6970
|
}
|
|
@@ -7624,12 +7628,6 @@ var init_open = __esm(() => {
|
|
|
7624
7628
|
});
|
|
7625
7629
|
|
|
7626
7630
|
// src/setup/github-step.ts
|
|
7627
|
-
var exports_github_step = {};
|
|
7628
|
-
__export(exports_github_step, {
|
|
7629
|
-
verifyDataSourcesPersist: () => verifyDataSourcesPersist,
|
|
7630
|
-
stepConnectGitHubRepo: () => stepConnectGitHubRepo,
|
|
7631
|
-
detectGitRepo: () => detectGitRepo
|
|
7632
|
-
});
|
|
7633
7631
|
import { execSync } from "node:child_process";
|
|
7634
7632
|
function detectGitRepo(cwd = process.cwd()) {
|
|
7635
7633
|
let url;
|
|
@@ -7722,6 +7720,7 @@ async function openGitHubInstallFlow(onInstalled, opts) {
|
|
|
7722
7720
|
middleURL.searchParams.set("callback", callbackURL);
|
|
7723
7721
|
log.info(`Opening your browser to GitHub.
|
|
7724
7722
|
` + "Add repositories or install the Dosu GitHub App, and we'll pick up automatically.");
|
|
7723
|
+
log.message(browserFallbackHint(middleURL.toString()));
|
|
7725
7724
|
try {
|
|
7726
7725
|
const open2 = await Promise.resolve().then(() => (init_open(), exports_open));
|
|
7727
7726
|
await open2.default(middleURL.toString());
|
|
@@ -11135,633 +11134,6 @@ var init_audit_handoff = __esm(() => {
|
|
|
11135
11134
|
init_styles();
|
|
11136
11135
|
});
|
|
11137
11136
|
|
|
11138
|
-
// src/setup/github-doc-import-prompt.ts
|
|
11139
|
-
async function promptGitHubDocsImport({
|
|
11140
|
-
repositories
|
|
11141
|
-
}) {
|
|
11142
|
-
const prompt = new GitHubDocsImportPrompt({ repositories });
|
|
11143
|
-
return await prompt.prompt();
|
|
11144
|
-
}
|
|
11145
|
-
function getSelectableFileIds(files) {
|
|
11146
|
-
return files.filter((file) => !file.is_synced).map((file) => file.id);
|
|
11147
|
-
}
|
|
11148
|
-
function visibleOptions2(cursor3, totalItems, maxItems) {
|
|
11149
|
-
const terminalRows = process.stdout.rows ? Math.max(process.stdout.rows - 8, 0) : totalItems;
|
|
11150
|
-
const visibleCount = Math.min(terminalRows || totalItems, Math.max(maxItems ?? Infinity, 5));
|
|
11151
|
-
if (visibleCount >= totalItems) {
|
|
11152
|
-
return Array.from({ length: totalItems }, (_2, index) => ({ kind: "option", index }));
|
|
11153
|
-
}
|
|
11154
|
-
let start = 0;
|
|
11155
|
-
if (cursor3 >= start + visibleCount - 3) {
|
|
11156
|
-
start = Math.max(Math.min(cursor3 - visibleCount + 3, totalItems - visibleCount), 0);
|
|
11157
|
-
} else if (cursor3 < start + 2) {
|
|
11158
|
-
start = Math.max(cursor3 - 2, 0);
|
|
11159
|
-
}
|
|
11160
|
-
const hasTopEllipsis = visibleCount < totalItems && start > 0;
|
|
11161
|
-
const hasBottomEllipsis = visibleCount < totalItems && start + visibleCount < totalItems;
|
|
11162
|
-
return Array.from({ length: visibleCount }, (_2, index) => {
|
|
11163
|
-
const isTopEllipsis = index === 0 && hasTopEllipsis;
|
|
11164
|
-
const isBottomEllipsis = index === visibleCount - 1 && hasBottomEllipsis;
|
|
11165
|
-
if (isTopEllipsis || isBottomEllipsis) {
|
|
11166
|
-
return { kind: "ellipsis" };
|
|
11167
|
-
}
|
|
11168
|
-
return { kind: "option", index: start + index };
|
|
11169
|
-
});
|
|
11170
|
-
}
|
|
11171
|
-
function wrapIndex(index, length) {
|
|
11172
|
-
if (length === 0)
|
|
11173
|
-
return 0;
|
|
11174
|
-
if (index < 0)
|
|
11175
|
-
return length - 1;
|
|
11176
|
-
if (index >= length)
|
|
11177
|
-
return 0;
|
|
11178
|
-
return index;
|
|
11179
|
-
}
|
|
11180
|
-
function isPrintableKey(key) {
|
|
11181
|
-
return key.length === 1 && key >= " " && key !== "";
|
|
11182
|
-
}
|
|
11183
|
-
var import_picocolors14, CHECKBOX_PARTIAL, MAX_VISIBLE_FILE_ITEMS = 15, GitHubDocsImportPrompt;
|
|
11184
|
-
var init_github_doc_import_prompt = __esm(() => {
|
|
11185
|
-
init_dist7();
|
|
11186
|
-
init_prompt_symbols();
|
|
11187
|
-
import_picocolors14 = __toESM(require_picocolors(), 1);
|
|
11188
|
-
CHECKBOX_PARTIAL = symbol2("◧", "[-]");
|
|
11189
|
-
GitHubDocsImportPrompt = class GitHubDocsImportPrompt extends V {
|
|
11190
|
-
repositories;
|
|
11191
|
-
mode = "repos";
|
|
11192
|
-
repoCursor = 0;
|
|
11193
|
-
fileCursor = 0;
|
|
11194
|
-
searchQuery = "";
|
|
11195
|
-
searchActive = false;
|
|
11196
|
-
selectedIds = new Set;
|
|
11197
|
-
constructor({ repositories }) {
|
|
11198
|
-
super({
|
|
11199
|
-
render() {
|
|
11200
|
-
return this.renderPrompt();
|
|
11201
|
-
}
|
|
11202
|
-
}, false);
|
|
11203
|
-
this.repositories = repositories;
|
|
11204
|
-
this.selectedIds = new Set(repositories.flatMap((repository) => getSelectableFileIds(repository.files)));
|
|
11205
|
-
this.syncValue();
|
|
11206
|
-
this.onKeypress = this.handleRawKeypress.bind(this);
|
|
11207
|
-
}
|
|
11208
|
-
handleRawKeypress(key, info2) {
|
|
11209
|
-
this.handleKeypress(key, info2);
|
|
11210
|
-
this.syncValue();
|
|
11211
|
-
if (this.rl) {
|
|
11212
|
-
this.render();
|
|
11213
|
-
}
|
|
11214
|
-
if ((this.state === "submit" || this.state === "cancel") && this.rl) {
|
|
11215
|
-
this.close();
|
|
11216
|
-
}
|
|
11217
|
-
}
|
|
11218
|
-
handleKeypress(key, info2) {
|
|
11219
|
-
if (info2?.ctrl && info2.name === "c") {
|
|
11220
|
-
this.state = "cancel";
|
|
11221
|
-
return;
|
|
11222
|
-
}
|
|
11223
|
-
if (this.mode === "repos") {
|
|
11224
|
-
this.handleRepoModeKey(info2);
|
|
11225
|
-
return;
|
|
11226
|
-
}
|
|
11227
|
-
this.handleFileModeKey(key, info2);
|
|
11228
|
-
}
|
|
11229
|
-
handleRepoModeKey(info2) {
|
|
11230
|
-
switch (info2?.name) {
|
|
11231
|
-
case "up":
|
|
11232
|
-
this.moveRepoCursor(-1);
|
|
11233
|
-
return;
|
|
11234
|
-
case "down":
|
|
11235
|
-
this.moveRepoCursor(1);
|
|
11236
|
-
return;
|
|
11237
|
-
case "right":
|
|
11238
|
-
this.enterRepository();
|
|
11239
|
-
return;
|
|
11240
|
-
case "space":
|
|
11241
|
-
this.toggleCurrentRepository();
|
|
11242
|
-
return;
|
|
11243
|
-
case "return":
|
|
11244
|
-
this.state = "submit";
|
|
11245
|
-
return;
|
|
11246
|
-
case "left":
|
|
11247
|
-
return;
|
|
11248
|
-
case "escape":
|
|
11249
|
-
this.state = "cancel";
|
|
11250
|
-
return;
|
|
11251
|
-
default:
|
|
11252
|
-
return;
|
|
11253
|
-
}
|
|
11254
|
-
}
|
|
11255
|
-
handleFileModeKey(key, info2) {
|
|
11256
|
-
switch (info2?.name) {
|
|
11257
|
-
case "up":
|
|
11258
|
-
this.moveFileCursor(-1);
|
|
11259
|
-
return;
|
|
11260
|
-
case "down":
|
|
11261
|
-
this.moveFileCursor(1);
|
|
11262
|
-
return;
|
|
11263
|
-
case "left":
|
|
11264
|
-
this.leaveRepository();
|
|
11265
|
-
return;
|
|
11266
|
-
case "space":
|
|
11267
|
-
this.toggleCurrentFile();
|
|
11268
|
-
return;
|
|
11269
|
-
case "backspace":
|
|
11270
|
-
this.searchQuery = this.searchQuery.slice(0, -1);
|
|
11271
|
-
this.searchActive = this.searchQuery.length > 0;
|
|
11272
|
-
this.resetFileCursor();
|
|
11273
|
-
return;
|
|
11274
|
-
case "return":
|
|
11275
|
-
this.leaveRepository();
|
|
11276
|
-
return;
|
|
11277
|
-
case "escape":
|
|
11278
|
-
if (this.searchQuery || this.searchActive) {
|
|
11279
|
-
this.searchQuery = "";
|
|
11280
|
-
this.searchActive = false;
|
|
11281
|
-
this.resetFileCursor();
|
|
11282
|
-
return;
|
|
11283
|
-
}
|
|
11284
|
-
this.state = "cancel";
|
|
11285
|
-
return;
|
|
11286
|
-
default:
|
|
11287
|
-
break;
|
|
11288
|
-
}
|
|
11289
|
-
if (!key)
|
|
11290
|
-
return;
|
|
11291
|
-
if (key === "/") {
|
|
11292
|
-
this.searchActive = true;
|
|
11293
|
-
return;
|
|
11294
|
-
}
|
|
11295
|
-
if (key === "a" && !this.searchActive && this.searchQuery.length === 0) {
|
|
11296
|
-
this.toggleAllVisibleFiles();
|
|
11297
|
-
return;
|
|
11298
|
-
}
|
|
11299
|
-
if (!isPrintableKey(key))
|
|
11300
|
-
return;
|
|
11301
|
-
this.searchActive = true;
|
|
11302
|
-
this.searchQuery += key;
|
|
11303
|
-
this.resetFileCursor();
|
|
11304
|
-
}
|
|
11305
|
-
get currentRepository() {
|
|
11306
|
-
return this.repositories[this.repoCursor];
|
|
11307
|
-
}
|
|
11308
|
-
get filteredFiles() {
|
|
11309
|
-
const files = this.currentRepository?.files ?? [];
|
|
11310
|
-
const query = this.searchQuery.trim().toLowerCase();
|
|
11311
|
-
if (!query)
|
|
11312
|
-
return files;
|
|
11313
|
-
return files.filter((file) => file.path.toLowerCase().includes(query));
|
|
11314
|
-
}
|
|
11315
|
-
syncValue() {
|
|
11316
|
-
this.value = Array.from(this.selectedIds);
|
|
11317
|
-
}
|
|
11318
|
-
moveRepoCursor(delta) {
|
|
11319
|
-
if (this.repositories.length === 0)
|
|
11320
|
-
return;
|
|
11321
|
-
this.repoCursor = wrapIndex(this.repoCursor + delta, this.repositories.length);
|
|
11322
|
-
}
|
|
11323
|
-
moveFileCursor(delta) {
|
|
11324
|
-
if (this.filteredFiles.length === 0)
|
|
11325
|
-
return;
|
|
11326
|
-
this.fileCursor = wrapIndex(this.fileCursor + delta, this.filteredFiles.length);
|
|
11327
|
-
}
|
|
11328
|
-
enterRepository() {
|
|
11329
|
-
if (!this.currentRepository)
|
|
11330
|
-
return;
|
|
11331
|
-
this.mode = "files";
|
|
11332
|
-
this.searchQuery = "";
|
|
11333
|
-
this.searchActive = false;
|
|
11334
|
-
this.resetFileCursor();
|
|
11335
|
-
}
|
|
11336
|
-
leaveRepository() {
|
|
11337
|
-
this.mode = "repos";
|
|
11338
|
-
this.searchQuery = "";
|
|
11339
|
-
this.searchActive = false;
|
|
11340
|
-
this.fileCursor = 0;
|
|
11341
|
-
}
|
|
11342
|
-
resetFileCursor() {
|
|
11343
|
-
this.fileCursor = 0;
|
|
11344
|
-
}
|
|
11345
|
-
toggleCurrentRepository() {
|
|
11346
|
-
const repo = this.currentRepository;
|
|
11347
|
-
if (!repo)
|
|
11348
|
-
return;
|
|
11349
|
-
const selectableIds = getSelectableFileIds(repo.files);
|
|
11350
|
-
if (selectableIds.length === 0)
|
|
11351
|
-
return;
|
|
11352
|
-
const allSelected = selectableIds.every((id) => this.selectedIds.has(id));
|
|
11353
|
-
if (allSelected) {
|
|
11354
|
-
for (const id of selectableIds) {
|
|
11355
|
-
this.selectedIds.delete(id);
|
|
11356
|
-
}
|
|
11357
|
-
return;
|
|
11358
|
-
}
|
|
11359
|
-
for (const id of selectableIds) {
|
|
11360
|
-
this.selectedIds.add(id);
|
|
11361
|
-
}
|
|
11362
|
-
}
|
|
11363
|
-
toggleCurrentFile() {
|
|
11364
|
-
const file = this.filteredFiles[this.fileCursor];
|
|
11365
|
-
if (!file || file.is_synced)
|
|
11366
|
-
return;
|
|
11367
|
-
if (this.selectedIds.has(file.id)) {
|
|
11368
|
-
this.selectedIds.delete(file.id);
|
|
11369
|
-
return;
|
|
11370
|
-
}
|
|
11371
|
-
this.selectedIds.add(file.id);
|
|
11372
|
-
}
|
|
11373
|
-
toggleAllVisibleFiles() {
|
|
11374
|
-
const selectableIds = getSelectableFileIds(this.filteredFiles);
|
|
11375
|
-
if (selectableIds.length === 0)
|
|
11376
|
-
return;
|
|
11377
|
-
const allSelected = selectableIds.every((id) => this.selectedIds.has(id));
|
|
11378
|
-
if (allSelected) {
|
|
11379
|
-
for (const id of selectableIds) {
|
|
11380
|
-
this.selectedIds.delete(id);
|
|
11381
|
-
}
|
|
11382
|
-
return;
|
|
11383
|
-
}
|
|
11384
|
-
for (const id of selectableIds) {
|
|
11385
|
-
this.selectedIds.add(id);
|
|
11386
|
-
}
|
|
11387
|
-
}
|
|
11388
|
-
getRepositorySelectionState(repo) {
|
|
11389
|
-
const selectableIds = getSelectableFileIds(repo.files);
|
|
11390
|
-
if (selectableIds.length === 0)
|
|
11391
|
-
return "locked";
|
|
11392
|
-
let selectedCount = 0;
|
|
11393
|
-
for (const id of selectableIds) {
|
|
11394
|
-
if (this.selectedIds.has(id))
|
|
11395
|
-
selectedCount += 1;
|
|
11396
|
-
}
|
|
11397
|
-
if (selectedCount === 0)
|
|
11398
|
-
return "none";
|
|
11399
|
-
if (selectedCount === selectableIds.length)
|
|
11400
|
-
return "all";
|
|
11401
|
-
return "partial";
|
|
11402
|
-
}
|
|
11403
|
-
renderPrompt() {
|
|
11404
|
-
const promptSymbol = this.state === "submit" ? import_picocolors14.default.green(SUBMIT_SYMBOL) : this.state === "cancel" ? import_picocolors14.default.red(CANCEL_SYMBOL2) : import_picocolors14.default.cyan(ACTIVE_SYMBOL);
|
|
11405
|
-
const title = this.mode === "repos" ? "Select docs to import" : this.currentRepository?.slug ?? "Files";
|
|
11406
|
-
const header = `${import_picocolors14.default.gray(BAR)}
|
|
11407
|
-
${promptSymbol} ${title}
|
|
11408
|
-
`;
|
|
11409
|
-
if (this.state === "submit") {
|
|
11410
|
-
return `${header}${import_picocolors14.default.gray(BAR)} ${import_picocolors14.default.dim(this.submitLabel())}`;
|
|
11411
|
-
}
|
|
11412
|
-
if (this.state === "cancel") {
|
|
11413
|
-
return `${header}${import_picocolors14.default.gray(BAR)}`;
|
|
11414
|
-
}
|
|
11415
|
-
return this.mode === "repos" ? this.renderRepositoryMode(header) : this.renderFileMode(header);
|
|
11416
|
-
}
|
|
11417
|
-
renderRepositoryMode(header) {
|
|
11418
|
-
const help = `${import_picocolors14.default.gray(BAR)} ${import_picocolors14.default.dim("space: import all docs in a repo →: browse repo docs Enter: confirm")}`;
|
|
11419
|
-
const body = visibleOptions2(this.repoCursor, this.repositories.length).map((option) => {
|
|
11420
|
-
if (option.kind === "ellipsis") {
|
|
11421
|
-
return `${import_picocolors14.default.gray(BAR)} ${import_picocolors14.default.dim(ELLIPSIS)}`;
|
|
11422
|
-
}
|
|
11423
|
-
const repo = this.repositories[option.index];
|
|
11424
|
-
const isActive = option.index === this.repoCursor;
|
|
11425
|
-
const state = this.getRepositorySelectionState(repo);
|
|
11426
|
-
const marker = this.renderRepositoryMarker(state, isActive);
|
|
11427
|
-
const label = isActive ? import_picocolors14.default.cyan(repo.slug) : repo.slug;
|
|
11428
|
-
const hint = state === "locked" ? ` ${import_picocolors14.default.dim("(All docs already imported)")}` : "";
|
|
11429
|
-
return `${import_picocolors14.default.gray(BAR)} ${marker} ${label}${hint}`;
|
|
11430
|
-
});
|
|
11431
|
-
return `${header}${help}
|
|
11432
|
-
${import_picocolors14.default.gray(BAR)}
|
|
11433
|
-
${body.join(`
|
|
11434
|
-
`)}
|
|
11435
|
-
${import_picocolors14.default.cyan(FOOTER)}`;
|
|
11436
|
-
}
|
|
11437
|
-
renderFileMode(header) {
|
|
11438
|
-
const back = `${import_picocolors14.default.gray(BAR)} ${import_picocolors14.default.dim("←: back / Enter")}`;
|
|
11439
|
-
const searchValue = this.searchQuery || import_picocolors14.default.dim(this.searchActive ? "" : "type to filter");
|
|
11440
|
-
const search = `${import_picocolors14.default.gray(BAR)} Search: ${searchValue}`;
|
|
11441
|
-
const help = `${import_picocolors14.default.gray(BAR)} ${import_picocolors14.default.dim("space: toggle doc type: search a: select all visible ←: back / Enter")}`;
|
|
11442
|
-
const body = visibleOptions2(this.fileCursor, this.filteredFiles.length, MAX_VISIBLE_FILE_ITEMS).map((option) => {
|
|
11443
|
-
if (option.kind === "ellipsis") {
|
|
11444
|
-
return `${import_picocolors14.default.gray(BAR)} ${import_picocolors14.default.dim(ELLIPSIS)}`;
|
|
11445
|
-
}
|
|
11446
|
-
const file = this.filteredFiles[option.index];
|
|
11447
|
-
const isActive = option.index === this.fileCursor;
|
|
11448
|
-
const isSelected = this.selectedIds.has(file.id);
|
|
11449
|
-
const marker = file.is_synced ? isActive ? import_picocolors14.default.cyan(CHECKBOX_OFF) : import_picocolors14.default.dim(CHECKBOX_OFF) : isSelected ? isActive ? import_picocolors14.default.cyan(CHECKBOX_ON) : CHECKBOX_ON : isActive ? import_picocolors14.default.cyan(CHECKBOX_OFF) : CHECKBOX_OFF;
|
|
11450
|
-
const label = file.is_synced ? isActive ? import_picocolors14.default.cyan(file.path) : import_picocolors14.default.dim(file.path) : isActive ? import_picocolors14.default.cyan(file.path) : file.path;
|
|
11451
|
-
const hint = file.is_synced ? ` ${import_picocolors14.default.dim("(Already imported)")}` : "";
|
|
11452
|
-
return `${import_picocolors14.default.gray(BAR)} ${marker} ${label}${hint}`;
|
|
11453
|
-
});
|
|
11454
|
-
const content = body.length > 0 ? body.join(`
|
|
11455
|
-
`) : `${import_picocolors14.default.gray(BAR)} ${import_picocolors14.default.dim("No docs match your search.")}`;
|
|
11456
|
-
return `${header}${back}
|
|
11457
|
-
${import_picocolors14.default.gray(BAR)}
|
|
11458
|
-
${search}
|
|
11459
|
-
${import_picocolors14.default.gray(BAR)}
|
|
11460
|
-
${content}
|
|
11461
|
-
${import_picocolors14.default.gray(BAR)}
|
|
11462
|
-
${help}
|
|
11463
|
-
${import_picocolors14.default.cyan(FOOTER)}`;
|
|
11464
|
-
}
|
|
11465
|
-
renderRepositoryMarker(state, isActive) {
|
|
11466
|
-
if (state === "all") {
|
|
11467
|
-
return isActive ? import_picocolors14.default.cyan(CHECKBOX_ON) : CHECKBOX_ON;
|
|
11468
|
-
}
|
|
11469
|
-
if (state === "partial") {
|
|
11470
|
-
return isActive ? import_picocolors14.default.cyan(CHECKBOX_PARTIAL) : CHECKBOX_PARTIAL;
|
|
11471
|
-
}
|
|
11472
|
-
if (state === "locked") {
|
|
11473
|
-
return isActive ? import_picocolors14.default.cyan(CHECKBOX_OFF) : import_picocolors14.default.dim(CHECKBOX_OFF);
|
|
11474
|
-
}
|
|
11475
|
-
return isActive ? import_picocolors14.default.cyan(CHECKBOX_OFF) : CHECKBOX_OFF;
|
|
11476
|
-
}
|
|
11477
|
-
submitLabel() {
|
|
11478
|
-
const count = this.selectedIds.size;
|
|
11479
|
-
if (count === 0) {
|
|
11480
|
-
return "Skip for now";
|
|
11481
|
-
}
|
|
11482
|
-
return `${count} doc${count === 1 ? "" : "s"} selected`;
|
|
11483
|
-
}
|
|
11484
|
-
};
|
|
11485
|
-
});
|
|
11486
|
-
|
|
11487
|
-
// src/setup/github-doc-import-step.ts
|
|
11488
|
-
var exports_github_doc_import_step = {};
|
|
11489
|
-
__export(exports_github_doc_import_step, {
|
|
11490
|
-
stepImportGitHubDocs: () => stepImportGitHubDocs
|
|
11491
|
-
});
|
|
11492
|
-
async function stepImportGitHubDocs(cfg, opts = {}) {
|
|
11493
|
-
logger.info("setup", "Step: import GitHub docs");
|
|
11494
|
-
if (!cfg.org_id || !cfg.space_id) {
|
|
11495
|
-
log.warn("Cannot import GitHub docs: your Dosu workspace is missing org/space context. " + "Re-run `dosu setup` from a fresh state.");
|
|
11496
|
-
return { advance: false };
|
|
11497
|
-
}
|
|
11498
|
-
const trpc = createTypedClient(cfg);
|
|
11499
|
-
const files = opts.waitForFreshDocs ? await waitForImportableGithubFiles(trpc, cfg.org_id, cfg.space_id, opts.expectedDataSourceIds) : await fetchImportableGithubFiles(trpc, cfg.space_id);
|
|
11500
|
-
if (files === null) {
|
|
11501
|
-
return { advance: false };
|
|
11502
|
-
}
|
|
11503
|
-
if (files.length === 0) {
|
|
11504
|
-
log.info("No markdown docs available to import right now. You can import them later.");
|
|
11505
|
-
return { advance: true, imported: false, imported_count: 0 };
|
|
11506
|
-
}
|
|
11507
|
-
const repositories = buildRepositories(files);
|
|
11508
|
-
const selected = await promptGitHubDocsImport({ repositories });
|
|
11509
|
-
if (isCancel(selected)) {
|
|
11510
|
-
logger.info("setup", "GitHub doc import selection cancelled");
|
|
11511
|
-
return { advance: false };
|
|
11512
|
-
}
|
|
11513
|
-
const fileIDs = selected;
|
|
11514
|
-
if (fileIDs.length === 0) {
|
|
11515
|
-
log.info("Skipped importing docs for now. You can import them later.");
|
|
11516
|
-
return { advance: true, imported: false, imported_count: 0 };
|
|
11517
|
-
}
|
|
11518
|
-
const knowledgeStoreID = await getKnowledgeStoreID(trpc, cfg.space_id);
|
|
11519
|
-
if (!knowledgeStoreID) {
|
|
11520
|
-
return { advance: false };
|
|
11521
|
-
}
|
|
11522
|
-
const spinner2 = spinner();
|
|
11523
|
-
spinner2.start(`Queueing import for ${fileIDs.length} doc${fileIDs.length === 1 ? "" : "s"}...`);
|
|
11524
|
-
try {
|
|
11525
|
-
const result = await trpc.docImports.importGithubFiles.mutate({
|
|
11526
|
-
knowledge_store_id: knowledgeStoreID,
|
|
11527
|
-
space_id: cfg.space_id,
|
|
11528
|
-
file_ids: fileIDs
|
|
11529
|
-
});
|
|
11530
|
-
const taskID = result?.task_id;
|
|
11531
|
-
if (!taskID) {
|
|
11532
|
-
spinner2.stop("Import task started");
|
|
11533
|
-
log.success("Import task started.");
|
|
11534
|
-
log.info("Your docs should finish importing in a few minutes.");
|
|
11535
|
-
return { advance: true, imported: false, imported_count: 0, queued: true };
|
|
11536
|
-
}
|
|
11537
|
-
spinner2.stop("Import task started");
|
|
11538
|
-
logger.info("setup", `Watching import task ${taskID}`);
|
|
11539
|
-
log.info("This can take a few minutes. We'll keep watching until it finishes.");
|
|
11540
|
-
const progressSpinner = spinner();
|
|
11541
|
-
progressSpinner.start(`Preparing document import... 0/${fileIDs.length} complete`);
|
|
11542
|
-
const finalStatus = await waitForImportTaskCompletion(trpc, taskID, progressSpinner, fileIDs.length);
|
|
11543
|
-
if (!finalStatus) {
|
|
11544
|
-
progressSpinner.stop("Stopped watching import progress");
|
|
11545
|
-
log.info(`The import is still running in the background.
|
|
11546
|
-
Check status later with: dosu docs import-status ${taskID}`);
|
|
11547
|
-
return {
|
|
11548
|
-
advance: true,
|
|
11549
|
-
imported: false,
|
|
11550
|
-
imported_count: 0,
|
|
11551
|
-
queued: true,
|
|
11552
|
-
task_id: taskID
|
|
11553
|
-
};
|
|
11554
|
-
}
|
|
11555
|
-
handleImportCompletion(finalStatus, progressSpinner);
|
|
11556
|
-
const importedCount = finalStatus.detail?.completed ?? 0;
|
|
11557
|
-
return {
|
|
11558
|
-
advance: true,
|
|
11559
|
-
imported: importedCount > 0,
|
|
11560
|
-
imported_count: importedCount,
|
|
11561
|
-
failed_count: finalStatus.detail?.failed ?? 0,
|
|
11562
|
-
task_id: taskID
|
|
11563
|
-
};
|
|
11564
|
-
} catch (err) {
|
|
11565
|
-
spinner2.stop("Failed");
|
|
11566
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
11567
|
-
logger.error("setup", `Failed to import GitHub docs: ${msg}`);
|
|
11568
|
-
log.error("Could not start the GitHub doc import.");
|
|
11569
|
-
return { advance: false };
|
|
11570
|
-
}
|
|
11571
|
-
}
|
|
11572
|
-
async function waitForImportTaskCompletion(trpc, taskID, spinner2, expectedTotal) {
|
|
11573
|
-
let consecutiveErrors = 0;
|
|
11574
|
-
while (true) {
|
|
11575
|
-
try {
|
|
11576
|
-
const status = await trpc.docImports.getImportStatus.query(taskID);
|
|
11577
|
-
if (!status) {
|
|
11578
|
-
consecutiveErrors += 1;
|
|
11579
|
-
if (consecutiveErrors >= IMPORT_STATUS_MAX_ERRORS) {
|
|
11580
|
-
return null;
|
|
11581
|
-
}
|
|
11582
|
-
} else {
|
|
11583
|
-
consecutiveErrors = 0;
|
|
11584
|
-
spinner2.message(buildImportProgressMessage(status, expectedTotal));
|
|
11585
|
-
if (status.state !== "PROGRESS") {
|
|
11586
|
-
return status;
|
|
11587
|
-
}
|
|
11588
|
-
}
|
|
11589
|
-
} catch (err) {
|
|
11590
|
-
consecutiveErrors += 1;
|
|
11591
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
11592
|
-
logger.warn("setup", `getImportStatus failed for ${taskID}: ${msg}`);
|
|
11593
|
-
if (consecutiveErrors >= IMPORT_STATUS_MAX_ERRORS) {
|
|
11594
|
-
return null;
|
|
11595
|
-
}
|
|
11596
|
-
}
|
|
11597
|
-
await sleep5(IMPORT_STATUS_POLL_INTERVAL_MS);
|
|
11598
|
-
}
|
|
11599
|
-
}
|
|
11600
|
-
function buildImportProgressMessage(status, expectedTotal) {
|
|
11601
|
-
const detail = status.detail;
|
|
11602
|
-
if (!detail) {
|
|
11603
|
-
return `Importing documents... 0/${expectedTotal} complete`;
|
|
11604
|
-
}
|
|
11605
|
-
const processed = detail.completed + detail.failed;
|
|
11606
|
-
const total = detail.total > 0 ? detail.total : expectedTotal;
|
|
11607
|
-
if (status.state === "SUCCESS") {
|
|
11608
|
-
return `Import complete (${processed}/${total})`;
|
|
11609
|
-
}
|
|
11610
|
-
if (status.state === "FAILURE") {
|
|
11611
|
-
return `Import finished with issues (${processed}/${total}, ${detail.failed} failed)`;
|
|
11612
|
-
}
|
|
11613
|
-
const prefix = detail.message === "STARTING" ? "Preparing document import" : "Importing documents";
|
|
11614
|
-
const failureSuffix = detail.failed > 0 ? `, ${detail.failed} failed` : "";
|
|
11615
|
-
return `${prefix}... ${processed}/${total} complete${failureSuffix}`;
|
|
11616
|
-
}
|
|
11617
|
-
function handleImportCompletion(status, spinner2) {
|
|
11618
|
-
const detail = status.detail;
|
|
11619
|
-
const processed = detail ? detail.completed + detail.failed : 0;
|
|
11620
|
-
const total = detail?.total ?? processed;
|
|
11621
|
-
const failed = detail?.failed ?? 0;
|
|
11622
|
-
if (status.state === "SUCCESS") {
|
|
11623
|
-
spinner2.stop("Import complete");
|
|
11624
|
-
log.success(`Imported ${total} doc${total === 1 ? "" : "s"}.
|
|
11625
|
-
Your GitHub docs are ready, and onboarding is complete.`);
|
|
11626
|
-
return;
|
|
11627
|
-
}
|
|
11628
|
-
spinner2.stop("Import completed with issues");
|
|
11629
|
-
log.warn(`Imported ${processed - failed} of ${total} doc${total === 1 ? "" : "s"}; ${failed} failed.
|
|
11630
|
-
You can review the failed docs later, but onboarding is complete.`);
|
|
11631
|
-
}
|
|
11632
|
-
async function waitForImportableGithubFiles(trpc, orgID, spaceID, expectedDataSourceIds) {
|
|
11633
|
-
while (true) {
|
|
11634
|
-
const spinner2 = spinner();
|
|
11635
|
-
spinner2.start("Scanning repositories for markdown documents...");
|
|
11636
|
-
log.info("This usually takes a few seconds.");
|
|
11637
|
-
const startedAt = Date.now();
|
|
11638
|
-
let latestFiles = [];
|
|
11639
|
-
const waitsForExpectedDataSources = expectedDataSourceIds !== undefined && expectedDataSourceIds.length > 0;
|
|
11640
|
-
while (Date.now() - startedAt < DOC_SCAN_POLL_TIMEOUT_MS) {
|
|
11641
|
-
const dataSources = await fetchGitHubDataSources(trpc, orgID);
|
|
11642
|
-
if (waitsForExpectedDataSources) {
|
|
11643
|
-
if (isScanComplete(dataSources, expectedDataSourceIds)) {
|
|
11644
|
-
latestFiles = await fetchImportableGithubFiles(trpc, spaceID);
|
|
11645
|
-
spinner2.stop(latestFiles.length > 0 ? "Docs ready" : "No markdown docs found");
|
|
11646
|
-
return latestFiles;
|
|
11647
|
-
}
|
|
11648
|
-
await sleep5(DOC_SCAN_POLL_INTERVAL_MS);
|
|
11649
|
-
continue;
|
|
11650
|
-
}
|
|
11651
|
-
latestFiles = await fetchImportableGithubFiles(trpc, spaceID);
|
|
11652
|
-
if (latestFiles.length > 0) {
|
|
11653
|
-
spinner2.stop("Docs ready");
|
|
11654
|
-
return latestFiles;
|
|
11655
|
-
}
|
|
11656
|
-
if (isScanComplete(dataSources, expectedDataSourceIds)) {
|
|
11657
|
-
spinner2.stop("No markdown docs found");
|
|
11658
|
-
return [];
|
|
11659
|
-
}
|
|
11660
|
-
await sleep5(DOC_SCAN_POLL_INTERVAL_MS);
|
|
11661
|
-
}
|
|
11662
|
-
spinner2.stop("Timed out");
|
|
11663
|
-
const choice = await select({
|
|
11664
|
-
message: "Still waiting for GitHub docs to become available",
|
|
11665
|
-
options: [
|
|
11666
|
-
{ value: "retry", label: "Retry" },
|
|
11667
|
-
{ value: "skip", label: "Skip for now" }
|
|
11668
|
-
]
|
|
11669
|
-
});
|
|
11670
|
-
if (isCancel(choice)) {
|
|
11671
|
-
return null;
|
|
11672
|
-
}
|
|
11673
|
-
if (choice === "skip") {
|
|
11674
|
-
log.info("Skipped importing docs for now. You can import them later.");
|
|
11675
|
-
return [];
|
|
11676
|
-
}
|
|
11677
|
-
}
|
|
11678
|
-
}
|
|
11679
|
-
function isScanComplete(dataSources, expectedDataSourceIds) {
|
|
11680
|
-
if (expectedDataSourceIds && expectedDataSourceIds.length > 0) {
|
|
11681
|
-
const byId = new Map;
|
|
11682
|
-
for (const ds of dataSources) {
|
|
11683
|
-
if (ds.data_source_id)
|
|
11684
|
-
byId.set(ds.data_source_id, ds);
|
|
11685
|
-
}
|
|
11686
|
-
for (const id of expectedDataSourceIds) {
|
|
11687
|
-
const ds = byId.get(id);
|
|
11688
|
-
if (!ds)
|
|
11689
|
-
continue;
|
|
11690
|
-
if (ds.is_indexed !== true)
|
|
11691
|
-
return false;
|
|
11692
|
-
}
|
|
11693
|
-
return true;
|
|
11694
|
-
}
|
|
11695
|
-
return dataSources.length > 0 && dataSources.every((ds) => ds.is_indexed === true);
|
|
11696
|
-
}
|
|
11697
|
-
async function fetchGitHubDataSources(trpc, orgID) {
|
|
11698
|
-
try {
|
|
11699
|
-
const dataSources = await trpc.dataSource.list.query({
|
|
11700
|
-
org_id: orgID,
|
|
11701
|
-
excluded_provider_slugs: []
|
|
11702
|
-
});
|
|
11703
|
-
return dataSources.filter((dataSource) => dataSource.provider_slug === "github");
|
|
11704
|
-
} catch (err) {
|
|
11705
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
11706
|
-
logger.warn("setup", `dataSource.list failed while waiting for docs: ${msg}`);
|
|
11707
|
-
return [];
|
|
11708
|
-
}
|
|
11709
|
-
}
|
|
11710
|
-
async function fetchImportableGithubFiles(trpc, spaceID) {
|
|
11711
|
-
try {
|
|
11712
|
-
return await trpc.docImports.listImportableGithubFiles.query(spaceID);
|
|
11713
|
-
} catch (err) {
|
|
11714
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
11715
|
-
logger.warn("setup", `listImportableGithubFiles failed: ${msg}`);
|
|
11716
|
-
return [];
|
|
11717
|
-
}
|
|
11718
|
-
}
|
|
11719
|
-
function buildRepositories(files) {
|
|
11720
|
-
const repositories = new Map;
|
|
11721
|
-
for (const file of files) {
|
|
11722
|
-
const slug = file.repository_slug ?? "unknown";
|
|
11723
|
-
if (!repositories.has(slug)) {
|
|
11724
|
-
repositories.set(slug, { slug, files: [] });
|
|
11725
|
-
}
|
|
11726
|
-
repositories.get(slug)?.files.push({
|
|
11727
|
-
id: file.id,
|
|
11728
|
-
path: file.file_path,
|
|
11729
|
-
is_synced: file.is_synced
|
|
11730
|
-
});
|
|
11731
|
-
}
|
|
11732
|
-
return Array.from(repositories.values()).map((repository) => ({
|
|
11733
|
-
...repository,
|
|
11734
|
-
files: [...repository.files].sort((a3, b2) => a3.path.localeCompare(b2.path))
|
|
11735
|
-
})).sort((a3, b2) => a3.slug.localeCompare(b2.slug));
|
|
11736
|
-
}
|
|
11737
|
-
async function getKnowledgeStoreID(trpc, spaceID) {
|
|
11738
|
-
try {
|
|
11739
|
-
const store = await trpc.knowledgeStore.getBySpaceId.query({
|
|
11740
|
-
space_id: spaceID
|
|
11741
|
-
});
|
|
11742
|
-
if (!store?.id) {
|
|
11743
|
-
log.error("No knowledge store found for this deployment.");
|
|
11744
|
-
return null;
|
|
11745
|
-
}
|
|
11746
|
-
return store.id;
|
|
11747
|
-
} catch (err) {
|
|
11748
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
11749
|
-
logger.error("setup", `knowledgeStore.getBySpaceId failed: ${msg}`);
|
|
11750
|
-
log.error("Could not load the knowledge store for this deployment.");
|
|
11751
|
-
return null;
|
|
11752
|
-
}
|
|
11753
|
-
}
|
|
11754
|
-
function sleep5(ms) {
|
|
11755
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
11756
|
-
}
|
|
11757
|
-
var DOC_SCAN_POLL_INTERVAL_MS = 2000, DOC_SCAN_POLL_TIMEOUT_MS = 60000, IMPORT_STATUS_POLL_INTERVAL_MS = 2000, IMPORT_STATUS_MAX_ERRORS = 3;
|
|
11758
|
-
var init_github_doc_import_step = __esm(() => {
|
|
11759
|
-
init_dist8();
|
|
11760
|
-
init_trpc();
|
|
11761
|
-
init_logger();
|
|
11762
|
-
init_github_doc_import_prompt();
|
|
11763
|
-
});
|
|
11764
|
-
|
|
11765
11137
|
// src/auth/errors.ts
|
|
11766
11138
|
var exports_errors = {};
|
|
11767
11139
|
__export(exports_errors, {
|
|
@@ -11841,14 +11213,53 @@ code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; background:
|
|
|
11841
11213
|
</body>
|
|
11842
11214
|
</html>`;
|
|
11843
11215
|
}
|
|
11844
|
-
function
|
|
11216
|
+
function buildNextPollScript(settleMsg) {
|
|
11217
|
+
return `<script>
|
|
11218
|
+
(function () {
|
|
11219
|
+
var tries = 0;
|
|
11220
|
+
var misses = 0;
|
|
11221
|
+
var setCopy = function (heading, msg) {
|
|
11222
|
+
var h = document.getElementById('heading');
|
|
11223
|
+
var m = document.getElementById('close-msg');
|
|
11224
|
+
if (h && heading) h.textContent = heading;
|
|
11225
|
+
if (m && msg) m.textContent = msg;
|
|
11226
|
+
};
|
|
11227
|
+
var settle = function () { setCopy(null, ${JSON.stringify(settleMsg)}); };
|
|
11228
|
+
var timer = setInterval(function () {
|
|
11229
|
+
tries += 1;
|
|
11230
|
+
if (tries > 720) { clearInterval(timer); settle(); return; }
|
|
11231
|
+
fetch('/next').then(function (res) {
|
|
11232
|
+
misses = 0;
|
|
11233
|
+
if (res.status === 200) {
|
|
11234
|
+
clearInterval(timer);
|
|
11235
|
+
res.json().then(function (body) {
|
|
11236
|
+
if (body && body.url) {
|
|
11237
|
+
setCopy("You're ready to connect your data sources", 'Redirecting...');
|
|
11238
|
+
window.location.replace(body.url);
|
|
11239
|
+
}
|
|
11240
|
+
});
|
|
11241
|
+
} else if (res.status === 410) {
|
|
11242
|
+
clearInterval(timer);
|
|
11243
|
+
settle();
|
|
11244
|
+
}
|
|
11245
|
+
}).catch(function () {
|
|
11246
|
+
misses += 1;
|
|
11247
|
+
if (misses >= 8) { clearInterval(timer); settle(); }
|
|
11248
|
+
});
|
|
11249
|
+
}, 250);
|
|
11250
|
+
})();
|
|
11251
|
+
</script>`;
|
|
11252
|
+
}
|
|
11253
|
+
function buildSuccessHtml(email, variant = "auth", withNextPoll = false) {
|
|
11254
|
+
const copy2 = SUCCESS_COPY[variant];
|
|
11255
|
+
const closeMsg = withNextPoll ? "Hang tight — this tab will continue automatically." : copy2.close;
|
|
11845
11256
|
const emailLine = email ? `<p class="email">Signed in as <strong>${email.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")}</strong></p>` : "";
|
|
11846
11257
|
return `<!DOCTYPE html>
|
|
11847
11258
|
<html lang="en">
|
|
11848
11259
|
<head>
|
|
11849
11260
|
<meta charset="UTF-8">
|
|
11850
11261
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
11851
|
-
<title
|
|
11262
|
+
<title>${copy2.title}</title>
|
|
11852
11263
|
<style>
|
|
11853
11264
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
11854
11265
|
body {
|
|
@@ -11950,31 +11361,47 @@ h1 {
|
|
|
11950
11361
|
<path d="M0.348633 85.4946C0.348633 85.4946 29.4856 85.8309 34.809 85.698C44.8337 85.4477 51.2872 84.402 57.5269 78.9724C62.8129 74.3727 75.1342 59.6836 75.1342 59.6836" stroke="black" stroke-width="6.16482"/>
|
|
11951
11362
|
</svg>
|
|
11952
11363
|
</div>
|
|
11953
|
-
<h1
|
|
11364
|
+
<h1 id="heading">${copy2.heading}</h1>
|
|
11954
11365
|
${emailLine}
|
|
11955
|
-
<p class="close-msg"
|
|
11366
|
+
<p class="close-msg" id="close-msg">${closeMsg}</p>
|
|
11956
11367
|
</div>
|
|
11957
11368
|
<div class="tip">
|
|
11958
11369
|
<div class="tip-rule" aria-hidden="true"><span class="tip-dot"></span></div>
|
|
11959
11370
|
<span class="tip-label">Did you know?</span>
|
|
11960
11371
|
You can use Dosu to make your coding agents faster and cheaper. Just ask your agent to use Dosu to update your AGENTS.md.
|
|
11961
11372
|
</div>
|
|
11373
|
+
${withNextPoll ? buildNextPollScript(copy2.close) : ""}
|
|
11962
11374
|
</body>
|
|
11963
11375
|
</html>`;
|
|
11964
11376
|
}
|
|
11965
|
-
async function startCallbackServer() {
|
|
11377
|
+
async function startCallbackServer(opts = {}) {
|
|
11966
11378
|
let resolveToken;
|
|
11967
11379
|
let rejectToken;
|
|
11968
11380
|
const tokenPromise = new Promise((resolve, reject) => {
|
|
11969
11381
|
resolveToken = resolve;
|
|
11970
11382
|
rejectToken = reject;
|
|
11971
11383
|
});
|
|
11384
|
+
let nextTarget;
|
|
11972
11385
|
const http = __require("node:http");
|
|
11973
11386
|
const httpServer = http.createServer((req, res) => {
|
|
11974
11387
|
const url = new URL(req.url ?? "/", `http://localhost`);
|
|
11975
11388
|
const cookieLen = (req.headers.cookie ?? "").length;
|
|
11976
11389
|
const ua = req.headers["user-agent"] ?? "none";
|
|
11977
11390
|
logger.debug("auth.server", `Request: ${req.method} ${url.pathname} cookie-len=${cookieLen} ua=${ua} has-token=${url.searchParams.has("access_token")}`);
|
|
11391
|
+
if (opts.nextHold && url.pathname === "/next") {
|
|
11392
|
+
if (nextTarget === undefined) {
|
|
11393
|
+
res.writeHead(204);
|
|
11394
|
+
res.end();
|
|
11395
|
+
} else if (nextTarget === null) {
|
|
11396
|
+
res.writeHead(410);
|
|
11397
|
+
res.end();
|
|
11398
|
+
} else {
|
|
11399
|
+
logger.info("auth.server", "Handing tab onward via /next");
|
|
11400
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
11401
|
+
res.end(JSON.stringify({ url: nextTarget }));
|
|
11402
|
+
}
|
|
11403
|
+
return;
|
|
11404
|
+
}
|
|
11978
11405
|
if (url.pathname !== "/callback") {
|
|
11979
11406
|
logger.debug("auth.server", `404: ${url.pathname}`);
|
|
11980
11407
|
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
@@ -12022,17 +11449,24 @@ async function startCallbackServer() {
|
|
|
12022
11449
|
});
|
|
12023
11450
|
logger.info("auth.server", "Served success HTML");
|
|
12024
11451
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
12025
|
-
res.end(buildSuccessHtml(email ?? undefined));
|
|
11452
|
+
res.end(buildSuccessHtml(email ?? undefined, opts.successVariant ?? "auth", Boolean(opts.nextHold)));
|
|
12026
11453
|
});
|
|
12027
11454
|
await new Promise((resolve) => {
|
|
12028
11455
|
httpServer.listen(0, "localhost", () => resolve());
|
|
12029
11456
|
});
|
|
11457
|
+
httpServer.unref();
|
|
12030
11458
|
const addr = httpServer.address();
|
|
12031
11459
|
logger.info("auth.server", `Callback server listening on port ${addr.port}`);
|
|
12032
11460
|
return {
|
|
12033
11461
|
server: {
|
|
12034
11462
|
port: addr.port,
|
|
12035
|
-
close: () =>
|
|
11463
|
+
close: () => {
|
|
11464
|
+
httpServer.close();
|
|
11465
|
+
httpServer.closeAllConnections?.();
|
|
11466
|
+
},
|
|
11467
|
+
setNext: (url) => {
|
|
11468
|
+
nextTarget = url;
|
|
11469
|
+
}
|
|
12036
11470
|
},
|
|
12037
11471
|
tokenPromise
|
|
12038
11472
|
};
|
|
@@ -12101,10 +11535,22 @@ if (hash) {
|
|
|
12101
11535
|
}
|
|
12102
11536
|
</script>
|
|
12103
11537
|
</body>
|
|
12104
|
-
</html
|
|
11538
|
+
</html>`, SUCCESS_COPY;
|
|
12105
11539
|
var init_server = __esm(() => {
|
|
12106
11540
|
init_logger();
|
|
12107
11541
|
init_errors();
|
|
11542
|
+
SUCCESS_COPY = {
|
|
11543
|
+
auth: {
|
|
11544
|
+
title: "Dosu CLI - Authentication Successful",
|
|
11545
|
+
heading: "Authentication Successful",
|
|
11546
|
+
close: "You can close this tab and return to your terminal."
|
|
11547
|
+
},
|
|
11548
|
+
onboarding: {
|
|
11549
|
+
title: "Dosu CLI - Onboarding Complete",
|
|
11550
|
+
heading: "Onboarding Complete",
|
|
11551
|
+
close: "You're all set — return to your terminal, Dosu is finishing your setup there."
|
|
11552
|
+
}
|
|
11553
|
+
};
|
|
12108
11554
|
});
|
|
12109
11555
|
|
|
12110
11556
|
// src/auth/flow.ts
|
|
@@ -12112,24 +11558,35 @@ var exports_flow = {};
|
|
|
12112
11558
|
__export(exports_flow, {
|
|
12113
11559
|
startOAuthFlow: () => startOAuthFlow
|
|
12114
11560
|
});
|
|
12115
|
-
async function startOAuthFlow(signal, path3 = "/cli/auth", params = {}) {
|
|
12116
|
-
const { server, tokenPromise } = await startCallbackServer(
|
|
11561
|
+
async function startOAuthFlow(signal, path3 = "/cli/auth", params = {}, onAuthURL, options = {}) {
|
|
11562
|
+
const { server, tokenPromise } = await startCallbackServer({
|
|
11563
|
+
nextHold: options.holdNext,
|
|
11564
|
+
successVariant: options.successVariant
|
|
11565
|
+
});
|
|
12117
11566
|
let timeoutId;
|
|
11567
|
+
let handedOver = false;
|
|
12118
11568
|
try {
|
|
12119
11569
|
const callbackURL = `http://localhost:${server.port}/callback`;
|
|
12120
11570
|
logger.debug("auth.flow", `Callback URL: ${callbackURL}`);
|
|
12121
11571
|
const authURL = buildAuthURL(callbackURL, path3, params);
|
|
12122
11572
|
logger.info("auth.flow", `Auth URL: ${authURL}`);
|
|
12123
|
-
|
|
11573
|
+
options.onAuthURL?.(authURL);
|
|
12124
11574
|
let browserOpened = false;
|
|
12125
|
-
|
|
12126
|
-
await open2.default(authURL);
|
|
11575
|
+
if (options.suppressBrowserOpen) {
|
|
12127
11576
|
browserOpened = true;
|
|
12128
|
-
logger.info("auth.flow", "Browser open
|
|
12129
|
-
}
|
|
12130
|
-
|
|
11577
|
+
logger.info("auth.flow", "Browser open suppressed — caller steers an existing tab");
|
|
11578
|
+
} else {
|
|
11579
|
+
const open2 = await Promise.resolve().then(() => (init_open(), exports_open));
|
|
11580
|
+
try {
|
|
11581
|
+
await open2.default(authURL);
|
|
11582
|
+
browserOpened = true;
|
|
11583
|
+
logger.info("auth.flow", "Browser open command executed");
|
|
11584
|
+
onAuthURL?.(authURL);
|
|
11585
|
+
} catch (openErr) {
|
|
11586
|
+
logger.warn("auth.flow", `Could not open browser automatically: ${openErr instanceof Error ? openErr.message : String(openErr)}`);
|
|
11587
|
+
}
|
|
12131
11588
|
}
|
|
12132
|
-
if (!browserOpened) {
|
|
11589
|
+
if (!browserOpened && !options.waitWithoutBrowser) {
|
|
12133
11590
|
logger.debug("auth.flow", "Browser unavailable — returning to caller for fallback");
|
|
12134
11591
|
return { browserOpened: false };
|
|
12135
11592
|
}
|
|
@@ -12147,11 +11604,17 @@ async function startOAuthFlow(signal, path3 = "/cli/auth", params = {}) {
|
|
|
12147
11604
|
}) : new Promise(() => {});
|
|
12148
11605
|
const token = await Promise.race([tokenPromise, timeout, abort]);
|
|
12149
11606
|
logger.info("auth.flow", "Token received");
|
|
11607
|
+
if (options.holdNext) {
|
|
11608
|
+
handedOver = true;
|
|
11609
|
+
return { browserOpened: true, token, server };
|
|
11610
|
+
}
|
|
12150
11611
|
return { browserOpened: true, token };
|
|
12151
11612
|
} finally {
|
|
12152
11613
|
clearTimeout(timeoutId);
|
|
12153
|
-
|
|
12154
|
-
|
|
11614
|
+
if (!handedOver) {
|
|
11615
|
+
server.close();
|
|
11616
|
+
logger.debug("auth.flow", "Cleaning up: timeout cleared, server closed");
|
|
11617
|
+
}
|
|
12155
11618
|
}
|
|
12156
11619
|
}
|
|
12157
11620
|
function buildAuthURL(callbackURL, path3, extraParams) {
|
|
@@ -12170,14 +11633,11 @@ __export(exports_flow2, {
|
|
|
12170
11633
|
stepShowSummary: () => stepShowSummary,
|
|
12171
11634
|
stepDetectTools: () => stepDetectTools,
|
|
12172
11635
|
stepConfigureTools: () => stepConfigureTools,
|
|
12173
|
-
showTryItOutPrompt: () => showTryItOutPrompt,
|
|
12174
11636
|
runSetup: () => runSetup,
|
|
12175
11637
|
runInstallSkill: () => runInstallSkill,
|
|
12176
11638
|
isStdioOnly: () => isStdioOnly
|
|
12177
11639
|
});
|
|
12178
11640
|
import { randomUUID } from "node:crypto";
|
|
12179
|
-
import { existsSync as existsSync16 } from "node:fs";
|
|
12180
|
-
import { join as join26 } from "node:path";
|
|
12181
11641
|
async function runSetup(opts = {}) {
|
|
12182
11642
|
const onboardingRunID = randomUUID();
|
|
12183
11643
|
logger.info("setup", `Setup flow started${opts.deploymentID ? ` deployment=${opts.deploymentID}` : ""}${opts.mode ? ` mode=${opts.mode}` : ""}`);
|
|
@@ -12192,10 +11652,15 @@ async function runSetup(opts = {}) {
|
|
|
12192
11652
|
cfg.mode = undefined;
|
|
12193
11653
|
saveConfig(cfg);
|
|
12194
11654
|
}
|
|
12195
|
-
const
|
|
12196
|
-
if (!
|
|
11655
|
+
const authed = await stepAuthenticate(cfg, onboardingRunID);
|
|
11656
|
+
if (!authed)
|
|
12197
11657
|
return;
|
|
12198
|
-
cfg =
|
|
11658
|
+
cfg = authed.cfg;
|
|
11659
|
+
const authTab = authed.authTab;
|
|
11660
|
+
const releaseAuthTab = () => {
|
|
11661
|
+
authTab?.setNext(null);
|
|
11662
|
+
authTab?.close();
|
|
11663
|
+
};
|
|
12199
11664
|
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_auth_completed");
|
|
12200
11665
|
const apiClient = new Client(cfg);
|
|
12201
11666
|
let cloudSetupContext = null;
|
|
@@ -12208,6 +11673,7 @@ async function runSetup(opts = {}) {
|
|
|
12208
11673
|
reason: "cloud_setup_context_failed"
|
|
12209
11674
|
});
|
|
12210
11675
|
s.stop("Workspace load failed");
|
|
11676
|
+
releaseAuthTab();
|
|
12211
11677
|
return;
|
|
12212
11678
|
}
|
|
12213
11679
|
s.stop("Workspace loaded");
|
|
@@ -12215,7 +11681,18 @@ async function runSetup(opts = {}) {
|
|
|
12215
11681
|
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_started", {
|
|
12216
11682
|
flow_kind: cloudSetupContext?.kind ?? "oss"
|
|
12217
11683
|
});
|
|
12218
|
-
|
|
11684
|
+
const firstRunOnboarding = cfg.mode !== MODE_OSS && cloudSetupContext?.kind === "onboarding" && !opts.deploymentID;
|
|
11685
|
+
if (!firstRunOnboarding) {
|
|
11686
|
+
releaseAuthTab();
|
|
11687
|
+
}
|
|
11688
|
+
if (firstRunOnboarding && cloudSetupContext) {
|
|
11689
|
+
const onboarded = await stepWebOnboarding(cfg, onboardingRunID, authTab);
|
|
11690
|
+
if (!onboarded) {
|
|
11691
|
+
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_failed", {
|
|
11692
|
+
reason: "web_onboarding_incomplete"
|
|
11693
|
+
});
|
|
11694
|
+
return;
|
|
11695
|
+
}
|
|
12219
11696
|
const ok = await bindOnboardingDeployment(apiClient, cfg, cloudSetupContext.targetOrg ?? null);
|
|
12220
11697
|
if (!ok) {
|
|
12221
11698
|
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_failed", {
|
|
@@ -12241,9 +11718,7 @@ async function runSetup(opts = {}) {
|
|
|
12241
11718
|
}
|
|
12242
11719
|
cfg.api_key = apiKey;
|
|
12243
11720
|
saveConfig(cfg);
|
|
12244
|
-
const choices = await stepOneShotConfirm(
|
|
12245
|
-
includeGitHub: cloudSetupContext?.kind === "onboarding"
|
|
12246
|
-
});
|
|
11721
|
+
const choices = await stepOneShotConfirm();
|
|
12247
11722
|
if (!choices) {
|
|
12248
11723
|
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_cancelled", {
|
|
12249
11724
|
reason: "options_cancelled"
|
|
@@ -12252,13 +11727,11 @@ async function runSetup(opts = {}) {
|
|
|
12252
11727
|
}
|
|
12253
11728
|
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_options_selected", {
|
|
12254
11729
|
configure_mcp: choices.configureMcp,
|
|
12255
|
-
install_skill: choices.installSkill
|
|
12256
|
-
connect_github: choices.connectGitHub
|
|
11730
|
+
install_skill: choices.installSkill
|
|
12257
11731
|
});
|
|
12258
11732
|
let mcpConfiguredThisRun = false;
|
|
12259
11733
|
let mcpCompleted = false;
|
|
12260
11734
|
let skillCompleted = false;
|
|
12261
|
-
let docsImported = false;
|
|
12262
11735
|
if (choices.configureMcp) {
|
|
12263
11736
|
const configured = await stepConfigureMcpTools(cfg);
|
|
12264
11737
|
if (configured === null) {
|
|
@@ -12283,84 +11756,14 @@ async function runSetup(opts = {}) {
|
|
|
12283
11756
|
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_skill_installed");
|
|
12284
11757
|
}
|
|
12285
11758
|
}
|
|
12286
|
-
let githubOnboardingDone = !choices.connectGitHub;
|
|
12287
|
-
if (choices.connectGitHub && cloudSetupContext?.kind === "onboarding") {
|
|
12288
|
-
const { stepConnectGitHubRepo: stepConnectGitHubRepo2 } = await Promise.resolve().then(() => (init_github_step(), exports_github_step));
|
|
12289
|
-
const connectResult = await stepConnectGitHubRepo2(cfg);
|
|
12290
|
-
if (!connectResult.advance) {
|
|
12291
|
-
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_cancelled", {
|
|
12292
|
-
reason: "github_connect_not_advanced",
|
|
12293
|
-
has_connected_repo: connectResult.has_connected_repo
|
|
12294
|
-
});
|
|
12295
|
-
return;
|
|
12296
|
-
}
|
|
12297
|
-
if (connectResult.has_connected_repo || (connectResult.created_data_source_ids?.length ?? 0) > 0) {
|
|
12298
|
-
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_github_connected", {
|
|
12299
|
-
created_data_source_count: connectResult.created_data_source_ids?.length ?? 0,
|
|
12300
|
-
created_repository_slugs: connectResult.created_repository_slugs
|
|
12301
|
-
});
|
|
12302
|
-
}
|
|
12303
|
-
if (connectResult.space_id && !cfg.space_id) {
|
|
12304
|
-
cfg.space_id = connectResult.space_id;
|
|
12305
|
-
saveConfig(cfg);
|
|
12306
|
-
}
|
|
12307
|
-
const { stepImportGitHubDocs: stepImportGitHubDocs2 } = await Promise.resolve().then(() => (init_github_doc_import_step(), exports_github_doc_import_step));
|
|
12308
|
-
const importResult = await stepImportGitHubDocs2(cfg, {
|
|
12309
|
-
waitForFreshDocs: Boolean(connectResult.deployment_id),
|
|
12310
|
-
expectedDataSourceIds: connectResult.created_data_source_ids
|
|
12311
|
-
});
|
|
12312
|
-
if (!importResult.advance) {
|
|
12313
|
-
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_failed", {
|
|
12314
|
-
reason: "github_docs_import_failed"
|
|
12315
|
-
});
|
|
12316
|
-
return;
|
|
12317
|
-
}
|
|
12318
|
-
docsImported = importResult.imported === true && (importResult.imported_count ?? 0) > 0;
|
|
12319
|
-
if (docsImported) {
|
|
12320
|
-
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_docs_imported", {
|
|
12321
|
-
imported_count: importResult.imported_count ?? 0,
|
|
12322
|
-
failed_count: importResult.failed_count ?? 0,
|
|
12323
|
-
task_id: importResult.task_id
|
|
12324
|
-
});
|
|
12325
|
-
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_activated", {
|
|
12326
|
-
imported_count: importResult.imported_count ?? 0,
|
|
12327
|
-
failed_count: importResult.failed_count ?? 0
|
|
12328
|
-
});
|
|
12329
|
-
}
|
|
12330
|
-
githubOnboardingDone = true;
|
|
12331
|
-
}
|
|
12332
|
-
const shouldCompleteRemoteOnboarding = cloudSetupContext?.kind === "onboarding" && githubOnboardingDone;
|
|
12333
|
-
if (shouldCompleteRemoteOnboarding && cloudSetupContext) {
|
|
12334
|
-
const profileUserID = cloudSetupContext.profileUserID;
|
|
12335
|
-
try {
|
|
12336
|
-
const { createTypedClient: createTypedClient2 } = await Promise.resolve().then(() => (init_trpc(), exports_trpc));
|
|
12337
|
-
const trpc = createTypedClient2(cfg);
|
|
12338
|
-
await trpc.user.updateProfile.mutate({
|
|
12339
|
-
user_id: profileUserID,
|
|
12340
|
-
finished_onboarding: true
|
|
12341
|
-
});
|
|
12342
|
-
logger.info("setup", "Server onboarding marked complete");
|
|
12343
|
-
} catch (err) {
|
|
12344
|
-
logger.warn("setup", `completeOnboarding failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
12345
|
-
log.warn("Could not mark onboarding complete on the server — you can retry later by running `dosu setup` again.");
|
|
12346
|
-
}
|
|
12347
|
-
}
|
|
12348
11759
|
let handoffToAudit = false;
|
|
12349
|
-
if (mcpConfiguredThisRun) {
|
|
12350
|
-
|
|
12351
|
-
mode: cfg.mode,
|
|
12352
|
-
docsImported: choices.connectGitHub && githubOnboardingDone,
|
|
12353
|
-
hasAgentsMd: existsSync16(join26(process.cwd(), "AGENTS.md"))
|
|
12354
|
-
});
|
|
12355
|
-
if (cfg.mode !== MODE_OSS) {
|
|
12356
|
-
handoffToAudit = await offerAuditHandoff();
|
|
12357
|
-
}
|
|
11760
|
+
if (mcpConfiguredThisRun && cfg.mode !== MODE_OSS) {
|
|
11761
|
+
handoffToAudit = await offerAuditHandoff();
|
|
12358
11762
|
}
|
|
12359
|
-
if (mcpCompleted || skillCompleted
|
|
11763
|
+
if (mcpCompleted || skillCompleted) {
|
|
12360
11764
|
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_completed", {
|
|
12361
11765
|
completed_mcp: mcpCompleted,
|
|
12362
|
-
completed_skill: skillCompleted
|
|
12363
|
-
imported_docs: docsImported
|
|
11766
|
+
completed_skill: skillCompleted
|
|
12364
11767
|
});
|
|
12365
11768
|
}
|
|
12366
11769
|
if (cfg.mode === MODE_OSS) {
|
|
@@ -12389,17 +11792,11 @@ function applyModeOverride(cfg, opts) {
|
|
|
12389
11792
|
}
|
|
12390
11793
|
saveConfig(cfg);
|
|
12391
11794
|
}
|
|
12392
|
-
async function stepOneShotConfirm(
|
|
11795
|
+
async function stepOneShotConfirm() {
|
|
12393
11796
|
const items = [
|
|
12394
11797
|
{ value: "configureMcp", label: "Install Dosu MCP" },
|
|
12395
11798
|
{ value: "installSkill", label: "Install Dosu skill" }
|
|
12396
11799
|
];
|
|
12397
|
-
if (opts.includeGitHub) {
|
|
12398
|
-
items.push({
|
|
12399
|
-
value: "connectGitHub",
|
|
12400
|
-
label: `Import docs from GitHub ${dim("(Keep them up to date)")}`
|
|
12401
|
-
});
|
|
12402
|
-
}
|
|
12403
11800
|
const selected = await multiselect({
|
|
12404
11801
|
message: "Dosu will set these up — press Enter to accept, space to toggle",
|
|
12405
11802
|
options: items.map((it) => ({ value: it.value, label: it.label })),
|
|
@@ -12413,8 +11810,7 @@ async function stepOneShotConfirm(opts) {
|
|
|
12413
11810
|
const chosen = new Set(selected);
|
|
12414
11811
|
return {
|
|
12415
11812
|
configureMcp: chosen.has("configureMcp"),
|
|
12416
|
-
installSkill: chosen.has("installSkill")
|
|
12417
|
-
connectGitHub: chosen.has("connectGitHub")
|
|
11813
|
+
installSkill: chosen.has("installSkill")
|
|
12418
11814
|
};
|
|
12419
11815
|
}
|
|
12420
11816
|
async function stepConfigureMcpTools(cfg) {
|
|
@@ -12461,7 +11857,7 @@ async function stepAuthenticate(existingCfg, onboardingRunID) {
|
|
|
12461
11857
|
if (resp.status === 200) {
|
|
12462
11858
|
logger.info("setup", `Session verified, status=${resp.status}`);
|
|
12463
11859
|
s.stop("Authenticated");
|
|
12464
|
-
return cfg;
|
|
11860
|
+
return { cfg };
|
|
12465
11861
|
}
|
|
12466
11862
|
try {
|
|
12467
11863
|
logger.debug("setup", "Attempting token refresh");
|
|
@@ -12469,7 +11865,7 @@ async function stepAuthenticate(existingCfg, onboardingRunID) {
|
|
|
12469
11865
|
const resp2 = await apiClient.doRequestRaw("GET", "/v1/mcp/deployments");
|
|
12470
11866
|
if (resp2.status === 200) {
|
|
12471
11867
|
s.stop("Authenticated");
|
|
12472
|
-
return cfg;
|
|
11868
|
+
return { cfg };
|
|
12473
11869
|
}
|
|
12474
11870
|
} catch {}
|
|
12475
11871
|
s.stop("Session expired");
|
|
@@ -12479,15 +11875,6 @@ async function stepAuthenticate(existingCfg, onboardingRunID) {
|
|
|
12479
11875
|
s.stop("Session verification failed");
|
|
12480
11876
|
}
|
|
12481
11877
|
}
|
|
12482
|
-
const shouldLogin = await confirm({ message: "Open browser to log in?" });
|
|
12483
|
-
if (isCancel(shouldLogin) || !shouldLogin) {
|
|
12484
|
-
if (onboardingRunID) {
|
|
12485
|
-
await trackCliOnboardingPreAuthEvent(onboardingRunID, "cli_onboarding_auth_cancelled", {
|
|
12486
|
-
reason: isCancel(shouldLogin) ? "prompt_cancelled" : "login_declined"
|
|
12487
|
-
});
|
|
12488
|
-
}
|
|
12489
|
-
return null;
|
|
12490
|
-
}
|
|
12491
11878
|
if (onboardingRunID) {
|
|
12492
11879
|
await trackCliOnboardingPreAuthEvent(onboardingRunID, "cli_onboarding_auth_started");
|
|
12493
11880
|
}
|
|
@@ -12497,11 +11884,16 @@ async function openBrowserForSetup(cfg, onboardingRunID) {
|
|
|
12497
11884
|
try {
|
|
12498
11885
|
const { startOAuthFlow: startOAuthFlow2 } = await Promise.resolve().then(() => (init_flow(), exports_flow));
|
|
12499
11886
|
const s = spinner();
|
|
12500
|
-
|
|
12501
|
-
|
|
11887
|
+
const result = await startOAuthFlow2(undefined, "/cli/auth", onboardingRunID ? { onboarding_run_id: onboardingRunID } : {}, undefined, {
|
|
11888
|
+
waitWithoutBrowser: true,
|
|
11889
|
+
holdNext: true,
|
|
11890
|
+
onAuthURL: (url) => {
|
|
11891
|
+
log.message(browserFallbackHint(url));
|
|
11892
|
+
s.start("Waiting for authentication...");
|
|
11893
|
+
}
|
|
11894
|
+
});
|
|
12502
11895
|
if (!result.browserOpened) {
|
|
12503
11896
|
s.stop("Could not open a browser");
|
|
12504
|
-
log.error("Run 'dosu login --no-browser' from the terminal to authenticate over SSH.");
|
|
12505
11897
|
return null;
|
|
12506
11898
|
}
|
|
12507
11899
|
const token = result.token;
|
|
@@ -12511,7 +11903,7 @@ async function openBrowserForSetup(cfg, onboardingRunID) {
|
|
|
12511
11903
|
cfg.refresh_token = token.refresh_token;
|
|
12512
11904
|
cfg.expires_at = Math.floor(Date.now() / 1000) + token.expires_in;
|
|
12513
11905
|
saveConfig(cfg);
|
|
12514
|
-
return cfg;
|
|
11906
|
+
return { cfg, authTab: result.server };
|
|
12515
11907
|
} catch (err) {
|
|
12516
11908
|
const msg = err instanceof Error ? err.stack ?? err.message : String(err);
|
|
12517
11909
|
logger.error("setup", `Auth failed: ${msg}`);
|
|
@@ -12534,6 +11926,43 @@ async function openBrowserForSetup(cfg, onboardingRunID) {
|
|
|
12534
11926
|
return null;
|
|
12535
11927
|
}
|
|
12536
11928
|
}
|
|
11929
|
+
async function stepWebOnboarding(cfg, onboardingRunID, authTab) {
|
|
11930
|
+
logger.info("setup", "Step: web onboarding handoff");
|
|
11931
|
+
log.info("Almost there — connect your repos in the browser and we'll pick up from here.");
|
|
11932
|
+
const s = spinner();
|
|
11933
|
+
try {
|
|
11934
|
+
const { startOAuthFlow: startOAuthFlow2 } = await Promise.resolve().then(() => (init_flow(), exports_flow));
|
|
11935
|
+
const result = await startOAuthFlow2(undefined, "/onboarding/connections", { source: "cli", onboarding_run_id: onboardingRunID }, undefined, {
|
|
11936
|
+
waitWithoutBrowser: true,
|
|
11937
|
+
suppressBrowserOpen: Boolean(authTab),
|
|
11938
|
+
successVariant: "onboarding",
|
|
11939
|
+
onAuthURL: (url) => {
|
|
11940
|
+
authTab?.setNext(url);
|
|
11941
|
+
log.message(browserFallbackHint(url));
|
|
11942
|
+
s.start("Waiting for onboarding to finish in the browser...");
|
|
11943
|
+
}
|
|
11944
|
+
});
|
|
11945
|
+
if (!result.browserOpened) {
|
|
11946
|
+
s.stop("Could not open a browser");
|
|
11947
|
+
return false;
|
|
11948
|
+
}
|
|
11949
|
+
cfg.access_token = result.token.access_token;
|
|
11950
|
+
cfg.refresh_token = result.token.refresh_token;
|
|
11951
|
+
cfg.expires_at = Math.floor(Date.now() / 1000) + result.token.expires_in;
|
|
11952
|
+
saveConfig(cfg);
|
|
11953
|
+
s.stop("Onboarding finished in the browser");
|
|
11954
|
+
logger.info("setup", "Web onboarding handoff completed");
|
|
11955
|
+
return true;
|
|
11956
|
+
} catch (err) {
|
|
11957
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
11958
|
+
logger.warn("setup", `Web onboarding handoff did not complete: ${msg}`);
|
|
11959
|
+
s.stop("Onboarding not completed");
|
|
11960
|
+
log.warn("Didn't hear back from the browser. Finish onboarding there, then re-run `dosu setup`.");
|
|
11961
|
+
return false;
|
|
11962
|
+
} finally {
|
|
11963
|
+
authTab?.close();
|
|
11964
|
+
}
|
|
11965
|
+
}
|
|
12537
11966
|
async function resolveCloudSetupContext(cfg) {
|
|
12538
11967
|
try {
|
|
12539
11968
|
const { createTypedClient: createTypedClient2 } = await Promise.resolve().then(() => (init_trpc(), exports_trpc));
|
|
@@ -12543,7 +11972,7 @@ async function resolveCloudSetupContext(cfg) {
|
|
|
12543
11972
|
log.error("Could not load your profile.");
|
|
12544
11973
|
return null;
|
|
12545
11974
|
}
|
|
12546
|
-
if (profile.finished_onboarding === true
|
|
11975
|
+
if (profile.finished_onboarding === true) {
|
|
12547
11976
|
return {
|
|
12548
11977
|
kind: "setup",
|
|
12549
11978
|
profileUserID: profile.user_id
|
|
@@ -12827,23 +12256,6 @@ ${lines}`);
|
|
|
12827
12256
|
log.success("All agents already configured. No changes needed.");
|
|
12828
12257
|
}
|
|
12829
12258
|
}
|
|
12830
|
-
function showTryItOutPrompt(opts = {}) {
|
|
12831
|
-
const prompt = (() => {
|
|
12832
|
-
if (opts.mode === MODE_OSS) {
|
|
12833
|
-
return `What can Dosu help me with? Pick an open source library related to my project and explain how it works.`;
|
|
12834
|
-
}
|
|
12835
|
-
if (opts.docsImported) {
|
|
12836
|
-
return `Use Dosu to summarize the most important docs in my repo.`;
|
|
12837
|
-
}
|
|
12838
|
-
if (opts.hasAgentsMd) {
|
|
12839
|
-
return `Please use Dosu to host my AGENTS.md`;
|
|
12840
|
-
}
|
|
12841
|
-
return `Ask Dosu to draft an AGENTS.md for this project.`;
|
|
12842
|
-
})();
|
|
12843
|
-
log.message(`Try it out! Paste this into your agent:
|
|
12844
|
-
|
|
12845
|
-
${info(prompt)}`);
|
|
12846
|
-
}
|
|
12847
12259
|
var init_flow2 = __esm(() => {
|
|
12848
12260
|
init_dist8();
|
|
12849
12261
|
init_client();
|
|
@@ -12857,8 +12269,8 @@ var init_flow2 = __esm(() => {
|
|
|
12857
12269
|
});
|
|
12858
12270
|
|
|
12859
12271
|
// src/commands/insights.ts
|
|
12860
|
-
import { existsSync as
|
|
12861
|
-
import { dirname as dirname5, join as
|
|
12272
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync8, readdirSync, unlinkSync, writeFileSync as writeFileSync7 } from "node:fs";
|
|
12273
|
+
import { dirname as dirname5, join as join26 } from "node:path";
|
|
12862
12274
|
function shuffled(arr) {
|
|
12863
12275
|
const copy2 = [...arr];
|
|
12864
12276
|
for (let i2 = copy2.length - 1;i2 > 0; i2--) {
|
|
@@ -12873,7 +12285,7 @@ function createDotsSpinner() {
|
|
|
12873
12285
|
let current = "";
|
|
12874
12286
|
const isTTY = Boolean(process.stdout.isTTY) && process.env.CI !== "true";
|
|
12875
12287
|
const draw = () => {
|
|
12876
|
-
process.stdout.write(`\r\x1B[2K${
|
|
12288
|
+
process.stdout.write(`\r\x1B[2K${import_picocolors14.default.cyan(SPINNER_FRAMES[frameIdx])} ${current}`);
|
|
12877
12289
|
frameIdx = (frameIdx + 1) % SPINNER_FRAMES.length;
|
|
12878
12290
|
};
|
|
12879
12291
|
return {
|
|
@@ -12895,7 +12307,7 @@ function createDotsSpinner() {
|
|
|
12895
12307
|
clearInterval(timer);
|
|
12896
12308
|
timer = undefined;
|
|
12897
12309
|
}
|
|
12898
|
-
const symbol3 = code === 0 ?
|
|
12310
|
+
const symbol3 = code === 0 ? import_picocolors14.default.green("✓") : import_picocolors14.default.red("✗");
|
|
12899
12311
|
if (isTTY) {
|
|
12900
12312
|
process.stdout.write(`\r\x1B[2K${symbol3} ${msg}
|
|
12901
12313
|
`);
|
|
@@ -12962,17 +12374,17 @@ function makeAskFn(cfg) {
|
|
|
12962
12374
|
};
|
|
12963
12375
|
}
|
|
12964
12376
|
function insightsDir() {
|
|
12965
|
-
return
|
|
12377
|
+
return join26(getConfigDir(), "insights");
|
|
12966
12378
|
}
|
|
12967
12379
|
function reportPath(timestamp) {
|
|
12968
12380
|
const dir = insightsDir();
|
|
12969
12381
|
if (!timestamp)
|
|
12970
|
-
return
|
|
12382
|
+
return join26(dir, "latest.html");
|
|
12971
12383
|
const iso = timestamp.toISOString().slice(0, 19).replace(/:/g, "-");
|
|
12972
|
-
return
|
|
12384
|
+
return join26(dir, `report-${iso}Z.html`);
|
|
12973
12385
|
}
|
|
12974
12386
|
function pruneOldReports(dir, keepN) {
|
|
12975
|
-
if (!
|
|
12387
|
+
if (!existsSync16(dir))
|
|
12976
12388
|
return;
|
|
12977
12389
|
let entries;
|
|
12978
12390
|
try {
|
|
@@ -12984,7 +12396,7 @@ function pruneOldReports(dir, keepN) {
|
|
|
12984
12396
|
const reports = entries.filter((f2) => REPORT_FILE_PATTERN.test(f2)).sort().reverse();
|
|
12985
12397
|
for (const f2 of reports.slice(keepN)) {
|
|
12986
12398
|
try {
|
|
12987
|
-
unlinkSync(
|
|
12399
|
+
unlinkSync(join26(dir, f2));
|
|
12988
12400
|
} catch (err) {
|
|
12989
12401
|
logger.debug("insights", `failed to prune ${f2}: ${err instanceof Error ? err.message : err}`);
|
|
12990
12402
|
}
|
|
@@ -13036,18 +12448,18 @@ async function runInsights(cfg, runner) {
|
|
|
13036
12448
|
runner.writeFile(latestPath, html);
|
|
13037
12449
|
runner.prune(insightsDir(), KEEP_REPORTS);
|
|
13038
12450
|
console.log("");
|
|
13039
|
-
console.log(
|
|
12451
|
+
console.log(import_picocolors14.default.bold(`\uD83D\uDCCA Dosu Insights · ${report.spaceName}`));
|
|
13040
12452
|
if (report.cheers[0]) {
|
|
13041
|
-
console.log(
|
|
12453
|
+
console.log(import_picocolors14.default.green(` ${report.cheers[0]}`));
|
|
13042
12454
|
}
|
|
13043
12455
|
console.log("");
|
|
13044
|
-
console.log(` Snapshot: ${
|
|
13045
|
-
console.log(` Latest: ${
|
|
13046
|
-
console.log(
|
|
12456
|
+
console.log(` Snapshot: ${import_picocolors14.default.cyan(`file://${snapshotPath}`)}`);
|
|
12457
|
+
console.log(` Latest: ${import_picocolors14.default.cyan(`file://${latestPath}`)}`);
|
|
12458
|
+
console.log(import_picocolors14.default.dim(" Opening in your browser..."));
|
|
13047
12459
|
try {
|
|
13048
12460
|
await runner.openInBrowser(snapshotPath);
|
|
13049
12461
|
} catch {
|
|
13050
|
-
console.log(
|
|
12462
|
+
console.log(import_picocolors14.default.dim(" (couldn't auto-open. Copy the link above.)"));
|
|
13051
12463
|
}
|
|
13052
12464
|
return snapshotPath;
|
|
13053
12465
|
}
|
|
@@ -13057,7 +12469,7 @@ function defaultRunner(cfg) {
|
|
|
13057
12469
|
render: renderHTML,
|
|
13058
12470
|
writeFile: (path3, content) => {
|
|
13059
12471
|
const dir = dirname5(path3);
|
|
13060
|
-
if (!
|
|
12472
|
+
if (!existsSync16(dir))
|
|
13061
12473
|
mkdirSync8(dir, { recursive: true, mode: 448 });
|
|
13062
12474
|
writeFileSync7(path3, content, { mode: 384 });
|
|
13063
12475
|
},
|
|
@@ -13074,7 +12486,7 @@ async function executeInsights(cfg) {
|
|
|
13074
12486
|
try {
|
|
13075
12487
|
await runInsights(cfg, defaultRunner(cfg));
|
|
13076
12488
|
} catch (err) {
|
|
13077
|
-
console.error(
|
|
12489
|
+
console.error(import_picocolors14.default.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
13078
12490
|
}
|
|
13079
12491
|
}
|
|
13080
12492
|
function insightsCommand() {
|
|
@@ -13085,12 +12497,12 @@ function insightsCommand() {
|
|
|
13085
12497
|
try {
|
|
13086
12498
|
await runInsights(cfg, defaultRunner(cfg));
|
|
13087
12499
|
} catch (err) {
|
|
13088
|
-
console.error(
|
|
12500
|
+
console.error(import_picocolors14.default.red(`Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
13089
12501
|
process.exit(1);
|
|
13090
12502
|
}
|
|
13091
12503
|
});
|
|
13092
12504
|
}
|
|
13093
|
-
var
|
|
12505
|
+
var import_picocolors14, ASK_TIMEOUT_MS = 90000, KEEP_REPORTS = 20, REPORT_FILE_PATTERN, HINT_INTERVAL_MS = 6000, NARRATIVE_HINTS, SPINNER_FRAMES, SPINNER_INTERVAL_MS = 80;
|
|
13094
12506
|
var init_insights3 = __esm(() => {
|
|
13095
12507
|
init_dist8();
|
|
13096
12508
|
init_commander();
|
|
@@ -13099,7 +12511,7 @@ var init_insights3 = __esm(() => {
|
|
|
13099
12511
|
init_logger();
|
|
13100
12512
|
init_insights2();
|
|
13101
12513
|
init_flow2();
|
|
13102
|
-
|
|
12514
|
+
import_picocolors14 = __toESM(require_picocolors(), 1);
|
|
13103
12515
|
REPORT_FILE_PATTERN = /^report-\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}Z\.html$/;
|
|
13104
12516
|
NARRATIVE_HINTS = [
|
|
13105
12517
|
"Reading your reactions and confidence levels",
|
|
@@ -13128,7 +12540,7 @@ __export(exports_tui, {
|
|
|
13128
12540
|
handleLogout: () => handleLogout
|
|
13129
12541
|
});
|
|
13130
12542
|
async function runTUI() {
|
|
13131
|
-
console.log(
|
|
12543
|
+
console.log(import_picocolors25.default.magenta(LOGO));
|
|
13132
12544
|
const cfg = loadConfig();
|
|
13133
12545
|
while (true) {
|
|
13134
12546
|
const insightsReady = Boolean(cfg.space_id && cfg.deployment_id && cfg.api_key);
|
|
@@ -13203,8 +12615,10 @@ async function handleAuthenticate(cfg) {
|
|
|
13203
12615
|
try {
|
|
13204
12616
|
const { startOAuthFlow: startOAuthFlow2 } = await Promise.resolve().then(() => (init_flow(), exports_flow));
|
|
13205
12617
|
const s = spinner();
|
|
13206
|
-
|
|
13207
|
-
|
|
12618
|
+
const result = await startOAuthFlow2(undefined, "/cli/auth", {}, (url) => {
|
|
12619
|
+
log.message(browserFallbackHint(url));
|
|
12620
|
+
s.start("Waiting for authentication...");
|
|
12621
|
+
});
|
|
13208
12622
|
if (!result.browserOpened) {
|
|
13209
12623
|
s.stop("Could not open a browser");
|
|
13210
12624
|
log.error("Run 'dosu login --no-browser' from the terminal to authenticate over SSH.");
|
|
@@ -13240,7 +12654,7 @@ function handleLogout(cfg) {
|
|
|
13240
12654
|
saveConfig(cfg);
|
|
13241
12655
|
log.success("Credentials cleared.");
|
|
13242
12656
|
}
|
|
13243
|
-
var
|
|
12657
|
+
var import_picocolors25, LOGO = `
|
|
13244
12658
|
/$$$$$$$
|
|
13245
12659
|
| $$__ $$
|
|
13246
12660
|
| $$ \\ $$ /$$$$$$ /$$$$$$$ /$$ /$$
|
|
@@ -13256,7 +12670,8 @@ var init_tui = __esm(() => {
|
|
|
13256
12670
|
init_insights3();
|
|
13257
12671
|
init_config();
|
|
13258
12672
|
init_flow2();
|
|
13259
|
-
|
|
12673
|
+
init_styles();
|
|
12674
|
+
import_picocolors25 = __toESM(require_picocolors(), 1);
|
|
13260
12675
|
});
|
|
13261
12676
|
|
|
13262
12677
|
// src/auth/ticket.ts
|
|
@@ -13460,7 +12875,7 @@ Could not open a browser automatically.`);
|
|
|
13460
12875
|
while (Date.now() < deadline) {
|
|
13461
12876
|
if (signal?.aborted)
|
|
13462
12877
|
throw new Error("authentication cancelled");
|
|
13463
|
-
await
|
|
12878
|
+
await sleep5(POLL_INTERVAL_MS);
|
|
13464
12879
|
if (signal?.aborted)
|
|
13465
12880
|
throw new Error("authentication cancelled");
|
|
13466
12881
|
const result = await exchangeTicket(minted.ticket);
|
|
@@ -13477,7 +12892,7 @@ Could not open a browser automatically.`);
|
|
|
13477
12892
|
}
|
|
13478
12893
|
throw new Error("Authentication timed out. Run 'dosu login' to try again.");
|
|
13479
12894
|
}
|
|
13480
|
-
function
|
|
12895
|
+
function sleep5(ms) {
|
|
13481
12896
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
13482
12897
|
}
|
|
13483
12898
|
var POLL_INTERVAL_MS = 5000;
|
|
@@ -15505,11 +14920,11 @@ init_insights3();
|
|
|
15505
14920
|
// src/commands/integrations.ts
|
|
15506
14921
|
init_commander();
|
|
15507
14922
|
init_trpc();
|
|
15508
|
-
var
|
|
14923
|
+
var import_picocolors15 = __toESM(require_picocolors(), 1);
|
|
15509
14924
|
function requireConfig6() {
|
|
15510
14925
|
const cfg = requireLoginConfig();
|
|
15511
14926
|
if (!cfg.org_id) {
|
|
15512
|
-
console.error(
|
|
14927
|
+
console.error(import_picocolors15.default.red("Missing org config. Run 'dosu setup' to reconfigure."));
|
|
15513
14928
|
process.exit(1);
|
|
15514
14929
|
}
|
|
15515
14930
|
return cfg;
|
|
@@ -15560,7 +14975,7 @@ function integrationsCommand() {
|
|
|
15560
14975
|
}
|
|
15561
14976
|
printTable(["Platform", "Status"], results.map((r2) => [
|
|
15562
14977
|
r2.platform,
|
|
15563
|
-
r2.connected ?
|
|
14978
|
+
r2.connected ? import_picocolors15.default.green("connected") : import_picocolors15.default.dim("not connected")
|
|
15564
14979
|
]), { rawData: results });
|
|
15565
14980
|
});
|
|
15566
14981
|
cmd.command("status").description("Check connection status of a specific platform").argument("<platform>", `Platform: ${DISPLAY_PLATFORMS.join(", ")}`).option("--json", "Output as JSON").action(async (platform4, opts) => {
|
|
@@ -15572,7 +14987,7 @@ function integrationsCommand() {
|
|
|
15572
14987
|
printResult({ platform: platform4, connected: false, note: "not queryable via nango" }, opts);
|
|
15573
14988
|
return;
|
|
15574
14989
|
}
|
|
15575
|
-
console.log(`${platform4}: ${
|
|
14990
|
+
console.log(`${platform4}: ${import_picocolors15.default.dim("not connected (not queryable)")}`);
|
|
15576
14991
|
return;
|
|
15577
14992
|
}
|
|
15578
14993
|
try {
|
|
@@ -15586,13 +15001,13 @@ function integrationsCommand() {
|
|
|
15586
15001
|
printResult({ platform: platform4, connected, connection: conn }, opts);
|
|
15587
15002
|
return;
|
|
15588
15003
|
}
|
|
15589
|
-
console.log(`${platform4}: ${connected ?
|
|
15004
|
+
console.log(`${platform4}: ${connected ? import_picocolors15.default.green("connected") : import_picocolors15.default.dim("not connected")}`);
|
|
15590
15005
|
} catch {
|
|
15591
15006
|
if (opts.json) {
|
|
15592
15007
|
printResult({ platform: platform4, connected: false }, opts);
|
|
15593
15008
|
return;
|
|
15594
15009
|
}
|
|
15595
|
-
console.log(`${platform4}: ${
|
|
15010
|
+
console.log(`${platform4}: ${import_picocolors15.default.dim("not connected")}`);
|
|
15596
15011
|
}
|
|
15597
15012
|
});
|
|
15598
15013
|
cmd.command("slack-channels").description("List Slack channels").option("--json", "Output as JSON").action(async (opts) => {
|
|
@@ -15604,7 +15019,7 @@ function integrationsCommand() {
|
|
|
15604
15019
|
return;
|
|
15605
15020
|
}
|
|
15606
15021
|
if (!channels || channels.length === 0) {
|
|
15607
|
-
console.log(
|
|
15022
|
+
console.log(import_picocolors15.default.dim("No Slack channels found."));
|
|
15608
15023
|
return;
|
|
15609
15024
|
}
|
|
15610
15025
|
printTable(["ID", "Name"], channels.map((c3) => [
|
|
@@ -15620,7 +15035,7 @@ function integrationsCommand() {
|
|
|
15620
15035
|
printResult({ success: true, channelId }, opts);
|
|
15621
15036
|
return;
|
|
15622
15037
|
}
|
|
15623
|
-
console.log(
|
|
15038
|
+
console.log(import_picocolors15.default.green(`Joined Slack channel ${channelId}.`));
|
|
15624
15039
|
});
|
|
15625
15040
|
cmd.command("github-collaborators").description("List GitHub repository collaborators").option("--json", "Output as JSON").action(async (opts) => {
|
|
15626
15041
|
const cfg = requireConfig6();
|
|
@@ -15631,7 +15046,7 @@ function integrationsCommand() {
|
|
|
15631
15046
|
return;
|
|
15632
15047
|
}
|
|
15633
15048
|
if (!collaborators || collaborators.length === 0) {
|
|
15634
|
-
console.log(
|
|
15049
|
+
console.log(import_picocolors15.default.dim("No collaborators found."));
|
|
15635
15050
|
return;
|
|
15636
15051
|
}
|
|
15637
15052
|
printTable(["Username", "Name", "Email"], collaborators.map((c3) => [c3.user_name ?? "—", c3.full_name ?? "—", c3.email ?? "—"]), { rawData: collaborators });
|
|
@@ -15642,11 +15057,11 @@ function integrationsCommand() {
|
|
|
15642
15057
|
// src/commands/knowledge.ts
|
|
15643
15058
|
init_commander();
|
|
15644
15059
|
init_trpc();
|
|
15645
|
-
var
|
|
15060
|
+
var import_picocolors16 = __toESM(require_picocolors(), 1);
|
|
15646
15061
|
function requireConfig7() {
|
|
15647
15062
|
const cfg = requireLoginConfig();
|
|
15648
15063
|
if (!cfg.org_id || !cfg.space_id) {
|
|
15649
|
-
console.error(
|
|
15064
|
+
console.error(import_picocolors16.default.red("Missing org/space config. Run 'dosu setup' to reconfigure."));
|
|
15650
15065
|
process.exit(1);
|
|
15651
15066
|
}
|
|
15652
15067
|
return cfg;
|
|
@@ -15662,7 +15077,7 @@ function knowledgeCommand() {
|
|
|
15662
15077
|
});
|
|
15663
15078
|
const dataSourceIds = dataSources.map((ds) => ds.id).filter((id) => id !== null);
|
|
15664
15079
|
if (dataSourceIds.length === 0) {
|
|
15665
|
-
console.log(
|
|
15080
|
+
console.log(import_picocolors16.default.dim("No data sources connected. Add data sources in the Dosu dashboard."));
|
|
15666
15081
|
return;
|
|
15667
15082
|
}
|
|
15668
15083
|
const data = await client.search.getMentions.query({
|
|
@@ -15676,7 +15091,7 @@ function knowledgeCommand() {
|
|
|
15676
15091
|
return;
|
|
15677
15092
|
}
|
|
15678
15093
|
if (!results || results.length === 0) {
|
|
15679
|
-
console.log(
|
|
15094
|
+
console.log(import_picocolors16.default.dim("No results found."));
|
|
15680
15095
|
return;
|
|
15681
15096
|
}
|
|
15682
15097
|
const limit = Number.parseInt(opts.limit ?? "10", 10);
|
|
@@ -15686,7 +15101,7 @@ function knowledgeCommand() {
|
|
|
15686
15101
|
r2.entity_type ?? "—"
|
|
15687
15102
|
]), { json: false, rawData: limited });
|
|
15688
15103
|
if (results.length > limit) {
|
|
15689
|
-
console.log(
|
|
15104
|
+
console.log(import_picocolors16.default.dim(`
|
|
15690
15105
|
${results.length - limit} more results not shown.`));
|
|
15691
15106
|
}
|
|
15692
15107
|
});
|
|
@@ -15699,10 +15114,10 @@ ${results.length - limit} more results not shown.`));
|
|
|
15699
15114
|
return;
|
|
15700
15115
|
}
|
|
15701
15116
|
if (!store) {
|
|
15702
|
-
console.log(
|
|
15117
|
+
console.log(import_picocolors16.default.dim("No knowledge store found for this deployment."));
|
|
15703
15118
|
return;
|
|
15704
15119
|
}
|
|
15705
|
-
console.log(
|
|
15120
|
+
console.log(import_picocolors16.default.bold("Knowledge Store"));
|
|
15706
15121
|
console.log(` ID: ${store.id}`);
|
|
15707
15122
|
console.log(` Space ID: ${store.space_id}`);
|
|
15708
15123
|
});
|
|
@@ -15712,11 +15127,11 @@ ${results.length - limit} more results not shown.`));
|
|
|
15712
15127
|
// src/commands/members.ts
|
|
15713
15128
|
init_commander();
|
|
15714
15129
|
init_trpc();
|
|
15715
|
-
var
|
|
15130
|
+
var import_picocolors17 = __toESM(require_picocolors(), 1);
|
|
15716
15131
|
function requireConfig8() {
|
|
15717
15132
|
const cfg = requireLoginConfig();
|
|
15718
15133
|
if (!cfg.org_id) {
|
|
15719
|
-
console.error(
|
|
15134
|
+
console.error(import_picocolors17.default.red("Missing org config. Run 'dosu setup' to reconfigure."));
|
|
15720
15135
|
process.exit(1);
|
|
15721
15136
|
}
|
|
15722
15137
|
return cfg;
|
|
@@ -15732,7 +15147,7 @@ function membersCommand() {
|
|
|
15732
15147
|
return;
|
|
15733
15148
|
}
|
|
15734
15149
|
if (!data.items || data.items.length === 0) {
|
|
15735
|
-
console.log(
|
|
15150
|
+
console.log(import_picocolors17.default.dim("No members or invitations found."));
|
|
15736
15151
|
return;
|
|
15737
15152
|
}
|
|
15738
15153
|
printTable(["Email", "Org"], data.items.map((m3) => [
|
|
@@ -15753,7 +15168,7 @@ function membersCommand() {
|
|
|
15753
15168
|
printResult({ success: true, email, role }, opts);
|
|
15754
15169
|
return;
|
|
15755
15170
|
}
|
|
15756
|
-
console.log(
|
|
15171
|
+
console.log(import_picocolors17.default.green(`Invitation sent to ${email} as ${role}.`));
|
|
15757
15172
|
});
|
|
15758
15173
|
cmd.command("requests").description("List pending access requests").option("--json", "Output as JSON").action(async (opts) => {
|
|
15759
15174
|
const cfg = requireConfig8();
|
|
@@ -15764,7 +15179,7 @@ function membersCommand() {
|
|
|
15764
15179
|
return;
|
|
15765
15180
|
}
|
|
15766
15181
|
if (!data.items || data.items.length === 0) {
|
|
15767
|
-
console.log(
|
|
15182
|
+
console.log(import_picocolors17.default.dim("No pending access requests."));
|
|
15768
15183
|
return;
|
|
15769
15184
|
}
|
|
15770
15185
|
printTable(["Email", "Org"], data.items.map((r2) => [
|
|
@@ -15783,7 +15198,7 @@ function membersCommand() {
|
|
|
15783
15198
|
printResult({ success: true, email, action: "approved" }, opts);
|
|
15784
15199
|
return;
|
|
15785
15200
|
}
|
|
15786
|
-
console.log(
|
|
15201
|
+
console.log(import_picocolors17.default.green(`Access request from ${email} approved.`));
|
|
15787
15202
|
});
|
|
15788
15203
|
cmd.command("deny").description("Deny an access request").argument("<email>", "Email of requester").option("--json", "Output as JSON").action(async (email, opts) => {
|
|
15789
15204
|
const cfg = requireConfig8();
|
|
@@ -15796,7 +15211,7 @@ function membersCommand() {
|
|
|
15796
15211
|
printResult({ success: true, email, action: "denied" }, opts);
|
|
15797
15212
|
return;
|
|
15798
15213
|
}
|
|
15799
|
-
console.log(
|
|
15214
|
+
console.log(import_picocolors17.default.green(`Access request from ${email} denied.`));
|
|
15800
15215
|
});
|
|
15801
15216
|
return cmd;
|
|
15802
15217
|
}
|
|
@@ -15804,7 +15219,7 @@ function membersCommand() {
|
|
|
15804
15219
|
// src/commands/org.ts
|
|
15805
15220
|
init_commander();
|
|
15806
15221
|
init_trpc();
|
|
15807
|
-
var
|
|
15222
|
+
var import_picocolors18 = __toESM(require_picocolors(), 1);
|
|
15808
15223
|
function requireConfig9() {
|
|
15809
15224
|
return requireLoginConfig();
|
|
15810
15225
|
}
|
|
@@ -15819,7 +15234,7 @@ function orgCommand() {
|
|
|
15819
15234
|
return;
|
|
15820
15235
|
}
|
|
15821
15236
|
if (!orgs || orgs.length === 0) {
|
|
15822
|
-
console.log(
|
|
15237
|
+
console.log(import_picocolors18.default.dim("No organizations found."));
|
|
15823
15238
|
return;
|
|
15824
15239
|
}
|
|
15825
15240
|
if (orgs.length === 1) {
|
|
@@ -15833,7 +15248,7 @@ function orgCommand() {
|
|
|
15833
15248
|
printTable(["ID", "Name"], orgs.map((o2) => [o2.org_id.slice(0, 8), o2.name]), { rawData: orgs });
|
|
15834
15249
|
if (cfg.org_id) {
|
|
15835
15250
|
console.log(`
|
|
15836
|
-
${
|
|
15251
|
+
${import_picocolors18.default.dim(`Current: ${cfg.org_id}`)}`);
|
|
15837
15252
|
}
|
|
15838
15253
|
});
|
|
15839
15254
|
return cmd;
|
|
@@ -15844,7 +15259,7 @@ init_dist8();
|
|
|
15844
15259
|
init_dist();
|
|
15845
15260
|
init_commander();
|
|
15846
15261
|
init_trpc();
|
|
15847
|
-
var
|
|
15262
|
+
var import_picocolors19 = __toESM(require_picocolors(), 1);
|
|
15848
15263
|
import { readFileSync as readFileSync14 } from "node:fs";
|
|
15849
15264
|
function requireConfig10() {
|
|
15850
15265
|
return requireLoginConfig();
|
|
@@ -15870,7 +15285,7 @@ async function requireChange(client, id) {
|
|
|
15870
15285
|
return await client.review.getChange.query({ id });
|
|
15871
15286
|
} catch (err) {
|
|
15872
15287
|
if (isNotFound(err) || isInvalidId(err)) {
|
|
15873
|
-
console.error(
|
|
15288
|
+
console.error(import_picocolors19.default.red(`No review item found for '${id}'. Run 'dosu review list' to see pending items.`));
|
|
15874
15289
|
process.exit(1);
|
|
15875
15290
|
}
|
|
15876
15291
|
throw err;
|
|
@@ -15879,7 +15294,7 @@ async function requireChange(client, id) {
|
|
|
15879
15294
|
async function requireDraft(client, id) {
|
|
15880
15295
|
const draft = await client.messages.getMessage.query(bareMessageId(id));
|
|
15881
15296
|
if (!draft) {
|
|
15882
|
-
console.error(
|
|
15297
|
+
console.error(import_picocolors19.default.red(`No review item found for '${id}'. Run 'dosu review list' to see pending items.`));
|
|
15883
15298
|
process.exit(1);
|
|
15884
15299
|
}
|
|
15885
15300
|
return draft;
|
|
@@ -15902,12 +15317,12 @@ function colorizeDiff(diff) {
|
|
|
15902
15317
|
return diff.split(`
|
|
15903
15318
|
`).map((line) => {
|
|
15904
15319
|
if (line.startsWith("+"))
|
|
15905
|
-
return
|
|
15320
|
+
return import_picocolors19.default.green(line);
|
|
15906
15321
|
if (line.startsWith("-"))
|
|
15907
|
-
return
|
|
15322
|
+
return import_picocolors19.default.red(line);
|
|
15908
15323
|
if (line.startsWith("@@"))
|
|
15909
|
-
return
|
|
15910
|
-
return
|
|
15324
|
+
return import_picocolors19.default.cyan(line);
|
|
15325
|
+
return import_picocolors19.default.dim(line);
|
|
15911
15326
|
}).join(`
|
|
15912
15327
|
`);
|
|
15913
15328
|
}
|
|
@@ -15921,7 +15336,7 @@ function printChangePreview(change) {
|
|
|
15921
15336
|
]
|
|
15922
15337
|
]);
|
|
15923
15338
|
if (!change.hasChanges) {
|
|
15924
|
-
console.log(
|
|
15339
|
+
console.log(import_picocolors19.default.dim("No content changes."));
|
|
15925
15340
|
return;
|
|
15926
15341
|
}
|
|
15927
15342
|
console.log();
|
|
@@ -15938,7 +15353,7 @@ function printDraftPreview(draft) {
|
|
|
15938
15353
|
async function getKnowledgeStoreId2(client, spaceId) {
|
|
15939
15354
|
const store = await client.knowledgeStore.getBySpaceId.query({ space_id: spaceId });
|
|
15940
15355
|
if (!store) {
|
|
15941
|
-
console.error(
|
|
15356
|
+
console.error(import_picocolors19.default.red("No knowledge store found for this deployment."));
|
|
15942
15357
|
process.exit(1);
|
|
15943
15358
|
}
|
|
15944
15359
|
return store.id;
|
|
@@ -15948,7 +15363,7 @@ function reviewCommand() {
|
|
|
15948
15363
|
cmd.command("list").description("List pending review items (doc changes and draft replies)").option("--json", "Output as JSON").action(async (opts) => {
|
|
15949
15364
|
const cfg = requireConfig10();
|
|
15950
15365
|
if (!cfg.space_id) {
|
|
15951
|
-
console.error(
|
|
15366
|
+
console.error(import_picocolors19.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
|
|
15952
15367
|
process.exit(1);
|
|
15953
15368
|
}
|
|
15954
15369
|
const client = createTypedClient(cfg);
|
|
@@ -15963,7 +15378,7 @@ function reviewCommand() {
|
|
|
15963
15378
|
return;
|
|
15964
15379
|
}
|
|
15965
15380
|
if (!items || items.length === 0) {
|
|
15966
|
-
console.log(
|
|
15381
|
+
console.log(import_picocolors19.default.dim("No pending review items."));
|
|
15967
15382
|
return;
|
|
15968
15383
|
}
|
|
15969
15384
|
printTable(["ID", "Kind", "Title", "Source", "Status", "Created"], items.map((i2) => i2.kind === "draft_message" ? [
|
|
@@ -15982,7 +15397,7 @@ function reviewCommand() {
|
|
|
15982
15397
|
formatDate(i2.createdAt)
|
|
15983
15398
|
]), { rawData: items });
|
|
15984
15399
|
if (truncated) {
|
|
15985
|
-
console.log(
|
|
15400
|
+
console.log(import_picocolors19.default.dim(`Showing ${items.length} of ${total}+ pending items (list truncated).`));
|
|
15986
15401
|
}
|
|
15987
15402
|
});
|
|
15988
15403
|
cmd.command("diff").description("Show a pending review item (doc-change diff or draft reply body)").argument("<id>", "Review item ID (from `dosu review list`)").option("--json", "Output as JSON").action(async (id, opts) => {
|
|
@@ -15994,8 +15409,8 @@ function reviewCommand() {
|
|
|
15994
15409
|
printResult({ id, kind: "draft_message", title: draft.title, body: draft.body }, opts);
|
|
15995
15410
|
return;
|
|
15996
15411
|
}
|
|
15997
|
-
console.log(
|
|
15998
|
-
console.log(
|
|
15412
|
+
console.log(import_picocolors19.default.bold(draft.title ?? "(untitled)"));
|
|
15413
|
+
console.log(import_picocolors19.default.dim("Draft reply"));
|
|
15999
15414
|
console.log("");
|
|
16000
15415
|
console.log(draft.body ?? "");
|
|
16001
15416
|
return;
|
|
@@ -16006,8 +15421,8 @@ function reviewCommand() {
|
|
|
16006
15421
|
return;
|
|
16007
15422
|
}
|
|
16008
15423
|
const versions = change.publishedVersion != null ? `v${change.publishedVersion} → v${change.version}` : `v${change.version}`;
|
|
16009
|
-
console.log(
|
|
16010
|
-
console.log(
|
|
15424
|
+
console.log(import_picocolors19.default.bold(change.title));
|
|
15425
|
+
console.log(import_picocolors19.default.dim(`${change.source} · ${versions}`));
|
|
16011
15426
|
console.log("");
|
|
16012
15427
|
console.log(change.diff);
|
|
16013
15428
|
});
|
|
@@ -16015,7 +15430,7 @@ function reviewCommand() {
|
|
|
16015
15430
|
const cfg = requireConfig10();
|
|
16016
15431
|
const client = createTypedClient(cfg);
|
|
16017
15432
|
if (opts.body !== undefined && opts.bodyFile !== undefined) {
|
|
16018
|
-
console.error(
|
|
15433
|
+
console.error(import_picocolors19.default.red("Pass only one of --body or --body-file."));
|
|
16019
15434
|
process.exit(1);
|
|
16020
15435
|
}
|
|
16021
15436
|
let body = opts.body;
|
|
@@ -16023,17 +15438,17 @@ function reviewCommand() {
|
|
|
16023
15438
|
try {
|
|
16024
15439
|
body = readFileSync14(opts.bodyFile, "utf-8");
|
|
16025
15440
|
} catch (err) {
|
|
16026
|
-
console.error(
|
|
15441
|
+
console.error(import_picocolors19.default.red(`Failed to read --body-file: ${err.message}`));
|
|
16027
15442
|
process.exit(1);
|
|
16028
15443
|
}
|
|
16029
15444
|
}
|
|
16030
15445
|
if (body === undefined && opts.title === undefined) {
|
|
16031
|
-
console.error(
|
|
15446
|
+
console.error(import_picocolors19.default.red("Nothing to edit. Pass --title and/or --body/--body-file."));
|
|
16032
15447
|
process.exit(1);
|
|
16033
15448
|
}
|
|
16034
15449
|
if (isDraftId(id)) {
|
|
16035
15450
|
if (opts.title !== undefined) {
|
|
16036
|
-
console.error(
|
|
15451
|
+
console.error(import_picocolors19.default.red("Draft replies support --body only (no --title)."));
|
|
16037
15452
|
process.exit(1);
|
|
16038
15453
|
}
|
|
16039
15454
|
await requireDraft(client, id);
|
|
@@ -16050,7 +15465,7 @@ function reviewCommand() {
|
|
|
16050
15465
|
});
|
|
16051
15466
|
} catch (err) {
|
|
16052
15467
|
if (isNotFound(err)) {
|
|
16053
|
-
console.error(
|
|
15468
|
+
console.error(import_picocolors19.default.red(`No pending review item found for '${id}'. Run 'dosu review list' to see editable items.`));
|
|
16054
15469
|
process.exit(1);
|
|
16055
15470
|
}
|
|
16056
15471
|
throw err;
|
|
@@ -16060,7 +15475,7 @@ function reviewCommand() {
|
|
|
16060
15475
|
printResult({ success: true, id }, opts);
|
|
16061
15476
|
return;
|
|
16062
15477
|
}
|
|
16063
|
-
console.log(
|
|
15478
|
+
console.log(import_picocolors19.default.green(`Review edited: ${truncateId(id)}`));
|
|
16064
15479
|
});
|
|
16065
15480
|
cmd.command("context").description("Get review context for a thread").argument("<thread-id>", "Thread ID").option("--json", "Output as JSON").action(async (threadId, opts) => {
|
|
16066
15481
|
const cfg = requireConfig10();
|
|
@@ -16107,7 +15522,7 @@ function reviewCommand() {
|
|
|
16107
15522
|
initialValue: false
|
|
16108
15523
|
});
|
|
16109
15524
|
if (isCancel(answer)) {
|
|
16110
|
-
console.log(
|
|
15525
|
+
console.log(import_picocolors19.default.dim("Cancelled."));
|
|
16111
15526
|
return;
|
|
16112
15527
|
}
|
|
16113
15528
|
proceed = answer === true;
|
|
@@ -16122,7 +15537,7 @@ function reviewCommand() {
|
|
|
16122
15537
|
};
|
|
16123
15538
|
printResult({ ...preview, applied: false, confirmRequired: true }, opts);
|
|
16124
15539
|
} else {
|
|
16125
|
-
console.log(
|
|
15540
|
+
console.log(import_picocolors19.default.dim("Aborted. Re-run with --confirm to apply."));
|
|
16126
15541
|
}
|
|
16127
15542
|
return;
|
|
16128
15543
|
}
|
|
@@ -16137,7 +15552,7 @@ function reviewCommand() {
|
|
|
16137
15552
|
printResult({ success: true, id, action }, opts);
|
|
16138
15553
|
return;
|
|
16139
15554
|
}
|
|
16140
|
-
console.log(
|
|
15555
|
+
console.log(import_picocolors19.default.green(`Review ${name}: ${truncateId(id)}`));
|
|
16141
15556
|
});
|
|
16142
15557
|
}
|
|
16143
15558
|
cmd.command("revert").description("Revert a doc change to pending review (not supported for draft replies)").argument("<id>", "Review item ID (from `dosu review list`)").option("--json", "Output as JSON").action(async (id, opts) => {
|
|
@@ -16145,7 +15560,7 @@ function reviewCommand() {
|
|
|
16145
15560
|
const client = createTypedClient(cfg);
|
|
16146
15561
|
if (isDraftId(id)) {
|
|
16147
15562
|
await requireDraft(client, id);
|
|
16148
|
-
console.error(
|
|
15563
|
+
console.error(import_picocolors19.default.red("Revert is not supported for draft replies. A rejected draft is regenerated on the next agent run."));
|
|
16149
15564
|
process.exit(1);
|
|
16150
15565
|
}
|
|
16151
15566
|
await requireChange(client, id);
|
|
@@ -16157,7 +15572,7 @@ function reviewCommand() {
|
|
|
16157
15572
|
printResult({ success: true, id, action: "revert_to_pending" }, opts);
|
|
16158
15573
|
return;
|
|
16159
15574
|
}
|
|
16160
|
-
console.log(
|
|
15575
|
+
console.log(import_picocolors19.default.green(`Review revert: ${truncateId(id)}`));
|
|
16161
15576
|
});
|
|
16162
15577
|
return cmd;
|
|
16163
15578
|
}
|
|
@@ -16168,11 +15583,11 @@ init_skill();
|
|
|
16168
15583
|
// src/commands/sources.ts
|
|
16169
15584
|
init_commander();
|
|
16170
15585
|
init_trpc();
|
|
16171
|
-
var
|
|
15586
|
+
var import_picocolors20 = __toESM(require_picocolors(), 1);
|
|
16172
15587
|
function requireConfig11() {
|
|
16173
15588
|
const cfg = requireLoginConfig();
|
|
16174
15589
|
if (!cfg.org_id) {
|
|
16175
|
-
console.error(
|
|
15590
|
+
console.error(import_picocolors20.default.red("Missing org config. Run 'dosu setup' to reconfigure."));
|
|
16176
15591
|
process.exit(1);
|
|
16177
15592
|
}
|
|
16178
15593
|
return cfg;
|
|
@@ -16192,7 +15607,7 @@ function sourcesCommand() {
|
|
|
16192
15607
|
}
|
|
16193
15608
|
const list = dataSources ?? [];
|
|
16194
15609
|
if (list.length === 0) {
|
|
16195
|
-
console.log(
|
|
15610
|
+
console.log(import_picocolors20.default.dim("No data sources connected."));
|
|
16196
15611
|
return;
|
|
16197
15612
|
}
|
|
16198
15613
|
printTable(["ID", "Name", "Provider", "Created"], list.map((ds) => [
|
|
@@ -16211,7 +15626,7 @@ function sourcesCommand() {
|
|
|
16211
15626
|
return;
|
|
16212
15627
|
}
|
|
16213
15628
|
if (!ds) {
|
|
16214
|
-
console.log(
|
|
15629
|
+
console.log(import_picocolors20.default.dim("Data source not found."));
|
|
16215
15630
|
return;
|
|
16216
15631
|
}
|
|
16217
15632
|
printInfo([
|
|
@@ -16230,7 +15645,7 @@ function sourcesCommand() {
|
|
|
16230
15645
|
printResult({ success: true, id }, opts);
|
|
16231
15646
|
return;
|
|
16232
15647
|
}
|
|
16233
|
-
console.log(
|
|
15648
|
+
console.log(import_picocolors20.default.green(`Data source sync triggered for ${id.slice(0, 8)}.`));
|
|
16234
15649
|
});
|
|
16235
15650
|
cmd.command("update").description("Update a data source").argument("<id>", "Data source ID").option("--name <name>", "New name").option("--description <desc>", "New description").option("--json", "Output as JSON").action(async (id, opts) => {
|
|
16236
15651
|
const cfg = requireConfig11();
|
|
@@ -16244,7 +15659,7 @@ function sourcesCommand() {
|
|
|
16244
15659
|
printResult(result, opts);
|
|
16245
15660
|
return;
|
|
16246
15661
|
}
|
|
16247
|
-
console.log(
|
|
15662
|
+
console.log(import_picocolors20.default.green("Data source updated."));
|
|
16248
15663
|
});
|
|
16249
15664
|
cmd.command("delete").description("Delete a data source").argument("<id>", "Data source ID").option("--json", "Output as JSON").action(async (id, opts) => {
|
|
16250
15665
|
const cfg = requireConfig11();
|
|
@@ -16254,7 +15669,7 @@ function sourcesCommand() {
|
|
|
16254
15669
|
printResult({ success: true, id }, opts);
|
|
16255
15670
|
return;
|
|
16256
15671
|
}
|
|
16257
|
-
console.log(
|
|
15672
|
+
console.log(import_picocolors20.default.green("Data source deleted."));
|
|
16258
15673
|
});
|
|
16259
15674
|
return cmd;
|
|
16260
15675
|
}
|
|
@@ -16262,11 +15677,11 @@ function sourcesCommand() {
|
|
|
16262
15677
|
// src/commands/suggest.ts
|
|
16263
15678
|
init_commander();
|
|
16264
15679
|
init_trpc();
|
|
16265
|
-
var
|
|
15680
|
+
var import_picocolors21 = __toESM(require_picocolors(), 1);
|
|
16266
15681
|
function requireConfig12() {
|
|
16267
15682
|
const cfg = requireLoginConfig();
|
|
16268
15683
|
if (!cfg.space_id) {
|
|
16269
|
-
console.error(
|
|
15684
|
+
console.error(import_picocolors21.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
|
|
16270
15685
|
process.exit(1);
|
|
16271
15686
|
}
|
|
16272
15687
|
return cfg;
|
|
@@ -16276,7 +15691,7 @@ async function getKnowledgeStoreId3(client, spaceId) {
|
|
|
16276
15691
|
space_id: spaceId
|
|
16277
15692
|
});
|
|
16278
15693
|
if (!store) {
|
|
16279
|
-
console.error(
|
|
15694
|
+
console.error(import_picocolors21.default.red("No knowledge store found for this deployment."));
|
|
16280
15695
|
process.exit(1);
|
|
16281
15696
|
}
|
|
16282
15697
|
return store.id;
|
|
@@ -16295,7 +15710,7 @@ function suggestCommand() {
|
|
|
16295
15710
|
return;
|
|
16296
15711
|
}
|
|
16297
15712
|
if (!suggestions || suggestions.length === 0) {
|
|
16298
|
-
console.log(
|
|
15713
|
+
console.log(import_picocolors21.default.dim("No pending suggestions."));
|
|
16299
15714
|
return;
|
|
16300
15715
|
}
|
|
16301
15716
|
printTable(["ID", "Title"], suggestions.map((s) => [
|
|
@@ -16308,7 +15723,7 @@ function suggestCommand() {
|
|
|
16308
15723
|
const client = createTypedClient(cfg);
|
|
16309
15724
|
const ksId = await getKnowledgeStoreId3(client, cfg.space_id);
|
|
16310
15725
|
if (!cfg.org_id) {
|
|
16311
|
-
console.error(
|
|
15726
|
+
console.error(import_picocolors21.default.red("Missing org config. Run 'dosu setup' to reconfigure."));
|
|
16312
15727
|
process.exit(1);
|
|
16313
15728
|
}
|
|
16314
15729
|
const dataSources = await client.dataSource.list.query({
|
|
@@ -16324,7 +15739,7 @@ function suggestCommand() {
|
|
|
16324
15739
|
printResult(result, opts);
|
|
16325
15740
|
return;
|
|
16326
15741
|
}
|
|
16327
|
-
console.log(
|
|
15742
|
+
console.log(import_picocolors21.default.green("Document suggestions are being generated."));
|
|
16328
15743
|
});
|
|
16329
15744
|
cmd.command("reject").description("Reject a suggestion").argument("<id>", "Suggestion ID").option("--json", "Output as JSON").action(async (id, opts) => {
|
|
16330
15745
|
const cfg = requireConfig12();
|
|
@@ -16334,7 +15749,7 @@ function suggestCommand() {
|
|
|
16334
15749
|
printResult({ success: true, id }, opts);
|
|
16335
15750
|
return;
|
|
16336
15751
|
}
|
|
16337
|
-
console.log(
|
|
15752
|
+
console.log(import_picocolors21.default.green("Suggestion rejected."));
|
|
16338
15753
|
});
|
|
16339
15754
|
return cmd;
|
|
16340
15755
|
}
|
|
@@ -16342,11 +15757,11 @@ function suggestCommand() {
|
|
|
16342
15757
|
// src/commands/threads.ts
|
|
16343
15758
|
init_commander();
|
|
16344
15759
|
init_trpc();
|
|
16345
|
-
var
|
|
15760
|
+
var import_picocolors22 = __toESM(require_picocolors(), 1);
|
|
16346
15761
|
function requireConfig13() {
|
|
16347
15762
|
const cfg = requireLoginConfig();
|
|
16348
15763
|
if (!cfg.space_id) {
|
|
16349
|
-
console.error(
|
|
15764
|
+
console.error(import_picocolors22.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
|
|
16350
15765
|
process.exit(1);
|
|
16351
15766
|
}
|
|
16352
15767
|
return cfg;
|
|
@@ -16393,7 +15808,7 @@ function threadsCommand() {
|
|
|
16393
15808
|
return;
|
|
16394
15809
|
}
|
|
16395
15810
|
if (!threads || threads.length === 0) {
|
|
16396
|
-
console.log(
|
|
15811
|
+
console.log(import_picocolors22.default.dim("No threads found."));
|
|
16397
15812
|
return;
|
|
16398
15813
|
}
|
|
16399
15814
|
printTable(["ID", "Title", "Status", "Created"], threads.map((t2) => [
|
|
@@ -16418,10 +15833,10 @@ function threadsCommand() {
|
|
|
16418
15833
|
return;
|
|
16419
15834
|
}
|
|
16420
15835
|
if (!thread) {
|
|
16421
|
-
console.log(
|
|
15836
|
+
console.log(import_picocolors22.default.dim("Thread not found."));
|
|
16422
15837
|
return;
|
|
16423
15838
|
}
|
|
16424
|
-
console.log(
|
|
15839
|
+
console.log(import_picocolors22.default.bold(thread.generated_title ?? "(untitled thread)"));
|
|
16425
15840
|
printInfo([
|
|
16426
15841
|
["ID", thread.id],
|
|
16427
15842
|
["Created", formatDate(thread.created_at)],
|
|
@@ -16432,13 +15847,13 @@ function threadsCommand() {
|
|
|
16432
15847
|
if (messages && messages.length > 0) {
|
|
16433
15848
|
const allMessages = messages.flatMap((group) => group.messages);
|
|
16434
15849
|
console.log(`
|
|
16435
|
-
${
|
|
16436
|
-
console.log(
|
|
15850
|
+
${import_picocolors22.default.bold("Messages")} (${allMessages.length})`);
|
|
15851
|
+
console.log(import_picocolors22.default.dim("─".repeat(60)));
|
|
16437
15852
|
for (const msg of allMessages) {
|
|
16438
15853
|
const role = msg.author_role ?? "unknown";
|
|
16439
15854
|
const date = formatDate(msg.created_at);
|
|
16440
15855
|
console.log(`
|
|
16441
|
-
${
|
|
15856
|
+
${import_picocolors22.default.bold(role)} ${import_picocolors22.default.dim(date)}`);
|
|
16442
15857
|
if (msg.body) {
|
|
16443
15858
|
console.log(truncate(msg.body, 500));
|
|
16444
15859
|
}
|
|
@@ -16453,7 +15868,7 @@ ${import_picocolors23.default.bold(role)} ${import_picocolors23.default.dim(date
|
|
|
16453
15868
|
printResult({ success: true, id }, opts);
|
|
16454
15869
|
return;
|
|
16455
15870
|
}
|
|
16456
|
-
console.log(
|
|
15871
|
+
console.log(import_picocolors22.default.green(`Thread ${id.slice(0, 8)} archived.`));
|
|
16457
15872
|
});
|
|
16458
15873
|
return cmd;
|
|
16459
15874
|
}
|
|
@@ -16461,11 +15876,11 @@ ${import_picocolors23.default.bold(role)} ${import_picocolors23.default.dim(date
|
|
|
16461
15876
|
// src/commands/topics.ts
|
|
16462
15877
|
init_commander();
|
|
16463
15878
|
init_trpc();
|
|
16464
|
-
var
|
|
15879
|
+
var import_picocolors23 = __toESM(require_picocolors(), 1);
|
|
16465
15880
|
function requireConfig14() {
|
|
16466
15881
|
const cfg = requireLoginConfig();
|
|
16467
15882
|
if (!cfg.space_id) {
|
|
16468
|
-
console.error(
|
|
15883
|
+
console.error(import_picocolors23.default.red("Missing space config. Run 'dosu setup' to reconfigure."));
|
|
16469
15884
|
process.exit(1);
|
|
16470
15885
|
}
|
|
16471
15886
|
return cfg;
|
|
@@ -16475,7 +15890,7 @@ async function getKnowledgeStoreId4(client, spaceId) {
|
|
|
16475
15890
|
space_id: spaceId
|
|
16476
15891
|
});
|
|
16477
15892
|
if (!store) {
|
|
16478
|
-
console.error(
|
|
15893
|
+
console.error(import_picocolors23.default.red("No knowledge store found for this deployment."));
|
|
16479
15894
|
process.exit(1);
|
|
16480
15895
|
}
|
|
16481
15896
|
return store.id;
|
|
@@ -16494,7 +15909,7 @@ function topicsCommand() {
|
|
|
16494
15909
|
return;
|
|
16495
15910
|
}
|
|
16496
15911
|
if (!topics || topics.length === 0) {
|
|
16497
|
-
console.log(
|
|
15912
|
+
console.log(import_picocolors23.default.dim("No topics found."));
|
|
16498
15913
|
return;
|
|
16499
15914
|
}
|
|
16500
15915
|
printTable(["ID", "Name", "Description"], topics.map((t2) => [
|
|
@@ -16519,7 +15934,7 @@ function topicsCommand() {
|
|
|
16519
15934
|
return;
|
|
16520
15935
|
}
|
|
16521
15936
|
if (!pages || pages.length === 0) {
|
|
16522
|
-
console.log(
|
|
15937
|
+
console.log(import_picocolors23.default.dim("No pages found with this topic."));
|
|
16523
15938
|
return;
|
|
16524
15939
|
}
|
|
16525
15940
|
printTable(["ID", "Title"], pages.map((p2) => [
|
|
@@ -16534,14 +15949,15 @@ function topicsCommand() {
|
|
|
16534
15949
|
init_config();
|
|
16535
15950
|
init_logger();
|
|
16536
15951
|
init_providers();
|
|
15952
|
+
init_styles();
|
|
16537
15953
|
init_skill_update_check();
|
|
16538
15954
|
|
|
16539
15955
|
// src/version/update-check.ts
|
|
16540
15956
|
init_config();
|
|
16541
15957
|
init_logger();
|
|
16542
|
-
var
|
|
16543
|
-
import { existsSync as
|
|
16544
|
-
import { join as
|
|
15958
|
+
var import_picocolors24 = __toESM(require_picocolors(), 1);
|
|
15959
|
+
import { existsSync as existsSync17, mkdirSync as mkdirSync9, readFileSync as readFileSync15, writeFileSync as writeFileSync8 } from "node:fs";
|
|
15960
|
+
import { join as join27 } from "node:path";
|
|
16545
15961
|
var CACHE_FILENAME3 = "update-check.json";
|
|
16546
15962
|
var CHECK_INTERVAL_MS3 = 24 * 60 * 60 * 1000;
|
|
16547
15963
|
var FETCH_TIMEOUT_MS3 = 5000;
|
|
@@ -16564,12 +15980,12 @@ function isNewerVersion(latest, current) {
|
|
|
16564
15980
|
return false;
|
|
16565
15981
|
}
|
|
16566
15982
|
function getCachePath3() {
|
|
16567
|
-
return
|
|
15983
|
+
return join27(getConfigDir(), CACHE_FILENAME3);
|
|
16568
15984
|
}
|
|
16569
15985
|
function readCache() {
|
|
16570
15986
|
try {
|
|
16571
15987
|
const path3 = getCachePath3();
|
|
16572
|
-
if (!
|
|
15988
|
+
if (!existsSync17(path3))
|
|
16573
15989
|
return null;
|
|
16574
15990
|
const data = JSON.parse(readFileSync15(path3, "utf-8"));
|
|
16575
15991
|
if (typeof data.lastCheck === "number" && typeof data.latestVersion === "string") {
|
|
@@ -16583,7 +15999,7 @@ function readCache() {
|
|
|
16583
15999
|
function writeCache(cache) {
|
|
16584
16000
|
try {
|
|
16585
16001
|
const dir = getConfigDir();
|
|
16586
|
-
if (!
|
|
16002
|
+
if (!existsSync17(dir)) {
|
|
16587
16003
|
mkdirSync9(dir, { recursive: true, mode: 448 });
|
|
16588
16004
|
}
|
|
16589
16005
|
writeFileSync8(getCachePath3(), JSON.stringify(cache), { mode: 384 });
|
|
@@ -16614,8 +16030,8 @@ function buildUpdateHint(channel) {
|
|
|
16614
16030
|
}
|
|
16615
16031
|
function displayNotice2(current, latest) {
|
|
16616
16032
|
const msg = `
|
|
16617
|
-
${
|
|
16618
|
-
` + `${
|
|
16033
|
+
${import_picocolors24.default.yellow(` Update available: ${current} → ${latest}`)}
|
|
16034
|
+
` + `${import_picocolors24.default.dim(` ${buildUpdateHint(INSTALL_CHANNEL)}`)}
|
|
16619
16035
|
`;
|
|
16620
16036
|
console.error(msg);
|
|
16621
16037
|
}
|
|
@@ -16714,7 +16130,9 @@ function createProgram() {
|
|
|
16714
16130
|
const { startOAuthFlow: startOAuthFlow2 } = await Promise.resolve().then(() => (init_flow(), exports_flow));
|
|
16715
16131
|
let result;
|
|
16716
16132
|
try {
|
|
16717
|
-
result = await startOAuthFlow2()
|
|
16133
|
+
result = await startOAuthFlow2(undefined, undefined, undefined, (url) => {
|
|
16134
|
+
console.log(browserFallbackHint(url));
|
|
16135
|
+
});
|
|
16718
16136
|
} catch (err) {
|
|
16719
16137
|
if (err instanceof OAuthCallbackError2) {
|
|
16720
16138
|
console.error(err.userMessage);
|