@stigmer/react 3.3.0 → 3.4.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.
Files changed (219) hide show
  1. package/billing/index.d.ts +0 -18
  2. package/billing/index.d.ts.map +1 -1
  3. package/billing/index.js +4 -9
  4. package/billing/index.js.map +1 -1
  5. package/cursor-accounts/CursorAccountEditor.d.ts +7 -1
  6. package/cursor-accounts/CursorAccountEditor.d.ts.map +1 -1
  7. package/cursor-accounts/CursorAccountEditor.js +21 -5
  8. package/cursor-accounts/CursorAccountEditor.js.map +1 -1
  9. package/cursor-accounts/CursorAccountsConsole.d.ts +9 -5
  10. package/cursor-accounts/CursorAccountsConsole.d.ts.map +1 -1
  11. package/cursor-accounts/CursorAccountsConsole.js +34 -140
  12. package/cursor-accounts/CursorAccountsConsole.js.map +1 -1
  13. package/cursor-accounts/MemberCoverageTable.d.ts +29 -0
  14. package/cursor-accounts/MemberCoverageTable.d.ts.map +1 -0
  15. package/cursor-accounts/MemberCoverageTable.js +150 -0
  16. package/cursor-accounts/MemberCoverageTable.js.map +1 -0
  17. package/cursor-accounts/MemberKeysPanel.d.ts +25 -0
  18. package/cursor-accounts/MemberKeysPanel.d.ts.map +1 -0
  19. package/cursor-accounts/MemberKeysPanel.js +115 -0
  20. package/cursor-accounts/MemberKeysPanel.js.map +1 -0
  21. package/cursor-accounts/badges.d.ts +9 -0
  22. package/cursor-accounts/badges.d.ts.map +1 -0
  23. package/cursor-accounts/badges.js +10 -0
  24. package/cursor-accounts/badges.js.map +1 -0
  25. package/cursor-accounts/cursor-account-coverage.d.ts +41 -0
  26. package/cursor-accounts/cursor-account-coverage.d.ts.map +1 -0
  27. package/cursor-accounts/cursor-account-coverage.js +26 -0
  28. package/cursor-accounts/cursor-account-coverage.js.map +1 -0
  29. package/cursor-accounts/cursor-account-format.d.ts +13 -0
  30. package/cursor-accounts/cursor-account-format.d.ts.map +1 -1
  31. package/cursor-accounts/cursor-account-format.js +16 -1
  32. package/cursor-accounts/cursor-account-format.js.map +1 -1
  33. package/datastore/CollectionRecordsBrowser.js +18 -4
  34. package/datastore/CollectionRecordsBrowser.js.map +1 -1
  35. package/datastore/RecordFilterBuilder.d.ts +8 -1
  36. package/datastore/RecordFilterBuilder.d.ts.map +1 -1
  37. package/datastore/RecordFilterBuilder.js +2 -2
  38. package/datastore/RecordFilterBuilder.js.map +1 -1
  39. package/datastore/recordFilter.d.ts +9 -1
  40. package/datastore/recordFilter.d.ts.map +1 -1
  41. package/datastore/recordFilter.js +12 -1
  42. package/datastore/recordFilter.js.map +1 -1
  43. package/execution/ExecutionProgress.d.ts.map +1 -1
  44. package/execution/ExecutionProgress.js +13 -4
  45. package/execution/ExecutionProgress.js.map +1 -1
  46. package/execution/MessageThread.d.ts.map +1 -1
  47. package/execution/MessageThread.js +10 -2
  48. package/execution/MessageThread.js.map +1 -1
  49. package/execution/useCreateAgentExecution.d.ts +31 -1
  50. package/execution/useCreateAgentExecution.d.ts.map +1 -1
  51. package/execution/useCreateAgentExecution.js +2 -0
  52. package/execution/useCreateAgentExecution.js.map +1 -1
  53. package/index.d.ts +4 -2
  54. package/index.d.ts.map +1 -1
  55. package/index.js +6 -2
  56. package/index.js.map +1 -1
  57. package/internal/form-primitives.d.ts +10 -0
  58. package/internal/form-primitives.d.ts.map +1 -0
  59. package/{billing → internal}/form-primitives.js +5 -9
  60. package/internal/form-primitives.js.map +1 -0
  61. package/package.json +4 -4
  62. package/pricing-governance/BaselineEditor.d.ts.map +1 -0
  63. package/{billing → pricing-governance}/BaselineEditor.js +19 -2
  64. package/pricing-governance/BaselineEditor.js.map +1 -0
  65. package/pricing-governance/ModelCatalogPanel.d.ts.map +1 -0
  66. package/pricing-governance/ModelCatalogPanel.js.map +1 -0
  67. package/pricing-governance/ModelGovernanceDetail.d.ts.map +1 -0
  68. package/pricing-governance/ModelGovernanceDetail.js.map +1 -0
  69. package/pricing-governance/OperatorAccessNotice.d.ts.map +1 -0
  70. package/pricing-governance/OperatorAccessNotice.js.map +1 -0
  71. package/pricing-governance/PricingGovernanceConsole.d.ts.map +1 -0
  72. package/{billing → pricing-governance}/PricingGovernanceConsole.js +1 -1
  73. package/pricing-governance/PricingGovernanceConsole.js.map +1 -0
  74. package/pricing-governance/PricingGovernancePanel.d.ts.map +1 -0
  75. package/pricing-governance/PricingGovernancePanel.js.map +1 -0
  76. package/pricing-governance/RetireConfirm.d.ts.map +1 -0
  77. package/{billing → pricing-governance}/RetireConfirm.js +1 -1
  78. package/pricing-governance/RetireConfirm.js.map +1 -0
  79. package/pricing-governance/governance-primitives.d.ts.map +1 -0
  80. package/pricing-governance/governance-primitives.js.map +1 -0
  81. package/pricing-governance/index.d.ts +19 -0
  82. package/pricing-governance/index.d.ts.map +1 -0
  83. package/pricing-governance/index.js +20 -0
  84. package/pricing-governance/index.js.map +1 -0
  85. package/pricing-governance/pricing-format.d.ts.map +1 -0
  86. package/pricing-governance/pricing-format.js.map +1 -0
  87. package/pricing-governance/useDecidePricingOverride.d.ts.map +1 -0
  88. package/pricing-governance/useDecidePricingOverride.js.map +1 -0
  89. package/pricing-governance/useModelGovernanceView.d.ts.map +1 -0
  90. package/pricing-governance/useModelGovernanceView.js.map +1 -0
  91. package/pricing-governance/useModelPricingBaselines.d.ts.map +1 -0
  92. package/pricing-governance/useModelPricingBaselines.js.map +1 -0
  93. package/pricing-governance/usePricingGovernance.d.ts.map +1 -0
  94. package/pricing-governance/usePricingGovernance.js.map +1 -0
  95. package/pricing-governance/useRetireModelPricingBaseline.d.ts.map +1 -0
  96. package/pricing-governance/useRetireModelPricingBaseline.js.map +1 -0
  97. package/pricing-governance/useUpsertModelPricingBaseline.d.ts.map +1 -0
  98. package/pricing-governance/useUpsertModelPricingBaseline.js.map +1 -0
  99. package/session/useCreateSession.d.ts +28 -0
  100. package/session/useCreateSession.d.ts.map +1 -1
  101. package/session/useCreateSession.js +2 -1
  102. package/session/useCreateSession.js.map +1 -1
  103. package/session/useNewSessionFlow.d.ts +30 -0
  104. package/session/useNewSessionFlow.d.ts.map +1 -1
  105. package/session/useNewSessionFlow.js +7 -1
  106. package/session/useNewSessionFlow.js.map +1 -1
  107. package/session/useUpdateSession.d.ts +29 -10
  108. package/session/useUpdateSession.d.ts.map +1 -1
  109. package/session/useUpdateSession.js +29 -10
  110. package/session/useUpdateSession.js.map +1 -1
  111. package/src/billing/index.ts +5 -37
  112. package/src/cursor-accounts/CursorAccountEditor.tsx +61 -13
  113. package/src/cursor-accounts/CursorAccountsConsole.tsx +44 -400
  114. package/src/cursor-accounts/MemberCoverageTable.tsx +439 -0
  115. package/src/cursor-accounts/MemberKeysPanel.tsx +278 -0
  116. package/src/cursor-accounts/__tests__/CursorAccountsConsole.test.tsx +306 -10
  117. package/src/cursor-accounts/__tests__/cursor-account-coverage.test.ts +73 -0
  118. package/src/cursor-accounts/badges.tsx +26 -0
  119. package/src/cursor-accounts/cursor-account-coverage.ts +71 -0
  120. package/src/cursor-accounts/cursor-account-format.ts +17 -1
  121. package/src/datastore/CollectionRecordsBrowser.tsx +29 -3
  122. package/src/datastore/RecordFilterBuilder.tsx +12 -1
  123. package/src/datastore/__tests__/CollectionRecordsBrowser.test.tsx +38 -0
  124. package/src/datastore/__tests__/RecordFilterBuilder.test.tsx +14 -0
  125. package/src/datastore/__tests__/recordFilter.test.ts +13 -0
  126. package/src/datastore/recordFilter.ts +15 -1
  127. package/src/execution/ExecutionProgress.tsx +14 -4
  128. package/src/execution/MessageThread.tsx +10 -2
  129. package/src/execution/__tests__/ExecutionProgress.test.tsx +67 -0
  130. package/src/execution/__tests__/MessageThread.test.tsx +44 -0
  131. package/src/execution/__tests__/useCreateAgentExecution.test.tsx +86 -0
  132. package/src/execution/useCreateAgentExecution.ts +41 -6
  133. package/src/index.ts +32 -24
  134. package/src/{billing → internal}/form-primitives.tsx +4 -32
  135. package/src/{billing → pricing-governance}/BaselineEditor.tsx +36 -3
  136. package/src/{billing → pricing-governance}/PricingGovernanceConsole.tsx +1 -1
  137. package/src/{billing → pricing-governance}/RetireConfirm.tsx +1 -1
  138. package/src/pricing-governance/index.ts +50 -0
  139. package/src/session/__tests__/useCreateSession.test.tsx +94 -0
  140. package/src/session/__tests__/useNewSessionFlow.test.tsx +33 -0
  141. package/src/session/useCreateSession.ts +30 -0
  142. package/src/session/useNewSessionFlow.ts +45 -1
  143. package/src/session/useUpdateSession.ts +29 -10
  144. package/styles.css +1 -1
  145. package/billing/BaselineEditor.d.ts.map +0 -1
  146. package/billing/BaselineEditor.js.map +0 -1
  147. package/billing/ModelCatalogPanel.d.ts.map +0 -1
  148. package/billing/ModelCatalogPanel.js.map +0 -1
  149. package/billing/ModelGovernanceDetail.d.ts.map +0 -1
  150. package/billing/ModelGovernanceDetail.js.map +0 -1
  151. package/billing/OperatorAccessNotice.d.ts.map +0 -1
  152. package/billing/OperatorAccessNotice.js.map +0 -1
  153. package/billing/PricingGovernanceConsole.d.ts.map +0 -1
  154. package/billing/PricingGovernanceConsole.js.map +0 -1
  155. package/billing/PricingGovernancePanel.d.ts.map +0 -1
  156. package/billing/PricingGovernancePanel.js.map +0 -1
  157. package/billing/RetireConfirm.d.ts.map +0 -1
  158. package/billing/RetireConfirm.js.map +0 -1
  159. package/billing/form-primitives.d.ts +0 -18
  160. package/billing/form-primitives.d.ts.map +0 -1
  161. package/billing/form-primitives.js.map +0 -1
  162. package/billing/governance-primitives.d.ts.map +0 -1
  163. package/billing/governance-primitives.js.map +0 -1
  164. package/billing/pricing-format.d.ts.map +0 -1
  165. package/billing/pricing-format.js.map +0 -1
  166. package/billing/useDecidePricingOverride.d.ts.map +0 -1
  167. package/billing/useDecidePricingOverride.js.map +0 -1
  168. package/billing/useModelGovernanceView.d.ts.map +0 -1
  169. package/billing/useModelGovernanceView.js.map +0 -1
  170. package/billing/useModelPricingBaselines.d.ts.map +0 -1
  171. package/billing/useModelPricingBaselines.js.map +0 -1
  172. package/billing/usePricingGovernance.d.ts.map +0 -1
  173. package/billing/usePricingGovernance.js.map +0 -1
  174. package/billing/useRetireModelPricingBaseline.d.ts.map +0 -1
  175. package/billing/useRetireModelPricingBaseline.js.map +0 -1
  176. package/billing/useUpsertModelPricingBaseline.d.ts.map +0 -1
  177. package/billing/useUpsertModelPricingBaseline.js.map +0 -1
  178. /package/{billing → pricing-governance}/BaselineEditor.d.ts +0 -0
  179. /package/{billing → pricing-governance}/ModelCatalogPanel.d.ts +0 -0
  180. /package/{billing → pricing-governance}/ModelCatalogPanel.js +0 -0
  181. /package/{billing → pricing-governance}/ModelGovernanceDetail.d.ts +0 -0
  182. /package/{billing → pricing-governance}/ModelGovernanceDetail.js +0 -0
  183. /package/{billing → pricing-governance}/OperatorAccessNotice.d.ts +0 -0
  184. /package/{billing → pricing-governance}/OperatorAccessNotice.js +0 -0
  185. /package/{billing → pricing-governance}/PricingGovernanceConsole.d.ts +0 -0
  186. /package/{billing → pricing-governance}/PricingGovernancePanel.d.ts +0 -0
  187. /package/{billing → pricing-governance}/PricingGovernancePanel.js +0 -0
  188. /package/{billing → pricing-governance}/RetireConfirm.d.ts +0 -0
  189. /package/{billing → pricing-governance}/governance-primitives.d.ts +0 -0
  190. /package/{billing → pricing-governance}/governance-primitives.js +0 -0
  191. /package/{billing → pricing-governance}/pricing-format.d.ts +0 -0
  192. /package/{billing → pricing-governance}/pricing-format.js +0 -0
  193. /package/{billing → pricing-governance}/useDecidePricingOverride.d.ts +0 -0
  194. /package/{billing → pricing-governance}/useDecidePricingOverride.js +0 -0
  195. /package/{billing → pricing-governance}/useModelGovernanceView.d.ts +0 -0
  196. /package/{billing → pricing-governance}/useModelGovernanceView.js +0 -0
  197. /package/{billing → pricing-governance}/useModelPricingBaselines.d.ts +0 -0
  198. /package/{billing → pricing-governance}/useModelPricingBaselines.js +0 -0
  199. /package/{billing → pricing-governance}/usePricingGovernance.d.ts +0 -0
  200. /package/{billing → pricing-governance}/usePricingGovernance.js +0 -0
  201. /package/{billing → pricing-governance}/useRetireModelPricingBaseline.d.ts +0 -0
  202. /package/{billing → pricing-governance}/useRetireModelPricingBaseline.js +0 -0
  203. /package/{billing → pricing-governance}/useUpsertModelPricingBaseline.d.ts +0 -0
  204. /package/{billing → pricing-governance}/useUpsertModelPricingBaseline.js +0 -0
  205. /package/src/{billing → pricing-governance}/ModelCatalogPanel.tsx +0 -0
  206. /package/src/{billing → pricing-governance}/ModelGovernanceDetail.tsx +0 -0
  207. /package/src/{billing → pricing-governance}/OperatorAccessNotice.tsx +0 -0
  208. /package/src/{billing → pricing-governance}/PricingGovernancePanel.tsx +0 -0
  209. /package/src/{billing → pricing-governance}/__tests__/ModelCatalogPanel.test.tsx +0 -0
  210. /package/src/{billing → pricing-governance}/__tests__/PricingGovernanceConsole.test.tsx +0 -0
  211. /package/src/{billing → pricing-governance}/__tests__/useModelGovernanceView.test.tsx +0 -0
  212. /package/src/{billing → pricing-governance}/governance-primitives.tsx +0 -0
  213. /package/src/{billing → pricing-governance}/pricing-format.ts +0 -0
  214. /package/src/{billing → pricing-governance}/useDecidePricingOverride.ts +0 -0
  215. /package/src/{billing → pricing-governance}/useModelGovernanceView.ts +0 -0
  216. /package/src/{billing → pricing-governance}/useModelPricingBaselines.ts +0 -0
  217. /package/src/{billing → pricing-governance}/usePricingGovernance.ts +0 -0
  218. /package/src/{billing → pricing-governance}/useRetireModelPricingBaseline.ts +0 -0
  219. /package/src/{billing → pricing-governance}/useUpsertModelPricingBaseline.ts +0 -0
