@shipfox/client-agent 0.2.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/.storybook/main.ts +1 -0
- package/.storybook/preview.css +4 -0
- package/.storybook/preview.tsx +56 -0
- package/.turbo/turbo-build.log +2 -0
- package/.turbo/turbo-type$colon$emit.log +1 -0
- package/.turbo/turbo-type.log +1 -0
- package/CHANGELOG.md +93 -0
- package/LICENSE +21 -0
- package/dist/components/add-custom-provider-card.d.ts +4 -0
- package/dist/components/add-custom-provider-card.d.ts.map +1 -0
- package/dist/components/add-custom-provider-card.js +41 -0
- package/dist/components/add-custom-provider-card.js.map +1 -0
- package/dist/components/agent-workflow-example.d.ts +11 -0
- package/dist/components/agent-workflow-example.d.ts.map +1 -0
- package/dist/components/agent-workflow-example.js +38 -0
- package/dist/components/agent-workflow-example.js.map +1 -0
- package/dist/components/available-provider-card.d.ts +6 -0
- package/dist/components/available-provider-card.d.ts.map +1 -0
- package/dist/components/available-provider-card.js +41 -0
- package/dist/components/available-provider-card.js.map +1 -0
- package/dist/components/available-providers-grid.d.ts +10 -0
- package/dist/components/available-providers-grid.d.ts.map +1 -0
- package/dist/components/available-providers-grid.js +89 -0
- package/dist/components/available-providers-grid.js.map +1 -0
- package/dist/components/change-default-model-form.d.ts +9 -0
- package/dist/components/change-default-model-form.d.ts.map +1 -0
- package/dist/components/change-default-model-form.js +98 -0
- package/dist/components/change-default-model-form.js.map +1 -0
- package/dist/components/custom-model-provider-api-options.d.ts +7 -0
- package/dist/components/custom-model-provider-api-options.d.ts.map +1 -0
- package/dist/components/custom-model-provider-api-options.js +23 -0
- package/dist/components/custom-model-provider-api-options.js.map +1 -0
- package/dist/components/custom-model-provider-form.d.ts +8 -0
- package/dist/components/custom-model-provider-form.d.ts.map +1 -0
- package/dist/components/custom-model-provider-form.js +667 -0
- package/dist/components/custom-model-provider-form.js.map +1 -0
- package/dist/components/custom-model-provider-form.stories.d.ts +20 -0
- package/dist/components/custom-model-provider-form.stories.d.ts.map +1 -0
- package/dist/components/custom-model-provider-form.stories.js +104 -0
- package/dist/components/custom-model-provider-form.stories.js.map +1 -0
- package/dist/components/custom-model-provider-payload.d.ts +39 -0
- package/dist/components/custom-model-provider-payload.d.ts.map +1 -0
- package/dist/components/custom-model-provider-payload.js +203 -0
- package/dist/components/custom-model-provider-payload.js.map +1 -0
- package/dist/components/custom-model-provider-slug.d.ts +3 -0
- package/dist/components/custom-model-provider-slug.d.ts.map +1 -0
- package/dist/components/custom-model-provider-slug.js +14 -0
- package/dist/components/custom-model-provider-slug.js.map +1 -0
- package/dist/components/default-model-field.d.ts +16 -0
- package/dist/components/default-model-field.d.ts.map +1 -0
- package/dist/components/default-model-field.js +60 -0
- package/dist/components/default-model-field.js.map +1 -0
- package/dist/components/form-errors.d.ts +11 -0
- package/dist/components/form-errors.d.ts.map +1 -0
- package/dist/components/form-errors.js +101 -0
- package/dist/components/form-errors.js.map +1 -0
- package/dist/components/harness-availability.d.ts +8 -0
- package/dist/components/harness-availability.d.ts.map +1 -0
- package/dist/components/harness-availability.js +16 -0
- package/dist/components/harness-availability.js.map +1 -0
- package/dist/components/harnesses-section.d.ts +4 -0
- package/dist/components/harnesses-section.d.ts.map +1 -0
- package/dist/components/harnesses-section.js +249 -0
- package/dist/components/harnesses-section.js.map +1 -0
- package/dist/components/harnesses-section.stories.d.ts +25 -0
- package/dist/components/harnesses-section.stories.d.ts.map +1 -0
- package/dist/components/harnesses-section.stories.js +138 -0
- package/dist/components/harnesses-section.stories.js.map +1 -0
- package/dist/components/model-provider-usage-modal.d.ts +11 -0
- package/dist/components/model-provider-usage-modal.d.ts.map +1 -0
- package/dist/components/model-provider-usage-modal.js +349 -0
- package/dist/components/model-provider-usage-modal.js.map +1 -0
- package/dist/components/model-provider-usage-modal.stories.d.ts +21 -0
- package/dist/components/model-provider-usage-modal.stories.d.ts.map +1 -0
- package/dist/components/model-provider-usage-modal.stories.js +115 -0
- package/dist/components/model-provider-usage-modal.stories.js.map +1 -0
- package/dist/components/model-provider-usage-target.d.ts +14 -0
- package/dist/components/model-provider-usage-target.d.ts.map +1 -0
- package/dist/components/model-provider-usage-target.js +20 -0
- package/dist/components/model-provider-usage-target.js.map +1 -0
- package/dist/components/model-providers-section.d.ts +4 -0
- package/dist/components/model-providers-section.d.ts.map +1 -0
- package/dist/components/model-providers-section.js +668 -0
- package/dist/components/model-providers-section.js.map +1 -0
- package/dist/components/model-providers-section.stories.d.ts +32 -0
- package/dist/components/model-providers-section.stories.d.ts.map +1 -0
- package/dist/components/model-providers-section.stories.js +442 -0
- package/dist/components/model-providers-section.stories.js.map +1 -0
- package/dist/components/provider-search.d.ts +4 -0
- package/dist/components/provider-search.d.ts.map +1 -0
- package/dist/components/provider-search.js +13 -0
- package/dist/components/provider-search.js.map +1 -0
- package/dist/components/supported-model-provider-catalog-entry.d.ts +8 -0
- package/dist/components/supported-model-provider-catalog-entry.d.ts.map +1 -0
- package/dist/components/supported-model-provider-catalog-entry.js +9 -0
- package/dist/components/supported-model-provider-catalog-entry.js.map +1 -0
- package/dist/components/test-and-save-form.d.ts +10 -0
- package/dist/components/test-and-save-form.d.ts.map +1 -0
- package/dist/components/test-and-save-form.js +138 -0
- package/dist/components/test-and-save-form.js.map +1 -0
- package/dist/feature.d.ts +9 -0
- package/dist/feature.d.ts.map +1 -0
- package/dist/feature.js +13 -0
- package/dist/feature.js.map +1 -0
- package/dist/hooks/api/model-providers.d.ts +334 -0
- package/dist/hooks/api/model-providers.d.ts.map +1 -0
- package/dist/hooks/api/model-providers.js +190 -0
- package/dist/hooks/api/model-providers.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/pages/model-provider-onboarding-page.d.ts +6 -0
- package/dist/pages/model-provider-onboarding-page.d.ts.map +1 -0
- package/dist/pages/model-provider-onboarding-page.js +295 -0
- package/dist/pages/model-provider-onboarding-page.js.map +1 -0
- package/dist/pages/model-provider-onboarding-page.stories.d.ts +27 -0
- package/dist/pages/model-provider-onboarding-page.stories.d.ts.map +1 -0
- package/dist/pages/model-provider-onboarding-page.stories.js +368 -0
- package/dist/pages/model-provider-onboarding-page.stories.js.map +1 -0
- package/dist/routes/model-provider.d.ts +5 -0
- package/dist/routes/model-provider.d.ts.map +1 -0
- package/dist/routes/model-provider.js +28 -0
- package/dist/routes/model-provider.js.map +1 -0
- package/dist/state/model-provider-onboarding.d.ts +3 -0
- package/dist/state/model-provider-onboarding.d.ts.map +1 -0
- package/dist/state/model-provider-onboarding.js +28 -0
- package/dist/state/model-provider-onboarding.js.map +1 -0
- package/dist/tsconfig.test.tsbuildinfo +1 -0
- package/package.json +114 -0
- package/src/components/add-custom-provider-card.tsx +32 -0
- package/src/components/agent-workflow-example.test.ts +74 -0
- package/src/components/agent-workflow-example.ts +55 -0
- package/src/components/available-provider-card.tsx +39 -0
- package/src/components/available-providers-grid.test.tsx +55 -0
- package/src/components/available-providers-grid.tsx +106 -0
- package/src/components/change-default-model-form.tsx +104 -0
- package/src/components/custom-model-provider-api-options.test.ts +18 -0
- package/src/components/custom-model-provider-api-options.ts +12 -0
- package/src/components/custom-model-provider-form.stories.tsx +91 -0
- package/src/components/custom-model-provider-form.tsx +710 -0
- package/src/components/custom-model-provider-payload.test.ts +170 -0
- package/src/components/custom-model-provider-payload.ts +264 -0
- package/src/components/custom-model-provider-slug.test.ts +40 -0
- package/src/components/custom-model-provider-slug.ts +23 -0
- package/src/components/default-model-field.tsx +85 -0
- package/src/components/form-errors.test.ts +159 -0
- package/src/components/form-errors.ts +102 -0
- package/src/components/harness-availability.test.ts +45 -0
- package/src/components/harness-availability.ts +35 -0
- package/src/components/harnesses-section.stories.tsx +129 -0
- package/src/components/harnesses-section.test.tsx +188 -0
- package/src/components/harnesses-section.tsx +245 -0
- package/src/components/model-provider-usage-modal.stories.tsx +106 -0
- package/src/components/model-provider-usage-modal.test.tsx +210 -0
- package/src/components/model-provider-usage-modal.tsx +326 -0
- package/src/components/model-provider-usage-target.ts +36 -0
- package/src/components/model-providers-section.stories.tsx +345 -0
- package/src/components/model-providers-section.test.tsx +831 -0
- package/src/components/model-providers-section.tsx +645 -0
- package/src/components/provider-search.test.ts +45 -0
- package/src/components/provider-search.ts +18 -0
- package/src/components/supported-model-provider-catalog-entry.ts +19 -0
- package/src/components/test-and-save-form.tsx +166 -0
- package/src/feature.ts +12 -0
- package/src/hooks/api/model-providers.test.ts +167 -0
- package/src/hooks/api/model-providers.ts +281 -0
- package/src/index.ts +8 -0
- package/src/pages/model-provider-onboarding-page.stories.tsx +284 -0
- package/src/pages/model-provider-onboarding-page.test.tsx +368 -0
- package/src/pages/model-provider-onboarding-page.tsx +290 -0
- package/src/routes/model-provider.tsx +20 -0
- package/src/state/model-provider-onboarding.test.ts +55 -0
- package/src/state/model-provider-onboarding.ts +34 -0
- package/test/fixtures/model-providers.ts +111 -0
- package/test/setup.ts +3 -0
- package/tsconfig.build.json +9 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.json +3 -0
- package/tsconfig.test.json +8 -0
- package/vercel.json +8 -0
- package/vitest.config.ts +72 -0
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { configureApiClient } from '@shipfox/client-api';
|
|
3
|
+
import { Toaster } from '@shipfox/react-ui/toast';
|
|
4
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
5
|
+
import { useMemo } from 'react';
|
|
6
|
+
import { screen, userEvent, within } from 'storybook/test';
|
|
7
|
+
import { ModelProviderOnboardingPage } from './model-provider-onboarding-page.js';
|
|
8
|
+
const WORKSPACE_ID = '11111111-1111-4111-8111-111111111111';
|
|
9
|
+
const CATALOG = [
|
|
10
|
+
providerEntry({
|
|
11
|
+
id: 'anthropic',
|
|
12
|
+
label: 'Anthropic',
|
|
13
|
+
default_model: 'claude-opus-4-8',
|
|
14
|
+
models: [
|
|
15
|
+
{
|
|
16
|
+
id: 'claude-opus-4-8',
|
|
17
|
+
label: 'Claude Opus 4.8'
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: 'claude-haiku-4-5',
|
|
21
|
+
label: 'Claude Haiku 4.5'
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}),
|
|
25
|
+
providerEntry({
|
|
26
|
+
id: 'openai',
|
|
27
|
+
label: 'OpenAI',
|
|
28
|
+
default_model: 'gpt-5.5-pro',
|
|
29
|
+
models: [
|
|
30
|
+
{
|
|
31
|
+
id: 'gpt-5.5-pro',
|
|
32
|
+
label: 'GPT-5.5 Pro'
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: 'gpt-5-mini',
|
|
36
|
+
label: 'GPT-5 Mini'
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
}),
|
|
40
|
+
providerEntry({
|
|
41
|
+
id: 'xai',
|
|
42
|
+
label: 'xAI',
|
|
43
|
+
default_model: 'grok-code-fast-1',
|
|
44
|
+
models: [
|
|
45
|
+
{
|
|
46
|
+
id: 'grok-code-fast-1',
|
|
47
|
+
label: 'Grok Code Fast 1'
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
}),
|
|
51
|
+
providerEntry({
|
|
52
|
+
id: 'openrouter',
|
|
53
|
+
label: 'OpenRouter',
|
|
54
|
+
default_model: 'openrouter/auto',
|
|
55
|
+
models: [
|
|
56
|
+
{
|
|
57
|
+
id: 'openrouter/auto',
|
|
58
|
+
label: 'OpenRouter Auto'
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
}),
|
|
62
|
+
providerEntry({
|
|
63
|
+
id: 'google',
|
|
64
|
+
label: 'Google Gemini',
|
|
65
|
+
default_model: 'gemini-3-pro',
|
|
66
|
+
models: [
|
|
67
|
+
{
|
|
68
|
+
id: 'gemini-3-pro',
|
|
69
|
+
label: 'Gemini 3 Pro'
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
}),
|
|
73
|
+
providerEntry({
|
|
74
|
+
id: 'mistral',
|
|
75
|
+
label: 'Mistral AI',
|
|
76
|
+
default_model: 'codestral-latest',
|
|
77
|
+
models: [
|
|
78
|
+
{
|
|
79
|
+
id: 'codestral-latest',
|
|
80
|
+
label: 'Codestral Latest'
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
}),
|
|
84
|
+
providerEntry({
|
|
85
|
+
id: 'groq',
|
|
86
|
+
label: 'Groq',
|
|
87
|
+
default_model: 'llama-4-fast',
|
|
88
|
+
models: [
|
|
89
|
+
{
|
|
90
|
+
id: 'llama-4-fast',
|
|
91
|
+
label: 'Llama 4 Fast'
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
}),
|
|
95
|
+
providerEntry({
|
|
96
|
+
id: 'deepseek',
|
|
97
|
+
label: 'DeepSeek',
|
|
98
|
+
default_model: 'deepseek-coder',
|
|
99
|
+
models: [
|
|
100
|
+
{
|
|
101
|
+
id: 'deepseek-coder',
|
|
102
|
+
label: 'DeepSeek Coder'
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
}),
|
|
106
|
+
providerEntry({
|
|
107
|
+
id: 'moonshotai',
|
|
108
|
+
label: 'Moonshot AI',
|
|
109
|
+
default_model: 'kimi-k2',
|
|
110
|
+
models: [
|
|
111
|
+
{
|
|
112
|
+
id: 'kimi-k2',
|
|
113
|
+
label: 'Kimi K2'
|
|
114
|
+
}
|
|
115
|
+
]
|
|
116
|
+
}),
|
|
117
|
+
providerEntry({
|
|
118
|
+
id: 'azure-openai-responses',
|
|
119
|
+
label: 'Azure OpenAI Responses',
|
|
120
|
+
default_model: 'gpt-5.5-pro',
|
|
121
|
+
models: [
|
|
122
|
+
{
|
|
123
|
+
id: 'gpt-5.5-pro',
|
|
124
|
+
label: 'GPT-5.5 Pro'
|
|
125
|
+
}
|
|
126
|
+
]
|
|
127
|
+
}),
|
|
128
|
+
providerEntry({
|
|
129
|
+
id: 'amazon-bedrock',
|
|
130
|
+
label: 'Amazon Bedrock',
|
|
131
|
+
support_status: 'unsupported',
|
|
132
|
+
credential_fields: [],
|
|
133
|
+
unsupported_reason: 'AWS cloud credentials are not supported yet.',
|
|
134
|
+
models: []
|
|
135
|
+
})
|
|
136
|
+
];
|
|
137
|
+
function ModelProviderOnboardingStory({ scenario }) {
|
|
138
|
+
configureApiClient({
|
|
139
|
+
baseUrl: 'https://api.example.test',
|
|
140
|
+
fetchImpl: fetchForScenario(scenario)
|
|
141
|
+
});
|
|
142
|
+
const queryClient = useMemo(()=>new QueryClient({
|
|
143
|
+
defaultOptions: {
|
|
144
|
+
queries: {
|
|
145
|
+
retry: false
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}), []);
|
|
149
|
+
return /*#__PURE__*/ _jsxs(QueryClientProvider, {
|
|
150
|
+
client: queryClient,
|
|
151
|
+
children: [
|
|
152
|
+
/*#__PURE__*/ _jsx("div", {
|
|
153
|
+
className: "bg-background-neutral-background px-24 py-32",
|
|
154
|
+
children: /*#__PURE__*/ _jsx(ModelProviderOnboardingPage, {
|
|
155
|
+
workspaceId: WORKSPACE_ID,
|
|
156
|
+
onSkip: ()=>undefined,
|
|
157
|
+
onConfigured: ()=>undefined
|
|
158
|
+
})
|
|
159
|
+
}),
|
|
160
|
+
/*#__PURE__*/ _jsx(Toaster, {})
|
|
161
|
+
]
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
const meta = {
|
|
165
|
+
title: 'Agent/ProviderOnboarding',
|
|
166
|
+
component: ModelProviderOnboardingStory,
|
|
167
|
+
parameters: {
|
|
168
|
+
layout: 'fullscreen'
|
|
169
|
+
},
|
|
170
|
+
args: {
|
|
171
|
+
scenario: 'available'
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
export default meta;
|
|
175
|
+
export const Playground = {};
|
|
176
|
+
export const Loading = {
|
|
177
|
+
args: {
|
|
178
|
+
scenario: 'loading'
|
|
179
|
+
},
|
|
180
|
+
play: async ({ canvasElement })=>{
|
|
181
|
+
const canvas = within(canvasElement);
|
|
182
|
+
await userEvent.click(canvas.getByRole('button', {
|
|
183
|
+
name: 'Choose pi'
|
|
184
|
+
}));
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
export const CatalogError = {
|
|
188
|
+
args: {
|
|
189
|
+
scenario: 'catalog-error'
|
|
190
|
+
},
|
|
191
|
+
play: async ({ canvasElement })=>{
|
|
192
|
+
const canvas = within(canvasElement);
|
|
193
|
+
await userEvent.click(canvas.getByRole('button', {
|
|
194
|
+
name: 'Choose pi'
|
|
195
|
+
}));
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
export const NoProvidersAvailable = {
|
|
199
|
+
args: {
|
|
200
|
+
scenario: 'no-providers'
|
|
201
|
+
},
|
|
202
|
+
play: async ({ canvasElement })=>{
|
|
203
|
+
const canvas = within(canvasElement);
|
|
204
|
+
await userEvent.click(canvas.getByRole('button', {
|
|
205
|
+
name: 'Choose pi'
|
|
206
|
+
}));
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
export const LongNames = {
|
|
210
|
+
args: {
|
|
211
|
+
scenario: 'long-names'
|
|
212
|
+
},
|
|
213
|
+
play: async ({ canvasElement })=>{
|
|
214
|
+
const canvas = within(canvasElement);
|
|
215
|
+
await userEvent.click(canvas.getByRole('button', {
|
|
216
|
+
name: 'Choose pi'
|
|
217
|
+
}));
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
export const FilteredProviders = {
|
|
221
|
+
args: {
|
|
222
|
+
scenario: 'available'
|
|
223
|
+
},
|
|
224
|
+
play: async ({ canvasElement })=>{
|
|
225
|
+
const canvas = within(canvasElement);
|
|
226
|
+
await userEvent.click(canvas.getByRole('button', {
|
|
227
|
+
name: 'Choose pi'
|
|
228
|
+
}));
|
|
229
|
+
await userEvent.type(await canvas.findByRole('searchbox', {
|
|
230
|
+
name: 'Search providers'
|
|
231
|
+
}), 'openrouter');
|
|
232
|
+
await canvas.findByRole('button', {
|
|
233
|
+
name: 'Configure OpenRouter'
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
export const NoMatchingProviders = {
|
|
238
|
+
args: {
|
|
239
|
+
scenario: 'available'
|
|
240
|
+
},
|
|
241
|
+
play: async ({ canvasElement })=>{
|
|
242
|
+
const canvas = within(canvasElement);
|
|
243
|
+
await userEvent.click(canvas.getByRole('button', {
|
|
244
|
+
name: 'Choose pi'
|
|
245
|
+
}));
|
|
246
|
+
await userEvent.type(await canvas.findByRole('searchbox', {
|
|
247
|
+
name: 'Search providers'
|
|
248
|
+
}), 'not-a-provider');
|
|
249
|
+
await canvas.findByRole('button', {
|
|
250
|
+
name: 'Clear search'
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
export const ConfigureModalOpen = {
|
|
255
|
+
args: {
|
|
256
|
+
scenario: 'available'
|
|
257
|
+
},
|
|
258
|
+
play: async ({ canvasElement })=>{
|
|
259
|
+
const canvas = within(canvasElement);
|
|
260
|
+
await userEvent.click(canvas.getByRole('button', {
|
|
261
|
+
name: 'Choose pi'
|
|
262
|
+
}));
|
|
263
|
+
await userEvent.click(await canvas.findByRole('button', {
|
|
264
|
+
name: 'Configure Anthropic'
|
|
265
|
+
}));
|
|
266
|
+
await screen.findByLabelText('API key');
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
function fetchForScenario(scenario) {
|
|
270
|
+
return (input)=>{
|
|
271
|
+
const url = requestUrl(input);
|
|
272
|
+
const request = input instanceof Request ? input : undefined;
|
|
273
|
+
if (scenario === 'loading') return new Promise(()=>undefined);
|
|
274
|
+
if (url.pathname.endsWith('/agent/model-provider-catalog')) {
|
|
275
|
+
if (scenario === 'catalog-error') return Promise.resolve(errorResponse());
|
|
276
|
+
return Promise.resolve(jsonResponse({
|
|
277
|
+
providers: catalogForScenario(scenario)
|
|
278
|
+
}));
|
|
279
|
+
}
|
|
280
|
+
if (request?.method === 'PUT' && url.pathname.includes('/agent/model-providers/')) {
|
|
281
|
+
return Promise.resolve(jsonResponse(providerConfig({
|
|
282
|
+
provider_id: url.pathname.endsWith('/openai') ? 'openai' : 'anthropic'
|
|
283
|
+
})));
|
|
284
|
+
}
|
|
285
|
+
return Promise.resolve(jsonResponse({}, {
|
|
286
|
+
status: 404
|
|
287
|
+
}));
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
function catalogForScenario(scenario) {
|
|
291
|
+
if (scenario === 'no-providers') return [];
|
|
292
|
+
if (scenario !== 'long-names') return CATALOG;
|
|
293
|
+
return [
|
|
294
|
+
providerEntry({
|
|
295
|
+
id: 'anthropic',
|
|
296
|
+
label: 'Anthropic Enterprise Production Claude Provider With Long Label',
|
|
297
|
+
default_model: 'claude-opus-4-8'
|
|
298
|
+
}),
|
|
299
|
+
providerEntry({
|
|
300
|
+
id: 'openai',
|
|
301
|
+
label: 'OpenAI Platform Shared Workspace Credentials With Long Label',
|
|
302
|
+
default_model: 'gpt-5.5-pro',
|
|
303
|
+
models: [
|
|
304
|
+
{
|
|
305
|
+
id: 'gpt-5.5-pro',
|
|
306
|
+
label: 'GPT-5.5 Pro'
|
|
307
|
+
}
|
|
308
|
+
]
|
|
309
|
+
})
|
|
310
|
+
];
|
|
311
|
+
}
|
|
312
|
+
function providerEntry(overrides = {}) {
|
|
313
|
+
return {
|
|
314
|
+
id: 'anthropic',
|
|
315
|
+
label: 'Anthropic',
|
|
316
|
+
support_status: 'supported',
|
|
317
|
+
default_model: null,
|
|
318
|
+
credential_fields: [
|
|
319
|
+
{
|
|
320
|
+
key: 'api_key',
|
|
321
|
+
label: 'API key',
|
|
322
|
+
secret: true
|
|
323
|
+
}
|
|
324
|
+
],
|
|
325
|
+
unsupported_reason: null,
|
|
326
|
+
models: [
|
|
327
|
+
{
|
|
328
|
+
id: 'claude-opus-4-8',
|
|
329
|
+
label: 'Claude Opus 4.8'
|
|
330
|
+
}
|
|
331
|
+
],
|
|
332
|
+
...overrides
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
function providerConfig(overrides = {}) {
|
|
336
|
+
return {
|
|
337
|
+
kind: 'builtin',
|
|
338
|
+
provider_id: 'anthropic',
|
|
339
|
+
default_model: null,
|
|
340
|
+
created_at: '2026-05-08T00:00:00.000Z',
|
|
341
|
+
updated_at: '2026-05-08T00:00:00.000Z',
|
|
342
|
+
...overrides
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
function requestUrl(input) {
|
|
346
|
+
if (typeof input === 'string') return new URL(input);
|
|
347
|
+
if (input instanceof URL) return input;
|
|
348
|
+
return new URL(input.url);
|
|
349
|
+
}
|
|
350
|
+
function jsonResponse(body, init = {}) {
|
|
351
|
+
return new Response(JSON.stringify(body), {
|
|
352
|
+
status: 200,
|
|
353
|
+
headers: {
|
|
354
|
+
'content-type': 'application/json'
|
|
355
|
+
},
|
|
356
|
+
...init
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
function errorResponse() {
|
|
360
|
+
return jsonResponse({
|
|
361
|
+
code: 'server-error'
|
|
362
|
+
}, {
|
|
363
|
+
status: 500,
|
|
364
|
+
statusText: 'Server error'
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
//# sourceMappingURL=model-provider-onboarding-page.stories.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/pages/model-provider-onboarding-page.stories.tsx"],"sourcesContent":["import type {ModelProviderCatalogEntryDto, ModelProviderConfigDto} from '@shipfox/api-agent-dto';\nimport {configureApiClient} from '@shipfox/client-api';\nimport {Toaster} from '@shipfox/react-ui/toast';\nimport type {Meta, StoryObj} from '@storybook/react';\nimport {QueryClient, QueryClientProvider} from '@tanstack/react-query';\nimport {useMemo} from 'react';\nimport {screen, userEvent, within} from 'storybook/test';\nimport {ModelProviderOnboardingPage} from './model-provider-onboarding-page.js';\n\nconst WORKSPACE_ID = '11111111-1111-4111-8111-111111111111';\n\ntype Scenario = 'available' | 'loading' | 'catalog-error' | 'no-providers' | 'long-names';\n\ninterface ModelProviderOnboardingStoryProps {\n scenario: Scenario;\n}\n\nconst CATALOG: ModelProviderCatalogEntryDto[] = [\n providerEntry({\n id: 'anthropic',\n label: 'Anthropic',\n default_model: 'claude-opus-4-8',\n models: [\n {id: 'claude-opus-4-8', label: 'Claude Opus 4.8'},\n {id: 'claude-haiku-4-5', label: 'Claude Haiku 4.5'},\n ],\n }),\n providerEntry({\n id: 'openai',\n label: 'OpenAI',\n default_model: 'gpt-5.5-pro',\n models: [\n {id: 'gpt-5.5-pro', label: 'GPT-5.5 Pro'},\n {id: 'gpt-5-mini', label: 'GPT-5 Mini'},\n ],\n }),\n providerEntry({\n id: 'xai',\n label: 'xAI',\n default_model: 'grok-code-fast-1',\n models: [{id: 'grok-code-fast-1', label: 'Grok Code Fast 1'}],\n }),\n providerEntry({\n id: 'openrouter',\n label: 'OpenRouter',\n default_model: 'openrouter/auto',\n models: [{id: 'openrouter/auto', label: 'OpenRouter Auto'}],\n }),\n providerEntry({\n id: 'google',\n label: 'Google Gemini',\n default_model: 'gemini-3-pro',\n models: [{id: 'gemini-3-pro', label: 'Gemini 3 Pro'}],\n }),\n providerEntry({\n id: 'mistral',\n label: 'Mistral AI',\n default_model: 'codestral-latest',\n models: [{id: 'codestral-latest', label: 'Codestral Latest'}],\n }),\n providerEntry({\n id: 'groq',\n label: 'Groq',\n default_model: 'llama-4-fast',\n models: [{id: 'llama-4-fast', label: 'Llama 4 Fast'}],\n }),\n providerEntry({\n id: 'deepseek',\n label: 'DeepSeek',\n default_model: 'deepseek-coder',\n models: [{id: 'deepseek-coder', label: 'DeepSeek Coder'}],\n }),\n providerEntry({\n id: 'moonshotai',\n label: 'Moonshot AI',\n default_model: 'kimi-k2',\n models: [{id: 'kimi-k2', label: 'Kimi K2'}],\n }),\n providerEntry({\n id: 'azure-openai-responses',\n label: 'Azure OpenAI Responses',\n default_model: 'gpt-5.5-pro',\n models: [{id: 'gpt-5.5-pro', label: 'GPT-5.5 Pro'}],\n }),\n providerEntry({\n id: 'amazon-bedrock',\n label: 'Amazon Bedrock',\n support_status: 'unsupported',\n credential_fields: [],\n unsupported_reason: 'AWS cloud credentials are not supported yet.',\n models: [],\n }),\n];\n\nfunction ModelProviderOnboardingStory({scenario}: ModelProviderOnboardingStoryProps) {\n configureApiClient({\n baseUrl: 'https://api.example.test',\n fetchImpl: fetchForScenario(scenario),\n });\n\n const queryClient = useMemo(\n () => new QueryClient({defaultOptions: {queries: {retry: false}}}),\n [],\n );\n\n return (\n <QueryClientProvider client={queryClient}>\n <div className=\"bg-background-neutral-background px-24 py-32\">\n <ModelProviderOnboardingPage\n workspaceId={WORKSPACE_ID}\n onSkip={() => undefined}\n onConfigured={() => undefined}\n />\n </div>\n <Toaster />\n </QueryClientProvider>\n );\n}\n\nconst meta = {\n title: 'Agent/ProviderOnboarding',\n component: ModelProviderOnboardingStory,\n parameters: {layout: 'fullscreen'},\n args: {scenario: 'available'},\n} satisfies Meta<typeof ModelProviderOnboardingStory>;\n\nexport default meta;\ntype Story = StoryObj<typeof meta>;\n\nexport const Playground: Story = {};\n\nexport const Loading: Story = {\n args: {scenario: 'loading'},\n play: async ({canvasElement}) => {\n const canvas = within(canvasElement);\n await userEvent.click(canvas.getByRole('button', {name: 'Choose pi'}));\n },\n};\n\nexport const CatalogError: Story = {\n args: {scenario: 'catalog-error'},\n play: async ({canvasElement}) => {\n const canvas = within(canvasElement);\n await userEvent.click(canvas.getByRole('button', {name: 'Choose pi'}));\n },\n};\n\nexport const NoProvidersAvailable: Story = {\n args: {scenario: 'no-providers'},\n play: async ({canvasElement}) => {\n const canvas = within(canvasElement);\n await userEvent.click(canvas.getByRole('button', {name: 'Choose pi'}));\n },\n};\n\nexport const LongNames: Story = {\n args: {scenario: 'long-names'},\n play: async ({canvasElement}) => {\n const canvas = within(canvasElement);\n await userEvent.click(canvas.getByRole('button', {name: 'Choose pi'}));\n },\n};\n\nexport const FilteredProviders: Story = {\n args: {scenario: 'available'},\n play: async ({canvasElement}) => {\n const canvas = within(canvasElement);\n await userEvent.click(canvas.getByRole('button', {name: 'Choose pi'}));\n await userEvent.type(\n await canvas.findByRole('searchbox', {name: 'Search providers'}),\n 'openrouter',\n );\n await canvas.findByRole('button', {name: 'Configure OpenRouter'});\n },\n};\n\nexport const NoMatchingProviders: Story = {\n args: {scenario: 'available'},\n play: async ({canvasElement}) => {\n const canvas = within(canvasElement);\n await userEvent.click(canvas.getByRole('button', {name: 'Choose pi'}));\n await userEvent.type(\n await canvas.findByRole('searchbox', {name: 'Search providers'}),\n 'not-a-provider',\n );\n await canvas.findByRole('button', {name: 'Clear search'});\n },\n};\n\nexport const ConfigureModalOpen: Story = {\n args: {scenario: 'available'},\n play: async ({canvasElement}) => {\n const canvas = within(canvasElement);\n await userEvent.click(canvas.getByRole('button', {name: 'Choose pi'}));\n await userEvent.click(await canvas.findByRole('button', {name: 'Configure Anthropic'}));\n await screen.findByLabelText('API key');\n },\n};\n\nfunction fetchForScenario(scenario: Scenario): typeof fetch {\n return (input) => {\n const url = requestUrl(input);\n const request = input instanceof Request ? input : undefined;\n if (scenario === 'loading') return new Promise<Response>(() => undefined);\n if (url.pathname.endsWith('/agent/model-provider-catalog')) {\n if (scenario === 'catalog-error') return Promise.resolve(errorResponse());\n return Promise.resolve(jsonResponse({providers: catalogForScenario(scenario)}));\n }\n if (request?.method === 'PUT' && url.pathname.includes('/agent/model-providers/')) {\n return Promise.resolve(\n jsonResponse(\n providerConfig({\n provider_id: url.pathname.endsWith('/openai') ? 'openai' : 'anthropic',\n }),\n ),\n );\n }\n return Promise.resolve(jsonResponse({}, {status: 404}));\n };\n}\n\nfunction catalogForScenario(scenario: Scenario): ModelProviderCatalogEntryDto[] {\n if (scenario === 'no-providers') return [];\n if (scenario !== 'long-names') return CATALOG;\n return [\n providerEntry({\n id: 'anthropic',\n label: 'Anthropic Enterprise Production Claude Provider With Long Label',\n default_model: 'claude-opus-4-8',\n }),\n providerEntry({\n id: 'openai',\n label: 'OpenAI Platform Shared Workspace Credentials With Long Label',\n default_model: 'gpt-5.5-pro',\n models: [{id: 'gpt-5.5-pro', label: 'GPT-5.5 Pro'}],\n }),\n ];\n}\n\nfunction providerEntry(\n overrides: Partial<ModelProviderCatalogEntryDto> = {},\n): ModelProviderCatalogEntryDto {\n return {\n id: 'anthropic',\n label: 'Anthropic',\n support_status: 'supported',\n default_model: null,\n credential_fields: [{key: 'api_key', label: 'API key', secret: true}],\n unsupported_reason: null,\n models: [{id: 'claude-opus-4-8', label: 'Claude Opus 4.8'}],\n ...overrides,\n };\n}\n\nfunction providerConfig(\n overrides: Partial<Omit<ModelProviderConfigDto, 'kind'>> = {},\n): ModelProviderConfigDto {\n return {\n kind: 'builtin',\n provider_id: 'anthropic',\n default_model: null,\n created_at: '2026-05-08T00:00:00.000Z',\n updated_at: '2026-05-08T00:00:00.000Z',\n ...overrides,\n };\n}\n\nfunction requestUrl(input: RequestInfo | URL): URL {\n if (typeof input === 'string') return new URL(input);\n if (input instanceof URL) return input;\n return new URL(input.url);\n}\n\nfunction jsonResponse(body: unknown, init: ResponseInit = {}) {\n return new Response(JSON.stringify(body), {\n status: 200,\n headers: {'content-type': 'application/json'},\n ...init,\n });\n}\n\nfunction errorResponse() {\n return jsonResponse({code: 'server-error'}, {status: 500, statusText: 'Server error'});\n}\n"],"names":["configureApiClient","Toaster","QueryClient","QueryClientProvider","useMemo","screen","userEvent","within","ModelProviderOnboardingPage","WORKSPACE_ID","CATALOG","providerEntry","id","label","default_model","models","support_status","credential_fields","unsupported_reason","ModelProviderOnboardingStory","scenario","baseUrl","fetchImpl","fetchForScenario","queryClient","defaultOptions","queries","retry","client","div","className","workspaceId","onSkip","undefined","onConfigured","meta","title","component","parameters","layout","args","Playground","Loading","play","canvasElement","canvas","click","getByRole","name","CatalogError","NoProvidersAvailable","LongNames","FilteredProviders","type","findByRole","NoMatchingProviders","ConfigureModalOpen","findByLabelText","input","url","requestUrl","request","Request","Promise","pathname","endsWith","resolve","errorResponse","jsonResponse","providers","catalogForScenario","method","includes","providerConfig","provider_id","status","overrides","key","secret","kind","created_at","updated_at","URL","body","init","Response","JSON","stringify","headers","code","statusText"],"mappings":";AACA,SAAQA,kBAAkB,QAAO,sBAAsB;AACvD,SAAQC,OAAO,QAAO,0BAA0B;AAEhD,SAAQC,WAAW,EAAEC,mBAAmB,QAAO,wBAAwB;AACvE,SAAQC,OAAO,QAAO,QAAQ;AAC9B,SAAQC,MAAM,EAAEC,SAAS,EAAEC,MAAM,QAAO,iBAAiB;AACzD,SAAQC,2BAA2B,QAAO,sCAAsC;AAEhF,MAAMC,eAAe;AAQrB,MAAMC,UAA0C;IAC9CC,cAAc;QACZC,IAAI;QACJC,OAAO;QACPC,eAAe;QACfC,QAAQ;YACN;gBAACH,IAAI;gBAAmBC,OAAO;YAAiB;YAChD;gBAACD,IAAI;gBAAoBC,OAAO;YAAkB;SACnD;IACH;IACAF,cAAc;QACZC,IAAI;QACJC,OAAO;QACPC,eAAe;QACfC,QAAQ;YACN;gBAACH,IAAI;gBAAeC,OAAO;YAAa;YACxC;gBAACD,IAAI;gBAAcC,OAAO;YAAY;SACvC;IACH;IACAF,cAAc;QACZC,IAAI;QACJC,OAAO;QACPC,eAAe;QACfC,QAAQ;YAAC;gBAACH,IAAI;gBAAoBC,OAAO;YAAkB;SAAE;IAC/D;IACAF,cAAc;QACZC,IAAI;QACJC,OAAO;QACPC,eAAe;QACfC,QAAQ;YAAC;gBAACH,IAAI;gBAAmBC,OAAO;YAAiB;SAAE;IAC7D;IACAF,cAAc;QACZC,IAAI;QACJC,OAAO;QACPC,eAAe;QACfC,QAAQ;YAAC;gBAACH,IAAI;gBAAgBC,OAAO;YAAc;SAAE;IACvD;IACAF,cAAc;QACZC,IAAI;QACJC,OAAO;QACPC,eAAe;QACfC,QAAQ;YAAC;gBAACH,IAAI;gBAAoBC,OAAO;YAAkB;SAAE;IAC/D;IACAF,cAAc;QACZC,IAAI;QACJC,OAAO;QACPC,eAAe;QACfC,QAAQ;YAAC;gBAACH,IAAI;gBAAgBC,OAAO;YAAc;SAAE;IACvD;IACAF,cAAc;QACZC,IAAI;QACJC,OAAO;QACPC,eAAe;QACfC,QAAQ;YAAC;gBAACH,IAAI;gBAAkBC,OAAO;YAAgB;SAAE;IAC3D;IACAF,cAAc;QACZC,IAAI;QACJC,OAAO;QACPC,eAAe;QACfC,QAAQ;YAAC;gBAACH,IAAI;gBAAWC,OAAO;YAAS;SAAE;IAC7C;IACAF,cAAc;QACZC,IAAI;QACJC,OAAO;QACPC,eAAe;QACfC,QAAQ;YAAC;gBAACH,IAAI;gBAAeC,OAAO;YAAa;SAAE;IACrD;IACAF,cAAc;QACZC,IAAI;QACJC,OAAO;QACPG,gBAAgB;QAChBC,mBAAmB,EAAE;QACrBC,oBAAoB;QACpBH,QAAQ,EAAE;IACZ;CACD;AAED,SAASI,6BAA6B,EAACC,QAAQ,EAAoC;IACjFpB,mBAAmB;QACjBqB,SAAS;QACTC,WAAWC,iBAAiBH;IAC9B;IAEA,MAAMI,cAAcpB,QAClB,IAAM,IAAIF,YAAY;YAACuB,gBAAgB;gBAACC,SAAS;oBAACC,OAAO;gBAAK;YAAC;QAAC,IAChE,EAAE;IAGJ,qBACE,MAACxB;QAAoByB,QAAQJ;;0BAC3B,KAACK;gBAAIC,WAAU;0BACb,cAAA,KAACtB;oBACCuB,aAAatB;oBACbuB,QAAQ,IAAMC;oBACdC,cAAc,IAAMD;;;0BAGxB,KAAChC;;;AAGP;AAEA,MAAMkC,OAAO;IACXC,OAAO;IACPC,WAAWlB;IACXmB,YAAY;QAACC,QAAQ;IAAY;IACjCC,MAAM;QAACpB,UAAU;IAAW;AAC9B;AAEA,eAAee,KAAK;AAGpB,OAAO,MAAMM,aAAoB,CAAC,EAAE;AAEpC,OAAO,MAAMC,UAAiB;IAC5BF,MAAM;QAACpB,UAAU;IAAS;IAC1BuB,MAAM,OAAO,EAACC,aAAa,EAAC;QAC1B,MAAMC,SAAStC,OAAOqC;QACtB,MAAMtC,UAAUwC,KAAK,CAACD,OAAOE,SAAS,CAAC,UAAU;YAACC,MAAM;QAAW;IACrE;AACF,EAAE;AAEF,OAAO,MAAMC,eAAsB;IACjCT,MAAM;QAACpB,UAAU;IAAe;IAChCuB,MAAM,OAAO,EAACC,aAAa,EAAC;QAC1B,MAAMC,SAAStC,OAAOqC;QACtB,MAAMtC,UAAUwC,KAAK,CAACD,OAAOE,SAAS,CAAC,UAAU;YAACC,MAAM;QAAW;IACrE;AACF,EAAE;AAEF,OAAO,MAAME,uBAA8B;IACzCV,MAAM;QAACpB,UAAU;IAAc;IAC/BuB,MAAM,OAAO,EAACC,aAAa,EAAC;QAC1B,MAAMC,SAAStC,OAAOqC;QACtB,MAAMtC,UAAUwC,KAAK,CAACD,OAAOE,SAAS,CAAC,UAAU;YAACC,MAAM;QAAW;IACrE;AACF,EAAE;AAEF,OAAO,MAAMG,YAAmB;IAC9BX,MAAM;QAACpB,UAAU;IAAY;IAC7BuB,MAAM,OAAO,EAACC,aAAa,EAAC;QAC1B,MAAMC,SAAStC,OAAOqC;QACtB,MAAMtC,UAAUwC,KAAK,CAACD,OAAOE,SAAS,CAAC,UAAU;YAACC,MAAM;QAAW;IACrE;AACF,EAAE;AAEF,OAAO,MAAMI,oBAA2B;IACtCZ,MAAM;QAACpB,UAAU;IAAW;IAC5BuB,MAAM,OAAO,EAACC,aAAa,EAAC;QAC1B,MAAMC,SAAStC,OAAOqC;QACtB,MAAMtC,UAAUwC,KAAK,CAACD,OAAOE,SAAS,CAAC,UAAU;YAACC,MAAM;QAAW;QACnE,MAAM1C,UAAU+C,IAAI,CAClB,MAAMR,OAAOS,UAAU,CAAC,aAAa;YAACN,MAAM;QAAkB,IAC9D;QAEF,MAAMH,OAAOS,UAAU,CAAC,UAAU;YAACN,MAAM;QAAsB;IACjE;AACF,EAAE;AAEF,OAAO,MAAMO,sBAA6B;IACxCf,MAAM;QAACpB,UAAU;IAAW;IAC5BuB,MAAM,OAAO,EAACC,aAAa,EAAC;QAC1B,MAAMC,SAAStC,OAAOqC;QACtB,MAAMtC,UAAUwC,KAAK,CAACD,OAAOE,SAAS,CAAC,UAAU;YAACC,MAAM;QAAW;QACnE,MAAM1C,UAAU+C,IAAI,CAClB,MAAMR,OAAOS,UAAU,CAAC,aAAa;YAACN,MAAM;QAAkB,IAC9D;QAEF,MAAMH,OAAOS,UAAU,CAAC,UAAU;YAACN,MAAM;QAAc;IACzD;AACF,EAAE;AAEF,OAAO,MAAMQ,qBAA4B;IACvChB,MAAM;QAACpB,UAAU;IAAW;IAC5BuB,MAAM,OAAO,EAACC,aAAa,EAAC;QAC1B,MAAMC,SAAStC,OAAOqC;QACtB,MAAMtC,UAAUwC,KAAK,CAACD,OAAOE,SAAS,CAAC,UAAU;YAACC,MAAM;QAAW;QACnE,MAAM1C,UAAUwC,KAAK,CAAC,MAAMD,OAAOS,UAAU,CAAC,UAAU;YAACN,MAAM;QAAqB;QACpF,MAAM3C,OAAOoD,eAAe,CAAC;IAC/B;AACF,EAAE;AAEF,SAASlC,iBAAiBH,QAAkB;IAC1C,OAAO,CAACsC;QACN,MAAMC,MAAMC,WAAWF;QACvB,MAAMG,UAAUH,iBAAiBI,UAAUJ,QAAQzB;QACnD,IAAIb,aAAa,WAAW,OAAO,IAAI2C,QAAkB,IAAM9B;QAC/D,IAAI0B,IAAIK,QAAQ,CAACC,QAAQ,CAAC,kCAAkC;YAC1D,IAAI7C,aAAa,iBAAiB,OAAO2C,QAAQG,OAAO,CAACC;YACzD,OAAOJ,QAAQG,OAAO,CAACE,aAAa;gBAACC,WAAWC,mBAAmBlD;YAAS;QAC9E;QACA,IAAIyC,SAASU,WAAW,SAASZ,IAAIK,QAAQ,CAACQ,QAAQ,CAAC,4BAA4B;YACjF,OAAOT,QAAQG,OAAO,CACpBE,aACEK,eAAe;gBACbC,aAAaf,IAAIK,QAAQ,CAACC,QAAQ,CAAC,aAAa,WAAW;YAC7D;QAGN;QACA,OAAOF,QAAQG,OAAO,CAACE,aAAa,CAAC,GAAG;YAACO,QAAQ;QAAG;IACtD;AACF;AAEA,SAASL,mBAAmBlD,QAAkB;IAC5C,IAAIA,aAAa,gBAAgB,OAAO,EAAE;IAC1C,IAAIA,aAAa,cAAc,OAAOV;IACtC,OAAO;QACLC,cAAc;YACZC,IAAI;YACJC,OAAO;YACPC,eAAe;QACjB;QACAH,cAAc;YACZC,IAAI;YACJC,OAAO;YACPC,eAAe;YACfC,QAAQ;gBAAC;oBAACH,IAAI;oBAAeC,OAAO;gBAAa;aAAE;QACrD;KACD;AACH;AAEA,SAASF,cACPiE,YAAmD,CAAC,CAAC;IAErD,OAAO;QACLhE,IAAI;QACJC,OAAO;QACPG,gBAAgB;QAChBF,eAAe;QACfG,mBAAmB;YAAC;gBAAC4D,KAAK;gBAAWhE,OAAO;gBAAWiE,QAAQ;YAAI;SAAE;QACrE5D,oBAAoB;QACpBH,QAAQ;YAAC;gBAACH,IAAI;gBAAmBC,OAAO;YAAiB;SAAE;QAC3D,GAAG+D,SAAS;IACd;AACF;AAEA,SAASH,eACPG,YAA2D,CAAC,CAAC;IAE7D,OAAO;QACLG,MAAM;QACNL,aAAa;QACb5D,eAAe;QACfkE,YAAY;QACZC,YAAY;QACZ,GAAGL,SAAS;IACd;AACF;AAEA,SAAShB,WAAWF,KAAwB;IAC1C,IAAI,OAAOA,UAAU,UAAU,OAAO,IAAIwB,IAAIxB;IAC9C,IAAIA,iBAAiBwB,KAAK,OAAOxB;IACjC,OAAO,IAAIwB,IAAIxB,MAAMC,GAAG;AAC1B;AAEA,SAASS,aAAae,IAAa,EAAEC,OAAqB,CAAC,CAAC;IAC1D,OAAO,IAAIC,SAASC,KAAKC,SAAS,CAACJ,OAAO;QACxCR,QAAQ;QACRa,SAAS;YAAC,gBAAgB;QAAkB;QAC5C,GAAGJ,IAAI;IACT;AACF;AAEA,SAASjB;IACP,OAAOC,aAAa;QAACqB,MAAM;IAAc,GAAG;QAACd,QAAQ;QAAKe,YAAY;IAAc;AACtF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-provider.d.ts","sourceRoot":"","sources":["../../src/routes/model-provider.tsx"],"names":[],"mappings":";;;AAIA,wBAeG"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { defineRoute } from '@shipfox/client-shell/runtime';
|
|
3
|
+
import { useNavigate, useParams } from '@tanstack/react-router';
|
|
4
|
+
import { ModelProviderOnboardingPage } from '#pages/model-provider-onboarding-page.js';
|
|
5
|
+
export default defineRoute({
|
|
6
|
+
component: ()=>{
|
|
7
|
+
const { wid } = useParams({
|
|
8
|
+
strict: false
|
|
9
|
+
});
|
|
10
|
+
const navigate = useNavigate();
|
|
11
|
+
const goToProjectCreation = ()=>{
|
|
12
|
+
void navigate({
|
|
13
|
+
to: '/workspaces/$wid/projects/new',
|
|
14
|
+
params: {
|
|
15
|
+
wid
|
|
16
|
+
},
|
|
17
|
+
replace: true
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
return /*#__PURE__*/ _jsx(ModelProviderOnboardingPage, {
|
|
21
|
+
workspaceId: wid,
|
|
22
|
+
onSkip: goToProjectCreation,
|
|
23
|
+
onConfigured: goToProjectCreation
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
//# sourceMappingURL=model-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/routes/model-provider.tsx"],"sourcesContent":["import {defineRoute} from '@shipfox/client-shell/runtime';\nimport {useNavigate, useParams} from '@tanstack/react-router';\nimport {ModelProviderOnboardingPage} from '#pages/model-provider-onboarding-page.js';\n\nexport default defineRoute({\n component: () => {\n const {wid} = useParams({strict: false}) as {wid: string};\n const navigate = useNavigate();\n const goToProjectCreation = () => {\n void navigate({to: '/workspaces/$wid/projects/new', params: {wid}, replace: true});\n };\n return (\n <ModelProviderOnboardingPage\n workspaceId={wid}\n onSkip={goToProjectCreation}\n onConfigured={goToProjectCreation}\n />\n );\n },\n});\n"],"names":["defineRoute","useNavigate","useParams","ModelProviderOnboardingPage","component","wid","strict","navigate","goToProjectCreation","to","params","replace","workspaceId","onSkip","onConfigured"],"mappings":";AAAA,SAAQA,WAAW,QAAO,gCAAgC;AAC1D,SAAQC,WAAW,EAAEC,SAAS,QAAO,yBAAyB;AAC9D,SAAQC,2BAA2B,QAAO,2CAA2C;AAErF,eAAeH,YAAY;IACzBI,WAAW;QACT,MAAM,EAACC,GAAG,EAAC,GAAGH,UAAU;YAACI,QAAQ;QAAK;QACtC,MAAMC,WAAWN;QACjB,MAAMO,sBAAsB;YAC1B,KAAKD,SAAS;gBAACE,IAAI;gBAAiCC,QAAQ;oBAACL;gBAAG;gBAAGM,SAAS;YAAI;QAClF;QACA,qBACE,KAACR;YACCS,aAAaP;YACbQ,QAAQL;YACRM,cAAcN;;IAGpB;AACF,GAAG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-provider-onboarding.d.ts","sourceRoot":"","sources":["../../src/state/model-provider-onboarding.ts"],"names":[],"mappings":"AAIA,wBAAgB,kCAAkC,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAE/E;AAED,wBAAgB,8BAA8B,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAMxE"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const MODEL_PROVIDER_ONBOARDING_STORAGE_KEY = 'shipfox.modelProviderOnboardingDismissed';
|
|
2
|
+
export function isModelProviderOnboardingDismissed(workspaceId) {
|
|
3
|
+
return Boolean(readDismissedMap()[workspaceId]);
|
|
4
|
+
}
|
|
5
|
+
export function dismissModelProviderOnboarding(workspaceId) {
|
|
6
|
+
if (typeof window === 'undefined') return;
|
|
7
|
+
const dismissed = readDismissedMap();
|
|
8
|
+
dismissed[workspaceId] = true;
|
|
9
|
+
window.localStorage.setItem(MODEL_PROVIDER_ONBOARDING_STORAGE_KEY, JSON.stringify(dismissed));
|
|
10
|
+
}
|
|
11
|
+
function readDismissedMap() {
|
|
12
|
+
if (typeof window === 'undefined') return {};
|
|
13
|
+
try {
|
|
14
|
+
const raw = window.localStorage.getItem(MODEL_PROVIDER_ONBOARDING_STORAGE_KEY);
|
|
15
|
+
if (!raw) return {};
|
|
16
|
+
const parsed = JSON.parse(raw);
|
|
17
|
+
if (!isDismissedMap(parsed)) return {};
|
|
18
|
+
return parsed;
|
|
19
|
+
} catch {
|
|
20
|
+
return {};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function isDismissedMap(value) {
|
|
24
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;
|
|
25
|
+
return Object.values(value).every((entry)=>entry === true);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
//# sourceMappingURL=model-provider-onboarding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/state/model-provider-onboarding.ts"],"sourcesContent":["const MODEL_PROVIDER_ONBOARDING_STORAGE_KEY = 'shipfox.modelProviderOnboardingDismissed';\n\ntype DismissedMap = Record<string, true>;\n\nexport function isModelProviderOnboardingDismissed(workspaceId: string): boolean {\n return Boolean(readDismissedMap()[workspaceId]);\n}\n\nexport function dismissModelProviderOnboarding(workspaceId: string): void {\n if (typeof window === 'undefined') return;\n\n const dismissed = readDismissedMap();\n dismissed[workspaceId] = true;\n window.localStorage.setItem(MODEL_PROVIDER_ONBOARDING_STORAGE_KEY, JSON.stringify(dismissed));\n}\n\nfunction readDismissedMap(): DismissedMap {\n if (typeof window === 'undefined') return {};\n\n try {\n const raw = window.localStorage.getItem(MODEL_PROVIDER_ONBOARDING_STORAGE_KEY);\n if (!raw) return {};\n const parsed: unknown = JSON.parse(raw);\n if (!isDismissedMap(parsed)) return {};\n return parsed;\n } catch {\n return {};\n }\n}\n\nfunction isDismissedMap(value: unknown): value is DismissedMap {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n return Object.values(value).every((entry) => entry === true);\n}\n"],"names":["MODEL_PROVIDER_ONBOARDING_STORAGE_KEY","isModelProviderOnboardingDismissed","workspaceId","Boolean","readDismissedMap","dismissModelProviderOnboarding","window","dismissed","localStorage","setItem","JSON","stringify","raw","getItem","parsed","parse","isDismissedMap","value","Array","isArray","Object","values","every","entry"],"mappings":"AAAA,MAAMA,wCAAwC;AAI9C,OAAO,SAASC,mCAAmCC,WAAmB;IACpE,OAAOC,QAAQC,kBAAkB,CAACF,YAAY;AAChD;AAEA,OAAO,SAASG,+BAA+BH,WAAmB;IAChE,IAAI,OAAOI,WAAW,aAAa;IAEnC,MAAMC,YAAYH;IAClBG,SAAS,CAACL,YAAY,GAAG;IACzBI,OAAOE,YAAY,CAACC,OAAO,CAACT,uCAAuCU,KAAKC,SAAS,CAACJ;AACpF;AAEA,SAASH;IACP,IAAI,OAAOE,WAAW,aAAa,OAAO,CAAC;IAE3C,IAAI;QACF,MAAMM,MAAMN,OAAOE,YAAY,CAACK,OAAO,CAACb;QACxC,IAAI,CAACY,KAAK,OAAO,CAAC;QAClB,MAAME,SAAkBJ,KAAKK,KAAK,CAACH;QACnC,IAAI,CAACI,eAAeF,SAAS,OAAO,CAAC;QACrC,OAAOA;IACT,EAAE,OAAM;QACN,OAAO,CAAC;IACV;AACF;AAEA,SAASE,eAAeC,KAAc;IACpC,IAAI,OAAOA,UAAU,YAAYA,UAAU,QAAQC,MAAMC,OAAO,CAACF,QAAQ,OAAO;IAChF,OAAOG,OAAOC,MAAM,CAACJ,OAAOK,KAAK,CAAC,CAACC,QAAUA,UAAU;AACzD"}
|