@siglume/api-sdk 0.10.8 → 1.1.0

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/dist/index.js CHANGED
@@ -8,6 +8,81 @@ var __export = (target, all) => {
8
8
  __defProp(target, name, { get: all[name], enumerable: true });
9
9
  };
10
10
 
11
+ // src/types.ts
12
+ var PermissionClass, ApprovalMode, ExecutionKind, Environment, PriceModel, AppCategory, StoreVertical, ListingCurrency, MINIMUM_JPY_OPERATION_PRICE_MINOR, PersistenceMode, ToolManualPermissionClass, SettlementMode;
13
+ var init_types = __esm({
14
+ "src/types.ts"() {
15
+ "use strict";
16
+ PermissionClass = {
17
+ READ_ONLY: "read-only",
18
+ ACTION: "action",
19
+ PAYMENT: "payment",
20
+ /** @deprecated Use READ_ONLY. Behaves identically. */
21
+ RECOMMENDATION: "recommendation"
22
+ };
23
+ ApprovalMode = {
24
+ AUTO: "auto",
25
+ BUDGET_BOUNDED: "budget-bounded",
26
+ ALWAYS_ASK: "always-ask",
27
+ DENY: "deny"
28
+ };
29
+ ExecutionKind = {
30
+ DRY_RUN: "dry_run",
31
+ QUOTE: "quote",
32
+ ACTION: "action",
33
+ PAYMENT: "payment"
34
+ };
35
+ Environment = {
36
+ SANDBOX: "sandbox",
37
+ LIVE: "live"
38
+ };
39
+ PriceModel = {
40
+ FREE: "free",
41
+ SUBSCRIPTION: "subscription",
42
+ ONE_TIME: "one_time",
43
+ BUNDLE: "bundle",
44
+ USAGE_BASED: "usage_based",
45
+ PER_ACTION: "per_action"
46
+ };
47
+ AppCategory = {
48
+ COMMERCE: "commerce",
49
+ BOOKING: "booking",
50
+ CRM: "crm",
51
+ FINANCE: "finance",
52
+ DOCUMENT: "document",
53
+ COMMUNICATION: "communication",
54
+ MONITORING: "monitoring",
55
+ OTHER: "other"
56
+ };
57
+ StoreVertical = {
58
+ API: "api",
59
+ GAME: "game"
60
+ };
61
+ ListingCurrency = {
62
+ USD: "USD",
63
+ JPY: "JPY"
64
+ };
65
+ MINIMUM_JPY_OPERATION_PRICE_MINOR = 15;
66
+ PersistenceMode = {
67
+ NONE: "none",
68
+ LOCAL: "local",
69
+ PLATFORM: "platform",
70
+ DEVELOPER_SERVER: "developer_server"
71
+ };
72
+ ToolManualPermissionClass = {
73
+ READ_ONLY: "read_only",
74
+ ACTION: "action",
75
+ PAYMENT: "payment"
76
+ };
77
+ SettlementMode = {
78
+ STRIPE_CHECKOUT: "stripe_checkout",
79
+ STRIPE_PAYMENT_INTENT: "stripe_payment_intent",
80
+ POLYGON_MANDATE: "polygon_mandate",
81
+ EMBEDDED_WALLET_CHARGE: "embedded_wallet_charge"
82
+ };
83
+ }
84
+ });
85
+
11
86
  // src/errors.ts
12
87
  var SiglumeError, SiglumeClientError, SiglumeProjectError, SiglumeValidationError, SiglumeAssistError, SiglumeNotFoundError, SiglumeWebhookError, SiglumeWebhookSignatureError, SiglumeWebhookPayloadError, SiglumeWebhookReplayError, SiglumeAPIError;
13
88
  var init_errors = __esm({
@@ -1587,6 +1662,58 @@ function validateSaveDataSchema(schema, fieldName) {
1587
1662
  }
1588
1663
  }
1589
1664
  }
