@siglume/api-sdk 1.0.0 → 1.2.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.cjs CHANGED
@@ -30,6 +30,81 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  ));
31
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
32
 
33
+ // src/types.ts
34
+ var PermissionClass, ApprovalMode, ExecutionKind, Environment, PriceModel, AppCategory, StoreVertical, ListingCurrency, MINIMUM_JPY_OPERATION_PRICE_MINOR, PersistenceMode, ToolManualPermissionClass, SettlementMode;
35
+ var init_types = __esm({
36
+ "src/types.ts"() {
37
+ "use strict";
38
+ PermissionClass = {
39
+ READ_ONLY: "read-only",
40
+ ACTION: "action",
41
+ PAYMENT: "payment",
42
+ /** @deprecated Use READ_ONLY. Behaves identically. */
43
+ RECOMMENDATION: "recommendation"
44
+ };
45
+ ApprovalMode = {
46
+ AUTO: "auto",
47
+ BUDGET_BOUNDED: "budget-bounded",
48
+ ALWAYS_ASK: "always-ask",
49
+ DENY: "deny"
50
+ };
51
+ ExecutionKind = {
52
+ DRY_RUN: "dry_run",
53
+ QUOTE: "quote",
54
+ ACTION: "action",
55
+ PAYMENT: "payment"
56
+ };
57
+ Environment = {
58
+ SANDBOX: "sandbox",
59
+ LIVE: "live"
60
+ };
61
+ PriceModel = {
62
+ FREE: "free",
63
+ SUBSCRIPTION: "subscription",
64
+ ONE_TIME: "one_time",
65
+ BUNDLE: "bundle",
66
+ USAGE_BASED: "usage_based",
67
+ PER_ACTION: "per_action"
68
+ };
69
+ AppCategory = {
70
+ COMMERCE: "commerce",
71
+ BOOKING: "booking",
72
+ CRM: "crm",
73
+ FINANCE: "finance",
74
+ DOCUMENT: "document",
75
+ COMMUNICATION: "communication",
76
+ MONITORING: "monitoring",
77
+ OTHER: "other"
78
+ };
79
+ StoreVertical = {
80
+ API: "api",
81
+ GAME: "game"
82
+ };
83
+ ListingCurrency = {
84
+ USD: "USD",
85
+ JPY: "JPY"
86
+ };
87
+ MINIMUM_JPY_OPERATION_PRICE_MINOR = 15;
88
+ PersistenceMode = {
89
+ NONE: "none",
90
+ LOCAL: "local",
91
+ PLATFORM: "platform",
92
+ DEVELOPER_SERVER: "developer_server"
93
+ };
94
+ ToolManualPermissionClass = {
95
+ READ_ONLY: "read_only",
96
+ ACTION: "action",
97
+ PAYMENT: "payment"
98
+ };
99
+ SettlementMode = {
100
+ STRIPE_CHECKOUT: "stripe_checkout",
101
+ STRIPE_PAYMENT_INTENT: "stripe_payment_intent",
102
+ POLYGON_MANDATE: "polygon_mandate",
103
+ EMBEDDED_WALLET_CHARGE: "embedded_wallet_charge"
104
+ };
105
+ }
106
+ });
107
+
33
108
  // src/errors.ts
34
109
  var SiglumeError, SiglumeClientError, SiglumeProjectError, SiglumeValidationError, SiglumeAssistError, SiglumeNotFoundError, SiglumeWebhookError, SiglumeWebhookSignatureError, SiglumeWebhookPayloadError, SiglumeWebhookReplayError, SiglumeAPIError;
35
110
  var init_errors = __esm({
@@ -1609,6 +1684,58 @@ function validateSaveDataSchema(schema, fieldName) {
1609
1684
  }
1610
1685
  }
1611
1686
  }
