@stigmer/react 0.0.84 → 0.0.86
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/demo/fixtures.d.ts +4 -0
- package/demo/fixtures.d.ts.map +1 -1
- package/demo/fixtures.js +4 -0
- package/demo/fixtures.js.map +1 -1
- package/demo/samples.d.ts +1 -0
- package/demo/samples.d.ts.map +1 -1
- package/demo/samples.js +1 -0
- package/demo/samples.js.map +1 -1
- package/execution/ArtifactPreviewModal.d.ts +78 -18
- package/execution/ArtifactPreviewModal.d.ts.map +1 -1
- package/execution/ArtifactPreviewModal.js +82 -60
- package/execution/ArtifactPreviewModal.js.map +1 -1
- package/execution/index.d.ts +2 -2
- package/execution/index.d.ts.map +1 -1
- package/execution/index.js +1 -1
- package/execution/index.js.map +1 -1
- package/index.d.ts +6 -4
- package/index.d.ts.map +1 -1
- package/index.js +4 -2
- package/index.js.map +1 -1
- package/library/ResourceListView.js +1 -1
- package/library/ResourceListView.js.map +1 -1
- package/mcp-server/McpServerConnectDialog.d.ts +51 -0
- package/mcp-server/McpServerConnectDialog.d.ts.map +1 -0
- package/mcp-server/McpServerConnectDialog.js +164 -0
- package/mcp-server/McpServerConnectDialog.js.map +1 -0
- package/mcp-server/McpServerDetailView.js +2 -2
- package/mcp-server/McpServerDetailView.js.map +1 -1
- package/mcp-server/McpServerPicker.d.ts.map +1 -1
- package/mcp-server/McpServerPicker.js +7 -1
- package/mcp-server/McpServerPicker.js.map +1 -1
- package/mcp-server/index.d.ts +2 -0
- package/mcp-server/index.d.ts.map +1 -1
- package/mcp-server/index.js +1 -0
- package/mcp-server/index.js.map +1 -1
- package/oauth-app/CreateOAuthAppForm.d.ts +41 -0
- package/oauth-app/CreateOAuthAppForm.d.ts.map +1 -0
- package/oauth-app/CreateOAuthAppForm.js +140 -0
- package/oauth-app/CreateOAuthAppForm.js.map +1 -0
- package/oauth-app/OAuthAppDetailPanel.d.ts +43 -0
- package/oauth-app/OAuthAppDetailPanel.d.ts.map +1 -0
- package/oauth-app/OAuthAppDetailPanel.js +202 -0
- package/oauth-app/OAuthAppDetailPanel.js.map +1 -0
- package/oauth-app/OAuthAppListPanel.d.ts +43 -0
- package/oauth-app/OAuthAppListPanel.d.ts.map +1 -0
- package/oauth-app/OAuthAppListPanel.js +79 -0
- package/oauth-app/OAuthAppListPanel.js.map +1 -0
- package/oauth-app/index.d.ts +15 -0
- package/oauth-app/index.d.ts.map +1 -0
- package/oauth-app/index.js +8 -0
- package/oauth-app/index.js.map +1 -0
- package/oauth-app/useCreateOAuthApp.d.ts +39 -0
- package/oauth-app/useCreateOAuthApp.d.ts.map +1 -0
- package/oauth-app/useCreateOAuthApp.js +50 -0
- package/oauth-app/useCreateOAuthApp.js.map +1 -0
- package/oauth-app/useDeleteOAuthApp.d.ts +31 -0
- package/oauth-app/useDeleteOAuthApp.d.ts.map +1 -0
- package/oauth-app/useDeleteOAuthApp.js +43 -0
- package/oauth-app/useDeleteOAuthApp.js.map +1 -0
- package/oauth-app/useOAuthAppList.d.ts +32 -0
- package/oauth-app/useOAuthAppList.d.ts.map +1 -0
- package/oauth-app/useOAuthAppList.js +61 -0
- package/oauth-app/useOAuthAppList.js.map +1 -0
- package/oauth-app/useUpdateOAuthApp.d.ts +38 -0
- package/oauth-app/useUpdateOAuthApp.d.ts.map +1 -0
- package/oauth-app/useUpdateOAuthApp.js +49 -0
- package/oauth-app/useUpdateOAuthApp.js.map +1 -0
- package/package.json +4 -4
- package/src/demo/fixtures.ts +8 -0
- package/src/demo/samples.ts +2 -0
- package/src/execution/ArtifactPreviewModal.tsx +206 -128
- package/src/execution/index.ts +2 -2
- package/src/index.ts +24 -0
- package/src/library/ResourceListView.tsx +8 -8
- package/src/mcp-server/McpServerConnectDialog.tsx +527 -0
- package/src/mcp-server/McpServerDetailView.tsx +2 -1
- package/src/mcp-server/McpServerPicker.tsx +8 -1
- package/src/mcp-server/index.ts +3 -0
- package/src/oauth-app/CreateOAuthAppForm.tsx +449 -0
- package/src/oauth-app/OAuthAppDetailPanel.tsx +671 -0
- package/src/oauth-app/OAuthAppListPanel.tsx +237 -0
- package/src/oauth-app/index.ts +14 -0
- package/src/oauth-app/useCreateOAuthApp.ts +70 -0
- package/src/oauth-app/useDeleteOAuthApp.ts +62 -0
- package/src/oauth-app/useOAuthAppList.ts +84 -0
- package/src/oauth-app/useUpdateOAuthApp.ts +69 -0
- package/styles.css +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useOAuthAppList.d.ts","sourceRoot":"","sources":["../../src/oauth-app/useOAuthAppList.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mDAAmD,CAAC;AAIlF,+CAA+C;AAC/C,MAAM,WAAW,qBAAqB;IACpC,6EAA6E;IAC7E,QAAQ,CAAC,SAAS,EAAE,SAAS,QAAQ,EAAE,CAAC;IACxC,gEAAgE;IAChE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B,iEAAiE;IACjE,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,GAAG,IAAI,GACjB,qBAAqB,CA0CvB"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useCallback, useEffect, useState } from "react";
|
|
3
|
+
import { create } from "@bufbuild/protobuf";
|
|
4
|
+
import { ListOAuthAppsByOrgInputSchema } from "@stigmer/protos/ai/stigmer/iam/oauthapp/v1/io_pb";
|
|
5
|
+
import { useStigmer } from "../hooks";
|
|
6
|
+
import { toError } from "../internal/toError";
|
|
7
|
+
/**
|
|
8
|
+
* Data hook that fetches all {@link OAuthApp} entries for an organization.
|
|
9
|
+
*
|
|
10
|
+
* Returns every OAuthApp whose `metadata.org` matches the input. In
|
|
11
|
+
* practice these are the BYOA OAuth apps created through the "Bring
|
|
12
|
+
* your own app" flow on MCP server detail pages.
|
|
13
|
+
*
|
|
14
|
+
* Pass `null` for `org` to skip fetching (stable no-op). Useful when
|
|
15
|
+
* the active organization has not been resolved yet.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* const { oauthApps, isLoading, error } = useOAuthAppList(org);
|
|
20
|
+
*
|
|
21
|
+
* if (isLoading) return <Spinner />;
|
|
22
|
+
* oauthApps.map((app) => app.spec?.provider);
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export function useOAuthAppList(org) {
|
|
26
|
+
const stigmer = useStigmer();
|
|
27
|
+
const [oauthApps, setOauthApps] = useState([]);
|
|
28
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
29
|
+
const [error, setError] = useState(null);
|
|
30
|
+
const [fetchKey, setFetchKey] = useState(0);
|
|
31
|
+
const refetch = useCallback(() => setFetchKey((k) => k + 1), []);
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (!org) {
|
|
34
|
+
setOauthApps([]);
|
|
35
|
+
setIsLoading(false);
|
|
36
|
+
setError(null);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const cancelled = { current: false };
|
|
40
|
+
setIsLoading(true);
|
|
41
|
+
setError(null);
|
|
42
|
+
stigmer.oauthapp
|
|
43
|
+
.listByOrg(create(ListOAuthAppsByOrgInputSchema, { org }))
|
|
44
|
+
.then((result) => {
|
|
45
|
+
if (cancelled.current)
|
|
46
|
+
return;
|
|
47
|
+
setOauthApps([...result.entries]);
|
|
48
|
+
setIsLoading(false);
|
|
49
|
+
}, (err) => {
|
|
50
|
+
if (cancelled.current)
|
|
51
|
+
return;
|
|
52
|
+
setError(toError(err));
|
|
53
|
+
setIsLoading(false);
|
|
54
|
+
});
|
|
55
|
+
return () => {
|
|
56
|
+
cancelled.current = true;
|
|
57
|
+
};
|
|
58
|
+
}, [org, stigmer, fetchKey]);
|
|
59
|
+
return { oauthApps, isLoading, error, refetch };
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=useOAuthAppList.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useOAuthAppList.js","sourceRoot":"","sources":["../../src/oauth-app/useOAuthAppList.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,6BAA6B,EAAE,MAAM,kDAAkD,CAAC;AAEjG,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAc9C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,eAAe,CAC7B,GAAkB;IAElB,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAa,EAAE,CAAC,CAAC;IAC3D,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IACvD,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAE5C,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEjE,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,YAAY,CAAC,EAAE,CAAC,CAAC;YACjB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,QAAQ,CAAC,IAAI,CAAC,CAAC;YACf,OAAO;QACT,CAAC;QAED,MAAM,SAAS,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QACrC,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEf,OAAO,CAAC,QAAQ;aACb,SAAS,CAAC,MAAM,CAAC,6BAA6B,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;aACzD,IAAI,CACH,CAAC,MAAM,EAAE,EAAE;YACT,IAAI,SAAS,CAAC,OAAO;gBAAE,OAAO;YAC9B,YAAY,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;YAClC,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC,EACD,CAAC,GAAG,EAAE,EAAE;YACN,IAAI,SAAS,CAAC,OAAO;gBAAE,OAAO;YAC9B,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;YACvB,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC,CACF,CAAC;QAEJ,OAAO,GAAG,EAAE;YACV,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC;QAC3B,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;IAE7B,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { OAuthAppInput } from "@stigmer/sdk";
|
|
2
|
+
import type { OAuthApp } from "@stigmer/protos/ai/stigmer/iam/oauthapp/v1/api_pb";
|
|
3
|
+
/** Return value of {@link useUpdateOAuthApp}. */
|
|
4
|
+
export interface UseUpdateOAuthAppReturn {
|
|
5
|
+
/** Submit an {@link OAuthAppInput} to update an existing OAuth app. Resolves with the updated resource. */
|
|
6
|
+
readonly update: (input: OAuthAppInput) => Promise<OAuthApp>;
|
|
7
|
+
/** `true` while the update request is in flight. */
|
|
8
|
+
readonly isUpdating: boolean;
|
|
9
|
+
/** Error from the last failed update, or `null` when healthy. */
|
|
10
|
+
readonly error: Error | null;
|
|
11
|
+
/** Reset `error` to `null`. */
|
|
12
|
+
readonly clearError: () => void;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Mutation hook that wraps `oauthapp.update()` with loading and error
|
|
16
|
+
* state.
|
|
17
|
+
*
|
|
18
|
+
* Updates an existing OAuth app. The input must include the `name` and
|
|
19
|
+
* `org` fields to identify the target resource, along with the updated
|
|
20
|
+
* spec fields. Omit `clientSecret` to leave the existing secret
|
|
21
|
+
* unchanged.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```tsx
|
|
25
|
+
* const { update, isUpdating, error } = useUpdateOAuthApp();
|
|
26
|
+
*
|
|
27
|
+
* await update({
|
|
28
|
+
* name: "My Slack App",
|
|
29
|
+
* org: "acme",
|
|
30
|
+
* provider: "Slack",
|
|
31
|
+
* clientId: "123456.789012",
|
|
32
|
+
* authorizationUrl: "https://slack.com/oauth/v2/authorize",
|
|
33
|
+
* tokenUrl: "https://slack.com/api/oauth.v2.access",
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare function useUpdateOAuthApp(): UseUpdateOAuthAppReturn;
|
|
38
|
+
//# sourceMappingURL=useUpdateOAuthApp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUpdateOAuthApp.d.ts","sourceRoot":"","sources":["../../src/oauth-app/useUpdateOAuthApp.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mDAAmD,CAAC;AAIlF,iDAAiD;AACjD,MAAM,WAAW,uBAAuB;IACtC,2GAA2G;IAC3G,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC7D,oDAAoD;IACpD,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAC7B,+BAA+B;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,IAAI,CAAC;CACjC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,iBAAiB,IAAI,uBAAuB,CAyB3D"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useCallback, useState } from "react";
|
|
3
|
+
import { useStigmer } from "../hooks";
|
|
4
|
+
import { toError } from "../internal/toError";
|
|
5
|
+
/**
|
|
6
|
+
* Mutation hook that wraps `oauthapp.update()` with loading and error
|
|
7
|
+
* state.
|
|
8
|
+
*
|
|
9
|
+
* Updates an existing OAuth app. The input must include the `name` and
|
|
10
|
+
* `org` fields to identify the target resource, along with the updated
|
|
11
|
+
* spec fields. Omit `clientSecret` to leave the existing secret
|
|
12
|
+
* unchanged.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* const { update, isUpdating, error } = useUpdateOAuthApp();
|
|
17
|
+
*
|
|
18
|
+
* await update({
|
|
19
|
+
* name: "My Slack App",
|
|
20
|
+
* org: "acme",
|
|
21
|
+
* provider: "Slack",
|
|
22
|
+
* clientId: "123456.789012",
|
|
23
|
+
* authorizationUrl: "https://slack.com/oauth/v2/authorize",
|
|
24
|
+
* tokenUrl: "https://slack.com/api/oauth.v2.access",
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export function useUpdateOAuthApp() {
|
|
29
|
+
const stigmer = useStigmer();
|
|
30
|
+
const [isUpdating, setIsUpdating] = useState(false);
|
|
31
|
+
const [error, setError] = useState(null);
|
|
32
|
+
const clearError = useCallback(() => setError(null), []);
|
|
33
|
+
const update = useCallback(async (input) => {
|
|
34
|
+
setIsUpdating(true);
|
|
35
|
+
setError(null);
|
|
36
|
+
try {
|
|
37
|
+
return await stigmer.oauthapp.update(input);
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
setError(toError(err));
|
|
41
|
+
throw err;
|
|
42
|
+
}
|
|
43
|
+
finally {
|
|
44
|
+
setIsUpdating(false);
|
|
45
|
+
}
|
|
46
|
+
}, [stigmer]);
|
|
47
|
+
return { update, isUpdating, error, clearError };
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=useUpdateOAuthApp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUpdateOAuthApp.js","sourceRoot":"","sources":["../../src/oauth-app/useUpdateOAuthApp.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAG9C,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAc9C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IAEvD,MAAM,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;IAEzD,MAAM,MAAM,GAAG,WAAW,CACxB,KAAK,EAAE,KAAoB,EAAqB,EAAE;QAChD,aAAa,CAAC,IAAI,CAAC,CAAC;QACpB,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEf,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;YACvB,MAAM,GAAG,CAAC;QACZ,CAAC;gBAAS,CAAC;YACT,aAAa,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,EACD,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AACnD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stigmer/react",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.86",
|
|
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.0.
|
|
38
|
+
"@stigmer/theme": "0.0.86",
|
|
39
39
|
"react-markdown": "^10.1.0",
|
|
40
40
|
"remark-gfm": "^4.0.1",
|
|
41
41
|
"yaml": "^2.8.2"
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"@base-ui/react": "^1.0.0",
|
|
45
45
|
"@bufbuild/protobuf": "^2.0.0",
|
|
46
|
-
"@stigmer/protos": "0.0.
|
|
47
|
-
"@stigmer/sdk": "0.0.
|
|
46
|
+
"@stigmer/protos": "0.0.86",
|
|
47
|
+
"@stigmer/sdk": "0.0.86",
|
|
48
48
|
"react": "^19.0.0",
|
|
49
49
|
"react-dom": "^19.0.0"
|
|
50
50
|
}
|
package/src/demo/fixtures.ts
CHANGED
|
@@ -238,6 +238,14 @@ export const fixtures = {
|
|
|
238
238
|
/** Hooks: `useUpdateVisibility` (when kind is McpServer) */
|
|
239
239
|
updateVisibility: (handler: UnaryFixtureHandler): FixtureSpec =>
|
|
240
240
|
unarySpec(McpServerCommandController, "updateVisibility", handler),
|
|
241
|
+
|
|
242
|
+
/** Hooks: `useOAuthGrantStatus` */
|
|
243
|
+
getOAuthGrantStatus: (handler: UnaryFixtureHandler): FixtureSpec =>
|
|
244
|
+
unarySpec(McpServerQueryController, "getOAuthGrantStatus", handler),
|
|
245
|
+
|
|
246
|
+
/** Hooks: `useOrgOAuthApp` */
|
|
247
|
+
getOrgOAuthApp: (handler: UnaryFixtureHandler): FixtureSpec =>
|
|
248
|
+
unarySpec(McpServerQueryController, "getOrgOAuthApp", handler),
|
|
241
249
|
},
|
|
242
250
|
|
|
243
251
|
// ---- Environment ----
|
package/src/demo/samples.ts
CHANGED
|
@@ -154,6 +154,7 @@ export interface SearchResultOverrides {
|
|
|
154
154
|
readonly slug?: string;
|
|
155
155
|
readonly kind?: ApiResourceKind;
|
|
156
156
|
readonly description?: string;
|
|
157
|
+
readonly iconUrl?: string;
|
|
157
158
|
}
|
|
158
159
|
|
|
159
160
|
// ---------------------------------------------------------------------------
|
|
@@ -465,6 +466,7 @@ export const samples = {
|
|
|
465
466
|
org: o?.org ?? "demo",
|
|
466
467
|
description: o?.description ?? "A sample resource for demo purposes.",
|
|
467
468
|
score: 1.0,
|
|
469
|
+
iconUrl: o?.iconUrl ?? "",
|
|
468
470
|
});
|
|
469
471
|
},
|
|
470
472
|
} as const;
|
|
@@ -17,8 +17,12 @@ import {
|
|
|
17
17
|
|
|
18
18
|
const COPIED_FEEDBACK_MS = 2000;
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// ArtifactPreviewContent — standalone content component
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
|
|
24
|
+
/** Props for {@link ArtifactPreviewContent}. */
|
|
25
|
+
export interface ArtifactPreviewContentProps {
|
|
22
26
|
/** The execution artifact to preview. */
|
|
23
27
|
readonly artifact: ExecutionArtifact;
|
|
24
28
|
/** ID of the execution that produced this artifact. */
|
|
@@ -33,9 +37,7 @@ export interface ArtifactPreviewModalProps {
|
|
|
33
37
|
* - `false` — CTA renders as a disabled secondary button
|
|
34
38
|
*/
|
|
35
39
|
readonly isTerminal: boolean;
|
|
36
|
-
/**
|
|
37
|
-
readonly open: boolean;
|
|
38
|
-
/** Called when the modal should close (Escape key or close button). */
|
|
40
|
+
/** Called when the close button is clicked. */
|
|
39
41
|
readonly onClose: () => void;
|
|
40
42
|
/**
|
|
41
43
|
* Called after a resource is successfully applied or a skill package
|
|
@@ -43,19 +45,20 @@ export interface ArtifactPreviewModalProps {
|
|
|
43
45
|
* as showing a toast or navigating to the Library.
|
|
44
46
|
*/
|
|
45
47
|
readonly onApplied?: (result: ApplyResourceResult) => void;
|
|
46
|
-
/** Additional CSS classes for the
|
|
48
|
+
/** Additional CSS classes for the root container. */
|
|
47
49
|
readonly className?: string;
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
/**
|
|
51
|
-
*
|
|
52
|
-
* Stigmer resource detection, and Apply/Push CTA.
|
|
53
|
+
* Artifact preview content with detection pipeline and Apply/Push CTA.
|
|
53
54
|
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
55
|
+
* Renders the header (name, size, detection badge, close button),
|
|
56
|
+
* content body (file content or directory listing), and action bar
|
|
57
|
+
* (copy, download, Apply/Push). The parent is responsible for rendering
|
|
58
|
+
* it inside a `<dialog>`, modal, sheet, overlay, or inline context as
|
|
59
|
+
* needed.
|
|
57
60
|
*
|
|
58
|
-
*
|
|
61
|
+
* Orchestrates the same detection pipeline as {@link ArtifactCard}:
|
|
59
62
|
*
|
|
60
63
|
* - **FILE artifacts**: Fetches text content via {@link useArtifactContent},
|
|
61
64
|
* renders via {@link ArtifactContentRenderer} (markdown, YAML, JSON, or
|
|
@@ -66,75 +69,47 @@ export interface ArtifactPreviewModalProps {
|
|
|
66
69
|
* `artifact.entries` and detects skill packages via
|
|
67
70
|
* {@link useDetectSkillPackage}.
|
|
68
71
|
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
72
|
+
* Content fetching begins immediately on mount. Unmounting the component
|
|
73
|
+
* resets all internal state (detection, apply result, clipboard). For
|
|
74
|
+
* gated rendering (e.g. only when a dialog is open), conditionally
|
|
75
|
+
* mount this component rather than passing an `active` flag.
|
|
71
76
|
*
|
|
72
77
|
* @example
|
|
73
78
|
* ```tsx
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
* open
|
|
84
|
-
* onClose={() => setPreviewArtifact(null)}
|
|
85
|
-
* onApplied={(result) => toast(`${result.kind} applied`)}
|
|
86
|
-
* />
|
|
87
|
-
* )}
|
|
79
|
+
* // Inside a dialog, modal, or overlay:
|
|
80
|
+
* <ArtifactPreviewContent
|
|
81
|
+
* artifact={artifact}
|
|
82
|
+
* executionId={execution.id}
|
|
83
|
+
* org={activeOrg}
|
|
84
|
+
* isTerminal={isTerminalPhase(execution.status?.phase)}
|
|
85
|
+
* onClose={() => setOpen(false)}
|
|
86
|
+
* onApplied={(result) => toast(`${result.kind} applied`)}
|
|
87
|
+
* />
|
|
88
88
|
* ```
|
|
89
89
|
*
|
|
90
|
+
* @see {@link ArtifactPreviewModal} — wraps this component in a native `<dialog>`
|
|
90
91
|
* @see {@link ArtifactCard} — compact card that triggers preview via `onPreview`
|
|
91
92
|
* @see {@link useArtifactContent} — content-fetching hook (headless alternative)
|
|
92
93
|
* @see {@link useDetectStigmerResource} — YAML resource detection (headless)
|
|
93
94
|
* @see {@link useDetectSkillPackage} — skill package detection (headless)
|
|
94
95
|
* @see {@link useApplyResource} — apply/push behavior hook (headless)
|
|
95
96
|
*/
|
|
96
|
-
export function
|
|
97
|
+
export function ArtifactPreviewContent({
|
|
97
98
|
artifact,
|
|
98
99
|
executionId,
|
|
99
100
|
org,
|
|
100
101
|
isTerminal,
|
|
101
|
-
open,
|
|
102
102
|
onClose,
|
|
103
103
|
onApplied,
|
|
104
104
|
className,
|
|
105
|
-
}:
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
// ---------------------------------------------------------------------------
|
|
109
|
-
// Native <dialog> lifecycle
|
|
110
|
-
// ---------------------------------------------------------------------------
|
|
111
|
-
|
|
112
|
-
useEffect(() => {
|
|
113
|
-
const dialog = dialogRef.current;
|
|
114
|
-
if (!dialog) return;
|
|
115
|
-
|
|
116
|
-
if (open && !dialog.open) {
|
|
117
|
-
dialog.showModal();
|
|
118
|
-
} else if (!open && dialog.open) {
|
|
119
|
-
dialog.close();
|
|
120
|
-
}
|
|
121
|
-
}, [open]);
|
|
122
|
-
|
|
123
|
-
const handleCancel = useCallback(
|
|
124
|
-
(e: React.SyntheticEvent) => {
|
|
125
|
-
e.preventDefault();
|
|
126
|
-
onClose();
|
|
127
|
-
},
|
|
128
|
-
[onClose],
|
|
129
|
-
);
|
|
105
|
+
}: ArtifactPreviewContentProps) {
|
|
106
|
+
const isDirectory = artifact.kind === ExecutionArtifactKind.DIRECTORY;
|
|
107
|
+
const canFetchContent = !isDirectory && isTextArtifact(artifact);
|
|
130
108
|
|
|
131
109
|
// ---------------------------------------------------------------------------
|
|
132
|
-
// Detection orchestration
|
|
110
|
+
// Detection orchestration
|
|
133
111
|
// ---------------------------------------------------------------------------
|
|
134
112
|
|
|
135
|
-
const isDirectory = artifact.kind === ExecutionArtifactKind.DIRECTORY;
|
|
136
|
-
const canFetchContent = open && !isDirectory && isTextArtifact(artifact);
|
|
137
|
-
|
|
138
113
|
const {
|
|
139
114
|
content,
|
|
140
115
|
contentType,
|
|
@@ -154,8 +129,8 @@ export function ArtifactPreviewModal({
|
|
|
154
129
|
|
|
155
130
|
const { detection: skillDetection, isLoading: isSkillLoading } =
|
|
156
131
|
useDetectSkillPackage(
|
|
157
|
-
isDirectory
|
|
158
|
-
isDirectory
|
|
132
|
+
isDirectory ? artifact : null,
|
|
133
|
+
isDirectory ? executionId : null,
|
|
159
134
|
);
|
|
160
135
|
|
|
161
136
|
// ---------------------------------------------------------------------------
|
|
@@ -223,13 +198,6 @@ export function ArtifactPreviewModal({
|
|
|
223
198
|
onApplied,
|
|
224
199
|
]);
|
|
225
200
|
|
|
226
|
-
useEffect(() => {
|
|
227
|
-
if (!open) {
|
|
228
|
-
setApplyResult(null);
|
|
229
|
-
clearError();
|
|
230
|
-
}
|
|
231
|
-
}, [open, clearError]);
|
|
232
|
-
|
|
233
201
|
// ---------------------------------------------------------------------------
|
|
234
202
|
// Copy to clipboard
|
|
235
203
|
// ---------------------------------------------------------------------------
|
|
@@ -244,10 +212,6 @@ export function ArtifactPreviewModal({
|
|
|
244
212
|
});
|
|
245
213
|
}, [content]);
|
|
246
214
|
|
|
247
|
-
useEffect(() => {
|
|
248
|
-
if (!open) setCopied(false);
|
|
249
|
-
}, [open]);
|
|
250
|
-
|
|
251
215
|
let ctaLabel: string | null = null;
|
|
252
216
|
if (yamlDetection.detected) {
|
|
253
217
|
ctaLabel = `Apply to ${org}`;
|
|
@@ -259,6 +223,159 @@ export function ArtifactPreviewModal({
|
|
|
259
223
|
// Render
|
|
260
224
|
// ---------------------------------------------------------------------------
|
|
261
225
|
|
|
226
|
+
return (
|
|
227
|
+
<div className={cn("flex max-h-[80vh] flex-col", className)}>
|
|
228
|
+
<ContentHeader
|
|
229
|
+
artifact={artifact}
|
|
230
|
+
isDirectory={isDirectory}
|
|
231
|
+
detectionLabel={detectionLabel}
|
|
232
|
+
isDetecting={isDetecting}
|
|
233
|
+
onClose={onClose}
|
|
234
|
+
/>
|
|
235
|
+
|
|
236
|
+
<div className="min-h-0 flex-1 overflow-y-auto border-t border-border">
|
|
237
|
+
{isDirectory ? (
|
|
238
|
+
<DirectoryContentView
|
|
239
|
+
artifact={artifact}
|
|
240
|
+
skillDetection={skillDetection}
|
|
241
|
+
/>
|
|
242
|
+
) : (
|
|
243
|
+
<FileContentStateView
|
|
244
|
+
artifact={artifact}
|
|
245
|
+
content={content}
|
|
246
|
+
contentType={contentType}
|
|
247
|
+
isLoading={isContentLoading}
|
|
248
|
+
error={contentError}
|
|
249
|
+
isTruncated={isTruncated}
|
|
250
|
+
/>
|
|
251
|
+
)}
|
|
252
|
+
</div>
|
|
253
|
+
|
|
254
|
+
<ActionBar
|
|
255
|
+
artifact={artifact}
|
|
256
|
+
isDirectory={isDirectory}
|
|
257
|
+
hasContent={content !== null}
|
|
258
|
+
copied={copied}
|
|
259
|
+
onCopy={handleCopy}
|
|
260
|
+
isDetected={isDetected}
|
|
261
|
+
ctaLabel={ctaLabel}
|
|
262
|
+
isTerminal={isTerminal}
|
|
263
|
+
isApplying={isApplying}
|
|
264
|
+
applyResult={applyResult}
|
|
265
|
+
applyError={applyError}
|
|
266
|
+
onApply={handleApply}
|
|
267
|
+
/>
|
|
268
|
+
|
|
269
|
+
<div
|
|
270
|
+
role="status"
|
|
271
|
+
aria-live="polite"
|
|
272
|
+
aria-atomic="true"
|
|
273
|
+
className="sr-only"
|
|
274
|
+
>
|
|
275
|
+
{copied && "Content copied to clipboard"}
|
|
276
|
+
</div>
|
|
277
|
+
</div>
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// ---------------------------------------------------------------------------
|
|
282
|
+
// ArtifactPreviewModal — thin <dialog> shell
|
|
283
|
+
// ---------------------------------------------------------------------------
|
|
284
|
+
|
|
285
|
+
/** Props for {@link ArtifactPreviewModal}. */
|
|
286
|
+
export interface ArtifactPreviewModalProps {
|
|
287
|
+
/** The execution artifact to preview. */
|
|
288
|
+
readonly artifact: ExecutionArtifact;
|
|
289
|
+
/** ID of the execution that produced this artifact. */
|
|
290
|
+
readonly executionId: string;
|
|
291
|
+
/** Organization slug for the "Apply to [org]" / "Push Skill to [org]" CTA. */
|
|
292
|
+
readonly org: string;
|
|
293
|
+
/**
|
|
294
|
+
* Whether the execution is in a terminal phase (completed, failed,
|
|
295
|
+
* cancelled, terminated). Controls Apply/Push CTA availability:
|
|
296
|
+
*
|
|
297
|
+
* - `true` — CTA renders as an enabled primary button
|
|
298
|
+
* - `false` — CTA renders as a disabled secondary button
|
|
299
|
+
*/
|
|
300
|
+
readonly isTerminal: boolean;
|
|
301
|
+
/** Controls modal visibility. `true` opens the dialog via `showModal()`. */
|
|
302
|
+
readonly open: boolean;
|
|
303
|
+
/** Called when the modal should close (Escape key or close button). */
|
|
304
|
+
readonly onClose: () => void;
|
|
305
|
+
/**
|
|
306
|
+
* Called after a resource is successfully applied or a skill package
|
|
307
|
+
* is pushed. The consumer can use this for post-apply behavior such
|
|
308
|
+
* as showing a toast or navigating to the Library.
|
|
309
|
+
*/
|
|
310
|
+
readonly onApplied?: (result: ApplyResourceResult) => void;
|
|
311
|
+
/** Additional CSS classes for the dialog element. */
|
|
312
|
+
readonly className?: string;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Full preview modal for execution artifacts using a native `<dialog>`.
|
|
317
|
+
*
|
|
318
|
+
* Thin shell around {@link ArtifactPreviewContent} that adds
|
|
319
|
+
* `showModal()` / `close()` lifecycle, `::backdrop` overlay, focus
|
|
320
|
+
* trap, and Escape key handling — with no dependency on
|
|
321
|
+
* `@base-ui/react`.
|
|
322
|
+
*
|
|
323
|
+
* The content component is conditionally mounted when `open` is true,
|
|
324
|
+
* so all internal state (detection, apply result, clipboard) resets
|
|
325
|
+
* automatically when the dialog closes.
|
|
326
|
+
*
|
|
327
|
+
* @example
|
|
328
|
+
* ```tsx
|
|
329
|
+
* const [previewArtifact, setPreviewArtifact] =
|
|
330
|
+
* useState<ExecutionArtifact | null>(null);
|
|
331
|
+
*
|
|
332
|
+
* {previewArtifact && (
|
|
333
|
+
* <ArtifactPreviewModal
|
|
334
|
+
* artifact={previewArtifact}
|
|
335
|
+
* executionId={execution.id}
|
|
336
|
+
* org={activeOrg}
|
|
337
|
+
* isTerminal={isTerminalPhase(execution.status?.phase)}
|
|
338
|
+
* open
|
|
339
|
+
* onClose={() => setPreviewArtifact(null)}
|
|
340
|
+
* onApplied={(result) => toast(`${result.kind} applied`)}
|
|
341
|
+
* />
|
|
342
|
+
* )}
|
|
343
|
+
* ```
|
|
344
|
+
*
|
|
345
|
+
* @see {@link ArtifactPreviewContent} — the content component (use directly for non-dialog contexts)
|
|
346
|
+
* @see {@link ArtifactCard} — compact card that triggers preview via `onPreview`
|
|
347
|
+
*/
|
|
348
|
+
export function ArtifactPreviewModal({
|
|
349
|
+
artifact,
|
|
350
|
+
executionId,
|
|
351
|
+
org,
|
|
352
|
+
isTerminal,
|
|
353
|
+
open,
|
|
354
|
+
onClose,
|
|
355
|
+
onApplied,
|
|
356
|
+
className,
|
|
357
|
+
}: ArtifactPreviewModalProps) {
|
|
358
|
+
const dialogRef = useRef<HTMLDialogElement>(null);
|
|
359
|
+
|
|
360
|
+
useEffect(() => {
|
|
361
|
+
const dialog = dialogRef.current;
|
|
362
|
+
if (!dialog) return;
|
|
363
|
+
|
|
364
|
+
if (open && !dialog.open) {
|
|
365
|
+
dialog.showModal();
|
|
366
|
+
} else if (!open && dialog.open) {
|
|
367
|
+
dialog.close();
|
|
368
|
+
}
|
|
369
|
+
}, [open]);
|
|
370
|
+
|
|
371
|
+
const handleCancel = useCallback(
|
|
372
|
+
(e: React.SyntheticEvent) => {
|
|
373
|
+
e.preventDefault();
|
|
374
|
+
onClose();
|
|
375
|
+
},
|
|
376
|
+
[onClose],
|
|
377
|
+
);
|
|
378
|
+
|
|
262
379
|
return (
|
|
263
380
|
<dialog
|
|
264
381
|
ref={dialogRef}
|
|
@@ -270,57 +387,16 @@ export function ArtifactPreviewModal({
|
|
|
270
387
|
className,
|
|
271
388
|
)}
|
|
272
389
|
>
|
|
273
|
-
|
|
274
|
-
<
|
|
275
|
-
artifact={artifact}
|
|
276
|
-
isDirectory={isDirectory}
|
|
277
|
-
detectionLabel={detectionLabel}
|
|
278
|
-
isDetecting={isDetecting}
|
|
279
|
-
onClose={onClose}
|
|
280
|
-
/>
|
|
281
|
-
|
|
282
|
-
<div className="min-h-0 flex-1 overflow-y-auto border-t border-border">
|
|
283
|
-
{isDirectory ? (
|
|
284
|
-
<DirectoryContentView
|
|
285
|
-
artifact={artifact}
|
|
286
|
-
skillDetection={skillDetection}
|
|
287
|
-
/>
|
|
288
|
-
) : (
|
|
289
|
-
<FileContentStateView
|
|
290
|
-
artifact={artifact}
|
|
291
|
-
content={content}
|
|
292
|
-
contentType={contentType}
|
|
293
|
-
isLoading={isContentLoading}
|
|
294
|
-
error={contentError}
|
|
295
|
-
isTruncated={isTruncated}
|
|
296
|
-
/>
|
|
297
|
-
)}
|
|
298
|
-
</div>
|
|
299
|
-
|
|
300
|
-
<ActionBar
|
|
390
|
+
{open && (
|
|
391
|
+
<ArtifactPreviewContent
|
|
301
392
|
artifact={artifact}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
copied={copied}
|
|
305
|
-
onCopy={handleCopy}
|
|
306
|
-
isDetected={isDetected}
|
|
307
|
-
ctaLabel={ctaLabel}
|
|
393
|
+
executionId={executionId}
|
|
394
|
+
org={org}
|
|
308
395
|
isTerminal={isTerminal}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
applyError={applyError}
|
|
312
|
-
onApply={handleApply}
|
|
396
|
+
onClose={onClose}
|
|
397
|
+
onApplied={onApplied}
|
|
313
398
|
/>
|
|
314
|
-
|
|
315
|
-
<div
|
|
316
|
-
role="status"
|
|
317
|
-
aria-live="polite"
|
|
318
|
-
aria-atomic="true"
|
|
319
|
-
className="sr-only"
|
|
320
|
-
>
|
|
321
|
-
{copied && "Content copied to clipboard"}
|
|
322
|
-
</div>
|
|
323
|
-
</div>
|
|
399
|
+
)}
|
|
324
400
|
</dialog>
|
|
325
401
|
);
|
|
326
402
|
}
|
|
@@ -333,10 +409,10 @@ const FOCUS_RING_CLASSES =
|
|
|
333
409
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:rounded-sm";
|
|
334
410
|
|
|
335
411
|
// ---------------------------------------------------------------------------
|
|
336
|
-
//
|
|
412
|
+
// ContentHeader (internal)
|
|
337
413
|
// ---------------------------------------------------------------------------
|
|
338
414
|
|
|
339
|
-
function
|
|
415
|
+
function ContentHeader({
|
|
340
416
|
artifact,
|
|
341
417
|
isDirectory,
|
|
342
418
|
detectionLabel,
|
|
@@ -603,12 +679,14 @@ function ActionBar({
|
|
|
603
679
|
</button>
|
|
604
680
|
</span>
|
|
605
681
|
) : isDetected && ctaLabel ? (
|
|
606
|
-
<
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
682
|
+
<span data-cursor-target="apply-resource-button">
|
|
683
|
+
<ApplyButton
|
|
684
|
+
label={ctaLabel}
|
|
685
|
+
isTerminal={isTerminal}
|
|
686
|
+
isApplying={isApplying}
|
|
687
|
+
onApply={onApply}
|
|
688
|
+
/>
|
|
689
|
+
</span>
|
|
612
690
|
) : null}
|
|
613
691
|
</div>
|
|
614
692
|
</div>
|