@shipfox/client-agent 21.0.0 → 22.0.1
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +24 -0
- package/dist/components/add-custom-provider-card.d.ts.map +1 -1
- package/dist/components/add-custom-provider-card.js +11 -31
- package/dist/components/add-custom-provider-card.js.map +1 -1
- package/dist/components/available-provider-card.d.ts.map +1 -1
- package/dist/components/available-provider-card.js +11 -31
- package/dist/components/available-provider-card.js.map +1 -1
- package/dist/components/available-providers-grid.d.ts +0 -1
- package/dist/components/available-providers-grid.d.ts.map +1 -1
- package/dist/components/available-providers-grid.js +33 -27
- package/dist/components/available-providers-grid.js.map +1 -1
- package/dist/components/harnesses-section.d.ts.map +1 -1
- package/dist/components/harnesses-section.js +152 -146
- package/dist/components/harnesses-section.js.map +1 -1
- package/dist/components/model-provider-grid-skeleton.d.ts +4 -0
- package/dist/components/model-provider-grid-skeleton.d.ts.map +1 -0
- package/dist/components/model-provider-grid-skeleton.js +34 -0
- package/dist/components/model-provider-grid-skeleton.js.map +1 -0
- package/dist/components/model-providers-section.d.ts.map +1 -1
- package/dist/components/model-providers-section.js +268 -281
- package/dist/components/model-providers-section.js.map +1 -1
- package/dist/pages/model-provider-onboarding-page.d.ts.map +1 -1
- package/dist/pages/model-provider-onboarding-page.js +32 -64
- package/dist/pages/model-provider-onboarding-page.js.map +1 -1
- package/dist/routes/agents-settings.js +15 -5
- package/dist/routes/agents-settings.js.map +1 -1
- package/dist/tsconfig.test.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/components/add-custom-provider-card.tsx +9 -23
- package/src/components/available-provider-card.tsx +9 -23
- package/src/components/available-providers-grid.tsx +36 -29
- package/src/components/harnesses-section.tsx +116 -109
- package/src/components/model-provider-grid-skeleton.tsx +21 -0
- package/src/components/model-providers-section.test.tsx +2 -2
- package/src/components/model-providers-section.tsx +208 -200
- package/src/pages/model-provider-onboarding-page.tsx +26 -54
- package/src/routes/agents-settings.tsx +7 -3
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -4,17 +4,16 @@ import { IconButton } from '@shipfox/react-ui/button';
|
|
|
4
4
|
import { Callout } from '@shipfox/react-ui/callout';
|
|
5
5
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@shipfox/react-ui/dropdown-menu';
|
|
6
6
|
import { Icon } from '@shipfox/react-ui/icon';
|
|
7
|
+
import { Panel, PanelBody, PanelRow } from '@shipfox/react-ui/panel';
|
|
7
8
|
import { Skeleton } from '@shipfox/react-ui/skeleton';
|
|
8
9
|
import { toast } from '@shipfox/react-ui/toast';
|
|
9
10
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@shipfox/react-ui/tooltip';
|
|
10
11
|
import { Header, Text } from '@shipfox/react-ui/typography';
|
|
11
|
-
import { cn } from '@shipfox/react-ui/utils';
|
|
12
12
|
import { useRef, useState } from 'react';
|
|
13
13
|
import { DEFAULT_HARNESS, listHarnesses } from '#core/harness-policy.js';
|
|
14
14
|
import { useModelProviderConfigsQuery, useSetDefaultHarnessMutation } from '#hooks/api/model-providers.js';
|
|
15
15
|
import { modelProviderConfigErrorToFormError } from './form-errors.js';
|
|
16
16
|
import { isHarnessAvailable } from './harness-availability.js';
|
|
17
|
-
const SURFACE_CLASS = 'overflow-hidden rounded-8 border border-border-neutral-base bg-background-neutral-base';
|
|
18
17
|
export function WorkspaceHarnessesSection({ workspaceId }) {
|
|
19
18
|
const configsQuery = useModelProviderConfigsQuery(workspaceId);
|
|
20
19
|
const setDefaultHarness = useSetDefaultHarnessMutation();
|
|
@@ -69,149 +68,149 @@ export function WorkspaceHarnessesSection({ workspaceId }) {
|
|
|
69
68
|
className: "flex flex-col gap-group",
|
|
70
69
|
"aria-label": "Harnesses",
|
|
71
70
|
children: [
|
|
72
|
-
/*#__PURE__*/
|
|
71
|
+
/*#__PURE__*/ _jsx("div", {
|
|
73
72
|
className: "flex flex-col gap-tight",
|
|
74
|
-
children:
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}),
|
|
79
|
-
/*#__PURE__*/ _jsx(Text, {
|
|
80
|
-
size: "sm",
|
|
81
|
-
className: "text-foreground-neutral-muted",
|
|
82
|
-
children: "Harnesses available to run agent steps in this workspace."
|
|
83
|
-
})
|
|
84
|
-
]
|
|
73
|
+
children: /*#__PURE__*/ _jsx(Header, {
|
|
74
|
+
variant: "h3",
|
|
75
|
+
children: "Harnesses"
|
|
76
|
+
})
|
|
85
77
|
}),
|
|
86
78
|
configsQuery.isPending ? /*#__PURE__*/ _jsx(HarnessRowsSkeleton, {}) : null,
|
|
87
|
-
configsQuery.isError && configsQuery.data === undefined ? /*#__PURE__*/ _jsx(
|
|
88
|
-
className: cn(SURFACE_CLASS, 'px-row'),
|
|
79
|
+
configsQuery.isError && configsQuery.data === undefined ? /*#__PURE__*/ _jsx(Panel, {
|
|
89
80
|
children: /*#__PURE__*/ _jsx(QueryLoadError, {
|
|
90
81
|
query: configsQuery,
|
|
91
|
-
subject: "harnesses"
|
|
82
|
+
subject: "harnesses",
|
|
83
|
+
variant: "panel"
|
|
92
84
|
})
|
|
93
85
|
}) : null,
|
|
94
|
-
configsQuery.data !== undefined ? /*#__PURE__*/ _jsx(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
86
|
+
configsQuery.data !== undefined ? /*#__PURE__*/ _jsx(Panel, {
|
|
87
|
+
children: /*#__PURE__*/ _jsx(PanelBody, {
|
|
88
|
+
asChild: true,
|
|
89
|
+
children: /*#__PURE__*/ _jsx("ul", {
|
|
90
|
+
children: listHarnesses().map((harness)=>/*#__PURE__*/ _jsx(HarnessRow, {
|
|
91
|
+
harness: harness,
|
|
92
|
+
isDefault: harness.id === defaultHarnessId,
|
|
93
|
+
isAvailable: isHarnessAvailable(harness, configs),
|
|
94
|
+
isSettingDefault: pendingDefaultHarness?.workspaceId === workspaceId,
|
|
95
|
+
defaultError: defaultError?.workspaceId === workspaceId && defaultError.harnessId === harness.id ? defaultError.message : undefined,
|
|
96
|
+
onSetDefault: handleSetDefault
|
|
97
|
+
}, harness.id))
|
|
98
|
+
})
|
|
99
|
+
})
|
|
104
100
|
}) : null
|
|
105
101
|
]
|
|
106
102
|
});
|
|
107
103
|
}
|
|
108
104
|
function HarnessRow({ harness, isDefault, isAvailable, isSettingDefault, defaultError, onSetDefault }) {
|
|
109
105
|
const unavailableCopy = harnessUnavailableCopy(isDefault);
|
|
110
|
-
return /*#__PURE__*/
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
children: /*#__PURE__*/ _jsx(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
106
|
+
return /*#__PURE__*/ _jsx(PanelRow, {
|
|
107
|
+
asChild: true,
|
|
108
|
+
className: "flex-col items-stretch gap-inline",
|
|
109
|
+
children: /*#__PURE__*/ _jsxs("li", {
|
|
110
|
+
children: [
|
|
111
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
112
|
+
className: "flex items-center justify-between gap-cluster",
|
|
113
|
+
children: [
|
|
114
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
115
|
+
className: "flex min-w-0 items-center gap-inline",
|
|
116
|
+
children: [
|
|
117
|
+
isDefault ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
118
|
+
children: [
|
|
119
|
+
/*#__PURE__*/ _jsxs(Tooltip, {
|
|
120
|
+
children: [
|
|
121
|
+
/*#__PURE__*/ _jsx(TooltipTrigger, {
|
|
122
|
+
asChild: true,
|
|
123
|
+
children: /*#__PURE__*/ _jsx("span", {
|
|
124
|
+
className: "inline-flex size-16 shrink-0 items-center justify-center",
|
|
125
|
+
children: /*#__PURE__*/ _jsx(Icon, {
|
|
126
|
+
name: "starLine",
|
|
127
|
+
className: "size-16 text-foreground-neutral-muted",
|
|
128
|
+
"aria-hidden": true
|
|
129
|
+
})
|
|
131
130
|
})
|
|
131
|
+
}),
|
|
132
|
+
/*#__PURE__*/ _jsx(TooltipContent, {
|
|
133
|
+
children: "Default harness"
|
|
132
134
|
})
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
name: "errorWarningLine",
|
|
161
|
-
className: "size-16 text-foreground-warning-base",
|
|
162
|
-
"aria-hidden": true
|
|
135
|
+
]
|
|
136
|
+
}),
|
|
137
|
+
/*#__PURE__*/ _jsx("span", {
|
|
138
|
+
className: "sr-only",
|
|
139
|
+
children: "Default harness"
|
|
140
|
+
})
|
|
141
|
+
]
|
|
142
|
+
}) : null,
|
|
143
|
+
/*#__PURE__*/ _jsx(Text, {
|
|
144
|
+
size: "md",
|
|
145
|
+
bold: true,
|
|
146
|
+
className: "truncate",
|
|
147
|
+
children: harness.label
|
|
148
|
+
}),
|
|
149
|
+
!isAvailable ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
150
|
+
children: [
|
|
151
|
+
/*#__PURE__*/ _jsxs(Tooltip, {
|
|
152
|
+
children: [
|
|
153
|
+
/*#__PURE__*/ _jsx(TooltipTrigger, {
|
|
154
|
+
asChild: true,
|
|
155
|
+
children: /*#__PURE__*/ _jsx("span", {
|
|
156
|
+
className: "inline-flex size-16 shrink-0 items-center justify-center",
|
|
157
|
+
children: /*#__PURE__*/ _jsx(Icon, {
|
|
158
|
+
name: "errorWarningLine",
|
|
159
|
+
className: "size-16 text-foreground-warning-base",
|
|
160
|
+
"aria-hidden": true
|
|
161
|
+
})
|
|
163
162
|
})
|
|
163
|
+
}),
|
|
164
|
+
/*#__PURE__*/ _jsx(TooltipContent, {
|
|
165
|
+
children: unavailableCopy
|
|
164
166
|
})
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
167
|
+
]
|
|
168
|
+
}),
|
|
169
|
+
/*#__PURE__*/ _jsx("span", {
|
|
170
|
+
className: "sr-only",
|
|
171
|
+
children: unavailableCopy
|
|
172
|
+
})
|
|
173
|
+
]
|
|
174
|
+
}) : null
|
|
175
|
+
]
|
|
176
|
+
}),
|
|
177
|
+
!isDefault ? /*#__PURE__*/ _jsxs(DropdownMenu, {
|
|
178
|
+
children: [
|
|
179
|
+
/*#__PURE__*/ _jsx(DropdownMenuTrigger, {
|
|
180
|
+
asChild: true,
|
|
181
|
+
children: /*#__PURE__*/ _jsx(IconButton, {
|
|
182
|
+
size: "sm",
|
|
183
|
+
variant: "transparent",
|
|
184
|
+
icon: "more2Line",
|
|
185
|
+
disabled: isSettingDefault,
|
|
186
|
+
"aria-label": `Open ${harness.label} harness actions`
|
|
187
|
+
})
|
|
188
|
+
}),
|
|
189
|
+
/*#__PURE__*/ _jsx(DropdownMenuContent, {
|
|
190
|
+
align: "end",
|
|
191
|
+
children: /*#__PURE__*/ _jsx(DropdownMenuItem, {
|
|
192
|
+
icon: "starLine",
|
|
193
|
+
disabled: isSettingDefault || !isAvailable,
|
|
194
|
+
onSelect: ()=>{
|
|
195
|
+
onSetDefault(harness);
|
|
196
|
+
},
|
|
197
|
+
children: "Set as default"
|
|
174
198
|
})
|
|
175
|
-
]
|
|
176
|
-
}) : null
|
|
177
|
-
]
|
|
178
|
-
}),
|
|
179
|
-
!isDefault ? /*#__PURE__*/ _jsxs(DropdownMenu, {
|
|
180
|
-
children: [
|
|
181
|
-
/*#__PURE__*/ _jsx(DropdownMenuTrigger, {
|
|
182
|
-
asChild: true,
|
|
183
|
-
children: /*#__PURE__*/ _jsx(IconButton, {
|
|
184
|
-
size: "sm",
|
|
185
|
-
variant: "transparent",
|
|
186
|
-
icon: "more2Line",
|
|
187
|
-
disabled: isSettingDefault,
|
|
188
|
-
"aria-label": `Open ${harness.label} harness actions`
|
|
189
|
-
})
|
|
190
|
-
}),
|
|
191
|
-
/*#__PURE__*/ _jsx(DropdownMenuContent, {
|
|
192
|
-
align: "end",
|
|
193
|
-
children: /*#__PURE__*/ _jsx(DropdownMenuItem, {
|
|
194
|
-
icon: "starLine",
|
|
195
|
-
disabled: isSettingDefault || !isAvailable,
|
|
196
|
-
onSelect: ()=>{
|
|
197
|
-
onSetDefault(harness);
|
|
198
|
-
},
|
|
199
|
-
children: "Set as default"
|
|
200
199
|
})
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
})
|
|
213
|
-
|
|
214
|
-
|
|
200
|
+
]
|
|
201
|
+
}) : null
|
|
202
|
+
]
|
|
203
|
+
}),
|
|
204
|
+
defaultError ? /*#__PURE__*/ _jsx(Callout, {
|
|
205
|
+
role: "alert",
|
|
206
|
+
type: "error",
|
|
207
|
+
children: /*#__PURE__*/ _jsx(Text, {
|
|
208
|
+
size: "sm",
|
|
209
|
+
children: defaultError
|
|
210
|
+
})
|
|
211
|
+
}) : null
|
|
212
|
+
]
|
|
213
|
+
})
|
|
215
214
|
});
|
|
216
215
|
}
|
|
217
216
|
function harnessUnavailableCopy(isDefault) {
|
|
@@ -220,27 +219,34 @@ function harnessUnavailableCopy(isDefault) {
|
|
|
220
219
|
return `${base} The stored default harness cannot currently run in this workspace.`;
|
|
221
220
|
}
|
|
222
221
|
function HarnessRowsSkeleton() {
|
|
223
|
-
return /*#__PURE__*/ _jsx(
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
1
|
|
230
|
-
].map((row)=>/*#__PURE__*/ _jsxs("li", {
|
|
231
|
-
className: "flex items-center gap-cluster px-row py-row",
|
|
222
|
+
return /*#__PURE__*/ _jsx(Panel, {
|
|
223
|
+
children: /*#__PURE__*/ _jsx(PanelBody, {
|
|
224
|
+
asChild: true,
|
|
225
|
+
children: /*#__PURE__*/ _jsx("ul", {
|
|
226
|
+
role: "status",
|
|
227
|
+
"aria-label": "Loading harnesses",
|
|
232
228
|
children: [
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
className: "
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
229
|
+
0,
|
|
230
|
+
1
|
|
231
|
+
].map((row)=>/*#__PURE__*/ _jsx(PanelRow, {
|
|
232
|
+
asChild: true,
|
|
233
|
+
className: "justify-start gap-cluster hover:bg-background-neutral-base",
|
|
234
|
+
children: /*#__PURE__*/ _jsxs("li", {
|
|
235
|
+
children: [
|
|
236
|
+
/*#__PURE__*/ _jsx(Skeleton, {
|
|
237
|
+
className: "size-16 shrink-0"
|
|
238
|
+
}),
|
|
239
|
+
/*#__PURE__*/ _jsx(Skeleton, {
|
|
240
|
+
className: "h-16 w-120"
|
|
241
|
+
}),
|
|
242
|
+
/*#__PURE__*/ _jsx(Skeleton, {
|
|
243
|
+
className: "ml-auto size-28 shrink-0"
|
|
244
|
+
})
|
|
245
|
+
]
|
|
246
|
+
})
|
|
247
|
+
}, row))
|
|
248
|
+
})
|
|
249
|
+
})
|
|
244
250
|
});
|
|
245
251
|
}
|
|
246
252
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/harnesses-section.tsx"],"sourcesContent":["import {QueryLoadError} from '@shipfox/client-ui';\nimport {IconButton} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@shipfox/react-ui/dropdown-menu';\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {Skeleton} from '@shipfox/react-ui/skeleton';\nimport {toast} from '@shipfox/react-ui/toast';\nimport {Tooltip, TooltipContent, TooltipTrigger} from '@shipfox/react-ui/tooltip';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport {cn} from '@shipfox/react-ui/utils';\nimport {useRef, useState} from 'react';\nimport {DEFAULT_HARNESS, listHarnesses} from '#core/harness-policy.js';\nimport type {HarnessDescriptor, HarnessId} from '#core/models.js';\nimport {\n useModelProviderConfigsQuery,\n useSetDefaultHarnessMutation,\n} from '#hooks/api/model-providers.js';\nimport {modelProviderConfigErrorToFormError} from './form-errors.js';\nimport {isHarnessAvailable} from './harness-availability.js';\n\nconst SURFACE_CLASS =\n 'overflow-hidden rounded-8 border border-border-neutral-base bg-background-neutral-base';\n\nexport function WorkspaceHarnessesSection({workspaceId}: {workspaceId: string}) {\n const configsQuery = useModelProviderConfigsQuery(workspaceId);\n const setDefaultHarness = useSetDefaultHarnessMutation();\n const activeWorkspaceIdRef = useRef(workspaceId);\n const defaultRequestSeqRef = useRef(0);\n const activeDefaultRequestRef = useRef<{workspaceId: string; id: number} | null>(null);\n const [pendingDefaultHarness, setPendingDefaultHarness] = useState<{\n workspaceId: string;\n harnessId: HarnessId;\n } | null>(null);\n const [defaultError, setDefaultError] = useState<\n {workspaceId: string; harnessId: HarnessId; message: string} | undefined\n >();\n const configs = configsQuery.data?.configs ?? [];\n const defaultHarnessId = configsQuery.data?.defaultHarnessId ?? DEFAULT_HARNESS;\n activeWorkspaceIdRef.current = workspaceId;\n\n function isActiveDefaultRequest(request: {workspaceId: string; id: number}) {\n const activeRequest = activeDefaultRequestRef.current;\n return (\n activeWorkspaceIdRef.current === request.workspaceId &&\n activeRequest?.workspaceId === request.workspaceId &&\n activeRequest.id === request.id\n );\n }\n\n async function handleSetDefault(harness: HarnessDescriptor) {\n if (activeDefaultRequestRef.current?.workspaceId === workspaceId) return;\n\n const request = {workspaceId, id: defaultRequestSeqRef.current + 1};\n defaultRequestSeqRef.current = request.id;\n activeDefaultRequestRef.current = request;\n setPendingDefaultHarness({workspaceId, harnessId: harness.id});\n setDefaultError(undefined);\n try {\n await setDefaultHarness.mutateAsync({\n workspaceId,\n harnessId: harness.id,\n });\n if (!isActiveDefaultRequest(request)) return;\n toast.success(`${harness.label} is now the default harness`);\n } catch (error) {\n if (!isActiveDefaultRequest(request)) return;\n const mapped = modelProviderConfigErrorToFormError(error);\n setDefaultError({\n workspaceId,\n harnessId: harness.id,\n message: mapped.message || 'Could not save default harness. Try again.',\n });\n } finally {\n if (isActiveDefaultRequest(request)) {\n activeDefaultRequestRef.current = null;\n setPendingDefaultHarness(null);\n }\n }\n }\n\n return (\n <section className=\"flex flex-col gap-group\" aria-label=\"Harnesses\">\n <div className=\"flex flex-col gap-tight\">\n <Header variant=\"h3\">Harnesses</Header>\n <Text size=\"sm\" className=\"text-foreground-neutral-muted\">\n Harnesses available to run agent steps in this workspace.\n </Text>\n </div>\n\n {configsQuery.isPending ? <HarnessRowsSkeleton /> : null}\n\n {configsQuery.isError && configsQuery.data === undefined ? (\n <div className={cn(SURFACE_CLASS, 'px-row')}>\n <QueryLoadError query={configsQuery} subject=\"harnesses\" />\n </div>\n ) : null}\n\n {configsQuery.data !== undefined ? (\n <ul className={cn('divide-y divide-border-neutral-base', SURFACE_CLASS)}>\n {listHarnesses().map((harness) => (\n <HarnessRow\n key={harness.id}\n harness={harness}\n isDefault={harness.id === defaultHarnessId}\n isAvailable={isHarnessAvailable(harness, configs)}\n isSettingDefault={pendingDefaultHarness?.workspaceId === workspaceId}\n defaultError={\n defaultError?.workspaceId === workspaceId && defaultError.harnessId === harness.id\n ? defaultError.message\n : undefined\n }\n onSetDefault={handleSetDefault}\n />\n ))}\n </ul>\n ) : null}\n </section>\n );\n}\n\nfunction HarnessRow({\n harness,\n isDefault,\n isAvailable,\n isSettingDefault,\n defaultError,\n onSetDefault,\n}: {\n harness: HarnessDescriptor;\n isDefault: boolean;\n isAvailable: boolean;\n isSettingDefault: boolean;\n defaultError: string | undefined;\n onSetDefault: (harness: HarnessDescriptor) => void;\n}) {\n const unavailableCopy = harnessUnavailableCopy(isDefault);\n\n return (\n <li className=\"flex flex-col gap-inline px-row py-row transition-colors hover:bg-background-components-hover\">\n <div className=\"flex items-center justify-between gap-cluster\">\n <div className=\"flex min-w-0 items-center gap-inline\">\n {isDefault ? (\n <>\n <Tooltip>\n <TooltipTrigger asChild>\n <span className=\"inline-flex size-16 shrink-0 items-center justify-center\">\n <Icon\n name=\"starLine\"\n className=\"size-16 text-foreground-neutral-muted\"\n aria-hidden\n />\n </span>\n </TooltipTrigger>\n <TooltipContent>Default harness</TooltipContent>\n </Tooltip>\n <span className=\"sr-only\">Default harness</span>\n </>\n ) : null}\n <Text size=\"md\" bold className=\"truncate\">\n {harness.label}\n </Text>\n {!isAvailable ? (\n <>\n <Tooltip>\n <TooltipTrigger asChild>\n <span className=\"inline-flex size-16 shrink-0 items-center justify-center\">\n <Icon\n name=\"errorWarningLine\"\n className=\"size-16 text-foreground-warning-base\"\n aria-hidden\n />\n </span>\n </TooltipTrigger>\n <TooltipContent>{unavailableCopy}</TooltipContent>\n </Tooltip>\n <span className=\"sr-only\">{unavailableCopy}</span>\n </>\n ) : null}\n </div>\n {!isDefault ? (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <IconButton\n size=\"sm\"\n variant=\"transparent\"\n icon=\"more2Line\"\n disabled={isSettingDefault}\n aria-label={`Open ${harness.label} harness actions`}\n />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem\n icon=\"starLine\"\n disabled={isSettingDefault || !isAvailable}\n onSelect={() => {\n onSetDefault(harness);\n }}\n >\n Set as default\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n ) : null}\n </div>\n {defaultError ? (\n <Callout role=\"alert\" type=\"error\">\n <Text size=\"sm\">{defaultError}</Text>\n </Callout>\n ) : null}\n </li>\n );\n}\n\nfunction harnessUnavailableCopy(isDefault: boolean): string {\n const base = 'Configure a compatible model provider to use this harness.';\n if (!isDefault) return base;\n return `${base} The stored default harness cannot currently run in this workspace.`;\n}\n\nfunction HarnessRowsSkeleton() {\n return (\n <ul\n role=\"status\"\n aria-label=\"Loading harnesses\"\n className={cn('divide-y divide-border-neutral-base', SURFACE_CLASS)}\n >\n {[0, 1].map((row) => (\n <li key={row} className=\"flex items-center gap-cluster px-row py-row\">\n <Skeleton className=\"size-16 shrink-0\" />\n <Skeleton className=\"h-16 w-120\" />\n <Skeleton className=\"ml-auto size-28 shrink-0\" />\n </li>\n ))}\n </ul>\n );\n}\n"],"names":["QueryLoadError","IconButton","Callout","DropdownMenu","DropdownMenuContent","DropdownMenuItem","DropdownMenuTrigger","Icon","Skeleton","toast","Tooltip","TooltipContent","TooltipTrigger","Header","Text","cn","useRef","useState","DEFAULT_HARNESS","listHarnesses","useModelProviderConfigsQuery","useSetDefaultHarnessMutation","modelProviderConfigErrorToFormError","isHarnessAvailable","SURFACE_CLASS","WorkspaceHarnessesSection","workspaceId","configsQuery","setDefaultHarness","activeWorkspaceIdRef","defaultRequestSeqRef","activeDefaultRequestRef","pendingDefaultHarness","setPendingDefaultHarness","defaultError","setDefaultError","configs","data","defaultHarnessId","current","isActiveDefaultRequest","request","activeRequest","id","handleSetDefault","harness","harnessId","undefined","mutateAsync","success","label","error","mapped","message","section","className","aria-label","div","variant","size","isPending","HarnessRowsSkeleton","isError","query","subject","ul","map","HarnessRow","isDefault","isAvailable","isSettingDefault","onSetDefault","unavailableCopy","harnessUnavailableCopy","li","asChild","span","name","aria-hidden","bold","icon","disabled","align","onSelect","role","type","base","row"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/components/harnesses-section.tsx"],"sourcesContent":["import {QueryLoadError} from '@shipfox/client-ui';\nimport {IconButton} from '@shipfox/react-ui/button';\nimport {Callout} from '@shipfox/react-ui/callout';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@shipfox/react-ui/dropdown-menu';\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {Panel, PanelBody, PanelRow} from '@shipfox/react-ui/panel';\nimport {Skeleton} from '@shipfox/react-ui/skeleton';\nimport {toast} from '@shipfox/react-ui/toast';\nimport {Tooltip, TooltipContent, TooltipTrigger} from '@shipfox/react-ui/tooltip';\nimport {Header, Text} from '@shipfox/react-ui/typography';\nimport {useRef, useState} from 'react';\nimport {DEFAULT_HARNESS, listHarnesses} from '#core/harness-policy.js';\nimport type {HarnessDescriptor, HarnessId} from '#core/models.js';\nimport {\n useModelProviderConfigsQuery,\n useSetDefaultHarnessMutation,\n} from '#hooks/api/model-providers.js';\nimport {modelProviderConfigErrorToFormError} from './form-errors.js';\nimport {isHarnessAvailable} from './harness-availability.js';\n\nexport function WorkspaceHarnessesSection({workspaceId}: {workspaceId: string}) {\n const configsQuery = useModelProviderConfigsQuery(workspaceId);\n const setDefaultHarness = useSetDefaultHarnessMutation();\n const activeWorkspaceIdRef = useRef(workspaceId);\n const defaultRequestSeqRef = useRef(0);\n const activeDefaultRequestRef = useRef<{workspaceId: string; id: number} | null>(null);\n const [pendingDefaultHarness, setPendingDefaultHarness] = useState<{\n workspaceId: string;\n harnessId: HarnessId;\n } | null>(null);\n const [defaultError, setDefaultError] = useState<\n {workspaceId: string; harnessId: HarnessId; message: string} | undefined\n >();\n const configs = configsQuery.data?.configs ?? [];\n const defaultHarnessId = configsQuery.data?.defaultHarnessId ?? DEFAULT_HARNESS;\n activeWorkspaceIdRef.current = workspaceId;\n\n function isActiveDefaultRequest(request: {workspaceId: string; id: number}) {\n const activeRequest = activeDefaultRequestRef.current;\n return (\n activeWorkspaceIdRef.current === request.workspaceId &&\n activeRequest?.workspaceId === request.workspaceId &&\n activeRequest.id === request.id\n );\n }\n\n async function handleSetDefault(harness: HarnessDescriptor) {\n if (activeDefaultRequestRef.current?.workspaceId === workspaceId) return;\n\n const request = {workspaceId, id: defaultRequestSeqRef.current + 1};\n defaultRequestSeqRef.current = request.id;\n activeDefaultRequestRef.current = request;\n setPendingDefaultHarness({workspaceId, harnessId: harness.id});\n setDefaultError(undefined);\n try {\n await setDefaultHarness.mutateAsync({\n workspaceId,\n harnessId: harness.id,\n });\n if (!isActiveDefaultRequest(request)) return;\n toast.success(`${harness.label} is now the default harness`);\n } catch (error) {\n if (!isActiveDefaultRequest(request)) return;\n const mapped = modelProviderConfigErrorToFormError(error);\n setDefaultError({\n workspaceId,\n harnessId: harness.id,\n message: mapped.message || 'Could not save default harness. Try again.',\n });\n } finally {\n if (isActiveDefaultRequest(request)) {\n activeDefaultRequestRef.current = null;\n setPendingDefaultHarness(null);\n }\n }\n }\n\n return (\n <section className=\"flex flex-col gap-group\" aria-label=\"Harnesses\">\n <div className=\"flex flex-col gap-tight\">\n <Header variant=\"h3\">Harnesses</Header>\n </div>\n\n {configsQuery.isPending ? <HarnessRowsSkeleton /> : null}\n\n {configsQuery.isError && configsQuery.data === undefined ? (\n <Panel>\n <QueryLoadError query={configsQuery} subject=\"harnesses\" variant=\"panel\" />\n </Panel>\n ) : null}\n\n {configsQuery.data !== undefined ? (\n <Panel>\n <PanelBody asChild>\n <ul>\n {listHarnesses().map((harness) => (\n <HarnessRow\n key={harness.id}\n harness={harness}\n isDefault={harness.id === defaultHarnessId}\n isAvailable={isHarnessAvailable(harness, configs)}\n isSettingDefault={pendingDefaultHarness?.workspaceId === workspaceId}\n defaultError={\n defaultError?.workspaceId === workspaceId &&\n defaultError.harnessId === harness.id\n ? defaultError.message\n : undefined\n }\n onSetDefault={handleSetDefault}\n />\n ))}\n </ul>\n </PanelBody>\n </Panel>\n ) : null}\n </section>\n );\n}\n\nfunction HarnessRow({\n harness,\n isDefault,\n isAvailable,\n isSettingDefault,\n defaultError,\n onSetDefault,\n}: {\n harness: HarnessDescriptor;\n isDefault: boolean;\n isAvailable: boolean;\n isSettingDefault: boolean;\n defaultError: string | undefined;\n onSetDefault: (harness: HarnessDescriptor) => void;\n}) {\n const unavailableCopy = harnessUnavailableCopy(isDefault);\n\n return (\n <PanelRow asChild className=\"flex-col items-stretch gap-inline\">\n <li>\n <div className=\"flex items-center justify-between gap-cluster\">\n <div className=\"flex min-w-0 items-center gap-inline\">\n {isDefault ? (\n <>\n <Tooltip>\n <TooltipTrigger asChild>\n <span className=\"inline-flex size-16 shrink-0 items-center justify-center\">\n <Icon\n name=\"starLine\"\n className=\"size-16 text-foreground-neutral-muted\"\n aria-hidden\n />\n </span>\n </TooltipTrigger>\n <TooltipContent>Default harness</TooltipContent>\n </Tooltip>\n <span className=\"sr-only\">Default harness</span>\n </>\n ) : null}\n <Text size=\"md\" bold className=\"truncate\">\n {harness.label}\n </Text>\n {!isAvailable ? (\n <>\n <Tooltip>\n <TooltipTrigger asChild>\n <span className=\"inline-flex size-16 shrink-0 items-center justify-center\">\n <Icon\n name=\"errorWarningLine\"\n className=\"size-16 text-foreground-warning-base\"\n aria-hidden\n />\n </span>\n </TooltipTrigger>\n <TooltipContent>{unavailableCopy}</TooltipContent>\n </Tooltip>\n <span className=\"sr-only\">{unavailableCopy}</span>\n </>\n ) : null}\n </div>\n {!isDefault ? (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <IconButton\n size=\"sm\"\n variant=\"transparent\"\n icon=\"more2Line\"\n disabled={isSettingDefault}\n aria-label={`Open ${harness.label} harness actions`}\n />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem\n icon=\"starLine\"\n disabled={isSettingDefault || !isAvailable}\n onSelect={() => {\n onSetDefault(harness);\n }}\n >\n Set as default\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n ) : null}\n </div>\n {defaultError ? (\n <Callout role=\"alert\" type=\"error\">\n <Text size=\"sm\">{defaultError}</Text>\n </Callout>\n ) : null}\n </li>\n </PanelRow>\n );\n}\n\nfunction harnessUnavailableCopy(isDefault: boolean): string {\n const base = 'Configure a compatible model provider to use this harness.';\n if (!isDefault) return base;\n return `${base} The stored default harness cannot currently run in this workspace.`;\n}\n\nfunction HarnessRowsSkeleton() {\n return (\n <Panel>\n <PanelBody asChild>\n <ul role=\"status\" aria-label=\"Loading harnesses\">\n {[0, 1].map((row) => (\n <PanelRow\n asChild\n className=\"justify-start gap-cluster hover:bg-background-neutral-base\"\n key={row}\n >\n <li>\n <Skeleton className=\"size-16 shrink-0\" />\n <Skeleton className=\"h-16 w-120\" />\n <Skeleton className=\"ml-auto size-28 shrink-0\" />\n </li>\n </PanelRow>\n ))}\n </ul>\n </PanelBody>\n </Panel>\n );\n}\n"],"names":["QueryLoadError","IconButton","Callout","DropdownMenu","DropdownMenuContent","DropdownMenuItem","DropdownMenuTrigger","Icon","Panel","PanelBody","PanelRow","Skeleton","toast","Tooltip","TooltipContent","TooltipTrigger","Header","Text","useRef","useState","DEFAULT_HARNESS","listHarnesses","useModelProviderConfigsQuery","useSetDefaultHarnessMutation","modelProviderConfigErrorToFormError","isHarnessAvailable","WorkspaceHarnessesSection","workspaceId","configsQuery","setDefaultHarness","activeWorkspaceIdRef","defaultRequestSeqRef","activeDefaultRequestRef","pendingDefaultHarness","setPendingDefaultHarness","defaultError","setDefaultError","configs","data","defaultHarnessId","current","isActiveDefaultRequest","request","activeRequest","id","handleSetDefault","harness","harnessId","undefined","mutateAsync","success","label","error","mapped","message","section","className","aria-label","div","variant","isPending","HarnessRowsSkeleton","isError","query","subject","asChild","ul","map","HarnessRow","isDefault","isAvailable","isSettingDefault","onSetDefault","unavailableCopy","harnessUnavailableCopy","li","span","name","aria-hidden","size","bold","icon","disabled","align","onSelect","role","type","base","row"],"mappings":";AAAA,SAAQA,cAAc,QAAO,qBAAqB;AAClD,SAAQC,UAAU,QAAO,2BAA2B;AACpD,SAAQC,OAAO,QAAO,4BAA4B;AAClD,SACEC,YAAY,EACZC,mBAAmB,EACnBC,gBAAgB,EAChBC,mBAAmB,QACd,kCAAkC;AACzC,SAAQC,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,KAAK,EAAEC,SAAS,EAAEC,QAAQ,QAAO,0BAA0B;AACnE,SAAQC,QAAQ,QAAO,6BAA6B;AACpD,SAAQC,KAAK,QAAO,0BAA0B;AAC9C,SAAQC,OAAO,EAAEC,cAAc,EAAEC,cAAc,QAAO,4BAA4B;AAClF,SAAQC,MAAM,EAAEC,IAAI,QAAO,+BAA+B;AAC1D,SAAQC,MAAM,EAAEC,QAAQ,QAAO,QAAQ;AACvC,SAAQC,eAAe,EAAEC,aAAa,QAAO,0BAA0B;AAEvE,SACEC,4BAA4B,EAC5BC,4BAA4B,QACvB,gCAAgC;AACvC,SAAQC,mCAAmC,QAAO,mBAAmB;AACrE,SAAQC,kBAAkB,QAAO,4BAA4B;AAE7D,OAAO,SAASC,0BAA0B,EAACC,WAAW,EAAwB;IAC5E,MAAMC,eAAeN,6BAA6BK;IAClD,MAAME,oBAAoBN;IAC1B,MAAMO,uBAAuBZ,OAAOS;IACpC,MAAMI,uBAAuBb,OAAO;IACpC,MAAMc,0BAA0Bd,OAAiD;IACjF,MAAM,CAACe,uBAAuBC,yBAAyB,GAAGf,SAGhD;IACV,MAAM,CAACgB,cAAcC,gBAAgB,GAAGjB;IAGxC,MAAMkB,UAAUT,aAAaU,IAAI,EAAED,WAAW,EAAE;IAChD,MAAME,mBAAmBX,aAAaU,IAAI,EAAEC,oBAAoBnB;IAChEU,qBAAqBU,OAAO,GAAGb;IAE/B,SAASc,uBAAuBC,OAA0C;QACxE,MAAMC,gBAAgBX,wBAAwBQ,OAAO;QACrD,OACEV,qBAAqBU,OAAO,KAAKE,QAAQf,WAAW,IACpDgB,eAAehB,gBAAgBe,QAAQf,WAAW,IAClDgB,cAAcC,EAAE,KAAKF,QAAQE,EAAE;IAEnC;IAEA,eAAeC,iBAAiBC,OAA0B;QACxD,IAAId,wBAAwBQ,OAAO,EAAEb,gBAAgBA,aAAa;QAElE,MAAMe,UAAU;YAACf;YAAaiB,IAAIb,qBAAqBS,OAAO,GAAG;QAAC;QAClET,qBAAqBS,OAAO,GAAGE,QAAQE,EAAE;QACzCZ,wBAAwBQ,OAAO,GAAGE;QAClCR,yBAAyB;YAACP;YAAaoB,WAAWD,QAAQF,EAAE;QAAA;QAC5DR,gBAAgBY;QAChB,IAAI;YACF,MAAMnB,kBAAkBoB,WAAW,CAAC;gBAClCtB;gBACAoB,WAAWD,QAAQF,EAAE;YACvB;YACA,IAAI,CAACH,uBAAuBC,UAAU;YACtC9B,MAAMsC,OAAO,CAAC,GAAGJ,QAAQK,KAAK,CAAC,2BAA2B,CAAC;QAC7D,EAAE,OAAOC,OAAO;YACd,IAAI,CAACX,uBAAuBC,UAAU;YACtC,MAAMW,SAAS7B,oCAAoC4B;YACnDhB,gBAAgB;gBACdT;gBACAoB,WAAWD,QAAQF,EAAE;gBACrBU,SAASD,OAAOC,OAAO,IAAI;YAC7B;QACF,SAAU;YACR,IAAIb,uBAAuBC,UAAU;gBACnCV,wBAAwBQ,OAAO,GAAG;gBAClCN,yBAAyB;YAC3B;QACF;IACF;IAEA,qBACE,MAACqB;QAAQC,WAAU;QAA0BC,cAAW;;0BACtD,KAACC;gBAAIF,WAAU;0BACb,cAAA,KAACxC;oBAAO2C,SAAQ;8BAAK;;;YAGtB/B,aAAagC,SAAS,iBAAG,KAACC,2BAAyB;YAEnDjC,aAAakC,OAAO,IAAIlC,aAAaU,IAAI,KAAKU,0BAC7C,KAACxC;0BACC,cAAA,KAACR;oBAAe+D,OAAOnC;oBAAcoC,SAAQ;oBAAYL,SAAQ;;iBAEjE;YAEH/B,aAAaU,IAAI,KAAKU,0BACrB,KAACxC;0BACC,cAAA,KAACC;oBAAUwD,OAAO;8BAChB,cAAA,KAACC;kCACE7C,gBAAgB8C,GAAG,CAAC,CAACrB,wBACpB,KAACsB;gCAECtB,SAASA;gCACTuB,WAAWvB,QAAQF,EAAE,KAAKL;gCAC1B+B,aAAa7C,mBAAmBqB,SAAST;gCACzCkC,kBAAkBtC,uBAAuBN,gBAAgBA;gCACzDQ,cACEA,cAAcR,gBAAgBA,eAC9BQ,aAAaY,SAAS,KAAKD,QAAQF,EAAE,GACjCT,aAAamB,OAAO,GACpBN;gCAENwB,cAAc3B;+BAXTC,QAAQF,EAAE;;;iBAiBvB;;;AAGV;AAEA,SAASwB,WAAW,EAClBtB,OAAO,EACPuB,SAAS,EACTC,WAAW,EACXC,gBAAgB,EAChBpC,YAAY,EACZqC,YAAY,EAQb;IACC,MAAMC,kBAAkBC,uBAAuBL;IAE/C,qBACE,KAAC3D;QAASuD,OAAO;QAACT,WAAU;kBAC1B,cAAA,MAACmB;;8BACC,MAACjB;oBAAIF,WAAU;;sCACb,MAACE;4BAAIF,WAAU;;gCACZa,0BACC;;sDACE,MAACxD;;8DACC,KAACE;oDAAekD,OAAO;8DACrB,cAAA,KAACW;wDAAKpB,WAAU;kEACd,cAAA,KAACjD;4DACCsE,MAAK;4DACLrB,WAAU;4DACVsB,aAAW;;;;8DAIjB,KAAChE;8DAAe;;;;sDAElB,KAAC8D;4CAAKpB,WAAU;sDAAU;;;qCAE1B;8CACJ,KAACvC;oCAAK8D,MAAK;oCAAKC,IAAI;oCAACxB,WAAU;8CAC5BV,QAAQK,KAAK;;gCAEf,CAACmB,4BACA;;sDACE,MAACzD;;8DACC,KAACE;oDAAekD,OAAO;8DACrB,cAAA,KAACW;wDAAKpB,WAAU;kEACd,cAAA,KAACjD;4DACCsE,MAAK;4DACLrB,WAAU;4DACVsB,aAAW;;;;8DAIjB,KAAChE;8DAAgB2D;;;;sDAEnB,KAACG;4CAAKpB,WAAU;sDAAWiB;;;qCAE3B;;;wBAEL,CAACJ,0BACA,MAAClE;;8CACC,KAACG;oCAAoB2D,OAAO;8CAC1B,cAAA,KAAChE;wCACC8E,MAAK;wCACLpB,SAAQ;wCACRsB,MAAK;wCACLC,UAAUX;wCACVd,cAAY,CAAC,KAAK,EAAEX,QAAQK,KAAK,CAAC,gBAAgB,CAAC;;;8CAGvD,KAAC/C;oCAAoB+E,OAAM;8CACzB,cAAA,KAAC9E;wCACC4E,MAAK;wCACLC,UAAUX,oBAAoB,CAACD;wCAC/Bc,UAAU;4CACRZ,aAAa1B;wCACf;kDACD;;;;6BAKH;;;gBAELX,6BACC,KAACjC;oBAAQmF,MAAK;oBAAQC,MAAK;8BACzB,cAAA,KAACrE;wBAAK8D,MAAK;kCAAM5C;;qBAEjB;;;;AAIZ;AAEA,SAASuC,uBAAuBL,SAAkB;IAChD,MAAMkB,OAAO;IACb,IAAI,CAAClB,WAAW,OAAOkB;IACvB,OAAO,GAAGA,KAAK,mEAAmE,CAAC;AACrF;AAEA,SAAS1B;IACP,qBACE,KAACrD;kBACC,cAAA,KAACC;YAAUwD,OAAO;sBAChB,cAAA,KAACC;gBAAGmB,MAAK;gBAAS5B,cAAW;0BAC1B;oBAAC;oBAAG;iBAAE,CAACU,GAAG,CAAC,CAACqB,oBACX,KAAC9E;wBACCuD,OAAO;wBACPT,WAAU;kCAGV,cAAA,MAACmB;;8CACC,KAAChE;oCAAS6C,WAAU;;8CACpB,KAAC7C;oCAAS6C,WAAU;;8CACpB,KAAC7C;oCAAS6C,WAAU;;;;uBALjBgC;;;;AAanB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-provider-grid-skeleton.d.ts","sourceRoot":"","sources":["../../src/components/model-provider-grid-skeleton.tsx"],"names":[],"mappings":"AAGA,wBAAgB,yBAAyB,CAAC,EAAC,KAAK,EAAC,EAAE;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,+BAiBjE"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Panel, PanelBody, PanelCell, PanelGrid } from '@shipfox/react-ui/panel';
|
|
3
|
+
import { Skeleton } from '@shipfox/react-ui/skeleton';
|
|
4
|
+
export function ModelProviderGridSkeleton({ label }) {
|
|
5
|
+
return /*#__PURE__*/ _jsx(Panel, {
|
|
6
|
+
children: /*#__PURE__*/ _jsx(PanelBody, {
|
|
7
|
+
children: /*#__PURE__*/ _jsx(PanelGrid, {
|
|
8
|
+
role: "status",
|
|
9
|
+
"aria-busy": "true",
|
|
10
|
+
"aria-label": label,
|
|
11
|
+
children: [
|
|
12
|
+
0,
|
|
13
|
+
1,
|
|
14
|
+
2,
|
|
15
|
+
3
|
|
16
|
+
].map((tile)=>/*#__PURE__*/ _jsx(PanelCell, {
|
|
17
|
+
children: /*#__PURE__*/ _jsxs("div", {
|
|
18
|
+
className: "flex items-center justify-between gap-cluster px-row py-row",
|
|
19
|
+
children: [
|
|
20
|
+
/*#__PURE__*/ _jsx(Skeleton, {
|
|
21
|
+
className: "h-16 w-100"
|
|
22
|
+
}),
|
|
23
|
+
/*#__PURE__*/ _jsx(Skeleton, {
|
|
24
|
+
className: "h-16 w-64 shrink-0"
|
|
25
|
+
})
|
|
26
|
+
]
|
|
27
|
+
})
|
|
28
|
+
}, tile))
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
//# sourceMappingURL=model-provider-grid-skeleton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/model-provider-grid-skeleton.tsx"],"sourcesContent":["import {Panel, PanelBody, PanelCell, PanelGrid} from '@shipfox/react-ui/panel';\nimport {Skeleton} from '@shipfox/react-ui/skeleton';\n\nexport function ModelProviderGridSkeleton({label}: {label: string}) {\n return (\n <Panel>\n <PanelBody>\n <PanelGrid role=\"status\" aria-busy=\"true\" aria-label={label}>\n {[0, 1, 2, 3].map((tile) => (\n <PanelCell key={tile}>\n <div className=\"flex items-center justify-between gap-cluster px-row py-row\">\n <Skeleton className=\"h-16 w-100\" />\n <Skeleton className=\"h-16 w-64 shrink-0\" />\n </div>\n </PanelCell>\n ))}\n </PanelGrid>\n </PanelBody>\n </Panel>\n );\n}\n"],"names":["Panel","PanelBody","PanelCell","PanelGrid","Skeleton","ModelProviderGridSkeleton","label","role","aria-busy","aria-label","map","tile","div","className"],"mappings":";AAAA,SAAQA,KAAK,EAAEC,SAAS,EAAEC,SAAS,EAAEC,SAAS,QAAO,0BAA0B;AAC/E,SAAQC,QAAQ,QAAO,6BAA6B;AAEpD,OAAO,SAASC,0BAA0B,EAACC,KAAK,EAAkB;IAChE,qBACE,KAACN;kBACC,cAAA,KAACC;sBACC,cAAA,KAACE;gBAAUI,MAAK;gBAASC,aAAU;gBAAOC,cAAYH;0BACnD;oBAAC;oBAAG;oBAAG;oBAAG;iBAAE,CAACI,GAAG,CAAC,CAACC,qBACjB,KAACT;kCACC,cAAA,MAACU;4BAAIC,WAAU;;8CACb,KAACT;oCAASS,WAAU;;8CACpB,KAACT;oCAASS,WAAU;;;;uBAHRF;;;;AAW5B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-providers-section.d.ts","sourceRoot":"","sources":["../../src/components/model-providers-section.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"model-providers-section.d.ts","sourceRoot":"","sources":["../../src/components/model-providers-section.tsx"],"names":[],"mappings":"AAqEA,wBAAgB,8BAA8B,CAAC,EAAC,WAAW,EAAC,EAAE;IAAC,WAAW,EAAE,MAAM,CAAA;CAAC,+BAuUlF"}
|