@amerged/ohmyhost-mcp 0.1.40 → 0.1.41
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-OW4IDEWK.js → chunk-6HQPHICK.js} +5 -5
- package/dist/index.js +1 -1
- package/dist/licenses/pgcf-bridge-NOTICE +1 -1
- package/dist/stdio-main.js +46 -52
- package/package.json +1 -1
- package/src/apps/mcp/package.json +1 -1
- package/src/apps/mcp/src/local-client.ts +2 -8
- package/src/apps/mcp/src/local-server.ts +12 -23
- package/src/apps/product-cli/package.json +1 -1
- package/src/apps/product-cli/src/cli.ts +2 -2
- package/src/apps/product-cli/src/command.ts +2 -16
- package/src/apps/product-cli/src/product-api.ts +3 -13
- package/src/apps/product-cli/src/runtime-contract.ts +1 -10
- package/src/packages/agent-skills/src/generated-skill-resources.ts +4 -4
- package/src/packages/contracts/src/credit-pricing.ts +78 -50
- package/src/packages/contracts/src/feedback.ts +0 -5
- package/src/packages/postgres-bridge/NOTICE +1 -1
- package/src/packages/sdk-ts/package.json +1 -1
- package/src/packages/sdk-ts/src/generated/sdk.gen.ts +6 -10
- package/src/packages/sdk-ts/src/generated/types.gen.ts +52 -24
package/dist/stdio-main.js
CHANGED
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
serverIdentityOf,
|
|
31
31
|
setNegotiatedProtocolVersion,
|
|
32
32
|
validateEnvelopeMeta
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-6HQPHICK.js";
|
|
34
34
|
|
|
35
35
|
// node_modules/.pnpm/ignore@7.0.12/node_modules/ignore/index.js
|
|
36
36
|
var require_ignore = __commonJS({
|
|
@@ -25417,31 +25417,41 @@ function assertOrganizationCreditUsage(value) {
|
|
|
25417
25417
|
};
|
|
25418
25418
|
const identifier3 = (input) => typeof input === "string" && /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u.test(input);
|
|
25419
25419
|
const amount = (input) => typeof input === "string" && /^(0|[1-9][0-9]{0,37})$/u.test(input);
|
|
25420
|
-
const
|
|
25421
|
-
|
|
25420
|
+
const instant2 = (input) => typeof input === "string" && Number.isFinite(Date.parse(input)) && new Date(input).toISOString() === input;
|
|
25421
|
+
const report = record7(value, "organization_id,as_of,unit,period,from,projects,days");
|
|
25422
|
+
if (!identifier3(report["organization_id"]) || !instant2(report["as_of"]) || !instant2(report["from"]) || report["unit"] !== "microcredits" || typeof report["period"] !== "string" || !/^20[0-9]{2}-(0[1-9]|1[0-2])$/u.test(report["period"]) || !Array.isArray(report["projects"]) || report["projects"].length > 1e3 || !Array.isArray(report["days"]) || report["days"].length > 15)
|
|
25422
25423
|
throw new TypeError("Invalid usage report");
|
|
25423
25424
|
let previous = "";
|
|
25424
|
-
for (const input of report["
|
|
25425
|
-
const project = record7(input, "project_id,
|
|
25426
|
-
if (!identifier3(project["project_id"]) || String(project["project_id"]) <= previous || !amount(project["
|
|
25425
|
+
for (const input of report["projects"]) {
|
|
25426
|
+
const project = record7(input, "project_id,used_micros");
|
|
25427
|
+
if (!identifier3(project["project_id"]) || String(project["project_id"]) <= previous || !amount(project["used_micros"]))
|
|
25427
25428
|
throw new TypeError("Invalid usage project");
|
|
25428
25429
|
previous = String(project["project_id"]);
|
|
25429
|
-
|
|
25430
|
-
|
|
25431
|
-
|
|
25432
|
-
|
|
25433
|
-
|
|
25434
|
-
|
|
25435
|
-
|
|
25436
|
-
|
|
25437
|
-
|
|
25430
|
+
}
|
|
25431
|
+
let previousDay = "";
|
|
25432
|
+
for (const input of report["days"]) {
|
|
25433
|
+
const day = record7(input, "day,projects");
|
|
25434
|
+
if (typeof day["day"] !== "string" || !/^20[0-9]{2}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/u.test(day["day"]) || day["day"] <= previousDay || !Array.isArray(day["projects"]) || day["projects"].length > 1e3)
|
|
25435
|
+
throw new TypeError("Invalid usage day");
|
|
25436
|
+
previousDay = day["day"];
|
|
25437
|
+
previous = "";
|
|
25438
|
+
for (const projectInput of day["projects"]) {
|
|
25439
|
+
const project = record7(projectInput, "project_id,meters");
|
|
25440
|
+
if (!identifier3(project["project_id"]) || String(project["project_id"]) <= previous || !Array.isArray(project["meters"]) || project["meters"].length > 1e3)
|
|
25441
|
+
throw new TypeError("Invalid usage project");
|
|
25442
|
+
previous = String(project["project_id"]);
|
|
25443
|
+
for (const meterInput of project["meters"]) {
|
|
25444
|
+
const meter = record7(meterInput, "environment_id,meter,unit,rate_card_id,quantity,charged_micros");
|
|
25445
|
+
if (meter["environment_id"] !== null && !identifier3(meter["environment_id"]))
|
|
25446
|
+
throw new TypeError("Invalid usage environment");
|
|
25447
|
+
for (const key of ["meter", "unit", "rate_card_id"])
|
|
25448
|
+
if (typeof meter[key] !== "string" || !/^[A-Za-z0-9_.:/-]{1,128}$/u.test(meter[key]))
|
|
25449
|
+
throw new TypeError("Invalid usage meter");
|
|
25450
|
+
if (typeof meter["quantity"] !== "string" || !/^(0|[1-9][0-9]{0,29})(\.[0-9]{1,12})?$/u.test(meter["quantity"]) || !amount(meter["charged_micros"]))
|
|
25438
25451
|
throw new TypeError("Invalid usage amount");
|
|
25439
|
-
|
|
25440
|
-
throw new TypeError("Inconsistent usage charge");
|
|
25452
|
+
}
|
|
25441
25453
|
}
|
|
25442
25454
|
}
|
|
25443
|
-
if (report["next_cursor"] !== null && report["next_cursor"] !== previous)
|
|
25444
|
-
throw new TypeError("Invalid usage cursor");
|
|
25445
25455
|
}
|
|
25446
25456
|
function assertOrganizationAccount(value) {
|
|
25447
25457
|
if (!value || typeof value !== "object" || Array.isArray(value) || Object.keys(value).sort().join(",") !== "as_of,available_micros,monthly_micros,name,next_expiry,one_time_micros,organization_id,paid_until,plan,plan_source,reserved_micros,workos_organization_id")
|
|
@@ -25452,7 +25462,9 @@ function assertOrganizationAccount(value) {
|
|
|
25452
25462
|
for (const field of ["available_micros", "monthly_micros", "one_time_micros", "reserved_micros"])
|
|
25453
25463
|
if (typeof v[field] !== "string" || !/^(0|[1-9][0-9]{0,18})$/u.test(v[field]))
|
|
25454
25464
|
throw new TypeError("Invalid account credits");
|
|
25455
|
-
|
|
25465
|
+
const held = BigInt(String(v["reserved_micros"]));
|
|
25466
|
+
const balance = BigInt(String(v["monthly_micros"])) + BigInt(String(v["one_time_micros"]));
|
|
25467
|
+
if (BigInt(String(v["available_micros"])) !== (balance > held ? balance - held : 0n))
|
|
25456
25468
|
throw new TypeError("Account credit buckets do not balance");
|
|
25457
25469
|
for (const field of ["as_of", "paid_until", "next_expiry"]) {
|
|
25458
25470
|
if (field !== "as_of" && v[field] === null)
|
|
@@ -27050,7 +27062,7 @@ function exact3(v, keys) {
|
|
|
27050
27062
|
// apps/product-cli/package.json
|
|
27051
27063
|
var package_default2 = {
|
|
27052
27064
|
name: "@ohmyhost/product-cli",
|
|
27053
|
-
version: "0.1.
|
|
27065
|
+
version: "0.1.41",
|
|
27054
27066
|
private: true,
|
|
27055
27067
|
ohmyhost: {
|
|
27056
27068
|
deployment: "production",
|
|
@@ -28128,7 +28140,7 @@ var HELP_USAGE = Object.freeze({
|
|
|
28128
28140
|
"billing checkout": "ohmyhost billing checkout --organization ULID --offer topup|paid [--packs 1] --idempotency-key KEY --json (returns a human payment URL; never auto-pays)",
|
|
28129
28141
|
"billing status": "ohmyhost billing status --organization ULID --checkout ULID --json",
|
|
28130
28142
|
"billing portal": "ohmyhost billing portal --organization ULID --json (short-lived human URL; request fresh after expiry)",
|
|
28131
|
-
"credits usage": "ohmyhost credits usage --organization ULID --
|
|
28143
|
+
"credits usage": "ohmyhost credits usage --organization ULID --json (billed usage of the last up to 14 UTC days by day, project and meter, and each project's use this UTC month)",
|
|
28132
28144
|
"budget get": "ohmyhost budget get --project ULID --json",
|
|
28133
28145
|
"budget set": "ohmyhost budget set --project ULID --credits NUMBER|none [--mode continue|stop] --idempotency-key KEY --json",
|
|
28134
28146
|
"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)",
|
|
@@ -29791,9 +29803,7 @@ var getOrganizationCreditUsage = (parameters, options) => {
|
|
|
29791
29803
|
{
|
|
29792
29804
|
args: [
|
|
29793
29805
|
{ in: "headers", key: "X-Request-Id" },
|
|
29794
|
-
{ in: "path", key: "organization_id" }
|
|
29795
|
-
{ in: "query", key: "month" },
|
|
29796
|
-
{ in: "query", key: "cursor" }
|
|
29806
|
+
{ in: "path", key: "organization_id" }
|
|
29797
29807
|
]
|
|
29798
29808
|
}
|
|
29799
29809
|
]);
|
|
@@ -32175,12 +32185,8 @@ var GeneratedSdkProductApi = class {
|
|
|
32175
32185
|
createBillingPortal(organizationId) {
|
|
32176
32186
|
return createBillingPortal({ organization_id: organizationId, body: {} }, { client: this.#client });
|
|
32177
32187
|
}
|
|
32178
|
-
getOrganizationCreditUsage(
|
|
32179
|
-
return getOrganizationCreditUsage({
|
|
32180
|
-
organization_id: input.organizationId,
|
|
32181
|
-
month: input.month,
|
|
32182
|
-
...input.cursor ? { cursor: input.cursor } : {}
|
|
32183
|
-
}, { client: this.#client });
|
|
32188
|
+
getOrganizationCreditUsage(organizationId) {
|
|
32189
|
+
return getOrganizationCreditUsage({ organization_id: organizationId }, { client: this.#client });
|
|
32184
32190
|
}
|
|
32185
32191
|
getProjectCreditBudget(projectId) {
|
|
32186
32192
|
return getProjectCreditBudget({ project_id: projectId }, { client: this.#client });
|
|
@@ -33209,12 +33215,8 @@ var GeneratedSdkLocalMcpClient = class {
|
|
|
33209
33215
|
assertBillingPortal(value);
|
|
33210
33216
|
return value;
|
|
33211
33217
|
}
|
|
33212
|
-
async getOrganizationCreditUsage(
|
|
33213
|
-
const value = await getOrganizationCreditUsage({
|
|
33214
|
-
organization_id: input.organizationId,
|
|
33215
|
-
month: input.month,
|
|
33216
|
-
...input.cursor ? { cursor: input.cursor } : {}
|
|
33217
|
-
}, { client: this.#client });
|
|
33218
|
+
async getOrganizationCreditUsage(organizationId) {
|
|
33219
|
+
const value = await getOrganizationCreditUsage({ organization_id: organizationId }, { client: this.#client });
|
|
33218
33220
|
assertOrganizationCreditUsage(value);
|
|
33219
33221
|
return value;
|
|
33220
33222
|
}
|
|
@@ -33804,7 +33806,7 @@ function createLocalOhmyhostMcpServer(dependencies) {
|
|
|
33804
33806
|
hostname: input.hostname,
|
|
33805
33807
|
idempotencyKey: input.idempotency_key
|
|
33806
33808
|
}), destructiveAnnotations());
|
|
33807
|
-
registerProductTool(server, dependencies, "billing_checkout_create", "Owner-only: create or resume a hosted Checkout. Paid is USD 10/month; each top-up pack is USD 10 before tax; a purchase grants 100 credits per dollar up to USD 100 and 125 credits per dollar for the part above, so 10 packs grant 10000 and 20 packs grant 22500 top-up credits. Monthly Paid credits expire at billing-period end; top-ups
|
|
33809
|
+
registerProductTool(server, dependencies, "billing_checkout_create", "Owner-only: create or resume a hosted Checkout. Paid is USD 10/month; each top-up pack is USD 10 before tax; a purchase grants 100 credits per dollar up to USD 100 and 125 credits per dollar for the part above, so 10 packs grant 10000 and 20 packs grant 22500 top-up credits. Monthly Paid credits expire at billing-period end; top-ups never expire, also after a downgrade to Free. Return the URL to the human to review/pay; never auto-pay or treat browser return as confirmation. Preserve the same offer/packs/idempotency key after uncertainty. An existing active, overdue, unpaid or paused subscription must be managed through billing_portal_create, not replaced with another Paid purchase. Then read checkout status and organization credits. Works at zero credit. Top-ups and enabling auto-recharge require active Paid access.", external_exports.object({
|
|
33808
33810
|
organization_id: identifier2,
|
|
33809
33811
|
offer: external_exports.enum(["topup", "paid"]),
|
|
33810
33812
|
packs: external_exports.number().int().min(1).max(100).default(1),
|
|
@@ -33815,12 +33817,12 @@ function createLocalOhmyhostMcpServer(dependencies) {
|
|
|
33815
33817
|
packs: input.packs,
|
|
33816
33818
|
idempotencyKey: input.idempotency_key
|
|
33817
33819
|
}), mutationAnnotations());
|
|
33818
|
-
registerProductTool(server, dependencies, "billing_checkout_get", "Owner-only: observe the original checkout and reconcile confirmed credits/refunds, without another purchase. payment_confirmed is historical; read organization_credits_get for spendable funds and organization_account_get's effective plan for Paid coverage; paid_until
|
|
33820
|
+
registerProductTool(server, dependencies, "billing_checkout_get", "Owner-only: observe the original checkout and reconcile confirmed credits/refunds, without another purchase. payment_confirmed is historical; read organization_credits_get for spendable funds and organization_account_get's effective plan for Paid coverage; paid_until is the end of paid coverage: the paid Stripe period end plus its 14-day renewal grace. Follow required_action: complete_checkout means give its URL to the human; open_billing_portal means call billing_portal_create and give that fresh URL to the human to resolve payment. contact_support means contact https://ohmyho.st/contact about the original invoice; none means no human payment step now, not proof of current Paid coverage. Never start a second subscription to repair a failed renewal. Follow billing_issue when tax needs attention: use billing_portal_create for open_billing_portal, or https://ohmyho.st/contact for contact_support; retain the original invoice and never disable tax. Retry the same checkout after an outage. state=expired ends this attempt; use a new key only for an explicitly requested new purchase, never automatically after an error or timeout.", external_exports.object({ organization_id: identifier2, checkout_id: identifier2 }), (client2, input) => client2.getBillingCheckout({
|
|
33819
33821
|
organizationId: input.organization_id,
|
|
33820
33822
|
checkoutId: input.checkout_id
|
|
33821
33823
|
}));
|
|
33822
33824
|
registerProductTool(server, dependencies, "billing_recharge_get", "Owner-only: read auto-recharge consent, spending limit and payment handoff. Reading never initiates a charge. Return private setup_url/invoice_url only to the human; never log them. Read again after Stripe card setup or payment. billing_issue identifies the original invoice: open_billing_portal means collect corrected billing details through billing_portal_create; contact_support means use https://ohmyho.st/contact. Never disable tax, discard the invoice or start another purchase to repair it.", external_exports.object({ organization_id: identifier2 }), (client2, input) => client2.getBillingRecharge(input.organization_id));
|
|
33823
|
-
registerProductTool(server, dependencies, "billing_recharge_configure", "Owner-only: enable or disable automatic off-session payments. Enabling requires active Paid access. NEVER enable without explicit human approval for USD 9 plus tax per 1000 top-up credits, which
|
|
33825
|
+
registerProductTool(server, dependencies, "billing_recharge_configure", "Owner-only: enable or disable automatic off-session payments. Enabling requires active Paid access. NEVER enable without explicit human approval for USD 9 plus tax per 1000 top-up credits, which never expire, refill below 100 credits, and the chosen gross USD monthly limit. Set consent off_session_v1 only after that approval; null when disabling. Read current revision first. Preserve the original idempotency key and payload after uncertainty. A saved Stripe card may require setup_url. Disabling prevents new payment initiation; in-progress payments may finish. This does not create a subscription or Paid access.", external_exports.object({
|
|
33824
33826
|
organization_id: identifier2,
|
|
33825
33827
|
enabled: external_exports.boolean(),
|
|
33826
33828
|
monthly_limit_minor: external_exports.number().int().min(1e3).max(1e5),
|
|
@@ -33846,19 +33848,11 @@ function createLocalOhmyhostMcpServer(dependencies) {
|
|
|
33846
33848
|
idempotencyKey: input.idempotency_key
|
|
33847
33849
|
}), mutationAnnotations());
|
|
33848
33850
|
registerProductTool(server, dependencies, "project_export_get", "Owner-only: read the original SQL ZIP export's progress/error and verified download URL. Follow next_poll_after_seconds while queued/running; never create another export to poll. The signed URL lasts 24 hours and is only issued with sufficient remaining seven-day archive retention. Keep the URL out of source, logs and persisted project notes. The password cannot be retrieved. Available at zero credits.", external_exports.object({ project_id: identifier2, export_id: identifier2 }), (client2, input) => client2.getProjectExport({ projectId: input.project_id, exportId: input.export_id }));
|
|
33849
|
-
registerProductTool(server, dependencies, "organization_usage_get", "Read
|
|
33850
|
-
|
|
33851
|
-
month: external_exports.string().regex(/^20[0-9]{2}-(0[1-9]|1[0-2])$/u),
|
|
33852
|
-
cursor: identifier2.optional()
|
|
33853
|
-
}), (client2, input) => client2.getOrganizationCreditUsage({
|
|
33854
|
-
organizationId: input.organization_id,
|
|
33855
|
-
month: input.month,
|
|
33856
|
-
...input.cursor ? { cursor: input.cursor } : {}
|
|
33857
|
-
}));
|
|
33858
|
-
registerProductTool(server, dependencies, "organization_account_get", "Owner-only: read the effective Free/Paid plan, its Stripe or granted source, available monthly credits that expire at period end and top-up credits that carry over while Paid but expire on downgrade to Free, reservations and next expiry. Granted Paid features do not imply a Stripe subscription or extra monthly Paid allowance. paid_until is the paid Stripe period end or grant end; null on Free or for an unbounded grant. An unpaid renewal may retain Paid features for up to 14 days after that Stripe period end, without new monthly credits. This read grants no access or credits.", external_exports.object({ organization_id: identifier2 }), (client2, input) => client2.getOrganizationAccount(input.organization_id));
|
|
33851
|
+
registerProductTool(server, dependencies, "organization_usage_get", "Read the billed usage of the last up to 14 UTC days (today included) grouped by day, project and meter, and what each project has used so far this UTC month. One credit is 1000000 microcredits. Null environment means shared project cost. Charges can arrive late and unmetered usage is not zero consumption. Owner-only; works at zero credit without new charges.", external_exports.object({ organization_id: identifier2 }), (client2, input) => client2.getOrganizationCreditUsage(input.organization_id));
|
|
33852
|
+
registerProductTool(server, dependencies, "organization_account_get", "Owner-only: read the effective Free/Paid plan, its Stripe or granted source, the monthly credits that expire at next_expiry, the top-up and bonus credits that never expire, the reservations that hold part of them, and available_micros (monthly plus one-time minus reservations). Granted Paid features do not imply a Stripe subscription or extra monthly Paid allowance. paid_until is the end of the paid coverage, which includes the 14-day renewal grace of a Stripe subscription; null on Free. This read grants no access or credits.", external_exports.object({ organization_id: identifier2 }), (client2, input) => client2.getOrganizationAccount(input.organization_id));
|
|
33859
33853
|
registerProductTool(server, dependencies, "referral_link_get", "Read the workspace's referral link to share. A new user whose first workspace comes from it starts with 30 days of Paid and 1,000 credits; that workspace's first payment gives this workspace 1,000 credits, plus 30 days of Paid unless a Stripe subscription or an unbounded grant already covers it. Any member may read it.", external_exports.object({ organization_id: identifier2 }), (client2, input) => client2.getOrganizationReferral(input.organization_id));
|
|
33860
|
-
registerProductTool(server, dependencies, "organization_credits_get", "Read the owner's shared organization credit pool, seven-day grace_started_at/grace_expires_at and published rate_cards. Existing services/domains are not immediately shut down at zero credit; an explicit project stop budget is separate. One credit is 1000000 microcredits. Each rate states credit_micros for units_per_charge; publication alone does not enable billing. active_meters identifies billed sources; provider outages
|
|
33861
|
-
registerProductTool(server, dependencies, "project_budget_get", "Read the owner's project UTC-month budget,
|
|
33854
|
+
registerProductTool(server, dependencies, "organization_credits_get", "Read the owner's shared organization credit pool (available_micros is monthly plus one-time credit minus reservations), the seven-day grace_started_at/grace_expires_at that begins when the credit is used up, and published rate_cards. Existing services/domains are not immediately shut down at zero credit; an explicit project stop budget is separate. One credit is 1000000 microcredits. Each rate states credit_micros for units_per_charge; publication alone does not enable billing. active_meters identifies billed sources; provider outages are not customer debt. Works at zero credit. Top-ups and enabling auto-recharge require active Paid access.", external_exports.object({ organization_id: identifier2 }), (client2, input) => client2.getOrganizationCredits(input.organization_id));
|
|
33855
|
+
registerProductTool(server, dependencies, "project_budget_get", "Read the owner's project UTC-month budget, this month's use and open reservations. A budget never allocates a second wallet.", external_exports.object({ project_id: identifier2 }), (client2, input) => client2.getProjectCreditBudget(input.project_id));
|
|
33862
33856
|
registerProductTool(server, dependencies, "project_budget_set", "Set an owner's optional monthly project budget in microcredits (1000000 = one credit). continue is the default and uses the org pool after the threshold; stop blocks new billable work. null clears the budget and requires continue. Changing it never resets usage or adds credits. Replay the same key after uncertainty; read the budget again for current usage.", external_exports.object({
|
|
33863
33857
|
project_id: identifier2,
|
|
33864
33858
|
amount_micros: external_exports.string().regex(/^(0|[1-9][0-9]{0,18})$/u).nullable(),
|
package/package.json
CHANGED
|
@@ -536,15 +536,9 @@ export class GeneratedSdkLocalMcpClient implements LocalMcpProductClient {
|
|
|
536
536
|
assertBillingPortal(value);
|
|
537
537
|
return value;
|
|
538
538
|
}
|
|
539
|
-
public async getOrganizationCreditUsage(
|
|
540
|
-
input: Parameters<LocalMcpProductClient["getOrganizationCreditUsage"]>[0],
|
|
541
|
-
) {
|
|
539
|
+
public async getOrganizationCreditUsage(organizationId: string) {
|
|
542
540
|
const value = await getOrganizationCreditUsage(
|
|
543
|
-
{
|
|
544
|
-
organization_id: input.organizationId,
|
|
545
|
-
month: input.month,
|
|
546
|
-
...(input.cursor ? { cursor: input.cursor } : {}),
|
|
547
|
-
},
|
|
541
|
+
{ organization_id: organizationId },
|
|
548
542
|
{ client: this.#client },
|
|
549
543
|
);
|
|
550
544
|
assertOrganizationCreditUsage(value);
|
|
@@ -189,11 +189,9 @@ export interface LocalMcpProductClient {
|
|
|
189
189
|
idempotencyKey: string;
|
|
190
190
|
}): Promise<import("@ohmyhost/sdk-ts").BillingRecharge>;
|
|
191
191
|
createBillingPortal(organizationId: string): Promise<import("@ohmyhost/sdk-ts").BillingPortal>;
|
|
192
|
-
getOrganizationCreditUsage(
|
|
193
|
-
organizationId: string
|
|
194
|
-
|
|
195
|
-
cursor?: string;
|
|
196
|
-
}): Promise<import("@ohmyhost/sdk-ts").OrganizationCreditUsage>;
|
|
192
|
+
getOrganizationCreditUsage(
|
|
193
|
+
organizationId: string,
|
|
194
|
+
): Promise<import("@ohmyhost/sdk-ts").OrganizationCreditUsage>;
|
|
197
195
|
getOrganizationAccount(
|
|
198
196
|
organizationId: string,
|
|
199
197
|
): Promise<import("@ohmyhost/sdk-ts").OrganizationAccount>;
|
|
@@ -702,7 +700,7 @@ export function createLocalOhmyhostMcpServer(dependencies: LocalOhmyhostMcpDepen
|
|
|
702
700
|
server,
|
|
703
701
|
dependencies,
|
|
704
702
|
"billing_checkout_create",
|
|
705
|
-
"Owner-only: create or resume a hosted Checkout. Paid is USD 10/month; each top-up pack is USD 10 before tax; a purchase grants 100 credits per dollar up to USD 100 and 125 credits per dollar for the part above, so 10 packs grant 10000 and 20 packs grant 22500 top-up credits. Monthly Paid credits expire at billing-period end; top-ups
|
|
703
|
+
"Owner-only: create or resume a hosted Checkout. Paid is USD 10/month; each top-up pack is USD 10 before tax; a purchase grants 100 credits per dollar up to USD 100 and 125 credits per dollar for the part above, so 10 packs grant 10000 and 20 packs grant 22500 top-up credits. Monthly Paid credits expire at billing-period end; top-ups never expire, also after a downgrade to Free. Return the URL to the human to review/pay; never auto-pay or treat browser return as confirmation. Preserve the same offer/packs/idempotency key after uncertainty. An existing active, overdue, unpaid or paused subscription must be managed through billing_portal_create, not replaced with another Paid purchase. Then read checkout status and organization credits. Works at zero credit. Top-ups and enabling auto-recharge require active Paid access.",
|
|
706
704
|
z.object({
|
|
707
705
|
organization_id: identifier,
|
|
708
706
|
offer: z.enum(["topup", "paid"]),
|
|
@@ -722,7 +720,7 @@ export function createLocalOhmyhostMcpServer(dependencies: LocalOhmyhostMcpDepen
|
|
|
722
720
|
server,
|
|
723
721
|
dependencies,
|
|
724
722
|
"billing_checkout_get",
|
|
725
|
-
"Owner-only: observe the original checkout and reconcile confirmed credits/refunds, without another purchase. payment_confirmed is historical; read organization_credits_get for spendable funds and organization_account_get's effective plan for Paid coverage; paid_until
|
|
723
|
+
"Owner-only: observe the original checkout and reconcile confirmed credits/refunds, without another purchase. payment_confirmed is historical; read organization_credits_get for spendable funds and organization_account_get's effective plan for Paid coverage; paid_until is the end of paid coverage: the paid Stripe period end plus its 14-day renewal grace. Follow required_action: complete_checkout means give its URL to the human; open_billing_portal means call billing_portal_create and give that fresh URL to the human to resolve payment. contact_support means contact https://ohmyho.st/contact about the original invoice; none means no human payment step now, not proof of current Paid coverage. Never start a second subscription to repair a failed renewal. Follow billing_issue when tax needs attention: use billing_portal_create for open_billing_portal, or https://ohmyho.st/contact for contact_support; retain the original invoice and never disable tax. Retry the same checkout after an outage. state=expired ends this attempt; use a new key only for an explicitly requested new purchase, never automatically after an error or timeout.",
|
|
726
724
|
z.object({ organization_id: identifier, checkout_id: identifier }),
|
|
727
725
|
(client, input) =>
|
|
728
726
|
client.getBillingCheckout({
|
|
@@ -742,7 +740,7 @@ export function createLocalOhmyhostMcpServer(dependencies: LocalOhmyhostMcpDepen
|
|
|
742
740
|
server,
|
|
743
741
|
dependencies,
|
|
744
742
|
"billing_recharge_configure",
|
|
745
|
-
"Owner-only: enable or disable automatic off-session payments. Enabling requires active Paid access. NEVER enable without explicit human approval for USD 9 plus tax per 1000 top-up credits, which
|
|
743
|
+
"Owner-only: enable or disable automatic off-session payments. Enabling requires active Paid access. NEVER enable without explicit human approval for USD 9 plus tax per 1000 top-up credits, which never expire, refill below 100 credits, and the chosen gross USD monthly limit. Set consent off_session_v1 only after that approval; null when disabling. Read current revision first. Preserve the original idempotency key and payload after uncertainty. A saved Stripe card may require setup_url. Disabling prevents new payment initiation; in-progress payments may finish. This does not create a subscription or Paid access.",
|
|
746
744
|
z.object({
|
|
747
745
|
organization_id: identifier,
|
|
748
746
|
enabled: z.boolean(),
|
|
@@ -804,24 +802,15 @@ export function createLocalOhmyhostMcpServer(dependencies: LocalOhmyhostMcpDepen
|
|
|
804
802
|
server,
|
|
805
803
|
dependencies,
|
|
806
804
|
"organization_usage_get",
|
|
807
|
-
"Read
|
|
808
|
-
z.object({
|
|
809
|
-
|
|
810
|
-
month: z.string().regex(/^20[0-9]{2}-(0[1-9]|1[0-2])$/u),
|
|
811
|
-
cursor: identifier.optional(),
|
|
812
|
-
}),
|
|
813
|
-
(client, input) =>
|
|
814
|
-
client.getOrganizationCreditUsage({
|
|
815
|
-
organizationId: input.organization_id,
|
|
816
|
-
month: input.month,
|
|
817
|
-
...(input.cursor ? { cursor: input.cursor } : {}),
|
|
818
|
-
}),
|
|
805
|
+
"Read the billed usage of the last up to 14 UTC days (today included) grouped by day, project and meter, and what each project has used so far this UTC month. One credit is 1000000 microcredits. Null environment means shared project cost. Charges can arrive late and unmetered usage is not zero consumption. Owner-only; works at zero credit without new charges.",
|
|
806
|
+
z.object({ organization_id: identifier }),
|
|
807
|
+
(client, input) => client.getOrganizationCreditUsage(input.organization_id),
|
|
819
808
|
);
|
|
820
809
|
registerProductTool(
|
|
821
810
|
server,
|
|
822
811
|
dependencies,
|
|
823
812
|
"organization_account_get",
|
|
824
|
-
"Owner-only: read the effective Free/Paid plan, its Stripe or granted source,
|
|
813
|
+
"Owner-only: read the effective Free/Paid plan, its Stripe or granted source, the monthly credits that expire at next_expiry, the top-up and bonus credits that never expire, the reservations that hold part of them, and available_micros (monthly plus one-time minus reservations). Granted Paid features do not imply a Stripe subscription or extra monthly Paid allowance. paid_until is the end of the paid coverage, which includes the 14-day renewal grace of a Stripe subscription; null on Free. This read grants no access or credits.",
|
|
825
814
|
z.object({ organization_id: identifier }),
|
|
826
815
|
(client, input) => client.getOrganizationAccount(input.organization_id),
|
|
827
816
|
);
|
|
@@ -837,7 +826,7 @@ export function createLocalOhmyhostMcpServer(dependencies: LocalOhmyhostMcpDepen
|
|
|
837
826
|
server,
|
|
838
827
|
dependencies,
|
|
839
828
|
"organization_credits_get",
|
|
840
|
-
"Read the owner's shared organization credit pool, seven-day grace_started_at/grace_expires_at and published rate_cards. Existing services/domains are not immediately shut down at zero credit; an explicit project stop budget is separate. One credit is 1000000 microcredits. Each rate states credit_micros for units_per_charge; publication alone does not enable billing. active_meters identifies billed sources; provider outages
|
|
829
|
+
"Read the owner's shared organization credit pool (available_micros is monthly plus one-time credit minus reservations), the seven-day grace_started_at/grace_expires_at that begins when the credit is used up, and published rate_cards. Existing services/domains are not immediately shut down at zero credit; an explicit project stop budget is separate. One credit is 1000000 microcredits. Each rate states credit_micros for units_per_charge; publication alone does not enable billing. active_meters identifies billed sources; provider outages are not customer debt. Works at zero credit. Top-ups and enabling auto-recharge require active Paid access.",
|
|
841
830
|
z.object({ organization_id: identifier }),
|
|
842
831
|
(client, input) => client.getOrganizationCredits(input.organization_id),
|
|
843
832
|
);
|
|
@@ -845,7 +834,7 @@ export function createLocalOhmyhostMcpServer(dependencies: LocalOhmyhostMcpDepen
|
|
|
845
834
|
server,
|
|
846
835
|
dependencies,
|
|
847
836
|
"project_budget_get",
|
|
848
|
-
"Read the owner's project UTC-month budget,
|
|
837
|
+
"Read the owner's project UTC-month budget, this month's use and open reservations. A budget never allocates a second wallet.",
|
|
849
838
|
z.object({ project_id: identifier }),
|
|
850
839
|
(client, input) => client.getProjectCreditBudget(input.project_id),
|
|
851
840
|
);
|
|
@@ -351,7 +351,7 @@ const HELP_USAGE = Object.freeze({
|
|
|
351
351
|
"billing portal":
|
|
352
352
|
"ohmyhost billing portal --organization ULID --json (short-lived human URL; request fresh after expiry)",
|
|
353
353
|
"credits usage":
|
|
354
|
-
"ohmyhost credits usage --organization ULID --
|
|
354
|
+
"ohmyhost credits usage --organization ULID --json (billed usage of the last up to 14 UTC days by day, project and meter, and each project's use this UTC month)",
|
|
355
355
|
"budget get": "ohmyhost budget get --project ULID --json",
|
|
356
356
|
"budget set":
|
|
357
357
|
"ohmyhost budget set --project ULID --credits NUMBER|none [--mode continue|stop] --idempotency-key KEY --json",
|
|
@@ -844,7 +844,7 @@ export class ProductCli {
|
|
|
844
844
|
}
|
|
845
845
|
if (command.kind === "credits-usage") {
|
|
846
846
|
const api = await this.authenticatedApi(command.credentialStore, signal);
|
|
847
|
-
const usage = await api.getOrganizationCreditUsage(command);
|
|
847
|
+
const usage = await api.getOrganizationCreditUsage(command.organizationId);
|
|
848
848
|
try {
|
|
849
849
|
assertOrganizationCreditUsage(usage);
|
|
850
850
|
} catch {
|
|
@@ -199,8 +199,6 @@ export type ProductCliCommand =
|
|
|
199
199
|
| {
|
|
200
200
|
readonly kind: "credits-usage";
|
|
201
201
|
readonly organizationId: string;
|
|
202
|
-
readonly month: string;
|
|
203
|
-
readonly cursor?: string;
|
|
204
202
|
readonly credentialStore: "native";
|
|
205
203
|
}
|
|
206
204
|
| {
|
|
@@ -1407,20 +1405,8 @@ export const parseProductCliCommand = (argv: readonly string[]): ProductCliComma
|
|
|
1407
1405
|
if (first === "credits" && values[0] === "usage") {
|
|
1408
1406
|
values.shift();
|
|
1409
1407
|
if (yes || wait || follow || stdin) throw new InvalidCommandError();
|
|
1410
|
-
const options =
|
|
1411
|
-
|
|
1412
|
-
!options["--organization"] ||
|
|
1413
|
-
!options["--month"] ||
|
|
1414
|
-
!/^20[0-9]{2}-(0[1-9]|1[0-2])$/u.test(options["--month"])
|
|
1415
|
-
)
|
|
1416
|
-
throw new InvalidCommandError();
|
|
1417
|
-
return {
|
|
1418
|
-
kind: "credits-usage",
|
|
1419
|
-
organizationId: options["--organization"],
|
|
1420
|
-
month: options["--month"],
|
|
1421
|
-
...(options["--cursor"] ? { cursor: options["--cursor"] } : {}),
|
|
1422
|
-
credentialStore,
|
|
1423
|
-
};
|
|
1408
|
+
const options = parseOptions(values, ["--organization"]);
|
|
1409
|
+
return { kind: "credits-usage", organizationId: options["--organization"], credentialStore };
|
|
1424
1410
|
}
|
|
1425
1411
|
if (first === "credits" && values[0] === "account") {
|
|
1426
1412
|
values.shift();
|
|
@@ -230,11 +230,7 @@ export interface ProductApi {
|
|
|
230
230
|
organizationId: string,
|
|
231
231
|
): Promise<import("@ohmyhost/sdk-ts").OrganizationReferral>;
|
|
232
232
|
getOrganizationCredits(organizationId: string): Promise<OrganizationCredits>;
|
|
233
|
-
getOrganizationCreditUsage(
|
|
234
|
-
organizationId: string;
|
|
235
|
-
month: string;
|
|
236
|
-
cursor?: string;
|
|
237
|
-
}): Promise<OrganizationCreditUsage>;
|
|
233
|
+
getOrganizationCreditUsage(organizationId: string): Promise<OrganizationCreditUsage>;
|
|
238
234
|
getProjectCreditBudget(projectId: string): Promise<ProjectCreditBudget>;
|
|
239
235
|
setProjectCreditBudget(input: {
|
|
240
236
|
projectId: string;
|
|
@@ -614,15 +610,9 @@ export class GeneratedSdkProductApi implements ProductApi {
|
|
|
614
610
|
{ client: this.#client },
|
|
615
611
|
);
|
|
616
612
|
}
|
|
617
|
-
public getOrganizationCreditUsage(
|
|
618
|
-
input: Parameters<ProductApi["getOrganizationCreditUsage"]>[0],
|
|
619
|
-
) {
|
|
613
|
+
public getOrganizationCreditUsage(organizationId: string) {
|
|
620
614
|
return getOrganizationCreditUsage(
|
|
621
|
-
{
|
|
622
|
-
organization_id: input.organizationId,
|
|
623
|
-
month: input.month,
|
|
624
|
-
...(input.cursor ? { cursor: input.cursor } : {}),
|
|
625
|
-
},
|
|
615
|
+
{ organization_id: organizationId },
|
|
626
616
|
{ client: this.#client },
|
|
627
617
|
);
|
|
628
618
|
}
|
|
@@ -552,9 +552,6 @@ export function parseOrganizationCredits(value: unknown): OrganizationCredits {
|
|
|
552
552
|
"as_of",
|
|
553
553
|
"available_micros",
|
|
554
554
|
"reserved_micros",
|
|
555
|
-
"spent_micros",
|
|
556
|
-
"expired_micros",
|
|
557
|
-
"platform_overrun_micros",
|
|
558
555
|
"grace_started_at",
|
|
559
556
|
"grace_expires_at",
|
|
560
557
|
"active_meters",
|
|
@@ -586,13 +583,7 @@ export function parseOrganizationCredits(value: unknown): OrganizationCredits {
|
|
|
586
583
|
)
|
|
587
584
|
)
|
|
588
585
|
throw new ResponseContractError();
|
|
589
|
-
for (const field of [
|
|
590
|
-
"available_micros",
|
|
591
|
-
"reserved_micros",
|
|
592
|
-
"spent_micros",
|
|
593
|
-
"expired_micros",
|
|
594
|
-
"platform_overrun_micros",
|
|
595
|
-
]) {
|
|
586
|
+
for (const field of ["available_micros", "reserved_micros"]) {
|
|
596
587
|
const amount = input[field];
|
|
597
588
|
if (
|
|
598
589
|
typeof amount !== "string" ||
|