@shipfox/client-agent 5.0.0 → 6.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.
Files changed (163) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +45 -0
  3. package/dist/components/available-provider-card.d.ts +2 -2
  4. package/dist/components/available-provider-card.d.ts.map +1 -1
  5. package/dist/components/available-provider-card.js.map +1 -1
  6. package/dist/components/available-providers-grid.d.ts +2 -2
  7. package/dist/components/available-providers-grid.d.ts.map +1 -1
  8. package/dist/components/available-providers-grid.js +1 -1
  9. package/dist/components/available-providers-grid.js.map +1 -1
  10. package/dist/components/change-default-model-form.d.ts +3 -4
  11. package/dist/components/change-default-model-form.d.ts.map +1 -1
  12. package/dist/components/change-default-model-form.js +2 -4
  13. package/dist/components/change-default-model-form.js.map +1 -1
  14. package/dist/components/custom-model-provider-api-options.d.ts +3 -3
  15. package/dist/components/custom-model-provider-api-options.d.ts.map +1 -1
  16. package/dist/components/custom-model-provider-api-options.js.map +1 -1
  17. package/dist/components/custom-model-provider-form.d.ts +2 -2
  18. package/dist/components/custom-model-provider-form.d.ts.map +1 -1
  19. package/dist/components/custom-model-provider-form.js +12 -10
  20. package/dist/components/custom-model-provider-form.js.map +1 -1
  21. package/dist/components/custom-model-provider-form.stories.d.ts.map +1 -1
  22. package/dist/components/custom-model-provider-form.stories.js +11 -11
  23. package/dist/components/custom-model-provider-form.stories.js.map +1 -1
  24. package/dist/components/custom-model-provider-payload.d.ts +9 -9
  25. package/dist/components/custom-model-provider-payload.d.ts.map +1 -1
  26. package/dist/components/custom-model-provider-payload.js +42 -26
  27. package/dist/components/custom-model-provider-payload.js.map +1 -1
  28. package/dist/components/custom-model-provider-slug.d.ts +1 -1
  29. package/dist/components/custom-model-provider-slug.d.ts.map +1 -1
  30. package/dist/components/custom-model-provider-slug.js +3 -3
  31. package/dist/components/custom-model-provider-slug.js.map +1 -1
  32. package/dist/components/default-model-field.d.ts +2 -2
  33. package/dist/components/default-model-field.d.ts.map +1 -1
  34. package/dist/components/default-model-field.js +1 -1
  35. package/dist/components/default-model-field.js.map +1 -1
  36. package/dist/components/harness-availability.d.ts +4 -7
  37. package/dist/components/harness-availability.d.ts.map +1 -1
  38. package/dist/components/harness-availability.js +2 -11
  39. package/dist/components/harness-availability.js.map +1 -1
  40. package/dist/components/harnesses-section.d.ts.map +1 -1
  41. package/dist/components/harnesses-section.js +4 -6
  42. package/dist/components/harnesses-section.js.map +1 -1
  43. package/dist/components/model-provider-usage-modal.d.ts +2 -2
  44. package/dist/components/model-provider-usage-modal.d.ts.map +1 -1
  45. package/dist/components/model-provider-usage-modal.js +4 -4
  46. package/dist/components/model-provider-usage-modal.js.map +1 -1
  47. package/dist/components/model-provider-usage-modal.stories.d.ts.map +1 -1
  48. package/dist/components/model-provider-usage-modal.stories.js +14 -16
  49. package/dist/components/model-provider-usage-modal.stories.js.map +1 -1
  50. package/dist/components/model-provider-usage-target.d.ts +5 -5
  51. package/dist/components/model-provider-usage-target.d.ts.map +1 -1
  52. package/dist/components/model-provider-usage-target.js +10 -8
  53. package/dist/components/model-provider-usage-target.js.map +1 -1
  54. package/dist/components/model-providers-section.d.ts.map +1 -1
  55. package/dist/components/model-providers-section.js +112 -94
  56. package/dist/components/model-providers-section.js.map +1 -1
  57. package/dist/components/model-providers-section.stories.js +8 -4
  58. package/dist/components/model-providers-section.stories.js.map +1 -1
  59. package/dist/components/test-and-save-form.d.ts +3 -3
  60. package/dist/components/test-and-save-form.d.ts.map +1 -1
  61. package/dist/components/test-and-save-form.js +7 -7
  62. package/dist/components/test-and-save-form.js.map +1 -1
  63. package/dist/core/harness-policy.d.ts +11 -0
  64. package/dist/core/harness-policy.d.ts.map +1 -0
  65. package/dist/core/harness-policy.js +71 -0
  66. package/dist/core/harness-policy.js.map +1 -0
  67. package/dist/core/model-provider-management-reducer.d.ts +51 -0
  68. package/dist/core/model-provider-management-reducer.d.ts.map +1 -0
  69. package/dist/core/model-provider-management-reducer.js +43 -0
  70. package/dist/core/model-provider-management-reducer.js.map +1 -0
  71. package/dist/core/models.d.ts +120 -0
  72. package/dist/core/models.d.ts.map +1 -0
  73. package/dist/core/models.js +3 -0
  74. package/dist/core/models.js.map +1 -0
  75. package/dist/core/onboarding-reducer.d.ts +36 -0
  76. package/dist/core/onboarding-reducer.d.ts.map +1 -0
  77. package/dist/core/onboarding-reducer.js +54 -0
  78. package/dist/core/onboarding-reducer.js.map +1 -0
  79. package/dist/core/provider-policy.d.ts +9 -0
  80. package/dist/core/provider-policy.d.ts.map +1 -0
  81. package/dist/core/provider-policy.js +37 -0
  82. package/dist/core/provider-policy.js.map +1 -0
  83. package/dist/feature.d.ts +7 -0
  84. package/dist/feature.d.ts.map +1 -1
  85. package/dist/feature.js +10 -9
  86. package/dist/feature.js.map +1 -1
  87. package/dist/hooks/api/model-provider-command-mapper.d.ts +11 -0
  88. package/dist/hooks/api/model-provider-command-mapper.d.ts.map +1 -0
  89. package/dist/hooks/api/model-provider-command-mapper.js +144 -0
  90. package/dist/hooks/api/model-provider-command-mapper.js.map +1 -0
  91. package/dist/hooks/api/model-provider-mapper.d.ts +11 -0
  92. package/dist/hooks/api/model-provider-mapper.d.ts.map +1 -0
  93. package/dist/hooks/api/model-provider-mapper.js +94 -0
  94. package/dist/hooks/api/model-provider-mapper.js.map +1 -0
  95. package/dist/hooks/api/model-providers.d.ts +60 -295
  96. package/dist/hooks/api/model-providers.d.ts.map +1 -1
  97. package/dist/hooks/api/model-providers.js +51 -37
  98. package/dist/hooks/api/model-providers.js.map +1 -1
  99. package/dist/pages/model-provider-onboarding-page.d.ts.map +1 -1
  100. package/dist/pages/model-provider-onboarding-page.js +57 -45
  101. package/dist/pages/model-provider-onboarding-page.js.map +1 -1
  102. package/dist/routes/inputs.d.ts +4 -0
  103. package/dist/routes/inputs.d.ts.map +1 -0
  104. package/dist/routes/inputs.js +12 -0
  105. package/dist/routes/inputs.js.map +1 -0
  106. package/dist/routes/model-provider.d.ts.map +1 -1
  107. package/dist/routes/model-provider.js +4 -5
  108. package/dist/routes/model-provider.js.map +1 -1
  109. package/dist/tsconfig.test.tsbuildinfo +1 -1
  110. package/package.json +9 -10
  111. package/src/components/available-provider-card.tsx +2 -2
  112. package/src/components/available-providers-grid.tsx +3 -3
  113. package/src/components/change-default-model-form.tsx +5 -6
  114. package/src/components/custom-model-provider-api-options.ts +3 -3
  115. package/src/components/custom-model-provider-form.stories.tsx +13 -13
  116. package/src/components/custom-model-provider-form.tsx +19 -12
  117. package/src/components/custom-model-provider-payload.test.ts +22 -22
  118. package/src/components/custom-model-provider-payload.ts +69 -54
  119. package/src/components/custom-model-provider-slug.test.ts +1 -1
  120. package/src/components/custom-model-provider-slug.ts +6 -3
  121. package/src/components/default-model-field.tsx +5 -5
  122. package/src/components/harness-availability.test.ts +13 -10
  123. package/src/components/harness-availability.ts +4 -28
  124. package/src/components/harnesses-section.tsx +7 -11
  125. package/src/components/model-provider-usage-modal.stories.tsx +18 -23
  126. package/src/components/model-provider-usage-modal.test.tsx +35 -7
  127. package/src/components/model-provider-usage-modal.tsx +12 -16
  128. package/src/components/model-provider-usage-target.ts +15 -18
  129. package/src/components/model-providers-section.stories.tsx +4 -1
  130. package/src/components/model-providers-section.tsx +112 -125
  131. package/src/components/test-and-save-form.tsx +13 -17
  132. package/src/core/harness-policy.test.ts +15 -0
  133. package/src/core/harness-policy.ts +83 -0
  134. package/src/core/model-provider-management-reducer.test.ts +59 -0
  135. package/src/core/model-provider-management-reducer.ts +72 -0
  136. package/src/core/models.ts +143 -0
  137. package/src/core/onboarding-reducer.test.ts +44 -0
  138. package/src/core/onboarding-reducer.ts +64 -0
  139. package/src/core/provider-policy.ts +53 -0
  140. package/src/feature.ts +12 -10
  141. package/src/hooks/api/model-provider-command-mapper.ts +122 -0
  142. package/src/hooks/api/model-provider-mapper.test.ts +27 -0
  143. package/src/hooks/api/model-provider-mapper.ts +120 -0
  144. package/src/hooks/api/model-providers.test.ts +15 -15
  145. package/src/hooks/api/model-providers.ts +146 -81
  146. package/src/pages/model-provider-onboarding-page.tsx +62 -56
  147. package/src/routes/inputs.test.ts +11 -0
  148. package/src/routes/inputs.ts +9 -0
  149. package/src/routes/model-provider.tsx +4 -3
  150. package/test/fixtures/model-providers.ts +1 -1
  151. package/tsconfig.build.tsbuildinfo +1 -1
  152. package/vercel.json +5 -0
  153. package/dist/components/provider-search.d.ts +0 -4
  154. package/dist/components/provider-search.d.ts.map +0 -1
  155. package/dist/components/provider-search.js +0 -13
  156. package/dist/components/provider-search.js.map +0 -1
  157. package/dist/components/supported-model-provider-catalog-entry.d.ts +0 -8
  158. package/dist/components/supported-model-provider-catalog-entry.d.ts.map +0 -1
  159. package/dist/components/supported-model-provider-catalog-entry.js +0 -9
  160. package/dist/components/supported-model-provider-catalog-entry.js.map +0 -1
  161. package/src/components/provider-search.test.ts +0 -45
  162. package/src/components/provider-search.ts +0 -18
  163. package/src/components/supported-model-provider-catalog-entry.ts +0 -19
