@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.
- package/mcp-server/McpServerDetailView.d.ts.map +1 -1
- package/mcp-server/McpServerDetailView.js +3 -3
- package/mcp-server/McpServerDetailView.js.map +1 -1
- package/mcp-server/useMcpServerOAuthConnect.d.ts.map +1 -1
- package/mcp-server/useMcpServerOAuthConnect.js +37 -9
- package/mcp-server/useMcpServerOAuthConnect.js.map +1 -1
- package/models/ModelSelector.d.ts +34 -18
- package/models/ModelSelector.d.ts.map +1 -1
- package/models/ModelSelector.js +76 -47
- package/models/ModelSelector.js.map +1 -1
- package/models/__tests__/useModelRegistry.test.js +4 -2
- package/models/__tests__/useModelRegistry.test.js.map +1 -1
- package/models/harness.d.ts +26 -2
- package/models/harness.d.ts.map +1 -1
- package/models/harness.js +29 -4
- package/models/harness.js.map +1 -1
- package/models/index.d.ts +5 -5
- package/models/index.d.ts.map +1 -1
- package/models/index.js +2 -2
- package/models/index.js.map +1 -1
- package/models/registry.d.ts +49 -2
- package/models/registry.d.ts.map +1 -1
- package/models/registry.js +45 -3
- package/models/registry.js.map +1 -1
- package/models/useModelRegistry.d.ts.map +1 -1
- package/models/useModelRegistry.js +7 -12
- package/models/useModelRegistry.js.map +1 -1
- package/package.json +4 -4
- package/src/mcp-server/McpServerDetailView.tsx +15 -0
- package/src/mcp-server/useMcpServerOAuthConnect.ts +37 -9
- package/src/models/ModelSelector.tsx +234 -97
- package/src/models/__tests__/useModelRegistry.test.tsx +4 -2
- package/src/models/harness.ts +51 -5
- package/src/models/index.ts +5 -5
- package/src/models/registry.ts +96 -3
- package/src/models/useModelRegistry.ts +6 -8
- 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,
|
|
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
|
|
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 (
|
|
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
|
-
|
|
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":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EACL,cAAc,EACd,gBAAgB,
|
|
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.
|
|
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.
|
|
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.
|
|
48
|
-
"@stigmer/sdk": "0.4.
|
|
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
|
-
|
|
218
|
-
|
|
219
|
-
|
|
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.
|
|
245
|
-
*
|
|
246
|
-
*
|
|
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
|
-
//
|
|
336
|
-
//
|
|
337
|
-
//
|
|
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();
|