@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/README.md +148 -99
- package/dist/bin/siglume.cjs +232 -334
- package/dist/bin/siglume.cjs.map +1 -1
- package/dist/bin/siglume.js +232 -334
- package/dist/bin/siglume.js.map +1 -1
- package/dist/cli/index.cjs +232 -334
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts +24 -67
- package/dist/cli/index.d.ts +24 -67
- package/dist/cli/index.js +232 -334
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +214 -202
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -112
- package/dist/index.d.ts +27 -112
- package/dist/index.js +214 -202
- package/dist/index.js.map +1 -1
- package/package.json +58 -58
package/dist/cli/index.cjs
CHANGED
|
@@ -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),
|
|
@@ -1460,18 +1569,6 @@ function parseBundleMember(data) {
|
|
|
1460
1569
|
link_id: stringOrNull(data.link_id)
|
|
1461
1570
|
};
|
|
1462
1571
|
}
|
|
1463
|
-
function parseConnectedAccountLifecycle(data) {
|
|
1464
|
-
return {
|
|
1465
|
-
connected_account_id: String(data.connected_account_id ?? ""),
|
|
1466
|
-
provider_key: String(data.provider_key ?? ""),
|
|
1467
|
-
expires_at: stringOrNull(data.expires_at),
|
|
1468
|
-
scopes: Array.isArray(data.scopes) ? data.scopes.filter((s) => typeof s === "string") : [],
|
|
1469
|
-
refreshed_at: stringOrNull(data.refreshed_at),
|
|
1470
|
-
connection_status: stringOrNull(data.connection_status),
|
|
1471
|
-
provider_revoked: typeof data.provider_revoked === "boolean" ? data.provider_revoked : null,
|
|
1472
|
-
revoked_at: stringOrNull(data.revoked_at)
|
|
1473
|
-
};
|
|
1474
|
-
}
|
|
1475
1572
|
function parseBundle(data) {
|
|
1476
1573
|
const membersRaw = Array.isArray(data.members) ? data.members : [];
|
|
1477
1574
|
return {
|
|
@@ -1550,21 +1647,6 @@ function parseBinding(data) {
|
|
|
1550
1647
|
raw: { ...data }
|
|
1551
1648
|
};
|
|
1552
1649
|
}
|
|
1553
|
-
function parseConnectedAccount(data) {
|
|
1554
|
-
return {
|
|
1555
|
-
connected_account_id: String(data.connected_account_id ?? data.id ?? ""),
|
|
1556
|
-
provider_key: String(data.provider_key ?? ""),
|
|
1557
|
-
account_role: String(data.account_role ?? ""),
|
|
1558
|
-
display_name: stringOrNull(data.display_name),
|
|
1559
|
-
environment: stringOrNull(data.environment),
|
|
1560
|
-
connection_status: stringOrNull(data.connection_status),
|
|
1561
|
-
scopes: Array.isArray(data.scopes) ? data.scopes.filter((item) => typeof item === "string") : [],
|
|
1562
|
-
metadata: toRecord(data.metadata),
|
|
1563
|
-
created_at: stringOrNull(data.created_at),
|
|
1564
|
-
updated_at: stringOrNull(data.updated_at),
|
|
1565
|
-
raw: { ...data }
|
|
1566
|
-
};
|
|
1567
|
-
}
|
|
1568
1650
|
function parseSupportCase(data) {
|
|
1569
1651
|
return {
|
|
1570
1652
|
support_case_id: String(data.support_case_id ?? data.id ?? ""),
|
|
@@ -2510,10 +2592,11 @@ function cloneJsonLike(value) {
|
|
|
2510
2592
|
}
|
|
2511
2593
|
return value;
|
|
2512
2594
|
}
|
|
2513
|
-
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;
|
|
2514
2596
|
var init_client = __esm({
|
|
2515
2597
|
"src/client.ts"() {
|
|
2516
2598
|
"use strict";
|
|
2599
|
+
init_types();
|
|
2517
2600
|
init_errors();
|
|
2518
2601
|
init_webhooks();
|
|
2519
2602
|
init_web3();
|
|
@@ -2521,6 +2604,7 @@ var init_client = __esm({
|
|
|
2521
2604
|
init_utils();
|
|
2522
2605
|
DEFAULT_SIGLUME_API_BASE = "https://siglume.com/v1";
|
|
2523
2606
|
RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
2607
|
+
MINIMUM_JPY_OPERATION_PRICE_CURRENCIES = /* @__PURE__ */ new Set(["JPY", "JPYC"]);
|
|
2524
2608
|
CursorPageResult = class {
|
|
2525
2609
|
items;
|
|
2526
2610
|
next_cursor;
|
|
@@ -2603,13 +2687,6 @@ var init_client = __esm({
|
|
|
2603
2687
|
if (options.runtime_validation) {
|
|
2604
2688
|
payload.runtime_validation = coerceMapping(options.runtime_validation, "runtime_validation");
|
|
2605
2689
|
}
|
|
2606
|
-
if (options.oauth_credentials) {
|
|
2607
|
-
payload.oauth_credentials = Array.isArray(options.oauth_credentials) ? {
|
|
2608
|
-
items: options.oauth_credentials.map(
|
|
2609
|
-
(item, index) => coerceMapping(item, `oauth_credentials[${index}]`)
|
|
2610
|
-
)
|
|
2611
|
-
} : coerceMapping(options.oauth_credentials, "oauth_credentials");
|
|
2612
|
-
}
|
|
2613
2690
|
if (options.source_context) {
|
|
2614
2691
|
payload.source_context = coerceMapping(options.source_context, "source_context");
|
|
2615
2692
|
}
|
|
@@ -2635,6 +2712,7 @@ var init_client = __esm({
|
|
|
2635
2712
|
"jurisdiction",
|
|
2636
2713
|
"price_model",
|
|
2637
2714
|
"price_value_minor",
|
|
2715
|
+
"pricing_plan",
|
|
2638
2716
|
"currency",
|
|
2639
2717
|
"allow_free_trial",
|
|
2640
2718
|
"free_trial_duration_days",
|
|
@@ -2651,6 +2729,9 @@ var init_client = __esm({
|
|
|
2651
2729
|
payload[fieldName] = value;
|
|
2652
2730
|
}
|
|
2653
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
|
+
}
|
|
2654
2735
|
if (payload.store_vertical === void 0 || payload.store_vertical === null) {
|
|
2655
2736
|
throw new SiglumeClientError(
|
|
2656
2737
|
"AppManifest.store_vertical is required. Choose 'api' for normal API Store listings or 'game' for API games."
|
|
@@ -2666,6 +2747,13 @@ var init_client = __esm({
|
|
|
2666
2747
|
throw new SiglumeClientError(`AppManifest.currency must be 'USD' or 'JPY'. Got ${String(payload.currency)}.`);
|
|
2667
2748
|
}
|
|
2668
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
|
+
}
|
|
2669
2757
|
if (payload.allow_free_trial === void 0 || payload.allow_free_trial === null) {
|
|
2670
2758
|
throw new SiglumeClientError(
|
|
2671
2759
|
"AppManifest.allow_free_trial is required. Pass true to offer a Plus/Pro buyer free trial or false to disable trials."
|
|
@@ -2739,7 +2827,6 @@ var init_client = __esm({
|
|
|
2739
2827
|
auto_manifest: toRecord(data.auto_manifest),
|
|
2740
2828
|
confidence: toRecord(data.confidence),
|
|
2741
2829
|
validation_report: toRecord(data.validation_report),
|
|
2742
|
-
oauth_status: toRecord(data.oauth_status),
|
|
2743
2830
|
review_url: stringOrNull(data.review_url),
|
|
2744
2831
|
trace_id: meta.trace_id,
|
|
2745
2832
|
request_id: meta.request_id
|
|
@@ -2915,66 +3002,9 @@ var init_client = __esm({
|
|
|
2915
3002
|
return parseBundle(data);
|
|
2916
3003
|
}
|
|
2917
3004
|
// ----- end bundles -------------------------------------------------------
|
|
2918
|
-
// ----- Connected accounts
|
|
2919
|
-
//
|
|
2920
|
-
|
|
2921
|
-
const body = {
|
|
2922
|
-
listing_id: input.listing_id,
|
|
2923
|
-
redirect_uri: input.redirect_uri
|
|
2924
|
-
};
|
|
2925
|
-
if (input.scopes !== void 0) body.scopes = input.scopes;
|
|
2926
|
-
if (input.account_role !== void 0) body.account_role = input.account_role;
|
|
2927
|
-
const [data] = await this.request("POST", "/me/connected-accounts/oauth/authorize", {
|
|
2928
|
-
json_body: body
|
|
2929
|
-
});
|
|
2930
|
-
return {
|
|
2931
|
-
authorize_url: String(data.authorize_url ?? ""),
|
|
2932
|
-
state: String(data.state ?? ""),
|
|
2933
|
-
provider_key: String(data.provider_key ?? ""),
|
|
2934
|
-
scopes: Array.isArray(data.scopes) ? data.scopes.filter((s) => typeof s === "string") : [],
|
|
2935
|
-
pkce_method: stringOrNull(data.pkce_method)
|
|
2936
|
-
};
|
|
2937
|
-
}
|
|
2938
|
-
async complete_connected_account_oauth(input) {
|
|
2939
|
-
const [data] = await this.request("POST", "/me/connected-accounts/oauth/callback", {
|
|
2940
|
-
json_body: { state: input.state, code: input.code }
|
|
2941
|
-
});
|
|
2942
|
-
return { ...data };
|
|
2943
|
-
}
|
|
2944
|
-
async refresh_connected_account(account_id) {
|
|
2945
|
-
const [data] = await this.request("POST", `/me/connected-accounts/${account_id}/refresh`);
|
|
2946
|
-
return parseConnectedAccountLifecycle(data);
|
|
2947
|
-
}
|
|
2948
|
-
async revoke_connected_account(account_id) {
|
|
2949
|
-
const [data] = await this.request("POST", `/me/connected-accounts/${account_id}/revoke`);
|
|
2950
|
-
return parseConnectedAccountLifecycle(data);
|
|
2951
|
-
}
|
|
2952
|
-
async set_listing_oauth_credentials(listing_id, input) {
|
|
2953
|
-
const body = {
|
|
2954
|
-
provider_key: input.provider_key,
|
|
2955
|
-
client_id: input.client_id,
|
|
2956
|
-
client_secret: input.client_secret,
|
|
2957
|
-
authorize_url: input.authorize_url,
|
|
2958
|
-
token_url: input.token_url
|
|
2959
|
-
};
|
|
2960
|
-
if (input.revoke_url !== void 0) body.revoke_url = input.revoke_url;
|
|
2961
|
-
if (input.display_name !== void 0) body.display_name = input.display_name;
|
|
2962
|
-
if (input.scope_separator !== void 0) body.scope_separator = input.scope_separator;
|
|
2963
|
-
if (input.token_endpoint_auth !== void 0) body.token_endpoint_auth = input.token_endpoint_auth;
|
|
2964
|
-
if (input.pkce_required !== void 0) body.pkce_required = input.pkce_required;
|
|
2965
|
-
if (input.refresh_supported !== void 0) body.refresh_supported = input.refresh_supported;
|
|
2966
|
-
if (input.available_scopes !== void 0) body.available_scopes = input.available_scopes;
|
|
2967
|
-
if (input.required_scopes !== void 0) body.required_scopes = input.required_scopes;
|
|
2968
|
-
const [data] = await this.request("PUT", `/market/capabilities/${listing_id}/oauth-credentials`, {
|
|
2969
|
-
json_body: body
|
|
2970
|
-
});
|
|
2971
|
-
return { ...data };
|
|
2972
|
-
}
|
|
2973
|
-
async get_listing_oauth_credentials_status(listing_id) {
|
|
2974
|
-
const [data] = await this.request("GET", `/market/capabilities/${listing_id}/oauth-credentials`);
|
|
2975
|
-
return { ...data };
|
|
2976
|
-
}
|
|
2977
|
-
// ----- end connected accounts --------------------------------------------
|
|
3005
|
+
// ----- Connected accounts ------------------------------------------------
|
|
3006
|
+
// Architecture B: publisher APIs own external OAuth and token storage.
|
|
3007
|
+
// The SDK no longer exposes platform OAuth or listing credential APIs.
|
|
2978
3008
|
async get_developer_portal() {
|
|
2979
3009
|
const [data, meta] = await this.request("GET", "/market/developer/portal");
|
|
2980
3010
|
return {
|
|
@@ -3007,7 +3037,6 @@ var init_client = __esm({
|
|
|
3007
3037
|
dry_run_supported: Boolean(data.dry_run_supported ?? false),
|
|
3008
3038
|
approval_mode: stringOrNull(data.approval_mode),
|
|
3009
3039
|
required_connected_accounts: Array.isArray(data.required_connected_accounts) ? data.required_connected_accounts : [],
|
|
3010
|
-
connected_accounts: Array.isArray(data.connected_accounts) ? data.connected_accounts.filter((item) => isRecord(item)).map((item) => ({ ...item })) : [],
|
|
3011
3040
|
stub_providers_enabled: Boolean(data.stub_providers_enabled ?? false),
|
|
3012
3041
|
simulated_receipts: Boolean(data.simulated_receipts ?? false),
|
|
3013
3042
|
approval_simulator: Boolean(data.approval_simulator ?? false),
|
|
@@ -4305,25 +4334,6 @@ var init_client = __esm({
|
|
|
4305
4334
|
raw: { ...data }
|
|
4306
4335
|
};
|
|
4307
4336
|
}
|
|
4308
|
-
async list_connected_accounts(options = {}) {
|
|
4309
|
-
const params = {
|
|
4310
|
-
provider_key: options.provider_key,
|
|
4311
|
-
environment: options.environment,
|
|
4312
|
-
limit: Math.max(1, Math.min(Math.trunc(options.limit ?? 50), 100)),
|
|
4313
|
-
cursor: options.cursor
|
|
4314
|
-
};
|
|
4315
|
-
const [data, meta] = await this.request("GET", "/market/connected-accounts", { params });
|
|
4316
|
-
const items = Array.isArray(data.items) ? data.items.filter((item) => isRecord(item)).map(parseConnectedAccount) : [];
|
|
4317
|
-
const next_cursor = stringOrNull(data.next_cursor);
|
|
4318
|
-
return new CursorPageResult({
|
|
4319
|
-
items,
|
|
4320
|
-
next_cursor,
|
|
4321
|
-
limit: typeof data.limit === "number" ? data.limit : params.limit,
|
|
4322
|
-
offset: typeof data.offset === "number" ? data.offset : null,
|
|
4323
|
-
meta,
|
|
4324
|
-
fetchNext: next_cursor ? (cursor) => this.list_connected_accounts({ ...options, cursor }) : void 0
|
|
4325
|
-
});
|
|
4326
|
-
}
|
|
4327
4337
|
async create_support_case(subject, body, options = {}) {
|
|
4328
4338
|
const summary = subject.trim();
|
|
4329
4339
|
const details = body.trim();
|
|
@@ -5423,53 +5433,8 @@ function stableValue(value) {
|
|
|
5423
5433
|
return value;
|
|
5424
5434
|
}
|
|
5425
5435
|
|
|
5426
|
-
// src/
|
|
5427
|
-
|
|
5428
|
-
READ_ONLY: "read-only",
|
|
5429
|
-
ACTION: "action",
|
|
5430
|
-
PAYMENT: "payment",
|
|
5431
|
-
/** @deprecated Use READ_ONLY. Behaves identically. */
|
|
5432
|
-
RECOMMENDATION: "recommendation"
|
|
5433
|
-
};
|
|
5434
|
-
var ApprovalMode = {
|
|
5435
|
-
AUTO: "auto",
|
|
5436
|
-
BUDGET_BOUNDED: "budget-bounded",
|
|
5437
|
-
ALWAYS_ASK: "always-ask",
|
|
5438
|
-
DENY: "deny"
|
|
5439
|
-
};
|
|
5440
|
-
var Environment = {
|
|
5441
|
-
SANDBOX: "sandbox",
|
|
5442
|
-
LIVE: "live"
|
|
5443
|
-
};
|
|
5444
|
-
var PriceModel = {
|
|
5445
|
-
FREE: "free",
|
|
5446
|
-
SUBSCRIPTION: "subscription",
|
|
5447
|
-
ONE_TIME: "one_time",
|
|
5448
|
-
BUNDLE: "bundle",
|
|
5449
|
-
USAGE_BASED: "usage_based",
|
|
5450
|
-
PER_ACTION: "per_action"
|
|
5451
|
-
};
|
|
5452
|
-
var AppCategory = {
|
|
5453
|
-
COMMERCE: "commerce",
|
|
5454
|
-
BOOKING: "booking",
|
|
5455
|
-
CRM: "crm",
|
|
5456
|
-
FINANCE: "finance",
|
|
5457
|
-
DOCUMENT: "document",
|
|
5458
|
-
COMMUNICATION: "communication",
|
|
5459
|
-
MONITORING: "monitoring",
|
|
5460
|
-
OTHER: "other"
|
|
5461
|
-
};
|
|
5462
|
-
var ToolManualPermissionClass = {
|
|
5463
|
-
READ_ONLY: "read_only",
|
|
5464
|
-
ACTION: "action",
|
|
5465
|
-
PAYMENT: "payment"
|
|
5466
|
-
};
|
|
5467
|
-
var SettlementMode = {
|
|
5468
|
-
STRIPE_CHECKOUT: "stripe_checkout",
|
|
5469
|
-
STRIPE_PAYMENT_INTENT: "stripe_payment_intent",
|
|
5470
|
-
POLYGON_MANDATE: "polygon_mandate",
|
|
5471
|
-
EMBEDDED_WALLET_CHARGE: "embedded_wallet_charge"
|
|
5472
|
-
};
|
|
5436
|
+
// src/runtime.ts
|
|
5437
|
+
init_types();
|
|
5473
5438
|
|
|
5474
5439
|
// src/testing/recorder.ts
|
|
5475
5440
|
var CASSETTE_VERSION = 1;
|
|
@@ -5861,6 +5826,7 @@ Actual: ${requestSignature(requestRecord, ignoreBodyFields)}`
|
|
|
5861
5826
|
};
|
|
5862
5827
|
|
|
5863
5828
|
// src/tool-manual-validator.ts
|
|
5829
|
+
init_types();
|
|
5864
5830
|
init_utils();
|
|
5865
5831
|
var JURISDICTION_PATTERN = /^[A-Z]{2}(-[A-Z0-9]{1,3})?$/;
|
|
5866
5832
|
var TOOL_NAME_RE = /^[A-Za-z0-9_]{3,64}$/;
|
|
@@ -6132,6 +6098,64 @@ function validate_tool_manual(manualInput) {
|
|
|
6132
6098
|
// src/runtime.ts
|
|
6133
6099
|
init_web3();
|
|
6134
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
|
+
}
|
|
6135
6159
|
function normalizeExecutionResult(result, executionKind) {
|
|
6136
6160
|
return {
|
|
6137
6161
|
success: Boolean(result.success),
|
|
@@ -6172,24 +6196,12 @@ var AppTestHarness = class {
|
|
|
6172
6196
|
this.stubs = stubs;
|
|
6173
6197
|
}
|
|
6174
6198
|
async executeWithKind(execution_kind, task_type = "default", options = {}) {
|
|
6175
|
-
const connected_accounts = options.connected_accounts ?? Object.fromEntries(
|
|
6176
|
-
Object.keys(this.stubs).map((key) => [
|
|
6177
|
-
key,
|
|
6178
|
-
{
|
|
6179
|
-
provider_key: key,
|
|
6180
|
-
session_token: `stub-token-${key}`,
|
|
6181
|
-
environment: Environment.SANDBOX,
|
|
6182
|
-
scopes: []
|
|
6183
|
-
}
|
|
6184
|
-
])
|
|
6185
|
-
);
|
|
6186
6199
|
const ctx = {
|
|
6187
6200
|
agent_id: "test-agent-001",
|
|
6188
6201
|
owner_user_id: "test-owner-001",
|
|
6189
6202
|
task_type,
|
|
6190
6203
|
environment: Environment.SANDBOX,
|
|
6191
6204
|
execution_kind,
|
|
6192
|
-
connected_accounts,
|
|
6193
6205
|
input_params: options.input_params ?? {},
|
|
6194
6206
|
trace_id: options.trace_id,
|
|
6195
6207
|
idempotency_key: options.idempotency_key,
|
|
@@ -6231,6 +6243,10 @@ var AppTestHarness = class {
|
|
|
6231
6243
|
if (!manifest.example_prompts || manifest.example_prompts.length === 0) {
|
|
6232
6244
|
issues.push("at least one example_prompt is recommended");
|
|
6233
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
|
+
}
|
|
6234
6250
|
if (manifest.permission_class === PermissionClass.ACTION || manifest.permission_class === PermissionClass.PAYMENT) {
|
|
6235
6251
|
if (!manifest.dry_run_supported) {
|
|
6236
6252
|
issues.push("action/payment apps should support dry_run");
|
|
@@ -6279,12 +6295,6 @@ var AppTestHarness = class {
|
|
|
6279
6295
|
}
|
|
6280
6296
|
return issues;
|
|
6281
6297
|
}
|
|
6282
|
-
async simulate_connected_account_missing(task_type = "default", options = {}) {
|
|
6283
|
-
return this.executeWithKind("dry_run", task_type, {
|
|
6284
|
-
...options,
|
|
6285
|
-
connected_accounts: {}
|
|
6286
|
-
});
|
|
6287
|
-
}
|
|
6288
6298
|
async simulate_metering(record, options = {}) {
|
|
6289
6299
|
const { normalizeUsageRecord: normalizeUsageRecord2 } = await Promise.resolve().then(() => (init_metering(), metering_exports));
|
|
6290
6300
|
const manifest = await this.app.manifest();
|
|
@@ -6312,7 +6322,7 @@ var AppTestHarness = class {
|
|
|
6312
6322
|
};
|
|
6313
6323
|
}
|
|
6314
6324
|
return {
|
|
6315
|
-
experimental:
|
|
6325
|
+
experimental: false,
|
|
6316
6326
|
usage_record,
|
|
6317
6327
|
invoice_line_preview
|
|
6318
6328
|
};
|
|
@@ -7247,15 +7257,6 @@ async function loadProject(path = ".") {
|
|
|
7247
7257
|
const tool_manual = tool_manual_path ? JSON.parse(await (0, import_promises.readFile)(tool_manual_path, "utf8")) : buildToolManualTemplate(manifest);
|
|
7248
7258
|
const runtime_validation_path = await findRuntimeValidationPath(root_dir);
|
|
7249
7259
|
const runtime_validation = runtime_validation_path ? await loadJsonObject(runtime_validation_path, "runtime_validation") : void 0;
|
|
7250
|
-
const oauth_credentials_path = await findOauthCredentialsPath(root_dir);
|
|
7251
|
-
let oauth_credentials;
|
|
7252
|
-
if (oauth_credentials_path) {
|
|
7253
|
-
const parsed = JSON.parse(await (0, import_promises.readFile)(oauth_credentials_path, "utf8"));
|
|
7254
|
-
if (!isRecord(parsed) && !Array.isArray(parsed)) {
|
|
7255
|
-
throw new SiglumeProjectError("oauth_credentials must be a JSON object or array");
|
|
7256
|
-
}
|
|
7257
|
-
oauth_credentials = parsed;
|
|
7258
|
-
}
|
|
7259
7260
|
return {
|
|
7260
7261
|
root_dir,
|
|
7261
7262
|
adapter_path,
|
|
@@ -7264,9 +7265,7 @@ async function loadProject(path = ".") {
|
|
|
7264
7265
|
tool_manual_path: tool_manual_path ?? void 0,
|
|
7265
7266
|
tool_manual,
|
|
7266
7267
|
runtime_validation_path: runtime_validation_path ?? void 0,
|
|
7267
|
-
runtime_validation
|
|
7268
|
-
oauth_credentials_path: oauth_credentials_path ?? void 0,
|
|
7269
|
-
oauth_credentials
|
|
7268
|
+
runtime_validation
|
|
7270
7269
|
};
|
|
7271
7270
|
}
|
|
7272
7271
|
function isPlatformManagedRequirement(value) {
|
|
@@ -7304,6 +7303,21 @@ function requiredOauthProviders(requirements) {
|
|
|
7304
7303
|
}
|
|
7305
7304
|
return providers;
|
|
7306
7305
|
}
|
|
7306
|
+
function apiManagedRequirementsMissingConnectUrl(requirements) {
|
|
7307
|
+
const missing = [];
|
|
7308
|
+
for (const item of requirements ?? []) {
|
|
7309
|
+
if (!isRecord(item)) continue;
|
|
7310
|
+
const managedBy = String(item.managed_by ?? "").trim().toLowerCase().replaceAll("_", "-");
|
|
7311
|
+
if (managedBy !== "api") continue;
|
|
7312
|
+
const connectUrl = String(item.connect_url ?? "").trim();
|
|
7313
|
+
if (connectUrl) continue;
|
|
7314
|
+
const label = oauthProviderKeyFromRequirement(item) ?? "(missing provider_key)";
|
|
7315
|
+
if (!missing.includes(label)) {
|
|
7316
|
+
missing.push(label);
|
|
7317
|
+
}
|
|
7318
|
+
}
|
|
7319
|
+
return missing;
|
|
7320
|
+
}
|
|
7307
7321
|
function connectedAccountRequirementLabel(value) {
|
|
7308
7322
|
if (isRecord(value)) {
|
|
7309
7323
|
for (const key of ["provider_key", "provider", "account_type", "name"]) {
|
|
@@ -7314,102 +7328,6 @@ function connectedAccountRequirementLabel(value) {
|
|
|
7314
7328
|
}
|
|
7315
7329
|
return String(value ?? "").trim();
|
|
7316
7330
|
}
|
|
7317
|
-
function oauthProviderRecordsMap(payload) {
|
|
7318
|
-
if (!payload) {
|
|
7319
|
-
return {};
|
|
7320
|
-
}
|
|
7321
|
-
const items = Array.isArray(payload) ? payload : Array.isArray(payload.items) ? payload.items : [payload];
|
|
7322
|
-
const resolved = {};
|
|
7323
|
-
for (const [index, item] of items.entries()) {
|
|
7324
|
-
if (!isRecord(item)) {
|
|
7325
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}] must be a JSON object.`);
|
|
7326
|
-
}
|
|
7327
|
-
const providerKey = oauthProviderKeyFromRequirement(item.provider_key ?? item.provider);
|
|
7328
|
-
if (!providerKey) {
|
|
7329
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}].provider_key is required.`);
|
|
7330
|
-
}
|
|
7331
|
-
const authorizeUrl = String(item.authorize_url ?? item.authorization_url ?? item.auth_url ?? "").trim();
|
|
7332
|
-
const tokenUrl = String(item.token_url ?? "").trim();
|
|
7333
|
-
if (!authorizeUrl || !tokenUrl) {
|
|
7334
|
-
throw new SiglumeProjectError(
|
|
7335
|
-
`oauth_credentials[${index}] must include authorize_url and token_url.`
|
|
7336
|
-
);
|
|
7337
|
-
}
|
|
7338
|
-
for (const [urlKey, urlValue] of Object.entries({
|
|
7339
|
-
authorize_url: authorizeUrl,
|
|
7340
|
-
token_url: tokenUrl,
|
|
7341
|
-
revoke_url: String(item.revoke_url ?? "").trim()
|
|
7342
|
-
})) {
|
|
7343
|
-
if (urlValue && !urlValue.startsWith("https://")) {
|
|
7344
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}].${urlKey} must be an https URL.`);
|
|
7345
|
-
}
|
|
7346
|
-
}
|
|
7347
|
-
const clientId = String(item.client_id ?? "").trim();
|
|
7348
|
-
const clientSecret = String(item.client_secret ?? "").trim();
|
|
7349
|
-
if (!clientId || !clientSecret) {
|
|
7350
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}] must include client_id and client_secret.`);
|
|
7351
|
-
}
|
|
7352
|
-
const rawScopes = item.required_scopes ?? item.scopes;
|
|
7353
|
-
let scopes = [];
|
|
7354
|
-
if (rawScopes == null) {
|
|
7355
|
-
scopes = [];
|
|
7356
|
-
} else if (!Array.isArray(rawScopes)) {
|
|
7357
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}].required_scopes must be a JSON array.`);
|
|
7358
|
-
} else {
|
|
7359
|
-
scopes = rawScopes.map((scope) => String(scope ?? "").trim()).filter(Boolean);
|
|
7360
|
-
}
|
|
7361
|
-
const record = {
|
|
7362
|
-
provider_key: providerKey,
|
|
7363
|
-
client_id: clientId,
|
|
7364
|
-
client_secret: clientSecret,
|
|
7365
|
-
required_scopes: scopes
|
|
7366
|
-
};
|
|
7367
|
-
for (const [key, value] of Object.entries({
|
|
7368
|
-
authorize_url: authorizeUrl,
|
|
7369
|
-
token_url: tokenUrl,
|
|
7370
|
-
revoke_url: String(item.revoke_url ?? "").trim(),
|
|
7371
|
-
display_name: String(item.display_name ?? "").trim(),
|
|
7372
|
-
scope_separator: String(item.scope_separator ?? "").trim(),
|
|
7373
|
-
token_endpoint_auth: String(item.token_endpoint_auth ?? "").trim()
|
|
7374
|
-
})) {
|
|
7375
|
-
if (value) record[key] = value;
|
|
7376
|
-
}
|
|
7377
|
-
for (const key of ["pkce_required", "refresh_supported"]) {
|
|
7378
|
-
if (typeof item[key] === "boolean") record[key] = item[key];
|
|
7379
|
-
}
|
|
7380
|
-
if (Array.isArray(item.available_scopes)) {
|
|
7381
|
-
const availableScopes = item.available_scopes.map((scope) => String(scope ?? "").trim()).filter(Boolean);
|
|
7382
|
-
if (availableScopes.length > 0) record.available_scopes = availableScopes;
|
|
7383
|
-
}
|
|
7384
|
-
resolved[providerKey] = record;
|
|
7385
|
-
}
|
|
7386
|
-
return resolved;
|
|
7387
|
-
}
|
|
7388
|
-
function canonicalOauthCredentialsPayload(payload) {
|
|
7389
|
-
const records = oauthProviderRecordsMap(payload);
|
|
7390
|
-
const providerKeys = Object.keys(records).sort();
|
|
7391
|
-
if (providerKeys.length === 0) {
|
|
7392
|
-
return void 0;
|
|
7393
|
-
}
|
|
7394
|
-
return {
|
|
7395
|
-
items: providerKeys.map((providerKey) => records[providerKey])
|
|
7396
|
-
};
|
|
7397
|
-
}
|
|
7398
|
-
function ensureRequiredOauthCredentials(project) {
|
|
7399
|
-
const requiredProviders = requiredOauthProviders(project.manifest.required_connected_accounts ?? []);
|
|
7400
|
-
if (requiredProviders.length === 0) {
|
|
7401
|
-
return;
|
|
7402
|
-
}
|
|
7403
|
-
const provided = new Set(Object.keys(oauthProviderRecordsMap(project.oauth_credentials)));
|
|
7404
|
-
const missing = requiredProviders.filter((provider) => !provided.has(provider));
|
|
7405
|
-
if (missing.length === 0) {
|
|
7406
|
-
return;
|
|
7407
|
-
}
|
|
7408
|
-
const path = project.oauth_credentials_path ?? (0, import_node_path.join)(project.root_dir, "oauth_credentials.json");
|
|
7409
|
-
throw new SiglumeProjectError(
|
|
7410
|
-
`${path} is required for platform-managed OAuth APIs. Missing provider seeds: ${missing.join(", ")}`
|
|
7411
|
-
);
|
|
7412
|
-
}
|
|
7413
7331
|
async function validateProject(path = ".", deps = {}) {
|
|
7414
7332
|
const project = await loadProject(path);
|
|
7415
7333
|
const manifest_issues = await projectValidationIssues(project);
|
|
@@ -7564,10 +7482,21 @@ function ensureExplicitToolManual(project) {
|
|
|
7564
7482
|
async function registrationPreflight(project, client) {
|
|
7565
7483
|
const manifestIssues = await projectValidationIssues(project);
|
|
7566
7484
|
const [toolManualValid, toolManualIssues] = validate_tool_manual(project.tool_manual);
|
|
7485
|
+
const retiredPlatformOauthProviders = requiredOauthProviders(project.manifest.required_connected_accounts ?? []);
|
|
7486
|
+
if (retiredPlatformOauthProviders.length > 0) {
|
|
7487
|
+
throw new SiglumeProjectError(
|
|
7488
|
+
`Registration preflight failed. Fix these before calling auto-register:
|
|
7489
|
+
- platform-managed OAuth is retired. Use managed_by="api" with connect_url: ${retiredPlatformOauthProviders.join(", ")}`
|
|
7490
|
+
);
|
|
7491
|
+
}
|
|
7492
|
+
const apiManagedMissingConnectUrl = apiManagedRequirementsMissingConnectUrl(project.manifest.required_connected_accounts ?? []);
|
|
7493
|
+
if (apiManagedMissingConnectUrl.length > 0) {
|
|
7494
|
+
throw new SiglumeProjectError(
|
|
7495
|
+
`Registration preflight failed. Fix these before calling auto-register:
|
|
7496
|
+
- API-managed OAuth requirements must include connect_url: ${apiManagedMissingConnectUrl.join(", ")}`
|
|
7497
|
+
);
|
|
7498
|
+
}
|
|
7567
7499
|
const remoteQuality = await client.preview_quality_score(project.tool_manual);
|
|
7568
|
-
const requiredOauthProvidersList = requiredOauthProviders(project.manifest.required_connected_accounts ?? []);
|
|
7569
|
-
const oauthProviderRecords = oauthProviderRecordsMap(project.oauth_credentials);
|
|
7570
|
-
const missingOauthProviders = requiredOauthProvidersList.filter((provider) => !oauthProviderRecords[provider]);
|
|
7571
7500
|
const blockingToolManualIssues = toolManualIssues.filter((issue2) => issue2.severity === "error");
|
|
7572
7501
|
const errors = [
|
|
7573
7502
|
...manifestIssues.map((issue2) => String(issue2)),
|
|
@@ -7579,17 +7508,12 @@ async function registrationPreflight(project, client) {
|
|
|
7579
7508
|
if (!remoteQualityOk(remoteQuality)) {
|
|
7580
7509
|
errors.push(`remote Tool Manual quality is not publishable: ${remoteQuality.grade} (${remoteQuality.overall_score}/100)`);
|
|
7581
7510
|
}
|
|
7582
|
-
if (missingOauthProviders.length > 0) {
|
|
7583
|
-
errors.push(`oauth_credentials.json is required for platform-managed OAuth APIs: ${missingOauthProviders.join(", ")}`);
|
|
7584
|
-
}
|
|
7585
7511
|
const preflight = {
|
|
7586
7512
|
manifest_issues: manifestIssues,
|
|
7587
7513
|
tool_manual_valid: toolManualValid,
|
|
7588
7514
|
tool_manual_issues: toolManualIssues.map((issue2) => toJsonable(issue2)),
|
|
7589
7515
|
remote_quality: toJsonable(remoteQuality),
|
|
7590
|
-
|
|
7591
|
-
oauth_credentials_path: project.oauth_credentials_path ?? null,
|
|
7592
|
-
oauth_missing_providers: missingOauthProviders,
|
|
7516
|
+
retired_platform_oauth_providers: retiredPlatformOauthProviders,
|
|
7593
7517
|
ok: errors.length === 0
|
|
7594
7518
|
};
|
|
7595
7519
|
if (errors.length > 0) {
|
|
@@ -7628,8 +7552,6 @@ async function runRegistration(path = ".", options = {}, deps = {}) {
|
|
|
7628
7552
|
ensureExplicitToolManual(project);
|
|
7629
7553
|
ensureManifestPublisherIdentity(project);
|
|
7630
7554
|
ensureRuntimeValidationReady(project);
|
|
7631
|
-
ensureRequiredOauthCredentials(project);
|
|
7632
|
-
const canonicalOauthCredentials = canonicalOauthCredentialsPayload(project.oauth_credentials);
|
|
7633
7555
|
const client = await createClient(deps);
|
|
7634
7556
|
if (requestedCompanySlug) {
|
|
7635
7557
|
const slug = companyNameSlug(requestedCompanySlug);
|
|
@@ -7706,14 +7628,12 @@ async function runRegistration(path = ".", options = {}, deps = {}) {
|
|
|
7706
7628
|
}
|
|
7707
7629
|
}
|
|
7708
7630
|
const receipt = await client.auto_register(project.manifest, project.tool_manual, {
|
|
7709
|
-
runtime_validation: project.runtime_validation
|
|
7710
|
-
oauth_credentials: canonicalOauthCredentials
|
|
7631
|
+
runtime_validation: project.runtime_validation
|
|
7711
7632
|
});
|
|
7712
7633
|
const result = {
|
|
7713
7634
|
receipt: toJsonable(receipt),
|
|
7714
7635
|
registration_preflight: preflight,
|
|
7715
|
-
runtime_validation_path: project.runtime_validation_path ?? null
|
|
7716
|
-
oauth_credentials_path: project.oauth_credentials_path ?? null
|
|
7636
|
+
runtime_validation_path: project.runtime_validation_path ?? null
|
|
7717
7637
|
};
|
|
7718
7638
|
if (developerPortalPreflight) {
|
|
7719
7639
|
result.developer_portal_preflight = developerPortalPreflight;
|
|
@@ -7734,7 +7654,6 @@ async function runPreflight(path = ".", deps = {}) {
|
|
|
7734
7654
|
ensureExplicitToolManual(project);
|
|
7735
7655
|
ensureManifestPublisherIdentity(project);
|
|
7736
7656
|
ensureRuntimeValidationReady(project);
|
|
7737
|
-
ensureRequiredOauthCredentials(project);
|
|
7738
7657
|
const client = await createClient(deps);
|
|
7739
7658
|
const preflight = await registrationPreflight(project, client);
|
|
7740
7659
|
let developerPortalPreflight = null;
|
|
@@ -7752,8 +7671,7 @@ async function runPreflight(path = ".", deps = {}) {
|
|
|
7752
7671
|
ok: true,
|
|
7753
7672
|
adapter_path: project.adapter_path,
|
|
7754
7673
|
registration_preflight: preflight,
|
|
7755
|
-
runtime_validation_path: project.runtime_validation_path ?? null
|
|
7756
|
-
oauth_credentials_path: project.oauth_credentials_path ?? null
|
|
7674
|
+
runtime_validation_path: project.runtime_validation_path ?? null
|
|
7757
7675
|
};
|
|
7758
7676
|
if (developerPortalPreflight) {
|
|
7759
7677
|
result.developer_portal_preflight = developerPortalPreflight;
|
|
@@ -8235,7 +8153,7 @@ function operationReadmeTemplate(operation, manifest, warning) {
|
|
|
8235
8153
|
"- `tool_manual.json`: machine-generated ToolManual scaffold",
|
|
8236
8154
|
"- `runtime_validation.json`: local public endpoint and review-key checks used by auto-register",
|
|
8237
8155
|
"- `docs/api-usage.md`: publishable API usage guide template for `docs_url`",
|
|
8238
|
-
"- `.gitignore`: keeps runtime review keys
|
|
8156
|
+
"- `.gitignore`: keeps runtime review keys out of Git",
|
|
8239
8157
|
"- `tests/test_adapter.ts`: smoke test for `AppTestHarness`",
|
|
8240
8158
|
"",
|
|
8241
8159
|
"Before registering, replace all generated placeholders:",
|
|
@@ -8243,8 +8161,8 @@ function operationReadmeTemplate(operation, manifest, warning) {
|
|
|
8243
8161
|
"- Replace `support_contact` with a real support email address or public support URL.",
|
|
8244
8162
|
"- Optional `seller_homepage_url` is the seller's official site and can stay blank.",
|
|
8245
8163
|
"- In the local `runtime_validation.json`, replace the public URL and review-key placeholders.",
|
|
8246
|
-
"- If the API uses
|
|
8247
|
-
"- Do not commit real review keys or
|
|
8164
|
+
"- If the API uses external OAuth, implement that flow in your API runtime and keep user tokens outside Siglume.",
|
|
8165
|
+
"- Do not commit real review keys or external-provider secrets; the generated `.gitignore` excludes local secret files.",
|
|
8248
8166
|
"- Because `runtime_validation.json` is ignored, GitHub samples do not commit review-key values.",
|
|
8249
8167
|
"",
|
|
8250
8168
|
"## Commands",
|
|
@@ -8320,8 +8238,6 @@ function generatedGitignore() {
|
|
|
8320
8238
|
"!.env.example",
|
|
8321
8239
|
"runtime_validation.json",
|
|
8322
8240
|
"runtime-validation.json",
|
|
8323
|
-
"oauth_credentials.json",
|
|
8324
|
-
"oauth-credentials.json",
|
|
8325
8241
|
"",
|
|
8326
8242
|
"# Python / test artifacts.",
|
|
8327
8243
|
"__pycache__/",
|
|
@@ -8467,13 +8383,6 @@ async function runHarnessForProject(project) {
|
|
|
8467
8383
|
checks.push(executionCheck("quote", await harness.execute_quote(task_type, { input_params: sample_input }), harness));
|
|
8468
8384
|
checks.push(executionCheck("payment", await harness.execute_payment(task_type, { input_params: sample_input }), harness));
|
|
8469
8385
|
}
|
|
8470
|
-
checks.push(
|
|
8471
|
-
executionCheck(
|
|
8472
|
-
"missing_account_simulation",
|
|
8473
|
-
await harness.simulate_connected_account_missing(task_type, { input_params: sample_input }),
|
|
8474
|
-
harness
|
|
8475
|
-
)
|
|
8476
|
-
);
|
|
8477
8386
|
return {
|
|
8478
8387
|
adapter_path: project.adapter_path,
|
|
8479
8388
|
task_type,
|
|
@@ -8576,15 +8485,6 @@ async function findRuntimeValidationPath(root_dir) {
|
|
|
8576
8485
|
}
|
|
8577
8486
|
return null;
|
|
8578
8487
|
}
|
|
8579
|
-
async function findOauthCredentialsPath(root_dir) {
|
|
8580
|
-
for (const name of ["oauth_credentials.json", "oauth-credentials.json"]) {
|
|
8581
|
-
const candidate = (0, import_node_path.join)(root_dir, name);
|
|
8582
|
-
if ((0, import_node_fs.existsSync)(candidate)) {
|
|
8583
|
-
return candidate;
|
|
8584
|
-
}
|
|
8585
|
-
}
|
|
8586
|
-
return null;
|
|
8587
|
-
}
|
|
8588
8488
|
async function loadJsonObject(path, label) {
|
|
8589
8489
|
let payload;
|
|
8590
8490
|
try {
|
|
@@ -8816,15 +8716,15 @@ function readmeTemplate(template) {
|
|
|
8816
8716
|
"- `tool_manual.json`: editable ToolManual draft for validation and registration",
|
|
8817
8717
|
"- `runtime_validation.json`: local live API smoke-test contract used during registration",
|
|
8818
8718
|
"- `docs/api-usage.md`: publish this page and use its public URL as `docs_url`",
|
|
8819
|
-
"- `.gitignore`: keeps runtime review keys
|
|
8719
|
+
"- `.gitignore`: keeps runtime review keys out of Git",
|
|
8820
8720
|
"",
|
|
8821
8721
|
"Before registering, replace all generated placeholders:",
|
|
8822
8722
|
"- In `adapter.ts` and `manifest.json`, replace `docs_url` with a dedicated public API usage guide, not a homepage.",
|
|
8823
8723
|
"- Replace `support_contact` with a real support email address or public support URL.",
|
|
8824
8724
|
"- Optional `seller_homepage_url` is the seller's official site and can stay blank.",
|
|
8825
8725
|
"- In the local `runtime_validation.json`, replace the public URL and review-key placeholders.",
|
|
8826
|
-
"- If the API uses
|
|
8827
|
-
"- Do not commit real review keys or
|
|
8726
|
+
"- If the API uses external OAuth, implement that flow in your API runtime and keep user tokens outside Siglume.",
|
|
8727
|
+
"- Do not commit real review keys or external-provider secrets; the generated `.gitignore` excludes local secret files.",
|
|
8828
8728
|
"- Because `runtime_validation.json` is ignored, GitHub samples do not commit review-key values.",
|
|
8829
8729
|
"",
|
|
8830
8730
|
"Suggested workflow:",
|
|
@@ -9042,7 +8942,6 @@ async function runCli(argv, deps = {}) {
|
|
|
9042
8942
|
emit(stdout, `preflight_quality: ${preflight.remote_quality.grade} (${preflight.remote_quality.overall_score}/100)`);
|
|
9043
8943
|
}
|
|
9044
8944
|
if (report.runtime_validation_path) emit(stdout, `runtime_validation_path: ${String(report.runtime_validation_path)}`);
|
|
9045
|
-
if (report.oauth_credentials_path) emit(stdout, `oauth_credentials_path: ${String(report.oauth_credentials_path)}`);
|
|
9046
8945
|
});
|
|
9047
8946
|
program.command("companies").description("List Siglume companies available for company-name publishing.").option("--json", "emit machine-readable JSON", false).action(async (options) => {
|
|
9048
8947
|
const report = await listCompanyPublishersReport(deps);
|
|
@@ -9093,7 +8992,6 @@ async function runCli(argv, deps = {}) {
|
|
|
9093
8992
|
emit(stdout, `listing_id: ${receipt.listing_id}`);
|
|
9094
8993
|
emit(stdout, `receipt_status: ${receipt.status}`);
|
|
9095
8994
|
if (receipt.listing_status) emit(stdout, `listing_status: ${receipt.listing_status}`);
|
|
9096
|
-
if (receipt.oauth_status) emit(stdout, `oauth_configured: ${Boolean(receipt.oauth_status.configured)}`);
|
|
9097
8995
|
if (receipt.review_url) emit(stdout, `review_url: ${receipt.review_url}`);
|
|
9098
8996
|
if (receipt.trace_id) emit(stdout, `trace_id: ${receipt.trace_id}`);
|
|
9099
8997
|
if (receipt.request_id) emit(stdout, `request_id: ${receipt.request_id}`);
|