@@ -1,11 +1,3 @@
1
- import {
2
- DEFAULT_HARNESS,
3
- type Harness,
4
- type HarnessDescriptor,
5
- harnessSupportsProvider,
6
- listHarnessDescriptors,
7
- type ModelProviderCatalogEntryDto,
8
- } from '@shipfox/api-agent-dto';
9
1
  import {QueryLoadError} from '@shipfox/client-ui';
10
2
  import {Button} from '@shipfox/react-ui/button';
11
3
  import {Callout} from '@shipfox/react-ui/callout';
@@ -16,10 +8,14 @@ import {Skeleton} from '@shipfox/react-ui/skeleton';
16
8
  import {toast} from '@shipfox/react-ui/toast';
17
9
  import {Header, Text} from '@shipfox/react-ui/typography';
18
10
  import {cn} from '@shipfox/react-ui/utils';
19
- import {useEffect, useMemo, useState} from 'react';
11
+ import {useEffect, useMemo, useReducer} from 'react';
20
12
  import {AvailableProvidersGrid, PROVIDER_GRID_CLASS} from '#components/available-providers-grid.js';
21
13
  import {modelProviderConfigErrorToFormError} from '#components/form-errors.js';
22
14
  import {ModelProviderTestAndSaveForm} from '#components/test-and-save-form.js';
