@siglume/api-sdk 1.0.0 → 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.
@@ -177,6 +177,61 @@ var init_utils = __esm({
177
177
  }
178
178
  });
179
179
 
180
+ // src/types.ts
181
+ var PermissionClass, ApprovalMode, Environment, PriceModel, AppCategory, MINIMUM_JPY_OPERATION_PRICE_MINOR, ToolManualPermissionClass, SettlementMode;
182
+ var init_types = __esm({
183
+ "src/types.ts"() {
184
+ "use strict";
185
+ PermissionClass = {
186
+ READ_ONLY: "read-only",
187
+ ACTION: "action",
188
+ PAYMENT: "payment",
189
+ /** @deprecated Use READ_ONLY. Behaves identically. */
190
+ RECOMMENDATION: "recommendation"
191
+ };
192
+ ApprovalMode = {
193
+ AUTO: "auto",
194
+ BUDGET_BOUNDED: "budget-bounded",
195
+ ALWAYS_ASK: "always-ask",
196
+ DENY: "deny"
197
+ };
198
+ Environment = {
199
+ SANDBOX: "sandbox",
200
+ LIVE: "live"
201
+ };
202
+ PriceModel = {
203
+ FREE: "free",
204
+ SUBSCRIPTION: "subscription",
205
+ ONE_TIME: "one_time",
206
+ BUNDLE: "bundle",
207
+ USAGE_BASED: "usage_based",
208
+ PER_ACTION: "per_action"
209
+ };
210
+ AppCategory = {
211
+ COMMERCE: "commerce",
212
+ BOOKING: "booking",
213
+ CRM: "crm",
214
+ FINANCE: "finance",
215
+ DOCUMENT: "document",
216
+ COMMUNICATION: "communication",
217
+ MONITORING: "monitoring",
218
+ OTHER: "other"
219
+ };
220
+ MINIMUM_JPY_OPERATION_PRICE_MINOR = 15;
221
+ ToolManualPermissionClass = {
222
+ READ_ONLY: "read_only",
223
+ ACTION: "action",
224
+ PAYMENT: "payment"
225
+ };
226
+ SettlementMode = {
227
+ STRIPE_CHECKOUT: "stripe_checkout",
228
+ STRIPE_PAYMENT_INTENT: "stripe_payment_intent",
229
+ POLYGON_MANDATE: "polygon_mandate",
230
+ EMBEDDED_WALLET_CHARGE: "embedded_wallet_charge"
231
+ };
232
+ }
233
+ });
234
+
180
235
  // src/webhooks.ts
181
236
  function isRecord2(value) {
182
237
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -1298,6 +1353,58 @@ function validateSaveDataSchema(schema, fieldName) {
1298
1353
  }
1299
1354
  }
1300
1355
  }
