@siglume/api-sdk 0.10.7 → 1.0.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 +12 -6
- package/dist/bin/siglume.cjs +349 -295
- package/dist/bin/siglume.cjs.map +1 -1
- package/dist/bin/siglume.js +349 -295
- package/dist/bin/siglume.js.map +1 -1
- package/dist/cli/index.cjs +349 -295
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts +76 -65
- package/dist/cli/index.d.ts +76 -65
- package/dist/cli/index.js +349 -295
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +171 -134
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +89 -108
- package/dist/index.d.ts +89 -108
- package/dist/index.js +171 -134
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/bin/siglume.cjs
CHANGED
|
@@ -1247,6 +1247,56 @@ var init_operations = __esm({
|
|
|
1247
1247
|
});
|
|
1248
1248
|
|
|
1249
1249
|
// src/client.ts
|
|
1250
|
+
function validateManifestPersistenceContract(payload) {
|
|
1251
|
+
const vertical = String(payload.store_vertical ?? "").trim().toLowerCase();
|
|
1252
|
+
const persistence = payload.persistence;
|
|
1253
|
+
if (persistence === void 0 || persistence === null) {
|
|
1254
|
+
return;
|
|
1255
|
+
}
|
|
1256
|
+
if (!isRecord(persistence)) {
|
|
1257
|
+
throw new SiglumeClientError("AppManifest.persistence must be an object.");
|
|
1258
|
+
}
|
|
1259
|
+
const mode = String(persistence.mode ?? (vertical === "game" ? "platform" : "none")).trim().toLowerCase();
|
|
1260
|
+
if (!["none", "local", "platform", "developer_server"].includes(mode)) {
|
|
1261
|
+
throw new SiglumeClientError(
|
|
1262
|
+
"AppManifest.persistence.mode must be one of: none, local, platform, developer_server."
|
|
1263
|
+
);
|
|
1264
|
+
}
|
|
1265
|
+
const schema = persistence.save_data_schema;
|
|
1266
|
+
if (vertical === "game" && mode !== "none" && schema === void 0) {
|
|
1267
|
+
throw new SiglumeClientError(
|
|
1268
|
+
"AppManifest.persistence.save_data_schema is required when store_vertical='game' and persistence.mode is not 'none'."
|
|
1269
|
+
);
|
|
1270
|
+
}
|
|
1271
|
+
if (schema !== void 0) {
|
|
1272
|
+
validateSaveDataSchema(schema, "AppManifest.persistence.save_data_schema");
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
function validateSaveDataSchema(schema, fieldName) {
|
|
1276
|
+
if (!isRecord(schema)) {
|
|
1277
|
+
throw new SiglumeClientError(`${fieldName} must be a JSON Schema object.`);
|
|
1278
|
+
}
|
|
1279
|
+
const schemaSize = new TextEncoder().encode(JSON.stringify(schema)).length;
|
|
1280
|
+
if (schemaSize > 8192) {
|
|
1281
|
+
throw new SiglumeClientError(`${fieldName} must be at most 8192 bytes.`);
|
|
1282
|
+
}
|
|
1283
|
+
if (schema.type !== "object") {
|
|
1284
|
+
throw new SiglumeClientError(`${fieldName}.type must be 'object'.`);
|
|
1285
|
+
}
|
|
1286
|
+
const properties = schema.properties;
|
|
1287
|
+
if (!isRecord(properties) || Object.keys(properties).length === 0) {
|
|
1288
|
+
throw new SiglumeClientError(`${fieldName}.properties must be a non-empty object.`);
|
|
1289
|
+
}
|
|
1290
|
+
if (schema.required !== void 0) {
|
|
1291
|
+
if (!Array.isArray(schema.required) || !schema.required.every((item) => typeof item === "string")) {
|
|
1292
|
+
throw new SiglumeClientError(`${fieldName}.required must be an array of strings when provided.`);
|
|
1293
|
+
}
|
|
1294
|
+
const missing = schema.required.filter((item) => !(item in properties));
|
|
1295
|
+
if (missing.length > 0) {
|
|
1296
|
+
throw new SiglumeClientError(`${fieldName}.required references undefined properties: ${missing.join(", ")}.`);
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1250
1300
|
function buildToolManualQualityReport(payload) {
|
|
1251
1301
|
const qualityBlock = isRecord(payload.quality) ? payload.quality : payload;
|
|
1252
1302
|
const issues = [];
|
|
@@ -1321,6 +1371,8 @@ function buildUrl(baseUrl, path, params) {
|
|
|
1321
1371
|
return url.toString();
|
|
1322
1372
|
}
|
|
1323
1373
|
function parseListing(data) {
|
|
1374
|
+
const metadata = isRecord(data.metadata) ? data.metadata : {};
|
|
1375
|
+
const persistence = isRecord(data.persistence) ? data.persistence : isRecord(metadata.persistence) ? metadata.persistence : {};
|
|
1324
1376
|
return {
|
|
1325
1377
|
listing_id: String(data.listing_id ?? data.id ?? ""),
|
|
1326
1378
|
capability_key: String(data.capability_key ?? ""),
|
|
@@ -1343,14 +1395,59 @@ function parseListing(data) {
|
|
|
1343
1395
|
seller_display_name: stringOrNull(data.seller_display_name),
|
|
1344
1396
|
seller_homepage_url: stringOrNull(data.seller_homepage_url),
|
|
1345
1397
|
seller_social_url: stringOrNull(data.seller_social_url),
|
|
1398
|
+
publisher_type: stringOrNull(data.publisher_type),
|
|
1399
|
+
publisher_company_id: stringOrNull(data.publisher_company_id),
|
|
1400
|
+
company_id: stringOrNull(data.company_id),
|
|
1401
|
+
company_name: stringOrNull(data.company_name),
|
|
1402
|
+
company_publish_status: stringOrNull(data.company_publish_status),
|
|
1403
|
+
company_terms_version: stringOrNull(data.company_terms_version),
|
|
1346
1404
|
review_status: stringOrNull(data.review_status),
|
|
1347
1405
|
review_note: stringOrNull(data.review_note),
|
|
1348
1406
|
submission_blockers: Array.isArray(data.submission_blockers) ? data.submission_blockers.filter((item) => typeof item === "string") : [],
|
|
1407
|
+
persistence: { ...persistence },
|
|
1349
1408
|
created_at: stringOrNull(data.created_at),
|
|
1350
1409
|
updated_at: stringOrNull(data.updated_at),
|
|
1351
1410
|
raw: { ...data }
|
|
1352
1411
|
};
|
|
1353
1412
|
}
|
|
1413
|
+
function parseCompanyPublisher(data) {
|
|
1414
|
+
const wallets = Array.isArray(data.settlement_wallets) ? data.settlement_wallets.filter((item) => isRecord(item)) : [];
|
|
1415
|
+
return {
|
|
1416
|
+
company_id: String(data.company_id ?? data.id ?? ""),
|
|
1417
|
+
name: String(data.name ?? ""),
|
|
1418
|
+
status: String(data.status ?? ""),
|
|
1419
|
+
description: stringOrNull(data.description),
|
|
1420
|
+
is_founder: Boolean(data.is_founder ?? false),
|
|
1421
|
+
membership_role: stringOrNull(data.membership_role),
|
|
1422
|
+
membership_status: stringOrNull(data.membership_status),
|
|
1423
|
+
can_publish: Boolean(data.can_publish ?? true),
|
|
1424
|
+
can_approve: Boolean(data.can_approve ?? false),
|
|
1425
|
+
approval_required: Boolean(data.approval_required ?? false),
|
|
1426
|
+
paid_listing_allowed: Boolean(data.paid_listing_allowed ?? false),
|
|
1427
|
+
disabled_reasons: Array.isArray(data.disabled_reasons) ? data.disabled_reasons.filter((item) => typeof item === "string") : [],
|
|
1428
|
+
company_terms_version: stringOrNull(data.company_terms_version),
|
|
1429
|
+
active_listing_count: Number(data.active_listing_count ?? 0),
|
|
1430
|
+
pending_approval_count: Number(data.pending_approval_count ?? 0),
|
|
1431
|
+
settlement_wallet_ready: Boolean(data.settlement_wallet_ready ?? false),
|
|
1432
|
+
settlement_wallets: wallets.map((item) => ({ ...item })),
|
|
1433
|
+
raw: { ...data }
|
|
1434
|
+
};
|
|
1435
|
+
}
|
|
1436
|
+
function parseCapabilitySaveState(data) {
|
|
1437
|
+
return {
|
|
1438
|
+
capability_key: String(data.capability_key ?? ""),
|
|
1439
|
+
save_key: String(data.save_key ?? ""),
|
|
1440
|
+
schema_version: String(data.schema_version ?? "1"),
|
|
1441
|
+
revision: Number(data.revision ?? 0),
|
|
1442
|
+
payload: toRecord(data.payload),
|
|
1443
|
+
metadata: toRecord(data.metadata),
|
|
1444
|
+
checksum: stringOrNull(data.checksum),
|
|
1445
|
+
updated_at: stringOrNull(data.updated_at),
|
|
1446
|
+
created_at: stringOrNull(data.created_at),
|
|
1447
|
+
exists: Boolean(data.exists ?? false),
|
|
1448
|
+
raw: { ...data }
|
|
1449
|
+
};
|
|
1450
|
+
}
|
|
1354
1451
|
function parseBundleMember(data) {
|
|
1355
1452
|
return {
|
|
1356
1453
|
capability_listing_id: String(data.capability_listing_id ?? ""),
|
|
@@ -1362,18 +1459,6 @@ function parseBundleMember(data) {
|
|
|
1362
1459
|
link_id: stringOrNull(data.link_id)
|
|
1363
1460
|
};
|
|
1364
1461
|
}
|
|
1365
|
-
function parseConnectedAccountLifecycle(data) {
|
|
1366
|
-
return {
|
|
1367
|
-
connected_account_id: String(data.connected_account_id ?? ""),
|
|
1368
|
-
provider_key: String(data.provider_key ?? ""),
|
|
1369
|
-
expires_at: stringOrNull(data.expires_at),
|
|
1370
|
-
scopes: Array.isArray(data.scopes) ? data.scopes.filter((s) => typeof s === "string") : [],
|
|
1371
|
-
refreshed_at: stringOrNull(data.refreshed_at),
|
|
1372
|
-
connection_status: stringOrNull(data.connection_status),
|
|
1373
|
-
provider_revoked: typeof data.provider_revoked === "boolean" ? data.provider_revoked : null,
|
|
1374
|
-
revoked_at: stringOrNull(data.revoked_at)
|
|
1375
|
-
};
|
|
1376
|
-
}
|
|
1377
1462
|
function parseBundle(data) {
|
|
1378
1463
|
const membersRaw = Array.isArray(data.members) ? data.members : [];
|
|
1379
1464
|
return {
|
|
@@ -1452,21 +1537,6 @@ function parseBinding(data) {
|
|
|
1452
1537
|
raw: { ...data }
|
|
1453
1538
|
};
|
|
1454
1539
|
}
|
|
1455
|
-
function parseConnectedAccount(data) {
|
|
1456
|
-
return {
|
|
1457
|
-
connected_account_id: String(data.connected_account_id ?? data.id ?? ""),
|
|
1458
|
-
provider_key: String(data.provider_key ?? ""),
|
|
1459
|
-
account_role: String(data.account_role ?? ""),
|
|
1460
|
-
display_name: stringOrNull(data.display_name),
|
|
1461
|
-
environment: stringOrNull(data.environment),
|
|
1462
|
-
connection_status: stringOrNull(data.connection_status),
|
|
1463
|
-
scopes: Array.isArray(data.scopes) ? data.scopes.filter((item) => typeof item === "string") : [],
|
|
1464
|
-
metadata: toRecord(data.metadata),
|
|
1465
|
-
created_at: stringOrNull(data.created_at),
|
|
1466
|
-
updated_at: stringOrNull(data.updated_at),
|
|
1467
|
-
raw: { ...data }
|
|
1468
|
-
};
|
|
1469
|
-
}
|
|
1470
1540
|
function parseSupportCase(data) {
|
|
1471
1541
|
return {
|
|
1472
1542
|
support_case_id: String(data.support_case_id ?? data.id ?? ""),
|
|
@@ -2505,13 +2575,6 @@ var init_client = __esm({
|
|
|
2505
2575
|
if (options.runtime_validation) {
|
|
2506
2576
|
payload.runtime_validation = coerceMapping(options.runtime_validation, "runtime_validation");
|
|
2507
2577
|
}
|
|
2508
|
-
if (options.oauth_credentials) {
|
|
2509
|
-
payload.oauth_credentials = Array.isArray(options.oauth_credentials) ? {
|
|
2510
|
-
items: options.oauth_credentials.map(
|
|
2511
|
-
(item, index) => coerceMapping(item, `oauth_credentials[${index}]`)
|
|
2512
|
-
)
|
|
2513
|
-
} : coerceMapping(options.oauth_credentials, "oauth_credentials");
|
|
2514
|
-
}
|
|
2515
2578
|
if (options.source_context) {
|
|
2516
2579
|
payload.source_context = coerceMapping(options.source_context, "source_context");
|
|
2517
2580
|
}
|
|
@@ -2530,6 +2593,9 @@ var init_client = __esm({
|
|
|
2530
2593
|
"support_contact",
|
|
2531
2594
|
"seller_homepage_url",
|
|
2532
2595
|
"seller_social_url",
|
|
2596
|
+
"publisher_type",
|
|
2597
|
+
"company_id",
|
|
2598
|
+
"publisher_company_id",
|
|
2533
2599
|
"store_vertical",
|
|
2534
2600
|
"jurisdiction",
|
|
2535
2601
|
"price_model",
|
|
@@ -2542,7 +2608,8 @@ var init_client = __esm({
|
|
|
2542
2608
|
"dry_run_supported",
|
|
2543
2609
|
"required_connected_accounts",
|
|
2544
2610
|
"permission_scopes",
|
|
2545
|
-
"compatibility_tags"
|
|
2611
|
+
"compatibility_tags",
|
|
2612
|
+
"persistence"
|
|
2546
2613
|
]) {
|
|
2547
2614
|
const value = manifestPayload[fieldName];
|
|
2548
2615
|
if (value !== void 0 && value !== null) {
|
|
@@ -2582,6 +2649,26 @@ var init_client = __esm({
|
|
|
2582
2649
|
);
|
|
2583
2650
|
}
|
|
2584
2651
|
}
|
|
2652
|
+
const explicitPublisherType = payload.publisher_type !== void 0 && payload.publisher_type !== null;
|
|
2653
|
+
const companyId = String(payload.company_id ?? "").trim() || String(payload.publisher_company_id ?? "").trim();
|
|
2654
|
+
const publisherType = String(payload.publisher_type ?? "user").trim().toLowerCase();
|
|
2655
|
+
if (publisherType !== "user" && publisherType !== "company") {
|
|
2656
|
+
throw new SiglumeClientError("AppManifest.publisher_type must be 'user' or 'company'.");
|
|
2657
|
+
}
|
|
2658
|
+
if (publisherType === "company" && !companyId) {
|
|
2659
|
+
throw new SiglumeClientError("AppManifest.company_id is required when publisher_type='company'.");
|
|
2660
|
+
}
|
|
2661
|
+
if (publisherType === "user" && companyId) {
|
|
2662
|
+
throw new SiglumeClientError("AppManifest.company_id cannot be combined with publisher_type='user'.");
|
|
2663
|
+
}
|
|
2664
|
+
if (explicitPublisherType || companyId) {
|
|
2665
|
+
payload.publisher_type = publisherType;
|
|
2666
|
+
}
|
|
2667
|
+
if (companyId) {
|
|
2668
|
+
payload.company_id = companyId;
|
|
2669
|
+
payload.publisher_company_id = companyId;
|
|
2670
|
+
}
|
|
2671
|
+
validateManifestPersistenceContract(payload);
|
|
2585
2672
|
if (payload.manifest && typeof payload.manifest === "object") {
|
|
2586
2673
|
delete payload.manifest.version;
|
|
2587
2674
|
}
|
|
@@ -2617,7 +2704,6 @@ var init_client = __esm({
|
|
|
2617
2704
|
auto_manifest: toRecord(data.auto_manifest),
|
|
2618
2705
|
confidence: toRecord(data.confidence),
|
|
2619
2706
|
validation_report: toRecord(data.validation_report),
|
|
2620
|
-
oauth_status: toRecord(data.oauth_status),
|
|
2621
2707
|
review_url: stringOrNull(data.review_url),
|
|
2622
2708
|
trace_id: meta.trace_id,
|
|
2623
2709
|
request_id: meta.request_id
|
|
@@ -2689,6 +2775,45 @@ var init_client = __esm({
|
|
|
2689
2775
|
const [data] = await this.request("GET", `/market/capabilities/${listing_id}`);
|
|
2690
2776
|
return parseListing(data);
|
|
2691
2777
|
}
|
|
2778
|
+
async list_company_publishers() {
|
|
2779
|
+
const [data] = await this.request("GET", "/market/company-publishers");
|
|
2780
|
+
return Array.isArray(data.items) ? data.items.filter((item) => isRecord(item)).map(parseCompanyPublisher) : [];
|
|
2781
|
+
}
|
|
2782
|
+
async request_company_publish_approval(listing_id, note) {
|
|
2783
|
+
const [data] = await this.request("POST", `/market/capabilities/${listing_id}/company-publish-approval`, {
|
|
2784
|
+
json_body: note ? { note } : {}
|
|
2785
|
+
});
|
|
2786
|
+
return parseListing(data);
|
|
2787
|
+
}
|
|
2788
|
+
async decide_company_publish_approval(listing_id, options) {
|
|
2789
|
+
const [data] = await this.request("POST", `/market/capabilities/${listing_id}/company-publish-approval/decision`, {
|
|
2790
|
+
json_body: {
|
|
2791
|
+
decision: options.decision,
|
|
2792
|
+
...options.reason ? { reason: options.reason } : {}
|
|
2793
|
+
}
|
|
2794
|
+
});
|
|
2795
|
+
return parseListing(data);
|
|
2796
|
+
}
|
|
2797
|
+
async get_capability_state(capability_key, save_key = "default") {
|
|
2798
|
+
const [data] = await this.request("GET", `/market/capability-state/${capability_key}/${save_key}`);
|
|
2799
|
+
return parseCapabilitySaveState(data);
|
|
2800
|
+
}
|
|
2801
|
+
async put_capability_state(capability_key, save_key = "default", payload = {}, options = {}) {
|
|
2802
|
+
const body = {
|
|
2803
|
+
payload: toRecord(payload),
|
|
2804
|
+
schema_version: options.schema_version ?? "1",
|
|
2805
|
+
metadata: toRecord(options.metadata)
|
|
2806
|
+
};
|
|
2807
|
+
if (options.expected_revision !== void 0 && options.expected_revision !== null) {
|
|
2808
|
+
body.expected_revision = Math.trunc(options.expected_revision);
|
|
2809
|
+
}
|
|
2810
|
+
const [data] = await this.request("PUT", `/market/capability-state/${capability_key}/${save_key}`, { json_body: body });
|
|
2811
|
+
return parseCapabilitySaveState(data);
|
|
2812
|
+
}
|
|
2813
|
+
async delete_capability_state(capability_key, save_key = "default") {
|
|
2814
|
+
const [data] = await this.request("DELETE", `/market/capability-state/${capability_key}/${save_key}`);
|
|
2815
|
+
return parseCapabilitySaveState(data);
|
|
2816
|
+
}
|
|
2692
2817
|
// ----- Capability bundles (v0.7 track 2) ---------------------------------
|
|
2693
2818
|
async list_bundles(options = {}) {
|
|
2694
2819
|
const params = {
|
|
@@ -2754,66 +2879,9 @@ var init_client = __esm({
|
|
|
2754
2879
|
return parseBundle(data);
|
|
2755
2880
|
}
|
|
2756
2881
|
// ----- end bundles -------------------------------------------------------
|
|
2757
|
-
// ----- Connected accounts
|
|
2758
|
-
//
|
|
2759
|
-
|
|
2760
|
-
const body = {
|
|
2761
|
-
listing_id: input.listing_id,
|
|
2762
|
-
redirect_uri: input.redirect_uri
|
|
2763
|
-
};
|
|
2764
|
-
if (input.scopes !== void 0) body.scopes = input.scopes;
|
|
2765
|
-
if (input.account_role !== void 0) body.account_role = input.account_role;
|
|
2766
|
-
const [data] = await this.request("POST", "/me/connected-accounts/oauth/authorize", {
|
|
2767
|
-
json_body: body
|
|
2768
|
-
});
|
|
2769
|
-
return {
|
|
2770
|
-
authorize_url: String(data.authorize_url ?? ""),
|
|
2771
|
-
state: String(data.state ?? ""),
|
|
2772
|
-
provider_key: String(data.provider_key ?? ""),
|
|
2773
|
-
scopes: Array.isArray(data.scopes) ? data.scopes.filter((s) => typeof s === "string") : [],
|
|
2774
|
-
pkce_method: stringOrNull(data.pkce_method)
|
|
2775
|
-
};
|
|
2776
|
-
}
|
|
2777
|
-
async complete_connected_account_oauth(input) {
|
|
2778
|
-
const [data] = await this.request("POST", "/me/connected-accounts/oauth/callback", {
|
|
2779
|
-
json_body: { state: input.state, code: input.code }
|
|
2780
|
-
});
|
|
2781
|
-
return { ...data };
|
|
2782
|
-
}
|
|
2783
|
-
async refresh_connected_account(account_id) {
|
|
2784
|
-
const [data] = await this.request("POST", `/me/connected-accounts/${account_id}/refresh`);
|
|
2785
|
-
return parseConnectedAccountLifecycle(data);
|
|
2786
|
-
}
|
|
2787
|
-
async revoke_connected_account(account_id) {
|
|
2788
|
-
const [data] = await this.request("POST", `/me/connected-accounts/${account_id}/revoke`);
|
|
2789
|
-
return parseConnectedAccountLifecycle(data);
|
|
2790
|
-
}
|
|
2791
|
-
async set_listing_oauth_credentials(listing_id, input) {
|
|
2792
|
-
const body = {
|
|
2793
|
-
provider_key: input.provider_key,
|
|
2794
|
-
client_id: input.client_id,
|
|
2795
|
-
client_secret: input.client_secret,
|
|
2796
|
-
authorize_url: input.authorize_url,
|
|
2797
|
-
token_url: input.token_url
|
|
2798
|
-
};
|
|
2799
|
-
if (input.revoke_url !== void 0) body.revoke_url = input.revoke_url;
|
|
2800
|
-
if (input.display_name !== void 0) body.display_name = input.display_name;
|
|
2801
|
-
if (input.scope_separator !== void 0) body.scope_separator = input.scope_separator;
|
|
2802
|
-
if (input.token_endpoint_auth !== void 0) body.token_endpoint_auth = input.token_endpoint_auth;
|
|
2803
|
-
if (input.pkce_required !== void 0) body.pkce_required = input.pkce_required;
|
|
2804
|
-
if (input.refresh_supported !== void 0) body.refresh_supported = input.refresh_supported;
|
|
2805
|
-
if (input.available_scopes !== void 0) body.available_scopes = input.available_scopes;
|
|
2806
|
-
if (input.required_scopes !== void 0) body.required_scopes = input.required_scopes;
|
|
2807
|
-
const [data] = await this.request("PUT", `/market/capabilities/${listing_id}/oauth-credentials`, {
|
|
2808
|
-
json_body: body
|
|
2809
|
-
});
|
|
2810
|
-
return { ...data };
|
|
2811
|
-
}
|
|
2812
|
-
async get_listing_oauth_credentials_status(listing_id) {
|
|
2813
|
-
const [data] = await this.request("GET", `/market/capabilities/${listing_id}/oauth-credentials`);
|
|
2814
|
-
return { ...data };
|
|
2815
|
-
}
|
|
2816
|
-
// ----- end connected accounts --------------------------------------------
|
|
2882
|
+
// ----- Connected accounts ------------------------------------------------
|
|
2883
|
+
// Architecture B: publisher APIs own external OAuth and token storage.
|
|
2884
|
+
// The SDK no longer exposes platform OAuth or listing credential APIs.
|
|
2817
2885
|
async get_developer_portal() {
|
|
2818
2886
|
const [data, meta] = await this.request("GET", "/market/developer/portal");
|
|
2819
2887
|
return {
|
|
@@ -2846,7 +2914,6 @@ var init_client = __esm({
|
|
|
2846
2914
|
dry_run_supported: Boolean(data.dry_run_supported ?? false),
|
|
2847
2915
|
approval_mode: stringOrNull(data.approval_mode),
|
|
2848
2916
|
required_connected_accounts: Array.isArray(data.required_connected_accounts) ? data.required_connected_accounts : [],
|
|
2849
|
-
connected_accounts: Array.isArray(data.connected_accounts) ? data.connected_accounts.filter((item) => isRecord(item)).map((item) => ({ ...item })) : [],
|
|
2850
2917
|
stub_providers_enabled: Boolean(data.stub_providers_enabled ?? false),
|
|
2851
2918
|
simulated_receipts: Boolean(data.simulated_receipts ?? false),
|
|
2852
2919
|
approval_simulator: Boolean(data.approval_simulator ?? false),
|
|
@@ -4144,25 +4211,6 @@ var init_client = __esm({
|
|
|
4144
4211
|
raw: { ...data }
|
|
4145
4212
|
};
|
|
4146
4213
|
}
|
|
4147
|
-
async list_connected_accounts(options = {}) {
|
|
4148
|
-
const params = {
|
|
4149
|
-
provider_key: options.provider_key,
|
|
4150
|
-
environment: options.environment,
|
|
4151
|
-
limit: Math.max(1, Math.min(Math.trunc(options.limit ?? 50), 100)),
|
|
4152
|
-
cursor: options.cursor
|
|
4153
|
-
};
|
|
4154
|
-
const [data, meta] = await this.request("GET", "/market/connected-accounts", { params });
|
|
4155
|
-
const items = Array.isArray(data.items) ? data.items.filter((item) => isRecord(item)).map(parseConnectedAccount) : [];
|
|
4156
|
-
const next_cursor = stringOrNull(data.next_cursor);
|
|
4157
|
-
return new CursorPageResult({
|
|
4158
|
-
items,
|
|
4159
|
-
next_cursor,
|
|
4160
|
-
limit: typeof data.limit === "number" ? data.limit : params.limit,
|
|
4161
|
-
offset: typeof data.offset === "number" ? data.offset : null,
|
|
4162
|
-
meta,
|
|
4163
|
-
fetchNext: next_cursor ? (cursor) => this.list_connected_accounts({ ...options, cursor }) : void 0
|
|
4164
|
-
});
|
|
4165
|
-
}
|
|
4166
4214
|
async create_support_case(subject, body, options = {}) {
|
|
4167
4215
|
const summary = subject.trim();
|
|
4168
4216
|
const details = body.trim();
|
|
@@ -6006,24 +6054,12 @@ var AppTestHarness = class {
|
|
|
6006
6054
|
this.stubs = stubs;
|
|
6007
6055
|
}
|
|
6008
6056
|
async executeWithKind(execution_kind, task_type = "default", options = {}) {
|
|
6009
|
-
const connected_accounts = options.connected_accounts ?? Object.fromEntries(
|
|
6010
|
-
Object.keys(this.stubs).map((key) => [
|
|
6011
|
-
key,
|
|
6012
|
-
{
|
|
6013
|
-
provider_key: key,
|
|
6014
|
-
session_token: `stub-token-${key}`,
|
|
6015
|
-
environment: Environment.SANDBOX,
|
|
6016
|
-
scopes: []
|
|
6017
|
-
}
|
|
6018
|
-
])
|
|
6019
|
-
);
|
|
6020
6057
|
const ctx = {
|
|
6021
6058
|
agent_id: "test-agent-001",
|
|
6022
6059
|
owner_user_id: "test-owner-001",
|
|
6023
6060
|
task_type,
|
|
6024
6061
|
environment: Environment.SANDBOX,
|
|
6025
6062
|
execution_kind,
|
|
6026
|
-
connected_accounts,
|
|
6027
6063
|
input_params: options.input_params ?? {},
|
|
6028
6064
|
trace_id: options.trace_id,
|
|
6029
6065
|
idempotency_key: options.idempotency_key,
|
|
@@ -6113,12 +6149,6 @@ var AppTestHarness = class {
|
|
|
6113
6149
|
}
|
|
6114
6150
|
return issues;
|
|
6115
6151
|
}
|
|
6116
|
-
async simulate_connected_account_missing(task_type = "default", options = {}) {
|
|
6117
|
-
return this.executeWithKind("dry_run", task_type, {
|
|
6118
|
-
...options,
|
|
6119
|
-
connected_accounts: {}
|
|
6120
|
-
});
|
|
6121
|
-
}
|
|
6122
6152
|
async simulate_metering(record, options = {}) {
|
|
6123
6153
|
const { normalizeUsageRecord: normalizeUsageRecord2 } = await Promise.resolve().then(() => (init_metering(), metering_exports));
|
|
6124
6154
|
const manifest = await this.app.manifest();
|
|
@@ -7081,15 +7111,6 @@ async function loadProject(path = ".") {
|
|
|
7081
7111
|
const tool_manual = tool_manual_path ? JSON.parse(await (0, import_promises.readFile)(tool_manual_path, "utf8")) : buildToolManualTemplate(manifest);
|
|
7082
7112
|
const runtime_validation_path = await findRuntimeValidationPath(root_dir);
|
|
7083
7113
|
const runtime_validation = runtime_validation_path ? await loadJsonObject(runtime_validation_path, "runtime_validation") : void 0;
|
|
7084
|
-
const oauth_credentials_path = await findOauthCredentialsPath(root_dir);
|
|
7085
|
-
let oauth_credentials;
|
|
7086
|
-
if (oauth_credentials_path) {
|
|
7087
|
-
const parsed = JSON.parse(await (0, import_promises.readFile)(oauth_credentials_path, "utf8"));
|
|
7088
|
-
if (!isRecord(parsed) && !Array.isArray(parsed)) {
|
|
7089
|
-
throw new SiglumeProjectError("oauth_credentials must be a JSON object or array");
|
|
7090
|
-
}
|
|
7091
|
-
oauth_credentials = parsed;
|
|
7092
|
-
}
|
|
7093
7114
|
return {
|
|
7094
7115
|
root_dir,
|
|
7095
7116
|
adapter_path,
|
|
@@ -7098,9 +7119,7 @@ async function loadProject(path = ".") {
|
|
|
7098
7119
|
tool_manual_path: tool_manual_path ?? void 0,
|
|
7099
7120
|
tool_manual,
|
|
7100
7121
|
runtime_validation_path: runtime_validation_path ?? void 0,
|
|
7101
|
-
runtime_validation
|
|
7102
|
-
oauth_credentials_path: oauth_credentials_path ?? void 0,
|
|
7103
|
-
oauth_credentials
|
|
7122
|
+
runtime_validation
|
|
7104
7123
|
};
|
|
7105
7124
|
}
|
|
7106
7125
|
function isPlatformManagedRequirement(value) {
|
|
@@ -7138,6 +7157,21 @@ function requiredOauthProviders(requirements) {
|
|
|
7138
7157
|
}
|
|
7139
7158
|
return providers;
|
|
7140
7159
|
}
|
|
7160
|
+
function apiManagedRequirementsMissingConnectUrl(requirements) {
|
|
7161
|
+
const missing = [];
|
|
7162
|
+
for (const item of requirements ?? []) {
|
|
7163
|
+
if (!isRecord(item)) continue;
|
|
7164
|
+
const managedBy = String(item.managed_by ?? "").trim().toLowerCase().replaceAll("_", "-");
|
|
7165
|
+
if (managedBy !== "api") continue;
|
|
7166
|
+
const connectUrl = String(item.connect_url ?? "").trim();
|
|
7167
|
+
if (connectUrl) continue;
|
|
7168
|
+
const label = oauthProviderKeyFromRequirement(item) ?? "(missing provider_key)";
|
|
7169
|
+
if (!missing.includes(label)) {
|
|
7170
|
+
missing.push(label);
|
|
7171
|
+
}
|
|
7172
|
+
}
|
|
7173
|
+
return missing;
|
|
7174
|
+
}
|
|
7141
7175
|
function connectedAccountRequirementLabel(value) {
|
|
7142
7176
|
if (isRecord(value)) {
|
|
7143
7177
|
for (const key of ["provider_key", "provider", "account_type", "name"]) {
|
|
@@ -7148,102 +7182,6 @@ function connectedAccountRequirementLabel(value) {
|
|
|
7148
7182
|
}
|
|
7149
7183
|
return String(value ?? "").trim();
|
|
7150
7184
|
}
|
|
7151
|
-
function oauthProviderRecordsMap(payload) {
|
|
7152
|
-
if (!payload) {
|
|
7153
|
-
return {};
|
|
7154
|
-
}
|
|
7155
|
-
const items = Array.isArray(payload) ? payload : Array.isArray(payload.items) ? payload.items : [payload];
|
|
7156
|
-
const resolved = {};
|
|
7157
|
-
for (const [index, item] of items.entries()) {
|
|
7158
|
-
if (!isRecord(item)) {
|
|
7159
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}] must be a JSON object.`);
|
|
7160
|
-
}
|
|
7161
|
-
const providerKey = oauthProviderKeyFromRequirement(item.provider_key ?? item.provider);
|
|
7162
|
-
if (!providerKey) {
|
|
7163
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}].provider_key is required.`);
|
|
7164
|
-
}
|
|
7165
|
-
const authorizeUrl = String(item.authorize_url ?? item.authorization_url ?? item.auth_url ?? "").trim();
|
|
7166
|
-
const tokenUrl = String(item.token_url ?? "").trim();
|
|
7167
|
-
if (!authorizeUrl || !tokenUrl) {
|
|
7168
|
-
throw new SiglumeProjectError(
|
|
7169
|
-
`oauth_credentials[${index}] must include authorize_url and token_url.`
|
|
7170
|
-
);
|
|
7171
|
-
}
|
|
7172
|
-
for (const [urlKey, urlValue] of Object.entries({
|
|
7173
|
-
authorize_url: authorizeUrl,
|
|
7174
|
-
token_url: tokenUrl,
|
|
7175
|
-
revoke_url: String(item.revoke_url ?? "").trim()
|
|
7176
|
-
})) {
|
|
7177
|
-
if (urlValue && !urlValue.startsWith("https://")) {
|
|
7178
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}].${urlKey} must be an https URL.`);
|
|
7179
|
-
}
|
|
7180
|
-
}
|
|
7181
|
-
const clientId = String(item.client_id ?? "").trim();
|
|
7182
|
-
const clientSecret = String(item.client_secret ?? "").trim();
|
|
7183
|
-
if (!clientId || !clientSecret) {
|
|
7184
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}] must include client_id and client_secret.`);
|
|
7185
|
-
}
|
|
7186
|
-
const rawScopes = item.required_scopes ?? item.scopes;
|
|
7187
|
-
let scopes = [];
|
|
7188
|
-
if (rawScopes == null) {
|
|
7189
|
-
scopes = [];
|
|
7190
|
-
} else if (!Array.isArray(rawScopes)) {
|
|
7191
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}].required_scopes must be a JSON array.`);
|
|
7192
|
-
} else {
|
|
7193
|
-
scopes = rawScopes.map((scope) => String(scope ?? "").trim()).filter(Boolean);
|
|
7194
|
-
}
|
|
7195
|
-
const record = {
|
|
7196
|
-
provider_key: providerKey,
|
|
7197
|
-
client_id: clientId,
|
|
7198
|
-
client_secret: clientSecret,
|
|
7199
|
-
required_scopes: scopes
|
|
7200
|
-
};
|
|
7201
|
-
for (const [key, value] of Object.entries({
|
|
7202
|
-
authorize_url: authorizeUrl,
|
|
7203
|
-
token_url: tokenUrl,
|
|
7204
|
-
revoke_url: String(item.revoke_url ?? "").trim(),
|
|
7205
|
-
display_name: String(item.display_name ?? "").trim(),
|
|
7206
|
-
scope_separator: String(item.scope_separator ?? "").trim(),
|
|
7207
|
-
token_endpoint_auth: String(item.token_endpoint_auth ?? "").trim()
|
|
7208
|
-
})) {
|
|
7209
|
-
if (value) record[key] = value;
|
|
7210
|
-
}
|
|
7211
|
-
for (const key of ["pkce_required", "refresh_supported"]) {
|
|
7212
|
-
if (typeof item[key] === "boolean") record[key] = item[key];
|
|
7213
|
-
}
|
|
7214
|
-
if (Array.isArray(item.available_scopes)) {
|
|
7215
|
-
const availableScopes = item.available_scopes.map((scope) => String(scope ?? "").trim()).filter(Boolean);
|
|
7216
|
-
if (availableScopes.length > 0) record.available_scopes = availableScopes;
|
|
7217
|
-
}
|
|
7218
|
-
resolved[providerKey] = record;
|
|
7219
|
-
}
|
|
7220
|
-
return resolved;
|
|
7221
|
-
}
|
|
7222
|
-
function canonicalOauthCredentialsPayload(payload) {
|
|
7223
|
-
const records = oauthProviderRecordsMap(payload);
|
|
7224
|
-
const providerKeys = Object.keys(records).sort();
|
|
7225
|
-
if (providerKeys.length === 0) {
|
|
7226
|
-
return void 0;
|
|
7227
|
-
}
|
|
7228
|
-
return {
|
|
7229
|
-
items: providerKeys.map((providerKey) => records[providerKey])
|
|
7230
|
-
};
|
|
7231
|
-
}
|
|
7232
|
-
function ensureRequiredOauthCredentials(project) {
|
|
7233
|
-
const requiredProviders = requiredOauthProviders(project.manifest.required_connected_accounts ?? []);
|
|
7234
|
-
if (requiredProviders.length === 0) {
|
|
7235
|
-
return;
|
|
7236
|
-
}
|
|
7237
|
-
const provided = new Set(Object.keys(oauthProviderRecordsMap(project.oauth_credentials)));
|
|
7238
|
-
const missing = requiredProviders.filter((provider) => !provided.has(provider));
|
|
7239
|
-
if (missing.length === 0) {
|
|
7240
|
-
return;
|
|
7241
|
-
}
|
|
7242
|
-
const path = project.oauth_credentials_path ?? (0, import_node_path.join)(project.root_dir, "oauth_credentials.json");
|
|
7243
|
-
throw new SiglumeProjectError(
|
|
7244
|
-
`${path} is required for platform-managed OAuth APIs. Missing provider seeds: ${missing.join(", ")}`
|
|
7245
|
-
);
|
|
7246
|
-
}
|
|
7247
7185
|
async function validateProject(path = ".", deps = {}) {
|
|
7248
7186
|
const project = await loadProject(path);
|
|
7249
7187
|
const manifest_issues = await projectValidationIssues(project);
|
|
@@ -7283,7 +7221,12 @@ function ensureManifestPublisherIdentity(project) {
|
|
|
7283
7221
|
const sellerHomepageUrl = String(manifestPayload.seller_homepage_url ?? "").trim();
|
|
7284
7222
|
const sellerSocialUrl = String(manifestPayload.seller_social_url ?? "").trim();
|
|
7285
7223
|
const jurisdiction = String(manifestPayload.jurisdiction ?? "").trim();
|
|
7224
|
+
const companyId = String(manifestPayload.company_id ?? "").trim() || String(manifestPayload.publisher_company_id ?? "").trim();
|
|
7225
|
+
const publisherType = String(manifestPayload.publisher_type ?? "user").trim().toLowerCase();
|
|
7286
7226
|
const issues = [];
|
|
7227
|
+
if (companyId && publisherType !== "company") {
|
|
7228
|
+
issues.push('manifest.company_id requires manifest.publisher_type to be "company"');
|
|
7229
|
+
}
|
|
7287
7230
|
if (!docsUrl) {
|
|
7288
7231
|
issues.push("manifest.docs_url is required");
|
|
7289
7232
|
} else if (looksLikePlaceholder(docsUrl)) {
|
|
@@ -7393,10 +7336,21 @@ function ensureExplicitToolManual(project) {
|
|
|
7393
7336
|
async function registrationPreflight(project, client) {
|
|
7394
7337
|
const manifestIssues = await projectValidationIssues(project);
|
|
7395
7338
|
const [toolManualValid, toolManualIssues] = validate_tool_manual(project.tool_manual);
|
|
7339
|
+
const retiredPlatformOauthProviders = requiredOauthProviders(project.manifest.required_connected_accounts ?? []);
|
|
7340
|
+
if (retiredPlatformOauthProviders.length > 0) {
|
|
7341
|
+
throw new SiglumeProjectError(
|
|
7342
|
+
`Registration preflight failed. Fix these before calling auto-register:
|
|
7343
|
+
- platform-managed OAuth is retired. Use managed_by="api" with connect_url: ${retiredPlatformOauthProviders.join(", ")}`
|
|
7344
|
+
);
|
|
7345
|
+
}
|
|
7346
|
+
const apiManagedMissingConnectUrl = apiManagedRequirementsMissingConnectUrl(project.manifest.required_connected_accounts ?? []);
|
|
7347
|
+
if (apiManagedMissingConnectUrl.length > 0) {
|
|
7348
|
+
throw new SiglumeProjectError(
|
|
7349
|
+
`Registration preflight failed. Fix these before calling auto-register:
|
|
7350
|
+
- API-managed OAuth requirements must include connect_url: ${apiManagedMissingConnectUrl.join(", ")}`
|
|
7351
|
+
);
|
|
7352
|
+
}
|
|
7396
7353
|
const remoteQuality = await client.preview_quality_score(project.tool_manual);
|
|
7397
|
-
const requiredOauthProvidersList = requiredOauthProviders(project.manifest.required_connected_accounts ?? []);
|
|
7398
|
-
const oauthProviderRecords = oauthProviderRecordsMap(project.oauth_credentials);
|
|
7399
|
-
const missingOauthProviders = requiredOauthProvidersList.filter((provider) => !oauthProviderRecords[provider]);
|
|
7400
7354
|
const blockingToolManualIssues = toolManualIssues.filter((issue2) => issue2.severity === "error");
|
|
7401
7355
|
const errors = [
|
|
7402
7356
|
...manifestIssues.map((issue2) => String(issue2)),
|
|
@@ -7408,17 +7362,12 @@ async function registrationPreflight(project, client) {
|
|
|
7408
7362
|
if (!remoteQualityOk(remoteQuality)) {
|
|
7409
7363
|
errors.push(`remote Tool Manual quality is not publishable: ${remoteQuality.grade} (${remoteQuality.overall_score}/100)`);
|
|
7410
7364
|
}
|
|
7411
|
-
if (missingOauthProviders.length > 0) {
|
|
7412
|
-
errors.push(`oauth_credentials.json is required for platform-managed OAuth APIs: ${missingOauthProviders.join(", ")}`);
|
|
7413
|
-
}
|
|
7414
7365
|
const preflight = {
|
|
7415
7366
|
manifest_issues: manifestIssues,
|
|
7416
7367
|
tool_manual_valid: toolManualValid,
|
|
7417
7368
|
tool_manual_issues: toolManualIssues.map((issue2) => toJsonable(issue2)),
|
|
7418
7369
|
remote_quality: toJsonable(remoteQuality),
|
|
7419
|
-
|
|
7420
|
-
oauth_credentials_path: project.oauth_credentials_path ?? null,
|
|
7421
|
-
oauth_missing_providers: missingOauthProviders,
|
|
7370
|
+
retired_platform_oauth_providers: retiredPlatformOauthProviders,
|
|
7422
7371
|
ok: errors.length === 0
|
|
7423
7372
|
};
|
|
7424
7373
|
if (errors.length > 0) {
|
|
@@ -7429,35 +7378,116 @@ ${errors.map((error) => `- ${error}`).join("\n")}`
|
|
|
7429
7378
|
}
|
|
7430
7379
|
return preflight;
|
|
7431
7380
|
}
|
|
7381
|
+
function companyNameSlug(value) {
|
|
7382
|
+
return value.normalize("NFKD").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
7383
|
+
}
|
|
7432
7384
|
async function runRegistration(path = ".", options = {}, deps = {}) {
|
|
7433
7385
|
const project = await loadProject(path);
|
|
7386
|
+
let requestedCompanyId = String(options.company_id ?? "").trim();
|
|
7387
|
+
const requestedCompanySlug = String(options.company_slug ?? "").trim();
|
|
7388
|
+
let companyPublisherCandidates = null;
|
|
7389
|
+
if (requestedCompanySlug) {
|
|
7390
|
+
if (requestedCompanyId) {
|
|
7391
|
+
throw new SiglumeProjectError("--company and --company-slug cannot be combined.");
|
|
7392
|
+
}
|
|
7393
|
+
const slug = companyNameSlug(requestedCompanySlug);
|
|
7394
|
+
if (!slug && requestedCompanySlug !== requestedCompanyId) {
|
|
7395
|
+
throw new SiglumeProjectError(`Company slug ${requestedCompanySlug} is not slug-compatible; use --company <company_id> instead.`);
|
|
7396
|
+
}
|
|
7397
|
+
}
|
|
7398
|
+
if (requestedCompanyId) {
|
|
7399
|
+
project.manifest = {
|
|
7400
|
+
...project.manifest,
|
|
7401
|
+
publisher_type: "company",
|
|
7402
|
+
company_id: requestedCompanyId,
|
|
7403
|
+
publisher_company_id: requestedCompanyId
|
|
7404
|
+
};
|
|
7405
|
+
}
|
|
7434
7406
|
ensureExplicitToolManual(project);
|
|
7435
7407
|
ensureManifestPublisherIdentity(project);
|
|
7436
7408
|
ensureRuntimeValidationReady(project);
|
|
7437
|
-
ensureRequiredOauthCredentials(project);
|
|
7438
|
-
const canonicalOauthCredentials = canonicalOauthCredentialsPayload(project.oauth_credentials);
|
|
7439
7409
|
const client = await createClient(deps);
|
|
7410
|
+
if (requestedCompanySlug) {
|
|
7411
|
+
const slug = companyNameSlug(requestedCompanySlug);
|
|
7412
|
+
companyPublisherCandidates = await client.list_company_publishers();
|
|
7413
|
+
const matches = companyPublisherCandidates.filter(
|
|
7414
|
+
(item) => companyNameSlug(item.name || item.company_id) === slug || item.company_id === requestedCompanySlug
|
|
7415
|
+
);
|
|
7416
|
+
if (matches.length === 0) {
|
|
7417
|
+
throw new SiglumeProjectError(`Company slug ${requestedCompanySlug} is not available to this API key.`);
|
|
7418
|
+
}
|
|
7419
|
+
if (matches.length > 1) {
|
|
7420
|
+
throw new SiglumeProjectError(`Company slug ${requestedCompanySlug} is ambiguous; use --company <company_id> instead.`);
|
|
7421
|
+
}
|
|
7422
|
+
const match = matches[0];
|
|
7423
|
+
if (!match) {
|
|
7424
|
+
throw new SiglumeProjectError(`Company slug ${requestedCompanySlug} is not available to this API key.`);
|
|
7425
|
+
}
|
|
7426
|
+
if (match.can_publish === false) {
|
|
7427
|
+
const disabledReasons = match.disabled_reasons ?? [];
|
|
7428
|
+
const reasons = disabledReasons.length > 0 ? disabledReasons.join(", ") : "company publisher is disabled";
|
|
7429
|
+
throw new SiglumeProjectError(`Company ${match.company_id} cannot publish: ${reasons}.`);
|
|
7430
|
+
}
|
|
7431
|
+
requestedCompanyId = match.company_id;
|
|
7432
|
+
project.manifest = {
|
|
7433
|
+
...project.manifest,
|
|
7434
|
+
publisher_type: "company",
|
|
7435
|
+
company_id: requestedCompanyId,
|
|
7436
|
+
publisher_company_id: requestedCompanyId
|
|
7437
|
+
};
|
|
7438
|
+
}
|
|
7440
7439
|
const preflight = await registrationPreflight(project, client);
|
|
7440
|
+
let companyPublisherPreflight = null;
|
|
7441
|
+
const companyId = String(project.manifest.company_id ?? "").trim() || String(project.manifest.publisher_company_id ?? "").trim();
|
|
7442
|
+
const publisherType = String(project.manifest.publisher_type ?? "user").toLowerCase();
|
|
7443
|
+
if (publisherType === "company") {
|
|
7444
|
+
if (!companyId) {
|
|
7445
|
+
throw new SiglumeProjectError("Company registration requires --company <company_id> or manifest.company_id.");
|
|
7446
|
+
}
|
|
7447
|
+
const companies = companyPublisherCandidates ?? await client.list_company_publishers();
|
|
7448
|
+
companyPublisherCandidates = companies;
|
|
7449
|
+
const company = companies.find((item) => item.company_id === companyId);
|
|
7450
|
+
if (!company) {
|
|
7451
|
+
throw new SiglumeProjectError(`Company ${companyId} is not available to this API key.`);
|
|
7452
|
+
}
|
|
7453
|
+
if (company.can_publish === false) {
|
|
7454
|
+
const disabledReasons = company.disabled_reasons ?? [];
|
|
7455
|
+
const reasons = disabledReasons.length > 0 ? disabledReasons.join(", ") : "company publisher is disabled";
|
|
7456
|
+
throw new SiglumeProjectError(`Company ${companyId} cannot publish: ${reasons}.`);
|
|
7457
|
+
}
|
|
7458
|
+
companyPublisherPreflight = company;
|
|
7459
|
+
}
|
|
7441
7460
|
let developerPortalPreflight = null;
|
|
7442
7461
|
if (String(project.manifest.price_model ?? "free").toLowerCase() !== "free") {
|
|
7443
|
-
|
|
7444
|
-
|
|
7445
|
-
|
|
7446
|
-
|
|
7447
|
-
|
|
7448
|
-
)
|
|
7462
|
+
if (publisherType === "company") {
|
|
7463
|
+
const company = companyPublisherPreflight;
|
|
7464
|
+
if (!company) {
|
|
7465
|
+
throw new SiglumeProjectError(`Company ${companyId} is not available to this API key.`);
|
|
7466
|
+
}
|
|
7467
|
+
if (company.settlement_wallet_ready !== true) {
|
|
7468
|
+
throw new SiglumeProjectError(
|
|
7469
|
+
`Paid company registration requires a verified company settlement wallet for ${company.name}. Open the company settings and complete settlement readiness before registering.`
|
|
7470
|
+
);
|
|
7471
|
+
}
|
|
7472
|
+
developerPortalPreflight = { company_publisher: toJsonable(company) };
|
|
7473
|
+
} else {
|
|
7474
|
+
const portal = await client.get_developer_portal();
|
|
7475
|
+
const verifiedDestination = portal.payout_readiness?.verified_destination;
|
|
7476
|
+
if (verifiedDestination !== true) {
|
|
7477
|
+
throw new SiglumeProjectError(
|
|
7478
|
+
"Paid API registration requires a verified Polygon payout destination. Open https://siglume.com/owner/credits/payout and confirm the embedded-wallet payout token, or call GET /v1/market/developer/portal until payout_readiness.verified_destination is true."
|
|
7479
|
+
);
|
|
7480
|
+
}
|
|
7481
|
+
developerPortalPreflight = toJsonable(portal);
|
|
7449
7482
|
}
|
|
7450
|
-
developerPortalPreflight = toJsonable(portal);
|
|
7451
7483
|
}
|
|
7452
7484
|
const receipt = await client.auto_register(project.manifest, project.tool_manual, {
|
|
7453
|
-
runtime_validation: project.runtime_validation
|
|
7454
|
-
oauth_credentials: canonicalOauthCredentials
|
|
7485
|
+
runtime_validation: project.runtime_validation
|
|
7455
7486
|
});
|
|
7456
7487
|
const result = {
|
|
7457
7488
|
receipt: toJsonable(receipt),
|
|
7458
7489
|
registration_preflight: preflight,
|
|
7459
|
-
runtime_validation_path: project.runtime_validation_path ?? null
|
|
7460
|
-
oauth_credentials_path: project.oauth_credentials_path ?? null
|
|
7490
|
+
runtime_validation_path: project.runtime_validation_path ?? null
|
|
7461
7491
|
};
|
|
7462
7492
|
if (developerPortalPreflight) {
|
|
7463
7493
|
result.developer_portal_preflight = developerPortalPreflight;
|
|
@@ -7478,7 +7508,6 @@ async function runPreflight(path = ".", deps = {}) {
|
|
|
7478
7508
|
ensureExplicitToolManual(project);
|
|
7479
7509
|
ensureManifestPublisherIdentity(project);
|
|
7480
7510
|
ensureRuntimeValidationReady(project);
|
|
7481
|
-
ensureRequiredOauthCredentials(project);
|
|
7482
7511
|
const client = await createClient(deps);
|
|
7483
7512
|
const preflight = await registrationPreflight(project, client);
|
|
7484
7513
|
let developerPortalPreflight = null;
|
|
@@ -7496,8 +7525,7 @@ async function runPreflight(path = ".", deps = {}) {
|
|
|
7496
7525
|
ok: true,
|
|
7497
7526
|
adapter_path: project.adapter_path,
|
|
7498
7527
|
registration_preflight: preflight,
|
|
7499
|
-
runtime_validation_path: project.runtime_validation_path ?? null
|
|
7500
|
-
oauth_credentials_path: project.oauth_credentials_path ?? null
|
|
7528
|
+
runtime_validation_path: project.runtime_validation_path ?? null
|
|
7501
7529
|
};
|
|
7502
7530
|
if (developerPortalPreflight) {
|
|
7503
7531
|
result.developer_portal_preflight = developerPortalPreflight;
|
|
@@ -7520,6 +7548,14 @@ async function getUsageReport(options, deps = {}) {
|
|
|
7520
7548
|
count: items.length
|
|
7521
7549
|
};
|
|
7522
7550
|
}
|
|
7551
|
+
async function listCompanyPublishersReport(deps = {}) {
|
|
7552
|
+
const client = await createClient(deps);
|
|
7553
|
+
const companies = await client.list_company_publishers();
|
|
7554
|
+
return {
|
|
7555
|
+
companies: companies.map((item) => toJsonable(item)),
|
|
7556
|
+
count: companies.length
|
|
7557
|
+
};
|
|
7558
|
+
}
|
|
7523
7559
|
async function diffJsonFiles(oldPath, newPath) {
|
|
7524
7560
|
const oldPayload = await loadJsonDocument(oldPath);
|
|
7525
7561
|
const newPayload = await loadJsonDocument(newPath);
|
|
@@ -7971,7 +8007,7 @@ function operationReadmeTemplate(operation, manifest, warning) {
|
|
|
7971
8007
|
"- `tool_manual.json`: machine-generated ToolManual scaffold",
|
|
7972
8008
|
"- `runtime_validation.json`: local public endpoint and review-key checks used by auto-register",
|
|
7973
8009
|
"- `docs/api-usage.md`: publishable API usage guide template for `docs_url`",
|
|
7974
|
-
"- `.gitignore`: keeps runtime review keys
|
|
8010
|
+
"- `.gitignore`: keeps runtime review keys out of Git",
|
|
7975
8011
|
"- `tests/test_adapter.ts`: smoke test for `AppTestHarness`",
|
|
7976
8012
|
"",
|
|
7977
8013
|
"Before registering, replace all generated placeholders:",
|
|
@@ -7979,8 +8015,8 @@ function operationReadmeTemplate(operation, manifest, warning) {
|
|
|
7979
8015
|
"- Replace `support_contact` with a real support email address or public support URL.",
|
|
7980
8016
|
"- Optional `seller_homepage_url` is the seller's official site and can stay blank.",
|
|
7981
8017
|
"- In the local `runtime_validation.json`, replace the public URL and review-key placeholders.",
|
|
7982
|
-
"- If the API uses
|
|
7983
|
-
"- Do not commit real review keys or
|
|
8018
|
+
"- If the API uses external OAuth, implement that flow in your API runtime and keep user tokens outside Siglume.",
|
|
8019
|
+
"- Do not commit real review keys or external-provider secrets; the generated `.gitignore` excludes local secret files.",
|
|
7984
8020
|
"- Because `runtime_validation.json` is ignored, GitHub samples do not commit review-key values.",
|
|
7985
8021
|
"",
|
|
7986
8022
|
"## Commands",
|
|
@@ -8056,8 +8092,6 @@ function generatedGitignore() {
|
|
|
8056
8092
|
"!.env.example",
|
|
8057
8093
|
"runtime_validation.json",
|
|
8058
8094
|
"runtime-validation.json",
|
|
8059
|
-
"oauth_credentials.json",
|
|
8060
|
-
"oauth-credentials.json",
|
|
8061
8095
|
"",
|
|
8062
8096
|
"# Python / test artifacts.",
|
|
8063
8097
|
"__pycache__/",
|
|
@@ -8203,13 +8237,6 @@ async function runHarnessForProject(project) {
|
|
|
8203
8237
|
checks.push(executionCheck("quote", await harness.execute_quote(task_type, { input_params: sample_input }), harness));
|
|
8204
8238
|
checks.push(executionCheck("payment", await harness.execute_payment(task_type, { input_params: sample_input }), harness));
|
|
8205
8239
|
}
|
|
8206
|
-
checks.push(
|
|
8207
|
-
executionCheck(
|
|
8208
|
-
"missing_account_simulation",
|
|
8209
|
-
await harness.simulate_connected_account_missing(task_type, { input_params: sample_input }),
|
|
8210
|
-
harness
|
|
8211
|
-
)
|
|
8212
|
-
);
|
|
8213
8240
|
return {
|
|
8214
8241
|
adapter_path: project.adapter_path,
|
|
8215
8242
|
task_type,
|
|
@@ -8312,15 +8339,6 @@ async function findRuntimeValidationPath(root_dir) {
|
|
|
8312
8339
|
}
|
|
8313
8340
|
return null;
|
|
8314
8341
|
}
|
|
8315
|
-
async function findOauthCredentialsPath(root_dir) {
|
|
8316
|
-
for (const name of ["oauth_credentials.json", "oauth-credentials.json"]) {
|
|
8317
|
-
const candidate = (0, import_node_path.join)(root_dir, name);
|
|
8318
|
-
if ((0, import_node_fs.existsSync)(candidate)) {
|
|
8319
|
-
return candidate;
|
|
8320
|
-
}
|
|
8321
|
-
}
|
|
8322
|
-
return null;
|
|
8323
|
-
}
|
|
8324
8342
|
async function loadJsonObject(path, label) {
|
|
8325
8343
|
let payload;
|
|
8326
8344
|
try {
|
|
@@ -8552,15 +8570,15 @@ function readmeTemplate(template) {
|
|
|
8552
8570
|
"- `tool_manual.json`: editable ToolManual draft for validation and registration",
|
|
8553
8571
|
"- `runtime_validation.json`: local live API smoke-test contract used during registration",
|
|
8554
8572
|
"- `docs/api-usage.md`: publish this page and use its public URL as `docs_url`",
|
|
8555
|
-
"- `.gitignore`: keeps runtime review keys
|
|
8573
|
+
"- `.gitignore`: keeps runtime review keys out of Git",
|
|
8556
8574
|
"",
|
|
8557
8575
|
"Before registering, replace all generated placeholders:",
|
|
8558
8576
|
"- In `adapter.ts` and `manifest.json`, replace `docs_url` with a dedicated public API usage guide, not a homepage.",
|
|
8559
8577
|
"- Replace `support_contact` with a real support email address or public support URL.",
|
|
8560
8578
|
"- Optional `seller_homepage_url` is the seller's official site and can stay blank.",
|
|
8561
8579
|
"- In the local `runtime_validation.json`, replace the public URL and review-key placeholders.",
|
|
8562
|
-
"- If the API uses
|
|
8563
|
-
"- Do not commit real review keys or
|
|
8580
|
+
"- If the API uses external OAuth, implement that flow in your API runtime and keep user tokens outside Siglume.",
|
|
8581
|
+
"- Do not commit real review keys or external-provider secrets; the generated `.gitignore` excludes local secret files.",
|
|
8564
8582
|
"- Because `runtime_validation.json` is ignored, GitHub samples do not commit review-key values.",
|
|
8565
8583
|
"",
|
|
8566
8584
|
"Suggested workflow:",
|
|
@@ -8606,6 +8624,24 @@ function renderOperationTable(operations) {
|
|
|
8606
8624
|
...rows.map((row) => row.map((cell, index) => cell.padEnd(widths[index] ?? cell.length)).join(" "))
|
|
8607
8625
|
];
|
|
8608
8626
|
}
|
|
8627
|
+
function renderCompanyTable(companies) {
|
|
8628
|
+
const rows = companies.map((item) => [
|
|
8629
|
+
String(item.company_id ?? item.id ?? ""),
|
|
8630
|
+
String(item.name ?? ""),
|
|
8631
|
+
String(item.membership_role ?? (item.is_founder ? "founder" : "")),
|
|
8632
|
+
String(item.settlement_wallet_ready === true ? "ready" : "not_ready"),
|
|
8633
|
+
String(item.pending_approval_count ?? 0)
|
|
8634
|
+
]);
|
|
8635
|
+
const headers = ["company_id", "name", "role", "settlement", "pending"];
|
|
8636
|
+
const widths = headers.map(
|
|
8637
|
+
(header, index) => Math.max(header.length, ...rows.map((row) => row[index]?.length ?? 0))
|
|
8638
|
+
);
|
|
8639
|
+
return [
|
|
8640
|
+
headers.map((header, index) => header.padEnd(widths[index] ?? header.length)).join(" "),
|
|
8641
|
+
widths.map((width) => "-".repeat(width)).join(" "),
|
|
8642
|
+
...rows.map((row) => row.map((cell, index) => cell.padEnd(widths[index] ?? cell.length)).join(" "))
|
|
8643
|
+
];
|
|
8644
|
+
}
|
|
8609
8645
|
async function runCli(argv, deps = {}) {
|
|
8610
8646
|
const stdout = deps.stdout;
|
|
8611
8647
|
const stderr = deps.stderr ?? console.error;
|
|
@@ -8760,9 +8796,22 @@ async function runCli(argv, deps = {}) {
|
|
|
8760
8796
|
emit(stdout, `preflight_quality: ${preflight.remote_quality.grade} (${preflight.remote_quality.overall_score}/100)`);
|
|
8761
8797
|
}
|
|
8762
8798
|
if (report.runtime_validation_path) emit(stdout, `runtime_validation_path: ${String(report.runtime_validation_path)}`);
|
|
8763
|
-
if (report.oauth_credentials_path) emit(stdout, `oauth_credentials_path: ${String(report.oauth_credentials_path)}`);
|
|
8764
8799
|
});
|
|
8765
|
-
program.command("
|
|
8800
|
+
program.command("companies").description("List Siglume companies available for company-name publishing.").option("--json", "emit machine-readable JSON", false).action(async (options) => {
|
|
8801
|
+
const report = await listCompanyPublishersReport(deps);
|
|
8802
|
+
if (options.json) {
|
|
8803
|
+
emit(stdout, renderJson(report));
|
|
8804
|
+
return;
|
|
8805
|
+
}
|
|
8806
|
+
const companies = Array.isArray(report.companies) ? report.companies.filter((item) => Boolean(item && typeof item === "object")) : [];
|
|
8807
|
+
if (companies.length === 0) {
|
|
8808
|
+
emit(stdout, "No company publishers available for this API key.");
|
|
8809
|
+
return;
|
|
8810
|
+
}
|
|
8811
|
+
emit(stdout, "Company publishers");
|
|
8812
|
+
renderCompanyTable(companies).forEach((line) => emit(stdout, line));
|
|
8813
|
+
});
|
|
8814
|
+
program.command("register").option("--confirm", "explicitly confirm the registration; this is the default unless --draft-only is set", false).option("--draft-only", "create or refresh the draft without confirming publication", false).option("--submit-review", "legacy alias: publish immediately if your environment still routes through submit-review", false).option("--company <companyId>", "publish under a Siglume company name; revenue is split equally among active members", "").option("--company-slug <slug>", "publish under a Siglume company by matching the slugified company name", "").option("--json", "emit machine-readable JSON", false).argument("[path]", ".", "project path").action(async (path, options) => {
|
|
8766
8815
|
const draftOnly = Boolean(options.draftOnly);
|
|
8767
8816
|
if (draftOnly && options.confirm) {
|
|
8768
8817
|
throw new SiglumeProjectError("--draft-only cannot be combined with --confirm.");
|
|
@@ -8771,7 +8820,13 @@ async function runCli(argv, deps = {}) {
|
|
|
8771
8820
|
throw new SiglumeProjectError("--draft-only cannot be combined with --submit-review.");
|
|
8772
8821
|
}
|
|
8773
8822
|
const shouldConfirm = Boolean(options.confirm) || !draftOnly && !options.submitReview;
|
|
8774
|
-
const report = await runRegistration(path, {
|
|
8823
|
+
const report = await runRegistration(path, {
|
|
8824
|
+
confirm: shouldConfirm,
|
|
8825
|
+
draft_only: draftOnly,
|
|
8826
|
+
submit_review: options.submitReview,
|
|
8827
|
+
company_id: options.company,
|
|
8828
|
+
company_slug: options.companySlug
|
|
8829
|
+
}, deps);
|
|
8775
8830
|
if (options.json) {
|
|
8776
8831
|
emit(stdout, renderJson(report));
|
|
8777
8832
|
} else {
|
|
@@ -8791,7 +8846,6 @@ async function runCli(argv, deps = {}) {
|
|
|
8791
8846
|
emit(stdout, `listing_id: ${receipt.listing_id}`);
|
|
8792
8847
|
emit(stdout, `receipt_status: ${receipt.status}`);
|
|
8793
8848
|
if (receipt.listing_status) emit(stdout, `listing_status: ${receipt.listing_status}`);
|
|
8794
|
-
if (receipt.oauth_status) emit(stdout, `oauth_configured: ${Boolean(receipt.oauth_status.configured)}`);
|
|
8795
8849
|
if (receipt.review_url) emit(stdout, `review_url: ${receipt.review_url}`);
|
|
8796
8850
|
if (receipt.trace_id) emit(stdout, `trace_id: ${receipt.trace_id}`);
|
|
8797
8851
|
if (receipt.request_id) emit(stdout, `request_id: ${receipt.request_id}`);
|