@siglume/api-sdk 1.2.1 → 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 +24 -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/dist/bin/siglume.js
CHANGED
|
@@ -333,7 +333,12 @@ var init_webhooks = __esm({
|
|
|
333
333
|
"capability.published",
|
|
334
334
|
"capability.delisted",
|
|
335
335
|
"execution.completed",
|
|
336
|
-
"execution.failed"
|
|
336
|
+
"execution.failed",
|
|
337
|
+
"reward_payout.created",
|
|
338
|
+
"reward_payout.provider_pending",
|
|
339
|
+
"reward_paid",
|
|
340
|
+
"reward_payout.failed",
|
|
341
|
+
"reward_payout.cancelled"
|
|
337
342
|
];
|
|
338
343
|
WEBHOOK_EVENT_SET = new Set(WEBHOOK_EVENT_TYPES);
|
|
339
344
|
}
|
|
@@ -1383,6 +1388,23 @@ function validatePricingPlanFloor(plan, defaultCurrency) {
|
|
|
1383
1388
|
function pricingPlanHasItems(plan) {
|
|
1384
1389
|
return isRecord(plan) && Array.isArray(plan.items) && plan.items.length > 0;
|
|
1385
1390
|
}
|
|
1391
|
+
function validateListingTextLengths(payload) {
|
|
1392
|
+
const limits = {
|
|
1393
|
+
short_description: LISTING_SHORT_DESCRIPTION_MAX_LENGTH,
|
|
1394
|
+
job_to_be_done: LISTING_JOB_TO_BE_DONE_MAX_LENGTH,
|
|
1395
|
+
description: LISTING_DESCRIPTION_MAX_LENGTH
|
|
1396
|
+
};
|
|
1397
|
+
for (const [fieldName, maxLength] of Object.entries(limits)) {
|
|
1398
|
+
const value = payload[fieldName];
|
|
1399
|
+
if (value === void 0 || value === null) continue;
|
|
1400
|
+
if (typeof value !== "string") {
|
|
1401
|
+
throw new SiglumeClientError(`AppManifest.${fieldName} must be a string when provided.`);
|
|
1402
|
+
}
|
|
1403
|
+
if (Array.from(value).length > maxLength) {
|
|
1404
|
+
throw new SiglumeClientError(`AppManifest.${fieldName} must be at most ${maxLength} characters.`);
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1386
1408
|
function buildToolManualQualityReport(payload) {
|
|
1387
1409
|
const qualityBlock = isRecord(payload.quality) ? payload.quality : payload;
|
|
1388
1410
|
const issues = [];
|
|
@@ -1940,139 +1962,6 @@ function parseInstalledToolReceiptStep(data) {
|
|
|
1940
1962
|
raw: { ...data }
|
|
1941
1963
|
};
|
|
1942
1964
|
}
|
|
1943
|
-
function toRecordList(value) {
|
|
1944
|
-
return Array.isArray(value) ? value.filter((item) => isRecord(item)).map((item) => ({ ...item })) : [];
|
|
1945
|
-
}
|
|
1946
|
-
function parsePartnerDashboard(data) {
|
|
1947
|
-
return {
|
|
1948
|
-
partner_id: String(data.partner_id ?? data.user_id ?? ""),
|
|
1949
|
-
company_name: stringOrNull(data.company_name) ?? void 0,
|
|
1950
|
-
plan: stringOrNull(data.plan) ?? void 0,
|
|
1951
|
-
plan_label: stringOrNull(data.plan_label) ?? void 0,
|
|
1952
|
-
month_bytes_used: Math.trunc(Number(data.month_bytes_used ?? 0)),
|
|
1953
|
-
month_bytes_limit: Math.trunc(Number(data.month_bytes_limit ?? 0)),
|
|
1954
|
-
month_usage_pct: Number(data.month_usage_pct ?? 0),
|
|
1955
|
-
total_source_items: Math.trunc(Number(data.total_source_items ?? 0)),
|
|
1956
|
-
has_billing: Boolean(data.has_billing ?? false),
|
|
1957
|
-
has_subscription: Boolean(data.has_subscription ?? false),
|
|
1958
|
-
raw: { ...data }
|
|
1959
|
-
};
|
|
1960
|
-
}
|
|
1961
|
-
function parsePartnerUsage(data) {
|
|
1962
|
-
return {
|
|
1963
|
-
plan: stringOrNull(data.plan) ?? void 0,
|
|
1964
|
-
month_bytes_used: Math.trunc(Number(data.month_bytes_used ?? 0)),
|
|
1965
|
-
month_bytes_limit: Math.trunc(Number(data.month_bytes_limit ?? 0)),
|
|
1966
|
-
month_bytes_remaining: Math.trunc(Number(data.month_bytes_remaining ?? 0)),
|
|
1967
|
-
month_usage_pct: Number(data.month_usage_pct ?? 0),
|
|
1968
|
-
raw: { ...data }
|
|
1969
|
-
};
|
|
1970
|
-
}
|
|
1971
|
-
function parsePartnerApiKey(data) {
|
|
1972
|
-
return {
|
|
1973
|
-
credential_id: String(data.credential_id ?? data.id ?? ""),
|
|
1974
|
-
name: stringOrNull(data.name) ?? void 0,
|
|
1975
|
-
key_id: stringOrNull(data.key_id) ?? void 0,
|
|
1976
|
-
allowed_source_types: Array.isArray(data.allowed_source_types) ? data.allowed_source_types.filter((item) => typeof item === "string") : [],
|
|
1977
|
-
last_used_at: stringOrNull(data.last_used_at) ?? void 0,
|
|
1978
|
-
created_at: stringOrNull(data.created_at) ?? void 0,
|
|
1979
|
-
revoked: Boolean(data.revoked ?? false),
|
|
1980
|
-
raw: { ...data }
|
|
1981
|
-
};
|
|
1982
|
-
}
|
|
1983
|
-
function parsePartnerApiKeyHandle(data) {
|
|
1984
|
-
const raw = Object.fromEntries(
|
|
1985
|
-
Object.entries(data).filter(([key]) => key !== "ingest_key" && key !== "full_key")
|
|
1986
|
-
);
|
|
1987
|
-
return {
|
|
1988
|
-
credential_id: String(raw.credential_id ?? raw.id ?? ""),
|
|
1989
|
-
name: stringOrNull(raw.name) ?? void 0,
|
|
1990
|
-
key_id: stringOrNull(raw.key_id) ?? void 0,
|
|
1991
|
-
allowed_source_types: Array.isArray(raw.allowed_source_types) ? raw.allowed_source_types.filter((item) => typeof item === "string") : [],
|
|
1992
|
-
masked_key_hint: stringOrNull(raw.masked_key_hint) ?? void 0,
|
|
1993
|
-
raw
|
|
1994
|
-
};
|
|
1995
|
-
}
|
|
1996
|
-
function parseAdsBilling(data) {
|
|
1997
|
-
return {
|
|
1998
|
-
currency: stringOrNull(data.currency) ?? void 0,
|
|
1999
|
-
billing_mode: stringOrNull(data.billing_mode) ?? void 0,
|
|
2000
|
-
month_spend_jpy: Math.trunc(Number(data.month_spend_jpy ?? 0)),
|
|
2001
|
-
month_spend_usd: Math.trunc(Number(data.month_spend_usd ?? 0)),
|
|
2002
|
-
all_time_spend_jpy: Math.trunc(Number(data.all_time_spend_jpy ?? 0)),
|
|
2003
|
-
all_time_spend_usd: Math.trunc(Number(data.all_time_spend_usd ?? 0)),
|
|
2004
|
-
total_impressions: Math.trunc(Number(data.total_impressions ?? 0)),
|
|
2005
|
-
total_replies: Math.trunc(Number(data.total_replies ?? 0)),
|
|
2006
|
-
has_billing: Boolean(data.has_billing ?? false),
|
|
2007
|
-
has_subscription: Boolean(data.has_subscription ?? false),
|
|
2008
|
-
invoices: toRecordList(data.invoices),
|
|
2009
|
-
wallet: isRecord(data.wallet) ? { ...data.wallet } : null,
|
|
2010
|
-
balances: toRecordList(data.balances),
|
|
2011
|
-
supported_tokens: toRecordList(data.supported_tokens),
|
|
2012
|
-
funding_instructions: isRecord(data.funding_instructions) ? { ...data.funding_instructions } : null,
|
|
2013
|
-
mandate: isRecord(data.mandate) ? parsePlanWeb3Mandate(data.mandate) : null,
|
|
2014
|
-
raw: { ...data }
|
|
2015
|
-
};
|
|
2016
|
-
}
|
|
2017
|
-
function parseAdsBillingSettlement(data) {
|
|
2018
|
-
return {
|
|
2019
|
-
status: stringOrNull(data.status) ?? void 0,
|
|
2020
|
-
message: stringOrNull(data.message ?? data.detail) ?? void 0,
|
|
2021
|
-
settles_automatically: typeof data.settles_automatically === "boolean" ? data.settles_automatically : typeof data.auto_settles === "boolean" ? data.auto_settles : void 0,
|
|
2022
|
-
cycle_key: stringOrNull(data.cycle_key) ?? void 0,
|
|
2023
|
-
settled_at: stringOrNull(data.settled_at) ?? void 0,
|
|
2024
|
-
raw: { ...data }
|
|
2025
|
-
};
|
|
2026
|
-
}
|
|
2027
|
-
function parseAdsProfile(data) {
|
|
2028
|
-
return {
|
|
2029
|
-
has_profile: Boolean(data.has_profile ?? false),
|
|
2030
|
-
company_name: stringOrNull(data.company_name) ?? void 0,
|
|
2031
|
-
ad_currency: stringOrNull(data.ad_currency) ?? void 0,
|
|
2032
|
-
has_billing: Boolean(data.has_billing ?? false),
|
|
2033
|
-
raw: { ...data }
|
|
2034
|
-
};
|
|
2035
|
-
}
|
|
2036
|
-
function parseAdsCampaign(data) {
|
|
2037
|
-
return {
|
|
2038
|
-
campaign_id: String(data.campaign_id ?? data.id ?? ""),
|
|
2039
|
-
name: stringOrNull(data.name) ?? void 0,
|
|
2040
|
-
target_url: stringOrNull(data.target_url) ?? void 0,
|
|
2041
|
-
content_brief: stringOrNull(data.content_brief) ?? void 0,
|
|
2042
|
-
target_topics: Array.isArray(data.target_topics) ? data.target_topics.filter((item) => typeof item === "string") : [],
|
|
2043
|
-
posting_interval_minutes: Math.trunc(Number(data.posting_interval_minutes ?? 360)),
|
|
2044
|
-
max_posts_per_day: Math.trunc(Number(data.max_posts_per_day ?? 4)),
|
|
2045
|
-
currency: stringOrNull(data.currency) ?? void 0,
|
|
2046
|
-
monthly_budget_jpy: Math.trunc(Number(data.monthly_budget_jpy ?? 0)),
|
|
2047
|
-
cpm_jpy: Math.trunc(Number(data.cpm_jpy ?? 0)),
|
|
2048
|
-
cpr_jpy: Math.trunc(Number(data.cpr_jpy ?? 0)),
|
|
2049
|
-
monthly_budget_usd: Math.trunc(Number(data.monthly_budget_usd ?? 0)),
|
|
2050
|
-
cpm_usd: Math.trunc(Number(data.cpm_usd ?? 0)),
|
|
2051
|
-
cpr_usd: Math.trunc(Number(data.cpr_usd ?? 0)),
|
|
2052
|
-
status: String(data.status ?? "active").trim().toLowerCase() || "active",
|
|
2053
|
-
month_spend_jpy: Math.trunc(Number(data.month_spend_jpy ?? 0)),
|
|
2054
|
-
month_spend_usd: Math.trunc(Number(data.month_spend_usd ?? 0)),
|
|
2055
|
-
total_posts: Math.trunc(Number(data.total_posts ?? 0)),
|
|
2056
|
-
total_impressions: Math.trunc(Number(data.total_impressions ?? 0)),
|
|
2057
|
-
total_replies: Math.trunc(Number(data.total_replies ?? 0)),
|
|
2058
|
-
next_post_at: stringOrNull(data.next_post_at) ?? void 0,
|
|
2059
|
-
created_at: stringOrNull(data.created_at) ?? void 0,
|
|
2060
|
-
raw: { ...data }
|
|
2061
|
-
};
|
|
2062
|
-
}
|
|
2063
|
-
function parseAdsCampaignPost(data) {
|
|
2064
|
-
return {
|
|
2065
|
-
post_id: String(data.post_id ?? data.id ?? ""),
|
|
2066
|
-
content_id: stringOrNull(data.content_id) ?? void 0,
|
|
2067
|
-
cost_jpy: Math.trunc(Number(data.cost_jpy ?? 0)),
|
|
2068
|
-
cost_usd: Math.trunc(Number(data.cost_usd ?? 0)),
|
|
2069
|
-
impressions: Math.trunc(Number(data.impressions ?? 0)),
|
|
2070
|
-
replies: Math.trunc(Number(data.replies ?? 0)),
|
|
2071
|
-
status: stringOrNull(data.status) ?? void 0,
|
|
2072
|
-
created_at: stringOrNull(data.created_at) ?? void 0,
|
|
2073
|
-
raw: { ...data }
|
|
2074
|
-
};
|
|
2075
|
-
}
|
|
2076
1965
|
function parseWorksCategory(data) {
|
|
2077
1966
|
return {
|
|
2078
1967
|
key: String(data.key ?? ""),
|
|
@@ -2571,7 +2460,7 @@ function cloneJsonLike(value) {
|
|
|
2571
2460
|
}
|
|
2572
2461
|
return value;
|
|
2573
2462
|
}
|
|
2574
|
-
var DEFAULT_SIGLUME_API_BASE, RETRYABLE_STATUS_CODES, MINIMUM_JPY_OPERATION_PRICE_CURRENCIES, CursorPageResult, SiglumeClient;
|
|
2463
|
+
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;
|
|
2575
2464
|
var init_client = __esm({
|
|
2576
2465
|
"src/client.ts"() {
|
|
2577
2466
|
"use strict";
|
|
@@ -2584,6 +2473,9 @@ var init_client = __esm({
|
|
|
2584
2473
|
DEFAULT_SIGLUME_API_BASE = "https://siglume.com/v1";
|
|
2585
2474
|
RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
2586
2475
|
MINIMUM_JPY_OPERATION_PRICE_CURRENCIES = /* @__PURE__ */ new Set(["JPY", "JPYC"]);
|
|
2476
|
+
LISTING_SHORT_DESCRIPTION_MAX_LENGTH = 60;
|
|
2477
|
+
LISTING_JOB_TO_BE_DONE_MAX_LENGTH = 240;
|
|
2478
|
+
LISTING_DESCRIPTION_MAX_LENGTH = 1e3;
|
|
2587
2479
|
CursorPageResult = class {
|
|
2588
2480
|
items;
|
|
2589
2481
|
next_cursor;
|
|
@@ -2737,6 +2629,7 @@ var init_client = __esm({
|
|
|
2737
2629
|
if (payload.pricing_plan !== void 0) {
|
|
2738
2630
|
validatePricingPlanFloor(payload.pricing_plan, currency);
|
|
2739
2631
|
}
|
|
2632
|
+
validateListingTextLengths(payload);
|
|
2740
2633
|
const priceModel = String(payload.price_model ?? "free").trim().toLowerCase();
|
|
2741
2634
|
if ((priceModel === "usage_based" || priceModel === "per_action") && !pricingPlanHasItems(payload.pricing_plan)) {
|
|
2742
2635
|
throw new SiglumeClientError("AppManifest.pricing_plan.items is required for usage_based/per_action pricing.");
|
|
@@ -3879,115 +3772,6 @@ var init_client = __esm({
|
|
|
3879
3772
|
);
|
|
3880
3773
|
return Array.isArray(data.result) ? data.result.filter((item) => isRecord(item)).map((item) => parseInstalledToolReceiptStep(item)) : [];
|
|
3881
3774
|
}
|
|
3882
|
-
async get_partner_dashboard(options = {}) {
|
|
3883
|
-
const execution = await this.execute_owner_operation(
|
|
3884
|
-
await this.resolveOwnerOperationAgentId(options.agent_id),
|
|
3885
|
-
"partner.dashboard.get",
|
|
3886
|
-
{},
|
|
3887
|
-
{ lang: options.lang }
|
|
3888
|
-
);
|
|
3889
|
-
return parsePartnerDashboard(execution.result);
|
|
3890
|
-
}
|
|
3891
|
-
async get_partner_usage(options = {}) {
|
|
3892
|
-
const execution = await this.execute_owner_operation(
|
|
3893
|
-
await this.resolveOwnerOperationAgentId(options.agent_id),
|
|
3894
|
-
"partner.usage.get",
|
|
3895
|
-
{},
|
|
3896
|
-
{ lang: options.lang }
|
|
3897
|
-
);
|
|
3898
|
-
return parsePartnerUsage(execution.result);
|
|
3899
|
-
}
|
|
3900
|
-
async list_partner_api_keys(options = {}) {
|
|
3901
|
-
const execution = await this.execute_owner_operation(
|
|
3902
|
-
await this.resolveOwnerOperationAgentId(options.agent_id),
|
|
3903
|
-
"partner.keys.list",
|
|
3904
|
-
{},
|
|
3905
|
-
{ lang: options.lang }
|
|
3906
|
-
);
|
|
3907
|
-
return Array.isArray(execution.result.keys) ? execution.result.keys.filter((item) => isRecord(item)).map((item) => parsePartnerApiKey(item)) : [];
|
|
3908
|
-
}
|
|
3909
|
-
async create_partner_api_key(options = {}) {
|
|
3910
|
-
const payload = {};
|
|
3911
|
-
if (options.name !== void 0) {
|
|
3912
|
-
const normalizedName = String(options.name).trim();
|
|
3913
|
-
if (!normalizedName) {
|
|
3914
|
-
throw new SiglumeClientError("name cannot be empty.");
|
|
3915
|
-
}
|
|
3916
|
-
payload.name = normalizedName;
|
|
3917
|
-
}
|
|
3918
|
-
if (options.allowed_source_types !== void 0) {
|
|
3919
|
-
if (!Array.isArray(options.allowed_source_types)) {
|
|
3920
|
-
throw new SiglumeClientError("allowed_source_types must be a list of strings.");
|
|
3921
|
-
}
|
|
3922
|
-
payload.allowed_source_types = options.allowed_source_types.flatMap((item) => {
|
|
3923
|
-
if (typeof item !== "string") {
|
|
3924
|
-
throw new SiglumeClientError("allowed_source_types must contain only strings.");
|
|
3925
|
-
}
|
|
3926
|
-
const normalizedItem = item.trim();
|
|
3927
|
-
return normalizedItem ? [normalizedItem] : [];
|
|
3928
|
-
});
|
|
3929
|
-
}
|
|
3930
|
-
const execution = await this.execute_owner_operation(
|
|
3931
|
-
await this.resolveOwnerOperationAgentId(options.agent_id),
|
|
3932
|
-
"partner.keys.create",
|
|
3933
|
-
payload,
|
|
3934
|
-
{ lang: options.lang }
|
|
3935
|
-
);
|
|
3936
|
-
return parsePartnerApiKeyHandle(execution.result);
|
|
3937
|
-
}
|
|
3938
|
-
async get_ads_billing(options = {}) {
|
|
3939
|
-
const payload = {};
|
|
3940
|
-
if (options.rail !== void 0 && String(options.rail).trim()) {
|
|
3941
|
-
payload.rail = String(options.rail).trim().toLowerCase();
|
|
3942
|
-
}
|
|
3943
|
-
const execution = await this.execute_owner_operation(
|
|
3944
|
-
await this.resolveOwnerOperationAgentId(options.agent_id),
|
|
3945
|
-
"ads.billing.get",
|
|
3946
|
-
payload,
|
|
3947
|
-
{ lang: options.lang }
|
|
3948
|
-
);
|
|
3949
|
-
return parseAdsBilling(execution.result);
|
|
3950
|
-
}
|
|
3951
|
-
async settle_ads_billing(options = {}) {
|
|
3952
|
-
const execution = await this.execute_owner_operation(
|
|
3953
|
-
await this.resolveOwnerOperationAgentId(options.agent_id),
|
|
3954
|
-
"ads.billing.settle",
|
|
3955
|
-
{},
|
|
3956
|
-
{ lang: options.lang }
|
|
3957
|
-
);
|
|
3958
|
-
return parseAdsBillingSettlement(execution.result);
|
|
3959
|
-
}
|
|
3960
|
-
async get_ads_profile(options = {}) {
|
|
3961
|
-
const execution = await this.execute_owner_operation(
|
|
3962
|
-
await this.resolveOwnerOperationAgentId(options.agent_id),
|
|
3963
|
-
"ads.profile.get",
|
|
3964
|
-
{},
|
|
3965
|
-
{ lang: options.lang }
|
|
3966
|
-
);
|
|
3967
|
-
return parseAdsProfile(execution.result);
|
|
3968
|
-
}
|
|
3969
|
-
async list_ads_campaigns(options = {}) {
|
|
3970
|
-
const execution = await this.execute_owner_operation(
|
|
3971
|
-
await this.resolveOwnerOperationAgentId(options.agent_id),
|
|
3972
|
-
"ads.campaigns.list",
|
|
3973
|
-
{},
|
|
3974
|
-
{ lang: options.lang }
|
|
3975
|
-
);
|
|
3976
|
-
return Array.isArray(execution.result.campaigns) ? execution.result.campaigns.filter((item) => isRecord(item)).map((item) => parseAdsCampaign(item)) : [];
|
|
3977
|
-
}
|
|
3978
|
-
async list_ads_campaign_posts(campaign_id, options = {}) {
|
|
3979
|
-
const normalizedCampaignId = String(campaign_id ?? "").trim();
|
|
3980
|
-
if (!normalizedCampaignId) {
|
|
3981
|
-
throw new SiglumeClientError("campaign_id is required.");
|
|
3982
|
-
}
|
|
3983
|
-
const execution = await this.execute_owner_operation(
|
|
3984
|
-
await this.resolveOwnerOperationAgentId(options.agent_id),
|
|
3985
|
-
"ads.campaign_posts.list",
|
|
3986
|
-
{ campaign_id: normalizedCampaignId },
|
|
3987
|
-
{ lang: options.lang }
|
|
3988
|
-
);
|
|
3989
|
-
return Array.isArray(execution.result.posts) ? execution.result.posts.filter((item) => isRecord(item)).map((item) => parseAdsCampaignPost(item)) : [];
|
|
3990
|
-
}
|
|
3991
3775
|
// `market.proposals.*` currently rides on the public owner-operation execute
|
|
3992
3776
|
// route. Read helpers return typed proposal records; guarded mutations return
|
|
3993
3777
|
// the approval envelope without treating it as an error.
|
|
@@ -5917,12 +5701,15 @@ function validate_tool_manual(manualInput) {
|
|
|
5917
5701
|
pushError("INVALID_TOOL_NAME", "tool_name must be alphanumeric + underscore, 3-64 chars", "tool_name");
|
|
5918
5702
|
}
|
|
5919
5703
|
for (const [fieldName, minLength, maxLength] of [
|
|
5920
|
-
["job_to_be_done", 10,
|
|
5704
|
+
["job_to_be_done", 10, 240],
|
|
5921
5705
|
["summary_for_model", 10, 300]
|
|
5922
5706
|
]) {
|
|
5923
5707
|
const value = manual[fieldName];
|
|
5924
|
-
if (typeof value === "string"
|
|
5925
|
-
|
|
5708
|
+
if (typeof value === "string") {
|
|
5709
|
+
const length = Array.from(value).length;
|
|
5710
|
+
if (length < minLength || length > maxLength) {
|
|
5711
|
+
pushError("INVALID_TYPE", `${fieldName} must be ${minLength}-${maxLength} characters`, fieldName);
|
|
5712
|
+
}
|
|
5926
5713
|
}
|
|
5927
5714
|
}
|
|
5928
5715
|
const triggerConditions = manual.trigger_conditions;
|
|
@@ -7110,8 +6897,12 @@ function buildRuntimeValidationTemplate(toolManual) {
|
|
|
7110
6897
|
healthcheck_url: "https://api.example.com/health",
|
|
7111
6898
|
invoke_url: "https://api.example.com/invoke",
|
|
7112
6899
|
invoke_method: "POST",
|
|
7113
|
-
|
|
7114
|
-
|
|
6900
|
+
// Shared secret Siglume attaches when it calls invoke_url at both
|
|
6901
|
+
// registration validation and production runtime. Use a strong random
|
|
6902
|
+
// value, keep it in the Git-ignored runtime_validation.json, and rotate it
|
|
6903
|
+
// if it leaks. (legacy aliases: test_auth_header_name/value)
|
|
6904
|
+
runtime_auth_header_name: "X-Siglume-Auth",
|
|
6905
|
+
runtime_auth_header_value: "replace-with-strong-random-runtime-auth-secret",
|
|
7115
6906
|
request_payload: requestPayload,
|
|
7116
6907
|
expected_response_fields: expectedFields.length > 0 ? expectedFields : ["summary"],
|
|
7117
6908
|
timeout_seconds: 10
|
|
@@ -7416,8 +7207,6 @@ function runtimePlaceholderIssues(runtimeValidation) {
|
|
|
7416
7207
|
"public_base_url",
|
|
7417
7208
|
"healthcheck_url",
|
|
7418
7209
|
"invoke_url",
|
|
7419
|
-
"test_auth_header_name",
|
|
7420
|
-
"test_auth_header_value",
|
|
7421
7210
|
"expected_response_fields"
|
|
7422
7211
|
]) {
|
|
7423
7212
|
if (!runtimeValidation[fieldName]) {
|
|
@@ -7430,9 +7219,19 @@ function runtimePlaceholderIssues(runtimeValidation) {
|
|
|
7430
7219
|
issues.push(`runtime_validation.${fieldName} must be replaced with your public production URL`);
|
|
7431
7220
|
}
|
|
7432
7221
|
}
|
|
7433
|
-
const
|
|
7222
|
+
const authName = String(
|
|
7223
|
+
runtimeValidation.runtime_auth_header_name || runtimeValidation.test_auth_header_name || ""
|
|
7224
|
+
).trim();
|
|
7225
|
+
if (!authName) {
|
|
7226
|
+
issues.push("runtime_validation.runtime_auth_header_name is required");
|
|
7227
|
+
}
|
|
7228
|
+
const authValue = String(
|
|
7229
|
+
runtimeValidation.runtime_auth_header_value || runtimeValidation.test_auth_header_value || ""
|
|
7230
|
+
).trim();
|
|
7434
7231
|
if (!authValue || authValue.startsWith("replace-with-")) {
|
|
7435
|
-
issues.push(
|
|
7232
|
+
issues.push(
|
|
7233
|
+
"runtime_validation.runtime_auth_header_value must be a strong, dedicated runtime auth secret, not a placeholder"
|
|
7234
|
+
);
|
|
7436
7235
|
}
|
|
7437
7236
|
const requestPayload = runtimeValidation.request_payload ?? runtimeValidation.test_request_body ?? runtimeValidation.runtime_sample ?? runtimeValidation.sample_request_payload ?? runtimeValidation.runtime_sample_request;
|
|
7438
7237
|
if (!isRecord(requestPayload)) {
|
|
@@ -7447,7 +7246,7 @@ function runtimePlaceholderIssues(runtimeValidation) {
|
|
|
7447
7246
|
function ensureRuntimeValidationReady(project) {
|
|
7448
7247
|
if (!project.runtime_validation) {
|
|
7449
7248
|
throw new SiglumeProjectError(
|
|
7450
|
-
"runtime_validation.json is required for `siglume register`. Create it with public_base_url, healthcheck_url, invoke_url,
|
|
7249
|
+
"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."
|
|
7451
7250
|
);
|
|
7452
7251
|
}
|
|
7453
7252
|
const issues = runtimePlaceholderIssues(project.runtime_validation);
|
|
@@ -8136,19 +7935,19 @@ function operationReadmeTemplate(operation, manifest, warning) {
|
|
|
8136
7935
|
"- `stubs.ts`: mock fallback used when `SIGLUME_API_KEY` is not set",
|
|
8137
7936
|
"- `manifest.json`: reviewable manifest snapshot",
|
|
8138
7937
|
"- `tool_manual.json`: machine-generated ToolManual scaffold",
|
|
8139
|
-
"- `runtime_validation.json`: local public endpoint
|
|
7938
|
+
"- `runtime_validation.json`: local public endpoint + runtime auth header checks used by auto-register",
|
|
8140
7939
|
"- `docs/api-usage.md`: publishable API usage guide template for `docs_url`",
|
|
8141
|
-
"- `.gitignore`: keeps runtime
|
|
7940
|
+
"- `.gitignore`: keeps the runtime auth secret out of Git",
|
|
8142
7941
|
"- `tests/test_adapter.ts`: smoke test for `AppTestHarness`",
|
|
8143
7942
|
"",
|
|
8144
7943
|
"Before registering, replace all generated placeholders:",
|
|
8145
7944
|
"- In `adapter.ts` and `manifest.json`, replace `docs_url` with a dedicated public API usage guide, not a homepage.",
|
|
8146
7945
|
"- Replace `support_contact` with a real support email address or public support URL.",
|
|
8147
7946
|
"- Optional `seller_homepage_url` is the seller's official site and can stay blank.",
|
|
8148
|
-
"- In the local `runtime_validation.json`, replace the public URL and
|
|
7947
|
+
"- In the local `runtime_validation.json`, replace the public URL and runtime auth header placeholders (runtime_auth_header_name/value).",
|
|
8149
7948
|
"- If the API uses external OAuth, implement that flow in your API runtime and keep user tokens outside Siglume.",
|
|
8150
|
-
"- Do not commit real
|
|
8151
|
-
"- Because `runtime_validation.json` is ignored, GitHub samples do not commit
|
|
7949
|
+
"- Do not commit the real runtime auth secret or external-provider secrets; the generated `.gitignore` excludes local secret files.",
|
|
7950
|
+
"- Because `runtime_validation.json` is ignored, GitHub samples do not commit runtime auth secret values.",
|
|
8152
7951
|
"",
|
|
8153
7952
|
"## Commands",
|
|
8154
7953
|
"",
|
|
@@ -8217,7 +8016,7 @@ function apiUsageDocsTemplate(manifest) {
|
|
|
8217
8016
|
}
|
|
8218
8017
|
function generatedGitignore() {
|
|
8219
8018
|
return [
|
|
8220
|
-
"# Local secrets
|
|
8019
|
+
"# Local secrets (incl. the runtime auth shared secret) and runtime checks.",
|
|
8221
8020
|
".env",
|
|
8222
8021
|
".env.*",
|
|
8223
8022
|
"!.env.example",
|
|
@@ -8701,16 +8500,16 @@ function readmeTemplate(template) {
|
|
|
8701
8500
|
"- `tool_manual.json`: editable ToolManual draft for validation and registration",
|
|
8702
8501
|
"- `runtime_validation.json`: local live API smoke-test contract used during registration",
|
|
8703
8502
|
"- `docs/api-usage.md`: publish this page and use its public URL as `docs_url`",
|
|
8704
|
-
"- `.gitignore`: keeps runtime
|
|
8503
|
+
"- `.gitignore`: keeps the runtime auth secret out of Git",
|
|
8705
8504
|
"",
|
|
8706
8505
|
"Before registering, replace all generated placeholders:",
|
|
8707
8506
|
"- In `adapter.ts` and `manifest.json`, replace `docs_url` with a dedicated public API usage guide, not a homepage.",
|
|
8708
8507
|
"- Replace `support_contact` with a real support email address or public support URL.",
|
|
8709
8508
|
"- Optional `seller_homepage_url` is the seller's official site and can stay blank.",
|
|
8710
|
-
"- In the local `runtime_validation.json`, replace the public URL and
|
|
8509
|
+
"- In the local `runtime_validation.json`, replace the public URL and runtime auth header placeholders (runtime_auth_header_name/value).",
|
|
8711
8510
|
"- If the API uses external OAuth, implement that flow in your API runtime and keep user tokens outside Siglume.",
|
|
8712
|
-
"- Do not commit real
|
|
8713
|
-
"- Because `runtime_validation.json` is ignored, GitHub samples do not commit
|
|
8511
|
+
"- Do not commit the real runtime auth secret or external-provider secrets; the generated `.gitignore` excludes local secret files.",
|
|
8512
|
+
"- Because `runtime_validation.json` is ignored, GitHub samples do not commit runtime auth secret values.",
|
|
8714
8513
|
"",
|
|
8715
8514
|
"Suggested workflow:",
|
|
8716
8515
|
"",
|