15
+ import {DEFAULT_HARNESS, harnessSupportsProvider, listHarnesses} from '#core/harness-policy.js';
16
+ import type {HarnessDescriptor, HarnessId, SupportedProvider} from '#core/models.js';
17
+ import {initialOnboardingState, onboardingReducer} from '#core/onboarding-reducer.js';
18
+ import {isSupportedProvider} from '#core/provider-policy.js';
23
19
  import {
24
20
  useModelProviderCatalogQuery,
25
21
  useSetDefaultHarnessMutation,
@@ -40,27 +36,24 @@ export function ModelProviderOnboardingPage({
40
36
  }) {
41
37
  const catalogQuery = useModelProviderCatalogQuery();
42
38
  const setDefaultHarness = useSetDefaultHarnessMutation();
43
- const [selectedHarness, setSelectedHarness] = useState<Harness | null>(null);
44
- const [selectedEntry, setSelectedEntry] = useState<ModelProviderCatalogEntryDto | null>(null);
45
- const [defaultHarnessError, setDefaultHarnessError] = useState<string | undefined>();
46
- const [isSettingDefaultHarness, setIsSettingDefaultHarness] = useState(false);
47
- const supportedProviders =
48
- catalogQuery.data?.providers.filter((provider) => provider.support_status === 'supported') ??
49
- [];
39
+ const [onboarding, dispatch] = useReducer(onboardingReducer, initialOnboardingState);
40
+ const supportedProviders = catalogQuery.data?.providers.filter(isSupportedProvider) ?? [];
50
41
  const filteredProviders = useMemo(() => {
51
- if (selectedHarness === null) return [];
42
+ if (onboarding.step === 'choose-harness') return [];
52
43
  return supportedProviders.filter((provider) =>
53
- harnessSupportsProvider(selectedHarness, provider.id),
44
+ harnessSupportsProvider(onboarding.harnessId, provider.id),
54
45
  );
55
- }, [selectedHarness, supportedProviders]);
46
+ }, [onboarding, supportedProviders]);
56
47
 