1687
+ function validatePricingPlanFloor(plan, defaultCurrency) {
1688
+ if (plan === void 0 || plan === null) {
1689
+ return;
1690
+ }
1691
+ if (!isRecord2(plan)) {
1692
+ throw new SiglumeClientError("AppManifest.pricing_plan must be an object when provided.");
1693
+ }
1694
+ const items = plan.items;
1695
+ if (items === void 0 || items === null) {
1696
+ return;
1697
+ }
1698
+ if (!Array.isArray(items)) {
1699
+ throw new SiglumeClientError("AppManifest.pricing_plan.items must be an array when provided.");
1700
+ }
1701
+ const planCurrency = String(plan.currency ?? defaultCurrency ?? "").trim().toUpperCase();
1702
+ const seenKeys = /* @__PURE__ */ new Set();
1703
+ items.forEach((item, index) => {
1704
+ if (!isRecord2(item)) {
1705
+ throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}] must be an object.`);
1706
+ }
1707
+ const itemKey = String(
1708
+ item.key ?? item.operation ?? item.operation_key ?? item.request_type ?? item.receipt_code ?? item.action ?? ""
1709
+ ).trim();
1710
+ if (!itemKey) {
1711
+ throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}].key is required.`);
1712
+ }
1713
+ if (seenKeys.has(itemKey)) {
1714
+ throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}].key duplicates ${itemKey}.`);
1715
+ }
1716
+ seenKeys.add(itemKey);
1717
+ const amountRaw = item.price_minor ?? item.amount_minor ?? item.cost_minor ?? item.value_minor;
1718
+ if (amountRaw === void 0 || amountRaw === null) {
1719
+ throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}].price_minor is required.`);
1720
+ }
1721
+ const amountMinor = typeof amountRaw === "number" ? amountRaw : typeof amountRaw === "string" && amountRaw.trim() ? Number(amountRaw) : NaN;
1722
+ if (!Number.isInteger(amountMinor)) {
1723
+ throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}].price_minor must be an integer.`);
1724
+ }
1725
+ if (amountMinor < 0) {
1726
+ throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}].price_minor must be zero or positive.`);
1727
+ }
1728
+ const currency = String(item.currency ?? planCurrency ?? defaultCurrency ?? "").trim().toUpperCase();
1729
+ if (MINIMUM_JPY_OPERATION_PRICE_CURRENCIES.has(currency) && amountMinor > 0 && amountMinor < MINIMUM_JPY_OPERATION_PRICE_MINOR) {
1730
+ throw new SiglumeClientError(
1731
+ `AppManifest.pricing_plan.items[${index}].price_minor must be 0 or at least ${MINIMUM_JPY_OPERATION_PRICE_MINOR} for JPY/JPYC operation billing.`
1732
+ );
1733
+ }
1734
+ });
1735
+ }
1736
+ function pricingPlanHasItems(plan) {
1737
+ return isRecord2(plan) && Array.isArray(plan.items) && plan.items.length > 0;
1738
+ }
1612
1739
  function buildToolManualQualityReport(payload) {
1613
1740
  const qualityBlock = isRecord2(payload.quality) ? payload.quality : payload;
1614
1741
  const issues = [];
@@ -1684,6 +1811,7 @@ function buildUrl(baseUrl, path, params) {
1684
1811
  }
1685
1812
  function parseListing(data) {
1686
1813
  const metadata = isRecord2(data.metadata) ? data.metadata : {};
1814
+ const pricing_plan = isRecord2(data.pricing_plan) ? data.pricing_plan : isRecord2(metadata.pricing_plan) ? metadata.pricing_plan : null;
1687
1815
  const persistence = isRecord2(data.persistence) ? data.persistence : isRecord2(metadata.persistence) ? metadata.persistence : {};
1688
1816
  return {
1689
1817
  listing_id: String(data.listing_id ?? data.id ?? ""),
@@ -1697,6 +1825,8 @@ function parseListing(data) {
1697
1825
  dry_run_supported: Boolean(data.dry_run_supported ?? false),
1698
1826
  price_model: stringOrNull2(data.price_model),
1699
1827
  price_value_minor: Number(data.price_value_minor ?? 0),
1828
+ pricing_plan,
1829
+ billing_timing: String(data.billing_timing ?? metadata.billing_timing ?? "post"),
1700
1830
  currency: String(data.currency ?? "USD"),
1701
1831
  allow_free_trial: Boolean(data.allow_free_trial ?? false),
1702
1832
  free_trial_duration_days: Number(data.free_trial_duration_days ?? 30),
@@ -2794,10 +2924,11 @@ function cloneJsonLike(value) {
2794
2924
  }
2795
2925
  return value;
2796
2926
  }
2797
- var DEFAULT_SIGLUME_API_BASE, RETRYABLE_STATUS_CODES, CursorPageResult, SiglumeClient;
2927
+ var DEFAULT_SIGLUME_API_BASE, RETRYABLE_STATUS_CODES, MINIMUM_JPY_OPERATION_PRICE_CURRENCIES, CursorPageResult, SiglumeClient;
2798
2928
  var init_client = __esm({
2799
2929
  "src/client.ts"() {
2800
2930
  "use strict";
2931
+ init_types();
2801
2932
  init_errors();
2802
2933
  init_webhooks();
2803
2934
  init_web3();
@@ -2805,6 +2936,7 @@ var init_client = __esm({
2805
2936
  init_utils();
2806
2937
  DEFAULT_SIGLUME_API_BASE = "https://siglume.com/v1";
2807
2938
  RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
2939
+ MINIMUM_JPY_OPERATION_PRICE_CURRENCIES = /* @__PURE__ */ new Set(["JPY", "JPYC"]);
2808
2940
  CursorPageResult = class {
2809
2941
  items;
2810
2942
  next_cursor;
@@ -2912,6 +3044,8 @@ var init_client = __esm({
2912
3044
  "jurisdiction",
2913
3045
  "price_model",
2914
3046
  "price_value_minor",
3047
+ "pricing_plan",
3048
+ "billing_timing",
2915
3049
  "currency",
2916
3050
  "allow_free_trial",
2917
3051
  "free_trial_duration_days",
@@ -2928,6 +3062,16 @@ var init_client = __esm({
2928
3062
  payload[fieldName] = value;
2929
3063
  }
2930
3064
  }
3065
+ if (payload.pricing_plan !== void 0 && (typeof payload.pricing_plan !== "object" || Array.isArray(payload.pricing_plan))) {
3066
+ throw new SiglumeClientError("AppManifest.pricing_plan must be an object when provided.");
3067
+ }
3068
+ if (payload.billing_timing !== void 0 && payload.billing_timing !== null) {
3069
+ const billingTiming = String(payload.billing_timing || "post").trim().toLowerCase();
3070
+ if (billingTiming !== "post" && billingTiming !== "prepay") {
3071
+ throw new SiglumeClientError("AppManifest.billing_timing must be 'post' or 'prepay'.");
3072
+ }
3073
+ payload.billing_timing = billingTiming;
3074
+ }
2931
3075
  if (payload.store_vertical === void 0 || payload.store_vertical === null) {
2932
3076
  throw new SiglumeClientError(
2933
3077
  "AppManifest.store_vertical is required. Choose 'api' for normal API Store listings or 'game' for API games."
@@ -2943,6 +3087,13 @@ var init_client = __esm({
2943
3087
  throw new SiglumeClientError(`AppManifest.currency must be 'USD' or 'JPY'. Got ${String(payload.currency)}.`);
2944
3088
  }
2945
3089
  payload.currency = currency;
3090
+ if (payload.pricing_plan !== void 0) {
3091
+ validatePricingPlanFloor(payload.pricing_plan, currency);
3092
+ }
3093
+ const priceModel = String(payload.price_model ?? "free").trim().toLowerCase();
3094
+ if ((priceModel === "usage_based" || priceModel === "per_action") && !pricingPlanHasItems(payload.pricing_plan)) {
3095
+ throw new SiglumeClientError("AppManifest.pricing_plan.items is required for usage_based/per_action pricing.");
3096
+ }
2946
3097
  if (payload.allow_free_trial === void 0 || payload.allow_free_trial === null) {
2947
3098
  throw new SiglumeClientError(
2948
3099
  "AppManifest.allow_free_trial is required. Pass true to offer a Plus/Pro buyer free trial or false to disable trials."
@@ -5205,6 +5356,7 @@ __export(src_exports, {
5205
5356
  InMemoryWebhookDedupe: () => InMemoryWebhookDedupe,
5206
5357
  LLMProvider: () => LLMProvider,
5207
5358
  ListingCurrency: () => ListingCurrency,
5359
+ MINIMUM_JPY_OPERATION_PRICE_MINOR: () => MINIMUM_JPY_OPERATION_PRICE_MINOR,
5208
5360
  MeterClient: () => MeterClient,
5209
5361
  OpenAIProvider: () => OpenAIProvider,
5210
5362
  PermissionClass: () => PermissionClass,
@@ -6569,73 +6721,8 @@ function toRecord3(value) {
6569
6721
  init_metering();
6570
6722
  init_operations();
6571
6723
 
6572
- // src/types.ts
6573
- var PermissionClass = {
6574
- READ_ONLY: "read-only",
6575
- ACTION: "action",
6576
- PAYMENT: "payment",
6577
- /** @deprecated Use READ_ONLY. Behaves identically. */
6578
- RECOMMENDATION: "recommendation"
6579
- };
6580
- var ApprovalMode = {
6581
- AUTO: "auto",
6582
- BUDGET_BOUNDED: "budget-bounded",
6583
- ALWAYS_ASK: "always-ask",
6584
- DENY: "deny"
6585
- };
6586
- var ExecutionKind = {
6587
- DRY_RUN: "dry_run",
6588
- QUOTE: "quote",
6589
- ACTION: "action",
6590
- PAYMENT: "payment"
6591
- };
6592
- var Environment = {
6593
- SANDBOX: "sandbox",
6594
- LIVE: "live"
6595
- };
6596
- var PriceModel = {
6597
- FREE: "free",
6598
- SUBSCRIPTION: "subscription",
6599
- ONE_TIME: "one_time",
6600
- BUNDLE: "bundle",
6601
- USAGE_BASED: "usage_based",
6602
- PER_ACTION: "per_action"
6603
- };
6604
- var AppCategory = {
6605
- COMMERCE: "commerce",
6606
- BOOKING: "booking",
6607
- CRM: "crm",
6608
- FINANCE: "finance",
6609
- DOCUMENT: "document",
6610
- COMMUNICATION: "communication",
6611
- MONITORING: "monitoring",
6612
- OTHER: "other"
6613
- };
6614
- var StoreVertical = {
6615
- API: "api",
6616
- GAME: "game"
6617
- };
6618
- var ListingCurrency = {
6619
- USD: "USD",
6620
- JPY: "JPY"
6621
- };
6622
- var PersistenceMode = {
6623
- NONE: "none",
6624
- LOCAL: "local",
6625
- PLATFORM: "platform",
6626
- DEVELOPER_SERVER: "developer_server"
6627
- };
6628
- var ToolManualPermissionClass = {
6629
- READ_ONLY: "read_only",
6630
- ACTION: "action",
6631
- PAYMENT: "payment"
6632
- };
6633
- var SettlementMode = {
6634
- STRIPE_CHECKOUT: "stripe_checkout",
6635
- STRIPE_PAYMENT_INTENT: "stripe_payment_intent",
6636
- POLYGON_MANDATE: "polygon_mandate",
6637
- EMBEDDED_WALLET_CHARGE: "embedded_wallet_charge"
6638
- };
6724
+ // src/runtime.ts
6725
+ init_types();
6639
6726
 
6640
6727
  // src/testing/recorder.ts
6641
6728
  var CASSETTE_VERSION = 1;
@@ -7033,6 +7120,7 @@ Actual: ${requestSignature(requestRecord, ignoreBodyFields)}`
7033
7120
  };
7034
7121
 
7035
7122
  // src/tool-manual-validator.ts
7123
+ init_types();
7036
7124
  init_utils();
7037
7125
  var JURISDICTION_PATTERN = /^[A-Z]{2}(-[A-Z0-9]{1,3})?$/;
7038
7126
  var TOOL_NAME_RE = /^[A-Za-z0-9_]{3,64}$/;
@@ -7307,6 +7395,64 @@ function validate_tool_manual(manualInput) {
7307
7395
  // src/runtime.ts
7308
7396
  init_web3();
7309
7397
  var CAPABILITY_KEY_RE = /^[a-z0-9][a-z0-9-]*[a-z0-9]$/;
7398
+ var MINIMUM_JPY_OPERATION_PRICE_CURRENCIES2 = /* @__PURE__ */ new Set(["JPY", "JPYC"]);
7399
+ function pricingPlanFloorIssues(plan, defaultCurrency) {
7400
+ const issues = [];
7401
+ if (plan === void 0 || plan === null) {
7402
+ return issues;
7403
+ }
7404
+ if (typeof plan !== "object" || Array.isArray(plan)) {
7405
+ return ["pricing_plan must be an object when provided"];
7406
+ }
7407
+ const record = plan;
7408
+ const items = record.items;
7409
+ if (items === void 0 || items === null) {
7410
+ return issues;
7411
+ }
7412
+ if (!Array.isArray(items)) {
7413
+ return ["pricing_plan.items must be an array when provided"];
7414
+ }
7415
+ const planCurrency = String(record.currency ?? defaultCurrency ?? "").trim().toUpperCase();
7416
+ const seenKeys = /* @__PURE__ */ new Set();
7417
+ items.forEach((item, index) => {
7418
+ if (typeof item !== "object" || item === null || Array.isArray(item)) {
7419
+ issues.push(`pricing_plan.items[${index}] must be an object`);
7420
+ return;
7421
+ }
7422
+ const itemRecord = item;
7423
+ const itemKey = String(
7424
+ itemRecord.key ?? itemRecord.operation ?? itemRecord.operation_key ?? itemRecord.request_type ?? itemRecord.receipt_code ?? itemRecord.action ?? ""
7425
+ ).trim();
7426
+ if (!itemKey) {
7427
+ issues.push(`pricing_plan.items[${index}].key is required`);
7428
+ } else if (seenKeys.has(itemKey)) {
7429
+ issues.push(`pricing_plan.items[${index}].key duplicates ${itemKey}`);
7430
+ } else {
7431
+ seenKeys.add(itemKey);
7432
+ }
7433
+ const amountRaw = itemRecord.price_minor ?? itemRecord.amount_minor ?? itemRecord.cost_minor ?? itemRecord.value_minor;
7434
+ if (amountRaw === void 0 || amountRaw === null) {
7435
+ issues.push(`pricing_plan.items[${index}].price_minor is required`);
7436
+ return;
7437
+ }
7438
+ const amountMinor = typeof amountRaw === "number" ? amountRaw : typeof amountRaw === "string" && amountRaw.trim() ? Number(amountRaw) : NaN;
7439
+ if (!Number.isInteger(amountMinor)) {
7440
+ issues.push(`pricing_plan.items[${index}].price_minor must be an integer`);
7441
+ return;
7442
+ }
7443
+ if (amountMinor < 0) {
7444
+ issues.push(`pricing_plan.items[${index}].price_minor must be zero or positive`);
7445
+ return;
7446
+ }
7447
+ const currency = String(itemRecord.currency ?? planCurrency ?? defaultCurrency ?? "").trim().toUpperCase();
7448
+ if (MINIMUM_JPY_OPERATION_PRICE_CURRENCIES2.has(currency) && amountMinor > 0 && amountMinor < MINIMUM_JPY_OPERATION_PRICE_MINOR) {
7449
+ issues.push(
7450
+ `pricing_plan.items[${index}].price_minor must be 0 or at least ${MINIMUM_JPY_OPERATION_PRICE_MINOR} for JPY/JPYC operation billing`
7451
+ );
7452
+ }
7453
+ });
7454
+ return issues;
7455
+ }
7310
7456
  function normalizeExecutionResult(result, executionKind) {
7311
7457
  return {
7312
7458
  success: Boolean(result.success),
@@ -7408,6 +7554,13 @@ var AppTestHarness = class {
7408
7554
  if (!manifest.example_prompts || manifest.example_prompts.length === 0) {
7409
7555
  issues.push("at least one example_prompt is recommended");
7410
7556
  }
7557
+ issues.push(...pricingPlanFloorIssues(manifest.pricing_plan, String(manifest.currency ?? "USD")));
7558
+ if (manifest.billing_timing !== void 0 && manifest.billing_timing !== "post" && manifest.billing_timing !== "prepay") {
7559
+ issues.push("billing_timing must be 'post' or 'prepay'");
7560
+ }
7561
+ 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)) {
7562
+ issues.push("pricing_plan.items is required for usage_based/per_action pricing");
7563
+ }
7411
7564
  if (manifest.permission_class === PermissionClass.ACTION || manifest.permission_class === PermissionClass.PAYMENT) {
7412
7565
  if (!manifest.dry_run_supported) {
7413
7566
  issues.push("action/payment apps should support dry_run");
@@ -7483,7 +7636,7 @@ var AppTestHarness = class {
7483
7636
  };
7484
7637
  }
7485
7638
  return {
7486
- experimental: manifest.price_model === PriceModel.USAGE_BASED || manifest.price_model === PriceModel.PER_ACTION,
7639
+ experimental: false,
7487
7640
  usage_record,
7488
7641
  invoice_line_preview
7489
7642
  };
@@ -8909,6 +9062,7 @@ function readEnv(name) {
8909
9062
  }
8910
9063
 
8911
9064
  // src/index.ts
9065
+ init_types();
8912
9066
  init_web3();
8913
9067
  init_webhooks();
8914
9068
  init_utils();