1665
+ function validatePricingPlanFloor(plan, defaultCurrency) {
1666
+ if (plan === void 0 || plan === null) {
1667
+ return;
1668
+ }
1669
+ if (!isRecord2(plan)) {
1670
+ throw new SiglumeClientError("AppManifest.pricing_plan must be an object when provided.");
1671
+ }
1672
+ const items = plan.items;
1673
+ if (items === void 0 || items === null) {
1674
+ return;
1675
+ }
1676
+ if (!Array.isArray(items)) {
1677
+ throw new SiglumeClientError("AppManifest.pricing_plan.items must be an array when provided.");
1678
+ }
1679
+ const planCurrency = String(plan.currency ?? defaultCurrency ?? "").trim().toUpperCase();
1680
+ const seenKeys = /* @__PURE__ */ new Set();
1681
+ items.forEach((item, index) => {
1682
+ if (!isRecord2(item)) {
1683
+ throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}] must be an object.`);
1684
+ }
1685
+ const itemKey = String(
1686
+ item.key ?? item.operation ?? item.operation_key ?? item.request_type ?? item.receipt_code ?? item.action ?? ""
1687
+ ).trim();
1688
+ if (!itemKey) {
1689
+ throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}].key is required.`);
1690
+ }
1691
+ if (seenKeys.has(itemKey)) {
1692
+ throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}].key duplicates ${itemKey}.`);
1693
+ }
1694
+ seenKeys.add(itemKey);
1695
+ const amountRaw = item.price_minor ?? item.amount_minor ?? item.cost_minor ?? item.value_minor;
1696
+ if (amountRaw === void 0 || amountRaw === null) {
1697
+ throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}].price_minor is required.`);
1698
+ }
1699
+ const amountMinor = typeof amountRaw === "number" ? amountRaw : typeof amountRaw === "string" && amountRaw.trim() ? Number(amountRaw) : NaN;
1700
+ if (!Number.isInteger(amountMinor)) {
1701
+ throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}].price_minor must be an integer.`);
1702
+ }
1703
+ if (amountMinor < 0) {
1704
+ throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}].price_minor must be zero or positive.`);
1705
+ }
1706
+ const currency = String(item.currency ?? planCurrency ?? defaultCurrency ?? "").trim().toUpperCase();
1707
+ if (MINIMUM_JPY_OPERATION_PRICE_CURRENCIES.has(currency) && amountMinor > 0 && amountMinor < MINIMUM_JPY_OPERATION_PRICE_MINOR) {
1708
+ throw new SiglumeClientError(
1709
+ `AppManifest.pricing_plan.items[${index}].price_minor must be 0 or at least ${MINIMUM_JPY_OPERATION_PRICE_MINOR} for JPY/JPYC operation billing.`
1710
+ );
1711
+ }
1712
+ });
1713
+ }
1714
+ function pricingPlanHasItems(plan) {
1715
+ return isRecord2(plan) && Array.isArray(plan.items) && plan.items.length > 0;
1716
+ }
1590
1717
  function buildToolManualQualityReport(payload) {
1591
1718
  const qualityBlock = isRecord2(payload.quality) ? payload.quality : payload;
1592
1719
  const issues = [];
@@ -1662,6 +1789,7 @@ function buildUrl(baseUrl, path, params) {
1662
1789
  }
1663
1790
  function parseListing(data) {
1664
1791
  const metadata = isRecord2(data.metadata) ? data.metadata : {};
1792
+ const pricing_plan = isRecord2(data.pricing_plan) ? data.pricing_plan : isRecord2(metadata.pricing_plan) ? metadata.pricing_plan : null;
1665
1793
  const persistence = isRecord2(data.persistence) ? data.persistence : isRecord2(metadata.persistence) ? metadata.persistence : {};
1666
1794
  return {
1667
1795
  listing_id: String(data.listing_id ?? data.id ?? ""),
@@ -1675,6 +1803,7 @@ function parseListing(data) {
1675
1803
  dry_run_supported: Boolean(data.dry_run_supported ?? false),
1676
1804
  price_model: stringOrNull2(data.price_model),
1677
1805
  price_value_minor: Number(data.price_value_minor ?? 0),
1806
+ pricing_plan,
1678
1807
  currency: String(data.currency ?? "USD"),
1679
1808
  allow_free_trial: Boolean(data.allow_free_trial ?? false),
1680
1809
  free_trial_duration_days: Number(data.free_trial_duration_days ?? 30),
@@ -1749,18 +1878,6 @@ function parseBundleMember(data) {
1749
1878
  link_id: stringOrNull2(data.link_id)
1750
1879
  };
1751
1880
  }
1752
- function parseConnectedAccountLifecycle(data) {
1753
- return {
1754
- connected_account_id: String(data.connected_account_id ?? ""),
1755
- provider_key: String(data.provider_key ?? ""),
1756
- expires_at: stringOrNull2(data.expires_at),
1757
- scopes: Array.isArray(data.scopes) ? data.scopes.filter((s) => typeof s === "string") : [],
1758
- refreshed_at: stringOrNull2(data.refreshed_at),
1759
- connection_status: stringOrNull2(data.connection_status),
1760
- provider_revoked: typeof data.provider_revoked === "boolean" ? data.provider_revoked : null,
1761
- revoked_at: stringOrNull2(data.revoked_at)
1762
- };
1763
- }
1764
1881
  function parseBundle(data) {
1765
1882
  const membersRaw = Array.isArray(data.members) ? data.members : [];
1766
1883
  return {
@@ -1839,21 +1956,6 @@ function parseBinding(data) {
1839
1956
  raw: { ...data }
1840
1957
  };
1841
1958
  }
1842
- function parseConnectedAccount(data) {
1843
- return {
1844
- connected_account_id: String(data.connected_account_id ?? data.id ?? ""),
1845
- provider_key: String(data.provider_key ?? ""),
1846
- account_role: String(data.account_role ?? ""),
1847
- display_name: stringOrNull2(data.display_name),
1848
- environment: stringOrNull2(data.environment),
1849
- connection_status: stringOrNull2(data.connection_status),
1850
- scopes: Array.isArray(data.scopes) ? data.scopes.filter((item) => typeof item === "string") : [],
1851
- metadata: toRecord2(data.metadata),
1852
- created_at: stringOrNull2(data.created_at),
1853
- updated_at: stringOrNull2(data.updated_at),
1854
- raw: { ...data }
1855
- };
1856
- }
1857
1959
  function parseSupportCase(data) {
1858
1960
  return {
1859
1961
  support_case_id: String(data.support_case_id ?? data.id ?? ""),
@@ -2799,10 +2901,11 @@ function cloneJsonLike(value) {
2799
2901
  }
2800
2902
  return value;
2801
2903
  }
2802
- var DEFAULT_SIGLUME_API_BASE, RETRYABLE_STATUS_CODES, CursorPageResult, SiglumeClient;
2904
+ var DEFAULT_SIGLUME_API_BASE, RETRYABLE_STATUS_CODES, MINIMUM_JPY_OPERATION_PRICE_CURRENCIES, CursorPageResult, SiglumeClient;
2803
2905
  var init_client = __esm({
2804
2906
  "src/client.ts"() {
2805
2907
  "use strict";
2908
+ init_types();
2806
2909
  init_errors();
2807
2910
  init_webhooks();
2808
2911
  init_web3();
@@ -2810,6 +2913,7 @@ var init_client = __esm({
2810
2913
  init_utils();
2811
2914
  DEFAULT_SIGLUME_API_BASE = "https://siglume.com/v1";
2812
2915
  RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
2916
+ MINIMUM_JPY_OPERATION_PRICE_CURRENCIES = /* @__PURE__ */ new Set(["JPY", "JPYC"]);
2813
2917
  CursorPageResult = class {
2814
2918
  items;
2815
2919
  next_cursor;
@@ -2892,13 +2996,6 @@ var init_client = __esm({
2892
2996
  if (options.runtime_validation) {
2893
2997
  payload.runtime_validation = coerceMapping(options.runtime_validation, "runtime_validation");
2894
2998
  }
2895
- if (options.oauth_credentials) {
2896
- payload.oauth_credentials = Array.isArray(options.oauth_credentials) ? {
2897
- items: options.oauth_credentials.map(
2898
- (item, index) => coerceMapping(item, `oauth_credentials[${index}]`)
2899
- )
2900
- } : coerceMapping(options.oauth_credentials, "oauth_credentials");
2901
- }
2902
2999
  if (options.source_context) {
2903
3000
  payload.source_context = coerceMapping(options.source_context, "source_context");
2904
3001
  }
@@ -2924,6 +3021,7 @@ var init_client = __esm({
2924
3021
  "jurisdiction",
2925
3022
  "price_model",
2926
3023
  "price_value_minor",
3024
+ "pricing_plan",
2927
3025
  "currency",
2928
3026
  "allow_free_trial",
2929
3027
  "free_trial_duration_days",
@@ -2940,6 +3038,9 @@ var init_client = __esm({
2940
3038
  payload[fieldName] = value;
2941
3039
  }
2942
3040
  }
3041
+ if (payload.pricing_plan !== void 0 && (typeof payload.pricing_plan !== "object" || Array.isArray(payload.pricing_plan))) {
3042
+ throw new SiglumeClientError("AppManifest.pricing_plan must be an object when provided.");
3043
+ }
2943
3044
  if (payload.store_vertical === void 0 || payload.store_vertical === null) {
2944
3045
  throw new SiglumeClientError(
2945
3046
  "AppManifest.store_vertical is required. Choose 'api' for normal API Store listings or 'game' for API games."
@@ -2955,6 +3056,13 @@ var init_client = __esm({
2955
3056
  throw new SiglumeClientError(`AppManifest.currency must be 'USD' or 'JPY'. Got ${String(payload.currency)}.`);
2956
3057
  }
2957
3058
  payload.currency = currency;
3059
+ if (payload.pricing_plan !== void 0) {
3060
+ validatePricingPlanFloor(payload.pricing_plan, currency);
3061
+ }
3062
+ const priceModel = String(payload.price_model ?? "free").trim().toLowerCase();
3063
+ if ((priceModel === "usage_based" || priceModel === "per_action") && !pricingPlanHasItems(payload.pricing_plan)) {
3064
+ throw new SiglumeClientError("AppManifest.pricing_plan.items is required for usage_based/per_action pricing.");
3065
+ }
2958
3066
  if (payload.allow_free_trial === void 0 || payload.allow_free_trial === null) {
2959
3067
  throw new SiglumeClientError(
2960
3068
  "AppManifest.allow_free_trial is required. Pass true to offer a Plus/Pro buyer free trial or false to disable trials."
@@ -3028,7 +3136,6 @@ var init_client = __esm({
3028
3136
  auto_manifest: toRecord2(data.auto_manifest),
3029
3137
  confidence: toRecord2(data.confidence),
3030
3138
  validation_report: toRecord2(data.validation_report),
3031
- oauth_status: toRecord2(data.oauth_status),
3032
3139
  review_url: stringOrNull2(data.review_url),
3033
3140
  trace_id: meta.trace_id,
3034
3141
  request_id: meta.request_id
@@ -3204,66 +3311,9 @@ var init_client = __esm({
3204
3311
  return parseBundle(data);
3205
3312
  }
3206
3313
  // ----- end bundles -------------------------------------------------------
3207
- // ----- Connected accounts (v0.7 track 3) ---------------------------------
3208
- // `resolve()` is intentionally NOT wrapped: runtime-only, never over the wire.
3209
- async start_connected_account_oauth(input) {
3210
- const body = {
3211
- listing_id: input.listing_id,
3212
- redirect_uri: input.redirect_uri
3213
- };
3214
- if (input.scopes !== void 0) body.scopes = input.scopes;
3215
- if (input.account_role !== void 0) body.account_role = input.account_role;
3216
- const [data] = await this.request("POST", "/me/connected-accounts/oauth/authorize", {
3217
- json_body: body
3218
- });
3219
- return {
3220
- authorize_url: String(data.authorize_url ?? ""),
3221
- state: String(data.state ?? ""),
3222
- provider_key: String(data.provider_key ?? ""),
3223
- scopes: Array.isArray(data.scopes) ? data.scopes.filter((s) => typeof s === "string") : [],
3224
- pkce_method: stringOrNull2(data.pkce_method)
3225
- };
3226
- }
3227
- async complete_connected_account_oauth(input) {
3228
- const [data] = await this.request("POST", "/me/connected-accounts/oauth/callback", {
3229
- json_body: { state: input.state, code: input.code }
3230
- });
3231
- return { ...data };
3232
- }
3233
- async refresh_connected_account(account_id) {
3234
- const [data] = await this.request("POST", `/me/connected-accounts/${account_id}/refresh`);
3235
- return parseConnectedAccountLifecycle(data);
3236
- }
3237
- async revoke_connected_account(account_id) {
3238
- const [data] = await this.request("POST", `/me/connected-accounts/${account_id}/revoke`);
3239
- return parseConnectedAccountLifecycle(data);
3240
- }
3241
- async set_listing_oauth_credentials(listing_id, input) {
3242
- const body = {
3243
- provider_key: input.provider_key,
3244
- client_id: input.client_id,
3245
- client_secret: input.client_secret,
3246
- authorize_url: input.authorize_url,
3247
- token_url: input.token_url
3248
- };
3249
- if (input.revoke_url !== void 0) body.revoke_url = input.revoke_url;
3250
- if (input.display_name !== void 0) body.display_name = input.display_name;
3251
- if (input.scope_separator !== void 0) body.scope_separator = input.scope_separator;
3252
- if (input.token_endpoint_auth !== void 0) body.token_endpoint_auth = input.token_endpoint_auth;
3253
- if (input.pkce_required !== void 0) body.pkce_required = input.pkce_required;
3254
- if (input.refresh_supported !== void 0) body.refresh_supported = input.refresh_supported;
3255
- if (input.available_scopes !== void 0) body.available_scopes = input.available_scopes;
3256
- if (input.required_scopes !== void 0) body.required_scopes = input.required_scopes;
3257
- const [data] = await this.request("PUT", `/market/capabilities/${listing_id}/oauth-credentials`, {
3258
- json_body: body
3259
- });
3260
- return { ...data };
3261
- }
3262
- async get_listing_oauth_credentials_status(listing_id) {
3263
- const [data] = await this.request("GET", `/market/capabilities/${listing_id}/oauth-credentials`);
3264
- return { ...data };
3265
- }
3266
- // ----- end connected accounts --------------------------------------------
3314
+ // ----- Connected accounts ------------------------------------------------
3315
+ // Architecture B: publisher APIs own external OAuth and token storage.
3316
+ // The SDK no longer exposes platform OAuth or listing credential APIs.
3267
3317
  async get_developer_portal() {
3268
3318
  const [data, meta] = await this.request("GET", "/market/developer/portal");
3269
3319
  return {
@@ -3296,7 +3346,6 @@ var init_client = __esm({
3296
3346
  dry_run_supported: Boolean(data.dry_run_supported ?? false),
3297
3347
  approval_mode: stringOrNull2(data.approval_mode),
3298
3348
  required_connected_accounts: Array.isArray(data.required_connected_accounts) ? data.required_connected_accounts : [],
3299
- connected_accounts: Array.isArray(data.connected_accounts) ? data.connected_accounts.filter((item) => isRecord2(item)).map((item) => ({ ...item })) : [],
3300
3349
  stub_providers_enabled: Boolean(data.stub_providers_enabled ?? false),
3301
3350
  simulated_receipts: Boolean(data.simulated_receipts ?? false),
3302
3351
  approval_simulator: Boolean(data.approval_simulator ?? false),
@@ -4594,25 +4643,6 @@ var init_client = __esm({
4594
4643
  raw: { ...data }
4595
4644
  };
4596
4645
  }
4597
- async list_connected_accounts(options = {}) {
4598
- const params = {
4599
- provider_key: options.provider_key,
4600
- environment: options.environment,
4601
- limit: Math.max(1, Math.min(Math.trunc(options.limit ?? 50), 100)),
4602
- cursor: options.cursor
4603
- };
4604
- const [data, meta] = await this.request("GET", "/market/connected-accounts", { params });
4605
- const items = Array.isArray(data.items) ? data.items.filter((item) => isRecord2(item)).map(parseConnectedAccount) : [];
4606
- const next_cursor = stringOrNull2(data.next_cursor);
4607
- return new CursorPageResult({
4608
- items,
4609
- next_cursor,
4610
- limit: typeof data.limit === "number" ? data.limit : params.limit,
4611
- offset: typeof data.offset === "number" ? data.offset : null,
4612
- meta,
4613
- fetchNext: next_cursor ? (cursor) => this.list_connected_accounts({ ...options, cursor }) : void 0
4614
- });
4615
- }
4616
4646
  async create_support_case(subject, body, options = {}) {
4617
4647
  const summary = subject.trim();
4618
4648
  const details = body.trim();
@@ -6575,73 +6605,8 @@ function toRecord3(value) {
6575
6605
  init_metering();
6576
6606
  init_operations();
6577
6607
 
6578
- // src/types.ts
6579
- var PermissionClass = {
6580
- READ_ONLY: "read-only",
6581
- ACTION: "action",
6582
- PAYMENT: "payment",
6583
- /** @deprecated Use READ_ONLY. Behaves identically. */
6584
- RECOMMENDATION: "recommendation"
6585
- };
6586
- var ApprovalMode = {
6587
- AUTO: "auto",
6588
- BUDGET_BOUNDED: "budget-bounded",
6589
- ALWAYS_ASK: "always-ask",
6590
- DENY: "deny"
6591
- };
6592
- var ExecutionKind = {
6593
- DRY_RUN: "dry_run",
6594
- QUOTE: "quote",
6595
- ACTION: "action",
6596
- PAYMENT: "payment"
6597
- };
6598
- var Environment = {
6599
- SANDBOX: "sandbox",
6600
- LIVE: "live"
6601
- };
6602
- var PriceModel = {
6603
- FREE: "free",
6604
- SUBSCRIPTION: "subscription",
6605
- ONE_TIME: "one_time",
6606
- BUNDLE: "bundle",
6607
- USAGE_BASED: "usage_based",
6608
- PER_ACTION: "per_action"
6609
- };
6610
- var AppCategory = {
6611
- COMMERCE: "commerce",
6612
- BOOKING: "booking",
6613
- CRM: "crm",
6614
- FINANCE: "finance",
6615
- DOCUMENT: "document",
6616
- COMMUNICATION: "communication",
6617
- MONITORING: "monitoring",
6618
- OTHER: "other"
6619
- };
6620
- var StoreVertical = {
6621
- API: "api",
6622
- GAME: "game"
6623
- };
6624
- var ListingCurrency = {
6625
- USD: "USD",
6626
- JPY: "JPY"
6627
- };
6628
- var PersistenceMode = {
6629
- NONE: "none",
6630
- LOCAL: "local",
6631
- PLATFORM: "platform",
6632
- DEVELOPER_SERVER: "developer_server"
6633
- };
6634
- var ToolManualPermissionClass = {
6635
- READ_ONLY: "read_only",
6636
- ACTION: "action",
6637
- PAYMENT: "payment"
6638
- };
6639
- var SettlementMode = {
6640
- STRIPE_CHECKOUT: "stripe_checkout",
6641
- STRIPE_PAYMENT_INTENT: "stripe_payment_intent",
6642
- POLYGON_MANDATE: "polygon_mandate",
6643
- EMBEDDED_WALLET_CHARGE: "embedded_wallet_charge"
6644
- };
6608
+ // src/runtime.ts
6609
+ init_types();
6645
6610
 
6646
6611
  // src/testing/recorder.ts
6647
6612
  var CASSETTE_VERSION = 1;
@@ -7039,6 +7004,7 @@ Actual: ${requestSignature(requestRecord, ignoreBodyFields)}`
7039
7004
  };
7040
7005
 
7041
7006
  // src/tool-manual-validator.ts
7007
+ init_types();
7042
7008
  init_utils();
7043
7009
  var JURISDICTION_PATTERN = /^[A-Z]{2}(-[A-Z0-9]{1,3})?$/;
7044
7010
  var TOOL_NAME_RE = /^[A-Za-z0-9_]{3,64}$/;
@@ -7313,6 +7279,64 @@ function validate_tool_manual(manualInput) {
7313
7279
  // src/runtime.ts
7314
7280
  init_web3();
7315
7281
  var CAPABILITY_KEY_RE = /^[a-z0-9][a-z0-9-]*[a-z0-9]$/;
7282
+ var MINIMUM_JPY_OPERATION_PRICE_CURRENCIES2 = /* @__PURE__ */ new Set(["JPY", "JPYC"]);
7283
+ function pricingPlanFloorIssues(plan, defaultCurrency) {
7284
+ const issues = [];
7285
+ if (plan === void 0 || plan === null) {
7286
+ return issues;
7287
+ }
7288
+ if (typeof plan !== "object" || Array.isArray(plan)) {
7289
+ return ["pricing_plan must be an object when provided"];
7290
+ }
7291
+ const record = plan;
7292
+ const items = record.items;
7293
+ if (items === void 0 || items === null) {
7294
+ return issues;
7295
+ }
7296
+ if (!Array.isArray(items)) {
7297
+ return ["pricing_plan.items must be an array when provided"];
7298
+ }
7299
+ const planCurrency = String(record.currency ?? defaultCurrency ?? "").trim().toUpperCase();
7300
+ const seenKeys = /* @__PURE__ */ new Set();
7301
+ items.forEach((item, index) => {
7302
+ if (typeof item !== "object" || item === null || Array.isArray(item)) {
7303
+ issues.push(`pricing_plan.items[${index}] must be an object`);
7304
+ return;
7305
+ }
7306
+ const itemRecord = item;
7307
+ const itemKey = String(
7308
+ itemRecord.key ?? itemRecord.operation ?? itemRecord.operation_key ?? itemRecord.request_type ?? itemRecord.receipt_code ?? itemRecord.action ?? ""
7309
+ ).trim();
7310
+ if (!itemKey) {
7311
+ issues.push(`pricing_plan.items[${index}].key is required`);
7312
+ } else if (seenKeys.has(itemKey)) {
7313
+ issues.push(`pricing_plan.items[${index}].key duplicates ${itemKey}`);
7314
+ } else {
7315
+ seenKeys.add(itemKey);
7316
+ }
7317
+ const amountRaw = itemRecord.price_minor ?? itemRecord.amount_minor ?? itemRecord.cost_minor ?? itemRecord.value_minor;
7318
+ if (amountRaw === void 0 || amountRaw === null) {
7319
+ issues.push(`pricing_plan.items[${index}].price_minor is required`);
7320
+ return;
7321
+ }
7322
+ const amountMinor = typeof amountRaw === "number" ? amountRaw : typeof amountRaw === "string" && amountRaw.trim() ? Number(amountRaw) : NaN;
7323
+ if (!Number.isInteger(amountMinor)) {
7324
+ issues.push(`pricing_plan.items[${index}].price_minor must be an integer`);
7325
+ return;
7326
+ }
7327
+ if (amountMinor < 0) {
7328
+ issues.push(`pricing_plan.items[${index}].price_minor must be zero or positive`);
7329
+ return;
7330
+ }
7331
+ const currency = String(itemRecord.currency ?? planCurrency ?? defaultCurrency ?? "").trim().toUpperCase();
7332
+ if (MINIMUM_JPY_OPERATION_PRICE_CURRENCIES2.has(currency) && amountMinor > 0 && amountMinor < MINIMUM_JPY_OPERATION_PRICE_MINOR) {
7333
+ issues.push(
7334
+ `pricing_plan.items[${index}].price_minor must be 0 or at least ${MINIMUM_JPY_OPERATION_PRICE_MINOR} for JPY/JPYC operation billing`
7335
+ );
7336
+ }
7337
+ });
7338
+ return issues;
7339
+ }
7316
7340
  function normalizeExecutionResult(result, executionKind) {
7317
7341
  return {
7318
7342
  success: Boolean(result.success),
@@ -7367,24 +7391,12 @@ var AppTestHarness = class {
7367
7391
  this.stubs = stubs;
7368
7392
  }
7369
7393
  async executeWithKind(execution_kind, task_type = "default", options = {}) {
7370
- const connected_accounts = options.connected_accounts ?? Object.fromEntries(
7371
- Object.keys(this.stubs).map((key) => [
7372
- key,
7373
- {
7374
- provider_key: key,
7375
- session_token: `stub-token-${key}`,
7376
- environment: Environment.SANDBOX,
7377
- scopes: []
7378
- }
7379
- ])
7380
- );
7381
7394
  const ctx = {
7382
7395
  agent_id: "test-agent-001",
7383
7396
  owner_user_id: "test-owner-001",
7384
7397
  task_type,
7385
7398
  environment: Environment.SANDBOX,
7386
7399
  execution_kind,
7387
- connected_accounts,
7388
7400
  input_params: options.input_params ?? {},
7389
7401
  trace_id: options.trace_id,
7390
7402
  idempotency_key: options.idempotency_key,
@@ -7426,6 +7438,10 @@ var AppTestHarness = class {
7426
7438
  if (!manifest.example_prompts || manifest.example_prompts.length === 0) {
7427
7439
  issues.push("at least one example_prompt is recommended");
7428
7440
  }
7441
+ issues.push(...pricingPlanFloorIssues(manifest.pricing_plan, String(manifest.currency ?? "USD")));
7442
+ if ((manifest.price_model === PriceModel.USAGE_BASED || manifest.price_model === PriceModel.PER_ACTION) && (!manifest.pricing_plan || !Array.isArray(manifest.pricing_plan.items) || manifest.pricing_plan.items.length === 0)) {
7443
+ issues.push("pricing_plan.items is required for usage_based/per_action pricing");
7444
+ }
7429
7445
  if (manifest.permission_class === PermissionClass.ACTION || manifest.permission_class === PermissionClass.PAYMENT) {
7430
7446
  if (!manifest.dry_run_supported) {
7431
7447
  issues.push("action/payment apps should support dry_run");
@@ -7474,12 +7490,6 @@ var AppTestHarness = class {
7474
7490
  }
7475
7491
  return issues;
7476
7492
  }
7477
- async simulate_connected_account_missing(task_type = "default", options = {}) {
7478
- return this.executeWithKind("dry_run", task_type, {
7479
- ...options,
7480
- connected_accounts: {}
7481
- });
7482
- }
7483
7493
  async simulate_metering(record, options = {}) {
7484
7494
  const { normalizeUsageRecord: normalizeUsageRecord2 } = await Promise.resolve().then(() => (init_metering(), metering_exports));
7485
7495
  const manifest = await this.app.manifest();
@@ -7507,7 +7517,7 @@ var AppTestHarness = class {
7507
7517
  };
7508
7518
  }
7509
7519
  return {
7510
- experimental: manifest.price_model === PriceModel.USAGE_BASED || manifest.price_model === PriceModel.PER_ACTION,
7520
+ experimental: false,
7511
7521
  usage_record,
7512
7522
  invoice_line_preview
7513
7523
  };
@@ -8933,6 +8943,7 @@ function readEnv(name) {
8933
8943
  }
8934
8944
 
8935
8945
  // src/index.ts
8946
+ init_types();
8936
8947
  init_web3();
8937
8948
  init_webhooks();
8938
8949
  init_utils();
@@ -8952,6 +8963,7 @@ export {
8952
8963
  InMemoryWebhookDedupe,
8953
8964
  LLMProvider,
8954
8965
  ListingCurrency,
8966
+ MINIMUM_JPY_OPERATION_PRICE_MINOR,
8955
8967
  MeterClient,
8956
8968
  OpenAIProvider,
8957
8969
  PermissionClass,