@amerged/ohmyhost-mcp 0.1.18 → 0.1.20
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 +1 -1
- package/dist/{chunk-X6IS5LX7.js → chunk-NESQZ3BS.js} +7 -7
- package/dist/index.js +1 -1
- package/dist/stdio-main.js +1316 -165
- package/package.json +1 -1
- package/src/apps/mcp/local-client.ts +86 -17
- package/src/apps/mcp/local-server.ts +280 -86
- package/src/apps/mcp/stdio-main.ts +11 -2
- package/src/apps/product-cli/cli.ts +337 -92
- package/src/apps/product-cli/command.ts +111 -6
- package/src/apps/product-cli/composition.ts +748 -120
- package/src/apps/product-cli/credential-store.ts +5 -3
- package/src/apps/product-cli/index.ts +2 -0
- package/src/apps/product-cli/product-api.ts +4 -4
- package/src/apps/product-cli/profile-store.ts +609 -0
- package/src/apps/product-cli/project-link-store.ts +169 -20
- package/src/apps/product-cli/runtime-contract.ts +15 -4
- package/src/apps/product-cli/workspace.ts +75 -13
- package/src/packages/agent-skills/generated-skill-resources.ts +6 -6
- package/src/packages/sdk-ts/generated/sdk.gen.ts +1 -1
package/dist/stdio-main.js
CHANGED
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
serverIdentityOf,
|
|
27
27
|
setNegotiatedProtocolVersion,
|
|
28
28
|
validateEnvelopeMeta
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-NESQZ3BS.js";
|
|
30
30
|
|
|
31
31
|
// node_modules/.pnpm/@modelcontextprotocol+server@2.0.0/node_modules/@modelcontextprotocol/server/dist/stdio.mjs
|
|
32
32
|
var StdioServerTransport = class {
|
|
@@ -799,7 +799,7 @@ function exact2(v, keys) {
|
|
|
799
799
|
// apps/product-cli/package.json
|
|
800
800
|
var package_default = {
|
|
801
801
|
name: "@ohmyhost/product-cli",
|
|
802
|
-
version: "0.1.
|
|
802
|
+
version: "0.1.20",
|
|
803
803
|
private: true,
|
|
804
804
|
ohmyhost: {
|
|
805
805
|
deployment: "production",
|
|
@@ -1210,6 +1210,15 @@ function expectPositiveInteger(value, field, options = {}) {
|
|
|
1210
1210
|
return value;
|
|
1211
1211
|
}
|
|
1212
1212
|
|
|
1213
|
+
// packages/workos-auth-contracts/dist/user-api-keys.js
|
|
1214
|
+
var WORKOS_USER_API_KEY_PATTERN = /^sk_[A-Za-z0-9_-]{20,128}$/u;
|
|
1215
|
+
|
|
1216
|
+
// apps/product-cli/dist/profile-store.js
|
|
1217
|
+
import { randomUUID } from "node:crypto";
|
|
1218
|
+
import { link, mkdir as mkdir2, open as open2, readFile, readdir, unlink } from "node:fs/promises";
|
|
1219
|
+
import { homedir } from "node:os";
|
|
1220
|
+
import { join } from "node:path";
|
|
1221
|
+
|
|
1213
1222
|
// apps/product-cli/dist/credential-store.js
|
|
1214
1223
|
var CredentialStoreUnavailableError = class extends Error {
|
|
1215
1224
|
constructor() {
|
|
@@ -1223,10 +1232,12 @@ var CredentialStoreIntegrityError = class extends Error {
|
|
|
1223
1232
|
this.name = "CredentialStoreIntegrityError";
|
|
1224
1233
|
}
|
|
1225
1234
|
};
|
|
1226
|
-
var
|
|
1235
|
+
var LEGACY_CREDENTIAL_ACCOUNT = "credential";
|
|
1227
1236
|
var NativeNapiKeyringCredentialStore = class {
|
|
1237
|
+
account;
|
|
1228
1238
|
createEntry;
|
|
1229
|
-
constructor(createEntry = void 0, serviceName = "ohmyhost") {
|
|
1239
|
+
constructor(createEntry = void 0, serviceName = "ohmyhost", account = LEGACY_CREDENTIAL_ACCOUNT) {
|
|
1240
|
+
this.account = account;
|
|
1230
1241
|
this.createEntry = createEntry ?? createNativeEntryFactory(serviceName);
|
|
1231
1242
|
}
|
|
1232
1243
|
async read() {
|
|
@@ -1248,7 +1259,7 @@ var NativeNapiKeyringCredentialStore = class {
|
|
|
1248
1259
|
throw new CredentialStoreIntegrityError();
|
|
1249
1260
|
}
|
|
1250
1261
|
entry() {
|
|
1251
|
-
return this.createEntry(
|
|
1262
|
+
return this.createEntry(this.account);
|
|
1252
1263
|
}
|
|
1253
1264
|
};
|
|
1254
1265
|
var parseVerifiedCredential = (serialized) => {
|
|
@@ -1301,6 +1312,340 @@ var parseCredential = (serialized) => {
|
|
|
1301
1312
|
};
|
|
1302
1313
|
};
|
|
1303
1314
|
|
|
1315
|
+
// apps/product-cli/dist/profile-store.js
|
|
1316
|
+
var ProfileNameConflictError = class extends Error {
|
|
1317
|
+
profile;
|
|
1318
|
+
constructor(profile) {
|
|
1319
|
+
super("The profile name is used by another saved login");
|
|
1320
|
+
this.profile = profile;
|
|
1321
|
+
this.name = "ProfileNameConflictError";
|
|
1322
|
+
}
|
|
1323
|
+
};
|
|
1324
|
+
var ProfileLimitError = class extends Error {
|
|
1325
|
+
saved;
|
|
1326
|
+
constructor(saved) {
|
|
1327
|
+
super("The saved logins of this environment reached their limit");
|
|
1328
|
+
this.saved = saved;
|
|
1329
|
+
this.name = "ProfileLimitError";
|
|
1330
|
+
}
|
|
1331
|
+
};
|
|
1332
|
+
var MAX_PROFILES = 64;
|
|
1333
|
+
var MAX_INDEX_ATTEMPTS = 64;
|
|
1334
|
+
var INDEX_FILE = /^index-([1-9][0-9]{0,14})\.json$/u;
|
|
1335
|
+
var SERVICE_NAME = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u;
|
|
1336
|
+
var PROFILE_NAME = /^[a-z0-9][a-z0-9_-]{0,62}$/u;
|
|
1337
|
+
var USER_ID = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/u;
|
|
1338
|
+
var ORGANIZATION_ID = /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u;
|
|
1339
|
+
var isProfileName = (value) => PROFILE_NAME.test(value);
|
|
1340
|
+
var isProfileUserId = (value) => USER_ID.test(value);
|
|
1341
|
+
var profileAccount = (profile) => `profile:${profile.userId}:${profile.organizationId ?? "none"}`;
|
|
1342
|
+
var sameLogin = (left, right) => profileAccount(left) === profileAccount(right);
|
|
1343
|
+
var profileIndexDirectory = (serviceName) => join(homedir(), ".ohmyhost", "profiles", serviceName);
|
|
1344
|
+
var nextProfileIndex = (current, profile, replaces) => [
|
|
1345
|
+
...current.filter((saved) => !sameLogin(saved, profile) && (replaces === void 0 || !sameLogin(saved, replaces))),
|
|
1346
|
+
profile
|
|
1347
|
+
];
|
|
1348
|
+
var admitProfile = (next, profile) => {
|
|
1349
|
+
const conflict = next.find((saved) => saved.name === profile.name && saved !== profile);
|
|
1350
|
+
if (conflict !== void 0)
|
|
1351
|
+
throw new ProfileNameConflictError(conflict);
|
|
1352
|
+
if (next.length > MAX_PROFILES)
|
|
1353
|
+
throw new ProfileLimitError(next.length - 1);
|
|
1354
|
+
};
|
|
1355
|
+
var NativeKeyringProfileRegistry = class {
|
|
1356
|
+
serviceName;
|
|
1357
|
+
#createEntry;
|
|
1358
|
+
#index;
|
|
1359
|
+
constructor(createEntry = void 0, serviceName = "ohmyhost", indexDirectory) {
|
|
1360
|
+
this.serviceName = serviceName;
|
|
1361
|
+
if (!SERVICE_NAME.test(serviceName))
|
|
1362
|
+
throw new CredentialStoreUnavailableError();
|
|
1363
|
+
this.#createEntry = createEntry ?? createNativeEntryFactory(serviceName);
|
|
1364
|
+
this.#index = new ProfileIndexFiles(indexDirectory ?? profileIndexDirectory(serviceName));
|
|
1365
|
+
}
|
|
1366
|
+
async list() {
|
|
1367
|
+
return (await this.#index.read()).profiles;
|
|
1368
|
+
}
|
|
1369
|
+
credential(profile) {
|
|
1370
|
+
return new NativeNapiKeyringCredentialStore(this.#createEntry, this.serviceName, profileAccount(profile));
|
|
1371
|
+
}
|
|
1372
|
+
legacy() {
|
|
1373
|
+
return new NativeNapiKeyringCredentialStore(this.#createEntry, this.serviceName, LEGACY_CREDENTIAL_ACCOUNT);
|
|
1374
|
+
}
|
|
1375
|
+
async save(profile, credential, replaces) {
|
|
1376
|
+
assertProfile(profile);
|
|
1377
|
+
const before = await this.list();
|
|
1378
|
+
admitProfile(nextProfileIndex(before, profile, replaces), profile);
|
|
1379
|
+
await this.credential(profile).replace(credential);
|
|
1380
|
+
try {
|
|
1381
|
+
await this.#index.update((current) => {
|
|
1382
|
+
const next = nextProfileIndex(current, profile, replaces);
|
|
1383
|
+
admitProfile(next, profile);
|
|
1384
|
+
return next;
|
|
1385
|
+
});
|
|
1386
|
+
} catch (error) {
|
|
1387
|
+
if (!before.some((saved) => sameLogin(saved, profile)))
|
|
1388
|
+
await this.credential(profile).clear();
|
|
1389
|
+
throw error;
|
|
1390
|
+
}
|
|
1391
|
+
if (replaces !== void 0 && !sameLogin(replaces, profile))
|
|
1392
|
+
await this.credential(replaces).clear();
|
|
1393
|
+
}
|
|
1394
|
+
async remove(profile) {
|
|
1395
|
+
await this.credential(profile).clear();
|
|
1396
|
+
await this.#index.update((current) => current.some((saved) => sameLogin(saved, profile)) ? current.filter((saved) => !sameLogin(saved, profile)) : void 0);
|
|
1397
|
+
}
|
|
1398
|
+
};
|
|
1399
|
+
var ProfileIndexFiles = class {
|
|
1400
|
+
directory;
|
|
1401
|
+
constructor(directory) {
|
|
1402
|
+
this.directory = directory;
|
|
1403
|
+
}
|
|
1404
|
+
async read() {
|
|
1405
|
+
for (let attempt = 0; attempt < MAX_INDEX_ATTEMPTS; attempt += 1) {
|
|
1406
|
+
const version2 = await this.#newest();
|
|
1407
|
+
if (version2 === 0)
|
|
1408
|
+
return { version: version2, profiles: [] };
|
|
1409
|
+
let serialized;
|
|
1410
|
+
try {
|
|
1411
|
+
serialized = await readFile(this.#file(version2), "utf8");
|
|
1412
|
+
} catch (error) {
|
|
1413
|
+
if (fileErrorCode(error) === "ENOENT")
|
|
1414
|
+
continue;
|
|
1415
|
+
throw new CredentialStoreUnavailableError();
|
|
1416
|
+
}
|
|
1417
|
+
return { version: version2, profiles: parseProfileIndex(serialized) };
|
|
1418
|
+
}
|
|
1419
|
+
throw new CredentialStoreUnavailableError();
|
|
1420
|
+
}
|
|
1421
|
+
/** Applies `change` to the newest index; `undefined` means nothing to change. */
|
|
1422
|
+
async update(change) {
|
|
1423
|
+
try {
|
|
1424
|
+
await mkdir2(this.directory, { recursive: true, mode: 448 });
|
|
1425
|
+
} catch {
|
|
1426
|
+
throw new CredentialStoreUnavailableError();
|
|
1427
|
+
}
|
|
1428
|
+
for (let attempt = 0; attempt < MAX_INDEX_ATTEMPTS; attempt += 1) {
|
|
1429
|
+
const { version: version2, profiles } = await this.read();
|
|
1430
|
+
const next = change(profiles);
|
|
1431
|
+
if (next === void 0)
|
|
1432
|
+
return;
|
|
1433
|
+
const temporary = join(this.directory, `.index-${randomUUID()}.tmp`);
|
|
1434
|
+
try {
|
|
1435
|
+
await writeDurably(temporary, serializeProfileIndex(next));
|
|
1436
|
+
await link(temporary, this.#file(version2 + 1));
|
|
1437
|
+
} catch (error) {
|
|
1438
|
+
if (fileErrorCode(error) === "EEXIST")
|
|
1439
|
+
continue;
|
|
1440
|
+
throw new CredentialStoreUnavailableError();
|
|
1441
|
+
} finally {
|
|
1442
|
+
await removeTemporary(temporary);
|
|
1443
|
+
}
|
|
1444
|
+
if (await this.#newest() !== version2 + 1)
|
|
1445
|
+
continue;
|
|
1446
|
+
await this.#prune(version2);
|
|
1447
|
+
return;
|
|
1448
|
+
}
|
|
1449
|
+
throw new CredentialStoreUnavailableError();
|
|
1450
|
+
}
|
|
1451
|
+
async #newest() {
|
|
1452
|
+
let names;
|
|
1453
|
+
try {
|
|
1454
|
+
names = await readdir(this.directory);
|
|
1455
|
+
} catch (error) {
|
|
1456
|
+
if (fileErrorCode(error) === "ENOENT")
|
|
1457
|
+
return 0;
|
|
1458
|
+
throw new CredentialStoreUnavailableError();
|
|
1459
|
+
}
|
|
1460
|
+
return names.reduce((newest, name) => Math.max(newest, indexVersion(name)), 0);
|
|
1461
|
+
}
|
|
1462
|
+
/**
|
|
1463
|
+
* Keeps the superseded version for readers that listed it just now; older ones go. Cleanup only:
|
|
1464
|
+
* a file left behind is ignored, since readers take the newest version, and another process may
|
|
1465
|
+
* be removing the same files at this moment.
|
|
1466
|
+
*/
|
|
1467
|
+
async #prune(superseded) {
|
|
1468
|
+
let names;
|
|
1469
|
+
try {
|
|
1470
|
+
names = await readdir(this.directory);
|
|
1471
|
+
} catch {
|
|
1472
|
+
return;
|
|
1473
|
+
}
|
|
1474
|
+
for (const name of names) {
|
|
1475
|
+
const version2 = indexVersion(name);
|
|
1476
|
+
if (version2 === 0 || version2 >= superseded)
|
|
1477
|
+
continue;
|
|
1478
|
+
try {
|
|
1479
|
+
await unlink(join(this.directory, name));
|
|
1480
|
+
} catch {
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
#file(version2) {
|
|
1485
|
+
return join(this.directory, `index-${String(version2)}.json`);
|
|
1486
|
+
}
|
|
1487
|
+
};
|
|
1488
|
+
var indexVersion = (name) => Number(INDEX_FILE.exec(name)?.[1] ?? 0);
|
|
1489
|
+
var removeTemporary = async (path) => {
|
|
1490
|
+
try {
|
|
1491
|
+
await unlink(path);
|
|
1492
|
+
} catch {
|
|
1493
|
+
}
|
|
1494
|
+
};
|
|
1495
|
+
var fileErrorCode = (error) => typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0;
|
|
1496
|
+
var writeDurably = async (path, text) => {
|
|
1497
|
+
const handle = await open2(path, "wx", 384);
|
|
1498
|
+
try {
|
|
1499
|
+
await handle.writeFile(text, "utf8");
|
|
1500
|
+
await handle.sync();
|
|
1501
|
+
} finally {
|
|
1502
|
+
await handle.close();
|
|
1503
|
+
}
|
|
1504
|
+
};
|
|
1505
|
+
var serializeProfileIndex = (profiles) => JSON.stringify({
|
|
1506
|
+
version: 1,
|
|
1507
|
+
profiles: [...profiles].sort((left, right) => left.name < right.name ? -1 : 1).map((profile) => ({
|
|
1508
|
+
name: profile.name,
|
|
1509
|
+
user_id: profile.userId,
|
|
1510
|
+
organization_id: profile.organizationId,
|
|
1511
|
+
organization_name: profile.organizationName
|
|
1512
|
+
}))
|
|
1513
|
+
});
|
|
1514
|
+
var parseProfileIndex = (serialized) => {
|
|
1515
|
+
try {
|
|
1516
|
+
const value = JSON.parse(serialized);
|
|
1517
|
+
if (!isRecord(value, ["version", "profiles"]) || value["version"] !== 1)
|
|
1518
|
+
throw new Error("Invalid profile index");
|
|
1519
|
+
const entries = value["profiles"];
|
|
1520
|
+
if (!Array.isArray(entries) || entries.length > MAX_PROFILES)
|
|
1521
|
+
throw new Error("Invalid profile index");
|
|
1522
|
+
const profiles = entries.map((entry) => {
|
|
1523
|
+
if (!isRecord(entry, ["name", "user_id", "organization_id", "organization_name"]))
|
|
1524
|
+
throw new Error("Invalid profile");
|
|
1525
|
+
const profile = {
|
|
1526
|
+
name: entry["name"],
|
|
1527
|
+
userId: entry["user_id"],
|
|
1528
|
+
organizationId: entry["organization_id"],
|
|
1529
|
+
organizationName: entry["organization_name"]
|
|
1530
|
+
};
|
|
1531
|
+
assertProfile(profile);
|
|
1532
|
+
return profile;
|
|
1533
|
+
});
|
|
1534
|
+
if (new Set(profiles.map((profile) => profile.name)).size !== profiles.length || new Set(profiles.map(profileAccount)).size !== profiles.length)
|
|
1535
|
+
throw new Error("Duplicate profile");
|
|
1536
|
+
return profiles;
|
|
1537
|
+
} catch {
|
|
1538
|
+
throw new CredentialStoreIntegrityError();
|
|
1539
|
+
}
|
|
1540
|
+
};
|
|
1541
|
+
var assertProfile = (profile) => {
|
|
1542
|
+
if (typeof profile.name !== "string" || !PROFILE_NAME.test(profile.name) || typeof profile.userId !== "string" || !USER_ID.test(profile.userId) || !(profile.organizationId === null || typeof profile.organizationId === "string" && ORGANIZATION_ID.test(profile.organizationId)) || !(profile.organizationName === null || typeof profile.organizationName === "string" && profile.organizationName.length > 0 && profile.organizationName.length <= 128 && !new RegExp("\\p{Cc}", "u").test(profile.organizationName)) || profile.organizationId === null && profile.organizationName !== null)
|
|
1543
|
+
throw new CredentialStoreIntegrityError();
|
|
1544
|
+
};
|
|
1545
|
+
var isRecord = (value, keys) => typeof value === "object" && value !== null && !Array.isArray(value) && Object.keys(value).sort().join(",") === [...keys].sort().join(",");
|
|
1546
|
+
var selectProfile = (profiles, request) => {
|
|
1547
|
+
if (request.name !== void 0 && request.bound !== void 0 && request.name !== request.bound)
|
|
1548
|
+
return { outcome: "conflict", field: "binding", profile: null };
|
|
1549
|
+
const named = request.name ?? request.bound;
|
|
1550
|
+
if (named !== void 0) {
|
|
1551
|
+
const profile = profiles.find((saved) => saved.name === named);
|
|
1552
|
+
if (profile === void 0)
|
|
1553
|
+
return { outcome: "not_found" };
|
|
1554
|
+
if (request.organizationId !== void 0 && profile.organizationId !== request.organizationId)
|
|
1555
|
+
return { outcome: "conflict", field: "organization", profile };
|
|
1556
|
+
if (request.userId !== void 0 && profile.userId !== request.userId)
|
|
1557
|
+
return { outcome: "conflict", field: "user", profile };
|
|
1558
|
+
return { outcome: "selected", profile };
|
|
1559
|
+
}
|
|
1560
|
+
const candidates = profiles.filter((profile) => (request.organizationId === void 0 || profile.organizationId === request.organizationId) && (request.userId === void 0 || profile.userId === request.userId));
|
|
1561
|
+
const only = candidates[0];
|
|
1562
|
+
if (candidates.length === 1 && only !== void 0)
|
|
1563
|
+
return { outcome: "selected", profile: only };
|
|
1564
|
+
if (candidates.length > 1)
|
|
1565
|
+
return { outcome: "ambiguous", candidates };
|
|
1566
|
+
return profiles.length === 0 ? { outcome: "none" } : { outcome: "not_found" };
|
|
1567
|
+
};
|
|
1568
|
+
var selectProfileForOrganization = (profiles, request) => {
|
|
1569
|
+
const user = request.userId === void 0 ? {} : { userId: request.userId };
|
|
1570
|
+
if (request.name !== void 0 || request.bound !== void 0)
|
|
1571
|
+
return selectProfile(profiles, {
|
|
1572
|
+
...request.name === void 0 ? {} : { name: request.name },
|
|
1573
|
+
...request.bound === void 0 ? {} : { bound: request.bound },
|
|
1574
|
+
...user
|
|
1575
|
+
});
|
|
1576
|
+
const candidates = profiles.filter((profile) => request.userId === void 0 || profile.userId === request.userId);
|
|
1577
|
+
const inOrganization = candidates.filter((profile) => profile.organizationId === request.organizationId);
|
|
1578
|
+
if (inOrganization.length > 1)
|
|
1579
|
+
return { outcome: "ambiguous", candidates: inOrganization };
|
|
1580
|
+
const unscoped = candidates.filter((profile) => profile.organizationId === null);
|
|
1581
|
+
const [member] = inOrganization;
|
|
1582
|
+
if (member !== void 0)
|
|
1583
|
+
return { outcome: "selected", profile: member };
|
|
1584
|
+
const [open4] = unscoped;
|
|
1585
|
+
if (unscoped.length === 1 && open4 !== void 0)
|
|
1586
|
+
return { outcome: "selected", profile: open4 };
|
|
1587
|
+
return selectProfile(profiles, user);
|
|
1588
|
+
};
|
|
1589
|
+
var defaultProfileName = (profiles, login) => {
|
|
1590
|
+
const same = profiles.find((profile) => profile.userId === login.userId && profile.organizationId === login.organizationId);
|
|
1591
|
+
if (same !== void 0)
|
|
1592
|
+
return same.name;
|
|
1593
|
+
const base = slug(login.organizationName ?? "") || (login.organizationId === null ? "account" : "workspace");
|
|
1594
|
+
const free = (name) => profiles.every((profile) => profile.name !== name);
|
|
1595
|
+
if (free(base))
|
|
1596
|
+
return base;
|
|
1597
|
+
const suffix = (login.organizationId ?? login.userId).replace(/[^A-Za-z0-9]/gu, "").slice(-6).toLowerCase();
|
|
1598
|
+
for (let attempt = 1; attempt <= profiles.length + 1; attempt += 1) {
|
|
1599
|
+
const candidate = `${base.slice(0, 48)}-${suffix}${attempt === 1 ? "" : `-${String(attempt)}`}`;
|
|
1600
|
+
if (free(candidate))
|
|
1601
|
+
return candidate;
|
|
1602
|
+
}
|
|
1603
|
+
throw new CredentialStoreIntegrityError();
|
|
1604
|
+
};
|
|
1605
|
+
var slug = (value) => value.normalize("NFKD").replace(/[\u0300-\u036f]/gu, "").toLowerCase().replace(/[^a-z0-9]+/gu, "-").replace(/^-+/u, "").slice(0, 40).replace(/-+$/u, "");
|
|
1606
|
+
var publicProfile = (profile) => ({
|
|
1607
|
+
name: profile.name,
|
|
1608
|
+
user_id: profile.userId,
|
|
1609
|
+
organization_id: profile.organizationId,
|
|
1610
|
+
organization_name: profile.organizationName
|
|
1611
|
+
});
|
|
1612
|
+
var profileLimitAction = (commandPrefix) => `Nothing was saved: this environment already keeps ${String(MAX_PROFILES)} saved logins, the most one computer holds. Remove one you no longer need with '${commandPrefix} logout --profile-name NAME --json' ('${commandPrefix} profile list --json' shows them), then retry.`;
|
|
1613
|
+
var ProfileSelectionError = class extends Error {
|
|
1614
|
+
code;
|
|
1615
|
+
exitCode;
|
|
1616
|
+
suggestedAction;
|
|
1617
|
+
constructor(code, exitCode, suggestedAction) {
|
|
1618
|
+
super(`${code}: ${suggestedAction}`);
|
|
1619
|
+
this.code = code;
|
|
1620
|
+
this.exitCode = exitCode;
|
|
1621
|
+
this.suggestedAction = suggestedAction;
|
|
1622
|
+
this.name = "ProfileSelectionError";
|
|
1623
|
+
}
|
|
1624
|
+
};
|
|
1625
|
+
var profileSelectionError = (selection, request, commandPrefix, selector) => {
|
|
1626
|
+
const choose = selector === "cli" ? `pass --profile-name NAME (see '${commandPrefix} profile list --json') or set OHMYHOST_PROFILE for this process` : "pass profile_name (see profile_list) or set OHMYHOST_PROFILE in this MCP server's configuration";
|
|
1627
|
+
const login = `${commandPrefix} login${request.organizationId === void 0 ? "" : ` --organization ${request.organizationId}`}${request.userId === void 0 ? "" : ` --user ${request.userId}`}${(request.name ?? request.bound) === void 0 ? "" : ` --profile-name ${String(request.name ?? request.bound)}`} --json`;
|
|
1628
|
+
if (selection.outcome === "none")
|
|
1629
|
+
return new ProfileSelectionError("authentication_required", 5, `No login is saved on this computer. Run '${login}'.`);
|
|
1630
|
+
if (selection.outcome === "not_found")
|
|
1631
|
+
return new ProfileSelectionError("profile_not_found", 5, `No saved login matches ${describeRequest(request)}. Run '${login}' to add it, signing in as that user; '${commandPrefix} profile list --json' shows the saved logins.`);
|
|
1632
|
+
if (selection.outcome === "ambiguous")
|
|
1633
|
+
return new ProfileSelectionError("profile_selection_required", 2, `Several saved logins could run this: ${selection.candidates.map((profile2) => profile2.name).join(", ")}. Ask the customer which account to use, then ${choose}.`);
|
|
1634
|
+
if (selection.field === "binding")
|
|
1635
|
+
return new ProfileSelectionError("profile_context_mismatch", 2, `This call names profile ${String(request.name)}, but the process is bound to OHMYHOST_PROFILE=${String(request.bound)}. Use the bound profile or start a process for the other one.`);
|
|
1636
|
+
const profile = selection.profile;
|
|
1637
|
+
return new ProfileSelectionError("profile_context_mismatch", 2, selection.field === "organization" ? `Profile ${String(profile?.name)} is signed in to organization ${String(profile?.organizationId ?? "none")}, but this targets organization ${String(request.organizationId)}. Use the profile of that organization or change the target; nothing was sent.` : `Profile ${String(profile?.name)} belongs to user ${String(profile?.userId)}, not ${String(request.userId)}. Use that user's profile; nothing was sent.`);
|
|
1638
|
+
};
|
|
1639
|
+
var describeRequest = (request) => {
|
|
1640
|
+
const parts = [
|
|
1641
|
+
...(request.name ?? request.bound) === void 0 ? [] : [`profile ${String(request.name ?? request.bound)}`],
|
|
1642
|
+
...request.organizationId === void 0 ? [] : [`organization ${request.organizationId}`],
|
|
1643
|
+
...request.userId === void 0 ? [] : [`user ${request.userId}`]
|
|
1644
|
+
];
|
|
1645
|
+
return parts.length === 0 ? "this request" : parts.join(", ");
|
|
1646
|
+
};
|
|
1647
|
+
var describeProfile = (profile) => `profile ${profile.name} (user ${profile.userId}, ${profile.organizationId === null ? "no organization" : `organization ${profile.organizationName === null ? "" : `${profile.organizationName} `}${profile.organizationId}`})`;
|
|
1648
|
+
|
|
1304
1649
|
// apps/product-cli/dist/device-token-expiry.js
|
|
1305
1650
|
var DeviceTokenExpiryError = class extends Error {
|
|
1306
1651
|
constructor() {
|
|
@@ -1375,46 +1720,6 @@ var resolveDeviceTokenExpiresAt = (accessToken, expiresInSeconds, now) => {
|
|
|
1375
1720
|
return new Date(jwtExpiryMilliseconds).toISOString();
|
|
1376
1721
|
};
|
|
1377
1722
|
|
|
1378
|
-
// apps/product-cli/dist/workspace.js
|
|
1379
|
-
var InteractiveSessionRequiredError = class extends Error {
|
|
1380
|
-
constructor() {
|
|
1381
|
-
super("Workspace selection requires an interactive login");
|
|
1382
|
-
this.name = "InteractiveSessionRequiredError";
|
|
1383
|
-
}
|
|
1384
|
-
};
|
|
1385
|
-
var chooseWorkspace = (organizations, requested) => {
|
|
1386
|
-
if (requested !== void 0) {
|
|
1387
|
-
const match = organizations.find((organization) => organization.id === requested);
|
|
1388
|
-
return match === void 0 ? { outcome: "not_a_member", organizations } : { outcome: "selected", organization: match };
|
|
1389
|
-
}
|
|
1390
|
-
if (organizations.length === 0)
|
|
1391
|
-
return { outcome: "no_workspace" };
|
|
1392
|
-
const only = organizations[0];
|
|
1393
|
-
if (organizations.length === 1 && only !== void 0)
|
|
1394
|
-
return { outcome: "selected", organization: only };
|
|
1395
|
-
return { outcome: "choice_required", organizations };
|
|
1396
|
-
};
|
|
1397
|
-
var selectWorkspace = async (session, organization, signal) => {
|
|
1398
|
-
const stored = await session.store.read();
|
|
1399
|
-
if (stored === void 0)
|
|
1400
|
-
throw new InteractiveSessionRequiredError();
|
|
1401
|
-
const refreshed = await session.refresher.refresh(stored.refreshToken, signal, organization.workos_id);
|
|
1402
|
-
await session.store.replace({
|
|
1403
|
-
...refreshed,
|
|
1404
|
-
workosOrganizationId: organization.workos_id,
|
|
1405
|
-
organizationId: organization.id
|
|
1406
|
-
});
|
|
1407
|
-
};
|
|
1408
|
-
var selectedWorkspaceId = async (session) => (await session.store.read())?.organizationId ?? null;
|
|
1409
|
-
var workspaceOf = (credential) => ({
|
|
1410
|
-
...credential.workosOrganizationId === void 0 ? {} : { workosOrganizationId: credential.workosOrganizationId },
|
|
1411
|
-
...credential.organizationId === void 0 ? {} : { organizationId: credential.organizationId }
|
|
1412
|
-
});
|
|
1413
|
-
var publicWorkspace = (organization) => ({
|
|
1414
|
-
id: organization.id,
|
|
1415
|
-
name: organization.name
|
|
1416
|
-
});
|
|
1417
|
-
|
|
1418
1723
|
// packages/contracts/dist/feedback.js
|
|
1419
1724
|
var FEEDBACK_HISTORY_PAGE_SIZE = 25;
|
|
1420
1725
|
var FEEDBACK_REPLY_MAX_LENGTH = 2e3;
|
|
@@ -1648,7 +1953,7 @@ var PROBLEM_POLICY = {
|
|
|
1648
1953
|
github_connection_required: {
|
|
1649
1954
|
status: 409,
|
|
1650
1955
|
retryable: false,
|
|
1651
|
-
action: "Run 'ohmyhost github connect --organization ULID --idempotency-key KEY --json' for
|
|
1956
|
+
action: "This workspace has no GitHub connection yet. Run 'ohmyhost github connect --organization ULID --idempotency-key KEY --json' for it, complete its browser link, then repeat the original source link. If the project belongs to another account, use that account's login instead; error.acting_as names the login this ran as."
|
|
1652
1957
|
},
|
|
1653
1958
|
github_connection_revoked: {
|
|
1654
1959
|
status: 409,
|
|
@@ -1722,7 +2027,11 @@ var PROBLEM_POLICY = {
|
|
|
1722
2027
|
retryable: false,
|
|
1723
2028
|
action: "Run 'ohmyhost organization list --json' and select one with 'ohmyhost organization use --organization ULID --json', or create the first workspace."
|
|
1724
2029
|
},
|
|
1725
|
-
resource_not_found: {
|
|
2030
|
+
resource_not_found: {
|
|
2031
|
+
status: 404,
|
|
2032
|
+
retryable: false,
|
|
2033
|
+
action: "Check the resource identifier and the account: a project is visible only to its own organization, and error.acting_as names the login this ran as. Use the login of the account that owns it."
|
|
2034
|
+
},
|
|
1726
2035
|
idempotency_key_reused: {
|
|
1727
2036
|
status: 409,
|
|
1728
2037
|
retryable: false,
|
|
@@ -2034,7 +2343,7 @@ var parseAccountProfile = (value) => {
|
|
|
2034
2343
|
});
|
|
2035
2344
|
if (new Set(workspaces.map((workspace) => workspace.id)).size !== organizationIds.length)
|
|
2036
2345
|
throw new ResponseContractError();
|
|
2037
|
-
return workspaces;
|
|
2346
|
+
return { userId: input["user_id"], organizations: workspaces };
|
|
2038
2347
|
};
|
|
2039
2348
|
var parseSafeProblem = (value) => {
|
|
2040
2349
|
const input = exactRecord2(value, [
|
|
@@ -2089,7 +2398,7 @@ var parseOperation = (value) => {
|
|
|
2089
2398
|
const blockingOperationId = input["blocking_operation_id"];
|
|
2090
2399
|
if (blockingOperationId !== void 0 && (state !== "queued" || !isUlid(blockingOperationId) || blockingOperationId === id3))
|
|
2091
2400
|
throw new ResponseContractError();
|
|
2092
|
-
if (!isUlid(id3) || !isOperationState(state) || !isIsoInstant(createdAt) || !isIsoInstant(updatedAt) || result !== void 0 && !
|
|
2401
|
+
if (!isUlid(id3) || !isOperationState(state) || !isIsoInstant(createdAt) || !isIsoInstant(updatedAt) || result !== void 0 && !isRecord2(result)) {
|
|
2093
2402
|
throw new ResponseContractError();
|
|
2094
2403
|
}
|
|
2095
2404
|
let progress;
|
|
@@ -2150,12 +2459,12 @@ function parseOperationFailure(value) {
|
|
|
2150
2459
|
return safe;
|
|
2151
2460
|
}
|
|
2152
2461
|
var exactRecord2 = (value, allowed) => {
|
|
2153
|
-
if (!
|
|
2462
|
+
if (!isRecord2(value) || Object.keys(value).some((key) => !allowed.includes(key))) {
|
|
2154
2463
|
throw new ResponseContractError();
|
|
2155
2464
|
}
|
|
2156
2465
|
return value;
|
|
2157
2466
|
};
|
|
2158
|
-
var
|
|
2467
|
+
var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2159
2468
|
var boundedString = (value, minimum, maximum) => typeof value === "string" && value.length >= minimum && value.length <= maximum;
|
|
2160
2469
|
var isUlid = (value) => typeof value === "string" && /^[0-9A-HJKMNP-TV-Z]{26}$/u.test(value);
|
|
2161
2470
|
var isIsoInstant = (value) => typeof value === "string" && value.length <= 64 && Number.isFinite(Date.parse(value));
|
|
@@ -2178,6 +2487,79 @@ var isPaidValidationRecord = (value) => {
|
|
|
2178
2487
|
return (record5["type"] === "CNAME" || record5["type"] === "TXT") && boundedString(record5["name"], 1, 253) && boundedString(record5["content"], 1, 2048) && ["traffic", "ownership", "ssl", "dcv_delegation"].includes(String(record5["purpose"]));
|
|
2179
2488
|
};
|
|
2180
2489
|
|
|
2490
|
+
// apps/product-cli/dist/workspace.js
|
|
2491
|
+
var InteractiveSessionRequiredError = class extends Error {
|
|
2492
|
+
constructor() {
|
|
2493
|
+
super("Workspace selection requires an interactive login");
|
|
2494
|
+
this.name = "InteractiveSessionRequiredError";
|
|
2495
|
+
}
|
|
2496
|
+
};
|
|
2497
|
+
var ProfileOrganizationFixedError = class extends Error {
|
|
2498
|
+
profile;
|
|
2499
|
+
organization;
|
|
2500
|
+
constructor(profile, organization) {
|
|
2501
|
+
super("The saved login is bound to another organization");
|
|
2502
|
+
this.profile = profile;
|
|
2503
|
+
this.organization = organization;
|
|
2504
|
+
this.name = "ProfileOrganizationFixedError";
|
|
2505
|
+
}
|
|
2506
|
+
};
|
|
2507
|
+
var AccountVerificationError = class extends Error {
|
|
2508
|
+
constructor() {
|
|
2509
|
+
super("The signed-in account does not match the requested one");
|
|
2510
|
+
this.name = "AccountVerificationError";
|
|
2511
|
+
}
|
|
2512
|
+
};
|
|
2513
|
+
var chooseWorkspace = (organizations, requested) => {
|
|
2514
|
+
if (requested !== void 0) {
|
|
2515
|
+
const match = organizations.find((organization) => organization.id === requested);
|
|
2516
|
+
return match === void 0 ? { outcome: "not_a_member", organizations } : { outcome: "selected", organization: match };
|
|
2517
|
+
}
|
|
2518
|
+
if (organizations.length === 0)
|
|
2519
|
+
return { outcome: "no_workspace" };
|
|
2520
|
+
const only = organizations[0];
|
|
2521
|
+
if (organizations.length === 1 && only !== void 0)
|
|
2522
|
+
return { outcome: "selected", organization: only };
|
|
2523
|
+
return { outcome: "choice_required", organizations };
|
|
2524
|
+
};
|
|
2525
|
+
var verifiedUserId = (identity) => {
|
|
2526
|
+
const actor = parseCurrentIdentity(identity).actor_id;
|
|
2527
|
+
if (!actor.startsWith("user:") || actor.length === 5)
|
|
2528
|
+
throw new AccountVerificationError();
|
|
2529
|
+
return actor.slice(5);
|
|
2530
|
+
};
|
|
2531
|
+
var assertVerifiedLogin = (identity, userId, organizationId) => {
|
|
2532
|
+
const organizations = parseCurrentIdentity(identity).organization_ids;
|
|
2533
|
+
if (verifiedUserId(identity) !== userId || (organizationId === null ? organizations.length !== 0 : organizations.length !== 1 || organizations[0] !== organizationId))
|
|
2534
|
+
throw new AccountVerificationError();
|
|
2535
|
+
};
|
|
2536
|
+
var selectWorkspace = async (session, organization, signal, identity) => {
|
|
2537
|
+
if (session.profile.organizationId === organization.id)
|
|
2538
|
+
return session.profile;
|
|
2539
|
+
if (session.profile.organizationId !== null)
|
|
2540
|
+
throw new ProfileOrganizationFixedError(session.profile, organization);
|
|
2541
|
+
const stored = await session.store.read();
|
|
2542
|
+
if (stored === void 0)
|
|
2543
|
+
throw new InteractiveSessionRequiredError();
|
|
2544
|
+
const refreshed = await session.refresher.refresh(stored.refreshToken, signal, organization.workos_id);
|
|
2545
|
+
assertVerifiedLogin(await identity(refreshed.accessToken), session.profile.userId, organization.id);
|
|
2546
|
+
const bound = {
|
|
2547
|
+
...session.profile,
|
|
2548
|
+
organizationId: organization.id,
|
|
2549
|
+
organizationName: organization.name
|
|
2550
|
+
};
|
|
2551
|
+
await session.profiles.save(bound, { ...refreshed, workosOrganizationId: organization.workos_id, organizationId: organization.id }, session.profile);
|
|
2552
|
+
return bound;
|
|
2553
|
+
};
|
|
2554
|
+
var workspaceOf = (credential) => ({
|
|
2555
|
+
...credential.workosOrganizationId === void 0 ? {} : { workosOrganizationId: credential.workosOrganizationId },
|
|
2556
|
+
...credential.organizationId === void 0 ? {} : { organizationId: credential.organizationId }
|
|
2557
|
+
});
|
|
2558
|
+
var publicWorkspace = (organization) => ({
|
|
2559
|
+
id: organization.id,
|
|
2560
|
+
name: organization.name
|
|
2561
|
+
});
|
|
2562
|
+
|
|
2181
2563
|
// apps/product-cli/dist/cli.js
|
|
2182
2564
|
var NetworkTransportError = class extends Error {
|
|
2183
2565
|
constructor() {
|
|
@@ -2206,9 +2588,10 @@ var PublicResponseTooLargeError = class extends Error {
|
|
|
2206
2588
|
var CLI_VERSION = package_default.version;
|
|
2207
2589
|
var HELP_USAGE = Object.freeze({
|
|
2208
2590
|
init: "ohmyhost init [--directory PATH] [--root PATH] [--project SLUG] [--region us|eu] [--dry-run] --json (pass the project's hosting region so storage.jurisdiction matches it; us when omitted)",
|
|
2209
|
-
login: "ohmyhost login [--organization ULID] --json",
|
|
2210
|
-
logout: "ohmyhost logout [--revoke] --json",
|
|
2211
|
-
whoami: "ohmyhost whoami --json",
|
|
2591
|
+
login: "ohmyhost login [--organization ULID] [--user USER_ID] [--profile-name NAME] --json (adds one saved login; nothing is saved unless the browser signed in as that user and organization)",
|
|
2592
|
+
logout: "ohmyhost logout [--profile-name NAME] [--revoke] --json (removes only the selected saved login)",
|
|
2593
|
+
whoami: "ohmyhost whoami [--profile-name NAME] --json (the effective user, organization and saved login)",
|
|
2594
|
+
"profile list": "ohmyhost profile list --json (saved logins on this computer: name, user and organization, never a token; pass --profile-name NAME or set OHMYHOST_PROFILE to choose one)",
|
|
2212
2595
|
"github connect": "ohmyhost github connect --organization ULID --idempotency-key KEY --json (connect once, then link covered repositories without another browser consent)",
|
|
2213
2596
|
"github status": "ohmyhost github status --organization ULID --json",
|
|
2214
2597
|
"export create": "ohmyhost export create --project ULID --idempotency-key KEY --stdin --json (password on stdin only; one accepted SQL ZIP per project per 24 hours)",
|
|
@@ -2223,9 +2606,9 @@ var HELP_USAGE = Object.freeze({
|
|
|
2223
2606
|
"credits usage": "ohmyhost credits usage --organization ULID --month YYYY-MM [--cursor ULID] --json",
|
|
2224
2607
|
"budget get": "ohmyhost budget get --project ULID --json",
|
|
2225
2608
|
"budget set": "ohmyhost budget set --project ULID --credits NUMBER|none [--mode continue|stop] --idempotency-key KEY --json",
|
|
2226
|
-
"organization create": "ohmyhost organization create --name NAME --idempotency-key KEY [--source SOURCE] --json (SOURCE is optional attribution from a link's r value; the new workspace
|
|
2227
|
-
"organization list": "ohmyhost organization list --json (the workspaces
|
|
2228
|
-
"organization use": "ohmyhost organization use --organization ULID --json",
|
|
2609
|
+
"organization create": "ohmyhost organization create --name NAME --idempotency-key KEY [--source SOURCE] --json (SOURCE is optional attribution from a link's r value; a login without organization is bound to the new workspace, another login keeps its own)",
|
|
2610
|
+
"organization list": "ohmyhost organization list [--profile-name NAME] --json (the workspaces of the chosen login's user and the one that login is scoped to)",
|
|
2611
|
+
"organization use": "ohmyhost organization use --organization ULID [--profile-name NAME] --json (binds a login that has no organization yet; another organization needs its own login)",
|
|
2229
2612
|
"operation get": "ohmyhost operation get OPERATION_ULID --json",
|
|
2230
2613
|
"operation reconcile": "ohmyhost operation reconcile OPERATION_ULID --idempotency-key KEY --yes --json",
|
|
2231
2614
|
"token create": "ohmyhost token create --organization ULID --name NAME --idempotency-key KEY --out .env.local --json",
|
|
@@ -2275,7 +2658,7 @@ var HELP_USAGE = Object.freeze({
|
|
|
2275
2658
|
delete: "ohmyhost delete --project ULID --if-match ETAG --confirmation-token TOKEN --idempotency-key KEY --yes --json",
|
|
2276
2659
|
"secret list": "ohmyhost secret list --project ULID --environment ENVIRONMENT_ULID --json",
|
|
2277
2660
|
"function runs": "ohmyhost function runs --project ULID --environment ENVIRONMENT_ULID [--limit 1-100] --json",
|
|
2278
|
-
"secret set": `printf '%s' "$SECRET_VALUE" | ohmyhost secret set NAME --project ULID --environment ENVIRONMENT_ULID --idempotency-key KEY --stdin [--wait] --json`,
|
|
2661
|
+
"secret set": `printf '%s' "$SECRET_VALUE" | ohmyhost secret set NAME --project ULID --environment ENVIRONMENT_ULID --idempotency-key KEY [--profile-user USER_ID --profile-organization ULID | --token-user USER_ID --token-organization ULID] --stdin [--wait] --json (with --profile-user and --profile-organization the saved login that runs it must belong to that user and organization; with --token-user and --token-organization it runs only with an OHMYHOST_TOKEN of that user and organization, never with a saved login)`,
|
|
2279
2662
|
"secret delete": "ohmyhost secret delete NAME --project ULID --environment ENVIRONMENT_ULID --idempotency-key KEY [--wait] --json",
|
|
2280
2663
|
"mail setup": "ohmyhost mail setup --project ULID --environment ULID --domain DOMAIN --sending true --receiving false --idempotency-key KEY --json",
|
|
2281
2664
|
"mail status": "ohmyhost mail status --project ULID --environment ULID --json",
|
|
@@ -2291,6 +2674,14 @@ var HELP_USAGE = Object.freeze({
|
|
|
2291
2674
|
});
|
|
2292
2675
|
var HELP_COMMANDS = Object.freeze(Object.entries(HELP_USAGE).map(([command, usage]) => Object.freeze({ command, usage })));
|
|
2293
2676
|
var SIGN_IN_WINDOW_MS = 30 * 60 * 1e3;
|
|
2677
|
+
var ACCOUNT_SENSITIVE_PROBLEMS = /* @__PURE__ */ new Set([
|
|
2678
|
+
"resource_not_found",
|
|
2679
|
+
"forbidden",
|
|
2680
|
+
"organization_required",
|
|
2681
|
+
"github_connection_required",
|
|
2682
|
+
"github_connection_revoked",
|
|
2683
|
+
"repository_not_installed"
|
|
2684
|
+
]);
|
|
2294
2685
|
|
|
2295
2686
|
// packages/sdk-ts/dist/generated/core/bodySerializer.gen.js
|
|
2296
2687
|
var jsonBodySerializer = {
|
|
@@ -3855,6 +4246,47 @@ var getProjectSource = (parameters, options) => {
|
|
|
3855
4246
|
...params
|
|
3856
4247
|
});
|
|
3857
4248
|
};
|
|
4249
|
+
var getProjectSourceAutoDeploy = (parameters, options) => {
|
|
4250
|
+
const params = buildClientParams([parameters], [
|
|
4251
|
+
{
|
|
4252
|
+
args: [
|
|
4253
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
4254
|
+
{ in: "path", key: "project_id" }
|
|
4255
|
+
]
|
|
4256
|
+
}
|
|
4257
|
+
]);
|
|
4258
|
+
return (options?.client ?? client).get({
|
|
4259
|
+
responseStyle: "data",
|
|
4260
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
4261
|
+
url: "/v1/projects/{project_id}/source/auto-deploy",
|
|
4262
|
+
...options,
|
|
4263
|
+
...params
|
|
4264
|
+
});
|
|
4265
|
+
};
|
|
4266
|
+
var configureProjectSourceAutoDeploy = (parameters, options) => {
|
|
4267
|
+
const params = buildClientParams([parameters], [
|
|
4268
|
+
{
|
|
4269
|
+
args: [
|
|
4270
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
4271
|
+
{ in: "headers", key: "Idempotency-Key" },
|
|
4272
|
+
{ in: "path", key: "project_id" },
|
|
4273
|
+
{ key: "configureSourceAutoDeployRequest", map: "body" }
|
|
4274
|
+
]
|
|
4275
|
+
}
|
|
4276
|
+
]);
|
|
4277
|
+
return (options?.client ?? client).put({
|
|
4278
|
+
responseStyle: "data",
|
|
4279
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
4280
|
+
url: "/v1/projects/{project_id}/source/auto-deploy",
|
|
4281
|
+
...options,
|
|
4282
|
+
...params,
|
|
4283
|
+
headers: {
|
|
4284
|
+
"Content-Type": "application/json",
|
|
4285
|
+
...options?.headers,
|
|
4286
|
+
...params.headers
|
|
4287
|
+
}
|
|
4288
|
+
});
|
|
4289
|
+
};
|
|
3858
4290
|
var createCloudflareDnsAuthorization = (parameters, options) => {
|
|
3859
4291
|
const params = buildClientParams([parameters], [
|
|
3860
4292
|
{
|
|
@@ -3921,6 +4353,24 @@ var changeProjectHandle = (parameters, options) => {
|
|
|
3921
4353
|
}
|
|
3922
4354
|
});
|
|
3923
4355
|
};
|
|
4356
|
+
var configureProjectDomains = (parameters, options) => {
|
|
4357
|
+
const params = buildClientParams([parameters], [
|
|
4358
|
+
{
|
|
4359
|
+
args: [
|
|
4360
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
4361
|
+
{ in: "headers", key: "Idempotency-Key" },
|
|
4362
|
+
{ in: "path", key: "project_id" }
|
|
4363
|
+
]
|
|
4364
|
+
}
|
|
4365
|
+
]);
|
|
4366
|
+
return (options?.client ?? client).put({
|
|
4367
|
+
responseStyle: "data",
|
|
4368
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
4369
|
+
url: "/v1/projects/{project_id}/domains",
|
|
4370
|
+
...options,
|
|
4371
|
+
...params
|
|
4372
|
+
});
|
|
4373
|
+
};
|
|
3924
4374
|
var planPaidProjectDomain = (parameters, options) => {
|
|
3925
4375
|
const params = buildClientParams([parameters], [
|
|
3926
4376
|
{
|
|
@@ -4113,6 +4563,24 @@ var getDeploymentLogs = (parameters, options) => {
|
|
|
4113
4563
|
...params
|
|
4114
4564
|
});
|
|
4115
4565
|
};
|
|
4566
|
+
var streamDeploymentLogs = (parameters, options) => {
|
|
4567
|
+
const params = buildClientParams([parameters], [
|
|
4568
|
+
{
|
|
4569
|
+
args: [
|
|
4570
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
4571
|
+
{ in: "path", key: "project_id" },
|
|
4572
|
+
{ in: "path", key: "deployment_id" }
|
|
4573
|
+
]
|
|
4574
|
+
}
|
|
4575
|
+
]);
|
|
4576
|
+
return (options?.client ?? client).sse.get({
|
|
4577
|
+
responseStyle: "data",
|
|
4578
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
4579
|
+
url: "/v1/projects/{project_id}/deployments/{deployment_id}/logs/events",
|
|
4580
|
+
...options,
|
|
4581
|
+
...params
|
|
4582
|
+
});
|
|
4583
|
+
};
|
|
4116
4584
|
var getDatabaseCompute = (parameters, options) => {
|
|
4117
4585
|
const params = buildClientParams([parameters], [
|
|
4118
4586
|
{
|
|
@@ -4398,6 +4866,32 @@ var deleteEnvironmentSecret = (parameters, options) => {
|
|
|
4398
4866
|
...params
|
|
4399
4867
|
});
|
|
4400
4868
|
};
|
|
4869
|
+
var putEnvironmentSecret = (parameters, options) => {
|
|
4870
|
+
const params = buildClientParams([parameters], [
|
|
4871
|
+
{
|
|
4872
|
+
args: [
|
|
4873
|
+
{ in: "headers", key: "X-Request-Id" },
|
|
4874
|
+
{ in: "headers", key: "Idempotency-Key" },
|
|
4875
|
+
{ in: "path", key: "project_id" },
|
|
4876
|
+
{ in: "path", key: "environment_id" },
|
|
4877
|
+
{ in: "path", key: "secret_name" },
|
|
4878
|
+
{ key: "putEnvironmentSecretRequest", map: "body" }
|
|
4879
|
+
]
|
|
4880
|
+
}
|
|
4881
|
+
]);
|
|
4882
|
+
return (options?.client ?? client).put({
|
|
4883
|
+
responseStyle: "data",
|
|
4884
|
+
security: [{ scheme: "bearer", type: "http" }],
|
|
4885
|
+
url: "/v1/projects/{project_id}/environments/{environment_id}/secrets/{secret_name}",
|
|
4886
|
+
...options,
|
|
4887
|
+
...params,
|
|
4888
|
+
headers: {
|
|
4889
|
+
"Content-Type": "application/json",
|
|
4890
|
+
...options?.headers,
|
|
4891
|
+
...params.headers
|
|
4892
|
+
}
|
|
4893
|
+
});
|
|
4894
|
+
};
|
|
4401
4895
|
var getOperation = (parameters, options) => {
|
|
4402
4896
|
const params = buildClientParams([parameters], [
|
|
4403
4897
|
{
|
|
@@ -4847,9 +5341,6 @@ async function executeManagedMail(client2, input) {
|
|
|
4847
5341
|
return result;
|
|
4848
5342
|
}
|
|
4849
5343
|
|
|
4850
|
-
// packages/workos-auth-contracts/dist/user-api-keys.js
|
|
4851
|
-
var WORKOS_USER_API_KEY_PATTERN = /^sk_[A-Za-z0-9_-]{20,128}$/u;
|
|
4852
|
-
|
|
4853
5344
|
// packages/workos-auth-contracts/dist/device-flow.js
|
|
4854
5345
|
var WORKOS_AUTHKIT_DEVICE_TOKEN_ENDPOINT = "https://api.workos.com/user_management/authenticate";
|
|
4855
5346
|
var allowedDeviceTokenFields = /* @__PURE__ */ new Set([
|
|
@@ -4881,8 +5372,404 @@ var parseDeviceTokens = (value) => {
|
|
|
4881
5372
|
};
|
|
4882
5373
|
};
|
|
4883
5374
|
|
|
4884
|
-
// apps/product-cli/dist/
|
|
4885
|
-
var
|
|
5375
|
+
// apps/product-cli/dist/product-api.js
|
|
5376
|
+
var GeneratedSdkProductApi = class {
|
|
5377
|
+
#client;
|
|
5378
|
+
constructor(baseUrl, accessToken, fetch2) {
|
|
5379
|
+
this.#client = createClient({ auth: accessToken, baseUrl, fetch: fetch2, throwOnError: true });
|
|
5380
|
+
}
|
|
5381
|
+
async changeDatabaseCompute(input) {
|
|
5382
|
+
return changeDatabaseCompute({
|
|
5383
|
+
project_id: input.projectId,
|
|
5384
|
+
environment: input.environment,
|
|
5385
|
+
profile: input.profile,
|
|
5386
|
+
confirm: true,
|
|
5387
|
+
"Idempotency-Key": input.idempotencyKey
|
|
5388
|
+
}, { client: this.#client });
|
|
5389
|
+
}
|
|
5390
|
+
async getDatabaseCompute(input) {
|
|
5391
|
+
const value = await getDatabaseCompute({ project_id: input.projectId, environment: input.environment }, { client: this.#client });
|
|
5392
|
+
assertDatabaseCompute(value);
|
|
5393
|
+
if (value.project_id !== input.projectId || value.environment !== input.environment)
|
|
5394
|
+
throw new TypeError("Compute response scope mismatch");
|
|
5395
|
+
return value;
|
|
5396
|
+
}
|
|
5397
|
+
async getProjectContext(projectId) {
|
|
5398
|
+
const result = await getProjectContext({ project_id: projectId }, { client: this.#client });
|
|
5399
|
+
assertProjectContext(result);
|
|
5400
|
+
if (result.project_id !== projectId)
|
|
5401
|
+
throw new TypeError("Project context scope mismatch");
|
|
5402
|
+
return result;
|
|
5403
|
+
}
|
|
5404
|
+
async setProjectNotes(input) {
|
|
5405
|
+
const result = await setProjectNotes({
|
|
5406
|
+
project_id: input.projectId,
|
|
5407
|
+
markdown: input.markdown,
|
|
5408
|
+
expected_version: input.expectedVersion,
|
|
5409
|
+
"Idempotency-Key": input.idempotencyKey
|
|
5410
|
+
}, { client: this.#client });
|
|
5411
|
+
assertProjectNotesReceipt(result);
|
|
5412
|
+
return result;
|
|
5413
|
+
}
|
|
5414
|
+
createProjectExport(input) {
|
|
5415
|
+
return createProjectExport({
|
|
5416
|
+
project_id: input.projectId,
|
|
5417
|
+
password: input.password,
|
|
5418
|
+
"Idempotency-Key": input.idempotencyKey
|
|
5419
|
+
}, { client: this.#client });
|
|
5420
|
+
}
|
|
5421
|
+
async getProjectExport(input) {
|
|
5422
|
+
const result = await getProjectExport({ project_id: input.projectId, export_id: input.exportId }, { client: this.#client });
|
|
5423
|
+
assertProjectExport(result);
|
|
5424
|
+
return result;
|
|
5425
|
+
}
|
|
5426
|
+
async getCurrentIdentity() {
|
|
5427
|
+
return getCurrentIdentity({}, { client: this.#client });
|
|
5428
|
+
}
|
|
5429
|
+
async getAccountProfile() {
|
|
5430
|
+
return parseAccountProfile(await getAccountProfile({ client: this.#client }));
|
|
5431
|
+
}
|
|
5432
|
+
getOrganizationAccount(organizationId) {
|
|
5433
|
+
return getOrganizationAccount({ organization_id: organizationId }, { client: this.#client });
|
|
5434
|
+
}
|
|
5435
|
+
getOrganizationCredits(organizationId) {
|
|
5436
|
+
return getOrganizationCredits({ organization_id: organizationId }, { client: this.#client });
|
|
5437
|
+
}
|
|
5438
|
+
async createUserApiKey(input) {
|
|
5439
|
+
return parseUserApiKeyCreation(await createUserApiKey({
|
|
5440
|
+
organization_id: input.organizationId,
|
|
5441
|
+
name: input.name,
|
|
5442
|
+
"Idempotency-Key": input.idempotencyKey
|
|
5443
|
+
}, { client: this.#client }));
|
|
5444
|
+
}
|
|
5445
|
+
async listUserApiKeys(input) {
|
|
5446
|
+
return parseUserApiKeyPage(await listUserApiKeys({ organization_id: input.organizationId, ...input.after ? { after: input.after } : {} }, { client: this.#client }));
|
|
5447
|
+
}
|
|
5448
|
+
async revokeUserApiKey(input) {
|
|
5449
|
+
await revokeUserApiKey({ organization_id: input.organizationId, key_id: input.keyId }, { client: this.#client });
|
|
5450
|
+
}
|
|
5451
|
+
createBillingCheckout(input) {
|
|
5452
|
+
return createBillingCheckout({
|
|
5453
|
+
organization_id: input.organizationId,
|
|
5454
|
+
offer: input.offer,
|
|
5455
|
+
packs: input.packs,
|
|
5456
|
+
"Idempotency-Key": input.idempotencyKey
|
|
5457
|
+
}, { client: this.#client });
|
|
5458
|
+
}
|
|
5459
|
+
getBillingCheckout(input) {
|
|
5460
|
+
return getBillingCheckout({ organization_id: input.organizationId, checkout_id: input.checkoutId }, { client: this.#client });
|
|
5461
|
+
}
|
|
5462
|
+
getBillingRecharge(organizationId) {
|
|
5463
|
+
return getBillingRecharge({ organization_id: organizationId }, { client: this.#client });
|
|
5464
|
+
}
|
|
5465
|
+
configureBillingRecharge(input) {
|
|
5466
|
+
return configureBillingRecharge({
|
|
5467
|
+
organization_id: input.organizationId,
|
|
5468
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5469
|
+
enabled: input.enabled,
|
|
5470
|
+
monthly_limit_minor: input.monthlyLimitMinor,
|
|
5471
|
+
consent: input.consent,
|
|
5472
|
+
revision: input.revision
|
|
5473
|
+
}, { client: this.#client });
|
|
5474
|
+
}
|
|
5475
|
+
createBillingPortal(organizationId) {
|
|
5476
|
+
return createBillingPortal({ organization_id: organizationId, body: {} }, { client: this.#client });
|
|
5477
|
+
}
|
|
5478
|
+
getOrganizationCreditUsage(input) {
|
|
5479
|
+
return getOrganizationCreditUsage({
|
|
5480
|
+
organization_id: input.organizationId,
|
|
5481
|
+
month: input.month,
|
|
5482
|
+
...input.cursor ? { cursor: input.cursor } : {}
|
|
5483
|
+
}, { client: this.#client });
|
|
5484
|
+
}
|
|
5485
|
+
getProjectCreditBudget(projectId) {
|
|
5486
|
+
return getProjectCreditBudget({ project_id: projectId }, { client: this.#client });
|
|
5487
|
+
}
|
|
5488
|
+
setProjectCreditBudget(input) {
|
|
5489
|
+
return setProjectCreditBudget({
|
|
5490
|
+
project_id: input.projectId,
|
|
5491
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5492
|
+
setProjectCreditBudgetRequest: { amount_micros: input.amountMicros, mode: input.mode }
|
|
5493
|
+
}, { client: this.#client });
|
|
5494
|
+
}
|
|
5495
|
+
createOrganization(input) {
|
|
5496
|
+
return createOrganization({
|
|
5497
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5498
|
+
createOrganizationRequest: {
|
|
5499
|
+
name: input.name,
|
|
5500
|
+
...input.signupSource === void 0 ? {} : { signup_source: input.signupSource }
|
|
5501
|
+
}
|
|
5502
|
+
}, { client: this.#client });
|
|
5503
|
+
}
|
|
5504
|
+
async listProjects(input) {
|
|
5505
|
+
return listProjects(input, { client: this.#client });
|
|
5506
|
+
}
|
|
5507
|
+
async changeProjectHandle(input) {
|
|
5508
|
+
return changeProjectHandle({
|
|
5509
|
+
project_id: input.projectId,
|
|
5510
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5511
|
+
"If-Match": input.ifMatch,
|
|
5512
|
+
handle: input.handle
|
|
5513
|
+
}, { client: this.#client });
|
|
5514
|
+
}
|
|
5515
|
+
async checkProjectHandle(input) {
|
|
5516
|
+
return getProjectHandleAvailability({ handle: input.handle }, { client: this.#client });
|
|
5517
|
+
}
|
|
5518
|
+
async getProjectStatus(projectId) {
|
|
5519
|
+
return getProjectStatus({ project_id: projectId }, { client: this.#client });
|
|
5520
|
+
}
|
|
5521
|
+
async writeProjectDatabase(input) {
|
|
5522
|
+
return writeProjectDatabase({
|
|
5523
|
+
project_id: input.projectId,
|
|
5524
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5525
|
+
projectDatabaseWriteRequest: {
|
|
5526
|
+
environment: input.environment,
|
|
5527
|
+
statement: input.statement,
|
|
5528
|
+
parameters: [...input.parameters]
|
|
5529
|
+
}
|
|
5530
|
+
}, { client: this.#client });
|
|
5531
|
+
}
|
|
5532
|
+
async queryProjectDatabase(input) {
|
|
5533
|
+
return queryProjectDatabase({
|
|
5534
|
+
project_id: input.projectId,
|
|
5535
|
+
projectDatabaseQueryRequest: {
|
|
5536
|
+
environment: input.environment,
|
|
5537
|
+
statement: input.statement,
|
|
5538
|
+
parameters: [...input.parameters]
|
|
5539
|
+
}
|
|
5540
|
+
}, { client: this.#client });
|
|
5541
|
+
}
|
|
5542
|
+
/** The connection URI exists only in this response; nothing in the CLI persists it. */
|
|
5543
|
+
async createProjectDatabaseAccess(input) {
|
|
5544
|
+
const value = await createProjectDatabaseAccess({
|
|
5545
|
+
project_id: input.projectId,
|
|
5546
|
+
projectDatabaseAccessRequest: {
|
|
5547
|
+
environment: input.environment,
|
|
5548
|
+
mode: input.mode,
|
|
5549
|
+
ttl_seconds: input.ttlSeconds,
|
|
5550
|
+
label: input.label
|
|
5551
|
+
}
|
|
5552
|
+
}, { client: this.#client });
|
|
5553
|
+
assertProjectDatabaseAccessCredential(value);
|
|
5554
|
+
return value;
|
|
5555
|
+
}
|
|
5556
|
+
async listProjectDatabaseAccess(input) {
|
|
5557
|
+
const value = await listProjectDatabaseAccess({
|
|
5558
|
+
project_id: input.projectId,
|
|
5559
|
+
...input.environment === void 0 ? {} : { environment: input.environment }
|
|
5560
|
+
}, { client: this.#client });
|
|
5561
|
+
assertProjectDatabaseAccessPage(value);
|
|
5562
|
+
return value;
|
|
5563
|
+
}
|
|
5564
|
+
async revokeProjectDatabaseAccess(input) {
|
|
5565
|
+
const value = await revokeProjectDatabaseAccess({ project_id: input.projectId, access_id: input.accessId }, { client: this.#client });
|
|
5566
|
+
assertProjectDatabaseAccess(value);
|
|
5567
|
+
return value;
|
|
5568
|
+
}
|
|
5569
|
+
async planPaidDomain(input) {
|
|
5570
|
+
return planPaidProjectDomain({ project_id: input.projectId, paidDomainRequest: { hostname: input.hostname } }, { client: this.#client });
|
|
5571
|
+
}
|
|
5572
|
+
async applyPaidDomain(input) {
|
|
5573
|
+
return applyPaidProjectDomain({
|
|
5574
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5575
|
+
project_id: input.projectId,
|
|
5576
|
+
paidDomainRequest: { hostname: input.hostname }
|
|
5577
|
+
}, { client: this.#client });
|
|
5578
|
+
}
|
|
5579
|
+
async getPaidDomain(projectId) {
|
|
5580
|
+
return getPaidProjectDomain({ project_id: projectId }, { client: this.#client });
|
|
5581
|
+
}
|
|
5582
|
+
async deletePaidDomain(input) {
|
|
5583
|
+
return deletePaidProjectDomain({
|
|
5584
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5585
|
+
project_id: input.projectId,
|
|
5586
|
+
paidDomainRequest: { hostname: input.hostname }
|
|
5587
|
+
}, { client: this.#client });
|
|
5588
|
+
}
|
|
5589
|
+
async ensureDevShareLink(projectId) {
|
|
5590
|
+
return ensureProjectDevShareLink({ project_id: projectId }, { client: this.#client });
|
|
5591
|
+
}
|
|
5592
|
+
async rotateDevShareLink(projectId, idempotencyKey2) {
|
|
5593
|
+
return rotateProjectDevShareLink({ project_id: projectId, "Idempotency-Key": idempotencyKey2 }, { client: this.#client });
|
|
5594
|
+
}
|
|
5595
|
+
async revokeDevShareLink(projectId, idempotencyKey2) {
|
|
5596
|
+
return revokeProjectDevShareLink({ project_id: projectId, "Idempotency-Key": idempotencyKey2 }, { client: this.#client });
|
|
5597
|
+
}
|
|
5598
|
+
async setDevAccessMode(projectId, mode, idempotencyKey2) {
|
|
5599
|
+
return setProjectDevAccessMode({
|
|
5600
|
+
project_id: projectId,
|
|
5601
|
+
"Idempotency-Key": idempotencyKey2,
|
|
5602
|
+
setDevAccessModeRequest: { mode }
|
|
5603
|
+
}, { client: this.#client });
|
|
5604
|
+
}
|
|
5605
|
+
async createDevAccessTicket(projectId) {
|
|
5606
|
+
return createProjectDevAccessTicket({ project_id: projectId }, { client: this.#client });
|
|
5607
|
+
}
|
|
5608
|
+
async submitFeedback(input) {
|
|
5609
|
+
return parseFeedbackReceipt(await submitFeedback({ "Idempotency-Key": input.idempotencyKey, feedbackSubmission: input.report }, { client: this.#client }));
|
|
5610
|
+
}
|
|
5611
|
+
async getFeedback(feedbackId, cursor) {
|
|
5612
|
+
return parseFeedbackStatus(await getFeedback({ feedback_id: feedbackId, ...cursor === void 0 ? {} : { cursor } }, { client: this.#client }));
|
|
5613
|
+
}
|
|
5614
|
+
async createProject(input) {
|
|
5615
|
+
return createProject({
|
|
5616
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5617
|
+
createProjectRequest: {
|
|
5618
|
+
organization_id: input.organizationId,
|
|
5619
|
+
name: input.name,
|
|
5620
|
+
...input.dataMode === void 0 ? {} : { data_mode: input.dataMode },
|
|
5621
|
+
...input.devAccessMode === void 0 ? {} : { dev_access_mode: input.devAccessMode },
|
|
5622
|
+
...input.region === void 0 ? {} : { region: input.region }
|
|
5623
|
+
}
|
|
5624
|
+
}, { client: this.#client });
|
|
5625
|
+
}
|
|
5626
|
+
async getOperation(operationId) {
|
|
5627
|
+
return getOperation({ operation_id: operationId }, { client: this.#client });
|
|
5628
|
+
}
|
|
5629
|
+
async reconcileOperation(input) {
|
|
5630
|
+
return reconcileOperation({
|
|
5631
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5632
|
+
operation_id: input.operationId
|
|
5633
|
+
}, { client: this.#client });
|
|
5634
|
+
}
|
|
5635
|
+
async connectGithub(input) {
|
|
5636
|
+
return connectGithubOrganization({
|
|
5637
|
+
organization_id: input.organizationId,
|
|
5638
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5639
|
+
connectGithubOrganizationRequest: {}
|
|
5640
|
+
}, { client: this.#client });
|
|
5641
|
+
}
|
|
5642
|
+
async getGithubConnection(organizationId) {
|
|
5643
|
+
return getGithubOrganizationConnection({ organization_id: organizationId }, { client: this.#client });
|
|
5644
|
+
}
|
|
5645
|
+
async linkSource(input) {
|
|
5646
|
+
return linkProjectSource({
|
|
5647
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5648
|
+
project_id: input.projectId,
|
|
5649
|
+
linkProjectSourceRequest: {
|
|
5650
|
+
repository_owner: input.repositoryOwner,
|
|
5651
|
+
repository_name: input.repositoryName
|
|
5652
|
+
}
|
|
5653
|
+
}, { client: this.#client });
|
|
5654
|
+
}
|
|
5655
|
+
async configureAutoDeploy(input) {
|
|
5656
|
+
return configureProjectSourceAutoDeploy({
|
|
5657
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5658
|
+
project_id: input.projectId,
|
|
5659
|
+
configureSourceAutoDeployRequest: { branch: input.branch, enabled: input.enabled }
|
|
5660
|
+
}, { client: this.#client });
|
|
5661
|
+
}
|
|
5662
|
+
async getAutoDeploy(projectId) {
|
|
5663
|
+
return getProjectSourceAutoDeploy({ project_id: projectId }, { client: this.#client });
|
|
5664
|
+
}
|
|
5665
|
+
async authorizeCloudflareDns(input) {
|
|
5666
|
+
return createCloudflareDnsAuthorization({
|
|
5667
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5668
|
+
project_id: input.projectId,
|
|
5669
|
+
createCloudflareDnsAuthorizationRequest: { zone: input.zone }
|
|
5670
|
+
}, { client: this.#client });
|
|
5671
|
+
}
|
|
5672
|
+
async getCloudflareDnsStatus(projectId) {
|
|
5673
|
+
return getCloudflareDnsAuthorizationStatus({ project_id: projectId }, { client: this.#client });
|
|
5674
|
+
}
|
|
5675
|
+
async applyProjectDomains(input) {
|
|
5676
|
+
return configureProjectDomains({ "Idempotency-Key": input.idempotencyKey, project_id: input.projectId }, { client: this.#client });
|
|
5677
|
+
}
|
|
5678
|
+
async planDeployment(input) {
|
|
5679
|
+
return planDeployment({
|
|
5680
|
+
project_id: input.projectId,
|
|
5681
|
+
planDeploymentRequest: { commit_sha: input.commitSha, environment: input.environment }
|
|
5682
|
+
}, { client: this.#client });
|
|
5683
|
+
}
|
|
5684
|
+
async createDeployment(input) {
|
|
5685
|
+
return createDeployment({
|
|
5686
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5687
|
+
project_id: input.projectId,
|
|
5688
|
+
createDeploymentRequest: { plan_id: input.planId }
|
|
5689
|
+
}, { client: this.#client });
|
|
5690
|
+
}
|
|
5691
|
+
async getDeployment(input) {
|
|
5692
|
+
return getDeployment({ project_id: input.projectId, deployment_id: input.deploymentId }, { client: this.#client });
|
|
5693
|
+
}
|
|
5694
|
+
async streamOperationEvents(operationId, signal) {
|
|
5695
|
+
return (await streamOperationEvents({ operation_id: operationId }, { client: this.#client, signal, headers: { Accept: "text/event-stream" } })).stream;
|
|
5696
|
+
}
|
|
5697
|
+
async getDeploymentLogs(input) {
|
|
5698
|
+
return getDeploymentLogs({
|
|
5699
|
+
project_id: input.projectId,
|
|
5700
|
+
deployment_id: input.deploymentId,
|
|
5701
|
+
limit: input.limit,
|
|
5702
|
+
...input.cursor === void 0 ? {} : { cursor: input.cursor }
|
|
5703
|
+
}, { client: this.#client });
|
|
5704
|
+
}
|
|
5705
|
+
async streamDeploymentLogs(input, signal) {
|
|
5706
|
+
return (await streamDeploymentLogs({ project_id: input.projectId, deployment_id: input.deploymentId }, { client: this.#client, signal, headers: { Accept: "text/event-stream" } })).stream;
|
|
5707
|
+
}
|
|
5708
|
+
async planRollback(input) {
|
|
5709
|
+
return planDeploymentRollback({ project_id: input.projectId, target_deployment_id: input.deploymentId }, { client: this.#client });
|
|
5710
|
+
}
|
|
5711
|
+
async rollback(input) {
|
|
5712
|
+
return rollbackDeployment({
|
|
5713
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5714
|
+
"If-Match": input.ifMatch,
|
|
5715
|
+
"X-Confirmation-Token": input.confirmationToken,
|
|
5716
|
+
project_id: input.projectId,
|
|
5717
|
+
target_deployment_id: input.deploymentId
|
|
5718
|
+
}, { client: this.#client });
|
|
5719
|
+
}
|
|
5720
|
+
async planPromotion(input) {
|
|
5721
|
+
return planDeploymentPromotion({ project_id: input.projectId, source_deployment_id: input.sourceDeploymentId }, { client: this.#client });
|
|
5722
|
+
}
|
|
5723
|
+
async promote(input) {
|
|
5724
|
+
return promoteDeployment({
|
|
5725
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5726
|
+
"If-Match": input.ifMatch,
|
|
5727
|
+
"X-Confirmation-Token": input.confirmationToken,
|
|
5728
|
+
project_id: input.projectId,
|
|
5729
|
+
source_deployment_id: input.sourceDeploymentId
|
|
5730
|
+
}, { client: this.#client });
|
|
5731
|
+
}
|
|
5732
|
+
async planDelete(projectId) {
|
|
5733
|
+
return planProjectDeletion({ project_id: projectId }, { client: this.#client });
|
|
5734
|
+
}
|
|
5735
|
+
async deleteProject(input) {
|
|
5736
|
+
return deleteProject({
|
|
5737
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5738
|
+
"If-Match": input.ifMatch,
|
|
5739
|
+
"X-Confirmation-Token": input.confirmationToken,
|
|
5740
|
+
project_id: input.projectId
|
|
5741
|
+
}, { client: this.#client });
|
|
5742
|
+
}
|
|
5743
|
+
async listEnvironmentSecrets(input) {
|
|
5744
|
+
return listEnvironmentSecrets({ project_id: input.projectId, environment_id: input.environmentId }, { client: this.#client });
|
|
5745
|
+
}
|
|
5746
|
+
async listFunctionRuns(input) {
|
|
5747
|
+
return listFunctionRuns({ project_id: input.projectId, environment_id: input.environmentId, limit: input.limit }, { client: this.#client });
|
|
5748
|
+
}
|
|
5749
|
+
async putEnvironmentSecret(input) {
|
|
5750
|
+
return putEnvironmentSecret({
|
|
5751
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5752
|
+
project_id: input.projectId,
|
|
5753
|
+
environment_id: input.environmentId,
|
|
5754
|
+
secret_name: input.name,
|
|
5755
|
+
putEnvironmentSecretRequest: { value: input.value }
|
|
5756
|
+
}, { client: this.#client });
|
|
5757
|
+
}
|
|
5758
|
+
async deleteEnvironmentSecret(input) {
|
|
5759
|
+
return deleteEnvironmentSecret({
|
|
5760
|
+
"Idempotency-Key": input.idempotencyKey,
|
|
5761
|
+
project_id: input.projectId,
|
|
5762
|
+
environment_id: input.environmentId,
|
|
5763
|
+
secret_name: input.name
|
|
5764
|
+
}, { client: this.#client });
|
|
5765
|
+
}
|
|
5766
|
+
managedMail(input) {
|
|
5767
|
+
return executeManagedMail(this.#client, input);
|
|
5768
|
+
}
|
|
5769
|
+
};
|
|
5770
|
+
|
|
5771
|
+
// apps/product-cli/dist/repository-init.js
|
|
5772
|
+
var MAXIMUM_PACKAGE_BYTES = 1024 * 1024;
|
|
4886
5773
|
var MAXIMUM_CONFIGURATION_BYTES = 64 * 1024;
|
|
4887
5774
|
var MAXIMUM_SOURCE_BYTES = 2 * 1024 * 1024;
|
|
4888
5775
|
var STORAGE_RUNTIME_BINDINGS = Object.freeze([
|
|
@@ -4942,33 +5829,95 @@ function environmentToken(environment2 = {}) {
|
|
|
4942
5829
|
throw new ProductApiAuthenticationError("invalid_environment_token");
|
|
4943
5830
|
return value;
|
|
4944
5831
|
}
|
|
5832
|
+
function environmentProfile(environment2 = {}) {
|
|
5833
|
+
const value = environment2.OHMYHOST_PROFILE;
|
|
5834
|
+
if (value === void 0 || value === "")
|
|
5835
|
+
return void 0;
|
|
5836
|
+
if (!isProfileName(value))
|
|
5837
|
+
throw new ProductApiAuthenticationError("invalid_profile_binding");
|
|
5838
|
+
return value;
|
|
5839
|
+
}
|
|
5840
|
+
var profileRequest = (input, bound) => ({
|
|
5841
|
+
...input?.name === void 0 ? {} : { name: input.name },
|
|
5842
|
+
...bound === void 0 ? {} : { bound },
|
|
5843
|
+
...input?.organizationId === void 0 ? {} : { organizationId: input.organizationId },
|
|
5844
|
+
...input?.userId === void 0 ? {} : { userId: input.userId }
|
|
5845
|
+
});
|
|
4945
5846
|
var createAuthenticatedProductTransport = async (signal, overrides = {}) => {
|
|
4946
|
-
const
|
|
5847
|
+
const platform = resolveProductCliEnvironment(overrides.environment);
|
|
4947
5848
|
const apiToken = environmentToken(overrides.environment);
|
|
5849
|
+
const bound = environmentProfile(overrides.environment);
|
|
5850
|
+
const baseUrl = overrides.productApiOrigin ?? platform.apiOrigin;
|
|
4948
5851
|
const boundedFetch = createBoundedFetch(overrides.fetch ?? fetch, signal, REQUEST_TIMEOUT_MS, MAX_PUBLIC_RESPONSE_BYTES);
|
|
4949
|
-
|
|
5852
|
+
const registry = overrides.profiles ?? new NativeKeyringProfileRegistry(void 0, platform.credentialService);
|
|
5853
|
+
const binding = overrides.request?.bindOrganization === true;
|
|
5854
|
+
const request = profileRequest(overrides.request, bound);
|
|
5855
|
+
if (apiToken !== void 0) {
|
|
5856
|
+
await verifyEnvironmentTokenContext({
|
|
5857
|
+
token: apiToken,
|
|
5858
|
+
request: binding ? profileRequest({}, bound) : request,
|
|
5859
|
+
registry,
|
|
5860
|
+
baseUrl,
|
|
5861
|
+
fetch: boundedFetch
|
|
5862
|
+
});
|
|
4950
5863
|
return {
|
|
4951
|
-
baseUrl
|
|
5864
|
+
baseUrl,
|
|
4952
5865
|
accessToken: apiToken,
|
|
4953
5866
|
fetch: boundedFetch,
|
|
4954
|
-
|
|
4955
|
-
|
|
5867
|
+
workspace: void 0,
|
|
5868
|
+
context: { credential: "environment_token", profile: null }
|
|
4956
5869
|
};
|
|
4957
|
-
|
|
4958
|
-
const stored = await store.read();
|
|
4959
|
-
if (stored === void 0)
|
|
4960
|
-
throw new ProductApiAuthenticationError("authentication_required");
|
|
5870
|
+
}
|
|
4961
5871
|
const now = overrides.now ?? (() => /* @__PURE__ */ new Date());
|
|
4962
5872
|
const refresher = overrides.tokenRefresher ?? new PublicWorkosTokenRefresher(overrides.environment, overrides.fetch, now);
|
|
4963
|
-
const
|
|
5873
|
+
const profiles = await loadProfiles(registry, {
|
|
5874
|
+
baseUrl,
|
|
5875
|
+
fetch: boundedFetch,
|
|
5876
|
+
signal,
|
|
5877
|
+
now,
|
|
5878
|
+
refresher
|
|
5879
|
+
});
|
|
5880
|
+
const selection = binding && request.organizationId !== void 0 ? selectProfileForOrganization(profiles, {
|
|
5881
|
+
...request,
|
|
5882
|
+
organizationId: request.organizationId
|
|
5883
|
+
}) : selectProfile(profiles, request);
|
|
5884
|
+
if (selection.outcome !== "selected")
|
|
5885
|
+
throw profileSelectionError(selection, request, platform.commandPrefix, overrides.selector ?? "cli");
|
|
5886
|
+
const profile = selection.profile;
|
|
5887
|
+
const store = registry.credential(profile);
|
|
5888
|
+
const stored = await store.read();
|
|
5889
|
+
if (stored === void 0)
|
|
5890
|
+
throw missingLogin(profile, platform.commandPrefix);
|
|
5891
|
+
const credential = await currentCredential(stored, store, signal, now, refresher, () => registry.remove(profile));
|
|
4964
5892
|
return {
|
|
4965
|
-
baseUrl
|
|
5893
|
+
baseUrl,
|
|
4966
5894
|
accessToken: credential.accessToken,
|
|
4967
5895
|
fetch: boundedFetch,
|
|
4968
|
-
workspace: { store, refresher }
|
|
5896
|
+
workspace: { store, refresher, profiles: registry, profile },
|
|
5897
|
+
context: { credential: "profile", profile }
|
|
5898
|
+
};
|
|
5899
|
+
};
|
|
5900
|
+
var listSavedProfiles = async (signal, overrides = {}) => {
|
|
5901
|
+
const platform = resolveProductCliEnvironment(overrides.environment);
|
|
5902
|
+
const apiToken = environmentToken(overrides.environment);
|
|
5903
|
+
const bound = environmentProfile(overrides.environment);
|
|
5904
|
+
const registry = overrides.profiles ?? new NativeKeyringProfileRegistry(void 0, platform.credentialService);
|
|
5905
|
+
const now = overrides.now ?? (() => /* @__PURE__ */ new Date());
|
|
5906
|
+
const profiles = apiToken === void 0 ? await loadProfiles(registry, {
|
|
5907
|
+
baseUrl: overrides.productApiOrigin ?? platform.apiOrigin,
|
|
5908
|
+
fetch: createBoundedFetch(overrides.fetch ?? fetch, signal, REQUEST_TIMEOUT_MS, MAX_PUBLIC_RESPONSE_BYTES),
|
|
5909
|
+
signal,
|
|
5910
|
+
now,
|
|
5911
|
+
refresher: overrides.tokenRefresher ?? new PublicWorkosTokenRefresher(overrides.environment, overrides.fetch, now)
|
|
5912
|
+
}) : await registry.list();
|
|
5913
|
+
return {
|
|
5914
|
+
profiles: profiles.map(publicProfile),
|
|
5915
|
+
bound: bound ?? null,
|
|
5916
|
+
environment_token: apiToken !== void 0
|
|
4969
5917
|
};
|
|
4970
5918
|
};
|
|
4971
|
-
var
|
|
5919
|
+
var missingLogin = (profile, commandPrefix) => new ProfileSelectionError("authentication_required", 5, `The saved login ${profile.name} has no credential on this computer. Run '${commandPrefix} login${profile.organizationId === null ? "" : ` --organization ${profile.organizationId}`} --profile-name ${profile.name} --json'.`);
|
|
5920
|
+
var currentCredential = async (stored, store, signal, now, tokenRefresher, forget) => {
|
|
4972
5921
|
const expiresAt = stored.expiresAt === void 0 ? NaN : Date.parse(stored.expiresAt);
|
|
4973
5922
|
if (Number.isFinite(expiresAt) && expiresAt > now().getTime() + REQUEST_TIMEOUT_MS) {
|
|
4974
5923
|
return stored;
|
|
@@ -4984,12 +5933,73 @@ var currentCredential = async (stored, store, signal, now, tokenRefresher) => {
|
|
|
4984
5933
|
return carried;
|
|
4985
5934
|
} catch (error) {
|
|
4986
5935
|
if (error instanceof TokenRefreshRejectedError) {
|
|
4987
|
-
await
|
|
5936
|
+
await forget();
|
|
4988
5937
|
throw new ProductApiAuthenticationError("authentication_required");
|
|
4989
5938
|
}
|
|
4990
5939
|
throw new ProductApiAuthenticationError("token_refresh_failed");
|
|
4991
5940
|
}
|
|
4992
5941
|
};
|
|
5942
|
+
var loadProfiles = async (registry, context) => {
|
|
5943
|
+
const legacy = registry.legacy();
|
|
5944
|
+
const stored = await legacy.read();
|
|
5945
|
+
if (stored !== void 0)
|
|
5946
|
+
await migrateLegacyLogin(registry, legacy, stored, context);
|
|
5947
|
+
return registry.list();
|
|
5948
|
+
};
|
|
5949
|
+
var migrateLegacyLogin = async (registry, legacy, stored, context) => {
|
|
5950
|
+
let credential;
|
|
5951
|
+
try {
|
|
5952
|
+
credential = await currentCredential(stored, legacy, context.signal, context.now, context.refresher, () => legacy.clear());
|
|
5953
|
+
} catch (error) {
|
|
5954
|
+
if (error instanceof ProductApiAuthenticationError && error.code === "authentication_required")
|
|
5955
|
+
return;
|
|
5956
|
+
throw error;
|
|
5957
|
+
}
|
|
5958
|
+
const api = new GeneratedSdkProductApi(context.baseUrl, credential.accessToken, context.fetch);
|
|
5959
|
+
let identity;
|
|
5960
|
+
try {
|
|
5961
|
+
identity = await api.getCurrentIdentity();
|
|
5962
|
+
} catch (error) {
|
|
5963
|
+
if (!isProblem(error, "unauthenticated"))
|
|
5964
|
+
throw error;
|
|
5965
|
+
return;
|
|
5966
|
+
}
|
|
5967
|
+
const userId = verifiedUserId(identity);
|
|
5968
|
+
const organizationId = parseCurrentIdentity(identity).organization_ids[0] ?? null;
|
|
5969
|
+
const organizationName = organizationId === null ? null : (await api.getAccountProfile()).organizations.find((organization) => organization.id === organizationId)?.name ?? null;
|
|
5970
|
+
const login = { userId, organizationId, organizationName };
|
|
5971
|
+
await registry.save({ name: defaultProfileName(await registry.list(), login), ...login }, credential);
|
|
5972
|
+
await legacy.clear();
|
|
5973
|
+
};
|
|
5974
|
+
var isProblem = (error, code) => typeof error === "object" && error !== null && "code" in error && error.code === code;
|
|
5975
|
+
var verifyEnvironmentTokenContext = async (input) => {
|
|
5976
|
+
const { request } = input;
|
|
5977
|
+
const named = request.name ?? request.bound;
|
|
5978
|
+
if (named === void 0 && request.organizationId === void 0 && request.userId === void 0)
|
|
5979
|
+
return null;
|
|
5980
|
+
const refuse = (target) => new ProfileSelectionError("environment_token_context_mismatch", 2, `${target} Unset OHMYHOST_TOKEN to use the saved login, or load the key of that account from its private env file. Nothing was sent.`);
|
|
5981
|
+
if (request.name !== void 0 && request.bound !== void 0 && request.name !== request.bound)
|
|
5982
|
+
throw refuse(`This call names profile ${request.name}, but the process is bound to OHMYHOST_PROFILE=${request.bound}.`);
|
|
5983
|
+
const profile = named === void 0 ? void 0 : (await input.registry.list()).find((saved) => saved.name === named);
|
|
5984
|
+
if (named !== void 0 && profile === void 0)
|
|
5985
|
+
throw refuse(`OHMYHOST_TOKEN overrides saved logins in this process, and no saved login is named ${named}.`);
|
|
5986
|
+
const { userId, organizationId } = await readTokenIdentity(input);
|
|
5987
|
+
const owner = `OHMYHOST_TOKEN belongs to user ${userId} in organization ${organizationId ?? "none"},`;
|
|
5988
|
+
if (profile !== void 0 && (profile.userId !== userId || profile.organizationId !== organizationId))
|
|
5989
|
+
throw refuse(`${owner} but this call names ${describeProfile(profile)}.`);
|
|
5990
|
+
if (request.organizationId !== void 0 && request.organizationId !== organizationId)
|
|
5991
|
+
throw refuse(`${owner} but this call targets organization ${request.organizationId}.`);
|
|
5992
|
+
if (request.userId !== void 0 && request.userId !== userId)
|
|
5993
|
+
throw refuse(`${owner} but this call targets user ${request.userId}.`);
|
|
5994
|
+
return { userId, organizationId };
|
|
5995
|
+
};
|
|
5996
|
+
var readTokenIdentity = async (input) => {
|
|
5997
|
+
const identity = parseCurrentIdentity(await new GeneratedSdkProductApi(input.baseUrl, input.token, input.fetch).getCurrentIdentity());
|
|
5998
|
+
return {
|
|
5999
|
+
userId: identity.actor_id.startsWith("user:") ? identity.actor_id.slice(5) : identity.actor_id,
|
|
6000
|
+
organizationId: identity.organization_ids[0] ?? null
|
|
6001
|
+
};
|
|
6002
|
+
};
|
|
4993
6003
|
var FetchWorkosPublicTransport = class {
|
|
4994
6004
|
parentSignal;
|
|
4995
6005
|
timeoutMs;
|
|
@@ -5167,7 +6177,7 @@ var boundedSignal = (parent, timeoutMs) => AbortSignal.any([parent, AbortSignal.
|
|
|
5167
6177
|
var isAbortOrTimeout = (error) => error instanceof DOMException && (error.name === "AbortError" || error.name === "TimeoutError");
|
|
5168
6178
|
|
|
5169
6179
|
// apps/mcp/dist/local-client.js
|
|
5170
|
-
import { lstat as lstat2, open as
|
|
6180
|
+
import { lstat as lstat2, open as open3 } from "node:fs/promises";
|
|
5171
6181
|
import { isAbsolute } from "node:path";
|
|
5172
6182
|
var OperationEventsUnavailableError = class extends Error {
|
|
5173
6183
|
constructor() {
|
|
@@ -5177,8 +6187,11 @@ var OperationEventsUnavailableError = class extends Error {
|
|
|
5177
6187
|
};
|
|
5178
6188
|
async function createAuthenticatedLocalMcpClient(signal, overrides = {}) {
|
|
5179
6189
|
try {
|
|
5180
|
-
const transport = await createAuthenticatedProductTransport(signal,
|
|
5181
|
-
|
|
6190
|
+
const transport = await createAuthenticatedProductTransport(signal, {
|
|
6191
|
+
...overrides,
|
|
6192
|
+
selector: "mcp"
|
|
6193
|
+
});
|
|
6194
|
+
return new GeneratedSdkLocalMcpClient(transport.baseUrl, transport.accessToken, transport.fetch, transport.workspace, transport.context, resolveProductCliEnvironment(overrides.environment).commandPrefix);
|
|
5182
6195
|
} catch (error) {
|
|
5183
6196
|
if (!(error instanceof ProductApiAuthenticationError))
|
|
5184
6197
|
throw error;
|
|
@@ -5191,11 +6204,44 @@ async function createAuthenticatedLocalMcpClient(signal, overrides = {}) {
|
|
|
5191
6204
|
var GeneratedSdkLocalMcpClient = class {
|
|
5192
6205
|
#client;
|
|
5193
6206
|
#workspace;
|
|
6207
|
+
#context;
|
|
6208
|
+
#commandPrefix;
|
|
5194
6209
|
#rescope;
|
|
5195
|
-
constructor(baseUrl, accessToken, fetch2, workspace) {
|
|
6210
|
+
constructor(baseUrl, accessToken, fetch2, workspace, context, commandPrefix = "OHMYHOST_ENVIRONMENT=production ohmyhost") {
|
|
5196
6211
|
this.#rescope = (token) => createClient({ auth: token, baseUrl, fetch: fetch2, throwOnError: true });
|
|
5197
6212
|
this.#client = this.#rescope(accessToken);
|
|
5198
6213
|
this.#workspace = workspace;
|
|
6214
|
+
this.#context = context ?? {
|
|
6215
|
+
credential: workspace === void 0 ? "environment_token" : "profile",
|
|
6216
|
+
profile: workspace?.profile ?? null
|
|
6217
|
+
};
|
|
6218
|
+
this.#commandPrefix = commandPrefix;
|
|
6219
|
+
}
|
|
6220
|
+
actingAs() {
|
|
6221
|
+
return this.#contextReport();
|
|
6222
|
+
}
|
|
6223
|
+
/** Which account this call acts as, without any credential. */
|
|
6224
|
+
#contextReport() {
|
|
6225
|
+
const profile = this.#workspace?.profile ?? this.#context.profile;
|
|
6226
|
+
return {
|
|
6227
|
+
credential: this.#context.credential,
|
|
6228
|
+
profile: profile === null ? null : publicProfile(profile)
|
|
6229
|
+
};
|
|
6230
|
+
}
|
|
6231
|
+
/**
|
|
6232
|
+
* Bind this call's login, which has no organization yet, and continue with its new credential.
|
|
6233
|
+
* A login in another organization keeps it; the provider verifies the account first.
|
|
6234
|
+
*/
|
|
6235
|
+
async #bind(organization, signal) {
|
|
6236
|
+
const session = this.#interactiveSession();
|
|
6237
|
+
const bound = await selectWorkspace(session, organization, signal, (token) => getCurrentIdentity({}, { client: this.#rescope(token) }));
|
|
6238
|
+
const store = session.profiles.credential(bound);
|
|
6239
|
+
const credential = await store.read();
|
|
6240
|
+
if (credential === void 0)
|
|
6241
|
+
throw new InteractiveSessionRequiredError();
|
|
6242
|
+
this.#workspace = { ...session, store, profile: bound };
|
|
6243
|
+
this.#client = this.#rescope(credential.accessToken);
|
|
6244
|
+
return bound;
|
|
5199
6245
|
}
|
|
5200
6246
|
async changeDatabaseCompute(input) {
|
|
5201
6247
|
return changeDatabaseCompute({
|
|
@@ -5261,13 +6307,15 @@ var GeneratedSdkLocalMcpClient = class {
|
|
|
5261
6307
|
async getCurrentIdentity(signal) {
|
|
5262
6308
|
const identity = await getCurrentIdentity({}, { client: this.#client });
|
|
5263
6309
|
if (this.#workspace === void 0 || parseCurrentIdentity(identity).organization_ids.length > 0)
|
|
5264
|
-
return identity;
|
|
6310
|
+
return { ...identity, context: this.#contextReport() };
|
|
5265
6311
|
const selection = chooseWorkspace(await this.#readWorkspaces(), void 0);
|
|
5266
6312
|
if (selection.outcome !== "selected")
|
|
5267
|
-
return identity;
|
|
5268
|
-
await
|
|
5269
|
-
|
|
5270
|
-
|
|
6313
|
+
return { ...identity, context: this.#contextReport() };
|
|
6314
|
+
await this.#bind(selection.organization, signal);
|
|
6315
|
+
return {
|
|
6316
|
+
...await getCurrentIdentity({}, { client: this.#client }),
|
|
6317
|
+
context: this.#contextReport()
|
|
6318
|
+
};
|
|
5271
6319
|
}
|
|
5272
6320
|
async changeProjectHandle(input) {
|
|
5273
6321
|
return changeProjectHandle({
|
|
@@ -5380,29 +6428,39 @@ var GeneratedSdkLocalMcpClient = class {
|
|
|
5380
6428
|
...input.signupSource === void 0 ? {} : { signup_source: input.signupSource }
|
|
5381
6429
|
}
|
|
5382
6430
|
}, { client: this.#client });
|
|
6431
|
+
const current = this.#interactiveSession().profile;
|
|
6432
|
+
if (current.organizationId !== null && current.organizationId !== created.id)
|
|
6433
|
+
return {
|
|
6434
|
+
organization: { id: created.id, name: created.name },
|
|
6435
|
+
selected: current.organizationId,
|
|
6436
|
+
profile: publicProfile(current),
|
|
6437
|
+
next_action: `Run '${this.#commandPrefix} login --organization ${created.id} --user ${current.userId} --json' to add a login for the new workspace as the same user, then pass its profile_name.`
|
|
6438
|
+
};
|
|
5383
6439
|
return this.selectOrganization(created.id, signal);
|
|
5384
6440
|
}
|
|
5385
6441
|
async listOrganizations() {
|
|
5386
6442
|
const session = this.#interactiveSession();
|
|
5387
6443
|
return {
|
|
5388
6444
|
organizations: (await this.#readWorkspaces()).map(publicWorkspace),
|
|
5389
|
-
selected:
|
|
6445
|
+
selected: session.profile.organizationId,
|
|
6446
|
+
profile: publicProfile(session.profile)
|
|
5390
6447
|
};
|
|
5391
6448
|
}
|
|
5392
6449
|
async selectOrganization(organizationId, signal) {
|
|
5393
|
-
|
|
6450
|
+
this.#interactiveSession();
|
|
5394
6451
|
const selection = chooseWorkspace(await this.#readWorkspaces(), organizationId);
|
|
5395
6452
|
if (selection.outcome !== "selected")
|
|
5396
6453
|
throw new Error(`ORGANIZATION_NOT_FOUND:${organizationId}`);
|
|
5397
|
-
await
|
|
6454
|
+
const profile = await this.#bind(selection.organization, signal);
|
|
5398
6455
|
return {
|
|
5399
6456
|
organization: publicWorkspace(selection.organization),
|
|
5400
|
-
selected: selection.organization.id
|
|
6457
|
+
selected: selection.organization.id,
|
|
6458
|
+
profile: publicProfile(profile)
|
|
5401
6459
|
};
|
|
5402
6460
|
}
|
|
5403
6461
|
async #readWorkspaces() {
|
|
5404
6462
|
this.#interactiveSession();
|
|
5405
|
-
return parseAccountProfile(await getAccountProfile({ client: this.#client }));
|
|
6463
|
+
return parseAccountProfile(await getAccountProfile({ client: this.#client })).organizations;
|
|
5406
6464
|
}
|
|
5407
6465
|
#interactiveSession() {
|
|
5408
6466
|
if (this.#workspace === void 0)
|
|
@@ -5681,7 +6739,7 @@ async function readExportPasswordFile(path) {
|
|
|
5681
6739
|
const before = await lstat2(path);
|
|
5682
6740
|
if (!before.isFile() || before.isSymbolicLink() || before.size < 1 || before.size > 1024 || process.platform !== "win32" && (before.mode & 63) !== 0)
|
|
5683
6741
|
throw new Error();
|
|
5684
|
-
file = await
|
|
6742
|
+
file = await open3(path, "r");
|
|
5685
6743
|
const after = await file.stat();
|
|
5686
6744
|
if (after.ino !== before.ino || after.dev !== before.dev || after.size !== before.size)
|
|
5687
6745
|
throw new Error();
|
|
@@ -5702,6 +6760,7 @@ async function readExportPasswordFile(path) {
|
|
|
5702
6760
|
|
|
5703
6761
|
// apps/mcp/dist/local-server.js
|
|
5704
6762
|
var identifier2 = external_exports.string().min(1).max(256);
|
|
6763
|
+
var profileName = external_exports.string().regex(/^[a-z0-9][a-z0-9_-]{0,62}$/u).optional().describe("Saved login to act as (profile_list shows them). Needed only when several logins could run this call; OHMYHOST_PROFILE of this server must match it.");
|
|
5705
6764
|
var idempotencyKey = external_exports.string().min(1).max(256);
|
|
5706
6765
|
var commitSha = external_exports.string().regex(/^[a-f0-9]{40}$/u);
|
|
5707
6766
|
var domainName = external_exports.string().regex(/^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/u);
|
|
@@ -5848,7 +6907,7 @@ function createLocalOhmyhostMcpServer(dependencies) {
|
|
|
5848
6907
|
mode: input.mode,
|
|
5849
6908
|
idempotencyKey: input.idempotency_key
|
|
5850
6909
|
}), { readOnlyHint: false, destructiveHint: false, idempotentHint: true });
|
|
5851
|
-
registerProductTool(server, dependencies, "organization_create", `Create an organization owned by the signed-in user
|
|
6910
|
+
registerProductTool(server, dependencies, "organization_create", `Create an organization owned by the signed-in user. Signup is open. signup_source is optional attribution from a link's r parameter, never a secret; omit it when the customer arrived directly. The server decides any once-per-user bonus; do not promise credits for arbitrary sources. Repeat the same name/source/key after uncertainty. A login that has no organization yet is bound to the new one, so selected names the workspace later calls use; a login already in another organization keeps it and next_action names the login for the new one. Continue with identity_get, github_status and github_connect if needed, then projects. An OHMYHOST_TOKEN process cannot do this; it needs ${commandPrefix} login --json.`, external_exports.object({
|
|
5852
6911
|
name: external_exports.string().min(1).max(128),
|
|
5853
6912
|
signup_source: external_exports.string().regex(/^[a-z0-9][a-z0-9_-]{0,63}$/u).optional(),
|
|
5854
6913
|
idempotency_key: idempotencyKey
|
|
@@ -5857,8 +6916,25 @@ function createLocalOhmyhostMcpServer(dependencies) {
|
|
|
5857
6916
|
...input.signup_source === void 0 ? {} : { signupSource: input.signup_source },
|
|
5858
6917
|
idempotencyKey: input.idempotency_key
|
|
5859
6918
|
}, signal), mutationAnnotations());
|
|
5860
|
-
registerProductTool(server, dependencies, "organization_list", "List the workspaces the
|
|
5861
|
-
registerProductTool(server, dependencies, "organization_use", `
|
|
6919
|
+
registerProductTool(server, dependencies, "organization_list", "List the workspaces the chosen login's user belongs to and which one that login is scoped to. selected is null while none is chosen; every project and billing call then answers resource_not_found. Ask the customer which workspace to use instead of guessing, then call organization_use.", external_exports.object({}), (client2) => client2.listOrganizations());
|
|
6920
|
+
registerProductTool(server, dependencies, "organization_use", `Bind a saved login that has no organization yet to one workspace, so later calls act inside it. A login already in another organization keeps it (profile_organization_fixed): add a login for the other workspace as the same user with ${commandPrefix} login --organization ULID --user USER_ID --json. Read organization_list first, then github_status for the selected workspace and github_connect if needed; the identifier is the platform ULID, not the provider identifier. An OHMYHOST_TOKEN process cannot select anything and needs ${commandPrefix} login --json instead.`, external_exports.object({ organization_id: identifier2 }), (client2, input, signal) => client2.selectOrganization(input.organization_id, signal), mutationAnnotations(), (input) => ({
|
|
6921
|
+
...input.profile_name === void 0 ? {} : { name: input.profile_name },
|
|
6922
|
+
organizationId: input.organization_id,
|
|
6923
|
+
bindOrganization: true
|
|
6924
|
+
}));
|
|
6925
|
+
server.registerTool("profile_list", {
|
|
6926
|
+
description: `List the saved ohmyho.st logins on this computer: each has a name, a user and an organization, never a token. When the customer named a user or organization, pass the matching name as profile_name on later calls; with several logins and no profile_name a call answers profile_selection_required. With no match, the customer adds one with ${commandPrefix} login --organization ULID --user USER_ID --json, which saves nothing if the browser signs in as another account. bound is this server's OHMYHOST_PROFILE; environment_token means OHMYHOST_TOKEN replaces saved logins here.`,
|
|
6927
|
+
inputSchema: external_exports.object({}),
|
|
6928
|
+
annotations: readAnnotations()
|
|
6929
|
+
}, (async (_input, context) => {
|
|
6930
|
+
try {
|
|
6931
|
+
if (dependencies.listProfiles === void 0)
|
|
6932
|
+
throw new CredentialStoreUnavailableError();
|
|
6933
|
+
return toolResult(await dependencies.listProfiles(context.mcpReq.signal));
|
|
6934
|
+
} catch (error) {
|
|
6935
|
+
return toolError(error, dependencies);
|
|
6936
|
+
}
|
|
6937
|
+
}));
|
|
5862
6938
|
registerProductTool(server, dependencies, "database_query", "Read one owner-authorized Dev or Prod database query (at most 100 rows, five-second timeout). Explicitly choose the environment. Shared data resolves to the same physical database. Application RLS policies apply; use an authorized SQL export when a full archive is required.", external_exports.object({
|
|
5863
6939
|
project_id: identifier2,
|
|
5864
6940
|
environment: external_exports.enum(["dev", "prod"]),
|
|
@@ -5956,7 +7032,7 @@ function createLocalOhmyhostMcpServer(dependencies) {
|
|
|
5956
7032
|
});
|
|
5957
7033
|
return { revoked: true, key_id: input.key_id };
|
|
5958
7034
|
}, destructiveAnnotations());
|
|
5959
|
-
registerProductTool(server, dependencies, "identity_get", "Get the
|
|
7035
|
+
registerProductTool(server, dependencies, "identity_get", "Get the ohmyho.st customer/agent identity this call acts as: user, organization and, in context, the saved login or OHMYHOST_TOKEN that supplied it. Compare it with the user and organization the customer named before any change. This does not authenticate the hosted application's end users or provision a customer AuthKit tenant; application authentication is the customer's chosen integration.", external_exports.object({}), (client2, _input, signal) => client2.getCurrentIdentity(signal));
|
|
5960
7036
|
registerProductTool(server, dependencies, "project_handle_check", "Check whether a project address is free before offering it to the customer. A handle is one to five lowercase words of letters and digits joined by single hyphens, three to fifty-nine characters, and never a reserved word such as admin, api, dev or www; it becomes <handle>.check.omh.st for Prod and dev-<handle>.check.omh.st for Dev. The answer names why a handle cannot be used and returns free alternatives, so offer one of those instead of guessing again. Check the name here first, then move an existing project onto it with project_handle_set.", external_exports.object({ handle: external_exports.string().min(1).max(120) }), (client2, input) => client2.checkProjectHandle({ handle: input.handle }));
|
|
5961
7037
|
registerProductTool(server, dependencies, "project_handle_set", "Move a project to an address the customer chose, after project_handle_check said it is free. The Dev and Prod gateways are re-published at the new address and it is stored only once both serve it; the previous address stops answering and anyone may claim it, so a link already shared stops working. Needs the project's current ETag from project_status and one idempotency key; reuse the same key after an uncertain answer. Refused while another operation is running for the project, and refused for an address that is taken, unusable, or the one the project already has. Returns an operation to follow with operation_get.", external_exports.object({
|
|
5962
7038
|
project_id: identifier2,
|
|
@@ -6032,8 +7108,8 @@ function createLocalOhmyhostMcpServer(dependencies) {
|
|
|
6032
7108
|
organizationId: input.organization_id,
|
|
6033
7109
|
idempotencyKey: input.idempotency_key
|
|
6034
7110
|
}), mutationAnnotations());
|
|
6035
|
-
registerProductTool(server, dependencies, "github_status", "Read this workspace's GitHub connection. If not_connected or revoked, an Owner or Admin must run github_connect. A connected installation covers only repositories selected in its settings.", external_exports.object({ organization_id: identifier2 }), (client2, input) => client2.getGithubConnection(input.organization_id));
|
|
6036
|
-
registerProductTool(server, dependencies, "source_link", "Link a repository covered by the workspace GitHub connection. Call github_status first and github_connect once if needed. This returns an operation without another browser consent and never starts a build. Wait for that operation before planning a deploy. If repository access is missing, update the installation using the returned settings action, then retry the same project and key. Never ask for an installation ID or provider token.", external_exports.object({
|
|
7111
|
+
registerProductTool(server, dependencies, "github_status", "Read this workspace's GitHub connection. If not_connected or revoked, an Owner or Admin must run github_connect. A connected installation covers only repositories selected in its settings. Each workspace has its own connection, so the same repository can be connected and linked in the workspaces of separate accounts.", external_exports.object({ organization_id: identifier2 }), (client2, input) => client2.getGithubConnection(input.organization_id));
|
|
7112
|
+
registerProductTool(server, dependencies, "source_link", "Link a repository covered by the workspace GitHub connection. Call github_status first and github_connect once if needed. This returns an operation without another browser consent and never starts a build. Wait for that operation before planning a deploy. If repository access is missing, update the installation using the returned settings action, then retry the same project and key. Never ask for an installation ID or provider token. Errors name the account the call ran as (acting_as): resource_not_found means that account cannot see the project (use the login of the account that owns it), github_connection_required means that workspace has no GitHub connection yet, and repository_not_installed means its GitHub App installation does not cover the repository.", external_exports.object({
|
|
6037
7113
|
project_id: identifier2,
|
|
6038
7114
|
repository_owner: identifier2,
|
|
6039
7115
|
repository_name: identifier2,
|
|
@@ -6251,31 +7327,33 @@ function createLocalOhmyhostMcpServer(dependencies) {
|
|
|
6251
7327
|
name: input.name,
|
|
6252
7328
|
idempotencyKey: input.idempotency_key
|
|
6253
7329
|
}), destructiveAnnotations());
|
|
6254
|
-
server
|
|
6255
|
-
|
|
6256
|
-
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
|
|
6269
|
-
|
|
6270
|
-
|
|
6271
|
-
|
|
6272
|
-
|
|
6273
|
-
|
|
6274
|
-
|
|
6275
|
-
|
|
6276
|
-
|
|
6277
|
-
|
|
6278
|
-
|
|
7330
|
+
registerProductTool(server, dependencies, "secret_set_command", "Return the stdin-only CLI command for setting a secret; the value never enters MCP. The call runs as the chosen login and first reads the project, so an account that cannot see it answers resource_not_found. The command names that login with --profile-name plus its user and organization (--profile-user, --profile-organization), so a login of the same name that belongs to anyone else is refused, for example on another computer; a server with OHMYHOST_TOKEN instead names its key's user and organization with --token-user and --token-organization, and the CLI then runs only with an OHMYHOST_TOKEN of that account. Either way the later write runs as exactly this account or not at all (acting_as shows which).", external_exports.object({
|
|
7331
|
+
project_id: identifier2,
|
|
7332
|
+
environment_id: identifier2,
|
|
7333
|
+
name: secretName,
|
|
7334
|
+
idempotency_key: idempotencyKey
|
|
7335
|
+
}), async (client2, input, signal) => {
|
|
7336
|
+
await client2.getProject(input.project_id);
|
|
7337
|
+
const account = await handoverAccount(client2, signal);
|
|
7338
|
+
return {
|
|
7339
|
+
command: [
|
|
7340
|
+
`${commandPrefix} secret set`,
|
|
7341
|
+
shellQuote(input.name),
|
|
7342
|
+
"--project",
|
|
7343
|
+
shellQuote(input.project_id),
|
|
7344
|
+
"--environment",
|
|
7345
|
+
shellQuote(input.environment_id),
|
|
7346
|
+
"--idempotency-key",
|
|
7347
|
+
shellQuote(input.idempotency_key),
|
|
7348
|
+
...account.flags,
|
|
7349
|
+
"--stdin",
|
|
7350
|
+
"--wait",
|
|
7351
|
+
"--json"
|
|
7352
|
+
].join(" "),
|
|
7353
|
+
acting_as: client2.actingAs?.() ?? null,
|
|
7354
|
+
instruction: `Pass the secret value on stdin in a local terminal; ${account.runs}. Never place the value or a key in MCP arguments, prompts, command-line arguments, source, or logs.`
|
|
7355
|
+
};
|
|
7356
|
+
});
|
|
6279
7357
|
registerProductTool(server, dependencies, "rollback_plan", "Plan a rollback", external_exports.object({ project_id: identifier2, deployment_id: identifier2 }), (client2, input) => client2.planRollback({ projectId: input.project_id, deploymentId: input.deployment_id }));
|
|
6280
7358
|
registerProductTool(server, dependencies, "rollback_execute", "Execute a reviewed rollback", external_exports.object({
|
|
6281
7359
|
project_id: identifier2,
|
|
@@ -6304,11 +7382,20 @@ function createLocalOhmyhostMcpServer(dependencies) {
|
|
|
6304
7382
|
}), destructiveAnnotations());
|
|
6305
7383
|
return server;
|
|
6306
7384
|
}
|
|
6307
|
-
function registerProductTool(server, dependencies, name, description,
|
|
7385
|
+
function registerProductTool(server, dependencies, name, description, schema, execute, annotations = readAnnotations(), selection = (input) => {
|
|
7386
|
+
const organizationId = input["organization_id"];
|
|
7387
|
+
return {
|
|
7388
|
+
...input.profile_name === void 0 ? {} : { name: input.profile_name },
|
|
7389
|
+
...typeof organizationId === "string" ? { organizationId } : {}
|
|
7390
|
+
};
|
|
7391
|
+
}) {
|
|
7392
|
+
const inputSchema = schema.extend({ profile_name: profileName });
|
|
6308
7393
|
const callback = (async (input, context) => {
|
|
6309
7394
|
const parsed = inputSchema.parse(input);
|
|
7395
|
+
let client2;
|
|
6310
7396
|
try {
|
|
6311
|
-
|
|
7397
|
+
client2 = await dependencies.authenticatedClient(context.mcpReq.signal, selection(parsed));
|
|
7398
|
+
const result = toolResult(await execute(client2, parsed, context.mcpReq.signal));
|
|
6312
7399
|
const scope = parsed;
|
|
6313
7400
|
if (typeof scope["project_id"] === "string" && identifier2.safeParse(scope["project_id"]).success)
|
|
6314
7401
|
result.content.push({
|
|
@@ -6320,48 +7407,106 @@ function registerProductTool(server, dependencies, name, description, inputSchem
|
|
|
6320
7407
|
});
|
|
6321
7408
|
return result;
|
|
6322
7409
|
} catch (error) {
|
|
6323
|
-
|
|
6324
|
-
try {
|
|
6325
|
-
safe = error instanceof Error && error.name === "InteractiveSessionRequiredError" ? {
|
|
6326
|
-
code: "interactive_login_required",
|
|
6327
|
-
retryable: false,
|
|
6328
|
-
suggestedAction: `A user API token cannot create, list or select a workspace. Run ${resolveProductCliEnvironment(dependencies.environment).commandPrefix} login --json in a process without OHMYHOST_TOKEN, then retry.`
|
|
6329
|
-
} : error instanceof Error && error.message.startsWith("ORGANIZATION_NOT_FOUND:") ? {
|
|
6330
|
-
code: "organization_not_found",
|
|
6331
|
-
retryable: false,
|
|
6332
|
-
suggestedAction: "Call organization_list and choose one of the returned workspace identifiers. Do not create another workspace to recover."
|
|
6333
|
-
} : error instanceof OperationEventsUnavailableError ? {
|
|
6334
|
-
code: "operation_events_unavailable",
|
|
6335
|
-
retryable: true,
|
|
6336
|
-
suggestedAction: "Read operation_get for current status, then retry operation_logs for this same operation. Do not submit another deployment to recover logs."
|
|
6337
|
-
} : error instanceof Error && error.message.startsWith("EXPORT_PASSWORD_FILE_INVALID:") ? {
|
|
6338
|
-
code: "export_password_file_invalid",
|
|
6339
|
-
retryable: false,
|
|
6340
|
-
suggestedAction: "Choose an existing private UTF-8 password file of 1\u20131024 bytes. The user retains the file and password. Do not paste the password into MCP arguments."
|
|
6341
|
-
} : parseSafeProblem(error);
|
|
6342
|
-
} catch {
|
|
6343
|
-
safe = {
|
|
6344
|
-
code: "client_request_failed",
|
|
6345
|
-
retryable: false,
|
|
6346
|
-
suggestedAction: "Check the connection and run 'ohmyhost login' if authentication expired. Inspect the existing operation before resubmitting any mutation."
|
|
6347
|
-
};
|
|
6348
|
-
}
|
|
6349
|
-
return {
|
|
6350
|
-
...toolResult({
|
|
6351
|
-
error: {
|
|
6352
|
-
code: safe.code,
|
|
6353
|
-
retryable: safe.retryable,
|
|
6354
|
-
suggested_action: safe.suggestedAction,
|
|
6355
|
-
...safe.requestId === void 0 ? {} : { request_id: safe.requestId },
|
|
6356
|
-
...safe.retryAfterSeconds === void 0 ? {} : { retry_after_seconds: safe.retryAfterSeconds }
|
|
6357
|
-
}
|
|
6358
|
-
}),
|
|
6359
|
-
isError: true
|
|
6360
|
-
};
|
|
7410
|
+
return toolError(error, dependencies, client2?.actingAs?.());
|
|
6361
7411
|
}
|
|
6362
7412
|
});
|
|
6363
7413
|
server.registerTool(name, { description, inputSchema, annotations }, callback);
|
|
6364
7414
|
}
|
|
7415
|
+
async function handoverAccount(client2, signal) {
|
|
7416
|
+
const profile = client2.actingAs?.()?.profile ?? null;
|
|
7417
|
+
if (profile !== null) {
|
|
7418
|
+
if (profile.organization_id === null)
|
|
7419
|
+
throw new ProfileSelectionError("profile_context_mismatch", 2, `The saved login ${profile.name} has no organization, so no command can be tied to its account. Nothing was sent.`);
|
|
7420
|
+
return {
|
|
7421
|
+
flags: [
|
|
7422
|
+
"--profile-name",
|
|
7423
|
+
shellQuote(profile.name),
|
|
7424
|
+
"--profile-user",
|
|
7425
|
+
shellQuote(profile.user_id),
|
|
7426
|
+
"--profile-organization",
|
|
7427
|
+
shellQuote(profile.organization_id)
|
|
7428
|
+
],
|
|
7429
|
+
runs: `the command runs only as the saved login it names and only while that login belongs to user ${profile.user_id} in organization ${profile.organization_id}, so a login of the same name that belongs to anyone else, for example on another computer, is refused before anything is read or sent`
|
|
7430
|
+
};
|
|
7431
|
+
}
|
|
7432
|
+
const report = await client2.getCurrentIdentity(signal);
|
|
7433
|
+
const identity = parseCurrentIdentity({
|
|
7434
|
+
actor_id: report.actor_id,
|
|
7435
|
+
organization_ids: report.organization_ids
|
|
7436
|
+
});
|
|
7437
|
+
const userId = identity.actor_id.startsWith("user:") ? identity.actor_id.slice(5) : "";
|
|
7438
|
+
const [organizationId, ...others] = identity.organization_ids;
|
|
7439
|
+
if (!isProfileUserId(userId) || organizationId === void 0 || others.length > 0)
|
|
7440
|
+
throw new ProfileSelectionError("environment_token_context_mismatch", 2, "This server's OHMYHOST_TOKEN does not belong to one user in one organization, so no command can be tied to its account. Nothing was sent.");
|
|
7441
|
+
return {
|
|
7442
|
+
flags: ["--token-user", shellQuote(userId), "--token-organization", shellQuote(organizationId)],
|
|
7443
|
+
runs: `run it only where OHMYHOST_TOKEN holds a key of user ${userId} in organization ${organizationId}, loaded from its private env file; it refuses a saved login and any other account's key before anything is sent`
|
|
7444
|
+
};
|
|
7445
|
+
}
|
|
7446
|
+
function fixedOrganizationAction(error, commandPrefix) {
|
|
7447
|
+
return `This saved login stays in its organization. Add a login for the other workspace with ${commandPrefix} login --organization ${error.organization.id} --user ${error.profile.userId} --json, then pass its profile_name.`;
|
|
7448
|
+
}
|
|
7449
|
+
function toolError(error, dependencies, actingAs) {
|
|
7450
|
+
let safe;
|
|
7451
|
+
try {
|
|
7452
|
+
safe = error instanceof Error && error.name === "ProfileSelectionError" ? {
|
|
7453
|
+
code: error.code,
|
|
7454
|
+
retryable: false,
|
|
7455
|
+
suggestedAction: error.suggestedAction
|
|
7456
|
+
} : error instanceof Error && error.name === "ProfileLimitError" ? {
|
|
7457
|
+
code: "profile_limit_reached",
|
|
7458
|
+
retryable: false,
|
|
7459
|
+
suggestedAction: profileLimitAction(resolveProductCliEnvironment(dependencies.environment).commandPrefix)
|
|
7460
|
+
} : error instanceof Error && error.name === "ProfileOrganizationFixedError" ? {
|
|
7461
|
+
code: "profile_organization_fixed",
|
|
7462
|
+
retryable: false,
|
|
7463
|
+
suggestedAction: fixedOrganizationAction(error, resolveProductCliEnvironment(dependencies.environment).commandPrefix)
|
|
7464
|
+
} : error instanceof Error && error.name === "AccountVerificationError" ? {
|
|
7465
|
+
code: "login_verification_failed",
|
|
7466
|
+
retryable: true,
|
|
7467
|
+
suggestedAction: `The signed-in account could not be verified; nothing was saved. Run ${resolveProductCliEnvironment(dependencies.environment).commandPrefix} login --json again.`
|
|
7468
|
+
} : error instanceof Error && error.name === "CredentialStoreUnavailableError" ? {
|
|
7469
|
+
code: "credential_store_unavailable",
|
|
7470
|
+
retryable: true,
|
|
7471
|
+
suggestedAction: "Unlock or repair this computer's credential store and retry. Saved logins were not changed."
|
|
7472
|
+
} : error instanceof Error && error.name === "InteractiveSessionRequiredError" ? {
|
|
7473
|
+
code: "interactive_login_required",
|
|
7474
|
+
retryable: false,
|
|
7475
|
+
suggestedAction: `A user API token cannot create, list or select a workspace. Run ${resolveProductCliEnvironment(dependencies.environment).commandPrefix} login --json in a process without OHMYHOST_TOKEN, then retry.`
|
|
7476
|
+
} : error instanceof Error && error.message.startsWith("ORGANIZATION_NOT_FOUND:") ? {
|
|
7477
|
+
code: "organization_not_found",
|
|
7478
|
+
retryable: false,
|
|
7479
|
+
suggestedAction: "Call organization_list and choose one of the returned workspace identifiers. Do not create another workspace to recover."
|
|
7480
|
+
} : error instanceof OperationEventsUnavailableError ? {
|
|
7481
|
+
code: "operation_events_unavailable",
|
|
7482
|
+
retryable: true,
|
|
7483
|
+
suggestedAction: "Read operation_get for current status, then retry operation_logs for this same operation. Do not submit another deployment to recover logs."
|
|
7484
|
+
} : error instanceof Error && error.message.startsWith("EXPORT_PASSWORD_FILE_INVALID:") ? {
|
|
7485
|
+
code: "export_password_file_invalid",
|
|
7486
|
+
retryable: false,
|
|
7487
|
+
suggestedAction: "Choose an existing private UTF-8 password file of 1\u20131024 bytes. The user retains the file and password. Do not paste the password into MCP arguments."
|
|
7488
|
+
} : parseSafeProblem(error);
|
|
7489
|
+
} catch {
|
|
7490
|
+
safe = {
|
|
7491
|
+
code: "client_request_failed",
|
|
7492
|
+
retryable: false,
|
|
7493
|
+
suggestedAction: "Check the connection and run 'ohmyhost login' if authentication expired. Inspect the existing operation before resubmitting any mutation."
|
|
7494
|
+
};
|
|
7495
|
+
}
|
|
7496
|
+
return {
|
|
7497
|
+
...toolResult({
|
|
7498
|
+
error: {
|
|
7499
|
+
code: safe.code,
|
|
7500
|
+
retryable: safe.retryable,
|
|
7501
|
+
suggested_action: safe.suggestedAction,
|
|
7502
|
+
...safe.requestId === void 0 ? {} : { request_id: safe.requestId },
|
|
7503
|
+
...safe.retryAfterSeconds === void 0 ? {} : { retry_after_seconds: safe.retryAfterSeconds },
|
|
7504
|
+
...actingAs !== void 0 && ACCOUNT_SENSITIVE_PROBLEMS.has(safe.code) ? { acting_as: actingAs } : {}
|
|
7505
|
+
}
|
|
7506
|
+
}),
|
|
7507
|
+
isError: true
|
|
7508
|
+
};
|
|
7509
|
+
}
|
|
6365
7510
|
function toolResult(result) {
|
|
6366
7511
|
const serialized = JSON.stringify(result);
|
|
6367
7512
|
return {
|
|
@@ -6392,11 +7537,17 @@ function destructiveAnnotations() {
|
|
|
6392
7537
|
// apps/mcp/dist/stdio-main.js
|
|
6393
7538
|
var environment = {
|
|
6394
7539
|
...process.env["OHMYHOST_ENVIRONMENT"] === void 0 ? {} : { OHMYHOST_ENVIRONMENT: process.env["OHMYHOST_ENVIRONMENT"] },
|
|
6395
|
-
...process.env["OHMYHOST_TOKEN"] === void 0 ? {} : { OHMYHOST_TOKEN: process.env["OHMYHOST_TOKEN"] }
|
|
7540
|
+
...process.env["OHMYHOST_TOKEN"] === void 0 ? {} : { OHMYHOST_TOKEN: process.env["OHMYHOST_TOKEN"] },
|
|
7541
|
+
...process.env["OHMYHOST_PROFILE"] === void 0 ? {} : { OHMYHOST_PROFILE: process.env["OHMYHOST_PROFILE"] }
|
|
6396
7542
|
};
|
|
6397
7543
|
resolveProductCliEnvironment(environment);
|
|
6398
7544
|
serveStdio(() => createLocalOhmyhostMcpServer({
|
|
6399
7545
|
environment,
|
|
6400
|
-
|
|
7546
|
+
// Every tool call chooses its own saved login; nothing this process remembers can retarget it.
|
|
7547
|
+
authenticatedClient: (signal, request) => createAuthenticatedLocalMcpClient(signal, {
|
|
7548
|
+
environment,
|
|
7549
|
+
...request === void 0 ? {} : { request }
|
|
7550
|
+
}),
|
|
7551
|
+
listProfiles: (signal) => listSavedProfiles(signal, { environment })
|
|
6401
7552
|
}), { onerror: (error) => process.stderr.write(`${error.message}
|
|
6402
7553
|
`) });
|