@stigmer/react 0.4.0 → 0.4.2

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 (37) hide show
  1. package/mcp-server/McpServerDetailView.d.ts.map +1 -1
  2. package/mcp-server/McpServerDetailView.js +3 -3
  3. package/mcp-server/McpServerDetailView.js.map +1 -1
  4. package/mcp-server/useMcpServerOAuthConnect.d.ts.map +1 -1
  5. package/mcp-server/useMcpServerOAuthConnect.js +37 -9
  6. package/mcp-server/useMcpServerOAuthConnect.js.map +1 -1
  7. package/models/ModelSelector.d.ts +34 -18
  8. package/models/ModelSelector.d.ts.map +1 -1
  9. package/models/ModelSelector.js +76 -47
  10. package/models/ModelSelector.js.map +1 -1
  11. package/models/__tests__/useModelRegistry.test.js +4 -2
  12. package/models/__tests__/useModelRegistry.test.js.map +1 -1
  13. package/models/harness.d.ts +26 -2
  14. package/models/harness.d.ts.map +1 -1
  15. package/models/harness.js +29 -4
  16. package/models/harness.js.map +1 -1
  17. package/models/index.d.ts +5 -5
  18. package/models/index.d.ts.map +1 -1
  19. package/models/index.js +2 -2
  20. package/models/index.js.map +1 -1
  21. package/models/registry.d.ts +49 -2
  22. package/models/registry.d.ts.map +1 -1
  23. package/models/registry.js +45 -3
  24. package/models/registry.js.map +1 -1
  25. package/models/useModelRegistry.d.ts.map +1 -1
  26. package/models/useModelRegistry.js +7 -12
  27. package/models/useModelRegistry.js.map +1 -1
  28. package/package.json +4 -4
  29. package/src/mcp-server/McpServerDetailView.tsx +15 -0
  30. package/src/mcp-server/useMcpServerOAuthConnect.ts +37 -9
  31. package/src/models/ModelSelector.tsx +234 -97
  32. package/src/models/__tests__/useModelRegistry.test.tsx +4 -2
  33. package/src/models/harness.ts +51 -5
  34. package/src/models/index.ts +5 -5
  35. package/src/models/registry.ts +96 -3
  36. package/src/models/useModelRegistry.ts +6 -8
  37. package/styles.css +1 -1
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { useMemo } from "react";
3
- import { MODEL_REGISTRY, DEFAULT_MODEL_ID, DEFAULT_CURSOR_MODEL_ID, DISABLED_PROVIDERS, modelKey, } from "./registry";
3
+ import { MODEL_REGISTRY, DEFAULT_MODEL_ID, DISABLED_PROVIDERS, resolveDefaultModelId, modelKey, } from "./registry";
4
4
  /**
5
5
  * Data hook that exposes the platform model registry with grouping
6
6
  * and lookup helpers.
@@ -26,10 +26,10 @@ import { MODEL_REGISTRY, DEFAULT_MODEL_ID, DEFAULT_CURSOR_MODEL_ID, DISABLED_PRO
26
26
  export function useModelRegistry(options) {
27
27
  const harness = options?.harness;
28
28
  return useMemo(() => {
29
- const isCursor = harness === "cursor";
30
- const isNative = harness === "native";
31
29
  const isUnified = harness === undefined;
32
- const defaultId = isCursor ? DEFAULT_CURSOR_MODEL_ID : DEFAULT_MODEL_ID;
30
+ const { modelId: defaultId } = harness
31
+ ? resolveDefaultModelId(harness)
32
+ : { modelId: DEFAULT_MODEL_ID };
33
33
  const byProvider = new Map();
34
34
  const byId = new Map();
35
35
  const byCompoundKey = new Map();
@@ -37,18 +37,13 @@ export function useModelRegistry(options) {
37
37
  const featuredModels = [];
38
38
  let defaultModel;
39
39
  for (const model of MODEL_REGISTRY) {
40
- if (isCursor) {
41
- if (model.harness !== "cursor")
42
- continue;
43
- }
44
- else if (isNative) {
45
- if (model.harness !== "native")
46
- continue;
40
+ if (isUnified) {
47
41
  if (DISABLED_PROVIDERS.has(model.provider))
48
42
  continue;
49
43
  }
50
44
  else {
51
- // Unified include both harnesses, still respect DISABLED_PROVIDERS
45
+ if (model.harness !== harness)
46
+ continue;
52
47
  if (DISABLED_PROVIDERS.has(model.provider))
53
48
  continue;
54
49
  }
@@ -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.0",
3
+ "version": "0.4.2",
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.0",
38
+ "@stigmer/theme": "0.4.2",
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.0",
48
- "@stigmer/sdk": "0.4.0",
47
+ "@stigmer/protos": "0.4.2",
48
+ "@stigmer/sdk": "0.4.2",
49
49
  "lucide-react": ">=0.400.0",
50
50
  "react": "^19.0.0",
51
51
  "react-dom": "^19.0.0",
@@ -383,6 +383,7 @@ export function McpServerDetailView({
383
383
  credentials.setManualOverride(false);
384
384
  setShowCredentialForm(false);
385
385
  }}
386
+ onCancelOAuth={oauth.clearError}
386
387
  />
387
388
 
388
389
  {showCredentialForm && credentials.missingVariables.length > 0 && (
@@ -566,6 +567,7 @@ function ConnectBar({
566
567
  manualOverride,
567
568
  onManualOverride,
568
569
  onBackToOAuth,
570
+ onCancelOAuth,
569
571
  }: {
570
572
  readonly isConnecting: boolean;
571
573
  readonly connectionError: Error | null;
@@ -600,6 +602,7 @@ function ConnectBar({
600
602
  readonly manualOverride: boolean;
601
603
  readonly onManualOverride: () => void;
602
604
  readonly onBackToOAuth: () => void;
605
+ readonly onCancelOAuth: () => void;
603
606
  }) {
604
607
  const [disconnectPhase, setDisconnectPhase] = useState<DisconnectPhase>("idle");
605
608
  const [removeOrgAppPhase, setRemoveOrgAppPhase] = useState<RemoveOrgAppPhase>("idle");
@@ -853,6 +856,18 @@ function ConnectBar({
853
856
  </button>
854
857
  </div>
855
858
 
859
+ {oauthPhase === "awaiting-callback" && (
860
+ <div className="flex items-center gap-3 border-t border-border px-3 py-1.5">
861
+ <button
862
+ type="button"
863
+ onClick={onCancelOAuth}
864
+ className="text-[11px] text-muted-foreground underline decoration-muted-foreground/40 underline-offset-2 hover:text-foreground hover:decoration-foreground"
865
+ >
866
+ Cancel sign-in
867
+ </button>
868
+ </div>
869
+ )}
870
+
856
871
  {/* Vendor approval blocked banner with BYOA CTA */}
