@dosu/cli 0.41.0 → 0.43.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/bin/dosu.js +163 -231
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -54,13 +54,16 @@ dosu setup
|
|
|
54
54
|
brew install dosu-ai/dosu/dosu
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
The fully qualified name works on every Homebrew version: it taps the repo if needed and, on Homebrew 6.0+, records trust for just the `dosu` formula. To use tapped short names instead:
|
|
58
58
|
|
|
59
59
|
```bash
|
|
60
60
|
brew tap dosu-ai/dosu
|
|
61
|
+
brew trust dosu-ai/dosu # Homebrew 6.0+ only — skip on older versions
|
|
61
62
|
brew install dosu
|
|
62
63
|
```
|
|
63
64
|
|
|
65
|
+
**Homebrew 6.0+ only** ([tap trust](https://docs.brew.sh/Tap-Trust), since June 2026): third-party taps start untrusted, so short-name installs or upgrades — including on machines that tapped `dosu-ai/dosu` before upgrading Homebrew — fail with `Error: Refusing to load formula dosu-ai/dosu/dosu from untrusted tap dosu-ai/dosu` until a one-time `brew trust dosu-ai/dosu` (the tap also ships [decant](https://github.com/dosu-ai/decant)). Homebrew 5 and earlier has no trust step and needs none. Tap trust is Homebrew's own consent step, separate from the macOS Gatekeeper warning below — Homebrew installs never trigger Gatekeeper.
|
|
66
|
+
|
|
64
67
|
### Manual Download
|
|
65
68
|
|
|
66
69
|
Download the appropriate archive from the [Releases](https://github.com/dosu-ai/dosu-cli/releases) page.
|
package/bin/dosu.js
CHANGED
|
@@ -4759,7 +4759,7 @@ var init_dist4 = __esm(() => {
|
|
|
4759
4759
|
function getVersionString() {
|
|
4760
4760
|
return `v${VERSION}`;
|
|
4761
4761
|
}
|
|
4762
|
-
var VERSION = "0.
|
|
4762
|
+
var VERSION = "0.43.0-alpha.1", INSTALL_CHANNEL = "npm";
|
|
4763
4763
|
|
|
4764
4764
|
// src/debug/logger.ts
|
|
4765
4765
|
import {
|
|
@@ -8744,6 +8744,25 @@ function mcpHeaders(apiKey) {
|
|
|
8744
8744
|
}
|
|
8745
8745
|
return { "X-Dosu-API-Key": apiKey };
|
|
8746
8746
|
}
|
|
8747
|
+
function mcpRemoteServer(url, apiKey) {
|
|
8748
|
+
const env = {};
|
|
8749
|
+
const headerArgs = Object.entries(mcpHeaders(apiKey)).flatMap(([key, value]) => {
|
|
8750
|
+
const envKey = key.toUpperCase().replace(/[^A-Z0-9]/g, "_");
|
|
8751
|
+
env[envKey] = value;
|
|
8752
|
+
return ["--header", `${key}:\${${envKey}}`];
|
|
8753
|
+
});
|
|
8754
|
+
return {
|
|
8755
|
+
args: [
|
|
8756
|
+
"-y",
|
|
8757
|
+
`mcp-remote@${MCP_REMOTE_VERSION}`,
|
|
8758
|
+
url,
|
|
8759
|
+
...headerArgs,
|
|
8760
|
+
"--transport",
|
|
8761
|
+
"http-only"
|
|
8762
|
+
],
|
|
8763
|
+
env
|
|
8764
|
+
};
|
|
8765
|
+
}
|
|
8747
8766
|
function loadJSONConfig(path3) {
|
|
8748
8767
|
if (!existsSync6(path3))
|
|
8749
8768
|
return {};
|
|
@@ -8845,7 +8864,7 @@ function removeJSONServer(configPath, topKey) {
|
|
|
8845
8864
|
}
|
|
8846
8865
|
saveJSONConfig(configPath, jsonCfg);
|
|
8847
8866
|
}
|
|
8848
|
-
var import_write_file_atomic, writeFileAtomic;
|
|
8867
|
+
var import_write_file_atomic, writeFileAtomic, MCP_REMOTE_VERSION = "0.1.38";
|
|
8849
8868
|
var init_config_helpers = __esm(() => {
|
|
8850
8869
|
import_write_file_atomic = __toESM(require_lib(), 1);
|
|
8851
8870
|
writeFileAtomic = import_write_file_atomic.default;
|
|
@@ -10610,7 +10629,7 @@ var MCP_PROVIDER_SLUG = "dosu_mcp";
|
|
|
10610
10629
|
// src/mcp/detect.ts
|
|
10611
10630
|
import { existsSync as existsSync13 } from "node:fs";
|
|
10612
10631
|
import { homedir as homedir2, platform as platform2 } from "node:os";
|
|
10613
|
-
import { join as join12 } from "node:path";
|
|
10632
|
+
import { delimiter, dirname as dirname5, join as join12 } from "node:path";
|
|
10614
10633
|
function isInstalled(paths) {
|
|
10615
10634
|
return paths.some((p2) => existsSync13(expandHome(p2)));
|
|
10616
10635
|
}
|
|
@@ -10635,6 +10654,20 @@ function appSupportDir() {
|
|
|
10635
10654
|
}
|
|
10636
10655
|
}
|
|
10637
10656
|
}
|
|
10657
|
+
function findNpx() {
|
|
10658
|
+
const bin = platform2() === "win32" ? "npx.cmd" : "npx";
|
|
10659
|
+
for (const dir of (process.env.PATH ?? "").split(delimiter)) {
|
|
10660
|
+
if (!dir)
|
|
10661
|
+
continue;
|
|
10662
|
+
const candidate = join12(dir, bin);
|
|
10663
|
+
if (existsSync13(candidate))
|
|
10664
|
+
return candidate;
|
|
10665
|
+
}
|
|
10666
|
+
throw new Error("npx not found on PATH — Node.js is required (the MCP entry runs `npx mcp-remote`).");
|
|
10667
|
+
}
|
|
10668
|
+
function npxPathEnv(npx) {
|
|
10669
|
+
return [dirname5(npx), "/usr/bin", "/bin"].join(delimiter);
|
|
10670
|
+
}
|
|
10638
10671
|
var init_detect = () => {};
|
|
10639
10672
|
|
|
10640
10673
|
// src/mcp/providers/base.ts
|
|
@@ -10729,6 +10762,9 @@ var init_claude = __esm(() => {
|
|
|
10729
10762
|
|
|
10730
10763
|
// src/mcp/providers/claude-desktop.ts
|
|
10731
10764
|
import { join as join14 } from "node:path";
|
|
10765
|
+
function configPath() {
|
|
10766
|
+
return join14(appSupportDir(), "Claude", "claude_desktop_config.json");
|
|
10767
|
+
}
|
|
10732
10768
|
var ClaudeDesktopProvider = () => ({
|
|
10733
10769
|
name: () => "Claude Desktop",
|
|
10734
10770
|
id: () => "claude-desktop",
|
|
@@ -10736,16 +10772,31 @@ var ClaudeDesktopProvider = () => ({
|
|
|
10736
10772
|
priority: () => 2,
|
|
10737
10773
|
detectPaths: () => [join14(appSupportDir(), "Claude")],
|
|
10738
10774
|
isInstalled: () => isInstalled([join14(appSupportDir(), "Claude")]),
|
|
10739
|
-
globalConfigPath: () =>
|
|
10740
|
-
isConfigured: () =>
|
|
10741
|
-
install() {
|
|
10742
|
-
|
|
10775
|
+
globalConfigPath: () => configPath(),
|
|
10776
|
+
isConfigured: () => isJSONKeyConfigured(configPath(), "mcpServers"),
|
|
10777
|
+
install(cfg, global) {
|
|
10778
|
+
if (!global)
|
|
10779
|
+
throw new Error("Claude Desktop does not support local installation");
|
|
10780
|
+
if (cfg.mode !== MODE_OSS && !cfg.active_account?.target?.deployment_id)
|
|
10781
|
+
throw new Error("deployment ID is required");
|
|
10782
|
+
const url = cfg.mode === MODE_OSS ? mcpBaseURL() : mcpURL(cfg.active_account.target.deployment_id);
|
|
10783
|
+
const npx = findNpx();
|
|
10784
|
+
const remote = mcpRemoteServer(url, cfg.active_account?.target?.api_key);
|
|
10785
|
+
installJSONServer(configPath(), "mcpServers", {
|
|
10786
|
+
command: npx,
|
|
10787
|
+
args: remote.args,
|
|
10788
|
+
env: { PATH: npxPathEnv(npx), ...remote.env }
|
|
10789
|
+
});
|
|
10743
10790
|
},
|
|
10744
|
-
remove() {
|
|
10745
|
-
|
|
10791
|
+
remove(global) {
|
|
10792
|
+
if (!global)
|
|
10793
|
+
throw new Error("Claude Desktop does not support local removal");
|
|
10794
|
+
removeJSONServer(configPath(), "mcpServers");
|
|
10746
10795
|
}
|
|
10747
10796
|
});
|
|
10748
10797
|
var init_claude_desktop = __esm(() => {
|
|
10798
|
+
init_config();
|
|
10799
|
+
init_config_helpers();
|
|
10749
10800
|
init_detect();
|
|
10750
10801
|
});
|
|
10751
10802
|
|
|
@@ -10824,20 +10875,25 @@ function mcpEndpoint(cfg) {
|
|
|
10824
10875
|
throw new Error("deployment ID is required");
|
|
10825
10876
|
return mcpURL(cfg.active_account?.target?.deployment_id);
|
|
10826
10877
|
}
|
|
10878
|
+
function tomlString(value) {
|
|
10879
|
+
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
|
|
10880
|
+
}
|
|
10827
10881
|
function installDosuToTOML(path3, cfg) {
|
|
10828
10882
|
let content = readTOML(path3);
|
|
10829
10883
|
content = removeDosuFromTOML(content);
|
|
10830
|
-
const
|
|
10831
|
-
const
|
|
10832
|
-
const
|
|
10884
|
+
const npx = findNpx();
|
|
10885
|
+
const remote = mcpRemoteServer(mcpEndpoint(cfg), cfg.active_account?.target?.api_key);
|
|
10886
|
+
const env = { PATH: npxPathEnv(npx), ...remote.env };
|
|
10887
|
+
const envEntries = Object.entries(env).map(([key, value]) => `${key} = ${tomlString(value)}`).join(`
|
|
10833
10888
|
`);
|
|
10889
|
+
const args = remote.args.map(tomlString).join(", ");
|
|
10834
10890
|
const section = `
|
|
10835
10891
|
[mcp_servers.dosu]
|
|
10836
|
-
|
|
10837
|
-
|
|
10838
|
-
|
|
10839
|
-
[mcp_servers.dosu.
|
|
10840
|
-
${
|
|
10892
|
+
command = ${tomlString(npx)}
|
|
10893
|
+
args = [${args}]
|
|
10894
|
+
` + `
|
|
10895
|
+
[mcp_servers.dosu.env]
|
|
10896
|
+
${envEntries}
|
|
10841
10897
|
`;
|
|
10842
10898
|
content += section;
|
|
10843
10899
|
writeTOML(path3, content);
|
|
@@ -10864,7 +10920,7 @@ function removeDosuFromTOML(content) {
|
|
|
10864
10920
|
`);
|
|
10865
10921
|
}
|
|
10866
10922
|
var CodexProvider = () => ({
|
|
10867
|
-
name: () => "Codex CLI",
|
|
10923
|
+
name: () => "Codex (CLI + Desktop)",
|
|
10868
10924
|
id: () => "codex",
|
|
10869
10925
|
supportsLocal: () => true,
|
|
10870
10926
|
priority: () => 8,
|
|
@@ -10928,21 +10984,21 @@ var CopilotProvider = () => ({
|
|
|
10928
10984
|
};
|
|
10929
10985
|
installJSONServer(globalPath(), "mcpServers", server);
|
|
10930
10986
|
} else {
|
|
10931
|
-
const
|
|
10987
|
+
const configPath2 = join18(process.cwd(), ".vscode", "mcp.json");
|
|
10932
10988
|
const server = {
|
|
10933
10989
|
type: "http",
|
|
10934
10990
|
url,
|
|
10935
10991
|
headers: mcpHeaders(cfg.active_account.target.api_key)
|
|
10936
10992
|
};
|
|
10937
|
-
installJSONServer(
|
|
10993
|
+
installJSONServer(configPath2, "servers", server);
|
|
10938
10994
|
}
|
|
10939
10995
|
},
|
|
10940
10996
|
remove(global) {
|
|
10941
10997
|
if (global) {
|
|
10942
10998
|
removeJSONServer(globalPath(), "mcpServers");
|
|
10943
10999
|
} else {
|
|
10944
|
-
const
|
|
10945
|
-
removeJSONServer(
|
|
11000
|
+
const configPath2 = join18(process.cwd(), ".vscode", "mcp.json");
|
|
11001
|
+
removeJSONServer(configPath2, "servers");
|
|
10946
11002
|
}
|
|
10947
11003
|
}
|
|
10948
11004
|
});
|
|
@@ -11077,17 +11133,17 @@ var MCPorterProvider = () => ({
|
|
|
11077
11133
|
globalConfigPath: () => resolveGlobalConfigPath(),
|
|
11078
11134
|
isConfigured: () => isJSONKeyConfigured(resolveGlobalConfigPath(), "mcpServers"),
|
|
11079
11135
|
install(cfg, global) {
|
|
11080
|
-
const
|
|
11136
|
+
const configPath2 = global ? resolveGlobalConfigPath() : join22(process.cwd(), "config", "mcporter.json");
|
|
11081
11137
|
const server = {
|
|
11082
11138
|
type: "http",
|
|
11083
11139
|
url: mcpEndpoint4(cfg),
|
|
11084
11140
|
headers: mcpHeaders(cfg.active_account.target.api_key)
|
|
11085
11141
|
};
|
|
11086
|
-
installJSONServer(
|
|
11142
|
+
installJSONServer(configPath2, "mcpServers", server);
|
|
11087
11143
|
},
|
|
11088
11144
|
remove(global) {
|
|
11089
|
-
const
|
|
11090
|
-
removeJSONServer(
|
|
11145
|
+
const configPath2 = global ? resolveGlobalConfigPath() : join22(process.cwd(), "config", "mcporter.json");
|
|
11146
|
+
removeJSONServer(configPath2, "mcpServers");
|
|
11091
11147
|
}
|
|
11092
11148
|
});
|
|
11093
11149
|
var init_mcporter = __esm(() => {
|
|
@@ -11236,7 +11292,7 @@ var init_providers = __esm(() => {
|
|
|
11236
11292
|
// src/rules/installer.ts
|
|
11237
11293
|
import { existsSync as existsSync16, mkdirSync as mkdirSync8, readFileSync as readFileSync14, unlinkSync, writeFileSync as writeFileSync7 } from "node:fs";
|
|
11238
11294
|
import { homedir as homedir4 } from "node:os";
|
|
11239
|
-
import { dirname as
|
|
11295
|
+
import { dirname as dirname6, join as join27 } from "node:path";
|
|
11240
11296
|
function claudeConfigDir() {
|
|
11241
11297
|
return process.env.CLAUDE_CONFIG_DIR || join27(homedir4(), ".claude");
|
|
11242
11298
|
}
|
|
@@ -11267,7 +11323,7 @@ async function fetchDosuRule(fetchImpl = globalThis.fetch) {
|
|
|
11267
11323
|
return normalizeRule(FALLBACK_DOSU_RULE);
|
|
11268
11324
|
}
|
|
11269
11325
|
function ensureParent(path3) {
|
|
11270
|
-
mkdirSync8(
|
|
11326
|
+
mkdirSync8(dirname6(path3), { recursive: true });
|
|
11271
11327
|
}
|
|
11272
11328
|
function writeIfChanged(path3, content) {
|
|
11273
11329
|
if (!existsSync16(path3)) {
|
|
@@ -11802,46 +11858,9 @@ code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; background:
|
|
|
11802
11858
|
</body>
|
|
11803
11859
|
</html>`;
|
|
11804
11860
|
}
|
|
11805
|
-
function
|
|
11806
|
-
return `<script>
|
|
11807
|
-
(function () {
|
|
11808
|
-
var tries = 0;
|
|
11809
|
-
var misses = 0;
|
|
11810
|
-
var setCopy = function (heading, msg) {
|
|
11811
|
-
var h = document.getElementById('heading');
|
|
11812
|
-
var m = document.getElementById('close-msg');
|
|
11813
|
-
if (h && heading) h.textContent = heading;
|
|
11814
|
-
if (m && msg) m.textContent = msg;
|
|
11815
|
-
};
|
|
11816
|
-
var settle = function () { setCopy(null, ${JSON.stringify(settleMsg)}); };
|
|
11817
|
-
var timer = setInterval(function () {
|
|
11818
|
-
tries += 1;
|
|
11819
|
-
if (tries > 720) { clearInterval(timer); settle(); return; }
|
|
11820
|
-
fetch('/next').then(function (res) {
|
|
11821
|
-
misses = 0;
|
|
11822
|
-
if (res.status === 200) {
|
|
11823
|
-
clearInterval(timer);
|
|
11824
|
-
res.json().then(function (body) {
|
|
11825
|
-
if (body && body.url) {
|
|
11826
|
-
setCopy("You're ready to connect your data sources", 'Redirecting...');
|
|
11827
|
-
window.location.replace(body.url);
|
|
11828
|
-
}
|
|
11829
|
-
});
|
|
11830
|
-
} else if (res.status === 410) {
|
|
11831
|
-
clearInterval(timer);
|
|
11832
|
-
settle();
|
|
11833
|
-
}
|
|
11834
|
-
}).catch(function () {
|
|
11835
|
-
misses += 1;
|
|
11836
|
-
if (misses >= 8) { clearInterval(timer); settle(); }
|
|
11837
|
-
});
|
|
11838
|
-
}, 250);
|
|
11839
|
-
})();
|
|
11840
|
-
</script>`;
|
|
11841
|
-
}
|
|
11842
|
-
function buildSuccessHtml(email, variant = "auth", withNextPoll = false) {
|
|
11861
|
+
function buildSuccessHtml(email, variant = "auth") {
|
|
11843
11862
|
const copy2 = SUCCESS_COPY[variant];
|
|
11844
|
-
const closeMsg =
|
|
11863
|
+
const closeMsg = copy2.close;
|
|
11845
11864
|
const emailLine = email ? `<p class="email">Signed in as <strong>${email.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">")}</strong></p>` : "";
|
|
11846
11865
|
return `<!DOCTYPE html>
|
|
11847
11866
|
<html lang="en">
|
|
@@ -11959,7 +11978,6 @@ h1 {
|
|
|
11959
11978
|
<span class="tip-label">Did you know?</span>
|
|
11960
11979
|
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
11980
|
</div>
|
|
11962
|
-
${withNextPoll ? buildNextPollScript(copy2.close) : ""}
|
|
11963
11981
|
</body>
|
|
11964
11982
|
</html>`;
|
|
11965
11983
|
}
|
|
@@ -11970,27 +11988,12 @@ async function startCallbackServer(opts = {}) {
|
|
|
11970
11988
|
resolveToken = resolve;
|
|
11971
11989
|
rejectToken = reject;
|
|
11972
11990
|
});
|
|
11973
|
-
let nextTarget;
|
|
11974
11991
|
const http = __require("node:http");
|
|
11975
11992
|
const httpServer = http.createServer((req, res) => {
|
|
11976
11993
|
const url = new URL(req.url ?? "/", `http://localhost`);
|
|
11977
11994
|
const cookieLen = (req.headers.cookie ?? "").length;
|
|
11978
11995
|
const ua = req.headers["user-agent"] ?? "none";
|
|
11979
11996
|
logger.debug("auth.server", `Request: ${req.method} ${url.pathname} cookie-len=${cookieLen} ua=${ua} has-token=${url.searchParams.has("access_token")}`);
|
|
11980
|
-
if (opts.nextHold && url.pathname === "/next") {
|
|
11981
|
-
if (nextTarget === undefined) {
|
|
11982
|
-
res.writeHead(204);
|
|
11983
|
-
res.end();
|
|
11984
|
-
} else if (nextTarget === null) {
|
|
11985
|
-
res.writeHead(410);
|
|
11986
|
-
res.end();
|
|
11987
|
-
} else {
|
|
11988
|
-
logger.info("auth.server", "Handing tab onward via /next");
|
|
11989
|
-
res.writeHead(200, { "Content-Type": "application/json" });
|
|
11990
|
-
res.end(JSON.stringify({ url: nextTarget }));
|
|
11991
|
-
}
|
|
11992
|
-
return;
|
|
11993
|
-
}
|
|
11994
11997
|
if (url.pathname !== "/callback") {
|
|
11995
11998
|
logger.debug("auth.server", `404: ${url.pathname}`);
|
|
11996
11999
|
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
@@ -12038,7 +12041,7 @@ async function startCallbackServer(opts = {}) {
|
|
|
12038
12041
|
});
|
|
12039
12042
|
logger.info("auth.server", "Served success HTML");
|
|
12040
12043
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
12041
|
-
res.end(buildSuccessHtml(email ?? undefined, opts.successVariant ?? "auth"
|
|
12044
|
+
res.end(buildSuccessHtml(email ?? undefined, opts.successVariant ?? "auth"));
|
|
12042
12045
|
});
|
|
12043
12046
|
await new Promise((resolve) => {
|
|
12044
12047
|
httpServer.listen(0, "localhost", () => resolve());
|
|
@@ -12052,9 +12055,6 @@ async function startCallbackServer(opts = {}) {
|
|
|
12052
12055
|
close: () => {
|
|
12053
12056
|
httpServer.close();
|
|
12054
12057
|
httpServer.closeAllConnections?.();
|
|
12055
|
-
},
|
|
12056
|
-
setNext: (url) => {
|
|
12057
|
-
nextTarget = url;
|
|
12058
12058
|
}
|
|
12059
12059
|
},
|
|
12060
12060
|
tokenPromise
|
|
@@ -12149,11 +12149,9 @@ __export(exports_flow, {
|
|
|
12149
12149
|
});
|
|
12150
12150
|
async function startOAuthFlow(signal, path3 = "/cli/auth", params = {}, onAuthURL, options = {}) {
|
|
12151
12151
|
const { server, tokenPromise } = await startCallbackServer({
|
|
12152
|
-
nextHold: options.holdNext,
|
|
12153
12152
|
successVariant: options.successVariant
|
|
12154
12153
|
});
|
|
12155
12154
|
let timeoutId;
|
|
12156
|
-
let handedOver = false;
|
|
12157
12155
|
try {
|
|
12158
12156
|
const callbackURL = `http://localhost:${server.port}/callback`;
|
|
12159
12157
|
logger.debug("auth.flow", `Callback URL: ${callbackURL}`);
|
|
@@ -12161,29 +12159,26 @@ async function startOAuthFlow(signal, path3 = "/cli/auth", params = {}, onAuthUR
|
|
|
12161
12159
|
logger.info("auth.flow", `Auth URL: ${authURL}`);
|
|
12162
12160
|
options.onAuthURL?.(authURL);
|
|
12163
12161
|
let browserOpened = false;
|
|
12164
|
-
|
|
12162
|
+
const open2 = await Promise.resolve().then(() => (init_open(), exports_open));
|
|
12163
|
+
try {
|
|
12164
|
+
await open2.default(authURL);
|
|
12165
12165
|
browserOpened = true;
|
|
12166
|
-
logger.info("auth.flow", "Browser open
|
|
12167
|
-
|
|
12168
|
-
|
|
12169
|
-
|
|
12170
|
-
await open2.default(authURL);
|
|
12171
|
-
browserOpened = true;
|
|
12172
|
-
logger.info("auth.flow", "Browser open command executed");
|
|
12173
|
-
onAuthURL?.(authURL);
|
|
12174
|
-
} catch (openErr) {
|
|
12175
|
-
logger.warn("auth.flow", `Could not open browser automatically: ${openErr instanceof Error ? openErr.message : String(openErr)}`);
|
|
12176
|
-
}
|
|
12166
|
+
logger.info("auth.flow", "Browser open command executed");
|
|
12167
|
+
onAuthURL?.(authURL);
|
|
12168
|
+
} catch (openErr) {
|
|
12169
|
+
logger.warn("auth.flow", `Could not open browser automatically: ${openErr instanceof Error ? openErr.message : String(openErr)}`);
|
|
12177
12170
|
}
|
|
12178
12171
|
if (!browserOpened && !options.waitWithoutBrowser) {
|
|
12179
12172
|
logger.debug("auth.flow", "Browser unavailable — returning to caller for fallback");
|
|
12180
12173
|
return { browserOpened: false };
|
|
12181
12174
|
}
|
|
12175
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
12176
|
+
const timeoutMinutes = Math.round(timeoutMs / 60000);
|
|
12182
12177
|
const timeout = new Promise((_2, reject) => {
|
|
12183
12178
|
timeoutId = setTimeout(() => {
|
|
12184
|
-
logger.warn("auth.flow",
|
|
12185
|
-
reject(new Error(
|
|
12186
|
-
},
|
|
12179
|
+
logger.warn("auth.flow", `Authentication timed out (${timeoutMinutes}min)`);
|
|
12180
|
+
reject(new Error(`Authentication did not complete within ${timeoutMinutes} minutes. If you finished in the browser after the timeout, just re-run the command.`));
|
|
12181
|
+
}, timeoutMs);
|
|
12187
12182
|
});
|
|
12188
12183
|
const abort = signal ? new Promise((_2, reject) => {
|
|
12189
12184
|
signal.addEventListener("abort", () => {
|
|
@@ -12193,17 +12188,11 @@ async function startOAuthFlow(signal, path3 = "/cli/auth", params = {}, onAuthUR
|
|
|
12193
12188
|
}) : new Promise(() => {});
|
|
12194
12189
|
const token = await Promise.race([tokenPromise, timeout, abort]);
|
|
12195
12190
|
logger.info("auth.flow", "Token received");
|
|
12196
|
-
if (options.holdNext) {
|
|
12197
|
-
handedOver = true;
|
|
12198
|
-
return { browserOpened: true, token, server };
|
|
12199
|
-
}
|
|
12200
12191
|
return { browserOpened: true, token };
|
|
12201
12192
|
} finally {
|
|
12202
12193
|
clearTimeout(timeoutId);
|
|
12203
|
-
|
|
12204
|
-
|
|
12205
|
-
logger.debug("auth.flow", "Cleaning up: timeout cleared, server closed");
|
|
12206
|
-
}
|
|
12194
|
+
server.close();
|
|
12195
|
+
logger.debug("auth.flow", "Cleaning up: timeout cleared, server closed");
|
|
12207
12196
|
}
|
|
12208
12197
|
}
|
|
12209
12198
|
function buildAuthURL(callbackURL, path3, extraParams) {
|
|
@@ -12211,9 +12200,11 @@ function buildAuthURL(callbackURL, path3, extraParams) {
|
|
|
12211
12200
|
const params = new URLSearchParams({ callback: callbackURL, ...extraParams });
|
|
12212
12201
|
return `${webAppURL}${path3}?${params}`;
|
|
12213
12202
|
}
|
|
12203
|
+
var DEFAULT_TIMEOUT_MS;
|
|
12214
12204
|
var init_flow = __esm(() => {
|
|
12215
12205
|
init_logger();
|
|
12216
12206
|
init_server();
|
|
12207
|
+
DEFAULT_TIMEOUT_MS = 8 * 60 * 1000;
|
|
12217
12208
|
});
|
|
12218
12209
|
|
|
12219
12210
|
// src/setup/flow.ts
|
|
@@ -12223,8 +12214,7 @@ __export(exports_flow2, {
|
|
|
12223
12214
|
stepDetectTools: () => stepDetectTools,
|
|
12224
12215
|
stepConfigureTools: () => stepConfigureTools,
|
|
12225
12216
|
runSetup: () => runSetup,
|
|
12226
|
-
runInstallSkill: () => runInstallSkill
|
|
12227
|
-
isStdioOnly: () => isStdioOnly
|
|
12217
|
+
runInstallSkill: () => runInstallSkill
|
|
12228
12218
|
});
|
|
12229
12219
|
import { randomUUID } from "node:crypto";
|
|
12230
12220
|
async function runSetup(opts = {}) {
|
|
@@ -12245,11 +12235,6 @@ async function runSetup(opts = {}) {
|
|
|
12245
12235
|
if (!authed)
|
|
12246
12236
|
return;
|
|
12247
12237
|
cfg = authed.cfg;
|
|
12248
|
-
const authTab = authed.authTab;
|
|
12249
|
-
const releaseAuthTab = () => {
|
|
12250
|
-
authTab?.setNext(null);
|
|
12251
|
-
authTab?.close();
|
|
12252
|
-
};
|
|
12253
12238
|
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_auth_completed");
|
|
12254
12239
|
let apiClient = new Client(cfg);
|
|
12255
12240
|
let cloudSetupContext = null;
|
|
@@ -12262,36 +12247,41 @@ async function runSetup(opts = {}) {
|
|
|
12262
12247
|
reason: "cloud_setup_context_failed"
|
|
12263
12248
|
});
|
|
12264
12249
|
s.stop("Workspace load failed");
|
|
12265
|
-
releaseAuthTab();
|
|
12266
12250
|
return;
|
|
12267
12251
|
}
|
|
12268
12252
|
s.stop("Workspace loaded");
|
|
12269
12253
|
}
|
|
12270
12254
|
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_started", {
|
|
12271
|
-
flow_kind: cloudSetupContext
|
|
12255
|
+
flow_kind: cloudSetupContext ? cloudSetupContext.finishedOnboarding ? "setup" : "onboarding" : "oss"
|
|
12272
12256
|
});
|
|
12273
|
-
const
|
|
12274
|
-
if (
|
|
12275
|
-
|
|
12276
|
-
|
|
12277
|
-
if (firstRunOnboarding && cloudSetupContext) {
|
|
12278
|
-
const onboarded = await stepWebOnboarding(cfg, onboardingRunID, authTab);
|
|
12279
|
-
if (!onboarded) {
|
|
12257
|
+
const needsHandshake = cfg.mode !== MODE_OSS && cloudSetupContext !== null && !cloudSetupContext.finishedOnboarding && !opts.deploymentID;
|
|
12258
|
+
if (needsHandshake) {
|
|
12259
|
+
const handshook = await stepSetupHandshake(cfg, onboardingRunID);
|
|
12260
|
+
if (!handshook) {
|
|
12280
12261
|
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_failed", {
|
|
12281
12262
|
reason: "web_onboarding_incomplete"
|
|
12282
12263
|
});
|
|
12283
12264
|
return;
|
|
12284
12265
|
}
|
|
12285
12266
|
apiClient = new Client(cfg);
|
|
12286
|
-
const
|
|
12287
|
-
|
|
12288
|
-
if (!ok) {
|
|
12267
|
+
const refreshed = await resolveCloudSetupContext(cfg);
|
|
12268
|
+
if (refreshed === null) {
|
|
12289
12269
|
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_failed", {
|
|
12290
|
-
reason: "
|
|
12270
|
+
reason: "cloud_setup_context_failed"
|
|
12291
12271
|
});
|
|
12292
12272
|
return;
|
|
12293
12273
|
}
|
|
12294
|
-
|
|
12274
|
+
if (!refreshed.finishedOnboarding) {
|
|
12275
|
+
log.warn("Your account still needs onboarding. Finish it in the browser at the Dosu app, then re-run `dosu setup`.");
|
|
12276
|
+
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_failed", {
|
|
12277
|
+
reason: "onboarding_incomplete_after_handshake"
|
|
12278
|
+
});
|
|
12279
|
+
process.exitCode = 1;
|
|
12280
|
+
return;
|
|
12281
|
+
}
|
|
12282
|
+
cloudSetupContext = refreshed;
|
|
12283
|
+
}
|
|
12284
|
+
if (!cfg.active_account?.target?.deployment_id || opts.deploymentID) {
|
|
12295
12285
|
const ok = await resolveDeployment(apiClient, cfg, opts);
|
|
12296
12286
|
if (!ok) {
|
|
12297
12287
|
await trackCliOnboardingEvent(cfg, onboardingRunID, "cli_onboarding_failed", {
|
|
@@ -12466,9 +12456,13 @@ async function openBrowserForSetup(cfg, onboardingRunID) {
|
|
|
12466
12456
|
try {
|
|
12467
12457
|
const { startOAuthFlow: startOAuthFlow2 } = await Promise.resolve().then(() => (init_flow(), exports_flow));
|
|
12468
12458
|
const s = spinner();
|
|
12469
|
-
const
|
|
12459
|
+
const isCloud = cfg.mode !== MODE_OSS;
|
|
12460
|
+
const result = await startOAuthFlow2(undefined, "/cli/auth", {
|
|
12461
|
+
...isCloud ? { intent: "setup" } : {},
|
|
12462
|
+
...onboardingRunID ? { onboarding_run_id: onboardingRunID } : {}
|
|
12463
|
+
}, undefined, {
|
|
12470
12464
|
waitWithoutBrowser: true,
|
|
12471
|
-
|
|
12465
|
+
...isCloud ? { timeoutMs: SETUP_HANDSHAKE_TIMEOUT_MS } : {},
|
|
12472
12466
|
onAuthURL: (url) => {
|
|
12473
12467
|
log.message(browserFallbackHint(url));
|
|
12474
12468
|
s.start("Waiting for authentication...");
|
|
@@ -12479,7 +12473,7 @@ async function openBrowserForSetup(cfg, onboardingRunID) {
|
|
|
12479
12473
|
return null;
|
|
12480
12474
|
}
|
|
12481
12475
|
const token = result.token;
|
|
12482
|
-
s.stop("Authenticated");
|
|
12476
|
+
s.stop(token.email ? `Authenticated as ${token.email}` : "Authenticated");
|
|
12483
12477
|
logger.info("setup", "Browser auth completed");
|
|
12484
12478
|
replaceLoginSession(cfg, {
|
|
12485
12479
|
access_token: token.access_token,
|
|
@@ -12487,7 +12481,7 @@ async function openBrowserForSetup(cfg, onboardingRunID) {
|
|
|
12487
12481
|
expires_at: Math.floor(Date.now() / 1000) + token.expires_in
|
|
12488
12482
|
});
|
|
12489
12483
|
saveConfig(cfg);
|
|
12490
|
-
return { cfg
|
|
12484
|
+
return { cfg };
|
|
12491
12485
|
} catch (err) {
|
|
12492
12486
|
const msg = err instanceof Error ? err.stack ?? err.message : String(err);
|
|
12493
12487
|
logger.error("setup", `Auth failed: ${msg}`);
|
|
@@ -12510,20 +12504,19 @@ async function openBrowserForSetup(cfg, onboardingRunID) {
|
|
|
12510
12504
|
return null;
|
|
12511
12505
|
}
|
|
12512
12506
|
}
|
|
12513
|
-
async function
|
|
12514
|
-
logger.info("setup", "Step:
|
|
12515
|
-
log.info("Almost there —
|
|
12507
|
+
async function stepSetupHandshake(cfg, onboardingRunID) {
|
|
12508
|
+
logger.info("setup", "Step: setup handshake");
|
|
12509
|
+
log.info("Almost there — finish setting up in the browser and we'll pick up from here.");
|
|
12516
12510
|
const s = spinner();
|
|
12517
12511
|
try {
|
|
12518
12512
|
const { startOAuthFlow: startOAuthFlow2 } = await Promise.resolve().then(() => (init_flow(), exports_flow));
|
|
12519
|
-
const result = await startOAuthFlow2(undefined, "/
|
|
12513
|
+
const result = await startOAuthFlow2(undefined, "/cli/auth", { intent: "setup", onboarding_run_id: onboardingRunID }, undefined, {
|
|
12520
12514
|
waitWithoutBrowser: true,
|
|
12521
|
-
suppressBrowserOpen: Boolean(authTab),
|
|
12522
12515
|
successVariant: "onboarding",
|
|
12516
|
+
timeoutMs: SETUP_HANDSHAKE_TIMEOUT_MS,
|
|
12523
12517
|
onAuthURL: (url) => {
|
|
12524
|
-
authTab?.setNext(url);
|
|
12525
12518
|
log.message(browserFallbackHint(url));
|
|
12526
|
-
s.start("Waiting for
|
|
12519
|
+
s.start("Waiting for the browser...");
|
|
12527
12520
|
}
|
|
12528
12521
|
});
|
|
12529
12522
|
if (!result.browserOpened) {
|
|
@@ -12536,17 +12529,20 @@ async function stepWebOnboarding(cfg, onboardingRunID, authTab) {
|
|
|
12536
12529
|
expires_at: Math.floor(Date.now() / 1000) + result.token.expires_in
|
|
12537
12530
|
});
|
|
12538
12531
|
saveConfig(cfg);
|
|
12539
|
-
s.stop(
|
|
12540
|
-
logger.info("setup", "
|
|
12532
|
+
s.stop(result.token.email ? `Authenticated as ${result.token.email}` : "Browser setup finished");
|
|
12533
|
+
logger.info("setup", "Setup handshake completed");
|
|
12541
12534
|
return true;
|
|
12542
12535
|
} catch (err) {
|
|
12543
12536
|
const msg = err instanceof Error ? err.message : String(err);
|
|
12544
|
-
logger.warn("setup", `
|
|
12545
|
-
s.stop("
|
|
12546
|
-
|
|
12537
|
+
logger.warn("setup", `Setup handshake did not complete: ${msg}`);
|
|
12538
|
+
s.stop("Setup not completed");
|
|
12539
|
+
const { OAuthCallbackError: OAuthCallbackError2 } = await Promise.resolve().then(() => (init_errors(), exports_errors));
|
|
12540
|
+
if (err instanceof OAuthCallbackError2) {
|
|
12541
|
+
log.error(err.userMessage);
|
|
12542
|
+
return false;
|
|
12543
|
+
}
|
|
12544
|
+
log.warn("Didn't hear back from the browser. If it opened the Dosu app instead of the setup " + "wizard, your CLI and browser may be signed in to different accounts — run " + "`dosu logout`, then retry. Otherwise finish in the browser and re-run `dosu setup`.");
|
|
12547
12545
|
return false;
|
|
12548
|
-
} finally {
|
|
12549
|
-
authTab?.close();
|
|
12550
12546
|
}
|
|
12551
12547
|
}
|
|
12552
12548
|
async function resolveCloudSetupContext(cfg) {
|
|
@@ -12560,22 +12556,9 @@ async function resolveCloudSetupContext(cfg) {
|
|
|
12560
12556
|
}
|
|
12561
12557
|
bindAccountIdentity(cfg, profile.user_id);
|
|
12562
12558
|
saveConfig(cfg);
|
|
12563
|
-
if (profile.finished_onboarding === true) {
|
|
12564
|
-
return {
|
|
12565
|
-
kind: "setup",
|
|
12566
|
-
profileUserID: profile.user_id
|
|
12567
|
-
};
|
|
12568
|
-
}
|
|
12569
|
-
const targetOrg = await resolveOnboardingTargetOrg(trpc);
|
|
12570
|
-
if (!targetOrg) {
|
|
12571
|
-
log.error("Could not determine your onboarding organization.");
|
|
12572
|
-
return null;
|
|
12573
|
-
}
|
|
12574
|
-
logger.info("setup", `First-run onboarding detected for org ${targetOrg.org_id}`);
|
|
12575
12559
|
return {
|
|
12576
|
-
kind: "onboarding",
|
|
12577
12560
|
profileUserID: profile.user_id,
|
|
12578
|
-
|
|
12561
|
+
finishedOnboarding: profile.finished_onboarding === true
|
|
12579
12562
|
};
|
|
12580
12563
|
} catch (err) {
|
|
12581
12564
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -12584,53 +12567,6 @@ async function resolveCloudSetupContext(cfg) {
|
|
|
12584
12567
|
return null;
|
|
12585
12568
|
}
|
|
12586
12569
|
}
|
|
12587
|
-
async function resolveOnboardingTargetOrg(trpc) {
|
|
12588
|
-
const accessibleOrgs = await trpc.organization.getOrganizations.query();
|
|
12589
|
-
const ownerOrg = accessibleOrgs.find((org) => org.user_role === "OWNER");
|
|
12590
|
-
if (ownerOrg) {
|
|
12591
|
-
return ownerOrg;
|
|
12592
|
-
}
|
|
12593
|
-
return accessibleOrgs[0] ?? null;
|
|
12594
|
-
}
|
|
12595
|
-
async function resolveCurrentOnboardingTargetOrg(cfg) {
|
|
12596
|
-
try {
|
|
12597
|
-
const { createTypedClient: createTypedClient2 } = await Promise.resolve().then(() => (init_trpc(), exports_trpc));
|
|
12598
|
-
const trpc = createTypedClient2(cfg);
|
|
12599
|
-
const profile = await trpc.user.getCliOnboardingContext.query();
|
|
12600
|
-
if (!profile?.user_id)
|
|
12601
|
-
return null;
|
|
12602
|
-
bindAccountIdentity(cfg, profile.user_id);
|
|
12603
|
-
saveConfig(cfg);
|
|
12604
|
-
return await resolveOnboardingTargetOrg(trpc);
|
|
12605
|
-
} catch (err) {
|
|
12606
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
12607
|
-
logger.error("setup", `Failed to resolve post-onboarding organization: ${msg}`);
|
|
12608
|
-
log.error(`Could not determine your onboarding organization: ${msg}`);
|
|
12609
|
-
return null;
|
|
12610
|
-
}
|
|
12611
|
-
}
|
|
12612
|
-
async function bindOnboardingDeployment(apiClient, cfg, targetOrg) {
|
|
12613
|
-
if (!targetOrg) {
|
|
12614
|
-
log.error("Could not determine your onboarding organization.");
|
|
12615
|
-
return false;
|
|
12616
|
-
}
|
|
12617
|
-
const deployment = await resolveOnboardingDeployment(apiClient, targetOrg);
|
|
12618
|
-
if (!deployment) {
|
|
12619
|
-
log.error(`No MCP found for ${targetOrg.name}.`);
|
|
12620
|
-
return false;
|
|
12621
|
-
}
|
|
12622
|
-
cfg.mode = undefined;
|
|
12623
|
-
applyDeployment(cfg, deployment);
|
|
12624
|
-
logger.info("setup", `Bound onboarding context org=${targetOrg.org_id} deployment=${deployment.deployment_id}`);
|
|
12625
|
-
log.success(`Organization
|
|
12626
|
-
${dim(targetOrg.name)}`);
|
|
12627
|
-
return true;
|
|
12628
|
-
}
|
|
12629
|
-
async function resolveOnboardingDeployment(apiClient, targetOrg) {
|
|
12630
|
-
const deployments = await fetchDeployments(apiClient);
|
|
12631
|
-
const orgDeployments = deployments.filter((deployment) => deployment.org_id === targetOrg.org_id);
|
|
12632
|
-
return orgDeployments.find((deployment) => deployment.provider_slug === MCP_PROVIDER_SLUG) ?? orgDeployments[0] ?? null;
|
|
12633
|
-
}
|
|
12634
12570
|
async function resolveDeployment(apiClient, cfg, opts) {
|
|
12635
12571
|
if (opts.deploymentID) {
|
|
12636
12572
|
const d2 = await stepResolveDeployment(apiClient, opts.deploymentID);
|
|
@@ -12728,6 +12664,13 @@ async function stepSelectDeployment(apiClient, org) {
|
|
|
12728
12664
|
${dim(deployments[0].name)}`);
|
|
12729
12665
|
return deployments[0];
|
|
12730
12666
|
}
|
|
12667
|
+
const mcpDeployments = deployments.filter((d2) => d2.provider_slug === MCP_PROVIDER_SLUG);
|
|
12668
|
+
if (mcpDeployments.length === 1) {
|
|
12669
|
+
logger.info("setup", `Selected deployment: ${mcpDeployments[0].name} (auto, single MCP)`);
|
|
12670
|
+
log.success(`Using MCP
|
|
12671
|
+
${dim(mcpDeployments[0].name)}`);
|
|
12672
|
+
return mcpDeployments[0];
|
|
12673
|
+
}
|
|
12731
12674
|
const selected = await select({
|
|
12732
12675
|
message: "Select an MCP",
|
|
12733
12676
|
options: deployments.map((d2) => ({ label: d2.name, value: d2.deployment_id }))
|
|
@@ -12771,11 +12714,8 @@ ${dim("created")}`);
|
|
|
12771
12714
|
return null;
|
|
12772
12715
|
}
|
|
12773
12716
|
}
|
|
12774
|
-
function isStdioOnly(p2) {
|
|
12775
|
-
return p2.id() === "claude-desktop";
|
|
12776
|
-
}
|
|
12777
12717
|
function stepDetectTools() {
|
|
12778
|
-
return allSetupProviders().filter((p2) => p2.isInstalled()
|
|
12718
|
+
return allSetupProviders().filter((p2) => p2.isInstalled());
|
|
12779
12719
|
}
|
|
12780
12720
|
async function stepSelectTools(detected) {
|
|
12781
12721
|
const configuredMap = new Map;
|
|
@@ -12861,6 +12801,7 @@ function stepShowSummary(results) {
|
|
|
12861
12801
|
log.success("All agents already configured. No changes needed.");
|
|
12862
12802
|
}
|
|
12863
12803
|
}
|
|
12804
|
+
var SETUP_HANDSHAKE_TIMEOUT_MS = 1800000;
|
|
12864
12805
|
var init_flow2 = __esm(() => {
|
|
12865
12806
|
init_dist8();
|
|
12866
12807
|
init_client();
|
|
@@ -12877,7 +12818,7 @@ var init_flow2 = __esm(() => {
|
|
|
12877
12818
|
|
|
12878
12819
|
// src/commands/insights.ts
|
|
12879
12820
|
import { existsSync as existsSync18, mkdirSync as mkdirSync9, readdirSync, unlinkSync as unlinkSync2, writeFileSync as writeFileSync9 } from "node:fs";
|
|
12880
|
-
import { dirname as
|
|
12821
|
+
import { dirname as dirname7, join as join29 } from "node:path";
|
|
12881
12822
|
function shuffled(arr) {
|
|
12882
12823
|
const copy2 = [...arr];
|
|
12883
12824
|
for (let i2 = copy2.length - 1;i2 > 0; i2--) {
|
|
@@ -13075,7 +13016,7 @@ function defaultRunner(cfg) {
|
|
|
13075
13016
|
build: buildInsights,
|
|
13076
13017
|
render: renderHTML,
|
|
13077
13018
|
writeFile: (path3, content) => {
|
|
13078
|
-
const dir =
|
|
13019
|
+
const dir = dirname7(path3);
|
|
13079
13020
|
if (!existsSync18(dir))
|
|
13080
13021
|
mkdirSync9(dir, { recursive: true, mode: 448 });
|
|
13081
13022
|
writeFileSync9(path3, content, { mode: 384 });
|
|
@@ -13519,7 +13460,7 @@ __export(exports_flow3, {
|
|
|
13519
13460
|
async function runAgentSetup(opts) {
|
|
13520
13461
|
const provider = allSetupProviders().find((p2) => p2.id() === opts.tool.toLowerCase());
|
|
13521
13462
|
if (!provider) {
|
|
13522
|
-
const available = allSetupProviders().
|
|
13463
|
+
const available = allSetupProviders().map((p2) => p2.id()).join(", ");
|
|
13523
13464
|
emitError({
|
|
13524
13465
|
step: "setup",
|
|
13525
13466
|
reason: "unknown_tool",
|
|
@@ -13527,14 +13468,6 @@ async function runAgentSetup(opts) {
|
|
|
13527
13468
|
});
|
|
13528
13469
|
return 2;
|
|
13529
13470
|
}
|
|
13530
|
-
if (isStdioOnly(provider)) {
|
|
13531
|
-
emitError({
|
|
13532
|
-
step: "setup",
|
|
13533
|
-
reason: "tool_unsupported_in_agent_mode",
|
|
13534
|
-
agent_next_steps: `${provider.name()} is not supported by agent setup. Tell the user to run 'dosu mcp add ${provider.id()}' manually after signing in.`
|
|
13535
|
-
});
|
|
13536
|
-
return 2;
|
|
13537
|
-
}
|
|
13538
13471
|
let cfg = loadConfig();
|
|
13539
13472
|
if (opts.loginTicket) {
|
|
13540
13473
|
const redeemed = await redeemTicket(opts.loginTicket, cfg);
|
|
@@ -13764,7 +13697,7 @@ async function resolveDeployment2(client, cfg, opts) {
|
|
|
13764
13697
|
emitError({
|
|
13765
13698
|
step: "deployment",
|
|
13766
13699
|
reason: "no_deployments",
|
|
13767
|
-
agent_next_steps: "No Dosu deployments are accessible to this account.
|
|
13700
|
+
agent_next_steps: "No Dosu deployments are accessible to this account. The CLI may be signed in to a " + "different account than the user expects — have them run 'dosu logout' and retry, or " + "create a deployment at https://app.dosu.dev before retrying."
|
|
13768
13701
|
});
|
|
13769
13702
|
return { code: 1, cfg };
|
|
13770
13703
|
}
|
|
@@ -13773,7 +13706,7 @@ async function resolveDeployment2(client, cfg, opts) {
|
|
|
13773
13706
|
emitError({
|
|
13774
13707
|
step: "deployment",
|
|
13775
13708
|
reason: "no_mcp_deployment",
|
|
13776
|
-
agent_next_steps: "Account has deployments but none of them back an MCP server.
|
|
13709
|
+
agent_next_steps: "Account has deployments but none of them back an MCP server. The CLI may be signed in " + "to a different account than the user expects — have them run 'dosu logout' and retry, " + "create an MCP deployment at https://app.dosu.dev, or pass --deployment <id> to target " + "a specific deployment."
|
|
13777
13710
|
});
|
|
13778
13711
|
return { code: 1, cfg };
|
|
13779
13712
|
}
|
|
@@ -13862,7 +13795,7 @@ function buildResumeCommand(tool, ticket, deploymentID) {
|
|
|
13862
13795
|
return parts.join(" ");
|
|
13863
13796
|
}
|
|
13864
13797
|
function listAgentSupportedToolIDs() {
|
|
13865
|
-
return allSetupProviders().
|
|
13798
|
+
return allSetupProviders().map((p2) => p2.id());
|
|
13866
13799
|
}
|
|
13867
13800
|
var NPX_INVOCATION = "npx @dosu/cli@latest";
|
|
13868
13801
|
var init_flow3 = __esm(() => {
|
|
@@ -13874,7 +13807,6 @@ var init_flow3 = __esm(() => {
|
|
|
13874
13807
|
init_providers();
|
|
13875
13808
|
init_installer();
|
|
13876
13809
|
init_agents_md_step();
|
|
13877
|
-
init_flow2();
|
|
13878
13810
|
});
|
|
13879
13811
|
|
|
13880
13812
|
// src/cli/cli.ts
|