multicorn-shield 1.9.3 → 1.9.5
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
CHANGED
|
@@ -9,6 +9,30 @@ 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.9.5] - 2026-05-13
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- CLI "Try it" prompt now suggests a real tool call instead of metadata discovery
|
|
17
|
+
- Duplicate "Add a new agent alongside these" menu option removed
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- CLI "Try it" prompt matches dashboard example: "Use the {agent} MCP server to list my GitHub repositories"
|
|
22
|
+
|
|
23
|
+
## [1.9.4] - 2026-05-13
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- Double "Bearer" prefix in Codex CLI hosted proxy TOML snippet (was outputting `Bearer Bearer mcs_...`)
|
|
28
|
+
- Codex CLI hosted proxy now auto-writes MCP server config to `~/.codex/config.toml` instead of asking users to paste manually
|
|
29
|
+
- PreToolUse hook now prints the consent/approval URL to stderr so users know where to approve
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- Codex CLI hosted proxy next-steps updated: "Restart Codex CLI to load the new MCP server config"
|
|
34
|
+
- Added copy-pasteable "Try it out" prompt to Codex CLI hosted proxy next-steps
|
|
35
|
+
|
|
12
36
|
## [1.9.3] - 2026-05-13
|
|
13
37
|
|
|
14
38
|
### Fixed
|
package/dist/multicorn-proxy.js
CHANGED
|
@@ -947,6 +947,68 @@ function getCodexCliHooksInstallDir() {
|
|
|
947
947
|
function getCodexConfigTomlPath() {
|
|
948
948
|
return join(homedir(), ".codex", "config.toml");
|
|
949
949
|
}
|
|
950
|
+
function escapeTomlDoubleQuotedScalar(value) {
|
|
951
|
+
return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
952
|
+
}
|
|
953
|
+
function stripCodexMcpServerTomlBlocks(content, serverKey) {
|
|
954
|
+
const lines = content.split(/\r?\n/);
|
|
955
|
+
const mainHeader = `[mcp_servers.${serverKey}]`;
|
|
956
|
+
const headersHeader = `[mcp_servers.${serverKey}.http_headers]`;
|
|
957
|
+
const out = [];
|
|
958
|
+
let state = "idle";
|
|
959
|
+
for (const line of lines) {
|
|
960
|
+
const t = line.trim();
|
|
961
|
+
if (state === "idle") {
|
|
962
|
+
if (t === mainHeader || t === headersHeader) {
|
|
963
|
+
state = t === headersHeader ? "skip_headers" : "skip_main";
|
|
964
|
+
continue;
|
|
965
|
+
}
|
|
966
|
+
out.push(line);
|
|
967
|
+
} else if (state === "skip_main") {
|
|
968
|
+
if (t.startsWith("[") && t.endsWith("]")) {
|
|
969
|
+
if (t === headersHeader) {
|
|
970
|
+
state = "skip_headers";
|
|
971
|
+
} else {
|
|
972
|
+
state = "idle";
|
|
973
|
+
out.push(line);
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
} else {
|
|
977
|
+
if (t.startsWith("[") && t.endsWith("]")) {
|
|
978
|
+
state = "idle";
|
|
979
|
+
out.push(line);
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
return out.join("\n").trimEnd();
|
|
984
|
+
}
|
|
985
|
+
async function mergeCodexHostedMcpIntoToml(shortName, proxyUrl, apiKey) {
|
|
986
|
+
const configPath = getCodexConfigTomlPath();
|
|
987
|
+
let existing = "";
|
|
988
|
+
try {
|
|
989
|
+
existing = await readFile(configPath, "utf8");
|
|
990
|
+
} catch (err) {
|
|
991
|
+
if (!(isErrnoException(err) && err.code === "ENOENT")) {
|
|
992
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
993
|
+
throw new Error(`Could not read Codex CLI config at ${configPath}: ${detail}`);
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
const stripped = stripCodexMcpServerTomlBlocks(existing, shortName);
|
|
997
|
+
const urlEsc = escapeTomlDoubleQuotedScalar(proxyUrl);
|
|
998
|
+
const tokenEsc = escapeTomlDoubleQuotedScalar(apiKey);
|
|
999
|
+
const block = `[mcp_servers.${shortName}]
|
|
1000
|
+
url = "${urlEsc}"
|
|
1001
|
+
|
|
1002
|
+
[mcp_servers.${shortName}.http_headers]
|
|
1003
|
+
Authorization = "Bearer ${tokenEsc}"
|
|
1004
|
+
`;
|
|
1005
|
+
const trimmedBase = stripped.trimEnd();
|
|
1006
|
+
const full = (trimmedBase.length > 0 ? `${trimmedBase}
|
|
1007
|
+
|
|
1008
|
+
` : "") + block;
|
|
1009
|
+
await mkdir(dirname(configPath), { recursive: true });
|
|
1010
|
+
await writeFile(configPath, full, SECRET_JSON_FILE_OPTIONS);
|
|
1011
|
+
}
|
|
950
1012
|
function getCodexHooksJsonPath() {
|
|
951
1013
|
return join(homedir(), ".codex", "hooks.json");
|
|
952
1014
|
}
|
|
@@ -2153,7 +2215,20 @@ async function applyHostedProxyMcpConfig(platform, proxyUrl, shortName, apiKey,
|
|
|
2153
2215
|
printHostedProxyJsonParseWarning(join(workspacePath, "opencode.json"));
|
|
2154
2216
|
}
|
|
2155
2217
|
} else if (platform === "codex-cli") {
|
|
2156
|
-
|
|
2218
|
+
let codexTomlWritten = false;
|
|
2219
|
+
try {
|
|
2220
|
+
await mergeCodexHostedMcpIntoToml(shortName, proxyUrlWithKeyWhenNeeded, apiKey);
|
|
2221
|
+
codexTomlWritten = true;
|
|
2222
|
+
process.stderr.write(
|
|
2223
|
+
style.green("\u2713 ") + "MCP server config written to " + style.cyan(getCodexConfigTomlPath()) + "\n"
|
|
2224
|
+
);
|
|
2225
|
+
} catch (err) {
|
|
2226
|
+
process.stderr.write(
|
|
2227
|
+
`${style.yellow("!")} Could not auto-write config: ${err instanceof Error ? err.message : String(err)}
|
|
2228
|
+
`
|
|
2229
|
+
);
|
|
2230
|
+
}
|
|
2231
|
+
printPlatformSnippet(platform, proxyUrl, shortName, apiKey, codexTomlWritten);
|
|
2157
2232
|
return;
|
|
2158
2233
|
} else if (platform === "continue-dev") {
|
|
2159
2234
|
result = await mergeContinueHostedMcp(
|
|
@@ -2279,7 +2354,7 @@ async function mergeGooseConfig(shortName, proxyUrl, apiKey) {
|
|
|
2279
2354
|
writeMcpAddedLine(shortName, filePath);
|
|
2280
2355
|
return "ok";
|
|
2281
2356
|
}
|
|
2282
|
-
function printPlatformSnippet(platform, routingToken, shortName, apiKey) {
|
|
2357
|
+
function printPlatformSnippet(platform, routingToken, shortName, apiKey, codexCliTomlWritten) {
|
|
2283
2358
|
const hostedInlinePlatforms = /* @__PURE__ */ new Set([
|
|
2284
2359
|
"cursor",
|
|
2285
2360
|
"claude-desktop",
|
|
@@ -2393,11 +2468,12 @@ mcpServers:
|
|
|
2393
2468
|
2
|
|
2394
2469
|
);
|
|
2395
2470
|
} else if (platform === "codex-cli") {
|
|
2471
|
+
const bearerToken = authHeader.startsWith("Bearer ") ? authHeader.slice("Bearer ".length) : authHeader;
|
|
2396
2472
|
snippetText = `[mcp_servers.${shortName}]
|
|
2397
2473
|
url = "${urlInSnippet}"
|
|
2398
2474
|
|
|
2399
2475
|
[mcp_servers.${shortName}.http_headers]
|
|
2400
|
-
Authorization = "Bearer ${
|
|
2476
|
+
Authorization = "Bearer ${bearerToken}"
|
|
2401
2477
|
`;
|
|
2402
2478
|
} else {
|
|
2403
2479
|
const urlKey = platform === "windsurf" ? "serverUrl" : "url";
|
|
@@ -2443,11 +2519,15 @@ Authorization = "Bearer ${authHeader}"
|
|
|
2443
2519
|
) + "\n\n"
|
|
2444
2520
|
);
|
|
2445
2521
|
} else if (platform === "codex-cli") {
|
|
2446
|
-
|
|
2447
|
-
"\n" + style.dim(
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2522
|
+
if (codexCliTomlWritten === true) {
|
|
2523
|
+
process.stderr.write("\n" + style.dim("Added to ~/.codex/config.toml:") + "\n\n");
|
|
2524
|
+
} else {
|
|
2525
|
+
process.stderr.write(
|
|
2526
|
+
"\n" + style.dim(
|
|
2527
|
+
"Add this to ~/.codex/config.toml (create the file if it does not exist). Restart Codex CLI after saving."
|
|
2528
|
+
) + "\n\n"
|
|
2529
|
+
);
|
|
2530
|
+
}
|
|
2451
2531
|
} else if (platform === "github-copilot") {
|
|
2452
2532
|
process.stderr.write(
|
|
2453
2533
|
"\n" + style.dim(
|
|
@@ -2723,15 +2803,7 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2723
2803
|
`);
|
|
2724
2804
|
}
|
|
2725
2805
|
process.stderr.write("\n" + style.bold("What would you like to do?") + "\n");
|
|
2726
|
-
const actionIdx = await arrowSelect(
|
|
2727
|
-
[
|
|
2728
|
-
"Add a new agent alongside these",
|
|
2729
|
-
"Replace an existing agent",
|
|
2730
|
-
"Skip - choose a different platform"
|
|
2731
|
-
],
|
|
2732
|
-
ask,
|
|
2733
|
-
"Action"
|
|
2734
|
-
);
|
|
2806
|
+
const actionIdx = await arrowSelect(INIT_EXISTING_AGENTS_PLATFORM_ACTIONS, ask, "Action");
|
|
2735
2807
|
if (actionIdx === 2) {
|
|
2736
2808
|
continue;
|
|
2737
2809
|
}
|
|
@@ -3241,11 +3313,6 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
3241
3313
|
apiKey,
|
|
3242
3314
|
initWorkspacePath
|
|
3243
3315
|
);
|
|
3244
|
-
process.stderr.write(
|
|
3245
|
-
"\n" + style.dim(
|
|
3246
|
-
"Add the TOML snippet above to ~/.codex/config.toml. Restart Codex CLI after saving."
|
|
3247
|
-
) + "\n"
|
|
3248
|
-
);
|
|
3249
3316
|
configuredAgents.push({
|
|
3250
3317
|
selection,
|
|
3251
3318
|
platform: selectedPlatform,
|
|
@@ -3582,8 +3649,9 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
3582
3649
|
);
|
|
3583
3650
|
}
|
|
3584
3651
|
if (codexHostedConfigured) {
|
|
3652
|
+
const codexLabel = mcpPromptLabel2("codex-cli");
|
|
3585
3653
|
blocks.push(
|
|
3586
|
-
"\n" + style.bold("Codex CLI (hosted)") + "\n \u2192 Restart Codex CLI
|
|
3654
|
+
"\n" + style.bold("Codex CLI (hosted)") + "\n \u2192 Restart Codex CLI to load the new MCP server config\n \u2192 Verify it's connected: run /mcp in Codex CLI to see your active MCP servers\n \u2192 Try it - paste this into Codex:\n Use the " + codexLabel + " MCP server to list my GitHub repositories\n"
|
|
3587
3655
|
);
|
|
3588
3656
|
}
|
|
3589
3657
|
if (configuredPlatforms.has("other-mcp")) {
|
|
@@ -3605,7 +3673,7 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
3605
3673
|
}
|
|
3606
3674
|
return lastConfig;
|
|
3607
3675
|
}
|
|
3608
|
-
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, OPENCODE_CONFIG_SCHEMA_URL, DEFAULT_SHIELD_API_BASE_URL;
|
|
3676
|
+
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, INIT_EXISTING_AGENTS_PLATFORM_ACTIONS, PLATFORM_BY_SELECTION, HOSTED_PROXY_PLATFORMS_WITH_URL_KEY, OPENCODE_CONFIG_SCHEMA_URL, DEFAULT_SHIELD_API_BASE_URL;
|
|
3609
3677
|
var init_config = __esm({
|
|
3610
3678
|
"src/proxy/config.ts"() {
|
|
3611
3679
|
init_consent();
|
|
@@ -3706,6 +3774,11 @@ var init_config = __esm({
|
|
|
3706
3774
|
];
|
|
3707
3775
|
})();
|
|
3708
3776
|
INIT_WIZARD_SELECTION_MAX = INIT_WIZARD_PLATFORM_REGISTRY.length;
|
|
3777
|
+
INIT_EXISTING_AGENTS_PLATFORM_ACTIONS = [
|
|
3778
|
+
"Add a new agent alongside these",
|
|
3779
|
+
"Replace an existing agent",
|
|
3780
|
+
"Skip - choose a different platform"
|
|
3781
|
+
];
|
|
3709
3782
|
PLATFORM_BY_SELECTION = Object.fromEntries(
|
|
3710
3783
|
INIT_WIZARD_PLATFORM_REGISTRY.map((e, i) => [i + 1, e.slug])
|
|
3711
3784
|
);
|
|
@@ -4662,7 +4735,7 @@ var init_package = __esm({
|
|
|
4662
4735
|
"package.json"() {
|
|
4663
4736
|
package_default = {
|
|
4664
4737
|
name: "multicorn-shield",
|
|
4665
|
-
version: "1.9.
|
|
4738
|
+
version: "1.9.5",
|
|
4666
4739
|
description: "The control layer for AI agents: permissions, consent, spending limits, and audit logging.",
|
|
4667
4740
|
license: "MIT",
|
|
4668
4741
|
author: "Multicorn AI Pty Ltd",
|
package/dist/multicorn-shield.js
CHANGED
|
@@ -961,6 +961,68 @@ function getCodexCliHooksInstallDir() {
|
|
|
961
961
|
function getCodexConfigTomlPath() {
|
|
962
962
|
return join(homedir(), ".codex", "config.toml");
|
|
963
963
|
}
|
|
964
|
+
function escapeTomlDoubleQuotedScalar(value) {
|
|
965
|
+
return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
966
|
+
}
|
|
967
|
+
function stripCodexMcpServerTomlBlocks(content, serverKey) {
|
|
968
|
+
const lines = content.split(/\r?\n/);
|
|
969
|
+
const mainHeader = `[mcp_servers.${serverKey}]`;
|
|
970
|
+
const headersHeader = `[mcp_servers.${serverKey}.http_headers]`;
|
|
971
|
+
const out = [];
|
|
972
|
+
let state = "idle";
|
|
973
|
+
for (const line of lines) {
|
|
974
|
+
const t = line.trim();
|
|
975
|
+
if (state === "idle") {
|
|
976
|
+
if (t === mainHeader || t === headersHeader) {
|
|
977
|
+
state = t === headersHeader ? "skip_headers" : "skip_main";
|
|
978
|
+
continue;
|
|
979
|
+
}
|
|
980
|
+
out.push(line);
|
|
981
|
+
} else if (state === "skip_main") {
|
|
982
|
+
if (t.startsWith("[") && t.endsWith("]")) {
|
|
983
|
+
if (t === headersHeader) {
|
|
984
|
+
state = "skip_headers";
|
|
985
|
+
} else {
|
|
986
|
+
state = "idle";
|
|
987
|
+
out.push(line);
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
} else {
|
|
991
|
+
if (t.startsWith("[") && t.endsWith("]")) {
|
|
992
|
+
state = "idle";
|
|
993
|
+
out.push(line);
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
return out.join("\n").trimEnd();
|
|
998
|
+
}
|
|
999
|
+
async function mergeCodexHostedMcpIntoToml(shortName, proxyUrl, apiKey) {
|
|
1000
|
+
const configPath = getCodexConfigTomlPath();
|
|
1001
|
+
let existing = "";
|
|
1002
|
+
try {
|
|
1003
|
+
existing = await readFile(configPath, "utf8");
|
|
1004
|
+
} catch (err) {
|
|
1005
|
+
if (!(isErrnoException(err) && err.code === "ENOENT")) {
|
|
1006
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
1007
|
+
throw new Error(`Could not read Codex CLI config at ${configPath}: ${detail}`);
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
const stripped = stripCodexMcpServerTomlBlocks(existing, shortName);
|
|
1011
|
+
const urlEsc = escapeTomlDoubleQuotedScalar(proxyUrl);
|
|
1012
|
+
const tokenEsc = escapeTomlDoubleQuotedScalar(apiKey);
|
|
1013
|
+
const block = `[mcp_servers.${shortName}]
|
|
1014
|
+
url = "${urlEsc}"
|
|
1015
|
+
|
|
1016
|
+
[mcp_servers.${shortName}.http_headers]
|
|
1017
|
+
Authorization = "Bearer ${tokenEsc}"
|
|
1018
|
+
`;
|
|
1019
|
+
const trimmedBase = stripped.trimEnd();
|
|
1020
|
+
const full = (trimmedBase.length > 0 ? `${trimmedBase}
|
|
1021
|
+
|
|
1022
|
+
` : "") + block;
|
|
1023
|
+
await mkdir(dirname(configPath), { recursive: true });
|
|
1024
|
+
await writeFile(configPath, full, SECRET_JSON_FILE_OPTIONS);
|
|
1025
|
+
}
|
|
964
1026
|
function getCodexHooksJsonPath() {
|
|
965
1027
|
return join(homedir(), ".codex", "hooks.json");
|
|
966
1028
|
}
|
|
@@ -1554,6 +1616,11 @@ var INIT_WIZARD_MENU_SECTIONS = (() => {
|
|
|
1554
1616
|
];
|
|
1555
1617
|
})();
|
|
1556
1618
|
var INIT_WIZARD_SELECTION_MAX = INIT_WIZARD_PLATFORM_REGISTRY.length;
|
|
1619
|
+
var INIT_EXISTING_AGENTS_PLATFORM_ACTIONS = [
|
|
1620
|
+
"Add a new agent alongside these",
|
|
1621
|
+
"Replace an existing agent",
|
|
1622
|
+
"Skip - choose a different platform"
|
|
1623
|
+
];
|
|
1557
1624
|
var PLATFORM_BY_SELECTION = Object.fromEntries(
|
|
1558
1625
|
INIT_WIZARD_PLATFORM_REGISTRY.map((e, i) => [i + 1, e.slug])
|
|
1559
1626
|
);
|
|
@@ -2246,7 +2313,20 @@ async function applyHostedProxyMcpConfig(platform, proxyUrl, shortName, apiKey,
|
|
|
2246
2313
|
printHostedProxyJsonParseWarning(join(workspacePath, "opencode.json"));
|
|
2247
2314
|
}
|
|
2248
2315
|
} else if (platform === "codex-cli") {
|
|
2249
|
-
|
|
2316
|
+
let codexTomlWritten = false;
|
|
2317
|
+
try {
|
|
2318
|
+
await mergeCodexHostedMcpIntoToml(shortName, proxyUrlWithKeyWhenNeeded, apiKey);
|
|
2319
|
+
codexTomlWritten = true;
|
|
2320
|
+
process.stderr.write(
|
|
2321
|
+
style.green("\u2713 ") + "MCP server config written to " + style.cyan(getCodexConfigTomlPath()) + "\n"
|
|
2322
|
+
);
|
|
2323
|
+
} catch (err) {
|
|
2324
|
+
process.stderr.write(
|
|
2325
|
+
`${style.yellow("!")} Could not auto-write config: ${err instanceof Error ? err.message : String(err)}
|
|
2326
|
+
`
|
|
2327
|
+
);
|
|
2328
|
+
}
|
|
2329
|
+
printPlatformSnippet(platform, proxyUrl, shortName, apiKey, codexTomlWritten);
|
|
2250
2330
|
return;
|
|
2251
2331
|
} else if (platform === "continue-dev") {
|
|
2252
2332
|
result = await mergeContinueHostedMcp(
|
|
@@ -2372,7 +2452,7 @@ async function mergeGooseConfig(shortName, proxyUrl, apiKey) {
|
|
|
2372
2452
|
writeMcpAddedLine(shortName, filePath);
|
|
2373
2453
|
return "ok";
|
|
2374
2454
|
}
|
|
2375
|
-
function printPlatformSnippet(platform, routingToken, shortName, apiKey) {
|
|
2455
|
+
function printPlatformSnippet(platform, routingToken, shortName, apiKey, codexCliTomlWritten) {
|
|
2376
2456
|
const hostedInlinePlatforms = /* @__PURE__ */ new Set([
|
|
2377
2457
|
"cursor",
|
|
2378
2458
|
"claude-desktop",
|
|
@@ -2486,11 +2566,12 @@ mcpServers:
|
|
|
2486
2566
|
2
|
|
2487
2567
|
);
|
|
2488
2568
|
} else if (platform === "codex-cli") {
|
|
2569
|
+
const bearerToken = authHeader.startsWith("Bearer ") ? authHeader.slice("Bearer ".length) : authHeader;
|
|
2489
2570
|
snippetText = `[mcp_servers.${shortName}]
|
|
2490
2571
|
url = "${urlInSnippet}"
|
|
2491
2572
|
|
|
2492
2573
|
[mcp_servers.${shortName}.http_headers]
|
|
2493
|
-
Authorization = "Bearer ${
|
|
2574
|
+
Authorization = "Bearer ${bearerToken}"
|
|
2494
2575
|
`;
|
|
2495
2576
|
} else {
|
|
2496
2577
|
const urlKey = platform === "windsurf" ? "serverUrl" : "url";
|
|
@@ -2536,11 +2617,15 @@ Authorization = "Bearer ${authHeader}"
|
|
|
2536
2617
|
) + "\n\n"
|
|
2537
2618
|
);
|
|
2538
2619
|
} else if (platform === "codex-cli") {
|
|
2539
|
-
|
|
2540
|
-
"\n" + style.dim(
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2620
|
+
if (codexCliTomlWritten === true) {
|
|
2621
|
+
process.stderr.write("\n" + style.dim("Added to ~/.codex/config.toml:") + "\n\n");
|
|
2622
|
+
} else {
|
|
2623
|
+
process.stderr.write(
|
|
2624
|
+
"\n" + style.dim(
|
|
2625
|
+
"Add this to ~/.codex/config.toml (create the file if it does not exist). Restart Codex CLI after saving."
|
|
2626
|
+
) + "\n\n"
|
|
2627
|
+
);
|
|
2628
|
+
}
|
|
2544
2629
|
} else if (platform === "github-copilot") {
|
|
2545
2630
|
process.stderr.write(
|
|
2546
2631
|
"\n" + style.dim(
|
|
@@ -2817,15 +2902,7 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
2817
2902
|
`);
|
|
2818
2903
|
}
|
|
2819
2904
|
process.stderr.write("\n" + style.bold("What would you like to do?") + "\n");
|
|
2820
|
-
const actionIdx = await arrowSelect(
|
|
2821
|
-
[
|
|
2822
|
-
"Add a new agent alongside these",
|
|
2823
|
-
"Replace an existing agent",
|
|
2824
|
-
"Skip - choose a different platform"
|
|
2825
|
-
],
|
|
2826
|
-
ask,
|
|
2827
|
-
"Action"
|
|
2828
|
-
);
|
|
2905
|
+
const actionIdx = await arrowSelect(INIT_EXISTING_AGENTS_PLATFORM_ACTIONS, ask, "Action");
|
|
2829
2906
|
if (actionIdx === 2) {
|
|
2830
2907
|
continue;
|
|
2831
2908
|
}
|
|
@@ -3335,11 +3412,6 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
3335
3412
|
apiKey,
|
|
3336
3413
|
initWorkspacePath
|
|
3337
3414
|
);
|
|
3338
|
-
process.stderr.write(
|
|
3339
|
-
"\n" + style.dim(
|
|
3340
|
-
"Add the TOML snippet above to ~/.codex/config.toml. Restart Codex CLI after saving."
|
|
3341
|
-
) + "\n"
|
|
3342
|
-
);
|
|
3343
3415
|
configuredAgents.push({
|
|
3344
3416
|
selection,
|
|
3345
3417
|
platform: selectedPlatform,
|
|
@@ -3676,8 +3748,9 @@ You have ${String(agentsForPlatform.length)} agent(s) connected for ${selectedLa
|
|
|
3676
3748
|
);
|
|
3677
3749
|
}
|
|
3678
3750
|
if (codexHostedConfigured) {
|
|
3751
|
+
const codexLabel = mcpPromptLabel2("codex-cli");
|
|
3679
3752
|
blocks.push(
|
|
3680
|
-
"\n" + style.bold("Codex CLI (hosted)") + "\n \u2192 Restart Codex CLI
|
|
3753
|
+
"\n" + style.bold("Codex CLI (hosted)") + "\n \u2192 Restart Codex CLI to load the new MCP server config\n \u2192 Verify it's connected: run /mcp in Codex CLI to see your active MCP servers\n \u2192 Try it - paste this into Codex:\n Use the " + codexLabel + " MCP server to list my GitHub repositories\n"
|
|
3681
3754
|
);
|
|
3682
3755
|
}
|
|
3683
3756
|
if (configuredPlatforms.has("other-mcp")) {
|
|
@@ -4585,7 +4658,7 @@ async function restoreClaudeDesktopMcpFromBackup() {
|
|
|
4585
4658
|
|
|
4586
4659
|
// package.json
|
|
4587
4660
|
var package_default = {
|
|
4588
|
-
version: "1.9.
|
|
4661
|
+
version: "1.9.5"};
|
|
4589
4662
|
|
|
4590
4663
|
// src/package-meta.ts
|
|
4591
4664
|
var PACKAGE_VERSION = package_default.version;
|
package/dist/shield-extension.js
CHANGED
|
@@ -22517,7 +22517,7 @@ async function writeExtensionBackup(claudeDesktopConfigPath, mcpServers) {
|
|
|
22517
22517
|
|
|
22518
22518
|
// package.json
|
|
22519
22519
|
var package_default = {
|
|
22520
|
-
version: "1.9.
|
|
22520
|
+
version: "1.9.5"};
|
|
22521
22521
|
|
|
22522
22522
|
// src/package-meta.ts
|
|
22523
22523
|
var PACKAGE_VERSION = package_default.version;
|
package/package.json
CHANGED
|
@@ -164,7 +164,7 @@ function openBrowser(url) {
|
|
|
164
164
|
function sleep(ms) {
|
|
165
165
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
166
166
|
}
|
|
167
|
-
async function pollApprovalStatus(config, approvalId) {
|
|
167
|
+
async function pollApprovalStatus(config, approvalId, consentLink) {
|
|
168
168
|
let lastProgressWrite = Date.now();
|
|
169
169
|
for (let i = 0; i < MAX_APPROVAL_POLLS; i++) {
|
|
170
170
|
if (i > 0) {
|
|
@@ -172,9 +172,8 @@ async function pollApprovalStatus(config, approvalId) {
|
|
|
172
172
|
}
|
|
173
173
|
const now = Date.now();
|
|
174
174
|
if (now - lastProgressWrite >= 3e4) {
|
|
175
|
-
process.stderr.write(
|
|
176
|
-
|
|
177
|
-
);
|
|
175
|
+
process.stderr.write(`[Shield] Waiting for approval... ${consentLink}
|
|
176
|
+
`);
|
|
178
177
|
lastProgressWrite = now;
|
|
179
178
|
}
|
|
180
179
|
let statusCode;
|
|
@@ -235,13 +234,16 @@ async function handlePendingWithConsentAndPoll(
|
|
|
235
234
|
actionType,
|
|
236
235
|
approvalsUrl,
|
|
237
236
|
) {
|
|
237
|
+
const consentLink = consentUrl(config.baseUrl, config.agentName, service, actionType);
|
|
238
|
+
process.stderr.write(`[Shield] Action requires approval. Open: ${consentLink}
|
|
239
|
+
`);
|
|
238
240
|
if (hasConsentMarker(config.agentName)) {
|
|
239
241
|
process.stderr.write(
|
|
240
242
|
`[Shield] Waiting for approval (up to 5 min)...
|
|
241
243
|
Approve in the Shield dashboard: ${approvalsUrl}
|
|
242
244
|
`,
|
|
243
245
|
);
|
|
244
|
-
const approved2 = await pollApprovalStatus(config, approvalId);
|
|
246
|
+
const approved2 = await pollApprovalStatus(config, approvalId, consentLink);
|
|
245
247
|
if (approved2) {
|
|
246
248
|
process.exit(0);
|
|
247
249
|
}
|
|
@@ -251,13 +253,12 @@ async function handlePendingWithConsentAndPoll(
|
|
|
251
253
|
);
|
|
252
254
|
process.exit(0);
|
|
253
255
|
}
|
|
254
|
-
const url = consentUrl(config.baseUrl, config.agentName, service, actionType);
|
|
255
256
|
writeConsentMarker(config.agentName);
|
|
256
|
-
openBrowser(
|
|
257
|
+
openBrowser(consentLink);
|
|
257
258
|
process.stderr.write(
|
|
258
259
|
"[Shield] Opening Shield consent screen... Waiting for approval (up to 5 min).\n",
|
|
259
260
|
);
|
|
260
|
-
const approved = await pollApprovalStatus(config, approvalId);
|
|
261
|
+
const approved = await pollApprovalStatus(config, approvalId, consentLink);
|
|
261
262
|
if (approved) {
|
|
262
263
|
process.exit(0);
|
|
263
264
|
}
|