857
872
  {oauthSignInDisabled && (
858
873
  <div className="flex items-start gap-2 border-t border-amber-500/20 bg-amber-500/5 px-3 py-2">
@@ -122,6 +122,7 @@ export function useMcpServerOAuthConnect(): UseMcpServerOAuthConnectReturn {
122
122
 
123
123
  const popupRef = useRef<Window | null>(null);
124
124
  const cleanupRef = useRef<(() => void) | null>(null);
125
+ const cancelledRef = useRef(false);
125
126
 
126
127
  useEffect(() => {
127
128
  return () => {
@@ -130,6 +131,13 @@ export function useMcpServerOAuthConnect(): UseMcpServerOAuthConnectReturn {
130
131
  }, []);
131
132
 
132
133
  const clearError = useCallback(() => {
134
+ if (cleanupRef.current || popupRef.current) {
135
+ cancelledRef.current = true;
136
+ cleanupRef.current?.();
137
+ closePopup(popupRef.current);
138
+ popupRef.current = null;
139
+ cleanupRef.current = null;
140
+ }
133
141
  setPhase("idle");
134
142
  setError(null);
135
143
  }, []);
@@ -138,6 +146,7 @@ export function useMcpServerOAuthConnect(): UseMcpServerOAuthConnectReturn {
138
146
  async (mcpServerId: string, org: string, declaredEnvKeys?: readonly string[]): Promise<McpServer> => {
139
147
  setPhase("initiating");
140
148
  setError(null);
149
+ cancelledRef.current = false;
141
150
 
142
151
  cleanupRef.current?.();
143
152
 
@@ -214,9 +223,12 @@ export function useMcpServerOAuthConnect(): UseMcpServerOAuthConnectReturn {
214
223
  return server;
215
224
  } catch (err) {
216
225
  const wrapped = toError(err);
217
- setError(wrapped);
218
- setPhase("idle");
219
- closePopup(popup);
226
+ if (!cancelledRef.current) {
227
+ setError(wrapped);
228
+ setPhase("idle");
229
+ closePopup(popup);
230
+ }
231
+ cancelledRef.current = false;
220
232
  throw wrapped;
221
233
  } finally {
222
234
  popupRef.current = null;
@@ -241,9 +253,14 @@ export function useMcpServerOAuthConnect(): UseMcpServerOAuthConnectReturn {
241
253
 
242
254
  /**
243
255
  * Grace period (ms) after `popup.closed` is first detected before treating
244
- * it as a user-initiated close. COOP providers sever the opener reference
245
- * immediately, making `popup.closed` appear `true` while the popup is still
246
- * active. The grace period lets the BroadcastChannel callback arrive.
256
+ * it as a user-initiated close.
257
+ *
258
+ * Only used when BroadcastChannel is unavailable. When BC is available,
259
+ * `popup.closed` polling is skipped entirely because COOP providers
260
+ * (e.g. Sentry, GitHub) sever the opener reference on cross-origin
261
+ * navigation, making `popup.closed` permanently `true` while the popup
262
+ * is still active. The overall {@link POPUP_CALLBACK_TIMEOUT_MS} serves
263
+ * as the safety net for abandoned flows instead.
247
264
  */
248
265
  const POPUP_CLOSED_GRACE_MS = 5_000;
249
266
 
@@ -257,6 +274,7 @@ function waitForOAuthCallback(
257
274
  let timeoutId: ReturnType<typeof setTimeout>;
258
275
  let pollId: ReturnType<typeof setInterval>;
259
276
  let bc: BroadcastChannel | null = null;
277
+ let hasBroadcastChannel = false;
260
278
 
261
279
  function cleanup() {
262
280
  if (timeoutId) clearTimeout(timeoutId);
@@ -314,6 +332,7 @@ function waitForOAuthCallback(
314
332
  // BroadcastChannel — works even when COOP severs window.opener.
315
333
  try {
316
334
  bc = new BroadcastChannel(OAUTH_BROADCAST_CHANNEL);
335
+ hasBroadcastChannel = true;
317
336
  bc.onmessage = (event: MessageEvent) => {
318
337
  validateAndSettle(event.data as OAuthCallbackMessage | undefined);
319
338
  };
@@ -332,12 +351,21 @@ function waitForOAuthCallback(
332
351
  closePopup(popup);
333
352
  }, POPUP_CALLBACK_TIMEOUT_MS);
334
353
 
335
- // COOP providers make popup.closed appear true immediately after
336
- // cross-origin navigation. Wait a grace period before treating it
337
- // as a real user-initiated close.
354
+ // When BroadcastChannel is available, skip popup.closed polling.
355
+ // COOP providers (Sentry, GitHub, etc.) sever the opener reference
356
+ // on cross-origin navigation, making popup.closed permanently true
357
+ // while the popup is still active. BroadcastChannel reliably
358
+ // delivers the callback regardless of COOP; the overall timeout
359
+ // above catches abandoned flows.
360
+ //
361
+ // When BroadcastChannel is NOT available (legacy browsers), fall
362
+ // back to popup.closed polling with a short grace period — it is
363
+ // the only signal we have in that degraded path.
338
364
  let popupClosedAt: number | null = null;
339
365
 
340
366
  pollId = setInterval(() => {
367
+ if (hasBroadcastChannel) return;
368
+
341
369
  if (popup.closed) {
342
370
  if (popupClosedAt === null) {
343
371
  popupClosedAt = Date.now();