@siglume/api-sdk 0.7.6 → 0.9.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 +34 -3
- package/dist/bin/siglume.cjs +423 -36
- package/dist/bin/siglume.cjs.map +1 -1
- package/dist/bin/siglume.js +423 -36
- package/dist/bin/siglume.js.map +1 -1
- package/dist/cli/index.cjs +423 -36
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts +11 -0
- package/dist/cli/index.d.ts +11 -0
- package/dist/cli/index.js +423 -36
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +35 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +35 -16
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.cjs
CHANGED
|
@@ -1352,6 +1352,9 @@ function parseListing(data) {
|
|
|
1352
1352
|
short_description: stringOrNull(data.short_description),
|
|
1353
1353
|
docs_url: stringOrNull(data.docs_url),
|
|
1354
1354
|
support_contact: stringOrNull(data.support_contact),
|
|
1355
|
+
seller_display_name: stringOrNull(data.seller_display_name),
|
|
1356
|
+
seller_homepage_url: stringOrNull(data.seller_homepage_url),
|
|
1357
|
+
seller_social_url: stringOrNull(data.seller_social_url),
|
|
1355
1358
|
review_status: stringOrNull(data.review_status),
|
|
1356
1359
|
review_note: stringOrNull(data.review_note),
|
|
1357
1360
|
submission_blockers: Array.isArray(data.submission_blockers) ? data.submission_blockers.filter((item) => typeof item === "string") : [],
|
|
@@ -2568,6 +2571,13 @@ var init_client = __esm({
|
|
|
2568
2571
|
if (options.runtime_validation) {
|
|
2569
2572
|
payload.runtime_validation = coerceMapping(options.runtime_validation, "runtime_validation");
|
|
2570
2573
|
}
|
|
2574
|
+
if (options.oauth_credentials) {
|
|
2575
|
+
payload.oauth_credentials = Array.isArray(options.oauth_credentials) ? {
|
|
2576
|
+
items: options.oauth_credentials.map(
|
|
2577
|
+
(item, index) => coerceMapping(item, `oauth_credentials[${index}]`)
|
|
2578
|
+
)
|
|
2579
|
+
} : coerceMapping(options.oauth_credentials, "oauth_credentials");
|
|
2580
|
+
}
|
|
2571
2581
|
if (options.metadata) {
|
|
2572
2582
|
payload.metadata = coerceMapping(options.metadata, "metadata");
|
|
2573
2583
|
}
|
|
@@ -2586,6 +2596,8 @@ var init_client = __esm({
|
|
|
2586
2596
|
"docs_url",
|
|
2587
2597
|
"documentation_url",
|
|
2588
2598
|
"support_contact",
|
|
2599
|
+
"seller_homepage_url",
|
|
2600
|
+
"seller_social_url",
|
|
2589
2601
|
"jurisdiction",
|
|
2590
2602
|
"price_model",
|
|
2591
2603
|
"price_value_minor",
|
|
@@ -2601,10 +2613,14 @@ var init_client = __esm({
|
|
|
2601
2613
|
}
|
|
2602
2614
|
const docsUrl = String(manifestPayload.docs_url ?? manifestPayload.documentation_url ?? "").trim();
|
|
2603
2615
|
const supportContact = String(manifestPayload.support_contact ?? "").trim();
|
|
2604
|
-
|
|
2616
|
+
const sellerHomepageUrl = String(manifestPayload.seller_homepage_url ?? "").trim();
|
|
2617
|
+
const sellerSocialUrl = String(manifestPayload.seller_social_url ?? "").trim();
|
|
2618
|
+
if (docsUrl || supportContact || sellerHomepageUrl || sellerSocialUrl) {
|
|
2605
2619
|
const publisherIdentity = {
|
|
2606
2620
|
documentation_url: docsUrl || null,
|
|
2607
|
-
support_contact: supportContact || null
|
|
2621
|
+
support_contact: supportContact || null,
|
|
2622
|
+
seller_homepage_url: sellerHomepageUrl || null,
|
|
2623
|
+
seller_social_url: sellerSocialUrl || null
|
|
2608
2624
|
};
|
|
2609
2625
|
payload.publisher_identity = publisherIdentity;
|
|
2610
2626
|
payload.legal = { publisher_identity: publisherIdentity };
|
|
@@ -2618,36 +2634,39 @@ var init_client = __esm({
|
|
|
2618
2634
|
return {
|
|
2619
2635
|
listing_id,
|
|
2620
2636
|
status: String(data.status ?? "draft"),
|
|
2637
|
+
registration_mode: stringOrNull(data.registration_mode),
|
|
2638
|
+
listing_status: stringOrNull(data.listing_status),
|
|
2621
2639
|
auto_manifest: toRecord(data.auto_manifest),
|
|
2622
2640
|
confidence: toRecord(data.confidence),
|
|
2623
2641
|
validation_report: toRecord(data.validation_report),
|
|
2642
|
+
oauth_status: toRecord(data.oauth_status),
|
|
2624
2643
|
review_url: stringOrNull(data.review_url),
|
|
2625
2644
|
trace_id: meta.trace_id,
|
|
2626
2645
|
request_id: meta.request_id
|
|
2627
2646
|
};
|
|
2628
2647
|
}
|
|
2629
2648
|
async confirm_registration(listing_id, options = {}) {
|
|
2630
|
-
const
|
|
2631
|
-
const manifestPayload = options.manifest ? coerceMapping(options.manifest, "manifest") : pending?.manifest ?? {};
|
|
2632
|
-
const toolManualPayload = options.tool_manual ? coerceMapping(options.tool_manual, "tool_manual") : pending?.tool_manual ?? {};
|
|
2633
|
-
const overrides = {};
|
|
2634
|
-
for (const fieldName of ["name", "job_to_be_done"]) {
|
|
2635
|
-
if (manifestPayload[fieldName]) {
|
|
2636
|
-
overrides[fieldName] = manifestPayload[fieldName];
|
|
2637
|
-
}
|
|
2638
|
-
}
|
|
2639
|
-
if (Object.keys(toolManualPayload).length > 0) {
|
|
2640
|
-
overrides.tool_manual = toolManualPayload;
|
|
2641
|
-
}
|
|
2649
|
+
const { version_bump: versionBump } = options;
|
|
2642
2650
|
const payload = { approved: true };
|
|
2643
|
-
if (
|
|
2644
|
-
|
|
2651
|
+
if (versionBump !== void 0) {
|
|
2652
|
+
const allowed = ["patch", "minor", "major"];
|
|
2653
|
+
if (!allowed.includes(versionBump)) {
|
|
2654
|
+
throw new Error(
|
|
2655
|
+
`version_bump must be one of ${JSON.stringify(allowed)}, got ${JSON.stringify(versionBump)}`
|
|
2656
|
+
);
|
|
2657
|
+
}
|
|
2658
|
+
payload.version_bump = versionBump;
|
|
2645
2659
|
}
|
|
2646
2660
|
const [data, meta] = await this.request("POST", `/market/capabilities/${listing_id}/confirm-auto-register`, { json_body: payload });
|
|
2647
2661
|
this.pendingConfirmations.delete(listing_id);
|
|
2662
|
+
const checklist = isRecord(data.checklist) ? Object.fromEntries(
|
|
2663
|
+
Object.entries(data.checklist).map(([key, value]) => [key, Boolean(value)])
|
|
2664
|
+
) : {};
|
|
2648
2665
|
return {
|
|
2649
2666
|
listing_id: String(data.listing_id ?? listing_id),
|
|
2650
2667
|
status: String(data.status ?? ""),
|
|
2668
|
+
message: stringOrNull(data.message),
|
|
2669
|
+
checklist,
|
|
2651
2670
|
release: toRecord(data.release),
|
|
2652
2671
|
quality: parseRegistrationQuality(toRecord(data.quality)),
|
|
2653
2672
|
trace_id: meta.trace_id,
|
|
@@ -7172,6 +7191,15 @@ async function loadProject(path = ".") {
|
|
|
7172
7191
|
const tool_manual = tool_manual_path ? JSON.parse(await (0, import_promises.readFile)(tool_manual_path, "utf8")) : buildToolManualTemplate(manifest);
|
|
7173
7192
|
const runtime_validation_path = await findRuntimeValidationPath(root_dir);
|
|
7174
7193
|
const runtime_validation = runtime_validation_path ? await loadJsonObject(runtime_validation_path, "runtime_validation") : void 0;
|
|
7194
|
+
const oauth_credentials_path = await findOauthCredentialsPath(root_dir);
|
|
7195
|
+
let oauth_credentials;
|
|
7196
|
+
if (oauth_credentials_path) {
|
|
7197
|
+
const parsed = JSON.parse(await (0, import_promises.readFile)(oauth_credentials_path, "utf8"));
|
|
7198
|
+
if (!isRecord(parsed) && !Array.isArray(parsed)) {
|
|
7199
|
+
throw new SiglumeProjectError("oauth_credentials must be a JSON object or array");
|
|
7200
|
+
}
|
|
7201
|
+
oauth_credentials = parsed;
|
|
7202
|
+
}
|
|
7175
7203
|
return {
|
|
7176
7204
|
root_dir,
|
|
7177
7205
|
adapter_path,
|
|
@@ -7180,9 +7208,110 @@ async function loadProject(path = ".") {
|
|
|
7180
7208
|
tool_manual_path: tool_manual_path ?? void 0,
|
|
7181
7209
|
tool_manual,
|
|
7182
7210
|
runtime_validation_path: runtime_validation_path ?? void 0,
|
|
7183
|
-
runtime_validation
|
|
7211
|
+
runtime_validation,
|
|
7212
|
+
oauth_credentials_path: oauth_credentials_path ?? void 0,
|
|
7213
|
+
oauth_credentials
|
|
7184
7214
|
};
|
|
7185
7215
|
}
|
|
7216
|
+
var OAUTH_PROVIDER_ALIASES = {
|
|
7217
|
+
x: "twitter",
|
|
7218
|
+
"x-twitter": "twitter",
|
|
7219
|
+
twitter: "twitter",
|
|
7220
|
+
slack: "slack",
|
|
7221
|
+
google: "google",
|
|
7222
|
+
gmail: "google",
|
|
7223
|
+
"google-drive": "google",
|
|
7224
|
+
"google-calendar": "google",
|
|
7225
|
+
github: "github",
|
|
7226
|
+
linear: "linear",
|
|
7227
|
+
notion: "notion"
|
|
7228
|
+
};
|
|
7229
|
+
function oauthProviderKeyFromRequirement(value) {
|
|
7230
|
+
const raw = String(value ?? "").trim().toLowerCase().replaceAll("_", "-");
|
|
7231
|
+
if (!raw) return null;
|
|
7232
|
+
if (OAUTH_PROVIDER_ALIASES[raw]) {
|
|
7233
|
+
return OAUTH_PROVIDER_ALIASES[raw];
|
|
7234
|
+
}
|
|
7235
|
+
for (const token of raw.replaceAll("/", "-").replaceAll(":", "-").split("-")) {
|
|
7236
|
+
const next = token.trim();
|
|
7237
|
+
if (OAUTH_PROVIDER_ALIASES[next]) {
|
|
7238
|
+
return OAUTH_PROVIDER_ALIASES[next];
|
|
7239
|
+
}
|
|
7240
|
+
}
|
|
7241
|
+
return null;
|
|
7242
|
+
}
|
|
7243
|
+
function requiredOauthProviders(requirements) {
|
|
7244
|
+
const providers = [];
|
|
7245
|
+
for (const item of requirements ?? []) {
|
|
7246
|
+
const providerKey = oauthProviderKeyFromRequirement(item);
|
|
7247
|
+
if (providerKey && !providers.includes(providerKey)) {
|
|
7248
|
+
providers.push(providerKey);
|
|
7249
|
+
}
|
|
7250
|
+
}
|
|
7251
|
+
return providers;
|
|
7252
|
+
}
|
|
7253
|
+
function oauthProviderRecordsMap(payload) {
|
|
7254
|
+
if (!payload) {
|
|
7255
|
+
return {};
|
|
7256
|
+
}
|
|
7257
|
+
const items = Array.isArray(payload) ? payload : Array.isArray(payload.items) ? payload.items : [payload];
|
|
7258
|
+
const resolved = {};
|
|
7259
|
+
for (const [index, item] of items.entries()) {
|
|
7260
|
+
if (!isRecord(item)) {
|
|
7261
|
+
throw new SiglumeProjectError(`oauth_credentials[${index}] must be a JSON object.`);
|
|
7262
|
+
}
|
|
7263
|
+
const providerKey = oauthProviderKeyFromRequirement(item.provider_key ?? item.provider);
|
|
7264
|
+
if (!providerKey) {
|
|
7265
|
+
throw new SiglumeProjectError(`oauth_credentials[${index}].provider_key is unsupported.`);
|
|
7266
|
+
}
|
|
7267
|
+
const clientId = String(item.client_id ?? "").trim();
|
|
7268
|
+
const clientSecret = String(item.client_secret ?? "").trim();
|
|
7269
|
+
if (!clientId || !clientSecret) {
|
|
7270
|
+
throw new SiglumeProjectError(`oauth_credentials[${index}] must include client_id and client_secret.`);
|
|
7271
|
+
}
|
|
7272
|
+
const rawScopes = item.required_scopes ?? item.scopes;
|
|
7273
|
+
let scopes = [];
|
|
7274
|
+
if (rawScopes == null) {
|
|
7275
|
+
scopes = [];
|
|
7276
|
+
} else if (!Array.isArray(rawScopes)) {
|
|
7277
|
+
throw new SiglumeProjectError(`oauth_credentials[${index}].required_scopes must be a JSON array.`);
|
|
7278
|
+
} else {
|
|
7279
|
+
scopes = rawScopes.map((scope) => String(scope ?? "").trim()).filter(Boolean);
|
|
7280
|
+
}
|
|
7281
|
+
resolved[providerKey] = {
|
|
7282
|
+
provider_key: providerKey,
|
|
7283
|
+
client_id: clientId,
|
|
7284
|
+
client_secret: clientSecret,
|
|
7285
|
+
required_scopes: scopes
|
|
7286
|
+
};
|
|
7287
|
+
}
|
|
7288
|
+
return resolved;
|
|
7289
|
+
}
|
|
7290
|
+
function canonicalOauthCredentialsPayload(payload) {
|
|
7291
|
+
const records = oauthProviderRecordsMap(payload);
|
|
7292
|
+
const providerKeys = Object.keys(records).sort();
|
|
7293
|
+
if (providerKeys.length === 0) {
|
|
7294
|
+
return void 0;
|
|
7295
|
+
}
|
|
7296
|
+
return {
|
|
7297
|
+
items: providerKeys.map((providerKey) => records[providerKey])
|
|
7298
|
+
};
|
|
7299
|
+
}
|
|
7300
|
+
function ensureRequiredOauthCredentials(project) {
|
|
7301
|
+
const requiredProviders = requiredOauthProviders(project.manifest.required_connected_accounts ?? []);
|
|
7302
|
+
if (requiredProviders.length === 0) {
|
|
7303
|
+
return;
|
|
7304
|
+
}
|
|
7305
|
+
const provided = new Set(Object.keys(oauthProviderRecordsMap(project.oauth_credentials)));
|
|
7306
|
+
const missing = requiredProviders.filter((provider) => !provided.has(provider));
|
|
7307
|
+
if (missing.length === 0) {
|
|
7308
|
+
return;
|
|
7309
|
+
}
|
|
7310
|
+
const path = project.oauth_credentials_path ?? (0, import_node_path.join)(project.root_dir, "oauth_credentials.json");
|
|
7311
|
+
throw new SiglumeProjectError(
|
|
7312
|
+
`${path} is required for OAuth-backed APIs. Missing provider seeds: ${missing.join(", ")}`
|
|
7313
|
+
);
|
|
7314
|
+
}
|
|
7186
7315
|
async function validateProject(path = ".", deps = {}) {
|
|
7187
7316
|
const project = await loadProject(path);
|
|
7188
7317
|
const manifest_issues = await projectValidationIssues(project);
|
|
@@ -7219,17 +7348,31 @@ function ensureManifestPublisherIdentity(project) {
|
|
|
7219
7348
|
const manifestPayload = project.manifest;
|
|
7220
7349
|
const docsUrl = String(manifestPayload.docs_url ?? manifestPayload.documentation_url ?? "").trim();
|
|
7221
7350
|
const supportContact = String(manifestPayload.support_contact ?? "").trim();
|
|
7351
|
+
const sellerHomepageUrl = String(manifestPayload.seller_homepage_url ?? "").trim();
|
|
7352
|
+
const sellerSocialUrl = String(manifestPayload.seller_social_url ?? "").trim();
|
|
7222
7353
|
const jurisdiction = String(manifestPayload.jurisdiction ?? "").trim();
|
|
7223
7354
|
const issues = [];
|
|
7224
7355
|
if (!docsUrl) {
|
|
7225
7356
|
issues.push("manifest.docs_url is required");
|
|
7226
7357
|
} else if (looksLikePlaceholder(docsUrl)) {
|
|
7227
7358
|
issues.push("manifest.docs_url must be replaced with your public documentation URL");
|
|
7359
|
+
} else if (!looksLikeHttpUrl(docsUrl)) {
|
|
7360
|
+
issues.push("manifest.docs_url must be an http(s) URL");
|
|
7361
|
+
} else if (looksLikeRootUrl(docsUrl)) {
|
|
7362
|
+
issues.push("manifest.docs_url must be a dedicated API usage page, not a root homepage URL");
|
|
7228
7363
|
}
|
|
7229
7364
|
if (!supportContact) {
|
|
7230
7365
|
issues.push("manifest.support_contact is required");
|
|
7231
7366
|
} else if (looksLikePlaceholder(supportContact)) {
|
|
7232
7367
|
issues.push("manifest.support_contact must be replaced with your real support email or support URL");
|
|
7368
|
+
} else if (!looksLikeEmail(supportContact) && !looksLikeHttpUrl(supportContact)) {
|
|
7369
|
+
issues.push("manifest.support_contact must be a real email address or http(s) support URL");
|
|
7370
|
+
}
|
|
7371
|
+
if (sellerHomepageUrl && (looksLikePlaceholder(sellerHomepageUrl) || !looksLikeHttpUrl(sellerHomepageUrl))) {
|
|
7372
|
+
issues.push("manifest.seller_homepage_url must be a real http(s) official homepage URL when provided");
|
|
7373
|
+
}
|
|
7374
|
+
if (sellerSocialUrl && (looksLikePlaceholder(sellerSocialUrl) || !looksLikeHttpUrl(sellerSocialUrl))) {
|
|
7375
|
+
issues.push("manifest.seller_social_url must be a real http(s) official social/profile URL when provided");
|
|
7233
7376
|
}
|
|
7234
7377
|
if (!jurisdiction) issues.push("manifest.jurisdiction is required");
|
|
7235
7378
|
if (issues.length > 0) {
|
|
@@ -7241,7 +7384,25 @@ ${issues.map((issue2) => `- ${issue2}`).join("\n")}`
|
|
|
7241
7384
|
}
|
|
7242
7385
|
function looksLikePlaceholder(value) {
|
|
7243
7386
|
const normalized = value.trim().toLowerCase();
|
|
7244
|
-
return !normalized || normalized.includes("example.com") || normalized.startsWith("replace-with-") || normalized.startsWith("your-") || normalized.includes("your-domain") || normalized.includes("localhost") || normalized.includes("127.0.0.1") || normalized.includes("0.0.0.0");
|
|
7387
|
+
return !normalized || normalized.includes("example.com") || normalized.includes("example.net") || normalized.includes("example.org") || normalized.startsWith("replace-with-") || normalized.startsWith("your-") || normalized.includes("your-domain") || normalized.includes("localhost") || normalized.includes("127.0.0.1") || normalized.includes("0.0.0.0");
|
|
7388
|
+
}
|
|
7389
|
+
function looksLikeHttpUrl(value) {
|
|
7390
|
+
try {
|
|
7391
|
+
const parsed = new URL(value.trim());
|
|
7392
|
+
return parsed.protocol === "http:" || parsed.protocol === "https:";
|
|
7393
|
+
} catch {
|
|
7394
|
+
return false;
|
|
7395
|
+
}
|
|
7396
|
+
}
|
|
7397
|
+
function looksLikeRootUrl(value) {
|
|
7398
|
+
if (!looksLikeHttpUrl(value)) return false;
|
|
7399
|
+
const parsed = new URL(value.trim());
|
|
7400
|
+
return parsed.pathname.replace(/^\/+|\/+$/g, "") === "";
|
|
7401
|
+
}
|
|
7402
|
+
function looksLikeEmail(value) {
|
|
7403
|
+
const normalized = value.trim();
|
|
7404
|
+
const domain = normalized.split("@").at(-1) ?? "";
|
|
7405
|
+
return normalized.includes("@") && !normalized.includes(" ") && domain.includes(".") && !normalized.startsWith("@");
|
|
7245
7406
|
}
|
|
7246
7407
|
function runtimePlaceholderIssues(runtimeValidation) {
|
|
7247
7408
|
const issues = [];
|
|
@@ -7301,6 +7462,9 @@ async function registrationPreflight(project, client) {
|
|
|
7301
7462
|
const manifestIssues = await projectValidationIssues(project);
|
|
7302
7463
|
const [toolManualValid, toolManualIssues] = validate_tool_manual(project.tool_manual);
|
|
7303
7464
|
const remoteQuality = await client.preview_quality_score(project.tool_manual);
|
|
7465
|
+
const requiredOauthProvidersList = requiredOauthProviders(project.manifest.required_connected_accounts ?? []);
|
|
7466
|
+
const oauthProviderRecords = oauthProviderRecordsMap(project.oauth_credentials);
|
|
7467
|
+
const missingOauthProviders = requiredOauthProvidersList.filter((provider) => !oauthProviderRecords[provider]);
|
|
7304
7468
|
const blockingToolManualIssues = toolManualIssues.filter((issue2) => issue2.severity === "error");
|
|
7305
7469
|
const errors = [
|
|
7306
7470
|
...manifestIssues.map((issue2) => String(issue2)),
|
|
@@ -7312,11 +7476,17 @@ async function registrationPreflight(project, client) {
|
|
|
7312
7476
|
if (!remoteQualityOk(remoteQuality)) {
|
|
7313
7477
|
errors.push(`remote Tool Manual quality is not publishable: ${remoteQuality.grade} (${remoteQuality.overall_score}/100)`);
|
|
7314
7478
|
}
|
|
7479
|
+
if (missingOauthProviders.length > 0) {
|
|
7480
|
+
errors.push(`oauth_credentials.json is required for OAuth-backed APIs: ${missingOauthProviders.join(", ")}`);
|
|
7481
|
+
}
|
|
7315
7482
|
const preflight = {
|
|
7316
7483
|
manifest_issues: manifestIssues,
|
|
7317
7484
|
tool_manual_valid: toolManualValid,
|
|
7318
7485
|
tool_manual_issues: toolManualIssues.map((issue2) => toJsonable(issue2)),
|
|
7319
7486
|
remote_quality: toJsonable(remoteQuality),
|
|
7487
|
+
required_oauth_providers: requiredOauthProvidersList,
|
|
7488
|
+
oauth_credentials_path: project.oauth_credentials_path ?? null,
|
|
7489
|
+
oauth_missing_providers: missingOauthProviders,
|
|
7320
7490
|
ok: errors.length === 0
|
|
7321
7491
|
};
|
|
7322
7492
|
if (errors.length > 0) {
|
|
@@ -7332,6 +7502,7 @@ async function runRegistration(path = ".", options = {}, deps = {}) {
|
|
|
7332
7502
|
ensureExplicitToolManual(project);
|
|
7333
7503
|
ensureManifestPublisherIdentity(project);
|
|
7334
7504
|
ensureRuntimeValidationReady(project);
|
|
7505
|
+
ensureRequiredOauthCredentials(project);
|
|
7335
7506
|
const client = await createClient(deps);
|
|
7336
7507
|
const preflight = await registrationPreflight(project, client);
|
|
7337
7508
|
let developerPortalPreflight = null;
|
|
@@ -7340,18 +7511,20 @@ async function runRegistration(path = ".", options = {}, deps = {}) {
|
|
|
7340
7511
|
const verifiedDestination = portal.payout_readiness?.verified_destination;
|
|
7341
7512
|
if (verifiedDestination !== true) {
|
|
7342
7513
|
throw new SiglumeProjectError(
|
|
7343
|
-
"Paid API registration requires a verified Polygon payout destination. Open https://siglume.com/owner/
|
|
7514
|
+
"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."
|
|
7344
7515
|
);
|
|
7345
7516
|
}
|
|
7346
7517
|
developerPortalPreflight = toJsonable(portal);
|
|
7347
7518
|
}
|
|
7348
7519
|
const receipt = await client.auto_register(project.manifest, project.tool_manual, {
|
|
7349
|
-
runtime_validation: project.runtime_validation
|
|
7520
|
+
runtime_validation: project.runtime_validation,
|
|
7521
|
+
oauth_credentials: canonicalOauthCredentialsPayload(project.oauth_credentials)
|
|
7350
7522
|
});
|
|
7351
7523
|
const result = {
|
|
7352
7524
|
receipt: toJsonable(receipt),
|
|
7353
7525
|
registration_preflight: preflight,
|
|
7354
|
-
runtime_validation_path: project.runtime_validation_path ?? null
|
|
7526
|
+
runtime_validation_path: project.runtime_validation_path ?? null,
|
|
7527
|
+
oauth_credentials_path: project.oauth_credentials_path ?? null
|
|
7355
7528
|
};
|
|
7356
7529
|
if (developerPortalPreflight) {
|
|
7357
7530
|
result.developer_portal_preflight = developerPortalPreflight;
|
|
@@ -7366,6 +7539,37 @@ async function runRegistration(path = ".", options = {}, deps = {}) {
|
|
|
7366
7539
|
}
|
|
7367
7540
|
return result;
|
|
7368
7541
|
}
|
|
7542
|
+
async function runPreflight(path = ".", deps = {}) {
|
|
7543
|
+
const project = await loadProject(path);
|
|
7544
|
+
ensureExplicitToolManual(project);
|
|
7545
|
+
ensureManifestPublisherIdentity(project);
|
|
7546
|
+
ensureRuntimeValidationReady(project);
|
|
7547
|
+
ensureRequiredOauthCredentials(project);
|
|
7548
|
+
const client = await createClient(deps);
|
|
7549
|
+
const preflight = await registrationPreflight(project, client);
|
|
7550
|
+
let developerPortalPreflight = null;
|
|
7551
|
+
if (String(project.manifest.price_model ?? "free").toLowerCase() !== "free") {
|
|
7552
|
+
const portal = await client.get_developer_portal();
|
|
7553
|
+
const verifiedDestination = portal.payout_readiness?.verified_destination;
|
|
7554
|
+
if (verifiedDestination !== true) {
|
|
7555
|
+
throw new SiglumeProjectError(
|
|
7556
|
+
"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."
|
|
7557
|
+
);
|
|
7558
|
+
}
|
|
7559
|
+
developerPortalPreflight = toJsonable(portal);
|
|
7560
|
+
}
|
|
7561
|
+
const result = {
|
|
7562
|
+
ok: true,
|
|
7563
|
+
adapter_path: project.adapter_path,
|
|
7564
|
+
registration_preflight: preflight,
|
|
7565
|
+
runtime_validation_path: project.runtime_validation_path ?? null,
|
|
7566
|
+
oauth_credentials_path: project.oauth_credentials_path ?? null
|
|
7567
|
+
};
|
|
7568
|
+
if (developerPortalPreflight) {
|
|
7569
|
+
result.developer_portal_preflight = developerPortalPreflight;
|
|
7570
|
+
}
|
|
7571
|
+
return result;
|
|
7572
|
+
}
|
|
7369
7573
|
async function createSupportCaseReport(options, deps = {}) {
|
|
7370
7574
|
const client = await createClient(deps);
|
|
7371
7575
|
const supportCase = await client.create_support_case(options.subject, options.body, { trace_id: options.trace_id });
|
|
@@ -7412,8 +7616,12 @@ async function writeInitTemplate(template, destination) {
|
|
|
7412
7616
|
const manifest_path = (0, import_node_path.join)(root, "manifest.json");
|
|
7413
7617
|
const tool_manual_path = (0, import_node_path.join)(root, "tool_manual.json");
|
|
7414
7618
|
const runtime_validation_path = (0, import_node_path.join)(root, "runtime_validation.json");
|
|
7619
|
+
const gitignore_path = (0, import_node_path.join)(root, ".gitignore");
|
|
7415
7620
|
const readme_path = (0, import_node_path.join)(root, "README.md");
|
|
7416
|
-
|
|
7621
|
+
const docs_dir = (0, import_node_path.join)(root, "docs");
|
|
7622
|
+
await (0, import_promises.mkdir)(docs_dir, { recursive: true });
|
|
7623
|
+
const docs_usage_path = (0, import_node_path.join)(docs_dir, "api-usage.md");
|
|
7624
|
+
for (const filePath of [adapter_path, manifest_path, tool_manual_path, runtime_validation_path, docs_usage_path, readme_path]) {
|
|
7417
7625
|
if ((0, import_node_fs.existsSync)(filePath)) {
|
|
7418
7626
|
throw new SiglumeProjectError(`${(0, import_node_path.basename)(filePath)} already exists in ${root}`);
|
|
7419
7627
|
}
|
|
@@ -7424,8 +7632,10 @@ async function writeInitTemplate(template, destination) {
|
|
|
7424
7632
|
await (0, import_promises.writeFile)(manifest_path, renderJson(manifest), "utf8");
|
|
7425
7633
|
await (0, import_promises.writeFile)(tool_manual_path, renderJson(toolManual), "utf8");
|
|
7426
7634
|
await (0, import_promises.writeFile)(runtime_validation_path, renderJson(buildRuntimeValidationTemplate(toolManual)), "utf8");
|
|
7635
|
+
await (0, import_promises.writeFile)(docs_usage_path, apiUsageDocsTemplate(manifest), "utf8");
|
|
7636
|
+
await writeOrMergeGitignore(gitignore_path);
|
|
7427
7637
|
await (0, import_promises.writeFile)(readme_path, readmeTemplate(template), "utf8");
|
|
7428
|
-
return [adapter_path, manifest_path, tool_manual_path, runtime_validation_path, readme_path];
|
|
7638
|
+
return [adapter_path, manifest_path, tool_manual_path, runtime_validation_path, docs_usage_path, gitignore_path, readme_path];
|
|
7429
7639
|
}
|
|
7430
7640
|
async function listOperationCatalog(options = {}, deps = {}) {
|
|
7431
7641
|
const resolvedAgentId = String(options.agent_id ?? "").trim();
|
|
@@ -7819,12 +8029,19 @@ function operationReadmeTemplate(operation, manifest, warning) {
|
|
|
7819
8029
|
"- `stubs.ts`: mock fallback used when `SIGLUME_API_KEY` is not set",
|
|
7820
8030
|
"- `manifest.json`: reviewable manifest snapshot",
|
|
7821
8031
|
"- `tool_manual.json`: machine-generated ToolManual scaffold",
|
|
7822
|
-
"- `runtime_validation.json`: public endpoint and review-key checks used by auto-register",
|
|
8032
|
+
"- `runtime_validation.json`: local public endpoint and review-key checks used by auto-register",
|
|
8033
|
+
"- `docs/api-usage.md`: publishable API usage guide template for `docs_url`",
|
|
8034
|
+
"- `.gitignore`: keeps runtime review keys and OAuth client secrets out of Git",
|
|
7823
8035
|
"- `tests/test_adapter.ts`: smoke test for `AppTestHarness`",
|
|
7824
8036
|
"",
|
|
7825
8037
|
"Before registering, replace all generated placeholders:",
|
|
7826
|
-
"- In `adapter.ts` and `manifest.json`, replace `docs_url`
|
|
7827
|
-
"-
|
|
8038
|
+
"- In `adapter.ts` and `manifest.json`, replace `docs_url` with a dedicated public API usage guide, not a homepage.",
|
|
8039
|
+
"- Replace `support_contact` with a real support email address or public support URL.",
|
|
8040
|
+
"- Optional `seller_homepage_url` is the seller's official site and can stay blank.",
|
|
8041
|
+
"- In the local `runtime_validation.json`, replace the public URL and review-key placeholders.",
|
|
8042
|
+
"- If the API uses seller-side OAuth, create a local `oauth_credentials.json` next to the adapter.",
|
|
8043
|
+
"- Do not commit real review keys or OAuth client secrets; the generated `.gitignore` excludes those files.",
|
|
8044
|
+
"- Because `runtime_validation.json` is ignored, GitHub samples do not commit review-key values.",
|
|
7828
8045
|
"",
|
|
7829
8046
|
"## Commands",
|
|
7830
8047
|
"",
|
|
@@ -7836,16 +8053,108 @@ function operationReadmeTemplate(operation, manifest, warning) {
|
|
|
7836
8053
|
"siglume score . --offline",
|
|
7837
8054
|
"```",
|
|
7838
8055
|
"",
|
|
7839
|
-
"After placeholders are replaced and `SIGLUME_API_KEY` is
|
|
8056
|
+
"After placeholders are replaced and `SIGLUME_API_KEY` is issued from Developer Portal -> CLI / API keys, run the server-aligned checks:",
|
|
7840
8057
|
"",
|
|
7841
8058
|
"```bash",
|
|
7842
8059
|
"siglume validate .",
|
|
7843
8060
|
"siglume score . --remote",
|
|
8061
|
+
"siglume preflight .",
|
|
8062
|
+
"siglume register .",
|
|
8063
|
+
"# inspect the draft, then explicitly approve publish:",
|
|
7844
8064
|
"siglume register . --confirm",
|
|
7845
8065
|
"```",
|
|
7846
8066
|
""
|
|
7847
8067
|
].join("\n");
|
|
7848
8068
|
}
|
|
8069
|
+
function apiUsageDocsTemplate(manifest) {
|
|
8070
|
+
const name = String(manifest.name ?? manifest.capability_key ?? "Siglume API");
|
|
8071
|
+
const capabilityKey = String(manifest.capability_key ?? "replace-with-capability-key");
|
|
8072
|
+
const jobToBeDone = String(manifest.job_to_be_done ?? "Describe what this API lets an agent do.");
|
|
8073
|
+
const permissionClass = String(manifest.permission_class ?? "read-only");
|
|
8074
|
+
const priceModel = String(manifest.price_model ?? "free");
|
|
8075
|
+
const requiredAccounts = (manifest.required_connected_accounts ?? []).join(", ") || "none";
|
|
8076
|
+
const supportContact = String(manifest.support_contact ?? "replace-with-support-contact");
|
|
8077
|
+
return [
|
|
8078
|
+
`# ${name} API Usage Guide`,
|
|
8079
|
+
"",
|
|
8080
|
+
`This page is the dedicated public usage guide for the Siglume API listing \`${capabilityKey}\`.`,
|
|
8081
|
+
"Publish this page at an anonymous HTTP 200 URL and use that URL as `docs_url`.",
|
|
8082
|
+
"",
|
|
8083
|
+
"Do not use your company homepage as `docs_url`; keep seller/company homepages in `seller_homepage_url`.",
|
|
8084
|
+
"",
|
|
8085
|
+
"## What This API Does",
|
|
8086
|
+
"",
|
|
8087
|
+
jobToBeDone,
|
|
8088
|
+
"",
|
|
8089
|
+
"## Permission Model",
|
|
8090
|
+
"",
|
|
8091
|
+
`- Permission class: \`${permissionClass}\``,
|
|
8092
|
+
`- Price model: \`${priceModel}\``,
|
|
8093
|
+
`- Required connected accounts: \`${requiredAccounts}\``,
|
|
8094
|
+
"",
|
|
8095
|
+
"## Inputs",
|
|
8096
|
+
"",
|
|
8097
|
+
"Describe the request fields your API accepts. Keep this aligned with `tool_manual.json` and `runtime_validation.json`.",
|
|
8098
|
+
"",
|
|
8099
|
+
"## Outputs",
|
|
8100
|
+
"",
|
|
8101
|
+
"Describe the response fields your API returns. Include the fields in `runtime_validation.expected_response_fields`.",
|
|
8102
|
+
"",
|
|
8103
|
+
"## Errors And Support",
|
|
8104
|
+
"",
|
|
8105
|
+
"Explain common error messages and how an owner should recover.",
|
|
8106
|
+
"",
|
|
8107
|
+
`Support contact: ${supportContact}`,
|
|
8108
|
+
""
|
|
8109
|
+
].join("\n");
|
|
8110
|
+
}
|
|
8111
|
+
function generatedGitignore() {
|
|
8112
|
+
return [
|
|
8113
|
+
"# Local secrets and registration-only runtime checks.",
|
|
8114
|
+
".env",
|
|
8115
|
+
".env.*",
|
|
8116
|
+
"!.env.example",
|
|
8117
|
+
"runtime_validation.json",
|
|
8118
|
+
"runtime-validation.json",
|
|
8119
|
+
"oauth_credentials.json",
|
|
8120
|
+
"oauth-credentials.json",
|
|
8121
|
+
"",
|
|
8122
|
+
"# Python / test artifacts.",
|
|
8123
|
+
"__pycache__/",
|
|
8124
|
+
"*.py[cod]",
|
|
8125
|
+
".pytest_cache/",
|
|
8126
|
+
".mypy_cache/",
|
|
8127
|
+
".coverage",
|
|
8128
|
+
"htmlcov/",
|
|
8129
|
+
"dist/",
|
|
8130
|
+
"build/",
|
|
8131
|
+
"*.egg-info/",
|
|
8132
|
+
"",
|
|
8133
|
+
"# JavaScript tooling if this project also uses TypeScript helpers.",
|
|
8134
|
+
"node_modules/",
|
|
8135
|
+
"coverage/",
|
|
8136
|
+
""
|
|
8137
|
+
].join("\n");
|
|
8138
|
+
}
|
|
8139
|
+
async function writeOrMergeGitignore(filePath) {
|
|
8140
|
+
const generated = generatedGitignore();
|
|
8141
|
+
if (!(0, import_node_fs.existsSync)(filePath)) {
|
|
8142
|
+
await (0, import_promises.writeFile)(filePath, generated, "utf8");
|
|
8143
|
+
return;
|
|
8144
|
+
}
|
|
8145
|
+
const existing = await (0, import_promises.readFile)(filePath, "utf8");
|
|
8146
|
+
const existingEntries = new Set(existing.split(/\r?\n/).map((line) => line.trim()));
|
|
8147
|
+
const additions = generated.split(/\r?\n/).filter((line) => line.trim() && !existingEntries.has(line.trim()));
|
|
8148
|
+
if (additions.length === 0) {
|
|
8149
|
+
return;
|
|
8150
|
+
}
|
|
8151
|
+
const prefix = existing.endsWith("\n") ? existing : `${existing}
|
|
8152
|
+
`;
|
|
8153
|
+
await (0, import_promises.writeFile)(filePath, `${prefix}
|
|
8154
|
+
# Siglume generated ignores.
|
|
8155
|
+
${additions.join("\n")}
|
|
8156
|
+
`, "utf8");
|
|
8157
|
+
}
|
|
7849
8158
|
async function writeOperationTemplate(operation_key, destination, options = {}, deps = {}) {
|
|
7850
8159
|
const root = (0, import_node_path.resolve)(destination);
|
|
7851
8160
|
await (0, import_promises.mkdir)(root, { recursive: true });
|
|
@@ -7856,9 +8165,22 @@ async function writeOperationTemplate(operation_key, destination, options = {},
|
|
|
7856
8165
|
const manifest_path = (0, import_node_path.join)(root, "manifest.json");
|
|
7857
8166
|
const tool_manual_path = (0, import_node_path.join)(root, "tool_manual.json");
|
|
7858
8167
|
const runtime_validation_path = (0, import_node_path.join)(root, "runtime_validation.json");
|
|
8168
|
+
const gitignore_path = (0, import_node_path.join)(root, ".gitignore");
|
|
7859
8169
|
const readme_path = (0, import_node_path.join)(root, "README.md");
|
|
7860
8170
|
const test_path = (0, import_node_path.join)(testsDir, "test_adapter.ts");
|
|
7861
|
-
|
|
8171
|
+
const docs_dir = (0, import_node_path.join)(root, "docs");
|
|
8172
|
+
await (0, import_promises.mkdir)(docs_dir, { recursive: true });
|
|
8173
|
+
const docs_usage_path = (0, import_node_path.join)(docs_dir, "api-usage.md");
|
|
8174
|
+
for (const filePath of [
|
|
8175
|
+
adapter_path,
|
|
8176
|
+
stubs_path,
|
|
8177
|
+
manifest_path,
|
|
8178
|
+
tool_manual_path,
|
|
8179
|
+
runtime_validation_path,
|
|
8180
|
+
docs_usage_path,
|
|
8181
|
+
readme_path,
|
|
8182
|
+
test_path
|
|
8183
|
+
]) {
|
|
7862
8184
|
if ((0, import_node_fs.existsSync)(filePath)) {
|
|
7863
8185
|
throw new SiglumeProjectError(`${(0, import_node_path.basename)(filePath)} already exists in ${root}`);
|
|
7864
8186
|
}
|
|
@@ -7886,10 +8208,22 @@ async function writeOperationTemplate(operation_key, destination, options = {},
|
|
|
7886
8208
|
await (0, import_promises.writeFile)(manifest_path, renderJson(manifest), "utf8");
|
|
7887
8209
|
await (0, import_promises.writeFile)(tool_manual_path, renderJson(tool_manual), "utf8");
|
|
7888
8210
|
await (0, import_promises.writeFile)(runtime_validation_path, renderJson(buildRuntimeValidationTemplate(tool_manual)), "utf8");
|
|
8211
|
+
await (0, import_promises.writeFile)(docs_usage_path, apiUsageDocsTemplate(manifest), "utf8");
|
|
8212
|
+
await writeOrMergeGitignore(gitignore_path);
|
|
7889
8213
|
await (0, import_promises.writeFile)(readme_path, operationReadmeTemplate(operation, manifest, warning), "utf8");
|
|
7890
8214
|
await (0, import_promises.writeFile)(test_path, operationTestSource(operation), "utf8");
|
|
7891
8215
|
return {
|
|
7892
|
-
files: [
|
|
8216
|
+
files: [
|
|
8217
|
+
adapter_path,
|
|
8218
|
+
stubs_path,
|
|
8219
|
+
manifest_path,
|
|
8220
|
+
tool_manual_path,
|
|
8221
|
+
runtime_validation_path,
|
|
8222
|
+
docs_usage_path,
|
|
8223
|
+
gitignore_path,
|
|
8224
|
+
readme_path,
|
|
8225
|
+
test_path
|
|
8226
|
+
],
|
|
7893
8227
|
operation,
|
|
7894
8228
|
report: {
|
|
7895
8229
|
tool_manual_valid,
|
|
@@ -8038,6 +8372,15 @@ async function findRuntimeValidationPath(root_dir) {
|
|
|
8038
8372
|
}
|
|
8039
8373
|
return null;
|
|
8040
8374
|
}
|
|
8375
|
+
async function findOauthCredentialsPath(root_dir) {
|
|
8376
|
+
for (const name of ["oauth_credentials.json", "oauth-credentials.json"]) {
|
|
8377
|
+
const candidate = (0, import_node_path.join)(root_dir, name);
|
|
8378
|
+
if ((0, import_node_fs.existsSync)(candidate)) {
|
|
8379
|
+
return candidate;
|
|
8380
|
+
}
|
|
8381
|
+
}
|
|
8382
|
+
return null;
|
|
8383
|
+
}
|
|
8041
8384
|
async function loadJsonObject(path, label) {
|
|
8042
8385
|
let payload;
|
|
8043
8386
|
try {
|
|
@@ -8261,11 +8604,18 @@ function readmeTemplate(template) {
|
|
|
8261
8604
|
"- `adapter.ts`: your AppAdapter implementation",
|
|
8262
8605
|
"- `manifest.json`: serialized AppManifest snapshot",
|
|
8263
8606
|
"- `tool_manual.json`: editable ToolManual draft for validation and registration",
|
|
8264
|
-
"- `runtime_validation.json`: live API smoke-test contract used during registration",
|
|
8607
|
+
"- `runtime_validation.json`: local live API smoke-test contract used during registration",
|
|
8608
|
+
"- `docs/api-usage.md`: publish this page and use its public URL as `docs_url`",
|
|
8609
|
+
"- `.gitignore`: keeps runtime review keys and OAuth client secrets out of Git",
|
|
8265
8610
|
"",
|
|
8266
8611
|
"Before registering, replace all generated placeholders:",
|
|
8267
|
-
"- In `adapter.ts` and `manifest.json`, replace `docs_url`
|
|
8268
|
-
"-
|
|
8612
|
+
"- In `adapter.ts` and `manifest.json`, replace `docs_url` with a dedicated public API usage guide, not a homepage.",
|
|
8613
|
+
"- Replace `support_contact` with a real support email address or public support URL.",
|
|
8614
|
+
"- Optional `seller_homepage_url` is the seller's official site and can stay blank.",
|
|
8615
|
+
"- In the local `runtime_validation.json`, replace the public URL and review-key placeholders.",
|
|
8616
|
+
"- If the API uses seller-side OAuth, create a local `oauth_credentials.json` next to the adapter.",
|
|
8617
|
+
"- Do not commit real review keys or OAuth client secrets; the generated `.gitignore` excludes those files.",
|
|
8618
|
+
"- Because `runtime_validation.json` is ignored, GitHub samples do not commit review-key values.",
|
|
8269
8619
|
"",
|
|
8270
8620
|
"Suggested workflow:",
|
|
8271
8621
|
"",
|
|
@@ -8276,11 +8626,14 @@ function readmeTemplate(template) {
|
|
|
8276
8626
|
"siglume score . --offline",
|
|
8277
8627
|
"```",
|
|
8278
8628
|
"",
|
|
8279
|
-
"After placeholders are replaced and `SIGLUME_API_KEY` is
|
|
8629
|
+
"After placeholders are replaced and `SIGLUME_API_KEY` is issued from Developer Portal -> CLI / API keys, run the server-aligned checks:",
|
|
8280
8630
|
"",
|
|
8281
8631
|
"```bash",
|
|
8282
8632
|
"siglume validate .",
|
|
8283
8633
|
"siglume score . --remote",
|
|
8634
|
+
"siglume preflight .",
|
|
8635
|
+
"siglume register .",
|
|
8636
|
+
"# inspect the draft, then explicitly approve publish:",
|
|
8284
8637
|
"siglume register . --confirm",
|
|
8285
8638
|
"```",
|
|
8286
8639
|
""
|
|
@@ -8449,18 +8802,52 @@ async function runCli(argv, deps = {}) {
|
|
|
8449
8802
|
throw new SiglumeProjectError("Score failed.");
|
|
8450
8803
|
}
|
|
8451
8804
|
});
|
|
8452
|
-
program.command("
|
|
8805
|
+
program.command("preflight").option("--json", "emit machine-readable JSON", false).argument("[path]", ".", "project path").action(async (path, options) => {
|
|
8806
|
+
const report = await runPreflight(path, deps);
|
|
8807
|
+
if (options.json) {
|
|
8808
|
+
emit(stdout, renderJson(report));
|
|
8809
|
+
return;
|
|
8810
|
+
}
|
|
8811
|
+
emit(stdout, "Preflight passed.");
|
|
8812
|
+
const preflight = report.registration_preflight;
|
|
8813
|
+
if (preflight?.remote_quality) {
|
|
8814
|
+
emit(stdout, `preflight_quality: ${preflight.remote_quality.grade} (${preflight.remote_quality.overall_score}/100)`);
|
|
8815
|
+
}
|
|
8816
|
+
if (report.runtime_validation_path) emit(stdout, `runtime_validation_path: ${String(report.runtime_validation_path)}`);
|
|
8817
|
+
if (report.oauth_credentials_path) emit(stdout, `oauth_credentials_path: ${String(report.oauth_credentials_path)}`);
|
|
8818
|
+
});
|
|
8819
|
+
program.command("register").option("--confirm", "confirm the draft registration immediately and publish it when the self-serve checks pass", false).option("--submit-review", "legacy alias: publish immediately if your environment still routes through submit-review", false).option("--json", "emit machine-readable JSON", false).argument("[path]", ".", "project path").action(async (path, options) => {
|
|
8453
8820
|
const report = await runRegistration(path, { confirm: options.confirm, submit_review: options.submitReview }, deps);
|
|
8454
8821
|
if (options.json) {
|
|
8455
8822
|
emit(stdout, renderJson(report));
|
|
8456
8823
|
} else {
|
|
8457
8824
|
const receipt = report.receipt;
|
|
8458
|
-
|
|
8825
|
+
if (report.confirmation) {
|
|
8826
|
+
emit(stdout, "Listing published.");
|
|
8827
|
+
} else if (report.review) {
|
|
8828
|
+
emit(stdout, "Listing published via legacy submit-review alias.");
|
|
8829
|
+
} else if (receipt.registration_mode === "upgrade") {
|
|
8830
|
+
emit(stdout, "Upgrade staged.");
|
|
8831
|
+
} else if (receipt.registration_mode === "refresh") {
|
|
8832
|
+
emit(stdout, "Draft refreshed.");
|
|
8833
|
+
} else {
|
|
8834
|
+
emit(stdout, "Draft listing created.");
|
|
8835
|
+
}
|
|
8459
8836
|
emit(stdout, `listing_id: ${receipt.listing_id}`);
|
|
8460
|
-
emit(stdout, `
|
|
8837
|
+
emit(stdout, `receipt_status: ${receipt.status}`);
|
|
8838
|
+
if (receipt.listing_status) emit(stdout, `listing_status: ${receipt.listing_status}`);
|
|
8839
|
+
if (receipt.oauth_status) emit(stdout, `oauth_configured: ${Boolean(receipt.oauth_status.configured)}`);
|
|
8461
8840
|
if (receipt.review_url) emit(stdout, `review_url: ${receipt.review_url}`);
|
|
8462
8841
|
if (receipt.trace_id) emit(stdout, `trace_id: ${receipt.trace_id}`);
|
|
8463
8842
|
if (receipt.request_id) emit(stdout, `request_id: ${receipt.request_id}`);
|
|
8843
|
+
if (report.confirmation) {
|
|
8844
|
+
const confirmation = report.confirmation;
|
|
8845
|
+
if (confirmation.status) emit(stdout, `confirmation_status: ${confirmation.status}`);
|
|
8846
|
+
if (confirmation.release?.release_status) emit(stdout, `release_status: ${confirmation.release.release_status}`);
|
|
8847
|
+
} else if (report.review) {
|
|
8848
|
+
const review = report.review;
|
|
8849
|
+
if (review.status) emit(stdout, `publish_status: ${review.status}`);
|
|
8850
|
+
}
|
|
8464
8851
|
const preflight = report.registration_preflight;
|
|
8465
8852
|
if (preflight?.remote_quality) {
|
|
8466
8853
|
emit(stdout, `preflight_quality: ${preflight.remote_quality.grade} (${preflight.remote_quality.overall_score}/100)`);
|