@kvell007/embed-labs-cli 0.1.0-alpha.16 → 0.1.0-alpha.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/dist/index.js +207 -8
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -81,6 +81,18 @@ embedlabs doctor
|
|
|
81
81
|
embedlabs auth login --token <token>
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
+
If a cloud or plugin command reaches a protected API before a token is
|
|
85
|
+
configured, the CLI returns `auth_token_missing` with the registration URL and
|
|
86
|
+
these setup options:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
open https://api.embedboard.com/dashboard
|
|
90
|
+
embedlabs auth login --token <your_token>
|
|
91
|
+
# or for automation:
|
|
92
|
+
export EMBED_API_TOKEN=<your_token>
|
|
93
|
+
embedlabs auth status
|
|
94
|
+
```
|
|
95
|
+
|
|
84
96
|
For the current public API plus local TaishanPi verification path, see
|
|
85
97
|
`docs/runbooks/PUBLIC_CLI_USER_VERIFICATION.md`.
|
|
86
98
|
|
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ const qrcodeTerminal = require("qrcode-terminal");
|
|
|
18
18
|
const DEFAULT_BRIDGE_URL = process.env.EMBED_BRIDGE_URL ?? "http://127.0.0.1:18083";
|
|
19
19
|
const DEFAULT_CLOUD_API_URL = process.env.EMBED_CLOUD_API_URL ?? "http://127.0.0.1:18100";
|
|
20
20
|
const DEFAULT_AUTH_FILE = process.env.EMBED_AUTH_FILE ?? ".embed-labs/auth.json";
|
|
21
|
+
const DEFAULT_DASHBOARD_URL = process.env.EMBED_DASHBOARD_URL ?? "https://api.embedboard.com/dashboard";
|
|
21
22
|
const DEFAULT_AGENT_ARTIFACT_DIR = process.env.EMBED_AGENT_ARTIFACT_DIR ?? ".embed-labs/artifacts";
|
|
22
23
|
const DOCTOR_USAGE = "Usage: embed doctor [--json]";
|
|
23
24
|
const DOCTOR_HTTP_TIMEOUT_MS = 8000;
|
|
@@ -27,6 +28,8 @@ const DEVICE_PROBE_USAGE = "Usage: embed device probe --host <host> --ports 22,1
|
|
|
27
28
|
const QUERY_USAGE = "Usage: embed query <natural language request> [--account <account_id>] [--qr] [--json]";
|
|
28
29
|
const DEFAULT_PLUGIN_RELEASE_URL = process.env.EMBED_PLUGIN_RELEASE_URL?.trim() || "https://api.embedboard.com/plugin-releases/agent-plugins/latest";
|
|
29
30
|
const PLUGIN_LIST_USAGE = "Usage: embed plugin list [--release-dir <dir>] [--release-url <url>] [--json]";
|
|
31
|
+
const CODEX_PLUGIN_NAME = "embed-labs";
|
|
32
|
+
const CODEX_MARKETPLACE_NAME = "embed-labs-plugins";
|
|
30
33
|
const PLUGIN_INSTALL_USAGE = "Usage: embed plugin install <codex|opencode|all> [--release-dir <dir>] [--release-url <url>] [--target <dir>] [--codex-target <dir>] [--opencode-target <dir>] [--force] [--json]";
|
|
31
34
|
const CLOUD_TASK_ARTIFACTS_USAGE = "Usage: embed cloud task artifacts <task_id> [--json]";
|
|
32
35
|
const CLOUD_TASK_EVIDENCE_USAGE = "Usage: embed cloud task evidence <task_id> [--json]";
|
|
@@ -1200,7 +1203,8 @@ function authDoctorCheck(status) {
|
|
|
1200
1203
|
: {
|
|
1201
1204
|
code: "auth_not_ready",
|
|
1202
1205
|
message: "No CLI auth token is configured.",
|
|
1203
|
-
remediation:
|
|
1206
|
+
remediation: cloudAuthSetupRemediation(),
|
|
1207
|
+
details: cloudAuthSetupDetails()
|
|
1204
1208
|
}
|
|
1205
1209
|
};
|
|
1206
1210
|
}
|
|
@@ -1411,7 +1415,7 @@ async function cloudDownloadArtifact(artifactId, outputPath) {
|
|
|
1411
1415
|
});
|
|
1412
1416
|
if (!response.ok) {
|
|
1413
1417
|
const parsed = await parseErrorResponse(response);
|
|
1414
|
-
return parsed
|
|
1418
|
+
return parsed ? enrichCloudAuthFailure(parsed, Boolean(token)) : fail("artifact_download_failed", `Artifact download failed with HTTP ${response.status}.`);
|
|
1415
1419
|
}
|
|
1416
1420
|
const bytes = Buffer.from(await response.arrayBuffer());
|
|
1417
1421
|
const expectedSha256 = response.headers.get("x-embed-artifact-sha256")?.trim();
|
|
@@ -1454,7 +1458,8 @@ async function cloudRequest(method, path, body) {
|
|
|
1454
1458
|
headers: Object.keys(headers).length > 0 ? headers : undefined,
|
|
1455
1459
|
body: body === undefined ? undefined : bodyText
|
|
1456
1460
|
});
|
|
1457
|
-
|
|
1461
|
+
const parsed = await response.json();
|
|
1462
|
+
return enrichCloudAuthFailure(parsed, Boolean(token));
|
|
1458
1463
|
}
|
|
1459
1464
|
catch (error) {
|
|
1460
1465
|
return fail("cloud_api_unreachable", error instanceof Error ? error.message : String(error), {
|
|
@@ -1462,6 +1467,39 @@ async function cloudRequest(method, path, body) {
|
|
|
1462
1467
|
});
|
|
1463
1468
|
}
|
|
1464
1469
|
}
|
|
1470
|
+
function enrichCloudAuthFailure(response, hadToken) {
|
|
1471
|
+
if (response.ok || response.error.code !== "unauthorized") {
|
|
1472
|
+
return response;
|
|
1473
|
+
}
|
|
1474
|
+
if (!hadToken) {
|
|
1475
|
+
return fail("auth_token_missing", "Embed Labs API Token is not configured. Register or sign in, create an API Token, then configure it locally before using cloud and plugin services.", {
|
|
1476
|
+
remediation: cloudAuthSetupRemediation(),
|
|
1477
|
+
details: cloudAuthSetupDetails()
|
|
1478
|
+
});
|
|
1479
|
+
}
|
|
1480
|
+
return fail("auth_token_rejected", "The configured Embed Labs API Token was rejected by the server. Recreate or copy a fresh token from the dashboard and sign in again.", {
|
|
1481
|
+
remediation: cloudAuthSetupRemediation(),
|
|
1482
|
+
details: cloudAuthSetupDetails()
|
|
1483
|
+
});
|
|
1484
|
+
}
|
|
1485
|
+
function cloudAuthSetupRemediation() {
|
|
1486
|
+
return [
|
|
1487
|
+
`1. Open ${DEFAULT_DASHBOARD_URL} and register or sign in.`,
|
|
1488
|
+
"2. Create or copy your Embed Labs API Token from the user dashboard.",
|
|
1489
|
+
"3. Run: embedlabs auth login --token <your_token>",
|
|
1490
|
+
"4. For automation, set: EMBED_API_TOKEN=<your_token>",
|
|
1491
|
+
"5. Verify with: embedlabs auth status"
|
|
1492
|
+
].join("\n");
|
|
1493
|
+
}
|
|
1494
|
+
function cloudAuthSetupDetails() {
|
|
1495
|
+
return {
|
|
1496
|
+
dashboard_url: DEFAULT_DASHBOARD_URL,
|
|
1497
|
+
login_command: "embedlabs auth login --token <your_token>",
|
|
1498
|
+
env_var: "EMBED_API_TOKEN",
|
|
1499
|
+
auth_status_command: "embedlabs auth status",
|
|
1500
|
+
auth_file: DEFAULT_AUTH_FILE
|
|
1501
|
+
};
|
|
1502
|
+
}
|
|
1465
1503
|
function addCloudRequestSignature(headers, method, pathWithQuery, bodyText, token) {
|
|
1466
1504
|
if (process.env.EMBED_CLOUD_API_SIGNING === "0") {
|
|
1467
1505
|
return;
|
|
@@ -1600,7 +1638,7 @@ async function installCodexPlugin(parsed, context) {
|
|
|
1600
1638
|
return source;
|
|
1601
1639
|
}
|
|
1602
1640
|
const targetRoot = codexPluginTargetRoot(parsed, context.installingAll);
|
|
1603
|
-
const targetPath = join(targetRoot,
|
|
1641
|
+
const targetPath = join(targetRoot, CODEX_PLUGIN_NAME);
|
|
1604
1642
|
const legacyCleanup = await cleanupLegacyCodexPluginRemnants(targetRoot);
|
|
1605
1643
|
if (await pathExists(targetPath) && !booleanFlag(parsed, "force")) {
|
|
1606
1644
|
return fail("plugin_already_installed", `Codex plugin already exists at ${targetPath}.`, {
|
|
@@ -1611,17 +1649,23 @@ async function installCodexPlugin(parsed, context) {
|
|
|
1611
1649
|
await mkdir(targetRoot, { recursive: true });
|
|
1612
1650
|
await cp(source.data.sourcePath, targetPath, { recursive: true });
|
|
1613
1651
|
const mcpRegistration = await maybeRegisterCodexMcp(parsed, targetRoot, targetPath);
|
|
1652
|
+
const marketplaceRegistration = await maybeRegisterCodexMarketplace(parsed, targetRoot, targetPath);
|
|
1614
1653
|
return ok({
|
|
1615
1654
|
id: "codex",
|
|
1616
1655
|
target_path: targetPath,
|
|
1617
1656
|
source: source.data.sourceLabel,
|
|
1618
1657
|
version: source.data.version,
|
|
1619
1658
|
command_hint: mcpRegistration.registered
|
|
1620
|
-
?
|
|
1659
|
+
? (marketplaceRegistration.registered
|
|
1660
|
+
? "Codex MCP and plugin marketplace entry were registered. Fully restart Codex to reload @Embed Labs."
|
|
1661
|
+
: "Codex MCP was registered. Start a new Codex session to reload tools.")
|
|
1621
1662
|
: mcpRegistration.hint,
|
|
1622
1663
|
warning: legacyCodexCleanupWarning(legacyCleanup),
|
|
1623
1664
|
mcp_registered: mcpRegistration.registered,
|
|
1624
1665
|
mcp_warning: mcpRegistration.warning,
|
|
1666
|
+
marketplace_registered: marketplaceRegistration.registered,
|
|
1667
|
+
marketplace_path: marketplaceRegistration.marketplacePath,
|
|
1668
|
+
marketplace_warning: marketplaceRegistration.warning,
|
|
1625
1669
|
cleanup: legacyCleanup
|
|
1626
1670
|
});
|
|
1627
1671
|
}
|
|
@@ -1914,7 +1958,8 @@ async function cleanupLegacyCodexPluginRemnants(targetRoot) {
|
|
|
1914
1958
|
];
|
|
1915
1959
|
legacyPaths.push(...await discoverLegacyCodexCachePaths(targetRoot));
|
|
1916
1960
|
if (resolve(targetRoot) === resolve(defaultCodexPluginRoot())) {
|
|
1917
|
-
legacyPaths.push(join(defaultCodexHome(), ".tmp", "plugins"), join(defaultCodexHome(), ".tmp", "plugins.sha"), join(defaultCodexHome(), "skills", "dbt-agent"), join(defaultCodexHome(), "skills", "development-board-toolchain-dev"), join(defaultCodexHome(), "memories", "skills", "dbt-agent-live-board-ops"), join(defaultCodexHome(), "memories", "skills", "dbt-agent-platform-plugin-maintenance"));
|
|
1961
|
+
legacyPaths.push(join(defaultCodexHome(), ".tmp", "plugins"), join(defaultCodexHome(), ".tmp", "plugins.sha"), join(defaultCodexHome(), "ambient-suggestions"), join(defaultCodexHome(), "skills", "dbt-agent"), join(defaultCodexHome(), "skills", "development-board-toolchain-dev"), join(defaultCodexHome(), "memories", "skills", "dbt-agent-live-board-ops"), join(defaultCodexHome(), "memories", "skills", "dbt-agent-platform-plugin-maintenance"));
|
|
1962
|
+
legacyPaths.push(...await discoverLegacyHomeAgentsMarketplacePaths(warnings), ...legacyDevelopmentBoardRuntimePluginPaths());
|
|
1918
1963
|
}
|
|
1919
1964
|
for (const candidate of legacyPaths) {
|
|
1920
1965
|
try {
|
|
@@ -1986,7 +2031,56 @@ async function stopLegacyCodexPluginProcesses(warnings) {
|
|
|
1986
2031
|
function isLegacyCodexPluginProcess(command) {
|
|
1987
2032
|
const trimmed = command.trim();
|
|
1988
2033
|
return /^\/.*\/dbt-agent-mcp-bridge(?:\s|$)/.test(trimmed)
|
|
1989
|
-
|| /^dbt-agent-mcp-bridge(?:\s|$)/.test(trimmed)
|
|
2034
|
+
|| /^dbt-agent-mcp-bridge(?:\s|$)/.test(trimmed)
|
|
2035
|
+
|| legacyDevelopmentBoardRuntimeProcessPatterns().some((pattern) => pattern.test(trimmed));
|
|
2036
|
+
}
|
|
2037
|
+
function legacyDevelopmentBoardRuntimeProcessPatterns() {
|
|
2038
|
+
const home = escapeRegExp(homedir());
|
|
2039
|
+
return [
|
|
2040
|
+
new RegExp(`^${home}/Library/development-board-toolchain/agent/bin/dbt-agentd(?:\\s|$)`),
|
|
2041
|
+
new RegExp(`^${home}/Library/Application Support/development-board-toolchain/agent/bin/dbt-agentd(?:\\s|$)`),
|
|
2042
|
+
new RegExp(`^${home}/Library/development-board-toolchain/runtime/dbtctl\\s+status(?:\\s|$)`),
|
|
2043
|
+
new RegExp(`^${home}/Library/Application Support/development-board-toolchain/runtime/dbtctl\\s+status(?:\\s|$)`),
|
|
2044
|
+
new RegExp(`^${home}/.*?/DBT-Agent\\.app/Contents/MacOS/DBT-Agent(?:\\s|$)`)
|
|
2045
|
+
];
|
|
2046
|
+
}
|
|
2047
|
+
function legacyDevelopmentBoardRuntimePluginPaths() {
|
|
2048
|
+
return [
|
|
2049
|
+
join(homedir(), "Library", "development-board-toolchain", "runtime", "editor_plugins"),
|
|
2050
|
+
join(homedir(), "Library", "development-board-toolchain", "runtime", "opencode_plugin"),
|
|
2051
|
+
join(homedir(), "Library", "Application Support", "development-board-toolchain", "runtime", "editor_plugins"),
|
|
2052
|
+
join(homedir(), "Library", "Application Support", "development-board-toolchain", "runtime", "opencode_plugin")
|
|
2053
|
+
];
|
|
2054
|
+
}
|
|
2055
|
+
async function discoverLegacyHomeAgentsMarketplacePaths(warnings) {
|
|
2056
|
+
const paths = [];
|
|
2057
|
+
const pluginRoot = join(homedir(), ".agents", "plugins");
|
|
2058
|
+
try {
|
|
2059
|
+
const entries = await readdir(pluginRoot, { withFileTypes: true });
|
|
2060
|
+
for (const entry of entries) {
|
|
2061
|
+
if (!entry.isFile() || !entry.name.startsWith("marketplace.json"))
|
|
2062
|
+
continue;
|
|
2063
|
+
const filePath = join(pluginRoot, entry.name);
|
|
2064
|
+
try {
|
|
2065
|
+
const current = await readFile(filePath, "utf8");
|
|
2066
|
+
if (isLegacyHomeAgentsMarketplace(current)) {
|
|
2067
|
+
paths.push(filePath);
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
catch (error) {
|
|
2071
|
+
warnings.push(`Could not inspect legacy Codex home marketplace ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
2072
|
+
}
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
catch {
|
|
2076
|
+
return paths;
|
|
2077
|
+
}
|
|
2078
|
+
return paths;
|
|
2079
|
+
}
|
|
2080
|
+
function isLegacyHomeAgentsMarketplace(text) {
|
|
2081
|
+
return text.includes('"name" : "plugins"') || text.includes('"name": "plugins"')
|
|
2082
|
+
? text.includes('"dbt-agent"') || text.includes('"./.codex/plugins/dbt-agent"') || text.includes('"./plugins/dbt-agent"')
|
|
2083
|
+
: false;
|
|
1990
2084
|
}
|
|
1991
2085
|
async function discoverLegacyCodexCachePaths(targetRoot) {
|
|
1992
2086
|
const paths = [];
|
|
@@ -2074,7 +2168,8 @@ function isLegacyCodexConfigTable(table) {
|
|
|
2074
2168
|
|| table === "mcp_servers.dbt-agent"
|
|
2075
2169
|
|| table.startsWith("mcp_servers.dbt-agent.")
|
|
2076
2170
|
|| table === 'mcp_servers."dbt-agent"'
|
|
2077
|
-
|| table.startsWith('mcp_servers."dbt-agent".')
|
|
2171
|
+
|| table.startsWith('mcp_servers."dbt-agent".')
|
|
2172
|
+
|| /^projects\."[^"]*\/DBT-Agent-Project(?:\/[^"]*)?"$/.test(table);
|
|
2078
2173
|
}
|
|
2079
2174
|
function legacyCodexCleanupWarning(cleanup) {
|
|
2080
2175
|
const parts = [];
|
|
@@ -2224,6 +2319,101 @@ async function maybeRegisterCodexMcp(parsed, targetRoot, targetPath) {
|
|
|
2224
2319
|
const warning = await upsertCodexMcpRuntimeConfig(bridgePath);
|
|
2225
2320
|
return warning ? { registered: true, warning } : { registered: true };
|
|
2226
2321
|
}
|
|
2322
|
+
async function maybeRegisterCodexMarketplace(parsed, targetRoot, targetPath) {
|
|
2323
|
+
const explicitTarget = Boolean(stringFlag(parsed, "target") || stringFlag(parsed, "codex-target"));
|
|
2324
|
+
if (explicitTarget && process.env.EMBED_CODEX_MARKETPLACE_REGISTER !== "1") {
|
|
2325
|
+
return {
|
|
2326
|
+
registered: false,
|
|
2327
|
+
warning: "Codex plugin marketplace entry was not registered because a custom target was used. Set EMBED_CODEX_MARKETPLACE_REGISTER=1 to register it anyway."
|
|
2328
|
+
};
|
|
2329
|
+
}
|
|
2330
|
+
if (resolve(targetRoot) !== resolve(defaultCodexPluginRoot()) && process.env.EMBED_CODEX_MARKETPLACE_REGISTER !== "1") {
|
|
2331
|
+
return {
|
|
2332
|
+
registered: false,
|
|
2333
|
+
warning: "Codex plugin marketplace entry was not registered because the install target is not the default Codex plugin root."
|
|
2334
|
+
};
|
|
2335
|
+
}
|
|
2336
|
+
const marketplacePath = defaultCodexLocalMarketplaceRoot();
|
|
2337
|
+
const marketplacePluginPath = join(marketplacePath, "plugins", CODEX_PLUGIN_NAME);
|
|
2338
|
+
try {
|
|
2339
|
+
if (!await pathExists(join(targetPath, ".codex-plugin", "plugin.json"))) {
|
|
2340
|
+
return {
|
|
2341
|
+
registered: false,
|
|
2342
|
+
warning: `Codex plugin manifest was not found at ${join(targetPath, ".codex-plugin", "plugin.json")}.`
|
|
2343
|
+
};
|
|
2344
|
+
}
|
|
2345
|
+
await rm(marketplacePluginPath, { recursive: true, force: true });
|
|
2346
|
+
await mkdir(dirname(marketplacePluginPath), { recursive: true });
|
|
2347
|
+
await cp(targetPath, marketplacePluginPath, { recursive: true });
|
|
2348
|
+
await writeCodexLocalMarketplaceManifest(marketplacePath);
|
|
2349
|
+
const warning = await upsertCodexPluginMarketplaceConfig(marketplacePath);
|
|
2350
|
+
return warning ? { registered: true, marketplacePath, warning } : { registered: true, marketplacePath };
|
|
2351
|
+
}
|
|
2352
|
+
catch (error) {
|
|
2353
|
+
return {
|
|
2354
|
+
registered: false,
|
|
2355
|
+
marketplacePath,
|
|
2356
|
+
warning: `Could not register Codex plugin marketplace entry: ${error instanceof Error ? error.message : String(error)}`
|
|
2357
|
+
};
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
function defaultCodexLocalMarketplaceRoot() {
|
|
2361
|
+
return join(defaultCodexHome(), "local-marketplaces", CODEX_PLUGIN_NAME);
|
|
2362
|
+
}
|
|
2363
|
+
async function writeCodexLocalMarketplaceManifest(marketplacePath) {
|
|
2364
|
+
const manifestPath = join(marketplacePath, ".agents", "plugins", "marketplace.json");
|
|
2365
|
+
const manifest = {
|
|
2366
|
+
name: CODEX_MARKETPLACE_NAME,
|
|
2367
|
+
interface: {
|
|
2368
|
+
displayName: "Embed Labs"
|
|
2369
|
+
},
|
|
2370
|
+
plugins: [
|
|
2371
|
+
{
|
|
2372
|
+
name: CODEX_PLUGIN_NAME,
|
|
2373
|
+
source: {
|
|
2374
|
+
source: "local",
|
|
2375
|
+
path: `./plugins/${CODEX_PLUGIN_NAME}`
|
|
2376
|
+
},
|
|
2377
|
+
policy: {
|
|
2378
|
+
installation: "AVAILABLE",
|
|
2379
|
+
authentication: "ON_USE"
|
|
2380
|
+
},
|
|
2381
|
+
category: "Developer Tools"
|
|
2382
|
+
}
|
|
2383
|
+
]
|
|
2384
|
+
};
|
|
2385
|
+
await mkdir(dirname(manifestPath), { recursive: true });
|
|
2386
|
+
await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, "utf8");
|
|
2387
|
+
}
|
|
2388
|
+
async function upsertCodexPluginMarketplaceConfig(marketplacePath) {
|
|
2389
|
+
const configPath = codexConfigPath();
|
|
2390
|
+
try {
|
|
2391
|
+
await mkdir(dirname(configPath), { recursive: true });
|
|
2392
|
+
let text = "";
|
|
2393
|
+
try {
|
|
2394
|
+
text = await readFile(configPath, "utf8");
|
|
2395
|
+
}
|
|
2396
|
+
catch {
|
|
2397
|
+
text = "";
|
|
2398
|
+
}
|
|
2399
|
+
text = removeLegacyCodexConfigTables(text).text;
|
|
2400
|
+
let updated = upsertTomlTableKeys(text, `marketplaces.${CODEX_MARKETPLACE_NAME}`, {
|
|
2401
|
+
source_type: tomlString("local"),
|
|
2402
|
+
source: tomlString(marketplacePath),
|
|
2403
|
+
last_updated: tomlString(new Date().toISOString().replace(/\.\d{3}Z$/, "Z"))
|
|
2404
|
+
});
|
|
2405
|
+
updated = upsertTomlTableKeys(updated, `plugins."${CODEX_PLUGIN_NAME}@${CODEX_MARKETPLACE_NAME}"`, {
|
|
2406
|
+
enabled: "true"
|
|
2407
|
+
});
|
|
2408
|
+
if (updated !== text) {
|
|
2409
|
+
await writeFile(configPath, updated, "utf8");
|
|
2410
|
+
}
|
|
2411
|
+
return undefined;
|
|
2412
|
+
}
|
|
2413
|
+
catch (error) {
|
|
2414
|
+
return `${configPath} could not be updated with the Embed Labs plugin marketplace entry: ${error instanceof Error ? error.message : String(error)}`;
|
|
2415
|
+
}
|
|
2416
|
+
}
|
|
2227
2417
|
function codexMcpAlreadyRegistered(stdout, bridgePath, cloudUrl, authFile, embedCliBin) {
|
|
2228
2418
|
try {
|
|
2229
2419
|
const parsed = JSON.parse(stdout);
|
|
@@ -5136,6 +5326,15 @@ function renderPluginInstall(result) {
|
|
|
5136
5326
|
if (item.mcp_warning) {
|
|
5137
5327
|
lines.push(` warning=${item.mcp_warning}`);
|
|
5138
5328
|
}
|
|
5329
|
+
if (item.marketplace_registered !== undefined) {
|
|
5330
|
+
lines.push(` codex_marketplace_registered=${item.marketplace_registered}`);
|
|
5331
|
+
}
|
|
5332
|
+
if (item.marketplace_path) {
|
|
5333
|
+
lines.push(` codex_marketplace=${item.marketplace_path}`);
|
|
5334
|
+
}
|
|
5335
|
+
if (item.marketplace_warning) {
|
|
5336
|
+
lines.push(` warning=${item.marketplace_warning}`);
|
|
5337
|
+
}
|
|
5139
5338
|
}
|
|
5140
5339
|
return lines.join("\n");
|
|
5141
5340
|
}
|