@levr-one/cli 0.7.0 → 0.7.2
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/dist/{addHandler-7QMKiy7o.js → addHandler-Brr4ndcR.js} +49 -1
- package/dist/cli.js +8 -8
- package/dist/{importHandler-D43Q8Jey.js → importHandler-DhF7psRj.js} +2 -2
- package/dist/{listHandler-jEyTQhBk.js → listHandler-hpPpE3WN.js} +1 -1
- package/dist/{loginHandler-BE8MQq83.js → loginHandler-BNmD3R0O.js} +2 -2
- package/dist/{pushHandler-Bf1F1Ltk.js → pushHandler-B0s2pHMU.js} +2 -2
- package/dist/{resolve-workspace-DfEX0LDh.js → resolve-workspace-CpmC9eWS.js} +1 -1
- package/dist/{sdk-client-DKifoBwD.js → sdk-client-CMgf3JjV.js} +16 -8
- package/dist/{selectHandler-KNiDUd9H.js → selectHandler-D4dL2zUJ.js} +1 -1
- package/dist/{statusHandler-C2_XOUal.js → statusHandler-ChymW9I9.js} +1 -1
- package/package.json +1 -1
|
@@ -1044,6 +1044,11 @@ const KNOWN_MCP_URLS = {
|
|
|
1044
1044
|
* deployments) derives `<api-url>/v1/mcp`.
|
|
1045
1045
|
*/
|
|
1046
1046
|
function resolveMcpUrl(flagUrl) {
|
|
1047
|
+
const resolved = resolveRaw(flagUrl);
|
|
1048
|
+
assertUsableMcpUrl(resolved.url, resolved.source);
|
|
1049
|
+
return resolved;
|
|
1050
|
+
}
|
|
1051
|
+
function resolveRaw(flagUrl) {
|
|
1047
1052
|
if (flagUrl) return {
|
|
1048
1053
|
url: stripSlash(flagUrl),
|
|
1049
1054
|
source: "flag"
|
|
@@ -1059,6 +1064,41 @@ function resolveMcpUrl(flagUrl) {
|
|
|
1059
1064
|
source: `derived:${apiUrl}`
|
|
1060
1065
|
};
|
|
1061
1066
|
}
|
|
1067
|
+
/** Name the input the user has to change, not our internal source tag. */
|
|
1068
|
+
function sourceLabel(source) {
|
|
1069
|
+
if (source === "flag") return "--url";
|
|
1070
|
+
if (source === "env:LEVR_MCP_URL") return "LEVR_MCP_URL";
|
|
1071
|
+
return `the API URL (${source.slice(8)})`;
|
|
1072
|
+
}
|
|
1073
|
+
/**
|
|
1074
|
+
* Reject a URL that must not reach a client config or a spawned CLI (ENG-4159).
|
|
1075
|
+
*
|
|
1076
|
+
* Three things this stops:
|
|
1077
|
+
*
|
|
1078
|
+
* 1. **No scheme.** `claude mcp add --transport http --scope user levr <value>`
|
|
1079
|
+
* is spawned with fixed argv since ENG-4156, so a value like `--foo` is read
|
|
1080
|
+
* by that CLI as a FLAG rather than as its URL operand — argument injection.
|
|
1081
|
+
* Requiring a parseable absolute URL removes the shape entirely.
|
|
1082
|
+
* 2. **A non-http(s) scheme.** `file:` / `javascript:` is never a valid MCP
|
|
1083
|
+
* endpoint, but would be written verbatim into every client's config.
|
|
1084
|
+
* 3. **Embedded credentials.** `https://user:pass@host` would be written into
|
|
1085
|
+
* a config file — and since ENG-4151 a config file can be `--scope project`,
|
|
1086
|
+
* which the user is told to COMMIT. That turns a bad URL into a secret in
|
|
1087
|
+
* git history. MCP authenticates via OAuth in the browser; credentials in
|
|
1088
|
+
* the URL are never needed.
|
|
1089
|
+
*/
|
|
1090
|
+
function assertUsableMcpUrl(url, source) {
|
|
1091
|
+
const from = sourceLabel(source);
|
|
1092
|
+
let parsed;
|
|
1093
|
+
try {
|
|
1094
|
+
parsed = new URL(url);
|
|
1095
|
+
} catch {
|
|
1096
|
+
throw new Error(`Invalid MCP URL from ${from}: ${JSON.stringify(url)} is not a URL. Expected an absolute http(s) URL, e.g. https://ai.levr.one/api/v1/mcp`);
|
|
1097
|
+
}
|
|
1098
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") throw new Error(`Invalid MCP URL from ${from}: ${JSON.stringify(url)} uses "${parsed.protocol}" — only http and https are supported.`);
|
|
1099
|
+
if (!parsed.hostname) throw new Error(`Invalid MCP URL from ${from}: ${JSON.stringify(url)} has no host.`);
|
|
1100
|
+
if (parsed.username || parsed.password) throw new Error(`Invalid MCP URL from ${from}: ${JSON.stringify(url)} embeds credentials. They would be written into client config files — including project-scoped ones you are told to commit. Levr authenticates in the browser; remove the user:password@ prefix.`);
|
|
1101
|
+
}
|
|
1062
1102
|
function knownMcpUrl(apiUrl) {
|
|
1063
1103
|
try {
|
|
1064
1104
|
return KNOWN_MCP_URLS[new URL(apiUrl).host];
|
|
@@ -1268,7 +1308,15 @@ const defaultDeps = {
|
|
|
1268
1308
|
install: defaultInstall
|
|
1269
1309
|
};
|
|
1270
1310
|
async function mcpAddHandler(flags) {
|
|
1271
|
-
|
|
1311
|
+
let url;
|
|
1312
|
+
let source;
|
|
1313
|
+
try {
|
|
1314
|
+
({url, source} = resolveMcpUrl(flags.url));
|
|
1315
|
+
} catch (err) {
|
|
1316
|
+
this.logger.error(err instanceof Error ? err.message : "Could not resolve the MCP URL.");
|
|
1317
|
+
this.process.exitCode = 1;
|
|
1318
|
+
return;
|
|
1319
|
+
}
|
|
1272
1320
|
const clients = (flags.client ?? []).flatMap((c) => c.split(",").map((s) => s.trim()).filter(Boolean));
|
|
1273
1321
|
const options = {
|
|
1274
1322
|
all: flags.all,
|
package/dist/cli.js
CHANGED
|
@@ -172,7 +172,7 @@ Examples:
|
|
|
172
172
|
aliases: { y: "yes" }
|
|
173
173
|
},
|
|
174
174
|
loader: async () => {
|
|
175
|
-
const { mcpAddHandler } = await import("./addHandler-
|
|
175
|
+
const { mcpAddHandler } = await import("./addHandler-Brr4ndcR.js");
|
|
176
176
|
return mcpAddHandler;
|
|
177
177
|
}
|
|
178
178
|
});
|
|
@@ -210,7 +210,7 @@ Examples:
|
|
|
210
210
|
aliases: { d: "device-code" }
|
|
211
211
|
},
|
|
212
212
|
loader: async () => {
|
|
213
|
-
const { loginHandler } = await import("./loginHandler-
|
|
213
|
+
const { loginHandler } = await import("./loginHandler-BNmD3R0O.js");
|
|
214
214
|
return loginHandler;
|
|
215
215
|
}
|
|
216
216
|
});
|
|
@@ -249,7 +249,7 @@ Examples:
|
|
|
249
249
|
},
|
|
250
250
|
parameters: {},
|
|
251
251
|
loader: async () => {
|
|
252
|
-
const { statusHandler } = await import("./statusHandler-
|
|
252
|
+
const { statusHandler } = await import("./statusHandler-ChymW9I9.js");
|
|
253
253
|
return statusHandler;
|
|
254
254
|
}
|
|
255
255
|
});
|
|
@@ -361,7 +361,7 @@ Examples:
|
|
|
361
361
|
}
|
|
362
362
|
},
|
|
363
363
|
loader: async () => {
|
|
364
|
-
const { pushHandler } = await import("./pushHandler-
|
|
364
|
+
const { pushHandler } = await import("./pushHandler-B0s2pHMU.js");
|
|
365
365
|
return pushHandler;
|
|
366
366
|
}
|
|
367
367
|
});
|
|
@@ -473,7 +473,7 @@ Examples:
|
|
|
473
473
|
}
|
|
474
474
|
},
|
|
475
475
|
loader: async () => {
|
|
476
|
-
const { importHandler } = await import("./importHandler-
|
|
476
|
+
const { importHandler } = await import("./importHandler-DhF7psRj.js");
|
|
477
477
|
return importHandler;
|
|
478
478
|
}
|
|
479
479
|
});
|
|
@@ -494,7 +494,7 @@ Examples:
|
|
|
494
494
|
},
|
|
495
495
|
parameters: {},
|
|
496
496
|
loader: async () => {
|
|
497
|
-
const { listHandler } = await import("./listHandler-
|
|
497
|
+
const { listHandler } = await import("./listHandler-hpPpE3WN.js");
|
|
498
498
|
return listHandler;
|
|
499
499
|
}
|
|
500
500
|
});
|
|
@@ -527,7 +527,7 @@ Examples:
|
|
|
527
527
|
flags: {}
|
|
528
528
|
},
|
|
529
529
|
loader: async () => {
|
|
530
|
-
const { selectHandler } = await import("./selectHandler-
|
|
530
|
+
const { selectHandler } = await import("./selectHandler-D4dL2zUJ.js");
|
|
531
531
|
return selectHandler;
|
|
532
532
|
}
|
|
533
533
|
});
|
|
@@ -551,7 +551,7 @@ Examples:
|
|
|
551
551
|
|
|
552
552
|
//#endregion
|
|
553
553
|
//#region package.json
|
|
554
|
-
var version = "0.7.
|
|
554
|
+
var version = "0.7.2";
|
|
555
555
|
|
|
556
556
|
//#endregion
|
|
557
557
|
//#region src/app.ts
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getApiUrl } from "./env-CHeKHu5S.js";
|
|
2
|
-
import { configureClient, testCaseImportCommitV1, testCaseImportPreviewV1 } from "./sdk-client-
|
|
2
|
+
import { configureClient, testCaseImportCommitV1, testCaseImportPreviewV1 } from "./sdk-client-CMgf3JjV.js";
|
|
3
3
|
import "./workspace-store-DDOxnut1.js";
|
|
4
|
-
import { resolveWorkspace } from "./resolve-workspace-
|
|
4
|
+
import { resolveWorkspace } from "./resolve-workspace-CpmC9eWS.js";
|
|
5
5
|
import "./token-refresh-Cu5RpkLJ.js";
|
|
6
6
|
import { resolveToken } from "./resolve-token-DbQsmn03.js";
|
|
7
7
|
import chalk from "chalk";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "./env-CHeKHu5S.js";
|
|
2
|
-
import { authGetSitesV1, configureClient } from "./sdk-client-
|
|
2
|
+
import { authGetSitesV1, configureClient } from "./sdk-client-CMgf3JjV.js";
|
|
3
3
|
import { loadWorkspace } from "./workspace-store-DDOxnut1.js";
|
|
4
4
|
import "./token-refresh-Cu5RpkLJ.js";
|
|
5
5
|
import { resolveToken } from "./resolve-token-DbQsmn03.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CLI_CLIENT_ID, getApiUrl, getAuthUrl, setSessionApiUrl, writeCredentials } from "./env-CHeKHu5S.js";
|
|
2
|
-
import { configureClient } from "./sdk-client-
|
|
2
|
+
import { configureClient } from "./sdk-client-CMgf3JjV.js";
|
|
3
3
|
import "./workspace-store-DDOxnut1.js";
|
|
4
|
-
import { autoSelectWorkspace } from "./resolve-workspace-
|
|
4
|
+
import { autoSelectWorkspace } from "./resolve-workspace-CpmC9eWS.js";
|
|
5
5
|
import chalk from "chalk";
|
|
6
6
|
import { createHash, randomBytes } from "node:crypto";
|
|
7
7
|
import { createServer } from "node:http";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getApiUrl, getAutomationSourceIdOverride, getSourceOverride, getTeamId } from "./env-CHeKHu5S.js";
|
|
2
|
-
import { client, configureClient, uploadAutomationIngest, uploadImport } from "./sdk-client-
|
|
2
|
+
import { client, configureClient, uploadAutomationIngest, uploadImport } from "./sdk-client-CMgf3JjV.js";
|
|
3
3
|
import "./workspace-store-DDOxnut1.js";
|
|
4
|
-
import { resolveWorkspace } from "./resolve-workspace-
|
|
4
|
+
import { resolveWorkspace } from "./resolve-workspace-CpmC9eWS.js";
|
|
5
5
|
import "./token-refresh-Cu5RpkLJ.js";
|
|
6
6
|
import { resolveToken } from "./resolve-token-DbQsmn03.js";
|
|
7
7
|
import { readFileSync, statSync } from "node:fs";
|
|
@@ -49,7 +49,8 @@ const zResponseIssueDto = z.object({
|
|
|
49
49
|
deleted_by: z.string().nullable().describe(""),
|
|
50
50
|
archived_at: z.unknown().describe(""),
|
|
51
51
|
archived_by: z.string().nullable().describe(""),
|
|
52
|
-
auto_archived_at: z.unknown().describe("")
|
|
52
|
+
auto_archived_at: z.unknown().describe(""),
|
|
53
|
+
web_url: z.string().nullable().optional().describe("")
|
|
53
54
|
});
|
|
54
55
|
const zPaginatedMetaDocumented = z.object({
|
|
55
56
|
itemsPerPage: z.number(),
|
|
@@ -2896,7 +2897,8 @@ const zResponseAutomationRunDto = z.object({
|
|
|
2896
2897
|
deleted_at: z.unknown().describe(""),
|
|
2897
2898
|
deleted_by: z.string().nullable().describe(""),
|
|
2898
2899
|
archived_at: z.unknown().describe(""),
|
|
2899
|
-
archived_by: z.string().nullable().describe("")
|
|
2900
|
+
archived_by: z.string().nullable().describe(""),
|
|
2901
|
+
web_url: z.string().nullable().optional().describe("")
|
|
2900
2902
|
});
|
|
2901
2903
|
const zUpdateAutomationRunDto = z.object({
|
|
2902
2904
|
id: z.string().optional().describe(""),
|
|
@@ -3312,7 +3314,8 @@ const zResponseAutomationRunResultDto = z.object({
|
|
|
3312
3314
|
deleted_at: z.unknown().describe(""),
|
|
3313
3315
|
deleted_by: z.string().nullable().describe(""),
|
|
3314
3316
|
archived_at: z.unknown().describe(""),
|
|
3315
|
-
archived_by: z.string().nullable().describe("")
|
|
3317
|
+
archived_by: z.string().nullable().describe(""),
|
|
3318
|
+
web_url: z.string().nullable().optional().describe("")
|
|
3316
3319
|
});
|
|
3317
3320
|
const zUpdateAutomationRunResultDto = z.object({
|
|
3318
3321
|
id: z.string().optional().describe(""),
|
|
@@ -9947,7 +9950,8 @@ const zResponseCycleDto = z.object({
|
|
|
9947
9950
|
updated_by: z.string().describe(""),
|
|
9948
9951
|
workspace_id: z.string().describe(""),
|
|
9949
9952
|
deleted_at: z.unknown().describe(""),
|
|
9950
|
-
deleted_by: z.string().nullable().describe("")
|
|
9953
|
+
deleted_by: z.string().nullable().describe(""),
|
|
9954
|
+
web_url: z.string().nullable().optional().describe("")
|
|
9951
9955
|
});
|
|
9952
9956
|
const zUpdateCycleDto = z.object({
|
|
9953
9957
|
id: z.string().optional().describe(""),
|
|
@@ -14921,7 +14925,8 @@ const zResponseGithubPullRequestDto = z.object({
|
|
|
14921
14925
|
epoch: z.number().describe(""),
|
|
14922
14926
|
created_by: z.string().describe(""),
|
|
14923
14927
|
updated_by: z.string().describe(""),
|
|
14924
|
-
workspace_id: z.string().describe("")
|
|
14928
|
+
workspace_id: z.string().describe(""),
|
|
14929
|
+
web_url: z.string().nullable().optional().describe("")
|
|
14925
14930
|
});
|
|
14926
14931
|
const zGithubPullRequestFindAllV1Data = z.object({
|
|
14927
14932
|
query: z.object({
|
|
@@ -15278,7 +15283,8 @@ const zResponseInitiativeDto = z.object({
|
|
|
15278
15283
|
deleted_at: z.unknown().describe(""),
|
|
15279
15284
|
deleted_by: z.string().nullable().describe(""),
|
|
15280
15285
|
archived_at: z.unknown().describe(""),
|
|
15281
|
-
archived_by: z.string().nullable().describe("")
|
|
15286
|
+
archived_by: z.string().nullable().describe(""),
|
|
15287
|
+
web_url: z.string().nullable().optional().describe("")
|
|
15282
15288
|
});
|
|
15283
15289
|
const zUpdateInitiativeDto = z.object({
|
|
15284
15290
|
id: z.string().optional().describe(""),
|
|
@@ -21213,7 +21219,8 @@ const zResponseProjectDto = z.object({
|
|
|
21213
21219
|
deleted_by: z.string().nullable().describe(""),
|
|
21214
21220
|
archived_at: z.unknown().describe(""),
|
|
21215
21221
|
archived_by: z.string().nullable().describe(""),
|
|
21216
|
-
auto_archived_at: z.unknown().describe("")
|
|
21222
|
+
auto_archived_at: z.unknown().describe(""),
|
|
21223
|
+
web_url: z.string().nullable().optional().describe("")
|
|
21217
21224
|
});
|
|
21218
21225
|
const zUpdateProjectDto = z.object({
|
|
21219
21226
|
id: z.string().optional().describe(""),
|
|
@@ -27468,7 +27475,8 @@ const zResponseTeamDto = z.object({
|
|
|
27468
27475
|
deleted_at: z.unknown().describe(""),
|
|
27469
27476
|
deleted_by: z.string().nullable().describe(""),
|
|
27470
27477
|
archived_at: z.unknown().describe(""),
|
|
27471
|
-
archived_by: z.string().nullable().describe("")
|
|
27478
|
+
archived_by: z.string().nullable().describe(""),
|
|
27479
|
+
web_url: z.string().nullable().optional().describe("")
|
|
27472
27480
|
});
|
|
27473
27481
|
const zUpdateTeamDto = z.object({
|
|
27474
27482
|
id: z.string().optional().describe(""),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "./env-CHeKHu5S.js";
|
|
2
|
-
import { authGetSitesV1, configureClient } from "./sdk-client-
|
|
2
|
+
import { authGetSitesV1, configureClient } from "./sdk-client-CMgf3JjV.js";
|
|
3
3
|
import { saveWorkspace } from "./workspace-store-DDOxnut1.js";
|
|
4
4
|
import "./token-refresh-Cu5RpkLJ.js";
|
|
5
5
|
import { resolveToken } from "./resolve-token-DbQsmn03.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getApiUrl, getPatToken, readCredentials } from "./env-CHeKHu5S.js";
|
|
2
|
-
import { authGetProfileV1, configureClient } from "./sdk-client-
|
|
2
|
+
import { authGetProfileV1, configureClient } from "./sdk-client-CMgf3JjV.js";
|
|
3
3
|
import { isTokenExpired } from "./token-refresh-Cu5RpkLJ.js";
|
|
4
4
|
import chalk from "chalk";
|
|
5
5
|
|