@siglume/api-sdk 0.10.6 → 0.10.8

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/dist/cli/index.js CHANGED
@@ -1226,6 +1226,56 @@ var init_operations = __esm({
1226
1226
  });
1227
1227
 
1228
1228
  // src/client.ts
1229
+ function validateManifestPersistenceContract(payload) {
1230
+ const vertical = String(payload.store_vertical ?? "").trim().toLowerCase();
1231
+ const persistence = payload.persistence;
1232
+ if (persistence === void 0 || persistence === null) {
1233
+ return;
1234
+ }
1235
+ if (!isRecord(persistence)) {
1236
+ throw new SiglumeClientError("AppManifest.persistence must be an object.");
1237
+ }
1238
+ const mode = String(persistence.mode ?? (vertical === "game" ? "platform" : "none")).trim().toLowerCase();
1239
+ if (!["none", "local", "platform", "developer_server"].includes(mode)) {
1240
+ throw new SiglumeClientError(
1241
+ "AppManifest.persistence.mode must be one of: none, local, platform, developer_server."
1242
+ );
1243
+ }
1244
+ const schema = persistence.save_data_schema;
1245
+ if (vertical === "game" && mode !== "none" && schema === void 0) {
1246
+ throw new SiglumeClientError(
1247
+ "AppManifest.persistence.save_data_schema is required when store_vertical='game' and persistence.mode is not 'none'."
1248
+ );
1249
+ }
1250
+ if (schema !== void 0) {
1251
+ validateSaveDataSchema(schema, "AppManifest.persistence.save_data_schema");
1252
+ }
1253
+ }
1254
+ function validateSaveDataSchema(schema, fieldName) {
1255
+ if (!isRecord(schema)) {
1256
+ throw new SiglumeClientError(`${fieldName} must be a JSON Schema object.`);
1257
+ }
1258
+ const schemaSize = new TextEncoder().encode(JSON.stringify(schema)).length;
1259
+ if (schemaSize > 8192) {
1260
+ throw new SiglumeClientError(`${fieldName} must be at most 8192 bytes.`);
1261
+ }
1262
+ if (schema.type !== "object") {
1263
+ throw new SiglumeClientError(`${fieldName}.type must be 'object'.`);
1264
+ }
1265
+ const properties = schema.properties;
1266
+ if (!isRecord(properties) || Object.keys(properties).length === 0) {
1267
+ throw new SiglumeClientError(`${fieldName}.properties must be a non-empty object.`);
1268
+ }
1269
+ if (schema.required !== void 0) {
1270
+ if (!Array.isArray(schema.required) || !schema.required.every((item) => typeof item === "string")) {
1271
+ throw new SiglumeClientError(`${fieldName}.required must be an array of strings when provided.`);
1272
+ }
1273
+ const missing = schema.required.filter((item) => !(item in properties));
1274
+ if (missing.length > 0) {
1275
+ throw new SiglumeClientError(`${fieldName}.required references undefined properties: ${missing.join(", ")}.`);
1276
+ }
1277
+ }
1278
+ }
1229
1279
  function buildToolManualQualityReport(payload) {
1230
1280
  const qualityBlock = isRecord(payload.quality) ? payload.quality : payload;
1231
1281
  const issues = [];
@@ -1300,6 +1350,8 @@ function buildUrl(baseUrl, path, params) {
1300
1350
  return url.toString();
1301
1351
  }
1302
1352
  function parseListing(data) {
1353
+ const metadata = isRecord(data.metadata) ? data.metadata : {};
1354
+ const persistence = isRecord(data.persistence) ? data.persistence : isRecord(metadata.persistence) ? metadata.persistence : {};
1303
1355
  return {
1304
1356
  listing_id: String(data.listing_id ?? data.id ?? ""),
1305
1357
  capability_key: String(data.capability_key ?? ""),
@@ -1313,6 +1365,8 @@ function parseListing(data) {
1313
1365
  price_model: stringOrNull(data.price_model),
1314
1366
  price_value_minor: Number(data.price_value_minor ?? 0),
1315
1367
  currency: String(data.currency ?? "USD"),
1368
+ allow_free_trial: Boolean(data.allow_free_trial ?? false),
1369
+ free_trial_duration_days: Number(data.free_trial_duration_days ?? 30),
1316
1370
  short_description: stringOrNull(data.short_description),
1317
1371
  description: stringOrNull(data.description),
1318
1372
  docs_url: stringOrNull(data.docs_url),
@@ -1320,14 +1374,59 @@ function parseListing(data) {
1320
1374
  seller_display_name: stringOrNull(data.seller_display_name),
1321
1375
  seller_homepage_url: stringOrNull(data.seller_homepage_url),
1322
1376
  seller_social_url: stringOrNull(data.seller_social_url),
1377
+ publisher_type: stringOrNull(data.publisher_type),
1378
+ publisher_company_id: stringOrNull(data.publisher_company_id),
1379
+ company_id: stringOrNull(data.company_id),
1380
+ company_name: stringOrNull(data.company_name),
1381
+ company_publish_status: stringOrNull(data.company_publish_status),
1382
+ company_terms_version: stringOrNull(data.company_terms_version),
1323
1383
  review_status: stringOrNull(data.review_status),
1324
1384
  review_note: stringOrNull(data.review_note),
1325
1385
  submission_blockers: Array.isArray(data.submission_blockers) ? data.submission_blockers.filter((item) => typeof item === "string") : [],
1386
+ persistence: { ...persistence },
1326
1387
  created_at: stringOrNull(data.created_at),
1327
1388
  updated_at: stringOrNull(data.updated_at),
1328
1389
  raw: { ...data }
1329
1390
  };
1330
1391
  }
1392
+ function parseCompanyPublisher(data) {
1393
+ const wallets = Array.isArray(data.settlement_wallets) ? data.settlement_wallets.filter((item) => isRecord(item)) : [];
1394
+ return {
1395
+ company_id: String(data.company_id ?? data.id ?? ""),
1396
+ name: String(data.name ?? ""),
1397
+ status: String(data.status ?? ""),
1398
+ description: stringOrNull(data.description),
1399
+ is_founder: Boolean(data.is_founder ?? false),
1400
+ membership_role: stringOrNull(data.membership_role),
1401
+ membership_status: stringOrNull(data.membership_status),
1402
+ can_publish: Boolean(data.can_publish ?? true),
1403
+ can_approve: Boolean(data.can_approve ?? false),
1404
+ approval_required: Boolean(data.approval_required ?? false),
1405
+ paid_listing_allowed: Boolean(data.paid_listing_allowed ?? false),
1406
+ disabled_reasons: Array.isArray(data.disabled_reasons) ? data.disabled_reasons.filter((item) => typeof item === "string") : [],
1407
+ company_terms_version: stringOrNull(data.company_terms_version),
1408
+ active_listing_count: Number(data.active_listing_count ?? 0),
1409
+ pending_approval_count: Number(data.pending_approval_count ?? 0),
1410
+ settlement_wallet_ready: Boolean(data.settlement_wallet_ready ?? false),
1411
+ settlement_wallets: wallets.map((item) => ({ ...item })),
1412
+ raw: { ...data }
1413
+ };
1414
+ }
1415
+ function parseCapabilitySaveState(data) {
1416
+ return {
1417
+ capability_key: String(data.capability_key ?? ""),
1418
+ save_key: String(data.save_key ?? ""),
1419
+ schema_version: String(data.schema_version ?? "1"),
1420
+ revision: Number(data.revision ?? 0),
1421
+ payload: toRecord(data.payload),
1422
+ metadata: toRecord(data.metadata),
1423
+ checksum: stringOrNull(data.checksum),
1424
+ updated_at: stringOrNull(data.updated_at),
1425
+ created_at: stringOrNull(data.created_at),
1426
+ exists: Boolean(data.exists ?? false),
1427
+ raw: { ...data }
1428
+ };
1429
+ }
1331
1430
  function parseBundleMember(data) {
1332
1431
  return {
1333
1432
  capability_listing_id: String(data.capability_listing_id ?? ""),
@@ -2507,17 +2606,23 @@ var init_client = __esm({
2507
2606
  "support_contact",
2508
2607
  "seller_homepage_url",
2509
2608
  "seller_social_url",
2609
+ "publisher_type",
2610
+ "company_id",
2611
+ "publisher_company_id",
2510
2612
  "store_vertical",
2511
2613
  "jurisdiction",
2512
2614
  "price_model",
2513
2615
  "price_value_minor",
2514
2616
  "currency",
2617
+ "allow_free_trial",
2618
+ "free_trial_duration_days",
2515
2619
  "permission_class",
2516
2620
  "approval_mode",
2517
2621
  "dry_run_supported",
2518
2622
  "required_connected_accounts",
2519
2623
  "permission_scopes",
2520
- "compatibility_tags"
2624
+ "compatibility_tags",
2625
+ "persistence"
2521
2626
  ]) {
2522
2627
  const value = manifestPayload[fieldName];
2523
2628
  if (value !== void 0 && value !== null) {
@@ -2539,6 +2644,44 @@ var init_client = __esm({
2539
2644
  throw new SiglumeClientError(`AppManifest.currency must be 'USD' or 'JPY'. Got ${String(payload.currency)}.`);
2540
2645
  }
2541
2646
  payload.currency = currency;
2647
+ if (payload.allow_free_trial === void 0 || payload.allow_free_trial === null) {
2648
+ throw new SiglumeClientError(
2649
+ "AppManifest.allow_free_trial is required. Pass true to offer a Plus/Pro buyer free trial or false to disable trials."
2650
+ );
2651
+ }
2652
+ if (Boolean(payload.allow_free_trial)) {
2653
+ const duration = payload.free_trial_duration_days ?? 30;
2654
+ if (typeof duration !== "number" || !Number.isInteger(duration)) {
2655
+ throw new SiglumeClientError(
2656
+ "AppManifest.free_trial_duration_days must be an integer when allow_free_trial=true."
2657
+ );
2658
+ }
2659
+ if (duration < 1 || duration > 90) {
2660
+ throw new SiglumeClientError(
2661
+ `AppManifest.free_trial_duration_days must be between 1 and 90 when allow_free_trial=true, got: ${duration}.`
2662
+ );
2663
+ }
2664
+ }
2665
+ const explicitPublisherType = payload.publisher_type !== void 0 && payload.publisher_type !== null;
2666
+ const companyId = String(payload.company_id ?? "").trim() || String(payload.publisher_company_id ?? "").trim();
2667
+ const publisherType = String(payload.publisher_type ?? "user").trim().toLowerCase();
2668
+ if (publisherType !== "user" && publisherType !== "company") {
2669
+ throw new SiglumeClientError("AppManifest.publisher_type must be 'user' or 'company'.");
2670
+ }
2671
+ if (publisherType === "company" && !companyId) {
2672
+ throw new SiglumeClientError("AppManifest.company_id is required when publisher_type='company'.");
2673
+ }
2674
+ if (publisherType === "user" && companyId) {
2675
+ throw new SiglumeClientError("AppManifest.company_id cannot be combined with publisher_type='user'.");
2676
+ }
2677
+ if (explicitPublisherType || companyId) {
2678
+ payload.publisher_type = publisherType;
2679
+ }
2680
+ if (companyId) {
2681
+ payload.company_id = companyId;
2682
+ payload.publisher_company_id = companyId;
2683
+ }
2684
+ validateManifestPersistenceContract(payload);
2542
2685
  if (payload.manifest && typeof payload.manifest === "object") {
2543
2686
  delete payload.manifest.version;
2544
2687
  }
@@ -2646,6 +2789,45 @@ var init_client = __esm({
2646
2789
  const [data] = await this.request("GET", `/market/capabilities/${listing_id}`);
2647
2790
  return parseListing(data);
2648
2791
  }
2792
+ async list_company_publishers() {
2793
+ const [data] = await this.request("GET", "/market/company-publishers");
2794
+ return Array.isArray(data.items) ? data.items.filter((item) => isRecord(item)).map(parseCompanyPublisher) : [];
2795
+ }
2796
+ async request_company_publish_approval(listing_id, note) {
2797
+ const [data] = await this.request("POST", `/market/capabilities/${listing_id}/company-publish-approval`, {
2798
+ json_body: note ? { note } : {}
2799
+ });
2800
+ return parseListing(data);
2801
+ }
2802
+ async decide_company_publish_approval(listing_id, options) {
2803
+ const [data] = await this.request("POST", `/market/capabilities/${listing_id}/company-publish-approval/decision`, {
2804
+ json_body: {
2805
+ decision: options.decision,
2806
+ ...options.reason ? { reason: options.reason } : {}
2807
+ }
2808
+ });
2809
+ return parseListing(data);
2810
+ }
2811
+ async get_capability_state(capability_key, save_key = "default") {
2812
+ const [data] = await this.request("GET", `/market/capability-state/${capability_key}/${save_key}`);
2813
+ return parseCapabilitySaveState(data);
2814
+ }
2815
+ async put_capability_state(capability_key, save_key = "default", payload = {}, options = {}) {
2816
+ const body = {
2817
+ payload: toRecord(payload),
2818
+ schema_version: options.schema_version ?? "1",
2819
+ metadata: toRecord(options.metadata)
2820
+ };
2821
+ if (options.expected_revision !== void 0 && options.expected_revision !== null) {
2822
+ body.expected_revision = Math.trunc(options.expected_revision);
2823
+ }
2824
+ const [data] = await this.request("PUT", `/market/capability-state/${capability_key}/${save_key}`, { json_body: body });
2825
+ return parseCapabilitySaveState(data);
2826
+ }
2827
+ async delete_capability_state(capability_key, save_key = "default") {
2828
+ const [data] = await this.request("DELETE", `/market/capability-state/${capability_key}/${save_key}`);
2829
+ return parseCapabilitySaveState(data);
2830
+ }
2649
2831
  // ----- Capability bundles (v0.7 track 2) ---------------------------------
2650
2832
  async list_bundles(options = {}) {
2651
2833
  const params = {
@@ -5114,10 +5296,14 @@ function appendValueChange(changes, emittedKeys, level, key, oldValue, newValue,
5114
5296
  }
5115
5297
  function normalizeManifest(value) {
5116
5298
  const payload = coerceMapping(value, "manifest");
5299
+ const rawDuration = payload.free_trial_duration_days;
5300
+ const duration = rawDuration === void 0 || rawDuration === null ? 30 : Number(rawDuration);
5117
5301
  return {
5118
5302
  ...payload,
5119
5303
  price_model: payload.price_model ?? "free",
5120
5304
  currency: payload.currency ?? "USD",
5305
+ allow_free_trial: Boolean(payload.allow_free_trial ?? false),
5306
+ free_trial_duration_days: Number.isFinite(duration) ? Math.trunc(duration) : 30,
5121
5307
  // AppManifest defaults permission_class to "read-only" (hyphen form,
5122
5308
  // PermissionClass.READ_ONLY). Without this default, a legacy / minimal
5123
5309
  // manifest without permission_class compared against an upgraded one
@@ -7236,7 +7422,12 @@ function ensureManifestPublisherIdentity(project) {
7236
7422
  const sellerHomepageUrl = String(manifestPayload.seller_homepage_url ?? "").trim();
7237
7423
  const sellerSocialUrl = String(manifestPayload.seller_social_url ?? "").trim();
7238
7424
  const jurisdiction = String(manifestPayload.jurisdiction ?? "").trim();
7425
+ const companyId = String(manifestPayload.company_id ?? "").trim() || String(manifestPayload.publisher_company_id ?? "").trim();
7426
+ const publisherType = String(manifestPayload.publisher_type ?? "user").trim().toLowerCase();
7239
7427
  const issues = [];
7428
+ if (companyId && publisherType !== "company") {
7429
+ issues.push('manifest.company_id requires manifest.publisher_type to be "company"');
7430
+ }
7240
7431
  if (!docsUrl) {
7241
7432
  issues.push("manifest.docs_url is required");
7242
7433
  } else if (looksLikePlaceholder(docsUrl)) {
@@ -7382,25 +7573,110 @@ ${errors.map((error) => `- ${error}`).join("\n")}`
7382
7573
  }
7383
7574
  return preflight;
7384
7575
  }
7576
+ function companyNameSlug(value) {
7577
+ return value.normalize("NFKD").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
7578
+ }
7385
7579
  async function runRegistration(path = ".", options = {}, deps = {}) {
7386
7580
  const project = await loadProject(path);
7581
+ let requestedCompanyId = String(options.company_id ?? "").trim();
7582
+ const requestedCompanySlug = String(options.company_slug ?? "").trim();
7583
+ let companyPublisherCandidates = null;
7584
+ if (requestedCompanySlug) {
7585
+ if (requestedCompanyId) {
7586
+ throw new SiglumeProjectError("--company and --company-slug cannot be combined.");
7587
+ }
7588
+ const slug = companyNameSlug(requestedCompanySlug);
7589
+ if (!slug && requestedCompanySlug !== requestedCompanyId) {
7590
+ throw new SiglumeProjectError(`Company slug ${requestedCompanySlug} is not slug-compatible; use --company <company_id> instead.`);
7591
+ }
7592
+ }
7593
+ if (requestedCompanyId) {
7594
+ project.manifest = {
7595
+ ...project.manifest,
7596
+ publisher_type: "company",
7597
+ company_id: requestedCompanyId,
7598
+ publisher_company_id: requestedCompanyId
7599
+ };
7600
+ }
7387
7601
  ensureExplicitToolManual(project);
7388
7602
  ensureManifestPublisherIdentity(project);
7389
7603
  ensureRuntimeValidationReady(project);
7390
7604
  ensureRequiredOauthCredentials(project);
7391
7605
  const canonicalOauthCredentials = canonicalOauthCredentialsPayload(project.oauth_credentials);
7392
7606
  const client = await createClient(deps);
7607
+ if (requestedCompanySlug) {
7608
+ const slug = companyNameSlug(requestedCompanySlug);
7609
+ companyPublisherCandidates = await client.list_company_publishers();
7610
+ const matches = companyPublisherCandidates.filter(
7611
+ (item) => companyNameSlug(item.name || item.company_id) === slug || item.company_id === requestedCompanySlug
7612
+ );
7613
+ if (matches.length === 0) {
7614
+ throw new SiglumeProjectError(`Company slug ${requestedCompanySlug} is not available to this API key.`);
7615
+ }
7616
+ if (matches.length > 1) {
7617
+ throw new SiglumeProjectError(`Company slug ${requestedCompanySlug} is ambiguous; use --company <company_id> instead.`);
7618
+ }
7619
+ const match = matches[0];
7620
+ if (!match) {
7621
+ throw new SiglumeProjectError(`Company slug ${requestedCompanySlug} is not available to this API key.`);
7622
+ }
7623
+ if (match.can_publish === false) {
7624
+ const disabledReasons = match.disabled_reasons ?? [];
7625
+ const reasons = disabledReasons.length > 0 ? disabledReasons.join(", ") : "company publisher is disabled";
7626
+ throw new SiglumeProjectError(`Company ${match.company_id} cannot publish: ${reasons}.`);
7627
+ }
7628
+ requestedCompanyId = match.company_id;
7629
+ project.manifest = {
7630
+ ...project.manifest,
7631
+ publisher_type: "company",
7632
+ company_id: requestedCompanyId,
7633
+ publisher_company_id: requestedCompanyId
7634
+ };
7635
+ }
7393
7636
  const preflight = await registrationPreflight(project, client);
7637
+ let companyPublisherPreflight = null;
7638
+ const companyId = String(project.manifest.company_id ?? "").trim() || String(project.manifest.publisher_company_id ?? "").trim();
7639
+ const publisherType = String(project.manifest.publisher_type ?? "user").toLowerCase();
7640
+ if (publisherType === "company") {
7641
+ if (!companyId) {
7642
+ throw new SiglumeProjectError("Company registration requires --company <company_id> or manifest.company_id.");
7643
+ }
7644
+ const companies = companyPublisherCandidates ?? await client.list_company_publishers();
7645
+ companyPublisherCandidates = companies;
7646
+ const company = companies.find((item) => item.company_id === companyId);
7647
+ if (!company) {
7648
+ throw new SiglumeProjectError(`Company ${companyId} is not available to this API key.`);
7649
+ }
7650
+ if (company.can_publish === false) {
7651
+ const disabledReasons = company.disabled_reasons ?? [];
7652
+ const reasons = disabledReasons.length > 0 ? disabledReasons.join(", ") : "company publisher is disabled";
7653
+ throw new SiglumeProjectError(`Company ${companyId} cannot publish: ${reasons}.`);
7654
+ }
7655
+ companyPublisherPreflight = company;
7656
+ }
7394
7657
  let developerPortalPreflight = null;
7395
7658
  if (String(project.manifest.price_model ?? "free").toLowerCase() !== "free") {
7396
- const portal = await client.get_developer_portal();
7397
- const verifiedDestination = portal.payout_readiness?.verified_destination;
7398
- if (verifiedDestination !== true) {
7399
- throw new SiglumeProjectError(
7400
- "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."
7401
- );
7659
+ if (publisherType === "company") {
7660
+ const company = companyPublisherPreflight;
7661
+ if (!company) {
7662
+ throw new SiglumeProjectError(`Company ${companyId} is not available to this API key.`);
7663
+ }
7664
+ if (company.settlement_wallet_ready !== true) {
7665
+ throw new SiglumeProjectError(
7666
+ `Paid company registration requires a verified company settlement wallet for ${company.name}. Open the company settings and complete settlement readiness before registering.`
7667
+ );
7668
+ }
7669
+ developerPortalPreflight = { company_publisher: toJsonable(company) };
7670
+ } else {
7671
+ const portal = await client.get_developer_portal();
7672
+ const verifiedDestination = portal.payout_readiness?.verified_destination;
7673
+ if (verifiedDestination !== true) {
7674
+ throw new SiglumeProjectError(
7675
+ "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."
7676
+ );
7677
+ }
7678
+ developerPortalPreflight = toJsonable(portal);
7402
7679
  }
7403
- developerPortalPreflight = toJsonable(portal);
7404
7680
  }
7405
7681
  const receipt = await client.auto_register(project.manifest, project.tool_manual, {
7406
7682
  runtime_validation: project.runtime_validation,
@@ -7473,6 +7749,14 @@ async function getUsageReport(options, deps = {}) {
7473
7749
  count: items.length
7474
7750
  };
7475
7751
  }
7752
+ async function listCompanyPublishersReport(deps = {}) {
7753
+ const client = await createClient(deps);
7754
+ const companies = await client.list_company_publishers();
7755
+ return {
7756
+ companies: companies.map((item) => toJsonable(item)),
7757
+ count: companies.length
7758
+ };
7759
+ }
7476
7760
  async function diffJsonFiles(oldPath, newPath) {
7477
7761
  const oldPayload = await loadJsonDocument(oldPath);
7478
7762
  const newPayload = await loadJsonDocument(newPath);
@@ -7669,6 +7953,7 @@ function buildOperationManifest(operation, capability_key_override) {
7669
7953
  required_connected_accounts: [],
7670
7954
  price_model: PriceModel.FREE,
7671
7955
  currency: "USD",
7956
+ allow_free_trial: false,
7672
7957
  jurisdiction: "US",
7673
7958
  short_description: operation.summary,
7674
7959
  docs_url: "https://example.com/docs",
@@ -7747,6 +8032,7 @@ function operationAdapterSource(operation, manifest) {
7747
8032
  " required_connected_accounts: [],",
7748
8033
  " price_model: PriceModel.FREE,",
7749
8034
  " currency: 'USD' as const,",
8035
+ " allow_free_trial: false,",
7750
8036
  ` jurisdiction: ${JSON.stringify(manifest.jurisdiction)},`,
7751
8037
  ` short_description: ${JSON.stringify(manifest.short_description ?? "")},`,
7752
8038
  ` support_contact: ${JSON.stringify(manifest.support_contact ?? "")},`,
@@ -8427,6 +8713,7 @@ function fallbackTemplateSource(template) {
8427
8713
  " required_connected_accounts: [],",
8428
8714
  " price_model: PriceModel.FREE,",
8429
8715
  " currency: 'USD' as const,",
8716
+ " allow_free_trial: false,",
8430
8717
  ' jurisdiction: "US",',
8431
8718
  ' short_description: "Starter template generated by siglume init.",',
8432
8719
  ' support_contact: "support@example.com",',
@@ -8481,6 +8768,7 @@ function starterManifest(template) {
8481
8768
  required_connected_accounts: [],
8482
8769
  price_model: "free",
8483
8770
  currency: "USD",
8771
+ allow_free_trial: false,
8484
8772
  jurisdiction: "US",
8485
8773
  short_description: "Starter template generated by siglume init.",
8486
8774
  support_contact: "support@example.com",
@@ -8555,6 +8843,24 @@ function renderOperationTable(operations) {
8555
8843
  ...rows.map((row) => row.map((cell, index) => cell.padEnd(widths[index] ?? cell.length)).join(" "))
8556
8844
  ];
8557
8845
  }
8846
+ function renderCompanyTable(companies) {
8847
+ const rows = companies.map((item) => [
8848
+ String(item.company_id ?? item.id ?? ""),
8849
+ String(item.name ?? ""),
8850
+ String(item.membership_role ?? (item.is_founder ? "founder" : "")),
8851
+ String(item.settlement_wallet_ready === true ? "ready" : "not_ready"),
8852
+ String(item.pending_approval_count ?? 0)
8853
+ ]);
8854
+ const headers = ["company_id", "name", "role", "settlement", "pending"];
8855
+ const widths = headers.map(
8856
+ (header, index) => Math.max(header.length, ...rows.map((row) => row[index]?.length ?? 0))
8857
+ );
8858
+ return [
8859
+ headers.map((header, index) => header.padEnd(widths[index] ?? header.length)).join(" "),
8860
+ widths.map((width) => "-".repeat(width)).join(" "),
8861
+ ...rows.map((row) => row.map((cell, index) => cell.padEnd(widths[index] ?? cell.length)).join(" "))
8862
+ ];
8863
+ }
8558
8864
  async function runCli(argv, deps = {}) {
8559
8865
  const stdout = deps.stdout;
8560
8866
  const stderr = deps.stderr ?? console.error;
@@ -8711,7 +9017,21 @@ async function runCli(argv, deps = {}) {
8711
9017
  if (report.runtime_validation_path) emit(stdout, `runtime_validation_path: ${String(report.runtime_validation_path)}`);
8712
9018
  if (report.oauth_credentials_path) emit(stdout, `oauth_credentials_path: ${String(report.oauth_credentials_path)}`);
8713
9019
  });
8714
- 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) => {
9020
+ program.command("companies").description("List Siglume companies available for company-name publishing.").option("--json", "emit machine-readable JSON", false).action(async (options) => {
9021
+ const report = await listCompanyPublishersReport(deps);
9022
+ if (options.json) {
9023
+ emit(stdout, renderJson(report));
9024
+ return;
9025
+ }
9026
+ const companies = Array.isArray(report.companies) ? report.companies.filter((item) => Boolean(item && typeof item === "object")) : [];
9027
+ if (companies.length === 0) {
9028
+ emit(stdout, "No company publishers available for this API key.");
9029
+ return;
9030
+ }
9031
+ emit(stdout, "Company publishers");
9032
+ renderCompanyTable(companies).forEach((line) => emit(stdout, line));
9033
+ });
9034
+ program.command("register").option("--confirm", "explicitly confirm the registration; this is the default unless --draft-only is set", false).option("--draft-only", "create or refresh the draft without confirming publication", false).option("--submit-review", "legacy alias: publish immediately if your environment still routes through submit-review", false).option("--company <companyId>", "publish under a Siglume company name; revenue is split equally among active members", "").option("--company-slug <slug>", "publish under a Siglume company by matching the slugified company name", "").option("--json", "emit machine-readable JSON", false).argument("[path]", ".", "project path").action(async (path, options) => {
8715
9035
  const draftOnly = Boolean(options.draftOnly);
8716
9036
  if (draftOnly && options.confirm) {
8717
9037
  throw new SiglumeProjectError("--draft-only cannot be combined with --confirm.");
@@ -8720,7 +9040,13 @@ async function runCli(argv, deps = {}) {
8720
9040
  throw new SiglumeProjectError("--draft-only cannot be combined with --submit-review.");
8721
9041
  }
8722
9042
  const shouldConfirm = Boolean(options.confirm) || !draftOnly && !options.submitReview;
8723
- const report = await runRegistration(path, { confirm: shouldConfirm, draft_only: draftOnly, submit_review: options.submitReview }, deps);
9043
+ const report = await runRegistration(path, {
9044
+ confirm: shouldConfirm,
9045
+ draft_only: draftOnly,
9046
+ submit_review: options.submitReview,
9047
+ company_id: options.company,
9048
+ company_slug: options.companySlug
9049
+ }, deps);
8724
9050
  if (options.json) {
8725
9051
  emit(stdout, renderJson(report));
8726
9052
  } else {