@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.js
CHANGED
|
@@ -1226,6 +1226,56 @@ var init_operations = __esm({
|
|
|
1226
1226
|
});
|
|
1227
1227
|
|
|
1228
1228
|
// src/client.ts
|
|
1229
|
+
function validateManifestPersistenceContract(payload) {
|
|
1230
|
+
const vertical = String(payload.store_vertical ?? "").trim().toLowerCase();
|
|
1231
|
+
const persistence = payload.persistence;
|
|
1232
|
+
if (persistence === void 0 || persistence === null) {
|
|
1233
|
+
return;
|
|
1234
|
+
}
|
|
1235
|
+
if (!isRecord(persistence)) {
|
|
1236
|
+
throw new SiglumeClientError("AppManifest.persistence must be an object.");
|
|
1237
|
+
}
|
|
1238
|
+
const mode = String(persistence.mode ?? (vertical === "game" ? "platform" : "none")).trim().toLowerCase();
|
|
1239
|
+
if (!["none", "local", "platform", "developer_server"].includes(mode)) {
|
|
1240
|
+
throw new SiglumeClientError(
|
|
1241
|
+
"AppManifest.persistence.mode must be one of: none, local, platform, developer_server."
|
|
1242
|
+
);
|
|
1243
|
+
}
|
|
1244
|
+
const schema = persistence.save_data_schema;
|
|
1245
|
+
if (vertical === "game" && mode !== "none" && schema === void 0) {
|
|
1246
|
+
throw new SiglumeClientError(
|
|
1247
|
+
"AppManifest.persistence.save_data_schema is required when store_vertical='game' and persistence.mode is not 'none'."
|
|
1248
|
+
);
|
|
1249
|
+
}
|
|
1250
|
+
if (schema !== void 0) {
|
|
1251
|
+
validateSaveDataSchema(schema, "AppManifest.persistence.save_data_schema");
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
function validateSaveDataSchema(schema, fieldName) {
|
|
1255
|
+
if (!isRecord(schema)) {
|
|
1256
|
+
throw new SiglumeClientError(`${fieldName} must be a JSON Schema object.`);
|
|
1257
|
+
}
|
|
1258
|
+
const schemaSize = new TextEncoder().encode(JSON.stringify(schema)).length;
|
|
1259
|
+
if (schemaSize > 8192) {
|
|
1260
|
+
throw new SiglumeClientError(`${fieldName} must be at most 8192 bytes.`);
|
|
1261
|
+
}
|
|
1262
|
+
if (schema.type !== "object") {
|
|
1263
|
+
throw new SiglumeClientError(`${fieldName}.type must be 'object'.`);
|
|
1264
|
+
}
|
|
1265
|
+
const properties = schema.properties;
|
|
1266
|
+
if (!isRecord(properties) || Object.keys(properties).length === 0) {
|
|
1267
|
+
throw new SiglumeClientError(`${fieldName}.properties must be a non-empty object.`);
|
|
1268
|
+
}
|
|
1269
|
+
if (schema.required !== void 0) {
|
|
1270
|
+
if (!Array.isArray(schema.required) || !schema.required.every((item) => typeof item === "string")) {
|
|
1271
|
+
throw new SiglumeClientError(`${fieldName}.required must be an array of strings when provided.`);
|
|
1272
|
+
}
|
|
1273
|
+
const missing = schema.required.filter((item) => !(item in properties));
|
|
1274
|
+
if (missing.length > 0) {
|
|
1275
|
+
throw new SiglumeClientError(`${fieldName}.required references undefined properties: ${missing.join(", ")}.`);
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1229
1279
|
function buildToolManualQualityReport(payload) {
|
|
1230
1280
|
const qualityBlock = isRecord(payload.quality) ? payload.quality : payload;
|
|
1231
1281
|
const issues = [];
|
|
@@ -1300,6 +1350,8 @@ function buildUrl(baseUrl, path, params) {
|
|
|
1300
1350
|
return url.toString();
|
|
1301
1351
|
}
|
|
1302
1352
|
function parseListing(data) {
|
|
1353
|
+
const metadata = isRecord(data.metadata) ? data.metadata : {};
|
|
1354
|
+
const persistence = isRecord(data.persistence) ? data.persistence : isRecord(metadata.persistence) ? metadata.persistence : {};
|
|
1303
1355
|
return {
|
|
1304
1356
|
listing_id: String(data.listing_id ?? data.id ?? ""),
|
|
1305
1357
|
capability_key: String(data.capability_key ?? ""),
|
|
@@ -1322,14 +1374,59 @@ function parseListing(data) {
|
|
|
1322
1374
|
seller_display_name: stringOrNull(data.seller_display_name),
|
|
1323
1375
|
seller_homepage_url: stringOrNull(data.seller_homepage_url),
|
|
1324
1376
|
seller_social_url: stringOrNull(data.seller_social_url),
|
|
1377
|
+
publisher_type: stringOrNull(data.publisher_type),
|
|
1378
|
+
publisher_company_id: stringOrNull(data.publisher_company_id),
|
|
1379
|
+
company_id: stringOrNull(data.company_id),
|
|
1380
|
+
company_name: stringOrNull(data.company_name),
|
|
1381
|
+
company_publish_status: stringOrNull(data.company_publish_status),
|
|
1382
|
+
company_terms_version: stringOrNull(data.company_terms_version),
|
|
1325
1383
|
review_status: stringOrNull(data.review_status),
|
|
1326
1384
|
review_note: stringOrNull(data.review_note),
|
|
1327
1385
|
submission_blockers: Array.isArray(data.submission_blockers) ? data.submission_blockers.filter((item) => typeof item === "string") : [],
|
|
1386
|
+
persistence: { ...persistence },
|
|
1328
1387
|
created_at: stringOrNull(data.created_at),
|
|
1329
1388
|
updated_at: stringOrNull(data.updated_at),
|
|
1330
1389
|
raw: { ...data }
|
|
1331
1390
|
};
|
|
1332
1391
|
}
|
|
1392
|
+
function parseCompanyPublisher(data) {
|
|
1393
|
+
const wallets = Array.isArray(data.settlement_wallets) ? data.settlement_wallets.filter((item) => isRecord(item)) : [];
|
|
1394
|
+
return {
|
|
1395
|
+
company_id: String(data.company_id ?? data.id ?? ""),
|
|
1396
|
+
name: String(data.name ?? ""),
|
|
1397
|
+
status: String(data.status ?? ""),
|
|
1398
|
+
description: stringOrNull(data.description),
|
|
1399
|
+
is_founder: Boolean(data.is_founder ?? false),
|
|
1400
|
+
membership_role: stringOrNull(data.membership_role),
|
|
1401
|
+
membership_status: stringOrNull(data.membership_status),
|
|
1402
|
+
can_publish: Boolean(data.can_publish ?? true),
|
|
1403
|
+
can_approve: Boolean(data.can_approve ?? false),
|
|
1404
|
+
approval_required: Boolean(data.approval_required ?? false),
|
|
1405
|
+
paid_listing_allowed: Boolean(data.paid_listing_allowed ?? false),
|
|
1406
|
+
disabled_reasons: Array.isArray(data.disabled_reasons) ? data.disabled_reasons.filter((item) => typeof item === "string") : [],
|
|
1407
|
+
company_terms_version: stringOrNull(data.company_terms_version),
|
|
1408
|
+
active_listing_count: Number(data.active_listing_count ?? 0),
|
|
1409
|
+
pending_approval_count: Number(data.pending_approval_count ?? 0),
|
|
1410
|
+
settlement_wallet_ready: Boolean(data.settlement_wallet_ready ?? false),
|
|
1411
|
+
settlement_wallets: wallets.map((item) => ({ ...item })),
|
|
1412
|
+
raw: { ...data }
|
|
1413
|
+
};
|
|
1414
|
+
}
|
|
1415
|
+
function parseCapabilitySaveState(data) {
|
|
1416
|
+
return {
|
|
1417
|
+
capability_key: String(data.capability_key ?? ""),
|
|
1418
|
+
save_key: String(data.save_key ?? ""),
|
|
1419
|
+
schema_version: String(data.schema_version ?? "1"),
|
|
1420
|
+
revision: Number(data.revision ?? 0),
|
|
1421
|
+
payload: toRecord(data.payload),
|
|
1422
|
+
metadata: toRecord(data.metadata),
|
|
1423
|
+
checksum: stringOrNull(data.checksum),
|
|
1424
|
+
updated_at: stringOrNull(data.updated_at),
|
|
1425
|
+
created_at: stringOrNull(data.created_at),
|
|
1426
|
+
exists: Boolean(data.exists ?? false),
|
|
1427
|
+
raw: { ...data }
|
|
1428
|
+
};
|
|
1429
|
+
}
|
|
1333
1430
|
function parseBundleMember(data) {
|
|
1334
1431
|
return {
|
|
1335
1432
|
capability_listing_id: String(data.capability_listing_id ?? ""),
|
|
@@ -1341,18 +1438,6 @@ function parseBundleMember(data) {
|
|
|
1341
1438
|
link_id: stringOrNull(data.link_id)
|
|
1342
1439
|
};
|
|
1343
1440
|
}
|
|
1344
|
-
function parseConnectedAccountLifecycle(data) {
|
|
1345
|
-
return {
|
|
1346
|
-
connected_account_id: String(data.connected_account_id ?? ""),
|
|
1347
|
-
provider_key: String(data.provider_key ?? ""),
|
|
1348
|
-
expires_at: stringOrNull(data.expires_at),
|
|
1349
|
-
scopes: Array.isArray(data.scopes) ? data.scopes.filter((s) => typeof s === "string") : [],
|
|
1350
|
-
refreshed_at: stringOrNull(data.refreshed_at),
|
|
1351
|
-
connection_status: stringOrNull(data.connection_status),
|
|
1352
|
-
provider_revoked: typeof data.provider_revoked === "boolean" ? data.provider_revoked : null,
|
|
1353
|
-
revoked_at: stringOrNull(data.revoked_at)
|
|
1354
|
-
};
|
|
1355
|
-
}
|
|
1356
1441
|
function parseBundle(data) {
|
|
1357
1442
|
const membersRaw = Array.isArray(data.members) ? data.members : [];
|
|
1358
1443
|
return {
|
|
@@ -1431,21 +1516,6 @@ function parseBinding(data) {
|
|
|
1431
1516
|
raw: { ...data }
|
|
1432
1517
|
};
|
|
1433
1518
|
}
|
|
1434
|
-
function parseConnectedAccount(data) {
|
|
1435
|
-
return {
|
|
1436
|
-
connected_account_id: String(data.connected_account_id ?? data.id ?? ""),
|
|
1437
|
-
provider_key: String(data.provider_key ?? ""),
|
|
1438
|
-
account_role: String(data.account_role ?? ""),
|
|
1439
|
-
display_name: stringOrNull(data.display_name),
|
|
1440
|
-
environment: stringOrNull(data.environment),
|
|
1441
|
-
connection_status: stringOrNull(data.connection_status),
|
|
1442
|
-
scopes: Array.isArray(data.scopes) ? data.scopes.filter((item) => typeof item === "string") : [],
|
|
1443
|
-
metadata: toRecord(data.metadata),
|
|
1444
|
-
created_at: stringOrNull(data.created_at),
|
|
1445
|
-
updated_at: stringOrNull(data.updated_at),
|
|
1446
|
-
raw: { ...data }
|
|
1447
|
-
};
|
|
1448
|
-
}
|
|
1449
1519
|
function parseSupportCase(data) {
|
|
1450
1520
|
return {
|
|
1451
1521
|
support_case_id: String(data.support_case_id ?? data.id ?? ""),
|
|
@@ -2484,13 +2554,6 @@ var init_client = __esm({
|
|
|
2484
2554
|
if (options.runtime_validation) {
|
|
2485
2555
|
payload.runtime_validation = coerceMapping(options.runtime_validation, "runtime_validation");
|
|
2486
2556
|
}
|
|
2487
|
-
if (options.oauth_credentials) {
|
|
2488
|
-
payload.oauth_credentials = Array.isArray(options.oauth_credentials) ? {
|
|
2489
|
-
items: options.oauth_credentials.map(
|
|
2490
|
-
(item, index) => coerceMapping(item, `oauth_credentials[${index}]`)
|
|
2491
|
-
)
|
|
2492
|
-
} : coerceMapping(options.oauth_credentials, "oauth_credentials");
|
|
2493
|
-
}
|
|
2494
2557
|
if (options.source_context) {
|
|
2495
2558
|
payload.source_context = coerceMapping(options.source_context, "source_context");
|
|
2496
2559
|
}
|
|
@@ -2509,6 +2572,9 @@ var init_client = __esm({
|
|
|
2509
2572
|
"support_contact",
|
|
2510
2573
|
"seller_homepage_url",
|
|
2511
2574
|
"seller_social_url",
|
|
2575
|
+
"publisher_type",
|
|
2576
|
+
"company_id",
|
|
2577
|
+
"publisher_company_id",
|
|
2512
2578
|
"store_vertical",
|
|
2513
2579
|
"jurisdiction",
|
|
2514
2580
|
"price_model",
|
|
@@ -2521,7 +2587,8 @@ var init_client = __esm({
|
|
|
2521
2587
|
"dry_run_supported",
|
|
2522
2588
|
"required_connected_accounts",
|
|
2523
2589
|
"permission_scopes",
|
|
2524
|
-
"compatibility_tags"
|
|
2590
|
+
"compatibility_tags",
|
|
2591
|
+
"persistence"
|
|
2525
2592
|
]) {
|
|
2526
2593
|
const value = manifestPayload[fieldName];
|
|
2527
2594
|
if (value !== void 0 && value !== null) {
|
|
@@ -2561,6 +2628,26 @@ var init_client = __esm({
|
|
|
2561
2628
|
);
|
|
2562
2629
|
}
|
|
2563
2630
|
}
|
|
2631
|
+
const explicitPublisherType = payload.publisher_type !== void 0 && payload.publisher_type !== null;
|
|
2632
|
+
const companyId = String(payload.company_id ?? "").trim() || String(payload.publisher_company_id ?? "").trim();
|
|
2633
|
+
const publisherType = String(payload.publisher_type ?? "user").trim().toLowerCase();
|
|
2634
|
+
if (publisherType !== "user" && publisherType !== "company") {
|
|
2635
|
+
throw new SiglumeClientError("AppManifest.publisher_type must be 'user' or 'company'.");
|
|
2636
|
+
}
|
|
2637
|
+
if (publisherType === "company" && !companyId) {
|
|
2638
|
+
throw new SiglumeClientError("AppManifest.company_id is required when publisher_type='company'.");
|
|
2639
|
+
}
|
|
2640
|
+
if (publisherType === "user" && companyId) {
|
|
2641
|
+
throw new SiglumeClientError("AppManifest.company_id cannot be combined with publisher_type='user'.");
|
|
2642
|
+
}
|
|
2643
|
+
if (explicitPublisherType || companyId) {
|
|
2644
|
+
payload.publisher_type = publisherType;
|
|
2645
|
+
}
|
|
2646
|
+
if (companyId) {
|
|
2647
|
+
payload.company_id = companyId;
|
|
2648
|
+
payload.publisher_company_id = companyId;
|
|
2649
|
+
}
|
|
2650
|
+
validateManifestPersistenceContract(payload);
|
|
2564
2651
|
if (payload.manifest && typeof payload.manifest === "object") {
|
|
2565
2652
|
delete payload.manifest.version;
|
|
2566
2653
|
}
|
|
@@ -2596,7 +2683,6 @@ var init_client = __esm({
|
|
|
2596
2683
|
auto_manifest: toRecord(data.auto_manifest),
|
|
2597
2684
|
confidence: toRecord(data.confidence),
|
|
2598
2685
|
validation_report: toRecord(data.validation_report),
|
|
2599
|
-
oauth_status: toRecord(data.oauth_status),
|
|
2600
2686
|
review_url: stringOrNull(data.review_url),
|
|
2601
2687
|
trace_id: meta.trace_id,
|
|
2602
2688
|
request_id: meta.request_id
|
|
@@ -2668,6 +2754,45 @@ var init_client = __esm({
|
|
|
2668
2754
|
const [data] = await this.request("GET", `/market/capabilities/${listing_id}`);
|
|
2669
2755
|
return parseListing(data);
|
|
2670
2756
|
}
|
|
2757
|
+
async list_company_publishers() {
|
|
2758
|
+
const [data] = await this.request("GET", "/market/company-publishers");
|
|
2759
|
+
return Array.isArray(data.items) ? data.items.filter((item) => isRecord(item)).map(parseCompanyPublisher) : [];
|
|
2760
|
+
}
|
|
2761
|
+
async request_company_publish_approval(listing_id, note) {
|
|
2762
|
+
const [data] = await this.request("POST", `/market/capabilities/${listing_id}/company-publish-approval`, {
|
|
2763
|
+
json_body: note ? { note } : {}
|
|
2764
|
+
});
|
|
2765
|
+
return parseListing(data);
|
|
2766
|
+
}
|
|
2767
|
+
async decide_company_publish_approval(listing_id, options) {
|
|
2768
|
+
const [data] = await this.request("POST", `/market/capabilities/${listing_id}/company-publish-approval/decision`, {
|
|
2769
|
+
json_body: {
|
|
2770
|
+
decision: options.decision,
|
|
2771
|
+
...options.reason ? { reason: options.reason } : {}
|
|
2772
|
+
}
|
|
2773
|
+
});
|
|
2774
|
+
return parseListing(data);
|
|
2775
|
+
}
|
|
2776
|
+
async get_capability_state(capability_key, save_key = "default") {
|
|
2777
|
+
const [data] = await this.request("GET", `/market/capability-state/${capability_key}/${save_key}`);
|
|
2778
|
+
return parseCapabilitySaveState(data);
|
|
2779
|
+
}
|
|
2780
|
+
async put_capability_state(capability_key, save_key = "default", payload = {}, options = {}) {
|
|
2781
|
+
const body = {
|
|
2782
|
+
payload: toRecord(payload),
|
|
2783
|
+
schema_version: options.schema_version ?? "1",
|
|
2784
|
+
metadata: toRecord(options.metadata)
|
|
2785
|
+
};
|
|
2786
|
+
if (options.expected_revision !== void 0 && options.expected_revision !== null) {
|
|
2787
|
+
body.expected_revision = Math.trunc(options.expected_revision);
|
|
2788
|
+
}
|
|
2789
|
+
const [data] = await this.request("PUT", `/market/capability-state/${capability_key}/${save_key}`, { json_body: body });
|
|
2790
|
+
return parseCapabilitySaveState(data);
|
|
2791
|
+
}
|
|
2792
|
+
async delete_capability_state(capability_key, save_key = "default") {
|
|
2793
|
+
const [data] = await this.request("DELETE", `/market/capability-state/${capability_key}/${save_key}`);
|
|
2794
|
+
return parseCapabilitySaveState(data);
|
|
2795
|
+
}
|
|
2671
2796
|
// ----- Capability bundles (v0.7 track 2) ---------------------------------
|
|
2672
2797
|
async list_bundles(options = {}) {
|
|
2673
2798
|
const params = {
|
|
@@ -2733,66 +2858,9 @@ var init_client = __esm({
|
|
|
2733
2858
|
return parseBundle(data);
|
|
2734
2859
|
}
|
|
2735
2860
|
// ----- end bundles -------------------------------------------------------
|
|
2736
|
-
// ----- Connected accounts
|
|
2737
|
-
//
|
|
2738
|
-
|
|
2739
|
-
const body = {
|
|
2740
|
-
listing_id: input.listing_id,
|
|
2741
|
-
redirect_uri: input.redirect_uri
|
|
2742
|
-
};
|
|
2743
|
-
if (input.scopes !== void 0) body.scopes = input.scopes;
|
|
2744
|
-
if (input.account_role !== void 0) body.account_role = input.account_role;
|
|
2745
|
-
const [data] = await this.request("POST", "/me/connected-accounts/oauth/authorize", {
|
|
2746
|
-
json_body: body
|
|
2747
|
-
});
|
|
2748
|
-
return {
|
|
2749
|
-
authorize_url: String(data.authorize_url ?? ""),
|
|
2750
|
-
state: String(data.state ?? ""),
|
|
2751
|
-
provider_key: String(data.provider_key ?? ""),
|
|
2752
|
-
scopes: Array.isArray(data.scopes) ? data.scopes.filter((s) => typeof s === "string") : [],
|
|
2753
|
-
pkce_method: stringOrNull(data.pkce_method)
|
|
2754
|
-
};
|
|
2755
|
-
}
|
|
2756
|
-
async complete_connected_account_oauth(input) {
|
|
2757
|
-
const [data] = await this.request("POST", "/me/connected-accounts/oauth/callback", {
|
|
2758
|
-
json_body: { state: input.state, code: input.code }
|
|
2759
|
-
});
|
|
2760
|
-
return { ...data };
|
|
2761
|
-
}
|
|
2762
|
-
async refresh_connected_account(account_id) {
|
|
2763
|
-
const [data] = await this.request("POST", `/me/connected-accounts/${account_id}/refresh`);
|
|
2764
|
-
return parseConnectedAccountLifecycle(data);
|
|
2765
|
-
}
|
|
2766
|
-
async revoke_connected_account(account_id) {
|
|
2767
|
-
const [data] = await this.request("POST", `/me/connected-accounts/${account_id}/revoke`);
|
|
2768
|
-
return parseConnectedAccountLifecycle(data);
|
|
2769
|
-
}
|
|
2770
|
-
async set_listing_oauth_credentials(listing_id, input) {
|
|
2771
|
-
const body = {
|
|
2772
|
-
provider_key: input.provider_key,
|
|
2773
|
-
client_id: input.client_id,
|
|
2774
|
-
client_secret: input.client_secret,
|
|
2775
|
-
authorize_url: input.authorize_url,
|
|
2776
|
-
token_url: input.token_url
|
|
2777
|
-
};
|
|
2778
|
-
if (input.revoke_url !== void 0) body.revoke_url = input.revoke_url;
|
|
2779
|
-
if (input.display_name !== void 0) body.display_name = input.display_name;
|
|
2780
|
-
if (input.scope_separator !== void 0) body.scope_separator = input.scope_separator;
|
|
2781
|
-
if (input.token_endpoint_auth !== void 0) body.token_endpoint_auth = input.token_endpoint_auth;
|
|
2782
|
-
if (input.pkce_required !== void 0) body.pkce_required = input.pkce_required;
|
|
2783
|
-
if (input.refresh_supported !== void 0) body.refresh_supported = input.refresh_supported;
|
|
2784
|
-
if (input.available_scopes !== void 0) body.available_scopes = input.available_scopes;
|
|
2785
|
-
if (input.required_scopes !== void 0) body.required_scopes = input.required_scopes;
|
|
2786
|
-
const [data] = await this.request("PUT", `/market/capabilities/${listing_id}/oauth-credentials`, {
|
|
2787
|
-
json_body: body
|
|
2788
|
-
});
|
|
2789
|
-
return { ...data };
|
|
2790
|
-
}
|
|
2791
|
-
async get_listing_oauth_credentials_status(listing_id) {
|
|
2792
|
-
const [data] = await this.request("GET", `/market/capabilities/${listing_id}/oauth-credentials`);
|
|
2793
|
-
return { ...data };
|
|
2794
|
-
}
|
|
2795
|
-
// ----- end connected accounts --------------------------------------------
|
|
2861
|
+
// ----- Connected accounts ------------------------------------------------
|
|
2862
|
+
// Architecture B: publisher APIs own external OAuth and token storage.
|
|
2863
|
+
// The SDK no longer exposes platform OAuth or listing credential APIs.
|
|
2796
2864
|
async get_developer_portal() {
|
|
2797
2865
|
const [data, meta] = await this.request("GET", "/market/developer/portal");
|
|
2798
2866
|
return {
|
|
@@ -2825,7 +2893,6 @@ var init_client = __esm({
|
|
|
2825
2893
|
dry_run_supported: Boolean(data.dry_run_supported ?? false),
|
|
2826
2894
|
approval_mode: stringOrNull(data.approval_mode),
|
|
2827
2895
|
required_connected_accounts: Array.isArray(data.required_connected_accounts) ? data.required_connected_accounts : [],
|
|
2828
|
-
connected_accounts: Array.isArray(data.connected_accounts) ? data.connected_accounts.filter((item) => isRecord(item)).map((item) => ({ ...item })) : [],
|
|
2829
2896
|
stub_providers_enabled: Boolean(data.stub_providers_enabled ?? false),
|
|
2830
2897
|
simulated_receipts: Boolean(data.simulated_receipts ?? false),
|
|
2831
2898
|
approval_simulator: Boolean(data.approval_simulator ?? false),
|
|
@@ -4123,25 +4190,6 @@ var init_client = __esm({
|
|
|
4123
4190
|
raw: { ...data }
|
|
4124
4191
|
};
|
|
4125
4192
|
}
|
|
4126
|
-
async list_connected_accounts(options = {}) {
|
|
4127
|
-
const params = {
|
|
4128
|
-
provider_key: options.provider_key,
|
|
4129
|
-
environment: options.environment,
|
|
4130
|
-
limit: Math.max(1, Math.min(Math.trunc(options.limit ?? 50), 100)),
|
|
4131
|
-
cursor: options.cursor
|
|
4132
|
-
};
|
|
4133
|
-
const [data, meta] = await this.request("GET", "/market/connected-accounts", { params });
|
|
4134
|
-
const items = Array.isArray(data.items) ? data.items.filter((item) => isRecord(item)).map(parseConnectedAccount) : [];
|
|
4135
|
-
const next_cursor = stringOrNull(data.next_cursor);
|
|
4136
|
-
return new CursorPageResult({
|
|
4137
|
-
items,
|
|
4138
|
-
next_cursor,
|
|
4139
|
-
limit: typeof data.limit === "number" ? data.limit : params.limit,
|
|
4140
|
-
offset: typeof data.offset === "number" ? data.offset : null,
|
|
4141
|
-
meta,
|
|
4142
|
-
fetchNext: next_cursor ? (cursor) => this.list_connected_accounts({ ...options, cursor }) : void 0
|
|
4143
|
-
});
|
|
4144
|
-
}
|
|
4145
4193
|
async create_support_case(subject, body, options = {}) {
|
|
4146
4194
|
const summary = subject.trim();
|
|
4147
4195
|
const details = body.trim();
|
|
@@ -5985,24 +6033,12 @@ var AppTestHarness = class {
|
|
|
5985
6033
|
this.stubs = stubs;
|
|
5986
6034
|
}
|
|
5987
6035
|
async executeWithKind(execution_kind, task_type = "default", options = {}) {
|
|
5988
|
-
const connected_accounts = options.connected_accounts ?? Object.fromEntries(
|
|
5989
|
-
Object.keys(this.stubs).map((key) => [
|
|
5990
|
-
key,
|
|
5991
|
-
{
|
|
5992
|
-
provider_key: key,
|
|
5993
|
-
session_token: `stub-token-${key}`,
|
|
5994
|
-
environment: Environment.SANDBOX,
|
|
5995
|
-
scopes: []
|
|
5996
|
-
}
|
|
5997
|
-
])
|
|
5998
|
-
);
|
|
5999
6036
|
const ctx = {
|
|
6000
6037
|
agent_id: "test-agent-001",
|
|
6001
6038
|
owner_user_id: "test-owner-001",
|
|
6002
6039
|
task_type,
|
|
6003
6040
|
environment: Environment.SANDBOX,
|
|
6004
6041
|
execution_kind,
|
|
6005
|
-
connected_accounts,
|
|
6006
6042
|
input_params: options.input_params ?? {},
|
|
6007
6043
|
trace_id: options.trace_id,
|
|
6008
6044
|
idempotency_key: options.idempotency_key,
|
|
@@ -6092,12 +6128,6 @@ var AppTestHarness = class {
|
|
|
6092
6128
|
}
|
|
6093
6129
|
return issues;
|
|
6094
6130
|
}
|
|
6095
|
-
async simulate_connected_account_missing(task_type = "default", options = {}) {
|
|
6096
|
-
return this.executeWithKind("dry_run", task_type, {
|
|
6097
|
-
...options,
|
|
6098
|
-
connected_accounts: {}
|
|
6099
|
-
});
|
|
6100
|
-
}
|
|
6101
6131
|
async simulate_metering(record, options = {}) {
|
|
6102
6132
|
const { normalizeUsageRecord: normalizeUsageRecord2 } = await Promise.resolve().then(() => (init_metering(), metering_exports));
|
|
6103
6133
|
const manifest = await this.app.manifest();
|
|
@@ -7060,15 +7090,6 @@ async function loadProject(path = ".") {
|
|
|
7060
7090
|
const tool_manual = tool_manual_path ? JSON.parse(await readFile(tool_manual_path, "utf8")) : buildToolManualTemplate(manifest);
|
|
7061
7091
|
const runtime_validation_path = await findRuntimeValidationPath(root_dir);
|
|
7062
7092
|
const runtime_validation = runtime_validation_path ? await loadJsonObject(runtime_validation_path, "runtime_validation") : void 0;
|
|
7063
|
-
const oauth_credentials_path = await findOauthCredentialsPath(root_dir);
|
|
7064
|
-
let oauth_credentials;
|
|
7065
|
-
if (oauth_credentials_path) {
|
|
7066
|
-
const parsed = JSON.parse(await readFile(oauth_credentials_path, "utf8"));
|
|
7067
|
-
if (!isRecord(parsed) && !Array.isArray(parsed)) {
|
|
7068
|
-
throw new SiglumeProjectError("oauth_credentials must be a JSON object or array");
|
|
7069
|
-
}
|
|
7070
|
-
oauth_credentials = parsed;
|
|
7071
|
-
}
|
|
7072
7093
|
return {
|
|
7073
7094
|
root_dir,
|
|
7074
7095
|
adapter_path,
|
|
@@ -7077,9 +7098,7 @@ async function loadProject(path = ".") {
|
|
|
7077
7098
|
tool_manual_path: tool_manual_path ?? void 0,
|
|
7078
7099
|
tool_manual,
|
|
7079
7100
|
runtime_validation_path: runtime_validation_path ?? void 0,
|
|
7080
|
-
runtime_validation
|
|
7081
|
-
oauth_credentials_path: oauth_credentials_path ?? void 0,
|
|
7082
|
-
oauth_credentials
|
|
7101
|
+
runtime_validation
|
|
7083
7102
|
};
|
|
7084
7103
|
}
|
|
7085
7104
|
function isPlatformManagedRequirement(value) {
|
|
@@ -7117,6 +7136,21 @@ function requiredOauthProviders(requirements) {
|
|
|
7117
7136
|
}
|
|
7118
7137
|
return providers;
|
|
7119
7138
|
}
|
|
7139
|
+
function apiManagedRequirementsMissingConnectUrl(requirements) {
|
|
7140
|
+
const missing = [];
|
|
7141
|
+
for (const item of requirements ?? []) {
|
|
7142
|
+
if (!isRecord(item)) continue;
|
|
7143
|
+
const managedBy = String(item.managed_by ?? "").trim().toLowerCase().replaceAll("_", "-");
|
|
7144
|
+
if (managedBy !== "api") continue;
|
|
7145
|
+
const connectUrl = String(item.connect_url ?? "").trim();
|
|
7146
|
+
if (connectUrl) continue;
|
|
7147
|
+
const label = oauthProviderKeyFromRequirement(item) ?? "(missing provider_key)";
|
|
7148
|
+
if (!missing.includes(label)) {
|
|
7149
|
+
missing.push(label);
|
|
7150
|
+
}
|
|
7151
|
+
}
|
|
7152
|
+
return missing;
|
|
7153
|
+
}
|
|
7120
7154
|
function connectedAccountRequirementLabel(value) {
|
|
7121
7155
|
if (isRecord(value)) {
|
|
7122
7156
|
for (const key of ["provider_key", "provider", "account_type", "name"]) {
|
|
@@ -7127,102 +7161,6 @@ function connectedAccountRequirementLabel(value) {
|
|
|
7127
7161
|
}
|
|
7128
7162
|
return String(value ?? "").trim();
|
|
7129
7163
|
}
|
|
7130
|
-
function oauthProviderRecordsMap(payload) {
|
|
7131
|
-
if (!payload) {
|
|
7132
|
-
return {};
|
|
7133
|
-
}
|
|
7134
|
-
const items = Array.isArray(payload) ? payload : Array.isArray(payload.items) ? payload.items : [payload];
|
|
7135
|
-
const resolved = {};
|
|
7136
|
-
for (const [index, item] of items.entries()) {
|
|
7137
|
-
if (!isRecord(item)) {
|
|
7138
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}] must be a JSON object.`);
|
|
7139
|
-
}
|
|
7140
|
-
const providerKey = oauthProviderKeyFromRequirement(item.provider_key ?? item.provider);
|
|
7141
|
-
if (!providerKey) {
|
|
7142
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}].provider_key is required.`);
|
|
7143
|
-
}
|
|
7144
|
-
const authorizeUrl = String(item.authorize_url ?? item.authorization_url ?? item.auth_url ?? "").trim();
|
|
7145
|
-
const tokenUrl = String(item.token_url ?? "").trim();
|
|
7146
|
-
if (!authorizeUrl || !tokenUrl) {
|
|
7147
|
-
throw new SiglumeProjectError(
|
|
7148
|
-
`oauth_credentials[${index}] must include authorize_url and token_url.`
|
|
7149
|
-
);
|
|
7150
|
-
}
|
|
7151
|
-
for (const [urlKey, urlValue] of Object.entries({
|
|
7152
|
-
authorize_url: authorizeUrl,
|
|
7153
|
-
token_url: tokenUrl,
|
|
7154
|
-
revoke_url: String(item.revoke_url ?? "").trim()
|
|
7155
|
-
})) {
|
|
7156
|
-
if (urlValue && !urlValue.startsWith("https://")) {
|
|
7157
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}].${urlKey} must be an https URL.`);
|
|
7158
|
-
}
|
|
7159
|
-
}
|
|
7160
|
-
const clientId = String(item.client_id ?? "").trim();
|
|
7161
|
-
const clientSecret = String(item.client_secret ?? "").trim();
|
|
7162
|
-
if (!clientId || !clientSecret) {
|
|
7163
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}] must include client_id and client_secret.`);
|
|
7164
|
-
}
|
|
7165
|
-
const rawScopes = item.required_scopes ?? item.scopes;
|
|
7166
|
-
let scopes = [];
|
|
7167
|
-
if (rawScopes == null) {
|
|
7168
|
-
scopes = [];
|
|
7169
|
-
} else if (!Array.isArray(rawScopes)) {
|
|
7170
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}].required_scopes must be a JSON array.`);
|
|
7171
|
-
} else {
|
|
7172
|
-
scopes = rawScopes.map((scope) => String(scope ?? "").trim()).filter(Boolean);
|
|
7173
|
-
}
|
|
7174
|
-
const record = {
|
|
7175
|
-
provider_key: providerKey,
|
|
7176
|
-
client_id: clientId,
|
|
7177
|
-
client_secret: clientSecret,
|
|
7178
|
-
required_scopes: scopes
|
|
7179
|
-
};
|
|
7180
|
-
for (const [key, value] of Object.entries({
|
|
7181
|
-
authorize_url: authorizeUrl,
|
|
7182
|
-
token_url: tokenUrl,
|
|
7183
|
-
revoke_url: String(item.revoke_url ?? "").trim(),
|
|
7184
|
-
display_name: String(item.display_name ?? "").trim(),
|
|
7185
|
-
scope_separator: String(item.scope_separator ?? "").trim(),
|
|
7186
|
-
token_endpoint_auth: String(item.token_endpoint_auth ?? "").trim()
|
|
7187
|
-
})) {
|
|
7188
|
-
if (value) record[key] = value;
|
|
7189
|
-
}
|
|
7190
|
-
for (const key of ["pkce_required", "refresh_supported"]) {
|
|
7191
|
-
if (typeof item[key] === "boolean") record[key] = item[key];
|
|
7192
|
-
}
|
|
7193
|
-
if (Array.isArray(item.available_scopes)) {
|
|
7194
|
-
const availableScopes = item.available_scopes.map((scope) => String(scope ?? "").trim()).filter(Boolean);
|
|
7195
|
-
if (availableScopes.length > 0) record.available_scopes = availableScopes;
|
|
7196
|
-
}
|
|
7197
|
-
resolved[providerKey] = record;
|
|
7198
|
-
}
|
|
7199
|
-
return resolved;
|
|
7200
|
-
}
|
|
7201
|
-
function canonicalOauthCredentialsPayload(payload) {
|
|
7202
|
-
const records = oauthProviderRecordsMap(payload);
|
|
7203
|
-
const providerKeys = Object.keys(records).sort();
|
|
7204
|
-
if (providerKeys.length === 0) {
|
|
7205
|
-
return void 0;
|
|
7206
|
-
}
|
|
7207
|
-
return {
|
|
7208
|
-
items: providerKeys.map((providerKey) => records[providerKey])
|
|
7209
|
-
};
|
|
7210
|
-
}
|
|
7211
|
-
function ensureRequiredOauthCredentials(project) {
|
|
7212
|
-
const requiredProviders = requiredOauthProviders(project.manifest.required_connected_accounts ?? []);
|
|
7213
|
-
if (requiredProviders.length === 0) {
|
|
7214
|
-
return;
|
|
7215
|
-
}
|
|
7216
|
-
const provided = new Set(Object.keys(oauthProviderRecordsMap(project.oauth_credentials)));
|
|
7217
|
-
const missing = requiredProviders.filter((provider) => !provided.has(provider));
|
|
7218
|
-
if (missing.length === 0) {
|
|
7219
|
-
return;
|
|
7220
|
-
}
|
|
7221
|
-
const path = project.oauth_credentials_path ?? join(project.root_dir, "oauth_credentials.json");
|
|
7222
|
-
throw new SiglumeProjectError(
|
|
7223
|
-
`${path} is required for platform-managed OAuth APIs. Missing provider seeds: ${missing.join(", ")}`
|
|
7224
|
-
);
|
|
7225
|
-
}
|
|
7226
7164
|
async function validateProject(path = ".", deps = {}) {
|
|
7227
7165
|
const project = await loadProject(path);
|
|
7228
7166
|
const manifest_issues = await projectValidationIssues(project);
|
|
@@ -7262,7 +7200,12 @@ function ensureManifestPublisherIdentity(project) {
|
|
|
7262
7200
|
const sellerHomepageUrl = String(manifestPayload.seller_homepage_url ?? "").trim();
|
|
7263
7201
|
const sellerSocialUrl = String(manifestPayload.seller_social_url ?? "").trim();
|
|
7264
7202
|
const jurisdiction = String(manifestPayload.jurisdiction ?? "").trim();
|
|
7203
|
+
const companyId = String(manifestPayload.company_id ?? "").trim() || String(manifestPayload.publisher_company_id ?? "").trim();
|
|
7204
|
+
const publisherType = String(manifestPayload.publisher_type ?? "user").trim().toLowerCase();
|
|
7265
7205
|
const issues = [];
|
|
7206
|
+
if (companyId && publisherType !== "company") {
|
|
7207
|
+
issues.push('manifest.company_id requires manifest.publisher_type to be "company"');
|
|
7208
|
+
}
|
|
7266
7209
|
if (!docsUrl) {
|
|
7267
7210
|
issues.push("manifest.docs_url is required");
|
|
7268
7211
|
} else if (looksLikePlaceholder(docsUrl)) {
|
|
@@ -7372,10 +7315,21 @@ function ensureExplicitToolManual(project) {
|
|
|
7372
7315
|
async function registrationPreflight(project, client) {
|
|
7373
7316
|
const manifestIssues = await projectValidationIssues(project);
|
|
7374
7317
|
const [toolManualValid, toolManualIssues] = validate_tool_manual(project.tool_manual);
|
|
7318
|
+
const retiredPlatformOauthProviders = requiredOauthProviders(project.manifest.required_connected_accounts ?? []);
|
|
7319
|
+
if (retiredPlatformOauthProviders.length > 0) {
|
|
7320
|
+
throw new SiglumeProjectError(
|
|
7321
|
+
`Registration preflight failed. Fix these before calling auto-register:
|
|
7322
|
+
- platform-managed OAuth is retired. Use managed_by="api" with connect_url: ${retiredPlatformOauthProviders.join(", ")}`
|
|
7323
|
+
);
|
|
7324
|
+
}
|
|
7325
|
+
const apiManagedMissingConnectUrl = apiManagedRequirementsMissingConnectUrl(project.manifest.required_connected_accounts ?? []);
|
|
7326
|
+
if (apiManagedMissingConnectUrl.length > 0) {
|
|
7327
|
+
throw new SiglumeProjectError(
|
|
7328
|
+
`Registration preflight failed. Fix these before calling auto-register:
|
|
7329
|
+
- API-managed OAuth requirements must include connect_url: ${apiManagedMissingConnectUrl.join(", ")}`
|
|
7330
|
+
);
|
|
7331
|
+
}
|
|
7375
7332
|
const remoteQuality = await client.preview_quality_score(project.tool_manual);
|
|
7376
|
-
const requiredOauthProvidersList = requiredOauthProviders(project.manifest.required_connected_accounts ?? []);
|
|
7377
|
-
const oauthProviderRecords = oauthProviderRecordsMap(project.oauth_credentials);
|
|
7378
|
-
const missingOauthProviders = requiredOauthProvidersList.filter((provider) => !oauthProviderRecords[provider]);
|
|
7379
7333
|
const blockingToolManualIssues = toolManualIssues.filter((issue2) => issue2.severity === "error");
|
|
7380
7334
|
const errors = [
|
|
7381
7335
|
...manifestIssues.map((issue2) => String(issue2)),
|
|
@@ -7387,17 +7341,12 @@ async function registrationPreflight(project, client) {
|
|
|
7387
7341
|
if (!remoteQualityOk(remoteQuality)) {
|
|
7388
7342
|
errors.push(`remote Tool Manual quality is not publishable: ${remoteQuality.grade} (${remoteQuality.overall_score}/100)`);
|
|
7389
7343
|
}
|
|
7390
|
-
if (missingOauthProviders.length > 0) {
|
|
7391
|
-
errors.push(`oauth_credentials.json is required for platform-managed OAuth APIs: ${missingOauthProviders.join(", ")}`);
|
|
7392
|
-
}
|
|
7393
7344
|
const preflight = {
|
|
7394
7345
|
manifest_issues: manifestIssues,
|
|
7395
7346
|
tool_manual_valid: toolManualValid,
|
|
7396
7347
|
tool_manual_issues: toolManualIssues.map((issue2) => toJsonable(issue2)),
|
|
7397
7348
|
remote_quality: toJsonable(remoteQuality),
|
|
7398
|
-
|
|
7399
|
-
oauth_credentials_path: project.oauth_credentials_path ?? null,
|
|
7400
|
-
oauth_missing_providers: missingOauthProviders,
|
|
7349
|
+
retired_platform_oauth_providers: retiredPlatformOauthProviders,
|
|
7401
7350
|
ok: errors.length === 0
|
|
7402
7351
|
};
|
|
7403
7352
|
if (errors.length > 0) {
|
|
@@ -7408,35 +7357,116 @@ ${errors.map((error) => `- ${error}`).join("\n")}`
|
|
|
7408
7357
|
}
|
|
7409
7358
|
return preflight;
|
|
7410
7359
|
}
|
|
7360
|
+
function companyNameSlug(value) {
|
|
7361
|
+
return value.normalize("NFKD").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
7362
|
+
}
|
|
7411
7363
|
async function runRegistration(path = ".", options = {}, deps = {}) {
|
|
7412
7364
|
const project = await loadProject(path);
|
|
7365
|
+
let requestedCompanyId = String(options.company_id ?? "").trim();
|
|
7366
|
+
const requestedCompanySlug = String(options.company_slug ?? "").trim();
|
|
7367
|
+
let companyPublisherCandidates = null;
|
|
7368
|
+
if (requestedCompanySlug) {
|
|
7369
|
+
if (requestedCompanyId) {
|
|
7370
|
+
throw new SiglumeProjectError("--company and --company-slug cannot be combined.");
|
|
7371
|
+
}
|
|
7372
|
+
const slug = companyNameSlug(requestedCompanySlug);
|
|
7373
|
+
if (!slug && requestedCompanySlug !== requestedCompanyId) {
|
|
7374
|
+
throw new SiglumeProjectError(`Company slug ${requestedCompanySlug} is not slug-compatible; use --company <company_id> instead.`);
|
|
7375
|
+
}
|
|
7376
|
+
}
|
|
7377
|
+
if (requestedCompanyId) {
|
|
7378
|
+
project.manifest = {
|
|
7379
|
+
...project.manifest,
|
|
7380
|
+
publisher_type: "company",
|
|
7381
|
+
company_id: requestedCompanyId,
|
|
7382
|
+
publisher_company_id: requestedCompanyId
|
|
7383
|
+
};
|
|
7384
|
+
}
|
|
7413
7385
|
ensureExplicitToolManual(project);
|
|
7414
7386
|
ensureManifestPublisherIdentity(project);
|
|
7415
7387
|
ensureRuntimeValidationReady(project);
|
|
7416
|
-
ensureRequiredOauthCredentials(project);
|
|
7417
|
-
const canonicalOauthCredentials = canonicalOauthCredentialsPayload(project.oauth_credentials);
|
|
7418
7388
|
const client = await createClient(deps);
|
|
7389
|
+
if (requestedCompanySlug) {
|
|
7390
|
+
const slug = companyNameSlug(requestedCompanySlug);
|
|
7391
|
+
companyPublisherCandidates = await client.list_company_publishers();
|
|
7392
|
+
const matches = companyPublisherCandidates.filter(
|
|
7393
|
+
(item) => companyNameSlug(item.name || item.company_id) === slug || item.company_id === requestedCompanySlug
|
|
7394
|
+
);
|
|
7395
|
+
if (matches.length === 0) {
|
|
7396
|
+
throw new SiglumeProjectError(`Company slug ${requestedCompanySlug} is not available to this API key.`);
|
|
7397
|
+
}
|
|
7398
|
+
if (matches.length > 1) {
|
|
7399
|
+
throw new SiglumeProjectError(`Company slug ${requestedCompanySlug} is ambiguous; use --company <company_id> instead.`);
|
|
7400
|
+
}
|
|
7401
|
+
const match = matches[0];
|
|
7402
|
+
if (!match) {
|
|
7403
|
+
throw new SiglumeProjectError(`Company slug ${requestedCompanySlug} is not available to this API key.`);
|
|
7404
|
+
}
|
|
7405
|
+
if (match.can_publish === false) {
|
|
7406
|
+
const disabledReasons = match.disabled_reasons ?? [];
|
|
7407
|
+
const reasons = disabledReasons.length > 0 ? disabledReasons.join(", ") : "company publisher is disabled";
|
|
7408
|
+
throw new SiglumeProjectError(`Company ${match.company_id} cannot publish: ${reasons}.`);
|
|
7409
|
+
}
|
|
7410
|
+
requestedCompanyId = match.company_id;
|
|
7411
|
+
project.manifest = {
|
|
7412
|
+
...project.manifest,
|
|
7413
|
+
publisher_type: "company",
|
|
7414
|
+
company_id: requestedCompanyId,
|
|
7415
|
+
publisher_company_id: requestedCompanyId
|
|
7416
|
+
};
|
|
7417
|
+
}
|
|
7419
7418
|
const preflight = await registrationPreflight(project, client);
|
|
7419
|
+
let companyPublisherPreflight = null;
|
|
7420
|
+
const companyId = String(project.manifest.company_id ?? "").trim() || String(project.manifest.publisher_company_id ?? "").trim();
|
|
7421
|
+
const publisherType = String(project.manifest.publisher_type ?? "user").toLowerCase();
|
|
7422
|
+
if (publisherType === "company") {
|
|
7423
|
+
if (!companyId) {
|
|
7424
|
+
throw new SiglumeProjectError("Company registration requires --company <company_id> or manifest.company_id.");
|
|
7425
|
+
}
|
|
7426
|
+
const companies = companyPublisherCandidates ?? await client.list_company_publishers();
|
|
7427
|
+
companyPublisherCandidates = companies;
|
|
7428
|
+
const company = companies.find((item) => item.company_id === companyId);
|
|
7429
|
+
if (!company) {
|
|
7430
|
+
throw new SiglumeProjectError(`Company ${companyId} is not available to this API key.`);
|
|
7431
|
+
}
|
|
7432
|
+
if (company.can_publish === false) {
|
|
7433
|
+
const disabledReasons = company.disabled_reasons ?? [];
|
|
7434
|
+
const reasons = disabledReasons.length > 0 ? disabledReasons.join(", ") : "company publisher is disabled";
|
|
7435
|
+
throw new SiglumeProjectError(`Company ${companyId} cannot publish: ${reasons}.`);
|
|
7436
|
+
}
|
|
7437
|
+
companyPublisherPreflight = company;
|
|
7438
|
+
}
|
|
7420
7439
|
let developerPortalPreflight = null;
|
|
7421
7440
|
if (String(project.manifest.price_model ?? "free").toLowerCase() !== "free") {
|
|
7422
|
-
|
|
7423
|
-
|
|
7424
|
-
|
|
7425
|
-
|
|
7426
|
-
|
|
7427
|
-
)
|
|
7441
|
+
if (publisherType === "company") {
|
|
7442
|
+
const company = companyPublisherPreflight;
|
|
7443
|
+
if (!company) {
|
|
7444
|
+
throw new SiglumeProjectError(`Company ${companyId} is not available to this API key.`);
|
|
7445
|
+
}
|
|
7446
|
+
if (company.settlement_wallet_ready !== true) {
|
|
7447
|
+
throw new SiglumeProjectError(
|
|
7448
|
+
`Paid company registration requires a verified company settlement wallet for ${company.name}. Open the company settings and complete settlement readiness before registering.`
|
|
7449
|
+
);
|
|
7450
|
+
}
|
|
7451
|
+
developerPortalPreflight = { company_publisher: toJsonable(company) };
|
|
7452
|
+
} else {
|
|
7453
|
+
const portal = await client.get_developer_portal();
|
|
7454
|
+
const verifiedDestination = portal.payout_readiness?.verified_destination;
|
|
7455
|
+
if (verifiedDestination !== true) {
|
|
7456
|
+
throw new SiglumeProjectError(
|
|
7457
|
+
"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."
|
|
7458
|
+
);
|
|
7459
|
+
}
|
|
7460
|
+
developerPortalPreflight = toJsonable(portal);
|
|
7428
7461
|
}
|
|
7429
|
-
developerPortalPreflight = toJsonable(portal);
|
|
7430
7462
|
}
|
|
7431
7463
|
const receipt = await client.auto_register(project.manifest, project.tool_manual, {
|
|
7432
|
-
runtime_validation: project.runtime_validation
|
|
7433
|
-
oauth_credentials: canonicalOauthCredentials
|
|
7464
|
+
runtime_validation: project.runtime_validation
|
|
7434
7465
|
});
|
|
7435
7466
|
const result = {
|
|
7436
7467
|
receipt: toJsonable(receipt),
|
|
7437
7468
|
registration_preflight: preflight,
|
|
7438
|
-
runtime_validation_path: project.runtime_validation_path ?? null
|
|
7439
|
-
oauth_credentials_path: project.oauth_credentials_path ?? null
|
|
7469
|
+
runtime_validation_path: project.runtime_validation_path ?? null
|
|
7440
7470
|
};
|
|
7441
7471
|
if (developerPortalPreflight) {
|
|
7442
7472
|
result.developer_portal_preflight = developerPortalPreflight;
|
|
@@ -7457,7 +7487,6 @@ async function runPreflight(path = ".", deps = {}) {
|
|
|
7457
7487
|
ensureExplicitToolManual(project);
|
|
7458
7488
|
ensureManifestPublisherIdentity(project);
|
|
7459
7489
|
ensureRuntimeValidationReady(project);
|
|
7460
|
-
ensureRequiredOauthCredentials(project);
|
|
7461
7490
|
const client = await createClient(deps);
|
|
7462
7491
|
const preflight = await registrationPreflight(project, client);
|
|
7463
7492
|
let developerPortalPreflight = null;
|
|
@@ -7475,8 +7504,7 @@ async function runPreflight(path = ".", deps = {}) {
|
|
|
7475
7504
|
ok: true,
|
|
7476
7505
|
adapter_path: project.adapter_path,
|
|
7477
7506
|
registration_preflight: preflight,
|
|
7478
|
-
runtime_validation_path: project.runtime_validation_path ?? null
|
|
7479
|
-
oauth_credentials_path: project.oauth_credentials_path ?? null
|
|
7507
|
+
runtime_validation_path: project.runtime_validation_path ?? null
|
|
7480
7508
|
};
|
|
7481
7509
|
if (developerPortalPreflight) {
|
|
7482
7510
|
result.developer_portal_preflight = developerPortalPreflight;
|
|
@@ -7499,6 +7527,14 @@ async function getUsageReport(options, deps = {}) {
|
|
|
7499
7527
|
count: items.length
|
|
7500
7528
|
};
|
|
7501
7529
|
}
|
|
7530
|
+
async function listCompanyPublishersReport(deps = {}) {
|
|
7531
|
+
const client = await createClient(deps);
|
|
7532
|
+
const companies = await client.list_company_publishers();
|
|
7533
|
+
return {
|
|
7534
|
+
companies: companies.map((item) => toJsonable(item)),
|
|
7535
|
+
count: companies.length
|
|
7536
|
+
};
|
|
7537
|
+
}
|
|
7502
7538
|
async function diffJsonFiles(oldPath, newPath) {
|
|
7503
7539
|
const oldPayload = await loadJsonDocument(oldPath);
|
|
7504
7540
|
const newPayload = await loadJsonDocument(newPath);
|
|
@@ -7950,7 +7986,7 @@ function operationReadmeTemplate(operation, manifest, warning) {
|
|
|
7950
7986
|
"- `tool_manual.json`: machine-generated ToolManual scaffold",
|
|
7951
7987
|
"- `runtime_validation.json`: local public endpoint and review-key checks used by auto-register",
|
|
7952
7988
|
"- `docs/api-usage.md`: publishable API usage guide template for `docs_url`",
|
|
7953
|
-
"- `.gitignore`: keeps runtime review keys
|
|
7989
|
+
"- `.gitignore`: keeps runtime review keys out of Git",
|
|
7954
7990
|
"- `tests/test_adapter.ts`: smoke test for `AppTestHarness`",
|
|
7955
7991
|
"",
|
|
7956
7992
|
"Before registering, replace all generated placeholders:",
|
|
@@ -7958,8 +7994,8 @@ function operationReadmeTemplate(operation, manifest, warning) {
|
|
|
7958
7994
|
"- Replace `support_contact` with a real support email address or public support URL.",
|
|
7959
7995
|
"- Optional `seller_homepage_url` is the seller's official site and can stay blank.",
|
|
7960
7996
|
"- In the local `runtime_validation.json`, replace the public URL and review-key placeholders.",
|
|
7961
|
-
"- If the API uses
|
|
7962
|
-
"- Do not commit real review keys or
|
|
7997
|
+
"- If the API uses external OAuth, implement that flow in your API runtime and keep user tokens outside Siglume.",
|
|
7998
|
+
"- Do not commit real review keys or external-provider secrets; the generated `.gitignore` excludes local secret files.",
|
|
7963
7999
|
"- Because `runtime_validation.json` is ignored, GitHub samples do not commit review-key values.",
|
|
7964
8000
|
"",
|
|
7965
8001
|
"## Commands",
|
|
@@ -8035,8 +8071,6 @@ function generatedGitignore() {
|
|
|
8035
8071
|
"!.env.example",
|
|
8036
8072
|
"runtime_validation.json",
|
|
8037
8073
|
"runtime-validation.json",
|
|
8038
|
-
"oauth_credentials.json",
|
|
8039
|
-
"oauth-credentials.json",
|
|
8040
8074
|
"",
|
|
8041
8075
|
"# Python / test artifacts.",
|
|
8042
8076
|
"__pycache__/",
|
|
@@ -8182,13 +8216,6 @@ async function runHarnessForProject(project) {
|
|
|
8182
8216
|
checks.push(executionCheck("quote", await harness.execute_quote(task_type, { input_params: sample_input }), harness));
|
|
8183
8217
|
checks.push(executionCheck("payment", await harness.execute_payment(task_type, { input_params: sample_input }), harness));
|
|
8184
8218
|
}
|
|
8185
|
-
checks.push(
|
|
8186
|
-
executionCheck(
|
|
8187
|
-
"missing_account_simulation",
|
|
8188
|
-
await harness.simulate_connected_account_missing(task_type, { input_params: sample_input }),
|
|
8189
|
-
harness
|
|
8190
|
-
)
|
|
8191
|
-
);
|
|
8192
8219
|
return {
|
|
8193
8220
|
adapter_path: project.adapter_path,
|
|
8194
8221
|
task_type,
|
|
@@ -8291,15 +8318,6 @@ async function findRuntimeValidationPath(root_dir) {
|
|
|
8291
8318
|
}
|
|
8292
8319
|
return null;
|
|
8293
8320
|
}
|
|
8294
|
-
async function findOauthCredentialsPath(root_dir) {
|
|
8295
|
-
for (const name of ["oauth_credentials.json", "oauth-credentials.json"]) {
|
|
8296
|
-
const candidate = join(root_dir, name);
|
|
8297
|
-
if (existsSync(candidate)) {
|
|
8298
|
-
return candidate;
|
|
8299
|
-
}
|
|
8300
|
-
}
|
|
8301
|
-
return null;
|
|
8302
|
-
}
|
|
8303
8321
|
async function loadJsonObject(path, label) {
|
|
8304
8322
|
let payload;
|
|
8305
8323
|
try {
|
|
@@ -8531,15 +8549,15 @@ function readmeTemplate(template) {
|
|
|
8531
8549
|
"- `tool_manual.json`: editable ToolManual draft for validation and registration",
|
|
8532
8550
|
"- `runtime_validation.json`: local live API smoke-test contract used during registration",
|
|
8533
8551
|
"- `docs/api-usage.md`: publish this page and use its public URL as `docs_url`",
|
|
8534
|
-
"- `.gitignore`: keeps runtime review keys
|
|
8552
|
+
"- `.gitignore`: keeps runtime review keys out of Git",
|
|
8535
8553
|
"",
|
|
8536
8554
|
"Before registering, replace all generated placeholders:",
|
|
8537
8555
|
"- In `adapter.ts` and `manifest.json`, replace `docs_url` with a dedicated public API usage guide, not a homepage.",
|
|
8538
8556
|
"- Replace `support_contact` with a real support email address or public support URL.",
|
|
8539
8557
|
"- Optional `seller_homepage_url` is the seller's official site and can stay blank.",
|
|
8540
8558
|
"- In the local `runtime_validation.json`, replace the public URL and review-key placeholders.",
|
|
8541
|
-
"- If the API uses
|
|
8542
|
-
"- Do not commit real review keys or
|
|
8559
|
+
"- If the API uses external OAuth, implement that flow in your API runtime and keep user tokens outside Siglume.",
|
|
8560
|
+
"- Do not commit real review keys or external-provider secrets; the generated `.gitignore` excludes local secret files.",
|
|
8543
8561
|
"- Because `runtime_validation.json` is ignored, GitHub samples do not commit review-key values.",
|
|
8544
8562
|
"",
|
|
8545
8563
|
"Suggested workflow:",
|
|
@@ -8585,6 +8603,24 @@ function renderOperationTable(operations) {
|
|
|
8585
8603
|
...rows.map((row) => row.map((cell, index) => cell.padEnd(widths[index] ?? cell.length)).join(" "))
|
|
8586
8604
|
];
|
|
8587
8605
|
}
|
|
8606
|
+
function renderCompanyTable(companies) {
|
|
8607
|
+
const rows = companies.map((item) => [
|
|
8608
|
+
String(item.company_id ?? item.id ?? ""),
|
|
8609
|
+
String(item.name ?? ""),
|
|
8610
|
+
String(item.membership_role ?? (item.is_founder ? "founder" : "")),
|
|
8611
|
+
String(item.settlement_wallet_ready === true ? "ready" : "not_ready"),
|
|
8612
|
+
String(item.pending_approval_count ?? 0)
|
|
8613
|
+
]);
|
|
8614
|
+
const headers = ["company_id", "name", "role", "settlement", "pending"];
|
|
8615
|
+
const widths = headers.map(
|
|
8616
|
+
(header, index) => Math.max(header.length, ...rows.map((row) => row[index]?.length ?? 0))
|
|
8617
|
+
);
|
|
8618
|
+
return [
|
|
8619
|
+
headers.map((header, index) => header.padEnd(widths[index] ?? header.length)).join(" "),
|
|
8620
|
+
widths.map((width) => "-".repeat(width)).join(" "),
|
|
8621
|
+
...rows.map((row) => row.map((cell, index) => cell.padEnd(widths[index] ?? cell.length)).join(" "))
|
|
8622
|
+
];
|
|
8623
|
+
}
|
|
8588
8624
|
async function runCli(argv, deps = {}) {
|
|
8589
8625
|
const stdout = deps.stdout;
|
|
8590
8626
|
const stderr = deps.stderr ?? console.error;
|
|
@@ -8739,9 +8775,22 @@ async function runCli(argv, deps = {}) {
|
|
|
8739
8775
|
emit(stdout, `preflight_quality: ${preflight.remote_quality.grade} (${preflight.remote_quality.overall_score}/100)`);
|
|
8740
8776
|
}
|
|
8741
8777
|
if (report.runtime_validation_path) emit(stdout, `runtime_validation_path: ${String(report.runtime_validation_path)}`);
|
|
8742
|
-
if (report.oauth_credentials_path) emit(stdout, `oauth_credentials_path: ${String(report.oauth_credentials_path)}`);
|
|
8743
8778
|
});
|
|
8744
|
-
program.command("
|
|
8779
|
+
program.command("companies").description("List Siglume companies available for company-name publishing.").option("--json", "emit machine-readable JSON", false).action(async (options) => {
|
|
8780
|
+
const report = await listCompanyPublishersReport(deps);
|
|
8781
|
+
if (options.json) {
|
|
8782
|
+
emit(stdout, renderJson(report));
|
|
8783
|
+
return;
|
|
8784
|
+
}
|
|
8785
|
+
const companies = Array.isArray(report.companies) ? report.companies.filter((item) => Boolean(item && typeof item === "object")) : [];
|
|
8786
|
+
if (companies.length === 0) {
|
|
8787
|
+
emit(stdout, "No company publishers available for this API key.");
|
|
8788
|
+
return;
|
|
8789
|
+
}
|
|
8790
|
+
emit(stdout, "Company publishers");
|
|
8791
|
+
renderCompanyTable(companies).forEach((line) => emit(stdout, line));
|
|
8792
|
+
});
|
|
8793
|
+
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) => {
|
|
8745
8794
|
const draftOnly = Boolean(options.draftOnly);
|
|
8746
8795
|
if (draftOnly && options.confirm) {
|
|
8747
8796
|
throw new SiglumeProjectError("--draft-only cannot be combined with --confirm.");
|
|
@@ -8750,7 +8799,13 @@ async function runCli(argv, deps = {}) {
|
|
|
8750
8799
|
throw new SiglumeProjectError("--draft-only cannot be combined with --submit-review.");
|
|
8751
8800
|
}
|
|
8752
8801
|
const shouldConfirm = Boolean(options.confirm) || !draftOnly && !options.submitReview;
|
|
8753
|
-
const report = await runRegistration(path, {
|
|
8802
|
+
const report = await runRegistration(path, {
|
|
8803
|
+
confirm: shouldConfirm,
|
|
8804
|
+
draft_only: draftOnly,
|
|
8805
|
+
submit_review: options.submitReview,
|
|
8806
|
+
company_id: options.company,
|
|
8807
|
+
company_slug: options.companySlug
|
|
8808
|
+
}, deps);
|
|
8754
8809
|
if (options.json) {
|
|
8755
8810
|
emit(stdout, renderJson(report));
|
|
8756
8811
|
} else {
|
|
@@ -8770,7 +8825,6 @@ async function runCli(argv, deps = {}) {
|
|
|
8770
8825
|
emit(stdout, `listing_id: ${receipt.listing_id}`);
|
|
8771
8826
|
emit(stdout, `receipt_status: ${receipt.status}`);
|
|
8772
8827
|
if (receipt.listing_status) emit(stdout, `listing_status: ${receipt.listing_status}`);
|
|
8773
|
-
if (receipt.oauth_status) emit(stdout, `oauth_configured: ${Boolean(receipt.oauth_status.configured)}`);
|
|
8774
8828
|
if (receipt.review_url) emit(stdout, `review_url: ${receipt.review_url}`);
|
|
8775
8829
|
if (receipt.trace_id) emit(stdout, `trace_id: ${receipt.trace_id}`);
|
|
8776
8830
|
if (receipt.request_id) emit(stdout, `request_id: ${receipt.request_id}`);
|