@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.
@@ -1248,6 +1248,56 @@ var init_operations = __esm({
1248
1248
  });
1249
1249
 
1250
1250
  // src/client.ts
1251
+ function validateManifestPersistenceContract(payload) {
1252
+ const vertical = String(payload.store_vertical ?? "").trim().toLowerCase();
1253
+ const persistence = payload.persistence;
1254
+ if (persistence === void 0 || persistence === null) {
1255
+ return;
1256
+ }
1257
+ if (!isRecord(persistence)) {
1258
+ throw new SiglumeClientError("AppManifest.persistence must be an object.");
1259
+ }
1260
+ const mode = String(persistence.mode ?? (vertical === "game" ? "platform" : "none")).trim().toLowerCase();
1261
+ if (!["none", "local", "platform", "developer_server"].includes(mode)) {
1262
+ throw new SiglumeClientError(
1263
+ "AppManifest.persistence.mode must be one of: none, local, platform, developer_server."
1264
+ );
1265
+ }
1266
+ const schema = persistence.save_data_schema;
1267
+ if (vertical === "game" && mode !== "none" && schema === void 0) {
1268
+ throw new SiglumeClientError(
1269
+ "AppManifest.persistence.save_data_schema is required when store_vertical='game' and persistence.mode is not 'none'."
1270
+ );
1271
+ }
1272
+ if (schema !== void 0) {
1273
+ validateSaveDataSchema(schema, "AppManifest.persistence.save_data_schema");
1274
+ }
1275
+ }
1276
+ function validateSaveDataSchema(schema, fieldName) {
1277
+ if (!isRecord(schema)) {
1278
+ throw new SiglumeClientError(`${fieldName} must be a JSON Schema object.`);
1279
+ }
1280
+ const schemaSize = new TextEncoder().encode(JSON.stringify(schema)).length;
1281
+ if (schemaSize > 8192) {
1282
+ throw new SiglumeClientError(`${fieldName} must be at most 8192 bytes.`);
1283
+ }
1284
+ if (schema.type !== "object") {
1285
+ throw new SiglumeClientError(`${fieldName}.type must be 'object'.`);
1286
+ }
1287
+ const properties = schema.properties;
1288
+ if (!isRecord(properties) || Object.keys(properties).length === 0) {
1289
+ throw new SiglumeClientError(`${fieldName}.properties must be a non-empty object.`);
1290
+ }
1291
+ if (schema.required !== void 0) {
1292
+ if (!Array.isArray(schema.required) || !schema.required.every((item) => typeof item === "string")) {
1293
+ throw new SiglumeClientError(`${fieldName}.required must be an array of strings when provided.`);
1294
+ }
1295
+ const missing = schema.required.filter((item) => !(item in properties));
1296
+ if (missing.length > 0) {
1297
+ throw new SiglumeClientError(`${fieldName}.required references undefined properties: ${missing.join(", ")}.`);
1298
+ }
1299
+ }
1300
+ }
1251
1301
  function buildToolManualQualityReport(payload) {
1252
1302
  const qualityBlock = isRecord(payload.quality) ? payload.quality : payload;
1253
1303
  const issues = [];
@@ -1322,6 +1372,8 @@ function buildUrl(baseUrl, path, params) {
1322
1372
  return url.toString();
1323
1373
  }
1324
1374
  function parseListing(data) {
1375
+ const metadata = isRecord(data.metadata) ? data.metadata : {};
1376
+ const persistence = isRecord(data.persistence) ? data.persistence : isRecord(metadata.persistence) ? metadata.persistence : {};
1325
1377
  return {
1326
1378
  listing_id: String(data.listing_id ?? data.id ?? ""),
1327
1379
  capability_key: String(data.capability_key ?? ""),
@@ -1335,6 +1387,8 @@ function parseListing(data) {
1335
1387
  price_model: stringOrNull(data.price_model),
1336
1388
  price_value_minor: Number(data.price_value_minor ?? 0),
1337
1389
  currency: String(data.currency ?? "USD"),
1390
+ allow_free_trial: Boolean(data.allow_free_trial ?? false),
1391
+ free_trial_duration_days: Number(data.free_trial_duration_days ?? 30),
1338
1392
  short_description: stringOrNull(data.short_description),
1339
1393
  description: stringOrNull(data.description),
1340
1394
  docs_url: stringOrNull(data.docs_url),
@@ -1342,14 +1396,59 @@ function parseListing(data) {
1342
1396
  seller_display_name: stringOrNull(data.seller_display_name),
1343
1397
  seller_homepage_url: stringOrNull(data.seller_homepage_url),
1344
1398
  seller_social_url: stringOrNull(data.seller_social_url),
1399
+ publisher_type: stringOrNull(data.publisher_type),
1400
+ publisher_company_id: stringOrNull(data.publisher_company_id),
1401
+ company_id: stringOrNull(data.company_id),
1402
+ company_name: stringOrNull(data.company_name),
1403
+ company_publish_status: stringOrNull(data.company_publish_status),
1404
+ company_terms_version: stringOrNull(data.company_terms_version),
1345
1405
  review_status: stringOrNull(data.review_status),
1346
1406
  review_note: stringOrNull(data.review_note),
1347
1407
  submission_blockers: Array.isArray(data.submission_blockers) ? data.submission_blockers.filter((item) => typeof item === "string") : [],
1408
+ persistence: { ...persistence },
1348
1409
  created_at: stringOrNull(data.created_at),
1349
1410
  updated_at: stringOrNull(data.updated_at),
1350
1411
  raw: { ...data }
1351
1412
  };
1352
1413
  }
1414
+ function parseCompanyPublisher(data) {
1415
+ const wallets = Array.isArray(data.settlement_wallets) ? data.settlement_wallets.filter((item) => isRecord(item)) : [];
1416
+ return {
1417
+ company_id: String(data.company_id ?? data.id ?? ""),
1418
+ name: String(data.name ?? ""),
1419
+ status: String(data.status ?? ""),
1420
+ description: stringOrNull(data.description),
1421
+ is_founder: Boolean(data.is_founder ?? false),
1422
+ membership_role: stringOrNull(data.membership_role),
1423
+ membership_status: stringOrNull(data.membership_status),
1424
+ can_publish: Boolean(data.can_publish ?? true),
1425
+ can_approve: Boolean(data.can_approve ?? false),
1426
+ approval_required: Boolean(data.approval_required ?? false),
1427
+ paid_listing_allowed: Boolean(data.paid_listing_allowed ?? false),
1428
+ disabled_reasons: Array.isArray(data.disabled_reasons) ? data.disabled_reasons.filter((item) => typeof item === "string") : [],
1429
+ company_terms_version: stringOrNull(data.company_terms_version),
1430
+ active_listing_count: Number(data.active_listing_count ?? 0),
1431
+ pending_approval_count: Number(data.pending_approval_count ?? 0),
1432
+ settlement_wallet_ready: Boolean(data.settlement_wallet_ready ?? false),
1433
+ settlement_wallets: wallets.map((item) => ({ ...item })),
1434
+ raw: { ...data }
1435
+ };
1436
+ }
1437
+ function parseCapabilitySaveState(data) {
1438
+ return {
1439
+ capability_key: String(data.capability_key ?? ""),
1440
+ save_key: String(data.save_key ?? ""),
1441
+ schema_version: String(data.schema_version ?? "1"),
1442
+ revision: Number(data.revision ?? 0),
1443
+ payload: toRecord(data.payload),
1444
+ metadata: toRecord(data.metadata),
1445
+ checksum: stringOrNull(data.checksum),
1446
+ updated_at: stringOrNull(data.updated_at),
1447
+ created_at: stringOrNull(data.created_at),
1448
+ exists: Boolean(data.exists ?? false),
1449
+ raw: { ...data }
1450
+ };
1451
+ }
1353
1452
  function parseBundleMember(data) {
1354
1453
  return {
1355
1454
  capability_listing_id: String(data.capability_listing_id ?? ""),
@@ -2529,17 +2628,23 @@ var init_client = __esm({
2529
2628
  "support_contact",
2530
2629
  "seller_homepage_url",
2531
2630
  "seller_social_url",
2631
+ "publisher_type",
2632
+ "company_id",
2633
+ "publisher_company_id",
2532
2634
  "store_vertical",
2533
2635
  "jurisdiction",
2534
2636
  "price_model",
2535
2637
  "price_value_minor",
2536
2638
  "currency",
2639
+ "allow_free_trial",
2640
+ "free_trial_duration_days",
2537
2641
  "permission_class",
2538
2642
  "approval_mode",
2539
2643
  "dry_run_supported",
2540
2644
  "required_connected_accounts",
2541
2645
  "permission_scopes",
2542
- "compatibility_tags"
2646
+ "compatibility_tags",
2647
+ "persistence"
2543
2648
  ]) {
2544
2649
  const value = manifestPayload[fieldName];
2545
2650
  if (value !== void 0 && value !== null) {
@@ -2561,6 +2666,44 @@ var init_client = __esm({
2561
2666
  throw new SiglumeClientError(`AppManifest.currency must be 'USD' or 'JPY'. Got ${String(payload.currency)}.`);
2562
2667
  }
2563
2668
  payload.currency = currency;
2669
+ if (payload.allow_free_trial === void 0 || payload.allow_free_trial === null) {
2670
+ throw new SiglumeClientError(
2671
+ "AppManifest.allow_free_trial is required. Pass true to offer a Plus/Pro buyer free trial or false to disable trials."
2672
+ );
2673
+ }
2674
+ if (Boolean(payload.allow_free_trial)) {
2675
+ const duration = payload.free_trial_duration_days ?? 30;
2676
+ if (typeof duration !== "number" || !Number.isInteger(duration)) {
2677
+ throw new SiglumeClientError(
2678
+ "AppManifest.free_trial_duration_days must be an integer when allow_free_trial=true."
2679
+ );
2680
+ }
2681
+ if (duration < 1 || duration > 90) {
2682
+ throw new SiglumeClientError(
2683
+ `AppManifest.free_trial_duration_days must be between 1 and 90 when allow_free_trial=true, got: ${duration}.`
2684
+ );
2685
+ }
2686
+ }
2687
+ const explicitPublisherType = payload.publisher_type !== void 0 && payload.publisher_type !== null;
2688
+ const companyId = String(payload.company_id ?? "").trim() || String(payload.publisher_company_id ?? "").trim();
2689
+ const publisherType = String(payload.publisher_type ?? "user").trim().toLowerCase();
2690
+ if (publisherType !== "user" && publisherType !== "company") {
2691
+ throw new SiglumeClientError("AppManifest.publisher_type must be 'user' or 'company'.");
2692
+ }
2693
+ if (publisherType === "company" && !companyId) {
2694
+ throw new SiglumeClientError("AppManifest.company_id is required when publisher_type='company'.");
2695
+ }
2696
+ if (publisherType === "user" && companyId) {
2697
+ throw new SiglumeClientError("AppManifest.company_id cannot be combined with publisher_type='user'.");
2698
+ }
2699
+ if (explicitPublisherType || companyId) {
2700
+ payload.publisher_type = publisherType;
2701
+ }
2702
+ if (companyId) {
2703
+ payload.company_id = companyId;
2704
+ payload.publisher_company_id = companyId;
2705
+ }
2706
+ validateManifestPersistenceContract(payload);
2564
2707
  if (payload.manifest && typeof payload.manifest === "object") {
2565
2708
  delete payload.manifest.version;
2566
2709
  }
@@ -2668,6 +2811,45 @@ var init_client = __esm({
2668
2811
  const [data] = await this.request("GET", `/market/capabilities/${listing_id}`);
2669
2812
  return parseListing(data);
2670
2813
  }
2814
+ async list_company_publishers() {
2815
+ const [data] = await this.request("GET", "/market/company-publishers");
2816
+ return Array.isArray(data.items) ? data.items.filter((item) => isRecord(item)).map(parseCompanyPublisher) : [];
2817
+ }
2818
+ async request_company_publish_approval(listing_id, note) {
2819
+ const [data] = await this.request("POST", `/market/capabilities/${listing_id}/company-publish-approval`, {
2820
+ json_body: note ? { note } : {}
2821
+ });
2822
+ return parseListing(data);
2823
+ }
2824
+ async decide_company_publish_approval(listing_id, options) {
2825
+ const [data] = await this.request("POST", `/market/capabilities/${listing_id}/company-publish-approval/decision`, {
2826
+ json_body: {
2827
+ decision: options.decision,
2828
+ ...options.reason ? { reason: options.reason } : {}
2829
+ }
2830
+ });
2831
+ return parseListing(data);
2832
+ }
2833
+ async get_capability_state(capability_key, save_key = "default") {
2834
+ const [data] = await this.request("GET", `/market/capability-state/${capability_key}/${save_key}`);
2835
+ return parseCapabilitySaveState(data);
2836
+ }
2837
+ async put_capability_state(capability_key, save_key = "default", payload = {}, options = {}) {
2838
+ const body = {
2839
+ payload: toRecord(payload),
2840
+ schema_version: options.schema_version ?? "1",
2841
+ metadata: toRecord(options.metadata)
2842
+ };
2843
+ if (options.expected_revision !== void 0 && options.expected_revision !== null) {
2844
+ body.expected_revision = Math.trunc(options.expected_revision);
2845
+ }
2846
+ const [data] = await this.request("PUT", `/market/capability-state/${capability_key}/${save_key}`, { json_body: body });
2847
+ return parseCapabilitySaveState(data);
2848
+ }
2849
+ async delete_capability_state(capability_key, save_key = "default") {
2850
+ const [data] = await this.request("DELETE", `/market/capability-state/${capability_key}/${save_key}`);
2851
+ return parseCapabilitySaveState(data);
2852
+ }
2671
2853
  // ----- Capability bundles (v0.7 track 2) ---------------------------------
2672
2854
  async list_bundles(options = {}) {
2673
2855
  const params = {
@@ -5141,10 +5323,14 @@ function appendValueChange(changes, emittedKeys, level, key, oldValue, newValue,
5141
5323
  }
5142
5324
  function normalizeManifest(value) {
5143
5325
  const payload = coerceMapping(value, "manifest");
5326
+ const rawDuration = payload.free_trial_duration_days;
5327
+ const duration = rawDuration === void 0 || rawDuration === null ? 30 : Number(rawDuration);
5144
5328
  return {
5145
5329
  ...payload,
5146
5330
  price_model: payload.price_model ?? "free",
5147
5331
  currency: payload.currency ?? "USD",
5332
+ allow_free_trial: Boolean(payload.allow_free_trial ?? false),
5333
+ free_trial_duration_days: Number.isFinite(duration) ? Math.trunc(duration) : 30,
5148
5334
  // AppManifest defaults permission_class to "read-only" (hyphen form,
5149
5335
  // PermissionClass.READ_ONLY). Without this default, a legacy / minimal
5150
5336
  // manifest without permission_class compared against an upgraded one
@@ -7263,7 +7449,12 @@ function ensureManifestPublisherIdentity(project) {
7263
7449
  const sellerHomepageUrl = String(manifestPayload.seller_homepage_url ?? "").trim();
7264
7450
  const sellerSocialUrl = String(manifestPayload.seller_social_url ?? "").trim();
7265
7451
  const jurisdiction = String(manifestPayload.jurisdiction ?? "").trim();
7452
+ const companyId = String(manifestPayload.company_id ?? "").trim() || String(manifestPayload.publisher_company_id ?? "").trim();
7453
+ const publisherType = String(manifestPayload.publisher_type ?? "user").trim().toLowerCase();
7266
7454
  const issues = [];
7455
+ if (companyId && publisherType !== "company") {
7456
+ issues.push('manifest.company_id requires manifest.publisher_type to be "company"');
7457
+ }
7267
7458
  if (!docsUrl) {
7268
7459
  issues.push("manifest.docs_url is required");
7269
7460
  } else if (looksLikePlaceholder(docsUrl)) {
@@ -7409,25 +7600,110 @@ ${errors.map((error) => `- ${error}`).join("\n")}`
7409
7600
  }
7410
7601
  return preflight;
7411
7602
  }
7603
+ function companyNameSlug(value) {
7604
+ return value.normalize("NFKD").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
7605
+ }
7412
7606
  async function runRegistration(path = ".", options = {}, deps = {}) {
7413
7607
  const project = await loadProject(path);
7608
+ let requestedCompanyId = String(options.company_id ?? "").trim();
7609
+ const requestedCompanySlug = String(options.company_slug ?? "").trim();
7610
+ let companyPublisherCandidates = null;
7611
+ if (requestedCompanySlug) {
7612
+ if (requestedCompanyId) {
7613
+ throw new SiglumeProjectError("--company and --company-slug cannot be combined.");
7614
+ }
7615
+ const slug = companyNameSlug(requestedCompanySlug);
7616
+ if (!slug && requestedCompanySlug !== requestedCompanyId) {
7617
+ throw new SiglumeProjectError(`Company slug ${requestedCompanySlug} is not slug-compatible; use --company <company_id> instead.`);
7618
+ }
7619
+ }
7620
+ if (requestedCompanyId) {
7621
+ project.manifest = {
7622
+ ...project.manifest,
7623
+ publisher_type: "company",
7624
+ company_id: requestedCompanyId,
7625
+ publisher_company_id: requestedCompanyId
7626
+ };
7627
+ }
7414
7628
  ensureExplicitToolManual(project);
7415
7629
  ensureManifestPublisherIdentity(project);
7416
7630
  ensureRuntimeValidationReady(project);
7417
7631
  ensureRequiredOauthCredentials(project);
7418
7632
  const canonicalOauthCredentials = canonicalOauthCredentialsPayload(project.oauth_credentials);
7419
7633
  const client = await createClient(deps);
7634
+ if (requestedCompanySlug) {
7635
+ const slug = companyNameSlug(requestedCompanySlug);
7636
+ companyPublisherCandidates = await client.list_company_publishers();
7637
+ const matches = companyPublisherCandidates.filter(
7638
+ (item) => companyNameSlug(item.name || item.company_id) === slug || item.company_id === requestedCompanySlug
7639
+ );
7640
+ if (matches.length === 0) {
7641
+ throw new SiglumeProjectError(`Company slug ${requestedCompanySlug} is not available to this API key.`);
7642
+ }
7643
+ if (matches.length > 1) {
7644
+ throw new SiglumeProjectError(`Company slug ${requestedCompanySlug} is ambiguous; use --company <company_id> instead.`);
7645
+ }
7646
+ const match = matches[0];
7647
+ if (!match) {
7648
+ throw new SiglumeProjectError(`Company slug ${requestedCompanySlug} is not available to this API key.`);
7649
+ }
7650
+ if (match.can_publish === false) {
7651
+ const disabledReasons = match.disabled_reasons ?? [];
7652
+ const reasons = disabledReasons.length > 0 ? disabledReasons.join(", ") : "company publisher is disabled";
7653
+ throw new SiglumeProjectError(`Company ${match.company_id} cannot publish: ${reasons}.`);
7654
+ }
7655
+ requestedCompanyId = match.company_id;
7656
+ project.manifest = {
7657
+ ...project.manifest,
7658
+ publisher_type: "company",
7659
+ company_id: requestedCompanyId,
7660
+ publisher_company_id: requestedCompanyId
7661
+ };
7662
+ }
7420
7663
  const preflight = await registrationPreflight(project, client);
7664
+ let companyPublisherPreflight = null;
7665
+ const companyId = String(project.manifest.company_id ?? "").trim() || String(project.manifest.publisher_company_id ?? "").trim();
7666
+ const publisherType = String(project.manifest.publisher_type ?? "user").toLowerCase();
7667
+ if (publisherType === "company") {
7668
+ if (!companyId) {
7669
+ throw new SiglumeProjectError("Company registration requires --company <company_id> or manifest.company_id.");
7670
+ }
7671
+ const companies = companyPublisherCandidates ?? await client.list_company_publishers();
7672
+ companyPublisherCandidates = companies;
7673
+ const company = companies.find((item) => item.company_id === companyId);
7674
+ if (!company) {
7675
+ throw new SiglumeProjectError(`Company ${companyId} is not available to this API key.`);
7676
+ }
7677
+ if (company.can_publish === false) {
7678
+ const disabledReasons = company.disabled_reasons ?? [];
7679
+ const reasons = disabledReasons.length > 0 ? disabledReasons.join(", ") : "company publisher is disabled";
7680
+ throw new SiglumeProjectError(`Company ${companyId} cannot publish: ${reasons}.`);
7681
+ }
7682
+ companyPublisherPreflight = company;
7683
+ }
7421
7684
  let developerPortalPreflight = null;
7422
7685
  if (String(project.manifest.price_model ?? "free").toLowerCase() !== "free") {
7423
- const portal = await client.get_developer_portal();
7424
- const verifiedDestination = portal.payout_readiness?.verified_destination;
7425
- if (verifiedDestination !== true) {
7426
- throw new SiglumeProjectError(
7427
- "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."
7428
- );
7686
+ if (publisherType === "company") {
7687
+ const company = companyPublisherPreflight;
7688
+ if (!company) {
7689
+ throw new SiglumeProjectError(`Company ${companyId} is not available to this API key.`);
7690
+ }
7691
+ if (company.settlement_wallet_ready !== true) {
7692
+ throw new SiglumeProjectError(
7693
+ `Paid company registration requires a verified company settlement wallet for ${company.name}. Open the company settings and complete settlement readiness before registering.`
7694
+ );
7695
+ }
7696
+ developerPortalPreflight = { company_publisher: toJsonable(company) };
7697
+ } else {
7698
+ const portal = await client.get_developer_portal();
7699
+ const verifiedDestination = portal.payout_readiness?.verified_destination;
7700
+ if (verifiedDestination !== true) {
7701
+ throw new SiglumeProjectError(
7702
+ "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."
7703
+ );
7704
+ }
7705
+ developerPortalPreflight = toJsonable(portal);
7429
7706
  }
7430
- developerPortalPreflight = toJsonable(portal);
7431
7707
  }
7432
7708
  const receipt = await client.auto_register(project.manifest, project.tool_manual, {
7433
7709
  runtime_validation: project.runtime_validation,
@@ -7500,6 +7776,14 @@ async function getUsageReport(options, deps = {}) {
7500
7776
  count: items.length
7501
7777
  };
7502
7778
  }
7779
+ async function listCompanyPublishersReport(deps = {}) {
7780
+ const client = await createClient(deps);
7781
+ const companies = await client.list_company_publishers();
7782
+ return {
7783
+ companies: companies.map((item) => toJsonable(item)),
7784
+ count: companies.length
7785
+ };
7786
+ }
7503
7787
  async function diffJsonFiles(oldPath, newPath) {
7504
7788
  const oldPayload = await loadJsonDocument(oldPath);
7505
7789
  const newPayload = await loadJsonDocument(newPath);
@@ -7696,6 +7980,7 @@ function buildOperationManifest(operation, capability_key_override) {
7696
7980
  required_connected_accounts: [],
7697
7981
  price_model: PriceModel.FREE,
7698
7982
  currency: "USD",
7983
+ allow_free_trial: false,
7699
7984
  jurisdiction: "US",
7700
7985
  short_description: operation.summary,
7701
7986
  docs_url: "https://example.com/docs",
@@ -7774,6 +8059,7 @@ function operationAdapterSource(operation, manifest) {
7774
8059
  " required_connected_accounts: [],",
7775
8060
  " price_model: PriceModel.FREE,",
7776
8061
  " currency: 'USD' as const,",
8062
+ " allow_free_trial: false,",
7777
8063
  ` jurisdiction: ${JSON.stringify(manifest.jurisdiction)},`,
7778
8064
  ` short_description: ${JSON.stringify(manifest.short_description ?? "")},`,
7779
8065
  ` support_contact: ${JSON.stringify(manifest.support_contact ?? "")},`,
@@ -8454,6 +8740,7 @@ function fallbackTemplateSource(template) {
8454
8740
  " required_connected_accounts: [],",
8455
8741
  " price_model: PriceModel.FREE,",
8456
8742
  " currency: 'USD' as const,",
8743
+ " allow_free_trial: false,",
8457
8744
  ' jurisdiction: "US",',
8458
8745
  ' short_description: "Starter template generated by siglume init.",',
8459
8746
  ' support_contact: "support@example.com",',
@@ -8508,6 +8795,7 @@ function starterManifest(template) {
8508
8795
  required_connected_accounts: [],
8509
8796
  price_model: "free",
8510
8797
  currency: "USD",
8798
+ allow_free_trial: false,
8511
8799
  jurisdiction: "US",
8512
8800
  short_description: "Starter template generated by siglume init.",
8513
8801
  support_contact: "support@example.com",
@@ -8582,6 +8870,24 @@ function renderOperationTable(operations) {
8582
8870
  ...rows.map((row) => row.map((cell, index) => cell.padEnd(widths[index] ?? cell.length)).join(" "))
8583
8871
  ];
8584
8872
  }
8873
+ function renderCompanyTable(companies) {
8874
+ const rows = companies.map((item) => [
8875
+ String(item.company_id ?? item.id ?? ""),
8876
+ String(item.name ?? ""),
8877
+ String(item.membership_role ?? (item.is_founder ? "founder" : "")),
8878
+ String(item.settlement_wallet_ready === true ? "ready" : "not_ready"),
8879
+ String(item.pending_approval_count ?? 0)
8880
+ ]);
8881
+ const headers = ["company_id", "name", "role", "settlement", "pending"];
8882
+ const widths = headers.map(
8883
+ (header, index) => Math.max(header.length, ...rows.map((row) => row[index]?.length ?? 0))
8884
+ );
8885
+ return [
8886
+ headers.map((header, index) => header.padEnd(widths[index] ?? header.length)).join(" "),
8887
+ widths.map((width) => "-".repeat(width)).join(" "),
8888
+ ...rows.map((row) => row.map((cell, index) => cell.padEnd(widths[index] ?? cell.length)).join(" "))
8889
+ ];
8890
+ }
8585
8891
  async function runCli(argv, deps = {}) {
8586
8892
  const stdout = deps.stdout;
8587
8893
  const stderr = deps.stderr ?? console.error;
@@ -8738,7 +9044,21 @@ async function runCli(argv, deps = {}) {
8738
9044
  if (report.runtime_validation_path) emit(stdout, `runtime_validation_path: ${String(report.runtime_validation_path)}`);
8739
9045
  if (report.oauth_credentials_path) emit(stdout, `oauth_credentials_path: ${String(report.oauth_credentials_path)}`);
8740
9046
  });
8741
- 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) => {
9047
+ program.command("companies").description("List Siglume companies available for company-name publishing.").option("--json", "emit machine-readable JSON", false).action(async (options) => {
9048
+ const report = await listCompanyPublishersReport(deps);
9049
+ if (options.json) {
9050
+ emit(stdout, renderJson(report));
9051
+ return;
9052
+ }
9053
+ const companies = Array.isArray(report.companies) ? report.companies.filter((item) => Boolean(item && typeof item === "object")) : [];
9054
+ if (companies.length === 0) {
9055
+ emit(stdout, "No company publishers available for this API key.");
9056
+ return;
9057
+ }
9058
+ emit(stdout, "Company publishers");
9059
+ renderCompanyTable(companies).forEach((line) => emit(stdout, line));
9060
+ });
9061
+ 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) => {
8742
9062
  const draftOnly = Boolean(options.draftOnly);
8743
9063
  if (draftOnly && options.confirm) {
8744
9064
  throw new SiglumeProjectError("--draft-only cannot be combined with --confirm.");
@@ -8747,7 +9067,13 @@ async function runCli(argv, deps = {}) {
8747
9067
  throw new SiglumeProjectError("--draft-only cannot be combined with --submit-review.");
8748
9068
  }
8749
9069
  const shouldConfirm = Boolean(options.confirm) || !draftOnly && !options.submitReview;
8750
- const report = await runRegistration(path, { confirm: shouldConfirm, draft_only: draftOnly, submit_review: options.submitReview }, deps);
9070
+ const report = await runRegistration(path, {
9071
+ confirm: shouldConfirm,
9072
+ draft_only: draftOnly,
9073
+ submit_review: options.submitReview,
9074
+ company_id: options.company,
9075
+ company_slug: options.companySlug
9076
+ }, deps);
8751
9077
  if (options.json) {
8752
9078
  emit(stdout, renderJson(report));
8753
9079
  } else {