@@ -137,6 +137,92 @@ describe("useCreateAgentExecution — one-call session bootstrap (sessionSpec)",
137
137
  expect(input.sessionSpec.executionTarget).toBeUndefined();
138
138
  });
139
139
 
140
+ it("passes the metadata map through on the bootstrap spec", async () => {
141
+ const { result } = renderHook(() => useCreateAgentExecution(), {
142
+ wrapper: createWrapper(makeMockClient()),
143
+ });
144
+
145
+ await act(async () => {
146
+ await result.current.create({
147
+ org: "acme",
148
+ message: "Hello",
149
+ sessionSpec: {
150
+ agentInstanceId: "ain-1",
151
+ metadata: { "acme/tenant": "t-1" },
152
+ },
153
+ });
154
+ });
155
+
156
+ const input = mockCreate.mock.calls[0][0];
157
+ expect(input.sessionSpec.metadata).toEqual({ "acme/tenant": "t-1" });
158
+ });
159
+
160
+ it("maps the typed sessionContext onto the reserved metadata key", async () => {
161
+ const { result } = renderHook(() => useCreateAgentExecution(), {
162
+ wrapper: createWrapper(makeMockClient()),
163
+ });
164
+
165
+ await act(async () => {
166
+ await result.current.create({
167
+ org: "acme",
168
+ message: "Hello",
169
+ sessionSpec: {
170
+ agentInstanceId: "ain-1",
171
+ sessionContext: "Role: platform admin",
172
+ },
173
+ });
174
+ });
175
+
176
+ const input = mockCreate.mock.calls[0][0];
177
+ expect(input.sessionSpec.metadata).toEqual({
178
+ "stigmer.ai/session-context": "Role: platform admin",
179
+ });
180
+ });
181
+
182
+ it("lets the typed sessionContext win over a raw entry under the reserved key", async () => {
183
+ const { result } = renderHook(() => useCreateAgentExecution(), {
184
+ wrapper: createWrapper(makeMockClient()),
185
+ });
186
+
187
+ await act(async () => {
188
+ await result.current.create({
189
+ org: "acme",
190
+ message: "Hello",
191
+ sessionSpec: {
192
+ agentInstanceId: "ain-1",
193
+ metadata: {
194
+ "acme/tenant": "t-1",
195
+ "stigmer.ai/session-context": "stale raw value",
196
+ },
197
+ sessionContext: "typed value",
198
+ },
199
+ });
200
+ });
201
+
202
+ const input = mockCreate.mock.calls[0][0];
203
+ expect(input.sessionSpec.metadata).toEqual({
204
+ "acme/tenant": "t-1",
205
+ "stigmer.ai/session-context": "typed value",
206
+ });
207
+ });
208
+
209
+ it("omits metadata entirely when neither field is provided", async () => {
210
+ const { result } = renderHook(() => useCreateAgentExecution(), {
211
+ wrapper: createWrapper(makeMockClient()),
212
+ });
213
+
214
+ await act(async () => {
215
+ await result.current.create({
216
+ org: "acme",
217
+ message: "Hello",
218
+ sessionSpec: { agentInstanceId: "ain-1" },
219
+ });
220
+ });
221
+
222
+ const input = mockCreate.mock.calls[0][0];
223
+ expect(input.sessionSpec.metadata).toBeUndefined();
224
+ });
225
+
140
226
  it("returns the server-assigned session id from the bootstrap response", async () => {
141
227
  mockCreate.mockResolvedValueOnce({
142
228
  metadata: { id: "aex-1" },
@@ -2,12 +2,13 @@
2
2
 
3
3
  import { useCallback, useState } from "react";
4
4
  import type { JsonObject } from "@bufbuild/protobuf";
5
- import type {
6
- AttachmentInput,
7
- EnvVarInput,
8
- McpServerUsageInput,
9
- ResourceRef,
10
- WorkspaceEntryInput,
5
+ import {
6
+ mergeSessionContext,
7
+ type AttachmentInput,
8
+ type EnvVarInput,
9
+ type McpServerUsageInput,
10
+ type ResourceRef,
11
+ type WorkspaceEntryInput,
11
12
  } from "@stigmer/sdk";
12
13
  import { useStigmer } from "../hooks.js";
13
14
  import { toError } from "../internal/toError.js";
@@ -41,6 +42,36 @@ export interface BootstrapSessionSpec {
41
42
  readonly mcpServerUsages?: McpServerUsageInput[];
42
43
  /** Skill references to enable for executions in this session. */
43
44
  readonly skillRefs?: ResourceRef[];
45
+ /**
46
+ * Custom key-value pairs stored on the created session's
47
+ * `SessionSpec.metadata`.
48
+ *
49
+ * A passthrough for embedder-owned keys (correlation IDs, tenant tags)
50
+ * and for platform-reserved `stigmer.ai/*` keys set explicitly. For the
51
+ * common case — standing user context injected into the agent's prompt —
52
+ * prefer the typed {@link sessionContext} field, which maps onto the
53
+ * reserved `stigmer.ai/session-context` key and wins over a raw entry
54
+ * under that key when both are provided.
55
+ */
56
+ readonly metadata?: Record<string, string>;
57
+ /**
58
+ * Standing, per-user context the agent receives on every turn but the
59
+ * conversation UI never renders — who the caller is, their experience
60
+ * level, their standing instructions (stigmer/stigmer#286).
61
+ *
62
+ * Stored on the created session's `SessionSpec.metadata` under
63
+ * `stigmer.ai/session-context`; the agent runner injects it into the
64
+ * system prompt as already-known background, so agents can greet the
65
+ * user by name and calibrate depth/defaults from the first turn without
66
+ * a visible context preamble.
67
+ *
68
+ * Personalization, not authorization: anyone who can create the session
69
+ * can set this (the same trust level as authoring the first message).
70
+ * Hidden from the conversation thread, not from the API — `session.get`
71
+ * returns it, so never put secrets here; secrets belong in `runtimeEnv`
72
+ * or Environment resources. Large values bloat every prompt.
73
+ */
74
+ readonly sessionContext?: string;
44
75
  /** Execution harness. Immutable after the first execution runs. */
45
76
  readonly harness?: HarnessOption;
46
77
  /** Where session activities execute. Immutable after the first execution runs. */
@@ -293,6 +324,10 @@ export function useCreateAgentExecution(): UseCreateAgentExecutionReturn {
293
324
  workspaceEntries: input.sessionSpec.workspaceEntries,
294
325
  mcpServerUsages: input.sessionSpec.mcpServerUsages,
295
326
  skillRefs: input.sessionSpec.skillRefs,
327
+ metadata: mergeSessionContext(
328
+ input.sessionSpec.metadata,
329
+ input.sessionSpec.sessionContext,
330
+ ),
296
331
  harness: input.sessionSpec.harness
297
332
  ? toProtoHarness(input.sessionSpec.harness)
298
333
  : undefined,
package/src/index.ts CHANGED
@@ -909,21 +909,16 @@ export type {
909
909
  OrgSwitcherProps,
910
910
  } from "./organization/index.js";
911
911
 
912
- // Billing — data hooks, behavior hooks, styled components, catalog, and formatting utilities
912
+ // Billing — customer-facing data hooks, behavior hooks, styled components,
913
+ // catalog, and formatting utilities
913
914
  export {
914
915
  useBillingAccount,
915
916
  useCreditLedger,
916
917
  useBillingUsageReport,
917
918
  useCustomerModelPricing,
918
- usePricingGovernance,
919
- useModelPricingBaselines,
920
- useModelGovernanceView,
921
919
  useCreateCheckoutSession,
922
920
  useCreateBillingPortalSession,
923
921
  useSetAutoRechargeConfig,
924
- useDecidePricingOverride,
925
- useUpsertModelPricingBaseline,
926
- useRetireModelPricingBaseline,
927
922
  BillingSection,
928
923
  CreditBalanceCard,
929
924
  PaymentMethodCard,
@@ -931,9 +926,6 @@ export {
931
926
  CreditPackGrid,
932
927
  CreditLedgerTable,
933
928
  LowBalanceBanner,
934
- PricingGovernancePanel,
935
- ModelCatalogPanel,
936
- PricingGovernanceConsole,
937
929
  CREDIT_PACKS,
938
930
  formatPackPrice,
939
931
  formatCreditCount,
@@ -950,23 +942,11 @@ export type {
950
942
  UseCreditLedgerOptions,
951
943
  UseBillingUsageReportReturn,
952
944
  UseCustomerModelPricingReturn,
953
- UsePricingGovernanceReturn,
954
- UseModelPricingBaselinesOptions,
955
- UseModelPricingBaselinesReturn,
956
- GovernanceFlow,
957
- ModelGovernanceRow,
958
- UseModelGovernanceViewReturn,
959
945
  CreateCheckoutSessionInput,
960
946
  UseCreateCheckoutSessionReturn,
961
947
  UseCreateBillingPortalSessionReturn,
962
948
  SetAutoRechargeConfigInput,
963
949
  UseSetAutoRechargeConfigReturn,
964
- DecidePricingOverrideInput,
965
- UseDecidePricingOverrideReturn,
966
- UpsertModelPricingBaselineInput,
967
- UseUpsertModelPricingBaselineReturn,
968
- RetireModelPricingBaselineInput,
969
- UseRetireModelPricingBaselineReturn,
970
950
  BillingSectionProps,
971
951
  CreditBalanceCardProps,
972
952
  PaymentMethodCardProps,
@@ -974,12 +954,40 @@ export type {
974
954
  CreditPackGridProps,
975
955
  CreditLedgerTableProps,
976
956
  LowBalanceBannerProps,
957
+ CreditPackInfo,
958
+ } from "./billing/index.js";
959
+
960
+ // Pricing governance — platform-operator authoring of the model registry
961
+ // baseline and pricing-override sign-offs (gated on can_manage_model_pricing)
962
+ export {
963
+ usePricingGovernance,
964
+ useModelPricingBaselines,
965
+ useModelGovernanceView,
966
+ useDecidePricingOverride,
967
+ useUpsertModelPricingBaseline,
968
+ useRetireModelPricingBaseline,
969
+ PricingGovernancePanel,
970
+ ModelCatalogPanel,
971
+ PricingGovernanceConsole,
972
+ } from "./pricing-governance/index.js";
973
+ export type {
974
+ UsePricingGovernanceReturn,
975
+ UseModelPricingBaselinesOptions,
976
+ UseModelPricingBaselinesReturn,
977
+ GovernanceFlow,
978
+ ModelGovernanceRow,
979
+ UseModelGovernanceViewReturn,
980
+ DecidePricingOverrideInput,
981
+ UseDecidePricingOverrideReturn,
982
+ UpsertModelPricingBaselineInput,
983
+ UseUpsertModelPricingBaselineReturn,
984
+ RetireModelPricingBaselineInput,
985
+ UseRetireModelPricingBaselineReturn,
977
986
  PricingGovernancePanelProps,
978
987
  ModelCatalogPanelProps,
979
988
  PricingGovernanceConsoleProps,
980
989
  PricingGovernanceTab,
981
- CreditPackInfo,
982
- } from "./billing/index.js";
990
+ } from "./pricing-governance/index.js";
983
991
 
984
992
  // Cursor accounts — platform-operator management of managed Cursor teams
985
993
  // (admin keys, member execution keys, org assignments, roster/spend)
@@ -3,12 +3,12 @@
3
3
  import { cn } from "@stigmer/theme";
4
4
 
5
5
  // ---------------------------------------------------------------------------
6
- // Shared form primitives for the operator pricing surfaces (BaselineEditor,
7
- // RetireConfirm, the console's search inputs). Internal not exported
8
- // from the billing barrel.
6
+ // Shared form primitives for the operator consoles (pricing-governance
7
+ // editors and search inputs, cursor-accounts editor and key forms).
8
+ // Internal — never exported from the package barrel.
9
9
  // ---------------------------------------------------------------------------
10
10
 
11
- /** Standard text-input styling for the pricing surfaces. */
11
+ /** Standard text-input styling for the operator consoles. */
12
12
  export const INPUT_CLASSES = cn(
13
13
  "w-full rounded-md border border-input bg-background px-2.5 py-1.5 text-xs text-foreground",
14
14
  "placeholder:text-muted-foreground",
@@ -38,31 +38,3 @@ export function Field({
38
38
  </label>
39
39
  );
40
40
  }
41
-
42
- /** Dollar-rate input field (decimal keypad, "$ per million tokens"). */
43
- export function RateField({
44
- label,
45
- value,
46
- placeholder,
47
- disabled,
48
- onChange,
49
- }: {
50
- readonly label: string;
51
- readonly value: string;
52
- readonly placeholder?: string;
53
- readonly disabled: boolean;
54
- readonly onChange: (value: string) => void;
55
- }) {
56
- return (
57
- <Field label={label}>
58
- <input
59
- className={INPUT_CLASSES}
60
- inputMode="decimal"
61
- value={value}
62
- onChange={(e) => onChange(e.target.value)}
63
- placeholder={placeholder ?? "0.00"}
64
- disabled={disabled}
65
- />
66
- </Field>
67
- );
68
- }
@@ -10,7 +10,7 @@ import {
10
10
  type ModelPricingBaseline,
11
11
  } from "@stigmer/protos/ai/stigmer/billing/v1/model_pricing_baseline_pb";
12
12
  import { Button } from "../button/index.js";
13
- import { Field, INPUT_CLASSES, RateField } from "./form-primitives.js";
13
+ import { Field, INPUT_CLASSES } from "../internal/form-primitives.js";
14
14
  import {
15
15
  ZERO,
16
16
  dollarsToMicros,
@@ -23,10 +23,43 @@ import {
23
23
  // explicit old→new rate confirmation step (a billing-critical edit is never
24
24
  // submitted without the operator seeing exactly which rates move).
25
25
  //
26
- // Internal to the billing module: rendered by PricingGovernanceConsole and
27
- // ModelCatalogPanel, never exported from the barrel.
26
+ // Internal to the pricing-governance module: rendered by
27
+ // PricingGovernanceConsole and ModelCatalogPanel, never exported from the
28
+ // barrel.
28
29
  // ---------------------------------------------------------------------------
29
30
 
31
+ /**
32
+ * Dollar-rate input field (decimal keypad, "$ per million tokens").
33
+ * File-local: this is the editor's own composition of the shared form
34
+ * primitives, used nowhere else.
35
+ */
36
+ function RateField({
37
+ label,
38
+ value,
39
+ placeholder,
40
+ disabled,
41
+ onChange,
42
+ }: {
43
+ readonly label: string;
44
+ readonly value: string;
45
+ readonly placeholder?: string;
46
+ readonly disabled: boolean;
47
+ readonly onChange: (value: string) => void;
48
+ }) {
49
+ return (
50
+ <Field label={label}>
51
+ <input
52
+ className={INPUT_CLASSES}
53
+ inputMode="decimal"
54
+ value={value}
55
+ onChange={(e) => onChange(e.target.value)}
56
+ placeholder={placeholder ?? "0.00"}
57
+ disabled={disabled}
58
+ />
59
+ </Field>
60
+ );
61
+ }
62
+
30
63
  // ---------------------------------------------------------------------------
31
64
  // Form model — strings while editing, converted + validated on submit.
32
65
  // Validation mirrors the protovalidate rules on ModelPricingBaseline so
@@ -11,7 +11,7 @@ import { RetireConfirm } from "./RetireConfirm.js";
11
11
  import { ModelGovernanceDetail } from "./ModelGovernanceDetail.js";
12
12
  import { OperatorAccessNotice } from "./OperatorAccessNotice.js";
13
13
  import { GovernanceBadge, PendingOverrideCard, RateCell } from "./governance-primitives.js";
14
- import { INPUT_CLASSES } from "./form-primitives.js";
14
+ import { INPUT_CLASSES } from "../internal/form-primitives.js";
15
15
  import { ZERO } from "./pricing-format.js";
16
16
  import { useDecidePricingOverride } from "./useDecidePricingOverride.js";
17
17
  import { useRetireModelPricingBaseline } from "./useRetireModelPricingBaseline.js";
@@ -4,7 +4,7 @@ import { useState } from "react";
4
4
  import { getUserMessage } from "@stigmer/sdk";
5
5
  import type { ModelPricingBaseline } from "@stigmer/protos/ai/stigmer/billing/v1/model_pricing_baseline_pb";
6
6
  import { Button } from "../button/index.js";
7
- import { INPUT_CLASSES } from "./form-primitives.js";
7
+ import { INPUT_CLASSES } from "../internal/form-primitives.js";
8
8
 
9
9
  // ---------------------------------------------------------------------------
10
10
  // RetireConfirm — typed confirmation for retiring a catalog entry (a
@@ -0,0 +1,50 @@
1
+ // Pricing governance — the platform-operator surface for the model
2
+ // registry baseline and the reconciliation-driven pricing feedback loop.
3
+ // Every export here is gated on `can_manage_model_pricing` on
4
+ // `platform:stigmer`; nothing in this module is customer-facing (customer
5
+ // billing lives in ../billing). The module boundary is deliberate: the
6
+ // docs generator excludes operator-only domains wholesale, so operator
7
+ // exports must never be mixed into customer modules.
8
+
9
+ // Data hooks
10
+ export { usePricingGovernance } from "./usePricingGovernance.js";
11
+ export type { UsePricingGovernanceReturn } from "./usePricingGovernance.js";
12
+ export { useModelPricingBaselines } from "./useModelPricingBaselines.js";
13
+ export type {
14
+ UseModelPricingBaselinesOptions,
15
+ UseModelPricingBaselinesReturn,
16
+ } from "./useModelPricingBaselines.js";
17
+ export { useModelGovernanceView } from "./useModelGovernanceView.js";
18
+ export type {
19
+ GovernanceFlow,
20
+ ModelGovernanceRow,
21
+ UseModelGovernanceViewReturn,
22
+ } from "./useModelGovernanceView.js";
23
+
24
+ // Behavior hooks
25
+ export { useDecidePricingOverride } from "./useDecidePricingOverride.js";
26
+ export type {
27
+ DecidePricingOverrideInput,
28
+ UseDecidePricingOverrideReturn,
29
+ } from "./useDecidePricingOverride.js";
30
+ export { useUpsertModelPricingBaseline } from "./useUpsertModelPricingBaseline.js";
31
+ export type {
32
+ UpsertModelPricingBaselineInput,
33
+ UseUpsertModelPricingBaselineReturn,
34
+ } from "./useUpsertModelPricingBaseline.js";
35
+ export { useRetireModelPricingBaseline } from "./useRetireModelPricingBaseline.js";
36
+ export type {
37
+ RetireModelPricingBaselineInput,
38
+ UseRetireModelPricingBaselineReturn,
39
+ } from "./useRetireModelPricingBaseline.js";
40
+
41
+ // Styled components
42
+ export { PricingGovernancePanel } from "./PricingGovernancePanel.js";
43
+ export type { PricingGovernancePanelProps } from "./PricingGovernancePanel.js";
44
+ export { ModelCatalogPanel } from "./ModelCatalogPanel.js";
45
+ export type { ModelCatalogPanelProps } from "./ModelCatalogPanel.js";
46
+ export { PricingGovernanceConsole } from "./PricingGovernanceConsole.js";
47
+ export type {
48
+ PricingGovernanceConsoleProps,
49
+ PricingGovernanceTab,
50
+ } from "./PricingGovernanceConsole.js";
@@ -193,6 +193,100 @@ describe("useCreateSession", () => {
193
193
  expect(callArg.executionTarget).toBeUndefined();
194
194
  });
195
195
 
196
+ describe("session metadata and sessionContext", () => {
197
+ it("passes the metadata map through to stigmer.session.create()", async () => {
198
+ const create = vi.fn().mockResolvedValue({ metadata: { id: "ses-md" } });
199
+ const client = createMockStigmer({ create });
200
+
201
+ const { result } = renderHook(() => useCreateSession(), {
202
+ wrapper: wrapper(client),
203
+ });
204
+
205
+ await act(async () => {
206
+ await result.current.create({
207
+ org: "acme",
208
+ agentInstanceId: "ain-123",
209
+ metadata: { "acme/tenant": "t-1" },
210
+ });
211
+ });
212
+
213
+ expect(create).toHaveBeenCalledWith(
214
+ expect.objectContaining({
215
+ metadata: { "acme/tenant": "t-1" },
216
+ }),
217
+ );
218
+ });
219
+
220
+ it("maps the typed sessionContext onto the reserved metadata key", async () => {
221
+ const create = vi.fn().mockResolvedValue({ metadata: { id: "ses-sc" } });
222
+ const client = createMockStigmer({ create });
223
+
224
+ const { result } = renderHook(() => useCreateSession(), {
225
+ wrapper: wrapper(client),
226
+ });
227
+
228
+ await act(async () => {
229
+ await result.current.create({
230
+ org: "acme",
231
+ agentInstanceId: "ain-123",
232
+ sessionContext: "Role: platform admin",
233
+ });
234
+ });
235
+
236
+ expect(create).toHaveBeenCalledWith(
237
+ expect.objectContaining({
238
+ metadata: { "stigmer.ai/session-context": "Role: platform admin" },
239
+ }),
240
+ );
241
+ });
242
+
243
+ it("lets the typed sessionContext win over a raw entry under the reserved key", async () => {
244
+ const create = vi.fn().mockResolvedValue({ metadata: { id: "ses-both" } });
245
+ const client = createMockStigmer({ create });
246
+
247
+ const { result } = renderHook(() => useCreateSession(), {
248
+ wrapper: wrapper(client),
249
+ });
250
+
251
+ await act(async () => {
252
+ await result.current.create({
253
+ org: "acme",
254
+ agentInstanceId: "ain-123",
255
+ metadata: {
256
+ "acme/tenant": "t-1",
257
+ "stigmer.ai/session-context": "stale raw value",
258
+ },
259
+ sessionContext: "typed value",
260
+ });
261
+ });
262
+
263
+ expect(create).toHaveBeenCalledWith(
264
+ expect.objectContaining({
265
+ metadata: {
266
+ "acme/tenant": "t-1",
267
+ "stigmer.ai/session-context": "typed value",
268
+ },
269
+ }),
270
+ );
271
+ });
272
+
273
+ it("omits metadata entirely when neither field is provided", async () => {
274
+ const create = vi.fn().mockResolvedValue({ metadata: { id: "ses-none" } });
275
+ const client = createMockStigmer({ create });
276
+
277
+ const { result } = renderHook(() => useCreateSession(), {
278
+ wrapper: wrapper(client),
279
+ });
280
+
281
+ await act(async () => {
282
+ await result.current.create({ org: "acme", agentInstanceId: "ain-123" });
283
+ });
284
+
285
+ const callArg = create.mock.calls[0][0];
286
+ expect(callArg.metadata).toBeUndefined();
287
+ });
288
+ });
289
+
196
290
  it("clearError resets the error state", async () => {
197
291
  const create = vi.fn().mockRejectedValue(new Error("fail"));
198
292
  const client = createMockStigmer({ create });
@@ -334,6 +334,39 @@ describe("useNewSessionFlow", () => {
334
334
  expect(execInput.sessionSpec.harness).toBe("cursor");
335
335
  });
336
336
 
337
+ it("forwards metadata and sessionContext verbatim in the sessionSpec", async () => {
338
+ // The typed-wins merge onto the reserved key happens downstream in
339
+ // useCreateAgentExecution (covered by its own tests); the flow's job
340
+ // is faithful forwarding.
341
+ const opts = {
342
+ ...defaultOptions(),
343
+ metadata: { "acme/tenant": "t-1" },
344
+ sessionContext: "Role: platform admin",
345
+ };
346
+ const { result } = renderHook(() => useNewSessionFlow(opts), { wrapper: createWrapper() });
347
+
348
+ await act(async () => {
349
+ await result.current.submit("Hello");
350
+ });
351
+
352
+ const execInput = mockCreateExecution.mock.calls[0][0];
353
+ expect(execInput.sessionSpec.metadata).toEqual({ "acme/tenant": "t-1" });
354
+ expect(execInput.sessionSpec.sessionContext).toBe("Role: platform admin");
355
+ });
356
+
357
+ it("leaves metadata and sessionContext undefined when not provided", async () => {
358
+ const opts = defaultOptions();
359
+ const { result } = renderHook(() => useNewSessionFlow(opts), { wrapper: createWrapper() });
360
+
361
+ await act(async () => {
362
+ await result.current.submit("Hello");
363
+ });
364
+
365
+ const execInput = mockCreateExecution.mock.calls[0][0];
366
+ expect(execInput.sessionSpec.metadata).toBeUndefined();
367
+ expect(execInput.sessionSpec.sessionContext).toBeUndefined();
368
+ });
369
+
337
370
  it("calls onSessionCreated with the server-assigned session id", async () => {
338
371
  const opts = defaultOptions();
339
372
  const { result } = renderHook(() => useNewSessionFlow(opts), { wrapper: createWrapper() });
@@ -3,6 +3,7 @@
3
3
  import { useCallback, useState } from "react";
4
4
  import {
5
5
  PENDING_SUBJECT,
6
+ mergeSessionContext,
6
7
  type McpServerUsageInput,
7
8
  type ResourceRef,
8
9
  type WorkspaceEntryInput,
@@ -25,6 +26,34 @@ export interface SharedSessionFields {
25
26
  readonly mcpServerUsages?: McpServerUsageInput[];
26
27
  /** Skill references to enable for executions in this session. */
27
28
  readonly skillRefs?: ResourceRef[];
29
+ /**
30
+ * Custom key-value pairs stored on `SessionSpec.metadata`.
31
+ *
32
+ * A passthrough for embedder-owned keys (correlation IDs, tenant tags)
33
+ * and for platform-reserved `stigmer.ai/*` keys set explicitly. For the
34
+ * common case — standing user context injected into the agent's prompt —
35
+ * prefer the typed {@link sessionContext} field, which maps onto the
36
+ * reserved `stigmer.ai/session-context` key and wins over a raw entry
37
+ * under that key when both are provided.
38
+ */
39
+ readonly metadata?: Record<string, string>;
40
+ /**
41
+ * Standing, per-user context the agent receives on every turn but the
42
+ * conversation UI never renders — who the caller is, their experience
43
+ * level, their standing instructions (stigmer/stigmer#286).
44
+ *
45
+ * Stored on `SessionSpec.metadata` under `stigmer.ai/session-context`;
46
+ * the agent runner injects it into the system prompt as already-known
47
+ * background, so agents can greet the user by name and calibrate
48
+ * depth/defaults from the first turn without a visible context preamble.
49
+ *
50
+ * Personalization, not authorization: anyone who can create the session
51
+ * can set this (the same trust level as authoring the first message).
52
+ * Hidden from the conversation thread, not from the API — `session.get`
53
+ * returns it, so never put secrets here; secrets belong in `runtimeEnv`
54
+ * or Environment resources. Large values bloat every prompt.
55
+ */
56
+ readonly sessionContext?: string;
28
57
  /**
29
58
  * Execution harness for this session.
30
59
  *
@@ -172,6 +201,7 @@ export function useCreateSession(): UseCreateSessionReturn {
172
201
  workspaceEntries: input.workspaceEntries,
173
202
  mcpServerUsages: input.mcpServerUsages,
174
203
  skillRefs: input.skillRefs,
204
+ metadata: mergeSessionContext(input.metadata, input.sessionContext),
175
205
  agentInstanceId: resolvedInstanceId,
176
206
  harness: input.harness ? toProtoHarness(input.harness) : undefined,
177
207
  executionTarget: resolvedTarget