@stigmer/react 0.4.5 → 0.4.6

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 (42) hide show
  1. package/index.d.ts +2 -2
  2. package/index.d.ts.map +1 -1
  3. package/index.js +1 -1
  4. package/index.js.map +1 -1
  5. package/models/ModelRegistryContext.d.ts +21 -0
  6. package/models/ModelRegistryContext.d.ts.map +1 -0
  7. package/models/ModelRegistryContext.js +22 -0
  8. package/models/ModelRegistryContext.js.map +1 -0
  9. package/models/ModelSelector.js +3 -3
  10. package/models/ModelSelector.js.map +1 -1
  11. package/models/__tests__/useModelRegistry.test.js +127 -32
  12. package/models/__tests__/useModelRegistry.test.js.map +1 -1
  13. package/models/index.d.ts +3 -1
  14. package/models/index.d.ts.map +1 -1
  15. package/models/index.js +2 -1
  16. package/models/index.js.map +1 -1
  17. package/models/registry.d.ts +20 -12
  18. package/models/registry.d.ts.map +1 -1
  19. package/models/registry.js +51 -27
  20. package/models/registry.js.map +1 -1
  21. package/models/useModelRegistry.d.ts +11 -3
  22. package/models/useModelRegistry.d.ts.map +1 -1
  23. package/models/useModelRegistry.js +13 -5
  24. package/models/useModelRegistry.js.map +1 -1
  25. package/package.json +4 -4
  26. package/provider.d.ts.map +1 -1
  27. package/provider.js +42 -1
  28. package/provider.js.map +1 -1
  29. package/session/__tests__/useNewSessionFlow.test.js +32 -18
  30. package/session/__tests__/useNewSessionFlow.test.js.map +1 -1
  31. package/session/__tests__/usePersistedModel.test.js +26 -12
  32. package/session/__tests__/usePersistedModel.test.js.map +1 -1
  33. package/src/index.ts +4 -1
  34. package/src/models/ModelRegistryContext.ts +32 -0
  35. package/src/models/ModelSelector.tsx +4 -4
  36. package/src/models/__tests__/useModelRegistry.test.tsx +150 -41
  37. package/src/models/index.ts +3 -1
  38. package/src/models/registry.ts +51 -30
  39. package/src/models/useModelRegistry.ts +18 -7
  40. package/src/provider.tsx +58 -8
  41. package/src/session/__tests__/useNewSessionFlow.test.tsx +39 -18
  42. package/src/session/__tests__/usePersistedModel.test.tsx +33 -12
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/models/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,QAAQ,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAG3J,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/models/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,QAAQ,EAAE,aAAa,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAGlL,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEvF,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC"}
@@ -1,11 +1,12 @@
1
1
  /**
2
2
  * Model registry — UI-relevant metadata for all platform-supported LLM models.
3
3
  *
4
- * Reads from the unified JSON registry at backend/libs/model-registry.json,
5
- * which is the single source of truth for model IDs, display names, pricing,
6
- * and cost tiers across all harnesses and runtimes.
4
+ * Fetches from the public model registry API endpoint at runtime and caches
5
+ * the result in the {@link StigmerProvider} context. This eliminates the
6
+ * static JSON file that previously shipped in the npm package.
7
7
  *
8
- * Update it with: @update-model-registry
8
+ * Platform consumers (React SDK, cursor-runner, graphton) all fetch from the
9
+ * same endpoint, each with their own local TTL cache.
9
10
  */
10
11
  import type { HarnessOption } from "./harness";
11
12
  /**
@@ -28,14 +29,14 @@ export type SpeedTier = "fastest" | "fast" | "balanced" | "slow";
28
29
  /**
29
30
  * LLM provider identifier. Each provider maps to a distinct inference
30
31
  * backend (or intermediary, in the case of Cursor-served third-party
31
- * models). The {@link MODEL_REGISTRY} uses this for grouping in the
32
+ * models). The model registry uses this for grouping in the
32
33
  * "Show All" expanded view.
33
34
  */
34
35
  export type Provider = "anthropic" | "openai" | "google" | "xai" | "cursor" | "moonshot" | "ollama";
35
36
  /**
36
37
  * Providers whose models should be hidden from the UI.
37
38
  *
38
- * The model entries themselves stay in MODEL_REGISTRY so backend
39
+ * The model entries themselves stay in the registry so backend
39
40
  * compatibility is preserved. The useModelRegistry hook filters
40
41
  * them out before anything reaches a component.
41
42
  *
@@ -106,13 +107,20 @@ export interface ParsedModelKey {
106
107
  */
107
108
  export declare function parseModelKey(key: string): ParsedModelKey | undefined;
108
109
  /**
109
- * Static catalog of all platform-supported LLM models, loaded from the
110
- * unified JSON registry.
110
+ * Parse raw registry JSON (from the API or a static file) into `ModelInfo[]`.
111
111
  *
112
- * {@link useModelRegistry} filters out disabled providers and provides
113
- * lookup helpers on top of this list.
112
+ * Expects the shape `{ models: RegistryJsonEntry[] }`. Filters out comment
113
+ * entries and invalid rows, then maps to the `ModelInfo` interface.
114
114
  */
