@kvell007/embed-labs-cli 0.1.0-alpha.16 → 0.1.0-alpha.17
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 +93 -6
- 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;
|
|
@@ -1200,7 +1201,8 @@ function authDoctorCheck(status) {
|
|
|
1200
1201
|
: {
|
|
1201
1202
|
code: "auth_not_ready",
|
|
1202
1203
|
message: "No CLI auth token is configured.",
|
|
1203
|
-
remediation:
|
|
1204
|
+
remediation: cloudAuthSetupRemediation(),
|
|
1205
|
+
details: cloudAuthSetupDetails()
|
|
1204
1206
|
}
|
|
1205
1207
|
};
|
|
1206
1208
|
}
|
|
@@ -1411,7 +1413,7 @@ async function cloudDownloadArtifact(artifactId, outputPath) {
|
|
|
1411
1413
|
});
|
|
1412
1414
|
if (!response.ok) {
|
|
1413
1415
|
const parsed = await parseErrorResponse(response);
|
|
1414
|
-
return parsed
|
|
1416
|
+
return parsed ? enrichCloudAuthFailure(parsed, Boolean(token)) : fail("artifact_download_failed", `Artifact download failed with HTTP ${response.status}.`);
|
|
1415
1417
|
}
|
|
1416
1418
|
const bytes = Buffer.from(await response.arrayBuffer());
|
|
1417
1419
|
const expectedSha256 = response.headers.get("x-embed-artifact-sha256")?.trim();
|
|
@@ -1454,7 +1456,8 @@ async function cloudRequest(method, path, body) {
|
|
|
1454
1456
|
headers: Object.keys(headers).length > 0 ? headers : undefined,
|
|
1455
1457
|
body: body === undefined ? undefined : bodyText
|
|
1456
1458
|
});
|
|
1457
|
-
|
|
1459
|
+
const parsed = await response.json();
|
|
1460
|
+
return enrichCloudAuthFailure(parsed, Boolean(token));
|
|
1458
1461
|
}
|
|
1459
1462
|
catch (error) {
|
|
1460
1463
|
return fail("cloud_api_unreachable", error instanceof Error ? error.message : String(error), {
|
|
@@ -1462,6 +1465,39 @@ async function cloudRequest(method, path, body) {
|
|
|
1462
1465
|
});
|
|
1463
1466
|
}
|
|
1464
1467
|
}
|
|
1468
|
+
function enrichCloudAuthFailure(response, hadToken) {
|
|
1469
|
+
if (response.ok || response.error.code !== "unauthorized") {
|
|
1470
|
+
return response;
|
|
1471
|
+
}
|
|
1472
|
+
if (!hadToken) {
|
|
1473
|
+
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.", {
|
|
1474
|
+
remediation: cloudAuthSetupRemediation(),
|
|
1475
|
+
details: cloudAuthSetupDetails()
|
|
1476
|
+
});
|
|
1477
|
+
}
|
|
1478
|
+
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.", {
|
|
1479
|
+
remediation: cloudAuthSetupRemediation(),
|
|
1480
|
+
details: cloudAuthSetupDetails()
|
|
1481
|
+
});
|
|
1482
|
+
}
|
|
1483
|
+
function cloudAuthSetupRemediation() {
|
|
1484
|
+
return [
|
|
1485
|
+
`1. Open ${DEFAULT_DASHBOARD_URL} and register or sign in.`,
|
|
1486
|
+
"2. Create or copy your Embed Labs API Token from the user dashboard.",
|
|
1487
|
+
"3. Run: embedlabs auth login --token <your_token>",
|
|
1488
|
+
"4. For automation, set: EMBED_API_TOKEN=<your_token>",
|
|
1489
|
+
"5. Verify with: embedlabs auth status"
|
|
1490
|
+
].join("\n");
|
|
1491
|
+
}
|
|
1492
|
+
function cloudAuthSetupDetails() {
|
|
1493
|
+
return {
|
|
1494
|
+
dashboard_url: DEFAULT_DASHBOARD_URL,
|
|
1495
|
+
login_command: "embedlabs auth login --token <your_token>",
|
|
1496
|
+
env_var: "EMBED_API_TOKEN",
|
|
1497
|
+
auth_status_command: "embedlabs auth status",
|
|
1498
|
+
auth_file: DEFAULT_AUTH_FILE
|
|
1499
|
+
};
|
|
1500
|
+
}
|
|
1465
1501
|
function addCloudRequestSignature(headers, method, pathWithQuery, bodyText, token) {
|
|
1466
1502
|
if (process.env.EMBED_CLOUD_API_SIGNING === "0") {
|
|
1467
1503
|
return;
|
|
@@ -1914,7 +1950,8 @@ async function cleanupLegacyCodexPluginRemnants(targetRoot) {
|
|
|
1914
1950
|
];
|
|
1915
1951
|
legacyPaths.push(...await discoverLegacyCodexCachePaths(targetRoot));
|
|
1916
1952
|
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"));
|
|
1953
|
+
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"));
|
|
1954
|
+
legacyPaths.push(...await discoverLegacyHomeAgentsMarketplacePaths(warnings), ...legacyDevelopmentBoardRuntimePluginPaths());
|
|
1918
1955
|
}
|
|
1919
1956
|
for (const candidate of legacyPaths) {
|
|
1920
1957
|
try {
|
|
@@ -1986,7 +2023,56 @@ async function stopLegacyCodexPluginProcesses(warnings) {
|
|
|
1986
2023
|
function isLegacyCodexPluginProcess(command) {
|
|
1987
2024
|
const trimmed = command.trim();
|
|
1988
2025
|
return /^\/.*\/dbt-agent-mcp-bridge(?:\s|$)/.test(trimmed)
|
|
1989
|
-
|| /^dbt-agent-mcp-bridge(?:\s|$)/.test(trimmed)
|
|
2026
|
+
|| /^dbt-agent-mcp-bridge(?:\s|$)/.test(trimmed)
|
|
2027
|
+
|| legacyDevelopmentBoardRuntimeProcessPatterns().some((pattern) => pattern.test(trimmed));
|
|
2028
|
+
}
|
|
2029
|
+
function legacyDevelopmentBoardRuntimeProcessPatterns() {
|
|
2030
|
+
const home = escapeRegExp(homedir());
|
|
2031
|
+
return [
|
|
2032
|
+
new RegExp(`^${home}/Library/development-board-toolchain/agent/bin/dbt-agentd(?:\\s|$)`),
|
|
2033
|
+
new RegExp(`^${home}/Library/Application Support/development-board-toolchain/agent/bin/dbt-agentd(?:\\s|$)`),
|
|
2034
|
+
new RegExp(`^${home}/Library/development-board-toolchain/runtime/dbtctl\\s+status(?:\\s|$)`),
|
|
2035
|
+
new RegExp(`^${home}/Library/Application Support/development-board-toolchain/runtime/dbtctl\\s+status(?:\\s|$)`),
|
|
2036
|
+
new RegExp(`^${home}/.*?/DBT-Agent\\.app/Contents/MacOS/DBT-Agent(?:\\s|$)`)
|
|
2037
|
+
];
|
|
2038
|
+
}
|
|
2039
|
+
function legacyDevelopmentBoardRuntimePluginPaths() {
|
|
2040
|
+
return [
|
|
2041
|
+
join(homedir(), "Library", "development-board-toolchain", "runtime", "editor_plugins"),
|
|
2042
|
+
join(homedir(), "Library", "development-board-toolchain", "runtime", "opencode_plugin"),
|
|
2043
|
+
join(homedir(), "Library", "Application Support", "development-board-toolchain", "runtime", "editor_plugins"),
|
|
2044
|
+
join(homedir(), "Library", "Application Support", "development-board-toolchain", "runtime", "opencode_plugin")
|
|
2045
|
+
];
|
|
2046
|
+
}
|
|
2047
|
+
async function discoverLegacyHomeAgentsMarketplacePaths(warnings) {
|
|
2048
|
+
const paths = [];
|
|
2049
|
+
const pluginRoot = join(homedir(), ".agents", "plugins");
|
|
2050
|
+
try {
|
|
2051
|
+
const entries = await readdir(pluginRoot, { withFileTypes: true });
|
|
2052
|
+
for (const entry of entries) {
|
|
2053
|
+
if (!entry.isFile() || !entry.name.startsWith("marketplace.json"))
|
|
2054
|
+
continue;
|
|
2055
|
+
const filePath = join(pluginRoot, entry.name);
|
|
2056
|
+
try {
|
|
2057
|
+
const current = await readFile(filePath, "utf8");
|
|
2058
|
+
if (isLegacyHomeAgentsMarketplace(current)) {
|
|
2059
|
+
paths.push(filePath);
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
catch (error) {
|
|
2063
|
+
warnings.push(`Could not inspect legacy Codex home marketplace ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
2064
|
+
}
|
|
2065
|
+
}
|
|
2066
|
+
}
|
|
2067
|
+
catch {
|
|
2068
|
+
return paths;
|
|
2069
|
+
}
|
|
2070
|
+
return paths;
|
|
2071
|
+
}
|
|
2072
|
+
function isLegacyHomeAgentsMarketplace(text) {
|
|
2073
|
+
return text.includes('"name" : "plugins"') || text.includes('"name": "plugins"')
|
|
2074
|
+
? text.includes('"dbt-agent"') || text.includes('"./.codex/plugins/dbt-agent"') || text.includes('"./plugins/dbt-agent"')
|
|
2075
|
+
: false;
|
|
1990
2076
|
}
|
|
1991
2077
|
async function discoverLegacyCodexCachePaths(targetRoot) {
|
|
1992
2078
|
const paths = [];
|
|
@@ -2074,7 +2160,8 @@ function isLegacyCodexConfigTable(table) {
|
|
|
2074
2160
|
|| table === "mcp_servers.dbt-agent"
|
|
2075
2161
|
|| table.startsWith("mcp_servers.dbt-agent.")
|
|
2076
2162
|
|| table === 'mcp_servers."dbt-agent"'
|
|
2077
|
-
|| table.startsWith('mcp_servers."dbt-agent".')
|
|
2163
|
+
|| table.startsWith('mcp_servers."dbt-agent".')
|
|
2164
|
+
|| /^projects\."[^"]*\/DBT-Agent-Project(?:\/[^"]*)?"$/.test(table);
|
|
2078
2165
|
}
|
|
2079
2166
|
function legacyCodexCleanupWarning(cleanup) {
|
|
2080
2167
|
const parts = [];
|