@dosu/cli 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/dosu.js +86 -23
- package/package.json +1 -1
package/bin/dosu.js
CHANGED
|
@@ -2115,6 +2115,7 @@ function emptyConfig() {
|
|
|
2115
2115
|
expires_at: 0
|
|
2116
2116
|
};
|
|
2117
2117
|
}
|
|
2118
|
+
var MODE_OSS = "oss";
|
|
2118
2119
|
var init_config = () => {};
|
|
2119
2120
|
|
|
2120
2121
|
// src/config/constants.ts
|
|
@@ -2137,6 +2138,9 @@ import { dirname } from "node:path";
|
|
|
2137
2138
|
function mcpURL(deploymentID) {
|
|
2138
2139
|
return `${getBackendURL()}/v1/mcp/deployments/${deploymentID}`;
|
|
2139
2140
|
}
|
|
2141
|
+
function mcpBaseURL() {
|
|
2142
|
+
return `${getBackendURL()}/v1/mcp`;
|
|
2143
|
+
}
|
|
2140
2144
|
function mcpHeaders(apiKey) {
|
|
2141
2145
|
return { "X-Dosu-API-Key": apiKey };
|
|
2142
2146
|
}
|
|
@@ -2277,6 +2281,11 @@ function createJSONProvider(opts) {
|
|
|
2277
2281
|
url: mcpURL(cfg.deployment_id),
|
|
2278
2282
|
headers: mcpHeaders(cfg.api_key)
|
|
2279
2283
|
});
|
|
2284
|
+
const defaultBuildOSSServer = (cfg) => ({
|
|
2285
|
+
type: "http",
|
|
2286
|
+
url: mcpBaseURL(),
|
|
2287
|
+
headers: mcpHeaders(cfg.api_key)
|
|
2288
|
+
});
|
|
2280
2289
|
const buildServer = opts.buildServer ?? defaultBuildServer;
|
|
2281
2290
|
return {
|
|
2282
2291
|
name: () => opts.providerName,
|
|
@@ -2288,7 +2297,7 @@ function createJSONProvider(opts) {
|
|
|
2288
2297
|
globalConfigPath: () => expandHome(opts.globalPath),
|
|
2289
2298
|
isConfigured: () => isJSONKeyConfigured(expandHome(opts.globalPath), opts.topKey),
|
|
2290
2299
|
install(cfg, global) {
|
|
2291
|
-
if (!cfg.deployment_id)
|
|
2300
|
+
if (cfg.mode !== MODE_OSS && !cfg.deployment_id)
|
|
2292
2301
|
throw new Error("deployment ID is required");
|
|
2293
2302
|
let configPath;
|
|
2294
2303
|
if (global) {
|
|
@@ -2298,7 +2307,8 @@ function createJSONProvider(opts) {
|
|
|
2298
2307
|
} else {
|
|
2299
2308
|
throw new Error(`${opts.providerName} does not support local installation`);
|
|
2300
2309
|
}
|
|
2301
|
-
|
|
2310
|
+
const serverBuilder = cfg.mode === MODE_OSS ? defaultBuildOSSServer : buildServer;
|
|
2311
|
+
installJSONServer(configPath, opts.topKey, serverBuilder(cfg));
|
|
2302
2312
|
},
|
|
2303
2313
|
remove(global) {
|
|
2304
2314
|
let configPath;
|
|
@@ -2314,6 +2324,7 @@ function createJSONProvider(opts) {
|
|
|
2314
2324
|
};
|
|
2315
2325
|
}
|
|
2316
2326
|
var init_base = __esm(() => {
|
|
2327
|
+
init_config();
|
|
2317
2328
|
init_config_helpers();
|
|
2318
2329
|
init_detect();
|
|
2319
2330
|
});
|
|
@@ -3626,7 +3637,7 @@ class Client {
|
|
|
3626
3637
|
options.body = JSON.stringify(body);
|
|
3627
3638
|
}
|
|
3628
3639
|
const controller = new AbortController;
|
|
3629
|
-
const timeout = setTimeout(() => controller.abort(),
|
|
3640
|
+
const timeout = setTimeout(() => controller.abort(), 1e4);
|
|
3630
3641
|
options.signal = controller.signal;
|
|
3631
3642
|
try {
|
|
3632
3643
|
return await fetch(url, options);
|
|
@@ -3864,6 +3875,7 @@ async function startCallbackServer() {
|
|
|
3864
3875
|
const refreshToken = url.searchParams.get("refresh_token");
|
|
3865
3876
|
const expiresIn = url.searchParams.get("expires_in");
|
|
3866
3877
|
const email = url.searchParams.get("email");
|
|
3878
|
+
const mode = url.searchParams.get("mode");
|
|
3867
3879
|
if (!accessToken) {
|
|
3868
3880
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
3869
3881
|
res.end(CALLBACK_HTML_EXTRACT);
|
|
@@ -3879,7 +3891,8 @@ async function startCallbackServer() {
|
|
|
3879
3891
|
access_token: accessToken,
|
|
3880
3892
|
refresh_token: refreshToken && refreshToken !== "null" ? refreshToken : "",
|
|
3881
3893
|
expires_in: expiresInInt,
|
|
3882
|
-
email: email ?? undefined
|
|
3894
|
+
email: email ?? undefined,
|
|
3895
|
+
...mode === MODE_OSS && { mode: MODE_OSS }
|
|
3883
3896
|
});
|
|
3884
3897
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
3885
3898
|
res.end(buildSuccessHtml(email ?? undefined));
|
|
@@ -3961,6 +3974,9 @@ if (hash) {
|
|
|
3961
3974
|
</script>
|
|
3962
3975
|
</body>
|
|
3963
3976
|
</html>`;
|
|
3977
|
+
var init_server = __esm(() => {
|
|
3978
|
+
init_config();
|
|
3979
|
+
});
|
|
3964
3980
|
|
|
3965
3981
|
// node_modules/is-docker/index.js
|
|
3966
3982
|
import fs from "node:fs";
|
|
@@ -4507,16 +4523,16 @@ var exports_flow = {};
|
|
|
4507
4523
|
__export(exports_flow, {
|
|
4508
4524
|
startOAuthFlow: () => startOAuthFlow
|
|
4509
4525
|
});
|
|
4510
|
-
async function startOAuthFlow(signal) {
|
|
4526
|
+
async function startOAuthFlow(signal, path2 = "/cli/auth") {
|
|
4511
4527
|
const { server, tokenPromise } = await startCallbackServer();
|
|
4512
4528
|
let timeoutId;
|
|
4513
4529
|
try {
|
|
4514
4530
|
const callbackURL = `http://localhost:${server.port}/callback`;
|
|
4515
|
-
const authURL = buildAuthURL(callbackURL);
|
|
4531
|
+
const authURL = buildAuthURL(callbackURL, path2);
|
|
4516
4532
|
const open2 = await Promise.resolve().then(() => (init_open(), exports_open));
|
|
4517
4533
|
await open2.default(authURL);
|
|
4518
4534
|
const timeout = new Promise((_3, reject) => {
|
|
4519
|
-
timeoutId = setTimeout(() => reject(new Error("authentication timeout - please try again")),
|
|
4535
|
+
timeoutId = setTimeout(() => reject(new Error("authentication timeout - please try again")), 900000);
|
|
4520
4536
|
});
|
|
4521
4537
|
const abort = signal ? new Promise((_3, reject) => {
|
|
4522
4538
|
signal.addEventListener("abort", () => reject(new Error("authentication cancelled")));
|
|
@@ -4527,12 +4543,17 @@ async function startOAuthFlow(signal) {
|
|
|
4527
4543
|
server.close();
|
|
4528
4544
|
}
|
|
4529
4545
|
}
|
|
4530
|
-
function buildAuthURL(callbackURL) {
|
|
4546
|
+
function buildAuthURL(callbackURL, path2) {
|
|
4531
4547
|
const webAppURL = getWebAppURL();
|
|
4532
4548
|
const params = new URLSearchParams({ callback: callbackURL });
|
|
4533
|
-
|
|
4549
|
+
if (path2 !== "/cli/auth") {
|
|
4550
|
+
params.set("redirect", `${path2}?callback=${encodeURIComponent(callbackURL)}`);
|
|
4551
|
+
}
|
|
4552
|
+
return `${webAppURL}${path2}?${params}`;
|
|
4534
4553
|
}
|
|
4535
|
-
var init_flow = () => {
|
|
4554
|
+
var init_flow = __esm(() => {
|
|
4555
|
+
init_server();
|
|
4556
|
+
});
|
|
4536
4557
|
|
|
4537
4558
|
// src/setup/flow.ts
|
|
4538
4559
|
var exports_flow2 = {};
|
|
@@ -4545,16 +4566,22 @@ __export(exports_flow2, {
|
|
|
4545
4566
|
});
|
|
4546
4567
|
async function runSetup(opts = {}) {
|
|
4547
4568
|
Ie("Dosu CLI Setup");
|
|
4548
|
-
const cfg = await stepAuthenticate();
|
|
4569
|
+
const cfg = await stepAuthenticate(opts);
|
|
4549
4570
|
if (!cfg)
|
|
4550
4571
|
return;
|
|
4551
4572
|
const apiClient = new Client(cfg);
|
|
4552
|
-
let deployment;
|
|
4553
4573
|
if (opts.deploymentID) {
|
|
4554
4574
|
const d3 = await stepResolveDeployment(apiClient, opts.deploymentID);
|
|
4555
4575
|
if (!d3)
|
|
4556
4576
|
return;
|
|
4557
|
-
|
|
4577
|
+
cfg.deployment_id = d3.deployment_id;
|
|
4578
|
+
cfg.deployment_name = d3.name;
|
|
4579
|
+
} else if (cfg.mode === MODE_OSS) {
|
|
4580
|
+
const deployments = await fetchDeployments(apiClient);
|
|
4581
|
+
if (deployments.length > 0) {
|
|
4582
|
+
cfg.deployment_id = deployments[0].deployment_id;
|
|
4583
|
+
cfg.deployment_name = deployments[0].name;
|
|
4584
|
+
}
|
|
4558
4585
|
} else {
|
|
4559
4586
|
const org = await stepSelectOrg(apiClient);
|
|
4560
4587
|
if (!org)
|
|
@@ -4562,10 +4589,9 @@ async function runSetup(opts = {}) {
|
|
|
4562
4589
|
const d3 = await stepSelectDeployment(apiClient, org);
|
|
4563
4590
|
if (!d3)
|
|
4564
4591
|
return;
|
|
4565
|
-
|
|
4592
|
+
cfg.deployment_id = d3.deployment_id;
|
|
4593
|
+
cfg.deployment_name = d3.name;
|
|
4566
4594
|
}
|
|
4567
|
-
cfg.deployment_id = deployment.deployment_id;
|
|
4568
|
-
cfg.deployment_name = deployment.name;
|
|
4569
4595
|
saveConfig(cfg);
|
|
4570
4596
|
const apiKey = await stepMintAPIKey(apiClient, cfg);
|
|
4571
4597
|
if (!apiKey)
|
|
@@ -4582,10 +4608,14 @@ Run ${info("dosu mcp add <tool>")} to manually configure a tool.`);
|
|
|
4582
4608
|
if (!selection)
|
|
4583
4609
|
return;
|
|
4584
4610
|
const results = stepConfigureTools(cfg, selection);
|
|
4585
|
-
stepShowSummary(results);
|
|
4586
|
-
|
|
4611
|
+
stepShowSummary(results, cfg.mode);
|
|
4612
|
+
if (cfg.mode === MODE_OSS) {
|
|
4613
|
+
Se("Setup complete! Using open-source libraries only.\nRun `dosu setup` again to connect your own repos.");
|
|
4614
|
+
} else {
|
|
4615
|
+
Se("\uD83C\uDF89 Setup complete!");
|
|
4616
|
+
}
|
|
4587
4617
|
}
|
|
4588
|
-
async function stepAuthenticate() {
|
|
4618
|
+
async function stepAuthenticate(opts) {
|
|
4589
4619
|
const cfg = loadConfig();
|
|
4590
4620
|
if (cfg.access_token) {
|
|
4591
4621
|
const s = Y2();
|
|
@@ -4595,6 +4625,21 @@ async function stepAuthenticate() {
|
|
|
4595
4625
|
const resp = await apiClient.doRequestRaw("GET", "/v1/mcp/deployments");
|
|
4596
4626
|
if (resp.status === 200) {
|
|
4597
4627
|
s.stop("Authenticated");
|
|
4628
|
+
if (!opts.deploymentID && cfg.mode === MODE_OSS) {
|
|
4629
|
+
const modeLabel = "open-source libraries only";
|
|
4630
|
+
const action = await ve({
|
|
4631
|
+
message: `Currently configured for ${modeLabel}. What would you like to do?`,
|
|
4632
|
+
options: [
|
|
4633
|
+
{ label: "Reconfigure (opens browser)", value: "reconfigure" },
|
|
4634
|
+
{ label: "Keep current setup and update tools", value: "keep" }
|
|
4635
|
+
]
|
|
4636
|
+
});
|
|
4637
|
+
if (pD(action))
|
|
4638
|
+
return null;
|
|
4639
|
+
if (action === "keep")
|
|
4640
|
+
return cfg;
|
|
4641
|
+
return await openBrowserForSetup(cfg, opts);
|
|
4642
|
+
}
|
|
4598
4643
|
return cfg;
|
|
4599
4644
|
}
|
|
4600
4645
|
try {
|
|
@@ -4614,15 +4659,21 @@ async function stepAuthenticate() {
|
|
|
4614
4659
|
const shouldLogin = await ye({ message: "Open browser to log in?" });
|
|
4615
4660
|
if (pD(shouldLogin) || !shouldLogin)
|
|
4616
4661
|
return null;
|
|
4662
|
+
return await openBrowserForSetup(cfg, opts);
|
|
4663
|
+
}
|
|
4664
|
+
async function openBrowserForSetup(cfg, opts) {
|
|
4617
4665
|
try {
|
|
4618
4666
|
const { startOAuthFlow: startOAuthFlow2 } = await Promise.resolve().then(() => (init_flow(), exports_flow));
|
|
4619
4667
|
const s = Y2();
|
|
4620
4668
|
s.start("Waiting for authentication...");
|
|
4621
|
-
const
|
|
4669
|
+
const authPath = opts.deploymentID ? "/cli/auth" : "/cli/setup";
|
|
4670
|
+
const token = await startOAuthFlow2(undefined, authPath);
|
|
4622
4671
|
s.stop("Authenticated");
|
|
4623
4672
|
cfg.access_token = token.access_token;
|
|
4624
4673
|
cfg.refresh_token = token.refresh_token;
|
|
4625
4674
|
cfg.expires_at = Math.floor(Date.now() / 1000) + token.expires_in;
|
|
4675
|
+
if (token.mode === MODE_OSS)
|
|
4676
|
+
cfg.mode = MODE_OSS;
|
|
4626
4677
|
saveConfig(cfg);
|
|
4627
4678
|
return cfg;
|
|
4628
4679
|
} catch (err) {
|
|
@@ -4630,6 +4681,13 @@ async function stepAuthenticate() {
|
|
|
4630
4681
|
return null;
|
|
4631
4682
|
}
|
|
4632
4683
|
}
|
|
4684
|
+
async function fetchDeployments(apiClient) {
|
|
4685
|
+
try {
|
|
4686
|
+
return await apiClient.getDeployments();
|
|
4687
|
+
} catch {
|
|
4688
|
+
return [];
|
|
4689
|
+
}
|
|
4690
|
+
}
|
|
4633
4691
|
async function stepSelectOrg(apiClient) {
|
|
4634
4692
|
try {
|
|
4635
4693
|
const orgs = await apiClient.getOrgs();
|
|
@@ -4700,6 +4758,10 @@ ${dim(deployments[0].name)}`);
|
|
|
4700
4758
|
}
|
|
4701
4759
|
}
|
|
4702
4760
|
async function stepMintAPIKey(apiClient, cfg) {
|
|
4761
|
+
if (!cfg.deployment_id) {
|
|
4762
|
+
M2.error("No deployment available for API key creation");
|
|
4763
|
+
return null;
|
|
4764
|
+
}
|
|
4703
4765
|
if (cfg.api_key) {
|
|
4704
4766
|
const valid = await apiClient.validateAPIKey(cfg.api_key, cfg.deployment_id);
|
|
4705
4767
|
if (valid) {
|
|
@@ -4787,7 +4849,7 @@ function stepConfigureTools(cfg, selection) {
|
|
|
4787
4849
|
}
|
|
4788
4850
|
return results;
|
|
4789
4851
|
}
|
|
4790
|
-
function stepShowSummary(results) {
|
|
4852
|
+
function stepShowSummary(results, mode) {
|
|
4791
4853
|
const installed = results.filter((r) => r.action === "install" && !r.error);
|
|
4792
4854
|
const removed = results.filter((r) => r.action === "remove" && !r.error);
|
|
4793
4855
|
const skipped = results.filter((r) => r.action === "skip");
|
|
@@ -4809,9 +4871,10 @@ ${lines}`);
|
|
|
4809
4871
|
M2.success("All tools already configured. No changes needed.");
|
|
4810
4872
|
}
|
|
4811
4873
|
if (installed.length > 0 || skipped.length > 0) {
|
|
4874
|
+
const prompt = mode === MODE_OSS ? `What can I do with the Dosu MCP?` : `Use Dosu to search our team's documentation and answer: what are the main components of our system?`;
|
|
4812
4875
|
M2.message(`Try it out! Paste this into your agent:
|
|
4813
4876
|
|
|
4814
|
-
|
|
4877
|
+
${info(prompt)}`);
|
|
4815
4878
|
}
|
|
4816
4879
|
}
|
|
4817
4880
|
var init_flow2 = __esm(() => {
|
|
@@ -5025,7 +5088,7 @@ init_config();
|
|
|
5025
5088
|
init_providers();
|
|
5026
5089
|
|
|
5027
5090
|
// src/version/version.ts
|
|
5028
|
-
var VERSION = "0.
|
|
5091
|
+
var VERSION = "0.3.1";
|
|
5029
5092
|
var COMMIT = "none";
|
|
5030
5093
|
var DATE = "unknown";
|
|
5031
5094
|
function getVersionString() {
|