@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/bin/siglume.cjs
CHANGED
|
@@ -176,6 +176,61 @@ var init_utils = __esm({
|
|
|
176
176
|
}
|
|
177
177
|
});
|
|
178
178
|
|
|
179
|
+
// src/types.ts
|
|
180
|
+
var PermissionClass, ApprovalMode, Environment, PriceModel, AppCategory, MINIMUM_JPY_OPERATION_PRICE_MINOR, ToolManualPermissionClass, SettlementMode;
|
|
181
|
+
var init_types = __esm({
|
|
182
|
+
"src/types.ts"() {
|
|
183
|
+
"use strict";
|
|
184
|
+
PermissionClass = {
|
|
185
|
+
READ_ONLY: "read-only",
|
|
186
|
+
ACTION: "action",
|
|
187
|
+
PAYMENT: "payment",
|
|
188
|
+
/** @deprecated Use READ_ONLY. Behaves identically. */
|
|
189
|
+
RECOMMENDATION: "recommendation"
|
|
190
|
+
};
|
|
191
|
+
ApprovalMode = {
|
|
192
|
+
AUTO: "auto",
|
|
193
|
+
BUDGET_BOUNDED: "budget-bounded",
|
|
194
|
+
ALWAYS_ASK: "always-ask",
|
|
195
|
+
DENY: "deny"
|
|
196
|
+
};
|
|
197
|
+
Environment = {
|
|
198
|
+
SANDBOX: "sandbox",
|
|
199
|
+
LIVE: "live"
|
|
200
|
+
};
|
|
201
|
+
PriceModel = {
|
|
202
|
+
FREE: "free",
|
|
203
|
+
SUBSCRIPTION: "subscription",
|
|
204
|
+
ONE_TIME: "one_time",
|
|
205
|
+
BUNDLE: "bundle",
|
|
206
|
+
USAGE_BASED: "usage_based",
|
|
207
|
+
PER_ACTION: "per_action"
|
|
208
|
+
};
|
|
209
|
+
AppCategory = {
|
|
210
|
+
COMMERCE: "commerce",
|
|
211
|
+
BOOKING: "booking",
|
|
212
|
+
CRM: "crm",
|
|
213
|
+
FINANCE: "finance",
|
|
214
|
+
DOCUMENT: "document",
|
|
215
|
+
COMMUNICATION: "communication",
|
|
216
|
+
MONITORING: "monitoring",
|
|
217
|
+
OTHER: "other"
|
|
218
|
+
};
|
|
219
|
+
MINIMUM_JPY_OPERATION_PRICE_MINOR = 15;
|
|
220
|
+
ToolManualPermissionClass = {
|
|
221
|
+
READ_ONLY: "read_only",
|
|
222
|
+
ACTION: "action",
|
|
223
|
+
PAYMENT: "payment"
|
|
224
|
+
};
|
|
225
|
+
SettlementMode = {
|
|
226
|
+
STRIPE_CHECKOUT: "stripe_checkout",
|
|
227
|
+
STRIPE_PAYMENT_INTENT: "stripe_payment_intent",
|
|
228
|
+
POLYGON_MANDATE: "polygon_mandate",
|
|
229
|
+
EMBEDDED_WALLET_CHARGE: "embedded_wallet_charge"
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
|
|
179
234
|
// src/webhooks.ts
|
|
180
235
|
function isRecord2(value) {
|
|
181
236
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -1297,6 +1352,58 @@ function validateSaveDataSchema(schema, fieldName) {
|
|
|
1297
1352
|
}
|
|
1298
1353
|
}
|
|
1299
1354
|
}
|
|
1355
|
+
function validatePricingPlanFloor(plan, defaultCurrency) {
|
|
1356
|
+
if (plan === void 0 || plan === null) {
|
|
1357
|
+
return;
|
|
1358
|
+
}
|
|
1359
|
+
if (!isRecord(plan)) {
|
|
1360
|
+
throw new SiglumeClientError("AppManifest.pricing_plan must be an object when provided.");
|
|
1361
|
+
}
|
|
1362
|
+
const items = plan.items;
|
|
1363
|
+
if (items === void 0 || items === null) {
|
|
1364
|
+
return;
|
|
1365
|
+
}
|
|
1366
|
+
if (!Array.isArray(items)) {
|
|
1367
|
+
throw new SiglumeClientError("AppManifest.pricing_plan.items must be an array when provided.");
|
|
1368
|
+
}
|
|
1369
|
+
const planCurrency = String(plan.currency ?? defaultCurrency ?? "").trim().toUpperCase();
|
|
1370
|
+
const seenKeys = /* @__PURE__ */ new Set();
|
|
1371
|
+
items.forEach((item, index) => {
|
|
1372
|
+
if (!isRecord(item)) {
|
|
1373
|
+
throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}] must be an object.`);
|
|
1374
|
+
}
|
|
1375
|
+
const itemKey = String(
|
|
1376
|
+
item.key ?? item.operation ?? item.operation_key ?? item.request_type ?? item.receipt_code ?? item.action ?? ""
|
|
1377
|
+
).trim();
|
|
1378
|
+
if (!itemKey) {
|
|
1379
|
+
throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}].key is required.`);
|
|
1380
|
+
}
|
|
1381
|
+
if (seenKeys.has(itemKey)) {
|
|
1382
|
+
throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}].key duplicates ${itemKey}.`);
|
|
1383
|
+
}
|
|
1384
|
+
seenKeys.add(itemKey);
|
|
1385
|
+
const amountRaw = item.price_minor ?? item.amount_minor ?? item.cost_minor ?? item.value_minor;
|
|
1386
|
+
if (amountRaw === void 0 || amountRaw === null) {
|
|
1387
|
+
throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}].price_minor is required.`);
|
|
1388
|
+
}
|
|
1389
|
+
const amountMinor = typeof amountRaw === "number" ? amountRaw : typeof amountRaw === "string" && amountRaw.trim() ? Number(amountRaw) : NaN;
|
|
1390
|
+
if (!Number.isInteger(amountMinor)) {
|
|
1391
|
+
throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}].price_minor must be an integer.`);
|
|
1392
|
+
}
|
|
1393
|
+
if (amountMinor < 0) {
|
|
1394
|
+
throw new SiglumeClientError(`AppManifest.pricing_plan.items[${index}].price_minor must be zero or positive.`);
|
|
1395
|
+
}
|
|
1396
|
+
const currency = String(item.currency ?? planCurrency ?? defaultCurrency ?? "").trim().toUpperCase();
|
|
1397
|
+
if (MINIMUM_JPY_OPERATION_PRICE_CURRENCIES.has(currency) && amountMinor > 0 && amountMinor < MINIMUM_JPY_OPERATION_PRICE_MINOR) {
|
|
1398
|
+
throw new SiglumeClientError(
|
|
1399
|
+
`AppManifest.pricing_plan.items[${index}].price_minor must be 0 or at least ${MINIMUM_JPY_OPERATION_PRICE_MINOR} for JPY/JPYC operation billing.`
|
|
1400
|
+
);
|
|
1401
|
+
}
|
|
1402
|
+
});
|
|
1403
|
+
}
|
|
1404
|
+
function pricingPlanHasItems(plan) {
|
|
1405
|
+
return isRecord(plan) && Array.isArray(plan.items) && plan.items.length > 0;
|
|
1406
|
+
}
|
|
1300
1407
|
function buildToolManualQualityReport(payload) {
|
|
1301
1408
|
const qualityBlock = isRecord(payload.quality) ? payload.quality : payload;
|
|
1302
1409
|
const issues = [];
|
|
@@ -1372,6 +1479,7 @@ function buildUrl(baseUrl, path, params) {
|
|
|
1372
1479
|
}
|
|
1373
1480
|
function parseListing(data) {
|
|
1374
1481
|
const metadata = isRecord(data.metadata) ? data.metadata : {};
|
|
1482
|
+
const pricing_plan = isRecord(data.pricing_plan) ? data.pricing_plan : isRecord(metadata.pricing_plan) ? metadata.pricing_plan : null;
|
|
1375
1483
|
const persistence = isRecord(data.persistence) ? data.persistence : isRecord(metadata.persistence) ? metadata.persistence : {};
|
|
1376
1484
|
return {
|
|
1377
1485
|
listing_id: String(data.listing_id ?? data.id ?? ""),
|
|
@@ -1385,6 +1493,7 @@ function parseListing(data) {
|
|
|
1385
1493
|
dry_run_supported: Boolean(data.dry_run_supported ?? false),
|
|
1386
1494
|
price_model: stringOrNull(data.price_model),
|
|
1387
1495
|
price_value_minor: Number(data.price_value_minor ?? 0),
|
|
1496
|
+
pricing_plan,
|
|
1388
1497
|
currency: String(data.currency ?? "USD"),
|
|
1389
1498
|
allow_free_trial: Boolean(data.allow_free_trial ?? false),
|
|
1390
1499
|
free_trial_duration_days: Number(data.free_trial_duration_days ?? 30),
|
|
@@ -1459,18 +1568,6 @@ function parseBundleMember(data) {
|
|
|
1459
1568
|
link_id: stringOrNull(data.link_id)
|
|
1460
1569
|
};
|
|
1461
1570
|
}
|
|
1462
|
-
function parseConnectedAccountLifecycle(data) {
|
|
1463
|
-
return {
|
|
1464
|
-
connected_account_id: String(data.connected_account_id ?? ""),
|
|
1465
|
-
provider_key: String(data.provider_key ?? ""),
|
|
1466
|
-
expires_at: stringOrNull(data.expires_at),
|
|
1467
|
-
scopes: Array.isArray(data.scopes) ? data.scopes.filter((s) => typeof s === "string") : [],
|
|
1468
|
-
refreshed_at: stringOrNull(data.refreshed_at),
|
|
1469
|
-
connection_status: stringOrNull(data.connection_status),
|
|
1470
|
-
provider_revoked: typeof data.provider_revoked === "boolean" ? data.provider_revoked : null,
|
|
1471
|
-
revoked_at: stringOrNull(data.revoked_at)
|
|
1472
|
-
};
|
|
1473
|
-
}
|
|
1474
1571
|
function parseBundle(data) {
|
|
1475
1572
|
const membersRaw = Array.isArray(data.members) ? data.members : [];
|
|
1476
1573
|
return {
|
|
@@ -1549,21 +1646,6 @@ function parseBinding(data) {
|
|
|
1549
1646
|
raw: { ...data }
|
|
1550
1647
|
};
|
|
1551
1648
|
}
|
|
1552
|
-
function parseConnectedAccount(data) {
|
|
1553
|
-
return {
|
|
1554
|
-
connected_account_id: String(data.connected_account_id ?? data.id ?? ""),
|
|
1555
|
-
provider_key: String(data.provider_key ?? ""),
|
|
1556
|
-
account_role: String(data.account_role ?? ""),
|
|
1557
|
-
display_name: stringOrNull(data.display_name),
|
|
1558
|
-
environment: stringOrNull(data.environment),
|
|
1559
|
-
connection_status: stringOrNull(data.connection_status),
|
|
1560
|
-
scopes: Array.isArray(data.scopes) ? data.scopes.filter((item) => typeof item === "string") : [],
|
|
1561
|
-
metadata: toRecord(data.metadata),
|
|
1562
|
-
created_at: stringOrNull(data.created_at),
|
|
1563
|
-
updated_at: stringOrNull(data.updated_at),
|
|
1564
|
-
raw: { ...data }
|
|
1565
|
-
};
|
|
1566
|
-
}
|
|
1567
1649
|
function parseSupportCase(data) {
|
|
1568
1650
|
return {
|
|
1569
1651
|
support_case_id: String(data.support_case_id ?? data.id ?? ""),
|
|
@@ -2509,10 +2591,11 @@ function cloneJsonLike(value) {
|
|
|
2509
2591
|
}
|
|
2510
2592
|
return value;
|
|
2511
2593
|
}
|
|
2512
|
-
var DEFAULT_SIGLUME_API_BASE, RETRYABLE_STATUS_CODES, CursorPageResult, SiglumeClient;
|
|
2594
|
+
var DEFAULT_SIGLUME_API_BASE, RETRYABLE_STATUS_CODES, MINIMUM_JPY_OPERATION_PRICE_CURRENCIES, CursorPageResult, SiglumeClient;
|
|
2513
2595
|
var init_client = __esm({
|
|
2514
2596
|
"src/client.ts"() {
|
|
2515
2597
|
"use strict";
|
|
2598
|
+
init_types();
|
|
2516
2599
|
init_errors();
|
|
2517
2600
|
init_webhooks();
|
|
2518
2601
|
init_web3();
|
|
@@ -2520,6 +2603,7 @@ var init_client = __esm({
|
|
|
2520
2603
|
init_utils();
|
|
2521
2604
|
DEFAULT_SIGLUME_API_BASE = "https://siglume.com/v1";
|
|
2522
2605
|
RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
2606
|
+
MINIMUM_JPY_OPERATION_PRICE_CURRENCIES = /* @__PURE__ */ new Set(["JPY", "JPYC"]);
|
|
2523
2607
|
CursorPageResult = class {
|
|
2524
2608
|
items;
|
|
2525
2609
|
next_cursor;
|
|
@@ -2602,13 +2686,6 @@ var init_client = __esm({
|
|
|
2602
2686
|
if (options.runtime_validation) {
|
|
2603
2687
|
payload.runtime_validation = coerceMapping(options.runtime_validation, "runtime_validation");
|
|
2604
2688
|
}
|
|
2605
|
-
if (options.oauth_credentials) {
|
|
2606
|
-
payload.oauth_credentials = Array.isArray(options.oauth_credentials) ? {
|
|
2607
|
-
items: options.oauth_credentials.map(
|
|
2608
|
-
(item, index) => coerceMapping(item, `oauth_credentials[${index}]`)
|
|
2609
|
-
)
|
|
2610
|
-
} : coerceMapping(options.oauth_credentials, "oauth_credentials");
|
|
2611
|
-
}
|
|
2612
2689
|
if (options.source_context) {
|
|
2613
2690
|
payload.source_context = coerceMapping(options.source_context, "source_context");
|
|
2614
2691
|
}
|
|
@@ -2634,6 +2711,7 @@ var init_client = __esm({
|
|
|
2634
2711
|
"jurisdiction",
|
|
2635
2712
|
"price_model",
|
|
2636
2713
|
"price_value_minor",
|
|
2714
|
+
"pricing_plan",
|
|
2637
2715
|
"currency",
|
|
2638
2716
|
"allow_free_trial",
|
|
2639
2717
|
"free_trial_duration_days",
|
|
@@ -2650,6 +2728,9 @@ var init_client = __esm({
|
|
|
2650
2728
|
payload[fieldName] = value;
|
|
2651
2729
|
}
|
|
2652
2730
|
}
|
|
2731
|
+
if (payload.pricing_plan !== void 0 && (typeof payload.pricing_plan !== "object" || Array.isArray(payload.pricing_plan))) {
|
|
2732
|
+
throw new SiglumeClientError("AppManifest.pricing_plan must be an object when provided.");
|
|
2733
|
+
}
|
|
2653
2734
|
if (payload.store_vertical === void 0 || payload.store_vertical === null) {
|
|
2654
2735
|
throw new SiglumeClientError(
|
|
2655
2736
|
"AppManifest.store_vertical is required. Choose 'api' for normal API Store listings or 'game' for API games."
|
|
@@ -2665,6 +2746,13 @@ var init_client = __esm({
|
|
|
2665
2746
|
throw new SiglumeClientError(`AppManifest.currency must be 'USD' or 'JPY'. Got ${String(payload.currency)}.`);
|
|
2666
2747
|
}
|
|
2667
2748
|
payload.currency = currency;
|
|
2749
|
+
if (payload.pricing_plan !== void 0) {
|
|
2750
|
+
validatePricingPlanFloor(payload.pricing_plan, currency);
|
|
2751
|
+
}
|
|
2752
|
+
const priceModel = String(payload.price_model ?? "free").trim().toLowerCase();
|
|
2753
|
+
if ((priceModel === "usage_based" || priceModel === "per_action") && !pricingPlanHasItems(payload.pricing_plan)) {
|
|
2754
|
+
throw new SiglumeClientError("AppManifest.pricing_plan.items is required for usage_based/per_action pricing.");
|
|
2755
|
+
}
|
|
2668
2756
|
if (payload.allow_free_trial === void 0 || payload.allow_free_trial === null) {
|
|
2669
2757
|
throw new SiglumeClientError(
|
|
2670
2758
|
"AppManifest.allow_free_trial is required. Pass true to offer a Plus/Pro buyer free trial or false to disable trials."
|
|
@@ -2738,7 +2826,6 @@ var init_client = __esm({
|
|
|
2738
2826
|
auto_manifest: toRecord(data.auto_manifest),
|
|
2739
2827
|
confidence: toRecord(data.confidence),
|
|
2740
2828
|
validation_report: toRecord(data.validation_report),
|
|
2741
|
-
oauth_status: toRecord(data.oauth_status),
|
|
2742
2829
|
review_url: stringOrNull(data.review_url),
|
|
2743
2830
|
trace_id: meta.trace_id,
|
|
2744
2831
|
request_id: meta.request_id
|
|
@@ -2914,66 +3001,9 @@ var init_client = __esm({
|
|
|
2914
3001
|
return parseBundle(data);
|
|
2915
3002
|
}
|
|
2916
3003
|
// ----- end bundles -------------------------------------------------------
|
|
2917
|
-
// ----- Connected accounts
|
|
2918
|
-
//
|
|
2919
|
-
|
|
2920
|
-
const body = {
|
|
2921
|
-
listing_id: input.listing_id,
|
|
2922
|
-
redirect_uri: input.redirect_uri
|
|
2923
|
-
};
|
|
2924
|
-
if (input.scopes !== void 0) body.scopes = input.scopes;
|
|
2925
|
-
if (input.account_role !== void 0) body.account_role = input.account_role;
|
|
2926
|
-
const [data] = await this.request("POST", "/me/connected-accounts/oauth/authorize", {
|
|
2927
|
-
json_body: body
|
|
2928
|
-
});
|
|
2929
|
-
return {
|
|
2930
|
-
authorize_url: String(data.authorize_url ?? ""),
|
|
2931
|
-
state: String(data.state ?? ""),
|
|
2932
|
-
provider_key: String(data.provider_key ?? ""),
|
|
2933
|
-
scopes: Array.isArray(data.scopes) ? data.scopes.filter((s) => typeof s === "string") : [],
|
|
2934
|
-
pkce_method: stringOrNull(data.pkce_method)
|
|
2935
|
-
};
|
|
2936
|
-
}
|
|
2937
|
-
async complete_connected_account_oauth(input) {
|
|
2938
|
-
const [data] = await this.request("POST", "/me/connected-accounts/oauth/callback", {
|
|
2939
|
-
json_body: { state: input.state, code: input.code }
|
|
2940
|
-
});
|
|
2941
|
-
return { ...data };
|
|
2942
|
-
}
|
|
2943
|
-
async refresh_connected_account(account_id) {
|
|
2944
|
-
const [data] = await this.request("POST", `/me/connected-accounts/${account_id}/refresh`);
|
|
2945
|
-
return parseConnectedAccountLifecycle(data);
|
|
2946
|
-
}
|
|
2947
|
-
async revoke_connected_account(account_id) {
|
|
2948
|
-
const [data] = await this.request("POST", `/me/connected-accounts/${account_id}/revoke`);
|
|
2949
|
-
return parseConnectedAccountLifecycle(data);
|
|
2950
|
-
}
|
|
2951
|
-
async set_listing_oauth_credentials(listing_id, input) {
|
|
2952
|
-
const body = {
|
|
2953
|
-
provider_key: input.provider_key,
|
|
2954
|
-
client_id: input.client_id,
|
|
2955
|
-
client_secret: input.client_secret,
|
|
2956
|
-
authorize_url: input.authorize_url,
|
|
2957
|
-
token_url: input.token_url
|
|
2958
|
-
};
|
|
2959
|
-
if (input.revoke_url !== void 0) body.revoke_url = input.revoke_url;
|
|
2960
|
-
if (input.display_name !== void 0) body.display_name = input.display_name;
|
|
2961
|
-
if (input.scope_separator !== void 0) body.scope_separator = input.scope_separator;
|
|
2962
|
-
if (input.token_endpoint_auth !== void 0) body.token_endpoint_auth = input.token_endpoint_auth;
|
|
2963
|
-
if (input.pkce_required !== void 0) body.pkce_required = input.pkce_required;
|
|
2964
|
-
if (input.refresh_supported !== void 0) body.refresh_supported = input.refresh_supported;
|
|
2965
|
-
if (input.available_scopes !== void 0) body.available_scopes = input.available_scopes;
|
|
2966
|
-
if (input.required_scopes !== void 0) body.required_scopes = input.required_scopes;
|
|
2967
|
-
const [data] = await this.request("PUT", `/market/capabilities/${listing_id}/oauth-credentials`, {
|
|
2968
|
-
json_body: body
|
|
2969
|
-
});
|
|
2970
|
-
return { ...data };
|
|
2971
|
-
}
|
|
2972
|
-
async get_listing_oauth_credentials_status(listing_id) {
|
|
2973
|
-
const [data] = await this.request("GET", `/market/capabilities/${listing_id}/oauth-credentials`);
|
|
2974
|
-
return { ...data };
|
|
2975
|
-
}
|
|
2976
|
-
// ----- end connected accounts --------------------------------------------
|
|
3004
|
+
// ----- Connected accounts ------------------------------------------------
|
|
3005
|
+
// Architecture B: publisher APIs own external OAuth and token storage.
|
|
3006
|
+
// The SDK no longer exposes platform OAuth or listing credential APIs.
|
|
2977
3007
|
async get_developer_portal() {
|
|
2978
3008
|
const [data, meta] = await this.request("GET", "/market/developer/portal");
|
|
2979
3009
|
return {
|
|
@@ -3006,7 +3036,6 @@ var init_client = __esm({
|
|
|
3006
3036
|
dry_run_supported: Boolean(data.dry_run_supported ?? false),
|
|
3007
3037
|
approval_mode: stringOrNull(data.approval_mode),
|
|
3008
3038
|
required_connected_accounts: Array.isArray(data.required_connected_accounts) ? data.required_connected_accounts : [],
|
|
3009
|
-
connected_accounts: Array.isArray(data.connected_accounts) ? data.connected_accounts.filter((item) => isRecord(item)).map((item) => ({ ...item })) : [],
|
|
3010
3039
|
stub_providers_enabled: Boolean(data.stub_providers_enabled ?? false),
|
|
3011
3040
|
simulated_receipts: Boolean(data.simulated_receipts ?? false),
|
|
3012
3041
|
approval_simulator: Boolean(data.approval_simulator ?? false),
|
|
@@ -4304,25 +4333,6 @@ var init_client = __esm({
|
|
|
4304
4333
|
raw: { ...data }
|
|
4305
4334
|
};
|
|
4306
4335
|
}
|
|
4307
|
-
async list_connected_accounts(options = {}) {
|
|
4308
|
-
const params = {
|
|
4309
|
-
provider_key: options.provider_key,
|
|
4310
|
-
environment: options.environment,
|
|
4311
|
-
limit: Math.max(1, Math.min(Math.trunc(options.limit ?? 50), 100)),
|
|
4312
|
-
cursor: options.cursor
|
|
4313
|
-
};
|
|
4314
|
-
const [data, meta] = await this.request("GET", "/market/connected-accounts", { params });
|
|
4315
|
-
const items = Array.isArray(data.items) ? data.items.filter((item) => isRecord(item)).map(parseConnectedAccount) : [];
|
|
4316
|
-
const next_cursor = stringOrNull(data.next_cursor);
|
|
4317
|
-
return new CursorPageResult({
|
|
4318
|
-
items,
|
|
4319
|
-
next_cursor,
|
|
4320
|
-
limit: typeof data.limit === "number" ? data.limit : params.limit,
|
|
4321
|
-
offset: typeof data.offset === "number" ? data.offset : null,
|
|
4322
|
-
meta,
|
|
4323
|
-
fetchNext: next_cursor ? (cursor) => this.list_connected_accounts({ ...options, cursor }) : void 0
|
|
4324
|
-
});
|
|
4325
|
-
}
|
|
4326
4336
|
async create_support_case(subject, body, options = {}) {
|
|
4327
4337
|
const summary = subject.trim();
|
|
4328
4338
|
const details = body.trim();
|
|
@@ -5417,53 +5427,8 @@ function stableValue(value) {
|
|
|
5417
5427
|
return value;
|
|
5418
5428
|
}
|
|
5419
5429
|
|
|
5420
|
-
// src/
|
|
5421
|
-
|
|
5422
|
-
READ_ONLY: "read-only",
|
|
5423
|
-
ACTION: "action",
|
|
5424
|
-
PAYMENT: "payment",
|
|
5425
|
-
/** @deprecated Use READ_ONLY. Behaves identically. */
|
|
5426
|
-
RECOMMENDATION: "recommendation"
|
|
5427
|
-
};
|
|
5428
|
-
var ApprovalMode = {
|
|
5429
|
-
AUTO: "auto",
|
|
5430
|
-
BUDGET_BOUNDED: "budget-bounded",
|
|
5431
|
-
ALWAYS_ASK: "always-ask",
|
|
5432
|
-
DENY: "deny"
|
|
5433
|
-
};
|
|
5434
|
-
var Environment = {
|
|
5435
|
-
SANDBOX: "sandbox",
|
|
5436
|
-
LIVE: "live"
|
|
5437
|
-
};
|
|
5438
|
-
var PriceModel = {
|
|
5439
|
-
FREE: "free",
|
|
5440
|
-
SUBSCRIPTION: "subscription",
|
|
5441
|
-
ONE_TIME: "one_time",
|
|
5442
|
-
BUNDLE: "bundle",
|
|
5443
|
-
USAGE_BASED: "usage_based",
|
|
5444
|
-
PER_ACTION: "per_action"
|
|
5445
|
-
};
|
|
5446
|
-
var AppCategory = {
|
|
5447
|
-
COMMERCE: "commerce",
|
|
5448
|
-
BOOKING: "booking",
|
|
5449
|
-
CRM: "crm",
|
|
5450
|
-
FINANCE: "finance",
|
|
5451
|
-
DOCUMENT: "document",
|
|
5452
|
-
COMMUNICATION: "communication",
|
|
5453
|
-
MONITORING: "monitoring",
|
|
5454
|
-
OTHER: "other"
|
|
5455
|
-
};
|
|
5456
|
-
var ToolManualPermissionClass = {
|
|
5457
|
-
READ_ONLY: "read_only",
|
|
5458
|
-
ACTION: "action",
|
|
5459
|
-
PAYMENT: "payment"
|
|
5460
|
-
};
|
|
5461
|
-
var SettlementMode = {
|
|
5462
|
-
STRIPE_CHECKOUT: "stripe_checkout",
|
|
5463
|
-
STRIPE_PAYMENT_INTENT: "stripe_payment_intent",
|
|
5464
|
-
POLYGON_MANDATE: "polygon_mandate",
|
|
5465
|
-
EMBEDDED_WALLET_CHARGE: "embedded_wallet_charge"
|
|
5466
|
-
};
|
|
5430
|
+
// src/runtime.ts
|
|
5431
|
+
init_types();
|
|
5467
5432
|
|
|
5468
5433
|
// src/testing/recorder.ts
|
|
5469
5434
|
var CASSETTE_VERSION = 1;
|
|
@@ -5855,6 +5820,7 @@ Actual: ${requestSignature(requestRecord, ignoreBodyFields)}`
|
|
|
5855
5820
|
};
|
|
5856
5821
|
|
|
5857
5822
|
// src/tool-manual-validator.ts
|
|
5823
|
+
init_types();
|
|
5858
5824
|
init_utils();
|
|
5859
5825
|
var JURISDICTION_PATTERN = /^[A-Z]{2}(-[A-Z0-9]{1,3})?$/;
|
|
5860
5826
|
var TOOL_NAME_RE = /^[A-Za-z0-9_]{3,64}$/;
|
|
@@ -6126,6 +6092,64 @@ function validate_tool_manual(manualInput) {
|
|
|
6126
6092
|
// src/runtime.ts
|
|
6127
6093
|
init_web3();
|
|
6128
6094
|
var CAPABILITY_KEY_RE = /^[a-z0-9][a-z0-9-]*[a-z0-9]$/;
|
|
6095
|
+
var MINIMUM_JPY_OPERATION_PRICE_CURRENCIES2 = /* @__PURE__ */ new Set(["JPY", "JPYC"]);
|
|
6096
|
+
function pricingPlanFloorIssues(plan, defaultCurrency) {
|
|
6097
|
+
const issues = [];
|
|
6098
|
+
if (plan === void 0 || plan === null) {
|
|
6099
|
+
return issues;
|
|
6100
|
+
}
|
|
6101
|
+
if (typeof plan !== "object" || Array.isArray(plan)) {
|
|
6102
|
+
return ["pricing_plan must be an object when provided"];
|
|
6103
|
+
}
|
|
6104
|
+
const record = plan;
|
|
6105
|
+
const items = record.items;
|
|
6106
|
+
if (items === void 0 || items === null) {
|
|
6107
|
+
return issues;
|
|
6108
|
+
}
|
|
6109
|
+
if (!Array.isArray(items)) {
|
|
6110
|
+
return ["pricing_plan.items must be an array when provided"];
|
|
6111
|
+
}
|
|
6112
|
+
const planCurrency = String(record.currency ?? defaultCurrency ?? "").trim().toUpperCase();
|
|
6113
|
+
const seenKeys = /* @__PURE__ */ new Set();
|
|
6114
|
+
items.forEach((item, index) => {
|
|
6115
|
+
if (typeof item !== "object" || item === null || Array.isArray(item)) {
|
|
6116
|
+
issues.push(`pricing_plan.items[${index}] must be an object`);
|
|
6117
|
+
return;
|
|
6118
|
+
}
|
|
6119
|
+
const itemRecord = item;
|
|
6120
|
+
const itemKey = String(
|
|
6121
|
+
itemRecord.key ?? itemRecord.operation ?? itemRecord.operation_key ?? itemRecord.request_type ?? itemRecord.receipt_code ?? itemRecord.action ?? ""
|
|
6122
|
+
).trim();
|
|
6123
|
+
if (!itemKey) {
|
|
6124
|
+
issues.push(`pricing_plan.items[${index}].key is required`);
|
|
6125
|
+
} else if (seenKeys.has(itemKey)) {
|
|
6126
|
+
issues.push(`pricing_plan.items[${index}].key duplicates ${itemKey}`);
|
|
6127
|
+
} else {
|
|
6128
|
+
seenKeys.add(itemKey);
|
|
6129
|
+
}
|
|
6130
|
+
const amountRaw = itemRecord.price_minor ?? itemRecord.amount_minor ?? itemRecord.cost_minor ?? itemRecord.value_minor;
|
|
6131
|
+
if (amountRaw === void 0 || amountRaw === null) {
|
|
6132
|
+
issues.push(`pricing_plan.items[${index}].price_minor is required`);
|
|
6133
|
+
return;
|
|
6134
|
+
}
|
|
6135
|
+
const amountMinor = typeof amountRaw === "number" ? amountRaw : typeof amountRaw === "string" && amountRaw.trim() ? Number(amountRaw) : NaN;
|
|
6136
|
+
if (!Number.isInteger(amountMinor)) {
|
|
6137
|
+
issues.push(`pricing_plan.items[${index}].price_minor must be an integer`);
|
|
6138
|
+
return;
|
|
6139
|
+
}
|
|
6140
|
+
if (amountMinor < 0) {
|
|
6141
|
+
issues.push(`pricing_plan.items[${index}].price_minor must be zero or positive`);
|
|
6142
|
+
return;
|
|
6143
|
+
}
|
|
6144
|
+
const currency = String(itemRecord.currency ?? planCurrency ?? defaultCurrency ?? "").trim().toUpperCase();
|
|
6145
|
+
if (MINIMUM_JPY_OPERATION_PRICE_CURRENCIES2.has(currency) && amountMinor > 0 && amountMinor < MINIMUM_JPY_OPERATION_PRICE_MINOR) {
|
|
6146
|
+
issues.push(
|
|
6147
|
+
`pricing_plan.items[${index}].price_minor must be 0 or at least ${MINIMUM_JPY_OPERATION_PRICE_MINOR} for JPY/JPYC operation billing`
|
|
6148
|
+
);
|
|
6149
|
+
}
|
|
6150
|
+
});
|
|
6151
|
+
return issues;
|
|
6152
|
+
}
|
|
6129
6153
|
function normalizeExecutionResult(result, executionKind) {
|
|
6130
6154
|
return {
|
|
6131
6155
|
success: Boolean(result.success),
|
|
@@ -6166,24 +6190,12 @@ var AppTestHarness = class {
|
|
|
6166
6190
|
this.stubs = stubs;
|
|
6167
6191
|
}
|
|
6168
6192
|
async executeWithKind(execution_kind, task_type = "default", options = {}) {
|
|
6169
|
-
const connected_accounts = options.connected_accounts ?? Object.fromEntries(
|
|
6170
|
-
Object.keys(this.stubs).map((key) => [
|
|
6171
|
-
key,
|
|
6172
|
-
{
|
|
6173
|
-
provider_key: key,
|
|
6174
|
-
session_token: `stub-token-${key}`,
|
|
6175
|
-
environment: Environment.SANDBOX,
|
|
6176
|
-
scopes: []
|
|
6177
|
-
}
|
|
6178
|
-
])
|
|
6179
|
-
);
|
|
6180
6193
|
const ctx = {
|
|
6181
6194
|
agent_id: "test-agent-001",
|
|
6182
6195
|
owner_user_id: "test-owner-001",
|
|
6183
6196
|
task_type,
|
|
6184
6197
|
environment: Environment.SANDBOX,
|
|
6185
6198
|
execution_kind,
|
|
6186
|
-
connected_accounts,
|
|
6187
6199
|
input_params: options.input_params ?? {},
|
|
6188
6200
|
trace_id: options.trace_id,
|
|
6189
6201
|
idempotency_key: options.idempotency_key,
|
|
@@ -6225,6 +6237,10 @@ var AppTestHarness = class {
|
|
|
6225
6237
|
if (!manifest.example_prompts || manifest.example_prompts.length === 0) {
|
|
6226
6238
|
issues.push("at least one example_prompt is recommended");
|
|
6227
6239
|
}
|
|
6240
|
+
issues.push(...pricingPlanFloorIssues(manifest.pricing_plan, String(manifest.currency ?? "USD")));
|
|
6241
|
+
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)) {
|
|
6242
|
+
issues.push("pricing_plan.items is required for usage_based/per_action pricing");
|
|
6243
|
+
}
|
|
6228
6244
|
if (manifest.permission_class === PermissionClass.ACTION || manifest.permission_class === PermissionClass.PAYMENT) {
|
|
6229
6245
|
if (!manifest.dry_run_supported) {
|
|
6230
6246
|
issues.push("action/payment apps should support dry_run");
|
|
@@ -6273,12 +6289,6 @@ var AppTestHarness = class {
|
|
|
6273
6289
|
}
|
|
6274
6290
|
return issues;
|
|
6275
6291
|
}
|
|
6276
|
-
async simulate_connected_account_missing(task_type = "default", options = {}) {
|
|
6277
|
-
return this.executeWithKind("dry_run", task_type, {
|
|
6278
|
-
...options,
|
|
6279
|
-
connected_accounts: {}
|
|
6280
|
-
});
|
|
6281
|
-
}
|
|
6282
6292
|
async simulate_metering(record, options = {}) {
|
|
6283
6293
|
const { normalizeUsageRecord: normalizeUsageRecord2 } = await Promise.resolve().then(() => (init_metering(), metering_exports));
|
|
6284
6294
|
const manifest = await this.app.manifest();
|
|
@@ -6306,7 +6316,7 @@ var AppTestHarness = class {
|
|
|
6306
6316
|
};
|
|
6307
6317
|
}
|
|
6308
6318
|
return {
|
|
6309
|
-
experimental:
|
|
6319
|
+
experimental: false,
|
|
6310
6320
|
usage_record,
|
|
6311
6321
|
invoice_line_preview
|
|
6312
6322
|
};
|
|
@@ -7241,15 +7251,6 @@ async function loadProject(path = ".") {
|
|
|
7241
7251
|
const tool_manual = tool_manual_path ? JSON.parse(await (0, import_promises.readFile)(tool_manual_path, "utf8")) : buildToolManualTemplate(manifest);
|
|
7242
7252
|
const runtime_validation_path = await findRuntimeValidationPath(root_dir);
|
|
7243
7253
|
const runtime_validation = runtime_validation_path ? await loadJsonObject(runtime_validation_path, "runtime_validation") : void 0;
|
|
7244
|
-
const oauth_credentials_path = await findOauthCredentialsPath(root_dir);
|
|
7245
|
-
let oauth_credentials;
|
|
7246
|
-
if (oauth_credentials_path) {
|
|
7247
|
-
const parsed = JSON.parse(await (0, import_promises.readFile)(oauth_credentials_path, "utf8"));
|
|
7248
|
-
if (!isRecord(parsed) && !Array.isArray(parsed)) {
|
|
7249
|
-
throw new SiglumeProjectError("oauth_credentials must be a JSON object or array");
|
|
7250
|
-
}
|
|
7251
|
-
oauth_credentials = parsed;
|
|
7252
|
-
}
|
|
7253
7254
|
return {
|
|
7254
7255
|
root_dir,
|
|
7255
7256
|
adapter_path,
|
|
@@ -7258,9 +7259,7 @@ async function loadProject(path = ".") {
|
|
|
7258
7259
|
tool_manual_path: tool_manual_path ?? void 0,
|
|
7259
7260
|
tool_manual,
|
|
7260
7261
|
runtime_validation_path: runtime_validation_path ?? void 0,
|
|
7261
|
-
runtime_validation
|
|
7262
|
-
oauth_credentials_path: oauth_credentials_path ?? void 0,
|
|
7263
|
-
oauth_credentials
|
|
7262
|
+
runtime_validation
|
|
7264
7263
|
};
|
|
7265
7264
|
}
|
|
7266
7265
|
function isPlatformManagedRequirement(value) {
|
|
@@ -7298,6 +7297,21 @@ function requiredOauthProviders(requirements) {
|
|
|
7298
7297
|
}
|
|
7299
7298
|
return providers;
|
|
7300
7299
|
}
|
|
7300
|
+
function apiManagedRequirementsMissingConnectUrl(requirements) {
|
|
7301
|
+
const missing = [];
|
|
7302
|
+
for (const item of requirements ?? []) {
|
|
7303
|
+
if (!isRecord(item)) continue;
|
|
7304
|
+
const managedBy = String(item.managed_by ?? "").trim().toLowerCase().replaceAll("_", "-");
|
|
7305
|
+
if (managedBy !== "api") continue;
|
|
7306
|
+
const connectUrl = String(item.connect_url ?? "").trim();
|
|
7307
|
+
if (connectUrl) continue;
|
|
7308
|
+
const label = oauthProviderKeyFromRequirement(item) ?? "(missing provider_key)";
|
|
7309
|
+
if (!missing.includes(label)) {
|
|
7310
|
+
missing.push(label);
|
|
7311
|
+
}
|
|
7312
|
+
}
|
|
7313
|
+
return missing;
|
|
7314
|
+
}
|
|
7301
7315
|
function connectedAccountRequirementLabel(value) {
|
|
7302
7316
|
if (isRecord(value)) {
|
|
7303
7317
|
for (const key of ["provider_key", "provider", "account_type", "name"]) {
|
|
@@ -7308,102 +7322,6 @@ function connectedAccountRequirementLabel(value) {
|
|
|
7308
7322
|
}
|
|
7309
7323
|
return String(value ?? "").trim();
|
|
7310
7324
|
}
|
|
7311
|
-
function oauthProviderRecordsMap(payload) {
|
|
7312
|
-
if (!payload) {
|
|
7313
|
-
return {};
|
|
7314
|
-
}
|
|
7315
|
-
const items = Array.isArray(payload) ? payload : Array.isArray(payload.items) ? payload.items : [payload];
|
|
7316
|
-
const resolved = {};
|
|
7317
|
-
for (const [index, item] of items.entries()) {
|
|
7318
|
-
if (!isRecord(item)) {
|
|
7319
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}] must be a JSON object.`);
|
|
7320
|
-
}
|
|
7321
|
-
const providerKey = oauthProviderKeyFromRequirement(item.provider_key ?? item.provider);
|
|
7322
|
-
if (!providerKey) {
|
|
7323
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}].provider_key is required.`);
|
|
7324
|
-
}
|
|
7325
|
-
const authorizeUrl = String(item.authorize_url ?? item.authorization_url ?? item.auth_url ?? "").trim();
|
|
7326
|
-
const tokenUrl = String(item.token_url ?? "").trim();
|
|
7327
|
-
if (!authorizeUrl || !tokenUrl) {
|
|
7328
|
-
throw new SiglumeProjectError(
|
|
7329
|
-
`oauth_credentials[${index}] must include authorize_url and token_url.`
|
|
7330
|
-
);
|
|
7331
|
-
}
|
|
7332
|
-
for (const [urlKey, urlValue] of Object.entries({
|
|
7333
|
-
authorize_url: authorizeUrl,
|
|
7334
|
-
token_url: tokenUrl,
|
|
7335
|
-
revoke_url: String(item.revoke_url ?? "").trim()
|
|
7336
|
-
})) {
|
|
7337
|
-
if (urlValue && !urlValue.startsWith("https://")) {
|
|
7338
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}].${urlKey} must be an https URL.`);
|
|
7339
|
-
}
|
|
7340
|
-
}
|
|
7341
|
-
const clientId = String(item.client_id ?? "").trim();
|
|
7342
|
-
const clientSecret = String(item.client_secret ?? "").trim();
|
|
7343
|
-
if (!clientId || !clientSecret) {
|
|
7344
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}] must include client_id and client_secret.`);
|
|
7345
|
-
}
|
|
7346
|
-
const rawScopes = item.required_scopes ?? item.scopes;
|
|
7347
|
-
let scopes = [];
|
|
7348
|
-
if (rawScopes == null) {
|
|
7349
|
-
scopes = [];
|
|
7350
|
-
} else if (!Array.isArray(rawScopes)) {
|
|
7351
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}].required_scopes must be a JSON array.`);
|
|
7352
|
-
} else {
|
|
7353
|
-
scopes = rawScopes.map((scope) => String(scope ?? "").trim()).filter(Boolean);
|
|
7354
|
-
}
|
|
7355
|
-
const record = {
|
|
7356
|
-
provider_key: providerKey,
|
|
7357
|
-
client_id: clientId,
|
|
7358
|
-
client_secret: clientSecret,
|
|
7359
|
-
required_scopes: scopes
|
|
7360
|
-
};
|
|
7361
|
-
for (const [key, value] of Object.entries({
|
|
7362
|
-
authorize_url: authorizeUrl,
|
|
7363
|
-
token_url: tokenUrl,
|
|
7364
|
-
revoke_url: String(item.revoke_url ?? "").trim(),
|
|
7365
|
-
display_name: String(item.display_name ?? "").trim(),
|
|
7366
|
-
scope_separator: String(item.scope_separator ?? "").trim(),
|
|
7367
|
-
token_endpoint_auth: String(item.token_endpoint_auth ?? "").trim()
|
|
7368
|
-
})) {
|
|
7369
|
-
if (value) record[key] = value;
|
|
7370
|
-
}
|
|
7371
|
-
for (const key of ["pkce_required", "refresh_supported"]) {
|
|
7372
|
-
if (typeof item[key] === "boolean") record[key] = item[key];
|
|
7373
|
-
}
|
|
7374
|
-
if (Array.isArray(item.available_scopes)) {
|
|
7375
|
-
const availableScopes = item.available_scopes.map((scope) => String(scope ?? "").trim()).filter(Boolean);
|
|
7376
|
-
if (availableScopes.length > 0) record.available_scopes = availableScopes;
|
|
7377
|
-
}
|
|
7378
|
-
resolved[providerKey] = record;
|
|
7379
|
-
}
|
|
7380
|
-
return resolved;
|
|
7381
|
-
}
|
|
7382
|
-
function canonicalOauthCredentialsPayload(payload) {
|
|
7383
|
-
const records = oauthProviderRecordsMap(payload);
|
|
7384
|
-
const providerKeys = Object.keys(records).sort();
|
|
7385
|
-
if (providerKeys.length === 0) {
|
|
7386
|
-
return void 0;
|
|
7387
|
-
}
|
|
7388
|
-
return {
|
|
7389
|
-
items: providerKeys.map((providerKey) => records[providerKey])
|
|
7390
|
-
};
|
|
7391
|
-
}
|
|
7392
|
-
function ensureRequiredOauthCredentials(project) {
|
|
7393
|
-
const requiredProviders = requiredOauthProviders(project.manifest.required_connected_accounts ?? []);
|
|
7394
|
-
if (requiredProviders.length === 0) {
|
|
7395
|
-
return;
|
|
7396
|
-
}
|
|
7397
|
-
const provided = new Set(Object.keys(oauthProviderRecordsMap(project.oauth_credentials)));
|
|
7398
|
-
const missing = requiredProviders.filter((provider) => !provided.has(provider));
|
|
7399
|
-
if (missing.length === 0) {
|
|
7400
|
-
return;
|
|
7401
|
-
}
|
|
7402
|
-
const path = project.oauth_credentials_path ?? (0, import_node_path.join)(project.root_dir, "oauth_credentials.json");
|
|
7403
|
-
throw new SiglumeProjectError(
|
|
7404
|
-
`${path} is required for platform-managed OAuth APIs. Missing provider seeds: ${missing.join(", ")}`
|
|
7405
|
-
);
|
|
7406
|
-
}
|
|
7407
7325
|
async function validateProject(path = ".", deps = {}) {
|
|
7408
7326
|
const project = await loadProject(path);
|
|
7409
7327
|
const manifest_issues = await projectValidationIssues(project);
|
|
@@ -7558,10 +7476,21 @@ function ensureExplicitToolManual(project) {
|
|
|
7558
7476
|
async function registrationPreflight(project, client) {
|
|
7559
7477
|
const manifestIssues = await projectValidationIssues(project);
|
|
7560
7478
|
const [toolManualValid, toolManualIssues] = validate_tool_manual(project.tool_manual);
|
|
7479
|
+
const retiredPlatformOauthProviders = requiredOauthProviders(project.manifest.required_connected_accounts ?? []);
|
|
7480
|
+
if (retiredPlatformOauthProviders.length > 0) {
|
|
7481
|
+
throw new SiglumeProjectError(
|
|
7482
|
+
`Registration preflight failed. Fix these before calling auto-register:
|
|
7483
|
+
- platform-managed OAuth is retired. Use managed_by="api" with connect_url: ${retiredPlatformOauthProviders.join(", ")}`
|
|
7484
|
+
);
|
|
7485
|
+
}
|
|
7486
|
+
const apiManagedMissingConnectUrl = apiManagedRequirementsMissingConnectUrl(project.manifest.required_connected_accounts ?? []);
|
|
7487
|
+
if (apiManagedMissingConnectUrl.length > 0) {
|
|
7488
|
+
throw new SiglumeProjectError(
|
|
7489
|
+
`Registration preflight failed. Fix these before calling auto-register:
|
|
7490
|
+
- API-managed OAuth requirements must include connect_url: ${apiManagedMissingConnectUrl.join(", ")}`
|
|
7491
|
+
);
|
|
7492
|
+
}
|
|
7561
7493
|
const remoteQuality = await client.preview_quality_score(project.tool_manual);
|
|
7562
|
-
const requiredOauthProvidersList = requiredOauthProviders(project.manifest.required_connected_accounts ?? []);
|
|
7563
|
-
const oauthProviderRecords = oauthProviderRecordsMap(project.oauth_credentials);
|
|
7564
|
-
const missingOauthProviders = requiredOauthProvidersList.filter((provider) => !oauthProviderRecords[provider]);
|
|
7565
7494
|
const blockingToolManualIssues = toolManualIssues.filter((issue2) => issue2.severity === "error");
|
|
7566
7495
|
const errors = [
|
|
7567
7496
|
...manifestIssues.map((issue2) => String(issue2)),
|
|
@@ -7573,17 +7502,12 @@ async function registrationPreflight(project, client) {
|
|
|
7573
7502
|
if (!remoteQualityOk(remoteQuality)) {
|
|
7574
7503
|
errors.push(`remote Tool Manual quality is not publishable: ${remoteQuality.grade} (${remoteQuality.overall_score}/100)`);
|
|
7575
7504
|
}
|
|
7576
|
-
if (missingOauthProviders.length > 0) {
|
|
7577
|
-
errors.push(`oauth_credentials.json is required for platform-managed OAuth APIs: ${missingOauthProviders.join(", ")}`);
|
|
7578
|
-
}
|
|
7579
7505
|
const preflight = {
|
|
7580
7506
|
manifest_issues: manifestIssues,
|
|
7581
7507
|
tool_manual_valid: toolManualValid,
|
|
7582
7508
|
tool_manual_issues: toolManualIssues.map((issue2) => toJsonable(issue2)),
|
|
7583
7509
|
remote_quality: toJsonable(remoteQuality),
|
|
7584
|
-
|
|
7585
|
-
oauth_credentials_path: project.oauth_credentials_path ?? null,
|
|
7586
|
-
oauth_missing_providers: missingOauthProviders,
|
|
7510
|
+
retired_platform_oauth_providers: retiredPlatformOauthProviders,
|
|
7587
7511
|
ok: errors.length === 0
|
|
7588
7512
|
};
|
|
7589
7513
|
if (errors.length > 0) {
|
|
@@ -7622,8 +7546,6 @@ async function runRegistration(path = ".", options = {}, deps = {}) {
|
|
|
7622
7546
|
ensureExplicitToolManual(project);
|
|
7623
7547
|
ensureManifestPublisherIdentity(project);
|
|
7624
7548
|
ensureRuntimeValidationReady(project);
|
|
7625
|
-
ensureRequiredOauthCredentials(project);
|
|
7626
|
-
const canonicalOauthCredentials = canonicalOauthCredentialsPayload(project.oauth_credentials);
|
|
7627
7549
|
const client = await createClient(deps);
|
|
7628
7550
|
if (requestedCompanySlug) {
|
|
7629
7551
|
const slug = companyNameSlug(requestedCompanySlug);
|
|
@@ -7700,14 +7622,12 @@ async function runRegistration(path = ".", options = {}, deps = {}) {
|
|
|
7700
7622
|
}
|
|
7701
7623
|
}
|
|
7702
7624
|
const receipt = await client.auto_register(project.manifest, project.tool_manual, {
|
|
7703
|
-
runtime_validation: project.runtime_validation
|
|
7704
|
-
oauth_credentials: canonicalOauthCredentials
|
|
7625
|
+
runtime_validation: project.runtime_validation
|
|
7705
7626
|
});
|
|
7706
7627
|
const result = {
|
|
7707
7628
|
receipt: toJsonable(receipt),
|
|
7708
7629
|
registration_preflight: preflight,
|
|
7709
|
-
runtime_validation_path: project.runtime_validation_path ?? null
|
|
7710
|
-
oauth_credentials_path: project.oauth_credentials_path ?? null
|
|
7630
|
+
runtime_validation_path: project.runtime_validation_path ?? null
|
|
7711
7631
|
};
|
|
7712
7632
|
if (developerPortalPreflight) {
|
|
7713
7633
|
result.developer_portal_preflight = developerPortalPreflight;
|
|
@@ -7728,7 +7648,6 @@ async function runPreflight(path = ".", deps = {}) {
|
|
|
7728
7648
|
ensureExplicitToolManual(project);
|
|
7729
7649
|
ensureManifestPublisherIdentity(project);
|
|
7730
7650
|
ensureRuntimeValidationReady(project);
|
|
7731
|
-
ensureRequiredOauthCredentials(project);
|
|
7732
7651
|
const client = await createClient(deps);
|
|
7733
7652
|
const preflight = await registrationPreflight(project, client);
|
|
7734
7653
|
let developerPortalPreflight = null;
|
|
@@ -7746,8 +7665,7 @@ async function runPreflight(path = ".", deps = {}) {
|
|
|
7746
7665
|
ok: true,
|
|
7747
7666
|
adapter_path: project.adapter_path,
|
|
7748
7667
|
registration_preflight: preflight,
|
|
7749
|
-
runtime_validation_path: project.runtime_validation_path ?? null
|
|
7750
|
-
oauth_credentials_path: project.oauth_credentials_path ?? null
|
|
7668
|
+
runtime_validation_path: project.runtime_validation_path ?? null
|
|
7751
7669
|
};
|
|
7752
7670
|
if (developerPortalPreflight) {
|
|
7753
7671
|
result.developer_portal_preflight = developerPortalPreflight;
|
|
@@ -8229,7 +8147,7 @@ function operationReadmeTemplate(operation, manifest, warning) {
|
|
|
8229
8147
|
"- `tool_manual.json`: machine-generated ToolManual scaffold",
|
|
8230
8148
|
"- `runtime_validation.json`: local public endpoint and review-key checks used by auto-register",
|
|
8231
8149
|
"- `docs/api-usage.md`: publishable API usage guide template for `docs_url`",
|
|
8232
|
-
"- `.gitignore`: keeps runtime review keys
|
|
8150
|
+
"- `.gitignore`: keeps runtime review keys out of Git",
|
|
8233
8151
|
"- `tests/test_adapter.ts`: smoke test for `AppTestHarness`",
|
|
8234
8152
|
"",
|
|
8235
8153
|
"Before registering, replace all generated placeholders:",
|
|
@@ -8237,8 +8155,8 @@ function operationReadmeTemplate(operation, manifest, warning) {
|
|
|
8237
8155
|
"- Replace `support_contact` with a real support email address or public support URL.",
|
|
8238
8156
|
"- Optional `seller_homepage_url` is the seller's official site and can stay blank.",
|
|
8239
8157
|
"- In the local `runtime_validation.json`, replace the public URL and review-key placeholders.",
|
|
8240
|
-
"- If the API uses
|
|
8241
|
-
"- Do not commit real review keys or
|
|
8158
|
+
"- If the API uses external OAuth, implement that flow in your API runtime and keep user tokens outside Siglume.",
|
|
8159
|
+
"- Do not commit real review keys or external-provider secrets; the generated `.gitignore` excludes local secret files.",
|
|
8242
8160
|
"- Because `runtime_validation.json` is ignored, GitHub samples do not commit review-key values.",
|
|
8243
8161
|
"",
|
|
8244
8162
|
"## Commands",
|
|
@@ -8314,8 +8232,6 @@ function generatedGitignore() {
|
|
|
8314
8232
|
"!.env.example",
|
|
8315
8233
|
"runtime_validation.json",
|
|
8316
8234
|
"runtime-validation.json",
|
|
8317
|
-
"oauth_credentials.json",
|
|
8318
|
-
"oauth-credentials.json",
|
|
8319
8235
|
"",
|
|
8320
8236
|
"# Python / test artifacts.",
|
|
8321
8237
|
"__pycache__/",
|
|
@@ -8461,13 +8377,6 @@ async function runHarnessForProject(project) {
|
|
|
8461
8377
|
checks.push(executionCheck("quote", await harness.execute_quote(task_type, { input_params: sample_input }), harness));
|
|
8462
8378
|
checks.push(executionCheck("payment", await harness.execute_payment(task_type, { input_params: sample_input }), harness));
|
|
8463
8379
|
}
|
|
8464
|
-
checks.push(
|
|
8465
|
-
executionCheck(
|
|
8466
|
-
"missing_account_simulation",
|
|
8467
|
-
await harness.simulate_connected_account_missing(task_type, { input_params: sample_input }),
|
|
8468
|
-
harness
|
|
8469
|
-
)
|
|
8470
|
-
);
|
|
8471
8380
|
return {
|
|
8472
8381
|
adapter_path: project.adapter_path,
|
|
8473
8382
|
task_type,
|
|
@@ -8570,15 +8479,6 @@ async function findRuntimeValidationPath(root_dir) {
|
|
|
8570
8479
|
}
|
|
8571
8480
|
return null;
|
|
8572
8481
|
}
|
|
8573
|
-
async function findOauthCredentialsPath(root_dir) {
|
|
8574
|
-
for (const name of ["oauth_credentials.json", "oauth-credentials.json"]) {
|
|
8575
|
-
const candidate = (0, import_node_path.join)(root_dir, name);
|
|
8576
|
-
if ((0, import_node_fs.existsSync)(candidate)) {
|
|
8577
|
-
return candidate;
|
|
8578
|
-
}
|
|
8579
|
-
}
|
|
8580
|
-
return null;
|
|
8581
|
-
}
|
|
8582
8482
|
async function loadJsonObject(path, label) {
|
|
8583
8483
|
let payload;
|
|
8584
8484
|
try {
|
|
@@ -8810,15 +8710,15 @@ function readmeTemplate(template) {
|
|
|
8810
8710
|
"- `tool_manual.json`: editable ToolManual draft for validation and registration",
|
|
8811
8711
|
"- `runtime_validation.json`: local live API smoke-test contract used during registration",
|
|
8812
8712
|
"- `docs/api-usage.md`: publish this page and use its public URL as `docs_url`",
|
|
8813
|
-
"- `.gitignore`: keeps runtime review keys
|
|
8713
|
+
"- `.gitignore`: keeps runtime review keys out of Git",
|
|
8814
8714
|
"",
|
|
8815
8715
|
"Before registering, replace all generated placeholders:",
|
|
8816
8716
|
"- In `adapter.ts` and `manifest.json`, replace `docs_url` with a dedicated public API usage guide, not a homepage.",
|
|
8817
8717
|
"- Replace `support_contact` with a real support email address or public support URL.",
|
|
8818
8718
|
"- Optional `seller_homepage_url` is the seller's official site and can stay blank.",
|
|
8819
8719
|
"- In the local `runtime_validation.json`, replace the public URL and review-key placeholders.",
|
|
8820
|
-
"- If the API uses
|
|
8821
|
-
"- Do not commit real review keys or
|
|
8720
|
+
"- If the API uses external OAuth, implement that flow in your API runtime and keep user tokens outside Siglume.",
|
|
8721
|
+
"- Do not commit real review keys or external-provider secrets; the generated `.gitignore` excludes local secret files.",
|
|
8822
8722
|
"- Because `runtime_validation.json` is ignored, GitHub samples do not commit review-key values.",
|
|
8823
8723
|
"",
|
|
8824
8724
|
"Suggested workflow:",
|
|
@@ -9036,7 +8936,6 @@ async function runCli(argv, deps = {}) {
|
|
|
9036
8936
|
emit(stdout, `preflight_quality: ${preflight.remote_quality.grade} (${preflight.remote_quality.overall_score}/100)`);
|
|
9037
8937
|
}
|
|
9038
8938
|
if (report.runtime_validation_path) emit(stdout, `runtime_validation_path: ${String(report.runtime_validation_path)}`);
|
|
9039
|
-
if (report.oauth_credentials_path) emit(stdout, `oauth_credentials_path: ${String(report.oauth_credentials_path)}`);
|
|
9040
8939
|
});
|
|
9041
8940
|
program.command("companies").description("List Siglume companies available for company-name publishing.").option("--json", "emit machine-readable JSON", false).action(async (options) => {
|
|
9042
8941
|
const report = await listCompanyPublishersReport(deps);
|
|
@@ -9087,7 +8986,6 @@ async function runCli(argv, deps = {}) {
|
|
|
9087
8986
|
emit(stdout, `listing_id: ${receipt.listing_id}`);
|
|
9088
8987
|
emit(stdout, `receipt_status: ${receipt.status}`);
|
|
9089
8988
|
if (receipt.listing_status) emit(stdout, `listing_status: ${receipt.listing_status}`);
|
|
9090
|
-
if (receipt.oauth_status) emit(stdout, `oauth_configured: ${Boolean(receipt.oauth_status.configured)}`);
|
|
9091
8989
|
if (receipt.review_url) emit(stdout, `review_url: ${receipt.review_url}`);
|
|
9092
8990
|
if (receipt.trace_id) emit(stdout, `trace_id: ${receipt.trace_id}`);
|
|
9093
8991
|
if (receipt.request_id) emit(stdout, `request_id: ${receipt.request_id}`);
|