115
- export declare const MODEL_REGISTRY: readonly ModelInfo[];
115
+ export declare function parseRegistryJson(data: unknown): ModelInfo[];
116
+ /**
117
+ * Fetch the model registry from the authenticated API endpoint.
118
+ *
119
+ * @param apiUrl - Base URL of the Stigmer Cloud API (e.g. `https://api.stigmer.ai`)
120
+ * @param token - Bearer token for authentication (from `client.getAuthCredential()`)
121
+ * @returns Parsed `ModelInfo[]`.
122
+ */
123
+ export declare function fetchModelRegistry(apiUrl: string, token: string | null): Promise<ModelInfo[]>;
116
124
  /**
117
125
  * Model ID used when no user preference is set (native harness).
118
126
  *
@@ -146,7 +154,7 @@ export interface DefaultModelResolution {
146
154
  * Future phases will add org-level and agent-level defaults between
147
155
  * user preference and harness default.
148
156
  */
149
- export declare function resolveDefaultModelId(harness: HarnessOption, options?: {
157
+ export declare function resolveDefaultModelId(harness: HarnessOption, models: readonly ModelInfo[], options?: {
150
158
  userPreference?: string;
151
159
  orgDefault?: string;
152
160
  agentDefault?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/models/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG/C;;;;;;GAMG;AACH,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC;AAE1D;;;;;;;GAOG;AACH,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;AAEjE;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAChB,WAAW,GACX,QAAQ,GACR,QAAQ,GACR,KAAK,GACL,QAAQ,GACR,UAAU,GACV,QAAQ,CAAC;AAEb;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,QAAQ,CAEnD,CAAC;AAEH;;;;;;;;;;GAUG;AACH,MAAM,WAAW,SAAS;IACxB,gFAAgF;IAChF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,2CAA2C;IAC3C,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,qDAAqD;IACrD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,mFAAmF;IACnF,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,kFAAkF;IAClF,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,+DAA+D;IAC/D,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,gDAAgD;IAChD,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,yBAAyB,EAAE,MAAM,CAAC;IAC3C,QAAQ,CAAC,wBAAwB,EAAE,MAAM,CAAC;CAC3C;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAExE;AAED,yDAAyD;AACzD,MAAM,WAAW,cAAc;IAC7B,2CAA2C;IAC3C,OAAO,EAAE,aAAa,CAAC;IACvB,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAMrE;AAsCD;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,SAAS,EAa1C,CAAC;AAEN;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,sBAAsB,CAAC;AAEpD,uFAAuF;AACvF,eAAO,MAAM,uBAAuB,YAAY,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAC1B,iBAAiB,GACjB,aAAa,GACb,eAAe,GACf,iBAAiB,GACjB,mBAAmB,CAAC;AAExB,8CAA8C;AAC9C,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;CACrC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,aAAa,EACtB,OAAO,CAAC,EAAE;IACR,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GACA,sBAAsB,CA6BxB"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/models/registry.ts"],"names":[],"mappings":"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"}
@@ -1,17 +1,17 @@
1
1
  /**
2
2
  * Model registry — UI-relevant metadata for all platform-supported LLM models.
3
3
  *
4
- * Reads from the unified JSON registry at backend/libs/model-registry.json,
5
- * which is the single source of truth for model IDs, display names, pricing,
6
- * and cost tiers across all harnesses and runtimes.
4
+ * Fetches from the public model registry API endpoint at runtime and caches
5
+ * the result in the {@link StigmerProvider} context. This eliminates the
6
+ * static JSON file that previously shipped in the npm package.
7
7
  *
8
- * Update it with: @update-model-registry
8
+ * Platform consumers (React SDK, cursor-runner, graphton) all fetch from the
9
+ * same endpoint, each with their own local TTL cache.
9
10
  */
10
- import registryData from "../../data/model-registry.json";
11
11
  /**
12
12
  * Providers whose models should be hidden from the UI.
13
13
  *
14
- * The model entries themselves stay in MODEL_REGISTRY so backend
14
+ * The model entries themselves stay in the registry so backend
15
15
  * compatibility is preserved. The useModelRegistry hook filters
16
16
  * them out before anything reaches a component.
17
17
  *
@@ -53,24 +53,48 @@ function isModelEntry(entry) {
53
53
  typeof entry.costTier === "string" && VALID_COST_TIERS.has(entry.costTier));
54
54
  }
55
55
  /**
56
- * Static catalog of all platform-supported LLM models, loaded from the
57
- * unified JSON registry.
56
+ * Parse raw registry JSON (from the API or a static file) into `ModelInfo[]`.
58
57
  *
59
- * {@link useModelRegistry} filters out disabled providers and provides
60
- * lookup helpers on top of this list.
58
+ * Expects the shape `{ models: RegistryJsonEntry[] }`. Filters out comment
59
+ * entries and invalid rows, then maps to the `ModelInfo` interface.
61
60
  */
62
- export const MODEL_REGISTRY = registryData.models
63
- .filter(isModelEntry)
64
- .map((m) => ({
65
- modelId: m.id,
66
- provider: m.provider,
67
- displayName: m.displayName,
68
- shortDescription: m.shortDescription ?? "",
69
- speedTier: (VALID_SPEED_TIERS.has(m.speedTier ?? "") ? m.speedTier : "fast"),
70
- costTier: m.costTier,
71
- harness: m.harness,
72
- featured: m.featured ?? false,
73
- }));
61
+ export function parseRegistryJson(data) {
62
+ if (!data || typeof data !== "object")
63
+ return [];
64
+ const models = data.models;
65
+ if (!Array.isArray(models))
66
+ return [];
67
+ return models
68
+ .filter(isModelEntry)
69
+ .map((m) => ({
70
+ modelId: m.id,
71
+ provider: m.provider,
72
+ displayName: m.displayName,
73
+ shortDescription: m.shortDescription ?? "",
74
+ speedTier: (VALID_SPEED_TIERS.has(m.speedTier ?? "") ? m.speedTier : "fast"),
75
+ costTier: m.costTier,
76
+ harness: m.harness,
77
+ featured: m.featured ?? false,
78
+ }));
79
+ }
80
+ /**
81
+ * Fetch the model registry from the authenticated API endpoint.
82
+ *
83
+ * @param apiUrl - Base URL of the Stigmer Cloud API (e.g. `https://api.stigmer.ai`)
84
+ * @param token - Bearer token for authentication (from `client.getAuthCredential()`)
85
+ * @returns Parsed `ModelInfo[]`.
86
+ */
87
+ export async function fetchModelRegistry(apiUrl, token) {
88
+ const headers = {};
89
+ if (token) {
90
+ headers["Authorization"] = `Bearer ${token}`;
91
+ }
92
+ const res = await fetch(`${apiUrl}/v1/proxy/model-registry`, { headers });
93
+ if (!res.ok)
94
+ throw new Error(`Model registry fetch failed: ${res.status}`);
95
+ const data = await res.json();
96
+ return parseRegistryJson(data);
97
+ }
74
98
  /**
75
99
  * Model ID used when no user preference is set (native harness).
76
100
  *
@@ -92,23 +116,23 @@ export const DEFAULT_CURSOR_MODEL_ID = "default";
92
116
  * Future phases will add org-level and agent-level defaults between
93
117
  * user preference and harness default.
94
118
  */
95
- export function resolveDefaultModelId(harness, options) {
119
+ export function resolveDefaultModelId(harness, models, options) {
96
120
  if (options?.userPreference) {
97
- const model = MODEL_REGISTRY.find((m) => m.harness === harness && m.modelId === options.userPreference);
121
+ const model = models.find((m) => m.harness === harness && m.modelId === options.userPreference);
98
122
  if (model)
99
123
  return { modelId: model.modelId, source: "user_preference" };
100
124
  }
101
125
  if (options?.orgDefault) {
102
- const model = MODEL_REGISTRY.find((m) => m.harness === harness && m.modelId === options.orgDefault);
126
+ const model = models.find((m) => m.harness === harness && m.modelId === options.orgDefault);
103
127
  if (model)
104
128
  return { modelId: model.modelId, source: "org_default" };
105
129
  }
106
130
  if (options?.agentDefault) {
107
- const model = MODEL_REGISTRY.find((m) => m.harness === harness && m.modelId === options.agentDefault);
131
+ const model = models.find((m) => m.harness === harness && m.modelId === options.agentDefault);
108
132
  if (model)
109
133
  return { modelId: model.modelId, source: "agent_default" };
110
134
  }
111
- const featured = MODEL_REGISTRY.find((m) => m.harness === harness && m.featured);
135
+ const featured = models.find((m) => m.harness === harness && m.featured);
112
136
  if (featured)
113
137
  return { modelId: featured.modelId, source: "harness_default" };
114
138
  const fallbackId = harness === "cursor" ? DEFAULT_CURSOR_MODEL_ID : DEFAULT_MODEL_ID;
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/models/registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/models/registry.ts"],"names":[],"mappings":"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"}
@@ -17,8 +17,8 @@ export interface UseModelRegistryReturn {
17
17
  readonly models: readonly ModelInfo[];
18
18
  /** Models grouped by provider for sectioned rendering. */
19
19
  readonly byProvider: ReadonlyMap<Provider, readonly ModelInfo[]>;
20
- /** The platform default model for the current mode. */
21
- readonly defaultModel: ModelInfo;
20
+ /** The platform default model for the current mode. `undefined` while the registry is loading. */
21
+ readonly defaultModel: ModelInfo | undefined;
22
22
  /**
23
23
  * Look up a single model by its `modelId`.
24
24
  *
@@ -37,6 +37,10 @@ export interface UseModelRegistryReturn {
37
37
  * Always unambiguous, even in unified mode.
38
38
  */
39
39
  readonly getByKey: (key: string) => ModelInfo | undefined;
40
+ /** `true` while the model registry is being fetched from the API. */
41
+ readonly isLoading: boolean;
42
+ /** Non-null if the API fetch failed. Models will be empty in this case. */
43
+ readonly error: Error | null;
40
44
  }
41
45
  /**
42
46
  * Data hook that exposes the platform model registry with grouping
@@ -46,6 +50,10 @@ export interface UseModelRegistryReturn {
46
50
  * who want full control over rendering import this hook and build
47
51
  * their own UI.
48
52
  *
53
+ * The model data is fetched from the public model registry API by
54
+ * {@link StigmerProvider} and cached in context. During loading,
55
+ * `isLoading` is `true` and `models` is empty.
56
+ *
49
57
  * **Modes:**
50
58
  * - `options.harness === "cursor"` — Cursor-harness models only
51
59
  * - `options.harness === "native"` — native models, excluding disabled providers
@@ -54,7 +62,7 @@ export interface UseModelRegistryReturn {
54
62
  * @example
55
63
  * ```tsx
56
64
  * // Unified mode — flat picker with all models
57
- * const { featured, models, getByKey } = useModelRegistry();
65
+ * const { featured, models, getByKey, isLoading } = useModelRegistry();
58
66
  *
59
67
  * // Legacy single-harness mode
60
68
  * const { models, defaultModel } = useModelRegistry({ harness: "native" });
@@ -1 +1 @@
1
- {"version":3,"file":"useModelRegistry.d.ts","sourceRoot":"","sources":["../../src/models/useModelRegistry.ts"],"names":[],"mappings":"AAGA,OAAO,EAOL,KAAK,SAAS,EACd,KAAK,QAAQ,EACd,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE/C,4CAA4C;AAC5C,MAAM,WAAW,uBAAuB;IACtC;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;CAClC;AAED,gDAAgD;AAChD,MAAM,WAAW,sBAAsB;IACrC,gDAAgD;IAChD,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;IACtC,0DAA0D;IAC1D,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC,QAAQ,EAAE,SAAS,SAAS,EAAE,CAAC,CAAC;IACjE,uDAAuD;IACvD,QAAQ,CAAC,YAAY,EAAE,SAAS,CAAC;IACjC;;;;;;;OAOG;IACH,QAAQ,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,SAAS,GAAG,SAAS,CAAC;IAC9D,oDAAoD;IACpD,QAAQ,CAAC,SAAS,EAAE,SAAS,QAAQ,EAAE,CAAC;IACxC,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,EAAE,SAAS,SAAS,EAAE,CAAC;IACxC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,SAAS,GAAG,SAAS,CAAC;CAC3D;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE,uBAAuB,GAAG,sBAAsB,CA2D1F"}
1
+ {"version":3,"file":"useModelRegistry.d.ts","sourceRoot":"","sources":["../../src/models/useModelRegistry.ts"],"names":[],"mappings":"AAGA,OAAO,EAML,KAAK,SAAS,EACd,KAAK,QAAQ,EACd,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG/C,4CAA4C;AAC5C,MAAM,WAAW,uBAAuB;IACtC;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC;CAClC;AAED,gDAAgD;AAChD,MAAM,WAAW,sBAAsB;IACrC,gDAAgD;IAChD,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;IACtC,0DAA0D;IAC1D,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC,QAAQ,EAAE,SAAS,SAAS,EAAE,CAAC,CAAC;IACjE,kGAAkG;IAClG,QAAQ,CAAC,YAAY,EAAE,SAAS,GAAG,SAAS,CAAC;IAC7C;;;;;;;OAOG;IACH,QAAQ,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,SAAS,GAAG,SAAS,CAAC;IAC9D,oDAAoD;IACpD,QAAQ,CAAC,SAAS,EAAE,SAAS,QAAQ,EAAE,CAAC;IACxC,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,EAAE,SAAS,SAAS,EAAE,CAAC;IACxC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,SAAS,GAAG,SAAS,CAAC;IAC1D,qEAAqE;IACrE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE,uBAAuB,GAAG,sBAAsB,CA8D1F"}
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { useMemo } from "react";
3
- import { MODEL_REGISTRY, DEFAULT_MODEL_ID, DISABLED_PROVIDERS, resolveDefaultModelId, modelKey, } from "./registry";
3
+ import { DEFAULT_MODEL_ID, DISABLED_PROVIDERS, resolveDefaultModelId, modelKey, } from "./registry";
4
+ import { useModelRegistryContext } from "./ModelRegistryContext";
4
5
  /**
5
6
  * Data hook that exposes the platform model registry with grouping
6
7
  * and lookup helpers.
@@ -9,6 +10,10 @@ import { MODEL_REGISTRY, DEFAULT_MODEL_ID, DISABLED_PROVIDERS, resolveDefaultMod
9
10
  * who want full control over rendering import this hook and build
10
11
  * their own UI.
11
12
  *
13
+ * The model data is fetched from the public model registry API by
14
+ * {@link StigmerProvider} and cached in context. During loading,
15
+ * `isLoading` is `true` and `models` is empty.
16
+ *
12
17
  * **Modes:**
13
18
  * - `options.harness === "cursor"` — Cursor-harness models only
14
19
  * - `options.harness === "native"` — native models, excluding disabled providers
@@ -17,7 +22,7 @@ import { MODEL_REGISTRY, DEFAULT_MODEL_ID, DISABLED_PROVIDERS, resolveDefaultMod
17
22
  * @example
18
23
  * ```tsx
19
24
  * // Unified mode — flat picker with all models
20
- * const { featured, models, getByKey } = useModelRegistry();
25
+ * const { featured, models, getByKey, isLoading } = useModelRegistry();
21
26
  *
22
27
  * // Legacy single-harness mode
23
28
  * const { models, defaultModel } = useModelRegistry({ harness: "native" });
@@ -25,10 +30,11 @@ import { MODEL_REGISTRY, DEFAULT_MODEL_ID, DISABLED_PROVIDERS, resolveDefaultMod
25
30
  */
26
31
  export function useModelRegistry(options) {
27
32
  const harness = options?.harness;
33
+ const { models: allModels, isLoading, error } = useModelRegistryContext();
28
34
  return useMemo(() => {
29
35
  const isUnified = harness === undefined;
30
36
  const { modelId: defaultId } = harness
31
- ? resolveDefaultModelId(harness)
37
+ ? resolveDefaultModelId(harness, allModels)
32
38
  : { modelId: DEFAULT_MODEL_ID };
33
39
  const byProvider = new Map();
34
40
  const byId = new Map();
@@ -36,7 +42,7 @@ export function useModelRegistry(options) {
36
42
  const enabledModels = [];
37
43
  const featuredModels = [];
38
44
  let defaultModel;
39
- for (const model of MODEL_REGISTRY) {
45
+ for (const model of allModels) {
40
46
  if (isUnified) {
41
47
  if (DISABLED_PROVIDERS.has(model.provider))
42
48
  continue;
@@ -75,7 +81,9 @@ export function useModelRegistry(options) {
75
81
  providers,
76
82
  featured: featuredModels,
77
83
  getByKey: (key) => byCompoundKey.get(key),
84
+ isLoading,
85
+ error,
78
86
  };
79
- }, [harness]);
87
+ }, [harness, allModels, isLoading, error]);
80
88
  }
81
89
  //# sourceMappingURL=useModelRegistry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useModelRegistry.js","sourceRoot":"","sources":["../../src/models/useModelRegistry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useModelRegistry.js","sourceRoot":"","sources":["../../src/models/useModelRegistry.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stigmer/react",
3
- "version": "0.4.5",
3
+ "version": "0.4.6",
4
4
  "description": "React provider and client hook for the Stigmer platform SDK",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -35,7 +35,7 @@
35
35
  }
36
36
  },
37
37
  "dependencies": {
38
- "@stigmer/theme": "0.4.5",
38
+ "@stigmer/theme": "0.4.6",
39
39
  "react-markdown": "^10.1.0",
40
40
  "remark-gfm": "^4.0.1",
41
41
  "streamdown": "^2.5.0",
@@ -44,8 +44,8 @@
44
44
  "peerDependencies": {
45
45
  "@base-ui/react": "^1.0.0",
46
46
  "@bufbuild/protobuf": "^2.0.0",
47
- "@stigmer/protos": "0.4.5",
48
- "@stigmer/sdk": "0.4.5",
47
+ "@stigmer/protos": "0.4.6",
48
+ "@stigmer/sdk": "0.4.6",
49
49
  "lucide-react": ">=0.400.0",
50
50
  "react": "^19.0.0",
51
51
  "react-dom": "^19.0.0",
package/provider.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACpE,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGpD,OAAO,KAAK,EAAE,SAAS,EAAqB,MAAM,cAAc,CAAC;AAIjE,yCAAyC;AACzC,MAAM,WAAW,oBAAoB;IACnC,oDAAoD;IACpD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,yDAAyD;IACzD,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC7B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;IACzC;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,eAAe,CAAC,EAC9B,MAAM,EACN,QAAQ,EACR,cAAwB,EACxB,MAAM,EACN,SAAS,EACT,SAAmB,GACpB,EAAE,oBAAoB,2CAyBtB"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA+B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACpE,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE5D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGpD,OAAO,KAAK,EAAE,SAAS,EAAqB,MAAM,cAAc,CAAC;AAOjE,yCAAyC;AACzC,MAAM,WAAW,oBAAoB;IACnC,oDAAoD;IACpD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,yDAAyD;IACzD,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC;IAC7B;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;IACzC;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,eAAe,CAAC,EAC9B,MAAM,EACN,QAAQ,EACR,cAAwB,EACxB,MAAM,EACN,SAAS,EACT,SAAmB,GACpB,EAAE,oBAAoB,2CA4BtB"}
package/provider.js CHANGED
@@ -6,6 +6,8 @@ import { StigmerContext } from "./context";
6
6
  import { DeploymentModeContext } from "./deployment-mode";
7
7
  import { ColorModeContext, useSystemColorMode } from "./color-mode";
8
8
  import { PortalContainerContext } from "./portal-container";
9
+ import { ModelRegistryContext } from "./models/ModelRegistryContext";
10
+ import { fetchModelRegistry } from "./models/registry";
9
11
  /**
10
12
  * React provider that distributes a {@link Stigmer} SDK client to
11
13
  * descendant components via {@link StigmerContext}.
@@ -41,7 +43,46 @@ export function StigmerProvider({ client, children, deploymentMode = "cloud", pr
41
43
  const resolvedMode = colorMode === "system" ? systemMode : colorMode;
42
44
  const presetClass = preset ? resolvePresetClass(preset) : "";
43
45
  const portalContainer = usePortalContainer(resolvedMode, presetClass);
44
- return (_jsx(StigmerContext.Provider, { value: client, children: _jsx(DeploymentModeContext.Provider, { value: deploymentMode, children: _jsx(ColorModeContext.Provider, { value: resolvedMode, children: _jsx(PortalContainerContext.Provider, { value: portalContainer, children: _jsx("div", { className: cn("stgm", presetClass, className), "data-stgm-color-mode": resolvedMode, children: children }) }) }) }) }));
46
+ const registryState = useModelRegistryFetch(client);
47
+ return (_jsx(StigmerContext.Provider, { value: client, children: _jsx(DeploymentModeContext.Provider, { value: deploymentMode, children: _jsx(ColorModeContext.Provider, { value: resolvedMode, children: _jsx(ModelRegistryContext.Provider, { value: registryState, children: _jsx(PortalContainerContext.Provider, { value: portalContainer, children: _jsx("div", { className: cn("stgm", presetClass, className), "data-stgm-color-mode": resolvedMode, children: children }) }) }) }) }) }));
48
+ }
49
+ /**
50
+ * Fetches the model registry from the authenticated API on mount and
51
+ * caches the result for the lifetime of the provider.
52
+ *
53
+ * Uses the client's `baseUrl` and `getAuthCredential()` so the fetch
54
+ * is authenticated with the same token the SDK uses for all other calls.
55
+ */
56
+ function useModelRegistryFetch(client) {
57
+ const [state, setState] = useState({
58
+ models: [],
59
+ isLoading: true,
60
+ error: null,
61
+ });
62
+ const clientRef = useRef(client);
63
+ clientRef.current = client;
64
+ useEffect(() => {
65
+ let cancelled = false;
66
+ const c = clientRef.current;
67
+ c.getAuthCredential()
68
+ .then((token) => fetchModelRegistry(c.baseUrl, token))
69
+ .then((models) => {
70
+ if (!cancelled) {
71
+ setState({ models, isLoading: false, error: null });
72
+ }
73
+ })
74
+ .catch((err) => {
75
+ if (!cancelled) {
76
+ setState({
77
+ models: [],
78
+ isLoading: false,
79
+ error: err instanceof Error ? err : new Error(String(err)),
80
+ });
81
+ }
82
+ });
83
+ return () => { cancelled = true; };
84
+ }, []);
85
+ return state;
45
86
  }
46
87
  /**
47
88
  * Creates and manages a portal container `<div>` appended to
package/provider.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":"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"}
@@ -1,6 +1,8 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
1
2
  import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
3
  import { renderHook, act } from "@testing-library/react";
3
- import { DEFAULT_MODEL_ID, DEFAULT_CURSOR_MODEL_ID } from "../../models/registry";
4
+ import { DEFAULT_MODEL_ID, DEFAULT_CURSOR_MODEL_ID, parseRegistryJson } from "../../models/registry";
5
+ import { ModelRegistryContext } from "../../models/ModelRegistryContext";
4
6
  const mockCreateSession = vi.fn();
5
7
  vi.mock("../useCreateSession", () => ({
6
8
  useCreateSession: () => ({
@@ -52,6 +54,18 @@ vi.mock("../../execution/useSessionVariables", () => ({
52
54
  useSessionVariables: () => mockSessionVariables,
53
55
  }));
54
56
  import { useNewSessionFlow } from "../useNewSessionFlow";
57
+ const TEST_MODELS = parseRegistryJson({
58
+ models: [
59
+ { id: "claude-sonnet-4.6", displayName: "Claude Sonnet 4.6", shortDescription: "", speedTier: "fast", provider: "anthropic", harness: "native", costTier: "standard", featured: true, pricing: { inputPricePerMillion: 3, outputPricePerMillion: 15, cacheWritePricePerMillion: 3.75, cacheReadPricePerMillion: 0.3 } },
60
+ { id: "default", displayName: "Cursor Auto", shortDescription: "", speedTier: "fast", provider: "cursor", harness: "cursor", costTier: "standard", featured: true, pricing: { inputPricePerMillion: 1.25, outputPricePerMillion: 6, cacheWritePricePerMillion: 1.25, cacheReadPricePerMillion: 0.25 } },
61
+ ],
62
+ });
63
+ function createWrapper() {
64
+ const state = { models: TEST_MODELS, isLoading: false, error: null };
65
+ return function Wrapper({ children }) {
66
+ return (_jsx(ModelRegistryContext.Provider, { value: state, children: children }));
67
+ };
68
+ }
55
69
  const STORAGE_KEY_HARNESS = "stigmer:session:harness";
56
70
  const STORAGE_KEY_MODEL_NATIVE = "stigmer:session:model";
57
71
  const STORAGE_KEY_MODEL_CURSOR = "stigmer:session:model:cursor";
@@ -79,53 +93,53 @@ describe("useNewSessionFlow", () => {
79
93
  });
80
94
  describe("harness state", () => {
81
95
  it("defaults to native when localStorage is empty", () => {
82
- const { result } = renderHook(() => useNewSessionFlow(defaultOptions()));
96
+ const { result } = renderHook(() => useNewSessionFlow(defaultOptions()), { wrapper: createWrapper() });
83
97
  expect(result.current.harness).toBe("native");
84
98
  });
85
99
  it("restores cursor harness from localStorage", () => {
86
100
  localStorage.setItem(STORAGE_KEY_HARNESS, "cursor");
87
- const { result } = renderHook(() => useNewSessionFlow(defaultOptions()));
101
+ const { result } = renderHook(() => useNewSessionFlow(defaultOptions()), { wrapper: createWrapper() });
88
102
  expect(result.current.harness).toBe("cursor");
89
103
  });
90
104
  it("falls back to native for unknown localStorage values", () => {
91
105
  localStorage.setItem(STORAGE_KEY_HARNESS, "unknown-value");
92
- const { result } = renderHook(() => useNewSessionFlow(defaultOptions()));
106
+ const { result } = renderHook(() => useNewSessionFlow(defaultOptions()), { wrapper: createWrapper() });
93
107
  expect(result.current.harness).toBe("native");
94
108
  });
95
109
  it("persists harness to localStorage on change", () => {
96
- const { result } = renderHook(() => useNewSessionFlow(defaultOptions()));
110
+ const { result } = renderHook(() => useNewSessionFlow(defaultOptions()), { wrapper: createWrapper() });
97
111
  act(() => result.current.setHarness("cursor"));
98
112
  expect(localStorage.getItem(STORAGE_KEY_HARNESS)).toBe("cursor");
99
113
  expect(result.current.harness).toBe("cursor");
100
114
  });
101
115
  it("persists native harness to localStorage", () => {
102
116
  localStorage.setItem(STORAGE_KEY_HARNESS, "cursor");
103
- const { result } = renderHook(() => useNewSessionFlow(defaultOptions()));
117
+ const { result } = renderHook(() => useNewSessionFlow(defaultOptions()), { wrapper: createWrapper() });
104
118
  act(() => result.current.setHarness("native"));
105
119
  expect(localStorage.getItem(STORAGE_KEY_HARNESS)).toBe("native");
106
120
  });
107
121
  });
108
122
  describe("per-harness model persistence", () => {
109
123
  it("uses separate storage keys for native and cursor models", () => {
110
- const { result } = renderHook(() => useNewSessionFlow(defaultOptions()));
124
+ const { result } = renderHook(() => useNewSessionFlow(defaultOptions()), { wrapper: createWrapper() });
111
125
  act(() => result.current.setModelId(DEFAULT_MODEL_ID));
112
126
  expect(localStorage.getItem(STORAGE_KEY_MODEL_NATIVE)).toBe(DEFAULT_MODEL_ID);
113
127
  expect(localStorage.getItem(STORAGE_KEY_MODEL_CURSOR)).toBeNull();
114
128
  });
115
129
  it("persists cursor model to cursor-specific key", () => {
116
130
  localStorage.setItem(STORAGE_KEY_HARNESS, "cursor");
117
- const { result } = renderHook(() => useNewSessionFlow(defaultOptions()));
131
+ const { result } = renderHook(() => useNewSessionFlow(defaultOptions()), { wrapper: createWrapper() });
118
132
  act(() => result.current.setModelId(DEFAULT_CURSOR_MODEL_ID));
119
133
  expect(localStorage.getItem(STORAGE_KEY_MODEL_CURSOR)).toBe(DEFAULT_CURSOR_MODEL_ID);
120
134
  });
121
135
  it("restores per-harness model when switching harness", () => {
122
136
  localStorage.setItem(STORAGE_KEY_MODEL_CURSOR, DEFAULT_CURSOR_MODEL_ID);
123
- const { result } = renderHook(() => useNewSessionFlow(defaultOptions()));
137
+ const { result } = renderHook(() => useNewSessionFlow(defaultOptions()), { wrapper: createWrapper() });
124
138
  act(() => result.current.setHarness("cursor"));
125
139
  expect(result.current.modelId).toBe(DEFAULT_CURSOR_MODEL_ID);
126
140
  });
127
141
  it("clears modelId when switching to a harness with no stored model", () => {
128
- const { result } = renderHook(() => useNewSessionFlow(defaultOptions()));
142
+ const { result } = renderHook(() => useNewSessionFlow(defaultOptions()), { wrapper: createWrapper() });
129
143
  act(() => result.current.setModelId(DEFAULT_MODEL_ID));
130
144
  expect(result.current.modelId).toBe(DEFAULT_MODEL_ID);
131
145
  act(() => result.current.setHarness("cursor"));
@@ -137,7 +151,7 @@ describe("useNewSessionFlow", () => {
137
151
  }
138
152
  });
139
153
  it("invalidates modelId when it is not in the active harness registry", () => {
140
- const { result } = renderHook(() => useNewSessionFlow(defaultOptions()));
154
+ const { result } = renderHook(() => useNewSessionFlow(defaultOptions()), { wrapper: createWrapper() });
141
155
  // Set a native-only model
142
156
  act(() => result.current.setModelId(DEFAULT_MODEL_ID));
143
157
  expect(result.current.modelId).toBe(DEFAULT_MODEL_ID);
@@ -148,7 +162,7 @@ describe("useNewSessionFlow", () => {
148
162
  });
149
163
  it("strips compound keys before persisting to localStorage", () => {
150
164
  localStorage.setItem(STORAGE_KEY_HARNESS, "cursor");
151
- const { result } = renderHook(() => useNewSessionFlow(defaultOptions()));
165
+ const { result } = renderHook(() => useNewSessionFlow(defaultOptions()), { wrapper: createWrapper() });
152
166
  // Simulate compound key from unified mode ModelSelector
153
167
  act(() => result.current.setModelId("cursor/default"));
154
168
  // Should store plain modelId, not compound key
@@ -158,7 +172,7 @@ describe("useNewSessionFlow", () => {
158
172
  localStorage.setItem(STORAGE_KEY_HARNESS, "cursor");
159
173
  // Legacy: compound key was stored before fix
160
174
  localStorage.setItem(STORAGE_KEY_MODEL_CURSOR, "cursor/default");
161
- const { result } = renderHook(() => useNewSessionFlow(defaultOptions()));
175
+ const { result } = renderHook(() => useNewSessionFlow(defaultOptions()), { wrapper: createWrapper() });
162
176
  // Should extract plain modelId and validate against registry
163
177
  expect(result.current.modelId).toBe(DEFAULT_CURSOR_MODEL_ID);
164
178
  });
@@ -166,7 +180,7 @@ describe("useNewSessionFlow", () => {
166
180
  describe("submit with harness", () => {
167
181
  it("passes harness field to createSession", async () => {
168
182
  const opts = defaultOptions();
169
- const { result } = renderHook(() => useNewSessionFlow(opts));
183
+ const { result } = renderHook(() => useNewSessionFlow(opts), { wrapper: createWrapper() });
170
184
  await act(async () => {
171
185
  await result.current.submit("Hello");
172
186
  });
@@ -176,7 +190,7 @@ describe("useNewSessionFlow", () => {
176
190
  });
177
191
  it("passes cursor harness to createSession after switching", async () => {
178
192
  const opts = defaultOptions();
179
- const { result } = renderHook(() => useNewSessionFlow(opts));
193
+ const { result } = renderHook(() => useNewSessionFlow(opts), { wrapper: createWrapper() });
180
194
  act(() => result.current.setHarness("cursor"));
181
195
  await act(async () => {
182
196
  await result.current.submit("Hello");
@@ -186,7 +200,7 @@ describe("useNewSessionFlow", () => {
186
200
  });
187
201
  it("calls onSessionCreated on success", async () => {
188
202
  const opts = defaultOptions();
189
- const { result } = renderHook(() => useNewSessionFlow(opts));
203
+ const { result } = renderHook(() => useNewSessionFlow(opts), { wrapper: createWrapper() });
190
204
  await act(async () => {
191
205
  await result.current.submit("Hello");
192
206
  });
@@ -195,7 +209,7 @@ describe("useNewSessionFlow", () => {
195
209
  it("sets submitError and calls onError on failure", async () => {
196
210
  mockCreateSession.mockRejectedValueOnce(new Error("RPC fail"));
197
211
  const opts = defaultOptions();
198
- const { result } = renderHook(() => useNewSessionFlow(opts));
212
+ const { result } = renderHook(() => useNewSessionFlow(opts), { wrapper: createWrapper() });
199
213
  await act(async () => {
200
214
  await result.current.submit("Hello");
201
215
  });
@@ -204,7 +218,7 @@ describe("useNewSessionFlow", () => {
204
218
  });
205
219
  it("resets isSubmitting after completion", async () => {
206
220
  const opts = defaultOptions();
207
- const { result } = renderHook(() => useNewSessionFlow(opts));
221
+ const { result } = renderHook(() => useNewSessionFlow(opts), { wrapper: createWrapper() });
208
222
  await act(async () => {
209
223
  await result.current.submit("Hello");
210
224
  });