@ornncompute/cli 0.2.16 → 0.2.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/package.json
CHANGED
package/src/update.mjs
CHANGED
|
@@ -125,7 +125,7 @@ export function detectInstallContext(binPath, env = process.env) {
|
|
|
125
125
|
if (isNpmGlobalInstall(lower, env)) {
|
|
126
126
|
return { kind: "npm", binPath: resolved };
|
|
127
127
|
}
|
|
128
|
-
if (isProjectInstall(resolved
|
|
128
|
+
if (isProjectInstall(resolved)) {
|
|
129
129
|
return { kind: "project", binPath: resolved };
|
|
130
130
|
}
|
|
131
131
|
if (has(".bun") || isUnderDir(lower, env.BUN_INSTALL)) {
|
|
@@ -140,14 +140,15 @@ export function detectInstallContext(binPath, env = process.env) {
|
|
|
140
140
|
return { kind: "npm", binPath: resolved };
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
function isProjectInstall(resolvedPath
|
|
143
|
+
function isProjectInstall(resolvedPath) {
|
|
144
144
|
// Global layouts have no package.json above node_modules; projects do.
|
|
145
|
-
const
|
|
146
|
-
|
|
145
|
+
const parts = resolvedPath.replaceAll("\\", "/").split("/");
|
|
146
|
+
const index = parts.findIndex((segment) => segment.toLowerCase() === "node_modules");
|
|
147
|
+
if (index <= 0) {
|
|
147
148
|
return false;
|
|
148
149
|
}
|
|
149
150
|
try {
|
|
150
|
-
return existsSync(join(
|
|
151
|
+
return existsSync(join(parts.slice(0, index).join("/"), "package.json"));
|
|
151
152
|
} catch {
|
|
152
153
|
return false;
|
|
153
154
|
}
|
|
@@ -212,9 +213,13 @@ function stableInstallRoot(binPath) {
|
|
|
212
213
|
try {
|
|
213
214
|
resolved = realpathSync(binPath);
|
|
214
215
|
} catch {}
|
|
215
|
-
const
|
|
216
|
-
const
|
|
217
|
-
|
|
216
|
+
const parts = resolved.replaceAll("\\", "/").split("/");
|
|
217
|
+
const index = parts.findIndex((segment) => segment.toLowerCase() === "node_modules");
|
|
218
|
+
if (index <= 0) {
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
const prefix = parts.slice(0, index).join("/");
|
|
222
|
+
return prefix.length > 0 ? prefix : null;
|
|
218
223
|
}
|
|
219
224
|
|
|
220
225
|
function pathIdentity(path) {
|
|
@@ -200,7 +200,21 @@ export const sshKeyAddCapability = defineStaffMcpCapability({
|
|
|
200
200
|
// (gateway `add_reservation_key`), which this tool previously bypassed by
|
|
201
201
|
// posting `public_key` into a body that only reads `sshKeyId`/`userId`.
|
|
202
202
|
let sshKeyId = parsed.sshKeyId;
|
|
203
|
-
if (
|
|
203
|
+
if (sshKeyId) {
|
|
204
|
+
// Commerce stores the id as a soft key without checking authorization,
|
|
205
|
+
// so gate it here the way gateway `add_reservation_key` does.
|
|
206
|
+
const listed = (await ctx.fetch(`/v1/organizations/${seg(parsed.tenantId)}/ssh-keys`, {
|
|
207
|
+
method: "GET",
|
|
208
|
+
}));
|
|
209
|
+
const key = (listed.ssh_keys ?? []).find((candidate) => candidate.id === sshKeyId);
|
|
210
|
+
if (!key) {
|
|
211
|
+
throw new Error("SSH key not found.");
|
|
212
|
+
}
|
|
213
|
+
if (key.status !== "active" || key.revoked_at) {
|
|
214
|
+
throw new Error("SSH key is not active.");
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
204
218
|
const registered = (await ctx.fetch(`/v1/organizations/${seg(parsed.tenantId)}/ssh-keys`, {
|
|
205
219
|
method: "POST",
|
|
206
220
|
body: { public_key: parsed.publicKey, ...mapBody(parsed, { label: "label" }) },
|