@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/cli/index.cjs
CHANGED
|
@@ -1248,6 +1248,56 @@ var init_operations = __esm({
|
|
|
1248
1248
|
});
|
|
1249
1249
|
|
|
1250
1250
|
// src/client.ts
|
|
1251
|
+
function validateManifestPersistenceContract(payload) {
|
|
1252
|
+
const vertical = String(payload.store_vertical ?? "").trim().toLowerCase();
|
|
1253
|
+
const persistence = payload.persistence;
|
|
1254
|
+
if (persistence === void 0 || persistence === null) {
|
|
1255
|
+
return;
|
|
1256
|
+
}
|
|
1257
|
+
if (!isRecord(persistence)) {
|
|
1258
|
+
throw new SiglumeClientError("AppManifest.persistence must be an object.");
|
|
1259
|
+
}
|
|
1260
|
+
const mode = String(persistence.mode ?? (vertical === "game" ? "platform" : "none")).trim().toLowerCase();
|
|
1261
|
+
if (!["none", "local", "platform", "developer_server"].includes(mode)) {
|
|
1262
|
+
throw new SiglumeClientError(
|
|
1263
|
+
"AppManifest.persistence.mode must be one of: none, local, platform, developer_server."
|
|
1264
|
+
);
|
|
1265
|
+
}
|
|
1266
|
+
const schema = persistence.save_data_schema;
|
|
1267
|
+
if (vertical === "game" && mode !== "none" && schema === void 0) {
|
|
1268
|
+
throw new SiglumeClientError(
|
|
1269
|
+
"AppManifest.persistence.save_data_schema is required when store_vertical='game' and persistence.mode is not 'none'."
|
|
1270
|
+
);
|
|
1271
|
+
}
|
|
1272
|
+
if (schema !== void 0) {
|
|
1273
|
+
validateSaveDataSchema(schema, "AppManifest.persistence.save_data_schema");
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
function validateSaveDataSchema(schema, fieldName) {
|
|
1277
|
+
if (!isRecord(schema)) {
|
|
1278
|
+
throw new SiglumeClientError(`${fieldName} must be a JSON Schema object.`);
|
|
1279
|
+
}
|
|
1280
|
+
const schemaSize = new TextEncoder().encode(JSON.stringify(schema)).length;
|
|
1281
|
+
if (schemaSize > 8192) {
|
|
1282
|
+
throw new SiglumeClientError(`${fieldName} must be at most 8192 bytes.`);
|
|
1283
|
+
}
|
|
1284
|
+
if (schema.type !== "object") {
|
|
1285
|
+
throw new SiglumeClientError(`${fieldName}.type must be 'object'.`);
|
|
1286
|
+
}
|
|
1287
|
+
const properties = schema.properties;
|
|
1288
|
+
if (!isRecord(properties) || Object.keys(properties).length === 0) {
|
|
1289
|
+
throw new SiglumeClientError(`${fieldName}.properties must be a non-empty object.`);
|
|
1290
|
+
}
|
|
1291
|
+
if (schema.required !== void 0) {
|
|
1292
|
+
if (!Array.isArray(schema.required) || !schema.required.every((item) => typeof item === "string")) {
|
|
1293
|
+
throw new SiglumeClientError(`${fieldName}.required must be an array of strings when provided.`);
|
|
1294
|
+
}
|
|
1295
|
+
const missing = schema.required.filter((item) => !(item in properties));
|
|
1296
|
+
if (missing.length > 0) {
|
|
1297
|
+
throw new SiglumeClientError(`${fieldName}.required references undefined properties: ${missing.join(", ")}.`);
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1251
1301
|
function buildToolManualQualityReport(payload) {
|
|
1252
1302
|
const qualityBlock = isRecord(payload.quality) ? payload.quality : payload;
|
|
1253
1303
|
const issues = [];
|
|
@@ -1322,6 +1372,8 @@ function buildUrl(baseUrl, path, params) {
|
|
|
1322
1372
|
return url.toString();
|
|
1323
1373
|
}
|
|
1324
1374
|
function parseListing(data) {
|
|
1375
|
+
const metadata = isRecord(data.metadata) ? data.metadata : {};
|
|
1376
|
+
const persistence = isRecord(data.persistence) ? data.persistence : isRecord(metadata.persistence) ? metadata.persistence : {};
|
|
1325
1377
|
return {
|
|
1326
1378
|
listing_id: String(data.listing_id ?? data.id ?? ""),
|
|
1327
1379
|
capability_key: String(data.capability_key ?? ""),
|
|
@@ -1344,14 +1396,59 @@ function parseListing(data) {
|
|
|
1344
1396
|
seller_display_name: stringOrNull(data.seller_display_name),
|
|
1345
1397
|
seller_homepage_url: stringOrNull(data.seller_homepage_url),
|
|
1346
1398
|
seller_social_url: stringOrNull(data.seller_social_url),
|
|
1399
|
+
publisher_type: stringOrNull(data.publisher_type),
|
|
1400
|
+
publisher_company_id: stringOrNull(data.publisher_company_id),
|
|
1401
|
+
company_id: stringOrNull(data.company_id),
|
|
1402
|
+
company_name: stringOrNull(data.company_name),
|
|
1403
|
+
company_publish_status: stringOrNull(data.company_publish_status),
|
|
1404
|
+
company_terms_version: stringOrNull(data.company_terms_version),
|
|
1347
1405
|
review_status: stringOrNull(data.review_status),
|
|
1348
1406
|
review_note: stringOrNull(data.review_note),
|
|
1349
1407
|
submission_blockers: Array.isArray(data.submission_blockers) ? data.submission_blockers.filter((item) => typeof item === "string") : [],
|
|
1408
|
+
persistence: { ...persistence },
|
|
1350
1409
|
created_at: stringOrNull(data.created_at),
|
|
1351
1410
|
updated_at: stringOrNull(data.updated_at),
|
|
1352
1411
|
raw: { ...data }
|
|
1353
1412
|
};
|
|
1354
1413
|
}
|
|
1414
|
+
function parseCompanyPublisher(data) {
|
|
1415
|
+
const wallets = Array.isArray(data.settlement_wallets) ? data.settlement_wallets.filter((item) => isRecord(item)) : [];
|
|
1416
|
+
return {
|
|
1417
|
+
company_id: String(data.company_id ?? data.id ?? ""),
|
|
1418
|
+
name: String(data.name ?? ""),
|
|
1419
|
+
status: String(data.status ?? ""),
|
|
1420
|
+
description: stringOrNull(data.description),
|
|
1421
|
+
is_founder: Boolean(data.is_founder ?? false),
|
|
1422
|
+
membership_role: stringOrNull(data.membership_role),
|
|
1423
|
+
membership_status: stringOrNull(data.membership_status),
|
|
1424
|
+
can_publish: Boolean(data.can_publish ?? true),
|
|
1425
|
+
can_approve: Boolean(data.can_approve ?? false),
|
|
1426
|
+
approval_required: Boolean(data.approval_required ?? false),
|
|
1427
|
+
paid_listing_allowed: Boolean(data.paid_listing_allowed ?? false),
|
|
1428
|
+
disabled_reasons: Array.isArray(data.disabled_reasons) ? data.disabled_reasons.filter((item) => typeof item === "string") : [],
|
|
1429
|
+
company_terms_version: stringOrNull(data.company_terms_version),
|
|
1430
|
+
active_listing_count: Number(data.active_listing_count ?? 0),
|
|
1431
|
+
pending_approval_count: Number(data.pending_approval_count ?? 0),
|
|
1432
|
+
settlement_wallet_ready: Boolean(data.settlement_wallet_ready ?? false),
|
|
1433
|
+
settlement_wallets: wallets.map((item) => ({ ...item })),
|
|
1434
|
+
raw: { ...data }
|
|
1435
|
+
};
|
|
1436
|
+
}
|
|
1437
|
+
function parseCapabilitySaveState(data) {
|
|
1438
|
+
return {
|
|
1439
|
+
capability_key: String(data.capability_key ?? ""),
|
|
1440
|
+
save_key: String(data.save_key ?? ""),
|
|
1441
|
+
schema_version: String(data.schema_version ?? "1"),
|
|
1442
|
+
revision: Number(data.revision ?? 0),
|
|
1443
|
+
payload: toRecord(data.payload),
|
|
1444
|
+
metadata: toRecord(data.metadata),
|
|
1445
|
+
checksum: stringOrNull(data.checksum),
|
|
1446
|
+
updated_at: stringOrNull(data.updated_at),
|
|
1447
|
+
created_at: stringOrNull(data.created_at),
|
|
1448
|
+
exists: Boolean(data.exists ?? false),
|
|
1449
|
+
raw: { ...data }
|
|
1450
|
+
};
|
|
1451
|
+
}
|
|
1355
1452
|
function parseBundleMember(data) {
|
|
1356
1453
|
return {
|
|
1357
1454
|
capability_listing_id: String(data.capability_listing_id ?? ""),
|
|
@@ -1363,18 +1460,6 @@ function parseBundleMember(data) {
|
|
|
1363
1460
|
link_id: stringOrNull(data.link_id)
|
|
1364
1461
|
};
|
|
1365
1462
|
}
|
|
1366
|
-
function parseConnectedAccountLifecycle(data) {
|
|
1367
|
-
return {
|
|
1368
|
-
connected_account_id: String(data.connected_account_id ?? ""),
|
|
1369
|
-
provider_key: String(data.provider_key ?? ""),
|
|
1370
|
-
expires_at: stringOrNull(data.expires_at),
|
|
1371
|
-
scopes: Array.isArray(data.scopes) ? data.scopes.filter((s) => typeof s === "string") : [],
|
|
1372
|
-
refreshed_at: stringOrNull(data.refreshed_at),
|
|
1373
|
-
connection_status: stringOrNull(data.connection_status),
|
|
1374
|
-
provider_revoked: typeof data.provider_revoked === "boolean" ? data.provider_revoked : null,
|
|
1375
|
-
revoked_at: stringOrNull(data.revoked_at)
|
|
1376
|
-
};
|
|
1377
|
-
}
|
|
1378
1463
|
function parseBundle(data) {
|
|
1379
1464
|
const membersRaw = Array.isArray(data.members) ? data.members : [];
|
|
1380
1465
|
return {
|
|
@@ -1453,21 +1538,6 @@ function parseBinding(data) {
|
|
|
1453
1538
|
raw: { ...data }
|
|
1454
1539
|
};
|
|
1455
1540
|
}
|
|
1456
|
-
function parseConnectedAccount(data) {
|
|
1457
|
-
return {
|
|
1458
|
-
connected_account_id: String(data.connected_account_id ?? data.id ?? ""),
|
|
1459
|
-
provider_key: String(data.provider_key ?? ""),
|
|
1460
|
-
account_role: String(data.account_role ?? ""),
|
|
1461
|
-
display_name: stringOrNull(data.display_name),
|
|
1462
|
-
environment: stringOrNull(data.environment),
|
|
1463
|
-
connection_status: stringOrNull(data.connection_status),
|
|
1464
|
-
scopes: Array.isArray(data.scopes) ? data.scopes.filter((item) => typeof item === "string") : [],
|
|
1465
|
-
metadata: toRecord(data.metadata),
|
|
1466
|
-
created_at: stringOrNull(data.created_at),
|
|
1467
|
-
updated_at: stringOrNull(data.updated_at),
|
|
1468
|
-
raw: { ...data }
|
|
1469
|
-
};
|
|
1470
|
-
}
|
|
1471
1541
|
function parseSupportCase(data) {
|
|
1472
1542
|
return {
|
|
1473
1543
|
support_case_id: String(data.support_case_id ?? data.id ?? ""),
|
|
@@ -2506,13 +2576,6 @@ var init_client = __esm({
|
|
|
2506
2576
|
if (options.runtime_validation) {
|
|
2507
2577
|
payload.runtime_validation = coerceMapping(options.runtime_validation, "runtime_validation");
|
|
2508
2578
|
}
|
|
2509
|
-
if (options.oauth_credentials) {
|
|
2510
|
-
payload.oauth_credentials = Array.isArray(options.oauth_credentials) ? {
|
|
2511
|
-
items: options.oauth_credentials.map(
|
|
2512
|
-
(item, index) => coerceMapping(item, `oauth_credentials[${index}]`)
|
|
2513
|
-
)
|
|
2514
|
-
} : coerceMapping(options.oauth_credentials, "oauth_credentials");
|
|
2515
|
-
}
|
|
2516
2579
|
if (options.source_context) {
|
|
2517
2580
|
payload.source_context = coerceMapping(options.source_context, "source_context");
|
|
2518
2581
|
}
|
|
@@ -2531,6 +2594,9 @@ var init_client = __esm({
|
|
|
2531
2594
|
"support_contact",
|
|
2532
2595
|
"seller_homepage_url",
|
|
2533
2596
|
"seller_social_url",
|
|
2597
|
+
"publisher_type",
|
|
2598
|
+
"company_id",
|
|
2599
|
+
"publisher_company_id",
|
|
2534
2600
|
"store_vertical",
|
|
2535
2601
|
"jurisdiction",
|
|
2536
2602
|
"price_model",
|
|
@@ -2543,7 +2609,8 @@ var init_client = __esm({
|
|
|
2543
2609
|
"dry_run_supported",
|
|
2544
2610
|
"required_connected_accounts",
|
|
2545
2611
|
"permission_scopes",
|
|
2546
|
-
"compatibility_tags"
|
|
2612
|
+
"compatibility_tags",
|
|
2613
|
+
"persistence"
|
|
2547
2614
|
]) {
|
|
2548
2615
|
const value = manifestPayload[fieldName];
|
|
2549
2616
|
if (value !== void 0 && value !== null) {
|
|
@@ -2583,6 +2650,26 @@ var init_client = __esm({
|
|
|
2583
2650
|
);
|
|
2584
2651
|
}
|
|
2585
2652
|
}
|
|
2653
|
+
const explicitPublisherType = payload.publisher_type !== void 0 && payload.publisher_type !== null;
|
|
2654
|
+
const companyId = String(payload.company_id ?? "").trim() || String(payload.publisher_company_id ?? "").trim();
|
|
2655
|
+
const publisherType = String(payload.publisher_type ?? "user").trim().toLowerCase();
|
|
2656
|
+
if (publisherType !== "user" && publisherType !== "company") {
|
|
2657
|
+
throw new SiglumeClientError("AppManifest.publisher_type must be 'user' or 'company'.");
|
|
2658
|
+
}
|
|
2659
|
+
if (publisherType === "company" && !companyId) {
|
|
2660
|
+
throw new SiglumeClientError("AppManifest.company_id is required when publisher_type='company'.");
|
|
2661
|
+
}
|
|
2662
|
+
if (publisherType === "user" && companyId) {
|
|
2663
|
+
throw new SiglumeClientError("AppManifest.company_id cannot be combined with publisher_type='user'.");
|
|
2664
|
+
}
|
|
2665
|
+
if (explicitPublisherType || companyId) {
|
|
2666
|
+
payload.publisher_type = publisherType;
|
|
2667
|
+
}
|
|
2668
|
+
if (companyId) {
|
|
2669
|
+
payload.company_id = companyId;
|
|
2670
|
+
payload.publisher_company_id = companyId;
|
|
2671
|
+
}
|
|
2672
|
+
validateManifestPersistenceContract(payload);
|
|
2586
2673
|
if (payload.manifest && typeof payload.manifest === "object") {
|
|
2587
2674
|
delete payload.manifest.version;
|
|
2588
2675
|
}
|
|
@@ -2618,7 +2705,6 @@ var init_client = __esm({
|
|
|
2618
2705
|
auto_manifest: toRecord(data.auto_manifest),
|
|
2619
2706
|
confidence: toRecord(data.confidence),
|
|
2620
2707
|
validation_report: toRecord(data.validation_report),
|
|
2621
|
-
oauth_status: toRecord(data.oauth_status),
|
|
2622
2708
|
review_url: stringOrNull(data.review_url),
|
|
2623
2709
|
trace_id: meta.trace_id,
|
|
2624
2710
|
request_id: meta.request_id
|
|
@@ -2690,6 +2776,45 @@ var init_client = __esm({
|
|
|
2690
2776
|
const [data] = await this.request("GET", `/market/capabilities/${listing_id}`);
|
|
2691
2777
|
return parseListing(data);
|
|
2692
2778
|
}
|
|
2779
|
+
async list_company_publishers() {
|
|
2780
|
+
const [data] = await this.request("GET", "/market/company-publishers");
|
|
2781
|
+
return Array.isArray(data.items) ? data.items.filter((item) => isRecord(item)).map(parseCompanyPublisher) : [];
|
|
2782
|
+
}
|
|
2783
|
+
async request_company_publish_approval(listing_id, note) {
|
|
2784
|
+
const [data] = await this.request("POST", `/market/capabilities/${listing_id}/company-publish-approval`, {
|
|
2785
|
+
json_body: note ? { note } : {}
|
|
2786
|
+
});
|
|
2787
|
+
return parseListing(data);
|
|
2788
|
+
}
|
|
2789
|
+
async decide_company_publish_approval(listing_id, options) {
|
|
2790
|
+
const [data] = await this.request("POST", `/market/capabilities/${listing_id}/company-publish-approval/decision`, {
|
|
2791
|
+
json_body: {
|
|
2792
|
+
decision: options.decision,
|
|
2793
|
+
...options.reason ? { reason: options.reason } : {}
|
|
2794
|
+
}
|
|
2795
|
+
});
|
|
2796
|
+
return parseListing(data);
|
|
2797
|
+
}
|
|
2798
|
+
async get_capability_state(capability_key, save_key = "default") {
|
|
2799
|
+
const [data] = await this.request("GET", `/market/capability-state/${capability_key}/${save_key}`);
|
|
2800
|
+
return parseCapabilitySaveState(data);
|
|
2801
|
+
}
|
|
2802
|
+
async put_capability_state(capability_key, save_key = "default", payload = {}, options = {}) {
|
|
2803
|
+
const body = {
|
|
2804
|
+
payload: toRecord(payload),
|
|
2805
|
+
schema_version: options.schema_version ?? "1",
|
|
2806
|
+
metadata: toRecord(options.metadata)
|
|
2807
|
+
};
|
|
2808
|
+
if (options.expected_revision !== void 0 && options.expected_revision !== null) {
|
|
2809
|
+
body.expected_revision = Math.trunc(options.expected_revision);
|
|
2810
|
+
}
|
|
2811
|
+
const [data] = await this.request("PUT", `/market/capability-state/${capability_key}/${save_key}`, { json_body: body });
|
|
2812
|
+
return parseCapabilitySaveState(data);
|
|
2813
|
+
}
|
|
2814
|
+
async delete_capability_state(capability_key, save_key = "default") {
|
|
2815
|
+
const [data] = await this.request("DELETE", `/market/capability-state/${capability_key}/${save_key}`);
|
|
2816
|
+
return parseCapabilitySaveState(data);
|
|
2817
|
+
}
|
|
2693
2818
|
// ----- Capability bundles (v0.7 track 2) ---------------------------------
|
|
2694
2819
|
async list_bundles(options = {}) {
|
|
2695
2820
|
const params = {
|
|
@@ -2755,66 +2880,9 @@ var init_client = __esm({
|
|
|
2755
2880
|
return parseBundle(data);
|
|
2756
2881
|
}
|
|
2757
2882
|
// ----- end bundles -------------------------------------------------------
|
|
2758
|
-
// ----- Connected accounts
|
|
2759
|
-
//
|
|
2760
|
-
|
|
2761
|
-
const body = {
|
|
2762
|
-
listing_id: input.listing_id,
|
|
2763
|
-
redirect_uri: input.redirect_uri
|
|
2764
|
-
};
|
|
2765
|
-
if (input.scopes !== void 0) body.scopes = input.scopes;
|
|
2766
|
-
if (input.account_role !== void 0) body.account_role = input.account_role;
|
|
2767
|
-
const [data] = await this.request("POST", "/me/connected-accounts/oauth/authorize", {
|
|
2768
|
-
json_body: body
|
|
2769
|
-
});
|
|
2770
|
-
return {
|
|
2771
|
-
authorize_url: String(data.authorize_url ?? ""),
|
|
2772
|
-
state: String(data.state ?? ""),
|
|
2773
|
-
provider_key: String(data.provider_key ?? ""),
|
|
2774
|
-
scopes: Array.isArray(data.scopes) ? data.scopes.filter((s) => typeof s === "string") : [],
|
|
2775
|
-
pkce_method: stringOrNull(data.pkce_method)
|
|
2776
|
-
};
|
|
2777
|
-
}
|
|
2778
|
-
async complete_connected_account_oauth(input) {
|
|
2779
|
-
const [data] = await this.request("POST", "/me/connected-accounts/oauth/callback", {
|
|
2780
|
-
json_body: { state: input.state, code: input.code }
|
|
2781
|
-
});
|
|
2782
|
-
return { ...data };
|
|
2783
|
-
}
|
|
2784
|
-
async refresh_connected_account(account_id) {
|
|
2785
|
-
const [data] = await this.request("POST", `/me/connected-accounts/${account_id}/refresh`);
|
|
2786
|
-
return parseConnectedAccountLifecycle(data);
|
|
2787
|
-
}
|
|
2788
|
-
async revoke_connected_account(account_id) {
|
|
2789
|
-
const [data] = await this.request("POST", `/me/connected-accounts/${account_id}/revoke`);
|
|
2790
|
-
return parseConnectedAccountLifecycle(data);
|
|
2791
|
-
}
|
|
2792
|
-
async set_listing_oauth_credentials(listing_id, input) {
|
|
2793
|
-
const body = {
|
|
2794
|
-
provider_key: input.provider_key,
|
|
2795
|
-
client_id: input.client_id,
|
|
2796
|
-
client_secret: input.client_secret,
|
|
2797
|
-
authorize_url: input.authorize_url,
|
|
2798
|
-
token_url: input.token_url
|
|
2799
|
-
};
|
|
2800
|
-
if (input.revoke_url !== void 0) body.revoke_url = input.revoke_url;
|
|
2801
|
-
if (input.display_name !== void 0) body.display_name = input.display_name;
|
|
2802
|
-
if (input.scope_separator !== void 0) body.scope_separator = input.scope_separator;
|
|
2803
|
-
if (input.token_endpoint_auth !== void 0) body.token_endpoint_auth = input.token_endpoint_auth;
|
|
2804
|
-
if (input.pkce_required !== void 0) body.pkce_required = input.pkce_required;
|
|
2805
|
-
if (input.refresh_supported !== void 0) body.refresh_supported = input.refresh_supported;
|
|
2806
|
-
if (input.available_scopes !== void 0) body.available_scopes = input.available_scopes;
|
|
2807
|
-
if (input.required_scopes !== void 0) body.required_scopes = input.required_scopes;
|
|
2808
|
-
const [data] = await this.request("PUT", `/market/capabilities/${listing_id}/oauth-credentials`, {
|
|
2809
|
-
json_body: body
|
|
2810
|
-
});
|
|
2811
|
-
return { ...data };
|
|
2812
|
-
}
|
|
2813
|
-
async get_listing_oauth_credentials_status(listing_id) {
|
|
2814
|
-
const [data] = await this.request("GET", `/market/capabilities/${listing_id}/oauth-credentials`);
|
|
2815
|
-
return { ...data };
|
|
2816
|
-
}
|
|
2817
|
-
// ----- end connected accounts --------------------------------------------
|
|
2883
|
+
// ----- Connected accounts ------------------------------------------------
|
|
2884
|
+
// Architecture B: publisher APIs own external OAuth and token storage.
|
|
2885
|
+
// The SDK no longer exposes platform OAuth or listing credential APIs.
|
|
2818
2886
|
async get_developer_portal() {
|
|
2819
2887
|
const [data, meta] = await this.request("GET", "/market/developer/portal");
|
|
2820
2888
|
return {
|
|
@@ -2847,7 +2915,6 @@ var init_client = __esm({
|
|
|
2847
2915
|
dry_run_supported: Boolean(data.dry_run_supported ?? false),
|
|
2848
2916
|
approval_mode: stringOrNull(data.approval_mode),
|
|
2849
2917
|
required_connected_accounts: Array.isArray(data.required_connected_accounts) ? data.required_connected_accounts : [],
|
|
2850
|
-
connected_accounts: Array.isArray(data.connected_accounts) ? data.connected_accounts.filter((item) => isRecord(item)).map((item) => ({ ...item })) : [],
|
|
2851
2918
|
stub_providers_enabled: Boolean(data.stub_providers_enabled ?? false),
|
|
2852
2919
|
simulated_receipts: Boolean(data.simulated_receipts ?? false),
|
|
2853
2920
|
approval_simulator: Boolean(data.approval_simulator ?? false),
|
|
@@ -4145,25 +4212,6 @@ var init_client = __esm({
|
|
|
4145
4212
|
raw: { ...data }
|
|
4146
4213
|
};
|
|
4147
4214
|
}
|
|
4148
|
-
async list_connected_accounts(options = {}) {
|
|
4149
|
-
const params = {
|
|
4150
|
-
provider_key: options.provider_key,
|
|
4151
|
-
environment: options.environment,
|
|
4152
|
-
limit: Math.max(1, Math.min(Math.trunc(options.limit ?? 50), 100)),
|
|
4153
|
-
cursor: options.cursor
|
|
4154
|
-
};
|
|
4155
|
-
const [data, meta] = await this.request("GET", "/market/connected-accounts", { params });
|
|
4156
|
-
const items = Array.isArray(data.items) ? data.items.filter((item) => isRecord(item)).map(parseConnectedAccount) : [];
|
|
4157
|
-
const next_cursor = stringOrNull(data.next_cursor);
|
|
4158
|
-
return new CursorPageResult({
|
|
4159
|
-
items,
|
|
4160
|
-
next_cursor,
|
|
4161
|
-
limit: typeof data.limit === "number" ? data.limit : params.limit,
|
|
4162
|
-
offset: typeof data.offset === "number" ? data.offset : null,
|
|
4163
|
-
meta,
|
|
4164
|
-
fetchNext: next_cursor ? (cursor) => this.list_connected_accounts({ ...options, cursor }) : void 0
|
|
4165
|
-
});
|
|
4166
|
-
}
|
|
4167
4215
|
async create_support_case(subject, body, options = {}) {
|
|
4168
4216
|
const summary = subject.trim();
|
|
4169
4217
|
const details = body.trim();
|
|
@@ -6012,24 +6060,12 @@ var AppTestHarness = class {
|
|
|
6012
6060
|
this.stubs = stubs;
|
|
6013
6061
|
}
|
|
6014
6062
|
async executeWithKind(execution_kind, task_type = "default", options = {}) {
|
|
6015
|
-
const connected_accounts = options.connected_accounts ?? Object.fromEntries(
|
|
6016
|
-
Object.keys(this.stubs).map((key) => [
|
|
6017
|
-
key,
|
|
6018
|
-
{
|
|
6019
|
-
provider_key: key,
|
|
6020
|
-
session_token: `stub-token-${key}`,
|
|
6021
|
-
environment: Environment.SANDBOX,
|
|
6022
|
-
scopes: []
|
|
6023
|
-
}
|
|
6024
|
-
])
|
|
6025
|
-
);
|
|
6026
6063
|
const ctx = {
|
|
6027
6064
|
agent_id: "test-agent-001",
|
|
6028
6065
|
owner_user_id: "test-owner-001",
|
|
6029
6066
|
task_type,
|
|
6030
6067
|
environment: Environment.SANDBOX,
|
|
6031
6068
|
execution_kind,
|
|
6032
|
-
connected_accounts,
|
|
6033
6069
|
input_params: options.input_params ?? {},
|
|
6034
6070
|
trace_id: options.trace_id,
|
|
6035
6071
|
idempotency_key: options.idempotency_key,
|
|
@@ -6119,12 +6155,6 @@ var AppTestHarness = class {
|
|
|
6119
6155
|
}
|
|
6120
6156
|
return issues;
|
|
6121
6157
|
}
|
|
6122
|
-
async simulate_connected_account_missing(task_type = "default", options = {}) {
|
|
6123
|
-
return this.executeWithKind("dry_run", task_type, {
|
|
6124
|
-
...options,
|
|
6125
|
-
connected_accounts: {}
|
|
6126
|
-
});
|
|
6127
|
-
}
|
|
6128
6158
|
async simulate_metering(record, options = {}) {
|
|
6129
6159
|
const { normalizeUsageRecord: normalizeUsageRecord2 } = await Promise.resolve().then(() => (init_metering(), metering_exports));
|
|
6130
6160
|
const manifest = await this.app.manifest();
|
|
@@ -7087,15 +7117,6 @@ async function loadProject(path = ".") {
|
|
|
7087
7117
|
const tool_manual = tool_manual_path ? JSON.parse(await (0, import_promises.readFile)(tool_manual_path, "utf8")) : buildToolManualTemplate(manifest);
|
|
7088
7118
|
const runtime_validation_path = await findRuntimeValidationPath(root_dir);
|
|
7089
7119
|
const runtime_validation = runtime_validation_path ? await loadJsonObject(runtime_validation_path, "runtime_validation") : void 0;
|
|
7090
|
-
const oauth_credentials_path = await findOauthCredentialsPath(root_dir);
|
|
7091
|
-
let oauth_credentials;
|
|
7092
|
-
if (oauth_credentials_path) {
|
|
7093
|
-
const parsed = JSON.parse(await (0, import_promises.readFile)(oauth_credentials_path, "utf8"));
|
|
7094
|
-
if (!isRecord(parsed) && !Array.isArray(parsed)) {
|
|
7095
|
-
throw new SiglumeProjectError("oauth_credentials must be a JSON object or array");
|
|
7096
|
-
}
|
|
7097
|
-
oauth_credentials = parsed;
|
|
7098
|
-
}
|
|
7099
7120
|
return {
|
|
7100
7121
|
root_dir,
|
|
7101
7122
|
adapter_path,
|
|
@@ -7104,9 +7125,7 @@ async function loadProject(path = ".") {
|
|
|
7104
7125
|
tool_manual_path: tool_manual_path ?? void 0,
|
|
7105
7126
|
tool_manual,
|
|
7106
7127
|
runtime_validation_path: runtime_validation_path ?? void 0,
|
|
7107
|
-
runtime_validation
|
|
7108
|
-
oauth_credentials_path: oauth_credentials_path ?? void 0,
|
|
7109
|
-
oauth_credentials
|
|
7128
|
+
runtime_validation
|
|
7110
7129
|
};
|
|
7111
7130
|
}
|
|
7112
7131
|
function isPlatformManagedRequirement(value) {
|
|
@@ -7144,6 +7163,21 @@ function requiredOauthProviders(requirements) {
|
|
|
7144
7163
|
}
|
|
7145
7164
|
return providers;
|
|
7146
7165
|
}
|
|
7166
|
+
function apiManagedRequirementsMissingConnectUrl(requirements) {
|
|
7167
|
+
const missing = [];
|
|
7168
|
+
for (const item of requirements ?? []) {
|
|
7169
|
+
if (!isRecord(item)) continue;
|
|
7170
|
+
const managedBy = String(item.managed_by ?? "").trim().toLowerCase().replaceAll("_", "-");
|
|
7171
|
+
if (managedBy !== "api") continue;
|
|
7172
|
+
const connectUrl = String(item.connect_url ?? "").trim();
|
|
7173
|
+
if (connectUrl) continue;
|
|
7174
|
+
const label = oauthProviderKeyFromRequirement(item) ?? "(missing provider_key)";
|
|
7175
|
+
if (!missing.includes(label)) {
|
|
7176
|
+
missing.push(label);
|
|
7177
|
+
}
|
|
7178
|
+
}
|
|
7179
|
+
return missing;
|
|
7180
|
+
}
|
|
7147
7181
|
function connectedAccountRequirementLabel(value) {
|
|
7148
7182
|
if (isRecord(value)) {
|
|
7149
7183
|
for (const key of ["provider_key", "provider", "account_type", "name"]) {
|
|
@@ -7154,102 +7188,6 @@ function connectedAccountRequirementLabel(value) {
|
|
|
7154
7188
|
}
|
|
7155
7189
|
return String(value ?? "").trim();
|
|
7156
7190
|
}
|
|
7157
|
-
function oauthProviderRecordsMap(payload) {
|
|
7158
|
-
if (!payload) {
|
|
7159
|
-
return {};
|
|
7160
|
-
}
|
|
7161
|
-
const items = Array.isArray(payload) ? payload : Array.isArray(payload.items) ? payload.items : [payload];
|
|
7162
|
-
const resolved = {};
|
|
7163
|
-
for (const [index, item] of items.entries()) {
|
|
7164
|
-
if (!isRecord(item)) {
|
|
7165
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}] must be a JSON object.`);
|
|
7166
|
-
}
|
|
7167
|
-
const providerKey = oauthProviderKeyFromRequirement(item.provider_key ?? item.provider);
|
|
7168
|
-
if (!providerKey) {
|
|
7169
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}].provider_key is required.`);
|
|
7170
|
-
}
|
|
7171
|
-
const authorizeUrl = String(item.authorize_url ?? item.authorization_url ?? item.auth_url ?? "").trim();
|
|
7172
|
-
const tokenUrl = String(item.token_url ?? "").trim();
|
|
7173
|
-
if (!authorizeUrl || !tokenUrl) {
|
|
7174
|
-
throw new SiglumeProjectError(
|
|
7175
|
-
`oauth_credentials[${index}] must include authorize_url and token_url.`
|
|
7176
|
-
);
|
|
7177
|
-
}
|
|
7178
|
-
for (const [urlKey, urlValue] of Object.entries({
|
|
7179
|
-
authorize_url: authorizeUrl,
|
|
7180
|
-
token_url: tokenUrl,
|
|
7181
|
-
revoke_url: String(item.revoke_url ?? "").trim()
|
|
7182
|
-
})) {
|
|
7183
|
-
if (urlValue && !urlValue.startsWith("https://")) {
|
|
7184
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}].${urlKey} must be an https URL.`);
|
|
7185
|
-
}
|
|
7186
|
-
}
|
|
7187
|
-
const clientId = String(item.client_id ?? "").trim();
|
|
7188
|
-
const clientSecret = String(item.client_secret ?? "").trim();
|
|
7189
|
-
if (!clientId || !clientSecret) {
|
|
7190
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}] must include client_id and client_secret.`);
|
|
7191
|
-
}
|
|
7192
|
-
const rawScopes = item.required_scopes ?? item.scopes;
|
|
7193
|
-
let scopes = [];
|
|
7194
|
-
if (rawScopes == null) {
|
|
7195
|
-
scopes = [];
|
|
7196
|
-
} else if (!Array.isArray(rawScopes)) {
|
|
7197
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}].required_scopes must be a JSON array.`);
|
|
7198
|
-
} else {
|
|
7199
|
-
scopes = rawScopes.map((scope) => String(scope ?? "").trim()).filter(Boolean);
|
|
7200
|
-
}
|
|
7201
|
-
const record = {
|
|
7202
|
-
provider_key: providerKey,
|
|
7203
|
-
client_id: clientId,
|
|
7204
|
-
client_secret: clientSecret,
|
|
7205
|
-
required_scopes: scopes
|
|
7206
|
-
};
|
|
7207
|
-
for (const [key, value] of Object.entries({
|
|
7208
|
-
authorize_url: authorizeUrl,
|
|
7209
|
-
token_url: tokenUrl,
|
|
7210
|
-
revoke_url: String(item.revoke_url ?? "").trim(),
|
|
7211
|
-
display_name: String(item.display_name ?? "").trim(),
|
|
7212
|
-
scope_separator: String(item.scope_separator ?? "").trim(),
|
|
7213
|
-
token_endpoint_auth: String(item.token_endpoint_auth ?? "").trim()
|
|
7214
|
-
})) {
|
|
7215
|
-
if (value) record[key] = value;
|
|
7216
|
-
}
|
|
7217
|
-
for (const key of ["pkce_required", "refresh_supported"]) {
|
|
7218
|
-
if (typeof item[key] === "boolean") record[key] = item[key];
|
|
7219
|
-
}
|
|
7220
|
-
if (Array.isArray(item.available_scopes)) {
|
|
7221
|
-
const availableScopes = item.available_scopes.map((scope) => String(scope ?? "").trim()).filter(Boolean);
|
|
7222
|
-
if (availableScopes.length > 0) record.available_scopes = availableScopes;
|
|
7223
|
-
}
|
|
7224
|
-
resolved[providerKey] = record;
|
|
7225
|
-
}
|
|
7226
|
-
return resolved;
|
|
7227
|
-
}
|
|
7228
|
-
function canonicalOauthCredentialsPayload(payload) {
|
|
7229
|
-
const records = oauthProviderRecordsMap(payload);
|
|
7230
|
-
const providerKeys = Object.keys(records).sort();
|
|
7231
|
-
if (providerKeys.length === 0) {
|
|
7232
|
-
return void 0;
|
|
7233
|
-
}
|
|
7234
|
-
return {
|
|
7235
|
-
items: providerKeys.map((providerKey) => records[providerKey])
|
|
7236
|
-
};
|
|
7237
|
-
}
|
|
7238
|
-
function ensureRequiredOauthCredentials(project) {
|
|
7239
|
-
const requiredProviders = requiredOauthProviders(project.manifest.required_connected_accounts ?? []);
|
|
7240
|
-
if (requiredProviders.length === 0) {
|
|
7241
|
-
return;
|
|
7242
|
-
}
|
|
7243
|
-
const provided = new Set(Object.keys(oauthProviderRecordsMap(project.oauth_credentials)));
|
|
7244
|
-
const missing = requiredProviders.filter((provider) => !provided.has(provider));
|
|
7245
|
-
if (missing.length === 0) {
|
|
7246
|
-
return;
|
|
7247
|
-
}
|
|
7248
|
-
const path = project.oauth_credentials_path ?? (0, import_node_path.join)(project.root_dir, "oauth_credentials.json");
|
|
7249
|
-
throw new SiglumeProjectError(
|
|
7250
|
-
`${path} is required for platform-managed OAuth APIs. Missing provider seeds: ${missing.join(", ")}`
|
|
7251
|
-
);
|
|
7252
|
-
}
|
|
7253
7191
|
async function validateProject(path = ".", deps = {}) {
|
|
7254
7192
|
const project = await loadProject(path);
|
|
7255
7193
|
const manifest_issues = await projectValidationIssues(project);
|
|
@@ -7289,7 +7227,12 @@ function ensureManifestPublisherIdentity(project) {
|
|
|
7289
7227
|
const sellerHomepageUrl = String(manifestPayload.seller_homepage_url ?? "").trim();
|
|
7290
7228
|
const sellerSocialUrl = String(manifestPayload.seller_social_url ?? "").trim();
|
|
7291
7229
|
const jurisdiction = String(manifestPayload.jurisdiction ?? "").trim();
|
|
7230
|
+
const companyId = String(manifestPayload.company_id ?? "").trim() || String(manifestPayload.publisher_company_id ?? "").trim();
|
|
7231
|
+
const publisherType = String(manifestPayload.publisher_type ?? "user").trim().toLowerCase();
|
|
7292
7232
|
const issues = [];
|
|
7233
|
+
if (companyId && publisherType !== "company") {
|
|
7234
|
+
issues.push('manifest.company_id requires manifest.publisher_type to be "company"');
|
|
7235
|
+
}
|
|
7293
7236
|
if (!docsUrl) {
|
|
7294
7237
|
issues.push("manifest.docs_url is required");
|
|
7295
7238
|
} else if (looksLikePlaceholder(docsUrl)) {
|
|
@@ -7399,10 +7342,21 @@ function ensureExplicitToolManual(project) {
|
|
|
7399
7342
|
async function registrationPreflight(project, client) {
|
|
7400
7343
|
const manifestIssues = await projectValidationIssues(project);
|
|
7401
7344
|
const [toolManualValid, toolManualIssues] = validate_tool_manual(project.tool_manual);
|
|
7345
|
+
const retiredPlatformOauthProviders = requiredOauthProviders(project.manifest.required_connected_accounts ?? []);
|
|
7346
|
+
if (retiredPlatformOauthProviders.length > 0) {
|
|
7347
|
+
throw new SiglumeProjectError(
|
|
7348
|
+
`Registration preflight failed. Fix these before calling auto-register:
|
|
7349
|
+
- platform-managed OAuth is retired. Use managed_by="api" with connect_url: ${retiredPlatformOauthProviders.join(", ")}`
|
|
7350
|
+
);
|
|
7351
|
+
}
|
|
7352
|
+
const apiManagedMissingConnectUrl = apiManagedRequirementsMissingConnectUrl(project.manifest.required_connected_accounts ?? []);
|
|
7353
|
+
if (apiManagedMissingConnectUrl.length > 0) {
|
|
7354
|
+
throw new SiglumeProjectError(
|
|
7355
|
+
`Registration preflight failed. Fix these before calling auto-register:
|
|
7356
|
+
- API-managed OAuth requirements must include connect_url: ${apiManagedMissingConnectUrl.join(", ")}`
|
|
7357
|
+
);
|
|
7358
|
+
}
|
|
7402
7359
|
const remoteQuality = await client.preview_quality_score(project.tool_manual);
|
|
7403
|
-
const requiredOauthProvidersList = requiredOauthProviders(project.manifest.required_connected_accounts ?? []);
|
|
7404
|
-
const oauthProviderRecords = oauthProviderRecordsMap(project.oauth_credentials);
|
|
7405
|
-
const missingOauthProviders = requiredOauthProvidersList.filter((provider) => !oauthProviderRecords[provider]);
|
|
7406
7360
|
const blockingToolManualIssues = toolManualIssues.filter((issue2) => issue2.severity === "error");
|
|
7407
7361
|
const errors = [
|
|
7408
7362
|
...manifestIssues.map((issue2) => String(issue2)),
|
|
@@ -7414,17 +7368,12 @@ async function registrationPreflight(project, client) {
|
|
|
7414
7368
|
if (!remoteQualityOk(remoteQuality)) {
|
|
7415
7369
|
errors.push(`remote Tool Manual quality is not publishable: ${remoteQuality.grade} (${remoteQuality.overall_score}/100)`);
|
|
7416
7370
|
}
|
|
7417
|
-
if (missingOauthProviders.length > 0) {
|
|
7418
|
-
errors.push(`oauth_credentials.json is required for platform-managed OAuth APIs: ${missingOauthProviders.join(", ")}`);
|
|
7419
|
-
}
|
|
7420
7371
|
const preflight = {
|
|
7421
7372
|
manifest_issues: manifestIssues,
|
|
7422
7373
|
tool_manual_valid: toolManualValid,
|
|
7423
7374
|
tool_manual_issues: toolManualIssues.map((issue2) => toJsonable(issue2)),
|
|
7424
7375
|
remote_quality: toJsonable(remoteQuality),
|
|
7425
|
-
|
|
7426
|
-
oauth_credentials_path: project.oauth_credentials_path ?? null,
|
|
7427
|
-
oauth_missing_providers: missingOauthProviders,
|
|
7376
|
+
retired_platform_oauth_providers: retiredPlatformOauthProviders,
|
|
7428
7377
|
ok: errors.length === 0
|
|
7429
7378
|
};
|
|
7430
7379
|
if (errors.length > 0) {
|
|
@@ -7435,35 +7384,116 @@ ${errors.map((error) => `- ${error}`).join("\n")}`
|
|
|
7435
7384
|
}
|
|
7436
7385
|
return preflight;
|
|
7437
7386
|
}
|
|
7387
|
+
function companyNameSlug(value) {
|
|
7388
|
+
return value.normalize("NFKD").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
7389
|
+
}
|
|
7438
7390
|
async function runRegistration(path = ".", options = {}, deps = {}) {
|
|
7439
7391
|
const project = await loadProject(path);
|
|
7392
|
+
let requestedCompanyId = String(options.company_id ?? "").trim();
|
|
7393
|
+
const requestedCompanySlug = String(options.company_slug ?? "").trim();
|
|
7394
|
+
let companyPublisherCandidates = null;
|
|
7395
|
+
if (requestedCompanySlug) {
|
|
7396
|
+
if (requestedCompanyId) {
|
|
7397
|
+
throw new SiglumeProjectError("--company and --company-slug cannot be combined.");
|
|
7398
|
+
}
|
|
7399
|
+
const slug = companyNameSlug(requestedCompanySlug);
|
|
7400
|
+
if (!slug && requestedCompanySlug !== requestedCompanyId) {
|
|
7401
|
+
throw new SiglumeProjectError(`Company slug ${requestedCompanySlug} is not slug-compatible; use --company <company_id> instead.`);
|
|
7402
|
+
}
|
|
7403
|
+
}
|
|
7404
|
+
if (requestedCompanyId) {
|
|
7405
|
+
project.manifest = {
|
|
7406
|
+
...project.manifest,
|
|
7407
|
+
publisher_type: "company",
|
|
7408
|
+
company_id: requestedCompanyId,
|
|
7409
|
+
publisher_company_id: requestedCompanyId
|
|
7410
|
+
};
|
|
7411
|
+
}
|
|
7440
7412
|
ensureExplicitToolManual(project);
|
|
7441
7413
|
ensureManifestPublisherIdentity(project);
|
|
7442
7414
|
ensureRuntimeValidationReady(project);
|
|
7443
|
-
ensureRequiredOauthCredentials(project);
|
|
7444
|
-
const canonicalOauthCredentials = canonicalOauthCredentialsPayload(project.oauth_credentials);
|
|
7445
7415
|
const client = await createClient(deps);
|
|
7416
|
+
if (requestedCompanySlug) {
|
|
7417
|
+
const slug = companyNameSlug(requestedCompanySlug);
|
|
7418
|
+
companyPublisherCandidates = await client.list_company_publishers();
|
|
7419
|
+
const matches = companyPublisherCandidates.filter(
|
|
7420
|
+
(item) => companyNameSlug(item.name || item.company_id) === slug || item.company_id === requestedCompanySlug
|
|
7421
|
+
);
|
|
7422
|
+
if (matches.length === 0) {
|
|
7423
|
+
throw new SiglumeProjectError(`Company slug ${requestedCompanySlug} is not available to this API key.`);
|
|
7424
|
+
}
|
|
7425
|
+
if (matches.length > 1) {
|
|
7426
|
+
throw new SiglumeProjectError(`Company slug ${requestedCompanySlug} is ambiguous; use --company <company_id> instead.`);
|
|
7427
|
+
}
|
|
7428
|
+
const match = matches[0];
|
|
7429
|
+
if (!match) {
|
|
7430
|
+
throw new SiglumeProjectError(`Company slug ${requestedCompanySlug} is not available to this API key.`);
|
|
7431
|
+
}
|
|
7432
|
+
if (match.can_publish === false) {
|
|
7433
|
+
const disabledReasons = match.disabled_reasons ?? [];
|
|
7434
|
+
const reasons = disabledReasons.length > 0 ? disabledReasons.join(", ") : "company publisher is disabled";
|
|
7435
|
+
throw new SiglumeProjectError(`Company ${match.company_id} cannot publish: ${reasons}.`);
|
|
7436
|
+
}
|
|
7437
|
+
requestedCompanyId = match.company_id;
|
|
7438
|
+
project.manifest = {
|
|
7439
|
+
...project.manifest,
|
|
7440
|
+
publisher_type: "company",
|
|
7441
|
+
company_id: requestedCompanyId,
|
|
7442
|
+
publisher_company_id: requestedCompanyId
|
|
7443
|
+
};
|
|
7444
|
+
}
|
|
7446
7445
|
const preflight = await registrationPreflight(project, client);
|
|
7446
|
+
let companyPublisherPreflight = null;
|
|
7447
|
+
const companyId = String(project.manifest.company_id ?? "").trim() || String(project.manifest.publisher_company_id ?? "").trim();
|
|
7448
|
+
const publisherType = String(project.manifest.publisher_type ?? "user").toLowerCase();
|
|
7449
|
+
if (publisherType === "company") {
|
|
7450
|
+
if (!companyId) {
|
|
7451
|
+
throw new SiglumeProjectError("Company registration requires --company <company_id> or manifest.company_id.");
|
|
7452
|
+
}
|
|
7453
|
+
const companies = companyPublisherCandidates ?? await client.list_company_publishers();
|
|
7454
|
+
companyPublisherCandidates = companies;
|
|
7455
|
+
const company = companies.find((item) => item.company_id === companyId);
|
|
7456
|
+
if (!company) {
|
|
7457
|
+
throw new SiglumeProjectError(`Company ${companyId} is not available to this API key.`);
|
|
7458
|
+
}
|
|
7459
|
+
if (company.can_publish === false) {
|
|
7460
|
+
const disabledReasons = company.disabled_reasons ?? [];
|
|
7461
|
+
const reasons = disabledReasons.length > 0 ? disabledReasons.join(", ") : "company publisher is disabled";
|
|
7462
|
+
throw new SiglumeProjectError(`Company ${companyId} cannot publish: ${reasons}.`);
|
|
7463
|
+
}
|
|
7464
|
+
companyPublisherPreflight = company;
|
|
7465
|
+
}
|
|
7447
7466
|
let developerPortalPreflight = null;
|
|
7448
7467
|
if (String(project.manifest.price_model ?? "free").toLowerCase() !== "free") {
|
|
7449
|
-
|
|
7450
|
-
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
)
|
|
7468
|
+
if (publisherType === "company") {
|
|
7469
|
+
const company = companyPublisherPreflight;
|
|
7470
|
+
if (!company) {
|
|
7471
|
+
throw new SiglumeProjectError(`Company ${companyId} is not available to this API key.`);
|
|
7472
|
+
}
|
|
7473
|
+
if (company.settlement_wallet_ready !== true) {
|
|
7474
|
+
throw new SiglumeProjectError(
|
|
7475
|
+
`Paid company registration requires a verified company settlement wallet for ${company.name}. Open the company settings and complete settlement readiness before registering.`
|
|
7476
|
+
);
|
|
7477
|
+
}
|
|
7478
|
+
developerPortalPreflight = { company_publisher: toJsonable(company) };
|
|
7479
|
+
} else {
|
|
7480
|
+
const portal = await client.get_developer_portal();
|
|
7481
|
+
const verifiedDestination = portal.payout_readiness?.verified_destination;
|
|
7482
|
+
if (verifiedDestination !== true) {
|
|
7483
|
+
throw new SiglumeProjectError(
|
|
7484
|
+
"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."
|
|
7485
|
+
);
|
|
7486
|
+
}
|
|
7487
|
+
developerPortalPreflight = toJsonable(portal);
|
|
7455
7488
|
}
|
|
7456
|
-
developerPortalPreflight = toJsonable(portal);
|
|
7457
7489
|
}
|
|
7458
7490
|
const receipt = await client.auto_register(project.manifest, project.tool_manual, {
|
|
7459
|
-
runtime_validation: project.runtime_validation
|
|
7460
|
-
oauth_credentials: canonicalOauthCredentials
|
|
7491
|
+
runtime_validation: project.runtime_validation
|
|
7461
7492
|
});
|
|
7462
7493
|
const result = {
|
|
7463
7494
|
receipt: toJsonable(receipt),
|
|
7464
7495
|
registration_preflight: preflight,
|
|
7465
|
-
runtime_validation_path: project.runtime_validation_path ?? null
|
|
7466
|
-
oauth_credentials_path: project.oauth_credentials_path ?? null
|
|
7496
|
+
runtime_validation_path: project.runtime_validation_path ?? null
|
|
7467
7497
|
};
|
|
7468
7498
|
if (developerPortalPreflight) {
|
|
7469
7499
|
result.developer_portal_preflight = developerPortalPreflight;
|
|
@@ -7484,7 +7514,6 @@ async function runPreflight(path = ".", deps = {}) {
|
|
|
7484
7514
|
ensureExplicitToolManual(project);
|
|
7485
7515
|
ensureManifestPublisherIdentity(project);
|
|
7486
7516
|
ensureRuntimeValidationReady(project);
|
|
7487
|
-
ensureRequiredOauthCredentials(project);
|
|
7488
7517
|
const client = await createClient(deps);
|
|
7489
7518
|
const preflight = await registrationPreflight(project, client);
|
|
7490
7519
|
let developerPortalPreflight = null;
|
|
@@ -7502,8 +7531,7 @@ async function runPreflight(path = ".", deps = {}) {
|
|
|
7502
7531
|
ok: true,
|
|
7503
7532
|
adapter_path: project.adapter_path,
|
|
7504
7533
|
registration_preflight: preflight,
|
|
7505
|
-
runtime_validation_path: project.runtime_validation_path ?? null
|
|
7506
|
-
oauth_credentials_path: project.oauth_credentials_path ?? null
|
|
7534
|
+
runtime_validation_path: project.runtime_validation_path ?? null
|
|
7507
7535
|
};
|
|
7508
7536
|
if (developerPortalPreflight) {
|
|
7509
7537
|
result.developer_portal_preflight = developerPortalPreflight;
|
|
@@ -7526,6 +7554,14 @@ async function getUsageReport(options, deps = {}) {
|
|
|
7526
7554
|
count: items.length
|
|
7527
7555
|
};
|
|
7528
7556
|
}
|
|
7557
|
+
async function listCompanyPublishersReport(deps = {}) {
|
|
7558
|
+
const client = await createClient(deps);
|
|
7559
|
+
const companies = await client.list_company_publishers();
|
|
7560
|
+
return {
|
|
7561
|
+
companies: companies.map((item) => toJsonable(item)),
|
|
7562
|
+
count: companies.length
|
|
7563
|
+
};
|
|
7564
|
+
}
|
|
7529
7565
|
async function diffJsonFiles(oldPath, newPath) {
|
|
7530
7566
|
const oldPayload = await loadJsonDocument(oldPath);
|
|
7531
7567
|
const newPayload = await loadJsonDocument(newPath);
|
|
@@ -7977,7 +8013,7 @@ function operationReadmeTemplate(operation, manifest, warning) {
|
|
|
7977
8013
|
"- `tool_manual.json`: machine-generated ToolManual scaffold",
|
|
7978
8014
|
"- `runtime_validation.json`: local public endpoint and review-key checks used by auto-register",
|
|
7979
8015
|
"- `docs/api-usage.md`: publishable API usage guide template for `docs_url`",
|
|
7980
|
-
"- `.gitignore`: keeps runtime review keys
|
|
8016
|
+
"- `.gitignore`: keeps runtime review keys out of Git",
|
|
7981
8017
|
"- `tests/test_adapter.ts`: smoke test for `AppTestHarness`",
|
|
7982
8018
|
"",
|
|
7983
8019
|
"Before registering, replace all generated placeholders:",
|
|
@@ -7985,8 +8021,8 @@ function operationReadmeTemplate(operation, manifest, warning) {
|
|
|
7985
8021
|
"- Replace `support_contact` with a real support email address or public support URL.",
|
|
7986
8022
|
"- Optional `seller_homepage_url` is the seller's official site and can stay blank.",
|
|
7987
8023
|
"- In the local `runtime_validation.json`, replace the public URL and review-key placeholders.",
|
|
7988
|
-
"- If the API uses
|
|
7989
|
-
"- Do not commit real review keys or
|
|
8024
|
+
"- If the API uses external OAuth, implement that flow in your API runtime and keep user tokens outside Siglume.",
|
|
8025
|
+
"- Do not commit real review keys or external-provider secrets; the generated `.gitignore` excludes local secret files.",
|
|
7990
8026
|
"- Because `runtime_validation.json` is ignored, GitHub samples do not commit review-key values.",
|
|
7991
8027
|
"",
|
|
7992
8028
|
"## Commands",
|
|
@@ -8062,8 +8098,6 @@ function generatedGitignore() {
|
|
|
8062
8098
|
"!.env.example",
|
|
8063
8099
|
"runtime_validation.json",
|
|
8064
8100
|
"runtime-validation.json",
|
|
8065
|
-
"oauth_credentials.json",
|
|
8066
|
-
"oauth-credentials.json",
|
|
8067
8101
|
"",
|
|
8068
8102
|
"# Python / test artifacts.",
|
|
8069
8103
|
"__pycache__/",
|
|
@@ -8209,13 +8243,6 @@ async function runHarnessForProject(project) {
|
|
|
8209
8243
|
checks.push(executionCheck("quote", await harness.execute_quote(task_type, { input_params: sample_input }), harness));
|
|
8210
8244
|
checks.push(executionCheck("payment", await harness.execute_payment(task_type, { input_params: sample_input }), harness));
|
|
8211
8245
|
}
|
|
8212
|
-
checks.push(
|
|
8213
|
-
executionCheck(
|
|
8214
|
-
"missing_account_simulation",
|
|
8215
|
-
await harness.simulate_connected_account_missing(task_type, { input_params: sample_input }),
|
|
8216
|
-
harness
|
|
8217
|
-
)
|
|
8218
|
-
);
|
|
8219
8246
|
return {
|
|
8220
8247
|
adapter_path: project.adapter_path,
|
|
8221
8248
|
task_type,
|
|
@@ -8318,15 +8345,6 @@ async function findRuntimeValidationPath(root_dir) {
|
|
|
8318
8345
|
}
|
|
8319
8346
|
return null;
|
|
8320
8347
|
}
|
|
8321
|
-
async function findOauthCredentialsPath(root_dir) {
|
|
8322
|
-
for (const name of ["oauth_credentials.json", "oauth-credentials.json"]) {
|
|
8323
|
-
const candidate = (0, import_node_path.join)(root_dir, name);
|
|
8324
|
-
if ((0, import_node_fs.existsSync)(candidate)) {
|
|
8325
|
-
return candidate;
|
|
8326
|
-
}
|
|
8327
|
-
}
|
|
8328
|
-
return null;
|
|
8329
|
-
}
|
|
8330
8348
|
async function loadJsonObject(path, label) {
|
|
8331
8349
|
let payload;
|
|
8332
8350
|
try {
|
|
@@ -8558,15 +8576,15 @@ function readmeTemplate(template) {
|
|
|
8558
8576
|
"- `tool_manual.json`: editable ToolManual draft for validation and registration",
|
|
8559
8577
|
"- `runtime_validation.json`: local live API smoke-test contract used during registration",
|
|
8560
8578
|
"- `docs/api-usage.md`: publish this page and use its public URL as `docs_url`",
|
|
8561
|
-
"- `.gitignore`: keeps runtime review keys
|
|
8579
|
+
"- `.gitignore`: keeps runtime review keys out of Git",
|
|
8562
8580
|
"",
|
|
8563
8581
|
"Before registering, replace all generated placeholders:",
|
|
8564
8582
|
"- In `adapter.ts` and `manifest.json`, replace `docs_url` with a dedicated public API usage guide, not a homepage.",
|
|
8565
8583
|
"- Replace `support_contact` with a real support email address or public support URL.",
|
|
8566
8584
|
"- Optional `seller_homepage_url` is the seller's official site and can stay blank.",
|
|
8567
8585
|
"- In the local `runtime_validation.json`, replace the public URL and review-key placeholders.",
|
|
8568
|
-
"- If the API uses
|
|
8569
|
-
"- Do not commit real review keys or
|
|
8586
|
+
"- If the API uses external OAuth, implement that flow in your API runtime and keep user tokens outside Siglume.",
|
|
8587
|
+
"- Do not commit real review keys or external-provider secrets; the generated `.gitignore` excludes local secret files.",
|
|
8570
8588
|
"- Because `runtime_validation.json` is ignored, GitHub samples do not commit review-key values.",
|
|
8571
8589
|
"",
|
|
8572
8590
|
"Suggested workflow:",
|
|
@@ -8612,6 +8630,24 @@ function renderOperationTable(operations) {
|
|
|
8612
8630
|
...rows.map((row) => row.map((cell, index) => cell.padEnd(widths[index] ?? cell.length)).join(" "))
|
|
8613
8631
|
];
|
|
8614
8632
|
}
|
|
8633
|
+
function renderCompanyTable(companies) {
|
|
8634
|
+
const rows = companies.map((item) => [
|
|
8635
|
+
String(item.company_id ?? item.id ?? ""),
|
|
8636
|
+
String(item.name ?? ""),
|
|
8637
|
+
String(item.membership_role ?? (item.is_founder ? "founder" : "")),
|
|
8638
|
+
String(item.settlement_wallet_ready === true ? "ready" : "not_ready"),
|
|
8639
|
+
String(item.pending_approval_count ?? 0)
|
|
8640
|
+
]);
|
|
8641
|
+
const headers = ["company_id", "name", "role", "settlement", "pending"];
|
|
8642
|
+
const widths = headers.map(
|
|
8643
|
+
(header, index) => Math.max(header.length, ...rows.map((row) => row[index]?.length ?? 0))
|
|
8644
|
+
);
|
|
8645
|
+
return [
|
|
8646
|
+
headers.map((header, index) => header.padEnd(widths[index] ?? header.length)).join(" "),
|
|
8647
|
+
widths.map((width) => "-".repeat(width)).join(" "),
|
|
8648
|
+
...rows.map((row) => row.map((cell, index) => cell.padEnd(widths[index] ?? cell.length)).join(" "))
|
|
8649
|
+
];
|
|
8650
|
+
}
|
|
8615
8651
|
async function runCli(argv, deps = {}) {
|
|
8616
8652
|
const stdout = deps.stdout;
|
|
8617
8653
|
const stderr = deps.stderr ?? console.error;
|
|
@@ -8766,9 +8802,22 @@ async function runCli(argv, deps = {}) {
|
|
|
8766
8802
|
emit(stdout, `preflight_quality: ${preflight.remote_quality.grade} (${preflight.remote_quality.overall_score}/100)`);
|
|
8767
8803
|
}
|
|
8768
8804
|
if (report.runtime_validation_path) emit(stdout, `runtime_validation_path: ${String(report.runtime_validation_path)}`);
|
|
8769
|
-
if (report.oauth_credentials_path) emit(stdout, `oauth_credentials_path: ${String(report.oauth_credentials_path)}`);
|
|
8770
8805
|
});
|
|
8771
|
-
program.command("
|
|
8806
|
+
program.command("companies").description("List Siglume companies available for company-name publishing.").option("--json", "emit machine-readable JSON", false).action(async (options) => {
|
|
8807
|
+
const report = await listCompanyPublishersReport(deps);
|
|
8808
|
+
if (options.json) {
|
|
8809
|
+
emit(stdout, renderJson(report));
|
|
8810
|
+
return;
|
|
8811
|
+
}
|
|
8812
|
+
const companies = Array.isArray(report.companies) ? report.companies.filter((item) => Boolean(item && typeof item === "object")) : [];
|
|
8813
|
+
if (companies.length === 0) {
|
|
8814
|
+
emit(stdout, "No company publishers available for this API key.");
|
|
8815
|
+
return;
|
|
8816
|
+
}
|
|
8817
|
+
emit(stdout, "Company publishers");
|
|
8818
|
+
renderCompanyTable(companies).forEach((line) => emit(stdout, line));
|
|
8819
|
+
});
|
|
8820
|
+
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) => {
|
|
8772
8821
|
const draftOnly = Boolean(options.draftOnly);
|
|
8773
8822
|
if (draftOnly && options.confirm) {
|
|
8774
8823
|
throw new SiglumeProjectError("--draft-only cannot be combined with --confirm.");
|
|
@@ -8777,7 +8826,13 @@ async function runCli(argv, deps = {}) {
|
|
|
8777
8826
|
throw new SiglumeProjectError("--draft-only cannot be combined with --submit-review.");
|
|
8778
8827
|
}
|
|
8779
8828
|
const shouldConfirm = Boolean(options.confirm) || !draftOnly && !options.submitReview;
|
|
8780
|
-
const report = await runRegistration(path, {
|
|
8829
|
+
const report = await runRegistration(path, {
|
|
8830
|
+
confirm: shouldConfirm,
|
|
8831
|
+
draft_only: draftOnly,
|
|
8832
|
+
submit_review: options.submitReview,
|
|
8833
|
+
company_id: options.company,
|
|
8834
|
+
company_slug: options.companySlug
|
|
8835
|
+
}, deps);
|
|
8781
8836
|
if (options.json) {
|
|
8782
8837
|
emit(stdout, renderJson(report));
|
|
8783
8838
|
} else {
|
|
@@ -8797,7 +8852,6 @@ async function runCli(argv, deps = {}) {
|
|
|
8797
8852
|
emit(stdout, `listing_id: ${receipt.listing_id}`);
|
|
8798
8853
|
emit(stdout, `receipt_status: ${receipt.status}`);
|
|
8799
8854
|
if (receipt.listing_status) emit(stdout, `listing_status: ${receipt.listing_status}`);
|
|
8800
|
-
if (receipt.oauth_status) emit(stdout, `oauth_configured: ${Boolean(receipt.oauth_status.configured)}`);
|
|
8801
8855
|
if (receipt.review_url) emit(stdout, `review_url: ${receipt.review_url}`);
|
|
8802
8856
|
if (receipt.trace_id) emit(stdout, `trace_id: ${receipt.trace_id}`);
|
|
8803
8857
|
if (receipt.request_id) emit(stdout, `request_id: ${receipt.request_id}`);
|