57
48
  useEffect(() => {
58
49
  document
59
50
  .getElementById(
60
- selectedHarness === null ? 'model-provider-harness-step' : 'model-provider-provider-step',
51
+ onboarding.step === 'choose-harness'
52
+ ? 'model-provider-harness-step'
53
+ : 'model-provider-provider-step',
61
54
  )
62
55
  ?.focus();
63
- }, [selectedHarness]);
56
+ }, [onboarding.step]);
64
57
 
65
58
  function handleSkip() {
66
59
  try {
@@ -72,37 +65,43 @@ export function ModelProviderOnboardingPage({
72
65
  }
73
66
 
74
67
  async function handleProviderSaved() {
75
- if (selectedEntry === null || selectedHarness === null) return;
68
+ if (onboarding.step !== 'configure-provider' && onboarding.step !== 'saving-default-harness')
69
+ return;
76
70
 
77
- setDefaultHarnessError(undefined);
78
- if (selectedHarness === DEFAULT_HARNESS) {
79
- toast.success(`${selectedEntry.label} saved`);
71
+ const provider = onboarding.provider;
72
+ if (onboarding.step === 'configure-provider') dispatch({type: 'provider-saved'});
73
+ if (onboarding.harnessId === DEFAULT_HARNESS) {
74
+ toast.success(`${provider.label} saved`);
75
+ dispatch({type: 'default-harness-saved'});
80
76
  onConfigured();
81
77
  return;
82
78
  }
83
79
 
84
- setIsSettingDefaultHarness(true);
85
80
  try {
86
81
  await setDefaultHarness.mutateAsync({
87
82
  workspaceId,
88
- body: {harness_id: selectedHarness},
83
+ harnessId: onboarding.harnessId,
89
84
  });
90
- toast.success(`${selectedEntry.label} saved`);
85
+ toast.success(`${provider.label} saved`);
86
+ dispatch({type: 'default-harness-saved'});
91
87
  onConfigured();
92
88
  } catch (error) {
93
89
  const mapped = modelProviderConfigErrorToFormError(error);
94
- setDefaultHarnessError(mapped.message || 'Could not save default harness. Try again.');
95
- } finally {
96
- setIsSettingDefaultHarness(false);
90
+ dispatch({
91
+ type: 'default-harness-failed',
92
+ message: mapped.message || 'Could not save default harness. Try again.',
93
+ });
97
94
  }
98
95
  }
99
96
 
100
97
  const selectedHarnessDescriptor =
101
- selectedHarness === null
98
+ onboarding.step === 'choose-harness'
102
99
  ? null
103
- : listHarnessDescriptors().find((harness) => harness.id === selectedHarness);
100
+ : listHarnesses().find((harness) => harness.id === onboarding.harnessId);
104
101
  const headingId =
105
- selectedHarness === null ? 'model-provider-harness-step' : 'model-provider-provider-step';
102
+ onboarding.step === 'choose-harness'
103
+ ? 'model-provider-harness-step'
104
+ : 'model-provider-provider-step';
106
105
 
107
106
  return (
108
107
  <div className="mx-auto flex w-full max-w-[640px] flex-col gap-20">
@@ -125,22 +124,23 @@ export function ModelProviderOnboardingPage({
125
124
  </header>
126
125
 
127
126
  <section aria-labelledby={headingId} className="flex flex-col gap-16">
128
- {selectedHarness === null ? (
129
- <HarnessPicker onSelect={setSelectedHarness} />
127
+ {onboarding.step === 'choose-harness' ? (
128
+ <HarnessPicker
129
+ onSelect={(harnessId) => dispatch({type: 'harness-selected', harnessId})}
130
+ />
130
131
  ) : (
131
132
  <>
132
133
  <div>
133
- <Button type="button" variant="transparent" onClick={() => setSelectedHarness(null)}>
134
+ <Button type="button" variant="transparent" onClick={() => dispatch({type: 'back'})}>
134
135
  Back
135
136
  </Button>
136
137
  </div>
137
138
  <ModelProviderPicker
138
- key={selectedHarness}
139
+ key={onboarding.harnessId}
139
140
  catalogQuery={catalogQuery}
140
141
  supportedProviders={filteredProviders}
141
142
  onSelect={(entry) => {
142
- setDefaultHarnessError(undefined);
143
- setSelectedEntry(entry);
143
+ dispatch({type: 'provider-selected', provider: entry});
144
144
  }}
145
145
  />
146
146
  </>
@@ -148,17 +148,19 @@ export function ModelProviderOnboardingPage({
148
148
  </section>
149
149
 
150
150
  <Modal
151
- open={selectedEntry !== null}
151
+ open={
152
+ onboarding.step === 'configure-provider' || onboarding.step === 'saving-default-harness'
153
+ }
152
154
  onOpenChange={(open) => {
153
- if (!open && !isSettingDefaultHarness) {
154
- setSelectedEntry(null);
155
- setDefaultHarnessError(undefined);
156
- }
155
+ if (!open && onboarding.step === 'configure-provider') dispatch({type: 'back'});
157
156
  }}
158
157
  >
159
158
  <ModalContent aria-describedby={undefined}>
160
159
  <ModalTitle className="sr-only">
161
- {selectedEntry ? `Configure ${selectedEntry.label}` : ''}
160
+ {onboarding.step === 'configure-provider' ||
161
+ onboarding.step === 'saving-default-harness'
162
+ ? `Configure ${onboarding.provider.label}`
163
+ : ''}
162
164
  </ModalTitle>
163
165
  <ModalHeader>
164
166
  <Text
@@ -166,32 +168,36 @@ export function ModelProviderOnboardingPage({
166
168
  aria-hidden="true"
167
169
  className="overflow-ellipsis overflow-hidden whitespace-nowrap"
168
170
  >
169
- {selectedEntry ? `Configure ${selectedEntry.label}` : ''}
171
+ {onboarding.step === 'configure-provider' ||
172
+ onboarding.step === 'saving-default-harness'
173
+ ? `Configure ${onboarding.provider.label}`
174
+ : ''}
170
175
  </Text>
171
176
  </ModalHeader>
172
- {isSettingDefaultHarness ? (
177
+ {onboarding.step === 'saving-default-harness' ? (
173
178
  <div role="status" className="px-20 pb-8">
174
179
  <Text size="sm" className="text-foreground-neutral-muted">
175
180
  Saving harness default...
176
181
  </Text>
177
182
  </div>
178
183
  ) : null}
179
- {defaultHarnessError ? (
184
+ {onboarding.step === 'saving-default-harness' && onboarding.error ? (
180
185
  <div className="px-20 pb-8">
181
186
  <Callout role="alert" type="error">
182
187
  <div className="flex flex-col gap-8">
183
188
  <Text size="sm" bold>
184
189
  Could not save default harness
185
190
  </Text>
186
- <Text size="sm">{defaultHarnessError}</Text>
191
+ <Text size="sm">{onboarding.error}</Text>
187
192
  </div>
188
193
  </Callout>
189
194
  </div>
190
195
  ) : null}
191
- {selectedEntry ? (
196
+ {onboarding.step === 'configure-provider' ||
197
+ onboarding.step === 'saving-default-harness' ? (
192
198
  <ModelProviderTestAndSaveForm
193
199
  workspaceId={workspaceId}
194
- entry={selectedEntry}
200
+ entry={onboarding.provider}
195
201
  setAsDefaultOnSave
196
202
  onSaved={() => {
197
203
  void handleProviderSaved();
@@ -204,10 +210,10 @@ export function ModelProviderOnboardingPage({
204
210
  );
205
211
  }
206
212
 
207
- function HarnessPicker({onSelect}: {onSelect: (harness: Harness) => void}) {
213
+ function HarnessPicker({onSelect}: {onSelect: (harness: HarnessId) => void}) {
208
214
  return (
209
215
  <ul className={PROVIDER_GRID_CLASS} aria-label="Agent harnesses">
210
- {listHarnessDescriptors().map((harness) => (
216
+ {listHarnesses().map((harness) => (
211
217
  <HarnessCard key={harness.id} harness={harness} onChoose={() => onSelect(harness.id)} />
212
218
  ))}
213
219
  </ul>
@@ -251,8 +257,8 @@ function ModelProviderPicker({
251
257
  onSelect,
252
258
  }: {
253
259
  catalogQuery: ReturnType<typeof useModelProviderCatalogQuery>;
254
- supportedProviders: ModelProviderCatalogEntryDto[];
255
- onSelect: (entry: ModelProviderCatalogEntryDto) => void;
260
+ supportedProviders: SupportedProvider[];
261
+ onSelect: (entry: SupportedProvider) => void;
256
262
  }) {
257
263
  if (catalogQuery.isPending) {
258
264
  return (
@@ -0,0 +1,11 @@
1
+ import {modelProviderRouteParams} from './inputs.js';
2
+
3
+ describe('model provider route inputs', () => {
4
+ it('requires a non-empty workspace id', () => {
5
+ expect(modelProviderRouteParams({wid: 'workspace-1'})).toEqual({wid: 'workspace-1'});
6
+ expect(() => modelProviderRouteParams({wid: ''})).toThrow(
7
+ 'Model provider route is missing the workspace path parameter.',
8
+ );
9
+ expect(() => modelProviderRouteParams({wid: 42})).toThrow();
10
+ });
11
+ });
@@ -0,0 +1,9 @@
1
+ export function modelProviderRouteParams(input: Record<string, unknown>): {wid: string} {
2
+ const wid = stringParam(input.wid);
3
+ if (!wid) throw new Error('Model provider route is missing the workspace path parameter.');
4
+ return {wid};
5
+ }
6
+
7
+ function stringParam(value: unknown): string | undefined {
8
+ return typeof value === 'string' && value.length > 0 ? value : undefined;
9
+ }
@@ -1,10 +1,11 @@
1
- import {defineRoute} from '@shipfox/client-shell/runtime';
2
- import {useNavigate, useParams} from '@tanstack/react-router';
1
+ import {defineRoute, useRouteParams} from '@shipfox/client-shell/runtime';
2
+ import {useNavigate} from '@tanstack/react-router';
3
3
  import {ModelProviderOnboardingPage} from '#pages/model-provider-onboarding-page.js';
4
+ import {modelProviderRouteParams} from './inputs.js';
4
5
 
5
6
  export default defineRoute({
6
7
  component: () => {
7
- const {wid} = useParams({strict: false}) as {wid: string};
8
+ const {wid} = useRouteParams(modelProviderRouteParams);
8
9
  const navigate = useNavigate();
9
10
  const goToProjectCreation = () => {
10
11
  void navigate({to: '/workspaces/$wid/projects/new', params: {wid}, replace: true});
@@ -27,7 +27,7 @@ export function modelProviderEntry(
27
27
  id: 'anthropic',
28
28
  label: 'Anthropic',
29
29
  support_status: 'supported',
30
- default_model: null,
30
+ default_model: 'claude-opus-4-8',
31
31
  credential_fields: [{key: 'api_key', label: 'API key', secret: true}],
32
32
  unsupported_reason: null,
33
33
  models: [{id: 'claude-opus-4-8', label: 'Claude Opus 4.8'}],