@siglume/api-sdk 1.2.2 → 2.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 +19 -2
- package/dist/bin/siglume.cjs +63 -264
- package/dist/bin/siglume.cjs.map +1 -1
- package/dist/bin/siglume.js +63 -264
- package/dist/bin/siglume.js.map +1 -1
- package/dist/cli/index.cjs +63 -264
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts +29 -150
- package/dist/cli/index.d.ts +29 -150
- package/dist/cli/index.js +63 -264
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +35 -248
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -190
- package/dist/index.d.ts +30 -190
- package/dist/index.js +35 -248
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ Buyer-side discovery and export helpers are also included:
|
|
|
27
27
|
import { SiglumeBuyerClient, to_anthropic_tool } from "@siglume/api-sdk";
|
|
28
28
|
|
|
29
29
|
const buyer = new SiglumeBuyerClient({
|
|
30
|
-
api_key: process.env.
|
|
30
|
+
api_key: process.env.SIGLUME_OWNER_SESSION_BEARER!,
|
|
31
31
|
default_agent_id: process.env.SIGLUME_AGENT_ID,
|
|
32
32
|
});
|
|
33
33
|
|
|
@@ -73,7 +73,7 @@ siglume register . --company company_123
|
|
|
73
73
|
|
|
74
74
|
`siglume register` reads `tool_manual.json`, the local Git-ignored
|
|
75
75
|
`runtime_validation.json`. Generated projects keep runtime validation files
|
|
76
|
-
Git-ignored because they
|
|
76
|
+
Git-ignored because they hold the runtime auth header shared secret. 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
79
|
`auto-register` route used by SDK / automation clients and confirms publication
|
|
@@ -88,6 +88,14 @@ public-order / morals compliance.
|
|
|
88
88
|
For the canonical pricing reference, see
|
|
89
89
|
[`../docs/pricing-and-billing.md`](../docs/pricing-and-billing.md).
|
|
90
90
|
|
|
91
|
+
Developer-funded reward or incentive payouts are not normal SDK/API-key calls.
|
|
92
|
+
Do not call MCP Gateway with `SIGLUME_API_KEY`, `cli_...`, `X-API-Key`, or
|
|
93
|
+
`X-Siglume-API-Key`. Reward payout execution uses
|
|
94
|
+
`https://mcp.siglume.com/` with `Authorization: Bearer mcpsk_...` and
|
|
95
|
+
`tools/call market_create_reward_payout`; SDK/API keys remain for
|
|
96
|
+
registration, validation, and listing automation. See
|
|
97
|
+
[`../docs/web3-settlement.md#generic-reward-payouts`](../docs/web3-settlement.md#generic-reward-payouts).
|
|
98
|
+
|
|
91
99
|
Use `price_model: PriceModel.USAGE_BASED` or `PriceModel.PER_ACTION` when the
|
|
92
100
|
API must execute before the final operation is known. These listings are free to
|
|
93
101
|
invoke up front. Your adapter returns the executed operation in
|
|
@@ -145,6 +153,15 @@ then calls the ACTION endpoint with the same token as `commit_token`. If payment
|
|
|
145
153
|
fails, the ACTION call is never made. Use the default `"post"` timing only for
|
|
146
154
|
read-only or reversible usage.
|
|
147
155
|
|
|
156
|
+
Responsibility boundary: Siglume owns payment, authorization, platform
|
|
157
|
+
idempotency, retry state, usage rows, and reconciliation state. Your API owns
|
|
158
|
+
the provider-specific action and the proof that it committed. The platform does
|
|
159
|
+
not infer whether an X post, email, CRM write, booking, or other external action
|
|
160
|
+
happened. Return committed evidence only after the side effect committed;
|
|
161
|
+
draft-only, preview, ambiguous, or `status="ready"` live-action results are not
|
|
162
|
+
delivered results. See
|
|
163
|
+
[`../docs/platform-api-boundary.md`](../docs/platform-api-boundary.md).
|
|
164
|
+
|
|
148
165
|
After live or sandbox execution, inspect receipts with `siglume dev tail`,
|
|
149
166
|
`siglume dev tail --listing-id <listing_id>`, or the SDK receipt helpers. The
|
|
150
167
|
publisher listing view is privacy-redacted. See
|
package/dist/bin/siglume.cjs
CHANGED
|
@@ -354,7 +354,12 @@ var init_webhooks = __esm({
|
|
|
354
354
|
"capability.published",
|
|
355
355
|
"capability.delisted",
|
|
356
356
|
"execution.completed",
|
|
357
|
-
"execution.failed"
|
|
357
|
+
"execution.failed",
|
|
358
|
+
"reward_payout.created",
|
|
359
|
+
"reward_payout.provider_pending",
|
|
360
|
+
"reward_paid",
|
|
361
|
+
"reward_payout.failed",
|
|
362
|
+
"reward_payout.cancelled"
|
|
358
363
|
];
|
|
359
364
|
WEBHOOK_EVENT_SET = new Set(WEBHOOK_EVENT_TYPES);
|
|
360
365
|
}
|
|
@@ -1404,6 +1409,23 @@ function validatePricingPlanFloor(plan, defaultCurrency) {
|
|
|
1404
1409
|
function pricingPlanHasItems(plan) {
|
|
1405
1410
|
return isRecord(plan) && Array.isArray(plan.items) && plan.items.length > 0;
|
|
1406
1411
|
}
|
|
1412
|
+
function validateListingTextLengths(payload) {
|
|
1413
|
+
const limits = {
|
|
1414
|
+
short_description: LISTING_SHORT_DESCRIPTION_MAX_LENGTH,
|
|
1415
|
+
job_to_be_done: LISTING_JOB_TO_BE_DONE_MAX_LENGTH,
|
|
1416
|
+
description: LISTING_DESCRIPTION_MAX_LENGTH
|
|
1417
|
+
};
|
|
1418
|
+
for (const [fieldName, maxLength] of Object.entries(limits)) {
|
|
1419
|
+
const value = payload[fieldName];
|
|
1420
|
+
if (value === void 0 || value === null) continue;
|
|
1421
|
+
if (typeof value !== "string") {
|
|
1422
|
+
throw new SiglumeClientError(`AppManifest.${fieldName} must be a string when provided.`);
|
|
1423
|
+
}
|
|
1424
|
+
if (Array.from(value).length > maxLength) {
|
|
1425
|
+
throw new SiglumeClientError(`AppManifest.${fieldName} must be at most ${maxLength} characters.`);
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1407
1429
|
function buildToolManualQualityReport(payload) {
|
|
1408
1430
|
const qualityBlock = isRecord(payload.quality) ? payload.quality : payload;
|
|
1409
1431
|
const issues = [];
|
|
@@ -1961,139 +1983,6 @@ function parseInstalledToolReceiptStep(data) {
|
|
|
1961
1983
|
raw: { ...data }
|
|
1962
1984
|
};
|
|
1963
1985
|
}
|
|
1964
|
-
function toRecordList(value) {
|
|
1965
|
-
return Array.isArray(value) ? value.filter((item) => isRecord(item)).map((item) => ({ ...item })) : [];
|
|
1966
|
-
}
|
|
1967
|
-
function parsePartnerDashboard(data) {
|
|
1968
|
-
return {
|
|
1969
|
-
partner_id: String(data.partner_id ?? data.user_id ?? ""),
|
|
1970
|
-
company_name: stringOrNull(data.company_name) ?? void 0,
|
|
1971
|
-
plan: stringOrNull(data.plan) ?? void 0,
|
|
1972
|
-
plan_label: stringOrNull(data.plan_label) ?? void 0,
|
|
1973
|
-
month_bytes_used: Math.trunc(Number(data.month_bytes_used ?? 0)),
|
|
1974
|
-
month_bytes_limit: Math.trunc(Number(data.month_bytes_limit ?? 0)),
|
|
1975
|
-
month_usage_pct: Number(data.month_usage_pct ?? 0),
|
|
1976
|
-
total_source_items: Math.trunc(Number(data.total_source_items ?? 0)),
|
|
1977
|
-
has_billing: Boolean(data.has_billing ?? false),
|
|
1978
|
-
has_subscription: Boolean(data.has_subscription ?? false),
|
|
1979
|
-
raw: { ...data }
|
|
1980
|
-
};
|
|
1981
|
-
}
|
|
1982
|
-
function parsePartnerUsage(data) {
|
|
1983
|
-
return {
|
|
1984
|
-
plan: stringOrNull(data.plan) ?? void 0,
|
|
1985
|
-
month_bytes_used: Math.trunc(Number(data.month_bytes_used ?? 0)),
|
|
1986
|
-
month_bytes_limit: Math.trunc(Number(data.month_bytes_limit ?? 0)),
|
|
1987
|
-
month_bytes_remaining: Math.trunc(Number(data.month_bytes_remaining ?? 0)),
|
|
1988
|
-
month_usage_pct: Number(data.month_usage_pct ?? 0),
|
|
1989
|
-
raw: { ...data }
|
|
1990
|
-
};
|
|
1991
|
-
}
|
|
1992
|
-
function parsePartnerApiKey(data) {
|
|
1993
|
-
return {
|
|
1994
|
-
credential_id: String(data.credential_id ?? data.id ?? ""),
|
|
1995
|
-
name: stringOrNull(data.name) ?? void 0,
|
|
1996
|
-
key_id: stringOrNull(data.key_id) ?? void 0,
|
|
1997
|
-
allowed_source_types: Array.isArray(data.allowed_source_types) ? data.allowed_source_types.filter((item) => typeof item === "string") : [],
|
|
1998
|
-
last_used_at: stringOrNull(data.last_used_at) ?? void 0,
|
|
1999
|
-
created_at: stringOrNull(data.created_at) ?? void 0,
|
|
2000
|
-
revoked: Boolean(data.revoked ?? false),
|
|
2001
|
-
raw: { ...data }
|
|
2002
|
-
};
|
|
2003
|
-
}
|
|
2004
|
-
function parsePartnerApiKeyHandle(data) {
|
|
2005
|
-
const raw = Object.fromEntries(
|
|
2006
|
-
Object.entries(data).filter(([key]) => key !== "ingest_key" && key !== "full_key")
|
|
2007
|
-
);
|
|
2008
|
-
return {
|
|
2009
|
-
credential_id: String(raw.credential_id ?? raw.id ?? ""),
|
|
2010
|
-
name: stringOrNull(raw.name) ?? void 0,
|
|
2011
|
-
key_id: stringOrNull(raw.key_id) ?? void 0,
|
|
2012
|
-
allowed_source_types: Array.isArray(raw.allowed_source_types) ? raw.allowed_source_types.filter((item) => typeof item === "string") : [],
|
|
2013
|
-
masked_key_hint: stringOrNull(raw.masked_key_hint) ?? void 0,
|
|
2014
|
-
raw
|
|
2015
|
-
};
|
|
2016
|
-
}
|
|
2017
|
-
function parseAdsBilling(data) {
|
|
2018
|
-
return {
|
|
2019
|
-
currency: stringOrNull(data.currency) ?? void 0,
|
|
2020
|
-
billing_mode: stringOrNull(data.billing_mode) ?? void 0,
|
|
2021
|
-
month_spend_jpy: Math.trunc(Number(data.month_spend_jpy ?? 0)),
|
|
2022
|
-
month_spend_usd: Math.trunc(Number(data.month_spend_usd ?? 0)),
|
|
2023
|
-
all_time_spend_jpy: Math.trunc(Number(data.all_time_spend_jpy ?? 0)),
|
|
2024
|
-
all_time_spend_usd: Math.trunc(Number(data.all_time_spend_usd ?? 0)),
|
|
2025
|
-
total_impressions: Math.trunc(Number(data.total_impressions ?? 0)),
|
|
2026
|
-
total_replies: Math.trunc(Number(data.total_replies ?? 0)),
|
|
2027
|
-
has_billing: Boolean(data.has_billing ?? false),
|
|
2028
|
-
has_subscription: Boolean(data.has_subscription ?? false),
|
|
2029
|
-
invoices: toRecordList(data.invoices),
|
|
2030
|
-
wallet: isRecord(data.wallet) ? { ...data.wallet } : null,
|
|
2031
|
-
balances: toRecordList(data.balances),
|
|
2032
|
-
supported_tokens: toRecordList(data.supported_tokens),
|
|
2033
|
-
funding_instructions: isRecord(data.funding_instructions) ? { ...data.funding_instructions } : null,
|
|
2034
|
-
mandate: isRecord(data.mandate) ? parsePlanWeb3Mandate(data.mandate) : null,
|
|
2035
|
-
raw: { ...data }
|
|
2036
|
-
};
|
|
2037
|
-
}
|
|
2038
|
-
function parseAdsBillingSettlement(data) {
|
|
2039
|
-
return {
|
|
2040
|
-
status: stringOrNull(data.status) ?? void 0,
|
|
2041
|
-
message: stringOrNull(data.message ?? data.detail) ?? void 0,
|
|
2042
|
-
settles_automatically: typeof data.settles_automatically === "boolean" ? data.settles_automatically : typeof data.auto_settles === "boolean" ? data.auto_settles : void 0,
|
|
2043
|
-
cycle_key: stringOrNull(data.cycle_key) ?? void 0,
|
|
2044
|
-
settled_at: stringOrNull(data.settled_at) ?? void 0,
|
|
2045
|
-
raw: { ...data }
|
|
2046
|
-
};
|
|
2047
|
-
}
|
|
2048
|
-
function parseAdsProfile(data) {
|
|
2049
|
-
return {
|
|
2050
|
-
has_profile: Boolean(data.has_profile ?? false),
|
|
2051
|
-
company_name: stringOrNull(data.company_name) ?? void 0,
|
|
2052
|
-
ad_currency: stringOrNull(data.ad_currency) ?? void 0,
|
|
2053
|
-
has_billing: Boolean(data.has_billing ?? false),
|
|
2054
|
-
raw: { ...data }
|
|
2055
|
-
};
|
|
2056
|
-
}
|
|
2057
|
-
function parseAdsCampaign(data) {
|
|
2058
|
-
return {
|
|
2059
|
-
campaign_id: String(data.campaign_id ?? data.id ?? ""),
|
|
2060
|
-
name: stringOrNull(data.name) ?? void 0,
|
|
2061
|
-
target_url: stringOrNull(data.target_url) ?? void 0,
|
|
2062
|
-
content_brief: stringOrNull(data.content_brief) ?? void 0,
|
|
2063
|
-
target_topics: Array.isArray(data.target_topics) ? data.target_topics.filter((item) => typeof item === "string") : [],
|
|
2064
|
-
posting_interval_minutes: Math.trunc(Number(data.posting_interval_minutes ?? 360)),
|
|
2065
|
-
max_posts_per_day: Math.trunc(Number(data.max_posts_per_day ?? 4)),
|
|
2066
|
-
currency: stringOrNull(data.currency) ?? void 0,
|
|
2067
|
-
monthly_budget_jpy: Math.trunc(Number(data.monthly_budget_jpy ?? 0)),
|
|
2068
|
-
cpm_jpy: Math.trunc(Number(data.cpm_jpy ?? 0)),
|
|
2069
|
-
cpr_jpy: Math.trunc(Number(data.cpr_jpy ?? 0)),
|
|
2070
|
-
monthly_budget_usd: Math.trunc(Number(data.monthly_budget_usd ?? 0)),
|
|
2071
|
-
cpm_usd: Math.trunc(Number(data.cpm_usd ?? 0)),
|
|
2072
|
-
cpr_usd: Math.trunc(Number(data.cpr_usd ?? 0)),
|
|
2073
|
-
status: String(data.status ?? "active").trim().toLowerCase() || "active",
|
|
2074
|
-
month_spend_jpy: Math.trunc(Number(data.month_spend_jpy ?? 0)),
|
|
2075
|
-
month_spend_usd: Math.trunc(Number(data.month_spend_usd ?? 0)),
|
|
2076
|
-
total_posts: Math.trunc(Number(data.total_posts ?? 0)),
|
|
2077
|
-
total_impressions: Math.trunc(Number(data.total_impressions ?? 0)),
|
|
2078
|
-
total_replies: Math.trunc(Number(data.total_replies ?? 0)),
|
|
2079
|
-
next_post_at: stringOrNull(data.next_post_at) ?? void 0,
|
|
2080
|
-
created_at: stringOrNull(data.created_at) ?? void 0,
|
|
2081
|
-
raw: { ...data }
|
|
2082
|
-
};
|
|
2083
|
-
}
|
|
2084
|
-
function parseAdsCampaignPost(data) {
|
|
2085
|
-
return {
|
|
2086
|
-
post_id: String(data.post_id ?? data.id ?? ""),
|
|
2087
|
-
content_id: stringOrNull(data.content_id) ?? void 0,
|
|
2088
|
-
cost_jpy: Math.trunc(Number(data.cost_jpy ?? 0)),
|
|
2089
|
-
cost_usd: Math.trunc(Number(data.cost_usd ?? 0)),
|
|
2090
|
-
impressions: Math.trunc(Number(data.impressions ?? 0)),
|
|
2091
|
-
replies: Math.trunc(Number(data.replies ?? 0)),
|
|
2092
|
-
status: stringOrNull(data.status) ?? void 0,
|
|
2093
|
-
created_at: stringOrNull(data.created_at) ?? void 0,
|
|
2094
|
-
raw: { ...data }
|
|
2095
|
-
};
|
|
2096
|
-
}
|
|
2097
1986
|
function parseWorksCategory(data) {
|
|
2098
1987
|
return {
|
|
2099
1988
|
key: String(data.key ?? ""),
|
|
@@ -2592,7 +2481,7 @@ function cloneJsonLike(value) {
|
|
|
2592
2481
|
}
|
|
2593
2482
|
return value;
|
|
2594
2483
|
}
|
|
2595
|
-
var DEFAULT_SIGLUME_API_BASE, RETRYABLE_STATUS_CODES, MINIMUM_JPY_OPERATION_PRICE_CURRENCIES, CursorPageResult, SiglumeClient;
|
|
2484
|
+
var DEFAULT_SIGLUME_API_BASE, RETRYABLE_STATUS_CODES, MINIMUM_JPY_OPERATION_PRICE_CURRENCIES, LISTING_SHORT_DESCRIPTION_MAX_LENGTH, LISTING_JOB_TO_BE_DONE_MAX_LENGTH, LISTING_DESCRIPTION_MAX_LENGTH, CursorPageResult, SiglumeClient;
|
|
2596
2485
|
var init_client = __esm({
|
|
2597
2486
|
"src/client.ts"() {
|
|
2598
2487
|
"use strict";
|
|
@@ -2605,6 +2494,9 @@ var init_client = __esm({
|
|
|
2605
2494
|
DEFAULT_SIGLUME_API_BASE = "https://siglume.com/v1";
|
|
2606
2495
|
RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
2607
2496
|
MINIMUM_JPY_OPERATION_PRICE_CURRENCIES = /* @__PURE__ */ new Set(["JPY", "JPYC"]);
|
|
2497
|
+
LISTING_SHORT_DESCRIPTION_MAX_LENGTH = 60;
|
|
2498
|
+
LISTING_JOB_TO_BE_DONE_MAX_LENGTH = 240;
|
|
2499
|
+
LISTING_DESCRIPTION_MAX_LENGTH = 1e3;
|
|
2608
2500
|
CursorPageResult = class {
|
|
2609
2501
|
items;
|
|
2610
2502
|
next_cursor;
|
|
@@ -2758,6 +2650,7 @@ var init_client = __esm({
|
|
|
2758
2650
|
if (payload.pricing_plan !== void 0) {
|
|
2759
2651
|
validatePricingPlanFloor(payload.pricing_plan, currency);
|
|
2760
2652
|
}
|
|
2653
|
+
validateListingTextLengths(payload);
|
|
2761
2654
|
const priceModel = String(payload.price_model ?? "free").trim().toLowerCase();
|
|
2762
2655
|
if ((priceModel === "usage_based" || priceModel === "per_action") && !pricingPlanHasItems(payload.pricing_plan)) {
|
|
2763
2656
|
throw new SiglumeClientError("AppManifest.pricing_plan.items is required for usage_based/per_action pricing.");
|
|
@@ -3900,115 +3793,6 @@ var init_client = __esm({
|
|
|
3900
3793
|
);
|
|
3901
3794
|
return Array.isArray(data.result) ? data.result.filter((item) => isRecord(item)).map((item) => parseInstalledToolReceiptStep(item)) : [];
|
|
3902
3795
|
}
|
|
3903
|
-
async get_partner_dashboard(options = {}) {
|
|
3904
|
-
const execution = await this.execute_owner_operation(
|
|
3905
|
-
await this.resolveOwnerOperationAgentId(options.agent_id),
|
|
3906
|
-
"partner.dashboard.get",
|
|
3907
|
-
{},
|
|
3908
|
-
{ lang: options.lang }
|
|
3909
|
-
);
|
|
3910
|
-
return parsePartnerDashboard(execution.result);
|
|
3911
|
-
}
|
|
3912
|
-
async get_partner_usage(options = {}) {
|
|
3913
|
-
const execution = await this.execute_owner_operation(
|
|
3914
|
-
await this.resolveOwnerOperationAgentId(options.agent_id),
|
|
3915
|
-
"partner.usage.get",
|
|
3916
|
-
{},
|
|
3917
|
-
{ lang: options.lang }
|
|
3918
|
-
);
|
|
3919
|
-
return parsePartnerUsage(execution.result);
|
|
3920
|
-
}
|
|
3921
|
-
async list_partner_api_keys(options = {}) {
|
|
3922
|
-
const execution = await this.execute_owner_operation(
|
|
3923
|
-
await this.resolveOwnerOperationAgentId(options.agent_id),
|
|
3924
|
-
"partner.keys.list",
|
|
3925
|
-
{},
|
|
3926
|
-
{ lang: options.lang }
|
|
3927
|
-
);
|
|
3928
|
-
return Array.isArray(execution.result.keys) ? execution.result.keys.filter((item) => isRecord(item)).map((item) => parsePartnerApiKey(item)) : [];
|
|
3929
|
-
}
|
|
3930
|
-
async create_partner_api_key(options = {}) {
|
|
3931
|
-
const payload = {};
|
|
3932
|
-
if (options.name !== void 0) {
|
|
3933
|
-
const normalizedName = String(options.name).trim();
|
|
3934
|
-
if (!normalizedName) {
|
|
3935
|
-
throw new SiglumeClientError("name cannot be empty.");
|
|
3936
|
-
}
|
|
3937
|
-
payload.name = normalizedName;
|
|
3938
|
-
}
|
|
3939
|
-
if (options.allowed_source_types !== void 0) {
|
|
3940
|
-
if (!Array.isArray(options.allowed_source_types)) {
|
|
3941
|
-
throw new SiglumeClientError("allowed_source_types must be a list of strings.");
|
|
3942
|
-
}
|
|
3943
|
-
payload.allowed_source_types = options.allowed_source_types.flatMap((item) => {
|
|
3944
|
-
if (typeof item !== "string") {
|
|
3945
|
-
throw new SiglumeClientError("allowed_source_types must contain only strings.");
|
|
3946
|
-
}
|
|
3947
|
-
const normalizedItem = item.trim();
|
|
3948
|
-
return normalizedItem ? [normalizedItem] : [];
|
|
3949
|
-
});
|
|
3950
|
-
}
|
|
3951
|
-
const execution = await this.execute_owner_operation(
|
|
3952
|
-
await this.resolveOwnerOperationAgentId(options.agent_id),
|
|
3953
|
-
"partner.keys.create",
|
|
3954
|
-
payload,
|
|
3955
|
-
{ lang: options.lang }
|
|
3956
|
-
);
|
|
3957
|
-
return parsePartnerApiKeyHandle(execution.result);
|
|
3958
|
-
}
|
|
3959
|
-
async get_ads_billing(options = {}) {
|
|
3960
|
-
const payload = {};
|
|
3961
|
-
if (options.rail !== void 0 && String(options.rail).trim()) {
|
|
3962
|
-
payload.rail = String(options.rail).trim().toLowerCase();
|
|
3963
|
-
}
|
|
3964
|
-
const execution = await this.execute_owner_operation(
|
|
3965
|
-
await this.resolveOwnerOperationAgentId(options.agent_id),
|
|
3966
|
-
"ads.billing.get",
|
|
3967
|
-
payload,
|
|
3968
|
-
{ lang: options.lang }
|
|
3969
|
-
);
|
|
3970
|
-
return parseAdsBilling(execution.result);
|
|
3971
|
-
}
|
|
3972
|
-
async settle_ads_billing(options = {}) {
|
|
3973
|
-
const execution = await this.execute_owner_operation(
|
|
3974
|
-
await this.resolveOwnerOperationAgentId(options.agent_id),
|
|
3975
|
-
"ads.billing.settle",
|
|
3976
|
-
{},
|
|
3977
|
-
{ lang: options.lang }
|
|
3978
|
-
);
|
|
3979
|
-
return parseAdsBillingSettlement(execution.result);
|
|
3980
|
-
}
|
|
3981
|
-
async get_ads_profile(options = {}) {
|
|
3982
|
-
const execution = await this.execute_owner_operation(
|
|
3983
|
-
await this.resolveOwnerOperationAgentId(options.agent_id),
|
|
3984
|
-
"ads.profile.get",
|
|
3985
|
-
{},
|
|
3986
|
-
{ lang: options.lang }
|
|
3987
|
-
);
|
|
3988
|
-
return parseAdsProfile(execution.result);
|
|
3989
|
-
}
|
|
3990
|
-
async list_ads_campaigns(options = {}) {
|
|
3991
|
-
const execution = await this.execute_owner_operation(
|
|
3992
|
-
await this.resolveOwnerOperationAgentId(options.agent_id),
|
|
3993
|
-
"ads.campaigns.list",
|
|
3994
|
-
{},
|
|
3995
|
-
{ lang: options.lang }
|
|
3996
|
-
);
|
|
3997
|
-
return Array.isArray(execution.result.campaigns) ? execution.result.campaigns.filter((item) => isRecord(item)).map((item) => parseAdsCampaign(item)) : [];
|
|
3998
|
-
}
|
|
3999
|
-
async list_ads_campaign_posts(campaign_id, options = {}) {
|
|
4000
|
-
const normalizedCampaignId = String(campaign_id ?? "").trim();
|
|
4001
|
-
if (!normalizedCampaignId) {
|
|
4002
|
-
throw new SiglumeClientError("campaign_id is required.");
|
|
4003
|
-
}
|
|
4004
|
-
const execution = await this.execute_owner_operation(
|
|
4005
|
-
await this.resolveOwnerOperationAgentId(options.agent_id),
|
|
4006
|
-
"ads.campaign_posts.list",
|
|
4007
|
-
{ campaign_id: normalizedCampaignId },
|
|
4008
|
-
{ lang: options.lang }
|
|
4009
|
-
);
|
|
4010
|
-
return Array.isArray(execution.result.posts) ? execution.result.posts.filter((item) => isRecord(item)).map((item) => parseAdsCampaignPost(item)) : [];
|
|
4011
|
-
}
|
|
4012
3796
|
// `market.proposals.*` currently rides on the public owner-operation execute
|
|
4013
3797
|
// route. Read helpers return typed proposal records; guarded mutations return
|
|
4014
3798
|
// the approval envelope without treating it as an error.
|
|
@@ -5938,12 +5722,15 @@ function validate_tool_manual(manualInput) {
|
|
|
5938
5722
|
pushError("INVALID_TOOL_NAME", "tool_name must be alphanumeric + underscore, 3-64 chars", "tool_name");
|
|
5939
5723
|
}
|
|
5940
5724
|
for (const [fieldName, minLength, maxLength] of [
|
|
5941
|
-
["job_to_be_done", 10,
|
|
5725
|
+
["job_to_be_done", 10, 240],
|
|
5942
5726
|
["summary_for_model", 10, 300]
|
|
5943
5727
|
]) {
|
|
5944
5728
|
const value = manual[fieldName];
|
|
5945
|
-
if (typeof value === "string"
|
|
5946
|
-
|
|
5729
|
+
if (typeof value === "string") {
|
|
5730
|
+
const length = Array.from(value).length;
|
|
5731
|
+
if (length < minLength || length > maxLength) {
|
|
5732
|
+
pushError("INVALID_TYPE", `${fieldName} must be ${minLength}-${maxLength} characters`, fieldName);
|
|
5733
|
+
}
|
|
5947
5734
|
}
|
|
5948
5735
|
}
|
|
5949
5736
|
const triggerConditions = manual.trigger_conditions;
|
|
@@ -7131,8 +6918,12 @@ function buildRuntimeValidationTemplate(toolManual) {
|
|
|
7131
6918
|
healthcheck_url: "https://api.example.com/health",
|
|
7132
6919
|
invoke_url: "https://api.example.com/invoke",
|
|
7133
6920
|
invoke_method: "POST",
|
|
7134
|
-
|
|
7135
|
-
|
|
6921
|
+
// Shared secret Siglume attaches when it calls invoke_url at both
|
|
6922
|
+
// registration validation and production runtime. Use a strong random
|
|
6923
|
+
// value, keep it in the Git-ignored runtime_validation.json, and rotate it
|
|
6924
|
+
// if it leaks. (legacy aliases: test_auth_header_name/value)
|
|
6925
|
+
runtime_auth_header_name: "X-Siglume-Auth",
|
|
6926
|
+
runtime_auth_header_value: "replace-with-strong-random-runtime-auth-secret",
|
|
7136
6927
|
request_payload: requestPayload,
|
|
7137
6928
|
expected_response_fields: expectedFields.length > 0 ? expectedFields : ["summary"],
|
|
7138
6929
|
timeout_seconds: 10
|
|
@@ -7437,8 +7228,6 @@ function runtimePlaceholderIssues(runtimeValidation) {
|
|
|
7437
7228
|
"public_base_url",
|
|
7438
7229
|
"healthcheck_url",
|
|
7439
7230
|
"invoke_url",
|
|
7440
|
-
"test_auth_header_name",
|
|
7441
|
-
"test_auth_header_value",
|
|
7442
7231
|
"expected_response_fields"
|
|
7443
7232
|
]) {
|
|
7444
7233
|
if (!runtimeValidation[fieldName]) {
|
|
@@ -7451,9 +7240,19 @@ function runtimePlaceholderIssues(runtimeValidation) {
|
|
|
7451
7240
|
issues.push(`runtime_validation.${fieldName} must be replaced with your public production URL`);
|
|
7452
7241
|
}
|
|
7453
7242
|
}
|
|
7454
|
-
const
|
|
7243
|
+
const authName = String(
|
|
7244
|
+
runtimeValidation.runtime_auth_header_name || runtimeValidation.test_auth_header_name || ""
|
|
7245
|
+
).trim();
|
|
7246
|
+
if (!authName) {
|
|
7247
|
+
issues.push("runtime_validation.runtime_auth_header_name is required");
|
|
7248
|
+
}
|
|
7249
|
+
const authValue = String(
|
|
7250
|
+
runtimeValidation.runtime_auth_header_value || runtimeValidation.test_auth_header_value || ""
|
|
7251
|
+
).trim();
|
|
7455
7252
|
if (!authValue || authValue.startsWith("replace-with-")) {
|
|
7456
|
-
issues.push(
|
|
7253
|
+
issues.push(
|
|
7254
|
+
"runtime_validation.runtime_auth_header_value must be a strong, dedicated runtime auth secret, not a placeholder"
|
|
7255
|
+
);
|
|
7457
7256
|
}
|
|
7458
7257
|
const requestPayload = runtimeValidation.request_payload ?? runtimeValidation.test_request_body ?? runtimeValidation.runtime_sample ?? runtimeValidation.sample_request_payload ?? runtimeValidation.runtime_sample_request;
|
|
7459
7258
|
if (!isRecord(requestPayload)) {
|
|
@@ -7468,7 +7267,7 @@ function runtimePlaceholderIssues(runtimeValidation) {
|
|
|
7468
7267
|
function ensureRuntimeValidationReady(project) {
|
|
7469
7268
|
if (!project.runtime_validation) {
|
|
7470
7269
|
throw new SiglumeProjectError(
|
|
7471
|
-
"runtime_validation.json is required for `siglume register`. Create it with public_base_url, healthcheck_url, invoke_url,
|
|
7270
|
+
"runtime_validation.json is required for `siglume register`. Create it with public_base_url, healthcheck_url, invoke_url, runtime auth header (runtime_auth_header_name/value), request_payload, and expected_response_fields."
|
|
7472
7271
|
);
|
|
7473
7272
|
}
|
|
7474
7273
|
const issues = runtimePlaceholderIssues(project.runtime_validation);
|
|
@@ -8157,19 +7956,19 @@ function operationReadmeTemplate(operation, manifest, warning) {
|
|
|
8157
7956
|
"- `stubs.ts`: mock fallback used when `SIGLUME_API_KEY` is not set",
|
|
8158
7957
|
"- `manifest.json`: reviewable manifest snapshot",
|
|
8159
7958
|
"- `tool_manual.json`: machine-generated ToolManual scaffold",
|
|
8160
|
-
"- `runtime_validation.json`: local public endpoint
|
|
7959
|
+
"- `runtime_validation.json`: local public endpoint + runtime auth header checks used by auto-register",
|
|
8161
7960
|
"- `docs/api-usage.md`: publishable API usage guide template for `docs_url`",
|
|
8162
|
-
"- `.gitignore`: keeps runtime
|
|
7961
|
+
"- `.gitignore`: keeps the runtime auth secret out of Git",
|
|
8163
7962
|
"- `tests/test_adapter.ts`: smoke test for `AppTestHarness`",
|
|
8164
7963
|
"",
|
|
8165
7964
|
"Before registering, replace all generated placeholders:",
|
|
8166
7965
|
"- In `adapter.ts` and `manifest.json`, replace `docs_url` with a dedicated public API usage guide, not a homepage.",
|
|
8167
7966
|
"- Replace `support_contact` with a real support email address or public support URL.",
|
|
8168
7967
|
"- Optional `seller_homepage_url` is the seller's official site and can stay blank.",
|
|
8169
|
-
"- In the local `runtime_validation.json`, replace the public URL and
|
|
7968
|
+
"- In the local `runtime_validation.json`, replace the public URL and runtime auth header placeholders (runtime_auth_header_name/value).",
|
|
8170
7969
|
"- If the API uses external OAuth, implement that flow in your API runtime and keep user tokens outside Siglume.",
|
|
8171
|
-
"- Do not commit real
|
|
8172
|
-
"- Because `runtime_validation.json` is ignored, GitHub samples do not commit
|
|
7970
|
+
"- Do not commit the real runtime auth secret or external-provider secrets; the generated `.gitignore` excludes local secret files.",
|
|
7971
|
+
"- Because `runtime_validation.json` is ignored, GitHub samples do not commit runtime auth secret values.",
|
|
8173
7972
|
"",
|
|
8174
7973
|
"## Commands",
|
|
8175
7974
|
"",
|
|
@@ -8238,7 +8037,7 @@ function apiUsageDocsTemplate(manifest) {
|
|
|
8238
8037
|
}
|
|
8239
8038
|
function generatedGitignore() {
|
|
8240
8039
|
return [
|
|
8241
|
-
"# Local secrets
|
|
8040
|
+
"# Local secrets (incl. the runtime auth shared secret) and runtime checks.",
|
|
8242
8041
|
".env",
|
|
8243
8042
|
".env.*",
|
|
8244
8043
|
"!.env.example",
|
|
@@ -8722,16 +8521,16 @@ function readmeTemplate(template) {
|
|
|
8722
8521
|
"- `tool_manual.json`: editable ToolManual draft for validation and registration",
|
|
8723
8522
|
"- `runtime_validation.json`: local live API smoke-test contract used during registration",
|
|
8724
8523
|
"- `docs/api-usage.md`: publish this page and use its public URL as `docs_url`",
|
|
8725
|
-
"- `.gitignore`: keeps runtime
|
|
8524
|
+
"- `.gitignore`: keeps the runtime auth secret out of Git",
|
|
8726
8525
|
"",
|
|
8727
8526
|
"Before registering, replace all generated placeholders:",
|
|
8728
8527
|
"- In `adapter.ts` and `manifest.json`, replace `docs_url` with a dedicated public API usage guide, not a homepage.",
|
|
8729
8528
|
"- Replace `support_contact` with a real support email address or public support URL.",
|
|
8730
8529
|
"- Optional `seller_homepage_url` is the seller's official site and can stay blank.",
|
|
8731
|
-
"- In the local `runtime_validation.json`, replace the public URL and
|
|
8530
|
+
"- In the local `runtime_validation.json`, replace the public URL and runtime auth header placeholders (runtime_auth_header_name/value).",
|
|
8732
8531
|
"- If the API uses external OAuth, implement that flow in your API runtime and keep user tokens outside Siglume.",
|
|
8733
|
-
"- Do not commit real
|
|
8734
|
-
"- Because `runtime_validation.json` is ignored, GitHub samples do not commit
|
|
8532
|
+
"- Do not commit the real runtime auth secret or external-provider secrets; the generated `.gitignore` excludes local secret files.",
|
|
8533
|
+
"- Because `runtime_validation.json` is ignored, GitHub samples do not commit runtime auth secret values.",
|
|
8735
8534
|
"",
|
|
8736
8535
|
"Suggested workflow:",
|
|
8737
8536
|
"",
|