@stigmer/react 0.0.100 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent/AgentPicker.js +1 -1
- package/agent/AgentPicker.js.map +1 -1
- package/agent/__tests__/useDefaultAgent.test.d.ts +2 -0
- package/agent/__tests__/useDefaultAgent.test.d.ts.map +1 -0
- package/agent/__tests__/useDefaultAgent.test.js +252 -0
- package/agent/__tests__/useDefaultAgent.test.js.map +1 -0
- package/agent/useAgent.d.ts +2 -0
- package/agent/useAgent.d.ts.map +1 -1
- package/agent/useAgent.js +14 -37
- package/agent/useAgent.js.map +1 -1
- package/agent/useAgentCount.d.ts +1 -1
- package/agent/useAgentCount.d.ts.map +1 -1
- package/agent/useAgentList.d.ts +2 -2
- package/agent/useAgentList.d.ts.map +1 -1
- package/agent/useDefaultAgent.d.ts +6 -2
- package/agent/useDefaultAgent.d.ts.map +1 -1
- package/agent/useDefaultAgent.js +51 -31
- package/agent/useDefaultAgent.js.map +1 -1
- package/agent-instance/useAgentInstance.d.ts +2 -0
- package/agent-instance/useAgentInstance.d.ts.map +1 -1
- package/agent-instance/useAgentInstance.js +6 -33
- package/agent-instance/useAgentInstance.js.map +1 -1
- package/agent-instance/useAgentInstanceList.d.ts +2 -0
- package/agent-instance/useAgentInstanceList.d.ts.map +1 -1
- package/agent-instance/useAgentInstanceList.js +22 -40
- package/agent-instance/useAgentInstanceList.js.map +1 -1
- package/api-key/useApiKeyList.d.ts +2 -0
- package/api-key/useApiKeyList.d.ts.map +1 -1
- package/api-key/useApiKeyList.js +3 -27
- package/api-key/useApiKeyList.js.map +1 -1
- package/composer/ComposerToolbar.d.ts +1 -5
- package/composer/ComposerToolbar.d.ts.map +1 -1
- package/composer/ComposerToolbar.js +3 -4
- package/composer/ComposerToolbar.js.map +1 -1
- package/composer/ContextChip.d.ts +1 -1
- package/composer/ContextChip.d.ts.map +1 -1
- package/composer/ContextChip.js +1 -0
- package/composer/ContextChip.js.map +1 -1
- package/composer/SessionComposer.d.ts.map +1 -1
- package/composer/SessionComposer.js +77 -4
- package/composer/SessionComposer.js.map +1 -1
- package/composer/icons.d.ts +1 -0
- package/composer/icons.d.ts.map +1 -1
- package/composer/icons.js +3 -0
- package/composer/icons.js.map +1 -1
- package/environment/useEnvironment.d.ts +2 -0
- package/environment/useEnvironment.d.ts.map +1 -1
- package/environment/useEnvironment.js +6 -33
- package/environment/useEnvironment.js.map +1 -1
- package/environment/useEnvironmentList.d.ts +2 -0
- package/environment/useEnvironmentList.d.ts.map +1 -1
- package/environment/useEnvironmentList.js +23 -53
- package/environment/useEnvironmentList.js.map +1 -1
- package/execution/ArtifactPreviewModal.js +1 -1
- package/execution/ArtifactPreviewModal.js.map +1 -1
- package/execution/useArtifactContent.d.ts +4 -2
- package/execution/useArtifactContent.d.ts.map +1 -1
- package/execution/useArtifactContent.js +23 -45
- package/execution/useArtifactContent.js.map +1 -1
- package/iam-policy/usePrincipalsCount.d.ts +2 -0
- package/iam-policy/usePrincipalsCount.d.ts.map +1 -1
- package/iam-policy/usePrincipalsCount.js +7 -46
- package/iam-policy/usePrincipalsCount.js.map +1 -1
- package/iam-policy/useResourceAccess.d.ts +2 -0
- package/iam-policy/useResourceAccess.d.ts.map +1 -1
- package/iam-policy/useResourceAccess.js +12 -47
- package/iam-policy/useResourceAccess.js.map +1 -1
- package/identity-provider/useIdentityProvider.d.ts +2 -0
- package/identity-provider/useIdentityProvider.d.ts.map +1 -1
- package/identity-provider/useIdentityProvider.js +3 -33
- package/identity-provider/useIdentityProvider.js.map +1 -1
- package/identity-provider/useIdentityProviderList.d.ts +2 -0
- package/identity-provider/useIdentityProviderList.d.ts.map +1 -1
- package/identity-provider/useIdentityProviderList.js +7 -33
- package/identity-provider/useIdentityProviderList.js.map +1 -1
- package/index.d.ts +2 -2
- package/index.d.ts.map +1 -1
- package/index.js +1 -1
- package/index.js.map +1 -1
- package/internal/__tests__/useFetch.test.d.ts +2 -0
- package/internal/__tests__/useFetch.test.d.ts.map +1 -0
- package/internal/__tests__/useFetch.test.js +95 -0
- package/internal/__tests__/useFetch.test.js.map +1 -0
- package/internal/useFetch.d.ts +51 -0
- package/internal/useFetch.d.ts.map +1 -0
- package/internal/useFetch.js +75 -0
- package/internal/useFetch.js.map +1 -0
- package/invitation/useInvitationPreview.d.ts +2 -0
- package/invitation/useInvitationPreview.d.ts.map +1 -1
- package/invitation/useInvitationPreview.js +5 -35
- package/invitation/useInvitationPreview.js.map +1 -1
- package/invitation/useOrgInvitations.d.ts +2 -0
- package/invitation/useOrgInvitations.d.ts.map +1 -1
- package/invitation/useOrgInvitations.js +6 -34
- package/invitation/useOrgInvitations.js.map +1 -1
- package/library/ResourceListView.d.ts +2 -2
- package/library/ResourceListView.d.ts.map +1 -1
- package/library/ResourceListView.js +1 -1
- package/library/ResourceListView.js.map +1 -1
- package/library/useDetectSkillPackage.d.ts +1 -1
- package/library/useDetectSkillPackage.d.ts.map +1 -1
- package/mcp-server/McpServerPicker.js +1 -1
- package/mcp-server/McpServerPicker.js.map +1 -1
- package/mcp-server/useMcpServer.d.ts +2 -0
- package/mcp-server/useMcpServer.d.ts.map +1 -1
- package/mcp-server/useMcpServer.js +13 -37
- package/mcp-server/useMcpServer.js.map +1 -1
- package/mcp-server/useMcpServerCount.d.ts +1 -1
- package/mcp-server/useMcpServerCount.d.ts.map +1 -1
- package/mcp-server/useMcpServerList.d.ts +2 -2
- package/mcp-server/useMcpServerList.d.ts.map +1 -1
- package/mcp-server/useOAuthGrantStatus.d.ts +2 -0
- package/mcp-server/useOAuthGrantStatus.d.ts.map +1 -1
- package/mcp-server/useOAuthGrantStatus.js +14 -61
- package/mcp-server/useOAuthGrantStatus.js.map +1 -1
- package/mcp-server/useOrgOAuthApp.d.ts +2 -0
- package/mcp-server/useOrgOAuthApp.d.ts.map +1 -1
- package/mcp-server/useOrgOAuthApp.js +19 -43
- package/mcp-server/useOrgOAuthApp.js.map +1 -1
- package/oauth-app/useOAuthAppList.d.ts +2 -0
- package/oauth-app/useOAuthAppList.d.ts.map +1 -1
- package/oauth-app/useOAuthAppList.js +6 -34
- package/oauth-app/useOAuthAppList.js.map +1 -1
- package/organization/useOrganization.d.ts +2 -0
- package/organization/useOrganization.d.ts.map +1 -1
- package/organization/useOrganization.js +3 -33
- package/organization/useOrganization.js.map +1 -1
- package/package.json +4 -4
- package/platform-client/usePlatformClient.d.ts +2 -0
- package/platform-client/usePlatformClient.d.ts.map +1 -1
- package/platform-client/usePlatformClient.js +3 -33
- package/platform-client/usePlatformClient.js.map +1 -1
- package/platform-client/usePlatformClientList.d.ts +2 -0
- package/platform-client/usePlatformClientList.d.ts.map +1 -1
- package/platform-client/usePlatformClientList.js +6 -34
- package/platform-client/usePlatformClientList.js.map +1 -1
- package/runner/RunnerListPanel.d.ts.map +1 -1
- package/runner/RunnerListPanel.js +21 -5
- package/runner/RunnerListPanel.js.map +1 -1
- package/runner/__tests__/phase.test.d.ts +2 -0
- package/runner/__tests__/phase.test.d.ts.map +1 -0
- package/runner/__tests__/phase.test.js +33 -0
- package/runner/__tests__/phase.test.js.map +1 -0
- package/runner/__tests__/useRunnerList.test.d.ts +2 -0
- package/runner/__tests__/useRunnerList.test.d.ts.map +1 -0
- package/runner/__tests__/useRunnerList.test.js +68 -0
- package/runner/__tests__/useRunnerList.test.js.map +1 -0
- package/runner/index.d.ts +3 -1
- package/runner/index.d.ts.map +1 -1
- package/runner/index.js +2 -1
- package/runner/index.js.map +1 -1
- package/runner/phase.d.ts +13 -0
- package/runner/phase.d.ts.map +1 -1
- package/runner/phase.js +15 -0
- package/runner/phase.js.map +1 -1
- package/runner/useRunnerCredential.d.ts +66 -0
- package/runner/useRunnerCredential.d.ts.map +1 -0
- package/runner/useRunnerCredential.js +50 -0
- package/runner/useRunnerCredential.js.map +1 -0
- package/runner/useRunnerList.d.ts +21 -0
- package/runner/useRunnerList.d.ts.map +1 -1
- package/runner/useRunnerList.js +9 -36
- package/runner/useRunnerList.js.map +1 -1
- package/search/useResourceCount.d.ts +2 -1
- package/search/useResourceCount.d.ts.map +1 -1
- package/search/useResourceCount.js +13 -37
- package/search/useResourceCount.js.map +1 -1
- package/search/useResourceList.d.ts +2 -1
- package/search/useResourceList.d.ts.map +1 -1
- package/search/useResourceList.js +26 -46
- package/search/useResourceList.js.map +1 -1
- package/search/useResourceSearch.d.ts +4 -2
- package/search/useResourceSearch.d.ts.map +1 -1
- package/search/useResourceSearch.js +7 -27
- package/search/useResourceSearch.js.map +1 -1
- package/session/useNewSessionFlow.d.ts.map +1 -1
- package/session/useNewSessionFlow.js +26 -1
- package/session/useNewSessionFlow.js.map +1 -1
- package/session/useSession.d.ts +3 -1
- package/session/useSession.d.ts.map +1 -1
- package/session/useSession.js +3 -33
- package/session/useSession.js.map +1 -1
- package/session/useSessionExecutions.d.ts +3 -1
- package/session/useSessionExecutions.d.ts.map +1 -1
- package/session/useSessionExecutions.js +6 -34
- package/session/useSessionExecutions.js.map +1 -1
- package/session/useSessionList.d.ts +5 -3
- package/session/useSessionList.d.ts.map +1 -1
- package/session/useSessionList.js +9 -31
- package/session/useSessionList.js.map +1 -1
- package/skill/SkillPicker.js +1 -1
- package/skill/SkillPicker.js.map +1 -1
- package/skill/useSkill.d.ts +2 -0
- package/skill/useSkill.d.ts.map +1 -1
- package/skill/useSkill.js +13 -37
- package/skill/useSkill.js.map +1 -1
- package/skill/useSkillCount.d.ts +1 -1
- package/skill/useSkillCount.d.ts.map +1 -1
- package/skill/useSkillList.d.ts +2 -2
- package/skill/useSkillList.d.ts.map +1 -1
- package/src/agent/AgentPicker.tsx +1 -1
- package/src/agent/__tests__/useDefaultAgent.test.tsx +308 -0
- package/src/agent/useAgent.ts +19 -41
- package/src/agent/useAgentCount.ts +1 -1
- package/src/agent/useAgentList.ts +2 -2
- package/src/agent/useDefaultAgent.ts +67 -35
- package/src/agent-instance/useAgentInstance.ts +13 -37
- package/src/agent-instance/useAgentInstanceList.ts +31 -47
- package/src/api-key/useApiKeyList.ts +9 -32
- package/src/composer/ComposerToolbar.tsx +1 -22
- package/src/composer/ContextChip.tsx +2 -1
- package/src/composer/SessionComposer.tsx +206 -5
- package/src/composer/icons.tsx +27 -0
- package/src/environment/useEnvironment.ts +13 -37
- package/src/environment/useEnvironmentList.ts +31 -58
- package/src/execution/ArtifactPreviewModal.tsx +2 -2
- package/src/execution/useArtifactContent.ts +48 -65
- package/src/iam-policy/usePrincipalsCount.ts +17 -53
- package/src/iam-policy/useResourceAccess.ts +18 -55
- package/src/identity-provider/useIdentityProvider.ts +9 -39
- package/src/identity-provider/useIdentityProviderList.ts +14 -40
- package/src/index.ts +4 -0
- package/src/internal/__tests__/useFetch.test.ts +133 -0
- package/src/internal/useFetch.ts +121 -0
- package/src/invitation/useInvitationPreview.ts +14 -40
- package/src/invitation/useOrgInvitations.ts +15 -41
- package/src/library/ResourceListView.tsx +3 -3
- package/src/library/useDetectSkillPackage.ts +1 -1
- package/src/mcp-server/McpServerPicker.tsx +1 -1
- package/src/mcp-server/useMcpServer.ts +17 -42
- package/src/mcp-server/useMcpServerCount.ts +1 -1
- package/src/mcp-server/useMcpServerList.ts +2 -2
- package/src/mcp-server/useOAuthGrantStatus.ts +31 -69
- package/src/mcp-server/useOrgOAuthApp.ts +34 -51
- package/src/oauth-app/useOAuthAppList.ts +15 -41
- package/src/organization/useOrganization.ts +9 -38
- package/src/platform-client/usePlatformClient.ts +9 -39
- package/src/platform-client/usePlatformClientList.ts +14 -42
- package/src/runner/RunnerListPanel.tsx +49 -41
- package/src/runner/__tests__/phase.test.ts +35 -0
- package/src/runner/__tests__/useRunnerList.test.tsx +96 -0
- package/src/runner/index.ts +7 -0
- package/src/runner/phase.ts +16 -0
- package/src/runner/useRunnerCredential.ts +89 -0
- package/src/runner/useRunnerList.ts +36 -44
- package/src/search/useResourceCount.ts +20 -48
- package/src/search/useResourceList.ts +40 -57
- package/src/search/useResourceSearch.ts +22 -43
- package/src/session/useNewSessionFlow.ts +35 -1
- package/src/session/useSession.ts +10 -39
- package/src/session/useSessionExecutions.ts +20 -46
- package/src/session/useSessionList.ts +21 -42
- package/src/skill/SkillPicker.tsx +1 -1
- package/src/skill/useSkill.ts +17 -42
- package/src/skill/useSkillCount.ts +1 -1
- package/src/skill/useSkillList.ts +2 -2
- package/src/usage/useOrgUsageReport.ts +18 -46
- package/styles.css +1 -1
- package/usage/useOrgUsageReport.d.ts +2 -0
- package/usage/useOrgUsageReport.d.ts.map +1 -1
- package/usage/useOrgUsageReport.js +5 -35
- package/usage/useOrgUsageReport.js.map +1 -1
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useCallback, useEffect, useState } from "react";
|
|
4
3
|
import type { PlatformClient } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/api_pb";
|
|
5
4
|
import { useStigmer } from "../hooks";
|
|
6
|
-
import {
|
|
5
|
+
import { useFetch } from "../internal/useFetch";
|
|
7
6
|
|
|
8
7
|
/** Return value of {@link usePlatformClient}. */
|
|
9
8
|
export interface UsePlatformClientReturn {
|
|
@@ -11,6 +10,8 @@ export interface UsePlatformClientReturn {
|
|
|
11
10
|
readonly platformClient: PlatformClient | null;
|
|
12
11
|
/** `true` while the initial fetch or a refetch is in flight. */
|
|
13
12
|
readonly isLoading: boolean;
|
|
13
|
+
/** `true` while a background refetch is in flight and stale data is shown. */
|
|
14
|
+
readonly isRefetching: boolean;
|
|
14
15
|
/** Error from the last failed request, or `null` when healthy. */
|
|
15
16
|
readonly error: Error | null;
|
|
16
17
|
/** Discard cached data and re-fetch from the server. */
|
|
@@ -44,43 +45,12 @@ export function usePlatformClient(
|
|
|
44
45
|
id: string | null,
|
|
45
46
|
): UsePlatformClientReturn {
|
|
46
47
|
const stigmer = useStigmer();
|
|
47
|
-
const [platformClient, setPlatformClient] =
|
|
48
|
-
useState<PlatformClient | null>(null);
|
|
49
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
50
|
-
const [error, setError] = useState<Error | null>(null);
|
|
51
|
-
const [fetchKey, setFetchKey] = useState(0);
|
|
52
48
|
|
|
53
|
-
const
|
|
49
|
+
const { data: platformClient, isLoading, isRefetching, error, refetch } = useFetch(
|
|
50
|
+
id ? () => stigmer.platformclient.get(id) : null,
|
|
51
|
+
[id, stigmer],
|
|
52
|
+
null as PlatformClient | null,
|
|
53
|
+
);
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
if (!id) {
|
|
57
|
-
setPlatformClient(null);
|
|
58
|
-
setIsLoading(false);
|
|
59
|
-
setError(null);
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const cancelled = { current: false };
|
|
64
|
-
setIsLoading(true);
|
|
65
|
-
setError(null);
|
|
66
|
-
|
|
67
|
-
stigmer.platformclient.get(id).then(
|
|
68
|
-
(result) => {
|
|
69
|
-
if (cancelled.current) return;
|
|
70
|
-
setPlatformClient(result);
|
|
71
|
-
setIsLoading(false);
|
|
72
|
-
},
|
|
73
|
-
(err) => {
|
|
74
|
-
if (cancelled.current) return;
|
|
75
|
-
setError(toError(err));
|
|
76
|
-
setIsLoading(false);
|
|
77
|
-
},
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
return () => {
|
|
81
|
-
cancelled.current = true;
|
|
82
|
-
};
|
|
83
|
-
}, [id, stigmer, fetchKey]);
|
|
84
|
-
|
|
85
|
-
return { platformClient, isLoading, error, refetch };
|
|
55
|
+
return { platformClient, isLoading, isRefetching, error, refetch };
|
|
86
56
|
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useCallback, useEffect, useState } from "react";
|
|
4
3
|
import { create } from "@bufbuild/protobuf";
|
|
5
4
|
import type { PlatformClient } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/api_pb";
|
|
6
5
|
import { ListPlatformClientsByOrgInputSchema } from "@stigmer/protos/ai/stigmer/iam/platformclient/v1/io_pb";
|
|
7
6
|
import { useStigmer } from "../hooks";
|
|
8
|
-
import {
|
|
7
|
+
import { useFetch } from "../internal/useFetch";
|
|
9
8
|
|
|
10
9
|
/** Return value of {@link usePlatformClientList}. */
|
|
11
10
|
export interface UsePlatformClientListReturn {
|
|
@@ -13,6 +12,8 @@ export interface UsePlatformClientListReturn {
|
|
|
13
12
|
readonly platformClients: readonly PlatformClient[];
|
|
14
13
|
/** `true` while the initial fetch or a refetch is in flight. */
|
|
15
14
|
readonly isLoading: boolean;
|
|
15
|
+
/** `true` while a background refetch is in flight and stale data is shown. */
|
|
16
|
+
readonly isRefetching: boolean;
|
|
16
17
|
/** Error from the last failed request, or `null` when healthy. */
|
|
17
18
|
readonly error: Error | null;
|
|
18
19
|
/** Discard cached data and re-fetch from the server. */
|
|
@@ -51,46 +52,17 @@ export function usePlatformClientList(
|
|
|
51
52
|
org: string | null,
|
|
52
53
|
): UsePlatformClientListReturn {
|
|
53
54
|
const stigmer = useStigmer();
|
|
54
|
-
const [platformClients, setPlatformClients] = useState<PlatformClient[]>([]);
|
|
55
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
56
|
-
const [error, setError] = useState<Error | null>(null);
|
|
57
|
-
const [fetchKey, setFetchKey] = useState(0);
|
|
58
55
|
|
|
59
|
-
const
|
|
56
|
+
const { data: platformClients, isLoading, isRefetching, error, refetch } = useFetch(
|
|
57
|
+
org
|
|
58
|
+
? () =>
|
|
59
|
+
stigmer.platformclient
|
|
60
|
+
.listByOrg(create(ListPlatformClientsByOrgInputSchema, { org }))
|
|
61
|
+
.then((r) => [...r.entries])
|
|
62
|
+
: null,
|
|
63
|
+
[org, stigmer],
|
|
64
|
+
[] as PlatformClient[],
|
|
65
|
+
);
|
|
60
66
|
|
|
61
|
-
|
|
62
|
-
if (!org) {
|
|
63
|
-
setPlatformClients([]);
|
|
64
|
-
setIsLoading(false);
|
|
65
|
-
setError(null);
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
const cancelled = { current: false };
|
|
70
|
-
setIsLoading(true);
|
|
71
|
-
setError(null);
|
|
72
|
-
|
|
73
|
-
stigmer.platformclient
|
|
74
|
-
.listByOrg(
|
|
75
|
-
create(ListPlatformClientsByOrgInputSchema, { org }),
|
|
76
|
-
)
|
|
77
|
-
.then(
|
|
78
|
-
(result) => {
|
|
79
|
-
if (cancelled.current) return;
|
|
80
|
-
setPlatformClients([...result.entries]);
|
|
81
|
-
setIsLoading(false);
|
|
82
|
-
},
|
|
83
|
-
(err) => {
|
|
84
|
-
if (cancelled.current) return;
|
|
85
|
-
setError(toError(err));
|
|
86
|
-
setIsLoading(false);
|
|
87
|
-
},
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
return () => {
|
|
91
|
-
cancelled.current = true;
|
|
92
|
-
};
|
|
93
|
-
}, [org, stigmer, fetchKey]);
|
|
94
|
-
|
|
95
|
-
return { platformClients, isLoading, error, refetch };
|
|
67
|
+
return { platformClients, isLoading, isRefetching, error, refetch };
|
|
96
68
|
}
|
|
@@ -17,12 +17,14 @@ import { useStopRunner } from "./useStopRunner";
|
|
|
17
17
|
import { useDeleteRunner } from "./useDeleteRunner";
|
|
18
18
|
import {
|
|
19
19
|
isActivePhase,
|
|
20
|
+
isTransitionalPhase,
|
|
20
21
|
phaseLabel,
|
|
21
22
|
phaseDotColor,
|
|
22
23
|
PHASE_SORT_ORDER,
|
|
23
24
|
} from "./phase";
|
|
24
25
|
|
|
25
26
|
const SYSTEM_MANAGED_LABEL = "stigmer.ai/system-managed";
|
|
27
|
+
const TRANSITIONAL_POLL_MS = 5_000;
|
|
26
28
|
|
|
27
29
|
type ConfirmingState = {
|
|
28
30
|
readonly runnerId: string;
|
|
@@ -109,11 +111,21 @@ export function RunnerListPanel({
|
|
|
109
111
|
onDeleted,
|
|
110
112
|
className,
|
|
111
113
|
}: RunnerListPanelProps) {
|
|
114
|
+
const [hasTransitional, setHasTransitional] = useState(false);
|
|
112
115
|
const { runners, isLoading, error, refetch } = useRunnerList(org, {
|
|
113
116
|
includeSystemManaged,
|
|
117
|
+
refetchInterval: hasTransitional ? TRANSITIONAL_POLL_MS : false,
|
|
114
118
|
});
|
|
115
119
|
const [confirming, setConfirming] = useState<ConfirmingState>(null);
|
|
116
120
|
|
|
121
|
+
useEffect(() => {
|
|
122
|
+
setHasTransitional(
|
|
123
|
+
runners.some((r) =>
|
|
124
|
+
isTransitionalPhase(r.status?.phase ?? RunnerPhase.UNSPECIFIED),
|
|
125
|
+
),
|
|
126
|
+
);
|
|
127
|
+
}, [runners]);
|
|
128
|
+
|
|
117
129
|
if (onRefetchRef) {
|
|
118
130
|
onRefetchRef(refetch);
|
|
119
131
|
}
|
|
@@ -154,7 +166,7 @@ export function RunnerListPanel({
|
|
|
154
166
|
{Array.from({ length: 3 }, (_, i) => (
|
|
155
167
|
<div
|
|
156
168
|
key={i}
|
|
157
|
-
className="bg-muted-subtle h-
|
|
169
|
+
className="bg-muted-subtle h-[4.25rem] animate-pulse rounded-lg"
|
|
158
170
|
/>
|
|
159
171
|
))}
|
|
160
172
|
</div>
|
|
@@ -328,54 +340,44 @@ function RunnerRow({
|
|
|
328
340
|
);
|
|
329
341
|
}
|
|
330
342
|
|
|
343
|
+
const metaSegments: string[] = [];
|
|
344
|
+
if (hostname) metaSegments.push(hostname);
|
|
345
|
+
if (osArch) metaSegments.push(osArch);
|
|
346
|
+
if (active) metaSegments.push(`${executions} exec${executions !== 1 ? "s" : ""}`);
|
|
347
|
+
if (lastHeartbeat) {
|
|
348
|
+
metaSegments.push(formatRelativeTime(timestampDate(lastHeartbeat)));
|
|
349
|
+
}
|
|
350
|
+
|
|
331
351
|
return (
|
|
332
352
|
<div
|
|
333
353
|
role="listitem"
|
|
334
354
|
className={cn(
|
|
335
|
-
"flex items-
|
|
355
|
+
"flex items-start gap-3 rounded-lg border border-border-muted px-3 py-2.5",
|
|
336
356
|
"hover:border-border transition-colors",
|
|
337
357
|
!active && "opacity-60",
|
|
338
358
|
)}
|
|
339
359
|
>
|
|
340
|
-
<RunnerIcon size={
|
|
341
|
-
|
|
342
|
-
{/* Name + phase badge */}
|
|
343
|
-
<div className="flex min-w-0 flex-1 items-center gap-2">
|
|
344
|
-
<span className="truncate text-sm font-medium text-foreground">
|
|
345
|
-
{name}
|
|
346
|
-
</span>
|
|
347
|
-
{systemManaged && (
|
|
348
|
-
<span className="shrink-0 rounded bg-muted px-1.5 py-0.5 text-[0.6rem] font-medium text-muted-foreground">
|
|
349
|
-
System
|
|
350
|
-
</span>
|
|
351
|
-
)}
|
|
352
|
-
<PhaseBadge phase={phase} />
|
|
353
|
-
</div>
|
|
360
|
+
<RunnerIcon size={16} className="mt-0.5" />
|
|
354
361
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
<span className="
|
|
359
|
-
{
|
|
360
|
-
</span>
|
|
361
|
-
)}
|
|
362
|
-
{osArch && (
|
|
363
|
-
<span className="font-mono text-[0.65rem]">{osArch}</span>
|
|
364
|
-
)}
|
|
365
|
-
{version && (
|
|
366
|
-
<span className="font-mono text-[0.65rem]">v{version}</span>
|
|
367
|
-
)}
|
|
368
|
-
{active && (
|
|
369
|
-
<span title="Current executions">
|
|
370
|
-
{executions} exec{executions !== 1 ? "s" : ""}
|
|
371
|
-
</span>
|
|
372
|
-
)}
|
|
373
|
-
{lastHeartbeat && (
|
|
374
|
-
<span
|
|
375
|
-
title={`Last heartbeat: ${timestampDate(lastHeartbeat).toISOString()}`}
|
|
376
|
-
>
|
|
377
|
-
{formatRelativeTime(timestampDate(lastHeartbeat))}
|
|
362
|
+
<div className="min-w-0 flex-1">
|
|
363
|
+
{/* Line 1: name + badges + phase */}
|
|
364
|
+
<div className="flex items-center gap-2">
|
|
365
|
+
<span className="truncate text-sm font-medium text-foreground">
|
|
366
|
+
{name}
|
|
378
367
|
</span>
|
|
368
|
+
{systemManaged && (
|
|
369
|
+
<span className="shrink-0 rounded bg-muted px-1.5 py-0.5 text-[0.6rem] font-medium text-muted-foreground">
|
|
370
|
+
System
|
|
371
|
+
</span>
|
|
372
|
+
)}
|
|
373
|
+
<PhaseBadge phase={phase} />
|
|
374
|
+
</div>
|
|
375
|
+
|
|
376
|
+
{/* Line 2: metadata */}
|
|
377
|
+
{metaSegments.length > 0 && (
|
|
378
|
+
<p className="mt-0.5 truncate text-[0.65rem] text-muted-foreground">
|
|
379
|
+
{metaSegments.join(" \u00b7 ")}
|
|
380
|
+
</p>
|
|
379
381
|
)}
|
|
380
382
|
</div>
|
|
381
383
|
|
|
@@ -627,7 +629,13 @@ function formatRelativeTime(date: Date): string {
|
|
|
627
629
|
// Icons
|
|
628
630
|
// ---------------------------------------------------------------------------
|
|
629
631
|
|
|
630
|
-
function RunnerIcon({
|
|
632
|
+
function RunnerIcon({
|
|
633
|
+
size = 14,
|
|
634
|
+
className,
|
|
635
|
+
}: {
|
|
636
|
+
size?: number;
|
|
637
|
+
className?: string;
|
|
638
|
+
}) {
|
|
631
639
|
return (
|
|
632
640
|
<svg
|
|
633
641
|
width={size}
|
|
@@ -639,7 +647,7 @@ function RunnerIcon({ size = 14 }: { size?: number }) {
|
|
|
639
647
|
strokeLinecap="round"
|
|
640
648
|
strokeLinejoin="round"
|
|
641
649
|
aria-hidden="true"
|
|
642
|
-
className="shrink-0 text-muted-foreground"
|
|
650
|
+
className={cn("shrink-0 text-muted-foreground", className)}
|
|
643
651
|
>
|
|
644
652
|
<rect x="4" y="4" width="16" height="16" rx="2" />
|
|
645
653
|
<rect x="9" y="9" width="6" height="6" />
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { RunnerPhase } from "@stigmer/protos/ai/stigmer/agentic/runner/v1/enum_pb";
|
|
3
|
+
import { isTransitionalPhase, isActivePhase } from "../phase";
|
|
4
|
+
|
|
5
|
+
describe("isTransitionalPhase", () => {
|
|
6
|
+
it("returns true for PENDING", () => {
|
|
7
|
+
expect(isTransitionalPhase(RunnerPhase.PENDING)).toBe(true);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it.each([
|
|
11
|
+
["READY", RunnerPhase.READY],
|
|
12
|
+
["BUSY", RunnerPhase.BUSY],
|
|
13
|
+
["STOPPED", RunnerPhase.STOPPED],
|
|
14
|
+
["FAILED", RunnerPhase.FAILED],
|
|
15
|
+
["UNSPECIFIED", RunnerPhase.UNSPECIFIED],
|
|
16
|
+
] as const)("returns false for %s", (_label, phase) => {
|
|
17
|
+
expect(isTransitionalPhase(phase)).toBe(false);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("is disjoint from isActivePhase", () => {
|
|
21
|
+
const allPhases = [
|
|
22
|
+
RunnerPhase.READY,
|
|
23
|
+
RunnerPhase.BUSY,
|
|
24
|
+
RunnerPhase.PENDING,
|
|
25
|
+
RunnerPhase.STOPPED,
|
|
26
|
+
RunnerPhase.FAILED,
|
|
27
|
+
RunnerPhase.UNSPECIFIED,
|
|
28
|
+
];
|
|
29
|
+
for (const phase of allPhases) {
|
|
30
|
+
if (isTransitionalPhase(phase)) {
|
|
31
|
+
expect(isActivePhase(phase)).toBe(false);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { renderHook, act } from "@testing-library/react";
|
|
3
|
+
import type { ReactNode } from "react";
|
|
4
|
+
import { create } from "@bufbuild/protobuf";
|
|
5
|
+
import {
|
|
6
|
+
RunnerSchema,
|
|
7
|
+
RunnerStatusSchema,
|
|
8
|
+
} from "@stigmer/protos/ai/stigmer/agentic/runner/v1/api_pb";
|
|
9
|
+
import { RunnerPhase } from "@stigmer/protos/ai/stigmer/agentic/runner/v1/enum_pb";
|
|
10
|
+
import { ApiResourceMetadataSchema } from "@stigmer/protos/ai/stigmer/commons/apiresource/metadata_pb";
|
|
11
|
+
import type { Stigmer } from "@stigmer/sdk";
|
|
12
|
+
import { StigmerContext } from "../../context";
|
|
13
|
+
import { useRunnerList } from "../useRunnerList";
|
|
14
|
+
|
|
15
|
+
function makeRunner(id: string, name: string, phase: RunnerPhase) {
|
|
16
|
+
const runner = create(RunnerSchema);
|
|
17
|
+
runner.metadata = create(ApiResourceMetadataSchema);
|
|
18
|
+
runner.metadata.id = id;
|
|
19
|
+
runner.metadata.name = name;
|
|
20
|
+
runner.status = create(RunnerStatusSchema);
|
|
21
|
+
runner.status.phase = phase;
|
|
22
|
+
return runner;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function buildMockClient(listMock: ReturnType<typeof vi.fn>) {
|
|
26
|
+
return {
|
|
27
|
+
runner: { list: listMock },
|
|
28
|
+
} as unknown as Stigmer;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function makeWrapper(client: Stigmer) {
|
|
32
|
+
return ({ children }: { children: ReactNode }) => (
|
|
33
|
+
<StigmerContext.Provider value={client}>
|
|
34
|
+
{children}
|
|
35
|
+
</StigmerContext.Provider>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function flush(): Promise<void> {
|
|
40
|
+
await act(async () => {
|
|
41
|
+
await Promise.resolve();
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
describe("useRunnerList — refetchInterval", () => {
|
|
46
|
+
let listMock: ReturnType<typeof vi.fn>;
|
|
47
|
+
let client: Stigmer;
|
|
48
|
+
|
|
49
|
+
beforeEach(() => {
|
|
50
|
+
vi.useFakeTimers();
|
|
51
|
+
listMock = vi.fn();
|
|
52
|
+
client = buildMockClient(listMock);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
afterEach(() => {
|
|
56
|
+
vi.useRealTimers();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("polls when refetchInterval is set", async () => {
|
|
60
|
+
const runners = [makeRunner("r1", "dev", RunnerPhase.PENDING)];
|
|
61
|
+
listMock.mockResolvedValue({ items: runners });
|
|
62
|
+
|
|
63
|
+
const { result } = renderHook(
|
|
64
|
+
() => useRunnerList("acme", { refetchInterval: 2000 }),
|
|
65
|
+
{ wrapper: makeWrapper(client) },
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
// Initial fetch.
|
|
69
|
+
await flush();
|
|
70
|
+
expect(listMock).toHaveBeenCalledTimes(1);
|
|
71
|
+
expect(result.current.runners).toHaveLength(1);
|
|
72
|
+
|
|
73
|
+
// Advance by one interval.
|
|
74
|
+
await act(async () => {
|
|
75
|
+
await vi.advanceTimersByTimeAsync(2000);
|
|
76
|
+
});
|
|
77
|
+
expect(listMock).toHaveBeenCalledTimes(2);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("does not poll when refetchInterval is false", async () => {
|
|
81
|
+
listMock.mockResolvedValue({ items: [] });
|
|
82
|
+
|
|
83
|
+
renderHook(
|
|
84
|
+
() => useRunnerList("acme", { refetchInterval: false }),
|
|
85
|
+
{ wrapper: makeWrapper(client) },
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
await flush();
|
|
89
|
+
expect(listMock).toHaveBeenCalledTimes(1);
|
|
90
|
+
|
|
91
|
+
await act(async () => {
|
|
92
|
+
await vi.advanceTimersByTimeAsync(10_000);
|
|
93
|
+
});
|
|
94
|
+
expect(listMock).toHaveBeenCalledTimes(1);
|
|
95
|
+
});
|
|
96
|
+
});
|
package/src/runner/index.ts
CHANGED
|
@@ -11,6 +11,12 @@ export type {
|
|
|
11
11
|
LaunchLocalRunnerResult,
|
|
12
12
|
} from "./useLaunchLocalRunner";
|
|
13
13
|
|
|
14
|
+
export { useRunnerCredential } from "./useRunnerCredential";
|
|
15
|
+
export type {
|
|
16
|
+
RunnerCredential,
|
|
17
|
+
UseRunnerCredentialReturn,
|
|
18
|
+
} from "./useRunnerCredential";
|
|
19
|
+
|
|
14
20
|
export { useStopRunner } from "./useStopRunner";
|
|
15
21
|
export type {
|
|
16
22
|
StopRunnerInput,
|
|
@@ -30,5 +36,6 @@ export {
|
|
|
30
36
|
phaseLabel,
|
|
31
37
|
phaseDotColor,
|
|
32
38
|
isActivePhase,
|
|
39
|
+
isTransitionalPhase,
|
|
33
40
|
PHASE_SORT_ORDER,
|
|
34
41
|
} from "./phase";
|
package/src/runner/phase.ts
CHANGED
|
@@ -60,3 +60,19 @@ export function phaseDotColor(phase: RunnerPhase): string {
|
|
|
60
60
|
export function isActivePhase(phase: RunnerPhase): boolean {
|
|
61
61
|
return phase === RunnerPhase.READY || phase === RunnerPhase.BUSY;
|
|
62
62
|
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Whether the runner is in a transitional phase whose status is
|
|
66
|
+
* expected to change soon without user action.
|
|
67
|
+
*
|
|
68
|
+
* Currently only `PENDING` — the runner has registered but hasn't
|
|
69
|
+
* completed its startup handshake yet. This is distinct from
|
|
70
|
+
* {@link isActivePhase} (READY | BUSY) where the runner is stable
|
|
71
|
+
* and accepting work.
|
|
72
|
+
*
|
|
73
|
+
* Useful for driving conditional polling: poll while transitional
|
|
74
|
+
* runners exist, stop when all runners reach a stable state.
|
|
75
|
+
*/
|
|
76
|
+
export function isTransitionalPhase(phase: RunnerPhase): boolean {
|
|
77
|
+
return phase === RunnerPhase.PENDING;
|
|
78
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback } from "react";
|
|
4
|
+
import type { Stigmer } from "@stigmer/sdk";
|
|
5
|
+
import { useStigmer } from "../hooks";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Resolved credential bundle for starting a runner sidecar process.
|
|
9
|
+
*
|
|
10
|
+
* Contains everything a CLI sidecar needs to authenticate with the
|
|
11
|
+
* Stigmer backend — the Bearer token (Auth0 JWT, PlatformClient JWT,
|
|
12
|
+
* or API key), the API endpoint, and the organization scope.
|
|
13
|
+
*/
|
|
14
|
+
export interface RunnerCredential {
|
|
15
|
+
/** Bearer token or API key. `null` when no credential is available. */
|
|
16
|
+
readonly token: string | null;
|
|
17
|
+
/** Base URL of the Stigmer API server (e.g., "https://api.stigmer.ai"). */
|
|
18
|
+
readonly endpoint: string;
|
|
19
|
+
/** Organization slug, if provided. */
|
|
20
|
+
readonly org?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Return value of {@link useRunnerCredential}. */
|
|
24
|
+
export interface UseRunnerCredentialReturn {
|
|
25
|
+
/**
|
|
26
|
+
* Resolve the current authentication credential for a runner sidecar.
|
|
27
|
+
*
|
|
28
|
+
* Reads the credential from the {@link Stigmer} client configured in
|
|
29
|
+
* the nearest `StigmerProvider`. Works with any auth mode: static API
|
|
30
|
+
* key, dynamic token provider (Auth0, PlatformClient), or custom
|
|
31
|
+
* transport.
|
|
32
|
+
*
|
|
33
|
+
* @param org - Optional organization slug to include in the result.
|
|
34
|
+
* @returns The credential bundle for the sidecar process.
|
|
35
|
+
*/
|
|
36
|
+
readonly getCredential: (org?: string) => Promise<RunnerCredential>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Behavior hook that resolves the current auth credential for passing
|
|
41
|
+
* to a runner sidecar process.
|
|
42
|
+
*
|
|
43
|
+
* This is the SDK-level abstraction for starting runners from within
|
|
44
|
+
* a desktop or native application — where the app already holds the
|
|
45
|
+
* credential and needs to hand it to a CLI child process. It avoids
|
|
46
|
+
* the `createLaunchToken` / `exchangeLaunchToken` round-trip, which
|
|
47
|
+
* is only needed for cross-process browser-to-desktop handshakes
|
|
48
|
+
* (see {@link useLaunchLocalRunner} for that scenario).
|
|
49
|
+
*
|
|
50
|
+
* The hook reads from `useStigmer()` and calls
|
|
51
|
+
* `client.getAuthCredential()`, so it works identically regardless
|
|
52
|
+
* of auth mode (Auth0 JWT, PlatformClient JWT, API key).
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```tsx
|
|
56
|
+
* function StartRunnerButton({ org }: { org: string }) {
|
|
57
|
+
* const { getCredential } = useRunnerCredential();
|
|
58
|
+
*
|
|
59
|
+
* const handleStart = async () => {
|
|
60
|
+
* const cred = await getCredential(org);
|
|
61
|
+
* // Pass cred.token, cred.endpoint, cred.org to your sidecar
|
|
62
|
+
* await nativeBridge.startRunner({
|
|
63
|
+
* token: cred.token,
|
|
64
|
+
* endpoint: cred.endpoint,
|
|
65
|
+
* org: cred.org,
|
|
66
|
+
* });
|
|
67
|
+
* };
|
|
68
|
+
*
|
|
69
|
+
* return <button onClick={handleStart}>Start Runner</button>;
|
|
70
|
+
* }
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export function useRunnerCredential(): UseRunnerCredentialReturn {
|
|
74
|
+
const stigmer = useStigmer();
|
|
75
|
+
|
|
76
|
+
const getCredential = useCallback(
|
|
77
|
+
async (org?: string): Promise<RunnerCredential> => {
|
|
78
|
+
const token = await stigmer.getAuthCredential();
|
|
79
|
+
return {
|
|
80
|
+
token,
|
|
81
|
+
endpoint: stigmer.baseUrl,
|
|
82
|
+
org,
|
|
83
|
+
};
|
|
84
|
+
},
|
|
85
|
+
[stigmer],
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
return { getCredential };
|
|
89
|
+
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useCallback, useEffect, useState } from "react";
|
|
4
3
|
import { create } from "@bufbuild/protobuf";
|
|
5
4
|
import type { Runner } from "@stigmer/protos/ai/stigmer/agentic/runner/v1/api_pb";
|
|
6
5
|
import { ListRunnersRequestSchema } from "@stigmer/protos/ai/stigmer/agentic/runner/v1/io_pb";
|
|
7
6
|
import { useStigmer } from "../hooks";
|
|
8
|
-
import {
|
|
7
|
+
import { useFetch, type UseFetchOptions } from "../internal/useFetch";
|
|
9
8
|
|
|
10
9
|
const SYSTEM_MANAGED_LABEL = "stigmer.ai/system-managed";
|
|
11
10
|
|
|
@@ -21,6 +20,24 @@ export interface UseRunnerListOptions {
|
|
|
21
20
|
* @default false
|
|
22
21
|
*/
|
|
23
22
|
readonly includeSystemManaged?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Poll interval in milliseconds for automatic re-fetching.
|
|
25
|
+
*
|
|
26
|
+
* When set to a positive number, the hook re-fetches the runner list
|
|
27
|
+
* on a timer. Useful for monitoring status transitions (e.g. Pending
|
|
28
|
+
* to Ready) without requiring the user to navigate away and back.
|
|
29
|
+
*
|
|
30
|
+
* Set to `false` or `0` to disable polling (the default).
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* // Poll every 5 seconds while runners are transitioning
|
|
35
|
+
* const { runners } = useRunnerList("acme", {
|
|
36
|
+
* refetchInterval: hasPendingRunners ? 5000 : false,
|
|
37
|
+
* });
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
readonly refetchInterval?: UseFetchOptions["refetchInterval"];
|
|
24
41
|
}
|
|
25
42
|
|
|
26
43
|
/** Return value of {@link useRunnerList}. */
|
|
@@ -29,6 +46,8 @@ export interface UseRunnerListReturn {
|
|
|
29
46
|
readonly runners: readonly Runner[];
|
|
30
47
|
/** `true` while the fetch is in flight. */
|
|
31
48
|
readonly isLoading: boolean;
|
|
49
|
+
/** `true` while a background refetch is in flight and stale data is shown. */
|
|
50
|
+
readonly isRefetching: boolean;
|
|
32
51
|
/** Error from the last failed fetch, or `null` when healthy. */
|
|
33
52
|
readonly error: Error | null;
|
|
34
53
|
/** Discard cached data and re-fetch the runner list from the server. */
|
|
@@ -62,53 +81,26 @@ export function useRunnerList(
|
|
|
62
81
|
options?: UseRunnerListOptions,
|
|
63
82
|
): UseRunnerListReturn {
|
|
64
83
|
const stigmer = useStigmer();
|
|
65
|
-
const [runners, setRunners] = useState<Runner[]>([]);
|
|
66
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
67
|
-
const [error, setError] = useState<Error | null>(null);
|
|
68
|
-
const [fetchKey, setFetchKey] = useState(0);
|
|
69
|
-
|
|
70
84
|
const includeSystemManaged = options?.includeSystemManaged ?? false;
|
|
85
|
+
const refetchInterval = options?.refetchInterval;
|
|
71
86
|
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const cancelled = { current: false };
|
|
83
|
-
setIsLoading(true);
|
|
84
|
-
setError(null);
|
|
85
|
-
|
|
86
|
-
stigmer.runner
|
|
87
|
-
.list(create(ListRunnersRequestSchema, { org }))
|
|
88
|
-
.then(
|
|
89
|
-
(result) => {
|
|
90
|
-
if (cancelled.current) return;
|
|
91
|
-
|
|
92
|
-
const items = includeSystemManaged
|
|
87
|
+
const { data: runners, isLoading, isRefetching, error, refetch } = useFetch(
|
|
88
|
+
org
|
|
89
|
+
? async () => {
|
|
90
|
+
const result = await stigmer.runner.list(
|
|
91
|
+
create(ListRunnersRequestSchema, { org }),
|
|
92
|
+
);
|
|
93
|
+
return includeSystemManaged
|
|
93
94
|
? result.items
|
|
94
95
|
: result.items.filter(
|
|
95
96
|
(r) => r.metadata?.labels[SYSTEM_MANAGED_LABEL] !== "true",
|
|
96
97
|
);
|
|
98
|
+
}
|
|
99
|
+
: null,
|
|
100
|
+
[stigmer, org, includeSystemManaged],
|
|
101
|
+
[] as Runner[],
|
|
102
|
+
{ refetchInterval },
|
|
103
|
+
);
|
|
97
104
|
|
|
98
|
-
|
|
99
|
-
setIsLoading(false);
|
|
100
|
-
},
|
|
101
|
-
(err) => {
|
|
102
|
-
if (cancelled.current) return;
|
|
103
|
-
setError(toError(err));
|
|
104
|
-
setIsLoading(false);
|
|
105
|
-
},
|
|
106
|
-
);
|
|
107
|
-
|
|
108
|
-
return () => {
|
|
109
|
-
cancelled.current = true;
|
|
110
|
-
};
|
|
111
|
-
}, [stigmer, org, includeSystemManaged, fetchKey]);
|
|
112
|
-
|
|
113
|
-
return { runners, isLoading, error, refetch };
|
|
105
|
+
return { runners, isLoading, isRefetching, error, refetch };
|
|
114
106
|
}
|