@siglume/api-sdk 0.10.0 → 0.10.2
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 +6 -5
- package/dist/bin/siglume.cjs +135 -233
- package/dist/bin/siglume.cjs.map +1 -1
- package/dist/bin/siglume.js +135 -233
- package/dist/bin/siglume.js.map +1 -1
- package/dist/cli/index.cjs +135 -233
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts +13 -129
- package/dist/cli/index.d.ts +13 -129
- package/dist/cli/index.js +135 -233
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +40 -254
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -216
- package/dist/index.d.ts +23 -216
- package/dist/index.js +40 -254
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
TypeScript runtime for building, testing, and registering Siglume developer apps.
|
|
4
4
|
|
|
5
|
-
This package is prepared in the public SDK repo and ships with the current v0.
|
|
5
|
+
This package is prepared in the public SDK repo and ships with the current v0.10.x release line.
|
|
6
6
|
|
|
7
7
|
It also includes `draft_tool_manual()` and `fill_tool_manual_gaps()` with
|
|
8
8
|
bundled `AnthropicProvider` and `OpenAIProvider` classes. Provide
|
|
@@ -65,8 +65,8 @@ siglume score . --offline
|
|
|
65
65
|
siglume validate .
|
|
66
66
|
siglume score . --remote
|
|
67
67
|
siglume preflight . # checks blockers without creating a draft
|
|
68
|
-
siglume register .
|
|
69
|
-
siglume register . --
|
|
68
|
+
siglume register . # preflight + auto-register + confirm/publish
|
|
69
|
+
siglume register . --draft-only # review-only draft staging
|
|
70
70
|
```
|
|
71
71
|
|
|
72
72
|
`siglume register` reads `tool_manual.json`, the local Git-ignored
|
|
@@ -76,8 +76,9 @@ credential files Git-ignored because they can contain review keys and client
|
|
|
76
76
|
secrets. SDK / HTTP automation can pass
|
|
77
77
|
`source_url`, `source_context`, and `input_form_spec` directly to
|
|
78
78
|
`auto-register`. The CLI runs preflight by default, then calls the same
|
|
79
|
-
`auto-register` route used by SDK / automation clients
|
|
80
|
-
|
|
79
|
+
`auto-register` route used by SDK / automation clients and confirms publication
|
|
80
|
+
unless `--draft-only` is set. Re-run the same `capability_key` to publish a
|
|
81
|
+
non-material upgrade when checks pass. The server-side publish gate
|
|
81
82
|
includes runtime checks, contract checks, seller OAuth checks, pricing / payout
|
|
82
83
|
rules, and a mandatory fail-closed LLM legal review for law compliance plus
|
|
83
84
|
public-order / morals compliance.
|
package/dist/bin/siglume.cjs
CHANGED
|
@@ -140,18 +140,6 @@ function camelCaseFromCapabilityKey(capabilityKey) {
|
|
|
140
140
|
}
|
|
141
141
|
return `${words.map((word) => word[0].toUpperCase() + word.slice(1)).join("")}App`;
|
|
142
142
|
}
|
|
143
|
-
function buildDefaultI18n(manifestPayload) {
|
|
144
|
-
const job = String(manifestPayload.job_to_be_done ?? "").trim();
|
|
145
|
-
const shortDescription = String(
|
|
146
|
-
manifestPayload.short_description ?? manifestPayload.job_to_be_done ?? manifestPayload.name ?? ""
|
|
147
|
-
).trim();
|
|
148
|
-
return {
|
|
149
|
-
job_to_be_done_en: job,
|
|
150
|
-
job_to_be_done_ja: job,
|
|
151
|
-
short_description_en: shortDescription,
|
|
152
|
-
short_description_ja: shortDescription
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
143
|
function buildRegistrationStubSource(manifestPayload, toolManualPayload) {
|
|
156
144
|
const capabilityKey = String(manifestPayload.capability_key ?? "generated-registration");
|
|
157
145
|
const jobToBeDone = String(
|
|
@@ -306,10 +294,8 @@ var init_webhooks = __esm({
|
|
|
306
294
|
"subscription.cancelled",
|
|
307
295
|
"subscription.paused",
|
|
308
296
|
"subscription.reinstated",
|
|
309
|
-
"refund.issued",
|
|
310
297
|
"payment.succeeded",
|
|
311
298
|
"payment.failed",
|
|
312
|
-
"payment.disputed",
|
|
313
299
|
"capability.published",
|
|
314
300
|
"capability.delisted",
|
|
315
301
|
"execution.completed",
|
|
@@ -1349,6 +1335,7 @@ function parseListing(data) {
|
|
|
1349
1335
|
price_value_minor: Number(data.price_value_minor ?? 0),
|
|
1350
1336
|
currency: String(data.currency ?? "USD"),
|
|
1351
1337
|
short_description: stringOrNull(data.short_description),
|
|
1338
|
+
description: stringOrNull(data.description),
|
|
1352
1339
|
docs_url: stringOrNull(data.docs_url),
|
|
1353
1340
|
support_contact: stringOrNull(data.support_contact),
|
|
1354
1341
|
seller_display_name: stringOrNull(data.seller_display_name),
|
|
@@ -1373,19 +1360,6 @@ function parseBundleMember(data) {
|
|
|
1373
1360
|
link_id: stringOrNull(data.link_id)
|
|
1374
1361
|
};
|
|
1375
1362
|
}
|
|
1376
|
-
function parseConnectedAccountProvider(data) {
|
|
1377
|
-
return {
|
|
1378
|
-
provider_key: String(data.provider_key ?? ""),
|
|
1379
|
-
display_name: String(data.display_name ?? ""),
|
|
1380
|
-
auth_type: String(data.auth_type ?? "oauth2"),
|
|
1381
|
-
refresh_supported: Boolean(data.refresh_supported ?? false),
|
|
1382
|
-
pkce_required: Boolean(data.pkce_required ?? false),
|
|
1383
|
-
default_scopes: Array.isArray(data.default_scopes) ? data.default_scopes.filter((s) => typeof s === "string") : [],
|
|
1384
|
-
available_scopes: Array.isArray(data.available_scopes) ? data.available_scopes.filter((s) => typeof s === "string") : [],
|
|
1385
|
-
scope_separator: String(data.scope_separator ?? " "),
|
|
1386
|
-
notes: stringOrNull(data.notes)
|
|
1387
|
-
};
|
|
1388
|
-
}
|
|
1389
1363
|
function parseConnectedAccountLifecycle(data) {
|
|
1390
1364
|
return {
|
|
1391
1365
|
connected_account_id: String(data.connected_account_id ?? ""),
|
|
@@ -2427,50 +2401,6 @@ function parseMarketProposalActionResult(execution) {
|
|
|
2427
2401
|
raw: { ...execution.raw }
|
|
2428
2402
|
};
|
|
2429
2403
|
}
|
|
2430
|
-
function parseRefund(data) {
|
|
2431
|
-
return {
|
|
2432
|
-
refund_id: String(data.refund_id ?? data.id ?? ""),
|
|
2433
|
-
receipt_id: String(data.receipt_id ?? ""),
|
|
2434
|
-
owner_user_id: stringOrNull(data.owner_user_id) ?? void 0,
|
|
2435
|
-
payment_mandate_id: stringOrNull(data.payment_mandate_id) ?? void 0,
|
|
2436
|
-
usage_event_id: stringOrNull(data.usage_event_id) ?? void 0,
|
|
2437
|
-
chain_receipt_id: stringOrNull(data.chain_receipt_id) ?? void 0,
|
|
2438
|
-
amount_minor: Number(data.amount_minor ?? 0),
|
|
2439
|
-
currency: String(data.currency ?? "USD"),
|
|
2440
|
-
status: String(data.status ?? "issued"),
|
|
2441
|
-
reason_code: String(data.reason_code ?? "customer-request"),
|
|
2442
|
-
note: stringOrNull(data.note) ?? void 0,
|
|
2443
|
-
idempotency_key: stringOrNull(data.idempotency_key) ?? void 0,
|
|
2444
|
-
on_chain_tx_hash: stringOrNull(data.on_chain_tx_hash) ?? void 0,
|
|
2445
|
-
metadata: toRecord(data.metadata),
|
|
2446
|
-
idempotent_replay: Boolean(data.idempotent_replay ?? false),
|
|
2447
|
-
created_at: stringOrNull(data.created_at) ?? void 0,
|
|
2448
|
-
updated_at: stringOrNull(data.updated_at) ?? void 0,
|
|
2449
|
-
raw: { ...data }
|
|
2450
|
-
};
|
|
2451
|
-
}
|
|
2452
|
-
function parseDispute(data) {
|
|
2453
|
-
return {
|
|
2454
|
-
dispute_id: String(data.dispute_id ?? data.id ?? ""),
|
|
2455
|
-
receipt_id: String(data.receipt_id ?? ""),
|
|
2456
|
-
owner_user_id: stringOrNull(data.owner_user_id) ?? void 0,
|
|
2457
|
-
payment_mandate_id: stringOrNull(data.payment_mandate_id) ?? void 0,
|
|
2458
|
-
usage_event_id: stringOrNull(data.usage_event_id) ?? void 0,
|
|
2459
|
-
external_dispute_id: stringOrNull(data.external_dispute_id) ?? void 0,
|
|
2460
|
-
status: String(data.status ?? "open"),
|
|
2461
|
-
reason_code: String(data.reason_code ?? "manual-review"),
|
|
2462
|
-
description: stringOrNull(data.description) ?? void 0,
|
|
2463
|
-
evidence: toRecord(data.evidence),
|
|
2464
|
-
response_decision: stringOrNull(data.response_decision) ?? void 0,
|
|
2465
|
-
response_note: stringOrNull(data.response_note) ?? void 0,
|
|
2466
|
-
responded_at: stringOrNull(data.responded_at) ?? void 0,
|
|
2467
|
-
metadata: toRecord(data.metadata),
|
|
2468
|
-
idempotent_replay: Boolean(data.idempotent_replay ?? false),
|
|
2469
|
-
created_at: stringOrNull(data.created_at) ?? void 0,
|
|
2470
|
-
updated_at: stringOrNull(data.updated_at) ?? void 0,
|
|
2471
|
-
raw: { ...data }
|
|
2472
|
-
};
|
|
2473
|
-
}
|
|
2474
2404
|
function cloneJsonLike(value) {
|
|
2475
2405
|
if (Array.isArray(value)) {
|
|
2476
2406
|
return value.map((item) => cloneJsonLike(item));
|
|
@@ -2555,10 +2485,13 @@ var init_client = __esm({
|
|
|
2555
2485
|
async auto_register(manifest, tool_manual, options = {}) {
|
|
2556
2486
|
const manifestPayload = coerceMapping(manifest, "manifest");
|
|
2557
2487
|
const toolManualPayload = coerceMapping(tool_manual, "tool_manual");
|
|
2488
|
+
const toolManualForRequest = { ...toolManualPayload };
|
|
2489
|
+
const embeddedInputFormSpec = toolManualForRequest.input_form_spec;
|
|
2490
|
+
delete toolManualForRequest.input_form_spec;
|
|
2491
|
+
const inputFormSpec = options.input_form_spec ?? embeddedInputFormSpec;
|
|
2558
2492
|
const payload = {
|
|
2559
|
-
i18n: buildDefaultI18n(manifestPayload),
|
|
2560
2493
|
manifest: { ...manifestPayload },
|
|
2561
|
-
tool_manual:
|
|
2494
|
+
tool_manual: toolManualForRequest
|
|
2562
2495
|
};
|
|
2563
2496
|
if (options.source_url) {
|
|
2564
2497
|
payload.source_url = options.source_url;
|
|
@@ -2577,14 +2510,11 @@ var init_client = __esm({
|
|
|
2577
2510
|
)
|
|
2578
2511
|
} : coerceMapping(options.oauth_credentials, "oauth_credentials");
|
|
2579
2512
|
}
|
|
2580
|
-
if (options.metadata) {
|
|
2581
|
-
payload.metadata = coerceMapping(options.metadata, "metadata");
|
|
2582
|
-
}
|
|
2583
2513
|
if (options.source_context) {
|
|
2584
2514
|
payload.source_context = coerceMapping(options.source_context, "source_context");
|
|
2585
2515
|
}
|
|
2586
|
-
if (
|
|
2587
|
-
payload.input_form_spec = coerceMapping(
|
|
2516
|
+
if (inputFormSpec !== void 0 && inputFormSpec !== null) {
|
|
2517
|
+
payload.input_form_spec = coerceMapping(inputFormSpec, "input_form_spec");
|
|
2588
2518
|
}
|
|
2589
2519
|
for (const fieldName of [
|
|
2590
2520
|
"capability_key",
|
|
@@ -2635,7 +2565,11 @@ var init_client = __esm({
|
|
|
2635
2565
|
if (!listing_id) {
|
|
2636
2566
|
throw new SiglumeClientError("Siglume auto-register response did not include listing_id.");
|
|
2637
2567
|
}
|
|
2638
|
-
this.pendingConfirmations.set(listing_id, {
|
|
2568
|
+
this.pendingConfirmations.set(listing_id, {
|
|
2569
|
+
manifest: manifestPayload,
|
|
2570
|
+
tool_manual: toRecord(payload.tool_manual),
|
|
2571
|
+
input_form_spec: toRecord(payload.input_form_spec)
|
|
2572
|
+
});
|
|
2639
2573
|
return {
|
|
2640
2574
|
listing_id,
|
|
2641
2575
|
status: String(data.status ?? "draft"),
|
|
@@ -2783,11 +2717,6 @@ var init_client = __esm({
|
|
|
2783
2717
|
// ----- end bundles -------------------------------------------------------
|
|
2784
2718
|
// ----- Connected accounts (v0.7 track 3) ---------------------------------
|
|
2785
2719
|
// `resolve()` is intentionally NOT wrapped: runtime-only, never over the wire.
|
|
2786
|
-
async list_connected_account_providers() {
|
|
2787
|
-
const [data] = await this.request("GET", "/me/connected-accounts/providers");
|
|
2788
|
-
const items = Array.isArray(data.items) ? data.items : [];
|
|
2789
|
-
return items.filter((item) => isRecord(item)).map(parseConnectedAccountProvider);
|
|
2790
|
-
}
|
|
2791
2720
|
async start_connected_account_oauth(input) {
|
|
2792
2721
|
const body = {
|
|
2793
2722
|
listing_id: input.listing_id,
|
|
@@ -2824,8 +2753,17 @@ var init_client = __esm({
|
|
|
2824
2753
|
const body = {
|
|
2825
2754
|
provider_key: input.provider_key,
|
|
2826
2755
|
client_id: input.client_id,
|
|
2827
|
-
client_secret: input.client_secret
|
|
2756
|
+
client_secret: input.client_secret,
|
|
2757
|
+
authorize_url: input.authorize_url,
|
|
2758
|
+
token_url: input.token_url
|
|
2828
2759
|
};
|
|
2760
|
+
if (input.revoke_url !== void 0) body.revoke_url = input.revoke_url;
|
|
2761
|
+
if (input.display_name !== void 0) body.display_name = input.display_name;
|
|
2762
|
+
if (input.scope_separator !== void 0) body.scope_separator = input.scope_separator;
|
|
2763
|
+
if (input.token_endpoint_auth !== void 0) body.token_endpoint_auth = input.token_endpoint_auth;
|
|
2764
|
+
if (input.pkce_required !== void 0) body.pkce_required = input.pkce_required;
|
|
2765
|
+
if (input.refresh_supported !== void 0) body.refresh_supported = input.refresh_supported;
|
|
2766
|
+
if (input.available_scopes !== void 0) body.available_scopes = input.available_scopes;
|
|
2829
2767
|
if (input.required_scopes !== void 0) body.required_scopes = input.required_scopes;
|
|
2830
2768
|
const [data] = await this.request("PUT", `/market/capabilities/${listing_id}/oauth-credentials`, {
|
|
2831
2769
|
json_body: body
|
|
@@ -4230,105 +4168,6 @@ ${details}` : summary;
|
|
|
4230
4168
|
fetchNext: next_cursor ? (cursor) => this.list_support_cases({ ...options, cursor }) : void 0
|
|
4231
4169
|
});
|
|
4232
4170
|
}
|
|
4233
|
-
async issue_partial_refund(options) {
|
|
4234
|
-
const receipt_id = String(options.receipt_id ?? "").trim();
|
|
4235
|
-
const idempotency_key = String(options.idempotency_key ?? "").trim();
|
|
4236
|
-
if (!receipt_id) {
|
|
4237
|
-
throw new SiglumeClientError("receipt_id is required.");
|
|
4238
|
-
}
|
|
4239
|
-
if (!idempotency_key) {
|
|
4240
|
-
throw new SiglumeClientError("idempotency_key is required.");
|
|
4241
|
-
}
|
|
4242
|
-
if (!Number.isFinite(options.amount_minor)) {
|
|
4243
|
-
throw new SiglumeClientError("amount_minor must be a finite number.");
|
|
4244
|
-
}
|
|
4245
|
-
const amount_minor = Math.trunc(options.amount_minor);
|
|
4246
|
-
if (amount_minor <= 0) {
|
|
4247
|
-
throw new SiglumeClientError("amount_minor must be positive.");
|
|
4248
|
-
}
|
|
4249
|
-
if (typeof options.original_amount_minor === "number" && amount_minor > Math.trunc(options.original_amount_minor)) {
|
|
4250
|
-
throw new SiglumeClientError("amount_minor cannot exceed the original receipt amount.");
|
|
4251
|
-
}
|
|
4252
|
-
const [data] = await this.request("POST", "/market/refunds", {
|
|
4253
|
-
json_body: {
|
|
4254
|
-
receipt_id,
|
|
4255
|
-
amount_minor,
|
|
4256
|
-
reason_code: options.reason ?? "customer-request",
|
|
4257
|
-
note: options.note,
|
|
4258
|
-
idempotency_key
|
|
4259
|
-
}
|
|
4260
|
-
});
|
|
4261
|
-
return parseRefund(data);
|
|
4262
|
-
}
|
|
4263
|
-
async issue_full_refund(options) {
|
|
4264
|
-
const receipt_id = String(options.receipt_id ?? "").trim();
|
|
4265
|
-
if (!receipt_id) {
|
|
4266
|
-
throw new SiglumeClientError("receipt_id is required.");
|
|
4267
|
-
}
|
|
4268
|
-
const provided_key = String(options.idempotency_key ?? "").trim();
|
|
4269
|
-
const idempotency_key = provided_key || `full-refund:${receipt_id}`;
|
|
4270
|
-
const [data] = await this.request("POST", "/market/refunds", {
|
|
4271
|
-
json_body: {
|
|
4272
|
-
receipt_id,
|
|
4273
|
-
reason_code: options.reason ?? "customer-request",
|
|
4274
|
-
note: options.note,
|
|
4275
|
-
idempotency_key
|
|
4276
|
-
}
|
|
4277
|
-
});
|
|
4278
|
-
return parseRefund(data);
|
|
4279
|
-
}
|
|
4280
|
-
async list_refunds(options = {}) {
|
|
4281
|
-
const [data] = await this.requestAny("GET", "/market/refunds", {
|
|
4282
|
-
params: {
|
|
4283
|
-
receipt_id: options.receipt_id,
|
|
4284
|
-
limit: Math.max(1, Math.min(Math.trunc(options.limit ?? 50), 100))
|
|
4285
|
-
}
|
|
4286
|
-
});
|
|
4287
|
-
if (!Array.isArray(data)) {
|
|
4288
|
-
throw new SiglumeClientError("Expected refunds to be returned as an array.");
|
|
4289
|
-
}
|
|
4290
|
-
return data.filter((item) => isRecord(item)).map(parseRefund);
|
|
4291
|
-
}
|
|
4292
|
-
async get_refund(refund_id) {
|
|
4293
|
-
const [data] = await this.request("GET", `/market/refunds/${refund_id}`);
|
|
4294
|
-
return parseRefund(data);
|
|
4295
|
-
}
|
|
4296
|
-
async get_refunds_for_receipt(receipt_id, options = {}) {
|
|
4297
|
-
return this.list_refunds({ receipt_id, limit: options.limit });
|
|
4298
|
-
}
|
|
4299
|
-
async list_disputes(options = {}) {
|
|
4300
|
-
const [data] = await this.requestAny("GET", "/market/disputes", {
|
|
4301
|
-
params: {
|
|
4302
|
-
receipt_id: options.receipt_id,
|
|
4303
|
-
limit: Math.max(1, Math.min(Math.trunc(options.limit ?? 50), 100))
|
|
4304
|
-
}
|
|
4305
|
-
});
|
|
4306
|
-
if (!Array.isArray(data)) {
|
|
4307
|
-
throw new SiglumeClientError("Expected disputes to be returned as an array.");
|
|
4308
|
-
}
|
|
4309
|
-
return data.filter((item) => isRecord(item)).map(parseDispute);
|
|
4310
|
-
}
|
|
4311
|
-
async get_dispute(dispute_id) {
|
|
4312
|
-
const [data] = await this.request("GET", `/market/disputes/${dispute_id}`);
|
|
4313
|
-
return parseDispute(data);
|
|
4314
|
-
}
|
|
4315
|
-
async respond_to_dispute(options) {
|
|
4316
|
-
const dispute_id = String(options.dispute_id ?? "").trim();
|
|
4317
|
-
if (!dispute_id) {
|
|
4318
|
-
throw new SiglumeClientError("dispute_id is required.");
|
|
4319
|
-
}
|
|
4320
|
-
if (!isRecord(options.evidence)) {
|
|
4321
|
-
throw new SiglumeClientError("evidence must be an object.");
|
|
4322
|
-
}
|
|
4323
|
-
const [data] = await this.request("POST", `/market/disputes/${dispute_id}/respond`, {
|
|
4324
|
-
json_body: {
|
|
4325
|
-
response: options.response,
|
|
4326
|
-
evidence: toRecord(options.evidence),
|
|
4327
|
-
note: options.note
|
|
4328
|
-
}
|
|
4329
|
-
});
|
|
4330
|
-
return parseDispute(data);
|
|
4331
|
-
}
|
|
4332
4171
|
async create_webhook_subscription(options) {
|
|
4333
4172
|
const normalizedEventTypes = options.event_types.map((item) => String(item).trim()).filter((item) => item.length > 0);
|
|
4334
4173
|
if (normalizedEventTypes.length === 0) {
|
|
@@ -5837,16 +5676,24 @@ function coerceToolManual(manual) {
|
|
|
5837
5676
|
}
|
|
5838
5677
|
function checkSchemaForbiddenRecursive(schema, rootField, pushIssue, path = "") {
|
|
5839
5678
|
for (const keyword of COMPOSITION_KEYWORDS) {
|
|
5840
|
-
if (keyword in schema) {
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
);
|
|
5679
|
+
if (!(keyword in schema)) {
|
|
5680
|
+
continue;
|
|
5681
|
+
}
|
|
5682
|
+
const branches = schema[keyword];
|
|
5683
|
+
const location = path ? `${rootField}.${path}.${keyword}` : `${rootField}.${keyword}`;
|
|
5684
|
+
if (!Array.isArray(branches) || branches.length === 0) {
|
|
5685
|
+
pushIssue(issue("INPUT_SCHEMA", `${keyword} must be a non-empty array`, location));
|
|
5686
|
+
continue;
|
|
5849
5687
|
}
|
|
5688
|
+
branches.forEach((branch, index) => {
|
|
5689
|
+
const branchPath = path ? `${path}.${keyword}[${index}]` : `${keyword}[${index}]`;
|
|
5690
|
+
const branchLocation = `${rootField}.${branchPath}`;
|
|
5691
|
+
if (!isRecord(branch)) {
|
|
5692
|
+
pushIssue(issue("INPUT_SCHEMA", `${keyword}[${index}] must be an object`, branchLocation));
|
|
5693
|
+
return;
|
|
5694
|
+
}
|
|
5695
|
+
checkSchemaForbiddenRecursive(branch, rootField, pushIssue, branchPath);
|
|
5696
|
+
});
|
|
5850
5697
|
}
|
|
5851
5698
|
for (const forbidden of INPUT_SCHEMA_FORBIDDEN_KEYS) {
|
|
5852
5699
|
if (forbidden in schema) {
|
|
@@ -7213,43 +7060,51 @@ async function loadProject(path = ".") {
|
|
|
7213
7060
|
oauth_credentials
|
|
7214
7061
|
};
|
|
7215
7062
|
}
|
|
7216
|
-
|
|
7217
|
-
|
|
7218
|
-
|
|
7219
|
-
|
|
7220
|
-
|
|
7221
|
-
|
|
7222
|
-
|
|
7223
|
-
|
|
7224
|
-
"google-calendar": "google",
|
|
7225
|
-
github: "github",
|
|
7226
|
-
linear: "linear",
|
|
7227
|
-
notion: "notion"
|
|
7228
|
-
};
|
|
7063
|
+
function isPlatformManagedRequirement(value) {
|
|
7064
|
+
if (!isRecord(value)) return false;
|
|
7065
|
+
if (value.platform_managed === true) return true;
|
|
7066
|
+
const owner = String(
|
|
7067
|
+
value.managed_by ?? value.auth_managed_by ?? value.connection_owner ?? ""
|
|
7068
|
+
).trim().toLowerCase().replaceAll("_", "-");
|
|
7069
|
+
return owner === "platform" || owner === "siglume" || owner === "siglume-platform";
|
|
7070
|
+
}
|
|
7229
7071
|
function oauthProviderKeyFromRequirement(value) {
|
|
7230
|
-
|
|
7231
|
-
|
|
7232
|
-
|
|
7233
|
-
|
|
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];
|
|
7072
|
+
if (isRecord(value)) {
|
|
7073
|
+
for (const key of ["provider_key", "provider", "account_type", "name"]) {
|
|
7074
|
+
const providerKey = oauthProviderKeyFromRequirement(value[key]);
|
|
7075
|
+
if (providerKey) return providerKey;
|
|
7239
7076
|
}
|
|
7077
|
+
return null;
|
|
7240
7078
|
}
|
|
7241
|
-
|
|
7079
|
+
const raw = String(value ?? "").trim();
|
|
7080
|
+
return raw || null;
|
|
7242
7081
|
}
|
|
7243
7082
|
function requiredOauthProviders(requirements) {
|
|
7244
7083
|
const providers = [];
|
|
7245
7084
|
for (const item of requirements ?? []) {
|
|
7085
|
+
if (!isPlatformManagedRequirement(item)) continue;
|
|
7246
7086
|
const providerKey = oauthProviderKeyFromRequirement(item);
|
|
7087
|
+
if (!providerKey) {
|
|
7088
|
+
throw new SiglumeProjectError(
|
|
7089
|
+
"required_connected_accounts platform-managed entries must include a provider_key"
|
|
7090
|
+
);
|
|
7091
|
+
}
|
|
7247
7092
|
if (providerKey && !providers.includes(providerKey)) {
|
|
7248
7093
|
providers.push(providerKey);
|
|
7249
7094
|
}
|
|
7250
7095
|
}
|
|
7251
7096
|
return providers;
|
|
7252
7097
|
}
|
|
7098
|
+
function connectedAccountRequirementLabel(value) {
|
|
7099
|
+
if (isRecord(value)) {
|
|
7100
|
+
for (const key of ["provider_key", "provider", "account_type", "name"]) {
|
|
7101
|
+
const label = String(value[key] ?? "").trim();
|
|
7102
|
+
if (label) return label;
|
|
7103
|
+
}
|
|
7104
|
+
return "";
|
|
7105
|
+
}
|
|
7106
|
+
return String(value ?? "").trim();
|
|
7107
|
+
}
|
|
7253
7108
|
function oauthProviderRecordsMap(payload) {
|
|
7254
7109
|
if (!payload) {
|
|
7255
7110
|
return {};
|
|
@@ -7262,7 +7117,23 @@ function oauthProviderRecordsMap(payload) {
|
|
|
7262
7117
|
}
|
|
7263
7118
|
const providerKey = oauthProviderKeyFromRequirement(item.provider_key ?? item.provider);
|
|
7264
7119
|
if (!providerKey) {
|
|
7265
|
-
throw new SiglumeProjectError(`oauth_credentials[${index}].provider_key is
|
|
7120
|
+
throw new SiglumeProjectError(`oauth_credentials[${index}].provider_key is required.`);
|
|
7121
|
+
}
|
|
7122
|
+
const authorizeUrl = String(item.authorize_url ?? item.authorization_url ?? item.auth_url ?? "").trim();
|
|
7123
|
+
const tokenUrl = String(item.token_url ?? "").trim();
|
|
7124
|
+
if (!authorizeUrl || !tokenUrl) {
|
|
7125
|
+
throw new SiglumeProjectError(
|
|
7126
|
+
`oauth_credentials[${index}] must include authorize_url and token_url.`
|
|
7127
|
+
);
|
|
7128
|
+
}
|
|
7129
|
+
for (const [urlKey, urlValue] of Object.entries({
|
|
7130
|
+
authorize_url: authorizeUrl,
|
|
7131
|
+
token_url: tokenUrl,
|
|
7132
|
+
revoke_url: String(item.revoke_url ?? "").trim()
|
|
7133
|
+
})) {
|
|
7134
|
+
if (urlValue && !urlValue.startsWith("https://")) {
|
|
7135
|
+
throw new SiglumeProjectError(`oauth_credentials[${index}].${urlKey} must be an https URL.`);
|
|
7136
|
+
}
|
|
7266
7137
|
}
|
|
7267
7138
|
const clientId = String(item.client_id ?? "").trim();
|
|
7268
7139
|
const clientSecret = String(item.client_secret ?? "").trim();
|
|
@@ -7278,12 +7149,30 @@ function oauthProviderRecordsMap(payload) {
|
|
|
7278
7149
|
} else {
|
|
7279
7150
|
scopes = rawScopes.map((scope) => String(scope ?? "").trim()).filter(Boolean);
|
|
7280
7151
|
}
|
|
7281
|
-
|
|
7152
|
+
const record = {
|
|
7282
7153
|
provider_key: providerKey,
|
|
7283
7154
|
client_id: clientId,
|
|
7284
7155
|
client_secret: clientSecret,
|
|
7285
7156
|
required_scopes: scopes
|
|
7286
7157
|
};
|
|
7158
|
+
for (const [key, value] of Object.entries({
|
|
7159
|
+
authorize_url: authorizeUrl,
|
|
7160
|
+
token_url: tokenUrl,
|
|
7161
|
+
revoke_url: String(item.revoke_url ?? "").trim(),
|
|
7162
|
+
display_name: String(item.display_name ?? "").trim(),
|
|
7163
|
+
scope_separator: String(item.scope_separator ?? "").trim(),
|
|
7164
|
+
token_endpoint_auth: String(item.token_endpoint_auth ?? "").trim()
|
|
7165
|
+
})) {
|
|
7166
|
+
if (value) record[key] = value;
|
|
7167
|
+
}
|
|
7168
|
+
for (const key of ["pkce_required", "refresh_supported"]) {
|
|
7169
|
+
if (typeof item[key] === "boolean") record[key] = item[key];
|
|
7170
|
+
}
|
|
7171
|
+
if (Array.isArray(item.available_scopes)) {
|
|
7172
|
+
const availableScopes = item.available_scopes.map((scope) => String(scope ?? "").trim()).filter(Boolean);
|
|
7173
|
+
if (availableScopes.length > 0) record.available_scopes = availableScopes;
|
|
7174
|
+
}
|
|
7175
|
+
resolved[providerKey] = record;
|
|
7287
7176
|
}
|
|
7288
7177
|
return resolved;
|
|
7289
7178
|
}
|
|
@@ -7309,7 +7198,7 @@ function ensureRequiredOauthCredentials(project) {
|
|
|
7309
7198
|
}
|
|
7310
7199
|
const path = project.oauth_credentials_path ?? (0, import_node_path.join)(project.root_dir, "oauth_credentials.json");
|
|
7311
7200
|
throw new SiglumeProjectError(
|
|
7312
|
-
`${path} is required for
|
|
7201
|
+
`${path} is required for platform-managed OAuth APIs. Missing provider seeds: ${missing.join(", ")}`
|
|
7313
7202
|
);
|
|
7314
7203
|
}
|
|
7315
7204
|
async function validateProject(path = ".", deps = {}) {
|
|
@@ -7477,7 +7366,7 @@ async function registrationPreflight(project, client) {
|
|
|
7477
7366
|
errors.push(`remote Tool Manual quality is not publishable: ${remoteQuality.grade} (${remoteQuality.overall_score}/100)`);
|
|
7478
7367
|
}
|
|
7479
7368
|
if (missingOauthProviders.length > 0) {
|
|
7480
|
-
errors.push(`oauth_credentials.json is required for
|
|
7369
|
+
errors.push(`oauth_credentials.json is required for platform-managed OAuth APIs: ${missingOauthProviders.join(", ")}`);
|
|
7481
7370
|
}
|
|
7482
7371
|
const preflight = {
|
|
7483
7372
|
manifest_issues: manifestIssues,
|
|
@@ -7503,6 +7392,7 @@ async function runRegistration(path = ".", options = {}, deps = {}) {
|
|
|
7503
7392
|
ensureManifestPublisherIdentity(project);
|
|
7504
7393
|
ensureRuntimeValidationReady(project);
|
|
7505
7394
|
ensureRequiredOauthCredentials(project);
|
|
7395
|
+
const canonicalOauthCredentials = canonicalOauthCredentialsPayload(project.oauth_credentials);
|
|
7506
7396
|
const client = await createClient(deps);
|
|
7507
7397
|
const preflight = await registrationPreflight(project, client);
|
|
7508
7398
|
let developerPortalPreflight = null;
|
|
@@ -7518,7 +7408,7 @@ async function runRegistration(path = ".", options = {}, deps = {}) {
|
|
|
7518
7408
|
}
|
|
7519
7409
|
const receipt = await client.auto_register(project.manifest, project.tool_manual, {
|
|
7520
7410
|
runtime_validation: project.runtime_validation,
|
|
7521
|
-
oauth_credentials:
|
|
7411
|
+
oauth_credentials: canonicalOauthCredentials
|
|
7522
7412
|
});
|
|
7523
7413
|
const result = {
|
|
7524
7414
|
receipt: toJsonable(receipt),
|
|
@@ -7529,7 +7419,8 @@ async function runRegistration(path = ".", options = {}, deps = {}) {
|
|
|
7529
7419
|
if (developerPortalPreflight) {
|
|
7530
7420
|
result.developer_portal_preflight = developerPortalPreflight;
|
|
7531
7421
|
}
|
|
7532
|
-
|
|
7422
|
+
const shouldConfirm = Boolean(options.confirm) || options.confirm === void 0 && !options.draft_only && !options.submit_review;
|
|
7423
|
+
if (shouldConfirm) {
|
|
7533
7424
|
result.confirmation = toJsonable(await client.confirm_registration(receipt.listing_id));
|
|
7534
7425
|
if (options.submit_review) {
|
|
7535
7426
|
result.submit_review_skipped = true;
|
|
@@ -8060,8 +7951,8 @@ function operationReadmeTemplate(operation, manifest, warning) {
|
|
|
8060
7951
|
"siglume score . --remote",
|
|
8061
7952
|
"siglume preflight .",
|
|
8062
7953
|
"siglume register .",
|
|
8063
|
-
"#
|
|
8064
|
-
"siglume register . --
|
|
7954
|
+
"# review-only staging path:",
|
|
7955
|
+
"siglume register . --draft-only",
|
|
8065
7956
|
"```",
|
|
8066
7957
|
""
|
|
8067
7958
|
].join("\n");
|
|
@@ -8072,7 +7963,7 @@ function apiUsageDocsTemplate(manifest) {
|
|
|
8072
7963
|
const jobToBeDone = String(manifest.job_to_be_done ?? "Describe what this API lets an agent do.");
|
|
8073
7964
|
const permissionClass = String(manifest.permission_class ?? "read-only");
|
|
8074
7965
|
const priceModel = String(manifest.price_model ?? "free");
|
|
8075
|
-
const requiredAccounts = (manifest.required_connected_accounts ?? []).join(", ") || "none";
|
|
7966
|
+
const requiredAccounts = (manifest.required_connected_accounts ?? []).map((item) => connectedAccountRequirementLabel(item)).filter(Boolean).join(", ") || "none";
|
|
8076
7967
|
const supportContact = String(manifest.support_contact ?? "replace-with-support-contact");
|
|
8077
7968
|
return [
|
|
8078
7969
|
`# ${name} API Usage Guide`,
|
|
@@ -8633,8 +8524,8 @@ function readmeTemplate(template) {
|
|
|
8633
8524
|
"siglume score . --remote",
|
|
8634
8525
|
"siglume preflight .",
|
|
8635
8526
|
"siglume register .",
|
|
8636
|
-
"#
|
|
8637
|
-
"siglume register . --
|
|
8527
|
+
"# review-only staging path:",
|
|
8528
|
+
"siglume register . --draft-only",
|
|
8638
8529
|
"```",
|
|
8639
8530
|
""
|
|
8640
8531
|
].join("\n");
|
|
@@ -8816,16 +8707,25 @@ async function runCli(argv, deps = {}) {
|
|
|
8816
8707
|
if (report.runtime_validation_path) emit(stdout, `runtime_validation_path: ${String(report.runtime_validation_path)}`);
|
|
8817
8708
|
if (report.oauth_credentials_path) emit(stdout, `oauth_credentials_path: ${String(report.oauth_credentials_path)}`);
|
|
8818
8709
|
});
|
|
8819
|
-
program.command("register").option("--confirm", "confirm the draft
|
|
8820
|
-
const
|
|
8710
|
+
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("--json", "emit machine-readable JSON", false).argument("[path]", ".", "project path").action(async (path, options) => {
|
|
8711
|
+
const draftOnly = Boolean(options.draftOnly);
|
|
8712
|
+
if (draftOnly && options.confirm) {
|
|
8713
|
+
throw new SiglumeProjectError("--draft-only cannot be combined with --confirm.");
|
|
8714
|
+
}
|
|
8715
|
+
if (draftOnly && options.submitReview) {
|
|
8716
|
+
throw new SiglumeProjectError("--draft-only cannot be combined with --submit-review.");
|
|
8717
|
+
}
|
|
8718
|
+
const shouldConfirm = Boolean(options.confirm) || !draftOnly && !options.submitReview;
|
|
8719
|
+
const report = await runRegistration(path, { confirm: shouldConfirm, draft_only: draftOnly, submit_review: options.submitReview }, deps);
|
|
8821
8720
|
if (options.json) {
|
|
8822
8721
|
emit(stdout, renderJson(report));
|
|
8823
8722
|
} else {
|
|
8824
8723
|
const receipt = report.receipt;
|
|
8825
|
-
|
|
8826
|
-
|
|
8827
|
-
|
|
8828
|
-
|
|
8724
|
+
const published = Boolean(report.confirmation || report.review);
|
|
8725
|
+
if (published && receipt.registration_mode === "upgrade") {
|
|
8726
|
+
emit(stdout, "Upgrade registered.");
|
|
8727
|
+
} else if (published) {
|
|
8728
|
+
emit(stdout, "Registration accepted.");
|
|
8829
8729
|
} else if (receipt.registration_mode === "upgrade") {
|
|
8830
8730
|
emit(stdout, "Upgrade staged.");
|
|
8831
8731
|
} else if (receipt.registration_mode === "refresh") {
|
|
@@ -8842,10 +8742,12 @@ async function runCli(argv, deps = {}) {
|
|
|
8842
8742
|
if (receipt.request_id) emit(stdout, `request_id: ${receipt.request_id}`);
|
|
8843
8743
|
if (report.confirmation) {
|
|
8844
8744
|
const confirmation = report.confirmation;
|
|
8745
|
+
emit(stdout, "Listing published.");
|
|
8845
8746
|
if (confirmation.status) emit(stdout, `confirmation_status: ${confirmation.status}`);
|
|
8846
8747
|
if (confirmation.release?.release_status) emit(stdout, `release_status: ${confirmation.release.release_status}`);
|
|
8847
8748
|
} else if (report.review) {
|
|
8848
8749
|
const review = report.review;
|
|
8750
|
+
emit(stdout, "Listing published via legacy submit-review alias.");
|
|
8849
8751
|
if (review.status) emit(stdout, `publish_status: ${review.status}`);
|
|
8850
8752
|
}
|
|
8851
8753
|
const preflight = report.registration_preflight;
|