1356
+ function validatePricingPlanFloor(plan, defaultCurrency) {
1357
+ if (plan === void 0 || plan === null) {
1358
+ return;
1359
+ }
1360
+ if (!isRecord(plan)) {
1361
+ throw new SiglumeClientError("AppManifest.pricing_plan must be an object when provided.");
1362
+ }
1363
+ const items = plan.items;
1364
+ if (items === void 0 || items === null) {
1365
+ return;
1366
+ }
1367
+ if (!Array.isArray(items)) {
1368
+ throw new SiglumeClientError("AppManifest.pricing_plan.items must be an array when provided.");
1369
+ }
1370
+ const planCurrency = String(plan.currency ?? defaultCurrency ?? "").trim().toUpperCase();
1371
+ const seenKeys = /* @__PURE__ */ new Set();
1372
+ items.forEach((item, index) => {
1373
+ if (!isRecord(item)) {
1374
+ throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}] must be an object.`);
1375
+ }
1376
+ const itemKey = String(
1377
+ item.key ?? item.operation ?? item.operation_key ?? item.request_type ?? item.receipt_code ?? item.action ?? ""
1378
+ ).trim();
1379
+ if (!itemKey) {
1380
+ throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}].key is required.`);
1381
+ }
1382
+ if (seenKeys.has(itemKey)) {
1383
+ throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}].key duplicates ${itemKey}.`);
1384
+ }
1385
+ seenKeys.add(itemKey);
1386
+ const amountRaw = item.price_minor ?? item.amount_minor ?? item.cost_minor ?? item.value_minor;
1387
+ if (amountRaw === void 0 || amountRaw === null) {
1388
+ throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}].price_minor is required.`);
1389
+ }
1390
+ const amountMinor = typeof amountRaw === "number" ? amountRaw : typeof amountRaw === "string" && amountRaw.trim() ? Number(amountRaw) : NaN;
1391
+ if (!Number.isInteger(amountMinor)) {
1392
+ throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}].price_minor must be an integer.`);
1393
+ }
1394
+ if (amountMinor < 0) {
1395
+ throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}].price_minor must be zero or positive.`);
1396
+ }
1397
+ const currency = String(item.currency ?? planCurrency ?? defaultCurrency ?? "").trim().toUpperCase();
1398
+ if (MINIMUM_JPY_OPERATION_PRICE_CURRENCIES.has(currency) && amountMinor > 0 && amountMinor < MINIMUM_JPY_OPERATION_PRICE_MINOR) {
1399
+ throw new SiglumeClientError(
1400
+ `AppManifest.pricing_plan.items[${index}].price_minor must be 0 or at least ${MINIMUM_JPY_OPERATION_PRICE_MINOR} for JPY/JPYC operation billing.`
1401
+ );
1402
+ }
1403
+ });
1404
+ }
1405
+ function pricingPlanHasItems(plan) {
1406
+ return isRecord(plan) && Array.isArray(plan.items) && plan.items.length > 0;
1407
+ }
1301
1408
  function buildToolManualQualityReport(payload) {
1302
1409
  const qualityBlock = isRecord(payload.quality) ? payload.quality : payload;
1303
1410
  const issues = [];
@@ -1373,6 +1480,7 @@ function buildUrl(baseUrl, path, params) {
1373
1480
  }
1374
1481
  function parseListing(data) {
1375
1482
  const metadata = isRecord(data.metadata) ? data.metadata : {};
1483
+ const pricing_plan = isRecord(data.pricing_plan) ? data.pricing_plan : isRecord(metadata.pricing_plan) ? metadata.pricing_plan : null;
1376
1484
  const persistence = isRecord(data.persistence) ? data.persistence : isRecord(metadata.persistence) ? metadata.persistence : {};
1377
1485
  return {
1378
1486
  listing_id: String(data.listing_id ?? data.id ?? ""),
@@ -1386,6 +1494,7 @@ function parseListing(data) {
1386
1494
  dry_run_supported: Boolean(data.dry_run_supported ?? false),
1387
1495
  price_model: stringOrNull(data.price_model),
1388
1496
  price_value_minor: Number(data.price_value_minor ?? 0),
1497
+ pricing_plan,
1389
1498
  currency: String(data.currency ?? "USD"),
1390
1499
  allow_free_trial: Boolean(data.allow_free_trial ?? false),
1391
1500
  free_trial_duration_days: Number(data.free_trial_duration_days ?? 30),
@@ -2483,10 +2592,11 @@ function cloneJsonLike(value) {
2483
2592
  }
2484
2593
  return value;
2485
2594
  }
2486
- var DEFAULT_SIGLUME_API_BASE, RETRYABLE_STATUS_CODES, CursorPageResult, SiglumeClient;
2595
+ var DEFAULT_SIGLUME_API_BASE, RETRYABLE_STATUS_CODES, MINIMUM_JPY_OPERATION_PRICE_CURRENCIES, CursorPageResult, SiglumeClient;
2487
2596
  var init_client = __esm({
2488
2597
  "src/client.ts"() {
2489
2598
  "use strict";
2599
+ init_types();
2490
2600
  init_errors();
2491
2601
  init_webhooks();
2492
2602
  init_web3();
@@ -2494,6 +2604,7 @@ var init_client = __esm({
2494
2604
  init_utils();
2495
2605
  DEFAULT_SIGLUME_API_BASE = "https://siglume.com/v1";
2496
2606
  RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
2607
+ MINIMUM_JPY_OPERATION_PRICE_CURRENCIES = /* @__PURE__ */ new Set(["JPY", "JPYC"]);
2497
2608
  CursorPageResult = class {
2498
2609
  items;
2499
2610
  next_cursor;
@@ -2601,6 +2712,7 @@ var init_client = __esm({
2601
2712
  "jurisdiction",
2602
2713
  "price_model",
2603
2714
  "price_value_minor",
2715
+ "pricing_plan",
2604
2716
  "currency",
2605
2717
  "allow_free_trial",
2606
2718
  "free_trial_duration_days",
@@ -2617,6 +2729,9 @@ var init_client = __esm({
2617
2729
  payload[fieldName] = value;
2618
2730
  }
2619
2731
  }
2732
+ if (payload.pricing_plan !== void 0 && (typeof payload.pricing_plan !== "object" || Array.isArray(payload.pricing_plan))) {
2733
+ throw new SiglumeClientError("AppManifest.pricing_plan must be an object when provided.");
2734
+ }
2620
2735
  if (payload.store_vertical === void 0 || payload.store_vertical === null) {
2621
2736
  throw new SiglumeClientError(
2622
2737
  "AppManifest.store_vertical is required. Choose 'api' for normal API Store listings or 'game' for API games."
@@ -2632,6 +2747,13 @@ var init_client = __esm({
2632
2747
  throw new SiglumeClientError(`AppManifest.currency must be 'USD' or 'JPY'. Got ${String(payload.currency)}.`);
2633
2748
  }
2634
2749
  payload.currency = currency;
2750
+ if (payload.pricing_plan !== void 0) {
2751
+ validatePricingPlanFloor(payload.pricing_plan, currency);
2752
+ }
2753
+ const priceModel = String(payload.price_model ?? "free").trim().toLowerCase();
2754
+ if ((priceModel === "usage_based" || priceModel === "per_action") && !pricingPlanHasItems(payload.pricing_plan)) {
2755
+ throw new SiglumeClientError("AppManifest.pricing_plan.items is required for usage_based/per_action pricing.");
2756
+ }
2635
2757
  if (payload.allow_free_trial === void 0 || payload.allow_free_trial === null) {
2636
2758
  throw new SiglumeClientError(
2637
2759
  "AppManifest.allow_free_trial is required. Pass true to offer a Plus/Pro buyer free trial or false to disable trials."
@@ -5311,53 +5433,8 @@ function stableValue(value) {
5311
5433
  return value;
5312
5434
  }
5313
5435
 
5314
- // src/types.ts
5315
- var PermissionClass = {
5316
- READ_ONLY: "read-only",
5317
- ACTION: "action",
5318
- PAYMENT: "payment",
5319
- /** @deprecated Use READ_ONLY. Behaves identically. */
5320
- RECOMMENDATION: "recommendation"
5321
- };
5322
- var ApprovalMode = {
5323
- AUTO: "auto",
5324
- BUDGET_BOUNDED: "budget-bounded",
5325
- ALWAYS_ASK: "always-ask",
5326
- DENY: "deny"
5327
- };
5328
- var Environment = {
5329
- SANDBOX: "sandbox",
5330
- LIVE: "live"
5331
- };
5332
- var PriceModel = {
5333
- FREE: "free",
5334
- SUBSCRIPTION: "subscription",
5335
- ONE_TIME: "one_time",
5336
- BUNDLE: "bundle",
5337
- USAGE_BASED: "usage_based",
5338
- PER_ACTION: "per_action"
5339
- };
5340
- var AppCategory = {
5341
- COMMERCE: "commerce",
5342
- BOOKING: "booking",
5343
- CRM: "crm",
5344
- FINANCE: "finance",
5345
- DOCUMENT: "document",
5346
- COMMUNICATION: "communication",
5347
- MONITORING: "monitoring",
5348
- OTHER: "other"
5349
- };
5350
- var ToolManualPermissionClass = {
5351
- READ_ONLY: "read_only",
5352
- ACTION: "action",
5353
- PAYMENT: "payment"
5354
- };
5355
- var SettlementMode = {
5356
- STRIPE_CHECKOUT: "stripe_checkout",
5357
- STRIPE_PAYMENT_INTENT: "stripe_payment_intent",
5358
- POLYGON_MANDATE: "polygon_mandate",
5359
- EMBEDDED_WALLET_CHARGE: "embedded_wallet_charge"
5360
- };
5436
+ // src/runtime.ts
5437
+ init_types();
5361
5438
 
5362
5439
  // src/testing/recorder.ts
5363
5440
  var CASSETTE_VERSION = 1;
@@ -5749,6 +5826,7 @@ Actual: ${requestSignature(requestRecord, ignoreBodyFields)}`
5749
5826
  };
5750
5827
 
5751
5828
  // src/tool-manual-validator.ts
5829
+ init_types();
5752
5830
  init_utils();
5753
5831
  var JURISDICTION_PATTERN = /^[A-Z]{2}(-[A-Z0-9]{1,3})?$/;
5754
5832
  var TOOL_NAME_RE = /^[A-Za-z0-9_]{3,64}$/;
@@ -6020,6 +6098,64 @@ function validate_tool_manual(manualInput) {
6020
6098
  // src/runtime.ts
6021
6099
  init_web3();
6022
6100
  var CAPABILITY_KEY_RE = /^[a-z0-9][a-z0-9-]*[a-z0-9]$/;
6101
+ var MINIMUM_JPY_OPERATION_PRICE_CURRENCIES2 = /* @__PURE__ */ new Set(["JPY", "JPYC"]);
6102
+ function pricingPlanFloorIssues(plan, defaultCurrency) {
6103
+ const issues = [];
6104
+ if (plan === void 0 || plan === null) {
6105
+ return issues;
6106
+ }
6107
+ if (typeof plan !== "object" || Array.isArray(plan)) {
6108
+ return ["pricing_plan must be an object when provided"];
6109
+ }
6110
+ const record = plan;
6111
+ const items = record.items;
6112
+ if (items === void 0 || items === null) {
6113
+ return issues;
6114
+ }
6115
+ if (!Array.isArray(items)) {
6116
+ return ["pricing_plan.items must be an array when provided"];
6117
+ }
6118
+ const planCurrency = String(record.currency ?? defaultCurrency ?? "").trim().toUpperCase();
6119
+ const seenKeys = /* @__PURE__ */ new Set();
6120
+ items.forEach((item, index) => {
6121
+ if (typeof item !== "object" || item === null || Array.isArray(item)) {
6122
+ issues.push(`pricing_plan.items[${index}] must be an object`);
6123
+ return;
6124
+ }
6125
+ const itemRecord = item;
6126
+ const itemKey = String(
6127
+ itemRecord.key ?? itemRecord.operation ?? itemRecord.operation_key ?? itemRecord.request_type ?? itemRecord.receipt_code ?? itemRecord.action ?? ""
6128
+ ).trim();
6129
+ if (!itemKey) {
6130
+ issues.push(`pricing_plan.items[${index}].key is required`);
6131
+ } else if (seenKeys.has(itemKey)) {
6132
+ issues.push(`pricing_plan.items[${index}].key duplicates ${itemKey}`);
6133
+ } else {
6134
+ seenKeys.add(itemKey);
6135
+ }
6136
+ const amountRaw = itemRecord.price_minor ?? itemRecord.amount_minor ?? itemRecord.cost_minor ?? itemRecord.value_minor;
6137
+ if (amountRaw === void 0 || amountRaw === null) {
6138
+ issues.push(`pricing_plan.items[${index}].price_minor is required`);
6139
+ return;
6140
+ }
6141
+ const amountMinor = typeof amountRaw === "number" ? amountRaw : typeof amountRaw === "string" && amountRaw.trim() ? Number(amountRaw) : NaN;
6142
+ if (!Number.isInteger(amountMinor)) {
6143
+ issues.push(`pricing_plan.items[${index}].price_minor must be an integer`);
6144
+ return;
6145
+ }
6146
+ if (amountMinor < 0) {
6147
+ issues.push(`pricing_plan.items[${index}].price_minor must be zero or positive`);
6148
+ return;
6149
+ }
6150
+ const currency = String(itemRecord.currency ?? planCurrency ?? defaultCurrency ?? "").trim().toUpperCase();
6151
+ if (MINIMUM_JPY_OPERATION_PRICE_CURRENCIES2.has(currency) && amountMinor > 0 && amountMinor < MINIMUM_JPY_OPERATION_PRICE_MINOR) {
6152
+ issues.push(
6153
+ `pricing_plan.items[${index}].price_minor must be 0 or at least ${MINIMUM_JPY_OPERATION_PRICE_MINOR} for JPY/JPYC operation billing`
6154
+ );
6155
+ }
6156
+ });
6157
+ return issues;
6158
+ }
6023
6159
  function normalizeExecutionResult(result, executionKind) {
6024
6160
  return {
6025
6161
  success: Boolean(result.success),
@@ -6107,6 +6243,10 @@ var AppTestHarness = class {
6107
6243
  if (!manifest.example_prompts || manifest.example_prompts.length === 0) {
6108
6244
  issues.push("at least one example_prompt is recommended");
6109
6245
  }
6246
+ issues.push(...pricingPlanFloorIssues(manifest.pricing_plan, String(manifest.currency ?? "USD")));
6247
+ 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)) {
6248
+ issues.push("pricing_plan.items is required for usage_based/per_action pricing");
6249
+ }
6110
6250
  if (manifest.permission_class === PermissionClass.ACTION || manifest.permission_class === PermissionClass.PAYMENT) {
6111
6251
  if (!manifest.dry_run_supported) {
6112
6252
  issues.push("action/payment apps should support dry_run");
@@ -6182,7 +6322,7 @@ var AppTestHarness = class {
6182
6322
  };
6183
6323
  }
6184
6324
  return {
6185
- experimental: manifest.price_model === PriceModel.USAGE_BASED || manifest.price_model === PriceModel.PER_ACTION,
6325
+ experimental: false,
6186
6326
  usage_record,
6187
6327
  invoice_line_preview
6188
6328
  };