multicorn-shield 1.4.0 → 1.6.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/CHANGELOG.md +29 -0
- package/dist/multicorn-proxy.js +239 -11
- package/dist/multicorn-shield.js +58 -10
- package/dist/proxy.cjs +6 -2
- package/dist/proxy.d.cts +1 -1
- package/dist/proxy.d.ts +1 -1
- package/dist/proxy.js +6 -2
- package/dist/shield-extension.js +142 -51
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
9
|
|
|
10
10
|
- Bump `version` in `package.json` before publishing to npm.
|
|
11
11
|
|
|
12
|
+
## [1.5.0] - 2026-05-10
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- Claude Code promotion note when selecting Cursor in the CLI
|
|
17
|
+
- Example usage prompt in CLI "Next steps" output
|
|
18
|
+
- `--version` flag prints version number and exits
|
|
19
|
+
- Consent-required errors now display a clear multi-line message with the approval URL on its own line
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- Auth prompt detects token pasted at the y/N confirmation and treats it as the token value directly
|
|
24
|
+
- Single-item arrow select skips the interactive picker and selects immediately
|
|
25
|
+
- Blocked response message reformatted for clarity
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- Hosted proxy blocks `.well-known` OAuth discovery probes to prevent `mcp-remote` entering OAuth mode
|
|
30
|
+
|
|
31
|
+
## [1.4.1] - 2026-05-09
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
|
|
35
|
+
- Upstream auth prompt accepts a raw API token (`Bearer` added automatically) or a full Authorization-style value (`Bearer`, `Basic`, `Token`, `ApiKey` prefixes are passed through unchanged)
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
|
|
39
|
+
- CLI replace flow no longer shows duplicate agent entries
|
|
40
|
+
|
|
12
41
|
## [1.4.0] - 2026-05-08
|
|
13
42
|
|
|
14
43
|
### Added
|
package/dist/multicorn-proxy.js
CHANGED
|
@@ -420,6 +420,17 @@ function stripAnsi(str) {
|
|
|
420
420
|
function normalizeAgentName(raw) {
|
|
421
421
|
return raw.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "").slice(0, 50);
|
|
422
422
|
}
|
|
423
|
+
function formatUpstreamAuthorizationBearerHeader(raw) {
|
|
424
|
+
const t = raw.trim();
|
|
425
|
+
if (t.length === 0) return void 0;
|
|
426
|
+
if (UPSTREAM_AUTH_KNOWN_SCHEME_WITH_PAYLOAD.test(t)) {
|
|
427
|
+
return t;
|
|
428
|
+
}
|
|
429
|
+
if (/^(Bearer|Basic|Token|ApiKey)$/i.test(t)) {
|
|
430
|
+
return void 0;
|
|
431
|
+
}
|
|
432
|
+
return `Bearer ${t}`;
|
|
433
|
+
}
|
|
423
434
|
function isErrnoException(e) {
|
|
424
435
|
return typeof e === "object" && e !== null && "code" in e;
|
|
425
436
|
}
|
|
@@ -1400,6 +1411,12 @@ async function promptWindsurfIntegrationMode(ask) {
|
|
|
1400
1411
|
return choice === 1 ? "native" : "hosted";
|
|
1401
1412
|
}
|
|
1402
1413
|
async function arrowSelect(options, ask, fallbackLabel) {
|
|
1414
|
+
if (options.length === 1) {
|
|
1415
|
+
const only = options[0] ?? "";
|
|
1416
|
+
process.stderr.write(`${style.violet("\u276F")} ${style.cyan(only)}
|
|
1417
|
+
`);
|
|
1418
|
+
return 0;
|
|
1419
|
+
}
|
|
1403
1420
|
const canRaw = process.stdin.isTTY && typeof process.stdin.setRawMode === "function";
|
|
1404
1421
|
if (!canRaw) {
|
|
1405
1422
|
for (let i = 0; i < options.length; i++) {
|
|
@@ -1452,7 +1469,7 @@ async function arrowSelect(options, ask, fallbackLabel) {
|
|
|
1452
1469
|
cleanup();
|
|
1453
1470
|
clearLines();
|
|
1454
1471
|
const chosen = options.at(idx);
|
|
1455
|
-
if (chosen !== void 0) {
|
|
1472
|
+
if (chosen !== void 0 && options.length > 1) {
|
|
1456
1473
|
process.stderr.write(`${style.violet("\u276F")} ${style.cyan(chosen)}
|
|
1457
1474
|
`);
|
|
1458
1475
|
}
|
|
@@ -1534,12 +1551,12 @@ async function promptProxyConfig(ask, agentName) {
|
|
|
1534
1551
|
let upstreamHeaders;
|
|
1535
1552
|
if (wantsAuth) {
|
|
1536
1553
|
process.stderr.write(
|
|
1537
|
-
"\n" + style.bold("Enter
|
|
1554
|
+
"\n" + style.bold("Enter your API token or full Authorization header value.") + "\n" + style.dim(" Bearer tokens: ghp_xxxxxxxxxxxx (Bearer is added automatically)") + "\n" + style.dim(" Other schemes: Basic dXNlcjpwYXNz (passed as-is)") + "\n"
|
|
1538
1555
|
);
|
|
1539
1556
|
const headerVal = await ask("Value: ");
|
|
1540
|
-
const
|
|
1541
|
-
if (
|
|
1542
|
-
upstreamHeaders = { Authorization:
|
|
1557
|
+
const authHeader = formatUpstreamAuthorizationBearerHeader(headerVal);
|
|
1558
|
+
if (authHeader !== void 0) {
|
|
1559
|
+
upstreamHeaders = { Authorization: authHeader };
|
|
1543
1560
|
}
|
|
1544
1561
|
}
|
|
1545
1562
|
return {
|
|
@@ -2064,7 +2081,7 @@ function printPlatformSnippet(platform, routingToken, shortName, apiKey) {
|
|
|
2064
2081
|
}
|
|
2065
2082
|
}
|
|
2066
2083
|
function agentDisplayNameDedupeKey(name) {
|
|
2067
|
-
return name.trim().toLowerCase();
|
|
2084
|
+
return name.trim().normalize("NFKC").toLowerCase();
|
|
2068
2085
|
}
|
|
2069
2086
|
function normalizeAgentEntryForMerge(a) {
|
|
2070
2087
|
const name = a.name.trim();
|
|
@@ -2291,6 +2308,9 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2291
2308
|
const victim = agentsForPlatform[replaceIdx];
|
|
2292
2309
|
if (victim !== void 0) {
|
|
2293
2310
|
removeAgentNameBeforeSave = victim.name;
|
|
2311
|
+
process.stderr.write(
|
|
2312
|
+
"\n" + style.dim("Replacing agent ") + style.cyan(victim.name) + style.dim("...") + "\n"
|
|
2313
|
+
);
|
|
2294
2314
|
}
|
|
2295
2315
|
}
|
|
2296
2316
|
}
|
|
@@ -2799,6 +2819,14 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2799
2819
|
}
|
|
2800
2820
|
rl.close();
|
|
2801
2821
|
if (configuredAgents.length > 0) {
|
|
2822
|
+
let mcpPromptLabel2 = function(platformSlug) {
|
|
2823
|
+
const rows = configuredAgents.filter((a) => a.platform === platformSlug);
|
|
2824
|
+
const last = rows[rows.length - 1];
|
|
2825
|
+
if (last === void 0) return "shield-mcp";
|
|
2826
|
+
const s = typeof last.shortName === "string" ? last.shortName.trim() : "";
|
|
2827
|
+
if (s.length > 0) return s;
|
|
2828
|
+
return last.agentName.trim().length > 0 ? last.agentName.trim() : "shield-mcp";
|
|
2829
|
+
};
|
|
2802
2830
|
process.stderr.write("\n" + style.bold(style.violet("Setup complete")) + "\n\n");
|
|
2803
2831
|
for (const agent of configuredAgents) {
|
|
2804
2832
|
const namePart = agent.agentName.length > 0 ? ` - ${style.cyan(agent.agentName)}` : "";
|
|
@@ -2822,13 +2850,15 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2822
2850
|
);
|
|
2823
2851
|
}
|
|
2824
2852
|
if (configuredPlatforms.has("claude-desktop")) {
|
|
2853
|
+
const cdLabel = mcpPromptLabel2("claude-desktop");
|
|
2825
2854
|
blocks.push(
|
|
2826
|
-
"\n" + style.bold("Claude Desktop") +
|
|
2855
|
+
"\n" + style.bold("Claude Desktop") + '\n \u2192 Restart Claude Desktop to load the updated configuration\n \u2192 Confirm connection: click your profile (bottom-left) \u2192 Settings \u2192 Developer\n Check that "' + cdLabel + '" shows a green "running" status\n \u2192 Try it: paste this into Claude Desktop:\n "Use the ' + cdLabel + ' MCP server to list my GitHub repositories"\n'
|
|
2827
2856
|
);
|
|
2828
2857
|
}
|
|
2829
2858
|
if (configuredPlatforms.has("cursor")) {
|
|
2859
|
+
const cursorLabel = mcpPromptLabel2("cursor");
|
|
2830
2860
|
blocks.push(
|
|
2831
|
-
"\n" + style.bold("Cursor") + "\n \u2192 If needed, download Cursor from " + style.cyan("https://www.cursor.com/downloads") +
|
|
2861
|
+
"\n" + style.bold("Cursor") + "\n \u2192 If needed, download Cursor from " + style.cyan("https://www.cursor.com/downloads") + '\n \u2192 Restart Cursor so it loads the MCP server\n \u2192 Confirm connection: open Settings \u2192 Tools & MCPs\n Check that "' + cursorLabel + '" shows a green status indicator\n \u2192 Try it: paste this into Cursor:\n "Use the ' + cursorLabel + ' MCP server to list my GitHub repositories"\n'
|
|
2832
2862
|
);
|
|
2833
2863
|
}
|
|
2834
2864
|
if (configuredPlatforms.has("kilo-code")) {
|
|
@@ -2918,7 +2948,7 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2918
2948
|
}
|
|
2919
2949
|
return lastConfig;
|
|
2920
2950
|
}
|
|
2921
|
-
var SECRET_JSON_FILE_OPTIONS, style, BANNER, NativePluginPrerequisiteMissingError, CONFIG_DIR, CONFIG_PATH, OPENCLAW_CONFIG_PATH, ANSI_PATTERN, OPENCLAW_MIN_VERSION, INIT_WIZARD_PLATFORM_REGISTRY, INIT_WIZARD_MENU_SECTIONS, INIT_WIZARD_SELECTION_MAX, PLATFORM_BY_SELECTION, HOSTED_PROXY_PLATFORMS_WITH_URL_KEY, DEFAULT_SHIELD_API_BASE_URL;
|
|
2951
|
+
var SECRET_JSON_FILE_OPTIONS, style, BANNER, NativePluginPrerequisiteMissingError, CONFIG_DIR, CONFIG_PATH, OPENCLAW_CONFIG_PATH, ANSI_PATTERN, UPSTREAM_AUTH_KNOWN_SCHEME_WITH_PAYLOAD, OPENCLAW_MIN_VERSION, INIT_WIZARD_PLATFORM_REGISTRY, INIT_WIZARD_MENU_SECTIONS, INIT_WIZARD_SELECTION_MAX, PLATFORM_BY_SELECTION, HOSTED_PROXY_PLATFORMS_WITH_URL_KEY, DEFAULT_SHIELD_API_BASE_URL;
|
|
2922
2952
|
var init_config = __esm({
|
|
2923
2953
|
"src/proxy/config.ts"() {
|
|
2924
2954
|
init_consent();
|
|
@@ -2950,6 +2980,7 @@ var init_config = __esm({
|
|
|
2950
2980
|
CONFIG_PATH = join(CONFIG_DIR, "config.json");
|
|
2951
2981
|
OPENCLAW_CONFIG_PATH = join(homedir(), ".openclaw", "openclaw.json");
|
|
2952
2982
|
ANSI_PATTERN = new RegExp(String.fromCharCode(27) + "\\[[0-9;]*[a-zA-Z]", "g");
|
|
2983
|
+
UPSTREAM_AUTH_KNOWN_SCHEME_WITH_PAYLOAD = /^(Bearer|Basic|Token|ApiKey)(\s+)(.+)$/is;
|
|
2953
2984
|
OPENCLAW_MIN_VERSION = "2026.2.26";
|
|
2954
2985
|
INIT_WIZARD_PLATFORM_REGISTRY = [
|
|
2955
2986
|
{ slug: "openclaw", displayName: "OpenClaw", section: "native" },
|
|
@@ -3415,9 +3446,13 @@ function extractToolCallParams(request) {
|
|
|
3415
3446
|
if (typeof args !== "object" || args === null) return null;
|
|
3416
3447
|
return { name, arguments: args };
|
|
3417
3448
|
}
|
|
3418
|
-
function buildBlockedResponse(id, service,
|
|
3449
|
+
function buildBlockedResponse(id, service, _permissionLevel, dashboardUrl) {
|
|
3419
3450
|
const displayService = capitalize(service);
|
|
3420
|
-
const message = `Action blocked by
|
|
3451
|
+
const message = `Action blocked by Shield
|
|
3452
|
+
|
|
3453
|
+
This agent cannot use ${displayService}.
|
|
3454
|
+
|
|
3455
|
+
Configure permissions: ${dashboardUrl}`;
|
|
3421
3456
|
return {
|
|
3422
3457
|
jsonrpc: "2.0",
|
|
3423
3458
|
id,
|
|
@@ -3951,6 +3986,192 @@ var init_restore = __esm({
|
|
|
3951
3986
|
}
|
|
3952
3987
|
});
|
|
3953
3988
|
|
|
3989
|
+
// package.json
|
|
3990
|
+
var package_default;
|
|
3991
|
+
var init_package = __esm({
|
|
3992
|
+
"package.json"() {
|
|
3993
|
+
package_default = {
|
|
3994
|
+
name: "multicorn-shield",
|
|
3995
|
+
version: "1.6.0",
|
|
3996
|
+
description: "The control layer for AI agents: permissions, consent, spending limits, and audit logging.",
|
|
3997
|
+
license: "MIT",
|
|
3998
|
+
author: "Multicorn AI Pty Ltd",
|
|
3999
|
+
type: "module",
|
|
4000
|
+
main: "./dist/index.cjs",
|
|
4001
|
+
module: "./dist/index.js",
|
|
4002
|
+
types: "./dist/index.d.ts",
|
|
4003
|
+
exports: {
|
|
4004
|
+
".": {
|
|
4005
|
+
import: {
|
|
4006
|
+
types: "./dist/index.d.ts",
|
|
4007
|
+
default: "./dist/index.js"
|
|
4008
|
+
},
|
|
4009
|
+
require: {
|
|
4010
|
+
types: "./dist/index.d.cts",
|
|
4011
|
+
default: "./dist/index.cjs"
|
|
4012
|
+
}
|
|
4013
|
+
},
|
|
4014
|
+
"./proxy": {
|
|
4015
|
+
import: {
|
|
4016
|
+
types: "./dist/proxy.d.ts",
|
|
4017
|
+
default: "./dist/proxy.js"
|
|
4018
|
+
},
|
|
4019
|
+
require: {
|
|
4020
|
+
types: "./dist/proxy.d.cts",
|
|
4021
|
+
default: "./dist/proxy.cjs"
|
|
4022
|
+
}
|
|
4023
|
+
}
|
|
4024
|
+
},
|
|
4025
|
+
bin: {
|
|
4026
|
+
"multicorn-shield": "./dist/multicorn-shield.js",
|
|
4027
|
+
"multicorn-proxy": "./dist/multicorn-proxy.js"
|
|
4028
|
+
},
|
|
4029
|
+
files: [
|
|
4030
|
+
"dist",
|
|
4031
|
+
"plugins/multicorn-shield",
|
|
4032
|
+
"plugins/windsurf",
|
|
4033
|
+
"plugins/cline",
|
|
4034
|
+
"plugins/gemini-cli",
|
|
4035
|
+
"LICENSE",
|
|
4036
|
+
"README.md",
|
|
4037
|
+
"CHANGELOG.md"
|
|
4038
|
+
],
|
|
4039
|
+
publishConfig: {
|
|
4040
|
+
access: "public",
|
|
4041
|
+
provenance: true
|
|
4042
|
+
},
|
|
4043
|
+
sideEffects: [
|
|
4044
|
+
"dist/index.js",
|
|
4045
|
+
"dist/index.cjs",
|
|
4046
|
+
"dist/badge.js",
|
|
4047
|
+
"src/badge/multicorn-badge.ts"
|
|
4048
|
+
],
|
|
4049
|
+
engines: {
|
|
4050
|
+
node: ">=20"
|
|
4051
|
+
},
|
|
4052
|
+
scripts: {
|
|
4053
|
+
build: "tsup",
|
|
4054
|
+
dev: "tsup --watch",
|
|
4055
|
+
lint: "eslint . --no-warn-ignored && prettier --check .",
|
|
4056
|
+
"lint:fix": "eslint --fix . --no-warn-ignored && prettier --write .",
|
|
4057
|
+
test: "vitest run",
|
|
4058
|
+
"test:watch": "vitest",
|
|
4059
|
+
"test:coverage": "vitest run --coverage",
|
|
4060
|
+
typecheck: "tsc --noEmit",
|
|
4061
|
+
docs: "typedoc",
|
|
4062
|
+
clean: "rm -rf dist coverage docs/api extension-pack",
|
|
4063
|
+
"stage-extension-pack": "rm -rf extension-pack && mkdir -p extension-pack/server && cp manifest.json extension-pack/ && cp icon.png extension-pack/ && cp dist/shield-extension.js extension-pack/server/index.js",
|
|
4064
|
+
"validate:extension": "pnpm run stage-extension-pack && mcpb validate extension-pack/manifest.json",
|
|
4065
|
+
"build:extension": "tsup",
|
|
4066
|
+
"pack:extension": "pnpm run build && pnpm run stage-extension-pack && mcpb validate extension-pack/manifest.json && mcpb pack extension-pack dist/multicorn-shield.mcpb",
|
|
4067
|
+
size: "size-limit",
|
|
4068
|
+
prepublishOnly: "pnpm run clean && pnpm run typecheck && pnpm run lint && pnpm run test && pnpm run build",
|
|
4069
|
+
prepare: "husky || true",
|
|
4070
|
+
"release:patch": "npm version patch && pnpm publish",
|
|
4071
|
+
"release:minor": "npm version minor && pnpm publish",
|
|
4072
|
+
"release:major": "npm version major && pnpm publish"
|
|
4073
|
+
},
|
|
4074
|
+
"lint-staged": {
|
|
4075
|
+
"*.ts": [
|
|
4076
|
+
"eslint --fix --no-warn-ignored",
|
|
4077
|
+
"prettier --write"
|
|
4078
|
+
],
|
|
4079
|
+
"*.{json,md}": [
|
|
4080
|
+
"prettier --write"
|
|
4081
|
+
]
|
|
4082
|
+
},
|
|
4083
|
+
dependencies: {
|
|
4084
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
4085
|
+
lit: "^3.2.0",
|
|
4086
|
+
zod: "^4.3.6"
|
|
4087
|
+
},
|
|
4088
|
+
devDependencies: {
|
|
4089
|
+
"@anthropic-ai/mcpb": "^2.1.2",
|
|
4090
|
+
"@eslint/js": "^9.19.0",
|
|
4091
|
+
"@open-wc/testing-helpers": "^3.0.1",
|
|
4092
|
+
"@size-limit/file": "^11.1.6",
|
|
4093
|
+
"@types/node": "^22.0.0",
|
|
4094
|
+
"@vitest/coverage-v8": "^3.0.5",
|
|
4095
|
+
eslint: "^9.19.0",
|
|
4096
|
+
"eslint-config-prettier": "^10.0.1",
|
|
4097
|
+
"eslint-plugin-unicorn": "^57.0.0",
|
|
4098
|
+
globals: "^15.14.0",
|
|
4099
|
+
husky: "^9.1.7",
|
|
4100
|
+
jiti: "^2.4.2",
|
|
4101
|
+
jsdom: "^25.0.1",
|
|
4102
|
+
"lint-staged": "^16.2.7",
|
|
4103
|
+
prettier: "^3.4.2",
|
|
4104
|
+
"size-limit": "^11.1.6",
|
|
4105
|
+
tsup: "^8.3.6",
|
|
4106
|
+
typedoc: "^0.28.17",
|
|
4107
|
+
typescript: "^5.7.3",
|
|
4108
|
+
"typescript-eslint": "^8.22.0",
|
|
4109
|
+
vite: "^7.3.2",
|
|
4110
|
+
vitest: "^3.0.5"
|
|
4111
|
+
},
|
|
4112
|
+
"size-limit": [
|
|
4113
|
+
{
|
|
4114
|
+
path: "dist/index.js",
|
|
4115
|
+
limit: "50 kB",
|
|
4116
|
+
gzip: true
|
|
4117
|
+
},
|
|
4118
|
+
{
|
|
4119
|
+
path: "dist/index.cjs",
|
|
4120
|
+
limit: "50 kB",
|
|
4121
|
+
gzip: true
|
|
4122
|
+
},
|
|
4123
|
+
{
|
|
4124
|
+
path: "dist/badge.js",
|
|
4125
|
+
limit: "5 kB",
|
|
4126
|
+
gzip: true
|
|
4127
|
+
}
|
|
4128
|
+
],
|
|
4129
|
+
keywords: [
|
|
4130
|
+
"ai",
|
|
4131
|
+
"agents",
|
|
4132
|
+
"permissions",
|
|
4133
|
+
"sdk",
|
|
4134
|
+
"typescript",
|
|
4135
|
+
"consent",
|
|
4136
|
+
"spending-limits",
|
|
4137
|
+
"audit-log",
|
|
4138
|
+
"mcp",
|
|
4139
|
+
"shield",
|
|
4140
|
+
"multicorn"
|
|
4141
|
+
],
|
|
4142
|
+
repository: {
|
|
4143
|
+
type: "git",
|
|
4144
|
+
url: "git+https://github.com/Multicorn-AI/multicorn-shield.git"
|
|
4145
|
+
},
|
|
4146
|
+
bugs: {
|
|
4147
|
+
url: "https://github.com/Multicorn-AI/multicorn-shield/issues"
|
|
4148
|
+
},
|
|
4149
|
+
homepage: "https://multicorn.ai",
|
|
4150
|
+
pnpm: {
|
|
4151
|
+
overrides: {
|
|
4152
|
+
vite: ">=7.3.2",
|
|
4153
|
+
flatted: ">=3.4.2",
|
|
4154
|
+
minimatch: ">=10.2.3",
|
|
4155
|
+
rollup: ">=4.59.0",
|
|
4156
|
+
picomatch: ">=4.0.4",
|
|
4157
|
+
"path-to-regexp": ">=8.4.0",
|
|
4158
|
+
"node-forge": ">=1.4.0",
|
|
4159
|
+
"fast-uri": ">=3.1.2"
|
|
4160
|
+
}
|
|
4161
|
+
}
|
|
4162
|
+
};
|
|
4163
|
+
}
|
|
4164
|
+
});
|
|
4165
|
+
|
|
4166
|
+
// src/package-meta.ts
|
|
4167
|
+
var PACKAGE_VERSION;
|
|
4168
|
+
var init_package_meta = __esm({
|
|
4169
|
+
"src/package-meta.ts"() {
|
|
4170
|
+
init_package();
|
|
4171
|
+
PACKAGE_VERSION = package_default.version;
|
|
4172
|
+
}
|
|
4173
|
+
});
|
|
4174
|
+
|
|
3954
4175
|
// bin/multicorn-shield.ts
|
|
3955
4176
|
var multicorn_shield_exports = {};
|
|
3956
4177
|
__export(multicorn_shield_exports, {
|
|
@@ -4109,6 +4330,7 @@ function printHelp() {
|
|
|
4109
4330
|
" Shield's permission layer.",
|
|
4110
4331
|
"",
|
|
4111
4332
|
"Options:",
|
|
4333
|
+
" --version, -v Print version and exit",
|
|
4112
4334
|
" --verbose, --debug Print extra diagnostics during init (menu selection, agent counts)",
|
|
4113
4335
|
" --api-key <key> Multicorn API key (overrides MULTICORN_API_KEY env var and config file)",
|
|
4114
4336
|
" --log-level <level> Log level: debug | info | warn | error (default: info)",
|
|
@@ -4133,6 +4355,11 @@ async function runCli() {
|
|
|
4133
4355
|
);
|
|
4134
4356
|
return;
|
|
4135
4357
|
}
|
|
4358
|
+
if (first === "--version" || first === "-v") {
|
|
4359
|
+
process.stdout.write(`${PACKAGE_VERSION}
|
|
4360
|
+
`);
|
|
4361
|
+
process.exit(0);
|
|
4362
|
+
}
|
|
4136
4363
|
const cli = parseArgs(process.argv);
|
|
4137
4364
|
const logger = createLogger(cli.logLevel);
|
|
4138
4365
|
if (cli.subcommand === "help") {
|
|
@@ -4279,6 +4506,7 @@ var init_multicorn_shield = __esm({
|
|
|
4279
4506
|
init_logger();
|
|
4280
4507
|
init_consent();
|
|
4281
4508
|
init_restore();
|
|
4509
|
+
init_package_meta();
|
|
4282
4510
|
isDirectRun = process.argv[1] !== void 0 && (import.meta.url.endsWith(process.argv[1]) || import.meta.url === `file://${process.argv[1]}` || import.meta.url.endsWith("/multicorn-shield.js") || import.meta.url.endsWith("/multicorn-shield.ts"));
|
|
4283
4511
|
if (isDirectRun && process.env["VITEST"] === void 0) {
|
|
4284
4512
|
runCli().catch((error) => {
|
package/dist/multicorn-shield.js
CHANGED
|
@@ -432,6 +432,18 @@ function stripAnsi(str) {
|
|
|
432
432
|
function normalizeAgentName(raw) {
|
|
433
433
|
return raw.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "").slice(0, 50);
|
|
434
434
|
}
|
|
435
|
+
var UPSTREAM_AUTH_KNOWN_SCHEME_WITH_PAYLOAD = /^(Bearer|Basic|Token|ApiKey)(\s+)(.+)$/is;
|
|
436
|
+
function formatUpstreamAuthorizationBearerHeader(raw) {
|
|
437
|
+
const t = raw.trim();
|
|
438
|
+
if (t.length === 0) return void 0;
|
|
439
|
+
if (UPSTREAM_AUTH_KNOWN_SCHEME_WITH_PAYLOAD.test(t)) {
|
|
440
|
+
return t;
|
|
441
|
+
}
|
|
442
|
+
if (/^(Bearer|Basic|Token|ApiKey)$/i.test(t)) {
|
|
443
|
+
return void 0;
|
|
444
|
+
}
|
|
445
|
+
return `Bearer ${t}`;
|
|
446
|
+
}
|
|
435
447
|
function isErrnoException(e) {
|
|
436
448
|
return typeof e === "object" && e !== null && "code" in e;
|
|
437
449
|
}
|
|
@@ -1471,6 +1483,12 @@ async function promptWindsurfIntegrationMode(ask) {
|
|
|
1471
1483
|
return choice === 1 ? "native" : "hosted";
|
|
1472
1484
|
}
|
|
1473
1485
|
async function arrowSelect(options, ask, fallbackLabel) {
|
|
1486
|
+
if (options.length === 1) {
|
|
1487
|
+
const only = options[0] ?? "";
|
|
1488
|
+
process.stderr.write(`${style.violet("\u276F")} ${style.cyan(only)}
|
|
1489
|
+
`);
|
|
1490
|
+
return 0;
|
|
1491
|
+
}
|
|
1474
1492
|
const canRaw = process.stdin.isTTY && typeof process.stdin.setRawMode === "function";
|
|
1475
1493
|
if (!canRaw) {
|
|
1476
1494
|
for (let i = 0; i < options.length; i++) {
|
|
@@ -1523,7 +1541,7 @@ async function arrowSelect(options, ask, fallbackLabel) {
|
|
|
1523
1541
|
cleanup();
|
|
1524
1542
|
clearLines();
|
|
1525
1543
|
const chosen = options.at(idx);
|
|
1526
|
-
if (chosen !== void 0) {
|
|
1544
|
+
if (chosen !== void 0 && options.length > 1) {
|
|
1527
1545
|
process.stderr.write(`${style.violet("\u276F")} ${style.cyan(chosen)}
|
|
1528
1546
|
`);
|
|
1529
1547
|
}
|
|
@@ -1605,12 +1623,12 @@ async function promptProxyConfig(ask, agentName) {
|
|
|
1605
1623
|
let upstreamHeaders;
|
|
1606
1624
|
if (wantsAuth) {
|
|
1607
1625
|
process.stderr.write(
|
|
1608
|
-
"\n" + style.bold("Enter
|
|
1626
|
+
"\n" + style.bold("Enter your API token or full Authorization header value.") + "\n" + style.dim(" Bearer tokens: ghp_xxxxxxxxxxxx (Bearer is added automatically)") + "\n" + style.dim(" Other schemes: Basic dXNlcjpwYXNz (passed as-is)") + "\n"
|
|
1609
1627
|
);
|
|
1610
1628
|
const headerVal = await ask("Value: ");
|
|
1611
|
-
const
|
|
1612
|
-
if (
|
|
1613
|
-
upstreamHeaders = { Authorization:
|
|
1629
|
+
const authHeader = formatUpstreamAuthorizationBearerHeader(headerVal);
|
|
1630
|
+
if (authHeader !== void 0) {
|
|
1631
|
+
upstreamHeaders = { Authorization: authHeader };
|
|
1614
1632
|
}
|
|
1615
1633
|
}
|
|
1616
1634
|
return {
|
|
@@ -2143,7 +2161,7 @@ function printPlatformSnippet(platform, routingToken, shortName, apiKey) {
|
|
|
2143
2161
|
}
|
|
2144
2162
|
}
|
|
2145
2163
|
function agentDisplayNameDedupeKey(name) {
|
|
2146
|
-
return name.trim().toLowerCase();
|
|
2164
|
+
return name.trim().normalize("NFKC").toLowerCase();
|
|
2147
2165
|
}
|
|
2148
2166
|
function normalizeAgentEntryForMerge(a) {
|
|
2149
2167
|
const name = a.name.trim();
|
|
@@ -2371,6 +2389,9 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2371
2389
|
const victim = agentsForPlatform[replaceIdx];
|
|
2372
2390
|
if (victim !== void 0) {
|
|
2373
2391
|
removeAgentNameBeforeSave = victim.name;
|
|
2392
|
+
process.stderr.write(
|
|
2393
|
+
"\n" + style.dim("Replacing agent ") + style.cyan(victim.name) + style.dim("...") + "\n"
|
|
2394
|
+
);
|
|
2374
2395
|
}
|
|
2375
2396
|
}
|
|
2376
2397
|
}
|
|
@@ -2879,6 +2900,14 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2879
2900
|
}
|
|
2880
2901
|
rl.close();
|
|
2881
2902
|
if (configuredAgents.length > 0) {
|
|
2903
|
+
let mcpPromptLabel2 = function(platformSlug) {
|
|
2904
|
+
const rows = configuredAgents.filter((a) => a.platform === platformSlug);
|
|
2905
|
+
const last = rows[rows.length - 1];
|
|
2906
|
+
if (last === void 0) return "shield-mcp";
|
|
2907
|
+
const s = typeof last.shortName === "string" ? last.shortName.trim() : "";
|
|
2908
|
+
if (s.length > 0) return s;
|
|
2909
|
+
return last.agentName.trim().length > 0 ? last.agentName.trim() : "shield-mcp";
|
|
2910
|
+
};
|
|
2882
2911
|
process.stderr.write("\n" + style.bold(style.violet("Setup complete")) + "\n\n");
|
|
2883
2912
|
for (const agent of configuredAgents) {
|
|
2884
2913
|
const namePart = agent.agentName.length > 0 ? ` - ${style.cyan(agent.agentName)}` : "";
|
|
@@ -2902,13 +2931,15 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2902
2931
|
);
|
|
2903
2932
|
}
|
|
2904
2933
|
if (configuredPlatforms.has("claude-desktop")) {
|
|
2934
|
+
const cdLabel = mcpPromptLabel2("claude-desktop");
|
|
2905
2935
|
blocks.push(
|
|
2906
|
-
"\n" + style.bold("Claude Desktop") +
|
|
2936
|
+
"\n" + style.bold("Claude Desktop") + '\n \u2192 Restart Claude Desktop to load the updated configuration\n \u2192 Confirm connection: click your profile (bottom-left) \u2192 Settings \u2192 Developer\n Check that "' + cdLabel + '" shows a green "running" status\n \u2192 Try it: paste this into Claude Desktop:\n "Use the ' + cdLabel + ' MCP server to list my GitHub repositories"\n'
|
|
2907
2937
|
);
|
|
2908
2938
|
}
|
|
2909
2939
|
if (configuredPlatforms.has("cursor")) {
|
|
2940
|
+
const cursorLabel = mcpPromptLabel2("cursor");
|
|
2910
2941
|
blocks.push(
|
|
2911
|
-
"\n" + style.bold("Cursor") + "\n \u2192 If needed, download Cursor from " + style.cyan("https://www.cursor.com/downloads") +
|
|
2942
|
+
"\n" + style.bold("Cursor") + "\n \u2192 If needed, download Cursor from " + style.cyan("https://www.cursor.com/downloads") + '\n \u2192 Restart Cursor so it loads the MCP server\n \u2192 Confirm connection: open Settings \u2192 Tools & MCPs\n Check that "' + cursorLabel + '" shows a green status indicator\n \u2192 Try it: paste this into Cursor:\n "Use the ' + cursorLabel + ' MCP server to list my GitHub repositories"\n'
|
|
2912
2943
|
);
|
|
2913
2944
|
}
|
|
2914
2945
|
if (configuredPlatforms.has("kilo-code")) {
|
|
@@ -3374,9 +3405,13 @@ function extractToolCallParams(request) {
|
|
|
3374
3405
|
if (typeof args !== "object" || args === null) return null;
|
|
3375
3406
|
return { name, arguments: args };
|
|
3376
3407
|
}
|
|
3377
|
-
function buildBlockedResponse(id, service,
|
|
3408
|
+
function buildBlockedResponse(id, service, _permissionLevel, dashboardUrl) {
|
|
3378
3409
|
const displayService = capitalize(service);
|
|
3379
|
-
const message = `Action blocked by
|
|
3410
|
+
const message = `Action blocked by Shield
|
|
3411
|
+
|
|
3412
|
+
This agent cannot use ${displayService}.
|
|
3413
|
+
|
|
3414
|
+
Configure permissions: ${dashboardUrl}`;
|
|
3380
3415
|
return {
|
|
3381
3416
|
jsonrpc: "2.0",
|
|
3382
3417
|
id,
|
|
@@ -3878,6 +3913,13 @@ async function restoreClaudeDesktopMcpFromBackup() {
|
|
|
3878
3913
|
});
|
|
3879
3914
|
}
|
|
3880
3915
|
|
|
3916
|
+
// package.json
|
|
3917
|
+
var package_default = {
|
|
3918
|
+
version: "1.6.0"};
|
|
3919
|
+
|
|
3920
|
+
// src/package-meta.ts
|
|
3921
|
+
var PACKAGE_VERSION = package_default.version;
|
|
3922
|
+
|
|
3881
3923
|
// bin/multicorn-shield.ts
|
|
3882
3924
|
function parseArgs(argv) {
|
|
3883
3925
|
const args = argv.slice(2);
|
|
@@ -4030,6 +4072,7 @@ function printHelp() {
|
|
|
4030
4072
|
" Shield's permission layer.",
|
|
4031
4073
|
"",
|
|
4032
4074
|
"Options:",
|
|
4075
|
+
" --version, -v Print version and exit",
|
|
4033
4076
|
" --verbose, --debug Print extra diagnostics during init (menu selection, agent counts)",
|
|
4034
4077
|
" --api-key <key> Multicorn API key (overrides MULTICORN_API_KEY env var and config file)",
|
|
4035
4078
|
" --log-level <level> Log level: debug | info | warn | error (default: info)",
|
|
@@ -4054,6 +4097,11 @@ async function runCli() {
|
|
|
4054
4097
|
);
|
|
4055
4098
|
return;
|
|
4056
4099
|
}
|
|
4100
|
+
if (first === "--version" || first === "-v") {
|
|
4101
|
+
process.stdout.write(`${PACKAGE_VERSION}
|
|
4102
|
+
`);
|
|
4103
|
+
process.exit(0);
|
|
4104
|
+
}
|
|
4057
4105
|
const cli = parseArgs(process.argv);
|
|
4058
4106
|
const logger = createLogger(cli.logLevel);
|
|
4059
4107
|
if (cli.subcommand === "help") {
|
package/dist/proxy.cjs
CHANGED
|
@@ -30,9 +30,13 @@ function extractToolCallParams(request) {
|
|
|
30
30
|
if (typeof args !== "object" || args === null) return null;
|
|
31
31
|
return { name, arguments: args };
|
|
32
32
|
}
|
|
33
|
-
function buildBlockedResponse(id, service,
|
|
33
|
+
function buildBlockedResponse(id, service, _permissionLevel, dashboardUrl) {
|
|
34
34
|
const displayService = capitalize(service);
|
|
35
|
-
const message = `Action blocked by
|
|
35
|
+
const message = `Action blocked by Shield
|
|
36
|
+
|
|
37
|
+
This agent cannot use ${displayService}.
|
|
38
|
+
|
|
39
|
+
Configure permissions: ${dashboardUrl}`;
|
|
36
40
|
return {
|
|
37
41
|
jsonrpc: "2.0",
|
|
38
42
|
id,
|
package/dist/proxy.d.cts
CHANGED
|
@@ -31,7 +31,7 @@ interface ToolCallParams {
|
|
|
31
31
|
}
|
|
32
32
|
declare function parseJsonRpcLine(line: string): JsonRpcRequest | null;
|
|
33
33
|
declare function extractToolCallParams(request: JsonRpcRequest): ToolCallParams | null;
|
|
34
|
-
declare function buildBlockedResponse(id: string | number | null, service: string,
|
|
34
|
+
declare function buildBlockedResponse(id: string | number | null, service: string, _permissionLevel: string, dashboardUrl: string): JsonRpcResponse;
|
|
35
35
|
declare function buildSpendingBlockedResponse(id: string | number | null, reason: string, dashboardUrl: string): JsonRpcResponse;
|
|
36
36
|
/**
|
|
37
37
|
* Internal error: Shield could not verify permissions due to an exception.
|
package/dist/proxy.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ interface ToolCallParams {
|
|
|
31
31
|
}
|
|
32
32
|
declare function parseJsonRpcLine(line: string): JsonRpcRequest | null;
|
|
33
33
|
declare function extractToolCallParams(request: JsonRpcRequest): ToolCallParams | null;
|
|
34
|
-
declare function buildBlockedResponse(id: string | number | null, service: string,
|
|
34
|
+
declare function buildBlockedResponse(id: string | number | null, service: string, _permissionLevel: string, dashboardUrl: string): JsonRpcResponse;
|
|
35
35
|
declare function buildSpendingBlockedResponse(id: string | number | null, reason: string, dashboardUrl: string): JsonRpcResponse;
|
|
36
36
|
/**
|
|
37
37
|
* Internal error: Shield could not verify permissions due to an exception.
|
package/dist/proxy.js
CHANGED
|
@@ -28,9 +28,13 @@ function extractToolCallParams(request) {
|
|
|
28
28
|
if (typeof args !== "object" || args === null) return null;
|
|
29
29
|
return { name, arguments: args };
|
|
30
30
|
}
|
|
31
|
-
function buildBlockedResponse(id, service,
|
|
31
|
+
function buildBlockedResponse(id, service, _permissionLevel, dashboardUrl) {
|
|
32
32
|
const displayService = capitalize(service);
|
|
33
|
-
const message = `Action blocked by
|
|
33
|
+
const message = `Action blocked by Shield
|
|
34
|
+
|
|
35
|
+
This agent cannot use ${displayService}.
|
|
36
|
+
|
|
37
|
+
Configure permissions: ${dashboardUrl}`;
|
|
34
38
|
return {
|
|
35
39
|
jsonrpc: "2.0",
|
|
36
40
|
id,
|
package/dist/shield-extension.js
CHANGED
|
@@ -3090,11 +3090,14 @@ var require_data = __commonJS({
|
|
|
3090
3090
|
}
|
|
3091
3091
|
});
|
|
3092
3092
|
|
|
3093
|
-
// node_modules/.pnpm/fast-uri@3.1.
|
|
3093
|
+
// node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/lib/utils.js
|
|
3094
3094
|
var require_utils = __commonJS({
|
|
3095
|
-
"node_modules/.pnpm/fast-uri@3.1.
|
|
3095
|
+
"node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/lib/utils.js"(exports$1, module) {
|
|
3096
3096
|
var isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
|
|
3097
3097
|
var isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
|
|
3098
|
+
var isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
|
|
3099
|
+
var isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu);
|
|
3100
|
+
var isPathCharacter = RegExp.prototype.test.bind(/^[\da-z\-._~!$&'()*+,;=:@/]$/iu);
|
|
3098
3101
|
function stringArrayToHexStripped(input) {
|
|
3099
3102
|
let acc = "";
|
|
3100
3103
|
let code = 0;
|
|
@@ -3287,27 +3290,77 @@ var require_utils = __commonJS({
|
|
|
3287
3290
|
}
|
|
3288
3291
|
return output.join("");
|
|
3289
3292
|
}
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3293
|
+
var HOST_DELIMS = { "@": "%40", "/": "%2F", "?": "%3F", "#": "%23", ":": "%3A" };
|
|
3294
|
+
var HOST_DELIM_RE = /[@/?#:]/g;
|
|
3295
|
+
var HOST_DELIM_NO_COLON_RE = /[@/?#]/g;
|
|
3296
|
+
function reescapeHostDelimiters(host, isIP) {
|
|
3297
|
+
const re = isIP ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE;
|
|
3298
|
+
re.lastIndex = 0;
|
|
3299
|
+
return host.replace(re, (ch) => HOST_DELIMS[ch]);
|
|
3300
|
+
}
|
|
3301
|
+
function normalizePercentEncoding(input, decodeUnreserved = false) {
|
|
3302
|
+
if (input.indexOf("%") === -1) {
|
|
3303
|
+
return input;
|
|
3300
3304
|
}
|
|
3301
|
-
|
|
3302
|
-
|
|
3305
|
+
let output = "";
|
|
3306
|
+
for (let i = 0; i < input.length; i++) {
|
|
3307
|
+
if (input[i] === "%" && i + 2 < input.length) {
|
|
3308
|
+
const hex3 = input.slice(i + 1, i + 3);
|
|
3309
|
+
if (isHexPair(hex3)) {
|
|
3310
|
+
const normalizedHex = hex3.toUpperCase();
|
|
3311
|
+
const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
|
|
3312
|
+
if (decodeUnreserved && isUnreserved(decoded)) {
|
|
3313
|
+
output += decoded;
|
|
3314
|
+
} else {
|
|
3315
|
+
output += "%" + normalizedHex;
|
|
3316
|
+
}
|
|
3317
|
+
i += 2;
|
|
3318
|
+
continue;
|
|
3319
|
+
}
|
|
3320
|
+
}
|
|
3321
|
+
output += input[i];
|
|
3303
3322
|
}
|
|
3304
|
-
|
|
3305
|
-
|
|
3323
|
+
return output;
|
|
3324
|
+
}
|
|
3325
|
+
function normalizePathEncoding(input) {
|
|
3326
|
+
let output = "";
|
|
3327
|
+
for (let i = 0; i < input.length; i++) {
|
|
3328
|
+
if (input[i] === "%" && i + 2 < input.length) {
|
|
3329
|
+
const hex3 = input.slice(i + 1, i + 3);
|
|
3330
|
+
if (isHexPair(hex3)) {
|
|
3331
|
+
const normalizedHex = hex3.toUpperCase();
|
|
3332
|
+
const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
|
|
3333
|
+
if (decoded !== "." && isUnreserved(decoded)) {
|
|
3334
|
+
output += decoded;
|
|
3335
|
+
} else {
|
|
3336
|
+
output += "%" + normalizedHex;
|
|
3337
|
+
}
|
|
3338
|
+
i += 2;
|
|
3339
|
+
continue;
|
|
3340
|
+
}
|
|
3341
|
+
}
|
|
3342
|
+
if (isPathCharacter(input[i])) {
|
|
3343
|
+
output += input[i];
|
|
3344
|
+
} else {
|
|
3345
|
+
output += escape(input[i]);
|
|
3346
|
+
}
|
|
3306
3347
|
}
|
|
3307
|
-
|
|
3308
|
-
|
|
3348
|
+
return output;
|
|
3349
|
+
}
|
|
3350
|
+
function escapePreservingEscapes(input) {
|
|
3351
|
+
let output = "";
|
|
3352
|
+
for (let i = 0; i < input.length; i++) {
|
|
3353
|
+
if (input[i] === "%" && i + 2 < input.length) {
|
|
3354
|
+
const hex3 = input.slice(i + 1, i + 3);
|
|
3355
|
+
if (isHexPair(hex3)) {
|
|
3356
|
+
output += "%" + hex3.toUpperCase();
|
|
3357
|
+
i += 2;
|
|
3358
|
+
continue;
|
|
3359
|
+
}
|
|
3360
|
+
}
|
|
3361
|
+
output += escape(input[i]);
|
|
3309
3362
|
}
|
|
3310
|
-
return
|
|
3363
|
+
return output;
|
|
3311
3364
|
}
|
|
3312
3365
|
function recomposeAuthority(component) {
|
|
3313
3366
|
const uriTokens = [];
|
|
@@ -3322,7 +3375,7 @@ var require_utils = __commonJS({
|
|
|
3322
3375
|
if (ipV6res.isIPV6 === true) {
|
|
3323
3376
|
host = `[${ipV6res.escapedHost}]`;
|
|
3324
3377
|
} else {
|
|
3325
|
-
host =
|
|
3378
|
+
host = reescapeHostDelimiters(host, false);
|
|
3326
3379
|
}
|
|
3327
3380
|
}
|
|
3328
3381
|
uriTokens.push(host);
|
|
@@ -3336,7 +3389,10 @@ var require_utils = __commonJS({
|
|
|
3336
3389
|
module.exports = {
|
|
3337
3390
|
nonSimpleDomain,
|
|
3338
3391
|
recomposeAuthority,
|
|
3339
|
-
|
|
3392
|
+
reescapeHostDelimiters,
|
|
3393
|
+
normalizePercentEncoding,
|
|
3394
|
+
normalizePathEncoding,
|
|
3395
|
+
escapePreservingEscapes,
|
|
3340
3396
|
removeDotSegments,
|
|
3341
3397
|
isIPv4,
|
|
3342
3398
|
isUUID,
|
|
@@ -3346,9 +3402,9 @@ var require_utils = __commonJS({
|
|
|
3346
3402
|
}
|
|
3347
3403
|
});
|
|
3348
3404
|
|
|
3349
|
-
// node_modules/.pnpm/fast-uri@3.1.
|
|
3405
|
+
// node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/lib/schemes.js
|
|
3350
3406
|
var require_schemes = __commonJS({
|
|
3351
|
-
"node_modules/.pnpm/fast-uri@3.1.
|
|
3407
|
+
"node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/lib/schemes.js"(exports$1, module) {
|
|
3352
3408
|
var { isUUID } = require_utils();
|
|
3353
3409
|
var URN_REG = /([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-.:;=@]|%[\da-f]{2})+)/iu;
|
|
3354
3410
|
var supportedSchemeNames = (
|
|
@@ -3555,15 +3611,15 @@ var require_schemes = __commonJS({
|
|
|
3555
3611
|
}
|
|
3556
3612
|
});
|
|
3557
3613
|
|
|
3558
|
-
// node_modules/.pnpm/fast-uri@3.1.
|
|
3614
|
+
// node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/index.js
|
|
3559
3615
|
var require_fast_uri = __commonJS({
|
|
3560
|
-
"node_modules/.pnpm/fast-uri@3.1.
|
|
3561
|
-
var { normalizeIPv6, removeDotSegments, recomposeAuthority,
|
|
3616
|
+
"node_modules/.pnpm/fast-uri@3.1.2/node_modules/fast-uri/index.js"(exports$1, module) {
|
|
3617
|
+
var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, escapePreservingEscapes, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
|
|
3562
3618
|
var { SCHEMES, getSchemeHandler } = require_schemes();
|
|
3563
3619
|
function normalize(uri, options) {
|
|
3564
3620
|
if (typeof uri === "string") {
|
|
3565
3621
|
uri = /** @type {T} */
|
|
3566
|
-
|
|
3622
|
+
normalizeString(uri, options);
|
|
3567
3623
|
} else if (typeof uri === "object") {
|
|
3568
3624
|
uri = /** @type {T} */
|
|
3569
3625
|
parse3(serialize(uri, options), options);
|
|
@@ -3630,19 +3686,9 @@ var require_fast_uri = __commonJS({
|
|
|
3630
3686
|
return target;
|
|
3631
3687
|
}
|
|
3632
3688
|
function equal(uriA, uriB, options) {
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
} else if (typeof uriA === "object") {
|
|
3637
|
-
uriA = serialize(normalizeComponentEncoding(uriA, true), { ...options, skipEscape: true });
|
|
3638
|
-
}
|
|
3639
|
-
if (typeof uriB === "string") {
|
|
3640
|
-
uriB = unescape(uriB);
|
|
3641
|
-
uriB = serialize(normalizeComponentEncoding(parse3(uriB, options), true), { ...options, skipEscape: true });
|
|
3642
|
-
} else if (typeof uriB === "object") {
|
|
3643
|
-
uriB = serialize(normalizeComponentEncoding(uriB, true), { ...options, skipEscape: true });
|
|
3644
|
-
}
|
|
3645
|
-
return uriA.toLowerCase() === uriB.toLowerCase();
|
|
3689
|
+
const normalizedA = normalizeComparableURI(uriA, options);
|
|
3690
|
+
const normalizedB = normalizeComparableURI(uriB, options);
|
|
3691
|
+
return normalizedA !== void 0 && normalizedB !== void 0 && normalizedA.toLowerCase() === normalizedB.toLowerCase();
|
|
3646
3692
|
}
|
|
3647
3693
|
function serialize(cmpts, opts) {
|
|
3648
3694
|
const component = {
|
|
@@ -3667,12 +3713,12 @@ var require_fast_uri = __commonJS({
|
|
|
3667
3713
|
if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(component, options);
|
|
3668
3714
|
if (component.path !== void 0) {
|
|
3669
3715
|
if (!options.skipEscape) {
|
|
3670
|
-
component.path =
|
|
3716
|
+
component.path = escapePreservingEscapes(component.path);
|
|
3671
3717
|
if (component.scheme !== void 0) {
|
|
3672
3718
|
component.path = component.path.split("%3A").join(":");
|
|
3673
3719
|
}
|
|
3674
3720
|
} else {
|
|
3675
|
-
component.path =
|
|
3721
|
+
component.path = normalizePercentEncoding(component.path);
|
|
3676
3722
|
}
|
|
3677
3723
|
}
|
|
3678
3724
|
if (options.reference !== "suffix" && component.scheme) {
|
|
@@ -3707,7 +3753,16 @@ var require_fast_uri = __commonJS({
|
|
|
3707
3753
|
return uriTokens.join("");
|
|
3708
3754
|
}
|
|
3709
3755
|
var URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u;
|
|
3710
|
-
function
|
|
3756
|
+
function getParseError(parsed, matches) {
|
|
3757
|
+
if (matches[2] !== void 0 && parsed.path && parsed.path[0] !== "/") {
|
|
3758
|
+
return 'URI path must start with "/" when authority is present.';
|
|
3759
|
+
}
|
|
3760
|
+
if (typeof parsed.port === "number" && (parsed.port < 0 || parsed.port > 65535)) {
|
|
3761
|
+
return "URI port is malformed.";
|
|
3762
|
+
}
|
|
3763
|
+
return void 0;
|
|
3764
|
+
}
|
|
3765
|
+
function parseWithStatus(uri, opts) {
|
|
3711
3766
|
const options = Object.assign({}, opts);
|
|
3712
3767
|
const parsed = {
|
|
3713
3768
|
scheme: void 0,
|
|
@@ -3718,6 +3773,7 @@ var require_fast_uri = __commonJS({
|
|
|
3718
3773
|
query: void 0,
|
|
3719
3774
|
fragment: void 0
|
|
3720
3775
|
};
|
|
3776
|
+
let malformedAuthorityOrPort = false;
|
|
3721
3777
|
let isIP = false;
|
|
3722
3778
|
if (options.reference === "suffix") {
|
|
3723
3779
|
if (options.scheme) {
|
|
@@ -3738,6 +3794,11 @@ var require_fast_uri = __commonJS({
|
|
|
3738
3794
|
if (isNaN(parsed.port)) {
|
|
3739
3795
|
parsed.port = matches[5];
|
|
3740
3796
|
}
|
|
3797
|
+
const parseError = getParseError(parsed, matches);
|
|
3798
|
+
if (parseError !== void 0) {
|
|
3799
|
+
parsed.error = parsed.error || parseError;
|
|
3800
|
+
malformedAuthorityOrPort = true;
|
|
3801
|
+
}
|
|
3741
3802
|
if (parsed.host) {
|
|
3742
3803
|
const ipv4result = isIPv4(parsed.host);
|
|
3743
3804
|
if (ipv4result === false) {
|
|
@@ -3776,14 +3837,18 @@ var require_fast_uri = __commonJS({
|
|
|
3776
3837
|
parsed.scheme = unescape(parsed.scheme);
|
|
3777
3838
|
}
|
|
3778
3839
|
if (parsed.host !== void 0) {
|
|
3779
|
-
parsed.host = unescape(parsed.host);
|
|
3840
|
+
parsed.host = reescapeHostDelimiters(unescape(parsed.host), isIP);
|
|
3780
3841
|
}
|
|
3781
3842
|
}
|
|
3782
3843
|
if (parsed.path) {
|
|
3783
|
-
parsed.path =
|
|
3844
|
+
parsed.path = normalizePathEncoding(parsed.path);
|
|
3784
3845
|
}
|
|
3785
3846
|
if (parsed.fragment) {
|
|
3786
|
-
|
|
3847
|
+
try {
|
|
3848
|
+
parsed.fragment = encodeURI(decodeURIComponent(parsed.fragment));
|
|
3849
|
+
} catch {
|
|
3850
|
+
parsed.error = parsed.error || "URI malformed";
|
|
3851
|
+
}
|
|
3787
3852
|
}
|
|
3788
3853
|
}
|
|
3789
3854
|
if (schemeHandler && schemeHandler.parse) {
|
|
@@ -3792,7 +3857,29 @@ var require_fast_uri = __commonJS({
|
|
|
3792
3857
|
} else {
|
|
3793
3858
|
parsed.error = parsed.error || "URI can not be parsed.";
|
|
3794
3859
|
}
|
|
3795
|
-
return parsed;
|
|
3860
|
+
return { parsed, malformedAuthorityOrPort };
|
|
3861
|
+
}
|
|
3862
|
+
function parse3(uri, opts) {
|
|
3863
|
+
return parseWithStatus(uri, opts).parsed;
|
|
3864
|
+
}
|
|
3865
|
+
function normalizeString(uri, opts) {
|
|
3866
|
+
return normalizeStringWithStatus(uri, opts).normalized;
|
|
3867
|
+
}
|
|
3868
|
+
function normalizeStringWithStatus(uri, opts) {
|
|
3869
|
+
const { parsed, malformedAuthorityOrPort } = parseWithStatus(uri, opts);
|
|
3870
|
+
return {
|
|
3871
|
+
normalized: malformedAuthorityOrPort ? uri : serialize(parsed, opts),
|
|
3872
|
+
malformedAuthorityOrPort
|
|
3873
|
+
};
|
|
3874
|
+
}
|
|
3875
|
+
function normalizeComparableURI(uri, opts) {
|
|
3876
|
+
if (typeof uri === "string") {
|
|
3877
|
+
const { normalized, malformedAuthorityOrPort } = normalizeStringWithStatus(uri, opts);
|
|
3878
|
+
return malformedAuthorityOrPort ? void 0 : normalized;
|
|
3879
|
+
}
|
|
3880
|
+
if (typeof uri === "object") {
|
|
3881
|
+
return serialize(uri, opts);
|
|
3882
|
+
}
|
|
3796
3883
|
}
|
|
3797
3884
|
var fastUri = {
|
|
3798
3885
|
SCHEMES,
|
|
@@ -22417,7 +22504,7 @@ async function writeExtensionBackup(claudeDesktopConfigPath, mcpServers) {
|
|
|
22417
22504
|
|
|
22418
22505
|
// package.json
|
|
22419
22506
|
var package_default = {
|
|
22420
|
-
version: "1.
|
|
22507
|
+
version: "1.6.0"};
|
|
22421
22508
|
|
|
22422
22509
|
// src/package-meta.ts
|
|
22423
22510
|
var PACKAGE_VERSION = package_default.version;
|
|
@@ -22980,7 +23067,7 @@ function resultSuggestsConsentNeeded(result) {
|
|
|
22980
23067
|
return false;
|
|
22981
23068
|
}
|
|
22982
23069
|
const t = first.text;
|
|
22983
|
-
return t.includes("Action blocked by
|
|
23070
|
+
return t.includes("Action blocked by Shield") || t.includes("Permission required") || t.includes("This agent cannot use") || t.includes("does not have") && t.includes("access to") || t.includes("Configure permissions:");
|
|
22984
23071
|
}
|
|
22985
23072
|
|
|
22986
23073
|
// src/types/index.ts
|
|
@@ -23203,9 +23290,13 @@ function sleep2(ms) {
|
|
|
23203
23290
|
var BLOCKED_ERROR_CODE = -32e3;
|
|
23204
23291
|
var INTERNAL_ERROR_CODE = -32002;
|
|
23205
23292
|
var SERVICE_UNREACHABLE_ERROR_CODE = -32003;
|
|
23206
|
-
function buildBlockedResponse(id, service,
|
|
23293
|
+
function buildBlockedResponse(id, service, _permissionLevel, dashboardUrl) {
|
|
23207
23294
|
const displayService = capitalize(service);
|
|
23208
|
-
const message = `Action blocked by
|
|
23295
|
+
const message = `Action blocked by Shield
|
|
23296
|
+
|
|
23297
|
+
This agent cannot use ${displayService}.
|
|
23298
|
+
|
|
23299
|
+
Configure permissions: ${dashboardUrl}`;
|
|
23209
23300
|
return {
|
|
23210
23301
|
jsonrpc: "2.0",
|
|
23211
23302
|
id,
|
package/package.json
CHANGED