@stigmer/react 3.36.0 → 3.37.1

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.
@@ -32,15 +32,24 @@ export type IssuableTerm = LicenseTerm.trial | LicenseTerm.paid;
32
32
  */
33
33
  export type PlanOnlyFeature = Feature.teams | Feature.managed_organizations;
34
34
 
35
+ /**
36
+ * Features the contract names but nothing gates: every edition serves them
37
+ * to every tenant, so granting one on a license would sell what the
38
+ * customer already has. A license issued before the value was ruled
39
+ * ungated may still carry one; the console shows it nowhere.
40
+ */
41
+ export type UngatedFeature = Feature.platform_client;
42
+
35
43
  /**
36
44
  * A feature an operator can grant on a license: every feature but the
37
- * unspecified zero value and the plan-only ones. Derived by exclusion, so
38
- * a feature added to the contract lands here by default and must be given
39
- * a label below, or be named plan-only above, before the package compiles.
45
+ * unspecified zero value, the plan-only ones and the ungated ones. Derived
46
+ * by exclusion, so a feature added to the contract lands here by default
47
+ * and must be given a label below, or be named above, before the package
48
+ * compiles.
40
49
  */
41
50
  export type GrantableFeature = Exclude<
42
51
  Feature,
43
- Feature.feature_unspecified | PlanOnlyFeature
52
+ Feature.feature_unspecified | PlanOnlyFeature | UngatedFeature
44
53
  >;
45
54
 
46
55
  /** Display labels for the issuable terms. */
@@ -61,10 +70,6 @@ export const FEATURE_LABELS: Readonly<
61
70
  label: "SSO enforcement",
62
71
  description: "Require members to sign in through a registered identity provider.",
63
72
  },
64
- [Feature.platform_client]: {
65
- label: "Platform clients",
66
- description: "Let the customer's own product mint Stigmer tokens for its users.",
67
- },
68
73
  [Feature.byo_provider_keys]: {
69
74
  label: "Bring your own provider keys",
70
75
  description: "Use the customer's own LLM provider keys instead of the metered proxy.",
@@ -84,6 +89,15 @@ export const GRANTABLE_FEATURES: readonly GrantableFeature[] = (
84
89
  Object.keys(FEATURE_LABELS).map(Number) as GrantableFeature[]
85
90
  ).sort((a, b) => a - b);
86
91
 
92
+ /**
93
+ * Whether a stored feature is one the console shows: the one test for
94
+ * which of a license's features the calendar counts, the names and the
95
+ * detail list, and a renewal carries forward.
96
+ */
97
+ export function isGrantableFeature(feature: number): feature is GrantableFeature {
98
+ return feature in FEATURE_LABELS;
99
+ }
100
+
87
101
  const DAY_MS = 24 * 60 * 60 * 1000;
88
102
 
89
103
  /**
@@ -145,7 +159,7 @@ export function formatDayFromToday(day: string, now: Date): string {
145
159
  */
146
160
  export function entitlementParts(entitlements: Entitlements | undefined): readonly string[] {
147
161
  const limits = entitlements?.limits;
148
- const features = entitlements?.features.length ?? 0;
162
+ const features = entitlements?.features.filter(isGrantableFeature).length ?? 0;
149
163
  return [
150
164
  limitPart(limits?.maxUsers, "user"),
151
165
  limitPart(limits?.maxOrganizations, "organization"),
@@ -23,6 +23,7 @@ import { ApiResourceMetadataSchema } from "@stigmer/protos/ai/stigmer/commons/ap
23
23
  import { Switch } from "../switch/Switch.js";
24
24
  import { Tabs, type TabItem } from "../tabs/Tabs.js";
25
25
  import { toast } from "../feedback/toast.js";
26
+ import { useStigmer } from "../hooks.js";
26
27
  import { useCopyResource } from "../resource-detail/useCopyResource.js";
27
28
  import { useDeploymentMode } from "../deployment-mode.js";
28
29
  import { useBillingAccount } from "../billing/useBillingAccount.js";
@@ -1507,12 +1508,24 @@ function MessageField({
1507
1508
  // Developer tab — the graduation ladder to the full SDK
1508
1509
  // ---------------------------------------------------------------------------
1509
1510
 
1510
- function buildDeveloperSnippet(org: string, slug: string): string {
1511
+ /**
1512
+ * The platform client snippet, aimed at the server the console is connected
1513
+ * to (`stigmer.baseUrl`) — a self-hosted admin copies code for their own
1514
+ * server, not Stigmer Cloud. The base URL is normalised as the channel-app
1515
+ * webhook URLs normalise it, and JSON-quoted so the line is always a valid
1516
+ * string literal.
1517
+ */
1518
+ function buildDeveloperSnippet(
1519
+ apiBaseUrl: string,
1520
+ org: string,
1521
+ slug: string,
1522
+ ): string {
1523
+ const baseUrl = JSON.stringify(apiBaseUrl.replace(/\/+$/, ""));
1511
1524
  return [
1512
1525
  `import { createPlatformClientAuth } from "@stigmer/sdk/node";`,
1513
1526
  ``,
1514
1527
  `const auth = createPlatformClientAuth({`,
1515
- ` baseUrl: "https://api.stigmer.ai",`,
1528
+ ` baseUrl: ${baseUrl},`,
1516
1529
  ` clientId: process.env.STIGMER_CLIENT_ID,`,
1517
1530
  ` clientSecret: process.env.STIGMER_CLIENT_SECRET,`,
1518
1531
  `});`,
@@ -1531,7 +1544,11 @@ function DeveloperTab({
1531
1544
  readonly org: string;
1532
1545
  readonly slug: string;
1533
1546
  }) {
1534
- const snippet = useMemo(() => buildDeveloperSnippet(org, slug), [org, slug]);
1547
+ const stigmer = useStigmer();
1548
+ const snippet = useMemo(
1549
+ () => buildDeveloperSnippet(stigmer.baseUrl, org, slug),
1550
+ [stigmer.baseUrl, org, slug],
1551
+ );
1535
1552
 
1536
1553
  return (
1537
1554
  <div className="stg:flex stg:flex-col stg:gap-3">